1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004
3 Free Software Foundation, Inc.
4 Contributed by Denis Chertykov (denisc@overta.ru)
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
25 #include "coretypes.h"
29 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-attr.h"
46 #include "target-def.h"
48 /* Maximal allowed offset for an address in the LD command */
49 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
51 static int avr_naked_function_p (tree);
52 static int interrupt_function_p (tree);
53 static int signal_function_p (tree);
54 static int avr_regs_to_save (HARD_REG_SET *);
55 static int sequent_regs_live (void);
56 static const char *ptrreg_to_str (int);
57 static const char *cond_string (enum rtx_code);
58 static int avr_num_arg_regs (enum machine_mode, tree);
59 static int out_adj_frame_ptr (FILE *, int);
60 static int out_set_stack_ptr (FILE *, int, int);
61 static RTX_CODE compare_condition (rtx insn);
62 static int compare_sign_p (rtx insn);
63 static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *);
64 static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
65 const struct attribute_spec avr_attribute_table[];
66 static bool avr_assemble_integer (rtx, unsigned int, int);
67 static void avr_file_start (void);
68 static void avr_file_end (void);
69 static void avr_output_function_prologue (FILE *, HOST_WIDE_INT);
70 static void avr_output_function_epilogue (FILE *, HOST_WIDE_INT);
71 static void avr_insert_attributes (tree, tree *);
72 static unsigned int avr_section_type_flags (tree, const char *, int);
74 static void avr_reorg (void);
75 static void avr_asm_out_ctor (rtx, int);
76 static void avr_asm_out_dtor (rtx, int);
77 static int default_rtx_costs (rtx, enum rtx_code, enum rtx_code);
78 static bool avr_rtx_costs (rtx, int, int, int *);
79 static int avr_address_cost (rtx);
80 static bool avr_return_in_memory (tree, tree);
82 /* Allocate registers from r25 to r8 for parameters for function calls. */
83 #define FIRST_CUM_REG 26
85 /* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */
86 static GTY(()) rtx tmp_reg_rtx;
88 /* Zeroed register RTX (gen_rtx_REG (QImode, ZERO_REGNO)) */
89 static GTY(()) rtx zero_reg_rtx;
91 /* AVR register names {"r0", "r1", ..., "r31"} */
92 static const char *const avr_regnames[] = REGISTER_NAMES;
94 /* This holds the last insn address. */
95 static int last_insn_address = 0;
97 /* Commands count in the compiled file */
98 static int commands_in_file;
100 /* Commands in the functions prologues in the compiled file */
101 static int commands_in_prologues;
103 /* Commands in the functions epilogues in the compiled file */
104 static int commands_in_epilogues;
106 /* Prologue/Epilogue size in words */
107 static int prologue_size;
108 static int epilogue_size;
110 /* Size of all jump tables in the current function, in words. */
111 static int jump_tables_size;
113 /* Initial stack value specified by the `-minit-stack=' option */
114 const char *avr_init_stack = "__stack";
116 /* Default MCU name */
117 const char *avr_mcu_name = "avr2";
119 /* Preprocessor macros to define depending on MCU type. */
120 const char *avr_base_arch_macro;
121 const char *avr_extra_arch_macro;
123 /* More than 8K of program memory: use "call" and "jmp". */
126 /* Enhanced core: use "movw", "mul", ... */
127 int avr_enhanced_p = 0;
129 /* Assembler only. */
130 int avr_asm_only_p = 0;
136 const char *const macro;
139 static const struct base_arch_s avr_arch_types[] = {
140 { 1, 0, 0, NULL }, /* unknown device specified */
141 { 1, 0, 0, "__AVR_ARCH__=1" },
142 { 0, 0, 0, "__AVR_ARCH__=2" },
143 { 0, 0, 1, "__AVR_ARCH__=3" },
144 { 0, 1, 0, "__AVR_ARCH__=4" },
145 { 0, 1, 1, "__AVR_ARCH__=5" }
149 const char *const name;
150 int arch; /* index in avr_arch_types[] */
151 /* Must lie outside user's namespace. NULL == no macro. */
152 const char *const macro;
155 /* List of all known AVR MCU types - if updated, it has to be kept
156 in sync in several places (FIXME: is there a better way?):
158 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
159 - t-avr (MULTILIB_MATCHES)
160 - gas/config/tc-avr.c
163 static const struct mcu_type_s avr_mcu_types[] = {
164 /* Classic, <= 8K. */
166 { "at90s2313", 2, "__AVR_AT90S2313__" },
167 { "at90s2323", 2, "__AVR_AT90S2323__" },
168 { "at90s2333", 2, "__AVR_AT90S2333__" },
169 { "at90s2343", 2, "__AVR_AT90S2343__" },
170 { "attiny22", 2, "__AVR_ATtiny22__" },
171 { "attiny26", 2, "__AVR_ATtiny26__" },
172 { "at90s4414", 2, "__AVR_AT90S4414__" },
173 { "at90s4433", 2, "__AVR_AT90S4433__" },
174 { "at90s4434", 2, "__AVR_AT90S4434__" },
175 { "at90s8515", 2, "__AVR_AT90S8515__" },
176 { "at90c8534", 2, "__AVR_AT90C8534__" },
177 { "at90s8535", 2, "__AVR_AT90S8535__" },
178 { "at86rf401", 2, "__AVR_AT86RF401__" },
181 { "atmega103", 3, "__AVR_ATmega103__" },
182 { "atmega603", 3, "__AVR_ATmega603__" },
183 { "at43usb320", 3, "__AVR_AT43USB320__" },
184 { "at43usb355", 3, "__AVR_AT43USB355__" },
185 { "at76c711", 3, "__AVR_AT76C711__" },
186 /* Enhanced, <= 8K. */
188 { "atmega8", 4, "__AVR_ATmega8__" },
189 { "atmega48", 4, "__AVR_ATmega48__" },
190 { "atmega88", 4, "__AVR_ATmega88__" },
191 { "atmega8515", 4, "__AVR_ATmega8515__" },
192 { "atmega8535", 4, "__AVR_ATmega8535__" },
193 { "attiny13", 4, "__AVR_ATtiny13__" },
194 { "attiny2313", 4, "__AVR_ATtiny2313__" },
195 /* Enhanced, > 8K. */
197 { "atmega16", 5, "__AVR_ATmega16__" },
198 { "atmega161", 5, "__AVR_ATmega161__" },
199 { "atmega162", 5, "__AVR_ATmega162__" },
200 { "atmega163", 5, "__AVR_ATmega163__" },
201 { "atmega165", 5, "__AVR_ATmega165__" },
202 { "atmega168", 5, "__AVR_ATmega168__" },
203 { "atmega169", 5, "__AVR_ATmega169__" },
204 { "atmega32", 5, "__AVR_ATmega32__" },
205 { "atmega323", 5, "__AVR_ATmega323__" },
206 { "atmega325", 5, "__AVR_ATmega325__" },
207 { "atmega3250", 5, "__AVR_ATmega3250__" },
208 { "atmega64", 5, "__AVR_ATmega64__" },
209 { "atmega645", 5, "__AVR_ATmega645__" },
210 { "atmega6450", 5, "__AVR_ATmega6450__" },
211 { "atmega128", 5, "__AVR_ATmega128__" },
212 { "at90can128", 5, "__AVR_AT90CAN128__" },
213 { "at94k", 5, "__AVR_AT94K__" },
214 /* Assembler only. */
216 { "at90s1200", 1, "__AVR_AT90S1200__" },
217 { "attiny11", 1, "__AVR_ATtiny11__" },
218 { "attiny12", 1, "__AVR_ATtiny12__" },
219 { "attiny15", 1, "__AVR_ATtiny15__" },
220 { "attiny28", 1, "__AVR_ATtiny28__" },
224 int avr_case_values_threshold = 30000;
226 /* Initialize the GCC target structure. */
227 #undef TARGET_ASM_ALIGNED_HI_OP
228 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
229 #undef TARGET_ASM_INTEGER
230 #define TARGET_ASM_INTEGER avr_assemble_integer
231 #undef TARGET_ASM_FILE_START
232 #define TARGET_ASM_FILE_START avr_file_start
233 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
234 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
235 #undef TARGET_ASM_FILE_END
236 #define TARGET_ASM_FILE_END avr_file_end
238 #undef TARGET_ASM_FUNCTION_PROLOGUE
239 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
240 #undef TARGET_ASM_FUNCTION_EPILOGUE
241 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
242 #undef TARGET_ATTRIBUTE_TABLE
243 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
244 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
245 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
246 #undef TARGET_INSERT_ATTRIBUTES
247 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
248 #undef TARGET_SECTION_TYPE_FLAGS
249 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
250 #undef TARGET_RTX_COSTS
251 #define TARGET_RTX_COSTS avr_rtx_costs
252 #undef TARGET_ADDRESS_COST
253 #define TARGET_ADDRESS_COST avr_address_cost
254 #undef TARGET_MACHINE_DEPENDENT_REORG
255 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
257 #undef TARGET_RETURN_IN_MEMORY
258 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
260 #undef TARGET_STRICT_ARGUMENT_NAMING
261 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
263 struct gcc_target targetm = TARGET_INITIALIZER;
266 avr_override_options (void)
268 const struct mcu_type_s *t;
269 const struct base_arch_s *base;
271 for (t = avr_mcu_types; t->name; t++)
272 if (strcmp (t->name, avr_mcu_name) == 0)
277 fprintf (stderr, "unknown MCU `%s' specified\nKnown MCU names:\n",
279 for (t = avr_mcu_types; t->name; t++)
280 fprintf (stderr," %s\n", t->name);
283 base = &avr_arch_types[t->arch];
284 avr_asm_only_p = base->asm_only;
285 avr_enhanced_p = base->enhanced;
286 avr_mega_p = base->mega;
287 avr_base_arch_macro = base->macro;
288 avr_extra_arch_macro = t->macro;
290 if (optimize && !TARGET_NO_TABLEJUMP)
291 avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
293 tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO);
294 zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO);
297 /* return register class from register number. */
299 static const int reg_class_tab[]={
300 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
301 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
302 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
303 GENERAL_REGS, /* r0 - r15 */
304 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
305 LD_REGS, /* r16 - 23 */
306 ADDW_REGS,ADDW_REGS, /* r24,r25 */
307 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
308 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
309 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
310 STACK_REG,STACK_REG /* SPL,SPH */
313 /* Return register class for register R. */
316 avr_regno_reg_class (int r)
319 return reg_class_tab[r];
324 /* A C expression which defines the machine-dependent operand
325 constraint letters for register classes. If C is such a
326 letter, the value should be the register class corresponding to
327 it. Otherwise, the value should be `NO_REGS'. The register
328 letter `r', corresponding to class `GENERAL_REGS', will not be
329 passed to this macro; you do not need to handle it. */
332 avr_reg_class_from_letter (int c)
336 case 't' : return R0_REG;
337 case 'b' : return BASE_POINTER_REGS;
338 case 'e' : return POINTER_REGS;
339 case 'w' : return ADDW_REGS;
340 case 'd' : return LD_REGS;
341 case 'l' : return NO_LD_REGS;
342 case 'a' : return SIMPLE_LD_REGS;
343 case 'x' : return POINTER_X_REGS;
344 case 'y' : return POINTER_Y_REGS;
345 case 'z' : return POINTER_Z_REGS;
346 case 'q' : return STACK_REG;
352 /* Return nonzero if FUNC is a naked function. */
355 avr_naked_function_p (tree func)
359 if (TREE_CODE (func) != FUNCTION_DECL)
362 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
363 return a != NULL_TREE;
366 /* Return nonzero if FUNC is an interrupt function as specified
367 by the "interrupt" attribute. */
370 interrupt_function_p (tree func)
374 if (TREE_CODE (func) != FUNCTION_DECL)
377 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
378 return a != NULL_TREE;
381 /* Return nonzero if FUNC is a signal function as specified
382 by the "signal" attribute. */
385 signal_function_p (tree func)
389 if (TREE_CODE (func) != FUNCTION_DECL)
392 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
393 return a != NULL_TREE;
396 /* Return the number of hard registers to push/pop in the prologue/epilogue
397 of the current function, and optionally store these registers in SET. */
400 avr_regs_to_save (HARD_REG_SET *set)
403 int int_or_sig_p = (interrupt_function_p (current_function_decl)
404 || signal_function_p (current_function_decl));
405 int leaf_func_p = leaf_function_p ();
408 CLEAR_HARD_REG_SET (*set);
411 /* No need to save any registers if the function never returns. */
412 if (TREE_THIS_VOLATILE (current_function_decl))
415 for (reg = 0; reg < 32; reg++)
417 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
418 any global register variables. */
422 if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
423 || (regs_ever_live[reg]
424 && (int_or_sig_p || !call_used_regs[reg])
425 && !(frame_pointer_needed
426 && (reg == REG_Y || reg == (REG_Y+1)))))
429 SET_HARD_REG_BIT (*set, reg);
436 /* Compute offset between arg_pointer and frame_pointer. */
439 initial_elimination_offset (int from, int to)
441 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
445 int offset = frame_pointer_needed ? 2 : 0;
447 offset += avr_regs_to_save (NULL);
448 return get_frame_size () + 2 + 1 + offset;
452 /* Return 1 if the function epilogue is just a single "ret". */
455 avr_simple_epilogue (void)
457 return (! frame_pointer_needed
458 && get_frame_size () == 0
459 && avr_regs_to_save (NULL) == 0
460 && ! interrupt_function_p (current_function_decl)
461 && ! signal_function_p (current_function_decl)
462 && ! avr_naked_function_p (current_function_decl)
463 && ! MAIN_NAME_P (DECL_NAME (current_function_decl))
464 && ! TREE_THIS_VOLATILE (current_function_decl));
467 /* This function checks sequence of live registers. */
470 sequent_regs_live (void)
476 for (reg = 0; reg < 18; ++reg)
478 if (!call_used_regs[reg])
480 if (regs_ever_live[reg])
490 if (!frame_pointer_needed)
492 if (regs_ever_live[REG_Y])
500 if (regs_ever_live[REG_Y+1])
513 return (cur_seq == live_seq) ? live_seq : 0;
517 /* Output to FILE the asm instructions to adjust the frame pointer by
518 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
519 (epilogue). Returns the number of instructions generated. */
522 out_adj_frame_ptr (FILE *file, int adj)
528 if (TARGET_TINY_STACK)
530 if (adj < -63 || adj > 63)
531 warning ("large frame pointer change (%d) with -mtiny-stack", adj);
533 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
534 over "sbiw" (2 cycles, same size). */
536 fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
539 else if (adj < -63 || adj > 63)
541 fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
542 AS2 (sbci, r29, hi8(%d)) CR_TAB),
548 fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
553 fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
561 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
562 handling various cases of interrupt enable flag state BEFORE and AFTER
563 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
564 Returns the number of instructions generated. */
567 out_set_stack_ptr (FILE *file, int before, int after)
569 int do_sph, do_cli, do_save, do_sei, lock_sph, size;
571 /* The logic here is so that -mno-interrupts actually means
572 "it is safe to write SPH in one instruction, then SPL in the
573 next instruction, without disabling interrupts first".
574 The after != -1 case (interrupt/signal) is not affected. */
576 do_sph = !TARGET_TINY_STACK;
577 lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
578 do_cli = (before != 0 && (after == 0 || lock_sph));
579 do_save = (do_cli && before == -1 && after == -1);
580 do_sei = ((do_cli || before != 1) && after == 1);
585 fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
591 fprintf (file, "cli" CR_TAB);
595 /* Do SPH first - maybe this will disable interrupts for one instruction
596 someday (a suggestion has been sent to avr@atmel.com for consideration
597 in future devices - that would make -mno-interrupts always safe). */
600 fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
604 /* Set/restore the I flag now - interrupts will be really enabled only
605 after the next instruction. This is not clearly documented, but
606 believed to be true for all AVR devices. */
609 fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
614 fprintf (file, "sei" CR_TAB);
618 fprintf (file, AS2 (out, __SP_L__, r28) "\n");
624 /* Output function prologue. */
627 avr_output_function_prologue (FILE *file, HOST_WIDE_INT size)
630 int interrupt_func_p;
636 last_insn_address = 0;
637 jump_tables_size = 0;
639 fprintf (file, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n",
642 if (avr_naked_function_p (current_function_decl))
644 fputs ("/* prologue: naked */\n", file);
648 interrupt_func_p = interrupt_function_p (current_function_decl);
649 signal_func_p = signal_function_p (current_function_decl);
650 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
651 live_seq = sequent_regs_live ();
652 minimize = (TARGET_CALL_PROLOGUES
653 && !interrupt_func_p && !signal_func_p && live_seq);
655 if (interrupt_func_p)
657 fprintf (file,"\tsei\n");
660 if (interrupt_func_p || signal_func_p)
663 AS1 (push,__zero_reg__) CR_TAB
664 AS1 (push,__tmp_reg__) CR_TAB
665 AS2 (in,__tmp_reg__,__SREG__) CR_TAB
666 AS1 (push,__tmp_reg__) CR_TAB
667 AS1 (clr,__zero_reg__) "\n");
673 AS1 (ldi,r28) ",lo8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
674 AS1 (ldi,r29) ",hi8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
675 AS2 (out,__SP_H__,r29) CR_TAB
676 AS2 (out,__SP_L__,r28) "\n"),
677 avr_init_stack, size, avr_init_stack, size);
681 else if (minimize && (frame_pointer_needed || live_seq > 6))
683 const char *cfun_name = current_function_name ();
685 AS1 (ldi, r26) ",lo8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
686 AS1 (ldi, r27) ",hi8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB), size, size);
688 fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB
689 AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB),
690 cfun_name, cfun_name);
696 fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
697 (18 - live_seq) * 2);
702 fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
703 (18 - live_seq) * 2);
706 fprintf (file, ".L_%s_body:\n", cfun_name);
712 prologue_size += avr_regs_to_save (&set);
713 for (reg = 0; reg < 32; ++reg)
715 if (TEST_HARD_REG_BIT (set, reg))
717 fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
720 if (frame_pointer_needed)
723 AS1 (push,r28) CR_TAB
724 AS1 (push,r29) CR_TAB
725 AS2 (in,r28,__SP_L__) CR_TAB
726 AS2 (in,r29,__SP_H__) "\n");
731 prologue_size += out_adj_frame_ptr (file, size);
733 if (interrupt_func_p)
735 prologue_size += out_set_stack_ptr (file, 1, 1);
737 else if (signal_func_p)
739 prologue_size += out_set_stack_ptr (file, 0, 0);
743 prologue_size += out_set_stack_ptr (file, -1, -1);
750 fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
753 /* Output function epilogue. */
756 avr_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
759 int interrupt_func_p;
765 rtx last = get_last_nonnote_insn ();
767 function_size = jump_tables_size;
770 rtx first = get_first_nonnote_insn ();
771 function_size += (INSN_ADDRESSES (INSN_UID (last)) -
772 INSN_ADDRESSES (INSN_UID (first)));
773 function_size += get_attr_length (last);
776 fprintf (file, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n", size);
779 if (avr_naked_function_p (current_function_decl))
781 fputs ("/* epilogue: naked */\n", file);
785 if (last && GET_CODE (last) == BARRIER)
787 fputs ("/* epilogue: noreturn */\n", file);
791 interrupt_func_p = interrupt_function_p (current_function_decl);
792 signal_func_p = signal_function_p (current_function_decl);
793 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
794 live_seq = sequent_regs_live ();
795 minimize = (TARGET_CALL_PROLOGUES
796 && !interrupt_func_p && !signal_func_p && live_seq);
800 /* Return value from main() is already in the correct registers
801 (r25:r24) as the exit() argument. */
804 fputs ("\t" AS1 (jmp,exit) "\n", file);
809 fputs ("\t" AS1 (rjmp,exit) "\n", file);
813 else if (minimize && (frame_pointer_needed || live_seq > 4))
815 fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
817 if (frame_pointer_needed)
819 epilogue_size += out_adj_frame_ptr (file, -size);
823 fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
824 AS2 (in , r29, __SP_H__) CR_TAB));
830 fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
831 (18 - live_seq) * 2);
836 fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
837 (18 - live_seq) * 2);
845 if (frame_pointer_needed)
850 epilogue_size += out_adj_frame_ptr (file, -size);
852 if (interrupt_func_p || signal_func_p)
854 epilogue_size += out_set_stack_ptr (file, -1, 0);
858 epilogue_size += out_set_stack_ptr (file, -1, -1);
867 epilogue_size += avr_regs_to_save (&set);
868 for (reg = 31; reg >= 0; --reg)
870 if (TEST_HARD_REG_BIT (set, reg))
872 fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
876 if (interrupt_func_p || signal_func_p)
879 AS1 (pop,__tmp_reg__) CR_TAB
880 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
881 AS1 (pop,__tmp_reg__) CR_TAB
882 AS1 (pop,__zero_reg__) "\n");
884 fprintf (file, "\treti\n");
887 fprintf (file, "\tret\n");
892 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
893 fprintf (file, "/* function %s size %d (%d) */\n", current_function_name (),
894 prologue_size + function_size + epilogue_size, function_size);
895 commands_in_file += prologue_size + function_size + epilogue_size;
896 commands_in_prologues += prologue_size;
897 commands_in_epilogues += epilogue_size;
901 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
902 machine for a memory operand of mode MODE. */
905 legitimate_address_p (enum machine_mode mode, rtx x, int strict)
907 enum reg_class r = NO_REGS;
909 if (TARGET_ALL_DEBUG)
911 fprintf (stderr, "mode: (%s) %s %s %s %s:",
913 strict ? "(strict)": "",
914 reload_completed ? "(reload_completed)": "",
915 reload_in_progress ? "(reload_in_progress)": "",
916 reg_renumber ? "(reg_renumber)" : "");
917 if (GET_CODE (x) == PLUS
918 && REG_P (XEXP (x, 0))
919 && GET_CODE (XEXP (x, 1)) == CONST_INT
920 && INTVAL (XEXP (x, 1)) >= 0
921 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
924 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
925 true_regnum (XEXP (x, 0)));
928 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
929 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
931 else if (CONSTANT_ADDRESS_P (x))
933 else if (GET_CODE (x) == PLUS
934 && REG_P (XEXP (x, 0))
935 && GET_CODE (XEXP (x, 1)) == CONST_INT
936 && INTVAL (XEXP (x, 1)) >= 0)
938 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
942 || REGNO (XEXP (x,0)) == REG_Y
943 || REGNO (XEXP (x,0)) == REG_Z)
944 r = BASE_POINTER_REGS;
945 if (XEXP (x,0) == frame_pointer_rtx
946 || XEXP (x,0) == arg_pointer_rtx)
947 r = BASE_POINTER_REGS;
949 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
952 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
953 && REG_P (XEXP (x, 0))
954 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
955 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
959 if (TARGET_ALL_DEBUG)
961 fprintf (stderr, " ret = %c\n", r);
963 return r == NO_REGS ? 0 : (int)r;
966 /* Attempts to replace X with a valid
967 memory address for an operand of mode MODE */
970 legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
973 if (TARGET_ALL_DEBUG)
975 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
979 if (GET_CODE (oldx) == PLUS
980 && REG_P (XEXP (oldx,0)))
982 if (REG_P (XEXP (oldx,1)))
983 x = force_reg (GET_MODE (oldx), oldx);
984 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
986 int offs = INTVAL (XEXP (oldx,1));
987 if (frame_pointer_rtx != XEXP (oldx,0))
988 if (offs > MAX_LD_OFFSET (mode))
990 if (TARGET_ALL_DEBUG)
991 fprintf (stderr, "force_reg (big offset)\n");
992 x = force_reg (GET_MODE (oldx), oldx);
1000 /* Return a pointer register name as a string. */
1003 ptrreg_to_str (int regno)
1007 case REG_X: return "X";
1008 case REG_Y: return "Y";
1009 case REG_Z: return "Z";
1016 /* Return the condition name as a string.
1017 Used in conditional jump constructing */
1020 cond_string (enum rtx_code code)
1029 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1034 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1047 /* Output ADDR to FILE as address. */
1050 print_operand_address (FILE *file, rtx addr)
1052 switch (GET_CODE (addr))
1055 fprintf (file, ptrreg_to_str (REGNO (addr)));
1059 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1063 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1067 if (CONSTANT_ADDRESS_P (addr)
1068 && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
1069 || GET_CODE (addr) == LABEL_REF))
1071 fprintf (file, "pm(");
1072 output_addr_const (file,addr);
1073 fprintf (file ,")");
1076 output_addr_const (file, addr);
1081 /* Output X as assembler operand to file FILE. */
1084 print_operand (FILE *file, rtx x, int code)
1088 if (code >= 'A' && code <= 'D')
1098 if (x == zero_reg_rtx)
1099 fprintf (file, "__zero_reg__");
1101 fprintf (file, reg_names[true_regnum (x) + abcd]);
1103 else if (GET_CODE (x) == CONST_INT)
1104 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
1105 else if (GET_CODE (x) == MEM)
1107 rtx addr = XEXP (x,0);
1109 if (CONSTANT_P (addr) && abcd)
1112 output_address (addr);
1113 fprintf (file, ")+%d", abcd);
1115 else if (code == 'o')
1117 if (GET_CODE (addr) != PLUS)
1118 fatal_insn ("bad address, not (reg+disp):", addr);
1120 print_operand (file, XEXP (addr, 1), 0);
1122 else if (GET_CODE (addr) == PLUS)
1124 print_operand_address (file, XEXP (addr,0));
1125 if (REGNO (XEXP (addr, 0)) == REG_X)
1126 fatal_insn ("internal compiler error. Bad address:"
1129 print_operand (file, XEXP (addr,1), code);
1132 print_operand_address (file, addr);
1134 else if (GET_CODE (x) == CONST_DOUBLE)
1138 if (GET_MODE (x) != SFmode)
1139 fatal_insn ("internal compiler error. Unknown mode:", x);
1140 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1141 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1142 fprintf (file, "0x%lx", val);
1144 else if (code == 'j')
1145 fputs (cond_string (GET_CODE (x)), file);
1146 else if (code == 'k')
1147 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
1149 print_operand_address (file, x);
1152 /* Recognize operand OP of mode MODE used in call instructions. */
1155 call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1157 if (GET_CODE (op) == MEM)
1159 rtx inside = XEXP (op, 0);
1160 if (register_operand (inside, Pmode))
1162 if (CONSTANT_ADDRESS_P (inside))
1168 /* Update the condition code in the INSN. */
1171 notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
1175 switch (get_attr_cc (insn))
1178 /* Insn does not affect CC at all. */
1186 set = single_set (insn);
1190 cc_status.flags |= CC_NO_OVERFLOW;
1191 cc_status.value1 = SET_DEST (set);
1196 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1197 The V flag may or may not be known but that's ok because
1198 alter_cond will change tests to use EQ/NE. */
1199 set = single_set (insn);
1203 cc_status.value1 = SET_DEST (set);
1204 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1209 set = single_set (insn);
1212 cc_status.value1 = SET_SRC (set);
1216 /* Insn doesn't leave CC in a usable state. */
1219 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1220 set = single_set (insn);
1223 rtx src = SET_SRC (set);
1225 if (GET_CODE (src) == ASHIFTRT
1226 && GET_MODE (src) == QImode)
1228 rtx x = XEXP (src, 1);
1230 if (GET_CODE (x) == CONST_INT
1233 cc_status.value1 = SET_DEST (set);
1234 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1242 /* Return maximum number of consecutive registers of
1243 class CLASS needed to hold a value of mode MODE. */
1246 class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,enum machine_mode mode)
1248 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1251 /* Choose mode for jump insn:
1252 1 - relative jump in range -63 <= x <= 62 ;
1253 2 - relative jump in range -2046 <= x <= 2045 ;
1254 3 - absolute jump (only for ATmega[16]03). */
1257 avr_jump_mode (rtx x, rtx insn)
1259 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1260 ? XEXP (x, 0) : x));
1261 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1262 int jump_distance = cur_addr - dest_addr;
1264 if (-63 <= jump_distance && jump_distance <= 62)
1266 else if (-2046 <= jump_distance && jump_distance <= 2045)
1274 /* return an AVR condition jump commands.
1275 X is a comparison RTX.
1276 LEN is a number returned by avr_jump_mode function.
1277 if REVERSE nonzero then condition code in X must be reversed. */
1280 ret_cond_branch (rtx x, int len, int reverse)
1282 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1287 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1288 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1290 len == 2 ? (AS1 (breq,.+4) CR_TAB
1291 AS1 (brmi,.+2) CR_TAB
1293 (AS1 (breq,.+6) CR_TAB
1294 AS1 (brmi,.+4) CR_TAB
1298 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1300 len == 2 ? (AS1 (breq,.+4) CR_TAB
1301 AS1 (brlt,.+2) CR_TAB
1303 (AS1 (breq,.+6) CR_TAB
1304 AS1 (brlt,.+4) CR_TAB
1307 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1309 len == 2 ? (AS1 (breq,.+4) CR_TAB
1310 AS1 (brlo,.+2) CR_TAB
1312 (AS1 (breq,.+6) CR_TAB
1313 AS1 (brlo,.+4) CR_TAB
1316 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1317 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1319 len == 2 ? (AS1 (breq,.+2) CR_TAB
1320 AS1 (brpl,.+2) CR_TAB
1322 (AS1 (breq,.+2) CR_TAB
1323 AS1 (brpl,.+4) CR_TAB
1326 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1328 len == 2 ? (AS1 (breq,.+2) CR_TAB
1329 AS1 (brge,.+2) CR_TAB
1331 (AS1 (breq,.+2) CR_TAB
1332 AS1 (brge,.+4) CR_TAB
1335 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1337 len == 2 ? (AS1 (breq,.+2) CR_TAB
1338 AS1 (brsh,.+2) CR_TAB
1340 (AS1 (breq,.+2) CR_TAB
1341 AS1 (brsh,.+4) CR_TAB
1349 return AS1 (br%k1,%0);
1351 return (AS1 (br%j1,.+2) CR_TAB
1354 return (AS1 (br%j1,.+4) CR_TAB
1363 return AS1 (br%j1,%0);
1365 return (AS1 (br%k1,.+2) CR_TAB
1368 return (AS1 (br%k1,.+4) CR_TAB
1376 /* Predicate function for immediate operand which fits to byte (8bit) */
1379 byte_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1381 return (GET_CODE (op) == CONST_INT
1382 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1385 /* Output all insn addresses and their sizes into the assembly language
1386 output file. This is helpful for debugging whether the length attributes
1387 in the md file are correct.
1388 Output insn cost for next insn. */
1391 final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
1392 int num_operands ATTRIBUTE_UNUSED)
1394 int uid = INSN_UID (insn);
1396 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1398 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1399 INSN_ADDRESSES (uid),
1400 INSN_ADDRESSES (uid) - last_insn_address,
1401 rtx_cost (PATTERN (insn), INSN));
1403 last_insn_address = INSN_ADDRESSES (uid);
1406 /* Return 0 if undefined, 1 if always true or always false. */
1409 avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE operator, rtx x)
1411 unsigned int max = (mode == QImode ? 0xff :
1412 mode == HImode ? 0xffff :
1413 mode == SImode ? 0xffffffff : 0);
1414 if (max && operator && GET_CODE (x) == CONST_INT)
1416 if (unsigned_condition (operator) != operator)
1419 if (max != (INTVAL (x) & max)
1420 && INTVAL (x) != 0xff)
1427 /* Returns nonzero if REGNO is the number of a hard
1428 register in which function arguments are sometimes passed. */
1431 function_arg_regno_p(int r)
1433 return (r >= 8 && r <= 25);
1436 /* Initializing the variable cum for the state at the beginning
1437 of the argument list. */
1440 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
1441 tree fndecl ATTRIBUTE_UNUSED)
1444 cum->regno = FIRST_CUM_REG;
1445 if (!libname && fntype)
1447 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1448 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1449 != void_type_node));
1455 /* Returns the number of registers to allocate for a function argument. */
1458 avr_num_arg_regs (enum machine_mode mode, tree type)
1462 if (mode == BLKmode)
1463 size = int_size_in_bytes (type);
1465 size = GET_MODE_SIZE (mode);
1467 /* Align all function arguments to start in even-numbered registers.
1468 Odd-sized arguments leave holes above them. */
1470 return (size + 1) & ~1;
1473 /* Controls whether a function argument is passed
1474 in a register, and which register. */
1477 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1478 int named ATTRIBUTE_UNUSED)
1480 int bytes = avr_num_arg_regs (mode, type);
1482 if (cum->nregs && bytes <= cum->nregs)
1483 return gen_rtx_REG (mode, cum->regno - bytes);
1488 /* Update the summarizer variable CUM to advance past an argument
1489 in the argument list. */
1492 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1493 int named ATTRIBUTE_UNUSED)
1495 int bytes = avr_num_arg_regs (mode, type);
1497 cum->nregs -= bytes;
1498 cum->regno -= bytes;
1500 if (cum->nregs <= 0)
1503 cum->regno = FIRST_CUM_REG;
1507 /***********************************************************************
1508 Functions for outputting various mov's for a various modes
1509 ************************************************************************/
1511 output_movqi (rtx insn, rtx operands[], int *l)
1514 rtx dest = operands[0];
1515 rtx src = operands[1];
1523 if (register_operand (dest, QImode))
1525 if (register_operand (src, QImode)) /* mov r,r */
1527 if (test_hard_reg_class (STACK_REG, dest))
1528 return AS2 (out,%0,%1);
1529 else if (test_hard_reg_class (STACK_REG, src))
1530 return AS2 (in,%0,%1);
1532 return AS2 (mov,%0,%1);
1534 else if (CONSTANT_P (src))
1536 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1537 return AS2 (ldi,%0,lo8(%1));
1539 if (GET_CODE (src) == CONST_INT)
1541 if (src == const0_rtx) /* mov r,L */
1542 return AS1 (clr,%0);
1543 else if (src == const1_rtx)
1546 return (AS1 (clr,%0) CR_TAB
1549 else if (src == constm1_rtx)
1551 /* Immediate constants -1 to any register */
1553 return (AS1 (clr,%0) CR_TAB
1558 int bit_nr = exact_log2 (INTVAL (src));
1564 output_asm_insn ((AS1 (clr,%0) CR_TAB
1567 avr_output_bld (operands, bit_nr);
1574 /* Last resort, larger than loading from memory. */
1576 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1577 AS2 (ldi,r31,lo8(%1)) CR_TAB
1578 AS2 (mov,%0,r31) CR_TAB
1579 AS2 (mov,r31,__tmp_reg__));
1581 else if (GET_CODE (src) == MEM)
1582 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1584 else if (GET_CODE (dest) == MEM)
1586 const char *template;
1588 if (src == const0_rtx)
1589 operands[1] = zero_reg_rtx;
1591 template = out_movqi_mr_r (insn, operands, real_l);
1594 output_asm_insn (template, operands);
1603 output_movhi (rtx insn, rtx operands[], int *l)
1606 rtx dest = operands[0];
1607 rtx src = operands[1];
1613 if (register_operand (dest, HImode))
1615 if (register_operand (src, HImode)) /* mov r,r */
1617 if (test_hard_reg_class (STACK_REG, dest))
1619 if (TARGET_TINY_STACK)
1622 return AS2 (out,__SP_L__,%A1);
1624 else if (TARGET_NO_INTERRUPTS)
1627 return (AS2 (out,__SP_H__,%B1) CR_TAB
1628 AS2 (out,__SP_L__,%A1));
1632 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1634 AS2 (out,__SP_H__,%B1) CR_TAB
1635 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1636 AS2 (out,__SP_L__,%A1));
1638 else if (test_hard_reg_class (STACK_REG, src))
1641 return (AS2 (in,%A0,__SP_L__) CR_TAB
1642 AS2 (in,%B0,__SP_H__));
1648 return (AS2 (movw,%0,%1));
1651 if (true_regnum (dest) > true_regnum (src))
1654 return (AS2 (mov,%B0,%B1) CR_TAB
1660 return (AS2 (mov,%A0,%A1) CR_TAB
1664 else if (CONSTANT_P (src))
1666 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1669 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1670 AS2 (ldi,%B0,hi8(%1)));
1673 if (GET_CODE (src) == CONST_INT)
1675 if (src == const0_rtx) /* mov r,L */
1678 return (AS1 (clr,%A0) CR_TAB
1681 else if (src == const1_rtx)
1684 return (AS1 (clr,%A0) CR_TAB
1685 AS1 (clr,%B0) CR_TAB
1688 else if (src == constm1_rtx)
1690 /* Immediate constants -1 to any register */
1692 return (AS1 (clr,%0) CR_TAB
1693 AS1 (dec,%A0) CR_TAB
1698 int bit_nr = exact_log2 (INTVAL (src));
1704 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1705 AS1 (clr,%B0) CR_TAB
1708 avr_output_bld (operands, bit_nr);
1714 if ((INTVAL (src) & 0xff) == 0)
1717 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1718 AS1 (clr,%A0) CR_TAB
1719 AS2 (ldi,r31,hi8(%1)) CR_TAB
1720 AS2 (mov,%B0,r31) CR_TAB
1721 AS2 (mov,r31,__tmp_reg__));
1723 else if ((INTVAL (src) & 0xff00) == 0)
1726 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1727 AS2 (ldi,r31,lo8(%1)) CR_TAB
1728 AS2 (mov,%A0,r31) CR_TAB
1729 AS1 (clr,%B0) CR_TAB
1730 AS2 (mov,r31,__tmp_reg__));
1734 /* Last resort, equal to loading from memory. */
1736 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1737 AS2 (ldi,r31,lo8(%1)) CR_TAB
1738 AS2 (mov,%A0,r31) CR_TAB
1739 AS2 (ldi,r31,hi8(%1)) CR_TAB
1740 AS2 (mov,%B0,r31) CR_TAB
1741 AS2 (mov,r31,__tmp_reg__));
1743 else if (GET_CODE (src) == MEM)
1744 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1746 else if (GET_CODE (dest) == MEM)
1748 const char *template;
1750 if (src == const0_rtx)
1751 operands[1] = zero_reg_rtx;
1753 template = out_movhi_mr_r (insn, operands, real_l);
1756 output_asm_insn (template, operands);
1761 fatal_insn ("invalid insn:", insn);
1766 out_movqi_r_mr (rtx insn, rtx op[], int *l)
1770 rtx x = XEXP (src, 0);
1776 if (CONSTANT_ADDRESS_P (x))
1778 if (avr_io_address_p (x, 1))
1781 return AS2 (in,%0,%1-0x20);
1784 return AS2 (lds,%0,%1);
1786 /* memory access by reg+disp */
1787 else if (GET_CODE (x) == PLUS
1788 && REG_P (XEXP (x,0))
1789 && GET_CODE (XEXP (x,1)) == CONST_INT)
1791 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
1793 int disp = INTVAL (XEXP (x,1));
1794 if (REGNO (XEXP (x,0)) != REG_Y)
1795 fatal_insn ("incorrect insn:",insn);
1797 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1798 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1799 AS2 (ldd,%0,Y+63) CR_TAB
1800 AS2 (sbiw,r28,%o1-63));
1802 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1803 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1804 AS2 (ld,%0,Y) CR_TAB
1805 AS2 (subi,r28,lo8(%o1)) CR_TAB
1806 AS2 (sbci,r29,hi8(%o1)));
1808 else if (REGNO (XEXP (x,0)) == REG_X)
1810 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1811 it but I have this situation with extremal optimizing options. */
1812 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
1813 || reg_unused_after (insn, XEXP (x,0)))
1814 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1817 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1818 AS2 (ld,%0,X) CR_TAB
1819 AS2 (sbiw,r26,%o1));
1822 return AS2 (ldd,%0,%1);
1825 return AS2 (ld,%0,%1);
1829 out_movhi_r_mr (rtx insn, rtx op[], int *l)
1833 rtx base = XEXP (src, 0);
1834 int reg_dest = true_regnum (dest);
1835 int reg_base = true_regnum (base);
1843 if (reg_dest == reg_base) /* R = (R) */
1846 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1847 AS2 (ld,%B0,%1) CR_TAB
1848 AS2 (mov,%A0,__tmp_reg__));
1850 else if (reg_base == REG_X) /* (R26) */
1852 if (reg_unused_after (insn, base))
1855 return (AS2 (ld,%A0,X+) CR_TAB
1859 return (AS2 (ld,%A0,X+) CR_TAB
1860 AS2 (ld,%B0,X) CR_TAB
1866 return (AS2 (ld,%A0,%1) CR_TAB
1867 AS2 (ldd,%B0,%1+1));
1870 else if (GET_CODE (base) == PLUS) /* (R + i) */
1872 int disp = INTVAL (XEXP (base, 1));
1873 int reg_base = true_regnum (XEXP (base, 0));
1875 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
1877 if (REGNO (XEXP (base, 0)) != REG_Y)
1878 fatal_insn ("incorrect insn:",insn);
1880 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1881 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
1882 AS2 (ldd,%A0,Y+62) CR_TAB
1883 AS2 (ldd,%B0,Y+63) CR_TAB
1884 AS2 (sbiw,r28,%o1-62));
1886 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1887 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1888 AS2 (ld,%A0,Y) CR_TAB
1889 AS2 (ldd,%B0,Y+1) CR_TAB
1890 AS2 (subi,r28,lo8(%o1)) CR_TAB
1891 AS2 (sbci,r29,hi8(%o1)));
1893 if (reg_base == REG_X)
1895 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1896 it but I have this situation with extremal
1897 optimization options. */
1900 if (reg_base == reg_dest)
1901 return (AS2 (adiw,r26,%o1) CR_TAB
1902 AS2 (ld,__tmp_reg__,X+) CR_TAB
1903 AS2 (ld,%B0,X) CR_TAB
1904 AS2 (mov,%A0,__tmp_reg__));
1906 return (AS2 (adiw,r26,%o1) CR_TAB
1907 AS2 (ld,%A0,X+) CR_TAB
1908 AS2 (ld,%B0,X) CR_TAB
1909 AS2 (sbiw,r26,%o1+1));
1912 if (reg_base == reg_dest)
1915 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
1916 AS2 (ldd,%B0,%B1) CR_TAB
1917 AS2 (mov,%A0,__tmp_reg__));
1921 return (AS2 (ldd,%A0,%A1) CR_TAB
1924 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
1926 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1927 fatal_insn ("incorrect insn:", insn);
1930 return (AS2 (ld,%B0,%1) CR_TAB
1933 else if (GET_CODE (base) == POST_INC) /* (R++) */
1935 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1936 fatal_insn ("incorrect insn:", insn);
1939 return (AS2 (ld,%A0,%1) CR_TAB
1942 else if (CONSTANT_ADDRESS_P (base))
1944 if (avr_io_address_p (base, 2))
1947 return (AS2 (in,%A0,%A1-0x20) CR_TAB
1948 AS2 (in,%B0,%B1-0x20));
1951 return (AS2 (lds,%A0,%A1) CR_TAB
1955 fatal_insn ("unknown move insn:",insn);
1960 out_movsi_r_mr (rtx insn, rtx op[], int *l)
1964 rtx base = XEXP (src, 0);
1965 int reg_dest = true_regnum (dest);
1966 int reg_base = true_regnum (base);
1974 if (reg_base == REG_X) /* (R26) */
1976 if (reg_dest == REG_X)
1977 /* "ld r26,-X" is undefined */
1978 return *l=7, (AS2 (adiw,r26,3) CR_TAB
1979 AS2 (ld,r29,X) CR_TAB
1980 AS2 (ld,r28,-X) CR_TAB
1981 AS2 (ld,__tmp_reg__,-X) CR_TAB
1982 AS2 (sbiw,r26,1) CR_TAB
1983 AS2 (ld,r26,X) CR_TAB
1984 AS2 (mov,r27,__tmp_reg__));
1985 else if (reg_dest == REG_X - 2)
1986 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
1987 AS2 (ld,%B0,X+) CR_TAB
1988 AS2 (ld,__tmp_reg__,X+) CR_TAB
1989 AS2 (ld,%D0,X) CR_TAB
1990 AS2 (mov,%C0,__tmp_reg__));
1991 else if (reg_unused_after (insn, base))
1992 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
1993 AS2 (ld,%B0,X+) CR_TAB
1994 AS2 (ld,%C0,X+) CR_TAB
1997 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
1998 AS2 (ld,%B0,X+) CR_TAB
1999 AS2 (ld,%C0,X+) CR_TAB
2000 AS2 (ld,%D0,X) CR_TAB
2005 if (reg_dest == reg_base)
2006 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2007 AS2 (ldd,%C0,%1+2) CR_TAB
2008 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2009 AS2 (ld,%A0,%1) CR_TAB
2010 AS2 (mov,%B0,__tmp_reg__));
2011 else if (reg_base == reg_dest + 2)
2012 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2013 AS2 (ldd,%B0,%1+1) CR_TAB
2014 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2015 AS2 (ldd,%D0,%1+3) CR_TAB
2016 AS2 (mov,%C0,__tmp_reg__));
2018 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2019 AS2 (ldd,%B0,%1+1) CR_TAB
2020 AS2 (ldd,%C0,%1+2) CR_TAB
2021 AS2 (ldd,%D0,%1+3));
2024 else if (GET_CODE (base) == PLUS) /* (R + i) */
2026 int disp = INTVAL (XEXP (base, 1));
2028 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2030 if (REGNO (XEXP (base, 0)) != REG_Y)
2031 fatal_insn ("incorrect insn:",insn);
2033 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2034 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2035 AS2 (ldd,%A0,Y+60) CR_TAB
2036 AS2 (ldd,%B0,Y+61) CR_TAB
2037 AS2 (ldd,%C0,Y+62) CR_TAB
2038 AS2 (ldd,%D0,Y+63) CR_TAB
2039 AS2 (sbiw,r28,%o1-60));
2041 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2042 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2043 AS2 (ld,%A0,Y) CR_TAB
2044 AS2 (ldd,%B0,Y+1) CR_TAB
2045 AS2 (ldd,%C0,Y+2) CR_TAB
2046 AS2 (ldd,%D0,Y+3) CR_TAB
2047 AS2 (subi,r28,lo8(%o1)) CR_TAB
2048 AS2 (sbci,r29,hi8(%o1)));
2051 reg_base = true_regnum (XEXP (base, 0));
2052 if (reg_base == REG_X)
2055 if (reg_dest == REG_X)
2058 /* "ld r26,-X" is undefined */
2059 return (AS2 (adiw,r26,%o1+3) CR_TAB
2060 AS2 (ld,r29,X) CR_TAB
2061 AS2 (ld,r28,-X) CR_TAB
2062 AS2 (ld,__tmp_reg__,-X) CR_TAB
2063 AS2 (sbiw,r26,1) CR_TAB
2064 AS2 (ld,r26,X) CR_TAB
2065 AS2 (mov,r27,__tmp_reg__));
2068 if (reg_dest == REG_X - 2)
2069 return (AS2 (adiw,r26,%o1) CR_TAB
2070 AS2 (ld,r24,X+) CR_TAB
2071 AS2 (ld,r25,X+) CR_TAB
2072 AS2 (ld,__tmp_reg__,X+) CR_TAB
2073 AS2 (ld,r27,X) CR_TAB
2074 AS2 (mov,r26,__tmp_reg__));
2076 return (AS2 (adiw,r26,%o1) CR_TAB
2077 AS2 (ld,%A0,X+) CR_TAB
2078 AS2 (ld,%B0,X+) CR_TAB
2079 AS2 (ld,%C0,X+) CR_TAB
2080 AS2 (ld,%D0,X) CR_TAB
2081 AS2 (sbiw,r26,%o1+3));
2083 if (reg_dest == reg_base)
2084 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2085 AS2 (ldd,%C0,%C1) CR_TAB
2086 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2087 AS2 (ldd,%A0,%A1) CR_TAB
2088 AS2 (mov,%B0,__tmp_reg__));
2089 else if (reg_dest == reg_base - 2)
2090 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2091 AS2 (ldd,%B0,%B1) CR_TAB
2092 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2093 AS2 (ldd,%D0,%D1) CR_TAB
2094 AS2 (mov,%C0,__tmp_reg__));
2095 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2096 AS2 (ldd,%B0,%B1) CR_TAB
2097 AS2 (ldd,%C0,%C1) CR_TAB
2100 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2101 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2102 AS2 (ld,%C0,%1) CR_TAB
2103 AS2 (ld,%B0,%1) CR_TAB
2105 else if (GET_CODE (base) == POST_INC) /* (R++) */
2106 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2107 AS2 (ld,%B0,%1) CR_TAB
2108 AS2 (ld,%C0,%1) CR_TAB
2110 else if (CONSTANT_ADDRESS_P (base))
2111 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2112 AS2 (lds,%B0,%B1) CR_TAB
2113 AS2 (lds,%C0,%C1) CR_TAB
2116 fatal_insn ("unknown move insn:",insn);
2121 out_movsi_mr_r (rtx insn, rtx op[], int *l)
2125 rtx base = XEXP (dest, 0);
2126 int reg_base = true_regnum (base);
2127 int reg_src = true_regnum (src);
2133 if (CONSTANT_ADDRESS_P (base))
2134 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2135 AS2 (sts,%B0,%B1) CR_TAB
2136 AS2 (sts,%C0,%C1) CR_TAB
2138 if (reg_base > 0) /* (r) */
2140 if (reg_base == REG_X) /* (R26) */
2142 if (reg_src == REG_X)
2144 /* "st X+,r26" is undefined */
2145 if (reg_unused_after (insn, base))
2146 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2147 AS2 (st,X,r26) CR_TAB
2148 AS2 (adiw,r26,1) CR_TAB
2149 AS2 (st,X+,__tmp_reg__) CR_TAB
2150 AS2 (st,X+,r28) CR_TAB
2153 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2154 AS2 (st,X,r26) CR_TAB
2155 AS2 (adiw,r26,1) CR_TAB
2156 AS2 (st,X+,__tmp_reg__) CR_TAB
2157 AS2 (st,X+,r28) CR_TAB
2158 AS2 (st,X,r29) CR_TAB
2161 else if (reg_base == reg_src + 2)
2163 if (reg_unused_after (insn, base))
2164 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2165 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2166 AS2 (st,%0+,%A1) CR_TAB
2167 AS2 (st,%0+,%B1) CR_TAB
2168 AS2 (st,%0+,__zero_reg__) CR_TAB
2169 AS2 (st,%0,__tmp_reg__) CR_TAB
2170 AS1 (clr,__zero_reg__));
2172 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2173 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2174 AS2 (st,%0+,%A1) CR_TAB
2175 AS2 (st,%0+,%B1) CR_TAB
2176 AS2 (st,%0+,__zero_reg__) CR_TAB
2177 AS2 (st,%0,__tmp_reg__) CR_TAB
2178 AS1 (clr,__zero_reg__) CR_TAB
2181 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2182 AS2 (st,%0+,%B1) CR_TAB
2183 AS2 (st,%0+,%C1) CR_TAB
2184 AS2 (st,%0,%D1) CR_TAB
2188 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2189 AS2 (std,%0+1,%B1) CR_TAB
2190 AS2 (std,%0+2,%C1) CR_TAB
2191 AS2 (std,%0+3,%D1));
2193 else if (GET_CODE (base) == PLUS) /* (R + i) */
2195 int disp = INTVAL (XEXP (base, 1));
2196 reg_base = REGNO (XEXP (base, 0));
2197 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2199 if (reg_base != REG_Y)
2200 fatal_insn ("incorrect insn:",insn);
2202 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2203 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2204 AS2 (std,Y+60,%A1) CR_TAB
2205 AS2 (std,Y+61,%B1) CR_TAB
2206 AS2 (std,Y+62,%C1) CR_TAB
2207 AS2 (std,Y+63,%D1) CR_TAB
2208 AS2 (sbiw,r28,%o0-60));
2210 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2211 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2212 AS2 (st,Y,%A1) CR_TAB
2213 AS2 (std,Y+1,%B1) CR_TAB
2214 AS2 (std,Y+2,%C1) CR_TAB
2215 AS2 (std,Y+3,%D1) CR_TAB
2216 AS2 (subi,r28,lo8(%o0)) CR_TAB
2217 AS2 (sbci,r29,hi8(%o0)));
2219 if (reg_base == REG_X)
2222 if (reg_src == REG_X)
2225 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2226 AS2 (mov,__zero_reg__,r27) CR_TAB
2227 AS2 (adiw,r26,%o0) CR_TAB
2228 AS2 (st,X+,__tmp_reg__) CR_TAB
2229 AS2 (st,X+,__zero_reg__) CR_TAB
2230 AS2 (st,X+,r28) CR_TAB
2231 AS2 (st,X,r29) CR_TAB
2232 AS1 (clr,__zero_reg__) CR_TAB
2233 AS2 (sbiw,r26,%o0+3));
2235 else if (reg_src == REG_X - 2)
2238 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2239 AS2 (mov,__zero_reg__,r27) CR_TAB
2240 AS2 (adiw,r26,%o0) CR_TAB
2241 AS2 (st,X+,r24) CR_TAB
2242 AS2 (st,X+,r25) CR_TAB
2243 AS2 (st,X+,__tmp_reg__) CR_TAB
2244 AS2 (st,X,__zero_reg__) CR_TAB
2245 AS1 (clr,__zero_reg__) CR_TAB
2246 AS2 (sbiw,r26,%o0+3));
2249 return (AS2 (adiw,r26,%o0) CR_TAB
2250 AS2 (st,X+,%A1) CR_TAB
2251 AS2 (st,X+,%B1) CR_TAB
2252 AS2 (st,X+,%C1) CR_TAB
2253 AS2 (st,X,%D1) CR_TAB
2254 AS2 (sbiw,r26,%o0+3));
2256 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2257 AS2 (std,%B0,%B1) CR_TAB
2258 AS2 (std,%C0,%C1) CR_TAB
2261 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2262 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2263 AS2 (st,%0,%C1) CR_TAB
2264 AS2 (st,%0,%B1) CR_TAB
2266 else if (GET_CODE (base) == POST_INC) /* (R++) */
2267 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2268 AS2 (st,%0,%B1) CR_TAB
2269 AS2 (st,%0,%C1) CR_TAB
2271 fatal_insn ("unknown move insn:",insn);
2276 output_movsisf(rtx insn, rtx operands[], int *l)
2279 rtx dest = operands[0];
2280 rtx src = operands[1];
2286 if (register_operand (dest, VOIDmode))
2288 if (register_operand (src, VOIDmode)) /* mov r,r */
2290 if (true_regnum (dest) > true_regnum (src))
2295 return (AS2 (movw,%C0,%C1) CR_TAB
2296 AS2 (movw,%A0,%A1));
2299 return (AS2 (mov,%D0,%D1) CR_TAB
2300 AS2 (mov,%C0,%C1) CR_TAB
2301 AS2 (mov,%B0,%B1) CR_TAB
2309 return (AS2 (movw,%A0,%A1) CR_TAB
2310 AS2 (movw,%C0,%C1));
2313 return (AS2 (mov,%A0,%A1) CR_TAB
2314 AS2 (mov,%B0,%B1) CR_TAB
2315 AS2 (mov,%C0,%C1) CR_TAB
2319 else if (CONSTANT_P (src))
2321 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2324 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2325 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2326 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2327 AS2 (ldi,%D0,hhi8(%1)));
2330 if (GET_CODE (src) == CONST_INT)
2332 const char *const clr_op0 =
2333 AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
2334 AS1 (clr,%B0) CR_TAB
2336 : (AS1 (clr,%A0) CR_TAB
2337 AS1 (clr,%B0) CR_TAB
2338 AS1 (clr,%C0) CR_TAB
2341 if (src == const0_rtx) /* mov r,L */
2343 *l = AVR_ENHANCED ? 3 : 4;
2346 else if (src == const1_rtx)
2349 output_asm_insn (clr_op0, operands);
2350 *l = AVR_ENHANCED ? 4 : 5;
2351 return AS1 (inc,%A0);
2353 else if (src == constm1_rtx)
2355 /* Immediate constants -1 to any register */
2359 return (AS1 (clr,%A0) CR_TAB
2360 AS1 (dec,%A0) CR_TAB
2361 AS2 (mov,%B0,%A0) CR_TAB
2362 AS2 (movw,%C0,%A0));
2365 return (AS1 (clr,%A0) CR_TAB
2366 AS1 (dec,%A0) CR_TAB
2367 AS2 (mov,%B0,%A0) CR_TAB
2368 AS2 (mov,%C0,%A0) CR_TAB
2373 int bit_nr = exact_log2 (INTVAL (src));
2377 *l = AVR_ENHANCED ? 5 : 6;
2380 output_asm_insn (clr_op0, operands);
2381 output_asm_insn ("set", operands);
2384 avr_output_bld (operands, bit_nr);
2391 /* Last resort, better than loading from memory. */
2393 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2394 AS2 (ldi,r31,lo8(%1)) CR_TAB
2395 AS2 (mov,%A0,r31) CR_TAB
2396 AS2 (ldi,r31,hi8(%1)) CR_TAB
2397 AS2 (mov,%B0,r31) CR_TAB
2398 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2399 AS2 (mov,%C0,r31) CR_TAB
2400 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2401 AS2 (mov,%D0,r31) CR_TAB
2402 AS2 (mov,r31,__tmp_reg__));
2404 else if (GET_CODE (src) == MEM)
2405 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2407 else if (GET_CODE (dest) == MEM)
2409 const char *template;
2411 if (src == const0_rtx)
2412 operands[1] = zero_reg_rtx;
2414 template = out_movsi_mr_r (insn, operands, real_l);
2417 output_asm_insn (template, operands);
2422 fatal_insn ("invalid insn:", insn);
2427 out_movqi_mr_r (rtx insn, rtx op[], int *l)
2431 rtx x = XEXP (dest, 0);
2437 if (CONSTANT_ADDRESS_P (x))
2439 if (avr_io_address_p (x, 1))
2442 return AS2 (out,%0-0x20,%1);
2445 return AS2 (sts,%0,%1);
2447 /* memory access by reg+disp */
2448 else if (GET_CODE (x) == PLUS
2449 && REG_P (XEXP (x,0))
2450 && GET_CODE (XEXP (x,1)) == CONST_INT)
2452 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
2454 int disp = INTVAL (XEXP (x,1));
2455 if (REGNO (XEXP (x,0)) != REG_Y)
2456 fatal_insn ("incorrect insn:",insn);
2458 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2459 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2460 AS2 (std,Y+63,%1) CR_TAB
2461 AS2 (sbiw,r28,%o0-63));
2463 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2464 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2465 AS2 (st,Y,%1) CR_TAB
2466 AS2 (subi,r28,lo8(%o0)) CR_TAB
2467 AS2 (sbci,r29,hi8(%o0)));
2469 else if (REGNO (XEXP (x,0)) == REG_X)
2471 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
2473 if (reg_unused_after (insn, XEXP (x,0)))
2474 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2475 AS2 (adiw,r26,%o0) CR_TAB
2476 AS2 (st,X,__tmp_reg__));
2478 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2479 AS2 (adiw,r26,%o0) CR_TAB
2480 AS2 (st,X,__tmp_reg__) CR_TAB
2481 AS2 (sbiw,r26,%o0));
2485 if (reg_unused_after (insn, XEXP (x,0)))
2486 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2489 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2490 AS2 (st,X,%1) CR_TAB
2491 AS2 (sbiw,r26,%o0));
2495 return AS2 (std,%0,%1);
2498 return AS2 (st,%0,%1);
2502 out_movhi_mr_r (rtx insn, rtx op[], int *l)
2506 rtx base = XEXP (dest, 0);
2507 int reg_base = true_regnum (base);
2508 int reg_src = true_regnum (src);
2512 if (CONSTANT_ADDRESS_P (base))
2514 if (avr_io_address_p (base, 2))
2517 return (AS2 (out,%B0-0x20,%B1) CR_TAB
2518 AS2 (out,%A0-0x20,%A1));
2520 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2525 if (reg_base == REG_X)
2527 if (reg_src == REG_X)
2529 /* "st X+,r26" is undefined */
2530 if (reg_unused_after (insn, src))
2531 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2532 AS2 (st,X,r26) CR_TAB
2533 AS2 (adiw,r26,1) CR_TAB
2534 AS2 (st,X,__tmp_reg__));
2536 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2537 AS2 (st,X,r26) CR_TAB
2538 AS2 (adiw,r26,1) CR_TAB
2539 AS2 (st,X,__tmp_reg__) CR_TAB
2544 if (reg_unused_after (insn, base))
2545 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2548 return *l=3, (AS2 (st ,X+,%A1) CR_TAB
2549 AS2 (st ,X,%B1) CR_TAB
2554 return *l=2, (AS2 (st ,%0,%A1) CR_TAB
2555 AS2 (std,%0+1,%B1));
2557 else if (GET_CODE (base) == PLUS)
2559 int disp = INTVAL (XEXP (base, 1));
2560 reg_base = REGNO (XEXP (base, 0));
2561 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2563 if (reg_base != REG_Y)
2564 fatal_insn ("incorrect insn:",insn);
2566 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2567 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
2568 AS2 (std,Y+62,%A1) CR_TAB
2569 AS2 (std,Y+63,%B1) CR_TAB
2570 AS2 (sbiw,r28,%o0-62));
2572 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2573 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2574 AS2 (st,Y,%A1) CR_TAB
2575 AS2 (std,Y+1,%B1) CR_TAB
2576 AS2 (subi,r28,lo8(%o0)) CR_TAB
2577 AS2 (sbci,r29,hi8(%o0)));
2579 if (reg_base == REG_X)
2582 if (reg_src == REG_X)
2585 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2586 AS2 (mov,__zero_reg__,r27) CR_TAB
2587 AS2 (adiw,r26,%o0) CR_TAB
2588 AS2 (st,X+,__tmp_reg__) CR_TAB
2589 AS2 (st,X,__zero_reg__) CR_TAB
2590 AS1 (clr,__zero_reg__) CR_TAB
2591 AS2 (sbiw,r26,%o0+1));
2594 return (AS2 (adiw,r26,%o0) CR_TAB
2595 AS2 (st,X+,%A1) CR_TAB
2596 AS2 (st,X,%B1) CR_TAB
2597 AS2 (sbiw,r26,%o0+1));
2599 return *l=2, (AS2 (std,%A0,%A1) CR_TAB
2602 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2603 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2605 else if (GET_CODE (base) == POST_INC) /* (R++) */
2606 return *l=2, (AS2 (st,%0,%A1) CR_TAB
2608 fatal_insn ("unknown move insn:",insn);
2612 /* Return 1 if frame pointer for current function required. */
2615 frame_pointer_required_p (void)
2617 return (current_function_calls_alloca
2618 || current_function_args_info.nregs == 0
2619 || get_frame_size () > 0);
2622 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2625 compare_condition (rtx insn)
2627 rtx next = next_real_insn (insn);
2628 RTX_CODE cond = UNKNOWN;
2629 if (next && GET_CODE (next) == JUMP_INSN)
2631 rtx pat = PATTERN (next);
2632 rtx src = SET_SRC (pat);
2633 rtx t = XEXP (src, 0);
2634 cond = GET_CODE (t);
2639 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2642 compare_sign_p (rtx insn)
2644 RTX_CODE cond = compare_condition (insn);
2645 return (cond == GE || cond == LT);
2648 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2649 that needs to be swapped (GT, GTU, LE, LEU). */
2652 compare_diff_p (rtx insn)
2654 RTX_CODE cond = compare_condition (insn);
2655 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2658 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2661 compare_eq_p (rtx insn)
2663 RTX_CODE cond = compare_condition (insn);
2664 return (cond == EQ || cond == NE);
2668 /* Output test instruction for HImode. */
2671 out_tsthi (rtx insn, int *l)
2673 if (compare_sign_p (insn))
2676 return AS1 (tst,%B0);
2678 if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2679 && compare_eq_p (insn))
2681 /* Faster than sbiw if we can clobber the operand. */
2683 return AS2 (or,%A0,%B0);
2685 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2688 return AS2 (sbiw,%0,0);
2691 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2692 AS2 (cpc,%B0,__zero_reg__));
2696 /* Output test instruction for SImode. */
2699 out_tstsi (rtx insn, int *l)
2701 if (compare_sign_p (insn))
2704 return AS1 (tst,%D0);
2706 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2709 return (AS2 (sbiw,%A0,0) CR_TAB
2710 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2711 AS2 (cpc,%D0,__zero_reg__));
2714 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2715 AS2 (cpc,%B0,__zero_reg__) CR_TAB
2716 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2717 AS2 (cpc,%D0,__zero_reg__));
2721 /* Generate asm equivalent for various shifts.
2722 Shift count is a CONST_INT, MEM or REG.
2723 This only handles cases that are not already
2724 carefully hand-optimized in ?sh??i3_out. */
2727 out_shift_with_cnt (const char *template, rtx insn, rtx operands[],
2728 int *len, int t_len)
2732 int second_label = 1;
2733 int saved_in_tmp = 0;
2734 int use_zero_reg = 0;
2736 op[0] = operands[0];
2737 op[1] = operands[1];
2738 op[2] = operands[2];
2739 op[3] = operands[3];
2745 if (GET_CODE (operands[2]) == CONST_INT)
2747 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2748 int count = INTVAL (operands[2]);
2749 int max_len = 10; /* If larger than this, always use a loop. */
2751 if (count < 8 && !scratch)
2755 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2757 if (t_len * count <= max_len)
2759 /* Output shifts inline with no loop - faster. */
2761 *len = t_len * count;
2765 output_asm_insn (template, op);
2774 strcat (str, AS2 (ldi,%3,%2));
2776 else if (use_zero_reg)
2778 /* Hack to save one word: use __zero_reg__ as loop counter.
2779 Set one bit, then shift in a loop until it is 0 again. */
2781 op[3] = zero_reg_rtx;
2785 strcat (str, ("set" CR_TAB
2786 AS2 (bld,%3,%2-1)));
2790 /* No scratch register available, use one from LD_REGS (saved in
2791 __tmp_reg__) that doesn't overlap with registers to shift. */
2793 op[3] = gen_rtx_REG (QImode,
2794 ((true_regnum (operands[0]) - 1) & 15) + 16);
2795 op[4] = tmp_reg_rtx;
2799 *len = 3; /* Includes "mov %3,%4" after the loop. */
2801 strcat (str, (AS2 (mov,%4,%3) CR_TAB
2807 else if (GET_CODE (operands[2]) == MEM)
2811 op[3] = op_mov[0] = tmp_reg_rtx;
2815 out_movqi_r_mr (insn, op_mov, len);
2817 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
2819 else if (register_operand (operands[2], QImode))
2821 if (reg_unused_after (insn, operands[2]))
2825 op[3] = tmp_reg_rtx;
2827 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
2831 fatal_insn ("bad shift insn:", insn);
2838 strcat (str, AS1 (rjmp,2f));
2842 *len += t_len + 2; /* template + dec + brXX */
2845 strcat (str, "\n1:\t");
2846 strcat (str, template);
2847 strcat (str, second_label ? "\n2:\t" : "\n\t");
2848 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
2849 strcat (str, CR_TAB);
2850 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
2852 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
2853 output_asm_insn (str, op);
2858 /* 8bit shift left ((char)x << i) */
2861 ashlqi3_out (rtx insn, rtx operands[], int *len)
2863 if (GET_CODE (operands[2]) == CONST_INT)
2870 switch (INTVAL (operands[2]))
2874 return AS1 (clr,%0);
2878 return AS1 (lsl,%0);
2882 return (AS1 (lsl,%0) CR_TAB
2887 return (AS1 (lsl,%0) CR_TAB
2892 if (test_hard_reg_class (LD_REGS, operands[0]))
2895 return (AS1 (swap,%0) CR_TAB
2896 AS2 (andi,%0,0xf0));
2899 return (AS1 (lsl,%0) CR_TAB
2905 if (test_hard_reg_class (LD_REGS, operands[0]))
2908 return (AS1 (swap,%0) CR_TAB
2910 AS2 (andi,%0,0xe0));
2913 return (AS1 (lsl,%0) CR_TAB
2920 if (test_hard_reg_class (LD_REGS, operands[0]))
2923 return (AS1 (swap,%0) CR_TAB
2926 AS2 (andi,%0,0xc0));
2929 return (AS1 (lsl,%0) CR_TAB
2938 return (AS1 (ror,%0) CR_TAB
2943 else if (CONSTANT_P (operands[2]))
2944 fatal_insn ("internal compiler error. Incorrect shift:", insn);
2946 out_shift_with_cnt (AS1 (lsl,%0),
2947 insn, operands, len, 1);
2952 /* 16bit shift left ((short)x << i) */
2955 ashlhi3_out (rtx insn, rtx operands[], int *len)
2957 if (GET_CODE (operands[2]) == CONST_INT)
2959 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2960 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
2967 switch (INTVAL (operands[2]))
2970 if (optimize_size && scratch)
2975 return (AS1 (swap,%A0) CR_TAB
2976 AS1 (swap,%B0) CR_TAB
2977 AS2 (andi,%B0,0xf0) CR_TAB
2978 AS2 (eor,%B0,%A0) CR_TAB
2979 AS2 (andi,%A0,0xf0) CR_TAB
2985 return (AS1 (swap,%A0) CR_TAB
2986 AS1 (swap,%B0) CR_TAB
2987 AS2 (ldi,%3,0xf0) CR_TAB
2988 AS2 (and,%B0,%3) CR_TAB
2989 AS2 (eor,%B0,%A0) CR_TAB
2990 AS2 (and,%A0,%3) CR_TAB
2993 break; /* optimize_size ? 6 : 8 */
2997 break; /* scratch ? 5 : 6 */
3001 return (AS1 (lsl,%A0) CR_TAB
3002 AS1 (rol,%B0) CR_TAB
3003 AS1 (swap,%A0) CR_TAB
3004 AS1 (swap,%B0) CR_TAB
3005 AS2 (andi,%B0,0xf0) CR_TAB
3006 AS2 (eor,%B0,%A0) CR_TAB
3007 AS2 (andi,%A0,0xf0) CR_TAB
3013 return (AS1 (lsl,%A0) CR_TAB
3014 AS1 (rol,%B0) CR_TAB
3015 AS1 (swap,%A0) CR_TAB
3016 AS1 (swap,%B0) CR_TAB
3017 AS2 (ldi,%3,0xf0) CR_TAB
3018 AS2 (and,%B0,%3) CR_TAB
3019 AS2 (eor,%B0,%A0) CR_TAB
3020 AS2 (and,%A0,%3) CR_TAB
3027 break; /* scratch ? 5 : 6 */
3029 return (AS1 (clr,__tmp_reg__) CR_TAB
3030 AS1 (lsr,%B0) CR_TAB
3031 AS1 (ror,%A0) CR_TAB
3032 AS1 (ror,__tmp_reg__) CR_TAB
3033 AS1 (lsr,%B0) CR_TAB
3034 AS1 (ror,%A0) CR_TAB
3035 AS1 (ror,__tmp_reg__) CR_TAB
3036 AS2 (mov,%B0,%A0) CR_TAB
3037 AS2 (mov,%A0,__tmp_reg__));
3041 return (AS1 (lsr,%B0) CR_TAB
3042 AS2 (mov,%B0,%A0) CR_TAB
3043 AS1 (clr,%A0) CR_TAB
3044 AS1 (ror,%B0) CR_TAB
3048 if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
3049 return *len = 1, AS1 (clr,%A0);
3051 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3056 return (AS2 (mov,%B0,%A0) CR_TAB
3057 AS1 (clr,%A0) CR_TAB
3062 return (AS2 (mov,%B0,%A0) CR_TAB
3063 AS1 (clr,%A0) CR_TAB
3064 AS1 (lsl,%B0) CR_TAB
3069 return (AS2 (mov,%B0,%A0) CR_TAB
3070 AS1 (clr,%A0) CR_TAB
3071 AS1 (lsl,%B0) CR_TAB
3072 AS1 (lsl,%B0) CR_TAB
3079 return (AS2 (mov,%B0,%A0) CR_TAB
3080 AS1 (clr,%A0) CR_TAB
3081 AS1 (swap,%B0) CR_TAB
3082 AS2 (andi,%B0,0xf0));
3087 return (AS2 (mov,%B0,%A0) CR_TAB
3088 AS1 (clr,%A0) CR_TAB
3089 AS1 (swap,%B0) CR_TAB
3090 AS2 (ldi,%3,0xf0) CR_TAB
3094 return (AS2 (mov,%B0,%A0) CR_TAB
3095 AS1 (clr,%A0) CR_TAB
3096 AS1 (lsl,%B0) CR_TAB
3097 AS1 (lsl,%B0) CR_TAB
3098 AS1 (lsl,%B0) CR_TAB
3105 return (AS2 (mov,%B0,%A0) CR_TAB
3106 AS1 (clr,%A0) CR_TAB
3107 AS1 (swap,%B0) CR_TAB
3108 AS1 (lsl,%B0) CR_TAB
3109 AS2 (andi,%B0,0xe0));
3111 if (AVR_ENHANCED && scratch)
3114 return (AS2 (ldi,%3,0x20) CR_TAB
3115 AS2 (mul,%A0,%3) CR_TAB
3116 AS2 (mov,%B0,r0) CR_TAB
3117 AS1 (clr,%A0) CR_TAB
3118 AS1 (clr,__zero_reg__));
3120 if (optimize_size && scratch)
3125 return (AS2 (mov,%B0,%A0) CR_TAB
3126 AS1 (clr,%A0) CR_TAB
3127 AS1 (swap,%B0) CR_TAB
3128 AS1 (lsl,%B0) CR_TAB
3129 AS2 (ldi,%3,0xe0) CR_TAB
3135 return ("set" CR_TAB
3136 AS2 (bld,r1,5) CR_TAB
3137 AS2 (mul,%A0,r1) CR_TAB
3138 AS2 (mov,%B0,r0) CR_TAB
3139 AS1 (clr,%A0) CR_TAB
3140 AS1 (clr,__zero_reg__));
3143 return (AS2 (mov,%B0,%A0) CR_TAB
3144 AS1 (clr,%A0) CR_TAB
3145 AS1 (lsl,%B0) CR_TAB
3146 AS1 (lsl,%B0) CR_TAB
3147 AS1 (lsl,%B0) CR_TAB
3148 AS1 (lsl,%B0) CR_TAB
3152 if (AVR_ENHANCED && ldi_ok)
3155 return (AS2 (ldi,%B0,0x40) CR_TAB
3156 AS2 (mul,%A0,%B0) CR_TAB
3157 AS2 (mov,%B0,r0) CR_TAB
3158 AS1 (clr,%A0) CR_TAB
3159 AS1 (clr,__zero_reg__));
3161 if (AVR_ENHANCED && scratch)
3164 return (AS2 (ldi,%3,0x40) CR_TAB
3165 AS2 (mul,%A0,%3) CR_TAB
3166 AS2 (mov,%B0,r0) CR_TAB
3167 AS1 (clr,%A0) CR_TAB
3168 AS1 (clr,__zero_reg__));
3170 if (optimize_size && ldi_ok)
3173 return (AS2 (mov,%B0,%A0) CR_TAB
3174 AS2 (ldi,%A0,6) "\n1:\t"
3175 AS1 (lsl,%B0) CR_TAB
3176 AS1 (dec,%A0) CR_TAB
3179 if (optimize_size && scratch)
3182 return (AS1 (clr,%B0) CR_TAB
3183 AS1 (lsr,%A0) CR_TAB
3184 AS1 (ror,%B0) CR_TAB
3185 AS1 (lsr,%A0) CR_TAB
3186 AS1 (ror,%B0) CR_TAB
3191 return (AS1 (clr,%B0) CR_TAB
3192 AS1 (lsr,%A0) CR_TAB
3193 AS1 (ror,%B0) CR_TAB
3198 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3200 insn, operands, len, 2);
3205 /* 32bit shift left ((long)x << i) */
3208 ashlsi3_out (rtx insn, rtx operands[], int *len)
3210 if (GET_CODE (operands[2]) == CONST_INT)
3218 switch (INTVAL (operands[2]))
3222 int reg0 = true_regnum (operands[0]);
3223 int reg1 = true_regnum (operands[1]);
3226 return (AS2 (mov,%D0,%C1) CR_TAB
3227 AS2 (mov,%C0,%B1) CR_TAB
3228 AS2 (mov,%B0,%A1) CR_TAB
3230 else if (reg0 + 1 == reg1)
3233 return AS1 (clr,%A0);
3236 return (AS1 (clr,%A0) CR_TAB
3237 AS2 (mov,%B0,%A1) CR_TAB
3238 AS2 (mov,%C0,%B1) CR_TAB
3244 int reg0 = true_regnum (operands[0]);
3245 int reg1 = true_regnum (operands[1]);
3247 if (AVR_ENHANCED && (reg0 + 2 != reg1))
3250 return (AS2 (movw,%C0,%A1) CR_TAB
3251 AS1 (clr,%B0) CR_TAB
3254 if (reg0 + 1 >= reg1)
3255 return (AS2 (mov,%D0,%B1) CR_TAB
3256 AS2 (mov,%C0,%A1) CR_TAB
3257 AS1 (clr,%B0) CR_TAB
3259 if (reg0 + 2 == reg1)
3262 return (AS1 (clr,%B0) CR_TAB
3266 return (AS2 (mov,%C0,%A1) CR_TAB
3267 AS2 (mov,%D0,%B1) CR_TAB
3268 AS1 (clr,%B0) CR_TAB
3274 if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
3275 return (AS2 (mov,%D0,%A1) CR_TAB
3276 AS1 (clr,%C0) CR_TAB
3277 AS1 (clr,%B0) CR_TAB
3282 return (AS1 (clr,%C0) CR_TAB
3283 AS1 (clr,%B0) CR_TAB
3289 return (AS1 (clr,%D0) CR_TAB
3290 AS1 (lsr,%A0) CR_TAB
3291 AS1 (ror,%D0) CR_TAB
3292 AS1 (clr,%C0) CR_TAB
3293 AS1 (clr,%B0) CR_TAB
3298 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3299 AS1 (rol,%B0) CR_TAB
3300 AS1 (rol,%C0) CR_TAB
3302 insn, operands, len, 4);
3306 /* 8bit arithmetic shift right ((signed char)x >> i) */
3309 ashrqi3_out (rtx insn, rtx operands[], int *len)
3311 if (GET_CODE (operands[2]) == CONST_INT)
3318 switch (INTVAL (operands[2]))
3322 return AS1 (asr,%0);
3326 return (AS1 (asr,%0) CR_TAB
3331 return (AS1 (asr,%0) CR_TAB
3337 return (AS1 (asr,%0) CR_TAB
3344 return (AS1 (asr,%0) CR_TAB
3352 return (AS2 (bst,%0,6) CR_TAB
3354 AS2 (sbc,%0,%0) CR_TAB
3360 return (AS1 (lsl,%0) CR_TAB
3364 else if (CONSTANT_P (operands[2]))
3365 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3367 out_shift_with_cnt (AS1 (asr,%0),
3368 insn, operands, len, 1);
3373 /* 16bit arithmetic shift right ((signed short)x >> i) */
3376 ashrhi3_out (rtx insn, rtx operands[], int *len)
3378 if (GET_CODE (operands[2]) == CONST_INT)
3380 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3381 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3388 switch (INTVAL (operands[2]))
3392 /* XXX try to optimize this too? */
3397 break; /* scratch ? 5 : 6 */
3399 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3400 AS2 (mov,%A0,%B0) CR_TAB
3401 AS1 (lsl,__tmp_reg__) CR_TAB
3402 AS1 (rol,%A0) CR_TAB
3403 AS2 (sbc,%B0,%B0) CR_TAB
3404 AS1 (lsl,__tmp_reg__) CR_TAB
3405 AS1 (rol,%A0) CR_TAB
3410 return (AS1 (lsl,%A0) CR_TAB
3411 AS2 (mov,%A0,%B0) CR_TAB
3412 AS1 (rol,%A0) CR_TAB
3417 int reg0 = true_regnum (operands[0]);
3418 int reg1 = true_regnum (operands[1]);
3421 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3422 AS1 (lsl,%B0) CR_TAB
3424 else if (reg0 == reg1 + 1)
3425 return *len = 3, (AS1 (clr,%B0) CR_TAB
3426 AS2 (sbrc,%A0,7) CR_TAB
3429 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3430 AS1 (clr,%B0) CR_TAB
3431 AS2 (sbrc,%A0,7) CR_TAB
3437 return (AS2 (mov,%A0,%B0) CR_TAB
3438 AS1 (lsl,%B0) CR_TAB
3439 AS2 (sbc,%B0,%B0) CR_TAB
3444 return (AS2 (mov,%A0,%B0) CR_TAB
3445 AS1 (lsl,%B0) CR_TAB
3446 AS2 (sbc,%B0,%B0) CR_TAB
3447 AS1 (asr,%A0) CR_TAB
3451 if (AVR_ENHANCED && ldi_ok)
3454 return (AS2 (ldi,%A0,0x20) CR_TAB
3455 AS2 (muls,%B0,%A0) CR_TAB
3456 AS2 (mov,%A0,r1) CR_TAB
3457 AS2 (sbc,%B0,%B0) CR_TAB
3458 AS1 (clr,__zero_reg__));
3460 if (optimize_size && scratch)
3463 return (AS2 (mov,%A0,%B0) CR_TAB
3464 AS1 (lsl,%B0) CR_TAB
3465 AS2 (sbc,%B0,%B0) CR_TAB
3466 AS1 (asr,%A0) CR_TAB
3467 AS1 (asr,%A0) CR_TAB
3471 if (AVR_ENHANCED && ldi_ok)
3474 return (AS2 (ldi,%A0,0x10) CR_TAB
3475 AS2 (muls,%B0,%A0) CR_TAB
3476 AS2 (mov,%A0,r1) CR_TAB
3477 AS2 (sbc,%B0,%B0) CR_TAB
3478 AS1 (clr,__zero_reg__));
3480 if (optimize_size && scratch)
3483 return (AS2 (mov,%A0,%B0) CR_TAB
3484 AS1 (lsl,%B0) CR_TAB
3485 AS2 (sbc,%B0,%B0) CR_TAB
3486 AS1 (asr,%A0) CR_TAB
3487 AS1 (asr,%A0) CR_TAB
3488 AS1 (asr,%A0) CR_TAB
3492 if (AVR_ENHANCED && ldi_ok)
3495 return (AS2 (ldi,%A0,0x08) CR_TAB
3496 AS2 (muls,%B0,%A0) CR_TAB
3497 AS2 (mov,%A0,r1) CR_TAB
3498 AS2 (sbc,%B0,%B0) CR_TAB
3499 AS1 (clr,__zero_reg__));
3502 break; /* scratch ? 5 : 7 */
3504 return (AS2 (mov,%A0,%B0) CR_TAB
3505 AS1 (lsl,%B0) CR_TAB
3506 AS2 (sbc,%B0,%B0) CR_TAB
3507 AS1 (asr,%A0) CR_TAB
3508 AS1 (asr,%A0) CR_TAB
3509 AS1 (asr,%A0) CR_TAB
3510 AS1 (asr,%A0) CR_TAB
3515 return (AS1 (lsl,%B0) CR_TAB
3516 AS2 (sbc,%A0,%A0) CR_TAB
3517 AS1 (lsl,%B0) CR_TAB
3518 AS2 (mov,%B0,%A0) CR_TAB
3522 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3523 AS2 (sbc,%A0,%A0) CR_TAB
3528 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3530 insn, operands, len, 2);
3535 /* 32bit arithmetic shift right ((signed long)x >> i) */
3538 ashrsi3_out (rtx insn, rtx operands[], int *len)
3540 if (GET_CODE (operands[2]) == CONST_INT)
3548 switch (INTVAL (operands[2]))
3552 int reg0 = true_regnum (operands[0]);
3553 int reg1 = true_regnum (operands[1]);
3556 return (AS2 (mov,%A0,%B1) CR_TAB
3557 AS2 (mov,%B0,%C1) CR_TAB
3558 AS2 (mov,%C0,%D1) CR_TAB
3559 AS1 (clr,%D0) CR_TAB
3560 AS2 (sbrc,%C0,7) CR_TAB
3562 else if (reg0 == reg1 + 1)
3565 return (AS1 (clr,%D0) CR_TAB
3566 AS2 (sbrc,%C0,7) CR_TAB
3570 return (AS1 (clr,%D0) CR_TAB
3571 AS2 (sbrc,%D1,7) CR_TAB
3572 AS1 (dec,%D0) CR_TAB
3573 AS2 (mov,%C0,%D1) CR_TAB
3574 AS2 (mov,%B0,%C1) CR_TAB
3580 int reg0 = true_regnum (operands[0]);
3581 int reg1 = true_regnum (operands[1]);
3583 if (AVR_ENHANCED && (reg0 != reg1 + 2))
3586 return (AS2 (movw,%A0,%C1) CR_TAB
3587 AS1 (clr,%D0) CR_TAB
3588 AS2 (sbrc,%B0,7) CR_TAB
3589 AS1 (com,%D0) CR_TAB
3592 if (reg0 <= reg1 + 1)
3593 return (AS2 (mov,%A0,%C1) CR_TAB
3594 AS2 (mov,%B0,%D1) CR_TAB
3595 AS1 (clr,%D0) CR_TAB
3596 AS2 (sbrc,%B0,7) CR_TAB
3597 AS1 (com,%D0) CR_TAB
3599 else if (reg0 == reg1 + 2)
3600 return *len = 4, (AS1 (clr,%D0) CR_TAB
3601 AS2 (sbrc,%B0,7) CR_TAB
3602 AS1 (com,%D0) CR_TAB
3605 return (AS2 (mov,%B0,%D1) CR_TAB
3606 AS2 (mov,%A0,%C1) CR_TAB
3607 AS1 (clr,%D0) CR_TAB
3608 AS2 (sbrc,%B0,7) CR_TAB
3609 AS1 (com,%D0) CR_TAB
3614 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
3615 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3616 AS1 (clr,%D0) CR_TAB
3617 AS2 (sbrc,%A0,7) CR_TAB
3618 AS1 (com,%D0) CR_TAB
3619 AS2 (mov,%B0,%D0) CR_TAB
3622 return *len = 5, (AS1 (clr,%D0) CR_TAB
3623 AS2 (sbrc,%A0,7) CR_TAB
3624 AS1 (com,%D0) CR_TAB
3625 AS2 (mov,%B0,%D0) CR_TAB
3630 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3631 AS2 (sbc,%A0,%A0) CR_TAB
3632 AS2 (mov,%B0,%A0) CR_TAB
3633 AS2 (movw,%C0,%A0));
3635 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3636 AS2 (sbc,%A0,%A0) CR_TAB
3637 AS2 (mov,%B0,%A0) CR_TAB
3638 AS2 (mov,%C0,%A0) CR_TAB
3643 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3644 AS1 (ror,%C0) CR_TAB
3645 AS1 (ror,%B0) CR_TAB
3647 insn, operands, len, 4);
3651 /* 8bit logic shift right ((unsigned char)x >> i) */
3654 lshrqi3_out (rtx insn, rtx operands[], int *len)
3656 if (GET_CODE (operands[2]) == CONST_INT)
3663 switch (INTVAL (operands[2]))
3667 return AS1 (clr,%0);
3671 return AS1 (lsr,%0);
3675 return (AS1 (lsr,%0) CR_TAB
3679 return (AS1 (lsr,%0) CR_TAB
3684 if (test_hard_reg_class (LD_REGS, operands[0]))
3687 return (AS1 (swap,%0) CR_TAB
3688 AS2 (andi,%0,0x0f));
3691 return (AS1 (lsr,%0) CR_TAB
3697 if (test_hard_reg_class (LD_REGS, operands[0]))
3700 return (AS1 (swap,%0) CR_TAB
3705 return (AS1 (lsr,%0) CR_TAB
3712 if (test_hard_reg_class (LD_REGS, operands[0]))
3715 return (AS1 (swap,%0) CR_TAB
3721 return (AS1 (lsr,%0) CR_TAB
3730 return (AS1 (rol,%0) CR_TAB
3735 else if (CONSTANT_P (operands[2]))
3736 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3738 out_shift_with_cnt (AS1 (lsr,%0),
3739 insn, operands, len, 1);
3743 /* 16bit logic shift right ((unsigned short)x >> i) */
3746 lshrhi3_out (rtx insn, rtx operands[], int *len)
3748 if (GET_CODE (operands[2]) == CONST_INT)
3750 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3751 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3758 switch (INTVAL (operands[2]))
3761 if (optimize_size && scratch)
3766 return (AS1 (swap,%B0) CR_TAB
3767 AS1 (swap,%A0) CR_TAB
3768 AS2 (andi,%A0,0x0f) CR_TAB
3769 AS2 (eor,%A0,%B0) CR_TAB
3770 AS2 (andi,%B0,0x0f) CR_TAB
3776 return (AS1 (swap,%B0) CR_TAB
3777 AS1 (swap,%A0) CR_TAB
3778 AS2 (ldi,%3,0x0f) CR_TAB
3779 AS2 (and,%A0,%3) CR_TAB
3780 AS2 (eor,%A0,%B0) CR_TAB
3781 AS2 (and,%B0,%3) CR_TAB
3784 break; /* optimize_size ? 6 : 8 */
3788 break; /* scratch ? 5 : 6 */
3792 return (AS1 (lsr,%B0) CR_TAB
3793 AS1 (ror,%A0) CR_TAB
3794 AS1 (swap,%B0) CR_TAB
3795 AS1 (swap,%A0) CR_TAB
3796 AS2 (andi,%A0,0x0f) CR_TAB
3797 AS2 (eor,%A0,%B0) CR_TAB
3798 AS2 (andi,%B0,0x0f) CR_TAB
3804 return (AS1 (lsr,%B0) CR_TAB
3805 AS1 (ror,%A0) CR_TAB
3806 AS1 (swap,%B0) CR_TAB
3807 AS1 (swap,%A0) CR_TAB
3808 AS2 (ldi,%3,0x0f) CR_TAB
3809 AS2 (and,%A0,%3) CR_TAB
3810 AS2 (eor,%A0,%B0) CR_TAB
3811 AS2 (and,%B0,%3) CR_TAB
3818 break; /* scratch ? 5 : 6 */
3820 return (AS1 (clr,__tmp_reg__) CR_TAB
3821 AS1 (lsl,%A0) CR_TAB
3822 AS1 (rol,%B0) CR_TAB
3823 AS1 (rol,__tmp_reg__) CR_TAB
3824 AS1 (lsl,%A0) CR_TAB
3825 AS1 (rol,%B0) CR_TAB
3826 AS1 (rol,__tmp_reg__) CR_TAB
3827 AS2 (mov,%A0,%B0) CR_TAB
3828 AS2 (mov,%B0,__tmp_reg__));
3832 return (AS1 (lsl,%A0) CR_TAB
3833 AS2 (mov,%A0,%B0) CR_TAB
3834 AS1 (rol,%A0) CR_TAB
3835 AS2 (sbc,%B0,%B0) CR_TAB
3839 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
3840 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
3843 return *len = 1, AS1 (clr,%B0);
3847 return (AS2 (mov,%A0,%B0) CR_TAB
3848 AS1 (clr,%B0) CR_TAB
3853 return (AS2 (mov,%A0,%B0) CR_TAB
3854 AS1 (clr,%B0) CR_TAB
3855 AS1 (lsr,%A0) CR_TAB
3860 return (AS2 (mov,%A0,%B0) CR_TAB
3861 AS1 (clr,%B0) CR_TAB
3862 AS1 (lsr,%A0) CR_TAB
3863 AS1 (lsr,%A0) CR_TAB
3870 return (AS2 (mov,%A0,%B0) CR_TAB
3871 AS1 (clr,%B0) CR_TAB
3872 AS1 (swap,%A0) CR_TAB
3873 AS2 (andi,%A0,0x0f));
3878 return (AS2 (mov,%A0,%B0) CR_TAB
3879 AS1 (clr,%B0) CR_TAB
3880 AS1 (swap,%A0) CR_TAB
3881 AS2 (ldi,%3,0x0f) CR_TAB
3885 return (AS2 (mov,%A0,%B0) CR_TAB
3886 AS1 (clr,%B0) CR_TAB
3887 AS1 (lsr,%A0) CR_TAB
3888 AS1 (lsr,%A0) CR_TAB
3889 AS1 (lsr,%A0) CR_TAB
3896 return (AS2 (mov,%A0,%B0) CR_TAB
3897 AS1 (clr,%B0) CR_TAB
3898 AS1 (swap,%A0) CR_TAB
3899 AS1 (lsr,%A0) CR_TAB
3900 AS2 (andi,%A0,0x07));
3902 if (AVR_ENHANCED && scratch)
3905 return (AS2 (ldi,%3,0x08) CR_TAB
3906 AS2 (mul,%B0,%3) CR_TAB
3907 AS2 (mov,%A0,r1) CR_TAB
3908 AS1 (clr,%B0) CR_TAB
3909 AS1 (clr,__zero_reg__));
3911 if (optimize_size && scratch)
3916 return (AS2 (mov,%A0,%B0) CR_TAB
3917 AS1 (clr,%B0) CR_TAB
3918 AS1 (swap,%A0) CR_TAB
3919 AS1 (lsr,%A0) CR_TAB
3920 AS2 (ldi,%3,0x07) CR_TAB
3926 return ("set" CR_TAB
3927 AS2 (bld,r1,3) CR_TAB
3928 AS2 (mul,%B0,r1) CR_TAB
3929 AS2 (mov,%A0,r1) CR_TAB
3930 AS1 (clr,%B0) CR_TAB
3931 AS1 (clr,__zero_reg__));
3934 return (AS2 (mov,%A0,%B0) CR_TAB
3935 AS1 (clr,%B0) CR_TAB
3936 AS1 (lsr,%A0) CR_TAB
3937 AS1 (lsr,%A0) CR_TAB
3938 AS1 (lsr,%A0) CR_TAB
3939 AS1 (lsr,%A0) CR_TAB
3943 if (AVR_ENHANCED && ldi_ok)
3946 return (AS2 (ldi,%A0,0x04) CR_TAB
3947 AS2 (mul,%B0,%A0) CR_TAB
3948 AS2 (mov,%A0,r1) CR_TAB
3949 AS1 (clr,%B0) CR_TAB
3950 AS1 (clr,__zero_reg__));
3952 if (AVR_ENHANCED && scratch)
3955 return (AS2 (ldi,%3,0x04) CR_TAB
3956 AS2 (mul,%B0,%3) CR_TAB
3957 AS2 (mov,%A0,r1) CR_TAB
3958 AS1 (clr,%B0) CR_TAB
3959 AS1 (clr,__zero_reg__));
3961 if (optimize_size && ldi_ok)
3964 return (AS2 (mov,%A0,%B0) CR_TAB
3965 AS2 (ldi,%B0,6) "\n1:\t"
3966 AS1 (lsr,%A0) CR_TAB
3967 AS1 (dec,%B0) CR_TAB
3970 if (optimize_size && scratch)
3973 return (AS1 (clr,%A0) CR_TAB
3974 AS1 (lsl,%B0) CR_TAB
3975 AS1 (rol,%A0) CR_TAB
3976 AS1 (lsl,%B0) CR_TAB
3977 AS1 (rol,%A0) CR_TAB
3982 return (AS1 (clr,%A0) CR_TAB
3983 AS1 (lsl,%B0) CR_TAB
3984 AS1 (rol,%A0) CR_TAB
3989 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
3991 insn, operands, len, 2);
3995 /* 32bit logic shift right ((unsigned int)x >> i) */
3998 lshrsi3_out (rtx insn, rtx operands[], int *len)
4000 if (GET_CODE (operands[2]) == CONST_INT)
4008 switch (INTVAL (operands[2]))
4012 int reg0 = true_regnum (operands[0]);
4013 int reg1 = true_regnum (operands[1]);
4016 return (AS2 (mov,%A0,%B1) CR_TAB
4017 AS2 (mov,%B0,%C1) CR_TAB
4018 AS2 (mov,%C0,%D1) CR_TAB
4020 else if (reg0 == reg1 + 1)
4021 return *len = 1, AS1 (clr,%D0);
4023 return (AS1 (clr,%D0) CR_TAB
4024 AS2 (mov,%C0,%D1) CR_TAB
4025 AS2 (mov,%B0,%C1) CR_TAB
4031 int reg0 = true_regnum (operands[0]);
4032 int reg1 = true_regnum (operands[1]);
4034 if (AVR_ENHANCED && (reg0 != reg1 + 2))
4037 return (AS2 (movw,%A0,%C1) CR_TAB
4038 AS1 (clr,%C0) CR_TAB
4041 if (reg0 <= reg1 + 1)
4042 return (AS2 (mov,%A0,%C1) CR_TAB
4043 AS2 (mov,%B0,%D1) CR_TAB
4044 AS1 (clr,%C0) CR_TAB
4046 else if (reg0 == reg1 + 2)
4047 return *len = 2, (AS1 (clr,%C0) CR_TAB
4050 return (AS2 (mov,%B0,%D1) CR_TAB
4051 AS2 (mov,%A0,%C1) CR_TAB
4052 AS1 (clr,%C0) CR_TAB
4057 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
4058 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4059 AS1 (clr,%B0) CR_TAB
4060 AS1 (clr,%C0) CR_TAB
4063 return *len = 3, (AS1 (clr,%B0) CR_TAB
4064 AS1 (clr,%C0) CR_TAB
4069 return (AS1 (clr,%A0) CR_TAB
4070 AS2 (sbrc,%D0,7) CR_TAB
4071 AS1 (inc,%A0) CR_TAB
4072 AS1 (clr,%B0) CR_TAB
4073 AS1 (clr,%C0) CR_TAB
4078 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4079 AS1 (ror,%C0) CR_TAB
4080 AS1 (ror,%B0) CR_TAB
4082 insn, operands, len, 4);
4086 /* Modifies the length assigned to instruction INSN
4087 LEN is the initially computed length of the insn. */
4090 adjust_insn_length (rtx insn, int len)
4092 rtx patt = PATTERN (insn);
4095 if (GET_CODE (patt) == SET)
4098 op[1] = SET_SRC (patt);
4099 op[0] = SET_DEST (patt);
4100 if (general_operand (op[1], VOIDmode)
4101 && general_operand (op[0], VOIDmode))
4103 switch (GET_MODE (op[0]))
4106 output_movqi (insn, op, &len);
4109 output_movhi (insn, op, &len);
4113 output_movsisf (insn, op, &len);
4119 else if (op[0] == cc0_rtx && REG_P (op[1]))
4121 switch (GET_MODE (op[1]))
4123 case HImode: out_tsthi (insn,&len); break;
4124 case SImode: out_tstsi (insn,&len); break;
4128 else if (GET_CODE (op[1]) == AND)
4130 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4132 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4133 if (GET_MODE (op[1]) == SImode)
4134 len = (((mask & 0xff) != 0xff)
4135 + ((mask & 0xff00) != 0xff00)
4136 + ((mask & 0xff0000L) != 0xff0000L)
4137 + ((mask & 0xff000000L) != 0xff000000L));
4138 else if (GET_MODE (op[1]) == HImode)
4139 len = (((mask & 0xff) != 0xff)
4140 + ((mask & 0xff00) != 0xff00));
4143 else if (GET_CODE (op[1]) == IOR)
4145 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4147 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4148 if (GET_MODE (op[1]) == SImode)
4149 len = (((mask & 0xff) != 0)
4150 + ((mask & 0xff00) != 0)
4151 + ((mask & 0xff0000L) != 0)
4152 + ((mask & 0xff000000L) != 0));
4153 else if (GET_MODE (op[1]) == HImode)
4154 len = (((mask & 0xff) != 0)
4155 + ((mask & 0xff00) != 0));
4159 set = single_set (insn);
4164 op[1] = SET_SRC (set);
4165 op[0] = SET_DEST (set);
4167 if (GET_CODE (patt) == PARALLEL
4168 && general_operand (op[1], VOIDmode)
4169 && general_operand (op[0], VOIDmode))
4171 if (XVECLEN (patt, 0) == 2)
4172 op[2] = XVECEXP (patt, 0, 1);
4174 switch (GET_MODE (op[0]))
4180 output_reload_inhi (insn, op, &len);
4184 output_reload_insisf (insn, op, &len);
4190 else if (GET_CODE (op[1]) == ASHIFT
4191 || GET_CODE (op[1]) == ASHIFTRT
4192 || GET_CODE (op[1]) == LSHIFTRT)
4196 ops[1] = XEXP (op[1],0);
4197 ops[2] = XEXP (op[1],1);
4198 switch (GET_CODE (op[1]))
4201 switch (GET_MODE (op[0]))
4203 case QImode: ashlqi3_out (insn,ops,&len); break;
4204 case HImode: ashlhi3_out (insn,ops,&len); break;
4205 case SImode: ashlsi3_out (insn,ops,&len); break;
4210 switch (GET_MODE (op[0]))
4212 case QImode: ashrqi3_out (insn,ops,&len); break;
4213 case HImode: ashrhi3_out (insn,ops,&len); break;
4214 case SImode: ashrsi3_out (insn,ops,&len); break;
4219 switch (GET_MODE (op[0]))
4221 case QImode: lshrqi3_out (insn,ops,&len); break;
4222 case HImode: lshrhi3_out (insn,ops,&len); break;
4223 case SImode: lshrsi3_out (insn,ops,&len); break;
4235 /* Return nonzero if register REG dead after INSN. */
4238 reg_unused_after (rtx insn, rtx reg)
4240 return (dead_or_set_p (insn, reg)
4241 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4244 /* Return nonzero if REG is not used after INSN.
4245 We assume REG is a reload reg, and therefore does
4246 not live past labels. It may live past calls or jumps though. */
4249 _reg_unused_after (rtx insn, rtx reg)
4254 /* If the reg is set by this instruction, then it is safe for our
4255 case. Disregard the case where this is a store to memory, since
4256 we are checking a register used in the store address. */
4257 set = single_set (insn);
4258 if (set && GET_CODE (SET_DEST (set)) != MEM
4259 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4262 while ((insn = NEXT_INSN (insn)))
4265 code = GET_CODE (insn);
4268 /* If this is a label that existed before reload, then the register
4269 if dead here. However, if this is a label added by reorg, then
4270 the register may still be live here. We can't tell the difference,
4271 so we just ignore labels completely. */
4272 if (code == CODE_LABEL)
4280 if (code == JUMP_INSN)
4283 /* If this is a sequence, we must handle them all at once.
4284 We could have for instance a call that sets the target register,
4285 and an insn in a delay slot that uses the register. In this case,
4286 we must return 0. */
4287 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4292 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4294 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4295 rtx set = single_set (this_insn);
4297 if (GET_CODE (this_insn) == CALL_INSN)
4299 else if (GET_CODE (this_insn) == JUMP_INSN)
4301 if (INSN_ANNULLED_BRANCH_P (this_insn))
4306 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4308 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4310 if (GET_CODE (SET_DEST (set)) != MEM)
4316 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4321 else if (code == JUMP_INSN)
4325 if (code == CALL_INSN)
4328 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4329 if (GET_CODE (XEXP (tem, 0)) == USE
4330 && REG_P (XEXP (XEXP (tem, 0), 0))
4331 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4333 if (call_used_regs[REGNO (reg)])
4337 set = single_set (insn);
4339 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4341 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4342 return GET_CODE (SET_DEST (set)) != MEM;
4343 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4349 /* Target hook for assembling integer objects. The AVR version needs
4350 special handling for references to certain labels. */
4353 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
4355 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
4356 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
4357 || GET_CODE (x) == LABEL_REF))
4359 fputs ("\t.word\tpm(", asm_out_file);
4360 output_addr_const (asm_out_file, x);
4361 fputs (")\n", asm_out_file);
4364 return default_assemble_integer (x, size, aligned_p);
4367 /* The routine used to output NUL terminated strings. We use a special
4368 version of this for most svr4 targets because doing so makes the
4369 generated assembly code more compact (and thus faster to assemble)
4370 as well as more readable, especially for targets like the i386
4371 (where the only alternative is to output character sequences as
4372 comma separated lists of numbers). */
4375 gas_output_limited_string(FILE *file, const char *str)
4377 const unsigned char *_limited_str = (unsigned char *) str;
4379 fprintf (file, "%s\"", STRING_ASM_OP);
4380 for (; (ch = *_limited_str); _limited_str++)
4383 switch (escape = ESCAPES[ch])
4389 fprintf (file, "\\%03o", ch);
4393 putc (escape, file);
4397 fprintf (file, "\"\n");
4400 /* The routine used to output sequences of byte values. We use a special
4401 version of this for most svr4 targets because doing so makes the
4402 generated assembly code more compact (and thus faster to assemble)
4403 as well as more readable. Note that if we find subparts of the
4404 character sequence which end with NUL (and which are shorter than
4405 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4408 gas_output_ascii(FILE *file, const char *str, size_t length)
4410 const unsigned char *_ascii_bytes = (const unsigned char *) str;
4411 const unsigned char *limit = _ascii_bytes + length;
4412 unsigned bytes_in_chunk = 0;
4413 for (; _ascii_bytes < limit; _ascii_bytes++)
4415 const unsigned char *p;
4416 if (bytes_in_chunk >= 60)
4418 fprintf (file, "\"\n");
4421 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4423 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4425 if (bytes_in_chunk > 0)
4427 fprintf (file, "\"\n");
4430 gas_output_limited_string (file, (char*)_ascii_bytes);
4437 if (bytes_in_chunk == 0)
4438 fprintf (file, "\t.ascii\t\"");
4439 switch (escape = ESCAPES[ch = *_ascii_bytes])
4446 fprintf (file, "\\%03o", ch);
4447 bytes_in_chunk += 4;
4451 putc (escape, file);
4452 bytes_in_chunk += 2;
4457 if (bytes_in_chunk > 0)
4458 fprintf (file, "\"\n");
4461 /* Return value is nonzero if pseudos that have been
4462 assigned to registers of class CLASS would likely be spilled
4463 because registers of CLASS are needed for spill registers. */
4466 class_likely_spilled_p (int c)
4468 return (c != ALL_REGS && c != ADDW_REGS);
4471 /* Valid attributes:
4472 progmem - put data to program memory;
4473 signal - make a function to be hardware interrupt. After function
4474 prologue interrupts are disabled;
4475 interrupt - make a function to be hardware interrupt. After function
4476 prologue interrupts are enabled;
4477 naked - don't generate function prologue/epilogue and `ret' command.
4479 Only `progmem' attribute valid for type. */
4481 const struct attribute_spec avr_attribute_table[] =
4483 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4484 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
4485 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4486 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4487 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4488 { NULL, 0, 0, false, false, false, NULL }
4491 /* Handle a "progmem" attribute; arguments as in
4492 struct attribute_spec.handler. */
4494 avr_handle_progmem_attribute (tree *node, tree name,
4495 tree args ATTRIBUTE_UNUSED,
4496 int flags ATTRIBUTE_UNUSED,
4501 if (TREE_CODE (*node) == TYPE_DECL)
4503 /* This is really a decl attribute, not a type attribute,
4504 but try to handle it for GCC 3.0 backwards compatibility. */
4506 tree type = TREE_TYPE (*node);
4507 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
4508 tree newtype = build_type_attribute_variant (type, attr);
4510 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
4511 TREE_TYPE (*node) = newtype;
4512 *no_add_attrs = true;
4514 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
4516 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
4518 warning ("only initialized variables can be placed into "
4519 "program memory area");
4520 *no_add_attrs = true;
4525 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
4526 *no_add_attrs = true;
4533 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4534 struct attribute_spec.handler. */
4537 avr_handle_fndecl_attribute (tree *node, tree name,
4538 tree args ATTRIBUTE_UNUSED,
4539 int flags ATTRIBUTE_UNUSED,
4542 if (TREE_CODE (*node) != FUNCTION_DECL)
4544 warning ("%qs attribute only applies to functions",
4545 IDENTIFIER_POINTER (name));
4546 *no_add_attrs = true;
4550 const char *func_name = IDENTIFIER_POINTER (DECL_NAME (*node));
4551 const char *attr = IDENTIFIER_POINTER (name);
4553 /* If the function has the 'signal' or 'interrupt' attribute, test to
4554 make sure that the name of the function is "__vector_NN" so as to
4555 catch when the user misspells the interrupt vector name. */
4557 if (strncmp (attr, "interrupt", strlen ("interrupt")) == 0)
4559 if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
4561 warning ("`%s' appears to be a misspelled interrupt handler",
4565 else if (strncmp (attr, "signal", strlen ("signal")) == 0)
4567 if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
4569 warning ("`%s' appears to be a misspelled signal handler",
4578 /* Look for attribute `progmem' in DECL
4579 if found return 1, otherwise 0. */
4582 avr_progmem_p (tree decl, tree attributes)
4586 if (TREE_CODE (decl) != VAR_DECL)
4590 != lookup_attribute ("progmem", attributes))
4596 while (TREE_CODE (a) == ARRAY_TYPE);
4598 if (a == error_mark_node)
4601 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4607 /* Add the section attribute if the variable is in progmem. */
4610 avr_insert_attributes (tree node, tree *attributes)
4612 if (TREE_CODE (node) == VAR_DECL
4613 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
4614 && avr_progmem_p (node, *attributes))
4616 static const char dsec[] = ".progmem.data";
4617 *attributes = tree_cons (get_identifier ("section"),
4618 build_tree_list (NULL, build_string (strlen (dsec), dsec)),
4621 /* ??? This seems sketchy. Why can't the user declare the
4622 thing const in the first place? */
4623 TREE_READONLY (node) = 1;
4628 avr_section_type_flags (tree decl, const char *name, int reloc)
4630 unsigned int flags = default_section_type_flags (decl, name, reloc);
4632 if (strncmp (name, ".noinit", 7) == 0)
4634 if (decl && TREE_CODE (decl) == VAR_DECL
4635 && DECL_INITIAL (decl) == NULL_TREE)
4636 flags |= SECTION_BSS; /* @nobits */
4638 warning ("only uninitialized variables can be placed in the "
4645 /* Outputs some appropriate text to go at the start of an assembler
4649 avr_file_start (void)
4652 error ("MCU %qs supported for assembler only", avr_mcu_name);
4654 default_file_start ();
4656 fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);
4657 fputs ("__SREG__ = 0x3f\n"
4659 "__SP_L__ = 0x3d\n", asm_out_file);
4661 fputs ("__tmp_reg__ = 0\n"
4662 "__zero_reg__ = 1\n", asm_out_file);
4664 /* FIXME: output these only if there is anything in the .data / .bss
4665 sections - some code size could be saved by not linking in the
4666 initialization code from libgcc if one or both sections are empty. */
4667 fputs ("\t.global __do_copy_data\n", asm_out_file);
4668 fputs ("\t.global __do_clear_bss\n", asm_out_file);
4670 commands_in_file = 0;
4671 commands_in_prologues = 0;
4672 commands_in_epilogues = 0;
4675 /* Outputs to the stdio stream FILE some
4676 appropriate text to go at the end of an assembler file. */
4681 fputs ("/* File ", asm_out_file);
4682 output_quoted_string (asm_out_file, main_input_filename);
4683 fprintf (asm_out_file,
4684 ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4687 commands_in_file - commands_in_prologues - commands_in_epilogues,
4688 commands_in_prologues, commands_in_epilogues);
4691 /* Choose the order in which to allocate hard registers for
4692 pseudo-registers local to a basic block.
4694 Store the desired register order in the array `reg_alloc_order'.
4695 Element 0 should be the register to allocate first; element 1, the
4696 next register; and so on. */
4699 order_regs_for_local_alloc (void)
4702 static const int order_0[] = {
4710 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4714 static const int order_1[] = {
4722 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4726 static const int order_2[] = {
4735 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4740 const int *order = (TARGET_ORDER_1 ? order_1 :
4741 TARGET_ORDER_2 ? order_2 :
4743 for (i=0; i < ARRAY_SIZE (order_0); ++i)
4744 reg_alloc_order[i] = order[i];
4747 /* Calculate the cost of X code of the expression in which it is contained,
4748 found in OUTER_CODE */
4751 default_rtx_costs (rtx X, enum rtx_code code, enum rtx_code outer_code)
4758 cost = 2 * GET_MODE_SIZE (GET_MODE (X));
4761 if (outer_code != SET)
4763 if (GET_CODE (XEXP (X,0)) == SYMBOL_REF)
4764 cost += 2 * GET_MODE_SIZE (GET_MODE (X));
4766 cost += GET_MODE_SIZE (GET_MODE (X));
4772 if (outer_code == SET)
4773 cost = GET_MODE_SIZE (GET_MODE (X));
4775 cost = -GET_MODE_SIZE (GET_MODE (X));
4778 if (outer_code == SET)
4779 cost = GET_MODE_SIZE (GET_MODE (X));
4785 if (outer_code == SET)
4787 if (X == stack_pointer_rtx)
4789 else if (GET_CODE (XEXP (X,1)) == CONST_INT)
4790 cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 :
4791 GET_MODE_SIZE (GET_MODE (X)));
4793 cost = GET_MODE_SIZE (GET_MODE (X));
4797 if (GET_CODE (XEXP (X,1)) == CONST_INT)
4798 cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0)));
4807 avr_rtx_costs (rtx x, int code, int outer_code, int *total)
4814 if (outer_code == PLUS
4815 || outer_code == IOR
4816 || outer_code == AND
4817 || outer_code == MINUS
4818 || outer_code == SET
4824 if (outer_code == COMPARE
4826 && INTVAL (x) <= 255)
4841 cst = default_rtx_costs (x, code, outer_code);
4853 /* Calculate the cost of a memory address. */
4856 avr_address_cost (rtx x)
4858 if (GET_CODE (x) == PLUS
4859 && GET_CODE (XEXP (x,1)) == CONST_INT
4860 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
4861 && INTVAL (XEXP (x,1)) >= 61)
4863 if (CONSTANT_ADDRESS_P (x))
4865 if (avr_io_address_p (x, 1))
4872 /* EXTRA_CONSTRAINT helper */
4875 extra_constraint (rtx x, int c)
4878 && GET_CODE (x) == MEM
4879 && GET_CODE (XEXP (x,0)) == PLUS)
4881 if (TARGET_ALL_DEBUG)
4883 fprintf (stderr, ("extra_constraint:\n"
4884 "reload_completed: %d\n"
4885 "reload_in_progress: %d\n"),
4886 reload_completed, reload_in_progress);
4889 if (GET_CODE (x) == MEM
4890 && GET_CODE (XEXP (x,0)) == PLUS
4891 && REG_P (XEXP (XEXP (x,0), 0))
4892 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
4893 && (INTVAL (XEXP (XEXP (x,0), 1))
4894 <= MAX_LD_OFFSET (GET_MODE (x))))
4896 rtx xx = XEXP (XEXP (x,0), 0);
4897 int regno = REGNO (xx);
4898 if (TARGET_ALL_DEBUG)
4900 fprintf (stderr, ("extra_constraint:\n"
4901 "reload_completed: %d\n"
4902 "reload_in_progress: %d\n"),
4903 reload_completed, reload_in_progress);
4906 if (regno >= FIRST_PSEUDO_REGISTER)
4907 return 1; /* allocate pseudos */
4908 else if (regno == REG_Z || regno == REG_Y)
4909 return 1; /* strictly check */
4910 else if (xx == frame_pointer_rtx
4911 || xx == arg_pointer_rtx)
4912 return 1; /* XXX frame & arg pointer checks */
4918 /* Convert condition code CONDITION to the valid AVR condition code. */
4921 avr_normalize_condition (RTX_CODE condition)
4938 /* This function optimizes conditional jumps. */
4945 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4947 if (! (GET_CODE (insn) == INSN
4948 || GET_CODE (insn) == CALL_INSN
4949 || GET_CODE (insn) == JUMP_INSN)
4950 || !single_set (insn))
4953 pattern = PATTERN (insn);
4955 if (GET_CODE (pattern) == PARALLEL)
4956 pattern = XVECEXP (pattern, 0, 0);
4957 if (GET_CODE (pattern) == SET
4958 && SET_DEST (pattern) == cc0_rtx
4959 && compare_diff_p (insn))
4961 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
4963 /* Now we work under compare insn. */
4965 pattern = SET_SRC (pattern);
4966 if (true_regnum (XEXP (pattern,0)) >= 0
4967 && true_regnum (XEXP (pattern,1)) >= 0 )
4969 rtx x = XEXP (pattern,0);
4970 rtx next = next_real_insn (insn);
4971 rtx pat = PATTERN (next);
4972 rtx src = SET_SRC (pat);
4973 rtx t = XEXP (src,0);
4974 PUT_CODE (t, swap_condition (GET_CODE (t)));
4975 XEXP (pattern,0) = XEXP (pattern,1);
4976 XEXP (pattern,1) = x;
4977 INSN_CODE (next) = -1;
4979 else if (true_regnum (XEXP (pattern,0)) >= 0
4980 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
4982 rtx x = XEXP (pattern,1);
4983 rtx next = next_real_insn (insn);
4984 rtx pat = PATTERN (next);
4985 rtx src = SET_SRC (pat);
4986 rtx t = XEXP (src,0);
4987 enum machine_mode mode = GET_MODE (XEXP (pattern, 0));
4989 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
4991 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
4992 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
4993 INSN_CODE (next) = -1;
4994 INSN_CODE (insn) = -1;
4998 else if (true_regnum (SET_SRC (pattern)) >= 0)
5000 /* This is a tst insn */
5001 rtx next = next_real_insn (insn);
5002 rtx pat = PATTERN (next);
5003 rtx src = SET_SRC (pat);
5004 rtx t = XEXP (src,0);
5006 PUT_CODE (t, swap_condition (GET_CODE (t)));
5007 SET_SRC (pattern) = gen_rtx_NEG (GET_MODE (SET_SRC (pattern)),
5009 INSN_CODE (next) = -1;
5010 INSN_CODE (insn) = -1;
5016 /* Returns register number for function return value.*/
5019 avr_ret_register (void)
5024 /* Ceate an RTX representing the place where a
5025 library function returns a value of mode MODE. */
5028 avr_libcall_value (enum machine_mode mode)
5030 int offs = GET_MODE_SIZE (mode);
5033 return gen_rtx_REG (mode, RET_REGISTER + 2 - offs);
5036 /* Create an RTX representing the place where a
5037 function returns a value of data type VALTYPE. */
5040 avr_function_value (tree type, tree func ATTRIBUTE_UNUSED)
5044 if (TYPE_MODE (type) != BLKmode)
5045 return avr_libcall_value (TYPE_MODE (type));
5047 offs = int_size_in_bytes (type);
5050 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5051 offs = GET_MODE_SIZE (SImode);
5052 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5053 offs = GET_MODE_SIZE (DImode);
5055 return gen_rtx_REG (BLKmode, RET_REGISTER + 2 - offs);
5058 /* Returns nonzero if the number MASK has only one bit set. */
5061 mask_one_bit_p (HOST_WIDE_INT mask)
5064 unsigned HOST_WIDE_INT n=mask;
5065 for (i = 0; i < 32; ++i)
5067 if (n & 0x80000000L)
5069 if (n & 0x7fffffffL)
5080 /* Places additional restrictions on the register class to
5081 use when it is necessary to copy value X into a register
5085 preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class class)
5091 test_hard_reg_class (enum reg_class class, rtx x)
5093 int regno = true_regnum (x);
5097 if (TEST_HARD_REG_CLASS (class, regno))
5105 jump_over_one_insn_p (rtx insn, rtx dest)
5107 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5110 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5111 int dest_addr = INSN_ADDRESSES (uid);
5112 return dest_addr - jump_addr == get_attr_length (insn) + 1;
5115 /* Returns 1 if a value of mode MODE can be stored starting with hard
5116 register number REGNO. On the enhanced core, anything larger than
5117 1 byte must start in even numbered register for "movw" to work
5118 (this way we don't have to check for odd registers everywhere). */
5121 avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
5123 /* Bug workaround: recog.c (peep2_find_free_register) and probably
5124 a few other places assume that the frame pointer is a single hard
5125 register, so r29 may be allocated and overwrite the high byte of
5126 the frame pointer. Do not allow any value to start in r29. */
5127 if (regno == REG_Y + 1)
5130 /* Reload can use r28:r29 for reload register and for frame pointer
5131 in one insn. It's wrong. We must disable it. */
5132 if (mode != Pmode && reload_in_progress && frame_pointer_required_p ()
5133 && regno <= REG_Y && (regno + GET_MODE_SIZE (mode)) >= (REG_Y + 1))
5138 /* if (regno < 24 && !AVR_ENHANCED)
5140 return !(regno & 1);
5143 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5144 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5145 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
5148 avr_io_address_p (rtx x, int size)
5150 return (optimize > 0 && GET_CODE (x) == CONST_INT
5151 && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
5154 /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5157 const_int_pow2_p (rtx x)
5159 if (GET_CODE (x) == CONST_INT)
5161 HOST_WIDE_INT d = INTVAL (x);
5162 HOST_WIDE_INT abs_d = (d >= 0) ? d : -d;
5163 return exact_log2 (abs_d) + 1;
5169 output_reload_inhi (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
5175 if (GET_CODE (operands[1]) == CONST_INT)
5177 int val = INTVAL (operands[1]);
5178 if ((val & 0xff) == 0)
5181 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5182 AS2 (ldi,%2,hi8(%1)) CR_TAB
5185 else if ((val & 0xff00) == 0)
5188 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5189 AS2 (mov,%A0,%2) CR_TAB
5190 AS2 (mov,%B0,__zero_reg__));
5192 else if ((val & 0xff) == ((val & 0xff00) >> 8))
5195 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5196 AS2 (mov,%A0,%2) CR_TAB
5201 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5202 AS2 (mov,%A0,%2) CR_TAB
5203 AS2 (ldi,%2,hi8(%1)) CR_TAB
5209 output_reload_insisf (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
5211 rtx src = operands[1];
5212 int cnst = (GET_CODE (src) == CONST_INT);
5217 *len = 4 + ((INTVAL (src) & 0xff) != 0)
5218 + ((INTVAL (src) & 0xff00) != 0)
5219 + ((INTVAL (src) & 0xff0000) != 0)
5220 + ((INTVAL (src) & 0xff000000) != 0);
5227 if (cnst && ((INTVAL (src) & 0xff) == 0))
5228 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5231 output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
5232 output_asm_insn (AS2 (mov, %A0, %2), operands);
5234 if (cnst && ((INTVAL (src) & 0xff00) == 0))
5235 output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
5238 output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
5239 output_asm_insn (AS2 (mov, %B0, %2), operands);
5241 if (cnst && ((INTVAL (src) & 0xff0000) == 0))
5242 output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
5245 output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
5246 output_asm_insn (AS2 (mov, %C0, %2), operands);
5248 if (cnst && ((INTVAL (src) & 0xff000000) == 0))
5249 output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
5252 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5253 output_asm_insn (AS2 (mov, %D0, %2), operands);
5259 avr_output_bld (rtx operands[], int bit_nr)
5261 static char s[] = "bld %A0,0";
5263 s[5] = 'A' + (bit_nr >> 3);
5264 s[8] = '0' + (bit_nr & 7);
5265 output_asm_insn (s, operands);
5269 avr_output_addr_vec_elt (FILE *stream, int value)
5272 fprintf (stream, "\t.word pm(.L%d)\n", value);
5274 fprintf (stream, "\trjmp .L%d\n", value);
5279 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5280 registers (for a define_peephole2) in the current function. */
5283 avr_peep2_scratch_safe (rtx scratch)
5285 if ((interrupt_function_p (current_function_decl)
5286 || signal_function_p (current_function_decl))
5287 && leaf_function_p ())
5289 int first_reg = true_regnum (scratch);
5290 int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
5293 for (reg = first_reg; reg <= last_reg; reg++)
5295 if (!regs_ever_live[reg])
5302 /* Output a branch that tests a single bit of a register (QI, HI or SImode)
5303 or memory location in the I/O space (QImode only).
5305 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5306 Operand 1: register operand to test, or CONST_INT memory address.
5307 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5308 Operand 3: label to jump to if the test is true. */
5311 avr_out_sbxx_branch (rtx insn, rtx operands[])
5313 enum rtx_code comp = GET_CODE (operands[0]);
5314 int long_jump = (get_attr_length (insn) >= 4);
5315 int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
5319 else if (comp == LT)
5323 comp = reverse_condition (comp);
5325 if (GET_CODE (operands[1]) == CONST_INT)
5327 if (INTVAL (operands[1]) < 0x40)
5330 output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
5332 output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
5336 output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
5338 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
5340 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
5343 else /* GET_CODE (operands[1]) == REG */
5345 if (GET_MODE (operands[1]) == QImode)
5348 output_asm_insn (AS2 (sbrs,%1,%2), operands);
5350 output_asm_insn (AS2 (sbrc,%1,%2), operands);
5352 else /* HImode or SImode */
5354 static char buf[] = "sbrc %A1,0";
5355 int bit_nr = exact_log2 (INTVAL (operands[2])
5356 & GET_MODE_MASK (GET_MODE (operands[1])));
5358 buf[3] = (comp == EQ) ? 's' : 'c';
5359 buf[6] = 'A' + (bit_nr >> 3);
5360 buf[9] = '0' + (bit_nr & 7);
5361 output_asm_insn (buf, operands);
5366 return (AS1 (rjmp,.+4) CR_TAB
5369 return AS1 (rjmp,%3);
5373 /* Worker function for TARGET_ASM_CONSTRUCTOR. */
5376 avr_asm_out_ctor (rtx symbol, int priority)
5378 fputs ("\t.global __do_global_ctors\n", asm_out_file);
5379 default_ctor_section_asm_out_constructor (symbol, priority);
5382 /* Worker function for TARGET_ASM_DESTRUCTOR. */
5385 avr_asm_out_dtor (rtx symbol, int priority)
5387 fputs ("\t.global __do_global_dtors\n", asm_out_file);
5388 default_dtor_section_asm_out_destructor (symbol, priority);
5391 /* Worker function for TARGET_RETURN_IN_MEMORY. */
5394 avr_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
5396 if (TYPE_MODE (type) == BLKmode)
5398 HOST_WIDE_INT size = int_size_in_bytes (type);
5399 return (size == -1 || size > 8);