1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998, 1999, 2000, 2001 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 int avr_valid_type_attribute PARAMS ((tree, tree, tree, tree));
62 static int avr_valid_decl_attribute PARAMS ((tree, tree, tree, tree));
63 static void avr_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
64 static void avr_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
66 /* Allocate registers from r25 to r8 for parameters for function calls */
67 #define FIRST_CUM_REG 26
69 /* Temporary register RTX (gen_rtx (REG,QImode,TMP_REGNO)) */
72 /* Zeroed register RTX (gen_rtx (REG,QImode,ZERO_REGNO)) */
75 /* RTX for register which will be used for loading immediate values to
79 /* AVR register names {"r0", "r1", ..., "r31"} */
80 const char * avr_regnames[] = REGISTER_NAMES;
82 /* This holds the last insn address. */
83 static int last_insn_address = 0;
85 /* Commands count in the compiled file */
86 static int commands_in_file;
88 /* Commands in the functions prologues in the compiled file */
89 static int commands_in_prologues;
91 /* Commands in the functions epilogues in the compiled file */
92 static int commands_in_epilogues;
94 /* Prologue/Epilogue size in words */
95 static int prologue_size;
96 static int epilogue_size;
98 /* Size of all jump tables in the current function, in words. */
99 static int jump_tables_size;
101 /* Initial stack value specified by the `-minit-stack=' option */
102 const char *avr_init_stack = "__stack";
104 /* Default MCU name */
105 const char *avr_mcu_name = "avr2";
107 /* More than 8K of program memory: use "call" and "jmp". */
110 /* Enhanced core: use "movw", "mul", ... */
111 int avr_enhanced_p = 0;
126 /* List of all known AVR MCU types - if updated, it has to be kept
127 in sync in several places (FIXME: is there a better way?):
129 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
130 - t-avr (MULTILIB_MATCHES)
131 - gas/config/tc-avr.c
134 static const struct mcu_type_s avr_mcu_types[] = {
135 /* Classic, <= 8K. */
137 { "at90s2313", AVR2 },
138 { "at90s2323", AVR2 },
139 { "attiny22", AVR2 },
140 { "at90s2333", AVR2 },
141 { "at90s2343", AVR2 },
142 { "at90s4414", AVR2 },
143 { "at90s4433", AVR2 },
144 { "at90s4434", AVR2 },
145 { "at90s8515", AVR2 },
146 { "at90c8534", AVR2 },
147 { "at90s8535", AVR2 },
150 { "atmega103", AVR3 },
151 { "atmega603", AVR3 },
152 /* Enhanced, <= 8K. */
154 { "atmega83", AVR4 },
155 { "atmega85", AVR4 },
156 /* Enhanced, > 8K. */
158 { "atmega161", AVR5 },
159 { "atmega163", AVR5 },
160 { "atmega32", AVR5 },
162 /* Assembler only. */
164 { "at90s1200", AVR1 },
165 { "attiny10", AVR1 },
166 { "attiny11", AVR1 },
167 { "attiny12", AVR1 },
168 { "attiny15", AVR1 },
169 { "attiny28", AVR1 },
173 int avr_case_values_threshold = 30000;
175 /* Initialize the GCC target structure. */
176 #undef TARGET_ASM_FUNCTION_PROLOGUE
177 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
178 #undef TARGET_ASM_FUNCTION_EPILOGUE
179 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
180 #undef TARGET_VALID_DECL_ATTRIBUTE
181 #define TARGET_VALID_DECL_ATTRIBUTE avr_valid_decl_attribute
183 #undef TARGET_VALID_TYPE_ATTRIBUTE
184 #define TARGET_VALID_TYPE_ATTRIBUTE avr_valid_type_attribute
186 struct gcc_target targetm = TARGET_INITIALIZER;
189 avr_override_options ()
191 const struct mcu_type_s *t;
193 for (t = avr_mcu_types; t->name; t++)
194 if (strcmp (t->name, avr_mcu_name) == 0)
199 fprintf (stderr, "Unknown MCU `%s' specified\nKnown MCU names:\n",
201 for (t = avr_mcu_types; t->name; t++)
202 fprintf (stderr," %s\n", t->name);
209 error ("MCU `%s' not supported", avr_mcu_name);
210 /* ... fall through ... */
211 case AVR2: avr_enhanced_p = 0; avr_mega_p = 0; break;
212 case AVR3: avr_enhanced_p = 0; avr_mega_p = 1; break;
213 case AVR4: avr_enhanced_p = 1; avr_mega_p = 0; break;
214 case AVR5: avr_enhanced_p = 1; avr_mega_p = 1; break;
217 if (optimize && !TARGET_NO_TABLEJUMP)
218 avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
222 /* Initialize TMP_REG_RTX and ZERO_REG_RTX */
226 tmp_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
227 memset (tmp_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
228 PUT_CODE (tmp_reg_rtx, REG);
229 PUT_MODE (tmp_reg_rtx, QImode);
230 XINT (tmp_reg_rtx, 0) = TMP_REGNO;
232 zero_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
233 memset (zero_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
234 PUT_CODE (zero_reg_rtx, REG);
235 PUT_MODE (zero_reg_rtx, QImode);
236 XINT (zero_reg_rtx, 0) = ZERO_REGNO;
238 ldi_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
239 memset (ldi_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
240 PUT_CODE (ldi_reg_rtx, REG);
241 PUT_MODE (ldi_reg_rtx, QImode);
242 XINT (ldi_reg_rtx, 0) = LDI_REG_REGNO;
245 /* return register class from register number */
247 static int reg_class_tab[]={
248 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
249 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
250 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
251 GENERAL_REGS, /* r0 - r15 */
252 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
253 LD_REGS, /* r16 - 23 */
254 ADDW_REGS,ADDW_REGS, /* r24,r25 */
255 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
256 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
257 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
258 STACK_REG,STACK_REG /* SPL,SPH */
261 /* Return register class for register R */
264 avr_regno_reg_class (r)
268 return reg_class_tab[r];
273 /* A C expression which defines the machine-dependent operand
274 constraint letters for register classes. If C is such a
275 letter, the value should be the register class corresponding to
276 it. Otherwise, the value should be `NO_REGS'. The register
277 letter `r', corresponding to class `GENERAL_REGS', will not be
278 passed to this macro; you do not need to handle it. */
281 avr_reg_class_from_letter (c)
286 case 't' : return R0_REG;
287 case 'b' : return BASE_POINTER_REGS;
288 case 'e' : return POINTER_REGS;
289 case 'w' : return ADDW_REGS;
290 case 'd' : return LD_REGS;
291 case 'l' : return NO_LD_REGS;
292 case 'a' : return SIMPLE_LD_REGS;
293 case 'x' : return POINTER_X_REGS;
294 case 'y' : return POINTER_Y_REGS;
295 case 'z' : return POINTER_Z_REGS;
296 case 'q' : return STACK_REG;
302 /* Return non-zero if FUNC is a naked function. */
305 avr_naked_function_p (func)
310 if (TREE_CODE (func) != FUNCTION_DECL)
313 a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
314 return a != NULL_TREE;
317 /* Return nonzero if FUNC is an interrupt function as specified
318 by the "interrupt" attribute. */
321 interrupt_function_p (func)
326 if (TREE_CODE (func) != FUNCTION_DECL)
329 a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func));
330 return a != NULL_TREE;
333 /* Return nonzero if FUNC is a signal function as specified
334 by the "signal" attribute. */
337 signal_function_p (func)
342 if (TREE_CODE (func) != FUNCTION_DECL)
345 a = lookup_attribute ("signal", DECL_MACHINE_ATTRIBUTES (func));
346 return a != NULL_TREE;
349 /* Compute offset between arg_pointer and frame_pointer */
352 initial_elimination_offset (from, to)
357 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
361 int interrupt_func_p = interrupt_function_p (current_function_decl);
362 int signal_func_p = signal_function_p (current_function_decl);
363 int leaf_func_p = leaf_function_p ();
364 int offset= frame_pointer_needed ? 2 : 0;
366 for (reg = 0; reg < 32; ++reg)
368 if ((!leaf_func_p && (call_used_regs[reg]
369 && (interrupt_func_p || signal_func_p)))
370 || (regs_ever_live[reg]
371 && (!call_used_regs[reg] || interrupt_func_p || signal_func_p)
372 && ! (frame_pointer_needed
373 && (reg == REG_Y || reg == (REG_Y+1)))))
378 return get_frame_size () + 2 + 1 + offset;
383 /* This function checks sequence of live registers */
392 for (reg = 0; reg < 18; ++reg)
394 if (!call_used_regs[reg])
396 if (regs_ever_live[reg])
406 if (!frame_pointer_needed)
408 if (regs_ever_live[REG_Y])
416 if (regs_ever_live[REG_Y+1])
429 return (cur_seq == live_seq) ? live_seq : 0;
433 /* Output to FILE the asm instructions to adjust the frame pointer by
434 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
435 (epilogue). Returns the number of instructions generated. */
438 out_adj_frame_ptr (file, adj)
446 if (TARGET_TINY_STACK)
448 if (adj < -63 || adj > 63)
449 warning ("large frame pointer change (%d) with -mtiny-stack", adj);
451 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
452 over "sbiw" (2 cycles, same size). */
454 fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
457 else if (adj < -63 || adj > 63)
459 fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
460 AS2 (sbci, r29, hi8(%d)) CR_TAB),
466 fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
471 fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
479 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
480 handling various cases of interrupt enable flag state BEFORE and AFTER
481 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
482 Returns the number of instructions generated. */
485 out_set_stack_ptr (file, before, after)
490 int do_sph, do_cli, do_save, do_sei, lock_sph, size;
492 /* The logic here is so that -mno-interrupts actually means
493 "it is safe to write SPH in one instruction, then SPL in the
494 next instruction, without disabling interrupts first".
495 The after != -1 case (interrupt/signal) is not affected. */
497 do_sph = !TARGET_TINY_STACK;
498 lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
499 do_cli = (before != 0 && (after == 0 || lock_sph));
500 do_save = (do_cli && before == -1 && after == -1);
501 do_sei = ((do_cli || before != 1) && after == 1);
506 fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
512 fprintf (file, "cli" CR_TAB);
516 /* Do SPH first - maybe this will disable interrupts for one instruction
517 someday (a suggestion has been sent to avr@atmel.com for consideration
518 in future devices - that would make -mno-interrupts always safe). */
521 fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
525 /* Set/restore the I flag now - interrupts will be really enabled only
526 after the next instruction. This is not clearly documented, but
527 believed to be true for all AVR devices. */
530 fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
535 fprintf (file, "sei" CR_TAB);
539 fprintf (file, AS2 (out, __SP_L__, r28) "\n");
545 /* Output function prologue */
548 avr_output_function_prologue (file, size)
553 int interrupt_func_p;
560 if (avr_naked_function_p (current_function_decl))
562 fprintf (file, "/* prologue: naked */\n");
566 interrupt_func_p = interrupt_function_p (current_function_decl);
567 signal_func_p = signal_function_p (current_function_decl);
568 leaf_func_p = leaf_function_p ();
569 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
570 live_seq = sequent_regs_live ();
571 minimize = (TARGET_CALL_PROLOGUES
572 && !interrupt_func_p && !signal_func_p && live_seq);
574 last_insn_address = 0;
575 jump_tables_size = 0;
577 fprintf (file, "/* prologue: frame size=%d */\n", size);
579 if (interrupt_func_p)
581 fprintf (file,"\tsei\n");
584 if (interrupt_func_p | signal_func_p)
587 AS1 (push,__zero_reg__) CR_TAB
588 AS1 (push,__tmp_reg__) CR_TAB
589 AS2 (in,__tmp_reg__,__SREG__) CR_TAB
590 AS1 (push,__tmp_reg__) CR_TAB
591 AS1 (clr,__zero_reg__) "\n");
597 AS2 (ldi,r28,lo8(%s - %d)) CR_TAB
598 AS2 (ldi,r29,hi8(%s - %d)) CR_TAB
599 AS2 (out,__SP_H__,r29) CR_TAB
600 AS2 (out,__SP_L__,r28) "\n"),
601 avr_init_stack, size, avr_init_stack, size);
605 else if (minimize && (frame_pointer_needed || live_seq > 6))
608 AS2 (ldi, r26, lo8(%d)) CR_TAB
609 AS2 (ldi, r27, hi8(%d)) CR_TAB), size, size);
611 fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB
612 AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB)
613 ,current_function_name, current_function_name);
619 fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
620 (18 - live_seq) * 2);
625 fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
626 (18 - live_seq) * 2);
629 fprintf (file, ".L_%s_body:\n", current_function_name);
633 for (reg = 0; reg < 32; ++reg)
636 && (call_used_regs[reg]
637 && (interrupt_func_p || signal_func_p)
638 && !(reg == TMP_REGNO || reg == ZERO_REGNO)))
639 || (regs_ever_live[reg]
640 && (!call_used_regs[reg]
641 || interrupt_func_p || signal_func_p)
642 && ! (frame_pointer_needed
643 && (reg == REG_Y || reg == (REG_Y+1)))))
645 fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
649 if (frame_pointer_needed)
653 AS1 (push,r28) CR_TAB
654 AS1 (push,r29) CR_TAB
655 AS2 (in,r28,__SP_L__) CR_TAB
656 AS2 (in,r29,__SP_H__) "\n");
661 prologue_size += out_adj_frame_ptr (file, size);
663 if (interrupt_func_p)
665 prologue_size += out_set_stack_ptr (file, 1, 1);
667 else if (signal_func_p)
669 prologue_size += out_set_stack_ptr (file, 0, 0);
673 prologue_size += out_set_stack_ptr (file, -1, -1);
679 fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
682 /* Output function epilogue */
685 avr_output_function_epilogue (file, size)
690 int interrupt_func_p;
698 if (avr_naked_function_p (current_function_decl))
700 fprintf (file, "/* epilogue: naked */\n");
704 interrupt_func_p = interrupt_function_p (current_function_decl);
705 signal_func_p = signal_function_p (current_function_decl);
706 leaf_func_p = leaf_function_p ();
707 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
708 function_size = (INSN_ADDRESSES (INSN_UID (get_last_insn ()))
709 - INSN_ADDRESSES (INSN_UID (get_insns ())));
710 function_size += jump_tables_size;
711 live_seq = sequent_regs_live ();
712 minimize = (TARGET_CALL_PROLOGUES
713 && !interrupt_func_p && !signal_func_p && live_seq);
716 fprintf (file, "/* epilogue: frame size=%d */\n", size);
719 fprintf (file, "__stop_progIi__:\n\trjmp __stop_progIi__\n");
722 else if (minimize && (frame_pointer_needed || live_seq > 4))
724 fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
726 if (frame_pointer_needed)
728 epilogue_size += out_adj_frame_ptr (file, -size);
732 fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
733 AS2 (in , r29, __SP_H__) CR_TAB));
739 fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
740 (18 - live_seq) * 2);
745 fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
746 (18 - live_seq) * 2);
752 if (frame_pointer_needed)
757 epilogue_size += out_adj_frame_ptr (file, -size);
759 if (interrupt_func_p | signal_func_p)
761 epilogue_size += out_set_stack_ptr (file, -1, 0);
765 epilogue_size += out_set_stack_ptr (file, -1, -1);
774 for (reg = 31; reg >= 0; --reg)
777 && (call_used_regs[reg]
778 && (interrupt_func_p || signal_func_p)
779 && !(reg == TMP_REGNO || reg == ZERO_REGNO)))
780 || (regs_ever_live[reg]
781 && (!call_used_regs[reg]
782 || interrupt_func_p || signal_func_p)
783 && ! (frame_pointer_needed
784 && (reg == REG_Y || reg == (REG_Y+1)))))
786 fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
791 if (interrupt_func_p | signal_func_p)
794 AS1 (pop,__tmp_reg__) CR_TAB
795 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
796 AS1 (pop,__tmp_reg__) CR_TAB
797 AS1 (pop,__zero_reg__) "\n");
799 fprintf (file, "\treti\n");
802 fprintf (file, "\tret\n");
806 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
807 fprintf (file, "/* function %s size %d (%d) */\n", current_function_name,
808 prologue_size + function_size + epilogue_size, function_size);
809 commands_in_file += prologue_size + function_size + epilogue_size;
810 commands_in_prologues += prologue_size;
811 commands_in_epilogues += epilogue_size;
815 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
816 machine for a memory operand of mode MODE. */
820 legitimate_address_p (mode, x, strict)
821 enum machine_mode mode;
825 enum reg_class r = NO_REGS;
827 if (TARGET_ALL_DEBUG)
829 fprintf (stderr, "mode: (%s) %s %s %s %s:",
831 strict ? "(strict)": "",
832 reload_completed ? "(reload_completed)": "",
833 reload_in_progress ? "(reload_in_progress)": "",
834 reg_renumber ? "(reg_renumber)" : "");
835 if (GET_CODE (x) == PLUS
836 && REG_P (XEXP (x, 0))
837 && GET_CODE (XEXP (x, 1)) == CONST_INT
838 && INTVAL (XEXP (x, 1)) >= 0
839 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
842 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
843 true_regnum (XEXP (x, 0)));
846 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
847 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
849 else if (CONSTANT_ADDRESS_P (x))
851 else if (GET_CODE (x) == PLUS
852 && REG_P (XEXP (x, 0))
853 && GET_CODE (XEXP (x, 1)) == CONST_INT
854 && INTVAL (XEXP (x, 1)) >= 0)
856 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
860 || REGNO (XEXP (x,0)) == REG_Y
861 || REGNO (XEXP (x,0)) == REG_Z)
862 r = BASE_POINTER_REGS;
863 if (XEXP (x,0) == frame_pointer_rtx
864 || XEXP (x,0) == arg_pointer_rtx)
865 r = BASE_POINTER_REGS;
867 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
870 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
871 && REG_P (XEXP (x, 0))
872 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
873 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
877 if (TARGET_ALL_DEBUG)
879 fprintf (stderr, " ret = %c\n", r);
881 return r == NO_REGS ? 0 : (int)r;
884 /* Attempts to replace X with a valid
885 memory address for an operand of mode MODE */
888 legitimize_address (x, oldx, mode)
891 enum machine_mode mode;
894 if (TARGET_ALL_DEBUG)
896 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
900 if (GET_CODE (oldx) == PLUS
901 && REG_P (XEXP (oldx,0)))
903 if (REG_P (XEXP (oldx,1)))
904 x = force_reg (GET_MODE (oldx), oldx);
905 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
907 int offs = INTVAL (XEXP (oldx,1));
908 if (frame_pointer_rtx != XEXP (oldx,0))
909 if (offs > MAX_LD_OFFSET (mode))
911 if (TARGET_ALL_DEBUG)
912 fprintf (stderr, "force_reg (big offset)\n");
913 x = force_reg (GET_MODE (oldx), oldx);
921 /* Return a pointer register name as a string */
924 ptrreg_to_str (regno)
929 case REG_X: return "X";
930 case REG_Y: return "Y";
931 case REG_Z: return "Z";
938 /* Return the condition name as a string.
939 Used in conditional jump constructing */
952 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
957 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
970 /* Output ADDR to FILE as address */
973 print_operand_address (file, addr)
977 switch (GET_CODE (addr))
980 fprintf (file, ptrreg_to_str (REGNO (addr)));
984 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
988 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
992 if (CONSTANT_ADDRESS_P (addr)
993 && (SYMBOL_REF_FLAG (addr) || GET_CODE (addr) == LABEL_REF))
995 fprintf (file, "pm(");
996 output_addr_const (file,addr);
1000 output_addr_const (file, addr);
1005 /* Output X as assembler operand to file FILE */
1008 print_operand (file, x, code)
1015 if (code >= 'A' && code <= 'D')
1025 if (x == zero_reg_rtx)
1026 fprintf (file, "__zero_reg__");
1028 fprintf (file, reg_names[true_regnum (x) + abcd]);
1030 else if (GET_CODE (x) == CONST_INT)
1031 fprintf (file, "%d", INTVAL (x) + abcd);
1032 else if (GET_CODE (x) == MEM)
1034 rtx addr = XEXP (x,0);
1036 if (CONSTANT_P (addr) && abcd)
1039 output_address (addr);
1040 fprintf (file, ")+%d", abcd);
1042 else if (code == 'o')
1044 if (GET_CODE (addr) != PLUS)
1045 fatal_insn ("Bad address, not (reg+disp):", addr);
1047 print_operand (file, XEXP (addr, 1), 0);
1049 else if (GET_CODE (addr) == PLUS)
1051 print_operand_address (file, XEXP (addr,0));
1052 if (REGNO (XEXP (addr, 0)) == REG_X)
1053 fatal_insn ("Internal compiler bug.\nBad address:"
1056 print_operand (file, XEXP (addr,1), code);
1059 print_operand_address (file, addr);
1061 else if (GET_CODE (x) == CONST_DOUBLE)
1065 if (GET_MODE (x) != SFmode)
1066 fatal_insn ("Internal compiler bug. Unknown mode:", x);
1067 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1068 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1069 asm_fprintf (file, "0x%lx", val);
1071 else if (code == 'j')
1072 asm_fprintf (file, cond_string (GET_CODE (x)));
1073 else if (code == 'k')
1074 asm_fprintf (file, cond_string (reverse_condition (GET_CODE (x))));
1076 print_operand_address (file, x);
1079 /* Recognize operand OP of mode MODE used in call instructions */
1082 call_insn_operand (op, mode)
1084 enum machine_mode mode ATTRIBUTE_UNUSED;
1086 if (GET_CODE (op) == MEM)
1088 rtx inside = XEXP (op, 0);
1089 if (register_operand (inside, Pmode))
1091 if (CONSTANT_ADDRESS_P (inside))
1097 /* Update the condition code in the INSN. */
1100 notice_update_cc (body, insn)
1101 rtx body ATTRIBUTE_UNUSED;
1106 switch (get_attr_cc (insn))
1109 /* Insn does not affect CC at all. */
1117 set = single_set (insn);
1121 cc_status.flags |= CC_NO_OVERFLOW;
1122 cc_status.value1 = SET_DEST (set);
1127 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1128 The V flag may or may not be known but that's ok because
1129 alter_cond will change tests to use EQ/NE. */
1130 set = single_set (insn);
1134 cc_status.value1 = SET_DEST (set);
1135 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1140 set = single_set (insn);
1143 cc_status.value1 = SET_SRC (set);
1147 /* Insn doesn't leave CC in a usable state. */
1150 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1151 set = single_set (insn);
1154 rtx src = SET_SRC (set);
1156 if (GET_CODE (src) == ASHIFTRT
1157 && GET_MODE (src) == QImode)
1159 rtx x = XEXP (src, 1);
1161 if (GET_CODE (x) == CONST_INT
1164 cc_status.value1 = SET_DEST (set);
1165 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1173 /* Return maximum number of consecutive registers of
1174 class CLASS needed to hold a value of mode MODE. */
1177 class_max_nregs (class, mode)
1178 enum reg_class class ATTRIBUTE_UNUSED;
1179 enum machine_mode mode;
1181 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1184 /* Choose mode for jump insn:
1185 1 - relative jump in range -63 <= x <= 62 ;
1186 2 - relative jump in range -2046 <= x <= 2045 ;
1187 3 - absolute jump (only for ATmega[16]03). */
1190 avr_jump_mode (x, insn)
1191 rtx x; /* jump operand */
1192 rtx insn; /* jump insn */
1194 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1195 ? XEXP (x, 0) : x));
1196 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1197 int jump_distance = cur_addr - dest_addr;
1199 if (-63 <= jump_distance && jump_distance <= 62)
1201 else if (-2046 <= jump_distance && jump_distance <= 2045)
1209 /* return an AVR condition jump commands.
1210 X is a comparison RTX.
1211 LEN is a number returned by avr_jump_mode function.
1212 if REVERSE nonzero then condition code in X must be reversed. */
1215 ret_cond_branch (x, len, reverse)
1220 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1225 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1226 return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1228 len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1229 AS1 (brmi,_PC_+2) CR_TAB
1231 (AS1 (breq,_PC_+6) CR_TAB
1232 AS1 (brmi,_PC_+4) CR_TAB
1236 return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1238 len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1239 AS1 (brlt,_PC_+2) CR_TAB
1241 (AS1 (breq,_PC_+6) CR_TAB
1242 AS1 (brlt,_PC_+4) CR_TAB
1245 return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1247 len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1248 AS1 (brlo,_PC_+2) CR_TAB
1250 (AS1 (breq,_PC_+6) CR_TAB
1251 AS1 (brlo,_PC_+4) CR_TAB
1254 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1255 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1257 len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1258 AS1 (brpl,_PC_+2) CR_TAB
1260 (AS1 (breq,_PC_+2) CR_TAB
1261 AS1 (brpl,_PC_+4) CR_TAB
1264 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1266 len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1267 AS1 (brge,_PC_+2) CR_TAB
1269 (AS1 (breq,_PC_+2) CR_TAB
1270 AS1 (brge,_PC_+4) CR_TAB
1273 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1275 len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1276 AS1 (brsh,_PC_+2) CR_TAB
1278 (AS1 (breq,_PC_+2) CR_TAB
1279 AS1 (brsh,_PC_+4) CR_TAB
1287 return AS1 (br%k1,%0);
1289 return (AS1 (br%j1,_PC_+2) CR_TAB
1292 return (AS1 (br%j1,_PC_+4) CR_TAB
1301 return AS1 (br%j1,%0);
1303 return (AS1 (br%k1,_PC_+2) CR_TAB
1306 return (AS1 (br%k1,_PC_+4) CR_TAB
1314 /* Predicate function for immediate operand which fits to byte (8bit) */
1317 byte_immediate_operand (op, mode)
1319 enum machine_mode mode ATTRIBUTE_UNUSED;
1321 return (GET_CODE (op) == CONST_INT
1322 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1325 /* Output all insn addresses and their sizes into the assembly language
1326 output file. This is helpful for debugging whether the length attributes
1327 in the md file are correct.
1328 Output insn cost for next insn. */
1331 final_prescan_insn (insn, operand, num_operands)
1332 rtx insn, *operand ATTRIBUTE_UNUSED;
1333 int num_operands ATTRIBUTE_UNUSED;
1335 int uid = INSN_UID (insn);
1337 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1339 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1340 INSN_ADDRESSES (uid),
1341 INSN_ADDRESSES (uid) - last_insn_address,
1342 rtx_cost (PATTERN (insn), INSN));
1344 last_insn_address = INSN_ADDRESSES (uid);
1346 if (TARGET_RTL_DUMP)
1348 fprintf (asm_out_file, "/*****************\n");
1349 print_rtl_single (asm_out_file, insn);
1350 fprintf (asm_out_file, "*****************/\n");
1354 /* Return 0 if undefined, 1 if always true or always false. */
1357 avr_simplify_comparision_p (mode, operator, x)
1358 enum machine_mode mode;
1362 unsigned int max = (mode == QImode ? 0xff :
1363 mode == HImode ? 0xffff :
1364 mode == SImode ? 0xffffffffU : 0);
1365 if (max && operator && GET_CODE (x) == CONST_INT)
1367 if (unsigned_condition (operator) != operator)
1370 if (max != (INTVAL (x) & max)
1371 && INTVAL (x) != 0xff)
1378 /* Returns nonzero if REGNO is the number of a hard
1379 register in which function arguments are sometimes passed. */
1382 function_arg_regno_p(r)
1385 return (r >= 8 && r <= 25);
1388 /* Initializing the variable cum for the state at the beginning
1389 of the argument list. */
1392 init_cumulative_args (cum, fntype, libname, indirect)
1393 CUMULATIVE_ARGS *cum;
1396 int indirect ATTRIBUTE_UNUSED;
1399 cum->regno = FIRST_CUM_REG;
1402 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1403 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1404 != void_type_node));
1410 /* Returns the number of registers to allocate for a function argument. */
1413 avr_num_arg_regs (mode, type)
1414 enum machine_mode mode;
1419 if (mode == BLKmode)
1420 size = int_size_in_bytes (type);
1422 size = GET_MODE_SIZE (mode);
1424 /* Align all function arguments to start in even-numbered registers.
1425 Odd-sized arguments leave holes above them. */
1427 return (size + 1) & ~1;
1430 /* Controls whether a function argument is passed
1431 in a register, and which register. */
1434 function_arg (cum, mode, type, named)
1435 CUMULATIVE_ARGS *cum;
1436 enum machine_mode mode;
1438 int named ATTRIBUTE_UNUSED;
1440 int bytes = avr_num_arg_regs (mode, type);
1442 if (cum->nregs && bytes <= cum->nregs)
1443 return gen_rtx (REG, mode, cum->regno - bytes);
1448 /* Update the summarizer variable CUM to advance past an argument
1449 in the argument list. */
1452 function_arg_advance (cum, mode, type, named)
1453 CUMULATIVE_ARGS *cum; /* current arg information */
1454 enum machine_mode mode; /* current arg mode */
1455 tree type; /* type of the argument or 0 if lib support */
1456 int named ATTRIBUTE_UNUSED; /* whether or not the argument was named */
1458 int bytes = avr_num_arg_regs (mode, type);
1460 cum->nregs -= bytes;
1461 cum->regno -= bytes;
1463 if (cum->nregs <= 0)
1466 cum->regno = FIRST_CUM_REG;
1470 /***********************************************************************
1471 Functions for outputting various mov's for a various modes
1472 ************************************************************************/
1474 output_movqi (insn, operands, l)
1480 rtx dest = operands[0];
1481 rtx src = operands[1];
1489 if (register_operand (dest, QImode))
1491 if (register_operand (src, QImode)) /* mov r,r */
1493 if (test_hard_reg_class (STACK_REG, dest))
1494 return AS2 (out,%0,%1);
1495 else if (test_hard_reg_class (STACK_REG, src))
1496 return AS2 (in,%0,%1);
1498 return AS2 (mov,%0,%1);
1500 else if (CONSTANT_P (src))
1502 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1503 return AS2 (ldi,%0,lo8(%1));
1505 if (GET_CODE (src) == CONST_INT)
1507 if (src == const0_rtx) /* mov r,L */
1508 return AS1 (clr,%0);
1509 else if (src == const1_rtx)
1511 if (reg_was_0 (insn, dest))
1512 return AS1 (inc,%0 ; reg_was_0);
1515 return (AS1 (clr,%0) CR_TAB
1518 else if (src == constm1_rtx)
1520 /* Immediate constants -1 to any register */
1521 if (reg_was_0 (insn, dest))
1522 return AS1 (dec,%0 ; reg_was_0);
1525 return (AS1 (clr,%0) CR_TAB
1530 int bit_nr = exact_log2 (INTVAL (src));
1534 if (reg_was_0 (insn, dest))
1538 output_asm_insn ("set ; reg_was_0", operands);
1544 output_asm_insn ((AS1 (clr,%0) CR_TAB
1548 avr_output_bld (operands, bit_nr);
1555 /* Last resort, larger than loading from memory. */
1557 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1558 AS2 (ldi,r31,lo8(%1)) CR_TAB
1559 AS2 (mov,%0,r31) CR_TAB
1560 AS2 (mov,r31,__tmp_reg__));
1562 else if (GET_CODE (src) == MEM)
1563 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1565 else if (GET_CODE (dest) == MEM)
1567 const char *template;
1569 if (src == const0_rtx)
1570 operands[1] = zero_reg_rtx;
1572 template = out_movqi_mr_r (insn, operands, real_l);
1575 output_asm_insn (template, operands);
1584 output_movhi (insn, operands, l)
1590 rtx dest = operands[0];
1591 rtx src = operands[1];
1597 if (register_operand (dest, HImode))
1599 if (register_operand (src, HImode)) /* mov r,r */
1601 if (test_hard_reg_class (STACK_REG, dest))
1603 if (TARGET_TINY_STACK)
1606 return AS2 (out,__SP_L__,%A1);
1608 else if (TARGET_NO_INTERRUPTS)
1611 return (AS2 (out,__SP_H__,%B1) CR_TAB
1612 AS2 (out,__SP_L__,%A1));
1616 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1618 AS2 (out,__SP_H__,%B1) CR_TAB
1619 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1620 AS2 (out,__SP_L__,%A1));
1622 else if (test_hard_reg_class (STACK_REG, src))
1625 return (AS2 (in,%A0,__SP_L__) CR_TAB
1626 AS2 (in,%B0,__SP_H__));
1632 return (AS2 (movw,%0,%1));
1635 if (true_regnum (dest) > true_regnum (src))
1638 return (AS2 (mov,%B0,%B1) CR_TAB
1644 return (AS2 (mov,%A0,%A1) CR_TAB
1648 else if (CONSTANT_P (src))
1650 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1652 if (byte_immediate_operand (src, HImode)
1653 && reg_was_0 (insn, dest))
1656 return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0));
1660 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1661 AS2 (ldi,%B0,hi8(%1)));
1664 if (GET_CODE (src) == CONST_INT)
1666 if (src == const0_rtx) /* mov r,L */
1669 return (AS1 (clr,%A0) CR_TAB
1672 else if (src == const1_rtx)
1674 if (reg_was_0 (insn, dest))
1677 return AS1 (inc,%0 ; reg_was_0);
1681 return (AS1 (clr,%A0) CR_TAB
1682 AS1 (clr,%B0) CR_TAB
1685 else if (src == constm1_rtx)
1687 /* Immediate constants -1 to any register */
1688 if (reg_was_0 (insn, dest))
1691 return (AS1 (dec,%A0 ; reg_was_0) CR_TAB
1696 return (AS1 (clr,%0) CR_TAB
1697 AS1 (dec,%A0) CR_TAB
1702 int bit_nr = exact_log2 (INTVAL (src));
1706 if (reg_was_0 (insn, dest))
1710 output_asm_insn ("set ; reg_was_0", operands);
1716 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1717 AS1 (clr,%B0) CR_TAB
1721 avr_output_bld (operands, bit_nr);
1727 if ((INTVAL (src) & 0xff) == 0)
1730 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1731 AS1 (clr,%A0) CR_TAB
1732 AS2 (ldi,r31,hi8(%1)) CR_TAB
1733 AS2 (mov,%B0,r31) CR_TAB
1734 AS2 (mov,r31,__tmp_reg__));
1736 else if ((INTVAL (src) & 0xff00) == 0)
1739 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1740 AS2 (ldi,r31,lo8(%1)) CR_TAB
1741 AS2 (mov,%A0,r31) CR_TAB
1742 AS1 (clr,%B0) CR_TAB
1743 AS2 (mov,r31,__tmp_reg__));
1747 /* Last resort, equal to loading from memory. */
1749 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1750 AS2 (ldi,r31,lo8(%1)) CR_TAB
1751 AS2 (mov,%A0,r31) CR_TAB
1752 AS2 (ldi,r31,hi8(%1)) CR_TAB
1753 AS2 (mov,%B0,r31) CR_TAB
1754 AS2 (mov,r31,__tmp_reg__));
1756 else if (GET_CODE (src) == MEM)
1757 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1759 else if (GET_CODE (dest) == MEM)
1761 const char *template;
1763 if (src == const0_rtx)
1764 operands[1] = zero_reg_rtx;
1766 template = out_movhi_mr_r (insn, operands, real_l);
1769 output_asm_insn (template, operands);
1774 fatal_insn ("Invalid insn:", insn);
1779 out_movqi_r_mr (insn, op, l)
1782 int *l; /* instruction length */
1786 rtx x = XEXP (src, 0);
1792 if (CONSTANT_ADDRESS_P (x))
1794 if (io_address_p (x, 1))
1797 return AS2 (in,%0,%1-0x20);
1800 return AS2 (lds,%0,%1);
1802 /* memory access by reg+disp */
1803 else if (GET_CODE (x) == PLUS
1804 && REG_P (XEXP (x,0))
1805 && GET_CODE (XEXP (x,1)) == CONST_INT)
1807 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
1809 int disp = INTVAL (XEXP (x,1));
1810 if (REGNO (XEXP (x,0)) != REG_Y)
1811 fatal_insn ("Incorrect insn:",insn);
1813 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1814 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1815 AS2 (ldd,%0,Y+63) CR_TAB
1816 AS2 (sbiw,r28,%o1-63));
1818 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1819 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1820 AS2 (ld,%0,Y) CR_TAB
1821 AS2 (subi,r28,lo8(%o1)) CR_TAB
1822 AS2 (sbci,r29,hi8(%o1)));
1824 else if (REGNO (XEXP (x,0)) == REG_X)
1826 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1827 it but I have this situation with extremal optimizing options. */
1828 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
1829 || reg_unused_after (insn, XEXP (x,0)))
1830 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1833 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1834 AS2 (ld,%0,X) CR_TAB
1835 AS2 (sbiw,r26,%o1));
1838 return AS2 (ldd,%0,%1);
1841 return AS2 (ld,%0,%1);
1845 out_movhi_r_mr (insn, op, l)
1848 int *l; /* instruction length */
1852 rtx base = XEXP (src, 0);
1853 int reg_dest = true_regnum (dest);
1854 int reg_base = true_regnum (base);
1862 if (reg_dest == reg_base) /* R = (R) */
1865 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1866 AS2 (ld,%B0,%1) CR_TAB
1867 AS2 (mov,%A0,__tmp_reg__));
1869 else if (reg_base == REG_X) /* (R26) */
1871 if (reg_unused_after (insn, base))
1874 return (AS2 (ld,%A0,X+) CR_TAB
1878 return (AS2 (ld,%A0,X+) CR_TAB
1879 AS2 (ld,%B0,X) CR_TAB
1885 return (AS2 (ld,%A0,%1) CR_TAB
1886 AS2 (ldd,%B0,%1+1));
1889 else if (GET_CODE (base) == PLUS) /* (R + i) */
1891 int disp = INTVAL (XEXP (base, 1));
1892 int reg_base = true_regnum (XEXP (base, 0));
1894 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
1896 if (REGNO (XEXP (base, 0)) != REG_Y)
1897 fatal_insn ("Incorrect insn:",insn);
1899 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1900 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
1901 AS2 (ldd,%A0,Y+62) CR_TAB
1902 AS2 (ldd,%B0,Y+63) CR_TAB
1903 AS2 (sbiw,r28,%o1-62));
1905 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1906 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1907 AS2 (ld,%A0,Y) CR_TAB
1908 AS2 (ldd,%B0,Y+1) CR_TAB
1909 AS2 (subi,r28,lo8(%o1)) CR_TAB
1910 AS2 (sbci,r29,hi8(%o1)));
1912 if (reg_base == REG_X)
1914 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1915 it but I have this situation with extremal
1916 optimization options. */
1919 if (reg_base == reg_dest)
1920 return (AS2 (adiw,r26,%o1) CR_TAB
1921 AS2 (ld,__tmp_reg__,X+) CR_TAB
1922 AS2 (ld,%B0,X) CR_TAB
1923 AS2 (mov,%A0,__tmp_reg__));
1925 return (AS2 (adiw,r26,%o1) CR_TAB
1926 AS2 (ld,%A0,X+) CR_TAB
1927 AS2 (ld,%B0,X) CR_TAB
1928 AS2 (sbiw,r26,%o1+1));
1931 if (reg_base == reg_dest)
1934 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
1935 AS2 (ldd,%B0,%B1) CR_TAB
1936 AS2 (mov,%A0,__tmp_reg__));
1940 return (AS2 (ldd,%A0,%A1) CR_TAB
1943 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
1945 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1946 fatal_insn ("Incorrect insn:", insn);
1949 return (AS2 (ld,%B0,%1) CR_TAB
1952 else if (GET_CODE (base) == POST_INC) /* (R++) */
1954 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1955 fatal_insn ("Incorrect insn:", insn);
1958 return (AS2 (ld,%A0,%1) CR_TAB
1961 else if (CONSTANT_ADDRESS_P (base))
1963 if (io_address_p (base, 2))
1966 return (AS2 (in,%A0,%A1-0x20) CR_TAB
1967 AS2 (in,%B0,%B1-0x20));
1970 return (AS2 (lds,%A0,%A1) CR_TAB
1974 fatal_insn ("Unknown move insn:",insn);
1979 out_movsi_r_mr (insn, op, l)
1982 int *l; /* instruction length */
1986 rtx base = XEXP (src, 0);
1987 int reg_dest = true_regnum (dest);
1988 int reg_base = true_regnum (base);
1996 if (reg_base == REG_X) /* (R26) */
1998 if (reg_dest == REG_X)
1999 /* "ld r26,-X" is undefined */
2000 return *l=7, (AS2 (adiw,r26,3) CR_TAB
2001 AS2 (ld,r29,X) CR_TAB
2002 AS2 (ld,r28,-X) CR_TAB
2003 AS2 (ld,__tmp_reg__,-X) CR_TAB
2004 AS2 (sbiw,r26,1) CR_TAB
2005 AS2 (ld,r26,X) CR_TAB
2006 AS2 (mov,r27,__tmp_reg__));
2007 else if (reg_dest == REG_X - 2)
2008 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2009 AS2 (ld,%B0,X+) CR_TAB
2010 AS2 (ld,__tmp_reg__,X+) CR_TAB
2011 AS2 (ld,%D0,X) CR_TAB
2012 AS2 (mov,%C0,__tmp_reg__));
2013 else if (reg_unused_after (insn, base))
2014 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
2015 AS2 (ld,%B0,X+) CR_TAB
2016 AS2 (ld,%C0,X+) CR_TAB
2019 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2020 AS2 (ld,%B0,X+) CR_TAB
2021 AS2 (ld,%C0,X+) CR_TAB
2022 AS2 (ld,%D0,X) CR_TAB
2027 if (reg_dest == reg_base)
2028 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2029 AS2 (ldd,%C0,%1+2) CR_TAB
2030 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2031 AS2 (ld,%A0,%1) CR_TAB
2032 AS2 (mov,%B0,__tmp_reg__));
2033 else if (reg_base == reg_dest + 2)
2034 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2035 AS2 (ldd,%B0,%1+1) CR_TAB
2036 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2037 AS2 (ldd,%D0,%1+3) CR_TAB
2038 AS2 (mov,%C0,__tmp_reg__));
2040 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2041 AS2 (ldd,%B0,%1+1) CR_TAB
2042 AS2 (ldd,%C0,%1+2) CR_TAB
2043 AS2 (ldd,%D0,%1+3));
2046 else if (GET_CODE (base) == PLUS) /* (R + i) */
2048 int disp = INTVAL (XEXP (base, 1));
2050 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2052 if (REGNO (XEXP (base, 0)) != REG_Y)
2053 fatal_insn ("Incorrect insn:",insn);
2055 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2056 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2057 AS2 (ldd,%A0,Y+60) CR_TAB
2058 AS2 (ldd,%B0,Y+61) CR_TAB
2059 AS2 (ldd,%C0,Y+62) CR_TAB
2060 AS2 (ldd,%D0,Y+63) CR_TAB
2061 AS2 (sbiw,r28,%o1-60));
2063 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2064 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2065 AS2 (ld,%A0,Y) CR_TAB
2066 AS2 (ldd,%B0,Y+1) CR_TAB
2067 AS2 (ldd,%C0,Y+2) CR_TAB
2068 AS2 (ldd,%D0,Y+3) CR_TAB
2069 AS2 (subi,r28,lo8(%o1)) CR_TAB
2070 AS2 (sbci,r29,hi8(%o1)));
2073 reg_base = true_regnum (XEXP (base, 0));
2074 if (reg_base == REG_X)
2077 if (reg_dest == REG_X)
2080 /* "ld r26,-X" is undefined */
2081 return (AS2 (adiw,r26,%o1+3) CR_TAB
2082 AS2 (ld,r29,X) CR_TAB
2083 AS2 (ld,r28,-X) CR_TAB
2084 AS2 (ld,__tmp_reg__,-X) CR_TAB
2085 AS2 (sbiw,r26,1) CR_TAB
2086 AS2 (ld,r26,X) CR_TAB
2087 AS2 (mov,r27,__tmp_reg__));
2090 if (reg_dest == REG_X - 2)
2091 return (AS2 (adiw,r26,%o1) CR_TAB
2092 AS2 (ld,r24,X+) CR_TAB
2093 AS2 (ld,r25,X+) CR_TAB
2094 AS2 (ld,__tmp_reg__,X+) CR_TAB
2095 AS2 (ld,r27,X) CR_TAB
2096 AS2 (mov,r26,__tmp_reg__));
2098 return (AS2 (adiw,r26,%o1) CR_TAB
2099 AS2 (ld,%A0,X+) CR_TAB
2100 AS2 (ld,%B0,X+) CR_TAB
2101 AS2 (ld,%C0,X+) CR_TAB
2102 AS2 (ld,%D0,X) CR_TAB
2103 AS2 (sbiw,r26,%o1+3));
2105 if (reg_dest == reg_base)
2106 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2107 AS2 (ldd,%C0,%C1) CR_TAB
2108 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2109 AS2 (ldd,%A0,%A1) CR_TAB
2110 AS2 (mov,%B0,__tmp_reg__));
2111 else if (reg_dest == reg_base - 2)
2112 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2113 AS2 (ldd,%B0,%B1) CR_TAB
2114 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2115 AS2 (ldd,%D0,%D1) CR_TAB
2116 AS2 (mov,%C0,__tmp_reg__));
2117 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2118 AS2 (ldd,%B0,%B1) CR_TAB
2119 AS2 (ldd,%C0,%C1) CR_TAB
2122 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2123 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2124 AS2 (ld,%C0,%1) CR_TAB
2125 AS2 (ld,%B0,%1) CR_TAB
2127 else if (GET_CODE (base) == POST_INC) /* (R++) */
2128 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2129 AS2 (ld,%B0,%1) CR_TAB
2130 AS2 (ld,%C0,%1) CR_TAB
2132 else if (CONSTANT_ADDRESS_P (base))
2133 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2134 AS2 (lds,%B0,%B1) CR_TAB
2135 AS2 (lds,%C0,%C1) CR_TAB
2138 fatal_insn ("Unknown move insn:",insn);
2143 out_movsi_mr_r (insn, op, l)
2150 rtx base = XEXP (dest, 0);
2151 int reg_base = true_regnum (base);
2152 int reg_src = true_regnum (src);
2158 if (CONSTANT_ADDRESS_P (base))
2159 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2160 AS2 (sts,%B0,%B1) CR_TAB
2161 AS2 (sts,%C0,%C1) CR_TAB
2163 if (reg_base > 0) /* (r) */
2165 if (reg_base == REG_X) /* (R26) */
2167 if (reg_src == REG_X)
2169 /* "st X+,r26" is undefined */
2170 if (reg_unused_after (insn, base))
2171 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2172 AS2 (st,X,r26) CR_TAB
2173 AS2 (adiw,r26,1) CR_TAB
2174 AS2 (st,X+,__tmp_reg__) CR_TAB
2175 AS2 (st,X+,r28) CR_TAB
2178 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2179 AS2 (st,X,r26) CR_TAB
2180 AS2 (adiw,r26,1) CR_TAB
2181 AS2 (st,X+,__tmp_reg__) CR_TAB
2182 AS2 (st,X+,r28) CR_TAB
2183 AS2 (st,X,r29) CR_TAB
2186 else if (reg_base == reg_src + 2)
2188 if (reg_unused_after (insn, base))
2189 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2190 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2191 AS2 (st,%0+,%A1) CR_TAB
2192 AS2 (st,%0+,%B1) CR_TAB
2193 AS2 (st,%0+,__zero_reg__) CR_TAB
2194 AS2 (st,%0,__tmp_reg__) CR_TAB
2195 AS1 (clr,__zero_reg__));
2197 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2198 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2199 AS2 (st,%0+,%A1) CR_TAB
2200 AS2 (st,%0+,%B1) CR_TAB
2201 AS2 (st,%0+,__zero_reg__) CR_TAB
2202 AS2 (st,%0,__tmp_reg__) CR_TAB
2203 AS1 (clr,__zero_reg__) CR_TAB
2206 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2207 AS2 (st,%0+,%B1) CR_TAB
2208 AS2 (st,%0+,%C1) CR_TAB
2209 AS2 (st,%0,%D1) CR_TAB
2213 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2214 AS2 (std,%0+1,%B1) CR_TAB
2215 AS2 (std,%0+2,%C1) CR_TAB
2216 AS2 (std,%0+3,%D1));
2218 else if (GET_CODE (base) == PLUS) /* (R + i) */
2220 int disp = INTVAL (XEXP (base, 1));
2221 reg_base = REGNO (XEXP (base, 0));
2222 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2224 if (reg_base != REG_Y)
2225 fatal_insn ("Incorrect insn:",insn);
2227 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2228 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2229 AS2 (std,Y+60,%A1) CR_TAB
2230 AS2 (std,Y+61,%B1) CR_TAB
2231 AS2 (std,Y+62,%C1) CR_TAB
2232 AS2 (std,Y+63,%D1) CR_TAB
2233 AS2 (sbiw,r28,%o0-60));
2235 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2236 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2237 AS2 (st,Y,%A1) CR_TAB
2238 AS2 (std,Y+1,%B1) CR_TAB
2239 AS2 (std,Y+2,%C1) CR_TAB
2240 AS2 (std,Y+3,%D1) CR_TAB
2241 AS2 (subi,r28,lo8(%o0)) CR_TAB
2242 AS2 (sbci,r29,hi8(%o0)));
2244 if (reg_base == REG_X)
2247 if (reg_src == REG_X)
2250 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2251 AS2 (mov,__zero_reg__,r27) CR_TAB
2252 AS2 (adiw,r26,%o0) CR_TAB
2253 AS2 (st,X+,__tmp_reg__) CR_TAB
2254 AS2 (st,X+,__zero_reg__) CR_TAB
2255 AS2 (st,X+,r28) CR_TAB
2256 AS2 (st,X,r29) CR_TAB
2257 AS1 (clr,__zero_reg__) CR_TAB
2258 AS2 (sbiw,r26,%o0+3));
2260 else if (reg_src == REG_X - 2)
2263 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2264 AS2 (mov,__zero_reg__,r27) CR_TAB
2265 AS2 (adiw,r26,%o0) CR_TAB
2266 AS2 (st,X+,r24) CR_TAB
2267 AS2 (st,X+,r25) CR_TAB
2268 AS2 (st,X+,__tmp_reg__) CR_TAB
2269 AS2 (st,X,__zero_reg__) CR_TAB
2270 AS1 (clr,__zero_reg__) CR_TAB
2271 AS2 (sbiw,r26,%o0+3));
2274 return (AS2 (adiw,r26,%o0) CR_TAB
2275 AS2 (st,X+,%A1) CR_TAB
2276 AS2 (st,X+,%B1) CR_TAB
2277 AS2 (st,X+,%C1) CR_TAB
2278 AS2 (st,X,%D1) CR_TAB
2279 AS2 (sbiw,r26,%o0+3));
2281 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2282 AS2 (std,%B0,%B1) CR_TAB
2283 AS2 (std,%C0,%C1) CR_TAB
2286 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2287 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2288 AS2 (st,%0,%C1) CR_TAB
2289 AS2 (st,%0,%B1) CR_TAB
2291 else if (GET_CODE (base) == POST_INC) /* (R++) */
2292 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2293 AS2 (st,%0,%B1) CR_TAB
2294 AS2 (st,%0,%C1) CR_TAB
2296 fatal_insn ("Unknown move insn:",insn);
2301 output_movsisf(insn, operands, l)
2307 rtx dest = operands[0];
2308 rtx src = operands[1];
2314 if (register_operand (dest, VOIDmode))
2316 if (register_operand (src, VOIDmode)) /* mov r,r */
2318 if (true_regnum (dest) > true_regnum (src))
2323 return (AS2 (movw,%C0,%C1) CR_TAB
2324 AS2 (movw,%A0,%A1));
2327 return (AS2 (mov,%D0,%D1) CR_TAB
2328 AS2 (mov,%C0,%C1) CR_TAB
2329 AS2 (mov,%B0,%B1) CR_TAB
2337 return (AS2 (movw,%A0,%A1) CR_TAB
2338 AS2 (movw,%C0,%C1));
2341 return (AS2 (mov,%A0,%A1) CR_TAB
2342 AS2 (mov,%B0,%B1) CR_TAB
2343 AS2 (mov,%C0,%C1) CR_TAB
2347 else if (CONSTANT_P (src))
2349 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2351 if (byte_immediate_operand (src, SImode)
2352 && reg_was_0 (insn, dest))
2355 return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0));
2359 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2360 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2361 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2362 AS2 (ldi,%D0,hhi8(%1)));
2365 if (GET_CODE (src) == CONST_INT)
2367 const char *clr_op0 =
2368 AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
2369 AS1 (clr,%B0) CR_TAB
2371 : (AS1 (clr,%A0) CR_TAB
2372 AS1 (clr,%B0) CR_TAB
2373 AS1 (clr,%C0) CR_TAB
2376 if (src == const0_rtx) /* mov r,L */
2378 *l = AVR_ENHANCED ? 3 : 4;
2381 else if (src == const1_rtx)
2383 if (reg_was_0 (insn, dest))
2386 return AS1 (inc,%A0 ; reg_was_0);
2389 output_asm_insn (clr_op0, operands);
2390 *l = AVR_ENHANCED ? 4 : 5;
2391 return AS1 (inc,%A0);
2393 else if (src == constm1_rtx)
2395 /* Immediate constants -1 to any register */
2396 if (reg_was_0 (insn, dest))
2401 return (AS1 (dec,%A0) CR_TAB
2402 AS1 (dec,%B0) CR_TAB
2403 AS2 (movw,%C0,%A0));
2406 return (AS1 (dec,%D0 ; reg_was_0) CR_TAB
2407 AS1 (dec,%C0) CR_TAB
2408 AS1 (dec,%B0) CR_TAB
2414 return (AS1 (clr,%A0) CR_TAB
2415 AS1 (dec,%A0) CR_TAB
2416 AS2 (mov,%B0,%A0) CR_TAB
2417 AS2 (movw,%C0,%A0));
2420 return (AS1 (clr,%A0) CR_TAB
2421 AS1 (dec,%A0) CR_TAB
2422 AS2 (mov,%B0,%A0) CR_TAB
2423 AS2 (mov,%C0,%A0) CR_TAB
2428 int bit_nr = exact_log2 (INTVAL (src));
2432 if (reg_was_0 (insn, dest))
2436 output_asm_insn ("set ; reg_was_0", operands);
2440 *l = AVR_ENHANCED ? 5 : 6;
2443 output_asm_insn (clr_op0, operands);
2444 output_asm_insn ("set", operands);
2448 avr_output_bld (operands, bit_nr);
2455 /* Last resort, better than loading from memory. */
2457 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2458 AS2 (ldi,r31,lo8(%1)) CR_TAB
2459 AS2 (mov,%A0,r31) CR_TAB
2460 AS2 (ldi,r31,hi8(%1)) CR_TAB
2461 AS2 (mov,%B0,r31) CR_TAB
2462 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2463 AS2 (mov,%C0,r31) CR_TAB
2464 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2465 AS2 (mov,%D0,r31) CR_TAB
2466 AS2 (mov,r31,__tmp_reg__));
2468 else if (GET_CODE (src) == MEM)
2469 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2471 else if (GET_CODE (dest) == MEM)
2473 const char *template;
2475 if (src == const0_rtx)
2476 operands[1] = zero_reg_rtx;
2478 template = out_movsi_mr_r (insn, operands, real_l);
2481 output_asm_insn (template, operands);
2486 fatal_insn ("Invalid insn:", insn);
2491 out_movqi_mr_r (insn, op, l)
2494 int *l; /* instruction length */
2498 rtx x = XEXP (dest, 0);
2504 if (CONSTANT_ADDRESS_P (x))
2506 if (io_address_p (x, 1))
2509 return AS2 (out,%0-0x20,%1);
2512 return AS2 (sts,%0,%1);
2514 /* memory access by reg+disp */
2515 else if (GET_CODE (x) == PLUS
2516 && REG_P (XEXP (x,0))
2517 && GET_CODE (XEXP (x,1)) == CONST_INT)
2519 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
2521 int disp = INTVAL (XEXP (x,1));
2522 if (REGNO (XEXP (x,0)) != REG_Y)
2523 fatal_insn ("Incorrect insn:",insn);
2525 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2526 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2527 AS2 (std,Y+63,%1) CR_TAB
2528 AS2 (sbiw,r28,%o0-63));
2530 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2531 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2532 AS2 (st,Y,%1) CR_TAB
2533 AS2 (subi,r28,lo8(%o0)) CR_TAB
2534 AS2 (sbci,r29,hi8(%o0)));
2536 else if (REGNO (XEXP (x,0)) == REG_X)
2538 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
2540 if (reg_unused_after (insn, XEXP (x,0)))
2541 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2542 AS2 (adiw,r26,%o0) CR_TAB
2543 AS2 (st,X,__tmp_reg__));
2545 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2546 AS2 (adiw,r26,%o0) CR_TAB
2547 AS2 (st,X,__tmp_reg__) CR_TAB
2548 AS2 (sbiw,r26,%o0));
2552 if (reg_unused_after (insn, XEXP (x,0)))
2553 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2556 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2557 AS2 (st,X,%1) CR_TAB
2558 AS2 (sbiw,r26,%o0));
2562 return AS2 (std,%0,%1);
2565 return AS2 (st,%0,%1);
2569 out_movhi_mr_r (insn, op, l)
2576 rtx base = XEXP (dest, 0);
2577 int reg_base = true_regnum (base);
2578 int reg_src = true_regnum (src);
2582 if (CONSTANT_ADDRESS_P (base))
2584 if (io_address_p (base, 2))
2587 return (AS2 (out,%B0-0x20,%B1) CR_TAB
2588 AS2 (out,%A0-0x20,%A1));
2590 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2595 if (reg_base == REG_X)
2597 if (reg_src == REG_X)
2599 /* "st X+,r26" is undefined */
2600 if (reg_unused_after (insn, src))
2601 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2602 AS2 (st,X,r26) CR_TAB
2603 AS2 (adiw,r26,1) CR_TAB
2604 AS2 (st,X,__tmp_reg__));
2606 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2607 AS2 (st,X,r26) CR_TAB
2608 AS2 (adiw,r26,1) CR_TAB
2609 AS2 (st,X,__tmp_reg__) CR_TAB
2614 if (reg_unused_after (insn, base))
2615 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2618 return *l=3, (AS2 (st ,X+,%A1) CR_TAB
2619 AS2 (st ,X,%B1) CR_TAB
2624 return *l=2, (AS2 (st ,%0,%A1) CR_TAB
2625 AS2 (std,%0+1,%B1));
2627 else if (GET_CODE (base) == PLUS)
2629 int disp = INTVAL (XEXP (base, 1));
2630 reg_base = REGNO (XEXP (base, 0));
2631 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2633 if (reg_base != REG_Y)
2634 fatal_insn ("Incorrect insn:",insn);
2636 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2637 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
2638 AS2 (std,Y+62,%A1) CR_TAB
2639 AS2 (std,Y+63,%B1) CR_TAB
2640 AS2 (sbiw,r28,%o0-62));
2642 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2643 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2644 AS2 (st,Y,%A1) CR_TAB
2645 AS2 (std,Y+1,%B1) CR_TAB
2646 AS2 (subi,r28,lo8(%o0)) CR_TAB
2647 AS2 (sbci,r29,hi8(%o0)));
2649 if (reg_base == REG_X)
2652 if (reg_src == REG_X)
2655 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2656 AS2 (mov,__zero_reg__,r27) CR_TAB
2657 AS2 (adiw,r26,%o0) CR_TAB
2658 AS2 (st,X+,__tmp_reg__) CR_TAB
2659 AS2 (st,X,__zero_reg__) CR_TAB
2660 AS1 (clr,__zero_reg__) CR_TAB
2661 AS2 (sbiw,r26,%o0+1));
2664 return (AS2 (adiw,r26,%o0) CR_TAB
2665 AS2 (st,X+,%A1) CR_TAB
2666 AS2 (st,X,%B1) CR_TAB
2667 AS2 (sbiw,r26,%o0+1));
2669 return *l=2, (AS2 (std,%A0,%A1) CR_TAB
2672 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2673 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2675 else if (GET_CODE (base) == POST_INC) /* (R++) */
2676 return *l=2, (AS2 (st,%0,%A1) CR_TAB
2678 fatal_insn ("Unknown move insn:",insn);
2682 /* Return 1 if frame pointer for current function required */
2685 frame_pointer_required_p ()
2687 return (current_function_calls_alloca
2688 || current_function_args_info.nregs == 0
2689 || current_function_varargs
2690 || get_frame_size () > 0);
2693 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2696 compare_condition (insn)
2699 rtx next = next_real_insn (insn);
2700 RTX_CODE cond = UNKNOWN;
2701 if (next && GET_CODE (next) == JUMP_INSN)
2703 rtx pat = PATTERN (next);
2704 rtx src = SET_SRC (pat);
2705 rtx t = XEXP (src, 0);
2706 cond = GET_CODE (t);
2711 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2714 compare_sign_p (insn)
2717 RTX_CODE cond = compare_condition (insn);
2718 return (cond == GE || cond == LT);
2721 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2722 that needs to be swapped (GT, GTU, LE, LEU). */
2725 compare_diff_p (insn)
2728 RTX_CODE cond = compare_condition (insn);
2729 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2732 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2738 RTX_CODE cond = compare_condition (insn);
2739 return (cond == EQ || cond == NE);
2743 /* Output test instruction for HImode */
2750 if (compare_sign_p (insn))
2753 return AS1 (tst,%B0);
2755 if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2756 && compare_eq_p (insn))
2758 /* faster than sbiw if we can clobber the operand */
2760 return AS2 (or,%A0,%B0);
2762 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2765 return AS2 (sbiw,%0,0);
2768 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2769 AS2 (cpc,%B0,__zero_reg__));
2773 /* Output test instruction for SImode */
2780 if (compare_sign_p (insn))
2783 return AS1 (tst,%D0);
2785 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2788 return (AS2 (sbiw,%A0,0) CR_TAB
2789 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2790 AS2 (cpc,%D0,__zero_reg__));
2793 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2794 AS2 (cpc,%B0,__zero_reg__) CR_TAB
2795 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2796 AS2 (cpc,%D0,__zero_reg__));
2800 /* Generate asm equivalent for various shifts.
2801 Shift count is a CONST_INT, MEM or REG.
2802 This only handles cases that are not already
2803 carefully hand-optimized in ?sh??i3_out. */
2806 out_shift_with_cnt (template, insn, operands, len, t_len)
2807 const char *template;
2811 int t_len; /* Length of template. */
2815 int second_label = 1;
2816 int saved_in_tmp = 0;
2817 int use_zero_reg = 0;
2819 op[0] = operands[0];
2820 op[1] = operands[1];
2821 op[2] = operands[2];
2822 op[3] = operands[3];
2828 if (GET_CODE (operands[2]) == CONST_INT)
2830 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2831 int count = INTVAL (operands[2]);
2832 int max_len = 10; /* If larger than this, always use a loop. */
2834 if (count < 8 && !scratch)
2838 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2840 if (t_len * count <= max_len)
2842 /* Output shifts inline with no loop - faster. */
2844 *len = t_len * count;
2848 output_asm_insn (template, op);
2857 strcat (str, AS2 (ldi,%3,%2));
2859 else if (use_zero_reg)
2861 /* Hack to save one word: use __zero_reg__ as loop counter.
2862 Set one bit, then shift in a loop until it is 0 again. */
2864 op[3] = zero_reg_rtx;
2868 strcat (str, ("set" CR_TAB
2869 AS2 (bld,%3,%2-1)));
2873 /* No scratch register available, use one from LD_REGS (saved in
2874 __tmp_reg__) that doesn't overlap with registers to shift. */
2876 op[3] = gen_rtx (REG, QImode,
2877 ((true_regnum (operands[0]) - 1) & 15) + 16);
2878 op[4] = tmp_reg_rtx;
2882 *len = 3; /* Includes "mov %3,%4" after the loop. */
2884 strcat (str, (AS2 (mov,%4,%3) CR_TAB
2890 else if (GET_CODE (operands[2]) == MEM)
2894 op[3] = op_mov[0] = tmp_reg_rtx;
2898 out_movqi_r_mr (insn, op_mov, len);
2900 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
2902 else if (register_operand (operands[2], QImode))
2904 if (reg_unused_after (insn, operands[2]))
2908 op[3] = tmp_reg_rtx;
2910 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
2914 fatal_insn ("Bad shift insn:", insn);
2921 strcat (str, AS1 (rjmp,2f));
2925 *len += t_len + 2; /* template + dec + brXX */
2928 strcat (str, "\n1:\t");
2929 strcat (str, template);
2930 strcat (str, second_label ? "\n2:\t" : "\n\t");
2931 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
2932 strcat (str, CR_TAB);
2933 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
2935 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
2936 output_asm_insn (str, op);
2941 /* 8bit shift left ((char)x << i) */
2944 ashlqi3_out (insn, operands, len)
2947 int *len; /* insn length (may be NULL) */
2949 if (GET_CODE (operands[2]) == CONST_INT)
2956 switch (INTVAL (operands[2]))
2960 return AS1 (clr,%0);
2964 return AS1 (lsl,%0);
2968 return (AS1 (lsl,%0) CR_TAB
2973 return (AS1 (lsl,%0) CR_TAB
2978 if (test_hard_reg_class (LD_REGS, operands[0]))
2981 return (AS1 (swap,%0) CR_TAB
2982 AS2 (andi,%0,0xf0));
2985 return (AS1 (lsl,%0) CR_TAB
2991 if (test_hard_reg_class (LD_REGS, operands[0]))
2994 return (AS1 (swap,%0) CR_TAB
2996 AS2 (andi,%0,0xe0));
2999 return (AS1 (lsl,%0) CR_TAB
3006 if (test_hard_reg_class (LD_REGS, operands[0]))
3009 return (AS1 (swap,%0) CR_TAB
3012 AS2 (andi,%0,0xc0));
3015 return (AS1 (lsl,%0) CR_TAB
3024 return (AS1 (ror,%0) CR_TAB
3029 else if (CONSTANT_P (operands[2]))
3030 fatal_insn ("Internal compiler bug.\nIncorrect shift:", insn);
3032 out_shift_with_cnt (AS1 (lsl,%0),
3033 insn, operands, len, 1);
3038 /* 16bit shift left ((short)x << i) */
3041 ashlhi3_out (insn, operands, len)
3046 if (GET_CODE (operands[2]) == CONST_INT)
3048 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3049 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3056 switch (INTVAL (operands[2]))
3059 if (optimize_size && scratch)
3064 return (AS1 (swap,%A0) CR_TAB
3065 AS1 (swap,%B0) CR_TAB
3066 AS2 (andi,%B0,0xf0) CR_TAB
3067 AS2 (eor,%B0,%A0) CR_TAB
3068 AS2 (andi,%A0,0xf0) CR_TAB
3074 return (AS1 (swap,%A0) CR_TAB
3075 AS1 (swap,%B0) CR_TAB
3076 AS2 (ldi,%3,0xf0) CR_TAB
3077 AS2 (and,%B0,%3) CR_TAB
3078 AS2 (eor,%B0,%A0) CR_TAB
3079 AS2 (and,%A0,%3) CR_TAB
3082 break; /* optimize_size ? 6 : 8 */
3086 break; /* scratch ? 5 : 6 */
3090 return (AS1 (lsl,%A0) CR_TAB
3091 AS1 (rol,%B0) CR_TAB
3092 AS1 (swap,%A0) CR_TAB
3093 AS1 (swap,%B0) CR_TAB
3094 AS2 (andi,%B0,0xf0) CR_TAB
3095 AS2 (eor,%B0,%A0) CR_TAB
3096 AS2 (andi,%A0,0xf0) CR_TAB
3102 return (AS1 (lsl,%A0) CR_TAB
3103 AS1 (rol,%B0) CR_TAB
3104 AS1 (swap,%A0) CR_TAB
3105 AS1 (swap,%B0) CR_TAB
3106 AS2 (ldi,%3,0xf0) CR_TAB
3107 AS2 (and,%B0,%3) CR_TAB
3108 AS2 (eor,%B0,%A0) CR_TAB
3109 AS2 (and,%A0,%3) CR_TAB
3116 break; /* scratch ? 5 : 6 */
3118 return (AS1 (clr,__tmp_reg__) CR_TAB
3119 AS1 (lsr,%B0) CR_TAB
3120 AS1 (ror,%A0) CR_TAB
3121 AS1 (ror,__tmp_reg__) CR_TAB
3122 AS1 (lsr,%B0) CR_TAB
3123 AS1 (ror,%A0) CR_TAB
3124 AS1 (ror,__tmp_reg__) CR_TAB
3125 AS2 (mov,%B0,%A0) CR_TAB
3126 AS2 (mov,%A0,__tmp_reg__));
3130 return (AS1 (lsr,%B0) CR_TAB
3131 AS2 (mov,%B0,%A0) CR_TAB
3132 AS1 (clr,%A0) CR_TAB
3133 AS1 (ror,%B0) CR_TAB
3137 if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
3138 return *len = 1, AS1 (clr,%A0);
3140 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3145 return (AS2 (mov,%B0,%A0) CR_TAB
3146 AS1 (clr,%A0) CR_TAB
3151 return (AS2 (mov,%B0,%A0) CR_TAB
3152 AS1 (clr,%A0) CR_TAB
3153 AS1 (lsl,%B0) CR_TAB
3158 return (AS2 (mov,%B0,%A0) CR_TAB
3159 AS1 (clr,%A0) CR_TAB
3160 AS1 (lsl,%B0) CR_TAB
3161 AS1 (lsl,%B0) CR_TAB
3168 return (AS2 (mov,%B0,%A0) CR_TAB
3169 AS1 (clr,%A0) CR_TAB
3170 AS1 (swap,%B0) CR_TAB
3171 AS2 (andi,%B0,0xf0));
3176 return (AS2 (mov,%B0,%A0) CR_TAB
3177 AS1 (clr,%A0) CR_TAB
3178 AS1 (swap,%B0) CR_TAB
3179 AS2 (ldi,%3,0xf0) CR_TAB
3183 return (AS2 (mov,%B0,%A0) CR_TAB
3184 AS1 (clr,%A0) CR_TAB
3185 AS1 (lsl,%B0) CR_TAB
3186 AS1 (lsl,%B0) CR_TAB
3187 AS1 (lsl,%B0) CR_TAB
3194 return (AS2 (mov,%B0,%A0) CR_TAB
3195 AS1 (clr,%A0) CR_TAB
3196 AS1 (swap,%B0) CR_TAB
3197 AS1 (lsl,%B0) CR_TAB
3198 AS2 (andi,%B0,0xe0));
3200 if (AVR_ENHANCED && scratch)
3203 return (AS2 (ldi,%3,0x20) CR_TAB
3204 AS2 (mul,%A0,%3) CR_TAB
3205 AS2 (mov,%B0,r0) CR_TAB
3206 AS1 (clr,%A0) CR_TAB
3207 AS1 (clr,__zero_reg__));
3209 if (optimize_size && scratch)
3214 return (AS2 (mov,%B0,%A0) CR_TAB
3215 AS1 (clr,%A0) CR_TAB
3216 AS1 (swap,%B0) CR_TAB
3217 AS1 (lsl,%B0) CR_TAB
3218 AS2 (ldi,%3,0xe0) CR_TAB
3224 return ("set" CR_TAB
3225 AS2 (bld,r1,5) CR_TAB
3226 AS2 (mul,%A0,r1) CR_TAB
3227 AS2 (mov,%B0,r0) CR_TAB
3228 AS1 (clr,%A0) CR_TAB
3229 AS1 (clr,__zero_reg__));
3232 return (AS2 (mov,%B0,%A0) CR_TAB
3233 AS1 (clr,%A0) CR_TAB
3234 AS1 (lsl,%B0) CR_TAB
3235 AS1 (lsl,%B0) CR_TAB
3236 AS1 (lsl,%B0) CR_TAB
3237 AS1 (lsl,%B0) CR_TAB
3241 if (AVR_ENHANCED && ldi_ok)
3244 return (AS2 (ldi,%B0,0x40) CR_TAB
3245 AS2 (mul,%A0,%B0) CR_TAB
3246 AS2 (mov,%B0,r0) CR_TAB
3247 AS1 (clr,%A0) CR_TAB
3248 AS1 (clr,__zero_reg__));
3250 if (AVR_ENHANCED && scratch)
3253 return (AS2 (ldi,%3,0x40) CR_TAB
3254 AS2 (mul,%A0,%3) CR_TAB
3255 AS2 (mov,%B0,r0) CR_TAB
3256 AS1 (clr,%A0) CR_TAB
3257 AS1 (clr,__zero_reg__));
3259 if (optimize_size && ldi_ok)
3262 return (AS2 (mov,%B0,%A0) CR_TAB
3263 AS2 (ldi,%A0,6) "\n1:\t"
3264 AS1 (lsl,%B0) CR_TAB
3265 AS1 (dec,%A0) CR_TAB
3268 if (optimize_size && scratch)
3271 return (AS1 (clr,%B0) CR_TAB
3272 AS1 (lsr,%A0) CR_TAB
3273 AS1 (ror,%B0) CR_TAB
3274 AS1 (lsr,%A0) CR_TAB
3275 AS1 (ror,%B0) CR_TAB
3280 return (AS1 (clr,%B0) CR_TAB
3281 AS1 (lsr,%A0) CR_TAB
3282 AS1 (ror,%B0) CR_TAB
3287 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3289 insn, operands, len, 2);
3294 /* 32bit shift left ((long)x << i) */
3297 ashlsi3_out (insn, operands, len)
3302 if (GET_CODE (operands[2]) == CONST_INT)
3310 switch (INTVAL (operands[2]))
3314 int reg0 = true_regnum (operands[0]);
3315 int reg1 = true_regnum (operands[1]);
3318 return (AS2 (mov,%D0,%C1) CR_TAB
3319 AS2 (mov,%C0,%B1) CR_TAB
3320 AS2 (mov,%B0,%A1) CR_TAB
3322 else if (reg0 + 1 == reg1)
3325 return AS1 (clr,%A0);
3328 return (AS1 (clr,%A0) CR_TAB
3329 AS2 (mov,%B0,%A1) CR_TAB
3330 AS2 (mov,%C0,%B1) CR_TAB
3336 int reg0 = true_regnum (operands[0]);
3337 int reg1 = true_regnum (operands[1]);
3339 if (AVR_ENHANCED && (reg0 + 2 != reg1))
3342 return (AS2 (movw,%C0,%A1) CR_TAB
3343 AS1 (clr,%B0) CR_TAB
3346 if (reg0 + 1 >= reg1)
3347 return (AS2 (mov,%D0,%B1) CR_TAB
3348 AS2 (mov,%C0,%A1) CR_TAB
3349 AS1 (clr,%B0) CR_TAB
3351 if (reg0 + 2 == reg1)
3354 return (AS1 (clr,%B0) CR_TAB
3358 return (AS2 (mov,%C0,%A1) CR_TAB
3359 AS2 (mov,%D0,%B1) CR_TAB
3360 AS1 (clr,%B0) CR_TAB
3366 if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
3367 return (AS2 (mov,%D0,%A1) CR_TAB
3368 AS1 (clr,%C0) CR_TAB
3369 AS1 (clr,%B0) CR_TAB
3374 return (AS1 (clr,%C0) CR_TAB
3375 AS1 (clr,%B0) CR_TAB
3381 return (AS1 (clr,%D0) CR_TAB
3382 AS1 (lsr,%A0) CR_TAB
3383 AS1 (ror,%D0) CR_TAB
3384 AS1 (clr,%C0) CR_TAB
3385 AS1 (clr,%B0) CR_TAB
3390 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3391 AS1 (rol,%B0) CR_TAB
3392 AS1 (rol,%C0) CR_TAB
3394 insn, operands, len, 4);
3398 /* 8bit arithmetic shift right ((signed char)x >> i) */
3401 ashrqi3_out (insn, operands, len)
3404 int *len; /* insn length */
3406 if (GET_CODE (operands[2]) == CONST_INT)
3413 switch (INTVAL (operands[2]))
3417 return AS1 (asr,%0);
3421 return (AS1 (asr,%0) CR_TAB
3426 return (AS1 (asr,%0) CR_TAB
3432 return (AS1 (asr,%0) CR_TAB
3439 return (AS1 (asr,%0) CR_TAB
3447 return (AS2 (bst,%0,6) CR_TAB
3449 AS2 (sbc,%0,%0) CR_TAB
3455 return (AS1 (lsl,%0) CR_TAB
3459 else if (CONSTANT_P (operands[2]))
3460 fatal_insn ("Internal compiler bug.\nIncorrect shift:", insn);
3462 out_shift_with_cnt (AS1 (asr,%0),
3463 insn, operands, len, 1);
3468 /* 16bit arithmetic shift right ((signed short)x >> i) */
3471 ashrhi3_out (insn, operands, len)
3476 if (GET_CODE (operands[2]) == CONST_INT)
3478 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3479 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3486 switch (INTVAL (operands[2]))
3490 /* XXX try to optimize this too? */
3495 break; /* scratch ? 5 : 6 */
3497 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3498 AS2 (mov,%A0,%B0) CR_TAB
3499 AS1 (lsl,__tmp_reg__) CR_TAB
3500 AS1 (rol,%A0) CR_TAB
3501 AS2 (sbc,%B0,%B0) CR_TAB
3502 AS1 (lsl,__tmp_reg__) CR_TAB
3503 AS1 (rol,%A0) CR_TAB
3508 return (AS1 (lsl,%A0) CR_TAB
3509 AS2 (mov,%A0,%B0) CR_TAB
3510 AS1 (rol,%A0) CR_TAB
3515 int reg0 = true_regnum (operands[0]);
3516 int reg1 = true_regnum (operands[1]);
3519 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3520 AS1 (lsl,%B0) CR_TAB
3522 else if (reg0 == reg1 + 1)
3523 return *len = 3, (AS1 (clr,%B0) CR_TAB
3524 AS2 (sbrc,%A0,7) CR_TAB
3527 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3528 AS1 (clr,%B0) CR_TAB
3529 AS2 (sbrc,%A0,7) CR_TAB
3535 return (AS2 (mov,%A0,%B0) CR_TAB
3536 AS1 (lsl,%B0) CR_TAB
3537 AS2 (sbc,%B0,%B0) CR_TAB
3542 return (AS2 (mov,%A0,%B0) CR_TAB
3543 AS1 (lsl,%B0) CR_TAB
3544 AS2 (sbc,%B0,%B0) CR_TAB
3545 AS1 (asr,%A0) CR_TAB
3549 if (AVR_ENHANCED && ldi_ok)
3552 return (AS2 (ldi,%A0,0x20) CR_TAB
3553 AS2 (muls,%B0,%A0) CR_TAB
3554 AS2 (mov,%A0,r1) CR_TAB
3555 AS2 (sbc,%B0,%B0) CR_TAB
3556 AS1 (clr,__zero_reg__));
3558 if (optimize_size && scratch)
3561 return (AS2 (mov,%A0,%B0) CR_TAB
3562 AS1 (lsl,%B0) CR_TAB
3563 AS2 (sbc,%B0,%B0) CR_TAB
3564 AS1 (asr,%A0) CR_TAB
3565 AS1 (asr,%A0) CR_TAB
3569 if (AVR_ENHANCED && ldi_ok)
3572 return (AS2 (ldi,%A0,0x10) CR_TAB
3573 AS2 (muls,%B0,%A0) CR_TAB
3574 AS2 (mov,%A0,r1) CR_TAB
3575 AS2 (sbc,%B0,%B0) CR_TAB
3576 AS1 (clr,__zero_reg__));
3578 if (optimize_size && scratch)
3581 return (AS2 (mov,%A0,%B0) CR_TAB
3582 AS1 (lsl,%B0) CR_TAB
3583 AS2 (sbc,%B0,%B0) CR_TAB
3584 AS1 (asr,%A0) CR_TAB
3585 AS1 (asr,%A0) CR_TAB
3586 AS1 (asr,%A0) CR_TAB
3590 if (AVR_ENHANCED && ldi_ok)
3593 return (AS2 (ldi,%A0,0x08) CR_TAB
3594 AS2 (muls,%B0,%A0) CR_TAB
3595 AS2 (mov,%A0,r1) CR_TAB
3596 AS2 (sbc,%B0,%B0) CR_TAB
3597 AS1 (clr,__zero_reg__));
3600 break; /* scratch ? 5 : 7 */
3602 return (AS2 (mov,%A0,%B0) CR_TAB
3603 AS1 (lsl,%B0) CR_TAB
3604 AS2 (sbc,%B0,%B0) CR_TAB
3605 AS1 (asr,%A0) CR_TAB
3606 AS1 (asr,%A0) CR_TAB
3607 AS1 (asr,%A0) CR_TAB
3608 AS1 (asr,%A0) CR_TAB
3613 return (AS1 (lsl,%B0) CR_TAB
3614 AS2 (sbc,%A0,%A0) CR_TAB
3615 AS1 (lsl,%B0) CR_TAB
3616 AS2 (mov,%B0,%A0) CR_TAB
3620 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3621 AS2 (sbc,%A0,%A0) CR_TAB
3626 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3628 insn, operands, len, 2);
3633 /* 32bit arithmetic shift right ((signed long)x >> i) */
3636 ashrsi3_out (insn, operands, len)
3641 if (GET_CODE (operands[2]) == CONST_INT)
3649 switch (INTVAL (operands[2]))
3653 int reg0 = true_regnum (operands[0]);
3654 int reg1 = true_regnum (operands[1]);
3657 return (AS2 (mov,%A0,%B1) CR_TAB
3658 AS2 (mov,%B0,%C1) CR_TAB
3659 AS2 (mov,%C0,%D1) CR_TAB
3660 AS1 (clr,%D0) CR_TAB
3661 AS2 (sbrc,%C0,7) CR_TAB
3663 else if (reg0 == reg1 + 1)
3666 return (AS1 (clr,%D0) CR_TAB
3667 AS2 (sbrc,%C0,7) CR_TAB
3671 return (AS1 (clr,%D0) CR_TAB
3672 AS2 (sbrc,%D1,7) CR_TAB
3673 AS1 (dec,%D0) CR_TAB
3674 AS2 (mov,%C0,%D1) CR_TAB
3675 AS2 (mov,%B0,%C1) CR_TAB
3681 int reg0 = true_regnum (operands[0]);
3682 int reg1 = true_regnum (operands[1]);
3684 if (AVR_ENHANCED && (reg0 != reg1 + 2))
3687 return (AS2 (movw,%A0,%C1) CR_TAB
3688 AS1 (clr,%D0) CR_TAB
3689 AS2 (sbrc,%B0,7) CR_TAB
3690 AS1 (com,%D0) CR_TAB
3693 if (reg0 <= reg1 + 1)
3694 return (AS2 (mov,%A0,%C1) CR_TAB
3695 AS2 (mov,%B0,%D1) CR_TAB
3696 AS1 (clr,%D0) CR_TAB
3697 AS2 (sbrc,%B0,7) CR_TAB
3698 AS1 (com,%D0) CR_TAB
3700 else if (reg0 == reg1 + 2)
3701 return *len = 4, (AS1 (clr,%D0) CR_TAB
3702 AS2 (sbrc,%B0,7) CR_TAB
3703 AS1 (com,%D0) CR_TAB
3706 return (AS2 (mov,%B0,%D1) CR_TAB
3707 AS2 (mov,%A0,%C1) CR_TAB
3708 AS1 (clr,%D0) CR_TAB
3709 AS2 (sbrc,%B0,7) CR_TAB
3710 AS1 (com,%D0) CR_TAB
3715 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
3716 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3717 AS1 (clr,%D0) CR_TAB
3718 AS2 (sbrc,%A0,7) CR_TAB
3719 AS1 (com,%D0) CR_TAB
3720 AS2 (mov,%B0,%D0) CR_TAB
3723 return *len = 5, (AS1 (clr,%D0) CR_TAB
3724 AS2 (sbrc,%A0,7) CR_TAB
3725 AS1 (com,%D0) CR_TAB
3726 AS2 (mov,%B0,%D0) CR_TAB
3731 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3732 AS2 (sbc,%A0,%A0) CR_TAB
3733 AS2 (mov,%B0,%A0) CR_TAB
3734 AS2 (movw,%C0,%A0));
3736 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3737 AS2 (sbc,%A0,%A0) CR_TAB
3738 AS2 (mov,%B0,%A0) CR_TAB
3739 AS2 (mov,%C0,%A0) CR_TAB
3744 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3745 AS1 (ror,%C0) CR_TAB
3746 AS1 (ror,%B0) CR_TAB
3748 insn, operands, len, 4);
3752 /* 8bit logic shift right ((unsigned char)x >> i) */
3755 lshrqi3_out (insn, operands, len)
3760 if (GET_CODE (operands[2]) == CONST_INT)
3767 switch (INTVAL (operands[2]))
3771 return AS1 (clr,%0);
3775 return AS1 (lsr,%0);
3779 return (AS1 (lsr,%0) CR_TAB
3783 return (AS1 (lsr,%0) CR_TAB
3788 if (test_hard_reg_class (LD_REGS, operands[0]))
3791 return (AS1 (swap,%0) CR_TAB
3792 AS2 (andi,%0,0x0f));
3795 return (AS1 (lsr,%0) CR_TAB
3801 if (test_hard_reg_class (LD_REGS, operands[0]))
3804 return (AS1 (swap,%0) CR_TAB
3809 return (AS1 (lsr,%0) CR_TAB
3816 if (test_hard_reg_class (LD_REGS, operands[0]))
3819 return (AS1 (swap,%0) CR_TAB
3825 return (AS1 (lsr,%0) CR_TAB
3834 return (AS1 (rol,%0) CR_TAB
3839 else if (CONSTANT_P (operands[2]))
3840 fatal_insn ("Internal compiler bug.\nIncorrect shift:", insn);
3842 out_shift_with_cnt (AS1 (lsr,%0),
3843 insn, operands, len, 1);
3847 /* 16bit logic shift right ((unsigned short)x >> i) */
3850 lshrhi3_out (insn, operands, len)
3855 if (GET_CODE (operands[2]) == CONST_INT)
3857 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3858 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3865 switch (INTVAL (operands[2]))
3868 if (optimize_size && scratch)
3873 return (AS1 (swap,%B0) CR_TAB
3874 AS1 (swap,%A0) CR_TAB
3875 AS2 (andi,%A0,0x0f) CR_TAB
3876 AS2 (eor,%A0,%B0) CR_TAB
3877 AS2 (andi,%B0,0x0f) CR_TAB
3883 return (AS1 (swap,%B0) CR_TAB
3884 AS1 (swap,%A0) CR_TAB
3885 AS2 (ldi,%3,0x0f) CR_TAB
3886 AS2 (and,%A0,%3) CR_TAB
3887 AS2 (eor,%A0,%B0) CR_TAB
3888 AS2 (and,%B0,%3) CR_TAB
3891 break; /* optimize_size ? 6 : 8 */
3895 break; /* scratch ? 5 : 6 */
3899 return (AS1 (lsr,%B0) CR_TAB
3900 AS1 (ror,%A0) CR_TAB
3901 AS1 (swap,%B0) CR_TAB
3902 AS1 (swap,%A0) CR_TAB
3903 AS2 (andi,%A0,0x0f) CR_TAB
3904 AS2 (eor,%A0,%B0) CR_TAB
3905 AS2 (andi,%B0,0x0f) CR_TAB
3911 return (AS1 (lsr,%B0) CR_TAB
3912 AS1 (ror,%A0) CR_TAB
3913 AS1 (swap,%B0) CR_TAB
3914 AS1 (swap,%A0) CR_TAB
3915 AS2 (ldi,%3,0x0f) CR_TAB
3916 AS2 (and,%A0,%3) CR_TAB
3917 AS2 (eor,%A0,%B0) CR_TAB
3918 AS2 (and,%B0,%3) CR_TAB
3925 break; /* scratch ? 5 : 6 */
3927 return (AS1 (clr,__tmp_reg__) CR_TAB
3928 AS1 (lsl,%A0) CR_TAB
3929 AS1 (rol,%B0) CR_TAB
3930 AS1 (rol,__tmp_reg__) CR_TAB
3931 AS1 (lsl,%A0) CR_TAB
3932 AS1 (rol,%B0) CR_TAB
3933 AS1 (rol,__tmp_reg__) CR_TAB
3934 AS2 (mov,%A0,%B0) CR_TAB
3935 AS2 (mov,%B0,__tmp_reg__));
3939 return (AS1 (lsl,%A0) CR_TAB
3940 AS2 (mov,%A0,%B0) CR_TAB
3941 AS1 (rol,%A0) CR_TAB
3942 AS2 (sbc,%B0,%B0) CR_TAB
3946 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
3947 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
3950 return *len = 1, AS1 (clr,%B0);
3954 return (AS2 (mov,%A0,%B0) CR_TAB
3955 AS1 (clr,%B0) CR_TAB
3960 return (AS2 (mov,%A0,%B0) CR_TAB
3961 AS1 (clr,%B0) CR_TAB
3962 AS1 (lsr,%A0) CR_TAB
3967 return (AS2 (mov,%A0,%B0) CR_TAB
3968 AS1 (clr,%B0) CR_TAB
3969 AS1 (lsr,%A0) CR_TAB
3970 AS1 (lsr,%A0) CR_TAB
3977 return (AS2 (mov,%A0,%B0) CR_TAB
3978 AS1 (clr,%B0) CR_TAB
3979 AS1 (swap,%A0) CR_TAB
3980 AS2 (andi,%A0,0x0f));
3985 return (AS2 (mov,%A0,%B0) CR_TAB
3986 AS1 (clr,%B0) CR_TAB
3987 AS1 (swap,%A0) CR_TAB
3988 AS2 (ldi,%3,0x0f) CR_TAB
3992 return (AS2 (mov,%A0,%B0) CR_TAB
3993 AS1 (clr,%B0) CR_TAB
3994 AS1 (lsr,%A0) CR_TAB
3995 AS1 (lsr,%A0) CR_TAB
3996 AS1 (lsr,%A0) CR_TAB
4003 return (AS2 (mov,%A0,%B0) CR_TAB
4004 AS1 (clr,%B0) CR_TAB
4005 AS1 (swap,%A0) CR_TAB
4006 AS1 (lsr,%A0) CR_TAB
4007 AS2 (andi,%A0,0x07));
4009 if (AVR_ENHANCED && scratch)
4012 return (AS2 (ldi,%3,0x08) CR_TAB
4013 AS2 (mul,%B0,%3) CR_TAB
4014 AS2 (mov,%A0,r1) CR_TAB
4015 AS1 (clr,%B0) CR_TAB
4016 AS1 (clr,__zero_reg__));
4018 if (optimize_size && scratch)
4023 return (AS2 (mov,%A0,%B0) CR_TAB
4024 AS1 (clr,%B0) CR_TAB
4025 AS1 (swap,%A0) CR_TAB
4026 AS1 (lsr,%A0) CR_TAB
4027 AS2 (ldi,%3,0x07) CR_TAB
4033 return ("set" CR_TAB
4034 AS2 (bld,r1,3) CR_TAB
4035 AS2 (mul,%B0,r1) CR_TAB
4036 AS2 (mov,%A0,r1) CR_TAB
4037 AS1 (clr,%B0) CR_TAB
4038 AS1 (clr,__zero_reg__));
4041 return (AS2 (mov,%A0,%B0) CR_TAB
4042 AS1 (clr,%B0) CR_TAB
4043 AS1 (lsr,%A0) CR_TAB
4044 AS1 (lsr,%A0) CR_TAB
4045 AS1 (lsr,%A0) CR_TAB
4046 AS1 (lsr,%A0) CR_TAB
4050 if (AVR_ENHANCED && ldi_ok)
4053 return (AS2 (ldi,%A0,0x04) CR_TAB
4054 AS2 (mul,%B0,%A0) CR_TAB
4055 AS2 (mov,%A0,r1) CR_TAB
4056 AS1 (clr,%B0) CR_TAB
4057 AS1 (clr,__zero_reg__));
4059 if (AVR_ENHANCED && scratch)
4062 return (AS2 (ldi,%3,0x04) CR_TAB
4063 AS2 (mul,%B0,%3) CR_TAB
4064 AS2 (mov,%A0,r1) CR_TAB
4065 AS1 (clr,%B0) CR_TAB
4066 AS1 (clr,__zero_reg__));
4068 if (optimize_size && ldi_ok)
4071 return (AS2 (mov,%A0,%B0) CR_TAB
4072 AS2 (ldi,%B0,6) "\n1:\t"
4073 AS1 (lsr,%A0) CR_TAB
4074 AS1 (dec,%B0) CR_TAB
4077 if (optimize_size && scratch)
4080 return (AS1 (clr,%A0) CR_TAB
4081 AS1 (lsl,%B0) CR_TAB
4082 AS1 (rol,%A0) CR_TAB
4083 AS1 (lsl,%B0) CR_TAB
4084 AS1 (rol,%A0) CR_TAB
4089 return (AS1 (clr,%A0) CR_TAB
4090 AS1 (lsl,%B0) CR_TAB
4091 AS1 (rol,%A0) CR_TAB
4096 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4098 insn, operands, len, 2);
4102 /* 32bit logic shift right ((unsigned int)x >> i) */
4105 lshrsi3_out (insn, operands, len)
4110 if (GET_CODE (operands[2]) == CONST_INT)
4118 switch (INTVAL (operands[2]))
4122 int reg0 = true_regnum (operands[0]);
4123 int reg1 = true_regnum (operands[1]);
4126 return (AS2 (mov,%A0,%B1) CR_TAB
4127 AS2 (mov,%B0,%C1) CR_TAB
4128 AS2 (mov,%C0,%D1) CR_TAB
4130 else if (reg0 == reg1 + 1)
4131 return *len = 1, AS1 (clr,%D0);
4133 return (AS1 (clr,%D0) CR_TAB
4134 AS2 (mov,%C0,%D1) CR_TAB
4135 AS2 (mov,%B0,%C1) CR_TAB
4141 int reg0 = true_regnum (operands[0]);
4142 int reg1 = true_regnum (operands[1]);
4144 if (AVR_ENHANCED && (reg0 != reg1 + 2))
4147 return (AS2 (movw,%A0,%C1) CR_TAB
4148 AS1 (clr,%C0) CR_TAB
4151 if (reg0 <= reg1 + 1)
4152 return (AS2 (mov,%A0,%C1) CR_TAB
4153 AS2 (mov,%B0,%D1) CR_TAB
4154 AS1 (clr,%C0) CR_TAB
4156 else if (reg0 == reg1 + 2)
4157 return *len = 2, (AS1 (clr,%C0) CR_TAB
4160 return (AS2 (mov,%B0,%D1) CR_TAB
4161 AS2 (mov,%A0,%C1) CR_TAB
4162 AS1 (clr,%C0) CR_TAB
4167 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
4168 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4169 AS1 (clr,%B0) CR_TAB
4170 AS1 (clr,%C0) CR_TAB
4173 return *len = 3, (AS1 (clr,%B0) CR_TAB
4174 AS1 (clr,%C0) CR_TAB
4179 return (AS1 (clr,%A0) CR_TAB
4180 AS2 (sbrc,%D0,7) CR_TAB
4181 AS1 (inc,%A0) CR_TAB
4182 AS1 (clr,%B0) CR_TAB
4183 AS1 (clr,%C0) CR_TAB
4188 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4189 AS1 (ror,%C0) CR_TAB
4190 AS1 (ror,%B0) CR_TAB
4192 insn, operands, len, 4);
4196 /* Modifies the length assigned to instruction INSN
4197 LEN is the initially computed length of the insn. */
4200 adjust_insn_length (insn, len)
4204 rtx patt = PATTERN (insn);
4207 if (GET_CODE (patt) == SET)
4210 op[1] = SET_SRC (patt);
4211 op[0] = SET_DEST (patt);
4212 if (general_operand (op[1], VOIDmode)
4213 && general_operand (op[0], VOIDmode))
4215 switch (GET_MODE (op[0]))
4218 output_movqi (insn, op, &len);
4221 output_movhi (insn, op, &len);
4225 output_movsisf (insn, op, &len);
4231 else if (op[0] == cc0_rtx && REG_P (op[1]))
4233 switch (GET_MODE (op[1]))
4235 case HImode: out_tsthi (insn,&len); break;
4236 case SImode: out_tstsi (insn,&len); break;
4240 else if (GET_CODE (op[1]) == AND)
4242 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4244 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4245 if (GET_MODE (op[1]) == SImode)
4246 len = (((mask & 0xff) != 0xff)
4247 + ((mask & 0xff00) != 0xff00)
4248 + ((mask & 0xff0000UL) != 0xff0000UL)
4249 + ((mask & 0xff000000UL) != 0xff000000UL));
4250 else if (GET_MODE (op[1]) == HImode)
4251 len = (((mask & 0xff) != 0xff)
4252 + ((mask & 0xff00) != 0xff00));
4255 else if (GET_CODE (op[1]) == IOR)
4257 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4259 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4260 if (GET_MODE (op[1]) == SImode)
4261 len = (((mask & 0xff) != 0)
4262 + ((mask & 0xff00) != 0)
4263 + ((mask & 0xff0000UL) != 0)
4264 + ((mask & 0xff000000UL) != 0));
4265 else if (GET_MODE (op[1]) == HImode)
4266 len = (((mask & 0xff) != 0)
4267 + ((mask & 0xff00) != 0));
4271 set = single_set (insn);
4276 op[1] = SET_SRC (set);
4277 op[0] = SET_DEST (set);
4279 if (GET_CODE (patt) == PARALLEL
4280 && general_operand (op[1], VOIDmode)
4281 && general_operand (op[0], VOIDmode))
4283 if (XVECLEN (patt, 0) == 2)
4284 op[2] = XVECEXP (patt, 0, 1);
4286 switch (GET_MODE (op[0]))
4292 output_reload_inhi (insn, op, &len);
4296 output_reload_insisf (insn, op, &len);
4302 else if (GET_CODE (op[1]) == ASHIFT
4303 || GET_CODE (op[1]) == ASHIFTRT
4304 || GET_CODE (op[1]) == LSHIFTRT)
4308 ops[1] = XEXP (op[1],0);
4309 ops[2] = XEXP (op[1],1);
4310 switch (GET_CODE (op[1]))
4313 switch (GET_MODE (op[0]))
4315 case QImode: ashlqi3_out (insn,ops,&len); break;
4316 case HImode: ashlhi3_out (insn,ops,&len); break;
4317 case SImode: ashlsi3_out (insn,ops,&len); break;
4322 switch (GET_MODE (op[0]))
4324 case QImode: ashrqi3_out (insn,ops,&len); break;
4325 case HImode: ashrhi3_out (insn,ops,&len); break;
4326 case SImode: ashrsi3_out (insn,ops,&len); break;
4331 switch (GET_MODE (op[0]))
4333 case QImode: lshrqi3_out (insn,ops,&len); break;
4334 case HImode: lshrhi3_out (insn,ops,&len); break;
4335 case SImode: lshrsi3_out (insn,ops,&len); break;
4347 /* Return non-zero if register REG dead after INSN */
4350 reg_unused_after (insn, reg)
4354 return (dead_or_set_p (insn, reg)
4355 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4358 /* Return non-zero if REG is not used after INSN.
4359 We assume REG is a reload reg, and therefore does
4360 not live past labels. It may live past calls or jumps though. */
4363 _reg_unused_after (insn, reg)
4370 /* If the reg is set by this instruction, then it is safe for our
4371 case. Disregard the case where this is a store to memory, since
4372 we are checking a register used in the store address. */
4373 set = single_set (insn);
4374 if (set && GET_CODE (SET_DEST (set)) != MEM
4375 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4378 while ((insn = NEXT_INSN (insn)))
4380 code = GET_CODE (insn);
4383 /* If this is a label that existed before reload, then the register
4384 if dead here. However, if this is a label added by reorg, then
4385 the register may still be live here. We can't tell the difference,
4386 so we just ignore labels completely. */
4387 if (code == CODE_LABEL)
4392 if (code == JUMP_INSN)
4395 /* If this is a sequence, we must handle them all at once.
4396 We could have for instance a call that sets the target register,
4397 and a insn in a delay slot that uses the register. In this case,
4398 we must return 0. */
4399 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4404 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4406 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4407 rtx set = single_set (this_insn);
4409 if (GET_CODE (this_insn) == CALL_INSN)
4411 else if (GET_CODE (this_insn) == JUMP_INSN)
4413 if (INSN_ANNULLED_BRANCH_P (this_insn))
4418 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4420 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4422 if (GET_CODE (SET_DEST (set)) != MEM)
4428 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4433 else if (code == JUMP_INSN)
4437 if (code == CALL_INSN)
4440 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4441 if (GET_CODE (XEXP (tem, 0)) == USE
4442 && REG_P (XEXP (XEXP (tem, 0), 0))
4443 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4445 if (call_used_regs[REGNO (reg)])
4449 if (GET_RTX_CLASS (code) == 'i')
4451 rtx set = single_set (insn);
4453 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4455 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4456 return GET_CODE (SET_DEST (set)) != MEM;
4457 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4464 /* Output rtx VALUE as .byte to file FILE */
4467 asm_output_char (file, value)
4471 fprintf (file, "\t.byte ");
4472 output_addr_const (file, value);
4473 fprintf (file, "\n");
4477 /* Output VALUE as .byte to file FILE */
4480 asm_output_byte (file, value)
4484 fprintf (file, "\t.byte 0x%x\n", value & 0xff);
4488 /* Output rtx VALUE as .word to file FILE */
4491 asm_output_short (file, value)
4495 if (SYMBOL_REF_FLAG (value) || GET_CODE (value) == LABEL_REF)
4497 fprintf (file, "\t.word pm(");
4498 output_addr_const (file, (value));
4499 fprintf (file, ")\n");
4503 fprintf (file, "\t.word ");
4504 output_addr_const (file, (value));
4505 fprintf (file, "\n");
4510 /* Output real N to file FILE */
4513 asm_output_float (file, n)
4520 REAL_VALUE_TO_TARGET_SINGLE (n, val);
4521 REAL_VALUE_TO_DECIMAL (n, "%g", dstr);
4522 fprintf (file, "\t.long 0x%08lx\t/* %s */\n", val, dstr);
4525 /* Sets section name for declaration DECL */
4528 unique_section (decl, reloc)
4530 int reloc ATTRIBUTE_UNUSED;
4533 const char *name, *prefix;
4535 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
4536 /* Strip off any encoding in name. */
4537 STRIP_NAME_ENCODING (name, name);
4539 if (TREE_CODE (decl) == FUNCTION_DECL)
4541 if (flag_function_sections)
4549 if (flag_function_sections)
4551 len = strlen (name) + strlen (prefix);
4552 string = alloca (len + 1);
4553 sprintf (string, "%s%s", prefix, name);
4554 DECL_SECTION_NAME (decl) = build_string (len, string);
4559 /* The routine used to output NUL terminated strings. We use a special
4560 version of this for most svr4 targets because doing so makes the
4561 generated assembly code more compact (and thus faster to assemble)
4562 as well as more readable, especially for targets like the i386
4563 (where the only alternative is to output character sequences as
4564 comma separated lists of numbers). */
4567 gas_output_limited_string(file, str)
4571 const unsigned char *_limited_str = (unsigned char *) str;
4573 fprintf (file, "%s\"", STRING_ASM_OP);
4574 for (; (ch = *_limited_str); _limited_str++)
4577 switch (escape = ESCAPES[ch])
4583 fprintf (file, "\\%03o", ch);
4587 putc (escape, file);
4591 fprintf (file, "\"\n");
4594 /* The routine used to output sequences of byte values. We use a special
4595 version of this for most svr4 targets because doing so makes the
4596 generated assembly code more compact (and thus faster to assemble)
4597 as well as more readable. Note that if we find subparts of the
4598 character sequence which end with NUL (and which are shorter than
4599 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4602 gas_output_ascii(file, str, length)
4607 const unsigned char *_ascii_bytes = (const unsigned char *) str;
4608 const unsigned char *limit = _ascii_bytes + length;
4609 unsigned bytes_in_chunk = 0;
4610 for (; _ascii_bytes < limit; _ascii_bytes++)
4612 const unsigned char *p;
4613 if (bytes_in_chunk >= 60)
4615 fprintf (file, "\"\n");
4618 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4620 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4622 if (bytes_in_chunk > 0)
4624 fprintf (file, "\"\n");
4627 gas_output_limited_string (file, (char*)_ascii_bytes);
4634 if (bytes_in_chunk == 0)
4635 fprintf (file, "\t.ascii\t\"");
4636 switch (escape = ESCAPES[ch = *_ascii_bytes])
4643 fprintf (file, "\\%03o", ch);
4644 bytes_in_chunk += 4;
4648 putc (escape, file);
4649 bytes_in_chunk += 2;
4654 if (bytes_in_chunk > 0)
4655 fprintf (file, "\"\n");
4658 /* Return value is nonzero if pseudos that have been
4659 assigned to registers of class CLASS would likely be spilled
4660 because registers of CLASS are needed for spill registers. */
4663 class_likely_spilled_p (c)
4666 return (c != ALL_REGS && c != ADDW_REGS);
4669 /* Only `progmem' attribute valid for type. */
4672 avr_valid_type_attribute (type, attributes, identifier, args)
4673 tree type ATTRIBUTE_UNUSED;
4674 tree attributes ATTRIBUTE_UNUSED;
4676 tree args ATTRIBUTE_UNUSED;
4678 return is_attribute_p ("progmem", identifier);
4681 /* If IDENTIFIER with arguments ARGS is a valid machine specific
4682 attribute for DECL return 1.
4684 progmem - put data to program memory;
4685 signal - make a function to be hardware interrupt. After function
4686 prologue interrupts are disabled;
4687 interrupt - make a function to be hardware interrupt. After function
4688 prologue interrupts are enabled;
4689 naked - don't generate function prologue/epilogue and `ret' command. */
4692 avr_valid_decl_attribute (decl, attributes, attr, args)
4694 tree attributes ATTRIBUTE_UNUSED;
4696 tree args ATTRIBUTE_UNUSED;
4698 if (is_attribute_p ("interrupt", attr)
4699 || is_attribute_p ("signal", attr)
4700 || is_attribute_p ("naked", attr))
4701 return TREE_CODE (decl) == FUNCTION_DECL;
4703 if (is_attribute_p ("progmem", attr)
4704 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
4706 if (DECL_INITIAL (decl) == NULL_TREE && !DECL_EXTERNAL (decl))
4708 warning ("Only initialized variables can be placed into "
4709 "program memory area.");
4718 /* Look for attribute `progmem' in DECL
4719 if found return 1, otherwise 0. */
4722 avr_progmem_p (decl)
4727 if (TREE_CODE (decl) != VAR_DECL)
4731 != lookup_attribute ("progmem", DECL_MACHINE_ATTRIBUTES (decl)))
4737 while (TREE_CODE (a) == ARRAY_TYPE);
4739 if (a == error_mark_node)
4742 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4748 /* Encode section information about tree DECL */
4751 encode_section_info (decl)
4754 if (TREE_CODE (decl) == FUNCTION_DECL)
4755 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
4756 else if ((TREE_STATIC (decl) || DECL_EXTERNAL (decl))
4757 && TREE_CODE (decl) == VAR_DECL
4758 && avr_progmem_p (decl))
4760 const char *dsec = ".progmem.data";
4761 DECL_SECTION_NAME (decl) = build_string (strlen (dsec), dsec);
4762 TREE_READONLY (decl) = 1;
4766 /* Outputs to the stdio stream FILE some
4767 appropriate text to go at the start of an assembler file. */
4770 asm_file_start (file)
4773 output_file_directive (file, main_input_filename);
4774 fprintf (file, "\t.arch %s\n", avr_mcu_name);
4775 fputs ("__SREG__ = 0x3f\n"
4777 "__SP_L__ = 0x3d\n", file);
4779 fputs ("__tmp_reg__ = 0\n"
4780 "__zero_reg__ = 1\n"
4781 "_PC_ = 2\n", file);
4783 commands_in_file = 0;
4784 commands_in_prologues = 0;
4785 commands_in_epilogues = 0;
4788 /* Outputs to the stdio stream FILE some
4789 appropriate text to go at the end of an assembler file. */
4796 "/* File %s: code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4797 main_input_filename,
4800 commands_in_file - commands_in_prologues - commands_in_epilogues,
4801 commands_in_prologues, commands_in_epilogues);
4804 /* Choose the order in which to allocate hard registers for
4805 pseudo-registers local to a basic block.
4807 Store the desired register order in the array `reg_alloc_order'.
4808 Element 0 should be the register to allocate first; element 1, the
4809 next register; and so on. */
4812 order_regs_for_local_alloc ()
4823 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4835 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4848 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4853 int *order = (TARGET_ORDER_1 ? order_1 :
4854 TARGET_ORDER_2 ? order_2 :
4856 for (i=0; i < ARRAY_SIZE (order_0); ++i)
4857 reg_alloc_order[i] = order[i];
4860 /* Calculate the cost of X code of the expression in which it is contained,
4861 found in OUTER_CODE */
4864 default_rtx_costs (X, code, outer_code)
4867 enum rtx_code outer_code;
4874 cost = 2 * GET_MODE_SIZE (GET_MODE (X));
4877 if (outer_code != SET)
4879 if (GET_CODE (XEXP (X,0)) == SYMBOL_REF)
4880 cost += 2 * GET_MODE_SIZE (GET_MODE (X));
4882 cost += GET_MODE_SIZE (GET_MODE (X));
4888 if (outer_code == SET)
4889 cost = GET_MODE_SIZE (GET_MODE (X));
4891 cost = -GET_MODE_SIZE (GET_MODE (X));
4894 if (outer_code == SET)
4895 cost = GET_MODE_SIZE (GET_MODE (X));
4901 if (outer_code == SET)
4903 if (X == stack_pointer_rtx)
4905 else if (GET_CODE (XEXP (X,1)) == CONST_INT)
4906 cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 :
4907 GET_MODE_SIZE (GET_MODE (X)));
4909 cost = GET_MODE_SIZE (GET_MODE (X));
4913 if (GET_CODE (XEXP (X,1)) == CONST_INT)
4914 cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0)));
4922 /* Calculate the cost of a memory address */
4925 avr_address_cost (x)
4928 if (GET_CODE (x) == PLUS
4929 && GET_CODE (XEXP (x,1)) == CONST_INT
4930 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
4931 && INTVAL (XEXP (x,1)) >= 61)
4933 if (CONSTANT_ADDRESS_P (x))
4935 if (io_address_p (x, 1))
4942 /* EXTRA_CONSTRAINT helper */
4945 extra_constraint (x, c)
4950 && GET_CODE (x) == MEM
4951 && GET_CODE (XEXP (x,0)) == PLUS)
4953 if (TARGET_ALL_DEBUG)
4955 fprintf (stderr, ("extra_constraint:\n"
4956 "reload_completed: %d\n"
4957 "reload_in_progress: %d\n"),
4958 reload_completed, reload_in_progress);
4961 if (GET_CODE (x) == MEM
4962 && GET_CODE (XEXP (x,0)) == PLUS
4963 && REG_P (XEXP (XEXP (x,0), 0))
4964 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
4965 && (INTVAL (XEXP (XEXP (x,0), 1))
4966 <= MAX_LD_OFFSET (GET_MODE (x))))
4968 rtx xx = XEXP (XEXP (x,0), 0);
4969 int regno = REGNO (xx);
4970 if (TARGET_ALL_DEBUG)
4972 fprintf (stderr, ("extra_constraint:\n"
4973 "reload_completed: %d\n"
4974 "reload_in_progress: %d\n"),
4975 reload_completed, reload_in_progress);
4978 if (regno >= FIRST_PSEUDO_REGISTER)
4979 return 1; /* allocate pseudos */
4980 else if (regno == REG_Z || regno == REG_Y)
4981 return 1; /* strictly check */
4982 else if (xx == frame_pointer_rtx
4983 || xx == arg_pointer_rtx)
4984 return 1; /* XXX frame & arg pointer checks */
4990 /* Convert condition code CONDITION to the valid AVR condition code */
4993 avr_normalize_condition (condition)
5011 /* This fnction optimizes conditional jumps */
5014 machine_dependent_reorg (first_insn)
5019 for (insn = first_insn; insn; insn = NEXT_INSN (insn))
5021 if (! (GET_CODE (insn) == INSN
5022 || GET_CODE (insn) == CALL_INSN
5023 || GET_CODE (insn) == JUMP_INSN)
5024 || !single_set (insn))
5027 pattern = PATTERN (insn);
5029 if (GET_CODE (pattern) == PARALLEL)
5030 pattern = XVECEXP (pattern, 0, 0);
5031 if (GET_CODE (pattern) == SET
5032 && SET_DEST (pattern) == cc0_rtx
5033 && compare_diff_p (insn))
5035 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
5037 /* Now we work under compare insn */
5039 pattern = SET_SRC (pattern);
5040 if (true_regnum (XEXP (pattern,0)) >= 0
5041 && true_regnum (XEXP (pattern,1)) >= 0 )
5043 rtx x = XEXP (pattern,0);
5044 rtx next = next_real_insn (insn);
5045 rtx pat = PATTERN (next);
5046 rtx src = SET_SRC (pat);
5047 rtx t = XEXP (src,0);
5048 PUT_CODE (t, swap_condition (GET_CODE (t)));
5049 XEXP (pattern,0) = XEXP (pattern,1);
5050 XEXP (pattern,1) = x;
5051 INSN_CODE (next) = -1;
5053 else if (true_regnum (XEXP (pattern,0)) >= 0
5054 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
5056 rtx x = XEXP (pattern,1);
5057 rtx next = next_real_insn (insn);
5058 rtx pat = PATTERN (next);
5059 rtx src = SET_SRC (pat);
5060 rtx t = XEXP (src,0);
5062 if (avr_simplify_comparision_p (GET_MODE (XEXP (pattern,0)),
5065 XEXP (pattern,1) = GEN_INT (INTVAL (x)+1);
5066 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
5067 INSN_CODE (next) = -1;
5068 INSN_CODE (insn) = -1;
5072 else if (true_regnum (SET_SRC (pattern)) >= 0)
5074 /* This is a tst insn */
5075 rtx next = next_real_insn (insn);
5076 rtx pat = PATTERN (next);
5077 rtx src = SET_SRC (pat);
5078 rtx t = XEXP (src,0);
5080 PUT_CODE (t, swap_condition (GET_CODE (t)));
5081 SET_SRC (pattern) = gen_rtx (NEG,
5082 GET_MODE (SET_SRC (pattern)),
5084 INSN_CODE (next) = -1;
5085 INSN_CODE (insn) = -1;
5091 /* Returns register number for function return value.*/
5099 /* Ceate an RTX representing the place where a
5100 library function returns a value of mode MODE. */
5103 avr_libcall_value (mode)
5104 enum machine_mode mode;
5106 int offs = GET_MODE_SIZE (mode);
5109 return gen_rtx (REG, mode, RET_REGISTER + 2 - offs);
5112 /* Create an RTX representing the place where a
5113 function returns a value of data type VALTYPE. */
5116 avr_function_value (type, func)
5118 tree func ATTRIBUTE_UNUSED;
5122 if (TYPE_MODE (type) != BLKmode)
5123 return avr_libcall_value (TYPE_MODE (type));
5125 offs = int_size_in_bytes (type);
5128 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5129 offs = GET_MODE_SIZE (SImode);
5130 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5131 offs = GET_MODE_SIZE (DImode);
5133 return gen_rtx (REG, BLKmode, RET_REGISTER + 2 - offs);
5136 /* Returns non-zero if the number MASK has only one bit set. */
5139 mask_one_bit_p (mask)
5143 unsigned HOST_WIDE_INT n=mask;
5144 for (i = 0; i < 32; ++i)
5146 if (n & 0x80000000UL)
5148 if (n & 0x7fffffffUL)
5159 /* Places additional restrictions on the register class to
5160 use when it is necessary to copy value X into a register
5164 preferred_reload_class (x, class)
5165 rtx x ATTRIBUTE_UNUSED;
5166 enum reg_class class;
5172 test_hard_reg_class (class, x)
5173 enum reg_class class;
5176 int regno = true_regnum (x);
5179 return TEST_HARD_REG_CLASS (class, regno);
5183 debug_hard_reg_set (set)
5187 for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
5189 if (TEST_HARD_REG_BIT (set, i))
5191 fprintf (stderr, "r%-2d ", i);
5194 fprintf (stderr, "\n");
5198 jump_over_one_insn_p (insn, dest)
5202 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5205 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5206 int dest_addr = INSN_ADDRESSES (uid);
5207 return dest_addr - jump_addr == 2;
5210 /* Returns 1 if a value of mode MODE can be stored starting with hard
5211 register number REGNO. On the enhanced core, anything larger than
5212 1 byte must start in even numbered register for "movw" to work
5213 (this way we don't have to check for odd registers everywhere). */
5216 avr_hard_regno_mode_ok (regno, mode)
5218 enum machine_mode mode;
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) & 0xff000000U) != 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) & 0xff000000U) == 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])