1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005
3 Free Software Foundation, Inc.
4 Contributed by Denis Chertykov (denisc@overta.ru)
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
25 #include "coretypes.h"
29 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-attr.h"
46 #include "target-def.h"
48 /* Maximal allowed offset for an address in the LD command */
49 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
51 static int avr_naked_function_p (tree);
52 static int interrupt_function_p (tree);
53 static int signal_function_p (tree);
54 static int avr_regs_to_save (HARD_REG_SET *);
55 static int sequent_regs_live (void);
56 static const char *ptrreg_to_str (int);
57 static const char *cond_string (enum rtx_code);
58 static int avr_num_arg_regs (enum machine_mode, tree);
59 static int out_adj_frame_ptr (FILE *, int);
60 static int out_set_stack_ptr (FILE *, int, int);
61 static RTX_CODE compare_condition (rtx insn);
62 static int compare_sign_p (rtx insn);
63 static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *);
64 static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
65 const struct attribute_spec avr_attribute_table[];
66 static bool avr_assemble_integer (rtx, unsigned int, int);
67 static void avr_file_start (void);
68 static void avr_file_end (void);
69 static void avr_output_function_prologue (FILE *, HOST_WIDE_INT);
70 static void avr_output_function_epilogue (FILE *, HOST_WIDE_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__" },
179 /* Classic + MOVW, <= 8K. */
180 { "attiny13", 2, "__AVR_ATtiny13__" },
181 { "attiny2313", 2, "__AVR_ATtiny2313__" },
184 { "atmega103", 3, "__AVR_ATmega103__" },
185 { "atmega603", 3, "__AVR_ATmega603__" },
186 { "at43usb320", 3, "__AVR_AT43USB320__" },
187 { "at43usb355", 3, "__AVR_AT43USB355__" },
188 { "at76c711", 3, "__AVR_AT76C711__" },
189 /* Enhanced, <= 8K. */
191 { "atmega8", 4, "__AVR_ATmega8__" },
192 { "atmega48", 4, "__AVR_ATmega48__" },
193 { "atmega88", 4, "__AVR_ATmega88__" },
194 { "atmega8515", 4, "__AVR_ATmega8515__" },
195 { "atmega8535", 4, "__AVR_ATmega8535__" },
196 /* Enhanced, > 8K. */
198 { "atmega16", 5, "__AVR_ATmega16__" },
199 { "atmega161", 5, "__AVR_ATmega161__" },
200 { "atmega162", 5, "__AVR_ATmega162__" },
201 { "atmega163", 5, "__AVR_ATmega163__" },
202 { "atmega165", 5, "__AVR_ATmega165__" },
203 { "atmega168", 5, "__AVR_ATmega168__" },
204 { "atmega169", 5, "__AVR_ATmega169__" },
205 { "atmega32", 5, "__AVR_ATmega32__" },
206 { "atmega323", 5, "__AVR_ATmega323__" },
207 { "atmega325", 5, "__AVR_ATmega325__" },
208 { "atmega3250", 5, "__AVR_ATmega3250__" },
209 { "atmega64", 5, "__AVR_ATmega64__" },
210 { "atmega645", 5, "__AVR_ATmega645__" },
211 { "atmega6450", 5, "__AVR_ATmega6450__" },
212 { "atmega128", 5, "__AVR_ATmega128__" },
213 { "at90can128", 5, "__AVR_AT90CAN128__" },
214 { "at94k", 5, "__AVR_AT94K__" },
215 /* Assembler only. */
217 { "at90s1200", 1, "__AVR_AT90S1200__" },
218 { "attiny11", 1, "__AVR_ATtiny11__" },
219 { "attiny12", 1, "__AVR_ATtiny12__" },
220 { "attiny15", 1, "__AVR_ATtiny15__" },
221 { "attiny28", 1, "__AVR_ATtiny28__" },
225 int avr_case_values_threshold = 30000;
227 /* Initialize the GCC target structure. */
228 #undef TARGET_ASM_ALIGNED_HI_OP
229 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
230 #undef TARGET_ASM_INTEGER
231 #define TARGET_ASM_INTEGER avr_assemble_integer
232 #undef TARGET_ASM_FILE_START
233 #define TARGET_ASM_FILE_START avr_file_start
234 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
235 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
236 #undef TARGET_ASM_FILE_END
237 #define TARGET_ASM_FILE_END avr_file_end
239 #undef TARGET_ASM_FUNCTION_PROLOGUE
240 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
241 #undef TARGET_ASM_FUNCTION_EPILOGUE
242 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
243 #undef TARGET_ATTRIBUTE_TABLE
244 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
245 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
246 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
247 #undef TARGET_INSERT_ATTRIBUTES
248 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
249 #undef TARGET_SECTION_TYPE_FLAGS
250 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
251 #undef TARGET_RTX_COSTS
252 #define TARGET_RTX_COSTS avr_rtx_costs
253 #undef TARGET_ADDRESS_COST
254 #define TARGET_ADDRESS_COST avr_address_cost
255 #undef TARGET_MACHINE_DEPENDENT_REORG
256 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
258 #undef TARGET_RETURN_IN_MEMORY
259 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
261 #undef TARGET_STRICT_ARGUMENT_NAMING
262 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
264 struct gcc_target targetm = TARGET_INITIALIZER;
267 avr_override_options (void)
269 const struct mcu_type_s *t;
270 const struct base_arch_s *base;
272 for (t = avr_mcu_types; t->name; t++)
273 if (strcmp (t->name, avr_mcu_name) == 0)
278 fprintf (stderr, "unknown MCU `%s' specified\nKnown MCU names:\n",
280 for (t = avr_mcu_types; t->name; t++)
281 fprintf (stderr," %s\n", t->name);
284 base = &avr_arch_types[t->arch];
285 avr_asm_only_p = base->asm_only;
286 avr_enhanced_p = base->enhanced;
287 avr_mega_p = base->mega;
288 avr_base_arch_macro = base->macro;
289 avr_extra_arch_macro = t->macro;
291 if (optimize && !TARGET_NO_TABLEJUMP)
292 avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
294 tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO);
295 zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO);
298 /* return register class from register number. */
300 static const int reg_class_tab[]={
301 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
302 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
303 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
304 GENERAL_REGS, /* r0 - r15 */
305 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
306 LD_REGS, /* r16 - 23 */
307 ADDW_REGS,ADDW_REGS, /* r24,r25 */
308 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
309 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
310 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
311 STACK_REG,STACK_REG /* SPL,SPH */
314 /* Return register class for register R. */
317 avr_regno_reg_class (int r)
320 return reg_class_tab[r];
325 /* A C expression which defines the machine-dependent operand
326 constraint letters for register classes. If C is such a
327 letter, the value should be the register class corresponding to
328 it. Otherwise, the value should be `NO_REGS'. The register
329 letter `r', corresponding to class `GENERAL_REGS', will not be
330 passed to this macro; you do not need to handle it. */
333 avr_reg_class_from_letter (int c)
337 case 't' : return R0_REG;
338 case 'b' : return BASE_POINTER_REGS;
339 case 'e' : return POINTER_REGS;
340 case 'w' : return ADDW_REGS;
341 case 'd' : return LD_REGS;
342 case 'l' : return NO_LD_REGS;
343 case 'a' : return SIMPLE_LD_REGS;
344 case 'x' : return POINTER_X_REGS;
345 case 'y' : return POINTER_Y_REGS;
346 case 'z' : return POINTER_Z_REGS;
347 case 'q' : return STACK_REG;
353 /* Return nonzero if FUNC is a naked function. */
356 avr_naked_function_p (tree func)
360 if (TREE_CODE (func) != FUNCTION_DECL)
363 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
364 return a != NULL_TREE;
367 /* Return nonzero if FUNC is an interrupt function as specified
368 by the "interrupt" attribute. */
371 interrupt_function_p (tree func)
375 if (TREE_CODE (func) != FUNCTION_DECL)
378 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
379 return a != NULL_TREE;
382 /* Return nonzero if FUNC is a signal function as specified
383 by the "signal" attribute. */
386 signal_function_p (tree func)
390 if (TREE_CODE (func) != FUNCTION_DECL)
393 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
394 return a != NULL_TREE;
397 /* Return the number of hard registers to push/pop in the prologue/epilogue
398 of the current function, and optionally store these registers in SET. */
401 avr_regs_to_save (HARD_REG_SET *set)
404 int int_or_sig_p = (interrupt_function_p (current_function_decl)
405 || signal_function_p (current_function_decl));
406 int leaf_func_p = leaf_function_p ();
409 CLEAR_HARD_REG_SET (*set);
412 /* No need to save any registers if the function never returns. */
413 if (TREE_THIS_VOLATILE (current_function_decl))
416 for (reg = 0; reg < 32; reg++)
418 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
419 any global register variables. */
423 if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
424 || (regs_ever_live[reg]
425 && (int_or_sig_p || !call_used_regs[reg])
426 && !(frame_pointer_needed
427 && (reg == REG_Y || reg == (REG_Y+1)))))
430 SET_HARD_REG_BIT (*set, reg);
437 /* Compute offset between arg_pointer and frame_pointer. */
440 initial_elimination_offset (int from, int to)
442 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
446 int offset = frame_pointer_needed ? 2 : 0;
448 offset += avr_regs_to_save (NULL);
449 return get_frame_size () + 2 + 1 + offset;
453 /* Return 1 if the function epilogue is just a single "ret". */
456 avr_simple_epilogue (void)
458 return (! frame_pointer_needed
459 && get_frame_size () == 0
460 && avr_regs_to_save (NULL) == 0
461 && ! interrupt_function_p (current_function_decl)
462 && ! signal_function_p (current_function_decl)
463 && ! avr_naked_function_p (current_function_decl)
464 && ! MAIN_NAME_P (DECL_NAME (current_function_decl))
465 && ! TREE_THIS_VOLATILE (current_function_decl));
468 /* This function checks sequence of live registers. */
471 sequent_regs_live (void)
477 for (reg = 0; reg < 18; ++reg)
479 if (!call_used_regs[reg])
481 if (regs_ever_live[reg])
491 if (!frame_pointer_needed)
493 if (regs_ever_live[REG_Y])
501 if (regs_ever_live[REG_Y+1])
514 return (cur_seq == live_seq) ? live_seq : 0;
518 /* Output to FILE the asm instructions to adjust the frame pointer by
519 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
520 (epilogue). Returns the number of instructions generated. */
523 out_adj_frame_ptr (FILE *file, int adj)
529 if (TARGET_TINY_STACK)
531 if (adj < -63 || adj > 63)
532 warning ("large frame pointer change (%d) with -mtiny-stack", adj);
534 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
535 over "sbiw" (2 cycles, same size). */
537 fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
540 else if (adj < -63 || adj > 63)
542 fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
543 AS2 (sbci, r29, hi8(%d)) CR_TAB),
549 fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
554 fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
562 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
563 handling various cases of interrupt enable flag state BEFORE and AFTER
564 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
565 Returns the number of instructions generated. */
568 out_set_stack_ptr (FILE *file, int before, int after)
570 int do_sph, do_cli, do_save, do_sei, lock_sph, size;
572 /* The logic here is so that -mno-interrupts actually means
573 "it is safe to write SPH in one instruction, then SPL in the
574 next instruction, without disabling interrupts first".
575 The after != -1 case (interrupt/signal) is not affected. */
577 do_sph = !TARGET_TINY_STACK;
578 lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
579 do_cli = (before != 0 && (after == 0 || lock_sph));
580 do_save = (do_cli && before == -1 && after == -1);
581 do_sei = ((do_cli || before != 1) && after == 1);
586 fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
592 fprintf (file, "cli" CR_TAB);
596 /* Do SPH first - maybe this will disable interrupts for one instruction
597 someday (a suggestion has been sent to avr@atmel.com for consideration
598 in future devices - that would make -mno-interrupts always safe). */
601 fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
605 /* Set/restore the I flag now - interrupts will be really enabled only
606 after the next instruction. This is not clearly documented, but
607 believed to be true for all AVR devices. */
610 fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
615 fprintf (file, "sei" CR_TAB);
619 fprintf (file, AS2 (out, __SP_L__, r28) "\n");
625 /* Output function prologue. */
628 avr_output_function_prologue (FILE *file, HOST_WIDE_INT size)
631 int interrupt_func_p;
637 last_insn_address = 0;
638 jump_tables_size = 0;
640 fprintf (file, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n",
643 if (avr_naked_function_p (current_function_decl))
645 fputs ("/* prologue: naked */\n", file);
649 interrupt_func_p = interrupt_function_p (current_function_decl);
650 signal_func_p = signal_function_p (current_function_decl);
651 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
652 live_seq = sequent_regs_live ();
653 minimize = (TARGET_CALL_PROLOGUES
654 && !interrupt_func_p && !signal_func_p && live_seq);
656 if (interrupt_func_p)
658 fprintf (file,"\tsei\n");
661 if (interrupt_func_p || signal_func_p)
664 AS1 (push,__zero_reg__) CR_TAB
665 AS1 (push,__tmp_reg__) CR_TAB
666 AS2 (in,__tmp_reg__,__SREG__) CR_TAB
667 AS1 (push,__tmp_reg__) CR_TAB
668 AS1 (clr,__zero_reg__) "\n");
674 AS1 (ldi,r28) ",lo8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
675 AS1 (ldi,r29) ",hi8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
676 AS2 (out,__SP_H__,r29) CR_TAB
677 AS2 (out,__SP_L__,r28) "\n"),
678 avr_init_stack, size, avr_init_stack, size);
682 else if (minimize && (frame_pointer_needed || live_seq > 6))
684 const char *cfun_name = current_function_name ();
686 AS1 (ldi, r26) ",lo8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
687 AS1 (ldi, r27) ",hi8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB), size, size);
689 fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB
690 AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB),
691 cfun_name, cfun_name);
697 fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
698 (18 - live_seq) * 2);
703 fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
704 (18 - live_seq) * 2);
707 fprintf (file, ".L_%s_body:\n", cfun_name);
713 prologue_size += avr_regs_to_save (&set);
714 for (reg = 0; reg < 32; ++reg)
716 if (TEST_HARD_REG_BIT (set, reg))
718 fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
721 if (frame_pointer_needed)
724 AS1 (push,r28) CR_TAB
725 AS1 (push,r29) CR_TAB
726 AS2 (in,r28,__SP_L__) CR_TAB
727 AS2 (in,r29,__SP_H__) "\n");
732 prologue_size += out_adj_frame_ptr (file, size);
734 if (interrupt_func_p)
736 prologue_size += out_set_stack_ptr (file, 1, 1);
738 else if (signal_func_p)
740 prologue_size += out_set_stack_ptr (file, 0, 0);
744 prologue_size += out_set_stack_ptr (file, -1, -1);
751 fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
754 /* Output function epilogue. */
757 avr_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
760 int interrupt_func_p;
766 rtx last = get_last_nonnote_insn ();
768 function_size = jump_tables_size;
771 rtx first = get_first_nonnote_insn ();
772 function_size += (INSN_ADDRESSES (INSN_UID (last)) -
773 INSN_ADDRESSES (INSN_UID (first)));
774 function_size += get_attr_length (last);
777 fprintf (file, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n", size);
780 if (avr_naked_function_p (current_function_decl))
782 fputs ("/* epilogue: naked */\n", file);
786 if (last && GET_CODE (last) == BARRIER)
788 fputs ("/* epilogue: noreturn */\n", file);
792 interrupt_func_p = interrupt_function_p (current_function_decl);
793 signal_func_p = signal_function_p (current_function_decl);
794 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
795 live_seq = sequent_regs_live ();
796 minimize = (TARGET_CALL_PROLOGUES
797 && !interrupt_func_p && !signal_func_p && live_seq);
801 /* Return value from main() is already in the correct registers
802 (r25:r24) as the exit() argument. */
805 fputs ("\t" AS1 (jmp,exit) "\n", file);
810 fputs ("\t" AS1 (rjmp,exit) "\n", file);
814 else if (minimize && (frame_pointer_needed || live_seq > 4))
816 fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
818 if (frame_pointer_needed)
820 epilogue_size += out_adj_frame_ptr (file, -size);
824 fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
825 AS2 (in , r29, __SP_H__) CR_TAB));
831 fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
832 (18 - live_seq) * 2);
837 fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
838 (18 - live_seq) * 2);
846 if (frame_pointer_needed)
851 epilogue_size += out_adj_frame_ptr (file, -size);
853 if (interrupt_func_p || signal_func_p)
855 epilogue_size += out_set_stack_ptr (file, -1, 0);
859 epilogue_size += out_set_stack_ptr (file, -1, -1);
868 epilogue_size += avr_regs_to_save (&set);
869 for (reg = 31; reg >= 0; --reg)
871 if (TEST_HARD_REG_BIT (set, reg))
873 fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
877 if (interrupt_func_p || signal_func_p)
880 AS1 (pop,__tmp_reg__) CR_TAB
881 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
882 AS1 (pop,__tmp_reg__) CR_TAB
883 AS1 (pop,__zero_reg__) "\n");
885 fprintf (file, "\treti\n");
888 fprintf (file, "\tret\n");
893 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
894 fprintf (file, "/* function %s size %d (%d) */\n", current_function_name (),
895 prologue_size + function_size + epilogue_size, function_size);
896 commands_in_file += prologue_size + function_size + epilogue_size;
897 commands_in_prologues += prologue_size;
898 commands_in_epilogues += epilogue_size;
902 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
903 machine for a memory operand of mode MODE. */
906 legitimate_address_p (enum machine_mode mode, rtx x, int strict)
908 enum reg_class r = NO_REGS;
910 if (TARGET_ALL_DEBUG)
912 fprintf (stderr, "mode: (%s) %s %s %s %s:",
914 strict ? "(strict)": "",
915 reload_completed ? "(reload_completed)": "",
916 reload_in_progress ? "(reload_in_progress)": "",
917 reg_renumber ? "(reg_renumber)" : "");
918 if (GET_CODE (x) == PLUS
919 && REG_P (XEXP (x, 0))
920 && GET_CODE (XEXP (x, 1)) == CONST_INT
921 && INTVAL (XEXP (x, 1)) >= 0
922 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
925 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
926 true_regnum (XEXP (x, 0)));
929 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
930 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
932 else if (CONSTANT_ADDRESS_P (x))
934 else if (GET_CODE (x) == PLUS
935 && REG_P (XEXP (x, 0))
936 && GET_CODE (XEXP (x, 1)) == CONST_INT
937 && INTVAL (XEXP (x, 1)) >= 0)
939 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
943 || REGNO (XEXP (x,0)) == REG_Y
944 || REGNO (XEXP (x,0)) == REG_Z)
945 r = BASE_POINTER_REGS;
946 if (XEXP (x,0) == frame_pointer_rtx
947 || XEXP (x,0) == arg_pointer_rtx)
948 r = BASE_POINTER_REGS;
950 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
953 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
954 && REG_P (XEXP (x, 0))
955 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
956 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
960 if (TARGET_ALL_DEBUG)
962 fprintf (stderr, " ret = %c\n", r);
964 return r == NO_REGS ? 0 : (int)r;
967 /* Attempts to replace X with a valid
968 memory address for an operand of mode MODE */
971 legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
974 if (TARGET_ALL_DEBUG)
976 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
980 if (GET_CODE (oldx) == PLUS
981 && REG_P (XEXP (oldx,0)))
983 if (REG_P (XEXP (oldx,1)))
984 x = force_reg (GET_MODE (oldx), oldx);
985 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
987 int offs = INTVAL (XEXP (oldx,1));
988 if (frame_pointer_rtx != XEXP (oldx,0))
989 if (offs > MAX_LD_OFFSET (mode))
991 if (TARGET_ALL_DEBUG)
992 fprintf (stderr, "force_reg (big offset)\n");
993 x = force_reg (GET_MODE (oldx), oldx);
1001 /* Return a pointer register name as a string. */
1004 ptrreg_to_str (int regno)
1008 case REG_X: return "X";
1009 case REG_Y: return "Y";
1010 case REG_Z: return "Z";
1017 /* Return the condition name as a string.
1018 Used in conditional jump constructing */
1021 cond_string (enum rtx_code code)
1030 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1035 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1048 /* Output ADDR to FILE as address. */
1051 print_operand_address (FILE *file, rtx addr)
1053 switch (GET_CODE (addr))
1056 fprintf (file, ptrreg_to_str (REGNO (addr)));
1060 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1064 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1068 if (CONSTANT_ADDRESS_P (addr)
1069 && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
1070 || GET_CODE (addr) == LABEL_REF))
1072 fprintf (file, "pm(");
1073 output_addr_const (file,addr);
1074 fprintf (file ,")");
1077 output_addr_const (file, addr);
1082 /* Output X as assembler operand to file FILE. */
1085 print_operand (FILE *file, rtx x, int code)
1089 if (code >= 'A' && code <= 'D')
1099 if (x == zero_reg_rtx)
1100 fprintf (file, "__zero_reg__");
1102 fprintf (file, reg_names[true_regnum (x) + abcd]);
1104 else if (GET_CODE (x) == CONST_INT)
1105 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
1106 else if (GET_CODE (x) == MEM)
1108 rtx addr = XEXP (x,0);
1110 if (CONSTANT_P (addr) && abcd)
1113 output_address (addr);
1114 fprintf (file, ")+%d", abcd);
1116 else if (code == 'o')
1118 if (GET_CODE (addr) != PLUS)
1119 fatal_insn ("bad address, not (reg+disp):", addr);
1121 print_operand (file, XEXP (addr, 1), 0);
1123 else if (GET_CODE (addr) == PLUS)
1125 print_operand_address (file, XEXP (addr,0));
1126 if (REGNO (XEXP (addr, 0)) == REG_X)
1127 fatal_insn ("internal compiler error. Bad address:"
1130 print_operand (file, XEXP (addr,1), code);
1133 print_operand_address (file, addr);
1135 else if (GET_CODE (x) == CONST_DOUBLE)
1139 if (GET_MODE (x) != SFmode)
1140 fatal_insn ("internal compiler error. Unknown mode:", x);
1141 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1142 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1143 fprintf (file, "0x%lx", val);
1145 else if (code == 'j')
1146 fputs (cond_string (GET_CODE (x)), file);
1147 else if (code == 'k')
1148 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
1150 print_operand_address (file, x);
1153 /* Recognize operand OP of mode MODE used in call instructions. */
1156 call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1158 if (GET_CODE (op) == MEM)
1160 rtx inside = XEXP (op, 0);
1161 if (register_operand (inside, Pmode))
1163 if (CONSTANT_ADDRESS_P (inside))
1169 /* Update the condition code in the INSN. */
1172 notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
1176 switch (get_attr_cc (insn))
1179 /* Insn does not affect CC at all. */
1187 set = single_set (insn);
1191 cc_status.flags |= CC_NO_OVERFLOW;
1192 cc_status.value1 = SET_DEST (set);
1197 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1198 The V flag may or may not be known but that's ok because
1199 alter_cond will change tests to use EQ/NE. */
1200 set = single_set (insn);
1204 cc_status.value1 = SET_DEST (set);
1205 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1210 set = single_set (insn);
1213 cc_status.value1 = SET_SRC (set);
1217 /* Insn doesn't leave CC in a usable state. */
1220 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1221 set = single_set (insn);
1224 rtx src = SET_SRC (set);
1226 if (GET_CODE (src) == ASHIFTRT
1227 && GET_MODE (src) == QImode)
1229 rtx x = XEXP (src, 1);
1231 if (GET_CODE (x) == CONST_INT
1235 cc_status.value1 = SET_DEST (set);
1236 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1244 /* Return maximum number of consecutive registers of
1245 class CLASS needed to hold a value of mode MODE. */
1248 class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,enum machine_mode mode)
1250 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1253 /* Choose mode for jump insn:
1254 1 - relative jump in range -63 <= x <= 62 ;
1255 2 - relative jump in range -2046 <= x <= 2045 ;
1256 3 - absolute jump (only for ATmega[16]03). */
1259 avr_jump_mode (rtx x, rtx insn)
1261 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1262 ? XEXP (x, 0) : x));
1263 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1264 int jump_distance = cur_addr - dest_addr;
1266 if (-63 <= jump_distance && jump_distance <= 62)
1268 else if (-2046 <= jump_distance && jump_distance <= 2045)
1276 /* return an AVR condition jump commands.
1277 X is a comparison RTX.
1278 LEN is a number returned by avr_jump_mode function.
1279 if REVERSE nonzero then condition code in X must be reversed. */
1282 ret_cond_branch (rtx x, int len, int reverse)
1284 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1289 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1290 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1292 len == 2 ? (AS1 (breq,.+4) CR_TAB
1293 AS1 (brmi,.+2) CR_TAB
1295 (AS1 (breq,.+6) CR_TAB
1296 AS1 (brmi,.+4) CR_TAB
1300 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1302 len == 2 ? (AS1 (breq,.+4) CR_TAB
1303 AS1 (brlt,.+2) CR_TAB
1305 (AS1 (breq,.+6) CR_TAB
1306 AS1 (brlt,.+4) CR_TAB
1309 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1311 len == 2 ? (AS1 (breq,.+4) CR_TAB
1312 AS1 (brlo,.+2) CR_TAB
1314 (AS1 (breq,.+6) CR_TAB
1315 AS1 (brlo,.+4) CR_TAB
1318 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1319 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1321 len == 2 ? (AS1 (breq,.+2) CR_TAB
1322 AS1 (brpl,.+2) CR_TAB
1324 (AS1 (breq,.+2) CR_TAB
1325 AS1 (brpl,.+4) CR_TAB
1328 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1330 len == 2 ? (AS1 (breq,.+2) CR_TAB
1331 AS1 (brge,.+2) CR_TAB
1333 (AS1 (breq,.+2) CR_TAB
1334 AS1 (brge,.+4) CR_TAB
1337 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1339 len == 2 ? (AS1 (breq,.+2) CR_TAB
1340 AS1 (brsh,.+2) CR_TAB
1342 (AS1 (breq,.+2) CR_TAB
1343 AS1 (brsh,.+4) CR_TAB
1351 return AS1 (br%k1,%0);
1353 return (AS1 (br%j1,.+2) CR_TAB
1356 return (AS1 (br%j1,.+4) CR_TAB
1365 return AS1 (br%j1,%0);
1367 return (AS1 (br%k1,.+2) CR_TAB
1370 return (AS1 (br%k1,.+4) CR_TAB
1378 /* Predicate function for immediate operand which fits to byte (8bit) */
1381 byte_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1383 return (GET_CODE (op) == CONST_INT
1384 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1387 /* Output all insn addresses and their sizes into the assembly language
1388 output file. This is helpful for debugging whether the length attributes
1389 in the md file are correct.
1390 Output insn cost for next insn. */
1393 final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
1394 int num_operands ATTRIBUTE_UNUSED)
1396 int uid = INSN_UID (insn);
1398 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1400 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1401 INSN_ADDRESSES (uid),
1402 INSN_ADDRESSES (uid) - last_insn_address,
1403 rtx_cost (PATTERN (insn), INSN));
1405 last_insn_address = INSN_ADDRESSES (uid);
1408 /* Return 0 if undefined, 1 if always true or always false. */
1411 avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE operator, rtx x)
1413 unsigned int max = (mode == QImode ? 0xff :
1414 mode == HImode ? 0xffff :
1415 mode == SImode ? 0xffffffff : 0);
1416 if (max && operator && GET_CODE (x) == CONST_INT)
1418 if (unsigned_condition (operator) != operator)
1421 if (max != (INTVAL (x) & max)
1422 && INTVAL (x) != 0xff)
1429 /* Returns nonzero if REGNO is the number of a hard
1430 register in which function arguments are sometimes passed. */
1433 function_arg_regno_p(int r)
1435 return (r >= 8 && r <= 25);
1438 /* Initializing the variable cum for the state at the beginning
1439 of the argument list. */
1442 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
1443 tree fndecl ATTRIBUTE_UNUSED)
1446 cum->regno = FIRST_CUM_REG;
1447 if (!libname && fntype)
1449 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1450 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1451 != void_type_node));
1457 /* Returns the number of registers to allocate for a function argument. */
1460 avr_num_arg_regs (enum machine_mode mode, tree type)
1464 if (mode == BLKmode)
1465 size = int_size_in_bytes (type);
1467 size = GET_MODE_SIZE (mode);
1469 /* Align all function arguments to start in even-numbered registers.
1470 Odd-sized arguments leave holes above them. */
1472 return (size + 1) & ~1;
1475 /* Controls whether a function argument is passed
1476 in a register, and which register. */
1479 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1480 int named ATTRIBUTE_UNUSED)
1482 int bytes = avr_num_arg_regs (mode, type);
1484 if (cum->nregs && bytes <= cum->nregs)
1485 return gen_rtx_REG (mode, cum->regno - bytes);
1490 /* Update the summarizer variable CUM to advance past an argument
1491 in the argument list. */
1494 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1495 int named ATTRIBUTE_UNUSED)
1497 int bytes = avr_num_arg_regs (mode, type);
1499 cum->nregs -= bytes;
1500 cum->regno -= bytes;
1502 if (cum->nregs <= 0)
1505 cum->regno = FIRST_CUM_REG;
1509 /***********************************************************************
1510 Functions for outputting various mov's for a various modes
1511 ************************************************************************/
1513 output_movqi (rtx insn, rtx operands[], int *l)
1516 rtx dest = operands[0];
1517 rtx src = operands[1];
1525 if (register_operand (dest, QImode))
1527 if (register_operand (src, QImode)) /* mov r,r */
1529 if (test_hard_reg_class (STACK_REG, dest))
1530 return AS2 (out,%0,%1);
1531 else if (test_hard_reg_class (STACK_REG, src))
1532 return AS2 (in,%0,%1);
1534 return AS2 (mov,%0,%1);
1536 else if (CONSTANT_P (src))
1538 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1539 return AS2 (ldi,%0,lo8(%1));
1541 if (GET_CODE (src) == CONST_INT)
1543 if (src == const0_rtx) /* mov r,L */
1544 return AS1 (clr,%0);
1545 else if (src == const1_rtx)
1548 return (AS1 (clr,%0) CR_TAB
1551 else if (src == constm1_rtx)
1553 /* Immediate constants -1 to any register */
1555 return (AS1 (clr,%0) CR_TAB
1560 int bit_nr = exact_log2 (INTVAL (src));
1566 output_asm_insn ((AS1 (clr,%0) CR_TAB
1569 avr_output_bld (operands, bit_nr);
1576 /* Last resort, larger than loading from memory. */
1578 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1579 AS2 (ldi,r31,lo8(%1)) CR_TAB
1580 AS2 (mov,%0,r31) CR_TAB
1581 AS2 (mov,r31,__tmp_reg__));
1583 else if (GET_CODE (src) == MEM)
1584 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1586 else if (GET_CODE (dest) == MEM)
1588 const char *template;
1590 if (src == const0_rtx)
1591 operands[1] = zero_reg_rtx;
1593 template = out_movqi_mr_r (insn, operands, real_l);
1596 output_asm_insn (template, operands);
1605 output_movhi (rtx insn, rtx operands[], int *l)
1608 rtx dest = operands[0];
1609 rtx src = operands[1];
1615 if (register_operand (dest, HImode))
1617 if (register_operand (src, HImode)) /* mov r,r */
1619 if (test_hard_reg_class (STACK_REG, dest))
1621 if (TARGET_TINY_STACK)
1624 return AS2 (out,__SP_L__,%A1);
1626 else if (TARGET_NO_INTERRUPTS)
1629 return (AS2 (out,__SP_H__,%B1) CR_TAB
1630 AS2 (out,__SP_L__,%A1));
1634 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1636 AS2 (out,__SP_H__,%B1) CR_TAB
1637 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1638 AS2 (out,__SP_L__,%A1));
1640 else if (test_hard_reg_class (STACK_REG, src))
1643 return (AS2 (in,%A0,__SP_L__) CR_TAB
1644 AS2 (in,%B0,__SP_H__));
1650 return (AS2 (movw,%0,%1));
1653 if (true_regnum (dest) > true_regnum (src))
1656 return (AS2 (mov,%B0,%B1) CR_TAB
1662 return (AS2 (mov,%A0,%A1) CR_TAB
1666 else if (CONSTANT_P (src))
1668 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1671 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1672 AS2 (ldi,%B0,hi8(%1)));
1675 if (GET_CODE (src) == CONST_INT)
1677 if (src == const0_rtx) /* mov r,L */
1680 return (AS1 (clr,%A0) CR_TAB
1683 else if (src == const1_rtx)
1686 return (AS1 (clr,%A0) CR_TAB
1687 AS1 (clr,%B0) CR_TAB
1690 else if (src == constm1_rtx)
1692 /* Immediate constants -1 to any register */
1694 return (AS1 (clr,%0) CR_TAB
1695 AS1 (dec,%A0) CR_TAB
1700 int bit_nr = exact_log2 (INTVAL (src));
1706 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1707 AS1 (clr,%B0) CR_TAB
1710 avr_output_bld (operands, bit_nr);
1716 if ((INTVAL (src) & 0xff) == 0)
1719 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1720 AS1 (clr,%A0) CR_TAB
1721 AS2 (ldi,r31,hi8(%1)) CR_TAB
1722 AS2 (mov,%B0,r31) CR_TAB
1723 AS2 (mov,r31,__tmp_reg__));
1725 else if ((INTVAL (src) & 0xff00) == 0)
1728 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1729 AS2 (ldi,r31,lo8(%1)) CR_TAB
1730 AS2 (mov,%A0,r31) CR_TAB
1731 AS1 (clr,%B0) CR_TAB
1732 AS2 (mov,r31,__tmp_reg__));
1736 /* Last resort, equal to loading from memory. */
1738 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1739 AS2 (ldi,r31,lo8(%1)) CR_TAB
1740 AS2 (mov,%A0,r31) CR_TAB
1741 AS2 (ldi,r31,hi8(%1)) CR_TAB
1742 AS2 (mov,%B0,r31) CR_TAB
1743 AS2 (mov,r31,__tmp_reg__));
1745 else if (GET_CODE (src) == MEM)
1746 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1748 else if (GET_CODE (dest) == MEM)
1750 const char *template;
1752 if (src == const0_rtx)
1753 operands[1] = zero_reg_rtx;
1755 template = out_movhi_mr_r (insn, operands, real_l);
1758 output_asm_insn (template, operands);
1763 fatal_insn ("invalid insn:", insn);
1768 out_movqi_r_mr (rtx insn, rtx op[], int *l)
1772 rtx x = XEXP (src, 0);
1778 if (CONSTANT_ADDRESS_P (x))
1780 if (avr_io_address_p (x, 1))
1783 return AS2 (in,%0,%1-0x20);
1786 return AS2 (lds,%0,%1);
1788 /* memory access by reg+disp */
1789 else if (GET_CODE (x) == PLUS
1790 && REG_P (XEXP (x,0))
1791 && GET_CODE (XEXP (x,1)) == CONST_INT)
1793 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
1795 int disp = INTVAL (XEXP (x,1));
1796 if (REGNO (XEXP (x,0)) != REG_Y)
1797 fatal_insn ("incorrect insn:",insn);
1799 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1800 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1801 AS2 (ldd,%0,Y+63) CR_TAB
1802 AS2 (sbiw,r28,%o1-63));
1804 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1805 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1806 AS2 (ld,%0,Y) CR_TAB
1807 AS2 (subi,r28,lo8(%o1)) CR_TAB
1808 AS2 (sbci,r29,hi8(%o1)));
1810 else if (REGNO (XEXP (x,0)) == REG_X)
1812 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1813 it but I have this situation with extremal optimizing options. */
1814 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
1815 || reg_unused_after (insn, XEXP (x,0)))
1816 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1819 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1820 AS2 (ld,%0,X) CR_TAB
1821 AS2 (sbiw,r26,%o1));
1824 return AS2 (ldd,%0,%1);
1827 return AS2 (ld,%0,%1);
1831 out_movhi_r_mr (rtx insn, rtx op[], int *l)
1835 rtx base = XEXP (src, 0);
1836 int reg_dest = true_regnum (dest);
1837 int reg_base = true_regnum (base);
1845 if (reg_dest == reg_base) /* R = (R) */
1848 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1849 AS2 (ld,%B0,%1) CR_TAB
1850 AS2 (mov,%A0,__tmp_reg__));
1852 else if (reg_base == REG_X) /* (R26) */
1854 if (reg_unused_after (insn, base))
1857 return (AS2 (ld,%A0,X+) CR_TAB
1861 return (AS2 (ld,%A0,X+) CR_TAB
1862 AS2 (ld,%B0,X) CR_TAB
1868 return (AS2 (ld,%A0,%1) CR_TAB
1869 AS2 (ldd,%B0,%1+1));
1872 else if (GET_CODE (base) == PLUS) /* (R + i) */
1874 int disp = INTVAL (XEXP (base, 1));
1875 int reg_base = true_regnum (XEXP (base, 0));
1877 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
1879 if (REGNO (XEXP (base, 0)) != REG_Y)
1880 fatal_insn ("incorrect insn:",insn);
1882 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1883 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
1884 AS2 (ldd,%A0,Y+62) CR_TAB
1885 AS2 (ldd,%B0,Y+63) CR_TAB
1886 AS2 (sbiw,r28,%o1-62));
1888 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1889 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1890 AS2 (ld,%A0,Y) CR_TAB
1891 AS2 (ldd,%B0,Y+1) CR_TAB
1892 AS2 (subi,r28,lo8(%o1)) CR_TAB
1893 AS2 (sbci,r29,hi8(%o1)));
1895 if (reg_base == REG_X)
1897 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1898 it but I have this situation with extremal
1899 optimization options. */
1902 if (reg_base == reg_dest)
1903 return (AS2 (adiw,r26,%o1) CR_TAB
1904 AS2 (ld,__tmp_reg__,X+) CR_TAB
1905 AS2 (ld,%B0,X) CR_TAB
1906 AS2 (mov,%A0,__tmp_reg__));
1908 return (AS2 (adiw,r26,%o1) CR_TAB
1909 AS2 (ld,%A0,X+) CR_TAB
1910 AS2 (ld,%B0,X) CR_TAB
1911 AS2 (sbiw,r26,%o1+1));
1914 if (reg_base == reg_dest)
1917 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
1918 AS2 (ldd,%B0,%B1) CR_TAB
1919 AS2 (mov,%A0,__tmp_reg__));
1923 return (AS2 (ldd,%A0,%A1) CR_TAB
1926 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
1928 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1929 fatal_insn ("incorrect insn:", insn);
1932 return (AS2 (ld,%B0,%1) CR_TAB
1935 else if (GET_CODE (base) == POST_INC) /* (R++) */
1937 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1938 fatal_insn ("incorrect insn:", insn);
1941 return (AS2 (ld,%A0,%1) CR_TAB
1944 else if (CONSTANT_ADDRESS_P (base))
1946 if (avr_io_address_p (base, 2))
1949 return (AS2 (in,%A0,%A1-0x20) CR_TAB
1950 AS2 (in,%B0,%B1-0x20));
1953 return (AS2 (lds,%A0,%A1) CR_TAB
1957 fatal_insn ("unknown move insn:",insn);
1962 out_movsi_r_mr (rtx insn, rtx op[], int *l)
1966 rtx base = XEXP (src, 0);
1967 int reg_dest = true_regnum (dest);
1968 int reg_base = true_regnum (base);
1976 if (reg_base == REG_X) /* (R26) */
1978 if (reg_dest == REG_X)
1979 /* "ld r26,-X" is undefined */
1980 return *l=7, (AS2 (adiw,r26,3) CR_TAB
1981 AS2 (ld,r29,X) CR_TAB
1982 AS2 (ld,r28,-X) CR_TAB
1983 AS2 (ld,__tmp_reg__,-X) CR_TAB
1984 AS2 (sbiw,r26,1) CR_TAB
1985 AS2 (ld,r26,X) CR_TAB
1986 AS2 (mov,r27,__tmp_reg__));
1987 else if (reg_dest == REG_X - 2)
1988 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
1989 AS2 (ld,%B0,X+) CR_TAB
1990 AS2 (ld,__tmp_reg__,X+) CR_TAB
1991 AS2 (ld,%D0,X) CR_TAB
1992 AS2 (mov,%C0,__tmp_reg__));
1993 else if (reg_unused_after (insn, base))
1994 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
1995 AS2 (ld,%B0,X+) CR_TAB
1996 AS2 (ld,%C0,X+) CR_TAB
1999 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2000 AS2 (ld,%B0,X+) CR_TAB
2001 AS2 (ld,%C0,X+) CR_TAB
2002 AS2 (ld,%D0,X) CR_TAB
2007 if (reg_dest == reg_base)
2008 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2009 AS2 (ldd,%C0,%1+2) CR_TAB
2010 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2011 AS2 (ld,%A0,%1) CR_TAB
2012 AS2 (mov,%B0,__tmp_reg__));
2013 else if (reg_base == reg_dest + 2)
2014 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2015 AS2 (ldd,%B0,%1+1) CR_TAB
2016 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2017 AS2 (ldd,%D0,%1+3) CR_TAB
2018 AS2 (mov,%C0,__tmp_reg__));
2020 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2021 AS2 (ldd,%B0,%1+1) CR_TAB
2022 AS2 (ldd,%C0,%1+2) CR_TAB
2023 AS2 (ldd,%D0,%1+3));
2026 else if (GET_CODE (base) == PLUS) /* (R + i) */
2028 int disp = INTVAL (XEXP (base, 1));
2030 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2032 if (REGNO (XEXP (base, 0)) != REG_Y)
2033 fatal_insn ("incorrect insn:",insn);
2035 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2036 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2037 AS2 (ldd,%A0,Y+60) CR_TAB
2038 AS2 (ldd,%B0,Y+61) CR_TAB
2039 AS2 (ldd,%C0,Y+62) CR_TAB
2040 AS2 (ldd,%D0,Y+63) CR_TAB
2041 AS2 (sbiw,r28,%o1-60));
2043 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2044 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2045 AS2 (ld,%A0,Y) CR_TAB
2046 AS2 (ldd,%B0,Y+1) CR_TAB
2047 AS2 (ldd,%C0,Y+2) CR_TAB
2048 AS2 (ldd,%D0,Y+3) CR_TAB
2049 AS2 (subi,r28,lo8(%o1)) CR_TAB
2050 AS2 (sbci,r29,hi8(%o1)));
2053 reg_base = true_regnum (XEXP (base, 0));
2054 if (reg_base == REG_X)
2057 if (reg_dest == REG_X)
2060 /* "ld r26,-X" is undefined */
2061 return (AS2 (adiw,r26,%o1+3) CR_TAB
2062 AS2 (ld,r29,X) CR_TAB
2063 AS2 (ld,r28,-X) CR_TAB
2064 AS2 (ld,__tmp_reg__,-X) CR_TAB
2065 AS2 (sbiw,r26,1) CR_TAB
2066 AS2 (ld,r26,X) CR_TAB
2067 AS2 (mov,r27,__tmp_reg__));
2070 if (reg_dest == REG_X - 2)
2071 return (AS2 (adiw,r26,%o1) CR_TAB
2072 AS2 (ld,r24,X+) CR_TAB
2073 AS2 (ld,r25,X+) CR_TAB
2074 AS2 (ld,__tmp_reg__,X+) CR_TAB
2075 AS2 (ld,r27,X) CR_TAB
2076 AS2 (mov,r26,__tmp_reg__));
2078 return (AS2 (adiw,r26,%o1) CR_TAB
2079 AS2 (ld,%A0,X+) CR_TAB
2080 AS2 (ld,%B0,X+) CR_TAB
2081 AS2 (ld,%C0,X+) CR_TAB
2082 AS2 (ld,%D0,X) CR_TAB
2083 AS2 (sbiw,r26,%o1+3));
2085 if (reg_dest == reg_base)
2086 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2087 AS2 (ldd,%C0,%C1) CR_TAB
2088 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2089 AS2 (ldd,%A0,%A1) CR_TAB
2090 AS2 (mov,%B0,__tmp_reg__));
2091 else if (reg_dest == reg_base - 2)
2092 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2093 AS2 (ldd,%B0,%B1) CR_TAB
2094 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2095 AS2 (ldd,%D0,%D1) CR_TAB
2096 AS2 (mov,%C0,__tmp_reg__));
2097 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2098 AS2 (ldd,%B0,%B1) CR_TAB
2099 AS2 (ldd,%C0,%C1) CR_TAB
2102 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2103 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2104 AS2 (ld,%C0,%1) CR_TAB
2105 AS2 (ld,%B0,%1) CR_TAB
2107 else if (GET_CODE (base) == POST_INC) /* (R++) */
2108 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2109 AS2 (ld,%B0,%1) CR_TAB
2110 AS2 (ld,%C0,%1) CR_TAB
2112 else if (CONSTANT_ADDRESS_P (base))
2113 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2114 AS2 (lds,%B0,%B1) CR_TAB
2115 AS2 (lds,%C0,%C1) CR_TAB
2118 fatal_insn ("unknown move insn:",insn);
2123 out_movsi_mr_r (rtx insn, rtx op[], int *l)
2127 rtx base = XEXP (dest, 0);
2128 int reg_base = true_regnum (base);
2129 int reg_src = true_regnum (src);
2135 if (CONSTANT_ADDRESS_P (base))
2136 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2137 AS2 (sts,%B0,%B1) CR_TAB
2138 AS2 (sts,%C0,%C1) CR_TAB
2140 if (reg_base > 0) /* (r) */
2142 if (reg_base == REG_X) /* (R26) */
2144 if (reg_src == REG_X)
2146 /* "st X+,r26" is undefined */
2147 if (reg_unused_after (insn, base))
2148 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2149 AS2 (st,X,r26) CR_TAB
2150 AS2 (adiw,r26,1) CR_TAB
2151 AS2 (st,X+,__tmp_reg__) CR_TAB
2152 AS2 (st,X+,r28) CR_TAB
2155 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2156 AS2 (st,X,r26) CR_TAB
2157 AS2 (adiw,r26,1) CR_TAB
2158 AS2 (st,X+,__tmp_reg__) CR_TAB
2159 AS2 (st,X+,r28) CR_TAB
2160 AS2 (st,X,r29) CR_TAB
2163 else if (reg_base == reg_src + 2)
2165 if (reg_unused_after (insn, base))
2166 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2167 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2168 AS2 (st,%0+,%A1) CR_TAB
2169 AS2 (st,%0+,%B1) CR_TAB
2170 AS2 (st,%0+,__zero_reg__) CR_TAB
2171 AS2 (st,%0,__tmp_reg__) CR_TAB
2172 AS1 (clr,__zero_reg__));
2174 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2175 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2176 AS2 (st,%0+,%A1) CR_TAB
2177 AS2 (st,%0+,%B1) CR_TAB
2178 AS2 (st,%0+,__zero_reg__) CR_TAB
2179 AS2 (st,%0,__tmp_reg__) CR_TAB
2180 AS1 (clr,__zero_reg__) CR_TAB
2183 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2184 AS2 (st,%0+,%B1) CR_TAB
2185 AS2 (st,%0+,%C1) CR_TAB
2186 AS2 (st,%0,%D1) CR_TAB
2190 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2191 AS2 (std,%0+1,%B1) CR_TAB
2192 AS2 (std,%0+2,%C1) CR_TAB
2193 AS2 (std,%0+3,%D1));
2195 else if (GET_CODE (base) == PLUS) /* (R + i) */
2197 int disp = INTVAL (XEXP (base, 1));
2198 reg_base = REGNO (XEXP (base, 0));
2199 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2201 if (reg_base != REG_Y)
2202 fatal_insn ("incorrect insn:",insn);
2204 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2205 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2206 AS2 (std,Y+60,%A1) CR_TAB
2207 AS2 (std,Y+61,%B1) CR_TAB
2208 AS2 (std,Y+62,%C1) CR_TAB
2209 AS2 (std,Y+63,%D1) CR_TAB
2210 AS2 (sbiw,r28,%o0-60));
2212 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2213 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2214 AS2 (st,Y,%A1) CR_TAB
2215 AS2 (std,Y+1,%B1) CR_TAB
2216 AS2 (std,Y+2,%C1) CR_TAB
2217 AS2 (std,Y+3,%D1) CR_TAB
2218 AS2 (subi,r28,lo8(%o0)) CR_TAB
2219 AS2 (sbci,r29,hi8(%o0)));
2221 if (reg_base == REG_X)
2224 if (reg_src == REG_X)
2227 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2228 AS2 (mov,__zero_reg__,r27) CR_TAB
2229 AS2 (adiw,r26,%o0) CR_TAB
2230 AS2 (st,X+,__tmp_reg__) CR_TAB
2231 AS2 (st,X+,__zero_reg__) CR_TAB
2232 AS2 (st,X+,r28) CR_TAB
2233 AS2 (st,X,r29) CR_TAB
2234 AS1 (clr,__zero_reg__) CR_TAB
2235 AS2 (sbiw,r26,%o0+3));
2237 else if (reg_src == REG_X - 2)
2240 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2241 AS2 (mov,__zero_reg__,r27) CR_TAB
2242 AS2 (adiw,r26,%o0) CR_TAB
2243 AS2 (st,X+,r24) CR_TAB
2244 AS2 (st,X+,r25) CR_TAB
2245 AS2 (st,X+,__tmp_reg__) CR_TAB
2246 AS2 (st,X,__zero_reg__) CR_TAB
2247 AS1 (clr,__zero_reg__) CR_TAB
2248 AS2 (sbiw,r26,%o0+3));
2251 return (AS2 (adiw,r26,%o0) CR_TAB
2252 AS2 (st,X+,%A1) CR_TAB
2253 AS2 (st,X+,%B1) CR_TAB
2254 AS2 (st,X+,%C1) CR_TAB
2255 AS2 (st,X,%D1) CR_TAB
2256 AS2 (sbiw,r26,%o0+3));
2258 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2259 AS2 (std,%B0,%B1) CR_TAB
2260 AS2 (std,%C0,%C1) CR_TAB
2263 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2264 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2265 AS2 (st,%0,%C1) CR_TAB
2266 AS2 (st,%0,%B1) CR_TAB
2268 else if (GET_CODE (base) == POST_INC) /* (R++) */
2269 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2270 AS2 (st,%0,%B1) CR_TAB
2271 AS2 (st,%0,%C1) CR_TAB
2273 fatal_insn ("unknown move insn:",insn);
2278 output_movsisf(rtx insn, rtx operands[], int *l)
2281 rtx dest = operands[0];
2282 rtx src = operands[1];
2288 if (register_operand (dest, VOIDmode))
2290 if (register_operand (src, VOIDmode)) /* mov r,r */
2292 if (true_regnum (dest) > true_regnum (src))
2297 return (AS2 (movw,%C0,%C1) CR_TAB
2298 AS2 (movw,%A0,%A1));
2301 return (AS2 (mov,%D0,%D1) CR_TAB
2302 AS2 (mov,%C0,%C1) CR_TAB
2303 AS2 (mov,%B0,%B1) CR_TAB
2311 return (AS2 (movw,%A0,%A1) CR_TAB
2312 AS2 (movw,%C0,%C1));
2315 return (AS2 (mov,%A0,%A1) CR_TAB
2316 AS2 (mov,%B0,%B1) CR_TAB
2317 AS2 (mov,%C0,%C1) CR_TAB
2321 else if (CONSTANT_P (src))
2323 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2326 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2327 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2328 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2329 AS2 (ldi,%D0,hhi8(%1)));
2332 if (GET_CODE (src) == CONST_INT)
2334 const char *const clr_op0 =
2335 AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
2336 AS1 (clr,%B0) CR_TAB
2338 : (AS1 (clr,%A0) CR_TAB
2339 AS1 (clr,%B0) CR_TAB
2340 AS1 (clr,%C0) CR_TAB
2343 if (src == const0_rtx) /* mov r,L */
2345 *l = AVR_ENHANCED ? 3 : 4;
2348 else if (src == const1_rtx)
2351 output_asm_insn (clr_op0, operands);
2352 *l = AVR_ENHANCED ? 4 : 5;
2353 return AS1 (inc,%A0);
2355 else if (src == constm1_rtx)
2357 /* Immediate constants -1 to any register */
2361 return (AS1 (clr,%A0) CR_TAB
2362 AS1 (dec,%A0) CR_TAB
2363 AS2 (mov,%B0,%A0) CR_TAB
2364 AS2 (movw,%C0,%A0));
2367 return (AS1 (clr,%A0) CR_TAB
2368 AS1 (dec,%A0) CR_TAB
2369 AS2 (mov,%B0,%A0) CR_TAB
2370 AS2 (mov,%C0,%A0) CR_TAB
2375 int bit_nr = exact_log2 (INTVAL (src));
2379 *l = AVR_ENHANCED ? 5 : 6;
2382 output_asm_insn (clr_op0, operands);
2383 output_asm_insn ("set", operands);
2386 avr_output_bld (operands, bit_nr);
2393 /* Last resort, better than loading from memory. */
2395 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2396 AS2 (ldi,r31,lo8(%1)) CR_TAB
2397 AS2 (mov,%A0,r31) CR_TAB
2398 AS2 (ldi,r31,hi8(%1)) CR_TAB
2399 AS2 (mov,%B0,r31) CR_TAB
2400 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2401 AS2 (mov,%C0,r31) CR_TAB
2402 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2403 AS2 (mov,%D0,r31) CR_TAB
2404 AS2 (mov,r31,__tmp_reg__));
2406 else if (GET_CODE (src) == MEM)
2407 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2409 else if (GET_CODE (dest) == MEM)
2411 const char *template;
2413 if (src == const0_rtx)
2414 operands[1] = zero_reg_rtx;
2416 template = out_movsi_mr_r (insn, operands, real_l);
2419 output_asm_insn (template, operands);
2424 fatal_insn ("invalid insn:", insn);
2429 out_movqi_mr_r (rtx insn, rtx op[], int *l)
2433 rtx x = XEXP (dest, 0);
2439 if (CONSTANT_ADDRESS_P (x))
2441 if (avr_io_address_p (x, 1))
2444 return AS2 (out,%0-0x20,%1);
2447 return AS2 (sts,%0,%1);
2449 /* memory access by reg+disp */
2450 else if (GET_CODE (x) == PLUS
2451 && REG_P (XEXP (x,0))
2452 && GET_CODE (XEXP (x,1)) == CONST_INT)
2454 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
2456 int disp = INTVAL (XEXP (x,1));
2457 if (REGNO (XEXP (x,0)) != REG_Y)
2458 fatal_insn ("incorrect insn:",insn);
2460 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2461 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2462 AS2 (std,Y+63,%1) CR_TAB
2463 AS2 (sbiw,r28,%o0-63));
2465 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2466 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2467 AS2 (st,Y,%1) CR_TAB
2468 AS2 (subi,r28,lo8(%o0)) CR_TAB
2469 AS2 (sbci,r29,hi8(%o0)));
2471 else if (REGNO (XEXP (x,0)) == REG_X)
2473 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
2475 if (reg_unused_after (insn, XEXP (x,0)))
2476 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2477 AS2 (adiw,r26,%o0) CR_TAB
2478 AS2 (st,X,__tmp_reg__));
2480 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2481 AS2 (adiw,r26,%o0) CR_TAB
2482 AS2 (st,X,__tmp_reg__) CR_TAB
2483 AS2 (sbiw,r26,%o0));
2487 if (reg_unused_after (insn, XEXP (x,0)))
2488 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2491 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2492 AS2 (st,X,%1) CR_TAB
2493 AS2 (sbiw,r26,%o0));
2497 return AS2 (std,%0,%1);
2500 return AS2 (st,%0,%1);
2504 out_movhi_mr_r (rtx insn, rtx op[], int *l)
2508 rtx base = XEXP (dest, 0);
2509 int reg_base = true_regnum (base);
2510 int reg_src = true_regnum (src);
2514 if (CONSTANT_ADDRESS_P (base))
2516 if (avr_io_address_p (base, 2))
2519 return (AS2 (out,%B0-0x20,%B1) CR_TAB
2520 AS2 (out,%A0-0x20,%A1));
2522 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2527 if (reg_base == REG_X)
2529 if (reg_src == REG_X)
2531 /* "st X+,r26" is undefined */
2532 if (reg_unused_after (insn, src))
2533 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2534 AS2 (st,X,r26) CR_TAB
2535 AS2 (adiw,r26,1) CR_TAB
2536 AS2 (st,X,__tmp_reg__));
2538 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2539 AS2 (st,X,r26) CR_TAB
2540 AS2 (adiw,r26,1) CR_TAB
2541 AS2 (st,X,__tmp_reg__) CR_TAB
2546 if (reg_unused_after (insn, base))
2547 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2550 return *l=3, (AS2 (st ,X+,%A1) CR_TAB
2551 AS2 (st ,X,%B1) CR_TAB
2556 return *l=2, (AS2 (st ,%0,%A1) CR_TAB
2557 AS2 (std,%0+1,%B1));
2559 else if (GET_CODE (base) == PLUS)
2561 int disp = INTVAL (XEXP (base, 1));
2562 reg_base = REGNO (XEXP (base, 0));
2563 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2565 if (reg_base != REG_Y)
2566 fatal_insn ("incorrect insn:",insn);
2568 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2569 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
2570 AS2 (std,Y+62,%A1) CR_TAB
2571 AS2 (std,Y+63,%B1) CR_TAB
2572 AS2 (sbiw,r28,%o0-62));
2574 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2575 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2576 AS2 (st,Y,%A1) CR_TAB
2577 AS2 (std,Y+1,%B1) CR_TAB
2578 AS2 (subi,r28,lo8(%o0)) CR_TAB
2579 AS2 (sbci,r29,hi8(%o0)));
2581 if (reg_base == REG_X)
2584 if (reg_src == REG_X)
2587 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2588 AS2 (mov,__zero_reg__,r27) CR_TAB
2589 AS2 (adiw,r26,%o0) CR_TAB
2590 AS2 (st,X+,__tmp_reg__) CR_TAB
2591 AS2 (st,X,__zero_reg__) CR_TAB
2592 AS1 (clr,__zero_reg__) CR_TAB
2593 AS2 (sbiw,r26,%o0+1));
2596 return (AS2 (adiw,r26,%o0) CR_TAB
2597 AS2 (st,X+,%A1) CR_TAB
2598 AS2 (st,X,%B1) CR_TAB
2599 AS2 (sbiw,r26,%o0+1));
2601 return *l=2, (AS2 (std,%A0,%A1) CR_TAB
2604 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2605 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2607 else if (GET_CODE (base) == POST_INC) /* (R++) */
2608 return *l=2, (AS2 (st,%0,%A1) CR_TAB
2610 fatal_insn ("unknown move insn:",insn);
2614 /* Return 1 if frame pointer for current function required. */
2617 frame_pointer_required_p (void)
2619 return (current_function_calls_alloca
2620 || current_function_args_info.nregs == 0
2621 || get_frame_size () > 0);
2624 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2627 compare_condition (rtx insn)
2629 rtx next = next_real_insn (insn);
2630 RTX_CODE cond = UNKNOWN;
2631 if (next && GET_CODE (next) == JUMP_INSN)
2633 rtx pat = PATTERN (next);
2634 rtx src = SET_SRC (pat);
2635 rtx t = XEXP (src, 0);
2636 cond = GET_CODE (t);
2641 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2644 compare_sign_p (rtx insn)
2646 RTX_CODE cond = compare_condition (insn);
2647 return (cond == GE || cond == LT);
2650 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2651 that needs to be swapped (GT, GTU, LE, LEU). */
2654 compare_diff_p (rtx insn)
2656 RTX_CODE cond = compare_condition (insn);
2657 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2660 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2663 compare_eq_p (rtx insn)
2665 RTX_CODE cond = compare_condition (insn);
2666 return (cond == EQ || cond == NE);
2670 /* Output test instruction for HImode. */
2673 out_tsthi (rtx insn, int *l)
2675 if (compare_sign_p (insn))
2678 return AS1 (tst,%B0);
2680 if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2681 && compare_eq_p (insn))
2683 /* Faster than sbiw if we can clobber the operand. */
2685 return AS2 (or,%A0,%B0);
2687 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2690 return AS2 (sbiw,%0,0);
2693 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2694 AS2 (cpc,%B0,__zero_reg__));
2698 /* Output test instruction for SImode. */
2701 out_tstsi (rtx insn, int *l)
2703 if (compare_sign_p (insn))
2706 return AS1 (tst,%D0);
2708 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2711 return (AS2 (sbiw,%A0,0) CR_TAB
2712 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2713 AS2 (cpc,%D0,__zero_reg__));
2716 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2717 AS2 (cpc,%B0,__zero_reg__) CR_TAB
2718 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2719 AS2 (cpc,%D0,__zero_reg__));
2723 /* Generate asm equivalent for various shifts.
2724 Shift count is a CONST_INT, MEM or REG.
2725 This only handles cases that are not already
2726 carefully hand-optimized in ?sh??i3_out. */
2729 out_shift_with_cnt (const char *template, rtx insn, rtx operands[],
2730 int *len, int t_len)
2734 int second_label = 1;
2735 int saved_in_tmp = 0;
2736 int use_zero_reg = 0;
2738 op[0] = operands[0];
2739 op[1] = operands[1];
2740 op[2] = operands[2];
2741 op[3] = operands[3];
2747 if (GET_CODE (operands[2]) == CONST_INT)
2749 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2750 int count = INTVAL (operands[2]);
2751 int max_len = 10; /* If larger than this, always use a loop. */
2760 if (count < 8 && !scratch)
2764 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2766 if (t_len * count <= max_len)
2768 /* Output shifts inline with no loop - faster. */
2770 *len = t_len * count;
2774 output_asm_insn (template, op);
2783 strcat (str, AS2 (ldi,%3,%2));
2785 else if (use_zero_reg)
2787 /* Hack to save one word: use __zero_reg__ as loop counter.
2788 Set one bit, then shift in a loop until it is 0 again. */
2790 op[3] = zero_reg_rtx;
2794 strcat (str, ("set" CR_TAB
2795 AS2 (bld,%3,%2-1)));
2799 /* No scratch register available, use one from LD_REGS (saved in
2800 __tmp_reg__) that doesn't overlap with registers to shift. */
2802 op[3] = gen_rtx_REG (QImode,
2803 ((true_regnum (operands[0]) - 1) & 15) + 16);
2804 op[4] = tmp_reg_rtx;
2808 *len = 3; /* Includes "mov %3,%4" after the loop. */
2810 strcat (str, (AS2 (mov,%4,%3) CR_TAB
2816 else if (GET_CODE (operands[2]) == MEM)
2820 op[3] = op_mov[0] = tmp_reg_rtx;
2824 out_movqi_r_mr (insn, op_mov, len);
2826 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
2828 else if (register_operand (operands[2], QImode))
2830 if (reg_unused_after (insn, operands[2]))
2834 op[3] = tmp_reg_rtx;
2836 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
2840 fatal_insn ("bad shift insn:", insn);
2847 strcat (str, AS1 (rjmp,2f));
2851 *len += t_len + 2; /* template + dec + brXX */
2854 strcat (str, "\n1:\t");
2855 strcat (str, template);
2856 strcat (str, second_label ? "\n2:\t" : "\n\t");
2857 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
2858 strcat (str, CR_TAB);
2859 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
2861 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
2862 output_asm_insn (str, op);
2867 /* 8bit shift left ((char)x << i) */
2870 ashlqi3_out (rtx insn, rtx operands[], int *len)
2872 if (GET_CODE (operands[2]) == CONST_INT)
2879 switch (INTVAL (operands[2]))
2882 if (INTVAL (operands[2]) < 8)
2886 return AS1 (clr,%0);
2890 return AS1 (lsl,%0);
2894 return (AS1 (lsl,%0) CR_TAB
2899 return (AS1 (lsl,%0) CR_TAB
2904 if (test_hard_reg_class (LD_REGS, operands[0]))
2907 return (AS1 (swap,%0) CR_TAB
2908 AS2 (andi,%0,0xf0));
2911 return (AS1 (lsl,%0) CR_TAB
2917 if (test_hard_reg_class (LD_REGS, operands[0]))
2920 return (AS1 (swap,%0) CR_TAB
2922 AS2 (andi,%0,0xe0));
2925 return (AS1 (lsl,%0) CR_TAB
2932 if (test_hard_reg_class (LD_REGS, operands[0]))
2935 return (AS1 (swap,%0) CR_TAB
2938 AS2 (andi,%0,0xc0));
2941 return (AS1 (lsl,%0) CR_TAB
2950 return (AS1 (ror,%0) CR_TAB
2955 else if (CONSTANT_P (operands[2]))
2956 fatal_insn ("internal compiler error. Incorrect shift:", insn);
2958 out_shift_with_cnt (AS1 (lsl,%0),
2959 insn, operands, len, 1);
2964 /* 16bit shift left ((short)x << i) */
2967 ashlhi3_out (rtx insn, rtx operands[], int *len)
2969 if (GET_CODE (operands[2]) == CONST_INT)
2971 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2972 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
2979 switch (INTVAL (operands[2]))
2982 if (INTVAL (operands[2]) < 16)
2986 return (AS1 (clr,%B0) CR_TAB
2990 if (optimize_size && scratch)
2995 return (AS1 (swap,%A0) CR_TAB
2996 AS1 (swap,%B0) CR_TAB
2997 AS2 (andi,%B0,0xf0) CR_TAB
2998 AS2 (eor,%B0,%A0) CR_TAB
2999 AS2 (andi,%A0,0xf0) CR_TAB
3005 return (AS1 (swap,%A0) CR_TAB
3006 AS1 (swap,%B0) CR_TAB
3007 AS2 (ldi,%3,0xf0) CR_TAB
3008 AS2 (and,%B0,%3) CR_TAB
3009 AS2 (eor,%B0,%A0) CR_TAB
3010 AS2 (and,%A0,%3) CR_TAB
3013 break; /* optimize_size ? 6 : 8 */
3017 break; /* scratch ? 5 : 6 */
3021 return (AS1 (lsl,%A0) CR_TAB
3022 AS1 (rol,%B0) CR_TAB
3023 AS1 (swap,%A0) CR_TAB
3024 AS1 (swap,%B0) CR_TAB
3025 AS2 (andi,%B0,0xf0) CR_TAB
3026 AS2 (eor,%B0,%A0) CR_TAB
3027 AS2 (andi,%A0,0xf0) CR_TAB
3033 return (AS1 (lsl,%A0) CR_TAB
3034 AS1 (rol,%B0) CR_TAB
3035 AS1 (swap,%A0) CR_TAB
3036 AS1 (swap,%B0) CR_TAB
3037 AS2 (ldi,%3,0xf0) CR_TAB
3038 AS2 (and,%B0,%3) CR_TAB
3039 AS2 (eor,%B0,%A0) CR_TAB
3040 AS2 (and,%A0,%3) CR_TAB
3047 break; /* scratch ? 5 : 6 */
3049 return (AS1 (clr,__tmp_reg__) CR_TAB
3050 AS1 (lsr,%B0) CR_TAB
3051 AS1 (ror,%A0) CR_TAB
3052 AS1 (ror,__tmp_reg__) CR_TAB
3053 AS1 (lsr,%B0) CR_TAB
3054 AS1 (ror,%A0) CR_TAB
3055 AS1 (ror,__tmp_reg__) CR_TAB
3056 AS2 (mov,%B0,%A0) CR_TAB
3057 AS2 (mov,%A0,__tmp_reg__));
3061 return (AS1 (lsr,%B0) CR_TAB
3062 AS2 (mov,%B0,%A0) CR_TAB
3063 AS1 (clr,%A0) CR_TAB
3064 AS1 (ror,%B0) CR_TAB
3068 if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
3069 return *len = 1, AS1 (clr,%A0);
3071 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3076 return (AS2 (mov,%B0,%A0) CR_TAB
3077 AS1 (clr,%A0) CR_TAB
3082 return (AS2 (mov,%B0,%A0) CR_TAB
3083 AS1 (clr,%A0) CR_TAB
3084 AS1 (lsl,%B0) CR_TAB
3089 return (AS2 (mov,%B0,%A0) CR_TAB
3090 AS1 (clr,%A0) CR_TAB
3091 AS1 (lsl,%B0) CR_TAB
3092 AS1 (lsl,%B0) CR_TAB
3099 return (AS2 (mov,%B0,%A0) CR_TAB
3100 AS1 (clr,%A0) CR_TAB
3101 AS1 (swap,%B0) CR_TAB
3102 AS2 (andi,%B0,0xf0));
3107 return (AS2 (mov,%B0,%A0) CR_TAB
3108 AS1 (clr,%A0) CR_TAB
3109 AS1 (swap,%B0) CR_TAB
3110 AS2 (ldi,%3,0xf0) CR_TAB
3114 return (AS2 (mov,%B0,%A0) CR_TAB
3115 AS1 (clr,%A0) CR_TAB
3116 AS1 (lsl,%B0) CR_TAB
3117 AS1 (lsl,%B0) CR_TAB
3118 AS1 (lsl,%B0) CR_TAB
3125 return (AS2 (mov,%B0,%A0) CR_TAB
3126 AS1 (clr,%A0) CR_TAB
3127 AS1 (swap,%B0) CR_TAB
3128 AS1 (lsl,%B0) CR_TAB
3129 AS2 (andi,%B0,0xe0));
3131 if (AVR_ENHANCED && scratch)
3134 return (AS2 (ldi,%3,0x20) CR_TAB
3135 AS2 (mul,%A0,%3) CR_TAB
3136 AS2 (mov,%B0,r0) CR_TAB
3137 AS1 (clr,%A0) CR_TAB
3138 AS1 (clr,__zero_reg__));
3140 if (optimize_size && scratch)
3145 return (AS2 (mov,%B0,%A0) CR_TAB
3146 AS1 (clr,%A0) CR_TAB
3147 AS1 (swap,%B0) CR_TAB
3148 AS1 (lsl,%B0) CR_TAB
3149 AS2 (ldi,%3,0xe0) CR_TAB
3155 return ("set" CR_TAB
3156 AS2 (bld,r1,5) CR_TAB
3157 AS2 (mul,%A0,r1) CR_TAB
3158 AS2 (mov,%B0,r0) CR_TAB
3159 AS1 (clr,%A0) CR_TAB
3160 AS1 (clr,__zero_reg__));
3163 return (AS2 (mov,%B0,%A0) CR_TAB
3164 AS1 (clr,%A0) CR_TAB
3165 AS1 (lsl,%B0) CR_TAB
3166 AS1 (lsl,%B0) CR_TAB
3167 AS1 (lsl,%B0) CR_TAB
3168 AS1 (lsl,%B0) CR_TAB
3172 if (AVR_ENHANCED && ldi_ok)
3175 return (AS2 (ldi,%B0,0x40) CR_TAB
3176 AS2 (mul,%A0,%B0) CR_TAB
3177 AS2 (mov,%B0,r0) CR_TAB
3178 AS1 (clr,%A0) CR_TAB
3179 AS1 (clr,__zero_reg__));
3181 if (AVR_ENHANCED && scratch)
3184 return (AS2 (ldi,%3,0x40) CR_TAB
3185 AS2 (mul,%A0,%3) CR_TAB
3186 AS2 (mov,%B0,r0) CR_TAB
3187 AS1 (clr,%A0) CR_TAB
3188 AS1 (clr,__zero_reg__));
3190 if (optimize_size && ldi_ok)
3193 return (AS2 (mov,%B0,%A0) CR_TAB
3194 AS2 (ldi,%A0,6) "\n1:\t"
3195 AS1 (lsl,%B0) CR_TAB
3196 AS1 (dec,%A0) CR_TAB
3199 if (optimize_size && scratch)
3202 return (AS1 (clr,%B0) CR_TAB
3203 AS1 (lsr,%A0) CR_TAB
3204 AS1 (ror,%B0) CR_TAB
3205 AS1 (lsr,%A0) CR_TAB
3206 AS1 (ror,%B0) CR_TAB
3211 return (AS1 (clr,%B0) CR_TAB
3212 AS1 (lsr,%A0) CR_TAB
3213 AS1 (ror,%B0) CR_TAB
3218 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3220 insn, operands, len, 2);
3225 /* 32bit shift left ((long)x << i) */
3228 ashlsi3_out (rtx insn, rtx operands[], int *len)
3230 if (GET_CODE (operands[2]) == CONST_INT)
3238 switch (INTVAL (operands[2]))
3241 if (INTVAL (operands[2]) < 32)
3245 return *len = 3, (AS1 (clr,%D0) CR_TAB
3246 AS1 (clr,%C0) CR_TAB
3247 AS2 (movw,%A0,%C0));
3249 return (AS1 (clr,%D0) CR_TAB
3250 AS1 (clr,%C0) CR_TAB
3251 AS1 (clr,%B0) CR_TAB
3256 int reg0 = true_regnum (operands[0]);
3257 int reg1 = true_regnum (operands[1]);
3260 return (AS2 (mov,%D0,%C1) CR_TAB
3261 AS2 (mov,%C0,%B1) CR_TAB
3262 AS2 (mov,%B0,%A1) CR_TAB
3264 else if (reg0 + 1 == reg1)
3267 return AS1 (clr,%A0);
3270 return (AS1 (clr,%A0) CR_TAB
3271 AS2 (mov,%B0,%A1) CR_TAB
3272 AS2 (mov,%C0,%B1) CR_TAB
3278 int reg0 = true_regnum (operands[0]);
3279 int reg1 = true_regnum (operands[1]);
3281 if (AVR_ENHANCED && (reg0 + 2 != reg1))
3284 return (AS2 (movw,%C0,%A1) CR_TAB
3285 AS1 (clr,%B0) CR_TAB
3288 if (reg0 + 1 >= reg1)
3289 return (AS2 (mov,%D0,%B1) CR_TAB
3290 AS2 (mov,%C0,%A1) CR_TAB
3291 AS1 (clr,%B0) CR_TAB
3293 if (reg0 + 2 == reg1)
3296 return (AS1 (clr,%B0) CR_TAB
3300 return (AS2 (mov,%C0,%A1) CR_TAB
3301 AS2 (mov,%D0,%B1) CR_TAB
3302 AS1 (clr,%B0) CR_TAB
3308 if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
3309 return (AS2 (mov,%D0,%A1) CR_TAB
3310 AS1 (clr,%C0) CR_TAB
3311 AS1 (clr,%B0) CR_TAB
3316 return (AS1 (clr,%C0) CR_TAB
3317 AS1 (clr,%B0) CR_TAB
3323 return (AS1 (clr,%D0) CR_TAB
3324 AS1 (lsr,%A0) CR_TAB
3325 AS1 (ror,%D0) CR_TAB
3326 AS1 (clr,%C0) CR_TAB
3327 AS1 (clr,%B0) CR_TAB
3332 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3333 AS1 (rol,%B0) CR_TAB
3334 AS1 (rol,%C0) CR_TAB
3336 insn, operands, len, 4);
3340 /* 8bit arithmetic shift right ((signed char)x >> i) */
3343 ashrqi3_out (rtx insn, rtx operands[], int *len)
3345 if (GET_CODE (operands[2]) == CONST_INT)
3352 switch (INTVAL (operands[2]))
3356 return AS1 (asr,%0);
3360 return (AS1 (asr,%0) CR_TAB
3365 return (AS1 (asr,%0) CR_TAB
3371 return (AS1 (asr,%0) CR_TAB
3378 return (AS1 (asr,%0) CR_TAB
3386 return (AS2 (bst,%0,6) CR_TAB
3388 AS2 (sbc,%0,%0) CR_TAB
3392 if (INTVAL (operands[2]) < 8)
3399 return (AS1 (lsl,%0) CR_TAB
3403 else if (CONSTANT_P (operands[2]))
3404 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3406 out_shift_with_cnt (AS1 (asr,%0),
3407 insn, operands, len, 1);
3412 /* 16bit arithmetic shift right ((signed short)x >> i) */
3415 ashrhi3_out (rtx insn, rtx operands[], int *len)
3417 if (GET_CODE (operands[2]) == CONST_INT)
3419 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3420 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3427 switch (INTVAL (operands[2]))
3431 /* XXX try to optimize this too? */
3436 break; /* scratch ? 5 : 6 */
3438 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3439 AS2 (mov,%A0,%B0) CR_TAB
3440 AS1 (lsl,__tmp_reg__) CR_TAB
3441 AS1 (rol,%A0) CR_TAB
3442 AS2 (sbc,%B0,%B0) CR_TAB
3443 AS1 (lsl,__tmp_reg__) CR_TAB
3444 AS1 (rol,%A0) CR_TAB
3449 return (AS1 (lsl,%A0) CR_TAB
3450 AS2 (mov,%A0,%B0) CR_TAB
3451 AS1 (rol,%A0) CR_TAB
3456 int reg0 = true_regnum (operands[0]);
3457 int reg1 = true_regnum (operands[1]);
3460 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3461 AS1 (lsl,%B0) CR_TAB
3463 else if (reg0 == reg1 + 1)
3464 return *len = 3, (AS1 (clr,%B0) CR_TAB
3465 AS2 (sbrc,%A0,7) CR_TAB
3468 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3469 AS1 (clr,%B0) CR_TAB
3470 AS2 (sbrc,%A0,7) CR_TAB
3476 return (AS2 (mov,%A0,%B0) CR_TAB
3477 AS1 (lsl,%B0) CR_TAB
3478 AS2 (sbc,%B0,%B0) CR_TAB
3483 return (AS2 (mov,%A0,%B0) CR_TAB
3484 AS1 (lsl,%B0) CR_TAB
3485 AS2 (sbc,%B0,%B0) CR_TAB
3486 AS1 (asr,%A0) CR_TAB
3490 if (AVR_ENHANCED && ldi_ok)
3493 return (AS2 (ldi,%A0,0x20) CR_TAB
3494 AS2 (muls,%B0,%A0) CR_TAB
3495 AS2 (mov,%A0,r1) CR_TAB
3496 AS2 (sbc,%B0,%B0) CR_TAB
3497 AS1 (clr,__zero_reg__));
3499 if (optimize_size && scratch)
3502 return (AS2 (mov,%A0,%B0) CR_TAB
3503 AS1 (lsl,%B0) CR_TAB
3504 AS2 (sbc,%B0,%B0) CR_TAB
3505 AS1 (asr,%A0) CR_TAB
3506 AS1 (asr,%A0) CR_TAB
3510 if (AVR_ENHANCED && ldi_ok)
3513 return (AS2 (ldi,%A0,0x10) CR_TAB
3514 AS2 (muls,%B0,%A0) CR_TAB
3515 AS2 (mov,%A0,r1) CR_TAB
3516 AS2 (sbc,%B0,%B0) CR_TAB
3517 AS1 (clr,__zero_reg__));
3519 if (optimize_size && scratch)
3522 return (AS2 (mov,%A0,%B0) CR_TAB
3523 AS1 (lsl,%B0) CR_TAB
3524 AS2 (sbc,%B0,%B0) CR_TAB
3525 AS1 (asr,%A0) CR_TAB
3526 AS1 (asr,%A0) CR_TAB
3527 AS1 (asr,%A0) CR_TAB
3531 if (AVR_ENHANCED && ldi_ok)
3534 return (AS2 (ldi,%A0,0x08) CR_TAB
3535 AS2 (muls,%B0,%A0) CR_TAB
3536 AS2 (mov,%A0,r1) CR_TAB
3537 AS2 (sbc,%B0,%B0) CR_TAB
3538 AS1 (clr,__zero_reg__));
3541 break; /* scratch ? 5 : 7 */
3543 return (AS2 (mov,%A0,%B0) CR_TAB
3544 AS1 (lsl,%B0) CR_TAB
3545 AS2 (sbc,%B0,%B0) CR_TAB
3546 AS1 (asr,%A0) CR_TAB
3547 AS1 (asr,%A0) CR_TAB
3548 AS1 (asr,%A0) CR_TAB
3549 AS1 (asr,%A0) CR_TAB
3554 return (AS1 (lsl,%B0) CR_TAB
3555 AS2 (sbc,%A0,%A0) CR_TAB
3556 AS1 (lsl,%B0) CR_TAB
3557 AS2 (mov,%B0,%A0) CR_TAB
3561 if (INTVAL (operands[2]) < 16)
3567 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3568 AS2 (sbc,%A0,%A0) CR_TAB
3573 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3575 insn, operands, len, 2);
3580 /* 32bit arithmetic shift right ((signed long)x >> i) */
3583 ashrsi3_out (rtx insn, rtx operands[], int *len)
3585 if (GET_CODE (operands[2]) == CONST_INT)
3593 switch (INTVAL (operands[2]))
3597 int reg0 = true_regnum (operands[0]);
3598 int reg1 = true_regnum (operands[1]);
3601 return (AS2 (mov,%A0,%B1) CR_TAB
3602 AS2 (mov,%B0,%C1) CR_TAB
3603 AS2 (mov,%C0,%D1) CR_TAB
3604 AS1 (clr,%D0) CR_TAB
3605 AS2 (sbrc,%C0,7) CR_TAB
3607 else if (reg0 == reg1 + 1)
3610 return (AS1 (clr,%D0) CR_TAB
3611 AS2 (sbrc,%C0,7) CR_TAB
3615 return (AS1 (clr,%D0) CR_TAB
3616 AS2 (sbrc,%D1,7) CR_TAB
3617 AS1 (dec,%D0) CR_TAB
3618 AS2 (mov,%C0,%D1) CR_TAB
3619 AS2 (mov,%B0,%C1) CR_TAB
3625 int reg0 = true_regnum (operands[0]);
3626 int reg1 = true_regnum (operands[1]);
3628 if (AVR_ENHANCED && (reg0 != reg1 + 2))
3631 return (AS2 (movw,%A0,%C1) CR_TAB
3632 AS1 (clr,%D0) CR_TAB
3633 AS2 (sbrc,%B0,7) CR_TAB
3634 AS1 (com,%D0) CR_TAB
3637 if (reg0 <= reg1 + 1)
3638 return (AS2 (mov,%A0,%C1) CR_TAB
3639 AS2 (mov,%B0,%D1) CR_TAB
3640 AS1 (clr,%D0) CR_TAB
3641 AS2 (sbrc,%B0,7) CR_TAB
3642 AS1 (com,%D0) CR_TAB
3644 else if (reg0 == reg1 + 2)
3645 return *len = 4, (AS1 (clr,%D0) CR_TAB
3646 AS2 (sbrc,%B0,7) CR_TAB
3647 AS1 (com,%D0) CR_TAB
3650 return (AS2 (mov,%B0,%D1) CR_TAB
3651 AS2 (mov,%A0,%C1) CR_TAB
3652 AS1 (clr,%D0) CR_TAB
3653 AS2 (sbrc,%B0,7) CR_TAB
3654 AS1 (com,%D0) CR_TAB
3659 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
3660 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3661 AS1 (clr,%D0) CR_TAB
3662 AS2 (sbrc,%A0,7) CR_TAB
3663 AS1 (com,%D0) CR_TAB
3664 AS2 (mov,%B0,%D0) CR_TAB
3667 return *len = 5, (AS1 (clr,%D0) CR_TAB
3668 AS2 (sbrc,%A0,7) CR_TAB
3669 AS1 (com,%D0) CR_TAB
3670 AS2 (mov,%B0,%D0) CR_TAB
3674 if (INTVAL (operands[2]) < 32)
3681 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3682 AS2 (sbc,%A0,%A0) CR_TAB
3683 AS2 (mov,%B0,%A0) CR_TAB
3684 AS2 (movw,%C0,%A0));
3686 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3687 AS2 (sbc,%A0,%A0) CR_TAB
3688 AS2 (mov,%B0,%A0) CR_TAB
3689 AS2 (mov,%C0,%A0) CR_TAB
3694 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3695 AS1 (ror,%C0) CR_TAB
3696 AS1 (ror,%B0) CR_TAB
3698 insn, operands, len, 4);
3702 /* 8bit logic shift right ((unsigned char)x >> i) */
3705 lshrqi3_out (rtx insn, rtx operands[], int *len)
3707 if (GET_CODE (operands[2]) == CONST_INT)
3714 switch (INTVAL (operands[2]))
3717 if (INTVAL (operands[2]) < 8)
3721 return AS1 (clr,%0);
3725 return AS1 (lsr,%0);
3729 return (AS1 (lsr,%0) CR_TAB
3733 return (AS1 (lsr,%0) CR_TAB
3738 if (test_hard_reg_class (LD_REGS, operands[0]))
3741 return (AS1 (swap,%0) CR_TAB
3742 AS2 (andi,%0,0x0f));
3745 return (AS1 (lsr,%0) CR_TAB
3751 if (test_hard_reg_class (LD_REGS, operands[0]))
3754 return (AS1 (swap,%0) CR_TAB
3759 return (AS1 (lsr,%0) CR_TAB
3766 if (test_hard_reg_class (LD_REGS, operands[0]))
3769 return (AS1 (swap,%0) CR_TAB
3775 return (AS1 (lsr,%0) CR_TAB
3784 return (AS1 (rol,%0) CR_TAB
3789 else if (CONSTANT_P (operands[2]))
3790 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3792 out_shift_with_cnt (AS1 (lsr,%0),
3793 insn, operands, len, 1);
3797 /* 16bit logic shift right ((unsigned short)x >> i) */
3800 lshrhi3_out (rtx insn, rtx operands[], int *len)
3802 if (GET_CODE (operands[2]) == CONST_INT)
3804 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3805 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3812 switch (INTVAL (operands[2]))
3815 if (INTVAL (operands[2]) < 16)
3819 return (AS1 (clr,%B0) CR_TAB
3823 if (optimize_size && scratch)
3828 return (AS1 (swap,%B0) CR_TAB
3829 AS1 (swap,%A0) CR_TAB
3830 AS2 (andi,%A0,0x0f) CR_TAB
3831 AS2 (eor,%A0,%B0) CR_TAB
3832 AS2 (andi,%B0,0x0f) CR_TAB
3838 return (AS1 (swap,%B0) CR_TAB
3839 AS1 (swap,%A0) CR_TAB
3840 AS2 (ldi,%3,0x0f) CR_TAB
3841 AS2 (and,%A0,%3) CR_TAB
3842 AS2 (eor,%A0,%B0) CR_TAB
3843 AS2 (and,%B0,%3) CR_TAB
3846 break; /* optimize_size ? 6 : 8 */
3850 break; /* scratch ? 5 : 6 */
3854 return (AS1 (lsr,%B0) CR_TAB
3855 AS1 (ror,%A0) CR_TAB
3856 AS1 (swap,%B0) CR_TAB
3857 AS1 (swap,%A0) CR_TAB
3858 AS2 (andi,%A0,0x0f) CR_TAB
3859 AS2 (eor,%A0,%B0) CR_TAB
3860 AS2 (andi,%B0,0x0f) CR_TAB
3866 return (AS1 (lsr,%B0) CR_TAB
3867 AS1 (ror,%A0) CR_TAB
3868 AS1 (swap,%B0) CR_TAB
3869 AS1 (swap,%A0) CR_TAB
3870 AS2 (ldi,%3,0x0f) CR_TAB
3871 AS2 (and,%A0,%3) CR_TAB
3872 AS2 (eor,%A0,%B0) CR_TAB
3873 AS2 (and,%B0,%3) CR_TAB
3880 break; /* scratch ? 5 : 6 */
3882 return (AS1 (clr,__tmp_reg__) CR_TAB
3883 AS1 (lsl,%A0) CR_TAB
3884 AS1 (rol,%B0) CR_TAB
3885 AS1 (rol,__tmp_reg__) CR_TAB
3886 AS1 (lsl,%A0) CR_TAB
3887 AS1 (rol,%B0) CR_TAB
3888 AS1 (rol,__tmp_reg__) CR_TAB
3889 AS2 (mov,%A0,%B0) CR_TAB
3890 AS2 (mov,%B0,__tmp_reg__));
3894 return (AS1 (lsl,%A0) CR_TAB
3895 AS2 (mov,%A0,%B0) CR_TAB
3896 AS1 (rol,%A0) CR_TAB
3897 AS2 (sbc,%B0,%B0) CR_TAB
3901 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
3902 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
3905 return *len = 1, AS1 (clr,%B0);
3909 return (AS2 (mov,%A0,%B0) CR_TAB
3910 AS1 (clr,%B0) CR_TAB
3915 return (AS2 (mov,%A0,%B0) CR_TAB
3916 AS1 (clr,%B0) CR_TAB
3917 AS1 (lsr,%A0) CR_TAB
3922 return (AS2 (mov,%A0,%B0) CR_TAB
3923 AS1 (clr,%B0) CR_TAB
3924 AS1 (lsr,%A0) CR_TAB
3925 AS1 (lsr,%A0) CR_TAB
3932 return (AS2 (mov,%A0,%B0) CR_TAB
3933 AS1 (clr,%B0) CR_TAB
3934 AS1 (swap,%A0) CR_TAB
3935 AS2 (andi,%A0,0x0f));
3940 return (AS2 (mov,%A0,%B0) CR_TAB
3941 AS1 (clr,%B0) CR_TAB
3942 AS1 (swap,%A0) CR_TAB
3943 AS2 (ldi,%3,0x0f) CR_TAB
3947 return (AS2 (mov,%A0,%B0) CR_TAB
3948 AS1 (clr,%B0) CR_TAB
3949 AS1 (lsr,%A0) CR_TAB
3950 AS1 (lsr,%A0) CR_TAB
3951 AS1 (lsr,%A0) CR_TAB
3958 return (AS2 (mov,%A0,%B0) CR_TAB
3959 AS1 (clr,%B0) CR_TAB
3960 AS1 (swap,%A0) CR_TAB
3961 AS1 (lsr,%A0) CR_TAB
3962 AS2 (andi,%A0,0x07));
3964 if (AVR_ENHANCED && scratch)
3967 return (AS2 (ldi,%3,0x08) CR_TAB
3968 AS2 (mul,%B0,%3) CR_TAB
3969 AS2 (mov,%A0,r1) CR_TAB
3970 AS1 (clr,%B0) CR_TAB
3971 AS1 (clr,__zero_reg__));
3973 if (optimize_size && scratch)
3978 return (AS2 (mov,%A0,%B0) CR_TAB
3979 AS1 (clr,%B0) CR_TAB
3980 AS1 (swap,%A0) CR_TAB
3981 AS1 (lsr,%A0) CR_TAB
3982 AS2 (ldi,%3,0x07) CR_TAB
3988 return ("set" CR_TAB
3989 AS2 (bld,r1,3) CR_TAB
3990 AS2 (mul,%B0,r1) CR_TAB
3991 AS2 (mov,%A0,r1) CR_TAB
3992 AS1 (clr,%B0) CR_TAB
3993 AS1 (clr,__zero_reg__));
3996 return (AS2 (mov,%A0,%B0) CR_TAB
3997 AS1 (clr,%B0) CR_TAB
3998 AS1 (lsr,%A0) CR_TAB
3999 AS1 (lsr,%A0) CR_TAB
4000 AS1 (lsr,%A0) CR_TAB
4001 AS1 (lsr,%A0) CR_TAB
4005 if (AVR_ENHANCED && ldi_ok)
4008 return (AS2 (ldi,%A0,0x04) CR_TAB
4009 AS2 (mul,%B0,%A0) CR_TAB
4010 AS2 (mov,%A0,r1) CR_TAB
4011 AS1 (clr,%B0) CR_TAB
4012 AS1 (clr,__zero_reg__));
4014 if (AVR_ENHANCED && scratch)
4017 return (AS2 (ldi,%3,0x04) CR_TAB
4018 AS2 (mul,%B0,%3) CR_TAB
4019 AS2 (mov,%A0,r1) CR_TAB
4020 AS1 (clr,%B0) CR_TAB
4021 AS1 (clr,__zero_reg__));
4023 if (optimize_size && ldi_ok)
4026 return (AS2 (mov,%A0,%B0) CR_TAB
4027 AS2 (ldi,%B0,6) "\n1:\t"
4028 AS1 (lsr,%A0) CR_TAB
4029 AS1 (dec,%B0) CR_TAB
4032 if (optimize_size && scratch)
4035 return (AS1 (clr,%A0) CR_TAB
4036 AS1 (lsl,%B0) CR_TAB
4037 AS1 (rol,%A0) CR_TAB
4038 AS1 (lsl,%B0) CR_TAB
4039 AS1 (rol,%A0) CR_TAB
4044 return (AS1 (clr,%A0) CR_TAB
4045 AS1 (lsl,%B0) CR_TAB
4046 AS1 (rol,%A0) CR_TAB
4051 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4053 insn, operands, len, 2);
4057 /* 32bit logic shift right ((unsigned int)x >> i) */
4060 lshrsi3_out (rtx insn, rtx operands[], int *len)
4062 if (GET_CODE (operands[2]) == CONST_INT)
4070 switch (INTVAL (operands[2]))
4073 if (INTVAL (operands[2]) < 32)
4077 return *len = 3, (AS1 (clr,%D0) CR_TAB
4078 AS1 (clr,%C0) CR_TAB
4079 AS2 (movw,%A0,%C0));
4081 return (AS1 (clr,%D0) CR_TAB
4082 AS1 (clr,%C0) CR_TAB
4083 AS1 (clr,%B0) CR_TAB
4088 int reg0 = true_regnum (operands[0]);
4089 int reg1 = true_regnum (operands[1]);
4092 return (AS2 (mov,%A0,%B1) CR_TAB
4093 AS2 (mov,%B0,%C1) CR_TAB
4094 AS2 (mov,%C0,%D1) CR_TAB
4096 else if (reg0 == reg1 + 1)
4097 return *len = 1, AS1 (clr,%D0);
4099 return (AS1 (clr,%D0) CR_TAB
4100 AS2 (mov,%C0,%D1) CR_TAB
4101 AS2 (mov,%B0,%C1) CR_TAB
4107 int reg0 = true_regnum (operands[0]);
4108 int reg1 = true_regnum (operands[1]);
4110 if (AVR_ENHANCED && (reg0 != reg1 + 2))
4113 return (AS2 (movw,%A0,%C1) CR_TAB
4114 AS1 (clr,%C0) CR_TAB
4117 if (reg0 <= reg1 + 1)
4118 return (AS2 (mov,%A0,%C1) CR_TAB
4119 AS2 (mov,%B0,%D1) CR_TAB
4120 AS1 (clr,%C0) CR_TAB
4122 else if (reg0 == reg1 + 2)
4123 return *len = 2, (AS1 (clr,%C0) CR_TAB
4126 return (AS2 (mov,%B0,%D1) CR_TAB
4127 AS2 (mov,%A0,%C1) CR_TAB
4128 AS1 (clr,%C0) CR_TAB
4133 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
4134 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4135 AS1 (clr,%B0) CR_TAB
4136 AS1 (clr,%C0) CR_TAB
4139 return *len = 3, (AS1 (clr,%B0) CR_TAB
4140 AS1 (clr,%C0) CR_TAB
4145 return (AS1 (clr,%A0) CR_TAB
4146 AS2 (sbrc,%D0,7) CR_TAB
4147 AS1 (inc,%A0) CR_TAB
4148 AS1 (clr,%B0) CR_TAB
4149 AS1 (clr,%C0) CR_TAB
4154 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4155 AS1 (ror,%C0) CR_TAB
4156 AS1 (ror,%B0) CR_TAB
4158 insn, operands, len, 4);
4162 /* Modifies the length assigned to instruction INSN
4163 LEN is the initially computed length of the insn. */
4166 adjust_insn_length (rtx insn, int len)
4168 rtx patt = PATTERN (insn);
4171 if (GET_CODE (patt) == SET)
4174 op[1] = SET_SRC (patt);
4175 op[0] = SET_DEST (patt);
4176 if (general_operand (op[1], VOIDmode)
4177 && general_operand (op[0], VOIDmode))
4179 switch (GET_MODE (op[0]))
4182 output_movqi (insn, op, &len);
4185 output_movhi (insn, op, &len);
4189 output_movsisf (insn, op, &len);
4195 else if (op[0] == cc0_rtx && REG_P (op[1]))
4197 switch (GET_MODE (op[1]))
4199 case HImode: out_tsthi (insn,&len); break;
4200 case SImode: out_tstsi (insn,&len); break;
4204 else if (GET_CODE (op[1]) == AND)
4206 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4208 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4209 if (GET_MODE (op[1]) == SImode)
4210 len = (((mask & 0xff) != 0xff)
4211 + ((mask & 0xff00) != 0xff00)
4212 + ((mask & 0xff0000L) != 0xff0000L)
4213 + ((mask & 0xff000000L) != 0xff000000L));
4214 else if (GET_MODE (op[1]) == HImode)
4215 len = (((mask & 0xff) != 0xff)
4216 + ((mask & 0xff00) != 0xff00));
4219 else if (GET_CODE (op[1]) == IOR)
4221 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4223 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4224 if (GET_MODE (op[1]) == SImode)
4225 len = (((mask & 0xff) != 0)
4226 + ((mask & 0xff00) != 0)
4227 + ((mask & 0xff0000L) != 0)
4228 + ((mask & 0xff000000L) != 0));
4229 else if (GET_MODE (op[1]) == HImode)
4230 len = (((mask & 0xff) != 0)
4231 + ((mask & 0xff00) != 0));
4235 set = single_set (insn);
4240 op[1] = SET_SRC (set);
4241 op[0] = SET_DEST (set);
4243 if (GET_CODE (patt) == PARALLEL
4244 && general_operand (op[1], VOIDmode)
4245 && general_operand (op[0], VOIDmode))
4247 if (XVECLEN (patt, 0) == 2)
4248 op[2] = XVECEXP (patt, 0, 1);
4250 switch (GET_MODE (op[0]))
4256 output_reload_inhi (insn, op, &len);
4260 output_reload_insisf (insn, op, &len);
4266 else if (GET_CODE (op[1]) == ASHIFT
4267 || GET_CODE (op[1]) == ASHIFTRT
4268 || GET_CODE (op[1]) == LSHIFTRT)
4272 ops[1] = XEXP (op[1],0);
4273 ops[2] = XEXP (op[1],1);
4274 switch (GET_CODE (op[1]))
4277 switch (GET_MODE (op[0]))
4279 case QImode: ashlqi3_out (insn,ops,&len); break;
4280 case HImode: ashlhi3_out (insn,ops,&len); break;
4281 case SImode: ashlsi3_out (insn,ops,&len); break;
4286 switch (GET_MODE (op[0]))
4288 case QImode: ashrqi3_out (insn,ops,&len); break;
4289 case HImode: ashrhi3_out (insn,ops,&len); break;
4290 case SImode: ashrsi3_out (insn,ops,&len); break;
4295 switch (GET_MODE (op[0]))
4297 case QImode: lshrqi3_out (insn,ops,&len); break;
4298 case HImode: lshrhi3_out (insn,ops,&len); break;
4299 case SImode: lshrsi3_out (insn,ops,&len); break;
4311 /* Return nonzero if register REG dead after INSN. */
4314 reg_unused_after (rtx insn, rtx reg)
4316 return (dead_or_set_p (insn, reg)
4317 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4320 /* Return nonzero if REG is not used after INSN.
4321 We assume REG is a reload reg, and therefore does
4322 not live past labels. It may live past calls or jumps though. */
4325 _reg_unused_after (rtx insn, rtx reg)
4330 /* If the reg is set by this instruction, then it is safe for our
4331 case. Disregard the case where this is a store to memory, since
4332 we are checking a register used in the store address. */
4333 set = single_set (insn);
4334 if (set && GET_CODE (SET_DEST (set)) != MEM
4335 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4338 while ((insn = NEXT_INSN (insn)))
4341 code = GET_CODE (insn);
4344 /* If this is a label that existed before reload, then the register
4345 if dead here. However, if this is a label added by reorg, then
4346 the register may still be live here. We can't tell the difference,
4347 so we just ignore labels completely. */
4348 if (code == CODE_LABEL)
4356 if (code == JUMP_INSN)
4359 /* If this is a sequence, we must handle them all at once.
4360 We could have for instance a call that sets the target register,
4361 and an insn in a delay slot that uses the register. In this case,
4362 we must return 0. */
4363 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4368 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4370 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4371 rtx set = single_set (this_insn);
4373 if (GET_CODE (this_insn) == CALL_INSN)
4375 else if (GET_CODE (this_insn) == JUMP_INSN)
4377 if (INSN_ANNULLED_BRANCH_P (this_insn))
4382 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4384 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4386 if (GET_CODE (SET_DEST (set)) != MEM)
4392 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4397 else if (code == JUMP_INSN)
4401 if (code == CALL_INSN)
4404 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4405 if (GET_CODE (XEXP (tem, 0)) == USE
4406 && REG_P (XEXP (XEXP (tem, 0), 0))
4407 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4409 if (call_used_regs[REGNO (reg)])
4413 set = single_set (insn);
4415 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4417 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4418 return GET_CODE (SET_DEST (set)) != MEM;
4419 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4425 /* Target hook for assembling integer objects. The AVR version needs
4426 special handling for references to certain labels. */
4429 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
4431 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
4432 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
4433 || GET_CODE (x) == LABEL_REF))
4435 fputs ("\t.word\tpm(", asm_out_file);
4436 output_addr_const (asm_out_file, x);
4437 fputs (")\n", asm_out_file);
4440 return default_assemble_integer (x, size, aligned_p);
4443 /* The routine used to output NUL terminated strings. We use a special
4444 version of this for most svr4 targets because doing so makes the
4445 generated assembly code more compact (and thus faster to assemble)
4446 as well as more readable, especially for targets like the i386
4447 (where the only alternative is to output character sequences as
4448 comma separated lists of numbers). */
4451 gas_output_limited_string(FILE *file, const char *str)
4453 const unsigned char *_limited_str = (unsigned char *) str;
4455 fprintf (file, "%s\"", STRING_ASM_OP);
4456 for (; (ch = *_limited_str); _limited_str++)
4459 switch (escape = ESCAPES[ch])
4465 fprintf (file, "\\%03o", ch);
4469 putc (escape, file);
4473 fprintf (file, "\"\n");
4476 /* The routine used to output sequences of byte values. We use a special
4477 version of this for most svr4 targets because doing so makes the
4478 generated assembly code more compact (and thus faster to assemble)
4479 as well as more readable. Note that if we find subparts of the
4480 character sequence which end with NUL (and which are shorter than
4481 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4484 gas_output_ascii(FILE *file, const char *str, size_t length)
4486 const unsigned char *_ascii_bytes = (const unsigned char *) str;
4487 const unsigned char *limit = _ascii_bytes + length;
4488 unsigned bytes_in_chunk = 0;
4489 for (; _ascii_bytes < limit; _ascii_bytes++)
4491 const unsigned char *p;
4492 if (bytes_in_chunk >= 60)
4494 fprintf (file, "\"\n");
4497 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4499 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4501 if (bytes_in_chunk > 0)
4503 fprintf (file, "\"\n");
4506 gas_output_limited_string (file, (char*)_ascii_bytes);
4513 if (bytes_in_chunk == 0)
4514 fprintf (file, "\t.ascii\t\"");
4515 switch (escape = ESCAPES[ch = *_ascii_bytes])
4522 fprintf (file, "\\%03o", ch);
4523 bytes_in_chunk += 4;
4527 putc (escape, file);
4528 bytes_in_chunk += 2;
4533 if (bytes_in_chunk > 0)
4534 fprintf (file, "\"\n");
4537 /* Return value is nonzero if pseudos that have been
4538 assigned to registers of class CLASS would likely be spilled
4539 because registers of CLASS are needed for spill registers. */
4542 class_likely_spilled_p (int c)
4544 return (c != ALL_REGS && c != ADDW_REGS);
4547 /* Valid attributes:
4548 progmem - put data to program memory;
4549 signal - make a function to be hardware interrupt. After function
4550 prologue interrupts are disabled;
4551 interrupt - make a function to be hardware interrupt. After function
4552 prologue interrupts are enabled;
4553 naked - don't generate function prologue/epilogue and `ret' command.
4555 Only `progmem' attribute valid for type. */
4557 const struct attribute_spec avr_attribute_table[] =
4559 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4560 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
4561 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4562 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4563 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4564 { NULL, 0, 0, false, false, false, NULL }
4567 /* Handle a "progmem" attribute; arguments as in
4568 struct attribute_spec.handler. */
4570 avr_handle_progmem_attribute (tree *node, tree name,
4571 tree args ATTRIBUTE_UNUSED,
4572 int flags ATTRIBUTE_UNUSED,
4577 if (TREE_CODE (*node) == TYPE_DECL)
4579 /* This is really a decl attribute, not a type attribute,
4580 but try to handle it for GCC 3.0 backwards compatibility. */
4582 tree type = TREE_TYPE (*node);
4583 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
4584 tree newtype = build_type_attribute_variant (type, attr);
4586 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
4587 TREE_TYPE (*node) = newtype;
4588 *no_add_attrs = true;
4590 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
4592 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
4594 warning ("only initialized variables can be placed into "
4595 "program memory area");
4596 *no_add_attrs = true;
4601 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
4602 *no_add_attrs = true;
4609 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4610 struct attribute_spec.handler. */
4613 avr_handle_fndecl_attribute (tree *node, tree name,
4614 tree args ATTRIBUTE_UNUSED,
4615 int flags ATTRIBUTE_UNUSED,
4618 if (TREE_CODE (*node) != FUNCTION_DECL)
4620 warning ("%qs attribute only applies to functions",
4621 IDENTIFIER_POINTER (name));
4622 *no_add_attrs = true;
4626 const char *func_name = IDENTIFIER_POINTER (DECL_NAME (*node));
4627 const char *attr = IDENTIFIER_POINTER (name);
4629 /* If the function has the 'signal' or 'interrupt' attribute, test to
4630 make sure that the name of the function is "__vector_NN" so as to
4631 catch when the user misspells the interrupt vector name. */
4633 if (strncmp (attr, "interrupt", strlen ("interrupt")) == 0)
4635 if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
4637 warning ("`%s' appears to be a misspelled interrupt handler",
4641 else if (strncmp (attr, "signal", strlen ("signal")) == 0)
4643 if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
4645 warning ("`%s' appears to be a misspelled signal handler",
4654 /* Look for attribute `progmem' in DECL
4655 if found return 1, otherwise 0. */
4658 avr_progmem_p (tree decl, tree attributes)
4662 if (TREE_CODE (decl) != VAR_DECL)
4666 != lookup_attribute ("progmem", attributes))
4672 while (TREE_CODE (a) == ARRAY_TYPE);
4674 if (a == error_mark_node)
4677 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4683 /* Add the section attribute if the variable is in progmem. */
4686 avr_insert_attributes (tree node, tree *attributes)
4688 if (TREE_CODE (node) == VAR_DECL
4689 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
4690 && avr_progmem_p (node, *attributes))
4692 static const char dsec[] = ".progmem.data";
4693 *attributes = tree_cons (get_identifier ("section"),
4694 build_tree_list (NULL, build_string (strlen (dsec), dsec)),
4697 /* ??? This seems sketchy. Why can't the user declare the
4698 thing const in the first place? */
4699 TREE_READONLY (node) = 1;
4704 avr_section_type_flags (tree decl, const char *name, int reloc)
4706 unsigned int flags = default_section_type_flags (decl, name, reloc);
4708 if (strncmp (name, ".noinit", 7) == 0)
4710 if (decl && TREE_CODE (decl) == VAR_DECL
4711 && DECL_INITIAL (decl) == NULL_TREE)
4712 flags |= SECTION_BSS; /* @nobits */
4714 warning ("only uninitialized variables can be placed in the "
4721 /* Outputs some appropriate text to go at the start of an assembler
4725 avr_file_start (void)
4728 error ("MCU %qs supported for assembler only", avr_mcu_name);
4730 default_file_start ();
4732 fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);
4733 fputs ("__SREG__ = 0x3f\n"
4735 "__SP_L__ = 0x3d\n", asm_out_file);
4737 fputs ("__tmp_reg__ = 0\n"
4738 "__zero_reg__ = 1\n", asm_out_file);
4740 /* FIXME: output these only if there is anything in the .data / .bss
4741 sections - some code size could be saved by not linking in the
4742 initialization code from libgcc if one or both sections are empty. */
4743 fputs ("\t.global __do_copy_data\n", asm_out_file);
4744 fputs ("\t.global __do_clear_bss\n", asm_out_file);
4746 commands_in_file = 0;
4747 commands_in_prologues = 0;
4748 commands_in_epilogues = 0;
4751 /* Outputs to the stdio stream FILE some
4752 appropriate text to go at the end of an assembler file. */
4757 fputs ("/* File ", asm_out_file);
4758 output_quoted_string (asm_out_file, main_input_filename);
4759 fprintf (asm_out_file,
4760 ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4763 commands_in_file - commands_in_prologues - commands_in_epilogues,
4764 commands_in_prologues, commands_in_epilogues);
4767 /* Choose the order in which to allocate hard registers for
4768 pseudo-registers local to a basic block.
4770 Store the desired register order in the array `reg_alloc_order'.
4771 Element 0 should be the register to allocate first; element 1, the
4772 next register; and so on. */
4775 order_regs_for_local_alloc (void)
4778 static const int order_0[] = {
4786 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4790 static const int order_1[] = {
4798 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4802 static const int order_2[] = {
4811 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4816 const int *order = (TARGET_ORDER_1 ? order_1 :
4817 TARGET_ORDER_2 ? order_2 :
4819 for (i=0; i < ARRAY_SIZE (order_0); ++i)
4820 reg_alloc_order[i] = order[i];
4823 /* Calculate the cost of X code of the expression in which it is contained,
4824 found in OUTER_CODE */
4827 default_rtx_costs (rtx X, enum rtx_code code, enum rtx_code outer_code)
4834 cost = 2 * GET_MODE_SIZE (GET_MODE (X));
4837 if (outer_code != SET)
4839 if (GET_CODE (XEXP (X,0)) == SYMBOL_REF)
4840 cost += 2 * GET_MODE_SIZE (GET_MODE (X));
4842 cost += GET_MODE_SIZE (GET_MODE (X));
4848 if (outer_code == SET)
4849 cost = GET_MODE_SIZE (GET_MODE (X));
4851 cost = -GET_MODE_SIZE (GET_MODE (X));
4854 if (outer_code == SET)
4855 cost = GET_MODE_SIZE (GET_MODE (X));
4861 if (outer_code == SET)
4863 if (X == stack_pointer_rtx)
4865 else if (GET_CODE (XEXP (X,1)) == CONST_INT)
4866 cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 :
4867 GET_MODE_SIZE (GET_MODE (X)));
4869 cost = GET_MODE_SIZE (GET_MODE (X));
4873 if (GET_CODE (XEXP (X,1)) == CONST_INT)
4874 cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0)));
4883 avr_rtx_costs (rtx x, int code, int outer_code, int *total)
4890 if (outer_code == PLUS
4891 || outer_code == IOR
4892 || outer_code == AND
4893 || outer_code == MINUS
4894 || outer_code == SET
4900 if (outer_code == COMPARE
4902 && INTVAL (x) <= 255)
4917 cst = default_rtx_costs (x, code, outer_code);
4929 /* Calculate the cost of a memory address. */
4932 avr_address_cost (rtx x)
4934 if (GET_CODE (x) == PLUS
4935 && GET_CODE (XEXP (x,1)) == CONST_INT
4936 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
4937 && INTVAL (XEXP (x,1)) >= 61)
4939 if (CONSTANT_ADDRESS_P (x))
4941 if (avr_io_address_p (x, 1))
4948 /* EXTRA_CONSTRAINT helper */
4951 extra_constraint (rtx x, int c)
4954 && GET_CODE (x) == MEM
4955 && GET_CODE (XEXP (x,0)) == PLUS)
4957 if (TARGET_ALL_DEBUG)
4959 fprintf (stderr, ("extra_constraint:\n"
4960 "reload_completed: %d\n"
4961 "reload_in_progress: %d\n"),
4962 reload_completed, reload_in_progress);
4965 if (GET_CODE (x) == MEM
4966 && GET_CODE (XEXP (x,0)) == PLUS
4967 && REG_P (XEXP (XEXP (x,0), 0))
4968 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
4969 && (INTVAL (XEXP (XEXP (x,0), 1))
4970 <= MAX_LD_OFFSET (GET_MODE (x))))
4972 rtx xx = XEXP (XEXP (x,0), 0);
4973 int regno = REGNO (xx);
4974 if (TARGET_ALL_DEBUG)
4976 fprintf (stderr, ("extra_constraint:\n"
4977 "reload_completed: %d\n"
4978 "reload_in_progress: %d\n"),
4979 reload_completed, reload_in_progress);
4982 if (regno >= FIRST_PSEUDO_REGISTER)
4983 return 1; /* allocate pseudos */
4984 else if (regno == REG_Z || regno == REG_Y)
4985 return 1; /* strictly check */
4986 else if (xx == frame_pointer_rtx
4987 || xx == arg_pointer_rtx)
4988 return 1; /* XXX frame & arg pointer checks */
4994 /* Convert condition code CONDITION to the valid AVR condition code. */
4997 avr_normalize_condition (RTX_CODE condition)
5014 /* This function optimizes conditional jumps. */
5021 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5023 if (! (GET_CODE (insn) == INSN
5024 || GET_CODE (insn) == CALL_INSN
5025 || GET_CODE (insn) == JUMP_INSN)
5026 || !single_set (insn))
5029 pattern = PATTERN (insn);
5031 if (GET_CODE (pattern) == PARALLEL)
5032 pattern = XVECEXP (pattern, 0, 0);
5033 if (GET_CODE (pattern) == SET
5034 && SET_DEST (pattern) == cc0_rtx
5035 && compare_diff_p (insn))
5037 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
5039 /* Now we work under compare insn. */
5041 pattern = SET_SRC (pattern);
5042 if (true_regnum (XEXP (pattern,0)) >= 0
5043 && true_regnum (XEXP (pattern,1)) >= 0 )
5045 rtx x = XEXP (pattern,0);
5046 rtx next = next_real_insn (insn);
5047 rtx pat = PATTERN (next);
5048 rtx src = SET_SRC (pat);
5049 rtx t = XEXP (src,0);
5050 PUT_CODE (t, swap_condition (GET_CODE (t)));
5051 XEXP (pattern,0) = XEXP (pattern,1);
5052 XEXP (pattern,1) = x;
5053 INSN_CODE (next) = -1;
5055 else if (true_regnum (XEXP (pattern,0)) >= 0
5056 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
5058 rtx x = XEXP (pattern,1);
5059 rtx next = next_real_insn (insn);
5060 rtx pat = PATTERN (next);
5061 rtx src = SET_SRC (pat);
5062 rtx t = XEXP (src,0);
5063 enum machine_mode mode = GET_MODE (XEXP (pattern, 0));
5065 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
5067 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
5068 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
5069 INSN_CODE (next) = -1;
5070 INSN_CODE (insn) = -1;
5074 else if (true_regnum (SET_SRC (pattern)) >= 0)
5076 /* This is a tst insn */
5077 rtx next = next_real_insn (insn);
5078 rtx pat = PATTERN (next);
5079 rtx src = SET_SRC (pat);
5080 rtx t = XEXP (src,0);
5082 PUT_CODE (t, swap_condition (GET_CODE (t)));
5083 SET_SRC (pattern) = gen_rtx_NEG (GET_MODE (SET_SRC (pattern)),
5085 INSN_CODE (next) = -1;
5086 INSN_CODE (insn) = -1;
5092 /* Returns register number for function return value.*/
5095 avr_ret_register (void)
5100 /* Ceate an RTX representing the place where a
5101 library function returns a value of mode MODE. */
5104 avr_libcall_value (enum machine_mode mode)
5106 int offs = GET_MODE_SIZE (mode);
5109 return gen_rtx_REG (mode, RET_REGISTER + 2 - offs);
5112 /* Create an RTX representing the place where a
5113 function returns a value of data type VALTYPE. */
5116 avr_function_value (tree type, tree func ATTRIBUTE_UNUSED)
5120 if (TYPE_MODE (type) != BLKmode)
5121 return avr_libcall_value (TYPE_MODE (type));
5123 offs = int_size_in_bytes (type);
5126 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5127 offs = GET_MODE_SIZE (SImode);
5128 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5129 offs = GET_MODE_SIZE (DImode);
5131 return gen_rtx_REG (BLKmode, RET_REGISTER + 2 - offs);
5134 /* Returns nonzero if the number MASK has only one bit set. */
5137 mask_one_bit_p (HOST_WIDE_INT mask)
5140 unsigned HOST_WIDE_INT n=mask;
5141 for (i = 0; i < 32; ++i)
5143 if (n & 0x80000000L)
5145 if (n & 0x7fffffffL)
5156 /* Places additional restrictions on the register class to
5157 use when it is necessary to copy value X into a register
5161 preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class class)
5167 test_hard_reg_class (enum reg_class class, rtx x)
5169 int regno = true_regnum (x);
5173 if (TEST_HARD_REG_CLASS (class, regno))
5181 jump_over_one_insn_p (rtx insn, rtx dest)
5183 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5186 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5187 int dest_addr = INSN_ADDRESSES (uid);
5188 return dest_addr - jump_addr == get_attr_length (insn) + 1;
5191 /* Returns 1 if a value of mode MODE can be stored starting with hard
5192 register number REGNO. On the enhanced core, anything larger than
5193 1 byte must start in even numbered register for "movw" to work
5194 (this way we don't have to check for odd registers everywhere). */
5197 avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
5199 /* The only thing that can go into registers r28:r29 is a Pmode. */
5200 if (regno == REG_Y && mode == Pmode)
5203 /* Otherwise disallow all regno/mode combinations that span r28:r29. */
5204 if (regno <= (REG_Y + 1) && (regno + GET_MODE_SIZE (mode)) >= (REG_Y + 1))
5210 /* Modes larger than QImode occupy consecutive registers. */
5211 if (regno + GET_MODE_SIZE (mode) > FIRST_PSEUDO_REGISTER)
5214 /* All modes larger than QImode should start in an even register. */
5215 return !(regno & 1);
5218 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5219 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5220 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
5223 avr_io_address_p (rtx x, int size)
5225 return (optimize > 0 && GET_CODE (x) == CONST_INT
5226 && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
5229 /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5232 const_int_pow2_p (rtx x)
5234 if (GET_CODE (x) == CONST_INT)
5236 HOST_WIDE_INT d = INTVAL (x);
5237 HOST_WIDE_INT abs_d = (d >= 0) ? d : -d;
5238 return exact_log2 (abs_d) + 1;
5244 output_reload_inhi (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
5250 if (GET_CODE (operands[1]) == CONST_INT)
5252 int val = INTVAL (operands[1]);
5253 if ((val & 0xff) == 0)
5256 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5257 AS2 (ldi,%2,hi8(%1)) CR_TAB
5260 else if ((val & 0xff00) == 0)
5263 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5264 AS2 (mov,%A0,%2) CR_TAB
5265 AS2 (mov,%B0,__zero_reg__));
5267 else if ((val & 0xff) == ((val & 0xff00) >> 8))
5270 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5271 AS2 (mov,%A0,%2) CR_TAB
5276 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5277 AS2 (mov,%A0,%2) CR_TAB
5278 AS2 (ldi,%2,hi8(%1)) CR_TAB
5284 output_reload_insisf (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
5286 rtx src = operands[1];
5287 int cnst = (GET_CODE (src) == CONST_INT);
5292 *len = 4 + ((INTVAL (src) & 0xff) != 0)
5293 + ((INTVAL (src) & 0xff00) != 0)
5294 + ((INTVAL (src) & 0xff0000) != 0)
5295 + ((INTVAL (src) & 0xff000000) != 0);
5302 if (cnst && ((INTVAL (src) & 0xff) == 0))
5303 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5306 output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
5307 output_asm_insn (AS2 (mov, %A0, %2), operands);
5309 if (cnst && ((INTVAL (src) & 0xff00) == 0))
5310 output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
5313 output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
5314 output_asm_insn (AS2 (mov, %B0, %2), operands);
5316 if (cnst && ((INTVAL (src) & 0xff0000) == 0))
5317 output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
5320 output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
5321 output_asm_insn (AS2 (mov, %C0, %2), operands);
5323 if (cnst && ((INTVAL (src) & 0xff000000) == 0))
5324 output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
5327 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5328 output_asm_insn (AS2 (mov, %D0, %2), operands);
5334 avr_output_bld (rtx operands[], int bit_nr)
5336 static char s[] = "bld %A0,0";
5338 s[5] = 'A' + (bit_nr >> 3);
5339 s[8] = '0' + (bit_nr & 7);
5340 output_asm_insn (s, operands);
5344 avr_output_addr_vec_elt (FILE *stream, int value)
5347 fprintf (stream, "\t.word pm(.L%d)\n", value);
5349 fprintf (stream, "\trjmp .L%d\n", value);
5354 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5355 registers (for a define_peephole2) in the current function. */
5358 avr_peep2_scratch_safe (rtx scratch)
5360 if ((interrupt_function_p (current_function_decl)
5361 || signal_function_p (current_function_decl))
5362 && leaf_function_p ())
5364 int first_reg = true_regnum (scratch);
5365 int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
5368 for (reg = first_reg; reg <= last_reg; reg++)
5370 if (!regs_ever_live[reg])
5377 /* Output a branch that tests a single bit of a register (QI, HI or SImode)
5378 or memory location in the I/O space (QImode only).
5380 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5381 Operand 1: register operand to test, or CONST_INT memory address.
5382 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5383 Operand 3: label to jump to if the test is true. */
5386 avr_out_sbxx_branch (rtx insn, rtx operands[])
5388 enum rtx_code comp = GET_CODE (operands[0]);
5389 int long_jump = (get_attr_length (insn) >= 4);
5390 int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
5394 else if (comp == LT)
5398 comp = reverse_condition (comp);
5400 if (GET_CODE (operands[1]) == CONST_INT)
5402 if (INTVAL (operands[1]) < 0x40)
5405 output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
5407 output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
5411 output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
5413 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
5415 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
5418 else /* GET_CODE (operands[1]) == REG */
5420 if (GET_MODE (operands[1]) == QImode)
5423 output_asm_insn (AS2 (sbrs,%1,%2), operands);
5425 output_asm_insn (AS2 (sbrc,%1,%2), operands);
5427 else /* HImode or SImode */
5429 static char buf[] = "sbrc %A1,0";
5430 int bit_nr = exact_log2 (INTVAL (operands[2])
5431 & GET_MODE_MASK (GET_MODE (operands[1])));
5433 buf[3] = (comp == EQ) ? 's' : 'c';
5434 buf[6] = 'A' + (bit_nr >> 3);
5435 buf[9] = '0' + (bit_nr & 7);
5436 output_asm_insn (buf, operands);
5441 return (AS1 (rjmp,.+4) CR_TAB
5444 return AS1 (rjmp,%3);
5448 /* Worker function for TARGET_ASM_CONSTRUCTOR. */
5451 avr_asm_out_ctor (rtx symbol, int priority)
5453 fputs ("\t.global __do_global_ctors\n", asm_out_file);
5454 default_ctor_section_asm_out_constructor (symbol, priority);
5457 /* Worker function for TARGET_ASM_DESTRUCTOR. */
5460 avr_asm_out_dtor (rtx symbol, int priority)
5462 fputs ("\t.global __do_global_dtors\n", asm_out_file);
5463 default_dtor_section_asm_out_destructor (symbol, priority);
5466 /* Worker function for TARGET_RETURN_IN_MEMORY. */
5469 avr_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
5471 if (TYPE_MODE (type) == BLKmode)
5473 HOST_WIDE_INT size = int_size_in_bytes (type);
5474 return (size == -1 || size > 8);