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 tree avr_handle_progmem_attribute PARAMS ((tree *, tree, tree, int, bool *));
62 static tree avr_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
63 const struct attribute_spec avr_attribute_table[];
64 static void avr_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
65 static void avr_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
67 /* Allocate registers from r25 to r8 for parameters for function calls */
68 #define FIRST_CUM_REG 26
70 /* Temporary register RTX (gen_rtx (REG,QImode,TMP_REGNO)) */
73 /* Zeroed register RTX (gen_rtx (REG,QImode,ZERO_REGNO)) */
76 /* RTX for register which will be used for loading immediate values to
80 /* AVR register names {"r0", "r1", ..., "r31"} */
81 static const char *const avr_regnames[] = REGISTER_NAMES;
83 /* This holds the last insn address. */
84 static int last_insn_address = 0;
86 /* Commands count in the compiled file */
87 static int commands_in_file;
89 /* Commands in the functions prologues in the compiled file */
90 static int commands_in_prologues;
92 /* Commands in the functions epilogues in the compiled file */
93 static int commands_in_epilogues;
95 /* Prologue/Epilogue size in words */
96 static int prologue_size;
97 static int epilogue_size;
99 /* Size of all jump tables in the current function, in words. */
100 static int jump_tables_size;
102 /* Initial stack value specified by the `-minit-stack=' option */
103 const char *avr_init_stack = "__stack";
105 /* Default MCU name */
106 const char *avr_mcu_name = "avr2";
108 /* More than 8K of program memory: use "call" and "jmp". */
111 /* Enhanced core: use "movw", "mul", ... */
112 int avr_enhanced_p = 0;
123 const char *const name;
124 const enum avr_arch arch;
127 /* List of all known AVR MCU types - if updated, it has to be kept
128 in sync in several places (FIXME: is there a better way?):
130 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
131 - t-avr (MULTILIB_MATCHES)
132 - gas/config/tc-avr.c
135 static const struct mcu_type_s avr_mcu_types[] = {
136 /* Classic, <= 8K. */
138 { "at90s2313", AVR2 },
139 { "at90s2323", AVR2 },
140 { "attiny22", AVR2 },
141 { "at90s2333", AVR2 },
142 { "at90s2343", AVR2 },
143 { "at90s4414", AVR2 },
144 { "at90s4433", AVR2 },
145 { "at90s4434", AVR2 },
146 { "at90s8515", AVR2 },
147 { "at90c8534", AVR2 },
148 { "at90s8535", AVR2 },
151 { "atmega103", AVR3 },
152 { "atmega603", AVR3 },
153 /* Enhanced, <= 8K. */
155 { "atmega83", AVR4 },
156 { "atmega85", AVR4 },
157 /* Enhanced, > 8K. */
159 { "atmega161", AVR5 },
160 { "atmega163", AVR5 },
161 { "atmega32", AVR5 },
163 /* Assembler only. */
165 { "at90s1200", AVR1 },
166 { "attiny10", AVR1 },
167 { "attiny11", AVR1 },
168 { "attiny12", AVR1 },
169 { "attiny15", AVR1 },
170 { "attiny28", AVR1 },
174 int avr_case_values_threshold = 30000;
176 /* Initialize the GCC target structure. */
177 #undef TARGET_ASM_FUNCTION_PROLOGUE
178 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
179 #undef TARGET_ASM_FUNCTION_EPILOGUE
180 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
181 #undef TARGET_ATTRIBUTE_TABLE
182 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
184 struct gcc_target targetm = TARGET_INITIALIZER;
187 avr_override_options ()
189 const struct mcu_type_s *t;
191 for (t = avr_mcu_types; t->name; t++)
192 if (strcmp (t->name, avr_mcu_name) == 0)
197 fprintf (stderr, "Unknown MCU `%s' specified\nKnown MCU names:\n",
199 for (t = avr_mcu_types; t->name; t++)
200 fprintf (stderr," %s\n", t->name);
207 error ("MCU `%s' not supported", avr_mcu_name);
208 /* ... fall through ... */
209 case AVR2: avr_enhanced_p = 0; avr_mega_p = 0; break;
210 case AVR3: avr_enhanced_p = 0; avr_mega_p = 1; break;
211 case AVR4: avr_enhanced_p = 1; avr_mega_p = 0; break;
212 case AVR5: avr_enhanced_p = 1; avr_mega_p = 1; break;
215 if (optimize && !TARGET_NO_TABLEJUMP)
216 avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
220 /* Initialize TMP_REG_RTX and ZERO_REG_RTX */
224 tmp_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
225 memset (tmp_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
226 PUT_CODE (tmp_reg_rtx, REG);
227 PUT_MODE (tmp_reg_rtx, QImode);
228 XINT (tmp_reg_rtx, 0) = TMP_REGNO;
230 zero_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
231 memset (zero_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
232 PUT_CODE (zero_reg_rtx, REG);
233 PUT_MODE (zero_reg_rtx, QImode);
234 XINT (zero_reg_rtx, 0) = ZERO_REGNO;
236 ldi_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
237 memset (ldi_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
238 PUT_CODE (ldi_reg_rtx, REG);
239 PUT_MODE (ldi_reg_rtx, QImode);
240 XINT (ldi_reg_rtx, 0) = LDI_REG_REGNO;
243 /* return register class from register number */
245 static const int reg_class_tab[]={
246 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
247 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
248 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
249 GENERAL_REGS, /* r0 - r15 */
250 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
251 LD_REGS, /* r16 - 23 */
252 ADDW_REGS,ADDW_REGS, /* r24,r25 */
253 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
254 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
255 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
256 STACK_REG,STACK_REG /* SPL,SPH */
259 /* Return register class for register R */
262 avr_regno_reg_class (r)
266 return reg_class_tab[r];
271 /* A C expression which defines the machine-dependent operand
272 constraint letters for register classes. If C is such a
273 letter, the value should be the register class corresponding to
274 it. Otherwise, the value should be `NO_REGS'. The register
275 letter `r', corresponding to class `GENERAL_REGS', will not be
276 passed to this macro; you do not need to handle it. */
279 avr_reg_class_from_letter (c)
284 case 't' : return R0_REG;
285 case 'b' : return BASE_POINTER_REGS;
286 case 'e' : return POINTER_REGS;
287 case 'w' : return ADDW_REGS;
288 case 'd' : return LD_REGS;
289 case 'l' : return NO_LD_REGS;
290 case 'a' : return SIMPLE_LD_REGS;
291 case 'x' : return POINTER_X_REGS;
292 case 'y' : return POINTER_Y_REGS;
293 case 'z' : return POINTER_Z_REGS;
294 case 'q' : return STACK_REG;
300 /* Return non-zero if FUNC is a naked function. */
303 avr_naked_function_p (func)
308 if (TREE_CODE (func) != FUNCTION_DECL)
311 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
312 return a != NULL_TREE;
315 /* Return nonzero if FUNC is an interrupt function as specified
316 by the "interrupt" attribute. */
319 interrupt_function_p (func)
324 if (TREE_CODE (func) != FUNCTION_DECL)
327 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
328 return a != NULL_TREE;
331 /* Return nonzero if FUNC is a signal function as specified
332 by the "signal" attribute. */
335 signal_function_p (func)
340 if (TREE_CODE (func) != FUNCTION_DECL)
343 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
344 return a != NULL_TREE;
347 /* Compute offset between arg_pointer and frame_pointer */
350 initial_elimination_offset (from, to)
355 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
359 int interrupt_func_p = interrupt_function_p (current_function_decl);
360 int signal_func_p = signal_function_p (current_function_decl);
361 int leaf_func_p = leaf_function_p ();
362 int offset= frame_pointer_needed ? 2 : 0;
364 for (reg = 0; reg < 32; ++reg)
366 if ((!leaf_func_p && (call_used_regs[reg]
367 && (interrupt_func_p || signal_func_p)))
368 || (regs_ever_live[reg]
369 && (!call_used_regs[reg] || interrupt_func_p || signal_func_p)
370 && ! (frame_pointer_needed
371 && (reg == REG_Y || reg == (REG_Y+1)))))
376 return get_frame_size () + 2 + 1 + offset;
381 /* This function checks sequence of live registers */
390 for (reg = 0; reg < 18; ++reg)
392 if (!call_used_regs[reg])
394 if (regs_ever_live[reg])
404 if (!frame_pointer_needed)
406 if (regs_ever_live[REG_Y])
414 if (regs_ever_live[REG_Y+1])
427 return (cur_seq == live_seq) ? live_seq : 0;
431 /* Output to FILE the asm instructions to adjust the frame pointer by
432 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
433 (epilogue). Returns the number of instructions generated. */
436 out_adj_frame_ptr (file, adj)
444 if (TARGET_TINY_STACK)
446 if (adj < -63 || adj > 63)
447 warning ("large frame pointer change (%d) with -mtiny-stack", adj);
449 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
450 over "sbiw" (2 cycles, same size). */
452 fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
455 else if (adj < -63 || adj > 63)
457 fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
458 AS2 (sbci, r29, hi8(%d)) CR_TAB),
464 fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
469 fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
477 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
478 handling various cases of interrupt enable flag state BEFORE and AFTER
479 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
480 Returns the number of instructions generated. */
483 out_set_stack_ptr (file, before, after)
488 int do_sph, do_cli, do_save, do_sei, lock_sph, size;
490 /* The logic here is so that -mno-interrupts actually means
491 "it is safe to write SPH in one instruction, then SPL in the
492 next instruction, without disabling interrupts first".
493 The after != -1 case (interrupt/signal) is not affected. */
495 do_sph = !TARGET_TINY_STACK;
496 lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
497 do_cli = (before != 0 && (after == 0 || lock_sph));
498 do_save = (do_cli && before == -1 && after == -1);
499 do_sei = ((do_cli || before != 1) && after == 1);
504 fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
510 fprintf (file, "cli" CR_TAB);
514 /* Do SPH first - maybe this will disable interrupts for one instruction
515 someday (a suggestion has been sent to avr@atmel.com for consideration
516 in future devices - that would make -mno-interrupts always safe). */
519 fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
523 /* Set/restore the I flag now - interrupts will be really enabled only
524 after the next instruction. This is not clearly documented, but
525 believed to be true for all AVR devices. */
528 fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
533 fprintf (file, "sei" CR_TAB);
537 fprintf (file, AS2 (out, __SP_L__, r28) "\n");
543 /* Output function prologue */
546 avr_output_function_prologue (file, size)
551 int interrupt_func_p;
558 if (avr_naked_function_p (current_function_decl))
560 fprintf (file, "/* prologue: naked */\n");
564 interrupt_func_p = interrupt_function_p (current_function_decl);
565 signal_func_p = signal_function_p (current_function_decl);
566 leaf_func_p = leaf_function_p ();
567 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
568 live_seq = sequent_regs_live ();
569 minimize = (TARGET_CALL_PROLOGUES
570 && !interrupt_func_p && !signal_func_p && live_seq);
572 last_insn_address = 0;
573 jump_tables_size = 0;
575 fprintf (file, "/* prologue: frame size=%d */\n", size);
577 if (interrupt_func_p)
579 fprintf (file,"\tsei\n");
582 if (interrupt_func_p | signal_func_p)
585 AS1 (push,__zero_reg__) CR_TAB
586 AS1 (push,__tmp_reg__) CR_TAB
587 AS2 (in,__tmp_reg__,__SREG__) CR_TAB
588 AS1 (push,__tmp_reg__) CR_TAB
589 AS1 (clr,__zero_reg__) "\n");
595 AS2 (ldi,r28,lo8(%s - %d)) CR_TAB
596 AS2 (ldi,r29,hi8(%s - %d)) CR_TAB
597 AS2 (out,__SP_H__,r29) CR_TAB
598 AS2 (out,__SP_L__,r28) "\n"),
599 avr_init_stack, size, avr_init_stack, size);
603 else if (minimize && (frame_pointer_needed || live_seq > 6))
606 AS2 (ldi, r26, lo8(%d)) CR_TAB
607 AS2 (ldi, r27, hi8(%d)) CR_TAB), size, size);
609 fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB
610 AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB)
611 ,current_function_name, current_function_name);
617 fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
618 (18 - live_seq) * 2);
623 fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
624 (18 - live_seq) * 2);
627 fprintf (file, ".L_%s_body:\n", current_function_name);
631 for (reg = 0; reg < 32; ++reg)
634 && (call_used_regs[reg]
635 && (interrupt_func_p || signal_func_p)
636 && !(reg == TMP_REGNO || reg == ZERO_REGNO)))
637 || (regs_ever_live[reg]
638 && (!call_used_regs[reg]
639 || interrupt_func_p || signal_func_p)
640 && ! (frame_pointer_needed
641 && (reg == REG_Y || reg == (REG_Y+1)))))
643 fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
647 if (frame_pointer_needed)
651 AS1 (push,r28) CR_TAB
652 AS1 (push,r29) CR_TAB
653 AS2 (in,r28,__SP_L__) CR_TAB
654 AS2 (in,r29,__SP_H__) "\n");
659 prologue_size += out_adj_frame_ptr (file, size);
661 if (interrupt_func_p)
663 prologue_size += out_set_stack_ptr (file, 1, 1);
665 else if (signal_func_p)
667 prologue_size += out_set_stack_ptr (file, 0, 0);
671 prologue_size += out_set_stack_ptr (file, -1, -1);
677 fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
680 /* Output function epilogue */
683 avr_output_function_epilogue (file, size)
688 int interrupt_func_p;
696 if (avr_naked_function_p (current_function_decl))
698 fprintf (file, "/* epilogue: naked */\n");
702 interrupt_func_p = interrupt_function_p (current_function_decl);
703 signal_func_p = signal_function_p (current_function_decl);
704 leaf_func_p = leaf_function_p ();
705 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
706 function_size = (INSN_ADDRESSES (INSN_UID (get_last_insn ()))
707 - INSN_ADDRESSES (INSN_UID (get_insns ())));
708 function_size += jump_tables_size;
709 live_seq = sequent_regs_live ();
710 minimize = (TARGET_CALL_PROLOGUES
711 && !interrupt_func_p && !signal_func_p && live_seq);
714 fprintf (file, "/* epilogue: frame size=%d */\n", size);
717 fprintf (file, "__stop_progIi__:\n\trjmp __stop_progIi__\n");
720 else if (minimize && (frame_pointer_needed || live_seq > 4))
722 fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
724 if (frame_pointer_needed)
726 epilogue_size += out_adj_frame_ptr (file, -size);
730 fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
731 AS2 (in , r29, __SP_H__) CR_TAB));
737 fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
738 (18 - live_seq) * 2);
743 fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
744 (18 - live_seq) * 2);
750 if (frame_pointer_needed)
755 epilogue_size += out_adj_frame_ptr (file, -size);
757 if (interrupt_func_p | signal_func_p)
759 epilogue_size += out_set_stack_ptr (file, -1, 0);
763 epilogue_size += out_set_stack_ptr (file, -1, -1);
772 for (reg = 31; reg >= 0; --reg)
775 && (call_used_regs[reg]
776 && (interrupt_func_p || signal_func_p)
777 && !(reg == TMP_REGNO || reg == ZERO_REGNO)))
778 || (regs_ever_live[reg]
779 && (!call_used_regs[reg]
780 || interrupt_func_p || signal_func_p)
781 && ! (frame_pointer_needed
782 && (reg == REG_Y || reg == (REG_Y+1)))))
784 fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
789 if (interrupt_func_p | signal_func_p)
792 AS1 (pop,__tmp_reg__) CR_TAB
793 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
794 AS1 (pop,__tmp_reg__) CR_TAB
795 AS1 (pop,__zero_reg__) "\n");
797 fprintf (file, "\treti\n");
800 fprintf (file, "\tret\n");
804 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
805 fprintf (file, "/* function %s size %d (%d) */\n", current_function_name,
806 prologue_size + function_size + epilogue_size, function_size);
807 commands_in_file += prologue_size + function_size + epilogue_size;
808 commands_in_prologues += prologue_size;
809 commands_in_epilogues += epilogue_size;
813 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
814 machine for a memory operand of mode MODE. */
817 legitimate_address_p (mode, x, strict)
818 enum machine_mode mode;
822 enum reg_class r = NO_REGS;
824 if (TARGET_ALL_DEBUG)
826 fprintf (stderr, "mode: (%s) %s %s %s %s:",
828 strict ? "(strict)": "",
829 reload_completed ? "(reload_completed)": "",
830 reload_in_progress ? "(reload_in_progress)": "",
831 reg_renumber ? "(reg_renumber)" : "");
832 if (GET_CODE (x) == PLUS
833 && REG_P (XEXP (x, 0))
834 && GET_CODE (XEXP (x, 1)) == CONST_INT
835 && INTVAL (XEXP (x, 1)) >= 0
836 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
839 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
840 true_regnum (XEXP (x, 0)));
843 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
844 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
846 else if (CONSTANT_ADDRESS_P (x))
848 else if (GET_CODE (x) == PLUS
849 && REG_P (XEXP (x, 0))
850 && GET_CODE (XEXP (x, 1)) == CONST_INT
851 && INTVAL (XEXP (x, 1)) >= 0)
853 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
857 || REGNO (XEXP (x,0)) == REG_Y
858 || REGNO (XEXP (x,0)) == REG_Z)
859 r = BASE_POINTER_REGS;
860 if (XEXP (x,0) == frame_pointer_rtx
861 || XEXP (x,0) == arg_pointer_rtx)
862 r = BASE_POINTER_REGS;
864 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
867 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
868 && REG_P (XEXP (x, 0))
869 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
870 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
874 if (TARGET_ALL_DEBUG)
876 fprintf (stderr, " ret = %c\n", r);
878 return r == NO_REGS ? 0 : (int)r;
881 /* Attempts to replace X with a valid
882 memory address for an operand of mode MODE */
885 legitimize_address (x, oldx, mode)
888 enum machine_mode mode;
891 if (TARGET_ALL_DEBUG)
893 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
897 if (GET_CODE (oldx) == PLUS
898 && REG_P (XEXP (oldx,0)))
900 if (REG_P (XEXP (oldx,1)))
901 x = force_reg (GET_MODE (oldx), oldx);
902 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
904 int offs = INTVAL (XEXP (oldx,1));
905 if (frame_pointer_rtx != XEXP (oldx,0))
906 if (offs > MAX_LD_OFFSET (mode))
908 if (TARGET_ALL_DEBUG)
909 fprintf (stderr, "force_reg (big offset)\n");
910 x = force_reg (GET_MODE (oldx), oldx);
918 /* Return a pointer register name as a string */
921 ptrreg_to_str (regno)
926 case REG_X: return "X";
927 case REG_Y: return "Y";
928 case REG_Z: return "Z";
935 /* Return the condition name as a string.
936 Used in conditional jump constructing */
949 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
954 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
967 /* Output ADDR to FILE as address */
970 print_operand_address (file, addr)
974 switch (GET_CODE (addr))
977 fprintf (file, ptrreg_to_str (REGNO (addr)));
981 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
985 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
989 if (CONSTANT_ADDRESS_P (addr)
990 && (SYMBOL_REF_FLAG (addr) || GET_CODE (addr) == LABEL_REF))
992 fprintf (file, "pm(");
993 output_addr_const (file,addr);
997 output_addr_const (file, addr);
1002 /* Output X as assembler operand to file FILE */
1005 print_operand (file, x, code)
1012 if (code >= 'A' && code <= 'D')
1022 if (x == zero_reg_rtx)
1023 fprintf (file, "__zero_reg__");
1025 fprintf (file, reg_names[true_regnum (x) + abcd]);
1027 else if (GET_CODE (x) == CONST_INT)
1028 fprintf (file, "%d", INTVAL (x) + abcd);
1029 else if (GET_CODE (x) == MEM)
1031 rtx addr = XEXP (x,0);
1033 if (CONSTANT_P (addr) && abcd)
1036 output_address (addr);
1037 fprintf (file, ")+%d", abcd);
1039 else if (code == 'o')
1041 if (GET_CODE (addr) != PLUS)
1042 fatal_insn ("Bad address, not (reg+disp):", addr);
1044 print_operand (file, XEXP (addr, 1), 0);
1046 else if (GET_CODE (addr) == PLUS)
1048 print_operand_address (file, XEXP (addr,0));
1049 if (REGNO (XEXP (addr, 0)) == REG_X)
1050 fatal_insn ("Internal compiler bug.\nBad address:"
1053 print_operand (file, XEXP (addr,1), code);
1056 print_operand_address (file, addr);
1058 else if (GET_CODE (x) == CONST_DOUBLE)
1062 if (GET_MODE (x) != SFmode)
1063 fatal_insn ("Internal compiler bug. Unknown mode:", x);
1064 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1065 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1066 asm_fprintf (file, "0x%lx", val);
1068 else if (code == 'j')
1069 asm_fprintf (file, cond_string (GET_CODE (x)));
1070 else if (code == 'k')
1071 asm_fprintf (file, cond_string (reverse_condition (GET_CODE (x))));
1073 print_operand_address (file, x);
1076 /* Recognize operand OP of mode MODE used in call instructions */
1079 call_insn_operand (op, mode)
1081 enum machine_mode mode ATTRIBUTE_UNUSED;
1083 if (GET_CODE (op) == MEM)
1085 rtx inside = XEXP (op, 0);
1086 if (register_operand (inside, Pmode))
1088 if (CONSTANT_ADDRESS_P (inside))
1094 /* Update the condition code in the INSN. */
1097 notice_update_cc (body, insn)
1098 rtx body ATTRIBUTE_UNUSED;
1103 switch (get_attr_cc (insn))
1106 /* Insn does not affect CC at all. */
1114 set = single_set (insn);
1118 cc_status.flags |= CC_NO_OVERFLOW;
1119 cc_status.value1 = SET_DEST (set);
1124 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1125 The V flag may or may not be known but that's ok because
1126 alter_cond will change tests to use EQ/NE. */
1127 set = single_set (insn);
1131 cc_status.value1 = SET_DEST (set);
1132 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1137 set = single_set (insn);
1140 cc_status.value1 = SET_SRC (set);
1144 /* Insn doesn't leave CC in a usable state. */
1147 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1148 set = single_set (insn);
1151 rtx src = SET_SRC (set);
1153 if (GET_CODE (src) == ASHIFTRT
1154 && GET_MODE (src) == QImode)
1156 rtx x = XEXP (src, 1);
1158 if (GET_CODE (x) == CONST_INT
1161 cc_status.value1 = SET_DEST (set);
1162 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1170 /* Return maximum number of consecutive registers of
1171 class CLASS needed to hold a value of mode MODE. */
1174 class_max_nregs (class, mode)
1175 enum reg_class class ATTRIBUTE_UNUSED;
1176 enum machine_mode mode;
1178 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1181 /* Choose mode for jump insn:
1182 1 - relative jump in range -63 <= x <= 62 ;
1183 2 - relative jump in range -2046 <= x <= 2045 ;
1184 3 - absolute jump (only for ATmega[16]03). */
1187 avr_jump_mode (x, insn)
1188 rtx x; /* jump operand */
1189 rtx insn; /* jump insn */
1191 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1192 ? XEXP (x, 0) : x));
1193 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1194 int jump_distance = cur_addr - dest_addr;
1196 if (-63 <= jump_distance && jump_distance <= 62)
1198 else if (-2046 <= jump_distance && jump_distance <= 2045)
1206 /* return an AVR condition jump commands.
1207 X is a comparison RTX.
1208 LEN is a number returned by avr_jump_mode function.
1209 if REVERSE nonzero then condition code in X must be reversed. */
1212 ret_cond_branch (x, len, reverse)
1217 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1222 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1223 return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1225 len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1226 AS1 (brmi,_PC_+2) CR_TAB
1228 (AS1 (breq,_PC_+6) CR_TAB
1229 AS1 (brmi,_PC_+4) CR_TAB
1233 return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1235 len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1236 AS1 (brlt,_PC_+2) CR_TAB
1238 (AS1 (breq,_PC_+6) CR_TAB
1239 AS1 (brlt,_PC_+4) CR_TAB
1242 return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1244 len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1245 AS1 (brlo,_PC_+2) CR_TAB
1247 (AS1 (breq,_PC_+6) CR_TAB
1248 AS1 (brlo,_PC_+4) CR_TAB
1251 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1252 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1254 len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1255 AS1 (brpl,_PC_+2) CR_TAB
1257 (AS1 (breq,_PC_+2) CR_TAB
1258 AS1 (brpl,_PC_+4) CR_TAB
1261 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1263 len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1264 AS1 (brge,_PC_+2) CR_TAB
1266 (AS1 (breq,_PC_+2) CR_TAB
1267 AS1 (brge,_PC_+4) CR_TAB
1270 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1272 len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1273 AS1 (brsh,_PC_+2) CR_TAB
1275 (AS1 (breq,_PC_+2) CR_TAB
1276 AS1 (brsh,_PC_+4) CR_TAB
1284 return AS1 (br%k1,%0);
1286 return (AS1 (br%j1,_PC_+2) CR_TAB
1289 return (AS1 (br%j1,_PC_+4) CR_TAB
1298 return AS1 (br%j1,%0);
1300 return (AS1 (br%k1,_PC_+2) CR_TAB
1303 return (AS1 (br%k1,_PC_+4) CR_TAB
1311 /* Predicate function for immediate operand which fits to byte (8bit) */
1314 byte_immediate_operand (op, mode)
1316 enum machine_mode mode ATTRIBUTE_UNUSED;
1318 return (GET_CODE (op) == CONST_INT
1319 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1322 /* Output all insn addresses and their sizes into the assembly language
1323 output file. This is helpful for debugging whether the length attributes
1324 in the md file are correct.
1325 Output insn cost for next insn. */
1328 final_prescan_insn (insn, operand, num_operands)
1329 rtx insn, *operand ATTRIBUTE_UNUSED;
1330 int num_operands ATTRIBUTE_UNUSED;
1332 int uid = INSN_UID (insn);
1334 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1336 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1337 INSN_ADDRESSES (uid),
1338 INSN_ADDRESSES (uid) - last_insn_address,
1339 rtx_cost (PATTERN (insn), INSN));
1341 last_insn_address = INSN_ADDRESSES (uid);
1343 if (TARGET_RTL_DUMP)
1345 fprintf (asm_out_file, "/*****************\n");
1346 print_rtl_single (asm_out_file, insn);
1347 fprintf (asm_out_file, "*****************/\n");
1351 /* Return 0 if undefined, 1 if always true or always false. */
1354 avr_simplify_comparision_p (mode, operator, x)
1355 enum machine_mode mode;
1359 unsigned int max = (mode == QImode ? 0xff :
1360 mode == HImode ? 0xffff :
1361 mode == SImode ? 0xffffffffU : 0);
1362 if (max && operator && GET_CODE (x) == CONST_INT)
1364 if (unsigned_condition (operator) != operator)
1367 if (max != (INTVAL (x) & max)
1368 && INTVAL (x) != 0xff)
1375 /* Returns nonzero if REGNO is the number of a hard
1376 register in which function arguments are sometimes passed. */
1379 function_arg_regno_p(r)
1382 return (r >= 8 && r <= 25);
1385 /* Initializing the variable cum for the state at the beginning
1386 of the argument list. */
1389 init_cumulative_args (cum, fntype, libname, indirect)
1390 CUMULATIVE_ARGS *cum;
1393 int indirect ATTRIBUTE_UNUSED;
1396 cum->regno = FIRST_CUM_REG;
1399 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1400 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1401 != void_type_node));
1407 /* Returns the number of registers to allocate for a function argument. */
1410 avr_num_arg_regs (mode, type)
1411 enum machine_mode mode;
1416 if (mode == BLKmode)
1417 size = int_size_in_bytes (type);
1419 size = GET_MODE_SIZE (mode);
1421 /* Align all function arguments to start in even-numbered registers.
1422 Odd-sized arguments leave holes above them. */
1424 return (size + 1) & ~1;
1427 /* Controls whether a function argument is passed
1428 in a register, and which register. */
1431 function_arg (cum, mode, type, named)
1432 CUMULATIVE_ARGS *cum;
1433 enum machine_mode mode;
1435 int named ATTRIBUTE_UNUSED;
1437 int bytes = avr_num_arg_regs (mode, type);
1439 if (cum->nregs && bytes <= cum->nregs)
1440 return gen_rtx (REG, mode, cum->regno - bytes);
1445 /* Update the summarizer variable CUM to advance past an argument
1446 in the argument list. */
1449 function_arg_advance (cum, mode, type, named)
1450 CUMULATIVE_ARGS *cum; /* current arg information */
1451 enum machine_mode mode; /* current arg mode */
1452 tree type; /* type of the argument or 0 if lib support */
1453 int named ATTRIBUTE_UNUSED; /* whether or not the argument was named */
1455 int bytes = avr_num_arg_regs (mode, type);
1457 cum->nregs -= bytes;
1458 cum->regno -= bytes;
1460 if (cum->nregs <= 0)
1463 cum->regno = FIRST_CUM_REG;
1467 /***********************************************************************
1468 Functions for outputting various mov's for a various modes
1469 ************************************************************************/
1471 output_movqi (insn, operands, l)
1477 rtx dest = operands[0];
1478 rtx src = operands[1];
1486 if (register_operand (dest, QImode))
1488 if (register_operand (src, QImode)) /* mov r,r */
1490 if (test_hard_reg_class (STACK_REG, dest))
1491 return AS2 (out,%0,%1);
1492 else if (test_hard_reg_class (STACK_REG, src))
1493 return AS2 (in,%0,%1);
1495 return AS2 (mov,%0,%1);
1497 else if (CONSTANT_P (src))
1499 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1500 return AS2 (ldi,%0,lo8(%1));
1502 if (GET_CODE (src) == CONST_INT)
1504 if (src == const0_rtx) /* mov r,L */
1505 return AS1 (clr,%0);
1506 else if (src == const1_rtx)
1508 if (reg_was_0 (insn, dest))
1509 return AS1 (inc,%0 ; reg_was_0);
1512 return (AS1 (clr,%0) CR_TAB
1515 else if (src == constm1_rtx)
1517 /* Immediate constants -1 to any register */
1518 if (reg_was_0 (insn, dest))
1519 return AS1 (dec,%0 ; reg_was_0);
1522 return (AS1 (clr,%0) CR_TAB
1527 int bit_nr = exact_log2 (INTVAL (src));
1531 if (reg_was_0 (insn, dest))
1535 output_asm_insn ("set ; reg_was_0", operands);
1541 output_asm_insn ((AS1 (clr,%0) CR_TAB
1545 avr_output_bld (operands, bit_nr);
1552 /* Last resort, larger than loading from memory. */
1554 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1555 AS2 (ldi,r31,lo8(%1)) CR_TAB
1556 AS2 (mov,%0,r31) CR_TAB
1557 AS2 (mov,r31,__tmp_reg__));
1559 else if (GET_CODE (src) == MEM)
1560 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1562 else if (GET_CODE (dest) == MEM)
1564 const char *template;
1566 if (src == const0_rtx)
1567 operands[1] = zero_reg_rtx;
1569 template = out_movqi_mr_r (insn, operands, real_l);
1572 output_asm_insn (template, operands);
1581 output_movhi (insn, operands, l)
1587 rtx dest = operands[0];
1588 rtx src = operands[1];
1594 if (register_operand (dest, HImode))
1596 if (register_operand (src, HImode)) /* mov r,r */
1598 if (test_hard_reg_class (STACK_REG, dest))
1600 if (TARGET_TINY_STACK)
1603 return AS2 (out,__SP_L__,%A1);
1605 else if (TARGET_NO_INTERRUPTS)
1608 return (AS2 (out,__SP_H__,%B1) CR_TAB
1609 AS2 (out,__SP_L__,%A1));
1613 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1615 AS2 (out,__SP_H__,%B1) CR_TAB
1616 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1617 AS2 (out,__SP_L__,%A1));
1619 else if (test_hard_reg_class (STACK_REG, src))
1622 return (AS2 (in,%A0,__SP_L__) CR_TAB
1623 AS2 (in,%B0,__SP_H__));
1629 return (AS2 (movw,%0,%1));
1632 if (true_regnum (dest) > true_regnum (src))
1635 return (AS2 (mov,%B0,%B1) CR_TAB
1641 return (AS2 (mov,%A0,%A1) CR_TAB
1645 else if (CONSTANT_P (src))
1647 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1649 if (byte_immediate_operand (src, HImode)
1650 && reg_was_0 (insn, dest))
1653 return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0));
1657 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1658 AS2 (ldi,%B0,hi8(%1)));
1661 if (GET_CODE (src) == CONST_INT)
1663 if (src == const0_rtx) /* mov r,L */
1666 return (AS1 (clr,%A0) CR_TAB
1669 else if (src == const1_rtx)
1671 if (reg_was_0 (insn, dest))
1674 return AS1 (inc,%0 ; reg_was_0);
1678 return (AS1 (clr,%A0) CR_TAB
1679 AS1 (clr,%B0) CR_TAB
1682 else if (src == constm1_rtx)
1684 /* Immediate constants -1 to any register */
1685 if (reg_was_0 (insn, dest))
1688 return (AS1 (dec,%A0 ; reg_was_0) CR_TAB
1693 return (AS1 (clr,%0) CR_TAB
1694 AS1 (dec,%A0) CR_TAB
1699 int bit_nr = exact_log2 (INTVAL (src));
1703 if (reg_was_0 (insn, dest))
1707 output_asm_insn ("set ; reg_was_0", operands);
1713 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1714 AS1 (clr,%B0) CR_TAB
1718 avr_output_bld (operands, bit_nr);
1724 if ((INTVAL (src) & 0xff) == 0)
1727 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1728 AS1 (clr,%A0) CR_TAB
1729 AS2 (ldi,r31,hi8(%1)) CR_TAB
1730 AS2 (mov,%B0,r31) CR_TAB
1731 AS2 (mov,r31,__tmp_reg__));
1733 else if ((INTVAL (src) & 0xff00) == 0)
1736 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1737 AS2 (ldi,r31,lo8(%1)) CR_TAB
1738 AS2 (mov,%A0,r31) CR_TAB
1739 AS1 (clr,%B0) CR_TAB
1740 AS2 (mov,r31,__tmp_reg__));
1744 /* Last resort, equal to loading from memory. */
1746 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1747 AS2 (ldi,r31,lo8(%1)) CR_TAB
1748 AS2 (mov,%A0,r31) CR_TAB
1749 AS2 (ldi,r31,hi8(%1)) CR_TAB
1750 AS2 (mov,%B0,r31) CR_TAB
1751 AS2 (mov,r31,__tmp_reg__));
1753 else if (GET_CODE (src) == MEM)
1754 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1756 else if (GET_CODE (dest) == MEM)
1758 const char *template;
1760 if (src == const0_rtx)
1761 operands[1] = zero_reg_rtx;
1763 template = out_movhi_mr_r (insn, operands, real_l);
1766 output_asm_insn (template, operands);
1771 fatal_insn ("Invalid insn:", insn);
1776 out_movqi_r_mr (insn, op, l)
1779 int *l; /* instruction length */
1783 rtx x = XEXP (src, 0);
1789 if (CONSTANT_ADDRESS_P (x))
1791 if (io_address_p (x, 1))
1794 return AS2 (in,%0,%1-0x20);
1797 return AS2 (lds,%0,%1);
1799 /* memory access by reg+disp */
1800 else if (GET_CODE (x) == PLUS
1801 && REG_P (XEXP (x,0))
1802 && GET_CODE (XEXP (x,1)) == CONST_INT)
1804 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
1806 int disp = INTVAL (XEXP (x,1));
1807 if (REGNO (XEXP (x,0)) != REG_Y)
1808 fatal_insn ("Incorrect insn:",insn);
1810 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1811 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1812 AS2 (ldd,%0,Y+63) CR_TAB
1813 AS2 (sbiw,r28,%o1-63));
1815 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1816 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1817 AS2 (ld,%0,Y) CR_TAB
1818 AS2 (subi,r28,lo8(%o1)) CR_TAB
1819 AS2 (sbci,r29,hi8(%o1)));
1821 else if (REGNO (XEXP (x,0)) == REG_X)
1823 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1824 it but I have this situation with extremal optimizing options. */
1825 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
1826 || reg_unused_after (insn, XEXP (x,0)))
1827 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1830 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1831 AS2 (ld,%0,X) CR_TAB
1832 AS2 (sbiw,r26,%o1));
1835 return AS2 (ldd,%0,%1);
1838 return AS2 (ld,%0,%1);
1842 out_movhi_r_mr (insn, op, l)
1845 int *l; /* instruction length */
1849 rtx base = XEXP (src, 0);
1850 int reg_dest = true_regnum (dest);
1851 int reg_base = true_regnum (base);
1859 if (reg_dest == reg_base) /* R = (R) */
1862 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1863 AS2 (ld,%B0,%1) CR_TAB
1864 AS2 (mov,%A0,__tmp_reg__));
1866 else if (reg_base == REG_X) /* (R26) */
1868 if (reg_unused_after (insn, base))
1871 return (AS2 (ld,%A0,X+) CR_TAB
1875 return (AS2 (ld,%A0,X+) CR_TAB
1876 AS2 (ld,%B0,X) CR_TAB
1882 return (AS2 (ld,%A0,%1) CR_TAB
1883 AS2 (ldd,%B0,%1+1));
1886 else if (GET_CODE (base) == PLUS) /* (R + i) */
1888 int disp = INTVAL (XEXP (base, 1));
1889 int reg_base = true_regnum (XEXP (base, 0));
1891 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
1893 if (REGNO (XEXP (base, 0)) != REG_Y)
1894 fatal_insn ("Incorrect insn:",insn);
1896 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1897 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
1898 AS2 (ldd,%A0,Y+62) CR_TAB
1899 AS2 (ldd,%B0,Y+63) CR_TAB
1900 AS2 (sbiw,r28,%o1-62));
1902 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1903 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1904 AS2 (ld,%A0,Y) CR_TAB
1905 AS2 (ldd,%B0,Y+1) CR_TAB
1906 AS2 (subi,r28,lo8(%o1)) CR_TAB
1907 AS2 (sbci,r29,hi8(%o1)));
1909 if (reg_base == REG_X)
1911 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1912 it but I have this situation with extremal
1913 optimization options. */
1916 if (reg_base == reg_dest)
1917 return (AS2 (adiw,r26,%o1) CR_TAB
1918 AS2 (ld,__tmp_reg__,X+) CR_TAB
1919 AS2 (ld,%B0,X) CR_TAB
1920 AS2 (mov,%A0,__tmp_reg__));
1922 return (AS2 (adiw,r26,%o1) CR_TAB
1923 AS2 (ld,%A0,X+) CR_TAB
1924 AS2 (ld,%B0,X) CR_TAB
1925 AS2 (sbiw,r26,%o1+1));
1928 if (reg_base == reg_dest)
1931 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
1932 AS2 (ldd,%B0,%B1) CR_TAB
1933 AS2 (mov,%A0,__tmp_reg__));
1937 return (AS2 (ldd,%A0,%A1) CR_TAB
1940 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
1942 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1943 fatal_insn ("Incorrect insn:", insn);
1946 return (AS2 (ld,%B0,%1) CR_TAB
1949 else if (GET_CODE (base) == POST_INC) /* (R++) */
1951 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1952 fatal_insn ("Incorrect insn:", insn);
1955 return (AS2 (ld,%A0,%1) CR_TAB
1958 else if (CONSTANT_ADDRESS_P (base))
1960 if (io_address_p (base, 2))
1963 return (AS2 (in,%A0,%A1-0x20) CR_TAB
1964 AS2 (in,%B0,%B1-0x20));
1967 return (AS2 (lds,%A0,%A1) CR_TAB
1971 fatal_insn ("Unknown move insn:",insn);
1976 out_movsi_r_mr (insn, op, l)
1979 int *l; /* instruction length */
1983 rtx base = XEXP (src, 0);
1984 int reg_dest = true_regnum (dest);
1985 int reg_base = true_regnum (base);
1993 if (reg_base == REG_X) /* (R26) */
1995 if (reg_dest == REG_X)
1996 /* "ld r26,-X" is undefined */
1997 return *l=7, (AS2 (adiw,r26,3) CR_TAB
1998 AS2 (ld,r29,X) CR_TAB
1999 AS2 (ld,r28,-X) CR_TAB
2000 AS2 (ld,__tmp_reg__,-X) CR_TAB
2001 AS2 (sbiw,r26,1) CR_TAB
2002 AS2 (ld,r26,X) CR_TAB
2003 AS2 (mov,r27,__tmp_reg__));
2004 else if (reg_dest == REG_X - 2)
2005 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2006 AS2 (ld,%B0,X+) CR_TAB
2007 AS2 (ld,__tmp_reg__,X+) CR_TAB
2008 AS2 (ld,%D0,X) CR_TAB
2009 AS2 (mov,%C0,__tmp_reg__));
2010 else if (reg_unused_after (insn, base))
2011 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
2012 AS2 (ld,%B0,X+) CR_TAB
2013 AS2 (ld,%C0,X+) CR_TAB
2016 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2017 AS2 (ld,%B0,X+) CR_TAB
2018 AS2 (ld,%C0,X+) CR_TAB
2019 AS2 (ld,%D0,X) CR_TAB
2024 if (reg_dest == reg_base)
2025 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2026 AS2 (ldd,%C0,%1+2) CR_TAB
2027 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2028 AS2 (ld,%A0,%1) CR_TAB
2029 AS2 (mov,%B0,__tmp_reg__));
2030 else if (reg_base == reg_dest + 2)
2031 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2032 AS2 (ldd,%B0,%1+1) CR_TAB
2033 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2034 AS2 (ldd,%D0,%1+3) CR_TAB
2035 AS2 (mov,%C0,__tmp_reg__));
2037 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2038 AS2 (ldd,%B0,%1+1) CR_TAB
2039 AS2 (ldd,%C0,%1+2) CR_TAB
2040 AS2 (ldd,%D0,%1+3));
2043 else if (GET_CODE (base) == PLUS) /* (R + i) */
2045 int disp = INTVAL (XEXP (base, 1));
2047 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2049 if (REGNO (XEXP (base, 0)) != REG_Y)
2050 fatal_insn ("Incorrect insn:",insn);
2052 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2053 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2054 AS2 (ldd,%A0,Y+60) CR_TAB
2055 AS2 (ldd,%B0,Y+61) CR_TAB
2056 AS2 (ldd,%C0,Y+62) CR_TAB
2057 AS2 (ldd,%D0,Y+63) CR_TAB
2058 AS2 (sbiw,r28,%o1-60));
2060 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2061 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2062 AS2 (ld,%A0,Y) CR_TAB
2063 AS2 (ldd,%B0,Y+1) CR_TAB
2064 AS2 (ldd,%C0,Y+2) CR_TAB
2065 AS2 (ldd,%D0,Y+3) CR_TAB
2066 AS2 (subi,r28,lo8(%o1)) CR_TAB
2067 AS2 (sbci,r29,hi8(%o1)));
2070 reg_base = true_regnum (XEXP (base, 0));
2071 if (reg_base == REG_X)
2074 if (reg_dest == REG_X)
2077 /* "ld r26,-X" is undefined */
2078 return (AS2 (adiw,r26,%o1+3) CR_TAB
2079 AS2 (ld,r29,X) CR_TAB
2080 AS2 (ld,r28,-X) CR_TAB
2081 AS2 (ld,__tmp_reg__,-X) CR_TAB
2082 AS2 (sbiw,r26,1) CR_TAB
2083 AS2 (ld,r26,X) CR_TAB
2084 AS2 (mov,r27,__tmp_reg__));
2087 if (reg_dest == REG_X - 2)
2088 return (AS2 (adiw,r26,%o1) CR_TAB
2089 AS2 (ld,r24,X+) CR_TAB
2090 AS2 (ld,r25,X+) CR_TAB
2091 AS2 (ld,__tmp_reg__,X+) CR_TAB
2092 AS2 (ld,r27,X) CR_TAB
2093 AS2 (mov,r26,__tmp_reg__));
2095 return (AS2 (adiw,r26,%o1) CR_TAB
2096 AS2 (ld,%A0,X+) CR_TAB
2097 AS2 (ld,%B0,X+) CR_TAB
2098 AS2 (ld,%C0,X+) CR_TAB
2099 AS2 (ld,%D0,X) CR_TAB
2100 AS2 (sbiw,r26,%o1+3));
2102 if (reg_dest == reg_base)
2103 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2104 AS2 (ldd,%C0,%C1) CR_TAB
2105 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2106 AS2 (ldd,%A0,%A1) CR_TAB
2107 AS2 (mov,%B0,__tmp_reg__));
2108 else if (reg_dest == reg_base - 2)
2109 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2110 AS2 (ldd,%B0,%B1) CR_TAB
2111 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2112 AS2 (ldd,%D0,%D1) CR_TAB
2113 AS2 (mov,%C0,__tmp_reg__));
2114 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2115 AS2 (ldd,%B0,%B1) CR_TAB
2116 AS2 (ldd,%C0,%C1) CR_TAB
2119 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2120 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2121 AS2 (ld,%C0,%1) CR_TAB
2122 AS2 (ld,%B0,%1) CR_TAB
2124 else if (GET_CODE (base) == POST_INC) /* (R++) */
2125 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2126 AS2 (ld,%B0,%1) CR_TAB
2127 AS2 (ld,%C0,%1) CR_TAB
2129 else if (CONSTANT_ADDRESS_P (base))
2130 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2131 AS2 (lds,%B0,%B1) CR_TAB
2132 AS2 (lds,%C0,%C1) CR_TAB
2135 fatal_insn ("Unknown move insn:",insn);
2140 out_movsi_mr_r (insn, op, l)
2147 rtx base = XEXP (dest, 0);
2148 int reg_base = true_regnum (base);
2149 int reg_src = true_regnum (src);
2155 if (CONSTANT_ADDRESS_P (base))
2156 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2157 AS2 (sts,%B0,%B1) CR_TAB
2158 AS2 (sts,%C0,%C1) CR_TAB
2160 if (reg_base > 0) /* (r) */
2162 if (reg_base == REG_X) /* (R26) */
2164 if (reg_src == REG_X)
2166 /* "st X+,r26" is undefined */
2167 if (reg_unused_after (insn, base))
2168 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2169 AS2 (st,X,r26) CR_TAB
2170 AS2 (adiw,r26,1) CR_TAB
2171 AS2 (st,X+,__tmp_reg__) CR_TAB
2172 AS2 (st,X+,r28) CR_TAB
2175 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2176 AS2 (st,X,r26) CR_TAB
2177 AS2 (adiw,r26,1) CR_TAB
2178 AS2 (st,X+,__tmp_reg__) CR_TAB
2179 AS2 (st,X+,r28) CR_TAB
2180 AS2 (st,X,r29) CR_TAB
2183 else if (reg_base == reg_src + 2)
2185 if (reg_unused_after (insn, base))
2186 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2187 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2188 AS2 (st,%0+,%A1) CR_TAB
2189 AS2 (st,%0+,%B1) CR_TAB
2190 AS2 (st,%0+,__zero_reg__) CR_TAB
2191 AS2 (st,%0,__tmp_reg__) CR_TAB
2192 AS1 (clr,__zero_reg__));
2194 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2195 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2196 AS2 (st,%0+,%A1) CR_TAB
2197 AS2 (st,%0+,%B1) CR_TAB
2198 AS2 (st,%0+,__zero_reg__) CR_TAB
2199 AS2 (st,%0,__tmp_reg__) CR_TAB
2200 AS1 (clr,__zero_reg__) CR_TAB
2203 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2204 AS2 (st,%0+,%B1) CR_TAB
2205 AS2 (st,%0+,%C1) CR_TAB
2206 AS2 (st,%0,%D1) CR_TAB
2210 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2211 AS2 (std,%0+1,%B1) CR_TAB
2212 AS2 (std,%0+2,%C1) CR_TAB
2213 AS2 (std,%0+3,%D1));
2215 else if (GET_CODE (base) == PLUS) /* (R + i) */
2217 int disp = INTVAL (XEXP (base, 1));
2218 reg_base = REGNO (XEXP (base, 0));
2219 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2221 if (reg_base != REG_Y)
2222 fatal_insn ("Incorrect insn:",insn);
2224 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2225 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2226 AS2 (std,Y+60,%A1) CR_TAB
2227 AS2 (std,Y+61,%B1) CR_TAB
2228 AS2 (std,Y+62,%C1) CR_TAB
2229 AS2 (std,Y+63,%D1) CR_TAB
2230 AS2 (sbiw,r28,%o0-60));
2232 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2233 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2234 AS2 (st,Y,%A1) CR_TAB
2235 AS2 (std,Y+1,%B1) CR_TAB
2236 AS2 (std,Y+2,%C1) CR_TAB
2237 AS2 (std,Y+3,%D1) CR_TAB
2238 AS2 (subi,r28,lo8(%o0)) CR_TAB
2239 AS2 (sbci,r29,hi8(%o0)));
2241 if (reg_base == REG_X)
2244 if (reg_src == REG_X)
2247 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2248 AS2 (mov,__zero_reg__,r27) CR_TAB
2249 AS2 (adiw,r26,%o0) CR_TAB
2250 AS2 (st,X+,__tmp_reg__) CR_TAB
2251 AS2 (st,X+,__zero_reg__) CR_TAB
2252 AS2 (st,X+,r28) CR_TAB
2253 AS2 (st,X,r29) CR_TAB
2254 AS1 (clr,__zero_reg__) CR_TAB
2255 AS2 (sbiw,r26,%o0+3));
2257 else if (reg_src == REG_X - 2)
2260 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2261 AS2 (mov,__zero_reg__,r27) CR_TAB
2262 AS2 (adiw,r26,%o0) CR_TAB
2263 AS2 (st,X+,r24) CR_TAB
2264 AS2 (st,X+,r25) CR_TAB
2265 AS2 (st,X+,__tmp_reg__) CR_TAB
2266 AS2 (st,X,__zero_reg__) CR_TAB
2267 AS1 (clr,__zero_reg__) CR_TAB
2268 AS2 (sbiw,r26,%o0+3));
2271 return (AS2 (adiw,r26,%o0) CR_TAB
2272 AS2 (st,X+,%A1) CR_TAB
2273 AS2 (st,X+,%B1) CR_TAB
2274 AS2 (st,X+,%C1) CR_TAB
2275 AS2 (st,X,%D1) CR_TAB
2276 AS2 (sbiw,r26,%o0+3));
2278 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2279 AS2 (std,%B0,%B1) CR_TAB
2280 AS2 (std,%C0,%C1) CR_TAB
2283 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2284 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2285 AS2 (st,%0,%C1) CR_TAB
2286 AS2 (st,%0,%B1) CR_TAB
2288 else if (GET_CODE (base) == POST_INC) /* (R++) */
2289 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2290 AS2 (st,%0,%B1) CR_TAB
2291 AS2 (st,%0,%C1) CR_TAB
2293 fatal_insn ("Unknown move insn:",insn);
2298 output_movsisf(insn, operands, l)
2304 rtx dest = operands[0];
2305 rtx src = operands[1];
2311 if (register_operand (dest, VOIDmode))
2313 if (register_operand (src, VOIDmode)) /* mov r,r */
2315 if (true_regnum (dest) > true_regnum (src))
2320 return (AS2 (movw,%C0,%C1) CR_TAB
2321 AS2 (movw,%A0,%A1));
2324 return (AS2 (mov,%D0,%D1) CR_TAB
2325 AS2 (mov,%C0,%C1) CR_TAB
2326 AS2 (mov,%B0,%B1) CR_TAB
2334 return (AS2 (movw,%A0,%A1) CR_TAB
2335 AS2 (movw,%C0,%C1));
2338 return (AS2 (mov,%A0,%A1) CR_TAB
2339 AS2 (mov,%B0,%B1) CR_TAB
2340 AS2 (mov,%C0,%C1) CR_TAB
2344 else if (CONSTANT_P (src))
2346 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2348 if (byte_immediate_operand (src, SImode)
2349 && reg_was_0 (insn, dest))
2352 return (AS2 (ldi,%A0,lo8(%1) ; reg_was_0));
2356 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2357 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2358 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2359 AS2 (ldi,%D0,hhi8(%1)));
2362 if (GET_CODE (src) == CONST_INT)
2364 const char *const clr_op0 =
2365 AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
2366 AS1 (clr,%B0) CR_TAB
2368 : (AS1 (clr,%A0) CR_TAB
2369 AS1 (clr,%B0) CR_TAB
2370 AS1 (clr,%C0) CR_TAB
2373 if (src == const0_rtx) /* mov r,L */
2375 *l = AVR_ENHANCED ? 3 : 4;
2378 else if (src == const1_rtx)
2380 if (reg_was_0 (insn, dest))
2383 return AS1 (inc,%A0 ; reg_was_0);
2386 output_asm_insn (clr_op0, operands);
2387 *l = AVR_ENHANCED ? 4 : 5;
2388 return AS1 (inc,%A0);
2390 else if (src == constm1_rtx)
2392 /* Immediate constants -1 to any register */
2393 if (reg_was_0 (insn, dest))
2398 return (AS1 (dec,%A0) CR_TAB
2399 AS1 (dec,%B0) CR_TAB
2400 AS2 (movw,%C0,%A0));
2403 return (AS1 (dec,%D0 ; reg_was_0) CR_TAB
2404 AS1 (dec,%C0) CR_TAB
2405 AS1 (dec,%B0) CR_TAB
2411 return (AS1 (clr,%A0) CR_TAB
2412 AS1 (dec,%A0) CR_TAB
2413 AS2 (mov,%B0,%A0) CR_TAB
2414 AS2 (movw,%C0,%A0));
2417 return (AS1 (clr,%A0) CR_TAB
2418 AS1 (dec,%A0) CR_TAB
2419 AS2 (mov,%B0,%A0) CR_TAB
2420 AS2 (mov,%C0,%A0) CR_TAB
2425 int bit_nr = exact_log2 (INTVAL (src));
2429 if (reg_was_0 (insn, dest))
2433 output_asm_insn ("set ; reg_was_0", operands);
2437 *l = AVR_ENHANCED ? 5 : 6;
2440 output_asm_insn (clr_op0, operands);
2441 output_asm_insn ("set", operands);
2445 avr_output_bld (operands, bit_nr);
2452 /* Last resort, better than loading from memory. */
2454 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2455 AS2 (ldi,r31,lo8(%1)) CR_TAB
2456 AS2 (mov,%A0,r31) CR_TAB
2457 AS2 (ldi,r31,hi8(%1)) CR_TAB
2458 AS2 (mov,%B0,r31) CR_TAB
2459 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2460 AS2 (mov,%C0,r31) CR_TAB
2461 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2462 AS2 (mov,%D0,r31) CR_TAB
2463 AS2 (mov,r31,__tmp_reg__));
2465 else if (GET_CODE (src) == MEM)
2466 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2468 else if (GET_CODE (dest) == MEM)
2470 const char *template;
2472 if (src == const0_rtx)
2473 operands[1] = zero_reg_rtx;
2475 template = out_movsi_mr_r (insn, operands, real_l);
2478 output_asm_insn (template, operands);
2483 fatal_insn ("Invalid insn:", insn);
2488 out_movqi_mr_r (insn, op, l)
2491 int *l; /* instruction length */
2495 rtx x = XEXP (dest, 0);
2501 if (CONSTANT_ADDRESS_P (x))
2503 if (io_address_p (x, 1))
2506 return AS2 (out,%0-0x20,%1);
2509 return AS2 (sts,%0,%1);
2511 /* memory access by reg+disp */
2512 else if (GET_CODE (x) == PLUS
2513 && REG_P (XEXP (x,0))
2514 && GET_CODE (XEXP (x,1)) == CONST_INT)
2516 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
2518 int disp = INTVAL (XEXP (x,1));
2519 if (REGNO (XEXP (x,0)) != REG_Y)
2520 fatal_insn ("Incorrect insn:",insn);
2522 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2523 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2524 AS2 (std,Y+63,%1) CR_TAB
2525 AS2 (sbiw,r28,%o0-63));
2527 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2528 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2529 AS2 (st,Y,%1) CR_TAB
2530 AS2 (subi,r28,lo8(%o0)) CR_TAB
2531 AS2 (sbci,r29,hi8(%o0)));
2533 else if (REGNO (XEXP (x,0)) == REG_X)
2535 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
2537 if (reg_unused_after (insn, XEXP (x,0)))
2538 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2539 AS2 (adiw,r26,%o0) CR_TAB
2540 AS2 (st,X,__tmp_reg__));
2542 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2543 AS2 (adiw,r26,%o0) CR_TAB
2544 AS2 (st,X,__tmp_reg__) CR_TAB
2545 AS2 (sbiw,r26,%o0));
2549 if (reg_unused_after (insn, XEXP (x,0)))
2550 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2553 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2554 AS2 (st,X,%1) CR_TAB
2555 AS2 (sbiw,r26,%o0));
2559 return AS2 (std,%0,%1);
2562 return AS2 (st,%0,%1);
2566 out_movhi_mr_r (insn, op, l)
2573 rtx base = XEXP (dest, 0);
2574 int reg_base = true_regnum (base);
2575 int reg_src = true_regnum (src);
2579 if (CONSTANT_ADDRESS_P (base))
2581 if (io_address_p (base, 2))
2584 return (AS2 (out,%B0-0x20,%B1) CR_TAB
2585 AS2 (out,%A0-0x20,%A1));
2587 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2592 if (reg_base == REG_X)
2594 if (reg_src == REG_X)
2596 /* "st X+,r26" is undefined */
2597 if (reg_unused_after (insn, src))
2598 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2599 AS2 (st,X,r26) CR_TAB
2600 AS2 (adiw,r26,1) CR_TAB
2601 AS2 (st,X,__tmp_reg__));
2603 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2604 AS2 (st,X,r26) CR_TAB
2605 AS2 (adiw,r26,1) CR_TAB
2606 AS2 (st,X,__tmp_reg__) CR_TAB
2611 if (reg_unused_after (insn, base))
2612 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2615 return *l=3, (AS2 (st ,X+,%A1) CR_TAB
2616 AS2 (st ,X,%B1) CR_TAB
2621 return *l=2, (AS2 (st ,%0,%A1) CR_TAB
2622 AS2 (std,%0+1,%B1));
2624 else if (GET_CODE (base) == PLUS)
2626 int disp = INTVAL (XEXP (base, 1));
2627 reg_base = REGNO (XEXP (base, 0));
2628 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2630 if (reg_base != REG_Y)
2631 fatal_insn ("Incorrect insn:",insn);
2633 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2634 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
2635 AS2 (std,Y+62,%A1) CR_TAB
2636 AS2 (std,Y+63,%B1) CR_TAB
2637 AS2 (sbiw,r28,%o0-62));
2639 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2640 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2641 AS2 (st,Y,%A1) CR_TAB
2642 AS2 (std,Y+1,%B1) CR_TAB
2643 AS2 (subi,r28,lo8(%o0)) CR_TAB
2644 AS2 (sbci,r29,hi8(%o0)));
2646 if (reg_base == REG_X)
2649 if (reg_src == REG_X)
2652 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2653 AS2 (mov,__zero_reg__,r27) CR_TAB
2654 AS2 (adiw,r26,%o0) CR_TAB
2655 AS2 (st,X+,__tmp_reg__) CR_TAB
2656 AS2 (st,X,__zero_reg__) CR_TAB
2657 AS1 (clr,__zero_reg__) CR_TAB
2658 AS2 (sbiw,r26,%o0+1));
2661 return (AS2 (adiw,r26,%o0) CR_TAB
2662 AS2 (st,X+,%A1) CR_TAB
2663 AS2 (st,X,%B1) CR_TAB
2664 AS2 (sbiw,r26,%o0+1));
2666 return *l=2, (AS2 (std,%A0,%A1) CR_TAB
2669 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2670 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2672 else if (GET_CODE (base) == POST_INC) /* (R++) */
2673 return *l=2, (AS2 (st,%0,%A1) CR_TAB
2675 fatal_insn ("Unknown move insn:",insn);
2679 /* Return 1 if frame pointer for current function required */
2682 frame_pointer_required_p ()
2684 return (current_function_calls_alloca
2685 || current_function_args_info.nregs == 0
2686 || current_function_varargs
2687 || get_frame_size () > 0);
2690 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2693 compare_condition (insn)
2696 rtx next = next_real_insn (insn);
2697 RTX_CODE cond = UNKNOWN;
2698 if (next && GET_CODE (next) == JUMP_INSN)
2700 rtx pat = PATTERN (next);
2701 rtx src = SET_SRC (pat);
2702 rtx t = XEXP (src, 0);
2703 cond = GET_CODE (t);
2708 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2711 compare_sign_p (insn)
2714 RTX_CODE cond = compare_condition (insn);
2715 return (cond == GE || cond == LT);
2718 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2719 that needs to be swapped (GT, GTU, LE, LEU). */
2722 compare_diff_p (insn)
2725 RTX_CODE cond = compare_condition (insn);
2726 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2729 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2735 RTX_CODE cond = compare_condition (insn);
2736 return (cond == EQ || cond == NE);
2740 /* Output test instruction for HImode */
2747 if (compare_sign_p (insn))
2750 return AS1 (tst,%B0);
2752 if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2753 && compare_eq_p (insn))
2755 /* faster than sbiw if we can clobber the operand */
2757 return AS2 (or,%A0,%B0);
2759 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2762 return AS2 (sbiw,%0,0);
2765 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2766 AS2 (cpc,%B0,__zero_reg__));
2770 /* Output test instruction for SImode */
2777 if (compare_sign_p (insn))
2780 return AS1 (tst,%D0);
2782 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2785 return (AS2 (sbiw,%A0,0) CR_TAB
2786 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2787 AS2 (cpc,%D0,__zero_reg__));
2790 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2791 AS2 (cpc,%B0,__zero_reg__) CR_TAB
2792 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2793 AS2 (cpc,%D0,__zero_reg__));
2797 /* Generate asm equivalent for various shifts.
2798 Shift count is a CONST_INT, MEM or REG.
2799 This only handles cases that are not already
2800 carefully hand-optimized in ?sh??i3_out. */
2803 out_shift_with_cnt (template, insn, operands, len, t_len)
2804 const char *template;
2808 int t_len; /* Length of template. */
2812 int second_label = 1;
2813 int saved_in_tmp = 0;
2814 int use_zero_reg = 0;
2816 op[0] = operands[0];
2817 op[1] = operands[1];
2818 op[2] = operands[2];
2819 op[3] = operands[3];
2825 if (GET_CODE (operands[2]) == CONST_INT)
2827 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2828 int count = INTVAL (operands[2]);
2829 int max_len = 10; /* If larger than this, always use a loop. */
2831 if (count < 8 && !scratch)
2835 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2837 if (t_len * count <= max_len)
2839 /* Output shifts inline with no loop - faster. */
2841 *len = t_len * count;
2845 output_asm_insn (template, op);
2854 strcat (str, AS2 (ldi,%3,%2));
2856 else if (use_zero_reg)
2858 /* Hack to save one word: use __zero_reg__ as loop counter.
2859 Set one bit, then shift in a loop until it is 0 again. */
2861 op[3] = zero_reg_rtx;
2865 strcat (str, ("set" CR_TAB
2866 AS2 (bld,%3,%2-1)));
2870 /* No scratch register available, use one from LD_REGS (saved in
2871 __tmp_reg__) that doesn't overlap with registers to shift. */
2873 op[3] = gen_rtx (REG, QImode,
2874 ((true_regnum (operands[0]) - 1) & 15) + 16);
2875 op[4] = tmp_reg_rtx;
2879 *len = 3; /* Includes "mov %3,%4" after the loop. */
2881 strcat (str, (AS2 (mov,%4,%3) CR_TAB
2887 else if (GET_CODE (operands[2]) == MEM)
2891 op[3] = op_mov[0] = tmp_reg_rtx;
2895 out_movqi_r_mr (insn, op_mov, len);
2897 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
2899 else if (register_operand (operands[2], QImode))
2901 if (reg_unused_after (insn, operands[2]))
2905 op[3] = tmp_reg_rtx;
2907 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
2911 fatal_insn ("Bad shift insn:", insn);
2918 strcat (str, AS1 (rjmp,2f));
2922 *len += t_len + 2; /* template + dec + brXX */
2925 strcat (str, "\n1:\t");
2926 strcat (str, template);
2927 strcat (str, second_label ? "\n2:\t" : "\n\t");
2928 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
2929 strcat (str, CR_TAB);
2930 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
2932 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
2933 output_asm_insn (str, op);
2938 /* 8bit shift left ((char)x << i) */
2941 ashlqi3_out (insn, operands, len)
2944 int *len; /* insn length (may be NULL) */
2946 if (GET_CODE (operands[2]) == CONST_INT)
2953 switch (INTVAL (operands[2]))
2957 return AS1 (clr,%0);
2961 return AS1 (lsl,%0);
2965 return (AS1 (lsl,%0) CR_TAB
2970 return (AS1 (lsl,%0) CR_TAB
2975 if (test_hard_reg_class (LD_REGS, operands[0]))
2978 return (AS1 (swap,%0) CR_TAB
2979 AS2 (andi,%0,0xf0));
2982 return (AS1 (lsl,%0) CR_TAB
2988 if (test_hard_reg_class (LD_REGS, operands[0]))
2991 return (AS1 (swap,%0) CR_TAB
2993 AS2 (andi,%0,0xe0));
2996 return (AS1 (lsl,%0) CR_TAB
3003 if (test_hard_reg_class (LD_REGS, operands[0]))
3006 return (AS1 (swap,%0) CR_TAB
3009 AS2 (andi,%0,0xc0));
3012 return (AS1 (lsl,%0) CR_TAB
3021 return (AS1 (ror,%0) CR_TAB
3026 else if (CONSTANT_P (operands[2]))
3027 fatal_insn ("Internal compiler bug.\nIncorrect shift:", insn);
3029 out_shift_with_cnt (AS1 (lsl,%0),
3030 insn, operands, len, 1);
3035 /* 16bit shift left ((short)x << i) */
3038 ashlhi3_out (insn, operands, len)
3043 if (GET_CODE (operands[2]) == CONST_INT)
3045 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3046 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3053 switch (INTVAL (operands[2]))
3056 if (optimize_size && scratch)
3061 return (AS1 (swap,%A0) CR_TAB
3062 AS1 (swap,%B0) CR_TAB
3063 AS2 (andi,%B0,0xf0) CR_TAB
3064 AS2 (eor,%B0,%A0) CR_TAB
3065 AS2 (andi,%A0,0xf0) CR_TAB
3071 return (AS1 (swap,%A0) CR_TAB
3072 AS1 (swap,%B0) CR_TAB
3073 AS2 (ldi,%3,0xf0) CR_TAB
3074 AS2 (and,%B0,%3) CR_TAB
3075 AS2 (eor,%B0,%A0) CR_TAB
3076 AS2 (and,%A0,%3) CR_TAB
3079 break; /* optimize_size ? 6 : 8 */
3083 break; /* scratch ? 5 : 6 */
3087 return (AS1 (lsl,%A0) CR_TAB
3088 AS1 (rol,%B0) CR_TAB
3089 AS1 (swap,%A0) CR_TAB
3090 AS1 (swap,%B0) CR_TAB
3091 AS2 (andi,%B0,0xf0) CR_TAB
3092 AS2 (eor,%B0,%A0) CR_TAB
3093 AS2 (andi,%A0,0xf0) CR_TAB
3099 return (AS1 (lsl,%A0) CR_TAB
3100 AS1 (rol,%B0) CR_TAB
3101 AS1 (swap,%A0) CR_TAB
3102 AS1 (swap,%B0) CR_TAB
3103 AS2 (ldi,%3,0xf0) CR_TAB
3104 AS2 (and,%B0,%3) CR_TAB
3105 AS2 (eor,%B0,%A0) CR_TAB
3106 AS2 (and,%A0,%3) CR_TAB
3113 break; /* scratch ? 5 : 6 */
3115 return (AS1 (clr,__tmp_reg__) CR_TAB
3116 AS1 (lsr,%B0) CR_TAB
3117 AS1 (ror,%A0) CR_TAB
3118 AS1 (ror,__tmp_reg__) CR_TAB
3119 AS1 (lsr,%B0) CR_TAB
3120 AS1 (ror,%A0) CR_TAB
3121 AS1 (ror,__tmp_reg__) CR_TAB
3122 AS2 (mov,%B0,%A0) CR_TAB
3123 AS2 (mov,%A0,__tmp_reg__));
3127 return (AS1 (lsr,%B0) CR_TAB
3128 AS2 (mov,%B0,%A0) CR_TAB
3129 AS1 (clr,%A0) CR_TAB
3130 AS1 (ror,%B0) CR_TAB
3134 if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
3135 return *len = 1, AS1 (clr,%A0);
3137 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3142 return (AS2 (mov,%B0,%A0) CR_TAB
3143 AS1 (clr,%A0) CR_TAB
3148 return (AS2 (mov,%B0,%A0) CR_TAB
3149 AS1 (clr,%A0) CR_TAB
3150 AS1 (lsl,%B0) CR_TAB
3155 return (AS2 (mov,%B0,%A0) CR_TAB
3156 AS1 (clr,%A0) CR_TAB
3157 AS1 (lsl,%B0) CR_TAB
3158 AS1 (lsl,%B0) CR_TAB
3165 return (AS2 (mov,%B0,%A0) CR_TAB
3166 AS1 (clr,%A0) CR_TAB
3167 AS1 (swap,%B0) CR_TAB
3168 AS2 (andi,%B0,0xf0));
3173 return (AS2 (mov,%B0,%A0) CR_TAB
3174 AS1 (clr,%A0) CR_TAB
3175 AS1 (swap,%B0) CR_TAB
3176 AS2 (ldi,%3,0xf0) CR_TAB
3180 return (AS2 (mov,%B0,%A0) CR_TAB
3181 AS1 (clr,%A0) CR_TAB
3182 AS1 (lsl,%B0) CR_TAB
3183 AS1 (lsl,%B0) CR_TAB
3184 AS1 (lsl,%B0) CR_TAB
3191 return (AS2 (mov,%B0,%A0) CR_TAB
3192 AS1 (clr,%A0) CR_TAB
3193 AS1 (swap,%B0) CR_TAB
3194 AS1 (lsl,%B0) CR_TAB
3195 AS2 (andi,%B0,0xe0));
3197 if (AVR_ENHANCED && scratch)
3200 return (AS2 (ldi,%3,0x20) CR_TAB
3201 AS2 (mul,%A0,%3) CR_TAB
3202 AS2 (mov,%B0,r0) CR_TAB
3203 AS1 (clr,%A0) CR_TAB
3204 AS1 (clr,__zero_reg__));
3206 if (optimize_size && scratch)
3211 return (AS2 (mov,%B0,%A0) CR_TAB
3212 AS1 (clr,%A0) CR_TAB
3213 AS1 (swap,%B0) CR_TAB
3214 AS1 (lsl,%B0) CR_TAB
3215 AS2 (ldi,%3,0xe0) CR_TAB
3221 return ("set" CR_TAB
3222 AS2 (bld,r1,5) CR_TAB
3223 AS2 (mul,%A0,r1) CR_TAB
3224 AS2 (mov,%B0,r0) CR_TAB
3225 AS1 (clr,%A0) CR_TAB
3226 AS1 (clr,__zero_reg__));
3229 return (AS2 (mov,%B0,%A0) CR_TAB
3230 AS1 (clr,%A0) CR_TAB
3231 AS1 (lsl,%B0) CR_TAB
3232 AS1 (lsl,%B0) CR_TAB
3233 AS1 (lsl,%B0) CR_TAB
3234 AS1 (lsl,%B0) CR_TAB
3238 if (AVR_ENHANCED && ldi_ok)
3241 return (AS2 (ldi,%B0,0x40) CR_TAB
3242 AS2 (mul,%A0,%B0) CR_TAB
3243 AS2 (mov,%B0,r0) CR_TAB
3244 AS1 (clr,%A0) CR_TAB
3245 AS1 (clr,__zero_reg__));
3247 if (AVR_ENHANCED && scratch)
3250 return (AS2 (ldi,%3,0x40) CR_TAB
3251 AS2 (mul,%A0,%3) CR_TAB
3252 AS2 (mov,%B0,r0) CR_TAB
3253 AS1 (clr,%A0) CR_TAB
3254 AS1 (clr,__zero_reg__));
3256 if (optimize_size && ldi_ok)
3259 return (AS2 (mov,%B0,%A0) CR_TAB
3260 AS2 (ldi,%A0,6) "\n1:\t"
3261 AS1 (lsl,%B0) CR_TAB
3262 AS1 (dec,%A0) CR_TAB
3265 if (optimize_size && scratch)
3268 return (AS1 (clr,%B0) CR_TAB
3269 AS1 (lsr,%A0) CR_TAB
3270 AS1 (ror,%B0) CR_TAB
3271 AS1 (lsr,%A0) CR_TAB
3272 AS1 (ror,%B0) CR_TAB
3277 return (AS1 (clr,%B0) CR_TAB
3278 AS1 (lsr,%A0) CR_TAB
3279 AS1 (ror,%B0) CR_TAB
3284 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3286 insn, operands, len, 2);
3291 /* 32bit shift left ((long)x << i) */
3294 ashlsi3_out (insn, operands, len)
3299 if (GET_CODE (operands[2]) == CONST_INT)
3307 switch (INTVAL (operands[2]))
3311 int reg0 = true_regnum (operands[0]);
3312 int reg1 = true_regnum (operands[1]);
3315 return (AS2 (mov,%D0,%C1) CR_TAB
3316 AS2 (mov,%C0,%B1) CR_TAB
3317 AS2 (mov,%B0,%A1) CR_TAB
3319 else if (reg0 + 1 == reg1)
3322 return AS1 (clr,%A0);
3325 return (AS1 (clr,%A0) CR_TAB
3326 AS2 (mov,%B0,%A1) CR_TAB
3327 AS2 (mov,%C0,%B1) CR_TAB
3333 int reg0 = true_regnum (operands[0]);
3334 int reg1 = true_regnum (operands[1]);
3336 if (AVR_ENHANCED && (reg0 + 2 != reg1))
3339 return (AS2 (movw,%C0,%A1) CR_TAB
3340 AS1 (clr,%B0) CR_TAB
3343 if (reg0 + 1 >= reg1)
3344 return (AS2 (mov,%D0,%B1) CR_TAB
3345 AS2 (mov,%C0,%A1) CR_TAB
3346 AS1 (clr,%B0) CR_TAB
3348 if (reg0 + 2 == reg1)
3351 return (AS1 (clr,%B0) CR_TAB
3355 return (AS2 (mov,%C0,%A1) CR_TAB
3356 AS2 (mov,%D0,%B1) CR_TAB
3357 AS1 (clr,%B0) CR_TAB
3363 if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
3364 return (AS2 (mov,%D0,%A1) CR_TAB
3365 AS1 (clr,%C0) CR_TAB
3366 AS1 (clr,%B0) CR_TAB
3371 return (AS1 (clr,%C0) CR_TAB
3372 AS1 (clr,%B0) CR_TAB
3378 return (AS1 (clr,%D0) CR_TAB
3379 AS1 (lsr,%A0) CR_TAB
3380 AS1 (ror,%D0) CR_TAB
3381 AS1 (clr,%C0) CR_TAB
3382 AS1 (clr,%B0) CR_TAB
3387 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3388 AS1 (rol,%B0) CR_TAB
3389 AS1 (rol,%C0) CR_TAB
3391 insn, operands, len, 4);
3395 /* 8bit arithmetic shift right ((signed char)x >> i) */
3398 ashrqi3_out (insn, operands, len)
3401 int *len; /* insn length */
3403 if (GET_CODE (operands[2]) == CONST_INT)
3410 switch (INTVAL (operands[2]))
3414 return AS1 (asr,%0);
3418 return (AS1 (asr,%0) CR_TAB
3423 return (AS1 (asr,%0) CR_TAB
3429 return (AS1 (asr,%0) CR_TAB
3436 return (AS1 (asr,%0) CR_TAB
3444 return (AS2 (bst,%0,6) CR_TAB
3446 AS2 (sbc,%0,%0) CR_TAB
3452 return (AS1 (lsl,%0) CR_TAB
3456 else if (CONSTANT_P (operands[2]))
3457 fatal_insn ("Internal compiler bug.\nIncorrect shift:", insn);
3459 out_shift_with_cnt (AS1 (asr,%0),
3460 insn, operands, len, 1);
3465 /* 16bit arithmetic shift right ((signed short)x >> i) */
3468 ashrhi3_out (insn, operands, len)
3473 if (GET_CODE (operands[2]) == CONST_INT)
3475 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3476 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3483 switch (INTVAL (operands[2]))
3487 /* XXX try to optimize this too? */
3492 break; /* scratch ? 5 : 6 */
3494 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3495 AS2 (mov,%A0,%B0) CR_TAB
3496 AS1 (lsl,__tmp_reg__) CR_TAB
3497 AS1 (rol,%A0) CR_TAB
3498 AS2 (sbc,%B0,%B0) CR_TAB
3499 AS1 (lsl,__tmp_reg__) CR_TAB
3500 AS1 (rol,%A0) CR_TAB
3505 return (AS1 (lsl,%A0) CR_TAB
3506 AS2 (mov,%A0,%B0) CR_TAB
3507 AS1 (rol,%A0) CR_TAB
3512 int reg0 = true_regnum (operands[0]);
3513 int reg1 = true_regnum (operands[1]);
3516 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3517 AS1 (lsl,%B0) CR_TAB
3519 else if (reg0 == reg1 + 1)
3520 return *len = 3, (AS1 (clr,%B0) CR_TAB
3521 AS2 (sbrc,%A0,7) CR_TAB
3524 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3525 AS1 (clr,%B0) CR_TAB
3526 AS2 (sbrc,%A0,7) CR_TAB
3532 return (AS2 (mov,%A0,%B0) CR_TAB
3533 AS1 (lsl,%B0) CR_TAB
3534 AS2 (sbc,%B0,%B0) CR_TAB
3539 return (AS2 (mov,%A0,%B0) CR_TAB
3540 AS1 (lsl,%B0) CR_TAB
3541 AS2 (sbc,%B0,%B0) CR_TAB
3542 AS1 (asr,%A0) CR_TAB
3546 if (AVR_ENHANCED && ldi_ok)
3549 return (AS2 (ldi,%A0,0x20) CR_TAB
3550 AS2 (muls,%B0,%A0) CR_TAB
3551 AS2 (mov,%A0,r1) CR_TAB
3552 AS2 (sbc,%B0,%B0) CR_TAB
3553 AS1 (clr,__zero_reg__));
3555 if (optimize_size && scratch)
3558 return (AS2 (mov,%A0,%B0) CR_TAB
3559 AS1 (lsl,%B0) CR_TAB
3560 AS2 (sbc,%B0,%B0) CR_TAB
3561 AS1 (asr,%A0) CR_TAB
3562 AS1 (asr,%A0) CR_TAB
3566 if (AVR_ENHANCED && ldi_ok)
3569 return (AS2 (ldi,%A0,0x10) CR_TAB
3570 AS2 (muls,%B0,%A0) CR_TAB
3571 AS2 (mov,%A0,r1) CR_TAB
3572 AS2 (sbc,%B0,%B0) CR_TAB
3573 AS1 (clr,__zero_reg__));
3575 if (optimize_size && scratch)
3578 return (AS2 (mov,%A0,%B0) CR_TAB
3579 AS1 (lsl,%B0) CR_TAB
3580 AS2 (sbc,%B0,%B0) CR_TAB
3581 AS1 (asr,%A0) CR_TAB
3582 AS1 (asr,%A0) CR_TAB
3583 AS1 (asr,%A0) CR_TAB
3587 if (AVR_ENHANCED && ldi_ok)
3590 return (AS2 (ldi,%A0,0x08) CR_TAB
3591 AS2 (muls,%B0,%A0) CR_TAB
3592 AS2 (mov,%A0,r1) CR_TAB
3593 AS2 (sbc,%B0,%B0) CR_TAB
3594 AS1 (clr,__zero_reg__));
3597 break; /* scratch ? 5 : 7 */
3599 return (AS2 (mov,%A0,%B0) CR_TAB
3600 AS1 (lsl,%B0) CR_TAB
3601 AS2 (sbc,%B0,%B0) CR_TAB
3602 AS1 (asr,%A0) CR_TAB
3603 AS1 (asr,%A0) CR_TAB
3604 AS1 (asr,%A0) CR_TAB
3605 AS1 (asr,%A0) CR_TAB
3610 return (AS1 (lsl,%B0) CR_TAB
3611 AS2 (sbc,%A0,%A0) CR_TAB
3612 AS1 (lsl,%B0) CR_TAB
3613 AS2 (mov,%B0,%A0) CR_TAB
3617 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3618 AS2 (sbc,%A0,%A0) CR_TAB
3623 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3625 insn, operands, len, 2);
3630 /* 32bit arithmetic shift right ((signed long)x >> i) */
3633 ashrsi3_out (insn, operands, len)
3638 if (GET_CODE (operands[2]) == CONST_INT)
3646 switch (INTVAL (operands[2]))
3650 int reg0 = true_regnum (operands[0]);
3651 int reg1 = true_regnum (operands[1]);
3654 return (AS2 (mov,%A0,%B1) CR_TAB
3655 AS2 (mov,%B0,%C1) CR_TAB
3656 AS2 (mov,%C0,%D1) CR_TAB
3657 AS1 (clr,%D0) CR_TAB
3658 AS2 (sbrc,%C0,7) CR_TAB
3660 else if (reg0 == reg1 + 1)
3663 return (AS1 (clr,%D0) CR_TAB
3664 AS2 (sbrc,%C0,7) CR_TAB
3668 return (AS1 (clr,%D0) CR_TAB
3669 AS2 (sbrc,%D1,7) CR_TAB
3670 AS1 (dec,%D0) CR_TAB
3671 AS2 (mov,%C0,%D1) CR_TAB
3672 AS2 (mov,%B0,%C1) CR_TAB
3678 int reg0 = true_regnum (operands[0]);
3679 int reg1 = true_regnum (operands[1]);
3681 if (AVR_ENHANCED && (reg0 != reg1 + 2))
3684 return (AS2 (movw,%A0,%C1) CR_TAB
3685 AS1 (clr,%D0) CR_TAB
3686 AS2 (sbrc,%B0,7) CR_TAB
3687 AS1 (com,%D0) CR_TAB
3690 if (reg0 <= reg1 + 1)
3691 return (AS2 (mov,%A0,%C1) CR_TAB
3692 AS2 (mov,%B0,%D1) CR_TAB
3693 AS1 (clr,%D0) CR_TAB
3694 AS2 (sbrc,%B0,7) CR_TAB
3695 AS1 (com,%D0) CR_TAB
3697 else if (reg0 == reg1 + 2)
3698 return *len = 4, (AS1 (clr,%D0) CR_TAB
3699 AS2 (sbrc,%B0,7) CR_TAB
3700 AS1 (com,%D0) CR_TAB
3703 return (AS2 (mov,%B0,%D1) CR_TAB
3704 AS2 (mov,%A0,%C1) CR_TAB
3705 AS1 (clr,%D0) CR_TAB
3706 AS2 (sbrc,%B0,7) CR_TAB
3707 AS1 (com,%D0) CR_TAB
3712 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
3713 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3714 AS1 (clr,%D0) CR_TAB
3715 AS2 (sbrc,%A0,7) CR_TAB
3716 AS1 (com,%D0) CR_TAB
3717 AS2 (mov,%B0,%D0) CR_TAB
3720 return *len = 5, (AS1 (clr,%D0) CR_TAB
3721 AS2 (sbrc,%A0,7) CR_TAB
3722 AS1 (com,%D0) CR_TAB
3723 AS2 (mov,%B0,%D0) CR_TAB
3728 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3729 AS2 (sbc,%A0,%A0) CR_TAB
3730 AS2 (mov,%B0,%A0) CR_TAB
3731 AS2 (movw,%C0,%A0));
3733 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3734 AS2 (sbc,%A0,%A0) CR_TAB
3735 AS2 (mov,%B0,%A0) CR_TAB
3736 AS2 (mov,%C0,%A0) CR_TAB
3741 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3742 AS1 (ror,%C0) CR_TAB
3743 AS1 (ror,%B0) CR_TAB
3745 insn, operands, len, 4);
3749 /* 8bit logic shift right ((unsigned char)x >> i) */
3752 lshrqi3_out (insn, operands, len)
3757 if (GET_CODE (operands[2]) == CONST_INT)
3764 switch (INTVAL (operands[2]))
3768 return AS1 (clr,%0);
3772 return AS1 (lsr,%0);
3776 return (AS1 (lsr,%0) CR_TAB
3780 return (AS1 (lsr,%0) CR_TAB
3785 if (test_hard_reg_class (LD_REGS, operands[0]))
3788 return (AS1 (swap,%0) CR_TAB
3789 AS2 (andi,%0,0x0f));
3792 return (AS1 (lsr,%0) CR_TAB
3798 if (test_hard_reg_class (LD_REGS, operands[0]))
3801 return (AS1 (swap,%0) CR_TAB
3806 return (AS1 (lsr,%0) CR_TAB
3813 if (test_hard_reg_class (LD_REGS, operands[0]))
3816 return (AS1 (swap,%0) CR_TAB
3822 return (AS1 (lsr,%0) CR_TAB
3831 return (AS1 (rol,%0) CR_TAB
3836 else if (CONSTANT_P (operands[2]))
3837 fatal_insn ("Internal compiler bug.\nIncorrect shift:", insn);
3839 out_shift_with_cnt (AS1 (lsr,%0),
3840 insn, operands, len, 1);
3844 /* 16bit logic shift right ((unsigned short)x >> i) */
3847 lshrhi3_out (insn, operands, len)
3852 if (GET_CODE (operands[2]) == CONST_INT)
3854 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3855 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3862 switch (INTVAL (operands[2]))
3865 if (optimize_size && scratch)
3870 return (AS1 (swap,%B0) CR_TAB
3871 AS1 (swap,%A0) CR_TAB
3872 AS2 (andi,%A0,0x0f) CR_TAB
3873 AS2 (eor,%A0,%B0) CR_TAB
3874 AS2 (andi,%B0,0x0f) CR_TAB
3880 return (AS1 (swap,%B0) CR_TAB
3881 AS1 (swap,%A0) CR_TAB
3882 AS2 (ldi,%3,0x0f) CR_TAB
3883 AS2 (and,%A0,%3) CR_TAB
3884 AS2 (eor,%A0,%B0) CR_TAB
3885 AS2 (and,%B0,%3) CR_TAB
3888 break; /* optimize_size ? 6 : 8 */
3892 break; /* scratch ? 5 : 6 */
3896 return (AS1 (lsr,%B0) CR_TAB
3897 AS1 (ror,%A0) CR_TAB
3898 AS1 (swap,%B0) CR_TAB
3899 AS1 (swap,%A0) CR_TAB
3900 AS2 (andi,%A0,0x0f) CR_TAB
3901 AS2 (eor,%A0,%B0) CR_TAB
3902 AS2 (andi,%B0,0x0f) CR_TAB
3908 return (AS1 (lsr,%B0) CR_TAB
3909 AS1 (ror,%A0) CR_TAB
3910 AS1 (swap,%B0) CR_TAB
3911 AS1 (swap,%A0) CR_TAB
3912 AS2 (ldi,%3,0x0f) CR_TAB
3913 AS2 (and,%A0,%3) CR_TAB
3914 AS2 (eor,%A0,%B0) CR_TAB
3915 AS2 (and,%B0,%3) CR_TAB
3922 break; /* scratch ? 5 : 6 */
3924 return (AS1 (clr,__tmp_reg__) CR_TAB
3925 AS1 (lsl,%A0) CR_TAB
3926 AS1 (rol,%B0) CR_TAB
3927 AS1 (rol,__tmp_reg__) CR_TAB
3928 AS1 (lsl,%A0) CR_TAB
3929 AS1 (rol,%B0) CR_TAB
3930 AS1 (rol,__tmp_reg__) CR_TAB
3931 AS2 (mov,%A0,%B0) CR_TAB
3932 AS2 (mov,%B0,__tmp_reg__));
3936 return (AS1 (lsl,%A0) CR_TAB
3937 AS2 (mov,%A0,%B0) CR_TAB
3938 AS1 (rol,%A0) CR_TAB
3939 AS2 (sbc,%B0,%B0) CR_TAB
3943 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
3944 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
3947 return *len = 1, AS1 (clr,%B0);
3951 return (AS2 (mov,%A0,%B0) CR_TAB
3952 AS1 (clr,%B0) CR_TAB
3957 return (AS2 (mov,%A0,%B0) CR_TAB
3958 AS1 (clr,%B0) CR_TAB
3959 AS1 (lsr,%A0) CR_TAB
3964 return (AS2 (mov,%A0,%B0) CR_TAB
3965 AS1 (clr,%B0) CR_TAB
3966 AS1 (lsr,%A0) CR_TAB
3967 AS1 (lsr,%A0) CR_TAB
3974 return (AS2 (mov,%A0,%B0) CR_TAB
3975 AS1 (clr,%B0) CR_TAB
3976 AS1 (swap,%A0) CR_TAB
3977 AS2 (andi,%A0,0x0f));
3982 return (AS2 (mov,%A0,%B0) CR_TAB
3983 AS1 (clr,%B0) CR_TAB
3984 AS1 (swap,%A0) CR_TAB
3985 AS2 (ldi,%3,0x0f) CR_TAB
3989 return (AS2 (mov,%A0,%B0) CR_TAB
3990 AS1 (clr,%B0) CR_TAB
3991 AS1 (lsr,%A0) CR_TAB
3992 AS1 (lsr,%A0) CR_TAB
3993 AS1 (lsr,%A0) CR_TAB
4000 return (AS2 (mov,%A0,%B0) CR_TAB
4001 AS1 (clr,%B0) CR_TAB
4002 AS1 (swap,%A0) CR_TAB
4003 AS1 (lsr,%A0) CR_TAB
4004 AS2 (andi,%A0,0x07));
4006 if (AVR_ENHANCED && scratch)
4009 return (AS2 (ldi,%3,0x08) CR_TAB
4010 AS2 (mul,%B0,%3) CR_TAB
4011 AS2 (mov,%A0,r1) CR_TAB
4012 AS1 (clr,%B0) CR_TAB
4013 AS1 (clr,__zero_reg__));
4015 if (optimize_size && scratch)
4020 return (AS2 (mov,%A0,%B0) CR_TAB
4021 AS1 (clr,%B0) CR_TAB
4022 AS1 (swap,%A0) CR_TAB
4023 AS1 (lsr,%A0) CR_TAB
4024 AS2 (ldi,%3,0x07) CR_TAB
4030 return ("set" CR_TAB
4031 AS2 (bld,r1,3) CR_TAB
4032 AS2 (mul,%B0,r1) CR_TAB
4033 AS2 (mov,%A0,r1) CR_TAB
4034 AS1 (clr,%B0) CR_TAB
4035 AS1 (clr,__zero_reg__));
4038 return (AS2 (mov,%A0,%B0) CR_TAB
4039 AS1 (clr,%B0) CR_TAB
4040 AS1 (lsr,%A0) CR_TAB
4041 AS1 (lsr,%A0) CR_TAB
4042 AS1 (lsr,%A0) CR_TAB
4043 AS1 (lsr,%A0) CR_TAB
4047 if (AVR_ENHANCED && ldi_ok)
4050 return (AS2 (ldi,%A0,0x04) CR_TAB
4051 AS2 (mul,%B0,%A0) CR_TAB
4052 AS2 (mov,%A0,r1) CR_TAB
4053 AS1 (clr,%B0) CR_TAB
4054 AS1 (clr,__zero_reg__));
4056 if (AVR_ENHANCED && scratch)
4059 return (AS2 (ldi,%3,0x04) CR_TAB
4060 AS2 (mul,%B0,%3) CR_TAB
4061 AS2 (mov,%A0,r1) CR_TAB
4062 AS1 (clr,%B0) CR_TAB
4063 AS1 (clr,__zero_reg__));
4065 if (optimize_size && ldi_ok)
4068 return (AS2 (mov,%A0,%B0) CR_TAB
4069 AS2 (ldi,%B0,6) "\n1:\t"
4070 AS1 (lsr,%A0) CR_TAB
4071 AS1 (dec,%B0) CR_TAB
4074 if (optimize_size && scratch)
4077 return (AS1 (clr,%A0) CR_TAB
4078 AS1 (lsl,%B0) CR_TAB
4079 AS1 (rol,%A0) CR_TAB
4080 AS1 (lsl,%B0) CR_TAB
4081 AS1 (rol,%A0) CR_TAB
4086 return (AS1 (clr,%A0) CR_TAB
4087 AS1 (lsl,%B0) CR_TAB
4088 AS1 (rol,%A0) CR_TAB
4093 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4095 insn, operands, len, 2);
4099 /* 32bit logic shift right ((unsigned int)x >> i) */
4102 lshrsi3_out (insn, operands, len)
4107 if (GET_CODE (operands[2]) == CONST_INT)
4115 switch (INTVAL (operands[2]))
4119 int reg0 = true_regnum (operands[0]);
4120 int reg1 = true_regnum (operands[1]);
4123 return (AS2 (mov,%A0,%B1) CR_TAB
4124 AS2 (mov,%B0,%C1) CR_TAB
4125 AS2 (mov,%C0,%D1) CR_TAB
4127 else if (reg0 == reg1 + 1)
4128 return *len = 1, AS1 (clr,%D0);
4130 return (AS1 (clr,%D0) CR_TAB
4131 AS2 (mov,%C0,%D1) CR_TAB
4132 AS2 (mov,%B0,%C1) CR_TAB
4138 int reg0 = true_regnum (operands[0]);
4139 int reg1 = true_regnum (operands[1]);
4141 if (AVR_ENHANCED && (reg0 != reg1 + 2))
4144 return (AS2 (movw,%A0,%C1) CR_TAB
4145 AS1 (clr,%C0) CR_TAB
4148 if (reg0 <= reg1 + 1)
4149 return (AS2 (mov,%A0,%C1) CR_TAB
4150 AS2 (mov,%B0,%D1) CR_TAB
4151 AS1 (clr,%C0) CR_TAB
4153 else if (reg0 == reg1 + 2)
4154 return *len = 2, (AS1 (clr,%C0) CR_TAB
4157 return (AS2 (mov,%B0,%D1) CR_TAB
4158 AS2 (mov,%A0,%C1) CR_TAB
4159 AS1 (clr,%C0) CR_TAB
4164 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
4165 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4166 AS1 (clr,%B0) CR_TAB
4167 AS1 (clr,%C0) CR_TAB
4170 return *len = 3, (AS1 (clr,%B0) CR_TAB
4171 AS1 (clr,%C0) CR_TAB
4176 return (AS1 (clr,%A0) CR_TAB
4177 AS2 (sbrc,%D0,7) CR_TAB
4178 AS1 (inc,%A0) CR_TAB
4179 AS1 (clr,%B0) CR_TAB
4180 AS1 (clr,%C0) CR_TAB
4185 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4186 AS1 (ror,%C0) CR_TAB
4187 AS1 (ror,%B0) CR_TAB
4189 insn, operands, len, 4);
4193 /* Modifies the length assigned to instruction INSN
4194 LEN is the initially computed length of the insn. */
4197 adjust_insn_length (insn, len)
4201 rtx patt = PATTERN (insn);
4204 if (GET_CODE (patt) == SET)
4207 op[1] = SET_SRC (patt);
4208 op[0] = SET_DEST (patt);
4209 if (general_operand (op[1], VOIDmode)
4210 && general_operand (op[0], VOIDmode))
4212 switch (GET_MODE (op[0]))
4215 output_movqi (insn, op, &len);
4218 output_movhi (insn, op, &len);
4222 output_movsisf (insn, op, &len);
4228 else if (op[0] == cc0_rtx && REG_P (op[1]))
4230 switch (GET_MODE (op[1]))
4232 case HImode: out_tsthi (insn,&len); break;
4233 case SImode: out_tstsi (insn,&len); break;
4237 else if (GET_CODE (op[1]) == AND)
4239 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4241 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4242 if (GET_MODE (op[1]) == SImode)
4243 len = (((mask & 0xff) != 0xff)
4244 + ((mask & 0xff00) != 0xff00)
4245 + ((mask & 0xff0000UL) != 0xff0000UL)
4246 + ((mask & 0xff000000UL) != 0xff000000UL));
4247 else if (GET_MODE (op[1]) == HImode)
4248 len = (((mask & 0xff) != 0xff)
4249 + ((mask & 0xff00) != 0xff00));
4252 else if (GET_CODE (op[1]) == IOR)
4254 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4256 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4257 if (GET_MODE (op[1]) == SImode)
4258 len = (((mask & 0xff) != 0)
4259 + ((mask & 0xff00) != 0)
4260 + ((mask & 0xff0000UL) != 0)
4261 + ((mask & 0xff000000UL) != 0));
4262 else if (GET_MODE (op[1]) == HImode)
4263 len = (((mask & 0xff) != 0)
4264 + ((mask & 0xff00) != 0));
4268 set = single_set (insn);
4273 op[1] = SET_SRC (set);
4274 op[0] = SET_DEST (set);
4276 if (GET_CODE (patt) == PARALLEL
4277 && general_operand (op[1], VOIDmode)
4278 && general_operand (op[0], VOIDmode))
4280 if (XVECLEN (patt, 0) == 2)
4281 op[2] = XVECEXP (patt, 0, 1);
4283 switch (GET_MODE (op[0]))
4289 output_reload_inhi (insn, op, &len);
4293 output_reload_insisf (insn, op, &len);
4299 else if (GET_CODE (op[1]) == ASHIFT
4300 || GET_CODE (op[1]) == ASHIFTRT
4301 || GET_CODE (op[1]) == LSHIFTRT)
4305 ops[1] = XEXP (op[1],0);
4306 ops[2] = XEXP (op[1],1);
4307 switch (GET_CODE (op[1]))
4310 switch (GET_MODE (op[0]))
4312 case QImode: ashlqi3_out (insn,ops,&len); break;
4313 case HImode: ashlhi3_out (insn,ops,&len); break;
4314 case SImode: ashlsi3_out (insn,ops,&len); break;
4319 switch (GET_MODE (op[0]))
4321 case QImode: ashrqi3_out (insn,ops,&len); break;
4322 case HImode: ashrhi3_out (insn,ops,&len); break;
4323 case SImode: ashrsi3_out (insn,ops,&len); break;
4328 switch (GET_MODE (op[0]))
4330 case QImode: lshrqi3_out (insn,ops,&len); break;
4331 case HImode: lshrhi3_out (insn,ops,&len); break;
4332 case SImode: lshrsi3_out (insn,ops,&len); break;
4344 /* Return non-zero if register REG dead after INSN */
4347 reg_unused_after (insn, reg)
4351 return (dead_or_set_p (insn, reg)
4352 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4355 /* Return non-zero if REG is not used after INSN.
4356 We assume REG is a reload reg, and therefore does
4357 not live past labels. It may live past calls or jumps though. */
4360 _reg_unused_after (insn, reg)
4367 /* If the reg is set by this instruction, then it is safe for our
4368 case. Disregard the case where this is a store to memory, since
4369 we are checking a register used in the store address. */
4370 set = single_set (insn);
4371 if (set && GET_CODE (SET_DEST (set)) != MEM
4372 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4375 while ((insn = NEXT_INSN (insn)))
4377 code = GET_CODE (insn);
4380 /* If this is a label that existed before reload, then the register
4381 if dead here. However, if this is a label added by reorg, then
4382 the register may still be live here. We can't tell the difference,
4383 so we just ignore labels completely. */
4384 if (code == CODE_LABEL)
4389 if (code == JUMP_INSN)
4392 /* If this is a sequence, we must handle them all at once.
4393 We could have for instance a call that sets the target register,
4394 and a insn in a delay slot that uses the register. In this case,
4395 we must return 0. */
4396 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4401 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4403 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4404 rtx set = single_set (this_insn);
4406 if (GET_CODE (this_insn) == CALL_INSN)
4408 else if (GET_CODE (this_insn) == JUMP_INSN)
4410 if (INSN_ANNULLED_BRANCH_P (this_insn))
4415 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4417 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4419 if (GET_CODE (SET_DEST (set)) != MEM)
4425 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4430 else if (code == JUMP_INSN)
4434 if (code == CALL_INSN)
4437 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4438 if (GET_CODE (XEXP (tem, 0)) == USE
4439 && REG_P (XEXP (XEXP (tem, 0), 0))
4440 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4442 if (call_used_regs[REGNO (reg)])
4446 if (GET_RTX_CLASS (code) == 'i')
4448 rtx set = single_set (insn);
4450 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4452 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4453 return GET_CODE (SET_DEST (set)) != MEM;
4454 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4461 /* Output rtx VALUE as .byte to file FILE */
4464 asm_output_char (file, value)
4468 fprintf (file, "\t.byte ");
4469 output_addr_const (file, value);
4470 fprintf (file, "\n");
4474 /* Output VALUE as .byte to file FILE */
4477 asm_output_byte (file, value)
4481 fprintf (file, "\t.byte 0x%x\n", value & 0xff);
4485 /* Output rtx VALUE as .word to file FILE */
4488 asm_output_short (file, value)
4492 if (SYMBOL_REF_FLAG (value) || GET_CODE (value) == LABEL_REF)
4494 fprintf (file, "\t.word pm(");
4495 output_addr_const (file, (value));
4496 fprintf (file, ")\n");
4500 fprintf (file, "\t.word ");
4501 output_addr_const (file, (value));
4502 fprintf (file, "\n");
4507 /* Output real N to file FILE */
4510 asm_output_float (file, n)
4517 REAL_VALUE_TO_TARGET_SINGLE (n, val);
4518 REAL_VALUE_TO_DECIMAL (n, "%g", dstr);
4519 fprintf (file, "\t.long 0x%08lx\t/* %s */\n", val, dstr);
4522 /* Sets section name for declaration DECL */
4525 unique_section (decl, reloc)
4527 int reloc ATTRIBUTE_UNUSED;
4530 const char *name, *prefix;
4532 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
4533 /* Strip off any encoding in name. */
4534 STRIP_NAME_ENCODING (name, name);
4536 if (TREE_CODE (decl) == FUNCTION_DECL)
4538 if (flag_function_sections)
4546 if (flag_function_sections)
4548 len = strlen (name) + strlen (prefix);
4549 string = alloca (len + 1);
4550 sprintf (string, "%s%s", prefix, name);
4551 DECL_SECTION_NAME (decl) = build_string (len, string);
4556 /* The routine used to output NUL terminated strings. We use a special
4557 version of this for most svr4 targets because doing so makes the
4558 generated assembly code more compact (and thus faster to assemble)
4559 as well as more readable, especially for targets like the i386
4560 (where the only alternative is to output character sequences as
4561 comma separated lists of numbers). */
4564 gas_output_limited_string(file, str)
4568 const unsigned char *_limited_str = (unsigned char *) str;
4570 fprintf (file, "%s\"", STRING_ASM_OP);
4571 for (; (ch = *_limited_str); _limited_str++)
4574 switch (escape = ESCAPES[ch])
4580 fprintf (file, "\\%03o", ch);
4584 putc (escape, file);
4588 fprintf (file, "\"\n");
4591 /* The routine used to output sequences of byte values. We use a special
4592 version of this for most svr4 targets because doing so makes the
4593 generated assembly code more compact (and thus faster to assemble)
4594 as well as more readable. Note that if we find subparts of the
4595 character sequence which end with NUL (and which are shorter than
4596 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4599 gas_output_ascii(file, str, length)
4604 const unsigned char *_ascii_bytes = (const unsigned char *) str;
4605 const unsigned char *limit = _ascii_bytes + length;
4606 unsigned bytes_in_chunk = 0;
4607 for (; _ascii_bytes < limit; _ascii_bytes++)
4609 const unsigned char *p;
4610 if (bytes_in_chunk >= 60)
4612 fprintf (file, "\"\n");
4615 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4617 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4619 if (bytes_in_chunk > 0)
4621 fprintf (file, "\"\n");
4624 gas_output_limited_string (file, (char*)_ascii_bytes);
4631 if (bytes_in_chunk == 0)
4632 fprintf (file, "\t.ascii\t\"");
4633 switch (escape = ESCAPES[ch = *_ascii_bytes])
4640 fprintf (file, "\\%03o", ch);
4641 bytes_in_chunk += 4;
4645 putc (escape, file);
4646 bytes_in_chunk += 2;
4651 if (bytes_in_chunk > 0)
4652 fprintf (file, "\"\n");
4655 /* Return value is nonzero if pseudos that have been
4656 assigned to registers of class CLASS would likely be spilled
4657 because registers of CLASS are needed for spill registers. */
4660 class_likely_spilled_p (c)
4663 return (c != ALL_REGS && c != ADDW_REGS);
4666 /* Valid attributes:
4667 progmem - put data to program memory;
4668 signal - make a function to be hardware interrupt. After function
4669 prologue interrupts are disabled;
4670 interrupt - make a function to be hardware interrupt. After function
4671 prologue interrupts are enabled;
4672 naked - don't generate function prologue/epilogue and `ret' command.
4674 Only `progmem' attribute valid for type. */
4676 const struct attribute_spec avr_attribute_table[] =
4678 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4679 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
4680 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4681 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4682 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4683 { NULL, 0, 0, false, false, false, NULL }
4686 /* Handle a "progmem" attribute; arguments as in
4687 struct attribute_spec.handler. */
4689 avr_handle_progmem_attribute (node, name, args, flags, no_add_attrs)
4692 tree args ATTRIBUTE_UNUSED;
4693 int flags ATTRIBUTE_UNUSED;
4698 if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
4700 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
4702 warning ("Only initialized variables can be placed into "
4703 "program memory area.");
4704 *no_add_attrs = true;
4709 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
4710 *no_add_attrs = true;
4717 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4718 struct attribute_spec.handler. */
4720 avr_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
4723 tree args ATTRIBUTE_UNUSED;
4724 int flags ATTRIBUTE_UNUSED;
4727 if (TREE_CODE (*node) != FUNCTION_DECL)
4729 warning ("`%s' attribute only applies to functions",
4730 IDENTIFIER_POINTER (name));
4731 *no_add_attrs = true;
4737 /* Look for attribute `progmem' in DECL
4738 if found return 1, otherwise 0. */
4741 avr_progmem_p (decl)
4746 if (TREE_CODE (decl) != VAR_DECL)
4750 != lookup_attribute ("progmem", DECL_ATTRIBUTES (decl)))
4756 while (TREE_CODE (a) == ARRAY_TYPE);
4758 if (a == error_mark_node)
4761 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4767 /* Encode section information about tree DECL */
4770 encode_section_info (decl)
4773 if (TREE_CODE (decl) == FUNCTION_DECL)
4774 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
4775 else if ((TREE_STATIC (decl) || DECL_EXTERNAL (decl))
4776 && TREE_CODE (decl) == VAR_DECL
4777 && avr_progmem_p (decl))
4779 static const char *const dsec = ".progmem.data";
4780 DECL_SECTION_NAME (decl) = build_string (strlen (dsec), dsec);
4781 TREE_READONLY (decl) = 1;
4785 /* Outputs to the stdio stream FILE some
4786 appropriate text to go at the start of an assembler file. */
4789 asm_file_start (file)
4792 output_file_directive (file, main_input_filename);
4793 fprintf (file, "\t.arch %s\n", avr_mcu_name);
4794 fputs ("__SREG__ = 0x3f\n"
4796 "__SP_L__ = 0x3d\n", file);
4798 fputs ("__tmp_reg__ = 0\n"
4799 "__zero_reg__ = 1\n"
4800 "_PC_ = 2\n", file);
4802 commands_in_file = 0;
4803 commands_in_prologues = 0;
4804 commands_in_epilogues = 0;
4807 /* Outputs to the stdio stream FILE some
4808 appropriate text to go at the end of an assembler file. */
4815 "/* File %s: code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4816 main_input_filename,
4819 commands_in_file - commands_in_prologues - commands_in_epilogues,
4820 commands_in_prologues, commands_in_epilogues);
4823 /* Choose the order in which to allocate hard registers for
4824 pseudo-registers local to a basic block.
4826 Store the desired register order in the array `reg_alloc_order'.
4827 Element 0 should be the register to allocate first; element 1, the
4828 next register; and so on. */
4831 order_regs_for_local_alloc ()
4834 static const int order_0[] = {
4842 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4846 static const int order_1[] = {
4854 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4858 static const int order_2[] = {
4867 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4872 const int *order = (TARGET_ORDER_1 ? order_1 :
4873 TARGET_ORDER_2 ? order_2 :
4875 for (i=0; i < ARRAY_SIZE (order_0); ++i)
4876 reg_alloc_order[i] = order[i];
4879 /* Calculate the cost of X code of the expression in which it is contained,
4880 found in OUTER_CODE */
4883 default_rtx_costs (X, code, outer_code)
4886 enum rtx_code outer_code;
4893 cost = 2 * GET_MODE_SIZE (GET_MODE (X));
4896 if (outer_code != SET)
4898 if (GET_CODE (XEXP (X,0)) == SYMBOL_REF)
4899 cost += 2 * GET_MODE_SIZE (GET_MODE (X));
4901 cost += GET_MODE_SIZE (GET_MODE (X));
4907 if (outer_code == SET)
4908 cost = GET_MODE_SIZE (GET_MODE (X));
4910 cost = -GET_MODE_SIZE (GET_MODE (X));
4913 if (outer_code == SET)
4914 cost = GET_MODE_SIZE (GET_MODE (X));
4920 if (outer_code == SET)
4922 if (X == stack_pointer_rtx)
4924 else if (GET_CODE (XEXP (X,1)) == CONST_INT)
4925 cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 :
4926 GET_MODE_SIZE (GET_MODE (X)));
4928 cost = GET_MODE_SIZE (GET_MODE (X));
4932 if (GET_CODE (XEXP (X,1)) == CONST_INT)
4933 cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0)));
4941 /* Calculate the cost of a memory address */
4944 avr_address_cost (x)
4947 if (GET_CODE (x) == PLUS
4948 && GET_CODE (XEXP (x,1)) == CONST_INT
4949 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
4950 && INTVAL (XEXP (x,1)) >= 61)
4952 if (CONSTANT_ADDRESS_P (x))
4954 if (io_address_p (x, 1))
4961 /* EXTRA_CONSTRAINT helper */
4964 extra_constraint (x, c)
4969 && GET_CODE (x) == MEM
4970 && GET_CODE (XEXP (x,0)) == PLUS)
4972 if (TARGET_ALL_DEBUG)
4974 fprintf (stderr, ("extra_constraint:\n"
4975 "reload_completed: %d\n"
4976 "reload_in_progress: %d\n"),
4977 reload_completed, reload_in_progress);
4980 if (GET_CODE (x) == MEM
4981 && GET_CODE (XEXP (x,0)) == PLUS
4982 && REG_P (XEXP (XEXP (x,0), 0))
4983 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
4984 && (INTVAL (XEXP (XEXP (x,0), 1))
4985 <= MAX_LD_OFFSET (GET_MODE (x))))
4987 rtx xx = XEXP (XEXP (x,0), 0);
4988 int regno = REGNO (xx);
4989 if (TARGET_ALL_DEBUG)
4991 fprintf (stderr, ("extra_constraint:\n"
4992 "reload_completed: %d\n"
4993 "reload_in_progress: %d\n"),
4994 reload_completed, reload_in_progress);
4997 if (regno >= FIRST_PSEUDO_REGISTER)
4998 return 1; /* allocate pseudos */
4999 else if (regno == REG_Z || regno == REG_Y)
5000 return 1; /* strictly check */
5001 else if (xx == frame_pointer_rtx
5002 || xx == arg_pointer_rtx)
5003 return 1; /* XXX frame & arg pointer checks */
5009 /* Convert condition code CONDITION to the valid AVR condition code */
5012 avr_normalize_condition (condition)
5030 /* This fnction optimizes conditional jumps */
5033 machine_dependent_reorg (first_insn)
5038 for (insn = first_insn; insn; insn = NEXT_INSN (insn))
5040 if (! (GET_CODE (insn) == INSN
5041 || GET_CODE (insn) == CALL_INSN
5042 || GET_CODE (insn) == JUMP_INSN)
5043 || !single_set (insn))
5046 pattern = PATTERN (insn);
5048 if (GET_CODE (pattern) == PARALLEL)
5049 pattern = XVECEXP (pattern, 0, 0);
5050 if (GET_CODE (pattern) == SET
5051 && SET_DEST (pattern) == cc0_rtx
5052 && compare_diff_p (insn))
5054 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
5056 /* Now we work under compare insn */
5058 pattern = SET_SRC (pattern);
5059 if (true_regnum (XEXP (pattern,0)) >= 0
5060 && true_regnum (XEXP (pattern,1)) >= 0 )
5062 rtx x = XEXP (pattern,0);
5063 rtx next = next_real_insn (insn);
5064 rtx pat = PATTERN (next);
5065 rtx src = SET_SRC (pat);
5066 rtx t = XEXP (src,0);
5067 PUT_CODE (t, swap_condition (GET_CODE (t)));
5068 XEXP (pattern,0) = XEXP (pattern,1);
5069 XEXP (pattern,1) = x;
5070 INSN_CODE (next) = -1;
5072 else if (true_regnum (XEXP (pattern,0)) >= 0
5073 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
5075 rtx x = XEXP (pattern,1);
5076 rtx next = next_real_insn (insn);
5077 rtx pat = PATTERN (next);
5078 rtx src = SET_SRC (pat);
5079 rtx t = XEXP (src,0);
5081 if (avr_simplify_comparision_p (GET_MODE (XEXP (pattern,0)),
5084 XEXP (pattern,1) = GEN_INT (INTVAL (x)+1);
5085 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
5086 INSN_CODE (next) = -1;
5087 INSN_CODE (insn) = -1;
5091 else if (true_regnum (SET_SRC (pattern)) >= 0)
5093 /* This is a tst insn */
5094 rtx next = next_real_insn (insn);
5095 rtx pat = PATTERN (next);
5096 rtx src = SET_SRC (pat);
5097 rtx t = XEXP (src,0);
5099 PUT_CODE (t, swap_condition (GET_CODE (t)));
5100 SET_SRC (pattern) = gen_rtx (NEG,
5101 GET_MODE (SET_SRC (pattern)),
5103 INSN_CODE (next) = -1;
5104 INSN_CODE (insn) = -1;
5110 /* Returns register number for function return value.*/
5118 /* Ceate an RTX representing the place where a
5119 library function returns a value of mode MODE. */
5122 avr_libcall_value (mode)
5123 enum machine_mode mode;
5125 int offs = GET_MODE_SIZE (mode);
5128 return gen_rtx (REG, mode, RET_REGISTER + 2 - offs);
5131 /* Create an RTX representing the place where a
5132 function returns a value of data type VALTYPE. */
5135 avr_function_value (type, func)
5137 tree func ATTRIBUTE_UNUSED;
5141 if (TYPE_MODE (type) != BLKmode)
5142 return avr_libcall_value (TYPE_MODE (type));
5144 offs = int_size_in_bytes (type);
5147 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5148 offs = GET_MODE_SIZE (SImode);
5149 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5150 offs = GET_MODE_SIZE (DImode);
5152 return gen_rtx (REG, BLKmode, RET_REGISTER + 2 - offs);
5155 /* Returns non-zero if the number MASK has only one bit set. */
5158 mask_one_bit_p (mask)
5162 unsigned HOST_WIDE_INT n=mask;
5163 for (i = 0; i < 32; ++i)
5165 if (n & 0x80000000UL)
5167 if (n & 0x7fffffffUL)
5178 /* Places additional restrictions on the register class to
5179 use when it is necessary to copy value X into a register
5183 preferred_reload_class (x, class)
5184 rtx x ATTRIBUTE_UNUSED;
5185 enum reg_class class;
5191 test_hard_reg_class (class, x)
5192 enum reg_class class;
5195 int regno = true_regnum (x);
5198 return TEST_HARD_REG_CLASS (class, regno);
5202 debug_hard_reg_set (set)
5206 for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
5208 if (TEST_HARD_REG_BIT (set, i))
5210 fprintf (stderr, "r%-2d ", i);
5213 fprintf (stderr, "\n");
5217 jump_over_one_insn_p (insn, dest)
5221 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5224 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5225 int dest_addr = INSN_ADDRESSES (uid);
5226 return dest_addr - jump_addr == 2;
5229 /* Returns 1 if a value of mode MODE can be stored starting with hard
5230 register number REGNO. On the enhanced core, anything larger than
5231 1 byte must start in even numbered register for "movw" to work
5232 (this way we don't have to check for odd registers everywhere). */
5235 avr_hard_regno_mode_ok (regno, mode)
5237 enum machine_mode mode;
5241 /* if (regno < 24 && !AVR_ENHANCED)
5243 return !(regno & 1);
5246 /* Returns 1 if we know register operand OP was 0 before INSN. */
5249 reg_was_0 (insn, op)
5254 return (optimize > 0 && insn && op && REG_P (op)
5255 && (link = find_reg_note (insn, REG_WAS_0, 0))
5256 /* Make sure the insn that stored the 0 is still present. */
5257 && ! INSN_DELETED_P (XEXP (link, 0))
5258 && GET_CODE (XEXP (link, 0)) != NOTE
5259 /* Make sure cross jumping didn't happen here. */
5260 && no_labels_between_p (XEXP (link, 0), insn)
5261 /* Make sure the reg hasn't been clobbered. */
5262 && ! reg_set_between_p (op, XEXP (link, 0), insn));
5265 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5266 (1 or 2). Used for lds/sts -> in/out optimization. */
5269 io_address_p (x, size)
5273 return (optimize > 0 && GET_CODE (x) == CONST_INT
5274 && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
5277 /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5280 const_int_pow2_p (x)
5283 if (GET_CODE (x) == CONST_INT)
5285 HOST_WIDE_INT d = INTVAL (x);
5286 HOST_WIDE_INT abs_d = (d >= 0) ? d : -d;
5287 return exact_log2 (abs_d) + 1;
5293 output_reload_inhi (insn, operands, len)
5294 rtx insn ATTRIBUTE_UNUSED;
5302 if (GET_CODE (operands[1]) == CONST_INT)
5304 int val = INTVAL (operands[1]);
5305 if ((val & 0xff) == 0)
5308 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5309 AS2 (ldi,%2,hi8(%1)) CR_TAB
5312 else if ((val & 0xff00) == 0)
5315 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5316 AS2 (mov,%A0,%2) CR_TAB
5317 AS2 (mov,%B0,__zero_reg__));
5319 else if ((val & 0xff) == ((val & 0xff00) >> 8))
5322 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5323 AS2 (mov,%A0,%2) CR_TAB
5328 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5329 AS2 (mov,%A0,%2) CR_TAB
5330 AS2 (ldi,%2,hi8(%1)) CR_TAB
5336 output_reload_insisf (insn, operands, len)
5337 rtx insn ATTRIBUTE_UNUSED;
5341 rtx src = operands[1];
5342 int cnst = (GET_CODE (src) == CONST_INT);
5347 *len = 4 + ((INTVAL (src) & 0xff) != 0)
5348 + ((INTVAL (src) & 0xff00) != 0)
5349 + ((INTVAL (src) & 0xff0000) != 0)
5350 + ((INTVAL (src) & 0xff000000U) != 0);
5357 if (cnst && ((INTVAL (src) & 0xff) == 0))
5358 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5361 output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
5362 output_asm_insn (AS2 (mov, %A0, %2), operands);
5364 if (cnst && ((INTVAL (src) & 0xff00) == 0))
5365 output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
5368 output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
5369 output_asm_insn (AS2 (mov, %B0, %2), operands);
5371 if (cnst && ((INTVAL (src) & 0xff0000) == 0))
5372 output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
5375 output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
5376 output_asm_insn (AS2 (mov, %C0, %2), operands);
5378 if (cnst && ((INTVAL (src) & 0xff000000U) == 0))
5379 output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
5382 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5383 output_asm_insn (AS2 (mov, %D0, %2), operands);
5389 avr_output_bld (operands, bit_nr)
5393 static char s[] = "bld %A0,0";
5395 s[5] = 'A' + (bit_nr >> 3);
5396 s[8] = '0' + (bit_nr & 7);
5397 output_asm_insn (s, operands);
5401 avr_output_addr_vec_elt (stream, value)
5406 fprintf (stream, "\t.word pm(.L%d)\n", value);
5408 fprintf (stream, "\trjmp .L%d\n", value);
5413 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5414 registers (for a define_peephole2) in the current function. */
5417 avr_peep2_scratch_safe (scratch)
5420 if ((interrupt_function_p (current_function_decl)
5421 || signal_function_p (current_function_decl))
5422 && leaf_function_p ())
5424 int first_reg = true_regnum (scratch);
5425 int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
5428 for (reg = first_reg; reg <= last_reg; reg++)
5430 if (!regs_ever_live[reg])