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 GCC.
7 GCC 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 GCC 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 GCC; 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"
45 #include "target-def.h"
47 /* Maximal allowed offset for an address in the LD command */
48 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
50 static int avr_naked_function_p (tree);
51 static int interrupt_function_p (tree);
52 static int signal_function_p (tree);
53 static int avr_regs_to_save (HARD_REG_SET *);
54 static int sequent_regs_live (void);
55 static const char *ptrreg_to_str (int);
56 static const char *cond_string (enum rtx_code);
57 static int avr_num_arg_regs (enum machine_mode, tree);
58 static int out_adj_frame_ptr (FILE *, int);
59 static int out_set_stack_ptr (FILE *, int, int);
60 static RTX_CODE compare_condition (rtx insn);
61 static int compare_sign_p (rtx insn);
62 static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *);
63 static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
64 const struct attribute_spec avr_attribute_table[];
65 static bool avr_assemble_integer (rtx, unsigned int, int);
66 static void avr_file_start (void);
67 static void avr_file_end (void);
68 static void avr_output_function_prologue (FILE *, HOST_WIDE_INT);
69 static void avr_output_function_epilogue (FILE *, HOST_WIDE_INT);
70 static void avr_unique_section (tree, int);
71 static void avr_insert_attributes (tree, tree *);
72 static unsigned int avr_section_type_flags (tree, const char *, int);
74 static void avr_reorg (void);
75 static void avr_asm_out_ctor (rtx, int);
76 static void avr_asm_out_dtor (rtx, int);
77 static int default_rtx_costs (rtx, enum rtx_code, enum rtx_code);
78 static bool avr_rtx_costs (rtx, int, int, int *);
79 static int avr_address_cost (rtx);
80 static bool avr_return_in_memory (tree, tree);
82 /* Allocate registers from r25 to r8 for parameters for function calls. */
83 #define FIRST_CUM_REG 26
85 /* Temporary register RTX (gen_rtx (REG,QImode,TMP_REGNO)) */
86 static GTY(()) rtx tmp_reg_rtx;
88 /* Zeroed register RTX (gen_rtx (REG,QImode,ZERO_REGNO)) */
89 static GTY(()) rtx zero_reg_rtx;
91 /* AVR register names {"r0", "r1", ..., "r31"} */
92 static const char *const avr_regnames[] = REGISTER_NAMES;
94 /* This holds the last insn address. */
95 static int last_insn_address = 0;
97 /* Commands count in the compiled file */
98 static int commands_in_file;
100 /* Commands in the functions prologues in the compiled file */
101 static int commands_in_prologues;
103 /* Commands in the functions epilogues in the compiled file */
104 static int commands_in_epilogues;
106 /* Prologue/Epilogue size in words */
107 static int prologue_size;
108 static int epilogue_size;
110 /* Size of all jump tables in the current function, in words. */
111 static int jump_tables_size;
113 /* Initial stack value specified by the `-minit-stack=' option */
114 const char *avr_init_stack = "__stack";
116 /* Default MCU name */
117 const char *avr_mcu_name = "avr2";
119 /* Preprocessor macros to define depending on MCU type. */
120 const char *avr_base_arch_macro;
121 const char *avr_extra_arch_macro;
123 /* More than 8K of program memory: use "call" and "jmp". */
126 /* Enhanced core: use "movw", "mul", ... */
127 int avr_enhanced_p = 0;
129 /* Assembler only. */
130 int avr_asm_only_p = 0;
136 const char *const macro;
139 static const struct base_arch_s avr_arch_types[] = {
140 { 1, 0, 0, NULL }, /* unknown device specified */
141 { 1, 0, 0, "__AVR_ARCH__=1" },
142 { 0, 0, 0, "__AVR_ARCH__=2" },
143 { 0, 0, 1, "__AVR_ARCH__=3" },
144 { 0, 1, 0, "__AVR_ARCH__=4" },
145 { 0, 1, 1, "__AVR_ARCH__=5" }
149 const char *const name;
150 int arch; /* index in avr_arch_types[] */
151 /* Must lie outside user's namespace. NULL == no macro. */
152 const char *const macro;
155 /* List of all known AVR MCU types - if updated, it has to be kept
156 in sync in several places (FIXME: is there a better way?):
158 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
159 - t-avr (MULTILIB_MATCHES)
160 - gas/config/tc-avr.c
163 static const struct mcu_type_s avr_mcu_types[] = {
164 /* Classic, <= 8K. */
166 { "at90s2313", 2, "__AVR_AT90S2313__" },
167 { "at90s2323", 2, "__AVR_AT90S2323__" },
168 { "at90s2333", 2, "__AVR_AT90S2333__" },
169 { "at90s2343", 2, "__AVR_AT90S2343__" },
170 { "attiny22", 2, "__AVR_ATtiny22__" },
171 { "attiny26", 2, "__AVR_ATtiny26__" },
172 { "at90s4414", 2, "__AVR_AT90S4414__" },
173 { "at90s4433", 2, "__AVR_AT90S4433__" },
174 { "at90s4434", 2, "__AVR_AT90S4434__" },
175 { "at90s8515", 2, "__AVR_AT90S8515__" },
176 { "at90c8534", 2, "__AVR_AT90C8534__" },
177 { "at90s8535", 2, "__AVR_AT90S8535__" },
178 { "at86rf401", 2, "__AVR_AT86RF401__" },
181 { "atmega103", 3, "__AVR_ATmega103__" },
182 { "atmega603", 3, "__AVR_ATmega603__" },
183 { "at43usb320", 3, "__AVR_AT43USB320__" },
184 { "at43usb355", 3, "__AVR_AT43USB355__" },
185 { "at76c711", 3, "__AVR_AT76C711__" },
186 /* Enhanced, <= 8K. */
188 { "atmega8", 4, "__AVR_ATmega8__" },
189 { "atmega8515", 4, "__AVR_ATmega8515__" },
190 { "atmega8535", 4, "__AVR_ATmega8535__" },
191 /* Enhanced, > 8K. */
193 { "atmega16", 5, "__AVR_ATmega16__" },
194 { "atmega161", 5, "__AVR_ATmega161__" },
195 { "atmega162", 5, "__AVR_ATmega162__" },
196 { "atmega163", 5, "__AVR_ATmega163__" },
197 { "atmega169", 5, "__AVR_ATmega169__" },
198 { "atmega32", 5, "__AVR_ATmega32__" },
199 { "atmega323", 5, "__AVR_ATmega323__" },
200 { "atmega64", 5, "__AVR_ATmega64__" },
201 { "atmega128", 5, "__AVR_ATmega128__" },
202 { "at94k", 5, "__AVR_AT94K__" },
203 /* Assembler only. */
205 { "at90s1200", 1, "__AVR_AT90S1200__" },
206 { "attiny11", 1, "__AVR_ATtiny11__" },
207 { "attiny12", 1, "__AVR_ATtiny12__" },
208 { "attiny15", 1, "__AVR_ATtiny15__" },
209 { "attiny28", 1, "__AVR_ATtiny28__" },
213 int avr_case_values_threshold = 30000;
215 /* Initialize the GCC target structure. */
216 #undef TARGET_ASM_ALIGNED_HI_OP
217 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
218 #undef TARGET_ASM_INTEGER
219 #define TARGET_ASM_INTEGER avr_assemble_integer
220 #undef TARGET_ASM_FILE_START
221 #define TARGET_ASM_FILE_START avr_file_start
222 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
223 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
224 #undef TARGET_ASM_FILE_END
225 #define TARGET_ASM_FILE_END avr_file_end
227 #undef TARGET_ASM_FUNCTION_PROLOGUE
228 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
229 #undef TARGET_ASM_FUNCTION_EPILOGUE
230 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
231 #undef TARGET_ATTRIBUTE_TABLE
232 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
233 #undef TARGET_ASM_UNIQUE_SECTION
234 #define TARGET_ASM_UNIQUE_SECTION avr_unique_section
235 #undef TARGET_INSERT_ATTRIBUTES
236 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
237 #undef TARGET_SECTION_TYPE_FLAGS
238 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
239 #undef TARGET_RTX_COSTS
240 #define TARGET_RTX_COSTS avr_rtx_costs
241 #undef TARGET_ADDRESS_COST
242 #define TARGET_ADDRESS_COST avr_address_cost
243 #undef TARGET_MACHINE_DEPENDENT_REORG
244 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
246 #undef TARGET_STRUCT_VALUE_RTX
247 #define TARGET_STRUCT_VALUE_RTX hook_rtx_tree_int_null
248 #undef TARGET_RETURN_IN_MEMORY
249 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
251 #undef TARGET_STRICT_ARGUMENT_NAMING
252 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
254 struct gcc_target targetm = TARGET_INITIALIZER;
257 avr_override_options (void)
259 const struct mcu_type_s *t;
260 const struct base_arch_s *base;
262 for (t = avr_mcu_types; t->name; t++)
263 if (strcmp (t->name, avr_mcu_name) == 0)
268 fprintf (stderr, "unknown MCU `%s' specified\nKnown MCU names:\n",
270 for (t = avr_mcu_types; t->name; t++)
271 fprintf (stderr," %s\n", t->name);
274 base = &avr_arch_types[t->arch];
275 avr_asm_only_p = base->asm_only;
276 avr_enhanced_p = base->enhanced;
277 avr_mega_p = base->mega;
278 avr_base_arch_macro = base->macro;
279 avr_extra_arch_macro = t->macro;
281 if (optimize && !TARGET_NO_TABLEJUMP)
282 avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
284 tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO);
285 zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO);
288 /* return register class from register number. */
290 static const int reg_class_tab[]={
291 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
292 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
293 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
294 GENERAL_REGS, /* r0 - r15 */
295 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
296 LD_REGS, /* r16 - 23 */
297 ADDW_REGS,ADDW_REGS, /* r24,r25 */
298 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
299 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
300 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
301 STACK_REG,STACK_REG /* SPL,SPH */
304 /* Return register class for register R. */
307 avr_regno_reg_class (int r)
310 return reg_class_tab[r];
315 /* A C expression which defines the machine-dependent operand
316 constraint letters for register classes. If C is such a
317 letter, the value should be the register class corresponding to
318 it. Otherwise, the value should be `NO_REGS'. The register
319 letter `r', corresponding to class `GENERAL_REGS', will not be
320 passed to this macro; you do not need to handle it. */
323 avr_reg_class_from_letter (int c)
327 case 't' : return R0_REG;
328 case 'b' : return BASE_POINTER_REGS;
329 case 'e' : return POINTER_REGS;
330 case 'w' : return ADDW_REGS;
331 case 'd' : return LD_REGS;
332 case 'l' : return NO_LD_REGS;
333 case 'a' : return SIMPLE_LD_REGS;
334 case 'x' : return POINTER_X_REGS;
335 case 'y' : return POINTER_Y_REGS;
336 case 'z' : return POINTER_Z_REGS;
337 case 'q' : return STACK_REG;
343 /* Return nonzero if FUNC is a naked function. */
346 avr_naked_function_p (tree func)
350 if (TREE_CODE (func) != FUNCTION_DECL)
353 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
354 return a != NULL_TREE;
357 /* Return nonzero if FUNC is an interrupt function as specified
358 by the "interrupt" attribute. */
361 interrupt_function_p (tree func)
365 if (TREE_CODE (func) != FUNCTION_DECL)
368 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
369 return a != NULL_TREE;
372 /* Return nonzero if FUNC is a signal function as specified
373 by the "signal" attribute. */
376 signal_function_p (tree func)
380 if (TREE_CODE (func) != FUNCTION_DECL)
383 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
384 return a != NULL_TREE;
387 /* Return the number of hard registers to push/pop in the prologue/epilogue
388 of the current function, and optionally store these registers in SET. */
391 avr_regs_to_save (HARD_REG_SET *set)
394 int int_or_sig_p = (interrupt_function_p (current_function_decl)
395 || signal_function_p (current_function_decl));
396 int leaf_func_p = leaf_function_p ();
399 CLEAR_HARD_REG_SET (*set);
402 /* No need to save any registers if the function never returns. */
403 if (TREE_THIS_VOLATILE (current_function_decl))
406 for (reg = 0; reg < 32; reg++)
408 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
409 any global register variables. */
413 if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
414 || (regs_ever_live[reg]
415 && (int_or_sig_p || !call_used_regs[reg])
416 && !(frame_pointer_needed
417 && (reg == REG_Y || reg == (REG_Y+1)))))
420 SET_HARD_REG_BIT (*set, reg);
427 /* Compute offset between arg_pointer and frame_pointer. */
430 initial_elimination_offset (int from, int to)
432 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
436 int offset = frame_pointer_needed ? 2 : 0;
438 offset += avr_regs_to_save (NULL);
439 return get_frame_size () + 2 + 1 + offset;
443 /* Return 1 if the function epilogue is just a single "ret". */
446 avr_simple_epilogue (void)
448 return (! frame_pointer_needed
449 && get_frame_size () == 0
450 && avr_regs_to_save (NULL) == 0
451 && ! interrupt_function_p (current_function_decl)
452 && ! signal_function_p (current_function_decl)
453 && ! avr_naked_function_p (current_function_decl)
454 && ! MAIN_NAME_P (DECL_NAME (current_function_decl))
455 && ! TREE_THIS_VOLATILE (current_function_decl));
458 /* This function checks sequence of live registers. */
461 sequent_regs_live (void)
467 for (reg = 0; reg < 18; ++reg)
469 if (!call_used_regs[reg])
471 if (regs_ever_live[reg])
481 if (!frame_pointer_needed)
483 if (regs_ever_live[REG_Y])
491 if (regs_ever_live[REG_Y+1])
504 return (cur_seq == live_seq) ? live_seq : 0;
508 /* Output to FILE the asm instructions to adjust the frame pointer by
509 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
510 (epilogue). Returns the number of instructions generated. */
513 out_adj_frame_ptr (FILE *file, int adj)
519 if (TARGET_TINY_STACK)
521 if (adj < -63 || adj > 63)
522 warning ("large frame pointer change (%d) with -mtiny-stack", adj);
524 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
525 over "sbiw" (2 cycles, same size). */
527 fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
530 else if (adj < -63 || adj > 63)
532 fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
533 AS2 (sbci, r29, hi8(%d)) CR_TAB),
539 fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
544 fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
552 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
553 handling various cases of interrupt enable flag state BEFORE and AFTER
554 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
555 Returns the number of instructions generated. */
558 out_set_stack_ptr (FILE *file, int before, int after)
560 int do_sph, do_cli, do_save, do_sei, lock_sph, size;
562 /* The logic here is so that -mno-interrupts actually means
563 "it is safe to write SPH in one instruction, then SPL in the
564 next instruction, without disabling interrupts first".
565 The after != -1 case (interrupt/signal) is not affected. */
567 do_sph = !TARGET_TINY_STACK;
568 lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
569 do_cli = (before != 0 && (after == 0 || lock_sph));
570 do_save = (do_cli && before == -1 && after == -1);
571 do_sei = ((do_cli || before != 1) && after == 1);
576 fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
582 fprintf (file, "cli" CR_TAB);
586 /* Do SPH first - maybe this will disable interrupts for one instruction
587 someday (a suggestion has been sent to avr@atmel.com for consideration
588 in future devices - that would make -mno-interrupts always safe). */
591 fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
595 /* Set/restore the I flag now - interrupts will be really enabled only
596 after the next instruction. This is not clearly documented, but
597 believed to be true for all AVR devices. */
600 fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
605 fprintf (file, "sei" CR_TAB);
609 fprintf (file, AS2 (out, __SP_L__, r28) "\n");
615 /* Output function prologue. */
618 avr_output_function_prologue (FILE *file, HOST_WIDE_INT size)
621 int interrupt_func_p;
627 last_insn_address = 0;
628 jump_tables_size = 0;
630 fprintf (file, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n",
633 if (avr_naked_function_p (current_function_decl))
635 fputs ("/* prologue: naked */\n", file);
639 interrupt_func_p = interrupt_function_p (current_function_decl);
640 signal_func_p = signal_function_p (current_function_decl);
641 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
642 live_seq = sequent_regs_live ();
643 minimize = (TARGET_CALL_PROLOGUES
644 && !interrupt_func_p && !signal_func_p && live_seq);
646 if (interrupt_func_p)
648 fprintf (file,"\tsei\n");
651 if (interrupt_func_p || signal_func_p)
654 AS1 (push,__zero_reg__) CR_TAB
655 AS1 (push,__tmp_reg__) CR_TAB
656 AS2 (in,__tmp_reg__,__SREG__) CR_TAB
657 AS1 (push,__tmp_reg__) CR_TAB
658 AS1 (clr,__zero_reg__) "\n");
664 AS1 (ldi,r28) ",lo8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
665 AS1 (ldi,r29) ",hi8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
666 AS2 (out,__SP_H__,r29) CR_TAB
667 AS2 (out,__SP_L__,r28) "\n"),
668 avr_init_stack, size, avr_init_stack, size);
672 else if (minimize && (frame_pointer_needed || live_seq > 6))
674 const char *cfun_name = current_function_name ();
676 AS1 (ldi, r26) ",lo8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
677 AS1 (ldi, r27) ",hi8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB), size, size);
679 fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB
680 AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB),
681 cfun_name, cfun_name);
687 fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
688 (18 - live_seq) * 2);
693 fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
694 (18 - live_seq) * 2);
697 fprintf (file, ".L_%s_body:\n", cfun_name);
703 prologue_size += avr_regs_to_save (&set);
704 for (reg = 0; reg < 32; ++reg)
706 if (TEST_HARD_REG_BIT (set, reg))
708 fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
711 if (frame_pointer_needed)
714 AS1 (push,r28) CR_TAB
715 AS1 (push,r29) CR_TAB
716 AS2 (in,r28,__SP_L__) CR_TAB
717 AS2 (in,r29,__SP_H__) "\n");
722 prologue_size += out_adj_frame_ptr (file, size);
724 if (interrupt_func_p)
726 prologue_size += out_set_stack_ptr (file, 1, 1);
728 else if (signal_func_p)
730 prologue_size += out_set_stack_ptr (file, 0, 0);
734 prologue_size += out_set_stack_ptr (file, -1, -1);
741 fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
744 /* Output function epilogue. */
747 avr_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
750 int interrupt_func_p;
756 rtx last = get_last_nonnote_insn ();
758 function_size = jump_tables_size;
761 rtx first = get_first_nonnote_insn ();
762 function_size += (INSN_ADDRESSES (INSN_UID (last)) -
763 INSN_ADDRESSES (INSN_UID (first)));
764 function_size += get_attr_length (last);
767 fprintf (file, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n", size);
770 if (avr_naked_function_p (current_function_decl))
772 fputs ("/* epilogue: naked */\n", file);
776 if (last && GET_CODE (last) == BARRIER)
778 fputs ("/* epilogue: noreturn */\n", file);
782 interrupt_func_p = interrupt_function_p (current_function_decl);
783 signal_func_p = signal_function_p (current_function_decl);
784 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
785 live_seq = sequent_regs_live ();
786 minimize = (TARGET_CALL_PROLOGUES
787 && !interrupt_func_p && !signal_func_p && live_seq);
791 /* Return value from main() is already in the correct registers
792 (r25:r24) as the exit() argument. */
795 fputs ("\t" AS1 (jmp,exit) "\n", file);
800 fputs ("\t" AS1 (rjmp,exit) "\n", file);
804 else if (minimize && (frame_pointer_needed || live_seq > 4))
806 fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
808 if (frame_pointer_needed)
810 epilogue_size += out_adj_frame_ptr (file, -size);
814 fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
815 AS2 (in , r29, __SP_H__) CR_TAB));
821 fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
822 (18 - live_seq) * 2);
827 fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
828 (18 - live_seq) * 2);
836 if (frame_pointer_needed)
841 epilogue_size += out_adj_frame_ptr (file, -size);
843 if (interrupt_func_p || signal_func_p)
845 epilogue_size += out_set_stack_ptr (file, -1, 0);
849 epilogue_size += out_set_stack_ptr (file, -1, -1);
858 epilogue_size += avr_regs_to_save (&set);
859 for (reg = 31; reg >= 0; --reg)
861 if (TEST_HARD_REG_BIT (set, reg))
863 fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
867 if (interrupt_func_p || signal_func_p)
870 AS1 (pop,__tmp_reg__) CR_TAB
871 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
872 AS1 (pop,__tmp_reg__) CR_TAB
873 AS1 (pop,__zero_reg__) "\n");
875 fprintf (file, "\treti\n");
878 fprintf (file, "\tret\n");
883 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
884 fprintf (file, "/* function %s size %d (%d) */\n", current_function_name (),
885 prologue_size + function_size + epilogue_size, function_size);
886 commands_in_file += prologue_size + function_size + epilogue_size;
887 commands_in_prologues += prologue_size;
888 commands_in_epilogues += epilogue_size;
892 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
893 machine for a memory operand of mode MODE. */
896 legitimate_address_p (enum machine_mode mode, rtx x, int strict)
898 enum reg_class r = NO_REGS;
900 if (TARGET_ALL_DEBUG)
902 fprintf (stderr, "mode: (%s) %s %s %s %s:",
904 strict ? "(strict)": "",
905 reload_completed ? "(reload_completed)": "",
906 reload_in_progress ? "(reload_in_progress)": "",
907 reg_renumber ? "(reg_renumber)" : "");
908 if (GET_CODE (x) == PLUS
909 && REG_P (XEXP (x, 0))
910 && GET_CODE (XEXP (x, 1)) == CONST_INT
911 && INTVAL (XEXP (x, 1)) >= 0
912 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
915 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
916 true_regnum (XEXP (x, 0)));
919 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
920 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
922 else if (CONSTANT_ADDRESS_P (x))
924 else if (GET_CODE (x) == PLUS
925 && REG_P (XEXP (x, 0))
926 && GET_CODE (XEXP (x, 1)) == CONST_INT
927 && INTVAL (XEXP (x, 1)) >= 0)
929 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
933 || REGNO (XEXP (x,0)) == REG_Y
934 || REGNO (XEXP (x,0)) == REG_Z)
935 r = BASE_POINTER_REGS;
936 if (XEXP (x,0) == frame_pointer_rtx
937 || XEXP (x,0) == arg_pointer_rtx)
938 r = BASE_POINTER_REGS;
940 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
943 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
944 && REG_P (XEXP (x, 0))
945 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
946 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
950 if (TARGET_ALL_DEBUG)
952 fprintf (stderr, " ret = %c\n", r);
954 return r == NO_REGS ? 0 : (int)r;
957 /* Attempts to replace X with a valid
958 memory address for an operand of mode MODE */
961 legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
964 if (TARGET_ALL_DEBUG)
966 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
970 if (GET_CODE (oldx) == PLUS
971 && REG_P (XEXP (oldx,0)))
973 if (REG_P (XEXP (oldx,1)))
974 x = force_reg (GET_MODE (oldx), oldx);
975 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
977 int offs = INTVAL (XEXP (oldx,1));
978 if (frame_pointer_rtx != XEXP (oldx,0))
979 if (offs > MAX_LD_OFFSET (mode))
981 if (TARGET_ALL_DEBUG)
982 fprintf (stderr, "force_reg (big offset)\n");
983 x = force_reg (GET_MODE (oldx), oldx);
991 /* Return a pointer register name as a string. */
994 ptrreg_to_str (int regno)
998 case REG_X: return "X";
999 case REG_Y: return "Y";
1000 case REG_Z: return "Z";
1007 /* Return the condition name as a string.
1008 Used in conditional jump constructing */
1011 cond_string (enum rtx_code code)
1020 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1025 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1038 /* Output ADDR to FILE as address. */
1041 print_operand_address (FILE *file, rtx addr)
1043 switch (GET_CODE (addr))
1046 fprintf (file, ptrreg_to_str (REGNO (addr)));
1050 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1054 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1058 if (CONSTANT_ADDRESS_P (addr)
1059 && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
1060 || GET_CODE (addr) == LABEL_REF))
1062 fprintf (file, "pm(");
1063 output_addr_const (file,addr);
1064 fprintf (file ,")");
1067 output_addr_const (file, addr);
1072 /* Output X as assembler operand to file FILE. */
1075 print_operand (FILE *file, rtx x, int code)
1079 if (code >= 'A' && code <= 'D')
1089 if (x == zero_reg_rtx)
1090 fprintf (file, "__zero_reg__");
1092 fprintf (file, reg_names[true_regnum (x) + abcd]);
1094 else if (GET_CODE (x) == CONST_INT)
1095 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
1096 else if (GET_CODE (x) == MEM)
1098 rtx addr = XEXP (x,0);
1100 if (CONSTANT_P (addr) && abcd)
1103 output_address (addr);
1104 fprintf (file, ")+%d", abcd);
1106 else if (code == 'o')
1108 if (GET_CODE (addr) != PLUS)
1109 fatal_insn ("bad address, not (reg+disp):", addr);
1111 print_operand (file, XEXP (addr, 1), 0);
1113 else if (GET_CODE (addr) == PLUS)
1115 print_operand_address (file, XEXP (addr,0));
1116 if (REGNO (XEXP (addr, 0)) == REG_X)
1117 fatal_insn ("internal compiler error. Bad address:"
1120 print_operand (file, XEXP (addr,1), code);
1123 print_operand_address (file, addr);
1125 else if (GET_CODE (x) == CONST_DOUBLE)
1129 if (GET_MODE (x) != SFmode)
1130 fatal_insn ("internal compiler error. Unknown mode:", x);
1131 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1132 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1133 fprintf (file, "0x%lx", val);
1135 else if (code == 'j')
1136 fputs (cond_string (GET_CODE (x)), file);
1137 else if (code == 'k')
1138 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
1140 print_operand_address (file, x);
1143 /* Recognize operand OP of mode MODE used in call instructions. */
1146 call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1148 if (GET_CODE (op) == MEM)
1150 rtx inside = XEXP (op, 0);
1151 if (register_operand (inside, Pmode))
1153 if (CONSTANT_ADDRESS_P (inside))
1159 /* Update the condition code in the INSN. */
1162 notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
1166 switch (get_attr_cc (insn))
1169 /* Insn does not affect CC at all. */
1177 set = single_set (insn);
1181 cc_status.flags |= CC_NO_OVERFLOW;
1182 cc_status.value1 = SET_DEST (set);
1187 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1188 The V flag may or may not be known but that's ok because
1189 alter_cond will change tests to use EQ/NE. */
1190 set = single_set (insn);
1194 cc_status.value1 = SET_DEST (set);
1195 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1200 set = single_set (insn);
1203 cc_status.value1 = SET_SRC (set);
1207 /* Insn doesn't leave CC in a usable state. */
1210 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1211 set = single_set (insn);
1214 rtx src = SET_SRC (set);
1216 if (GET_CODE (src) == ASHIFTRT
1217 && GET_MODE (src) == QImode)
1219 rtx x = XEXP (src, 1);
1221 if (GET_CODE (x) == CONST_INT
1224 cc_status.value1 = SET_DEST (set);
1225 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1233 /* Return maximum number of consecutive registers of
1234 class CLASS needed to hold a value of mode MODE. */
1237 class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,enum machine_mode mode)
1239 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1242 /* Choose mode for jump insn:
1243 1 - relative jump in range -63 <= x <= 62 ;
1244 2 - relative jump in range -2046 <= x <= 2045 ;
1245 3 - absolute jump (only for ATmega[16]03). */
1248 avr_jump_mode (rtx x, rtx insn)
1250 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1251 ? XEXP (x, 0) : x));
1252 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1253 int jump_distance = cur_addr - dest_addr;
1255 if (-63 <= jump_distance && jump_distance <= 62)
1257 else if (-2046 <= jump_distance && jump_distance <= 2045)
1265 /* return an AVR condition jump commands.
1266 X is a comparison RTX.
1267 LEN is a number returned by avr_jump_mode function.
1268 if REVERSE nonzero then condition code in X must be reversed. */
1271 ret_cond_branch (rtx x, int len, int reverse)
1273 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1278 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1279 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1281 len == 2 ? (AS1 (breq,.+4) CR_TAB
1282 AS1 (brmi,.+2) CR_TAB
1284 (AS1 (breq,.+6) CR_TAB
1285 AS1 (brmi,.+4) CR_TAB
1289 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1291 len == 2 ? (AS1 (breq,.+4) CR_TAB
1292 AS1 (brlt,.+2) CR_TAB
1294 (AS1 (breq,.+6) CR_TAB
1295 AS1 (brlt,.+4) CR_TAB
1298 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1300 len == 2 ? (AS1 (breq,.+4) CR_TAB
1301 AS1 (brlo,.+2) CR_TAB
1303 (AS1 (breq,.+6) CR_TAB
1304 AS1 (brlo,.+4) CR_TAB
1307 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1308 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1310 len == 2 ? (AS1 (breq,.+2) CR_TAB
1311 AS1 (brpl,.+2) CR_TAB
1313 (AS1 (breq,.+2) CR_TAB
1314 AS1 (brpl,.+4) CR_TAB
1317 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1319 len == 2 ? (AS1 (breq,.+2) CR_TAB
1320 AS1 (brge,.+2) CR_TAB
1322 (AS1 (breq,.+2) CR_TAB
1323 AS1 (brge,.+4) CR_TAB
1326 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1328 len == 2 ? (AS1 (breq,.+2) CR_TAB
1329 AS1 (brsh,.+2) CR_TAB
1331 (AS1 (breq,.+2) CR_TAB
1332 AS1 (brsh,.+4) CR_TAB
1340 return AS1 (br%k1,%0);
1342 return (AS1 (br%j1,.+2) CR_TAB
1345 return (AS1 (br%j1,.+4) CR_TAB
1354 return AS1 (br%j1,%0);
1356 return (AS1 (br%k1,.+2) CR_TAB
1359 return (AS1 (br%k1,.+4) CR_TAB
1367 /* Predicate function for immediate operand which fits to byte (8bit) */
1370 byte_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1372 return (GET_CODE (op) == CONST_INT
1373 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1376 /* Output all insn addresses and their sizes into the assembly language
1377 output file. This is helpful for debugging whether the length attributes
1378 in the md file are correct.
1379 Output insn cost for next insn. */
1382 final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
1383 int num_operands ATTRIBUTE_UNUSED)
1385 int uid = INSN_UID (insn);
1387 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1389 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1390 INSN_ADDRESSES (uid),
1391 INSN_ADDRESSES (uid) - last_insn_address,
1392 rtx_cost (PATTERN (insn), INSN));
1394 last_insn_address = INSN_ADDRESSES (uid);
1397 /* Return 0 if undefined, 1 if always true or always false. */
1400 avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE operator, rtx x)
1402 unsigned int max = (mode == QImode ? 0xff :
1403 mode == HImode ? 0xffff :
1404 mode == SImode ? 0xffffffff : 0);
1405 if (max && operator && GET_CODE (x) == CONST_INT)
1407 if (unsigned_condition (operator) != operator)
1410 if (max != (INTVAL (x) & max)
1411 && INTVAL (x) != 0xff)
1418 /* Returns nonzero if REGNO is the number of a hard
1419 register in which function arguments are sometimes passed. */
1422 function_arg_regno_p(int r)
1424 return (r >= 8 && r <= 25);
1427 /* Initializing the variable cum for the state at the beginning
1428 of the argument list. */
1431 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
1432 tree fndecl ATTRIBUTE_UNUSED)
1435 cum->regno = FIRST_CUM_REG;
1436 if (!libname && fntype)
1438 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1439 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1440 != void_type_node));
1446 /* Returns the number of registers to allocate for a function argument. */
1449 avr_num_arg_regs (enum machine_mode mode, tree type)
1453 if (mode == BLKmode)
1454 size = int_size_in_bytes (type);
1456 size = GET_MODE_SIZE (mode);
1458 /* Align all function arguments to start in even-numbered registers.
1459 Odd-sized arguments leave holes above them. */
1461 return (size + 1) & ~1;
1464 /* Controls whether a function argument is passed
1465 in a register, and which register. */
1468 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1469 int named ATTRIBUTE_UNUSED)
1471 int bytes = avr_num_arg_regs (mode, type);
1473 if (cum->nregs && bytes <= cum->nregs)
1474 return gen_rtx (REG, mode, cum->regno - bytes);
1479 /* Update the summarizer variable CUM to advance past an argument
1480 in the argument list. */
1483 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1484 int named ATTRIBUTE_UNUSED)
1486 int bytes = avr_num_arg_regs (mode, type);
1488 cum->nregs -= bytes;
1489 cum->regno -= bytes;
1491 if (cum->nregs <= 0)
1494 cum->regno = FIRST_CUM_REG;
1498 /***********************************************************************
1499 Functions for outputting various mov's for a various modes
1500 ************************************************************************/
1502 output_movqi (rtx insn, rtx operands[], int *l)
1505 rtx dest = operands[0];
1506 rtx src = operands[1];
1514 if (register_operand (dest, QImode))
1516 if (register_operand (src, QImode)) /* mov r,r */
1518 if (test_hard_reg_class (STACK_REG, dest))
1519 return AS2 (out,%0,%1);
1520 else if (test_hard_reg_class (STACK_REG, src))
1521 return AS2 (in,%0,%1);
1523 return AS2 (mov,%0,%1);
1525 else if (CONSTANT_P (src))
1527 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1528 return AS2 (ldi,%0,lo8(%1));
1530 if (GET_CODE (src) == CONST_INT)
1532 if (src == const0_rtx) /* mov r,L */
1533 return AS1 (clr,%0);
1534 else if (src == const1_rtx)
1537 return (AS1 (clr,%0) CR_TAB
1540 else if (src == constm1_rtx)
1542 /* Immediate constants -1 to any register */
1544 return (AS1 (clr,%0) CR_TAB
1549 int bit_nr = exact_log2 (INTVAL (src));
1555 output_asm_insn ((AS1 (clr,%0) CR_TAB
1558 avr_output_bld (operands, bit_nr);
1565 /* Last resort, larger than loading from memory. */
1567 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1568 AS2 (ldi,r31,lo8(%1)) CR_TAB
1569 AS2 (mov,%0,r31) CR_TAB
1570 AS2 (mov,r31,__tmp_reg__));
1572 else if (GET_CODE (src) == MEM)
1573 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1575 else if (GET_CODE (dest) == MEM)
1577 const char *template;
1579 if (src == const0_rtx)
1580 operands[1] = zero_reg_rtx;
1582 template = out_movqi_mr_r (insn, operands, real_l);
1585 output_asm_insn (template, operands);
1594 output_movhi (rtx insn, rtx operands[], int *l)
1597 rtx dest = operands[0];
1598 rtx src = operands[1];
1604 if (register_operand (dest, HImode))
1606 if (register_operand (src, HImode)) /* mov r,r */
1608 if (test_hard_reg_class (STACK_REG, dest))
1610 if (TARGET_TINY_STACK)
1613 return AS2 (out,__SP_L__,%A1);
1615 else if (TARGET_NO_INTERRUPTS)
1618 return (AS2 (out,__SP_H__,%B1) CR_TAB
1619 AS2 (out,__SP_L__,%A1));
1623 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1625 AS2 (out,__SP_H__,%B1) CR_TAB
1626 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1627 AS2 (out,__SP_L__,%A1));
1629 else if (test_hard_reg_class (STACK_REG, src))
1632 return (AS2 (in,%A0,__SP_L__) CR_TAB
1633 AS2 (in,%B0,__SP_H__));
1639 return (AS2 (movw,%0,%1));
1642 if (true_regnum (dest) > true_regnum (src))
1645 return (AS2 (mov,%B0,%B1) CR_TAB
1651 return (AS2 (mov,%A0,%A1) CR_TAB
1655 else if (CONSTANT_P (src))
1657 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1660 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1661 AS2 (ldi,%B0,hi8(%1)));
1664 if (GET_CODE (src) == CONST_INT)
1666 if (src == const0_rtx) /* mov r,L */
1669 return (AS1 (clr,%A0) CR_TAB
1672 else if (src == const1_rtx)
1675 return (AS1 (clr,%A0) CR_TAB
1676 AS1 (clr,%B0) CR_TAB
1679 else if (src == constm1_rtx)
1681 /* Immediate constants -1 to any register */
1683 return (AS1 (clr,%0) CR_TAB
1684 AS1 (dec,%A0) CR_TAB
1689 int bit_nr = exact_log2 (INTVAL (src));
1695 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1696 AS1 (clr,%B0) CR_TAB
1699 avr_output_bld (operands, bit_nr);
1705 if ((INTVAL (src) & 0xff) == 0)
1708 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1709 AS1 (clr,%A0) CR_TAB
1710 AS2 (ldi,r31,hi8(%1)) CR_TAB
1711 AS2 (mov,%B0,r31) CR_TAB
1712 AS2 (mov,r31,__tmp_reg__));
1714 else if ((INTVAL (src) & 0xff00) == 0)
1717 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1718 AS2 (ldi,r31,lo8(%1)) CR_TAB
1719 AS2 (mov,%A0,r31) CR_TAB
1720 AS1 (clr,%B0) CR_TAB
1721 AS2 (mov,r31,__tmp_reg__));
1725 /* Last resort, equal to loading from memory. */
1727 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1728 AS2 (ldi,r31,lo8(%1)) CR_TAB
1729 AS2 (mov,%A0,r31) CR_TAB
1730 AS2 (ldi,r31,hi8(%1)) CR_TAB
1731 AS2 (mov,%B0,r31) CR_TAB
1732 AS2 (mov,r31,__tmp_reg__));
1734 else if (GET_CODE (src) == MEM)
1735 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1737 else if (GET_CODE (dest) == MEM)
1739 const char *template;
1741 if (src == const0_rtx)
1742 operands[1] = zero_reg_rtx;
1744 template = out_movhi_mr_r (insn, operands, real_l);
1747 output_asm_insn (template, operands);
1752 fatal_insn ("invalid insn:", insn);
1757 out_movqi_r_mr (rtx insn, rtx op[], int *l)
1761 rtx x = XEXP (src, 0);
1767 if (CONSTANT_ADDRESS_P (x))
1769 if (avr_io_address_p (x, 1))
1772 return AS2 (in,%0,%1-0x20);
1775 return AS2 (lds,%0,%1);
1777 /* memory access by reg+disp */
1778 else if (GET_CODE (x) == PLUS
1779 && REG_P (XEXP (x,0))
1780 && GET_CODE (XEXP (x,1)) == CONST_INT)
1782 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
1784 int disp = INTVAL (XEXP (x,1));
1785 if (REGNO (XEXP (x,0)) != REG_Y)
1786 fatal_insn ("incorrect insn:",insn);
1788 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1789 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1790 AS2 (ldd,%0,Y+63) CR_TAB
1791 AS2 (sbiw,r28,%o1-63));
1793 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1794 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1795 AS2 (ld,%0,Y) CR_TAB
1796 AS2 (subi,r28,lo8(%o1)) CR_TAB
1797 AS2 (sbci,r29,hi8(%o1)));
1799 else if (REGNO (XEXP (x,0)) == REG_X)
1801 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1802 it but I have this situation with extremal optimizing options. */
1803 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
1804 || reg_unused_after (insn, XEXP (x,0)))
1805 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1808 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1809 AS2 (ld,%0,X) CR_TAB
1810 AS2 (sbiw,r26,%o1));
1813 return AS2 (ldd,%0,%1);
1816 return AS2 (ld,%0,%1);
1820 out_movhi_r_mr (rtx insn, rtx op[], int *l)
1824 rtx base = XEXP (src, 0);
1825 int reg_dest = true_regnum (dest);
1826 int reg_base = true_regnum (base);
1834 if (reg_dest == reg_base) /* R = (R) */
1837 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1838 AS2 (ld,%B0,%1) CR_TAB
1839 AS2 (mov,%A0,__tmp_reg__));
1841 else if (reg_base == REG_X) /* (R26) */
1843 if (reg_unused_after (insn, base))
1846 return (AS2 (ld,%A0,X+) CR_TAB
1850 return (AS2 (ld,%A0,X+) CR_TAB
1851 AS2 (ld,%B0,X) CR_TAB
1857 return (AS2 (ld,%A0,%1) CR_TAB
1858 AS2 (ldd,%B0,%1+1));
1861 else if (GET_CODE (base) == PLUS) /* (R + i) */
1863 int disp = INTVAL (XEXP (base, 1));
1864 int reg_base = true_regnum (XEXP (base, 0));
1866 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
1868 if (REGNO (XEXP (base, 0)) != REG_Y)
1869 fatal_insn ("incorrect insn:",insn);
1871 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1872 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
1873 AS2 (ldd,%A0,Y+62) CR_TAB
1874 AS2 (ldd,%B0,Y+63) CR_TAB
1875 AS2 (sbiw,r28,%o1-62));
1877 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1878 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1879 AS2 (ld,%A0,Y) CR_TAB
1880 AS2 (ldd,%B0,Y+1) CR_TAB
1881 AS2 (subi,r28,lo8(%o1)) CR_TAB
1882 AS2 (sbci,r29,hi8(%o1)));
1884 if (reg_base == REG_X)
1886 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1887 it but I have this situation with extremal
1888 optimization options. */
1891 if (reg_base == reg_dest)
1892 return (AS2 (adiw,r26,%o1) CR_TAB
1893 AS2 (ld,__tmp_reg__,X+) CR_TAB
1894 AS2 (ld,%B0,X) CR_TAB
1895 AS2 (mov,%A0,__tmp_reg__));
1897 return (AS2 (adiw,r26,%o1) CR_TAB
1898 AS2 (ld,%A0,X+) CR_TAB
1899 AS2 (ld,%B0,X) CR_TAB
1900 AS2 (sbiw,r26,%o1+1));
1903 if (reg_base == reg_dest)
1906 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
1907 AS2 (ldd,%B0,%B1) CR_TAB
1908 AS2 (mov,%A0,__tmp_reg__));
1912 return (AS2 (ldd,%A0,%A1) CR_TAB
1915 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
1917 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1918 fatal_insn ("incorrect insn:", insn);
1921 return (AS2 (ld,%B0,%1) CR_TAB
1924 else if (GET_CODE (base) == POST_INC) /* (R++) */
1926 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1927 fatal_insn ("incorrect insn:", insn);
1930 return (AS2 (ld,%A0,%1) CR_TAB
1933 else if (CONSTANT_ADDRESS_P (base))
1935 if (avr_io_address_p (base, 2))
1938 return (AS2 (in,%A0,%A1-0x20) CR_TAB
1939 AS2 (in,%B0,%B1-0x20));
1942 return (AS2 (lds,%A0,%A1) CR_TAB
1946 fatal_insn ("unknown move insn:",insn);
1951 out_movsi_r_mr (rtx insn, rtx op[], int *l)
1955 rtx base = XEXP (src, 0);
1956 int reg_dest = true_regnum (dest);
1957 int reg_base = true_regnum (base);
1965 if (reg_base == REG_X) /* (R26) */
1967 if (reg_dest == REG_X)
1968 /* "ld r26,-X" is undefined */
1969 return *l=7, (AS2 (adiw,r26,3) CR_TAB
1970 AS2 (ld,r29,X) CR_TAB
1971 AS2 (ld,r28,-X) CR_TAB
1972 AS2 (ld,__tmp_reg__,-X) CR_TAB
1973 AS2 (sbiw,r26,1) CR_TAB
1974 AS2 (ld,r26,X) CR_TAB
1975 AS2 (mov,r27,__tmp_reg__));
1976 else if (reg_dest == REG_X - 2)
1977 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
1978 AS2 (ld,%B0,X+) CR_TAB
1979 AS2 (ld,__tmp_reg__,X+) CR_TAB
1980 AS2 (ld,%D0,X) CR_TAB
1981 AS2 (mov,%C0,__tmp_reg__));
1982 else if (reg_unused_after (insn, base))
1983 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
1984 AS2 (ld,%B0,X+) CR_TAB
1985 AS2 (ld,%C0,X+) CR_TAB
1988 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
1989 AS2 (ld,%B0,X+) CR_TAB
1990 AS2 (ld,%C0,X+) CR_TAB
1991 AS2 (ld,%D0,X) CR_TAB
1996 if (reg_dest == reg_base)
1997 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
1998 AS2 (ldd,%C0,%1+2) CR_TAB
1999 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2000 AS2 (ld,%A0,%1) CR_TAB
2001 AS2 (mov,%B0,__tmp_reg__));
2002 else if (reg_base == reg_dest + 2)
2003 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2004 AS2 (ldd,%B0,%1+1) CR_TAB
2005 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2006 AS2 (ldd,%D0,%1+3) CR_TAB
2007 AS2 (mov,%C0,__tmp_reg__));
2009 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2010 AS2 (ldd,%B0,%1+1) CR_TAB
2011 AS2 (ldd,%C0,%1+2) CR_TAB
2012 AS2 (ldd,%D0,%1+3));
2015 else if (GET_CODE (base) == PLUS) /* (R + i) */
2017 int disp = INTVAL (XEXP (base, 1));
2019 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2021 if (REGNO (XEXP (base, 0)) != REG_Y)
2022 fatal_insn ("incorrect insn:",insn);
2024 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2025 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2026 AS2 (ldd,%A0,Y+60) CR_TAB
2027 AS2 (ldd,%B0,Y+61) CR_TAB
2028 AS2 (ldd,%C0,Y+62) CR_TAB
2029 AS2 (ldd,%D0,Y+63) CR_TAB
2030 AS2 (sbiw,r28,%o1-60));
2032 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2033 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2034 AS2 (ld,%A0,Y) CR_TAB
2035 AS2 (ldd,%B0,Y+1) CR_TAB
2036 AS2 (ldd,%C0,Y+2) CR_TAB
2037 AS2 (ldd,%D0,Y+3) CR_TAB
2038 AS2 (subi,r28,lo8(%o1)) CR_TAB
2039 AS2 (sbci,r29,hi8(%o1)));
2042 reg_base = true_regnum (XEXP (base, 0));
2043 if (reg_base == REG_X)
2046 if (reg_dest == REG_X)
2049 /* "ld r26,-X" is undefined */
2050 return (AS2 (adiw,r26,%o1+3) CR_TAB
2051 AS2 (ld,r29,X) CR_TAB
2052 AS2 (ld,r28,-X) CR_TAB
2053 AS2 (ld,__tmp_reg__,-X) CR_TAB
2054 AS2 (sbiw,r26,1) CR_TAB
2055 AS2 (ld,r26,X) CR_TAB
2056 AS2 (mov,r27,__tmp_reg__));
2059 if (reg_dest == REG_X - 2)
2060 return (AS2 (adiw,r26,%o1) CR_TAB
2061 AS2 (ld,r24,X+) CR_TAB
2062 AS2 (ld,r25,X+) CR_TAB
2063 AS2 (ld,__tmp_reg__,X+) CR_TAB
2064 AS2 (ld,r27,X) CR_TAB
2065 AS2 (mov,r26,__tmp_reg__));
2067 return (AS2 (adiw,r26,%o1) CR_TAB
2068 AS2 (ld,%A0,X+) CR_TAB
2069 AS2 (ld,%B0,X+) CR_TAB
2070 AS2 (ld,%C0,X+) CR_TAB
2071 AS2 (ld,%D0,X) CR_TAB
2072 AS2 (sbiw,r26,%o1+3));
2074 if (reg_dest == reg_base)
2075 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2076 AS2 (ldd,%C0,%C1) CR_TAB
2077 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2078 AS2 (ldd,%A0,%A1) CR_TAB
2079 AS2 (mov,%B0,__tmp_reg__));
2080 else if (reg_dest == reg_base - 2)
2081 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2082 AS2 (ldd,%B0,%B1) CR_TAB
2083 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2084 AS2 (ldd,%D0,%D1) CR_TAB
2085 AS2 (mov,%C0,__tmp_reg__));
2086 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2087 AS2 (ldd,%B0,%B1) CR_TAB
2088 AS2 (ldd,%C0,%C1) CR_TAB
2091 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2092 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2093 AS2 (ld,%C0,%1) CR_TAB
2094 AS2 (ld,%B0,%1) CR_TAB
2096 else if (GET_CODE (base) == POST_INC) /* (R++) */
2097 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2098 AS2 (ld,%B0,%1) CR_TAB
2099 AS2 (ld,%C0,%1) CR_TAB
2101 else if (CONSTANT_ADDRESS_P (base))
2102 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2103 AS2 (lds,%B0,%B1) CR_TAB
2104 AS2 (lds,%C0,%C1) CR_TAB
2107 fatal_insn ("unknown move insn:",insn);
2112 out_movsi_mr_r (rtx insn, rtx op[], int *l)
2116 rtx base = XEXP (dest, 0);
2117 int reg_base = true_regnum (base);
2118 int reg_src = true_regnum (src);
2124 if (CONSTANT_ADDRESS_P (base))
2125 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2126 AS2 (sts,%B0,%B1) CR_TAB
2127 AS2 (sts,%C0,%C1) CR_TAB
2129 if (reg_base > 0) /* (r) */
2131 if (reg_base == REG_X) /* (R26) */
2133 if (reg_src == REG_X)
2135 /* "st X+,r26" is undefined */
2136 if (reg_unused_after (insn, base))
2137 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2138 AS2 (st,X,r26) CR_TAB
2139 AS2 (adiw,r26,1) CR_TAB
2140 AS2 (st,X+,__tmp_reg__) CR_TAB
2141 AS2 (st,X+,r28) CR_TAB
2144 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2145 AS2 (st,X,r26) CR_TAB
2146 AS2 (adiw,r26,1) CR_TAB
2147 AS2 (st,X+,__tmp_reg__) CR_TAB
2148 AS2 (st,X+,r28) CR_TAB
2149 AS2 (st,X,r29) CR_TAB
2152 else if (reg_base == reg_src + 2)
2154 if (reg_unused_after (insn, base))
2155 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2156 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2157 AS2 (st,%0+,%A1) CR_TAB
2158 AS2 (st,%0+,%B1) CR_TAB
2159 AS2 (st,%0+,__zero_reg__) CR_TAB
2160 AS2 (st,%0,__tmp_reg__) CR_TAB
2161 AS1 (clr,__zero_reg__));
2163 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2164 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2165 AS2 (st,%0+,%A1) CR_TAB
2166 AS2 (st,%0+,%B1) CR_TAB
2167 AS2 (st,%0+,__zero_reg__) CR_TAB
2168 AS2 (st,%0,__tmp_reg__) CR_TAB
2169 AS1 (clr,__zero_reg__) CR_TAB
2172 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2173 AS2 (st,%0+,%B1) CR_TAB
2174 AS2 (st,%0+,%C1) CR_TAB
2175 AS2 (st,%0,%D1) CR_TAB
2179 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2180 AS2 (std,%0+1,%B1) CR_TAB
2181 AS2 (std,%0+2,%C1) CR_TAB
2182 AS2 (std,%0+3,%D1));
2184 else if (GET_CODE (base) == PLUS) /* (R + i) */
2186 int disp = INTVAL (XEXP (base, 1));
2187 reg_base = REGNO (XEXP (base, 0));
2188 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2190 if (reg_base != REG_Y)
2191 fatal_insn ("incorrect insn:",insn);
2193 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2194 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2195 AS2 (std,Y+60,%A1) CR_TAB
2196 AS2 (std,Y+61,%B1) CR_TAB
2197 AS2 (std,Y+62,%C1) CR_TAB
2198 AS2 (std,Y+63,%D1) CR_TAB
2199 AS2 (sbiw,r28,%o0-60));
2201 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2202 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2203 AS2 (st,Y,%A1) CR_TAB
2204 AS2 (std,Y+1,%B1) CR_TAB
2205 AS2 (std,Y+2,%C1) CR_TAB
2206 AS2 (std,Y+3,%D1) CR_TAB
2207 AS2 (subi,r28,lo8(%o0)) CR_TAB
2208 AS2 (sbci,r29,hi8(%o0)));
2210 if (reg_base == REG_X)
2213 if (reg_src == REG_X)
2216 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2217 AS2 (mov,__zero_reg__,r27) CR_TAB
2218 AS2 (adiw,r26,%o0) CR_TAB
2219 AS2 (st,X+,__tmp_reg__) CR_TAB
2220 AS2 (st,X+,__zero_reg__) CR_TAB
2221 AS2 (st,X+,r28) CR_TAB
2222 AS2 (st,X,r29) CR_TAB
2223 AS1 (clr,__zero_reg__) CR_TAB
2224 AS2 (sbiw,r26,%o0+3));
2226 else if (reg_src == REG_X - 2)
2229 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2230 AS2 (mov,__zero_reg__,r27) CR_TAB
2231 AS2 (adiw,r26,%o0) CR_TAB
2232 AS2 (st,X+,r24) CR_TAB
2233 AS2 (st,X+,r25) CR_TAB
2234 AS2 (st,X+,__tmp_reg__) CR_TAB
2235 AS2 (st,X,__zero_reg__) CR_TAB
2236 AS1 (clr,__zero_reg__) CR_TAB
2237 AS2 (sbiw,r26,%o0+3));
2240 return (AS2 (adiw,r26,%o0) CR_TAB
2241 AS2 (st,X+,%A1) CR_TAB
2242 AS2 (st,X+,%B1) CR_TAB
2243 AS2 (st,X+,%C1) CR_TAB
2244 AS2 (st,X,%D1) CR_TAB
2245 AS2 (sbiw,r26,%o0+3));
2247 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2248 AS2 (std,%B0,%B1) CR_TAB
2249 AS2 (std,%C0,%C1) CR_TAB
2252 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2253 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2254 AS2 (st,%0,%C1) CR_TAB
2255 AS2 (st,%0,%B1) CR_TAB
2257 else if (GET_CODE (base) == POST_INC) /* (R++) */
2258 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2259 AS2 (st,%0,%B1) CR_TAB
2260 AS2 (st,%0,%C1) CR_TAB
2262 fatal_insn ("unknown move insn:",insn);
2267 output_movsisf(rtx insn, rtx operands[], int *l)
2270 rtx dest = operands[0];
2271 rtx src = operands[1];
2277 if (register_operand (dest, VOIDmode))
2279 if (register_operand (src, VOIDmode)) /* mov r,r */
2281 if (true_regnum (dest) > true_regnum (src))
2286 return (AS2 (movw,%C0,%C1) CR_TAB
2287 AS2 (movw,%A0,%A1));
2290 return (AS2 (mov,%D0,%D1) CR_TAB
2291 AS2 (mov,%C0,%C1) CR_TAB
2292 AS2 (mov,%B0,%B1) CR_TAB
2300 return (AS2 (movw,%A0,%A1) CR_TAB
2301 AS2 (movw,%C0,%C1));
2304 return (AS2 (mov,%A0,%A1) CR_TAB
2305 AS2 (mov,%B0,%B1) CR_TAB
2306 AS2 (mov,%C0,%C1) CR_TAB
2310 else if (CONSTANT_P (src))
2312 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2315 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2316 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2317 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2318 AS2 (ldi,%D0,hhi8(%1)));
2321 if (GET_CODE (src) == CONST_INT)
2323 const char *const clr_op0 =
2324 AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
2325 AS1 (clr,%B0) CR_TAB
2327 : (AS1 (clr,%A0) CR_TAB
2328 AS1 (clr,%B0) CR_TAB
2329 AS1 (clr,%C0) CR_TAB
2332 if (src == const0_rtx) /* mov r,L */
2334 *l = AVR_ENHANCED ? 3 : 4;
2337 else if (src == const1_rtx)
2340 output_asm_insn (clr_op0, operands);
2341 *l = AVR_ENHANCED ? 4 : 5;
2342 return AS1 (inc,%A0);
2344 else if (src == constm1_rtx)
2346 /* Immediate constants -1 to any register */
2350 return (AS1 (clr,%A0) CR_TAB
2351 AS1 (dec,%A0) CR_TAB
2352 AS2 (mov,%B0,%A0) CR_TAB
2353 AS2 (movw,%C0,%A0));
2356 return (AS1 (clr,%A0) CR_TAB
2357 AS1 (dec,%A0) CR_TAB
2358 AS2 (mov,%B0,%A0) CR_TAB
2359 AS2 (mov,%C0,%A0) CR_TAB
2364 int bit_nr = exact_log2 (INTVAL (src));
2368 *l = AVR_ENHANCED ? 5 : 6;
2371 output_asm_insn (clr_op0, operands);
2372 output_asm_insn ("set", operands);
2375 avr_output_bld (operands, bit_nr);
2382 /* Last resort, better than loading from memory. */
2384 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2385 AS2 (ldi,r31,lo8(%1)) CR_TAB
2386 AS2 (mov,%A0,r31) CR_TAB
2387 AS2 (ldi,r31,hi8(%1)) CR_TAB
2388 AS2 (mov,%B0,r31) CR_TAB
2389 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2390 AS2 (mov,%C0,r31) CR_TAB
2391 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2392 AS2 (mov,%D0,r31) CR_TAB
2393 AS2 (mov,r31,__tmp_reg__));
2395 else if (GET_CODE (src) == MEM)
2396 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2398 else if (GET_CODE (dest) == MEM)
2400 const char *template;
2402 if (src == const0_rtx)
2403 operands[1] = zero_reg_rtx;
2405 template = out_movsi_mr_r (insn, operands, real_l);
2408 output_asm_insn (template, operands);
2413 fatal_insn ("invalid insn:", insn);
2418 out_movqi_mr_r (rtx insn, rtx op[], int *l)
2422 rtx x = XEXP (dest, 0);
2428 if (CONSTANT_ADDRESS_P (x))
2430 if (avr_io_address_p (x, 1))
2433 return AS2 (out,%0-0x20,%1);
2436 return AS2 (sts,%0,%1);
2438 /* memory access by reg+disp */
2439 else if (GET_CODE (x) == PLUS
2440 && REG_P (XEXP (x,0))
2441 && GET_CODE (XEXP (x,1)) == CONST_INT)
2443 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
2445 int disp = INTVAL (XEXP (x,1));
2446 if (REGNO (XEXP (x,0)) != REG_Y)
2447 fatal_insn ("incorrect insn:",insn);
2449 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2450 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2451 AS2 (std,Y+63,%1) CR_TAB
2452 AS2 (sbiw,r28,%o0-63));
2454 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2455 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2456 AS2 (st,Y,%1) CR_TAB
2457 AS2 (subi,r28,lo8(%o0)) CR_TAB
2458 AS2 (sbci,r29,hi8(%o0)));
2460 else if (REGNO (XEXP (x,0)) == REG_X)
2462 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
2464 if (reg_unused_after (insn, XEXP (x,0)))
2465 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2466 AS2 (adiw,r26,%o0) CR_TAB
2467 AS2 (st,X,__tmp_reg__));
2469 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2470 AS2 (adiw,r26,%o0) CR_TAB
2471 AS2 (st,X,__tmp_reg__) CR_TAB
2472 AS2 (sbiw,r26,%o0));
2476 if (reg_unused_after (insn, XEXP (x,0)))
2477 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2480 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2481 AS2 (st,X,%1) CR_TAB
2482 AS2 (sbiw,r26,%o0));
2486 return AS2 (std,%0,%1);
2489 return AS2 (st,%0,%1);
2493 out_movhi_mr_r (rtx insn, rtx op[], int *l)
2497 rtx base = XEXP (dest, 0);
2498 int reg_base = true_regnum (base);
2499 int reg_src = true_regnum (src);
2503 if (CONSTANT_ADDRESS_P (base))
2505 if (avr_io_address_p (base, 2))
2508 return (AS2 (out,%B0-0x20,%B1) CR_TAB
2509 AS2 (out,%A0-0x20,%A1));
2511 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2516 if (reg_base == REG_X)
2518 if (reg_src == REG_X)
2520 /* "st X+,r26" is undefined */
2521 if (reg_unused_after (insn, src))
2522 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2523 AS2 (st,X,r26) CR_TAB
2524 AS2 (adiw,r26,1) CR_TAB
2525 AS2 (st,X,__tmp_reg__));
2527 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2528 AS2 (st,X,r26) CR_TAB
2529 AS2 (adiw,r26,1) CR_TAB
2530 AS2 (st,X,__tmp_reg__) CR_TAB
2535 if (reg_unused_after (insn, base))
2536 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2539 return *l=3, (AS2 (st ,X+,%A1) CR_TAB
2540 AS2 (st ,X,%B1) CR_TAB
2545 return *l=2, (AS2 (st ,%0,%A1) CR_TAB
2546 AS2 (std,%0+1,%B1));
2548 else if (GET_CODE (base) == PLUS)
2550 int disp = INTVAL (XEXP (base, 1));
2551 reg_base = REGNO (XEXP (base, 0));
2552 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2554 if (reg_base != REG_Y)
2555 fatal_insn ("incorrect insn:",insn);
2557 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2558 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
2559 AS2 (std,Y+62,%A1) CR_TAB
2560 AS2 (std,Y+63,%B1) CR_TAB
2561 AS2 (sbiw,r28,%o0-62));
2563 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2564 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2565 AS2 (st,Y,%A1) CR_TAB
2566 AS2 (std,Y+1,%B1) CR_TAB
2567 AS2 (subi,r28,lo8(%o0)) CR_TAB
2568 AS2 (sbci,r29,hi8(%o0)));
2570 if (reg_base == REG_X)
2573 if (reg_src == REG_X)
2576 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2577 AS2 (mov,__zero_reg__,r27) CR_TAB
2578 AS2 (adiw,r26,%o0) CR_TAB
2579 AS2 (st,X+,__tmp_reg__) CR_TAB
2580 AS2 (st,X,__zero_reg__) CR_TAB
2581 AS1 (clr,__zero_reg__) CR_TAB
2582 AS2 (sbiw,r26,%o0+1));
2585 return (AS2 (adiw,r26,%o0) CR_TAB
2586 AS2 (st,X+,%A1) CR_TAB
2587 AS2 (st,X,%B1) CR_TAB
2588 AS2 (sbiw,r26,%o0+1));
2590 return *l=2, (AS2 (std,%A0,%A1) CR_TAB
2593 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2594 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2596 else if (GET_CODE (base) == POST_INC) /* (R++) */
2597 return *l=2, (AS2 (st,%0,%A1) CR_TAB
2599 fatal_insn ("unknown move insn:",insn);
2603 /* Return 1 if frame pointer for current function required. */
2606 frame_pointer_required_p (void)
2608 return (current_function_calls_alloca
2609 || current_function_args_info.nregs == 0
2610 || get_frame_size () > 0);
2613 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2616 compare_condition (rtx insn)
2618 rtx next = next_real_insn (insn);
2619 RTX_CODE cond = UNKNOWN;
2620 if (next && GET_CODE (next) == JUMP_INSN)
2622 rtx pat = PATTERN (next);
2623 rtx src = SET_SRC (pat);
2624 rtx t = XEXP (src, 0);
2625 cond = GET_CODE (t);
2630 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2633 compare_sign_p (rtx insn)
2635 RTX_CODE cond = compare_condition (insn);
2636 return (cond == GE || cond == LT);
2639 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2640 that needs to be swapped (GT, GTU, LE, LEU). */
2643 compare_diff_p (rtx insn)
2645 RTX_CODE cond = compare_condition (insn);
2646 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2649 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2652 compare_eq_p (rtx insn)
2654 RTX_CODE cond = compare_condition (insn);
2655 return (cond == EQ || cond == NE);
2659 /* Output test instruction for HImode. */
2662 out_tsthi (rtx insn, int *l)
2664 if (compare_sign_p (insn))
2667 return AS1 (tst,%B0);
2669 if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2670 && compare_eq_p (insn))
2672 /* Faster than sbiw if we can clobber the operand. */
2674 return AS2 (or,%A0,%B0);
2676 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2679 return AS2 (sbiw,%0,0);
2682 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2683 AS2 (cpc,%B0,__zero_reg__));
2687 /* Output test instruction for SImode. */
2690 out_tstsi (rtx insn, int *l)
2692 if (compare_sign_p (insn))
2695 return AS1 (tst,%D0);
2697 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2700 return (AS2 (sbiw,%A0,0) CR_TAB
2701 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2702 AS2 (cpc,%D0,__zero_reg__));
2705 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2706 AS2 (cpc,%B0,__zero_reg__) CR_TAB
2707 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2708 AS2 (cpc,%D0,__zero_reg__));
2712 /* Generate asm equivalent for various shifts.
2713 Shift count is a CONST_INT, MEM or REG.
2714 This only handles cases that are not already
2715 carefully hand-optimized in ?sh??i3_out. */
2718 out_shift_with_cnt (const char *template, rtx insn, rtx operands[],
2719 int *len, int t_len)
2723 int second_label = 1;
2724 int saved_in_tmp = 0;
2725 int use_zero_reg = 0;
2727 op[0] = operands[0];
2728 op[1] = operands[1];
2729 op[2] = operands[2];
2730 op[3] = operands[3];
2736 if (GET_CODE (operands[2]) == CONST_INT)
2738 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2739 int count = INTVAL (operands[2]);
2740 int max_len = 10; /* If larger than this, always use a loop. */
2742 if (count < 8 && !scratch)
2746 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2748 if (t_len * count <= max_len)
2750 /* Output shifts inline with no loop - faster. */
2752 *len = t_len * count;
2756 output_asm_insn (template, op);
2765 strcat (str, AS2 (ldi,%3,%2));
2767 else if (use_zero_reg)
2769 /* Hack to save one word: use __zero_reg__ as loop counter.
2770 Set one bit, then shift in a loop until it is 0 again. */
2772 op[3] = zero_reg_rtx;
2776 strcat (str, ("set" CR_TAB
2777 AS2 (bld,%3,%2-1)));
2781 /* No scratch register available, use one from LD_REGS (saved in
2782 __tmp_reg__) that doesn't overlap with registers to shift. */
2784 op[3] = gen_rtx (REG, QImode,
2785 ((true_regnum (operands[0]) - 1) & 15) + 16);
2786 op[4] = tmp_reg_rtx;
2790 *len = 3; /* Includes "mov %3,%4" after the loop. */
2792 strcat (str, (AS2 (mov,%4,%3) CR_TAB
2798 else if (GET_CODE (operands[2]) == MEM)
2802 op[3] = op_mov[0] = tmp_reg_rtx;
2806 out_movqi_r_mr (insn, op_mov, len);
2808 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
2810 else if (register_operand (operands[2], QImode))
2812 if (reg_unused_after (insn, operands[2]))
2816 op[3] = tmp_reg_rtx;
2818 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
2822 fatal_insn ("bad shift insn:", insn);
2829 strcat (str, AS1 (rjmp,2f));
2833 *len += t_len + 2; /* template + dec + brXX */
2836 strcat (str, "\n1:\t");
2837 strcat (str, template);
2838 strcat (str, second_label ? "\n2:\t" : "\n\t");
2839 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
2840 strcat (str, CR_TAB);
2841 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
2843 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
2844 output_asm_insn (str, op);
2849 /* 8bit shift left ((char)x << i) */
2852 ashlqi3_out (rtx insn, rtx operands[], int *len)
2854 if (GET_CODE (operands[2]) == CONST_INT)
2861 switch (INTVAL (operands[2]))
2865 return AS1 (clr,%0);
2869 return AS1 (lsl,%0);
2873 return (AS1 (lsl,%0) CR_TAB
2878 return (AS1 (lsl,%0) CR_TAB
2883 if (test_hard_reg_class (LD_REGS, operands[0]))
2886 return (AS1 (swap,%0) CR_TAB
2887 AS2 (andi,%0,0xf0));
2890 return (AS1 (lsl,%0) CR_TAB
2896 if (test_hard_reg_class (LD_REGS, operands[0]))
2899 return (AS1 (swap,%0) CR_TAB
2901 AS2 (andi,%0,0xe0));
2904 return (AS1 (lsl,%0) CR_TAB
2911 if (test_hard_reg_class (LD_REGS, operands[0]))
2914 return (AS1 (swap,%0) CR_TAB
2917 AS2 (andi,%0,0xc0));
2920 return (AS1 (lsl,%0) CR_TAB
2929 return (AS1 (ror,%0) CR_TAB
2934 else if (CONSTANT_P (operands[2]))
2935 fatal_insn ("internal compiler error. Incorrect shift:", insn);
2937 out_shift_with_cnt (AS1 (lsl,%0),
2938 insn, operands, len, 1);
2943 /* 16bit shift left ((short)x << i) */
2946 ashlhi3_out (rtx insn, rtx operands[], int *len)
2948 if (GET_CODE (operands[2]) == CONST_INT)
2950 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2951 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
2958 switch (INTVAL (operands[2]))
2961 if (optimize_size && scratch)
2966 return (AS1 (swap,%A0) CR_TAB
2967 AS1 (swap,%B0) CR_TAB
2968 AS2 (andi,%B0,0xf0) CR_TAB
2969 AS2 (eor,%B0,%A0) CR_TAB
2970 AS2 (andi,%A0,0xf0) CR_TAB
2976 return (AS1 (swap,%A0) CR_TAB
2977 AS1 (swap,%B0) CR_TAB
2978 AS2 (ldi,%3,0xf0) CR_TAB
2979 AS2 (and,%B0,%3) CR_TAB
2980 AS2 (eor,%B0,%A0) CR_TAB
2981 AS2 (and,%A0,%3) CR_TAB
2984 break; /* optimize_size ? 6 : 8 */
2988 break; /* scratch ? 5 : 6 */
2992 return (AS1 (lsl,%A0) CR_TAB
2993 AS1 (rol,%B0) CR_TAB
2994 AS1 (swap,%A0) CR_TAB
2995 AS1 (swap,%B0) CR_TAB
2996 AS2 (andi,%B0,0xf0) CR_TAB
2997 AS2 (eor,%B0,%A0) CR_TAB
2998 AS2 (andi,%A0,0xf0) CR_TAB
3004 return (AS1 (lsl,%A0) CR_TAB
3005 AS1 (rol,%B0) CR_TAB
3006 AS1 (swap,%A0) CR_TAB
3007 AS1 (swap,%B0) CR_TAB
3008 AS2 (ldi,%3,0xf0) CR_TAB
3009 AS2 (and,%B0,%3) CR_TAB
3010 AS2 (eor,%B0,%A0) CR_TAB
3011 AS2 (and,%A0,%3) CR_TAB
3018 break; /* scratch ? 5 : 6 */
3020 return (AS1 (clr,__tmp_reg__) CR_TAB
3021 AS1 (lsr,%B0) CR_TAB
3022 AS1 (ror,%A0) CR_TAB
3023 AS1 (ror,__tmp_reg__) CR_TAB
3024 AS1 (lsr,%B0) CR_TAB
3025 AS1 (ror,%A0) CR_TAB
3026 AS1 (ror,__tmp_reg__) CR_TAB
3027 AS2 (mov,%B0,%A0) CR_TAB
3028 AS2 (mov,%A0,__tmp_reg__));
3032 return (AS1 (lsr,%B0) CR_TAB
3033 AS2 (mov,%B0,%A0) CR_TAB
3034 AS1 (clr,%A0) CR_TAB
3035 AS1 (ror,%B0) CR_TAB
3039 if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
3040 return *len = 1, AS1 (clr,%A0);
3042 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3047 return (AS2 (mov,%B0,%A0) CR_TAB
3048 AS1 (clr,%A0) CR_TAB
3053 return (AS2 (mov,%B0,%A0) CR_TAB
3054 AS1 (clr,%A0) CR_TAB
3055 AS1 (lsl,%B0) CR_TAB
3060 return (AS2 (mov,%B0,%A0) CR_TAB
3061 AS1 (clr,%A0) CR_TAB
3062 AS1 (lsl,%B0) CR_TAB
3063 AS1 (lsl,%B0) CR_TAB
3070 return (AS2 (mov,%B0,%A0) CR_TAB
3071 AS1 (clr,%A0) CR_TAB
3072 AS1 (swap,%B0) CR_TAB
3073 AS2 (andi,%B0,0xf0));
3078 return (AS2 (mov,%B0,%A0) CR_TAB
3079 AS1 (clr,%A0) CR_TAB
3080 AS1 (swap,%B0) CR_TAB
3081 AS2 (ldi,%3,0xf0) CR_TAB
3085 return (AS2 (mov,%B0,%A0) CR_TAB
3086 AS1 (clr,%A0) CR_TAB
3087 AS1 (lsl,%B0) CR_TAB
3088 AS1 (lsl,%B0) CR_TAB
3089 AS1 (lsl,%B0) CR_TAB
3096 return (AS2 (mov,%B0,%A0) CR_TAB
3097 AS1 (clr,%A0) CR_TAB
3098 AS1 (swap,%B0) CR_TAB
3099 AS1 (lsl,%B0) CR_TAB
3100 AS2 (andi,%B0,0xe0));
3102 if (AVR_ENHANCED && scratch)
3105 return (AS2 (ldi,%3,0x20) CR_TAB
3106 AS2 (mul,%A0,%3) CR_TAB
3107 AS2 (mov,%B0,r0) CR_TAB
3108 AS1 (clr,%A0) CR_TAB
3109 AS1 (clr,__zero_reg__));
3111 if (optimize_size && scratch)
3116 return (AS2 (mov,%B0,%A0) CR_TAB
3117 AS1 (clr,%A0) CR_TAB
3118 AS1 (swap,%B0) CR_TAB
3119 AS1 (lsl,%B0) CR_TAB
3120 AS2 (ldi,%3,0xe0) CR_TAB
3126 return ("set" CR_TAB
3127 AS2 (bld,r1,5) CR_TAB
3128 AS2 (mul,%A0,r1) CR_TAB
3129 AS2 (mov,%B0,r0) CR_TAB
3130 AS1 (clr,%A0) CR_TAB
3131 AS1 (clr,__zero_reg__));
3134 return (AS2 (mov,%B0,%A0) CR_TAB
3135 AS1 (clr,%A0) CR_TAB
3136 AS1 (lsl,%B0) CR_TAB
3137 AS1 (lsl,%B0) CR_TAB
3138 AS1 (lsl,%B0) CR_TAB
3139 AS1 (lsl,%B0) CR_TAB
3143 if (AVR_ENHANCED && ldi_ok)
3146 return (AS2 (ldi,%B0,0x40) CR_TAB
3147 AS2 (mul,%A0,%B0) CR_TAB
3148 AS2 (mov,%B0,r0) CR_TAB
3149 AS1 (clr,%A0) CR_TAB
3150 AS1 (clr,__zero_reg__));
3152 if (AVR_ENHANCED && scratch)
3155 return (AS2 (ldi,%3,0x40) CR_TAB
3156 AS2 (mul,%A0,%3) CR_TAB
3157 AS2 (mov,%B0,r0) CR_TAB
3158 AS1 (clr,%A0) CR_TAB
3159 AS1 (clr,__zero_reg__));
3161 if (optimize_size && ldi_ok)
3164 return (AS2 (mov,%B0,%A0) CR_TAB
3165 AS2 (ldi,%A0,6) "\n1:\t"
3166 AS1 (lsl,%B0) CR_TAB
3167 AS1 (dec,%A0) CR_TAB
3170 if (optimize_size && scratch)
3173 return (AS1 (clr,%B0) CR_TAB
3174 AS1 (lsr,%A0) CR_TAB
3175 AS1 (ror,%B0) CR_TAB
3176 AS1 (lsr,%A0) CR_TAB
3177 AS1 (ror,%B0) CR_TAB
3182 return (AS1 (clr,%B0) CR_TAB
3183 AS1 (lsr,%A0) CR_TAB
3184 AS1 (ror,%B0) CR_TAB
3189 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3191 insn, operands, len, 2);
3196 /* 32bit shift left ((long)x << i) */
3199 ashlsi3_out (rtx insn, rtx operands[], int *len)
3201 if (GET_CODE (operands[2]) == CONST_INT)
3209 switch (INTVAL (operands[2]))
3213 int reg0 = true_regnum (operands[0]);
3214 int reg1 = true_regnum (operands[1]);
3217 return (AS2 (mov,%D0,%C1) CR_TAB
3218 AS2 (mov,%C0,%B1) CR_TAB
3219 AS2 (mov,%B0,%A1) CR_TAB
3221 else if (reg0 + 1 == reg1)
3224 return AS1 (clr,%A0);
3227 return (AS1 (clr,%A0) CR_TAB
3228 AS2 (mov,%B0,%A1) CR_TAB
3229 AS2 (mov,%C0,%B1) CR_TAB
3235 int reg0 = true_regnum (operands[0]);
3236 int reg1 = true_regnum (operands[1]);
3238 if (AVR_ENHANCED && (reg0 + 2 != reg1))
3241 return (AS2 (movw,%C0,%A1) CR_TAB
3242 AS1 (clr,%B0) CR_TAB
3245 if (reg0 + 1 >= reg1)
3246 return (AS2 (mov,%D0,%B1) CR_TAB
3247 AS2 (mov,%C0,%A1) CR_TAB
3248 AS1 (clr,%B0) CR_TAB
3250 if (reg0 + 2 == reg1)
3253 return (AS1 (clr,%B0) CR_TAB
3257 return (AS2 (mov,%C0,%A1) CR_TAB
3258 AS2 (mov,%D0,%B1) CR_TAB
3259 AS1 (clr,%B0) CR_TAB
3265 if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
3266 return (AS2 (mov,%D0,%A1) CR_TAB
3267 AS1 (clr,%C0) CR_TAB
3268 AS1 (clr,%B0) CR_TAB
3273 return (AS1 (clr,%C0) CR_TAB
3274 AS1 (clr,%B0) CR_TAB
3280 return (AS1 (clr,%D0) CR_TAB
3281 AS1 (lsr,%A0) CR_TAB
3282 AS1 (ror,%D0) CR_TAB
3283 AS1 (clr,%C0) CR_TAB
3284 AS1 (clr,%B0) CR_TAB
3289 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3290 AS1 (rol,%B0) CR_TAB
3291 AS1 (rol,%C0) CR_TAB
3293 insn, operands, len, 4);
3297 /* 8bit arithmetic shift right ((signed char)x >> i) */
3300 ashrqi3_out (rtx insn, rtx operands[], int *len)
3302 if (GET_CODE (operands[2]) == CONST_INT)
3309 switch (INTVAL (operands[2]))
3313 return AS1 (asr,%0);
3317 return (AS1 (asr,%0) CR_TAB
3322 return (AS1 (asr,%0) CR_TAB
3328 return (AS1 (asr,%0) CR_TAB
3335 return (AS1 (asr,%0) CR_TAB
3343 return (AS2 (bst,%0,6) CR_TAB
3345 AS2 (sbc,%0,%0) CR_TAB
3351 return (AS1 (lsl,%0) CR_TAB
3355 else if (CONSTANT_P (operands[2]))
3356 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3358 out_shift_with_cnt (AS1 (asr,%0),
3359 insn, operands, len, 1);
3364 /* 16bit arithmetic shift right ((signed short)x >> i) */
3367 ashrhi3_out (rtx insn, rtx operands[], int *len)
3369 if (GET_CODE (operands[2]) == CONST_INT)
3371 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3372 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3379 switch (INTVAL (operands[2]))
3383 /* XXX try to optimize this too? */
3388 break; /* scratch ? 5 : 6 */
3390 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3391 AS2 (mov,%A0,%B0) CR_TAB
3392 AS1 (lsl,__tmp_reg__) CR_TAB
3393 AS1 (rol,%A0) CR_TAB
3394 AS2 (sbc,%B0,%B0) CR_TAB
3395 AS1 (lsl,__tmp_reg__) CR_TAB
3396 AS1 (rol,%A0) CR_TAB
3401 return (AS1 (lsl,%A0) CR_TAB
3402 AS2 (mov,%A0,%B0) CR_TAB
3403 AS1 (rol,%A0) CR_TAB
3408 int reg0 = true_regnum (operands[0]);
3409 int reg1 = true_regnum (operands[1]);
3412 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3413 AS1 (lsl,%B0) CR_TAB
3415 else if (reg0 == reg1 + 1)
3416 return *len = 3, (AS1 (clr,%B0) CR_TAB
3417 AS2 (sbrc,%A0,7) CR_TAB
3420 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3421 AS1 (clr,%B0) CR_TAB
3422 AS2 (sbrc,%A0,7) CR_TAB
3428 return (AS2 (mov,%A0,%B0) CR_TAB
3429 AS1 (lsl,%B0) CR_TAB
3430 AS2 (sbc,%B0,%B0) CR_TAB
3435 return (AS2 (mov,%A0,%B0) CR_TAB
3436 AS1 (lsl,%B0) CR_TAB
3437 AS2 (sbc,%B0,%B0) CR_TAB
3438 AS1 (asr,%A0) CR_TAB
3442 if (AVR_ENHANCED && ldi_ok)
3445 return (AS2 (ldi,%A0,0x20) CR_TAB
3446 AS2 (muls,%B0,%A0) CR_TAB
3447 AS2 (mov,%A0,r1) CR_TAB
3448 AS2 (sbc,%B0,%B0) CR_TAB
3449 AS1 (clr,__zero_reg__));
3451 if (optimize_size && scratch)
3454 return (AS2 (mov,%A0,%B0) CR_TAB
3455 AS1 (lsl,%B0) CR_TAB
3456 AS2 (sbc,%B0,%B0) CR_TAB
3457 AS1 (asr,%A0) CR_TAB
3458 AS1 (asr,%A0) CR_TAB
3462 if (AVR_ENHANCED && ldi_ok)
3465 return (AS2 (ldi,%A0,0x10) CR_TAB
3466 AS2 (muls,%B0,%A0) CR_TAB
3467 AS2 (mov,%A0,r1) CR_TAB
3468 AS2 (sbc,%B0,%B0) CR_TAB
3469 AS1 (clr,__zero_reg__));
3471 if (optimize_size && scratch)
3474 return (AS2 (mov,%A0,%B0) CR_TAB
3475 AS1 (lsl,%B0) CR_TAB
3476 AS2 (sbc,%B0,%B0) CR_TAB
3477 AS1 (asr,%A0) CR_TAB
3478 AS1 (asr,%A0) CR_TAB
3479 AS1 (asr,%A0) CR_TAB
3483 if (AVR_ENHANCED && ldi_ok)
3486 return (AS2 (ldi,%A0,0x08) CR_TAB
3487 AS2 (muls,%B0,%A0) CR_TAB
3488 AS2 (mov,%A0,r1) CR_TAB
3489 AS2 (sbc,%B0,%B0) CR_TAB
3490 AS1 (clr,__zero_reg__));
3493 break; /* scratch ? 5 : 7 */
3495 return (AS2 (mov,%A0,%B0) CR_TAB
3496 AS1 (lsl,%B0) CR_TAB
3497 AS2 (sbc,%B0,%B0) CR_TAB
3498 AS1 (asr,%A0) CR_TAB
3499 AS1 (asr,%A0) CR_TAB
3500 AS1 (asr,%A0) CR_TAB
3501 AS1 (asr,%A0) CR_TAB
3506 return (AS1 (lsl,%B0) CR_TAB
3507 AS2 (sbc,%A0,%A0) CR_TAB
3508 AS1 (lsl,%B0) CR_TAB
3509 AS2 (mov,%B0,%A0) CR_TAB
3513 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3514 AS2 (sbc,%A0,%A0) CR_TAB
3519 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3521 insn, operands, len, 2);
3526 /* 32bit arithmetic shift right ((signed long)x >> i) */
3529 ashrsi3_out (rtx insn, rtx operands[], int *len)
3531 if (GET_CODE (operands[2]) == CONST_INT)
3539 switch (INTVAL (operands[2]))
3543 int reg0 = true_regnum (operands[0]);
3544 int reg1 = true_regnum (operands[1]);
3547 return (AS2 (mov,%A0,%B1) CR_TAB
3548 AS2 (mov,%B0,%C1) CR_TAB
3549 AS2 (mov,%C0,%D1) CR_TAB
3550 AS1 (clr,%D0) CR_TAB
3551 AS2 (sbrc,%C0,7) CR_TAB
3553 else if (reg0 == reg1 + 1)
3556 return (AS1 (clr,%D0) CR_TAB
3557 AS2 (sbrc,%C0,7) CR_TAB
3561 return (AS1 (clr,%D0) CR_TAB
3562 AS2 (sbrc,%D1,7) CR_TAB
3563 AS1 (dec,%D0) CR_TAB
3564 AS2 (mov,%C0,%D1) CR_TAB
3565 AS2 (mov,%B0,%C1) CR_TAB
3571 int reg0 = true_regnum (operands[0]);
3572 int reg1 = true_regnum (operands[1]);
3574 if (AVR_ENHANCED && (reg0 != reg1 + 2))
3577 return (AS2 (movw,%A0,%C1) CR_TAB
3578 AS1 (clr,%D0) CR_TAB
3579 AS2 (sbrc,%B0,7) CR_TAB
3580 AS1 (com,%D0) CR_TAB
3583 if (reg0 <= reg1 + 1)
3584 return (AS2 (mov,%A0,%C1) CR_TAB
3585 AS2 (mov,%B0,%D1) CR_TAB
3586 AS1 (clr,%D0) CR_TAB
3587 AS2 (sbrc,%B0,7) CR_TAB
3588 AS1 (com,%D0) CR_TAB
3590 else if (reg0 == reg1 + 2)
3591 return *len = 4, (AS1 (clr,%D0) CR_TAB
3592 AS2 (sbrc,%B0,7) CR_TAB
3593 AS1 (com,%D0) CR_TAB
3596 return (AS2 (mov,%B0,%D1) CR_TAB
3597 AS2 (mov,%A0,%C1) CR_TAB
3598 AS1 (clr,%D0) CR_TAB
3599 AS2 (sbrc,%B0,7) CR_TAB
3600 AS1 (com,%D0) CR_TAB
3605 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
3606 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3607 AS1 (clr,%D0) CR_TAB
3608 AS2 (sbrc,%A0,7) CR_TAB
3609 AS1 (com,%D0) CR_TAB
3610 AS2 (mov,%B0,%D0) CR_TAB
3613 return *len = 5, (AS1 (clr,%D0) CR_TAB
3614 AS2 (sbrc,%A0,7) CR_TAB
3615 AS1 (com,%D0) CR_TAB
3616 AS2 (mov,%B0,%D0) CR_TAB
3621 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3622 AS2 (sbc,%A0,%A0) CR_TAB
3623 AS2 (mov,%B0,%A0) CR_TAB
3624 AS2 (movw,%C0,%A0));
3626 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3627 AS2 (sbc,%A0,%A0) CR_TAB
3628 AS2 (mov,%B0,%A0) CR_TAB
3629 AS2 (mov,%C0,%A0) CR_TAB
3634 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3635 AS1 (ror,%C0) CR_TAB
3636 AS1 (ror,%B0) CR_TAB
3638 insn, operands, len, 4);
3642 /* 8bit logic shift right ((unsigned char)x >> i) */
3645 lshrqi3_out (rtx insn, rtx operands[], int *len)
3647 if (GET_CODE (operands[2]) == CONST_INT)
3654 switch (INTVAL (operands[2]))
3658 return AS1 (clr,%0);
3662 return AS1 (lsr,%0);
3666 return (AS1 (lsr,%0) CR_TAB
3670 return (AS1 (lsr,%0) CR_TAB
3675 if (test_hard_reg_class (LD_REGS, operands[0]))
3678 return (AS1 (swap,%0) CR_TAB
3679 AS2 (andi,%0,0x0f));
3682 return (AS1 (lsr,%0) CR_TAB
3688 if (test_hard_reg_class (LD_REGS, operands[0]))
3691 return (AS1 (swap,%0) CR_TAB
3696 return (AS1 (lsr,%0) CR_TAB
3703 if (test_hard_reg_class (LD_REGS, operands[0]))
3706 return (AS1 (swap,%0) CR_TAB
3712 return (AS1 (lsr,%0) CR_TAB
3721 return (AS1 (rol,%0) CR_TAB
3726 else if (CONSTANT_P (operands[2]))
3727 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3729 out_shift_with_cnt (AS1 (lsr,%0),
3730 insn, operands, len, 1);
3734 /* 16bit logic shift right ((unsigned short)x >> i) */
3737 lshrhi3_out (rtx insn, rtx operands[], int *len)
3739 if (GET_CODE (operands[2]) == CONST_INT)
3741 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3742 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3749 switch (INTVAL (operands[2]))
3752 if (optimize_size && scratch)
3757 return (AS1 (swap,%B0) CR_TAB
3758 AS1 (swap,%A0) CR_TAB
3759 AS2 (andi,%A0,0x0f) CR_TAB
3760 AS2 (eor,%A0,%B0) CR_TAB
3761 AS2 (andi,%B0,0x0f) CR_TAB
3767 return (AS1 (swap,%B0) CR_TAB
3768 AS1 (swap,%A0) CR_TAB
3769 AS2 (ldi,%3,0x0f) CR_TAB
3770 AS2 (and,%A0,%3) CR_TAB
3771 AS2 (eor,%A0,%B0) CR_TAB
3772 AS2 (and,%B0,%3) CR_TAB
3775 break; /* optimize_size ? 6 : 8 */
3779 break; /* scratch ? 5 : 6 */
3783 return (AS1 (lsr,%B0) CR_TAB
3784 AS1 (ror,%A0) CR_TAB
3785 AS1 (swap,%B0) CR_TAB
3786 AS1 (swap,%A0) CR_TAB
3787 AS2 (andi,%A0,0x0f) CR_TAB
3788 AS2 (eor,%A0,%B0) CR_TAB
3789 AS2 (andi,%B0,0x0f) CR_TAB
3795 return (AS1 (lsr,%B0) CR_TAB
3796 AS1 (ror,%A0) CR_TAB
3797 AS1 (swap,%B0) CR_TAB
3798 AS1 (swap,%A0) CR_TAB
3799 AS2 (ldi,%3,0x0f) CR_TAB
3800 AS2 (and,%A0,%3) CR_TAB
3801 AS2 (eor,%A0,%B0) CR_TAB
3802 AS2 (and,%B0,%3) CR_TAB
3809 break; /* scratch ? 5 : 6 */
3811 return (AS1 (clr,__tmp_reg__) CR_TAB
3812 AS1 (lsl,%A0) CR_TAB
3813 AS1 (rol,%B0) CR_TAB
3814 AS1 (rol,__tmp_reg__) CR_TAB
3815 AS1 (lsl,%A0) CR_TAB
3816 AS1 (rol,%B0) CR_TAB
3817 AS1 (rol,__tmp_reg__) CR_TAB
3818 AS2 (mov,%A0,%B0) CR_TAB
3819 AS2 (mov,%B0,__tmp_reg__));
3823 return (AS1 (lsl,%A0) CR_TAB
3824 AS2 (mov,%A0,%B0) CR_TAB
3825 AS1 (rol,%A0) CR_TAB
3826 AS2 (sbc,%B0,%B0) CR_TAB
3830 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
3831 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
3834 return *len = 1, AS1 (clr,%B0);
3838 return (AS2 (mov,%A0,%B0) CR_TAB
3839 AS1 (clr,%B0) CR_TAB
3844 return (AS2 (mov,%A0,%B0) CR_TAB
3845 AS1 (clr,%B0) CR_TAB
3846 AS1 (lsr,%A0) CR_TAB
3851 return (AS2 (mov,%A0,%B0) CR_TAB
3852 AS1 (clr,%B0) CR_TAB
3853 AS1 (lsr,%A0) CR_TAB
3854 AS1 (lsr,%A0) CR_TAB
3861 return (AS2 (mov,%A0,%B0) CR_TAB
3862 AS1 (clr,%B0) CR_TAB
3863 AS1 (swap,%A0) CR_TAB
3864 AS2 (andi,%A0,0x0f));
3869 return (AS2 (mov,%A0,%B0) CR_TAB
3870 AS1 (clr,%B0) CR_TAB
3871 AS1 (swap,%A0) CR_TAB
3872 AS2 (ldi,%3,0x0f) CR_TAB
3876 return (AS2 (mov,%A0,%B0) CR_TAB
3877 AS1 (clr,%B0) CR_TAB
3878 AS1 (lsr,%A0) CR_TAB
3879 AS1 (lsr,%A0) CR_TAB
3880 AS1 (lsr,%A0) CR_TAB
3887 return (AS2 (mov,%A0,%B0) CR_TAB
3888 AS1 (clr,%B0) CR_TAB
3889 AS1 (swap,%A0) CR_TAB
3890 AS1 (lsr,%A0) CR_TAB
3891 AS2 (andi,%A0,0x07));
3893 if (AVR_ENHANCED && scratch)
3896 return (AS2 (ldi,%3,0x08) CR_TAB
3897 AS2 (mul,%B0,%3) CR_TAB
3898 AS2 (mov,%A0,r1) CR_TAB
3899 AS1 (clr,%B0) CR_TAB
3900 AS1 (clr,__zero_reg__));
3902 if (optimize_size && scratch)
3907 return (AS2 (mov,%A0,%B0) CR_TAB
3908 AS1 (clr,%B0) CR_TAB
3909 AS1 (swap,%A0) CR_TAB
3910 AS1 (lsr,%A0) CR_TAB
3911 AS2 (ldi,%3,0x07) CR_TAB
3917 return ("set" CR_TAB
3918 AS2 (bld,r1,3) CR_TAB
3919 AS2 (mul,%B0,r1) CR_TAB
3920 AS2 (mov,%A0,r1) CR_TAB
3921 AS1 (clr,%B0) CR_TAB
3922 AS1 (clr,__zero_reg__));
3925 return (AS2 (mov,%A0,%B0) CR_TAB
3926 AS1 (clr,%B0) CR_TAB
3927 AS1 (lsr,%A0) CR_TAB
3928 AS1 (lsr,%A0) CR_TAB
3929 AS1 (lsr,%A0) CR_TAB
3930 AS1 (lsr,%A0) CR_TAB
3934 if (AVR_ENHANCED && ldi_ok)
3937 return (AS2 (ldi,%A0,0x04) CR_TAB
3938 AS2 (mul,%B0,%A0) CR_TAB
3939 AS2 (mov,%A0,r1) CR_TAB
3940 AS1 (clr,%B0) CR_TAB
3941 AS1 (clr,__zero_reg__));
3943 if (AVR_ENHANCED && scratch)
3946 return (AS2 (ldi,%3,0x04) CR_TAB
3947 AS2 (mul,%B0,%3) CR_TAB
3948 AS2 (mov,%A0,r1) CR_TAB
3949 AS1 (clr,%B0) CR_TAB
3950 AS1 (clr,__zero_reg__));
3952 if (optimize_size && ldi_ok)
3955 return (AS2 (mov,%A0,%B0) CR_TAB
3956 AS2 (ldi,%B0,6) "\n1:\t"
3957 AS1 (lsr,%A0) CR_TAB
3958 AS1 (dec,%B0) CR_TAB
3961 if (optimize_size && scratch)
3964 return (AS1 (clr,%A0) CR_TAB
3965 AS1 (lsl,%B0) CR_TAB
3966 AS1 (rol,%A0) CR_TAB
3967 AS1 (lsl,%B0) CR_TAB
3968 AS1 (rol,%A0) CR_TAB
3973 return (AS1 (clr,%A0) CR_TAB
3974 AS1 (lsl,%B0) CR_TAB
3975 AS1 (rol,%A0) CR_TAB
3980 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
3982 insn, operands, len, 2);
3986 /* 32bit logic shift right ((unsigned int)x >> i) */
3989 lshrsi3_out (rtx insn, rtx operands[], int *len)
3991 if (GET_CODE (operands[2]) == CONST_INT)
3999 switch (INTVAL (operands[2]))
4003 int reg0 = true_regnum (operands[0]);
4004 int reg1 = true_regnum (operands[1]);
4007 return (AS2 (mov,%A0,%B1) CR_TAB
4008 AS2 (mov,%B0,%C1) CR_TAB
4009 AS2 (mov,%C0,%D1) CR_TAB
4011 else if (reg0 == reg1 + 1)
4012 return *len = 1, AS1 (clr,%D0);
4014 return (AS1 (clr,%D0) CR_TAB
4015 AS2 (mov,%C0,%D1) CR_TAB
4016 AS2 (mov,%B0,%C1) CR_TAB
4022 int reg0 = true_regnum (operands[0]);
4023 int reg1 = true_regnum (operands[1]);
4025 if (AVR_ENHANCED && (reg0 != reg1 + 2))
4028 return (AS2 (movw,%A0,%C1) CR_TAB
4029 AS1 (clr,%C0) CR_TAB
4032 if (reg0 <= reg1 + 1)
4033 return (AS2 (mov,%A0,%C1) CR_TAB
4034 AS2 (mov,%B0,%D1) CR_TAB
4035 AS1 (clr,%C0) CR_TAB
4037 else if (reg0 == reg1 + 2)
4038 return *len = 2, (AS1 (clr,%C0) CR_TAB
4041 return (AS2 (mov,%B0,%D1) CR_TAB
4042 AS2 (mov,%A0,%C1) CR_TAB
4043 AS1 (clr,%C0) CR_TAB
4048 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
4049 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4050 AS1 (clr,%B0) CR_TAB
4051 AS1 (clr,%C0) CR_TAB
4054 return *len = 3, (AS1 (clr,%B0) CR_TAB
4055 AS1 (clr,%C0) CR_TAB
4060 return (AS1 (clr,%A0) CR_TAB
4061 AS2 (sbrc,%D0,7) CR_TAB
4062 AS1 (inc,%A0) CR_TAB
4063 AS1 (clr,%B0) CR_TAB
4064 AS1 (clr,%C0) CR_TAB
4069 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4070 AS1 (ror,%C0) CR_TAB
4071 AS1 (ror,%B0) CR_TAB
4073 insn, operands, len, 4);
4077 /* Modifies the length assigned to instruction INSN
4078 LEN is the initially computed length of the insn. */
4081 adjust_insn_length (rtx insn, int len)
4083 rtx patt = PATTERN (insn);
4086 if (GET_CODE (patt) == SET)
4089 op[1] = SET_SRC (patt);
4090 op[0] = SET_DEST (patt);
4091 if (general_operand (op[1], VOIDmode)
4092 && general_operand (op[0], VOIDmode))
4094 switch (GET_MODE (op[0]))
4097 output_movqi (insn, op, &len);
4100 output_movhi (insn, op, &len);
4104 output_movsisf (insn, op, &len);
4110 else if (op[0] == cc0_rtx && REG_P (op[1]))
4112 switch (GET_MODE (op[1]))
4114 case HImode: out_tsthi (insn,&len); break;
4115 case SImode: out_tstsi (insn,&len); break;
4119 else if (GET_CODE (op[1]) == AND)
4121 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4123 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4124 if (GET_MODE (op[1]) == SImode)
4125 len = (((mask & 0xff) != 0xff)
4126 + ((mask & 0xff00) != 0xff00)
4127 + ((mask & 0xff0000L) != 0xff0000L)
4128 + ((mask & 0xff000000L) != 0xff000000L));
4129 else if (GET_MODE (op[1]) == HImode)
4130 len = (((mask & 0xff) != 0xff)
4131 + ((mask & 0xff00) != 0xff00));
4134 else if (GET_CODE (op[1]) == IOR)
4136 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4138 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4139 if (GET_MODE (op[1]) == SImode)
4140 len = (((mask & 0xff) != 0)
4141 + ((mask & 0xff00) != 0)
4142 + ((mask & 0xff0000L) != 0)
4143 + ((mask & 0xff000000L) != 0));
4144 else if (GET_MODE (op[1]) == HImode)
4145 len = (((mask & 0xff) != 0)
4146 + ((mask & 0xff00) != 0));
4150 set = single_set (insn);
4155 op[1] = SET_SRC (set);
4156 op[0] = SET_DEST (set);
4158 if (GET_CODE (patt) == PARALLEL
4159 && general_operand (op[1], VOIDmode)
4160 && general_operand (op[0], VOIDmode))
4162 if (XVECLEN (patt, 0) == 2)
4163 op[2] = XVECEXP (patt, 0, 1);
4165 switch (GET_MODE (op[0]))
4171 output_reload_inhi (insn, op, &len);
4175 output_reload_insisf (insn, op, &len);
4181 else if (GET_CODE (op[1]) == ASHIFT
4182 || GET_CODE (op[1]) == ASHIFTRT
4183 || GET_CODE (op[1]) == LSHIFTRT)
4187 ops[1] = XEXP (op[1],0);
4188 ops[2] = XEXP (op[1],1);
4189 switch (GET_CODE (op[1]))
4192 switch (GET_MODE (op[0]))
4194 case QImode: ashlqi3_out (insn,ops,&len); break;
4195 case HImode: ashlhi3_out (insn,ops,&len); break;
4196 case SImode: ashlsi3_out (insn,ops,&len); break;
4201 switch (GET_MODE (op[0]))
4203 case QImode: ashrqi3_out (insn,ops,&len); break;
4204 case HImode: ashrhi3_out (insn,ops,&len); break;
4205 case SImode: ashrsi3_out (insn,ops,&len); break;
4210 switch (GET_MODE (op[0]))
4212 case QImode: lshrqi3_out (insn,ops,&len); break;
4213 case HImode: lshrhi3_out (insn,ops,&len); break;
4214 case SImode: lshrsi3_out (insn,ops,&len); break;
4226 /* Return nonzero if register REG dead after INSN. */
4229 reg_unused_after (rtx insn, rtx reg)
4231 return (dead_or_set_p (insn, reg)
4232 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4235 /* Return nonzero if REG is not used after INSN.
4236 We assume REG is a reload reg, and therefore does
4237 not live past labels. It may live past calls or jumps though. */
4240 _reg_unused_after (rtx insn, rtx reg)
4245 /* If the reg is set by this instruction, then it is safe for our
4246 case. Disregard the case where this is a store to memory, since
4247 we are checking a register used in the store address. */
4248 set = single_set (insn);
4249 if (set && GET_CODE (SET_DEST (set)) != MEM
4250 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4253 while ((insn = NEXT_INSN (insn)))
4255 code = GET_CODE (insn);
4258 /* If this is a label that existed before reload, then the register
4259 if dead here. However, if this is a label added by reorg, then
4260 the register may still be live here. We can't tell the difference,
4261 so we just ignore labels completely. */
4262 if (code == CODE_LABEL)
4267 if (code == JUMP_INSN)
4270 /* If this is a sequence, we must handle them all at once.
4271 We could have for instance a call that sets the target register,
4272 and an insn in a delay slot that uses the register. In this case,
4273 we must return 0. */
4274 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4279 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4281 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4282 rtx set = single_set (this_insn);
4284 if (GET_CODE (this_insn) == CALL_INSN)
4286 else if (GET_CODE (this_insn) == JUMP_INSN)
4288 if (INSN_ANNULLED_BRANCH_P (this_insn))
4293 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4295 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4297 if (GET_CODE (SET_DEST (set)) != MEM)
4303 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4308 else if (code == JUMP_INSN)
4312 if (code == CALL_INSN)
4315 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4316 if (GET_CODE (XEXP (tem, 0)) == USE
4317 && REG_P (XEXP (XEXP (tem, 0), 0))
4318 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4320 if (call_used_regs[REGNO (reg)])
4324 if (GET_RTX_CLASS (code) == 'i')
4326 rtx set = single_set (insn);
4328 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4330 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4331 return GET_CODE (SET_DEST (set)) != MEM;
4332 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4339 /* Target hook for assembling integer objects. The AVR version needs
4340 special handling for references to certain labels. */
4343 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
4345 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
4346 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
4347 || GET_CODE (x) == LABEL_REF))
4349 fputs ("\t.word\tpm(", asm_out_file);
4350 output_addr_const (asm_out_file, x);
4351 fputs (")\n", asm_out_file);
4354 return default_assemble_integer (x, size, aligned_p);
4357 /* Sets section name for declaration DECL. */
4360 avr_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
4363 const char *name, *prefix;
4366 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
4367 name = (* targetm.strip_name_encoding) (name);
4369 if (TREE_CODE (decl) == FUNCTION_DECL)
4371 if (flag_function_sections)
4379 if (flag_function_sections)
4381 len = strlen (name) + strlen (prefix);
4382 string = alloca (len + 1);
4383 sprintf (string, "%s%s", prefix, name);
4384 DECL_SECTION_NAME (decl) = build_string (len, string);
4389 /* The routine used to output NUL terminated strings. We use a special
4390 version of this for most svr4 targets because doing so makes the
4391 generated assembly code more compact (and thus faster to assemble)
4392 as well as more readable, especially for targets like the i386
4393 (where the only alternative is to output character sequences as
4394 comma separated lists of numbers). */
4397 gas_output_limited_string(FILE *file, const char *str)
4399 const unsigned char *_limited_str = (unsigned char *) str;
4401 fprintf (file, "%s\"", STRING_ASM_OP);
4402 for (; (ch = *_limited_str); _limited_str++)
4405 switch (escape = ESCAPES[ch])
4411 fprintf (file, "\\%03o", ch);
4415 putc (escape, file);
4419 fprintf (file, "\"\n");
4422 /* The routine used to output sequences of byte values. We use a special
4423 version of this for most svr4 targets because doing so makes the
4424 generated assembly code more compact (and thus faster to assemble)
4425 as well as more readable. Note that if we find subparts of the
4426 character sequence which end with NUL (and which are shorter than
4427 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4430 gas_output_ascii(FILE *file, const char *str, size_t length)
4432 const unsigned char *_ascii_bytes = (const unsigned char *) str;
4433 const unsigned char *limit = _ascii_bytes + length;
4434 unsigned bytes_in_chunk = 0;
4435 for (; _ascii_bytes < limit; _ascii_bytes++)
4437 const unsigned char *p;
4438 if (bytes_in_chunk >= 60)
4440 fprintf (file, "\"\n");
4443 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4445 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4447 if (bytes_in_chunk > 0)
4449 fprintf (file, "\"\n");
4452 gas_output_limited_string (file, (char*)_ascii_bytes);
4459 if (bytes_in_chunk == 0)
4460 fprintf (file, "\t.ascii\t\"");
4461 switch (escape = ESCAPES[ch = *_ascii_bytes])
4468 fprintf (file, "\\%03o", ch);
4469 bytes_in_chunk += 4;
4473 putc (escape, file);
4474 bytes_in_chunk += 2;
4479 if (bytes_in_chunk > 0)
4480 fprintf (file, "\"\n");
4483 /* Return value is nonzero if pseudos that have been
4484 assigned to registers of class CLASS would likely be spilled
4485 because registers of CLASS are needed for spill registers. */
4488 class_likely_spilled_p (int c)
4490 return (c != ALL_REGS && c != ADDW_REGS);
4493 /* Valid attributes:
4494 progmem - put data to program memory;
4495 signal - make a function to be hardware interrupt. After function
4496 prologue interrupts are disabled;
4497 interrupt - make a function to be hardware interrupt. After function
4498 prologue interrupts are enabled;
4499 naked - don't generate function prologue/epilogue and `ret' command.
4501 Only `progmem' attribute valid for type. */
4503 const struct attribute_spec avr_attribute_table[] =
4505 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4506 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
4507 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4508 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4509 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4510 { NULL, 0, 0, false, false, false, NULL }
4513 /* Handle a "progmem" attribute; arguments as in
4514 struct attribute_spec.handler. */
4516 avr_handle_progmem_attribute (tree *node, tree name,
4517 tree args ATTRIBUTE_UNUSED,
4518 int flags ATTRIBUTE_UNUSED,
4523 if (TREE_CODE (*node) == TYPE_DECL)
4525 /* This is really a decl attribute, not a type attribute,
4526 but try to handle it for GCC 3.0 backwards compatibility. */
4528 tree type = TREE_TYPE (*node);
4529 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
4530 tree newtype = build_type_attribute_variant (type, attr);
4532 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
4533 TREE_TYPE (*node) = newtype;
4534 *no_add_attrs = true;
4536 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
4538 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
4540 warning ("only initialized variables can be placed into "
4541 "program memory area");
4542 *no_add_attrs = true;
4547 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
4548 *no_add_attrs = true;
4555 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4556 struct attribute_spec.handler. */
4559 avr_handle_fndecl_attribute (tree *node, tree name,
4560 tree args ATTRIBUTE_UNUSED,
4561 int flags ATTRIBUTE_UNUSED,
4564 if (TREE_CODE (*node) != FUNCTION_DECL)
4566 warning ("`%s' attribute only applies to functions",
4567 IDENTIFIER_POINTER (name));
4568 *no_add_attrs = true;
4574 /* Look for attribute `progmem' in DECL
4575 if found return 1, otherwise 0. */
4578 avr_progmem_p (tree decl)
4582 if (TREE_CODE (decl) != VAR_DECL)
4586 != lookup_attribute ("progmem", DECL_ATTRIBUTES (decl)))
4592 while (TREE_CODE (a) == ARRAY_TYPE);
4594 if (a == error_mark_node)
4597 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4603 /* Add the section attribute if the variable is in progmem. */
4606 avr_insert_attributes (tree node, tree *attributes)
4608 if (TREE_CODE (node) == VAR_DECL
4609 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
4610 && avr_progmem_p (node))
4612 static const char dsec[] = ".progmem.data";
4613 *attributes = tree_cons (get_identifier ("section"),
4614 build_tree_list (NULL, build_string (strlen (dsec), dsec)),
4617 /* ??? This seems sketchy. Why can't the user declare the
4618 thing const in the first place? */
4619 TREE_READONLY (node) = 1;
4624 avr_section_type_flags (tree decl, const char *name, int reloc)
4626 unsigned int flags = default_section_type_flags (decl, name, reloc);
4628 if (strncmp (name, ".noinit", 7) == 0)
4630 if (decl && TREE_CODE (decl) == VAR_DECL
4631 && DECL_INITIAL (decl) == NULL_TREE)
4632 flags |= SECTION_BSS; /* @nobits */
4634 warning ("only uninitialized variables can be placed in the "
4641 /* Outputs some appropriate text to go at the start of an assembler
4645 avr_file_start (void)
4648 error ("MCU `%s' supported for assembler only", avr_mcu_name);
4650 default_file_start ();
4652 fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);
4653 fputs ("__SREG__ = 0x3f\n"
4655 "__SP_L__ = 0x3d\n", asm_out_file);
4657 fputs ("__tmp_reg__ = 0\n"
4658 "__zero_reg__ = 1\n", asm_out_file);
4660 /* FIXME: output these only if there is anything in the .data / .bss
4661 sections - some code size could be saved by not linking in the
4662 initialization code from libgcc if one or both sections are empty. */
4663 fputs ("\t.global __do_copy_data\n", asm_out_file);
4664 fputs ("\t.global __do_clear_bss\n", asm_out_file);
4666 commands_in_file = 0;
4667 commands_in_prologues = 0;
4668 commands_in_epilogues = 0;
4671 /* Outputs to the stdio stream FILE some
4672 appropriate text to go at the end of an assembler file. */
4677 fputs ("/* File ", asm_out_file);
4678 output_quoted_string (asm_out_file, main_input_filename);
4679 fprintf (asm_out_file,
4680 ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4683 commands_in_file - commands_in_prologues - commands_in_epilogues,
4684 commands_in_prologues, commands_in_epilogues);
4687 /* Choose the order in which to allocate hard registers for
4688 pseudo-registers local to a basic block.
4690 Store the desired register order in the array `reg_alloc_order'.
4691 Element 0 should be the register to allocate first; element 1, the
4692 next register; and so on. */
4695 order_regs_for_local_alloc (void)
4698 static const int order_0[] = {
4706 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4710 static const int order_1[] = {
4718 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4722 static const int order_2[] = {
4731 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4736 const int *order = (TARGET_ORDER_1 ? order_1 :
4737 TARGET_ORDER_2 ? order_2 :
4739 for (i=0; i < ARRAY_SIZE (order_0); ++i)
4740 reg_alloc_order[i] = order[i];
4743 /* Calculate the cost of X code of the expression in which it is contained,
4744 found in OUTER_CODE */
4747 default_rtx_costs (rtx X, enum rtx_code code, enum rtx_code outer_code)
4754 cost = 2 * GET_MODE_SIZE (GET_MODE (X));
4757 if (outer_code != SET)
4759 if (GET_CODE (XEXP (X,0)) == SYMBOL_REF)
4760 cost += 2 * GET_MODE_SIZE (GET_MODE (X));
4762 cost += GET_MODE_SIZE (GET_MODE (X));
4768 if (outer_code == SET)
4769 cost = GET_MODE_SIZE (GET_MODE (X));
4771 cost = -GET_MODE_SIZE (GET_MODE (X));
4774 if (outer_code == SET)
4775 cost = GET_MODE_SIZE (GET_MODE (X));
4781 if (outer_code == SET)
4783 if (X == stack_pointer_rtx)
4785 else if (GET_CODE (XEXP (X,1)) == CONST_INT)
4786 cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 :
4787 GET_MODE_SIZE (GET_MODE (X)));
4789 cost = GET_MODE_SIZE (GET_MODE (X));
4793 if (GET_CODE (XEXP (X,1)) == CONST_INT)
4794 cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0)));
4803 avr_rtx_costs (rtx x, int code, int outer_code, int *total)
4810 if (outer_code == PLUS
4811 || outer_code == IOR
4812 || outer_code == AND
4813 || outer_code == MINUS
4814 || outer_code == SET
4820 if (outer_code == COMPARE
4822 && INTVAL (x) <= 255)
4837 cst = default_rtx_costs (x, code, outer_code);
4849 /* Calculate the cost of a memory address. */
4852 avr_address_cost (rtx x)
4854 if (GET_CODE (x) == PLUS
4855 && GET_CODE (XEXP (x,1)) == CONST_INT
4856 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
4857 && INTVAL (XEXP (x,1)) >= 61)
4859 if (CONSTANT_ADDRESS_P (x))
4861 if (avr_io_address_p (x, 1))
4868 /* EXTRA_CONSTRAINT helper */
4871 extra_constraint (rtx x, int c)
4874 && GET_CODE (x) == MEM
4875 && GET_CODE (XEXP (x,0)) == PLUS)
4877 if (TARGET_ALL_DEBUG)
4879 fprintf (stderr, ("extra_constraint:\n"
4880 "reload_completed: %d\n"
4881 "reload_in_progress: %d\n"),
4882 reload_completed, reload_in_progress);
4885 if (GET_CODE (x) == MEM
4886 && GET_CODE (XEXP (x,0)) == PLUS
4887 && REG_P (XEXP (XEXP (x,0), 0))
4888 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
4889 && (INTVAL (XEXP (XEXP (x,0), 1))
4890 <= MAX_LD_OFFSET (GET_MODE (x))))
4892 rtx xx = XEXP (XEXP (x,0), 0);
4893 int regno = REGNO (xx);
4894 if (TARGET_ALL_DEBUG)
4896 fprintf (stderr, ("extra_constraint:\n"
4897 "reload_completed: %d\n"
4898 "reload_in_progress: %d\n"),
4899 reload_completed, reload_in_progress);
4902 if (regno >= FIRST_PSEUDO_REGISTER)
4903 return 1; /* allocate pseudos */
4904 else if (regno == REG_Z || regno == REG_Y)
4905 return 1; /* strictly check */
4906 else if (xx == frame_pointer_rtx
4907 || xx == arg_pointer_rtx)
4908 return 1; /* XXX frame & arg pointer checks */
4914 /* Convert condition code CONDITION to the valid AVR condition code. */
4917 avr_normalize_condition (RTX_CODE condition)
4934 /* This function optimizes conditional jumps. */
4941 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4943 if (! (GET_CODE (insn) == INSN
4944 || GET_CODE (insn) == CALL_INSN
4945 || GET_CODE (insn) == JUMP_INSN)
4946 || !single_set (insn))
4949 pattern = PATTERN (insn);
4951 if (GET_CODE (pattern) == PARALLEL)
4952 pattern = XVECEXP (pattern, 0, 0);
4953 if (GET_CODE (pattern) == SET
4954 && SET_DEST (pattern) == cc0_rtx
4955 && compare_diff_p (insn))
4957 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
4959 /* Now we work under compare insn. */
4961 pattern = SET_SRC (pattern);
4962 if (true_regnum (XEXP (pattern,0)) >= 0
4963 && true_regnum (XEXP (pattern,1)) >= 0 )
4965 rtx x = XEXP (pattern,0);
4966 rtx next = next_real_insn (insn);
4967 rtx pat = PATTERN (next);
4968 rtx src = SET_SRC (pat);
4969 rtx t = XEXP (src,0);
4970 PUT_CODE (t, swap_condition (GET_CODE (t)));
4971 XEXP (pattern,0) = XEXP (pattern,1);
4972 XEXP (pattern,1) = x;
4973 INSN_CODE (next) = -1;
4975 else if (true_regnum (XEXP (pattern,0)) >= 0
4976 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
4978 rtx x = XEXP (pattern,1);
4979 rtx next = next_real_insn (insn);
4980 rtx pat = PATTERN (next);
4981 rtx src = SET_SRC (pat);
4982 rtx t = XEXP (src,0);
4983 enum machine_mode mode = GET_MODE (XEXP (pattern, 0));
4985 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
4987 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
4988 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
4989 INSN_CODE (next) = -1;
4990 INSN_CODE (insn) = -1;
4994 else if (true_regnum (SET_SRC (pattern)) >= 0)
4996 /* This is a tst insn */
4997 rtx next = next_real_insn (insn);
4998 rtx pat = PATTERN (next);
4999 rtx src = SET_SRC (pat);
5000 rtx t = XEXP (src,0);
5002 PUT_CODE (t, swap_condition (GET_CODE (t)));
5003 SET_SRC (pattern) = gen_rtx (NEG,
5004 GET_MODE (SET_SRC (pattern)),
5006 INSN_CODE (next) = -1;
5007 INSN_CODE (insn) = -1;
5013 /* Returns register number for function return value.*/
5016 avr_ret_register (void)
5021 /* Ceate an RTX representing the place where a
5022 library function returns a value of mode MODE. */
5025 avr_libcall_value (enum machine_mode mode)
5027 int offs = GET_MODE_SIZE (mode);
5030 return gen_rtx (REG, mode, RET_REGISTER + 2 - offs);
5033 /* Create an RTX representing the place where a
5034 function returns a value of data type VALTYPE. */
5037 avr_function_value (tree type, tree func ATTRIBUTE_UNUSED)
5041 if (TYPE_MODE (type) != BLKmode)
5042 return avr_libcall_value (TYPE_MODE (type));
5044 offs = int_size_in_bytes (type);
5047 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5048 offs = GET_MODE_SIZE (SImode);
5049 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5050 offs = GET_MODE_SIZE (DImode);
5052 return gen_rtx (REG, BLKmode, RET_REGISTER + 2 - offs);
5055 /* Returns nonzero if the number MASK has only one bit set. */
5058 mask_one_bit_p (HOST_WIDE_INT mask)
5061 unsigned HOST_WIDE_INT n=mask;
5062 for (i = 0; i < 32; ++i)
5064 if (n & 0x80000000L)
5066 if (n & 0x7fffffffL)
5077 /* Places additional restrictions on the register class to
5078 use when it is necessary to copy value X into a register
5082 preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class class)
5088 test_hard_reg_class (enum reg_class class, rtx x)
5090 int regno = true_regnum (x);
5094 if (TEST_HARD_REG_CLASS (class, regno))
5102 jump_over_one_insn_p (rtx insn, rtx dest)
5104 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5107 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5108 int dest_addr = INSN_ADDRESSES (uid);
5109 return dest_addr - jump_addr == get_attr_length (insn) + 1;
5112 /* Returns 1 if a value of mode MODE can be stored starting with hard
5113 register number REGNO. On the enhanced core, anything larger than
5114 1 byte must start in even numbered register for "movw" to work
5115 (this way we don't have to check for odd registers everywhere). */
5118 avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
5120 /* Bug workaround: recog.c (peep2_find_free_register) and probably
5121 a few other places assume that the frame pointer is a single hard
5122 register, so r29 may be allocated and overwrite the high byte of
5123 the frame pointer. Do not allow any value to start in r29. */
5124 if (regno == REG_Y + 1)
5129 /* if (regno < 24 && !AVR_ENHANCED)
5131 return !(regno & 1);
5134 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5135 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5136 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
5139 avr_io_address_p (rtx x, int size)
5141 return (optimize > 0 && GET_CODE (x) == CONST_INT
5142 && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
5145 /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5148 const_int_pow2_p (rtx x)
5150 if (GET_CODE (x) == CONST_INT)
5152 HOST_WIDE_INT d = INTVAL (x);
5153 HOST_WIDE_INT abs_d = (d >= 0) ? d : -d;
5154 return exact_log2 (abs_d) + 1;
5160 output_reload_inhi (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
5166 if (GET_CODE (operands[1]) == CONST_INT)
5168 int val = INTVAL (operands[1]);
5169 if ((val & 0xff) == 0)
5172 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5173 AS2 (ldi,%2,hi8(%1)) CR_TAB
5176 else if ((val & 0xff00) == 0)
5179 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5180 AS2 (mov,%A0,%2) CR_TAB
5181 AS2 (mov,%B0,__zero_reg__));
5183 else if ((val & 0xff) == ((val & 0xff00) >> 8))
5186 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5187 AS2 (mov,%A0,%2) CR_TAB
5192 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5193 AS2 (mov,%A0,%2) CR_TAB
5194 AS2 (ldi,%2,hi8(%1)) CR_TAB
5200 output_reload_insisf (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
5202 rtx src = operands[1];
5203 int cnst = (GET_CODE (src) == CONST_INT);
5208 *len = 4 + ((INTVAL (src) & 0xff) != 0)
5209 + ((INTVAL (src) & 0xff00) != 0)
5210 + ((INTVAL (src) & 0xff0000) != 0)
5211 + ((INTVAL (src) & 0xff000000) != 0);
5218 if (cnst && ((INTVAL (src) & 0xff) == 0))
5219 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5222 output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
5223 output_asm_insn (AS2 (mov, %A0, %2), operands);
5225 if (cnst && ((INTVAL (src) & 0xff00) == 0))
5226 output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
5229 output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
5230 output_asm_insn (AS2 (mov, %B0, %2), operands);
5232 if (cnst && ((INTVAL (src) & 0xff0000) == 0))
5233 output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
5236 output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
5237 output_asm_insn (AS2 (mov, %C0, %2), operands);
5239 if (cnst && ((INTVAL (src) & 0xff000000) == 0))
5240 output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
5243 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5244 output_asm_insn (AS2 (mov, %D0, %2), operands);
5250 avr_output_bld (rtx operands[], int bit_nr)
5252 static char s[] = "bld %A0,0";
5254 s[5] = 'A' + (bit_nr >> 3);
5255 s[8] = '0' + (bit_nr & 7);
5256 output_asm_insn (s, operands);
5260 avr_output_addr_vec_elt (FILE *stream, int value)
5263 fprintf (stream, "\t.word pm(.L%d)\n", value);
5265 fprintf (stream, "\trjmp .L%d\n", value);
5270 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5271 registers (for a define_peephole2) in the current function. */
5274 avr_peep2_scratch_safe (rtx scratch)
5276 if ((interrupt_function_p (current_function_decl)
5277 || signal_function_p (current_function_decl))
5278 && leaf_function_p ())
5280 int first_reg = true_regnum (scratch);
5281 int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
5284 for (reg = first_reg; reg <= last_reg; reg++)
5286 if (!regs_ever_live[reg])
5293 /* Output a branch that tests a single bit of a register (QI, HI or SImode)
5294 or memory location in the I/O space (QImode only).
5296 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5297 Operand 1: register operand to test, or CONST_INT memory address.
5298 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5299 Operand 3: label to jump to if the test is true. */
5302 avr_out_sbxx_branch (rtx insn, rtx operands[])
5304 enum rtx_code comp = GET_CODE (operands[0]);
5305 int long_jump = (get_attr_length (insn) >= 4);
5306 int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
5310 else if (comp == LT)
5314 comp = reverse_condition (comp);
5316 if (GET_CODE (operands[1]) == CONST_INT)
5318 if (INTVAL (operands[1]) < 0x40)
5321 output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
5323 output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
5327 output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
5329 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
5331 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
5334 else /* GET_CODE (operands[1]) == REG */
5336 if (GET_MODE (operands[1]) == QImode)
5339 output_asm_insn (AS2 (sbrs,%1,%2), operands);
5341 output_asm_insn (AS2 (sbrc,%1,%2), operands);
5343 else /* HImode or SImode */
5345 static char buf[] = "sbrc %A1,0";
5346 int bit_nr = exact_log2 (INTVAL (operands[2])
5347 & GET_MODE_MASK (GET_MODE (operands[1])));
5349 buf[3] = (comp == EQ) ? 's' : 'c';
5350 buf[6] = 'A' + (bit_nr >> 3);
5351 buf[9] = '0' + (bit_nr & 7);
5352 output_asm_insn (buf, operands);
5357 return (AS1 (rjmp,.+4) CR_TAB
5360 return AS1 (rjmp,%3);
5365 avr_asm_out_ctor (rtx symbol, int priority)
5367 fputs ("\t.global __do_global_ctors\n", asm_out_file);
5368 default_ctor_section_asm_out_constructor (symbol, priority);
5372 avr_asm_out_dtor (rtx symbol, int priority)
5374 fputs ("\t.global __do_global_dtors\n", asm_out_file);
5375 default_dtor_section_asm_out_destructor (symbol, priority);
5379 avr_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
5381 return ((TYPE_MODE (type) == BLKmode)
5382 ? int_size_in_bytes (type) > 8