1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007
3 Free Software Foundation, Inc.
4 Contributed by Denis Chertykov (denisc@overta.ru)
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
28 #include "hard-reg-set.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-attr.h"
45 #include "target-def.h"
48 /* Maximal allowed offset for an address in the LD command */
49 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
51 static int avr_naked_function_p (tree
);
52 static int interrupt_function_p (tree
);
53 static int signal_function_p (tree
);
54 static int avr_regs_to_save (HARD_REG_SET
*);
55 static int sequent_regs_live (void);
56 static const char *ptrreg_to_str (int);
57 static const char *cond_string (enum rtx_code
);
58 static int avr_num_arg_regs (enum machine_mode
, tree
);
60 static RTX_CODE
compare_condition (rtx insn
);
61 static int compare_sign_p (rtx insn
);
62 static tree
avr_handle_progmem_attribute (tree
*, tree
, tree
, int, bool *);
63 static tree
avr_handle_fndecl_attribute (tree
*, tree
, tree
, int, bool *);
64 static tree
avr_handle_fntype_attribute (tree
*, tree
, tree
, int, bool *);
65 const struct attribute_spec avr_attribute_table
[];
66 static bool avr_assemble_integer (rtx
, unsigned int, int);
67 static void avr_file_start (void);
68 static void avr_file_end (void);
69 static void avr_asm_function_end_prologue (FILE *);
70 static void avr_asm_function_begin_epilogue (FILE *);
71 static void avr_insert_attributes (tree
, tree
*);
72 static void avr_asm_init_sections (void);
73 static unsigned int avr_section_type_flags (tree
, const char *, int);
75 static void avr_reorg (void);
76 static void avr_asm_out_ctor (rtx
, int);
77 static void avr_asm_out_dtor (rtx
, int);
78 static int avr_operand_rtx_cost (rtx
, enum machine_mode
, enum rtx_code
);
79 static bool avr_rtx_costs (rtx
, int, int, int *);
80 static int avr_address_cost (rtx
);
81 static bool avr_return_in_memory (const_tree
, const_tree
);
82 static struct machine_function
* avr_init_machine_status (void);
83 /* Allocate registers from r25 to r8 for parameters for function calls. */
84 #define FIRST_CUM_REG 26
86 /* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */
87 static GTY(()) rtx tmp_reg_rtx
;
89 /* Zeroed register RTX (gen_rtx_REG (QImode, ZERO_REGNO)) */
90 static GTY(()) rtx zero_reg_rtx
;
92 /* AVR register names {"r0", "r1", ..., "r31"} */
93 static const char *const avr_regnames
[] = REGISTER_NAMES
;
95 /* This holds the last insn address. */
96 static int last_insn_address
= 0;
98 /* Preprocessor macros to define depending on MCU type. */
99 const char *avr_base_arch_macro
;
100 const char *avr_extra_arch_macro
;
102 section
*progmem_section
;
104 /* More than 8K of program memory: use "call" and "jmp". */
107 /* Core have 'MUL*' instructions. */
108 int avr_have_mul_p
= 0;
110 /* Assembler only. */
111 int avr_asm_only_p
= 0;
113 /* Core have 'MOVW' and 'LPM Rx,Z' instructions. */
114 int avr_have_movw_lpmx_p
= 0;
121 const char *const macro
;
124 static const struct base_arch_s avr_arch_types
[] = {
125 { 1, 0, 0, 0, NULL
}, /* unknown device specified */
126 { 1, 0, 0, 0, "__AVR_ARCH__=1" },
127 { 0, 0, 0, 0, "__AVR_ARCH__=2" },
128 { 0, 0, 0, 1, "__AVR_ARCH__=25"},
129 { 0, 0, 1, 0, "__AVR_ARCH__=3" },
130 { 0, 1, 0, 1, "__AVR_ARCH__=4" },
131 { 0, 1, 1, 1, "__AVR_ARCH__=5" }
134 /* These names are used as the index into the avr_arch_types[] table
149 const char *const name
;
150 int arch
; /* index in avr_arch_types[] */
151 /* Must lie outside user's namespace. NULL == no macro. */
152 const char *const macro
;
155 /* List of all known AVR MCU types - if updated, it has to be kept
156 in sync in several places (FIXME: is there a better way?):
158 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
159 - t-avr (MULTILIB_MATCHES)
160 - gas/config/tc-avr.c
163 static const struct mcu_type_s avr_mcu_types
[] = {
164 /* Classic, <= 8K. */
165 { "avr2", ARCH_AVR2
, NULL
},
166 { "at90s2313", ARCH_AVR2
, "__AVR_AT90S2313__" },
167 { "at90s2323", ARCH_AVR2
, "__AVR_AT90S2323__" },
168 { "at90s2333", ARCH_AVR2
, "__AVR_AT90S2333__" },
169 { "at90s2343", ARCH_AVR2
, "__AVR_AT90S2343__" },
170 { "attiny22", ARCH_AVR2
, "__AVR_ATtiny22__" },
171 { "attiny26", ARCH_AVR2
, "__AVR_ATtiny26__" },
172 { "at90s4414", ARCH_AVR2
, "__AVR_AT90S4414__" },
173 { "at90s4433", ARCH_AVR2
, "__AVR_AT90S4433__" },
174 { "at90s4434", ARCH_AVR2
, "__AVR_AT90S4434__" },
175 { "at90s8515", ARCH_AVR2
, "__AVR_AT90S8515__" },
176 { "at90c8534", ARCH_AVR2
, "__AVR_AT90C8534__" },
177 { "at90s8535", ARCH_AVR2
, "__AVR_AT90S8535__" },
178 /* Classic + MOVW, <= 8K. */
179 { "avr25", ARCH_AVR25
, NULL
},
180 { "attiny13", ARCH_AVR25
, "__AVR_ATtiny13__" },
181 { "attiny2313", ARCH_AVR25
, "__AVR_ATtiny2313__" },
182 { "attiny24", ARCH_AVR25
, "__AVR_ATtiny24__" },
183 { "attiny44", ARCH_AVR25
, "__AVR_ATtiny44__" },
184 { "attiny84", ARCH_AVR25
, "__AVR_ATtiny84__" },
185 { "attiny25", ARCH_AVR25
, "__AVR_ATtiny25__" },
186 { "attiny45", ARCH_AVR25
, "__AVR_ATtiny45__" },
187 { "attiny85", ARCH_AVR25
, "__AVR_ATtiny85__" },
188 { "attiny261", ARCH_AVR25
, "__AVR_ATtiny261__" },
189 { "attiny461", ARCH_AVR25
, "__AVR_ATtiny461__" },
190 { "attiny861", ARCH_AVR25
, "__AVR_ATtiny861__" },
191 { "at86rf401", ARCH_AVR25
, "__AVR_AT86RF401__" },
193 { "avr3", ARCH_AVR3
, NULL
},
194 { "atmega103", ARCH_AVR3
, "__AVR_ATmega103__" },
195 { "atmega603", ARCH_AVR3
, "__AVR_ATmega603__" },
196 { "at43usb320", ARCH_AVR3
, "__AVR_AT43USB320__" },
197 { "at43usb355", ARCH_AVR3
, "__AVR_AT43USB355__" },
198 { "at76c711", ARCH_AVR3
, "__AVR_AT76C711__" },
199 /* Enhanced, <= 8K. */
200 { "avr4", ARCH_AVR4
, NULL
},
201 { "atmega8", ARCH_AVR4
, "__AVR_ATmega8__" },
202 { "atmega48", ARCH_AVR4
, "__AVR_ATmega48__" },
203 { "atmega88", ARCH_AVR4
, "__AVR_ATmega88__" },
204 { "atmega8515", ARCH_AVR4
, "__AVR_ATmega8515__" },
205 { "atmega8535", ARCH_AVR4
, "__AVR_ATmega8535__" },
206 { "atmega8hva", ARCH_AVR4
, "__AVR_ATmega8HVA__" },
207 { "at90pwm1", ARCH_AVR4
, "__AVR_AT90PWM1__" },
208 { "at90pwm2", ARCH_AVR4
, "__AVR_AT90PWM2__" },
209 { "at90pwm3", ARCH_AVR4
, "__AVR_AT90PWM3__" },
210 /* Enhanced, > 8K. */
211 { "avr5", ARCH_AVR5
, NULL
},
212 { "atmega16", ARCH_AVR5
, "__AVR_ATmega16__" },
213 { "atmega161", ARCH_AVR5
, "__AVR_ATmega161__" },
214 { "atmega162", ARCH_AVR5
, "__AVR_ATmega162__" },
215 { "atmega163", ARCH_AVR5
, "__AVR_ATmega163__" },
216 { "atmega164p", ARCH_AVR5
, "__AVR_ATmega164P__" },
217 { "atmega165", ARCH_AVR5
, "__AVR_ATmega165__" },
218 { "atmega165p", ARCH_AVR5
, "__AVR_ATmega165P__" },
219 { "atmega168", ARCH_AVR5
, "__AVR_ATmega168__" },
220 { "atmega169", ARCH_AVR5
, "__AVR_ATmega169__" },
221 { "atmega169p", ARCH_AVR5
, "__AVR_ATmega169P__" },
222 { "atmega32", ARCH_AVR5
, "__AVR_ATmega32__" },
223 { "atmega323", ARCH_AVR5
, "__AVR_ATmega323__" },
224 { "atmega324p", ARCH_AVR5
, "__AVR_ATmega324P__" },
225 { "atmega325", ARCH_AVR5
, "__AVR_ATmega325__" },
226 { "atmega325p", ARCH_AVR5
, "__AVR_ATmega325P__" },
227 { "atmega3250", ARCH_AVR5
, "__AVR_ATmega3250__" },
228 { "atmega3250p", ARCH_AVR5
, "__AVR_ATmega3250P__" },
229 { "atmega329", ARCH_AVR5
, "__AVR_ATmega329__" },
230 { "atmega329p", ARCH_AVR5
, "__AVR_ATmega329P__" },
231 { "atmega3290", ARCH_AVR5
, "__AVR_ATmega3290__" },
232 { "atmega3290p", ARCH_AVR5
, "__AVR_ATmega3290P__" },
233 { "atmega406", ARCH_AVR5
, "__AVR_ATmega406__" },
234 { "atmega64", ARCH_AVR5
, "__AVR_ATmega64__" },
235 { "atmega640", ARCH_AVR5
, "__AVR_ATmega640__" },
236 { "atmega644", ARCH_AVR5
, "__AVR_ATmega644__" },
237 { "atmega644p", ARCH_AVR5
, "__AVR_ATmega644P__" },
238 { "atmega645", ARCH_AVR5
, "__AVR_ATmega645__" },
239 { "atmega6450", ARCH_AVR5
, "__AVR_ATmega6450__" },
240 { "atmega649", ARCH_AVR5
, "__AVR_ATmega649__" },
241 { "atmega6490", ARCH_AVR5
, "__AVR_ATmega6490__" },
242 { "atmega128", ARCH_AVR5
, "__AVR_ATmega128__" },
243 { "atmega1280", ARCH_AVR5
, "__AVR_ATmega1280__" },
244 { "atmega1281", ARCH_AVR5
, "__AVR_ATmega1281__" },
245 { "atmega16hva", ARCH_AVR5
, "__AVR_ATmega16HVA__" },
246 { "at90can32", ARCH_AVR5
, "__AVR_AT90CAN32__" },
247 { "at90can64", ARCH_AVR5
, "__AVR_AT90CAN64__" },
248 { "at90can128", ARCH_AVR5
, "__AVR_AT90CAN128__" },
249 { "at90usb82", ARCH_AVR5
, "__AVR_AT90USB82__" },
250 { "at90usb162", ARCH_AVR5
, "__AVR_AT90USB162__" },
251 { "at90usb646", ARCH_AVR5
, "__AVR_AT90USB646__" },
252 { "at90usb647", ARCH_AVR5
, "__AVR_AT90USB647__" },
253 { "at90usb1286", ARCH_AVR5
, "__AVR_AT90USB1286__" },
254 { "at90usb1287", ARCH_AVR5
, "__AVR_AT90USB1287__" },
255 { "at94k", ARCH_AVR5
, "__AVR_AT94K__" },
256 /* Assembler only. */
257 { "avr1", ARCH_AVR1
, NULL
},
258 { "at90s1200", ARCH_AVR1
, "__AVR_AT90S1200__" },
259 { "attiny11", ARCH_AVR1
, "__AVR_ATtiny11__" },
260 { "attiny12", ARCH_AVR1
, "__AVR_ATtiny12__" },
261 { "attiny15", ARCH_AVR1
, "__AVR_ATtiny15__" },
262 { "attiny28", ARCH_AVR1
, "__AVR_ATtiny28__" },
263 { NULL
, ARCH_UNKNOWN
, NULL
}
266 int avr_case_values_threshold
= 30000;
268 /* Initialize the GCC target structure. */
269 #undef TARGET_ASM_ALIGNED_HI_OP
270 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
271 #undef TARGET_ASM_ALIGNED_SI_OP
272 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
273 #undef TARGET_ASM_UNALIGNED_HI_OP
274 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
275 #undef TARGET_ASM_UNALIGNED_SI_OP
276 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
277 #undef TARGET_ASM_INTEGER
278 #define TARGET_ASM_INTEGER avr_assemble_integer
279 #undef TARGET_ASM_FILE_START
280 #define TARGET_ASM_FILE_START avr_file_start
281 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
282 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
283 #undef TARGET_ASM_FILE_END
284 #define TARGET_ASM_FILE_END avr_file_end
286 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
287 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
288 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
289 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
290 #undef TARGET_ATTRIBUTE_TABLE
291 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
292 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
293 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
294 #undef TARGET_INSERT_ATTRIBUTES
295 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
296 #undef TARGET_SECTION_TYPE_FLAGS
297 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
298 #undef TARGET_RTX_COSTS
299 #define TARGET_RTX_COSTS avr_rtx_costs
300 #undef TARGET_ADDRESS_COST
301 #define TARGET_ADDRESS_COST avr_address_cost
302 #undef TARGET_MACHINE_DEPENDENT_REORG
303 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
305 #undef TARGET_RETURN_IN_MEMORY
306 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
308 #undef TARGET_STRICT_ARGUMENT_NAMING
309 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
311 struct gcc_target targetm
= TARGET_INITIALIZER
;
314 avr_override_options (void)
316 const struct mcu_type_s
*t
;
317 const struct base_arch_s
*base
;
319 flag_delete_null_pointer_checks
= 0;
321 for (t
= avr_mcu_types
; t
->name
; t
++)
322 if (strcmp (t
->name
, avr_mcu_name
) == 0)
327 fprintf (stderr
, "unknown MCU '%s' specified\nKnown MCU names:\n",
329 for (t
= avr_mcu_types
; t
->name
; t
++)
330 fprintf (stderr
," %s\n", t
->name
);
333 base
= &avr_arch_types
[t
->arch
];
334 avr_asm_only_p
= base
->asm_only
;
335 avr_have_mul_p
= base
->have_mul
;
336 avr_mega_p
= base
->mega
;
337 avr_have_movw_lpmx_p
= base
->have_movw_lpmx
;
338 avr_base_arch_macro
= base
->macro
;
339 avr_extra_arch_macro
= t
->macro
;
341 if (optimize
&& !TARGET_NO_TABLEJUMP
)
342 avr_case_values_threshold
= (!AVR_MEGA
|| TARGET_CALL_PROLOGUES
) ? 8 : 17;
344 tmp_reg_rtx
= gen_rtx_REG (QImode
, TMP_REGNO
);
345 zero_reg_rtx
= gen_rtx_REG (QImode
, ZERO_REGNO
);
347 init_machine_status
= avr_init_machine_status
;
350 /* return register class from register number. */
352 static const int reg_class_tab
[]={
353 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
354 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
355 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
356 GENERAL_REGS
, /* r0 - r15 */
357 LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,
358 LD_REGS
, /* r16 - 23 */
359 ADDW_REGS
,ADDW_REGS
, /* r24,r25 */
360 POINTER_X_REGS
,POINTER_X_REGS
, /* r26,27 */
361 POINTER_Y_REGS
,POINTER_Y_REGS
, /* r28,r29 */
362 POINTER_Z_REGS
,POINTER_Z_REGS
, /* r30,r31 */
363 STACK_REG
,STACK_REG
/* SPL,SPH */
366 /* Function to set up the backend function structure. */
368 static struct machine_function
*
369 avr_init_machine_status (void)
371 return ((struct machine_function
*)
372 ggc_alloc_cleared (sizeof (struct machine_function
)));
375 /* Return register class for register R. */
378 avr_regno_reg_class (int r
)
381 return reg_class_tab
[r
];
385 /* Return nonzero if FUNC is a naked function. */
388 avr_naked_function_p (tree func
)
392 gcc_assert (TREE_CODE (func
) == FUNCTION_DECL
);
394 a
= lookup_attribute ("naked", TYPE_ATTRIBUTES (TREE_TYPE (func
)));
395 return a
!= NULL_TREE
;
398 /* Return nonzero if FUNC is an interrupt function as specified
399 by the "interrupt" attribute. */
402 interrupt_function_p (tree func
)
406 if (TREE_CODE (func
) != FUNCTION_DECL
)
409 a
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (func
));
410 return a
!= NULL_TREE
;
413 /* Return nonzero if FUNC is a signal function as specified
414 by the "signal" attribute. */
417 signal_function_p (tree func
)
421 if (TREE_CODE (func
) != FUNCTION_DECL
)
424 a
= lookup_attribute ("signal", DECL_ATTRIBUTES (func
));
425 return a
!= NULL_TREE
;
428 /* Return the number of hard registers to push/pop in the prologue/epilogue
429 of the current function, and optionally store these registers in SET. */
432 avr_regs_to_save (HARD_REG_SET
*set
)
435 int int_or_sig_p
= (interrupt_function_p (current_function_decl
)
436 || signal_function_p (current_function_decl
));
437 int leaf_func_p
= leaf_function_p ();
440 CLEAR_HARD_REG_SET (*set
);
443 /* No need to save any registers if the function never returns. */
444 if (TREE_THIS_VOLATILE (current_function_decl
))
447 for (reg
= 0; reg
< 32; reg
++)
449 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
450 any global register variables. */
454 if ((int_or_sig_p
&& !leaf_func_p
&& call_used_regs
[reg
])
455 || (df_regs_ever_live_p (reg
)
456 && (int_or_sig_p
|| !call_used_regs
[reg
])
457 && !(frame_pointer_needed
458 && (reg
== REG_Y
|| reg
== (REG_Y
+1)))))
461 SET_HARD_REG_BIT (*set
, reg
);
468 /* Compute offset between arg_pointer and frame_pointer. */
471 initial_elimination_offset (int from
, int to
)
473 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
477 int offset
= frame_pointer_needed
? 2 : 0;
479 offset
+= avr_regs_to_save (NULL
);
480 return get_frame_size () + 2 + 1 + offset
;
484 /* Return 1 if the function epilogue is just a single "ret". */
487 avr_simple_epilogue (void)
489 return (! frame_pointer_needed
490 && get_frame_size () == 0
491 && avr_regs_to_save (NULL
) == 0
492 && ! interrupt_function_p (current_function_decl
)
493 && ! signal_function_p (current_function_decl
)
494 && ! avr_naked_function_p (current_function_decl
)
495 && ! MAIN_NAME_P (DECL_NAME (current_function_decl
))
496 && ! TREE_THIS_VOLATILE (current_function_decl
));
499 /* This function checks sequence of live registers. */
502 sequent_regs_live (void)
508 for (reg
= 0; reg
< 18; ++reg
)
510 if (!call_used_regs
[reg
])
512 if (df_regs_ever_live_p (reg
))
522 if (!frame_pointer_needed
)
524 if (df_regs_ever_live_p (REG_Y
))
532 if (df_regs_ever_live_p (REG_Y
+1))
545 return (cur_seq
== live_seq
) ? live_seq
: 0;
548 /* Output function prologue. */
551 expand_prologue (void)
555 HOST_WIDE_INT size
= get_frame_size();
556 /* Define templates for push instructions. */
557 rtx pushbyte
= gen_rtx_MEM (QImode
,
558 gen_rtx_POST_DEC (HImode
, stack_pointer_rtx
));
559 rtx pushword
= gen_rtx_MEM (HImode
,
560 gen_rtx_POST_DEC (HImode
, stack_pointer_rtx
));
563 last_insn_address
= 0;
565 /* Init cfun->machine. */
566 cfun
->machine
->is_main
= MAIN_NAME_P (DECL_NAME (current_function_decl
));
567 cfun
->machine
->is_naked
= avr_naked_function_p (current_function_decl
);
568 cfun
->machine
->is_interrupt
= interrupt_function_p (current_function_decl
);
569 cfun
->machine
->is_signal
= signal_function_p (current_function_decl
);
571 /* Prologue: naked. */
572 if (cfun
->machine
->is_naked
)
577 live_seq
= sequent_regs_live ();
578 minimize
= (TARGET_CALL_PROLOGUES
579 && !(cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
582 if (cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
584 if (cfun
->machine
->is_interrupt
)
586 /* Enable interrupts. */
587 insn
= emit_insn (gen_enable_interrupt ());
588 RTX_FRAME_RELATED_P (insn
) = 1;
592 insn
= emit_move_insn (pushbyte
, zero_reg_rtx
);
593 RTX_FRAME_RELATED_P (insn
) = 1;
596 insn
= emit_move_insn (pushbyte
, tmp_reg_rtx
);
597 RTX_FRAME_RELATED_P (insn
) = 1;
600 insn
= emit_move_insn (tmp_reg_rtx
,
601 gen_rtx_MEM (QImode
, GEN_INT (SREG_ADDR
)));
602 RTX_FRAME_RELATED_P (insn
) = 1;
603 insn
= emit_move_insn (pushbyte
, tmp_reg_rtx
);
604 RTX_FRAME_RELATED_P (insn
) = 1;
606 /* Clear zero reg. */
607 insn
= emit_move_insn (zero_reg_rtx
, const0_rtx
);
608 RTX_FRAME_RELATED_P (insn
) = 1;
610 /* Prevent any attempt to delete the setting of ZERO_REG! */
611 emit_insn (gen_rtx_USE (VOIDmode
, zero_reg_rtx
));
613 if (cfun
->machine
->is_main
)
616 sprintf (buffer
, "%s - %d", avr_init_stack
, (int) size
);
617 rtx sym
= gen_rtx_SYMBOL_REF (HImode
, ggc_strdup (buffer
));
618 /* Initialize stack pointer using frame pointer. */
619 insn
= emit_move_insn (frame_pointer_rtx
, sym
);
620 RTX_FRAME_RELATED_P (insn
) = 1;
621 insn
= emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
622 RTX_FRAME_RELATED_P (insn
) = 1;
624 else if (minimize
&& (frame_pointer_needed
|| live_seq
> 6))
626 insn
= emit_move_insn (gen_rtx_REG (HImode
, REG_X
),
627 gen_int_mode (size
, HImode
));
628 RTX_FRAME_RELATED_P (insn
) = 1;
631 emit_insn (gen_call_prologue_saves (gen_int_mode (live_seq
, HImode
),
632 gen_int_mode (size
+ live_seq
, HImode
)));
633 RTX_FRAME_RELATED_P (insn
) = 1;
638 avr_regs_to_save (&set
);
640 for (reg
= 0; reg
< 32; ++reg
)
642 if (TEST_HARD_REG_BIT (set
, reg
))
644 /* Emit push of register to save. */
645 insn
=emit_move_insn (pushbyte
, gen_rtx_REG (QImode
, reg
));
646 RTX_FRAME_RELATED_P (insn
) = 1;
649 if (frame_pointer_needed
)
651 /* Push frame pointer. */
652 insn
= emit_move_insn (pushword
, frame_pointer_rtx
);
653 RTX_FRAME_RELATED_P (insn
) = 1;
656 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
657 RTX_FRAME_RELATED_P (insn
) = 1;
661 /* Creating a frame can be done by direct manipulation of the
662 stack or via the frame pointer. These two methods are:
669 the optimum method depends on function type, stack and frame size.
670 To avoid a complex logic, both methods are tested and shortest
674 if (TARGET_TINY_STACK
)
676 if (size
< -63 || size
> 63)
677 warning (0, "large frame pointer change (%d) with -mtiny-stack", size
);
679 /* The high byte (r29) doesn't change - prefer 'subi' (1 cycle)
680 over 'sbiw' (2 cycles, same size). */
681 myfp
= gen_rtx_REG (QImode
, REGNO (frame_pointer_rtx
));
685 /* Normal sized addition. */
686 myfp
= frame_pointer_rtx
;
688 /* Calculate length. */
691 get_attr_length (gen_move_insn (frame_pointer_rtx
, stack_pointer_rtx
));
693 get_attr_length (gen_move_insn (myfp
,
694 gen_rtx_PLUS (GET_MODE(myfp
), myfp
,
698 get_attr_length (gen_move_insn (stack_pointer_rtx
, frame_pointer_rtx
));
700 /* Method 2-Adjust Stack pointer. */
701 int sp_plus_length
= 0;
705 get_attr_length (gen_move_insn (stack_pointer_rtx
,
706 gen_rtx_PLUS (HImode
, stack_pointer_rtx
,
710 get_attr_length (gen_move_insn (frame_pointer_rtx
, stack_pointer_rtx
));
712 /* Use shortest method. */
713 if (size
<= 6 && (sp_plus_length
< method1_length
))
715 insn
= emit_move_insn (stack_pointer_rtx
,
716 gen_rtx_PLUS (HImode
, stack_pointer_rtx
,
717 gen_int_mode (-size
, HImode
)));
718 RTX_FRAME_RELATED_P (insn
) = 1;
719 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
720 RTX_FRAME_RELATED_P (insn
) = 1;
724 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
725 RTX_FRAME_RELATED_P (insn
) = 1;
726 insn
= emit_move_insn (myfp
,
727 gen_rtx_PLUS (GET_MODE(myfp
), frame_pointer_rtx
,
728 gen_int_mode (-size
, GET_MODE(myfp
))));
729 RTX_FRAME_RELATED_P (insn
) = 1;
730 insn
= emit_move_insn ( stack_pointer_rtx
, frame_pointer_rtx
);
731 RTX_FRAME_RELATED_P (insn
) = 1;
738 /* Output summary at end of function prologue. */
741 avr_asm_function_end_prologue (FILE *file
)
743 if (cfun
->machine
->is_naked
)
745 fputs ("/* prologue: naked */\n", file
);
749 if (cfun
->machine
->is_interrupt
)
751 fputs ("/* prologue: Interrupt */\n", file
);
753 else if (cfun
->machine
->is_signal
)
755 fputs ("/* prologue: Signal */\n", file
);
757 else if (cfun
->machine
->is_main
)
759 fputs ("/* prologue: main */\n", file
);
762 fputs ("/* prologue: function */\n", file
);
764 fprintf (file
, "/* frame size = " HOST_WIDE_INT_PRINT_DEC
" */\n",
769 /* Implement EPILOGUE_USES. */
772 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED
)
776 && (cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
))
781 /* Output RTL epilogue. */
784 expand_epilogue (void)
789 HOST_WIDE_INT size
= get_frame_size();
792 /* epilogue: naked */
793 if (cfun
->machine
->is_naked
)
795 insn
= emit_jump_insn (gen_return ());
796 RTX_FRAME_RELATED_P (insn
) = 1;
800 live_seq
= sequent_regs_live ();
801 minimize
= (TARGET_CALL_PROLOGUES
802 && !(cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
805 if (cfun
->machine
->is_main
)
807 /* Return value from main() is already in the correct registers
808 (r25:r24) as the exit() argument. */
809 insn
= emit_jump_insn (gen_return ());
810 RTX_FRAME_RELATED_P (insn
) = 1;
812 else if (minimize
&& (frame_pointer_needed
|| live_seq
> 4))
814 if (frame_pointer_needed
)
816 /* Get rid of frame. */
818 emit_move_insn(frame_pointer_rtx
,
819 gen_rtx_PLUS (HImode
, frame_pointer_rtx
,
820 gen_int_mode (size
, HImode
)));
821 RTX_FRAME_RELATED_P (insn
) = 1;
825 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
826 RTX_FRAME_RELATED_P (insn
) = 1;
830 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq
, HImode
)));
831 RTX_FRAME_RELATED_P (insn
) = 1;
835 if (frame_pointer_needed
)
839 /* Try two methods to adjust stack and select shortest. */
841 /* Method 1-Adjust frame pointer. */
843 get_attr_length (gen_move_insn (frame_pointer_rtx
,
844 gen_rtx_PLUS (HImode
, frame_pointer_rtx
,
847 /* Copy to stack pointer. */
849 get_attr_length (gen_move_insn (stack_pointer_rtx
, frame_pointer_rtx
));
851 /* Method 2-Adjust Stack pointer. */
852 int sp_plus_length
= 0;
856 get_attr_length (gen_move_insn (stack_pointer_rtx
,
857 gen_rtx_PLUS (HImode
, stack_pointer_rtx
,
861 /* Use shortest method. */
862 if (size
<= 5 && (sp_plus_length
< fp_plus_length
))
864 insn
= emit_move_insn (stack_pointer_rtx
,
865 gen_rtx_PLUS (HImode
, stack_pointer_rtx
,
866 gen_int_mode (size
, HImode
)));
867 RTX_FRAME_RELATED_P (insn
) = 1;
871 insn
= emit_move_insn (frame_pointer_rtx
,
872 gen_rtx_PLUS (HImode
, frame_pointer_rtx
,
873 gen_int_mode (size
, HImode
)));
874 RTX_FRAME_RELATED_P (insn
) = 1;
875 /* Copy to stack pointer. */
876 insn
= emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
877 RTX_FRAME_RELATED_P (insn
) = 1;
881 /* Restore previous frame_pointer. */
882 insn
= emit_insn (gen_pophi (frame_pointer_rtx
));
883 RTX_FRAME_RELATED_P (insn
) = 1;
885 /* Restore used registers. */
887 avr_regs_to_save (&set
);
888 for (reg
= 31; reg
>= 0; --reg
)
890 if (TEST_HARD_REG_BIT (set
, reg
))
892 insn
= emit_insn (gen_popqi (gen_rtx_REG (QImode
, reg
)));
893 RTX_FRAME_RELATED_P (insn
) = 1;
896 if (cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
899 /* Restore SREG using tmp reg as scratch. */
900 insn
= emit_insn (gen_popqi (tmp_reg_rtx
));
901 RTX_FRAME_RELATED_P (insn
) = 1;
903 insn
= emit_move_insn (gen_rtx_MEM(QImode
, GEN_INT(SREG_ADDR
)),
905 RTX_FRAME_RELATED_P (insn
) = 1;
907 /* Restore tmp REG. */
908 insn
= emit_insn (gen_popqi (tmp_reg_rtx
));
909 RTX_FRAME_RELATED_P (insn
) = 1;
911 /* Restore zero REG. */
912 insn
= emit_insn (gen_popqi (zero_reg_rtx
));
913 RTX_FRAME_RELATED_P (insn
) = 1;
916 insn
= emit_jump_insn (gen_return ());
917 RTX_FRAME_RELATED_P (insn
) = 1;
921 /* Output summary messages at beginning of function epilogue. */
924 avr_asm_function_begin_epilogue (FILE *file
)
926 fprintf (file
, "/* epilogue start */\n");
929 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
930 machine for a memory operand of mode MODE. */
933 legitimate_address_p (enum machine_mode mode
, rtx x
, int strict
)
935 enum reg_class r
= NO_REGS
;
937 if (TARGET_ALL_DEBUG
)
939 fprintf (stderr
, "mode: (%s) %s %s %s %s:",
941 strict
? "(strict)": "",
942 reload_completed
? "(reload_completed)": "",
943 reload_in_progress
? "(reload_in_progress)": "",
944 reg_renumber
? "(reg_renumber)" : "");
945 if (GET_CODE (x
) == PLUS
946 && REG_P (XEXP (x
, 0))
947 && GET_CODE (XEXP (x
, 1)) == CONST_INT
948 && INTVAL (XEXP (x
, 1)) >= 0
949 && INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
)
952 fprintf (stderr
, "(r%d ---> r%d)", REGNO (XEXP (x
, 0)),
953 true_regnum (XEXP (x
, 0)));
956 if (REG_P (x
) && (strict
? REG_OK_FOR_BASE_STRICT_P (x
)
957 : REG_OK_FOR_BASE_NOSTRICT_P (x
)))
959 else if (CONSTANT_ADDRESS_P (x
))
961 else if (GET_CODE (x
) == PLUS
962 && REG_P (XEXP (x
, 0))
963 && GET_CODE (XEXP (x
, 1)) == CONST_INT
964 && INTVAL (XEXP (x
, 1)) >= 0)
966 int fit
= INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
);
970 || REGNO (XEXP (x
,0)) == REG_Y
971 || REGNO (XEXP (x
,0)) == REG_Z
)
972 r
= BASE_POINTER_REGS
;
973 if (XEXP (x
,0) == frame_pointer_rtx
974 || XEXP (x
,0) == arg_pointer_rtx
)
975 r
= BASE_POINTER_REGS
;
977 else if (frame_pointer_needed
&& XEXP (x
,0) == frame_pointer_rtx
)
980 else if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == POST_INC
)
981 && REG_P (XEXP (x
, 0))
982 && (strict
? REG_OK_FOR_BASE_STRICT_P (XEXP (x
, 0))
983 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x
, 0))))
987 if (TARGET_ALL_DEBUG
)
989 fprintf (stderr
, " ret = %c\n", r
+ '0');
991 return r
== NO_REGS
? 0 : (int)r
;
994 /* Attempts to replace X with a valid
995 memory address for an operand of mode MODE */
998 legitimize_address (rtx x
, rtx oldx
, enum machine_mode mode
)
1001 if (TARGET_ALL_DEBUG
)
1003 fprintf (stderr
, "legitimize_address mode: %s", GET_MODE_NAME(mode
));
1007 if (GET_CODE (oldx
) == PLUS
1008 && REG_P (XEXP (oldx
,0)))
1010 if (REG_P (XEXP (oldx
,1)))
1011 x
= force_reg (GET_MODE (oldx
), oldx
);
1012 else if (GET_CODE (XEXP (oldx
, 1)) == CONST_INT
)
1014 int offs
= INTVAL (XEXP (oldx
,1));
1015 if (frame_pointer_rtx
!= XEXP (oldx
,0))
1016 if (offs
> MAX_LD_OFFSET (mode
))
1018 if (TARGET_ALL_DEBUG
)
1019 fprintf (stderr
, "force_reg (big offset)\n");
1020 x
= force_reg (GET_MODE (oldx
), oldx
);
1028 /* Return a pointer register name as a string. */
1031 ptrreg_to_str (int regno
)
1035 case REG_X
: return "X";
1036 case REG_Y
: return "Y";
1037 case REG_Z
: return "Z";
1039 output_operand_lossage ("address operand requires constraint for X, Y, or Z register");
1044 /* Return the condition name as a string.
1045 Used in conditional jump constructing */
1048 cond_string (enum rtx_code code
)
1057 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1062 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1075 /* Output ADDR to FILE as address. */
1078 print_operand_address (FILE *file
, rtx addr
)
1080 switch (GET_CODE (addr
))
1083 fprintf (file
, ptrreg_to_str (REGNO (addr
)));
1087 fprintf (file
, "-%s", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
1091 fprintf (file
, "%s+", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
1095 if (CONSTANT_ADDRESS_P (addr
)
1096 && ((GET_CODE (addr
) == SYMBOL_REF
&& SYMBOL_REF_FUNCTION_P (addr
))
1097 || GET_CODE (addr
) == LABEL_REF
))
1099 fprintf (file
, "pm(");
1100 output_addr_const (file
,addr
);
1101 fprintf (file
,")");
1104 output_addr_const (file
, addr
);
1109 /* Output X as assembler operand to file FILE. */
1112 print_operand (FILE *file
, rtx x
, int code
)
1116 if (code
>= 'A' && code
<= 'D')
1126 if (x
== zero_reg_rtx
)
1127 fprintf (file
, "__zero_reg__");
1129 fprintf (file
, reg_names
[true_regnum (x
) + abcd
]);
1131 else if (GET_CODE (x
) == CONST_INT
)
1132 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
) + abcd
);
1133 else if (GET_CODE (x
) == MEM
)
1135 rtx addr
= XEXP (x
,0);
1137 if (CONSTANT_P (addr
) && abcd
)
1140 output_address (addr
);
1141 fprintf (file
, ")+%d", abcd
);
1143 else if (code
== 'o')
1145 if (GET_CODE (addr
) != PLUS
)
1146 fatal_insn ("bad address, not (reg+disp):", addr
);
1148 print_operand (file
, XEXP (addr
, 1), 0);
1150 else if (code
== 'p' || code
== 'r')
1152 if (GET_CODE (addr
) != POST_INC
&& GET_CODE (addr
) != PRE_DEC
)
1153 fatal_insn ("bad address, not post_inc or pre_dec:", addr
);
1156 print_operand_address (file
, XEXP (addr
, 0)); /* X, Y, Z */
1158 print_operand (file
, XEXP (addr
, 0), 0); /* r26, r28, r30 */
1160 else if (GET_CODE (addr
) == PLUS
)
1162 print_operand_address (file
, XEXP (addr
,0));
1163 if (REGNO (XEXP (addr
, 0)) == REG_X
)
1164 fatal_insn ("internal compiler error. Bad address:"
1167 print_operand (file
, XEXP (addr
,1), code
);
1170 print_operand_address (file
, addr
);
1172 else if (GET_CODE (x
) == CONST_DOUBLE
)
1176 if (GET_MODE (x
) != SFmode
)
1177 fatal_insn ("internal compiler error. Unknown mode:", x
);
1178 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
1179 REAL_VALUE_TO_TARGET_SINGLE (rv
, val
);
1180 fprintf (file
, "0x%lx", val
);
1182 else if (code
== 'j')
1183 fputs (cond_string (GET_CODE (x
)), file
);
1184 else if (code
== 'k')
1185 fputs (cond_string (reverse_condition (GET_CODE (x
))), file
);
1187 print_operand_address (file
, x
);
1190 /* Update the condition code in the INSN. */
1193 notice_update_cc (rtx body ATTRIBUTE_UNUSED
, rtx insn
)
1197 switch (get_attr_cc (insn
))
1200 /* Insn does not affect CC at all. */
1208 set
= single_set (insn
);
1212 cc_status
.flags
|= CC_NO_OVERFLOW
;
1213 cc_status
.value1
= SET_DEST (set
);
1218 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1219 The V flag may or may not be known but that's ok because
1220 alter_cond will change tests to use EQ/NE. */
1221 set
= single_set (insn
);
1225 cc_status
.value1
= SET_DEST (set
);
1226 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1231 set
= single_set (insn
);
1234 cc_status
.value1
= SET_SRC (set
);
1238 /* Insn doesn't leave CC in a usable state. */
1241 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1242 set
= single_set (insn
);
1245 rtx src
= SET_SRC (set
);
1247 if (GET_CODE (src
) == ASHIFTRT
1248 && GET_MODE (src
) == QImode
)
1250 rtx x
= XEXP (src
, 1);
1252 if (GET_CODE (x
) == CONST_INT
1256 cc_status
.value1
= SET_DEST (set
);
1257 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1265 /* Return maximum number of consecutive registers of
1266 class CLASS needed to hold a value of mode MODE. */
1269 class_max_nregs (enum reg_class
class ATTRIBUTE_UNUSED
,enum machine_mode mode
)
1271 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
);
1274 /* Choose mode for jump insn:
1275 1 - relative jump in range -63 <= x <= 62 ;
1276 2 - relative jump in range -2046 <= x <= 2045 ;
1277 3 - absolute jump (only for ATmega[16]03). */
1280 avr_jump_mode (rtx x
, rtx insn
)
1282 int dest_addr
= INSN_ADDRESSES (INSN_UID (GET_MODE (x
) == LABEL_REF
1283 ? XEXP (x
, 0) : x
));
1284 int cur_addr
= INSN_ADDRESSES (INSN_UID (insn
));
1285 int jump_distance
= cur_addr
- dest_addr
;
1287 if (-63 <= jump_distance
&& jump_distance
<= 62)
1289 else if (-2046 <= jump_distance
&& jump_distance
<= 2045)
1297 /* return an AVR condition jump commands.
1298 X is a comparison RTX.
1299 LEN is a number returned by avr_jump_mode function.
1300 if REVERSE nonzero then condition code in X must be reversed. */
1303 ret_cond_branch (rtx x
, int len
, int reverse
)
1305 RTX_CODE cond
= reverse
? reverse_condition (GET_CODE (x
)) : GET_CODE (x
);
1310 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1311 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1313 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1314 AS1 (brmi
,.+2) CR_TAB
1316 (AS1 (breq
,.+6) CR_TAB
1317 AS1 (brmi
,.+4) CR_TAB
1321 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1323 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1324 AS1 (brlt
,.+2) CR_TAB
1326 (AS1 (breq
,.+6) CR_TAB
1327 AS1 (brlt
,.+4) CR_TAB
1330 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1332 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1333 AS1 (brlo
,.+2) CR_TAB
1335 (AS1 (breq
,.+6) CR_TAB
1336 AS1 (brlo
,.+4) CR_TAB
1339 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1340 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1342 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1343 AS1 (brpl
,.+2) CR_TAB
1345 (AS1 (breq
,.+2) CR_TAB
1346 AS1 (brpl
,.+4) CR_TAB
1349 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1351 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1352 AS1 (brge
,.+2) CR_TAB
1354 (AS1 (breq
,.+2) CR_TAB
1355 AS1 (brge
,.+4) CR_TAB
1358 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1360 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1361 AS1 (brsh
,.+2) CR_TAB
1363 (AS1 (breq
,.+2) CR_TAB
1364 AS1 (brsh
,.+4) CR_TAB
1372 return AS1 (br
%k1
,%0);
1374 return (AS1 (br
%j1
,.+2) CR_TAB
1377 return (AS1 (br
%j1
,.+4) CR_TAB
1386 return AS1 (br
%j1
,%0);
1388 return (AS1 (br
%k1
,.+2) CR_TAB
1391 return (AS1 (br
%k1
,.+4) CR_TAB
1399 /* Predicate function for immediate operand which fits to byte (8bit) */
1402 byte_immediate_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
1404 return (GET_CODE (op
) == CONST_INT
1405 && INTVAL (op
) <= 0xff && INTVAL (op
) >= 0);
1408 /* Output all insn addresses and their sizes into the assembly language
1409 output file. This is helpful for debugging whether the length attributes
1410 in the md file are correct.
1411 Output insn cost for next insn. */
1414 final_prescan_insn (rtx insn
, rtx
*operand ATTRIBUTE_UNUSED
,
1415 int num_operands ATTRIBUTE_UNUSED
)
1417 int uid
= INSN_UID (insn
);
1419 if (TARGET_INSN_SIZE_DUMP
|| TARGET_ALL_DEBUG
)
1421 fprintf (asm_out_file
, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1422 INSN_ADDRESSES (uid
),
1423 INSN_ADDRESSES (uid
) - last_insn_address
,
1424 rtx_cost (PATTERN (insn
), INSN
));
1426 last_insn_address
= INSN_ADDRESSES (uid
);
1429 /* Return 0 if undefined, 1 if always true or always false. */
1432 avr_simplify_comparison_p (enum machine_mode mode
, RTX_CODE
operator, rtx x
)
1434 unsigned int max
= (mode
== QImode
? 0xff :
1435 mode
== HImode
? 0xffff :
1436 mode
== SImode
? 0xffffffff : 0);
1437 if (max
&& operator && GET_CODE (x
) == CONST_INT
)
1439 if (unsigned_condition (operator) != operator)
1442 if (max
!= (INTVAL (x
) & max
)
1443 && INTVAL (x
) != 0xff)
1450 /* Returns nonzero if REGNO is the number of a hard
1451 register in which function arguments are sometimes passed. */
1454 function_arg_regno_p(int r
)
1456 return (r
>= 8 && r
<= 25);
1459 /* Initializing the variable cum for the state at the beginning
1460 of the argument list. */
1463 init_cumulative_args (CUMULATIVE_ARGS
*cum
, tree fntype
, rtx libname
,
1464 tree fndecl ATTRIBUTE_UNUSED
)
1467 cum
->regno
= FIRST_CUM_REG
;
1468 if (!libname
&& fntype
)
1470 int stdarg
= (TYPE_ARG_TYPES (fntype
) != 0
1471 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype
)))
1472 != void_type_node
));
1478 /* Returns the number of registers to allocate for a function argument. */
1481 avr_num_arg_regs (enum machine_mode mode
, tree type
)
1485 if (mode
== BLKmode
)
1486 size
= int_size_in_bytes (type
);
1488 size
= GET_MODE_SIZE (mode
);
1490 /* Align all function arguments to start in even-numbered registers.
1491 Odd-sized arguments leave holes above them. */
1493 return (size
+ 1) & ~1;
1496 /* Controls whether a function argument is passed
1497 in a register, and which register. */
1500 function_arg (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
, tree type
,
1501 int named ATTRIBUTE_UNUSED
)
1503 int bytes
= avr_num_arg_regs (mode
, type
);
1505 if (cum
->nregs
&& bytes
<= cum
->nregs
)
1506 return gen_rtx_REG (mode
, cum
->regno
- bytes
);
1511 /* Update the summarizer variable CUM to advance past an argument
1512 in the argument list. */
1515 function_arg_advance (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
, tree type
,
1516 int named ATTRIBUTE_UNUSED
)
1518 int bytes
= avr_num_arg_regs (mode
, type
);
1520 cum
->nregs
-= bytes
;
1521 cum
->regno
-= bytes
;
1523 if (cum
->nregs
<= 0)
1526 cum
->regno
= FIRST_CUM_REG
;
1530 /***********************************************************************
1531 Functions for outputting various mov's for a various modes
1532 ************************************************************************/
1534 output_movqi (rtx insn
, rtx operands
[], int *l
)
1537 rtx dest
= operands
[0];
1538 rtx src
= operands
[1];
1546 if (register_operand (dest
, QImode
))
1548 if (register_operand (src
, QImode
)) /* mov r,r */
1550 if (test_hard_reg_class (STACK_REG
, dest
))
1551 return AS2 (out
,%0,%1);
1552 else if (test_hard_reg_class (STACK_REG
, src
))
1553 return AS2 (in
,%0,%1);
1555 return AS2 (mov
,%0,%1);
1557 else if (CONSTANT_P (src
))
1559 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
1560 return AS2 (ldi
,%0,lo8(%1));
1562 if (GET_CODE (src
) == CONST_INT
)
1564 if (src
== const0_rtx
) /* mov r,L */
1565 return AS1 (clr
,%0);
1566 else if (src
== const1_rtx
)
1569 return (AS1 (clr
,%0) CR_TAB
1572 else if (src
== constm1_rtx
)
1574 /* Immediate constants -1 to any register */
1576 return (AS1 (clr
,%0) CR_TAB
1581 int bit_nr
= exact_log2 (INTVAL (src
));
1587 output_asm_insn ((AS1 (clr
,%0) CR_TAB
1590 avr_output_bld (operands
, bit_nr
);
1597 /* Last resort, larger than loading from memory. */
1599 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1600 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1601 AS2 (mov
,%0,r31
) CR_TAB
1602 AS2 (mov
,r31
,__tmp_reg__
));
1604 else if (GET_CODE (src
) == MEM
)
1605 return out_movqi_r_mr (insn
, operands
, real_l
); /* mov r,m */
1607 else if (GET_CODE (dest
) == MEM
)
1609 const char *template;
1611 if (src
== const0_rtx
)
1612 operands
[1] = zero_reg_rtx
;
1614 template = out_movqi_mr_r (insn
, operands
, real_l
);
1617 output_asm_insn (template, operands
);
1626 output_movhi (rtx insn
, rtx operands
[], int *l
)
1629 rtx dest
= operands
[0];
1630 rtx src
= operands
[1];
1636 if (register_operand (dest
, HImode
))
1638 if (register_operand (src
, HImode
)) /* mov r,r */
1640 if (test_hard_reg_class (STACK_REG
, dest
))
1642 if (TARGET_TINY_STACK
)
1645 return AS2 (out
,__SP_L__
,%A1
);
1647 /* Use simple load of stack pointer if no interrupts are used
1648 or inside main or signal function prologue where they disabled. */
1649 else if (TARGET_NO_INTERRUPTS
1650 || (reload_completed
1651 && cfun
->machine
->is_main
1652 && prologue_epilogue_contains (insn
))
1653 || (reload_completed
1654 && cfun
->machine
->is_signal
1655 && prologue_epilogue_contains (insn
)))
1658 return (AS2 (out
,__SP_H__
,%B1
) CR_TAB
1659 AS2 (out
,__SP_L__
,%A1
));
1661 /* In interrupt prolog we know interrupts are enabled. */
1662 else if (reload_completed
1663 && cfun
->machine
->is_interrupt
1664 && prologue_epilogue_contains (insn
))
1667 return ("cli" CR_TAB
1668 AS2 (out
,__SP_H__
,%B1
) CR_TAB
1670 AS2 (out
,__SP_L__
,%A1
));
1673 return (AS2 (in
,__tmp_reg__
,__SREG__
) CR_TAB
1675 AS2 (out
,__SP_H__
,%B1
) CR_TAB
1676 AS2 (out
,__SREG__
,__tmp_reg__
) CR_TAB
1677 AS2 (out
,__SP_L__
,%A1
));
1679 else if (test_hard_reg_class (STACK_REG
, src
))
1682 return (AS2 (in
,%A0
,__SP_L__
) CR_TAB
1683 AS2 (in
,%B0
,__SP_H__
));
1689 return (AS2 (movw
,%0,%1));
1694 return (AS2 (mov
,%A0
,%A1
) CR_TAB
1698 else if (CONSTANT_P (src
))
1700 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
1703 return (AS2 (ldi
,%A0
,lo8(%1)) CR_TAB
1704 AS2 (ldi
,%B0
,hi8(%1)));
1707 if (GET_CODE (src
) == CONST_INT
)
1709 if (src
== const0_rtx
) /* mov r,L */
1712 return (AS1 (clr
,%A0
) CR_TAB
1715 else if (src
== const1_rtx
)
1718 return (AS1 (clr
,%A0
) CR_TAB
1719 AS1 (clr
,%B0
) CR_TAB
1722 else if (src
== constm1_rtx
)
1724 /* Immediate constants -1 to any register */
1726 return (AS1 (clr
,%0) CR_TAB
1727 AS1 (dec
,%A0
) CR_TAB
1732 int bit_nr
= exact_log2 (INTVAL (src
));
1738 output_asm_insn ((AS1 (clr
,%A0
) CR_TAB
1739 AS1 (clr
,%B0
) CR_TAB
1742 avr_output_bld (operands
, bit_nr
);
1748 if ((INTVAL (src
) & 0xff) == 0)
1751 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1752 AS1 (clr
,%A0
) CR_TAB
1753 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
1754 AS2 (mov
,%B0
,r31
) CR_TAB
1755 AS2 (mov
,r31
,__tmp_reg__
));
1757 else if ((INTVAL (src
) & 0xff00) == 0)
1760 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1761 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1762 AS2 (mov
,%A0
,r31
) CR_TAB
1763 AS1 (clr
,%B0
) CR_TAB
1764 AS2 (mov
,r31
,__tmp_reg__
));
1768 /* Last resort, equal to loading from memory. */
1770 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1771 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1772 AS2 (mov
,%A0
,r31
) CR_TAB
1773 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
1774 AS2 (mov
,%B0
,r31
) CR_TAB
1775 AS2 (mov
,r31
,__tmp_reg__
));
1777 else if (GET_CODE (src
) == MEM
)
1778 return out_movhi_r_mr (insn
, operands
, real_l
); /* mov r,m */
1780 else if (GET_CODE (dest
) == MEM
)
1782 const char *template;
1784 if (src
== const0_rtx
)
1785 operands
[1] = zero_reg_rtx
;
1787 template = out_movhi_mr_r (insn
, operands
, real_l
);
1790 output_asm_insn (template, operands
);
1795 fatal_insn ("invalid insn:", insn
);
1800 out_movqi_r_mr (rtx insn
, rtx op
[], int *l
)
1804 rtx x
= XEXP (src
, 0);
1810 if (CONSTANT_ADDRESS_P (x
))
1812 if (CONST_INT_P (x
) && INTVAL (x
) == SREG_ADDR
)
1815 return AS2 (in
,%0,__SREG__
);
1817 if (avr_io_address_p (x
, 1))
1820 return AS2 (in
,%0,%1-0x20);
1823 return AS2 (lds
,%0,%1);
1825 /* memory access by reg+disp */
1826 else if (GET_CODE (x
) == PLUS
1827 && REG_P (XEXP (x
,0))
1828 && GET_CODE (XEXP (x
,1)) == CONST_INT
)
1830 if ((INTVAL (XEXP (x
,1)) - GET_MODE_SIZE (GET_MODE (src
))) >= 63)
1832 int disp
= INTVAL (XEXP (x
,1));
1833 if (REGNO (XEXP (x
,0)) != REG_Y
)
1834 fatal_insn ("incorrect insn:",insn
);
1836 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
1837 return *l
= 3, (AS2 (adiw
,r28
,%o1
-63) CR_TAB
1838 AS2 (ldd
,%0,Y
+63) CR_TAB
1839 AS2 (sbiw
,r28
,%o1
-63));
1841 return *l
= 5, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
1842 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
1843 AS2 (ld
,%0,Y
) CR_TAB
1844 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
1845 AS2 (sbci
,r29
,hi8(%o1
)));
1847 else if (REGNO (XEXP (x
,0)) == REG_X
)
1849 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1850 it but I have this situation with extremal optimizing options. */
1851 if (reg_overlap_mentioned_p (dest
, XEXP (x
,0))
1852 || reg_unused_after (insn
, XEXP (x
,0)))
1853 return *l
= 2, (AS2 (adiw
,r26
,%o1
) CR_TAB
1856 return *l
= 3, (AS2 (adiw
,r26
,%o1
) CR_TAB
1857 AS2 (ld
,%0,X
) CR_TAB
1858 AS2 (sbiw
,r26
,%o1
));
1861 return AS2 (ldd
,%0,%1);
1864 return AS2 (ld
,%0,%1);
1868 out_movhi_r_mr (rtx insn
, rtx op
[], int *l
)
1872 rtx base
= XEXP (src
, 0);
1873 int reg_dest
= true_regnum (dest
);
1874 int reg_base
= true_regnum (base
);
1875 /* "volatile" forces reading low byte first, even if less efficient,
1876 for correct operation with 16-bit I/O registers. */
1877 int mem_volatile_p
= MEM_VOLATILE_P (src
);
1885 if (reg_dest
== reg_base
) /* R = (R) */
1888 return (AS2 (ld
,__tmp_reg__
,%1+) CR_TAB
1889 AS2 (ld
,%B0
,%1) CR_TAB
1890 AS2 (mov
,%A0
,__tmp_reg__
));
1892 else if (reg_base
== REG_X
) /* (R26) */
1894 if (reg_unused_after (insn
, base
))
1897 return (AS2 (ld
,%A0
,X
+) CR_TAB
1901 return (AS2 (ld
,%A0
,X
+) CR_TAB
1902 AS2 (ld
,%B0
,X
) CR_TAB
1908 return (AS2 (ld
,%A0
,%1) CR_TAB
1909 AS2 (ldd
,%B0
,%1+1));
1912 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
1914 int disp
= INTVAL (XEXP (base
, 1));
1915 int reg_base
= true_regnum (XEXP (base
, 0));
1917 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
1919 if (REGNO (XEXP (base
, 0)) != REG_Y
)
1920 fatal_insn ("incorrect insn:",insn
);
1922 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
1923 return *l
= 4, (AS2 (adiw
,r28
,%o1
-62) CR_TAB
1924 AS2 (ldd
,%A0
,Y
+62) CR_TAB
1925 AS2 (ldd
,%B0
,Y
+63) CR_TAB
1926 AS2 (sbiw
,r28
,%o1
-62));
1928 return *l
= 6, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
1929 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
1930 AS2 (ld
,%A0
,Y
) CR_TAB
1931 AS2 (ldd
,%B0
,Y
+1) CR_TAB
1932 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
1933 AS2 (sbci
,r29
,hi8(%o1
)));
1935 if (reg_base
== REG_X
)
1937 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1938 it but I have this situation with extremal
1939 optimization options. */
1942 if (reg_base
== reg_dest
)
1943 return (AS2 (adiw
,r26
,%o1
) CR_TAB
1944 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
1945 AS2 (ld
,%B0
,X
) CR_TAB
1946 AS2 (mov
,%A0
,__tmp_reg__
));
1948 return (AS2 (adiw
,r26
,%o1
) CR_TAB
1949 AS2 (ld
,%A0
,X
+) CR_TAB
1950 AS2 (ld
,%B0
,X
) CR_TAB
1951 AS2 (sbiw
,r26
,%o1
+1));
1954 if (reg_base
== reg_dest
)
1957 return (AS2 (ldd
,__tmp_reg__
,%A1
) CR_TAB
1958 AS2 (ldd
,%B0
,%B1
) CR_TAB
1959 AS2 (mov
,%A0
,__tmp_reg__
));
1963 return (AS2 (ldd
,%A0
,%A1
) CR_TAB
1966 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
1968 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
1969 fatal_insn ("incorrect insn:", insn
);
1973 if (REGNO (XEXP (base
, 0)) == REG_X
)
1976 return (AS2 (sbiw
,r26
,2) CR_TAB
1977 AS2 (ld
,%A0
,X
+) CR_TAB
1978 AS2 (ld
,%B0
,X
) CR_TAB
1984 return (AS2 (sbiw
,%r1
,2) CR_TAB
1985 AS2 (ld
,%A0
,%p1
) CR_TAB
1986 AS2 (ldd
,%B0
,%p1
+1));
1991 return (AS2 (ld
,%B0
,%1) CR_TAB
1994 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
1996 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
1997 fatal_insn ("incorrect insn:", insn
);
2000 return (AS2 (ld
,%A0
,%1) CR_TAB
2003 else if (CONSTANT_ADDRESS_P (base
))
2005 if (avr_io_address_p (base
, 2))
2008 return (AS2 (in
,%A0
,%A1
-0x20) CR_TAB
2009 AS2 (in
,%B0
,%B1
-0x20));
2012 return (AS2 (lds
,%A0
,%A1
) CR_TAB
2016 fatal_insn ("unknown move insn:",insn
);
2021 out_movsi_r_mr (rtx insn
, rtx op
[], int *l
)
2025 rtx base
= XEXP (src
, 0);
2026 int reg_dest
= true_regnum (dest
);
2027 int reg_base
= true_regnum (base
);
2035 if (reg_base
== REG_X
) /* (R26) */
2037 if (reg_dest
== REG_X
)
2038 /* "ld r26,-X" is undefined */
2039 return *l
=7, (AS2 (adiw
,r26
,3) CR_TAB
2040 AS2 (ld
,r29
,X
) CR_TAB
2041 AS2 (ld
,r28
,-X
) CR_TAB
2042 AS2 (ld
,__tmp_reg__
,-X
) CR_TAB
2043 AS2 (sbiw
,r26
,1) CR_TAB
2044 AS2 (ld
,r26
,X
) CR_TAB
2045 AS2 (mov
,r27
,__tmp_reg__
));
2046 else if (reg_dest
== REG_X
- 2)
2047 return *l
=5, (AS2 (ld
,%A0
,X
+) CR_TAB
2048 AS2 (ld
,%B0
,X
+) CR_TAB
2049 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2050 AS2 (ld
,%D0
,X
) CR_TAB
2051 AS2 (mov
,%C0
,__tmp_reg__
));
2052 else if (reg_unused_after (insn
, base
))
2053 return *l
=4, (AS2 (ld
,%A0
,X
+) CR_TAB
2054 AS2 (ld
,%B0
,X
+) CR_TAB
2055 AS2 (ld
,%C0
,X
+) CR_TAB
2058 return *l
=5, (AS2 (ld
,%A0
,X
+) CR_TAB
2059 AS2 (ld
,%B0
,X
+) CR_TAB
2060 AS2 (ld
,%C0
,X
+) CR_TAB
2061 AS2 (ld
,%D0
,X
) CR_TAB
2066 if (reg_dest
== reg_base
)
2067 return *l
=5, (AS2 (ldd
,%D0
,%1+3) CR_TAB
2068 AS2 (ldd
,%C0
,%1+2) CR_TAB
2069 AS2 (ldd
,__tmp_reg__
,%1+1) CR_TAB
2070 AS2 (ld
,%A0
,%1) CR_TAB
2071 AS2 (mov
,%B0
,__tmp_reg__
));
2072 else if (reg_base
== reg_dest
+ 2)
2073 return *l
=5, (AS2 (ld
,%A0
,%1) CR_TAB
2074 AS2 (ldd
,%B0
,%1+1) CR_TAB
2075 AS2 (ldd
,__tmp_reg__
,%1+2) CR_TAB
2076 AS2 (ldd
,%D0
,%1+3) CR_TAB
2077 AS2 (mov
,%C0
,__tmp_reg__
));
2079 return *l
=4, (AS2 (ld
,%A0
,%1) CR_TAB
2080 AS2 (ldd
,%B0
,%1+1) CR_TAB
2081 AS2 (ldd
,%C0
,%1+2) CR_TAB
2082 AS2 (ldd
,%D0
,%1+3));
2085 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2087 int disp
= INTVAL (XEXP (base
, 1));
2089 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
2091 if (REGNO (XEXP (base
, 0)) != REG_Y
)
2092 fatal_insn ("incorrect insn:",insn
);
2094 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
2095 return *l
= 6, (AS2 (adiw
,r28
,%o1
-60) CR_TAB
2096 AS2 (ldd
,%A0
,Y
+60) CR_TAB
2097 AS2 (ldd
,%B0
,Y
+61) CR_TAB
2098 AS2 (ldd
,%C0
,Y
+62) CR_TAB
2099 AS2 (ldd
,%D0
,Y
+63) CR_TAB
2100 AS2 (sbiw
,r28
,%o1
-60));
2102 return *l
= 8, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
2103 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
2104 AS2 (ld
,%A0
,Y
) CR_TAB
2105 AS2 (ldd
,%B0
,Y
+1) CR_TAB
2106 AS2 (ldd
,%C0
,Y
+2) CR_TAB
2107 AS2 (ldd
,%D0
,Y
+3) CR_TAB
2108 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
2109 AS2 (sbci
,r29
,hi8(%o1
)));
2112 reg_base
= true_regnum (XEXP (base
, 0));
2113 if (reg_base
== REG_X
)
2116 if (reg_dest
== REG_X
)
2119 /* "ld r26,-X" is undefined */
2120 return (AS2 (adiw
,r26
,%o1
+3) CR_TAB
2121 AS2 (ld
,r29
,X
) CR_TAB
2122 AS2 (ld
,r28
,-X
) CR_TAB
2123 AS2 (ld
,__tmp_reg__
,-X
) CR_TAB
2124 AS2 (sbiw
,r26
,1) CR_TAB
2125 AS2 (ld
,r26
,X
) CR_TAB
2126 AS2 (mov
,r27
,__tmp_reg__
));
2129 if (reg_dest
== REG_X
- 2)
2130 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2131 AS2 (ld
,r24
,X
+) CR_TAB
2132 AS2 (ld
,r25
,X
+) CR_TAB
2133 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2134 AS2 (ld
,r27
,X
) CR_TAB
2135 AS2 (mov
,r26
,__tmp_reg__
));
2137 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2138 AS2 (ld
,%A0
,X
+) CR_TAB
2139 AS2 (ld
,%B0
,X
+) CR_TAB
2140 AS2 (ld
,%C0
,X
+) CR_TAB
2141 AS2 (ld
,%D0
,X
) CR_TAB
2142 AS2 (sbiw
,r26
,%o1
+3));
2144 if (reg_dest
== reg_base
)
2145 return *l
=5, (AS2 (ldd
,%D0
,%D1
) CR_TAB
2146 AS2 (ldd
,%C0
,%C1
) CR_TAB
2147 AS2 (ldd
,__tmp_reg__
,%B1
) CR_TAB
2148 AS2 (ldd
,%A0
,%A1
) CR_TAB
2149 AS2 (mov
,%B0
,__tmp_reg__
));
2150 else if (reg_dest
== reg_base
- 2)
2151 return *l
=5, (AS2 (ldd
,%A0
,%A1
) CR_TAB
2152 AS2 (ldd
,%B0
,%B1
) CR_TAB
2153 AS2 (ldd
,__tmp_reg__
,%C1
) CR_TAB
2154 AS2 (ldd
,%D0
,%D1
) CR_TAB
2155 AS2 (mov
,%C0
,__tmp_reg__
));
2156 return *l
=4, (AS2 (ldd
,%A0
,%A1
) CR_TAB
2157 AS2 (ldd
,%B0
,%B1
) CR_TAB
2158 AS2 (ldd
,%C0
,%C1
) CR_TAB
2161 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2162 return *l
=4, (AS2 (ld
,%D0
,%1) CR_TAB
2163 AS2 (ld
,%C0
,%1) CR_TAB
2164 AS2 (ld
,%B0
,%1) CR_TAB
2166 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2167 return *l
=4, (AS2 (ld
,%A0
,%1) CR_TAB
2168 AS2 (ld
,%B0
,%1) CR_TAB
2169 AS2 (ld
,%C0
,%1) CR_TAB
2171 else if (CONSTANT_ADDRESS_P (base
))
2172 return *l
=8, (AS2 (lds
,%A0
,%A1
) CR_TAB
2173 AS2 (lds
,%B0
,%B1
) CR_TAB
2174 AS2 (lds
,%C0
,%C1
) CR_TAB
2177 fatal_insn ("unknown move insn:",insn
);
2182 out_movsi_mr_r (rtx insn
, rtx op
[], int *l
)
2186 rtx base
= XEXP (dest
, 0);
2187 int reg_base
= true_regnum (base
);
2188 int reg_src
= true_regnum (src
);
2194 if (CONSTANT_ADDRESS_P (base
))
2195 return *l
=8,(AS2 (sts
,%A0
,%A1
) CR_TAB
2196 AS2 (sts
,%B0
,%B1
) CR_TAB
2197 AS2 (sts
,%C0
,%C1
) CR_TAB
2199 if (reg_base
> 0) /* (r) */
2201 if (reg_base
== REG_X
) /* (R26) */
2203 if (reg_src
== REG_X
)
2205 /* "st X+,r26" is undefined */
2206 if (reg_unused_after (insn
, base
))
2207 return *l
=6, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2208 AS2 (st
,X
,r26
) CR_TAB
2209 AS2 (adiw
,r26
,1) CR_TAB
2210 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2211 AS2 (st
,X
+,r28
) CR_TAB
2214 return *l
=7, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2215 AS2 (st
,X
,r26
) CR_TAB
2216 AS2 (adiw
,r26
,1) CR_TAB
2217 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2218 AS2 (st
,X
+,r28
) CR_TAB
2219 AS2 (st
,X
,r29
) CR_TAB
2222 else if (reg_base
== reg_src
+ 2)
2224 if (reg_unused_after (insn
, base
))
2225 return *l
=7, (AS2 (mov
,__zero_reg__
,%C1
) CR_TAB
2226 AS2 (mov
,__tmp_reg__
,%D1
) CR_TAB
2227 AS2 (st
,%0+,%A1
) CR_TAB
2228 AS2 (st
,%0+,%B1
) CR_TAB
2229 AS2 (st
,%0+,__zero_reg__
) CR_TAB
2230 AS2 (st
,%0,__tmp_reg__
) CR_TAB
2231 AS1 (clr
,__zero_reg__
));
2233 return *l
=8, (AS2 (mov
,__zero_reg__
,%C1
) CR_TAB
2234 AS2 (mov
,__tmp_reg__
,%D1
) CR_TAB
2235 AS2 (st
,%0+,%A1
) CR_TAB
2236 AS2 (st
,%0+,%B1
) CR_TAB
2237 AS2 (st
,%0+,__zero_reg__
) CR_TAB
2238 AS2 (st
,%0,__tmp_reg__
) CR_TAB
2239 AS1 (clr
,__zero_reg__
) CR_TAB
2242 return *l
=5, (AS2 (st
,%0+,%A1
) CR_TAB
2243 AS2 (st
,%0+,%B1
) CR_TAB
2244 AS2 (st
,%0+,%C1
) CR_TAB
2245 AS2 (st
,%0,%D1
) CR_TAB
2249 return *l
=4, (AS2 (st
,%0,%A1
) CR_TAB
2250 AS2 (std
,%0+1,%B1
) CR_TAB
2251 AS2 (std
,%0+2,%C1
) CR_TAB
2252 AS2 (std
,%0+3,%D1
));
2254 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2256 int disp
= INTVAL (XEXP (base
, 1));
2257 reg_base
= REGNO (XEXP (base
, 0));
2258 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
2260 if (reg_base
!= REG_Y
)
2261 fatal_insn ("incorrect insn:",insn
);
2263 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2264 return *l
= 6, (AS2 (adiw
,r28
,%o0
-60) CR_TAB
2265 AS2 (std
,Y
+60,%A1
) CR_TAB
2266 AS2 (std
,Y
+61,%B1
) CR_TAB
2267 AS2 (std
,Y
+62,%C1
) CR_TAB
2268 AS2 (std
,Y
+63,%D1
) CR_TAB
2269 AS2 (sbiw
,r28
,%o0
-60));
2271 return *l
= 8, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2272 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2273 AS2 (st
,Y
,%A1
) CR_TAB
2274 AS2 (std
,Y
+1,%B1
) CR_TAB
2275 AS2 (std
,Y
+2,%C1
) CR_TAB
2276 AS2 (std
,Y
+3,%D1
) CR_TAB
2277 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2278 AS2 (sbci
,r29
,hi8(%o0
)));
2280 if (reg_base
== REG_X
)
2283 if (reg_src
== REG_X
)
2286 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2287 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2288 AS2 (adiw
,r26
,%o0
) CR_TAB
2289 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2290 AS2 (st
,X
+,__zero_reg__
) CR_TAB
2291 AS2 (st
,X
+,r28
) CR_TAB
2292 AS2 (st
,X
,r29
) CR_TAB
2293 AS1 (clr
,__zero_reg__
) CR_TAB
2294 AS2 (sbiw
,r26
,%o0
+3));
2296 else if (reg_src
== REG_X
- 2)
2299 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2300 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2301 AS2 (adiw
,r26
,%o0
) CR_TAB
2302 AS2 (st
,X
+,r24
) CR_TAB
2303 AS2 (st
,X
+,r25
) CR_TAB
2304 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2305 AS2 (st
,X
,__zero_reg__
) CR_TAB
2306 AS1 (clr
,__zero_reg__
) CR_TAB
2307 AS2 (sbiw
,r26
,%o0
+3));
2310 return (AS2 (adiw
,r26
,%o0
) CR_TAB
2311 AS2 (st
,X
+,%A1
) CR_TAB
2312 AS2 (st
,X
+,%B1
) CR_TAB
2313 AS2 (st
,X
+,%C1
) CR_TAB
2314 AS2 (st
,X
,%D1
) CR_TAB
2315 AS2 (sbiw
,r26
,%o0
+3));
2317 return *l
=4, (AS2 (std
,%A0
,%A1
) CR_TAB
2318 AS2 (std
,%B0
,%B1
) CR_TAB
2319 AS2 (std
,%C0
,%C1
) CR_TAB
2322 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2323 return *l
=4, (AS2 (st
,%0,%D1
) CR_TAB
2324 AS2 (st
,%0,%C1
) CR_TAB
2325 AS2 (st
,%0,%B1
) CR_TAB
2327 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2328 return *l
=4, (AS2 (st
,%0,%A1
) CR_TAB
2329 AS2 (st
,%0,%B1
) CR_TAB
2330 AS2 (st
,%0,%C1
) CR_TAB
2332 fatal_insn ("unknown move insn:",insn
);
2337 output_movsisf(rtx insn
, rtx operands
[], int *l
)
2340 rtx dest
= operands
[0];
2341 rtx src
= operands
[1];
2347 if (register_operand (dest
, VOIDmode
))
2349 if (register_operand (src
, VOIDmode
)) /* mov r,r */
2351 if (true_regnum (dest
) > true_regnum (src
))
2356 return (AS2 (movw
,%C0
,%C1
) CR_TAB
2357 AS2 (movw
,%A0
,%A1
));
2360 return (AS2 (mov
,%D0
,%D1
) CR_TAB
2361 AS2 (mov
,%C0
,%C1
) CR_TAB
2362 AS2 (mov
,%B0
,%B1
) CR_TAB
2370 return (AS2 (movw
,%A0
,%A1
) CR_TAB
2371 AS2 (movw
,%C0
,%C1
));
2374 return (AS2 (mov
,%A0
,%A1
) CR_TAB
2375 AS2 (mov
,%B0
,%B1
) CR_TAB
2376 AS2 (mov
,%C0
,%C1
) CR_TAB
2380 else if (CONSTANT_P (src
))
2382 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
2385 return (AS2 (ldi
,%A0
,lo8(%1)) CR_TAB
2386 AS2 (ldi
,%B0
,hi8(%1)) CR_TAB
2387 AS2 (ldi
,%C0
,hlo8(%1)) CR_TAB
2388 AS2 (ldi
,%D0
,hhi8(%1)));
2391 if (GET_CODE (src
) == CONST_INT
)
2393 const char *const clr_op0
=
2394 AVR_HAVE_MOVW
? (AS1 (clr
,%A0
) CR_TAB
2395 AS1 (clr
,%B0
) CR_TAB
2397 : (AS1 (clr
,%A0
) CR_TAB
2398 AS1 (clr
,%B0
) CR_TAB
2399 AS1 (clr
,%C0
) CR_TAB
2402 if (src
== const0_rtx
) /* mov r,L */
2404 *l
= AVR_HAVE_MOVW
? 3 : 4;
2407 else if (src
== const1_rtx
)
2410 output_asm_insn (clr_op0
, operands
);
2411 *l
= AVR_HAVE_MOVW
? 4 : 5;
2412 return AS1 (inc
,%A0
);
2414 else if (src
== constm1_rtx
)
2416 /* Immediate constants -1 to any register */
2420 return (AS1 (clr
,%A0
) CR_TAB
2421 AS1 (dec
,%A0
) CR_TAB
2422 AS2 (mov
,%B0
,%A0
) CR_TAB
2423 AS2 (movw
,%C0
,%A0
));
2426 return (AS1 (clr
,%A0
) CR_TAB
2427 AS1 (dec
,%A0
) CR_TAB
2428 AS2 (mov
,%B0
,%A0
) CR_TAB
2429 AS2 (mov
,%C0
,%A0
) CR_TAB
2434 int bit_nr
= exact_log2 (INTVAL (src
));
2438 *l
= AVR_HAVE_MOVW
? 5 : 6;
2441 output_asm_insn (clr_op0
, operands
);
2442 output_asm_insn ("set", operands
);
2445 avr_output_bld (operands
, bit_nr
);
2452 /* Last resort, better than loading from memory. */
2454 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
2455 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
2456 AS2 (mov
,%A0
,r31
) CR_TAB
2457 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
2458 AS2 (mov
,%B0
,r31
) CR_TAB
2459 AS2 (ldi
,r31
,hlo8(%1)) CR_TAB
2460 AS2 (mov
,%C0
,r31
) CR_TAB
2461 AS2 (ldi
,r31
,hhi8(%1)) CR_TAB
2462 AS2 (mov
,%D0
,r31
) CR_TAB
2463 AS2 (mov
,r31
,__tmp_reg__
));
2465 else if (GET_CODE (src
) == MEM
)
2466 return out_movsi_r_mr (insn
, operands
, real_l
); /* mov r,m */
2468 else if (GET_CODE (dest
) == MEM
)
2470 const char *template;
2472 if (src
== const0_rtx
)
2473 operands
[1] = zero_reg_rtx
;
2475 template = out_movsi_mr_r (insn
, operands
, real_l
);
2478 output_asm_insn (template, operands
);
2483 fatal_insn ("invalid insn:", insn
);
2488 out_movqi_mr_r (rtx insn
, rtx op
[], int *l
)
2492 rtx x
= XEXP (dest
, 0);
2498 if (CONSTANT_ADDRESS_P (x
))
2500 if (CONST_INT_P (x
) && INTVAL (x
) == SREG_ADDR
)
2503 return AS2 (out
,__SREG__
,%1);
2505 if (avr_io_address_p (x
, 1))
2508 return AS2 (out
,%0-0x20,%1);
2511 return AS2 (sts
,%0,%1);
2513 /* memory access by reg+disp */
2514 else if (GET_CODE (x
) == PLUS
2515 && REG_P (XEXP (x
,0))
2516 && GET_CODE (XEXP (x
,1)) == CONST_INT
)
2518 if ((INTVAL (XEXP (x
,1)) - GET_MODE_SIZE (GET_MODE (dest
))) >= 63)
2520 int disp
= INTVAL (XEXP (x
,1));
2521 if (REGNO (XEXP (x
,0)) != REG_Y
)
2522 fatal_insn ("incorrect insn:",insn
);
2524 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2525 return *l
= 3, (AS2 (adiw
,r28
,%o0
-63) CR_TAB
2526 AS2 (std
,Y
+63,%1) CR_TAB
2527 AS2 (sbiw
,r28
,%o0
-63));
2529 return *l
= 5, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2530 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2531 AS2 (st
,Y
,%1) CR_TAB
2532 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2533 AS2 (sbci
,r29
,hi8(%o0
)));
2535 else if (REGNO (XEXP (x
,0)) == REG_X
)
2537 if (reg_overlap_mentioned_p (src
, XEXP (x
, 0)))
2539 if (reg_unused_after (insn
, XEXP (x
,0)))
2540 return *l
= 3, (AS2 (mov
,__tmp_reg__
,%1) CR_TAB
2541 AS2 (adiw
,r26
,%o0
) CR_TAB
2542 AS2 (st
,X
,__tmp_reg__
));
2544 return *l
= 4, (AS2 (mov
,__tmp_reg__
,%1) CR_TAB
2545 AS2 (adiw
,r26
,%o0
) CR_TAB
2546 AS2 (st
,X
,__tmp_reg__
) CR_TAB
2547 AS2 (sbiw
,r26
,%o0
));
2551 if (reg_unused_after (insn
, XEXP (x
,0)))
2552 return *l
= 2, (AS2 (adiw
,r26
,%o0
) CR_TAB
2555 return *l
= 3, (AS2 (adiw
,r26
,%o0
) CR_TAB
2556 AS2 (st
,X
,%1) CR_TAB
2557 AS2 (sbiw
,r26
,%o0
));
2561 return AS2 (std
,%0,%1);
2564 return AS2 (st
,%0,%1);
2568 out_movhi_mr_r (rtx insn
, rtx op
[], int *l
)
2572 rtx base
= XEXP (dest
, 0);
2573 int reg_base
= true_regnum (base
);
2574 int reg_src
= true_regnum (src
);
2575 /* "volatile" forces writing high byte first, even if less efficient,
2576 for correct operation with 16-bit I/O registers. */
2577 int mem_volatile_p
= MEM_VOLATILE_P (dest
);
2582 if (CONSTANT_ADDRESS_P (base
))
2584 if (avr_io_address_p (base
, 2))
2587 return (AS2 (out
,%B0
-0x20,%B1
) CR_TAB
2588 AS2 (out
,%A0
-0x20,%A1
));
2590 return *l
= 4, (AS2 (sts
,%B0
,%B1
) CR_TAB
2595 if (reg_base
== REG_X
)
2597 if (reg_src
== REG_X
)
2599 /* "st X+,r26" and "st -X,r26" are undefined. */
2600 if (!mem_volatile_p
&& reg_unused_after (insn
, src
))
2601 return *l
=4, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2602 AS2 (st
,X
,r26
) CR_TAB
2603 AS2 (adiw
,r26
,1) CR_TAB
2604 AS2 (st
,X
,__tmp_reg__
));
2606 return *l
=5, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2607 AS2 (adiw
,r26
,1) CR_TAB
2608 AS2 (st
,X
,__tmp_reg__
) CR_TAB
2609 AS2 (sbiw
,r26
,1) CR_TAB
2614 if (!mem_volatile_p
&& reg_unused_after (insn
, base
))
2615 return *l
=2, (AS2 (st
,X
+,%A1
) CR_TAB
2618 return *l
=3, (AS2 (adiw
,r26
,1) CR_TAB
2619 AS2 (st
,X
,%B1
) CR_TAB
2624 return *l
=2, (AS2 (std
,%0+1,%B1
) CR_TAB
2627 else if (GET_CODE (base
) == PLUS
)
2629 int disp
= INTVAL (XEXP (base
, 1));
2630 reg_base
= REGNO (XEXP (base
, 0));
2631 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
2633 if (reg_base
!= REG_Y
)
2634 fatal_insn ("incorrect insn:",insn
);
2636 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2637 return *l
= 4, (AS2 (adiw
,r28
,%o0
-62) CR_TAB
2638 AS2 (std
,Y
+63,%B1
) CR_TAB
2639 AS2 (std
,Y
+62,%A1
) CR_TAB
2640 AS2 (sbiw
,r28
,%o0
-62));
2642 return *l
= 6, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2643 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2644 AS2 (std
,Y
+1,%B1
) CR_TAB
2645 AS2 (st
,Y
,%A1
) CR_TAB
2646 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2647 AS2 (sbci
,r29
,hi8(%o0
)));
2649 if (reg_base
== REG_X
)
2652 if (reg_src
== REG_X
)
2655 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2656 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2657 AS2 (adiw
,r26
,%o0
+1) CR_TAB
2658 AS2 (st
,X
,__zero_reg__
) CR_TAB
2659 AS2 (st
,-X
,__tmp_reg__
) CR_TAB
2660 AS1 (clr
,__zero_reg__
) CR_TAB
2661 AS2 (sbiw
,r26
,%o0
));
2664 return (AS2 (adiw
,r26
,%o0
+1) CR_TAB
2665 AS2 (st
,X
,%B1
) CR_TAB
2666 AS2 (st
,-X
,%A1
) CR_TAB
2667 AS2 (sbiw
,r26
,%o0
));
2669 return *l
=2, (AS2 (std
,%B0
,%B1
) CR_TAB
2672 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2673 return *l
=2, (AS2 (st
,%0,%B1
) CR_TAB
2675 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2679 if (REGNO (XEXP (base
, 0)) == REG_X
)
2682 return (AS2 (adiw
,r26
,1) CR_TAB
2683 AS2 (st
,X
,%B1
) CR_TAB
2684 AS2 (st
,-X
,%A1
) CR_TAB
2690 return (AS2 (std
,%p0
+1,%B1
) CR_TAB
2691 AS2 (st
,%p0
,%A1
) CR_TAB
2697 return (AS2 (st
,%0,%A1
) CR_TAB
2700 fatal_insn ("unknown move insn:",insn
);
2704 /* Return 1 if frame pointer for current function required. */
2707 frame_pointer_required_p (void)
2709 return (current_function_calls_alloca
2710 || current_function_args_info
.nregs
== 0
2711 || get_frame_size () > 0);
2714 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2717 compare_condition (rtx insn
)
2719 rtx next
= next_real_insn (insn
);
2720 RTX_CODE cond
= UNKNOWN
;
2721 if (next
&& GET_CODE (next
) == JUMP_INSN
)
2723 rtx pat
= PATTERN (next
);
2724 rtx src
= SET_SRC (pat
);
2725 rtx t
= XEXP (src
, 0);
2726 cond
= GET_CODE (t
);
2731 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2734 compare_sign_p (rtx insn
)
2736 RTX_CODE cond
= compare_condition (insn
);
2737 return (cond
== GE
|| cond
== LT
);
2740 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2741 that needs to be swapped (GT, GTU, LE, LEU). */
2744 compare_diff_p (rtx insn
)
2746 RTX_CODE cond
= compare_condition (insn
);
2747 return (cond
== GT
|| cond
== GTU
|| cond
== LE
|| cond
== LEU
) ? cond
: 0;
2750 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2753 compare_eq_p (rtx insn
)
2755 RTX_CODE cond
= compare_condition (insn
);
2756 return (cond
== EQ
|| cond
== NE
);
2760 /* Output test instruction for HImode. */
2763 out_tsthi (rtx insn
, int *l
)
2765 if (compare_sign_p (insn
))
2768 return AS1 (tst
,%B0
);
2770 if (reg_unused_after (insn
, SET_SRC (PATTERN (insn
)))
2771 && compare_eq_p (insn
))
2773 /* Faster than sbiw if we can clobber the operand. */
2775 return AS2 (or,%A0
,%B0
);
2777 if (test_hard_reg_class (ADDW_REGS
, SET_SRC (PATTERN (insn
))))
2780 return AS2 (sbiw
,%0,0);
2783 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2784 AS2 (cpc
,%B0
,__zero_reg__
));
2788 /* Output test instruction for SImode. */
2791 out_tstsi (rtx insn
, int *l
)
2793 if (compare_sign_p (insn
))
2796 return AS1 (tst
,%D0
);
2798 if (test_hard_reg_class (ADDW_REGS
, SET_SRC (PATTERN (insn
))))
2801 return (AS2 (sbiw
,%A0
,0) CR_TAB
2802 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2803 AS2 (cpc
,%D0
,__zero_reg__
));
2806 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2807 AS2 (cpc
,%B0
,__zero_reg__
) CR_TAB
2808 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2809 AS2 (cpc
,%D0
,__zero_reg__
));
2813 /* Generate asm equivalent for various shifts.
2814 Shift count is a CONST_INT, MEM or REG.
2815 This only handles cases that are not already
2816 carefully hand-optimized in ?sh??i3_out. */
2819 out_shift_with_cnt (const char *template, rtx insn
, rtx operands
[],
2820 int *len
, int t_len
)
2824 int second_label
= 1;
2825 int saved_in_tmp
= 0;
2826 int use_zero_reg
= 0;
2828 op
[0] = operands
[0];
2829 op
[1] = operands
[1];
2830 op
[2] = operands
[2];
2831 op
[3] = operands
[3];
2837 if (GET_CODE (operands
[2]) == CONST_INT
)
2839 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
2840 int count
= INTVAL (operands
[2]);
2841 int max_len
= 10; /* If larger than this, always use a loop. */
2850 if (count
< 8 && !scratch
)
2854 max_len
= t_len
+ (scratch
? 3 : (use_zero_reg
? 4 : 5));
2856 if (t_len
* count
<= max_len
)
2858 /* Output shifts inline with no loop - faster. */
2860 *len
= t_len
* count
;
2864 output_asm_insn (template, op
);
2873 strcat (str
, AS2 (ldi
,%3,%2));
2875 else if (use_zero_reg
)
2877 /* Hack to save one word: use __zero_reg__ as loop counter.
2878 Set one bit, then shift in a loop until it is 0 again. */
2880 op
[3] = zero_reg_rtx
;
2884 strcat (str
, ("set" CR_TAB
2885 AS2 (bld
,%3,%2-1)));
2889 /* No scratch register available, use one from LD_REGS (saved in
2890 __tmp_reg__) that doesn't overlap with registers to shift. */
2892 op
[3] = gen_rtx_REG (QImode
,
2893 ((true_regnum (operands
[0]) - 1) & 15) + 16);
2894 op
[4] = tmp_reg_rtx
;
2898 *len
= 3; /* Includes "mov %3,%4" after the loop. */
2900 strcat (str
, (AS2 (mov
,%4,%3) CR_TAB
2906 else if (GET_CODE (operands
[2]) == MEM
)
2910 op
[3] = op_mov
[0] = tmp_reg_rtx
;
2914 out_movqi_r_mr (insn
, op_mov
, len
);
2916 output_asm_insn (out_movqi_r_mr (insn
, op_mov
, NULL
), op_mov
);
2918 else if (register_operand (operands
[2], QImode
))
2920 if (reg_unused_after (insn
, operands
[2]))
2924 op
[3] = tmp_reg_rtx
;
2926 strcat (str
, (AS2 (mov
,%3,%2) CR_TAB
));
2930 fatal_insn ("bad shift insn:", insn
);
2937 strcat (str
, AS1 (rjmp
,2f
));
2941 *len
+= t_len
+ 2; /* template + dec + brXX */
2944 strcat (str
, "\n1:\t");
2945 strcat (str
, template);
2946 strcat (str
, second_label
? "\n2:\t" : "\n\t");
2947 strcat (str
, use_zero_reg
? AS1 (lsr
,%3) : AS1 (dec
,%3));
2948 strcat (str
, CR_TAB
);
2949 strcat (str
, second_label
? AS1 (brpl
,1b
) : AS1 (brne
,1b
));
2951 strcat (str
, (CR_TAB
AS2 (mov
,%3,%4)));
2952 output_asm_insn (str
, op
);
2957 /* 8bit shift left ((char)x << i) */
2960 ashlqi3_out (rtx insn
, rtx operands
[], int *len
)
2962 if (GET_CODE (operands
[2]) == CONST_INT
)
2969 switch (INTVAL (operands
[2]))
2972 if (INTVAL (operands
[2]) < 8)
2976 return AS1 (clr
,%0);
2980 return AS1 (lsl
,%0);
2984 return (AS1 (lsl
,%0) CR_TAB
2989 return (AS1 (lsl
,%0) CR_TAB
2994 if (test_hard_reg_class (LD_REGS
, operands
[0]))
2997 return (AS1 (swap
,%0) CR_TAB
2998 AS2 (andi
,%0,0xf0));
3001 return (AS1 (lsl
,%0) CR_TAB
3007 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3010 return (AS1 (swap
,%0) CR_TAB
3012 AS2 (andi
,%0,0xe0));
3015 return (AS1 (lsl
,%0) CR_TAB
3022 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3025 return (AS1 (swap
,%0) CR_TAB
3028 AS2 (andi
,%0,0xc0));
3031 return (AS1 (lsl
,%0) CR_TAB
3040 return (AS1 (ror
,%0) CR_TAB
3045 else if (CONSTANT_P (operands
[2]))
3046 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3048 out_shift_with_cnt (AS1 (lsl
,%0),
3049 insn
, operands
, len
, 1);
3054 /* 16bit shift left ((short)x << i) */
3057 ashlhi3_out (rtx insn
, rtx operands
[], int *len
)
3059 if (GET_CODE (operands
[2]) == CONST_INT
)
3061 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3062 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3069 switch (INTVAL (operands
[2]))
3072 if (INTVAL (operands
[2]) < 16)
3076 return (AS1 (clr
,%B0
) CR_TAB
3080 if (optimize_size
&& scratch
)
3085 return (AS1 (swap
,%A0
) CR_TAB
3086 AS1 (swap
,%B0
) CR_TAB
3087 AS2 (andi
,%B0
,0xf0) CR_TAB
3088 AS2 (eor
,%B0
,%A0
) CR_TAB
3089 AS2 (andi
,%A0
,0xf0) CR_TAB
3095 return (AS1 (swap
,%A0
) CR_TAB
3096 AS1 (swap
,%B0
) CR_TAB
3097 AS2 (ldi
,%3,0xf0) CR_TAB
3098 AS2 (and,%B0
,%3) CR_TAB
3099 AS2 (eor
,%B0
,%A0
) CR_TAB
3100 AS2 (and,%A0
,%3) CR_TAB
3103 break; /* optimize_size ? 6 : 8 */
3107 break; /* scratch ? 5 : 6 */
3111 return (AS1 (lsl
,%A0
) CR_TAB
3112 AS1 (rol
,%B0
) CR_TAB
3113 AS1 (swap
,%A0
) CR_TAB
3114 AS1 (swap
,%B0
) CR_TAB
3115 AS2 (andi
,%B0
,0xf0) CR_TAB
3116 AS2 (eor
,%B0
,%A0
) CR_TAB
3117 AS2 (andi
,%A0
,0xf0) CR_TAB
3123 return (AS1 (lsl
,%A0
) CR_TAB
3124 AS1 (rol
,%B0
) CR_TAB
3125 AS1 (swap
,%A0
) CR_TAB
3126 AS1 (swap
,%B0
) CR_TAB
3127 AS2 (ldi
,%3,0xf0) CR_TAB
3128 AS2 (and,%B0
,%3) CR_TAB
3129 AS2 (eor
,%B0
,%A0
) CR_TAB
3130 AS2 (and,%A0
,%3) CR_TAB
3137 break; /* scratch ? 5 : 6 */
3139 return (AS1 (clr
,__tmp_reg__
) CR_TAB
3140 AS1 (lsr
,%B0
) CR_TAB
3141 AS1 (ror
,%A0
) CR_TAB
3142 AS1 (ror
,__tmp_reg__
) CR_TAB
3143 AS1 (lsr
,%B0
) CR_TAB
3144 AS1 (ror
,%A0
) CR_TAB
3145 AS1 (ror
,__tmp_reg__
) CR_TAB
3146 AS2 (mov
,%B0
,%A0
) CR_TAB
3147 AS2 (mov
,%A0
,__tmp_reg__
));
3151 return (AS1 (lsr
,%B0
) CR_TAB
3152 AS2 (mov
,%B0
,%A0
) CR_TAB
3153 AS1 (clr
,%A0
) CR_TAB
3154 AS1 (ror
,%B0
) CR_TAB
3158 return *len
= 2, (AS2 (mov
,%B0
,%A1
) CR_TAB
3163 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3164 AS1 (clr
,%A0
) CR_TAB
3169 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3170 AS1 (clr
,%A0
) CR_TAB
3171 AS1 (lsl
,%B0
) CR_TAB
3176 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3177 AS1 (clr
,%A0
) CR_TAB
3178 AS1 (lsl
,%B0
) CR_TAB
3179 AS1 (lsl
,%B0
) CR_TAB
3186 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3187 AS1 (clr
,%A0
) CR_TAB
3188 AS1 (swap
,%B0
) CR_TAB
3189 AS2 (andi
,%B0
,0xf0));
3194 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3195 AS1 (clr
,%A0
) CR_TAB
3196 AS1 (swap
,%B0
) CR_TAB
3197 AS2 (ldi
,%3,0xf0) CR_TAB
3201 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3202 AS1 (clr
,%A0
) CR_TAB
3203 AS1 (lsl
,%B0
) CR_TAB
3204 AS1 (lsl
,%B0
) CR_TAB
3205 AS1 (lsl
,%B0
) CR_TAB
3212 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3213 AS1 (clr
,%A0
) CR_TAB
3214 AS1 (swap
,%B0
) CR_TAB
3215 AS1 (lsl
,%B0
) CR_TAB
3216 AS2 (andi
,%B0
,0xe0));
3218 if (AVR_HAVE_MUL
&& scratch
)
3221 return (AS2 (ldi
,%3,0x20) CR_TAB
3222 AS2 (mul
,%A0
,%3) CR_TAB
3223 AS2 (mov
,%B0
,r0
) CR_TAB
3224 AS1 (clr
,%A0
) CR_TAB
3225 AS1 (clr
,__zero_reg__
));
3227 if (optimize_size
&& scratch
)
3232 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3233 AS1 (clr
,%A0
) CR_TAB
3234 AS1 (swap
,%B0
) CR_TAB
3235 AS1 (lsl
,%B0
) CR_TAB
3236 AS2 (ldi
,%3,0xe0) CR_TAB
3242 return ("set" CR_TAB
3243 AS2 (bld
,r1
,5) CR_TAB
3244 AS2 (mul
,%A0
,r1
) CR_TAB
3245 AS2 (mov
,%B0
,r0
) CR_TAB
3246 AS1 (clr
,%A0
) CR_TAB
3247 AS1 (clr
,__zero_reg__
));
3250 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3251 AS1 (clr
,%A0
) CR_TAB
3252 AS1 (lsl
,%B0
) CR_TAB
3253 AS1 (lsl
,%B0
) CR_TAB
3254 AS1 (lsl
,%B0
) CR_TAB
3255 AS1 (lsl
,%B0
) CR_TAB
3259 if (AVR_HAVE_MUL
&& ldi_ok
)
3262 return (AS2 (ldi
,%B0
,0x40) CR_TAB
3263 AS2 (mul
,%A0
,%B0
) CR_TAB
3264 AS2 (mov
,%B0
,r0
) CR_TAB
3265 AS1 (clr
,%A0
) CR_TAB
3266 AS1 (clr
,__zero_reg__
));
3268 if (AVR_HAVE_MUL
&& scratch
)
3271 return (AS2 (ldi
,%3,0x40) CR_TAB
3272 AS2 (mul
,%A0
,%3) CR_TAB
3273 AS2 (mov
,%B0
,r0
) CR_TAB
3274 AS1 (clr
,%A0
) CR_TAB
3275 AS1 (clr
,__zero_reg__
));
3277 if (optimize_size
&& ldi_ok
)
3280 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3281 AS2 (ldi
,%A0
,6) "\n1:\t"
3282 AS1 (lsl
,%B0
) CR_TAB
3283 AS1 (dec
,%A0
) CR_TAB
3286 if (optimize_size
&& scratch
)
3289 return (AS1 (clr
,%B0
) CR_TAB
3290 AS1 (lsr
,%A0
) CR_TAB
3291 AS1 (ror
,%B0
) CR_TAB
3292 AS1 (lsr
,%A0
) CR_TAB
3293 AS1 (ror
,%B0
) CR_TAB
3298 return (AS1 (clr
,%B0
) CR_TAB
3299 AS1 (lsr
,%A0
) CR_TAB
3300 AS1 (ror
,%B0
) CR_TAB
3305 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3307 insn
, operands
, len
, 2);
3312 /* 32bit shift left ((long)x << i) */
3315 ashlsi3_out (rtx insn
, rtx operands
[], int *len
)
3317 if (GET_CODE (operands
[2]) == CONST_INT
)
3325 switch (INTVAL (operands
[2]))
3328 if (INTVAL (operands
[2]) < 32)
3332 return *len
= 3, (AS1 (clr
,%D0
) CR_TAB
3333 AS1 (clr
,%C0
) CR_TAB
3334 AS2 (movw
,%A0
,%C0
));
3336 return (AS1 (clr
,%D0
) CR_TAB
3337 AS1 (clr
,%C0
) CR_TAB
3338 AS1 (clr
,%B0
) CR_TAB
3343 int reg0
= true_regnum (operands
[0]);
3344 int reg1
= true_regnum (operands
[1]);
3347 return (AS2 (mov
,%D0
,%C1
) CR_TAB
3348 AS2 (mov
,%C0
,%B1
) CR_TAB
3349 AS2 (mov
,%B0
,%A1
) CR_TAB
3352 return (AS1 (clr
,%A0
) CR_TAB
3353 AS2 (mov
,%B0
,%A1
) CR_TAB
3354 AS2 (mov
,%C0
,%B1
) CR_TAB
3360 int reg0
= true_regnum (operands
[0]);
3361 int reg1
= true_regnum (operands
[1]);
3362 if (reg0
+ 2 == reg1
)
3363 return *len
= 2, (AS1 (clr
,%B0
) CR_TAB
3366 return *len
= 3, (AS2 (movw
,%C0
,%A1
) CR_TAB
3367 AS1 (clr
,%B0
) CR_TAB
3370 return *len
= 4, (AS2 (mov
,%C0
,%A1
) CR_TAB
3371 AS2 (mov
,%D0
,%B1
) CR_TAB
3372 AS1 (clr
,%B0
) CR_TAB
3378 return (AS2 (mov
,%D0
,%A1
) CR_TAB
3379 AS1 (clr
,%C0
) CR_TAB
3380 AS1 (clr
,%B0
) CR_TAB
3385 return (AS1 (clr
,%D0
) CR_TAB
3386 AS1 (lsr
,%A0
) CR_TAB
3387 AS1 (ror
,%D0
) CR_TAB
3388 AS1 (clr
,%C0
) CR_TAB
3389 AS1 (clr
,%B0
) CR_TAB
3394 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3395 AS1 (rol
,%B0
) CR_TAB
3396 AS1 (rol
,%C0
) CR_TAB
3398 insn
, operands
, len
, 4);
3402 /* 8bit arithmetic shift right ((signed char)x >> i) */
3405 ashrqi3_out (rtx insn
, rtx operands
[], int *len
)
3407 if (GET_CODE (operands
[2]) == CONST_INT
)
3414 switch (INTVAL (operands
[2]))
3418 return AS1 (asr
,%0);
3422 return (AS1 (asr
,%0) CR_TAB
3427 return (AS1 (asr
,%0) CR_TAB
3433 return (AS1 (asr
,%0) CR_TAB
3440 return (AS1 (asr
,%0) CR_TAB
3448 return (AS2 (bst
,%0,6) CR_TAB
3450 AS2 (sbc
,%0,%0) CR_TAB
3454 if (INTVAL (operands
[2]) < 8)
3461 return (AS1 (lsl
,%0) CR_TAB
3465 else if (CONSTANT_P (operands
[2]))
3466 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3468 out_shift_with_cnt (AS1 (asr
,%0),
3469 insn
, operands
, len
, 1);
3474 /* 16bit arithmetic shift right ((signed short)x >> i) */
3477 ashrhi3_out (rtx insn
, rtx operands
[], int *len
)
3479 if (GET_CODE (operands
[2]) == CONST_INT
)
3481 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3482 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3489 switch (INTVAL (operands
[2]))
3493 /* XXX try to optimize this too? */
3498 break; /* scratch ? 5 : 6 */
3500 return (AS2 (mov
,__tmp_reg__
,%A0
) CR_TAB
3501 AS2 (mov
,%A0
,%B0
) CR_TAB
3502 AS1 (lsl
,__tmp_reg__
) CR_TAB
3503 AS1 (rol
,%A0
) CR_TAB
3504 AS2 (sbc
,%B0
,%B0
) CR_TAB
3505 AS1 (lsl
,__tmp_reg__
) CR_TAB
3506 AS1 (rol
,%A0
) CR_TAB
3511 return (AS1 (lsl
,%A0
) CR_TAB
3512 AS2 (mov
,%A0
,%B0
) CR_TAB
3513 AS1 (rol
,%A0
) CR_TAB
3518 int reg0
= true_regnum (operands
[0]);
3519 int reg1
= true_regnum (operands
[1]);
3522 return *len
= 3, (AS2 (mov
,%A0
,%B0
) CR_TAB
3523 AS1 (lsl
,%B0
) CR_TAB
3526 return *len
= 4, (AS2 (mov
,%A0
,%B1
) CR_TAB
3527 AS1 (clr
,%B0
) CR_TAB
3528 AS2 (sbrc
,%A0
,7) CR_TAB
3534 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3535 AS1 (lsl
,%B0
) CR_TAB
3536 AS2 (sbc
,%B0
,%B0
) CR_TAB
3541 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3542 AS1 (lsl
,%B0
) CR_TAB
3543 AS2 (sbc
,%B0
,%B0
) CR_TAB
3544 AS1 (asr
,%A0
) CR_TAB
3548 if (AVR_HAVE_MUL
&& ldi_ok
)
3551 return (AS2 (ldi
,%A0
,0x20) CR_TAB
3552 AS2 (muls
,%B0
,%A0
) CR_TAB
3553 AS2 (mov
,%A0
,r1
) CR_TAB
3554 AS2 (sbc
,%B0
,%B0
) CR_TAB
3555 AS1 (clr
,__zero_reg__
));
3557 if (optimize_size
&& scratch
)
3560 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3561 AS1 (lsl
,%B0
) CR_TAB
3562 AS2 (sbc
,%B0
,%B0
) CR_TAB
3563 AS1 (asr
,%A0
) CR_TAB
3564 AS1 (asr
,%A0
) CR_TAB
3568 if (AVR_HAVE_MUL
&& ldi_ok
)
3571 return (AS2 (ldi
,%A0
,0x10) CR_TAB
3572 AS2 (muls
,%B0
,%A0
) CR_TAB
3573 AS2 (mov
,%A0
,r1
) CR_TAB
3574 AS2 (sbc
,%B0
,%B0
) CR_TAB
3575 AS1 (clr
,__zero_reg__
));
3577 if (optimize_size
&& scratch
)
3580 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3581 AS1 (lsl
,%B0
) CR_TAB
3582 AS2 (sbc
,%B0
,%B0
) CR_TAB
3583 AS1 (asr
,%A0
) CR_TAB
3584 AS1 (asr
,%A0
) CR_TAB
3585 AS1 (asr
,%A0
) CR_TAB
3589 if (AVR_HAVE_MUL
&& ldi_ok
)
3592 return (AS2 (ldi
,%A0
,0x08) CR_TAB
3593 AS2 (muls
,%B0
,%A0
) CR_TAB
3594 AS2 (mov
,%A0
,r1
) CR_TAB
3595 AS2 (sbc
,%B0
,%B0
) CR_TAB
3596 AS1 (clr
,__zero_reg__
));
3599 break; /* scratch ? 5 : 7 */
3601 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3602 AS1 (lsl
,%B0
) CR_TAB
3603 AS2 (sbc
,%B0
,%B0
) CR_TAB
3604 AS1 (asr
,%A0
) CR_TAB
3605 AS1 (asr
,%A0
) CR_TAB
3606 AS1 (asr
,%A0
) CR_TAB
3607 AS1 (asr
,%A0
) CR_TAB
3612 return (AS1 (lsl
,%B0
) CR_TAB
3613 AS2 (sbc
,%A0
,%A0
) CR_TAB
3614 AS1 (lsl
,%B0
) CR_TAB
3615 AS2 (mov
,%B0
,%A0
) CR_TAB
3619 if (INTVAL (operands
[2]) < 16)
3625 return *len
= 3, (AS1 (lsl
,%B0
) CR_TAB
3626 AS2 (sbc
,%A0
,%A0
) CR_TAB
3631 out_shift_with_cnt ((AS1 (asr
,%B0
) CR_TAB
3633 insn
, operands
, len
, 2);
3638 /* 32bit arithmetic shift right ((signed long)x >> i) */
3641 ashrsi3_out (rtx insn
, rtx operands
[], int *len
)
3643 if (GET_CODE (operands
[2]) == CONST_INT
)
3651 switch (INTVAL (operands
[2]))
3655 int reg0
= true_regnum (operands
[0]);
3656 int reg1
= true_regnum (operands
[1]);
3659 return (AS2 (mov
,%A0
,%B1
) CR_TAB
3660 AS2 (mov
,%B0
,%C1
) CR_TAB
3661 AS2 (mov
,%C0
,%D1
) CR_TAB
3662 AS1 (clr
,%D0
) CR_TAB
3663 AS2 (sbrc
,%C0
,7) CR_TAB
3666 return (AS1 (clr
,%D0
) CR_TAB
3667 AS2 (sbrc
,%D1
,7) CR_TAB
3668 AS1 (dec
,%D0
) CR_TAB
3669 AS2 (mov
,%C0
,%D1
) CR_TAB
3670 AS2 (mov
,%B0
,%C1
) CR_TAB
3676 int reg0
= true_regnum (operands
[0]);
3677 int reg1
= true_regnum (operands
[1]);
3679 if (reg0
== reg1
+ 2)
3680 return *len
= 4, (AS1 (clr
,%D0
) CR_TAB
3681 AS2 (sbrc
,%B0
,7) CR_TAB
3682 AS1 (com
,%D0
) CR_TAB
3685 return *len
= 5, (AS2 (movw
,%A0
,%C1
) CR_TAB
3686 AS1 (clr
,%D0
) CR_TAB
3687 AS2 (sbrc
,%B0
,7) CR_TAB
3688 AS1 (com
,%D0
) CR_TAB
3691 return *len
= 6, (AS2 (mov
,%B0
,%D1
) CR_TAB
3692 AS2 (mov
,%A0
,%C1
) CR_TAB
3693 AS1 (clr
,%D0
) CR_TAB
3694 AS2 (sbrc
,%B0
,7) CR_TAB
3695 AS1 (com
,%D0
) CR_TAB
3700 return *len
= 6, (AS2 (mov
,%A0
,%D1
) CR_TAB
3701 AS1 (clr
,%D0
) CR_TAB
3702 AS2 (sbrc
,%A0
,7) CR_TAB
3703 AS1 (com
,%D0
) CR_TAB
3704 AS2 (mov
,%B0
,%D0
) CR_TAB
3708 if (INTVAL (operands
[2]) < 32)
3715 return *len
= 4, (AS1 (lsl
,%D0
) CR_TAB
3716 AS2 (sbc
,%A0
,%A0
) CR_TAB
3717 AS2 (mov
,%B0
,%A0
) CR_TAB
3718 AS2 (movw
,%C0
,%A0
));
3720 return *len
= 5, (AS1 (lsl
,%D0
) CR_TAB
3721 AS2 (sbc
,%A0
,%A0
) CR_TAB
3722 AS2 (mov
,%B0
,%A0
) CR_TAB
3723 AS2 (mov
,%C0
,%A0
) CR_TAB
3728 out_shift_with_cnt ((AS1 (asr
,%D0
) CR_TAB
3729 AS1 (ror
,%C0
) CR_TAB
3730 AS1 (ror
,%B0
) CR_TAB
3732 insn
, operands
, len
, 4);
3736 /* 8bit logic shift right ((unsigned char)x >> i) */
3739 lshrqi3_out (rtx insn
, rtx operands
[], int *len
)
3741 if (GET_CODE (operands
[2]) == CONST_INT
)
3748 switch (INTVAL (operands
[2]))
3751 if (INTVAL (operands
[2]) < 8)
3755 return AS1 (clr
,%0);
3759 return AS1 (lsr
,%0);
3763 return (AS1 (lsr
,%0) CR_TAB
3767 return (AS1 (lsr
,%0) CR_TAB
3772 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3775 return (AS1 (swap
,%0) CR_TAB
3776 AS2 (andi
,%0,0x0f));
3779 return (AS1 (lsr
,%0) CR_TAB
3785 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3788 return (AS1 (swap
,%0) CR_TAB
3793 return (AS1 (lsr
,%0) CR_TAB
3800 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3803 return (AS1 (swap
,%0) CR_TAB
3809 return (AS1 (lsr
,%0) CR_TAB
3818 return (AS1 (rol
,%0) CR_TAB
3823 else if (CONSTANT_P (operands
[2]))
3824 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3826 out_shift_with_cnt (AS1 (lsr
,%0),
3827 insn
, operands
, len
, 1);
3831 /* 16bit logic shift right ((unsigned short)x >> i) */
3834 lshrhi3_out (rtx insn
, rtx operands
[], int *len
)
3836 if (GET_CODE (operands
[2]) == CONST_INT
)
3838 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3839 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3846 switch (INTVAL (operands
[2]))
3849 if (INTVAL (operands
[2]) < 16)
3853 return (AS1 (clr
,%B0
) CR_TAB
3857 if (optimize_size
&& scratch
)
3862 return (AS1 (swap
,%B0
) CR_TAB
3863 AS1 (swap
,%A0
) CR_TAB
3864 AS2 (andi
,%A0
,0x0f) CR_TAB
3865 AS2 (eor
,%A0
,%B0
) CR_TAB
3866 AS2 (andi
,%B0
,0x0f) CR_TAB
3872 return (AS1 (swap
,%B0
) CR_TAB
3873 AS1 (swap
,%A0
) CR_TAB
3874 AS2 (ldi
,%3,0x0f) CR_TAB
3875 AS2 (and,%A0
,%3) CR_TAB
3876 AS2 (eor
,%A0
,%B0
) CR_TAB
3877 AS2 (and,%B0
,%3) CR_TAB
3880 break; /* optimize_size ? 6 : 8 */
3884 break; /* scratch ? 5 : 6 */
3888 return (AS1 (lsr
,%B0
) CR_TAB
3889 AS1 (ror
,%A0
) CR_TAB
3890 AS1 (swap
,%B0
) CR_TAB
3891 AS1 (swap
,%A0
) CR_TAB
3892 AS2 (andi
,%A0
,0x0f) CR_TAB
3893 AS2 (eor
,%A0
,%B0
) CR_TAB
3894 AS2 (andi
,%B0
,0x0f) CR_TAB
3900 return (AS1 (lsr
,%B0
) CR_TAB
3901 AS1 (ror
,%A0
) CR_TAB
3902 AS1 (swap
,%B0
) CR_TAB
3903 AS1 (swap
,%A0
) CR_TAB
3904 AS2 (ldi
,%3,0x0f) CR_TAB
3905 AS2 (and,%A0
,%3) CR_TAB
3906 AS2 (eor
,%A0
,%B0
) CR_TAB
3907 AS2 (and,%B0
,%3) CR_TAB
3914 break; /* scratch ? 5 : 6 */
3916 return (AS1 (clr
,__tmp_reg__
) CR_TAB
3917 AS1 (lsl
,%A0
) CR_TAB
3918 AS1 (rol
,%B0
) CR_TAB
3919 AS1 (rol
,__tmp_reg__
) CR_TAB
3920 AS1 (lsl
,%A0
) CR_TAB
3921 AS1 (rol
,%B0
) CR_TAB
3922 AS1 (rol
,__tmp_reg__
) CR_TAB
3923 AS2 (mov
,%A0
,%B0
) CR_TAB
3924 AS2 (mov
,%B0
,__tmp_reg__
));
3928 return (AS1 (lsl
,%A0
) CR_TAB
3929 AS2 (mov
,%A0
,%B0
) CR_TAB
3930 AS1 (rol
,%A0
) CR_TAB
3931 AS2 (sbc
,%B0
,%B0
) CR_TAB
3935 return *len
= 2, (AS2 (mov
,%A0
,%B1
) CR_TAB
3940 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3941 AS1 (clr
,%B0
) CR_TAB
3946 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3947 AS1 (clr
,%B0
) CR_TAB
3948 AS1 (lsr
,%A0
) CR_TAB
3953 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3954 AS1 (clr
,%B0
) CR_TAB
3955 AS1 (lsr
,%A0
) CR_TAB
3956 AS1 (lsr
,%A0
) CR_TAB
3963 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3964 AS1 (clr
,%B0
) CR_TAB
3965 AS1 (swap
,%A0
) CR_TAB
3966 AS2 (andi
,%A0
,0x0f));
3971 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3972 AS1 (clr
,%B0
) CR_TAB
3973 AS1 (swap
,%A0
) CR_TAB
3974 AS2 (ldi
,%3,0x0f) CR_TAB
3978 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3979 AS1 (clr
,%B0
) CR_TAB
3980 AS1 (lsr
,%A0
) CR_TAB
3981 AS1 (lsr
,%A0
) CR_TAB
3982 AS1 (lsr
,%A0
) CR_TAB
3989 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3990 AS1 (clr
,%B0
) CR_TAB
3991 AS1 (swap
,%A0
) CR_TAB
3992 AS1 (lsr
,%A0
) CR_TAB
3993 AS2 (andi
,%A0
,0x07));
3995 if (AVR_HAVE_MUL
&& scratch
)
3998 return (AS2 (ldi
,%3,0x08) CR_TAB
3999 AS2 (mul
,%B0
,%3) CR_TAB
4000 AS2 (mov
,%A0
,r1
) CR_TAB
4001 AS1 (clr
,%B0
) CR_TAB
4002 AS1 (clr
,__zero_reg__
));
4004 if (optimize_size
&& scratch
)
4009 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4010 AS1 (clr
,%B0
) CR_TAB
4011 AS1 (swap
,%A0
) CR_TAB
4012 AS1 (lsr
,%A0
) CR_TAB
4013 AS2 (ldi
,%3,0x07) CR_TAB
4019 return ("set" CR_TAB
4020 AS2 (bld
,r1
,3) CR_TAB
4021 AS2 (mul
,%B0
,r1
) CR_TAB
4022 AS2 (mov
,%A0
,r1
) CR_TAB
4023 AS1 (clr
,%B0
) CR_TAB
4024 AS1 (clr
,__zero_reg__
));
4027 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4028 AS1 (clr
,%B0
) CR_TAB
4029 AS1 (lsr
,%A0
) CR_TAB
4030 AS1 (lsr
,%A0
) CR_TAB
4031 AS1 (lsr
,%A0
) CR_TAB
4032 AS1 (lsr
,%A0
) CR_TAB
4036 if (AVR_HAVE_MUL
&& ldi_ok
)
4039 return (AS2 (ldi
,%A0
,0x04) CR_TAB
4040 AS2 (mul
,%B0
,%A0
) CR_TAB
4041 AS2 (mov
,%A0
,r1
) CR_TAB
4042 AS1 (clr
,%B0
) CR_TAB
4043 AS1 (clr
,__zero_reg__
));
4045 if (AVR_HAVE_MUL
&& scratch
)
4048 return (AS2 (ldi
,%3,0x04) CR_TAB
4049 AS2 (mul
,%B0
,%3) CR_TAB
4050 AS2 (mov
,%A0
,r1
) CR_TAB
4051 AS1 (clr
,%B0
) CR_TAB
4052 AS1 (clr
,__zero_reg__
));
4054 if (optimize_size
&& ldi_ok
)
4057 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4058 AS2 (ldi
,%B0
,6) "\n1:\t"
4059 AS1 (lsr
,%A0
) CR_TAB
4060 AS1 (dec
,%B0
) CR_TAB
4063 if (optimize_size
&& scratch
)
4066 return (AS1 (clr
,%A0
) CR_TAB
4067 AS1 (lsl
,%B0
) CR_TAB
4068 AS1 (rol
,%A0
) CR_TAB
4069 AS1 (lsl
,%B0
) CR_TAB
4070 AS1 (rol
,%A0
) CR_TAB
4075 return (AS1 (clr
,%A0
) CR_TAB
4076 AS1 (lsl
,%B0
) CR_TAB
4077 AS1 (rol
,%A0
) CR_TAB
4082 out_shift_with_cnt ((AS1 (lsr
,%B0
) CR_TAB
4084 insn
, operands
, len
, 2);
4088 /* 32bit logic shift right ((unsigned int)x >> i) */
4091 lshrsi3_out (rtx insn
, rtx operands
[], int *len
)
4093 if (GET_CODE (operands
[2]) == CONST_INT
)
4101 switch (INTVAL (operands
[2]))
4104 if (INTVAL (operands
[2]) < 32)
4108 return *len
= 3, (AS1 (clr
,%D0
) CR_TAB
4109 AS1 (clr
,%C0
) CR_TAB
4110 AS2 (movw
,%A0
,%C0
));
4112 return (AS1 (clr
,%D0
) CR_TAB
4113 AS1 (clr
,%C0
) CR_TAB
4114 AS1 (clr
,%B0
) CR_TAB
4119 int reg0
= true_regnum (operands
[0]);
4120 int reg1
= true_regnum (operands
[1]);
4123 return (AS2 (mov
,%A0
,%B1
) CR_TAB
4124 AS2 (mov
,%B0
,%C1
) CR_TAB
4125 AS2 (mov
,%C0
,%D1
) CR_TAB
4128 return (AS1 (clr
,%D0
) CR_TAB
4129 AS2 (mov
,%C0
,%D1
) CR_TAB
4130 AS2 (mov
,%B0
,%C1
) CR_TAB
4136 int reg0
= true_regnum (operands
[0]);
4137 int reg1
= true_regnum (operands
[1]);
4139 if (reg0
== reg1
+ 2)
4140 return *len
= 2, (AS1 (clr
,%C0
) CR_TAB
4143 return *len
= 3, (AS2 (movw
,%A0
,%C1
) CR_TAB
4144 AS1 (clr
,%C0
) CR_TAB
4147 return *len
= 4, (AS2 (mov
,%B0
,%D1
) CR_TAB
4148 AS2 (mov
,%A0
,%C1
) CR_TAB
4149 AS1 (clr
,%C0
) CR_TAB
4154 return *len
= 4, (AS2 (mov
,%A0
,%D1
) CR_TAB
4155 AS1 (clr
,%B0
) CR_TAB
4156 AS1 (clr
,%C0
) CR_TAB
4161 return (AS1 (clr
,%A0
) CR_TAB
4162 AS2 (sbrc
,%D0
,7) CR_TAB
4163 AS1 (inc
,%A0
) CR_TAB
4164 AS1 (clr
,%B0
) CR_TAB
4165 AS1 (clr
,%C0
) CR_TAB
4170 out_shift_with_cnt ((AS1 (lsr
,%D0
) CR_TAB
4171 AS1 (ror
,%C0
) CR_TAB
4172 AS1 (ror
,%B0
) CR_TAB
4174 insn
, operands
, len
, 4);
4178 /* Modifies the length assigned to instruction INSN
4179 LEN is the initially computed length of the insn. */
4182 adjust_insn_length (rtx insn
, int len
)
4184 rtx patt
= PATTERN (insn
);
4187 if (GET_CODE (patt
) == SET
)
4190 op
[1] = SET_SRC (patt
);
4191 op
[0] = SET_DEST (patt
);
4192 if (general_operand (op
[1], VOIDmode
)
4193 && general_operand (op
[0], VOIDmode
))
4195 switch (GET_MODE (op
[0]))
4198 output_movqi (insn
, op
, &len
);
4201 output_movhi (insn
, op
, &len
);
4205 output_movsisf (insn
, op
, &len
);
4211 else if (op
[0] == cc0_rtx
&& REG_P (op
[1]))
4213 switch (GET_MODE (op
[1]))
4215 case HImode
: out_tsthi (insn
,&len
); break;
4216 case SImode
: out_tstsi (insn
,&len
); break;
4220 else if (GET_CODE (op
[1]) == AND
)
4222 if (GET_CODE (XEXP (op
[1],1)) == CONST_INT
)
4224 HOST_WIDE_INT mask
= INTVAL (XEXP (op
[1],1));
4225 if (GET_MODE (op
[1]) == SImode
)
4226 len
= (((mask
& 0xff) != 0xff)
4227 + ((mask
& 0xff00) != 0xff00)
4228 + ((mask
& 0xff0000L
) != 0xff0000L
)
4229 + ((mask
& 0xff000000L
) != 0xff000000L
));
4230 else if (GET_MODE (op
[1]) == HImode
)
4231 len
= (((mask
& 0xff) != 0xff)
4232 + ((mask
& 0xff00) != 0xff00));
4235 else if (GET_CODE (op
[1]) == IOR
)
4237 if (GET_CODE (XEXP (op
[1],1)) == CONST_INT
)
4239 HOST_WIDE_INT mask
= INTVAL (XEXP (op
[1],1));
4240 if (GET_MODE (op
[1]) == SImode
)
4241 len
= (((mask
& 0xff) != 0)
4242 + ((mask
& 0xff00) != 0)
4243 + ((mask
& 0xff0000L
) != 0)
4244 + ((mask
& 0xff000000L
) != 0));
4245 else if (GET_MODE (op
[1]) == HImode
)
4246 len
= (((mask
& 0xff) != 0)
4247 + ((mask
& 0xff00) != 0));
4251 set
= single_set (insn
);
4256 op
[1] = SET_SRC (set
);
4257 op
[0] = SET_DEST (set
);
4259 if (GET_CODE (patt
) == PARALLEL
4260 && general_operand (op
[1], VOIDmode
)
4261 && general_operand (op
[0], VOIDmode
))
4263 if (XVECLEN (patt
, 0) == 2)
4264 op
[2] = XVECEXP (patt
, 0, 1);
4266 switch (GET_MODE (op
[0]))
4272 output_reload_inhi (insn
, op
, &len
);
4276 output_reload_insisf (insn
, op
, &len
);
4282 else if (GET_CODE (op
[1]) == ASHIFT
4283 || GET_CODE (op
[1]) == ASHIFTRT
4284 || GET_CODE (op
[1]) == LSHIFTRT
)
4288 ops
[1] = XEXP (op
[1],0);
4289 ops
[2] = XEXP (op
[1],1);
4290 switch (GET_CODE (op
[1]))
4293 switch (GET_MODE (op
[0]))
4295 case QImode
: ashlqi3_out (insn
,ops
,&len
); break;
4296 case HImode
: ashlhi3_out (insn
,ops
,&len
); break;
4297 case SImode
: ashlsi3_out (insn
,ops
,&len
); break;
4302 switch (GET_MODE (op
[0]))
4304 case QImode
: ashrqi3_out (insn
,ops
,&len
); break;
4305 case HImode
: ashrhi3_out (insn
,ops
,&len
); break;
4306 case SImode
: ashrsi3_out (insn
,ops
,&len
); break;
4311 switch (GET_MODE (op
[0]))
4313 case QImode
: lshrqi3_out (insn
,ops
,&len
); break;
4314 case HImode
: lshrhi3_out (insn
,ops
,&len
); break;
4315 case SImode
: lshrsi3_out (insn
,ops
,&len
); break;
4327 /* Return nonzero if register REG dead after INSN. */
4330 reg_unused_after (rtx insn
, rtx reg
)
4332 return (dead_or_set_p (insn
, reg
)
4333 || (REG_P(reg
) && _reg_unused_after (insn
, reg
)));
4336 /* Return nonzero if REG is not used after INSN.
4337 We assume REG is a reload reg, and therefore does
4338 not live past labels. It may live past calls or jumps though. */
4341 _reg_unused_after (rtx insn
, rtx reg
)
4346 /* If the reg is set by this instruction, then it is safe for our
4347 case. Disregard the case where this is a store to memory, since
4348 we are checking a register used in the store address. */
4349 set
= single_set (insn
);
4350 if (set
&& GET_CODE (SET_DEST (set
)) != MEM
4351 && reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4354 while ((insn
= NEXT_INSN (insn
)))
4357 code
= GET_CODE (insn
);
4360 /* If this is a label that existed before reload, then the register
4361 if dead here. However, if this is a label added by reorg, then
4362 the register may still be live here. We can't tell the difference,
4363 so we just ignore labels completely. */
4364 if (code
== CODE_LABEL
)
4372 if (code
== JUMP_INSN
)
4375 /* If this is a sequence, we must handle them all at once.
4376 We could have for instance a call that sets the target register,
4377 and an insn in a delay slot that uses the register. In this case,
4378 we must return 0. */
4379 else if (code
== INSN
&& GET_CODE (PATTERN (insn
)) == SEQUENCE
)
4384 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
4386 rtx this_insn
= XVECEXP (PATTERN (insn
), 0, i
);
4387 rtx set
= single_set (this_insn
);
4389 if (GET_CODE (this_insn
) == CALL_INSN
)
4391 else if (GET_CODE (this_insn
) == JUMP_INSN
)
4393 if (INSN_ANNULLED_BRANCH_P (this_insn
))
4398 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4400 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4402 if (GET_CODE (SET_DEST (set
)) != MEM
)
4408 && reg_overlap_mentioned_p (reg
, PATTERN (this_insn
)))
4413 else if (code
== JUMP_INSN
)
4417 if (code
== CALL_INSN
)
4420 for (tem
= CALL_INSN_FUNCTION_USAGE (insn
); tem
; tem
= XEXP (tem
, 1))
4421 if (GET_CODE (XEXP (tem
, 0)) == USE
4422 && REG_P (XEXP (XEXP (tem
, 0), 0))
4423 && reg_overlap_mentioned_p (reg
, XEXP (XEXP (tem
, 0), 0)))
4425 if (call_used_regs
[REGNO (reg
)])
4429 set
= single_set (insn
);
4431 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4433 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4434 return GET_CODE (SET_DEST (set
)) != MEM
;
4435 if (set
== 0 && reg_overlap_mentioned_p (reg
, PATTERN (insn
)))
4441 /* Target hook for assembling integer objects. The AVR version needs
4442 special handling for references to certain labels. */
4445 avr_assemble_integer (rtx x
, unsigned int size
, int aligned_p
)
4447 if (size
== POINTER_SIZE
/ BITS_PER_UNIT
&& aligned_p
4448 && ((GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_FUNCTION_P (x
))
4449 || GET_CODE (x
) == LABEL_REF
))
4451 fputs ("\t.word\tpm(", asm_out_file
);
4452 output_addr_const (asm_out_file
, x
);
4453 fputs (")\n", asm_out_file
);
4456 return default_assemble_integer (x
, size
, aligned_p
);
4459 /* The routine used to output NUL terminated strings. We use a special
4460 version of this for most svr4 targets because doing so makes the
4461 generated assembly code more compact (and thus faster to assemble)
4462 as well as more readable, especially for targets like the i386
4463 (where the only alternative is to output character sequences as
4464 comma separated lists of numbers). */
4467 gas_output_limited_string(FILE *file
, const char *str
)
4469 const unsigned char *_limited_str
= (const unsigned char *) str
;
4471 fprintf (file
, "%s\"", STRING_ASM_OP
);
4472 for (; (ch
= *_limited_str
); _limited_str
++)
4475 switch (escape
= ESCAPES
[ch
])
4481 fprintf (file
, "\\%03o", ch
);
4485 putc (escape
, file
);
4489 fprintf (file
, "\"\n");
4492 /* The routine used to output sequences of byte values. We use a special
4493 version of this for most svr4 targets because doing so makes the
4494 generated assembly code more compact (and thus faster to assemble)
4495 as well as more readable. Note that if we find subparts of the
4496 character sequence which end with NUL (and which are shorter than
4497 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4500 gas_output_ascii(FILE *file
, const char *str
, size_t length
)
4502 const unsigned char *_ascii_bytes
= (const unsigned char *) str
;
4503 const unsigned char *limit
= _ascii_bytes
+ length
;
4504 unsigned bytes_in_chunk
= 0;
4505 for (; _ascii_bytes
< limit
; _ascii_bytes
++)
4507 const unsigned char *p
;
4508 if (bytes_in_chunk
>= 60)
4510 fprintf (file
, "\"\n");
4513 for (p
= _ascii_bytes
; p
< limit
&& *p
!= '\0'; p
++)
4515 if (p
< limit
&& (p
- _ascii_bytes
) <= (signed)STRING_LIMIT
)
4517 if (bytes_in_chunk
> 0)
4519 fprintf (file
, "\"\n");
4522 gas_output_limited_string (file
, (const char*)_ascii_bytes
);
4529 if (bytes_in_chunk
== 0)
4530 fprintf (file
, "\t.ascii\t\"");
4531 switch (escape
= ESCAPES
[ch
= *_ascii_bytes
])
4538 fprintf (file
, "\\%03o", ch
);
4539 bytes_in_chunk
+= 4;
4543 putc (escape
, file
);
4544 bytes_in_chunk
+= 2;
4549 if (bytes_in_chunk
> 0)
4550 fprintf (file
, "\"\n");
4553 /* Return value is nonzero if pseudos that have been
4554 assigned to registers of class CLASS would likely be spilled
4555 because registers of CLASS are needed for spill registers. */
4558 class_likely_spilled_p (int c
)
4560 return (c
!= ALL_REGS
&& c
!= ADDW_REGS
);
4563 /* Valid attributes:
4564 progmem - put data to program memory;
4565 signal - make a function to be hardware interrupt. After function
4566 prologue interrupts are disabled;
4567 interrupt - make a function to be hardware interrupt. After function
4568 prologue interrupts are enabled;
4569 naked - don't generate function prologue/epilogue and `ret' command.
4571 Only `progmem' attribute valid for type. */
4573 const struct attribute_spec avr_attribute_table
[] =
4575 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4576 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute
},
4577 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4578 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4579 { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute
},
4580 { NULL
, 0, 0, false, false, false, NULL
}
4583 /* Handle a "progmem" attribute; arguments as in
4584 struct attribute_spec.handler. */
4586 avr_handle_progmem_attribute (tree
*node
, tree name
,
4587 tree args ATTRIBUTE_UNUSED
,
4588 int flags ATTRIBUTE_UNUSED
,
4593 if (TREE_CODE (*node
) == TYPE_DECL
)
4595 /* This is really a decl attribute, not a type attribute,
4596 but try to handle it for GCC 3.0 backwards compatibility. */
4598 tree type
= TREE_TYPE (*node
);
4599 tree attr
= tree_cons (name
, args
, TYPE_ATTRIBUTES (type
));
4600 tree newtype
= build_type_attribute_variant (type
, attr
);
4602 TYPE_MAIN_VARIANT (newtype
) = TYPE_MAIN_VARIANT (type
);
4603 TREE_TYPE (*node
) = newtype
;
4604 *no_add_attrs
= true;
4606 else if (TREE_STATIC (*node
) || DECL_EXTERNAL (*node
))
4608 if (DECL_INITIAL (*node
) == NULL_TREE
&& !DECL_EXTERNAL (*node
))
4610 warning (0, "only initialized variables can be placed into "
4611 "program memory area");
4612 *no_add_attrs
= true;
4617 warning (OPT_Wattributes
, "%qs attribute ignored",
4618 IDENTIFIER_POINTER (name
));
4619 *no_add_attrs
= true;
4626 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4627 struct attribute_spec.handler. */
4630 avr_handle_fndecl_attribute (tree
*node
, tree name
,
4631 tree args ATTRIBUTE_UNUSED
,
4632 int flags ATTRIBUTE_UNUSED
,
4635 if (TREE_CODE (*node
) != FUNCTION_DECL
)
4637 warning (OPT_Wattributes
, "%qs attribute only applies to functions",
4638 IDENTIFIER_POINTER (name
));
4639 *no_add_attrs
= true;
4643 const char *func_name
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (*node
));
4644 const char *attr
= IDENTIFIER_POINTER (name
);
4646 /* If the function has the 'signal' or 'interrupt' attribute, test to
4647 make sure that the name of the function is "__vector_NN" so as to
4648 catch when the user misspells the interrupt vector name. */
4650 if (strncmp (attr
, "interrupt", strlen ("interrupt")) == 0)
4652 if (strncmp (func_name
, "__vector", strlen ("__vector")) != 0)
4654 warning (0, "%qs appears to be a misspelled interrupt handler",
4658 else if (strncmp (attr
, "signal", strlen ("signal")) == 0)
4660 if (strncmp (func_name
, "__vector", strlen ("__vector")) != 0)
4662 warning (0, "%qs appears to be a misspelled signal handler",
4672 avr_handle_fntype_attribute (tree
*node
, tree name
,
4673 tree args ATTRIBUTE_UNUSED
,
4674 int flags ATTRIBUTE_UNUSED
,
4677 if (TREE_CODE (*node
) != FUNCTION_TYPE
)
4679 warning (OPT_Wattributes
, "%qs attribute only applies to functions",
4680 IDENTIFIER_POINTER (name
));
4681 *no_add_attrs
= true;
4687 /* Look for attribute `progmem' in DECL
4688 if found return 1, otherwise 0. */
4691 avr_progmem_p (tree decl
, tree attributes
)
4695 if (TREE_CODE (decl
) != VAR_DECL
)
4699 != lookup_attribute ("progmem", attributes
))
4705 while (TREE_CODE (a
) == ARRAY_TYPE
);
4707 if (a
== error_mark_node
)
4710 if (NULL_TREE
!= lookup_attribute ("progmem", TYPE_ATTRIBUTES (a
)))
4716 /* Add the section attribute if the variable is in progmem. */
4719 avr_insert_attributes (tree node
, tree
*attributes
)
4721 if (TREE_CODE (node
) == VAR_DECL
4722 && (TREE_STATIC (node
) || DECL_EXTERNAL (node
))
4723 && avr_progmem_p (node
, *attributes
))
4725 static const char dsec
[] = ".progmem.data";
4726 *attributes
= tree_cons (get_identifier ("section"),
4727 build_tree_list (NULL
, build_string (strlen (dsec
), dsec
)),
4730 /* ??? This seems sketchy. Why can't the user declare the
4731 thing const in the first place? */
4732 TREE_READONLY (node
) = 1;
4736 /* A get_unnamed_section callback for switching to progmem_section. */
4739 avr_output_progmem_section_asm_op (const void *arg ATTRIBUTE_UNUSED
)
4741 fprintf (asm_out_file
,
4742 "\t.section .progmem.gcc_sw_table, \"%s\", @progbits\n",
4743 AVR_MEGA
? "a" : "ax");
4744 /* Should already be aligned, this is just to be safe if it isn't. */
4745 fprintf (asm_out_file
, "\t.p2align 1\n");
4748 /* Implement TARGET_ASM_INIT_SECTIONS. */
4751 avr_asm_init_sections (void)
4753 progmem_section
= get_unnamed_section (AVR_MEGA
? 0 : SECTION_CODE
,
4754 avr_output_progmem_section_asm_op
,
4756 readonly_data_section
= data_section
;
4760 avr_section_type_flags (tree decl
, const char *name
, int reloc
)
4762 unsigned int flags
= default_section_type_flags (decl
, name
, reloc
);
4764 if (strncmp (name
, ".noinit", 7) == 0)
4766 if (decl
&& TREE_CODE (decl
) == VAR_DECL
4767 && DECL_INITIAL (decl
) == NULL_TREE
)
4768 flags
|= SECTION_BSS
; /* @nobits */
4770 warning (0, "only uninitialized variables can be placed in the "
4777 /* Outputs some appropriate text to go at the start of an assembler
4781 avr_file_start (void)
4784 error ("MCU %qs supported for assembler only", avr_mcu_name
);
4786 default_file_start ();
4788 /* fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);*/
4789 fputs ("__SREG__ = 0x3f\n"
4791 "__SP_L__ = 0x3d\n", asm_out_file
);
4793 fputs ("__tmp_reg__ = 0\n"
4794 "__zero_reg__ = 1\n", asm_out_file
);
4796 /* FIXME: output these only if there is anything in the .data / .bss
4797 sections - some code size could be saved by not linking in the
4798 initialization code from libgcc if one or both sections are empty. */
4799 fputs ("\t.global __do_copy_data\n", asm_out_file
);
4800 fputs ("\t.global __do_clear_bss\n", asm_out_file
);
4803 /* Outputs to the stdio stream FILE some
4804 appropriate text to go at the end of an assembler file. */
4811 /* Choose the order in which to allocate hard registers for
4812 pseudo-registers local to a basic block.
4814 Store the desired register order in the array `reg_alloc_order'.
4815 Element 0 should be the register to allocate first; element 1, the
4816 next register; and so on. */
4819 order_regs_for_local_alloc (void)
4822 static const int order_0
[] = {
4830 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4834 static const int order_1
[] = {
4842 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4846 static const int order_2
[] = {
4855 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4860 const int *order
= (TARGET_ORDER_1
? order_1
:
4861 TARGET_ORDER_2
? order_2
:
4863 for (i
=0; i
< ARRAY_SIZE (order_0
); ++i
)
4864 reg_alloc_order
[i
] = order
[i
];
4868 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
4869 cost of an RTX operand given its context. X is the rtx of the
4870 operand, MODE is its mode, and OUTER is the rtx_code of this
4871 operand's parent operator. */
4874 avr_operand_rtx_cost (rtx x
, enum machine_mode mode
, enum rtx_code outer
)
4876 enum rtx_code code
= GET_CODE (x
);
4887 return COSTS_N_INSNS (GET_MODE_SIZE (mode
));
4894 avr_rtx_costs (x
, code
, outer
, &total
);
4898 /* The AVR backend's rtx_cost function. X is rtx expression whose cost
4899 is to be calculated. Return true if the complete cost has been
4900 computed, and false if subexpressions should be scanned. In either
4901 case, *TOTAL contains the cost result. */
4904 avr_rtx_costs (rtx x
, int code
, int outer_code ATTRIBUTE_UNUSED
, int *total
)
4906 enum machine_mode mode
= GET_MODE (x
);
4913 /* Immediate constants are as cheap as registers. */
4921 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
4929 *total
= COSTS_N_INSNS (1);
4933 *total
= COSTS_N_INSNS (3);
4937 *total
= COSTS_N_INSNS (7);
4943 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4951 *total
= COSTS_N_INSNS (1);
4957 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4961 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
4962 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4966 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
)
4967 - GET_MODE_SIZE (GET_MODE (XEXP (x
, 0))));
4968 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4972 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) + 2
4973 - GET_MODE_SIZE (GET_MODE (XEXP (x
, 0))));
4974 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4981 *total
= COSTS_N_INSNS (1);
4982 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4983 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
4987 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4989 *total
= COSTS_N_INSNS (2);
4990 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
4992 else if (INTVAL (XEXP (x
, 1)) >= -63 && INTVAL (XEXP (x
, 1)) <= 63)
4993 *total
= COSTS_N_INSNS (1);
4995 *total
= COSTS_N_INSNS (2);
4999 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5001 *total
= COSTS_N_INSNS (4);
5002 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5004 else if (INTVAL (XEXP (x
, 1)) >= -63 && INTVAL (XEXP (x
, 1)) <= 63)
5005 *total
= COSTS_N_INSNS (1);
5007 *total
= COSTS_N_INSNS (4);
5013 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5019 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
5020 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5021 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5022 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5026 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
5027 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5028 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5036 *total
= COSTS_N_INSNS (optimize_size
? 3 : 4);
5037 else if (optimize_size
)
5038 *total
= COSTS_N_INSNS (AVR_MEGA
? 2 : 1);
5045 *total
= COSTS_N_INSNS (optimize_size
? 7 : 10);
5046 else if (optimize_size
)
5047 *total
= COSTS_N_INSNS (AVR_MEGA
? 2 : 1);
5055 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5056 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5064 *total
= COSTS_N_INSNS (AVR_MEGA
? 2 : 1);
5067 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5068 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5075 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5077 *total
= COSTS_N_INSNS (optimize_size
? 4 : 17);
5078 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5082 val
= INTVAL (XEXP (x
, 1));
5084 *total
= COSTS_N_INSNS (3);
5085 else if (val
>= 0 && val
<= 7)
5086 *total
= COSTS_N_INSNS (val
);
5088 *total
= COSTS_N_INSNS (1);
5093 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5095 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5096 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5099 switch (INTVAL (XEXP (x
, 1)))
5106 *total
= COSTS_N_INSNS (2);
5109 *total
= COSTS_N_INSNS (3);
5115 *total
= COSTS_N_INSNS (4);
5120 *total
= COSTS_N_INSNS (5);
5123 *total
= COSTS_N_INSNS (optimize_size
? 5 : 8);
5126 *total
= COSTS_N_INSNS (optimize_size
? 5 : 9);
5129 *total
= COSTS_N_INSNS (optimize_size
? 5 : 10);
5132 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5133 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5138 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5140 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5141 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5144 switch (INTVAL (XEXP (x
, 1)))
5150 *total
= COSTS_N_INSNS (3);
5155 *total
= COSTS_N_INSNS (4);
5158 *total
= COSTS_N_INSNS (6);
5161 *total
= COSTS_N_INSNS (optimize_size
? 7 : 8);
5164 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5165 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5172 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5179 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5181 *total
= COSTS_N_INSNS (optimize_size
? 4 : 17);
5182 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5186 val
= INTVAL (XEXP (x
, 1));
5188 *total
= COSTS_N_INSNS (4);
5190 *total
= COSTS_N_INSNS (2);
5191 else if (val
>= 0 && val
<= 7)
5192 *total
= COSTS_N_INSNS (val
);
5194 *total
= COSTS_N_INSNS (1);
5199 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5201 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5202 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5205 switch (INTVAL (XEXP (x
, 1)))
5211 *total
= COSTS_N_INSNS (2);
5214 *total
= COSTS_N_INSNS (3);
5220 *total
= COSTS_N_INSNS (4);
5224 *total
= COSTS_N_INSNS (5);
5227 *total
= COSTS_N_INSNS (optimize_size
? 5 : 6);
5230 *total
= COSTS_N_INSNS (optimize_size
? 5 : 7);
5234 *total
= COSTS_N_INSNS (optimize_size
? 5 : 8);
5237 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5238 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5243 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5245 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5246 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5249 switch (INTVAL (XEXP (x
, 1)))
5255 *total
= COSTS_N_INSNS (4);
5260 *total
= COSTS_N_INSNS (6);
5263 *total
= COSTS_N_INSNS (optimize_size
? 7 : 8);
5266 *total
= COSTS_N_INSNS (AVR_HAVE_MOVW
? 4 : 5);
5269 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5270 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5277 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5284 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5286 *total
= COSTS_N_INSNS (optimize_size
? 4 : 17);
5287 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5291 val
= INTVAL (XEXP (x
, 1));
5293 *total
= COSTS_N_INSNS (3);
5294 else if (val
>= 0 && val
<= 7)
5295 *total
= COSTS_N_INSNS (val
);
5297 *total
= COSTS_N_INSNS (1);
5302 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5304 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5305 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5308 switch (INTVAL (XEXP (x
, 1)))
5315 *total
= COSTS_N_INSNS (2);
5318 *total
= COSTS_N_INSNS (3);
5323 *total
= COSTS_N_INSNS (4);
5327 *total
= COSTS_N_INSNS (5);
5333 *total
= COSTS_N_INSNS (optimize_size
? 5 : 6);
5336 *total
= COSTS_N_INSNS (optimize_size
? 5 : 7);
5340 *total
= COSTS_N_INSNS (optimize_size
? 5 : 9);
5343 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5344 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5349 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5351 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5352 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5355 switch (INTVAL (XEXP (x
, 1)))
5361 *total
= COSTS_N_INSNS (4);
5364 *total
= COSTS_N_INSNS (optimize_size
? 7 : 8);
5369 *total
= COSTS_N_INSNS (4);
5372 *total
= COSTS_N_INSNS (6);
5375 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5376 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5383 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5387 switch (GET_MODE (XEXP (x
, 0)))
5390 *total
= COSTS_N_INSNS (1);
5391 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5392 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5396 *total
= COSTS_N_INSNS (2);
5397 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5398 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5399 else if (INTVAL (XEXP (x
, 1)) != 0)
5400 *total
+= COSTS_N_INSNS (1);
5404 *total
= COSTS_N_INSNS (4);
5405 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5406 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5407 else if (INTVAL (XEXP (x
, 1)) != 0)
5408 *total
+= COSTS_N_INSNS (3);
5414 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5423 /* Calculate the cost of a memory address. */
5426 avr_address_cost (rtx x
)
5428 if (GET_CODE (x
) == PLUS
5429 && GET_CODE (XEXP (x
,1)) == CONST_INT
5430 && (REG_P (XEXP (x
,0)) || GET_CODE (XEXP (x
,0)) == SUBREG
)
5431 && INTVAL (XEXP (x
,1)) >= 61)
5433 if (CONSTANT_ADDRESS_P (x
))
5435 if (avr_io_address_p (x
, 1))
5442 /* Test for extra memory constraint 'Q'.
5443 It's a memory address based on Y or Z pointer with valid displacement. */
5446 extra_constraint_Q (rtx x
)
5448 if (GET_CODE (XEXP (x
,0)) == PLUS
5449 && REG_P (XEXP (XEXP (x
,0), 0))
5450 && GET_CODE (XEXP (XEXP (x
,0), 1)) == CONST_INT
5451 && (INTVAL (XEXP (XEXP (x
,0), 1))
5452 <= MAX_LD_OFFSET (GET_MODE (x
))))
5454 rtx xx
= XEXP (XEXP (x
,0), 0);
5455 int regno
= REGNO (xx
);
5456 if (TARGET_ALL_DEBUG
)
5458 fprintf (stderr
, ("extra_constraint:\n"
5459 "reload_completed: %d\n"
5460 "reload_in_progress: %d\n"),
5461 reload_completed
, reload_in_progress
);
5464 if (regno
>= FIRST_PSEUDO_REGISTER
)
5465 return 1; /* allocate pseudos */
5466 else if (regno
== REG_Z
|| regno
== REG_Y
)
5467 return 1; /* strictly check */
5468 else if (xx
== frame_pointer_rtx
5469 || xx
== arg_pointer_rtx
)
5470 return 1; /* XXX frame & arg pointer checks */
5475 /* Convert condition code CONDITION to the valid AVR condition code. */
5478 avr_normalize_condition (RTX_CODE condition
)
5495 /* This function optimizes conditional jumps. */
5502 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5504 if (! (GET_CODE (insn
) == INSN
5505 || GET_CODE (insn
) == CALL_INSN
5506 || GET_CODE (insn
) == JUMP_INSN
)
5507 || !single_set (insn
))
5510 pattern
= PATTERN (insn
);
5512 if (GET_CODE (pattern
) == PARALLEL
)
5513 pattern
= XVECEXP (pattern
, 0, 0);
5514 if (GET_CODE (pattern
) == SET
5515 && SET_DEST (pattern
) == cc0_rtx
5516 && compare_diff_p (insn
))
5518 if (GET_CODE (SET_SRC (pattern
)) == COMPARE
)
5520 /* Now we work under compare insn. */
5522 pattern
= SET_SRC (pattern
);
5523 if (true_regnum (XEXP (pattern
,0)) >= 0
5524 && true_regnum (XEXP (pattern
,1)) >= 0 )
5526 rtx x
= XEXP (pattern
,0);
5527 rtx next
= next_real_insn (insn
);
5528 rtx pat
= PATTERN (next
);
5529 rtx src
= SET_SRC (pat
);
5530 rtx t
= XEXP (src
,0);
5531 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
5532 XEXP (pattern
,0) = XEXP (pattern
,1);
5533 XEXP (pattern
,1) = x
;
5534 INSN_CODE (next
) = -1;
5536 else if (true_regnum (XEXP (pattern
,0)) >= 0
5537 && GET_CODE (XEXP (pattern
,1)) == CONST_INT
)
5539 rtx x
= XEXP (pattern
,1);
5540 rtx next
= next_real_insn (insn
);
5541 rtx pat
= PATTERN (next
);
5542 rtx src
= SET_SRC (pat
);
5543 rtx t
= XEXP (src
,0);
5544 enum machine_mode mode
= GET_MODE (XEXP (pattern
, 0));
5546 if (avr_simplify_comparison_p (mode
, GET_CODE (t
), x
))
5548 XEXP (pattern
, 1) = gen_int_mode (INTVAL (x
) + 1, mode
);
5549 PUT_CODE (t
, avr_normalize_condition (GET_CODE (t
)));
5550 INSN_CODE (next
) = -1;
5551 INSN_CODE (insn
) = -1;
5555 else if (true_regnum (SET_SRC (pattern
)) >= 0)
5557 /* This is a tst insn */
5558 rtx next
= next_real_insn (insn
);
5559 rtx pat
= PATTERN (next
);
5560 rtx src
= SET_SRC (pat
);
5561 rtx t
= XEXP (src
,0);
5563 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
5564 SET_SRC (pattern
) = gen_rtx_NEG (GET_MODE (SET_SRC (pattern
)),
5566 INSN_CODE (next
) = -1;
5567 INSN_CODE (insn
) = -1;
5573 /* Returns register number for function return value.*/
5576 avr_ret_register (void)
5581 /* Create an RTX representing the place where a
5582 library function returns a value of mode MODE. */
5585 avr_libcall_value (enum machine_mode mode
)
5587 int offs
= GET_MODE_SIZE (mode
);
5590 return gen_rtx_REG (mode
, RET_REGISTER
+ 2 - offs
);
5593 /* Create an RTX representing the place where a
5594 function returns a value of data type VALTYPE. */
5597 avr_function_value (const_tree type
, const_tree func ATTRIBUTE_UNUSED
)
5601 if (TYPE_MODE (type
) != BLKmode
)
5602 return avr_libcall_value (TYPE_MODE (type
));
5604 offs
= int_size_in_bytes (type
);
5607 if (offs
> 2 && offs
< GET_MODE_SIZE (SImode
))
5608 offs
= GET_MODE_SIZE (SImode
);
5609 else if (offs
> GET_MODE_SIZE (SImode
) && offs
< GET_MODE_SIZE (DImode
))
5610 offs
= GET_MODE_SIZE (DImode
);
5612 return gen_rtx_REG (BLKmode
, RET_REGISTER
+ 2 - offs
);
5615 /* Places additional restrictions on the register class to
5616 use when it is necessary to copy value X into a register
5620 preferred_reload_class (rtx x ATTRIBUTE_UNUSED
, enum reg_class
class)
5626 test_hard_reg_class (enum reg_class
class, rtx x
)
5628 int regno
= true_regnum (x
);
5632 if (TEST_HARD_REG_CLASS (class, regno
))
5640 jump_over_one_insn_p (rtx insn
, rtx dest
)
5642 int uid
= INSN_UID (GET_CODE (dest
) == LABEL_REF
5645 int jump_addr
= INSN_ADDRESSES (INSN_UID (insn
));
5646 int dest_addr
= INSN_ADDRESSES (uid
);
5647 return dest_addr
- jump_addr
== get_attr_length (insn
) + 1;
5650 /* Returns 1 if a value of mode MODE can be stored starting with hard
5651 register number REGNO. On the enhanced core, anything larger than
5652 1 byte must start in even numbered register for "movw" to work
5653 (this way we don't have to check for odd registers everywhere). */
5656 avr_hard_regno_mode_ok (int regno
, enum machine_mode mode
)
5658 /* Disallow QImode in stack pointer regs. */
5659 if ((regno
== REG_SP
|| regno
== (REG_SP
+ 1)) && mode
== QImode
)
5662 /* The only thing that can go into registers r28:r29 is a Pmode. */
5663 if (regno
== REG_Y
&& mode
== Pmode
)
5666 /* Otherwise disallow all regno/mode combinations that span r28:r29. */
5667 if (regno
<= (REG_Y
+ 1) && (regno
+ GET_MODE_SIZE (mode
)) >= (REG_Y
+ 1))
5673 /* Modes larger than QImode occupy consecutive registers. */
5674 if (regno
+ GET_MODE_SIZE (mode
) > FIRST_PSEUDO_REGISTER
)
5677 /* All modes larger than QImode should start in an even register. */
5678 return !(regno
& 1);
5681 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5682 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5683 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
5686 avr_io_address_p (rtx x
, int size
)
5688 return (optimize
> 0 && GET_CODE (x
) == CONST_INT
5689 && INTVAL (x
) >= 0x20 && INTVAL (x
) <= 0x60 - size
);
5693 output_reload_inhi (rtx insn ATTRIBUTE_UNUSED
, rtx
*operands
, int *len
)
5699 if (GET_CODE (operands
[1]) == CONST_INT
)
5701 int val
= INTVAL (operands
[1]);
5702 if ((val
& 0xff) == 0)
5705 return (AS2 (mov
,%A0
,__zero_reg__
) CR_TAB
5706 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5709 else if ((val
& 0xff00) == 0)
5712 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5713 AS2 (mov
,%A0
,%2) CR_TAB
5714 AS2 (mov
,%B0
,__zero_reg__
));
5716 else if ((val
& 0xff) == ((val
& 0xff00) >> 8))
5719 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5720 AS2 (mov
,%A0
,%2) CR_TAB
5725 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5726 AS2 (mov
,%A0
,%2) CR_TAB
5727 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5733 output_reload_insisf (rtx insn ATTRIBUTE_UNUSED
, rtx
*operands
, int *len
)
5735 rtx src
= operands
[1];
5736 int cnst
= (GET_CODE (src
) == CONST_INT
);
5741 *len
= 4 + ((INTVAL (src
) & 0xff) != 0)
5742 + ((INTVAL (src
) & 0xff00) != 0)
5743 + ((INTVAL (src
) & 0xff0000) != 0)
5744 + ((INTVAL (src
) & 0xff000000) != 0);
5751 if (cnst
&& ((INTVAL (src
) & 0xff) == 0))
5752 output_asm_insn (AS2 (mov
, %A0
, __zero_reg__
), operands
);
5755 output_asm_insn (AS2 (ldi
, %2, lo8(%1)), operands
);
5756 output_asm_insn (AS2 (mov
, %A0
, %2), operands
);
5758 if (cnst
&& ((INTVAL (src
) & 0xff00) == 0))
5759 output_asm_insn (AS2 (mov
, %B0
, __zero_reg__
), operands
);
5762 output_asm_insn (AS2 (ldi
, %2, hi8(%1)), operands
);
5763 output_asm_insn (AS2 (mov
, %B0
, %2), operands
);
5765 if (cnst
&& ((INTVAL (src
) & 0xff0000) == 0))
5766 output_asm_insn (AS2 (mov
, %C0
, __zero_reg__
), operands
);
5769 output_asm_insn (AS2 (ldi
, %2, hlo8(%1)), operands
);
5770 output_asm_insn (AS2 (mov
, %C0
, %2), operands
);
5772 if (cnst
&& ((INTVAL (src
) & 0xff000000) == 0))
5773 output_asm_insn (AS2 (mov
, %D0
, __zero_reg__
), operands
);
5776 output_asm_insn (AS2 (ldi
, %2, hhi8(%1)), operands
);
5777 output_asm_insn (AS2 (mov
, %D0
, %2), operands
);
5783 avr_output_bld (rtx operands
[], int bit_nr
)
5785 static char s
[] = "bld %A0,0";
5787 s
[5] = 'A' + (bit_nr
>> 3);
5788 s
[8] = '0' + (bit_nr
& 7);
5789 output_asm_insn (s
, operands
);
5793 avr_output_addr_vec_elt (FILE *stream
, int value
)
5795 switch_to_section (progmem_section
);
5797 fprintf (stream
, "\t.word pm(.L%d)\n", value
);
5799 fprintf (stream
, "\trjmp .L%d\n", value
);
5802 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5803 registers (for a define_peephole2) in the current function. */
5806 avr_peep2_scratch_safe (rtx scratch
)
5808 if ((interrupt_function_p (current_function_decl
)
5809 || signal_function_p (current_function_decl
))
5810 && leaf_function_p ())
5812 int first_reg
= true_regnum (scratch
);
5813 int last_reg
= first_reg
+ GET_MODE_SIZE (GET_MODE (scratch
)) - 1;
5816 for (reg
= first_reg
; reg
<= last_reg
; reg
++)
5818 if (!df_regs_ever_live_p (reg
))
5825 /* Output a branch that tests a single bit of a register (QI, HI or SImode)
5826 or memory location in the I/O space (QImode only).
5828 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5829 Operand 1: register operand to test, or CONST_INT memory address.
5830 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5831 Operand 3: label to jump to if the test is true. */
5834 avr_out_sbxx_branch (rtx insn
, rtx operands
[])
5836 enum rtx_code comp
= GET_CODE (operands
[0]);
5837 int long_jump
= (get_attr_length (insn
) >= 4);
5838 int reverse
= long_jump
|| jump_over_one_insn_p (insn
, operands
[3]);
5842 else if (comp
== LT
)
5846 comp
= reverse_condition (comp
);
5848 if (GET_CODE (operands
[1]) == CONST_INT
)
5850 if (INTVAL (operands
[1]) < 0x40)
5853 output_asm_insn (AS2 (sbis
,%1-0x20,%2), operands
);
5855 output_asm_insn (AS2 (sbic
,%1-0x20,%2), operands
);
5859 output_asm_insn (AS2 (in
,__tmp_reg__
,%1-0x20), operands
);
5861 output_asm_insn (AS2 (sbrs
,__tmp_reg__
,%2), operands
);
5863 output_asm_insn (AS2 (sbrc
,__tmp_reg__
,%2), operands
);
5866 else /* GET_CODE (operands[1]) == REG */
5868 if (GET_MODE (operands
[1]) == QImode
)
5871 output_asm_insn (AS2 (sbrs
,%1,%2), operands
);
5873 output_asm_insn (AS2 (sbrc
,%1,%2), operands
);
5875 else /* HImode or SImode */
5877 static char buf
[] = "sbrc %A1,0";
5878 int bit_nr
= exact_log2 (INTVAL (operands
[2])
5879 & GET_MODE_MASK (GET_MODE (operands
[1])));
5881 buf
[3] = (comp
== EQ
) ? 's' : 'c';
5882 buf
[6] = 'A' + (bit_nr
>> 3);
5883 buf
[9] = '0' + (bit_nr
& 7);
5884 output_asm_insn (buf
, operands
);
5889 return (AS1 (rjmp
,.+4) CR_TAB
5892 return AS1 (rjmp
,%3);
5896 /* Worker function for TARGET_ASM_CONSTRUCTOR. */
5899 avr_asm_out_ctor (rtx symbol
, int priority
)
5901 fputs ("\t.global __do_global_ctors\n", asm_out_file
);
5902 default_ctor_section_asm_out_constructor (symbol
, priority
);
5905 /* Worker function for TARGET_ASM_DESTRUCTOR. */
5908 avr_asm_out_dtor (rtx symbol
, int priority
)
5910 fputs ("\t.global __do_global_dtors\n", asm_out_file
);
5911 default_dtor_section_asm_out_destructor (symbol
, priority
);
5914 /* Worker function for TARGET_RETURN_IN_MEMORY. */
5917 avr_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
5919 if (TYPE_MODE (type
) == BLKmode
)
5921 HOST_WIDE_INT size
= int_size_in_bytes (type
);
5922 return (size
== -1 || size
> 8);