1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Denis Chertykov (denisc@overta.ru)
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
24 #include "coretypes.h"
28 #include "hard-reg-set.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-attr.h"
44 #include "target-def.h"
46 /* Maximal allowed offset for an address in the LD command */
47 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
49 static int avr_naked_function_p PARAMS ((tree));
50 static int interrupt_function_p PARAMS ((tree));
51 static int signal_function_p PARAMS ((tree));
52 static int avr_regs_to_save PARAMS ((HARD_REG_SET *));
53 static int sequent_regs_live PARAMS ((void));
54 static const char * ptrreg_to_str PARAMS ((int));
55 static const char * cond_string PARAMS ((enum rtx_code));
56 static int avr_num_arg_regs PARAMS ((enum machine_mode, tree));
57 static int out_adj_frame_ptr PARAMS ((FILE *, int));
58 static int out_set_stack_ptr PARAMS ((FILE *, int, int));
59 static RTX_CODE compare_condition PARAMS ((rtx insn));
60 static int compare_sign_p PARAMS ((rtx insn));
61 static int reg_was_0 PARAMS ((rtx insn, rtx op));
62 static tree avr_handle_progmem_attribute PARAMS ((tree *, tree, tree, int, bool *));
63 static tree avr_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
64 const struct attribute_spec avr_attribute_table[];
65 static bool avr_assemble_integer PARAMS ((rtx, unsigned int, int));
66 static void avr_file_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_END
223 #define TARGET_ASM_FILE_END avr_file_end
225 #undef TARGET_ASM_FUNCTION_PROLOGUE
226 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
227 #undef TARGET_ASM_FUNCTION_EPILOGUE
228 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
229 #undef TARGET_ATTRIBUTE_TABLE
230 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
231 #undef TARGET_ASM_UNIQUE_SECTION
232 #define TARGET_ASM_UNIQUE_SECTION avr_unique_section
233 #undef TARGET_INSERT_ATTRIBUTES
234 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
235 #undef TARGET_SECTION_TYPE_FLAGS
236 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
237 #undef TARGET_RTX_COSTS
238 #define TARGET_RTX_COSTS avr_rtx_costs
239 #undef TARGET_ADDRESS_COST
240 #define TARGET_ADDRESS_COST avr_address_cost
241 #undef TARGET_MACHINE_DEPENDENT_REORG
242 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
244 struct gcc_target targetm = TARGET_INITIALIZER;
247 avr_override_options ()
249 const struct mcu_type_s *t;
250 const struct base_arch_s *base;
252 for (t = avr_mcu_types; t->name; t++)
253 if (strcmp (t->name, avr_mcu_name) == 0)
258 fprintf (stderr, "unknown MCU `%s' specified\nKnown MCU names:\n",
260 for (t = avr_mcu_types; t->name; t++)
261 fprintf (stderr," %s\n", t->name);
264 base = &avr_arch_types[t->arch];
265 avr_asm_only_p = base->asm_only;
266 avr_enhanced_p = base->enhanced;
267 avr_mega_p = base->mega;
268 avr_base_arch_macro = base->macro;
269 avr_extra_arch_macro = t->macro;
271 if (optimize && !TARGET_NO_TABLEJUMP)
272 avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
276 /* Initialize TMP_REG_RTX and ZERO_REG_RTX */
280 tmp_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
281 memset (tmp_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
282 PUT_CODE (tmp_reg_rtx, REG);
283 PUT_MODE (tmp_reg_rtx, QImode);
284 XINT (tmp_reg_rtx, 0) = TMP_REGNO;
286 zero_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
287 memset (zero_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
288 PUT_CODE (zero_reg_rtx, REG);
289 PUT_MODE (zero_reg_rtx, QImode);
290 XINT (zero_reg_rtx, 0) = ZERO_REGNO;
292 ldi_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
293 memset (ldi_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
294 PUT_CODE (ldi_reg_rtx, REG);
295 PUT_MODE (ldi_reg_rtx, QImode);
296 XINT (ldi_reg_rtx, 0) = LDI_REG_REGNO;
299 /* return register class from register number */
301 static const int reg_class_tab[]={
302 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
303 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
304 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
305 GENERAL_REGS, /* r0 - r15 */
306 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
307 LD_REGS, /* r16 - 23 */
308 ADDW_REGS,ADDW_REGS, /* r24,r25 */
309 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
310 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
311 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
312 STACK_REG,STACK_REG /* SPL,SPH */
315 /* Return register class for register R */
318 avr_regno_reg_class (r)
322 return reg_class_tab[r];
327 /* A C expression which defines the machine-dependent operand
328 constraint letters for register classes. If C is such a
329 letter, the value should be the register class corresponding to
330 it. Otherwise, the value should be `NO_REGS'. The register
331 letter `r', corresponding to class `GENERAL_REGS', will not be
332 passed to this macro; you do not need to handle it. */
335 avr_reg_class_from_letter (c)
340 case 't' : return R0_REG;
341 case 'b' : return BASE_POINTER_REGS;
342 case 'e' : return POINTER_REGS;
343 case 'w' : return ADDW_REGS;
344 case 'd' : return LD_REGS;
345 case 'l' : return NO_LD_REGS;
346 case 'a' : return SIMPLE_LD_REGS;
347 case 'x' : return POINTER_X_REGS;
348 case 'y' : return POINTER_Y_REGS;
349 case 'z' : return POINTER_Z_REGS;
350 case 'q' : return STACK_REG;
356 /* Return nonzero if FUNC is a naked function. */
359 avr_naked_function_p (func)
364 if (TREE_CODE (func) != FUNCTION_DECL)
367 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
368 return a != NULL_TREE;
371 /* Return nonzero if FUNC is an interrupt function as specified
372 by the "interrupt" attribute. */
375 interrupt_function_p (func)
380 if (TREE_CODE (func) != FUNCTION_DECL)
383 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
384 return a != NULL_TREE;
387 /* Return nonzero if FUNC is a signal function as specified
388 by the "signal" attribute. */
391 signal_function_p (func)
396 if (TREE_CODE (func) != FUNCTION_DECL)
399 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
400 return a != NULL_TREE;
403 /* Return the number of hard registers to push/pop in the prologue/epilogue
404 of the current function, and optionally store these registers in SET. */
407 avr_regs_to_save (set)
411 int int_or_sig_p = (interrupt_function_p (current_function_decl)
412 || signal_function_p (current_function_decl));
413 int leaf_func_p = leaf_function_p ();
416 CLEAR_HARD_REG_SET (*set);
419 /* No need to save any registers if the function never returns. */
420 if (TREE_THIS_VOLATILE (current_function_decl))
423 for (reg = 0; reg < 32; reg++)
425 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
426 any global register variables. */
430 if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
431 || (regs_ever_live[reg]
432 && (int_or_sig_p || !call_used_regs[reg])
433 && !(frame_pointer_needed
434 && (reg == REG_Y || reg == (REG_Y+1)))))
437 SET_HARD_REG_BIT (*set, reg);
444 /* Compute offset between arg_pointer and frame_pointer */
447 initial_elimination_offset (from, to)
451 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
455 int offset = frame_pointer_needed ? 2 : 0;
457 offset += avr_regs_to_save (NULL);
458 return get_frame_size () + 2 + 1 + offset;
462 /* Return 1 if the function epilogue is just a single "ret". */
465 avr_simple_epilogue ()
467 return (! frame_pointer_needed
468 && get_frame_size () == 0
469 && avr_regs_to_save (NULL) == 0
470 && ! interrupt_function_p (current_function_decl)
471 && ! signal_function_p (current_function_decl)
472 && ! avr_naked_function_p (current_function_decl)
473 && ! MAIN_NAME_P (DECL_NAME (current_function_decl))
474 && ! TREE_THIS_VOLATILE (current_function_decl));
477 /* This function checks sequence of live registers */
486 for (reg = 0; reg < 18; ++reg)
488 if (!call_used_regs[reg])
490 if (regs_ever_live[reg])
500 if (!frame_pointer_needed)
502 if (regs_ever_live[REG_Y])
510 if (regs_ever_live[REG_Y+1])
523 return (cur_seq == live_seq) ? live_seq : 0;
527 /* Output to FILE the asm instructions to adjust the frame pointer by
528 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
529 (epilogue). Returns the number of instructions generated. */
532 out_adj_frame_ptr (file, adj)
540 if (TARGET_TINY_STACK)
542 if (adj < -63 || adj > 63)
543 warning ("large frame pointer change (%d) with -mtiny-stack", adj);
545 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
546 over "sbiw" (2 cycles, same size). */
548 fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
551 else if (adj < -63 || adj > 63)
553 fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
554 AS2 (sbci, r29, hi8(%d)) CR_TAB),
560 fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
565 fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
573 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
574 handling various cases of interrupt enable flag state BEFORE and AFTER
575 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
576 Returns the number of instructions generated. */
579 out_set_stack_ptr (file, before, after)
584 int do_sph, do_cli, do_save, do_sei, lock_sph, size;
586 /* The logic here is so that -mno-interrupts actually means
587 "it is safe to write SPH in one instruction, then SPL in the
588 next instruction, without disabling interrupts first".
589 The after != -1 case (interrupt/signal) is not affected. */
591 do_sph = !TARGET_TINY_STACK;
592 lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
593 do_cli = (before != 0 && (after == 0 || lock_sph));
594 do_save = (do_cli && before == -1 && after == -1);
595 do_sei = ((do_cli || before != 1) && after == 1);
600 fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
606 fprintf (file, "cli" CR_TAB);
610 /* Do SPH first - maybe this will disable interrupts for one instruction
611 someday (a suggestion has been sent to avr@atmel.com for consideration
612 in future devices - that would make -mno-interrupts always safe). */
615 fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
619 /* Set/restore the I flag now - interrupts will be really enabled only
620 after the next instruction. This is not clearly documented, but
621 believed to be true for all AVR devices. */
624 fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
629 fprintf (file, "sei" CR_TAB);
633 fprintf (file, AS2 (out, __SP_L__, r28) "\n");
639 /* Output function prologue */
642 avr_output_function_prologue (file, size)
647 int interrupt_func_p;
653 last_insn_address = 0;
654 jump_tables_size = 0;
656 fprintf (file, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n",
659 if (avr_naked_function_p (current_function_decl))
661 fputs ("/* prologue: naked */\n", file);
665 interrupt_func_p = interrupt_function_p (current_function_decl);
666 signal_func_p = signal_function_p (current_function_decl);
667 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
668 live_seq = sequent_regs_live ();
669 minimize = (TARGET_CALL_PROLOGUES
670 && !interrupt_func_p && !signal_func_p && live_seq);
672 if (interrupt_func_p)
674 fprintf (file,"\tsei\n");
677 if (interrupt_func_p || signal_func_p)
680 AS1 (push,__zero_reg__) CR_TAB
681 AS1 (push,__tmp_reg__) CR_TAB
682 AS2 (in,__tmp_reg__,__SREG__) CR_TAB
683 AS1 (push,__tmp_reg__) CR_TAB
684 AS1 (clr,__zero_reg__) "\n");
690 AS1 (ldi,r28) ",lo8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
691 AS1 (ldi,r29) ",hi8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
692 AS2 (out,__SP_H__,r29) CR_TAB
693 AS2 (out,__SP_L__,r28) "\n"),
694 avr_init_stack, size, avr_init_stack, size);
698 else if (minimize && (frame_pointer_needed || live_seq > 6))
701 AS1 (ldi, r26) ",lo8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
702 AS1 (ldi, r27) ",hi8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB), size, size);
704 fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB
705 AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB)
706 ,current_function_name, current_function_name);
712 fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
713 (18 - live_seq) * 2);
718 fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
719 (18 - live_seq) * 2);
722 fprintf (file, ".L_%s_body:\n", current_function_name);
728 prologue_size += avr_regs_to_save (&set);
729 for (reg = 0; reg < 32; ++reg)
731 if (TEST_HARD_REG_BIT (set, reg))
733 fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
736 if (frame_pointer_needed)
740 AS1 (push,r28) CR_TAB
741 AS1 (push,r29) CR_TAB
742 AS2 (in,r28,__SP_L__) CR_TAB
743 AS2 (in,r29,__SP_H__) "\n");
748 prologue_size += out_adj_frame_ptr (file, size);
750 if (interrupt_func_p)
752 prologue_size += out_set_stack_ptr (file, 1, 1);
754 else if (signal_func_p)
756 prologue_size += out_set_stack_ptr (file, 0, 0);
760 prologue_size += out_set_stack_ptr (file, -1, -1);
768 fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
771 /* Output function epilogue */
774 avr_output_function_epilogue (file, size)
779 int interrupt_func_p;
785 rtx last = get_last_nonnote_insn ();
787 function_size = jump_tables_size;
790 rtx first = get_first_nonnote_insn ();
791 function_size += (INSN_ADDRESSES (INSN_UID (last)) -
792 INSN_ADDRESSES (INSN_UID (first)));
793 function_size += get_attr_length (last);
796 fprintf (file, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n", size);
799 if (avr_naked_function_p (current_function_decl))
801 fputs ("/* epilogue: naked */\n", file);
805 if (last && GET_CODE (last) == BARRIER)
807 fputs ("/* epilogue: noreturn */\n", file);
811 interrupt_func_p = interrupt_function_p (current_function_decl);
812 signal_func_p = signal_function_p (current_function_decl);
813 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
814 live_seq = sequent_regs_live ();
815 minimize = (TARGET_CALL_PROLOGUES
816 && !interrupt_func_p && !signal_func_p && live_seq);
820 /* Return value from main() is already in the correct registers
821 (r25:r24) as the exit() argument. */
824 fputs ("\t" AS1 (jmp,exit) "\n", file);
829 fputs ("\t" AS1 (rjmp,exit) "\n", file);
833 else if (minimize && (frame_pointer_needed || live_seq > 4))
835 fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
837 if (frame_pointer_needed)
839 epilogue_size += out_adj_frame_ptr (file, -size);
843 fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
844 AS2 (in , r29, __SP_H__) CR_TAB));
850 fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
851 (18 - live_seq) * 2);
856 fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
857 (18 - live_seq) * 2);
865 if (frame_pointer_needed)
870 epilogue_size += out_adj_frame_ptr (file, -size);
872 if (interrupt_func_p || signal_func_p)
874 epilogue_size += out_set_stack_ptr (file, -1, 0);
878 epilogue_size += out_set_stack_ptr (file, -1, -1);
887 epilogue_size += avr_regs_to_save (&set);
888 for (reg = 31; reg >= 0; --reg)
890 if (TEST_HARD_REG_BIT (set, reg))
892 fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
896 if (interrupt_func_p || signal_func_p)
899 AS1 (pop,__tmp_reg__) CR_TAB
900 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
901 AS1 (pop,__tmp_reg__) CR_TAB
902 AS1 (pop,__zero_reg__) "\n");
904 fprintf (file, "\treti\n");
907 fprintf (file, "\tret\n");
912 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
913 fprintf (file, "/* function %s size %d (%d) */\n", current_function_name,
914 prologue_size + function_size + epilogue_size, function_size);
915 commands_in_file += prologue_size + function_size + epilogue_size;
916 commands_in_prologues += prologue_size;
917 commands_in_epilogues += epilogue_size;
921 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
922 machine for a memory operand of mode MODE. */
925 legitimate_address_p (mode, x, strict)
926 enum machine_mode mode;
930 enum reg_class r = NO_REGS;
932 if (TARGET_ALL_DEBUG)
934 fprintf (stderr, "mode: (%s) %s %s %s %s:",
936 strict ? "(strict)": "",
937 reload_completed ? "(reload_completed)": "",
938 reload_in_progress ? "(reload_in_progress)": "",
939 reg_renumber ? "(reg_renumber)" : "");
940 if (GET_CODE (x) == PLUS
941 && REG_P (XEXP (x, 0))
942 && GET_CODE (XEXP (x, 1)) == CONST_INT
943 && INTVAL (XEXP (x, 1)) >= 0
944 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
947 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
948 true_regnum (XEXP (x, 0)));
951 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
952 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
954 else if (CONSTANT_ADDRESS_P (x))
956 else if (GET_CODE (x) == PLUS
957 && REG_P (XEXP (x, 0))
958 && GET_CODE (XEXP (x, 1)) == CONST_INT
959 && INTVAL (XEXP (x, 1)) >= 0)
961 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
965 || REGNO (XEXP (x,0)) == REG_Y
966 || REGNO (XEXP (x,0)) == REG_Z)
967 r = BASE_POINTER_REGS;
968 if (XEXP (x,0) == frame_pointer_rtx
969 || XEXP (x,0) == arg_pointer_rtx)
970 r = BASE_POINTER_REGS;
972 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
975 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
976 && REG_P (XEXP (x, 0))
977 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
978 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
982 if (TARGET_ALL_DEBUG)
984 fprintf (stderr, " ret = %c\n", r);
986 return r == NO_REGS ? 0 : (int)r;
989 /* Attempts to replace X with a valid
990 memory address for an operand of mode MODE */
993 legitimize_address (x, oldx, mode)
996 enum machine_mode mode;
999 if (TARGET_ALL_DEBUG)
1001 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
1005 if (GET_CODE (oldx) == PLUS
1006 && REG_P (XEXP (oldx,0)))
1008 if (REG_P (XEXP (oldx,1)))
1009 x = force_reg (GET_MODE (oldx), oldx);
1010 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
1012 int offs = INTVAL (XEXP (oldx,1));
1013 if (frame_pointer_rtx != XEXP (oldx,0))
1014 if (offs > MAX_LD_OFFSET (mode))
1016 if (TARGET_ALL_DEBUG)
1017 fprintf (stderr, "force_reg (big offset)\n");
1018 x = force_reg (GET_MODE (oldx), oldx);
1026 /* Return a pointer register name as a string */
1029 ptrreg_to_str (regno)
1034 case REG_X: return "X";
1035 case REG_Y: return "Y";
1036 case REG_Z: return "Z";
1043 /* Return the condition name as a string.
1044 Used in conditional jump constructing */
1057 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1062 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1075 /* Output ADDR to FILE as address */
1078 print_operand_address (file, addr)
1082 switch (GET_CODE (addr))
1085 fprintf (file, ptrreg_to_str (REGNO (addr)));
1089 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1093 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1097 if (CONSTANT_ADDRESS_P (addr)
1098 && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
1099 || GET_CODE (addr) == LABEL_REF))
1101 fprintf (file, "pm(");
1102 output_addr_const (file,addr);
1103 fprintf (file ,")");
1106 output_addr_const (file, addr);
1111 /* Output X as assembler operand to file FILE */
1114 print_operand (file, x, code)
1121 if (code >= 'A' && code <= 'D')
1131 if (x == zero_reg_rtx)
1132 fprintf (file, "__zero_reg__");
1134 fprintf (file, reg_names[true_regnum (x) + abcd]);
1136 else if (GET_CODE (x) == CONST_INT)
1137 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
1138 else if (GET_CODE (x) == MEM)
1140 rtx addr = XEXP (x,0);
1142 if (CONSTANT_P (addr) && abcd)
1145 output_address (addr);
1146 fprintf (file, ")+%d", abcd);
1148 else if (code == 'o')
1150 if (GET_CODE (addr) != PLUS)
1151 fatal_insn ("bad address, not (reg+disp):", addr);
1153 print_operand (file, XEXP (addr, 1), 0);
1155 else if (GET_CODE (addr) == PLUS)
1157 print_operand_address (file, XEXP (addr,0));
1158 if (REGNO (XEXP (addr, 0)) == REG_X)
1159 fatal_insn ("internal compiler error. Bad address:"
1162 print_operand (file, XEXP (addr,1), code);
1165 print_operand_address (file, addr);
1167 else if (GET_CODE (x) == CONST_DOUBLE)
1171 if (GET_MODE (x) != SFmode)
1172 fatal_insn ("internal compiler error. Unknown mode:", x);
1173 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1174 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1175 fprintf (file, "0x%lx", val);
1177 else if (code == 'j')
1178 fputs (cond_string (GET_CODE (x)), file);
1179 else if (code == 'k')
1180 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
1182 print_operand_address (file, x);
1185 /* Recognize operand OP of mode MODE used in call instructions */
1188 call_insn_operand (op, mode)
1190 enum machine_mode mode ATTRIBUTE_UNUSED;
1192 if (GET_CODE (op) == MEM)
1194 rtx inside = XEXP (op, 0);
1195 if (register_operand (inside, Pmode))
1197 if (CONSTANT_ADDRESS_P (inside))
1203 /* Update the condition code in the INSN. */
1206 notice_update_cc (body, insn)
1207 rtx body ATTRIBUTE_UNUSED;
1212 switch (get_attr_cc (insn))
1215 /* Insn does not affect CC at all. */
1223 set = single_set (insn);
1227 cc_status.flags |= CC_NO_OVERFLOW;
1228 cc_status.value1 = SET_DEST (set);
1233 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1234 The V flag may or may not be known but that's ok because
1235 alter_cond will change tests to use EQ/NE. */
1236 set = single_set (insn);
1240 cc_status.value1 = SET_DEST (set);
1241 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1246 set = single_set (insn);
1249 cc_status.value1 = SET_SRC (set);
1253 /* Insn doesn't leave CC in a usable state. */
1256 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1257 set = single_set (insn);
1260 rtx src = SET_SRC (set);
1262 if (GET_CODE (src) == ASHIFTRT
1263 && GET_MODE (src) == QImode)
1265 rtx x = XEXP (src, 1);
1267 if (GET_CODE (x) == CONST_INT
1270 cc_status.value1 = SET_DEST (set);
1271 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1279 /* Return maximum number of consecutive registers of
1280 class CLASS needed to hold a value of mode MODE. */
1283 class_max_nregs (class, mode)
1284 enum reg_class class ATTRIBUTE_UNUSED;
1285 enum machine_mode mode;
1287 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1290 /* Choose mode for jump insn:
1291 1 - relative jump in range -63 <= x <= 62 ;
1292 2 - relative jump in range -2046 <= x <= 2045 ;
1293 3 - absolute jump (only for ATmega[16]03). */
1296 avr_jump_mode (x, insn)
1297 rtx x; /* jump operand */
1298 rtx insn; /* jump insn */
1300 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1301 ? XEXP (x, 0) : x));
1302 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1303 int jump_distance = cur_addr - dest_addr;
1305 if (-63 <= jump_distance && jump_distance <= 62)
1307 else if (-2046 <= jump_distance && jump_distance <= 2045)
1315 /* return an AVR condition jump commands.
1316 X is a comparison RTX.
1317 LEN is a number returned by avr_jump_mode function.
1318 if REVERSE nonzero then condition code in X must be reversed. */
1321 ret_cond_branch (x, len, reverse)
1326 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1331 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1332 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1334 len == 2 ? (AS1 (breq,.+4) CR_TAB
1335 AS1 (brmi,.+2) CR_TAB
1337 (AS1 (breq,.+6) CR_TAB
1338 AS1 (brmi,.+4) CR_TAB
1342 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1344 len == 2 ? (AS1 (breq,.+4) CR_TAB
1345 AS1 (brlt,.+2) CR_TAB
1347 (AS1 (breq,.+6) CR_TAB
1348 AS1 (brlt,.+4) CR_TAB
1351 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1353 len == 2 ? (AS1 (breq,.+4) CR_TAB
1354 AS1 (brlo,.+2) CR_TAB
1356 (AS1 (breq,.+6) CR_TAB
1357 AS1 (brlo,.+4) CR_TAB
1360 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1361 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1363 len == 2 ? (AS1 (breq,.+2) CR_TAB
1364 AS1 (brpl,.+2) CR_TAB
1366 (AS1 (breq,.+2) CR_TAB
1367 AS1 (brpl,.+4) CR_TAB
1370 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1372 len == 2 ? (AS1 (breq,.+2) CR_TAB
1373 AS1 (brge,.+2) CR_TAB
1375 (AS1 (breq,.+2) CR_TAB
1376 AS1 (brge,.+4) CR_TAB
1379 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1381 len == 2 ? (AS1 (breq,.+2) CR_TAB
1382 AS1 (brsh,.+2) CR_TAB
1384 (AS1 (breq,.+2) CR_TAB
1385 AS1 (brsh,.+4) CR_TAB
1393 return AS1 (br%k1,%0);
1395 return (AS1 (br%j1,.+2) CR_TAB
1398 return (AS1 (br%j1,.+4) CR_TAB
1407 return AS1 (br%j1,%0);
1409 return (AS1 (br%k1,.+2) CR_TAB
1412 return (AS1 (br%k1,.+4) CR_TAB
1420 /* Predicate function for immediate operand which fits to byte (8bit) */
1423 byte_immediate_operand (op, mode)
1425 enum machine_mode mode ATTRIBUTE_UNUSED;
1427 return (GET_CODE (op) == CONST_INT
1428 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1431 /* Output all insn addresses and their sizes into the assembly language
1432 output file. This is helpful for debugging whether the length attributes
1433 in the md file are correct.
1434 Output insn cost for next insn. */
1437 final_prescan_insn (insn, operand, num_operands)
1438 rtx insn, *operand ATTRIBUTE_UNUSED;
1439 int num_operands ATTRIBUTE_UNUSED;
1441 int uid = INSN_UID (insn);
1443 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1445 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1446 INSN_ADDRESSES (uid),
1447 INSN_ADDRESSES (uid) - last_insn_address,
1448 rtx_cost (PATTERN (insn), INSN));
1450 last_insn_address = INSN_ADDRESSES (uid);
1452 if (TARGET_RTL_DUMP)
1454 fprintf (asm_out_file, "/*****************\n");
1455 print_rtl_single (asm_out_file, insn);
1456 fprintf (asm_out_file, "*****************/\n");
1460 /* Return 0 if undefined, 1 if always true or always false. */
1463 avr_simplify_comparision_p (mode, operator, x)
1464 enum machine_mode mode;
1468 unsigned int max = (mode == QImode ? 0xff :
1469 mode == HImode ? 0xffff :
1470 mode == SImode ? 0xffffffff : 0);
1471 if (max && operator && GET_CODE (x) == CONST_INT)
1473 if (unsigned_condition (operator) != operator)
1476 if (max != (INTVAL (x) & max)
1477 && INTVAL (x) != 0xff)
1484 /* Returns nonzero if REGNO is the number of a hard
1485 register in which function arguments are sometimes passed. */
1488 function_arg_regno_p(r)
1491 return (r >= 8 && r <= 25);
1494 /* Initializing the variable cum for the state at the beginning
1495 of the argument list. */
1498 init_cumulative_args (cum, fntype, libname, fndecl)
1499 CUMULATIVE_ARGS *cum;
1502 tree fndecl ATTRIBUTE_UNUSED;
1505 cum->regno = FIRST_CUM_REG;
1506 if (!libname && fntype)
1508 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1509 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1510 != void_type_node));
1516 /* Returns the number of registers to allocate for a function argument. */
1519 avr_num_arg_regs (mode, type)
1520 enum machine_mode mode;
1525 if (mode == BLKmode)
1526 size = int_size_in_bytes (type);
1528 size = GET_MODE_SIZE (mode);
1530 /* Align all function arguments to start in even-numbered registers.
1531 Odd-sized arguments leave holes above them. */
1533 return (size + 1) & ~1;
1536 /* Controls whether a function argument is passed
1537 in a register, and which register. */
1540 function_arg (cum, mode, type, named)
1541 CUMULATIVE_ARGS *cum;
1542 enum machine_mode mode;
1544 int named ATTRIBUTE_UNUSED;
1546 int bytes = avr_num_arg_regs (mode, type);
1548 if (cum->nregs && bytes <= cum->nregs)
1549 return gen_rtx (REG, mode, cum->regno - bytes);
1554 /* Update the summarizer variable CUM to advance past an argument
1555 in the argument list. */
1558 function_arg_advance (cum, mode, type, named)
1559 CUMULATIVE_ARGS *cum; /* current arg information */
1560 enum machine_mode mode; /* current arg mode */
1561 tree type; /* type of the argument or 0 if lib support */
1562 int named ATTRIBUTE_UNUSED; /* whether or not the argument was named */
1564 int bytes = avr_num_arg_regs (mode, type);
1566 cum->nregs -= bytes;
1567 cum->regno -= bytes;
1569 if (cum->nregs <= 0)
1572 cum->regno = FIRST_CUM_REG;
1576 /***********************************************************************
1577 Functions for outputting various mov's for a various modes
1578 ************************************************************************/
1580 output_movqi (insn, operands, l)
1586 rtx dest = operands[0];
1587 rtx src = operands[1];
1595 if (register_operand (dest, QImode))
1597 if (register_operand (src, QImode)) /* mov r,r */
1599 if (test_hard_reg_class (STACK_REG, dest))
1600 return AS2 (out,%0,%1);
1601 else if (test_hard_reg_class (STACK_REG, src))
1602 return AS2 (in,%0,%1);
1604 return AS2 (mov,%0,%1);
1606 else if (CONSTANT_P (src))
1608 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1609 return AS2 (ldi,%0,lo8(%1));
1611 if (GET_CODE (src) == CONST_INT)
1613 if (src == const0_rtx) /* mov r,L */
1614 return AS1 (clr,%0);
1615 else if (src == const1_rtx)
1617 if (reg_was_0 (insn, dest))
1618 return AS1 (inc,%0 ; reg_was_0);
1621 return (AS1 (clr,%0) CR_TAB
1624 else if (src == constm1_rtx)
1626 /* Immediate constants -1 to any register */
1627 if (reg_was_0 (insn, dest))
1628 return AS1 (dec,%0 ; reg_was_0);
1631 return (AS1 (clr,%0) CR_TAB
1636 int bit_nr = exact_log2 (INTVAL (src));
1640 if (reg_was_0 (insn, dest))
1644 output_asm_insn ("set ; reg_was_0", operands);
1650 output_asm_insn ((AS1 (clr,%0) CR_TAB
1654 avr_output_bld (operands, bit_nr);
1661 /* Last resort, larger than loading from memory. */
1663 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1664 AS2 (ldi,r31,lo8(%1)) CR_TAB
1665 AS2 (mov,%0,r31) CR_TAB
1666 AS2 (mov,r31,__tmp_reg__));
1668 else if (GET_CODE (src) == MEM)
1669 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1671 else if (GET_CODE (dest) == MEM)
1673 const char *template;
1675 if (src == const0_rtx)
1676 operands[1] = zero_reg_rtx;
1678 template = out_movqi_mr_r (insn, operands, real_l);
1681 output_asm_insn (template, operands);
1690 output_movhi (insn, operands, l)
1696 rtx dest = operands[0];
1697 rtx src = operands[1];
1703 if (register_operand (dest, HImode))
1705 if (register_operand (src, HImode)) /* mov r,r */
1707 if (test_hard_reg_class (STACK_REG, dest))
1709 if (TARGET_TINY_STACK)
1712 return AS2 (out,__SP_L__,%A1);
1714 else if (TARGET_NO_INTERRUPTS)
1717 return (AS2 (out,__SP_H__,%B1) CR_TAB
1718 AS2 (out,__SP_L__,%A1));
1722 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1724 AS2 (out,__SP_H__,%B1) CR_TAB
1725 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1726 AS2 (out,__SP_L__,%A1));
1728 else if (test_hard_reg_class (STACK_REG, src))
1731 return (AS2 (in,%A0,__SP_L__) CR_TAB
1732 AS2 (in,%B0,__SP_H__));
1738 return (AS2 (movw,%0,%1));
1741 if (true_regnum (dest) > true_regnum (src))
1744 return (AS2 (mov,%B0,%B1) CR_TAB
1750 return (AS2 (mov,%A0,%A1) CR_TAB
1754 else if (CONSTANT_P (src))
1756 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1758 if (byte_immediate_operand (src, HImode)
1759 && reg_was_0 (insn, dest))
1762 return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0));
1766 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1767 AS2 (ldi,%B0,hi8(%1)));
1770 if (GET_CODE (src) == CONST_INT)
1772 if (src == const0_rtx) /* mov r,L */
1775 return (AS1 (clr,%A0) CR_TAB
1778 else if (src == const1_rtx)
1780 if (reg_was_0 (insn, dest))
1783 return AS1 (inc,%0 ; reg_was_0);
1787 return (AS1 (clr,%A0) CR_TAB
1788 AS1 (clr,%B0) CR_TAB
1791 else if (src == constm1_rtx)
1793 /* Immediate constants -1 to any register */
1794 if (reg_was_0 (insn, dest))
1797 return (AS1 (dec,%A0 ; reg_was_0) CR_TAB
1802 return (AS1 (clr,%0) CR_TAB
1803 AS1 (dec,%A0) CR_TAB
1808 int bit_nr = exact_log2 (INTVAL (src));
1812 if (reg_was_0 (insn, dest))
1816 output_asm_insn ("set ; reg_was_0", operands);
1822 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1823 AS1 (clr,%B0) CR_TAB
1827 avr_output_bld (operands, bit_nr);
1833 if ((INTVAL (src) & 0xff) == 0)
1836 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1837 AS1 (clr,%A0) CR_TAB
1838 AS2 (ldi,r31,hi8(%1)) CR_TAB
1839 AS2 (mov,%B0,r31) CR_TAB
1840 AS2 (mov,r31,__tmp_reg__));
1842 else if ((INTVAL (src) & 0xff00) == 0)
1845 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1846 AS2 (ldi,r31,lo8(%1)) CR_TAB
1847 AS2 (mov,%A0,r31) CR_TAB
1848 AS1 (clr,%B0) CR_TAB
1849 AS2 (mov,r31,__tmp_reg__));
1853 /* Last resort, equal to loading from memory. */
1855 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1856 AS2 (ldi,r31,lo8(%1)) CR_TAB
1857 AS2 (mov,%A0,r31) CR_TAB
1858 AS2 (ldi,r31,hi8(%1)) CR_TAB
1859 AS2 (mov,%B0,r31) CR_TAB
1860 AS2 (mov,r31,__tmp_reg__));
1862 else if (GET_CODE (src) == MEM)
1863 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1865 else if (GET_CODE (dest) == MEM)
1867 const char *template;
1869 if (src == const0_rtx)
1870 operands[1] = zero_reg_rtx;
1872 template = out_movhi_mr_r (insn, operands, real_l);
1875 output_asm_insn (template, operands);
1880 fatal_insn ("invalid insn:", insn);
1885 out_movqi_r_mr (insn, op, l)
1888 int *l; /* instruction length */
1892 rtx x = XEXP (src, 0);
1898 if (CONSTANT_ADDRESS_P (x))
1900 if (avr_io_address_p (x, 1))
1903 return AS2 (in,%0,%1-0x20);
1906 return AS2 (lds,%0,%1);
1908 /* memory access by reg+disp */
1909 else if (GET_CODE (x) == PLUS
1910 && REG_P (XEXP (x,0))
1911 && GET_CODE (XEXP (x,1)) == CONST_INT)
1913 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
1915 int disp = INTVAL (XEXP (x,1));
1916 if (REGNO (XEXP (x,0)) != REG_Y)
1917 fatal_insn ("incorrect insn:",insn);
1919 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1920 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1921 AS2 (ldd,%0,Y+63) CR_TAB
1922 AS2 (sbiw,r28,%o1-63));
1924 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1925 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1926 AS2 (ld,%0,Y) CR_TAB
1927 AS2 (subi,r28,lo8(%o1)) CR_TAB
1928 AS2 (sbci,r29,hi8(%o1)));
1930 else if (REGNO (XEXP (x,0)) == REG_X)
1932 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1933 it but I have this situation with extremal optimizing options. */
1934 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
1935 || reg_unused_after (insn, XEXP (x,0)))
1936 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1939 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1940 AS2 (ld,%0,X) CR_TAB
1941 AS2 (sbiw,r26,%o1));
1944 return AS2 (ldd,%0,%1);
1947 return AS2 (ld,%0,%1);
1951 out_movhi_r_mr (insn, op, l)
1954 int *l; /* instruction length */
1958 rtx base = XEXP (src, 0);
1959 int reg_dest = true_regnum (dest);
1960 int reg_base = true_regnum (base);
1968 if (reg_dest == reg_base) /* R = (R) */
1971 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1972 AS2 (ld,%B0,%1) CR_TAB
1973 AS2 (mov,%A0,__tmp_reg__));
1975 else if (reg_base == REG_X) /* (R26) */
1977 if (reg_unused_after (insn, base))
1980 return (AS2 (ld,%A0,X+) CR_TAB
1984 return (AS2 (ld,%A0,X+) CR_TAB
1985 AS2 (ld,%B0,X) CR_TAB
1991 return (AS2 (ld,%A0,%1) CR_TAB
1992 AS2 (ldd,%B0,%1+1));
1995 else if (GET_CODE (base) == PLUS) /* (R + i) */
1997 int disp = INTVAL (XEXP (base, 1));
1998 int reg_base = true_regnum (XEXP (base, 0));
2000 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2002 if (REGNO (XEXP (base, 0)) != REG_Y)
2003 fatal_insn ("incorrect insn:",insn);
2005 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2006 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
2007 AS2 (ldd,%A0,Y+62) CR_TAB
2008 AS2 (ldd,%B0,Y+63) CR_TAB
2009 AS2 (sbiw,r28,%o1-62));
2011 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2012 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2013 AS2 (ld,%A0,Y) CR_TAB
2014 AS2 (ldd,%B0,Y+1) CR_TAB
2015 AS2 (subi,r28,lo8(%o1)) CR_TAB
2016 AS2 (sbci,r29,hi8(%o1)));
2018 if (reg_base == REG_X)
2020 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
2021 it but I have this situation with extremal
2022 optimization options. */
2025 if (reg_base == reg_dest)
2026 return (AS2 (adiw,r26,%o1) CR_TAB
2027 AS2 (ld,__tmp_reg__,X+) CR_TAB
2028 AS2 (ld,%B0,X) CR_TAB
2029 AS2 (mov,%A0,__tmp_reg__));
2031 return (AS2 (adiw,r26,%o1) CR_TAB
2032 AS2 (ld,%A0,X+) CR_TAB
2033 AS2 (ld,%B0,X) CR_TAB
2034 AS2 (sbiw,r26,%o1+1));
2037 if (reg_base == reg_dest)
2040 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
2041 AS2 (ldd,%B0,%B1) CR_TAB
2042 AS2 (mov,%A0,__tmp_reg__));
2046 return (AS2 (ldd,%A0,%A1) CR_TAB
2049 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2051 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
2052 fatal_insn ("incorrect insn:", insn);
2055 return (AS2 (ld,%B0,%1) CR_TAB
2058 else if (GET_CODE (base) == POST_INC) /* (R++) */
2060 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
2061 fatal_insn ("incorrect insn:", insn);
2064 return (AS2 (ld,%A0,%1) CR_TAB
2067 else if (CONSTANT_ADDRESS_P (base))
2069 if (avr_io_address_p (base, 2))
2072 return (AS2 (in,%A0,%A1-0x20) CR_TAB
2073 AS2 (in,%B0,%B1-0x20));
2076 return (AS2 (lds,%A0,%A1) CR_TAB
2080 fatal_insn ("unknown move insn:",insn);
2085 out_movsi_r_mr (insn, op, l)
2088 int *l; /* instruction length */
2092 rtx base = XEXP (src, 0);
2093 int reg_dest = true_regnum (dest);
2094 int reg_base = true_regnum (base);
2102 if (reg_base == REG_X) /* (R26) */
2104 if (reg_dest == REG_X)
2105 /* "ld r26,-X" is undefined */
2106 return *l=7, (AS2 (adiw,r26,3) CR_TAB
2107 AS2 (ld,r29,X) CR_TAB
2108 AS2 (ld,r28,-X) CR_TAB
2109 AS2 (ld,__tmp_reg__,-X) CR_TAB
2110 AS2 (sbiw,r26,1) CR_TAB
2111 AS2 (ld,r26,X) CR_TAB
2112 AS2 (mov,r27,__tmp_reg__));
2113 else if (reg_dest == REG_X - 2)
2114 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2115 AS2 (ld,%B0,X+) CR_TAB
2116 AS2 (ld,__tmp_reg__,X+) CR_TAB
2117 AS2 (ld,%D0,X) CR_TAB
2118 AS2 (mov,%C0,__tmp_reg__));
2119 else if (reg_unused_after (insn, base))
2120 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
2121 AS2 (ld,%B0,X+) CR_TAB
2122 AS2 (ld,%C0,X+) CR_TAB
2125 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2126 AS2 (ld,%B0,X+) CR_TAB
2127 AS2 (ld,%C0,X+) CR_TAB
2128 AS2 (ld,%D0,X) CR_TAB
2133 if (reg_dest == reg_base)
2134 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2135 AS2 (ldd,%C0,%1+2) CR_TAB
2136 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2137 AS2 (ld,%A0,%1) CR_TAB
2138 AS2 (mov,%B0,__tmp_reg__));
2139 else if (reg_base == reg_dest + 2)
2140 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2141 AS2 (ldd,%B0,%1+1) CR_TAB
2142 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2143 AS2 (ldd,%D0,%1+3) CR_TAB
2144 AS2 (mov,%C0,__tmp_reg__));
2146 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2147 AS2 (ldd,%B0,%1+1) CR_TAB
2148 AS2 (ldd,%C0,%1+2) CR_TAB
2149 AS2 (ldd,%D0,%1+3));
2152 else if (GET_CODE (base) == PLUS) /* (R + i) */
2154 int disp = INTVAL (XEXP (base, 1));
2156 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2158 if (REGNO (XEXP (base, 0)) != REG_Y)
2159 fatal_insn ("incorrect insn:",insn);
2161 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2162 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2163 AS2 (ldd,%A0,Y+60) CR_TAB
2164 AS2 (ldd,%B0,Y+61) CR_TAB
2165 AS2 (ldd,%C0,Y+62) CR_TAB
2166 AS2 (ldd,%D0,Y+63) CR_TAB
2167 AS2 (sbiw,r28,%o1-60));
2169 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2170 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2171 AS2 (ld,%A0,Y) CR_TAB
2172 AS2 (ldd,%B0,Y+1) CR_TAB
2173 AS2 (ldd,%C0,Y+2) CR_TAB
2174 AS2 (ldd,%D0,Y+3) CR_TAB
2175 AS2 (subi,r28,lo8(%o1)) CR_TAB
2176 AS2 (sbci,r29,hi8(%o1)));
2179 reg_base = true_regnum (XEXP (base, 0));
2180 if (reg_base == REG_X)
2183 if (reg_dest == REG_X)
2186 /* "ld r26,-X" is undefined */
2187 return (AS2 (adiw,r26,%o1+3) CR_TAB
2188 AS2 (ld,r29,X) CR_TAB
2189 AS2 (ld,r28,-X) CR_TAB
2190 AS2 (ld,__tmp_reg__,-X) CR_TAB
2191 AS2 (sbiw,r26,1) CR_TAB
2192 AS2 (ld,r26,X) CR_TAB
2193 AS2 (mov,r27,__tmp_reg__));
2196 if (reg_dest == REG_X - 2)
2197 return (AS2 (adiw,r26,%o1) CR_TAB
2198 AS2 (ld,r24,X+) CR_TAB
2199 AS2 (ld,r25,X+) CR_TAB
2200 AS2 (ld,__tmp_reg__,X+) CR_TAB
2201 AS2 (ld,r27,X) CR_TAB
2202 AS2 (mov,r26,__tmp_reg__));
2204 return (AS2 (adiw,r26,%o1) CR_TAB
2205 AS2 (ld,%A0,X+) CR_TAB
2206 AS2 (ld,%B0,X+) CR_TAB
2207 AS2 (ld,%C0,X+) CR_TAB
2208 AS2 (ld,%D0,X) CR_TAB
2209 AS2 (sbiw,r26,%o1+3));
2211 if (reg_dest == reg_base)
2212 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2213 AS2 (ldd,%C0,%C1) CR_TAB
2214 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2215 AS2 (ldd,%A0,%A1) CR_TAB
2216 AS2 (mov,%B0,__tmp_reg__));
2217 else if (reg_dest == reg_base - 2)
2218 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2219 AS2 (ldd,%B0,%B1) CR_TAB
2220 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2221 AS2 (ldd,%D0,%D1) CR_TAB
2222 AS2 (mov,%C0,__tmp_reg__));
2223 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2224 AS2 (ldd,%B0,%B1) CR_TAB
2225 AS2 (ldd,%C0,%C1) CR_TAB
2228 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2229 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2230 AS2 (ld,%C0,%1) CR_TAB
2231 AS2 (ld,%B0,%1) CR_TAB
2233 else if (GET_CODE (base) == POST_INC) /* (R++) */
2234 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2235 AS2 (ld,%B0,%1) CR_TAB
2236 AS2 (ld,%C0,%1) CR_TAB
2238 else if (CONSTANT_ADDRESS_P (base))
2239 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2240 AS2 (lds,%B0,%B1) CR_TAB
2241 AS2 (lds,%C0,%C1) CR_TAB
2244 fatal_insn ("unknown move insn:",insn);
2249 out_movsi_mr_r (insn, op, l)
2256 rtx base = XEXP (dest, 0);
2257 int reg_base = true_regnum (base);
2258 int reg_src = true_regnum (src);
2264 if (CONSTANT_ADDRESS_P (base))
2265 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2266 AS2 (sts,%B0,%B1) CR_TAB
2267 AS2 (sts,%C0,%C1) CR_TAB
2269 if (reg_base > 0) /* (r) */
2271 if (reg_base == REG_X) /* (R26) */
2273 if (reg_src == REG_X)
2275 /* "st X+,r26" is undefined */
2276 if (reg_unused_after (insn, base))
2277 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2278 AS2 (st,X,r26) CR_TAB
2279 AS2 (adiw,r26,1) CR_TAB
2280 AS2 (st,X+,__tmp_reg__) CR_TAB
2281 AS2 (st,X+,r28) CR_TAB
2284 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2285 AS2 (st,X,r26) CR_TAB
2286 AS2 (adiw,r26,1) CR_TAB
2287 AS2 (st,X+,__tmp_reg__) CR_TAB
2288 AS2 (st,X+,r28) CR_TAB
2289 AS2 (st,X,r29) CR_TAB
2292 else if (reg_base == reg_src + 2)
2294 if (reg_unused_after (insn, base))
2295 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2296 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2297 AS2 (st,%0+,%A1) CR_TAB
2298 AS2 (st,%0+,%B1) CR_TAB
2299 AS2 (st,%0+,__zero_reg__) CR_TAB
2300 AS2 (st,%0,__tmp_reg__) CR_TAB
2301 AS1 (clr,__zero_reg__));
2303 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2304 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2305 AS2 (st,%0+,%A1) CR_TAB
2306 AS2 (st,%0+,%B1) CR_TAB
2307 AS2 (st,%0+,__zero_reg__) CR_TAB
2308 AS2 (st,%0,__tmp_reg__) CR_TAB
2309 AS1 (clr,__zero_reg__) CR_TAB
2312 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2313 AS2 (st,%0+,%B1) CR_TAB
2314 AS2 (st,%0+,%C1) CR_TAB
2315 AS2 (st,%0,%D1) CR_TAB
2319 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2320 AS2 (std,%0+1,%B1) CR_TAB
2321 AS2 (std,%0+2,%C1) CR_TAB
2322 AS2 (std,%0+3,%D1));
2324 else if (GET_CODE (base) == PLUS) /* (R + i) */
2326 int disp = INTVAL (XEXP (base, 1));
2327 reg_base = REGNO (XEXP (base, 0));
2328 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2330 if (reg_base != REG_Y)
2331 fatal_insn ("incorrect insn:",insn);
2333 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2334 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2335 AS2 (std,Y+60,%A1) CR_TAB
2336 AS2 (std,Y+61,%B1) CR_TAB
2337 AS2 (std,Y+62,%C1) CR_TAB
2338 AS2 (std,Y+63,%D1) CR_TAB
2339 AS2 (sbiw,r28,%o0-60));
2341 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2342 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2343 AS2 (st,Y,%A1) CR_TAB
2344 AS2 (std,Y+1,%B1) CR_TAB
2345 AS2 (std,Y+2,%C1) CR_TAB
2346 AS2 (std,Y+3,%D1) CR_TAB
2347 AS2 (subi,r28,lo8(%o0)) CR_TAB
2348 AS2 (sbci,r29,hi8(%o0)));
2350 if (reg_base == REG_X)
2353 if (reg_src == REG_X)
2356 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2357 AS2 (mov,__zero_reg__,r27) CR_TAB
2358 AS2 (adiw,r26,%o0) CR_TAB
2359 AS2 (st,X+,__tmp_reg__) CR_TAB
2360 AS2 (st,X+,__zero_reg__) CR_TAB
2361 AS2 (st,X+,r28) CR_TAB
2362 AS2 (st,X,r29) CR_TAB
2363 AS1 (clr,__zero_reg__) CR_TAB
2364 AS2 (sbiw,r26,%o0+3));
2366 else if (reg_src == REG_X - 2)
2369 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2370 AS2 (mov,__zero_reg__,r27) CR_TAB
2371 AS2 (adiw,r26,%o0) CR_TAB
2372 AS2 (st,X+,r24) CR_TAB
2373 AS2 (st,X+,r25) CR_TAB
2374 AS2 (st,X+,__tmp_reg__) CR_TAB
2375 AS2 (st,X,__zero_reg__) CR_TAB
2376 AS1 (clr,__zero_reg__) CR_TAB
2377 AS2 (sbiw,r26,%o0+3));
2380 return (AS2 (adiw,r26,%o0) CR_TAB
2381 AS2 (st,X+,%A1) CR_TAB
2382 AS2 (st,X+,%B1) CR_TAB
2383 AS2 (st,X+,%C1) CR_TAB
2384 AS2 (st,X,%D1) CR_TAB
2385 AS2 (sbiw,r26,%o0+3));
2387 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2388 AS2 (std,%B0,%B1) CR_TAB
2389 AS2 (std,%C0,%C1) CR_TAB
2392 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2393 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2394 AS2 (st,%0,%C1) CR_TAB
2395 AS2 (st,%0,%B1) CR_TAB
2397 else if (GET_CODE (base) == POST_INC) /* (R++) */
2398 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2399 AS2 (st,%0,%B1) CR_TAB
2400 AS2 (st,%0,%C1) CR_TAB
2402 fatal_insn ("unknown move insn:",insn);
2407 output_movsisf(insn, operands, l)
2413 rtx dest = operands[0];
2414 rtx src = operands[1];
2420 if (register_operand (dest, VOIDmode))
2422 if (register_operand (src, VOIDmode)) /* mov r,r */
2424 if (true_regnum (dest) > true_regnum (src))
2429 return (AS2 (movw,%C0,%C1) CR_TAB
2430 AS2 (movw,%A0,%A1));
2433 return (AS2 (mov,%D0,%D1) CR_TAB
2434 AS2 (mov,%C0,%C1) CR_TAB
2435 AS2 (mov,%B0,%B1) CR_TAB
2443 return (AS2 (movw,%A0,%A1) CR_TAB
2444 AS2 (movw,%C0,%C1));
2447 return (AS2 (mov,%A0,%A1) CR_TAB
2448 AS2 (mov,%B0,%B1) CR_TAB
2449 AS2 (mov,%C0,%C1) CR_TAB
2453 else if (CONSTANT_P (src))
2455 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2457 if (byte_immediate_operand (src, SImode)
2458 && reg_was_0 (insn, dest))
2461 return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0));
2465 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2466 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2467 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2468 AS2 (ldi,%D0,hhi8(%1)));
2471 if (GET_CODE (src) == CONST_INT)
2473 const char *const clr_op0 =
2474 AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
2475 AS1 (clr,%B0) CR_TAB
2477 : (AS1 (clr,%A0) CR_TAB
2478 AS1 (clr,%B0) CR_TAB
2479 AS1 (clr,%C0) CR_TAB
2482 if (src == const0_rtx) /* mov r,L */
2484 *l = AVR_ENHANCED ? 3 : 4;
2487 else if (src == const1_rtx)
2489 if (reg_was_0 (insn, dest))
2492 return AS1 (inc,%A0 ; reg_was_0);
2495 output_asm_insn (clr_op0, operands);
2496 *l = AVR_ENHANCED ? 4 : 5;
2497 return AS1 (inc,%A0);
2499 else if (src == constm1_rtx)
2501 /* Immediate constants -1 to any register */
2502 if (reg_was_0 (insn, dest))
2507 return (AS1 (dec,%A0) CR_TAB
2508 AS1 (dec,%B0) CR_TAB
2509 AS2 (movw,%C0,%A0));
2512 return (AS1 (dec,%D0 ; reg_was_0) CR_TAB
2513 AS1 (dec,%C0) CR_TAB
2514 AS1 (dec,%B0) CR_TAB
2520 return (AS1 (clr,%A0) CR_TAB
2521 AS1 (dec,%A0) CR_TAB
2522 AS2 (mov,%B0,%A0) CR_TAB
2523 AS2 (movw,%C0,%A0));
2526 return (AS1 (clr,%A0) CR_TAB
2527 AS1 (dec,%A0) CR_TAB
2528 AS2 (mov,%B0,%A0) CR_TAB
2529 AS2 (mov,%C0,%A0) CR_TAB
2534 int bit_nr = exact_log2 (INTVAL (src));
2538 if (reg_was_0 (insn, dest))
2542 output_asm_insn ("set ; reg_was_0", operands);
2546 *l = AVR_ENHANCED ? 5 : 6;
2549 output_asm_insn (clr_op0, operands);
2550 output_asm_insn ("set", operands);
2554 avr_output_bld (operands, bit_nr);
2561 /* Last resort, better than loading from memory. */
2563 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2564 AS2 (ldi,r31,lo8(%1)) CR_TAB
2565 AS2 (mov,%A0,r31) CR_TAB
2566 AS2 (ldi,r31,hi8(%1)) CR_TAB
2567 AS2 (mov,%B0,r31) CR_TAB
2568 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2569 AS2 (mov,%C0,r31) CR_TAB
2570 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2571 AS2 (mov,%D0,r31) CR_TAB
2572 AS2 (mov,r31,__tmp_reg__));
2574 else if (GET_CODE (src) == MEM)
2575 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2577 else if (GET_CODE (dest) == MEM)
2579 const char *template;
2581 if (src == const0_rtx)
2582 operands[1] = zero_reg_rtx;
2584 template = out_movsi_mr_r (insn, operands, real_l);
2587 output_asm_insn (template, operands);
2592 fatal_insn ("invalid insn:", insn);
2597 out_movqi_mr_r (insn, op, l)
2600 int *l; /* instruction length */
2604 rtx x = XEXP (dest, 0);
2610 if (CONSTANT_ADDRESS_P (x))
2612 if (avr_io_address_p (x, 1))
2615 return AS2 (out,%0-0x20,%1);
2618 return AS2 (sts,%0,%1);
2620 /* memory access by reg+disp */
2621 else if (GET_CODE (x) == PLUS
2622 && REG_P (XEXP (x,0))
2623 && GET_CODE (XEXP (x,1)) == CONST_INT)
2625 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
2627 int disp = INTVAL (XEXP (x,1));
2628 if (REGNO (XEXP (x,0)) != REG_Y)
2629 fatal_insn ("incorrect insn:",insn);
2631 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2632 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2633 AS2 (std,Y+63,%1) CR_TAB
2634 AS2 (sbiw,r28,%o0-63));
2636 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2637 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2638 AS2 (st,Y,%1) CR_TAB
2639 AS2 (subi,r28,lo8(%o0)) CR_TAB
2640 AS2 (sbci,r29,hi8(%o0)));
2642 else if (REGNO (XEXP (x,0)) == REG_X)
2644 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
2646 if (reg_unused_after (insn, XEXP (x,0)))
2647 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2648 AS2 (adiw,r26,%o0) CR_TAB
2649 AS2 (st,X,__tmp_reg__));
2651 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2652 AS2 (adiw,r26,%o0) CR_TAB
2653 AS2 (st,X,__tmp_reg__) CR_TAB
2654 AS2 (sbiw,r26,%o0));
2658 if (reg_unused_after (insn, XEXP (x,0)))
2659 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2662 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2663 AS2 (st,X,%1) CR_TAB
2664 AS2 (sbiw,r26,%o0));
2668 return AS2 (std,%0,%1);
2671 return AS2 (st,%0,%1);
2675 out_movhi_mr_r (insn, op, l)
2682 rtx base = XEXP (dest, 0);
2683 int reg_base = true_regnum (base);
2684 int reg_src = true_regnum (src);
2688 if (CONSTANT_ADDRESS_P (base))
2690 if (avr_io_address_p (base, 2))
2693 return (AS2 (out,%B0-0x20,%B1) CR_TAB
2694 AS2 (out,%A0-0x20,%A1));
2696 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2701 if (reg_base == REG_X)
2703 if (reg_src == REG_X)
2705 /* "st X+,r26" is undefined */
2706 if (reg_unused_after (insn, src))
2707 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2708 AS2 (st,X,r26) CR_TAB
2709 AS2 (adiw,r26,1) CR_TAB
2710 AS2 (st,X,__tmp_reg__));
2712 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2713 AS2 (st,X,r26) CR_TAB
2714 AS2 (adiw,r26,1) CR_TAB
2715 AS2 (st,X,__tmp_reg__) CR_TAB
2720 if (reg_unused_after (insn, base))
2721 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2724 return *l=3, (AS2 (st ,X+,%A1) CR_TAB
2725 AS2 (st ,X,%B1) CR_TAB
2730 return *l=2, (AS2 (st ,%0,%A1) CR_TAB
2731 AS2 (std,%0+1,%B1));
2733 else if (GET_CODE (base) == PLUS)
2735 int disp = INTVAL (XEXP (base, 1));
2736 reg_base = REGNO (XEXP (base, 0));
2737 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2739 if (reg_base != REG_Y)
2740 fatal_insn ("incorrect insn:",insn);
2742 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2743 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
2744 AS2 (std,Y+62,%A1) CR_TAB
2745 AS2 (std,Y+63,%B1) CR_TAB
2746 AS2 (sbiw,r28,%o0-62));
2748 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2749 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2750 AS2 (st,Y,%A1) CR_TAB
2751 AS2 (std,Y+1,%B1) CR_TAB
2752 AS2 (subi,r28,lo8(%o0)) CR_TAB
2753 AS2 (sbci,r29,hi8(%o0)));
2755 if (reg_base == REG_X)
2758 if (reg_src == REG_X)
2761 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2762 AS2 (mov,__zero_reg__,r27) CR_TAB
2763 AS2 (adiw,r26,%o0) CR_TAB
2764 AS2 (st,X+,__tmp_reg__) CR_TAB
2765 AS2 (st,X,__zero_reg__) CR_TAB
2766 AS1 (clr,__zero_reg__) CR_TAB
2767 AS2 (sbiw,r26,%o0+1));
2770 return (AS2 (adiw,r26,%o0) CR_TAB
2771 AS2 (st,X+,%A1) CR_TAB
2772 AS2 (st,X,%B1) CR_TAB
2773 AS2 (sbiw,r26,%o0+1));
2775 return *l=2, (AS2 (std,%A0,%A1) CR_TAB
2778 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2779 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2781 else if (GET_CODE (base) == POST_INC) /* (R++) */
2782 return *l=2, (AS2 (st,%0,%A1) CR_TAB
2784 fatal_insn ("unknown move insn:",insn);
2788 /* Return 1 if frame pointer for current function required */
2791 frame_pointer_required_p ()
2793 return (current_function_calls_alloca
2794 || current_function_args_info.nregs == 0
2795 || get_frame_size () > 0);
2798 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2801 compare_condition (insn)
2804 rtx next = next_real_insn (insn);
2805 RTX_CODE cond = UNKNOWN;
2806 if (next && GET_CODE (next) == JUMP_INSN)
2808 rtx pat = PATTERN (next);
2809 rtx src = SET_SRC (pat);
2810 rtx t = XEXP (src, 0);
2811 cond = GET_CODE (t);
2816 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2819 compare_sign_p (insn)
2822 RTX_CODE cond = compare_condition (insn);
2823 return (cond == GE || cond == LT);
2826 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2827 that needs to be swapped (GT, GTU, LE, LEU). */
2830 compare_diff_p (insn)
2833 RTX_CODE cond = compare_condition (insn);
2834 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2837 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2843 RTX_CODE cond = compare_condition (insn);
2844 return (cond == EQ || cond == NE);
2848 /* Output test instruction for HImode */
2855 if (compare_sign_p (insn))
2858 return AS1 (tst,%B0);
2860 if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2861 && compare_eq_p (insn))
2863 /* faster than sbiw if we can clobber the operand */
2865 return AS2 (or,%A0,%B0);
2867 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2870 return AS2 (sbiw,%0,0);
2873 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2874 AS2 (cpc,%B0,__zero_reg__));
2878 /* Output test instruction for SImode */
2885 if (compare_sign_p (insn))
2888 return AS1 (tst,%D0);
2890 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2893 return (AS2 (sbiw,%A0,0) CR_TAB
2894 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2895 AS2 (cpc,%D0,__zero_reg__));
2898 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2899 AS2 (cpc,%B0,__zero_reg__) CR_TAB
2900 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2901 AS2 (cpc,%D0,__zero_reg__));
2905 /* Generate asm equivalent for various shifts.
2906 Shift count is a CONST_INT, MEM or REG.
2907 This only handles cases that are not already
2908 carefully hand-optimized in ?sh??i3_out. */
2911 out_shift_with_cnt (template, insn, operands, len, t_len)
2912 const char *template;
2916 int t_len; /* Length of template. */
2920 int second_label = 1;
2921 int saved_in_tmp = 0;
2922 int use_zero_reg = 0;
2924 op[0] = operands[0];
2925 op[1] = operands[1];
2926 op[2] = operands[2];
2927 op[3] = operands[3];
2933 if (GET_CODE (operands[2]) == CONST_INT)
2935 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2936 int count = INTVAL (operands[2]);
2937 int max_len = 10; /* If larger than this, always use a loop. */
2939 if (count < 8 && !scratch)
2943 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2945 if (t_len * count <= max_len)
2947 /* Output shifts inline with no loop - faster. */
2949 *len = t_len * count;
2953 output_asm_insn (template, op);
2962 strcat (str, AS2 (ldi,%3,%2));
2964 else if (use_zero_reg)
2966 /* Hack to save one word: use __zero_reg__ as loop counter.
2967 Set one bit, then shift in a loop until it is 0 again. */
2969 op[3] = zero_reg_rtx;
2973 strcat (str, ("set" CR_TAB
2974 AS2 (bld,%3,%2-1)));
2978 /* No scratch register available, use one from LD_REGS (saved in
2979 __tmp_reg__) that doesn't overlap with registers to shift. */
2981 op[3] = gen_rtx (REG, QImode,
2982 ((true_regnum (operands[0]) - 1) & 15) + 16);
2983 op[4] = tmp_reg_rtx;
2987 *len = 3; /* Includes "mov %3,%4" after the loop. */
2989 strcat (str, (AS2 (mov,%4,%3) CR_TAB
2995 else if (GET_CODE (operands[2]) == MEM)
2999 op[3] = op_mov[0] = tmp_reg_rtx;
3003 out_movqi_r_mr (insn, op_mov, len);
3005 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
3007 else if (register_operand (operands[2], QImode))
3009 if (reg_unused_after (insn, operands[2]))
3013 op[3] = tmp_reg_rtx;
3015 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
3019 fatal_insn ("bad shift insn:", insn);
3026 strcat (str, AS1 (rjmp,2f));
3030 *len += t_len + 2; /* template + dec + brXX */
3033 strcat (str, "\n1:\t");
3034 strcat (str, template);
3035 strcat (str, second_label ? "\n2:\t" : "\n\t");
3036 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
3037 strcat (str, CR_TAB);
3038 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
3040 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
3041 output_asm_insn (str, op);
3046 /* 8bit shift left ((char)x << i) */
3049 ashlqi3_out (insn, operands, len)
3052 int *len; /* insn length (may be NULL) */
3054 if (GET_CODE (operands[2]) == CONST_INT)
3061 switch (INTVAL (operands[2]))
3065 return AS1 (clr,%0);
3069 return AS1 (lsl,%0);
3073 return (AS1 (lsl,%0) CR_TAB
3078 return (AS1 (lsl,%0) CR_TAB
3083 if (test_hard_reg_class (LD_REGS, operands[0]))
3086 return (AS1 (swap,%0) CR_TAB
3087 AS2 (andi,%0,0xf0));
3090 return (AS1 (lsl,%0) CR_TAB
3096 if (test_hard_reg_class (LD_REGS, operands[0]))
3099 return (AS1 (swap,%0) CR_TAB
3101 AS2 (andi,%0,0xe0));
3104 return (AS1 (lsl,%0) CR_TAB
3111 if (test_hard_reg_class (LD_REGS, operands[0]))
3114 return (AS1 (swap,%0) CR_TAB
3117 AS2 (andi,%0,0xc0));
3120 return (AS1 (lsl,%0) CR_TAB
3129 return (AS1 (ror,%0) CR_TAB
3134 else if (CONSTANT_P (operands[2]))
3135 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3137 out_shift_with_cnt (AS1 (lsl,%0),
3138 insn, operands, len, 1);
3143 /* 16bit shift left ((short)x << i) */
3146 ashlhi3_out (insn, operands, len)
3151 if (GET_CODE (operands[2]) == CONST_INT)
3153 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3154 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3161 switch (INTVAL (operands[2]))
3164 if (optimize_size && scratch)
3169 return (AS1 (swap,%A0) CR_TAB
3170 AS1 (swap,%B0) CR_TAB
3171 AS2 (andi,%B0,0xf0) CR_TAB
3172 AS2 (eor,%B0,%A0) CR_TAB
3173 AS2 (andi,%A0,0xf0) CR_TAB
3179 return (AS1 (swap,%A0) CR_TAB
3180 AS1 (swap,%B0) CR_TAB
3181 AS2 (ldi,%3,0xf0) CR_TAB
3182 AS2 (and,%B0,%3) CR_TAB
3183 AS2 (eor,%B0,%A0) CR_TAB
3184 AS2 (and,%A0,%3) CR_TAB
3187 break; /* optimize_size ? 6 : 8 */
3191 break; /* scratch ? 5 : 6 */
3195 return (AS1 (lsl,%A0) CR_TAB
3196 AS1 (rol,%B0) CR_TAB
3197 AS1 (swap,%A0) CR_TAB
3198 AS1 (swap,%B0) CR_TAB
3199 AS2 (andi,%B0,0xf0) CR_TAB
3200 AS2 (eor,%B0,%A0) CR_TAB
3201 AS2 (andi,%A0,0xf0) CR_TAB
3207 return (AS1 (lsl,%A0) CR_TAB
3208 AS1 (rol,%B0) CR_TAB
3209 AS1 (swap,%A0) CR_TAB
3210 AS1 (swap,%B0) CR_TAB
3211 AS2 (ldi,%3,0xf0) CR_TAB
3212 AS2 (and,%B0,%3) CR_TAB
3213 AS2 (eor,%B0,%A0) CR_TAB
3214 AS2 (and,%A0,%3) CR_TAB
3221 break; /* scratch ? 5 : 6 */
3223 return (AS1 (clr,__tmp_reg__) CR_TAB
3224 AS1 (lsr,%B0) CR_TAB
3225 AS1 (ror,%A0) CR_TAB
3226 AS1 (ror,__tmp_reg__) CR_TAB
3227 AS1 (lsr,%B0) CR_TAB
3228 AS1 (ror,%A0) CR_TAB
3229 AS1 (ror,__tmp_reg__) CR_TAB
3230 AS2 (mov,%B0,%A0) CR_TAB
3231 AS2 (mov,%A0,__tmp_reg__));
3235 return (AS1 (lsr,%B0) CR_TAB
3236 AS2 (mov,%B0,%A0) CR_TAB
3237 AS1 (clr,%A0) CR_TAB
3238 AS1 (ror,%B0) CR_TAB
3242 if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
3243 return *len = 1, AS1 (clr,%A0);
3245 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3250 return (AS2 (mov,%B0,%A0) CR_TAB
3251 AS1 (clr,%A0) CR_TAB
3256 return (AS2 (mov,%B0,%A0) CR_TAB
3257 AS1 (clr,%A0) CR_TAB
3258 AS1 (lsl,%B0) CR_TAB
3263 return (AS2 (mov,%B0,%A0) CR_TAB
3264 AS1 (clr,%A0) CR_TAB
3265 AS1 (lsl,%B0) CR_TAB
3266 AS1 (lsl,%B0) CR_TAB
3273 return (AS2 (mov,%B0,%A0) CR_TAB
3274 AS1 (clr,%A0) CR_TAB
3275 AS1 (swap,%B0) CR_TAB
3276 AS2 (andi,%B0,0xf0));
3281 return (AS2 (mov,%B0,%A0) CR_TAB
3282 AS1 (clr,%A0) CR_TAB
3283 AS1 (swap,%B0) CR_TAB
3284 AS2 (ldi,%3,0xf0) CR_TAB
3288 return (AS2 (mov,%B0,%A0) CR_TAB
3289 AS1 (clr,%A0) CR_TAB
3290 AS1 (lsl,%B0) CR_TAB
3291 AS1 (lsl,%B0) CR_TAB
3292 AS1 (lsl,%B0) CR_TAB
3299 return (AS2 (mov,%B0,%A0) CR_TAB
3300 AS1 (clr,%A0) CR_TAB
3301 AS1 (swap,%B0) CR_TAB
3302 AS1 (lsl,%B0) CR_TAB
3303 AS2 (andi,%B0,0xe0));
3305 if (AVR_ENHANCED && scratch)
3308 return (AS2 (ldi,%3,0x20) CR_TAB
3309 AS2 (mul,%A0,%3) CR_TAB
3310 AS2 (mov,%B0,r0) CR_TAB
3311 AS1 (clr,%A0) CR_TAB
3312 AS1 (clr,__zero_reg__));
3314 if (optimize_size && scratch)
3319 return (AS2 (mov,%B0,%A0) CR_TAB
3320 AS1 (clr,%A0) CR_TAB
3321 AS1 (swap,%B0) CR_TAB
3322 AS1 (lsl,%B0) CR_TAB
3323 AS2 (ldi,%3,0xe0) CR_TAB
3329 return ("set" CR_TAB
3330 AS2 (bld,r1,5) CR_TAB
3331 AS2 (mul,%A0,r1) CR_TAB
3332 AS2 (mov,%B0,r0) CR_TAB
3333 AS1 (clr,%A0) CR_TAB
3334 AS1 (clr,__zero_reg__));
3337 return (AS2 (mov,%B0,%A0) CR_TAB
3338 AS1 (clr,%A0) CR_TAB
3339 AS1 (lsl,%B0) CR_TAB
3340 AS1 (lsl,%B0) CR_TAB
3341 AS1 (lsl,%B0) CR_TAB
3342 AS1 (lsl,%B0) CR_TAB
3346 if (AVR_ENHANCED && ldi_ok)
3349 return (AS2 (ldi,%B0,0x40) CR_TAB
3350 AS2 (mul,%A0,%B0) CR_TAB
3351 AS2 (mov,%B0,r0) CR_TAB
3352 AS1 (clr,%A0) CR_TAB
3353 AS1 (clr,__zero_reg__));
3355 if (AVR_ENHANCED && scratch)
3358 return (AS2 (ldi,%3,0x40) CR_TAB
3359 AS2 (mul,%A0,%3) CR_TAB
3360 AS2 (mov,%B0,r0) CR_TAB
3361 AS1 (clr,%A0) CR_TAB
3362 AS1 (clr,__zero_reg__));
3364 if (optimize_size && ldi_ok)
3367 return (AS2 (mov,%B0,%A0) CR_TAB
3368 AS2 (ldi,%A0,6) "\n1:\t"
3369 AS1 (lsl,%B0) CR_TAB
3370 AS1 (dec,%A0) CR_TAB
3373 if (optimize_size && scratch)
3376 return (AS1 (clr,%B0) CR_TAB
3377 AS1 (lsr,%A0) CR_TAB
3378 AS1 (ror,%B0) CR_TAB
3379 AS1 (lsr,%A0) CR_TAB
3380 AS1 (ror,%B0) CR_TAB
3385 return (AS1 (clr,%B0) CR_TAB
3386 AS1 (lsr,%A0) CR_TAB
3387 AS1 (ror,%B0) CR_TAB
3392 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3394 insn, operands, len, 2);
3399 /* 32bit shift left ((long)x << i) */
3402 ashlsi3_out (insn, operands, len)
3407 if (GET_CODE (operands[2]) == CONST_INT)
3415 switch (INTVAL (operands[2]))
3419 int reg0 = true_regnum (operands[0]);
3420 int reg1 = true_regnum (operands[1]);
3423 return (AS2 (mov,%D0,%C1) CR_TAB
3424 AS2 (mov,%C0,%B1) CR_TAB
3425 AS2 (mov,%B0,%A1) CR_TAB
3427 else if (reg0 + 1 == reg1)
3430 return AS1 (clr,%A0);
3433 return (AS1 (clr,%A0) CR_TAB
3434 AS2 (mov,%B0,%A1) CR_TAB
3435 AS2 (mov,%C0,%B1) CR_TAB
3441 int reg0 = true_regnum (operands[0]);
3442 int reg1 = true_regnum (operands[1]);
3444 if (AVR_ENHANCED && (reg0 + 2 != reg1))
3447 return (AS2 (movw,%C0,%A1) CR_TAB
3448 AS1 (clr,%B0) CR_TAB
3451 if (reg0 + 1 >= reg1)
3452 return (AS2 (mov,%D0,%B1) CR_TAB
3453 AS2 (mov,%C0,%A1) CR_TAB
3454 AS1 (clr,%B0) CR_TAB
3456 if (reg0 + 2 == reg1)
3459 return (AS1 (clr,%B0) CR_TAB
3463 return (AS2 (mov,%C0,%A1) CR_TAB
3464 AS2 (mov,%D0,%B1) CR_TAB
3465 AS1 (clr,%B0) CR_TAB
3471 if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
3472 return (AS2 (mov,%D0,%A1) CR_TAB
3473 AS1 (clr,%C0) CR_TAB
3474 AS1 (clr,%B0) CR_TAB
3479 return (AS1 (clr,%C0) CR_TAB
3480 AS1 (clr,%B0) CR_TAB
3486 return (AS1 (clr,%D0) CR_TAB
3487 AS1 (lsr,%A0) CR_TAB
3488 AS1 (ror,%D0) CR_TAB
3489 AS1 (clr,%C0) CR_TAB
3490 AS1 (clr,%B0) CR_TAB
3495 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3496 AS1 (rol,%B0) CR_TAB
3497 AS1 (rol,%C0) CR_TAB
3499 insn, operands, len, 4);
3503 /* 8bit arithmetic shift right ((signed char)x >> i) */
3506 ashrqi3_out (insn, operands, len)
3509 int *len; /* insn length */
3511 if (GET_CODE (operands[2]) == CONST_INT)
3518 switch (INTVAL (operands[2]))
3522 return AS1 (asr,%0);
3526 return (AS1 (asr,%0) CR_TAB
3531 return (AS1 (asr,%0) CR_TAB
3537 return (AS1 (asr,%0) CR_TAB
3544 return (AS1 (asr,%0) CR_TAB
3552 return (AS2 (bst,%0,6) CR_TAB
3554 AS2 (sbc,%0,%0) CR_TAB
3560 return (AS1 (lsl,%0) CR_TAB
3564 else if (CONSTANT_P (operands[2]))
3565 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3567 out_shift_with_cnt (AS1 (asr,%0),
3568 insn, operands, len, 1);
3573 /* 16bit arithmetic shift right ((signed short)x >> i) */
3576 ashrhi3_out (insn, operands, len)
3581 if (GET_CODE (operands[2]) == CONST_INT)
3583 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3584 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3591 switch (INTVAL (operands[2]))
3595 /* XXX try to optimize this too? */
3600 break; /* scratch ? 5 : 6 */
3602 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3603 AS2 (mov,%A0,%B0) CR_TAB
3604 AS1 (lsl,__tmp_reg__) CR_TAB
3605 AS1 (rol,%A0) CR_TAB
3606 AS2 (sbc,%B0,%B0) CR_TAB
3607 AS1 (lsl,__tmp_reg__) CR_TAB
3608 AS1 (rol,%A0) CR_TAB
3613 return (AS1 (lsl,%A0) CR_TAB
3614 AS2 (mov,%A0,%B0) CR_TAB
3615 AS1 (rol,%A0) CR_TAB
3620 int reg0 = true_regnum (operands[0]);
3621 int reg1 = true_regnum (operands[1]);
3624 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3625 AS1 (lsl,%B0) CR_TAB
3627 else if (reg0 == reg1 + 1)
3628 return *len = 3, (AS1 (clr,%B0) CR_TAB
3629 AS2 (sbrc,%A0,7) CR_TAB
3632 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3633 AS1 (clr,%B0) CR_TAB
3634 AS2 (sbrc,%A0,7) CR_TAB
3640 return (AS2 (mov,%A0,%B0) CR_TAB
3641 AS1 (lsl,%B0) CR_TAB
3642 AS2 (sbc,%B0,%B0) CR_TAB
3647 return (AS2 (mov,%A0,%B0) CR_TAB
3648 AS1 (lsl,%B0) CR_TAB
3649 AS2 (sbc,%B0,%B0) CR_TAB
3650 AS1 (asr,%A0) CR_TAB
3654 if (AVR_ENHANCED && ldi_ok)
3657 return (AS2 (ldi,%A0,0x20) CR_TAB
3658 AS2 (muls,%B0,%A0) CR_TAB
3659 AS2 (mov,%A0,r1) CR_TAB
3660 AS2 (sbc,%B0,%B0) CR_TAB
3661 AS1 (clr,__zero_reg__));
3663 if (optimize_size && scratch)
3666 return (AS2 (mov,%A0,%B0) CR_TAB
3667 AS1 (lsl,%B0) CR_TAB
3668 AS2 (sbc,%B0,%B0) CR_TAB
3669 AS1 (asr,%A0) CR_TAB
3670 AS1 (asr,%A0) CR_TAB
3674 if (AVR_ENHANCED && ldi_ok)
3677 return (AS2 (ldi,%A0,0x10) CR_TAB
3678 AS2 (muls,%B0,%A0) CR_TAB
3679 AS2 (mov,%A0,r1) CR_TAB
3680 AS2 (sbc,%B0,%B0) CR_TAB
3681 AS1 (clr,__zero_reg__));
3683 if (optimize_size && scratch)
3686 return (AS2 (mov,%A0,%B0) CR_TAB
3687 AS1 (lsl,%B0) CR_TAB
3688 AS2 (sbc,%B0,%B0) CR_TAB
3689 AS1 (asr,%A0) CR_TAB
3690 AS1 (asr,%A0) CR_TAB
3691 AS1 (asr,%A0) CR_TAB
3695 if (AVR_ENHANCED && ldi_ok)
3698 return (AS2 (ldi,%A0,0x08) CR_TAB
3699 AS2 (muls,%B0,%A0) CR_TAB
3700 AS2 (mov,%A0,r1) CR_TAB
3701 AS2 (sbc,%B0,%B0) CR_TAB
3702 AS1 (clr,__zero_reg__));
3705 break; /* scratch ? 5 : 7 */
3707 return (AS2 (mov,%A0,%B0) CR_TAB
3708 AS1 (lsl,%B0) CR_TAB
3709 AS2 (sbc,%B0,%B0) CR_TAB
3710 AS1 (asr,%A0) CR_TAB
3711 AS1 (asr,%A0) CR_TAB
3712 AS1 (asr,%A0) CR_TAB
3713 AS1 (asr,%A0) CR_TAB
3718 return (AS1 (lsl,%B0) CR_TAB
3719 AS2 (sbc,%A0,%A0) CR_TAB
3720 AS1 (lsl,%B0) CR_TAB
3721 AS2 (mov,%B0,%A0) CR_TAB
3725 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3726 AS2 (sbc,%A0,%A0) CR_TAB
3731 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3733 insn, operands, len, 2);
3738 /* 32bit arithmetic shift right ((signed long)x >> i) */
3741 ashrsi3_out (insn, operands, len)
3746 if (GET_CODE (operands[2]) == CONST_INT)
3754 switch (INTVAL (operands[2]))
3758 int reg0 = true_regnum (operands[0]);
3759 int reg1 = true_regnum (operands[1]);
3762 return (AS2 (mov,%A0,%B1) CR_TAB
3763 AS2 (mov,%B0,%C1) CR_TAB
3764 AS2 (mov,%C0,%D1) CR_TAB
3765 AS1 (clr,%D0) CR_TAB
3766 AS2 (sbrc,%C0,7) CR_TAB
3768 else if (reg0 == reg1 + 1)
3771 return (AS1 (clr,%D0) CR_TAB
3772 AS2 (sbrc,%C0,7) CR_TAB
3776 return (AS1 (clr,%D0) CR_TAB
3777 AS2 (sbrc,%D1,7) CR_TAB
3778 AS1 (dec,%D0) CR_TAB
3779 AS2 (mov,%C0,%D1) CR_TAB
3780 AS2 (mov,%B0,%C1) CR_TAB
3786 int reg0 = true_regnum (operands[0]);
3787 int reg1 = true_regnum (operands[1]);
3789 if (AVR_ENHANCED && (reg0 != reg1 + 2))
3792 return (AS2 (movw,%A0,%C1) CR_TAB
3793 AS1 (clr,%D0) CR_TAB
3794 AS2 (sbrc,%B0,7) CR_TAB
3795 AS1 (com,%D0) CR_TAB
3798 if (reg0 <= reg1 + 1)
3799 return (AS2 (mov,%A0,%C1) CR_TAB
3800 AS2 (mov,%B0,%D1) CR_TAB
3801 AS1 (clr,%D0) CR_TAB
3802 AS2 (sbrc,%B0,7) CR_TAB
3803 AS1 (com,%D0) CR_TAB
3805 else if (reg0 == reg1 + 2)
3806 return *len = 4, (AS1 (clr,%D0) CR_TAB
3807 AS2 (sbrc,%B0,7) CR_TAB
3808 AS1 (com,%D0) CR_TAB
3811 return (AS2 (mov,%B0,%D1) CR_TAB
3812 AS2 (mov,%A0,%C1) CR_TAB
3813 AS1 (clr,%D0) CR_TAB
3814 AS2 (sbrc,%B0,7) CR_TAB
3815 AS1 (com,%D0) CR_TAB
3820 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
3821 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3822 AS1 (clr,%D0) CR_TAB
3823 AS2 (sbrc,%A0,7) CR_TAB
3824 AS1 (com,%D0) CR_TAB
3825 AS2 (mov,%B0,%D0) CR_TAB
3828 return *len = 5, (AS1 (clr,%D0) CR_TAB
3829 AS2 (sbrc,%A0,7) CR_TAB
3830 AS1 (com,%D0) CR_TAB
3831 AS2 (mov,%B0,%D0) CR_TAB
3836 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3837 AS2 (sbc,%A0,%A0) CR_TAB
3838 AS2 (mov,%B0,%A0) CR_TAB
3839 AS2 (movw,%C0,%A0));
3841 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3842 AS2 (sbc,%A0,%A0) CR_TAB
3843 AS2 (mov,%B0,%A0) CR_TAB
3844 AS2 (mov,%C0,%A0) CR_TAB
3849 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3850 AS1 (ror,%C0) CR_TAB
3851 AS1 (ror,%B0) CR_TAB
3853 insn, operands, len, 4);
3857 /* 8bit logic shift right ((unsigned char)x >> i) */
3860 lshrqi3_out (insn, operands, len)
3865 if (GET_CODE (operands[2]) == CONST_INT)
3872 switch (INTVAL (operands[2]))
3876 return AS1 (clr,%0);
3880 return AS1 (lsr,%0);
3884 return (AS1 (lsr,%0) CR_TAB
3888 return (AS1 (lsr,%0) CR_TAB
3893 if (test_hard_reg_class (LD_REGS, operands[0]))
3896 return (AS1 (swap,%0) CR_TAB
3897 AS2 (andi,%0,0x0f));
3900 return (AS1 (lsr,%0) CR_TAB
3906 if (test_hard_reg_class (LD_REGS, operands[0]))
3909 return (AS1 (swap,%0) CR_TAB
3914 return (AS1 (lsr,%0) CR_TAB
3921 if (test_hard_reg_class (LD_REGS, operands[0]))
3924 return (AS1 (swap,%0) CR_TAB
3930 return (AS1 (lsr,%0) CR_TAB
3939 return (AS1 (rol,%0) CR_TAB
3944 else if (CONSTANT_P (operands[2]))
3945 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3947 out_shift_with_cnt (AS1 (lsr,%0),
3948 insn, operands, len, 1);
3952 /* 16bit logic shift right ((unsigned short)x >> i) */
3955 lshrhi3_out (insn, operands, len)
3960 if (GET_CODE (operands[2]) == CONST_INT)
3962 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3963 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3970 switch (INTVAL (operands[2]))
3973 if (optimize_size && scratch)
3978 return (AS1 (swap,%B0) CR_TAB
3979 AS1 (swap,%A0) CR_TAB
3980 AS2 (andi,%A0,0x0f) CR_TAB
3981 AS2 (eor,%A0,%B0) CR_TAB
3982 AS2 (andi,%B0,0x0f) CR_TAB
3988 return (AS1 (swap,%B0) CR_TAB
3989 AS1 (swap,%A0) CR_TAB
3990 AS2 (ldi,%3,0x0f) CR_TAB
3991 AS2 (and,%A0,%3) CR_TAB
3992 AS2 (eor,%A0,%B0) CR_TAB
3993 AS2 (and,%B0,%3) CR_TAB
3996 break; /* optimize_size ? 6 : 8 */
4000 break; /* scratch ? 5 : 6 */
4004 return (AS1 (lsr,%B0) CR_TAB
4005 AS1 (ror,%A0) CR_TAB
4006 AS1 (swap,%B0) CR_TAB
4007 AS1 (swap,%A0) CR_TAB
4008 AS2 (andi,%A0,0x0f) CR_TAB
4009 AS2 (eor,%A0,%B0) CR_TAB
4010 AS2 (andi,%B0,0x0f) CR_TAB
4016 return (AS1 (lsr,%B0) CR_TAB
4017 AS1 (ror,%A0) CR_TAB
4018 AS1 (swap,%B0) CR_TAB
4019 AS1 (swap,%A0) CR_TAB
4020 AS2 (ldi,%3,0x0f) CR_TAB
4021 AS2 (and,%A0,%3) CR_TAB
4022 AS2 (eor,%A0,%B0) CR_TAB
4023 AS2 (and,%B0,%3) CR_TAB
4030 break; /* scratch ? 5 : 6 */
4032 return (AS1 (clr,__tmp_reg__) CR_TAB
4033 AS1 (lsl,%A0) CR_TAB
4034 AS1 (rol,%B0) CR_TAB
4035 AS1 (rol,__tmp_reg__) CR_TAB
4036 AS1 (lsl,%A0) CR_TAB
4037 AS1 (rol,%B0) CR_TAB
4038 AS1 (rol,__tmp_reg__) CR_TAB
4039 AS2 (mov,%A0,%B0) CR_TAB
4040 AS2 (mov,%B0,__tmp_reg__));
4044 return (AS1 (lsl,%A0) CR_TAB
4045 AS2 (mov,%A0,%B0) CR_TAB
4046 AS1 (rol,%A0) CR_TAB
4047 AS2 (sbc,%B0,%B0) CR_TAB
4051 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
4052 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
4055 return *len = 1, AS1 (clr,%B0);
4059 return (AS2 (mov,%A0,%B0) CR_TAB
4060 AS1 (clr,%B0) CR_TAB
4065 return (AS2 (mov,%A0,%B0) CR_TAB
4066 AS1 (clr,%B0) CR_TAB
4067 AS1 (lsr,%A0) CR_TAB
4072 return (AS2 (mov,%A0,%B0) CR_TAB
4073 AS1 (clr,%B0) CR_TAB
4074 AS1 (lsr,%A0) CR_TAB
4075 AS1 (lsr,%A0) CR_TAB
4082 return (AS2 (mov,%A0,%B0) CR_TAB
4083 AS1 (clr,%B0) CR_TAB
4084 AS1 (swap,%A0) CR_TAB
4085 AS2 (andi,%A0,0x0f));
4090 return (AS2 (mov,%A0,%B0) CR_TAB
4091 AS1 (clr,%B0) CR_TAB
4092 AS1 (swap,%A0) CR_TAB
4093 AS2 (ldi,%3,0x0f) CR_TAB
4097 return (AS2 (mov,%A0,%B0) CR_TAB
4098 AS1 (clr,%B0) CR_TAB
4099 AS1 (lsr,%A0) CR_TAB
4100 AS1 (lsr,%A0) CR_TAB
4101 AS1 (lsr,%A0) CR_TAB
4108 return (AS2 (mov,%A0,%B0) CR_TAB
4109 AS1 (clr,%B0) CR_TAB
4110 AS1 (swap,%A0) CR_TAB
4111 AS1 (lsr,%A0) CR_TAB
4112 AS2 (andi,%A0,0x07));
4114 if (AVR_ENHANCED && scratch)
4117 return (AS2 (ldi,%3,0x08) CR_TAB
4118 AS2 (mul,%B0,%3) CR_TAB
4119 AS2 (mov,%A0,r1) CR_TAB
4120 AS1 (clr,%B0) CR_TAB
4121 AS1 (clr,__zero_reg__));
4123 if (optimize_size && scratch)
4128 return (AS2 (mov,%A0,%B0) CR_TAB
4129 AS1 (clr,%B0) CR_TAB
4130 AS1 (swap,%A0) CR_TAB
4131 AS1 (lsr,%A0) CR_TAB
4132 AS2 (ldi,%3,0x07) CR_TAB
4138 return ("set" CR_TAB
4139 AS2 (bld,r1,3) CR_TAB
4140 AS2 (mul,%B0,r1) CR_TAB
4141 AS2 (mov,%A0,r1) CR_TAB
4142 AS1 (clr,%B0) CR_TAB
4143 AS1 (clr,__zero_reg__));
4146 return (AS2 (mov,%A0,%B0) CR_TAB
4147 AS1 (clr,%B0) CR_TAB
4148 AS1 (lsr,%A0) CR_TAB
4149 AS1 (lsr,%A0) CR_TAB
4150 AS1 (lsr,%A0) CR_TAB
4151 AS1 (lsr,%A0) CR_TAB
4155 if (AVR_ENHANCED && ldi_ok)
4158 return (AS2 (ldi,%A0,0x04) CR_TAB
4159 AS2 (mul,%B0,%A0) CR_TAB
4160 AS2 (mov,%A0,r1) CR_TAB
4161 AS1 (clr,%B0) CR_TAB
4162 AS1 (clr,__zero_reg__));
4164 if (AVR_ENHANCED && scratch)
4167 return (AS2 (ldi,%3,0x04) CR_TAB
4168 AS2 (mul,%B0,%3) CR_TAB
4169 AS2 (mov,%A0,r1) CR_TAB
4170 AS1 (clr,%B0) CR_TAB
4171 AS1 (clr,__zero_reg__));
4173 if (optimize_size && ldi_ok)
4176 return (AS2 (mov,%A0,%B0) CR_TAB
4177 AS2 (ldi,%B0,6) "\n1:\t"
4178 AS1 (lsr,%A0) CR_TAB
4179 AS1 (dec,%B0) CR_TAB
4182 if (optimize_size && scratch)
4185 return (AS1 (clr,%A0) CR_TAB
4186 AS1 (lsl,%B0) CR_TAB
4187 AS1 (rol,%A0) CR_TAB
4188 AS1 (lsl,%B0) CR_TAB
4189 AS1 (rol,%A0) CR_TAB
4194 return (AS1 (clr,%A0) CR_TAB
4195 AS1 (lsl,%B0) CR_TAB
4196 AS1 (rol,%A0) CR_TAB
4201 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4203 insn, operands, len, 2);
4207 /* 32bit logic shift right ((unsigned int)x >> i) */
4210 lshrsi3_out (insn, operands, len)
4215 if (GET_CODE (operands[2]) == CONST_INT)
4223 switch (INTVAL (operands[2]))
4227 int reg0 = true_regnum (operands[0]);
4228 int reg1 = true_regnum (operands[1]);
4231 return (AS2 (mov,%A0,%B1) CR_TAB
4232 AS2 (mov,%B0,%C1) CR_TAB
4233 AS2 (mov,%C0,%D1) CR_TAB
4235 else if (reg0 == reg1 + 1)
4236 return *len = 1, AS1 (clr,%D0);
4238 return (AS1 (clr,%D0) CR_TAB
4239 AS2 (mov,%C0,%D1) CR_TAB
4240 AS2 (mov,%B0,%C1) CR_TAB
4246 int reg0 = true_regnum (operands[0]);
4247 int reg1 = true_regnum (operands[1]);
4249 if (AVR_ENHANCED && (reg0 != reg1 + 2))
4252 return (AS2 (movw,%A0,%C1) CR_TAB
4253 AS1 (clr,%C0) CR_TAB
4256 if (reg0 <= reg1 + 1)
4257 return (AS2 (mov,%A0,%C1) CR_TAB
4258 AS2 (mov,%B0,%D1) CR_TAB
4259 AS1 (clr,%C0) CR_TAB
4261 else if (reg0 == reg1 + 2)
4262 return *len = 2, (AS1 (clr,%C0) CR_TAB
4265 return (AS2 (mov,%B0,%D1) CR_TAB
4266 AS2 (mov,%A0,%C1) CR_TAB
4267 AS1 (clr,%C0) CR_TAB
4272 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
4273 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4274 AS1 (clr,%B0) CR_TAB
4275 AS1 (clr,%C0) CR_TAB
4278 return *len = 3, (AS1 (clr,%B0) CR_TAB
4279 AS1 (clr,%C0) CR_TAB
4284 return (AS1 (clr,%A0) CR_TAB
4285 AS2 (sbrc,%D0,7) CR_TAB
4286 AS1 (inc,%A0) CR_TAB
4287 AS1 (clr,%B0) CR_TAB
4288 AS1 (clr,%C0) CR_TAB
4293 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4294 AS1 (ror,%C0) CR_TAB
4295 AS1 (ror,%B0) CR_TAB
4297 insn, operands, len, 4);
4301 /* Modifies the length assigned to instruction INSN
4302 LEN is the initially computed length of the insn. */
4305 adjust_insn_length (insn, len)
4309 rtx patt = PATTERN (insn);
4312 if (GET_CODE (patt) == SET)
4315 op[1] = SET_SRC (patt);
4316 op[0] = SET_DEST (patt);
4317 if (general_operand (op[1], VOIDmode)
4318 && general_operand (op[0], VOIDmode))
4320 switch (GET_MODE (op[0]))
4323 output_movqi (insn, op, &len);
4326 output_movhi (insn, op, &len);
4330 output_movsisf (insn, op, &len);
4336 else if (op[0] == cc0_rtx && REG_P (op[1]))
4338 switch (GET_MODE (op[1]))
4340 case HImode: out_tsthi (insn,&len); break;
4341 case SImode: out_tstsi (insn,&len); break;
4345 else if (GET_CODE (op[1]) == AND)
4347 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4349 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4350 if (GET_MODE (op[1]) == SImode)
4351 len = (((mask & 0xff) != 0xff)
4352 + ((mask & 0xff00) != 0xff00)
4353 + ((mask & 0xff0000L) != 0xff0000L)
4354 + ((mask & 0xff000000L) != 0xff000000L));
4355 else if (GET_MODE (op[1]) == HImode)
4356 len = (((mask & 0xff) != 0xff)
4357 + ((mask & 0xff00) != 0xff00));
4360 else if (GET_CODE (op[1]) == IOR)
4362 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4364 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4365 if (GET_MODE (op[1]) == SImode)
4366 len = (((mask & 0xff) != 0)
4367 + ((mask & 0xff00) != 0)
4368 + ((mask & 0xff0000L) != 0)
4369 + ((mask & 0xff000000L) != 0));
4370 else if (GET_MODE (op[1]) == HImode)
4371 len = (((mask & 0xff) != 0)
4372 + ((mask & 0xff00) != 0));
4376 set = single_set (insn);
4381 op[1] = SET_SRC (set);
4382 op[0] = SET_DEST (set);
4384 if (GET_CODE (patt) == PARALLEL
4385 && general_operand (op[1], VOIDmode)
4386 && general_operand (op[0], VOIDmode))
4388 if (XVECLEN (patt, 0) == 2)
4389 op[2] = XVECEXP (patt, 0, 1);
4391 switch (GET_MODE (op[0]))
4397 output_reload_inhi (insn, op, &len);
4401 output_reload_insisf (insn, op, &len);
4407 else if (GET_CODE (op[1]) == ASHIFT
4408 || GET_CODE (op[1]) == ASHIFTRT
4409 || GET_CODE (op[1]) == LSHIFTRT)
4413 ops[1] = XEXP (op[1],0);
4414 ops[2] = XEXP (op[1],1);
4415 switch (GET_CODE (op[1]))
4418 switch (GET_MODE (op[0]))
4420 case QImode: ashlqi3_out (insn,ops,&len); break;
4421 case HImode: ashlhi3_out (insn,ops,&len); break;
4422 case SImode: ashlsi3_out (insn,ops,&len); break;
4427 switch (GET_MODE (op[0]))
4429 case QImode: ashrqi3_out (insn,ops,&len); break;
4430 case HImode: ashrhi3_out (insn,ops,&len); break;
4431 case SImode: ashrsi3_out (insn,ops,&len); break;
4436 switch (GET_MODE (op[0]))
4438 case QImode: lshrqi3_out (insn,ops,&len); break;
4439 case HImode: lshrhi3_out (insn,ops,&len); break;
4440 case SImode: lshrsi3_out (insn,ops,&len); break;
4452 /* Return nonzero if register REG dead after INSN */
4455 reg_unused_after (insn, reg)
4459 return (dead_or_set_p (insn, reg)
4460 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4463 /* Return nonzero if REG is not used after INSN.
4464 We assume REG is a reload reg, and therefore does
4465 not live past labels. It may live past calls or jumps though. */
4468 _reg_unused_after (insn, reg)
4475 /* If the reg is set by this instruction, then it is safe for our
4476 case. Disregard the case where this is a store to memory, since
4477 we are checking a register used in the store address. */
4478 set = single_set (insn);
4479 if (set && GET_CODE (SET_DEST (set)) != MEM
4480 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4483 while ((insn = NEXT_INSN (insn)))
4485 code = GET_CODE (insn);
4488 /* If this is a label that existed before reload, then the register
4489 if dead here. However, if this is a label added by reorg, then
4490 the register may still be live here. We can't tell the difference,
4491 so we just ignore labels completely. */
4492 if (code == CODE_LABEL)
4497 if (code == JUMP_INSN)
4500 /* If this is a sequence, we must handle them all at once.
4501 We could have for instance a call that sets the target register,
4502 and an insn in a delay slot that uses the register. In this case,
4503 we must return 0. */
4504 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4509 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4511 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4512 rtx set = single_set (this_insn);
4514 if (GET_CODE (this_insn) == CALL_INSN)
4516 else if (GET_CODE (this_insn) == JUMP_INSN)
4518 if (INSN_ANNULLED_BRANCH_P (this_insn))
4523 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4525 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4527 if (GET_CODE (SET_DEST (set)) != MEM)
4533 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4538 else if (code == JUMP_INSN)
4542 if (code == CALL_INSN)
4545 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4546 if (GET_CODE (XEXP (tem, 0)) == USE
4547 && REG_P (XEXP (XEXP (tem, 0), 0))
4548 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4550 if (call_used_regs[REGNO (reg)])
4554 if (GET_RTX_CLASS (code) == 'i')
4556 rtx set = single_set (insn);
4558 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4560 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4561 return GET_CODE (SET_DEST (set)) != MEM;
4562 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4569 /* Target hook for assembling integer objects. The AVR version needs
4570 special handling for references to certain labels. */
4573 avr_assemble_integer (x, size, aligned_p)
4578 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
4579 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
4580 || GET_CODE (x) == LABEL_REF))
4582 fputs ("\t.word\tpm(", asm_out_file);
4583 output_addr_const (asm_out_file, x);
4584 fputs (")\n", asm_out_file);
4587 return default_assemble_integer (x, size, aligned_p);
4590 /* Sets section name for declaration DECL */
4593 avr_unique_section (decl, reloc)
4595 int reloc ATTRIBUTE_UNUSED;
4598 const char *name, *prefix;
4601 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
4602 name = (* targetm.strip_name_encoding) (name);
4604 if (TREE_CODE (decl) == FUNCTION_DECL)
4606 if (flag_function_sections)
4614 if (flag_function_sections)
4616 len = strlen (name) + strlen (prefix);
4617 string = alloca (len + 1);
4618 sprintf (string, "%s%s", prefix, name);
4619 DECL_SECTION_NAME (decl) = build_string (len, string);
4624 /* The routine used to output NUL terminated strings. We use a special
4625 version of this for most svr4 targets because doing so makes the
4626 generated assembly code more compact (and thus faster to assemble)
4627 as well as more readable, especially for targets like the i386
4628 (where the only alternative is to output character sequences as
4629 comma separated lists of numbers). */
4632 gas_output_limited_string(file, str)
4636 const unsigned char *_limited_str = (unsigned char *) str;
4638 fprintf (file, "%s\"", STRING_ASM_OP);
4639 for (; (ch = *_limited_str); _limited_str++)
4642 switch (escape = ESCAPES[ch])
4648 fprintf (file, "\\%03o", ch);
4652 putc (escape, file);
4656 fprintf (file, "\"\n");
4659 /* The routine used to output sequences of byte values. We use a special
4660 version of this for most svr4 targets because doing so makes the
4661 generated assembly code more compact (and thus faster to assemble)
4662 as well as more readable. Note that if we find subparts of the
4663 character sequence which end with NUL (and which are shorter than
4664 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4667 gas_output_ascii(file, str, length)
4672 const unsigned char *_ascii_bytes = (const unsigned char *) str;
4673 const unsigned char *limit = _ascii_bytes + length;
4674 unsigned bytes_in_chunk = 0;
4675 for (; _ascii_bytes < limit; _ascii_bytes++)
4677 const unsigned char *p;
4678 if (bytes_in_chunk >= 60)
4680 fprintf (file, "\"\n");
4683 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4685 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4687 if (bytes_in_chunk > 0)
4689 fprintf (file, "\"\n");
4692 gas_output_limited_string (file, (char*)_ascii_bytes);
4699 if (bytes_in_chunk == 0)
4700 fprintf (file, "\t.ascii\t\"");
4701 switch (escape = ESCAPES[ch = *_ascii_bytes])
4708 fprintf (file, "\\%03o", ch);
4709 bytes_in_chunk += 4;
4713 putc (escape, file);
4714 bytes_in_chunk += 2;
4719 if (bytes_in_chunk > 0)
4720 fprintf (file, "\"\n");
4723 /* Return value is nonzero if pseudos that have been
4724 assigned to registers of class CLASS would likely be spilled
4725 because registers of CLASS are needed for spill registers. */
4728 class_likely_spilled_p (c)
4731 return (c != ALL_REGS && c != ADDW_REGS);
4734 /* Valid attributes:
4735 progmem - put data to program memory;
4736 signal - make a function to be hardware interrupt. After function
4737 prologue interrupts are disabled;
4738 interrupt - make a function to be hardware interrupt. After function
4739 prologue interrupts are enabled;
4740 naked - don't generate function prologue/epilogue and `ret' command.
4742 Only `progmem' attribute valid for type. */
4744 const struct attribute_spec avr_attribute_table[] =
4746 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4747 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
4748 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4749 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4750 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4751 { NULL, 0, 0, false, false, false, NULL }
4754 /* Handle a "progmem" attribute; arguments as in
4755 struct attribute_spec.handler. */
4757 avr_handle_progmem_attribute (node, name, args, flags, no_add_attrs)
4760 tree args ATTRIBUTE_UNUSED;
4761 int flags ATTRIBUTE_UNUSED;
4766 if (TREE_CODE (*node) == TYPE_DECL)
4768 /* This is really a decl attribute, not a type attribute,
4769 but try to handle it for GCC 3.0 backwards compatibility. */
4771 tree type = TREE_TYPE (*node);
4772 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
4773 tree newtype = build_type_attribute_variant (type, attr);
4775 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
4776 TREE_TYPE (*node) = newtype;
4777 *no_add_attrs = true;
4779 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
4781 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
4783 warning ("only initialized variables can be placed into "
4784 "program memory area");
4785 *no_add_attrs = true;
4790 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
4791 *no_add_attrs = true;
4798 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4799 struct attribute_spec.handler. */
4801 avr_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
4804 tree args ATTRIBUTE_UNUSED;
4805 int flags ATTRIBUTE_UNUSED;
4808 if (TREE_CODE (*node) != FUNCTION_DECL)
4810 warning ("`%s' attribute only applies to functions",
4811 IDENTIFIER_POINTER (name));
4812 *no_add_attrs = true;
4818 /* Look for attribute `progmem' in DECL
4819 if found return 1, otherwise 0. */
4822 avr_progmem_p (decl)
4827 if (TREE_CODE (decl) != VAR_DECL)
4831 != lookup_attribute ("progmem", DECL_ATTRIBUTES (decl)))
4837 while (TREE_CODE (a) == ARRAY_TYPE);
4839 if (a == error_mark_node)
4842 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4848 /* Add the section attribute if the variable is in progmem. */
4851 avr_insert_attributes (node, attributes)
4855 if (TREE_CODE (node) == VAR_DECL
4856 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
4857 && avr_progmem_p (node))
4859 static const char dsec[] = ".progmem.data";
4860 *attributes = tree_cons (get_identifier ("section"),
4861 build_tree_list (NULL, build_string (strlen (dsec), dsec)),
4864 /* ??? This seems sketchy. Why can't the user declare the
4865 thing const in the first place? */
4866 TREE_READONLY (node) = 1;
4871 avr_section_type_flags (decl, name, reloc)
4876 unsigned int flags = default_section_type_flags (decl, name, reloc);
4878 if (strncmp (name, ".noinit", 7) == 0)
4880 if (decl && TREE_CODE (decl) == VAR_DECL
4881 && DECL_INITIAL (decl) == NULL_TREE)
4882 flags |= SECTION_BSS; /* @nobits */
4884 warning ("only uninitialized variables can be placed in the "
4891 /* Outputs to the stdio stream FILE some
4892 appropriate text to go at the start of an assembler file. */
4895 asm_file_start (file)
4899 error ("MCU `%s' supported for assembler only", avr_mcu_name);
4901 output_file_directive (file, main_input_filename);
4902 fprintf (file, "\t.arch %s\n", avr_mcu_name);
4903 fputs ("__SREG__ = 0x3f\n"
4905 "__SP_L__ = 0x3d\n", file);
4907 fputs ("__tmp_reg__ = 0\n"
4908 "__zero_reg__ = 1\n", file);
4910 /* FIXME: output these only if there is anything in the .data / .bss
4911 sections - some code size could be saved by not linking in the
4912 initialization code from libgcc if one or both sections are empty. */
4913 fputs ("\t.global __do_copy_data\n", file);
4914 fputs ("\t.global __do_clear_bss\n", file);
4916 commands_in_file = 0;
4917 commands_in_prologues = 0;
4918 commands_in_epilogues = 0;
4921 /* Outputs to the stdio stream FILE some
4922 appropriate text to go at the end of an assembler file. */
4927 fputs ("/* File ", asm_out_file);
4928 output_quoted_string (asm_out_file, main_input_filename);
4929 fprintf (asm_out_file,
4930 ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4933 commands_in_file - commands_in_prologues - commands_in_epilogues,
4934 commands_in_prologues, commands_in_epilogues);
4937 /* Choose the order in which to allocate hard registers for
4938 pseudo-registers local to a basic block.
4940 Store the desired register order in the array `reg_alloc_order'.
4941 Element 0 should be the register to allocate first; element 1, the
4942 next register; and so on. */
4945 order_regs_for_local_alloc ()
4948 static const int order_0[] = {
4956 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4960 static const int order_1[] = {
4968 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4972 static const int order_2[] = {
4981 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4986 const int *order = (TARGET_ORDER_1 ? order_1 :
4987 TARGET_ORDER_2 ? order_2 :
4989 for (i=0; i < ARRAY_SIZE (order_0); ++i)
4990 reg_alloc_order[i] = order[i];
4993 /* Calculate the cost of X code of the expression in which it is contained,
4994 found in OUTER_CODE */
4997 default_rtx_costs (X, code, outer_code)
5000 enum rtx_code outer_code;
5007 cost = 2 * GET_MODE_SIZE (GET_MODE (X));
5010 if (outer_code != SET)
5012 if (GET_CODE (XEXP (X,0)) == SYMBOL_REF)
5013 cost += 2 * GET_MODE_SIZE (GET_MODE (X));
5015 cost += GET_MODE_SIZE (GET_MODE (X));
5021 if (outer_code == SET)
5022 cost = GET_MODE_SIZE (GET_MODE (X));
5024 cost = -GET_MODE_SIZE (GET_MODE (X));
5027 if (outer_code == SET)
5028 cost = GET_MODE_SIZE (GET_MODE (X));
5034 if (outer_code == SET)
5036 if (X == stack_pointer_rtx)
5038 else if (GET_CODE (XEXP (X,1)) == CONST_INT)
5039 cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 :
5040 GET_MODE_SIZE (GET_MODE (X)));
5042 cost = GET_MODE_SIZE (GET_MODE (X));
5046 if (GET_CODE (XEXP (X,1)) == CONST_INT)
5047 cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0)));
5056 avr_rtx_costs (x, code, outer_code, total)
5058 int code, outer_code;
5066 if (outer_code == PLUS
5067 || outer_code == IOR
5068 || outer_code == AND
5069 || outer_code == MINUS
5070 || outer_code == SET
5076 if (outer_code == COMPARE
5078 && INTVAL (x) <= 255)
5093 cst = default_rtx_costs (x, code, outer_code);
5105 /* Calculate the cost of a memory address */
5108 avr_address_cost (x)
5111 if (GET_CODE (x) == PLUS
5112 && GET_CODE (XEXP (x,1)) == CONST_INT
5113 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
5114 && INTVAL (XEXP (x,1)) >= 61)
5116 if (CONSTANT_ADDRESS_P (x))
5118 if (avr_io_address_p (x, 1))
5125 /* EXTRA_CONSTRAINT helper */
5128 extra_constraint (x, c)
5133 && GET_CODE (x) == MEM
5134 && GET_CODE (XEXP (x,0)) == PLUS)
5136 if (TARGET_ALL_DEBUG)
5138 fprintf (stderr, ("extra_constraint:\n"
5139 "reload_completed: %d\n"
5140 "reload_in_progress: %d\n"),
5141 reload_completed, reload_in_progress);
5144 if (GET_CODE (x) == MEM
5145 && GET_CODE (XEXP (x,0)) == PLUS
5146 && REG_P (XEXP (XEXP (x,0), 0))
5147 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
5148 && (INTVAL (XEXP (XEXP (x,0), 1))
5149 <= MAX_LD_OFFSET (GET_MODE (x))))
5151 rtx xx = XEXP (XEXP (x,0), 0);
5152 int regno = REGNO (xx);
5153 if (TARGET_ALL_DEBUG)
5155 fprintf (stderr, ("extra_constraint:\n"
5156 "reload_completed: %d\n"
5157 "reload_in_progress: %d\n"),
5158 reload_completed, reload_in_progress);
5161 if (regno >= FIRST_PSEUDO_REGISTER)
5162 return 1; /* allocate pseudos */
5163 else if (regno == REG_Z || regno == REG_Y)
5164 return 1; /* strictly check */
5165 else if (xx == frame_pointer_rtx
5166 || xx == arg_pointer_rtx)
5167 return 1; /* XXX frame & arg pointer checks */
5173 /* Convert condition code CONDITION to the valid AVR condition code */
5176 avr_normalize_condition (condition)
5194 /* This fnction optimizes conditional jumps */
5201 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5203 if (! (GET_CODE (insn) == INSN
5204 || GET_CODE (insn) == CALL_INSN
5205 || GET_CODE (insn) == JUMP_INSN)
5206 || !single_set (insn))
5209 pattern = PATTERN (insn);
5211 if (GET_CODE (pattern) == PARALLEL)
5212 pattern = XVECEXP (pattern, 0, 0);
5213 if (GET_CODE (pattern) == SET
5214 && SET_DEST (pattern) == cc0_rtx
5215 && compare_diff_p (insn))
5217 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
5219 /* Now we work under compare insn */
5221 pattern = SET_SRC (pattern);
5222 if (true_regnum (XEXP (pattern,0)) >= 0
5223 && true_regnum (XEXP (pattern,1)) >= 0 )
5225 rtx x = XEXP (pattern,0);
5226 rtx next = next_real_insn (insn);
5227 rtx pat = PATTERN (next);
5228 rtx src = SET_SRC (pat);
5229 rtx t = XEXP (src,0);
5230 PUT_CODE (t, swap_condition (GET_CODE (t)));
5231 XEXP (pattern,0) = XEXP (pattern,1);
5232 XEXP (pattern,1) = x;
5233 INSN_CODE (next) = -1;
5235 else if (true_regnum (XEXP (pattern,0)) >= 0
5236 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
5238 rtx x = XEXP (pattern,1);
5239 rtx next = next_real_insn (insn);
5240 rtx pat = PATTERN (next);
5241 rtx src = SET_SRC (pat);
5242 rtx t = XEXP (src,0);
5243 enum machine_mode mode = GET_MODE (XEXP (pattern, 0));
5245 if (avr_simplify_comparision_p (mode, GET_CODE (t), x))
5247 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
5248 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
5249 INSN_CODE (next) = -1;
5250 INSN_CODE (insn) = -1;
5254 else if (true_regnum (SET_SRC (pattern)) >= 0)
5256 /* This is a tst insn */
5257 rtx next = next_real_insn (insn);
5258 rtx pat = PATTERN (next);
5259 rtx src = SET_SRC (pat);
5260 rtx t = XEXP (src,0);
5262 PUT_CODE (t, swap_condition (GET_CODE (t)));
5263 SET_SRC (pattern) = gen_rtx (NEG,
5264 GET_MODE (SET_SRC (pattern)),
5266 INSN_CODE (next) = -1;
5267 INSN_CODE (insn) = -1;
5273 /* Returns register number for function return value.*/
5281 /* Ceate an RTX representing the place where a
5282 library function returns a value of mode MODE. */
5285 avr_libcall_value (mode)
5286 enum machine_mode mode;
5288 int offs = GET_MODE_SIZE (mode);
5291 return gen_rtx (REG, mode, RET_REGISTER + 2 - offs);
5294 /* Create an RTX representing the place where a
5295 function returns a value of data type VALTYPE. */
5298 avr_function_value (type, func)
5300 tree func ATTRIBUTE_UNUSED;
5304 if (TYPE_MODE (type) != BLKmode)
5305 return avr_libcall_value (TYPE_MODE (type));
5307 offs = int_size_in_bytes (type);
5310 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5311 offs = GET_MODE_SIZE (SImode);
5312 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5313 offs = GET_MODE_SIZE (DImode);
5315 return gen_rtx (REG, BLKmode, RET_REGISTER + 2 - offs);
5318 /* Returns nonzero if the number MASK has only one bit set. */
5321 mask_one_bit_p (mask)
5325 unsigned HOST_WIDE_INT n=mask;
5326 for (i = 0; i < 32; ++i)
5328 if (n & 0x80000000L)
5330 if (n & 0x7fffffffL)
5341 /* Places additional restrictions on the register class to
5342 use when it is necessary to copy value X into a register
5346 preferred_reload_class (x, class)
5347 rtx x ATTRIBUTE_UNUSED;
5348 enum reg_class class;
5354 test_hard_reg_class (class, x)
5355 enum reg_class class;
5358 int regno = true_regnum (x);
5362 if (TEST_HARD_REG_CLASS (class, regno))
5370 jump_over_one_insn_p (insn, dest)
5374 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5377 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5378 int dest_addr = INSN_ADDRESSES (uid);
5379 return dest_addr - jump_addr == get_attr_length (insn) + 1;
5382 /* Returns 1 if a value of mode MODE can be stored starting with hard
5383 register number REGNO. On the enhanced core, anything larger than
5384 1 byte must start in even numbered register for "movw" to work
5385 (this way we don't have to check for odd registers everywhere). */
5388 avr_hard_regno_mode_ok (regno, mode)
5390 enum machine_mode mode;
5392 /* Bug workaround: recog.c (peep2_find_free_register) and probably
5393 a few other places assume that the frame pointer is a single hard
5394 register, so r29 may be allocated and overwrite the high byte of
5395 the frame pointer. Do not allow any value to start in r29. */
5396 if (regno == REG_Y + 1)
5401 /* if (regno < 24 && !AVR_ENHANCED)
5403 return !(regno & 1);
5406 /* Returns 1 if we know register operand OP was 0 before INSN. */
5409 reg_was_0 (insn, op)
5414 return (optimize > 0 && insn && op && REG_P (op)
5415 && (link = find_reg_note (insn, REG_WAS_0, 0))
5416 /* Make sure the insn that stored the 0 is still present. */
5417 && ! INSN_DELETED_P (XEXP (link, 0))
5418 && GET_CODE (XEXP (link, 0)) != NOTE
5419 /* Make sure cross jumping didn't happen here. */
5420 && no_labels_between_p (XEXP (link, 0), insn)
5421 /* Make sure the reg hasn't been clobbered. */
5422 && ! reg_set_between_p (op, XEXP (link, 0), insn));
5425 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5426 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5427 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
5430 avr_io_address_p (x, size)
5434 return (optimize > 0 && GET_CODE (x) == CONST_INT
5435 && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
5438 /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5441 const_int_pow2_p (x)
5444 if (GET_CODE (x) == CONST_INT)
5446 HOST_WIDE_INT d = INTVAL (x);
5447 HOST_WIDE_INT abs_d = (d >= 0) ? d : -d;
5448 return exact_log2 (abs_d) + 1;
5454 output_reload_inhi (insn, operands, len)
5455 rtx insn ATTRIBUTE_UNUSED;
5463 if (GET_CODE (operands[1]) == CONST_INT)
5465 int val = INTVAL (operands[1]);
5466 if ((val & 0xff) == 0)
5469 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5470 AS2 (ldi,%2,hi8(%1)) CR_TAB
5473 else if ((val & 0xff00) == 0)
5476 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5477 AS2 (mov,%A0,%2) CR_TAB
5478 AS2 (mov,%B0,__zero_reg__));
5480 else if ((val & 0xff) == ((val & 0xff00) >> 8))
5483 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5484 AS2 (mov,%A0,%2) CR_TAB
5489 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5490 AS2 (mov,%A0,%2) CR_TAB
5491 AS2 (ldi,%2,hi8(%1)) CR_TAB
5497 output_reload_insisf (insn, operands, len)
5498 rtx insn ATTRIBUTE_UNUSED;
5502 rtx src = operands[1];
5503 int cnst = (GET_CODE (src) == CONST_INT);
5508 *len = 4 + ((INTVAL (src) & 0xff) != 0)
5509 + ((INTVAL (src) & 0xff00) != 0)
5510 + ((INTVAL (src) & 0xff0000) != 0)
5511 + ((INTVAL (src) & 0xff000000) != 0);
5518 if (cnst && ((INTVAL (src) & 0xff) == 0))
5519 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5522 output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
5523 output_asm_insn (AS2 (mov, %A0, %2), operands);
5525 if (cnst && ((INTVAL (src) & 0xff00) == 0))
5526 output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
5529 output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
5530 output_asm_insn (AS2 (mov, %B0, %2), operands);
5532 if (cnst && ((INTVAL (src) & 0xff0000) == 0))
5533 output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
5536 output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
5537 output_asm_insn (AS2 (mov, %C0, %2), operands);
5539 if (cnst && ((INTVAL (src) & 0xff000000) == 0))
5540 output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
5543 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5544 output_asm_insn (AS2 (mov, %D0, %2), operands);
5550 avr_output_bld (operands, bit_nr)
5554 static char s[] = "bld %A0,0";
5556 s[5] = 'A' + (bit_nr >> 3);
5557 s[8] = '0' + (bit_nr & 7);
5558 output_asm_insn (s, operands);
5562 avr_output_addr_vec_elt (stream, value)
5567 fprintf (stream, "\t.word pm(.L%d)\n", value);
5569 fprintf (stream, "\trjmp .L%d\n", value);
5574 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5575 registers (for a define_peephole2) in the current function. */
5578 avr_peep2_scratch_safe (scratch)
5581 if ((interrupt_function_p (current_function_decl)
5582 || signal_function_p (current_function_decl))
5583 && leaf_function_p ())
5585 int first_reg = true_regnum (scratch);
5586 int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
5589 for (reg = first_reg; reg <= last_reg; reg++)
5591 if (!regs_ever_live[reg])
5598 /* Output a branch that tests a single bit of a register (QI, HI or SImode)
5599 or memory location in the I/O space (QImode only).
5601 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5602 Operand 1: register operand to test, or CONST_INT memory address.
5603 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5604 Operand 3: label to jump to if the test is true. */
5607 avr_out_sbxx_branch (insn, operands)
5611 enum rtx_code comp = GET_CODE (operands[0]);
5612 int long_jump = (get_attr_length (insn) >= 4);
5613 int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
5617 else if (comp == LT)
5621 comp = reverse_condition (comp);
5623 if (GET_CODE (operands[1]) == CONST_INT)
5625 if (INTVAL (operands[1]) < 0x40)
5628 output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
5630 output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
5634 output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
5636 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
5638 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
5641 else /* GET_CODE (operands[1]) == REG */
5643 if (GET_MODE (operands[1]) == QImode)
5646 output_asm_insn (AS2 (sbrs,%1,%2), operands);
5648 output_asm_insn (AS2 (sbrc,%1,%2), operands);
5650 else /* HImode or SImode */
5652 static char buf[] = "sbrc %A1,0";
5653 int bit_nr = exact_log2 (INTVAL (operands[2])
5654 & GET_MODE_MASK (GET_MODE (operands[1])));
5656 buf[3] = (comp == EQ) ? 's' : 'c';
5657 buf[6] = 'A' + (bit_nr >> 3);
5658 buf[9] = '0' + (bit_nr & 7);
5659 output_asm_insn (buf, operands);
5664 return (AS1 (rjmp,.+4) CR_TAB
5667 return AS1 (rjmp,%3);
5672 avr_asm_out_ctor (symbol, priority)
5676 fputs ("\t.global __do_global_ctors\n", asm_out_file);
5677 default_ctor_section_asm_out_constructor (symbol, priority);
5681 avr_asm_out_dtor (symbol, priority)
5685 fputs ("\t.global __do_global_dtors\n", asm_out_file);
5686 default_dtor_section_asm_out_destructor (symbol, priority);