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 sequent_regs_live PARAMS ((void));
51 static const char * ptrreg_to_str PARAMS ((int));
52 static const char * cond_string PARAMS ((enum rtx_code));
53 static int avr_num_arg_regs PARAMS ((enum machine_mode, tree));
54 static int out_adj_frame_ptr PARAMS ((FILE *, int));
55 static int out_set_stack_ptr PARAMS ((FILE *, int, int));
56 static RTX_CODE compare_condition PARAMS ((rtx insn));
57 static int compare_sign_p PARAMS ((rtx insn));
58 static int reg_was_0 PARAMS ((rtx insn, rtx op));
59 static int io_address_p PARAMS ((rtx x, int size));
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));
68 /* Allocate registers from r25 to r8 for parameters for function calls */
69 #define FIRST_CUM_REG 26
71 /* Temporary register RTX (gen_rtx (REG,QImode,TMP_REGNO)) */
74 /* Zeroed register RTX (gen_rtx (REG,QImode,ZERO_REGNO)) */
77 /* RTX for register which will be used for loading immediate values to
81 /* AVR register names {"r0", "r1", ..., "r31"} */
82 static const char *const avr_regnames[] = REGISTER_NAMES;
84 /* This holds the last insn address. */
85 static int last_insn_address = 0;
87 /* Commands count in the compiled file */
88 static int commands_in_file;
90 /* Commands in the functions prologues in the compiled file */
91 static int commands_in_prologues;
93 /* Commands in the functions epilogues in the compiled file */
94 static int commands_in_epilogues;
96 /* Prologue/Epilogue size in words */
97 static int prologue_size;
98 static int epilogue_size;
100 /* Size of all jump tables in the current function, in words. */
101 static int jump_tables_size;
103 /* Initial stack value specified by the `-minit-stack=' option */
104 const char *avr_init_stack = "__stack";
106 /* Default MCU name */
107 const char *avr_mcu_name = "avr2";
109 /* More than 8K of program memory: use "call" and "jmp". */
112 /* Enhanced core: use "movw", "mul", ... */
113 int avr_enhanced_p = 0;
124 const char *const name;
125 const enum avr_arch arch;
128 /* List of all known AVR MCU types - if updated, it has to be kept
129 in sync in several places (FIXME: is there a better way?):
131 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
132 - t-avr (MULTILIB_MATCHES)
133 - gas/config/tc-avr.c
136 static const struct mcu_type_s avr_mcu_types[] = {
137 /* Classic, <= 8K. */
139 { "at90s2313", AVR2 },
140 { "at90s2323", AVR2 },
141 { "attiny22", AVR2 },
142 { "at90s2333", AVR2 },
143 { "at90s2343", AVR2 },
144 { "at90s4414", AVR2 },
145 { "at90s4433", AVR2 },
146 { "at90s4434", AVR2 },
147 { "at90s8515", AVR2 },
148 { "at90c8534", AVR2 },
149 { "at90s8535", AVR2 },
152 { "atmega103", AVR3 },
153 { "atmega603", AVR3 },
154 { "at43usb320", AVR3 },
155 { "at76c711", AVR3 },
156 /* Enhanced, <= 8K. */
159 { "atmega83", AVR4 },
160 { "atmega85", AVR4 },
161 /* Enhanced, > 8K. */
163 { "atmega16", AVR5 },
164 { "atmega161", AVR5 },
165 { "atmega163", AVR5 },
166 { "atmega32", AVR5 },
167 { "atmega323", AVR5 },
168 { "atmega64", AVR5 },
169 { "atmega128", AVR5 },
170 { "at43usb355", AVR5 },
172 /* Assembler only. */
174 { "at90s1200", AVR1 },
175 { "attiny10", AVR1 },
176 { "attiny11", AVR1 },
177 { "attiny12", AVR1 },
178 { "attiny15", AVR1 },
179 { "attiny28", AVR1 },
183 int avr_case_values_threshold = 30000;
185 /* Initialize the GCC target structure. */
186 #undef TARGET_ASM_ALIGNED_HI_OP
187 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
188 #undef TARGET_ASM_INTEGER
189 #define TARGET_ASM_INTEGER avr_assemble_integer
191 #undef TARGET_ASM_FUNCTION_PROLOGUE
192 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
193 #undef TARGET_ASM_FUNCTION_EPILOGUE
194 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
195 #undef TARGET_ATTRIBUTE_TABLE
196 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
198 struct gcc_target targetm = TARGET_INITIALIZER;
201 avr_override_options ()
203 const struct mcu_type_s *t;
205 for (t = avr_mcu_types; t->name; t++)
206 if (strcmp (t->name, avr_mcu_name) == 0)
211 fprintf (stderr, "unknown MCU `%s' specified\nKnown MCU names:\n",
213 for (t = avr_mcu_types; t->name; t++)
214 fprintf (stderr," %s\n", t->name);
221 error ("MCU `%s' not supported", avr_mcu_name);
222 /* ... fall through ... */
223 case AVR2: avr_enhanced_p = 0; avr_mega_p = 0; break;
224 case AVR3: avr_enhanced_p = 0; avr_mega_p = 1; break;
225 case AVR4: avr_enhanced_p = 1; avr_mega_p = 0; break;
226 case AVR5: avr_enhanced_p = 1; avr_mega_p = 1; break;
229 if (optimize && !TARGET_NO_TABLEJUMP)
230 avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
234 /* Initialize TMP_REG_RTX and ZERO_REG_RTX */
238 tmp_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
239 memset (tmp_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
240 PUT_CODE (tmp_reg_rtx, REG);
241 PUT_MODE (tmp_reg_rtx, QImode);
242 XINT (tmp_reg_rtx, 0) = TMP_REGNO;
244 zero_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
245 memset (zero_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
246 PUT_CODE (zero_reg_rtx, REG);
247 PUT_MODE (zero_reg_rtx, QImode);
248 XINT (zero_reg_rtx, 0) = ZERO_REGNO;
250 ldi_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
251 memset (ldi_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
252 PUT_CODE (ldi_reg_rtx, REG);
253 PUT_MODE (ldi_reg_rtx, QImode);
254 XINT (ldi_reg_rtx, 0) = LDI_REG_REGNO;
257 /* return register class from register number */
259 static const int reg_class_tab[]={
260 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
261 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
262 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
263 GENERAL_REGS, /* r0 - r15 */
264 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
265 LD_REGS, /* r16 - 23 */
266 ADDW_REGS,ADDW_REGS, /* r24,r25 */
267 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
268 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
269 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
270 STACK_REG,STACK_REG /* SPL,SPH */
273 /* Return register class for register R */
276 avr_regno_reg_class (r)
280 return reg_class_tab[r];
285 /* A C expression which defines the machine-dependent operand
286 constraint letters for register classes. If C is such a
287 letter, the value should be the register class corresponding to
288 it. Otherwise, the value should be `NO_REGS'. The register
289 letter `r', corresponding to class `GENERAL_REGS', will not be
290 passed to this macro; you do not need to handle it. */
293 avr_reg_class_from_letter (c)
298 case 't' : return R0_REG;
299 case 'b' : return BASE_POINTER_REGS;
300 case 'e' : return POINTER_REGS;
301 case 'w' : return ADDW_REGS;
302 case 'd' : return LD_REGS;
303 case 'l' : return NO_LD_REGS;
304 case 'a' : return SIMPLE_LD_REGS;
305 case 'x' : return POINTER_X_REGS;
306 case 'y' : return POINTER_Y_REGS;
307 case 'z' : return POINTER_Z_REGS;
308 case 'q' : return STACK_REG;
314 /* Return non-zero if FUNC is a naked function. */
317 avr_naked_function_p (func)
322 if (TREE_CODE (func) != FUNCTION_DECL)
325 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
326 return a != NULL_TREE;
329 /* Return nonzero if FUNC is an interrupt function as specified
330 by the "interrupt" attribute. */
333 interrupt_function_p (func)
338 if (TREE_CODE (func) != FUNCTION_DECL)
341 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
342 return a != NULL_TREE;
345 /* Return nonzero if FUNC is a signal function as specified
346 by the "signal" attribute. */
349 signal_function_p (func)
354 if (TREE_CODE (func) != FUNCTION_DECL)
357 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
358 return a != NULL_TREE;
361 /* Compute offset between arg_pointer and frame_pointer */
364 initial_elimination_offset (from, to)
369 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
373 int interrupt_func_p = interrupt_function_p (current_function_decl);
374 int signal_func_p = signal_function_p (current_function_decl);
375 int leaf_func_p = leaf_function_p ();
376 int offset= frame_pointer_needed ? 2 : 0;
378 for (reg = 0; reg < 32; ++reg)
380 if ((!leaf_func_p && (call_used_regs[reg]
381 && (interrupt_func_p || signal_func_p)))
382 || (regs_ever_live[reg]
383 && (!call_used_regs[reg] || interrupt_func_p || signal_func_p)
384 && ! (frame_pointer_needed
385 && (reg == REG_Y || reg == (REG_Y+1)))))
390 return get_frame_size () + 2 + 1 + offset;
395 /* This function checks sequence of live registers */
404 for (reg = 0; reg < 18; ++reg)
406 if (!call_used_regs[reg])
408 if (regs_ever_live[reg])
418 if (!frame_pointer_needed)
420 if (regs_ever_live[REG_Y])
428 if (regs_ever_live[REG_Y+1])
441 return (cur_seq == live_seq) ? live_seq : 0;
445 /* Output to FILE the asm instructions to adjust the frame pointer by
446 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
447 (epilogue). Returns the number of instructions generated. */
450 out_adj_frame_ptr (file, adj)
458 if (TARGET_TINY_STACK)
460 if (adj < -63 || adj > 63)
461 warning ("large frame pointer change (%d) with -mtiny-stack", adj);
463 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
464 over "sbiw" (2 cycles, same size). */
466 fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
469 else if (adj < -63 || adj > 63)
471 fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
472 AS2 (sbci, r29, hi8(%d)) CR_TAB),
478 fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
483 fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
491 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
492 handling various cases of interrupt enable flag state BEFORE and AFTER
493 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
494 Returns the number of instructions generated. */
497 out_set_stack_ptr (file, before, after)
502 int do_sph, do_cli, do_save, do_sei, lock_sph, size;
504 /* The logic here is so that -mno-interrupts actually means
505 "it is safe to write SPH in one instruction, then SPL in the
506 next instruction, without disabling interrupts first".
507 The after != -1 case (interrupt/signal) is not affected. */
509 do_sph = !TARGET_TINY_STACK;
510 lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
511 do_cli = (before != 0 && (after == 0 || lock_sph));
512 do_save = (do_cli && before == -1 && after == -1);
513 do_sei = ((do_cli || before != 1) && after == 1);
518 fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
524 fprintf (file, "cli" CR_TAB);
528 /* Do SPH first - maybe this will disable interrupts for one instruction
529 someday (a suggestion has been sent to avr@atmel.com for consideration
530 in future devices - that would make -mno-interrupts always safe). */
533 fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
537 /* Set/restore the I flag now - interrupts will be really enabled only
538 after the next instruction. This is not clearly documented, but
539 believed to be true for all AVR devices. */
542 fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
547 fprintf (file, "sei" CR_TAB);
551 fprintf (file, AS2 (out, __SP_L__, r28) "\n");
557 /* Output function prologue */
560 avr_output_function_prologue (file, size)
565 int interrupt_func_p;
572 if (avr_naked_function_p (current_function_decl))
574 fprintf (file, "/* prologue: naked */\n");
578 interrupt_func_p = interrupt_function_p (current_function_decl);
579 signal_func_p = signal_function_p (current_function_decl);
580 leaf_func_p = leaf_function_p ();
581 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
582 live_seq = sequent_regs_live ();
583 minimize = (TARGET_CALL_PROLOGUES
584 && !interrupt_func_p && !signal_func_p && live_seq);
586 last_insn_address = 0;
587 jump_tables_size = 0;
589 fprintf (file, "/* prologue: frame size=%d */\n", size);
591 if (interrupt_func_p)
593 fprintf (file,"\tsei\n");
596 if (interrupt_func_p | signal_func_p)
599 AS1 (push,__zero_reg__) CR_TAB
600 AS1 (push,__tmp_reg__) CR_TAB
601 AS2 (in,__tmp_reg__,__SREG__) CR_TAB
602 AS1 (push,__tmp_reg__) CR_TAB
603 AS1 (clr,__zero_reg__) "\n");
609 AS2 (ldi,r28,lo8(%s - %d)) CR_TAB
610 AS2 (ldi,r29,hi8(%s - %d)) CR_TAB
611 AS2 (out,__SP_H__,r29) CR_TAB
612 AS2 (out,__SP_L__,r28) "\n"),
613 avr_init_stack, size, avr_init_stack, size);
617 else if (minimize && (frame_pointer_needed || live_seq > 6))
620 AS2 (ldi, r26, lo8(%d)) CR_TAB
621 AS2 (ldi, r27, hi8(%d)) CR_TAB), size, size);
623 fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB
624 AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB)
625 ,current_function_name, current_function_name);
631 fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
632 (18 - live_seq) * 2);
637 fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
638 (18 - live_seq) * 2);
641 fprintf (file, ".L_%s_body:\n", current_function_name);
645 for (reg = 0; reg < 32; ++reg)
648 && (call_used_regs[reg]
649 && (interrupt_func_p || signal_func_p)
650 && !(reg == TMP_REGNO || reg == ZERO_REGNO)))
651 || (regs_ever_live[reg]
652 && (!call_used_regs[reg]
653 || interrupt_func_p || signal_func_p)
654 && ! (frame_pointer_needed
655 && (reg == REG_Y || reg == (REG_Y+1)))))
657 fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
661 if (frame_pointer_needed)
665 AS1 (push,r28) CR_TAB
666 AS1 (push,r29) CR_TAB
667 AS2 (in,r28,__SP_L__) CR_TAB
668 AS2 (in,r29,__SP_H__) "\n");
673 prologue_size += out_adj_frame_ptr (file, size);
675 if (interrupt_func_p)
677 prologue_size += out_set_stack_ptr (file, 1, 1);
679 else if (signal_func_p)
681 prologue_size += out_set_stack_ptr (file, 0, 0);
685 prologue_size += out_set_stack_ptr (file, -1, -1);
691 fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
694 /* Output function epilogue */
697 avr_output_function_epilogue (file, size)
702 int interrupt_func_p;
710 if (avr_naked_function_p (current_function_decl))
712 fprintf (file, "/* epilogue: naked */\n");
716 interrupt_func_p = interrupt_function_p (current_function_decl);
717 signal_func_p = signal_function_p (current_function_decl);
718 leaf_func_p = leaf_function_p ();
719 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
720 function_size = (INSN_ADDRESSES (INSN_UID (get_last_insn ()))
721 - INSN_ADDRESSES (INSN_UID (get_insns ())));
722 function_size += jump_tables_size;
723 live_seq = sequent_regs_live ();
724 minimize = (TARGET_CALL_PROLOGUES
725 && !interrupt_func_p && !signal_func_p && live_seq);
728 fprintf (file, "/* epilogue: frame size=%d */\n", size);
731 fprintf (file, "__stop_progIi__:\n\trjmp __stop_progIi__\n");
734 else if (minimize && (frame_pointer_needed || live_seq > 4))
736 fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
738 if (frame_pointer_needed)
740 epilogue_size += out_adj_frame_ptr (file, -size);
744 fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
745 AS2 (in , r29, __SP_H__) CR_TAB));
751 fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
752 (18 - live_seq) * 2);
757 fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
758 (18 - live_seq) * 2);
764 if (frame_pointer_needed)
769 epilogue_size += out_adj_frame_ptr (file, -size);
771 if (interrupt_func_p | signal_func_p)
773 epilogue_size += out_set_stack_ptr (file, -1, 0);
777 epilogue_size += out_set_stack_ptr (file, -1, -1);
786 for (reg = 31; reg >= 0; --reg)
789 && (call_used_regs[reg]
790 && (interrupt_func_p || signal_func_p)
791 && !(reg == TMP_REGNO || reg == ZERO_REGNO)))
792 || (regs_ever_live[reg]
793 && (!call_used_regs[reg]
794 || interrupt_func_p || signal_func_p)
795 && ! (frame_pointer_needed
796 && (reg == REG_Y || reg == (REG_Y+1)))))
798 fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
803 if (interrupt_func_p | signal_func_p)
806 AS1 (pop,__tmp_reg__) CR_TAB
807 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
808 AS1 (pop,__tmp_reg__) CR_TAB
809 AS1 (pop,__zero_reg__) "\n");
811 fprintf (file, "\treti\n");
814 fprintf (file, "\tret\n");
818 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
819 fprintf (file, "/* function %s size %d (%d) */\n", current_function_name,
820 prologue_size + function_size + epilogue_size, function_size);
821 commands_in_file += prologue_size + function_size + epilogue_size;
822 commands_in_prologues += prologue_size;
823 commands_in_epilogues += epilogue_size;
827 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
828 machine for a memory operand of mode MODE. */
831 legitimate_address_p (mode, x, strict)
832 enum machine_mode mode;
836 enum reg_class r = NO_REGS;
838 if (TARGET_ALL_DEBUG)
840 fprintf (stderr, "mode: (%s) %s %s %s %s:",
842 strict ? "(strict)": "",
843 reload_completed ? "(reload_completed)": "",
844 reload_in_progress ? "(reload_in_progress)": "",
845 reg_renumber ? "(reg_renumber)" : "");
846 if (GET_CODE (x) == PLUS
847 && REG_P (XEXP (x, 0))
848 && GET_CODE (XEXP (x, 1)) == CONST_INT
849 && INTVAL (XEXP (x, 1)) >= 0
850 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
853 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
854 true_regnum (XEXP (x, 0)));
857 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
858 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
860 else if (CONSTANT_ADDRESS_P (x))
862 else if (GET_CODE (x) == PLUS
863 && REG_P (XEXP (x, 0))
864 && GET_CODE (XEXP (x, 1)) == CONST_INT
865 && INTVAL (XEXP (x, 1)) >= 0)
867 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
871 || REGNO (XEXP (x,0)) == REG_Y
872 || REGNO (XEXP (x,0)) == REG_Z)
873 r = BASE_POINTER_REGS;
874 if (XEXP (x,0) == frame_pointer_rtx
875 || XEXP (x,0) == arg_pointer_rtx)
876 r = BASE_POINTER_REGS;
878 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
881 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
882 && REG_P (XEXP (x, 0))
883 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
884 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
888 if (TARGET_ALL_DEBUG)
890 fprintf (stderr, " ret = %c\n", r);
892 return r == NO_REGS ? 0 : (int)r;
895 /* Attempts to replace X with a valid
896 memory address for an operand of mode MODE */
899 legitimize_address (x, oldx, mode)
902 enum machine_mode mode;
905 if (TARGET_ALL_DEBUG)
907 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
911 if (GET_CODE (oldx) == PLUS
912 && REG_P (XEXP (oldx,0)))
914 if (REG_P (XEXP (oldx,1)))
915 x = force_reg (GET_MODE (oldx), oldx);
916 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
918 int offs = INTVAL (XEXP (oldx,1));
919 if (frame_pointer_rtx != XEXP (oldx,0))
920 if (offs > MAX_LD_OFFSET (mode))
922 if (TARGET_ALL_DEBUG)
923 fprintf (stderr, "force_reg (big offset)\n");
924 x = force_reg (GET_MODE (oldx), oldx);
932 /* Return a pointer register name as a string */
935 ptrreg_to_str (regno)
940 case REG_X: return "X";
941 case REG_Y: return "Y";
942 case REG_Z: return "Z";
949 /* Return the condition name as a string.
950 Used in conditional jump constructing */
963 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
968 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
981 /* Output ADDR to FILE as address */
984 print_operand_address (file, addr)
988 switch (GET_CODE (addr))
991 fprintf (file, ptrreg_to_str (REGNO (addr)));
995 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
999 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1003 if (CONSTANT_ADDRESS_P (addr)
1004 && (SYMBOL_REF_FLAG (addr) || GET_CODE (addr) == LABEL_REF))
1006 fprintf (file, "pm(");
1007 output_addr_const (file,addr);
1008 fprintf (file ,")");
1011 output_addr_const (file, addr);
1016 /* Output X as assembler operand to file FILE */
1019 print_operand (file, x, code)
1026 if (code >= 'A' && code <= 'D')
1036 if (x == zero_reg_rtx)
1037 fprintf (file, "__zero_reg__");
1039 fprintf (file, reg_names[true_regnum (x) + abcd]);
1041 else if (GET_CODE (x) == CONST_INT)
1042 fprintf (file, "%d", INTVAL (x) + abcd);
1043 else if (GET_CODE (x) == MEM)
1045 rtx addr = XEXP (x,0);
1047 if (CONSTANT_P (addr) && abcd)
1050 output_address (addr);
1051 fprintf (file, ")+%d", abcd);
1053 else if (code == 'o')
1055 if (GET_CODE (addr) != PLUS)
1056 fatal_insn ("bad address, not (reg+disp):", addr);
1058 print_operand (file, XEXP (addr, 1), 0);
1060 else if (GET_CODE (addr) == PLUS)
1062 print_operand_address (file, XEXP (addr,0));
1063 if (REGNO (XEXP (addr, 0)) == REG_X)
1064 fatal_insn ("internal compiler error. Bad address:"
1067 print_operand (file, XEXP (addr,1), code);
1070 print_operand_address (file, addr);
1072 else if (GET_CODE (x) == CONST_DOUBLE)
1076 if (GET_MODE (x) != SFmode)
1077 fatal_insn ("internal compiler error. Unknown mode:", x);
1078 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1079 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1080 asm_fprintf (file, "0x%lx", val);
1082 else if (code == 'j')
1083 asm_fprintf (file, cond_string (GET_CODE (x)));
1084 else if (code == 'k')
1085 asm_fprintf (file, cond_string (reverse_condition (GET_CODE (x))));
1087 print_operand_address (file, x);
1090 /* Recognize operand OP of mode MODE used in call instructions */
1093 call_insn_operand (op, mode)
1095 enum machine_mode mode ATTRIBUTE_UNUSED;
1097 if (GET_CODE (op) == MEM)
1099 rtx inside = XEXP (op, 0);
1100 if (register_operand (inside, Pmode))
1102 if (CONSTANT_ADDRESS_P (inside))
1108 /* Update the condition code in the INSN. */
1111 notice_update_cc (body, insn)
1112 rtx body ATTRIBUTE_UNUSED;
1117 switch (get_attr_cc (insn))
1120 /* Insn does not affect CC at all. */
1128 set = single_set (insn);
1132 cc_status.flags |= CC_NO_OVERFLOW;
1133 cc_status.value1 = SET_DEST (set);
1138 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1139 The V flag may or may not be known but that's ok because
1140 alter_cond will change tests to use EQ/NE. */
1141 set = single_set (insn);
1145 cc_status.value1 = SET_DEST (set);
1146 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1151 set = single_set (insn);
1154 cc_status.value1 = SET_SRC (set);
1158 /* Insn doesn't leave CC in a usable state. */
1161 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1162 set = single_set (insn);
1165 rtx src = SET_SRC (set);
1167 if (GET_CODE (src) == ASHIFTRT
1168 && GET_MODE (src) == QImode)
1170 rtx x = XEXP (src, 1);
1172 if (GET_CODE (x) == CONST_INT
1175 cc_status.value1 = SET_DEST (set);
1176 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1184 /* Return maximum number of consecutive registers of
1185 class CLASS needed to hold a value of mode MODE. */
1188 class_max_nregs (class, mode)
1189 enum reg_class class ATTRIBUTE_UNUSED;
1190 enum machine_mode mode;
1192 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1195 /* Choose mode for jump insn:
1196 1 - relative jump in range -63 <= x <= 62 ;
1197 2 - relative jump in range -2046 <= x <= 2045 ;
1198 3 - absolute jump (only for ATmega[16]03). */
1201 avr_jump_mode (x, insn)
1202 rtx x; /* jump operand */
1203 rtx insn; /* jump insn */
1205 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1206 ? XEXP (x, 0) : x));
1207 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1208 int jump_distance = cur_addr - dest_addr;
1210 if (-63 <= jump_distance && jump_distance <= 62)
1212 else if (-2046 <= jump_distance && jump_distance <= 2045)
1220 /* return an AVR condition jump commands.
1221 X is a comparison RTX.
1222 LEN is a number returned by avr_jump_mode function.
1223 if REVERSE nonzero then condition code in X must be reversed. */
1226 ret_cond_branch (x, len, reverse)
1231 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1236 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1237 return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1239 len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1240 AS1 (brmi,_PC_+2) CR_TAB
1242 (AS1 (breq,_PC_+6) CR_TAB
1243 AS1 (brmi,_PC_+4) CR_TAB
1247 return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1249 len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1250 AS1 (brlt,_PC_+2) CR_TAB
1252 (AS1 (breq,_PC_+6) CR_TAB
1253 AS1 (brlt,_PC_+4) CR_TAB
1256 return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1258 len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1259 AS1 (brlo,_PC_+2) CR_TAB
1261 (AS1 (breq,_PC_+6) CR_TAB
1262 AS1 (brlo,_PC_+4) CR_TAB
1265 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1266 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1268 len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1269 AS1 (brpl,_PC_+2) CR_TAB
1271 (AS1 (breq,_PC_+2) CR_TAB
1272 AS1 (brpl,_PC_+4) CR_TAB
1275 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1277 len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1278 AS1 (brge,_PC_+2) CR_TAB
1280 (AS1 (breq,_PC_+2) CR_TAB
1281 AS1 (brge,_PC_+4) CR_TAB
1284 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1286 len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1287 AS1 (brsh,_PC_+2) CR_TAB
1289 (AS1 (breq,_PC_+2) CR_TAB
1290 AS1 (brsh,_PC_+4) CR_TAB
1298 return AS1 (br%k1,%0);
1300 return (AS1 (br%j1,_PC_+2) CR_TAB
1303 return (AS1 (br%j1,_PC_+4) CR_TAB
1312 return AS1 (br%j1,%0);
1314 return (AS1 (br%k1,_PC_+2) CR_TAB
1317 return (AS1 (br%k1,_PC_+4) CR_TAB
1325 /* Predicate function for immediate operand which fits to byte (8bit) */
1328 byte_immediate_operand (op, mode)
1330 enum machine_mode mode ATTRIBUTE_UNUSED;
1332 return (GET_CODE (op) == CONST_INT
1333 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1336 /* Output all insn addresses and their sizes into the assembly language
1337 output file. This is helpful for debugging whether the length attributes
1338 in the md file are correct.
1339 Output insn cost for next insn. */
1342 final_prescan_insn (insn, operand, num_operands)
1343 rtx insn, *operand ATTRIBUTE_UNUSED;
1344 int num_operands ATTRIBUTE_UNUSED;
1346 int uid = INSN_UID (insn);
1348 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1350 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1351 INSN_ADDRESSES (uid),
1352 INSN_ADDRESSES (uid) - last_insn_address,
1353 rtx_cost (PATTERN (insn), INSN));
1355 last_insn_address = INSN_ADDRESSES (uid);
1357 if (TARGET_RTL_DUMP)
1359 fprintf (asm_out_file, "/*****************\n");
1360 print_rtl_single (asm_out_file, insn);
1361 fprintf (asm_out_file, "*****************/\n");
1365 /* Return 0 if undefined, 1 if always true or always false. */
1368 avr_simplify_comparision_p (mode, operator, x)
1369 enum machine_mode mode;
1373 unsigned int max = (mode == QImode ? 0xff :
1374 mode == HImode ? 0xffff :
1375 mode == SImode ? 0xffffffff : 0);
1376 if (max && operator && GET_CODE (x) == CONST_INT)
1378 if (unsigned_condition (operator) != operator)
1381 if (max != (INTVAL (x) & max)
1382 && INTVAL (x) != 0xff)
1389 /* Returns nonzero if REGNO is the number of a hard
1390 register in which function arguments are sometimes passed. */
1393 function_arg_regno_p(r)
1396 return (r >= 8 && r <= 25);
1399 /* Initializing the variable cum for the state at the beginning
1400 of the argument list. */
1403 init_cumulative_args (cum, fntype, libname, indirect)
1404 CUMULATIVE_ARGS *cum;
1407 int indirect ATTRIBUTE_UNUSED;
1410 cum->regno = FIRST_CUM_REG;
1413 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1414 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1415 != void_type_node));
1421 /* Returns the number of registers to allocate for a function argument. */
1424 avr_num_arg_regs (mode, type)
1425 enum machine_mode mode;
1430 if (mode == BLKmode)
1431 size = int_size_in_bytes (type);
1433 size = GET_MODE_SIZE (mode);
1435 /* Align all function arguments to start in even-numbered registers.
1436 Odd-sized arguments leave holes above them. */
1438 return (size + 1) & ~1;
1441 /* Controls whether a function argument is passed
1442 in a register, and which register. */
1445 function_arg (cum, mode, type, named)
1446 CUMULATIVE_ARGS *cum;
1447 enum machine_mode mode;
1449 int named ATTRIBUTE_UNUSED;
1451 int bytes = avr_num_arg_regs (mode, type);
1453 if (cum->nregs && bytes <= cum->nregs)
1454 return gen_rtx (REG, mode, cum->regno - bytes);
1459 /* Update the summarizer variable CUM to advance past an argument
1460 in the argument list. */
1463 function_arg_advance (cum, mode, type, named)
1464 CUMULATIVE_ARGS *cum; /* current arg information */
1465 enum machine_mode mode; /* current arg mode */
1466 tree type; /* type of the argument or 0 if lib support */
1467 int named ATTRIBUTE_UNUSED; /* whether or not the argument was named */
1469 int bytes = avr_num_arg_regs (mode, type);
1471 cum->nregs -= bytes;
1472 cum->regno -= bytes;
1474 if (cum->nregs <= 0)
1477 cum->regno = FIRST_CUM_REG;
1481 /***********************************************************************
1482 Functions for outputting various mov's for a various modes
1483 ************************************************************************/
1485 output_movqi (insn, operands, l)
1491 rtx dest = operands[0];
1492 rtx src = operands[1];
1500 if (register_operand (dest, QImode))
1502 if (register_operand (src, QImode)) /* mov r,r */
1504 if (test_hard_reg_class (STACK_REG, dest))
1505 return AS2 (out,%0,%1);
1506 else if (test_hard_reg_class (STACK_REG, src))
1507 return AS2 (in,%0,%1);
1509 return AS2 (mov,%0,%1);
1511 else if (CONSTANT_P (src))
1513 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1514 return AS2 (ldi,%0,lo8(%1));
1516 if (GET_CODE (src) == CONST_INT)
1518 if (src == const0_rtx) /* mov r,L */
1519 return AS1 (clr,%0);
1520 else if (src == const1_rtx)
1522 if (reg_was_0 (insn, dest))
1523 return AS1 (inc,%0 ; reg_was_0);
1526 return (AS1 (clr,%0) CR_TAB
1529 else if (src == constm1_rtx)
1531 /* Immediate constants -1 to any register */
1532 if (reg_was_0 (insn, dest))
1533 return AS1 (dec,%0 ; reg_was_0);
1536 return (AS1 (clr,%0) CR_TAB
1541 int bit_nr = exact_log2 (INTVAL (src));
1545 if (reg_was_0 (insn, dest))
1549 output_asm_insn ("set ; reg_was_0", operands);
1555 output_asm_insn ((AS1 (clr,%0) CR_TAB
1559 avr_output_bld (operands, bit_nr);
1566 /* Last resort, larger than loading from memory. */
1568 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1569 AS2 (ldi,r31,lo8(%1)) CR_TAB
1570 AS2 (mov,%0,r31) CR_TAB
1571 AS2 (mov,r31,__tmp_reg__));
1573 else if (GET_CODE (src) == MEM)
1574 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1576 else if (GET_CODE (dest) == MEM)
1578 const char *template;
1580 if (src == const0_rtx)
1581 operands[1] = zero_reg_rtx;
1583 template = out_movqi_mr_r (insn, operands, real_l);
1586 output_asm_insn (template, operands);
1595 output_movhi (insn, operands, l)
1601 rtx dest = operands[0];
1602 rtx src = operands[1];
1608 if (register_operand (dest, HImode))
1610 if (register_operand (src, HImode)) /* mov r,r */
1612 if (test_hard_reg_class (STACK_REG, dest))
1614 if (TARGET_TINY_STACK)
1617 return AS2 (out,__SP_L__,%A1);
1619 else if (TARGET_NO_INTERRUPTS)
1622 return (AS2 (out,__SP_H__,%B1) CR_TAB
1623 AS2 (out,__SP_L__,%A1));
1627 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1629 AS2 (out,__SP_H__,%B1) CR_TAB
1630 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1631 AS2 (out,__SP_L__,%A1));
1633 else if (test_hard_reg_class (STACK_REG, src))
1636 return (AS2 (in,%A0,__SP_L__) CR_TAB
1637 AS2 (in,%B0,__SP_H__));
1643 return (AS2 (movw,%0,%1));
1646 if (true_regnum (dest) > true_regnum (src))
1649 return (AS2 (mov,%B0,%B1) CR_TAB
1655 return (AS2 (mov,%A0,%A1) CR_TAB
1659 else if (CONSTANT_P (src))
1661 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1663 if (byte_immediate_operand (src, HImode)
1664 && reg_was_0 (insn, dest))
1667 return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0));
1671 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1672 AS2 (ldi,%B0,hi8(%1)));
1675 if (GET_CODE (src) == CONST_INT)
1677 if (src == const0_rtx) /* mov r,L */
1680 return (AS1 (clr,%A0) CR_TAB
1683 else if (src == const1_rtx)
1685 if (reg_was_0 (insn, dest))
1688 return AS1 (inc,%0 ; reg_was_0);
1692 return (AS1 (clr,%A0) CR_TAB
1693 AS1 (clr,%B0) CR_TAB
1696 else if (src == constm1_rtx)
1698 /* Immediate constants -1 to any register */
1699 if (reg_was_0 (insn, dest))
1702 return (AS1 (dec,%A0 ; reg_was_0) CR_TAB
1707 return (AS1 (clr,%0) CR_TAB
1708 AS1 (dec,%A0) CR_TAB
1713 int bit_nr = exact_log2 (INTVAL (src));
1717 if (reg_was_0 (insn, dest))
1721 output_asm_insn ("set ; reg_was_0", operands);
1727 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1728 AS1 (clr,%B0) CR_TAB
1732 avr_output_bld (operands, bit_nr);
1738 if ((INTVAL (src) & 0xff) == 0)
1741 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1742 AS1 (clr,%A0) CR_TAB
1743 AS2 (ldi,r31,hi8(%1)) CR_TAB
1744 AS2 (mov,%B0,r31) CR_TAB
1745 AS2 (mov,r31,__tmp_reg__));
1747 else if ((INTVAL (src) & 0xff00) == 0)
1750 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1751 AS2 (ldi,r31,lo8(%1)) CR_TAB
1752 AS2 (mov,%A0,r31) CR_TAB
1753 AS1 (clr,%B0) CR_TAB
1754 AS2 (mov,r31,__tmp_reg__));
1758 /* Last resort, equal to loading from memory. */
1760 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1761 AS2 (ldi,r31,lo8(%1)) CR_TAB
1762 AS2 (mov,%A0,r31) CR_TAB
1763 AS2 (ldi,r31,hi8(%1)) CR_TAB
1764 AS2 (mov,%B0,r31) CR_TAB
1765 AS2 (mov,r31,__tmp_reg__));
1767 else if (GET_CODE (src) == MEM)
1768 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1770 else if (GET_CODE (dest) == MEM)
1772 const char *template;
1774 if (src == const0_rtx)
1775 operands[1] = zero_reg_rtx;
1777 template = out_movhi_mr_r (insn, operands, real_l);
1780 output_asm_insn (template, operands);
1785 fatal_insn ("invalid insn:", insn);
1790 out_movqi_r_mr (insn, op, l)
1793 int *l; /* instruction length */
1797 rtx x = XEXP (src, 0);
1803 if (CONSTANT_ADDRESS_P (x))
1805 if (io_address_p (x, 1))
1808 return AS2 (in,%0,%1-0x20);
1811 return AS2 (lds,%0,%1);
1813 /* memory access by reg+disp */
1814 else if (GET_CODE (x) == PLUS
1815 && REG_P (XEXP (x,0))
1816 && GET_CODE (XEXP (x,1)) == CONST_INT)
1818 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
1820 int disp = INTVAL (XEXP (x,1));
1821 if (REGNO (XEXP (x,0)) != REG_Y)
1822 fatal_insn ("incorrect insn:",insn);
1824 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1825 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1826 AS2 (ldd,%0,Y+63) CR_TAB
1827 AS2 (sbiw,r28,%o1-63));
1829 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1830 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1831 AS2 (ld,%0,Y) CR_TAB
1832 AS2 (subi,r28,lo8(%o1)) CR_TAB
1833 AS2 (sbci,r29,hi8(%o1)));
1835 else if (REGNO (XEXP (x,0)) == REG_X)
1837 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1838 it but I have this situation with extremal optimizing options. */
1839 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
1840 || reg_unused_after (insn, XEXP (x,0)))
1841 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1844 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1845 AS2 (ld,%0,X) CR_TAB
1846 AS2 (sbiw,r26,%o1));
1849 return AS2 (ldd,%0,%1);
1852 return AS2 (ld,%0,%1);
1856 out_movhi_r_mr (insn, op, l)
1859 int *l; /* instruction length */
1863 rtx base = XEXP (src, 0);
1864 int reg_dest = true_regnum (dest);
1865 int reg_base = true_regnum (base);
1873 if (reg_dest == reg_base) /* R = (R) */
1876 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1877 AS2 (ld,%B0,%1) CR_TAB
1878 AS2 (mov,%A0,__tmp_reg__));
1880 else if (reg_base == REG_X) /* (R26) */
1882 if (reg_unused_after (insn, base))
1885 return (AS2 (ld,%A0,X+) CR_TAB
1889 return (AS2 (ld,%A0,X+) CR_TAB
1890 AS2 (ld,%B0,X) CR_TAB
1896 return (AS2 (ld,%A0,%1) CR_TAB
1897 AS2 (ldd,%B0,%1+1));
1900 else if (GET_CODE (base) == PLUS) /* (R + i) */
1902 int disp = INTVAL (XEXP (base, 1));
1903 int reg_base = true_regnum (XEXP (base, 0));
1905 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
1907 if (REGNO (XEXP (base, 0)) != REG_Y)
1908 fatal_insn ("incorrect insn:",insn);
1910 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1911 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
1912 AS2 (ldd,%A0,Y+62) CR_TAB
1913 AS2 (ldd,%B0,Y+63) CR_TAB
1914 AS2 (sbiw,r28,%o1-62));
1916 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1917 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1918 AS2 (ld,%A0,Y) CR_TAB
1919 AS2 (ldd,%B0,Y+1) CR_TAB
1920 AS2 (subi,r28,lo8(%o1)) CR_TAB
1921 AS2 (sbci,r29,hi8(%o1)));
1923 if (reg_base == REG_X)
1925 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1926 it but I have this situation with extremal
1927 optimization options. */
1930 if (reg_base == reg_dest)
1931 return (AS2 (adiw,r26,%o1) CR_TAB
1932 AS2 (ld,__tmp_reg__,X+) CR_TAB
1933 AS2 (ld,%B0,X) CR_TAB
1934 AS2 (mov,%A0,__tmp_reg__));
1936 return (AS2 (adiw,r26,%o1) CR_TAB
1937 AS2 (ld,%A0,X+) CR_TAB
1938 AS2 (ld,%B0,X) CR_TAB
1939 AS2 (sbiw,r26,%o1+1));
1942 if (reg_base == reg_dest)
1945 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
1946 AS2 (ldd,%B0,%B1) CR_TAB
1947 AS2 (mov,%A0,__tmp_reg__));
1951 return (AS2 (ldd,%A0,%A1) CR_TAB
1954 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
1956 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1957 fatal_insn ("incorrect insn:", insn);
1960 return (AS2 (ld,%B0,%1) CR_TAB
1963 else if (GET_CODE (base) == POST_INC) /* (R++) */
1965 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1966 fatal_insn ("incorrect insn:", insn);
1969 return (AS2 (ld,%A0,%1) CR_TAB
1972 else if (CONSTANT_ADDRESS_P (base))
1974 if (io_address_p (base, 2))
1977 return (AS2 (in,%A0,%A1-0x20) CR_TAB
1978 AS2 (in,%B0,%B1-0x20));
1981 return (AS2 (lds,%A0,%A1) CR_TAB
1985 fatal_insn ("unknown move insn:",insn);
1990 out_movsi_r_mr (insn, op, l)
1993 int *l; /* instruction length */
1997 rtx base = XEXP (src, 0);
1998 int reg_dest = true_regnum (dest);
1999 int reg_base = true_regnum (base);
2007 if (reg_base == REG_X) /* (R26) */
2009 if (reg_dest == REG_X)
2010 /* "ld r26,-X" is undefined */
2011 return *l=7, (AS2 (adiw,r26,3) CR_TAB
2012 AS2 (ld,r29,X) CR_TAB
2013 AS2 (ld,r28,-X) CR_TAB
2014 AS2 (ld,__tmp_reg__,-X) CR_TAB
2015 AS2 (sbiw,r26,1) CR_TAB
2016 AS2 (ld,r26,X) CR_TAB
2017 AS2 (mov,r27,__tmp_reg__));
2018 else if (reg_dest == REG_X - 2)
2019 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2020 AS2 (ld,%B0,X+) CR_TAB
2021 AS2 (ld,__tmp_reg__,X+) CR_TAB
2022 AS2 (ld,%D0,X) CR_TAB
2023 AS2 (mov,%C0,__tmp_reg__));
2024 else if (reg_unused_after (insn, base))
2025 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
2026 AS2 (ld,%B0,X+) CR_TAB
2027 AS2 (ld,%C0,X+) CR_TAB
2030 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2031 AS2 (ld,%B0,X+) CR_TAB
2032 AS2 (ld,%C0,X+) CR_TAB
2033 AS2 (ld,%D0,X) CR_TAB
2038 if (reg_dest == reg_base)
2039 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2040 AS2 (ldd,%C0,%1+2) CR_TAB
2041 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2042 AS2 (ld,%A0,%1) CR_TAB
2043 AS2 (mov,%B0,__tmp_reg__));
2044 else if (reg_base == reg_dest + 2)
2045 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2046 AS2 (ldd,%B0,%1+1) CR_TAB
2047 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2048 AS2 (ldd,%D0,%1+3) CR_TAB
2049 AS2 (mov,%C0,__tmp_reg__));
2051 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2052 AS2 (ldd,%B0,%1+1) CR_TAB
2053 AS2 (ldd,%C0,%1+2) CR_TAB
2054 AS2 (ldd,%D0,%1+3));
2057 else if (GET_CODE (base) == PLUS) /* (R + i) */
2059 int disp = INTVAL (XEXP (base, 1));
2061 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2063 if (REGNO (XEXP (base, 0)) != REG_Y)
2064 fatal_insn ("incorrect insn:",insn);
2066 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2067 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2068 AS2 (ldd,%A0,Y+60) CR_TAB
2069 AS2 (ldd,%B0,Y+61) CR_TAB
2070 AS2 (ldd,%C0,Y+62) CR_TAB
2071 AS2 (ldd,%D0,Y+63) CR_TAB
2072 AS2 (sbiw,r28,%o1-60));
2074 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2075 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2076 AS2 (ld,%A0,Y) CR_TAB
2077 AS2 (ldd,%B0,Y+1) CR_TAB
2078 AS2 (ldd,%C0,Y+2) CR_TAB
2079 AS2 (ldd,%D0,Y+3) CR_TAB
2080 AS2 (subi,r28,lo8(%o1)) CR_TAB
2081 AS2 (sbci,r29,hi8(%o1)));
2084 reg_base = true_regnum (XEXP (base, 0));
2085 if (reg_base == REG_X)
2088 if (reg_dest == REG_X)
2091 /* "ld r26,-X" is undefined */
2092 return (AS2 (adiw,r26,%o1+3) CR_TAB
2093 AS2 (ld,r29,X) CR_TAB
2094 AS2 (ld,r28,-X) CR_TAB
2095 AS2 (ld,__tmp_reg__,-X) CR_TAB
2096 AS2 (sbiw,r26,1) CR_TAB
2097 AS2 (ld,r26,X) CR_TAB
2098 AS2 (mov,r27,__tmp_reg__));
2101 if (reg_dest == REG_X - 2)
2102 return (AS2 (adiw,r26,%o1) CR_TAB
2103 AS2 (ld,r24,X+) CR_TAB
2104 AS2 (ld,r25,X+) CR_TAB
2105 AS2 (ld,__tmp_reg__,X+) CR_TAB
2106 AS2 (ld,r27,X) CR_TAB
2107 AS2 (mov,r26,__tmp_reg__));
2109 return (AS2 (adiw,r26,%o1) CR_TAB
2110 AS2 (ld,%A0,X+) CR_TAB
2111 AS2 (ld,%B0,X+) CR_TAB
2112 AS2 (ld,%C0,X+) CR_TAB
2113 AS2 (ld,%D0,X) CR_TAB
2114 AS2 (sbiw,r26,%o1+3));
2116 if (reg_dest == reg_base)
2117 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2118 AS2 (ldd,%C0,%C1) CR_TAB
2119 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2120 AS2 (ldd,%A0,%A1) CR_TAB
2121 AS2 (mov,%B0,__tmp_reg__));
2122 else if (reg_dest == reg_base - 2)
2123 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2124 AS2 (ldd,%B0,%B1) CR_TAB
2125 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2126 AS2 (ldd,%D0,%D1) CR_TAB
2127 AS2 (mov,%C0,__tmp_reg__));
2128 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2129 AS2 (ldd,%B0,%B1) CR_TAB
2130 AS2 (ldd,%C0,%C1) CR_TAB
2133 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2134 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2135 AS2 (ld,%C0,%1) CR_TAB
2136 AS2 (ld,%B0,%1) CR_TAB
2138 else if (GET_CODE (base) == POST_INC) /* (R++) */
2139 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2140 AS2 (ld,%B0,%1) CR_TAB
2141 AS2 (ld,%C0,%1) CR_TAB
2143 else if (CONSTANT_ADDRESS_P (base))
2144 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2145 AS2 (lds,%B0,%B1) CR_TAB
2146 AS2 (lds,%C0,%C1) CR_TAB
2149 fatal_insn ("unknown move insn:",insn);
2154 out_movsi_mr_r (insn, op, l)
2161 rtx base = XEXP (dest, 0);
2162 int reg_base = true_regnum (base);
2163 int reg_src = true_regnum (src);
2169 if (CONSTANT_ADDRESS_P (base))
2170 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2171 AS2 (sts,%B0,%B1) CR_TAB
2172 AS2 (sts,%C0,%C1) CR_TAB
2174 if (reg_base > 0) /* (r) */
2176 if (reg_base == REG_X) /* (R26) */
2178 if (reg_src == REG_X)
2180 /* "st X+,r26" is undefined */
2181 if (reg_unused_after (insn, base))
2182 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2183 AS2 (st,X,r26) CR_TAB
2184 AS2 (adiw,r26,1) CR_TAB
2185 AS2 (st,X+,__tmp_reg__) CR_TAB
2186 AS2 (st,X+,r28) CR_TAB
2189 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2190 AS2 (st,X,r26) CR_TAB
2191 AS2 (adiw,r26,1) CR_TAB
2192 AS2 (st,X+,__tmp_reg__) CR_TAB
2193 AS2 (st,X+,r28) CR_TAB
2194 AS2 (st,X,r29) CR_TAB
2197 else if (reg_base == reg_src + 2)
2199 if (reg_unused_after (insn, base))
2200 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2201 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2202 AS2 (st,%0+,%A1) CR_TAB
2203 AS2 (st,%0+,%B1) CR_TAB
2204 AS2 (st,%0+,__zero_reg__) CR_TAB
2205 AS2 (st,%0,__tmp_reg__) CR_TAB
2206 AS1 (clr,__zero_reg__));
2208 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2209 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2210 AS2 (st,%0+,%A1) CR_TAB
2211 AS2 (st,%0+,%B1) CR_TAB
2212 AS2 (st,%0+,__zero_reg__) CR_TAB
2213 AS2 (st,%0,__tmp_reg__) CR_TAB
2214 AS1 (clr,__zero_reg__) CR_TAB
2217 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2218 AS2 (st,%0+,%B1) CR_TAB
2219 AS2 (st,%0+,%C1) CR_TAB
2220 AS2 (st,%0,%D1) CR_TAB
2224 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2225 AS2 (std,%0+1,%B1) CR_TAB
2226 AS2 (std,%0+2,%C1) CR_TAB
2227 AS2 (std,%0+3,%D1));
2229 else if (GET_CODE (base) == PLUS) /* (R + i) */
2231 int disp = INTVAL (XEXP (base, 1));
2232 reg_base = REGNO (XEXP (base, 0));
2233 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2235 if (reg_base != REG_Y)
2236 fatal_insn ("incorrect insn:",insn);
2238 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2239 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2240 AS2 (std,Y+60,%A1) CR_TAB
2241 AS2 (std,Y+61,%B1) CR_TAB
2242 AS2 (std,Y+62,%C1) CR_TAB
2243 AS2 (std,Y+63,%D1) CR_TAB
2244 AS2 (sbiw,r28,%o0-60));
2246 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2247 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2248 AS2 (st,Y,%A1) CR_TAB
2249 AS2 (std,Y+1,%B1) CR_TAB
2250 AS2 (std,Y+2,%C1) CR_TAB
2251 AS2 (std,Y+3,%D1) CR_TAB
2252 AS2 (subi,r28,lo8(%o0)) CR_TAB
2253 AS2 (sbci,r29,hi8(%o0)));
2255 if (reg_base == REG_X)
2258 if (reg_src == REG_X)
2261 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2262 AS2 (mov,__zero_reg__,r27) CR_TAB
2263 AS2 (adiw,r26,%o0) CR_TAB
2264 AS2 (st,X+,__tmp_reg__) CR_TAB
2265 AS2 (st,X+,__zero_reg__) CR_TAB
2266 AS2 (st,X+,r28) CR_TAB
2267 AS2 (st,X,r29) CR_TAB
2268 AS1 (clr,__zero_reg__) CR_TAB
2269 AS2 (sbiw,r26,%o0+3));
2271 else if (reg_src == REG_X - 2)
2274 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2275 AS2 (mov,__zero_reg__,r27) CR_TAB
2276 AS2 (adiw,r26,%o0) CR_TAB
2277 AS2 (st,X+,r24) CR_TAB
2278 AS2 (st,X+,r25) CR_TAB
2279 AS2 (st,X+,__tmp_reg__) CR_TAB
2280 AS2 (st,X,__zero_reg__) CR_TAB
2281 AS1 (clr,__zero_reg__) CR_TAB
2282 AS2 (sbiw,r26,%o0+3));
2285 return (AS2 (adiw,r26,%o0) CR_TAB
2286 AS2 (st,X+,%A1) CR_TAB
2287 AS2 (st,X+,%B1) CR_TAB
2288 AS2 (st,X+,%C1) CR_TAB
2289 AS2 (st,X,%D1) CR_TAB
2290 AS2 (sbiw,r26,%o0+3));
2292 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2293 AS2 (std,%B0,%B1) CR_TAB
2294 AS2 (std,%C0,%C1) CR_TAB
2297 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2298 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2299 AS2 (st,%0,%C1) CR_TAB
2300 AS2 (st,%0,%B1) CR_TAB
2302 else if (GET_CODE (base) == POST_INC) /* (R++) */
2303 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2304 AS2 (st,%0,%B1) CR_TAB
2305 AS2 (st,%0,%C1) CR_TAB
2307 fatal_insn ("unknown move insn:",insn);
2312 output_movsisf(insn, operands, l)
2318 rtx dest = operands[0];
2319 rtx src = operands[1];
2325 if (register_operand (dest, VOIDmode))
2327 if (register_operand (src, VOIDmode)) /* mov r,r */
2329 if (true_regnum (dest) > true_regnum (src))
2334 return (AS2 (movw,%C0,%C1) CR_TAB
2335 AS2 (movw,%A0,%A1));
2338 return (AS2 (mov,%D0,%D1) CR_TAB
2339 AS2 (mov,%C0,%C1) CR_TAB
2340 AS2 (mov,%B0,%B1) CR_TAB
2348 return (AS2 (movw,%A0,%A1) CR_TAB
2349 AS2 (movw,%C0,%C1));
2352 return (AS2 (mov,%A0,%A1) CR_TAB
2353 AS2 (mov,%B0,%B1) CR_TAB
2354 AS2 (mov,%C0,%C1) CR_TAB
2358 else if (CONSTANT_P (src))
2360 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2362 if (byte_immediate_operand (src, SImode)
2363 && reg_was_0 (insn, dest))
2366 return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0));
2370 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2371 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2372 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2373 AS2 (ldi,%D0,hhi8(%1)));
2376 if (GET_CODE (src) == CONST_INT)
2378 const char *const clr_op0 =
2379 AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
2380 AS1 (clr,%B0) CR_TAB
2382 : (AS1 (clr,%A0) CR_TAB
2383 AS1 (clr,%B0) CR_TAB
2384 AS1 (clr,%C0) CR_TAB
2387 if (src == const0_rtx) /* mov r,L */
2389 *l = AVR_ENHANCED ? 3 : 4;
2392 else if (src == const1_rtx)
2394 if (reg_was_0 (insn, dest))
2397 return AS1 (inc,%A0 ; reg_was_0);
2400 output_asm_insn (clr_op0, operands);
2401 *l = AVR_ENHANCED ? 4 : 5;
2402 return AS1 (inc,%A0);
2404 else if (src == constm1_rtx)
2406 /* Immediate constants -1 to any register */
2407 if (reg_was_0 (insn, dest))
2412 return (AS1 (dec,%A0) CR_TAB
2413 AS1 (dec,%B0) CR_TAB
2414 AS2 (movw,%C0,%A0));
2417 return (AS1 (dec,%D0 ; reg_was_0) CR_TAB
2418 AS1 (dec,%C0) CR_TAB
2419 AS1 (dec,%B0) CR_TAB
2425 return (AS1 (clr,%A0) CR_TAB
2426 AS1 (dec,%A0) CR_TAB
2427 AS2 (mov,%B0,%A0) CR_TAB
2428 AS2 (movw,%C0,%A0));
2431 return (AS1 (clr,%A0) CR_TAB
2432 AS1 (dec,%A0) CR_TAB
2433 AS2 (mov,%B0,%A0) CR_TAB
2434 AS2 (mov,%C0,%A0) CR_TAB
2439 int bit_nr = exact_log2 (INTVAL (src));
2443 if (reg_was_0 (insn, dest))
2447 output_asm_insn ("set ; reg_was_0", operands);
2451 *l = AVR_ENHANCED ? 5 : 6;
2454 output_asm_insn (clr_op0, operands);
2455 output_asm_insn ("set", operands);
2459 avr_output_bld (operands, bit_nr);
2466 /* Last resort, better than loading from memory. */
2468 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2469 AS2 (ldi,r31,lo8(%1)) CR_TAB
2470 AS2 (mov,%A0,r31) CR_TAB
2471 AS2 (ldi,r31,hi8(%1)) CR_TAB
2472 AS2 (mov,%B0,r31) CR_TAB
2473 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2474 AS2 (mov,%C0,r31) CR_TAB
2475 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2476 AS2 (mov,%D0,r31) CR_TAB
2477 AS2 (mov,r31,__tmp_reg__));
2479 else if (GET_CODE (src) == MEM)
2480 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2482 else if (GET_CODE (dest) == MEM)
2484 const char *template;
2486 if (src == const0_rtx)
2487 operands[1] = zero_reg_rtx;
2489 template = out_movsi_mr_r (insn, operands, real_l);
2492 output_asm_insn (template, operands);
2497 fatal_insn ("invalid insn:", insn);
2502 out_movqi_mr_r (insn, op, l)
2505 int *l; /* instruction length */
2509 rtx x = XEXP (dest, 0);
2515 if (CONSTANT_ADDRESS_P (x))
2517 if (io_address_p (x, 1))
2520 return AS2 (out,%0-0x20,%1);
2523 return AS2 (sts,%0,%1);
2525 /* memory access by reg+disp */
2526 else if (GET_CODE (x) == PLUS
2527 && REG_P (XEXP (x,0))
2528 && GET_CODE (XEXP (x,1)) == CONST_INT)
2530 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
2532 int disp = INTVAL (XEXP (x,1));
2533 if (REGNO (XEXP (x,0)) != REG_Y)
2534 fatal_insn ("incorrect insn:",insn);
2536 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2537 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2538 AS2 (std,Y+63,%1) CR_TAB
2539 AS2 (sbiw,r28,%o0-63));
2541 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2542 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2543 AS2 (st,Y,%1) CR_TAB
2544 AS2 (subi,r28,lo8(%o0)) CR_TAB
2545 AS2 (sbci,r29,hi8(%o0)));
2547 else if (REGNO (XEXP (x,0)) == REG_X)
2549 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
2551 if (reg_unused_after (insn, XEXP (x,0)))
2552 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2553 AS2 (adiw,r26,%o0) CR_TAB
2554 AS2 (st,X,__tmp_reg__));
2556 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2557 AS2 (adiw,r26,%o0) CR_TAB
2558 AS2 (st,X,__tmp_reg__) CR_TAB
2559 AS2 (sbiw,r26,%o0));
2563 if (reg_unused_after (insn, XEXP (x,0)))
2564 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2567 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2568 AS2 (st,X,%1) CR_TAB
2569 AS2 (sbiw,r26,%o0));
2573 return AS2 (std,%0,%1);
2576 return AS2 (st,%0,%1);
2580 out_movhi_mr_r (insn, op, l)
2587 rtx base = XEXP (dest, 0);
2588 int reg_base = true_regnum (base);
2589 int reg_src = true_regnum (src);
2593 if (CONSTANT_ADDRESS_P (base))
2595 if (io_address_p (base, 2))
2598 return (AS2 (out,%B0-0x20,%B1) CR_TAB
2599 AS2 (out,%A0-0x20,%A1));
2601 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2606 if (reg_base == REG_X)
2608 if (reg_src == REG_X)
2610 /* "st X+,r26" is undefined */
2611 if (reg_unused_after (insn, src))
2612 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2613 AS2 (st,X,r26) CR_TAB
2614 AS2 (adiw,r26,1) CR_TAB
2615 AS2 (st,X,__tmp_reg__));
2617 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2618 AS2 (st,X,r26) CR_TAB
2619 AS2 (adiw,r26,1) CR_TAB
2620 AS2 (st,X,__tmp_reg__) CR_TAB
2625 if (reg_unused_after (insn, base))
2626 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2629 return *l=3, (AS2 (st ,X+,%A1) CR_TAB
2630 AS2 (st ,X,%B1) CR_TAB
2635 return *l=2, (AS2 (st ,%0,%A1) CR_TAB
2636 AS2 (std,%0+1,%B1));
2638 else if (GET_CODE (base) == PLUS)
2640 int disp = INTVAL (XEXP (base, 1));
2641 reg_base = REGNO (XEXP (base, 0));
2642 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2644 if (reg_base != REG_Y)
2645 fatal_insn ("incorrect insn:",insn);
2647 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2648 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
2649 AS2 (std,Y+62,%A1) CR_TAB
2650 AS2 (std,Y+63,%B1) CR_TAB
2651 AS2 (sbiw,r28,%o0-62));
2653 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2654 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2655 AS2 (st,Y,%A1) CR_TAB
2656 AS2 (std,Y+1,%B1) CR_TAB
2657 AS2 (subi,r28,lo8(%o0)) CR_TAB
2658 AS2 (sbci,r29,hi8(%o0)));
2660 if (reg_base == REG_X)
2663 if (reg_src == REG_X)
2666 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2667 AS2 (mov,__zero_reg__,r27) CR_TAB
2668 AS2 (adiw,r26,%o0) CR_TAB
2669 AS2 (st,X+,__tmp_reg__) CR_TAB
2670 AS2 (st,X,__zero_reg__) CR_TAB
2671 AS1 (clr,__zero_reg__) CR_TAB
2672 AS2 (sbiw,r26,%o0+1));
2675 return (AS2 (adiw,r26,%o0) CR_TAB
2676 AS2 (st,X+,%A1) CR_TAB
2677 AS2 (st,X,%B1) CR_TAB
2678 AS2 (sbiw,r26,%o0+1));
2680 return *l=2, (AS2 (std,%A0,%A1) CR_TAB
2683 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2684 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2686 else if (GET_CODE (base) == POST_INC) /* (R++) */
2687 return *l=2, (AS2 (st,%0,%A1) CR_TAB
2689 fatal_insn ("unknown move insn:",insn);
2693 /* Return 1 if frame pointer for current function required */
2696 frame_pointer_required_p ()
2698 return (current_function_calls_alloca
2699 || current_function_args_info.nregs == 0
2700 || current_function_varargs
2701 || get_frame_size () > 0);
2704 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2707 compare_condition (insn)
2710 rtx next = next_real_insn (insn);
2711 RTX_CODE cond = UNKNOWN;
2712 if (next && GET_CODE (next) == JUMP_INSN)
2714 rtx pat = PATTERN (next);
2715 rtx src = SET_SRC (pat);
2716 rtx t = XEXP (src, 0);
2717 cond = GET_CODE (t);
2722 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2725 compare_sign_p (insn)
2728 RTX_CODE cond = compare_condition (insn);
2729 return (cond == GE || cond == LT);
2732 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2733 that needs to be swapped (GT, GTU, LE, LEU). */
2736 compare_diff_p (insn)
2739 RTX_CODE cond = compare_condition (insn);
2740 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2743 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2749 RTX_CODE cond = compare_condition (insn);
2750 return (cond == EQ || cond == NE);
2754 /* Output test instruction for HImode */
2761 if (compare_sign_p (insn))
2764 return AS1 (tst,%B0);
2766 if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2767 && compare_eq_p (insn))
2769 /* faster than sbiw if we can clobber the operand */
2771 return AS2 (or,%A0,%B0);
2773 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2776 return AS2 (sbiw,%0,0);
2779 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2780 AS2 (cpc,%B0,__zero_reg__));
2784 /* Output test instruction for SImode */
2791 if (compare_sign_p (insn))
2794 return AS1 (tst,%D0);
2796 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2799 return (AS2 (sbiw,%A0,0) CR_TAB
2800 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2801 AS2 (cpc,%D0,__zero_reg__));
2804 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2805 AS2 (cpc,%B0,__zero_reg__) CR_TAB
2806 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2807 AS2 (cpc,%D0,__zero_reg__));
2811 /* Generate asm equivalent for various shifts.
2812 Shift count is a CONST_INT, MEM or REG.
2813 This only handles cases that are not already
2814 carefully hand-optimized in ?sh??i3_out. */
2817 out_shift_with_cnt (template, insn, operands, len, t_len)
2818 const char *template;
2822 int t_len; /* Length of template. */
2826 int second_label = 1;
2827 int saved_in_tmp = 0;
2828 int use_zero_reg = 0;
2830 op[0] = operands[0];
2831 op[1] = operands[1];
2832 op[2] = operands[2];
2833 op[3] = operands[3];
2839 if (GET_CODE (operands[2]) == CONST_INT)
2841 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2842 int count = INTVAL (operands[2]);
2843 int max_len = 10; /* If larger than this, always use a loop. */
2845 if (count < 8 && !scratch)
2849 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2851 if (t_len * count <= max_len)
2853 /* Output shifts inline with no loop - faster. */
2855 *len = t_len * count;
2859 output_asm_insn (template, op);
2868 strcat (str, AS2 (ldi,%3,%2));
2870 else if (use_zero_reg)
2872 /* Hack to save one word: use __zero_reg__ as loop counter.
2873 Set one bit, then shift in a loop until it is 0 again. */
2875 op[3] = zero_reg_rtx;
2879 strcat (str, ("set" CR_TAB
2880 AS2 (bld,%3,%2-1)));
2884 /* No scratch register available, use one from LD_REGS (saved in
2885 __tmp_reg__) that doesn't overlap with registers to shift. */
2887 op[3] = gen_rtx (REG, QImode,
2888 ((true_regnum (operands[0]) - 1) & 15) + 16);
2889 op[4] = tmp_reg_rtx;
2893 *len = 3; /* Includes "mov %3,%4" after the loop. */
2895 strcat (str, (AS2 (mov,%4,%3) CR_TAB
2901 else if (GET_CODE (operands[2]) == MEM)
2905 op[3] = op_mov[0] = tmp_reg_rtx;
2909 out_movqi_r_mr (insn, op_mov, len);
2911 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
2913 else if (register_operand (operands[2], QImode))
2915 if (reg_unused_after (insn, operands[2]))
2919 op[3] = tmp_reg_rtx;
2921 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
2925 fatal_insn ("bad shift insn:", insn);
2932 strcat (str, AS1 (rjmp,2f));
2936 *len += t_len + 2; /* template + dec + brXX */
2939 strcat (str, "\n1:\t");
2940 strcat (str, template);
2941 strcat (str, second_label ? "\n2:\t" : "\n\t");
2942 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
2943 strcat (str, CR_TAB);
2944 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
2946 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
2947 output_asm_insn (str, op);
2952 /* 8bit shift left ((char)x << i) */
2955 ashlqi3_out (insn, operands, len)
2958 int *len; /* insn length (may be NULL) */
2960 if (GET_CODE (operands[2]) == CONST_INT)
2967 switch (INTVAL (operands[2]))
2971 return AS1 (clr,%0);
2975 return AS1 (lsl,%0);
2979 return (AS1 (lsl,%0) CR_TAB
2984 return (AS1 (lsl,%0) CR_TAB
2989 if (test_hard_reg_class (LD_REGS, operands[0]))
2992 return (AS1 (swap,%0) CR_TAB
2993 AS2 (andi,%0,0xf0));
2996 return (AS1 (lsl,%0) CR_TAB
3002 if (test_hard_reg_class (LD_REGS, operands[0]))
3005 return (AS1 (swap,%0) CR_TAB
3007 AS2 (andi,%0,0xe0));
3010 return (AS1 (lsl,%0) CR_TAB
3017 if (test_hard_reg_class (LD_REGS, operands[0]))
3020 return (AS1 (swap,%0) CR_TAB
3023 AS2 (andi,%0,0xc0));
3026 return (AS1 (lsl,%0) CR_TAB
3035 return (AS1 (ror,%0) CR_TAB
3040 else if (CONSTANT_P (operands[2]))
3041 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3043 out_shift_with_cnt (AS1 (lsl,%0),
3044 insn, operands, len, 1);
3049 /* 16bit shift left ((short)x << i) */
3052 ashlhi3_out (insn, operands, len)
3057 if (GET_CODE (operands[2]) == CONST_INT)
3059 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3060 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3067 switch (INTVAL (operands[2]))
3070 if (optimize_size && scratch)
3075 return (AS1 (swap,%A0) CR_TAB
3076 AS1 (swap,%B0) CR_TAB
3077 AS2 (andi,%B0,0xf0) CR_TAB
3078 AS2 (eor,%B0,%A0) CR_TAB
3079 AS2 (andi,%A0,0xf0) CR_TAB
3085 return (AS1 (swap,%A0) CR_TAB
3086 AS1 (swap,%B0) CR_TAB
3087 AS2 (ldi,%3,0xf0) CR_TAB
3088 AS2 (and,%B0,%3) CR_TAB
3089 AS2 (eor,%B0,%A0) CR_TAB
3090 AS2 (and,%A0,%3) CR_TAB
3093 break; /* optimize_size ? 6 : 8 */
3097 break; /* scratch ? 5 : 6 */
3101 return (AS1 (lsl,%A0) CR_TAB
3102 AS1 (rol,%B0) CR_TAB
3103 AS1 (swap,%A0) CR_TAB
3104 AS1 (swap,%B0) CR_TAB
3105 AS2 (andi,%B0,0xf0) CR_TAB
3106 AS2 (eor,%B0,%A0) CR_TAB
3107 AS2 (andi,%A0,0xf0) CR_TAB
3113 return (AS1 (lsl,%A0) CR_TAB
3114 AS1 (rol,%B0) CR_TAB
3115 AS1 (swap,%A0) CR_TAB
3116 AS1 (swap,%B0) CR_TAB
3117 AS2 (ldi,%3,0xf0) CR_TAB
3118 AS2 (and,%B0,%3) CR_TAB
3119 AS2 (eor,%B0,%A0) CR_TAB
3120 AS2 (and,%A0,%3) CR_TAB
3127 break; /* scratch ? 5 : 6 */
3129 return (AS1 (clr,__tmp_reg__) CR_TAB
3130 AS1 (lsr,%B0) CR_TAB
3131 AS1 (ror,%A0) CR_TAB
3132 AS1 (ror,__tmp_reg__) CR_TAB
3133 AS1 (lsr,%B0) CR_TAB
3134 AS1 (ror,%A0) CR_TAB
3135 AS1 (ror,__tmp_reg__) CR_TAB
3136 AS2 (mov,%B0,%A0) CR_TAB
3137 AS2 (mov,%A0,__tmp_reg__));
3141 return (AS1 (lsr,%B0) CR_TAB
3142 AS2 (mov,%B0,%A0) CR_TAB
3143 AS1 (clr,%A0) CR_TAB
3144 AS1 (ror,%B0) CR_TAB
3148 if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
3149 return *len = 1, AS1 (clr,%A0);
3151 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3156 return (AS2 (mov,%B0,%A0) CR_TAB
3157 AS1 (clr,%A0) CR_TAB
3162 return (AS2 (mov,%B0,%A0) CR_TAB
3163 AS1 (clr,%A0) CR_TAB
3164 AS1 (lsl,%B0) CR_TAB
3169 return (AS2 (mov,%B0,%A0) CR_TAB
3170 AS1 (clr,%A0) CR_TAB
3171 AS1 (lsl,%B0) CR_TAB
3172 AS1 (lsl,%B0) CR_TAB
3179 return (AS2 (mov,%B0,%A0) CR_TAB
3180 AS1 (clr,%A0) CR_TAB
3181 AS1 (swap,%B0) CR_TAB
3182 AS2 (andi,%B0,0xf0));
3187 return (AS2 (mov,%B0,%A0) CR_TAB
3188 AS1 (clr,%A0) CR_TAB
3189 AS1 (swap,%B0) CR_TAB
3190 AS2 (ldi,%3,0xf0) CR_TAB
3194 return (AS2 (mov,%B0,%A0) CR_TAB
3195 AS1 (clr,%A0) CR_TAB
3196 AS1 (lsl,%B0) CR_TAB
3197 AS1 (lsl,%B0) CR_TAB
3198 AS1 (lsl,%B0) CR_TAB
3205 return (AS2 (mov,%B0,%A0) CR_TAB
3206 AS1 (clr,%A0) CR_TAB
3207 AS1 (swap,%B0) CR_TAB
3208 AS1 (lsl,%B0) CR_TAB
3209 AS2 (andi,%B0,0xe0));
3211 if (AVR_ENHANCED && scratch)
3214 return (AS2 (ldi,%3,0x20) CR_TAB
3215 AS2 (mul,%A0,%3) CR_TAB
3216 AS2 (mov,%B0,r0) CR_TAB
3217 AS1 (clr,%A0) CR_TAB
3218 AS1 (clr,__zero_reg__));
3220 if (optimize_size && scratch)
3225 return (AS2 (mov,%B0,%A0) CR_TAB
3226 AS1 (clr,%A0) CR_TAB
3227 AS1 (swap,%B0) CR_TAB
3228 AS1 (lsl,%B0) CR_TAB
3229 AS2 (ldi,%3,0xe0) CR_TAB
3235 return ("set" CR_TAB
3236 AS2 (bld,r1,5) CR_TAB
3237 AS2 (mul,%A0,r1) CR_TAB
3238 AS2 (mov,%B0,r0) CR_TAB
3239 AS1 (clr,%A0) CR_TAB
3240 AS1 (clr,__zero_reg__));
3243 return (AS2 (mov,%B0,%A0) CR_TAB
3244 AS1 (clr,%A0) CR_TAB
3245 AS1 (lsl,%B0) CR_TAB
3246 AS1 (lsl,%B0) CR_TAB
3247 AS1 (lsl,%B0) CR_TAB
3248 AS1 (lsl,%B0) CR_TAB
3252 if (AVR_ENHANCED && ldi_ok)
3255 return (AS2 (ldi,%B0,0x40) CR_TAB
3256 AS2 (mul,%A0,%B0) CR_TAB
3257 AS2 (mov,%B0,r0) CR_TAB
3258 AS1 (clr,%A0) CR_TAB
3259 AS1 (clr,__zero_reg__));
3261 if (AVR_ENHANCED && scratch)
3264 return (AS2 (ldi,%3,0x40) CR_TAB
3265 AS2 (mul,%A0,%3) CR_TAB
3266 AS2 (mov,%B0,r0) CR_TAB
3267 AS1 (clr,%A0) CR_TAB
3268 AS1 (clr,__zero_reg__));
3270 if (optimize_size && ldi_ok)
3273 return (AS2 (mov,%B0,%A0) CR_TAB
3274 AS2 (ldi,%A0,6) "\n1:\t"
3275 AS1 (lsl,%B0) CR_TAB
3276 AS1 (dec,%A0) CR_TAB
3279 if (optimize_size && scratch)
3282 return (AS1 (clr,%B0) CR_TAB
3283 AS1 (lsr,%A0) CR_TAB
3284 AS1 (ror,%B0) CR_TAB
3285 AS1 (lsr,%A0) CR_TAB
3286 AS1 (ror,%B0) CR_TAB
3291 return (AS1 (clr,%B0) CR_TAB
3292 AS1 (lsr,%A0) CR_TAB
3293 AS1 (ror,%B0) CR_TAB
3298 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3300 insn, operands, len, 2);
3305 /* 32bit shift left ((long)x << i) */
3308 ashlsi3_out (insn, operands, len)
3313 if (GET_CODE (operands[2]) == CONST_INT)
3321 switch (INTVAL (operands[2]))
3325 int reg0 = true_regnum (operands[0]);
3326 int reg1 = true_regnum (operands[1]);
3329 return (AS2 (mov,%D0,%C1) CR_TAB
3330 AS2 (mov,%C0,%B1) CR_TAB
3331 AS2 (mov,%B0,%A1) CR_TAB
3333 else if (reg0 + 1 == reg1)
3336 return AS1 (clr,%A0);
3339 return (AS1 (clr,%A0) CR_TAB
3340 AS2 (mov,%B0,%A1) CR_TAB
3341 AS2 (mov,%C0,%B1) CR_TAB
3347 int reg0 = true_regnum (operands[0]);
3348 int reg1 = true_regnum (operands[1]);
3350 if (AVR_ENHANCED && (reg0 + 2 != reg1))
3353 return (AS2 (movw,%C0,%A1) CR_TAB
3354 AS1 (clr,%B0) CR_TAB
3357 if (reg0 + 1 >= reg1)
3358 return (AS2 (mov,%D0,%B1) CR_TAB
3359 AS2 (mov,%C0,%A1) CR_TAB
3360 AS1 (clr,%B0) CR_TAB
3362 if (reg0 + 2 == reg1)
3365 return (AS1 (clr,%B0) CR_TAB
3369 return (AS2 (mov,%C0,%A1) CR_TAB
3370 AS2 (mov,%D0,%B1) CR_TAB
3371 AS1 (clr,%B0) CR_TAB
3377 if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
3378 return (AS2 (mov,%D0,%A1) CR_TAB
3379 AS1 (clr,%C0) CR_TAB
3380 AS1 (clr,%B0) CR_TAB
3385 return (AS1 (clr,%C0) CR_TAB
3386 AS1 (clr,%B0) CR_TAB
3392 return (AS1 (clr,%D0) CR_TAB
3393 AS1 (lsr,%A0) CR_TAB
3394 AS1 (ror,%D0) CR_TAB
3395 AS1 (clr,%C0) CR_TAB
3396 AS1 (clr,%B0) CR_TAB
3401 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3402 AS1 (rol,%B0) CR_TAB
3403 AS1 (rol,%C0) CR_TAB
3405 insn, operands, len, 4);
3409 /* 8bit arithmetic shift right ((signed char)x >> i) */
3412 ashrqi3_out (insn, operands, len)
3415 int *len; /* insn length */
3417 if (GET_CODE (operands[2]) == CONST_INT)
3424 switch (INTVAL (operands[2]))
3428 return AS1 (asr,%0);
3432 return (AS1 (asr,%0) CR_TAB
3437 return (AS1 (asr,%0) CR_TAB
3443 return (AS1 (asr,%0) CR_TAB
3450 return (AS1 (asr,%0) CR_TAB
3458 return (AS2 (bst,%0,6) CR_TAB
3460 AS2 (sbc,%0,%0) CR_TAB
3466 return (AS1 (lsl,%0) CR_TAB
3470 else if (CONSTANT_P (operands[2]))
3471 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3473 out_shift_with_cnt (AS1 (asr,%0),
3474 insn, operands, len, 1);
3479 /* 16bit arithmetic shift right ((signed short)x >> i) */
3482 ashrhi3_out (insn, operands, len)
3487 if (GET_CODE (operands[2]) == CONST_INT)
3489 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3490 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3497 switch (INTVAL (operands[2]))
3501 /* XXX try to optimize this too? */
3506 break; /* scratch ? 5 : 6 */
3508 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3509 AS2 (mov,%A0,%B0) CR_TAB
3510 AS1 (lsl,__tmp_reg__) CR_TAB
3511 AS1 (rol,%A0) CR_TAB
3512 AS2 (sbc,%B0,%B0) CR_TAB
3513 AS1 (lsl,__tmp_reg__) CR_TAB
3514 AS1 (rol,%A0) CR_TAB
3519 return (AS1 (lsl,%A0) CR_TAB
3520 AS2 (mov,%A0,%B0) CR_TAB
3521 AS1 (rol,%A0) CR_TAB
3526 int reg0 = true_regnum (operands[0]);
3527 int reg1 = true_regnum (operands[1]);
3530 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3531 AS1 (lsl,%B0) CR_TAB
3533 else if (reg0 == reg1 + 1)
3534 return *len = 3, (AS1 (clr,%B0) CR_TAB
3535 AS2 (sbrc,%A0,7) CR_TAB
3538 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3539 AS1 (clr,%B0) CR_TAB
3540 AS2 (sbrc,%A0,7) CR_TAB
3546 return (AS2 (mov,%A0,%B0) CR_TAB
3547 AS1 (lsl,%B0) CR_TAB
3548 AS2 (sbc,%B0,%B0) CR_TAB
3553 return (AS2 (mov,%A0,%B0) CR_TAB
3554 AS1 (lsl,%B0) CR_TAB
3555 AS2 (sbc,%B0,%B0) CR_TAB
3556 AS1 (asr,%A0) CR_TAB
3560 if (AVR_ENHANCED && ldi_ok)
3563 return (AS2 (ldi,%A0,0x20) CR_TAB
3564 AS2 (muls,%B0,%A0) CR_TAB
3565 AS2 (mov,%A0,r1) CR_TAB
3566 AS2 (sbc,%B0,%B0) CR_TAB
3567 AS1 (clr,__zero_reg__));
3569 if (optimize_size && scratch)
3572 return (AS2 (mov,%A0,%B0) CR_TAB
3573 AS1 (lsl,%B0) CR_TAB
3574 AS2 (sbc,%B0,%B0) CR_TAB
3575 AS1 (asr,%A0) CR_TAB
3576 AS1 (asr,%A0) CR_TAB
3580 if (AVR_ENHANCED && ldi_ok)
3583 return (AS2 (ldi,%A0,0x10) CR_TAB
3584 AS2 (muls,%B0,%A0) CR_TAB
3585 AS2 (mov,%A0,r1) CR_TAB
3586 AS2 (sbc,%B0,%B0) CR_TAB
3587 AS1 (clr,__zero_reg__));
3589 if (optimize_size && scratch)
3592 return (AS2 (mov,%A0,%B0) CR_TAB
3593 AS1 (lsl,%B0) CR_TAB
3594 AS2 (sbc,%B0,%B0) CR_TAB
3595 AS1 (asr,%A0) CR_TAB
3596 AS1 (asr,%A0) CR_TAB
3597 AS1 (asr,%A0) CR_TAB
3601 if (AVR_ENHANCED && ldi_ok)
3604 return (AS2 (ldi,%A0,0x08) CR_TAB
3605 AS2 (muls,%B0,%A0) CR_TAB
3606 AS2 (mov,%A0,r1) CR_TAB
3607 AS2 (sbc,%B0,%B0) CR_TAB
3608 AS1 (clr,__zero_reg__));
3611 break; /* scratch ? 5 : 7 */
3613 return (AS2 (mov,%A0,%B0) CR_TAB
3614 AS1 (lsl,%B0) CR_TAB
3615 AS2 (sbc,%B0,%B0) CR_TAB
3616 AS1 (asr,%A0) CR_TAB
3617 AS1 (asr,%A0) CR_TAB
3618 AS1 (asr,%A0) CR_TAB
3619 AS1 (asr,%A0) CR_TAB
3624 return (AS1 (lsl,%B0) CR_TAB
3625 AS2 (sbc,%A0,%A0) CR_TAB
3626 AS1 (lsl,%B0) CR_TAB
3627 AS2 (mov,%B0,%A0) CR_TAB
3631 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3632 AS2 (sbc,%A0,%A0) CR_TAB
3637 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3639 insn, operands, len, 2);
3644 /* 32bit arithmetic shift right ((signed long)x >> i) */
3647 ashrsi3_out (insn, operands, len)
3652 if (GET_CODE (operands[2]) == CONST_INT)
3660 switch (INTVAL (operands[2]))
3664 int reg0 = true_regnum (operands[0]);
3665 int reg1 = true_regnum (operands[1]);
3668 return (AS2 (mov,%A0,%B1) CR_TAB
3669 AS2 (mov,%B0,%C1) CR_TAB
3670 AS2 (mov,%C0,%D1) CR_TAB
3671 AS1 (clr,%D0) CR_TAB
3672 AS2 (sbrc,%C0,7) CR_TAB
3674 else if (reg0 == reg1 + 1)
3677 return (AS1 (clr,%D0) CR_TAB
3678 AS2 (sbrc,%C0,7) CR_TAB
3682 return (AS1 (clr,%D0) CR_TAB
3683 AS2 (sbrc,%D1,7) CR_TAB
3684 AS1 (dec,%D0) CR_TAB
3685 AS2 (mov,%C0,%D1) CR_TAB
3686 AS2 (mov,%B0,%C1) CR_TAB
3692 int reg0 = true_regnum (operands[0]);
3693 int reg1 = true_regnum (operands[1]);
3695 if (AVR_ENHANCED && (reg0 != reg1 + 2))
3698 return (AS2 (movw,%A0,%C1) CR_TAB
3699 AS1 (clr,%D0) CR_TAB
3700 AS2 (sbrc,%B0,7) CR_TAB
3701 AS1 (com,%D0) CR_TAB
3704 if (reg0 <= reg1 + 1)
3705 return (AS2 (mov,%A0,%C1) CR_TAB
3706 AS2 (mov,%B0,%D1) CR_TAB
3707 AS1 (clr,%D0) CR_TAB
3708 AS2 (sbrc,%B0,7) CR_TAB
3709 AS1 (com,%D0) CR_TAB
3711 else if (reg0 == reg1 + 2)
3712 return *len = 4, (AS1 (clr,%D0) CR_TAB
3713 AS2 (sbrc,%B0,7) CR_TAB
3714 AS1 (com,%D0) CR_TAB
3717 return (AS2 (mov,%B0,%D1) CR_TAB
3718 AS2 (mov,%A0,%C1) CR_TAB
3719 AS1 (clr,%D0) CR_TAB
3720 AS2 (sbrc,%B0,7) CR_TAB
3721 AS1 (com,%D0) CR_TAB
3726 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
3727 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3728 AS1 (clr,%D0) CR_TAB
3729 AS2 (sbrc,%A0,7) CR_TAB
3730 AS1 (com,%D0) CR_TAB
3731 AS2 (mov,%B0,%D0) CR_TAB
3734 return *len = 5, (AS1 (clr,%D0) CR_TAB
3735 AS2 (sbrc,%A0,7) CR_TAB
3736 AS1 (com,%D0) CR_TAB
3737 AS2 (mov,%B0,%D0) CR_TAB
3742 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3743 AS2 (sbc,%A0,%A0) CR_TAB
3744 AS2 (mov,%B0,%A0) CR_TAB
3745 AS2 (movw,%C0,%A0));
3747 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3748 AS2 (sbc,%A0,%A0) CR_TAB
3749 AS2 (mov,%B0,%A0) CR_TAB
3750 AS2 (mov,%C0,%A0) CR_TAB
3755 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3756 AS1 (ror,%C0) CR_TAB
3757 AS1 (ror,%B0) CR_TAB
3759 insn, operands, len, 4);
3763 /* 8bit logic shift right ((unsigned char)x >> i) */
3766 lshrqi3_out (insn, operands, len)
3771 if (GET_CODE (operands[2]) == CONST_INT)
3778 switch (INTVAL (operands[2]))
3782 return AS1 (clr,%0);
3786 return AS1 (lsr,%0);
3790 return (AS1 (lsr,%0) CR_TAB
3794 return (AS1 (lsr,%0) CR_TAB
3799 if (test_hard_reg_class (LD_REGS, operands[0]))
3802 return (AS1 (swap,%0) CR_TAB
3803 AS2 (andi,%0,0x0f));
3806 return (AS1 (lsr,%0) CR_TAB
3812 if (test_hard_reg_class (LD_REGS, operands[0]))
3815 return (AS1 (swap,%0) CR_TAB
3820 return (AS1 (lsr,%0) CR_TAB
3827 if (test_hard_reg_class (LD_REGS, operands[0]))
3830 return (AS1 (swap,%0) CR_TAB
3836 return (AS1 (lsr,%0) CR_TAB
3845 return (AS1 (rol,%0) CR_TAB
3850 else if (CONSTANT_P (operands[2]))
3851 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3853 out_shift_with_cnt (AS1 (lsr,%0),
3854 insn, operands, len, 1);
3858 /* 16bit logic shift right ((unsigned short)x >> i) */
3861 lshrhi3_out (insn, operands, len)
3866 if (GET_CODE (operands[2]) == CONST_INT)
3868 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3869 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3876 switch (INTVAL (operands[2]))
3879 if (optimize_size && scratch)
3884 return (AS1 (swap,%B0) CR_TAB
3885 AS1 (swap,%A0) CR_TAB
3886 AS2 (andi,%A0,0x0f) CR_TAB
3887 AS2 (eor,%A0,%B0) CR_TAB
3888 AS2 (andi,%B0,0x0f) CR_TAB
3894 return (AS1 (swap,%B0) CR_TAB
3895 AS1 (swap,%A0) CR_TAB
3896 AS2 (ldi,%3,0x0f) CR_TAB
3897 AS2 (and,%A0,%3) CR_TAB
3898 AS2 (eor,%A0,%B0) CR_TAB
3899 AS2 (and,%B0,%3) CR_TAB
3902 break; /* optimize_size ? 6 : 8 */
3906 break; /* scratch ? 5 : 6 */
3910 return (AS1 (lsr,%B0) CR_TAB
3911 AS1 (ror,%A0) CR_TAB
3912 AS1 (swap,%B0) CR_TAB
3913 AS1 (swap,%A0) CR_TAB
3914 AS2 (andi,%A0,0x0f) CR_TAB
3915 AS2 (eor,%A0,%B0) CR_TAB
3916 AS2 (andi,%B0,0x0f) CR_TAB
3922 return (AS1 (lsr,%B0) CR_TAB
3923 AS1 (ror,%A0) CR_TAB
3924 AS1 (swap,%B0) CR_TAB
3925 AS1 (swap,%A0) CR_TAB
3926 AS2 (ldi,%3,0x0f) CR_TAB
3927 AS2 (and,%A0,%3) CR_TAB
3928 AS2 (eor,%A0,%B0) CR_TAB
3929 AS2 (and,%B0,%3) CR_TAB
3936 break; /* scratch ? 5 : 6 */
3938 return (AS1 (clr,__tmp_reg__) CR_TAB
3939 AS1 (lsl,%A0) CR_TAB
3940 AS1 (rol,%B0) CR_TAB
3941 AS1 (rol,__tmp_reg__) CR_TAB
3942 AS1 (lsl,%A0) CR_TAB
3943 AS1 (rol,%B0) CR_TAB
3944 AS1 (rol,__tmp_reg__) CR_TAB
3945 AS2 (mov,%A0,%B0) CR_TAB
3946 AS2 (mov,%B0,__tmp_reg__));
3950 return (AS1 (lsl,%A0) CR_TAB
3951 AS2 (mov,%A0,%B0) CR_TAB
3952 AS1 (rol,%A0) CR_TAB
3953 AS2 (sbc,%B0,%B0) CR_TAB
3957 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
3958 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
3961 return *len = 1, AS1 (clr,%B0);
3965 return (AS2 (mov,%A0,%B0) CR_TAB
3966 AS1 (clr,%B0) CR_TAB
3971 return (AS2 (mov,%A0,%B0) CR_TAB
3972 AS1 (clr,%B0) CR_TAB
3973 AS1 (lsr,%A0) CR_TAB
3978 return (AS2 (mov,%A0,%B0) CR_TAB
3979 AS1 (clr,%B0) CR_TAB
3980 AS1 (lsr,%A0) CR_TAB
3981 AS1 (lsr,%A0) CR_TAB
3988 return (AS2 (mov,%A0,%B0) CR_TAB
3989 AS1 (clr,%B0) CR_TAB
3990 AS1 (swap,%A0) CR_TAB
3991 AS2 (andi,%A0,0x0f));
3996 return (AS2 (mov,%A0,%B0) CR_TAB
3997 AS1 (clr,%B0) CR_TAB
3998 AS1 (swap,%A0) CR_TAB
3999 AS2 (ldi,%3,0x0f) CR_TAB
4003 return (AS2 (mov,%A0,%B0) CR_TAB
4004 AS1 (clr,%B0) CR_TAB
4005 AS1 (lsr,%A0) CR_TAB
4006 AS1 (lsr,%A0) CR_TAB
4007 AS1 (lsr,%A0) CR_TAB
4014 return (AS2 (mov,%A0,%B0) CR_TAB
4015 AS1 (clr,%B0) CR_TAB
4016 AS1 (swap,%A0) CR_TAB
4017 AS1 (lsr,%A0) CR_TAB
4018 AS2 (andi,%A0,0x07));
4020 if (AVR_ENHANCED && scratch)
4023 return (AS2 (ldi,%3,0x08) CR_TAB
4024 AS2 (mul,%B0,%3) CR_TAB
4025 AS2 (mov,%A0,r1) CR_TAB
4026 AS1 (clr,%B0) CR_TAB
4027 AS1 (clr,__zero_reg__));
4029 if (optimize_size && scratch)
4034 return (AS2 (mov,%A0,%B0) CR_TAB
4035 AS1 (clr,%B0) CR_TAB
4036 AS1 (swap,%A0) CR_TAB
4037 AS1 (lsr,%A0) CR_TAB
4038 AS2 (ldi,%3,0x07) CR_TAB
4044 return ("set" CR_TAB
4045 AS2 (bld,r1,3) CR_TAB
4046 AS2 (mul,%B0,r1) CR_TAB
4047 AS2 (mov,%A0,r1) CR_TAB
4048 AS1 (clr,%B0) CR_TAB
4049 AS1 (clr,__zero_reg__));
4052 return (AS2 (mov,%A0,%B0) CR_TAB
4053 AS1 (clr,%B0) CR_TAB
4054 AS1 (lsr,%A0) CR_TAB
4055 AS1 (lsr,%A0) CR_TAB
4056 AS1 (lsr,%A0) CR_TAB
4057 AS1 (lsr,%A0) CR_TAB
4061 if (AVR_ENHANCED && ldi_ok)
4064 return (AS2 (ldi,%A0,0x04) CR_TAB
4065 AS2 (mul,%B0,%A0) CR_TAB
4066 AS2 (mov,%A0,r1) CR_TAB
4067 AS1 (clr,%B0) CR_TAB
4068 AS1 (clr,__zero_reg__));
4070 if (AVR_ENHANCED && scratch)
4073 return (AS2 (ldi,%3,0x04) CR_TAB
4074 AS2 (mul,%B0,%3) CR_TAB
4075 AS2 (mov,%A0,r1) CR_TAB
4076 AS1 (clr,%B0) CR_TAB
4077 AS1 (clr,__zero_reg__));
4079 if (optimize_size && ldi_ok)
4082 return (AS2 (mov,%A0,%B0) CR_TAB
4083 AS2 (ldi,%B0,6) "\n1:\t"
4084 AS1 (lsr,%A0) CR_TAB
4085 AS1 (dec,%B0) CR_TAB
4088 if (optimize_size && scratch)
4091 return (AS1 (clr,%A0) CR_TAB
4092 AS1 (lsl,%B0) CR_TAB
4093 AS1 (rol,%A0) CR_TAB
4094 AS1 (lsl,%B0) CR_TAB
4095 AS1 (rol,%A0) CR_TAB
4100 return (AS1 (clr,%A0) CR_TAB
4101 AS1 (lsl,%B0) CR_TAB
4102 AS1 (rol,%A0) CR_TAB
4107 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4109 insn, operands, len, 2);
4113 /* 32bit logic shift right ((unsigned int)x >> i) */
4116 lshrsi3_out (insn, operands, len)
4121 if (GET_CODE (operands[2]) == CONST_INT)
4129 switch (INTVAL (operands[2]))
4133 int reg0 = true_regnum (operands[0]);
4134 int reg1 = true_regnum (operands[1]);
4137 return (AS2 (mov,%A0,%B1) CR_TAB
4138 AS2 (mov,%B0,%C1) CR_TAB
4139 AS2 (mov,%C0,%D1) CR_TAB
4141 else if (reg0 == reg1 + 1)
4142 return *len = 1, AS1 (clr,%D0);
4144 return (AS1 (clr,%D0) CR_TAB
4145 AS2 (mov,%C0,%D1) CR_TAB
4146 AS2 (mov,%B0,%C1) CR_TAB
4152 int reg0 = true_regnum (operands[0]);
4153 int reg1 = true_regnum (operands[1]);
4155 if (AVR_ENHANCED && (reg0 != reg1 + 2))
4158 return (AS2 (movw,%A0,%C1) CR_TAB
4159 AS1 (clr,%C0) CR_TAB
4162 if (reg0 <= reg1 + 1)
4163 return (AS2 (mov,%A0,%C1) CR_TAB
4164 AS2 (mov,%B0,%D1) CR_TAB
4165 AS1 (clr,%C0) CR_TAB
4167 else if (reg0 == reg1 + 2)
4168 return *len = 2, (AS1 (clr,%C0) CR_TAB
4171 return (AS2 (mov,%B0,%D1) CR_TAB
4172 AS2 (mov,%A0,%C1) CR_TAB
4173 AS1 (clr,%C0) CR_TAB
4178 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
4179 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4180 AS1 (clr,%B0) CR_TAB
4181 AS1 (clr,%C0) CR_TAB
4184 return *len = 3, (AS1 (clr,%B0) CR_TAB
4185 AS1 (clr,%C0) CR_TAB
4190 return (AS1 (clr,%A0) CR_TAB
4191 AS2 (sbrc,%D0,7) CR_TAB
4192 AS1 (inc,%A0) CR_TAB
4193 AS1 (clr,%B0) CR_TAB
4194 AS1 (clr,%C0) CR_TAB
4199 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4200 AS1 (ror,%C0) CR_TAB
4201 AS1 (ror,%B0) CR_TAB
4203 insn, operands, len, 4);
4207 /* Modifies the length assigned to instruction INSN
4208 LEN is the initially computed length of the insn. */
4211 adjust_insn_length (insn, len)
4215 rtx patt = PATTERN (insn);
4218 if (GET_CODE (patt) == SET)
4221 op[1] = SET_SRC (patt);
4222 op[0] = SET_DEST (patt);
4223 if (general_operand (op[1], VOIDmode)
4224 && general_operand (op[0], VOIDmode))
4226 switch (GET_MODE (op[0]))
4229 output_movqi (insn, op, &len);
4232 output_movhi (insn, op, &len);
4236 output_movsisf (insn, op, &len);
4242 else if (op[0] == cc0_rtx && REG_P (op[1]))
4244 switch (GET_MODE (op[1]))
4246 case HImode: out_tsthi (insn,&len); break;
4247 case SImode: out_tstsi (insn,&len); break;
4251 else if (GET_CODE (op[1]) == AND)
4253 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4255 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4256 if (GET_MODE (op[1]) == SImode)
4257 len = (((mask & 0xff) != 0xff)
4258 + ((mask & 0xff00) != 0xff00)
4259 + ((mask & 0xff0000L) != 0xff0000L)
4260 + ((mask & 0xff000000L) != 0xff000000L));
4261 else if (GET_MODE (op[1]) == HImode)
4262 len = (((mask & 0xff) != 0xff)
4263 + ((mask & 0xff00) != 0xff00));
4266 else if (GET_CODE (op[1]) == IOR)
4268 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4270 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4271 if (GET_MODE (op[1]) == SImode)
4272 len = (((mask & 0xff) != 0)
4273 + ((mask & 0xff00) != 0)
4274 + ((mask & 0xff0000L) != 0)
4275 + ((mask & 0xff000000L) != 0));
4276 else if (GET_MODE (op[1]) == HImode)
4277 len = (((mask & 0xff) != 0)
4278 + ((mask & 0xff00) != 0));
4282 set = single_set (insn);
4287 op[1] = SET_SRC (set);
4288 op[0] = SET_DEST (set);
4290 if (GET_CODE (patt) == PARALLEL
4291 && general_operand (op[1], VOIDmode)
4292 && general_operand (op[0], VOIDmode))
4294 if (XVECLEN (patt, 0) == 2)
4295 op[2] = XVECEXP (patt, 0, 1);
4297 switch (GET_MODE (op[0]))
4303 output_reload_inhi (insn, op, &len);
4307 output_reload_insisf (insn, op, &len);
4313 else if (GET_CODE (op[1]) == ASHIFT
4314 || GET_CODE (op[1]) == ASHIFTRT
4315 || GET_CODE (op[1]) == LSHIFTRT)
4319 ops[1] = XEXP (op[1],0);
4320 ops[2] = XEXP (op[1],1);
4321 switch (GET_CODE (op[1]))
4324 switch (GET_MODE (op[0]))
4326 case QImode: ashlqi3_out (insn,ops,&len); break;
4327 case HImode: ashlhi3_out (insn,ops,&len); break;
4328 case SImode: ashlsi3_out (insn,ops,&len); break;
4333 switch (GET_MODE (op[0]))
4335 case QImode: ashrqi3_out (insn,ops,&len); break;
4336 case HImode: ashrhi3_out (insn,ops,&len); break;
4337 case SImode: ashrsi3_out (insn,ops,&len); break;
4342 switch (GET_MODE (op[0]))
4344 case QImode: lshrqi3_out (insn,ops,&len); break;
4345 case HImode: lshrhi3_out (insn,ops,&len); break;
4346 case SImode: lshrsi3_out (insn,ops,&len); break;
4358 /* Return non-zero if register REG dead after INSN */
4361 reg_unused_after (insn, reg)
4365 return (dead_or_set_p (insn, reg)
4366 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4369 /* Return non-zero if REG is not used after INSN.
4370 We assume REG is a reload reg, and therefore does
4371 not live past labels. It may live past calls or jumps though. */
4374 _reg_unused_after (insn, reg)
4381 /* If the reg is set by this instruction, then it is safe for our
4382 case. Disregard the case where this is a store to memory, since
4383 we are checking a register used in the store address. */
4384 set = single_set (insn);
4385 if (set && GET_CODE (SET_DEST (set)) != MEM
4386 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4389 while ((insn = NEXT_INSN (insn)))
4391 code = GET_CODE (insn);
4394 /* If this is a label that existed before reload, then the register
4395 if dead here. However, if this is a label added by reorg, then
4396 the register may still be live here. We can't tell the difference,
4397 so we just ignore labels completely. */
4398 if (code == CODE_LABEL)
4403 if (code == JUMP_INSN)
4406 /* If this is a sequence, we must handle them all at once.
4407 We could have for instance a call that sets the target register,
4408 and an insn in a delay slot that uses the register. In this case,
4409 we must return 0. */
4410 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4415 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4417 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4418 rtx set = single_set (this_insn);
4420 if (GET_CODE (this_insn) == CALL_INSN)
4422 else if (GET_CODE (this_insn) == JUMP_INSN)
4424 if (INSN_ANNULLED_BRANCH_P (this_insn))
4429 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4431 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4433 if (GET_CODE (SET_DEST (set)) != MEM)
4439 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4444 else if (code == JUMP_INSN)
4448 if (code == CALL_INSN)
4451 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4452 if (GET_CODE (XEXP (tem, 0)) == USE
4453 && REG_P (XEXP (XEXP (tem, 0), 0))
4454 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4456 if (call_used_regs[REGNO (reg)])
4460 if (GET_RTX_CLASS (code) == 'i')
4462 rtx set = single_set (insn);
4464 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4466 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4467 return GET_CODE (SET_DEST (set)) != MEM;
4468 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4475 /* Target hook for assembling integer objects. The AVR version needs
4476 special handling for references to certain labels. */
4479 avr_assemble_integer (x, size, aligned_p)
4484 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
4485 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x))
4486 || GET_CODE (x) == LABEL_REF))
4488 fputs ("\t.word\tpm(", asm_out_file);
4489 output_addr_const (asm_out_file, x);
4490 fputs (")\n", asm_out_file);
4493 return default_assemble_integer (x, size, aligned_p);
4496 /* Sets section name for declaration DECL */
4499 unique_section (decl, reloc)
4501 int reloc ATTRIBUTE_UNUSED;
4504 const char *name, *prefix;
4506 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
4507 /* Strip off any encoding in name. */
4508 STRIP_NAME_ENCODING (name, name);
4510 if (TREE_CODE (decl) == FUNCTION_DECL)
4512 if (flag_function_sections)
4520 if (flag_function_sections)
4522 len = strlen (name) + strlen (prefix);
4523 string = alloca (len + 1);
4524 sprintf (string, "%s%s", prefix, name);
4525 DECL_SECTION_NAME (decl) = build_string (len, string);
4530 /* The routine used to output NUL terminated strings. We use a special
4531 version of this for most svr4 targets because doing so makes the
4532 generated assembly code more compact (and thus faster to assemble)
4533 as well as more readable, especially for targets like the i386
4534 (where the only alternative is to output character sequences as
4535 comma separated lists of numbers). */
4538 gas_output_limited_string(file, str)
4542 const unsigned char *_limited_str = (unsigned char *) str;
4544 fprintf (file, "%s\"", STRING_ASM_OP);
4545 for (; (ch = *_limited_str); _limited_str++)
4548 switch (escape = ESCAPES[ch])
4554 fprintf (file, "\\%03o", ch);
4558 putc (escape, file);
4562 fprintf (file, "\"\n");
4565 /* The routine used to output sequences of byte values. We use a special
4566 version of this for most svr4 targets because doing so makes the
4567 generated assembly code more compact (and thus faster to assemble)
4568 as well as more readable. Note that if we find subparts of the
4569 character sequence which end with NUL (and which are shorter than
4570 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4573 gas_output_ascii(file, str, length)
4578 const unsigned char *_ascii_bytes = (const unsigned char *) str;
4579 const unsigned char *limit = _ascii_bytes + length;
4580 unsigned bytes_in_chunk = 0;
4581 for (; _ascii_bytes < limit; _ascii_bytes++)
4583 const unsigned char *p;
4584 if (bytes_in_chunk >= 60)
4586 fprintf (file, "\"\n");
4589 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4591 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4593 if (bytes_in_chunk > 0)
4595 fprintf (file, "\"\n");
4598 gas_output_limited_string (file, (char*)_ascii_bytes);
4605 if (bytes_in_chunk == 0)
4606 fprintf (file, "\t.ascii\t\"");
4607 switch (escape = ESCAPES[ch = *_ascii_bytes])
4614 fprintf (file, "\\%03o", ch);
4615 bytes_in_chunk += 4;
4619 putc (escape, file);
4620 bytes_in_chunk += 2;
4625 if (bytes_in_chunk > 0)
4626 fprintf (file, "\"\n");
4629 /* Return value is nonzero if pseudos that have been
4630 assigned to registers of class CLASS would likely be spilled
4631 because registers of CLASS are needed for spill registers. */
4634 class_likely_spilled_p (c)
4637 return (c != ALL_REGS && c != ADDW_REGS);
4640 /* Valid attributes:
4641 progmem - put data to program memory;
4642 signal - make a function to be hardware interrupt. After function
4643 prologue interrupts are disabled;
4644 interrupt - make a function to be hardware interrupt. After function
4645 prologue interrupts are enabled;
4646 naked - don't generate function prologue/epilogue and `ret' command.
4648 Only `progmem' attribute valid for type. */
4650 const struct attribute_spec avr_attribute_table[] =
4652 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4653 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
4654 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4655 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4656 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4657 { NULL, 0, 0, false, false, false, NULL }
4660 /* Handle a "progmem" attribute; arguments as in
4661 struct attribute_spec.handler. */
4663 avr_handle_progmem_attribute (node, name, args, flags, no_add_attrs)
4666 tree args ATTRIBUTE_UNUSED;
4667 int flags ATTRIBUTE_UNUSED;
4672 if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
4674 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
4676 warning ("only initialized variables can be placed into "
4677 "program memory area");
4678 *no_add_attrs = true;
4683 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
4684 *no_add_attrs = true;
4691 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4692 struct attribute_spec.handler. */
4694 avr_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
4697 tree args ATTRIBUTE_UNUSED;
4698 int flags ATTRIBUTE_UNUSED;
4701 if (TREE_CODE (*node) != FUNCTION_DECL)
4703 warning ("`%s' attribute only applies to functions",
4704 IDENTIFIER_POINTER (name));
4705 *no_add_attrs = true;
4711 /* Look for attribute `progmem' in DECL
4712 if found return 1, otherwise 0. */
4715 avr_progmem_p (decl)
4720 if (TREE_CODE (decl) != VAR_DECL)
4724 != lookup_attribute ("progmem", DECL_ATTRIBUTES (decl)))
4730 while (TREE_CODE (a) == ARRAY_TYPE);
4732 if (a == error_mark_node)
4735 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4741 /* Encode section information about tree DECL */
4744 encode_section_info (decl)
4747 if (TREE_CODE (decl) == FUNCTION_DECL)
4748 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
4749 else if ((TREE_STATIC (decl) || DECL_EXTERNAL (decl))
4750 && TREE_CODE (decl) == VAR_DECL
4751 && avr_progmem_p (decl))
4753 static const char *const dsec = ".progmem.data";
4754 DECL_SECTION_NAME (decl) = build_string (strlen (dsec), dsec);
4755 TREE_READONLY (decl) = 1;
4759 /* Outputs to the stdio stream FILE some
4760 appropriate text to go at the start of an assembler file. */
4763 asm_file_start (file)
4766 output_file_directive (file, main_input_filename);
4767 fprintf (file, "\t.arch %s\n", avr_mcu_name);
4768 fputs ("__SREG__ = 0x3f\n"
4770 "__SP_L__ = 0x3d\n", file);
4772 fputs ("__tmp_reg__ = 0\n"
4773 "__zero_reg__ = 1\n"
4774 "_PC_ = 2\n", file);
4776 commands_in_file = 0;
4777 commands_in_prologues = 0;
4778 commands_in_epilogues = 0;
4781 /* Outputs to the stdio stream FILE some
4782 appropriate text to go at the end of an assembler file. */
4789 "/* File %s: code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4790 main_input_filename,
4793 commands_in_file - commands_in_prologues - commands_in_epilogues,
4794 commands_in_prologues, commands_in_epilogues);
4797 /* Choose the order in which to allocate hard registers for
4798 pseudo-registers local to a basic block.
4800 Store the desired register order in the array `reg_alloc_order'.
4801 Element 0 should be the register to allocate first; element 1, the
4802 next register; and so on. */
4805 order_regs_for_local_alloc ()
4808 static const int order_0[] = {
4816 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4820 static const int order_1[] = {
4828 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4832 static const int order_2[] = {
4841 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4846 const int *order = (TARGET_ORDER_1 ? order_1 :
4847 TARGET_ORDER_2 ? order_2 :
4849 for (i=0; i < ARRAY_SIZE (order_0); ++i)
4850 reg_alloc_order[i] = order[i];
4853 /* Calculate the cost of X code of the expression in which it is contained,
4854 found in OUTER_CODE */
4857 default_rtx_costs (X, code, outer_code)
4860 enum rtx_code outer_code;
4867 cost = 2 * GET_MODE_SIZE (GET_MODE (X));
4870 if (outer_code != SET)
4872 if (GET_CODE (XEXP (X,0)) == SYMBOL_REF)
4873 cost += 2 * GET_MODE_SIZE (GET_MODE (X));
4875 cost += GET_MODE_SIZE (GET_MODE (X));
4881 if (outer_code == SET)
4882 cost = GET_MODE_SIZE (GET_MODE (X));
4884 cost = -GET_MODE_SIZE (GET_MODE (X));
4887 if (outer_code == SET)
4888 cost = GET_MODE_SIZE (GET_MODE (X));
4894 if (outer_code == SET)
4896 if (X == stack_pointer_rtx)
4898 else if (GET_CODE (XEXP (X,1)) == CONST_INT)
4899 cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 :
4900 GET_MODE_SIZE (GET_MODE (X)));
4902 cost = GET_MODE_SIZE (GET_MODE (X));
4906 if (GET_CODE (XEXP (X,1)) == CONST_INT)
4907 cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0)));
4915 /* Calculate the cost of a memory address */
4918 avr_address_cost (x)
4921 if (GET_CODE (x) == PLUS
4922 && GET_CODE (XEXP (x,1)) == CONST_INT
4923 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
4924 && INTVAL (XEXP (x,1)) >= 61)
4926 if (CONSTANT_ADDRESS_P (x))
4928 if (io_address_p (x, 1))
4935 /* EXTRA_CONSTRAINT helper */
4938 extra_constraint (x, c)
4943 && GET_CODE (x) == MEM
4944 && GET_CODE (XEXP (x,0)) == PLUS)
4946 if (TARGET_ALL_DEBUG)
4948 fprintf (stderr, ("extra_constraint:\n"
4949 "reload_completed: %d\n"
4950 "reload_in_progress: %d\n"),
4951 reload_completed, reload_in_progress);
4954 if (GET_CODE (x) == MEM
4955 && GET_CODE (XEXP (x,0)) == PLUS
4956 && REG_P (XEXP (XEXP (x,0), 0))
4957 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
4958 && (INTVAL (XEXP (XEXP (x,0), 1))
4959 <= MAX_LD_OFFSET (GET_MODE (x))))
4961 rtx xx = XEXP (XEXP (x,0), 0);
4962 int regno = REGNO (xx);
4963 if (TARGET_ALL_DEBUG)
4965 fprintf (stderr, ("extra_constraint:\n"
4966 "reload_completed: %d\n"
4967 "reload_in_progress: %d\n"),
4968 reload_completed, reload_in_progress);
4971 if (regno >= FIRST_PSEUDO_REGISTER)
4972 return 1; /* allocate pseudos */
4973 else if (regno == REG_Z || regno == REG_Y)
4974 return 1; /* strictly check */
4975 else if (xx == frame_pointer_rtx
4976 || xx == arg_pointer_rtx)
4977 return 1; /* XXX frame & arg pointer checks */
4983 /* Convert condition code CONDITION to the valid AVR condition code */
4986 avr_normalize_condition (condition)
5004 /* This fnction optimizes conditional jumps */
5007 machine_dependent_reorg (first_insn)
5012 for (insn = first_insn; insn; insn = NEXT_INSN (insn))
5014 if (! (GET_CODE (insn) == INSN
5015 || GET_CODE (insn) == CALL_INSN
5016 || GET_CODE (insn) == JUMP_INSN)
5017 || !single_set (insn))
5020 pattern = PATTERN (insn);
5022 if (GET_CODE (pattern) == PARALLEL)
5023 pattern = XVECEXP (pattern, 0, 0);
5024 if (GET_CODE (pattern) == SET
5025 && SET_DEST (pattern) == cc0_rtx
5026 && compare_diff_p (insn))
5028 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
5030 /* Now we work under compare insn */
5032 pattern = SET_SRC (pattern);
5033 if (true_regnum (XEXP (pattern,0)) >= 0
5034 && true_regnum (XEXP (pattern,1)) >= 0 )
5036 rtx x = XEXP (pattern,0);
5037 rtx next = next_real_insn (insn);
5038 rtx pat = PATTERN (next);
5039 rtx src = SET_SRC (pat);
5040 rtx t = XEXP (src,0);
5041 PUT_CODE (t, swap_condition (GET_CODE (t)));
5042 XEXP (pattern,0) = XEXP (pattern,1);
5043 XEXP (pattern,1) = x;
5044 INSN_CODE (next) = -1;
5046 else if (true_regnum (XEXP (pattern,0)) >= 0
5047 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
5049 rtx x = XEXP (pattern,1);
5050 rtx next = next_real_insn (insn);
5051 rtx pat = PATTERN (next);
5052 rtx src = SET_SRC (pat);
5053 rtx t = XEXP (src,0);
5055 if (avr_simplify_comparision_p (GET_MODE (XEXP (pattern,0)),
5058 XEXP (pattern,1) = GEN_INT (INTVAL (x)+1);
5059 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
5060 INSN_CODE (next) = -1;
5061 INSN_CODE (insn) = -1;
5065 else if (true_regnum (SET_SRC (pattern)) >= 0)
5067 /* This is a tst insn */
5068 rtx next = next_real_insn (insn);
5069 rtx pat = PATTERN (next);
5070 rtx src = SET_SRC (pat);
5071 rtx t = XEXP (src,0);
5073 PUT_CODE (t, swap_condition (GET_CODE (t)));
5074 SET_SRC (pattern) = gen_rtx (NEG,
5075 GET_MODE (SET_SRC (pattern)),
5077 INSN_CODE (next) = -1;
5078 INSN_CODE (insn) = -1;
5084 /* Returns register number for function return value.*/
5092 /* Ceate an RTX representing the place where a
5093 library function returns a value of mode MODE. */
5096 avr_libcall_value (mode)
5097 enum machine_mode mode;
5099 int offs = GET_MODE_SIZE (mode);
5102 return gen_rtx (REG, mode, RET_REGISTER + 2 - offs);
5105 /* Create an RTX representing the place where a
5106 function returns a value of data type VALTYPE. */
5109 avr_function_value (type, func)
5111 tree func ATTRIBUTE_UNUSED;
5115 if (TYPE_MODE (type) != BLKmode)
5116 return avr_libcall_value (TYPE_MODE (type));
5118 offs = int_size_in_bytes (type);
5121 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5122 offs = GET_MODE_SIZE (SImode);
5123 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5124 offs = GET_MODE_SIZE (DImode);
5126 return gen_rtx (REG, BLKmode, RET_REGISTER + 2 - offs);
5129 /* Returns non-zero if the number MASK has only one bit set. */
5132 mask_one_bit_p (mask)
5136 unsigned HOST_WIDE_INT n=mask;
5137 for (i = 0; i < 32; ++i)
5139 if (n & 0x80000000L)
5141 if (n & 0x7fffffffL)
5152 /* Places additional restrictions on the register class to
5153 use when it is necessary to copy value X into a register
5157 preferred_reload_class (x, class)
5158 rtx x ATTRIBUTE_UNUSED;
5159 enum reg_class class;
5165 test_hard_reg_class (class, x)
5166 enum reg_class class;
5169 int regno = true_regnum (x);
5172 return TEST_HARD_REG_CLASS (class, regno);
5176 debug_hard_reg_set (set)
5180 for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
5182 if (TEST_HARD_REG_BIT (set, i))
5184 fprintf (stderr, "r%-2d ", i);
5187 fprintf (stderr, "\n");
5191 jump_over_one_insn_p (insn, dest)
5195 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5198 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5199 int dest_addr = INSN_ADDRESSES (uid);
5200 return dest_addr - jump_addr == 2;
5203 /* Returns 1 if a value of mode MODE can be stored starting with hard
5204 register number REGNO. On the enhanced core, anything larger than
5205 1 byte must start in even numbered register for "movw" to work
5206 (this way we don't have to check for odd registers everywhere). */
5209 avr_hard_regno_mode_ok (regno, mode)
5211 enum machine_mode mode;
5213 /* Bug workaround: recog.c (peep2_find_free_register) and probably
5214 a few other places assume that the frame pointer is a single hard
5215 register, so r29 may be allocated and overwrite the high byte of
5216 the frame pointer. Do not allow any value to start in r29. */
5217 if (regno == REG_Y + 1)
5222 /* if (regno < 24 && !AVR_ENHANCED)
5224 return !(regno & 1);
5227 /* Returns 1 if we know register operand OP was 0 before INSN. */
5230 reg_was_0 (insn, op)
5235 return (optimize > 0 && insn && op && REG_P (op)
5236 && (link = find_reg_note (insn, REG_WAS_0, 0))
5237 /* Make sure the insn that stored the 0 is still present. */
5238 && ! INSN_DELETED_P (XEXP (link, 0))
5239 && GET_CODE (XEXP (link, 0)) != NOTE
5240 /* Make sure cross jumping didn't happen here. */
5241 && no_labels_between_p (XEXP (link, 0), insn)
5242 /* Make sure the reg hasn't been clobbered. */
5243 && ! reg_set_between_p (op, XEXP (link, 0), insn));
5246 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5247 (1 or 2). Used for lds/sts -> in/out optimization. */
5250 io_address_p (x, size)
5254 return (optimize > 0 && GET_CODE (x) == CONST_INT
5255 && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
5258 /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5261 const_int_pow2_p (x)
5264 if (GET_CODE (x) == CONST_INT)
5266 HOST_WIDE_INT d = INTVAL (x);
5267 HOST_WIDE_INT abs_d = (d >= 0) ? d : -d;
5268 return exact_log2 (abs_d) + 1;
5274 output_reload_inhi (insn, operands, len)
5275 rtx insn ATTRIBUTE_UNUSED;
5283 if (GET_CODE (operands[1]) == CONST_INT)
5285 int val = INTVAL (operands[1]);
5286 if ((val & 0xff) == 0)
5289 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5290 AS2 (ldi,%2,hi8(%1)) CR_TAB
5293 else if ((val & 0xff00) == 0)
5296 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5297 AS2 (mov,%A0,%2) CR_TAB
5298 AS2 (mov,%B0,__zero_reg__));
5300 else if ((val & 0xff) == ((val & 0xff00) >> 8))
5303 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5304 AS2 (mov,%A0,%2) CR_TAB
5309 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5310 AS2 (mov,%A0,%2) CR_TAB
5311 AS2 (ldi,%2,hi8(%1)) CR_TAB
5317 output_reload_insisf (insn, operands, len)
5318 rtx insn ATTRIBUTE_UNUSED;
5322 rtx src = operands[1];
5323 int cnst = (GET_CODE (src) == CONST_INT);
5328 *len = 4 + ((INTVAL (src) & 0xff) != 0)
5329 + ((INTVAL (src) & 0xff00) != 0)
5330 + ((INTVAL (src) & 0xff0000) != 0)
5331 + ((INTVAL (src) & 0xff000000) != 0);
5338 if (cnst && ((INTVAL (src) & 0xff) == 0))
5339 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5342 output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
5343 output_asm_insn (AS2 (mov, %A0, %2), operands);
5345 if (cnst && ((INTVAL (src) & 0xff00) == 0))
5346 output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
5349 output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
5350 output_asm_insn (AS2 (mov, %B0, %2), operands);
5352 if (cnst && ((INTVAL (src) & 0xff0000) == 0))
5353 output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
5356 output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
5357 output_asm_insn (AS2 (mov, %C0, %2), operands);
5359 if (cnst && ((INTVAL (src) & 0xff000000) == 0))
5360 output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
5363 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5364 output_asm_insn (AS2 (mov, %D0, %2), operands);
5370 avr_output_bld (operands, bit_nr)
5374 static char s[] = "bld %A0,0";
5376 s[5] = 'A' + (bit_nr >> 3);
5377 s[8] = '0' + (bit_nr & 7);
5378 output_asm_insn (s, operands);
5382 avr_output_addr_vec_elt (stream, value)
5387 fprintf (stream, "\t.word pm(.L%d)\n", value);
5389 fprintf (stream, "\trjmp .L%d\n", value);
5394 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5395 registers (for a define_peephole2) in the current function. */
5398 avr_peep2_scratch_safe (scratch)
5401 if ((interrupt_function_p (current_function_decl)
5402 || signal_function_p (current_function_decl))
5403 && leaf_function_p ())
5405 int first_reg = true_regnum (scratch);
5406 int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
5409 for (reg = first_reg; reg <= last_reg; reg++)
5411 if (!regs_ever_live[reg])