tm.texi (LEGITIMIZE_ADDRESS): Revise documentation.
[official-gcc.git] / gcc / config / avr / avr.c
blob449c0ee4f89da6f6d31e9c9f9f3878eeb4dcff14
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)
11 any later version.
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/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "real.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-attr.h"
33 #include "flags.h"
34 #include "reload.h"
35 #include "tree.h"
36 #include "output.h"
37 #include "expr.h"
38 #include "toplev.h"
39 #include "obstack.h"
40 #include "function.h"
41 #include "recog.h"
42 #include "ggc.h"
43 #include "tm_p.h"
44 #include "target.h"
45 #include "target-def.h"
46 #include "params.h"
47 #include "df.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
131 above. */
133 enum avr_arch
135 ARCH_UNKNOWN,
136 ARCH_AVR1,
137 ARCH_AVR2,
138 ARCH_AVR25,
139 ARCH_AVR3,
140 ARCH_AVR31,
141 ARCH_AVR35,
142 ARCH_AVR4,
143 ARCH_AVR5,
144 ARCH_AVR51,
145 ARCH_AVR6
148 struct mcu_type_s {
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?):
157 - here
158 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
159 - t-avr (MULTILIB_MATCHES)
160 - gas/config/tc-avr.c
161 - avr-libc */
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__" },
299 /* 3-Byte PC. */
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;
372 void
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)
384 break;
386 if (!t->name)
388 fprintf (stderr, "unknown MCU '%s' specified\nKnown MCU names:\n",
389 avr_mcu_name);
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. */
430 enum reg_class
431 avr_regno_reg_class (int r)
433 if (r <= 33)
434 return reg_class_tab[r];
435 return ALL_REGS;
438 /* Return nonzero if FUNC is a naked function. */
440 static int
441 avr_naked_function_p (tree func)
443 tree a;
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. */
454 static int
455 interrupt_function_p (tree func)
457 tree a;
459 if (TREE_CODE (func) != FUNCTION_DECL)
460 return 0;
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. */
469 static int
470 signal_function_p (tree func)
472 tree a;
474 if (TREE_CODE (func) != FUNCTION_DECL)
475 return 0;
477 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
478 return a != NULL_TREE;
481 /* Return nonzero if FUNC is a OS_task function. */
483 static int
484 avr_OS_task_function_p (tree func)
486 tree a;
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. */
496 static int
497 avr_OS_main_function_p (tree func)
499 tree a;
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. */
510 static int
511 avr_regs_to_save (HARD_REG_SET *set)
513 int reg, count;
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 ();
520 if (set)
521 CLEAR_HARD_REG_SET (*set);
522 count = 0;
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)
529 return 0;
531 for (reg = 0; reg < 32; reg++)
533 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
534 any global register variables. */
535 if (fixed_regs[reg])
536 continue;
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)))))
544 if (set)
545 SET_HARD_REG_BIT (*set, reg);
546 count++;
549 return count;
552 /* Return true if register FROM can be eliminated via register TO. */
554 bool
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)
569 return 0;
570 else
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. */
607 static int
608 sequent_regs_live (void)
610 int reg;
611 int live_seq=0;
612 int cur_seq=0;
614 for (reg = 0; reg < 18; ++reg)
616 if (!call_used_regs[reg])
618 if (df_regs_ever_live_p (reg))
620 ++live_seq;
621 ++cur_seq;
623 else
624 cur_seq = 0;
628 if (!frame_pointer_needed)
630 if (df_regs_ever_live_p (REG_Y))
632 ++live_seq;
633 ++cur_seq;
635 else
636 cur_seq = 0;
638 if (df_regs_ever_live_p (REG_Y+1))
640 ++live_seq;
641 ++cur_seq;
643 else
644 cur_seq = 0;
646 else
648 cur_seq += 2;
649 live_seq += 2;
651 return (cur_seq == live_seq) ? live_seq : 0;
654 /* Obtain the length sequence of insns. */
657 get_sequence_length (rtx insns)
659 rtx insn;
660 int length;
662 for (insn = insns, length = 0; insn; insn = NEXT_INSN (insn))
663 length += get_attr_length (insn);
665 return length;
668 /* Output function prologue. */
670 void
671 expand_prologue (void)
673 int live_seq;
674 HARD_REG_SET set;
675 int minimize;
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));
682 rtx insn;
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)
696 return;
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
706 && live_seq);
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;
717 /* Push zero reg. */
718 insn = emit_move_insn (pushbyte, zero_reg_rtx);
719 RTX_FRAME_RELATED_P (insn) = 1;
721 /* Push tmp reg. */
722 insn = emit_move_insn (pushbyte, tmp_reg_rtx);
723 RTX_FRAME_RELATED_P (insn) = 1;
725 /* Push SREG. */
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;
732 /* Push RAMPZ. */
733 if(AVR_HAVE_RAMPZ
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)
752 || live_seq > 7))
754 insn = emit_move_insn (gen_rtx_REG (HImode, REG_X),
755 gen_int_mode (size, HImode));
756 RTX_FRAME_RELATED_P (insn) = 1;
758 insn =
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;
763 else
765 int reg;
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;
784 if (!size)
786 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
787 RTX_FRAME_RELATED_P (insn) = 1;
789 else
791 /* Creating a frame can be done by direct manipulation of the
792 stack or via the frame pointer. These two methods are:
793 fp=sp
794 fp-=size
795 sp=fp
797 sp-=size
798 fp=sp
799 the optimum method depends on function type, stack and frame size.
800 To avoid a complex logic, both methods are tested and shortest
801 is selected. */
802 rtx myfp;
803 rtx fp_plus_insns;
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));
812 else
814 /* Normal sized addition. */
815 myfp = frame_pointer_rtx;
818 /* Method 1-Adjust frame pointer. */
819 start_sequence ();
821 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
822 RTX_FRAME_RELATED_P (insn) = 1;
824 insn =
825 emit_move_insn (myfp,
826 gen_rtx_PLUS (GET_MODE(myfp), myfp,
827 gen_int_mode (-size,
828 GET_MODE(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)
841 insn =
842 emit_insn (gen_movhi_sp_r_irq_off (stack_pointer_rtx,
843 frame_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,
849 frame_pointer_rtx));
850 RTX_FRAME_RELATED_P (insn) = 1;
852 else
854 insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
855 RTX_FRAME_RELATED_P (insn) = 1;
858 fp_plus_insns = get_insns ();
859 end_sequence ();
861 /* Method 2-Adjust Stack pointer. */
862 if (size <= 6)
864 start_sequence ();
866 insn =
867 emit_move_insn (stack_pointer_rtx,
868 gen_rtx_PLUS (HImode,
869 stack_pointer_rtx,
870 gen_int_mode (-size,
871 HImode)));
872 RTX_FRAME_RELATED_P (insn) = 1;
874 insn =
875 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
876 RTX_FRAME_RELATED_P (insn) = 1;
878 sp_plus_insns = get_insns ();
879 end_sequence ();
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);
886 else
887 emit_insn (fp_plus_insns);
893 /* Output summary at end of function prologue. */
895 static void
896 avr_asm_function_end_prologue (FILE *file)
898 if (cfun->machine->is_naked)
900 fputs ("/* prologue: naked */\n", file);
902 else
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);
912 else
913 fputs ("/* prologue: function */\n", file);
915 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
916 get_frame_size());
920 /* Implement EPILOGUE_USES. */
923 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
925 if (reload_completed
926 && cfun->machine
927 && (cfun->machine->is_interrupt || cfun->machine->is_signal))
928 return 1;
929 return 0;
932 /* Output RTL epilogue. */
934 void
935 expand_epilogue (void)
937 int reg;
938 int live_seq;
939 HARD_REG_SET set;
940 int minimize;
941 HOST_WIDE_INT size = get_frame_size();
943 /* epilogue: naked */
944 if (cfun->machine->is_naked)
946 emit_jump_insn (gen_return ());
947 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
957 && live_seq);
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)));
968 else
970 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
973 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
975 else
977 if (frame_pointer_needed)
979 if (size)
981 /* Try two methods to adjust stack and select shortest. */
982 rtx myfp;
983 rtx fp_plus_insns;
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));
992 else
994 /* Normal sized addition. */
995 myfp = frame_pointer_rtx;
998 /* Method 1-Adjust frame pointer. */
999 start_sequence ();
1001 emit_move_insn (myfp,
1002 gen_rtx_PLUS (HImode, myfp,
1003 gen_int_mode (size,
1004 GET_MODE(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));
1022 else
1024 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
1027 fp_plus_insns = get_insns ();
1028 end_sequence ();
1030 /* Method 2-Adjust Stack pointer. */
1031 if (size <= 5)
1033 start_sequence ();
1035 emit_move_insn (stack_pointer_rtx,
1036 gen_rtx_PLUS (HImode, stack_pointer_rtx,
1037 gen_int_mode (size,
1038 HImode)));
1040 sp_plus_insns = get_insns ();
1041 end_sequence ();
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);
1048 else
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. */
1066 if(AVR_HAVE_RAMPZ
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)),
1071 tmp_reg_rtx);
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)),
1078 tmp_reg_rtx);
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. */
1093 static void
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)
1120 && reg_renumber
1122 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
1123 true_regnum (XEXP (x, 0)));
1124 debug_rtx (x);
1126 if (!strict && GET_CODE (x) == SUBREG)
1127 x = SUBREG_REG (x);
1128 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
1129 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
1130 r = POINTER_REGS;
1131 else if (CONSTANT_ADDRESS_P (x))
1132 r = ALL_REGS;
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);
1139 if (fit)
1141 if (! strict
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)
1151 r = POINTER_Y_REGS;
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))))
1158 r = POINTER_REGS;
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)
1173 x = oldx;
1174 if (TARGET_ALL_DEBUG)
1176 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
1177 debug_rtx (oldx);
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);
1197 return x;
1201 /* Return a pointer register name as a string. */
1203 static const char *
1204 ptrreg_to_str (int regno)
1206 switch (regno)
1208 case REG_X: return "X";
1209 case REG_Y: return "Y";
1210 case REG_Z: return "Z";
1211 default:
1212 output_operand_lossage ("address operand requires constraint for X, Y, or Z register");
1214 return NULL;
1217 /* Return the condition name as a string.
1218 Used in conditional jump constructing */
1220 static const char *
1221 cond_string (enum rtx_code code)
1223 switch (code)
1225 case NE:
1226 return "ne";
1227 case EQ:
1228 return "eq";
1229 case GE:
1230 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1231 return "pl";
1232 else
1233 return "ge";
1234 case LT:
1235 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1236 return "mi";
1237 else
1238 return "lt";
1239 case GEU:
1240 return "sh";
1241 case LTU:
1242 return "lo";
1243 default:
1244 gcc_unreachable ();
1248 /* Output ADDR to FILE as address. */
1250 void
1251 print_operand_address (FILE *file, rtx addr)
1253 switch (GET_CODE (addr))
1255 case REG:
1256 fprintf (file, ptrreg_to_str (REGNO (addr)));
1257 break;
1259 case PRE_DEC:
1260 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1261 break;
1263 case POST_INC:
1264 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1265 break;
1267 default:
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 ,")");
1276 else
1277 output_addr_const (file, addr);
1282 /* Output X as assembler operand to file FILE. */
1284 void
1285 print_operand (FILE *file, rtx x, int code)
1287 int abcd = 0;
1289 if (code >= 'A' && code <= 'D')
1290 abcd = code - 'A';
1292 if (code == '~')
1294 if (!AVR_HAVE_JMP_CALL)
1295 fputc ('r', file);
1297 else if (code == '!')
1299 if (AVR_HAVE_EIJMP_EICALL)
1300 fputc ('e', file);
1302 else if (REG_P (x))
1304 if (x == zero_reg_rtx)
1305 fprintf (file, "__zero_reg__");
1306 else
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)
1317 fputc ('(', file);
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);
1333 if (code == 'p')
1334 print_operand_address (file, XEXP (addr, 0)); /* X, Y, Z */
1335 else
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:"
1343 ,addr);
1344 fputc ('+', file);
1345 print_operand (file, XEXP (addr,1), code);
1347 else
1348 print_operand_address (file, addr);
1350 else if (GET_CODE (x) == CONST_DOUBLE)
1352 long val;
1353 REAL_VALUE_TYPE rv;
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);
1364 else
1365 print_operand_address (file, x);
1368 /* Update the condition code in the INSN. */
1370 void
1371 notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
1373 rtx set;
1375 switch (get_attr_cc (insn))
1377 case CC_NONE:
1378 /* Insn does not affect CC at all. */
1379 break;
1381 case CC_SET_N:
1382 CC_STATUS_INIT;
1383 break;
1385 case CC_SET_ZN:
1386 set = single_set (insn);
1387 CC_STATUS_INIT;
1388 if (set)
1390 cc_status.flags |= CC_NO_OVERFLOW;
1391 cc_status.value1 = SET_DEST (set);
1393 break;
1395 case CC_SET_CZN:
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);
1400 CC_STATUS_INIT;
1401 if (set)
1403 cc_status.value1 = SET_DEST (set);
1404 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1406 break;
1408 case CC_COMPARE:
1409 set = single_set (insn);
1410 CC_STATUS_INIT;
1411 if (set)
1412 cc_status.value1 = SET_SRC (set);
1413 break;
1415 case CC_CLOBBER:
1416 /* Insn doesn't leave CC in a usable state. */
1417 CC_STATUS_INIT;
1419 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1420 set = single_set (insn);
1421 if (set)
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
1431 && INTVAL (x) > 0
1432 && INTVAL (x) != 6)
1434 cc_status.value1 = SET_DEST (set);
1435 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1439 break;
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)
1466 return 1;
1467 else if (-2046 <= jump_distance && jump_distance <= 2045)
1468 return 2;
1469 else if (AVR_HAVE_JMP_CALL)
1470 return 3;
1472 return 2;
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. */
1480 const char *
1481 ret_cond_branch (rtx x, int len, int reverse)
1483 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1485 switch (cond)
1487 case GT:
1488 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1489 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1490 AS1 (brpl,%0)) :
1491 len == 2 ? (AS1 (breq,.+4) CR_TAB
1492 AS1 (brmi,.+2) CR_TAB
1493 AS1 (rjmp,%0)) :
1494 (AS1 (breq,.+6) CR_TAB
1495 AS1 (brmi,.+4) CR_TAB
1496 AS1 (jmp,%0)));
1498 else
1499 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1500 AS1 (brge,%0)) :
1501 len == 2 ? (AS1 (breq,.+4) CR_TAB
1502 AS1 (brlt,.+2) CR_TAB
1503 AS1 (rjmp,%0)) :
1504 (AS1 (breq,.+6) CR_TAB
1505 AS1 (brlt,.+4) CR_TAB
1506 AS1 (jmp,%0)));
1507 case GTU:
1508 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1509 AS1 (brsh,%0)) :
1510 len == 2 ? (AS1 (breq,.+4) CR_TAB
1511 AS1 (brlo,.+2) CR_TAB
1512 AS1 (rjmp,%0)) :
1513 (AS1 (breq,.+6) CR_TAB
1514 AS1 (brlo,.+4) CR_TAB
1515 AS1 (jmp,%0)));
1516 case LE:
1517 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1518 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1519 AS1 (brmi,%0)) :
1520 len == 2 ? (AS1 (breq,.+2) CR_TAB
1521 AS1 (brpl,.+2) CR_TAB
1522 AS1 (rjmp,%0)) :
1523 (AS1 (breq,.+2) CR_TAB
1524 AS1 (brpl,.+4) CR_TAB
1525 AS1 (jmp,%0)));
1526 else
1527 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1528 AS1 (brlt,%0)) :
1529 len == 2 ? (AS1 (breq,.+2) CR_TAB
1530 AS1 (brge,.+2) CR_TAB
1531 AS1 (rjmp,%0)) :
1532 (AS1 (breq,.+2) CR_TAB
1533 AS1 (brge,.+4) CR_TAB
1534 AS1 (jmp,%0)));
1535 case LEU:
1536 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1537 AS1 (brlo,%0)) :
1538 len == 2 ? (AS1 (breq,.+2) CR_TAB
1539 AS1 (brsh,.+2) CR_TAB
1540 AS1 (rjmp,%0)) :
1541 (AS1 (breq,.+2) CR_TAB
1542 AS1 (brsh,.+4) CR_TAB
1543 AS1 (jmp,%0)));
1544 default:
1545 if (reverse)
1547 switch (len)
1549 case 1:
1550 return AS1 (br%k1,%0);
1551 case 2:
1552 return (AS1 (br%j1,.+2) CR_TAB
1553 AS1 (rjmp,%0));
1554 default:
1555 return (AS1 (br%j1,.+4) CR_TAB
1556 AS1 (jmp,%0));
1559 else
1561 switch (len)
1563 case 1:
1564 return AS1 (br%j1,%0);
1565 case 2:
1566 return (AS1 (br%k1,.+2) CR_TAB
1567 AS1 (rjmp,%0));
1568 default:
1569 return (AS1 (br%k1,.+4) CR_TAB
1570 AS1 (jmp,%0));
1574 return "";
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. */
1591 void
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)
1618 max >>= 1;
1620 if (max != (INTVAL (x) & max)
1621 && INTVAL (x) != 0xff)
1622 return 1;
1624 return 0;
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. */
1640 void
1641 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
1642 tree fndecl ATTRIBUTE_UNUSED)
1644 cum->nregs = 18;
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));
1651 if (stdarg)
1652 cum->nregs = 0;
1656 /* Returns the number of registers to allocate for a function argument. */
1658 static int
1659 avr_num_arg_regs (enum machine_mode mode, tree type)
1661 int size;
1663 if (mode == BLKmode)
1664 size = int_size_in_bytes (type);
1665 else
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);
1686 return NULL_RTX;
1689 /* Update the summarizer variable CUM to advance past an argument
1690 in the argument list. */
1692 void
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)
1703 cum->nregs = 0;
1704 cum->regno = FIRST_CUM_REG;
1708 /***********************************************************************
1709 Functions for outputting various mov's for a various modes
1710 ************************************************************************/
1711 const char *
1712 output_movqi (rtx insn, rtx operands[], int *l)
1714 int dummy;
1715 rtx dest = operands[0];
1716 rtx src = operands[1];
1717 int *real_l = l;
1719 if (!l)
1720 l = &dummy;
1722 *l = 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)
1746 *l = 2;
1747 return (AS1 (clr,%0) CR_TAB
1748 AS1 (inc,%0));
1750 else if (src == constm1_rtx)
1752 /* Immediate constants -1 to any register */
1753 *l = 2;
1754 return (AS1 (clr,%0) CR_TAB
1755 AS1 (dec,%0));
1757 else
1759 int bit_nr = exact_log2 (INTVAL (src));
1761 if (bit_nr >= 0)
1763 *l = 3;
1764 if (!real_l)
1765 output_asm_insn ((AS1 (clr,%0) CR_TAB
1766 "set"), operands);
1767 if (!real_l)
1768 avr_output_bld (operands, bit_nr);
1770 return "";
1775 /* Last resort, larger than loading from memory. */
1776 *l = 4;
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)
1787 const char *templ;
1789 if (src == const0_rtx)
1790 operands[1] = zero_reg_rtx;
1792 templ = out_movqi_mr_r (insn, operands, real_l);
1794 if (!real_l)
1795 output_asm_insn (templ, operands);
1797 operands[1] = src;
1799 return "";
1803 const char *
1804 output_movhi (rtx insn, rtx operands[], int *l)
1806 int dummy;
1807 rtx dest = operands[0];
1808 rtx src = operands[1];
1809 int *real_l = l;
1811 if (!l)
1812 l = &dummy;
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
1823 used. */
1824 else if (TARGET_NO_INTERRUPTS)
1825 return *l = 2, (AS2 (out,__SP_H__,%B1) CR_TAB
1826 AS2 (out,__SP_L__,%A1));
1827 *l = 5;
1828 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1829 "cli" 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))
1836 *l = 2;
1837 return (AS2 (in,%A0,__SP_L__) CR_TAB
1838 AS2 (in,%B0,__SP_H__));
1841 if (AVR_HAVE_MOVW)
1843 *l = 1;
1844 return (AS2 (movw,%0,%1));
1846 else
1848 *l = 2;
1849 return (AS2 (mov,%A0,%A1) CR_TAB
1850 AS2 (mov,%B0,%B1));
1853 else if (CONSTANT_P (src))
1855 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1857 *l = 2;
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 */
1866 *l = 2;
1867 return (AS1 (clr,%A0) CR_TAB
1868 AS1 (clr,%B0));
1870 else if (src == const1_rtx)
1872 *l = 3;
1873 return (AS1 (clr,%A0) CR_TAB
1874 AS1 (clr,%B0) CR_TAB
1875 AS1 (inc,%A0));
1877 else if (src == constm1_rtx)
1879 /* Immediate constants -1 to any register */
1880 *l = 3;
1881 return (AS1 (clr,%0) CR_TAB
1882 AS1 (dec,%A0) CR_TAB
1883 AS2 (mov,%B0,%A0));
1885 else
1887 int bit_nr = exact_log2 (INTVAL (src));
1889 if (bit_nr >= 0)
1891 *l = 4;
1892 if (!real_l)
1893 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1894 AS1 (clr,%B0) CR_TAB
1895 "set"), operands);
1896 if (!real_l)
1897 avr_output_bld (operands, bit_nr);
1899 return "";
1903 if ((INTVAL (src) & 0xff) == 0)
1905 *l = 5;
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)
1914 *l = 5;
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. */
1924 *l = 6;
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)
1937 const char *templ;
1939 if (src == const0_rtx)
1940 operands[1] = zero_reg_rtx;
1942 templ = out_movhi_mr_r (insn, operands, real_l);
1944 if (!real_l)
1945 output_asm_insn (templ, operands);
1947 operands[1] = src;
1948 return "";
1950 fatal_insn ("invalid insn:", insn);
1951 return "";
1954 const char *
1955 out_movqi_r_mr (rtx insn, rtx op[], int *l)
1957 rtx dest = op[0];
1958 rtx src = op[1];
1959 rtx x = XEXP (src, 0);
1960 int dummy;
1962 if (!l)
1963 l = &dummy;
1965 if (CONSTANT_ADDRESS_P (x))
1967 if (CONST_INT_P (x) && INTVAL (x) == SREG_ADDR)
1969 *l = 1;
1970 return AS2 (in,%0,__SREG__);
1972 if (optimize > 0 && io_address_operand (x, QImode))
1974 *l = 1;
1975 return AS2 (in,%0,%1-0x20);
1977 *l = 2;
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
2009 AS2 (ld,%0,X));
2011 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
2012 AS2 (ld,%0,X) CR_TAB
2013 AS2 (sbiw,r26,%o1));
2015 *l = 1;
2016 return AS2 (ldd,%0,%1);
2018 *l = 1;
2019 return AS2 (ld,%0,%1);
2022 const char *
2023 out_movhi_r_mr (rtx insn, rtx op[], int *l)
2025 rtx dest = op[0];
2026 rtx src = op[1];
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);
2033 int tmp;
2035 if (!l)
2036 l = &tmp;
2038 if (reg_base > 0)
2040 if (reg_dest == reg_base) /* R = (R) */
2042 *l = 3;
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))
2051 *l = 2;
2052 return (AS2 (ld,%A0,X+) CR_TAB
2053 AS2 (ld,%B0,X));
2055 *l = 3;
2056 return (AS2 (ld,%A0,X+) CR_TAB
2057 AS2 (ld,%B0,X) CR_TAB
2058 AS2 (sbiw,r26,1));
2060 else /* (R) */
2062 *l = 2;
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. */
2096 *l = 4;
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)
2111 *l = 3;
2112 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
2113 AS2 (ldd,%B0,%B1) CR_TAB
2114 AS2 (mov,%A0,__tmp_reg__));
2117 *l = 2;
2118 return (AS2 (ldd,%A0,%A1) CR_TAB
2119 AS2 (ldd,%B0,%B1));
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);
2126 if (mem_volatile_p)
2128 if (REGNO (XEXP (base, 0)) == REG_X)
2130 *l = 4;
2131 return (AS2 (sbiw,r26,2) CR_TAB
2132 AS2 (ld,%A0,X+) CR_TAB
2133 AS2 (ld,%B0,X) CR_TAB
2134 AS2 (sbiw,r26,1));
2136 else
2138 *l = 3;
2139 return (AS2 (sbiw,%r1,2) CR_TAB
2140 AS2 (ld,%A0,%p1) CR_TAB
2141 AS2 (ldd,%B0,%p1+1));
2145 *l = 2;
2146 return (AS2 (ld,%B0,%1) CR_TAB
2147 AS2 (ld,%A0,%1));
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);
2154 *l = 2;
2155 return (AS2 (ld,%A0,%1) CR_TAB
2156 AS2 (ld,%B0,%1));
2158 else if (CONSTANT_ADDRESS_P (base))
2160 if (optimize > 0 && io_address_operand (base, HImode))
2162 *l = 2;
2163 return (AS2 (in,%A0,%A1-0x20) CR_TAB
2164 AS2 (in,%B0,%B1-0x20));
2166 *l = 4;
2167 return (AS2 (lds,%A0,%A1) CR_TAB
2168 AS2 (lds,%B0,%B1));
2171 fatal_insn ("unknown move insn:",insn);
2172 return "";
2175 const char *
2176 out_movsi_r_mr (rtx insn, rtx op[], int *l)
2178 rtx dest = op[0];
2179 rtx src = op[1];
2180 rtx base = XEXP (src, 0);
2181 int reg_dest = true_regnum (dest);
2182 int reg_base = true_regnum (base);
2183 int tmp;
2185 if (!l)
2186 l = &tmp;
2188 if (reg_base > 0)
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
2211 AS2 (ld,%D0,X));
2212 else
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
2217 AS2 (sbiw,r26,3));
2219 else
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__));
2233 else
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)
2270 /* R = (X + d) */
2271 if (reg_dest == REG_X)
2273 *l = 7;
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__));
2283 *l = 6;
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
2314 AS2 (ldd,%D0,%D1));
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
2320 AS2 (ld,%A0,%1));
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
2325 AS2 (ld,%D0,%1));
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
2330 AS2 (lds,%D0,%D1));
2332 fatal_insn ("unknown move insn:",insn);
2333 return "";
2336 const char *
2337 out_movsi_mr_r (rtx insn, rtx op[], int *l)
2339 rtx dest = op[0];
2340 rtx src = op[1];
2341 rtx base = XEXP (dest, 0);
2342 int reg_base = true_regnum (base);
2343 int reg_src = true_regnum (src);
2344 int tmp;
2346 if (!l)
2347 l = &tmp;
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
2353 AS2 (sts,%D0,%D1));
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
2367 AS2 (st,X,r29));
2368 else
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
2375 AS2 (sbiw,r26,3));
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__));
2387 else
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
2395 AS2 (sbiw,r26,3));
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
2401 AS2 (sbiw,r26,3));
2403 else
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)
2437 /* (X + d) = R */
2438 if (reg_src == REG_X)
2440 *l = 9;
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)
2453 *l = 9;
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));
2464 *l = 6;
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
2475 AS2 (std,%D0,%D1));
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
2481 AS2 (st,%0,%A1));
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
2486 AS2 (st,%0,%D1));
2487 fatal_insn ("unknown move insn:",insn);
2488 return "";
2491 const char *
2492 output_movsisf(rtx insn, rtx operands[], int *l)
2494 int dummy;
2495 rtx dest = operands[0];
2496 rtx src = operands[1];
2497 int *real_l = l;
2499 if (!l)
2500 l = &dummy;
2502 if (register_operand (dest, VOIDmode))
2504 if (register_operand (src, VOIDmode)) /* mov r,r */
2506 if (true_regnum (dest) > true_regnum (src))
2508 if (AVR_HAVE_MOVW)
2510 *l = 2;
2511 return (AS2 (movw,%C0,%C1) CR_TAB
2512 AS2 (movw,%A0,%A1));
2514 *l = 4;
2515 return (AS2 (mov,%D0,%D1) CR_TAB
2516 AS2 (mov,%C0,%C1) CR_TAB
2517 AS2 (mov,%B0,%B1) CR_TAB
2518 AS2 (mov,%A0,%A1));
2520 else
2522 if (AVR_HAVE_MOVW)
2524 *l = 2;
2525 return (AS2 (movw,%A0,%A1) CR_TAB
2526 AS2 (movw,%C0,%C1));
2528 *l = 4;
2529 return (AS2 (mov,%A0,%A1) CR_TAB
2530 AS2 (mov,%B0,%B1) CR_TAB
2531 AS2 (mov,%C0,%C1) CR_TAB
2532 AS2 (mov,%D0,%D1));
2535 else if (CONSTANT_P (src))
2537 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2539 *l = 4;
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
2551 AS2 (movw,%C0,%A0))
2552 : (AS1 (clr,%A0) CR_TAB
2553 AS1 (clr,%B0) CR_TAB
2554 AS1 (clr,%C0) CR_TAB
2555 AS1 (clr,%D0));
2557 if (src == const0_rtx) /* mov r,L */
2559 *l = AVR_HAVE_MOVW ? 3 : 4;
2560 return clr_op0;
2562 else if (src == const1_rtx)
2564 if (!real_l)
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 */
2572 if (AVR_HAVE_MOVW)
2574 *l = 4;
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));
2580 *l = 5;
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
2585 AS2 (mov,%D0,%A0));
2587 else
2589 int bit_nr = exact_log2 (INTVAL (src));
2591 if (bit_nr >= 0)
2593 *l = AVR_HAVE_MOVW ? 5 : 6;
2594 if (!real_l)
2596 output_asm_insn (clr_op0, operands);
2597 output_asm_insn ("set", operands);
2599 if (!real_l)
2600 avr_output_bld (operands, bit_nr);
2602 return "";
2607 /* Last resort, better than loading from memory. */
2608 *l = 10;
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)
2625 const char *templ;
2627 if (src == const0_rtx)
2628 operands[1] = zero_reg_rtx;
2630 templ = out_movsi_mr_r (insn, operands, real_l);
2632 if (!real_l)
2633 output_asm_insn (templ, operands);
2635 operands[1] = src;
2636 return "";
2638 fatal_insn ("invalid insn:", insn);
2639 return "";
2642 const char *
2643 out_movqi_mr_r (rtx insn, rtx op[], int *l)
2645 rtx dest = op[0];
2646 rtx src = op[1];
2647 rtx x = XEXP (dest, 0);
2648 int dummy;
2650 if (!l)
2651 l = &dummy;
2653 if (CONSTANT_ADDRESS_P (x))
2655 if (CONST_INT_P (x) && INTVAL (x) == SREG_ADDR)
2657 *l = 1;
2658 return AS2 (out,__SREG__,%1);
2660 if (optimize > 0 && io_address_operand (x, QImode))
2662 *l = 1;
2663 return AS2 (out,%0-0x20,%1);
2665 *l = 2;
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));
2704 else
2706 if (reg_unused_after (insn, XEXP (x,0)))
2707 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2708 AS2 (st,X,%1));
2710 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2711 AS2 (st,X,%1) CR_TAB
2712 AS2 (sbiw,r26,%o0));
2715 *l = 1;
2716 return AS2 (std,%0,%1);
2718 *l = 1;
2719 return AS2 (st,%0,%1);
2722 const char *
2723 out_movhi_mr_r (rtx insn, rtx op[], int *l)
2725 rtx dest = op[0];
2726 rtx src = op[1];
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);
2733 int tmp;
2735 if (!l)
2736 l = &tmp;
2737 if (CONSTANT_ADDRESS_P (base))
2739 if (optimize > 0 && io_address_operand (base, HImode))
2741 *l = 2;
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
2746 AS2 (sts,%A0,%A1));
2748 if (reg_base > 0)
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__));
2760 else
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
2765 AS2 (st,X,r26));
2767 else
2769 if (!mem_volatile_p && reg_unused_after (insn, base))
2770 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2771 AS2 (st,X,%B1));
2772 else
2773 return *l=3, (AS2 (adiw,r26,1) CR_TAB
2774 AS2 (st,X,%B1) CR_TAB
2775 AS2 (st,-X,%A1));
2778 else
2779 return *l=2, (AS2 (std,%0+1,%B1) CR_TAB
2780 AS2 (st,%0,%A1));
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)
2806 /* (X + d) = R */
2807 if (reg_src == REG_X)
2809 *l = 7;
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));
2818 *l = 4;
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
2825 AS2 (std,%A0,%A1));
2827 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2828 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2829 AS2 (st,%0,%A1));
2830 else if (GET_CODE (base) == POST_INC) /* (R++) */
2832 if (mem_volatile_p)
2834 if (REGNO (XEXP (base, 0)) == REG_X)
2836 *l = 4;
2837 return (AS2 (adiw,r26,1) CR_TAB
2838 AS2 (st,X,%B1) CR_TAB
2839 AS2 (st,-X,%A1) CR_TAB
2840 AS2 (adiw,r26,2));
2842 else
2844 *l = 3;
2845 return (AS2 (std,%p0+1,%B1) CR_TAB
2846 AS2 (st,%p0,%A1) CR_TAB
2847 AS2 (adiw,%r0,2));
2851 *l = 2;
2852 return (AS2 (st,%0,%A1) CR_TAB
2853 AS2 (st,%0,%B1));
2855 fatal_insn ("unknown move insn:",insn);
2856 return "";
2859 /* Return 1 if frame pointer for current function required. */
2861 bool
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. */
2871 static RTX_CODE
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);
2883 return cond;
2886 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2888 static int
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. */
2917 const char *
2918 out_tsthi (rtx insn, int *l)
2920 if (compare_sign_p (insn))
2922 if (l) *l = 1;
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. */
2929 if (l) *l = 1;
2930 return AS2 (or,%A0,%B0);
2932 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2934 if (l) *l = 1;
2935 return AS2 (sbiw,%0,0);
2937 if (l) *l = 2;
2938 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2939 AS2 (cpc,%B0,__zero_reg__));
2943 /* Output test instruction for SImode. */
2945 const char *
2946 out_tstsi (rtx insn, int *l)
2948 if (compare_sign_p (insn))
2950 if (l) *l = 1;
2951 return AS1 (tst,%D0);
2953 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2955 if (l) *l = 3;
2956 return (AS2 (sbiw,%A0,0) CR_TAB
2957 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2958 AS2 (cpc,%D0,__zero_reg__));
2960 if (l) *l = 4;
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. */
2973 void
2974 out_shift_with_cnt (const char *templ, rtx insn, rtx operands[],
2975 int *len, int t_len)
2977 rtx op[10];
2978 char str[500];
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];
2987 str[0] = 0;
2989 if (len)
2990 *len = 1;
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. */
2998 if (count <= 0)
3000 if (len)
3001 *len = 0;
3002 return;
3005 if (count < 8 && !scratch)
3006 use_zero_reg = 1;
3008 if (optimize_size)
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. */
3014 if (len)
3015 *len = t_len * count;
3016 else
3018 while (count-- > 0)
3019 output_asm_insn (templ, op);
3022 return;
3025 if (scratch)
3027 if (!len)
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;
3036 if (len)
3037 *len = 2;
3038 else
3039 strcat (str, ("set" CR_TAB
3040 AS2 (bld,%3,%2-1)));
3042 else
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;
3050 saved_in_tmp = 1;
3052 if (len)
3053 *len = 3; /* Includes "mov %3,%4" after the loop. */
3054 else
3055 strcat (str, (AS2 (mov,%4,%3) CR_TAB
3056 AS2 (ldi,%3,%2)));
3059 second_label = 0;
3061 else if (GET_CODE (operands[2]) == MEM)
3063 rtx op_mov[10];
3065 op[3] = op_mov[0] = tmp_reg_rtx;
3066 op_mov[1] = op[2];
3068 if (len)
3069 out_movqi_r_mr (insn, op_mov, len);
3070 else
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]))
3076 op[3] = op[2];
3077 else
3079 op[3] = tmp_reg_rtx;
3080 if (!len)
3081 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
3084 else
3085 fatal_insn ("bad shift insn:", insn);
3087 if (second_label)
3089 if (len)
3090 ++*len;
3091 else
3092 strcat (str, AS1 (rjmp,2f));
3095 if (len)
3096 *len += t_len + 2; /* template + dec + brXX */
3097 else
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));
3105 if (saved_in_tmp)
3106 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
3107 output_asm_insn (str, op);
3112 /* 8bit shift left ((char)x << i) */
3114 const char *
3115 ashlqi3_out (rtx insn, rtx operands[], int *len)
3117 if (GET_CODE (operands[2]) == CONST_INT)
3119 int k;
3121 if (!len)
3122 len = &k;
3124 switch (INTVAL (operands[2]))
3126 default:
3127 if (INTVAL (operands[2]) < 8)
3128 break;
3130 *len = 1;
3131 return AS1 (clr,%0);
3133 case 1:
3134 *len = 1;
3135 return AS1 (lsl,%0);
3137 case 2:
3138 *len = 2;
3139 return (AS1 (lsl,%0) CR_TAB
3140 AS1 (lsl,%0));
3142 case 3:
3143 *len = 3;
3144 return (AS1 (lsl,%0) CR_TAB
3145 AS1 (lsl,%0) CR_TAB
3146 AS1 (lsl,%0));
3148 case 4:
3149 if (test_hard_reg_class (LD_REGS, operands[0]))
3151 *len = 2;
3152 return (AS1 (swap,%0) CR_TAB
3153 AS2 (andi,%0,0xf0));
3155 *len = 4;
3156 return (AS1 (lsl,%0) CR_TAB
3157 AS1 (lsl,%0) CR_TAB
3158 AS1 (lsl,%0) CR_TAB
3159 AS1 (lsl,%0));
3161 case 5:
3162 if (test_hard_reg_class (LD_REGS, operands[0]))
3164 *len = 3;
3165 return (AS1 (swap,%0) CR_TAB
3166 AS1 (lsl,%0) CR_TAB
3167 AS2 (andi,%0,0xe0));
3169 *len = 5;
3170 return (AS1 (lsl,%0) CR_TAB
3171 AS1 (lsl,%0) CR_TAB
3172 AS1 (lsl,%0) CR_TAB
3173 AS1 (lsl,%0) CR_TAB
3174 AS1 (lsl,%0));
3176 case 6:
3177 if (test_hard_reg_class (LD_REGS, operands[0]))
3179 *len = 4;
3180 return (AS1 (swap,%0) CR_TAB
3181 AS1 (lsl,%0) CR_TAB
3182 AS1 (lsl,%0) CR_TAB
3183 AS2 (andi,%0,0xc0));
3185 *len = 6;
3186 return (AS1 (lsl,%0) CR_TAB
3187 AS1 (lsl,%0) CR_TAB
3188 AS1 (lsl,%0) CR_TAB
3189 AS1 (lsl,%0) CR_TAB
3190 AS1 (lsl,%0) CR_TAB
3191 AS1 (lsl,%0));
3193 case 7:
3194 *len = 3;
3195 return (AS1 (ror,%0) CR_TAB
3196 AS1 (clr,%0) CR_TAB
3197 AS1 (ror,%0));
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);
3205 return "";
3209 /* 16bit shift left ((short)x << i) */
3211 const char *
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]);
3218 int k;
3219 int *t = len;
3221 if (!len)
3222 len = &k;
3224 switch (INTVAL (operands[2]))
3226 default:
3227 if (INTVAL (operands[2]) < 16)
3228 break;
3230 *len = 2;
3231 return (AS1 (clr,%B0) CR_TAB
3232 AS1 (clr,%A0));
3234 case 4:
3235 if (optimize_size && scratch)
3236 break; /* 5 */
3237 if (ldi_ok)
3239 *len = 6;
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
3245 AS2 (eor,%B0,%A0));
3247 if (scratch)
3249 *len = 7;
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
3256 AS2 (eor,%B0,%A0));
3258 break; /* optimize_size ? 6 : 8 */
3260 case 5:
3261 if (optimize_size)
3262 break; /* scratch ? 5 : 6 */
3263 if (ldi_ok)
3265 *len = 8;
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
3273 AS2 (eor,%B0,%A0));
3275 if (scratch)
3277 *len = 9;
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
3286 AS2 (eor,%B0,%A0));
3288 break; /* 10 */
3290 case 6:
3291 if (optimize_size)
3292 break; /* scratch ? 5 : 6 */
3293 *len = 9;
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__));
3304 case 7:
3305 *len = 5;
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
3310 AS1 (ror,%A0));
3312 case 8:
3313 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3314 AS1 (clr,%A0));
3316 case 9:
3317 *len = 3;
3318 return (AS2 (mov,%B0,%A0) CR_TAB
3319 AS1 (clr,%A0) CR_TAB
3320 AS1 (lsl,%B0));
3322 case 10:
3323 *len = 4;
3324 return (AS2 (mov,%B0,%A0) CR_TAB
3325 AS1 (clr,%A0) CR_TAB
3326 AS1 (lsl,%B0) CR_TAB
3327 AS1 (lsl,%B0));
3329 case 11:
3330 *len = 5;
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
3335 AS1 (lsl,%B0));
3337 case 12:
3338 if (ldi_ok)
3340 *len = 4;
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));
3346 if (scratch)
3348 *len = 5;
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
3353 AS2 (and,%B0,%3));
3355 *len = 6;
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
3361 AS1 (lsl,%B0));
3363 case 13:
3364 if (ldi_ok)
3366 *len = 5;
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)
3375 *len = 5;
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)
3383 break; /* 5 */
3384 if (scratch)
3386 *len = 6;
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
3392 AS2 (and,%B0,%3));
3394 if (AVR_HAVE_MUL)
3396 *len = 6;
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__));
3404 *len = 7;
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
3411 AS1 (lsl,%B0));
3413 case 14:
3414 if (AVR_HAVE_MUL && ldi_ok)
3416 *len = 5;
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)
3425 *len = 5;
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)
3434 *len = 5;
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
3439 AS1 (brne,1b));
3441 if (optimize_size && scratch)
3442 break; /* 5 */
3443 *len = 6;
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
3449 AS1 (clr,%A0));
3451 case 15:
3452 *len = 4;
3453 return (AS1 (clr,%B0) CR_TAB
3454 AS1 (lsr,%A0) CR_TAB
3455 AS1 (ror,%B0) CR_TAB
3456 AS1 (clr,%A0));
3458 len = t;
3460 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3461 AS1 (rol,%B0)),
3462 insn, operands, len, 2);
3463 return "";
3467 /* 32bit shift left ((long)x << i) */
3469 const char *
3470 ashlsi3_out (rtx insn, rtx operands[], int *len)
3472 if (GET_CODE (operands[2]) == CONST_INT)
3474 int k;
3475 int *t = len;
3477 if (!len)
3478 len = &k;
3480 switch (INTVAL (operands[2]))
3482 default:
3483 if (INTVAL (operands[2]) < 32)
3484 break;
3486 if (AVR_HAVE_MOVW)
3487 return *len = 3, (AS1 (clr,%D0) CR_TAB
3488 AS1 (clr,%C0) CR_TAB
3489 AS2 (movw,%A0,%C0));
3490 *len = 4;
3491 return (AS1 (clr,%D0) CR_TAB
3492 AS1 (clr,%C0) CR_TAB
3493 AS1 (clr,%B0) CR_TAB
3494 AS1 (clr,%A0));
3496 case 8:
3498 int reg0 = true_regnum (operands[0]);
3499 int reg1 = true_regnum (operands[1]);
3500 *len = 4;
3501 if (reg0 >= reg1)
3502 return (AS2 (mov,%D0,%C1) CR_TAB
3503 AS2 (mov,%C0,%B1) CR_TAB
3504 AS2 (mov,%B0,%A1) CR_TAB
3505 AS1 (clr,%A0));
3506 else
3507 return (AS1 (clr,%A0) CR_TAB
3508 AS2 (mov,%B0,%A1) CR_TAB
3509 AS2 (mov,%C0,%B1) CR_TAB
3510 AS2 (mov,%D0,%C1));
3513 case 16:
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
3519 AS1 (clr,%A0));
3520 if (AVR_HAVE_MOVW)
3521 return *len = 3, (AS2 (movw,%C0,%A1) CR_TAB
3522 AS1 (clr,%B0) CR_TAB
3523 AS1 (clr,%A0));
3524 else
3525 return *len = 4, (AS2 (mov,%C0,%A1) CR_TAB
3526 AS2 (mov,%D0,%B1) CR_TAB
3527 AS1 (clr,%B0) CR_TAB
3528 AS1 (clr,%A0));
3531 case 24:
3532 *len = 4;
3533 return (AS2 (mov,%D0,%A1) CR_TAB
3534 AS1 (clr,%C0) CR_TAB
3535 AS1 (clr,%B0) CR_TAB
3536 AS1 (clr,%A0));
3538 case 31:
3539 *len = 6;
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
3545 AS1 (clr,%A0));
3547 len = t;
3549 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3550 AS1 (rol,%B0) CR_TAB
3551 AS1 (rol,%C0) CR_TAB
3552 AS1 (rol,%D0)),
3553 insn, operands, len, 4);
3554 return "";
3557 /* 8bit arithmetic shift right ((signed char)x >> i) */
3559 const char *
3560 ashrqi3_out (rtx insn, rtx operands[], int *len)
3562 if (GET_CODE (operands[2]) == CONST_INT)
3564 int k;
3566 if (!len)
3567 len = &k;
3569 switch (INTVAL (operands[2]))
3571 case 1:
3572 *len = 1;
3573 return AS1 (asr,%0);
3575 case 2:
3576 *len = 2;
3577 return (AS1 (asr,%0) CR_TAB
3578 AS1 (asr,%0));
3580 case 3:
3581 *len = 3;
3582 return (AS1 (asr,%0) CR_TAB
3583 AS1 (asr,%0) CR_TAB
3584 AS1 (asr,%0));
3586 case 4:
3587 *len = 4;
3588 return (AS1 (asr,%0) CR_TAB
3589 AS1 (asr,%0) CR_TAB
3590 AS1 (asr,%0) CR_TAB
3591 AS1 (asr,%0));
3593 case 5:
3594 *len = 5;
3595 return (AS1 (asr,%0) CR_TAB
3596 AS1 (asr,%0) CR_TAB
3597 AS1 (asr,%0) CR_TAB
3598 AS1 (asr,%0) CR_TAB
3599 AS1 (asr,%0));
3601 case 6:
3602 *len = 4;
3603 return (AS2 (bst,%0,6) CR_TAB
3604 AS1 (lsl,%0) CR_TAB
3605 AS2 (sbc,%0,%0) CR_TAB
3606 AS2 (bld,%0,0));
3608 default:
3609 if (INTVAL (operands[2]) < 8)
3610 break;
3612 /* fall through */
3614 case 7:
3615 *len = 2;
3616 return (AS1 (lsl,%0) CR_TAB
3617 AS2 (sbc,%0,%0));
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);
3625 return "";
3629 /* 16bit arithmetic shift right ((signed short)x >> i) */
3631 const char *
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]);
3638 int k;
3639 int *t = len;
3641 if (!len)
3642 len = &k;
3644 switch (INTVAL (operands[2]))
3646 case 4:
3647 case 5:
3648 /* XXX try to optimize this too? */
3649 break;
3651 case 6:
3652 if (optimize_size)
3653 break; /* scratch ? 5 : 6 */
3654 *len = 8;
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
3662 AS1 (rol,%B0));
3664 case 7:
3665 *len = 4;
3666 return (AS1 (lsl,%A0) CR_TAB
3667 AS2 (mov,%A0,%B0) CR_TAB
3668 AS1 (rol,%A0) CR_TAB
3669 AS2 (sbc,%B0,%B0));
3671 case 8:
3673 int reg0 = true_regnum (operands[0]);
3674 int reg1 = true_regnum (operands[1]);
3676 if (reg0 == reg1)
3677 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3678 AS1 (lsl,%B0) CR_TAB
3679 AS2 (sbc,%B0,%B0));
3680 else
3681 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3682 AS1 (clr,%B0) CR_TAB
3683 AS2 (sbrc,%A0,7) CR_TAB
3684 AS1 (dec,%B0));
3687 case 9:
3688 *len = 4;
3689 return (AS2 (mov,%A0,%B0) CR_TAB
3690 AS1 (lsl,%B0) CR_TAB
3691 AS2 (sbc,%B0,%B0) CR_TAB
3692 AS1 (asr,%A0));
3694 case 10:
3695 *len = 5;
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
3700 AS1 (asr,%A0));
3702 case 11:
3703 if (AVR_HAVE_MUL && ldi_ok)
3705 *len = 5;
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)
3713 break; /* 5 */
3714 *len = 6;
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
3720 AS1 (asr,%A0));
3722 case 12:
3723 if (AVR_HAVE_MUL && ldi_ok)
3725 *len = 5;
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)
3733 break; /* 5 */
3734 *len = 7;
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
3741 AS1 (asr,%A0));
3743 case 13:
3744 if (AVR_HAVE_MUL && ldi_ok)
3746 *len = 5;
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__));
3753 if (optimize_size)
3754 break; /* scratch ? 5 : 7 */
3755 *len = 8;
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
3763 AS1 (asr,%A0));
3765 case 14:
3766 *len = 5;
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
3771 AS1 (rol,%A0));
3773 default:
3774 if (INTVAL (operands[2]) < 16)
3775 break;
3777 /* fall through */
3779 case 15:
3780 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3781 AS2 (sbc,%A0,%A0) CR_TAB
3782 AS2 (mov,%B0,%A0));
3784 len = t;
3786 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3787 AS1 (ror,%A0)),
3788 insn, operands, len, 2);
3789 return "";
3793 /* 32bit arithmetic shift right ((signed long)x >> i) */
3795 const char *
3796 ashrsi3_out (rtx insn, rtx operands[], int *len)
3798 if (GET_CODE (operands[2]) == CONST_INT)
3800 int k;
3801 int *t = len;
3803 if (!len)
3804 len = &k;
3806 switch (INTVAL (operands[2]))
3808 case 8:
3810 int reg0 = true_regnum (operands[0]);
3811 int reg1 = true_regnum (operands[1]);
3812 *len=6;
3813 if (reg0 <= reg1)
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
3819 AS1 (dec,%D0));
3820 else
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
3826 AS2 (mov,%A0,%B1));
3829 case 16:
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
3838 AS2 (mov,%C0,%D0));
3839 if (AVR_HAVE_MOVW)
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
3844 AS2 (mov,%C0,%D0));
3845 else
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
3851 AS2 (mov,%C0,%D0));
3854 case 24:
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
3860 AS2 (mov,%C0,%D0));
3862 default:
3863 if (INTVAL (operands[2]) < 32)
3864 break;
3866 /* fall through */
3868 case 31:
3869 if (AVR_HAVE_MOVW)
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));
3874 else
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
3879 AS2 (mov,%D0,%A0));
3881 len = t;
3883 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3884 AS1 (ror,%C0) CR_TAB
3885 AS1 (ror,%B0) CR_TAB
3886 AS1 (ror,%A0)),
3887 insn, operands, len, 4);
3888 return "";
3891 /* 8bit logic shift right ((unsigned char)x >> i) */
3893 const char *
3894 lshrqi3_out (rtx insn, rtx operands[], int *len)
3896 if (GET_CODE (operands[2]) == CONST_INT)
3898 int k;
3900 if (!len)
3901 len = &k;
3903 switch (INTVAL (operands[2]))
3905 default:
3906 if (INTVAL (operands[2]) < 8)
3907 break;
3909 *len = 1;
3910 return AS1 (clr,%0);
3912 case 1:
3913 *len = 1;
3914 return AS1 (lsr,%0);
3916 case 2:
3917 *len = 2;
3918 return (AS1 (lsr,%0) CR_TAB
3919 AS1 (lsr,%0));
3920 case 3:
3921 *len = 3;
3922 return (AS1 (lsr,%0) CR_TAB
3923 AS1 (lsr,%0) CR_TAB
3924 AS1 (lsr,%0));
3926 case 4:
3927 if (test_hard_reg_class (LD_REGS, operands[0]))
3929 *len=2;
3930 return (AS1 (swap,%0) CR_TAB
3931 AS2 (andi,%0,0x0f));
3933 *len = 4;
3934 return (AS1 (lsr,%0) CR_TAB
3935 AS1 (lsr,%0) CR_TAB
3936 AS1 (lsr,%0) CR_TAB
3937 AS1 (lsr,%0));
3939 case 5:
3940 if (test_hard_reg_class (LD_REGS, operands[0]))
3942 *len = 3;
3943 return (AS1 (swap,%0) CR_TAB
3944 AS1 (lsr,%0) CR_TAB
3945 AS2 (andi,%0,0x7));
3947 *len = 5;
3948 return (AS1 (lsr,%0) CR_TAB
3949 AS1 (lsr,%0) CR_TAB
3950 AS1 (lsr,%0) CR_TAB
3951 AS1 (lsr,%0) CR_TAB
3952 AS1 (lsr,%0));
3954 case 6:
3955 if (test_hard_reg_class (LD_REGS, operands[0]))
3957 *len = 4;
3958 return (AS1 (swap,%0) CR_TAB
3959 AS1 (lsr,%0) CR_TAB
3960 AS1 (lsr,%0) CR_TAB
3961 AS2 (andi,%0,0x3));
3963 *len = 6;
3964 return (AS1 (lsr,%0) CR_TAB
3965 AS1 (lsr,%0) CR_TAB
3966 AS1 (lsr,%0) CR_TAB
3967 AS1 (lsr,%0) CR_TAB
3968 AS1 (lsr,%0) CR_TAB
3969 AS1 (lsr,%0));
3971 case 7:
3972 *len = 3;
3973 return (AS1 (rol,%0) CR_TAB
3974 AS1 (clr,%0) CR_TAB
3975 AS1 (rol,%0));
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);
3983 return "";
3986 /* 16bit logic shift right ((unsigned short)x >> i) */
3988 const char *
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]);
3995 int k;
3996 int *t = len;
3998 if (!len)
3999 len = &k;
4001 switch (INTVAL (operands[2]))
4003 default:
4004 if (INTVAL (operands[2]) < 16)
4005 break;
4007 *len = 2;
4008 return (AS1 (clr,%B0) CR_TAB
4009 AS1 (clr,%A0));
4011 case 4:
4012 if (optimize_size && scratch)
4013 break; /* 5 */
4014 if (ldi_ok)
4016 *len = 6;
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
4022 AS2 (eor,%A0,%B0));
4024 if (scratch)
4026 *len = 7;
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
4033 AS2 (eor,%A0,%B0));
4035 break; /* optimize_size ? 6 : 8 */
4037 case 5:
4038 if (optimize_size)
4039 break; /* scratch ? 5 : 6 */
4040 if (ldi_ok)
4042 *len = 8;
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
4050 AS2 (eor,%A0,%B0));
4052 if (scratch)
4054 *len = 9;
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
4063 AS2 (eor,%A0,%B0));
4065 break; /* 10 */
4067 case 6:
4068 if (optimize_size)
4069 break; /* scratch ? 5 : 6 */
4070 *len = 9;
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__));
4081 case 7:
4082 *len = 5;
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
4087 AS1 (neg,%B0));
4089 case 8:
4090 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
4091 AS1 (clr,%B0));
4093 case 9:
4094 *len = 3;
4095 return (AS2 (mov,%A0,%B0) CR_TAB
4096 AS1 (clr,%B0) CR_TAB
4097 AS1 (lsr,%A0));
4099 case 10:
4100 *len = 4;
4101 return (AS2 (mov,%A0,%B0) CR_TAB
4102 AS1 (clr,%B0) CR_TAB
4103 AS1 (lsr,%A0) CR_TAB
4104 AS1 (lsr,%A0));
4106 case 11:
4107 *len = 5;
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
4112 AS1 (lsr,%A0));
4114 case 12:
4115 if (ldi_ok)
4117 *len = 4;
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));
4123 if (scratch)
4125 *len = 5;
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
4130 AS2 (and,%A0,%3));
4132 *len = 6;
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
4138 AS1 (lsr,%A0));
4140 case 13:
4141 if (ldi_ok)
4143 *len = 5;
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)
4152 *len = 5;
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)
4160 break; /* 5 */
4161 if (scratch)
4163 *len = 6;
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
4169 AS2 (and,%A0,%3));
4171 if (AVR_HAVE_MUL)
4173 *len = 6;
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__));
4181 *len = 7;
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
4188 AS1 (lsr,%A0));
4190 case 14:
4191 if (AVR_HAVE_MUL && ldi_ok)
4193 *len = 5;
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)
4202 *len = 5;
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)
4211 *len = 5;
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
4216 AS1 (brne,1b));
4218 if (optimize_size && scratch)
4219 break; /* 5 */
4220 *len = 6;
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
4226 AS1 (clr,%B0));
4228 case 15:
4229 *len = 4;
4230 return (AS1 (clr,%A0) CR_TAB
4231 AS1 (lsl,%B0) CR_TAB
4232 AS1 (rol,%A0) CR_TAB
4233 AS1 (clr,%B0));
4235 len = t;
4237 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4238 AS1 (ror,%A0)),
4239 insn, operands, len, 2);
4240 return "";
4243 /* 32bit logic shift right ((unsigned int)x >> i) */
4245 const char *
4246 lshrsi3_out (rtx insn, rtx operands[], int *len)
4248 if (GET_CODE (operands[2]) == CONST_INT)
4250 int k;
4251 int *t = len;
4253 if (!len)
4254 len = &k;
4256 switch (INTVAL (operands[2]))
4258 default:
4259 if (INTVAL (operands[2]) < 32)
4260 break;
4262 if (AVR_HAVE_MOVW)
4263 return *len = 3, (AS1 (clr,%D0) CR_TAB
4264 AS1 (clr,%C0) CR_TAB
4265 AS2 (movw,%A0,%C0));
4266 *len = 4;
4267 return (AS1 (clr,%D0) CR_TAB
4268 AS1 (clr,%C0) CR_TAB
4269 AS1 (clr,%B0) CR_TAB
4270 AS1 (clr,%A0));
4272 case 8:
4274 int reg0 = true_regnum (operands[0]);
4275 int reg1 = true_regnum (operands[1]);
4276 *len = 4;
4277 if (reg0 <= reg1)
4278 return (AS2 (mov,%A0,%B1) CR_TAB
4279 AS2 (mov,%B0,%C1) CR_TAB
4280 AS2 (mov,%C0,%D1) CR_TAB
4281 AS1 (clr,%D0));
4282 else
4283 return (AS1 (clr,%D0) CR_TAB
4284 AS2 (mov,%C0,%D1) CR_TAB
4285 AS2 (mov,%B0,%C1) CR_TAB
4286 AS2 (mov,%A0,%B1));
4289 case 16:
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
4296 AS1 (clr,%D0));
4297 if (AVR_HAVE_MOVW)
4298 return *len = 3, (AS2 (movw,%A0,%C1) CR_TAB
4299 AS1 (clr,%C0) CR_TAB
4300 AS1 (clr,%D0));
4301 else
4302 return *len = 4, (AS2 (mov,%B0,%D1) CR_TAB
4303 AS2 (mov,%A0,%C1) CR_TAB
4304 AS1 (clr,%C0) CR_TAB
4305 AS1 (clr,%D0));
4308 case 24:
4309 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4310 AS1 (clr,%B0) CR_TAB
4311 AS1 (clr,%C0) CR_TAB
4312 AS1 (clr,%D0));
4314 case 31:
4315 *len = 6;
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
4321 AS1 (clr,%D0));
4323 len = t;
4325 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4326 AS1 (ror,%C0) CR_TAB
4327 AS1 (ror,%B0) CR_TAB
4328 AS1 (ror,%A0)),
4329 insn, operands, len, 4);
4330 return "";
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);
4340 rtx set;
4342 if (GET_CODE (patt) == SET)
4344 rtx op[10];
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]))
4352 case QImode:
4353 output_movqi (insn, op, &len);
4354 break;
4355 case HImode:
4356 output_movhi (insn, op, &len);
4357 break;
4358 case SImode:
4359 case SFmode:
4360 output_movsisf (insn, op, &len);
4361 break;
4362 default:
4363 break;
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;
4372 default: 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);
4407 if (set)
4409 rtx op[10];
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]))
4423 case QImode:
4424 len = 2;
4425 break;
4426 case HImode:
4427 output_reload_inhi (insn, op, &len);
4428 break;
4429 case SImode:
4430 case SFmode:
4431 output_reload_insisf (insn, op, &len);
4432 break;
4433 default:
4434 break;
4437 else if (GET_CODE (op[1]) == ASHIFT
4438 || GET_CODE (op[1]) == ASHIFTRT
4439 || GET_CODE (op[1]) == LSHIFTRT)
4441 rtx ops[10];
4442 ops[0] = op[0];
4443 ops[1] = XEXP (op[1],0);
4444 ops[2] = XEXP (op[1],1);
4445 switch (GET_CODE (op[1]))
4447 case ASHIFT:
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;
4453 default: break;
4455 break;
4456 case ASHIFTRT:
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;
4462 default: break;
4464 break;
4465 case LSHIFTRT:
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;
4471 default: break;
4473 break;
4474 default:
4475 break;
4479 return len;
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)
4498 enum rtx_code code;
4499 rtx set;
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)))
4507 return 1;
4509 while ((insn = NEXT_INSN (insn)))
4511 rtx set;
4512 code = GET_CODE (insn);
4514 #if 0
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)
4520 return 1;
4521 /* else */
4522 #endif
4524 if (!INSN_P (insn))
4525 continue;
4527 if (code == JUMP_INSN)
4528 return 0;
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)
4536 int i;
4537 int retval = 0;
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)
4545 code = CALL_INSN;
4546 else if (GET_CODE (this_insn) == JUMP_INSN)
4548 if (INSN_ANNULLED_BRANCH_P (this_insn))
4549 return 0;
4550 code = JUMP_INSN;
4553 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4554 return 0;
4555 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4557 if (GET_CODE (SET_DEST (set)) != MEM)
4558 retval = 1;
4559 else
4560 return 0;
4562 if (set == 0
4563 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4564 return 0;
4566 if (retval == 1)
4567 return 1;
4568 else if (code == JUMP_INSN)
4569 return 0;
4572 if (code == CALL_INSN)
4574 rtx tem;
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)))
4579 return 0;
4580 if (call_used_regs[REGNO (reg)])
4581 return 1;
4584 set = single_set (insn);
4586 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4587 return 0;
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)))
4591 return 0;
4593 return 1;
4596 /* Target hook for assembling integer objects. The AVR version needs
4597 special handling for references to certain labels. */
4599 static bool
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);
4609 return true;
4611 return default_assemble_integer (x, size, aligned_p);
4614 /* Worker function for ASM_DECLARE_FUNCTION_NAME. */
4616 void
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",
4630 name);
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",
4639 name);
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). */
4654 void
4655 gas_output_limited_string(FILE *file, const char *str)
4657 const unsigned char *_limited_str = (const unsigned char *) str;
4658 unsigned ch;
4659 fprintf (file, "%s\"", STRING_ASM_OP);
4660 for (; (ch = *_limited_str); _limited_str++)
4662 int escape;
4663 switch (escape = ESCAPES[ch])
4665 case 0:
4666 putc (ch, file);
4667 break;
4668 case 1:
4669 fprintf (file, "\\%03o", ch);
4670 break;
4671 default:
4672 putc ('\\', file);
4673 putc (escape, file);
4674 break;
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. */
4687 void
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");
4699 bytes_in_chunk = 0;
4701 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4702 continue;
4703 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4705 if (bytes_in_chunk > 0)
4707 fprintf (file, "\"\n");
4708 bytes_in_chunk = 0;
4710 gas_output_limited_string (file, (const char*)_ascii_bytes);
4711 _ascii_bytes = p;
4713 else
4715 int escape;
4716 unsigned ch;
4717 if (bytes_in_chunk == 0)
4718 fprintf (file, "\t.ascii\t\"");
4719 switch (escape = ESCAPES[ch = *_ascii_bytes])
4721 case 0:
4722 putc (ch, file);
4723 bytes_in_chunk++;
4724 break;
4725 case 1:
4726 fprintf (file, "\\%03o", ch);
4727 bytes_in_chunk += 4;
4728 break;
4729 default:
4730 putc ('\\', file);
4731 putc (escape, file);
4732 bytes_in_chunk += 2;
4733 break;
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. */
4745 enum reg_class
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. */
4775 static tree
4776 avr_handle_progmem_attribute (tree *node, tree name,
4777 tree args ATTRIBUTE_UNUSED,
4778 int flags ATTRIBUTE_UNUSED,
4779 bool *no_add_attrs)
4781 if (DECL_P (*node))
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;
4805 else
4807 warning (OPT_Wattributes, "%qs attribute ignored",
4808 IDENTIFIER_POINTER (name));
4809 *no_add_attrs = true;
4813 return NULL_TREE;
4816 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4817 struct attribute_spec.handler. */
4819 static tree
4820 avr_handle_fndecl_attribute (tree *node, tree name,
4821 tree args ATTRIBUTE_UNUSED,
4822 int flags ATTRIBUTE_UNUSED,
4823 bool *no_add_attrs)
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;
4832 return NULL_TREE;
4835 static tree
4836 avr_handle_fntype_attribute (tree *node, tree name,
4837 tree args ATTRIBUTE_UNUSED,
4838 int flags ATTRIBUTE_UNUSED,
4839 bool *no_add_attrs)
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;
4848 return NULL_TREE;
4851 /* Look for attribute `progmem' in DECL
4852 if found return 1, otherwise 0. */
4855 avr_progmem_p (tree decl, tree attributes)
4857 tree a;
4859 if (TREE_CODE (decl) != VAR_DECL)
4860 return 0;
4862 if (NULL_TREE
4863 != lookup_attribute ("progmem", attributes))
4864 return 1;
4866 a=decl;
4868 a = TREE_TYPE(a);
4869 while (TREE_CODE (a) == ARRAY_TYPE);
4871 if (a == error_mark_node)
4872 return 0;
4874 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4875 return 1;
4877 return 0;
4880 /* Add the section attribute if the variable is in progmem. */
4882 static void
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)),
4892 *attributes);
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. */
4902 static void
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. */
4914 static void
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,
4919 NULL);
4920 readonly_data_section = data_section;
4923 static unsigned int
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 */
4933 else
4934 warning (0, "only uninitialized variables can be placed in the "
4935 ".noinit section");
4938 return flags;
4941 /* Outputs some appropriate text to go at the start of an assembler
4942 file. */
4944 static void
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"
4954 "__SP_H__ = 0x3e\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. */
4970 static void
4971 avr_file_end (void)
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. */
4982 void
4983 order_regs_for_local_alloc (void)
4985 unsigned int i;
4986 static const int order_0[] = {
4987 24,25,
4988 18,19,
4989 20,21,
4990 22,23,
4991 30,31,
4992 26,27,
4993 28,29,
4994 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4995 0,1,
4996 32,33,34,35
4998 static const int order_1[] = {
4999 18,19,
5000 20,21,
5001 22,23,
5002 24,25,
5003 30,31,
5004 26,27,
5005 28,29,
5006 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
5007 0,1,
5008 32,33,34,35
5010 static const int order_2[] = {
5011 25,24,
5012 23,22,
5013 21,20,
5014 19,18,
5015 30,31,
5016 26,27,
5017 28,29,
5018 17,16,
5019 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
5020 1,0,
5021 32,33,34,35
5024 const int *order = (TARGET_ORDER_1 ? order_1 :
5025 TARGET_ORDER_2 ? order_2 :
5026 order_0);
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. */
5037 static int
5038 avr_operand_rtx_cost (rtx x, enum machine_mode mode, enum rtx_code outer,
5039 bool speed)
5041 enum rtx_code code = GET_CODE (x);
5042 int total;
5044 switch (code)
5046 case REG:
5047 case SUBREG:
5048 return 0;
5050 case CONST_INT:
5051 case CONST_DOUBLE:
5052 return COSTS_N_INSNS (GET_MODE_SIZE (mode));
5054 default:
5055 break;
5058 total = 0;
5059 avr_rtx_costs (x, code, outer, &total, speed);
5060 return total;
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. */
5068 static bool
5069 avr_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
5070 bool speed)
5072 enum machine_mode mode = GET_MODE (x);
5073 HOST_WIDE_INT val;
5075 switch (code)
5077 case CONST_INT:
5078 case CONST_DOUBLE:
5079 /* Immediate constants are as cheap as registers. */
5080 *total = 0;
5081 return true;
5083 case MEM:
5084 case CONST:
5085 case LABEL_REF:
5086 case SYMBOL_REF:
5087 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
5088 return true;
5090 case NEG:
5091 switch (mode)
5093 case QImode:
5094 case SFmode:
5095 *total = COSTS_N_INSNS (1);
5096 break;
5098 case HImode:
5099 *total = COSTS_N_INSNS (3);
5100 break;
5102 case SImode:
5103 *total = COSTS_N_INSNS (7);
5104 break;
5106 default:
5107 return false;
5109 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5110 return true;
5112 case ABS:
5113 switch (mode)
5115 case QImode:
5116 case SFmode:
5117 *total = COSTS_N_INSNS (1);
5118 break;
5120 default:
5121 return false;
5123 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5124 return true;
5126 case NOT:
5127 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
5128 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5129 return true;
5131 case ZERO_EXTEND:
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);
5135 return true;
5137 case SIGN_EXTEND:
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);
5141 return true;
5143 case PLUS:
5144 switch (mode)
5146 case QImode:
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);
5150 break;
5152 case HImode:
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);
5160 else
5161 *total = COSTS_N_INSNS (2);
5162 break;
5164 case SImode:
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);
5172 else
5173 *total = COSTS_N_INSNS (4);
5174 break;
5176 default:
5177 return false;
5179 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5180 return true;
5182 case MINUS:
5183 case AND:
5184 case IOR:
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);
5189 return true;
5191 case XOR:
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);
5195 return true;
5197 case MULT:
5198 switch (mode)
5200 case QImode:
5201 if (AVR_HAVE_MUL)
5202 *total = COSTS_N_INSNS (!speed ? 3 : 4);
5203 else if (!speed)
5204 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
5205 else
5206 return false;
5207 break;
5209 case HImode:
5210 if (AVR_HAVE_MUL)
5211 *total = COSTS_N_INSNS (!speed ? 7 : 10);
5212 else if (!speed)
5213 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
5214 else
5215 return false;
5216 break;
5218 default:
5219 return false;
5221 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5222 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5223 return true;
5225 case DIV:
5226 case MOD:
5227 case UDIV:
5228 case UMOD:
5229 if (!speed)
5230 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
5231 else
5232 return false;
5233 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5234 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5235 return true;
5237 case ROTATE:
5238 switch (mode)
5240 case QImode:
5241 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
5242 *total = COSTS_N_INSNS (1);
5244 break;
5246 case HImode:
5247 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
5248 *total = COSTS_N_INSNS (3);
5250 break;
5252 case SImode:
5253 if (CONST_INT_P (XEXP (x, 1)))
5254 switch (INTVAL (XEXP (x, 1)))
5256 case 8:
5257 case 24:
5258 *total = COSTS_N_INSNS (5);
5259 break;
5260 case 16:
5261 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
5262 break;
5264 break;
5266 default:
5267 return false;
5269 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5270 return true;
5272 case ASHIFT:
5273 switch (mode)
5275 case QImode:
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);
5281 else
5283 val = INTVAL (XEXP (x, 1));
5284 if (val == 7)
5285 *total = COSTS_N_INSNS (3);
5286 else if (val >= 0 && val <= 7)
5287 *total = COSTS_N_INSNS (val);
5288 else
5289 *total = COSTS_N_INSNS (1);
5291 break;
5293 case HImode:
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);
5299 else
5300 switch (INTVAL (XEXP (x, 1)))
5302 case 0:
5303 *total = 0;
5304 break;
5305 case 1:
5306 case 8:
5307 *total = COSTS_N_INSNS (2);
5308 break;
5309 case 9:
5310 *total = COSTS_N_INSNS (3);
5311 break;
5312 case 2:
5313 case 3:
5314 case 10:
5315 case 15:
5316 *total = COSTS_N_INSNS (4);
5317 break;
5318 case 7:
5319 case 11:
5320 case 12:
5321 *total = COSTS_N_INSNS (5);
5322 break;
5323 case 4:
5324 *total = COSTS_N_INSNS (!speed ? 5 : 8);
5325 break;
5326 case 6:
5327 *total = COSTS_N_INSNS (!speed ? 5 : 9);
5328 break;
5329 case 5:
5330 *total = COSTS_N_INSNS (!speed ? 5 : 10);
5331 break;
5332 default:
5333 *total = COSTS_N_INSNS (!speed ? 5 : 41);
5334 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5336 break;
5338 case SImode:
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);
5344 else
5345 switch (INTVAL (XEXP (x, 1)))
5347 case 0:
5348 *total = 0;
5349 break;
5350 case 24:
5351 *total = COSTS_N_INSNS (3);
5352 break;
5353 case 1:
5354 case 8:
5355 case 16:
5356 *total = COSTS_N_INSNS (4);
5357 break;
5358 case 31:
5359 *total = COSTS_N_INSNS (6);
5360 break;
5361 case 2:
5362 *total = COSTS_N_INSNS (!speed ? 7 : 8);
5363 break;
5364 default:
5365 *total = COSTS_N_INSNS (!speed ? 7 : 113);
5366 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5368 break;
5370 default:
5371 return false;
5373 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5374 return true;
5376 case ASHIFTRT:
5377 switch (mode)
5379 case QImode:
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);
5385 else
5387 val = INTVAL (XEXP (x, 1));
5388 if (val == 6)
5389 *total = COSTS_N_INSNS (4);
5390 else if (val == 7)
5391 *total = COSTS_N_INSNS (2);
5392 else if (val >= 0 && val <= 7)
5393 *total = COSTS_N_INSNS (val);
5394 else
5395 *total = COSTS_N_INSNS (1);
5397 break;
5399 case HImode:
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);
5405 else
5406 switch (INTVAL (XEXP (x, 1)))
5408 case 0:
5409 *total = 0;
5410 break;
5411 case 1:
5412 *total = COSTS_N_INSNS (2);
5413 break;
5414 case 15:
5415 *total = COSTS_N_INSNS (3);
5416 break;
5417 case 2:
5418 case 7:
5419 case 8:
5420 case 9:
5421 *total = COSTS_N_INSNS (4);
5422 break;
5423 case 10:
5424 case 14:
5425 *total = COSTS_N_INSNS (5);
5426 break;
5427 case 11:
5428 *total = COSTS_N_INSNS (!speed ? 5 : 6);
5429 break;
5430 case 12:
5431 *total = COSTS_N_INSNS (!speed ? 5 : 7);
5432 break;
5433 case 6:
5434 case 13:
5435 *total = COSTS_N_INSNS (!speed ? 5 : 8);
5436 break;
5437 default:
5438 *total = COSTS_N_INSNS (!speed ? 5 : 41);
5439 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5441 break;
5443 case SImode:
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);
5449 else
5450 switch (INTVAL (XEXP (x, 1)))
5452 case 0:
5453 *total = 0;
5454 break;
5455 case 1:
5456 *total = COSTS_N_INSNS (4);
5457 break;
5458 case 8:
5459 case 16:
5460 case 24:
5461 *total = COSTS_N_INSNS (6);
5462 break;
5463 case 2:
5464 *total = COSTS_N_INSNS (!speed ? 7 : 8);
5465 break;
5466 case 31:
5467 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
5468 break;
5469 default:
5470 *total = COSTS_N_INSNS (!speed ? 7 : 113);
5471 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5473 break;
5475 default:
5476 return false;
5478 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5479 return true;
5481 case LSHIFTRT:
5482 switch (mode)
5484 case QImode:
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);
5490 else
5492 val = INTVAL (XEXP (x, 1));
5493 if (val == 7)
5494 *total = COSTS_N_INSNS (3);
5495 else if (val >= 0 && val <= 7)
5496 *total = COSTS_N_INSNS (val);
5497 else
5498 *total = COSTS_N_INSNS (1);
5500 break;
5502 case HImode:
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);
5508 else
5509 switch (INTVAL (XEXP (x, 1)))
5511 case 0:
5512 *total = 0;
5513 break;
5514 case 1:
5515 case 8:
5516 *total = COSTS_N_INSNS (2);
5517 break;
5518 case 9:
5519 *total = COSTS_N_INSNS (3);
5520 break;
5521 case 2:
5522 case 10:
5523 case 15:
5524 *total = COSTS_N_INSNS (4);
5525 break;
5526 case 7:
5527 case 11:
5528 *total = COSTS_N_INSNS (5);
5529 break;
5530 case 3:
5531 case 12:
5532 case 13:
5533 case 14:
5534 *total = COSTS_N_INSNS (!speed ? 5 : 6);
5535 break;
5536 case 4:
5537 *total = COSTS_N_INSNS (!speed ? 5 : 7);
5538 break;
5539 case 5:
5540 case 6:
5541 *total = COSTS_N_INSNS (!speed ? 5 : 9);
5542 break;
5543 default:
5544 *total = COSTS_N_INSNS (!speed ? 5 : 41);
5545 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5547 break;
5549 case SImode:
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);
5555 else
5556 switch (INTVAL (XEXP (x, 1)))
5558 case 0:
5559 *total = 0;
5560 break;
5561 case 1:
5562 *total = COSTS_N_INSNS (4);
5563 break;
5564 case 2:
5565 *total = COSTS_N_INSNS (!speed ? 7 : 8);
5566 break;
5567 case 8:
5568 case 16:
5569 case 24:
5570 *total = COSTS_N_INSNS (4);
5571 break;
5572 case 31:
5573 *total = COSTS_N_INSNS (6);
5574 break;
5575 default:
5576 *total = COSTS_N_INSNS (!speed ? 7 : 113);
5577 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
5579 break;
5581 default:
5582 return false;
5584 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5585 return true;
5587 case COMPARE:
5588 switch (GET_MODE (XEXP (x, 0)))
5590 case QImode:
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);
5594 break;
5596 case HImode:
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);
5602 break;
5604 case SImode:
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);
5610 break;
5612 default:
5613 return false;
5615 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
5616 return true;
5618 default:
5619 break;
5621 return false;
5624 /* Calculate the cost of a memory address. */
5626 static int
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)
5633 return 18;
5634 if (CONSTANT_ADDRESS_P (x))
5636 if (optimize > 0 && io_address_operand (x, QImode))
5637 return 2;
5638 return 4;
5640 return 4;
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);
5663 debug_rtx (x);
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 */
5673 return 0;
5676 /* Convert condition code CONDITION to the valid AVR condition code. */
5678 RTX_CODE
5679 avr_normalize_condition (RTX_CODE condition)
5681 switch (condition)
5683 case GT:
5684 return GE;
5685 case GTU:
5686 return GEU;
5687 case LE:
5688 return LT;
5689 case LEU:
5690 return LTU;
5691 default:
5692 gcc_unreachable ();
5696 /* This function optimizes conditional jumps. */
5698 static void
5699 avr_reorg (void)
5701 rtx insn, pattern;
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))
5709 continue;
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,
5766 SET_SRC (pattern));
5767 INSN_CODE (next) = -1;
5768 INSN_CODE (insn) = -1;
5774 /* Returns register number for function return value.*/
5777 avr_ret_register (void)
5779 return 24;
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);
5789 if (offs < 2)
5790 offs = 2;
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)
5802 unsigned int offs;
5804 if (TYPE_MODE (type) != BLKmode)
5805 return avr_libcall_value (TYPE_MODE (type));
5807 offs = int_size_in_bytes (type);
5808 if (offs < 2)
5809 offs = 2;
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
5820 in class CLASS. */
5822 enum reg_class
5823 preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class rclass)
5825 return rclass;
5829 test_hard_reg_class (enum reg_class rclass, rtx x)
5831 int regno = true_regnum (x);
5832 if (regno < 0)
5833 return 0;
5835 if (TEST_HARD_REG_CLASS (rclass, regno))
5836 return 1;
5838 return 0;
5843 jump_over_one_insn_p (rtx insn, rtx dest)
5845 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5846 ? XEXP (dest, 0)
5847 : dest);
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)
5863 return 0;
5865 /* The only thing that can go into registers r28:r29 is a Pmode. */
5866 if (regno == REG_Y && mode == Pmode)
5867 return 1;
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))
5871 return 0;
5873 if (mode == QImode)
5874 return 1;
5876 /* Modes larger than QImode occupy consecutive registers. */
5877 if (regno + GET_MODE_SIZE (mode) > FIRST_PSEUDO_REGISTER)
5878 return 0;
5880 /* All modes larger than QImode should start in an even register. */
5881 return !(regno & 1);
5884 const char *
5885 output_reload_inhi (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
5887 int tmp;
5888 if (!len)
5889 len = &tmp;
5891 if (GET_CODE (operands[1]) == CONST_INT)
5893 int val = INTVAL (operands[1]);
5894 if ((val & 0xff) == 0)
5896 *len = 3;
5897 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5898 AS2 (ldi,%2,hi8(%1)) CR_TAB
5899 AS2 (mov,%B0,%2));
5901 else if ((val & 0xff00) == 0)
5903 *len = 3;
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))
5910 *len = 3;
5911 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5912 AS2 (mov,%A0,%2) CR_TAB
5913 AS2 (mov,%B0,%2));
5916 *len = 4;
5917 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5918 AS2 (mov,%A0,%2) CR_TAB
5919 AS2 (ldi,%2,hi8(%1)) CR_TAB
5920 AS2 (mov,%B0,%2));
5924 const char *
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);
5930 if (len)
5932 if (cnst)
5933 *len = 4 + ((INTVAL (src) & 0xff) != 0)
5934 + ((INTVAL (src) & 0xff00) != 0)
5935 + ((INTVAL (src) & 0xff0000) != 0)
5936 + ((INTVAL (src) & 0xff000000) != 0);
5937 else
5938 *len = 8;
5940 return "";
5943 if (cnst && ((INTVAL (src) & 0xff) == 0))
5944 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5945 else
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);
5952 else
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);
5959 else
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);
5966 else
5968 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5969 output_asm_insn (AS2 (mov, %D0, %2), operands);
5971 return "";
5974 void
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);
5984 void
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);
5990 else
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. */
5997 bool
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))
6005 return false;
6007 return true;
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
6018 call-clobbered. */
6020 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
6021 && !df_regs_ever_live_p (new_reg))
6022 return 0;
6024 return 1;
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. */
6035 const char *
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]);
6042 if (comp == GE)
6043 comp = EQ;
6044 else if (comp == LT)
6045 comp = NE;
6047 if (reverse)
6048 comp = reverse_condition (comp);
6050 if (GET_CODE (operands[1]) == CONST_INT)
6052 if (INTVAL (operands[1]) < 0x40)
6054 if (comp == EQ)
6055 output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
6056 else
6057 output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
6059 else
6061 output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
6062 if (comp == EQ)
6063 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
6064 else
6065 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
6068 else /* GET_CODE (operands[1]) == REG */
6070 if (GET_MODE (operands[1]) == QImode)
6072 if (comp == EQ)
6073 output_asm_insn (AS2 (sbrs,%1,%2), operands);
6074 else
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);
6090 if (long_jump)
6091 return (AS1 (rjmp,.+4) CR_TAB
6092 AS1 (jmp,%3));
6093 if (!reverse)
6094 return AS1 (rjmp,%3);
6095 return "";
6098 /* Worker function for TARGET_ASM_CONSTRUCTOR. */
6100 static void
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. */
6109 static void
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. */
6118 static bool
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);
6126 else
6127 return false;
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;
6137 #include "gt-avr.h"