1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Denis Chertykov (denisc@overta.ru)
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
26 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "conditions.h"
31 #include "insn-attr.h"
42 #include "target-def.h"
44 /* Maximal allowed offset for an address in the LD command */
45 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
47 static int avr_naked_function_p PARAMS ((tree));
48 static int interrupt_function_p PARAMS ((tree));
49 static int signal_function_p PARAMS ((tree));
50 static int avr_regs_to_save PARAMS ((HARD_REG_SET *));
51 static int sequent_regs_live PARAMS ((void));
52 static const char * ptrreg_to_str PARAMS ((int));
53 static const char * cond_string PARAMS ((enum rtx_code));
54 static int avr_num_arg_regs PARAMS ((enum machine_mode, tree));
55 static int out_adj_frame_ptr PARAMS ((FILE *, int));
56 static int out_set_stack_ptr PARAMS ((FILE *, int, int));
57 static RTX_CODE compare_condition PARAMS ((rtx insn));
58 static int compare_sign_p PARAMS ((rtx insn));
59 static int reg_was_0 PARAMS ((rtx insn, rtx op));
60 void debug_hard_reg_set PARAMS ((HARD_REG_SET set));
61 static tree avr_handle_progmem_attribute PARAMS ((tree *, tree, tree, int, bool *));
62 static tree avr_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
63 const struct attribute_spec avr_attribute_table[];
64 static bool avr_assemble_integer PARAMS ((rtx, unsigned int, int));
65 static void avr_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
66 static void avr_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
67 static void avr_unique_section PARAMS ((tree, int));
68 static void avr_encode_section_info PARAMS ((tree, int));
70 static void avr_asm_out_ctor PARAMS ((rtx, int));
71 static void avr_asm_out_dtor PARAMS ((rtx, int));
73 /* Allocate registers from r25 to r8 for parameters for function calls */
74 #define FIRST_CUM_REG 26
76 /* Temporary register RTX (gen_rtx (REG,QImode,TMP_REGNO)) */
79 /* Zeroed register RTX (gen_rtx (REG,QImode,ZERO_REGNO)) */
82 /* RTX for register which will be used for loading immediate values to
86 /* AVR register names {"r0", "r1", ..., "r31"} */
87 static const char *const avr_regnames[] = REGISTER_NAMES;
89 /* This holds the last insn address. */
90 static int last_insn_address = 0;
92 /* Commands count in the compiled file */
93 static int commands_in_file;
95 /* Commands in the functions prologues in the compiled file */
96 static int commands_in_prologues;
98 /* Commands in the functions epilogues in the compiled file */
99 static int commands_in_epilogues;
101 /* Prologue/Epilogue size in words */
102 static int prologue_size;
103 static int epilogue_size;
105 /* Size of all jump tables in the current function, in words. */
106 static int jump_tables_size;
108 /* Initial stack value specified by the `-minit-stack=' option */
109 const char *avr_init_stack = "__stack";
111 /* Default MCU name */
112 const char *avr_mcu_name = "avr2";
114 /* Preprocessor macros to define depending on MCU type. */
115 const char *avr_base_arch_macro;
116 const char *avr_extra_arch_macro;
118 /* More than 8K of program memory: use "call" and "jmp". */
121 /* Enhanced core: use "movw", "mul", ... */
122 int avr_enhanced_p = 0;
124 /* Assembler only. */
125 int avr_asm_only_p = 0;
131 const char *const macro;
134 static const struct base_arch_s avr_arch_types[] = {
135 { 1, 0, 0, NULL }, /* unknown device specified */
136 { 1, 0, 0, "__AVR_ARCH__=1" },
137 { 0, 0, 0, "__AVR_ARCH__=2" },
138 { 0, 0, 1, "__AVR_ARCH__=3" },
139 { 0, 1, 0, "__AVR_ARCH__=4" },
140 { 0, 1, 1, "__AVR_ARCH__=5" }
144 const char *const name;
145 int arch; /* index in avr_arch_types[] */
146 /* Must lie outside user's namespace. NULL == no macro. */
147 const char *const macro;
150 /* List of all known AVR MCU types - if updated, it has to be kept
151 in sync in several places (FIXME: is there a better way?):
153 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
154 - t-avr (MULTILIB_MATCHES)
155 - gas/config/tc-avr.c
158 static const struct mcu_type_s avr_mcu_types[] = {
159 /* Classic, <= 8K. */
161 { "at90s2313", 2, "__AVR_AT90S2313__" },
162 { "at90s2323", 2, "__AVR_AT90S2323__" },
163 { "at90s2333", 2, "__AVR_AT90S2333__" },
164 { "at90s2343", 2, "__AVR_AT90S2343__" },
165 { "attiny22", 2, "__AVR_ATtiny22__" },
166 { "attiny26", 2, "__AVR_ATtiny26__" },
167 { "at90s4414", 2, "__AVR_AT90S4414__" },
168 { "at90s4433", 2, "__AVR_AT90S4433__" },
169 { "at90s4434", 2, "__AVR_AT90S4434__" },
170 { "at90s8515", 2, "__AVR_AT90S8515__" },
171 { "at90c8534", 2, "__AVR_AT90C8534__" },
172 { "at90s8535", 2, "__AVR_AT90S8535__" },
175 { "atmega103", 3, "__AVR_ATmega103__" },
176 { "atmega603", 3, "__AVR_ATmega603__" },
177 { "at43usb320", 3, "__AVR_AT43USB320__" },
178 { "at43usb355", 3, "__AVR_AT43USB355__" },
179 { "at76c711", 3, "__AVR_AT76C711__" },
180 /* Enhanced, <= 8K. */
182 { "atmega8", 4, "__AVR_ATmega8__" },
183 { "atmega8515", 4, "__AVR_ATmega8515__" },
184 /* Enhanced, > 8K. */
186 { "atmega16", 5, "__AVR_ATmega16__" },
187 { "atmega161", 5, "__AVR_ATmega161__" },
188 { "atmega162", 5, "__AVR_ATmega162__" },
189 { "atmega163", 5, "__AVR_ATmega163__" },
190 { "atmega32", 5, "__AVR_ATmega32__" },
191 { "atmega323", 5, "__AVR_ATmega323__" },
192 { "atmega64", 5, "__AVR_ATmega64__" },
193 { "atmega128", 5, "__AVR_ATmega128__" },
194 { "at94k", 5, "__AVR_AT94K__" },
195 /* Assembler only. */
197 { "at90s1200", 1, "__AVR_AT90S1200__" },
198 { "attiny11", 1, "__AVR_ATtiny11__" },
199 { "attiny12", 1, "__AVR_ATtiny12__" },
200 { "attiny15", 1, "__AVR_ATtiny15__" },
201 { "attiny28", 1, "__AVR_ATtiny28__" },
205 int avr_case_values_threshold = 30000;
207 /* Initialize the GCC target structure. */
208 #undef TARGET_ASM_ALIGNED_HI_OP
209 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
210 #undef TARGET_ASM_INTEGER
211 #define TARGET_ASM_INTEGER avr_assemble_integer
213 #undef TARGET_ASM_FUNCTION_PROLOGUE
214 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
215 #undef TARGET_ASM_FUNCTION_EPILOGUE
216 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
217 #undef TARGET_ATTRIBUTE_TABLE
218 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
219 #undef TARGET_ASM_UNIQUE_SECTION
220 #define TARGET_ASM_UNIQUE_SECTION avr_unique_section
221 #undef TARGET_ENCODE_SECTION_INFO
222 #define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
224 struct gcc_target targetm = TARGET_INITIALIZER;
227 avr_override_options ()
229 const struct mcu_type_s *t;
230 const struct base_arch_s *base;
232 for (t = avr_mcu_types; t->name; t++)
233 if (strcmp (t->name, avr_mcu_name) == 0)
238 fprintf (stderr, "unknown MCU `%s' specified\nKnown MCU names:\n",
240 for (t = avr_mcu_types; t->name; t++)
241 fprintf (stderr," %s\n", t->name);
244 base = &avr_arch_types[t->arch];
245 avr_asm_only_p = base->asm_only;
246 avr_enhanced_p = base->enhanced;
247 avr_mega_p = base->mega;
248 avr_base_arch_macro = base->macro;
249 avr_extra_arch_macro = t->macro;
251 if (optimize && !TARGET_NO_TABLEJUMP)
252 avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
256 /* Initialize TMP_REG_RTX and ZERO_REG_RTX */
260 tmp_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
261 memset (tmp_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
262 PUT_CODE (tmp_reg_rtx, REG);
263 PUT_MODE (tmp_reg_rtx, QImode);
264 XINT (tmp_reg_rtx, 0) = TMP_REGNO;
266 zero_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
267 memset (zero_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
268 PUT_CODE (zero_reg_rtx, REG);
269 PUT_MODE (zero_reg_rtx, QImode);
270 XINT (zero_reg_rtx, 0) = ZERO_REGNO;
272 ldi_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
273 memset (ldi_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
274 PUT_CODE (ldi_reg_rtx, REG);
275 PUT_MODE (ldi_reg_rtx, QImode);
276 XINT (ldi_reg_rtx, 0) = LDI_REG_REGNO;
279 /* return register class from register number */
281 static const int reg_class_tab[]={
282 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
283 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
284 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
285 GENERAL_REGS, /* r0 - r15 */
286 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
287 LD_REGS, /* r16 - 23 */
288 ADDW_REGS,ADDW_REGS, /* r24,r25 */
289 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
290 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
291 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
292 STACK_REG,STACK_REG /* SPL,SPH */
295 /* Return register class for register R */
298 avr_regno_reg_class (r)
302 return reg_class_tab[r];
307 /* A C expression which defines the machine-dependent operand
308 constraint letters for register classes. If C is such a
309 letter, the value should be the register class corresponding to
310 it. Otherwise, the value should be `NO_REGS'. The register
311 letter `r', corresponding to class `GENERAL_REGS', will not be
312 passed to this macro; you do not need to handle it. */
315 avr_reg_class_from_letter (c)
320 case 't' : return R0_REG;
321 case 'b' : return BASE_POINTER_REGS;
322 case 'e' : return POINTER_REGS;
323 case 'w' : return ADDW_REGS;
324 case 'd' : return LD_REGS;
325 case 'l' : return NO_LD_REGS;
326 case 'a' : return SIMPLE_LD_REGS;
327 case 'x' : return POINTER_X_REGS;
328 case 'y' : return POINTER_Y_REGS;
329 case 'z' : return POINTER_Z_REGS;
330 case 'q' : return STACK_REG;
336 /* Return non-zero if FUNC is a naked function. */
339 avr_naked_function_p (func)
344 if (TREE_CODE (func) != FUNCTION_DECL)
347 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
348 return a != NULL_TREE;
351 /* Return nonzero if FUNC is an interrupt function as specified
352 by the "interrupt" attribute. */
355 interrupt_function_p (func)
360 if (TREE_CODE (func) != FUNCTION_DECL)
363 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
364 return a != NULL_TREE;
367 /* Return nonzero if FUNC is a signal function as specified
368 by the "signal" attribute. */
371 signal_function_p (func)
376 if (TREE_CODE (func) != FUNCTION_DECL)
379 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
380 return a != NULL_TREE;
383 /* Return the number of hard registers to push/pop in the prologue/epilogue
384 of the current function, and optionally store these registers in SET. */
387 avr_regs_to_save (set)
391 int int_or_sig_p = (interrupt_function_p (current_function_decl)
392 || signal_function_p (current_function_decl));
393 int leaf_func_p = leaf_function_p ();
396 CLEAR_HARD_REG_SET (*set);
399 /* No need to save any registers if the function never returns. */
400 if (TREE_THIS_VOLATILE (current_function_decl))
403 for (reg = 0; reg < 32; reg++)
405 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
406 any global register variables. */
410 if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
411 || (regs_ever_live[reg]
412 && (int_or_sig_p || !call_used_regs[reg])
413 && !(frame_pointer_needed
414 && (reg == REG_Y || reg == (REG_Y+1)))))
417 SET_HARD_REG_BIT (*set, reg);
424 /* Compute offset between arg_pointer and frame_pointer */
427 initial_elimination_offset (from, to)
431 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
435 int offset = frame_pointer_needed ? 2 : 0;
437 offset += avr_regs_to_save (NULL);
438 return get_frame_size () + 2 + 1 + offset;
442 /* This function checks sequence of live registers */
451 for (reg = 0; reg < 18; ++reg)
453 if (!call_used_regs[reg])
455 if (regs_ever_live[reg])
465 if (!frame_pointer_needed)
467 if (regs_ever_live[REG_Y])
475 if (regs_ever_live[REG_Y+1])
488 return (cur_seq == live_seq) ? live_seq : 0;
492 /* Output to FILE the asm instructions to adjust the frame pointer by
493 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
494 (epilogue). Returns the number of instructions generated. */
497 out_adj_frame_ptr (file, adj)
505 if (TARGET_TINY_STACK)
507 if (adj < -63 || adj > 63)
508 warning ("large frame pointer change (%d) with -mtiny-stack", adj);
510 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
511 over "sbiw" (2 cycles, same size). */
513 fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
516 else if (adj < -63 || adj > 63)
518 fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
519 AS2 (sbci, r29, hi8(%d)) CR_TAB),
525 fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
530 fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
538 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
539 handling various cases of interrupt enable flag state BEFORE and AFTER
540 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
541 Returns the number of instructions generated. */
544 out_set_stack_ptr (file, before, after)
549 int do_sph, do_cli, do_save, do_sei, lock_sph, size;
551 /* The logic here is so that -mno-interrupts actually means
552 "it is safe to write SPH in one instruction, then SPL in the
553 next instruction, without disabling interrupts first".
554 The after != -1 case (interrupt/signal) is not affected. */
556 do_sph = !TARGET_TINY_STACK;
557 lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
558 do_cli = (before != 0 && (after == 0 || lock_sph));
559 do_save = (do_cli && before == -1 && after == -1);
560 do_sei = ((do_cli || before != 1) && after == 1);
565 fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
571 fprintf (file, "cli" CR_TAB);
575 /* Do SPH first - maybe this will disable interrupts for one instruction
576 someday (a suggestion has been sent to avr@atmel.com for consideration
577 in future devices - that would make -mno-interrupts always safe). */
580 fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
584 /* Set/restore the I flag now - interrupts will be really enabled only
585 after the next instruction. This is not clearly documented, but
586 believed to be true for all AVR devices. */
589 fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
594 fprintf (file, "sei" CR_TAB);
598 fprintf (file, AS2 (out, __SP_L__, r28) "\n");
604 /* Output function prologue */
607 avr_output_function_prologue (file, size)
612 int interrupt_func_p;
618 last_insn_address = 0;
619 jump_tables_size = 0;
621 fprintf (file, "/* prologue: frame size=%d */\n", size);
623 if (avr_naked_function_p (current_function_decl))
625 fputs ("/* prologue: naked */\n", file);
629 interrupt_func_p = interrupt_function_p (current_function_decl);
630 signal_func_p = signal_function_p (current_function_decl);
631 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
632 live_seq = sequent_regs_live ();
633 minimize = (TARGET_CALL_PROLOGUES
634 && !interrupt_func_p && !signal_func_p && live_seq);
636 if (interrupt_func_p)
638 fprintf (file,"\tsei\n");
641 if (interrupt_func_p || signal_func_p)
644 AS1 (push,__zero_reg__) CR_TAB
645 AS1 (push,__tmp_reg__) CR_TAB
646 AS2 (in,__tmp_reg__,__SREG__) CR_TAB
647 AS1 (push,__tmp_reg__) CR_TAB
648 AS1 (clr,__zero_reg__) "\n");
654 AS2 (ldi,r28,lo8(%s - %d)) CR_TAB
655 AS2 (ldi,r29,hi8(%s - %d)) CR_TAB
656 AS2 (out,__SP_H__,r29) CR_TAB
657 AS2 (out,__SP_L__,r28) "\n"),
658 avr_init_stack, size, avr_init_stack, size);
662 else if (minimize && (frame_pointer_needed || live_seq > 6))
665 AS2 (ldi, r26, lo8(%d)) CR_TAB
666 AS2 (ldi, r27, hi8(%d)) CR_TAB), size, size);
668 fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB
669 AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB)
670 ,current_function_name, current_function_name);
676 fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
677 (18 - live_seq) * 2);
682 fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
683 (18 - live_seq) * 2);
686 fprintf (file, ".L_%s_body:\n", current_function_name);
692 prologue_size += avr_regs_to_save (&set);
693 for (reg = 0; reg < 32; ++reg)
695 if (TEST_HARD_REG_BIT (set, reg))
697 fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
700 if (frame_pointer_needed)
704 AS1 (push,r28) CR_TAB
705 AS1 (push,r29) CR_TAB
706 AS2 (in,r28,__SP_L__) CR_TAB
707 AS2 (in,r29,__SP_H__) "\n");
712 prologue_size += out_adj_frame_ptr (file, size);
714 if (interrupt_func_p)
716 prologue_size += out_set_stack_ptr (file, 1, 1);
718 else if (signal_func_p)
720 prologue_size += out_set_stack_ptr (file, 0, 0);
724 prologue_size += out_set_stack_ptr (file, -1, -1);
732 fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
735 /* Output function epilogue */
738 avr_output_function_epilogue (file, size)
743 int interrupt_func_p;
749 rtx last = get_last_nonnote_insn ();
751 function_size = jump_tables_size;
754 rtx first = get_first_nonnote_insn ();
755 function_size += (INSN_ADDRESSES (INSN_UID (last)) -
756 INSN_ADDRESSES (INSN_UID (first)));
757 function_size += get_attr_length (last);
760 fprintf (file, "/* epilogue: frame size=%d */\n", size);
763 if (avr_naked_function_p (current_function_decl))
765 fputs ("/* epilogue: naked */\n", file);
769 if (last && GET_CODE (last) == BARRIER)
771 fputs ("/* epilogue: noreturn */\n", file);
775 interrupt_func_p = interrupt_function_p (current_function_decl);
776 signal_func_p = signal_function_p (current_function_decl);
777 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
778 live_seq = sequent_regs_live ();
779 minimize = (TARGET_CALL_PROLOGUES
780 && !interrupt_func_p && !signal_func_p && live_seq);
784 /* Return value from main() is already in the correct registers
785 (r25:r24) as the exit() argument. */
788 fputs ("\t" AS1 (jmp,exit) "\n", file);
793 fputs ("\t" AS1 (rjmp,exit) "\n", file);
797 else if (minimize && (frame_pointer_needed || live_seq > 4))
799 fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
801 if (frame_pointer_needed)
803 epilogue_size += out_adj_frame_ptr (file, -size);
807 fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
808 AS2 (in , r29, __SP_H__) CR_TAB));
814 fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
815 (18 - live_seq) * 2);
820 fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
821 (18 - live_seq) * 2);
829 if (frame_pointer_needed)
834 epilogue_size += out_adj_frame_ptr (file, -size);
836 if (interrupt_func_p || signal_func_p)
838 epilogue_size += out_set_stack_ptr (file, -1, 0);
842 epilogue_size += out_set_stack_ptr (file, -1, -1);
851 epilogue_size += avr_regs_to_save (&set);
852 for (reg = 31; reg >= 0; --reg)
854 if (TEST_HARD_REG_BIT (set, reg))
856 fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
860 if (interrupt_func_p || signal_func_p)
863 AS1 (pop,__tmp_reg__) CR_TAB
864 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
865 AS1 (pop,__tmp_reg__) CR_TAB
866 AS1 (pop,__zero_reg__) "\n");
868 fprintf (file, "\treti\n");
871 fprintf (file, "\tret\n");
876 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
877 fprintf (file, "/* function %s size %d (%d) */\n", current_function_name,
878 prologue_size + function_size + epilogue_size, function_size);
879 commands_in_file += prologue_size + function_size + epilogue_size;
880 commands_in_prologues += prologue_size;
881 commands_in_epilogues += epilogue_size;
885 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
886 machine for a memory operand of mode MODE. */
889 legitimate_address_p (mode, x, strict)
890 enum machine_mode mode;
894 enum reg_class r = NO_REGS;
896 if (TARGET_ALL_DEBUG)
898 fprintf (stderr, "mode: (%s) %s %s %s %s:",
900 strict ? "(strict)": "",
901 reload_completed ? "(reload_completed)": "",
902 reload_in_progress ? "(reload_in_progress)": "",
903 reg_renumber ? "(reg_renumber)" : "");
904 if (GET_CODE (x) == PLUS
905 && REG_P (XEXP (x, 0))
906 && GET_CODE (XEXP (x, 1)) == CONST_INT
907 && INTVAL (XEXP (x, 1)) >= 0
908 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
911 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
912 true_regnum (XEXP (x, 0)));
915 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
916 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
918 else if (CONSTANT_ADDRESS_P (x))
920 else if (GET_CODE (x) == PLUS
921 && REG_P (XEXP (x, 0))
922 && GET_CODE (XEXP (x, 1)) == CONST_INT
923 && INTVAL (XEXP (x, 1)) >= 0)
925 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
929 || REGNO (XEXP (x,0)) == REG_Y
930 || REGNO (XEXP (x,0)) == REG_Z)
931 r = BASE_POINTER_REGS;
932 if (XEXP (x,0) == frame_pointer_rtx
933 || XEXP (x,0) == arg_pointer_rtx)
934 r = BASE_POINTER_REGS;
936 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
939 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
940 && REG_P (XEXP (x, 0))
941 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
942 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
946 if (TARGET_ALL_DEBUG)
948 fprintf (stderr, " ret = %c\n", r);
950 return r == NO_REGS ? 0 : (int)r;
953 /* Attempts to replace X with a valid
954 memory address for an operand of mode MODE */
957 legitimize_address (x, oldx, mode)
960 enum machine_mode mode;
963 if (TARGET_ALL_DEBUG)
965 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
969 if (GET_CODE (oldx) == PLUS
970 && REG_P (XEXP (oldx,0)))
972 if (REG_P (XEXP (oldx,1)))
973 x = force_reg (GET_MODE (oldx), oldx);
974 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
976 int offs = INTVAL (XEXP (oldx,1));
977 if (frame_pointer_rtx != XEXP (oldx,0))
978 if (offs > MAX_LD_OFFSET (mode))
980 if (TARGET_ALL_DEBUG)
981 fprintf (stderr, "force_reg (big offset)\n");
982 x = force_reg (GET_MODE (oldx), oldx);
990 /* Return a pointer register name as a string */
993 ptrreg_to_str (regno)
998 case REG_X: return "X";
999 case REG_Y: return "Y";
1000 case REG_Z: return "Z";
1007 /* Return the condition name as a string.
1008 Used in conditional jump constructing */
1021 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1026 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1039 /* Output ADDR to FILE as address */
1042 print_operand_address (file, addr)
1046 switch (GET_CODE (addr))
1049 fprintf (file, ptrreg_to_str (REGNO (addr)));
1053 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1057 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1061 if (CONSTANT_ADDRESS_P (addr)
1062 && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))
1063 || GET_CODE (addr) == LABEL_REF))
1065 fprintf (file, "pm(");
1066 output_addr_const (file,addr);
1067 fprintf (file ,")");
1070 output_addr_const (file, addr);
1075 /* Output X as assembler operand to file FILE */
1078 print_operand (file, x, code)
1085 if (code >= 'A' && code <= 'D')
1095 if (x == zero_reg_rtx)
1096 fprintf (file, "__zero_reg__");
1098 fprintf (file, reg_names[true_regnum (x) + abcd]);
1100 else if (GET_CODE (x) == CONST_INT)
1101 fprintf (file, "%d", INTVAL (x) + abcd);
1102 else if (GET_CODE (x) == MEM)
1104 rtx addr = XEXP (x,0);
1106 if (CONSTANT_P (addr) && abcd)
1109 output_address (addr);
1110 fprintf (file, ")+%d", abcd);
1112 else if (code == 'o')
1114 if (GET_CODE (addr) != PLUS)
1115 fatal_insn ("bad address, not (reg+disp):", addr);
1117 print_operand (file, XEXP (addr, 1), 0);
1119 else if (GET_CODE (addr) == PLUS)
1121 print_operand_address (file, XEXP (addr,0));
1122 if (REGNO (XEXP (addr, 0)) == REG_X)
1123 fatal_insn ("internal compiler error. Bad address:"
1126 print_operand (file, XEXP (addr,1), code);
1129 print_operand_address (file, addr);
1131 else if (GET_CODE (x) == CONST_DOUBLE)
1135 if (GET_MODE (x) != SFmode)
1136 fatal_insn ("internal compiler error. Unknown mode:", x);
1137 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1138 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1139 asm_fprintf (file, "0x%lx", val);
1141 else if (code == 'j')
1142 asm_fprintf (file, cond_string (GET_CODE (x)));
1143 else if (code == 'k')
1144 asm_fprintf (file, cond_string (reverse_condition (GET_CODE (x))));
1146 print_operand_address (file, x);
1149 /* Recognize operand OP of mode MODE used in call instructions */
1152 call_insn_operand (op, mode)
1154 enum machine_mode mode ATTRIBUTE_UNUSED;
1156 if (GET_CODE (op) == MEM)
1158 rtx inside = XEXP (op, 0);
1159 if (register_operand (inside, Pmode))
1161 if (CONSTANT_ADDRESS_P (inside))
1167 /* Update the condition code in the INSN. */
1170 notice_update_cc (body, insn)
1171 rtx body ATTRIBUTE_UNUSED;
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
1234 cc_status.value1 = SET_DEST (set);
1235 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1243 /* Return maximum number of consecutive registers of
1244 class CLASS needed to hold a value of mode MODE. */
1247 class_max_nregs (class, mode)
1248 enum reg_class class ATTRIBUTE_UNUSED;
1249 enum machine_mode mode;
1251 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1254 /* Choose mode for jump insn:
1255 1 - relative jump in range -63 <= x <= 62 ;
1256 2 - relative jump in range -2046 <= x <= 2045 ;
1257 3 - absolute jump (only for ATmega[16]03). */
1260 avr_jump_mode (x, insn)
1261 rtx x; /* jump operand */
1262 rtx insn; /* jump insn */
1264 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1265 ? XEXP (x, 0) : x));
1266 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1267 int jump_distance = cur_addr - dest_addr;
1269 if (-63 <= jump_distance && jump_distance <= 62)
1271 else if (-2046 <= jump_distance && jump_distance <= 2045)
1279 /* return an AVR condition jump commands.
1280 X is a comparison RTX.
1281 LEN is a number returned by avr_jump_mode function.
1282 if REVERSE nonzero then condition code in X must be reversed. */
1285 ret_cond_branch (x, len, reverse)
1290 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1295 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1296 return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1298 len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1299 AS1 (brmi,_PC_+2) CR_TAB
1301 (AS1 (breq,_PC_+6) CR_TAB
1302 AS1 (brmi,_PC_+4) CR_TAB
1306 return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1308 len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1309 AS1 (brlt,_PC_+2) CR_TAB
1311 (AS1 (breq,_PC_+6) CR_TAB
1312 AS1 (brlt,_PC_+4) CR_TAB
1315 return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1317 len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1318 AS1 (brlo,_PC_+2) CR_TAB
1320 (AS1 (breq,_PC_+6) CR_TAB
1321 AS1 (brlo,_PC_+4) CR_TAB
1324 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1325 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1327 len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1328 AS1 (brpl,_PC_+2) CR_TAB
1330 (AS1 (breq,_PC_+2) CR_TAB
1331 AS1 (brpl,_PC_+4) CR_TAB
1334 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1336 len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1337 AS1 (brge,_PC_+2) CR_TAB
1339 (AS1 (breq,_PC_+2) CR_TAB
1340 AS1 (brge,_PC_+4) CR_TAB
1343 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1345 len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1346 AS1 (brsh,_PC_+2) CR_TAB
1348 (AS1 (breq,_PC_+2) CR_TAB
1349 AS1 (brsh,_PC_+4) CR_TAB
1357 return AS1 (br%k1,%0);
1359 return (AS1 (br%j1,_PC_+2) CR_TAB
1362 return (AS1 (br%j1,_PC_+4) CR_TAB
1371 return AS1 (br%j1,%0);
1373 return (AS1 (br%k1,_PC_+2) CR_TAB
1376 return (AS1 (br%k1,_PC_+4) CR_TAB
1384 /* Predicate function for immediate operand which fits to byte (8bit) */
1387 byte_immediate_operand (op, mode)
1389 enum machine_mode mode ATTRIBUTE_UNUSED;
1391 return (GET_CODE (op) == CONST_INT
1392 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1395 /* Output all insn addresses and their sizes into the assembly language
1396 output file. This is helpful for debugging whether the length attributes
1397 in the md file are correct.
1398 Output insn cost for next insn. */
1401 final_prescan_insn (insn, operand, num_operands)
1402 rtx insn, *operand ATTRIBUTE_UNUSED;
1403 int num_operands ATTRIBUTE_UNUSED;
1405 int uid = INSN_UID (insn);
1407 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1409 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1410 INSN_ADDRESSES (uid),
1411 INSN_ADDRESSES (uid) - last_insn_address,
1412 rtx_cost (PATTERN (insn), INSN));
1414 last_insn_address = INSN_ADDRESSES (uid);
1416 if (TARGET_RTL_DUMP)
1418 fprintf (asm_out_file, "/*****************\n");
1419 print_rtl_single (asm_out_file, insn);
1420 fprintf (asm_out_file, "*****************/\n");
1424 /* Return 0 if undefined, 1 if always true or always false. */
1427 avr_simplify_comparision_p (mode, operator, x)
1428 enum machine_mode mode;
1432 unsigned int max = (mode == QImode ? 0xff :
1433 mode == HImode ? 0xffff :
1434 mode == SImode ? 0xffffffff : 0);
1435 if (max && operator && GET_CODE (x) == CONST_INT)
1437 if (unsigned_condition (operator) != operator)
1440 if (max != (INTVAL (x) & max)
1441 && INTVAL (x) != 0xff)
1448 /* Returns nonzero if REGNO is the number of a hard
1449 register in which function arguments are sometimes passed. */
1452 function_arg_regno_p(r)
1455 return (r >= 8 && r <= 25);
1458 /* Initializing the variable cum for the state at the beginning
1459 of the argument list. */
1462 init_cumulative_args (cum, fntype, libname, indirect)
1463 CUMULATIVE_ARGS *cum;
1466 int indirect ATTRIBUTE_UNUSED;
1469 cum->regno = FIRST_CUM_REG;
1472 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1473 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1474 != void_type_node));
1480 /* Returns the number of registers to allocate for a function argument. */
1483 avr_num_arg_regs (mode, type)
1484 enum machine_mode mode;
1489 if (mode == BLKmode)
1490 size = int_size_in_bytes (type);
1492 size = GET_MODE_SIZE (mode);
1494 /* Align all function arguments to start in even-numbered registers.
1495 Odd-sized arguments leave holes above them. */
1497 return (size + 1) & ~1;
1500 /* Controls whether a function argument is passed
1501 in a register, and which register. */
1504 function_arg (cum, mode, type, named)
1505 CUMULATIVE_ARGS *cum;
1506 enum machine_mode mode;
1508 int named ATTRIBUTE_UNUSED;
1510 int bytes = avr_num_arg_regs (mode, type);
1512 if (cum->nregs && bytes <= cum->nregs)
1513 return gen_rtx (REG, mode, cum->regno - bytes);
1518 /* Update the summarizer variable CUM to advance past an argument
1519 in the argument list. */
1522 function_arg_advance (cum, mode, type, named)
1523 CUMULATIVE_ARGS *cum; /* current arg information */
1524 enum machine_mode mode; /* current arg mode */
1525 tree type; /* type of the argument or 0 if lib support */
1526 int named ATTRIBUTE_UNUSED; /* whether or not the argument was named */
1528 int bytes = avr_num_arg_regs (mode, type);
1530 cum->nregs -= bytes;
1531 cum->regno -= bytes;
1533 if (cum->nregs <= 0)
1536 cum->regno = FIRST_CUM_REG;
1540 /***********************************************************************
1541 Functions for outputting various mov's for a various modes
1542 ************************************************************************/
1544 output_movqi (insn, operands, l)
1550 rtx dest = operands[0];
1551 rtx src = operands[1];
1559 if (register_operand (dest, QImode))
1561 if (register_operand (src, QImode)) /* mov r,r */
1563 if (test_hard_reg_class (STACK_REG, dest))
1564 return AS2 (out,%0,%1);
1565 else if (test_hard_reg_class (STACK_REG, src))
1566 return AS2 (in,%0,%1);
1568 return AS2 (mov,%0,%1);
1570 else if (CONSTANT_P (src))
1572 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1573 return AS2 (ldi,%0,lo8(%1));
1575 if (GET_CODE (src) == CONST_INT)
1577 if (src == const0_rtx) /* mov r,L */
1578 return AS1 (clr,%0);
1579 else if (src == const1_rtx)
1581 if (reg_was_0 (insn, dest))
1582 return AS1 (inc,%0 ; reg_was_0);
1585 return (AS1 (clr,%0) CR_TAB
1588 else if (src == constm1_rtx)
1590 /* Immediate constants -1 to any register */
1591 if (reg_was_0 (insn, dest))
1592 return AS1 (dec,%0 ; reg_was_0);
1595 return (AS1 (clr,%0) CR_TAB
1600 int bit_nr = exact_log2 (INTVAL (src));
1604 if (reg_was_0 (insn, dest))
1608 output_asm_insn ("set ; reg_was_0", operands);
1614 output_asm_insn ((AS1 (clr,%0) CR_TAB
1618 avr_output_bld (operands, bit_nr);
1625 /* Last resort, larger than loading from memory. */
1627 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1628 AS2 (ldi,r31,lo8(%1)) CR_TAB
1629 AS2 (mov,%0,r31) CR_TAB
1630 AS2 (mov,r31,__tmp_reg__));
1632 else if (GET_CODE (src) == MEM)
1633 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1635 else if (GET_CODE (dest) == MEM)
1637 const char *template;
1639 if (src == const0_rtx)
1640 operands[1] = zero_reg_rtx;
1642 template = out_movqi_mr_r (insn, operands, real_l);
1645 output_asm_insn (template, operands);
1654 output_movhi (insn, operands, l)
1660 rtx dest = operands[0];
1661 rtx src = operands[1];
1667 if (register_operand (dest, HImode))
1669 if (register_operand (src, HImode)) /* mov r,r */
1671 if (test_hard_reg_class (STACK_REG, dest))
1673 if (TARGET_TINY_STACK)
1676 return AS2 (out,__SP_L__,%A1);
1678 else if (TARGET_NO_INTERRUPTS)
1681 return (AS2 (out,__SP_H__,%B1) CR_TAB
1682 AS2 (out,__SP_L__,%A1));
1686 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1688 AS2 (out,__SP_H__,%B1) CR_TAB
1689 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1690 AS2 (out,__SP_L__,%A1));
1692 else if (test_hard_reg_class (STACK_REG, src))
1695 return (AS2 (in,%A0,__SP_L__) CR_TAB
1696 AS2 (in,%B0,__SP_H__));
1702 return (AS2 (movw,%0,%1));
1705 if (true_regnum (dest) > true_regnum (src))
1708 return (AS2 (mov,%B0,%B1) CR_TAB
1714 return (AS2 (mov,%A0,%A1) CR_TAB
1718 else if (CONSTANT_P (src))
1720 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1722 if (byte_immediate_operand (src, HImode)
1723 && reg_was_0 (insn, dest))
1726 return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0));
1730 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1731 AS2 (ldi,%B0,hi8(%1)));
1734 if (GET_CODE (src) == CONST_INT)
1736 if (src == const0_rtx) /* mov r,L */
1739 return (AS1 (clr,%A0) CR_TAB
1742 else if (src == const1_rtx)
1744 if (reg_was_0 (insn, dest))
1747 return AS1 (inc,%0 ; reg_was_0);
1751 return (AS1 (clr,%A0) CR_TAB
1752 AS1 (clr,%B0) CR_TAB
1755 else if (src == constm1_rtx)
1757 /* Immediate constants -1 to any register */
1758 if (reg_was_0 (insn, dest))
1761 return (AS1 (dec,%A0 ; reg_was_0) CR_TAB
1766 return (AS1 (clr,%0) CR_TAB
1767 AS1 (dec,%A0) CR_TAB
1772 int bit_nr = exact_log2 (INTVAL (src));
1776 if (reg_was_0 (insn, dest))
1780 output_asm_insn ("set ; reg_was_0", operands);
1786 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1787 AS1 (clr,%B0) CR_TAB
1791 avr_output_bld (operands, bit_nr);
1797 if ((INTVAL (src) & 0xff) == 0)
1800 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1801 AS1 (clr,%A0) CR_TAB
1802 AS2 (ldi,r31,hi8(%1)) CR_TAB
1803 AS2 (mov,%B0,r31) CR_TAB
1804 AS2 (mov,r31,__tmp_reg__));
1806 else if ((INTVAL (src) & 0xff00) == 0)
1809 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1810 AS2 (ldi,r31,lo8(%1)) CR_TAB
1811 AS2 (mov,%A0,r31) CR_TAB
1812 AS1 (clr,%B0) CR_TAB
1813 AS2 (mov,r31,__tmp_reg__));
1817 /* Last resort, equal to loading from memory. */
1819 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1820 AS2 (ldi,r31,lo8(%1)) CR_TAB
1821 AS2 (mov,%A0,r31) CR_TAB
1822 AS2 (ldi,r31,hi8(%1)) CR_TAB
1823 AS2 (mov,%B0,r31) CR_TAB
1824 AS2 (mov,r31,__tmp_reg__));
1826 else if (GET_CODE (src) == MEM)
1827 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1829 else if (GET_CODE (dest) == MEM)
1831 const char *template;
1833 if (src == const0_rtx)
1834 operands[1] = zero_reg_rtx;
1836 template = out_movhi_mr_r (insn, operands, real_l);
1839 output_asm_insn (template, operands);
1844 fatal_insn ("invalid insn:", insn);
1849 out_movqi_r_mr (insn, op, l)
1852 int *l; /* instruction length */
1856 rtx x = XEXP (src, 0);
1862 if (CONSTANT_ADDRESS_P (x))
1864 if (avr_io_address_p (x, 1))
1867 return AS2 (in,%0,%1-0x20);
1870 return AS2 (lds,%0,%1);
1872 /* memory access by reg+disp */
1873 else if (GET_CODE (x) == PLUS
1874 && REG_P (XEXP (x,0))
1875 && GET_CODE (XEXP (x,1)) == CONST_INT)
1877 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
1879 int disp = INTVAL (XEXP (x,1));
1880 if (REGNO (XEXP (x,0)) != REG_Y)
1881 fatal_insn ("incorrect insn:",insn);
1883 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1884 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1885 AS2 (ldd,%0,Y+63) CR_TAB
1886 AS2 (sbiw,r28,%o1-63));
1888 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1889 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1890 AS2 (ld,%0,Y) CR_TAB
1891 AS2 (subi,r28,lo8(%o1)) CR_TAB
1892 AS2 (sbci,r29,hi8(%o1)));
1894 else if (REGNO (XEXP (x,0)) == REG_X)
1896 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1897 it but I have this situation with extremal optimizing options. */
1898 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
1899 || reg_unused_after (insn, XEXP (x,0)))
1900 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1903 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1904 AS2 (ld,%0,X) CR_TAB
1905 AS2 (sbiw,r26,%o1));
1908 return AS2 (ldd,%0,%1);
1911 return AS2 (ld,%0,%1);
1915 out_movhi_r_mr (insn, op, l)
1918 int *l; /* instruction length */
1922 rtx base = XEXP (src, 0);
1923 int reg_dest = true_regnum (dest);
1924 int reg_base = true_regnum (base);
1932 if (reg_dest == reg_base) /* R = (R) */
1935 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1936 AS2 (ld,%B0,%1) CR_TAB
1937 AS2 (mov,%A0,__tmp_reg__));
1939 else if (reg_base == REG_X) /* (R26) */
1941 if (reg_unused_after (insn, base))
1944 return (AS2 (ld,%A0,X+) CR_TAB
1948 return (AS2 (ld,%A0,X+) CR_TAB
1949 AS2 (ld,%B0,X) CR_TAB
1955 return (AS2 (ld,%A0,%1) CR_TAB
1956 AS2 (ldd,%B0,%1+1));
1959 else if (GET_CODE (base) == PLUS) /* (R + i) */
1961 int disp = INTVAL (XEXP (base, 1));
1962 int reg_base = true_regnum (XEXP (base, 0));
1964 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
1966 if (REGNO (XEXP (base, 0)) != REG_Y)
1967 fatal_insn ("incorrect insn:",insn);
1969 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1970 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
1971 AS2 (ldd,%A0,Y+62) CR_TAB
1972 AS2 (ldd,%B0,Y+63) CR_TAB
1973 AS2 (sbiw,r28,%o1-62));
1975 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1976 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1977 AS2 (ld,%A0,Y) CR_TAB
1978 AS2 (ldd,%B0,Y+1) CR_TAB
1979 AS2 (subi,r28,lo8(%o1)) CR_TAB
1980 AS2 (sbci,r29,hi8(%o1)));
1982 if (reg_base == REG_X)
1984 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1985 it but I have this situation with extremal
1986 optimization options. */
1989 if (reg_base == reg_dest)
1990 return (AS2 (adiw,r26,%o1) CR_TAB
1991 AS2 (ld,__tmp_reg__,X+) CR_TAB
1992 AS2 (ld,%B0,X) CR_TAB
1993 AS2 (mov,%A0,__tmp_reg__));
1995 return (AS2 (adiw,r26,%o1) CR_TAB
1996 AS2 (ld,%A0,X+) CR_TAB
1997 AS2 (ld,%B0,X) CR_TAB
1998 AS2 (sbiw,r26,%o1+1));
2001 if (reg_base == reg_dest)
2004 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
2005 AS2 (ldd,%B0,%B1) CR_TAB
2006 AS2 (mov,%A0,__tmp_reg__));
2010 return (AS2 (ldd,%A0,%A1) CR_TAB
2013 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2015 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
2016 fatal_insn ("incorrect insn:", insn);
2019 return (AS2 (ld,%B0,%1) CR_TAB
2022 else if (GET_CODE (base) == POST_INC) /* (R++) */
2024 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
2025 fatal_insn ("incorrect insn:", insn);
2028 return (AS2 (ld,%A0,%1) CR_TAB
2031 else if (CONSTANT_ADDRESS_P (base))
2033 if (avr_io_address_p (base, 2))
2036 return (AS2 (in,%A0,%A1-0x20) CR_TAB
2037 AS2 (in,%B0,%B1-0x20));
2040 return (AS2 (lds,%A0,%A1) CR_TAB
2044 fatal_insn ("unknown move insn:",insn);
2049 out_movsi_r_mr (insn, op, l)
2052 int *l; /* instruction length */
2056 rtx base = XEXP (src, 0);
2057 int reg_dest = true_regnum (dest);
2058 int reg_base = true_regnum (base);
2066 if (reg_base == REG_X) /* (R26) */
2068 if (reg_dest == REG_X)
2069 /* "ld r26,-X" is undefined */
2070 return *l=7, (AS2 (adiw,r26,3) CR_TAB
2071 AS2 (ld,r29,X) CR_TAB
2072 AS2 (ld,r28,-X) CR_TAB
2073 AS2 (ld,__tmp_reg__,-X) CR_TAB
2074 AS2 (sbiw,r26,1) CR_TAB
2075 AS2 (ld,r26,X) CR_TAB
2076 AS2 (mov,r27,__tmp_reg__));
2077 else if (reg_dest == REG_X - 2)
2078 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2079 AS2 (ld,%B0,X+) CR_TAB
2080 AS2 (ld,__tmp_reg__,X+) CR_TAB
2081 AS2 (ld,%D0,X) CR_TAB
2082 AS2 (mov,%C0,__tmp_reg__));
2083 else if (reg_unused_after (insn, base))
2084 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
2085 AS2 (ld,%B0,X+) CR_TAB
2086 AS2 (ld,%C0,X+) CR_TAB
2089 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2090 AS2 (ld,%B0,X+) CR_TAB
2091 AS2 (ld,%C0,X+) CR_TAB
2092 AS2 (ld,%D0,X) CR_TAB
2097 if (reg_dest == reg_base)
2098 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2099 AS2 (ldd,%C0,%1+2) CR_TAB
2100 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2101 AS2 (ld,%A0,%1) CR_TAB
2102 AS2 (mov,%B0,__tmp_reg__));
2103 else if (reg_base == reg_dest + 2)
2104 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2105 AS2 (ldd,%B0,%1+1) CR_TAB
2106 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2107 AS2 (ldd,%D0,%1+3) CR_TAB
2108 AS2 (mov,%C0,__tmp_reg__));
2110 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2111 AS2 (ldd,%B0,%1+1) CR_TAB
2112 AS2 (ldd,%C0,%1+2) CR_TAB
2113 AS2 (ldd,%D0,%1+3));
2116 else if (GET_CODE (base) == PLUS) /* (R + i) */
2118 int disp = INTVAL (XEXP (base, 1));
2120 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2122 if (REGNO (XEXP (base, 0)) != REG_Y)
2123 fatal_insn ("incorrect insn:",insn);
2125 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2126 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2127 AS2 (ldd,%A0,Y+60) CR_TAB
2128 AS2 (ldd,%B0,Y+61) CR_TAB
2129 AS2 (ldd,%C0,Y+62) CR_TAB
2130 AS2 (ldd,%D0,Y+63) CR_TAB
2131 AS2 (sbiw,r28,%o1-60));
2133 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2134 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2135 AS2 (ld,%A0,Y) CR_TAB
2136 AS2 (ldd,%B0,Y+1) CR_TAB
2137 AS2 (ldd,%C0,Y+2) CR_TAB
2138 AS2 (ldd,%D0,Y+3) CR_TAB
2139 AS2 (subi,r28,lo8(%o1)) CR_TAB
2140 AS2 (sbci,r29,hi8(%o1)));
2143 reg_base = true_regnum (XEXP (base, 0));
2144 if (reg_base == REG_X)
2147 if (reg_dest == REG_X)
2150 /* "ld r26,-X" is undefined */
2151 return (AS2 (adiw,r26,%o1+3) CR_TAB
2152 AS2 (ld,r29,X) CR_TAB
2153 AS2 (ld,r28,-X) CR_TAB
2154 AS2 (ld,__tmp_reg__,-X) CR_TAB
2155 AS2 (sbiw,r26,1) CR_TAB
2156 AS2 (ld,r26,X) CR_TAB
2157 AS2 (mov,r27,__tmp_reg__));
2160 if (reg_dest == REG_X - 2)
2161 return (AS2 (adiw,r26,%o1) CR_TAB
2162 AS2 (ld,r24,X+) CR_TAB
2163 AS2 (ld,r25,X+) CR_TAB
2164 AS2 (ld,__tmp_reg__,X+) CR_TAB
2165 AS2 (ld,r27,X) CR_TAB
2166 AS2 (mov,r26,__tmp_reg__));
2168 return (AS2 (adiw,r26,%o1) CR_TAB
2169 AS2 (ld,%A0,X+) CR_TAB
2170 AS2 (ld,%B0,X+) CR_TAB
2171 AS2 (ld,%C0,X+) CR_TAB
2172 AS2 (ld,%D0,X) CR_TAB
2173 AS2 (sbiw,r26,%o1+3));
2175 if (reg_dest == reg_base)
2176 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2177 AS2 (ldd,%C0,%C1) CR_TAB
2178 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2179 AS2 (ldd,%A0,%A1) CR_TAB
2180 AS2 (mov,%B0,__tmp_reg__));
2181 else if (reg_dest == reg_base - 2)
2182 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2183 AS2 (ldd,%B0,%B1) CR_TAB
2184 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2185 AS2 (ldd,%D0,%D1) CR_TAB
2186 AS2 (mov,%C0,__tmp_reg__));
2187 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2188 AS2 (ldd,%B0,%B1) CR_TAB
2189 AS2 (ldd,%C0,%C1) CR_TAB
2192 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2193 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2194 AS2 (ld,%C0,%1) CR_TAB
2195 AS2 (ld,%B0,%1) CR_TAB
2197 else if (GET_CODE (base) == POST_INC) /* (R++) */
2198 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2199 AS2 (ld,%B0,%1) CR_TAB
2200 AS2 (ld,%C0,%1) CR_TAB
2202 else if (CONSTANT_ADDRESS_P (base))
2203 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2204 AS2 (lds,%B0,%B1) CR_TAB
2205 AS2 (lds,%C0,%C1) CR_TAB
2208 fatal_insn ("unknown move insn:",insn);
2213 out_movsi_mr_r (insn, op, l)
2220 rtx base = XEXP (dest, 0);
2221 int reg_base = true_regnum (base);
2222 int reg_src = true_regnum (src);
2228 if (CONSTANT_ADDRESS_P (base))
2229 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2230 AS2 (sts,%B0,%B1) CR_TAB
2231 AS2 (sts,%C0,%C1) CR_TAB
2233 if (reg_base > 0) /* (r) */
2235 if (reg_base == REG_X) /* (R26) */
2237 if (reg_src == REG_X)
2239 /* "st X+,r26" is undefined */
2240 if (reg_unused_after (insn, base))
2241 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2242 AS2 (st,X,r26) CR_TAB
2243 AS2 (adiw,r26,1) CR_TAB
2244 AS2 (st,X+,__tmp_reg__) CR_TAB
2245 AS2 (st,X+,r28) CR_TAB
2248 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2249 AS2 (st,X,r26) CR_TAB
2250 AS2 (adiw,r26,1) CR_TAB
2251 AS2 (st,X+,__tmp_reg__) CR_TAB
2252 AS2 (st,X+,r28) CR_TAB
2253 AS2 (st,X,r29) CR_TAB
2256 else if (reg_base == reg_src + 2)
2258 if (reg_unused_after (insn, base))
2259 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2260 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2261 AS2 (st,%0+,%A1) CR_TAB
2262 AS2 (st,%0+,%B1) CR_TAB
2263 AS2 (st,%0+,__zero_reg__) CR_TAB
2264 AS2 (st,%0,__tmp_reg__) CR_TAB
2265 AS1 (clr,__zero_reg__));
2267 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2268 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2269 AS2 (st,%0+,%A1) CR_TAB
2270 AS2 (st,%0+,%B1) CR_TAB
2271 AS2 (st,%0+,__zero_reg__) CR_TAB
2272 AS2 (st,%0,__tmp_reg__) CR_TAB
2273 AS1 (clr,__zero_reg__) CR_TAB
2276 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2277 AS2 (st,%0+,%B1) CR_TAB
2278 AS2 (st,%0+,%C1) CR_TAB
2279 AS2 (st,%0,%D1) CR_TAB
2283 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2284 AS2 (std,%0+1,%B1) CR_TAB
2285 AS2 (std,%0+2,%C1) CR_TAB
2286 AS2 (std,%0+3,%D1));
2288 else if (GET_CODE (base) == PLUS) /* (R + i) */
2290 int disp = INTVAL (XEXP (base, 1));
2291 reg_base = REGNO (XEXP (base, 0));
2292 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2294 if (reg_base != REG_Y)
2295 fatal_insn ("incorrect insn:",insn);
2297 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2298 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2299 AS2 (std,Y+60,%A1) CR_TAB
2300 AS2 (std,Y+61,%B1) CR_TAB
2301 AS2 (std,Y+62,%C1) CR_TAB
2302 AS2 (std,Y+63,%D1) CR_TAB
2303 AS2 (sbiw,r28,%o0-60));
2305 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2306 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2307 AS2 (st,Y,%A1) CR_TAB
2308 AS2 (std,Y+1,%B1) CR_TAB
2309 AS2 (std,Y+2,%C1) CR_TAB
2310 AS2 (std,Y+3,%D1) CR_TAB
2311 AS2 (subi,r28,lo8(%o0)) CR_TAB
2312 AS2 (sbci,r29,hi8(%o0)));
2314 if (reg_base == REG_X)
2317 if (reg_src == REG_X)
2320 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2321 AS2 (mov,__zero_reg__,r27) CR_TAB
2322 AS2 (adiw,r26,%o0) CR_TAB
2323 AS2 (st,X+,__tmp_reg__) CR_TAB
2324 AS2 (st,X+,__zero_reg__) CR_TAB
2325 AS2 (st,X+,r28) CR_TAB
2326 AS2 (st,X,r29) CR_TAB
2327 AS1 (clr,__zero_reg__) CR_TAB
2328 AS2 (sbiw,r26,%o0+3));
2330 else if (reg_src == REG_X - 2)
2333 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2334 AS2 (mov,__zero_reg__,r27) CR_TAB
2335 AS2 (adiw,r26,%o0) CR_TAB
2336 AS2 (st,X+,r24) CR_TAB
2337 AS2 (st,X+,r25) CR_TAB
2338 AS2 (st,X+,__tmp_reg__) CR_TAB
2339 AS2 (st,X,__zero_reg__) CR_TAB
2340 AS1 (clr,__zero_reg__) CR_TAB
2341 AS2 (sbiw,r26,%o0+3));
2344 return (AS2 (adiw,r26,%o0) CR_TAB
2345 AS2 (st,X+,%A1) CR_TAB
2346 AS2 (st,X+,%B1) CR_TAB
2347 AS2 (st,X+,%C1) CR_TAB
2348 AS2 (st,X,%D1) CR_TAB
2349 AS2 (sbiw,r26,%o0+3));
2351 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2352 AS2 (std,%B0,%B1) CR_TAB
2353 AS2 (std,%C0,%C1) CR_TAB
2356 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2357 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2358 AS2 (st,%0,%C1) CR_TAB
2359 AS2 (st,%0,%B1) CR_TAB
2361 else if (GET_CODE (base) == POST_INC) /* (R++) */
2362 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2363 AS2 (st,%0,%B1) CR_TAB
2364 AS2 (st,%0,%C1) CR_TAB
2366 fatal_insn ("unknown move insn:",insn);
2371 output_movsisf(insn, operands, l)
2377 rtx dest = operands[0];
2378 rtx src = operands[1];
2384 if (register_operand (dest, VOIDmode))
2386 if (register_operand (src, VOIDmode)) /* mov r,r */
2388 if (true_regnum (dest) > true_regnum (src))
2393 return (AS2 (movw,%C0,%C1) CR_TAB
2394 AS2 (movw,%A0,%A1));
2397 return (AS2 (mov,%D0,%D1) CR_TAB
2398 AS2 (mov,%C0,%C1) CR_TAB
2399 AS2 (mov,%B0,%B1) CR_TAB
2407 return (AS2 (movw,%A0,%A1) CR_TAB
2408 AS2 (movw,%C0,%C1));
2411 return (AS2 (mov,%A0,%A1) CR_TAB
2412 AS2 (mov,%B0,%B1) CR_TAB
2413 AS2 (mov,%C0,%C1) CR_TAB
2417 else if (CONSTANT_P (src))
2419 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2421 if (byte_immediate_operand (src, SImode)
2422 && reg_was_0 (insn, dest))
2425 return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0));
2429 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2430 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2431 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2432 AS2 (ldi,%D0,hhi8(%1)));
2435 if (GET_CODE (src) == CONST_INT)
2437 const char *const clr_op0 =
2438 AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
2439 AS1 (clr,%B0) CR_TAB
2441 : (AS1 (clr,%A0) CR_TAB
2442 AS1 (clr,%B0) CR_TAB
2443 AS1 (clr,%C0) CR_TAB
2446 if (src == const0_rtx) /* mov r,L */
2448 *l = AVR_ENHANCED ? 3 : 4;
2451 else if (src == const1_rtx)
2453 if (reg_was_0 (insn, dest))
2456 return AS1 (inc,%A0 ; reg_was_0);
2459 output_asm_insn (clr_op0, operands);
2460 *l = AVR_ENHANCED ? 4 : 5;
2461 return AS1 (inc,%A0);
2463 else if (src == constm1_rtx)
2465 /* Immediate constants -1 to any register */
2466 if (reg_was_0 (insn, dest))
2471 return (AS1 (dec,%A0) CR_TAB
2472 AS1 (dec,%B0) CR_TAB
2473 AS2 (movw,%C0,%A0));
2476 return (AS1 (dec,%D0 ; reg_was_0) CR_TAB
2477 AS1 (dec,%C0) CR_TAB
2478 AS1 (dec,%B0) CR_TAB
2484 return (AS1 (clr,%A0) CR_TAB
2485 AS1 (dec,%A0) CR_TAB
2486 AS2 (mov,%B0,%A0) CR_TAB
2487 AS2 (movw,%C0,%A0));
2490 return (AS1 (clr,%A0) CR_TAB
2491 AS1 (dec,%A0) CR_TAB
2492 AS2 (mov,%B0,%A0) CR_TAB
2493 AS2 (mov,%C0,%A0) CR_TAB
2498 int bit_nr = exact_log2 (INTVAL (src));
2502 if (reg_was_0 (insn, dest))
2506 output_asm_insn ("set ; reg_was_0", operands);
2510 *l = AVR_ENHANCED ? 5 : 6;
2513 output_asm_insn (clr_op0, operands);
2514 output_asm_insn ("set", operands);
2518 avr_output_bld (operands, bit_nr);
2525 /* Last resort, better than loading from memory. */
2527 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2528 AS2 (ldi,r31,lo8(%1)) CR_TAB
2529 AS2 (mov,%A0,r31) CR_TAB
2530 AS2 (ldi,r31,hi8(%1)) CR_TAB
2531 AS2 (mov,%B0,r31) CR_TAB
2532 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2533 AS2 (mov,%C0,r31) CR_TAB
2534 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2535 AS2 (mov,%D0,r31) CR_TAB
2536 AS2 (mov,r31,__tmp_reg__));
2538 else if (GET_CODE (src) == MEM)
2539 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2541 else if (GET_CODE (dest) == MEM)
2543 const char *template;
2545 if (src == const0_rtx)
2546 operands[1] = zero_reg_rtx;
2548 template = out_movsi_mr_r (insn, operands, real_l);
2551 output_asm_insn (template, operands);
2556 fatal_insn ("invalid insn:", insn);
2561 out_movqi_mr_r (insn, op, l)
2564 int *l; /* instruction length */
2568 rtx x = XEXP (dest, 0);
2574 if (CONSTANT_ADDRESS_P (x))
2576 if (avr_io_address_p (x, 1))
2579 return AS2 (out,%0-0x20,%1);
2582 return AS2 (sts,%0,%1);
2584 /* memory access by reg+disp */
2585 else if (GET_CODE (x) == PLUS
2586 && REG_P (XEXP (x,0))
2587 && GET_CODE (XEXP (x,1)) == CONST_INT)
2589 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
2591 int disp = INTVAL (XEXP (x,1));
2592 if (REGNO (XEXP (x,0)) != REG_Y)
2593 fatal_insn ("incorrect insn:",insn);
2595 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2596 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2597 AS2 (std,Y+63,%1) CR_TAB
2598 AS2 (sbiw,r28,%o0-63));
2600 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2601 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2602 AS2 (st,Y,%1) CR_TAB
2603 AS2 (subi,r28,lo8(%o0)) CR_TAB
2604 AS2 (sbci,r29,hi8(%o0)));
2606 else if (REGNO (XEXP (x,0)) == REG_X)
2608 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
2610 if (reg_unused_after (insn, XEXP (x,0)))
2611 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2612 AS2 (adiw,r26,%o0) CR_TAB
2613 AS2 (st,X,__tmp_reg__));
2615 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2616 AS2 (adiw,r26,%o0) CR_TAB
2617 AS2 (st,X,__tmp_reg__) CR_TAB
2618 AS2 (sbiw,r26,%o0));
2622 if (reg_unused_after (insn, XEXP (x,0)))
2623 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2626 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2627 AS2 (st,X,%1) CR_TAB
2628 AS2 (sbiw,r26,%o0));
2632 return AS2 (std,%0,%1);
2635 return AS2 (st,%0,%1);
2639 out_movhi_mr_r (insn, op, l)
2646 rtx base = XEXP (dest, 0);
2647 int reg_base = true_regnum (base);
2648 int reg_src = true_regnum (src);
2652 if (CONSTANT_ADDRESS_P (base))
2654 if (avr_io_address_p (base, 2))
2657 return (AS2 (out,%B0-0x20,%B1) CR_TAB
2658 AS2 (out,%A0-0x20,%A1));
2660 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2665 if (reg_base == REG_X)
2667 if (reg_src == REG_X)
2669 /* "st X+,r26" is undefined */
2670 if (reg_unused_after (insn, src))
2671 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2672 AS2 (st,X,r26) CR_TAB
2673 AS2 (adiw,r26,1) CR_TAB
2674 AS2 (st,X,__tmp_reg__));
2676 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2677 AS2 (st,X,r26) CR_TAB
2678 AS2 (adiw,r26,1) CR_TAB
2679 AS2 (st,X,__tmp_reg__) CR_TAB
2684 if (reg_unused_after (insn, base))
2685 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2688 return *l=3, (AS2 (st ,X+,%A1) CR_TAB
2689 AS2 (st ,X,%B1) CR_TAB
2694 return *l=2, (AS2 (st ,%0,%A1) CR_TAB
2695 AS2 (std,%0+1,%B1));
2697 else if (GET_CODE (base) == PLUS)
2699 int disp = INTVAL (XEXP (base, 1));
2700 reg_base = REGNO (XEXP (base, 0));
2701 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2703 if (reg_base != REG_Y)
2704 fatal_insn ("incorrect insn:",insn);
2706 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2707 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
2708 AS2 (std,Y+62,%A1) CR_TAB
2709 AS2 (std,Y+63,%B1) CR_TAB
2710 AS2 (sbiw,r28,%o0-62));
2712 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2713 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2714 AS2 (st,Y,%A1) CR_TAB
2715 AS2 (std,Y+1,%B1) CR_TAB
2716 AS2 (subi,r28,lo8(%o0)) CR_TAB
2717 AS2 (sbci,r29,hi8(%o0)));
2719 if (reg_base == REG_X)
2722 if (reg_src == REG_X)
2725 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2726 AS2 (mov,__zero_reg__,r27) CR_TAB
2727 AS2 (adiw,r26,%o0) CR_TAB
2728 AS2 (st,X+,__tmp_reg__) CR_TAB
2729 AS2 (st,X,__zero_reg__) CR_TAB
2730 AS1 (clr,__zero_reg__) CR_TAB
2731 AS2 (sbiw,r26,%o0+1));
2734 return (AS2 (adiw,r26,%o0) CR_TAB
2735 AS2 (st,X+,%A1) CR_TAB
2736 AS2 (st,X,%B1) CR_TAB
2737 AS2 (sbiw,r26,%o0+1));
2739 return *l=2, (AS2 (std,%A0,%A1) CR_TAB
2742 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2743 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2745 else if (GET_CODE (base) == POST_INC) /* (R++) */
2746 return *l=2, (AS2 (st,%0,%A1) CR_TAB
2748 fatal_insn ("unknown move insn:",insn);
2752 /* Return 1 if frame pointer for current function required */
2755 frame_pointer_required_p ()
2757 return (current_function_calls_alloca
2758 || current_function_args_info.nregs == 0
2759 || current_function_varargs
2760 || get_frame_size () > 0);
2763 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2766 compare_condition (insn)
2769 rtx next = next_real_insn (insn);
2770 RTX_CODE cond = UNKNOWN;
2771 if (next && GET_CODE (next) == JUMP_INSN)
2773 rtx pat = PATTERN (next);
2774 rtx src = SET_SRC (pat);
2775 rtx t = XEXP (src, 0);
2776 cond = GET_CODE (t);
2781 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2784 compare_sign_p (insn)
2787 RTX_CODE cond = compare_condition (insn);
2788 return (cond == GE || cond == LT);
2791 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2792 that needs to be swapped (GT, GTU, LE, LEU). */
2795 compare_diff_p (insn)
2798 RTX_CODE cond = compare_condition (insn);
2799 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2802 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2808 RTX_CODE cond = compare_condition (insn);
2809 return (cond == EQ || cond == NE);
2813 /* Output test instruction for HImode */
2820 if (compare_sign_p (insn))
2823 return AS1 (tst,%B0);
2825 if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2826 && compare_eq_p (insn))
2828 /* faster than sbiw if we can clobber the operand */
2830 return AS2 (or,%A0,%B0);
2832 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2835 return AS2 (sbiw,%0,0);
2838 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2839 AS2 (cpc,%B0,__zero_reg__));
2843 /* Output test instruction for SImode */
2850 if (compare_sign_p (insn))
2853 return AS1 (tst,%D0);
2855 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2858 return (AS2 (sbiw,%A0,0) CR_TAB
2859 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2860 AS2 (cpc,%D0,__zero_reg__));
2863 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2864 AS2 (cpc,%B0,__zero_reg__) CR_TAB
2865 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2866 AS2 (cpc,%D0,__zero_reg__));
2870 /* Generate asm equivalent for various shifts.
2871 Shift count is a CONST_INT, MEM or REG.
2872 This only handles cases that are not already
2873 carefully hand-optimized in ?sh??i3_out. */
2876 out_shift_with_cnt (template, insn, operands, len, t_len)
2877 const char *template;
2881 int t_len; /* Length of template. */
2885 int second_label = 1;
2886 int saved_in_tmp = 0;
2887 int use_zero_reg = 0;
2889 op[0] = operands[0];
2890 op[1] = operands[1];
2891 op[2] = operands[2];
2892 op[3] = operands[3];
2898 if (GET_CODE (operands[2]) == CONST_INT)
2900 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2901 int count = INTVAL (operands[2]);
2902 int max_len = 10; /* If larger than this, always use a loop. */
2904 if (count < 8 && !scratch)
2908 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2910 if (t_len * count <= max_len)
2912 /* Output shifts inline with no loop - faster. */
2914 *len = t_len * count;
2918 output_asm_insn (template, op);
2927 strcat (str, AS2 (ldi,%3,%2));
2929 else if (use_zero_reg)
2931 /* Hack to save one word: use __zero_reg__ as loop counter.
2932 Set one bit, then shift in a loop until it is 0 again. */
2934 op[3] = zero_reg_rtx;
2938 strcat (str, ("set" CR_TAB
2939 AS2 (bld,%3,%2-1)));
2943 /* No scratch register available, use one from LD_REGS (saved in
2944 __tmp_reg__) that doesn't overlap with registers to shift. */
2946 op[3] = gen_rtx (REG, QImode,
2947 ((true_regnum (operands[0]) - 1) & 15) + 16);
2948 op[4] = tmp_reg_rtx;
2952 *len = 3; /* Includes "mov %3,%4" after the loop. */
2954 strcat (str, (AS2 (mov,%4,%3) CR_TAB
2960 else if (GET_CODE (operands[2]) == MEM)
2964 op[3] = op_mov[0] = tmp_reg_rtx;
2968 out_movqi_r_mr (insn, op_mov, len);
2970 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
2972 else if (register_operand (operands[2], QImode))
2974 if (reg_unused_after (insn, operands[2]))
2978 op[3] = tmp_reg_rtx;
2980 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
2984 fatal_insn ("bad shift insn:", insn);
2991 strcat (str, AS1 (rjmp,2f));
2995 *len += t_len + 2; /* template + dec + brXX */
2998 strcat (str, "\n1:\t");
2999 strcat (str, template);
3000 strcat (str, second_label ? "\n2:\t" : "\n\t");
3001 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
3002 strcat (str, CR_TAB);
3003 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
3005 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
3006 output_asm_insn (str, op);
3011 /* 8bit shift left ((char)x << i) */
3014 ashlqi3_out (insn, operands, len)
3017 int *len; /* insn length (may be NULL) */
3019 if (GET_CODE (operands[2]) == CONST_INT)
3026 switch (INTVAL (operands[2]))
3030 return AS1 (clr,%0);
3034 return AS1 (lsl,%0);
3038 return (AS1 (lsl,%0) CR_TAB
3043 return (AS1 (lsl,%0) CR_TAB
3048 if (test_hard_reg_class (LD_REGS, operands[0]))
3051 return (AS1 (swap,%0) CR_TAB
3052 AS2 (andi,%0,0xf0));
3055 return (AS1 (lsl,%0) CR_TAB
3061 if (test_hard_reg_class (LD_REGS, operands[0]))
3064 return (AS1 (swap,%0) CR_TAB
3066 AS2 (andi,%0,0xe0));
3069 return (AS1 (lsl,%0) CR_TAB
3076 if (test_hard_reg_class (LD_REGS, operands[0]))
3079 return (AS1 (swap,%0) CR_TAB
3082 AS2 (andi,%0,0xc0));
3085 return (AS1 (lsl,%0) CR_TAB
3094 return (AS1 (ror,%0) CR_TAB
3099 else if (CONSTANT_P (operands[2]))
3100 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3102 out_shift_with_cnt (AS1 (lsl,%0),
3103 insn, operands, len, 1);
3108 /* 16bit shift left ((short)x << i) */
3111 ashlhi3_out (insn, operands, len)
3116 if (GET_CODE (operands[2]) == CONST_INT)
3118 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3119 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3126 switch (INTVAL (operands[2]))
3129 if (optimize_size && scratch)
3134 return (AS1 (swap,%A0) CR_TAB
3135 AS1 (swap,%B0) CR_TAB
3136 AS2 (andi,%B0,0xf0) CR_TAB
3137 AS2 (eor,%B0,%A0) CR_TAB
3138 AS2 (andi,%A0,0xf0) CR_TAB
3144 return (AS1 (swap,%A0) CR_TAB
3145 AS1 (swap,%B0) CR_TAB
3146 AS2 (ldi,%3,0xf0) CR_TAB
3147 AS2 (and,%B0,%3) CR_TAB
3148 AS2 (eor,%B0,%A0) CR_TAB
3149 AS2 (and,%A0,%3) CR_TAB
3152 break; /* optimize_size ? 6 : 8 */
3156 break; /* scratch ? 5 : 6 */
3160 return (AS1 (lsl,%A0) CR_TAB
3161 AS1 (rol,%B0) CR_TAB
3162 AS1 (swap,%A0) CR_TAB
3163 AS1 (swap,%B0) CR_TAB
3164 AS2 (andi,%B0,0xf0) CR_TAB
3165 AS2 (eor,%B0,%A0) CR_TAB
3166 AS2 (andi,%A0,0xf0) CR_TAB
3172 return (AS1 (lsl,%A0) CR_TAB
3173 AS1 (rol,%B0) CR_TAB
3174 AS1 (swap,%A0) CR_TAB
3175 AS1 (swap,%B0) CR_TAB
3176 AS2 (ldi,%3,0xf0) CR_TAB
3177 AS2 (and,%B0,%3) CR_TAB
3178 AS2 (eor,%B0,%A0) CR_TAB
3179 AS2 (and,%A0,%3) CR_TAB
3186 break; /* scratch ? 5 : 6 */
3188 return (AS1 (clr,__tmp_reg__) CR_TAB
3189 AS1 (lsr,%B0) CR_TAB
3190 AS1 (ror,%A0) CR_TAB
3191 AS1 (ror,__tmp_reg__) CR_TAB
3192 AS1 (lsr,%B0) CR_TAB
3193 AS1 (ror,%A0) CR_TAB
3194 AS1 (ror,__tmp_reg__) CR_TAB
3195 AS2 (mov,%B0,%A0) CR_TAB
3196 AS2 (mov,%A0,__tmp_reg__));
3200 return (AS1 (lsr,%B0) CR_TAB
3201 AS2 (mov,%B0,%A0) CR_TAB
3202 AS1 (clr,%A0) CR_TAB
3203 AS1 (ror,%B0) CR_TAB
3207 if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
3208 return *len = 1, AS1 (clr,%A0);
3210 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3215 return (AS2 (mov,%B0,%A0) CR_TAB
3216 AS1 (clr,%A0) CR_TAB
3221 return (AS2 (mov,%B0,%A0) CR_TAB
3222 AS1 (clr,%A0) CR_TAB
3223 AS1 (lsl,%B0) CR_TAB
3228 return (AS2 (mov,%B0,%A0) CR_TAB
3229 AS1 (clr,%A0) CR_TAB
3230 AS1 (lsl,%B0) CR_TAB
3231 AS1 (lsl,%B0) CR_TAB
3238 return (AS2 (mov,%B0,%A0) CR_TAB
3239 AS1 (clr,%A0) CR_TAB
3240 AS1 (swap,%B0) CR_TAB
3241 AS2 (andi,%B0,0xf0));
3246 return (AS2 (mov,%B0,%A0) CR_TAB
3247 AS1 (clr,%A0) CR_TAB
3248 AS1 (swap,%B0) CR_TAB
3249 AS2 (ldi,%3,0xf0) CR_TAB
3253 return (AS2 (mov,%B0,%A0) CR_TAB
3254 AS1 (clr,%A0) CR_TAB
3255 AS1 (lsl,%B0) CR_TAB
3256 AS1 (lsl,%B0) CR_TAB
3257 AS1 (lsl,%B0) CR_TAB
3264 return (AS2 (mov,%B0,%A0) CR_TAB
3265 AS1 (clr,%A0) CR_TAB
3266 AS1 (swap,%B0) CR_TAB
3267 AS1 (lsl,%B0) CR_TAB
3268 AS2 (andi,%B0,0xe0));
3270 if (AVR_ENHANCED && scratch)
3273 return (AS2 (ldi,%3,0x20) CR_TAB
3274 AS2 (mul,%A0,%3) CR_TAB
3275 AS2 (mov,%B0,r0) CR_TAB
3276 AS1 (clr,%A0) CR_TAB
3277 AS1 (clr,__zero_reg__));
3279 if (optimize_size && scratch)
3284 return (AS2 (mov,%B0,%A0) CR_TAB
3285 AS1 (clr,%A0) CR_TAB
3286 AS1 (swap,%B0) CR_TAB
3287 AS1 (lsl,%B0) CR_TAB
3288 AS2 (ldi,%3,0xe0) CR_TAB
3294 return ("set" CR_TAB
3295 AS2 (bld,r1,5) CR_TAB
3296 AS2 (mul,%A0,r1) CR_TAB
3297 AS2 (mov,%B0,r0) CR_TAB
3298 AS1 (clr,%A0) CR_TAB
3299 AS1 (clr,__zero_reg__));
3302 return (AS2 (mov,%B0,%A0) CR_TAB
3303 AS1 (clr,%A0) CR_TAB
3304 AS1 (lsl,%B0) CR_TAB
3305 AS1 (lsl,%B0) CR_TAB
3306 AS1 (lsl,%B0) CR_TAB
3307 AS1 (lsl,%B0) CR_TAB
3311 if (AVR_ENHANCED && ldi_ok)
3314 return (AS2 (ldi,%B0,0x40) CR_TAB
3315 AS2 (mul,%A0,%B0) CR_TAB
3316 AS2 (mov,%B0,r0) CR_TAB
3317 AS1 (clr,%A0) CR_TAB
3318 AS1 (clr,__zero_reg__));
3320 if (AVR_ENHANCED && scratch)
3323 return (AS2 (ldi,%3,0x40) CR_TAB
3324 AS2 (mul,%A0,%3) CR_TAB
3325 AS2 (mov,%B0,r0) CR_TAB
3326 AS1 (clr,%A0) CR_TAB
3327 AS1 (clr,__zero_reg__));
3329 if (optimize_size && ldi_ok)
3332 return (AS2 (mov,%B0,%A0) CR_TAB
3333 AS2 (ldi,%A0,6) "\n1:\t"
3334 AS1 (lsl,%B0) CR_TAB
3335 AS1 (dec,%A0) CR_TAB
3338 if (optimize_size && scratch)
3341 return (AS1 (clr,%B0) CR_TAB
3342 AS1 (lsr,%A0) CR_TAB
3343 AS1 (ror,%B0) CR_TAB
3344 AS1 (lsr,%A0) CR_TAB
3345 AS1 (ror,%B0) CR_TAB
3350 return (AS1 (clr,%B0) CR_TAB
3351 AS1 (lsr,%A0) CR_TAB
3352 AS1 (ror,%B0) CR_TAB
3357 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3359 insn, operands, len, 2);
3364 /* 32bit shift left ((long)x << i) */
3367 ashlsi3_out (insn, operands, len)
3372 if (GET_CODE (operands[2]) == CONST_INT)
3380 switch (INTVAL (operands[2]))
3384 int reg0 = true_regnum (operands[0]);
3385 int reg1 = true_regnum (operands[1]);
3388 return (AS2 (mov,%D0,%C1) CR_TAB
3389 AS2 (mov,%C0,%B1) CR_TAB
3390 AS2 (mov,%B0,%A1) CR_TAB
3392 else if (reg0 + 1 == reg1)
3395 return AS1 (clr,%A0);
3398 return (AS1 (clr,%A0) CR_TAB
3399 AS2 (mov,%B0,%A1) CR_TAB
3400 AS2 (mov,%C0,%B1) CR_TAB
3406 int reg0 = true_regnum (operands[0]);
3407 int reg1 = true_regnum (operands[1]);
3409 if (AVR_ENHANCED && (reg0 + 2 != reg1))
3412 return (AS2 (movw,%C0,%A1) CR_TAB
3413 AS1 (clr,%B0) CR_TAB
3416 if (reg0 + 1 >= reg1)
3417 return (AS2 (mov,%D0,%B1) CR_TAB
3418 AS2 (mov,%C0,%A1) CR_TAB
3419 AS1 (clr,%B0) CR_TAB
3421 if (reg0 + 2 == reg1)
3424 return (AS1 (clr,%B0) CR_TAB
3428 return (AS2 (mov,%C0,%A1) CR_TAB
3429 AS2 (mov,%D0,%B1) CR_TAB
3430 AS1 (clr,%B0) CR_TAB
3436 if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
3437 return (AS2 (mov,%D0,%A1) CR_TAB
3438 AS1 (clr,%C0) CR_TAB
3439 AS1 (clr,%B0) CR_TAB
3444 return (AS1 (clr,%C0) CR_TAB
3445 AS1 (clr,%B0) CR_TAB
3451 return (AS1 (clr,%D0) CR_TAB
3452 AS1 (lsr,%A0) CR_TAB
3453 AS1 (ror,%D0) CR_TAB
3454 AS1 (clr,%C0) CR_TAB
3455 AS1 (clr,%B0) CR_TAB
3460 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3461 AS1 (rol,%B0) CR_TAB
3462 AS1 (rol,%C0) CR_TAB
3464 insn, operands, len, 4);
3468 /* 8bit arithmetic shift right ((signed char)x >> i) */
3471 ashrqi3_out (insn, operands, len)
3474 int *len; /* insn length */
3476 if (GET_CODE (operands[2]) == CONST_INT)
3483 switch (INTVAL (operands[2]))
3487 return AS1 (asr,%0);
3491 return (AS1 (asr,%0) CR_TAB
3496 return (AS1 (asr,%0) CR_TAB
3502 return (AS1 (asr,%0) CR_TAB
3509 return (AS1 (asr,%0) CR_TAB
3517 return (AS2 (bst,%0,6) CR_TAB
3519 AS2 (sbc,%0,%0) CR_TAB
3525 return (AS1 (lsl,%0) CR_TAB
3529 else if (CONSTANT_P (operands[2]))
3530 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3532 out_shift_with_cnt (AS1 (asr,%0),
3533 insn, operands, len, 1);
3538 /* 16bit arithmetic shift right ((signed short)x >> i) */
3541 ashrhi3_out (insn, operands, len)
3546 if (GET_CODE (operands[2]) == CONST_INT)
3548 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3549 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3556 switch (INTVAL (operands[2]))
3560 /* XXX try to optimize this too? */
3565 break; /* scratch ? 5 : 6 */
3567 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3568 AS2 (mov,%A0,%B0) CR_TAB
3569 AS1 (lsl,__tmp_reg__) CR_TAB
3570 AS1 (rol,%A0) CR_TAB
3571 AS2 (sbc,%B0,%B0) CR_TAB
3572 AS1 (lsl,__tmp_reg__) CR_TAB
3573 AS1 (rol,%A0) CR_TAB
3578 return (AS1 (lsl,%A0) CR_TAB
3579 AS2 (mov,%A0,%B0) CR_TAB
3580 AS1 (rol,%A0) CR_TAB
3585 int reg0 = true_regnum (operands[0]);
3586 int reg1 = true_regnum (operands[1]);
3589 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3590 AS1 (lsl,%B0) CR_TAB
3592 else if (reg0 == reg1 + 1)
3593 return *len = 3, (AS1 (clr,%B0) CR_TAB
3594 AS2 (sbrc,%A0,7) CR_TAB
3597 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3598 AS1 (clr,%B0) CR_TAB
3599 AS2 (sbrc,%A0,7) CR_TAB
3605 return (AS2 (mov,%A0,%B0) CR_TAB
3606 AS1 (lsl,%B0) CR_TAB
3607 AS2 (sbc,%B0,%B0) CR_TAB
3612 return (AS2 (mov,%A0,%B0) CR_TAB
3613 AS1 (lsl,%B0) CR_TAB
3614 AS2 (sbc,%B0,%B0) CR_TAB
3615 AS1 (asr,%A0) CR_TAB
3619 if (AVR_ENHANCED && ldi_ok)
3622 return (AS2 (ldi,%A0,0x20) CR_TAB
3623 AS2 (muls,%B0,%A0) CR_TAB
3624 AS2 (mov,%A0,r1) CR_TAB
3625 AS2 (sbc,%B0,%B0) CR_TAB
3626 AS1 (clr,__zero_reg__));
3628 if (optimize_size && scratch)
3631 return (AS2 (mov,%A0,%B0) CR_TAB
3632 AS1 (lsl,%B0) CR_TAB
3633 AS2 (sbc,%B0,%B0) CR_TAB
3634 AS1 (asr,%A0) CR_TAB
3635 AS1 (asr,%A0) CR_TAB
3639 if (AVR_ENHANCED && ldi_ok)
3642 return (AS2 (ldi,%A0,0x10) CR_TAB
3643 AS2 (muls,%B0,%A0) CR_TAB
3644 AS2 (mov,%A0,r1) CR_TAB
3645 AS2 (sbc,%B0,%B0) CR_TAB
3646 AS1 (clr,__zero_reg__));
3648 if (optimize_size && scratch)
3651 return (AS2 (mov,%A0,%B0) CR_TAB
3652 AS1 (lsl,%B0) CR_TAB
3653 AS2 (sbc,%B0,%B0) CR_TAB
3654 AS1 (asr,%A0) CR_TAB
3655 AS1 (asr,%A0) CR_TAB
3656 AS1 (asr,%A0) CR_TAB
3660 if (AVR_ENHANCED && ldi_ok)
3663 return (AS2 (ldi,%A0,0x08) CR_TAB
3664 AS2 (muls,%B0,%A0) CR_TAB
3665 AS2 (mov,%A0,r1) CR_TAB
3666 AS2 (sbc,%B0,%B0) CR_TAB
3667 AS1 (clr,__zero_reg__));
3670 break; /* scratch ? 5 : 7 */
3672 return (AS2 (mov,%A0,%B0) CR_TAB
3673 AS1 (lsl,%B0) CR_TAB
3674 AS2 (sbc,%B0,%B0) CR_TAB
3675 AS1 (asr,%A0) CR_TAB
3676 AS1 (asr,%A0) CR_TAB
3677 AS1 (asr,%A0) CR_TAB
3678 AS1 (asr,%A0) CR_TAB
3683 return (AS1 (lsl,%B0) CR_TAB
3684 AS2 (sbc,%A0,%A0) CR_TAB
3685 AS1 (lsl,%B0) CR_TAB
3686 AS2 (mov,%B0,%A0) CR_TAB
3690 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3691 AS2 (sbc,%A0,%A0) CR_TAB
3696 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3698 insn, operands, len, 2);
3703 /* 32bit arithmetic shift right ((signed long)x >> i) */
3706 ashrsi3_out (insn, operands, len)
3711 if (GET_CODE (operands[2]) == CONST_INT)
3719 switch (INTVAL (operands[2]))
3723 int reg0 = true_regnum (operands[0]);
3724 int reg1 = true_regnum (operands[1]);
3727 return (AS2 (mov,%A0,%B1) CR_TAB
3728 AS2 (mov,%B0,%C1) CR_TAB
3729 AS2 (mov,%C0,%D1) CR_TAB
3730 AS1 (clr,%D0) CR_TAB
3731 AS2 (sbrc,%C0,7) CR_TAB
3733 else if (reg0 == reg1 + 1)
3736 return (AS1 (clr,%D0) CR_TAB
3737 AS2 (sbrc,%C0,7) CR_TAB
3741 return (AS1 (clr,%D0) CR_TAB
3742 AS2 (sbrc,%D1,7) CR_TAB
3743 AS1 (dec,%D0) CR_TAB
3744 AS2 (mov,%C0,%D1) CR_TAB
3745 AS2 (mov,%B0,%C1) CR_TAB
3751 int reg0 = true_regnum (operands[0]);
3752 int reg1 = true_regnum (operands[1]);
3754 if (AVR_ENHANCED && (reg0 != reg1 + 2))
3757 return (AS2 (movw,%A0,%C1) CR_TAB
3758 AS1 (clr,%D0) CR_TAB
3759 AS2 (sbrc,%B0,7) CR_TAB
3760 AS1 (com,%D0) CR_TAB
3763 if (reg0 <= reg1 + 1)
3764 return (AS2 (mov,%A0,%C1) CR_TAB
3765 AS2 (mov,%B0,%D1) CR_TAB
3766 AS1 (clr,%D0) CR_TAB
3767 AS2 (sbrc,%B0,7) CR_TAB
3768 AS1 (com,%D0) CR_TAB
3770 else if (reg0 == reg1 + 2)
3771 return *len = 4, (AS1 (clr,%D0) CR_TAB
3772 AS2 (sbrc,%B0,7) CR_TAB
3773 AS1 (com,%D0) CR_TAB
3776 return (AS2 (mov,%B0,%D1) CR_TAB
3777 AS2 (mov,%A0,%C1) CR_TAB
3778 AS1 (clr,%D0) CR_TAB
3779 AS2 (sbrc,%B0,7) CR_TAB
3780 AS1 (com,%D0) CR_TAB
3785 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
3786 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3787 AS1 (clr,%D0) CR_TAB
3788 AS2 (sbrc,%A0,7) CR_TAB
3789 AS1 (com,%D0) CR_TAB
3790 AS2 (mov,%B0,%D0) CR_TAB
3793 return *len = 5, (AS1 (clr,%D0) CR_TAB
3794 AS2 (sbrc,%A0,7) CR_TAB
3795 AS1 (com,%D0) CR_TAB
3796 AS2 (mov,%B0,%D0) CR_TAB
3801 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3802 AS2 (sbc,%A0,%A0) CR_TAB
3803 AS2 (mov,%B0,%A0) CR_TAB
3804 AS2 (movw,%C0,%A0));
3806 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3807 AS2 (sbc,%A0,%A0) CR_TAB
3808 AS2 (mov,%B0,%A0) CR_TAB
3809 AS2 (mov,%C0,%A0) CR_TAB
3814 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3815 AS1 (ror,%C0) CR_TAB
3816 AS1 (ror,%B0) CR_TAB
3818 insn, operands, len, 4);
3822 /* 8bit logic shift right ((unsigned char)x >> i) */
3825 lshrqi3_out (insn, operands, len)
3830 if (GET_CODE (operands[2]) == CONST_INT)
3837 switch (INTVAL (operands[2]))
3841 return AS1 (clr,%0);
3845 return AS1 (lsr,%0);
3849 return (AS1 (lsr,%0) CR_TAB
3853 return (AS1 (lsr,%0) CR_TAB
3858 if (test_hard_reg_class (LD_REGS, operands[0]))
3861 return (AS1 (swap,%0) CR_TAB
3862 AS2 (andi,%0,0x0f));
3865 return (AS1 (lsr,%0) CR_TAB
3871 if (test_hard_reg_class (LD_REGS, operands[0]))
3874 return (AS1 (swap,%0) CR_TAB
3879 return (AS1 (lsr,%0) CR_TAB
3886 if (test_hard_reg_class (LD_REGS, operands[0]))
3889 return (AS1 (swap,%0) CR_TAB
3895 return (AS1 (lsr,%0) CR_TAB
3904 return (AS1 (rol,%0) CR_TAB
3909 else if (CONSTANT_P (operands[2]))
3910 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3912 out_shift_with_cnt (AS1 (lsr,%0),
3913 insn, operands, len, 1);
3917 /* 16bit logic shift right ((unsigned short)x >> i) */
3920 lshrhi3_out (insn, operands, len)
3925 if (GET_CODE (operands[2]) == CONST_INT)
3927 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3928 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3935 switch (INTVAL (operands[2]))
3938 if (optimize_size && scratch)
3943 return (AS1 (swap,%B0) CR_TAB
3944 AS1 (swap,%A0) CR_TAB
3945 AS2 (andi,%A0,0x0f) CR_TAB
3946 AS2 (eor,%A0,%B0) CR_TAB
3947 AS2 (andi,%B0,0x0f) CR_TAB
3953 return (AS1 (swap,%B0) CR_TAB
3954 AS1 (swap,%A0) CR_TAB
3955 AS2 (ldi,%3,0x0f) CR_TAB
3956 AS2 (and,%A0,%3) CR_TAB
3957 AS2 (eor,%A0,%B0) CR_TAB
3958 AS2 (and,%B0,%3) CR_TAB
3961 break; /* optimize_size ? 6 : 8 */
3965 break; /* scratch ? 5 : 6 */
3969 return (AS1 (lsr,%B0) CR_TAB
3970 AS1 (ror,%A0) CR_TAB
3971 AS1 (swap,%B0) CR_TAB
3972 AS1 (swap,%A0) CR_TAB
3973 AS2 (andi,%A0,0x0f) CR_TAB
3974 AS2 (eor,%A0,%B0) CR_TAB
3975 AS2 (andi,%B0,0x0f) CR_TAB
3981 return (AS1 (lsr,%B0) CR_TAB
3982 AS1 (ror,%A0) CR_TAB
3983 AS1 (swap,%B0) CR_TAB
3984 AS1 (swap,%A0) CR_TAB
3985 AS2 (ldi,%3,0x0f) CR_TAB
3986 AS2 (and,%A0,%3) CR_TAB
3987 AS2 (eor,%A0,%B0) CR_TAB
3988 AS2 (and,%B0,%3) CR_TAB
3995 break; /* scratch ? 5 : 6 */
3997 return (AS1 (clr,__tmp_reg__) CR_TAB
3998 AS1 (lsl,%A0) CR_TAB
3999 AS1 (rol,%B0) CR_TAB
4000 AS1 (rol,__tmp_reg__) CR_TAB
4001 AS1 (lsl,%A0) CR_TAB
4002 AS1 (rol,%B0) CR_TAB
4003 AS1 (rol,__tmp_reg__) CR_TAB
4004 AS2 (mov,%A0,%B0) CR_TAB
4005 AS2 (mov,%B0,__tmp_reg__));
4009 return (AS1 (lsl,%A0) CR_TAB
4010 AS2 (mov,%A0,%B0) CR_TAB
4011 AS1 (rol,%A0) CR_TAB
4012 AS2 (sbc,%B0,%B0) CR_TAB
4016 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
4017 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
4020 return *len = 1, AS1 (clr,%B0);
4024 return (AS2 (mov,%A0,%B0) CR_TAB
4025 AS1 (clr,%B0) CR_TAB
4030 return (AS2 (mov,%A0,%B0) CR_TAB
4031 AS1 (clr,%B0) CR_TAB
4032 AS1 (lsr,%A0) CR_TAB
4037 return (AS2 (mov,%A0,%B0) CR_TAB
4038 AS1 (clr,%B0) CR_TAB
4039 AS1 (lsr,%A0) CR_TAB
4040 AS1 (lsr,%A0) CR_TAB
4047 return (AS2 (mov,%A0,%B0) CR_TAB
4048 AS1 (clr,%B0) CR_TAB
4049 AS1 (swap,%A0) CR_TAB
4050 AS2 (andi,%A0,0x0f));
4055 return (AS2 (mov,%A0,%B0) CR_TAB
4056 AS1 (clr,%B0) CR_TAB
4057 AS1 (swap,%A0) CR_TAB
4058 AS2 (ldi,%3,0x0f) CR_TAB
4062 return (AS2 (mov,%A0,%B0) CR_TAB
4063 AS1 (clr,%B0) CR_TAB
4064 AS1 (lsr,%A0) CR_TAB
4065 AS1 (lsr,%A0) CR_TAB
4066 AS1 (lsr,%A0) CR_TAB
4073 return (AS2 (mov,%A0,%B0) CR_TAB
4074 AS1 (clr,%B0) CR_TAB
4075 AS1 (swap,%A0) CR_TAB
4076 AS1 (lsr,%A0) CR_TAB
4077 AS2 (andi,%A0,0x07));
4079 if (AVR_ENHANCED && scratch)
4082 return (AS2 (ldi,%3,0x08) CR_TAB
4083 AS2 (mul,%B0,%3) CR_TAB
4084 AS2 (mov,%A0,r1) CR_TAB
4085 AS1 (clr,%B0) CR_TAB
4086 AS1 (clr,__zero_reg__));
4088 if (optimize_size && scratch)
4093 return (AS2 (mov,%A0,%B0) CR_TAB
4094 AS1 (clr,%B0) CR_TAB
4095 AS1 (swap,%A0) CR_TAB
4096 AS1 (lsr,%A0) CR_TAB
4097 AS2 (ldi,%3,0x07) CR_TAB
4103 return ("set" CR_TAB
4104 AS2 (bld,r1,3) CR_TAB
4105 AS2 (mul,%B0,r1) CR_TAB
4106 AS2 (mov,%A0,r1) CR_TAB
4107 AS1 (clr,%B0) CR_TAB
4108 AS1 (clr,__zero_reg__));
4111 return (AS2 (mov,%A0,%B0) CR_TAB
4112 AS1 (clr,%B0) CR_TAB
4113 AS1 (lsr,%A0) CR_TAB
4114 AS1 (lsr,%A0) CR_TAB
4115 AS1 (lsr,%A0) CR_TAB
4116 AS1 (lsr,%A0) CR_TAB
4120 if (AVR_ENHANCED && ldi_ok)
4123 return (AS2 (ldi,%A0,0x04) CR_TAB
4124 AS2 (mul,%B0,%A0) CR_TAB
4125 AS2 (mov,%A0,r1) CR_TAB
4126 AS1 (clr,%B0) CR_TAB
4127 AS1 (clr,__zero_reg__));
4129 if (AVR_ENHANCED && scratch)
4132 return (AS2 (ldi,%3,0x04) CR_TAB
4133 AS2 (mul,%B0,%3) CR_TAB
4134 AS2 (mov,%A0,r1) CR_TAB
4135 AS1 (clr,%B0) CR_TAB
4136 AS1 (clr,__zero_reg__));
4138 if (optimize_size && ldi_ok)
4141 return (AS2 (mov,%A0,%B0) CR_TAB
4142 AS2 (ldi,%B0,6) "\n1:\t"
4143 AS1 (lsr,%A0) CR_TAB
4144 AS1 (dec,%B0) CR_TAB
4147 if (optimize_size && scratch)
4150 return (AS1 (clr,%A0) CR_TAB
4151 AS1 (lsl,%B0) CR_TAB
4152 AS1 (rol,%A0) CR_TAB
4153 AS1 (lsl,%B0) CR_TAB
4154 AS1 (rol,%A0) CR_TAB
4159 return (AS1 (clr,%A0) CR_TAB
4160 AS1 (lsl,%B0) CR_TAB
4161 AS1 (rol,%A0) CR_TAB
4166 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4168 insn, operands, len, 2);
4172 /* 32bit logic shift right ((unsigned int)x >> i) */
4175 lshrsi3_out (insn, operands, len)
4180 if (GET_CODE (operands[2]) == CONST_INT)
4188 switch (INTVAL (operands[2]))
4192 int reg0 = true_regnum (operands[0]);
4193 int reg1 = true_regnum (operands[1]);
4196 return (AS2 (mov,%A0,%B1) CR_TAB
4197 AS2 (mov,%B0,%C1) CR_TAB
4198 AS2 (mov,%C0,%D1) CR_TAB
4200 else if (reg0 == reg1 + 1)
4201 return *len = 1, AS1 (clr,%D0);
4203 return (AS1 (clr,%D0) CR_TAB
4204 AS2 (mov,%C0,%D1) CR_TAB
4205 AS2 (mov,%B0,%C1) CR_TAB
4211 int reg0 = true_regnum (operands[0]);
4212 int reg1 = true_regnum (operands[1]);
4214 if (AVR_ENHANCED && (reg0 != reg1 + 2))
4217 return (AS2 (movw,%A0,%C1) CR_TAB
4218 AS1 (clr,%C0) CR_TAB
4221 if (reg0 <= reg1 + 1)
4222 return (AS2 (mov,%A0,%C1) CR_TAB
4223 AS2 (mov,%B0,%D1) CR_TAB
4224 AS1 (clr,%C0) CR_TAB
4226 else if (reg0 == reg1 + 2)
4227 return *len = 2, (AS1 (clr,%C0) CR_TAB
4230 return (AS2 (mov,%B0,%D1) CR_TAB
4231 AS2 (mov,%A0,%C1) CR_TAB
4232 AS1 (clr,%C0) CR_TAB
4237 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
4238 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4239 AS1 (clr,%B0) CR_TAB
4240 AS1 (clr,%C0) CR_TAB
4243 return *len = 3, (AS1 (clr,%B0) CR_TAB
4244 AS1 (clr,%C0) CR_TAB
4249 return (AS1 (clr,%A0) CR_TAB
4250 AS2 (sbrc,%D0,7) CR_TAB
4251 AS1 (inc,%A0) CR_TAB
4252 AS1 (clr,%B0) CR_TAB
4253 AS1 (clr,%C0) CR_TAB
4258 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4259 AS1 (ror,%C0) CR_TAB
4260 AS1 (ror,%B0) CR_TAB
4262 insn, operands, len, 4);
4266 /* Modifies the length assigned to instruction INSN
4267 LEN is the initially computed length of the insn. */
4270 adjust_insn_length (insn, len)
4274 rtx patt = PATTERN (insn);
4277 if (GET_CODE (patt) == SET)
4280 op[1] = SET_SRC (patt);
4281 op[0] = SET_DEST (patt);
4282 if (general_operand (op[1], VOIDmode)
4283 && general_operand (op[0], VOIDmode))
4285 switch (GET_MODE (op[0]))
4288 output_movqi (insn, op, &len);
4291 output_movhi (insn, op, &len);
4295 output_movsisf (insn, op, &len);
4301 else if (op[0] == cc0_rtx && REG_P (op[1]))
4303 switch (GET_MODE (op[1]))
4305 case HImode: out_tsthi (insn,&len); break;
4306 case SImode: out_tstsi (insn,&len); break;
4310 else if (GET_CODE (op[1]) == AND)
4312 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4314 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4315 if (GET_MODE (op[1]) == SImode)
4316 len = (((mask & 0xff) != 0xff)
4317 + ((mask & 0xff00) != 0xff00)
4318 + ((mask & 0xff0000L) != 0xff0000L)
4319 + ((mask & 0xff000000L) != 0xff000000L));
4320 else if (GET_MODE (op[1]) == HImode)
4321 len = (((mask & 0xff) != 0xff)
4322 + ((mask & 0xff00) != 0xff00));
4325 else if (GET_CODE (op[1]) == IOR)
4327 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4329 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4330 if (GET_MODE (op[1]) == SImode)
4331 len = (((mask & 0xff) != 0)
4332 + ((mask & 0xff00) != 0)
4333 + ((mask & 0xff0000L) != 0)
4334 + ((mask & 0xff000000L) != 0));
4335 else if (GET_MODE (op[1]) == HImode)
4336 len = (((mask & 0xff) != 0)
4337 + ((mask & 0xff00) != 0));
4341 set = single_set (insn);
4346 op[1] = SET_SRC (set);
4347 op[0] = SET_DEST (set);
4349 if (GET_CODE (patt) == PARALLEL
4350 && general_operand (op[1], VOIDmode)
4351 && general_operand (op[0], VOIDmode))
4353 if (XVECLEN (patt, 0) == 2)
4354 op[2] = XVECEXP (patt, 0, 1);
4356 switch (GET_MODE (op[0]))
4362 output_reload_inhi (insn, op, &len);
4366 output_reload_insisf (insn, op, &len);
4372 else if (GET_CODE (op[1]) == ASHIFT
4373 || GET_CODE (op[1]) == ASHIFTRT
4374 || GET_CODE (op[1]) == LSHIFTRT)
4378 ops[1] = XEXP (op[1],0);
4379 ops[2] = XEXP (op[1],1);
4380 switch (GET_CODE (op[1]))
4383 switch (GET_MODE (op[0]))
4385 case QImode: ashlqi3_out (insn,ops,&len); break;
4386 case HImode: ashlhi3_out (insn,ops,&len); break;
4387 case SImode: ashlsi3_out (insn,ops,&len); break;
4392 switch (GET_MODE (op[0]))
4394 case QImode: ashrqi3_out (insn,ops,&len); break;
4395 case HImode: ashrhi3_out (insn,ops,&len); break;
4396 case SImode: ashrsi3_out (insn,ops,&len); break;
4401 switch (GET_MODE (op[0]))
4403 case QImode: lshrqi3_out (insn,ops,&len); break;
4404 case HImode: lshrhi3_out (insn,ops,&len); break;
4405 case SImode: lshrsi3_out (insn,ops,&len); break;
4417 /* Return non-zero if register REG dead after INSN */
4420 reg_unused_after (insn, reg)
4424 return (dead_or_set_p (insn, reg)
4425 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4428 /* Return non-zero if REG is not used after INSN.
4429 We assume REG is a reload reg, and therefore does
4430 not live past labels. It may live past calls or jumps though. */
4433 _reg_unused_after (insn, reg)
4440 /* If the reg is set by this instruction, then it is safe for our
4441 case. Disregard the case where this is a store to memory, since
4442 we are checking a register used in the store address. */
4443 set = single_set (insn);
4444 if (set && GET_CODE (SET_DEST (set)) != MEM
4445 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4448 while ((insn = NEXT_INSN (insn)))
4450 code = GET_CODE (insn);
4453 /* If this is a label that existed before reload, then the register
4454 if dead here. However, if this is a label added by reorg, then
4455 the register may still be live here. We can't tell the difference,
4456 so we just ignore labels completely. */
4457 if (code == CODE_LABEL)
4462 if (code == JUMP_INSN)
4465 /* If this is a sequence, we must handle them all at once.
4466 We could have for instance a call that sets the target register,
4467 and an insn in a delay slot that uses the register. In this case,
4468 we must return 0. */
4469 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4474 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4476 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4477 rtx set = single_set (this_insn);
4479 if (GET_CODE (this_insn) == CALL_INSN)
4481 else if (GET_CODE (this_insn) == JUMP_INSN)
4483 if (INSN_ANNULLED_BRANCH_P (this_insn))
4488 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4490 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4492 if (GET_CODE (SET_DEST (set)) != MEM)
4498 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4503 else if (code == JUMP_INSN)
4507 if (code == CALL_INSN)
4510 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4511 if (GET_CODE (XEXP (tem, 0)) == USE
4512 && REG_P (XEXP (XEXP (tem, 0), 0))
4513 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4515 if (call_used_regs[REGNO (reg)])
4519 if (GET_RTX_CLASS (code) == 'i')
4521 rtx set = single_set (insn);
4523 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4525 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4526 return GET_CODE (SET_DEST (set)) != MEM;
4527 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4534 /* Target hook for assembling integer objects. The AVR version needs
4535 special handling for references to certain labels. */
4538 avr_assemble_integer (x, size, aligned_p)
4543 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
4544 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x))
4545 || GET_CODE (x) == LABEL_REF))
4547 fputs ("\t.word\tpm(", asm_out_file);
4548 output_addr_const (asm_out_file, x);
4549 fputs (")\n", asm_out_file);
4552 return default_assemble_integer (x, size, aligned_p);
4555 /* Sets section name for declaration DECL */
4558 avr_unique_section (decl, reloc)
4560 int reloc ATTRIBUTE_UNUSED;
4563 const char *name, *prefix;
4566 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
4567 name = (* targetm.strip_name_encoding) (name);
4569 if (TREE_CODE (decl) == FUNCTION_DECL)
4571 if (flag_function_sections)
4579 if (flag_function_sections)
4581 len = strlen (name) + strlen (prefix);
4582 string = alloca (len + 1);
4583 sprintf (string, "%s%s", prefix, name);
4584 DECL_SECTION_NAME (decl) = build_string (len, string);
4589 /* The routine used to output NUL terminated strings. We use a special
4590 version of this for most svr4 targets because doing so makes the
4591 generated assembly code more compact (and thus faster to assemble)
4592 as well as more readable, especially for targets like the i386
4593 (where the only alternative is to output character sequences as
4594 comma separated lists of numbers). */
4597 gas_output_limited_string(file, str)
4601 const unsigned char *_limited_str = (unsigned char *) str;
4603 fprintf (file, "%s\"", STRING_ASM_OP);
4604 for (; (ch = *_limited_str); _limited_str++)
4607 switch (escape = ESCAPES[ch])
4613 fprintf (file, "\\%03o", ch);
4617 putc (escape, file);
4621 fprintf (file, "\"\n");
4624 /* The routine used to output sequences of byte values. We use a special
4625 version of this for most svr4 targets because doing so makes the
4626 generated assembly code more compact (and thus faster to assemble)
4627 as well as more readable. Note that if we find subparts of the
4628 character sequence which end with NUL (and which are shorter than
4629 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4632 gas_output_ascii(file, str, length)
4637 const unsigned char *_ascii_bytes = (const unsigned char *) str;
4638 const unsigned char *limit = _ascii_bytes + length;
4639 unsigned bytes_in_chunk = 0;
4640 for (; _ascii_bytes < limit; _ascii_bytes++)
4642 const unsigned char *p;
4643 if (bytes_in_chunk >= 60)
4645 fprintf (file, "\"\n");
4648 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4650 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4652 if (bytes_in_chunk > 0)
4654 fprintf (file, "\"\n");
4657 gas_output_limited_string (file, (char*)_ascii_bytes);
4664 if (bytes_in_chunk == 0)
4665 fprintf (file, "\t.ascii\t\"");
4666 switch (escape = ESCAPES[ch = *_ascii_bytes])
4673 fprintf (file, "\\%03o", ch);
4674 bytes_in_chunk += 4;
4678 putc (escape, file);
4679 bytes_in_chunk += 2;
4684 if (bytes_in_chunk > 0)
4685 fprintf (file, "\"\n");
4688 /* Return value is nonzero if pseudos that have been
4689 assigned to registers of class CLASS would likely be spilled
4690 because registers of CLASS are needed for spill registers. */
4693 class_likely_spilled_p (c)
4696 return (c != ALL_REGS && c != ADDW_REGS);
4699 /* Valid attributes:
4700 progmem - put data to program memory;
4701 signal - make a function to be hardware interrupt. After function
4702 prologue interrupts are disabled;
4703 interrupt - make a function to be hardware interrupt. After function
4704 prologue interrupts are enabled;
4705 naked - don't generate function prologue/epilogue and `ret' command.
4707 Only `progmem' attribute valid for type. */
4709 const struct attribute_spec avr_attribute_table[] =
4711 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4712 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
4713 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4714 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4715 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4716 { NULL, 0, 0, false, false, false, NULL }
4719 /* Handle a "progmem" attribute; arguments as in
4720 struct attribute_spec.handler. */
4722 avr_handle_progmem_attribute (node, name, args, flags, no_add_attrs)
4725 tree args ATTRIBUTE_UNUSED;
4726 int flags ATTRIBUTE_UNUSED;
4731 if (TREE_CODE (*node) == TYPE_DECL)
4733 /* This is really a decl attribute, not a type attribute,
4734 but try to handle it for GCC 3.0 backwards compatibility. */
4736 tree type = TREE_TYPE (*node);
4737 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
4738 tree newtype = build_type_attribute_variant (type, attr);
4740 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
4741 TREE_TYPE (*node) = newtype;
4742 *no_add_attrs = true;
4744 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
4746 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
4748 warning ("only initialized variables can be placed into "
4749 "program memory area");
4750 *no_add_attrs = true;
4755 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
4756 *no_add_attrs = true;
4763 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4764 struct attribute_spec.handler. */
4766 avr_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
4769 tree args ATTRIBUTE_UNUSED;
4770 int flags ATTRIBUTE_UNUSED;
4773 if (TREE_CODE (*node) != FUNCTION_DECL)
4775 warning ("`%s' attribute only applies to functions",
4776 IDENTIFIER_POINTER (name));
4777 *no_add_attrs = true;
4783 /* Look for attribute `progmem' in DECL
4784 if found return 1, otherwise 0. */
4787 avr_progmem_p (decl)
4792 if (TREE_CODE (decl) != VAR_DECL)
4796 != lookup_attribute ("progmem", DECL_ATTRIBUTES (decl)))
4802 while (TREE_CODE (a) == ARRAY_TYPE);
4804 if (a == error_mark_node)
4807 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4813 /* Encode section information about tree DECL. */
4816 avr_encode_section_info (decl, first)
4820 if (TREE_CODE (decl) == FUNCTION_DECL)
4821 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
4823 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
4824 && TREE_CODE (decl) == VAR_DECL
4825 && avr_progmem_p (decl))
4827 static const char *const dsec = ".progmem.data";
4828 DECL_SECTION_NAME (decl) = build_string (strlen (dsec), dsec);
4829 TREE_READONLY (decl) = 1;
4833 /* Outputs to the stdio stream FILE some
4834 appropriate text to go at the start of an assembler file. */
4837 asm_file_start (file)
4841 error ("MCU `%s' supported for assembler only", avr_mcu_name);
4843 output_file_directive (file, main_input_filename);
4844 fprintf (file, "\t.arch %s\n", avr_mcu_name);
4845 fputs ("__SREG__ = 0x3f\n"
4847 "__SP_L__ = 0x3d\n", file);
4849 fputs ("__tmp_reg__ = 0\n"
4850 "__zero_reg__ = 1\n"
4851 "_PC_ = 2\n", file);
4853 /* FIXME: output these only if there is anything in the .data / .bss
4854 sections - some code size could be saved by not linking in the
4855 initialization code from libgcc if one or both sections are empty. */
4856 fputs ("\t.global __do_copy_data\n", file);
4857 fputs ("\t.global __do_clear_bss\n", file);
4859 commands_in_file = 0;
4860 commands_in_prologues = 0;
4861 commands_in_epilogues = 0;
4864 /* Outputs to the stdio stream FILE some
4865 appropriate text to go at the end of an assembler file. */
4871 fputs ("/* File ", file);
4872 output_quoted_string (file, main_input_filename);
4874 ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4877 commands_in_file - commands_in_prologues - commands_in_epilogues,
4878 commands_in_prologues, commands_in_epilogues);
4881 /* Choose the order in which to allocate hard registers for
4882 pseudo-registers local to a basic block.
4884 Store the desired register order in the array `reg_alloc_order'.
4885 Element 0 should be the register to allocate first; element 1, the
4886 next register; and so on. */
4889 order_regs_for_local_alloc ()
4892 static const int order_0[] = {
4900 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4904 static const int order_1[] = {
4912 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4916 static const int order_2[] = {
4925 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4930 const int *order = (TARGET_ORDER_1 ? order_1 :
4931 TARGET_ORDER_2 ? order_2 :
4933 for (i=0; i < ARRAY_SIZE (order_0); ++i)
4934 reg_alloc_order[i] = order[i];
4937 /* Calculate the cost of X code of the expression in which it is contained,
4938 found in OUTER_CODE */
4941 default_rtx_costs (X, code, outer_code)
4944 enum rtx_code outer_code;
4951 cost = 2 * GET_MODE_SIZE (GET_MODE (X));
4954 if (outer_code != SET)
4956 if (GET_CODE (XEXP (X,0)) == SYMBOL_REF)
4957 cost += 2 * GET_MODE_SIZE (GET_MODE (X));
4959 cost += GET_MODE_SIZE (GET_MODE (X));
4965 if (outer_code == SET)
4966 cost = GET_MODE_SIZE (GET_MODE (X));
4968 cost = -GET_MODE_SIZE (GET_MODE (X));
4971 if (outer_code == SET)
4972 cost = GET_MODE_SIZE (GET_MODE (X));
4978 if (outer_code == SET)
4980 if (X == stack_pointer_rtx)
4982 else if (GET_CODE (XEXP (X,1)) == CONST_INT)
4983 cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 :
4984 GET_MODE_SIZE (GET_MODE (X)));
4986 cost = GET_MODE_SIZE (GET_MODE (X));
4990 if (GET_CODE (XEXP (X,1)) == CONST_INT)
4991 cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0)));
4999 /* Calculate the cost of a memory address */
5002 avr_address_cost (x)
5005 if (GET_CODE (x) == PLUS
5006 && GET_CODE (XEXP (x,1)) == CONST_INT
5007 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
5008 && INTVAL (XEXP (x,1)) >= 61)
5010 if (CONSTANT_ADDRESS_P (x))
5012 if (avr_io_address_p (x, 1))
5019 /* EXTRA_CONSTRAINT helper */
5022 extra_constraint (x, c)
5027 && GET_CODE (x) == MEM
5028 && GET_CODE (XEXP (x,0)) == PLUS)
5030 if (TARGET_ALL_DEBUG)
5032 fprintf (stderr, ("extra_constraint:\n"
5033 "reload_completed: %d\n"
5034 "reload_in_progress: %d\n"),
5035 reload_completed, reload_in_progress);
5038 if (GET_CODE (x) == MEM
5039 && GET_CODE (XEXP (x,0)) == PLUS
5040 && REG_P (XEXP (XEXP (x,0), 0))
5041 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
5042 && (INTVAL (XEXP (XEXP (x,0), 1))
5043 <= MAX_LD_OFFSET (GET_MODE (x))))
5045 rtx xx = XEXP (XEXP (x,0), 0);
5046 int regno = REGNO (xx);
5047 if (TARGET_ALL_DEBUG)
5049 fprintf (stderr, ("extra_constraint:\n"
5050 "reload_completed: %d\n"
5051 "reload_in_progress: %d\n"),
5052 reload_completed, reload_in_progress);
5055 if (regno >= FIRST_PSEUDO_REGISTER)
5056 return 1; /* allocate pseudos */
5057 else if (regno == REG_Z || regno == REG_Y)
5058 return 1; /* strictly check */
5059 else if (xx == frame_pointer_rtx
5060 || xx == arg_pointer_rtx)
5061 return 1; /* XXX frame & arg pointer checks */
5067 /* Convert condition code CONDITION to the valid AVR condition code */
5070 avr_normalize_condition (condition)
5088 /* This fnction optimizes conditional jumps */
5091 machine_dependent_reorg (first_insn)
5096 for (insn = first_insn; insn; insn = NEXT_INSN (insn))
5098 if (! (GET_CODE (insn) == INSN
5099 || GET_CODE (insn) == CALL_INSN
5100 || GET_CODE (insn) == JUMP_INSN)
5101 || !single_set (insn))
5104 pattern = PATTERN (insn);
5106 if (GET_CODE (pattern) == PARALLEL)
5107 pattern = XVECEXP (pattern, 0, 0);
5108 if (GET_CODE (pattern) == SET
5109 && SET_DEST (pattern) == cc0_rtx
5110 && compare_diff_p (insn))
5112 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
5114 /* Now we work under compare insn */
5116 pattern = SET_SRC (pattern);
5117 if (true_regnum (XEXP (pattern,0)) >= 0
5118 && true_regnum (XEXP (pattern,1)) >= 0 )
5120 rtx x = XEXP (pattern,0);
5121 rtx next = next_real_insn (insn);
5122 rtx pat = PATTERN (next);
5123 rtx src = SET_SRC (pat);
5124 rtx t = XEXP (src,0);
5125 PUT_CODE (t, swap_condition (GET_CODE (t)));
5126 XEXP (pattern,0) = XEXP (pattern,1);
5127 XEXP (pattern,1) = x;
5128 INSN_CODE (next) = -1;
5130 else if (true_regnum (XEXP (pattern,0)) >= 0
5131 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
5133 rtx x = XEXP (pattern,1);
5134 rtx next = next_real_insn (insn);
5135 rtx pat = PATTERN (next);
5136 rtx src = SET_SRC (pat);
5137 rtx t = XEXP (src,0);
5138 enum machine_mode mode = GET_MODE (XEXP (pattern, 0));
5140 if (avr_simplify_comparision_p (mode, GET_CODE (t), x))
5142 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
5143 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
5144 INSN_CODE (next) = -1;
5145 INSN_CODE (insn) = -1;
5149 else if (true_regnum (SET_SRC (pattern)) >= 0)
5151 /* This is a tst insn */
5152 rtx next = next_real_insn (insn);
5153 rtx pat = PATTERN (next);
5154 rtx src = SET_SRC (pat);
5155 rtx t = XEXP (src,0);
5157 PUT_CODE (t, swap_condition (GET_CODE (t)));
5158 SET_SRC (pattern) = gen_rtx (NEG,
5159 GET_MODE (SET_SRC (pattern)),
5161 INSN_CODE (next) = -1;
5162 INSN_CODE (insn) = -1;
5168 /* Returns register number for function return value.*/
5176 /* Ceate an RTX representing the place where a
5177 library function returns a value of mode MODE. */
5180 avr_libcall_value (mode)
5181 enum machine_mode mode;
5183 int offs = GET_MODE_SIZE (mode);
5186 return gen_rtx (REG, mode, RET_REGISTER + 2 - offs);
5189 /* Create an RTX representing the place where a
5190 function returns a value of data type VALTYPE. */
5193 avr_function_value (type, func)
5195 tree func ATTRIBUTE_UNUSED;
5199 if (TYPE_MODE (type) != BLKmode)
5200 return avr_libcall_value (TYPE_MODE (type));
5202 offs = int_size_in_bytes (type);
5205 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5206 offs = GET_MODE_SIZE (SImode);
5207 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5208 offs = GET_MODE_SIZE (DImode);
5210 return gen_rtx (REG, BLKmode, RET_REGISTER + 2 - offs);
5213 /* Returns non-zero if the number MASK has only one bit set. */
5216 mask_one_bit_p (mask)
5220 unsigned HOST_WIDE_INT n=mask;
5221 for (i = 0; i < 32; ++i)
5223 if (n & 0x80000000L)
5225 if (n & 0x7fffffffL)
5236 /* Places additional restrictions on the register class to
5237 use when it is necessary to copy value X into a register
5241 preferred_reload_class (x, class)
5242 rtx x ATTRIBUTE_UNUSED;
5243 enum reg_class class;
5249 test_hard_reg_class (class, x)
5250 enum reg_class class;
5253 int regno = true_regnum (x);
5256 return TEST_HARD_REG_CLASS (class, regno);
5260 debug_hard_reg_set (set)
5264 for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
5266 if (TEST_HARD_REG_BIT (set, i))
5268 fprintf (stderr, "r%-2d ", i);
5271 fprintf (stderr, "\n");
5275 jump_over_one_insn_p (insn, dest)
5279 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5282 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5283 int dest_addr = INSN_ADDRESSES (uid);
5284 return dest_addr - jump_addr == get_attr_length (insn) + 1;
5287 /* Returns 1 if a value of mode MODE can be stored starting with hard
5288 register number REGNO. On the enhanced core, anything larger than
5289 1 byte must start in even numbered register for "movw" to work
5290 (this way we don't have to check for odd registers everywhere). */
5293 avr_hard_regno_mode_ok (regno, mode)
5295 enum machine_mode mode;
5297 /* Bug workaround: recog.c (peep2_find_free_register) and probably
5298 a few other places assume that the frame pointer is a single hard
5299 register, so r29 may be allocated and overwrite the high byte of
5300 the frame pointer. Do not allow any value to start in r29. */
5301 if (regno == REG_Y + 1)
5306 /* if (regno < 24 && !AVR_ENHANCED)
5308 return !(regno & 1);
5311 /* Returns 1 if we know register operand OP was 0 before INSN. */
5314 reg_was_0 (insn, op)
5319 return (optimize > 0 && insn && op && REG_P (op)
5320 && (link = find_reg_note (insn, REG_WAS_0, 0))
5321 /* Make sure the insn that stored the 0 is still present. */
5322 && ! INSN_DELETED_P (XEXP (link, 0))
5323 && GET_CODE (XEXP (link, 0)) != NOTE
5324 /* Make sure cross jumping didn't happen here. */
5325 && no_labels_between_p (XEXP (link, 0), insn)
5326 /* Make sure the reg hasn't been clobbered. */
5327 && ! reg_set_between_p (op, XEXP (link, 0), insn));
5330 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5331 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5332 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
5335 avr_io_address_p (x, size)
5339 return (optimize > 0 && GET_CODE (x) == CONST_INT
5340 && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
5343 /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5346 const_int_pow2_p (x)
5349 if (GET_CODE (x) == CONST_INT)
5351 HOST_WIDE_INT d = INTVAL (x);
5352 HOST_WIDE_INT abs_d = (d >= 0) ? d : -d;
5353 return exact_log2 (abs_d) + 1;
5359 output_reload_inhi (insn, operands, len)
5360 rtx insn ATTRIBUTE_UNUSED;
5368 if (GET_CODE (operands[1]) == CONST_INT)
5370 int val = INTVAL (operands[1]);
5371 if ((val & 0xff) == 0)
5374 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5375 AS2 (ldi,%2,hi8(%1)) CR_TAB
5378 else if ((val & 0xff00) == 0)
5381 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5382 AS2 (mov,%A0,%2) CR_TAB
5383 AS2 (mov,%B0,__zero_reg__));
5385 else if ((val & 0xff) == ((val & 0xff00) >> 8))
5388 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5389 AS2 (mov,%A0,%2) CR_TAB
5394 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5395 AS2 (mov,%A0,%2) CR_TAB
5396 AS2 (ldi,%2,hi8(%1)) CR_TAB
5402 output_reload_insisf (insn, operands, len)
5403 rtx insn ATTRIBUTE_UNUSED;
5407 rtx src = operands[1];
5408 int cnst = (GET_CODE (src) == CONST_INT);
5413 *len = 4 + ((INTVAL (src) & 0xff) != 0)
5414 + ((INTVAL (src) & 0xff00) != 0)
5415 + ((INTVAL (src) & 0xff0000) != 0)
5416 + ((INTVAL (src) & 0xff000000) != 0);
5423 if (cnst && ((INTVAL (src) & 0xff) == 0))
5424 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5427 output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
5428 output_asm_insn (AS2 (mov, %A0, %2), operands);
5430 if (cnst && ((INTVAL (src) & 0xff00) == 0))
5431 output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
5434 output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
5435 output_asm_insn (AS2 (mov, %B0, %2), operands);
5437 if (cnst && ((INTVAL (src) & 0xff0000) == 0))
5438 output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
5441 output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
5442 output_asm_insn (AS2 (mov, %C0, %2), operands);
5444 if (cnst && ((INTVAL (src) & 0xff000000) == 0))
5445 output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
5448 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5449 output_asm_insn (AS2 (mov, %D0, %2), operands);
5455 avr_output_bld (operands, bit_nr)
5459 static char s[] = "bld %A0,0";
5461 s[5] = 'A' + (bit_nr >> 3);
5462 s[8] = '0' + (bit_nr & 7);
5463 output_asm_insn (s, operands);
5467 avr_output_addr_vec_elt (stream, value)
5472 fprintf (stream, "\t.word pm(.L%d)\n", value);
5474 fprintf (stream, "\trjmp .L%d\n", value);
5479 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5480 registers (for a define_peephole2) in the current function. */
5483 avr_peep2_scratch_safe (scratch)
5486 if ((interrupt_function_p (current_function_decl)
5487 || signal_function_p (current_function_decl))
5488 && leaf_function_p ())
5490 int first_reg = true_regnum (scratch);
5491 int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
5494 for (reg = first_reg; reg <= last_reg; reg++)
5496 if (!regs_ever_live[reg])
5503 /* Output a branch that tests a single bit of a register (QI, HI or SImode)
5504 or memory location in the I/O space (QImode only).
5506 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5507 Operand 1: register operand to test, or CONST_INT memory address.
5508 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5509 Operand 3: label to jump to if the test is true. */
5512 avr_out_sbxx_branch (insn, operands)
5516 enum rtx_code comp = GET_CODE (operands[0]);
5517 int long_jump = (get_attr_length (insn) >= 4);
5518 int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
5522 else if (comp == LT)
5526 comp = reverse_condition (comp);
5528 if (GET_CODE (operands[1]) == CONST_INT)
5530 if (INTVAL (operands[1]) < 0x40)
5533 output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
5535 output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
5539 output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
5541 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
5543 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
5546 else /* GET_CODE (operands[1]) == REG */
5548 if (GET_MODE (operands[1]) == QImode)
5551 output_asm_insn (AS2 (sbrs,%1,%2), operands);
5553 output_asm_insn (AS2 (sbrc,%1,%2), operands);
5555 else /* HImode or SImode */
5557 static char buf[] = "sbrc %A1,0";
5558 int bit_nr = exact_log2 (INTVAL (operands[2])
5559 & GET_MODE_MASK (GET_MODE (operands[1])));
5561 buf[3] = (comp == EQ) ? 's' : 'c';
5562 buf[6] = 'A' + (bit_nr >> 3);
5563 buf[9] = '0' + (bit_nr & 7);
5564 output_asm_insn (buf, operands);
5569 return (AS1 (rjmp,_PC_+4) CR_TAB
5572 return AS1 (rjmp,%3);
5577 avr_asm_out_ctor (symbol, priority)
5581 fputs ("\t.global __do_global_ctors\n", asm_out_file);
5582 default_ctor_section_asm_out_constructor (symbol, priority);
5586 avr_asm_out_dtor (symbol, priority)
5590 fputs ("\t.global __do_global_dtors\n", asm_out_file);
5591 default_dtor_section_asm_out_destructor (symbol, priority);