1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008,
3 2009 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"
49 /* Maximal allowed offset for an address in the LD command */
50 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
52 static int avr_naked_function_p (tree
);
53 static int interrupt_function_p (tree
);
54 static int signal_function_p (tree
);
55 static int avr_OS_task_function_p (tree
);
56 static int avr_OS_main_function_p (tree
);
57 static int avr_regs_to_save (HARD_REG_SET
*);
58 static int get_sequence_length (rtx insns
);
59 static int sequent_regs_live (void);
60 static const char *ptrreg_to_str (int);
61 static const char *cond_string (enum rtx_code
);
62 static int avr_num_arg_regs (enum machine_mode
, tree
);
64 static RTX_CODE
compare_condition (rtx insn
);
65 static rtx
avr_legitimize_address (rtx
, rtx
, enum machine_mode
);
66 static int compare_sign_p (rtx insn
);
67 static tree
avr_handle_progmem_attribute (tree
*, tree
, tree
, int, bool *);
68 static tree
avr_handle_fndecl_attribute (tree
*, tree
, tree
, int, bool *);
69 static tree
avr_handle_fntype_attribute (tree
*, tree
, tree
, int, bool *);
70 const struct attribute_spec avr_attribute_table
[];
71 static bool avr_assemble_integer (rtx
, unsigned int, int);
72 static void avr_file_start (void);
73 static void avr_file_end (void);
74 static void avr_asm_function_end_prologue (FILE *);
75 static void avr_asm_function_begin_epilogue (FILE *);
76 static rtx
avr_function_value (const_tree
, const_tree
, bool);
77 static void avr_insert_attributes (tree
, tree
*);
78 static void avr_asm_init_sections (void);
79 static unsigned int avr_section_type_flags (tree
, const char *, int);
81 static void avr_reorg (void);
82 static void avr_asm_out_ctor (rtx
, int);
83 static void avr_asm_out_dtor (rtx
, int);
84 static int avr_operand_rtx_cost (rtx
, enum machine_mode
, enum rtx_code
, bool);
85 static bool avr_rtx_costs (rtx
, int, int, int *, bool);
86 static int avr_address_cost (rtx
, bool);
87 static bool avr_return_in_memory (const_tree
, const_tree
);
88 static struct machine_function
* avr_init_machine_status (void);
89 static rtx
avr_builtin_setjmp_frame_value (void);
90 static bool avr_hard_regno_scratch_ok (unsigned int);
91 static unsigned int avr_case_values_threshold (void);
93 /* Allocate registers from r25 to r8 for parameters for function calls. */
94 #define FIRST_CUM_REG 26
96 /* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */
97 static GTY(()) rtx tmp_reg_rtx
;
99 /* Zeroed register RTX (gen_rtx_REG (QImode, ZERO_REGNO)) */
100 static GTY(()) rtx zero_reg_rtx
;
102 /* AVR register names {"r0", "r1", ..., "r31"} */
103 static const char *const avr_regnames
[] = REGISTER_NAMES
;
105 /* This holds the last insn address. */
106 static int last_insn_address
= 0;
108 /* Preprocessor macros to define depending on MCU type. */
109 const char *avr_extra_arch_macro
;
111 /* Current architecture. */
112 const struct base_arch_s
*avr_current_arch
;
114 section
*progmem_section
;
116 static const struct base_arch_s avr_arch_types
[] = {
117 { 1, 0, 0, 0, 0, 0, 0, 0, NULL
}, /* unknown device specified */
118 { 1, 0, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=1" },
119 { 0, 0, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=2" },
120 { 0, 0, 0, 1, 0, 0, 0, 0, "__AVR_ARCH__=25" },
121 { 0, 0, 1, 0, 0, 0, 0, 0, "__AVR_ARCH__=3" },
122 { 0, 0, 1, 0, 1, 0, 0, 0, "__AVR_ARCH__=31" },
123 { 0, 0, 1, 1, 0, 0, 0, 0, "__AVR_ARCH__=35" },
124 { 0, 1, 0, 1, 0, 0, 0, 0, "__AVR_ARCH__=4" },
125 { 0, 1, 1, 1, 0, 0, 0, 0, "__AVR_ARCH__=5" },
126 { 0, 1, 1, 1, 1, 1, 0, 0, "__AVR_ARCH__=51" },
127 { 0, 1, 1, 1, 1, 1, 1, 0, "__AVR_ARCH__=6" }
130 /* 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 { "ata6289", ARCH_AVR25
, "__AVR_ATA6289__" },
181 { "attiny13", ARCH_AVR25
, "__AVR_ATtiny13__" },
182 { "attiny13a", ARCH_AVR25
, "__AVR_ATtiny13A__" },
183 { "attiny2313", ARCH_AVR25
, "__AVR_ATtiny2313__" },
184 { "attiny24", ARCH_AVR25
, "__AVR_ATtiny24__" },
185 { "attiny44", ARCH_AVR25
, "__AVR_ATtiny44__" },
186 { "attiny84", ARCH_AVR25
, "__AVR_ATtiny84__" },
187 { "attiny25", ARCH_AVR25
, "__AVR_ATtiny25__" },
188 { "attiny45", ARCH_AVR25
, "__AVR_ATtiny45__" },
189 { "attiny85", ARCH_AVR25
, "__AVR_ATtiny85__" },
190 { "attiny261", ARCH_AVR25
, "__AVR_ATtiny261__" },
191 { "attiny461", ARCH_AVR25
, "__AVR_ATtiny461__" },
192 { "attiny861", ARCH_AVR25
, "__AVR_ATtiny861__" },
193 { "attiny43u", ARCH_AVR25
, "__AVR_ATtiny43U__" },
194 { "attiny87", ARCH_AVR25
, "__AVR_ATtiny87__" },
195 { "attiny48", ARCH_AVR25
, "__AVR_ATtiny48__" },
196 { "attiny88", ARCH_AVR25
, "__AVR_ATtiny88__" },
197 { "at86rf401", ARCH_AVR25
, "__AVR_AT86RF401__" },
198 /* Classic, > 8K, <= 64K. */
199 { "avr3", ARCH_AVR3
, NULL
},
200 { "at43usb355", ARCH_AVR3
, "__AVR_AT43USB355__" },
201 { "at76c711", ARCH_AVR3
, "__AVR_AT76C711__" },
202 /* Classic, == 128K. */
203 { "avr31", ARCH_AVR31
, NULL
},
204 { "atmega103", ARCH_AVR31
, "__AVR_ATmega103__" },
205 { "at43usb320", ARCH_AVR31
, "__AVR_AT43USB320__" },
206 /* Classic + MOVW + JMP/CALL. */
207 { "avr35", ARCH_AVR35
, NULL
},
208 { "at90usb82", ARCH_AVR35
, "__AVR_AT90USB82__" },
209 { "at90usb162", ARCH_AVR35
, "__AVR_AT90USB162__" },
210 { "attiny167", ARCH_AVR35
, "__AVR_ATtiny167__" },
211 { "attiny327", ARCH_AVR35
, "__AVR_ATtiny327__" },
212 /* Enhanced, <= 8K. */
213 { "avr4", ARCH_AVR4
, NULL
},
214 { "atmega8", ARCH_AVR4
, "__AVR_ATmega8__" },
215 { "atmega48", ARCH_AVR4
, "__AVR_ATmega48__" },
216 { "atmega48p", ARCH_AVR4
, "__AVR_ATmega48P__" },
217 { "atmega88", ARCH_AVR4
, "__AVR_ATmega88__" },
218 { "atmega88p", ARCH_AVR4
, "__AVR_ATmega88P__" },
219 { "atmega8515", ARCH_AVR4
, "__AVR_ATmega8515__" },
220 { "atmega8535", ARCH_AVR4
, "__AVR_ATmega8535__" },
221 { "atmega8hva", ARCH_AVR4
, "__AVR_ATmega8HVA__" },
222 { "atmega4hvd", ARCH_AVR4
, "__AVR_ATmega4HVD__" },
223 { "atmega8hvd", ARCH_AVR4
, "__AVR_ATmega8HVD__" },
224 { "atmega8c1", ARCH_AVR4
, "__AVR_ATmega8C1__" },
225 { "atmega8m1", ARCH_AVR4
, "__AVR_ATmega8M1__" },
226 { "at90pwm1", ARCH_AVR4
, "__AVR_AT90PWM1__" },
227 { "at90pwm2", ARCH_AVR4
, "__AVR_AT90PWM2__" },
228 { "at90pwm2b", ARCH_AVR4
, "__AVR_AT90PWM2B__" },
229 { "at90pwm3", ARCH_AVR4
, "__AVR_AT90PWM3__" },
230 { "at90pwm3b", ARCH_AVR4
, "__AVR_AT90PWM3B__" },
231 { "at90pwm81", ARCH_AVR4
, "__AVR_AT90PWM81__" },
232 /* Enhanced, > 8K, <= 64K. */
233 { "avr5", ARCH_AVR5
, NULL
},
234 { "atmega16", ARCH_AVR5
, "__AVR_ATmega16__" },
235 { "atmega161", ARCH_AVR5
, "__AVR_ATmega161__" },
236 { "atmega162", ARCH_AVR5
, "__AVR_ATmega162__" },
237 { "atmega163", ARCH_AVR5
, "__AVR_ATmega163__" },
238 { "atmega164p", ARCH_AVR5
, "__AVR_ATmega164P__" },
239 { "atmega165", ARCH_AVR5
, "__AVR_ATmega165__" },
240 { "atmega165p", ARCH_AVR5
, "__AVR_ATmega165P__" },
241 { "atmega168", ARCH_AVR5
, "__AVR_ATmega168__" },
242 { "atmega168p", ARCH_AVR5
, "__AVR_ATmega168P__" },
243 { "atmega169", ARCH_AVR5
, "__AVR_ATmega169__" },
244 { "atmega169p", ARCH_AVR5
, "__AVR_ATmega169P__" },
245 { "atmega32", ARCH_AVR5
, "__AVR_ATmega32__" },
246 { "atmega323", ARCH_AVR5
, "__AVR_ATmega323__" },
247 { "atmega324p", ARCH_AVR5
, "__AVR_ATmega324P__" },
248 { "atmega325", ARCH_AVR5
, "__AVR_ATmega325__" },
249 { "atmega325p", ARCH_AVR5
, "__AVR_ATmega325P__" },
250 { "atmega3250", ARCH_AVR5
, "__AVR_ATmega3250__" },
251 { "atmega3250p", ARCH_AVR5
, "__AVR_ATmega3250P__" },
252 { "atmega328p", ARCH_AVR5
, "__AVR_ATmega328P__" },
253 { "atmega329", ARCH_AVR5
, "__AVR_ATmega329__" },
254 { "atmega329p", ARCH_AVR5
, "__AVR_ATmega329P__" },
255 { "atmega3290", ARCH_AVR5
, "__AVR_ATmega3290__" },
256 { "atmega3290p", ARCH_AVR5
, "__AVR_ATmega3290P__" },
257 { "atmega406", ARCH_AVR5
, "__AVR_ATmega406__" },
258 { "atmega64", ARCH_AVR5
, "__AVR_ATmega64__" },
259 { "atmega640", ARCH_AVR5
, "__AVR_ATmega640__" },
260 { "atmega644", ARCH_AVR5
, "__AVR_ATmega644__" },
261 { "atmega644p", ARCH_AVR5
, "__AVR_ATmega644P__" },
262 { "atmega645", ARCH_AVR5
, "__AVR_ATmega645__" },
263 { "atmega6450", ARCH_AVR5
, "__AVR_ATmega6450__" },
264 { "atmega649", ARCH_AVR5
, "__AVR_ATmega649__" },
265 { "atmega6490", ARCH_AVR5
, "__AVR_ATmega6490__" },
266 { "atmega16hva", ARCH_AVR5
, "__AVR_ATmega16HVA__" },
267 { "atmega16hvb", ARCH_AVR5
, "__AVR_ATmega16HVB__" },
268 { "atmega32hvb", ARCH_AVR5
, "__AVR_ATmega32HVB__" },
269 { "at90can32", ARCH_AVR5
, "__AVR_AT90CAN32__" },
270 { "at90can64", ARCH_AVR5
, "__AVR_AT90CAN64__" },
271 { "at90pwm216", ARCH_AVR5
, "__AVR_AT90PWM216__" },
272 { "at90pwm316", ARCH_AVR5
, "__AVR_AT90PWM316__" },
273 { "atmega16c1", ARCH_AVR5
, "__AVR_ATmega16C1__" },
274 { "atmega32c1", ARCH_AVR5
, "__AVR_ATmega32C1__" },
275 { "atmega64c1", ARCH_AVR5
, "__AVR_ATmega64C1__" },
276 { "atmega16m1", ARCH_AVR5
, "__AVR_ATmega16M1__" },
277 { "atmega32m1", ARCH_AVR5
, "__AVR_ATmega32M1__" },
278 { "atmega64m1", ARCH_AVR5
, "__AVR_ATmega64M1__" },
279 { "atmega16u4", ARCH_AVR5
, "__AVR_ATmega16U4__" },
280 { "atmega32u4", ARCH_AVR5
, "__AVR_ATmega32U4__" },
281 { "atmega32u6", ARCH_AVR5
, "__AVR_ATmega32U6__" },
282 { "at90scr100", ARCH_AVR5
, "__AVR_AT90SCR100__" },
283 { "at90usb646", ARCH_AVR5
, "__AVR_AT90USB646__" },
284 { "at90usb647", ARCH_AVR5
, "__AVR_AT90USB647__" },
285 { "at94k", ARCH_AVR5
, "__AVR_AT94K__" },
286 /* Enhanced, == 128K. */
287 { "avr51", ARCH_AVR51
, NULL
},
288 { "atmega128", ARCH_AVR51
, "__AVR_ATmega128__" },
289 { "atmega1280", ARCH_AVR51
, "__AVR_ATmega1280__" },
290 { "atmega1281", ARCH_AVR51
, "__AVR_ATmega1281__" },
291 { "atmega1284p", ARCH_AVR51
, "__AVR_ATmega1284P__" },
292 { "atmega128rfa1", ARCH_AVR51
, "__AVR_ATmega128RFA1__" },
293 { "at90can128", ARCH_AVR51
, "__AVR_AT90CAN128__" },
294 { "at90usb1286", ARCH_AVR51
, "__AVR_AT90USB1286__" },
295 { "at90usb1287", ARCH_AVR51
, "__AVR_AT90USB1287__" },
296 { "m3000f", ARCH_AVR51
, "__AVR_M3000F__" },
297 { "m3000s", ARCH_AVR51
, "__AVR_M3000S__" },
298 { "m3001b", ARCH_AVR51
, "__AVR_M3001B__" },
300 { "avr6", ARCH_AVR6
, NULL
},
301 { "atmega2560", ARCH_AVR6
, "__AVR_ATmega2560__" },
302 { "atmega2561", ARCH_AVR6
, "__AVR_ATmega2561__" },
303 /* Assembler only. */
304 { "avr1", ARCH_AVR1
, NULL
},
305 { "at90s1200", ARCH_AVR1
, "__AVR_AT90S1200__" },
306 { "attiny11", ARCH_AVR1
, "__AVR_ATtiny11__" },
307 { "attiny12", ARCH_AVR1
, "__AVR_ATtiny12__" },
308 { "attiny15", ARCH_AVR1
, "__AVR_ATtiny15__" },
309 { "attiny28", ARCH_AVR1
, "__AVR_ATtiny28__" },
310 { NULL
, ARCH_UNKNOWN
, NULL
}
314 /* Initialize the GCC target structure. */
315 #undef TARGET_ASM_ALIGNED_HI_OP
316 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
317 #undef TARGET_ASM_ALIGNED_SI_OP
318 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
319 #undef TARGET_ASM_UNALIGNED_HI_OP
320 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
321 #undef TARGET_ASM_UNALIGNED_SI_OP
322 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
323 #undef TARGET_ASM_INTEGER
324 #define TARGET_ASM_INTEGER avr_assemble_integer
325 #undef TARGET_ASM_FILE_START
326 #define TARGET_ASM_FILE_START avr_file_start
327 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
328 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
329 #undef TARGET_ASM_FILE_END
330 #define TARGET_ASM_FILE_END avr_file_end
332 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
333 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
334 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
335 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
336 #undef TARGET_FUNCTION_VALUE
337 #define TARGET_FUNCTION_VALUE avr_function_value
338 #undef TARGET_ATTRIBUTE_TABLE
339 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
340 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
341 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
342 #undef TARGET_INSERT_ATTRIBUTES
343 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
344 #undef TARGET_SECTION_TYPE_FLAGS
345 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
346 #undef TARGET_RTX_COSTS
347 #define TARGET_RTX_COSTS avr_rtx_costs
348 #undef TARGET_ADDRESS_COST
349 #define TARGET_ADDRESS_COST avr_address_cost
350 #undef TARGET_MACHINE_DEPENDENT_REORG
351 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
353 #undef TARGET_LEGITIMIZE_ADDRESS
354 #define TARGET_LEGITIMIZE_ADDRESS avr_legitimize_address
356 #undef TARGET_RETURN_IN_MEMORY
357 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
359 #undef TARGET_STRICT_ARGUMENT_NAMING
360 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
362 #undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
363 #define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
365 #undef TARGET_HARD_REGNO_SCRATCH_OK
366 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
367 #undef TARGET_CASE_VALUES_THRESHOLD
368 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
370 struct gcc_target targetm
= TARGET_INITIALIZER
;
373 avr_override_options (void)
375 const struct mcu_type_s
*t
;
377 flag_delete_null_pointer_checks
= 0;
379 if (!PARAM_SET_P (PARAM_INLINE_CALL_COST
))
380 set_param_value ("inline-call-cost", 5);
382 for (t
= avr_mcu_types
; t
->name
; t
++)
383 if (strcmp (t
->name
, avr_mcu_name
) == 0)
388 fprintf (stderr
, "unknown MCU '%s' specified\nKnown MCU names:\n",
390 for (t
= avr_mcu_types
; t
->name
; t
++)
391 fprintf (stderr
," %s\n", t
->name
);
394 avr_current_arch
= &avr_arch_types
[t
->arch
];
395 avr_extra_arch_macro
= t
->macro
;
397 tmp_reg_rtx
= gen_rtx_REG (QImode
, TMP_REGNO
);
398 zero_reg_rtx
= gen_rtx_REG (QImode
, ZERO_REGNO
);
400 init_machine_status
= avr_init_machine_status
;
403 /* return register class from register number. */
405 static const int reg_class_tab
[]={
406 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
407 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
408 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
409 GENERAL_REGS
, /* r0 - r15 */
410 LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,
411 LD_REGS
, /* r16 - 23 */
412 ADDW_REGS
,ADDW_REGS
, /* r24,r25 */
413 POINTER_X_REGS
,POINTER_X_REGS
, /* r26,27 */
414 POINTER_Y_REGS
,POINTER_Y_REGS
, /* r28,r29 */
415 POINTER_Z_REGS
,POINTER_Z_REGS
, /* r30,r31 */
416 STACK_REG
,STACK_REG
/* SPL,SPH */
419 /* Function to set up the backend function structure. */
421 static struct machine_function
*
422 avr_init_machine_status (void)
424 return ((struct machine_function
*)
425 ggc_alloc_cleared (sizeof (struct machine_function
)));
428 /* Return register class for register R. */
431 avr_regno_reg_class (int r
)
434 return reg_class_tab
[r
];
438 /* Return nonzero if FUNC is a naked function. */
441 avr_naked_function_p (tree func
)
445 gcc_assert (TREE_CODE (func
) == FUNCTION_DECL
);
447 a
= lookup_attribute ("naked", TYPE_ATTRIBUTES (TREE_TYPE (func
)));
448 return a
!= NULL_TREE
;
451 /* Return nonzero if FUNC is an interrupt function as specified
452 by the "interrupt" attribute. */
455 interrupt_function_p (tree func
)
459 if (TREE_CODE (func
) != FUNCTION_DECL
)
462 a
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (func
));
463 return a
!= NULL_TREE
;
466 /* Return nonzero if FUNC is a signal function as specified
467 by the "signal" attribute. */
470 signal_function_p (tree func
)
474 if (TREE_CODE (func
) != FUNCTION_DECL
)
477 a
= lookup_attribute ("signal", DECL_ATTRIBUTES (func
));
478 return a
!= NULL_TREE
;
481 /* Return nonzero if FUNC is a OS_task function. */
484 avr_OS_task_function_p (tree func
)
488 gcc_assert (TREE_CODE (func
) == FUNCTION_DECL
);
490 a
= lookup_attribute ("OS_task", TYPE_ATTRIBUTES (TREE_TYPE (func
)));
491 return a
!= NULL_TREE
;
494 /* Return nonzero if FUNC is a OS_main function. */
497 avr_OS_main_function_p (tree func
)
501 gcc_assert (TREE_CODE (func
) == FUNCTION_DECL
);
503 a
= lookup_attribute ("OS_main", TYPE_ATTRIBUTES (TREE_TYPE (func
)));
504 return a
!= NULL_TREE
;
507 /* Return the number of hard registers to push/pop in the prologue/epilogue
508 of the current function, and optionally store these registers in SET. */
511 avr_regs_to_save (HARD_REG_SET
*set
)
514 int int_or_sig_p
= (interrupt_function_p (current_function_decl
)
515 || signal_function_p (current_function_decl
));
517 if (!reload_completed
)
518 cfun
->machine
->is_leaf
= leaf_function_p ();
521 CLEAR_HARD_REG_SET (*set
);
524 /* No need to save any registers if the function never returns or
525 is have "OS_task" or "OS_main" attribute. */
526 if (TREE_THIS_VOLATILE (current_function_decl
)
527 || cfun
->machine
->is_OS_task
528 || cfun
->machine
->is_OS_main
)
531 for (reg
= 0; reg
< 32; reg
++)
533 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
534 any global register variables. */
538 if ((int_or_sig_p
&& !cfun
->machine
->is_leaf
&& call_used_regs
[reg
])
539 || (df_regs_ever_live_p (reg
)
540 && (int_or_sig_p
|| !call_used_regs
[reg
])
541 && !(frame_pointer_needed
542 && (reg
== REG_Y
|| reg
== (REG_Y
+1)))))
545 SET_HARD_REG_BIT (*set
, reg
);
552 /* Return true if register FROM can be eliminated via register TO. */
555 avr_can_eliminate (int from
, int to
)
557 return ((from
== ARG_POINTER_REGNUM
&& to
== FRAME_POINTER_REGNUM
)
558 || ((from
== FRAME_POINTER_REGNUM
559 || from
== FRAME_POINTER_REGNUM
+ 1)
560 && !frame_pointer_needed
));
563 /* Compute offset between arg_pointer and frame_pointer. */
566 avr_initial_elimination_offset (int from
, int to
)
568 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
572 int offset
= frame_pointer_needed
? 2 : 0;
573 int avr_pc_size
= AVR_HAVE_EIJMP_EICALL
? 3 : 2;
575 offset
+= avr_regs_to_save (NULL
);
576 return get_frame_size () + (avr_pc_size
) + 1 + offset
;
580 /* Actual start of frame is virtual_stack_vars_rtx this is offset from
581 frame pointer by +STARTING_FRAME_OFFSET.
582 Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET
583 avoids creating add/sub of offset in nonlocal goto and setjmp. */
585 rtx
avr_builtin_setjmp_frame_value (void)
587 return gen_rtx_MINUS (Pmode
, virtual_stack_vars_rtx
,
588 gen_int_mode (STARTING_FRAME_OFFSET
, Pmode
));
591 /* Return 1 if the function epilogue is just a single "ret". */
594 avr_simple_epilogue (void)
596 return (! frame_pointer_needed
597 && get_frame_size () == 0
598 && avr_regs_to_save (NULL
) == 0
599 && ! interrupt_function_p (current_function_decl
)
600 && ! signal_function_p (current_function_decl
)
601 && ! avr_naked_function_p (current_function_decl
)
602 && ! TREE_THIS_VOLATILE (current_function_decl
));
605 /* This function checks sequence of live registers. */
608 sequent_regs_live (void)
614 for (reg
= 0; reg
< 18; ++reg
)
616 if (!call_used_regs
[reg
])
618 if (df_regs_ever_live_p (reg
))
628 if (!frame_pointer_needed
)
630 if (df_regs_ever_live_p (REG_Y
))
638 if (df_regs_ever_live_p (REG_Y
+1))
651 return (cur_seq
== live_seq
) ? live_seq
: 0;
654 /* Obtain the length sequence of insns. */
657 get_sequence_length (rtx insns
)
662 for (insn
= insns
, length
= 0; insn
; insn
= NEXT_INSN (insn
))
663 length
+= get_attr_length (insn
);
668 /* Output function prologue. */
671 expand_prologue (void)
676 HOST_WIDE_INT size
= get_frame_size();
677 /* Define templates for push instructions. */
678 rtx pushbyte
= gen_rtx_MEM (QImode
,
679 gen_rtx_POST_DEC (HImode
, stack_pointer_rtx
));
680 rtx pushword
= gen_rtx_MEM (HImode
,
681 gen_rtx_POST_DEC (HImode
, stack_pointer_rtx
));
684 last_insn_address
= 0;
686 /* Init cfun->machine. */
687 cfun
->machine
->is_naked
= avr_naked_function_p (current_function_decl
);
688 cfun
->machine
->is_interrupt
= interrupt_function_p (current_function_decl
);
689 cfun
->machine
->is_signal
= signal_function_p (current_function_decl
);
690 cfun
->machine
->is_OS_task
= avr_OS_task_function_p (current_function_decl
);
691 cfun
->machine
->is_OS_main
= avr_OS_main_function_p (current_function_decl
);
693 /* Prologue: naked. */
694 if (cfun
->machine
->is_naked
)
699 avr_regs_to_save (&set
);
700 live_seq
= sequent_regs_live ();
701 minimize
= (TARGET_CALL_PROLOGUES
702 && !cfun
->machine
->is_interrupt
703 && !cfun
->machine
->is_signal
704 && !cfun
->machine
->is_OS_task
705 && !cfun
->machine
->is_OS_main
708 if (cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
710 if (cfun
->machine
->is_interrupt
)
712 /* Enable interrupts. */
713 insn
= emit_insn (gen_enable_interrupt ());
714 RTX_FRAME_RELATED_P (insn
) = 1;
718 insn
= emit_move_insn (pushbyte
, zero_reg_rtx
);
719 RTX_FRAME_RELATED_P (insn
) = 1;
722 insn
= emit_move_insn (pushbyte
, tmp_reg_rtx
);
723 RTX_FRAME_RELATED_P (insn
) = 1;
726 insn
= emit_move_insn (tmp_reg_rtx
,
727 gen_rtx_MEM (QImode
, GEN_INT (SREG_ADDR
)));
728 RTX_FRAME_RELATED_P (insn
) = 1;
729 insn
= emit_move_insn (pushbyte
, tmp_reg_rtx
);
730 RTX_FRAME_RELATED_P (insn
) = 1;
734 && (TEST_HARD_REG_BIT (set
, REG_Z
) && TEST_HARD_REG_BIT (set
, REG_Z
+ 1)))
736 insn
= emit_move_insn (tmp_reg_rtx
,
737 gen_rtx_MEM (QImode
, GEN_INT (RAMPZ_ADDR
)));
738 RTX_FRAME_RELATED_P (insn
) = 1;
739 insn
= emit_move_insn (pushbyte
, tmp_reg_rtx
);
740 RTX_FRAME_RELATED_P (insn
) = 1;
743 /* Clear zero reg. */
744 insn
= emit_move_insn (zero_reg_rtx
, const0_rtx
);
745 RTX_FRAME_RELATED_P (insn
) = 1;
747 /* Prevent any attempt to delete the setting of ZERO_REG! */
748 emit_use (zero_reg_rtx
);
750 if (minimize
&& (frame_pointer_needed
751 || (AVR_2_BYTE_PC
&& live_seq
> 6)
754 insn
= emit_move_insn (gen_rtx_REG (HImode
, REG_X
),
755 gen_int_mode (size
, HImode
));
756 RTX_FRAME_RELATED_P (insn
) = 1;
759 emit_insn (gen_call_prologue_saves (gen_int_mode (live_seq
, HImode
),
760 gen_int_mode (size
+ live_seq
, HImode
)));
761 RTX_FRAME_RELATED_P (insn
) = 1;
766 for (reg
= 0; reg
< 32; ++reg
)
768 if (TEST_HARD_REG_BIT (set
, reg
))
770 /* Emit push of register to save. */
771 insn
=emit_move_insn (pushbyte
, gen_rtx_REG (QImode
, reg
));
772 RTX_FRAME_RELATED_P (insn
) = 1;
775 if (frame_pointer_needed
)
777 if (!(cfun
->machine
->is_OS_task
|| cfun
->machine
->is_OS_main
))
779 /* Push frame pointer. */
780 insn
= emit_move_insn (pushword
, frame_pointer_rtx
);
781 RTX_FRAME_RELATED_P (insn
) = 1;
786 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
787 RTX_FRAME_RELATED_P (insn
) = 1;
791 /* Creating a frame can be done by direct manipulation of the
792 stack or via the frame pointer. These two methods are:
799 the optimum method depends on function type, stack and frame size.
800 To avoid a complex logic, both methods are tested and shortest
804 rtx sp_plus_insns
= NULL_RTX
;
806 if (TARGET_TINY_STACK
)
808 /* The high byte (r29) doesn't change - prefer 'subi' (1 cycle)
809 over 'sbiw' (2 cycles, same size). */
810 myfp
= gen_rtx_REG (QImode
, REGNO (frame_pointer_rtx
));
814 /* Normal sized addition. */
815 myfp
= frame_pointer_rtx
;
818 /* Method 1-Adjust frame pointer. */
821 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
822 RTX_FRAME_RELATED_P (insn
) = 1;
825 emit_move_insn (myfp
,
826 gen_rtx_PLUS (GET_MODE(myfp
), myfp
,
829 RTX_FRAME_RELATED_P (insn
) = 1;
831 /* Copy to stack pointer. */
832 if (TARGET_TINY_STACK
)
834 insn
= emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
835 RTX_FRAME_RELATED_P (insn
) = 1;
837 else if (TARGET_NO_INTERRUPTS
838 || cfun
->machine
->is_signal
839 || cfun
->machine
->is_OS_main
)
842 emit_insn (gen_movhi_sp_r_irq_off (stack_pointer_rtx
,
844 RTX_FRAME_RELATED_P (insn
) = 1;
846 else if (cfun
->machine
->is_interrupt
)
848 insn
= emit_insn (gen_movhi_sp_r_irq_on (stack_pointer_rtx
,
850 RTX_FRAME_RELATED_P (insn
) = 1;
854 insn
= emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
855 RTX_FRAME_RELATED_P (insn
) = 1;
858 fp_plus_insns
= get_insns ();
861 /* Method 2-Adjust Stack pointer. */
867 emit_move_insn (stack_pointer_rtx
,
868 gen_rtx_PLUS (HImode
,
872 RTX_FRAME_RELATED_P (insn
) = 1;
875 emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
876 RTX_FRAME_RELATED_P (insn
) = 1;
878 sp_plus_insns
= get_insns ();
882 /* Use shortest method. */
883 if (size
<= 6 && (get_sequence_length (sp_plus_insns
)
884 < get_sequence_length (fp_plus_insns
)))
885 emit_insn (sp_plus_insns
);
887 emit_insn (fp_plus_insns
);
893 /* Output summary at end of function prologue. */
896 avr_asm_function_end_prologue (FILE *file
)
898 if (cfun
->machine
->is_naked
)
900 fputs ("/* prologue: naked */\n", file
);
904 if (cfun
->machine
->is_interrupt
)
906 fputs ("/* prologue: Interrupt */\n", file
);
908 else if (cfun
->machine
->is_signal
)
910 fputs ("/* prologue: Signal */\n", file
);
913 fputs ("/* prologue: function */\n", file
);
915 fprintf (file
, "/* frame size = " HOST_WIDE_INT_PRINT_DEC
" */\n",
920 /* Implement EPILOGUE_USES. */
923 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED
)
927 && (cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
))
932 /* Output RTL epilogue. */
935 expand_epilogue (void)
941 HOST_WIDE_INT size
= get_frame_size();
943 /* epilogue: naked */
944 if (cfun
->machine
->is_naked
)
946 emit_jump_insn (gen_return ());
950 avr_regs_to_save (&set
);
951 live_seq
= sequent_regs_live ();
952 minimize
= (TARGET_CALL_PROLOGUES
953 && !cfun
->machine
->is_interrupt
954 && !cfun
->machine
->is_signal
955 && !cfun
->machine
->is_OS_task
956 && !cfun
->machine
->is_OS_main
959 if (minimize
&& (frame_pointer_needed
|| live_seq
> 4))
961 if (frame_pointer_needed
)
963 /* Get rid of frame. */
964 emit_move_insn(frame_pointer_rtx
,
965 gen_rtx_PLUS (HImode
, frame_pointer_rtx
,
966 gen_int_mode (size
, HImode
)));
970 emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
973 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq
, HImode
)));
977 if (frame_pointer_needed
)
981 /* Try two methods to adjust stack and select shortest. */
984 rtx sp_plus_insns
= NULL_RTX
;
986 if (TARGET_TINY_STACK
)
988 /* The high byte (r29) doesn't change - prefer 'subi'
989 (1 cycle) over 'sbiw' (2 cycles, same size). */
990 myfp
= gen_rtx_REG (QImode
, REGNO (frame_pointer_rtx
));
994 /* Normal sized addition. */
995 myfp
= frame_pointer_rtx
;
998 /* Method 1-Adjust frame pointer. */
1001 emit_move_insn (myfp
,
1002 gen_rtx_PLUS (HImode
, myfp
,
1006 /* Copy to stack pointer. */
1007 if (TARGET_TINY_STACK
)
1009 emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
1011 else if (TARGET_NO_INTERRUPTS
1012 || cfun
->machine
->is_signal
)
1014 emit_insn (gen_movhi_sp_r_irq_off (stack_pointer_rtx
,
1015 frame_pointer_rtx
));
1017 else if (cfun
->machine
->is_interrupt
)
1019 emit_insn (gen_movhi_sp_r_irq_on (stack_pointer_rtx
,
1020 frame_pointer_rtx
));
1024 emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
1027 fp_plus_insns
= get_insns ();
1030 /* Method 2-Adjust Stack pointer. */
1035 emit_move_insn (stack_pointer_rtx
,
1036 gen_rtx_PLUS (HImode
, stack_pointer_rtx
,
1040 sp_plus_insns
= get_insns ();
1044 /* Use shortest method. */
1045 if (size
<= 5 && (get_sequence_length (sp_plus_insns
)
1046 < get_sequence_length (fp_plus_insns
)))
1047 emit_insn (sp_plus_insns
);
1049 emit_insn (fp_plus_insns
);
1051 if (!(cfun
->machine
->is_OS_task
|| cfun
->machine
->is_OS_main
))
1053 /* Restore previous frame_pointer. */
1054 emit_insn (gen_pophi (frame_pointer_rtx
));
1057 /* Restore used registers. */
1058 for (reg
= 31; reg
>= 0; --reg
)
1060 if (TEST_HARD_REG_BIT (set
, reg
))
1061 emit_insn (gen_popqi (gen_rtx_REG (QImode
, reg
)));
1063 if (cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
1065 /* Restore RAMPZ using tmp reg as scratch. */
1067 && (TEST_HARD_REG_BIT (set
, REG_Z
) && TEST_HARD_REG_BIT (set
, REG_Z
+ 1)))
1069 emit_insn (gen_popqi (tmp_reg_rtx
));
1070 emit_move_insn (gen_rtx_MEM(QImode
, GEN_INT(RAMPZ_ADDR
)),
1074 /* Restore SREG using tmp reg as scratch. */
1075 emit_insn (gen_popqi (tmp_reg_rtx
));
1077 emit_move_insn (gen_rtx_MEM(QImode
, GEN_INT(SREG_ADDR
)),
1080 /* Restore tmp REG. */
1081 emit_insn (gen_popqi (tmp_reg_rtx
));
1083 /* Restore zero REG. */
1084 emit_insn (gen_popqi (zero_reg_rtx
));
1087 emit_jump_insn (gen_return ());
1091 /* Output summary messages at beginning of function epilogue. */
1094 avr_asm_function_begin_epilogue (FILE *file
)
1096 fprintf (file
, "/* epilogue start */\n");
1099 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
1100 machine for a memory operand of mode MODE. */
1103 legitimate_address_p (enum machine_mode mode
, rtx x
, int strict
)
1105 enum reg_class r
= NO_REGS
;
1107 if (TARGET_ALL_DEBUG
)
1109 fprintf (stderr
, "mode: (%s) %s %s %s %s:",
1110 GET_MODE_NAME(mode
),
1111 strict
? "(strict)": "",
1112 reload_completed
? "(reload_completed)": "",
1113 reload_in_progress
? "(reload_in_progress)": "",
1114 reg_renumber
? "(reg_renumber)" : "");
1115 if (GET_CODE (x
) == PLUS
1116 && REG_P (XEXP (x
, 0))
1117 && GET_CODE (XEXP (x
, 1)) == CONST_INT
1118 && INTVAL (XEXP (x
, 1)) >= 0
1119 && INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
)
1122 fprintf (stderr
, "(r%d ---> r%d)", REGNO (XEXP (x
, 0)),
1123 true_regnum (XEXP (x
, 0)));
1126 if (!strict
&& GET_CODE (x
) == SUBREG
)
1128 if (REG_P (x
) && (strict
? REG_OK_FOR_BASE_STRICT_P (x
)
1129 : REG_OK_FOR_BASE_NOSTRICT_P (x
)))
1131 else if (CONSTANT_ADDRESS_P (x
))
1133 else if (GET_CODE (x
) == PLUS
1134 && REG_P (XEXP (x
, 0))
1135 && GET_CODE (XEXP (x
, 1)) == CONST_INT
1136 && INTVAL (XEXP (x
, 1)) >= 0)
1138 int fit
= INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
);
1142 || REGNO (XEXP (x
,0)) == REG_X
1143 || REGNO (XEXP (x
,0)) == REG_Y
1144 || REGNO (XEXP (x
,0)) == REG_Z
)
1145 r
= BASE_POINTER_REGS
;
1146 if (XEXP (x
,0) == frame_pointer_rtx
1147 || XEXP (x
,0) == arg_pointer_rtx
)
1148 r
= BASE_POINTER_REGS
;
1150 else if (frame_pointer_needed
&& XEXP (x
,0) == frame_pointer_rtx
)
1153 else if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == POST_INC
)
1154 && REG_P (XEXP (x
, 0))
1155 && (strict
? REG_OK_FOR_BASE_STRICT_P (XEXP (x
, 0))
1156 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x
, 0))))
1160 if (TARGET_ALL_DEBUG
)
1162 fprintf (stderr
, " ret = %c\n", r
+ '0');
1164 return r
== NO_REGS
? 0 : (int)r
;
1167 /* Attempts to replace X with a valid
1168 memory address for an operand of mode MODE */
1171 avr_legitimize_address (rtx x
, rtx oldx
, enum machine_mode mode
)
1174 if (TARGET_ALL_DEBUG
)
1176 fprintf (stderr
, "legitimize_address mode: %s", GET_MODE_NAME(mode
));
1180 if (GET_CODE (oldx
) == PLUS
1181 && REG_P (XEXP (oldx
,0)))
1183 if (REG_P (XEXP (oldx
,1)))
1184 x
= force_reg (GET_MODE (oldx
), oldx
);
1185 else if (GET_CODE (XEXP (oldx
, 1)) == CONST_INT
)
1187 int offs
= INTVAL (XEXP (oldx
,1));
1188 if (frame_pointer_rtx
!= XEXP (oldx
,0))
1189 if (offs
> MAX_LD_OFFSET (mode
))
1191 if (TARGET_ALL_DEBUG
)
1192 fprintf (stderr
, "force_reg (big offset)\n");
1193 x
= force_reg (GET_MODE (oldx
), oldx
);
1201 /* Return a pointer register name as a string. */
1204 ptrreg_to_str (int regno
)
1208 case REG_X
: return "X";
1209 case REG_Y
: return "Y";
1210 case REG_Z
: return "Z";
1212 output_operand_lossage ("address operand requires constraint for X, Y, or Z register");
1217 /* Return the condition name as a string.
1218 Used in conditional jump constructing */
1221 cond_string (enum rtx_code code
)
1230 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1235 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1248 /* Output ADDR to FILE as address. */
1251 print_operand_address (FILE *file
, rtx addr
)
1253 switch (GET_CODE (addr
))
1256 fprintf (file
, ptrreg_to_str (REGNO (addr
)));
1260 fprintf (file
, "-%s", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
1264 fprintf (file
, "%s+", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
1268 if (CONSTANT_ADDRESS_P (addr
)
1269 && ((GET_CODE (addr
) == SYMBOL_REF
&& SYMBOL_REF_FUNCTION_P (addr
))
1270 || GET_CODE (addr
) == LABEL_REF
))
1272 fprintf (file
, "gs(");
1273 output_addr_const (file
,addr
);
1274 fprintf (file
,")");
1277 output_addr_const (file
, addr
);
1282 /* Output X as assembler operand to file FILE. */
1285 print_operand (FILE *file
, rtx x
, int code
)
1289 if (code
>= 'A' && code
<= 'D')
1294 if (!AVR_HAVE_JMP_CALL
)
1297 else if (code
== '!')
1299 if (AVR_HAVE_EIJMP_EICALL
)
1304 if (x
== zero_reg_rtx
)
1305 fprintf (file
, "__zero_reg__");
1307 fprintf (file
, reg_names
[true_regnum (x
) + abcd
]);
1309 else if (GET_CODE (x
) == CONST_INT
)
1310 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
) + abcd
);
1311 else if (GET_CODE (x
) == MEM
)
1313 rtx addr
= XEXP (x
,0);
1315 if (CONSTANT_P (addr
) && abcd
)
1318 output_address (addr
);
1319 fprintf (file
, ")+%d", abcd
);
1321 else if (code
== 'o')
1323 if (GET_CODE (addr
) != PLUS
)
1324 fatal_insn ("bad address, not (reg+disp):", addr
);
1326 print_operand (file
, XEXP (addr
, 1), 0);
1328 else if (code
== 'p' || code
== 'r')
1330 if (GET_CODE (addr
) != POST_INC
&& GET_CODE (addr
) != PRE_DEC
)
1331 fatal_insn ("bad address, not post_inc or pre_dec:", addr
);
1334 print_operand_address (file
, XEXP (addr
, 0)); /* X, Y, Z */
1336 print_operand (file
, XEXP (addr
, 0), 0); /* r26, r28, r30 */
1338 else if (GET_CODE (addr
) == PLUS
)
1340 print_operand_address (file
, XEXP (addr
,0));
1341 if (REGNO (XEXP (addr
, 0)) == REG_X
)
1342 fatal_insn ("internal compiler error. Bad address:"
1345 print_operand (file
, XEXP (addr
,1), code
);
1348 print_operand_address (file
, addr
);
1350 else if (GET_CODE (x
) == CONST_DOUBLE
)
1354 if (GET_MODE (x
) != SFmode
)
1355 fatal_insn ("internal compiler error. Unknown mode:", x
);
1356 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
1357 REAL_VALUE_TO_TARGET_SINGLE (rv
, val
);
1358 fprintf (file
, "0x%lx", val
);
1360 else if (code
== 'j')
1361 fputs (cond_string (GET_CODE (x
)), file
);
1362 else if (code
== 'k')
1363 fputs (cond_string (reverse_condition (GET_CODE (x
))), file
);
1365 print_operand_address (file
, x
);
1368 /* Update the condition code in the INSN. */
1371 notice_update_cc (rtx body ATTRIBUTE_UNUSED
, rtx insn
)
1375 switch (get_attr_cc (insn
))
1378 /* Insn does not affect CC at all. */
1386 set
= single_set (insn
);
1390 cc_status
.flags
|= CC_NO_OVERFLOW
;
1391 cc_status
.value1
= SET_DEST (set
);
1396 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1397 The V flag may or may not be known but that's ok because
1398 alter_cond will change tests to use EQ/NE. */
1399 set
= single_set (insn
);
1403 cc_status
.value1
= SET_DEST (set
);
1404 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1409 set
= single_set (insn
);
1412 cc_status
.value1
= SET_SRC (set
);
1416 /* Insn doesn't leave CC in a usable state. */
1419 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1420 set
= single_set (insn
);
1423 rtx src
= SET_SRC (set
);
1425 if (GET_CODE (src
) == ASHIFTRT
1426 && GET_MODE (src
) == QImode
)
1428 rtx x
= XEXP (src
, 1);
1430 if (GET_CODE (x
) == CONST_INT
1434 cc_status
.value1
= SET_DEST (set
);
1435 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1443 /* Return maximum number of consecutive registers of
1444 class CLASS needed to hold a value of mode MODE. */
1447 class_max_nregs (enum reg_class rclass ATTRIBUTE_UNUSED
,enum machine_mode mode
)
1449 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
);
1452 /* Choose mode for jump insn:
1453 1 - relative jump in range -63 <= x <= 62 ;
1454 2 - relative jump in range -2046 <= x <= 2045 ;
1455 3 - absolute jump (only for ATmega[16]03). */
1458 avr_jump_mode (rtx x
, rtx insn
)
1460 int dest_addr
= INSN_ADDRESSES (INSN_UID (GET_MODE (x
) == LABEL_REF
1461 ? XEXP (x
, 0) : x
));
1462 int cur_addr
= INSN_ADDRESSES (INSN_UID (insn
));
1463 int jump_distance
= cur_addr
- dest_addr
;
1465 if (-63 <= jump_distance
&& jump_distance
<= 62)
1467 else if (-2046 <= jump_distance
&& jump_distance
<= 2045)
1469 else if (AVR_HAVE_JMP_CALL
)
1475 /* return an AVR condition jump commands.
1476 X is a comparison RTX.
1477 LEN is a number returned by avr_jump_mode function.
1478 if REVERSE nonzero then condition code in X must be reversed. */
1481 ret_cond_branch (rtx x
, int len
, int reverse
)
1483 RTX_CODE cond
= reverse
? reverse_condition (GET_CODE (x
)) : GET_CODE (x
);
1488 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1489 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1491 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1492 AS1 (brmi
,.+2) CR_TAB
1494 (AS1 (breq
,.+6) CR_TAB
1495 AS1 (brmi
,.+4) CR_TAB
1499 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1501 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1502 AS1 (brlt
,.+2) CR_TAB
1504 (AS1 (breq
,.+6) CR_TAB
1505 AS1 (brlt
,.+4) CR_TAB
1508 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1510 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1511 AS1 (brlo
,.+2) CR_TAB
1513 (AS1 (breq
,.+6) CR_TAB
1514 AS1 (brlo
,.+4) CR_TAB
1517 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1518 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1520 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1521 AS1 (brpl
,.+2) CR_TAB
1523 (AS1 (breq
,.+2) CR_TAB
1524 AS1 (brpl
,.+4) CR_TAB
1527 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1529 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1530 AS1 (brge
,.+2) CR_TAB
1532 (AS1 (breq
,.+2) CR_TAB
1533 AS1 (brge
,.+4) CR_TAB
1536 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1538 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1539 AS1 (brsh
,.+2) CR_TAB
1541 (AS1 (breq
,.+2) CR_TAB
1542 AS1 (brsh
,.+4) CR_TAB
1550 return AS1 (br
%k1
,%0);
1552 return (AS1 (br
%j1
,.+2) CR_TAB
1555 return (AS1 (br
%j1
,.+4) CR_TAB
1564 return AS1 (br
%j1
,%0);
1566 return (AS1 (br
%k1
,.+2) CR_TAB
1569 return (AS1 (br
%k1
,.+4) CR_TAB
1577 /* Predicate function for immediate operand which fits to byte (8bit) */
1580 byte_immediate_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
1582 return (GET_CODE (op
) == CONST_INT
1583 && INTVAL (op
) <= 0xff && INTVAL (op
) >= 0);
1586 /* Output all insn addresses and their sizes into the assembly language
1587 output file. This is helpful for debugging whether the length attributes
1588 in the md file are correct.
1589 Output insn cost for next insn. */
1592 final_prescan_insn (rtx insn
, rtx
*operand ATTRIBUTE_UNUSED
,
1593 int num_operands ATTRIBUTE_UNUSED
)
1595 int uid
= INSN_UID (insn
);
1597 if (TARGET_INSN_SIZE_DUMP
|| TARGET_ALL_DEBUG
)
1599 fprintf (asm_out_file
, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1600 INSN_ADDRESSES (uid
),
1601 INSN_ADDRESSES (uid
) - last_insn_address
,
1602 rtx_cost (PATTERN (insn
), INSN
, !optimize_size
));
1604 last_insn_address
= INSN_ADDRESSES (uid
);
1607 /* Return 0 if undefined, 1 if always true or always false. */
1610 avr_simplify_comparison_p (enum machine_mode mode
, RTX_CODE op
, rtx x
)
1612 unsigned int max
= (mode
== QImode
? 0xff :
1613 mode
== HImode
? 0xffff :
1614 mode
== SImode
? 0xffffffff : 0);
1615 if (max
&& op
&& GET_CODE (x
) == CONST_INT
)
1617 if (unsigned_condition (op
) != op
)
1620 if (max
!= (INTVAL (x
) & max
)
1621 && INTVAL (x
) != 0xff)
1628 /* Returns nonzero if REGNO is the number of a hard
1629 register in which function arguments are sometimes passed. */
1632 function_arg_regno_p(int r
)
1634 return (r
>= 8 && r
<= 25);
1637 /* Initializing the variable cum for the state at the beginning
1638 of the argument list. */
1641 init_cumulative_args (CUMULATIVE_ARGS
*cum
, tree fntype
, rtx libname
,
1642 tree fndecl ATTRIBUTE_UNUSED
)
1645 cum
->regno
= FIRST_CUM_REG
;
1646 if (!libname
&& fntype
)
1648 int stdarg
= (TYPE_ARG_TYPES (fntype
) != 0
1649 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype
)))
1650 != void_type_node
));
1656 /* Returns the number of registers to allocate for a function argument. */
1659 avr_num_arg_regs (enum machine_mode mode
, tree type
)
1663 if (mode
== BLKmode
)
1664 size
= int_size_in_bytes (type
);
1666 size
= GET_MODE_SIZE (mode
);
1668 /* Align all function arguments to start in even-numbered registers.
1669 Odd-sized arguments leave holes above them. */
1671 return (size
+ 1) & ~1;
1674 /* Controls whether a function argument is passed
1675 in a register, and which register. */
1678 function_arg (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
, tree type
,
1679 int named ATTRIBUTE_UNUSED
)
1681 int bytes
= avr_num_arg_regs (mode
, type
);
1683 if (cum
->nregs
&& bytes
<= cum
->nregs
)
1684 return gen_rtx_REG (mode
, cum
->regno
- bytes
);
1689 /* Update the summarizer variable CUM to advance past an argument
1690 in the argument list. */
1693 function_arg_advance (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
, tree type
,
1694 int named ATTRIBUTE_UNUSED
)
1696 int bytes
= avr_num_arg_regs (mode
, type
);
1698 cum
->nregs
-= bytes
;
1699 cum
->regno
-= bytes
;
1701 if (cum
->nregs
<= 0)
1704 cum
->regno
= FIRST_CUM_REG
;
1708 /***********************************************************************
1709 Functions for outputting various mov's for a various modes
1710 ************************************************************************/
1712 output_movqi (rtx insn
, rtx operands
[], int *l
)
1715 rtx dest
= operands
[0];
1716 rtx src
= operands
[1];
1724 if (register_operand (dest
, QImode
))
1726 if (register_operand (src
, QImode
)) /* mov r,r */
1728 if (test_hard_reg_class (STACK_REG
, dest
))
1729 return AS2 (out
,%0,%1);
1730 else if (test_hard_reg_class (STACK_REG
, src
))
1731 return AS2 (in
,%0,%1);
1733 return AS2 (mov
,%0,%1);
1735 else if (CONSTANT_P (src
))
1737 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
1738 return AS2 (ldi
,%0,lo8(%1));
1740 if (GET_CODE (src
) == CONST_INT
)
1742 if (src
== const0_rtx
) /* mov r,L */
1743 return AS1 (clr
,%0);
1744 else if (src
== const1_rtx
)
1747 return (AS1 (clr
,%0) CR_TAB
1750 else if (src
== constm1_rtx
)
1752 /* Immediate constants -1 to any register */
1754 return (AS1 (clr
,%0) CR_TAB
1759 int bit_nr
= exact_log2 (INTVAL (src
));
1765 output_asm_insn ((AS1 (clr
,%0) CR_TAB
1768 avr_output_bld (operands
, bit_nr
);
1775 /* Last resort, larger than loading from memory. */
1777 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1778 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1779 AS2 (mov
,%0,r31
) CR_TAB
1780 AS2 (mov
,r31
,__tmp_reg__
));
1782 else if (GET_CODE (src
) == MEM
)
1783 return out_movqi_r_mr (insn
, operands
, real_l
); /* mov r,m */
1785 else if (GET_CODE (dest
) == MEM
)
1789 if (src
== const0_rtx
)
1790 operands
[1] = zero_reg_rtx
;
1792 templ
= out_movqi_mr_r (insn
, operands
, real_l
);
1795 output_asm_insn (templ
, operands
);
1804 output_movhi (rtx insn
, rtx operands
[], int *l
)
1807 rtx dest
= operands
[0];
1808 rtx src
= operands
[1];
1814 if (register_operand (dest
, HImode
))
1816 if (register_operand (src
, HImode
)) /* mov r,r */
1818 if (test_hard_reg_class (STACK_REG
, dest
))
1820 if (TARGET_TINY_STACK
)
1821 return *l
= 1, AS2 (out
,__SP_L__
,%A1
);
1822 /* Use simple load of stack pointer if no interrupts are
1824 else if (TARGET_NO_INTERRUPTS
)
1825 return *l
= 2, (AS2 (out
,__SP_H__
,%B1
) CR_TAB
1826 AS2 (out
,__SP_L__
,%A1
));
1828 return (AS2 (in
,__tmp_reg__
,__SREG__
) CR_TAB
1830 AS2 (out
,__SP_H__
,%B1
) CR_TAB
1831 AS2 (out
,__SREG__
,__tmp_reg__
) CR_TAB
1832 AS2 (out
,__SP_L__
,%A1
));
1834 else if (test_hard_reg_class (STACK_REG
, src
))
1837 return (AS2 (in
,%A0
,__SP_L__
) CR_TAB
1838 AS2 (in
,%B0
,__SP_H__
));
1844 return (AS2 (movw
,%0,%1));
1849 return (AS2 (mov
,%A0
,%A1
) CR_TAB
1853 else if (CONSTANT_P (src
))
1855 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
1858 return (AS2 (ldi
,%A0
,lo8(%1)) CR_TAB
1859 AS2 (ldi
,%B0
,hi8(%1)));
1862 if (GET_CODE (src
) == CONST_INT
)
1864 if (src
== const0_rtx
) /* mov r,L */
1867 return (AS1 (clr
,%A0
) CR_TAB
1870 else if (src
== const1_rtx
)
1873 return (AS1 (clr
,%A0
) CR_TAB
1874 AS1 (clr
,%B0
) CR_TAB
1877 else if (src
== constm1_rtx
)
1879 /* Immediate constants -1 to any register */
1881 return (AS1 (clr
,%0) CR_TAB
1882 AS1 (dec
,%A0
) CR_TAB
1887 int bit_nr
= exact_log2 (INTVAL (src
));
1893 output_asm_insn ((AS1 (clr
,%A0
) CR_TAB
1894 AS1 (clr
,%B0
) CR_TAB
1897 avr_output_bld (operands
, bit_nr
);
1903 if ((INTVAL (src
) & 0xff) == 0)
1906 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1907 AS1 (clr
,%A0
) CR_TAB
1908 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
1909 AS2 (mov
,%B0
,r31
) CR_TAB
1910 AS2 (mov
,r31
,__tmp_reg__
));
1912 else if ((INTVAL (src
) & 0xff00) == 0)
1915 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1916 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1917 AS2 (mov
,%A0
,r31
) CR_TAB
1918 AS1 (clr
,%B0
) CR_TAB
1919 AS2 (mov
,r31
,__tmp_reg__
));
1923 /* Last resort, equal to loading from memory. */
1925 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1926 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1927 AS2 (mov
,%A0
,r31
) CR_TAB
1928 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
1929 AS2 (mov
,%B0
,r31
) CR_TAB
1930 AS2 (mov
,r31
,__tmp_reg__
));
1932 else if (GET_CODE (src
) == MEM
)
1933 return out_movhi_r_mr (insn
, operands
, real_l
); /* mov r,m */
1935 else if (GET_CODE (dest
) == MEM
)
1939 if (src
== const0_rtx
)
1940 operands
[1] = zero_reg_rtx
;
1942 templ
= out_movhi_mr_r (insn
, operands
, real_l
);
1945 output_asm_insn (templ
, operands
);
1950 fatal_insn ("invalid insn:", insn
);
1955 out_movqi_r_mr (rtx insn
, rtx op
[], int *l
)
1959 rtx x
= XEXP (src
, 0);
1965 if (CONSTANT_ADDRESS_P (x
))
1967 if (CONST_INT_P (x
) && INTVAL (x
) == SREG_ADDR
)
1970 return AS2 (in
,%0,__SREG__
);
1972 if (optimize
> 0 && io_address_operand (x
, QImode
))
1975 return AS2 (in
,%0,%1-0x20);
1978 return AS2 (lds
,%0,%1);
1980 /* memory access by reg+disp */
1981 else if (GET_CODE (x
) == PLUS
1982 && REG_P (XEXP (x
,0))
1983 && GET_CODE (XEXP (x
,1)) == CONST_INT
)
1985 if ((INTVAL (XEXP (x
,1)) - GET_MODE_SIZE (GET_MODE (src
))) >= 63)
1987 int disp
= INTVAL (XEXP (x
,1));
1988 if (REGNO (XEXP (x
,0)) != REG_Y
)
1989 fatal_insn ("incorrect insn:",insn
);
1991 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
1992 return *l
= 3, (AS2 (adiw
,r28
,%o1
-63) CR_TAB
1993 AS2 (ldd
,%0,Y
+63) CR_TAB
1994 AS2 (sbiw
,r28
,%o1
-63));
1996 return *l
= 5, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
1997 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
1998 AS2 (ld
,%0,Y
) CR_TAB
1999 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
2000 AS2 (sbci
,r29
,hi8(%o1
)));
2002 else if (REGNO (XEXP (x
,0)) == REG_X
)
2004 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
2005 it but I have this situation with extremal optimizing options. */
2006 if (reg_overlap_mentioned_p (dest
, XEXP (x
,0))
2007 || reg_unused_after (insn
, XEXP (x
,0)))
2008 return *l
= 2, (AS2 (adiw
,r26
,%o1
) CR_TAB
2011 return *l
= 3, (AS2 (adiw
,r26
,%o1
) CR_TAB
2012 AS2 (ld
,%0,X
) CR_TAB
2013 AS2 (sbiw
,r26
,%o1
));
2016 return AS2 (ldd
,%0,%1);
2019 return AS2 (ld
,%0,%1);
2023 out_movhi_r_mr (rtx insn
, rtx op
[], int *l
)
2027 rtx base
= XEXP (src
, 0);
2028 int reg_dest
= true_regnum (dest
);
2029 int reg_base
= true_regnum (base
);
2030 /* "volatile" forces reading low byte first, even if less efficient,
2031 for correct operation with 16-bit I/O registers. */
2032 int mem_volatile_p
= MEM_VOLATILE_P (src
);
2040 if (reg_dest
== reg_base
) /* R = (R) */
2043 return (AS2 (ld
,__tmp_reg__
,%1+) CR_TAB
2044 AS2 (ld
,%B0
,%1) CR_TAB
2045 AS2 (mov
,%A0
,__tmp_reg__
));
2047 else if (reg_base
== REG_X
) /* (R26) */
2049 if (reg_unused_after (insn
, base
))
2052 return (AS2 (ld
,%A0
,X
+) CR_TAB
2056 return (AS2 (ld
,%A0
,X
+) CR_TAB
2057 AS2 (ld
,%B0
,X
) CR_TAB
2063 return (AS2 (ld
,%A0
,%1) CR_TAB
2064 AS2 (ldd
,%B0
,%1+1));
2067 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2069 int disp
= INTVAL (XEXP (base
, 1));
2070 int reg_base
= true_regnum (XEXP (base
, 0));
2072 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
2074 if (REGNO (XEXP (base
, 0)) != REG_Y
)
2075 fatal_insn ("incorrect insn:",insn
);
2077 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
2078 return *l
= 4, (AS2 (adiw
,r28
,%o1
-62) CR_TAB
2079 AS2 (ldd
,%A0
,Y
+62) CR_TAB
2080 AS2 (ldd
,%B0
,Y
+63) CR_TAB
2081 AS2 (sbiw
,r28
,%o1
-62));
2083 return *l
= 6, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
2084 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
2085 AS2 (ld
,%A0
,Y
) CR_TAB
2086 AS2 (ldd
,%B0
,Y
+1) CR_TAB
2087 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
2088 AS2 (sbci
,r29
,hi8(%o1
)));
2090 if (reg_base
== REG_X
)
2092 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
2093 it but I have this situation with extremal
2094 optimization options. */
2097 if (reg_base
== reg_dest
)
2098 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2099 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2100 AS2 (ld
,%B0
,X
) CR_TAB
2101 AS2 (mov
,%A0
,__tmp_reg__
));
2103 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2104 AS2 (ld
,%A0
,X
+) CR_TAB
2105 AS2 (ld
,%B0
,X
) CR_TAB
2106 AS2 (sbiw
,r26
,%o1
+1));
2109 if (reg_base
== reg_dest
)
2112 return (AS2 (ldd
,__tmp_reg__
,%A1
) CR_TAB
2113 AS2 (ldd
,%B0
,%B1
) CR_TAB
2114 AS2 (mov
,%A0
,__tmp_reg__
));
2118 return (AS2 (ldd
,%A0
,%A1
) CR_TAB
2121 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2123 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
2124 fatal_insn ("incorrect insn:", insn
);
2128 if (REGNO (XEXP (base
, 0)) == REG_X
)
2131 return (AS2 (sbiw
,r26
,2) CR_TAB
2132 AS2 (ld
,%A0
,X
+) CR_TAB
2133 AS2 (ld
,%B0
,X
) CR_TAB
2139 return (AS2 (sbiw
,%r1
,2) CR_TAB
2140 AS2 (ld
,%A0
,%p1
) CR_TAB
2141 AS2 (ldd
,%B0
,%p1
+1));
2146 return (AS2 (ld
,%B0
,%1) CR_TAB
2149 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2151 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
2152 fatal_insn ("incorrect insn:", insn
);
2155 return (AS2 (ld
,%A0
,%1) CR_TAB
2158 else if (CONSTANT_ADDRESS_P (base
))
2160 if (optimize
> 0 && io_address_operand (base
, HImode
))
2163 return (AS2 (in
,%A0
,%A1
-0x20) CR_TAB
2164 AS2 (in
,%B0
,%B1
-0x20));
2167 return (AS2 (lds
,%A0
,%A1
) CR_TAB
2171 fatal_insn ("unknown move insn:",insn
);
2176 out_movsi_r_mr (rtx insn
, rtx op
[], int *l
)
2180 rtx base
= XEXP (src
, 0);
2181 int reg_dest
= true_regnum (dest
);
2182 int reg_base
= true_regnum (base
);
2190 if (reg_base
== REG_X
) /* (R26) */
2192 if (reg_dest
== REG_X
)
2193 /* "ld r26,-X" is undefined */
2194 return *l
=7, (AS2 (adiw
,r26
,3) CR_TAB
2195 AS2 (ld
,r29
,X
) CR_TAB
2196 AS2 (ld
,r28
,-X
) CR_TAB
2197 AS2 (ld
,__tmp_reg__
,-X
) CR_TAB
2198 AS2 (sbiw
,r26
,1) CR_TAB
2199 AS2 (ld
,r26
,X
) CR_TAB
2200 AS2 (mov
,r27
,__tmp_reg__
));
2201 else if (reg_dest
== REG_X
- 2)
2202 return *l
=5, (AS2 (ld
,%A0
,X
+) CR_TAB
2203 AS2 (ld
,%B0
,X
+) CR_TAB
2204 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2205 AS2 (ld
,%D0
,X
) CR_TAB
2206 AS2 (mov
,%C0
,__tmp_reg__
));
2207 else if (reg_unused_after (insn
, base
))
2208 return *l
=4, (AS2 (ld
,%A0
,X
+) CR_TAB
2209 AS2 (ld
,%B0
,X
+) CR_TAB
2210 AS2 (ld
,%C0
,X
+) CR_TAB
2213 return *l
=5, (AS2 (ld
,%A0
,X
+) CR_TAB
2214 AS2 (ld
,%B0
,X
+) CR_TAB
2215 AS2 (ld
,%C0
,X
+) CR_TAB
2216 AS2 (ld
,%D0
,X
) CR_TAB
2221 if (reg_dest
== reg_base
)
2222 return *l
=5, (AS2 (ldd
,%D0
,%1+3) CR_TAB
2223 AS2 (ldd
,%C0
,%1+2) CR_TAB
2224 AS2 (ldd
,__tmp_reg__
,%1+1) CR_TAB
2225 AS2 (ld
,%A0
,%1) CR_TAB
2226 AS2 (mov
,%B0
,__tmp_reg__
));
2227 else if (reg_base
== reg_dest
+ 2)
2228 return *l
=5, (AS2 (ld
,%A0
,%1) CR_TAB
2229 AS2 (ldd
,%B0
,%1+1) CR_TAB
2230 AS2 (ldd
,__tmp_reg__
,%1+2) CR_TAB
2231 AS2 (ldd
,%D0
,%1+3) CR_TAB
2232 AS2 (mov
,%C0
,__tmp_reg__
));
2234 return *l
=4, (AS2 (ld
,%A0
,%1) CR_TAB
2235 AS2 (ldd
,%B0
,%1+1) CR_TAB
2236 AS2 (ldd
,%C0
,%1+2) CR_TAB
2237 AS2 (ldd
,%D0
,%1+3));
2240 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2242 int disp
= INTVAL (XEXP (base
, 1));
2244 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
2246 if (REGNO (XEXP (base
, 0)) != REG_Y
)
2247 fatal_insn ("incorrect insn:",insn
);
2249 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
2250 return *l
= 6, (AS2 (adiw
,r28
,%o1
-60) CR_TAB
2251 AS2 (ldd
,%A0
,Y
+60) CR_TAB
2252 AS2 (ldd
,%B0
,Y
+61) CR_TAB
2253 AS2 (ldd
,%C0
,Y
+62) CR_TAB
2254 AS2 (ldd
,%D0
,Y
+63) CR_TAB
2255 AS2 (sbiw
,r28
,%o1
-60));
2257 return *l
= 8, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
2258 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
2259 AS2 (ld
,%A0
,Y
) CR_TAB
2260 AS2 (ldd
,%B0
,Y
+1) CR_TAB
2261 AS2 (ldd
,%C0
,Y
+2) CR_TAB
2262 AS2 (ldd
,%D0
,Y
+3) CR_TAB
2263 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
2264 AS2 (sbci
,r29
,hi8(%o1
)));
2267 reg_base
= true_regnum (XEXP (base
, 0));
2268 if (reg_base
== REG_X
)
2271 if (reg_dest
== REG_X
)
2274 /* "ld r26,-X" is undefined */
2275 return (AS2 (adiw
,r26
,%o1
+3) CR_TAB
2276 AS2 (ld
,r29
,X
) CR_TAB
2277 AS2 (ld
,r28
,-X
) CR_TAB
2278 AS2 (ld
,__tmp_reg__
,-X
) CR_TAB
2279 AS2 (sbiw
,r26
,1) CR_TAB
2280 AS2 (ld
,r26
,X
) CR_TAB
2281 AS2 (mov
,r27
,__tmp_reg__
));
2284 if (reg_dest
== REG_X
- 2)
2285 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2286 AS2 (ld
,r24
,X
+) CR_TAB
2287 AS2 (ld
,r25
,X
+) CR_TAB
2288 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2289 AS2 (ld
,r27
,X
) CR_TAB
2290 AS2 (mov
,r26
,__tmp_reg__
));
2292 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2293 AS2 (ld
,%A0
,X
+) CR_TAB
2294 AS2 (ld
,%B0
,X
+) CR_TAB
2295 AS2 (ld
,%C0
,X
+) CR_TAB
2296 AS2 (ld
,%D0
,X
) CR_TAB
2297 AS2 (sbiw
,r26
,%o1
+3));
2299 if (reg_dest
== reg_base
)
2300 return *l
=5, (AS2 (ldd
,%D0
,%D1
) CR_TAB
2301 AS2 (ldd
,%C0
,%C1
) CR_TAB
2302 AS2 (ldd
,__tmp_reg__
,%B1
) CR_TAB
2303 AS2 (ldd
,%A0
,%A1
) CR_TAB
2304 AS2 (mov
,%B0
,__tmp_reg__
));
2305 else if (reg_dest
== reg_base
- 2)
2306 return *l
=5, (AS2 (ldd
,%A0
,%A1
) CR_TAB
2307 AS2 (ldd
,%B0
,%B1
) CR_TAB
2308 AS2 (ldd
,__tmp_reg__
,%C1
) CR_TAB
2309 AS2 (ldd
,%D0
,%D1
) CR_TAB
2310 AS2 (mov
,%C0
,__tmp_reg__
));
2311 return *l
=4, (AS2 (ldd
,%A0
,%A1
) CR_TAB
2312 AS2 (ldd
,%B0
,%B1
) CR_TAB
2313 AS2 (ldd
,%C0
,%C1
) CR_TAB
2316 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2317 return *l
=4, (AS2 (ld
,%D0
,%1) CR_TAB
2318 AS2 (ld
,%C0
,%1) CR_TAB
2319 AS2 (ld
,%B0
,%1) CR_TAB
2321 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2322 return *l
=4, (AS2 (ld
,%A0
,%1) CR_TAB
2323 AS2 (ld
,%B0
,%1) CR_TAB
2324 AS2 (ld
,%C0
,%1) CR_TAB
2326 else if (CONSTANT_ADDRESS_P (base
))
2327 return *l
=8, (AS2 (lds
,%A0
,%A1
) CR_TAB
2328 AS2 (lds
,%B0
,%B1
) CR_TAB
2329 AS2 (lds
,%C0
,%C1
) CR_TAB
2332 fatal_insn ("unknown move insn:",insn
);
2337 out_movsi_mr_r (rtx insn
, rtx op
[], int *l
)
2341 rtx base
= XEXP (dest
, 0);
2342 int reg_base
= true_regnum (base
);
2343 int reg_src
= true_regnum (src
);
2349 if (CONSTANT_ADDRESS_P (base
))
2350 return *l
=8,(AS2 (sts
,%A0
,%A1
) CR_TAB
2351 AS2 (sts
,%B0
,%B1
) CR_TAB
2352 AS2 (sts
,%C0
,%C1
) CR_TAB
2354 if (reg_base
> 0) /* (r) */
2356 if (reg_base
== REG_X
) /* (R26) */
2358 if (reg_src
== REG_X
)
2360 /* "st X+,r26" is undefined */
2361 if (reg_unused_after (insn
, base
))
2362 return *l
=6, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2363 AS2 (st
,X
,r26
) CR_TAB
2364 AS2 (adiw
,r26
,1) CR_TAB
2365 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2366 AS2 (st
,X
+,r28
) CR_TAB
2369 return *l
=7, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2370 AS2 (st
,X
,r26
) CR_TAB
2371 AS2 (adiw
,r26
,1) CR_TAB
2372 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2373 AS2 (st
,X
+,r28
) CR_TAB
2374 AS2 (st
,X
,r29
) CR_TAB
2377 else if (reg_base
== reg_src
+ 2)
2379 if (reg_unused_after (insn
, base
))
2380 return *l
=7, (AS2 (mov
,__zero_reg__
,%C1
) CR_TAB
2381 AS2 (mov
,__tmp_reg__
,%D1
) CR_TAB
2382 AS2 (st
,%0+,%A1
) CR_TAB
2383 AS2 (st
,%0+,%B1
) CR_TAB
2384 AS2 (st
,%0+,__zero_reg__
) CR_TAB
2385 AS2 (st
,%0,__tmp_reg__
) CR_TAB
2386 AS1 (clr
,__zero_reg__
));
2388 return *l
=8, (AS2 (mov
,__zero_reg__
,%C1
) CR_TAB
2389 AS2 (mov
,__tmp_reg__
,%D1
) CR_TAB
2390 AS2 (st
,%0+,%A1
) CR_TAB
2391 AS2 (st
,%0+,%B1
) CR_TAB
2392 AS2 (st
,%0+,__zero_reg__
) CR_TAB
2393 AS2 (st
,%0,__tmp_reg__
) CR_TAB
2394 AS1 (clr
,__zero_reg__
) CR_TAB
2397 return *l
=5, (AS2 (st
,%0+,%A1
) CR_TAB
2398 AS2 (st
,%0+,%B1
) CR_TAB
2399 AS2 (st
,%0+,%C1
) CR_TAB
2400 AS2 (st
,%0,%D1
) CR_TAB
2404 return *l
=4, (AS2 (st
,%0,%A1
) CR_TAB
2405 AS2 (std
,%0+1,%B1
) CR_TAB
2406 AS2 (std
,%0+2,%C1
) CR_TAB
2407 AS2 (std
,%0+3,%D1
));
2409 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2411 int disp
= INTVAL (XEXP (base
, 1));
2412 reg_base
= REGNO (XEXP (base
, 0));
2413 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
2415 if (reg_base
!= REG_Y
)
2416 fatal_insn ("incorrect insn:",insn
);
2418 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2419 return *l
= 6, (AS2 (adiw
,r28
,%o0
-60) CR_TAB
2420 AS2 (std
,Y
+60,%A1
) CR_TAB
2421 AS2 (std
,Y
+61,%B1
) CR_TAB
2422 AS2 (std
,Y
+62,%C1
) CR_TAB
2423 AS2 (std
,Y
+63,%D1
) CR_TAB
2424 AS2 (sbiw
,r28
,%o0
-60));
2426 return *l
= 8, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2427 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2428 AS2 (st
,Y
,%A1
) CR_TAB
2429 AS2 (std
,Y
+1,%B1
) CR_TAB
2430 AS2 (std
,Y
+2,%C1
) CR_TAB
2431 AS2 (std
,Y
+3,%D1
) CR_TAB
2432 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2433 AS2 (sbci
,r29
,hi8(%o0
)));
2435 if (reg_base
== REG_X
)
2438 if (reg_src
== REG_X
)
2441 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2442 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2443 AS2 (adiw
,r26
,%o0
) CR_TAB
2444 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2445 AS2 (st
,X
+,__zero_reg__
) CR_TAB
2446 AS2 (st
,X
+,r28
) CR_TAB
2447 AS2 (st
,X
,r29
) CR_TAB
2448 AS1 (clr
,__zero_reg__
) CR_TAB
2449 AS2 (sbiw
,r26
,%o0
+3));
2451 else if (reg_src
== REG_X
- 2)
2454 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2455 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2456 AS2 (adiw
,r26
,%o0
) CR_TAB
2457 AS2 (st
,X
+,r24
) CR_TAB
2458 AS2 (st
,X
+,r25
) CR_TAB
2459 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2460 AS2 (st
,X
,__zero_reg__
) CR_TAB
2461 AS1 (clr
,__zero_reg__
) CR_TAB
2462 AS2 (sbiw
,r26
,%o0
+3));
2465 return (AS2 (adiw
,r26
,%o0
) CR_TAB
2466 AS2 (st
,X
+,%A1
) CR_TAB
2467 AS2 (st
,X
+,%B1
) CR_TAB
2468 AS2 (st
,X
+,%C1
) CR_TAB
2469 AS2 (st
,X
,%D1
) CR_TAB
2470 AS2 (sbiw
,r26
,%o0
+3));
2472 return *l
=4, (AS2 (std
,%A0
,%A1
) CR_TAB
2473 AS2 (std
,%B0
,%B1
) CR_TAB
2474 AS2 (std
,%C0
,%C1
) CR_TAB
2477 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2478 return *l
=4, (AS2 (st
,%0,%D1
) CR_TAB
2479 AS2 (st
,%0,%C1
) CR_TAB
2480 AS2 (st
,%0,%B1
) CR_TAB
2482 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2483 return *l
=4, (AS2 (st
,%0,%A1
) CR_TAB
2484 AS2 (st
,%0,%B1
) CR_TAB
2485 AS2 (st
,%0,%C1
) CR_TAB
2487 fatal_insn ("unknown move insn:",insn
);
2492 output_movsisf(rtx insn
, rtx operands
[], int *l
)
2495 rtx dest
= operands
[0];
2496 rtx src
= operands
[1];
2502 if (register_operand (dest
, VOIDmode
))
2504 if (register_operand (src
, VOIDmode
)) /* mov r,r */
2506 if (true_regnum (dest
) > true_regnum (src
))
2511 return (AS2 (movw
,%C0
,%C1
) CR_TAB
2512 AS2 (movw
,%A0
,%A1
));
2515 return (AS2 (mov
,%D0
,%D1
) CR_TAB
2516 AS2 (mov
,%C0
,%C1
) CR_TAB
2517 AS2 (mov
,%B0
,%B1
) CR_TAB
2525 return (AS2 (movw
,%A0
,%A1
) CR_TAB
2526 AS2 (movw
,%C0
,%C1
));
2529 return (AS2 (mov
,%A0
,%A1
) CR_TAB
2530 AS2 (mov
,%B0
,%B1
) CR_TAB
2531 AS2 (mov
,%C0
,%C1
) CR_TAB
2535 else if (CONSTANT_P (src
))
2537 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
2540 return (AS2 (ldi
,%A0
,lo8(%1)) CR_TAB
2541 AS2 (ldi
,%B0
,hi8(%1)) CR_TAB
2542 AS2 (ldi
,%C0
,hlo8(%1)) CR_TAB
2543 AS2 (ldi
,%D0
,hhi8(%1)));
2546 if (GET_CODE (src
) == CONST_INT
)
2548 const char *const clr_op0
=
2549 AVR_HAVE_MOVW
? (AS1 (clr
,%A0
) CR_TAB
2550 AS1 (clr
,%B0
) CR_TAB
2552 : (AS1 (clr
,%A0
) CR_TAB
2553 AS1 (clr
,%B0
) CR_TAB
2554 AS1 (clr
,%C0
) CR_TAB
2557 if (src
== const0_rtx
) /* mov r,L */
2559 *l
= AVR_HAVE_MOVW
? 3 : 4;
2562 else if (src
== const1_rtx
)
2565 output_asm_insn (clr_op0
, operands
);
2566 *l
= AVR_HAVE_MOVW
? 4 : 5;
2567 return AS1 (inc
,%A0
);
2569 else if (src
== constm1_rtx
)
2571 /* Immediate constants -1 to any register */
2575 return (AS1 (clr
,%A0
) CR_TAB
2576 AS1 (dec
,%A0
) CR_TAB
2577 AS2 (mov
,%B0
,%A0
) CR_TAB
2578 AS2 (movw
,%C0
,%A0
));
2581 return (AS1 (clr
,%A0
) CR_TAB
2582 AS1 (dec
,%A0
) CR_TAB
2583 AS2 (mov
,%B0
,%A0
) CR_TAB
2584 AS2 (mov
,%C0
,%A0
) CR_TAB
2589 int bit_nr
= exact_log2 (INTVAL (src
));
2593 *l
= AVR_HAVE_MOVW
? 5 : 6;
2596 output_asm_insn (clr_op0
, operands
);
2597 output_asm_insn ("set", operands
);
2600 avr_output_bld (operands
, bit_nr
);
2607 /* Last resort, better than loading from memory. */
2609 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
2610 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
2611 AS2 (mov
,%A0
,r31
) CR_TAB
2612 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
2613 AS2 (mov
,%B0
,r31
) CR_TAB
2614 AS2 (ldi
,r31
,hlo8(%1)) CR_TAB
2615 AS2 (mov
,%C0
,r31
) CR_TAB
2616 AS2 (ldi
,r31
,hhi8(%1)) CR_TAB
2617 AS2 (mov
,%D0
,r31
) CR_TAB
2618 AS2 (mov
,r31
,__tmp_reg__
));
2620 else if (GET_CODE (src
) == MEM
)
2621 return out_movsi_r_mr (insn
, operands
, real_l
); /* mov r,m */
2623 else if (GET_CODE (dest
) == MEM
)
2627 if (src
== const0_rtx
)
2628 operands
[1] = zero_reg_rtx
;
2630 templ
= out_movsi_mr_r (insn
, operands
, real_l
);
2633 output_asm_insn (templ
, operands
);
2638 fatal_insn ("invalid insn:", insn
);
2643 out_movqi_mr_r (rtx insn
, rtx op
[], int *l
)
2647 rtx x
= XEXP (dest
, 0);
2653 if (CONSTANT_ADDRESS_P (x
))
2655 if (CONST_INT_P (x
) && INTVAL (x
) == SREG_ADDR
)
2658 return AS2 (out
,__SREG__
,%1);
2660 if (optimize
> 0 && io_address_operand (x
, QImode
))
2663 return AS2 (out
,%0-0x20,%1);
2666 return AS2 (sts
,%0,%1);
2668 /* memory access by reg+disp */
2669 else if (GET_CODE (x
) == PLUS
2670 && REG_P (XEXP (x
,0))
2671 && GET_CODE (XEXP (x
,1)) == CONST_INT
)
2673 if ((INTVAL (XEXP (x
,1)) - GET_MODE_SIZE (GET_MODE (dest
))) >= 63)
2675 int disp
= INTVAL (XEXP (x
,1));
2676 if (REGNO (XEXP (x
,0)) != REG_Y
)
2677 fatal_insn ("incorrect insn:",insn
);
2679 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2680 return *l
= 3, (AS2 (adiw
,r28
,%o0
-63) CR_TAB
2681 AS2 (std
,Y
+63,%1) CR_TAB
2682 AS2 (sbiw
,r28
,%o0
-63));
2684 return *l
= 5, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2685 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2686 AS2 (st
,Y
,%1) CR_TAB
2687 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2688 AS2 (sbci
,r29
,hi8(%o0
)));
2690 else if (REGNO (XEXP (x
,0)) == REG_X
)
2692 if (reg_overlap_mentioned_p (src
, XEXP (x
, 0)))
2694 if (reg_unused_after (insn
, XEXP (x
,0)))
2695 return *l
= 3, (AS2 (mov
,__tmp_reg__
,%1) CR_TAB
2696 AS2 (adiw
,r26
,%o0
) CR_TAB
2697 AS2 (st
,X
,__tmp_reg__
));
2699 return *l
= 4, (AS2 (mov
,__tmp_reg__
,%1) CR_TAB
2700 AS2 (adiw
,r26
,%o0
) CR_TAB
2701 AS2 (st
,X
,__tmp_reg__
) CR_TAB
2702 AS2 (sbiw
,r26
,%o0
));
2706 if (reg_unused_after (insn
, XEXP (x
,0)))
2707 return *l
= 2, (AS2 (adiw
,r26
,%o0
) CR_TAB
2710 return *l
= 3, (AS2 (adiw
,r26
,%o0
) CR_TAB
2711 AS2 (st
,X
,%1) CR_TAB
2712 AS2 (sbiw
,r26
,%o0
));
2716 return AS2 (std
,%0,%1);
2719 return AS2 (st
,%0,%1);
2723 out_movhi_mr_r (rtx insn
, rtx op
[], int *l
)
2727 rtx base
= XEXP (dest
, 0);
2728 int reg_base
= true_regnum (base
);
2729 int reg_src
= true_regnum (src
);
2730 /* "volatile" forces writing high byte first, even if less efficient,
2731 for correct operation with 16-bit I/O registers. */
2732 int mem_volatile_p
= MEM_VOLATILE_P (dest
);
2737 if (CONSTANT_ADDRESS_P (base
))
2739 if (optimize
> 0 && io_address_operand (base
, HImode
))
2742 return (AS2 (out
,%B0
-0x20,%B1
) CR_TAB
2743 AS2 (out
,%A0
-0x20,%A1
));
2745 return *l
= 4, (AS2 (sts
,%B0
,%B1
) CR_TAB
2750 if (reg_base
== REG_X
)
2752 if (reg_src
== REG_X
)
2754 /* "st X+,r26" and "st -X,r26" are undefined. */
2755 if (!mem_volatile_p
&& reg_unused_after (insn
, src
))
2756 return *l
=4, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2757 AS2 (st
,X
,r26
) CR_TAB
2758 AS2 (adiw
,r26
,1) CR_TAB
2759 AS2 (st
,X
,__tmp_reg__
));
2761 return *l
=5, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2762 AS2 (adiw
,r26
,1) CR_TAB
2763 AS2 (st
,X
,__tmp_reg__
) CR_TAB
2764 AS2 (sbiw
,r26
,1) CR_TAB
2769 if (!mem_volatile_p
&& reg_unused_after (insn
, base
))
2770 return *l
=2, (AS2 (st
,X
+,%A1
) CR_TAB
2773 return *l
=3, (AS2 (adiw
,r26
,1) CR_TAB
2774 AS2 (st
,X
,%B1
) CR_TAB
2779 return *l
=2, (AS2 (std
,%0+1,%B1
) CR_TAB
2782 else if (GET_CODE (base
) == PLUS
)
2784 int disp
= INTVAL (XEXP (base
, 1));
2785 reg_base
= REGNO (XEXP (base
, 0));
2786 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
2788 if (reg_base
!= REG_Y
)
2789 fatal_insn ("incorrect insn:",insn
);
2791 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2792 return *l
= 4, (AS2 (adiw
,r28
,%o0
-62) CR_TAB
2793 AS2 (std
,Y
+63,%B1
) CR_TAB
2794 AS2 (std
,Y
+62,%A1
) CR_TAB
2795 AS2 (sbiw
,r28
,%o0
-62));
2797 return *l
= 6, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2798 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2799 AS2 (std
,Y
+1,%B1
) CR_TAB
2800 AS2 (st
,Y
,%A1
) CR_TAB
2801 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2802 AS2 (sbci
,r29
,hi8(%o0
)));
2804 if (reg_base
== REG_X
)
2807 if (reg_src
== REG_X
)
2810 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2811 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2812 AS2 (adiw
,r26
,%o0
+1) CR_TAB
2813 AS2 (st
,X
,__zero_reg__
) CR_TAB
2814 AS2 (st
,-X
,__tmp_reg__
) CR_TAB
2815 AS1 (clr
,__zero_reg__
) CR_TAB
2816 AS2 (sbiw
,r26
,%o0
));
2819 return (AS2 (adiw
,r26
,%o0
+1) CR_TAB
2820 AS2 (st
,X
,%B1
) CR_TAB
2821 AS2 (st
,-X
,%A1
) CR_TAB
2822 AS2 (sbiw
,r26
,%o0
));
2824 return *l
=2, (AS2 (std
,%B0
,%B1
) CR_TAB
2827 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2828 return *l
=2, (AS2 (st
,%0,%B1
) CR_TAB
2830 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2834 if (REGNO (XEXP (base
, 0)) == REG_X
)
2837 return (AS2 (adiw
,r26
,1) CR_TAB
2838 AS2 (st
,X
,%B1
) CR_TAB
2839 AS2 (st
,-X
,%A1
) CR_TAB
2845 return (AS2 (std
,%p0
+1,%B1
) CR_TAB
2846 AS2 (st
,%p0
,%A1
) CR_TAB
2852 return (AS2 (st
,%0,%A1
) CR_TAB
2855 fatal_insn ("unknown move insn:",insn
);
2859 /* Return 1 if frame pointer for current function required. */
2862 avr_frame_pointer_required_p (void)
2864 return (cfun
->calls_alloca
2865 || crtl
->args
.info
.nregs
== 0
2866 || get_frame_size () > 0);
2869 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2872 compare_condition (rtx insn
)
2874 rtx next
= next_real_insn (insn
);
2875 RTX_CODE cond
= UNKNOWN
;
2876 if (next
&& GET_CODE (next
) == JUMP_INSN
)
2878 rtx pat
= PATTERN (next
);
2879 rtx src
= SET_SRC (pat
);
2880 rtx t
= XEXP (src
, 0);
2881 cond
= GET_CODE (t
);
2886 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2889 compare_sign_p (rtx insn
)
2891 RTX_CODE cond
= compare_condition (insn
);
2892 return (cond
== GE
|| cond
== LT
);
2895 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2896 that needs to be swapped (GT, GTU, LE, LEU). */
2899 compare_diff_p (rtx insn
)
2901 RTX_CODE cond
= compare_condition (insn
);
2902 return (cond
== GT
|| cond
== GTU
|| cond
== LE
|| cond
== LEU
) ? cond
: 0;
2905 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2908 compare_eq_p (rtx insn
)
2910 RTX_CODE cond
= compare_condition (insn
);
2911 return (cond
== EQ
|| cond
== NE
);
2915 /* Output test instruction for HImode. */
2918 out_tsthi (rtx insn
, int *l
)
2920 if (compare_sign_p (insn
))
2923 return AS1 (tst
,%B0
);
2925 if (reg_unused_after (insn
, SET_SRC (PATTERN (insn
)))
2926 && compare_eq_p (insn
))
2928 /* Faster than sbiw if we can clobber the operand. */
2930 return AS2 (or,%A0
,%B0
);
2932 if (test_hard_reg_class (ADDW_REGS
, SET_SRC (PATTERN (insn
))))
2935 return AS2 (sbiw
,%0,0);
2938 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2939 AS2 (cpc
,%B0
,__zero_reg__
));
2943 /* Output test instruction for SImode. */
2946 out_tstsi (rtx insn
, int *l
)
2948 if (compare_sign_p (insn
))
2951 return AS1 (tst
,%D0
);
2953 if (test_hard_reg_class (ADDW_REGS
, SET_SRC (PATTERN (insn
))))
2956 return (AS2 (sbiw
,%A0
,0) CR_TAB
2957 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2958 AS2 (cpc
,%D0
,__zero_reg__
));
2961 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2962 AS2 (cpc
,%B0
,__zero_reg__
) CR_TAB
2963 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2964 AS2 (cpc
,%D0
,__zero_reg__
));
2968 /* Generate asm equivalent for various shifts.
2969 Shift count is a CONST_INT, MEM or REG.
2970 This only handles cases that are not already
2971 carefully hand-optimized in ?sh??i3_out. */
2974 out_shift_with_cnt (const char *templ
, rtx insn
, rtx operands
[],
2975 int *len
, int t_len
)
2979 int second_label
= 1;
2980 int saved_in_tmp
= 0;
2981 int use_zero_reg
= 0;
2983 op
[0] = operands
[0];
2984 op
[1] = operands
[1];
2985 op
[2] = operands
[2];
2986 op
[3] = operands
[3];
2992 if (GET_CODE (operands
[2]) == CONST_INT
)
2994 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
2995 int count
= INTVAL (operands
[2]);
2996 int max_len
= 10; /* If larger than this, always use a loop. */
3005 if (count
< 8 && !scratch
)
3009 max_len
= t_len
+ (scratch
? 3 : (use_zero_reg
? 4 : 5));
3011 if (t_len
* count
<= max_len
)
3013 /* Output shifts inline with no loop - faster. */
3015 *len
= t_len
* count
;
3019 output_asm_insn (templ
, op
);
3028 strcat (str
, AS2 (ldi
,%3,%2));
3030 else if (use_zero_reg
)
3032 /* Hack to save one word: use __zero_reg__ as loop counter.
3033 Set one bit, then shift in a loop until it is 0 again. */
3035 op
[3] = zero_reg_rtx
;
3039 strcat (str
, ("set" CR_TAB
3040 AS2 (bld
,%3,%2-1)));
3044 /* No scratch register available, use one from LD_REGS (saved in
3045 __tmp_reg__) that doesn't overlap with registers to shift. */
3047 op
[3] = gen_rtx_REG (QImode
,
3048 ((true_regnum (operands
[0]) - 1) & 15) + 16);
3049 op
[4] = tmp_reg_rtx
;
3053 *len
= 3; /* Includes "mov %3,%4" after the loop. */
3055 strcat (str
, (AS2 (mov
,%4,%3) CR_TAB
3061 else if (GET_CODE (operands
[2]) == MEM
)
3065 op
[3] = op_mov
[0] = tmp_reg_rtx
;
3069 out_movqi_r_mr (insn
, op_mov
, len
);
3071 output_asm_insn (out_movqi_r_mr (insn
, op_mov
, NULL
), op_mov
);
3073 else if (register_operand (operands
[2], QImode
))
3075 if (reg_unused_after (insn
, operands
[2]))
3079 op
[3] = tmp_reg_rtx
;
3081 strcat (str
, (AS2 (mov
,%3,%2) CR_TAB
));
3085 fatal_insn ("bad shift insn:", insn
);
3092 strcat (str
, AS1 (rjmp
,2f
));
3096 *len
+= t_len
+ 2; /* template + dec + brXX */
3099 strcat (str
, "\n1:\t");
3100 strcat (str
, templ
);
3101 strcat (str
, second_label
? "\n2:\t" : "\n\t");
3102 strcat (str
, use_zero_reg
? AS1 (lsr
,%3) : AS1 (dec
,%3));
3103 strcat (str
, CR_TAB
);
3104 strcat (str
, second_label
? AS1 (brpl
,1b
) : AS1 (brne
,1b
));
3106 strcat (str
, (CR_TAB
AS2 (mov
,%3,%4)));
3107 output_asm_insn (str
, op
);
3112 /* 8bit shift left ((char)x << i) */
3115 ashlqi3_out (rtx insn
, rtx operands
[], int *len
)
3117 if (GET_CODE (operands
[2]) == CONST_INT
)
3124 switch (INTVAL (operands
[2]))
3127 if (INTVAL (operands
[2]) < 8)
3131 return AS1 (clr
,%0);
3135 return AS1 (lsl
,%0);
3139 return (AS1 (lsl
,%0) CR_TAB
3144 return (AS1 (lsl
,%0) CR_TAB
3149 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3152 return (AS1 (swap
,%0) CR_TAB
3153 AS2 (andi
,%0,0xf0));
3156 return (AS1 (lsl
,%0) CR_TAB
3162 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3165 return (AS1 (swap
,%0) CR_TAB
3167 AS2 (andi
,%0,0xe0));
3170 return (AS1 (lsl
,%0) CR_TAB
3177 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3180 return (AS1 (swap
,%0) CR_TAB
3183 AS2 (andi
,%0,0xc0));
3186 return (AS1 (lsl
,%0) CR_TAB
3195 return (AS1 (ror
,%0) CR_TAB
3200 else if (CONSTANT_P (operands
[2]))
3201 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3203 out_shift_with_cnt (AS1 (lsl
,%0),
3204 insn
, operands
, len
, 1);
3209 /* 16bit shift left ((short)x << i) */
3212 ashlhi3_out (rtx insn
, rtx operands
[], int *len
)
3214 if (GET_CODE (operands
[2]) == CONST_INT
)
3216 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3217 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3224 switch (INTVAL (operands
[2]))
3227 if (INTVAL (operands
[2]) < 16)
3231 return (AS1 (clr
,%B0
) CR_TAB
3235 if (optimize_size
&& scratch
)
3240 return (AS1 (swap
,%A0
) CR_TAB
3241 AS1 (swap
,%B0
) CR_TAB
3242 AS2 (andi
,%B0
,0xf0) CR_TAB
3243 AS2 (eor
,%B0
,%A0
) CR_TAB
3244 AS2 (andi
,%A0
,0xf0) CR_TAB
3250 return (AS1 (swap
,%A0
) CR_TAB
3251 AS1 (swap
,%B0
) CR_TAB
3252 AS2 (ldi
,%3,0xf0) CR_TAB
3253 AS2 (and,%B0
,%3) CR_TAB
3254 AS2 (eor
,%B0
,%A0
) CR_TAB
3255 AS2 (and,%A0
,%3) CR_TAB
3258 break; /* optimize_size ? 6 : 8 */
3262 break; /* scratch ? 5 : 6 */
3266 return (AS1 (lsl
,%A0
) CR_TAB
3267 AS1 (rol
,%B0
) CR_TAB
3268 AS1 (swap
,%A0
) CR_TAB
3269 AS1 (swap
,%B0
) CR_TAB
3270 AS2 (andi
,%B0
,0xf0) CR_TAB
3271 AS2 (eor
,%B0
,%A0
) CR_TAB
3272 AS2 (andi
,%A0
,0xf0) CR_TAB
3278 return (AS1 (lsl
,%A0
) CR_TAB
3279 AS1 (rol
,%B0
) CR_TAB
3280 AS1 (swap
,%A0
) CR_TAB
3281 AS1 (swap
,%B0
) CR_TAB
3282 AS2 (ldi
,%3,0xf0) CR_TAB
3283 AS2 (and,%B0
,%3) CR_TAB
3284 AS2 (eor
,%B0
,%A0
) CR_TAB
3285 AS2 (and,%A0
,%3) CR_TAB
3292 break; /* scratch ? 5 : 6 */
3294 return (AS1 (clr
,__tmp_reg__
) CR_TAB
3295 AS1 (lsr
,%B0
) CR_TAB
3296 AS1 (ror
,%A0
) CR_TAB
3297 AS1 (ror
,__tmp_reg__
) CR_TAB
3298 AS1 (lsr
,%B0
) CR_TAB
3299 AS1 (ror
,%A0
) CR_TAB
3300 AS1 (ror
,__tmp_reg__
) CR_TAB
3301 AS2 (mov
,%B0
,%A0
) CR_TAB
3302 AS2 (mov
,%A0
,__tmp_reg__
));
3306 return (AS1 (lsr
,%B0
) CR_TAB
3307 AS2 (mov
,%B0
,%A0
) CR_TAB
3308 AS1 (clr
,%A0
) CR_TAB
3309 AS1 (ror
,%B0
) CR_TAB
3313 return *len
= 2, (AS2 (mov
,%B0
,%A1
) CR_TAB
3318 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3319 AS1 (clr
,%A0
) CR_TAB
3324 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3325 AS1 (clr
,%A0
) CR_TAB
3326 AS1 (lsl
,%B0
) CR_TAB
3331 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3332 AS1 (clr
,%A0
) CR_TAB
3333 AS1 (lsl
,%B0
) CR_TAB
3334 AS1 (lsl
,%B0
) CR_TAB
3341 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3342 AS1 (clr
,%A0
) CR_TAB
3343 AS1 (swap
,%B0
) CR_TAB
3344 AS2 (andi
,%B0
,0xf0));
3349 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3350 AS1 (clr
,%A0
) CR_TAB
3351 AS1 (swap
,%B0
) CR_TAB
3352 AS2 (ldi
,%3,0xf0) CR_TAB
3356 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3357 AS1 (clr
,%A0
) CR_TAB
3358 AS1 (lsl
,%B0
) CR_TAB
3359 AS1 (lsl
,%B0
) CR_TAB
3360 AS1 (lsl
,%B0
) CR_TAB
3367 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3368 AS1 (clr
,%A0
) CR_TAB
3369 AS1 (swap
,%B0
) CR_TAB
3370 AS1 (lsl
,%B0
) CR_TAB
3371 AS2 (andi
,%B0
,0xe0));
3373 if (AVR_HAVE_MUL
&& scratch
)
3376 return (AS2 (ldi
,%3,0x20) CR_TAB
3377 AS2 (mul
,%A0
,%3) CR_TAB
3378 AS2 (mov
,%B0
,r0
) CR_TAB
3379 AS1 (clr
,%A0
) CR_TAB
3380 AS1 (clr
,__zero_reg__
));
3382 if (optimize_size
&& scratch
)
3387 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3388 AS1 (clr
,%A0
) CR_TAB
3389 AS1 (swap
,%B0
) CR_TAB
3390 AS1 (lsl
,%B0
) CR_TAB
3391 AS2 (ldi
,%3,0xe0) CR_TAB
3397 return ("set" CR_TAB
3398 AS2 (bld
,r1
,5) CR_TAB
3399 AS2 (mul
,%A0
,r1
) CR_TAB
3400 AS2 (mov
,%B0
,r0
) CR_TAB
3401 AS1 (clr
,%A0
) CR_TAB
3402 AS1 (clr
,__zero_reg__
));
3405 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3406 AS1 (clr
,%A0
) CR_TAB
3407 AS1 (lsl
,%B0
) CR_TAB
3408 AS1 (lsl
,%B0
) CR_TAB
3409 AS1 (lsl
,%B0
) CR_TAB
3410 AS1 (lsl
,%B0
) CR_TAB
3414 if (AVR_HAVE_MUL
&& ldi_ok
)
3417 return (AS2 (ldi
,%B0
,0x40) CR_TAB
3418 AS2 (mul
,%A0
,%B0
) CR_TAB
3419 AS2 (mov
,%B0
,r0
) CR_TAB
3420 AS1 (clr
,%A0
) CR_TAB
3421 AS1 (clr
,__zero_reg__
));
3423 if (AVR_HAVE_MUL
&& scratch
)
3426 return (AS2 (ldi
,%3,0x40) CR_TAB
3427 AS2 (mul
,%A0
,%3) CR_TAB
3428 AS2 (mov
,%B0
,r0
) CR_TAB
3429 AS1 (clr
,%A0
) CR_TAB
3430 AS1 (clr
,__zero_reg__
));
3432 if (optimize_size
&& ldi_ok
)
3435 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3436 AS2 (ldi
,%A0
,6) "\n1:\t"
3437 AS1 (lsl
,%B0
) CR_TAB
3438 AS1 (dec
,%A0
) CR_TAB
3441 if (optimize_size
&& scratch
)
3444 return (AS1 (clr
,%B0
) CR_TAB
3445 AS1 (lsr
,%A0
) CR_TAB
3446 AS1 (ror
,%B0
) CR_TAB
3447 AS1 (lsr
,%A0
) CR_TAB
3448 AS1 (ror
,%B0
) CR_TAB
3453 return (AS1 (clr
,%B0
) CR_TAB
3454 AS1 (lsr
,%A0
) CR_TAB
3455 AS1 (ror
,%B0
) CR_TAB
3460 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3462 insn
, operands
, len
, 2);
3467 /* 32bit shift left ((long)x << i) */
3470 ashlsi3_out (rtx insn
, rtx operands
[], int *len
)
3472 if (GET_CODE (operands
[2]) == CONST_INT
)
3480 switch (INTVAL (operands
[2]))
3483 if (INTVAL (operands
[2]) < 32)
3487 return *len
= 3, (AS1 (clr
,%D0
) CR_TAB
3488 AS1 (clr
,%C0
) CR_TAB
3489 AS2 (movw
,%A0
,%C0
));
3491 return (AS1 (clr
,%D0
) CR_TAB
3492 AS1 (clr
,%C0
) CR_TAB
3493 AS1 (clr
,%B0
) CR_TAB
3498 int reg0
= true_regnum (operands
[0]);
3499 int reg1
= true_regnum (operands
[1]);
3502 return (AS2 (mov
,%D0
,%C1
) CR_TAB
3503 AS2 (mov
,%C0
,%B1
) CR_TAB
3504 AS2 (mov
,%B0
,%A1
) CR_TAB
3507 return (AS1 (clr
,%A0
) CR_TAB
3508 AS2 (mov
,%B0
,%A1
) CR_TAB
3509 AS2 (mov
,%C0
,%B1
) CR_TAB
3515 int reg0
= true_regnum (operands
[0]);
3516 int reg1
= true_regnum (operands
[1]);
3517 if (reg0
+ 2 == reg1
)
3518 return *len
= 2, (AS1 (clr
,%B0
) CR_TAB
3521 return *len
= 3, (AS2 (movw
,%C0
,%A1
) CR_TAB
3522 AS1 (clr
,%B0
) CR_TAB
3525 return *len
= 4, (AS2 (mov
,%C0
,%A1
) CR_TAB
3526 AS2 (mov
,%D0
,%B1
) CR_TAB
3527 AS1 (clr
,%B0
) CR_TAB
3533 return (AS2 (mov
,%D0
,%A1
) CR_TAB
3534 AS1 (clr
,%C0
) CR_TAB
3535 AS1 (clr
,%B0
) CR_TAB
3540 return (AS1 (clr
,%D0
) CR_TAB
3541 AS1 (lsr
,%A0
) CR_TAB
3542 AS1 (ror
,%D0
) CR_TAB
3543 AS1 (clr
,%C0
) CR_TAB
3544 AS1 (clr
,%B0
) CR_TAB
3549 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3550 AS1 (rol
,%B0
) CR_TAB
3551 AS1 (rol
,%C0
) CR_TAB
3553 insn
, operands
, len
, 4);
3557 /* 8bit arithmetic shift right ((signed char)x >> i) */
3560 ashrqi3_out (rtx insn
, rtx operands
[], int *len
)
3562 if (GET_CODE (operands
[2]) == CONST_INT
)
3569 switch (INTVAL (operands
[2]))
3573 return AS1 (asr
,%0);
3577 return (AS1 (asr
,%0) CR_TAB
3582 return (AS1 (asr
,%0) CR_TAB
3588 return (AS1 (asr
,%0) CR_TAB
3595 return (AS1 (asr
,%0) CR_TAB
3603 return (AS2 (bst
,%0,6) CR_TAB
3605 AS2 (sbc
,%0,%0) CR_TAB
3609 if (INTVAL (operands
[2]) < 8)
3616 return (AS1 (lsl
,%0) CR_TAB
3620 else if (CONSTANT_P (operands
[2]))
3621 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3623 out_shift_with_cnt (AS1 (asr
,%0),
3624 insn
, operands
, len
, 1);
3629 /* 16bit arithmetic shift right ((signed short)x >> i) */
3632 ashrhi3_out (rtx insn
, rtx operands
[], int *len
)
3634 if (GET_CODE (operands
[2]) == CONST_INT
)
3636 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3637 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3644 switch (INTVAL (operands
[2]))
3648 /* XXX try to optimize this too? */
3653 break; /* scratch ? 5 : 6 */
3655 return (AS2 (mov
,__tmp_reg__
,%A0
) CR_TAB
3656 AS2 (mov
,%A0
,%B0
) CR_TAB
3657 AS1 (lsl
,__tmp_reg__
) CR_TAB
3658 AS1 (rol
,%A0
) CR_TAB
3659 AS2 (sbc
,%B0
,%B0
) CR_TAB
3660 AS1 (lsl
,__tmp_reg__
) CR_TAB
3661 AS1 (rol
,%A0
) CR_TAB
3666 return (AS1 (lsl
,%A0
) CR_TAB
3667 AS2 (mov
,%A0
,%B0
) CR_TAB
3668 AS1 (rol
,%A0
) CR_TAB
3673 int reg0
= true_regnum (operands
[0]);
3674 int reg1
= true_regnum (operands
[1]);
3677 return *len
= 3, (AS2 (mov
,%A0
,%B0
) CR_TAB
3678 AS1 (lsl
,%B0
) CR_TAB
3681 return *len
= 4, (AS2 (mov
,%A0
,%B1
) CR_TAB
3682 AS1 (clr
,%B0
) CR_TAB
3683 AS2 (sbrc
,%A0
,7) CR_TAB
3689 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3690 AS1 (lsl
,%B0
) CR_TAB
3691 AS2 (sbc
,%B0
,%B0
) CR_TAB
3696 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3697 AS1 (lsl
,%B0
) CR_TAB
3698 AS2 (sbc
,%B0
,%B0
) CR_TAB
3699 AS1 (asr
,%A0
) CR_TAB
3703 if (AVR_HAVE_MUL
&& ldi_ok
)
3706 return (AS2 (ldi
,%A0
,0x20) CR_TAB
3707 AS2 (muls
,%B0
,%A0
) CR_TAB
3708 AS2 (mov
,%A0
,r1
) CR_TAB
3709 AS2 (sbc
,%B0
,%B0
) CR_TAB
3710 AS1 (clr
,__zero_reg__
));
3712 if (optimize_size
&& scratch
)
3715 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3716 AS1 (lsl
,%B0
) CR_TAB
3717 AS2 (sbc
,%B0
,%B0
) CR_TAB
3718 AS1 (asr
,%A0
) CR_TAB
3719 AS1 (asr
,%A0
) CR_TAB
3723 if (AVR_HAVE_MUL
&& ldi_ok
)
3726 return (AS2 (ldi
,%A0
,0x10) CR_TAB
3727 AS2 (muls
,%B0
,%A0
) CR_TAB
3728 AS2 (mov
,%A0
,r1
) CR_TAB
3729 AS2 (sbc
,%B0
,%B0
) CR_TAB
3730 AS1 (clr
,__zero_reg__
));
3732 if (optimize_size
&& scratch
)
3735 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3736 AS1 (lsl
,%B0
) CR_TAB
3737 AS2 (sbc
,%B0
,%B0
) CR_TAB
3738 AS1 (asr
,%A0
) CR_TAB
3739 AS1 (asr
,%A0
) CR_TAB
3740 AS1 (asr
,%A0
) CR_TAB
3744 if (AVR_HAVE_MUL
&& ldi_ok
)
3747 return (AS2 (ldi
,%A0
,0x08) CR_TAB
3748 AS2 (muls
,%B0
,%A0
) CR_TAB
3749 AS2 (mov
,%A0
,r1
) CR_TAB
3750 AS2 (sbc
,%B0
,%B0
) CR_TAB
3751 AS1 (clr
,__zero_reg__
));
3754 break; /* scratch ? 5 : 7 */
3756 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3757 AS1 (lsl
,%B0
) CR_TAB
3758 AS2 (sbc
,%B0
,%B0
) CR_TAB
3759 AS1 (asr
,%A0
) CR_TAB
3760 AS1 (asr
,%A0
) CR_TAB
3761 AS1 (asr
,%A0
) CR_TAB
3762 AS1 (asr
,%A0
) CR_TAB
3767 return (AS1 (lsl
,%B0
) CR_TAB
3768 AS2 (sbc
,%A0
,%A0
) CR_TAB
3769 AS1 (lsl
,%B0
) CR_TAB
3770 AS2 (mov
,%B0
,%A0
) CR_TAB
3774 if (INTVAL (operands
[2]) < 16)
3780 return *len
= 3, (AS1 (lsl
,%B0
) CR_TAB
3781 AS2 (sbc
,%A0
,%A0
) CR_TAB
3786 out_shift_with_cnt ((AS1 (asr
,%B0
) CR_TAB
3788 insn
, operands
, len
, 2);
3793 /* 32bit arithmetic shift right ((signed long)x >> i) */
3796 ashrsi3_out (rtx insn
, rtx operands
[], int *len
)
3798 if (GET_CODE (operands
[2]) == CONST_INT
)
3806 switch (INTVAL (operands
[2]))
3810 int reg0
= true_regnum (operands
[0]);
3811 int reg1
= true_regnum (operands
[1]);
3814 return (AS2 (mov
,%A0
,%B1
) CR_TAB
3815 AS2 (mov
,%B0
,%C1
) CR_TAB
3816 AS2 (mov
,%C0
,%D1
) CR_TAB
3817 AS1 (clr
,%D0
) CR_TAB
3818 AS2 (sbrc
,%C0
,7) CR_TAB
3821 return (AS1 (clr
,%D0
) CR_TAB
3822 AS2 (sbrc
,%D1
,7) CR_TAB
3823 AS1 (dec
,%D0
) CR_TAB
3824 AS2 (mov
,%C0
,%D1
) CR_TAB
3825 AS2 (mov
,%B0
,%C1
) CR_TAB
3831 int reg0
= true_regnum (operands
[0]);
3832 int reg1
= true_regnum (operands
[1]);
3834 if (reg0
== reg1
+ 2)
3835 return *len
= 4, (AS1 (clr
,%D0
) CR_TAB
3836 AS2 (sbrc
,%B0
,7) CR_TAB
3837 AS1 (com
,%D0
) CR_TAB
3840 return *len
= 5, (AS2 (movw
,%A0
,%C1
) CR_TAB
3841 AS1 (clr
,%D0
) CR_TAB
3842 AS2 (sbrc
,%B0
,7) CR_TAB
3843 AS1 (com
,%D0
) CR_TAB
3846 return *len
= 6, (AS2 (mov
,%B0
,%D1
) CR_TAB
3847 AS2 (mov
,%A0
,%C1
) CR_TAB
3848 AS1 (clr
,%D0
) CR_TAB
3849 AS2 (sbrc
,%B0
,7) CR_TAB
3850 AS1 (com
,%D0
) CR_TAB
3855 return *len
= 6, (AS2 (mov
,%A0
,%D1
) CR_TAB
3856 AS1 (clr
,%D0
) CR_TAB
3857 AS2 (sbrc
,%A0
,7) CR_TAB
3858 AS1 (com
,%D0
) CR_TAB
3859 AS2 (mov
,%B0
,%D0
) CR_TAB
3863 if (INTVAL (operands
[2]) < 32)
3870 return *len
= 4, (AS1 (lsl
,%D0
) CR_TAB
3871 AS2 (sbc
,%A0
,%A0
) CR_TAB
3872 AS2 (mov
,%B0
,%A0
) CR_TAB
3873 AS2 (movw
,%C0
,%A0
));
3875 return *len
= 5, (AS1 (lsl
,%D0
) CR_TAB
3876 AS2 (sbc
,%A0
,%A0
) CR_TAB
3877 AS2 (mov
,%B0
,%A0
) CR_TAB
3878 AS2 (mov
,%C0
,%A0
) CR_TAB
3883 out_shift_with_cnt ((AS1 (asr
,%D0
) CR_TAB
3884 AS1 (ror
,%C0
) CR_TAB
3885 AS1 (ror
,%B0
) CR_TAB
3887 insn
, operands
, len
, 4);
3891 /* 8bit logic shift right ((unsigned char)x >> i) */
3894 lshrqi3_out (rtx insn
, rtx operands
[], int *len
)
3896 if (GET_CODE (operands
[2]) == CONST_INT
)
3903 switch (INTVAL (operands
[2]))
3906 if (INTVAL (operands
[2]) < 8)
3910 return AS1 (clr
,%0);
3914 return AS1 (lsr
,%0);
3918 return (AS1 (lsr
,%0) CR_TAB
3922 return (AS1 (lsr
,%0) CR_TAB
3927 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3930 return (AS1 (swap
,%0) CR_TAB
3931 AS2 (andi
,%0,0x0f));
3934 return (AS1 (lsr
,%0) CR_TAB
3940 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3943 return (AS1 (swap
,%0) CR_TAB
3948 return (AS1 (lsr
,%0) CR_TAB
3955 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3958 return (AS1 (swap
,%0) CR_TAB
3964 return (AS1 (lsr
,%0) CR_TAB
3973 return (AS1 (rol
,%0) CR_TAB
3978 else if (CONSTANT_P (operands
[2]))
3979 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3981 out_shift_with_cnt (AS1 (lsr
,%0),
3982 insn
, operands
, len
, 1);
3986 /* 16bit logic shift right ((unsigned short)x >> i) */
3989 lshrhi3_out (rtx insn
, rtx operands
[], int *len
)
3991 if (GET_CODE (operands
[2]) == CONST_INT
)
3993 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3994 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
4001 switch (INTVAL (operands
[2]))
4004 if (INTVAL (operands
[2]) < 16)
4008 return (AS1 (clr
,%B0
) CR_TAB
4012 if (optimize_size
&& scratch
)
4017 return (AS1 (swap
,%B0
) CR_TAB
4018 AS1 (swap
,%A0
) CR_TAB
4019 AS2 (andi
,%A0
,0x0f) CR_TAB
4020 AS2 (eor
,%A0
,%B0
) CR_TAB
4021 AS2 (andi
,%B0
,0x0f) CR_TAB
4027 return (AS1 (swap
,%B0
) CR_TAB
4028 AS1 (swap
,%A0
) CR_TAB
4029 AS2 (ldi
,%3,0x0f) CR_TAB
4030 AS2 (and,%A0
,%3) CR_TAB
4031 AS2 (eor
,%A0
,%B0
) CR_TAB
4032 AS2 (and,%B0
,%3) CR_TAB
4035 break; /* optimize_size ? 6 : 8 */
4039 break; /* scratch ? 5 : 6 */
4043 return (AS1 (lsr
,%B0
) CR_TAB
4044 AS1 (ror
,%A0
) CR_TAB
4045 AS1 (swap
,%B0
) CR_TAB
4046 AS1 (swap
,%A0
) CR_TAB
4047 AS2 (andi
,%A0
,0x0f) CR_TAB
4048 AS2 (eor
,%A0
,%B0
) CR_TAB
4049 AS2 (andi
,%B0
,0x0f) CR_TAB
4055 return (AS1 (lsr
,%B0
) CR_TAB
4056 AS1 (ror
,%A0
) CR_TAB
4057 AS1 (swap
,%B0
) CR_TAB
4058 AS1 (swap
,%A0
) CR_TAB
4059 AS2 (ldi
,%3,0x0f) CR_TAB
4060 AS2 (and,%A0
,%3) CR_TAB
4061 AS2 (eor
,%A0
,%B0
) CR_TAB
4062 AS2 (and,%B0
,%3) CR_TAB
4069 break; /* scratch ? 5 : 6 */
4071 return (AS1 (clr
,__tmp_reg__
) CR_TAB
4072 AS1 (lsl
,%A0
) CR_TAB
4073 AS1 (rol
,%B0
) CR_TAB
4074 AS1 (rol
,__tmp_reg__
) CR_TAB
4075 AS1 (lsl
,%A0
) CR_TAB
4076 AS1 (rol
,%B0
) CR_TAB
4077 AS1 (rol
,__tmp_reg__
) CR_TAB
4078 AS2 (mov
,%A0
,%B0
) CR_TAB
4079 AS2 (mov
,%B0
,__tmp_reg__
));
4083 return (AS1 (lsl
,%A0
) CR_TAB
4084 AS2 (mov
,%A0
,%B0
) CR_TAB
4085 AS1 (rol
,%A0
) CR_TAB
4086 AS2 (sbc
,%B0
,%B0
) CR_TAB
4090 return *len
= 2, (AS2 (mov
,%A0
,%B1
) CR_TAB
4095 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4096 AS1 (clr
,%B0
) CR_TAB
4101 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4102 AS1 (clr
,%B0
) CR_TAB
4103 AS1 (lsr
,%A0
) CR_TAB
4108 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4109 AS1 (clr
,%B0
) CR_TAB
4110 AS1 (lsr
,%A0
) CR_TAB
4111 AS1 (lsr
,%A0
) CR_TAB
4118 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4119 AS1 (clr
,%B0
) CR_TAB
4120 AS1 (swap
,%A0
) CR_TAB
4121 AS2 (andi
,%A0
,0x0f));
4126 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4127 AS1 (clr
,%B0
) CR_TAB
4128 AS1 (swap
,%A0
) CR_TAB
4129 AS2 (ldi
,%3,0x0f) CR_TAB
4133 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4134 AS1 (clr
,%B0
) CR_TAB
4135 AS1 (lsr
,%A0
) CR_TAB
4136 AS1 (lsr
,%A0
) CR_TAB
4137 AS1 (lsr
,%A0
) CR_TAB
4144 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4145 AS1 (clr
,%B0
) CR_TAB
4146 AS1 (swap
,%A0
) CR_TAB
4147 AS1 (lsr
,%A0
) CR_TAB
4148 AS2 (andi
,%A0
,0x07));
4150 if (AVR_HAVE_MUL
&& scratch
)
4153 return (AS2 (ldi
,%3,0x08) CR_TAB
4154 AS2 (mul
,%B0
,%3) CR_TAB
4155 AS2 (mov
,%A0
,r1
) CR_TAB
4156 AS1 (clr
,%B0
) CR_TAB
4157 AS1 (clr
,__zero_reg__
));
4159 if (optimize_size
&& scratch
)
4164 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4165 AS1 (clr
,%B0
) CR_TAB
4166 AS1 (swap
,%A0
) CR_TAB
4167 AS1 (lsr
,%A0
) CR_TAB
4168 AS2 (ldi
,%3,0x07) CR_TAB
4174 return ("set" CR_TAB
4175 AS2 (bld
,r1
,3) CR_TAB
4176 AS2 (mul
,%B0
,r1
) CR_TAB
4177 AS2 (mov
,%A0
,r1
) CR_TAB
4178 AS1 (clr
,%B0
) CR_TAB
4179 AS1 (clr
,__zero_reg__
));
4182 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4183 AS1 (clr
,%B0
) CR_TAB
4184 AS1 (lsr
,%A0
) CR_TAB
4185 AS1 (lsr
,%A0
) CR_TAB
4186 AS1 (lsr
,%A0
) CR_TAB
4187 AS1 (lsr
,%A0
) CR_TAB
4191 if (AVR_HAVE_MUL
&& ldi_ok
)
4194 return (AS2 (ldi
,%A0
,0x04) CR_TAB
4195 AS2 (mul
,%B0
,%A0
) CR_TAB
4196 AS2 (mov
,%A0
,r1
) CR_TAB
4197 AS1 (clr
,%B0
) CR_TAB
4198 AS1 (clr
,__zero_reg__
));
4200 if (AVR_HAVE_MUL
&& scratch
)
4203 return (AS2 (ldi
,%3,0x04) CR_TAB
4204 AS2 (mul
,%B0
,%3) CR_TAB
4205 AS2 (mov
,%A0
,r1
) CR_TAB
4206 AS1 (clr
,%B0
) CR_TAB
4207 AS1 (clr
,__zero_reg__
));
4209 if (optimize_size
&& ldi_ok
)
4212 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4213 AS2 (ldi
,%B0
,6) "\n1:\t"
4214 AS1 (lsr
,%A0
) CR_TAB
4215 AS1 (dec
,%B0
) CR_TAB
4218 if (optimize_size
&& scratch
)
4221 return (AS1 (clr
,%A0
) CR_TAB
4222 AS1 (lsl
,%B0
) CR_TAB
4223 AS1 (rol
,%A0
) CR_TAB
4224 AS1 (lsl
,%B0
) CR_TAB
4225 AS1 (rol
,%A0
) CR_TAB
4230 return (AS1 (clr
,%A0
) CR_TAB
4231 AS1 (lsl
,%B0
) CR_TAB
4232 AS1 (rol
,%A0
) CR_TAB
4237 out_shift_with_cnt ((AS1 (lsr
,%B0
) CR_TAB
4239 insn
, operands
, len
, 2);
4243 /* 32bit logic shift right ((unsigned int)x >> i) */
4246 lshrsi3_out (rtx insn
, rtx operands
[], int *len
)
4248 if (GET_CODE (operands
[2]) == CONST_INT
)
4256 switch (INTVAL (operands
[2]))
4259 if (INTVAL (operands
[2]) < 32)
4263 return *len
= 3, (AS1 (clr
,%D0
) CR_TAB
4264 AS1 (clr
,%C0
) CR_TAB
4265 AS2 (movw
,%A0
,%C0
));
4267 return (AS1 (clr
,%D0
) CR_TAB
4268 AS1 (clr
,%C0
) CR_TAB
4269 AS1 (clr
,%B0
) CR_TAB
4274 int reg0
= true_regnum (operands
[0]);
4275 int reg1
= true_regnum (operands
[1]);
4278 return (AS2 (mov
,%A0
,%B1
) CR_TAB
4279 AS2 (mov
,%B0
,%C1
) CR_TAB
4280 AS2 (mov
,%C0
,%D1
) CR_TAB
4283 return (AS1 (clr
,%D0
) CR_TAB
4284 AS2 (mov
,%C0
,%D1
) CR_TAB
4285 AS2 (mov
,%B0
,%C1
) CR_TAB
4291 int reg0
= true_regnum (operands
[0]);
4292 int reg1
= true_regnum (operands
[1]);
4294 if (reg0
== reg1
+ 2)
4295 return *len
= 2, (AS1 (clr
,%C0
) CR_TAB
4298 return *len
= 3, (AS2 (movw
,%A0
,%C1
) CR_TAB
4299 AS1 (clr
,%C0
) CR_TAB
4302 return *len
= 4, (AS2 (mov
,%B0
,%D1
) CR_TAB
4303 AS2 (mov
,%A0
,%C1
) CR_TAB
4304 AS1 (clr
,%C0
) CR_TAB
4309 return *len
= 4, (AS2 (mov
,%A0
,%D1
) CR_TAB
4310 AS1 (clr
,%B0
) CR_TAB
4311 AS1 (clr
,%C0
) CR_TAB
4316 return (AS1 (clr
,%A0
) CR_TAB
4317 AS2 (sbrc
,%D0
,7) CR_TAB
4318 AS1 (inc
,%A0
) CR_TAB
4319 AS1 (clr
,%B0
) CR_TAB
4320 AS1 (clr
,%C0
) CR_TAB
4325 out_shift_with_cnt ((AS1 (lsr
,%D0
) CR_TAB
4326 AS1 (ror
,%C0
) CR_TAB
4327 AS1 (ror
,%B0
) CR_TAB
4329 insn
, operands
, len
, 4);
4333 /* Modifies the length assigned to instruction INSN
4334 LEN is the initially computed length of the insn. */
4337 adjust_insn_length (rtx insn
, int len
)
4339 rtx patt
= PATTERN (insn
);
4342 if (GET_CODE (patt
) == SET
)
4345 op
[1] = SET_SRC (patt
);
4346 op
[0] = SET_DEST (patt
);
4347 if (general_operand (op
[1], VOIDmode
)
4348 && general_operand (op
[0], VOIDmode
))
4350 switch (GET_MODE (op
[0]))
4353 output_movqi (insn
, op
, &len
);
4356 output_movhi (insn
, op
, &len
);
4360 output_movsisf (insn
, op
, &len
);
4366 else if (op
[0] == cc0_rtx
&& REG_P (op
[1]))
4368 switch (GET_MODE (op
[1]))
4370 case HImode
: out_tsthi (insn
,&len
); break;
4371 case SImode
: out_tstsi (insn
,&len
); break;
4375 else if (GET_CODE (op
[1]) == AND
)
4377 if (GET_CODE (XEXP (op
[1],1)) == CONST_INT
)
4379 HOST_WIDE_INT mask
= INTVAL (XEXP (op
[1],1));
4380 if (GET_MODE (op
[1]) == SImode
)
4381 len
= (((mask
& 0xff) != 0xff)
4382 + ((mask
& 0xff00) != 0xff00)
4383 + ((mask
& 0xff0000L
) != 0xff0000L
)
4384 + ((mask
& 0xff000000L
) != 0xff000000L
));
4385 else if (GET_MODE (op
[1]) == HImode
)
4386 len
= (((mask
& 0xff) != 0xff)
4387 + ((mask
& 0xff00) != 0xff00));
4390 else if (GET_CODE (op
[1]) == IOR
)
4392 if (GET_CODE (XEXP (op
[1],1)) == CONST_INT
)
4394 HOST_WIDE_INT mask
= INTVAL (XEXP (op
[1],1));
4395 if (GET_MODE (op
[1]) == SImode
)
4396 len
= (((mask
& 0xff) != 0)
4397 + ((mask
& 0xff00) != 0)
4398 + ((mask
& 0xff0000L
) != 0)
4399 + ((mask
& 0xff000000L
) != 0));
4400 else if (GET_MODE (op
[1]) == HImode
)
4401 len
= (((mask
& 0xff) != 0)
4402 + ((mask
& 0xff00) != 0));
4406 set
= single_set (insn
);
4411 op
[1] = SET_SRC (set
);
4412 op
[0] = SET_DEST (set
);
4414 if (GET_CODE (patt
) == PARALLEL
4415 && general_operand (op
[1], VOIDmode
)
4416 && general_operand (op
[0], VOIDmode
))
4418 if (XVECLEN (patt
, 0) == 2)
4419 op
[2] = XVECEXP (patt
, 0, 1);
4421 switch (GET_MODE (op
[0]))
4427 output_reload_inhi (insn
, op
, &len
);
4431 output_reload_insisf (insn
, op
, &len
);
4437 else if (GET_CODE (op
[1]) == ASHIFT
4438 || GET_CODE (op
[1]) == ASHIFTRT
4439 || GET_CODE (op
[1]) == LSHIFTRT
)
4443 ops
[1] = XEXP (op
[1],0);
4444 ops
[2] = XEXP (op
[1],1);
4445 switch (GET_CODE (op
[1]))
4448 switch (GET_MODE (op
[0]))
4450 case QImode
: ashlqi3_out (insn
,ops
,&len
); break;
4451 case HImode
: ashlhi3_out (insn
,ops
,&len
); break;
4452 case SImode
: ashlsi3_out (insn
,ops
,&len
); break;
4457 switch (GET_MODE (op
[0]))
4459 case QImode
: ashrqi3_out (insn
,ops
,&len
); break;
4460 case HImode
: ashrhi3_out (insn
,ops
,&len
); break;
4461 case SImode
: ashrsi3_out (insn
,ops
,&len
); break;
4466 switch (GET_MODE (op
[0]))
4468 case QImode
: lshrqi3_out (insn
,ops
,&len
); break;
4469 case HImode
: lshrhi3_out (insn
,ops
,&len
); break;
4470 case SImode
: lshrsi3_out (insn
,ops
,&len
); break;
4482 /* Return nonzero if register REG dead after INSN. */
4485 reg_unused_after (rtx insn
, rtx reg
)
4487 return (dead_or_set_p (insn
, reg
)
4488 || (REG_P(reg
) && _reg_unused_after (insn
, reg
)));
4491 /* Return nonzero if REG is not used after INSN.
4492 We assume REG is a reload reg, and therefore does
4493 not live past labels. It may live past calls or jumps though. */
4496 _reg_unused_after (rtx insn
, rtx reg
)
4501 /* If the reg is set by this instruction, then it is safe for our
4502 case. Disregard the case where this is a store to memory, since
4503 we are checking a register used in the store address. */
4504 set
= single_set (insn
);
4505 if (set
&& GET_CODE (SET_DEST (set
)) != MEM
4506 && reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4509 while ((insn
= NEXT_INSN (insn
)))
4512 code
= GET_CODE (insn
);
4515 /* If this is a label that existed before reload, then the register
4516 if dead here. However, if this is a label added by reorg, then
4517 the register may still be live here. We can't tell the difference,
4518 so we just ignore labels completely. */
4519 if (code
== CODE_LABEL
)
4527 if (code
== JUMP_INSN
)
4530 /* If this is a sequence, we must handle them all at once.
4531 We could have for instance a call that sets the target register,
4532 and an insn in a delay slot that uses the register. In this case,
4533 we must return 0. */
4534 else if (code
== INSN
&& GET_CODE (PATTERN (insn
)) == SEQUENCE
)
4539 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
4541 rtx this_insn
= XVECEXP (PATTERN (insn
), 0, i
);
4542 rtx set
= single_set (this_insn
);
4544 if (GET_CODE (this_insn
) == CALL_INSN
)
4546 else if (GET_CODE (this_insn
) == JUMP_INSN
)
4548 if (INSN_ANNULLED_BRANCH_P (this_insn
))
4553 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4555 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4557 if (GET_CODE (SET_DEST (set
)) != MEM
)
4563 && reg_overlap_mentioned_p (reg
, PATTERN (this_insn
)))
4568 else if (code
== JUMP_INSN
)
4572 if (code
== CALL_INSN
)
4575 for (tem
= CALL_INSN_FUNCTION_USAGE (insn
); tem
; tem
= XEXP (tem
, 1))
4576 if (GET_CODE (XEXP (tem
, 0)) == USE
4577 && REG_P (XEXP (XEXP (tem
, 0), 0))
4578 && reg_overlap_mentioned_p (reg
, XEXP (XEXP (tem
, 0), 0)))
4580 if (call_used_regs
[REGNO (reg
)])
4584 set
= single_set (insn
);
4586 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4588 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4589 return GET_CODE (SET_DEST (set
)) != MEM
;
4590 if (set
== 0 && reg_overlap_mentioned_p (reg
, PATTERN (insn
)))
4596 /* Target hook for assembling integer objects. The AVR version needs
4597 special handling for references to certain labels. */
4600 avr_assemble_integer (rtx x
, unsigned int size
, int aligned_p
)
4602 if (size
== POINTER_SIZE
/ BITS_PER_UNIT
&& aligned_p
4603 && ((GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_FUNCTION_P (x
))
4604 || GET_CODE (x
) == LABEL_REF
))
4606 fputs ("\t.word\tgs(", asm_out_file
);
4607 output_addr_const (asm_out_file
, x
);
4608 fputs (")\n", asm_out_file
);
4611 return default_assemble_integer (x
, size
, aligned_p
);
4614 /* Worker function for ASM_DECLARE_FUNCTION_NAME. */
4617 avr_asm_declare_function_name (FILE *file
, const char *name
, tree decl
)
4620 /* If the function has the 'signal' or 'interrupt' attribute, test to
4621 make sure that the name of the function is "__vector_NN" so as to
4622 catch when the user misspells the interrupt vector name. */
4624 if (cfun
->machine
->is_interrupt
)
4626 if (strncmp (name
, "__vector", strlen ("__vector")) != 0)
4628 warning_at (DECL_SOURCE_LOCATION (decl
), 0,
4629 "%qs appears to be a misspelled interrupt handler",
4633 else if (cfun
->machine
->is_signal
)
4635 if (strncmp (name
, "__vector", strlen ("__vector")) != 0)
4637 warning_at (DECL_SOURCE_LOCATION (decl
), 0,
4638 "%qs appears to be a misspelled signal handler",
4643 ASM_OUTPUT_TYPE_DIRECTIVE (file
, name
, "function");
4644 ASM_OUTPUT_LABEL (file
, name
);
4647 /* The routine used to output NUL terminated strings. We use a special
4648 version of this for most svr4 targets because doing so makes the
4649 generated assembly code more compact (and thus faster to assemble)
4650 as well as more readable, especially for targets like the i386
4651 (where the only alternative is to output character sequences as
4652 comma separated lists of numbers). */
4655 gas_output_limited_string(FILE *file
, const char *str
)
4657 const unsigned char *_limited_str
= (const unsigned char *) str
;
4659 fprintf (file
, "%s\"", STRING_ASM_OP
);
4660 for (; (ch
= *_limited_str
); _limited_str
++)
4663 switch (escape
= ESCAPES
[ch
])
4669 fprintf (file
, "\\%03o", ch
);
4673 putc (escape
, file
);
4677 fprintf (file
, "\"\n");
4680 /* The routine used to output sequences of byte values. We use a special
4681 version of this for most svr4 targets because doing so makes the
4682 generated assembly code more compact (and thus faster to assemble)
4683 as well as more readable. Note that if we find subparts of the
4684 character sequence which end with NUL (and which are shorter than
4685 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4688 gas_output_ascii(FILE *file
, const char *str
, size_t length
)
4690 const unsigned char *_ascii_bytes
= (const unsigned char *) str
;
4691 const unsigned char *limit
= _ascii_bytes
+ length
;
4692 unsigned bytes_in_chunk
= 0;
4693 for (; _ascii_bytes
< limit
; _ascii_bytes
++)
4695 const unsigned char *p
;
4696 if (bytes_in_chunk
>= 60)
4698 fprintf (file
, "\"\n");
4701 for (p
= _ascii_bytes
; p
< limit
&& *p
!= '\0'; p
++)
4703 if (p
< limit
&& (p
- _ascii_bytes
) <= (signed)STRING_LIMIT
)
4705 if (bytes_in_chunk
> 0)
4707 fprintf (file
, "\"\n");
4710 gas_output_limited_string (file
, (const char*)_ascii_bytes
);
4717 if (bytes_in_chunk
== 0)
4718 fprintf (file
, "\t.ascii\t\"");
4719 switch (escape
= ESCAPES
[ch
= *_ascii_bytes
])
4726 fprintf (file
, "\\%03o", ch
);
4727 bytes_in_chunk
+= 4;
4731 putc (escape
, file
);
4732 bytes_in_chunk
+= 2;
4737 if (bytes_in_chunk
> 0)
4738 fprintf (file
, "\"\n");
4741 /* Return value is nonzero if pseudos that have been
4742 assigned to registers of class CLASS would likely be spilled
4743 because registers of CLASS are needed for spill registers. */
4746 class_likely_spilled_p (int c
)
4748 return (c
!= ALL_REGS
&& c
!= ADDW_REGS
);
4751 /* Valid attributes:
4752 progmem - put data to program memory;
4753 signal - make a function to be hardware interrupt. After function
4754 prologue interrupts are disabled;
4755 interrupt - make a function to be hardware interrupt. After function
4756 prologue interrupts are enabled;
4757 naked - don't generate function prologue/epilogue and `ret' command.
4759 Only `progmem' attribute valid for type. */
4761 const struct attribute_spec avr_attribute_table
[] =
4763 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4764 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute
},
4765 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4766 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4767 { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute
},
4768 { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute
},
4769 { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute
},
4770 { NULL
, 0, 0, false, false, false, NULL
}
4773 /* Handle a "progmem" attribute; arguments as in
4774 struct attribute_spec.handler. */
4776 avr_handle_progmem_attribute (tree
*node
, tree name
,
4777 tree args ATTRIBUTE_UNUSED
,
4778 int flags ATTRIBUTE_UNUSED
,
4783 if (TREE_CODE (*node
) == TYPE_DECL
)
4785 /* This is really a decl attribute, not a type attribute,
4786 but try to handle it for GCC 3.0 backwards compatibility. */
4788 tree type
= TREE_TYPE (*node
);
4789 tree attr
= tree_cons (name
, args
, TYPE_ATTRIBUTES (type
));
4790 tree newtype
= build_type_attribute_variant (type
, attr
);
4792 TYPE_MAIN_VARIANT (newtype
) = TYPE_MAIN_VARIANT (type
);
4793 TREE_TYPE (*node
) = newtype
;
4794 *no_add_attrs
= true;
4796 else if (TREE_STATIC (*node
) || DECL_EXTERNAL (*node
))
4798 if (DECL_INITIAL (*node
) == NULL_TREE
&& !DECL_EXTERNAL (*node
))
4800 warning (0, "only initialized variables can be placed into "
4801 "program memory area");
4802 *no_add_attrs
= true;
4807 warning (OPT_Wattributes
, "%qs attribute ignored",
4808 IDENTIFIER_POINTER (name
));
4809 *no_add_attrs
= true;
4816 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4817 struct attribute_spec.handler. */
4820 avr_handle_fndecl_attribute (tree
*node
, tree name
,
4821 tree args ATTRIBUTE_UNUSED
,
4822 int flags ATTRIBUTE_UNUSED
,
4825 if (TREE_CODE (*node
) != FUNCTION_DECL
)
4827 warning (OPT_Wattributes
, "%qs attribute only applies to functions",
4828 IDENTIFIER_POINTER (name
));
4829 *no_add_attrs
= true;
4836 avr_handle_fntype_attribute (tree
*node
, tree name
,
4837 tree args ATTRIBUTE_UNUSED
,
4838 int flags ATTRIBUTE_UNUSED
,
4841 if (TREE_CODE (*node
) != FUNCTION_TYPE
)
4843 warning (OPT_Wattributes
, "%qs attribute only applies to functions",
4844 IDENTIFIER_POINTER (name
));
4845 *no_add_attrs
= true;
4851 /* Look for attribute `progmem' in DECL
4852 if found return 1, otherwise 0. */
4855 avr_progmem_p (tree decl
, tree attributes
)
4859 if (TREE_CODE (decl
) != VAR_DECL
)
4863 != lookup_attribute ("progmem", attributes
))
4869 while (TREE_CODE (a
) == ARRAY_TYPE
);
4871 if (a
== error_mark_node
)
4874 if (NULL_TREE
!= lookup_attribute ("progmem", TYPE_ATTRIBUTES (a
)))
4880 /* Add the section attribute if the variable is in progmem. */
4883 avr_insert_attributes (tree node
, tree
*attributes
)
4885 if (TREE_CODE (node
) == VAR_DECL
4886 && (TREE_STATIC (node
) || DECL_EXTERNAL (node
))
4887 && avr_progmem_p (node
, *attributes
))
4889 static const char dsec
[] = ".progmem.data";
4890 *attributes
= tree_cons (get_identifier ("section"),
4891 build_tree_list (NULL
, build_string (strlen (dsec
), dsec
)),
4894 /* ??? This seems sketchy. Why can't the user declare the
4895 thing const in the first place? */
4896 TREE_READONLY (node
) = 1;
4900 /* A get_unnamed_section callback for switching to progmem_section. */
4903 avr_output_progmem_section_asm_op (const void *arg ATTRIBUTE_UNUSED
)
4905 fprintf (asm_out_file
,
4906 "\t.section .progmem.gcc_sw_table, \"%s\", @progbits\n",
4907 AVR_HAVE_JMP_CALL
? "a" : "ax");
4908 /* Should already be aligned, this is just to be safe if it isn't. */
4909 fprintf (asm_out_file
, "\t.p2align 1\n");
4912 /* Implement TARGET_ASM_INIT_SECTIONS. */
4915 avr_asm_init_sections (void)
4917 progmem_section
= get_unnamed_section (AVR_HAVE_JMP_CALL
? 0 : SECTION_CODE
,
4918 avr_output_progmem_section_asm_op
,
4920 readonly_data_section
= data_section
;
4924 avr_section_type_flags (tree decl
, const char *name
, int reloc
)
4926 unsigned int flags
= default_section_type_flags (decl
, name
, reloc
);
4928 if (strncmp (name
, ".noinit", 7) == 0)
4930 if (decl
&& TREE_CODE (decl
) == VAR_DECL
4931 && DECL_INITIAL (decl
) == NULL_TREE
)
4932 flags
|= SECTION_BSS
; /* @nobits */
4934 warning (0, "only uninitialized variables can be placed in the "
4941 /* Outputs some appropriate text to go at the start of an assembler
4945 avr_file_start (void)
4947 if (avr_current_arch
->asm_only
)
4948 error ("MCU %qs supported for assembler only", avr_mcu_name
);
4950 default_file_start ();
4952 /* fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);*/
4953 fputs ("__SREG__ = 0x3f\n"
4955 "__SP_L__ = 0x3d\n", asm_out_file
);
4957 fputs ("__tmp_reg__ = 0\n"
4958 "__zero_reg__ = 1\n", asm_out_file
);
4960 /* FIXME: output these only if there is anything in the .data / .bss
4961 sections - some code size could be saved by not linking in the
4962 initialization code from libgcc if one or both sections are empty. */
4963 fputs ("\t.global __do_copy_data\n", asm_out_file
);
4964 fputs ("\t.global __do_clear_bss\n", asm_out_file
);
4967 /* Outputs to the stdio stream FILE some
4968 appropriate text to go at the end of an assembler file. */
4975 /* Choose the order in which to allocate hard registers for
4976 pseudo-registers local to a basic block.
4978 Store the desired register order in the array `reg_alloc_order'.
4979 Element 0 should be the register to allocate first; element 1, the
4980 next register; and so on. */
4983 order_regs_for_local_alloc (void)
4986 static const int order_0
[] = {
4994 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4998 static const int order_1
[] = {
5006 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
5010 static const int order_2
[] = {
5019 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
5024 const int *order
= (TARGET_ORDER_1
? order_1
:
5025 TARGET_ORDER_2
? order_2
:
5027 for (i
=0; i
< ARRAY_SIZE (order_0
); ++i
)
5028 reg_alloc_order
[i
] = order
[i
];
5032 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
5033 cost of an RTX operand given its context. X is the rtx of the
5034 operand, MODE is its mode, and OUTER is the rtx_code of this
5035 operand's parent operator. */
5038 avr_operand_rtx_cost (rtx x
, enum machine_mode mode
, enum rtx_code outer
,
5041 enum rtx_code code
= GET_CODE (x
);
5052 return COSTS_N_INSNS (GET_MODE_SIZE (mode
));
5059 avr_rtx_costs (x
, code
, outer
, &total
, speed
);
5063 /* The AVR backend's rtx_cost function. X is rtx expression whose cost
5064 is to be calculated. Return true if the complete cost has been
5065 computed, and false if subexpressions should be scanned. In either
5066 case, *TOTAL contains the cost result. */
5069 avr_rtx_costs (rtx x
, int code
, int outer_code ATTRIBUTE_UNUSED
, int *total
,
5072 enum machine_mode mode
= GET_MODE (x
);
5079 /* Immediate constants are as cheap as registers. */
5087 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
5095 *total
= COSTS_N_INSNS (1);
5099 *total
= COSTS_N_INSNS (3);
5103 *total
= COSTS_N_INSNS (7);
5109 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5117 *total
= COSTS_N_INSNS (1);
5123 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5127 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
5128 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5132 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
)
5133 - GET_MODE_SIZE (GET_MODE (XEXP (x
, 0))));
5134 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5138 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) + 2
5139 - GET_MODE_SIZE (GET_MODE (XEXP (x
, 0))));
5140 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5147 *total
= COSTS_N_INSNS (1);
5148 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5149 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5153 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5155 *total
= COSTS_N_INSNS (2);
5156 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5158 else if (INTVAL (XEXP (x
, 1)) >= -63 && INTVAL (XEXP (x
, 1)) <= 63)
5159 *total
= COSTS_N_INSNS (1);
5161 *total
= COSTS_N_INSNS (2);
5165 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5167 *total
= COSTS_N_INSNS (4);
5168 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5170 else if (INTVAL (XEXP (x
, 1)) >= -63 && INTVAL (XEXP (x
, 1)) <= 63)
5171 *total
= COSTS_N_INSNS (1);
5173 *total
= COSTS_N_INSNS (4);
5179 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5185 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
5186 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5187 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5188 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5192 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
5193 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5194 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5202 *total
= COSTS_N_INSNS (!speed
? 3 : 4);
5204 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 2 : 1);
5211 *total
= COSTS_N_INSNS (!speed
? 7 : 10);
5213 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 2 : 1);
5221 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5222 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5230 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 2 : 1);
5233 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5234 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5241 if (CONST_INT_P (XEXP (x
, 1)) && INTVAL (XEXP (x
, 1)) == 4)
5242 *total
= COSTS_N_INSNS (1);
5247 if (CONST_INT_P (XEXP (x
, 1)) && INTVAL (XEXP (x
, 1)) == 8)
5248 *total
= COSTS_N_INSNS (3);
5253 if (CONST_INT_P (XEXP (x
, 1)))
5254 switch (INTVAL (XEXP (x
, 1)))
5258 *total
= COSTS_N_INSNS (5);
5261 *total
= COSTS_N_INSNS (AVR_HAVE_MOVW
? 4 : 6);
5269 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5276 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5278 *total
= COSTS_N_INSNS (!speed
? 4 : 17);
5279 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5283 val
= INTVAL (XEXP (x
, 1));
5285 *total
= COSTS_N_INSNS (3);
5286 else if (val
>= 0 && val
<= 7)
5287 *total
= COSTS_N_INSNS (val
);
5289 *total
= COSTS_N_INSNS (1);
5294 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5296 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
5297 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5300 switch (INTVAL (XEXP (x
, 1)))
5307 *total
= COSTS_N_INSNS (2);
5310 *total
= COSTS_N_INSNS (3);
5316 *total
= COSTS_N_INSNS (4);
5321 *total
= COSTS_N_INSNS (5);
5324 *total
= COSTS_N_INSNS (!speed
? 5 : 8);
5327 *total
= COSTS_N_INSNS (!speed
? 5 : 9);
5330 *total
= COSTS_N_INSNS (!speed
? 5 : 10);
5333 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
5334 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5339 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5341 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
5342 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5345 switch (INTVAL (XEXP (x
, 1)))
5351 *total
= COSTS_N_INSNS (3);
5356 *total
= COSTS_N_INSNS (4);
5359 *total
= COSTS_N_INSNS (6);
5362 *total
= COSTS_N_INSNS (!speed
? 7 : 8);
5365 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
5366 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5373 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5380 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5382 *total
= COSTS_N_INSNS (!speed
? 4 : 17);
5383 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5387 val
= INTVAL (XEXP (x
, 1));
5389 *total
= COSTS_N_INSNS (4);
5391 *total
= COSTS_N_INSNS (2);
5392 else if (val
>= 0 && val
<= 7)
5393 *total
= COSTS_N_INSNS (val
);
5395 *total
= COSTS_N_INSNS (1);
5400 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5402 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
5403 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5406 switch (INTVAL (XEXP (x
, 1)))
5412 *total
= COSTS_N_INSNS (2);
5415 *total
= COSTS_N_INSNS (3);
5421 *total
= COSTS_N_INSNS (4);
5425 *total
= COSTS_N_INSNS (5);
5428 *total
= COSTS_N_INSNS (!speed
? 5 : 6);
5431 *total
= COSTS_N_INSNS (!speed
? 5 : 7);
5435 *total
= COSTS_N_INSNS (!speed
? 5 : 8);
5438 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
5439 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5444 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5446 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
5447 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5450 switch (INTVAL (XEXP (x
, 1)))
5456 *total
= COSTS_N_INSNS (4);
5461 *total
= COSTS_N_INSNS (6);
5464 *total
= COSTS_N_INSNS (!speed
? 7 : 8);
5467 *total
= COSTS_N_INSNS (AVR_HAVE_MOVW
? 4 : 5);
5470 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
5471 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5478 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5485 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5487 *total
= COSTS_N_INSNS (!speed
? 4 : 17);
5488 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5492 val
= INTVAL (XEXP (x
, 1));
5494 *total
= COSTS_N_INSNS (3);
5495 else if (val
>= 0 && val
<= 7)
5496 *total
= COSTS_N_INSNS (val
);
5498 *total
= COSTS_N_INSNS (1);
5503 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5505 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
5506 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5509 switch (INTVAL (XEXP (x
, 1)))
5516 *total
= COSTS_N_INSNS (2);
5519 *total
= COSTS_N_INSNS (3);
5524 *total
= COSTS_N_INSNS (4);
5528 *total
= COSTS_N_INSNS (5);
5534 *total
= COSTS_N_INSNS (!speed
? 5 : 6);
5537 *total
= COSTS_N_INSNS (!speed
? 5 : 7);
5541 *total
= COSTS_N_INSNS (!speed
? 5 : 9);
5544 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
5545 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5550 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5552 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
5553 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5556 switch (INTVAL (XEXP (x
, 1)))
5562 *total
= COSTS_N_INSNS (4);
5565 *total
= COSTS_N_INSNS (!speed
? 7 : 8);
5570 *total
= COSTS_N_INSNS (4);
5573 *total
= COSTS_N_INSNS (6);
5576 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
5577 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5584 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5588 switch (GET_MODE (XEXP (x
, 0)))
5591 *total
= COSTS_N_INSNS (1);
5592 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5593 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5597 *total
= COSTS_N_INSNS (2);
5598 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5599 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5600 else if (INTVAL (XEXP (x
, 1)) != 0)
5601 *total
+= COSTS_N_INSNS (1);
5605 *total
= COSTS_N_INSNS (4);
5606 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5607 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5608 else if (INTVAL (XEXP (x
, 1)) != 0)
5609 *total
+= COSTS_N_INSNS (3);
5615 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5624 /* Calculate the cost of a memory address. */
5627 avr_address_cost (rtx x
, bool speed ATTRIBUTE_UNUSED
)
5629 if (GET_CODE (x
) == PLUS
5630 && GET_CODE (XEXP (x
,1)) == CONST_INT
5631 && (REG_P (XEXP (x
,0)) || GET_CODE (XEXP (x
,0)) == SUBREG
)
5632 && INTVAL (XEXP (x
,1)) >= 61)
5634 if (CONSTANT_ADDRESS_P (x
))
5636 if (optimize
> 0 && io_address_operand (x
, QImode
))
5643 /* Test for extra memory constraint 'Q'.
5644 It's a memory address based on Y or Z pointer with valid displacement. */
5647 extra_constraint_Q (rtx x
)
5649 if (GET_CODE (XEXP (x
,0)) == PLUS
5650 && REG_P (XEXP (XEXP (x
,0), 0))
5651 && GET_CODE (XEXP (XEXP (x
,0), 1)) == CONST_INT
5652 && (INTVAL (XEXP (XEXP (x
,0), 1))
5653 <= MAX_LD_OFFSET (GET_MODE (x
))))
5655 rtx xx
= XEXP (XEXP (x
,0), 0);
5656 int regno
= REGNO (xx
);
5657 if (TARGET_ALL_DEBUG
)
5659 fprintf (stderr
, ("extra_constraint:\n"
5660 "reload_completed: %d\n"
5661 "reload_in_progress: %d\n"),
5662 reload_completed
, reload_in_progress
);
5665 if (regno
>= FIRST_PSEUDO_REGISTER
)
5666 return 1; /* allocate pseudos */
5667 else if (regno
== REG_Z
|| regno
== REG_Y
)
5668 return 1; /* strictly check */
5669 else if (xx
== frame_pointer_rtx
5670 || xx
== arg_pointer_rtx
)
5671 return 1; /* XXX frame & arg pointer checks */
5676 /* Convert condition code CONDITION to the valid AVR condition code. */
5679 avr_normalize_condition (RTX_CODE condition
)
5696 /* This function optimizes conditional jumps. */
5703 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5705 if (! (GET_CODE (insn
) == INSN
5706 || GET_CODE (insn
) == CALL_INSN
5707 || GET_CODE (insn
) == JUMP_INSN
)
5708 || !single_set (insn
))
5711 pattern
= PATTERN (insn
);
5713 if (GET_CODE (pattern
) == PARALLEL
)
5714 pattern
= XVECEXP (pattern
, 0, 0);
5715 if (GET_CODE (pattern
) == SET
5716 && SET_DEST (pattern
) == cc0_rtx
5717 && compare_diff_p (insn
))
5719 if (GET_CODE (SET_SRC (pattern
)) == COMPARE
)
5721 /* Now we work under compare insn. */
5723 pattern
= SET_SRC (pattern
);
5724 if (true_regnum (XEXP (pattern
,0)) >= 0
5725 && true_regnum (XEXP (pattern
,1)) >= 0 )
5727 rtx x
= XEXP (pattern
,0);
5728 rtx next
= next_real_insn (insn
);
5729 rtx pat
= PATTERN (next
);
5730 rtx src
= SET_SRC (pat
);
5731 rtx t
= XEXP (src
,0);
5732 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
5733 XEXP (pattern
,0) = XEXP (pattern
,1);
5734 XEXP (pattern
,1) = x
;
5735 INSN_CODE (next
) = -1;
5737 else if (true_regnum (XEXP (pattern
,0)) >= 0
5738 && GET_CODE (XEXP (pattern
,1)) == CONST_INT
)
5740 rtx x
= XEXP (pattern
,1);
5741 rtx next
= next_real_insn (insn
);
5742 rtx pat
= PATTERN (next
);
5743 rtx src
= SET_SRC (pat
);
5744 rtx t
= XEXP (src
,0);
5745 enum machine_mode mode
= GET_MODE (XEXP (pattern
, 0));
5747 if (avr_simplify_comparison_p (mode
, GET_CODE (t
), x
))
5749 XEXP (pattern
, 1) = gen_int_mode (INTVAL (x
) + 1, mode
);
5750 PUT_CODE (t
, avr_normalize_condition (GET_CODE (t
)));
5751 INSN_CODE (next
) = -1;
5752 INSN_CODE (insn
) = -1;
5756 else if (true_regnum (SET_SRC (pattern
)) >= 0)
5758 /* This is a tst insn */
5759 rtx next
= next_real_insn (insn
);
5760 rtx pat
= PATTERN (next
);
5761 rtx src
= SET_SRC (pat
);
5762 rtx t
= XEXP (src
,0);
5764 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
5765 SET_SRC (pattern
) = gen_rtx_COMPARE (GET_MODE (SET_SRC (pattern
)), const0_rtx
,
5767 INSN_CODE (next
) = -1;
5768 INSN_CODE (insn
) = -1;
5774 /* Returns register number for function return value.*/
5777 avr_ret_register (void)
5782 /* Create an RTX representing the place where a
5783 library function returns a value of mode MODE. */
5786 avr_libcall_value (enum machine_mode mode
)
5788 int offs
= GET_MODE_SIZE (mode
);
5791 return gen_rtx_REG (mode
, RET_REGISTER
+ 2 - offs
);
5794 /* Create an RTX representing the place where a
5795 function returns a value of data type VALTYPE. */
5798 avr_function_value (const_tree type
,
5799 const_tree func ATTRIBUTE_UNUSED
,
5800 bool outgoing ATTRIBUTE_UNUSED
)
5804 if (TYPE_MODE (type
) != BLKmode
)
5805 return avr_libcall_value (TYPE_MODE (type
));
5807 offs
= int_size_in_bytes (type
);
5810 if (offs
> 2 && offs
< GET_MODE_SIZE (SImode
))
5811 offs
= GET_MODE_SIZE (SImode
);
5812 else if (offs
> GET_MODE_SIZE (SImode
) && offs
< GET_MODE_SIZE (DImode
))
5813 offs
= GET_MODE_SIZE (DImode
);
5815 return gen_rtx_REG (BLKmode
, RET_REGISTER
+ 2 - offs
);
5818 /* Places additional restrictions on the register class to
5819 use when it is necessary to copy value X into a register
5823 preferred_reload_class (rtx x ATTRIBUTE_UNUSED
, enum reg_class rclass
)
5829 test_hard_reg_class (enum reg_class rclass
, rtx x
)
5831 int regno
= true_regnum (x
);
5835 if (TEST_HARD_REG_CLASS (rclass
, regno
))
5843 jump_over_one_insn_p (rtx insn
, rtx dest
)
5845 int uid
= INSN_UID (GET_CODE (dest
) == LABEL_REF
5848 int jump_addr
= INSN_ADDRESSES (INSN_UID (insn
));
5849 int dest_addr
= INSN_ADDRESSES (uid
);
5850 return dest_addr
- jump_addr
== get_attr_length (insn
) + 1;
5853 /* Returns 1 if a value of mode MODE can be stored starting with hard
5854 register number REGNO. On the enhanced core, anything larger than
5855 1 byte must start in even numbered register for "movw" to work
5856 (this way we don't have to check for odd registers everywhere). */
5859 avr_hard_regno_mode_ok (int regno
, enum machine_mode mode
)
5861 /* Disallow QImode in stack pointer regs. */
5862 if ((regno
== REG_SP
|| regno
== (REG_SP
+ 1)) && mode
== QImode
)
5865 /* The only thing that can go into registers r28:r29 is a Pmode. */
5866 if (regno
== REG_Y
&& mode
== Pmode
)
5869 /* Otherwise disallow all regno/mode combinations that span r28:r29. */
5870 if (regno
<= (REG_Y
+ 1) && (regno
+ GET_MODE_SIZE (mode
)) >= (REG_Y
+ 1))
5876 /* Modes larger than QImode occupy consecutive registers. */
5877 if (regno
+ GET_MODE_SIZE (mode
) > FIRST_PSEUDO_REGISTER
)
5880 /* All modes larger than QImode should start in an even register. */
5881 return !(regno
& 1);
5885 output_reload_inhi (rtx insn ATTRIBUTE_UNUSED
, rtx
*operands
, int *len
)
5891 if (GET_CODE (operands
[1]) == CONST_INT
)
5893 int val
= INTVAL (operands
[1]);
5894 if ((val
& 0xff) == 0)
5897 return (AS2 (mov
,%A0
,__zero_reg__
) CR_TAB
5898 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5901 else if ((val
& 0xff00) == 0)
5904 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5905 AS2 (mov
,%A0
,%2) CR_TAB
5906 AS2 (mov
,%B0
,__zero_reg__
));
5908 else if ((val
& 0xff) == ((val
& 0xff00) >> 8))
5911 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5912 AS2 (mov
,%A0
,%2) CR_TAB
5917 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5918 AS2 (mov
,%A0
,%2) CR_TAB
5919 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5925 output_reload_insisf (rtx insn ATTRIBUTE_UNUSED
, rtx
*operands
, int *len
)
5927 rtx src
= operands
[1];
5928 int cnst
= (GET_CODE (src
) == CONST_INT
);
5933 *len
= 4 + ((INTVAL (src
) & 0xff) != 0)
5934 + ((INTVAL (src
) & 0xff00) != 0)
5935 + ((INTVAL (src
) & 0xff0000) != 0)
5936 + ((INTVAL (src
) & 0xff000000) != 0);
5943 if (cnst
&& ((INTVAL (src
) & 0xff) == 0))
5944 output_asm_insn (AS2 (mov
, %A0
, __zero_reg__
), operands
);
5947 output_asm_insn (AS2 (ldi
, %2, lo8(%1)), operands
);
5948 output_asm_insn (AS2 (mov
, %A0
, %2), operands
);
5950 if (cnst
&& ((INTVAL (src
) & 0xff00) == 0))
5951 output_asm_insn (AS2 (mov
, %B0
, __zero_reg__
), operands
);
5954 output_asm_insn (AS2 (ldi
, %2, hi8(%1)), operands
);
5955 output_asm_insn (AS2 (mov
, %B0
, %2), operands
);
5957 if (cnst
&& ((INTVAL (src
) & 0xff0000) == 0))
5958 output_asm_insn (AS2 (mov
, %C0
, __zero_reg__
), operands
);
5961 output_asm_insn (AS2 (ldi
, %2, hlo8(%1)), operands
);
5962 output_asm_insn (AS2 (mov
, %C0
, %2), operands
);
5964 if (cnst
&& ((INTVAL (src
) & 0xff000000) == 0))
5965 output_asm_insn (AS2 (mov
, %D0
, __zero_reg__
), operands
);
5968 output_asm_insn (AS2 (ldi
, %2, hhi8(%1)), operands
);
5969 output_asm_insn (AS2 (mov
, %D0
, %2), operands
);
5975 avr_output_bld (rtx operands
[], int bit_nr
)
5977 static char s
[] = "bld %A0,0";
5979 s
[5] = 'A' + (bit_nr
>> 3);
5980 s
[8] = '0' + (bit_nr
& 7);
5981 output_asm_insn (s
, operands
);
5985 avr_output_addr_vec_elt (FILE *stream
, int value
)
5987 switch_to_section (progmem_section
);
5988 if (AVR_HAVE_JMP_CALL
)
5989 fprintf (stream
, "\t.word gs(.L%d)\n", value
);
5991 fprintf (stream
, "\trjmp .L%d\n", value
);
5994 /* Returns true if SCRATCH are safe to be allocated as a scratch
5995 registers (for a define_peephole2) in the current function. */
5998 avr_hard_regno_scratch_ok (unsigned int regno
)
6000 /* Interrupt functions can only use registers that have already been saved
6001 by the prologue, even if they would normally be call-clobbered. */
6003 if ((cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
6004 && !df_regs_ever_live_p (regno
))
6010 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
6013 avr_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED
,
6014 unsigned int new_reg
)
6016 /* Interrupt functions can only use registers that have already been
6017 saved by the prologue, even if they would normally be
6020 if ((cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
6021 && !df_regs_ever_live_p (new_reg
))
6027 /* Output a branch that tests a single bit of a register (QI, HI or SImode)
6028 or memory location in the I/O space (QImode only).
6030 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
6031 Operand 1: register operand to test, or CONST_INT memory address.
6032 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
6033 Operand 3: label to jump to if the test is true. */
6036 avr_out_sbxx_branch (rtx insn
, rtx operands
[])
6038 enum rtx_code comp
= GET_CODE (operands
[0]);
6039 int long_jump
= (get_attr_length (insn
) >= 4);
6040 int reverse
= long_jump
|| jump_over_one_insn_p (insn
, operands
[3]);
6044 else if (comp
== LT
)
6048 comp
= reverse_condition (comp
);
6050 if (GET_CODE (operands
[1]) == CONST_INT
)
6052 if (INTVAL (operands
[1]) < 0x40)
6055 output_asm_insn (AS2 (sbis
,%1-0x20,%2), operands
);
6057 output_asm_insn (AS2 (sbic
,%1-0x20,%2), operands
);
6061 output_asm_insn (AS2 (in
,__tmp_reg__
,%1-0x20), operands
);
6063 output_asm_insn (AS2 (sbrs
,__tmp_reg__
,%2), operands
);
6065 output_asm_insn (AS2 (sbrc
,__tmp_reg__
,%2), operands
);
6068 else /* GET_CODE (operands[1]) == REG */
6070 if (GET_MODE (operands
[1]) == QImode
)
6073 output_asm_insn (AS2 (sbrs
,%1,%2), operands
);
6075 output_asm_insn (AS2 (sbrc
,%1,%2), operands
);
6077 else /* HImode or SImode */
6079 static char buf
[] = "sbrc %A1,0";
6080 int bit_nr
= exact_log2 (INTVAL (operands
[2])
6081 & GET_MODE_MASK (GET_MODE (operands
[1])));
6083 buf
[3] = (comp
== EQ
) ? 's' : 'c';
6084 buf
[6] = 'A' + (bit_nr
>> 3);
6085 buf
[9] = '0' + (bit_nr
& 7);
6086 output_asm_insn (buf
, operands
);
6091 return (AS1 (rjmp
,.+4) CR_TAB
6094 return AS1 (rjmp
,%3);
6098 /* Worker function for TARGET_ASM_CONSTRUCTOR. */
6101 avr_asm_out_ctor (rtx symbol
, int priority
)
6103 fputs ("\t.global __do_global_ctors\n", asm_out_file
);
6104 default_ctor_section_asm_out_constructor (symbol
, priority
);
6107 /* Worker function for TARGET_ASM_DESTRUCTOR. */
6110 avr_asm_out_dtor (rtx symbol
, int priority
)
6112 fputs ("\t.global __do_global_dtors\n", asm_out_file
);
6113 default_dtor_section_asm_out_destructor (symbol
, priority
);
6116 /* Worker function for TARGET_RETURN_IN_MEMORY. */
6119 avr_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
6121 if (TYPE_MODE (type
) == BLKmode
)
6123 HOST_WIDE_INT size
= int_size_in_bytes (type
);
6124 return (size
== -1 || size
> 8);
6130 /* Worker function for CASE_VALUES_THRESHOLD. */
6132 unsigned int avr_case_values_threshold (void)
6134 return (!AVR_HAVE_JMP_CALL
|| TARGET_CALL_PROLOGUES
) ? 8 : 17;