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_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
67 static void avr_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
68 static void avr_unique_section PARAMS ((tree, int));
69 static void avr_insert_attributes PARAMS ((tree, tree *));
70 static unsigned int avr_section_type_flags PARAMS ((tree, const char *, int));
72 static void avr_reorg PARAMS ((void));
73 static void avr_asm_out_ctor PARAMS ((rtx, int));
74 static void avr_asm_out_dtor PARAMS ((rtx, int));
75 static int default_rtx_costs PARAMS ((rtx, enum rtx_code, enum rtx_code));
76 static bool avr_rtx_costs PARAMS ((rtx, int, int, int *));
77 static int avr_address_cost PARAMS ((rtx));
79 /* Allocate registers from r25 to r8 for parameters for function calls */
80 #define FIRST_CUM_REG 26
82 /* Temporary register RTX (gen_rtx (REG,QImode,TMP_REGNO)) */
85 /* Zeroed register RTX (gen_rtx (REG,QImode,ZERO_REGNO)) */
88 /* RTX for register which will be used for loading immediate values to
92 /* AVR register names {"r0", "r1", ..., "r31"} */
93 static const char *const avr_regnames[] = REGISTER_NAMES;
95 /* This holds the last insn address. */
96 static int last_insn_address = 0;
98 /* Commands count in the compiled file */
99 static int commands_in_file;
101 /* Commands in the functions prologues in the compiled file */
102 static int commands_in_prologues;
104 /* Commands in the functions epilogues in the compiled file */
105 static int commands_in_epilogues;
107 /* Prologue/Epilogue size in words */
108 static int prologue_size;
109 static int epilogue_size;
111 /* Size of all jump tables in the current function, in words. */
112 static int jump_tables_size;
114 /* Initial stack value specified by the `-minit-stack=' option */
115 const char *avr_init_stack = "__stack";
117 /* Default MCU name */
118 const char *avr_mcu_name = "avr2";
120 /* Preprocessor macros to define depending on MCU type. */
121 const char *avr_base_arch_macro;
122 const char *avr_extra_arch_macro;
124 /* More than 8K of program memory: use "call" and "jmp". */
127 /* Enhanced core: use "movw", "mul", ... */
128 int avr_enhanced_p = 0;
130 /* Assembler only. */
131 int avr_asm_only_p = 0;
137 const char *const macro;
140 static const struct base_arch_s avr_arch_types[] = {
141 { 1, 0, 0, NULL }, /* unknown device specified */
142 { 1, 0, 0, "__AVR_ARCH__=1" },
143 { 0, 0, 0, "__AVR_ARCH__=2" },
144 { 0, 0, 1, "__AVR_ARCH__=3" },
145 { 0, 1, 0, "__AVR_ARCH__=4" },
146 { 0, 1, 1, "__AVR_ARCH__=5" }
150 const char *const name;
151 int arch; /* index in avr_arch_types[] */
152 /* Must lie outside user's namespace. NULL == no macro. */
153 const char *const macro;
156 /* List of all known AVR MCU types - if updated, it has to be kept
157 in sync in several places (FIXME: is there a better way?):
159 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
160 - t-avr (MULTILIB_MATCHES)
161 - gas/config/tc-avr.c
164 static const struct mcu_type_s avr_mcu_types[] = {
165 /* Classic, <= 8K. */
167 { "at90s2313", 2, "__AVR_AT90S2313__" },
168 { "at90s2323", 2, "__AVR_AT90S2323__" },
169 { "at90s2333", 2, "__AVR_AT90S2333__" },
170 { "at90s2343", 2, "__AVR_AT90S2343__" },
171 { "attiny22", 2, "__AVR_ATtiny22__" },
172 { "attiny26", 2, "__AVR_ATtiny26__" },
173 { "at90s4414", 2, "__AVR_AT90S4414__" },
174 { "at90s4433", 2, "__AVR_AT90S4433__" },
175 { "at90s4434", 2, "__AVR_AT90S4434__" },
176 { "at90s8515", 2, "__AVR_AT90S8515__" },
177 { "at90c8534", 2, "__AVR_AT90C8534__" },
178 { "at90s8535", 2, "__AVR_AT90S8535__" },
179 { "at86rf401", 2, "__AVR_AT86RF401__" },
182 { "atmega103", 3, "__AVR_ATmega103__" },
183 { "atmega603", 3, "__AVR_ATmega603__" },
184 { "at43usb320", 3, "__AVR_AT43USB320__" },
185 { "at43usb355", 3, "__AVR_AT43USB355__" },
186 { "at76c711", 3, "__AVR_AT76C711__" },
187 /* Enhanced, <= 8K. */
189 { "atmega8", 4, "__AVR_ATmega8__" },
190 { "atmega8515", 4, "__AVR_ATmega8515__" },
191 { "atmega8535", 4, "__AVR_ATmega8535__" },
192 /* Enhanced, > 8K. */
194 { "atmega16", 5, "__AVR_ATmega16__" },
195 { "atmega161", 5, "__AVR_ATmega161__" },
196 { "atmega162", 5, "__AVR_ATmega162__" },
197 { "atmega163", 5, "__AVR_ATmega163__" },
198 { "atmega169", 5, "__AVR_ATmega169__" },
199 { "atmega32", 5, "__AVR_ATmega32__" },
200 { "atmega323", 5, "__AVR_ATmega323__" },
201 { "atmega64", 5, "__AVR_ATmega64__" },
202 { "atmega128", 5, "__AVR_ATmega128__" },
203 { "at94k", 5, "__AVR_AT94K__" },
204 /* Assembler only. */
206 { "at90s1200", 1, "__AVR_AT90S1200__" },
207 { "attiny11", 1, "__AVR_ATtiny11__" },
208 { "attiny12", 1, "__AVR_ATtiny12__" },
209 { "attiny15", 1, "__AVR_ATtiny15__" },
210 { "attiny28", 1, "__AVR_ATtiny28__" },
214 int avr_case_values_threshold = 30000;
216 /* Initialize the GCC target structure. */
217 #undef TARGET_ASM_ALIGNED_HI_OP
218 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
219 #undef TARGET_ASM_INTEGER
220 #define TARGET_ASM_INTEGER avr_assemble_integer
222 #undef TARGET_ASM_FUNCTION_PROLOGUE
223 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
224 #undef TARGET_ASM_FUNCTION_EPILOGUE
225 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
226 #undef TARGET_ATTRIBUTE_TABLE
227 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
228 #undef TARGET_ASM_UNIQUE_SECTION
229 #define TARGET_ASM_UNIQUE_SECTION avr_unique_section
230 #undef TARGET_INSERT_ATTRIBUTES
231 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
232 #undef TARGET_SECTION_TYPE_FLAGS
233 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
234 #undef TARGET_RTX_COSTS
235 #define TARGET_RTX_COSTS avr_rtx_costs
236 #undef TARGET_ADDRESS_COST
237 #define TARGET_ADDRESS_COST avr_address_cost
238 #undef TARGET_MACHINE_DEPENDENT_REORG
239 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
241 struct gcc_target targetm = TARGET_INITIALIZER;
244 avr_override_options ()
246 const struct mcu_type_s *t;
247 const struct base_arch_s *base;
249 for (t = avr_mcu_types; t->name; t++)
250 if (strcmp (t->name, avr_mcu_name) == 0)
255 fprintf (stderr, "unknown MCU `%s' specified\nKnown MCU names:\n",
257 for (t = avr_mcu_types; t->name; t++)
258 fprintf (stderr," %s\n", t->name);
261 base = &avr_arch_types[t->arch];
262 avr_asm_only_p = base->asm_only;
263 avr_enhanced_p = base->enhanced;
264 avr_mega_p = base->mega;
265 avr_base_arch_macro = base->macro;
266 avr_extra_arch_macro = t->macro;
268 if (optimize && !TARGET_NO_TABLEJUMP)
269 avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
273 /* Initialize TMP_REG_RTX and ZERO_REG_RTX */
277 tmp_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
278 memset (tmp_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
279 PUT_CODE (tmp_reg_rtx, REG);
280 PUT_MODE (tmp_reg_rtx, QImode);
281 XINT (tmp_reg_rtx, 0) = TMP_REGNO;
283 zero_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
284 memset (zero_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
285 PUT_CODE (zero_reg_rtx, REG);
286 PUT_MODE (zero_reg_rtx, QImode);
287 XINT (zero_reg_rtx, 0) = ZERO_REGNO;
289 ldi_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
290 memset (ldi_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
291 PUT_CODE (ldi_reg_rtx, REG);
292 PUT_MODE (ldi_reg_rtx, QImode);
293 XINT (ldi_reg_rtx, 0) = LDI_REG_REGNO;
296 /* return register class from register number */
298 static const int reg_class_tab[]={
299 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
300 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
301 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
302 GENERAL_REGS, /* r0 - r15 */
303 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
304 LD_REGS, /* r16 - 23 */
305 ADDW_REGS,ADDW_REGS, /* r24,r25 */
306 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
307 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
308 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
309 STACK_REG,STACK_REG /* SPL,SPH */
312 /* Return register class for register R */
315 avr_regno_reg_class (r)
319 return reg_class_tab[r];
324 /* A C expression which defines the machine-dependent operand
325 constraint letters for register classes. If C is such a
326 letter, the value should be the register class corresponding to
327 it. Otherwise, the value should be `NO_REGS'. The register
328 letter `r', corresponding to class `GENERAL_REGS', will not be
329 passed to this macro; you do not need to handle it. */
332 avr_reg_class_from_letter (c)
337 case 't' : return R0_REG;
338 case 'b' : return BASE_POINTER_REGS;
339 case 'e' : return POINTER_REGS;
340 case 'w' : return ADDW_REGS;
341 case 'd' : return LD_REGS;
342 case 'l' : return NO_LD_REGS;
343 case 'a' : return SIMPLE_LD_REGS;
344 case 'x' : return POINTER_X_REGS;
345 case 'y' : return POINTER_Y_REGS;
346 case 'z' : return POINTER_Z_REGS;
347 case 'q' : return STACK_REG;
353 /* Return nonzero if FUNC is a naked function. */
356 avr_naked_function_p (func)
361 if (TREE_CODE (func) != FUNCTION_DECL)
364 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
365 return a != NULL_TREE;
368 /* Return nonzero if FUNC is an interrupt function as specified
369 by the "interrupt" attribute. */
372 interrupt_function_p (func)
377 if (TREE_CODE (func) != FUNCTION_DECL)
380 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
381 return a != NULL_TREE;
384 /* Return nonzero if FUNC is a signal function as specified
385 by the "signal" attribute. */
388 signal_function_p (func)
393 if (TREE_CODE (func) != FUNCTION_DECL)
396 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
397 return a != NULL_TREE;
400 /* Return the number of hard registers to push/pop in the prologue/epilogue
401 of the current function, and optionally store these registers in SET. */
404 avr_regs_to_save (set)
408 int int_or_sig_p = (interrupt_function_p (current_function_decl)
409 || signal_function_p (current_function_decl));
410 int leaf_func_p = leaf_function_p ();
413 CLEAR_HARD_REG_SET (*set);
416 /* No need to save any registers if the function never returns. */
417 if (TREE_THIS_VOLATILE (current_function_decl))
420 for (reg = 0; reg < 32; reg++)
422 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
423 any global register variables. */
427 if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
428 || (regs_ever_live[reg]
429 && (int_or_sig_p || !call_used_regs[reg])
430 && !(frame_pointer_needed
431 && (reg == REG_Y || reg == (REG_Y+1)))))
434 SET_HARD_REG_BIT (*set, reg);
441 /* Compute offset between arg_pointer and frame_pointer */
444 initial_elimination_offset (from, to)
448 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
452 int offset = frame_pointer_needed ? 2 : 0;
454 offset += avr_regs_to_save (NULL);
455 return get_frame_size () + 2 + 1 + offset;
459 /* Return 1 if the function epilogue is just a single "ret". */
462 avr_simple_epilogue ()
464 return (! frame_pointer_needed
465 && get_frame_size () == 0
466 && avr_regs_to_save (NULL) == 0
467 && ! interrupt_function_p (current_function_decl)
468 && ! signal_function_p (current_function_decl)
469 && ! avr_naked_function_p (current_function_decl)
470 && ! MAIN_NAME_P (DECL_NAME (current_function_decl))
471 && ! TREE_THIS_VOLATILE (current_function_decl));
474 /* This function checks sequence of live registers */
483 for (reg = 0; reg < 18; ++reg)
485 if (!call_used_regs[reg])
487 if (regs_ever_live[reg])
497 if (!frame_pointer_needed)
499 if (regs_ever_live[REG_Y])
507 if (regs_ever_live[REG_Y+1])
520 return (cur_seq == live_seq) ? live_seq : 0;
524 /* Output to FILE the asm instructions to adjust the frame pointer by
525 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
526 (epilogue). Returns the number of instructions generated. */
529 out_adj_frame_ptr (file, adj)
537 if (TARGET_TINY_STACK)
539 if (adj < -63 || adj > 63)
540 warning ("large frame pointer change (%d) with -mtiny-stack", adj);
542 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
543 over "sbiw" (2 cycles, same size). */
545 fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
548 else if (adj < -63 || adj > 63)
550 fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
551 AS2 (sbci, r29, hi8(%d)) CR_TAB),
557 fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
562 fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
570 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
571 handling various cases of interrupt enable flag state BEFORE and AFTER
572 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
573 Returns the number of instructions generated. */
576 out_set_stack_ptr (file, before, after)
581 int do_sph, do_cli, do_save, do_sei, lock_sph, size;
583 /* The logic here is so that -mno-interrupts actually means
584 "it is safe to write SPH in one instruction, then SPL in the
585 next instruction, without disabling interrupts first".
586 The after != -1 case (interrupt/signal) is not affected. */
588 do_sph = !TARGET_TINY_STACK;
589 lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
590 do_cli = (before != 0 && (after == 0 || lock_sph));
591 do_save = (do_cli && before == -1 && after == -1);
592 do_sei = ((do_cli || before != 1) && after == 1);
597 fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
603 fprintf (file, "cli" CR_TAB);
607 /* Do SPH first - maybe this will disable interrupts for one instruction
608 someday (a suggestion has been sent to avr@atmel.com for consideration
609 in future devices - that would make -mno-interrupts always safe). */
612 fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
616 /* Set/restore the I flag now - interrupts will be really enabled only
617 after the next instruction. This is not clearly documented, but
618 believed to be true for all AVR devices. */
621 fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
626 fprintf (file, "sei" CR_TAB);
630 fprintf (file, AS2 (out, __SP_L__, r28) "\n");
636 /* Output function prologue */
639 avr_output_function_prologue (file, size)
644 int interrupt_func_p;
650 last_insn_address = 0;
651 jump_tables_size = 0;
653 fprintf (file, "/* prologue: frame size=%d */\n", size);
655 if (avr_naked_function_p (current_function_decl))
657 fputs ("/* prologue: naked */\n", file);
661 interrupt_func_p = interrupt_function_p (current_function_decl);
662 signal_func_p = signal_function_p (current_function_decl);
663 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
664 live_seq = sequent_regs_live ();
665 minimize = (TARGET_CALL_PROLOGUES
666 && !interrupt_func_p && !signal_func_p && live_seq);
668 if (interrupt_func_p)
670 fprintf (file,"\tsei\n");
673 if (interrupt_func_p || signal_func_p)
676 AS1 (push,__zero_reg__) CR_TAB
677 AS1 (push,__tmp_reg__) CR_TAB
678 AS2 (in,__tmp_reg__,__SREG__) CR_TAB
679 AS1 (push,__tmp_reg__) CR_TAB
680 AS1 (clr,__zero_reg__) "\n");
686 AS2 (ldi,r28,lo8(%s - %d)) CR_TAB
687 AS2 (ldi,r29,hi8(%s - %d)) CR_TAB
688 AS2 (out,__SP_H__,r29) CR_TAB
689 AS2 (out,__SP_L__,r28) "\n"),
690 avr_init_stack, size, avr_init_stack, size);
694 else if (minimize && (frame_pointer_needed || live_seq > 6))
697 AS2 (ldi, r26, lo8(%d)) CR_TAB
698 AS2 (ldi, r27, hi8(%d)) CR_TAB), size, size);
700 fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB
701 AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB)
702 ,current_function_name, current_function_name);
708 fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
709 (18 - live_seq) * 2);
714 fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
715 (18 - live_seq) * 2);
718 fprintf (file, ".L_%s_body:\n", current_function_name);
724 prologue_size += avr_regs_to_save (&set);
725 for (reg = 0; reg < 32; ++reg)
727 if (TEST_HARD_REG_BIT (set, reg))
729 fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
732 if (frame_pointer_needed)
736 AS1 (push,r28) CR_TAB
737 AS1 (push,r29) CR_TAB
738 AS2 (in,r28,__SP_L__) CR_TAB
739 AS2 (in,r29,__SP_H__) "\n");
744 prologue_size += out_adj_frame_ptr (file, size);
746 if (interrupt_func_p)
748 prologue_size += out_set_stack_ptr (file, 1, 1);
750 else if (signal_func_p)
752 prologue_size += out_set_stack_ptr (file, 0, 0);
756 prologue_size += out_set_stack_ptr (file, -1, -1);
764 fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
767 /* Output function epilogue */
770 avr_output_function_epilogue (file, size)
775 int interrupt_func_p;
781 rtx last = get_last_nonnote_insn ();
783 function_size = jump_tables_size;
786 rtx first = get_first_nonnote_insn ();
787 function_size += (INSN_ADDRESSES (INSN_UID (last)) -
788 INSN_ADDRESSES (INSN_UID (first)));
789 function_size += get_attr_length (last);
792 fprintf (file, "/* epilogue: frame size=%d */\n", size);
795 if (avr_naked_function_p (current_function_decl))
797 fputs ("/* epilogue: naked */\n", file);
801 if (last && GET_CODE (last) == BARRIER)
803 fputs ("/* epilogue: noreturn */\n", file);
807 interrupt_func_p = interrupt_function_p (current_function_decl);
808 signal_func_p = signal_function_p (current_function_decl);
809 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
810 live_seq = sequent_regs_live ();
811 minimize = (TARGET_CALL_PROLOGUES
812 && !interrupt_func_p && !signal_func_p && live_seq);
816 /* Return value from main() is already in the correct registers
817 (r25:r24) as the exit() argument. */
820 fputs ("\t" AS1 (jmp,exit) "\n", file);
825 fputs ("\t" AS1 (rjmp,exit) "\n", file);
829 else if (minimize && (frame_pointer_needed || live_seq > 4))
831 fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
833 if (frame_pointer_needed)
835 epilogue_size += out_adj_frame_ptr (file, -size);
839 fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
840 AS2 (in , r29, __SP_H__) CR_TAB));
846 fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
847 (18 - live_seq) * 2);
852 fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
853 (18 - live_seq) * 2);
861 if (frame_pointer_needed)
866 epilogue_size += out_adj_frame_ptr (file, -size);
868 if (interrupt_func_p || signal_func_p)
870 epilogue_size += out_set_stack_ptr (file, -1, 0);
874 epilogue_size += out_set_stack_ptr (file, -1, -1);
883 epilogue_size += avr_regs_to_save (&set);
884 for (reg = 31; reg >= 0; --reg)
886 if (TEST_HARD_REG_BIT (set, reg))
888 fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
892 if (interrupt_func_p || signal_func_p)
895 AS1 (pop,__tmp_reg__) CR_TAB
896 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
897 AS1 (pop,__tmp_reg__) CR_TAB
898 AS1 (pop,__zero_reg__) "\n");
900 fprintf (file, "\treti\n");
903 fprintf (file, "\tret\n");
908 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
909 fprintf (file, "/* function %s size %d (%d) */\n", current_function_name,
910 prologue_size + function_size + epilogue_size, function_size);
911 commands_in_file += prologue_size + function_size + epilogue_size;
912 commands_in_prologues += prologue_size;
913 commands_in_epilogues += epilogue_size;
917 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
918 machine for a memory operand of mode MODE. */
921 legitimate_address_p (mode, x, strict)
922 enum machine_mode mode;
926 enum reg_class r = NO_REGS;
928 if (TARGET_ALL_DEBUG)
930 fprintf (stderr, "mode: (%s) %s %s %s %s:",
932 strict ? "(strict)": "",
933 reload_completed ? "(reload_completed)": "",
934 reload_in_progress ? "(reload_in_progress)": "",
935 reg_renumber ? "(reg_renumber)" : "");
936 if (GET_CODE (x) == PLUS
937 && REG_P (XEXP (x, 0))
938 && GET_CODE (XEXP (x, 1)) == CONST_INT
939 && INTVAL (XEXP (x, 1)) >= 0
940 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
943 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
944 true_regnum (XEXP (x, 0)));
947 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
948 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
950 else if (CONSTANT_ADDRESS_P (x))
952 else if (GET_CODE (x) == PLUS
953 && REG_P (XEXP (x, 0))
954 && GET_CODE (XEXP (x, 1)) == CONST_INT
955 && INTVAL (XEXP (x, 1)) >= 0)
957 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
961 || REGNO (XEXP (x,0)) == REG_Y
962 || REGNO (XEXP (x,0)) == REG_Z)
963 r = BASE_POINTER_REGS;
964 if (XEXP (x,0) == frame_pointer_rtx
965 || XEXP (x,0) == arg_pointer_rtx)
966 r = BASE_POINTER_REGS;
968 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
971 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
972 && REG_P (XEXP (x, 0))
973 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
974 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
978 if (TARGET_ALL_DEBUG)
980 fprintf (stderr, " ret = %c\n", r);
982 return r == NO_REGS ? 0 : (int)r;
985 /* Attempts to replace X with a valid
986 memory address for an operand of mode MODE */
989 legitimize_address (x, oldx, mode)
992 enum machine_mode mode;
995 if (TARGET_ALL_DEBUG)
997 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
1001 if (GET_CODE (oldx) == PLUS
1002 && REG_P (XEXP (oldx,0)))
1004 if (REG_P (XEXP (oldx,1)))
1005 x = force_reg (GET_MODE (oldx), oldx);
1006 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
1008 int offs = INTVAL (XEXP (oldx,1));
1009 if (frame_pointer_rtx != XEXP (oldx,0))
1010 if (offs > MAX_LD_OFFSET (mode))
1012 if (TARGET_ALL_DEBUG)
1013 fprintf (stderr, "force_reg (big offset)\n");
1014 x = force_reg (GET_MODE (oldx), oldx);
1022 /* Return a pointer register name as a string */
1025 ptrreg_to_str (regno)
1030 case REG_X: return "X";
1031 case REG_Y: return "Y";
1032 case REG_Z: return "Z";
1039 /* Return the condition name as a string.
1040 Used in conditional jump constructing */
1053 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1058 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1071 /* Output ADDR to FILE as address */
1074 print_operand_address (file, addr)
1078 switch (GET_CODE (addr))
1081 fprintf (file, ptrreg_to_str (REGNO (addr)));
1085 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1089 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1093 if (CONSTANT_ADDRESS_P (addr)
1094 && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
1095 || GET_CODE (addr) == LABEL_REF))
1097 fprintf (file, "pm(");
1098 output_addr_const (file,addr);
1099 fprintf (file ,")");
1102 output_addr_const (file, addr);
1107 /* Output X as assembler operand to file FILE */
1110 print_operand (file, x, code)
1117 if (code >= 'A' && code <= 'D')
1127 if (x == zero_reg_rtx)
1128 fprintf (file, "__zero_reg__");
1130 fprintf (file, reg_names[true_regnum (x) + abcd]);
1132 else if (GET_CODE (x) == CONST_INT)
1133 fprintf (file, "%d", INTVAL (x) + abcd);
1134 else if (GET_CODE (x) == MEM)
1136 rtx addr = XEXP (x,0);
1138 if (CONSTANT_P (addr) && abcd)
1141 output_address (addr);
1142 fprintf (file, ")+%d", abcd);
1144 else if (code == 'o')
1146 if (GET_CODE (addr) != PLUS)
1147 fatal_insn ("bad address, not (reg+disp):", addr);
1149 print_operand (file, XEXP (addr, 1), 0);
1151 else if (GET_CODE (addr) == PLUS)
1153 print_operand_address (file, XEXP (addr,0));
1154 if (REGNO (XEXP (addr, 0)) == REG_X)
1155 fatal_insn ("internal compiler error. Bad address:"
1158 print_operand (file, XEXP (addr,1), code);
1161 print_operand_address (file, addr);
1163 else if (GET_CODE (x) == CONST_DOUBLE)
1167 if (GET_MODE (x) != SFmode)
1168 fatal_insn ("internal compiler error. Unknown mode:", x);
1169 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1170 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1171 fprintf (file, "0x%lx", val);
1173 else if (code == 'j')
1174 fputs (cond_string (GET_CODE (x)), file);
1175 else if (code == 'k')
1176 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
1178 print_operand_address (file, x);
1181 /* Recognize operand OP of mode MODE used in call instructions */
1184 call_insn_operand (op, mode)
1186 enum machine_mode mode ATTRIBUTE_UNUSED;
1188 if (GET_CODE (op) == MEM)
1190 rtx inside = XEXP (op, 0);
1191 if (register_operand (inside, Pmode))
1193 if (CONSTANT_ADDRESS_P (inside))
1199 /* Update the condition code in the INSN. */
1202 notice_update_cc (body, insn)
1203 rtx body ATTRIBUTE_UNUSED;
1208 switch (get_attr_cc (insn))
1211 /* Insn does not affect CC at all. */
1219 set = single_set (insn);
1223 cc_status.flags |= CC_NO_OVERFLOW;
1224 cc_status.value1 = SET_DEST (set);
1229 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1230 The V flag may or may not be known but that's ok because
1231 alter_cond will change tests to use EQ/NE. */
1232 set = single_set (insn);
1236 cc_status.value1 = SET_DEST (set);
1237 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1242 set = single_set (insn);
1245 cc_status.value1 = SET_SRC (set);
1249 /* Insn doesn't leave CC in a usable state. */
1252 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1253 set = single_set (insn);
1256 rtx src = SET_SRC (set);
1258 if (GET_CODE (src) == ASHIFTRT
1259 && GET_MODE (src) == QImode)
1261 rtx x = XEXP (src, 1);
1263 if (GET_CODE (x) == CONST_INT
1266 cc_status.value1 = SET_DEST (set);
1267 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1275 /* Return maximum number of consecutive registers of
1276 class CLASS needed to hold a value of mode MODE. */
1279 class_max_nregs (class, mode)
1280 enum reg_class class ATTRIBUTE_UNUSED;
1281 enum machine_mode mode;
1283 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1286 /* Choose mode for jump insn:
1287 1 - relative jump in range -63 <= x <= 62 ;
1288 2 - relative jump in range -2046 <= x <= 2045 ;
1289 3 - absolute jump (only for ATmega[16]03). */
1292 avr_jump_mode (x, insn)
1293 rtx x; /* jump operand */
1294 rtx insn; /* jump insn */
1296 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1297 ? XEXP (x, 0) : x));
1298 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1299 int jump_distance = cur_addr - dest_addr;
1301 if (-63 <= jump_distance && jump_distance <= 62)
1303 else if (-2046 <= jump_distance && jump_distance <= 2045)
1311 /* return an AVR condition jump commands.
1312 X is a comparison RTX.
1313 LEN is a number returned by avr_jump_mode function.
1314 if REVERSE nonzero then condition code in X must be reversed. */
1317 ret_cond_branch (x, len, reverse)
1322 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1327 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1328 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1330 len == 2 ? (AS1 (breq,.+4) CR_TAB
1331 AS1 (brmi,.+2) CR_TAB
1333 (AS1 (breq,.+6) CR_TAB
1334 AS1 (brmi,.+4) CR_TAB
1338 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1340 len == 2 ? (AS1 (breq,.+4) CR_TAB
1341 AS1 (brlt,.+2) CR_TAB
1343 (AS1 (breq,.+6) CR_TAB
1344 AS1 (brlt,.+4) CR_TAB
1347 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1349 len == 2 ? (AS1 (breq,.+4) CR_TAB
1350 AS1 (brlo,.+2) CR_TAB
1352 (AS1 (breq,.+6) CR_TAB
1353 AS1 (brlo,.+4) CR_TAB
1356 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1357 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1359 len == 2 ? (AS1 (breq,.+2) CR_TAB
1360 AS1 (brpl,.+2) CR_TAB
1362 (AS1 (breq,.+2) CR_TAB
1363 AS1 (brpl,.+4) CR_TAB
1366 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1368 len == 2 ? (AS1 (breq,.+2) CR_TAB
1369 AS1 (brge,.+2) CR_TAB
1371 (AS1 (breq,.+2) CR_TAB
1372 AS1 (brge,.+4) CR_TAB
1375 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1377 len == 2 ? (AS1 (breq,.+2) CR_TAB
1378 AS1 (brsh,.+2) CR_TAB
1380 (AS1 (breq,.+2) CR_TAB
1381 AS1 (brsh,.+4) CR_TAB
1389 return AS1 (br%k1,%0);
1391 return (AS1 (br%j1,.+2) CR_TAB
1394 return (AS1 (br%j1,.+4) CR_TAB
1403 return AS1 (br%j1,%0);
1405 return (AS1 (br%k1,.+2) CR_TAB
1408 return (AS1 (br%k1,.+4) CR_TAB
1416 /* Predicate function for immediate operand which fits to byte (8bit) */
1419 byte_immediate_operand (op, mode)
1421 enum machine_mode mode ATTRIBUTE_UNUSED;
1423 return (GET_CODE (op) == CONST_INT
1424 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1427 /* Output all insn addresses and their sizes into the assembly language
1428 output file. This is helpful for debugging whether the length attributes
1429 in the md file are correct.
1430 Output insn cost for next insn. */
1433 final_prescan_insn (insn, operand, num_operands)
1434 rtx insn, *operand ATTRIBUTE_UNUSED;
1435 int num_operands ATTRIBUTE_UNUSED;
1437 int uid = INSN_UID (insn);
1439 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1441 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1442 INSN_ADDRESSES (uid),
1443 INSN_ADDRESSES (uid) - last_insn_address,
1444 rtx_cost (PATTERN (insn), INSN));
1446 last_insn_address = INSN_ADDRESSES (uid);
1448 if (TARGET_RTL_DUMP)
1450 fprintf (asm_out_file, "/*****************\n");
1451 print_rtl_single (asm_out_file, insn);
1452 fprintf (asm_out_file, "*****************/\n");
1456 /* Return 0 if undefined, 1 if always true or always false. */
1459 avr_simplify_comparision_p (mode, operator, x)
1460 enum machine_mode mode;
1464 unsigned int max = (mode == QImode ? 0xff :
1465 mode == HImode ? 0xffff :
1466 mode == SImode ? 0xffffffff : 0);
1467 if (max && operator && GET_CODE (x) == CONST_INT)
1469 if (unsigned_condition (operator) != operator)
1472 if (max != (INTVAL (x) & max)
1473 && INTVAL (x) != 0xff)
1480 /* Returns nonzero if REGNO is the number of a hard
1481 register in which function arguments are sometimes passed. */
1484 function_arg_regno_p(r)
1487 return (r >= 8 && r <= 25);
1490 /* Initializing the variable cum for the state at the beginning
1491 of the argument list. */
1494 init_cumulative_args (cum, fntype, libname, fndecl)
1495 CUMULATIVE_ARGS *cum;
1501 cum->regno = FIRST_CUM_REG;
1502 if (!libname && fntype)
1504 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1505 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1506 != void_type_node));
1512 /* Returns the number of registers to allocate for a function argument. */
1515 avr_num_arg_regs (mode, type)
1516 enum machine_mode mode;
1521 if (mode == BLKmode)
1522 size = int_size_in_bytes (type);
1524 size = GET_MODE_SIZE (mode);
1526 /* Align all function arguments to start in even-numbered registers.
1527 Odd-sized arguments leave holes above them. */
1529 return (size + 1) & ~1;
1532 /* Controls whether a function argument is passed
1533 in a register, and which register. */
1536 function_arg (cum, mode, type, named)
1537 CUMULATIVE_ARGS *cum;
1538 enum machine_mode mode;
1540 int named ATTRIBUTE_UNUSED;
1542 int bytes = avr_num_arg_regs (mode, type);
1544 if (cum->nregs && bytes <= cum->nregs)
1545 return gen_rtx (REG, mode, cum->regno - bytes);
1550 /* Update the summarizer variable CUM to advance past an argument
1551 in the argument list. */
1554 function_arg_advance (cum, mode, type, named)
1555 CUMULATIVE_ARGS *cum; /* current arg information */
1556 enum machine_mode mode; /* current arg mode */
1557 tree type; /* type of the argument or 0 if lib support */
1558 int named ATTRIBUTE_UNUSED; /* whether or not the argument was named */
1560 int bytes = avr_num_arg_regs (mode, type);
1562 cum->nregs -= bytes;
1563 cum->regno -= bytes;
1565 if (cum->nregs <= 0)
1568 cum->regno = FIRST_CUM_REG;
1572 /***********************************************************************
1573 Functions for outputting various mov's for a various modes
1574 ************************************************************************/
1576 output_movqi (insn, operands, l)
1582 rtx dest = operands[0];
1583 rtx src = operands[1];
1591 if (register_operand (dest, QImode))
1593 if (register_operand (src, QImode)) /* mov r,r */
1595 if (test_hard_reg_class (STACK_REG, dest))
1596 return AS2 (out,%0,%1);
1597 else if (test_hard_reg_class (STACK_REG, src))
1598 return AS2 (in,%0,%1);
1600 return AS2 (mov,%0,%1);
1602 else if (CONSTANT_P (src))
1604 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1605 return AS2 (ldi,%0,lo8(%1));
1607 if (GET_CODE (src) == CONST_INT)
1609 if (src == const0_rtx) /* mov r,L */
1610 return AS1 (clr,%0);
1611 else if (src == const1_rtx)
1613 if (reg_was_0 (insn, dest))
1614 return AS1 (inc,%0 ; reg_was_0);
1617 return (AS1 (clr,%0) CR_TAB
1620 else if (src == constm1_rtx)
1622 /* Immediate constants -1 to any register */
1623 if (reg_was_0 (insn, dest))
1624 return AS1 (dec,%0 ; reg_was_0);
1627 return (AS1 (clr,%0) CR_TAB
1632 int bit_nr = exact_log2 (INTVAL (src));
1636 if (reg_was_0 (insn, dest))
1640 output_asm_insn ("set ; reg_was_0", operands);
1646 output_asm_insn ((AS1 (clr,%0) CR_TAB
1650 avr_output_bld (operands, bit_nr);
1657 /* Last resort, larger than loading from memory. */
1659 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1660 AS2 (ldi,r31,lo8(%1)) CR_TAB
1661 AS2 (mov,%0,r31) CR_TAB
1662 AS2 (mov,r31,__tmp_reg__));
1664 else if (GET_CODE (src) == MEM)
1665 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1667 else if (GET_CODE (dest) == MEM)
1669 const char *template;
1671 if (src == const0_rtx)
1672 operands[1] = zero_reg_rtx;
1674 template = out_movqi_mr_r (insn, operands, real_l);
1677 output_asm_insn (template, operands);
1686 output_movhi (insn, operands, l)
1692 rtx dest = operands[0];
1693 rtx src = operands[1];
1699 if (register_operand (dest, HImode))
1701 if (register_operand (src, HImode)) /* mov r,r */
1703 if (test_hard_reg_class (STACK_REG, dest))
1705 if (TARGET_TINY_STACK)
1708 return AS2 (out,__SP_L__,%A1);
1710 else if (TARGET_NO_INTERRUPTS)
1713 return (AS2 (out,__SP_H__,%B1) CR_TAB
1714 AS2 (out,__SP_L__,%A1));
1718 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1720 AS2 (out,__SP_H__,%B1) CR_TAB
1721 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1722 AS2 (out,__SP_L__,%A1));
1724 else if (test_hard_reg_class (STACK_REG, src))
1727 return (AS2 (in,%A0,__SP_L__) CR_TAB
1728 AS2 (in,%B0,__SP_H__));
1734 return (AS2 (movw,%0,%1));
1737 if (true_regnum (dest) > true_regnum (src))
1740 return (AS2 (mov,%B0,%B1) CR_TAB
1746 return (AS2 (mov,%A0,%A1) CR_TAB
1750 else if (CONSTANT_P (src))
1752 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1754 if (byte_immediate_operand (src, HImode)
1755 && reg_was_0 (insn, dest))
1758 return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0));
1762 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1763 AS2 (ldi,%B0,hi8(%1)));
1766 if (GET_CODE (src) == CONST_INT)
1768 if (src == const0_rtx) /* mov r,L */
1771 return (AS1 (clr,%A0) CR_TAB
1774 else if (src == const1_rtx)
1776 if (reg_was_0 (insn, dest))
1779 return AS1 (inc,%0 ; reg_was_0);
1783 return (AS1 (clr,%A0) CR_TAB
1784 AS1 (clr,%B0) CR_TAB
1787 else if (src == constm1_rtx)
1789 /* Immediate constants -1 to any register */
1790 if (reg_was_0 (insn, dest))
1793 return (AS1 (dec,%A0 ; reg_was_0) CR_TAB
1798 return (AS1 (clr,%0) CR_TAB
1799 AS1 (dec,%A0) CR_TAB
1804 int bit_nr = exact_log2 (INTVAL (src));
1808 if (reg_was_0 (insn, dest))
1812 output_asm_insn ("set ; reg_was_0", operands);
1818 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1819 AS1 (clr,%B0) CR_TAB
1823 avr_output_bld (operands, bit_nr);
1829 if ((INTVAL (src) & 0xff) == 0)
1832 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1833 AS1 (clr,%A0) CR_TAB
1834 AS2 (ldi,r31,hi8(%1)) CR_TAB
1835 AS2 (mov,%B0,r31) CR_TAB
1836 AS2 (mov,r31,__tmp_reg__));
1838 else if ((INTVAL (src) & 0xff00) == 0)
1841 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1842 AS2 (ldi,r31,lo8(%1)) CR_TAB
1843 AS2 (mov,%A0,r31) CR_TAB
1844 AS1 (clr,%B0) CR_TAB
1845 AS2 (mov,r31,__tmp_reg__));
1849 /* Last resort, equal to loading from memory. */
1851 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1852 AS2 (ldi,r31,lo8(%1)) CR_TAB
1853 AS2 (mov,%A0,r31) CR_TAB
1854 AS2 (ldi,r31,hi8(%1)) CR_TAB
1855 AS2 (mov,%B0,r31) CR_TAB
1856 AS2 (mov,r31,__tmp_reg__));
1858 else if (GET_CODE (src) == MEM)
1859 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1861 else if (GET_CODE (dest) == MEM)
1863 const char *template;
1865 if (src == const0_rtx)
1866 operands[1] = zero_reg_rtx;
1868 template = out_movhi_mr_r (insn, operands, real_l);
1871 output_asm_insn (template, operands);
1876 fatal_insn ("invalid insn:", insn);
1881 out_movqi_r_mr (insn, op, l)
1884 int *l; /* instruction length */
1888 rtx x = XEXP (src, 0);
1894 if (CONSTANT_ADDRESS_P (x))
1896 if (avr_io_address_p (x, 1))
1899 return AS2 (in,%0,%1-0x20);
1902 return AS2 (lds,%0,%1);
1904 /* memory access by reg+disp */
1905 else if (GET_CODE (x) == PLUS
1906 && REG_P (XEXP (x,0))
1907 && GET_CODE (XEXP (x,1)) == CONST_INT)
1909 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
1911 int disp = INTVAL (XEXP (x,1));
1912 if (REGNO (XEXP (x,0)) != REG_Y)
1913 fatal_insn ("incorrect insn:",insn);
1915 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1916 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1917 AS2 (ldd,%0,Y+63) CR_TAB
1918 AS2 (sbiw,r28,%o1-63));
1920 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1921 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1922 AS2 (ld,%0,Y) CR_TAB
1923 AS2 (subi,r28,lo8(%o1)) CR_TAB
1924 AS2 (sbci,r29,hi8(%o1)));
1926 else if (REGNO (XEXP (x,0)) == REG_X)
1928 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1929 it but I have this situation with extremal optimizing options. */
1930 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
1931 || reg_unused_after (insn, XEXP (x,0)))
1932 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1935 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1936 AS2 (ld,%0,X) CR_TAB
1937 AS2 (sbiw,r26,%o1));
1940 return AS2 (ldd,%0,%1);
1943 return AS2 (ld,%0,%1);
1947 out_movhi_r_mr (insn, op, l)
1950 int *l; /* instruction length */
1954 rtx base = XEXP (src, 0);
1955 int reg_dest = true_regnum (dest);
1956 int reg_base = true_regnum (base);
1964 if (reg_dest == reg_base) /* R = (R) */
1967 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1968 AS2 (ld,%B0,%1) CR_TAB
1969 AS2 (mov,%A0,__tmp_reg__));
1971 else if (reg_base == REG_X) /* (R26) */
1973 if (reg_unused_after (insn, base))
1976 return (AS2 (ld,%A0,X+) CR_TAB
1980 return (AS2 (ld,%A0,X+) CR_TAB
1981 AS2 (ld,%B0,X) CR_TAB
1987 return (AS2 (ld,%A0,%1) CR_TAB
1988 AS2 (ldd,%B0,%1+1));
1991 else if (GET_CODE (base) == PLUS) /* (R + i) */
1993 int disp = INTVAL (XEXP (base, 1));
1994 int reg_base = true_regnum (XEXP (base, 0));
1996 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
1998 if (REGNO (XEXP (base, 0)) != REG_Y)
1999 fatal_insn ("incorrect insn:",insn);
2001 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2002 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
2003 AS2 (ldd,%A0,Y+62) CR_TAB
2004 AS2 (ldd,%B0,Y+63) CR_TAB
2005 AS2 (sbiw,r28,%o1-62));
2007 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2008 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2009 AS2 (ld,%A0,Y) CR_TAB
2010 AS2 (ldd,%B0,Y+1) CR_TAB
2011 AS2 (subi,r28,lo8(%o1)) CR_TAB
2012 AS2 (sbci,r29,hi8(%o1)));
2014 if (reg_base == REG_X)
2016 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
2017 it but I have this situation with extremal
2018 optimization options. */
2021 if (reg_base == reg_dest)
2022 return (AS2 (adiw,r26,%o1) CR_TAB
2023 AS2 (ld,__tmp_reg__,X+) CR_TAB
2024 AS2 (ld,%B0,X) CR_TAB
2025 AS2 (mov,%A0,__tmp_reg__));
2027 return (AS2 (adiw,r26,%o1) CR_TAB
2028 AS2 (ld,%A0,X+) CR_TAB
2029 AS2 (ld,%B0,X) CR_TAB
2030 AS2 (sbiw,r26,%o1+1));
2033 if (reg_base == reg_dest)
2036 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
2037 AS2 (ldd,%B0,%B1) CR_TAB
2038 AS2 (mov,%A0,__tmp_reg__));
2042 return (AS2 (ldd,%A0,%A1) CR_TAB
2045 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2047 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
2048 fatal_insn ("incorrect insn:", insn);
2051 return (AS2 (ld,%B0,%1) CR_TAB
2054 else if (GET_CODE (base) == POST_INC) /* (R++) */
2056 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
2057 fatal_insn ("incorrect insn:", insn);
2060 return (AS2 (ld,%A0,%1) CR_TAB
2063 else if (CONSTANT_ADDRESS_P (base))
2065 if (avr_io_address_p (base, 2))
2068 return (AS2 (in,%A0,%A1-0x20) CR_TAB
2069 AS2 (in,%B0,%B1-0x20));
2072 return (AS2 (lds,%A0,%A1) CR_TAB
2076 fatal_insn ("unknown move insn:",insn);
2081 out_movsi_r_mr (insn, op, l)
2084 int *l; /* instruction length */
2088 rtx base = XEXP (src, 0);
2089 int reg_dest = true_regnum (dest);
2090 int reg_base = true_regnum (base);
2098 if (reg_base == REG_X) /* (R26) */
2100 if (reg_dest == REG_X)
2101 /* "ld r26,-X" is undefined */
2102 return *l=7, (AS2 (adiw,r26,3) CR_TAB
2103 AS2 (ld,r29,X) CR_TAB
2104 AS2 (ld,r28,-X) CR_TAB
2105 AS2 (ld,__tmp_reg__,-X) CR_TAB
2106 AS2 (sbiw,r26,1) CR_TAB
2107 AS2 (ld,r26,X) CR_TAB
2108 AS2 (mov,r27,__tmp_reg__));
2109 else if (reg_dest == REG_X - 2)
2110 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2111 AS2 (ld,%B0,X+) CR_TAB
2112 AS2 (ld,__tmp_reg__,X+) CR_TAB
2113 AS2 (ld,%D0,X) CR_TAB
2114 AS2 (mov,%C0,__tmp_reg__));
2115 else if (reg_unused_after (insn, base))
2116 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
2117 AS2 (ld,%B0,X+) CR_TAB
2118 AS2 (ld,%C0,X+) CR_TAB
2121 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2122 AS2 (ld,%B0,X+) CR_TAB
2123 AS2 (ld,%C0,X+) CR_TAB
2124 AS2 (ld,%D0,X) CR_TAB
2129 if (reg_dest == reg_base)
2130 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2131 AS2 (ldd,%C0,%1+2) CR_TAB
2132 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2133 AS2 (ld,%A0,%1) CR_TAB
2134 AS2 (mov,%B0,__tmp_reg__));
2135 else if (reg_base == reg_dest + 2)
2136 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2137 AS2 (ldd,%B0,%1+1) CR_TAB
2138 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2139 AS2 (ldd,%D0,%1+3) CR_TAB
2140 AS2 (mov,%C0,__tmp_reg__));
2142 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2143 AS2 (ldd,%B0,%1+1) CR_TAB
2144 AS2 (ldd,%C0,%1+2) CR_TAB
2145 AS2 (ldd,%D0,%1+3));
2148 else if (GET_CODE (base) == PLUS) /* (R + i) */
2150 int disp = INTVAL (XEXP (base, 1));
2152 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2154 if (REGNO (XEXP (base, 0)) != REG_Y)
2155 fatal_insn ("incorrect insn:",insn);
2157 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2158 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2159 AS2 (ldd,%A0,Y+60) CR_TAB
2160 AS2 (ldd,%B0,Y+61) CR_TAB
2161 AS2 (ldd,%C0,Y+62) CR_TAB
2162 AS2 (ldd,%D0,Y+63) CR_TAB
2163 AS2 (sbiw,r28,%o1-60));
2165 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2166 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2167 AS2 (ld,%A0,Y) CR_TAB
2168 AS2 (ldd,%B0,Y+1) CR_TAB
2169 AS2 (ldd,%C0,Y+2) CR_TAB
2170 AS2 (ldd,%D0,Y+3) CR_TAB
2171 AS2 (subi,r28,lo8(%o1)) CR_TAB
2172 AS2 (sbci,r29,hi8(%o1)));
2175 reg_base = true_regnum (XEXP (base, 0));
2176 if (reg_base == REG_X)
2179 if (reg_dest == REG_X)
2182 /* "ld r26,-X" is undefined */
2183 return (AS2 (adiw,r26,%o1+3) CR_TAB
2184 AS2 (ld,r29,X) CR_TAB
2185 AS2 (ld,r28,-X) CR_TAB
2186 AS2 (ld,__tmp_reg__,-X) CR_TAB
2187 AS2 (sbiw,r26,1) CR_TAB
2188 AS2 (ld,r26,X) CR_TAB
2189 AS2 (mov,r27,__tmp_reg__));
2192 if (reg_dest == REG_X - 2)
2193 return (AS2 (adiw,r26,%o1) CR_TAB
2194 AS2 (ld,r24,X+) CR_TAB
2195 AS2 (ld,r25,X+) CR_TAB
2196 AS2 (ld,__tmp_reg__,X+) CR_TAB
2197 AS2 (ld,r27,X) CR_TAB
2198 AS2 (mov,r26,__tmp_reg__));
2200 return (AS2 (adiw,r26,%o1) CR_TAB
2201 AS2 (ld,%A0,X+) CR_TAB
2202 AS2 (ld,%B0,X+) CR_TAB
2203 AS2 (ld,%C0,X+) CR_TAB
2204 AS2 (ld,%D0,X) CR_TAB
2205 AS2 (sbiw,r26,%o1+3));
2207 if (reg_dest == reg_base)
2208 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2209 AS2 (ldd,%C0,%C1) CR_TAB
2210 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2211 AS2 (ldd,%A0,%A1) CR_TAB
2212 AS2 (mov,%B0,__tmp_reg__));
2213 else if (reg_dest == reg_base - 2)
2214 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2215 AS2 (ldd,%B0,%B1) CR_TAB
2216 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2217 AS2 (ldd,%D0,%D1) CR_TAB
2218 AS2 (mov,%C0,__tmp_reg__));
2219 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2220 AS2 (ldd,%B0,%B1) CR_TAB
2221 AS2 (ldd,%C0,%C1) CR_TAB
2224 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2225 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2226 AS2 (ld,%C0,%1) CR_TAB
2227 AS2 (ld,%B0,%1) CR_TAB
2229 else if (GET_CODE (base) == POST_INC) /* (R++) */
2230 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2231 AS2 (ld,%B0,%1) CR_TAB
2232 AS2 (ld,%C0,%1) CR_TAB
2234 else if (CONSTANT_ADDRESS_P (base))
2235 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2236 AS2 (lds,%B0,%B1) CR_TAB
2237 AS2 (lds,%C0,%C1) CR_TAB
2240 fatal_insn ("unknown move insn:",insn);
2245 out_movsi_mr_r (insn, op, l)
2252 rtx base = XEXP (dest, 0);
2253 int reg_base = true_regnum (base);
2254 int reg_src = true_regnum (src);
2260 if (CONSTANT_ADDRESS_P (base))
2261 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2262 AS2 (sts,%B0,%B1) CR_TAB
2263 AS2 (sts,%C0,%C1) CR_TAB
2265 if (reg_base > 0) /* (r) */
2267 if (reg_base == REG_X) /* (R26) */
2269 if (reg_src == REG_X)
2271 /* "st X+,r26" is undefined */
2272 if (reg_unused_after (insn, base))
2273 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2274 AS2 (st,X,r26) CR_TAB
2275 AS2 (adiw,r26,1) CR_TAB
2276 AS2 (st,X+,__tmp_reg__) CR_TAB
2277 AS2 (st,X+,r28) CR_TAB
2280 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2281 AS2 (st,X,r26) CR_TAB
2282 AS2 (adiw,r26,1) CR_TAB
2283 AS2 (st,X+,__tmp_reg__) CR_TAB
2284 AS2 (st,X+,r28) CR_TAB
2285 AS2 (st,X,r29) CR_TAB
2288 else if (reg_base == reg_src + 2)
2290 if (reg_unused_after (insn, base))
2291 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2292 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2293 AS2 (st,%0+,%A1) CR_TAB
2294 AS2 (st,%0+,%B1) CR_TAB
2295 AS2 (st,%0+,__zero_reg__) CR_TAB
2296 AS2 (st,%0,__tmp_reg__) CR_TAB
2297 AS1 (clr,__zero_reg__));
2299 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2300 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2301 AS2 (st,%0+,%A1) CR_TAB
2302 AS2 (st,%0+,%B1) CR_TAB
2303 AS2 (st,%0+,__zero_reg__) CR_TAB
2304 AS2 (st,%0,__tmp_reg__) CR_TAB
2305 AS1 (clr,__zero_reg__) CR_TAB
2308 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2309 AS2 (st,%0+,%B1) CR_TAB
2310 AS2 (st,%0+,%C1) CR_TAB
2311 AS2 (st,%0,%D1) CR_TAB
2315 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2316 AS2 (std,%0+1,%B1) CR_TAB
2317 AS2 (std,%0+2,%C1) CR_TAB
2318 AS2 (std,%0+3,%D1));
2320 else if (GET_CODE (base) == PLUS) /* (R + i) */
2322 int disp = INTVAL (XEXP (base, 1));
2323 reg_base = REGNO (XEXP (base, 0));
2324 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2326 if (reg_base != REG_Y)
2327 fatal_insn ("incorrect insn:",insn);
2329 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2330 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2331 AS2 (std,Y+60,%A1) CR_TAB
2332 AS2 (std,Y+61,%B1) CR_TAB
2333 AS2 (std,Y+62,%C1) CR_TAB
2334 AS2 (std,Y+63,%D1) CR_TAB
2335 AS2 (sbiw,r28,%o0-60));
2337 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2338 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2339 AS2 (st,Y,%A1) CR_TAB
2340 AS2 (std,Y+1,%B1) CR_TAB
2341 AS2 (std,Y+2,%C1) CR_TAB
2342 AS2 (std,Y+3,%D1) CR_TAB
2343 AS2 (subi,r28,lo8(%o0)) CR_TAB
2344 AS2 (sbci,r29,hi8(%o0)));
2346 if (reg_base == REG_X)
2349 if (reg_src == REG_X)
2352 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2353 AS2 (mov,__zero_reg__,r27) CR_TAB
2354 AS2 (adiw,r26,%o0) CR_TAB
2355 AS2 (st,X+,__tmp_reg__) CR_TAB
2356 AS2 (st,X+,__zero_reg__) CR_TAB
2357 AS2 (st,X+,r28) CR_TAB
2358 AS2 (st,X,r29) CR_TAB
2359 AS1 (clr,__zero_reg__) CR_TAB
2360 AS2 (sbiw,r26,%o0+3));
2362 else if (reg_src == REG_X - 2)
2365 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2366 AS2 (mov,__zero_reg__,r27) CR_TAB
2367 AS2 (adiw,r26,%o0) CR_TAB
2368 AS2 (st,X+,r24) CR_TAB
2369 AS2 (st,X+,r25) CR_TAB
2370 AS2 (st,X+,__tmp_reg__) CR_TAB
2371 AS2 (st,X,__zero_reg__) CR_TAB
2372 AS1 (clr,__zero_reg__) CR_TAB
2373 AS2 (sbiw,r26,%o0+3));
2376 return (AS2 (adiw,r26,%o0) CR_TAB
2377 AS2 (st,X+,%A1) CR_TAB
2378 AS2 (st,X+,%B1) CR_TAB
2379 AS2 (st,X+,%C1) CR_TAB
2380 AS2 (st,X,%D1) CR_TAB
2381 AS2 (sbiw,r26,%o0+3));
2383 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2384 AS2 (std,%B0,%B1) CR_TAB
2385 AS2 (std,%C0,%C1) CR_TAB
2388 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2389 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2390 AS2 (st,%0,%C1) CR_TAB
2391 AS2 (st,%0,%B1) CR_TAB
2393 else if (GET_CODE (base) == POST_INC) /* (R++) */
2394 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2395 AS2 (st,%0,%B1) CR_TAB
2396 AS2 (st,%0,%C1) CR_TAB
2398 fatal_insn ("unknown move insn:",insn);
2403 output_movsisf(insn, operands, l)
2409 rtx dest = operands[0];
2410 rtx src = operands[1];
2416 if (register_operand (dest, VOIDmode))
2418 if (register_operand (src, VOIDmode)) /* mov r,r */
2420 if (true_regnum (dest) > true_regnum (src))
2425 return (AS2 (movw,%C0,%C1) CR_TAB
2426 AS2 (movw,%A0,%A1));
2429 return (AS2 (mov,%D0,%D1) CR_TAB
2430 AS2 (mov,%C0,%C1) CR_TAB
2431 AS2 (mov,%B0,%B1) CR_TAB
2439 return (AS2 (movw,%A0,%A1) CR_TAB
2440 AS2 (movw,%C0,%C1));
2443 return (AS2 (mov,%A0,%A1) CR_TAB
2444 AS2 (mov,%B0,%B1) CR_TAB
2445 AS2 (mov,%C0,%C1) CR_TAB
2449 else if (CONSTANT_P (src))
2451 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2453 if (byte_immediate_operand (src, SImode)
2454 && reg_was_0 (insn, dest))
2457 return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0));
2461 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2462 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2463 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2464 AS2 (ldi,%D0,hhi8(%1)));
2467 if (GET_CODE (src) == CONST_INT)
2469 const char *const clr_op0 =
2470 AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
2471 AS1 (clr,%B0) CR_TAB
2473 : (AS1 (clr,%A0) CR_TAB
2474 AS1 (clr,%B0) CR_TAB
2475 AS1 (clr,%C0) CR_TAB
2478 if (src == const0_rtx) /* mov r,L */
2480 *l = AVR_ENHANCED ? 3 : 4;
2483 else if (src == const1_rtx)
2485 if (reg_was_0 (insn, dest))
2488 return AS1 (inc,%A0 ; reg_was_0);
2491 output_asm_insn (clr_op0, operands);
2492 *l = AVR_ENHANCED ? 4 : 5;
2493 return AS1 (inc,%A0);
2495 else if (src == constm1_rtx)
2497 /* Immediate constants -1 to any register */
2498 if (reg_was_0 (insn, dest))
2503 return (AS1 (dec,%A0) CR_TAB
2504 AS1 (dec,%B0) CR_TAB
2505 AS2 (movw,%C0,%A0));
2508 return (AS1 (dec,%D0 ; reg_was_0) CR_TAB
2509 AS1 (dec,%C0) CR_TAB
2510 AS1 (dec,%B0) CR_TAB
2516 return (AS1 (clr,%A0) CR_TAB
2517 AS1 (dec,%A0) CR_TAB
2518 AS2 (mov,%B0,%A0) CR_TAB
2519 AS2 (movw,%C0,%A0));
2522 return (AS1 (clr,%A0) CR_TAB
2523 AS1 (dec,%A0) CR_TAB
2524 AS2 (mov,%B0,%A0) CR_TAB
2525 AS2 (mov,%C0,%A0) CR_TAB
2530 int bit_nr = exact_log2 (INTVAL (src));
2534 if (reg_was_0 (insn, dest))
2538 output_asm_insn ("set ; reg_was_0", operands);
2542 *l = AVR_ENHANCED ? 5 : 6;
2545 output_asm_insn (clr_op0, operands);
2546 output_asm_insn ("set", operands);
2550 avr_output_bld (operands, bit_nr);
2557 /* Last resort, better than loading from memory. */
2559 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2560 AS2 (ldi,r31,lo8(%1)) CR_TAB
2561 AS2 (mov,%A0,r31) CR_TAB
2562 AS2 (ldi,r31,hi8(%1)) CR_TAB
2563 AS2 (mov,%B0,r31) CR_TAB
2564 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2565 AS2 (mov,%C0,r31) CR_TAB
2566 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2567 AS2 (mov,%D0,r31) CR_TAB
2568 AS2 (mov,r31,__tmp_reg__));
2570 else if (GET_CODE (src) == MEM)
2571 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2573 else if (GET_CODE (dest) == MEM)
2575 const char *template;
2577 if (src == const0_rtx)
2578 operands[1] = zero_reg_rtx;
2580 template = out_movsi_mr_r (insn, operands, real_l);
2583 output_asm_insn (template, operands);
2588 fatal_insn ("invalid insn:", insn);
2593 out_movqi_mr_r (insn, op, l)
2596 int *l; /* instruction length */
2600 rtx x = XEXP (dest, 0);
2606 if (CONSTANT_ADDRESS_P (x))
2608 if (avr_io_address_p (x, 1))
2611 return AS2 (out,%0-0x20,%1);
2614 return AS2 (sts,%0,%1);
2616 /* memory access by reg+disp */
2617 else if (GET_CODE (x) == PLUS
2618 && REG_P (XEXP (x,0))
2619 && GET_CODE (XEXP (x,1)) == CONST_INT)
2621 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
2623 int disp = INTVAL (XEXP (x,1));
2624 if (REGNO (XEXP (x,0)) != REG_Y)
2625 fatal_insn ("incorrect insn:",insn);
2627 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2628 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2629 AS2 (std,Y+63,%1) CR_TAB
2630 AS2 (sbiw,r28,%o0-63));
2632 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2633 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2634 AS2 (st,Y,%1) CR_TAB
2635 AS2 (subi,r28,lo8(%o0)) CR_TAB
2636 AS2 (sbci,r29,hi8(%o0)));
2638 else if (REGNO (XEXP (x,0)) == REG_X)
2640 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
2642 if (reg_unused_after (insn, XEXP (x,0)))
2643 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2644 AS2 (adiw,r26,%o0) CR_TAB
2645 AS2 (st,X,__tmp_reg__));
2647 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2648 AS2 (adiw,r26,%o0) CR_TAB
2649 AS2 (st,X,__tmp_reg__) CR_TAB
2650 AS2 (sbiw,r26,%o0));
2654 if (reg_unused_after (insn, XEXP (x,0)))
2655 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2658 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2659 AS2 (st,X,%1) CR_TAB
2660 AS2 (sbiw,r26,%o0));
2664 return AS2 (std,%0,%1);
2667 return AS2 (st,%0,%1);
2671 out_movhi_mr_r (insn, op, l)
2678 rtx base = XEXP (dest, 0);
2679 int reg_base = true_regnum (base);
2680 int reg_src = true_regnum (src);
2684 if (CONSTANT_ADDRESS_P (base))
2686 if (avr_io_address_p (base, 2))
2689 return (AS2 (out,%B0-0x20,%B1) CR_TAB
2690 AS2 (out,%A0-0x20,%A1));
2692 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2697 if (reg_base == REG_X)
2699 if (reg_src == REG_X)
2701 /* "st X+,r26" is undefined */
2702 if (reg_unused_after (insn, src))
2703 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2704 AS2 (st,X,r26) CR_TAB
2705 AS2 (adiw,r26,1) CR_TAB
2706 AS2 (st,X,__tmp_reg__));
2708 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2709 AS2 (st,X,r26) CR_TAB
2710 AS2 (adiw,r26,1) CR_TAB
2711 AS2 (st,X,__tmp_reg__) CR_TAB
2716 if (reg_unused_after (insn, base))
2717 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2720 return *l=3, (AS2 (st ,X+,%A1) CR_TAB
2721 AS2 (st ,X,%B1) CR_TAB
2726 return *l=2, (AS2 (st ,%0,%A1) CR_TAB
2727 AS2 (std,%0+1,%B1));
2729 else if (GET_CODE (base) == PLUS)
2731 int disp = INTVAL (XEXP (base, 1));
2732 reg_base = REGNO (XEXP (base, 0));
2733 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2735 if (reg_base != REG_Y)
2736 fatal_insn ("incorrect insn:",insn);
2738 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2739 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
2740 AS2 (std,Y+62,%A1) CR_TAB
2741 AS2 (std,Y+63,%B1) CR_TAB
2742 AS2 (sbiw,r28,%o0-62));
2744 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2745 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2746 AS2 (st,Y,%A1) CR_TAB
2747 AS2 (std,Y+1,%B1) CR_TAB
2748 AS2 (subi,r28,lo8(%o0)) CR_TAB
2749 AS2 (sbci,r29,hi8(%o0)));
2751 if (reg_base == REG_X)
2754 if (reg_src == REG_X)
2757 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2758 AS2 (mov,__zero_reg__,r27) CR_TAB
2759 AS2 (adiw,r26,%o0) CR_TAB
2760 AS2 (st,X+,__tmp_reg__) CR_TAB
2761 AS2 (st,X,__zero_reg__) CR_TAB
2762 AS1 (clr,__zero_reg__) CR_TAB
2763 AS2 (sbiw,r26,%o0+1));
2766 return (AS2 (adiw,r26,%o0) CR_TAB
2767 AS2 (st,X+,%A1) CR_TAB
2768 AS2 (st,X,%B1) CR_TAB
2769 AS2 (sbiw,r26,%o0+1));
2771 return *l=2, (AS2 (std,%A0,%A1) CR_TAB
2774 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2775 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2777 else if (GET_CODE (base) == POST_INC) /* (R++) */
2778 return *l=2, (AS2 (st,%0,%A1) CR_TAB
2780 fatal_insn ("unknown move insn:",insn);
2784 /* Return 1 if frame pointer for current function required */
2787 frame_pointer_required_p ()
2789 return (current_function_calls_alloca
2790 || current_function_args_info.nregs == 0
2791 || get_frame_size () > 0);
2794 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2797 compare_condition (insn)
2800 rtx next = next_real_insn (insn);
2801 RTX_CODE cond = UNKNOWN;
2802 if (next && GET_CODE (next) == JUMP_INSN)
2804 rtx pat = PATTERN (next);
2805 rtx src = SET_SRC (pat);
2806 rtx t = XEXP (src, 0);
2807 cond = GET_CODE (t);
2812 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2815 compare_sign_p (insn)
2818 RTX_CODE cond = compare_condition (insn);
2819 return (cond == GE || cond == LT);
2822 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2823 that needs to be swapped (GT, GTU, LE, LEU). */
2826 compare_diff_p (insn)
2829 RTX_CODE cond = compare_condition (insn);
2830 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2833 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2839 RTX_CODE cond = compare_condition (insn);
2840 return (cond == EQ || cond == NE);
2844 /* Output test instruction for HImode */
2851 if (compare_sign_p (insn))
2854 return AS1 (tst,%B0);
2856 if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2857 && compare_eq_p (insn))
2859 /* faster than sbiw if we can clobber the operand */
2861 return AS2 (or,%A0,%B0);
2863 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2866 return AS2 (sbiw,%0,0);
2869 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2870 AS2 (cpc,%B0,__zero_reg__));
2874 /* Output test instruction for SImode */
2881 if (compare_sign_p (insn))
2884 return AS1 (tst,%D0);
2886 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2889 return (AS2 (sbiw,%A0,0) CR_TAB
2890 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2891 AS2 (cpc,%D0,__zero_reg__));
2894 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2895 AS2 (cpc,%B0,__zero_reg__) CR_TAB
2896 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2897 AS2 (cpc,%D0,__zero_reg__));
2901 /* Generate asm equivalent for various shifts.
2902 Shift count is a CONST_INT, MEM or REG.
2903 This only handles cases that are not already
2904 carefully hand-optimized in ?sh??i3_out. */
2907 out_shift_with_cnt (template, insn, operands, len, t_len)
2908 const char *template;
2912 int t_len; /* Length of template. */
2916 int second_label = 1;
2917 int saved_in_tmp = 0;
2918 int use_zero_reg = 0;
2920 op[0] = operands[0];
2921 op[1] = operands[1];
2922 op[2] = operands[2];
2923 op[3] = operands[3];
2929 if (GET_CODE (operands[2]) == CONST_INT)
2931 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2932 int count = INTVAL (operands[2]);
2933 int max_len = 10; /* If larger than this, always use a loop. */
2935 if (count < 8 && !scratch)
2939 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2941 if (t_len * count <= max_len)
2943 /* Output shifts inline with no loop - faster. */
2945 *len = t_len * count;
2949 output_asm_insn (template, op);
2958 strcat (str, AS2 (ldi,%3,%2));
2960 else if (use_zero_reg)
2962 /* Hack to save one word: use __zero_reg__ as loop counter.
2963 Set one bit, then shift in a loop until it is 0 again. */
2965 op[3] = zero_reg_rtx;
2969 strcat (str, ("set" CR_TAB
2970 AS2 (bld,%3,%2-1)));
2974 /* No scratch register available, use one from LD_REGS (saved in
2975 __tmp_reg__) that doesn't overlap with registers to shift. */
2977 op[3] = gen_rtx (REG, QImode,
2978 ((true_regnum (operands[0]) - 1) & 15) + 16);
2979 op[4] = tmp_reg_rtx;
2983 *len = 3; /* Includes "mov %3,%4" after the loop. */
2985 strcat (str, (AS2 (mov,%4,%3) CR_TAB
2991 else if (GET_CODE (operands[2]) == MEM)
2995 op[3] = op_mov[0] = tmp_reg_rtx;
2999 out_movqi_r_mr (insn, op_mov, len);
3001 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
3003 else if (register_operand (operands[2], QImode))
3005 if (reg_unused_after (insn, operands[2]))
3009 op[3] = tmp_reg_rtx;
3011 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
3015 fatal_insn ("bad shift insn:", insn);
3022 strcat (str, AS1 (rjmp,2f));
3026 *len += t_len + 2; /* template + dec + brXX */
3029 strcat (str, "\n1:\t");
3030 strcat (str, template);
3031 strcat (str, second_label ? "\n2:\t" : "\n\t");
3032 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
3033 strcat (str, CR_TAB);
3034 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
3036 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
3037 output_asm_insn (str, op);
3042 /* 8bit shift left ((char)x << i) */
3045 ashlqi3_out (insn, operands, len)
3048 int *len; /* insn length (may be NULL) */
3050 if (GET_CODE (operands[2]) == CONST_INT)
3057 switch (INTVAL (operands[2]))
3061 return AS1 (clr,%0);
3065 return AS1 (lsl,%0);
3069 return (AS1 (lsl,%0) CR_TAB
3074 return (AS1 (lsl,%0) CR_TAB
3079 if (test_hard_reg_class (LD_REGS, operands[0]))
3082 return (AS1 (swap,%0) CR_TAB
3083 AS2 (andi,%0,0xf0));
3086 return (AS1 (lsl,%0) CR_TAB
3092 if (test_hard_reg_class (LD_REGS, operands[0]))
3095 return (AS1 (swap,%0) CR_TAB
3097 AS2 (andi,%0,0xe0));
3100 return (AS1 (lsl,%0) CR_TAB
3107 if (test_hard_reg_class (LD_REGS, operands[0]))
3110 return (AS1 (swap,%0) CR_TAB
3113 AS2 (andi,%0,0xc0));
3116 return (AS1 (lsl,%0) CR_TAB
3125 return (AS1 (ror,%0) CR_TAB
3130 else if (CONSTANT_P (operands[2]))
3131 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3133 out_shift_with_cnt (AS1 (lsl,%0),
3134 insn, operands, len, 1);
3139 /* 16bit shift left ((short)x << i) */
3142 ashlhi3_out (insn, operands, len)
3147 if (GET_CODE (operands[2]) == CONST_INT)
3149 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3150 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3157 switch (INTVAL (operands[2]))
3160 if (optimize_size && scratch)
3165 return (AS1 (swap,%A0) CR_TAB
3166 AS1 (swap,%B0) CR_TAB
3167 AS2 (andi,%B0,0xf0) CR_TAB
3168 AS2 (eor,%B0,%A0) CR_TAB
3169 AS2 (andi,%A0,0xf0) CR_TAB
3175 return (AS1 (swap,%A0) CR_TAB
3176 AS1 (swap,%B0) CR_TAB
3177 AS2 (ldi,%3,0xf0) CR_TAB
3178 AS2 (and,%B0,%3) CR_TAB
3179 AS2 (eor,%B0,%A0) CR_TAB
3180 AS2 (and,%A0,%3) CR_TAB
3183 break; /* optimize_size ? 6 : 8 */
3187 break; /* scratch ? 5 : 6 */
3191 return (AS1 (lsl,%A0) CR_TAB
3192 AS1 (rol,%B0) CR_TAB
3193 AS1 (swap,%A0) CR_TAB
3194 AS1 (swap,%B0) CR_TAB
3195 AS2 (andi,%B0,0xf0) CR_TAB
3196 AS2 (eor,%B0,%A0) CR_TAB
3197 AS2 (andi,%A0,0xf0) CR_TAB
3203 return (AS1 (lsl,%A0) CR_TAB
3204 AS1 (rol,%B0) CR_TAB
3205 AS1 (swap,%A0) CR_TAB
3206 AS1 (swap,%B0) CR_TAB
3207 AS2 (ldi,%3,0xf0) CR_TAB
3208 AS2 (and,%B0,%3) CR_TAB
3209 AS2 (eor,%B0,%A0) CR_TAB
3210 AS2 (and,%A0,%3) CR_TAB
3217 break; /* scratch ? 5 : 6 */
3219 return (AS1 (clr,__tmp_reg__) CR_TAB
3220 AS1 (lsr,%B0) CR_TAB
3221 AS1 (ror,%A0) CR_TAB
3222 AS1 (ror,__tmp_reg__) CR_TAB
3223 AS1 (lsr,%B0) CR_TAB
3224 AS1 (ror,%A0) CR_TAB
3225 AS1 (ror,__tmp_reg__) CR_TAB
3226 AS2 (mov,%B0,%A0) CR_TAB
3227 AS2 (mov,%A0,__tmp_reg__));
3231 return (AS1 (lsr,%B0) CR_TAB
3232 AS2 (mov,%B0,%A0) CR_TAB
3233 AS1 (clr,%A0) CR_TAB
3234 AS1 (ror,%B0) CR_TAB
3238 if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
3239 return *len = 1, AS1 (clr,%A0);
3241 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3246 return (AS2 (mov,%B0,%A0) CR_TAB
3247 AS1 (clr,%A0) CR_TAB
3252 return (AS2 (mov,%B0,%A0) CR_TAB
3253 AS1 (clr,%A0) CR_TAB
3254 AS1 (lsl,%B0) CR_TAB
3259 return (AS2 (mov,%B0,%A0) CR_TAB
3260 AS1 (clr,%A0) CR_TAB
3261 AS1 (lsl,%B0) CR_TAB
3262 AS1 (lsl,%B0) CR_TAB
3269 return (AS2 (mov,%B0,%A0) CR_TAB
3270 AS1 (clr,%A0) CR_TAB
3271 AS1 (swap,%B0) CR_TAB
3272 AS2 (andi,%B0,0xf0));
3277 return (AS2 (mov,%B0,%A0) CR_TAB
3278 AS1 (clr,%A0) CR_TAB
3279 AS1 (swap,%B0) CR_TAB
3280 AS2 (ldi,%3,0xf0) CR_TAB
3284 return (AS2 (mov,%B0,%A0) CR_TAB
3285 AS1 (clr,%A0) CR_TAB
3286 AS1 (lsl,%B0) CR_TAB
3287 AS1 (lsl,%B0) CR_TAB
3288 AS1 (lsl,%B0) CR_TAB
3295 return (AS2 (mov,%B0,%A0) CR_TAB
3296 AS1 (clr,%A0) CR_TAB
3297 AS1 (swap,%B0) CR_TAB
3298 AS1 (lsl,%B0) CR_TAB
3299 AS2 (andi,%B0,0xe0));
3301 if (AVR_ENHANCED && scratch)
3304 return (AS2 (ldi,%3,0x20) CR_TAB
3305 AS2 (mul,%A0,%3) CR_TAB
3306 AS2 (mov,%B0,r0) CR_TAB
3307 AS1 (clr,%A0) CR_TAB
3308 AS1 (clr,__zero_reg__));
3310 if (optimize_size && scratch)
3315 return (AS2 (mov,%B0,%A0) CR_TAB
3316 AS1 (clr,%A0) CR_TAB
3317 AS1 (swap,%B0) CR_TAB
3318 AS1 (lsl,%B0) CR_TAB
3319 AS2 (ldi,%3,0xe0) CR_TAB
3325 return ("set" CR_TAB
3326 AS2 (bld,r1,5) CR_TAB
3327 AS2 (mul,%A0,r1) CR_TAB
3328 AS2 (mov,%B0,r0) CR_TAB
3329 AS1 (clr,%A0) CR_TAB
3330 AS1 (clr,__zero_reg__));
3333 return (AS2 (mov,%B0,%A0) CR_TAB
3334 AS1 (clr,%A0) CR_TAB
3335 AS1 (lsl,%B0) CR_TAB
3336 AS1 (lsl,%B0) CR_TAB
3337 AS1 (lsl,%B0) CR_TAB
3338 AS1 (lsl,%B0) CR_TAB
3342 if (AVR_ENHANCED && ldi_ok)
3345 return (AS2 (ldi,%B0,0x40) CR_TAB
3346 AS2 (mul,%A0,%B0) CR_TAB
3347 AS2 (mov,%B0,r0) CR_TAB
3348 AS1 (clr,%A0) CR_TAB
3349 AS1 (clr,__zero_reg__));
3351 if (AVR_ENHANCED && scratch)
3354 return (AS2 (ldi,%3,0x40) CR_TAB
3355 AS2 (mul,%A0,%3) CR_TAB
3356 AS2 (mov,%B0,r0) CR_TAB
3357 AS1 (clr,%A0) CR_TAB
3358 AS1 (clr,__zero_reg__));
3360 if (optimize_size && ldi_ok)
3363 return (AS2 (mov,%B0,%A0) CR_TAB
3364 AS2 (ldi,%A0,6) "\n1:\t"
3365 AS1 (lsl,%B0) CR_TAB
3366 AS1 (dec,%A0) CR_TAB
3369 if (optimize_size && scratch)
3372 return (AS1 (clr,%B0) CR_TAB
3373 AS1 (lsr,%A0) CR_TAB
3374 AS1 (ror,%B0) CR_TAB
3375 AS1 (lsr,%A0) CR_TAB
3376 AS1 (ror,%B0) CR_TAB
3381 return (AS1 (clr,%B0) CR_TAB
3382 AS1 (lsr,%A0) CR_TAB
3383 AS1 (ror,%B0) CR_TAB
3388 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3390 insn, operands, len, 2);
3395 /* 32bit shift left ((long)x << i) */
3398 ashlsi3_out (insn, operands, len)
3403 if (GET_CODE (operands[2]) == CONST_INT)
3411 switch (INTVAL (operands[2]))
3415 int reg0 = true_regnum (operands[0]);
3416 int reg1 = true_regnum (operands[1]);
3419 return (AS2 (mov,%D0,%C1) CR_TAB
3420 AS2 (mov,%C0,%B1) CR_TAB
3421 AS2 (mov,%B0,%A1) CR_TAB
3423 else if (reg0 + 1 == reg1)
3426 return AS1 (clr,%A0);
3429 return (AS1 (clr,%A0) CR_TAB
3430 AS2 (mov,%B0,%A1) CR_TAB
3431 AS2 (mov,%C0,%B1) CR_TAB
3437 int reg0 = true_regnum (operands[0]);
3438 int reg1 = true_regnum (operands[1]);
3440 if (AVR_ENHANCED && (reg0 + 2 != reg1))
3443 return (AS2 (movw,%C0,%A1) CR_TAB
3444 AS1 (clr,%B0) CR_TAB
3447 if (reg0 + 1 >= reg1)
3448 return (AS2 (mov,%D0,%B1) CR_TAB
3449 AS2 (mov,%C0,%A1) CR_TAB
3450 AS1 (clr,%B0) CR_TAB
3452 if (reg0 + 2 == reg1)
3455 return (AS1 (clr,%B0) CR_TAB
3459 return (AS2 (mov,%C0,%A1) CR_TAB
3460 AS2 (mov,%D0,%B1) CR_TAB
3461 AS1 (clr,%B0) CR_TAB
3467 if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
3468 return (AS2 (mov,%D0,%A1) CR_TAB
3469 AS1 (clr,%C0) CR_TAB
3470 AS1 (clr,%B0) CR_TAB
3475 return (AS1 (clr,%C0) CR_TAB
3476 AS1 (clr,%B0) CR_TAB
3482 return (AS1 (clr,%D0) CR_TAB
3483 AS1 (lsr,%A0) CR_TAB
3484 AS1 (ror,%D0) CR_TAB
3485 AS1 (clr,%C0) CR_TAB
3486 AS1 (clr,%B0) CR_TAB
3491 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3492 AS1 (rol,%B0) CR_TAB
3493 AS1 (rol,%C0) CR_TAB
3495 insn, operands, len, 4);
3499 /* 8bit arithmetic shift right ((signed char)x >> i) */
3502 ashrqi3_out (insn, operands, len)
3505 int *len; /* insn length */
3507 if (GET_CODE (operands[2]) == CONST_INT)
3514 switch (INTVAL (operands[2]))
3518 return AS1 (asr,%0);
3522 return (AS1 (asr,%0) CR_TAB
3527 return (AS1 (asr,%0) CR_TAB
3533 return (AS1 (asr,%0) CR_TAB
3540 return (AS1 (asr,%0) CR_TAB
3548 return (AS2 (bst,%0,6) CR_TAB
3550 AS2 (sbc,%0,%0) CR_TAB
3556 return (AS1 (lsl,%0) CR_TAB
3560 else if (CONSTANT_P (operands[2]))
3561 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3563 out_shift_with_cnt (AS1 (asr,%0),
3564 insn, operands, len, 1);
3569 /* 16bit arithmetic shift right ((signed short)x >> i) */
3572 ashrhi3_out (insn, operands, len)
3577 if (GET_CODE (operands[2]) == CONST_INT)
3579 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3580 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3587 switch (INTVAL (operands[2]))
3591 /* XXX try to optimize this too? */
3596 break; /* scratch ? 5 : 6 */
3598 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3599 AS2 (mov,%A0,%B0) CR_TAB
3600 AS1 (lsl,__tmp_reg__) CR_TAB
3601 AS1 (rol,%A0) CR_TAB
3602 AS2 (sbc,%B0,%B0) CR_TAB
3603 AS1 (lsl,__tmp_reg__) CR_TAB
3604 AS1 (rol,%A0) CR_TAB
3609 return (AS1 (lsl,%A0) CR_TAB
3610 AS2 (mov,%A0,%B0) CR_TAB
3611 AS1 (rol,%A0) CR_TAB
3616 int reg0 = true_regnum (operands[0]);
3617 int reg1 = true_regnum (operands[1]);
3620 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3621 AS1 (lsl,%B0) CR_TAB
3623 else if (reg0 == reg1 + 1)
3624 return *len = 3, (AS1 (clr,%B0) CR_TAB
3625 AS2 (sbrc,%A0,7) CR_TAB
3628 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3629 AS1 (clr,%B0) CR_TAB
3630 AS2 (sbrc,%A0,7) CR_TAB
3636 return (AS2 (mov,%A0,%B0) CR_TAB
3637 AS1 (lsl,%B0) CR_TAB
3638 AS2 (sbc,%B0,%B0) CR_TAB
3643 return (AS2 (mov,%A0,%B0) CR_TAB
3644 AS1 (lsl,%B0) CR_TAB
3645 AS2 (sbc,%B0,%B0) CR_TAB
3646 AS1 (asr,%A0) CR_TAB
3650 if (AVR_ENHANCED && ldi_ok)
3653 return (AS2 (ldi,%A0,0x20) CR_TAB
3654 AS2 (muls,%B0,%A0) CR_TAB
3655 AS2 (mov,%A0,r1) CR_TAB
3656 AS2 (sbc,%B0,%B0) CR_TAB
3657 AS1 (clr,__zero_reg__));
3659 if (optimize_size && scratch)
3662 return (AS2 (mov,%A0,%B0) CR_TAB
3663 AS1 (lsl,%B0) CR_TAB
3664 AS2 (sbc,%B0,%B0) CR_TAB
3665 AS1 (asr,%A0) CR_TAB
3666 AS1 (asr,%A0) CR_TAB
3670 if (AVR_ENHANCED && ldi_ok)
3673 return (AS2 (ldi,%A0,0x10) CR_TAB
3674 AS2 (muls,%B0,%A0) CR_TAB
3675 AS2 (mov,%A0,r1) CR_TAB
3676 AS2 (sbc,%B0,%B0) CR_TAB
3677 AS1 (clr,__zero_reg__));
3679 if (optimize_size && scratch)
3682 return (AS2 (mov,%A0,%B0) CR_TAB
3683 AS1 (lsl,%B0) CR_TAB
3684 AS2 (sbc,%B0,%B0) CR_TAB
3685 AS1 (asr,%A0) CR_TAB
3686 AS1 (asr,%A0) CR_TAB
3687 AS1 (asr,%A0) CR_TAB
3691 if (AVR_ENHANCED && ldi_ok)
3694 return (AS2 (ldi,%A0,0x08) CR_TAB
3695 AS2 (muls,%B0,%A0) CR_TAB
3696 AS2 (mov,%A0,r1) CR_TAB
3697 AS2 (sbc,%B0,%B0) CR_TAB
3698 AS1 (clr,__zero_reg__));
3701 break; /* scratch ? 5 : 7 */
3703 return (AS2 (mov,%A0,%B0) CR_TAB
3704 AS1 (lsl,%B0) CR_TAB
3705 AS2 (sbc,%B0,%B0) CR_TAB
3706 AS1 (asr,%A0) CR_TAB
3707 AS1 (asr,%A0) CR_TAB
3708 AS1 (asr,%A0) CR_TAB
3709 AS1 (asr,%A0) CR_TAB
3714 return (AS1 (lsl,%B0) CR_TAB
3715 AS2 (sbc,%A0,%A0) CR_TAB
3716 AS1 (lsl,%B0) CR_TAB
3717 AS2 (mov,%B0,%A0) CR_TAB
3721 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3722 AS2 (sbc,%A0,%A0) CR_TAB
3727 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3729 insn, operands, len, 2);
3734 /* 32bit arithmetic shift right ((signed long)x >> i) */
3737 ashrsi3_out (insn, operands, len)
3742 if (GET_CODE (operands[2]) == CONST_INT)
3750 switch (INTVAL (operands[2]))
3754 int reg0 = true_regnum (operands[0]);
3755 int reg1 = true_regnum (operands[1]);
3758 return (AS2 (mov,%A0,%B1) CR_TAB
3759 AS2 (mov,%B0,%C1) CR_TAB
3760 AS2 (mov,%C0,%D1) CR_TAB
3761 AS1 (clr,%D0) CR_TAB
3762 AS2 (sbrc,%C0,7) CR_TAB
3764 else if (reg0 == reg1 + 1)
3767 return (AS1 (clr,%D0) CR_TAB
3768 AS2 (sbrc,%C0,7) CR_TAB
3772 return (AS1 (clr,%D0) CR_TAB
3773 AS2 (sbrc,%D1,7) CR_TAB
3774 AS1 (dec,%D0) CR_TAB
3775 AS2 (mov,%C0,%D1) CR_TAB
3776 AS2 (mov,%B0,%C1) CR_TAB
3782 int reg0 = true_regnum (operands[0]);
3783 int reg1 = true_regnum (operands[1]);
3785 if (AVR_ENHANCED && (reg0 != reg1 + 2))
3788 return (AS2 (movw,%A0,%C1) CR_TAB
3789 AS1 (clr,%D0) CR_TAB
3790 AS2 (sbrc,%B0,7) CR_TAB
3791 AS1 (com,%D0) CR_TAB
3794 if (reg0 <= reg1 + 1)
3795 return (AS2 (mov,%A0,%C1) CR_TAB
3796 AS2 (mov,%B0,%D1) CR_TAB
3797 AS1 (clr,%D0) CR_TAB
3798 AS2 (sbrc,%B0,7) CR_TAB
3799 AS1 (com,%D0) CR_TAB
3801 else if (reg0 == reg1 + 2)
3802 return *len = 4, (AS1 (clr,%D0) CR_TAB
3803 AS2 (sbrc,%B0,7) CR_TAB
3804 AS1 (com,%D0) CR_TAB
3807 return (AS2 (mov,%B0,%D1) CR_TAB
3808 AS2 (mov,%A0,%C1) CR_TAB
3809 AS1 (clr,%D0) CR_TAB
3810 AS2 (sbrc,%B0,7) CR_TAB
3811 AS1 (com,%D0) CR_TAB
3816 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
3817 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3818 AS1 (clr,%D0) CR_TAB
3819 AS2 (sbrc,%A0,7) CR_TAB
3820 AS1 (com,%D0) CR_TAB
3821 AS2 (mov,%B0,%D0) CR_TAB
3824 return *len = 5, (AS1 (clr,%D0) CR_TAB
3825 AS2 (sbrc,%A0,7) CR_TAB
3826 AS1 (com,%D0) CR_TAB
3827 AS2 (mov,%B0,%D0) CR_TAB
3832 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3833 AS2 (sbc,%A0,%A0) CR_TAB
3834 AS2 (mov,%B0,%A0) CR_TAB
3835 AS2 (movw,%C0,%A0));
3837 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3838 AS2 (sbc,%A0,%A0) CR_TAB
3839 AS2 (mov,%B0,%A0) CR_TAB
3840 AS2 (mov,%C0,%A0) CR_TAB
3845 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3846 AS1 (ror,%C0) CR_TAB
3847 AS1 (ror,%B0) CR_TAB
3849 insn, operands, len, 4);
3853 /* 8bit logic shift right ((unsigned char)x >> i) */
3856 lshrqi3_out (insn, operands, len)
3861 if (GET_CODE (operands[2]) == CONST_INT)
3868 switch (INTVAL (operands[2]))
3872 return AS1 (clr,%0);
3876 return AS1 (lsr,%0);
3880 return (AS1 (lsr,%0) CR_TAB
3884 return (AS1 (lsr,%0) CR_TAB
3889 if (test_hard_reg_class (LD_REGS, operands[0]))
3892 return (AS1 (swap,%0) CR_TAB
3893 AS2 (andi,%0,0x0f));
3896 return (AS1 (lsr,%0) CR_TAB
3902 if (test_hard_reg_class (LD_REGS, operands[0]))
3905 return (AS1 (swap,%0) CR_TAB
3910 return (AS1 (lsr,%0) CR_TAB
3917 if (test_hard_reg_class (LD_REGS, operands[0]))
3920 return (AS1 (swap,%0) CR_TAB
3926 return (AS1 (lsr,%0) CR_TAB
3935 return (AS1 (rol,%0) CR_TAB
3940 else if (CONSTANT_P (operands[2]))
3941 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3943 out_shift_with_cnt (AS1 (lsr,%0),
3944 insn, operands, len, 1);
3948 /* 16bit logic shift right ((unsigned short)x >> i) */
3951 lshrhi3_out (insn, operands, len)
3956 if (GET_CODE (operands[2]) == CONST_INT)
3958 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3959 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3966 switch (INTVAL (operands[2]))
3969 if (optimize_size && scratch)
3974 return (AS1 (swap,%B0) CR_TAB
3975 AS1 (swap,%A0) CR_TAB
3976 AS2 (andi,%A0,0x0f) CR_TAB
3977 AS2 (eor,%A0,%B0) CR_TAB
3978 AS2 (andi,%B0,0x0f) CR_TAB
3984 return (AS1 (swap,%B0) CR_TAB
3985 AS1 (swap,%A0) CR_TAB
3986 AS2 (ldi,%3,0x0f) CR_TAB
3987 AS2 (and,%A0,%3) CR_TAB
3988 AS2 (eor,%A0,%B0) CR_TAB
3989 AS2 (and,%B0,%3) CR_TAB
3992 break; /* optimize_size ? 6 : 8 */
3996 break; /* scratch ? 5 : 6 */
4000 return (AS1 (lsr,%B0) CR_TAB
4001 AS1 (ror,%A0) CR_TAB
4002 AS1 (swap,%B0) CR_TAB
4003 AS1 (swap,%A0) CR_TAB
4004 AS2 (andi,%A0,0x0f) CR_TAB
4005 AS2 (eor,%A0,%B0) CR_TAB
4006 AS2 (andi,%B0,0x0f) CR_TAB
4012 return (AS1 (lsr,%B0) CR_TAB
4013 AS1 (ror,%A0) CR_TAB
4014 AS1 (swap,%B0) CR_TAB
4015 AS1 (swap,%A0) CR_TAB
4016 AS2 (ldi,%3,0x0f) CR_TAB
4017 AS2 (and,%A0,%3) CR_TAB
4018 AS2 (eor,%A0,%B0) CR_TAB
4019 AS2 (and,%B0,%3) CR_TAB
4026 break; /* scratch ? 5 : 6 */
4028 return (AS1 (clr,__tmp_reg__) CR_TAB
4029 AS1 (lsl,%A0) CR_TAB
4030 AS1 (rol,%B0) CR_TAB
4031 AS1 (rol,__tmp_reg__) CR_TAB
4032 AS1 (lsl,%A0) CR_TAB
4033 AS1 (rol,%B0) CR_TAB
4034 AS1 (rol,__tmp_reg__) CR_TAB
4035 AS2 (mov,%A0,%B0) CR_TAB
4036 AS2 (mov,%B0,__tmp_reg__));
4040 return (AS1 (lsl,%A0) CR_TAB
4041 AS2 (mov,%A0,%B0) CR_TAB
4042 AS1 (rol,%A0) CR_TAB
4043 AS2 (sbc,%B0,%B0) CR_TAB
4047 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
4048 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
4051 return *len = 1, AS1 (clr,%B0);
4055 return (AS2 (mov,%A0,%B0) CR_TAB
4056 AS1 (clr,%B0) CR_TAB
4061 return (AS2 (mov,%A0,%B0) CR_TAB
4062 AS1 (clr,%B0) CR_TAB
4063 AS1 (lsr,%A0) CR_TAB
4068 return (AS2 (mov,%A0,%B0) CR_TAB
4069 AS1 (clr,%B0) CR_TAB
4070 AS1 (lsr,%A0) CR_TAB
4071 AS1 (lsr,%A0) CR_TAB
4078 return (AS2 (mov,%A0,%B0) CR_TAB
4079 AS1 (clr,%B0) CR_TAB
4080 AS1 (swap,%A0) CR_TAB
4081 AS2 (andi,%A0,0x0f));
4086 return (AS2 (mov,%A0,%B0) CR_TAB
4087 AS1 (clr,%B0) CR_TAB
4088 AS1 (swap,%A0) CR_TAB
4089 AS2 (ldi,%3,0x0f) CR_TAB
4093 return (AS2 (mov,%A0,%B0) CR_TAB
4094 AS1 (clr,%B0) CR_TAB
4095 AS1 (lsr,%A0) CR_TAB
4096 AS1 (lsr,%A0) CR_TAB
4097 AS1 (lsr,%A0) CR_TAB
4104 return (AS2 (mov,%A0,%B0) CR_TAB
4105 AS1 (clr,%B0) CR_TAB
4106 AS1 (swap,%A0) CR_TAB
4107 AS1 (lsr,%A0) CR_TAB
4108 AS2 (andi,%A0,0x07));
4110 if (AVR_ENHANCED && scratch)
4113 return (AS2 (ldi,%3,0x08) CR_TAB
4114 AS2 (mul,%B0,%3) CR_TAB
4115 AS2 (mov,%A0,r1) CR_TAB
4116 AS1 (clr,%B0) CR_TAB
4117 AS1 (clr,__zero_reg__));
4119 if (optimize_size && scratch)
4124 return (AS2 (mov,%A0,%B0) CR_TAB
4125 AS1 (clr,%B0) CR_TAB
4126 AS1 (swap,%A0) CR_TAB
4127 AS1 (lsr,%A0) CR_TAB
4128 AS2 (ldi,%3,0x07) CR_TAB
4134 return ("set" CR_TAB
4135 AS2 (bld,r1,3) CR_TAB
4136 AS2 (mul,%B0,r1) CR_TAB
4137 AS2 (mov,%A0,r1) CR_TAB
4138 AS1 (clr,%B0) CR_TAB
4139 AS1 (clr,__zero_reg__));
4142 return (AS2 (mov,%A0,%B0) CR_TAB
4143 AS1 (clr,%B0) CR_TAB
4144 AS1 (lsr,%A0) CR_TAB
4145 AS1 (lsr,%A0) CR_TAB
4146 AS1 (lsr,%A0) CR_TAB
4147 AS1 (lsr,%A0) CR_TAB
4151 if (AVR_ENHANCED && ldi_ok)
4154 return (AS2 (ldi,%A0,0x04) CR_TAB
4155 AS2 (mul,%B0,%A0) CR_TAB
4156 AS2 (mov,%A0,r1) CR_TAB
4157 AS1 (clr,%B0) CR_TAB
4158 AS1 (clr,__zero_reg__));
4160 if (AVR_ENHANCED && scratch)
4163 return (AS2 (ldi,%3,0x04) CR_TAB
4164 AS2 (mul,%B0,%3) CR_TAB
4165 AS2 (mov,%A0,r1) CR_TAB
4166 AS1 (clr,%B0) CR_TAB
4167 AS1 (clr,__zero_reg__));
4169 if (optimize_size && ldi_ok)
4172 return (AS2 (mov,%A0,%B0) CR_TAB
4173 AS2 (ldi,%B0,6) "\n1:\t"
4174 AS1 (lsr,%A0) CR_TAB
4175 AS1 (dec,%B0) CR_TAB
4178 if (optimize_size && scratch)
4181 return (AS1 (clr,%A0) CR_TAB
4182 AS1 (lsl,%B0) CR_TAB
4183 AS1 (rol,%A0) CR_TAB
4184 AS1 (lsl,%B0) CR_TAB
4185 AS1 (rol,%A0) CR_TAB
4190 return (AS1 (clr,%A0) CR_TAB
4191 AS1 (lsl,%B0) CR_TAB
4192 AS1 (rol,%A0) CR_TAB
4197 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4199 insn, operands, len, 2);
4203 /* 32bit logic shift right ((unsigned int)x >> i) */
4206 lshrsi3_out (insn, operands, len)
4211 if (GET_CODE (operands[2]) == CONST_INT)
4219 switch (INTVAL (operands[2]))
4223 int reg0 = true_regnum (operands[0]);
4224 int reg1 = true_regnum (operands[1]);
4227 return (AS2 (mov,%A0,%B1) CR_TAB
4228 AS2 (mov,%B0,%C1) CR_TAB
4229 AS2 (mov,%C0,%D1) CR_TAB
4231 else if (reg0 == reg1 + 1)
4232 return *len = 1, AS1 (clr,%D0);
4234 return (AS1 (clr,%D0) CR_TAB
4235 AS2 (mov,%C0,%D1) CR_TAB
4236 AS2 (mov,%B0,%C1) CR_TAB
4242 int reg0 = true_regnum (operands[0]);
4243 int reg1 = true_regnum (operands[1]);
4245 if (AVR_ENHANCED && (reg0 != reg1 + 2))
4248 return (AS2 (movw,%A0,%C1) CR_TAB
4249 AS1 (clr,%C0) CR_TAB
4252 if (reg0 <= reg1 + 1)
4253 return (AS2 (mov,%A0,%C1) CR_TAB
4254 AS2 (mov,%B0,%D1) CR_TAB
4255 AS1 (clr,%C0) CR_TAB
4257 else if (reg0 == reg1 + 2)
4258 return *len = 2, (AS1 (clr,%C0) CR_TAB
4261 return (AS2 (mov,%B0,%D1) CR_TAB
4262 AS2 (mov,%A0,%C1) CR_TAB
4263 AS1 (clr,%C0) CR_TAB
4268 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
4269 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4270 AS1 (clr,%B0) CR_TAB
4271 AS1 (clr,%C0) CR_TAB
4274 return *len = 3, (AS1 (clr,%B0) CR_TAB
4275 AS1 (clr,%C0) CR_TAB
4280 return (AS1 (clr,%A0) CR_TAB
4281 AS2 (sbrc,%D0,7) CR_TAB
4282 AS1 (inc,%A0) CR_TAB
4283 AS1 (clr,%B0) CR_TAB
4284 AS1 (clr,%C0) CR_TAB
4289 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4290 AS1 (ror,%C0) CR_TAB
4291 AS1 (ror,%B0) CR_TAB
4293 insn, operands, len, 4);
4297 /* Modifies the length assigned to instruction INSN
4298 LEN is the initially computed length of the insn. */
4301 adjust_insn_length (insn, len)
4305 rtx patt = PATTERN (insn);
4308 if (GET_CODE (patt) == SET)
4311 op[1] = SET_SRC (patt);
4312 op[0] = SET_DEST (patt);
4313 if (general_operand (op[1], VOIDmode)
4314 && general_operand (op[0], VOIDmode))
4316 switch (GET_MODE (op[0]))
4319 output_movqi (insn, op, &len);
4322 output_movhi (insn, op, &len);
4326 output_movsisf (insn, op, &len);
4332 else if (op[0] == cc0_rtx && REG_P (op[1]))
4334 switch (GET_MODE (op[1]))
4336 case HImode: out_tsthi (insn,&len); break;
4337 case SImode: out_tstsi (insn,&len); break;
4341 else if (GET_CODE (op[1]) == AND)
4343 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4345 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4346 if (GET_MODE (op[1]) == SImode)
4347 len = (((mask & 0xff) != 0xff)
4348 + ((mask & 0xff00) != 0xff00)
4349 + ((mask & 0xff0000L) != 0xff0000L)
4350 + ((mask & 0xff000000L) != 0xff000000L));
4351 else if (GET_MODE (op[1]) == HImode)
4352 len = (((mask & 0xff) != 0xff)
4353 + ((mask & 0xff00) != 0xff00));
4356 else if (GET_CODE (op[1]) == IOR)
4358 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4360 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4361 if (GET_MODE (op[1]) == SImode)
4362 len = (((mask & 0xff) != 0)
4363 + ((mask & 0xff00) != 0)
4364 + ((mask & 0xff0000L) != 0)
4365 + ((mask & 0xff000000L) != 0));
4366 else if (GET_MODE (op[1]) == HImode)
4367 len = (((mask & 0xff) != 0)
4368 + ((mask & 0xff00) != 0));
4372 set = single_set (insn);
4377 op[1] = SET_SRC (set);
4378 op[0] = SET_DEST (set);
4380 if (GET_CODE (patt) == PARALLEL
4381 && general_operand (op[1], VOIDmode)
4382 && general_operand (op[0], VOIDmode))
4384 if (XVECLEN (patt, 0) == 2)
4385 op[2] = XVECEXP (patt, 0, 1);
4387 switch (GET_MODE (op[0]))
4393 output_reload_inhi (insn, op, &len);
4397 output_reload_insisf (insn, op, &len);
4403 else if (GET_CODE (op[1]) == ASHIFT
4404 || GET_CODE (op[1]) == ASHIFTRT
4405 || GET_CODE (op[1]) == LSHIFTRT)
4409 ops[1] = XEXP (op[1],0);
4410 ops[2] = XEXP (op[1],1);
4411 switch (GET_CODE (op[1]))
4414 switch (GET_MODE (op[0]))
4416 case QImode: ashlqi3_out (insn,ops,&len); break;
4417 case HImode: ashlhi3_out (insn,ops,&len); break;
4418 case SImode: ashlsi3_out (insn,ops,&len); break;
4423 switch (GET_MODE (op[0]))
4425 case QImode: ashrqi3_out (insn,ops,&len); break;
4426 case HImode: ashrhi3_out (insn,ops,&len); break;
4427 case SImode: ashrsi3_out (insn,ops,&len); break;
4432 switch (GET_MODE (op[0]))
4434 case QImode: lshrqi3_out (insn,ops,&len); break;
4435 case HImode: lshrhi3_out (insn,ops,&len); break;
4436 case SImode: lshrsi3_out (insn,ops,&len); break;
4448 /* Return nonzero if register REG dead after INSN */
4451 reg_unused_after (insn, reg)
4455 return (dead_or_set_p (insn, reg)
4456 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4459 /* Return nonzero if REG is not used after INSN.
4460 We assume REG is a reload reg, and therefore does
4461 not live past labels. It may live past calls or jumps though. */
4464 _reg_unused_after (insn, reg)
4471 /* If the reg is set by this instruction, then it is safe for our
4472 case. Disregard the case where this is a store to memory, since
4473 we are checking a register used in the store address. */
4474 set = single_set (insn);
4475 if (set && GET_CODE (SET_DEST (set)) != MEM
4476 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4479 while ((insn = NEXT_INSN (insn)))
4481 code = GET_CODE (insn);
4484 /* If this is a label that existed before reload, then the register
4485 if dead here. However, if this is a label added by reorg, then
4486 the register may still be live here. We can't tell the difference,
4487 so we just ignore labels completely. */
4488 if (code == CODE_LABEL)
4493 if (code == JUMP_INSN)
4496 /* If this is a sequence, we must handle them all at once.
4497 We could have for instance a call that sets the target register,
4498 and an insn in a delay slot that uses the register. In this case,
4499 we must return 0. */
4500 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4505 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4507 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4508 rtx set = single_set (this_insn);
4510 if (GET_CODE (this_insn) == CALL_INSN)
4512 else if (GET_CODE (this_insn) == JUMP_INSN)
4514 if (INSN_ANNULLED_BRANCH_P (this_insn))
4519 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4521 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4523 if (GET_CODE (SET_DEST (set)) != MEM)
4529 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4534 else if (code == JUMP_INSN)
4538 if (code == CALL_INSN)
4541 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4542 if (GET_CODE (XEXP (tem, 0)) == USE
4543 && REG_P (XEXP (XEXP (tem, 0), 0))
4544 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4546 if (call_used_regs[REGNO (reg)])
4550 if (GET_RTX_CLASS (code) == 'i')
4552 rtx set = single_set (insn);
4554 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4556 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4557 return GET_CODE (SET_DEST (set)) != MEM;
4558 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4565 /* Target hook for assembling integer objects. The AVR version needs
4566 special handling for references to certain labels. */
4569 avr_assemble_integer (x, size, aligned_p)
4574 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
4575 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
4576 || GET_CODE (x) == LABEL_REF))
4578 fputs ("\t.word\tpm(", asm_out_file);
4579 output_addr_const (asm_out_file, x);
4580 fputs (")\n", asm_out_file);
4583 return default_assemble_integer (x, size, aligned_p);
4586 /* Sets section name for declaration DECL */
4589 avr_unique_section (decl, reloc)
4591 int reloc ATTRIBUTE_UNUSED;
4594 const char *name, *prefix;
4597 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
4598 name = (* targetm.strip_name_encoding) (name);
4600 if (TREE_CODE (decl) == FUNCTION_DECL)
4602 if (flag_function_sections)
4610 if (flag_function_sections)
4612 len = strlen (name) + strlen (prefix);
4613 string = alloca (len + 1);
4614 sprintf (string, "%s%s", prefix, name);
4615 DECL_SECTION_NAME (decl) = build_string (len, string);
4620 /* The routine used to output NUL terminated strings. We use a special
4621 version of this for most svr4 targets because doing so makes the
4622 generated assembly code more compact (and thus faster to assemble)
4623 as well as more readable, especially for targets like the i386
4624 (where the only alternative is to output character sequences as
4625 comma separated lists of numbers). */
4628 gas_output_limited_string(file, str)
4632 const unsigned char *_limited_str = (unsigned char *) str;
4634 fprintf (file, "%s\"", STRING_ASM_OP);
4635 for (; (ch = *_limited_str); _limited_str++)
4638 switch (escape = ESCAPES[ch])
4644 fprintf (file, "\\%03o", ch);
4648 putc (escape, file);
4652 fprintf (file, "\"\n");
4655 /* The routine used to output sequences of byte values. We use a special
4656 version of this for most svr4 targets because doing so makes the
4657 generated assembly code more compact (and thus faster to assemble)
4658 as well as more readable. Note that if we find subparts of the
4659 character sequence which end with NUL (and which are shorter than
4660 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4663 gas_output_ascii(file, str, length)
4668 const unsigned char *_ascii_bytes = (const unsigned char *) str;
4669 const unsigned char *limit = _ascii_bytes + length;
4670 unsigned bytes_in_chunk = 0;
4671 for (; _ascii_bytes < limit; _ascii_bytes++)
4673 const unsigned char *p;
4674 if (bytes_in_chunk >= 60)
4676 fprintf (file, "\"\n");
4679 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4681 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4683 if (bytes_in_chunk > 0)
4685 fprintf (file, "\"\n");
4688 gas_output_limited_string (file, (char*)_ascii_bytes);
4695 if (bytes_in_chunk == 0)
4696 fprintf (file, "\t.ascii\t\"");
4697 switch (escape = ESCAPES[ch = *_ascii_bytes])
4704 fprintf (file, "\\%03o", ch);
4705 bytes_in_chunk += 4;
4709 putc (escape, file);
4710 bytes_in_chunk += 2;
4715 if (bytes_in_chunk > 0)
4716 fprintf (file, "\"\n");
4719 /* Return value is nonzero if pseudos that have been
4720 assigned to registers of class CLASS would likely be spilled
4721 because registers of CLASS are needed for spill registers. */
4724 class_likely_spilled_p (c)
4727 return (c != ALL_REGS && c != ADDW_REGS);
4730 /* Valid attributes:
4731 progmem - put data to program memory;
4732 signal - make a function to be hardware interrupt. After function
4733 prologue interrupts are disabled;
4734 interrupt - make a function to be hardware interrupt. After function
4735 prologue interrupts are enabled;
4736 naked - don't generate function prologue/epilogue and `ret' command.
4738 Only `progmem' attribute valid for type. */
4740 const struct attribute_spec avr_attribute_table[] =
4742 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4743 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
4744 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4745 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4746 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4747 { NULL, 0, 0, false, false, false, NULL }
4750 /* Handle a "progmem" attribute; arguments as in
4751 struct attribute_spec.handler. */
4753 avr_handle_progmem_attribute (node, name, args, flags, no_add_attrs)
4756 tree args ATTRIBUTE_UNUSED;
4757 int flags ATTRIBUTE_UNUSED;
4762 if (TREE_CODE (*node) == TYPE_DECL)
4764 /* This is really a decl attribute, not a type attribute,
4765 but try to handle it for GCC 3.0 backwards compatibility. */
4767 tree type = TREE_TYPE (*node);
4768 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
4769 tree newtype = build_type_attribute_variant (type, attr);
4771 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
4772 TREE_TYPE (*node) = newtype;
4773 *no_add_attrs = true;
4775 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
4777 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
4779 warning ("only initialized variables can be placed into "
4780 "program memory area");
4781 *no_add_attrs = true;
4786 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
4787 *no_add_attrs = true;
4794 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4795 struct attribute_spec.handler. */
4797 avr_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
4800 tree args ATTRIBUTE_UNUSED;
4801 int flags ATTRIBUTE_UNUSED;
4804 if (TREE_CODE (*node) != FUNCTION_DECL)
4806 warning ("`%s' attribute only applies to functions",
4807 IDENTIFIER_POINTER (name));
4808 *no_add_attrs = true;
4814 /* Look for attribute `progmem' in DECL
4815 if found return 1, otherwise 0. */
4818 avr_progmem_p (decl)
4823 if (TREE_CODE (decl) != VAR_DECL)
4827 != lookup_attribute ("progmem", DECL_ATTRIBUTES (decl)))
4833 while (TREE_CODE (a) == ARRAY_TYPE);
4835 if (a == error_mark_node)
4838 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4844 /* Add the section attribute if the variable is in progmem. */
4847 avr_insert_attributes (node, attributes)
4851 if (TREE_CODE (node) == VAR_DECL
4852 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
4853 && avr_progmem_p (node))
4855 static const char dsec[] = ".progmem.data";
4856 *attributes = tree_cons (get_identifier ("section"),
4857 build_tree_list (NULL, build_string (strlen (dsec), dsec)),
4860 /* ??? This seems sketchy. Why can't the user declare the
4861 thing const in the first place? */
4862 TREE_READONLY (node) = 1;
4867 avr_section_type_flags (decl, name, reloc)
4872 unsigned int flags = default_section_type_flags (decl, name, reloc);
4874 if (strncmp (name, ".noinit", 7) == 0)
4876 if (decl && TREE_CODE (decl) == VAR_DECL
4877 && DECL_INITIAL (decl) == NULL_TREE)
4878 flags |= SECTION_BSS; /* @nobits */
4880 warning ("only uninitialized variables can be placed in the "
4887 /* Outputs to the stdio stream FILE some
4888 appropriate text to go at the start of an assembler file. */
4891 asm_file_start (file)
4895 error ("MCU `%s' supported for assembler only", avr_mcu_name);
4897 output_file_directive (file, main_input_filename);
4898 fprintf (file, "\t.arch %s\n", avr_mcu_name);
4899 fputs ("__SREG__ = 0x3f\n"
4901 "__SP_L__ = 0x3d\n", file);
4903 fputs ("__tmp_reg__ = 0\n"
4904 "__zero_reg__ = 1\n", file);
4906 /* FIXME: output these only if there is anything in the .data / .bss
4907 sections - some code size could be saved by not linking in the
4908 initialization code from libgcc if one or both sections are empty. */
4909 fputs ("\t.global __do_copy_data\n", file);
4910 fputs ("\t.global __do_clear_bss\n", file);
4912 commands_in_file = 0;
4913 commands_in_prologues = 0;
4914 commands_in_epilogues = 0;
4917 /* Outputs to the stdio stream FILE some
4918 appropriate text to go at the end of an assembler file. */
4924 fputs ("/* File ", file);
4925 output_quoted_string (file, main_input_filename);
4927 ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4930 commands_in_file - commands_in_prologues - commands_in_epilogues,
4931 commands_in_prologues, commands_in_epilogues);
4934 /* Choose the order in which to allocate hard registers for
4935 pseudo-registers local to a basic block.
4937 Store the desired register order in the array `reg_alloc_order'.
4938 Element 0 should be the register to allocate first; element 1, the
4939 next register; and so on. */
4942 order_regs_for_local_alloc ()
4945 static const int order_0[] = {
4953 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4957 static const int order_1[] = {
4965 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4969 static const int order_2[] = {
4978 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4983 const int *order = (TARGET_ORDER_1 ? order_1 :
4984 TARGET_ORDER_2 ? order_2 :
4986 for (i=0; i < ARRAY_SIZE (order_0); ++i)
4987 reg_alloc_order[i] = order[i];
4990 /* Calculate the cost of X code of the expression in which it is contained,
4991 found in OUTER_CODE */
4994 default_rtx_costs (X, code, outer_code)
4997 enum rtx_code outer_code;
5004 cost = 2 * GET_MODE_SIZE (GET_MODE (X));
5007 if (outer_code != SET)
5009 if (GET_CODE (XEXP (X,0)) == SYMBOL_REF)
5010 cost += 2 * GET_MODE_SIZE (GET_MODE (X));
5012 cost += GET_MODE_SIZE (GET_MODE (X));
5018 if (outer_code == SET)
5019 cost = GET_MODE_SIZE (GET_MODE (X));
5021 cost = -GET_MODE_SIZE (GET_MODE (X));
5024 if (outer_code == SET)
5025 cost = GET_MODE_SIZE (GET_MODE (X));
5031 if (outer_code == SET)
5033 if (X == stack_pointer_rtx)
5035 else if (GET_CODE (XEXP (X,1)) == CONST_INT)
5036 cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 :
5037 GET_MODE_SIZE (GET_MODE (X)));
5039 cost = GET_MODE_SIZE (GET_MODE (X));
5043 if (GET_CODE (XEXP (X,1)) == CONST_INT)
5044 cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0)));
5053 avr_rtx_costs (x, code, outer_code, total)
5055 int code, outer_code;
5063 if (outer_code == PLUS
5064 || outer_code == IOR
5065 || outer_code == AND
5066 || outer_code == MINUS
5067 || outer_code == SET
5073 if (outer_code == COMPARE
5075 && INTVAL (x) <= 255)
5090 cst = default_rtx_costs (x, code, outer_code);
5102 /* Calculate the cost of a memory address */
5105 avr_address_cost (x)
5108 if (GET_CODE (x) == PLUS
5109 && GET_CODE (XEXP (x,1)) == CONST_INT
5110 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
5111 && INTVAL (XEXP (x,1)) >= 61)
5113 if (CONSTANT_ADDRESS_P (x))
5115 if (avr_io_address_p (x, 1))
5122 /* EXTRA_CONSTRAINT helper */
5125 extra_constraint (x, c)
5130 && GET_CODE (x) == MEM
5131 && GET_CODE (XEXP (x,0)) == PLUS)
5133 if (TARGET_ALL_DEBUG)
5135 fprintf (stderr, ("extra_constraint:\n"
5136 "reload_completed: %d\n"
5137 "reload_in_progress: %d\n"),
5138 reload_completed, reload_in_progress);
5141 if (GET_CODE (x) == MEM
5142 && GET_CODE (XEXP (x,0)) == PLUS
5143 && REG_P (XEXP (XEXP (x,0), 0))
5144 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
5145 && (INTVAL (XEXP (XEXP (x,0), 1))
5146 <= MAX_LD_OFFSET (GET_MODE (x))))
5148 rtx xx = XEXP (XEXP (x,0), 0);
5149 int regno = REGNO (xx);
5150 if (TARGET_ALL_DEBUG)
5152 fprintf (stderr, ("extra_constraint:\n"
5153 "reload_completed: %d\n"
5154 "reload_in_progress: %d\n"),
5155 reload_completed, reload_in_progress);
5158 if (regno >= FIRST_PSEUDO_REGISTER)
5159 return 1; /* allocate pseudos */
5160 else if (regno == REG_Z || regno == REG_Y)
5161 return 1; /* strictly check */
5162 else if (xx == frame_pointer_rtx
5163 || xx == arg_pointer_rtx)
5164 return 1; /* XXX frame & arg pointer checks */
5170 /* Convert condition code CONDITION to the valid AVR condition code */
5173 avr_normalize_condition (condition)
5191 /* This fnction optimizes conditional jumps */
5198 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5200 if (! (GET_CODE (insn) == INSN
5201 || GET_CODE (insn) == CALL_INSN
5202 || GET_CODE (insn) == JUMP_INSN)
5203 || !single_set (insn))
5206 pattern = PATTERN (insn);
5208 if (GET_CODE (pattern) == PARALLEL)
5209 pattern = XVECEXP (pattern, 0, 0);
5210 if (GET_CODE (pattern) == SET
5211 && SET_DEST (pattern) == cc0_rtx
5212 && compare_diff_p (insn))
5214 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
5216 /* Now we work under compare insn */
5218 pattern = SET_SRC (pattern);
5219 if (true_regnum (XEXP (pattern,0)) >= 0
5220 && true_regnum (XEXP (pattern,1)) >= 0 )
5222 rtx x = XEXP (pattern,0);
5223 rtx next = next_real_insn (insn);
5224 rtx pat = PATTERN (next);
5225 rtx src = SET_SRC (pat);
5226 rtx t = XEXP (src,0);
5227 PUT_CODE (t, swap_condition (GET_CODE (t)));
5228 XEXP (pattern,0) = XEXP (pattern,1);
5229 XEXP (pattern,1) = x;
5230 INSN_CODE (next) = -1;
5232 else if (true_regnum (XEXP (pattern,0)) >= 0
5233 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
5235 rtx x = XEXP (pattern,1);
5236 rtx next = next_real_insn (insn);
5237 rtx pat = PATTERN (next);
5238 rtx src = SET_SRC (pat);
5239 rtx t = XEXP (src,0);
5240 enum machine_mode mode = GET_MODE (XEXP (pattern, 0));
5242 if (avr_simplify_comparision_p (mode, GET_CODE (t), x))
5244 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
5245 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
5246 INSN_CODE (next) = -1;
5247 INSN_CODE (insn) = -1;
5251 else if (true_regnum (SET_SRC (pattern)) >= 0)
5253 /* This is a tst insn */
5254 rtx next = next_real_insn (insn);
5255 rtx pat = PATTERN (next);
5256 rtx src = SET_SRC (pat);
5257 rtx t = XEXP (src,0);
5259 PUT_CODE (t, swap_condition (GET_CODE (t)));
5260 SET_SRC (pattern) = gen_rtx (NEG,
5261 GET_MODE (SET_SRC (pattern)),
5263 INSN_CODE (next) = -1;
5264 INSN_CODE (insn) = -1;
5270 /* Returns register number for function return value.*/
5278 /* Ceate an RTX representing the place where a
5279 library function returns a value of mode MODE. */
5282 avr_libcall_value (mode)
5283 enum machine_mode mode;
5285 int offs = GET_MODE_SIZE (mode);
5288 return gen_rtx (REG, mode, RET_REGISTER + 2 - offs);
5291 /* Create an RTX representing the place where a
5292 function returns a value of data type VALTYPE. */
5295 avr_function_value (type, func)
5297 tree func ATTRIBUTE_UNUSED;
5301 if (TYPE_MODE (type) != BLKmode)
5302 return avr_libcall_value (TYPE_MODE (type));
5304 offs = int_size_in_bytes (type);
5307 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5308 offs = GET_MODE_SIZE (SImode);
5309 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5310 offs = GET_MODE_SIZE (DImode);
5312 return gen_rtx (REG, BLKmode, RET_REGISTER + 2 - offs);
5315 /* Returns nonzero if the number MASK has only one bit set. */
5318 mask_one_bit_p (mask)
5322 unsigned HOST_WIDE_INT n=mask;
5323 for (i = 0; i < 32; ++i)
5325 if (n & 0x80000000L)
5327 if (n & 0x7fffffffL)
5338 /* Places additional restrictions on the register class to
5339 use when it is necessary to copy value X into a register
5343 preferred_reload_class (x, class)
5344 rtx x ATTRIBUTE_UNUSED;
5345 enum reg_class class;
5351 test_hard_reg_class (class, x)
5352 enum reg_class class;
5355 int regno = true_regnum (x);
5359 if (TEST_HARD_REG_CLASS (class, regno))
5367 jump_over_one_insn_p (insn, dest)
5371 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5374 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5375 int dest_addr = INSN_ADDRESSES (uid);
5376 return dest_addr - jump_addr == get_attr_length (insn) + 1;
5379 /* Returns 1 if a value of mode MODE can be stored starting with hard
5380 register number REGNO. On the enhanced core, anything larger than
5381 1 byte must start in even numbered register for "movw" to work
5382 (this way we don't have to check for odd registers everywhere). */
5385 avr_hard_regno_mode_ok (regno, mode)
5387 enum machine_mode mode;
5389 /* Bug workaround: recog.c (peep2_find_free_register) and probably
5390 a few other places assume that the frame pointer is a single hard
5391 register, so r29 may be allocated and overwrite the high byte of
5392 the frame pointer. Do not allow any value to start in r29. */
5393 if (regno == REG_Y + 1)
5398 /* if (regno < 24 && !AVR_ENHANCED)
5400 return !(regno & 1);
5403 /* Returns 1 if we know register operand OP was 0 before INSN. */
5406 reg_was_0 (insn, op)
5411 return (optimize > 0 && insn && op && REG_P (op)
5412 && (link = find_reg_note (insn, REG_WAS_0, 0))
5413 /* Make sure the insn that stored the 0 is still present. */
5414 && ! INSN_DELETED_P (XEXP (link, 0))
5415 && GET_CODE (XEXP (link, 0)) != NOTE
5416 /* Make sure cross jumping didn't happen here. */
5417 && no_labels_between_p (XEXP (link, 0), insn)
5418 /* Make sure the reg hasn't been clobbered. */
5419 && ! reg_set_between_p (op, XEXP (link, 0), insn));
5422 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5423 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5424 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
5427 avr_io_address_p (x, size)
5431 return (optimize > 0 && GET_CODE (x) == CONST_INT
5432 && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
5435 /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5438 const_int_pow2_p (x)
5441 if (GET_CODE (x) == CONST_INT)
5443 HOST_WIDE_INT d = INTVAL (x);
5444 HOST_WIDE_INT abs_d = (d >= 0) ? d : -d;
5445 return exact_log2 (abs_d) + 1;
5451 output_reload_inhi (insn, operands, len)
5452 rtx insn ATTRIBUTE_UNUSED;
5460 if (GET_CODE (operands[1]) == CONST_INT)
5462 int val = INTVAL (operands[1]);
5463 if ((val & 0xff) == 0)
5466 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5467 AS2 (ldi,%2,hi8(%1)) CR_TAB
5470 else if ((val & 0xff00) == 0)
5473 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5474 AS2 (mov,%A0,%2) CR_TAB
5475 AS2 (mov,%B0,__zero_reg__));
5477 else if ((val & 0xff) == ((val & 0xff00) >> 8))
5480 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5481 AS2 (mov,%A0,%2) CR_TAB
5486 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5487 AS2 (mov,%A0,%2) CR_TAB
5488 AS2 (ldi,%2,hi8(%1)) CR_TAB
5494 output_reload_insisf (insn, operands, len)
5495 rtx insn ATTRIBUTE_UNUSED;
5499 rtx src = operands[1];
5500 int cnst = (GET_CODE (src) == CONST_INT);
5505 *len = 4 + ((INTVAL (src) & 0xff) != 0)
5506 + ((INTVAL (src) & 0xff00) != 0)
5507 + ((INTVAL (src) & 0xff0000) != 0)
5508 + ((INTVAL (src) & 0xff000000) != 0);
5515 if (cnst && ((INTVAL (src) & 0xff) == 0))
5516 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5519 output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
5520 output_asm_insn (AS2 (mov, %A0, %2), operands);
5522 if (cnst && ((INTVAL (src) & 0xff00) == 0))
5523 output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
5526 output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
5527 output_asm_insn (AS2 (mov, %B0, %2), operands);
5529 if (cnst && ((INTVAL (src) & 0xff0000) == 0))
5530 output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
5533 output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
5534 output_asm_insn (AS2 (mov, %C0, %2), operands);
5536 if (cnst && ((INTVAL (src) & 0xff000000) == 0))
5537 output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
5540 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5541 output_asm_insn (AS2 (mov, %D0, %2), operands);
5547 avr_output_bld (operands, bit_nr)
5551 static char s[] = "bld %A0,0";
5553 s[5] = 'A' + (bit_nr >> 3);
5554 s[8] = '0' + (bit_nr & 7);
5555 output_asm_insn (s, operands);
5559 avr_output_addr_vec_elt (stream, value)
5564 fprintf (stream, "\t.word pm(.L%d)\n", value);
5566 fprintf (stream, "\trjmp .L%d\n", value);
5571 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5572 registers (for a define_peephole2) in the current function. */
5575 avr_peep2_scratch_safe (scratch)
5578 if ((interrupt_function_p (current_function_decl)
5579 || signal_function_p (current_function_decl))
5580 && leaf_function_p ())
5582 int first_reg = true_regnum (scratch);
5583 int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
5586 for (reg = first_reg; reg <= last_reg; reg++)
5588 if (!regs_ever_live[reg])
5595 /* Output a branch that tests a single bit of a register (QI, HI or SImode)
5596 or memory location in the I/O space (QImode only).
5598 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5599 Operand 1: register operand to test, or CONST_INT memory address.
5600 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5601 Operand 3: label to jump to if the test is true. */
5604 avr_out_sbxx_branch (insn, operands)
5608 enum rtx_code comp = GET_CODE (operands[0]);
5609 int long_jump = (get_attr_length (insn) >= 4);
5610 int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
5614 else if (comp == LT)
5618 comp = reverse_condition (comp);
5620 if (GET_CODE (operands[1]) == CONST_INT)
5622 if (INTVAL (operands[1]) < 0x40)
5625 output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
5627 output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
5631 output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
5633 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
5635 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
5638 else /* GET_CODE (operands[1]) == REG */
5640 if (GET_MODE (operands[1]) == QImode)
5643 output_asm_insn (AS2 (sbrs,%1,%2), operands);
5645 output_asm_insn (AS2 (sbrc,%1,%2), operands);
5647 else /* HImode or SImode */
5649 static char buf[] = "sbrc %A1,0";
5650 int bit_nr = exact_log2 (INTVAL (operands[2])
5651 & GET_MODE_MASK (GET_MODE (operands[1])));
5653 buf[3] = (comp == EQ) ? 's' : 'c';
5654 buf[6] = 'A' + (bit_nr >> 3);
5655 buf[9] = '0' + (bit_nr & 7);
5656 output_asm_insn (buf, operands);
5661 return (AS1 (rjmp,.+4) CR_TAB
5664 return AS1 (rjmp,%3);
5669 avr_asm_out_ctor (symbol, priority)
5673 fputs ("\t.global __do_global_ctors\n", asm_out_file);
5674 default_ctor_section_asm_out_constructor (symbol, priority);
5678 avr_asm_out_dtor (symbol, priority)
5682 fputs ("\t.global __do_global_dtors\n", asm_out_file);
5683 default_dtor_section_asm_out_destructor (symbol, priority);