1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Denis Chertykov (denisc@overta.ru)
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
26 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "conditions.h"
31 #include "insn-attr.h"
42 #include "target-def.h"
44 /* Maximal allowed offset for an address in the LD command */
45 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
47 static int avr_naked_function_p
PARAMS ((tree
));
48 static int interrupt_function_p
PARAMS ((tree
));
49 static int signal_function_p
PARAMS ((tree
));
50 static int sequent_regs_live
PARAMS ((void));
51 static const char * ptrreg_to_str
PARAMS ((int));
52 static const char * cond_string
PARAMS ((enum rtx_code
));
53 static int avr_num_arg_regs
PARAMS ((enum machine_mode
, tree
));
54 static int out_adj_frame_ptr
PARAMS ((FILE *, int));
55 static int out_set_stack_ptr
PARAMS ((FILE *, int, int));
56 static RTX_CODE compare_condition
PARAMS ((rtx insn
));
57 static int compare_sign_p
PARAMS ((rtx insn
));
58 static int reg_was_0
PARAMS ((rtx insn
, rtx op
));
59 void debug_hard_reg_set
PARAMS ((HARD_REG_SET set
));
60 static tree avr_handle_progmem_attribute
PARAMS ((tree
*, tree
, tree
, int, bool *));
61 static tree avr_handle_fndecl_attribute
PARAMS ((tree
*, tree
, tree
, int, bool *));
62 const struct attribute_spec avr_attribute_table
[];
63 static bool avr_assemble_integer
PARAMS ((rtx
, unsigned int, int));
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 { "at90s2333", AVR2
},
141 { "at90s2343", AVR2
},
142 { "attiny22", AVR2
},
143 { "attiny26", AVR2
},
144 { "at90s4414", AVR2
},
145 { "at90s4433", AVR2
},
146 { "at90s4434", AVR2
},
147 { "at90s8515", AVR2
},
148 { "at90c8534", AVR2
},
149 { "at90s8535", AVR2
},
152 { "atmega103", AVR3
},
153 { "atmega603", AVR3
},
154 { "at43usb320", AVR3
},
155 { "at43usb355", AVR3
},
156 { "at76c711", AVR3
},
157 /* Enhanced, <= 8K. */
160 { "atmega83", AVR4
},
161 { "atmega85", AVR4
},
162 { "atmega8515", AVR4
},
163 /* Enhanced, > 8K. */
165 { "atmega16", AVR5
},
166 { "atmega161", AVR5
},
167 { "atmega162", AVR5
},
168 { "atmega163", AVR5
},
169 { "atmega32", AVR5
},
170 { "atmega323", AVR5
},
171 { "atmega64", AVR5
},
172 { "atmega128", AVR5
},
174 /* Assembler only. */
176 { "at90s1200", AVR1
},
177 { "attiny10", AVR1
},
178 { "attiny11", AVR1
},
179 { "attiny12", AVR1
},
180 { "attiny15", AVR1
},
181 { "attiny28", AVR1
},
185 int avr_case_values_threshold
= 30000;
187 /* Initialize the GCC target structure. */
188 #undef TARGET_ASM_ALIGNED_HI_OP
189 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
190 #undef TARGET_ASM_INTEGER
191 #define TARGET_ASM_INTEGER avr_assemble_integer
193 #undef TARGET_ASM_FUNCTION_PROLOGUE
194 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
195 #undef TARGET_ASM_FUNCTION_EPILOGUE
196 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
197 #undef TARGET_ATTRIBUTE_TABLE
198 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
200 struct gcc_target targetm
= TARGET_INITIALIZER
;
203 avr_override_options ()
205 const struct mcu_type_s
*t
;
207 for (t
= avr_mcu_types
; t
->name
; t
++)
208 if (strcmp (t
->name
, avr_mcu_name
) == 0)
213 fprintf (stderr
, "unknown MCU `%s' specified\nKnown MCU names:\n",
215 for (t
= avr_mcu_types
; t
->name
; t
++)
216 fprintf (stderr
," %s\n", t
->name
);
223 error ("MCU `%s' not supported", avr_mcu_name
);
224 /* ... fall through ... */
225 case AVR2
: avr_enhanced_p
= 0; avr_mega_p
= 0; break;
226 case AVR3
: avr_enhanced_p
= 0; avr_mega_p
= 1; break;
227 case AVR4
: avr_enhanced_p
= 1; avr_mega_p
= 0; break;
228 case AVR5
: avr_enhanced_p
= 1; avr_mega_p
= 1; break;
231 if (optimize
&& !TARGET_NO_TABLEJUMP
)
232 avr_case_values_threshold
= (!AVR_MEGA
|| TARGET_CALL_PROLOGUES
) ? 8 : 17;
236 /* Initialize TMP_REG_RTX and ZERO_REG_RTX */
240 tmp_reg_rtx
= xmalloc (sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
241 memset (tmp_reg_rtx
, 0, sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
242 PUT_CODE (tmp_reg_rtx
, REG
);
243 PUT_MODE (tmp_reg_rtx
, QImode
);
244 XINT (tmp_reg_rtx
, 0) = TMP_REGNO
;
246 zero_reg_rtx
= xmalloc (sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
247 memset (zero_reg_rtx
, 0, sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
248 PUT_CODE (zero_reg_rtx
, REG
);
249 PUT_MODE (zero_reg_rtx
, QImode
);
250 XINT (zero_reg_rtx
, 0) = ZERO_REGNO
;
252 ldi_reg_rtx
= xmalloc (sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
253 memset (ldi_reg_rtx
, 0, sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
254 PUT_CODE (ldi_reg_rtx
, REG
);
255 PUT_MODE (ldi_reg_rtx
, QImode
);
256 XINT (ldi_reg_rtx
, 0) = LDI_REG_REGNO
;
259 /* return register class from register number */
261 static const int reg_class_tab
[]={
262 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
263 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
264 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
265 GENERAL_REGS
, /* r0 - r15 */
266 LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,
267 LD_REGS
, /* r16 - 23 */
268 ADDW_REGS
,ADDW_REGS
, /* r24,r25 */
269 POINTER_X_REGS
,POINTER_X_REGS
, /* r26,27 */
270 POINTER_Y_REGS
,POINTER_Y_REGS
, /* r28,r29 */
271 POINTER_Z_REGS
,POINTER_Z_REGS
, /* r30,r31 */
272 STACK_REG
,STACK_REG
/* SPL,SPH */
275 /* Return register class for register R */
278 avr_regno_reg_class (r
)
282 return reg_class_tab
[r
];
287 /* A C expression which defines the machine-dependent operand
288 constraint letters for register classes. If C is such a
289 letter, the value should be the register class corresponding to
290 it. Otherwise, the value should be `NO_REGS'. The register
291 letter `r', corresponding to class `GENERAL_REGS', will not be
292 passed to this macro; you do not need to handle it. */
295 avr_reg_class_from_letter (c
)
300 case 't' : return R0_REG
;
301 case 'b' : return BASE_POINTER_REGS
;
302 case 'e' : return POINTER_REGS
;
303 case 'w' : return ADDW_REGS
;
304 case 'd' : return LD_REGS
;
305 case 'l' : return NO_LD_REGS
;
306 case 'a' : return SIMPLE_LD_REGS
;
307 case 'x' : return POINTER_X_REGS
;
308 case 'y' : return POINTER_Y_REGS
;
309 case 'z' : return POINTER_Z_REGS
;
310 case 'q' : return STACK_REG
;
316 /* Return non-zero if FUNC is a naked function. */
319 avr_naked_function_p (func
)
324 if (TREE_CODE (func
) != FUNCTION_DECL
)
327 a
= lookup_attribute ("naked", DECL_ATTRIBUTES (func
));
328 return a
!= NULL_TREE
;
331 /* Return nonzero if FUNC is an interrupt function as specified
332 by the "interrupt" attribute. */
335 interrupt_function_p (func
)
340 if (TREE_CODE (func
) != FUNCTION_DECL
)
343 a
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (func
));
344 return a
!= NULL_TREE
;
347 /* Return nonzero if FUNC is a signal function as specified
348 by the "signal" attribute. */
351 signal_function_p (func
)
356 if (TREE_CODE (func
) != FUNCTION_DECL
)
359 a
= lookup_attribute ("signal", DECL_ATTRIBUTES (func
));
360 return a
!= NULL_TREE
;
363 /* Compute offset between arg_pointer and frame_pointer */
366 initial_elimination_offset (from
, to
)
371 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
375 int interrupt_func_p
= interrupt_function_p (current_function_decl
);
376 int signal_func_p
= signal_function_p (current_function_decl
);
377 int leaf_func_p
= leaf_function_p ();
378 int offset
= frame_pointer_needed
? 2 : 0;
380 for (reg
= 0; reg
< 32; ++reg
)
382 if ((!leaf_func_p
&& (call_used_regs
[reg
]
383 && (interrupt_func_p
|| signal_func_p
)))
384 || (regs_ever_live
[reg
]
385 && (!call_used_regs
[reg
] || interrupt_func_p
|| signal_func_p
)
386 && ! (frame_pointer_needed
387 && (reg
== REG_Y
|| reg
== (REG_Y
+1)))))
392 return get_frame_size () + 2 + 1 + offset
;
397 /* This function checks sequence of live registers */
406 for (reg
= 0; reg
< 18; ++reg
)
408 if (!call_used_regs
[reg
])
410 if (regs_ever_live
[reg
])
420 if (!frame_pointer_needed
)
422 if (regs_ever_live
[REG_Y
])
430 if (regs_ever_live
[REG_Y
+1])
443 return (cur_seq
== live_seq
) ? live_seq
: 0;
447 /* Output to FILE the asm instructions to adjust the frame pointer by
448 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
449 (epilogue). Returns the number of instructions generated. */
452 out_adj_frame_ptr (file
, adj
)
460 if (TARGET_TINY_STACK
)
462 if (adj
< -63 || adj
> 63)
463 warning ("large frame pointer change (%d) with -mtiny-stack", adj
);
465 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
466 over "sbiw" (2 cycles, same size). */
468 fprintf (file
, (AS2 (subi
, r28
, %d
) CR_TAB
), adj
);
471 else if (adj
< -63 || adj
> 63)
473 fprintf (file
, (AS2 (subi
, r28
, lo8(%d
)) CR_TAB
474 AS2 (sbci
, r29
, hi8(%d
)) CR_TAB
),
480 fprintf (file
, (AS2 (adiw
, r28
, %d
) CR_TAB
), -adj
);
485 fprintf (file
, (AS2 (sbiw
, r28
, %d
) CR_TAB
), adj
);
493 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
494 handling various cases of interrupt enable flag state BEFORE and AFTER
495 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
496 Returns the number of instructions generated. */
499 out_set_stack_ptr (file
, before
, after
)
504 int do_sph
, do_cli
, do_save
, do_sei
, lock_sph
, size
;
506 /* The logic here is so that -mno-interrupts actually means
507 "it is safe to write SPH in one instruction, then SPL in the
508 next instruction, without disabling interrupts first".
509 The after != -1 case (interrupt/signal) is not affected. */
511 do_sph
= !TARGET_TINY_STACK
;
512 lock_sph
= do_sph
&& !TARGET_NO_INTERRUPTS
;
513 do_cli
= (before
!= 0 && (after
== 0 || lock_sph
));
514 do_save
= (do_cli
&& before
== -1 && after
== -1);
515 do_sei
= ((do_cli
|| before
!= 1) && after
== 1);
520 fprintf (file
, AS2 (in
, __tmp_reg__
, __SREG__
) CR_TAB
);
526 fprintf (file
, "cli" CR_TAB
);
530 /* Do SPH first - maybe this will disable interrupts for one instruction
531 someday (a suggestion has been sent to avr@atmel.com for consideration
532 in future devices - that would make -mno-interrupts always safe). */
535 fprintf (file
, AS2 (out
, __SP_H__
, r29
) CR_TAB
);
539 /* Set/restore the I flag now - interrupts will be really enabled only
540 after the next instruction. This is not clearly documented, but
541 believed to be true for all AVR devices. */
544 fprintf (file
, AS2 (out
, __SREG__
, __tmp_reg__
) CR_TAB
);
549 fprintf (file
, "sei" CR_TAB
);
553 fprintf (file
, AS2 (out
, __SP_L__
, r28
) "\n");
559 /* Output function prologue */
562 avr_output_function_prologue (file
, size
)
567 int interrupt_func_p
;
574 if (avr_naked_function_p (current_function_decl
))
576 fprintf (file
, "/* prologue: naked */\n");
580 interrupt_func_p
= interrupt_function_p (current_function_decl
);
581 signal_func_p
= signal_function_p (current_function_decl
);
582 leaf_func_p
= leaf_function_p ();
583 main_p
= MAIN_NAME_P (DECL_NAME (current_function_decl
));
584 live_seq
= sequent_regs_live ();
585 minimize
= (TARGET_CALL_PROLOGUES
586 && !interrupt_func_p
&& !signal_func_p
&& live_seq
);
588 last_insn_address
= 0;
589 jump_tables_size
= 0;
591 fprintf (file
, "/* prologue: frame size=%d */\n", size
);
593 if (interrupt_func_p
)
595 fprintf (file
,"\tsei\n");
598 if (interrupt_func_p
| signal_func_p
)
601 AS1 (push
,__zero_reg__
) CR_TAB
602 AS1 (push
,__tmp_reg__
) CR_TAB
603 AS2 (in
,__tmp_reg__
,__SREG__
) CR_TAB
604 AS1 (push
,__tmp_reg__
) CR_TAB
605 AS1 (clr
,__zero_reg__
) "\n");
611 AS2 (ldi
,r28
,lo8(%s
- %d
)) CR_TAB
612 AS2 (ldi
,r29
,hi8(%s
- %d
)) CR_TAB
613 AS2 (out
,__SP_H__
,r29
) CR_TAB
614 AS2 (out
,__SP_L__
,r28
) "\n"),
615 avr_init_stack
, size
, avr_init_stack
, size
);
619 else if (minimize
&& (frame_pointer_needed
|| live_seq
> 6))
622 AS2 (ldi
, r26
, lo8(%d
)) CR_TAB
623 AS2 (ldi
, r27
, hi8(%d
)) CR_TAB
), size
, size
);
625 fprintf (file
, (AS2 (ldi
, r30
, pm_lo8(.L_
%s_body
)) CR_TAB
626 AS2 (ldi
, r31
, pm_hi8(.L_
%s_body
)) CR_TAB
)
627 ,current_function_name
, current_function_name
);
633 fprintf (file
, AS1 (jmp
,__prologue_saves__
+%d
) "\n",
634 (18 - live_seq
) * 2);
639 fprintf (file
, AS1 (rjmp
,__prologue_saves__
+%d
) "\n",
640 (18 - live_seq
) * 2);
643 fprintf (file
, ".L_%s_body:\n", current_function_name
);
647 for (reg
= 0; reg
< 32; ++reg
)
650 && (call_used_regs
[reg
]
651 && (interrupt_func_p
|| signal_func_p
)
652 && !(reg
== TMP_REGNO
|| reg
== ZERO_REGNO
)))
653 || (regs_ever_live
[reg
]
654 && (!call_used_regs
[reg
]
655 || interrupt_func_p
|| signal_func_p
)
656 && ! (frame_pointer_needed
657 && (reg
== REG_Y
|| reg
== (REG_Y
+1)))))
659 fprintf (file
, "\t" AS1 (push
,%s
) "\n", avr_regnames
[reg
]);
663 if (frame_pointer_needed
)
667 AS1 (push
,r28
) CR_TAB
668 AS1 (push
,r29
) CR_TAB
669 AS2 (in
,r28
,__SP_L__
) CR_TAB
670 AS2 (in
,r29
,__SP_H__
) "\n");
675 prologue_size
+= out_adj_frame_ptr (file
, size
);
677 if (interrupt_func_p
)
679 prologue_size
+= out_set_stack_ptr (file
, 1, 1);
681 else if (signal_func_p
)
683 prologue_size
+= out_set_stack_ptr (file
, 0, 0);
687 prologue_size
+= out_set_stack_ptr (file
, -1, -1);
693 fprintf (file
, "/* prologue end (size=%d) */\n", prologue_size
);
696 /* Output function epilogue */
699 avr_output_function_epilogue (file
, size
)
704 int interrupt_func_p
;
712 if (avr_naked_function_p (current_function_decl
))
714 fprintf (file
, "/* epilogue: naked */\n");
718 interrupt_func_p
= interrupt_function_p (current_function_decl
);
719 signal_func_p
= signal_function_p (current_function_decl
);
720 leaf_func_p
= leaf_function_p ();
721 main_p
= MAIN_NAME_P (DECL_NAME (current_function_decl
));
722 function_size
= (INSN_ADDRESSES (INSN_UID (get_last_insn ()))
723 - INSN_ADDRESSES (INSN_UID (get_insns ())));
724 function_size
+= jump_tables_size
;
725 live_seq
= sequent_regs_live ();
726 minimize
= (TARGET_CALL_PROLOGUES
727 && !interrupt_func_p
&& !signal_func_p
&& live_seq
);
730 fprintf (file
, "/* epilogue: frame size=%d */\n", size
);
733 fprintf (file
, "__stop_progIi__:\n\trjmp __stop_progIi__\n");
736 else if (minimize
&& (frame_pointer_needed
|| live_seq
> 4))
738 fprintf (file
, ("\t" AS2 (ldi
, r30
, %d
) CR_TAB
), live_seq
);
740 if (frame_pointer_needed
)
742 epilogue_size
+= out_adj_frame_ptr (file
, -size
);
746 fprintf (file
, (AS2 (in
, r28
, __SP_L__
) CR_TAB
747 AS2 (in
, r29
, __SP_H__
) CR_TAB
));
753 fprintf (file
, AS1 (jmp
,__epilogue_restores__
+%d
) "\n",
754 (18 - live_seq
) * 2);
759 fprintf (file
, AS1 (rjmp
,__epilogue_restores__
+%d
) "\n",
760 (18 - live_seq
) * 2);
766 if (frame_pointer_needed
)
771 epilogue_size
+= out_adj_frame_ptr (file
, -size
);
773 if (interrupt_func_p
| signal_func_p
)
775 epilogue_size
+= out_set_stack_ptr (file
, -1, 0);
779 epilogue_size
+= out_set_stack_ptr (file
, -1, -1);
788 for (reg
= 31; reg
>= 0; --reg
)
791 && (call_used_regs
[reg
]
792 && (interrupt_func_p
|| signal_func_p
)
793 && !(reg
== TMP_REGNO
|| reg
== ZERO_REGNO
)))
794 || (regs_ever_live
[reg
]
795 && (!call_used_regs
[reg
]
796 || interrupt_func_p
|| signal_func_p
)
797 && ! (frame_pointer_needed
798 && (reg
== REG_Y
|| reg
== (REG_Y
+1)))))
800 fprintf (file
, "\t" AS1 (pop
,%s
) "\n", avr_regnames
[reg
]);
805 if (interrupt_func_p
| signal_func_p
)
808 AS1 (pop
,__tmp_reg__
) CR_TAB
809 AS2 (out
,__SREG__
,__tmp_reg__
) CR_TAB
810 AS1 (pop
,__tmp_reg__
) CR_TAB
811 AS1 (pop
,__zero_reg__
) "\n");
813 fprintf (file
, "\treti\n");
816 fprintf (file
, "\tret\n");
820 fprintf (file
, "/* epilogue end (size=%d) */\n", epilogue_size
);
821 fprintf (file
, "/* function %s size %d (%d) */\n", current_function_name
,
822 prologue_size
+ function_size
+ epilogue_size
, function_size
);
823 commands_in_file
+= prologue_size
+ function_size
+ epilogue_size
;
824 commands_in_prologues
+= prologue_size
;
825 commands_in_epilogues
+= epilogue_size
;
829 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
830 machine for a memory operand of mode MODE. */
833 legitimate_address_p (mode
, x
, strict
)
834 enum machine_mode mode
;
838 enum reg_class r
= NO_REGS
;
840 if (TARGET_ALL_DEBUG
)
842 fprintf (stderr
, "mode: (%s) %s %s %s %s:",
844 strict
? "(strict)": "",
845 reload_completed
? "(reload_completed)": "",
846 reload_in_progress
? "(reload_in_progress)": "",
847 reg_renumber
? "(reg_renumber)" : "");
848 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
852 && INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
)
855 fprintf (stderr
, "(r%d ---> r%d)", REGNO (XEXP (x
, 0)),
856 true_regnum (XEXP (x
, 0)));
859 if (REG_P (x
) && (strict
? REG_OK_FOR_BASE_STRICT_P (x
)
860 : REG_OK_FOR_BASE_NOSTRICT_P (x
)))
862 else if (CONSTANT_ADDRESS_P (x
))
864 else if (GET_CODE (x
) == PLUS
865 && REG_P (XEXP (x
, 0))
866 && GET_CODE (XEXP (x
, 1)) == CONST_INT
867 && INTVAL (XEXP (x
, 1)) >= 0)
869 int fit
= INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
);
873 || REGNO (XEXP (x
,0)) == REG_Y
874 || REGNO (XEXP (x
,0)) == REG_Z
)
875 r
= BASE_POINTER_REGS
;
876 if (XEXP (x
,0) == frame_pointer_rtx
877 || XEXP (x
,0) == arg_pointer_rtx
)
878 r
= BASE_POINTER_REGS
;
880 else if (frame_pointer_needed
&& XEXP (x
,0) == frame_pointer_rtx
)
883 else if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == POST_INC
)
884 && REG_P (XEXP (x
, 0))
885 && (strict
? REG_OK_FOR_BASE_STRICT_P (XEXP (x
, 0))
886 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x
, 0))))
890 if (TARGET_ALL_DEBUG
)
892 fprintf (stderr
, " ret = %c\n", r
);
894 return r
== NO_REGS
? 0 : (int)r
;
897 /* Attempts to replace X with a valid
898 memory address for an operand of mode MODE */
901 legitimize_address (x
, oldx
, mode
)
904 enum machine_mode mode
;
907 if (TARGET_ALL_DEBUG
)
909 fprintf (stderr
, "legitimize_address mode: %s", GET_MODE_NAME(mode
));
913 if (GET_CODE (oldx
) == PLUS
914 && REG_P (XEXP (oldx
,0)))
916 if (REG_P (XEXP (oldx
,1)))
917 x
= force_reg (GET_MODE (oldx
), oldx
);
918 else if (GET_CODE (XEXP (oldx
, 1)) == CONST_INT
)
920 int offs
= INTVAL (XEXP (oldx
,1));
921 if (frame_pointer_rtx
!= XEXP (oldx
,0))
922 if (offs
> MAX_LD_OFFSET (mode
))
924 if (TARGET_ALL_DEBUG
)
925 fprintf (stderr
, "force_reg (big offset)\n");
926 x
= force_reg (GET_MODE (oldx
), oldx
);
934 /* Return a pointer register name as a string */
937 ptrreg_to_str (regno
)
942 case REG_X
: return "X";
943 case REG_Y
: return "Y";
944 case REG_Z
: return "Z";
951 /* Return the condition name as a string.
952 Used in conditional jump constructing */
965 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
970 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
983 /* Output ADDR to FILE as address */
986 print_operand_address (file
, addr
)
990 switch (GET_CODE (addr
))
993 fprintf (file
, ptrreg_to_str (REGNO (addr
)));
997 fprintf (file
, "-%s", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
1001 fprintf (file
, "%s+", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
1005 if (CONSTANT_ADDRESS_P (addr
)
1006 && ((GET_CODE (addr
) == SYMBOL_REF
&& SYMBOL_REF_FLAG (addr
))
1007 || GET_CODE (addr
) == LABEL_REF
))
1009 fprintf (file
, "pm(");
1010 output_addr_const (file
,addr
);
1011 fprintf (file
,")");
1014 output_addr_const (file
, addr
);
1019 /* Output X as assembler operand to file FILE */
1022 print_operand (file
, x
, code
)
1029 if (code
>= 'A' && code
<= 'D')
1039 if (x
== zero_reg_rtx
)
1040 fprintf (file
, "__zero_reg__");
1042 fprintf (file
, reg_names
[true_regnum (x
) + abcd
]);
1044 else if (GET_CODE (x
) == CONST_INT
)
1045 fprintf (file
, "%d", INTVAL (x
) + abcd
);
1046 else if (GET_CODE (x
) == MEM
)
1048 rtx addr
= XEXP (x
,0);
1050 if (CONSTANT_P (addr
) && abcd
)
1053 output_address (addr
);
1054 fprintf (file
, ")+%d", abcd
);
1056 else if (code
== 'o')
1058 if (GET_CODE (addr
) != PLUS
)
1059 fatal_insn ("bad address, not (reg+disp):", addr
);
1061 print_operand (file
, XEXP (addr
, 1), 0);
1063 else if (GET_CODE (addr
) == PLUS
)
1065 print_operand_address (file
, XEXP (addr
,0));
1066 if (REGNO (XEXP (addr
, 0)) == REG_X
)
1067 fatal_insn ("internal compiler error. Bad address:"
1070 print_operand (file
, XEXP (addr
,1), code
);
1073 print_operand_address (file
, addr
);
1075 else if (GET_CODE (x
) == CONST_DOUBLE
)
1079 if (GET_MODE (x
) != SFmode
)
1080 fatal_insn ("internal compiler error. Unknown mode:", x
);
1081 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
1082 REAL_VALUE_TO_TARGET_SINGLE (rv
, val
);
1083 asm_fprintf (file
, "0x%lx", val
);
1085 else if (code
== 'j')
1086 asm_fprintf (file
, cond_string (GET_CODE (x
)));
1087 else if (code
== 'k')
1088 asm_fprintf (file
, cond_string (reverse_condition (GET_CODE (x
))));
1090 print_operand_address (file
, x
);
1093 /* Recognize operand OP of mode MODE used in call instructions */
1096 call_insn_operand (op
, mode
)
1098 enum machine_mode mode ATTRIBUTE_UNUSED
;
1100 if (GET_CODE (op
) == MEM
)
1102 rtx inside
= XEXP (op
, 0);
1103 if (register_operand (inside
, Pmode
))
1105 if (CONSTANT_ADDRESS_P (inside
))
1111 /* Update the condition code in the INSN. */
1114 notice_update_cc (body
, insn
)
1115 rtx body ATTRIBUTE_UNUSED
;
1120 switch (get_attr_cc (insn
))
1123 /* Insn does not affect CC at all. */
1131 set
= single_set (insn
);
1135 cc_status
.flags
|= CC_NO_OVERFLOW
;
1136 cc_status
.value1
= SET_DEST (set
);
1141 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1142 The V flag may or may not be known but that's ok because
1143 alter_cond will change tests to use EQ/NE. */
1144 set
= single_set (insn
);
1148 cc_status
.value1
= SET_DEST (set
);
1149 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1154 set
= single_set (insn
);
1157 cc_status
.value1
= SET_SRC (set
);
1161 /* Insn doesn't leave CC in a usable state. */
1164 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1165 set
= single_set (insn
);
1168 rtx src
= SET_SRC (set
);
1170 if (GET_CODE (src
) == ASHIFTRT
1171 && GET_MODE (src
) == QImode
)
1173 rtx x
= XEXP (src
, 1);
1175 if (GET_CODE (x
) == CONST_INT
1178 cc_status
.value1
= SET_DEST (set
);
1179 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1187 /* Return maximum number of consecutive registers of
1188 class CLASS needed to hold a value of mode MODE. */
1191 class_max_nregs (class, mode
)
1192 enum reg_class
class ATTRIBUTE_UNUSED
;
1193 enum machine_mode mode
;
1195 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
);
1198 /* Choose mode for jump insn:
1199 1 - relative jump in range -63 <= x <= 62 ;
1200 2 - relative jump in range -2046 <= x <= 2045 ;
1201 3 - absolute jump (only for ATmega[16]03). */
1204 avr_jump_mode (x
, insn
)
1205 rtx x
; /* jump operand */
1206 rtx insn
; /* jump insn */
1208 int dest_addr
= INSN_ADDRESSES (INSN_UID (GET_MODE (x
) == LABEL_REF
1209 ? XEXP (x
, 0) : x
));
1210 int cur_addr
= INSN_ADDRESSES (INSN_UID (insn
));
1211 int jump_distance
= cur_addr
- dest_addr
;
1213 if (-63 <= jump_distance
&& jump_distance
<= 62)
1215 else if (-2046 <= jump_distance
&& jump_distance
<= 2045)
1223 /* return an AVR condition jump commands.
1224 X is a comparison RTX.
1225 LEN is a number returned by avr_jump_mode function.
1226 if REVERSE nonzero then condition code in X must be reversed. */
1229 ret_cond_branch (x
, len
, reverse
)
1234 RTX_CODE cond
= reverse
? reverse_condition (GET_CODE (x
)) : GET_CODE (x
);
1239 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1240 return (len
== 1 ? (AS1 (breq
,_PC_
+2) CR_TAB
1242 len
== 2 ? (AS1 (breq
,_PC_
+4) CR_TAB
1243 AS1 (brmi
,_PC_
+2) CR_TAB
1245 (AS1 (breq
,_PC_
+6) CR_TAB
1246 AS1 (brmi
,_PC_
+4) CR_TAB
1250 return (len
== 1 ? (AS1 (breq
,_PC_
+2) CR_TAB
1252 len
== 2 ? (AS1 (breq
,_PC_
+4) CR_TAB
1253 AS1 (brlt
,_PC_
+2) CR_TAB
1255 (AS1 (breq
,_PC_
+6) CR_TAB
1256 AS1 (brlt
,_PC_
+4) CR_TAB
1259 return (len
== 1 ? (AS1 (breq
,_PC_
+2) CR_TAB
1261 len
== 2 ? (AS1 (breq
,_PC_
+4) CR_TAB
1262 AS1 (brlo
,_PC_
+2) CR_TAB
1264 (AS1 (breq
,_PC_
+6) CR_TAB
1265 AS1 (brlo
,_PC_
+4) CR_TAB
1268 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1269 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1271 len
== 2 ? (AS1 (breq
,_PC_
+2) CR_TAB
1272 AS1 (brpl
,_PC_
+2) CR_TAB
1274 (AS1 (breq
,_PC_
+2) CR_TAB
1275 AS1 (brpl
,_PC_
+4) CR_TAB
1278 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1280 len
== 2 ? (AS1 (breq
,_PC_
+2) CR_TAB
1281 AS1 (brge
,_PC_
+2) CR_TAB
1283 (AS1 (breq
,_PC_
+2) CR_TAB
1284 AS1 (brge
,_PC_
+4) CR_TAB
1287 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1289 len
== 2 ? (AS1 (breq
,_PC_
+2) CR_TAB
1290 AS1 (brsh
,_PC_
+2) CR_TAB
1292 (AS1 (breq
,_PC_
+2) CR_TAB
1293 AS1 (brsh
,_PC_
+4) CR_TAB
1301 return AS1 (br
%k1
,%0);
1303 return (AS1 (br
%j1
,_PC_
+2) CR_TAB
1306 return (AS1 (br
%j1
,_PC_
+4) CR_TAB
1315 return AS1 (br
%j1
,%0);
1317 return (AS1 (br
%k1
,_PC_
+2) CR_TAB
1320 return (AS1 (br
%k1
,_PC_
+4) CR_TAB
1328 /* Predicate function for immediate operand which fits to byte (8bit) */
1331 byte_immediate_operand (op
, mode
)
1333 enum machine_mode mode ATTRIBUTE_UNUSED
;
1335 return (GET_CODE (op
) == CONST_INT
1336 && INTVAL (op
) <= 0xff && INTVAL (op
) >= 0);
1339 /* Output all insn addresses and their sizes into the assembly language
1340 output file. This is helpful for debugging whether the length attributes
1341 in the md file are correct.
1342 Output insn cost for next insn. */
1345 final_prescan_insn (insn
, operand
, num_operands
)
1346 rtx insn
, *operand ATTRIBUTE_UNUSED
;
1347 int num_operands ATTRIBUTE_UNUSED
;
1349 int uid
= INSN_UID (insn
);
1351 if (TARGET_INSN_SIZE_DUMP
|| TARGET_ALL_DEBUG
)
1353 fprintf (asm_out_file
, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1354 INSN_ADDRESSES (uid
),
1355 INSN_ADDRESSES (uid
) - last_insn_address
,
1356 rtx_cost (PATTERN (insn
), INSN
));
1358 last_insn_address
= INSN_ADDRESSES (uid
);
1360 if (TARGET_RTL_DUMP
)
1362 fprintf (asm_out_file
, "/*****************\n");
1363 print_rtl_single (asm_out_file
, insn
);
1364 fprintf (asm_out_file
, "*****************/\n");
1368 /* Return 0 if undefined, 1 if always true or always false. */
1371 avr_simplify_comparision_p (mode
, operator, x
)
1372 enum machine_mode mode
;
1376 unsigned int max
= (mode
== QImode
? 0xff :
1377 mode
== HImode
? 0xffff :
1378 mode
== SImode
? 0xffffffff : 0);
1379 if (max
&& operator && GET_CODE (x
) == CONST_INT
)
1381 if (unsigned_condition (operator) != operator)
1384 if (max
!= (INTVAL (x
) & max
)
1385 && INTVAL (x
) != 0xff)
1392 /* Returns nonzero if REGNO is the number of a hard
1393 register in which function arguments are sometimes passed. */
1396 function_arg_regno_p(r
)
1399 return (r
>= 8 && r
<= 25);
1402 /* Initializing the variable cum for the state at the beginning
1403 of the argument list. */
1406 init_cumulative_args (cum
, fntype
, libname
, indirect
)
1407 CUMULATIVE_ARGS
*cum
;
1410 int indirect ATTRIBUTE_UNUSED
;
1413 cum
->regno
= FIRST_CUM_REG
;
1416 int stdarg
= (TYPE_ARG_TYPES (fntype
) != 0
1417 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype
)))
1418 != void_type_node
));
1424 /* Returns the number of registers to allocate for a function argument. */
1427 avr_num_arg_regs (mode
, type
)
1428 enum machine_mode mode
;
1433 if (mode
== BLKmode
)
1434 size
= int_size_in_bytes (type
);
1436 size
= GET_MODE_SIZE (mode
);
1438 /* Align all function arguments to start in even-numbered registers.
1439 Odd-sized arguments leave holes above them. */
1441 return (size
+ 1) & ~1;
1444 /* Controls whether a function argument is passed
1445 in a register, and which register. */
1448 function_arg (cum
, mode
, type
, named
)
1449 CUMULATIVE_ARGS
*cum
;
1450 enum machine_mode mode
;
1452 int named ATTRIBUTE_UNUSED
;
1454 int bytes
= avr_num_arg_regs (mode
, type
);
1456 if (cum
->nregs
&& bytes
<= cum
->nregs
)
1457 return gen_rtx (REG
, mode
, cum
->regno
- bytes
);
1462 /* Update the summarizer variable CUM to advance past an argument
1463 in the argument list. */
1466 function_arg_advance (cum
, mode
, type
, named
)
1467 CUMULATIVE_ARGS
*cum
; /* current arg information */
1468 enum machine_mode mode
; /* current arg mode */
1469 tree type
; /* type of the argument or 0 if lib support */
1470 int named ATTRIBUTE_UNUSED
; /* whether or not the argument was named */
1472 int bytes
= avr_num_arg_regs (mode
, type
);
1474 cum
->nregs
-= bytes
;
1475 cum
->regno
-= bytes
;
1477 if (cum
->nregs
<= 0)
1480 cum
->regno
= FIRST_CUM_REG
;
1484 /***********************************************************************
1485 Functions for outputting various mov's for a various modes
1486 ************************************************************************/
1488 output_movqi (insn
, operands
, l
)
1494 rtx dest
= operands
[0];
1495 rtx src
= operands
[1];
1503 if (register_operand (dest
, QImode
))
1505 if (register_operand (src
, QImode
)) /* mov r,r */
1507 if (test_hard_reg_class (STACK_REG
, dest
))
1508 return AS2 (out
,%0,%1);
1509 else if (test_hard_reg_class (STACK_REG
, src
))
1510 return AS2 (in
,%0,%1);
1512 return AS2 (mov
,%0,%1);
1514 else if (CONSTANT_P (src
))
1516 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
1517 return AS2 (ldi
,%0,lo8(%1));
1519 if (GET_CODE (src
) == CONST_INT
)
1521 if (src
== const0_rtx
) /* mov r,L */
1522 return AS1 (clr
,%0);
1523 else if (src
== const1_rtx
)
1525 if (reg_was_0 (insn
, dest
))
1526 return AS1 (inc
,%0 ; reg_was_0
);
1529 return (AS1 (clr
,%0) CR_TAB
1532 else if (src
== constm1_rtx
)
1534 /* Immediate constants -1 to any register */
1535 if (reg_was_0 (insn
, dest
))
1536 return AS1 (dec
,%0 ; reg_was_0
);
1539 return (AS1 (clr
,%0) CR_TAB
1544 int bit_nr
= exact_log2 (INTVAL (src
));
1548 if (reg_was_0 (insn
, dest
))
1552 output_asm_insn ("set ; reg_was_0", operands
);
1558 output_asm_insn ((AS1 (clr
,%0) CR_TAB
1562 avr_output_bld (operands
, bit_nr
);
1569 /* Last resort, larger than loading from memory. */
1571 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1572 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1573 AS2 (mov
,%0,r31
) CR_TAB
1574 AS2 (mov
,r31
,__tmp_reg__
));
1576 else if (GET_CODE (src
) == MEM
)
1577 return out_movqi_r_mr (insn
, operands
, real_l
); /* mov r,m */
1579 else if (GET_CODE (dest
) == MEM
)
1581 const char *template;
1583 if (src
== const0_rtx
)
1584 operands
[1] = zero_reg_rtx
;
1586 template = out_movqi_mr_r (insn
, operands
, real_l
);
1589 output_asm_insn (template, operands
);
1598 output_movhi (insn
, operands
, l
)
1604 rtx dest
= operands
[0];
1605 rtx src
= operands
[1];
1611 if (register_operand (dest
, HImode
))
1613 if (register_operand (src
, HImode
)) /* mov r,r */
1615 if (test_hard_reg_class (STACK_REG
, dest
))
1617 if (TARGET_TINY_STACK
)
1620 return AS2 (out
,__SP_L__
,%A1
);
1622 else if (TARGET_NO_INTERRUPTS
)
1625 return (AS2 (out
,__SP_H__
,%B1
) CR_TAB
1626 AS2 (out
,__SP_L__
,%A1
));
1630 return (AS2 (in
,__tmp_reg__
,__SREG__
) CR_TAB
1632 AS2 (out
,__SP_H__
,%B1
) CR_TAB
1633 AS2 (out
,__SREG__
,__tmp_reg__
) CR_TAB
1634 AS2 (out
,__SP_L__
,%A1
));
1636 else if (test_hard_reg_class (STACK_REG
, src
))
1639 return (AS2 (in
,%A0
,__SP_L__
) CR_TAB
1640 AS2 (in
,%B0
,__SP_H__
));
1646 return (AS2 (movw
,%0,%1));
1649 if (true_regnum (dest
) > true_regnum (src
))
1652 return (AS2 (mov
,%B0
,%B1
) CR_TAB
1658 return (AS2 (mov
,%A0
,%A1
) CR_TAB
1662 else if (CONSTANT_P (src
))
1664 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
1666 if (byte_immediate_operand (src
, HImode
)
1667 && reg_was_0 (insn
, dest
))
1670 return (AS2 (ldi
,%A0
,lo8(%1) ; reg_was_0
));
1674 return (AS2 (ldi
,%A0
,lo8(%1)) CR_TAB
1675 AS2 (ldi
,%B0
,hi8(%1)));
1678 if (GET_CODE (src
) == CONST_INT
)
1680 if (src
== const0_rtx
) /* mov r,L */
1683 return (AS1 (clr
,%A0
) CR_TAB
1686 else if (src
== const1_rtx
)
1688 if (reg_was_0 (insn
, dest
))
1691 return AS1 (inc
,%0 ; reg_was_0
);
1695 return (AS1 (clr
,%A0
) CR_TAB
1696 AS1 (clr
,%B0
) CR_TAB
1699 else if (src
== constm1_rtx
)
1701 /* Immediate constants -1 to any register */
1702 if (reg_was_0 (insn
, dest
))
1705 return (AS1 (dec
,%A0
; reg_was_0
) CR_TAB
1710 return (AS1 (clr
,%0) CR_TAB
1711 AS1 (dec
,%A0
) CR_TAB
1716 int bit_nr
= exact_log2 (INTVAL (src
));
1720 if (reg_was_0 (insn
, dest
))
1724 output_asm_insn ("set ; reg_was_0", operands
);
1730 output_asm_insn ((AS1 (clr
,%A0
) CR_TAB
1731 AS1 (clr
,%B0
) CR_TAB
1735 avr_output_bld (operands
, bit_nr
);
1741 if ((INTVAL (src
) & 0xff) == 0)
1744 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1745 AS1 (clr
,%A0
) CR_TAB
1746 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
1747 AS2 (mov
,%B0
,r31
) CR_TAB
1748 AS2 (mov
,r31
,__tmp_reg__
));
1750 else if ((INTVAL (src
) & 0xff00) == 0)
1753 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1754 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1755 AS2 (mov
,%A0
,r31
) CR_TAB
1756 AS1 (clr
,%B0
) CR_TAB
1757 AS2 (mov
,r31
,__tmp_reg__
));
1761 /* Last resort, equal to loading from memory. */
1763 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1764 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1765 AS2 (mov
,%A0
,r31
) CR_TAB
1766 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
1767 AS2 (mov
,%B0
,r31
) CR_TAB
1768 AS2 (mov
,r31
,__tmp_reg__
));
1770 else if (GET_CODE (src
) == MEM
)
1771 return out_movhi_r_mr (insn
, operands
, real_l
); /* mov r,m */
1773 else if (GET_CODE (dest
) == MEM
)
1775 const char *template;
1777 if (src
== const0_rtx
)
1778 operands
[1] = zero_reg_rtx
;
1780 template = out_movhi_mr_r (insn
, operands
, real_l
);
1783 output_asm_insn (template, operands
);
1788 fatal_insn ("invalid insn:", insn
);
1793 out_movqi_r_mr (insn
, op
, l
)
1796 int *l
; /* instruction length */
1800 rtx x
= XEXP (src
, 0);
1806 if (CONSTANT_ADDRESS_P (x
))
1808 if (avr_io_address_p (x
, 1))
1811 return AS2 (in
,%0,%1-0x20);
1814 return AS2 (lds
,%0,%1);
1816 /* memory access by reg+disp */
1817 else if (GET_CODE (x
) == PLUS
1818 && REG_P (XEXP (x
,0))
1819 && GET_CODE (XEXP (x
,1)) == CONST_INT
)
1821 if ((INTVAL (XEXP (x
,1)) - GET_MODE_SIZE (GET_MODE (src
))) >= 63)
1823 int disp
= INTVAL (XEXP (x
,1));
1824 if (REGNO (XEXP (x
,0)) != REG_Y
)
1825 fatal_insn ("incorrect insn:",insn
);
1827 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
1828 return *l
= 3, (AS2 (adiw
,r28
,%o1
-63) CR_TAB
1829 AS2 (ldd
,%0,Y
+63) CR_TAB
1830 AS2 (sbiw
,r28
,%o1
-63));
1832 return *l
= 5, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
1833 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
1834 AS2 (ld
,%0,Y
) CR_TAB
1835 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
1836 AS2 (sbci
,r29
,hi8(%o1
)));
1838 else if (REGNO (XEXP (x
,0)) == REG_X
)
1840 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1841 it but I have this situation with extremal optimizing options. */
1842 if (reg_overlap_mentioned_p (dest
, XEXP (x
,0))
1843 || reg_unused_after (insn
, XEXP (x
,0)))
1844 return *l
= 2, (AS2 (adiw
,r26
,%o1
) CR_TAB
1847 return *l
= 3, (AS2 (adiw
,r26
,%o1
) CR_TAB
1848 AS2 (ld
,%0,X
) CR_TAB
1849 AS2 (sbiw
,r26
,%o1
));
1852 return AS2 (ldd
,%0,%1);
1855 return AS2 (ld
,%0,%1);
1859 out_movhi_r_mr (insn
, op
, l
)
1862 int *l
; /* instruction length */
1866 rtx base
= XEXP (src
, 0);
1867 int reg_dest
= true_regnum (dest
);
1868 int reg_base
= true_regnum (base
);
1876 if (reg_dest
== reg_base
) /* R = (R) */
1879 return (AS2 (ld
,__tmp_reg__
,%1+) CR_TAB
1880 AS2 (ld
,%B0
,%1) CR_TAB
1881 AS2 (mov
,%A0
,__tmp_reg__
));
1883 else if (reg_base
== REG_X
) /* (R26) */
1885 if (reg_unused_after (insn
, base
))
1888 return (AS2 (ld
,%A0
,X
+) CR_TAB
1892 return (AS2 (ld
,%A0
,X
+) CR_TAB
1893 AS2 (ld
,%B0
,X
) CR_TAB
1899 return (AS2 (ld
,%A0
,%1) CR_TAB
1900 AS2 (ldd
,%B0
,%1+1));
1903 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
1905 int disp
= INTVAL (XEXP (base
, 1));
1906 int reg_base
= true_regnum (XEXP (base
, 0));
1908 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
1910 if (REGNO (XEXP (base
, 0)) != REG_Y
)
1911 fatal_insn ("incorrect insn:",insn
);
1913 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
1914 return *l
= 4, (AS2 (adiw
,r28
,%o1
-62) CR_TAB
1915 AS2 (ldd
,%A0
,Y
+62) CR_TAB
1916 AS2 (ldd
,%B0
,Y
+63) CR_TAB
1917 AS2 (sbiw
,r28
,%o1
-62));
1919 return *l
= 6, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
1920 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
1921 AS2 (ld
,%A0
,Y
) CR_TAB
1922 AS2 (ldd
,%B0
,Y
+1) CR_TAB
1923 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
1924 AS2 (sbci
,r29
,hi8(%o1
)));
1926 if (reg_base
== REG_X
)
1928 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1929 it but I have this situation with extremal
1930 optimization options. */
1933 if (reg_base
== reg_dest
)
1934 return (AS2 (adiw
,r26
,%o1
) CR_TAB
1935 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
1936 AS2 (ld
,%B0
,X
) CR_TAB
1937 AS2 (mov
,%A0
,__tmp_reg__
));
1939 return (AS2 (adiw
,r26
,%o1
) CR_TAB
1940 AS2 (ld
,%A0
,X
+) CR_TAB
1941 AS2 (ld
,%B0
,X
) CR_TAB
1942 AS2 (sbiw
,r26
,%o1
+1));
1945 if (reg_base
== reg_dest
)
1948 return (AS2 (ldd
,__tmp_reg__
,%A1
) CR_TAB
1949 AS2 (ldd
,%B0
,%B1
) CR_TAB
1950 AS2 (mov
,%A0
,__tmp_reg__
));
1954 return (AS2 (ldd
,%A0
,%A1
) CR_TAB
1957 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
1959 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
1960 fatal_insn ("incorrect insn:", insn
);
1963 return (AS2 (ld
,%B0
,%1) CR_TAB
1966 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
1968 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
1969 fatal_insn ("incorrect insn:", insn
);
1972 return (AS2 (ld
,%A0
,%1) CR_TAB
1975 else if (CONSTANT_ADDRESS_P (base
))
1977 if (avr_io_address_p (base
, 2))
1980 return (AS2 (in
,%A0
,%A1
-0x20) CR_TAB
1981 AS2 (in
,%B0
,%B1
-0x20));
1984 return (AS2 (lds
,%A0
,%A1
) CR_TAB
1988 fatal_insn ("unknown move insn:",insn
);
1993 out_movsi_r_mr (insn
, op
, l
)
1996 int *l
; /* instruction length */
2000 rtx base
= XEXP (src
, 0);
2001 int reg_dest
= true_regnum (dest
);
2002 int reg_base
= true_regnum (base
);
2010 if (reg_base
== REG_X
) /* (R26) */
2012 if (reg_dest
== REG_X
)
2013 /* "ld r26,-X" is undefined */
2014 return *l
=7, (AS2 (adiw
,r26
,3) CR_TAB
2015 AS2 (ld
,r29
,X
) CR_TAB
2016 AS2 (ld
,r28
,-X
) CR_TAB
2017 AS2 (ld
,__tmp_reg__
,-X
) CR_TAB
2018 AS2 (sbiw
,r26
,1) CR_TAB
2019 AS2 (ld
,r26
,X
) CR_TAB
2020 AS2 (mov
,r27
,__tmp_reg__
));
2021 else if (reg_dest
== REG_X
- 2)
2022 return *l
=5, (AS2 (ld
,%A0
,X
+) CR_TAB
2023 AS2 (ld
,%B0
,X
+) CR_TAB
2024 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2025 AS2 (ld
,%D0
,X
) CR_TAB
2026 AS2 (mov
,%C0
,__tmp_reg__
));
2027 else if (reg_unused_after (insn
, base
))
2028 return *l
=4, (AS2 (ld
,%A0
,X
+) CR_TAB
2029 AS2 (ld
,%B0
,X
+) CR_TAB
2030 AS2 (ld
,%C0
,X
+) CR_TAB
2033 return *l
=5, (AS2 (ld
,%A0
,X
+) CR_TAB
2034 AS2 (ld
,%B0
,X
+) CR_TAB
2035 AS2 (ld
,%C0
,X
+) CR_TAB
2036 AS2 (ld
,%D0
,X
) CR_TAB
2041 if (reg_dest
== reg_base
)
2042 return *l
=5, (AS2 (ldd
,%D0
,%1+3) CR_TAB
2043 AS2 (ldd
,%C0
,%1+2) CR_TAB
2044 AS2 (ldd
,__tmp_reg__
,%1+1) CR_TAB
2045 AS2 (ld
,%A0
,%1) CR_TAB
2046 AS2 (mov
,%B0
,__tmp_reg__
));
2047 else if (reg_base
== reg_dest
+ 2)
2048 return *l
=5, (AS2 (ld
,%A0
,%1) CR_TAB
2049 AS2 (ldd
,%B0
,%1+1) CR_TAB
2050 AS2 (ldd
,__tmp_reg__
,%1+2) CR_TAB
2051 AS2 (ldd
,%D0
,%1+3) CR_TAB
2052 AS2 (mov
,%C0
,__tmp_reg__
));
2054 return *l
=4, (AS2 (ld
,%A0
,%1) CR_TAB
2055 AS2 (ldd
,%B0
,%1+1) CR_TAB
2056 AS2 (ldd
,%C0
,%1+2) CR_TAB
2057 AS2 (ldd
,%D0
,%1+3));
2060 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2062 int disp
= INTVAL (XEXP (base
, 1));
2064 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
2066 if (REGNO (XEXP (base
, 0)) != REG_Y
)
2067 fatal_insn ("incorrect insn:",insn
);
2069 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
2070 return *l
= 6, (AS2 (adiw
,r28
,%o1
-60) CR_TAB
2071 AS2 (ldd
,%A0
,Y
+60) CR_TAB
2072 AS2 (ldd
,%B0
,Y
+61) CR_TAB
2073 AS2 (ldd
,%C0
,Y
+62) CR_TAB
2074 AS2 (ldd
,%D0
,Y
+63) CR_TAB
2075 AS2 (sbiw
,r28
,%o1
-60));
2077 return *l
= 8, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
2078 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
2079 AS2 (ld
,%A0
,Y
) CR_TAB
2080 AS2 (ldd
,%B0
,Y
+1) CR_TAB
2081 AS2 (ldd
,%C0
,Y
+2) CR_TAB
2082 AS2 (ldd
,%D0
,Y
+3) CR_TAB
2083 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
2084 AS2 (sbci
,r29
,hi8(%o1
)));
2087 reg_base
= true_regnum (XEXP (base
, 0));
2088 if (reg_base
== REG_X
)
2091 if (reg_dest
== REG_X
)
2094 /* "ld r26,-X" is undefined */
2095 return (AS2 (adiw
,r26
,%o1
+3) CR_TAB
2096 AS2 (ld
,r29
,X
) CR_TAB
2097 AS2 (ld
,r28
,-X
) CR_TAB
2098 AS2 (ld
,__tmp_reg__
,-X
) CR_TAB
2099 AS2 (sbiw
,r26
,1) CR_TAB
2100 AS2 (ld
,r26
,X
) CR_TAB
2101 AS2 (mov
,r27
,__tmp_reg__
));
2104 if (reg_dest
== REG_X
- 2)
2105 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2106 AS2 (ld
,r24
,X
+) CR_TAB
2107 AS2 (ld
,r25
,X
+) CR_TAB
2108 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2109 AS2 (ld
,r27
,X
) CR_TAB
2110 AS2 (mov
,r26
,__tmp_reg__
));
2112 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2113 AS2 (ld
,%A0
,X
+) CR_TAB
2114 AS2 (ld
,%B0
,X
+) CR_TAB
2115 AS2 (ld
,%C0
,X
+) CR_TAB
2116 AS2 (ld
,%D0
,X
) CR_TAB
2117 AS2 (sbiw
,r26
,%o1
+3));
2119 if (reg_dest
== reg_base
)
2120 return *l
=5, (AS2 (ldd
,%D0
,%D1
) CR_TAB
2121 AS2 (ldd
,%C0
,%C1
) CR_TAB
2122 AS2 (ldd
,__tmp_reg__
,%B1
) CR_TAB
2123 AS2 (ldd
,%A0
,%A1
) CR_TAB
2124 AS2 (mov
,%B0
,__tmp_reg__
));
2125 else if (reg_dest
== reg_base
- 2)
2126 return *l
=5, (AS2 (ldd
,%A0
,%A1
) CR_TAB
2127 AS2 (ldd
,%B0
,%B1
) CR_TAB
2128 AS2 (ldd
,__tmp_reg__
,%C1
) CR_TAB
2129 AS2 (ldd
,%D0
,%D1
) CR_TAB
2130 AS2 (mov
,%C0
,__tmp_reg__
));
2131 return *l
=4, (AS2 (ldd
,%A0
,%A1
) CR_TAB
2132 AS2 (ldd
,%B0
,%B1
) CR_TAB
2133 AS2 (ldd
,%C0
,%C1
) CR_TAB
2136 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2137 return *l
=4, (AS2 (ld
,%D0
,%1) CR_TAB
2138 AS2 (ld
,%C0
,%1) CR_TAB
2139 AS2 (ld
,%B0
,%1) CR_TAB
2141 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2142 return *l
=4, (AS2 (ld
,%A0
,%1) CR_TAB
2143 AS2 (ld
,%B0
,%1) CR_TAB
2144 AS2 (ld
,%C0
,%1) CR_TAB
2146 else if (CONSTANT_ADDRESS_P (base
))
2147 return *l
=8, (AS2 (lds
,%A0
,%A1
) CR_TAB
2148 AS2 (lds
,%B0
,%B1
) CR_TAB
2149 AS2 (lds
,%C0
,%C1
) CR_TAB
2152 fatal_insn ("unknown move insn:",insn
);
2157 out_movsi_mr_r (insn
, op
, l
)
2164 rtx base
= XEXP (dest
, 0);
2165 int reg_base
= true_regnum (base
);
2166 int reg_src
= true_regnum (src
);
2172 if (CONSTANT_ADDRESS_P (base
))
2173 return *l
=8,(AS2 (sts
,%A0
,%A1
) CR_TAB
2174 AS2 (sts
,%B0
,%B1
) CR_TAB
2175 AS2 (sts
,%C0
,%C1
) CR_TAB
2177 if (reg_base
> 0) /* (r) */
2179 if (reg_base
== REG_X
) /* (R26) */
2181 if (reg_src
== REG_X
)
2183 /* "st X+,r26" is undefined */
2184 if (reg_unused_after (insn
, base
))
2185 return *l
=6, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2186 AS2 (st
,X
,r26
) CR_TAB
2187 AS2 (adiw
,r26
,1) CR_TAB
2188 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2189 AS2 (st
,X
+,r28
) CR_TAB
2192 return *l
=7, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2193 AS2 (st
,X
,r26
) CR_TAB
2194 AS2 (adiw
,r26
,1) CR_TAB
2195 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2196 AS2 (st
,X
+,r28
) CR_TAB
2197 AS2 (st
,X
,r29
) CR_TAB
2200 else if (reg_base
== reg_src
+ 2)
2202 if (reg_unused_after (insn
, base
))
2203 return *l
=7, (AS2 (mov
,__zero_reg__
,%C1
) CR_TAB
2204 AS2 (mov
,__tmp_reg__
,%D1
) CR_TAB
2205 AS2 (st
,%0+,%A1
) CR_TAB
2206 AS2 (st
,%0+,%B1
) CR_TAB
2207 AS2 (st
,%0+,__zero_reg__
) CR_TAB
2208 AS2 (st
,%0,__tmp_reg__
) CR_TAB
2209 AS1 (clr
,__zero_reg__
));
2211 return *l
=8, (AS2 (mov
,__zero_reg__
,%C1
) CR_TAB
2212 AS2 (mov
,__tmp_reg__
,%D1
) CR_TAB
2213 AS2 (st
,%0+,%A1
) CR_TAB
2214 AS2 (st
,%0+,%B1
) CR_TAB
2215 AS2 (st
,%0+,__zero_reg__
) CR_TAB
2216 AS2 (st
,%0,__tmp_reg__
) CR_TAB
2217 AS1 (clr
,__zero_reg__
) CR_TAB
2220 return *l
=5, (AS2 (st
,%0+,%A1
) CR_TAB
2221 AS2 (st
,%0+,%B1
) CR_TAB
2222 AS2 (st
,%0+,%C1
) CR_TAB
2223 AS2 (st
,%0,%D1
) CR_TAB
2227 return *l
=4, (AS2 (st
,%0,%A1
) CR_TAB
2228 AS2 (std
,%0+1,%B1
) CR_TAB
2229 AS2 (std
,%0+2,%C1
) CR_TAB
2230 AS2 (std
,%0+3,%D1
));
2232 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2234 int disp
= INTVAL (XEXP (base
, 1));
2235 reg_base
= REGNO (XEXP (base
, 0));
2236 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
2238 if (reg_base
!= REG_Y
)
2239 fatal_insn ("incorrect insn:",insn
);
2241 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2242 return *l
= 6, (AS2 (adiw
,r28
,%o0
-60) CR_TAB
2243 AS2 (std
,Y
+60,%A1
) CR_TAB
2244 AS2 (std
,Y
+61,%B1
) CR_TAB
2245 AS2 (std
,Y
+62,%C1
) CR_TAB
2246 AS2 (std
,Y
+63,%D1
) CR_TAB
2247 AS2 (sbiw
,r28
,%o0
-60));
2249 return *l
= 8, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2250 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2251 AS2 (st
,Y
,%A1
) CR_TAB
2252 AS2 (std
,Y
+1,%B1
) CR_TAB
2253 AS2 (std
,Y
+2,%C1
) CR_TAB
2254 AS2 (std
,Y
+3,%D1
) CR_TAB
2255 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2256 AS2 (sbci
,r29
,hi8(%o0
)));
2258 if (reg_base
== REG_X
)
2261 if (reg_src
== REG_X
)
2264 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2265 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2266 AS2 (adiw
,r26
,%o0
) CR_TAB
2267 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2268 AS2 (st
,X
+,__zero_reg__
) CR_TAB
2269 AS2 (st
,X
+,r28
) CR_TAB
2270 AS2 (st
,X
,r29
) CR_TAB
2271 AS1 (clr
,__zero_reg__
) CR_TAB
2272 AS2 (sbiw
,r26
,%o0
+3));
2274 else if (reg_src
== REG_X
- 2)
2277 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2278 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2279 AS2 (adiw
,r26
,%o0
) CR_TAB
2280 AS2 (st
,X
+,r24
) CR_TAB
2281 AS2 (st
,X
+,r25
) CR_TAB
2282 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2283 AS2 (st
,X
,__zero_reg__
) CR_TAB
2284 AS1 (clr
,__zero_reg__
) CR_TAB
2285 AS2 (sbiw
,r26
,%o0
+3));
2288 return (AS2 (adiw
,r26
,%o0
) CR_TAB
2289 AS2 (st
,X
+,%A1
) CR_TAB
2290 AS2 (st
,X
+,%B1
) CR_TAB
2291 AS2 (st
,X
+,%C1
) CR_TAB
2292 AS2 (st
,X
,%D1
) CR_TAB
2293 AS2 (sbiw
,r26
,%o0
+3));
2295 return *l
=4, (AS2 (std
,%A0
,%A1
) CR_TAB
2296 AS2 (std
,%B0
,%B1
) CR_TAB
2297 AS2 (std
,%C0
,%C1
) CR_TAB
2300 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2301 return *l
=4, (AS2 (st
,%0,%D1
) CR_TAB
2302 AS2 (st
,%0,%C1
) CR_TAB
2303 AS2 (st
,%0,%B1
) CR_TAB
2305 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2306 return *l
=4, (AS2 (st
,%0,%A1
) CR_TAB
2307 AS2 (st
,%0,%B1
) CR_TAB
2308 AS2 (st
,%0,%C1
) CR_TAB
2310 fatal_insn ("unknown move insn:",insn
);
2315 output_movsisf(insn
, operands
, l
)
2321 rtx dest
= operands
[0];
2322 rtx src
= operands
[1];
2328 if (register_operand (dest
, VOIDmode
))
2330 if (register_operand (src
, VOIDmode
)) /* mov r,r */
2332 if (true_regnum (dest
) > true_regnum (src
))
2337 return (AS2 (movw
,%C0
,%C1
) CR_TAB
2338 AS2 (movw
,%A0
,%A1
));
2341 return (AS2 (mov
,%D0
,%D1
) CR_TAB
2342 AS2 (mov
,%C0
,%C1
) CR_TAB
2343 AS2 (mov
,%B0
,%B1
) CR_TAB
2351 return (AS2 (movw
,%A0
,%A1
) CR_TAB
2352 AS2 (movw
,%C0
,%C1
));
2355 return (AS2 (mov
,%A0
,%A1
) CR_TAB
2356 AS2 (mov
,%B0
,%B1
) CR_TAB
2357 AS2 (mov
,%C0
,%C1
) CR_TAB
2361 else if (CONSTANT_P (src
))
2363 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
2365 if (byte_immediate_operand (src
, SImode
)
2366 && reg_was_0 (insn
, dest
))
2369 return (AS2 (ldi
,%A0
,lo8(%1) ; reg_was_0
));
2373 return (AS2 (ldi
,%A0
,lo8(%1)) CR_TAB
2374 AS2 (ldi
,%B0
,hi8(%1)) CR_TAB
2375 AS2 (ldi
,%C0
,hlo8(%1)) CR_TAB
2376 AS2 (ldi
,%D0
,hhi8(%1)));
2379 if (GET_CODE (src
) == CONST_INT
)
2381 const char *const clr_op0
=
2382 AVR_ENHANCED
? (AS1 (clr
,%A0
) CR_TAB
2383 AS1 (clr
,%B0
) CR_TAB
2385 : (AS1 (clr
,%A0
) CR_TAB
2386 AS1 (clr
,%B0
) CR_TAB
2387 AS1 (clr
,%C0
) CR_TAB
2390 if (src
== const0_rtx
) /* mov r,L */
2392 *l
= AVR_ENHANCED
? 3 : 4;
2395 else if (src
== const1_rtx
)
2397 if (reg_was_0 (insn
, dest
))
2400 return AS1 (inc
,%A0
; reg_was_0
);
2403 output_asm_insn (clr_op0
, operands
);
2404 *l
= AVR_ENHANCED
? 4 : 5;
2405 return AS1 (inc
,%A0
);
2407 else if (src
== constm1_rtx
)
2409 /* Immediate constants -1 to any register */
2410 if (reg_was_0 (insn
, dest
))
2415 return (AS1 (dec
,%A0
) CR_TAB
2416 AS1 (dec
,%B0
) CR_TAB
2417 AS2 (movw
,%C0
,%A0
));
2420 return (AS1 (dec
,%D0
; reg_was_0
) CR_TAB
2421 AS1 (dec
,%C0
) CR_TAB
2422 AS1 (dec
,%B0
) CR_TAB
2428 return (AS1 (clr
,%A0
) CR_TAB
2429 AS1 (dec
,%A0
) CR_TAB
2430 AS2 (mov
,%B0
,%A0
) CR_TAB
2431 AS2 (movw
,%C0
,%A0
));
2434 return (AS1 (clr
,%A0
) CR_TAB
2435 AS1 (dec
,%A0
) CR_TAB
2436 AS2 (mov
,%B0
,%A0
) CR_TAB
2437 AS2 (mov
,%C0
,%A0
) CR_TAB
2442 int bit_nr
= exact_log2 (INTVAL (src
));
2446 if (reg_was_0 (insn
, dest
))
2450 output_asm_insn ("set ; reg_was_0", operands
);
2454 *l
= AVR_ENHANCED
? 5 : 6;
2457 output_asm_insn (clr_op0
, operands
);
2458 output_asm_insn ("set", operands
);
2462 avr_output_bld (operands
, bit_nr
);
2469 /* Last resort, better than loading from memory. */
2471 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
2472 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
2473 AS2 (mov
,%A0
,r31
) CR_TAB
2474 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
2475 AS2 (mov
,%B0
,r31
) CR_TAB
2476 AS2 (ldi
,r31
,hlo8(%1)) CR_TAB
2477 AS2 (mov
,%C0
,r31
) CR_TAB
2478 AS2 (ldi
,r31
,hhi8(%1)) CR_TAB
2479 AS2 (mov
,%D0
,r31
) CR_TAB
2480 AS2 (mov
,r31
,__tmp_reg__
));
2482 else if (GET_CODE (src
) == MEM
)
2483 return out_movsi_r_mr (insn
, operands
, real_l
); /* mov r,m */
2485 else if (GET_CODE (dest
) == MEM
)
2487 const char *template;
2489 if (src
== const0_rtx
)
2490 operands
[1] = zero_reg_rtx
;
2492 template = out_movsi_mr_r (insn
, operands
, real_l
);
2495 output_asm_insn (template, operands
);
2500 fatal_insn ("invalid insn:", insn
);
2505 out_movqi_mr_r (insn
, op
, l
)
2508 int *l
; /* instruction length */
2512 rtx x
= XEXP (dest
, 0);
2518 if (CONSTANT_ADDRESS_P (x
))
2520 if (avr_io_address_p (x
, 1))
2523 return AS2 (out
,%0-0x20,%1);
2526 return AS2 (sts
,%0,%1);
2528 /* memory access by reg+disp */
2529 else if (GET_CODE (x
) == PLUS
2530 && REG_P (XEXP (x
,0))
2531 && GET_CODE (XEXP (x
,1)) == CONST_INT
)
2533 if ((INTVAL (XEXP (x
,1)) - GET_MODE_SIZE (GET_MODE (dest
))) >= 63)
2535 int disp
= INTVAL (XEXP (x
,1));
2536 if (REGNO (XEXP (x
,0)) != REG_Y
)
2537 fatal_insn ("incorrect insn:",insn
);
2539 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2540 return *l
= 3, (AS2 (adiw
,r28
,%o0
-63) CR_TAB
2541 AS2 (std
,Y
+63,%1) CR_TAB
2542 AS2 (sbiw
,r28
,%o0
-63));
2544 return *l
= 5, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2545 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2546 AS2 (st
,Y
,%1) CR_TAB
2547 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2548 AS2 (sbci
,r29
,hi8(%o0
)));
2550 else if (REGNO (XEXP (x
,0)) == REG_X
)
2552 if (reg_overlap_mentioned_p (src
, XEXP (x
, 0)))
2554 if (reg_unused_after (insn
, XEXP (x
,0)))
2555 return *l
= 3, (AS2 (mov
,__tmp_reg__
,%1) CR_TAB
2556 AS2 (adiw
,r26
,%o0
) CR_TAB
2557 AS2 (st
,X
,__tmp_reg__
));
2559 return *l
= 4, (AS2 (mov
,__tmp_reg__
,%1) CR_TAB
2560 AS2 (adiw
,r26
,%o0
) CR_TAB
2561 AS2 (st
,X
,__tmp_reg__
) CR_TAB
2562 AS2 (sbiw
,r26
,%o0
));
2566 if (reg_unused_after (insn
, XEXP (x
,0)))
2567 return *l
= 2, (AS2 (adiw
,r26
,%o0
) CR_TAB
2570 return *l
= 3, (AS2 (adiw
,r26
,%o0
) CR_TAB
2571 AS2 (st
,X
,%1) CR_TAB
2572 AS2 (sbiw
,r26
,%o0
));
2576 return AS2 (std
,%0,%1);
2579 return AS2 (st
,%0,%1);
2583 out_movhi_mr_r (insn
, op
, l
)
2590 rtx base
= XEXP (dest
, 0);
2591 int reg_base
= true_regnum (base
);
2592 int reg_src
= true_regnum (src
);
2596 if (CONSTANT_ADDRESS_P (base
))
2598 if (avr_io_address_p (base
, 2))
2601 return (AS2 (out
,%B0
-0x20,%B1
) CR_TAB
2602 AS2 (out
,%A0
-0x20,%A1
));
2604 return *l
= 4, (AS2 (sts
,%B0
,%B1
) CR_TAB
2609 if (reg_base
== REG_X
)
2611 if (reg_src
== REG_X
)
2613 /* "st X+,r26" is undefined */
2614 if (reg_unused_after (insn
, src
))
2615 return *l
=4, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2616 AS2 (st
,X
,r26
) CR_TAB
2617 AS2 (adiw
,r26
,1) CR_TAB
2618 AS2 (st
,X
,__tmp_reg__
));
2620 return *l
=5, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2621 AS2 (st
,X
,r26
) CR_TAB
2622 AS2 (adiw
,r26
,1) CR_TAB
2623 AS2 (st
,X
,__tmp_reg__
) CR_TAB
2628 if (reg_unused_after (insn
, base
))
2629 return *l
=2, (AS2 (st
,X
+,%A1
) CR_TAB
2632 return *l
=3, (AS2 (st
,X
+,%A1
) CR_TAB
2633 AS2 (st
,X
,%B1
) CR_TAB
2638 return *l
=2, (AS2 (st
,%0,%A1
) CR_TAB
2639 AS2 (std
,%0+1,%B1
));
2641 else if (GET_CODE (base
) == PLUS
)
2643 int disp
= INTVAL (XEXP (base
, 1));
2644 reg_base
= REGNO (XEXP (base
, 0));
2645 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
2647 if (reg_base
!= REG_Y
)
2648 fatal_insn ("incorrect insn:",insn
);
2650 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2651 return *l
= 4, (AS2 (adiw
,r28
,%o0
-62) CR_TAB
2652 AS2 (std
,Y
+62,%A1
) CR_TAB
2653 AS2 (std
,Y
+63,%B1
) CR_TAB
2654 AS2 (sbiw
,r28
,%o0
-62));
2656 return *l
= 6, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2657 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2658 AS2 (st
,Y
,%A1
) CR_TAB
2659 AS2 (std
,Y
+1,%B1
) CR_TAB
2660 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2661 AS2 (sbci
,r29
,hi8(%o0
)));
2663 if (reg_base
== REG_X
)
2666 if (reg_src
== REG_X
)
2669 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2670 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2671 AS2 (adiw
,r26
,%o0
) CR_TAB
2672 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2673 AS2 (st
,X
,__zero_reg__
) CR_TAB
2674 AS1 (clr
,__zero_reg__
) CR_TAB
2675 AS2 (sbiw
,r26
,%o0
+1));
2678 return (AS2 (adiw
,r26
,%o0
) CR_TAB
2679 AS2 (st
,X
+,%A1
) CR_TAB
2680 AS2 (st
,X
,%B1
) CR_TAB
2681 AS2 (sbiw
,r26
,%o0
+1));
2683 return *l
=2, (AS2 (std
,%A0
,%A1
) CR_TAB
2686 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2687 return *l
=2, (AS2 (st
,%0,%B1
) CR_TAB
2689 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2690 return *l
=2, (AS2 (st
,%0,%A1
) CR_TAB
2692 fatal_insn ("unknown move insn:",insn
);
2696 /* Return 1 if frame pointer for current function required */
2699 frame_pointer_required_p ()
2701 return (current_function_calls_alloca
2702 || current_function_args_info
.nregs
== 0
2703 || current_function_varargs
2704 || get_frame_size () > 0);
2707 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2710 compare_condition (insn
)
2713 rtx next
= next_real_insn (insn
);
2714 RTX_CODE cond
= UNKNOWN
;
2715 if (next
&& GET_CODE (next
) == JUMP_INSN
)
2717 rtx pat
= PATTERN (next
);
2718 rtx src
= SET_SRC (pat
);
2719 rtx t
= XEXP (src
, 0);
2720 cond
= GET_CODE (t
);
2725 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2728 compare_sign_p (insn
)
2731 RTX_CODE cond
= compare_condition (insn
);
2732 return (cond
== GE
|| cond
== LT
);
2735 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2736 that needs to be swapped (GT, GTU, LE, LEU). */
2739 compare_diff_p (insn
)
2742 RTX_CODE cond
= compare_condition (insn
);
2743 return (cond
== GT
|| cond
== GTU
|| cond
== LE
|| cond
== LEU
) ? cond
: 0;
2746 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2752 RTX_CODE cond
= compare_condition (insn
);
2753 return (cond
== EQ
|| cond
== NE
);
2757 /* Output test instruction for HImode */
2764 if (compare_sign_p (insn
))
2767 return AS1 (tst
,%B0
);
2769 if (reg_unused_after (insn
, SET_SRC (PATTERN (insn
)))
2770 && compare_eq_p (insn
))
2772 /* faster than sbiw if we can clobber the operand */
2774 return AS2 (or,%A0
,%B0
);
2776 if (test_hard_reg_class (ADDW_REGS
, SET_SRC (PATTERN (insn
))))
2779 return AS2 (sbiw
,%0,0);
2782 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2783 AS2 (cpc
,%B0
,__zero_reg__
));
2787 /* Output test instruction for SImode */
2794 if (compare_sign_p (insn
))
2797 return AS1 (tst
,%D0
);
2799 if (test_hard_reg_class (ADDW_REGS
, SET_SRC (PATTERN (insn
))))
2802 return (AS2 (sbiw
,%A0
,0) CR_TAB
2803 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2804 AS2 (cpc
,%D0
,__zero_reg__
));
2807 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2808 AS2 (cpc
,%B0
,__zero_reg__
) CR_TAB
2809 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2810 AS2 (cpc
,%D0
,__zero_reg__
));
2814 /* Generate asm equivalent for various shifts.
2815 Shift count is a CONST_INT, MEM or REG.
2816 This only handles cases that are not already
2817 carefully hand-optimized in ?sh??i3_out. */
2820 out_shift_with_cnt (template, insn
, operands
, len
, t_len
)
2821 const char *template;
2825 int t_len
; /* Length of template. */
2829 int second_label
= 1;
2830 int saved_in_tmp
= 0;
2831 int use_zero_reg
= 0;
2833 op
[0] = operands
[0];
2834 op
[1] = operands
[1];
2835 op
[2] = operands
[2];
2836 op
[3] = operands
[3];
2842 if (GET_CODE (operands
[2]) == CONST_INT
)
2844 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
2845 int count
= INTVAL (operands
[2]);
2846 int max_len
= 10; /* If larger than this, always use a loop. */
2848 if (count
< 8 && !scratch
)
2852 max_len
= t_len
+ (scratch
? 3 : (use_zero_reg
? 4 : 5));
2854 if (t_len
* count
<= max_len
)
2856 /* Output shifts inline with no loop - faster. */
2858 *len
= t_len
* count
;
2862 output_asm_insn (template, op
);
2871 strcat (str
, AS2 (ldi
,%3,%2));
2873 else if (use_zero_reg
)
2875 /* Hack to save one word: use __zero_reg__ as loop counter.
2876 Set one bit, then shift in a loop until it is 0 again. */
2878 op
[3] = zero_reg_rtx
;
2882 strcat (str
, ("set" CR_TAB
2883 AS2 (bld
,%3,%2-1)));
2887 /* No scratch register available, use one from LD_REGS (saved in
2888 __tmp_reg__) that doesn't overlap with registers to shift. */
2890 op
[3] = gen_rtx (REG
, QImode
,
2891 ((true_regnum (operands
[0]) - 1) & 15) + 16);
2892 op
[4] = tmp_reg_rtx
;
2896 *len
= 3; /* Includes "mov %3,%4" after the loop. */
2898 strcat (str
, (AS2 (mov
,%4,%3) CR_TAB
2904 else if (GET_CODE (operands
[2]) == MEM
)
2908 op
[3] = op_mov
[0] = tmp_reg_rtx
;
2912 out_movqi_r_mr (insn
, op_mov
, len
);
2914 output_asm_insn (out_movqi_r_mr (insn
, op_mov
, NULL
), op_mov
);
2916 else if (register_operand (operands
[2], QImode
))
2918 if (reg_unused_after (insn
, operands
[2]))
2922 op
[3] = tmp_reg_rtx
;
2924 strcat (str
, (AS2 (mov
,%3,%2) CR_TAB
));
2928 fatal_insn ("bad shift insn:", insn
);
2935 strcat (str
, AS1 (rjmp
,2f
));
2939 *len
+= t_len
+ 2; /* template + dec + brXX */
2942 strcat (str
, "\n1:\t");
2943 strcat (str
, template);
2944 strcat (str
, second_label
? "\n2:\t" : "\n\t");
2945 strcat (str
, use_zero_reg
? AS1 (lsr
,%3) : AS1 (dec
,%3));
2946 strcat (str
, CR_TAB
);
2947 strcat (str
, second_label
? AS1 (brpl
,1b
) : AS1 (brne
,1b
));
2949 strcat (str
, (CR_TAB
AS2 (mov
,%3,%4)));
2950 output_asm_insn (str
, op
);
2955 /* 8bit shift left ((char)x << i) */
2958 ashlqi3_out (insn
, operands
, len
)
2961 int *len
; /* insn length (may be NULL) */
2963 if (GET_CODE (operands
[2]) == CONST_INT
)
2970 switch (INTVAL (operands
[2]))
2974 return AS1 (clr
,%0);
2978 return AS1 (lsl
,%0);
2982 return (AS1 (lsl
,%0) CR_TAB
2987 return (AS1 (lsl
,%0) CR_TAB
2992 if (test_hard_reg_class (LD_REGS
, operands
[0]))
2995 return (AS1 (swap
,%0) CR_TAB
2996 AS2 (andi
,%0,0xf0));
2999 return (AS1 (lsl
,%0) CR_TAB
3005 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3008 return (AS1 (swap
,%0) CR_TAB
3010 AS2 (andi
,%0,0xe0));
3013 return (AS1 (lsl
,%0) CR_TAB
3020 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3023 return (AS1 (swap
,%0) CR_TAB
3026 AS2 (andi
,%0,0xc0));
3029 return (AS1 (lsl
,%0) CR_TAB
3038 return (AS1 (ror
,%0) CR_TAB
3043 else if (CONSTANT_P (operands
[2]))
3044 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3046 out_shift_with_cnt (AS1 (lsl
,%0),
3047 insn
, operands
, len
, 1);
3052 /* 16bit shift left ((short)x << i) */
3055 ashlhi3_out (insn
, operands
, len
)
3060 if (GET_CODE (operands
[2]) == CONST_INT
)
3062 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3063 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3070 switch (INTVAL (operands
[2]))
3073 if (optimize_size
&& scratch
)
3078 return (AS1 (swap
,%A0
) CR_TAB
3079 AS1 (swap
,%B0
) CR_TAB
3080 AS2 (andi
,%B0
,0xf0) CR_TAB
3081 AS2 (eor
,%B0
,%A0
) CR_TAB
3082 AS2 (andi
,%A0
,0xf0) CR_TAB
3088 return (AS1 (swap
,%A0
) CR_TAB
3089 AS1 (swap
,%B0
) CR_TAB
3090 AS2 (ldi
,%3,0xf0) CR_TAB
3091 AS2 (and,%B0
,%3) CR_TAB
3092 AS2 (eor
,%B0
,%A0
) CR_TAB
3093 AS2 (and,%A0
,%3) CR_TAB
3096 break; /* optimize_size ? 6 : 8 */
3100 break; /* scratch ? 5 : 6 */
3104 return (AS1 (lsl
,%A0
) CR_TAB
3105 AS1 (rol
,%B0
) CR_TAB
3106 AS1 (swap
,%A0
) CR_TAB
3107 AS1 (swap
,%B0
) CR_TAB
3108 AS2 (andi
,%B0
,0xf0) CR_TAB
3109 AS2 (eor
,%B0
,%A0
) CR_TAB
3110 AS2 (andi
,%A0
,0xf0) CR_TAB
3116 return (AS1 (lsl
,%A0
) CR_TAB
3117 AS1 (rol
,%B0
) CR_TAB
3118 AS1 (swap
,%A0
) CR_TAB
3119 AS1 (swap
,%B0
) CR_TAB
3120 AS2 (ldi
,%3,0xf0) CR_TAB
3121 AS2 (and,%B0
,%3) CR_TAB
3122 AS2 (eor
,%B0
,%A0
) CR_TAB
3123 AS2 (and,%A0
,%3) CR_TAB
3130 break; /* scratch ? 5 : 6 */
3132 return (AS1 (clr
,__tmp_reg__
) CR_TAB
3133 AS1 (lsr
,%B0
) CR_TAB
3134 AS1 (ror
,%A0
) CR_TAB
3135 AS1 (ror
,__tmp_reg__
) CR_TAB
3136 AS1 (lsr
,%B0
) CR_TAB
3137 AS1 (ror
,%A0
) CR_TAB
3138 AS1 (ror
,__tmp_reg__
) CR_TAB
3139 AS2 (mov
,%B0
,%A0
) CR_TAB
3140 AS2 (mov
,%A0
,__tmp_reg__
));
3144 return (AS1 (lsr
,%B0
) CR_TAB
3145 AS2 (mov
,%B0
,%A0
) CR_TAB
3146 AS1 (clr
,%A0
) CR_TAB
3147 AS1 (ror
,%B0
) CR_TAB
3151 if (true_regnum (operands
[0]) + 1 == true_regnum (operands
[1]))
3152 return *len
= 1, AS1 (clr
,%A0
);
3154 return *len
= 2, (AS2 (mov
,%B0
,%A1
) CR_TAB
3159 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3160 AS1 (clr
,%A0
) CR_TAB
3165 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3166 AS1 (clr
,%A0
) CR_TAB
3167 AS1 (lsl
,%B0
) CR_TAB
3172 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3173 AS1 (clr
,%A0
) CR_TAB
3174 AS1 (lsl
,%B0
) CR_TAB
3175 AS1 (lsl
,%B0
) CR_TAB
3182 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3183 AS1 (clr
,%A0
) CR_TAB
3184 AS1 (swap
,%B0
) CR_TAB
3185 AS2 (andi
,%B0
,0xf0));
3190 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3191 AS1 (clr
,%A0
) CR_TAB
3192 AS1 (swap
,%B0
) CR_TAB
3193 AS2 (ldi
,%3,0xf0) CR_TAB
3197 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3198 AS1 (clr
,%A0
) CR_TAB
3199 AS1 (lsl
,%B0
) CR_TAB
3200 AS1 (lsl
,%B0
) CR_TAB
3201 AS1 (lsl
,%B0
) CR_TAB
3208 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3209 AS1 (clr
,%A0
) CR_TAB
3210 AS1 (swap
,%B0
) CR_TAB
3211 AS1 (lsl
,%B0
) CR_TAB
3212 AS2 (andi
,%B0
,0xe0));
3214 if (AVR_ENHANCED
&& scratch
)
3217 return (AS2 (ldi
,%3,0x20) CR_TAB
3218 AS2 (mul
,%A0
,%3) CR_TAB
3219 AS2 (mov
,%B0
,r0
) CR_TAB
3220 AS1 (clr
,%A0
) CR_TAB
3221 AS1 (clr
,__zero_reg__
));
3223 if (optimize_size
&& scratch
)
3228 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3229 AS1 (clr
,%A0
) CR_TAB
3230 AS1 (swap
,%B0
) CR_TAB
3231 AS1 (lsl
,%B0
) CR_TAB
3232 AS2 (ldi
,%3,0xe0) CR_TAB
3238 return ("set" CR_TAB
3239 AS2 (bld
,r1
,5) CR_TAB
3240 AS2 (mul
,%A0
,r1
) CR_TAB
3241 AS2 (mov
,%B0
,r0
) CR_TAB
3242 AS1 (clr
,%A0
) CR_TAB
3243 AS1 (clr
,__zero_reg__
));
3246 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3247 AS1 (clr
,%A0
) CR_TAB
3248 AS1 (lsl
,%B0
) CR_TAB
3249 AS1 (lsl
,%B0
) CR_TAB
3250 AS1 (lsl
,%B0
) CR_TAB
3251 AS1 (lsl
,%B0
) CR_TAB
3255 if (AVR_ENHANCED
&& ldi_ok
)
3258 return (AS2 (ldi
,%B0
,0x40) CR_TAB
3259 AS2 (mul
,%A0
,%B0
) CR_TAB
3260 AS2 (mov
,%B0
,r0
) CR_TAB
3261 AS1 (clr
,%A0
) CR_TAB
3262 AS1 (clr
,__zero_reg__
));
3264 if (AVR_ENHANCED
&& scratch
)
3267 return (AS2 (ldi
,%3,0x40) CR_TAB
3268 AS2 (mul
,%A0
,%3) CR_TAB
3269 AS2 (mov
,%B0
,r0
) CR_TAB
3270 AS1 (clr
,%A0
) CR_TAB
3271 AS1 (clr
,__zero_reg__
));
3273 if (optimize_size
&& ldi_ok
)
3276 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3277 AS2 (ldi
,%A0
,6) "\n1:\t"
3278 AS1 (lsl
,%B0
) CR_TAB
3279 AS1 (dec
,%A0
) CR_TAB
3282 if (optimize_size
&& scratch
)
3285 return (AS1 (clr
,%B0
) CR_TAB
3286 AS1 (lsr
,%A0
) CR_TAB
3287 AS1 (ror
,%B0
) CR_TAB
3288 AS1 (lsr
,%A0
) CR_TAB
3289 AS1 (ror
,%B0
) CR_TAB
3294 return (AS1 (clr
,%B0
) CR_TAB
3295 AS1 (lsr
,%A0
) CR_TAB
3296 AS1 (ror
,%B0
) CR_TAB
3301 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3303 insn
, operands
, len
, 2);
3308 /* 32bit shift left ((long)x << i) */
3311 ashlsi3_out (insn
, operands
, len
)
3316 if (GET_CODE (operands
[2]) == CONST_INT
)
3324 switch (INTVAL (operands
[2]))
3328 int reg0
= true_regnum (operands
[0]);
3329 int reg1
= true_regnum (operands
[1]);
3332 return (AS2 (mov
,%D0
,%C1
) CR_TAB
3333 AS2 (mov
,%C0
,%B1
) CR_TAB
3334 AS2 (mov
,%B0
,%A1
) CR_TAB
3336 else if (reg0
+ 1 == reg1
)
3339 return AS1 (clr
,%A0
);
3342 return (AS1 (clr
,%A0
) CR_TAB
3343 AS2 (mov
,%B0
,%A1
) CR_TAB
3344 AS2 (mov
,%C0
,%B1
) CR_TAB
3350 int reg0
= true_regnum (operands
[0]);
3351 int reg1
= true_regnum (operands
[1]);
3353 if (AVR_ENHANCED
&& (reg0
+ 2 != reg1
))
3356 return (AS2 (movw
,%C0
,%A1
) CR_TAB
3357 AS1 (clr
,%B0
) CR_TAB
3360 if (reg0
+ 1 >= reg1
)
3361 return (AS2 (mov
,%D0
,%B1
) CR_TAB
3362 AS2 (mov
,%C0
,%A1
) CR_TAB
3363 AS1 (clr
,%B0
) CR_TAB
3365 if (reg0
+ 2 == reg1
)
3368 return (AS1 (clr
,%B0
) CR_TAB
3372 return (AS2 (mov
,%C0
,%A1
) CR_TAB
3373 AS2 (mov
,%D0
,%B1
) CR_TAB
3374 AS1 (clr
,%B0
) CR_TAB
3380 if (true_regnum (operands
[0]) + 3 != true_regnum (operands
[1]))
3381 return (AS2 (mov
,%D0
,%A1
) CR_TAB
3382 AS1 (clr
,%C0
) CR_TAB
3383 AS1 (clr
,%B0
) CR_TAB
3388 return (AS1 (clr
,%C0
) CR_TAB
3389 AS1 (clr
,%B0
) CR_TAB
3395 return (AS1 (clr
,%D0
) CR_TAB
3396 AS1 (lsr
,%A0
) CR_TAB
3397 AS1 (ror
,%D0
) CR_TAB
3398 AS1 (clr
,%C0
) CR_TAB
3399 AS1 (clr
,%B0
) CR_TAB
3404 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3405 AS1 (rol
,%B0
) CR_TAB
3406 AS1 (rol
,%C0
) CR_TAB
3408 insn
, operands
, len
, 4);
3412 /* 8bit arithmetic shift right ((signed char)x >> i) */
3415 ashrqi3_out (insn
, operands
, len
)
3418 int *len
; /* insn length */
3420 if (GET_CODE (operands
[2]) == CONST_INT
)
3427 switch (INTVAL (operands
[2]))
3431 return AS1 (asr
,%0);
3435 return (AS1 (asr
,%0) CR_TAB
3440 return (AS1 (asr
,%0) CR_TAB
3446 return (AS1 (asr
,%0) CR_TAB
3453 return (AS1 (asr
,%0) CR_TAB
3461 return (AS2 (bst
,%0,6) CR_TAB
3463 AS2 (sbc
,%0,%0) CR_TAB
3469 return (AS1 (lsl
,%0) CR_TAB
3473 else if (CONSTANT_P (operands
[2]))
3474 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3476 out_shift_with_cnt (AS1 (asr
,%0),
3477 insn
, operands
, len
, 1);
3482 /* 16bit arithmetic shift right ((signed short)x >> i) */
3485 ashrhi3_out (insn
, operands
, len
)
3490 if (GET_CODE (operands
[2]) == CONST_INT
)
3492 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3493 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3500 switch (INTVAL (operands
[2]))
3504 /* XXX try to optimize this too? */
3509 break; /* scratch ? 5 : 6 */
3511 return (AS2 (mov
,__tmp_reg__
,%A0
) CR_TAB
3512 AS2 (mov
,%A0
,%B0
) CR_TAB
3513 AS1 (lsl
,__tmp_reg__
) CR_TAB
3514 AS1 (rol
,%A0
) CR_TAB
3515 AS2 (sbc
,%B0
,%B0
) CR_TAB
3516 AS1 (lsl
,__tmp_reg__
) CR_TAB
3517 AS1 (rol
,%A0
) CR_TAB
3522 return (AS1 (lsl
,%A0
) CR_TAB
3523 AS2 (mov
,%A0
,%B0
) CR_TAB
3524 AS1 (rol
,%A0
) CR_TAB
3529 int reg0
= true_regnum (operands
[0]);
3530 int reg1
= true_regnum (operands
[1]);
3533 return *len
= 3, (AS2 (mov
,%A0
,%B0
) CR_TAB
3534 AS1 (lsl
,%B0
) CR_TAB
3536 else if (reg0
== reg1
+ 1)
3537 return *len
= 3, (AS1 (clr
,%B0
) CR_TAB
3538 AS2 (sbrc
,%A0
,7) CR_TAB
3541 return *len
= 4, (AS2 (mov
,%A0
,%B1
) CR_TAB
3542 AS1 (clr
,%B0
) CR_TAB
3543 AS2 (sbrc
,%A0
,7) CR_TAB
3549 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3550 AS1 (lsl
,%B0
) CR_TAB
3551 AS2 (sbc
,%B0
,%B0
) CR_TAB
3556 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3557 AS1 (lsl
,%B0
) CR_TAB
3558 AS2 (sbc
,%B0
,%B0
) CR_TAB
3559 AS1 (asr
,%A0
) CR_TAB
3563 if (AVR_ENHANCED
&& ldi_ok
)
3566 return (AS2 (ldi
,%A0
,0x20) CR_TAB
3567 AS2 (muls
,%B0
,%A0
) CR_TAB
3568 AS2 (mov
,%A0
,r1
) CR_TAB
3569 AS2 (sbc
,%B0
,%B0
) CR_TAB
3570 AS1 (clr
,__zero_reg__
));
3572 if (optimize_size
&& scratch
)
3575 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3576 AS1 (lsl
,%B0
) CR_TAB
3577 AS2 (sbc
,%B0
,%B0
) CR_TAB
3578 AS1 (asr
,%A0
) CR_TAB
3579 AS1 (asr
,%A0
) CR_TAB
3583 if (AVR_ENHANCED
&& ldi_ok
)
3586 return (AS2 (ldi
,%A0
,0x10) CR_TAB
3587 AS2 (muls
,%B0
,%A0
) CR_TAB
3588 AS2 (mov
,%A0
,r1
) CR_TAB
3589 AS2 (sbc
,%B0
,%B0
) CR_TAB
3590 AS1 (clr
,__zero_reg__
));
3592 if (optimize_size
&& scratch
)
3595 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3596 AS1 (lsl
,%B0
) CR_TAB
3597 AS2 (sbc
,%B0
,%B0
) CR_TAB
3598 AS1 (asr
,%A0
) CR_TAB
3599 AS1 (asr
,%A0
) CR_TAB
3600 AS1 (asr
,%A0
) CR_TAB
3604 if (AVR_ENHANCED
&& ldi_ok
)
3607 return (AS2 (ldi
,%A0
,0x08) CR_TAB
3608 AS2 (muls
,%B0
,%A0
) CR_TAB
3609 AS2 (mov
,%A0
,r1
) CR_TAB
3610 AS2 (sbc
,%B0
,%B0
) CR_TAB
3611 AS1 (clr
,__zero_reg__
));
3614 break; /* scratch ? 5 : 7 */
3616 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3617 AS1 (lsl
,%B0
) CR_TAB
3618 AS2 (sbc
,%B0
,%B0
) CR_TAB
3619 AS1 (asr
,%A0
) CR_TAB
3620 AS1 (asr
,%A0
) CR_TAB
3621 AS1 (asr
,%A0
) CR_TAB
3622 AS1 (asr
,%A0
) CR_TAB
3627 return (AS1 (lsl
,%B0
) CR_TAB
3628 AS2 (sbc
,%A0
,%A0
) CR_TAB
3629 AS1 (lsl
,%B0
) CR_TAB
3630 AS2 (mov
,%B0
,%A0
) CR_TAB
3634 return *len
= 3, (AS1 (lsl
,%B0
) CR_TAB
3635 AS2 (sbc
,%A0
,%A0
) CR_TAB
3640 out_shift_with_cnt ((AS1 (asr
,%B0
) CR_TAB
3642 insn
, operands
, len
, 2);
3647 /* 32bit arithmetic shift right ((signed long)x >> i) */
3650 ashrsi3_out (insn
, operands
, len
)
3655 if (GET_CODE (operands
[2]) == CONST_INT
)
3663 switch (INTVAL (operands
[2]))
3667 int reg0
= true_regnum (operands
[0]);
3668 int reg1
= true_regnum (operands
[1]);
3671 return (AS2 (mov
,%A0
,%B1
) CR_TAB
3672 AS2 (mov
,%B0
,%C1
) CR_TAB
3673 AS2 (mov
,%C0
,%D1
) CR_TAB
3674 AS1 (clr
,%D0
) CR_TAB
3675 AS2 (sbrc
,%C0
,7) CR_TAB
3677 else if (reg0
== reg1
+ 1)
3680 return (AS1 (clr
,%D0
) CR_TAB
3681 AS2 (sbrc
,%C0
,7) CR_TAB
3685 return (AS1 (clr
,%D0
) CR_TAB
3686 AS2 (sbrc
,%D1
,7) CR_TAB
3687 AS1 (dec
,%D0
) CR_TAB
3688 AS2 (mov
,%C0
,%D1
) CR_TAB
3689 AS2 (mov
,%B0
,%C1
) CR_TAB
3695 int reg0
= true_regnum (operands
[0]);
3696 int reg1
= true_regnum (operands
[1]);
3698 if (AVR_ENHANCED
&& (reg0
!= reg1
+ 2))
3701 return (AS2 (movw
,%A0
,%C1
) CR_TAB
3702 AS1 (clr
,%D0
) CR_TAB
3703 AS2 (sbrc
,%B0
,7) CR_TAB
3704 AS1 (com
,%D0
) CR_TAB
3707 if (reg0
<= reg1
+ 1)
3708 return (AS2 (mov
,%A0
,%C1
) CR_TAB
3709 AS2 (mov
,%B0
,%D1
) CR_TAB
3710 AS1 (clr
,%D0
) CR_TAB
3711 AS2 (sbrc
,%B0
,7) CR_TAB
3712 AS1 (com
,%D0
) CR_TAB
3714 else if (reg0
== reg1
+ 2)
3715 return *len
= 4, (AS1 (clr
,%D0
) CR_TAB
3716 AS2 (sbrc
,%B0
,7) CR_TAB
3717 AS1 (com
,%D0
) CR_TAB
3720 return (AS2 (mov
,%B0
,%D1
) CR_TAB
3721 AS2 (mov
,%A0
,%C1
) CR_TAB
3722 AS1 (clr
,%D0
) CR_TAB
3723 AS2 (sbrc
,%B0
,7) CR_TAB
3724 AS1 (com
,%D0
) CR_TAB
3729 if (true_regnum (operands
[0]) != true_regnum (operands
[1]) + 3)
3730 return *len
= 6, (AS2 (mov
,%A0
,%D1
) CR_TAB
3731 AS1 (clr
,%D0
) CR_TAB
3732 AS2 (sbrc
,%A0
,7) CR_TAB
3733 AS1 (com
,%D0
) CR_TAB
3734 AS2 (mov
,%B0
,%D0
) CR_TAB
3737 return *len
= 5, (AS1 (clr
,%D0
) CR_TAB
3738 AS2 (sbrc
,%A0
,7) CR_TAB
3739 AS1 (com
,%D0
) CR_TAB
3740 AS2 (mov
,%B0
,%D0
) CR_TAB
3745 return *len
= 4, (AS1 (lsl
,%D0
) CR_TAB
3746 AS2 (sbc
,%A0
,%A0
) CR_TAB
3747 AS2 (mov
,%B0
,%A0
) CR_TAB
3748 AS2 (movw
,%C0
,%A0
));
3750 return *len
= 5, (AS1 (lsl
,%D0
) CR_TAB
3751 AS2 (sbc
,%A0
,%A0
) CR_TAB
3752 AS2 (mov
,%B0
,%A0
) CR_TAB
3753 AS2 (mov
,%C0
,%A0
) CR_TAB
3758 out_shift_with_cnt ((AS1 (asr
,%D0
) CR_TAB
3759 AS1 (ror
,%C0
) CR_TAB
3760 AS1 (ror
,%B0
) CR_TAB
3762 insn
, operands
, len
, 4);
3766 /* 8bit logic shift right ((unsigned char)x >> i) */
3769 lshrqi3_out (insn
, operands
, len
)
3774 if (GET_CODE (operands
[2]) == CONST_INT
)
3781 switch (INTVAL (operands
[2]))
3785 return AS1 (clr
,%0);
3789 return AS1 (lsr
,%0);
3793 return (AS1 (lsr
,%0) CR_TAB
3797 return (AS1 (lsr
,%0) CR_TAB
3802 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3805 return (AS1 (swap
,%0) CR_TAB
3806 AS2 (andi
,%0,0x0f));
3809 return (AS1 (lsr
,%0) CR_TAB
3815 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3818 return (AS1 (swap
,%0) CR_TAB
3823 return (AS1 (lsr
,%0) CR_TAB
3830 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3833 return (AS1 (swap
,%0) CR_TAB
3839 return (AS1 (lsr
,%0) CR_TAB
3848 return (AS1 (rol
,%0) CR_TAB
3853 else if (CONSTANT_P (operands
[2]))
3854 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3856 out_shift_with_cnt (AS1 (lsr
,%0),
3857 insn
, operands
, len
, 1);
3861 /* 16bit logic shift right ((unsigned short)x >> i) */
3864 lshrhi3_out (insn
, operands
, len
)
3869 if (GET_CODE (operands
[2]) == CONST_INT
)
3871 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3872 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3879 switch (INTVAL (operands
[2]))
3882 if (optimize_size
&& scratch
)
3887 return (AS1 (swap
,%B0
) CR_TAB
3888 AS1 (swap
,%A0
) CR_TAB
3889 AS2 (andi
,%A0
,0x0f) CR_TAB
3890 AS2 (eor
,%A0
,%B0
) CR_TAB
3891 AS2 (andi
,%B0
,0x0f) CR_TAB
3897 return (AS1 (swap
,%B0
) CR_TAB
3898 AS1 (swap
,%A0
) CR_TAB
3899 AS2 (ldi
,%3,0x0f) CR_TAB
3900 AS2 (and,%A0
,%3) CR_TAB
3901 AS2 (eor
,%A0
,%B0
) CR_TAB
3902 AS2 (and,%B0
,%3) CR_TAB
3905 break; /* optimize_size ? 6 : 8 */
3909 break; /* scratch ? 5 : 6 */
3913 return (AS1 (lsr
,%B0
) CR_TAB
3914 AS1 (ror
,%A0
) CR_TAB
3915 AS1 (swap
,%B0
) CR_TAB
3916 AS1 (swap
,%A0
) CR_TAB
3917 AS2 (andi
,%A0
,0x0f) CR_TAB
3918 AS2 (eor
,%A0
,%B0
) CR_TAB
3919 AS2 (andi
,%B0
,0x0f) CR_TAB
3925 return (AS1 (lsr
,%B0
) CR_TAB
3926 AS1 (ror
,%A0
) CR_TAB
3927 AS1 (swap
,%B0
) CR_TAB
3928 AS1 (swap
,%A0
) CR_TAB
3929 AS2 (ldi
,%3,0x0f) CR_TAB
3930 AS2 (and,%A0
,%3) CR_TAB
3931 AS2 (eor
,%A0
,%B0
) CR_TAB
3932 AS2 (and,%B0
,%3) CR_TAB
3939 break; /* scratch ? 5 : 6 */
3941 return (AS1 (clr
,__tmp_reg__
) CR_TAB
3942 AS1 (lsl
,%A0
) CR_TAB
3943 AS1 (rol
,%B0
) CR_TAB
3944 AS1 (rol
,__tmp_reg__
) CR_TAB
3945 AS1 (lsl
,%A0
) CR_TAB
3946 AS1 (rol
,%B0
) CR_TAB
3947 AS1 (rol
,__tmp_reg__
) CR_TAB
3948 AS2 (mov
,%A0
,%B0
) CR_TAB
3949 AS2 (mov
,%B0
,__tmp_reg__
));
3953 return (AS1 (lsl
,%A0
) CR_TAB
3954 AS2 (mov
,%A0
,%B0
) CR_TAB
3955 AS1 (rol
,%A0
) CR_TAB
3956 AS2 (sbc
,%B0
,%B0
) CR_TAB
3960 if (true_regnum (operands
[0]) != true_regnum (operands
[1]) + 1)
3961 return *len
= 2, (AS2 (mov
,%A0
,%B1
) CR_TAB
3964 return *len
= 1, AS1 (clr
,%B0
);
3968 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3969 AS1 (clr
,%B0
) CR_TAB
3974 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3975 AS1 (clr
,%B0
) CR_TAB
3976 AS1 (lsr
,%A0
) CR_TAB
3981 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3982 AS1 (clr
,%B0
) CR_TAB
3983 AS1 (lsr
,%A0
) CR_TAB
3984 AS1 (lsr
,%A0
) CR_TAB
3991 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3992 AS1 (clr
,%B0
) CR_TAB
3993 AS1 (swap
,%A0
) CR_TAB
3994 AS2 (andi
,%A0
,0x0f));
3999 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4000 AS1 (clr
,%B0
) CR_TAB
4001 AS1 (swap
,%A0
) CR_TAB
4002 AS2 (ldi
,%3,0x0f) CR_TAB
4006 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4007 AS1 (clr
,%B0
) CR_TAB
4008 AS1 (lsr
,%A0
) CR_TAB
4009 AS1 (lsr
,%A0
) CR_TAB
4010 AS1 (lsr
,%A0
) CR_TAB
4017 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4018 AS1 (clr
,%B0
) CR_TAB
4019 AS1 (swap
,%A0
) CR_TAB
4020 AS1 (lsr
,%A0
) CR_TAB
4021 AS2 (andi
,%A0
,0x07));
4023 if (AVR_ENHANCED
&& scratch
)
4026 return (AS2 (ldi
,%3,0x08) CR_TAB
4027 AS2 (mul
,%B0
,%3) CR_TAB
4028 AS2 (mov
,%A0
,r1
) CR_TAB
4029 AS1 (clr
,%B0
) CR_TAB
4030 AS1 (clr
,__zero_reg__
));
4032 if (optimize_size
&& scratch
)
4037 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4038 AS1 (clr
,%B0
) CR_TAB
4039 AS1 (swap
,%A0
) CR_TAB
4040 AS1 (lsr
,%A0
) CR_TAB
4041 AS2 (ldi
,%3,0x07) CR_TAB
4047 return ("set" CR_TAB
4048 AS2 (bld
,r1
,3) CR_TAB
4049 AS2 (mul
,%B0
,r1
) CR_TAB
4050 AS2 (mov
,%A0
,r1
) CR_TAB
4051 AS1 (clr
,%B0
) CR_TAB
4052 AS1 (clr
,__zero_reg__
));
4055 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4056 AS1 (clr
,%B0
) CR_TAB
4057 AS1 (lsr
,%A0
) CR_TAB
4058 AS1 (lsr
,%A0
) CR_TAB
4059 AS1 (lsr
,%A0
) CR_TAB
4060 AS1 (lsr
,%A0
) CR_TAB
4064 if (AVR_ENHANCED
&& ldi_ok
)
4067 return (AS2 (ldi
,%A0
,0x04) CR_TAB
4068 AS2 (mul
,%B0
,%A0
) CR_TAB
4069 AS2 (mov
,%A0
,r1
) CR_TAB
4070 AS1 (clr
,%B0
) CR_TAB
4071 AS1 (clr
,__zero_reg__
));
4073 if (AVR_ENHANCED
&& scratch
)
4076 return (AS2 (ldi
,%3,0x04) CR_TAB
4077 AS2 (mul
,%B0
,%3) CR_TAB
4078 AS2 (mov
,%A0
,r1
) CR_TAB
4079 AS1 (clr
,%B0
) CR_TAB
4080 AS1 (clr
,__zero_reg__
));
4082 if (optimize_size
&& ldi_ok
)
4085 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4086 AS2 (ldi
,%B0
,6) "\n1:\t"
4087 AS1 (lsr
,%A0
) CR_TAB
4088 AS1 (dec
,%B0
) CR_TAB
4091 if (optimize_size
&& scratch
)
4094 return (AS1 (clr
,%A0
) CR_TAB
4095 AS1 (lsl
,%B0
) CR_TAB
4096 AS1 (rol
,%A0
) CR_TAB
4097 AS1 (lsl
,%B0
) CR_TAB
4098 AS1 (rol
,%A0
) CR_TAB
4103 return (AS1 (clr
,%A0
) CR_TAB
4104 AS1 (lsl
,%B0
) CR_TAB
4105 AS1 (rol
,%A0
) CR_TAB
4110 out_shift_with_cnt ((AS1 (lsr
,%B0
) CR_TAB
4112 insn
, operands
, len
, 2);
4116 /* 32bit logic shift right ((unsigned int)x >> i) */
4119 lshrsi3_out (insn
, operands
, len
)
4124 if (GET_CODE (operands
[2]) == CONST_INT
)
4132 switch (INTVAL (operands
[2]))
4136 int reg0
= true_regnum (operands
[0]);
4137 int reg1
= true_regnum (operands
[1]);
4140 return (AS2 (mov
,%A0
,%B1
) CR_TAB
4141 AS2 (mov
,%B0
,%C1
) CR_TAB
4142 AS2 (mov
,%C0
,%D1
) CR_TAB
4144 else if (reg0
== reg1
+ 1)
4145 return *len
= 1, AS1 (clr
,%D0
);
4147 return (AS1 (clr
,%D0
) CR_TAB
4148 AS2 (mov
,%C0
,%D1
) CR_TAB
4149 AS2 (mov
,%B0
,%C1
) CR_TAB
4155 int reg0
= true_regnum (operands
[0]);
4156 int reg1
= true_regnum (operands
[1]);
4158 if (AVR_ENHANCED
&& (reg0
!= reg1
+ 2))
4161 return (AS2 (movw
,%A0
,%C1
) CR_TAB
4162 AS1 (clr
,%C0
) CR_TAB
4165 if (reg0
<= reg1
+ 1)
4166 return (AS2 (mov
,%A0
,%C1
) CR_TAB
4167 AS2 (mov
,%B0
,%D1
) CR_TAB
4168 AS1 (clr
,%C0
) CR_TAB
4170 else if (reg0
== reg1
+ 2)
4171 return *len
= 2, (AS1 (clr
,%C0
) CR_TAB
4174 return (AS2 (mov
,%B0
,%D1
) CR_TAB
4175 AS2 (mov
,%A0
,%C1
) CR_TAB
4176 AS1 (clr
,%C0
) CR_TAB
4181 if (true_regnum (operands
[0]) != true_regnum (operands
[1]) + 3)
4182 return *len
= 4, (AS2 (mov
,%A0
,%D1
) CR_TAB
4183 AS1 (clr
,%B0
) CR_TAB
4184 AS1 (clr
,%C0
) CR_TAB
4187 return *len
= 3, (AS1 (clr
,%B0
) CR_TAB
4188 AS1 (clr
,%C0
) CR_TAB
4193 return (AS1 (clr
,%A0
) CR_TAB
4194 AS2 (sbrc
,%D0
,7) CR_TAB
4195 AS1 (inc
,%A0
) CR_TAB
4196 AS1 (clr
,%B0
) CR_TAB
4197 AS1 (clr
,%C0
) CR_TAB
4202 out_shift_with_cnt ((AS1 (lsr
,%D0
) CR_TAB
4203 AS1 (ror
,%C0
) CR_TAB
4204 AS1 (ror
,%B0
) CR_TAB
4206 insn
, operands
, len
, 4);
4210 /* Modifies the length assigned to instruction INSN
4211 LEN is the initially computed length of the insn. */
4214 adjust_insn_length (insn
, len
)
4218 rtx patt
= PATTERN (insn
);
4221 if (GET_CODE (patt
) == SET
)
4224 op
[1] = SET_SRC (patt
);
4225 op
[0] = SET_DEST (patt
);
4226 if (general_operand (op
[1], VOIDmode
)
4227 && general_operand (op
[0], VOIDmode
))
4229 switch (GET_MODE (op
[0]))
4232 output_movqi (insn
, op
, &len
);
4235 output_movhi (insn
, op
, &len
);
4239 output_movsisf (insn
, op
, &len
);
4245 else if (op
[0] == cc0_rtx
&& REG_P (op
[1]))
4247 switch (GET_MODE (op
[1]))
4249 case HImode
: out_tsthi (insn
,&len
); break;
4250 case SImode
: out_tstsi (insn
,&len
); break;
4254 else if (GET_CODE (op
[1]) == AND
)
4256 if (GET_CODE (XEXP (op
[1],1)) == CONST_INT
)
4258 HOST_WIDE_INT mask
= INTVAL (XEXP (op
[1],1));
4259 if (GET_MODE (op
[1]) == SImode
)
4260 len
= (((mask
& 0xff) != 0xff)
4261 + ((mask
& 0xff00) != 0xff00)
4262 + ((mask
& 0xff0000L
) != 0xff0000L
)
4263 + ((mask
& 0xff000000L
) != 0xff000000L
));
4264 else if (GET_MODE (op
[1]) == HImode
)
4265 len
= (((mask
& 0xff) != 0xff)
4266 + ((mask
& 0xff00) != 0xff00));
4269 else if (GET_CODE (op
[1]) == IOR
)
4271 if (GET_CODE (XEXP (op
[1],1)) == CONST_INT
)
4273 HOST_WIDE_INT mask
= INTVAL (XEXP (op
[1],1));
4274 if (GET_MODE (op
[1]) == SImode
)
4275 len
= (((mask
& 0xff) != 0)
4276 + ((mask
& 0xff00) != 0)
4277 + ((mask
& 0xff0000L
) != 0)
4278 + ((mask
& 0xff000000L
) != 0));
4279 else if (GET_MODE (op
[1]) == HImode
)
4280 len
= (((mask
& 0xff) != 0)
4281 + ((mask
& 0xff00) != 0));
4285 set
= single_set (insn
);
4290 op
[1] = SET_SRC (set
);
4291 op
[0] = SET_DEST (set
);
4293 if (GET_CODE (patt
) == PARALLEL
4294 && general_operand (op
[1], VOIDmode
)
4295 && general_operand (op
[0], VOIDmode
))
4297 if (XVECLEN (patt
, 0) == 2)
4298 op
[2] = XVECEXP (patt
, 0, 1);
4300 switch (GET_MODE (op
[0]))
4306 output_reload_inhi (insn
, op
, &len
);
4310 output_reload_insisf (insn
, op
, &len
);
4316 else if (GET_CODE (op
[1]) == ASHIFT
4317 || GET_CODE (op
[1]) == ASHIFTRT
4318 || GET_CODE (op
[1]) == LSHIFTRT
)
4322 ops
[1] = XEXP (op
[1],0);
4323 ops
[2] = XEXP (op
[1],1);
4324 switch (GET_CODE (op
[1]))
4327 switch (GET_MODE (op
[0]))
4329 case QImode
: ashlqi3_out (insn
,ops
,&len
); break;
4330 case HImode
: ashlhi3_out (insn
,ops
,&len
); break;
4331 case SImode
: ashlsi3_out (insn
,ops
,&len
); break;
4336 switch (GET_MODE (op
[0]))
4338 case QImode
: ashrqi3_out (insn
,ops
,&len
); break;
4339 case HImode
: ashrhi3_out (insn
,ops
,&len
); break;
4340 case SImode
: ashrsi3_out (insn
,ops
,&len
); break;
4345 switch (GET_MODE (op
[0]))
4347 case QImode
: lshrqi3_out (insn
,ops
,&len
); break;
4348 case HImode
: lshrhi3_out (insn
,ops
,&len
); break;
4349 case SImode
: lshrsi3_out (insn
,ops
,&len
); break;
4361 /* Return non-zero if register REG dead after INSN */
4364 reg_unused_after (insn
, reg
)
4368 return (dead_or_set_p (insn
, reg
)
4369 || (REG_P(reg
) && _reg_unused_after (insn
, reg
)));
4372 /* Return non-zero if REG is not used after INSN.
4373 We assume REG is a reload reg, and therefore does
4374 not live past labels. It may live past calls or jumps though. */
4377 _reg_unused_after (insn
, reg
)
4384 /* If the reg is set by this instruction, then it is safe for our
4385 case. Disregard the case where this is a store to memory, since
4386 we are checking a register used in the store address. */
4387 set
= single_set (insn
);
4388 if (set
&& GET_CODE (SET_DEST (set
)) != MEM
4389 && reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4392 while ((insn
= NEXT_INSN (insn
)))
4394 code
= GET_CODE (insn
);
4397 /* If this is a label that existed before reload, then the register
4398 if dead here. However, if this is a label added by reorg, then
4399 the register may still be live here. We can't tell the difference,
4400 so we just ignore labels completely. */
4401 if (code
== CODE_LABEL
)
4406 if (code
== JUMP_INSN
)
4409 /* If this is a sequence, we must handle them all at once.
4410 We could have for instance a call that sets the target register,
4411 and an insn in a delay slot that uses the register. In this case,
4412 we must return 0. */
4413 else if (code
== INSN
&& GET_CODE (PATTERN (insn
)) == SEQUENCE
)
4418 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
4420 rtx this_insn
= XVECEXP (PATTERN (insn
), 0, i
);
4421 rtx set
= single_set (this_insn
);
4423 if (GET_CODE (this_insn
) == CALL_INSN
)
4425 else if (GET_CODE (this_insn
) == JUMP_INSN
)
4427 if (INSN_ANNULLED_BRANCH_P (this_insn
))
4432 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4434 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4436 if (GET_CODE (SET_DEST (set
)) != MEM
)
4442 && reg_overlap_mentioned_p (reg
, PATTERN (this_insn
)))
4447 else if (code
== JUMP_INSN
)
4451 if (code
== CALL_INSN
)
4454 for (tem
= CALL_INSN_FUNCTION_USAGE (insn
); tem
; tem
= XEXP (tem
, 1))
4455 if (GET_CODE (XEXP (tem
, 0)) == USE
4456 && REG_P (XEXP (XEXP (tem
, 0), 0))
4457 && reg_overlap_mentioned_p (reg
, XEXP (XEXP (tem
, 0), 0)))
4459 if (call_used_regs
[REGNO (reg
)])
4463 if (GET_RTX_CLASS (code
) == 'i')
4465 rtx set
= single_set (insn
);
4467 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4469 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4470 return GET_CODE (SET_DEST (set
)) != MEM
;
4471 if (set
== 0 && reg_overlap_mentioned_p (reg
, PATTERN (insn
)))
4478 /* Target hook for assembling integer objects. The AVR version needs
4479 special handling for references to certain labels. */
4482 avr_assemble_integer (x
, size
, aligned_p
)
4487 if (size
== POINTER_SIZE
/ BITS_PER_UNIT
&& aligned_p
4488 && ((GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_FLAG (x
))
4489 || GET_CODE (x
) == LABEL_REF
))
4491 fputs ("\t.word\tpm(", asm_out_file
);
4492 output_addr_const (asm_out_file
, x
);
4493 fputs (")\n", asm_out_file
);
4496 return default_assemble_integer (x
, size
, aligned_p
);
4499 /* Sets section name for declaration DECL */
4502 unique_section (decl
, reloc
)
4504 int reloc ATTRIBUTE_UNUSED
;
4507 const char *name
, *prefix
;
4509 name
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
));
4510 /* Strip off any encoding in name. */
4511 STRIP_NAME_ENCODING (name
, name
);
4513 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4515 if (flag_function_sections
)
4523 if (flag_function_sections
)
4525 len
= strlen (name
) + strlen (prefix
);
4526 string
= alloca (len
+ 1);
4527 sprintf (string
, "%s%s", prefix
, name
);
4528 DECL_SECTION_NAME (decl
) = build_string (len
, string
);
4533 /* The routine used to output NUL terminated strings. We use a special
4534 version of this for most svr4 targets because doing so makes the
4535 generated assembly code more compact (and thus faster to assemble)
4536 as well as more readable, especially for targets like the i386
4537 (where the only alternative is to output character sequences as
4538 comma separated lists of numbers). */
4541 gas_output_limited_string(file
, str
)
4545 const unsigned char *_limited_str
= (unsigned char *) str
;
4547 fprintf (file
, "%s\"", STRING_ASM_OP
);
4548 for (; (ch
= *_limited_str
); _limited_str
++)
4551 switch (escape
= ESCAPES
[ch
])
4557 fprintf (file
, "\\%03o", ch
);
4561 putc (escape
, file
);
4565 fprintf (file
, "\"\n");
4568 /* The routine used to output sequences of byte values. We use a special
4569 version of this for most svr4 targets because doing so makes the
4570 generated assembly code more compact (and thus faster to assemble)
4571 as well as more readable. Note that if we find subparts of the
4572 character sequence which end with NUL (and which are shorter than
4573 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4576 gas_output_ascii(file
, str
, length
)
4581 const unsigned char *_ascii_bytes
= (const unsigned char *) str
;
4582 const unsigned char *limit
= _ascii_bytes
+ length
;
4583 unsigned bytes_in_chunk
= 0;
4584 for (; _ascii_bytes
< limit
; _ascii_bytes
++)
4586 const unsigned char *p
;
4587 if (bytes_in_chunk
>= 60)
4589 fprintf (file
, "\"\n");
4592 for (p
= _ascii_bytes
; p
< limit
&& *p
!= '\0'; p
++)
4594 if (p
< limit
&& (p
- _ascii_bytes
) <= (signed)STRING_LIMIT
)
4596 if (bytes_in_chunk
> 0)
4598 fprintf (file
, "\"\n");
4601 gas_output_limited_string (file
, (char*)_ascii_bytes
);
4608 if (bytes_in_chunk
== 0)
4609 fprintf (file
, "\t.ascii\t\"");
4610 switch (escape
= ESCAPES
[ch
= *_ascii_bytes
])
4617 fprintf (file
, "\\%03o", ch
);
4618 bytes_in_chunk
+= 4;
4622 putc (escape
, file
);
4623 bytes_in_chunk
+= 2;
4628 if (bytes_in_chunk
> 0)
4629 fprintf (file
, "\"\n");
4632 /* Return value is nonzero if pseudos that have been
4633 assigned to registers of class CLASS would likely be spilled
4634 because registers of CLASS are needed for spill registers. */
4637 class_likely_spilled_p (c
)
4640 return (c
!= ALL_REGS
&& c
!= ADDW_REGS
);
4643 /* Valid attributes:
4644 progmem - put data to program memory;
4645 signal - make a function to be hardware interrupt. After function
4646 prologue interrupts are disabled;
4647 interrupt - make a function to be hardware interrupt. After function
4648 prologue interrupts are enabled;
4649 naked - don't generate function prologue/epilogue and `ret' command.
4651 Only `progmem' attribute valid for type. */
4653 const struct attribute_spec avr_attribute_table
[] =
4655 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4656 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute
},
4657 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4658 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4659 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4660 { NULL
, 0, 0, false, false, false, NULL
}
4663 /* Handle a "progmem" attribute; arguments as in
4664 struct attribute_spec.handler. */
4666 avr_handle_progmem_attribute (node
, name
, args
, flags
, no_add_attrs
)
4669 tree args ATTRIBUTE_UNUSED
;
4670 int flags ATTRIBUTE_UNUSED
;
4675 if (TREE_STATIC (*node
) || DECL_EXTERNAL (*node
))
4677 if (DECL_INITIAL (*node
) == NULL_TREE
&& !DECL_EXTERNAL (*node
))
4679 warning ("only initialized variables can be placed into "
4680 "program memory area");
4681 *no_add_attrs
= true;
4686 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name
));
4687 *no_add_attrs
= true;
4694 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4695 struct attribute_spec.handler. */
4697 avr_handle_fndecl_attribute (node
, name
, args
, flags
, no_add_attrs
)
4700 tree args ATTRIBUTE_UNUSED
;
4701 int flags ATTRIBUTE_UNUSED
;
4704 if (TREE_CODE (*node
) != FUNCTION_DECL
)
4706 warning ("`%s' attribute only applies to functions",
4707 IDENTIFIER_POINTER (name
));
4708 *no_add_attrs
= true;
4714 /* Look for attribute `progmem' in DECL
4715 if found return 1, otherwise 0. */
4718 avr_progmem_p (decl
)
4723 if (TREE_CODE (decl
) != VAR_DECL
)
4727 != lookup_attribute ("progmem", DECL_ATTRIBUTES (decl
)))
4733 while (TREE_CODE (a
) == ARRAY_TYPE
);
4735 if (a
== error_mark_node
)
4738 if (NULL_TREE
!= lookup_attribute ("progmem", TYPE_ATTRIBUTES (a
)))
4744 /* Encode section information about tree DECL */
4747 encode_section_info (decl
, first
)
4751 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4752 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl
), 0)) = 1;
4754 && (TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
4755 && TREE_CODE (decl
) == VAR_DECL
4756 && avr_progmem_p (decl
))
4758 static const char *const dsec
= ".progmem.data";
4759 DECL_SECTION_NAME (decl
) = build_string (strlen (dsec
), dsec
);
4760 TREE_READONLY (decl
) = 1;
4764 /* Outputs to the stdio stream FILE some
4765 appropriate text to go at the start of an assembler file. */
4768 asm_file_start (file
)
4771 output_file_directive (file
, main_input_filename
);
4772 fprintf (file
, "\t.arch %s\n", avr_mcu_name
);
4773 fputs ("__SREG__ = 0x3f\n"
4775 "__SP_L__ = 0x3d\n", file
);
4777 fputs ("__tmp_reg__ = 0\n"
4778 "__zero_reg__ = 1\n"
4779 "_PC_ = 2\n", file
);
4781 commands_in_file
= 0;
4782 commands_in_prologues
= 0;
4783 commands_in_epilogues
= 0;
4786 /* Outputs to the stdio stream FILE some
4787 appropriate text to go at the end of an assembler file. */
4794 "/* File %s: code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4795 main_input_filename
,
4798 commands_in_file
- commands_in_prologues
- commands_in_epilogues
,
4799 commands_in_prologues
, commands_in_epilogues
);
4802 /* Choose the order in which to allocate hard registers for
4803 pseudo-registers local to a basic block.
4805 Store the desired register order in the array `reg_alloc_order'.
4806 Element 0 should be the register to allocate first; element 1, the
4807 next register; and so on. */
4810 order_regs_for_local_alloc ()
4813 static const int order_0
[] = {
4821 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4825 static const int order_1
[] = {
4833 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4837 static const int order_2
[] = {
4846 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4851 const int *order
= (TARGET_ORDER_1
? order_1
:
4852 TARGET_ORDER_2
? order_2
:
4854 for (i
=0; i
< ARRAY_SIZE (order_0
); ++i
)
4855 reg_alloc_order
[i
] = order
[i
];
4858 /* Calculate the cost of X code of the expression in which it is contained,
4859 found in OUTER_CODE */
4862 default_rtx_costs (X
, code
, outer_code
)
4865 enum rtx_code outer_code
;
4872 cost
= 2 * GET_MODE_SIZE (GET_MODE (X
));
4875 if (outer_code
!= SET
)
4877 if (GET_CODE (XEXP (X
,0)) == SYMBOL_REF
)
4878 cost
+= 2 * GET_MODE_SIZE (GET_MODE (X
));
4880 cost
+= GET_MODE_SIZE (GET_MODE (X
));
4886 if (outer_code
== SET
)
4887 cost
= GET_MODE_SIZE (GET_MODE (X
));
4889 cost
= -GET_MODE_SIZE (GET_MODE (X
));
4892 if (outer_code
== SET
)
4893 cost
= GET_MODE_SIZE (GET_MODE (X
));
4899 if (outer_code
== SET
)
4901 if (X
== stack_pointer_rtx
)
4903 else if (GET_CODE (XEXP (X
,1)) == CONST_INT
)
4904 cost
= (INTVAL (XEXP (X
,1)) <= 63 ? 1 :
4905 GET_MODE_SIZE (GET_MODE (X
)));
4907 cost
= GET_MODE_SIZE (GET_MODE (X
));
4911 if (GET_CODE (XEXP (X
,1)) == CONST_INT
)
4912 cost
= GET_MODE_SIZE (GET_MODE (XEXP (X
,0)));
4920 /* Calculate the cost of a memory address */
4923 avr_address_cost (x
)
4926 if (GET_CODE (x
) == PLUS
4927 && GET_CODE (XEXP (x
,1)) == CONST_INT
4928 && (REG_P (XEXP (x
,0)) || GET_CODE (XEXP (x
,0)) == SUBREG
)
4929 && INTVAL (XEXP (x
,1)) >= 61)
4931 if (CONSTANT_ADDRESS_P (x
))
4933 if (avr_io_address_p (x
, 1))
4940 /* EXTRA_CONSTRAINT helper */
4943 extra_constraint (x
, c
)
4948 && GET_CODE (x
) == MEM
4949 && GET_CODE (XEXP (x
,0)) == PLUS
)
4951 if (TARGET_ALL_DEBUG
)
4953 fprintf (stderr
, ("extra_constraint:\n"
4954 "reload_completed: %d\n"
4955 "reload_in_progress: %d\n"),
4956 reload_completed
, reload_in_progress
);
4959 if (GET_CODE (x
) == MEM
4960 && GET_CODE (XEXP (x
,0)) == PLUS
4961 && REG_P (XEXP (XEXP (x
,0), 0))
4962 && GET_CODE (XEXP (XEXP (x
,0), 1)) == CONST_INT
4963 && (INTVAL (XEXP (XEXP (x
,0), 1))
4964 <= MAX_LD_OFFSET (GET_MODE (x
))))
4966 rtx xx
= XEXP (XEXP (x
,0), 0);
4967 int regno
= REGNO (xx
);
4968 if (TARGET_ALL_DEBUG
)
4970 fprintf (stderr
, ("extra_constraint:\n"
4971 "reload_completed: %d\n"
4972 "reload_in_progress: %d\n"),
4973 reload_completed
, reload_in_progress
);
4976 if (regno
>= FIRST_PSEUDO_REGISTER
)
4977 return 1; /* allocate pseudos */
4978 else if (regno
== REG_Z
|| regno
== REG_Y
)
4979 return 1; /* strictly check */
4980 else if (xx
== frame_pointer_rtx
4981 || xx
== arg_pointer_rtx
)
4982 return 1; /* XXX frame & arg pointer checks */
4988 /* Convert condition code CONDITION to the valid AVR condition code */
4991 avr_normalize_condition (condition
)
5009 /* This fnction optimizes conditional jumps */
5012 machine_dependent_reorg (first_insn
)
5017 for (insn
= first_insn
; insn
; insn
= NEXT_INSN (insn
))
5019 if (! (GET_CODE (insn
) == INSN
5020 || GET_CODE (insn
) == CALL_INSN
5021 || GET_CODE (insn
) == JUMP_INSN
)
5022 || !single_set (insn
))
5025 pattern
= PATTERN (insn
);
5027 if (GET_CODE (pattern
) == PARALLEL
)
5028 pattern
= XVECEXP (pattern
, 0, 0);
5029 if (GET_CODE (pattern
) == SET
5030 && SET_DEST (pattern
) == cc0_rtx
5031 && compare_diff_p (insn
))
5033 if (GET_CODE (SET_SRC (pattern
)) == COMPARE
)
5035 /* Now we work under compare insn */
5037 pattern
= SET_SRC (pattern
);
5038 if (true_regnum (XEXP (pattern
,0)) >= 0
5039 && true_regnum (XEXP (pattern
,1)) >= 0 )
5041 rtx x
= XEXP (pattern
,0);
5042 rtx next
= next_real_insn (insn
);
5043 rtx pat
= PATTERN (next
);
5044 rtx src
= SET_SRC (pat
);
5045 rtx t
= XEXP (src
,0);
5046 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
5047 XEXP (pattern
,0) = XEXP (pattern
,1);
5048 XEXP (pattern
,1) = x
;
5049 INSN_CODE (next
) = -1;
5051 else if (true_regnum (XEXP (pattern
,0)) >= 0
5052 && GET_CODE (XEXP (pattern
,1)) == CONST_INT
)
5054 rtx x
= XEXP (pattern
,1);
5055 rtx next
= next_real_insn (insn
);
5056 rtx pat
= PATTERN (next
);
5057 rtx src
= SET_SRC (pat
);
5058 rtx t
= XEXP (src
,0);
5060 if (avr_simplify_comparision_p (GET_MODE (XEXP (pattern
,0)),
5063 XEXP (pattern
,1) = GEN_INT (INTVAL (x
)+1);
5064 PUT_CODE (t
, avr_normalize_condition (GET_CODE (t
)));
5065 INSN_CODE (next
) = -1;
5066 INSN_CODE (insn
) = -1;
5070 else if (true_regnum (SET_SRC (pattern
)) >= 0)
5072 /* This is a tst insn */
5073 rtx next
= next_real_insn (insn
);
5074 rtx pat
= PATTERN (next
);
5075 rtx src
= SET_SRC (pat
);
5076 rtx t
= XEXP (src
,0);
5078 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
5079 SET_SRC (pattern
) = gen_rtx (NEG
,
5080 GET_MODE (SET_SRC (pattern
)),
5082 INSN_CODE (next
) = -1;
5083 INSN_CODE (insn
) = -1;
5089 /* Returns register number for function return value.*/
5097 /* Ceate an RTX representing the place where a
5098 library function returns a value of mode MODE. */
5101 avr_libcall_value (mode
)
5102 enum machine_mode mode
;
5104 int offs
= GET_MODE_SIZE (mode
);
5107 return gen_rtx (REG
, mode
, RET_REGISTER
+ 2 - offs
);
5110 /* Create an RTX representing the place where a
5111 function returns a value of data type VALTYPE. */
5114 avr_function_value (type
, func
)
5116 tree func ATTRIBUTE_UNUSED
;
5120 if (TYPE_MODE (type
) != BLKmode
)
5121 return avr_libcall_value (TYPE_MODE (type
));
5123 offs
= int_size_in_bytes (type
);
5126 if (offs
> 2 && offs
< GET_MODE_SIZE (SImode
))
5127 offs
= GET_MODE_SIZE (SImode
);
5128 else if (offs
> GET_MODE_SIZE (SImode
) && offs
< GET_MODE_SIZE (DImode
))
5129 offs
= GET_MODE_SIZE (DImode
);
5131 return gen_rtx (REG
, BLKmode
, RET_REGISTER
+ 2 - offs
);
5134 /* Returns non-zero if the number MASK has only one bit set. */
5137 mask_one_bit_p (mask
)
5141 unsigned HOST_WIDE_INT n
=mask
;
5142 for (i
= 0; i
< 32; ++i
)
5144 if (n
& 0x80000000L
)
5146 if (n
& 0x7fffffffL
)
5157 /* Places additional restrictions on the register class to
5158 use when it is necessary to copy value X into a register
5162 preferred_reload_class (x
, class)
5163 rtx x ATTRIBUTE_UNUSED
;
5164 enum reg_class
class;
5170 test_hard_reg_class (class, x
)
5171 enum reg_class
class;
5174 int regno
= true_regnum (x
);
5177 return TEST_HARD_REG_CLASS (class, regno
);
5181 debug_hard_reg_set (set
)
5185 for (i
=0; i
< FIRST_PSEUDO_REGISTER
; ++i
)
5187 if (TEST_HARD_REG_BIT (set
, i
))
5189 fprintf (stderr
, "r%-2d ", i
);
5192 fprintf (stderr
, "\n");
5196 jump_over_one_insn_p (insn
, dest
)
5200 int uid
= INSN_UID (GET_CODE (dest
) == LABEL_REF
5203 int jump_addr
= INSN_ADDRESSES (INSN_UID (insn
));
5204 int dest_addr
= INSN_ADDRESSES (uid
);
5205 return dest_addr
- jump_addr
== 2;
5208 /* Returns 1 if a value of mode MODE can be stored starting with hard
5209 register number REGNO. On the enhanced core, anything larger than
5210 1 byte must start in even numbered register for "movw" to work
5211 (this way we don't have to check for odd registers everywhere). */
5214 avr_hard_regno_mode_ok (regno
, mode
)
5216 enum machine_mode mode
;
5218 /* Bug workaround: recog.c (peep2_find_free_register) and probably
5219 a few other places assume that the frame pointer is a single hard
5220 register, so r29 may be allocated and overwrite the high byte of
5221 the frame pointer. Do not allow any value to start in r29. */
5222 if (regno
== REG_Y
+ 1)
5227 /* if (regno < 24 && !AVR_ENHANCED)
5229 return !(regno
& 1);
5232 /* Returns 1 if we know register operand OP was 0 before INSN. */
5235 reg_was_0 (insn
, op
)
5240 return (optimize
> 0 && insn
&& op
&& REG_P (op
)
5241 && (link
= find_reg_note (insn
, REG_WAS_0
, 0))
5242 /* Make sure the insn that stored the 0 is still present. */
5243 && ! INSN_DELETED_P (XEXP (link
, 0))
5244 && GET_CODE (XEXP (link
, 0)) != NOTE
5245 /* Make sure cross jumping didn't happen here. */
5246 && no_labels_between_p (XEXP (link
, 0), insn
)
5247 /* Make sure the reg hasn't been clobbered. */
5248 && ! reg_set_between_p (op
, XEXP (link
, 0), insn
));
5251 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5252 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5253 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
5256 avr_io_address_p (x
, size
)
5260 return (optimize
> 0 && GET_CODE (x
) == CONST_INT
5261 && INTVAL (x
) >= 0x20 && INTVAL (x
) <= 0x60 - size
);
5264 /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5267 const_int_pow2_p (x
)
5270 if (GET_CODE (x
) == CONST_INT
)
5272 HOST_WIDE_INT d
= INTVAL (x
);
5273 HOST_WIDE_INT abs_d
= (d
>= 0) ? d
: -d
;
5274 return exact_log2 (abs_d
) + 1;
5280 output_reload_inhi (insn
, operands
, len
)
5281 rtx insn ATTRIBUTE_UNUSED
;
5289 if (GET_CODE (operands
[1]) == CONST_INT
)
5291 int val
= INTVAL (operands
[1]);
5292 if ((val
& 0xff) == 0)
5295 return (AS2 (mov
,%A0
,__zero_reg__
) CR_TAB
5296 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5299 else if ((val
& 0xff00) == 0)
5302 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5303 AS2 (mov
,%A0
,%2) CR_TAB
5304 AS2 (mov
,%B0
,__zero_reg__
));
5306 else if ((val
& 0xff) == ((val
& 0xff00) >> 8))
5309 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5310 AS2 (mov
,%A0
,%2) CR_TAB
5315 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5316 AS2 (mov
,%A0
,%2) CR_TAB
5317 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5323 output_reload_insisf (insn
, operands
, len
)
5324 rtx insn ATTRIBUTE_UNUSED
;
5328 rtx src
= operands
[1];
5329 int cnst
= (GET_CODE (src
) == CONST_INT
);
5334 *len
= 4 + ((INTVAL (src
) & 0xff) != 0)
5335 + ((INTVAL (src
) & 0xff00) != 0)
5336 + ((INTVAL (src
) & 0xff0000) != 0)
5337 + ((INTVAL (src
) & 0xff000000) != 0);
5344 if (cnst
&& ((INTVAL (src
) & 0xff) == 0))
5345 output_asm_insn (AS2 (mov
, %A0
, __zero_reg__
), operands
);
5348 output_asm_insn (AS2 (ldi
, %2, lo8(%1)), operands
);
5349 output_asm_insn (AS2 (mov
, %A0
, %2), operands
);
5351 if (cnst
&& ((INTVAL (src
) & 0xff00) == 0))
5352 output_asm_insn (AS2 (mov
, %B0
, __zero_reg__
), operands
);
5355 output_asm_insn (AS2 (ldi
, %2, hi8(%1)), operands
);
5356 output_asm_insn (AS2 (mov
, %B0
, %2), operands
);
5358 if (cnst
&& ((INTVAL (src
) & 0xff0000) == 0))
5359 output_asm_insn (AS2 (mov
, %C0
, __zero_reg__
), operands
);
5362 output_asm_insn (AS2 (ldi
, %2, hlo8(%1)), operands
);
5363 output_asm_insn (AS2 (mov
, %C0
, %2), operands
);
5365 if (cnst
&& ((INTVAL (src
) & 0xff000000) == 0))
5366 output_asm_insn (AS2 (mov
, %D0
, __zero_reg__
), operands
);
5369 output_asm_insn (AS2 (ldi
, %2, hhi8(%1)), operands
);
5370 output_asm_insn (AS2 (mov
, %D0
, %2), operands
);
5376 avr_output_bld (operands
, bit_nr
)
5380 static char s
[] = "bld %A0,0";
5382 s
[5] = 'A' + (bit_nr
>> 3);
5383 s
[8] = '0' + (bit_nr
& 7);
5384 output_asm_insn (s
, operands
);
5388 avr_output_addr_vec_elt (stream
, value
)
5393 fprintf (stream
, "\t.word pm(.L%d)\n", value
);
5395 fprintf (stream
, "\trjmp .L%d\n", value
);
5400 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5401 registers (for a define_peephole2) in the current function. */
5404 avr_peep2_scratch_safe (scratch
)
5407 if ((interrupt_function_p (current_function_decl
)
5408 || signal_function_p (current_function_decl
))
5409 && leaf_function_p ())
5411 int first_reg
= true_regnum (scratch
);
5412 int last_reg
= first_reg
+ GET_MODE_SIZE (GET_MODE (scratch
)) - 1;
5415 for (reg
= first_reg
; reg
<= last_reg
; reg
++)
5417 if (!regs_ever_live
[reg
])