1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Denis Chertykov (denisc@overta.ru)
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
24 #include "coretypes.h"
28 #include "hard-reg-set.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-attr.h"
44 #include "target-def.h"
46 /* Maximal allowed offset for an address in the LD command */
47 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
49 static int avr_naked_function_p PARAMS ((tree));
50 static int interrupt_function_p PARAMS ((tree));
51 static int signal_function_p PARAMS ((tree));
52 static int avr_regs_to_save PARAMS ((HARD_REG_SET *));
53 static int sequent_regs_live PARAMS ((void));
54 static const char * ptrreg_to_str PARAMS ((int));
55 static const char * cond_string PARAMS ((enum rtx_code));
56 static int avr_num_arg_regs PARAMS ((enum machine_mode, tree));
57 static int out_adj_frame_ptr PARAMS ((FILE *, int));
58 static int out_set_stack_ptr PARAMS ((FILE *, int, int));
59 static RTX_CODE compare_condition PARAMS ((rtx insn));
60 static int compare_sign_p PARAMS ((rtx insn));
61 static int reg_was_0 PARAMS ((rtx insn, rtx op));
62 static tree avr_handle_progmem_attribute PARAMS ((tree *, tree, tree, int, bool *));
63 static tree avr_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
64 const struct attribute_spec avr_attribute_table[];
65 static bool avr_assemble_integer PARAMS ((rtx, unsigned int, int));
66 static void avr_file_start PARAMS ((void));
67 static void avr_file_end PARAMS ((void));
68 static void avr_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
69 static void avr_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
70 static void avr_unique_section PARAMS ((tree, int));
71 static void avr_insert_attributes PARAMS ((tree, tree *));
72 static unsigned int avr_section_type_flags PARAMS ((tree, const char *, int));
74 static void avr_reorg PARAMS ((void));
75 static void avr_asm_out_ctor PARAMS ((rtx, int));
76 static void avr_asm_out_dtor PARAMS ((rtx, int));
77 static int default_rtx_costs PARAMS ((rtx, enum rtx_code, enum rtx_code));
78 static bool avr_rtx_costs PARAMS ((rtx, int, int, int *));
79 static int avr_address_cost PARAMS ((rtx));
81 /* Allocate registers from r25 to r8 for parameters for function calls */
82 #define FIRST_CUM_REG 26
84 /* Temporary register RTX (gen_rtx (REG,QImode,TMP_REGNO)) */
87 /* Zeroed register RTX (gen_rtx (REG,QImode,ZERO_REGNO)) */
90 /* RTX for register which will be used for loading immediate values to
94 /* AVR register names {"r0", "r1", ..., "r31"} */
95 static const char *const avr_regnames[] = REGISTER_NAMES;
97 /* This holds the last insn address. */
98 static int last_insn_address = 0;
100 /* Commands count in the compiled file */
101 static int commands_in_file;
103 /* Commands in the functions prologues in the compiled file */
104 static int commands_in_prologues;
106 /* Commands in the functions epilogues in the compiled file */
107 static int commands_in_epilogues;
109 /* Prologue/Epilogue size in words */
110 static int prologue_size;
111 static int epilogue_size;
113 /* Size of all jump tables in the current function, in words. */
114 static int jump_tables_size;
116 /* Initial stack value specified by the `-minit-stack=' option */
117 const char *avr_init_stack = "__stack";
119 /* Default MCU name */
120 const char *avr_mcu_name = "avr2";
122 /* Preprocessor macros to define depending on MCU type. */
123 const char *avr_base_arch_macro;
124 const char *avr_extra_arch_macro;
126 /* More than 8K of program memory: use "call" and "jmp". */
129 /* Enhanced core: use "movw", "mul", ... */
130 int avr_enhanced_p = 0;
132 /* Assembler only. */
133 int avr_asm_only_p = 0;
139 const char *const macro;
142 static const struct base_arch_s avr_arch_types[] = {
143 { 1, 0, 0, NULL }, /* unknown device specified */
144 { 1, 0, 0, "__AVR_ARCH__=1" },
145 { 0, 0, 0, "__AVR_ARCH__=2" },
146 { 0, 0, 1, "__AVR_ARCH__=3" },
147 { 0, 1, 0, "__AVR_ARCH__=4" },
148 { 0, 1, 1, "__AVR_ARCH__=5" }
152 const char *const name;
153 int arch; /* index in avr_arch_types[] */
154 /* Must lie outside user's namespace. NULL == no macro. */
155 const char *const macro;
158 /* List of all known AVR MCU types - if updated, it has to be kept
159 in sync in several places (FIXME: is there a better way?):
161 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
162 - t-avr (MULTILIB_MATCHES)
163 - gas/config/tc-avr.c
166 static const struct mcu_type_s avr_mcu_types[] = {
167 /* Classic, <= 8K. */
169 { "at90s2313", 2, "__AVR_AT90S2313__" },
170 { "at90s2323", 2, "__AVR_AT90S2323__" },
171 { "at90s2333", 2, "__AVR_AT90S2333__" },
172 { "at90s2343", 2, "__AVR_AT90S2343__" },
173 { "attiny22", 2, "__AVR_ATtiny22__" },
174 { "attiny26", 2, "__AVR_ATtiny26__" },
175 { "at90s4414", 2, "__AVR_AT90S4414__" },
176 { "at90s4433", 2, "__AVR_AT90S4433__" },
177 { "at90s4434", 2, "__AVR_AT90S4434__" },
178 { "at90s8515", 2, "__AVR_AT90S8515__" },
179 { "at90c8534", 2, "__AVR_AT90C8534__" },
180 { "at90s8535", 2, "__AVR_AT90S8535__" },
181 { "at86rf401", 2, "__AVR_AT86RF401__" },
184 { "atmega103", 3, "__AVR_ATmega103__" },
185 { "atmega603", 3, "__AVR_ATmega603__" },
186 { "at43usb320", 3, "__AVR_AT43USB320__" },
187 { "at43usb355", 3, "__AVR_AT43USB355__" },
188 { "at76c711", 3, "__AVR_AT76C711__" },
189 /* Enhanced, <= 8K. */
191 { "atmega8", 4, "__AVR_ATmega8__" },
192 { "atmega8515", 4, "__AVR_ATmega8515__" },
193 { "atmega8535", 4, "__AVR_ATmega8535__" },
194 /* Enhanced, > 8K. */
196 { "atmega16", 5, "__AVR_ATmega16__" },
197 { "atmega161", 5, "__AVR_ATmega161__" },
198 { "atmega162", 5, "__AVR_ATmega162__" },
199 { "atmega163", 5, "__AVR_ATmega163__" },
200 { "atmega169", 5, "__AVR_ATmega169__" },
201 { "atmega32", 5, "__AVR_ATmega32__" },
202 { "atmega323", 5, "__AVR_ATmega323__" },
203 { "atmega64", 5, "__AVR_ATmega64__" },
204 { "atmega128", 5, "__AVR_ATmega128__" },
205 { "at94k", 5, "__AVR_AT94K__" },
206 /* Assembler only. */
208 { "at90s1200", 1, "__AVR_AT90S1200__" },
209 { "attiny11", 1, "__AVR_ATtiny11__" },
210 { "attiny12", 1, "__AVR_ATtiny12__" },
211 { "attiny15", 1, "__AVR_ATtiny15__" },
212 { "attiny28", 1, "__AVR_ATtiny28__" },
216 int avr_case_values_threshold = 30000;
218 /* Initialize the GCC target structure. */
219 #undef TARGET_ASM_ALIGNED_HI_OP
220 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
221 #undef TARGET_ASM_INTEGER
222 #define TARGET_ASM_INTEGER avr_assemble_integer
223 #undef TARGET_ASM_FILE_START
224 #define TARGET_ASM_FILE_START avr_file_start
225 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
226 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
227 #undef TARGET_ASM_FILE_END
228 #define TARGET_ASM_FILE_END avr_file_end
230 #undef TARGET_ASM_FUNCTION_PROLOGUE
231 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
232 #undef TARGET_ASM_FUNCTION_EPILOGUE
233 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
234 #undef TARGET_ATTRIBUTE_TABLE
235 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
236 #undef TARGET_ASM_UNIQUE_SECTION
237 #define TARGET_ASM_UNIQUE_SECTION avr_unique_section
238 #undef TARGET_INSERT_ATTRIBUTES
239 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
240 #undef TARGET_SECTION_TYPE_FLAGS
241 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
242 #undef TARGET_RTX_COSTS
243 #define TARGET_RTX_COSTS avr_rtx_costs
244 #undef TARGET_ADDRESS_COST
245 #define TARGET_ADDRESS_COST avr_address_cost
246 #undef TARGET_MACHINE_DEPENDENT_REORG
247 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
249 struct gcc_target targetm = TARGET_INITIALIZER;
252 avr_override_options ()
254 const struct mcu_type_s *t;
255 const struct base_arch_s *base;
257 for (t = avr_mcu_types; t->name; t++)
258 if (strcmp (t->name, avr_mcu_name) == 0)
263 fprintf (stderr, "unknown MCU `%s' specified\nKnown MCU names:\n",
265 for (t = avr_mcu_types; t->name; t++)
266 fprintf (stderr," %s\n", t->name);
269 base = &avr_arch_types[t->arch];
270 avr_asm_only_p = base->asm_only;
271 avr_enhanced_p = base->enhanced;
272 avr_mega_p = base->mega;
273 avr_base_arch_macro = base->macro;
274 avr_extra_arch_macro = t->macro;
276 if (optimize && !TARGET_NO_TABLEJUMP)
277 avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
281 /* Initialize TMP_REG_RTX and ZERO_REG_RTX */
285 tmp_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
286 memset (tmp_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
287 PUT_CODE (tmp_reg_rtx, REG);
288 PUT_MODE (tmp_reg_rtx, QImode);
289 XINT (tmp_reg_rtx, 0) = TMP_REGNO;
291 zero_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
292 memset (zero_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
293 PUT_CODE (zero_reg_rtx, REG);
294 PUT_MODE (zero_reg_rtx, QImode);
295 XINT (zero_reg_rtx, 0) = ZERO_REGNO;
297 ldi_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
298 memset (ldi_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
299 PUT_CODE (ldi_reg_rtx, REG);
300 PUT_MODE (ldi_reg_rtx, QImode);
301 XINT (ldi_reg_rtx, 0) = LDI_REG_REGNO;
304 /* return register class from register number */
306 static const int reg_class_tab[]={
307 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
308 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
309 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
310 GENERAL_REGS, /* r0 - r15 */
311 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
312 LD_REGS, /* r16 - 23 */
313 ADDW_REGS,ADDW_REGS, /* r24,r25 */
314 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
315 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
316 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
317 STACK_REG,STACK_REG /* SPL,SPH */
320 /* Return register class for register R */
323 avr_regno_reg_class (r)
327 return reg_class_tab[r];
332 /* A C expression which defines the machine-dependent operand
333 constraint letters for register classes. If C is such a
334 letter, the value should be the register class corresponding to
335 it. Otherwise, the value should be `NO_REGS'. The register
336 letter `r', corresponding to class `GENERAL_REGS', will not be
337 passed to this macro; you do not need to handle it. */
340 avr_reg_class_from_letter (c)
345 case 't' : return R0_REG;
346 case 'b' : return BASE_POINTER_REGS;
347 case 'e' : return POINTER_REGS;
348 case 'w' : return ADDW_REGS;
349 case 'd' : return LD_REGS;
350 case 'l' : return NO_LD_REGS;
351 case 'a' : return SIMPLE_LD_REGS;
352 case 'x' : return POINTER_X_REGS;
353 case 'y' : return POINTER_Y_REGS;
354 case 'z' : return POINTER_Z_REGS;
355 case 'q' : return STACK_REG;
361 /* Return nonzero if FUNC is a naked function. */
364 avr_naked_function_p (func)
369 if (TREE_CODE (func) != FUNCTION_DECL)
372 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
373 return a != NULL_TREE;
376 /* Return nonzero if FUNC is an interrupt function as specified
377 by the "interrupt" attribute. */
380 interrupt_function_p (func)
385 if (TREE_CODE (func) != FUNCTION_DECL)
388 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
389 return a != NULL_TREE;
392 /* Return nonzero if FUNC is a signal function as specified
393 by the "signal" attribute. */
396 signal_function_p (func)
401 if (TREE_CODE (func) != FUNCTION_DECL)
404 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
405 return a != NULL_TREE;
408 /* Return the number of hard registers to push/pop in the prologue/epilogue
409 of the current function, and optionally store these registers in SET. */
412 avr_regs_to_save (set)
416 int int_or_sig_p = (interrupt_function_p (current_function_decl)
417 || signal_function_p (current_function_decl));
418 int leaf_func_p = leaf_function_p ();
421 CLEAR_HARD_REG_SET (*set);
424 /* No need to save any registers if the function never returns. */
425 if (TREE_THIS_VOLATILE (current_function_decl))
428 for (reg = 0; reg < 32; reg++)
430 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
431 any global register variables. */
435 if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
436 || (regs_ever_live[reg]
437 && (int_or_sig_p || !call_used_regs[reg])
438 && !(frame_pointer_needed
439 && (reg == REG_Y || reg == (REG_Y+1)))))
442 SET_HARD_REG_BIT (*set, reg);
449 /* Compute offset between arg_pointer and frame_pointer */
452 initial_elimination_offset (from, to)
456 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
460 int offset = frame_pointer_needed ? 2 : 0;
462 offset += avr_regs_to_save (NULL);
463 return get_frame_size () + 2 + 1 + offset;
467 /* Return 1 if the function epilogue is just a single "ret". */
470 avr_simple_epilogue ()
472 return (! frame_pointer_needed
473 && get_frame_size () == 0
474 && avr_regs_to_save (NULL) == 0
475 && ! interrupt_function_p (current_function_decl)
476 && ! signal_function_p (current_function_decl)
477 && ! avr_naked_function_p (current_function_decl)
478 && ! MAIN_NAME_P (DECL_NAME (current_function_decl))
479 && ! TREE_THIS_VOLATILE (current_function_decl));
482 /* This function checks sequence of live registers */
491 for (reg = 0; reg < 18; ++reg)
493 if (!call_used_regs[reg])
495 if (regs_ever_live[reg])
505 if (!frame_pointer_needed)
507 if (regs_ever_live[REG_Y])
515 if (regs_ever_live[REG_Y+1])
528 return (cur_seq == live_seq) ? live_seq : 0;
532 /* Output to FILE the asm instructions to adjust the frame pointer by
533 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
534 (epilogue). Returns the number of instructions generated. */
537 out_adj_frame_ptr (file, adj)
545 if (TARGET_TINY_STACK)
547 if (adj < -63 || adj > 63)
548 warning ("large frame pointer change (%d) with -mtiny-stack", adj);
550 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
551 over "sbiw" (2 cycles, same size). */
553 fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
556 else if (adj < -63 || adj > 63)
558 fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
559 AS2 (sbci, r29, hi8(%d)) CR_TAB),
565 fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
570 fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
578 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
579 handling various cases of interrupt enable flag state BEFORE and AFTER
580 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
581 Returns the number of instructions generated. */
584 out_set_stack_ptr (file, before, after)
589 int do_sph, do_cli, do_save, do_sei, lock_sph, size;
591 /* The logic here is so that -mno-interrupts actually means
592 "it is safe to write SPH in one instruction, then SPL in the
593 next instruction, without disabling interrupts first".
594 The after != -1 case (interrupt/signal) is not affected. */
596 do_sph = !TARGET_TINY_STACK;
597 lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
598 do_cli = (before != 0 && (after == 0 || lock_sph));
599 do_save = (do_cli && before == -1 && after == -1);
600 do_sei = ((do_cli || before != 1) && after == 1);
605 fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
611 fprintf (file, "cli" CR_TAB);
615 /* Do SPH first - maybe this will disable interrupts for one instruction
616 someday (a suggestion has been sent to avr@atmel.com for consideration
617 in future devices - that would make -mno-interrupts always safe). */
620 fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
624 /* Set/restore the I flag now - interrupts will be really enabled only
625 after the next instruction. This is not clearly documented, but
626 believed to be true for all AVR devices. */
629 fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
634 fprintf (file, "sei" CR_TAB);
638 fprintf (file, AS2 (out, __SP_L__, r28) "\n");
644 /* Output function prologue */
647 avr_output_function_prologue (file, size)
652 int interrupt_func_p;
658 last_insn_address = 0;
659 jump_tables_size = 0;
661 fprintf (file, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n",
664 if (avr_naked_function_p (current_function_decl))
666 fputs ("/* prologue: naked */\n", file);
670 interrupt_func_p = interrupt_function_p (current_function_decl);
671 signal_func_p = signal_function_p (current_function_decl);
672 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
673 live_seq = sequent_regs_live ();
674 minimize = (TARGET_CALL_PROLOGUES
675 && !interrupt_func_p && !signal_func_p && live_seq);
677 if (interrupt_func_p)
679 fprintf (file,"\tsei\n");
682 if (interrupt_func_p || signal_func_p)
685 AS1 (push,__zero_reg__) CR_TAB
686 AS1 (push,__tmp_reg__) CR_TAB
687 AS2 (in,__tmp_reg__,__SREG__) CR_TAB
688 AS1 (push,__tmp_reg__) CR_TAB
689 AS1 (clr,__zero_reg__) "\n");
695 AS1 (ldi,r28) ",lo8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
696 AS1 (ldi,r29) ",hi8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
697 AS2 (out,__SP_H__,r29) CR_TAB
698 AS2 (out,__SP_L__,r28) "\n"),
699 avr_init_stack, size, avr_init_stack, size);
703 else if (minimize && (frame_pointer_needed || live_seq > 6))
706 AS1 (ldi, r26) ",lo8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
707 AS1 (ldi, r27) ",hi8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB), size, size);
709 fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB
710 AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB)
711 ,current_function_name, current_function_name);
717 fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
718 (18 - live_seq) * 2);
723 fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
724 (18 - live_seq) * 2);
727 fprintf (file, ".L_%s_body:\n", current_function_name);
733 prologue_size += avr_regs_to_save (&set);
734 for (reg = 0; reg < 32; ++reg)
736 if (TEST_HARD_REG_BIT (set, reg))
738 fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
741 if (frame_pointer_needed)
745 AS1 (push,r28) CR_TAB
746 AS1 (push,r29) CR_TAB
747 AS2 (in,r28,__SP_L__) CR_TAB
748 AS2 (in,r29,__SP_H__) "\n");
753 prologue_size += out_adj_frame_ptr (file, size);
755 if (interrupt_func_p)
757 prologue_size += out_set_stack_ptr (file, 1, 1);
759 else if (signal_func_p)
761 prologue_size += out_set_stack_ptr (file, 0, 0);
765 prologue_size += out_set_stack_ptr (file, -1, -1);
773 fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
776 /* Output function epilogue */
779 avr_output_function_epilogue (file, size)
784 int interrupt_func_p;
790 rtx last = get_last_nonnote_insn ();
792 function_size = jump_tables_size;
795 rtx first = get_first_nonnote_insn ();
796 function_size += (INSN_ADDRESSES (INSN_UID (last)) -
797 INSN_ADDRESSES (INSN_UID (first)));
798 function_size += get_attr_length (last);
801 fprintf (file, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n", size);
804 if (avr_naked_function_p (current_function_decl))
806 fputs ("/* epilogue: naked */\n", file);
810 if (last && GET_CODE (last) == BARRIER)
812 fputs ("/* epilogue: noreturn */\n", file);
816 interrupt_func_p = interrupt_function_p (current_function_decl);
817 signal_func_p = signal_function_p (current_function_decl);
818 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
819 live_seq = sequent_regs_live ();
820 minimize = (TARGET_CALL_PROLOGUES
821 && !interrupt_func_p && !signal_func_p && live_seq);
825 /* Return value from main() is already in the correct registers
826 (r25:r24) as the exit() argument. */
829 fputs ("\t" AS1 (jmp,exit) "\n", file);
834 fputs ("\t" AS1 (rjmp,exit) "\n", file);
838 else if (minimize && (frame_pointer_needed || live_seq > 4))
840 fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
842 if (frame_pointer_needed)
844 epilogue_size += out_adj_frame_ptr (file, -size);
848 fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
849 AS2 (in , r29, __SP_H__) CR_TAB));
855 fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
856 (18 - live_seq) * 2);
861 fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
862 (18 - live_seq) * 2);
870 if (frame_pointer_needed)
875 epilogue_size += out_adj_frame_ptr (file, -size);
877 if (interrupt_func_p || signal_func_p)
879 epilogue_size += out_set_stack_ptr (file, -1, 0);
883 epilogue_size += out_set_stack_ptr (file, -1, -1);
892 epilogue_size += avr_regs_to_save (&set);
893 for (reg = 31; reg >= 0; --reg)
895 if (TEST_HARD_REG_BIT (set, reg))
897 fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
901 if (interrupt_func_p || signal_func_p)
904 AS1 (pop,__tmp_reg__) CR_TAB
905 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
906 AS1 (pop,__tmp_reg__) CR_TAB
907 AS1 (pop,__zero_reg__) "\n");
909 fprintf (file, "\treti\n");
912 fprintf (file, "\tret\n");
917 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
918 fprintf (file, "/* function %s size %d (%d) */\n", current_function_name,
919 prologue_size + function_size + epilogue_size, function_size);
920 commands_in_file += prologue_size + function_size + epilogue_size;
921 commands_in_prologues += prologue_size;
922 commands_in_epilogues += epilogue_size;
926 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
927 machine for a memory operand of mode MODE. */
930 legitimate_address_p (mode, x, strict)
931 enum machine_mode mode;
935 enum reg_class r = NO_REGS;
937 if (TARGET_ALL_DEBUG)
939 fprintf (stderr, "mode: (%s) %s %s %s %s:",
941 strict ? "(strict)": "",
942 reload_completed ? "(reload_completed)": "",
943 reload_in_progress ? "(reload_in_progress)": "",
944 reg_renumber ? "(reg_renumber)" : "");
945 if (GET_CODE (x) == PLUS
946 && REG_P (XEXP (x, 0))
947 && GET_CODE (XEXP (x, 1)) == CONST_INT
948 && INTVAL (XEXP (x, 1)) >= 0
949 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
952 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
953 true_regnum (XEXP (x, 0)));
956 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
957 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
959 else if (CONSTANT_ADDRESS_P (x))
961 else if (GET_CODE (x) == PLUS
962 && REG_P (XEXP (x, 0))
963 && GET_CODE (XEXP (x, 1)) == CONST_INT
964 && INTVAL (XEXP (x, 1)) >= 0)
966 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
970 || REGNO (XEXP (x,0)) == REG_Y
971 || REGNO (XEXP (x,0)) == REG_Z)
972 r = BASE_POINTER_REGS;
973 if (XEXP (x,0) == frame_pointer_rtx
974 || XEXP (x,0) == arg_pointer_rtx)
975 r = BASE_POINTER_REGS;
977 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
980 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
981 && REG_P (XEXP (x, 0))
982 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
983 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
987 if (TARGET_ALL_DEBUG)
989 fprintf (stderr, " ret = %c\n", r);
991 return r == NO_REGS ? 0 : (int)r;
994 /* Attempts to replace X with a valid
995 memory address for an operand of mode MODE */
998 legitimize_address (x, oldx, mode)
1001 enum machine_mode mode;
1004 if (TARGET_ALL_DEBUG)
1006 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
1010 if (GET_CODE (oldx) == PLUS
1011 && REG_P (XEXP (oldx,0)))
1013 if (REG_P (XEXP (oldx,1)))
1014 x = force_reg (GET_MODE (oldx), oldx);
1015 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
1017 int offs = INTVAL (XEXP (oldx,1));
1018 if (frame_pointer_rtx != XEXP (oldx,0))
1019 if (offs > MAX_LD_OFFSET (mode))
1021 if (TARGET_ALL_DEBUG)
1022 fprintf (stderr, "force_reg (big offset)\n");
1023 x = force_reg (GET_MODE (oldx), oldx);
1031 /* Return a pointer register name as a string */
1034 ptrreg_to_str (regno)
1039 case REG_X: return "X";
1040 case REG_Y: return "Y";
1041 case REG_Z: return "Z";
1048 /* Return the condition name as a string.
1049 Used in conditional jump constructing */
1062 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1067 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1080 /* Output ADDR to FILE as address */
1083 print_operand_address (file, addr)
1087 switch (GET_CODE (addr))
1090 fprintf (file, ptrreg_to_str (REGNO (addr)));
1094 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1098 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1102 if (CONSTANT_ADDRESS_P (addr)
1103 && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
1104 || GET_CODE (addr) == LABEL_REF))
1106 fprintf (file, "pm(");
1107 output_addr_const (file,addr);
1108 fprintf (file ,")");
1111 output_addr_const (file, addr);
1116 /* Output X as assembler operand to file FILE */
1119 print_operand (file, x, code)
1126 if (code >= 'A' && code <= 'D')
1136 if (x == zero_reg_rtx)
1137 fprintf (file, "__zero_reg__");
1139 fprintf (file, reg_names[true_regnum (x) + abcd]);
1141 else if (GET_CODE (x) == CONST_INT)
1142 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
1143 else if (GET_CODE (x) == MEM)
1145 rtx addr = XEXP (x,0);
1147 if (CONSTANT_P (addr) && abcd)
1150 output_address (addr);
1151 fprintf (file, ")+%d", abcd);
1153 else if (code == 'o')
1155 if (GET_CODE (addr) != PLUS)
1156 fatal_insn ("bad address, not (reg+disp):", addr);
1158 print_operand (file, XEXP (addr, 1), 0);
1160 else if (GET_CODE (addr) == PLUS)
1162 print_operand_address (file, XEXP (addr,0));
1163 if (REGNO (XEXP (addr, 0)) == REG_X)
1164 fatal_insn ("internal compiler error. Bad address:"
1167 print_operand (file, XEXP (addr,1), code);
1170 print_operand_address (file, addr);
1172 else if (GET_CODE (x) == CONST_DOUBLE)
1176 if (GET_MODE (x) != SFmode)
1177 fatal_insn ("internal compiler error. Unknown mode:", x);
1178 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1179 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1180 fprintf (file, "0x%lx", val);
1182 else if (code == 'j')
1183 fputs (cond_string (GET_CODE (x)), file);
1184 else if (code == 'k')
1185 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
1187 print_operand_address (file, x);
1190 /* Recognize operand OP of mode MODE used in call instructions */
1193 call_insn_operand (op, mode)
1195 enum machine_mode mode ATTRIBUTE_UNUSED;
1197 if (GET_CODE (op) == MEM)
1199 rtx inside = XEXP (op, 0);
1200 if (register_operand (inside, Pmode))
1202 if (CONSTANT_ADDRESS_P (inside))
1208 /* Update the condition code in the INSN. */
1211 notice_update_cc (body, insn)
1212 rtx body ATTRIBUTE_UNUSED;
1217 switch (get_attr_cc (insn))
1220 /* Insn does not affect CC at all. */
1228 set = single_set (insn);
1232 cc_status.flags |= CC_NO_OVERFLOW;
1233 cc_status.value1 = SET_DEST (set);
1238 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1239 The V flag may or may not be known but that's ok because
1240 alter_cond will change tests to use EQ/NE. */
1241 set = single_set (insn);
1245 cc_status.value1 = SET_DEST (set);
1246 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1251 set = single_set (insn);
1254 cc_status.value1 = SET_SRC (set);
1258 /* Insn doesn't leave CC in a usable state. */
1261 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1262 set = single_set (insn);
1265 rtx src = SET_SRC (set);
1267 if (GET_CODE (src) == ASHIFTRT
1268 && GET_MODE (src) == QImode)
1270 rtx x = XEXP (src, 1);
1272 if (GET_CODE (x) == CONST_INT
1275 cc_status.value1 = SET_DEST (set);
1276 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1284 /* Return maximum number of consecutive registers of
1285 class CLASS needed to hold a value of mode MODE. */
1288 class_max_nregs (class, mode)
1289 enum reg_class class ATTRIBUTE_UNUSED;
1290 enum machine_mode mode;
1292 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1295 /* Choose mode for jump insn:
1296 1 - relative jump in range -63 <= x <= 62 ;
1297 2 - relative jump in range -2046 <= x <= 2045 ;
1298 3 - absolute jump (only for ATmega[16]03). */
1301 avr_jump_mode (x, insn)
1302 rtx x; /* jump operand */
1303 rtx insn; /* jump insn */
1305 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1306 ? XEXP (x, 0) : x));
1307 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1308 int jump_distance = cur_addr - dest_addr;
1310 if (-63 <= jump_distance && jump_distance <= 62)
1312 else if (-2046 <= jump_distance && jump_distance <= 2045)
1320 /* return an AVR condition jump commands.
1321 X is a comparison RTX.
1322 LEN is a number returned by avr_jump_mode function.
1323 if REVERSE nonzero then condition code in X must be reversed. */
1326 ret_cond_branch (x, len, reverse)
1331 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1336 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1337 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1339 len == 2 ? (AS1 (breq,.+4) CR_TAB
1340 AS1 (brmi,.+2) CR_TAB
1342 (AS1 (breq,.+6) CR_TAB
1343 AS1 (brmi,.+4) CR_TAB
1347 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1349 len == 2 ? (AS1 (breq,.+4) CR_TAB
1350 AS1 (brlt,.+2) CR_TAB
1352 (AS1 (breq,.+6) CR_TAB
1353 AS1 (brlt,.+4) CR_TAB
1356 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1358 len == 2 ? (AS1 (breq,.+4) CR_TAB
1359 AS1 (brlo,.+2) CR_TAB
1361 (AS1 (breq,.+6) CR_TAB
1362 AS1 (brlo,.+4) CR_TAB
1365 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1366 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1368 len == 2 ? (AS1 (breq,.+2) CR_TAB
1369 AS1 (brpl,.+2) CR_TAB
1371 (AS1 (breq,.+2) CR_TAB
1372 AS1 (brpl,.+4) CR_TAB
1375 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1377 len == 2 ? (AS1 (breq,.+2) CR_TAB
1378 AS1 (brge,.+2) CR_TAB
1380 (AS1 (breq,.+2) CR_TAB
1381 AS1 (brge,.+4) CR_TAB
1384 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1386 len == 2 ? (AS1 (breq,.+2) CR_TAB
1387 AS1 (brsh,.+2) CR_TAB
1389 (AS1 (breq,.+2) CR_TAB
1390 AS1 (brsh,.+4) CR_TAB
1398 return AS1 (br%k1,%0);
1400 return (AS1 (br%j1,.+2) CR_TAB
1403 return (AS1 (br%j1,.+4) CR_TAB
1412 return AS1 (br%j1,%0);
1414 return (AS1 (br%k1,.+2) CR_TAB
1417 return (AS1 (br%k1,.+4) CR_TAB
1425 /* Predicate function for immediate operand which fits to byte (8bit) */
1428 byte_immediate_operand (op, mode)
1430 enum machine_mode mode ATTRIBUTE_UNUSED;
1432 return (GET_CODE (op) == CONST_INT
1433 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1436 /* Output all insn addresses and their sizes into the assembly language
1437 output file. This is helpful for debugging whether the length attributes
1438 in the md file are correct.
1439 Output insn cost for next insn. */
1442 final_prescan_insn (insn, operand, num_operands)
1443 rtx insn, *operand ATTRIBUTE_UNUSED;
1444 int num_operands ATTRIBUTE_UNUSED;
1446 int uid = INSN_UID (insn);
1448 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1450 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1451 INSN_ADDRESSES (uid),
1452 INSN_ADDRESSES (uid) - last_insn_address,
1453 rtx_cost (PATTERN (insn), INSN));
1455 last_insn_address = INSN_ADDRESSES (uid);
1458 /* Return 0 if undefined, 1 if always true or always false. */
1461 avr_simplify_comparison_p (mode, operator, x)
1462 enum machine_mode mode;
1466 unsigned int max = (mode == QImode ? 0xff :
1467 mode == HImode ? 0xffff :
1468 mode == SImode ? 0xffffffff : 0);
1469 if (max && operator && GET_CODE (x) == CONST_INT)
1471 if (unsigned_condition (operator) != operator)
1474 if (max != (INTVAL (x) & max)
1475 && INTVAL (x) != 0xff)
1482 /* Returns nonzero if REGNO is the number of a hard
1483 register in which function arguments are sometimes passed. */
1486 function_arg_regno_p(r)
1489 return (r >= 8 && r <= 25);
1492 /* Initializing the variable cum for the state at the beginning
1493 of the argument list. */
1496 init_cumulative_args (cum, fntype, libname, fndecl)
1497 CUMULATIVE_ARGS *cum;
1500 tree fndecl ATTRIBUTE_UNUSED;
1503 cum->regno = FIRST_CUM_REG;
1504 if (!libname && fntype)
1506 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1507 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1508 != void_type_node));
1514 /* Returns the number of registers to allocate for a function argument. */
1517 avr_num_arg_regs (mode, type)
1518 enum machine_mode mode;
1523 if (mode == BLKmode)
1524 size = int_size_in_bytes (type);
1526 size = GET_MODE_SIZE (mode);
1528 /* Align all function arguments to start in even-numbered registers.
1529 Odd-sized arguments leave holes above them. */
1531 return (size + 1) & ~1;
1534 /* Controls whether a function argument is passed
1535 in a register, and which register. */
1538 function_arg (cum, mode, type, named)
1539 CUMULATIVE_ARGS *cum;
1540 enum machine_mode mode;
1542 int named ATTRIBUTE_UNUSED;
1544 int bytes = avr_num_arg_regs (mode, type);
1546 if (cum->nregs && bytes <= cum->nregs)
1547 return gen_rtx (REG, mode, cum->regno - bytes);
1552 /* Update the summarizer variable CUM to advance past an argument
1553 in the argument list. */
1556 function_arg_advance (cum, mode, type, named)
1557 CUMULATIVE_ARGS *cum; /* current arg information */
1558 enum machine_mode mode; /* current arg mode */
1559 tree type; /* type of the argument or 0 if lib support */
1560 int named ATTRIBUTE_UNUSED; /* whether or not the argument was named */
1562 int bytes = avr_num_arg_regs (mode, type);
1564 cum->nregs -= bytes;
1565 cum->regno -= bytes;
1567 if (cum->nregs <= 0)
1570 cum->regno = FIRST_CUM_REG;
1574 /***********************************************************************
1575 Functions for outputting various mov's for a various modes
1576 ************************************************************************/
1578 output_movqi (insn, operands, l)
1584 rtx dest = operands[0];
1585 rtx src = operands[1];
1593 if (register_operand (dest, QImode))
1595 if (register_operand (src, QImode)) /* mov r,r */
1597 if (test_hard_reg_class (STACK_REG, dest))
1598 return AS2 (out,%0,%1);
1599 else if (test_hard_reg_class (STACK_REG, src))
1600 return AS2 (in,%0,%1);
1602 return AS2 (mov,%0,%1);
1604 else if (CONSTANT_P (src))
1606 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1607 return AS2 (ldi,%0,lo8(%1));
1609 if (GET_CODE (src) == CONST_INT)
1611 if (src == const0_rtx) /* mov r,L */
1612 return AS1 (clr,%0);
1613 else if (src == const1_rtx)
1615 if (reg_was_0 (insn, dest))
1616 return AS1 (inc,%0 ; reg_was_0);
1619 return (AS1 (clr,%0) CR_TAB
1622 else if (src == constm1_rtx)
1624 /* Immediate constants -1 to any register */
1625 if (reg_was_0 (insn, dest))
1626 return AS1 (dec,%0 ; reg_was_0);
1629 return (AS1 (clr,%0) CR_TAB
1634 int bit_nr = exact_log2 (INTVAL (src));
1638 if (reg_was_0 (insn, dest))
1642 output_asm_insn ("set ; reg_was_0", operands);
1648 output_asm_insn ((AS1 (clr,%0) CR_TAB
1652 avr_output_bld (operands, bit_nr);
1659 /* Last resort, larger than loading from memory. */
1661 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1662 AS2 (ldi,r31,lo8(%1)) CR_TAB
1663 AS2 (mov,%0,r31) CR_TAB
1664 AS2 (mov,r31,__tmp_reg__));
1666 else if (GET_CODE (src) == MEM)
1667 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1669 else if (GET_CODE (dest) == MEM)
1671 const char *template;
1673 if (src == const0_rtx)
1674 operands[1] = zero_reg_rtx;
1676 template = out_movqi_mr_r (insn, operands, real_l);
1679 output_asm_insn (template, operands);
1688 output_movhi (insn, operands, l)
1694 rtx dest = operands[0];
1695 rtx src = operands[1];
1701 if (register_operand (dest, HImode))
1703 if (register_operand (src, HImode)) /* mov r,r */
1705 if (test_hard_reg_class (STACK_REG, dest))
1707 if (TARGET_TINY_STACK)
1710 return AS2 (out,__SP_L__,%A1);
1712 else if (TARGET_NO_INTERRUPTS)
1715 return (AS2 (out,__SP_H__,%B1) CR_TAB
1716 AS2 (out,__SP_L__,%A1));
1720 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1722 AS2 (out,__SP_H__,%B1) CR_TAB
1723 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1724 AS2 (out,__SP_L__,%A1));
1726 else if (test_hard_reg_class (STACK_REG, src))
1729 return (AS2 (in,%A0,__SP_L__) CR_TAB
1730 AS2 (in,%B0,__SP_H__));
1736 return (AS2 (movw,%0,%1));
1739 if (true_regnum (dest) > true_regnum (src))
1742 return (AS2 (mov,%B0,%B1) CR_TAB
1748 return (AS2 (mov,%A0,%A1) CR_TAB
1752 else if (CONSTANT_P (src))
1754 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1756 if (byte_immediate_operand (src, HImode)
1757 && reg_was_0 (insn, dest))
1760 return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0));
1764 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1765 AS2 (ldi,%B0,hi8(%1)));
1768 if (GET_CODE (src) == CONST_INT)
1770 if (src == const0_rtx) /* mov r,L */
1773 return (AS1 (clr,%A0) CR_TAB
1776 else if (src == const1_rtx)
1778 if (reg_was_0 (insn, dest))
1781 return AS1 (inc,%0 ; reg_was_0);
1785 return (AS1 (clr,%A0) CR_TAB
1786 AS1 (clr,%B0) CR_TAB
1789 else if (src == constm1_rtx)
1791 /* Immediate constants -1 to any register */
1792 if (reg_was_0 (insn, dest))
1795 return (AS1 (dec,%A0 ; reg_was_0) CR_TAB
1800 return (AS1 (clr,%0) CR_TAB
1801 AS1 (dec,%A0) CR_TAB
1806 int bit_nr = exact_log2 (INTVAL (src));
1810 if (reg_was_0 (insn, dest))
1814 output_asm_insn ("set ; reg_was_0", operands);
1820 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1821 AS1 (clr,%B0) CR_TAB
1825 avr_output_bld (operands, bit_nr);
1831 if ((INTVAL (src) & 0xff) == 0)
1834 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1835 AS1 (clr,%A0) CR_TAB
1836 AS2 (ldi,r31,hi8(%1)) CR_TAB
1837 AS2 (mov,%B0,r31) CR_TAB
1838 AS2 (mov,r31,__tmp_reg__));
1840 else if ((INTVAL (src) & 0xff00) == 0)
1843 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1844 AS2 (ldi,r31,lo8(%1)) CR_TAB
1845 AS2 (mov,%A0,r31) CR_TAB
1846 AS1 (clr,%B0) CR_TAB
1847 AS2 (mov,r31,__tmp_reg__));
1851 /* Last resort, equal to loading from memory. */
1853 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1854 AS2 (ldi,r31,lo8(%1)) CR_TAB
1855 AS2 (mov,%A0,r31) CR_TAB
1856 AS2 (ldi,r31,hi8(%1)) CR_TAB
1857 AS2 (mov,%B0,r31) CR_TAB
1858 AS2 (mov,r31,__tmp_reg__));
1860 else if (GET_CODE (src) == MEM)
1861 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1863 else if (GET_CODE (dest) == MEM)
1865 const char *template;
1867 if (src == const0_rtx)
1868 operands[1] = zero_reg_rtx;
1870 template = out_movhi_mr_r (insn, operands, real_l);
1873 output_asm_insn (template, operands);
1878 fatal_insn ("invalid insn:", insn);
1883 out_movqi_r_mr (insn, op, l)
1886 int *l; /* instruction length */
1890 rtx x = XEXP (src, 0);
1896 if (CONSTANT_ADDRESS_P (x))
1898 if (avr_io_address_p (x, 1))
1901 return AS2 (in,%0,%1-0x20);
1904 return AS2 (lds,%0,%1);
1906 /* memory access by reg+disp */
1907 else if (GET_CODE (x) == PLUS
1908 && REG_P (XEXP (x,0))
1909 && GET_CODE (XEXP (x,1)) == CONST_INT)
1911 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
1913 int disp = INTVAL (XEXP (x,1));
1914 if (REGNO (XEXP (x,0)) != REG_Y)
1915 fatal_insn ("incorrect insn:",insn);
1917 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1918 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1919 AS2 (ldd,%0,Y+63) CR_TAB
1920 AS2 (sbiw,r28,%o1-63));
1922 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1923 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1924 AS2 (ld,%0,Y) CR_TAB
1925 AS2 (subi,r28,lo8(%o1)) CR_TAB
1926 AS2 (sbci,r29,hi8(%o1)));
1928 else if (REGNO (XEXP (x,0)) == REG_X)
1930 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1931 it but I have this situation with extremal optimizing options. */
1932 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
1933 || reg_unused_after (insn, XEXP (x,0)))
1934 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1937 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1938 AS2 (ld,%0,X) CR_TAB
1939 AS2 (sbiw,r26,%o1));
1942 return AS2 (ldd,%0,%1);
1945 return AS2 (ld,%0,%1);
1949 out_movhi_r_mr (insn, op, l)
1952 int *l; /* instruction length */
1956 rtx base = XEXP (src, 0);
1957 int reg_dest = true_regnum (dest);
1958 int reg_base = true_regnum (base);
1966 if (reg_dest == reg_base) /* R = (R) */
1969 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1970 AS2 (ld,%B0,%1) CR_TAB
1971 AS2 (mov,%A0,__tmp_reg__));
1973 else if (reg_base == REG_X) /* (R26) */
1975 if (reg_unused_after (insn, base))
1978 return (AS2 (ld,%A0,X+) CR_TAB
1982 return (AS2 (ld,%A0,X+) CR_TAB
1983 AS2 (ld,%B0,X) CR_TAB
1989 return (AS2 (ld,%A0,%1) CR_TAB
1990 AS2 (ldd,%B0,%1+1));
1993 else if (GET_CODE (base) == PLUS) /* (R + i) */
1995 int disp = INTVAL (XEXP (base, 1));
1996 int reg_base = true_regnum (XEXP (base, 0));
1998 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2000 if (REGNO (XEXP (base, 0)) != REG_Y)
2001 fatal_insn ("incorrect insn:",insn);
2003 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2004 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
2005 AS2 (ldd,%A0,Y+62) CR_TAB
2006 AS2 (ldd,%B0,Y+63) CR_TAB
2007 AS2 (sbiw,r28,%o1-62));
2009 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2010 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2011 AS2 (ld,%A0,Y) CR_TAB
2012 AS2 (ldd,%B0,Y+1) CR_TAB
2013 AS2 (subi,r28,lo8(%o1)) CR_TAB
2014 AS2 (sbci,r29,hi8(%o1)));
2016 if (reg_base == REG_X)
2018 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
2019 it but I have this situation with extremal
2020 optimization options. */
2023 if (reg_base == reg_dest)
2024 return (AS2 (adiw,r26,%o1) CR_TAB
2025 AS2 (ld,__tmp_reg__,X+) CR_TAB
2026 AS2 (ld,%B0,X) CR_TAB
2027 AS2 (mov,%A0,__tmp_reg__));
2029 return (AS2 (adiw,r26,%o1) CR_TAB
2030 AS2 (ld,%A0,X+) CR_TAB
2031 AS2 (ld,%B0,X) CR_TAB
2032 AS2 (sbiw,r26,%o1+1));
2035 if (reg_base == reg_dest)
2038 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
2039 AS2 (ldd,%B0,%B1) CR_TAB
2040 AS2 (mov,%A0,__tmp_reg__));
2044 return (AS2 (ldd,%A0,%A1) CR_TAB
2047 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2049 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
2050 fatal_insn ("incorrect insn:", insn);
2053 return (AS2 (ld,%B0,%1) CR_TAB
2056 else if (GET_CODE (base) == POST_INC) /* (R++) */
2058 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
2059 fatal_insn ("incorrect insn:", insn);
2062 return (AS2 (ld,%A0,%1) CR_TAB
2065 else if (CONSTANT_ADDRESS_P (base))
2067 if (avr_io_address_p (base, 2))
2070 return (AS2 (in,%A0,%A1-0x20) CR_TAB
2071 AS2 (in,%B0,%B1-0x20));
2074 return (AS2 (lds,%A0,%A1) CR_TAB
2078 fatal_insn ("unknown move insn:",insn);
2083 out_movsi_r_mr (insn, op, l)
2086 int *l; /* instruction length */
2090 rtx base = XEXP (src, 0);
2091 int reg_dest = true_regnum (dest);
2092 int reg_base = true_regnum (base);
2100 if (reg_base == REG_X) /* (R26) */
2102 if (reg_dest == REG_X)
2103 /* "ld r26,-X" is undefined */
2104 return *l=7, (AS2 (adiw,r26,3) CR_TAB
2105 AS2 (ld,r29,X) CR_TAB
2106 AS2 (ld,r28,-X) CR_TAB
2107 AS2 (ld,__tmp_reg__,-X) CR_TAB
2108 AS2 (sbiw,r26,1) CR_TAB
2109 AS2 (ld,r26,X) CR_TAB
2110 AS2 (mov,r27,__tmp_reg__));
2111 else if (reg_dest == REG_X - 2)
2112 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2113 AS2 (ld,%B0,X+) CR_TAB
2114 AS2 (ld,__tmp_reg__,X+) CR_TAB
2115 AS2 (ld,%D0,X) CR_TAB
2116 AS2 (mov,%C0,__tmp_reg__));
2117 else if (reg_unused_after (insn, base))
2118 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
2119 AS2 (ld,%B0,X+) CR_TAB
2120 AS2 (ld,%C0,X+) CR_TAB
2123 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2124 AS2 (ld,%B0,X+) CR_TAB
2125 AS2 (ld,%C0,X+) CR_TAB
2126 AS2 (ld,%D0,X) CR_TAB
2131 if (reg_dest == reg_base)
2132 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2133 AS2 (ldd,%C0,%1+2) CR_TAB
2134 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2135 AS2 (ld,%A0,%1) CR_TAB
2136 AS2 (mov,%B0,__tmp_reg__));
2137 else if (reg_base == reg_dest + 2)
2138 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2139 AS2 (ldd,%B0,%1+1) CR_TAB
2140 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2141 AS2 (ldd,%D0,%1+3) CR_TAB
2142 AS2 (mov,%C0,__tmp_reg__));
2144 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2145 AS2 (ldd,%B0,%1+1) CR_TAB
2146 AS2 (ldd,%C0,%1+2) CR_TAB
2147 AS2 (ldd,%D0,%1+3));
2150 else if (GET_CODE (base) == PLUS) /* (R + i) */
2152 int disp = INTVAL (XEXP (base, 1));
2154 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2156 if (REGNO (XEXP (base, 0)) != REG_Y)
2157 fatal_insn ("incorrect insn:",insn);
2159 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2160 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2161 AS2 (ldd,%A0,Y+60) CR_TAB
2162 AS2 (ldd,%B0,Y+61) CR_TAB
2163 AS2 (ldd,%C0,Y+62) CR_TAB
2164 AS2 (ldd,%D0,Y+63) CR_TAB
2165 AS2 (sbiw,r28,%o1-60));
2167 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2168 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2169 AS2 (ld,%A0,Y) CR_TAB
2170 AS2 (ldd,%B0,Y+1) CR_TAB
2171 AS2 (ldd,%C0,Y+2) CR_TAB
2172 AS2 (ldd,%D0,Y+3) CR_TAB
2173 AS2 (subi,r28,lo8(%o1)) CR_TAB
2174 AS2 (sbci,r29,hi8(%o1)));
2177 reg_base = true_regnum (XEXP (base, 0));
2178 if (reg_base == REG_X)
2181 if (reg_dest == REG_X)
2184 /* "ld r26,-X" is undefined */
2185 return (AS2 (adiw,r26,%o1+3) CR_TAB
2186 AS2 (ld,r29,X) CR_TAB
2187 AS2 (ld,r28,-X) CR_TAB
2188 AS2 (ld,__tmp_reg__,-X) CR_TAB
2189 AS2 (sbiw,r26,1) CR_TAB
2190 AS2 (ld,r26,X) CR_TAB
2191 AS2 (mov,r27,__tmp_reg__));
2194 if (reg_dest == REG_X - 2)
2195 return (AS2 (adiw,r26,%o1) CR_TAB
2196 AS2 (ld,r24,X+) CR_TAB
2197 AS2 (ld,r25,X+) CR_TAB
2198 AS2 (ld,__tmp_reg__,X+) CR_TAB
2199 AS2 (ld,r27,X) CR_TAB
2200 AS2 (mov,r26,__tmp_reg__));
2202 return (AS2 (adiw,r26,%o1) CR_TAB
2203 AS2 (ld,%A0,X+) CR_TAB
2204 AS2 (ld,%B0,X+) CR_TAB
2205 AS2 (ld,%C0,X+) CR_TAB
2206 AS2 (ld,%D0,X) CR_TAB
2207 AS2 (sbiw,r26,%o1+3));
2209 if (reg_dest == reg_base)
2210 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2211 AS2 (ldd,%C0,%C1) CR_TAB
2212 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2213 AS2 (ldd,%A0,%A1) CR_TAB
2214 AS2 (mov,%B0,__tmp_reg__));
2215 else if (reg_dest == reg_base - 2)
2216 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2217 AS2 (ldd,%B0,%B1) CR_TAB
2218 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2219 AS2 (ldd,%D0,%D1) CR_TAB
2220 AS2 (mov,%C0,__tmp_reg__));
2221 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2222 AS2 (ldd,%B0,%B1) CR_TAB
2223 AS2 (ldd,%C0,%C1) CR_TAB
2226 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2227 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2228 AS2 (ld,%C0,%1) CR_TAB
2229 AS2 (ld,%B0,%1) CR_TAB
2231 else if (GET_CODE (base) == POST_INC) /* (R++) */
2232 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2233 AS2 (ld,%B0,%1) CR_TAB
2234 AS2 (ld,%C0,%1) CR_TAB
2236 else if (CONSTANT_ADDRESS_P (base))
2237 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2238 AS2 (lds,%B0,%B1) CR_TAB
2239 AS2 (lds,%C0,%C1) CR_TAB
2242 fatal_insn ("unknown move insn:",insn);
2247 out_movsi_mr_r (insn, op, l)
2254 rtx base = XEXP (dest, 0);
2255 int reg_base = true_regnum (base);
2256 int reg_src = true_regnum (src);
2262 if (CONSTANT_ADDRESS_P (base))
2263 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2264 AS2 (sts,%B0,%B1) CR_TAB
2265 AS2 (sts,%C0,%C1) CR_TAB
2267 if (reg_base > 0) /* (r) */
2269 if (reg_base == REG_X) /* (R26) */
2271 if (reg_src == REG_X)
2273 /* "st X+,r26" is undefined */
2274 if (reg_unused_after (insn, base))
2275 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2276 AS2 (st,X,r26) CR_TAB
2277 AS2 (adiw,r26,1) CR_TAB
2278 AS2 (st,X+,__tmp_reg__) CR_TAB
2279 AS2 (st,X+,r28) CR_TAB
2282 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2283 AS2 (st,X,r26) CR_TAB
2284 AS2 (adiw,r26,1) CR_TAB
2285 AS2 (st,X+,__tmp_reg__) CR_TAB
2286 AS2 (st,X+,r28) CR_TAB
2287 AS2 (st,X,r29) CR_TAB
2290 else if (reg_base == reg_src + 2)
2292 if (reg_unused_after (insn, base))
2293 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2294 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2295 AS2 (st,%0+,%A1) CR_TAB
2296 AS2 (st,%0+,%B1) CR_TAB
2297 AS2 (st,%0+,__zero_reg__) CR_TAB
2298 AS2 (st,%0,__tmp_reg__) CR_TAB
2299 AS1 (clr,__zero_reg__));
2301 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2302 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2303 AS2 (st,%0+,%A1) CR_TAB
2304 AS2 (st,%0+,%B1) CR_TAB
2305 AS2 (st,%0+,__zero_reg__) CR_TAB
2306 AS2 (st,%0,__tmp_reg__) CR_TAB
2307 AS1 (clr,__zero_reg__) CR_TAB
2310 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2311 AS2 (st,%0+,%B1) CR_TAB
2312 AS2 (st,%0+,%C1) CR_TAB
2313 AS2 (st,%0,%D1) CR_TAB
2317 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2318 AS2 (std,%0+1,%B1) CR_TAB
2319 AS2 (std,%0+2,%C1) CR_TAB
2320 AS2 (std,%0+3,%D1));
2322 else if (GET_CODE (base) == PLUS) /* (R + i) */
2324 int disp = INTVAL (XEXP (base, 1));
2325 reg_base = REGNO (XEXP (base, 0));
2326 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2328 if (reg_base != REG_Y)
2329 fatal_insn ("incorrect insn:",insn);
2331 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2332 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2333 AS2 (std,Y+60,%A1) CR_TAB
2334 AS2 (std,Y+61,%B1) CR_TAB
2335 AS2 (std,Y+62,%C1) CR_TAB
2336 AS2 (std,Y+63,%D1) CR_TAB
2337 AS2 (sbiw,r28,%o0-60));
2339 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2340 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2341 AS2 (st,Y,%A1) CR_TAB
2342 AS2 (std,Y+1,%B1) CR_TAB
2343 AS2 (std,Y+2,%C1) CR_TAB
2344 AS2 (std,Y+3,%D1) CR_TAB
2345 AS2 (subi,r28,lo8(%o0)) CR_TAB
2346 AS2 (sbci,r29,hi8(%o0)));
2348 if (reg_base == REG_X)
2351 if (reg_src == REG_X)
2354 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2355 AS2 (mov,__zero_reg__,r27) CR_TAB
2356 AS2 (adiw,r26,%o0) CR_TAB
2357 AS2 (st,X+,__tmp_reg__) CR_TAB
2358 AS2 (st,X+,__zero_reg__) CR_TAB
2359 AS2 (st,X+,r28) CR_TAB
2360 AS2 (st,X,r29) CR_TAB
2361 AS1 (clr,__zero_reg__) CR_TAB
2362 AS2 (sbiw,r26,%o0+3));
2364 else if (reg_src == REG_X - 2)
2367 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2368 AS2 (mov,__zero_reg__,r27) CR_TAB
2369 AS2 (adiw,r26,%o0) CR_TAB
2370 AS2 (st,X+,r24) CR_TAB
2371 AS2 (st,X+,r25) CR_TAB
2372 AS2 (st,X+,__tmp_reg__) CR_TAB
2373 AS2 (st,X,__zero_reg__) CR_TAB
2374 AS1 (clr,__zero_reg__) CR_TAB
2375 AS2 (sbiw,r26,%o0+3));
2378 return (AS2 (adiw,r26,%o0) CR_TAB
2379 AS2 (st,X+,%A1) CR_TAB
2380 AS2 (st,X+,%B1) CR_TAB
2381 AS2 (st,X+,%C1) CR_TAB
2382 AS2 (st,X,%D1) CR_TAB
2383 AS2 (sbiw,r26,%o0+3));
2385 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2386 AS2 (std,%B0,%B1) CR_TAB
2387 AS2 (std,%C0,%C1) CR_TAB
2390 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2391 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2392 AS2 (st,%0,%C1) CR_TAB
2393 AS2 (st,%0,%B1) CR_TAB
2395 else if (GET_CODE (base) == POST_INC) /* (R++) */
2396 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2397 AS2 (st,%0,%B1) CR_TAB
2398 AS2 (st,%0,%C1) CR_TAB
2400 fatal_insn ("unknown move insn:",insn);
2405 output_movsisf(insn, operands, l)
2411 rtx dest = operands[0];
2412 rtx src = operands[1];
2418 if (register_operand (dest, VOIDmode))
2420 if (register_operand (src, VOIDmode)) /* mov r,r */
2422 if (true_regnum (dest) > true_regnum (src))
2427 return (AS2 (movw,%C0,%C1) CR_TAB
2428 AS2 (movw,%A0,%A1));
2431 return (AS2 (mov,%D0,%D1) CR_TAB
2432 AS2 (mov,%C0,%C1) CR_TAB
2433 AS2 (mov,%B0,%B1) CR_TAB
2441 return (AS2 (movw,%A0,%A1) CR_TAB
2442 AS2 (movw,%C0,%C1));
2445 return (AS2 (mov,%A0,%A1) CR_TAB
2446 AS2 (mov,%B0,%B1) CR_TAB
2447 AS2 (mov,%C0,%C1) CR_TAB
2451 else if (CONSTANT_P (src))
2453 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2455 if (byte_immediate_operand (src, SImode)
2456 && reg_was_0 (insn, dest))
2459 return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0));
2463 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2464 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2465 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2466 AS2 (ldi,%D0,hhi8(%1)));
2469 if (GET_CODE (src) == CONST_INT)
2471 const char *const clr_op0 =
2472 AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
2473 AS1 (clr,%B0) CR_TAB
2475 : (AS1 (clr,%A0) CR_TAB
2476 AS1 (clr,%B0) CR_TAB
2477 AS1 (clr,%C0) CR_TAB
2480 if (src == const0_rtx) /* mov r,L */
2482 *l = AVR_ENHANCED ? 3 : 4;
2485 else if (src == const1_rtx)
2487 if (reg_was_0 (insn, dest))
2490 return AS1 (inc,%A0 ; reg_was_0);
2493 output_asm_insn (clr_op0, operands);
2494 *l = AVR_ENHANCED ? 4 : 5;
2495 return AS1 (inc,%A0);
2497 else if (src == constm1_rtx)
2499 /* Immediate constants -1 to any register */
2500 if (reg_was_0 (insn, dest))
2505 return (AS1 (dec,%A0) CR_TAB
2506 AS1 (dec,%B0) CR_TAB
2507 AS2 (movw,%C0,%A0));
2510 return (AS1 (dec,%D0 ; reg_was_0) CR_TAB
2511 AS1 (dec,%C0) CR_TAB
2512 AS1 (dec,%B0) CR_TAB
2518 return (AS1 (clr,%A0) CR_TAB
2519 AS1 (dec,%A0) CR_TAB
2520 AS2 (mov,%B0,%A0) CR_TAB
2521 AS2 (movw,%C0,%A0));
2524 return (AS1 (clr,%A0) CR_TAB
2525 AS1 (dec,%A0) CR_TAB
2526 AS2 (mov,%B0,%A0) CR_TAB
2527 AS2 (mov,%C0,%A0) CR_TAB
2532 int bit_nr = exact_log2 (INTVAL (src));
2536 if (reg_was_0 (insn, dest))
2540 output_asm_insn ("set ; reg_was_0", operands);
2544 *l = AVR_ENHANCED ? 5 : 6;
2547 output_asm_insn (clr_op0, operands);
2548 output_asm_insn ("set", operands);
2552 avr_output_bld (operands, bit_nr);
2559 /* Last resort, better than loading from memory. */
2561 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2562 AS2 (ldi,r31,lo8(%1)) CR_TAB
2563 AS2 (mov,%A0,r31) CR_TAB
2564 AS2 (ldi,r31,hi8(%1)) CR_TAB
2565 AS2 (mov,%B0,r31) CR_TAB
2566 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2567 AS2 (mov,%C0,r31) CR_TAB
2568 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2569 AS2 (mov,%D0,r31) CR_TAB
2570 AS2 (mov,r31,__tmp_reg__));
2572 else if (GET_CODE (src) == MEM)
2573 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2575 else if (GET_CODE (dest) == MEM)
2577 const char *template;
2579 if (src == const0_rtx)
2580 operands[1] = zero_reg_rtx;
2582 template = out_movsi_mr_r (insn, operands, real_l);
2585 output_asm_insn (template, operands);
2590 fatal_insn ("invalid insn:", insn);
2595 out_movqi_mr_r (insn, op, l)
2598 int *l; /* instruction length */
2602 rtx x = XEXP (dest, 0);
2608 if (CONSTANT_ADDRESS_P (x))
2610 if (avr_io_address_p (x, 1))
2613 return AS2 (out,%0-0x20,%1);
2616 return AS2 (sts,%0,%1);
2618 /* memory access by reg+disp */
2619 else if (GET_CODE (x) == PLUS
2620 && REG_P (XEXP (x,0))
2621 && GET_CODE (XEXP (x,1)) == CONST_INT)
2623 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
2625 int disp = INTVAL (XEXP (x,1));
2626 if (REGNO (XEXP (x,0)) != REG_Y)
2627 fatal_insn ("incorrect insn:",insn);
2629 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2630 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2631 AS2 (std,Y+63,%1) CR_TAB
2632 AS2 (sbiw,r28,%o0-63));
2634 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2635 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2636 AS2 (st,Y,%1) CR_TAB
2637 AS2 (subi,r28,lo8(%o0)) CR_TAB
2638 AS2 (sbci,r29,hi8(%o0)));
2640 else if (REGNO (XEXP (x,0)) == REG_X)
2642 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
2644 if (reg_unused_after (insn, XEXP (x,0)))
2645 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2646 AS2 (adiw,r26,%o0) CR_TAB
2647 AS2 (st,X,__tmp_reg__));
2649 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2650 AS2 (adiw,r26,%o0) CR_TAB
2651 AS2 (st,X,__tmp_reg__) CR_TAB
2652 AS2 (sbiw,r26,%o0));
2656 if (reg_unused_after (insn, XEXP (x,0)))
2657 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2660 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2661 AS2 (st,X,%1) CR_TAB
2662 AS2 (sbiw,r26,%o0));
2666 return AS2 (std,%0,%1);
2669 return AS2 (st,%0,%1);
2673 out_movhi_mr_r (insn, op, l)
2680 rtx base = XEXP (dest, 0);
2681 int reg_base = true_regnum (base);
2682 int reg_src = true_regnum (src);
2686 if (CONSTANT_ADDRESS_P (base))
2688 if (avr_io_address_p (base, 2))
2691 return (AS2 (out,%B0-0x20,%B1) CR_TAB
2692 AS2 (out,%A0-0x20,%A1));
2694 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2699 if (reg_base == REG_X)
2701 if (reg_src == REG_X)
2703 /* "st X+,r26" is undefined */
2704 if (reg_unused_after (insn, src))
2705 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2706 AS2 (st,X,r26) CR_TAB
2707 AS2 (adiw,r26,1) CR_TAB
2708 AS2 (st,X,__tmp_reg__));
2710 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2711 AS2 (st,X,r26) CR_TAB
2712 AS2 (adiw,r26,1) CR_TAB
2713 AS2 (st,X,__tmp_reg__) CR_TAB
2718 if (reg_unused_after (insn, base))
2719 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2722 return *l=3, (AS2 (st ,X+,%A1) CR_TAB
2723 AS2 (st ,X,%B1) CR_TAB
2728 return *l=2, (AS2 (st ,%0,%A1) CR_TAB
2729 AS2 (std,%0+1,%B1));
2731 else if (GET_CODE (base) == PLUS)
2733 int disp = INTVAL (XEXP (base, 1));
2734 reg_base = REGNO (XEXP (base, 0));
2735 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2737 if (reg_base != REG_Y)
2738 fatal_insn ("incorrect insn:",insn);
2740 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2741 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
2742 AS2 (std,Y+62,%A1) CR_TAB
2743 AS2 (std,Y+63,%B1) CR_TAB
2744 AS2 (sbiw,r28,%o0-62));
2746 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2747 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2748 AS2 (st,Y,%A1) CR_TAB
2749 AS2 (std,Y+1,%B1) CR_TAB
2750 AS2 (subi,r28,lo8(%o0)) CR_TAB
2751 AS2 (sbci,r29,hi8(%o0)));
2753 if (reg_base == REG_X)
2756 if (reg_src == REG_X)
2759 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2760 AS2 (mov,__zero_reg__,r27) CR_TAB
2761 AS2 (adiw,r26,%o0) CR_TAB
2762 AS2 (st,X+,__tmp_reg__) CR_TAB
2763 AS2 (st,X,__zero_reg__) CR_TAB
2764 AS1 (clr,__zero_reg__) CR_TAB
2765 AS2 (sbiw,r26,%o0+1));
2768 return (AS2 (adiw,r26,%o0) CR_TAB
2769 AS2 (st,X+,%A1) CR_TAB
2770 AS2 (st,X,%B1) CR_TAB
2771 AS2 (sbiw,r26,%o0+1));
2773 return *l=2, (AS2 (std,%A0,%A1) CR_TAB
2776 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2777 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2779 else if (GET_CODE (base) == POST_INC) /* (R++) */
2780 return *l=2, (AS2 (st,%0,%A1) CR_TAB
2782 fatal_insn ("unknown move insn:",insn);
2786 /* Return 1 if frame pointer for current function required */
2789 frame_pointer_required_p ()
2791 return (current_function_calls_alloca
2792 || current_function_args_info.nregs == 0
2793 || get_frame_size () > 0);
2796 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2799 compare_condition (insn)
2802 rtx next = next_real_insn (insn);
2803 RTX_CODE cond = UNKNOWN;
2804 if (next && GET_CODE (next) == JUMP_INSN)
2806 rtx pat = PATTERN (next);
2807 rtx src = SET_SRC (pat);
2808 rtx t = XEXP (src, 0);
2809 cond = GET_CODE (t);
2814 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2817 compare_sign_p (insn)
2820 RTX_CODE cond = compare_condition (insn);
2821 return (cond == GE || cond == LT);
2824 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2825 that needs to be swapped (GT, GTU, LE, LEU). */
2828 compare_diff_p (insn)
2831 RTX_CODE cond = compare_condition (insn);
2832 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2835 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2841 RTX_CODE cond = compare_condition (insn);
2842 return (cond == EQ || cond == NE);
2846 /* Output test instruction for HImode */
2853 if (compare_sign_p (insn))
2856 return AS1 (tst,%B0);
2858 if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2859 && compare_eq_p (insn))
2861 /* faster than sbiw if we can clobber the operand */
2863 return AS2 (or,%A0,%B0);
2865 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2868 return AS2 (sbiw,%0,0);
2871 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2872 AS2 (cpc,%B0,__zero_reg__));
2876 /* Output test instruction for SImode */
2883 if (compare_sign_p (insn))
2886 return AS1 (tst,%D0);
2888 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2891 return (AS2 (sbiw,%A0,0) CR_TAB
2892 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2893 AS2 (cpc,%D0,__zero_reg__));
2896 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2897 AS2 (cpc,%B0,__zero_reg__) CR_TAB
2898 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2899 AS2 (cpc,%D0,__zero_reg__));
2903 /* Generate asm equivalent for various shifts.
2904 Shift count is a CONST_INT, MEM or REG.
2905 This only handles cases that are not already
2906 carefully hand-optimized in ?sh??i3_out. */
2909 out_shift_with_cnt (template, insn, operands, len, t_len)
2910 const char *template;
2914 int t_len; /* Length of template. */
2918 int second_label = 1;
2919 int saved_in_tmp = 0;
2920 int use_zero_reg = 0;
2922 op[0] = operands[0];
2923 op[1] = operands[1];
2924 op[2] = operands[2];
2925 op[3] = operands[3];
2931 if (GET_CODE (operands[2]) == CONST_INT)
2933 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2934 int count = INTVAL (operands[2]);
2935 int max_len = 10; /* If larger than this, always use a loop. */
2937 if (count < 8 && !scratch)
2941 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2943 if (t_len * count <= max_len)
2945 /* Output shifts inline with no loop - faster. */
2947 *len = t_len * count;
2951 output_asm_insn (template, op);
2960 strcat (str, AS2 (ldi,%3,%2));
2962 else if (use_zero_reg)
2964 /* Hack to save one word: use __zero_reg__ as loop counter.
2965 Set one bit, then shift in a loop until it is 0 again. */
2967 op[3] = zero_reg_rtx;
2971 strcat (str, ("set" CR_TAB
2972 AS2 (bld,%3,%2-1)));
2976 /* No scratch register available, use one from LD_REGS (saved in
2977 __tmp_reg__) that doesn't overlap with registers to shift. */
2979 op[3] = gen_rtx (REG, QImode,
2980 ((true_regnum (operands[0]) - 1) & 15) + 16);
2981 op[4] = tmp_reg_rtx;
2985 *len = 3; /* Includes "mov %3,%4" after the loop. */
2987 strcat (str, (AS2 (mov,%4,%3) CR_TAB
2993 else if (GET_CODE (operands[2]) == MEM)
2997 op[3] = op_mov[0] = tmp_reg_rtx;
3001 out_movqi_r_mr (insn, op_mov, len);
3003 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
3005 else if (register_operand (operands[2], QImode))
3007 if (reg_unused_after (insn, operands[2]))
3011 op[3] = tmp_reg_rtx;
3013 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
3017 fatal_insn ("bad shift insn:", insn);
3024 strcat (str, AS1 (rjmp,2f));
3028 *len += t_len + 2; /* template + dec + brXX */
3031 strcat (str, "\n1:\t");
3032 strcat (str, template);
3033 strcat (str, second_label ? "\n2:\t" : "\n\t");
3034 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
3035 strcat (str, CR_TAB);
3036 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
3038 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
3039 output_asm_insn (str, op);
3044 /* 8bit shift left ((char)x << i) */
3047 ashlqi3_out (insn, operands, len)
3050 int *len; /* insn length (may be NULL) */
3052 if (GET_CODE (operands[2]) == CONST_INT)
3059 switch (INTVAL (operands[2]))
3063 return AS1 (clr,%0);
3067 return AS1 (lsl,%0);
3071 return (AS1 (lsl,%0) CR_TAB
3076 return (AS1 (lsl,%0) CR_TAB
3081 if (test_hard_reg_class (LD_REGS, operands[0]))
3084 return (AS1 (swap,%0) CR_TAB
3085 AS2 (andi,%0,0xf0));
3088 return (AS1 (lsl,%0) CR_TAB
3094 if (test_hard_reg_class (LD_REGS, operands[0]))
3097 return (AS1 (swap,%0) CR_TAB
3099 AS2 (andi,%0,0xe0));
3102 return (AS1 (lsl,%0) CR_TAB
3109 if (test_hard_reg_class (LD_REGS, operands[0]))
3112 return (AS1 (swap,%0) CR_TAB
3115 AS2 (andi,%0,0xc0));
3118 return (AS1 (lsl,%0) CR_TAB
3127 return (AS1 (ror,%0) CR_TAB
3132 else if (CONSTANT_P (operands[2]))
3133 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3135 out_shift_with_cnt (AS1 (lsl,%0),
3136 insn, operands, len, 1);
3141 /* 16bit shift left ((short)x << i) */
3144 ashlhi3_out (insn, operands, len)
3149 if (GET_CODE (operands[2]) == CONST_INT)
3151 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3152 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3159 switch (INTVAL (operands[2]))
3162 if (optimize_size && scratch)
3167 return (AS1 (swap,%A0) CR_TAB
3168 AS1 (swap,%B0) CR_TAB
3169 AS2 (andi,%B0,0xf0) CR_TAB
3170 AS2 (eor,%B0,%A0) CR_TAB
3171 AS2 (andi,%A0,0xf0) CR_TAB
3177 return (AS1 (swap,%A0) CR_TAB
3178 AS1 (swap,%B0) CR_TAB
3179 AS2 (ldi,%3,0xf0) CR_TAB
3180 AS2 (and,%B0,%3) CR_TAB
3181 AS2 (eor,%B0,%A0) CR_TAB
3182 AS2 (and,%A0,%3) CR_TAB
3185 break; /* optimize_size ? 6 : 8 */
3189 break; /* scratch ? 5 : 6 */
3193 return (AS1 (lsl,%A0) CR_TAB
3194 AS1 (rol,%B0) CR_TAB
3195 AS1 (swap,%A0) CR_TAB
3196 AS1 (swap,%B0) CR_TAB
3197 AS2 (andi,%B0,0xf0) CR_TAB
3198 AS2 (eor,%B0,%A0) CR_TAB
3199 AS2 (andi,%A0,0xf0) CR_TAB
3205 return (AS1 (lsl,%A0) CR_TAB
3206 AS1 (rol,%B0) CR_TAB
3207 AS1 (swap,%A0) CR_TAB
3208 AS1 (swap,%B0) CR_TAB
3209 AS2 (ldi,%3,0xf0) CR_TAB
3210 AS2 (and,%B0,%3) CR_TAB
3211 AS2 (eor,%B0,%A0) CR_TAB
3212 AS2 (and,%A0,%3) CR_TAB
3219 break; /* scratch ? 5 : 6 */
3221 return (AS1 (clr,__tmp_reg__) CR_TAB
3222 AS1 (lsr,%B0) CR_TAB
3223 AS1 (ror,%A0) CR_TAB
3224 AS1 (ror,__tmp_reg__) CR_TAB
3225 AS1 (lsr,%B0) CR_TAB
3226 AS1 (ror,%A0) CR_TAB
3227 AS1 (ror,__tmp_reg__) CR_TAB
3228 AS2 (mov,%B0,%A0) CR_TAB
3229 AS2 (mov,%A0,__tmp_reg__));
3233 return (AS1 (lsr,%B0) CR_TAB
3234 AS2 (mov,%B0,%A0) CR_TAB
3235 AS1 (clr,%A0) CR_TAB
3236 AS1 (ror,%B0) CR_TAB
3240 if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
3241 return *len = 1, AS1 (clr,%A0);
3243 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3248 return (AS2 (mov,%B0,%A0) CR_TAB
3249 AS1 (clr,%A0) CR_TAB
3254 return (AS2 (mov,%B0,%A0) CR_TAB
3255 AS1 (clr,%A0) CR_TAB
3256 AS1 (lsl,%B0) CR_TAB
3261 return (AS2 (mov,%B0,%A0) CR_TAB
3262 AS1 (clr,%A0) CR_TAB
3263 AS1 (lsl,%B0) CR_TAB
3264 AS1 (lsl,%B0) CR_TAB
3271 return (AS2 (mov,%B0,%A0) CR_TAB
3272 AS1 (clr,%A0) CR_TAB
3273 AS1 (swap,%B0) CR_TAB
3274 AS2 (andi,%B0,0xf0));
3279 return (AS2 (mov,%B0,%A0) CR_TAB
3280 AS1 (clr,%A0) CR_TAB
3281 AS1 (swap,%B0) CR_TAB
3282 AS2 (ldi,%3,0xf0) CR_TAB
3286 return (AS2 (mov,%B0,%A0) CR_TAB
3287 AS1 (clr,%A0) CR_TAB
3288 AS1 (lsl,%B0) CR_TAB
3289 AS1 (lsl,%B0) CR_TAB
3290 AS1 (lsl,%B0) CR_TAB
3297 return (AS2 (mov,%B0,%A0) CR_TAB
3298 AS1 (clr,%A0) CR_TAB
3299 AS1 (swap,%B0) CR_TAB
3300 AS1 (lsl,%B0) CR_TAB
3301 AS2 (andi,%B0,0xe0));
3303 if (AVR_ENHANCED && scratch)
3306 return (AS2 (ldi,%3,0x20) CR_TAB
3307 AS2 (mul,%A0,%3) CR_TAB
3308 AS2 (mov,%B0,r0) CR_TAB
3309 AS1 (clr,%A0) CR_TAB
3310 AS1 (clr,__zero_reg__));
3312 if (optimize_size && scratch)
3317 return (AS2 (mov,%B0,%A0) CR_TAB
3318 AS1 (clr,%A0) CR_TAB
3319 AS1 (swap,%B0) CR_TAB
3320 AS1 (lsl,%B0) CR_TAB
3321 AS2 (ldi,%3,0xe0) CR_TAB
3327 return ("set" CR_TAB
3328 AS2 (bld,r1,5) CR_TAB
3329 AS2 (mul,%A0,r1) CR_TAB
3330 AS2 (mov,%B0,r0) CR_TAB
3331 AS1 (clr,%A0) CR_TAB
3332 AS1 (clr,__zero_reg__));
3335 return (AS2 (mov,%B0,%A0) CR_TAB
3336 AS1 (clr,%A0) CR_TAB
3337 AS1 (lsl,%B0) CR_TAB
3338 AS1 (lsl,%B0) CR_TAB
3339 AS1 (lsl,%B0) CR_TAB
3340 AS1 (lsl,%B0) CR_TAB
3344 if (AVR_ENHANCED && ldi_ok)
3347 return (AS2 (ldi,%B0,0x40) CR_TAB
3348 AS2 (mul,%A0,%B0) CR_TAB
3349 AS2 (mov,%B0,r0) CR_TAB
3350 AS1 (clr,%A0) CR_TAB
3351 AS1 (clr,__zero_reg__));
3353 if (AVR_ENHANCED && scratch)
3356 return (AS2 (ldi,%3,0x40) CR_TAB
3357 AS2 (mul,%A0,%3) CR_TAB
3358 AS2 (mov,%B0,r0) CR_TAB
3359 AS1 (clr,%A0) CR_TAB
3360 AS1 (clr,__zero_reg__));
3362 if (optimize_size && ldi_ok)
3365 return (AS2 (mov,%B0,%A0) CR_TAB
3366 AS2 (ldi,%A0,6) "\n1:\t"
3367 AS1 (lsl,%B0) CR_TAB
3368 AS1 (dec,%A0) CR_TAB
3371 if (optimize_size && scratch)
3374 return (AS1 (clr,%B0) CR_TAB
3375 AS1 (lsr,%A0) CR_TAB
3376 AS1 (ror,%B0) CR_TAB
3377 AS1 (lsr,%A0) CR_TAB
3378 AS1 (ror,%B0) CR_TAB
3383 return (AS1 (clr,%B0) CR_TAB
3384 AS1 (lsr,%A0) CR_TAB
3385 AS1 (ror,%B0) CR_TAB
3390 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3392 insn, operands, len, 2);
3397 /* 32bit shift left ((long)x << i) */
3400 ashlsi3_out (insn, operands, len)
3405 if (GET_CODE (operands[2]) == CONST_INT)
3413 switch (INTVAL (operands[2]))
3417 int reg0 = true_regnum (operands[0]);
3418 int reg1 = true_regnum (operands[1]);
3421 return (AS2 (mov,%D0,%C1) CR_TAB
3422 AS2 (mov,%C0,%B1) CR_TAB
3423 AS2 (mov,%B0,%A1) CR_TAB
3425 else if (reg0 + 1 == reg1)
3428 return AS1 (clr,%A0);
3431 return (AS1 (clr,%A0) CR_TAB
3432 AS2 (mov,%B0,%A1) CR_TAB
3433 AS2 (mov,%C0,%B1) CR_TAB
3439 int reg0 = true_regnum (operands[0]);
3440 int reg1 = true_regnum (operands[1]);
3442 if (AVR_ENHANCED && (reg0 + 2 != reg1))
3445 return (AS2 (movw,%C0,%A1) CR_TAB
3446 AS1 (clr,%B0) CR_TAB
3449 if (reg0 + 1 >= reg1)
3450 return (AS2 (mov,%D0,%B1) CR_TAB
3451 AS2 (mov,%C0,%A1) CR_TAB
3452 AS1 (clr,%B0) CR_TAB
3454 if (reg0 + 2 == reg1)
3457 return (AS1 (clr,%B0) CR_TAB
3461 return (AS2 (mov,%C0,%A1) CR_TAB
3462 AS2 (mov,%D0,%B1) CR_TAB
3463 AS1 (clr,%B0) CR_TAB
3469 if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
3470 return (AS2 (mov,%D0,%A1) CR_TAB
3471 AS1 (clr,%C0) CR_TAB
3472 AS1 (clr,%B0) CR_TAB
3477 return (AS1 (clr,%C0) CR_TAB
3478 AS1 (clr,%B0) CR_TAB
3484 return (AS1 (clr,%D0) CR_TAB
3485 AS1 (lsr,%A0) CR_TAB
3486 AS1 (ror,%D0) CR_TAB
3487 AS1 (clr,%C0) CR_TAB
3488 AS1 (clr,%B0) CR_TAB
3493 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3494 AS1 (rol,%B0) CR_TAB
3495 AS1 (rol,%C0) CR_TAB
3497 insn, operands, len, 4);
3501 /* 8bit arithmetic shift right ((signed char)x >> i) */
3504 ashrqi3_out (insn, operands, len)
3507 int *len; /* insn length */
3509 if (GET_CODE (operands[2]) == CONST_INT)
3516 switch (INTVAL (operands[2]))
3520 return AS1 (asr,%0);
3524 return (AS1 (asr,%0) CR_TAB
3529 return (AS1 (asr,%0) CR_TAB
3535 return (AS1 (asr,%0) CR_TAB
3542 return (AS1 (asr,%0) CR_TAB
3550 return (AS2 (bst,%0,6) CR_TAB
3552 AS2 (sbc,%0,%0) CR_TAB
3558 return (AS1 (lsl,%0) CR_TAB
3562 else if (CONSTANT_P (operands[2]))
3563 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3565 out_shift_with_cnt (AS1 (asr,%0),
3566 insn, operands, len, 1);
3571 /* 16bit arithmetic shift right ((signed short)x >> i) */
3574 ashrhi3_out (insn, operands, len)
3579 if (GET_CODE (operands[2]) == CONST_INT)
3581 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3582 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3589 switch (INTVAL (operands[2]))
3593 /* XXX try to optimize this too? */
3598 break; /* scratch ? 5 : 6 */
3600 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3601 AS2 (mov,%A0,%B0) CR_TAB
3602 AS1 (lsl,__tmp_reg__) CR_TAB
3603 AS1 (rol,%A0) CR_TAB
3604 AS2 (sbc,%B0,%B0) CR_TAB
3605 AS1 (lsl,__tmp_reg__) CR_TAB
3606 AS1 (rol,%A0) CR_TAB
3611 return (AS1 (lsl,%A0) CR_TAB
3612 AS2 (mov,%A0,%B0) CR_TAB
3613 AS1 (rol,%A0) CR_TAB
3618 int reg0 = true_regnum (operands[0]);
3619 int reg1 = true_regnum (operands[1]);
3622 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3623 AS1 (lsl,%B0) CR_TAB
3625 else if (reg0 == reg1 + 1)
3626 return *len = 3, (AS1 (clr,%B0) CR_TAB
3627 AS2 (sbrc,%A0,7) CR_TAB
3630 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3631 AS1 (clr,%B0) CR_TAB
3632 AS2 (sbrc,%A0,7) CR_TAB
3638 return (AS2 (mov,%A0,%B0) CR_TAB
3639 AS1 (lsl,%B0) CR_TAB
3640 AS2 (sbc,%B0,%B0) CR_TAB
3645 return (AS2 (mov,%A0,%B0) CR_TAB
3646 AS1 (lsl,%B0) CR_TAB
3647 AS2 (sbc,%B0,%B0) CR_TAB
3648 AS1 (asr,%A0) CR_TAB
3652 if (AVR_ENHANCED && ldi_ok)
3655 return (AS2 (ldi,%A0,0x20) CR_TAB
3656 AS2 (muls,%B0,%A0) CR_TAB
3657 AS2 (mov,%A0,r1) CR_TAB
3658 AS2 (sbc,%B0,%B0) CR_TAB
3659 AS1 (clr,__zero_reg__));
3661 if (optimize_size && scratch)
3664 return (AS2 (mov,%A0,%B0) CR_TAB
3665 AS1 (lsl,%B0) CR_TAB
3666 AS2 (sbc,%B0,%B0) CR_TAB
3667 AS1 (asr,%A0) CR_TAB
3668 AS1 (asr,%A0) CR_TAB
3672 if (AVR_ENHANCED && ldi_ok)
3675 return (AS2 (ldi,%A0,0x10) CR_TAB
3676 AS2 (muls,%B0,%A0) CR_TAB
3677 AS2 (mov,%A0,r1) CR_TAB
3678 AS2 (sbc,%B0,%B0) CR_TAB
3679 AS1 (clr,__zero_reg__));
3681 if (optimize_size && scratch)
3684 return (AS2 (mov,%A0,%B0) CR_TAB
3685 AS1 (lsl,%B0) CR_TAB
3686 AS2 (sbc,%B0,%B0) CR_TAB
3687 AS1 (asr,%A0) CR_TAB
3688 AS1 (asr,%A0) CR_TAB
3689 AS1 (asr,%A0) CR_TAB
3693 if (AVR_ENHANCED && ldi_ok)
3696 return (AS2 (ldi,%A0,0x08) CR_TAB
3697 AS2 (muls,%B0,%A0) CR_TAB
3698 AS2 (mov,%A0,r1) CR_TAB
3699 AS2 (sbc,%B0,%B0) CR_TAB
3700 AS1 (clr,__zero_reg__));
3703 break; /* scratch ? 5 : 7 */
3705 return (AS2 (mov,%A0,%B0) CR_TAB
3706 AS1 (lsl,%B0) CR_TAB
3707 AS2 (sbc,%B0,%B0) CR_TAB
3708 AS1 (asr,%A0) CR_TAB
3709 AS1 (asr,%A0) CR_TAB
3710 AS1 (asr,%A0) CR_TAB
3711 AS1 (asr,%A0) CR_TAB
3716 return (AS1 (lsl,%B0) CR_TAB
3717 AS2 (sbc,%A0,%A0) CR_TAB
3718 AS1 (lsl,%B0) CR_TAB
3719 AS2 (mov,%B0,%A0) CR_TAB
3723 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3724 AS2 (sbc,%A0,%A0) CR_TAB
3729 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3731 insn, operands, len, 2);
3736 /* 32bit arithmetic shift right ((signed long)x >> i) */
3739 ashrsi3_out (insn, operands, len)
3744 if (GET_CODE (operands[2]) == CONST_INT)
3752 switch (INTVAL (operands[2]))
3756 int reg0 = true_regnum (operands[0]);
3757 int reg1 = true_regnum (operands[1]);
3760 return (AS2 (mov,%A0,%B1) CR_TAB
3761 AS2 (mov,%B0,%C1) CR_TAB
3762 AS2 (mov,%C0,%D1) CR_TAB
3763 AS1 (clr,%D0) CR_TAB
3764 AS2 (sbrc,%C0,7) CR_TAB
3766 else if (reg0 == reg1 + 1)
3769 return (AS1 (clr,%D0) CR_TAB
3770 AS2 (sbrc,%C0,7) CR_TAB
3774 return (AS1 (clr,%D0) CR_TAB
3775 AS2 (sbrc,%D1,7) CR_TAB
3776 AS1 (dec,%D0) CR_TAB
3777 AS2 (mov,%C0,%D1) CR_TAB
3778 AS2 (mov,%B0,%C1) CR_TAB
3784 int reg0 = true_regnum (operands[0]);
3785 int reg1 = true_regnum (operands[1]);
3787 if (AVR_ENHANCED && (reg0 != reg1 + 2))
3790 return (AS2 (movw,%A0,%C1) CR_TAB
3791 AS1 (clr,%D0) CR_TAB
3792 AS2 (sbrc,%B0,7) CR_TAB
3793 AS1 (com,%D0) CR_TAB
3796 if (reg0 <= reg1 + 1)
3797 return (AS2 (mov,%A0,%C1) CR_TAB
3798 AS2 (mov,%B0,%D1) CR_TAB
3799 AS1 (clr,%D0) CR_TAB
3800 AS2 (sbrc,%B0,7) CR_TAB
3801 AS1 (com,%D0) CR_TAB
3803 else if (reg0 == reg1 + 2)
3804 return *len = 4, (AS1 (clr,%D0) CR_TAB
3805 AS2 (sbrc,%B0,7) CR_TAB
3806 AS1 (com,%D0) CR_TAB
3809 return (AS2 (mov,%B0,%D1) CR_TAB
3810 AS2 (mov,%A0,%C1) CR_TAB
3811 AS1 (clr,%D0) CR_TAB
3812 AS2 (sbrc,%B0,7) CR_TAB
3813 AS1 (com,%D0) CR_TAB
3818 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
3819 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3820 AS1 (clr,%D0) CR_TAB
3821 AS2 (sbrc,%A0,7) CR_TAB
3822 AS1 (com,%D0) CR_TAB
3823 AS2 (mov,%B0,%D0) CR_TAB
3826 return *len = 5, (AS1 (clr,%D0) CR_TAB
3827 AS2 (sbrc,%A0,7) CR_TAB
3828 AS1 (com,%D0) CR_TAB
3829 AS2 (mov,%B0,%D0) CR_TAB
3834 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3835 AS2 (sbc,%A0,%A0) CR_TAB
3836 AS2 (mov,%B0,%A0) CR_TAB
3837 AS2 (movw,%C0,%A0));
3839 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3840 AS2 (sbc,%A0,%A0) CR_TAB
3841 AS2 (mov,%B0,%A0) CR_TAB
3842 AS2 (mov,%C0,%A0) CR_TAB
3847 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3848 AS1 (ror,%C0) CR_TAB
3849 AS1 (ror,%B0) CR_TAB
3851 insn, operands, len, 4);
3855 /* 8bit logic shift right ((unsigned char)x >> i) */
3858 lshrqi3_out (insn, operands, len)
3863 if (GET_CODE (operands[2]) == CONST_INT)
3870 switch (INTVAL (operands[2]))
3874 return AS1 (clr,%0);
3878 return AS1 (lsr,%0);
3882 return (AS1 (lsr,%0) CR_TAB
3886 return (AS1 (lsr,%0) CR_TAB
3891 if (test_hard_reg_class (LD_REGS, operands[0]))
3894 return (AS1 (swap,%0) CR_TAB
3895 AS2 (andi,%0,0x0f));
3898 return (AS1 (lsr,%0) CR_TAB
3904 if (test_hard_reg_class (LD_REGS, operands[0]))
3907 return (AS1 (swap,%0) CR_TAB
3912 return (AS1 (lsr,%0) CR_TAB
3919 if (test_hard_reg_class (LD_REGS, operands[0]))
3922 return (AS1 (swap,%0) CR_TAB
3928 return (AS1 (lsr,%0) CR_TAB
3937 return (AS1 (rol,%0) CR_TAB
3942 else if (CONSTANT_P (operands[2]))
3943 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3945 out_shift_with_cnt (AS1 (lsr,%0),
3946 insn, operands, len, 1);
3950 /* 16bit logic shift right ((unsigned short)x >> i) */
3953 lshrhi3_out (insn, operands, len)
3958 if (GET_CODE (operands[2]) == CONST_INT)
3960 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3961 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3968 switch (INTVAL (operands[2]))
3971 if (optimize_size && scratch)
3976 return (AS1 (swap,%B0) CR_TAB
3977 AS1 (swap,%A0) CR_TAB
3978 AS2 (andi,%A0,0x0f) CR_TAB
3979 AS2 (eor,%A0,%B0) CR_TAB
3980 AS2 (andi,%B0,0x0f) CR_TAB
3986 return (AS1 (swap,%B0) CR_TAB
3987 AS1 (swap,%A0) CR_TAB
3988 AS2 (ldi,%3,0x0f) CR_TAB
3989 AS2 (and,%A0,%3) CR_TAB
3990 AS2 (eor,%A0,%B0) CR_TAB
3991 AS2 (and,%B0,%3) CR_TAB
3994 break; /* optimize_size ? 6 : 8 */
3998 break; /* scratch ? 5 : 6 */
4002 return (AS1 (lsr,%B0) CR_TAB
4003 AS1 (ror,%A0) CR_TAB
4004 AS1 (swap,%B0) CR_TAB
4005 AS1 (swap,%A0) CR_TAB
4006 AS2 (andi,%A0,0x0f) CR_TAB
4007 AS2 (eor,%A0,%B0) CR_TAB
4008 AS2 (andi,%B0,0x0f) CR_TAB
4014 return (AS1 (lsr,%B0) CR_TAB
4015 AS1 (ror,%A0) CR_TAB
4016 AS1 (swap,%B0) CR_TAB
4017 AS1 (swap,%A0) CR_TAB
4018 AS2 (ldi,%3,0x0f) CR_TAB
4019 AS2 (and,%A0,%3) CR_TAB
4020 AS2 (eor,%A0,%B0) CR_TAB
4021 AS2 (and,%B0,%3) CR_TAB
4028 break; /* scratch ? 5 : 6 */
4030 return (AS1 (clr,__tmp_reg__) CR_TAB
4031 AS1 (lsl,%A0) CR_TAB
4032 AS1 (rol,%B0) CR_TAB
4033 AS1 (rol,__tmp_reg__) CR_TAB
4034 AS1 (lsl,%A0) CR_TAB
4035 AS1 (rol,%B0) CR_TAB
4036 AS1 (rol,__tmp_reg__) CR_TAB
4037 AS2 (mov,%A0,%B0) CR_TAB
4038 AS2 (mov,%B0,__tmp_reg__));
4042 return (AS1 (lsl,%A0) CR_TAB
4043 AS2 (mov,%A0,%B0) CR_TAB
4044 AS1 (rol,%A0) CR_TAB
4045 AS2 (sbc,%B0,%B0) CR_TAB
4049 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
4050 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
4053 return *len = 1, AS1 (clr,%B0);
4057 return (AS2 (mov,%A0,%B0) CR_TAB
4058 AS1 (clr,%B0) CR_TAB
4063 return (AS2 (mov,%A0,%B0) CR_TAB
4064 AS1 (clr,%B0) CR_TAB
4065 AS1 (lsr,%A0) CR_TAB
4070 return (AS2 (mov,%A0,%B0) CR_TAB
4071 AS1 (clr,%B0) CR_TAB
4072 AS1 (lsr,%A0) CR_TAB
4073 AS1 (lsr,%A0) CR_TAB
4080 return (AS2 (mov,%A0,%B0) CR_TAB
4081 AS1 (clr,%B0) CR_TAB
4082 AS1 (swap,%A0) CR_TAB
4083 AS2 (andi,%A0,0x0f));
4088 return (AS2 (mov,%A0,%B0) CR_TAB
4089 AS1 (clr,%B0) CR_TAB
4090 AS1 (swap,%A0) CR_TAB
4091 AS2 (ldi,%3,0x0f) CR_TAB
4095 return (AS2 (mov,%A0,%B0) CR_TAB
4096 AS1 (clr,%B0) CR_TAB
4097 AS1 (lsr,%A0) CR_TAB
4098 AS1 (lsr,%A0) CR_TAB
4099 AS1 (lsr,%A0) CR_TAB
4106 return (AS2 (mov,%A0,%B0) CR_TAB
4107 AS1 (clr,%B0) CR_TAB
4108 AS1 (swap,%A0) CR_TAB
4109 AS1 (lsr,%A0) CR_TAB
4110 AS2 (andi,%A0,0x07));
4112 if (AVR_ENHANCED && scratch)
4115 return (AS2 (ldi,%3,0x08) CR_TAB
4116 AS2 (mul,%B0,%3) CR_TAB
4117 AS2 (mov,%A0,r1) CR_TAB
4118 AS1 (clr,%B0) CR_TAB
4119 AS1 (clr,__zero_reg__));
4121 if (optimize_size && scratch)
4126 return (AS2 (mov,%A0,%B0) CR_TAB
4127 AS1 (clr,%B0) CR_TAB
4128 AS1 (swap,%A0) CR_TAB
4129 AS1 (lsr,%A0) CR_TAB
4130 AS2 (ldi,%3,0x07) CR_TAB
4136 return ("set" CR_TAB
4137 AS2 (bld,r1,3) CR_TAB
4138 AS2 (mul,%B0,r1) CR_TAB
4139 AS2 (mov,%A0,r1) CR_TAB
4140 AS1 (clr,%B0) CR_TAB
4141 AS1 (clr,__zero_reg__));
4144 return (AS2 (mov,%A0,%B0) CR_TAB
4145 AS1 (clr,%B0) CR_TAB
4146 AS1 (lsr,%A0) CR_TAB
4147 AS1 (lsr,%A0) CR_TAB
4148 AS1 (lsr,%A0) CR_TAB
4149 AS1 (lsr,%A0) CR_TAB
4153 if (AVR_ENHANCED && ldi_ok)
4156 return (AS2 (ldi,%A0,0x04) CR_TAB
4157 AS2 (mul,%B0,%A0) CR_TAB
4158 AS2 (mov,%A0,r1) CR_TAB
4159 AS1 (clr,%B0) CR_TAB
4160 AS1 (clr,__zero_reg__));
4162 if (AVR_ENHANCED && scratch)
4165 return (AS2 (ldi,%3,0x04) CR_TAB
4166 AS2 (mul,%B0,%3) CR_TAB
4167 AS2 (mov,%A0,r1) CR_TAB
4168 AS1 (clr,%B0) CR_TAB
4169 AS1 (clr,__zero_reg__));
4171 if (optimize_size && ldi_ok)
4174 return (AS2 (mov,%A0,%B0) CR_TAB
4175 AS2 (ldi,%B0,6) "\n1:\t"
4176 AS1 (lsr,%A0) CR_TAB
4177 AS1 (dec,%B0) CR_TAB
4180 if (optimize_size && scratch)
4183 return (AS1 (clr,%A0) CR_TAB
4184 AS1 (lsl,%B0) CR_TAB
4185 AS1 (rol,%A0) CR_TAB
4186 AS1 (lsl,%B0) CR_TAB
4187 AS1 (rol,%A0) CR_TAB
4192 return (AS1 (clr,%A0) CR_TAB
4193 AS1 (lsl,%B0) CR_TAB
4194 AS1 (rol,%A0) CR_TAB
4199 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4201 insn, operands, len, 2);
4205 /* 32bit logic shift right ((unsigned int)x >> i) */
4208 lshrsi3_out (insn, operands, len)
4213 if (GET_CODE (operands[2]) == CONST_INT)
4221 switch (INTVAL (operands[2]))
4225 int reg0 = true_regnum (operands[0]);
4226 int reg1 = true_regnum (operands[1]);
4229 return (AS2 (mov,%A0,%B1) CR_TAB
4230 AS2 (mov,%B0,%C1) CR_TAB
4231 AS2 (mov,%C0,%D1) CR_TAB
4233 else if (reg0 == reg1 + 1)
4234 return *len = 1, AS1 (clr,%D0);
4236 return (AS1 (clr,%D0) CR_TAB
4237 AS2 (mov,%C0,%D1) CR_TAB
4238 AS2 (mov,%B0,%C1) CR_TAB
4244 int reg0 = true_regnum (operands[0]);
4245 int reg1 = true_regnum (operands[1]);
4247 if (AVR_ENHANCED && (reg0 != reg1 + 2))
4250 return (AS2 (movw,%A0,%C1) CR_TAB
4251 AS1 (clr,%C0) CR_TAB
4254 if (reg0 <= reg1 + 1)
4255 return (AS2 (mov,%A0,%C1) CR_TAB
4256 AS2 (mov,%B0,%D1) CR_TAB
4257 AS1 (clr,%C0) CR_TAB
4259 else if (reg0 == reg1 + 2)
4260 return *len = 2, (AS1 (clr,%C0) CR_TAB
4263 return (AS2 (mov,%B0,%D1) CR_TAB
4264 AS2 (mov,%A0,%C1) CR_TAB
4265 AS1 (clr,%C0) CR_TAB
4270 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
4271 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4272 AS1 (clr,%B0) CR_TAB
4273 AS1 (clr,%C0) CR_TAB
4276 return *len = 3, (AS1 (clr,%B0) CR_TAB
4277 AS1 (clr,%C0) CR_TAB
4282 return (AS1 (clr,%A0) CR_TAB
4283 AS2 (sbrc,%D0,7) CR_TAB
4284 AS1 (inc,%A0) CR_TAB
4285 AS1 (clr,%B0) CR_TAB
4286 AS1 (clr,%C0) CR_TAB
4291 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4292 AS1 (ror,%C0) CR_TAB
4293 AS1 (ror,%B0) CR_TAB
4295 insn, operands, len, 4);
4299 /* Modifies the length assigned to instruction INSN
4300 LEN is the initially computed length of the insn. */
4303 adjust_insn_length (insn, len)
4307 rtx patt = PATTERN (insn);
4310 if (GET_CODE (patt) == SET)
4313 op[1] = SET_SRC (patt);
4314 op[0] = SET_DEST (patt);
4315 if (general_operand (op[1], VOIDmode)
4316 && general_operand (op[0], VOIDmode))
4318 switch (GET_MODE (op[0]))
4321 output_movqi (insn, op, &len);
4324 output_movhi (insn, op, &len);
4328 output_movsisf (insn, op, &len);
4334 else if (op[0] == cc0_rtx && REG_P (op[1]))
4336 switch (GET_MODE (op[1]))
4338 case HImode: out_tsthi (insn,&len); break;
4339 case SImode: out_tstsi (insn,&len); break;
4343 else if (GET_CODE (op[1]) == AND)
4345 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4347 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4348 if (GET_MODE (op[1]) == SImode)
4349 len = (((mask & 0xff) != 0xff)
4350 + ((mask & 0xff00) != 0xff00)
4351 + ((mask & 0xff0000L) != 0xff0000L)
4352 + ((mask & 0xff000000L) != 0xff000000L));
4353 else if (GET_MODE (op[1]) == HImode)
4354 len = (((mask & 0xff) != 0xff)
4355 + ((mask & 0xff00) != 0xff00));
4358 else if (GET_CODE (op[1]) == IOR)
4360 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4362 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4363 if (GET_MODE (op[1]) == SImode)
4364 len = (((mask & 0xff) != 0)
4365 + ((mask & 0xff00) != 0)
4366 + ((mask & 0xff0000L) != 0)
4367 + ((mask & 0xff000000L) != 0));
4368 else if (GET_MODE (op[1]) == HImode)
4369 len = (((mask & 0xff) != 0)
4370 + ((mask & 0xff00) != 0));
4374 set = single_set (insn);
4379 op[1] = SET_SRC (set);
4380 op[0] = SET_DEST (set);
4382 if (GET_CODE (patt) == PARALLEL
4383 && general_operand (op[1], VOIDmode)
4384 && general_operand (op[0], VOIDmode))
4386 if (XVECLEN (patt, 0) == 2)
4387 op[2] = XVECEXP (patt, 0, 1);
4389 switch (GET_MODE (op[0]))
4395 output_reload_inhi (insn, op, &len);
4399 output_reload_insisf (insn, op, &len);
4405 else if (GET_CODE (op[1]) == ASHIFT
4406 || GET_CODE (op[1]) == ASHIFTRT
4407 || GET_CODE (op[1]) == LSHIFTRT)
4411 ops[1] = XEXP (op[1],0);
4412 ops[2] = XEXP (op[1],1);
4413 switch (GET_CODE (op[1]))
4416 switch (GET_MODE (op[0]))
4418 case QImode: ashlqi3_out (insn,ops,&len); break;
4419 case HImode: ashlhi3_out (insn,ops,&len); break;
4420 case SImode: ashlsi3_out (insn,ops,&len); break;
4425 switch (GET_MODE (op[0]))
4427 case QImode: ashrqi3_out (insn,ops,&len); break;
4428 case HImode: ashrhi3_out (insn,ops,&len); break;
4429 case SImode: ashrsi3_out (insn,ops,&len); break;
4434 switch (GET_MODE (op[0]))
4436 case QImode: lshrqi3_out (insn,ops,&len); break;
4437 case HImode: lshrhi3_out (insn,ops,&len); break;
4438 case SImode: lshrsi3_out (insn,ops,&len); break;
4450 /* Return nonzero if register REG dead after INSN */
4453 reg_unused_after (insn, reg)
4457 return (dead_or_set_p (insn, reg)
4458 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4461 /* Return nonzero if REG is not used after INSN.
4462 We assume REG is a reload reg, and therefore does
4463 not live past labels. It may live past calls or jumps though. */
4466 _reg_unused_after (insn, reg)
4473 /* If the reg is set by this instruction, then it is safe for our
4474 case. Disregard the case where this is a store to memory, since
4475 we are checking a register used in the store address. */
4476 set = single_set (insn);
4477 if (set && GET_CODE (SET_DEST (set)) != MEM
4478 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4481 while ((insn = NEXT_INSN (insn)))
4483 code = GET_CODE (insn);
4486 /* If this is a label that existed before reload, then the register
4487 if dead here. However, if this is a label added by reorg, then
4488 the register may still be live here. We can't tell the difference,
4489 so we just ignore labels completely. */
4490 if (code == CODE_LABEL)
4495 if (code == JUMP_INSN)
4498 /* If this is a sequence, we must handle them all at once.
4499 We could have for instance a call that sets the target register,
4500 and an insn in a delay slot that uses the register. In this case,
4501 we must return 0. */
4502 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4507 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4509 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4510 rtx set = single_set (this_insn);
4512 if (GET_CODE (this_insn) == CALL_INSN)
4514 else if (GET_CODE (this_insn) == JUMP_INSN)
4516 if (INSN_ANNULLED_BRANCH_P (this_insn))
4521 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4523 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4525 if (GET_CODE (SET_DEST (set)) != MEM)
4531 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4536 else if (code == JUMP_INSN)
4540 if (code == CALL_INSN)
4543 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4544 if (GET_CODE (XEXP (tem, 0)) == USE
4545 && REG_P (XEXP (XEXP (tem, 0), 0))
4546 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4548 if (call_used_regs[REGNO (reg)])
4552 if (GET_RTX_CLASS (code) == 'i')
4554 rtx set = single_set (insn);
4556 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4558 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4559 return GET_CODE (SET_DEST (set)) != MEM;
4560 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4567 /* Target hook for assembling integer objects. The AVR version needs
4568 special handling for references to certain labels. */
4571 avr_assemble_integer (x, size, aligned_p)
4576 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
4577 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
4578 || GET_CODE (x) == LABEL_REF))
4580 fputs ("\t.word\tpm(", asm_out_file);
4581 output_addr_const (asm_out_file, x);
4582 fputs (")\n", asm_out_file);
4585 return default_assemble_integer (x, size, aligned_p);
4588 /* Sets section name for declaration DECL */
4591 avr_unique_section (decl, reloc)
4593 int reloc ATTRIBUTE_UNUSED;
4596 const char *name, *prefix;
4599 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
4600 name = (* targetm.strip_name_encoding) (name);
4602 if (TREE_CODE (decl) == FUNCTION_DECL)
4604 if (flag_function_sections)
4612 if (flag_function_sections)
4614 len = strlen (name) + strlen (prefix);
4615 string = alloca (len + 1);
4616 sprintf (string, "%s%s", prefix, name);
4617 DECL_SECTION_NAME (decl) = build_string (len, string);
4622 /* The routine used to output NUL terminated strings. We use a special
4623 version of this for most svr4 targets because doing so makes the
4624 generated assembly code more compact (and thus faster to assemble)
4625 as well as more readable, especially for targets like the i386
4626 (where the only alternative is to output character sequences as
4627 comma separated lists of numbers). */
4630 gas_output_limited_string(file, str)
4634 const unsigned char *_limited_str = (unsigned char *) str;
4636 fprintf (file, "%s\"", STRING_ASM_OP);
4637 for (; (ch = *_limited_str); _limited_str++)
4640 switch (escape = ESCAPES[ch])
4646 fprintf (file, "\\%03o", ch);
4650 putc (escape, file);
4654 fprintf (file, "\"\n");
4657 /* The routine used to output sequences of byte values. We use a special
4658 version of this for most svr4 targets because doing so makes the
4659 generated assembly code more compact (and thus faster to assemble)
4660 as well as more readable. Note that if we find subparts of the
4661 character sequence which end with NUL (and which are shorter than
4662 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4665 gas_output_ascii(file, str, length)
4670 const unsigned char *_ascii_bytes = (const unsigned char *) str;
4671 const unsigned char *limit = _ascii_bytes + length;
4672 unsigned bytes_in_chunk = 0;
4673 for (; _ascii_bytes < limit; _ascii_bytes++)
4675 const unsigned char *p;
4676 if (bytes_in_chunk >= 60)
4678 fprintf (file, "\"\n");
4681 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4683 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4685 if (bytes_in_chunk > 0)
4687 fprintf (file, "\"\n");
4690 gas_output_limited_string (file, (char*)_ascii_bytes);
4697 if (bytes_in_chunk == 0)
4698 fprintf (file, "\t.ascii\t\"");
4699 switch (escape = ESCAPES[ch = *_ascii_bytes])
4706 fprintf (file, "\\%03o", ch);
4707 bytes_in_chunk += 4;
4711 putc (escape, file);
4712 bytes_in_chunk += 2;
4717 if (bytes_in_chunk > 0)
4718 fprintf (file, "\"\n");
4721 /* Return value is nonzero if pseudos that have been
4722 assigned to registers of class CLASS would likely be spilled
4723 because registers of CLASS are needed for spill registers. */
4726 class_likely_spilled_p (c)
4729 return (c != ALL_REGS && c != ADDW_REGS);
4732 /* Valid attributes:
4733 progmem - put data to program memory;
4734 signal - make a function to be hardware interrupt. After function
4735 prologue interrupts are disabled;
4736 interrupt - make a function to be hardware interrupt. After function
4737 prologue interrupts are enabled;
4738 naked - don't generate function prologue/epilogue and `ret' command.
4740 Only `progmem' attribute valid for type. */
4742 const struct attribute_spec avr_attribute_table[] =
4744 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4745 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
4746 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4747 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4748 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4749 { NULL, 0, 0, false, false, false, NULL }
4752 /* Handle a "progmem" attribute; arguments as in
4753 struct attribute_spec.handler. */
4755 avr_handle_progmem_attribute (node, name, args, flags, no_add_attrs)
4758 tree args ATTRIBUTE_UNUSED;
4759 int flags ATTRIBUTE_UNUSED;
4764 if (TREE_CODE (*node) == TYPE_DECL)
4766 /* This is really a decl attribute, not a type attribute,
4767 but try to handle it for GCC 3.0 backwards compatibility. */
4769 tree type = TREE_TYPE (*node);
4770 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
4771 tree newtype = build_type_attribute_variant (type, attr);
4773 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
4774 TREE_TYPE (*node) = newtype;
4775 *no_add_attrs = true;
4777 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
4779 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
4781 warning ("only initialized variables can be placed into "
4782 "program memory area");
4783 *no_add_attrs = true;
4788 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
4789 *no_add_attrs = true;
4796 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4797 struct attribute_spec.handler. */
4799 avr_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
4802 tree args ATTRIBUTE_UNUSED;
4803 int flags ATTRIBUTE_UNUSED;
4806 if (TREE_CODE (*node) != FUNCTION_DECL)
4808 warning ("`%s' attribute only applies to functions",
4809 IDENTIFIER_POINTER (name));
4810 *no_add_attrs = true;
4816 /* Look for attribute `progmem' in DECL
4817 if found return 1, otherwise 0. */
4820 avr_progmem_p (decl)
4825 if (TREE_CODE (decl) != VAR_DECL)
4829 != lookup_attribute ("progmem", DECL_ATTRIBUTES (decl)))
4835 while (TREE_CODE (a) == ARRAY_TYPE);
4837 if (a == error_mark_node)
4840 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4846 /* Add the section attribute if the variable is in progmem. */
4849 avr_insert_attributes (node, attributes)
4853 if (TREE_CODE (node) == VAR_DECL
4854 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
4855 && avr_progmem_p (node))
4857 static const char dsec[] = ".progmem.data";
4858 *attributes = tree_cons (get_identifier ("section"),
4859 build_tree_list (NULL, build_string (strlen (dsec), dsec)),
4862 /* ??? This seems sketchy. Why can't the user declare the
4863 thing const in the first place? */
4864 TREE_READONLY (node) = 1;
4869 avr_section_type_flags (decl, name, reloc)
4874 unsigned int flags = default_section_type_flags (decl, name, reloc);
4876 if (strncmp (name, ".noinit", 7) == 0)
4878 if (decl && TREE_CODE (decl) == VAR_DECL
4879 && DECL_INITIAL (decl) == NULL_TREE)
4880 flags |= SECTION_BSS; /* @nobits */
4882 warning ("only uninitialized variables can be placed in the "
4889 /* Outputs some appropriate text to go at the start of an assembler
4896 error ("MCU `%s' supported for assembler only", avr_mcu_name);
4898 default_file_start ();
4900 fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);
4901 fputs ("__SREG__ = 0x3f\n"
4903 "__SP_L__ = 0x3d\n", asm_out_file);
4905 fputs ("__tmp_reg__ = 0\n"
4906 "__zero_reg__ = 1\n", asm_out_file);
4908 /* FIXME: output these only if there is anything in the .data / .bss
4909 sections - some code size could be saved by not linking in the
4910 initialization code from libgcc if one or both sections are empty. */
4911 fputs ("\t.global __do_copy_data\n", asm_out_file);
4912 fputs ("\t.global __do_clear_bss\n", asm_out_file);
4914 commands_in_file = 0;
4915 commands_in_prologues = 0;
4916 commands_in_epilogues = 0;
4919 /* Outputs to the stdio stream FILE some
4920 appropriate text to go at the end of an assembler file. */
4925 fputs ("/* File ", asm_out_file);
4926 output_quoted_string (asm_out_file, main_input_filename);
4927 fprintf (asm_out_file,
4928 ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4931 commands_in_file - commands_in_prologues - commands_in_epilogues,
4932 commands_in_prologues, commands_in_epilogues);
4935 /* Choose the order in which to allocate hard registers for
4936 pseudo-registers local to a basic block.
4938 Store the desired register order in the array `reg_alloc_order'.
4939 Element 0 should be the register to allocate first; element 1, the
4940 next register; and so on. */
4943 order_regs_for_local_alloc ()
4946 static const int order_0[] = {
4954 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4958 static const int order_1[] = {
4966 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4970 static const int order_2[] = {
4979 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4984 const int *order = (TARGET_ORDER_1 ? order_1 :
4985 TARGET_ORDER_2 ? order_2 :
4987 for (i=0; i < ARRAY_SIZE (order_0); ++i)
4988 reg_alloc_order[i] = order[i];
4991 /* Calculate the cost of X code of the expression in which it is contained,
4992 found in OUTER_CODE */
4995 default_rtx_costs (X, code, outer_code)
4998 enum rtx_code outer_code;
5005 cost = 2 * GET_MODE_SIZE (GET_MODE (X));
5008 if (outer_code != SET)
5010 if (GET_CODE (XEXP (X,0)) == SYMBOL_REF)
5011 cost += 2 * GET_MODE_SIZE (GET_MODE (X));
5013 cost += GET_MODE_SIZE (GET_MODE (X));
5019 if (outer_code == SET)
5020 cost = GET_MODE_SIZE (GET_MODE (X));
5022 cost = -GET_MODE_SIZE (GET_MODE (X));
5025 if (outer_code == SET)
5026 cost = GET_MODE_SIZE (GET_MODE (X));
5032 if (outer_code == SET)
5034 if (X == stack_pointer_rtx)
5036 else if (GET_CODE (XEXP (X,1)) == CONST_INT)
5037 cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 :
5038 GET_MODE_SIZE (GET_MODE (X)));
5040 cost = GET_MODE_SIZE (GET_MODE (X));
5044 if (GET_CODE (XEXP (X,1)) == CONST_INT)
5045 cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0)));
5054 avr_rtx_costs (x, code, outer_code, total)
5056 int code, outer_code;
5064 if (outer_code == PLUS
5065 || outer_code == IOR
5066 || outer_code == AND
5067 || outer_code == MINUS
5068 || outer_code == SET
5074 if (outer_code == COMPARE
5076 && INTVAL (x) <= 255)
5091 cst = default_rtx_costs (x, code, outer_code);
5103 /* Calculate the cost of a memory address */
5106 avr_address_cost (x)
5109 if (GET_CODE (x) == PLUS
5110 && GET_CODE (XEXP (x,1)) == CONST_INT
5111 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
5112 && INTVAL (XEXP (x,1)) >= 61)
5114 if (CONSTANT_ADDRESS_P (x))
5116 if (avr_io_address_p (x, 1))
5123 /* EXTRA_CONSTRAINT helper */
5126 extra_constraint (x, c)
5131 && GET_CODE (x) == MEM
5132 && GET_CODE (XEXP (x,0)) == PLUS)
5134 if (TARGET_ALL_DEBUG)
5136 fprintf (stderr, ("extra_constraint:\n"
5137 "reload_completed: %d\n"
5138 "reload_in_progress: %d\n"),
5139 reload_completed, reload_in_progress);
5142 if (GET_CODE (x) == MEM
5143 && GET_CODE (XEXP (x,0)) == PLUS
5144 && REG_P (XEXP (XEXP (x,0), 0))
5145 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
5146 && (INTVAL (XEXP (XEXP (x,0), 1))
5147 <= MAX_LD_OFFSET (GET_MODE (x))))
5149 rtx xx = XEXP (XEXP (x,0), 0);
5150 int regno = REGNO (xx);
5151 if (TARGET_ALL_DEBUG)
5153 fprintf (stderr, ("extra_constraint:\n"
5154 "reload_completed: %d\n"
5155 "reload_in_progress: %d\n"),
5156 reload_completed, reload_in_progress);
5159 if (regno >= FIRST_PSEUDO_REGISTER)
5160 return 1; /* allocate pseudos */
5161 else if (regno == REG_Z || regno == REG_Y)
5162 return 1; /* strictly check */
5163 else if (xx == frame_pointer_rtx
5164 || xx == arg_pointer_rtx)
5165 return 1; /* XXX frame & arg pointer checks */
5171 /* Convert condition code CONDITION to the valid AVR condition code */
5174 avr_normalize_condition (condition)
5192 /* This fnction optimizes conditional jumps */
5199 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5201 if (! (GET_CODE (insn) == INSN
5202 || GET_CODE (insn) == CALL_INSN
5203 || GET_CODE (insn) == JUMP_INSN)
5204 || !single_set (insn))
5207 pattern = PATTERN (insn);
5209 if (GET_CODE (pattern) == PARALLEL)
5210 pattern = XVECEXP (pattern, 0, 0);
5211 if (GET_CODE (pattern) == SET
5212 && SET_DEST (pattern) == cc0_rtx
5213 && compare_diff_p (insn))
5215 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
5217 /* Now we work under compare insn */
5219 pattern = SET_SRC (pattern);
5220 if (true_regnum (XEXP (pattern,0)) >= 0
5221 && true_regnum (XEXP (pattern,1)) >= 0 )
5223 rtx x = XEXP (pattern,0);
5224 rtx next = next_real_insn (insn);
5225 rtx pat = PATTERN (next);
5226 rtx src = SET_SRC (pat);
5227 rtx t = XEXP (src,0);
5228 PUT_CODE (t, swap_condition (GET_CODE (t)));
5229 XEXP (pattern,0) = XEXP (pattern,1);
5230 XEXP (pattern,1) = x;
5231 INSN_CODE (next) = -1;
5233 else if (true_regnum (XEXP (pattern,0)) >= 0
5234 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
5236 rtx x = XEXP (pattern,1);
5237 rtx next = next_real_insn (insn);
5238 rtx pat = PATTERN (next);
5239 rtx src = SET_SRC (pat);
5240 rtx t = XEXP (src,0);
5241 enum machine_mode mode = GET_MODE (XEXP (pattern, 0));
5243 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
5245 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
5246 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
5247 INSN_CODE (next) = -1;
5248 INSN_CODE (insn) = -1;
5252 else if (true_regnum (SET_SRC (pattern)) >= 0)
5254 /* This is a tst insn */
5255 rtx next = next_real_insn (insn);
5256 rtx pat = PATTERN (next);
5257 rtx src = SET_SRC (pat);
5258 rtx t = XEXP (src,0);
5260 PUT_CODE (t, swap_condition (GET_CODE (t)));
5261 SET_SRC (pattern) = gen_rtx (NEG,
5262 GET_MODE (SET_SRC (pattern)),
5264 INSN_CODE (next) = -1;
5265 INSN_CODE (insn) = -1;
5271 /* Returns register number for function return value.*/
5279 /* Ceate an RTX representing the place where a
5280 library function returns a value of mode MODE. */
5283 avr_libcall_value (mode)
5284 enum machine_mode mode;
5286 int offs = GET_MODE_SIZE (mode);
5289 return gen_rtx (REG, mode, RET_REGISTER + 2 - offs);
5292 /* Create an RTX representing the place where a
5293 function returns a value of data type VALTYPE. */
5296 avr_function_value (type, func)
5298 tree func ATTRIBUTE_UNUSED;
5302 if (TYPE_MODE (type) != BLKmode)
5303 return avr_libcall_value (TYPE_MODE (type));
5305 offs = int_size_in_bytes (type);
5308 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5309 offs = GET_MODE_SIZE (SImode);
5310 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5311 offs = GET_MODE_SIZE (DImode);
5313 return gen_rtx (REG, BLKmode, RET_REGISTER + 2 - offs);
5316 /* Returns nonzero if the number MASK has only one bit set. */
5319 mask_one_bit_p (mask)
5323 unsigned HOST_WIDE_INT n=mask;
5324 for (i = 0; i < 32; ++i)
5326 if (n & 0x80000000L)
5328 if (n & 0x7fffffffL)
5339 /* Places additional restrictions on the register class to
5340 use when it is necessary to copy value X into a register
5344 preferred_reload_class (x, class)
5345 rtx x ATTRIBUTE_UNUSED;
5346 enum reg_class class;
5352 test_hard_reg_class (class, x)
5353 enum reg_class class;
5356 int regno = true_regnum (x);
5360 if (TEST_HARD_REG_CLASS (class, regno))
5368 jump_over_one_insn_p (insn, dest)
5372 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5375 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5376 int dest_addr = INSN_ADDRESSES (uid);
5377 return dest_addr - jump_addr == get_attr_length (insn) + 1;
5380 /* Returns 1 if a value of mode MODE can be stored starting with hard
5381 register number REGNO. On the enhanced core, anything larger than
5382 1 byte must start in even numbered register for "movw" to work
5383 (this way we don't have to check for odd registers everywhere). */
5386 avr_hard_regno_mode_ok (regno, mode)
5388 enum machine_mode mode;
5390 /* Bug workaround: recog.c (peep2_find_free_register) and probably
5391 a few other places assume that the frame pointer is a single hard
5392 register, so r29 may be allocated and overwrite the high byte of
5393 the frame pointer. Do not allow any value to start in r29. */
5394 if (regno == REG_Y + 1)
5399 /* if (regno < 24 && !AVR_ENHANCED)
5401 return !(regno & 1);
5404 /* Returns 1 if we know register operand OP was 0 before INSN. */
5407 reg_was_0 (insn, op)
5412 return (optimize > 0 && insn && op && REG_P (op)
5413 && (link = find_reg_note (insn, REG_WAS_0, 0))
5414 /* Make sure the insn that stored the 0 is still present. */
5415 && ! INSN_DELETED_P (XEXP (link, 0))
5416 && GET_CODE (XEXP (link, 0)) != NOTE
5417 /* Make sure cross jumping didn't happen here. */
5418 && no_labels_between_p (XEXP (link, 0), insn)
5419 /* Make sure the reg hasn't been clobbered. */
5420 && ! reg_set_between_p (op, XEXP (link, 0), insn));
5423 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5424 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5425 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
5428 avr_io_address_p (x, size)
5432 return (optimize > 0 && GET_CODE (x) == CONST_INT
5433 && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
5436 /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5439 const_int_pow2_p (x)
5442 if (GET_CODE (x) == CONST_INT)
5444 HOST_WIDE_INT d = INTVAL (x);
5445 HOST_WIDE_INT abs_d = (d >= 0) ? d : -d;
5446 return exact_log2 (abs_d) + 1;
5452 output_reload_inhi (insn, operands, len)
5453 rtx insn ATTRIBUTE_UNUSED;
5461 if (GET_CODE (operands[1]) == CONST_INT)
5463 int val = INTVAL (operands[1]);
5464 if ((val & 0xff) == 0)
5467 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5468 AS2 (ldi,%2,hi8(%1)) CR_TAB
5471 else if ((val & 0xff00) == 0)
5474 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5475 AS2 (mov,%A0,%2) CR_TAB
5476 AS2 (mov,%B0,__zero_reg__));
5478 else if ((val & 0xff) == ((val & 0xff00) >> 8))
5481 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5482 AS2 (mov,%A0,%2) CR_TAB
5487 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5488 AS2 (mov,%A0,%2) CR_TAB
5489 AS2 (ldi,%2,hi8(%1)) CR_TAB
5495 output_reload_insisf (insn, operands, len)
5496 rtx insn ATTRIBUTE_UNUSED;
5500 rtx src = operands[1];
5501 int cnst = (GET_CODE (src) == CONST_INT);
5506 *len = 4 + ((INTVAL (src) & 0xff) != 0)
5507 + ((INTVAL (src) & 0xff00) != 0)
5508 + ((INTVAL (src) & 0xff0000) != 0)
5509 + ((INTVAL (src) & 0xff000000) != 0);
5516 if (cnst && ((INTVAL (src) & 0xff) == 0))
5517 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5520 output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
5521 output_asm_insn (AS2 (mov, %A0, %2), operands);
5523 if (cnst && ((INTVAL (src) & 0xff00) == 0))
5524 output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
5527 output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
5528 output_asm_insn (AS2 (mov, %B0, %2), operands);
5530 if (cnst && ((INTVAL (src) & 0xff0000) == 0))
5531 output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
5534 output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
5535 output_asm_insn (AS2 (mov, %C0, %2), operands);
5537 if (cnst && ((INTVAL (src) & 0xff000000) == 0))
5538 output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
5541 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5542 output_asm_insn (AS2 (mov, %D0, %2), operands);
5548 avr_output_bld (operands, bit_nr)
5552 static char s[] = "bld %A0,0";
5554 s[5] = 'A' + (bit_nr >> 3);
5555 s[8] = '0' + (bit_nr & 7);
5556 output_asm_insn (s, operands);
5560 avr_output_addr_vec_elt (stream, value)
5565 fprintf (stream, "\t.word pm(.L%d)\n", value);
5567 fprintf (stream, "\trjmp .L%d\n", value);
5572 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5573 registers (for a define_peephole2) in the current function. */
5576 avr_peep2_scratch_safe (scratch)
5579 if ((interrupt_function_p (current_function_decl)
5580 || signal_function_p (current_function_decl))
5581 && leaf_function_p ())
5583 int first_reg = true_regnum (scratch);
5584 int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
5587 for (reg = first_reg; reg <= last_reg; reg++)
5589 if (!regs_ever_live[reg])
5596 /* Output a branch that tests a single bit of a register (QI, HI or SImode)
5597 or memory location in the I/O space (QImode only).
5599 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5600 Operand 1: register operand to test, or CONST_INT memory address.
5601 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5602 Operand 3: label to jump to if the test is true. */
5605 avr_out_sbxx_branch (insn, operands)
5609 enum rtx_code comp = GET_CODE (operands[0]);
5610 int long_jump = (get_attr_length (insn) >= 4);
5611 int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
5615 else if (comp == LT)
5619 comp = reverse_condition (comp);
5621 if (GET_CODE (operands[1]) == CONST_INT)
5623 if (INTVAL (operands[1]) < 0x40)
5626 output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
5628 output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
5632 output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
5634 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
5636 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
5639 else /* GET_CODE (operands[1]) == REG */
5641 if (GET_MODE (operands[1]) == QImode)
5644 output_asm_insn (AS2 (sbrs,%1,%2), operands);
5646 output_asm_insn (AS2 (sbrc,%1,%2), operands);
5648 else /* HImode or SImode */
5650 static char buf[] = "sbrc %A1,0";
5651 int bit_nr = exact_log2 (INTVAL (operands[2])
5652 & GET_MODE_MASK (GET_MODE (operands[1])));
5654 buf[3] = (comp == EQ) ? 's' : 'c';
5655 buf[6] = 'A' + (bit_nr >> 3);
5656 buf[9] = '0' + (bit_nr & 7);
5657 output_asm_insn (buf, operands);
5662 return (AS1 (rjmp,.+4) CR_TAB
5665 return AS1 (rjmp,%3);
5670 avr_asm_out_ctor (symbol, priority)
5674 fputs ("\t.global __do_global_ctors\n", asm_out_file);
5675 default_ctor_section_asm_out_constructor (symbol, priority);
5679 avr_asm_out_dtor (symbol, priority)
5683 fputs ("\t.global __do_global_dtors\n", asm_out_file);
5684 default_dtor_section_asm_out_destructor (symbol, priority);