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 tree avr_handle_progmem_attribute PARAMS ((tree *, tree, tree, int, bool *));
62 static tree avr_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
63 const struct attribute_spec avr_attribute_table[];
64 static bool avr_assemble_integer PARAMS ((rtx, unsigned int, int));
65 static void avr_file_start PARAMS ((void));
66 static void avr_file_end PARAMS ((void));
67 static void avr_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
68 static void avr_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
69 static void avr_unique_section PARAMS ((tree, int));
70 static void avr_insert_attributes PARAMS ((tree, tree *));
71 static unsigned int avr_section_type_flags PARAMS ((tree, const char *, int));
73 static void avr_reorg PARAMS ((void));
74 static void avr_asm_out_ctor PARAMS ((rtx, int));
75 static void avr_asm_out_dtor PARAMS ((rtx, int));
76 static int default_rtx_costs PARAMS ((rtx, enum rtx_code, enum rtx_code));
77 static bool avr_rtx_costs PARAMS ((rtx, int, int, int *));
78 static int avr_address_cost PARAMS ((rtx));
80 /* Allocate registers from r25 to r8 for parameters for function calls */
81 #define FIRST_CUM_REG 26
83 /* Temporary register RTX (gen_rtx (REG,QImode,TMP_REGNO)) */
86 /* Zeroed register RTX (gen_rtx (REG,QImode,ZERO_REGNO)) */
89 /* RTX for register which will be used for loading immediate values to
93 /* AVR register names {"r0", "r1", ..., "r31"} */
94 static const char *const avr_regnames[] = REGISTER_NAMES;
96 /* This holds the last insn address. */
97 static int last_insn_address = 0;
99 /* Commands count in the compiled file */
100 static int commands_in_file;
102 /* Commands in the functions prologues in the compiled file */
103 static int commands_in_prologues;
105 /* Commands in the functions epilogues in the compiled file */
106 static int commands_in_epilogues;
108 /* Prologue/Epilogue size in words */
109 static int prologue_size;
110 static int epilogue_size;
112 /* Size of all jump tables in the current function, in words. */
113 static int jump_tables_size;
115 /* Initial stack value specified by the `-minit-stack=' option */
116 const char *avr_init_stack = "__stack";
118 /* Default MCU name */
119 const char *avr_mcu_name = "avr2";
121 /* Preprocessor macros to define depending on MCU type. */
122 const char *avr_base_arch_macro;
123 const char *avr_extra_arch_macro;
125 /* More than 8K of program memory: use "call" and "jmp". */
128 /* Enhanced core: use "movw", "mul", ... */
129 int avr_enhanced_p = 0;
131 /* Assembler only. */
132 int avr_asm_only_p = 0;
138 const char *const macro;
141 static const struct base_arch_s avr_arch_types[] = {
142 { 1, 0, 0, NULL }, /* unknown device specified */
143 { 1, 0, 0, "__AVR_ARCH__=1" },
144 { 0, 0, 0, "__AVR_ARCH__=2" },
145 { 0, 0, 1, "__AVR_ARCH__=3" },
146 { 0, 1, 0, "__AVR_ARCH__=4" },
147 { 0, 1, 1, "__AVR_ARCH__=5" }
151 const char *const name;
152 int arch; /* index in avr_arch_types[] */
153 /* Must lie outside user's namespace. NULL == no macro. */
154 const char *const macro;
157 /* List of all known AVR MCU types - if updated, it has to be kept
158 in sync in several places (FIXME: is there a better way?):
160 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
161 - t-avr (MULTILIB_MATCHES)
162 - gas/config/tc-avr.c
165 static const struct mcu_type_s avr_mcu_types[] = {
166 /* Classic, <= 8K. */
168 { "at90s2313", 2, "__AVR_AT90S2313__" },
169 { "at90s2323", 2, "__AVR_AT90S2323__" },
170 { "at90s2333", 2, "__AVR_AT90S2333__" },
171 { "at90s2343", 2, "__AVR_AT90S2343__" },
172 { "attiny22", 2, "__AVR_ATtiny22__" },
173 { "attiny26", 2, "__AVR_ATtiny26__" },
174 { "at90s4414", 2, "__AVR_AT90S4414__" },
175 { "at90s4433", 2, "__AVR_AT90S4433__" },
176 { "at90s4434", 2, "__AVR_AT90S4434__" },
177 { "at90s8515", 2, "__AVR_AT90S8515__" },
178 { "at90c8534", 2, "__AVR_AT90C8534__" },
179 { "at90s8535", 2, "__AVR_AT90S8535__" },
180 { "at86rf401", 2, "__AVR_AT86RF401__" },
183 { "atmega103", 3, "__AVR_ATmega103__" },
184 { "atmega603", 3, "__AVR_ATmega603__" },
185 { "at43usb320", 3, "__AVR_AT43USB320__" },
186 { "at43usb355", 3, "__AVR_AT43USB355__" },
187 { "at76c711", 3, "__AVR_AT76C711__" },
188 /* Enhanced, <= 8K. */
190 { "atmega8", 4, "__AVR_ATmega8__" },
191 { "atmega8515", 4, "__AVR_ATmega8515__" },
192 { "atmega8535", 4, "__AVR_ATmega8535__" },
193 /* Enhanced, > 8K. */
195 { "atmega16", 5, "__AVR_ATmega16__" },
196 { "atmega161", 5, "__AVR_ATmega161__" },
197 { "atmega162", 5, "__AVR_ATmega162__" },
198 { "atmega163", 5, "__AVR_ATmega163__" },
199 { "atmega169", 5, "__AVR_ATmega169__" },
200 { "atmega32", 5, "__AVR_ATmega32__" },
201 { "atmega323", 5, "__AVR_ATmega323__" },
202 { "atmega64", 5, "__AVR_ATmega64__" },
203 { "atmega128", 5, "__AVR_ATmega128__" },
204 { "at94k", 5, "__AVR_AT94K__" },
205 /* Assembler only. */
207 { "at90s1200", 1, "__AVR_AT90S1200__" },
208 { "attiny11", 1, "__AVR_ATtiny11__" },
209 { "attiny12", 1, "__AVR_ATtiny12__" },
210 { "attiny15", 1, "__AVR_ATtiny15__" },
211 { "attiny28", 1, "__AVR_ATtiny28__" },
215 int avr_case_values_threshold = 30000;
217 /* Initialize the GCC target structure. */
218 #undef TARGET_ASM_ALIGNED_HI_OP
219 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
220 #undef TARGET_ASM_INTEGER
221 #define TARGET_ASM_INTEGER avr_assemble_integer
222 #undef TARGET_ASM_FILE_START
223 #define TARGET_ASM_FILE_START avr_file_start
224 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
225 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
226 #undef TARGET_ASM_FILE_END
227 #define TARGET_ASM_FILE_END avr_file_end
229 #undef TARGET_ASM_FUNCTION_PROLOGUE
230 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
231 #undef TARGET_ASM_FUNCTION_EPILOGUE
232 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
233 #undef TARGET_ATTRIBUTE_TABLE
234 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
235 #undef TARGET_ASM_UNIQUE_SECTION
236 #define TARGET_ASM_UNIQUE_SECTION avr_unique_section
237 #undef TARGET_INSERT_ATTRIBUTES
238 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
239 #undef TARGET_SECTION_TYPE_FLAGS
240 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
241 #undef TARGET_RTX_COSTS
242 #define TARGET_RTX_COSTS avr_rtx_costs
243 #undef TARGET_ADDRESS_COST
244 #define TARGET_ADDRESS_COST avr_address_cost
245 #undef TARGET_MACHINE_DEPENDENT_REORG
246 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
248 struct gcc_target targetm = TARGET_INITIALIZER;
251 avr_override_options ()
253 const struct mcu_type_s *t;
254 const struct base_arch_s *base;
256 for (t = avr_mcu_types; t->name; t++)
257 if (strcmp (t->name, avr_mcu_name) == 0)
262 fprintf (stderr, "unknown MCU `%s' specified\nKnown MCU names:\n",
264 for (t = avr_mcu_types; t->name; t++)
265 fprintf (stderr," %s\n", t->name);
268 base = &avr_arch_types[t->arch];
269 avr_asm_only_p = base->asm_only;
270 avr_enhanced_p = base->enhanced;
271 avr_mega_p = base->mega;
272 avr_base_arch_macro = base->macro;
273 avr_extra_arch_macro = t->macro;
275 if (optimize && !TARGET_NO_TABLEJUMP)
276 avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
280 /* Initialize TMP_REG_RTX and ZERO_REG_RTX */
284 tmp_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
285 memset (tmp_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
286 PUT_CODE (tmp_reg_rtx, REG);
287 PUT_MODE (tmp_reg_rtx, QImode);
288 XINT (tmp_reg_rtx, 0) = TMP_REGNO;
290 zero_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
291 memset (zero_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
292 PUT_CODE (zero_reg_rtx, REG);
293 PUT_MODE (zero_reg_rtx, QImode);
294 XINT (zero_reg_rtx, 0) = ZERO_REGNO;
296 ldi_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
297 memset (ldi_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
298 PUT_CODE (ldi_reg_rtx, REG);
299 PUT_MODE (ldi_reg_rtx, QImode);
300 XINT (ldi_reg_rtx, 0) = LDI_REG_REGNO;
303 /* return register class from register number */
305 static const int reg_class_tab[]={
306 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
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, /* r0 - r15 */
310 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
311 LD_REGS, /* r16 - 23 */
312 ADDW_REGS,ADDW_REGS, /* r24,r25 */
313 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
314 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
315 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
316 STACK_REG,STACK_REG /* SPL,SPH */
319 /* Return register class for register R */
322 avr_regno_reg_class (r)
326 return reg_class_tab[r];
331 /* A C expression which defines the machine-dependent operand
332 constraint letters for register classes. If C is such a
333 letter, the value should be the register class corresponding to
334 it. Otherwise, the value should be `NO_REGS'. The register
335 letter `r', corresponding to class `GENERAL_REGS', will not be
336 passed to this macro; you do not need to handle it. */
339 avr_reg_class_from_letter (c)
344 case 't' : return R0_REG;
345 case 'b' : return BASE_POINTER_REGS;
346 case 'e' : return POINTER_REGS;
347 case 'w' : return ADDW_REGS;
348 case 'd' : return LD_REGS;
349 case 'l' : return NO_LD_REGS;
350 case 'a' : return SIMPLE_LD_REGS;
351 case 'x' : return POINTER_X_REGS;
352 case 'y' : return POINTER_Y_REGS;
353 case 'z' : return POINTER_Z_REGS;
354 case 'q' : return STACK_REG;
360 /* Return nonzero if FUNC is a naked function. */
363 avr_naked_function_p (func)
368 if (TREE_CODE (func) != FUNCTION_DECL)
371 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
372 return a != NULL_TREE;
375 /* Return nonzero if FUNC is an interrupt function as specified
376 by the "interrupt" attribute. */
379 interrupt_function_p (func)
384 if (TREE_CODE (func) != FUNCTION_DECL)
387 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
388 return a != NULL_TREE;
391 /* Return nonzero if FUNC is a signal function as specified
392 by the "signal" attribute. */
395 signal_function_p (func)
400 if (TREE_CODE (func) != FUNCTION_DECL)
403 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
404 return a != NULL_TREE;
407 /* Return the number of hard registers to push/pop in the prologue/epilogue
408 of the current function, and optionally store these registers in SET. */
411 avr_regs_to_save (set)
415 int int_or_sig_p = (interrupt_function_p (current_function_decl)
416 || signal_function_p (current_function_decl));
417 int leaf_func_p = leaf_function_p ();
420 CLEAR_HARD_REG_SET (*set);
423 /* No need to save any registers if the function never returns. */
424 if (TREE_THIS_VOLATILE (current_function_decl))
427 for (reg = 0; reg < 32; reg++)
429 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
430 any global register variables. */
434 if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
435 || (regs_ever_live[reg]
436 && (int_or_sig_p || !call_used_regs[reg])
437 && !(frame_pointer_needed
438 && (reg == REG_Y || reg == (REG_Y+1)))))
441 SET_HARD_REG_BIT (*set, reg);
448 /* Compute offset between arg_pointer and frame_pointer */
451 initial_elimination_offset (from, to)
455 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
459 int offset = frame_pointer_needed ? 2 : 0;
461 offset += avr_regs_to_save (NULL);
462 return get_frame_size () + 2 + 1 + offset;
466 /* Return 1 if the function epilogue is just a single "ret". */
469 avr_simple_epilogue ()
471 return (! frame_pointer_needed
472 && get_frame_size () == 0
473 && avr_regs_to_save (NULL) == 0
474 && ! interrupt_function_p (current_function_decl)
475 && ! signal_function_p (current_function_decl)
476 && ! avr_naked_function_p (current_function_decl)
477 && ! MAIN_NAME_P (DECL_NAME (current_function_decl))
478 && ! TREE_THIS_VOLATILE (current_function_decl));
481 /* This function checks sequence of live registers */
490 for (reg = 0; reg < 18; ++reg)
492 if (!call_used_regs[reg])
494 if (regs_ever_live[reg])
504 if (!frame_pointer_needed)
506 if (regs_ever_live[REG_Y])
514 if (regs_ever_live[REG_Y+1])
527 return (cur_seq == live_seq) ? live_seq : 0;
531 /* Output to FILE the asm instructions to adjust the frame pointer by
532 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
533 (epilogue). Returns the number of instructions generated. */
536 out_adj_frame_ptr (file, adj)
544 if (TARGET_TINY_STACK)
546 if (adj < -63 || adj > 63)
547 warning ("large frame pointer change (%d) with -mtiny-stack", adj);
549 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
550 over "sbiw" (2 cycles, same size). */
552 fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
555 else if (adj < -63 || adj > 63)
557 fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
558 AS2 (sbci, r29, hi8(%d)) CR_TAB),
564 fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
569 fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
577 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
578 handling various cases of interrupt enable flag state BEFORE and AFTER
579 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
580 Returns the number of instructions generated. */
583 out_set_stack_ptr (file, before, after)
588 int do_sph, do_cli, do_save, do_sei, lock_sph, size;
590 /* The logic here is so that -mno-interrupts actually means
591 "it is safe to write SPH in one instruction, then SPL in the
592 next instruction, without disabling interrupts first".
593 The after != -1 case (interrupt/signal) is not affected. */
595 do_sph = !TARGET_TINY_STACK;
596 lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
597 do_cli = (before != 0 && (after == 0 || lock_sph));
598 do_save = (do_cli && before == -1 && after == -1);
599 do_sei = ((do_cli || before != 1) && after == 1);
604 fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
610 fprintf (file, "cli" CR_TAB);
614 /* Do SPH first - maybe this will disable interrupts for one instruction
615 someday (a suggestion has been sent to avr@atmel.com for consideration
616 in future devices - that would make -mno-interrupts always safe). */
619 fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
623 /* Set/restore the I flag now - interrupts will be really enabled only
624 after the next instruction. This is not clearly documented, but
625 believed to be true for all AVR devices. */
628 fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
633 fprintf (file, "sei" CR_TAB);
637 fprintf (file, AS2 (out, __SP_L__, r28) "\n");
643 /* Output function prologue */
646 avr_output_function_prologue (file, size)
651 int interrupt_func_p;
657 last_insn_address = 0;
658 jump_tables_size = 0;
660 fprintf (file, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n",
663 if (avr_naked_function_p (current_function_decl))
665 fputs ("/* prologue: naked */\n", file);
669 interrupt_func_p = interrupt_function_p (current_function_decl);
670 signal_func_p = signal_function_p (current_function_decl);
671 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
672 live_seq = sequent_regs_live ();
673 minimize = (TARGET_CALL_PROLOGUES
674 && !interrupt_func_p && !signal_func_p && live_seq);
676 if (interrupt_func_p)
678 fprintf (file,"\tsei\n");
681 if (interrupt_func_p || signal_func_p)
684 AS1 (push,__zero_reg__) CR_TAB
685 AS1 (push,__tmp_reg__) CR_TAB
686 AS2 (in,__tmp_reg__,__SREG__) CR_TAB
687 AS1 (push,__tmp_reg__) CR_TAB
688 AS1 (clr,__zero_reg__) "\n");
694 AS1 (ldi,r28) ",lo8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
695 AS1 (ldi,r29) ",hi8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
696 AS2 (out,__SP_H__,r29) CR_TAB
697 AS2 (out,__SP_L__,r28) "\n"),
698 avr_init_stack, size, avr_init_stack, size);
702 else if (minimize && (frame_pointer_needed || live_seq > 6))
705 AS1 (ldi, r26) ",lo8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
706 AS1 (ldi, r27) ",hi8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB), size, size);
708 fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB
709 AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB)
710 ,current_function_name, current_function_name);
716 fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
717 (18 - live_seq) * 2);
722 fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
723 (18 - live_seq) * 2);
726 fprintf (file, ".L_%s_body:\n", current_function_name);
732 prologue_size += avr_regs_to_save (&set);
733 for (reg = 0; reg < 32; ++reg)
735 if (TEST_HARD_REG_BIT (set, reg))
737 fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
740 if (frame_pointer_needed)
744 AS1 (push,r28) CR_TAB
745 AS1 (push,r29) CR_TAB
746 AS2 (in,r28,__SP_L__) CR_TAB
747 AS2 (in,r29,__SP_H__) "\n");
752 prologue_size += out_adj_frame_ptr (file, size);
754 if (interrupt_func_p)
756 prologue_size += out_set_stack_ptr (file, 1, 1);
758 else if (signal_func_p)
760 prologue_size += out_set_stack_ptr (file, 0, 0);
764 prologue_size += out_set_stack_ptr (file, -1, -1);
772 fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
775 /* Output function epilogue */
778 avr_output_function_epilogue (file, size)
783 int interrupt_func_p;
789 rtx last = get_last_nonnote_insn ();
791 function_size = jump_tables_size;
794 rtx first = get_first_nonnote_insn ();
795 function_size += (INSN_ADDRESSES (INSN_UID (last)) -
796 INSN_ADDRESSES (INSN_UID (first)));
797 function_size += get_attr_length (last);
800 fprintf (file, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n", size);
803 if (avr_naked_function_p (current_function_decl))
805 fputs ("/* epilogue: naked */\n", file);
809 if (last && GET_CODE (last) == BARRIER)
811 fputs ("/* epilogue: noreturn */\n", file);
815 interrupt_func_p = interrupt_function_p (current_function_decl);
816 signal_func_p = signal_function_p (current_function_decl);
817 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
818 live_seq = sequent_regs_live ();
819 minimize = (TARGET_CALL_PROLOGUES
820 && !interrupt_func_p && !signal_func_p && live_seq);
824 /* Return value from main() is already in the correct registers
825 (r25:r24) as the exit() argument. */
828 fputs ("\t" AS1 (jmp,exit) "\n", file);
833 fputs ("\t" AS1 (rjmp,exit) "\n", file);
837 else if (minimize && (frame_pointer_needed || live_seq > 4))
839 fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
841 if (frame_pointer_needed)
843 epilogue_size += out_adj_frame_ptr (file, -size);
847 fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
848 AS2 (in , r29, __SP_H__) CR_TAB));
854 fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
855 (18 - live_seq) * 2);
860 fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
861 (18 - live_seq) * 2);
869 if (frame_pointer_needed)
874 epilogue_size += out_adj_frame_ptr (file, -size);
876 if (interrupt_func_p || signal_func_p)
878 epilogue_size += out_set_stack_ptr (file, -1, 0);
882 epilogue_size += out_set_stack_ptr (file, -1, -1);
891 epilogue_size += avr_regs_to_save (&set);
892 for (reg = 31; reg >= 0; --reg)
894 if (TEST_HARD_REG_BIT (set, reg))
896 fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
900 if (interrupt_func_p || signal_func_p)
903 AS1 (pop,__tmp_reg__) CR_TAB
904 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
905 AS1 (pop,__tmp_reg__) CR_TAB
906 AS1 (pop,__zero_reg__) "\n");
908 fprintf (file, "\treti\n");
911 fprintf (file, "\tret\n");
916 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
917 fprintf (file, "/* function %s size %d (%d) */\n", current_function_name,
918 prologue_size + function_size + epilogue_size, function_size);
919 commands_in_file += prologue_size + function_size + epilogue_size;
920 commands_in_prologues += prologue_size;
921 commands_in_epilogues += epilogue_size;
925 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
926 machine for a memory operand of mode MODE. */
929 legitimate_address_p (mode, x, strict)
930 enum machine_mode mode;
934 enum reg_class r = NO_REGS;
936 if (TARGET_ALL_DEBUG)
938 fprintf (stderr, "mode: (%s) %s %s %s %s:",
940 strict ? "(strict)": "",
941 reload_completed ? "(reload_completed)": "",
942 reload_in_progress ? "(reload_in_progress)": "",
943 reg_renumber ? "(reg_renumber)" : "");
944 if (GET_CODE (x) == PLUS
945 && REG_P (XEXP (x, 0))
946 && GET_CODE (XEXP (x, 1)) == CONST_INT
947 && INTVAL (XEXP (x, 1)) >= 0
948 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
951 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
952 true_regnum (XEXP (x, 0)));
955 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
956 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
958 else if (CONSTANT_ADDRESS_P (x))
960 else if (GET_CODE (x) == PLUS
961 && REG_P (XEXP (x, 0))
962 && GET_CODE (XEXP (x, 1)) == CONST_INT
963 && INTVAL (XEXP (x, 1)) >= 0)
965 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
969 || REGNO (XEXP (x,0)) == REG_Y
970 || REGNO (XEXP (x,0)) == REG_Z)
971 r = BASE_POINTER_REGS;
972 if (XEXP (x,0) == frame_pointer_rtx
973 || XEXP (x,0) == arg_pointer_rtx)
974 r = BASE_POINTER_REGS;
976 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
979 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
980 && REG_P (XEXP (x, 0))
981 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
982 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
986 if (TARGET_ALL_DEBUG)
988 fprintf (stderr, " ret = %c\n", r);
990 return r == NO_REGS ? 0 : (int)r;
993 /* Attempts to replace X with a valid
994 memory address for an operand of mode MODE */
997 legitimize_address (x, oldx, mode)
1000 enum machine_mode mode;
1003 if (TARGET_ALL_DEBUG)
1005 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
1009 if (GET_CODE (oldx) == PLUS
1010 && REG_P (XEXP (oldx,0)))
1012 if (REG_P (XEXP (oldx,1)))
1013 x = force_reg (GET_MODE (oldx), oldx);
1014 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
1016 int offs = INTVAL (XEXP (oldx,1));
1017 if (frame_pointer_rtx != XEXP (oldx,0))
1018 if (offs > MAX_LD_OFFSET (mode))
1020 if (TARGET_ALL_DEBUG)
1021 fprintf (stderr, "force_reg (big offset)\n");
1022 x = force_reg (GET_MODE (oldx), oldx);
1030 /* Return a pointer register name as a string */
1033 ptrreg_to_str (regno)
1038 case REG_X: return "X";
1039 case REG_Y: return "Y";
1040 case REG_Z: return "Z";
1047 /* Return the condition name as a string.
1048 Used in conditional jump constructing */
1061 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1066 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1079 /* Output ADDR to FILE as address */
1082 print_operand_address (file, addr)
1086 switch (GET_CODE (addr))
1089 fprintf (file, ptrreg_to_str (REGNO (addr)));
1093 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1097 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1101 if (CONSTANT_ADDRESS_P (addr)
1102 && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
1103 || GET_CODE (addr) == LABEL_REF))
1105 fprintf (file, "pm(");
1106 output_addr_const (file,addr);
1107 fprintf (file ,")");
1110 output_addr_const (file, addr);
1115 /* Output X as assembler operand to file FILE */
1118 print_operand (file, x, code)
1125 if (code >= 'A' && code <= 'D')
1135 if (x == zero_reg_rtx)
1136 fprintf (file, "__zero_reg__");
1138 fprintf (file, reg_names[true_regnum (x) + abcd]);
1140 else if (GET_CODE (x) == CONST_INT)
1141 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
1142 else if (GET_CODE (x) == MEM)
1144 rtx addr = XEXP (x,0);
1146 if (CONSTANT_P (addr) && abcd)
1149 output_address (addr);
1150 fprintf (file, ")+%d", abcd);
1152 else if (code == 'o')
1154 if (GET_CODE (addr) != PLUS)
1155 fatal_insn ("bad address, not (reg+disp):", addr);
1157 print_operand (file, XEXP (addr, 1), 0);
1159 else if (GET_CODE (addr) == PLUS)
1161 print_operand_address (file, XEXP (addr,0));
1162 if (REGNO (XEXP (addr, 0)) == REG_X)
1163 fatal_insn ("internal compiler error. Bad address:"
1166 print_operand (file, XEXP (addr,1), code);
1169 print_operand_address (file, addr);
1171 else if (GET_CODE (x) == CONST_DOUBLE)
1175 if (GET_MODE (x) != SFmode)
1176 fatal_insn ("internal compiler error. Unknown mode:", x);
1177 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1178 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1179 fprintf (file, "0x%lx", val);
1181 else if (code == 'j')
1182 fputs (cond_string (GET_CODE (x)), file);
1183 else if (code == 'k')
1184 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
1186 print_operand_address (file, x);
1189 /* Recognize operand OP of mode MODE used in call instructions */
1192 call_insn_operand (op, mode)
1194 enum machine_mode mode ATTRIBUTE_UNUSED;
1196 if (GET_CODE (op) == MEM)
1198 rtx inside = XEXP (op, 0);
1199 if (register_operand (inside, Pmode))
1201 if (CONSTANT_ADDRESS_P (inside))
1207 /* Update the condition code in the INSN. */
1210 notice_update_cc (body, insn)
1211 rtx body ATTRIBUTE_UNUSED;
1216 switch (get_attr_cc (insn))
1219 /* Insn does not affect CC at all. */
1227 set = single_set (insn);
1231 cc_status.flags |= CC_NO_OVERFLOW;
1232 cc_status.value1 = SET_DEST (set);
1237 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1238 The V flag may or may not be known but that's ok because
1239 alter_cond will change tests to use EQ/NE. */
1240 set = single_set (insn);
1244 cc_status.value1 = SET_DEST (set);
1245 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1250 set = single_set (insn);
1253 cc_status.value1 = SET_SRC (set);
1257 /* Insn doesn't leave CC in a usable state. */
1260 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1261 set = single_set (insn);
1264 rtx src = SET_SRC (set);
1266 if (GET_CODE (src) == ASHIFTRT
1267 && GET_MODE (src) == QImode)
1269 rtx x = XEXP (src, 1);
1271 if (GET_CODE (x) == CONST_INT
1274 cc_status.value1 = SET_DEST (set);
1275 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1283 /* Return maximum number of consecutive registers of
1284 class CLASS needed to hold a value of mode MODE. */
1287 class_max_nregs (class, mode)
1288 enum reg_class class ATTRIBUTE_UNUSED;
1289 enum machine_mode mode;
1291 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1294 /* Choose mode for jump insn:
1295 1 - relative jump in range -63 <= x <= 62 ;
1296 2 - relative jump in range -2046 <= x <= 2045 ;
1297 3 - absolute jump (only for ATmega[16]03). */
1300 avr_jump_mode (x, insn)
1301 rtx x; /* jump operand */
1302 rtx insn; /* jump insn */
1304 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1305 ? XEXP (x, 0) : x));
1306 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1307 int jump_distance = cur_addr - dest_addr;
1309 if (-63 <= jump_distance && jump_distance <= 62)
1311 else if (-2046 <= jump_distance && jump_distance <= 2045)
1319 /* return an AVR condition jump commands.
1320 X is a comparison RTX.
1321 LEN is a number returned by avr_jump_mode function.
1322 if REVERSE nonzero then condition code in X must be reversed. */
1325 ret_cond_branch (x, len, reverse)
1330 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1335 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1336 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1338 len == 2 ? (AS1 (breq,.+4) CR_TAB
1339 AS1 (brmi,.+2) CR_TAB
1341 (AS1 (breq,.+6) CR_TAB
1342 AS1 (brmi,.+4) CR_TAB
1346 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1348 len == 2 ? (AS1 (breq,.+4) CR_TAB
1349 AS1 (brlt,.+2) CR_TAB
1351 (AS1 (breq,.+6) CR_TAB
1352 AS1 (brlt,.+4) CR_TAB
1355 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1357 len == 2 ? (AS1 (breq,.+4) CR_TAB
1358 AS1 (brlo,.+2) CR_TAB
1360 (AS1 (breq,.+6) CR_TAB
1361 AS1 (brlo,.+4) CR_TAB
1364 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1365 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1367 len == 2 ? (AS1 (breq,.+2) CR_TAB
1368 AS1 (brpl,.+2) CR_TAB
1370 (AS1 (breq,.+2) CR_TAB
1371 AS1 (brpl,.+4) CR_TAB
1374 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1376 len == 2 ? (AS1 (breq,.+2) CR_TAB
1377 AS1 (brge,.+2) CR_TAB
1379 (AS1 (breq,.+2) CR_TAB
1380 AS1 (brge,.+4) CR_TAB
1383 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1385 len == 2 ? (AS1 (breq,.+2) CR_TAB
1386 AS1 (brsh,.+2) CR_TAB
1388 (AS1 (breq,.+2) CR_TAB
1389 AS1 (brsh,.+4) CR_TAB
1397 return AS1 (br%k1,%0);
1399 return (AS1 (br%j1,.+2) CR_TAB
1402 return (AS1 (br%j1,.+4) CR_TAB
1411 return AS1 (br%j1,%0);
1413 return (AS1 (br%k1,.+2) CR_TAB
1416 return (AS1 (br%k1,.+4) CR_TAB
1424 /* Predicate function for immediate operand which fits to byte (8bit) */
1427 byte_immediate_operand (op, mode)
1429 enum machine_mode mode ATTRIBUTE_UNUSED;
1431 return (GET_CODE (op) == CONST_INT
1432 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1435 /* Output all insn addresses and their sizes into the assembly language
1436 output file. This is helpful for debugging whether the length attributes
1437 in the md file are correct.
1438 Output insn cost for next insn. */
1441 final_prescan_insn (insn, operand, num_operands)
1442 rtx insn, *operand ATTRIBUTE_UNUSED;
1443 int num_operands ATTRIBUTE_UNUSED;
1445 int uid = INSN_UID (insn);
1447 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1449 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1450 INSN_ADDRESSES (uid),
1451 INSN_ADDRESSES (uid) - last_insn_address,
1452 rtx_cost (PATTERN (insn), INSN));
1454 last_insn_address = INSN_ADDRESSES (uid);
1457 /* Return 0 if undefined, 1 if always true or always false. */
1460 avr_simplify_comparison_p (mode, operator, x)
1461 enum machine_mode mode;
1465 unsigned int max = (mode == QImode ? 0xff :
1466 mode == HImode ? 0xffff :
1467 mode == SImode ? 0xffffffff : 0);
1468 if (max && operator && GET_CODE (x) == CONST_INT)
1470 if (unsigned_condition (operator) != operator)
1473 if (max != (INTVAL (x) & max)
1474 && INTVAL (x) != 0xff)
1481 /* Returns nonzero if REGNO is the number of a hard
1482 register in which function arguments are sometimes passed. */
1485 function_arg_regno_p(r)
1488 return (r >= 8 && r <= 25);
1491 /* Initializing the variable cum for the state at the beginning
1492 of the argument list. */
1495 init_cumulative_args (cum, fntype, libname, fndecl)
1496 CUMULATIVE_ARGS *cum;
1499 tree fndecl ATTRIBUTE_UNUSED;
1502 cum->regno = FIRST_CUM_REG;
1503 if (!libname && fntype)
1505 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1506 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1507 != void_type_node));
1513 /* Returns the number of registers to allocate for a function argument. */
1516 avr_num_arg_regs (mode, type)
1517 enum machine_mode mode;
1522 if (mode == BLKmode)
1523 size = int_size_in_bytes (type);
1525 size = GET_MODE_SIZE (mode);
1527 /* Align all function arguments to start in even-numbered registers.
1528 Odd-sized arguments leave holes above them. */
1530 return (size + 1) & ~1;
1533 /* Controls whether a function argument is passed
1534 in a register, and which register. */
1537 function_arg (cum, mode, type, named)
1538 CUMULATIVE_ARGS *cum;
1539 enum machine_mode mode;
1541 int named ATTRIBUTE_UNUSED;
1543 int bytes = avr_num_arg_regs (mode, type);
1545 if (cum->nregs && bytes <= cum->nregs)
1546 return gen_rtx (REG, mode, cum->regno - bytes);
1551 /* Update the summarizer variable CUM to advance past an argument
1552 in the argument list. */
1555 function_arg_advance (cum, mode, type, named)
1556 CUMULATIVE_ARGS *cum; /* current arg information */
1557 enum machine_mode mode; /* current arg mode */
1558 tree type; /* type of the argument or 0 if lib support */
1559 int named ATTRIBUTE_UNUSED; /* whether or not the argument was named */
1561 int bytes = avr_num_arg_regs (mode, type);
1563 cum->nregs -= bytes;
1564 cum->regno -= bytes;
1566 if (cum->nregs <= 0)
1569 cum->regno = FIRST_CUM_REG;
1573 /***********************************************************************
1574 Functions for outputting various mov's for a various modes
1575 ************************************************************************/
1577 output_movqi (insn, operands, l)
1583 rtx dest = operands[0];
1584 rtx src = operands[1];
1592 if (register_operand (dest, QImode))
1594 if (register_operand (src, QImode)) /* mov r,r */
1596 if (test_hard_reg_class (STACK_REG, dest))
1597 return AS2 (out,%0,%1);
1598 else if (test_hard_reg_class (STACK_REG, src))
1599 return AS2 (in,%0,%1);
1601 return AS2 (mov,%0,%1);
1603 else if (CONSTANT_P (src))
1605 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1606 return AS2 (ldi,%0,lo8(%1));
1608 if (GET_CODE (src) == CONST_INT)
1610 if (src == const0_rtx) /* mov r,L */
1611 return AS1 (clr,%0);
1612 else if (src == const1_rtx)
1615 return (AS1 (clr,%0) CR_TAB
1618 else if (src == constm1_rtx)
1620 /* Immediate constants -1 to any register */
1622 return (AS1 (clr,%0) CR_TAB
1627 int bit_nr = exact_log2 (INTVAL (src));
1633 output_asm_insn ((AS1 (clr,%0) CR_TAB
1636 avr_output_bld (operands, bit_nr);
1643 /* Last resort, larger than loading from memory. */
1645 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1646 AS2 (ldi,r31,lo8(%1)) CR_TAB
1647 AS2 (mov,%0,r31) CR_TAB
1648 AS2 (mov,r31,__tmp_reg__));
1650 else if (GET_CODE (src) == MEM)
1651 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1653 else if (GET_CODE (dest) == MEM)
1655 const char *template;
1657 if (src == const0_rtx)
1658 operands[1] = zero_reg_rtx;
1660 template = out_movqi_mr_r (insn, operands, real_l);
1663 output_asm_insn (template, operands);
1672 output_movhi (insn, operands, l)
1678 rtx dest = operands[0];
1679 rtx src = operands[1];
1685 if (register_operand (dest, HImode))
1687 if (register_operand (src, HImode)) /* mov r,r */
1689 if (test_hard_reg_class (STACK_REG, dest))
1691 if (TARGET_TINY_STACK)
1694 return AS2 (out,__SP_L__,%A1);
1696 else if (TARGET_NO_INTERRUPTS)
1699 return (AS2 (out,__SP_H__,%B1) CR_TAB
1700 AS2 (out,__SP_L__,%A1));
1704 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1706 AS2 (out,__SP_H__,%B1) CR_TAB
1707 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1708 AS2 (out,__SP_L__,%A1));
1710 else if (test_hard_reg_class (STACK_REG, src))
1713 return (AS2 (in,%A0,__SP_L__) CR_TAB
1714 AS2 (in,%B0,__SP_H__));
1720 return (AS2 (movw,%0,%1));
1723 if (true_regnum (dest) > true_regnum (src))
1726 return (AS2 (mov,%B0,%B1) CR_TAB
1732 return (AS2 (mov,%A0,%A1) CR_TAB
1736 else if (CONSTANT_P (src))
1738 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1741 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1742 AS2 (ldi,%B0,hi8(%1)));
1745 if (GET_CODE (src) == CONST_INT)
1747 if (src == const0_rtx) /* mov r,L */
1750 return (AS1 (clr,%A0) CR_TAB
1753 else if (src == const1_rtx)
1756 return (AS1 (clr,%A0) CR_TAB
1757 AS1 (clr,%B0) CR_TAB
1760 else if (src == constm1_rtx)
1762 /* Immediate constants -1 to any register */
1764 return (AS1 (clr,%0) CR_TAB
1765 AS1 (dec,%A0) CR_TAB
1770 int bit_nr = exact_log2 (INTVAL (src));
1776 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1777 AS1 (clr,%B0) CR_TAB
1780 avr_output_bld (operands, bit_nr);
1786 if ((INTVAL (src) & 0xff) == 0)
1789 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1790 AS1 (clr,%A0) CR_TAB
1791 AS2 (ldi,r31,hi8(%1)) CR_TAB
1792 AS2 (mov,%B0,r31) CR_TAB
1793 AS2 (mov,r31,__tmp_reg__));
1795 else if ((INTVAL (src) & 0xff00) == 0)
1798 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1799 AS2 (ldi,r31,lo8(%1)) CR_TAB
1800 AS2 (mov,%A0,r31) CR_TAB
1801 AS1 (clr,%B0) CR_TAB
1802 AS2 (mov,r31,__tmp_reg__));
1806 /* Last resort, equal to loading from memory. */
1808 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1809 AS2 (ldi,r31,lo8(%1)) CR_TAB
1810 AS2 (mov,%A0,r31) CR_TAB
1811 AS2 (ldi,r31,hi8(%1)) CR_TAB
1812 AS2 (mov,%B0,r31) CR_TAB
1813 AS2 (mov,r31,__tmp_reg__));
1815 else if (GET_CODE (src) == MEM)
1816 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1818 else if (GET_CODE (dest) == MEM)
1820 const char *template;
1822 if (src == const0_rtx)
1823 operands[1] = zero_reg_rtx;
1825 template = out_movhi_mr_r (insn, operands, real_l);
1828 output_asm_insn (template, operands);
1833 fatal_insn ("invalid insn:", insn);
1838 out_movqi_r_mr (insn, op, l)
1841 int *l; /* instruction length */
1845 rtx x = XEXP (src, 0);
1851 if (CONSTANT_ADDRESS_P (x))
1853 if (avr_io_address_p (x, 1))
1856 return AS2 (in,%0,%1-0x20);
1859 return AS2 (lds,%0,%1);
1861 /* memory access by reg+disp */
1862 else if (GET_CODE (x) == PLUS
1863 && REG_P (XEXP (x,0))
1864 && GET_CODE (XEXP (x,1)) == CONST_INT)
1866 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
1868 int disp = INTVAL (XEXP (x,1));
1869 if (REGNO (XEXP (x,0)) != REG_Y)
1870 fatal_insn ("incorrect insn:",insn);
1872 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1873 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1874 AS2 (ldd,%0,Y+63) CR_TAB
1875 AS2 (sbiw,r28,%o1-63));
1877 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1878 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1879 AS2 (ld,%0,Y) CR_TAB
1880 AS2 (subi,r28,lo8(%o1)) CR_TAB
1881 AS2 (sbci,r29,hi8(%o1)));
1883 else if (REGNO (XEXP (x,0)) == REG_X)
1885 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1886 it but I have this situation with extremal optimizing options. */
1887 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
1888 || reg_unused_after (insn, XEXP (x,0)))
1889 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1892 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1893 AS2 (ld,%0,X) CR_TAB
1894 AS2 (sbiw,r26,%o1));
1897 return AS2 (ldd,%0,%1);
1900 return AS2 (ld,%0,%1);
1904 out_movhi_r_mr (insn, op, l)
1907 int *l; /* instruction length */
1911 rtx base = XEXP (src, 0);
1912 int reg_dest = true_regnum (dest);
1913 int reg_base = true_regnum (base);
1921 if (reg_dest == reg_base) /* R = (R) */
1924 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1925 AS2 (ld,%B0,%1) CR_TAB
1926 AS2 (mov,%A0,__tmp_reg__));
1928 else if (reg_base == REG_X) /* (R26) */
1930 if (reg_unused_after (insn, base))
1933 return (AS2 (ld,%A0,X+) CR_TAB
1937 return (AS2 (ld,%A0,X+) CR_TAB
1938 AS2 (ld,%B0,X) CR_TAB
1944 return (AS2 (ld,%A0,%1) CR_TAB
1945 AS2 (ldd,%B0,%1+1));
1948 else if (GET_CODE (base) == PLUS) /* (R + i) */
1950 int disp = INTVAL (XEXP (base, 1));
1951 int reg_base = true_regnum (XEXP (base, 0));
1953 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
1955 if (REGNO (XEXP (base, 0)) != REG_Y)
1956 fatal_insn ("incorrect insn:",insn);
1958 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1959 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
1960 AS2 (ldd,%A0,Y+62) CR_TAB
1961 AS2 (ldd,%B0,Y+63) CR_TAB
1962 AS2 (sbiw,r28,%o1-62));
1964 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1965 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1966 AS2 (ld,%A0,Y) CR_TAB
1967 AS2 (ldd,%B0,Y+1) CR_TAB
1968 AS2 (subi,r28,lo8(%o1)) CR_TAB
1969 AS2 (sbci,r29,hi8(%o1)));
1971 if (reg_base == REG_X)
1973 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1974 it but I have this situation with extremal
1975 optimization options. */
1978 if (reg_base == reg_dest)
1979 return (AS2 (adiw,r26,%o1) CR_TAB
1980 AS2 (ld,__tmp_reg__,X+) CR_TAB
1981 AS2 (ld,%B0,X) CR_TAB
1982 AS2 (mov,%A0,__tmp_reg__));
1984 return (AS2 (adiw,r26,%o1) CR_TAB
1985 AS2 (ld,%A0,X+) CR_TAB
1986 AS2 (ld,%B0,X) CR_TAB
1987 AS2 (sbiw,r26,%o1+1));
1990 if (reg_base == reg_dest)
1993 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
1994 AS2 (ldd,%B0,%B1) CR_TAB
1995 AS2 (mov,%A0,__tmp_reg__));
1999 return (AS2 (ldd,%A0,%A1) CR_TAB
2002 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2004 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
2005 fatal_insn ("incorrect insn:", insn);
2008 return (AS2 (ld,%B0,%1) CR_TAB
2011 else if (GET_CODE (base) == POST_INC) /* (R++) */
2013 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
2014 fatal_insn ("incorrect insn:", insn);
2017 return (AS2 (ld,%A0,%1) CR_TAB
2020 else if (CONSTANT_ADDRESS_P (base))
2022 if (avr_io_address_p (base, 2))
2025 return (AS2 (in,%A0,%A1-0x20) CR_TAB
2026 AS2 (in,%B0,%B1-0x20));
2029 return (AS2 (lds,%A0,%A1) CR_TAB
2033 fatal_insn ("unknown move insn:",insn);
2038 out_movsi_r_mr (insn, op, l)
2041 int *l; /* instruction length */
2045 rtx base = XEXP (src, 0);
2046 int reg_dest = true_regnum (dest);
2047 int reg_base = true_regnum (base);
2055 if (reg_base == REG_X) /* (R26) */
2057 if (reg_dest == REG_X)
2058 /* "ld r26,-X" is undefined */
2059 return *l=7, (AS2 (adiw,r26,3) CR_TAB
2060 AS2 (ld,r29,X) CR_TAB
2061 AS2 (ld,r28,-X) CR_TAB
2062 AS2 (ld,__tmp_reg__,-X) CR_TAB
2063 AS2 (sbiw,r26,1) CR_TAB
2064 AS2 (ld,r26,X) CR_TAB
2065 AS2 (mov,r27,__tmp_reg__));
2066 else if (reg_dest == REG_X - 2)
2067 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2068 AS2 (ld,%B0,X+) CR_TAB
2069 AS2 (ld,__tmp_reg__,X+) CR_TAB
2070 AS2 (ld,%D0,X) CR_TAB
2071 AS2 (mov,%C0,__tmp_reg__));
2072 else if (reg_unused_after (insn, base))
2073 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
2074 AS2 (ld,%B0,X+) CR_TAB
2075 AS2 (ld,%C0,X+) CR_TAB
2078 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2079 AS2 (ld,%B0,X+) CR_TAB
2080 AS2 (ld,%C0,X+) CR_TAB
2081 AS2 (ld,%D0,X) CR_TAB
2086 if (reg_dest == reg_base)
2087 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2088 AS2 (ldd,%C0,%1+2) CR_TAB
2089 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2090 AS2 (ld,%A0,%1) CR_TAB
2091 AS2 (mov,%B0,__tmp_reg__));
2092 else if (reg_base == reg_dest + 2)
2093 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2094 AS2 (ldd,%B0,%1+1) CR_TAB
2095 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2096 AS2 (ldd,%D0,%1+3) CR_TAB
2097 AS2 (mov,%C0,__tmp_reg__));
2099 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2100 AS2 (ldd,%B0,%1+1) CR_TAB
2101 AS2 (ldd,%C0,%1+2) CR_TAB
2102 AS2 (ldd,%D0,%1+3));
2105 else if (GET_CODE (base) == PLUS) /* (R + i) */
2107 int disp = INTVAL (XEXP (base, 1));
2109 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2111 if (REGNO (XEXP (base, 0)) != REG_Y)
2112 fatal_insn ("incorrect insn:",insn);
2114 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2115 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2116 AS2 (ldd,%A0,Y+60) CR_TAB
2117 AS2 (ldd,%B0,Y+61) CR_TAB
2118 AS2 (ldd,%C0,Y+62) CR_TAB
2119 AS2 (ldd,%D0,Y+63) CR_TAB
2120 AS2 (sbiw,r28,%o1-60));
2122 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2123 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2124 AS2 (ld,%A0,Y) CR_TAB
2125 AS2 (ldd,%B0,Y+1) CR_TAB
2126 AS2 (ldd,%C0,Y+2) CR_TAB
2127 AS2 (ldd,%D0,Y+3) CR_TAB
2128 AS2 (subi,r28,lo8(%o1)) CR_TAB
2129 AS2 (sbci,r29,hi8(%o1)));
2132 reg_base = true_regnum (XEXP (base, 0));
2133 if (reg_base == REG_X)
2136 if (reg_dest == REG_X)
2139 /* "ld r26,-X" is undefined */
2140 return (AS2 (adiw,r26,%o1+3) CR_TAB
2141 AS2 (ld,r29,X) CR_TAB
2142 AS2 (ld,r28,-X) CR_TAB
2143 AS2 (ld,__tmp_reg__,-X) CR_TAB
2144 AS2 (sbiw,r26,1) CR_TAB
2145 AS2 (ld,r26,X) CR_TAB
2146 AS2 (mov,r27,__tmp_reg__));
2149 if (reg_dest == REG_X - 2)
2150 return (AS2 (adiw,r26,%o1) CR_TAB
2151 AS2 (ld,r24,X+) CR_TAB
2152 AS2 (ld,r25,X+) CR_TAB
2153 AS2 (ld,__tmp_reg__,X+) CR_TAB
2154 AS2 (ld,r27,X) CR_TAB
2155 AS2 (mov,r26,__tmp_reg__));
2157 return (AS2 (adiw,r26,%o1) CR_TAB
2158 AS2 (ld,%A0,X+) CR_TAB
2159 AS2 (ld,%B0,X+) CR_TAB
2160 AS2 (ld,%C0,X+) CR_TAB
2161 AS2 (ld,%D0,X) CR_TAB
2162 AS2 (sbiw,r26,%o1+3));
2164 if (reg_dest == reg_base)
2165 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2166 AS2 (ldd,%C0,%C1) CR_TAB
2167 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2168 AS2 (ldd,%A0,%A1) CR_TAB
2169 AS2 (mov,%B0,__tmp_reg__));
2170 else if (reg_dest == reg_base - 2)
2171 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2172 AS2 (ldd,%B0,%B1) CR_TAB
2173 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2174 AS2 (ldd,%D0,%D1) CR_TAB
2175 AS2 (mov,%C0,__tmp_reg__));
2176 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2177 AS2 (ldd,%B0,%B1) CR_TAB
2178 AS2 (ldd,%C0,%C1) CR_TAB
2181 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2182 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2183 AS2 (ld,%C0,%1) CR_TAB
2184 AS2 (ld,%B0,%1) CR_TAB
2186 else if (GET_CODE (base) == POST_INC) /* (R++) */
2187 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2188 AS2 (ld,%B0,%1) CR_TAB
2189 AS2 (ld,%C0,%1) CR_TAB
2191 else if (CONSTANT_ADDRESS_P (base))
2192 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2193 AS2 (lds,%B0,%B1) CR_TAB
2194 AS2 (lds,%C0,%C1) CR_TAB
2197 fatal_insn ("unknown move insn:",insn);
2202 out_movsi_mr_r (insn, op, l)
2209 rtx base = XEXP (dest, 0);
2210 int reg_base = true_regnum (base);
2211 int reg_src = true_regnum (src);
2217 if (CONSTANT_ADDRESS_P (base))
2218 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2219 AS2 (sts,%B0,%B1) CR_TAB
2220 AS2 (sts,%C0,%C1) CR_TAB
2222 if (reg_base > 0) /* (r) */
2224 if (reg_base == REG_X) /* (R26) */
2226 if (reg_src == REG_X)
2228 /* "st X+,r26" is undefined */
2229 if (reg_unused_after (insn, base))
2230 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2231 AS2 (st,X,r26) CR_TAB
2232 AS2 (adiw,r26,1) CR_TAB
2233 AS2 (st,X+,__tmp_reg__) CR_TAB
2234 AS2 (st,X+,r28) CR_TAB
2237 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2238 AS2 (st,X,r26) CR_TAB
2239 AS2 (adiw,r26,1) CR_TAB
2240 AS2 (st,X+,__tmp_reg__) CR_TAB
2241 AS2 (st,X+,r28) CR_TAB
2242 AS2 (st,X,r29) CR_TAB
2245 else if (reg_base == reg_src + 2)
2247 if (reg_unused_after (insn, base))
2248 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2249 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2250 AS2 (st,%0+,%A1) CR_TAB
2251 AS2 (st,%0+,%B1) CR_TAB
2252 AS2 (st,%0+,__zero_reg__) CR_TAB
2253 AS2 (st,%0,__tmp_reg__) CR_TAB
2254 AS1 (clr,__zero_reg__));
2256 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2257 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2258 AS2 (st,%0+,%A1) CR_TAB
2259 AS2 (st,%0+,%B1) CR_TAB
2260 AS2 (st,%0+,__zero_reg__) CR_TAB
2261 AS2 (st,%0,__tmp_reg__) CR_TAB
2262 AS1 (clr,__zero_reg__) CR_TAB
2265 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2266 AS2 (st,%0+,%B1) CR_TAB
2267 AS2 (st,%0+,%C1) CR_TAB
2268 AS2 (st,%0,%D1) CR_TAB
2272 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2273 AS2 (std,%0+1,%B1) CR_TAB
2274 AS2 (std,%0+2,%C1) CR_TAB
2275 AS2 (std,%0+3,%D1));
2277 else if (GET_CODE (base) == PLUS) /* (R + i) */
2279 int disp = INTVAL (XEXP (base, 1));
2280 reg_base = REGNO (XEXP (base, 0));
2281 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2283 if (reg_base != REG_Y)
2284 fatal_insn ("incorrect insn:",insn);
2286 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2287 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2288 AS2 (std,Y+60,%A1) CR_TAB
2289 AS2 (std,Y+61,%B1) CR_TAB
2290 AS2 (std,Y+62,%C1) CR_TAB
2291 AS2 (std,Y+63,%D1) CR_TAB
2292 AS2 (sbiw,r28,%o0-60));
2294 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2295 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2296 AS2 (st,Y,%A1) CR_TAB
2297 AS2 (std,Y+1,%B1) CR_TAB
2298 AS2 (std,Y+2,%C1) CR_TAB
2299 AS2 (std,Y+3,%D1) CR_TAB
2300 AS2 (subi,r28,lo8(%o0)) CR_TAB
2301 AS2 (sbci,r29,hi8(%o0)));
2303 if (reg_base == REG_X)
2306 if (reg_src == REG_X)
2309 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2310 AS2 (mov,__zero_reg__,r27) CR_TAB
2311 AS2 (adiw,r26,%o0) CR_TAB
2312 AS2 (st,X+,__tmp_reg__) CR_TAB
2313 AS2 (st,X+,__zero_reg__) CR_TAB
2314 AS2 (st,X+,r28) CR_TAB
2315 AS2 (st,X,r29) CR_TAB
2316 AS1 (clr,__zero_reg__) CR_TAB
2317 AS2 (sbiw,r26,%o0+3));
2319 else if (reg_src == REG_X - 2)
2322 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2323 AS2 (mov,__zero_reg__,r27) CR_TAB
2324 AS2 (adiw,r26,%o0) CR_TAB
2325 AS2 (st,X+,r24) CR_TAB
2326 AS2 (st,X+,r25) CR_TAB
2327 AS2 (st,X+,__tmp_reg__) CR_TAB
2328 AS2 (st,X,__zero_reg__) CR_TAB
2329 AS1 (clr,__zero_reg__) CR_TAB
2330 AS2 (sbiw,r26,%o0+3));
2333 return (AS2 (adiw,r26,%o0) CR_TAB
2334 AS2 (st,X+,%A1) CR_TAB
2335 AS2 (st,X+,%B1) CR_TAB
2336 AS2 (st,X+,%C1) CR_TAB
2337 AS2 (st,X,%D1) CR_TAB
2338 AS2 (sbiw,r26,%o0+3));
2340 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2341 AS2 (std,%B0,%B1) CR_TAB
2342 AS2 (std,%C0,%C1) CR_TAB
2345 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2346 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2347 AS2 (st,%0,%C1) CR_TAB
2348 AS2 (st,%0,%B1) CR_TAB
2350 else if (GET_CODE (base) == POST_INC) /* (R++) */
2351 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2352 AS2 (st,%0,%B1) CR_TAB
2353 AS2 (st,%0,%C1) CR_TAB
2355 fatal_insn ("unknown move insn:",insn);
2360 output_movsisf(insn, operands, l)
2366 rtx dest = operands[0];
2367 rtx src = operands[1];
2373 if (register_operand (dest, VOIDmode))
2375 if (register_operand (src, VOIDmode)) /* mov r,r */
2377 if (true_regnum (dest) > true_regnum (src))
2382 return (AS2 (movw,%C0,%C1) CR_TAB
2383 AS2 (movw,%A0,%A1));
2386 return (AS2 (mov,%D0,%D1) CR_TAB
2387 AS2 (mov,%C0,%C1) CR_TAB
2388 AS2 (mov,%B0,%B1) CR_TAB
2396 return (AS2 (movw,%A0,%A1) CR_TAB
2397 AS2 (movw,%C0,%C1));
2400 return (AS2 (mov,%A0,%A1) CR_TAB
2401 AS2 (mov,%B0,%B1) CR_TAB
2402 AS2 (mov,%C0,%C1) CR_TAB
2406 else if (CONSTANT_P (src))
2408 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2411 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2412 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2413 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2414 AS2 (ldi,%D0,hhi8(%1)));
2417 if (GET_CODE (src) == CONST_INT)
2419 const char *const clr_op0 =
2420 AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
2421 AS1 (clr,%B0) CR_TAB
2423 : (AS1 (clr,%A0) CR_TAB
2424 AS1 (clr,%B0) CR_TAB
2425 AS1 (clr,%C0) CR_TAB
2428 if (src == const0_rtx) /* mov r,L */
2430 *l = AVR_ENHANCED ? 3 : 4;
2433 else if (src == const1_rtx)
2436 output_asm_insn (clr_op0, operands);
2437 *l = AVR_ENHANCED ? 4 : 5;
2438 return AS1 (inc,%A0);
2440 else if (src == constm1_rtx)
2442 /* Immediate constants -1 to any register */
2446 return (AS1 (clr,%A0) CR_TAB
2447 AS1 (dec,%A0) CR_TAB
2448 AS2 (mov,%B0,%A0) CR_TAB
2449 AS2 (movw,%C0,%A0));
2452 return (AS1 (clr,%A0) CR_TAB
2453 AS1 (dec,%A0) CR_TAB
2454 AS2 (mov,%B0,%A0) CR_TAB
2455 AS2 (mov,%C0,%A0) CR_TAB
2460 int bit_nr = exact_log2 (INTVAL (src));
2464 *l = AVR_ENHANCED ? 5 : 6;
2467 output_asm_insn (clr_op0, operands);
2468 output_asm_insn ("set", operands);
2471 avr_output_bld (operands, bit_nr);
2478 /* Last resort, better than loading from memory. */
2480 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2481 AS2 (ldi,r31,lo8(%1)) CR_TAB
2482 AS2 (mov,%A0,r31) CR_TAB
2483 AS2 (ldi,r31,hi8(%1)) CR_TAB
2484 AS2 (mov,%B0,r31) CR_TAB
2485 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2486 AS2 (mov,%C0,r31) CR_TAB
2487 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2488 AS2 (mov,%D0,r31) CR_TAB
2489 AS2 (mov,r31,__tmp_reg__));
2491 else if (GET_CODE (src) == MEM)
2492 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2494 else if (GET_CODE (dest) == MEM)
2496 const char *template;
2498 if (src == const0_rtx)
2499 operands[1] = zero_reg_rtx;
2501 template = out_movsi_mr_r (insn, operands, real_l);
2504 output_asm_insn (template, operands);
2509 fatal_insn ("invalid insn:", insn);
2514 out_movqi_mr_r (insn, op, l)
2517 int *l; /* instruction length */
2521 rtx x = XEXP (dest, 0);
2527 if (CONSTANT_ADDRESS_P (x))
2529 if (avr_io_address_p (x, 1))
2532 return AS2 (out,%0-0x20,%1);
2535 return AS2 (sts,%0,%1);
2537 /* memory access by reg+disp */
2538 else if (GET_CODE (x) == PLUS
2539 && REG_P (XEXP (x,0))
2540 && GET_CODE (XEXP (x,1)) == CONST_INT)
2542 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
2544 int disp = INTVAL (XEXP (x,1));
2545 if (REGNO (XEXP (x,0)) != REG_Y)
2546 fatal_insn ("incorrect insn:",insn);
2548 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2549 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2550 AS2 (std,Y+63,%1) CR_TAB
2551 AS2 (sbiw,r28,%o0-63));
2553 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2554 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2555 AS2 (st,Y,%1) CR_TAB
2556 AS2 (subi,r28,lo8(%o0)) CR_TAB
2557 AS2 (sbci,r29,hi8(%o0)));
2559 else if (REGNO (XEXP (x,0)) == REG_X)
2561 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
2563 if (reg_unused_after (insn, XEXP (x,0)))
2564 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2565 AS2 (adiw,r26,%o0) CR_TAB
2566 AS2 (st,X,__tmp_reg__));
2568 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2569 AS2 (adiw,r26,%o0) CR_TAB
2570 AS2 (st,X,__tmp_reg__) CR_TAB
2571 AS2 (sbiw,r26,%o0));
2575 if (reg_unused_after (insn, XEXP (x,0)))
2576 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2579 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2580 AS2 (st,X,%1) CR_TAB
2581 AS2 (sbiw,r26,%o0));
2585 return AS2 (std,%0,%1);
2588 return AS2 (st,%0,%1);
2592 out_movhi_mr_r (insn, op, l)
2599 rtx base = XEXP (dest, 0);
2600 int reg_base = true_regnum (base);
2601 int reg_src = true_regnum (src);
2605 if (CONSTANT_ADDRESS_P (base))
2607 if (avr_io_address_p (base, 2))
2610 return (AS2 (out,%B0-0x20,%B1) CR_TAB
2611 AS2 (out,%A0-0x20,%A1));
2613 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2618 if (reg_base == REG_X)
2620 if (reg_src == REG_X)
2622 /* "st X+,r26" is undefined */
2623 if (reg_unused_after (insn, src))
2624 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2625 AS2 (st,X,r26) CR_TAB
2626 AS2 (adiw,r26,1) CR_TAB
2627 AS2 (st,X,__tmp_reg__));
2629 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2630 AS2 (st,X,r26) CR_TAB
2631 AS2 (adiw,r26,1) CR_TAB
2632 AS2 (st,X,__tmp_reg__) CR_TAB
2637 if (reg_unused_after (insn, base))
2638 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2641 return *l=3, (AS2 (st ,X+,%A1) CR_TAB
2642 AS2 (st ,X,%B1) CR_TAB
2647 return *l=2, (AS2 (st ,%0,%A1) CR_TAB
2648 AS2 (std,%0+1,%B1));
2650 else if (GET_CODE (base) == PLUS)
2652 int disp = INTVAL (XEXP (base, 1));
2653 reg_base = REGNO (XEXP (base, 0));
2654 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2656 if (reg_base != REG_Y)
2657 fatal_insn ("incorrect insn:",insn);
2659 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2660 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
2661 AS2 (std,Y+62,%A1) CR_TAB
2662 AS2 (std,Y+63,%B1) CR_TAB
2663 AS2 (sbiw,r28,%o0-62));
2665 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2666 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2667 AS2 (st,Y,%A1) CR_TAB
2668 AS2 (std,Y+1,%B1) CR_TAB
2669 AS2 (subi,r28,lo8(%o0)) CR_TAB
2670 AS2 (sbci,r29,hi8(%o0)));
2672 if (reg_base == REG_X)
2675 if (reg_src == REG_X)
2678 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2679 AS2 (mov,__zero_reg__,r27) CR_TAB
2680 AS2 (adiw,r26,%o0) CR_TAB
2681 AS2 (st,X+,__tmp_reg__) CR_TAB
2682 AS2 (st,X,__zero_reg__) CR_TAB
2683 AS1 (clr,__zero_reg__) CR_TAB
2684 AS2 (sbiw,r26,%o0+1));
2687 return (AS2 (adiw,r26,%o0) CR_TAB
2688 AS2 (st,X+,%A1) CR_TAB
2689 AS2 (st,X,%B1) CR_TAB
2690 AS2 (sbiw,r26,%o0+1));
2692 return *l=2, (AS2 (std,%A0,%A1) CR_TAB
2695 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2696 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2698 else if (GET_CODE (base) == POST_INC) /* (R++) */
2699 return *l=2, (AS2 (st,%0,%A1) CR_TAB
2701 fatal_insn ("unknown move insn:",insn);
2705 /* Return 1 if frame pointer for current function required */
2708 frame_pointer_required_p ()
2710 return (current_function_calls_alloca
2711 || current_function_args_info.nregs == 0
2712 || get_frame_size () > 0);
2715 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2718 compare_condition (insn)
2721 rtx next = next_real_insn (insn);
2722 RTX_CODE cond = UNKNOWN;
2723 if (next && GET_CODE (next) == JUMP_INSN)
2725 rtx pat = PATTERN (next);
2726 rtx src = SET_SRC (pat);
2727 rtx t = XEXP (src, 0);
2728 cond = GET_CODE (t);
2733 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2736 compare_sign_p (insn)
2739 RTX_CODE cond = compare_condition (insn);
2740 return (cond == GE || cond == LT);
2743 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2744 that needs to be swapped (GT, GTU, LE, LEU). */
2747 compare_diff_p (insn)
2750 RTX_CODE cond = compare_condition (insn);
2751 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2754 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2760 RTX_CODE cond = compare_condition (insn);
2761 return (cond == EQ || cond == NE);
2765 /* Output test instruction for HImode */
2772 if (compare_sign_p (insn))
2775 return AS1 (tst,%B0);
2777 if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2778 && compare_eq_p (insn))
2780 /* faster than sbiw if we can clobber the operand */
2782 return AS2 (or,%A0,%B0);
2784 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2787 return AS2 (sbiw,%0,0);
2790 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2791 AS2 (cpc,%B0,__zero_reg__));
2795 /* Output test instruction for SImode */
2802 if (compare_sign_p (insn))
2805 return AS1 (tst,%D0);
2807 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2810 return (AS2 (sbiw,%A0,0) CR_TAB
2811 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2812 AS2 (cpc,%D0,__zero_reg__));
2815 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2816 AS2 (cpc,%B0,__zero_reg__) CR_TAB
2817 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2818 AS2 (cpc,%D0,__zero_reg__));
2822 /* Generate asm equivalent for various shifts.
2823 Shift count is a CONST_INT, MEM or REG.
2824 This only handles cases that are not already
2825 carefully hand-optimized in ?sh??i3_out. */
2828 out_shift_with_cnt (template, insn, operands, len, t_len)
2829 const char *template;
2833 int t_len; /* Length of template. */
2837 int second_label = 1;
2838 int saved_in_tmp = 0;
2839 int use_zero_reg = 0;
2841 op[0] = operands[0];
2842 op[1] = operands[1];
2843 op[2] = operands[2];
2844 op[3] = operands[3];
2850 if (GET_CODE (operands[2]) == CONST_INT)
2852 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2853 int count = INTVAL (operands[2]);
2854 int max_len = 10; /* If larger than this, always use a loop. */
2856 if (count < 8 && !scratch)
2860 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2862 if (t_len * count <= max_len)
2864 /* Output shifts inline with no loop - faster. */
2866 *len = t_len * count;
2870 output_asm_insn (template, op);
2879 strcat (str, AS2 (ldi,%3,%2));
2881 else if (use_zero_reg)
2883 /* Hack to save one word: use __zero_reg__ as loop counter.
2884 Set one bit, then shift in a loop until it is 0 again. */
2886 op[3] = zero_reg_rtx;
2890 strcat (str, ("set" CR_TAB
2891 AS2 (bld,%3,%2-1)));
2895 /* No scratch register available, use one from LD_REGS (saved in
2896 __tmp_reg__) that doesn't overlap with registers to shift. */
2898 op[3] = gen_rtx (REG, QImode,
2899 ((true_regnum (operands[0]) - 1) & 15) + 16);
2900 op[4] = tmp_reg_rtx;
2904 *len = 3; /* Includes "mov %3,%4" after the loop. */
2906 strcat (str, (AS2 (mov,%4,%3) CR_TAB
2912 else if (GET_CODE (operands[2]) == MEM)
2916 op[3] = op_mov[0] = tmp_reg_rtx;
2920 out_movqi_r_mr (insn, op_mov, len);
2922 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
2924 else if (register_operand (operands[2], QImode))
2926 if (reg_unused_after (insn, operands[2]))
2930 op[3] = tmp_reg_rtx;
2932 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
2936 fatal_insn ("bad shift insn:", insn);
2943 strcat (str, AS1 (rjmp,2f));
2947 *len += t_len + 2; /* template + dec + brXX */
2950 strcat (str, "\n1:\t");
2951 strcat (str, template);
2952 strcat (str, second_label ? "\n2:\t" : "\n\t");
2953 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
2954 strcat (str, CR_TAB);
2955 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
2957 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
2958 output_asm_insn (str, op);
2963 /* 8bit shift left ((char)x << i) */
2966 ashlqi3_out (insn, operands, len)
2969 int *len; /* insn length (may be NULL) */
2971 if (GET_CODE (operands[2]) == CONST_INT)
2978 switch (INTVAL (operands[2]))
2982 return AS1 (clr,%0);
2986 return AS1 (lsl,%0);
2990 return (AS1 (lsl,%0) CR_TAB
2995 return (AS1 (lsl,%0) CR_TAB
3000 if (test_hard_reg_class (LD_REGS, operands[0]))
3003 return (AS1 (swap,%0) CR_TAB
3004 AS2 (andi,%0,0xf0));
3007 return (AS1 (lsl,%0) CR_TAB
3013 if (test_hard_reg_class (LD_REGS, operands[0]))
3016 return (AS1 (swap,%0) CR_TAB
3018 AS2 (andi,%0,0xe0));
3021 return (AS1 (lsl,%0) CR_TAB
3028 if (test_hard_reg_class (LD_REGS, operands[0]))
3031 return (AS1 (swap,%0) CR_TAB
3034 AS2 (andi,%0,0xc0));
3037 return (AS1 (lsl,%0) CR_TAB
3046 return (AS1 (ror,%0) CR_TAB
3051 else if (CONSTANT_P (operands[2]))
3052 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3054 out_shift_with_cnt (AS1 (lsl,%0),
3055 insn, operands, len, 1);
3060 /* 16bit shift left ((short)x << i) */
3063 ashlhi3_out (insn, operands, len)
3068 if (GET_CODE (operands[2]) == CONST_INT)
3070 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3071 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3078 switch (INTVAL (operands[2]))
3081 if (optimize_size && scratch)
3086 return (AS1 (swap,%A0) CR_TAB
3087 AS1 (swap,%B0) CR_TAB
3088 AS2 (andi,%B0,0xf0) CR_TAB
3089 AS2 (eor,%B0,%A0) CR_TAB
3090 AS2 (andi,%A0,0xf0) CR_TAB
3096 return (AS1 (swap,%A0) CR_TAB
3097 AS1 (swap,%B0) CR_TAB
3098 AS2 (ldi,%3,0xf0) CR_TAB
3099 AS2 (and,%B0,%3) CR_TAB
3100 AS2 (eor,%B0,%A0) CR_TAB
3101 AS2 (and,%A0,%3) CR_TAB
3104 break; /* optimize_size ? 6 : 8 */
3108 break; /* scratch ? 5 : 6 */
3112 return (AS1 (lsl,%A0) CR_TAB
3113 AS1 (rol,%B0) CR_TAB
3114 AS1 (swap,%A0) CR_TAB
3115 AS1 (swap,%B0) CR_TAB
3116 AS2 (andi,%B0,0xf0) CR_TAB
3117 AS2 (eor,%B0,%A0) CR_TAB
3118 AS2 (andi,%A0,0xf0) CR_TAB
3124 return (AS1 (lsl,%A0) CR_TAB
3125 AS1 (rol,%B0) CR_TAB
3126 AS1 (swap,%A0) CR_TAB
3127 AS1 (swap,%B0) CR_TAB
3128 AS2 (ldi,%3,0xf0) CR_TAB
3129 AS2 (and,%B0,%3) CR_TAB
3130 AS2 (eor,%B0,%A0) CR_TAB
3131 AS2 (and,%A0,%3) CR_TAB
3138 break; /* scratch ? 5 : 6 */
3140 return (AS1 (clr,__tmp_reg__) CR_TAB
3141 AS1 (lsr,%B0) CR_TAB
3142 AS1 (ror,%A0) CR_TAB
3143 AS1 (ror,__tmp_reg__) CR_TAB
3144 AS1 (lsr,%B0) CR_TAB
3145 AS1 (ror,%A0) CR_TAB
3146 AS1 (ror,__tmp_reg__) CR_TAB
3147 AS2 (mov,%B0,%A0) CR_TAB
3148 AS2 (mov,%A0,__tmp_reg__));
3152 return (AS1 (lsr,%B0) CR_TAB
3153 AS2 (mov,%B0,%A0) CR_TAB
3154 AS1 (clr,%A0) CR_TAB
3155 AS1 (ror,%B0) CR_TAB
3159 if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
3160 return *len = 1, AS1 (clr,%A0);
3162 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3167 return (AS2 (mov,%B0,%A0) CR_TAB
3168 AS1 (clr,%A0) CR_TAB
3173 return (AS2 (mov,%B0,%A0) CR_TAB
3174 AS1 (clr,%A0) CR_TAB
3175 AS1 (lsl,%B0) CR_TAB
3180 return (AS2 (mov,%B0,%A0) CR_TAB
3181 AS1 (clr,%A0) CR_TAB
3182 AS1 (lsl,%B0) CR_TAB
3183 AS1 (lsl,%B0) CR_TAB
3190 return (AS2 (mov,%B0,%A0) CR_TAB
3191 AS1 (clr,%A0) CR_TAB
3192 AS1 (swap,%B0) CR_TAB
3193 AS2 (andi,%B0,0xf0));
3198 return (AS2 (mov,%B0,%A0) CR_TAB
3199 AS1 (clr,%A0) CR_TAB
3200 AS1 (swap,%B0) CR_TAB
3201 AS2 (ldi,%3,0xf0) CR_TAB
3205 return (AS2 (mov,%B0,%A0) CR_TAB
3206 AS1 (clr,%A0) CR_TAB
3207 AS1 (lsl,%B0) CR_TAB
3208 AS1 (lsl,%B0) CR_TAB
3209 AS1 (lsl,%B0) CR_TAB
3216 return (AS2 (mov,%B0,%A0) CR_TAB
3217 AS1 (clr,%A0) CR_TAB
3218 AS1 (swap,%B0) CR_TAB
3219 AS1 (lsl,%B0) CR_TAB
3220 AS2 (andi,%B0,0xe0));
3222 if (AVR_ENHANCED && scratch)
3225 return (AS2 (ldi,%3,0x20) CR_TAB
3226 AS2 (mul,%A0,%3) CR_TAB
3227 AS2 (mov,%B0,r0) CR_TAB
3228 AS1 (clr,%A0) CR_TAB
3229 AS1 (clr,__zero_reg__));
3231 if (optimize_size && scratch)
3236 return (AS2 (mov,%B0,%A0) CR_TAB
3237 AS1 (clr,%A0) CR_TAB
3238 AS1 (swap,%B0) CR_TAB
3239 AS1 (lsl,%B0) CR_TAB
3240 AS2 (ldi,%3,0xe0) CR_TAB
3246 return ("set" CR_TAB
3247 AS2 (bld,r1,5) CR_TAB
3248 AS2 (mul,%A0,r1) CR_TAB
3249 AS2 (mov,%B0,r0) CR_TAB
3250 AS1 (clr,%A0) CR_TAB
3251 AS1 (clr,__zero_reg__));
3254 return (AS2 (mov,%B0,%A0) CR_TAB
3255 AS1 (clr,%A0) CR_TAB
3256 AS1 (lsl,%B0) CR_TAB
3257 AS1 (lsl,%B0) CR_TAB
3258 AS1 (lsl,%B0) CR_TAB
3259 AS1 (lsl,%B0) CR_TAB
3263 if (AVR_ENHANCED && ldi_ok)
3266 return (AS2 (ldi,%B0,0x40) CR_TAB
3267 AS2 (mul,%A0,%B0) CR_TAB
3268 AS2 (mov,%B0,r0) CR_TAB
3269 AS1 (clr,%A0) CR_TAB
3270 AS1 (clr,__zero_reg__));
3272 if (AVR_ENHANCED && scratch)
3275 return (AS2 (ldi,%3,0x40) CR_TAB
3276 AS2 (mul,%A0,%3) CR_TAB
3277 AS2 (mov,%B0,r0) CR_TAB
3278 AS1 (clr,%A0) CR_TAB
3279 AS1 (clr,__zero_reg__));
3281 if (optimize_size && ldi_ok)
3284 return (AS2 (mov,%B0,%A0) CR_TAB
3285 AS2 (ldi,%A0,6) "\n1:\t"
3286 AS1 (lsl,%B0) CR_TAB
3287 AS1 (dec,%A0) CR_TAB
3290 if (optimize_size && scratch)
3293 return (AS1 (clr,%B0) CR_TAB
3294 AS1 (lsr,%A0) CR_TAB
3295 AS1 (ror,%B0) CR_TAB
3296 AS1 (lsr,%A0) CR_TAB
3297 AS1 (ror,%B0) CR_TAB
3302 return (AS1 (clr,%B0) CR_TAB
3303 AS1 (lsr,%A0) CR_TAB
3304 AS1 (ror,%B0) CR_TAB
3309 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3311 insn, operands, len, 2);
3316 /* 32bit shift left ((long)x << i) */
3319 ashlsi3_out (insn, operands, len)
3324 if (GET_CODE (operands[2]) == CONST_INT)
3332 switch (INTVAL (operands[2]))
3336 int reg0 = true_regnum (operands[0]);
3337 int reg1 = true_regnum (operands[1]);
3340 return (AS2 (mov,%D0,%C1) CR_TAB
3341 AS2 (mov,%C0,%B1) CR_TAB
3342 AS2 (mov,%B0,%A1) CR_TAB
3344 else if (reg0 + 1 == reg1)
3347 return AS1 (clr,%A0);
3350 return (AS1 (clr,%A0) CR_TAB
3351 AS2 (mov,%B0,%A1) CR_TAB
3352 AS2 (mov,%C0,%B1) CR_TAB
3358 int reg0 = true_regnum (operands[0]);
3359 int reg1 = true_regnum (operands[1]);
3361 if (AVR_ENHANCED && (reg0 + 2 != reg1))
3364 return (AS2 (movw,%C0,%A1) CR_TAB
3365 AS1 (clr,%B0) CR_TAB
3368 if (reg0 + 1 >= reg1)
3369 return (AS2 (mov,%D0,%B1) CR_TAB
3370 AS2 (mov,%C0,%A1) CR_TAB
3371 AS1 (clr,%B0) CR_TAB
3373 if (reg0 + 2 == reg1)
3376 return (AS1 (clr,%B0) CR_TAB
3380 return (AS2 (mov,%C0,%A1) CR_TAB
3381 AS2 (mov,%D0,%B1) CR_TAB
3382 AS1 (clr,%B0) CR_TAB
3388 if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
3389 return (AS2 (mov,%D0,%A1) CR_TAB
3390 AS1 (clr,%C0) CR_TAB
3391 AS1 (clr,%B0) CR_TAB
3396 return (AS1 (clr,%C0) CR_TAB
3397 AS1 (clr,%B0) CR_TAB
3403 return (AS1 (clr,%D0) CR_TAB
3404 AS1 (lsr,%A0) CR_TAB
3405 AS1 (ror,%D0) CR_TAB
3406 AS1 (clr,%C0) CR_TAB
3407 AS1 (clr,%B0) CR_TAB
3412 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3413 AS1 (rol,%B0) CR_TAB
3414 AS1 (rol,%C0) CR_TAB
3416 insn, operands, len, 4);
3420 /* 8bit arithmetic shift right ((signed char)x >> i) */
3423 ashrqi3_out (insn, operands, len)
3426 int *len; /* insn length */
3428 if (GET_CODE (operands[2]) == CONST_INT)
3435 switch (INTVAL (operands[2]))
3439 return AS1 (asr,%0);
3443 return (AS1 (asr,%0) CR_TAB
3448 return (AS1 (asr,%0) CR_TAB
3454 return (AS1 (asr,%0) CR_TAB
3461 return (AS1 (asr,%0) CR_TAB
3469 return (AS2 (bst,%0,6) CR_TAB
3471 AS2 (sbc,%0,%0) CR_TAB
3477 return (AS1 (lsl,%0) CR_TAB
3481 else if (CONSTANT_P (operands[2]))
3482 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3484 out_shift_with_cnt (AS1 (asr,%0),
3485 insn, operands, len, 1);
3490 /* 16bit arithmetic shift right ((signed short)x >> i) */
3493 ashrhi3_out (insn, operands, len)
3498 if (GET_CODE (operands[2]) == CONST_INT)
3500 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3501 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3508 switch (INTVAL (operands[2]))
3512 /* XXX try to optimize this too? */
3517 break; /* scratch ? 5 : 6 */
3519 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3520 AS2 (mov,%A0,%B0) CR_TAB
3521 AS1 (lsl,__tmp_reg__) CR_TAB
3522 AS1 (rol,%A0) CR_TAB
3523 AS2 (sbc,%B0,%B0) CR_TAB
3524 AS1 (lsl,__tmp_reg__) CR_TAB
3525 AS1 (rol,%A0) CR_TAB
3530 return (AS1 (lsl,%A0) CR_TAB
3531 AS2 (mov,%A0,%B0) CR_TAB
3532 AS1 (rol,%A0) CR_TAB
3537 int reg0 = true_regnum (operands[0]);
3538 int reg1 = true_regnum (operands[1]);
3541 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3542 AS1 (lsl,%B0) CR_TAB
3544 else if (reg0 == reg1 + 1)
3545 return *len = 3, (AS1 (clr,%B0) CR_TAB
3546 AS2 (sbrc,%A0,7) CR_TAB
3549 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3550 AS1 (clr,%B0) CR_TAB
3551 AS2 (sbrc,%A0,7) CR_TAB
3557 return (AS2 (mov,%A0,%B0) CR_TAB
3558 AS1 (lsl,%B0) CR_TAB
3559 AS2 (sbc,%B0,%B0) CR_TAB
3564 return (AS2 (mov,%A0,%B0) CR_TAB
3565 AS1 (lsl,%B0) CR_TAB
3566 AS2 (sbc,%B0,%B0) CR_TAB
3567 AS1 (asr,%A0) CR_TAB
3571 if (AVR_ENHANCED && ldi_ok)
3574 return (AS2 (ldi,%A0,0x20) CR_TAB
3575 AS2 (muls,%B0,%A0) CR_TAB
3576 AS2 (mov,%A0,r1) CR_TAB
3577 AS2 (sbc,%B0,%B0) CR_TAB
3578 AS1 (clr,__zero_reg__));
3580 if (optimize_size && scratch)
3583 return (AS2 (mov,%A0,%B0) CR_TAB
3584 AS1 (lsl,%B0) CR_TAB
3585 AS2 (sbc,%B0,%B0) CR_TAB
3586 AS1 (asr,%A0) CR_TAB
3587 AS1 (asr,%A0) CR_TAB
3591 if (AVR_ENHANCED && ldi_ok)
3594 return (AS2 (ldi,%A0,0x10) CR_TAB
3595 AS2 (muls,%B0,%A0) CR_TAB
3596 AS2 (mov,%A0,r1) CR_TAB
3597 AS2 (sbc,%B0,%B0) CR_TAB
3598 AS1 (clr,__zero_reg__));
3600 if (optimize_size && scratch)
3603 return (AS2 (mov,%A0,%B0) CR_TAB
3604 AS1 (lsl,%B0) CR_TAB
3605 AS2 (sbc,%B0,%B0) CR_TAB
3606 AS1 (asr,%A0) CR_TAB
3607 AS1 (asr,%A0) CR_TAB
3608 AS1 (asr,%A0) CR_TAB
3612 if (AVR_ENHANCED && ldi_ok)
3615 return (AS2 (ldi,%A0,0x08) CR_TAB
3616 AS2 (muls,%B0,%A0) CR_TAB
3617 AS2 (mov,%A0,r1) CR_TAB
3618 AS2 (sbc,%B0,%B0) CR_TAB
3619 AS1 (clr,__zero_reg__));
3622 break; /* scratch ? 5 : 7 */
3624 return (AS2 (mov,%A0,%B0) CR_TAB
3625 AS1 (lsl,%B0) CR_TAB
3626 AS2 (sbc,%B0,%B0) CR_TAB
3627 AS1 (asr,%A0) CR_TAB
3628 AS1 (asr,%A0) CR_TAB
3629 AS1 (asr,%A0) CR_TAB
3630 AS1 (asr,%A0) CR_TAB
3635 return (AS1 (lsl,%B0) CR_TAB
3636 AS2 (sbc,%A0,%A0) CR_TAB
3637 AS1 (lsl,%B0) CR_TAB
3638 AS2 (mov,%B0,%A0) CR_TAB
3642 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3643 AS2 (sbc,%A0,%A0) CR_TAB
3648 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3650 insn, operands, len, 2);
3655 /* 32bit arithmetic shift right ((signed long)x >> i) */
3658 ashrsi3_out (insn, operands, len)
3663 if (GET_CODE (operands[2]) == CONST_INT)
3671 switch (INTVAL (operands[2]))
3675 int reg0 = true_regnum (operands[0]);
3676 int reg1 = true_regnum (operands[1]);
3679 return (AS2 (mov,%A0,%B1) CR_TAB
3680 AS2 (mov,%B0,%C1) CR_TAB
3681 AS2 (mov,%C0,%D1) CR_TAB
3682 AS1 (clr,%D0) CR_TAB
3683 AS2 (sbrc,%C0,7) CR_TAB
3685 else if (reg0 == reg1 + 1)
3688 return (AS1 (clr,%D0) CR_TAB
3689 AS2 (sbrc,%C0,7) CR_TAB
3693 return (AS1 (clr,%D0) CR_TAB
3694 AS2 (sbrc,%D1,7) CR_TAB
3695 AS1 (dec,%D0) CR_TAB
3696 AS2 (mov,%C0,%D1) CR_TAB
3697 AS2 (mov,%B0,%C1) CR_TAB
3703 int reg0 = true_regnum (operands[0]);
3704 int reg1 = true_regnum (operands[1]);
3706 if (AVR_ENHANCED && (reg0 != reg1 + 2))
3709 return (AS2 (movw,%A0,%C1) CR_TAB
3710 AS1 (clr,%D0) CR_TAB
3711 AS2 (sbrc,%B0,7) CR_TAB
3712 AS1 (com,%D0) CR_TAB
3715 if (reg0 <= reg1 + 1)
3716 return (AS2 (mov,%A0,%C1) CR_TAB
3717 AS2 (mov,%B0,%D1) CR_TAB
3718 AS1 (clr,%D0) CR_TAB
3719 AS2 (sbrc,%B0,7) CR_TAB
3720 AS1 (com,%D0) CR_TAB
3722 else if (reg0 == reg1 + 2)
3723 return *len = 4, (AS1 (clr,%D0) CR_TAB
3724 AS2 (sbrc,%B0,7) CR_TAB
3725 AS1 (com,%D0) CR_TAB
3728 return (AS2 (mov,%B0,%D1) CR_TAB
3729 AS2 (mov,%A0,%C1) CR_TAB
3730 AS1 (clr,%D0) CR_TAB
3731 AS2 (sbrc,%B0,7) CR_TAB
3732 AS1 (com,%D0) CR_TAB
3737 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
3738 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3739 AS1 (clr,%D0) CR_TAB
3740 AS2 (sbrc,%A0,7) CR_TAB
3741 AS1 (com,%D0) CR_TAB
3742 AS2 (mov,%B0,%D0) CR_TAB
3745 return *len = 5, (AS1 (clr,%D0) CR_TAB
3746 AS2 (sbrc,%A0,7) CR_TAB
3747 AS1 (com,%D0) CR_TAB
3748 AS2 (mov,%B0,%D0) CR_TAB
3753 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3754 AS2 (sbc,%A0,%A0) CR_TAB
3755 AS2 (mov,%B0,%A0) CR_TAB
3756 AS2 (movw,%C0,%A0));
3758 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3759 AS2 (sbc,%A0,%A0) CR_TAB
3760 AS2 (mov,%B0,%A0) CR_TAB
3761 AS2 (mov,%C0,%A0) CR_TAB
3766 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3767 AS1 (ror,%C0) CR_TAB
3768 AS1 (ror,%B0) CR_TAB
3770 insn, operands, len, 4);
3774 /* 8bit logic shift right ((unsigned char)x >> i) */
3777 lshrqi3_out (insn, operands, len)
3782 if (GET_CODE (operands[2]) == CONST_INT)
3789 switch (INTVAL (operands[2]))
3793 return AS1 (clr,%0);
3797 return AS1 (lsr,%0);
3801 return (AS1 (lsr,%0) CR_TAB
3805 return (AS1 (lsr,%0) CR_TAB
3810 if (test_hard_reg_class (LD_REGS, operands[0]))
3813 return (AS1 (swap,%0) CR_TAB
3814 AS2 (andi,%0,0x0f));
3817 return (AS1 (lsr,%0) CR_TAB
3823 if (test_hard_reg_class (LD_REGS, operands[0]))
3826 return (AS1 (swap,%0) CR_TAB
3831 return (AS1 (lsr,%0) CR_TAB
3838 if (test_hard_reg_class (LD_REGS, operands[0]))
3841 return (AS1 (swap,%0) CR_TAB
3847 return (AS1 (lsr,%0) CR_TAB
3856 return (AS1 (rol,%0) CR_TAB
3861 else if (CONSTANT_P (operands[2]))
3862 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3864 out_shift_with_cnt (AS1 (lsr,%0),
3865 insn, operands, len, 1);
3869 /* 16bit logic shift right ((unsigned short)x >> i) */
3872 lshrhi3_out (insn, operands, len)
3877 if (GET_CODE (operands[2]) == CONST_INT)
3879 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3880 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3887 switch (INTVAL (operands[2]))
3890 if (optimize_size && scratch)
3895 return (AS1 (swap,%B0) CR_TAB
3896 AS1 (swap,%A0) CR_TAB
3897 AS2 (andi,%A0,0x0f) CR_TAB
3898 AS2 (eor,%A0,%B0) CR_TAB
3899 AS2 (andi,%B0,0x0f) CR_TAB
3905 return (AS1 (swap,%B0) CR_TAB
3906 AS1 (swap,%A0) CR_TAB
3907 AS2 (ldi,%3,0x0f) CR_TAB
3908 AS2 (and,%A0,%3) CR_TAB
3909 AS2 (eor,%A0,%B0) CR_TAB
3910 AS2 (and,%B0,%3) CR_TAB
3913 break; /* optimize_size ? 6 : 8 */
3917 break; /* scratch ? 5 : 6 */
3921 return (AS1 (lsr,%B0) CR_TAB
3922 AS1 (ror,%A0) CR_TAB
3923 AS1 (swap,%B0) CR_TAB
3924 AS1 (swap,%A0) CR_TAB
3925 AS2 (andi,%A0,0x0f) CR_TAB
3926 AS2 (eor,%A0,%B0) CR_TAB
3927 AS2 (andi,%B0,0x0f) CR_TAB
3933 return (AS1 (lsr,%B0) CR_TAB
3934 AS1 (ror,%A0) CR_TAB
3935 AS1 (swap,%B0) CR_TAB
3936 AS1 (swap,%A0) CR_TAB
3937 AS2 (ldi,%3,0x0f) CR_TAB
3938 AS2 (and,%A0,%3) CR_TAB
3939 AS2 (eor,%A0,%B0) CR_TAB
3940 AS2 (and,%B0,%3) CR_TAB
3947 break; /* scratch ? 5 : 6 */
3949 return (AS1 (clr,__tmp_reg__) CR_TAB
3950 AS1 (lsl,%A0) CR_TAB
3951 AS1 (rol,%B0) CR_TAB
3952 AS1 (rol,__tmp_reg__) CR_TAB
3953 AS1 (lsl,%A0) CR_TAB
3954 AS1 (rol,%B0) CR_TAB
3955 AS1 (rol,__tmp_reg__) CR_TAB
3956 AS2 (mov,%A0,%B0) CR_TAB
3957 AS2 (mov,%B0,__tmp_reg__));
3961 return (AS1 (lsl,%A0) CR_TAB
3962 AS2 (mov,%A0,%B0) CR_TAB
3963 AS1 (rol,%A0) CR_TAB
3964 AS2 (sbc,%B0,%B0) CR_TAB
3968 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
3969 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
3972 return *len = 1, AS1 (clr,%B0);
3976 return (AS2 (mov,%A0,%B0) CR_TAB
3977 AS1 (clr,%B0) CR_TAB
3982 return (AS2 (mov,%A0,%B0) CR_TAB
3983 AS1 (clr,%B0) CR_TAB
3984 AS1 (lsr,%A0) CR_TAB
3989 return (AS2 (mov,%A0,%B0) CR_TAB
3990 AS1 (clr,%B0) CR_TAB
3991 AS1 (lsr,%A0) CR_TAB
3992 AS1 (lsr,%A0) CR_TAB
3999 return (AS2 (mov,%A0,%B0) CR_TAB
4000 AS1 (clr,%B0) CR_TAB
4001 AS1 (swap,%A0) CR_TAB
4002 AS2 (andi,%A0,0x0f));
4007 return (AS2 (mov,%A0,%B0) CR_TAB
4008 AS1 (clr,%B0) CR_TAB
4009 AS1 (swap,%A0) CR_TAB
4010 AS2 (ldi,%3,0x0f) CR_TAB
4014 return (AS2 (mov,%A0,%B0) CR_TAB
4015 AS1 (clr,%B0) CR_TAB
4016 AS1 (lsr,%A0) CR_TAB
4017 AS1 (lsr,%A0) CR_TAB
4018 AS1 (lsr,%A0) CR_TAB
4025 return (AS2 (mov,%A0,%B0) CR_TAB
4026 AS1 (clr,%B0) CR_TAB
4027 AS1 (swap,%A0) CR_TAB
4028 AS1 (lsr,%A0) CR_TAB
4029 AS2 (andi,%A0,0x07));
4031 if (AVR_ENHANCED && scratch)
4034 return (AS2 (ldi,%3,0x08) CR_TAB
4035 AS2 (mul,%B0,%3) CR_TAB
4036 AS2 (mov,%A0,r1) CR_TAB
4037 AS1 (clr,%B0) CR_TAB
4038 AS1 (clr,__zero_reg__));
4040 if (optimize_size && scratch)
4045 return (AS2 (mov,%A0,%B0) CR_TAB
4046 AS1 (clr,%B0) CR_TAB
4047 AS1 (swap,%A0) CR_TAB
4048 AS1 (lsr,%A0) CR_TAB
4049 AS2 (ldi,%3,0x07) CR_TAB
4055 return ("set" CR_TAB
4056 AS2 (bld,r1,3) CR_TAB
4057 AS2 (mul,%B0,r1) CR_TAB
4058 AS2 (mov,%A0,r1) CR_TAB
4059 AS1 (clr,%B0) CR_TAB
4060 AS1 (clr,__zero_reg__));
4063 return (AS2 (mov,%A0,%B0) CR_TAB
4064 AS1 (clr,%B0) CR_TAB
4065 AS1 (lsr,%A0) CR_TAB
4066 AS1 (lsr,%A0) CR_TAB
4067 AS1 (lsr,%A0) CR_TAB
4068 AS1 (lsr,%A0) CR_TAB
4072 if (AVR_ENHANCED && ldi_ok)
4075 return (AS2 (ldi,%A0,0x04) CR_TAB
4076 AS2 (mul,%B0,%A0) CR_TAB
4077 AS2 (mov,%A0,r1) CR_TAB
4078 AS1 (clr,%B0) CR_TAB
4079 AS1 (clr,__zero_reg__));
4081 if (AVR_ENHANCED && scratch)
4084 return (AS2 (ldi,%3,0x04) CR_TAB
4085 AS2 (mul,%B0,%3) CR_TAB
4086 AS2 (mov,%A0,r1) CR_TAB
4087 AS1 (clr,%B0) CR_TAB
4088 AS1 (clr,__zero_reg__));
4090 if (optimize_size && ldi_ok)
4093 return (AS2 (mov,%A0,%B0) CR_TAB
4094 AS2 (ldi,%B0,6) "\n1:\t"
4095 AS1 (lsr,%A0) CR_TAB
4096 AS1 (dec,%B0) CR_TAB
4099 if (optimize_size && scratch)
4102 return (AS1 (clr,%A0) CR_TAB
4103 AS1 (lsl,%B0) CR_TAB
4104 AS1 (rol,%A0) CR_TAB
4105 AS1 (lsl,%B0) CR_TAB
4106 AS1 (rol,%A0) CR_TAB
4111 return (AS1 (clr,%A0) CR_TAB
4112 AS1 (lsl,%B0) CR_TAB
4113 AS1 (rol,%A0) CR_TAB
4118 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4120 insn, operands, len, 2);
4124 /* 32bit logic shift right ((unsigned int)x >> i) */
4127 lshrsi3_out (insn, operands, len)
4132 if (GET_CODE (operands[2]) == CONST_INT)
4140 switch (INTVAL (operands[2]))
4144 int reg0 = true_regnum (operands[0]);
4145 int reg1 = true_regnum (operands[1]);
4148 return (AS2 (mov,%A0,%B1) CR_TAB
4149 AS2 (mov,%B0,%C1) CR_TAB
4150 AS2 (mov,%C0,%D1) CR_TAB
4152 else if (reg0 == reg1 + 1)
4153 return *len = 1, AS1 (clr,%D0);
4155 return (AS1 (clr,%D0) CR_TAB
4156 AS2 (mov,%C0,%D1) CR_TAB
4157 AS2 (mov,%B0,%C1) CR_TAB
4163 int reg0 = true_regnum (operands[0]);
4164 int reg1 = true_regnum (operands[1]);
4166 if (AVR_ENHANCED && (reg0 != reg1 + 2))
4169 return (AS2 (movw,%A0,%C1) CR_TAB
4170 AS1 (clr,%C0) CR_TAB
4173 if (reg0 <= reg1 + 1)
4174 return (AS2 (mov,%A0,%C1) CR_TAB
4175 AS2 (mov,%B0,%D1) CR_TAB
4176 AS1 (clr,%C0) CR_TAB
4178 else if (reg0 == reg1 + 2)
4179 return *len = 2, (AS1 (clr,%C0) CR_TAB
4182 return (AS2 (mov,%B0,%D1) CR_TAB
4183 AS2 (mov,%A0,%C1) CR_TAB
4184 AS1 (clr,%C0) CR_TAB
4189 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
4190 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4191 AS1 (clr,%B0) CR_TAB
4192 AS1 (clr,%C0) CR_TAB
4195 return *len = 3, (AS1 (clr,%B0) CR_TAB
4196 AS1 (clr,%C0) CR_TAB
4201 return (AS1 (clr,%A0) CR_TAB
4202 AS2 (sbrc,%D0,7) CR_TAB
4203 AS1 (inc,%A0) CR_TAB
4204 AS1 (clr,%B0) CR_TAB
4205 AS1 (clr,%C0) CR_TAB
4210 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4211 AS1 (ror,%C0) CR_TAB
4212 AS1 (ror,%B0) CR_TAB
4214 insn, operands, len, 4);
4218 /* Modifies the length assigned to instruction INSN
4219 LEN is the initially computed length of the insn. */
4222 adjust_insn_length (insn, len)
4226 rtx patt = PATTERN (insn);
4229 if (GET_CODE (patt) == SET)
4232 op[1] = SET_SRC (patt);
4233 op[0] = SET_DEST (patt);
4234 if (general_operand (op[1], VOIDmode)
4235 && general_operand (op[0], VOIDmode))
4237 switch (GET_MODE (op[0]))
4240 output_movqi (insn, op, &len);
4243 output_movhi (insn, op, &len);
4247 output_movsisf (insn, op, &len);
4253 else if (op[0] == cc0_rtx && REG_P (op[1]))
4255 switch (GET_MODE (op[1]))
4257 case HImode: out_tsthi (insn,&len); break;
4258 case SImode: out_tstsi (insn,&len); break;
4262 else if (GET_CODE (op[1]) == AND)
4264 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4266 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4267 if (GET_MODE (op[1]) == SImode)
4268 len = (((mask & 0xff) != 0xff)
4269 + ((mask & 0xff00) != 0xff00)
4270 + ((mask & 0xff0000L) != 0xff0000L)
4271 + ((mask & 0xff000000L) != 0xff000000L));
4272 else if (GET_MODE (op[1]) == HImode)
4273 len = (((mask & 0xff) != 0xff)
4274 + ((mask & 0xff00) != 0xff00));
4277 else if (GET_CODE (op[1]) == IOR)
4279 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4281 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4282 if (GET_MODE (op[1]) == SImode)
4283 len = (((mask & 0xff) != 0)
4284 + ((mask & 0xff00) != 0)
4285 + ((mask & 0xff0000L) != 0)
4286 + ((mask & 0xff000000L) != 0));
4287 else if (GET_MODE (op[1]) == HImode)
4288 len = (((mask & 0xff) != 0)
4289 + ((mask & 0xff00) != 0));
4293 set = single_set (insn);
4298 op[1] = SET_SRC (set);
4299 op[0] = SET_DEST (set);
4301 if (GET_CODE (patt) == PARALLEL
4302 && general_operand (op[1], VOIDmode)
4303 && general_operand (op[0], VOIDmode))
4305 if (XVECLEN (patt, 0) == 2)
4306 op[2] = XVECEXP (patt, 0, 1);
4308 switch (GET_MODE (op[0]))
4314 output_reload_inhi (insn, op, &len);
4318 output_reload_insisf (insn, op, &len);
4324 else if (GET_CODE (op[1]) == ASHIFT
4325 || GET_CODE (op[1]) == ASHIFTRT
4326 || GET_CODE (op[1]) == LSHIFTRT)
4330 ops[1] = XEXP (op[1],0);
4331 ops[2] = XEXP (op[1],1);
4332 switch (GET_CODE (op[1]))
4335 switch (GET_MODE (op[0]))
4337 case QImode: ashlqi3_out (insn,ops,&len); break;
4338 case HImode: ashlhi3_out (insn,ops,&len); break;
4339 case SImode: ashlsi3_out (insn,ops,&len); break;
4344 switch (GET_MODE (op[0]))
4346 case QImode: ashrqi3_out (insn,ops,&len); break;
4347 case HImode: ashrhi3_out (insn,ops,&len); break;
4348 case SImode: ashrsi3_out (insn,ops,&len); break;
4353 switch (GET_MODE (op[0]))
4355 case QImode: lshrqi3_out (insn,ops,&len); break;
4356 case HImode: lshrhi3_out (insn,ops,&len); break;
4357 case SImode: lshrsi3_out (insn,ops,&len); break;
4369 /* Return nonzero if register REG dead after INSN */
4372 reg_unused_after (insn, reg)
4376 return (dead_or_set_p (insn, reg)
4377 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4380 /* Return nonzero if REG is not used after INSN.
4381 We assume REG is a reload reg, and therefore does
4382 not live past labels. It may live past calls or jumps though. */
4385 _reg_unused_after (insn, reg)
4392 /* If the reg is set by this instruction, then it is safe for our
4393 case. Disregard the case where this is a store to memory, since
4394 we are checking a register used in the store address. */
4395 set = single_set (insn);
4396 if (set && GET_CODE (SET_DEST (set)) != MEM
4397 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4400 while ((insn = NEXT_INSN (insn)))
4402 code = GET_CODE (insn);
4405 /* If this is a label that existed before reload, then the register
4406 if dead here. However, if this is a label added by reorg, then
4407 the register may still be live here. We can't tell the difference,
4408 so we just ignore labels completely. */
4409 if (code == CODE_LABEL)
4414 if (code == JUMP_INSN)
4417 /* If this is a sequence, we must handle them all at once.
4418 We could have for instance a call that sets the target register,
4419 and an insn in a delay slot that uses the register. In this case,
4420 we must return 0. */
4421 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4426 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4428 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4429 rtx set = single_set (this_insn);
4431 if (GET_CODE (this_insn) == CALL_INSN)
4433 else if (GET_CODE (this_insn) == JUMP_INSN)
4435 if (INSN_ANNULLED_BRANCH_P (this_insn))
4440 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4442 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4444 if (GET_CODE (SET_DEST (set)) != MEM)
4450 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4455 else if (code == JUMP_INSN)
4459 if (code == CALL_INSN)
4462 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4463 if (GET_CODE (XEXP (tem, 0)) == USE
4464 && REG_P (XEXP (XEXP (tem, 0), 0))
4465 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4467 if (call_used_regs[REGNO (reg)])
4471 if (GET_RTX_CLASS (code) == 'i')
4473 rtx set = single_set (insn);
4475 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4477 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4478 return GET_CODE (SET_DEST (set)) != MEM;
4479 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4486 /* Target hook for assembling integer objects. The AVR version needs
4487 special handling for references to certain labels. */
4490 avr_assemble_integer (x, size, aligned_p)
4495 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
4496 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
4497 || GET_CODE (x) == LABEL_REF))
4499 fputs ("\t.word\tpm(", asm_out_file);
4500 output_addr_const (asm_out_file, x);
4501 fputs (")\n", asm_out_file);
4504 return default_assemble_integer (x, size, aligned_p);
4507 /* Sets section name for declaration DECL */
4510 avr_unique_section (decl, reloc)
4512 int reloc ATTRIBUTE_UNUSED;
4515 const char *name, *prefix;
4518 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
4519 name = (* targetm.strip_name_encoding) (name);
4521 if (TREE_CODE (decl) == FUNCTION_DECL)
4523 if (flag_function_sections)
4531 if (flag_function_sections)
4533 len = strlen (name) + strlen (prefix);
4534 string = alloca (len + 1);
4535 sprintf (string, "%s%s", prefix, name);
4536 DECL_SECTION_NAME (decl) = build_string (len, string);
4541 /* The routine used to output NUL terminated strings. We use a special
4542 version of this for most svr4 targets because doing so makes the
4543 generated assembly code more compact (and thus faster to assemble)
4544 as well as more readable, especially for targets like the i386
4545 (where the only alternative is to output character sequences as
4546 comma separated lists of numbers). */
4549 gas_output_limited_string(file, str)
4553 const unsigned char *_limited_str = (unsigned char *) str;
4555 fprintf (file, "%s\"", STRING_ASM_OP);
4556 for (; (ch = *_limited_str); _limited_str++)
4559 switch (escape = ESCAPES[ch])
4565 fprintf (file, "\\%03o", ch);
4569 putc (escape, file);
4573 fprintf (file, "\"\n");
4576 /* The routine used to output sequences of byte values. We use a special
4577 version of this for most svr4 targets because doing so makes the
4578 generated assembly code more compact (and thus faster to assemble)
4579 as well as more readable. Note that if we find subparts of the
4580 character sequence which end with NUL (and which are shorter than
4581 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4584 gas_output_ascii(file, str, length)
4589 const unsigned char *_ascii_bytes = (const unsigned char *) str;
4590 const unsigned char *limit = _ascii_bytes + length;
4591 unsigned bytes_in_chunk = 0;
4592 for (; _ascii_bytes < limit; _ascii_bytes++)
4594 const unsigned char *p;
4595 if (bytes_in_chunk >= 60)
4597 fprintf (file, "\"\n");
4600 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4602 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4604 if (bytes_in_chunk > 0)
4606 fprintf (file, "\"\n");
4609 gas_output_limited_string (file, (char*)_ascii_bytes);
4616 if (bytes_in_chunk == 0)
4617 fprintf (file, "\t.ascii\t\"");
4618 switch (escape = ESCAPES[ch = *_ascii_bytes])
4625 fprintf (file, "\\%03o", ch);
4626 bytes_in_chunk += 4;
4630 putc (escape, file);
4631 bytes_in_chunk += 2;
4636 if (bytes_in_chunk > 0)
4637 fprintf (file, "\"\n");
4640 /* Return value is nonzero if pseudos that have been
4641 assigned to registers of class CLASS would likely be spilled
4642 because registers of CLASS are needed for spill registers. */
4645 class_likely_spilled_p (c)
4648 return (c != ALL_REGS && c != ADDW_REGS);
4651 /* Valid attributes:
4652 progmem - put data to program memory;
4653 signal - make a function to be hardware interrupt. After function
4654 prologue interrupts are disabled;
4655 interrupt - make a function to be hardware interrupt. After function
4656 prologue interrupts are enabled;
4657 naked - don't generate function prologue/epilogue and `ret' command.
4659 Only `progmem' attribute valid for type. */
4661 const struct attribute_spec avr_attribute_table[] =
4663 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4664 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
4665 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4666 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4667 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4668 { NULL, 0, 0, false, false, false, NULL }
4671 /* Handle a "progmem" attribute; arguments as in
4672 struct attribute_spec.handler. */
4674 avr_handle_progmem_attribute (node, name, args, flags, no_add_attrs)
4677 tree args ATTRIBUTE_UNUSED;
4678 int flags ATTRIBUTE_UNUSED;
4683 if (TREE_CODE (*node) == TYPE_DECL)
4685 /* This is really a decl attribute, not a type attribute,
4686 but try to handle it for GCC 3.0 backwards compatibility. */
4688 tree type = TREE_TYPE (*node);
4689 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
4690 tree newtype = build_type_attribute_variant (type, attr);
4692 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
4693 TREE_TYPE (*node) = newtype;
4694 *no_add_attrs = true;
4696 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
4698 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
4700 warning ("only initialized variables can be placed into "
4701 "program memory area");
4702 *no_add_attrs = true;
4707 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
4708 *no_add_attrs = true;
4715 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4716 struct attribute_spec.handler. */
4718 avr_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
4721 tree args ATTRIBUTE_UNUSED;
4722 int flags ATTRIBUTE_UNUSED;
4725 if (TREE_CODE (*node) != FUNCTION_DECL)
4727 warning ("`%s' attribute only applies to functions",
4728 IDENTIFIER_POINTER (name));
4729 *no_add_attrs = true;
4735 /* Look for attribute `progmem' in DECL
4736 if found return 1, otherwise 0. */
4739 avr_progmem_p (decl)
4744 if (TREE_CODE (decl) != VAR_DECL)
4748 != lookup_attribute ("progmem", DECL_ATTRIBUTES (decl)))
4754 while (TREE_CODE (a) == ARRAY_TYPE);
4756 if (a == error_mark_node)
4759 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4765 /* Add the section attribute if the variable is in progmem. */
4768 avr_insert_attributes (node, attributes)
4772 if (TREE_CODE (node) == VAR_DECL
4773 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
4774 && avr_progmem_p (node))
4776 static const char dsec[] = ".progmem.data";
4777 *attributes = tree_cons (get_identifier ("section"),
4778 build_tree_list (NULL, build_string (strlen (dsec), dsec)),
4781 /* ??? This seems sketchy. Why can't the user declare the
4782 thing const in the first place? */
4783 TREE_READONLY (node) = 1;
4788 avr_section_type_flags (decl, name, reloc)
4793 unsigned int flags = default_section_type_flags (decl, name, reloc);
4795 if (strncmp (name, ".noinit", 7) == 0)
4797 if (decl && TREE_CODE (decl) == VAR_DECL
4798 && DECL_INITIAL (decl) == NULL_TREE)
4799 flags |= SECTION_BSS; /* @nobits */
4801 warning ("only uninitialized variables can be placed in the "
4808 /* Outputs some appropriate text to go at the start of an assembler
4815 error ("MCU `%s' supported for assembler only", avr_mcu_name);
4817 default_file_start ();
4819 fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);
4820 fputs ("__SREG__ = 0x3f\n"
4822 "__SP_L__ = 0x3d\n", asm_out_file);
4824 fputs ("__tmp_reg__ = 0\n"
4825 "__zero_reg__ = 1\n", asm_out_file);
4827 /* FIXME: output these only if there is anything in the .data / .bss
4828 sections - some code size could be saved by not linking in the
4829 initialization code from libgcc if one or both sections are empty. */
4830 fputs ("\t.global __do_copy_data\n", asm_out_file);
4831 fputs ("\t.global __do_clear_bss\n", asm_out_file);
4833 commands_in_file = 0;
4834 commands_in_prologues = 0;
4835 commands_in_epilogues = 0;
4838 /* Outputs to the stdio stream FILE some
4839 appropriate text to go at the end of an assembler file. */
4844 fputs ("/* File ", asm_out_file);
4845 output_quoted_string (asm_out_file, main_input_filename);
4846 fprintf (asm_out_file,
4847 ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4850 commands_in_file - commands_in_prologues - commands_in_epilogues,
4851 commands_in_prologues, commands_in_epilogues);
4854 /* Choose the order in which to allocate hard registers for
4855 pseudo-registers local to a basic block.
4857 Store the desired register order in the array `reg_alloc_order'.
4858 Element 0 should be the register to allocate first; element 1, the
4859 next register; and so on. */
4862 order_regs_for_local_alloc ()
4865 static const int order_0[] = {
4873 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4877 static const int order_1[] = {
4885 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4889 static const int order_2[] = {
4898 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4903 const int *order = (TARGET_ORDER_1 ? order_1 :
4904 TARGET_ORDER_2 ? order_2 :
4906 for (i=0; i < ARRAY_SIZE (order_0); ++i)
4907 reg_alloc_order[i] = order[i];
4910 /* Calculate the cost of X code of the expression in which it is contained,
4911 found in OUTER_CODE */
4914 default_rtx_costs (X, code, outer_code)
4917 enum rtx_code outer_code;
4924 cost = 2 * GET_MODE_SIZE (GET_MODE (X));
4927 if (outer_code != SET)
4929 if (GET_CODE (XEXP (X,0)) == SYMBOL_REF)
4930 cost += 2 * GET_MODE_SIZE (GET_MODE (X));
4932 cost += GET_MODE_SIZE (GET_MODE (X));
4938 if (outer_code == SET)
4939 cost = GET_MODE_SIZE (GET_MODE (X));
4941 cost = -GET_MODE_SIZE (GET_MODE (X));
4944 if (outer_code == SET)
4945 cost = GET_MODE_SIZE (GET_MODE (X));
4951 if (outer_code == SET)
4953 if (X == stack_pointer_rtx)
4955 else if (GET_CODE (XEXP (X,1)) == CONST_INT)
4956 cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 :
4957 GET_MODE_SIZE (GET_MODE (X)));
4959 cost = GET_MODE_SIZE (GET_MODE (X));
4963 if (GET_CODE (XEXP (X,1)) == CONST_INT)
4964 cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0)));
4973 avr_rtx_costs (x, code, outer_code, total)
4975 int code, outer_code;
4983 if (outer_code == PLUS
4984 || outer_code == IOR
4985 || outer_code == AND
4986 || outer_code == MINUS
4987 || outer_code == SET
4993 if (outer_code == COMPARE
4995 && INTVAL (x) <= 255)
5010 cst = default_rtx_costs (x, code, outer_code);
5022 /* Calculate the cost of a memory address */
5025 avr_address_cost (x)
5028 if (GET_CODE (x) == PLUS
5029 && GET_CODE (XEXP (x,1)) == CONST_INT
5030 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
5031 && INTVAL (XEXP (x,1)) >= 61)
5033 if (CONSTANT_ADDRESS_P (x))
5035 if (avr_io_address_p (x, 1))
5042 /* EXTRA_CONSTRAINT helper */
5045 extra_constraint (x, c)
5050 && GET_CODE (x) == MEM
5051 && GET_CODE (XEXP (x,0)) == PLUS)
5053 if (TARGET_ALL_DEBUG)
5055 fprintf (stderr, ("extra_constraint:\n"
5056 "reload_completed: %d\n"
5057 "reload_in_progress: %d\n"),
5058 reload_completed, reload_in_progress);
5061 if (GET_CODE (x) == MEM
5062 && GET_CODE (XEXP (x,0)) == PLUS
5063 && REG_P (XEXP (XEXP (x,0), 0))
5064 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
5065 && (INTVAL (XEXP (XEXP (x,0), 1))
5066 <= MAX_LD_OFFSET (GET_MODE (x))))
5068 rtx xx = XEXP (XEXP (x,0), 0);
5069 int regno = REGNO (xx);
5070 if (TARGET_ALL_DEBUG)
5072 fprintf (stderr, ("extra_constraint:\n"
5073 "reload_completed: %d\n"
5074 "reload_in_progress: %d\n"),
5075 reload_completed, reload_in_progress);
5078 if (regno >= FIRST_PSEUDO_REGISTER)
5079 return 1; /* allocate pseudos */
5080 else if (regno == REG_Z || regno == REG_Y)
5081 return 1; /* strictly check */
5082 else if (xx == frame_pointer_rtx
5083 || xx == arg_pointer_rtx)
5084 return 1; /* XXX frame & arg pointer checks */
5090 /* Convert condition code CONDITION to the valid AVR condition code */
5093 avr_normalize_condition (condition)
5111 /* This function optimizes conditional jumps. */
5118 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5120 if (! (GET_CODE (insn) == INSN
5121 || GET_CODE (insn) == CALL_INSN
5122 || GET_CODE (insn) == JUMP_INSN)
5123 || !single_set (insn))
5126 pattern = PATTERN (insn);
5128 if (GET_CODE (pattern) == PARALLEL)
5129 pattern = XVECEXP (pattern, 0, 0);
5130 if (GET_CODE (pattern) == SET
5131 && SET_DEST (pattern) == cc0_rtx
5132 && compare_diff_p (insn))
5134 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
5136 /* Now we work under compare insn */
5138 pattern = SET_SRC (pattern);
5139 if (true_regnum (XEXP (pattern,0)) >= 0
5140 && true_regnum (XEXP (pattern,1)) >= 0 )
5142 rtx x = XEXP (pattern,0);
5143 rtx next = next_real_insn (insn);
5144 rtx pat = PATTERN (next);
5145 rtx src = SET_SRC (pat);
5146 rtx t = XEXP (src,0);
5147 PUT_CODE (t, swap_condition (GET_CODE (t)));
5148 XEXP (pattern,0) = XEXP (pattern,1);
5149 XEXP (pattern,1) = x;
5150 INSN_CODE (next) = -1;
5152 else if (true_regnum (XEXP (pattern,0)) >= 0
5153 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
5155 rtx x = XEXP (pattern,1);
5156 rtx next = next_real_insn (insn);
5157 rtx pat = PATTERN (next);
5158 rtx src = SET_SRC (pat);
5159 rtx t = XEXP (src,0);
5160 enum machine_mode mode = GET_MODE (XEXP (pattern, 0));
5162 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
5164 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
5165 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
5166 INSN_CODE (next) = -1;
5167 INSN_CODE (insn) = -1;
5171 else if (true_regnum (SET_SRC (pattern)) >= 0)
5173 /* This is a tst insn */
5174 rtx next = next_real_insn (insn);
5175 rtx pat = PATTERN (next);
5176 rtx src = SET_SRC (pat);
5177 rtx t = XEXP (src,0);
5179 PUT_CODE (t, swap_condition (GET_CODE (t)));
5180 SET_SRC (pattern) = gen_rtx (NEG,
5181 GET_MODE (SET_SRC (pattern)),
5183 INSN_CODE (next) = -1;
5184 INSN_CODE (insn) = -1;
5190 /* Returns register number for function return value.*/
5198 /* Ceate an RTX representing the place where a
5199 library function returns a value of mode MODE. */
5202 avr_libcall_value (mode)
5203 enum machine_mode mode;
5205 int offs = GET_MODE_SIZE (mode);
5208 return gen_rtx (REG, mode, RET_REGISTER + 2 - offs);
5211 /* Create an RTX representing the place where a
5212 function returns a value of data type VALTYPE. */
5215 avr_function_value (type, func)
5217 tree func ATTRIBUTE_UNUSED;
5221 if (TYPE_MODE (type) != BLKmode)
5222 return avr_libcall_value (TYPE_MODE (type));
5224 offs = int_size_in_bytes (type);
5227 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5228 offs = GET_MODE_SIZE (SImode);
5229 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5230 offs = GET_MODE_SIZE (DImode);
5232 return gen_rtx (REG, BLKmode, RET_REGISTER + 2 - offs);
5235 /* Returns nonzero if the number MASK has only one bit set. */
5238 mask_one_bit_p (mask)
5242 unsigned HOST_WIDE_INT n=mask;
5243 for (i = 0; i < 32; ++i)
5245 if (n & 0x80000000L)
5247 if (n & 0x7fffffffL)
5258 /* Places additional restrictions on the register class to
5259 use when it is necessary to copy value X into a register
5263 preferred_reload_class (x, class)
5264 rtx x ATTRIBUTE_UNUSED;
5265 enum reg_class class;
5271 test_hard_reg_class (class, x)
5272 enum reg_class class;
5275 int regno = true_regnum (x);
5279 if (TEST_HARD_REG_CLASS (class, regno))
5287 jump_over_one_insn_p (insn, dest)
5291 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5294 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5295 int dest_addr = INSN_ADDRESSES (uid);
5296 return dest_addr - jump_addr == get_attr_length (insn) + 1;
5299 /* Returns 1 if a value of mode MODE can be stored starting with hard
5300 register number REGNO. On the enhanced core, anything larger than
5301 1 byte must start in even numbered register for "movw" to work
5302 (this way we don't have to check for odd registers everywhere). */
5305 avr_hard_regno_mode_ok (regno, mode)
5307 enum machine_mode mode;
5309 /* Bug workaround: recog.c (peep2_find_free_register) and probably
5310 a few other places assume that the frame pointer is a single hard
5311 register, so r29 may be allocated and overwrite the high byte of
5312 the frame pointer. Do not allow any value to start in r29. */
5313 if (regno == REG_Y + 1)
5318 /* if (regno < 24 && !AVR_ENHANCED)
5320 return !(regno & 1);
5323 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5324 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5325 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
5328 avr_io_address_p (x, size)
5332 return (optimize > 0 && GET_CODE (x) == CONST_INT
5333 && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
5336 /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5339 const_int_pow2_p (x)
5342 if (GET_CODE (x) == CONST_INT)
5344 HOST_WIDE_INT d = INTVAL (x);
5345 HOST_WIDE_INT abs_d = (d >= 0) ? d : -d;
5346 return exact_log2 (abs_d) + 1;
5352 output_reload_inhi (insn, operands, len)
5353 rtx insn ATTRIBUTE_UNUSED;
5361 if (GET_CODE (operands[1]) == CONST_INT)
5363 int val = INTVAL (operands[1]);
5364 if ((val & 0xff) == 0)
5367 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5368 AS2 (ldi,%2,hi8(%1)) CR_TAB
5371 else if ((val & 0xff00) == 0)
5374 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5375 AS2 (mov,%A0,%2) CR_TAB
5376 AS2 (mov,%B0,__zero_reg__));
5378 else if ((val & 0xff) == ((val & 0xff00) >> 8))
5381 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5382 AS2 (mov,%A0,%2) CR_TAB
5387 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5388 AS2 (mov,%A0,%2) CR_TAB
5389 AS2 (ldi,%2,hi8(%1)) CR_TAB
5395 output_reload_insisf (insn, operands, len)
5396 rtx insn ATTRIBUTE_UNUSED;
5400 rtx src = operands[1];
5401 int cnst = (GET_CODE (src) == CONST_INT);
5406 *len = 4 + ((INTVAL (src) & 0xff) != 0)
5407 + ((INTVAL (src) & 0xff00) != 0)
5408 + ((INTVAL (src) & 0xff0000) != 0)
5409 + ((INTVAL (src) & 0xff000000) != 0);
5416 if (cnst && ((INTVAL (src) & 0xff) == 0))
5417 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5420 output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
5421 output_asm_insn (AS2 (mov, %A0, %2), operands);
5423 if (cnst && ((INTVAL (src) & 0xff00) == 0))
5424 output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
5427 output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
5428 output_asm_insn (AS2 (mov, %B0, %2), operands);
5430 if (cnst && ((INTVAL (src) & 0xff0000) == 0))
5431 output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
5434 output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
5435 output_asm_insn (AS2 (mov, %C0, %2), operands);
5437 if (cnst && ((INTVAL (src) & 0xff000000) == 0))
5438 output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
5441 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5442 output_asm_insn (AS2 (mov, %D0, %2), operands);
5448 avr_output_bld (operands, bit_nr)
5452 static char s[] = "bld %A0,0";
5454 s[5] = 'A' + (bit_nr >> 3);
5455 s[8] = '0' + (bit_nr & 7);
5456 output_asm_insn (s, operands);
5460 avr_output_addr_vec_elt (stream, value)
5465 fprintf (stream, "\t.word pm(.L%d)\n", value);
5467 fprintf (stream, "\trjmp .L%d\n", value);
5472 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5473 registers (for a define_peephole2) in the current function. */
5476 avr_peep2_scratch_safe (scratch)
5479 if ((interrupt_function_p (current_function_decl)
5480 || signal_function_p (current_function_decl))
5481 && leaf_function_p ())
5483 int first_reg = true_regnum (scratch);
5484 int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
5487 for (reg = first_reg; reg <= last_reg; reg++)
5489 if (!regs_ever_live[reg])
5496 /* Output a branch that tests a single bit of a register (QI, HI or SImode)
5497 or memory location in the I/O space (QImode only).
5499 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5500 Operand 1: register operand to test, or CONST_INT memory address.
5501 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5502 Operand 3: label to jump to if the test is true. */
5505 avr_out_sbxx_branch (insn, operands)
5509 enum rtx_code comp = GET_CODE (operands[0]);
5510 int long_jump = (get_attr_length (insn) >= 4);
5511 int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
5515 else if (comp == LT)
5519 comp = reverse_condition (comp);
5521 if (GET_CODE (operands[1]) == CONST_INT)
5523 if (INTVAL (operands[1]) < 0x40)
5526 output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
5528 output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
5532 output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
5534 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
5536 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
5539 else /* GET_CODE (operands[1]) == REG */
5541 if (GET_MODE (operands[1]) == QImode)
5544 output_asm_insn (AS2 (sbrs,%1,%2), operands);
5546 output_asm_insn (AS2 (sbrc,%1,%2), operands);
5548 else /* HImode or SImode */
5550 static char buf[] = "sbrc %A1,0";
5551 int bit_nr = exact_log2 (INTVAL (operands[2])
5552 & GET_MODE_MASK (GET_MODE (operands[1])));
5554 buf[3] = (comp == EQ) ? 's' : 'c';
5555 buf[6] = 'A' + (bit_nr >> 3);
5556 buf[9] = '0' + (bit_nr & 7);
5557 output_asm_insn (buf, operands);
5562 return (AS1 (rjmp,.+4) CR_TAB
5565 return AS1 (rjmp,%3);
5570 avr_asm_out_ctor (symbol, priority)
5574 fputs ("\t.global __do_global_ctors\n", asm_out_file);
5575 default_ctor_section_asm_out_constructor (symbol, priority);
5579 avr_asm_out_dtor (symbol, priority)
5583 fputs ("\t.global __do_global_dtors\n", asm_out_file);
5584 default_dtor_section_asm_out_destructor (symbol, priority);