xref: /openbsd/gnu/gcc/gcc/config/avr/avr.c (revision 404b540a)
1*404b540aSrobert /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2*404b540aSrobert    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007
3*404b540aSrobert    Free Software Foundation, Inc.
4*404b540aSrobert    Contributed by Denis Chertykov (denisc@overta.ru)
5*404b540aSrobert 
6*404b540aSrobert    This file is part of GCC.
7*404b540aSrobert 
8*404b540aSrobert    GCC is free software; you can redistribute it and/or modify
9*404b540aSrobert    it under the terms of the GNU General Public License as published by
10*404b540aSrobert    the Free Software Foundation; either version 2, or (at your option)
11*404b540aSrobert    any later version.
12*404b540aSrobert 
13*404b540aSrobert    GCC is distributed in the hope that it will be useful,
14*404b540aSrobert    but WITHOUT ANY WARRANTY; without even the implied warranty of
15*404b540aSrobert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*404b540aSrobert    GNU General Public License for more details.
17*404b540aSrobert 
18*404b540aSrobert    You should have received a copy of the GNU General Public License
19*404b540aSrobert    along with GCC; see the file COPYING.  If not, write to
20*404b540aSrobert    the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21*404b540aSrobert    Boston, MA 02110-1301, USA.  */
22*404b540aSrobert 
23*404b540aSrobert #include "config.h"
24*404b540aSrobert #include "system.h"
25*404b540aSrobert #include "coretypes.h"
26*404b540aSrobert #include "tm.h"
27*404b540aSrobert #include "rtl.h"
28*404b540aSrobert #include "regs.h"
29*404b540aSrobert #include "hard-reg-set.h"
30*404b540aSrobert #include "real.h"
31*404b540aSrobert #include "insn-config.h"
32*404b540aSrobert #include "conditions.h"
33*404b540aSrobert #include "insn-attr.h"
34*404b540aSrobert #include "flags.h"
35*404b540aSrobert #include "reload.h"
36*404b540aSrobert #include "tree.h"
37*404b540aSrobert #include "output.h"
38*404b540aSrobert #include "expr.h"
39*404b540aSrobert #include "toplev.h"
40*404b540aSrobert #include "obstack.h"
41*404b540aSrobert #include "function.h"
42*404b540aSrobert #include "recog.h"
43*404b540aSrobert #include "ggc.h"
44*404b540aSrobert #include "tm_p.h"
45*404b540aSrobert #include "target.h"
46*404b540aSrobert #include "target-def.h"
47*404b540aSrobert 
48*404b540aSrobert /* Maximal allowed offset for an address in the LD command */
49*404b540aSrobert #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
50*404b540aSrobert 
51*404b540aSrobert static int avr_naked_function_p (tree);
52*404b540aSrobert static int interrupt_function_p (tree);
53*404b540aSrobert static int signal_function_p (tree);
54*404b540aSrobert static int avr_regs_to_save (HARD_REG_SET *);
55*404b540aSrobert static int sequent_regs_live (void);
56*404b540aSrobert static const char *ptrreg_to_str (int);
57*404b540aSrobert static const char *cond_string (enum rtx_code);
58*404b540aSrobert static int avr_num_arg_regs (enum machine_mode, tree);
59*404b540aSrobert static int out_adj_frame_ptr (FILE *, int);
60*404b540aSrobert static int out_set_stack_ptr (FILE *, int, int);
61*404b540aSrobert static RTX_CODE compare_condition (rtx insn);
62*404b540aSrobert static int compare_sign_p (rtx insn);
63*404b540aSrobert static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *);
64*404b540aSrobert static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
65*404b540aSrobert static tree avr_handle_fntype_attribute (tree *, tree, tree, int, bool *);
66*404b540aSrobert const struct attribute_spec avr_attribute_table[];
67*404b540aSrobert static bool avr_assemble_integer (rtx, unsigned int, int);
68*404b540aSrobert static void avr_file_start (void);
69*404b540aSrobert static void avr_file_end (void);
70*404b540aSrobert static void avr_output_function_prologue (FILE *, HOST_WIDE_INT);
71*404b540aSrobert static void avr_output_function_epilogue (FILE *, HOST_WIDE_INT);
72*404b540aSrobert static void avr_insert_attributes (tree, tree *);
73*404b540aSrobert static void avr_asm_init_sections (void);
74*404b540aSrobert static unsigned int avr_section_type_flags (tree, const char *, int);
75*404b540aSrobert 
76*404b540aSrobert static void avr_reorg (void);
77*404b540aSrobert static void avr_asm_out_ctor (rtx, int);
78*404b540aSrobert static void avr_asm_out_dtor (rtx, int);
79*404b540aSrobert static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code);
80*404b540aSrobert static bool avr_rtx_costs (rtx, int, int, int *);
81*404b540aSrobert static int avr_address_cost (rtx);
82*404b540aSrobert static bool avr_return_in_memory (tree, tree);
83*404b540aSrobert 
84*404b540aSrobert /* Allocate registers from r25 to r8 for parameters for function calls.  */
85*404b540aSrobert #define FIRST_CUM_REG 26
86*404b540aSrobert 
87*404b540aSrobert /* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */
88*404b540aSrobert static GTY(()) rtx tmp_reg_rtx;
89*404b540aSrobert 
90*404b540aSrobert /* Zeroed register RTX (gen_rtx_REG (QImode, ZERO_REGNO)) */
91*404b540aSrobert static GTY(()) rtx zero_reg_rtx;
92*404b540aSrobert 
93*404b540aSrobert /* AVR register names {"r0", "r1", ..., "r31"} */
94*404b540aSrobert static const char *const avr_regnames[] = REGISTER_NAMES;
95*404b540aSrobert 
96*404b540aSrobert /* This holds the last insn address.  */
97*404b540aSrobert static int last_insn_address = 0;
98*404b540aSrobert 
99*404b540aSrobert /* Commands count in the compiled file */
100*404b540aSrobert static int commands_in_file;
101*404b540aSrobert 
102*404b540aSrobert /* Commands in the functions prologues in the compiled file */
103*404b540aSrobert static int commands_in_prologues;
104*404b540aSrobert 
105*404b540aSrobert /* Commands in the functions epilogues in the compiled file */
106*404b540aSrobert static int commands_in_epilogues;
107*404b540aSrobert 
108*404b540aSrobert /* Prologue/Epilogue size in words */
109*404b540aSrobert static int prologue_size;
110*404b540aSrobert static int epilogue_size;
111*404b540aSrobert 
112*404b540aSrobert /* Size of all jump tables in the current function, in words.  */
113*404b540aSrobert static int jump_tables_size;
114*404b540aSrobert 
115*404b540aSrobert /* Preprocessor macros to define depending on MCU type.  */
116*404b540aSrobert const char *avr_base_arch_macro;
117*404b540aSrobert const char *avr_extra_arch_macro;
118*404b540aSrobert 
119*404b540aSrobert section *progmem_section;
120*404b540aSrobert 
121*404b540aSrobert /* More than 8K of program memory: use "call" and "jmp".  */
122*404b540aSrobert int avr_mega_p = 0;
123*404b540aSrobert 
124*404b540aSrobert /* Enhanced core: use "movw", "mul", ...  */
125*404b540aSrobert int avr_enhanced_p = 0;
126*404b540aSrobert 
127*404b540aSrobert /* Assembler only.  */
128*404b540aSrobert int avr_asm_only_p = 0;
129*404b540aSrobert 
130*404b540aSrobert /* Core have 'MOVW' and 'LPM Rx,Z' instructions.  */
131*404b540aSrobert int avr_have_movw_lpmx_p = 0;
132*404b540aSrobert 
133*404b540aSrobert struct base_arch_s {
134*404b540aSrobert   int asm_only;
135*404b540aSrobert   int enhanced;
136*404b540aSrobert   int mega;
137*404b540aSrobert   int have_movw_lpmx;
138*404b540aSrobert   const char *const macro;
139*404b540aSrobert };
140*404b540aSrobert 
141*404b540aSrobert static const struct base_arch_s avr_arch_types[] = {
142*404b540aSrobert   { 1, 0, 0, 0,  NULL },  /* unknown device specified */
143*404b540aSrobert   { 1, 0, 0, 0, "__AVR_ARCH__=1" },
144*404b540aSrobert   { 0, 0, 0, 0, "__AVR_ARCH__=2" },
145*404b540aSrobert   { 0, 0, 0, 1, "__AVR_ARCH__=25"},
146*404b540aSrobert   { 0, 0, 1, 0, "__AVR_ARCH__=3" },
147*404b540aSrobert   { 0, 1, 0, 1, "__AVR_ARCH__=4" },
148*404b540aSrobert   { 0, 1, 1, 1, "__AVR_ARCH__=5" }
149*404b540aSrobert };
150*404b540aSrobert 
151*404b540aSrobert /* These names are used as the index into the avr_arch_types[] table
152*404b540aSrobert    above.  */
153*404b540aSrobert 
154*404b540aSrobert enum avr_arch
155*404b540aSrobert {
156*404b540aSrobert   ARCH_UNKNOWN,
157*404b540aSrobert   ARCH_AVR1,
158*404b540aSrobert   ARCH_AVR2,
159*404b540aSrobert   ARCH_AVR25,
160*404b540aSrobert   ARCH_AVR3,
161*404b540aSrobert   ARCH_AVR4,
162*404b540aSrobert   ARCH_AVR5
163*404b540aSrobert };
164*404b540aSrobert 
165*404b540aSrobert struct mcu_type_s {
166*404b540aSrobert   const char *const name;
167*404b540aSrobert   int arch;  /* index in avr_arch_types[] */
168*404b540aSrobert   /* Must lie outside user's namespace.  NULL == no macro.  */
169*404b540aSrobert   const char *const macro;
170*404b540aSrobert };
171*404b540aSrobert 
172*404b540aSrobert /* List of all known AVR MCU types - if updated, it has to be kept
173*404b540aSrobert    in sync in several places (FIXME: is there a better way?):
174*404b540aSrobert     - here
175*404b540aSrobert     - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
176*404b540aSrobert     - t-avr (MULTILIB_MATCHES)
177*404b540aSrobert     - gas/config/tc-avr.c
178*404b540aSrobert     - avr-libc  */
179*404b540aSrobert 
180*404b540aSrobert static const struct mcu_type_s avr_mcu_types[] = {
181*404b540aSrobert     /* Classic, <= 8K.  */
182*404b540aSrobert   { "avr2",         ARCH_AVR2, NULL },
183*404b540aSrobert   { "at90s2313",    ARCH_AVR2, "__AVR_AT90S2313__" },
184*404b540aSrobert   { "at90s2323",    ARCH_AVR2, "__AVR_AT90S2323__" },
185*404b540aSrobert   { "at90s2333",    ARCH_AVR2, "__AVR_AT90S2333__" },
186*404b540aSrobert   { "at90s2343",    ARCH_AVR2, "__AVR_AT90S2343__" },
187*404b540aSrobert   { "attiny22",     ARCH_AVR2, "__AVR_ATtiny22__" },
188*404b540aSrobert   { "attiny26",     ARCH_AVR2, "__AVR_ATtiny26__" },
189*404b540aSrobert   { "at90s4414",    ARCH_AVR2, "__AVR_AT90S4414__" },
190*404b540aSrobert   { "at90s4433",    ARCH_AVR2, "__AVR_AT90S4433__" },
191*404b540aSrobert   { "at90s4434",    ARCH_AVR2, "__AVR_AT90S4434__" },
192*404b540aSrobert   { "at90s8515",    ARCH_AVR2, "__AVR_AT90S8515__" },
193*404b540aSrobert   { "at90c8534",    ARCH_AVR2, "__AVR_AT90C8534__" },
194*404b540aSrobert   { "at90s8535",    ARCH_AVR2, "__AVR_AT90S8535__" },
195*404b540aSrobert     /* Classic + MOVW, <= 8K.  */
196*404b540aSrobert   { "avr25",        ARCH_AVR25, NULL },
197*404b540aSrobert   { "attiny13",     ARCH_AVR25, "__AVR_ATtiny13__" },
198*404b540aSrobert   { "attiny2313",   ARCH_AVR25, "__AVR_ATtiny2313__" },
199*404b540aSrobert   { "attiny24",     ARCH_AVR25, "__AVR_ATtiny24__" },
200*404b540aSrobert   { "attiny44",     ARCH_AVR25, "__AVR_ATtiny44__" },
201*404b540aSrobert   { "attiny84",     ARCH_AVR25, "__AVR_ATtiny84__" },
202*404b540aSrobert   { "attiny25",     ARCH_AVR25, "__AVR_ATtiny25__" },
203*404b540aSrobert   { "attiny45",     ARCH_AVR25, "__AVR_ATtiny45__" },
204*404b540aSrobert   { "attiny85",     ARCH_AVR25, "__AVR_ATtiny85__" },
205*404b540aSrobert   { "attiny261",    ARCH_AVR25, "__AVR_ATtiny261__" },
206*404b540aSrobert   { "attiny461",    ARCH_AVR25, "__AVR_ATtiny461__" },
207*404b540aSrobert   { "attiny861",    ARCH_AVR25, "__AVR_ATtiny861__" },
208*404b540aSrobert   { "at86rf401",    ARCH_AVR25, "__AVR_AT86RF401__" },
209*404b540aSrobert     /* Classic, > 8K.  */
210*404b540aSrobert   { "avr3",         ARCH_AVR3, NULL },
211*404b540aSrobert   { "atmega103",    ARCH_AVR3, "__AVR_ATmega103__" },
212*404b540aSrobert   { "atmega603",    ARCH_AVR3, "__AVR_ATmega603__" },
213*404b540aSrobert   { "at43usb320",   ARCH_AVR3, "__AVR_AT43USB320__" },
214*404b540aSrobert   { "at43usb355",   ARCH_AVR3, "__AVR_AT43USB355__" },
215*404b540aSrobert   { "at76c711",     ARCH_AVR3, "__AVR_AT76C711__" },
216*404b540aSrobert     /* Enhanced, <= 8K.  */
217*404b540aSrobert   { "avr4",         ARCH_AVR4, NULL },
218*404b540aSrobert   { "atmega8",      ARCH_AVR4, "__AVR_ATmega8__" },
219*404b540aSrobert   { "atmega48",     ARCH_AVR4, "__AVR_ATmega48__" },
220*404b540aSrobert   { "atmega88",     ARCH_AVR4, "__AVR_ATmega88__" },
221*404b540aSrobert   { "atmega8515",   ARCH_AVR4, "__AVR_ATmega8515__" },
222*404b540aSrobert   { "atmega8535",   ARCH_AVR4, "__AVR_ATmega8535__" },
223*404b540aSrobert   { "atmega8hva",   ARCH_AVR4, "__AVR_ATmega8HVA__" },
224*404b540aSrobert   { "at90pwm1",     ARCH_AVR4, "__AVR_AT90PWM1__" },
225*404b540aSrobert   { "at90pwm2",     ARCH_AVR4, "__AVR_AT90PWM2__" },
226*404b540aSrobert   { "at90pwm3",     ARCH_AVR4, "__AVR_AT90PWM3__" },
227*404b540aSrobert     /* Enhanced, > 8K.  */
228*404b540aSrobert   { "avr5",         ARCH_AVR5, NULL },
229*404b540aSrobert   { "atmega16",     ARCH_AVR5, "__AVR_ATmega16__" },
230*404b540aSrobert   { "atmega161",    ARCH_AVR5, "__AVR_ATmega161__" },
231*404b540aSrobert   { "atmega162",    ARCH_AVR5, "__AVR_ATmega162__" },
232*404b540aSrobert   { "atmega163",    ARCH_AVR5, "__AVR_ATmega163__" },
233*404b540aSrobert   { "atmega164p",   ARCH_AVR5, "__AVR_ATmega164P__" },
234*404b540aSrobert   { "atmega165",    ARCH_AVR5, "__AVR_ATmega165__" },
235*404b540aSrobert   { "atmega165p",   ARCH_AVR5, "__AVR_ATmega165P__" },
236*404b540aSrobert   { "atmega168",    ARCH_AVR5, "__AVR_ATmega168__" },
237*404b540aSrobert   { "atmega169",    ARCH_AVR5, "__AVR_ATmega169__" },
238*404b540aSrobert   { "atmega169p",   ARCH_AVR5, "__AVR_ATmega169P__" },
239*404b540aSrobert   { "atmega32",     ARCH_AVR5, "__AVR_ATmega32__" },
240*404b540aSrobert   { "atmega323",    ARCH_AVR5, "__AVR_ATmega323__" },
241*404b540aSrobert   { "atmega324p",   ARCH_AVR5, "__AVR_ATmega324P__" },
242*404b540aSrobert   { "atmega325",    ARCH_AVR5, "__AVR_ATmega325__" },
243*404b540aSrobert   { "atmega325p",   ARCH_AVR5, "__AVR_ATmega325P__" },
244*404b540aSrobert   { "atmega3250",   ARCH_AVR5, "__AVR_ATmega3250__" },
245*404b540aSrobert   { "atmega3250p",  ARCH_AVR5, "__AVR_ATmega3250P__" },
246*404b540aSrobert   { "atmega329",    ARCH_AVR5, "__AVR_ATmega329__" },
247*404b540aSrobert   { "atmega329p",   ARCH_AVR5, "__AVR_ATmega329P__" },
248*404b540aSrobert   { "atmega3290",   ARCH_AVR5, "__AVR_ATmega3290__" },
249*404b540aSrobert   { "atmega3290p",  ARCH_AVR5, "__AVR_ATmega3290P__" },
250*404b540aSrobert   { "atmega406",    ARCH_AVR5, "__AVR_ATmega406__" },
251*404b540aSrobert   { "atmega64",     ARCH_AVR5, "__AVR_ATmega64__" },
252*404b540aSrobert   { "atmega640",    ARCH_AVR5, "__AVR_ATmega640__" },
253*404b540aSrobert   { "atmega644",    ARCH_AVR5, "__AVR_ATmega644__" },
254*404b540aSrobert   { "atmega644p",   ARCH_AVR5, "__AVR_ATmega644P__" },
255*404b540aSrobert   { "atmega645",    ARCH_AVR5, "__AVR_ATmega645__" },
256*404b540aSrobert   { "atmega6450",   ARCH_AVR5, "__AVR_ATmega6450__" },
257*404b540aSrobert   { "atmega649",    ARCH_AVR5, "__AVR_ATmega649__" },
258*404b540aSrobert   { "atmega6490",   ARCH_AVR5, "__AVR_ATmega6490__" },
259*404b540aSrobert   { "atmega128",    ARCH_AVR5, "__AVR_ATmega128__" },
260*404b540aSrobert   { "atmega1280",   ARCH_AVR5, "__AVR_ATmega1280__" },
261*404b540aSrobert   { "atmega1281",   ARCH_AVR5, "__AVR_ATmega1281__" },
262*404b540aSrobert   { "atmega16hva",  ARCH_AVR5, "__AVR_ATmega16HVA__" },
263*404b540aSrobert   { "at90can32",    ARCH_AVR5, "__AVR_AT90CAN32__" },
264*404b540aSrobert   { "at90can64",    ARCH_AVR5, "__AVR_AT90CAN64__" },
265*404b540aSrobert   { "at90can128",   ARCH_AVR5, "__AVR_AT90CAN128__" },
266*404b540aSrobert   { "at90usb82",    ARCH_AVR5, "__AVR_AT90USB82__" },
267*404b540aSrobert   { "at90usb162",   ARCH_AVR5, "__AVR_AT90USB162__" },
268*404b540aSrobert   { "at90usb646",   ARCH_AVR5, "__AVR_AT90USB646__" },
269*404b540aSrobert   { "at90usb647",   ARCH_AVR5, "__AVR_AT90USB647__" },
270*404b540aSrobert   { "at90usb1286",  ARCH_AVR5, "__AVR_AT90USB1286__" },
271*404b540aSrobert   { "at90usb1287",  ARCH_AVR5, "__AVR_AT90USB1287__" },
272*404b540aSrobert   { "at94k",        ARCH_AVR5, "__AVR_AT94K__" },
273*404b540aSrobert     /* Assembler only.  */
274*404b540aSrobert   { "avr1",         ARCH_AVR1, NULL },
275*404b540aSrobert   { "at90s1200",    ARCH_AVR1, "__AVR_AT90S1200__" },
276*404b540aSrobert   { "attiny11",     ARCH_AVR1, "__AVR_ATtiny11__" },
277*404b540aSrobert   { "attiny12",     ARCH_AVR1, "__AVR_ATtiny12__" },
278*404b540aSrobert   { "attiny15",     ARCH_AVR1, "__AVR_ATtiny15__" },
279*404b540aSrobert   { "attiny28",     ARCH_AVR1, "__AVR_ATtiny28__" },
280*404b540aSrobert   { NULL,           ARCH_UNKNOWN, NULL }
281*404b540aSrobert };
282*404b540aSrobert 
283*404b540aSrobert int avr_case_values_threshold = 30000;
284*404b540aSrobert 
285*404b540aSrobert /* Initialize the GCC target structure.  */
286*404b540aSrobert #undef TARGET_ASM_ALIGNED_HI_OP
287*404b540aSrobert #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
288*404b540aSrobert #undef TARGET_ASM_ALIGNED_SI_OP
289*404b540aSrobert #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
290*404b540aSrobert #undef TARGET_ASM_UNALIGNED_HI_OP
291*404b540aSrobert #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
292*404b540aSrobert #undef TARGET_ASM_UNALIGNED_SI_OP
293*404b540aSrobert #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
294*404b540aSrobert #undef TARGET_ASM_INTEGER
295*404b540aSrobert #define TARGET_ASM_INTEGER avr_assemble_integer
296*404b540aSrobert #undef TARGET_ASM_FILE_START
297*404b540aSrobert #define TARGET_ASM_FILE_START avr_file_start
298*404b540aSrobert #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
299*404b540aSrobert #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
300*404b540aSrobert #undef TARGET_ASM_FILE_END
301*404b540aSrobert #define TARGET_ASM_FILE_END avr_file_end
302*404b540aSrobert 
303*404b540aSrobert #undef TARGET_ASM_FUNCTION_PROLOGUE
304*404b540aSrobert #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
305*404b540aSrobert #undef TARGET_ASM_FUNCTION_EPILOGUE
306*404b540aSrobert #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
307*404b540aSrobert #undef TARGET_ATTRIBUTE_TABLE
308*404b540aSrobert #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
309*404b540aSrobert #undef TARGET_ASM_FUNCTION_RODATA_SECTION
310*404b540aSrobert #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
311*404b540aSrobert #undef TARGET_INSERT_ATTRIBUTES
312*404b540aSrobert #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
313*404b540aSrobert #undef TARGET_SECTION_TYPE_FLAGS
314*404b540aSrobert #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
315*404b540aSrobert #undef TARGET_RTX_COSTS
316*404b540aSrobert #define TARGET_RTX_COSTS avr_rtx_costs
317*404b540aSrobert #undef TARGET_ADDRESS_COST
318*404b540aSrobert #define TARGET_ADDRESS_COST avr_address_cost
319*404b540aSrobert #undef TARGET_MACHINE_DEPENDENT_REORG
320*404b540aSrobert #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
321*404b540aSrobert 
322*404b540aSrobert #undef TARGET_RETURN_IN_MEMORY
323*404b540aSrobert #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
324*404b540aSrobert 
325*404b540aSrobert #undef TARGET_STRICT_ARGUMENT_NAMING
326*404b540aSrobert #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
327*404b540aSrobert 
328*404b540aSrobert struct gcc_target targetm = TARGET_INITIALIZER;
329*404b540aSrobert 
330*404b540aSrobert void
avr_override_options(void)331*404b540aSrobert avr_override_options (void)
332*404b540aSrobert {
333*404b540aSrobert   const struct mcu_type_s *t;
334*404b540aSrobert   const struct base_arch_s *base;
335*404b540aSrobert 
336*404b540aSrobert   flag_delete_null_pointer_checks = 0;
337*404b540aSrobert 
338*404b540aSrobert   for (t = avr_mcu_types; t->name; t++)
339*404b540aSrobert     if (strcmp (t->name, avr_mcu_name) == 0)
340*404b540aSrobert       break;
341*404b540aSrobert 
342*404b540aSrobert   if (!t->name)
343*404b540aSrobert     {
344*404b540aSrobert       fprintf (stderr, "unknown MCU '%s' specified\nKnown MCU names:\n",
345*404b540aSrobert 	       avr_mcu_name);
346*404b540aSrobert       for (t = avr_mcu_types; t->name; t++)
347*404b540aSrobert 	fprintf (stderr,"   %s\n", t->name);
348*404b540aSrobert     }
349*404b540aSrobert 
350*404b540aSrobert   base = &avr_arch_types[t->arch];
351*404b540aSrobert   avr_asm_only_p = base->asm_only;
352*404b540aSrobert   avr_enhanced_p = base->enhanced;
353*404b540aSrobert   avr_mega_p = base->mega;
354*404b540aSrobert   avr_have_movw_lpmx_p = base->have_movw_lpmx;
355*404b540aSrobert   avr_base_arch_macro = base->macro;
356*404b540aSrobert   avr_extra_arch_macro = t->macro;
357*404b540aSrobert 
358*404b540aSrobert   if (optimize && !TARGET_NO_TABLEJUMP)
359*404b540aSrobert     avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
360*404b540aSrobert 
361*404b540aSrobert   tmp_reg_rtx  = gen_rtx_REG (QImode, TMP_REGNO);
362*404b540aSrobert   zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO);
363*404b540aSrobert }
364*404b540aSrobert 
365*404b540aSrobert /*  return register class from register number.  */
366*404b540aSrobert 
367*404b540aSrobert static const int reg_class_tab[]={
368*404b540aSrobert   GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
369*404b540aSrobert   GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
370*404b540aSrobert   GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
371*404b540aSrobert   GENERAL_REGS, /* r0 - r15 */
372*404b540aSrobert   LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
373*404b540aSrobert   LD_REGS,                      /* r16 - 23 */
374*404b540aSrobert   ADDW_REGS,ADDW_REGS,          /* r24,r25 */
375*404b540aSrobert   POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
376*404b540aSrobert   POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
377*404b540aSrobert   POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
378*404b540aSrobert   STACK_REG,STACK_REG           /* SPL,SPH */
379*404b540aSrobert };
380*404b540aSrobert 
381*404b540aSrobert /* Return register class for register R.  */
382*404b540aSrobert 
383*404b540aSrobert enum reg_class
avr_regno_reg_class(int r)384*404b540aSrobert avr_regno_reg_class (int r)
385*404b540aSrobert {
386*404b540aSrobert   if (r <= 33)
387*404b540aSrobert     return reg_class_tab[r];
388*404b540aSrobert   return ALL_REGS;
389*404b540aSrobert }
390*404b540aSrobert 
391*404b540aSrobert /* Return nonzero if FUNC is a naked function.  */
392*404b540aSrobert 
393*404b540aSrobert static int
avr_naked_function_p(tree func)394*404b540aSrobert avr_naked_function_p (tree func)
395*404b540aSrobert {
396*404b540aSrobert   tree a;
397*404b540aSrobert 
398*404b540aSrobert   gcc_assert (TREE_CODE (func) == FUNCTION_DECL);
399*404b540aSrobert 
400*404b540aSrobert   a = lookup_attribute ("naked", TYPE_ATTRIBUTES (TREE_TYPE (func)));
401*404b540aSrobert   return a != NULL_TREE;
402*404b540aSrobert }
403*404b540aSrobert 
404*404b540aSrobert /* Return nonzero if FUNC is an interrupt function as specified
405*404b540aSrobert    by the "interrupt" attribute.  */
406*404b540aSrobert 
407*404b540aSrobert static int
interrupt_function_p(tree func)408*404b540aSrobert interrupt_function_p (tree func)
409*404b540aSrobert {
410*404b540aSrobert   tree a;
411*404b540aSrobert 
412*404b540aSrobert   if (TREE_CODE (func) != FUNCTION_DECL)
413*404b540aSrobert     return 0;
414*404b540aSrobert 
415*404b540aSrobert   a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
416*404b540aSrobert   return a != NULL_TREE;
417*404b540aSrobert }
418*404b540aSrobert 
419*404b540aSrobert /* Return nonzero if FUNC is a signal function as specified
420*404b540aSrobert    by the "signal" attribute.  */
421*404b540aSrobert 
422*404b540aSrobert static int
signal_function_p(tree func)423*404b540aSrobert signal_function_p (tree func)
424*404b540aSrobert {
425*404b540aSrobert   tree a;
426*404b540aSrobert 
427*404b540aSrobert   if (TREE_CODE (func) != FUNCTION_DECL)
428*404b540aSrobert     return 0;
429*404b540aSrobert 
430*404b540aSrobert   a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
431*404b540aSrobert   return a != NULL_TREE;
432*404b540aSrobert }
433*404b540aSrobert 
434*404b540aSrobert /* Return the number of hard registers to push/pop in the prologue/epilogue
435*404b540aSrobert    of the current function, and optionally store these registers in SET.  */
436*404b540aSrobert 
437*404b540aSrobert static int
avr_regs_to_save(HARD_REG_SET * set)438*404b540aSrobert avr_regs_to_save (HARD_REG_SET *set)
439*404b540aSrobert {
440*404b540aSrobert   int reg, count;
441*404b540aSrobert   int int_or_sig_p = (interrupt_function_p (current_function_decl)
442*404b540aSrobert 		      || signal_function_p (current_function_decl));
443*404b540aSrobert   int leaf_func_p = leaf_function_p ();
444*404b540aSrobert 
445*404b540aSrobert   if (set)
446*404b540aSrobert     CLEAR_HARD_REG_SET (*set);
447*404b540aSrobert   count = 0;
448*404b540aSrobert 
449*404b540aSrobert   /* No need to save any registers if the function never returns.  */
450*404b540aSrobert   if (TREE_THIS_VOLATILE (current_function_decl))
451*404b540aSrobert     return 0;
452*404b540aSrobert 
453*404b540aSrobert   for (reg = 0; reg < 32; reg++)
454*404b540aSrobert     {
455*404b540aSrobert       /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
456*404b540aSrobert 	 any global register variables.  */
457*404b540aSrobert       if (fixed_regs[reg])
458*404b540aSrobert 	continue;
459*404b540aSrobert 
460*404b540aSrobert       if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
461*404b540aSrobert 	  || (regs_ever_live[reg]
462*404b540aSrobert 	      && (int_or_sig_p || !call_used_regs[reg])
463*404b540aSrobert 	      && !(frame_pointer_needed
464*404b540aSrobert 		   && (reg == REG_Y || reg == (REG_Y+1)))))
465*404b540aSrobert 	{
466*404b540aSrobert 	  if (set)
467*404b540aSrobert 	    SET_HARD_REG_BIT (*set, reg);
468*404b540aSrobert 	  count++;
469*404b540aSrobert 	}
470*404b540aSrobert     }
471*404b540aSrobert   return count;
472*404b540aSrobert }
473*404b540aSrobert 
474*404b540aSrobert /* Compute offset between arg_pointer and frame_pointer.  */
475*404b540aSrobert 
476*404b540aSrobert int
initial_elimination_offset(int from,int to)477*404b540aSrobert initial_elimination_offset (int from, int to)
478*404b540aSrobert {
479*404b540aSrobert   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
480*404b540aSrobert     return 0;
481*404b540aSrobert   else
482*404b540aSrobert     {
483*404b540aSrobert       int offset = frame_pointer_needed ? 2 : 0;
484*404b540aSrobert 
485*404b540aSrobert       offset += avr_regs_to_save (NULL);
486*404b540aSrobert       return get_frame_size () + 2 + 1 + offset;
487*404b540aSrobert     }
488*404b540aSrobert }
489*404b540aSrobert 
490*404b540aSrobert /* Return 1 if the function epilogue is just a single "ret".  */
491*404b540aSrobert 
492*404b540aSrobert int
avr_simple_epilogue(void)493*404b540aSrobert avr_simple_epilogue (void)
494*404b540aSrobert {
495*404b540aSrobert   return (! frame_pointer_needed
496*404b540aSrobert 	  && get_frame_size () == 0
497*404b540aSrobert 	  && avr_regs_to_save (NULL) == 0
498*404b540aSrobert 	  && ! interrupt_function_p (current_function_decl)
499*404b540aSrobert 	  && ! signal_function_p (current_function_decl)
500*404b540aSrobert 	  && ! avr_naked_function_p (current_function_decl)
501*404b540aSrobert 	  && ! MAIN_NAME_P (DECL_NAME (current_function_decl))
502*404b540aSrobert 	  && ! TREE_THIS_VOLATILE (current_function_decl));
503*404b540aSrobert }
504*404b540aSrobert 
505*404b540aSrobert /* This function checks sequence of live registers.  */
506*404b540aSrobert 
507*404b540aSrobert static int
sequent_regs_live(void)508*404b540aSrobert sequent_regs_live (void)
509*404b540aSrobert {
510*404b540aSrobert   int reg;
511*404b540aSrobert   int live_seq=0;
512*404b540aSrobert   int cur_seq=0;
513*404b540aSrobert 
514*404b540aSrobert   for (reg = 0; reg < 18; ++reg)
515*404b540aSrobert     {
516*404b540aSrobert       if (!call_used_regs[reg])
517*404b540aSrobert 	{
518*404b540aSrobert 	  if (regs_ever_live[reg])
519*404b540aSrobert 	    {
520*404b540aSrobert 	      ++live_seq;
521*404b540aSrobert 	      ++cur_seq;
522*404b540aSrobert 	    }
523*404b540aSrobert 	  else
524*404b540aSrobert 	    cur_seq = 0;
525*404b540aSrobert 	}
526*404b540aSrobert     }
527*404b540aSrobert 
528*404b540aSrobert   if (!frame_pointer_needed)
529*404b540aSrobert     {
530*404b540aSrobert       if (regs_ever_live[REG_Y])
531*404b540aSrobert 	{
532*404b540aSrobert 	  ++live_seq;
533*404b540aSrobert 	  ++cur_seq;
534*404b540aSrobert 	}
535*404b540aSrobert       else
536*404b540aSrobert 	cur_seq = 0;
537*404b540aSrobert 
538*404b540aSrobert       if (regs_ever_live[REG_Y+1])
539*404b540aSrobert 	{
540*404b540aSrobert 	  ++live_seq;
541*404b540aSrobert 	  ++cur_seq;
542*404b540aSrobert 	}
543*404b540aSrobert       else
544*404b540aSrobert 	cur_seq = 0;
545*404b540aSrobert     }
546*404b540aSrobert   else
547*404b540aSrobert     {
548*404b540aSrobert       cur_seq += 2;
549*404b540aSrobert       live_seq += 2;
550*404b540aSrobert     }
551*404b540aSrobert   return (cur_seq == live_seq) ? live_seq : 0;
552*404b540aSrobert }
553*404b540aSrobert 
554*404b540aSrobert 
555*404b540aSrobert /* Output to FILE the asm instructions to adjust the frame pointer by
556*404b540aSrobert    ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
557*404b540aSrobert    (epilogue).  Returns the number of instructions generated.  */
558*404b540aSrobert 
559*404b540aSrobert static int
out_adj_frame_ptr(FILE * file,int adj)560*404b540aSrobert out_adj_frame_ptr (FILE *file, int adj)
561*404b540aSrobert {
562*404b540aSrobert   int size = 0;
563*404b540aSrobert 
564*404b540aSrobert   if (adj)
565*404b540aSrobert     {
566*404b540aSrobert       if (TARGET_TINY_STACK)
567*404b540aSrobert 	{
568*404b540aSrobert 	  if (adj < -63 || adj > 63)
569*404b540aSrobert 	    warning (0, "large frame pointer change (%d) with -mtiny-stack", adj);
570*404b540aSrobert 
571*404b540aSrobert 	  /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
572*404b540aSrobert 	     over "sbiw" (2 cycles, same size).  */
573*404b540aSrobert 
574*404b540aSrobert 	  fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
575*404b540aSrobert 	  size++;
576*404b540aSrobert 	}
577*404b540aSrobert       else if (adj < -63 || adj > 63)
578*404b540aSrobert 	{
579*404b540aSrobert 	  fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
580*404b540aSrobert 			  AS2 (sbci, r29, hi8(%d)) CR_TAB),
581*404b540aSrobert 		   adj, adj);
582*404b540aSrobert 	  size += 2;
583*404b540aSrobert 	}
584*404b540aSrobert       else if (adj < 0)
585*404b540aSrobert 	{
586*404b540aSrobert 	  fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
587*404b540aSrobert 	  size++;
588*404b540aSrobert 	}
589*404b540aSrobert       else
590*404b540aSrobert 	{
591*404b540aSrobert 	  fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
592*404b540aSrobert 	  size++;
593*404b540aSrobert 	}
594*404b540aSrobert     }
595*404b540aSrobert   return size;
596*404b540aSrobert }
597*404b540aSrobert 
598*404b540aSrobert 
599*404b540aSrobert /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
600*404b540aSrobert    handling various cases of interrupt enable flag state BEFORE and AFTER
601*404b540aSrobert    (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
602*404b540aSrobert    Returns the number of instructions generated.  */
603*404b540aSrobert 
604*404b540aSrobert static int
out_set_stack_ptr(FILE * file,int before,int after)605*404b540aSrobert out_set_stack_ptr (FILE *file, int before, int after)
606*404b540aSrobert {
607*404b540aSrobert   int do_sph, do_cli, do_save, do_sei, lock_sph, size;
608*404b540aSrobert 
609*404b540aSrobert   /* The logic here is so that -mno-interrupts actually means
610*404b540aSrobert      "it is safe to write SPH in one instruction, then SPL in the
611*404b540aSrobert      next instruction, without disabling interrupts first".
612*404b540aSrobert      The after != -1 case (interrupt/signal) is not affected.  */
613*404b540aSrobert 
614*404b540aSrobert   do_sph = !TARGET_TINY_STACK;
615*404b540aSrobert   lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
616*404b540aSrobert   do_cli = (before != 0 && (after == 0 || lock_sph));
617*404b540aSrobert   do_save = (do_cli && before == -1 && after == -1);
618*404b540aSrobert   do_sei = ((do_cli || before != 1) && after == 1);
619*404b540aSrobert   size = 1;
620*404b540aSrobert 
621*404b540aSrobert   if (do_save)
622*404b540aSrobert     {
623*404b540aSrobert       fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
624*404b540aSrobert       size++;
625*404b540aSrobert     }
626*404b540aSrobert 
627*404b540aSrobert   if (do_cli)
628*404b540aSrobert     {
629*404b540aSrobert       fprintf (file, "cli" CR_TAB);
630*404b540aSrobert       size++;
631*404b540aSrobert     }
632*404b540aSrobert 
633*404b540aSrobert   /* Do SPH first - maybe this will disable interrupts for one instruction
634*404b540aSrobert      someday (a suggestion has been sent to avr@atmel.com for consideration
635*404b540aSrobert      in future devices - that would make -mno-interrupts always safe).  */
636*404b540aSrobert   if (do_sph)
637*404b540aSrobert     {
638*404b540aSrobert       fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
639*404b540aSrobert       size++;
640*404b540aSrobert     }
641*404b540aSrobert 
642*404b540aSrobert   /* Set/restore the I flag now - interrupts will be really enabled only
643*404b540aSrobert      after the next instruction.  This is not clearly documented, but
644*404b540aSrobert      believed to be true for all AVR devices.  */
645*404b540aSrobert   if (do_save)
646*404b540aSrobert     {
647*404b540aSrobert       fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
648*404b540aSrobert       size++;
649*404b540aSrobert     }
650*404b540aSrobert   else if (do_sei)
651*404b540aSrobert     {
652*404b540aSrobert       fprintf (file, "sei" CR_TAB);
653*404b540aSrobert       size++;
654*404b540aSrobert     }
655*404b540aSrobert 
656*404b540aSrobert   fprintf (file, AS2 (out, __SP_L__, r28) "\n");
657*404b540aSrobert 
658*404b540aSrobert   return size;
659*404b540aSrobert }
660*404b540aSrobert 
661*404b540aSrobert 
662*404b540aSrobert /* Output function prologue.  */
663*404b540aSrobert 
664*404b540aSrobert static void
avr_output_function_prologue(FILE * file,HOST_WIDE_INT size)665*404b540aSrobert avr_output_function_prologue (FILE *file, HOST_WIDE_INT size)
666*404b540aSrobert {
667*404b540aSrobert   int reg;
668*404b540aSrobert   int interrupt_func_p;
669*404b540aSrobert   int signal_func_p;
670*404b540aSrobert   int main_p;
671*404b540aSrobert   int live_seq;
672*404b540aSrobert   int minimize;
673*404b540aSrobert 
674*404b540aSrobert   last_insn_address = 0;
675*404b540aSrobert   jump_tables_size = 0;
676*404b540aSrobert   prologue_size = 0;
677*404b540aSrobert   fprintf (file, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n",
678*404b540aSrobert 	   size);
679*404b540aSrobert 
680*404b540aSrobert   if (avr_naked_function_p (current_function_decl))
681*404b540aSrobert     {
682*404b540aSrobert       fputs ("/* prologue: naked */\n", file);
683*404b540aSrobert       goto out;
684*404b540aSrobert     }
685*404b540aSrobert 
686*404b540aSrobert   interrupt_func_p = interrupt_function_p (current_function_decl);
687*404b540aSrobert   signal_func_p = signal_function_p (current_function_decl);
688*404b540aSrobert   main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
689*404b540aSrobert   live_seq = sequent_regs_live ();
690*404b540aSrobert   minimize = (TARGET_CALL_PROLOGUES
691*404b540aSrobert 	      && !interrupt_func_p && !signal_func_p && live_seq);
692*404b540aSrobert 
693*404b540aSrobert   if (interrupt_func_p)
694*404b540aSrobert     {
695*404b540aSrobert       fprintf (file,"\tsei\n");
696*404b540aSrobert       ++prologue_size;
697*404b540aSrobert     }
698*404b540aSrobert   if (interrupt_func_p || signal_func_p)
699*404b540aSrobert     {
700*404b540aSrobert       fprintf (file, "\t"
701*404b540aSrobert                AS1 (push,__zero_reg__)   CR_TAB
702*404b540aSrobert                AS1 (push,__tmp_reg__)    CR_TAB
703*404b540aSrobert 	       AS2 (in,__tmp_reg__,__SREG__) CR_TAB
704*404b540aSrobert 	       AS1 (push,__tmp_reg__)    CR_TAB
705*404b540aSrobert 	       AS1 (clr,__zero_reg__)    "\n");
706*404b540aSrobert       prologue_size += 5;
707*404b540aSrobert     }
708*404b540aSrobert   if (main_p)
709*404b540aSrobert     {
710*404b540aSrobert       fprintf (file, ("\t"
711*404b540aSrobert 		      AS1 (ldi,r28) ",lo8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
712*404b540aSrobert 		      AS1 (ldi,r29) ",hi8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
713*404b540aSrobert 		      AS2 (out,__SP_H__,r29)     CR_TAB
714*404b540aSrobert 		      AS2 (out,__SP_L__,r28) "\n"),
715*404b540aSrobert 	       avr_init_stack, size, avr_init_stack, size);
716*404b540aSrobert 
717*404b540aSrobert       prologue_size += 4;
718*404b540aSrobert     }
719*404b540aSrobert   else if (minimize && (frame_pointer_needed || live_seq > 6))
720*404b540aSrobert     {
721*404b540aSrobert       fprintf (file, ("\t"
722*404b540aSrobert 		      AS1 (ldi, r26) ",lo8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
723*404b540aSrobert 		      AS1 (ldi, r27) ",hi8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB), size, size);
724*404b540aSrobert 
725*404b540aSrobert       fputs ((AS2 (ldi,r30,pm_lo8(1f)) CR_TAB
726*404b540aSrobert 	      AS2 (ldi,r31,pm_hi8(1f)) CR_TAB), file);
727*404b540aSrobert 
728*404b540aSrobert       prologue_size += 4;
729*404b540aSrobert 
730*404b540aSrobert       if (AVR_MEGA)
731*404b540aSrobert 	{
732*404b540aSrobert 	  fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
733*404b540aSrobert 		   (18 - live_seq) * 2);
734*404b540aSrobert 	  prologue_size += 2;
735*404b540aSrobert 	}
736*404b540aSrobert       else
737*404b540aSrobert 	{
738*404b540aSrobert 	  fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
739*404b540aSrobert 		   (18 - live_seq) * 2);
740*404b540aSrobert 	  ++prologue_size;
741*404b540aSrobert 	}
742*404b540aSrobert       fputs ("1:\n", file);
743*404b540aSrobert     }
744*404b540aSrobert   else
745*404b540aSrobert     {
746*404b540aSrobert       HARD_REG_SET set;
747*404b540aSrobert 
748*404b540aSrobert       prologue_size += avr_regs_to_save (&set);
749*404b540aSrobert       for (reg = 0; reg < 32; ++reg)
750*404b540aSrobert 	{
751*404b540aSrobert 	  if (TEST_HARD_REG_BIT (set, reg))
752*404b540aSrobert 	    {
753*404b540aSrobert 	      fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
754*404b540aSrobert 	    }
755*404b540aSrobert 	}
756*404b540aSrobert       if (frame_pointer_needed)
757*404b540aSrobert 	{
758*404b540aSrobert 	  fprintf (file, "\t"
759*404b540aSrobert 		   AS1 (push,r28) CR_TAB
760*404b540aSrobert 		   AS1 (push,r29) CR_TAB
761*404b540aSrobert 		   AS2 (in,r28,__SP_L__) CR_TAB
762*404b540aSrobert 		   AS2 (in,r29,__SP_H__) "\n");
763*404b540aSrobert 	  prologue_size += 4;
764*404b540aSrobert 	  if (size)
765*404b540aSrobert 	    {
766*404b540aSrobert 	      fputs ("\t", file);
767*404b540aSrobert 	      prologue_size += out_adj_frame_ptr (file, size);
768*404b540aSrobert 
769*404b540aSrobert 	      if (interrupt_func_p)
770*404b540aSrobert 		{
771*404b540aSrobert 		  prologue_size += out_set_stack_ptr (file, 1, 1);
772*404b540aSrobert 		}
773*404b540aSrobert 	      else if (signal_func_p)
774*404b540aSrobert 		{
775*404b540aSrobert 		  prologue_size += out_set_stack_ptr (file, 0, 0);
776*404b540aSrobert 		}
777*404b540aSrobert 	      else
778*404b540aSrobert 		{
779*404b540aSrobert 		  prologue_size += out_set_stack_ptr (file, -1, -1);
780*404b540aSrobert 		}
781*404b540aSrobert 	    }
782*404b540aSrobert 	}
783*404b540aSrobert     }
784*404b540aSrobert 
785*404b540aSrobert  out:
786*404b540aSrobert   fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
787*404b540aSrobert }
788*404b540aSrobert 
789*404b540aSrobert /* Output function epilogue.  */
790*404b540aSrobert 
791*404b540aSrobert static void
avr_output_function_epilogue(FILE * file,HOST_WIDE_INT size)792*404b540aSrobert avr_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
793*404b540aSrobert {
794*404b540aSrobert   int reg;
795*404b540aSrobert   int interrupt_func_p;
796*404b540aSrobert   int signal_func_p;
797*404b540aSrobert   int main_p;
798*404b540aSrobert   int function_size;
799*404b540aSrobert   int live_seq;
800*404b540aSrobert   int minimize;
801*404b540aSrobert   rtx last = get_last_nonnote_insn ();
802*404b540aSrobert 
803*404b540aSrobert   function_size = jump_tables_size;
804*404b540aSrobert   if (last)
805*404b540aSrobert     {
806*404b540aSrobert       rtx first = get_first_nonnote_insn ();
807*404b540aSrobert       function_size += (INSN_ADDRESSES (INSN_UID (last)) -
808*404b540aSrobert 			INSN_ADDRESSES (INSN_UID (first)));
809*404b540aSrobert       function_size += get_attr_length (last);
810*404b540aSrobert     }
811*404b540aSrobert 
812*404b540aSrobert   fprintf (file, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n", size);
813*404b540aSrobert   epilogue_size = 0;
814*404b540aSrobert 
815*404b540aSrobert   if (avr_naked_function_p (current_function_decl))
816*404b540aSrobert     {
817*404b540aSrobert       fputs ("/* epilogue: naked */\n", file);
818*404b540aSrobert       goto out;
819*404b540aSrobert     }
820*404b540aSrobert 
821*404b540aSrobert   if (last && GET_CODE (last) == BARRIER)
822*404b540aSrobert     {
823*404b540aSrobert       fputs ("/* epilogue: noreturn */\n", file);
824*404b540aSrobert       goto out;
825*404b540aSrobert     }
826*404b540aSrobert 
827*404b540aSrobert   interrupt_func_p = interrupt_function_p (current_function_decl);
828*404b540aSrobert   signal_func_p = signal_function_p (current_function_decl);
829*404b540aSrobert   main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
830*404b540aSrobert   live_seq = sequent_regs_live ();
831*404b540aSrobert   minimize = (TARGET_CALL_PROLOGUES
832*404b540aSrobert 	      && !interrupt_func_p && !signal_func_p && live_seq);
833*404b540aSrobert 
834*404b540aSrobert   if (main_p)
835*404b540aSrobert     {
836*404b540aSrobert       /* Return value from main() is already in the correct registers
837*404b540aSrobert 	 (r25:r24) as the exit() argument.  */
838*404b540aSrobert       if (AVR_MEGA)
839*404b540aSrobert 	{
840*404b540aSrobert 	  fputs ("\t" AS1 (jmp,exit) "\n", file);
841*404b540aSrobert 	  epilogue_size += 2;
842*404b540aSrobert 	}
843*404b540aSrobert       else
844*404b540aSrobert 	{
845*404b540aSrobert 	  fputs ("\t" AS1 (rjmp,exit) "\n", file);
846*404b540aSrobert 	  ++epilogue_size;
847*404b540aSrobert 	}
848*404b540aSrobert     }
849*404b540aSrobert   else if (minimize && (frame_pointer_needed || live_seq > 4))
850*404b540aSrobert     {
851*404b540aSrobert       fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
852*404b540aSrobert       ++epilogue_size;
853*404b540aSrobert       if (frame_pointer_needed)
854*404b540aSrobert 	{
855*404b540aSrobert 	  epilogue_size += out_adj_frame_ptr (file, -size);
856*404b540aSrobert 	}
857*404b540aSrobert       else
858*404b540aSrobert 	{
859*404b540aSrobert 	  fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
860*404b540aSrobert 			  AS2 (in , r29, __SP_H__) CR_TAB));
861*404b540aSrobert 	  epilogue_size += 2;
862*404b540aSrobert 	}
863*404b540aSrobert 
864*404b540aSrobert       if (AVR_MEGA)
865*404b540aSrobert 	{
866*404b540aSrobert 	  fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
867*404b540aSrobert 		   (18 - live_seq) * 2);
868*404b540aSrobert 	  epilogue_size += 2;
869*404b540aSrobert 	}
870*404b540aSrobert       else
871*404b540aSrobert 	{
872*404b540aSrobert 	  fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
873*404b540aSrobert 		   (18 - live_seq) * 2);
874*404b540aSrobert 	  ++epilogue_size;
875*404b540aSrobert 	}
876*404b540aSrobert     }
877*404b540aSrobert   else
878*404b540aSrobert     {
879*404b540aSrobert       HARD_REG_SET set;
880*404b540aSrobert 
881*404b540aSrobert       if (frame_pointer_needed)
882*404b540aSrobert 	{
883*404b540aSrobert 	  if (size)
884*404b540aSrobert 	    {
885*404b540aSrobert 	      fputs ("\t", file);
886*404b540aSrobert 	      epilogue_size += out_adj_frame_ptr (file, -size);
887*404b540aSrobert 
888*404b540aSrobert 	      if (interrupt_func_p || signal_func_p)
889*404b540aSrobert 		{
890*404b540aSrobert 		  epilogue_size += out_set_stack_ptr (file, -1, 0);
891*404b540aSrobert 		}
892*404b540aSrobert 	      else
893*404b540aSrobert 		{
894*404b540aSrobert 		  epilogue_size += out_set_stack_ptr (file, -1, -1);
895*404b540aSrobert 		}
896*404b540aSrobert 	    }
897*404b540aSrobert 	  fprintf (file, "\t"
898*404b540aSrobert 		   AS1 (pop,r29) CR_TAB
899*404b540aSrobert 		   AS1 (pop,r28) "\n");
900*404b540aSrobert 	  epilogue_size += 2;
901*404b540aSrobert 	}
902*404b540aSrobert 
903*404b540aSrobert       epilogue_size += avr_regs_to_save (&set);
904*404b540aSrobert       for (reg = 31; reg >= 0; --reg)
905*404b540aSrobert 	{
906*404b540aSrobert 	  if (TEST_HARD_REG_BIT (set, reg))
907*404b540aSrobert 	    {
908*404b540aSrobert 	      fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
909*404b540aSrobert 	    }
910*404b540aSrobert 	}
911*404b540aSrobert 
912*404b540aSrobert       if (interrupt_func_p || signal_func_p)
913*404b540aSrobert 	{
914*404b540aSrobert 	  fprintf (file, "\t"
915*404b540aSrobert 		   AS1 (pop,__tmp_reg__)      CR_TAB
916*404b540aSrobert 		   AS2 (out,__SREG__,__tmp_reg__) CR_TAB
917*404b540aSrobert 		   AS1 (pop,__tmp_reg__)      CR_TAB
918*404b540aSrobert 		   AS1 (pop,__zero_reg__)     "\n");
919*404b540aSrobert 	  epilogue_size += 4;
920*404b540aSrobert 	  fprintf (file, "\treti\n");
921*404b540aSrobert 	}
922*404b540aSrobert       else
923*404b540aSrobert 	fprintf (file, "\tret\n");
924*404b540aSrobert       ++epilogue_size;
925*404b540aSrobert     }
926*404b540aSrobert 
927*404b540aSrobert  out:
928*404b540aSrobert   fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
929*404b540aSrobert   fprintf (file, "/* function %s size %d (%d) */\n", current_function_name (),
930*404b540aSrobert 	   prologue_size + function_size + epilogue_size, function_size);
931*404b540aSrobert   commands_in_file += prologue_size + function_size + epilogue_size;
932*404b540aSrobert   commands_in_prologues += prologue_size;
933*404b540aSrobert   commands_in_epilogues += epilogue_size;
934*404b540aSrobert }
935*404b540aSrobert 
936*404b540aSrobert 
937*404b540aSrobert /* Return nonzero if X (an RTX) is a legitimate memory address on the target
938*404b540aSrobert    machine for a memory operand of mode MODE.  */
939*404b540aSrobert 
940*404b540aSrobert int
legitimate_address_p(enum machine_mode mode,rtx x,int strict)941*404b540aSrobert legitimate_address_p (enum machine_mode mode, rtx x, int strict)
942*404b540aSrobert {
943*404b540aSrobert   enum reg_class r = NO_REGS;
944*404b540aSrobert 
945*404b540aSrobert   if (TARGET_ALL_DEBUG)
946*404b540aSrobert     {
947*404b540aSrobert       fprintf (stderr, "mode: (%s) %s %s %s %s:",
948*404b540aSrobert 	       GET_MODE_NAME(mode),
949*404b540aSrobert 	       strict ? "(strict)": "",
950*404b540aSrobert 	       reload_completed ? "(reload_completed)": "",
951*404b540aSrobert 	       reload_in_progress ? "(reload_in_progress)": "",
952*404b540aSrobert 	       reg_renumber ? "(reg_renumber)" : "");
953*404b540aSrobert       if (GET_CODE (x) == PLUS
954*404b540aSrobert 	  && REG_P (XEXP (x, 0))
955*404b540aSrobert 	  && GET_CODE (XEXP (x, 1)) == CONST_INT
956*404b540aSrobert 	  && INTVAL (XEXP (x, 1)) >= 0
957*404b540aSrobert 	  && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
958*404b540aSrobert 	  && reg_renumber
959*404b540aSrobert 	  )
960*404b540aSrobert 	fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
961*404b540aSrobert 		 true_regnum (XEXP (x, 0)));
962*404b540aSrobert       debug_rtx (x);
963*404b540aSrobert     }
964*404b540aSrobert   if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
965*404b540aSrobert                     : REG_OK_FOR_BASE_NOSTRICT_P (x)))
966*404b540aSrobert     r = POINTER_REGS;
967*404b540aSrobert   else if (CONSTANT_ADDRESS_P (x))
968*404b540aSrobert     r = ALL_REGS;
969*404b540aSrobert   else if (GET_CODE (x) == PLUS
970*404b540aSrobert            && REG_P (XEXP (x, 0))
971*404b540aSrobert 	   && GET_CODE (XEXP (x, 1)) == CONST_INT
972*404b540aSrobert 	   && INTVAL (XEXP (x, 1)) >= 0)
973*404b540aSrobert     {
974*404b540aSrobert       int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
975*404b540aSrobert       if (fit)
976*404b540aSrobert 	{
977*404b540aSrobert 	  if (! strict
978*404b540aSrobert 	      || REGNO (XEXP (x,0)) == REG_Y
979*404b540aSrobert 	      || REGNO (XEXP (x,0)) == REG_Z)
980*404b540aSrobert 	    r = BASE_POINTER_REGS;
981*404b540aSrobert 	  if (XEXP (x,0) == frame_pointer_rtx
982*404b540aSrobert 	      || XEXP (x,0) == arg_pointer_rtx)
983*404b540aSrobert 	    r = BASE_POINTER_REGS;
984*404b540aSrobert 	}
985*404b540aSrobert       else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
986*404b540aSrobert 	r = POINTER_Y_REGS;
987*404b540aSrobert     }
988*404b540aSrobert   else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
989*404b540aSrobert            && REG_P (XEXP (x, 0))
990*404b540aSrobert            && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
991*404b540aSrobert                : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
992*404b540aSrobert     {
993*404b540aSrobert       r = POINTER_REGS;
994*404b540aSrobert     }
995*404b540aSrobert   if (TARGET_ALL_DEBUG)
996*404b540aSrobert     {
997*404b540aSrobert       fprintf (stderr, "   ret = %c\n", r + '0');
998*404b540aSrobert     }
999*404b540aSrobert   return r == NO_REGS ? 0 : (int)r;
1000*404b540aSrobert }
1001*404b540aSrobert 
1002*404b540aSrobert /* Attempts to replace X with a valid
1003*404b540aSrobert    memory address for an operand of mode MODE  */
1004*404b540aSrobert 
1005*404b540aSrobert rtx
legitimize_address(rtx x,rtx oldx,enum machine_mode mode)1006*404b540aSrobert legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
1007*404b540aSrobert {
1008*404b540aSrobert   x = oldx;
1009*404b540aSrobert   if (TARGET_ALL_DEBUG)
1010*404b540aSrobert     {
1011*404b540aSrobert       fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
1012*404b540aSrobert       debug_rtx (oldx);
1013*404b540aSrobert     }
1014*404b540aSrobert 
1015*404b540aSrobert   if (GET_CODE (oldx) == PLUS
1016*404b540aSrobert       && REG_P (XEXP (oldx,0)))
1017*404b540aSrobert     {
1018*404b540aSrobert       if (REG_P (XEXP (oldx,1)))
1019*404b540aSrobert 	x = force_reg (GET_MODE (oldx), oldx);
1020*404b540aSrobert       else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
1021*404b540aSrobert 	{
1022*404b540aSrobert 	  int offs = INTVAL (XEXP (oldx,1));
1023*404b540aSrobert 	  if (frame_pointer_rtx != XEXP (oldx,0))
1024*404b540aSrobert 	    if (offs > MAX_LD_OFFSET (mode))
1025*404b540aSrobert 	      {
1026*404b540aSrobert 		if (TARGET_ALL_DEBUG)
1027*404b540aSrobert 		  fprintf (stderr, "force_reg (big offset)\n");
1028*404b540aSrobert 		x = force_reg (GET_MODE (oldx), oldx);
1029*404b540aSrobert 	      }
1030*404b540aSrobert 	}
1031*404b540aSrobert     }
1032*404b540aSrobert   return x;
1033*404b540aSrobert }
1034*404b540aSrobert 
1035*404b540aSrobert 
1036*404b540aSrobert /* Return a pointer register name as a string.  */
1037*404b540aSrobert 
1038*404b540aSrobert static const char *
ptrreg_to_str(int regno)1039*404b540aSrobert ptrreg_to_str (int regno)
1040*404b540aSrobert {
1041*404b540aSrobert   switch (regno)
1042*404b540aSrobert     {
1043*404b540aSrobert     case REG_X: return "X";
1044*404b540aSrobert     case REG_Y: return "Y";
1045*404b540aSrobert     case REG_Z: return "Z";
1046*404b540aSrobert     default:
1047*404b540aSrobert       output_operand_lossage ("address operand requires constraint for X, Y, or Z register");
1048*404b540aSrobert     }
1049*404b540aSrobert   return NULL;
1050*404b540aSrobert }
1051*404b540aSrobert 
1052*404b540aSrobert /* Return the condition name as a string.
1053*404b540aSrobert    Used in conditional jump constructing  */
1054*404b540aSrobert 
1055*404b540aSrobert static const char *
cond_string(enum rtx_code code)1056*404b540aSrobert cond_string (enum rtx_code code)
1057*404b540aSrobert {
1058*404b540aSrobert   switch (code)
1059*404b540aSrobert     {
1060*404b540aSrobert     case NE:
1061*404b540aSrobert       return "ne";
1062*404b540aSrobert     case EQ:
1063*404b540aSrobert       return "eq";
1064*404b540aSrobert     case GE:
1065*404b540aSrobert       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1066*404b540aSrobert 	return "pl";
1067*404b540aSrobert       else
1068*404b540aSrobert 	return "ge";
1069*404b540aSrobert     case LT:
1070*404b540aSrobert       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1071*404b540aSrobert 	return "mi";
1072*404b540aSrobert       else
1073*404b540aSrobert 	return "lt";
1074*404b540aSrobert     case GEU:
1075*404b540aSrobert       return "sh";
1076*404b540aSrobert     case LTU:
1077*404b540aSrobert       return "lo";
1078*404b540aSrobert     default:
1079*404b540aSrobert       gcc_unreachable ();
1080*404b540aSrobert     }
1081*404b540aSrobert }
1082*404b540aSrobert 
1083*404b540aSrobert /* Output ADDR to FILE as address.  */
1084*404b540aSrobert 
1085*404b540aSrobert void
print_operand_address(FILE * file,rtx addr)1086*404b540aSrobert print_operand_address (FILE *file, rtx addr)
1087*404b540aSrobert {
1088*404b540aSrobert   switch (GET_CODE (addr))
1089*404b540aSrobert     {
1090*404b540aSrobert     case REG:
1091*404b540aSrobert       fprintf (file, ptrreg_to_str (REGNO (addr)));
1092*404b540aSrobert       break;
1093*404b540aSrobert 
1094*404b540aSrobert     case PRE_DEC:
1095*404b540aSrobert       fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1096*404b540aSrobert       break;
1097*404b540aSrobert 
1098*404b540aSrobert     case POST_INC:
1099*404b540aSrobert       fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1100*404b540aSrobert       break;
1101*404b540aSrobert 
1102*404b540aSrobert     default:
1103*404b540aSrobert       if (CONSTANT_ADDRESS_P (addr)
1104*404b540aSrobert 	  && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
1105*404b540aSrobert 	      || GET_CODE (addr) == LABEL_REF))
1106*404b540aSrobert 	{
1107*404b540aSrobert 	  fprintf (file, "pm(");
1108*404b540aSrobert 	  output_addr_const (file,addr);
1109*404b540aSrobert 	  fprintf (file ,")");
1110*404b540aSrobert 	}
1111*404b540aSrobert       else
1112*404b540aSrobert 	output_addr_const (file, addr);
1113*404b540aSrobert     }
1114*404b540aSrobert }
1115*404b540aSrobert 
1116*404b540aSrobert 
1117*404b540aSrobert /* Output X as assembler operand to file FILE.  */
1118*404b540aSrobert 
1119*404b540aSrobert void
print_operand(FILE * file,rtx x,int code)1120*404b540aSrobert print_operand (FILE *file, rtx x, int code)
1121*404b540aSrobert {
1122*404b540aSrobert   int abcd = 0;
1123*404b540aSrobert 
1124*404b540aSrobert   if (code >= 'A' && code <= 'D')
1125*404b540aSrobert     abcd = code - 'A';
1126*404b540aSrobert 
1127*404b540aSrobert   if (code == '~')
1128*404b540aSrobert     {
1129*404b540aSrobert       if (!AVR_MEGA)
1130*404b540aSrobert 	fputc ('r', file);
1131*404b540aSrobert     }
1132*404b540aSrobert   else if (REG_P (x))
1133*404b540aSrobert     {
1134*404b540aSrobert       if (x == zero_reg_rtx)
1135*404b540aSrobert 	fprintf (file, "__zero_reg__");
1136*404b540aSrobert       else
1137*404b540aSrobert 	fprintf (file, reg_names[true_regnum (x) + abcd]);
1138*404b540aSrobert     }
1139*404b540aSrobert   else if (GET_CODE (x) == CONST_INT)
1140*404b540aSrobert     fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
1141*404b540aSrobert   else if (GET_CODE (x) == MEM)
1142*404b540aSrobert     {
1143*404b540aSrobert       rtx addr = XEXP (x,0);
1144*404b540aSrobert 
1145*404b540aSrobert       if (CONSTANT_P (addr) && abcd)
1146*404b540aSrobert 	{
1147*404b540aSrobert 	  fputc ('(', file);
1148*404b540aSrobert 	  output_address (addr);
1149*404b540aSrobert 	  fprintf (file, ")+%d", abcd);
1150*404b540aSrobert 	}
1151*404b540aSrobert       else if (code == 'o')
1152*404b540aSrobert 	{
1153*404b540aSrobert 	  if (GET_CODE (addr) != PLUS)
1154*404b540aSrobert 	    fatal_insn ("bad address, not (reg+disp):", addr);
1155*404b540aSrobert 
1156*404b540aSrobert 	  print_operand (file, XEXP (addr, 1), 0);
1157*404b540aSrobert 	}
1158*404b540aSrobert       else if (code == 'p' || code == 'r')
1159*404b540aSrobert         {
1160*404b540aSrobert           if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
1161*404b540aSrobert             fatal_insn ("bad address, not post_inc or pre_dec:", addr);
1162*404b540aSrobert 
1163*404b540aSrobert           if (code == 'p')
1164*404b540aSrobert             print_operand_address (file, XEXP (addr, 0));  /* X, Y, Z */
1165*404b540aSrobert           else
1166*404b540aSrobert             print_operand (file, XEXP (addr, 0), 0);  /* r26, r28, r30 */
1167*404b540aSrobert         }
1168*404b540aSrobert       else if (GET_CODE (addr) == PLUS)
1169*404b540aSrobert 	{
1170*404b540aSrobert 	  print_operand_address (file, XEXP (addr,0));
1171*404b540aSrobert 	  if (REGNO (XEXP (addr, 0)) == REG_X)
1172*404b540aSrobert 	    fatal_insn ("internal compiler error.  Bad address:"
1173*404b540aSrobert 			,addr);
1174*404b540aSrobert 	  fputc ('+', file);
1175*404b540aSrobert 	  print_operand (file, XEXP (addr,1), code);
1176*404b540aSrobert 	}
1177*404b540aSrobert       else
1178*404b540aSrobert 	print_operand_address (file, addr);
1179*404b540aSrobert     }
1180*404b540aSrobert   else if (GET_CODE (x) == CONST_DOUBLE)
1181*404b540aSrobert     {
1182*404b540aSrobert       long val;
1183*404b540aSrobert       REAL_VALUE_TYPE rv;
1184*404b540aSrobert       if (GET_MODE (x) != SFmode)
1185*404b540aSrobert 	fatal_insn ("internal compiler error.  Unknown mode:", x);
1186*404b540aSrobert       REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1187*404b540aSrobert       REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1188*404b540aSrobert       fprintf (file, "0x%lx", val);
1189*404b540aSrobert     }
1190*404b540aSrobert   else if (code == 'j')
1191*404b540aSrobert     fputs (cond_string (GET_CODE (x)), file);
1192*404b540aSrobert   else if (code == 'k')
1193*404b540aSrobert     fputs (cond_string (reverse_condition (GET_CODE (x))), file);
1194*404b540aSrobert   else
1195*404b540aSrobert     print_operand_address (file, x);
1196*404b540aSrobert }
1197*404b540aSrobert 
1198*404b540aSrobert /* Recognize operand OP of mode MODE used in call instructions.  */
1199*404b540aSrobert 
1200*404b540aSrobert int
call_insn_operand(rtx op,enum machine_mode mode ATTRIBUTE_UNUSED)1201*404b540aSrobert call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1202*404b540aSrobert {
1203*404b540aSrobert   if (GET_CODE (op) == MEM)
1204*404b540aSrobert     {
1205*404b540aSrobert       rtx inside = XEXP (op, 0);
1206*404b540aSrobert       if (register_operand (inside, Pmode))
1207*404b540aSrobert         return 1;
1208*404b540aSrobert       if (CONSTANT_ADDRESS_P (inside))
1209*404b540aSrobert         return 1;
1210*404b540aSrobert     }
1211*404b540aSrobert   return 0;
1212*404b540aSrobert }
1213*404b540aSrobert 
1214*404b540aSrobert /* Update the condition code in the INSN.  */
1215*404b540aSrobert 
1216*404b540aSrobert void
notice_update_cc(rtx body ATTRIBUTE_UNUSED,rtx insn)1217*404b540aSrobert notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
1218*404b540aSrobert {
1219*404b540aSrobert   rtx set;
1220*404b540aSrobert 
1221*404b540aSrobert   switch (get_attr_cc (insn))
1222*404b540aSrobert     {
1223*404b540aSrobert     case CC_NONE:
1224*404b540aSrobert       /* Insn does not affect CC at all.  */
1225*404b540aSrobert       break;
1226*404b540aSrobert 
1227*404b540aSrobert     case CC_SET_N:
1228*404b540aSrobert       CC_STATUS_INIT;
1229*404b540aSrobert       break;
1230*404b540aSrobert 
1231*404b540aSrobert     case CC_SET_ZN:
1232*404b540aSrobert       set = single_set (insn);
1233*404b540aSrobert       CC_STATUS_INIT;
1234*404b540aSrobert       if (set)
1235*404b540aSrobert 	{
1236*404b540aSrobert 	  cc_status.flags |= CC_NO_OVERFLOW;
1237*404b540aSrobert 	  cc_status.value1 = SET_DEST (set);
1238*404b540aSrobert 	}
1239*404b540aSrobert       break;
1240*404b540aSrobert 
1241*404b540aSrobert     case CC_SET_CZN:
1242*404b540aSrobert       /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1243*404b540aSrobert          The V flag may or may not be known but that's ok because
1244*404b540aSrobert          alter_cond will change tests to use EQ/NE.  */
1245*404b540aSrobert       set = single_set (insn);
1246*404b540aSrobert       CC_STATUS_INIT;
1247*404b540aSrobert       if (set)
1248*404b540aSrobert 	{
1249*404b540aSrobert 	  cc_status.value1 = SET_DEST (set);
1250*404b540aSrobert 	  cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1251*404b540aSrobert 	}
1252*404b540aSrobert       break;
1253*404b540aSrobert 
1254*404b540aSrobert     case CC_COMPARE:
1255*404b540aSrobert       set = single_set (insn);
1256*404b540aSrobert       CC_STATUS_INIT;
1257*404b540aSrobert       if (set)
1258*404b540aSrobert 	cc_status.value1 = SET_SRC (set);
1259*404b540aSrobert       break;
1260*404b540aSrobert 
1261*404b540aSrobert     case CC_CLOBBER:
1262*404b540aSrobert       /* Insn doesn't leave CC in a usable state.  */
1263*404b540aSrobert       CC_STATUS_INIT;
1264*404b540aSrobert 
1265*404b540aSrobert       /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1266*404b540aSrobert       set = single_set (insn);
1267*404b540aSrobert       if (set)
1268*404b540aSrobert 	{
1269*404b540aSrobert 	  rtx src = SET_SRC (set);
1270*404b540aSrobert 
1271*404b540aSrobert 	  if (GET_CODE (src) == ASHIFTRT
1272*404b540aSrobert 	      && GET_MODE (src) == QImode)
1273*404b540aSrobert 	    {
1274*404b540aSrobert 	      rtx x = XEXP (src, 1);
1275*404b540aSrobert 
1276*404b540aSrobert 	      if (GET_CODE (x) == CONST_INT
1277*404b540aSrobert 		  && INTVAL (x) > 0
1278*404b540aSrobert 		  && INTVAL (x) != 6)
1279*404b540aSrobert 		{
1280*404b540aSrobert 		  cc_status.value1 = SET_DEST (set);
1281*404b540aSrobert 		  cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1282*404b540aSrobert 		}
1283*404b540aSrobert 	    }
1284*404b540aSrobert 	}
1285*404b540aSrobert       break;
1286*404b540aSrobert     }
1287*404b540aSrobert }
1288*404b540aSrobert 
1289*404b540aSrobert /* Return maximum number of consecutive registers of
1290*404b540aSrobert    class CLASS needed to hold a value of mode MODE.  */
1291*404b540aSrobert 
1292*404b540aSrobert int
class_max_nregs(enum reg_class class ATTRIBUTE_UNUSED,enum machine_mode mode)1293*404b540aSrobert class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,enum machine_mode mode)
1294*404b540aSrobert {
1295*404b540aSrobert   return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1296*404b540aSrobert }
1297*404b540aSrobert 
1298*404b540aSrobert /* Choose mode for jump insn:
1299*404b540aSrobert    1 - relative jump in range -63 <= x <= 62 ;
1300*404b540aSrobert    2 - relative jump in range -2046 <= x <= 2045 ;
1301*404b540aSrobert    3 - absolute jump (only for ATmega[16]03).  */
1302*404b540aSrobert 
1303*404b540aSrobert int
avr_jump_mode(rtx x,rtx insn)1304*404b540aSrobert avr_jump_mode (rtx x, rtx insn)
1305*404b540aSrobert {
1306*404b540aSrobert   int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1307*404b540aSrobert 					    ? XEXP (x, 0) : x));
1308*404b540aSrobert   int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1309*404b540aSrobert   int jump_distance = cur_addr - dest_addr;
1310*404b540aSrobert 
1311*404b540aSrobert   if (-63 <= jump_distance && jump_distance <= 62)
1312*404b540aSrobert     return 1;
1313*404b540aSrobert   else if (-2046 <= jump_distance && jump_distance <= 2045)
1314*404b540aSrobert     return 2;
1315*404b540aSrobert   else if (AVR_MEGA)
1316*404b540aSrobert     return 3;
1317*404b540aSrobert 
1318*404b540aSrobert   return 2;
1319*404b540aSrobert }
1320*404b540aSrobert 
1321*404b540aSrobert /* return an AVR condition jump commands.
1322*404b540aSrobert    X is a comparison RTX.
1323*404b540aSrobert    LEN is a number returned by avr_jump_mode function.
1324*404b540aSrobert    if REVERSE nonzero then condition code in X must be reversed.  */
1325*404b540aSrobert 
1326*404b540aSrobert const char *
ret_cond_branch(rtx x,int len,int reverse)1327*404b540aSrobert ret_cond_branch (rtx x, int len, int reverse)
1328*404b540aSrobert {
1329*404b540aSrobert   RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1330*404b540aSrobert 
1331*404b540aSrobert   switch (cond)
1332*404b540aSrobert     {
1333*404b540aSrobert     case GT:
1334*404b540aSrobert       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1335*404b540aSrobert 	return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1336*404b540aSrobert 			    AS1 (brpl,%0)) :
1337*404b540aSrobert 		len == 2 ? (AS1 (breq,.+4) CR_TAB
1338*404b540aSrobert 			    AS1 (brmi,.+2) CR_TAB
1339*404b540aSrobert 			    AS1 (rjmp,%0)) :
1340*404b540aSrobert 		(AS1 (breq,.+6) CR_TAB
1341*404b540aSrobert 		 AS1 (brmi,.+4) CR_TAB
1342*404b540aSrobert 		 AS1 (jmp,%0)));
1343*404b540aSrobert 
1344*404b540aSrobert       else
1345*404b540aSrobert 	return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1346*404b540aSrobert 			    AS1 (brge,%0)) :
1347*404b540aSrobert 		len == 2 ? (AS1 (breq,.+4) CR_TAB
1348*404b540aSrobert 			    AS1 (brlt,.+2) CR_TAB
1349*404b540aSrobert 			    AS1 (rjmp,%0)) :
1350*404b540aSrobert 		(AS1 (breq,.+6) CR_TAB
1351*404b540aSrobert 		 AS1 (brlt,.+4) CR_TAB
1352*404b540aSrobert 		 AS1 (jmp,%0)));
1353*404b540aSrobert     case GTU:
1354*404b540aSrobert       return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1355*404b540aSrobert                           AS1 (brsh,%0)) :
1356*404b540aSrobert               len == 2 ? (AS1 (breq,.+4) CR_TAB
1357*404b540aSrobert                           AS1 (brlo,.+2) CR_TAB
1358*404b540aSrobert                           AS1 (rjmp,%0)) :
1359*404b540aSrobert               (AS1 (breq,.+6) CR_TAB
1360*404b540aSrobert                AS1 (brlo,.+4) CR_TAB
1361*404b540aSrobert                AS1 (jmp,%0)));
1362*404b540aSrobert     case LE:
1363*404b540aSrobert       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1364*404b540aSrobert 	return (len == 1 ? (AS1 (breq,%0) CR_TAB
1365*404b540aSrobert 			    AS1 (brmi,%0)) :
1366*404b540aSrobert 		len == 2 ? (AS1 (breq,.+2) CR_TAB
1367*404b540aSrobert 			    AS1 (brpl,.+2) CR_TAB
1368*404b540aSrobert 			    AS1 (rjmp,%0)) :
1369*404b540aSrobert 		(AS1 (breq,.+2) CR_TAB
1370*404b540aSrobert 		 AS1 (brpl,.+4) CR_TAB
1371*404b540aSrobert 		 AS1 (jmp,%0)));
1372*404b540aSrobert       else
1373*404b540aSrobert 	return (len == 1 ? (AS1 (breq,%0) CR_TAB
1374*404b540aSrobert 			    AS1 (brlt,%0)) :
1375*404b540aSrobert 		len == 2 ? (AS1 (breq,.+2) CR_TAB
1376*404b540aSrobert 			    AS1 (brge,.+2) CR_TAB
1377*404b540aSrobert 			    AS1 (rjmp,%0)) :
1378*404b540aSrobert 		(AS1 (breq,.+2) CR_TAB
1379*404b540aSrobert 		 AS1 (brge,.+4) CR_TAB
1380*404b540aSrobert 		 AS1 (jmp,%0)));
1381*404b540aSrobert     case LEU:
1382*404b540aSrobert       return (len == 1 ? (AS1 (breq,%0) CR_TAB
1383*404b540aSrobert                           AS1 (brlo,%0)) :
1384*404b540aSrobert               len == 2 ? (AS1 (breq,.+2) CR_TAB
1385*404b540aSrobert                           AS1 (brsh,.+2) CR_TAB
1386*404b540aSrobert 			  AS1 (rjmp,%0)) :
1387*404b540aSrobert               (AS1 (breq,.+2) CR_TAB
1388*404b540aSrobert                AS1 (brsh,.+4) CR_TAB
1389*404b540aSrobert 	       AS1 (jmp,%0)));
1390*404b540aSrobert     default:
1391*404b540aSrobert       if (reverse)
1392*404b540aSrobert 	{
1393*404b540aSrobert 	  switch (len)
1394*404b540aSrobert 	    {
1395*404b540aSrobert 	    case 1:
1396*404b540aSrobert 	      return AS1 (br%k1,%0);
1397*404b540aSrobert 	    case 2:
1398*404b540aSrobert 	      return (AS1 (br%j1,.+2) CR_TAB
1399*404b540aSrobert 		      AS1 (rjmp,%0));
1400*404b540aSrobert 	    default:
1401*404b540aSrobert 	      return (AS1 (br%j1,.+4) CR_TAB
1402*404b540aSrobert 		      AS1 (jmp,%0));
1403*404b540aSrobert 	    }
1404*404b540aSrobert 	}
1405*404b540aSrobert 	else
1406*404b540aSrobert 	  {
1407*404b540aSrobert 	    switch (len)
1408*404b540aSrobert 	      {
1409*404b540aSrobert 	      case 1:
1410*404b540aSrobert 		return AS1 (br%j1,%0);
1411*404b540aSrobert 	      case 2:
1412*404b540aSrobert 		return (AS1 (br%k1,.+2) CR_TAB
1413*404b540aSrobert 			AS1 (rjmp,%0));
1414*404b540aSrobert 	      default:
1415*404b540aSrobert 		return (AS1 (br%k1,.+4) CR_TAB
1416*404b540aSrobert 			AS1 (jmp,%0));
1417*404b540aSrobert 	      }
1418*404b540aSrobert 	  }
1419*404b540aSrobert     }
1420*404b540aSrobert   return "";
1421*404b540aSrobert }
1422*404b540aSrobert 
1423*404b540aSrobert /* Predicate function for immediate operand which fits to byte (8bit) */
1424*404b540aSrobert 
1425*404b540aSrobert int
byte_immediate_operand(rtx op,enum machine_mode mode ATTRIBUTE_UNUSED)1426*404b540aSrobert byte_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1427*404b540aSrobert {
1428*404b540aSrobert   return (GET_CODE (op) == CONST_INT
1429*404b540aSrobert           && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1430*404b540aSrobert }
1431*404b540aSrobert 
1432*404b540aSrobert /* Output all insn addresses and their sizes into the assembly language
1433*404b540aSrobert    output file.  This is helpful for debugging whether the length attributes
1434*404b540aSrobert    in the md file are correct.
1435*404b540aSrobert    Output insn cost for next insn.  */
1436*404b540aSrobert 
1437*404b540aSrobert void
final_prescan_insn(rtx insn,rtx * operand ATTRIBUTE_UNUSED,int num_operands ATTRIBUTE_UNUSED)1438*404b540aSrobert final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
1439*404b540aSrobert 		    int num_operands ATTRIBUTE_UNUSED)
1440*404b540aSrobert {
1441*404b540aSrobert   int uid = INSN_UID (insn);
1442*404b540aSrobert 
1443*404b540aSrobert   if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1444*404b540aSrobert     {
1445*404b540aSrobert       fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1446*404b540aSrobert 	       INSN_ADDRESSES (uid),
1447*404b540aSrobert                INSN_ADDRESSES (uid) - last_insn_address,
1448*404b540aSrobert 	       rtx_cost (PATTERN (insn), INSN));
1449*404b540aSrobert     }
1450*404b540aSrobert   last_insn_address = INSN_ADDRESSES (uid);
1451*404b540aSrobert }
1452*404b540aSrobert 
1453*404b540aSrobert /* Return 0 if undefined, 1 if always true or always false.  */
1454*404b540aSrobert 
1455*404b540aSrobert int
avr_simplify_comparison_p(enum machine_mode mode,RTX_CODE operator,rtx x)1456*404b540aSrobert avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE operator, rtx x)
1457*404b540aSrobert {
1458*404b540aSrobert   unsigned int max = (mode == QImode ? 0xff :
1459*404b540aSrobert                       mode == HImode ? 0xffff :
1460*404b540aSrobert                       mode == SImode ? 0xffffffff : 0);
1461*404b540aSrobert   if (max && operator && GET_CODE (x) == CONST_INT)
1462*404b540aSrobert     {
1463*404b540aSrobert       if (unsigned_condition (operator) != operator)
1464*404b540aSrobert 	max >>= 1;
1465*404b540aSrobert 
1466*404b540aSrobert       if (max != (INTVAL (x) & max)
1467*404b540aSrobert 	  && INTVAL (x) != 0xff)
1468*404b540aSrobert 	return 1;
1469*404b540aSrobert     }
1470*404b540aSrobert   return 0;
1471*404b540aSrobert }
1472*404b540aSrobert 
1473*404b540aSrobert 
1474*404b540aSrobert /* Returns nonzero if REGNO is the number of a hard
1475*404b540aSrobert    register in which function arguments are sometimes passed.  */
1476*404b540aSrobert 
1477*404b540aSrobert int
function_arg_regno_p(int r)1478*404b540aSrobert function_arg_regno_p(int r)
1479*404b540aSrobert {
1480*404b540aSrobert   return (r >= 8 && r <= 25);
1481*404b540aSrobert }
1482*404b540aSrobert 
1483*404b540aSrobert /* Initializing the variable cum for the state at the beginning
1484*404b540aSrobert    of the argument list.  */
1485*404b540aSrobert 
1486*404b540aSrobert void
init_cumulative_args(CUMULATIVE_ARGS * cum,tree fntype,rtx libname,tree fndecl ATTRIBUTE_UNUSED)1487*404b540aSrobert init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
1488*404b540aSrobert 		      tree fndecl ATTRIBUTE_UNUSED)
1489*404b540aSrobert {
1490*404b540aSrobert   cum->nregs = 18;
1491*404b540aSrobert   cum->regno = FIRST_CUM_REG;
1492*404b540aSrobert   if (!libname && fntype)
1493*404b540aSrobert     {
1494*404b540aSrobert       int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1495*404b540aSrobert                     && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1496*404b540aSrobert                         != void_type_node));
1497*404b540aSrobert       if (stdarg)
1498*404b540aSrobert         cum->nregs = 0;
1499*404b540aSrobert     }
1500*404b540aSrobert }
1501*404b540aSrobert 
1502*404b540aSrobert /* Returns the number of registers to allocate for a function argument.  */
1503*404b540aSrobert 
1504*404b540aSrobert static int
avr_num_arg_regs(enum machine_mode mode,tree type)1505*404b540aSrobert avr_num_arg_regs (enum machine_mode mode, tree type)
1506*404b540aSrobert {
1507*404b540aSrobert   int size;
1508*404b540aSrobert 
1509*404b540aSrobert   if (mode == BLKmode)
1510*404b540aSrobert     size = int_size_in_bytes (type);
1511*404b540aSrobert   else
1512*404b540aSrobert     size = GET_MODE_SIZE (mode);
1513*404b540aSrobert 
1514*404b540aSrobert   /* Align all function arguments to start in even-numbered registers.
1515*404b540aSrobert      Odd-sized arguments leave holes above them.  */
1516*404b540aSrobert 
1517*404b540aSrobert   return (size + 1) & ~1;
1518*404b540aSrobert }
1519*404b540aSrobert 
1520*404b540aSrobert /* Controls whether a function argument is passed
1521*404b540aSrobert    in a register, and which register.  */
1522*404b540aSrobert 
1523*404b540aSrobert rtx
function_arg(CUMULATIVE_ARGS * cum,enum machine_mode mode,tree type,int named ATTRIBUTE_UNUSED)1524*404b540aSrobert function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1525*404b540aSrobert 	      int named ATTRIBUTE_UNUSED)
1526*404b540aSrobert {
1527*404b540aSrobert   int bytes = avr_num_arg_regs (mode, type);
1528*404b540aSrobert 
1529*404b540aSrobert   if (cum->nregs && bytes <= cum->nregs)
1530*404b540aSrobert     return gen_rtx_REG (mode, cum->regno - bytes);
1531*404b540aSrobert 
1532*404b540aSrobert   return NULL_RTX;
1533*404b540aSrobert }
1534*404b540aSrobert 
1535*404b540aSrobert /* Update the summarizer variable CUM to advance past an argument
1536*404b540aSrobert    in the argument list.  */
1537*404b540aSrobert 
1538*404b540aSrobert void
function_arg_advance(CUMULATIVE_ARGS * cum,enum machine_mode mode,tree type,int named ATTRIBUTE_UNUSED)1539*404b540aSrobert function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1540*404b540aSrobert 		      int named ATTRIBUTE_UNUSED)
1541*404b540aSrobert {
1542*404b540aSrobert   int bytes = avr_num_arg_regs (mode, type);
1543*404b540aSrobert 
1544*404b540aSrobert   cum->nregs -= bytes;
1545*404b540aSrobert   cum->regno -= bytes;
1546*404b540aSrobert 
1547*404b540aSrobert   if (cum->nregs <= 0)
1548*404b540aSrobert     {
1549*404b540aSrobert       cum->nregs = 0;
1550*404b540aSrobert       cum->regno = FIRST_CUM_REG;
1551*404b540aSrobert     }
1552*404b540aSrobert }
1553*404b540aSrobert 
1554*404b540aSrobert /***********************************************************************
1555*404b540aSrobert   Functions for outputting various mov's for a various modes
1556*404b540aSrobert ************************************************************************/
1557*404b540aSrobert const char *
output_movqi(rtx insn,rtx operands[],int * l)1558*404b540aSrobert output_movqi (rtx insn, rtx operands[], int *l)
1559*404b540aSrobert {
1560*404b540aSrobert   int dummy;
1561*404b540aSrobert   rtx dest = operands[0];
1562*404b540aSrobert   rtx src = operands[1];
1563*404b540aSrobert   int *real_l = l;
1564*404b540aSrobert 
1565*404b540aSrobert   if (!l)
1566*404b540aSrobert     l = &dummy;
1567*404b540aSrobert 
1568*404b540aSrobert   *l = 1;
1569*404b540aSrobert 
1570*404b540aSrobert   if (register_operand (dest, QImode))
1571*404b540aSrobert     {
1572*404b540aSrobert       if (register_operand (src, QImode)) /* mov r,r */
1573*404b540aSrobert 	{
1574*404b540aSrobert 	  if (test_hard_reg_class (STACK_REG, dest))
1575*404b540aSrobert 	    return AS2 (out,%0,%1);
1576*404b540aSrobert 	  else if (test_hard_reg_class (STACK_REG, src))
1577*404b540aSrobert 	    return AS2 (in,%0,%1);
1578*404b540aSrobert 
1579*404b540aSrobert 	  return AS2 (mov,%0,%1);
1580*404b540aSrobert 	}
1581*404b540aSrobert       else if (CONSTANT_P (src))
1582*404b540aSrobert 	{
1583*404b540aSrobert 	  if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1584*404b540aSrobert 	    return AS2 (ldi,%0,lo8(%1));
1585*404b540aSrobert 
1586*404b540aSrobert 	  if (GET_CODE (src) == CONST_INT)
1587*404b540aSrobert 	    {
1588*404b540aSrobert 	      if (src == const0_rtx) /* mov r,L */
1589*404b540aSrobert 		return AS1 (clr,%0);
1590*404b540aSrobert 	      else if (src == const1_rtx)
1591*404b540aSrobert 		{
1592*404b540aSrobert 		  *l = 2;
1593*404b540aSrobert 		  return (AS1 (clr,%0) CR_TAB
1594*404b540aSrobert 			  AS1 (inc,%0));
1595*404b540aSrobert 		}
1596*404b540aSrobert 	      else if (src == constm1_rtx)
1597*404b540aSrobert 		{
1598*404b540aSrobert 		  /* Immediate constants -1 to any register */
1599*404b540aSrobert 		  *l = 2;
1600*404b540aSrobert 		  return (AS1 (clr,%0) CR_TAB
1601*404b540aSrobert 			  AS1 (dec,%0));
1602*404b540aSrobert 		}
1603*404b540aSrobert 	      else
1604*404b540aSrobert 		{
1605*404b540aSrobert 		  int bit_nr = exact_log2 (INTVAL (src));
1606*404b540aSrobert 
1607*404b540aSrobert 		  if (bit_nr >= 0)
1608*404b540aSrobert 		    {
1609*404b540aSrobert 		      *l = 3;
1610*404b540aSrobert 		      if (!real_l)
1611*404b540aSrobert 			output_asm_insn ((AS1 (clr,%0) CR_TAB
1612*404b540aSrobert 					  "set"), operands);
1613*404b540aSrobert 		      if (!real_l)
1614*404b540aSrobert 			avr_output_bld (operands, bit_nr);
1615*404b540aSrobert 
1616*404b540aSrobert 		      return "";
1617*404b540aSrobert 		    }
1618*404b540aSrobert 		}
1619*404b540aSrobert 	    }
1620*404b540aSrobert 
1621*404b540aSrobert 	  /* Last resort, larger than loading from memory.  */
1622*404b540aSrobert 	  *l = 4;
1623*404b540aSrobert 	  return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1624*404b540aSrobert 		  AS2 (ldi,r31,lo8(%1))     CR_TAB
1625*404b540aSrobert 		  AS2 (mov,%0,r31)          CR_TAB
1626*404b540aSrobert 		  AS2 (mov,r31,__tmp_reg__));
1627*404b540aSrobert 	}
1628*404b540aSrobert       else if (GET_CODE (src) == MEM)
1629*404b540aSrobert 	return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1630*404b540aSrobert     }
1631*404b540aSrobert   else if (GET_CODE (dest) == MEM)
1632*404b540aSrobert     {
1633*404b540aSrobert       const char *template;
1634*404b540aSrobert 
1635*404b540aSrobert       if (src == const0_rtx)
1636*404b540aSrobert 	operands[1] = zero_reg_rtx;
1637*404b540aSrobert 
1638*404b540aSrobert       template = out_movqi_mr_r (insn, operands, real_l);
1639*404b540aSrobert 
1640*404b540aSrobert       if (!real_l)
1641*404b540aSrobert 	output_asm_insn (template, operands);
1642*404b540aSrobert 
1643*404b540aSrobert       operands[1] = src;
1644*404b540aSrobert     }
1645*404b540aSrobert   return "";
1646*404b540aSrobert }
1647*404b540aSrobert 
1648*404b540aSrobert 
1649*404b540aSrobert const char *
output_movhi(rtx insn,rtx operands[],int * l)1650*404b540aSrobert output_movhi (rtx insn, rtx operands[], int *l)
1651*404b540aSrobert {
1652*404b540aSrobert   int dummy;
1653*404b540aSrobert   rtx dest = operands[0];
1654*404b540aSrobert   rtx src = operands[1];
1655*404b540aSrobert   int *real_l = l;
1656*404b540aSrobert 
1657*404b540aSrobert   if (!l)
1658*404b540aSrobert     l = &dummy;
1659*404b540aSrobert 
1660*404b540aSrobert   if (register_operand (dest, HImode))
1661*404b540aSrobert     {
1662*404b540aSrobert       if (register_operand (src, HImode)) /* mov r,r */
1663*404b540aSrobert 	{
1664*404b540aSrobert 	  if (test_hard_reg_class (STACK_REG, dest))
1665*404b540aSrobert 	    {
1666*404b540aSrobert 	      if (TARGET_TINY_STACK)
1667*404b540aSrobert 		{
1668*404b540aSrobert 		  *l = 1;
1669*404b540aSrobert 		  return AS2 (out,__SP_L__,%A1);
1670*404b540aSrobert 		}
1671*404b540aSrobert 	      else if (TARGET_NO_INTERRUPTS)
1672*404b540aSrobert 		{
1673*404b540aSrobert 		  *l = 2;
1674*404b540aSrobert 		  return (AS2 (out,__SP_H__,%B1) CR_TAB
1675*404b540aSrobert 			  AS2 (out,__SP_L__,%A1));
1676*404b540aSrobert 		}
1677*404b540aSrobert 
1678*404b540aSrobert 	      *l = 5;
1679*404b540aSrobert 	      return (AS2 (in,__tmp_reg__,__SREG__)  CR_TAB
1680*404b540aSrobert 		      "cli"                          CR_TAB
1681*404b540aSrobert 		      AS2 (out,__SP_H__,%B1)         CR_TAB
1682*404b540aSrobert 		      AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1683*404b540aSrobert 		      AS2 (out,__SP_L__,%A1));
1684*404b540aSrobert 	    }
1685*404b540aSrobert 	  else if (test_hard_reg_class (STACK_REG, src))
1686*404b540aSrobert 	    {
1687*404b540aSrobert 	      *l = 2;
1688*404b540aSrobert 	      return (AS2 (in,%A0,__SP_L__) CR_TAB
1689*404b540aSrobert 		      AS2 (in,%B0,__SP_H__));
1690*404b540aSrobert 	    }
1691*404b540aSrobert 
1692*404b540aSrobert 	  if (AVR_HAVE_MOVW)
1693*404b540aSrobert 	    {
1694*404b540aSrobert 	      *l = 1;
1695*404b540aSrobert 	      return (AS2 (movw,%0,%1));
1696*404b540aSrobert 	    }
1697*404b540aSrobert 
1698*404b540aSrobert 	  if (true_regnum (dest) > true_regnum (src))
1699*404b540aSrobert 	    {
1700*404b540aSrobert 	      *l = 2;
1701*404b540aSrobert 	      return (AS2 (mov,%B0,%B1) CR_TAB
1702*404b540aSrobert 		      AS2 (mov,%A0,%A1));
1703*404b540aSrobert 	    }
1704*404b540aSrobert 	  else
1705*404b540aSrobert 	    {
1706*404b540aSrobert 	      *l = 2;
1707*404b540aSrobert 	      return (AS2 (mov,%A0,%A1) CR_TAB
1708*404b540aSrobert 		      AS2 (mov,%B0,%B1));
1709*404b540aSrobert 	    }
1710*404b540aSrobert 	}
1711*404b540aSrobert       else if (CONSTANT_P (src))
1712*404b540aSrobert 	{
1713*404b540aSrobert 	  if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1714*404b540aSrobert 	    {
1715*404b540aSrobert 	      *l = 2;
1716*404b540aSrobert 	      return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1717*404b540aSrobert 		      AS2 (ldi,%B0,hi8(%1)));
1718*404b540aSrobert 	    }
1719*404b540aSrobert 
1720*404b540aSrobert 	  if (GET_CODE (src) == CONST_INT)
1721*404b540aSrobert 	    {
1722*404b540aSrobert 	      if (src == const0_rtx) /* mov r,L */
1723*404b540aSrobert 		{
1724*404b540aSrobert 		  *l = 2;
1725*404b540aSrobert 		  return (AS1 (clr,%A0) CR_TAB
1726*404b540aSrobert 			  AS1 (clr,%B0));
1727*404b540aSrobert 		}
1728*404b540aSrobert 	      else if (src == const1_rtx)
1729*404b540aSrobert 		{
1730*404b540aSrobert 		  *l = 3;
1731*404b540aSrobert 		  return (AS1 (clr,%A0) CR_TAB
1732*404b540aSrobert 			  AS1 (clr,%B0) CR_TAB
1733*404b540aSrobert 			  AS1 (inc,%A0));
1734*404b540aSrobert 		}
1735*404b540aSrobert 	      else if (src == constm1_rtx)
1736*404b540aSrobert 		{
1737*404b540aSrobert 		  /* Immediate constants -1 to any register */
1738*404b540aSrobert 		  *l = 3;
1739*404b540aSrobert 		  return (AS1 (clr,%0)  CR_TAB
1740*404b540aSrobert 			  AS1 (dec,%A0) CR_TAB
1741*404b540aSrobert 			  AS2 (mov,%B0,%A0));
1742*404b540aSrobert 		}
1743*404b540aSrobert 	      else
1744*404b540aSrobert 		{
1745*404b540aSrobert 		  int bit_nr = exact_log2 (INTVAL (src));
1746*404b540aSrobert 
1747*404b540aSrobert 		  if (bit_nr >= 0)
1748*404b540aSrobert 		    {
1749*404b540aSrobert 		      *l = 4;
1750*404b540aSrobert 		      if (!real_l)
1751*404b540aSrobert 			output_asm_insn ((AS1 (clr,%A0) CR_TAB
1752*404b540aSrobert 					  AS1 (clr,%B0) CR_TAB
1753*404b540aSrobert 					  "set"), operands);
1754*404b540aSrobert 		      if (!real_l)
1755*404b540aSrobert 			avr_output_bld (operands, bit_nr);
1756*404b540aSrobert 
1757*404b540aSrobert 		      return "";
1758*404b540aSrobert 		    }
1759*404b540aSrobert 		}
1760*404b540aSrobert 
1761*404b540aSrobert 	      if ((INTVAL (src) & 0xff) == 0)
1762*404b540aSrobert 		{
1763*404b540aSrobert 		  *l = 5;
1764*404b540aSrobert 		  return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1765*404b540aSrobert 			  AS1 (clr,%A0)             CR_TAB
1766*404b540aSrobert 			  AS2 (ldi,r31,hi8(%1))     CR_TAB
1767*404b540aSrobert 			  AS2 (mov,%B0,r31)         CR_TAB
1768*404b540aSrobert 			  AS2 (mov,r31,__tmp_reg__));
1769*404b540aSrobert 		}
1770*404b540aSrobert 	      else if ((INTVAL (src) & 0xff00) == 0)
1771*404b540aSrobert 		{
1772*404b540aSrobert 		  *l = 5;
1773*404b540aSrobert 		  return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1774*404b540aSrobert 			  AS2 (ldi,r31,lo8(%1))     CR_TAB
1775*404b540aSrobert 			  AS2 (mov,%A0,r31)         CR_TAB
1776*404b540aSrobert 			  AS1 (clr,%B0)             CR_TAB
1777*404b540aSrobert 			  AS2 (mov,r31,__tmp_reg__));
1778*404b540aSrobert 		}
1779*404b540aSrobert 	    }
1780*404b540aSrobert 
1781*404b540aSrobert 	  /* Last resort, equal to loading from memory.  */
1782*404b540aSrobert 	  *l = 6;
1783*404b540aSrobert 	  return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1784*404b540aSrobert 		  AS2 (ldi,r31,lo8(%1))     CR_TAB
1785*404b540aSrobert 		  AS2 (mov,%A0,r31)         CR_TAB
1786*404b540aSrobert 		  AS2 (ldi,r31,hi8(%1))     CR_TAB
1787*404b540aSrobert 		  AS2 (mov,%B0,r31)         CR_TAB
1788*404b540aSrobert 		  AS2 (mov,r31,__tmp_reg__));
1789*404b540aSrobert 	}
1790*404b540aSrobert       else if (GET_CODE (src) == MEM)
1791*404b540aSrobert 	return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1792*404b540aSrobert     }
1793*404b540aSrobert   else if (GET_CODE (dest) == MEM)
1794*404b540aSrobert     {
1795*404b540aSrobert       const char *template;
1796*404b540aSrobert 
1797*404b540aSrobert       if (src == const0_rtx)
1798*404b540aSrobert 	operands[1] = zero_reg_rtx;
1799*404b540aSrobert 
1800*404b540aSrobert       template = out_movhi_mr_r (insn, operands, real_l);
1801*404b540aSrobert 
1802*404b540aSrobert       if (!real_l)
1803*404b540aSrobert 	output_asm_insn (template, operands);
1804*404b540aSrobert 
1805*404b540aSrobert       operands[1] = src;
1806*404b540aSrobert       return "";
1807*404b540aSrobert     }
1808*404b540aSrobert   fatal_insn ("invalid insn:", insn);
1809*404b540aSrobert   return "";
1810*404b540aSrobert }
1811*404b540aSrobert 
1812*404b540aSrobert const char *
out_movqi_r_mr(rtx insn,rtx op[],int * l)1813*404b540aSrobert out_movqi_r_mr (rtx insn, rtx op[], int *l)
1814*404b540aSrobert {
1815*404b540aSrobert   rtx dest = op[0];
1816*404b540aSrobert   rtx src = op[1];
1817*404b540aSrobert   rtx x = XEXP (src, 0);
1818*404b540aSrobert   int dummy;
1819*404b540aSrobert 
1820*404b540aSrobert   if (!l)
1821*404b540aSrobert     l = &dummy;
1822*404b540aSrobert 
1823*404b540aSrobert   if (CONSTANT_ADDRESS_P (x))
1824*404b540aSrobert     {
1825*404b540aSrobert       if (avr_io_address_p (x, 1))
1826*404b540aSrobert 	{
1827*404b540aSrobert 	  *l = 1;
1828*404b540aSrobert 	  return AS2 (in,%0,%1-0x20);
1829*404b540aSrobert 	}
1830*404b540aSrobert       *l = 2;
1831*404b540aSrobert       return AS2 (lds,%0,%1);
1832*404b540aSrobert     }
1833*404b540aSrobert   /* memory access by reg+disp */
1834*404b540aSrobert   else if (GET_CODE (x) == PLUS
1835*404b540aSrobert       && REG_P (XEXP (x,0))
1836*404b540aSrobert       && GET_CODE (XEXP (x,1)) == CONST_INT)
1837*404b540aSrobert     {
1838*404b540aSrobert       if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
1839*404b540aSrobert 	{
1840*404b540aSrobert 	  int disp = INTVAL (XEXP (x,1));
1841*404b540aSrobert 	  if (REGNO (XEXP (x,0)) != REG_Y)
1842*404b540aSrobert 	    fatal_insn ("incorrect insn:",insn);
1843*404b540aSrobert 
1844*404b540aSrobert 	  if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1845*404b540aSrobert 	    return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1846*404b540aSrobert 			    AS2 (ldd,%0,Y+63)     CR_TAB
1847*404b540aSrobert 			    AS2 (sbiw,r28,%o1-63));
1848*404b540aSrobert 
1849*404b540aSrobert 	  return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1850*404b540aSrobert 			  AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1851*404b540aSrobert 			  AS2 (ld,%0,Y)            CR_TAB
1852*404b540aSrobert 			  AS2 (subi,r28,lo8(%o1))  CR_TAB
1853*404b540aSrobert 			  AS2 (sbci,r29,hi8(%o1)));
1854*404b540aSrobert 	}
1855*404b540aSrobert       else if (REGNO (XEXP (x,0)) == REG_X)
1856*404b540aSrobert 	{
1857*404b540aSrobert 	  /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1858*404b540aSrobert 	     it but I have this situation with extremal optimizing options.  */
1859*404b540aSrobert 	  if (reg_overlap_mentioned_p (dest, XEXP (x,0))
1860*404b540aSrobert 	      || reg_unused_after (insn, XEXP (x,0)))
1861*404b540aSrobert 	    return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1862*404b540aSrobert 			    AS2 (ld,%0,X));
1863*404b540aSrobert 
1864*404b540aSrobert 	  return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1865*404b540aSrobert 			  AS2 (ld,%0,X)      CR_TAB
1866*404b540aSrobert 			  AS2 (sbiw,r26,%o1));
1867*404b540aSrobert 	}
1868*404b540aSrobert       *l = 1;
1869*404b540aSrobert       return AS2 (ldd,%0,%1);
1870*404b540aSrobert     }
1871*404b540aSrobert   *l = 1;
1872*404b540aSrobert   return AS2 (ld,%0,%1);
1873*404b540aSrobert }
1874*404b540aSrobert 
1875*404b540aSrobert const char *
out_movhi_r_mr(rtx insn,rtx op[],int * l)1876*404b540aSrobert out_movhi_r_mr (rtx insn, rtx op[], int *l)
1877*404b540aSrobert {
1878*404b540aSrobert   rtx dest = op[0];
1879*404b540aSrobert   rtx src = op[1];
1880*404b540aSrobert   rtx base = XEXP (src, 0);
1881*404b540aSrobert   int reg_dest = true_regnum (dest);
1882*404b540aSrobert   int reg_base = true_regnum (base);
1883*404b540aSrobert   /* "volatile" forces reading low byte first, even if less efficient,
1884*404b540aSrobert      for correct operation with 16-bit I/O registers.  */
1885*404b540aSrobert   int mem_volatile_p = MEM_VOLATILE_P (src);
1886*404b540aSrobert   int tmp;
1887*404b540aSrobert 
1888*404b540aSrobert   if (!l)
1889*404b540aSrobert     l = &tmp;
1890*404b540aSrobert 
1891*404b540aSrobert   if (reg_base > 0)
1892*404b540aSrobert     {
1893*404b540aSrobert       if (reg_dest == reg_base)         /* R = (R) */
1894*404b540aSrobert 	{
1895*404b540aSrobert 	  *l = 3;
1896*404b540aSrobert 	  return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1897*404b540aSrobert 		  AS2 (ld,%B0,%1) CR_TAB
1898*404b540aSrobert 		  AS2 (mov,%A0,__tmp_reg__));
1899*404b540aSrobert 	}
1900*404b540aSrobert       else if (reg_base == REG_X)        /* (R26) */
1901*404b540aSrobert         {
1902*404b540aSrobert           if (reg_unused_after (insn, base))
1903*404b540aSrobert 	    {
1904*404b540aSrobert 	      *l = 2;
1905*404b540aSrobert 	      return (AS2 (ld,%A0,X+) CR_TAB
1906*404b540aSrobert 		      AS2 (ld,%B0,X));
1907*404b540aSrobert 	    }
1908*404b540aSrobert 	  *l  = 3;
1909*404b540aSrobert 	  return (AS2 (ld,%A0,X+) CR_TAB
1910*404b540aSrobert 		  AS2 (ld,%B0,X) CR_TAB
1911*404b540aSrobert 		  AS2 (sbiw,r26,1));
1912*404b540aSrobert         }
1913*404b540aSrobert       else                      /* (R)  */
1914*404b540aSrobert 	{
1915*404b540aSrobert 	  *l = 2;
1916*404b540aSrobert 	  return (AS2 (ld,%A0,%1)    CR_TAB
1917*404b540aSrobert 		  AS2 (ldd,%B0,%1+1));
1918*404b540aSrobert 	}
1919*404b540aSrobert     }
1920*404b540aSrobert   else if (GET_CODE (base) == PLUS) /* (R + i) */
1921*404b540aSrobert     {
1922*404b540aSrobert       int disp = INTVAL (XEXP (base, 1));
1923*404b540aSrobert       int reg_base = true_regnum (XEXP (base, 0));
1924*404b540aSrobert 
1925*404b540aSrobert       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
1926*404b540aSrobert 	{
1927*404b540aSrobert 	  if (REGNO (XEXP (base, 0)) != REG_Y)
1928*404b540aSrobert 	    fatal_insn ("incorrect insn:",insn);
1929*404b540aSrobert 
1930*404b540aSrobert 	  if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1931*404b540aSrobert 	    return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
1932*404b540aSrobert 			    AS2 (ldd,%A0,Y+62)    CR_TAB
1933*404b540aSrobert 			    AS2 (ldd,%B0,Y+63)    CR_TAB
1934*404b540aSrobert 			    AS2 (sbiw,r28,%o1-62));
1935*404b540aSrobert 
1936*404b540aSrobert 	  return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1937*404b540aSrobert 			  AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1938*404b540aSrobert 			  AS2 (ld,%A0,Y)           CR_TAB
1939*404b540aSrobert 			  AS2 (ldd,%B0,Y+1)        CR_TAB
1940*404b540aSrobert 			  AS2 (subi,r28,lo8(%o1))  CR_TAB
1941*404b540aSrobert 			  AS2 (sbci,r29,hi8(%o1)));
1942*404b540aSrobert 	}
1943*404b540aSrobert       if (reg_base == REG_X)
1944*404b540aSrobert 	{
1945*404b540aSrobert 	  /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1946*404b540aSrobert 	     it but I have this situation with extremal
1947*404b540aSrobert 	     optimization options.  */
1948*404b540aSrobert 
1949*404b540aSrobert 	  *l = 4;
1950*404b540aSrobert 	  if (reg_base == reg_dest)
1951*404b540aSrobert 	    return (AS2 (adiw,r26,%o1)      CR_TAB
1952*404b540aSrobert 		    AS2 (ld,__tmp_reg__,X+) CR_TAB
1953*404b540aSrobert 		    AS2 (ld,%B0,X)          CR_TAB
1954*404b540aSrobert 		    AS2 (mov,%A0,__tmp_reg__));
1955*404b540aSrobert 
1956*404b540aSrobert 	  return (AS2 (adiw,r26,%o1) CR_TAB
1957*404b540aSrobert 		  AS2 (ld,%A0,X+)    CR_TAB
1958*404b540aSrobert 		  AS2 (ld,%B0,X)     CR_TAB
1959*404b540aSrobert 		  AS2 (sbiw,r26,%o1+1));
1960*404b540aSrobert 	}
1961*404b540aSrobert 
1962*404b540aSrobert       if (reg_base == reg_dest)
1963*404b540aSrobert 	{
1964*404b540aSrobert 	  *l = 3;
1965*404b540aSrobert 	  return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
1966*404b540aSrobert 		  AS2 (ldd,%B0,%B1)         CR_TAB
1967*404b540aSrobert 		  AS2 (mov,%A0,__tmp_reg__));
1968*404b540aSrobert 	}
1969*404b540aSrobert 
1970*404b540aSrobert       *l = 2;
1971*404b540aSrobert       return (AS2 (ldd,%A0,%A1) CR_TAB
1972*404b540aSrobert 	      AS2 (ldd,%B0,%B1));
1973*404b540aSrobert     }
1974*404b540aSrobert   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
1975*404b540aSrobert     {
1976*404b540aSrobert       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1977*404b540aSrobert 	fatal_insn ("incorrect insn:", insn);
1978*404b540aSrobert 
1979*404b540aSrobert       if (mem_volatile_p)
1980*404b540aSrobert         {
1981*404b540aSrobert           if (REGNO (XEXP (base, 0)) == REG_X)
1982*404b540aSrobert             {
1983*404b540aSrobert               *l = 4;
1984*404b540aSrobert               return (AS2 (sbiw,r26,2)  CR_TAB
1985*404b540aSrobert                       AS2 (ld,%A0,X+)   CR_TAB
1986*404b540aSrobert                       AS2 (ld,%B0,X)    CR_TAB
1987*404b540aSrobert                       AS2 (sbiw,r26,1));
1988*404b540aSrobert             }
1989*404b540aSrobert           else
1990*404b540aSrobert             {
1991*404b540aSrobert               *l = 3;
1992*404b540aSrobert               return (AS2 (sbiw,%r1,2)   CR_TAB
1993*404b540aSrobert                       AS2 (ld,%A0,%p1)  CR_TAB
1994*404b540aSrobert                       AS2 (ldd,%B0,%p1+1));
1995*404b540aSrobert             }
1996*404b540aSrobert         }
1997*404b540aSrobert 
1998*404b540aSrobert       *l = 2;
1999*404b540aSrobert       return (AS2 (ld,%B0,%1) CR_TAB
2000*404b540aSrobert 	      AS2 (ld,%A0,%1));
2001*404b540aSrobert     }
2002*404b540aSrobert   else if (GET_CODE (base) == POST_INC) /* (R++) */
2003*404b540aSrobert     {
2004*404b540aSrobert       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
2005*404b540aSrobert 	fatal_insn ("incorrect insn:", insn);
2006*404b540aSrobert 
2007*404b540aSrobert       *l = 2;
2008*404b540aSrobert       return (AS2 (ld,%A0,%1)  CR_TAB
2009*404b540aSrobert 	      AS2 (ld,%B0,%1));
2010*404b540aSrobert     }
2011*404b540aSrobert   else if (CONSTANT_ADDRESS_P (base))
2012*404b540aSrobert     {
2013*404b540aSrobert       if (avr_io_address_p (base, 2))
2014*404b540aSrobert 	{
2015*404b540aSrobert 	  *l = 2;
2016*404b540aSrobert 	  return (AS2 (in,%A0,%A1-0x20) CR_TAB
2017*404b540aSrobert 		  AS2 (in,%B0,%B1-0x20));
2018*404b540aSrobert 	}
2019*404b540aSrobert       *l = 4;
2020*404b540aSrobert       return (AS2 (lds,%A0,%A1) CR_TAB
2021*404b540aSrobert 	      AS2 (lds,%B0,%B1));
2022*404b540aSrobert     }
2023*404b540aSrobert 
2024*404b540aSrobert   fatal_insn ("unknown move insn:",insn);
2025*404b540aSrobert   return "";
2026*404b540aSrobert }
2027*404b540aSrobert 
2028*404b540aSrobert const char *
out_movsi_r_mr(rtx insn,rtx op[],int * l)2029*404b540aSrobert out_movsi_r_mr (rtx insn, rtx op[], int *l)
2030*404b540aSrobert {
2031*404b540aSrobert   rtx dest = op[0];
2032*404b540aSrobert   rtx src = op[1];
2033*404b540aSrobert   rtx base = XEXP (src, 0);
2034*404b540aSrobert   int reg_dest = true_regnum (dest);
2035*404b540aSrobert   int reg_base = true_regnum (base);
2036*404b540aSrobert   int tmp;
2037*404b540aSrobert 
2038*404b540aSrobert   if (!l)
2039*404b540aSrobert     l = &tmp;
2040*404b540aSrobert 
2041*404b540aSrobert   if (reg_base > 0)
2042*404b540aSrobert     {
2043*404b540aSrobert       if (reg_base == REG_X)        /* (R26) */
2044*404b540aSrobert         {
2045*404b540aSrobert           if (reg_dest == REG_X)
2046*404b540aSrobert 	    /* "ld r26,-X" is undefined */
2047*404b540aSrobert 	    return *l=7, (AS2 (adiw,r26,3)        CR_TAB
2048*404b540aSrobert 			  AS2 (ld,r29,X)          CR_TAB
2049*404b540aSrobert 			  AS2 (ld,r28,-X)         CR_TAB
2050*404b540aSrobert 			  AS2 (ld,__tmp_reg__,-X) CR_TAB
2051*404b540aSrobert 			  AS2 (sbiw,r26,1)        CR_TAB
2052*404b540aSrobert 			  AS2 (ld,r26,X)          CR_TAB
2053*404b540aSrobert 			  AS2 (mov,r27,__tmp_reg__));
2054*404b540aSrobert           else if (reg_dest == REG_X - 2)
2055*404b540aSrobert             return *l=5, (AS2 (ld,%A0,X+)  CR_TAB
2056*404b540aSrobert                           AS2 (ld,%B0,X+) CR_TAB
2057*404b540aSrobert                           AS2 (ld,__tmp_reg__,X+)  CR_TAB
2058*404b540aSrobert                           AS2 (ld,%D0,X)  CR_TAB
2059*404b540aSrobert                           AS2 (mov,%C0,__tmp_reg__));
2060*404b540aSrobert           else if (reg_unused_after (insn, base))
2061*404b540aSrobert             return  *l=4, (AS2 (ld,%A0,X+)  CR_TAB
2062*404b540aSrobert                            AS2 (ld,%B0,X+) CR_TAB
2063*404b540aSrobert                            AS2 (ld,%C0,X+) CR_TAB
2064*404b540aSrobert                            AS2 (ld,%D0,X));
2065*404b540aSrobert           else
2066*404b540aSrobert             return  *l=5, (AS2 (ld,%A0,X+)  CR_TAB
2067*404b540aSrobert                            AS2 (ld,%B0,X+) CR_TAB
2068*404b540aSrobert                            AS2 (ld,%C0,X+) CR_TAB
2069*404b540aSrobert                            AS2 (ld,%D0,X)  CR_TAB
2070*404b540aSrobert                            AS2 (sbiw,r26,3));
2071*404b540aSrobert         }
2072*404b540aSrobert       else
2073*404b540aSrobert         {
2074*404b540aSrobert           if (reg_dest == reg_base)
2075*404b540aSrobert             return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2076*404b540aSrobert                           AS2 (ldd,%C0,%1+2) CR_TAB
2077*404b540aSrobert                           AS2 (ldd,__tmp_reg__,%1+1)  CR_TAB
2078*404b540aSrobert                           AS2 (ld,%A0,%1)  CR_TAB
2079*404b540aSrobert                           AS2 (mov,%B0,__tmp_reg__));
2080*404b540aSrobert           else if (reg_base == reg_dest + 2)
2081*404b540aSrobert             return *l=5, (AS2 (ld ,%A0,%1)    CR_TAB
2082*404b540aSrobert                           AS2 (ldd,%B0,%1+1) CR_TAB
2083*404b540aSrobert                           AS2 (ldd,__tmp_reg__,%1+2)  CR_TAB
2084*404b540aSrobert                           AS2 (ldd,%D0,%1+3) CR_TAB
2085*404b540aSrobert                           AS2 (mov,%C0,__tmp_reg__));
2086*404b540aSrobert           else
2087*404b540aSrobert             return *l=4, (AS2 (ld ,%A0,%1)   CR_TAB
2088*404b540aSrobert                           AS2 (ldd,%B0,%1+1) CR_TAB
2089*404b540aSrobert                           AS2 (ldd,%C0,%1+2) CR_TAB
2090*404b540aSrobert                           AS2 (ldd,%D0,%1+3));
2091*404b540aSrobert         }
2092*404b540aSrobert     }
2093*404b540aSrobert   else if (GET_CODE (base) == PLUS) /* (R + i) */
2094*404b540aSrobert     {
2095*404b540aSrobert       int disp = INTVAL (XEXP (base, 1));
2096*404b540aSrobert 
2097*404b540aSrobert       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2098*404b540aSrobert 	{
2099*404b540aSrobert 	  if (REGNO (XEXP (base, 0)) != REG_Y)
2100*404b540aSrobert 	    fatal_insn ("incorrect insn:",insn);
2101*404b540aSrobert 
2102*404b540aSrobert 	  if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2103*404b540aSrobert 	    return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2104*404b540aSrobert 			    AS2 (ldd,%A0,Y+60)    CR_TAB
2105*404b540aSrobert 			    AS2 (ldd,%B0,Y+61)    CR_TAB
2106*404b540aSrobert 			    AS2 (ldd,%C0,Y+62)    CR_TAB
2107*404b540aSrobert 			    AS2 (ldd,%D0,Y+63)    CR_TAB
2108*404b540aSrobert 			    AS2 (sbiw,r28,%o1-60));
2109*404b540aSrobert 
2110*404b540aSrobert 	  return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2111*404b540aSrobert 			  AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2112*404b540aSrobert 			  AS2 (ld,%A0,Y)           CR_TAB
2113*404b540aSrobert 			  AS2 (ldd,%B0,Y+1)        CR_TAB
2114*404b540aSrobert 			  AS2 (ldd,%C0,Y+2)        CR_TAB
2115*404b540aSrobert 			  AS2 (ldd,%D0,Y+3)        CR_TAB
2116*404b540aSrobert 			  AS2 (subi,r28,lo8(%o1))  CR_TAB
2117*404b540aSrobert 			  AS2 (sbci,r29,hi8(%o1)));
2118*404b540aSrobert 	}
2119*404b540aSrobert 
2120*404b540aSrobert       reg_base = true_regnum (XEXP (base, 0));
2121*404b540aSrobert       if (reg_base == REG_X)
2122*404b540aSrobert 	{
2123*404b540aSrobert 	  /* R = (X + d) */
2124*404b540aSrobert 	  if (reg_dest == REG_X)
2125*404b540aSrobert 	    {
2126*404b540aSrobert 	      *l = 7;
2127*404b540aSrobert 	      /* "ld r26,-X" is undefined */
2128*404b540aSrobert 	      return (AS2 (adiw,r26,%o1+3)    CR_TAB
2129*404b540aSrobert 		      AS2 (ld,r29,X)          CR_TAB
2130*404b540aSrobert 		      AS2 (ld,r28,-X)         CR_TAB
2131*404b540aSrobert 		      AS2 (ld,__tmp_reg__,-X) CR_TAB
2132*404b540aSrobert 		      AS2 (sbiw,r26,1)        CR_TAB
2133*404b540aSrobert 		      AS2 (ld,r26,X)          CR_TAB
2134*404b540aSrobert 		      AS2 (mov,r27,__tmp_reg__));
2135*404b540aSrobert 	    }
2136*404b540aSrobert 	  *l = 6;
2137*404b540aSrobert 	  if (reg_dest == REG_X - 2)
2138*404b540aSrobert 	    return (AS2 (adiw,r26,%o1)      CR_TAB
2139*404b540aSrobert 		    AS2 (ld,r24,X+)         CR_TAB
2140*404b540aSrobert 		    AS2 (ld,r25,X+)         CR_TAB
2141*404b540aSrobert 		    AS2 (ld,__tmp_reg__,X+) CR_TAB
2142*404b540aSrobert 		    AS2 (ld,r27,X)          CR_TAB
2143*404b540aSrobert 		    AS2 (mov,r26,__tmp_reg__));
2144*404b540aSrobert 
2145*404b540aSrobert 	  return (AS2 (adiw,r26,%o1) CR_TAB
2146*404b540aSrobert 		  AS2 (ld,%A0,X+)    CR_TAB
2147*404b540aSrobert 		  AS2 (ld,%B0,X+)    CR_TAB
2148*404b540aSrobert 		  AS2 (ld,%C0,X+)    CR_TAB
2149*404b540aSrobert 		  AS2 (ld,%D0,X)     CR_TAB
2150*404b540aSrobert 		  AS2 (sbiw,r26,%o1+3));
2151*404b540aSrobert 	}
2152*404b540aSrobert       if (reg_dest == reg_base)
2153*404b540aSrobert         return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2154*404b540aSrobert                       AS2 (ldd,%C0,%C1) CR_TAB
2155*404b540aSrobert                       AS2 (ldd,__tmp_reg__,%B1)  CR_TAB
2156*404b540aSrobert                       AS2 (ldd,%A0,%A1) CR_TAB
2157*404b540aSrobert                       AS2 (mov,%B0,__tmp_reg__));
2158*404b540aSrobert       else if (reg_dest == reg_base - 2)
2159*404b540aSrobert         return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2160*404b540aSrobert                       AS2 (ldd,%B0,%B1) CR_TAB
2161*404b540aSrobert                       AS2 (ldd,__tmp_reg__,%C1)  CR_TAB
2162*404b540aSrobert                       AS2 (ldd,%D0,%D1) CR_TAB
2163*404b540aSrobert                       AS2 (mov,%C0,__tmp_reg__));
2164*404b540aSrobert       return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2165*404b540aSrobert                     AS2 (ldd,%B0,%B1) CR_TAB
2166*404b540aSrobert                     AS2 (ldd,%C0,%C1) CR_TAB
2167*404b540aSrobert                     AS2 (ldd,%D0,%D1));
2168*404b540aSrobert     }
2169*404b540aSrobert   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2170*404b540aSrobert     return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2171*404b540aSrobert 		  AS2 (ld,%C0,%1) CR_TAB
2172*404b540aSrobert 		  AS2 (ld,%B0,%1) CR_TAB
2173*404b540aSrobert 		  AS2 (ld,%A0,%1));
2174*404b540aSrobert   else if (GET_CODE (base) == POST_INC) /* (R++) */
2175*404b540aSrobert     return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2176*404b540aSrobert 		  AS2 (ld,%B0,%1) CR_TAB
2177*404b540aSrobert 		  AS2 (ld,%C0,%1) CR_TAB
2178*404b540aSrobert 		  AS2 (ld,%D0,%1));
2179*404b540aSrobert   else if (CONSTANT_ADDRESS_P (base))
2180*404b540aSrobert       return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2181*404b540aSrobert 		    AS2 (lds,%B0,%B1) CR_TAB
2182*404b540aSrobert 		    AS2 (lds,%C0,%C1) CR_TAB
2183*404b540aSrobert 		    AS2 (lds,%D0,%D1));
2184*404b540aSrobert 
2185*404b540aSrobert   fatal_insn ("unknown move insn:",insn);
2186*404b540aSrobert   return "";
2187*404b540aSrobert }
2188*404b540aSrobert 
2189*404b540aSrobert const char *
out_movsi_mr_r(rtx insn,rtx op[],int * l)2190*404b540aSrobert out_movsi_mr_r (rtx insn, rtx op[], int *l)
2191*404b540aSrobert {
2192*404b540aSrobert   rtx dest = op[0];
2193*404b540aSrobert   rtx src = op[1];
2194*404b540aSrobert   rtx base = XEXP (dest, 0);
2195*404b540aSrobert   int reg_base = true_regnum (base);
2196*404b540aSrobert   int reg_src = true_regnum (src);
2197*404b540aSrobert   int tmp;
2198*404b540aSrobert 
2199*404b540aSrobert   if (!l)
2200*404b540aSrobert     l = &tmp;
2201*404b540aSrobert 
2202*404b540aSrobert   if (CONSTANT_ADDRESS_P (base))
2203*404b540aSrobert     return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2204*404b540aSrobert 		 AS2 (sts,%B0,%B1) CR_TAB
2205*404b540aSrobert 		 AS2 (sts,%C0,%C1) CR_TAB
2206*404b540aSrobert 		 AS2 (sts,%D0,%D1));
2207*404b540aSrobert   if (reg_base > 0)                 /* (r) */
2208*404b540aSrobert     {
2209*404b540aSrobert       if (reg_base == REG_X)                /* (R26) */
2210*404b540aSrobert         {
2211*404b540aSrobert           if (reg_src == REG_X)
2212*404b540aSrobert             {
2213*404b540aSrobert 	      /* "st X+,r26" is undefined */
2214*404b540aSrobert               if (reg_unused_after (insn, base))
2215*404b540aSrobert 		return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2216*404b540aSrobert 			      AS2 (st,X,r26)            CR_TAB
2217*404b540aSrobert 			      AS2 (adiw,r26,1)          CR_TAB
2218*404b540aSrobert 			      AS2 (st,X+,__tmp_reg__)   CR_TAB
2219*404b540aSrobert 			      AS2 (st,X+,r28)           CR_TAB
2220*404b540aSrobert 			      AS2 (st,X,r29));
2221*404b540aSrobert               else
2222*404b540aSrobert                 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2223*404b540aSrobert 			      AS2 (st,X,r26)            CR_TAB
2224*404b540aSrobert 			      AS2 (adiw,r26,1)          CR_TAB
2225*404b540aSrobert 			      AS2 (st,X+,__tmp_reg__)   CR_TAB
2226*404b540aSrobert 			      AS2 (st,X+,r28)           CR_TAB
2227*404b540aSrobert 			      AS2 (st,X,r29)            CR_TAB
2228*404b540aSrobert 			      AS2 (sbiw,r26,3));
2229*404b540aSrobert             }
2230*404b540aSrobert           else if (reg_base == reg_src + 2)
2231*404b540aSrobert             {
2232*404b540aSrobert               if (reg_unused_after (insn, base))
2233*404b540aSrobert                 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2234*404b540aSrobert                               AS2 (mov,__tmp_reg__,%D1) CR_TAB
2235*404b540aSrobert                               AS2 (st,%0+,%A1) CR_TAB
2236*404b540aSrobert                               AS2 (st,%0+,%B1) CR_TAB
2237*404b540aSrobert                               AS2 (st,%0+,__zero_reg__)  CR_TAB
2238*404b540aSrobert                               AS2 (st,%0,__tmp_reg__)   CR_TAB
2239*404b540aSrobert                               AS1 (clr,__zero_reg__));
2240*404b540aSrobert               else
2241*404b540aSrobert                 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2242*404b540aSrobert                               AS2 (mov,__tmp_reg__,%D1) CR_TAB
2243*404b540aSrobert                               AS2 (st,%0+,%A1) CR_TAB
2244*404b540aSrobert                               AS2 (st,%0+,%B1) CR_TAB
2245*404b540aSrobert                               AS2 (st,%0+,__zero_reg__)  CR_TAB
2246*404b540aSrobert                               AS2 (st,%0,__tmp_reg__)   CR_TAB
2247*404b540aSrobert                               AS1 (clr,__zero_reg__)     CR_TAB
2248*404b540aSrobert                               AS2 (sbiw,r26,3));
2249*404b540aSrobert             }
2250*404b540aSrobert           return *l=5, (AS2 (st,%0+,%A1)  CR_TAB
2251*404b540aSrobert                         AS2 (st,%0+,%B1) CR_TAB
2252*404b540aSrobert                         AS2 (st,%0+,%C1) CR_TAB
2253*404b540aSrobert                         AS2 (st,%0,%D1)  CR_TAB
2254*404b540aSrobert                         AS2 (sbiw,r26,3));
2255*404b540aSrobert         }
2256*404b540aSrobert       else
2257*404b540aSrobert         return *l=4, (AS2 (st,%0,%A1)    CR_TAB
2258*404b540aSrobert 		      AS2 (std,%0+1,%B1) CR_TAB
2259*404b540aSrobert 		      AS2 (std,%0+2,%C1) CR_TAB
2260*404b540aSrobert 		      AS2 (std,%0+3,%D1));
2261*404b540aSrobert     }
2262*404b540aSrobert   else if (GET_CODE (base) == PLUS) /* (R + i) */
2263*404b540aSrobert     {
2264*404b540aSrobert       int disp = INTVAL (XEXP (base, 1));
2265*404b540aSrobert       reg_base = REGNO (XEXP (base, 0));
2266*404b540aSrobert       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2267*404b540aSrobert 	{
2268*404b540aSrobert 	  if (reg_base != REG_Y)
2269*404b540aSrobert 	    fatal_insn ("incorrect insn:",insn);
2270*404b540aSrobert 
2271*404b540aSrobert 	  if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2272*404b540aSrobert 	    return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2273*404b540aSrobert 			    AS2 (std,Y+60,%A1)    CR_TAB
2274*404b540aSrobert 			    AS2 (std,Y+61,%B1)    CR_TAB
2275*404b540aSrobert 			    AS2 (std,Y+62,%C1)    CR_TAB
2276*404b540aSrobert 			    AS2 (std,Y+63,%D1)    CR_TAB
2277*404b540aSrobert 			    AS2 (sbiw,r28,%o0-60));
2278*404b540aSrobert 
2279*404b540aSrobert 	  return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2280*404b540aSrobert 			  AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2281*404b540aSrobert 			  AS2 (st,Y,%A1)           CR_TAB
2282*404b540aSrobert 			  AS2 (std,Y+1,%B1)        CR_TAB
2283*404b540aSrobert 			  AS2 (std,Y+2,%C1)        CR_TAB
2284*404b540aSrobert 			  AS2 (std,Y+3,%D1)        CR_TAB
2285*404b540aSrobert 			  AS2 (subi,r28,lo8(%o0))  CR_TAB
2286*404b540aSrobert 			  AS2 (sbci,r29,hi8(%o0)));
2287*404b540aSrobert 	}
2288*404b540aSrobert       if (reg_base == REG_X)
2289*404b540aSrobert 	{
2290*404b540aSrobert 	  /* (X + d) = R */
2291*404b540aSrobert 	  if (reg_src == REG_X)
2292*404b540aSrobert 	    {
2293*404b540aSrobert 	      *l = 9;
2294*404b540aSrobert 	      return (AS2 (mov,__tmp_reg__,r26)  CR_TAB
2295*404b540aSrobert 		      AS2 (mov,__zero_reg__,r27) CR_TAB
2296*404b540aSrobert 		      AS2 (adiw,r26,%o0)         CR_TAB
2297*404b540aSrobert 		      AS2 (st,X+,__tmp_reg__)    CR_TAB
2298*404b540aSrobert 		      AS2 (st,X+,__zero_reg__)   CR_TAB
2299*404b540aSrobert 		      AS2 (st,X+,r28)            CR_TAB
2300*404b540aSrobert 		      AS2 (st,X,r29)             CR_TAB
2301*404b540aSrobert 		      AS1 (clr,__zero_reg__)     CR_TAB
2302*404b540aSrobert 		      AS2 (sbiw,r26,%o0+3));
2303*404b540aSrobert 	    }
2304*404b540aSrobert 	  else if (reg_src == REG_X - 2)
2305*404b540aSrobert 	    {
2306*404b540aSrobert 	      *l = 9;
2307*404b540aSrobert 	      return (AS2 (mov,__tmp_reg__,r26)  CR_TAB
2308*404b540aSrobert 		      AS2 (mov,__zero_reg__,r27) CR_TAB
2309*404b540aSrobert 		      AS2 (adiw,r26,%o0)         CR_TAB
2310*404b540aSrobert 		      AS2 (st,X+,r24)            CR_TAB
2311*404b540aSrobert 		      AS2 (st,X+,r25)            CR_TAB
2312*404b540aSrobert 		      AS2 (st,X+,__tmp_reg__)    CR_TAB
2313*404b540aSrobert 		      AS2 (st,X,__zero_reg__)    CR_TAB
2314*404b540aSrobert 		      AS1 (clr,__zero_reg__)     CR_TAB
2315*404b540aSrobert 		      AS2 (sbiw,r26,%o0+3));
2316*404b540aSrobert 	    }
2317*404b540aSrobert 	  *l = 6;
2318*404b540aSrobert 	  return (AS2 (adiw,r26,%o0) CR_TAB
2319*404b540aSrobert 		  AS2 (st,X+,%A1)    CR_TAB
2320*404b540aSrobert 		  AS2 (st,X+,%B1)    CR_TAB
2321*404b540aSrobert 		  AS2 (st,X+,%C1)    CR_TAB
2322*404b540aSrobert 		  AS2 (st,X,%D1)     CR_TAB
2323*404b540aSrobert 		  AS2 (sbiw,r26,%o0+3));
2324*404b540aSrobert 	}
2325*404b540aSrobert       return *l=4, (AS2 (std,%A0,%A1)    CR_TAB
2326*404b540aSrobert 		    AS2 (std,%B0,%B1) CR_TAB
2327*404b540aSrobert 		    AS2 (std,%C0,%C1) CR_TAB
2328*404b540aSrobert 		    AS2 (std,%D0,%D1));
2329*404b540aSrobert     }
2330*404b540aSrobert   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2331*404b540aSrobert     return *l=4, (AS2 (st,%0,%D1) CR_TAB
2332*404b540aSrobert 		  AS2 (st,%0,%C1) CR_TAB
2333*404b540aSrobert 		  AS2 (st,%0,%B1) CR_TAB
2334*404b540aSrobert 		  AS2 (st,%0,%A1));
2335*404b540aSrobert   else if (GET_CODE (base) == POST_INC) /* (R++) */
2336*404b540aSrobert     return *l=4, (AS2 (st,%0,%A1)  CR_TAB
2337*404b540aSrobert 		  AS2 (st,%0,%B1) CR_TAB
2338*404b540aSrobert 		  AS2 (st,%0,%C1) CR_TAB
2339*404b540aSrobert 		  AS2 (st,%0,%D1));
2340*404b540aSrobert   fatal_insn ("unknown move insn:",insn);
2341*404b540aSrobert   return "";
2342*404b540aSrobert }
2343*404b540aSrobert 
2344*404b540aSrobert const char *
output_movsisf(rtx insn,rtx operands[],int * l)2345*404b540aSrobert output_movsisf(rtx insn, rtx operands[], int *l)
2346*404b540aSrobert {
2347*404b540aSrobert   int dummy;
2348*404b540aSrobert   rtx dest = operands[0];
2349*404b540aSrobert   rtx src = operands[1];
2350*404b540aSrobert   int *real_l = l;
2351*404b540aSrobert 
2352*404b540aSrobert   if (!l)
2353*404b540aSrobert     l = &dummy;
2354*404b540aSrobert 
2355*404b540aSrobert   if (register_operand (dest, VOIDmode))
2356*404b540aSrobert     {
2357*404b540aSrobert       if (register_operand (src, VOIDmode)) /* mov r,r */
2358*404b540aSrobert 	{
2359*404b540aSrobert 	  if (true_regnum (dest) > true_regnum (src))
2360*404b540aSrobert 	    {
2361*404b540aSrobert 	      if (AVR_HAVE_MOVW)
2362*404b540aSrobert 		{
2363*404b540aSrobert 		  *l = 2;
2364*404b540aSrobert 		  return (AS2 (movw,%C0,%C1) CR_TAB
2365*404b540aSrobert 			  AS2 (movw,%A0,%A1));
2366*404b540aSrobert 		}
2367*404b540aSrobert 	      *l = 4;
2368*404b540aSrobert 	      return (AS2 (mov,%D0,%D1) CR_TAB
2369*404b540aSrobert 		      AS2 (mov,%C0,%C1) CR_TAB
2370*404b540aSrobert 		      AS2 (mov,%B0,%B1) CR_TAB
2371*404b540aSrobert 		      AS2 (mov,%A0,%A1));
2372*404b540aSrobert 	    }
2373*404b540aSrobert 	  else
2374*404b540aSrobert 	    {
2375*404b540aSrobert 	      if (AVR_HAVE_MOVW)
2376*404b540aSrobert 		{
2377*404b540aSrobert 		  *l = 2;
2378*404b540aSrobert 		  return (AS2 (movw,%A0,%A1) CR_TAB
2379*404b540aSrobert 			  AS2 (movw,%C0,%C1));
2380*404b540aSrobert 		}
2381*404b540aSrobert 	      *l = 4;
2382*404b540aSrobert 	      return (AS2 (mov,%A0,%A1) CR_TAB
2383*404b540aSrobert 		      AS2 (mov,%B0,%B1) CR_TAB
2384*404b540aSrobert 		      AS2 (mov,%C0,%C1) CR_TAB
2385*404b540aSrobert 		      AS2 (mov,%D0,%D1));
2386*404b540aSrobert 	    }
2387*404b540aSrobert 	}
2388*404b540aSrobert       else if (CONSTANT_P (src))
2389*404b540aSrobert 	{
2390*404b540aSrobert 	  if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2391*404b540aSrobert 	    {
2392*404b540aSrobert 	      *l = 4;
2393*404b540aSrobert 	      return (AS2 (ldi,%A0,lo8(%1))  CR_TAB
2394*404b540aSrobert 		      AS2 (ldi,%B0,hi8(%1))  CR_TAB
2395*404b540aSrobert 		      AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2396*404b540aSrobert 		      AS2 (ldi,%D0,hhi8(%1)));
2397*404b540aSrobert 	    }
2398*404b540aSrobert 
2399*404b540aSrobert 	  if (GET_CODE (src) == CONST_INT)
2400*404b540aSrobert 	    {
2401*404b540aSrobert 	      const char *const clr_op0 =
2402*404b540aSrobert 		AVR_HAVE_MOVW ? (AS1 (clr,%A0) CR_TAB
2403*404b540aSrobert 				AS1 (clr,%B0) CR_TAB
2404*404b540aSrobert 				AS2 (movw,%C0,%A0))
2405*404b540aSrobert 			     : (AS1 (clr,%A0) CR_TAB
2406*404b540aSrobert 				AS1 (clr,%B0) CR_TAB
2407*404b540aSrobert 				AS1 (clr,%C0) CR_TAB
2408*404b540aSrobert 				AS1 (clr,%D0));
2409*404b540aSrobert 
2410*404b540aSrobert 	      if (src == const0_rtx) /* mov r,L */
2411*404b540aSrobert 		{
2412*404b540aSrobert 		  *l = AVR_HAVE_MOVW ? 3 : 4;
2413*404b540aSrobert 		  return clr_op0;
2414*404b540aSrobert 		}
2415*404b540aSrobert 	      else if (src == const1_rtx)
2416*404b540aSrobert 		{
2417*404b540aSrobert 		  if (!real_l)
2418*404b540aSrobert 		    output_asm_insn (clr_op0, operands);
2419*404b540aSrobert 		  *l = AVR_HAVE_MOVW ? 4 : 5;
2420*404b540aSrobert 		  return AS1 (inc,%A0);
2421*404b540aSrobert 		}
2422*404b540aSrobert 	      else if (src == constm1_rtx)
2423*404b540aSrobert 		{
2424*404b540aSrobert 		  /* Immediate constants -1 to any register */
2425*404b540aSrobert 		  if (AVR_HAVE_MOVW)
2426*404b540aSrobert 		    {
2427*404b540aSrobert 		      *l = 4;
2428*404b540aSrobert 		      return (AS1 (clr,%A0)     CR_TAB
2429*404b540aSrobert 			      AS1 (dec,%A0)     CR_TAB
2430*404b540aSrobert 			      AS2 (mov,%B0,%A0) CR_TAB
2431*404b540aSrobert 			      AS2 (movw,%C0,%A0));
2432*404b540aSrobert 		    }
2433*404b540aSrobert 		  *l = 5;
2434*404b540aSrobert 		  return (AS1 (clr,%A0)     CR_TAB
2435*404b540aSrobert 			  AS1 (dec,%A0)     CR_TAB
2436*404b540aSrobert 			  AS2 (mov,%B0,%A0) CR_TAB
2437*404b540aSrobert 			  AS2 (mov,%C0,%A0) CR_TAB
2438*404b540aSrobert 			  AS2 (mov,%D0,%A0));
2439*404b540aSrobert 		}
2440*404b540aSrobert 	      else
2441*404b540aSrobert 		{
2442*404b540aSrobert 		  int bit_nr = exact_log2 (INTVAL (src));
2443*404b540aSrobert 
2444*404b540aSrobert 		  if (bit_nr >= 0)
2445*404b540aSrobert 		    {
2446*404b540aSrobert 		      *l = AVR_HAVE_MOVW ? 5 : 6;
2447*404b540aSrobert 		      if (!real_l)
2448*404b540aSrobert 			{
2449*404b540aSrobert 			  output_asm_insn (clr_op0, operands);
2450*404b540aSrobert 			  output_asm_insn ("set", operands);
2451*404b540aSrobert 			}
2452*404b540aSrobert 		      if (!real_l)
2453*404b540aSrobert 			avr_output_bld (operands, bit_nr);
2454*404b540aSrobert 
2455*404b540aSrobert 		      return "";
2456*404b540aSrobert 		    }
2457*404b540aSrobert 		}
2458*404b540aSrobert 	    }
2459*404b540aSrobert 
2460*404b540aSrobert 	  /* Last resort, better than loading from memory.  */
2461*404b540aSrobert 	  *l = 10;
2462*404b540aSrobert 	  return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2463*404b540aSrobert 		  AS2 (ldi,r31,lo8(%1))     CR_TAB
2464*404b540aSrobert 		  AS2 (mov,%A0,r31)         CR_TAB
2465*404b540aSrobert 		  AS2 (ldi,r31,hi8(%1))     CR_TAB
2466*404b540aSrobert 		  AS2 (mov,%B0,r31)         CR_TAB
2467*404b540aSrobert 		  AS2 (ldi,r31,hlo8(%1))    CR_TAB
2468*404b540aSrobert 		  AS2 (mov,%C0,r31)         CR_TAB
2469*404b540aSrobert 		  AS2 (ldi,r31,hhi8(%1))    CR_TAB
2470*404b540aSrobert 		  AS2 (mov,%D0,r31)         CR_TAB
2471*404b540aSrobert 		  AS2 (mov,r31,__tmp_reg__));
2472*404b540aSrobert 	}
2473*404b540aSrobert       else if (GET_CODE (src) == MEM)
2474*404b540aSrobert 	return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2475*404b540aSrobert     }
2476*404b540aSrobert   else if (GET_CODE (dest) == MEM)
2477*404b540aSrobert     {
2478*404b540aSrobert       const char *template;
2479*404b540aSrobert 
2480*404b540aSrobert       if (src == const0_rtx)
2481*404b540aSrobert 	  operands[1] = zero_reg_rtx;
2482*404b540aSrobert 
2483*404b540aSrobert       template = out_movsi_mr_r (insn, operands, real_l);
2484*404b540aSrobert 
2485*404b540aSrobert       if (!real_l)
2486*404b540aSrobert 	output_asm_insn (template, operands);
2487*404b540aSrobert 
2488*404b540aSrobert       operands[1] = src;
2489*404b540aSrobert       return "";
2490*404b540aSrobert     }
2491*404b540aSrobert   fatal_insn ("invalid insn:", insn);
2492*404b540aSrobert   return "";
2493*404b540aSrobert }
2494*404b540aSrobert 
2495*404b540aSrobert const char *
out_movqi_mr_r(rtx insn,rtx op[],int * l)2496*404b540aSrobert out_movqi_mr_r (rtx insn, rtx op[], int *l)
2497*404b540aSrobert {
2498*404b540aSrobert   rtx dest = op[0];
2499*404b540aSrobert   rtx src = op[1];
2500*404b540aSrobert   rtx x = XEXP (dest, 0);
2501*404b540aSrobert   int dummy;
2502*404b540aSrobert 
2503*404b540aSrobert   if (!l)
2504*404b540aSrobert     l = &dummy;
2505*404b540aSrobert 
2506*404b540aSrobert   if (CONSTANT_ADDRESS_P (x))
2507*404b540aSrobert     {
2508*404b540aSrobert       if (avr_io_address_p (x, 1))
2509*404b540aSrobert 	{
2510*404b540aSrobert 	  *l = 1;
2511*404b540aSrobert 	  return AS2 (out,%0-0x20,%1);
2512*404b540aSrobert 	}
2513*404b540aSrobert       *l = 2;
2514*404b540aSrobert       return AS2 (sts,%0,%1);
2515*404b540aSrobert     }
2516*404b540aSrobert   /* memory access by reg+disp */
2517*404b540aSrobert   else if (GET_CODE (x) == PLUS
2518*404b540aSrobert       && REG_P (XEXP (x,0))
2519*404b540aSrobert       && GET_CODE (XEXP (x,1)) == CONST_INT)
2520*404b540aSrobert     {
2521*404b540aSrobert       if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
2522*404b540aSrobert 	{
2523*404b540aSrobert 	  int disp = INTVAL (XEXP (x,1));
2524*404b540aSrobert 	  if (REGNO (XEXP (x,0)) != REG_Y)
2525*404b540aSrobert 	    fatal_insn ("incorrect insn:",insn);
2526*404b540aSrobert 
2527*404b540aSrobert 	  if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2528*404b540aSrobert 	    return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2529*404b540aSrobert 			    AS2 (std,Y+63,%1)     CR_TAB
2530*404b540aSrobert 			    AS2 (sbiw,r28,%o0-63));
2531*404b540aSrobert 
2532*404b540aSrobert 	  return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2533*404b540aSrobert 			  AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2534*404b540aSrobert 			  AS2 (st,Y,%1)            CR_TAB
2535*404b540aSrobert 			  AS2 (subi,r28,lo8(%o0))  CR_TAB
2536*404b540aSrobert 			  AS2 (sbci,r29,hi8(%o0)));
2537*404b540aSrobert 	}
2538*404b540aSrobert       else if (REGNO (XEXP (x,0)) == REG_X)
2539*404b540aSrobert 	{
2540*404b540aSrobert 	  if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
2541*404b540aSrobert 	    {
2542*404b540aSrobert 	      if (reg_unused_after (insn, XEXP (x,0)))
2543*404b540aSrobert 		return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2544*404b540aSrobert 				AS2 (adiw,r26,%o0)       CR_TAB
2545*404b540aSrobert 				AS2 (st,X,__tmp_reg__));
2546*404b540aSrobert 
2547*404b540aSrobert 	      return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2548*404b540aSrobert 			      AS2 (adiw,r26,%o0)       CR_TAB
2549*404b540aSrobert 			      AS2 (st,X,__tmp_reg__)   CR_TAB
2550*404b540aSrobert 			      AS2 (sbiw,r26,%o0));
2551*404b540aSrobert 	    }
2552*404b540aSrobert 	  else
2553*404b540aSrobert 	    {
2554*404b540aSrobert 	      if (reg_unused_after (insn, XEXP (x,0)))
2555*404b540aSrobert 		return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2556*404b540aSrobert 				AS2 (st,X,%1));
2557*404b540aSrobert 
2558*404b540aSrobert 	      return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2559*404b540aSrobert 			      AS2 (st,X,%1)      CR_TAB
2560*404b540aSrobert 			      AS2 (sbiw,r26,%o0));
2561*404b540aSrobert 	    }
2562*404b540aSrobert 	}
2563*404b540aSrobert       *l = 1;
2564*404b540aSrobert       return AS2 (std,%0,%1);
2565*404b540aSrobert     }
2566*404b540aSrobert   *l = 1;
2567*404b540aSrobert   return AS2 (st,%0,%1);
2568*404b540aSrobert }
2569*404b540aSrobert 
2570*404b540aSrobert const char *
out_movhi_mr_r(rtx insn,rtx op[],int * l)2571*404b540aSrobert out_movhi_mr_r (rtx insn, rtx op[], int *l)
2572*404b540aSrobert {
2573*404b540aSrobert   rtx dest = op[0];
2574*404b540aSrobert   rtx src = op[1];
2575*404b540aSrobert   rtx base = XEXP (dest, 0);
2576*404b540aSrobert   int reg_base = true_regnum (base);
2577*404b540aSrobert   int reg_src = true_regnum (src);
2578*404b540aSrobert   /* "volatile" forces writing high byte first, even if less efficient,
2579*404b540aSrobert      for correct operation with 16-bit I/O registers.  */
2580*404b540aSrobert   int mem_volatile_p = MEM_VOLATILE_P (dest);
2581*404b540aSrobert   int tmp;
2582*404b540aSrobert 
2583*404b540aSrobert   if (!l)
2584*404b540aSrobert     l = &tmp;
2585*404b540aSrobert   if (CONSTANT_ADDRESS_P (base))
2586*404b540aSrobert     {
2587*404b540aSrobert       if (avr_io_address_p (base, 2))
2588*404b540aSrobert 	{
2589*404b540aSrobert 	  *l = 2;
2590*404b540aSrobert 	  return (AS2 (out,%B0-0x20,%B1) CR_TAB
2591*404b540aSrobert 		  AS2 (out,%A0-0x20,%A1));
2592*404b540aSrobert 	}
2593*404b540aSrobert       return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2594*404b540aSrobert 		      AS2 (sts,%A0,%A1));
2595*404b540aSrobert     }
2596*404b540aSrobert   if (reg_base > 0)
2597*404b540aSrobert     {
2598*404b540aSrobert       if (reg_base == REG_X)
2599*404b540aSrobert         {
2600*404b540aSrobert           if (reg_src == REG_X)
2601*404b540aSrobert             {
2602*404b540aSrobert               /* "st X+,r26" and "st -X,r26" are undefined.  */
2603*404b540aSrobert               if (!mem_volatile_p && reg_unused_after (insn, src))
2604*404b540aSrobert 		return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2605*404b540aSrobert 			      AS2 (st,X,r26)            CR_TAB
2606*404b540aSrobert 			      AS2 (adiw,r26,1)          CR_TAB
2607*404b540aSrobert 			      AS2 (st,X,__tmp_reg__));
2608*404b540aSrobert               else
2609*404b540aSrobert 		return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2610*404b540aSrobert 			      AS2 (adiw,r26,1)          CR_TAB
2611*404b540aSrobert 			      AS2 (st,X,__tmp_reg__)    CR_TAB
2612*404b540aSrobert                               AS2 (sbiw,r26,1)          CR_TAB
2613*404b540aSrobert                               AS2 (st,X,r26));
2614*404b540aSrobert             }
2615*404b540aSrobert           else
2616*404b540aSrobert             {
2617*404b540aSrobert               if (!mem_volatile_p && reg_unused_after (insn, base))
2618*404b540aSrobert                 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2619*404b540aSrobert                               AS2 (st,X,%B1));
2620*404b540aSrobert               else
2621*404b540aSrobert                 return *l=3, (AS2 (adiw,r26,1) CR_TAB
2622*404b540aSrobert                               AS2 (st,X,%B1)   CR_TAB
2623*404b540aSrobert                               AS2 (st,-X,%A1));
2624*404b540aSrobert             }
2625*404b540aSrobert         }
2626*404b540aSrobert       else
2627*404b540aSrobert         return  *l=2, (AS2 (std,%0+1,%B1) CR_TAB
2628*404b540aSrobert                        AS2 (st,%0,%A1));
2629*404b540aSrobert     }
2630*404b540aSrobert   else if (GET_CODE (base) == PLUS)
2631*404b540aSrobert     {
2632*404b540aSrobert       int disp = INTVAL (XEXP (base, 1));
2633*404b540aSrobert       reg_base = REGNO (XEXP (base, 0));
2634*404b540aSrobert       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2635*404b540aSrobert 	{
2636*404b540aSrobert 	  if (reg_base != REG_Y)
2637*404b540aSrobert 	    fatal_insn ("incorrect insn:",insn);
2638*404b540aSrobert 
2639*404b540aSrobert 	  if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2640*404b540aSrobert 	    return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
2641*404b540aSrobert 			    AS2 (std,Y+63,%B1)    CR_TAB
2642*404b540aSrobert 			    AS2 (std,Y+62,%A1)    CR_TAB
2643*404b540aSrobert 			    AS2 (sbiw,r28,%o0-62));
2644*404b540aSrobert 
2645*404b540aSrobert 	  return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2646*404b540aSrobert 			  AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2647*404b540aSrobert 			  AS2 (std,Y+1,%B1)        CR_TAB
2648*404b540aSrobert 			  AS2 (st,Y,%A1)           CR_TAB
2649*404b540aSrobert 			  AS2 (subi,r28,lo8(%o0))  CR_TAB
2650*404b540aSrobert 			  AS2 (sbci,r29,hi8(%o0)));
2651*404b540aSrobert 	}
2652*404b540aSrobert       if (reg_base == REG_X)
2653*404b540aSrobert 	{
2654*404b540aSrobert 	  /* (X + d) = R */
2655*404b540aSrobert 	  if (reg_src == REG_X)
2656*404b540aSrobert             {
2657*404b540aSrobert 	      *l = 7;
2658*404b540aSrobert 	      return (AS2 (mov,__tmp_reg__,r26)  CR_TAB
2659*404b540aSrobert 		      AS2 (mov,__zero_reg__,r27) CR_TAB
2660*404b540aSrobert                       AS2 (adiw,r26,%o0+1)       CR_TAB
2661*404b540aSrobert 		      AS2 (st,X,__zero_reg__)    CR_TAB
2662*404b540aSrobert 		      AS2 (st,-X,__tmp_reg__)    CR_TAB
2663*404b540aSrobert 		      AS1 (clr,__zero_reg__)     CR_TAB
2664*404b540aSrobert                       AS2 (sbiw,r26,%o0));
2665*404b540aSrobert 	    }
2666*404b540aSrobert 	  *l = 4;
2667*404b540aSrobert           return (AS2 (adiw,r26,%o0+1) CR_TAB
2668*404b540aSrobert                   AS2 (st,X,%B1)       CR_TAB
2669*404b540aSrobert                   AS2 (st,-X,%A1)      CR_TAB
2670*404b540aSrobert                   AS2 (sbiw,r26,%o0));
2671*404b540aSrobert 	}
2672*404b540aSrobert       return *l=2, (AS2 (std,%B0,%B1)    CR_TAB
2673*404b540aSrobert                     AS2 (std,%A0,%A1));
2674*404b540aSrobert     }
2675*404b540aSrobert   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2676*404b540aSrobert     return *l=2, (AS2 (st,%0,%B1) CR_TAB
2677*404b540aSrobert 		  AS2 (st,%0,%A1));
2678*404b540aSrobert   else if (GET_CODE (base) == POST_INC) /* (R++) */
2679*404b540aSrobert     {
2680*404b540aSrobert       if (mem_volatile_p)
2681*404b540aSrobert         {
2682*404b540aSrobert           if (REGNO (XEXP (base, 0)) == REG_X)
2683*404b540aSrobert             {
2684*404b540aSrobert               *l = 4;
2685*404b540aSrobert               return (AS2 (adiw,r26,1)  CR_TAB
2686*404b540aSrobert                       AS2 (st,X,%B1)    CR_TAB
2687*404b540aSrobert                       AS2 (st,-X,%A1)   CR_TAB
2688*404b540aSrobert                       AS2 (adiw,r26,2));
2689*404b540aSrobert             }
2690*404b540aSrobert           else
2691*404b540aSrobert             {
2692*404b540aSrobert               *l = 3;
2693*404b540aSrobert               return (AS2 (std,%p0+1,%B1) CR_TAB
2694*404b540aSrobert                       AS2 (st,%p0,%A1)    CR_TAB
2695*404b540aSrobert                       AS2 (adiw,%r0,2));
2696*404b540aSrobert             }
2697*404b540aSrobert         }
2698*404b540aSrobert 
2699*404b540aSrobert       *l = 2;
2700*404b540aSrobert       return (AS2 (st,%0,%A1)  CR_TAB
2701*404b540aSrobert             AS2 (st,%0,%B1));
2702*404b540aSrobert     }
2703*404b540aSrobert   fatal_insn ("unknown move insn:",insn);
2704*404b540aSrobert   return "";
2705*404b540aSrobert }
2706*404b540aSrobert 
2707*404b540aSrobert /* Return 1 if frame pointer for current function required.  */
2708*404b540aSrobert 
2709*404b540aSrobert int
frame_pointer_required_p(void)2710*404b540aSrobert frame_pointer_required_p (void)
2711*404b540aSrobert {
2712*404b540aSrobert   return (current_function_calls_alloca
2713*404b540aSrobert 	  || current_function_args_info.nregs == 0
2714*404b540aSrobert   	  || get_frame_size () > 0);
2715*404b540aSrobert }
2716*404b540aSrobert 
2717*404b540aSrobert /* Returns the condition of compare insn INSN, or UNKNOWN.  */
2718*404b540aSrobert 
2719*404b540aSrobert static RTX_CODE
compare_condition(rtx insn)2720*404b540aSrobert compare_condition (rtx insn)
2721*404b540aSrobert {
2722*404b540aSrobert   rtx next = next_real_insn (insn);
2723*404b540aSrobert   RTX_CODE cond = UNKNOWN;
2724*404b540aSrobert   if (next && GET_CODE (next) == JUMP_INSN)
2725*404b540aSrobert     {
2726*404b540aSrobert       rtx pat = PATTERN (next);
2727*404b540aSrobert       rtx src = SET_SRC (pat);
2728*404b540aSrobert       rtx t = XEXP (src, 0);
2729*404b540aSrobert       cond = GET_CODE (t);
2730*404b540aSrobert     }
2731*404b540aSrobert   return cond;
2732*404b540aSrobert }
2733*404b540aSrobert 
2734*404b540aSrobert /* Returns nonzero if INSN is a tst insn that only tests the sign.  */
2735*404b540aSrobert 
2736*404b540aSrobert static int
compare_sign_p(rtx insn)2737*404b540aSrobert compare_sign_p (rtx insn)
2738*404b540aSrobert {
2739*404b540aSrobert   RTX_CODE cond = compare_condition (insn);
2740*404b540aSrobert   return (cond == GE || cond == LT);
2741*404b540aSrobert }
2742*404b540aSrobert 
2743*404b540aSrobert /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2744*404b540aSrobert    that needs to be swapped (GT, GTU, LE, LEU).  */
2745*404b540aSrobert 
2746*404b540aSrobert int
compare_diff_p(rtx insn)2747*404b540aSrobert compare_diff_p (rtx insn)
2748*404b540aSrobert {
2749*404b540aSrobert   RTX_CODE cond = compare_condition (insn);
2750*404b540aSrobert   return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2751*404b540aSrobert }
2752*404b540aSrobert 
2753*404b540aSrobert /* Returns nonzero if INSN is a compare insn with the EQ or NE condition.  */
2754*404b540aSrobert 
2755*404b540aSrobert int
compare_eq_p(rtx insn)2756*404b540aSrobert compare_eq_p (rtx insn)
2757*404b540aSrobert {
2758*404b540aSrobert   RTX_CODE cond = compare_condition (insn);
2759*404b540aSrobert   return (cond == EQ || cond == NE);
2760*404b540aSrobert }
2761*404b540aSrobert 
2762*404b540aSrobert 
2763*404b540aSrobert /* Output test instruction for HImode.  */
2764*404b540aSrobert 
2765*404b540aSrobert const char *
out_tsthi(rtx insn,int * l)2766*404b540aSrobert out_tsthi (rtx insn, int *l)
2767*404b540aSrobert {
2768*404b540aSrobert   if (compare_sign_p (insn))
2769*404b540aSrobert     {
2770*404b540aSrobert       if (l) *l = 1;
2771*404b540aSrobert       return AS1 (tst,%B0);
2772*404b540aSrobert     }
2773*404b540aSrobert   if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2774*404b540aSrobert       && compare_eq_p (insn))
2775*404b540aSrobert     {
2776*404b540aSrobert       /* Faster than sbiw if we can clobber the operand.  */
2777*404b540aSrobert       if (l) *l = 1;
2778*404b540aSrobert       return AS2 (or,%A0,%B0);
2779*404b540aSrobert     }
2780*404b540aSrobert   if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2781*404b540aSrobert     {
2782*404b540aSrobert       if (l) *l = 1;
2783*404b540aSrobert       return AS2 (sbiw,%0,0);
2784*404b540aSrobert     }
2785*404b540aSrobert   if (l) *l = 2;
2786*404b540aSrobert   return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2787*404b540aSrobert           AS2 (cpc,%B0,__zero_reg__));
2788*404b540aSrobert }
2789*404b540aSrobert 
2790*404b540aSrobert 
2791*404b540aSrobert /* Output test instruction for SImode.  */
2792*404b540aSrobert 
2793*404b540aSrobert const char *
out_tstsi(rtx insn,int * l)2794*404b540aSrobert out_tstsi (rtx insn, int *l)
2795*404b540aSrobert {
2796*404b540aSrobert   if (compare_sign_p (insn))
2797*404b540aSrobert     {
2798*404b540aSrobert       if (l) *l = 1;
2799*404b540aSrobert       return AS1 (tst,%D0);
2800*404b540aSrobert     }
2801*404b540aSrobert   if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2802*404b540aSrobert     {
2803*404b540aSrobert       if (l) *l = 3;
2804*404b540aSrobert       return (AS2 (sbiw,%A0,0) CR_TAB
2805*404b540aSrobert               AS2 (cpc,%C0,__zero_reg__) CR_TAB
2806*404b540aSrobert               AS2 (cpc,%D0,__zero_reg__));
2807*404b540aSrobert     }
2808*404b540aSrobert   if (l) *l = 4;
2809*404b540aSrobert   return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2810*404b540aSrobert           AS2 (cpc,%B0,__zero_reg__) CR_TAB
2811*404b540aSrobert           AS2 (cpc,%C0,__zero_reg__) CR_TAB
2812*404b540aSrobert           AS2 (cpc,%D0,__zero_reg__));
2813*404b540aSrobert }
2814*404b540aSrobert 
2815*404b540aSrobert 
2816*404b540aSrobert /* Generate asm equivalent for various shifts.
2817*404b540aSrobert    Shift count is a CONST_INT, MEM or REG.
2818*404b540aSrobert    This only handles cases that are not already
2819*404b540aSrobert    carefully hand-optimized in ?sh??i3_out.  */
2820*404b540aSrobert 
2821*404b540aSrobert void
out_shift_with_cnt(const char * template,rtx insn,rtx operands[],int * len,int t_len)2822*404b540aSrobert out_shift_with_cnt (const char *template, rtx insn, rtx operands[],
2823*404b540aSrobert 		    int *len, int t_len)
2824*404b540aSrobert {
2825*404b540aSrobert   rtx op[10];
2826*404b540aSrobert   char str[500];
2827*404b540aSrobert   int second_label = 1;
2828*404b540aSrobert   int saved_in_tmp = 0;
2829*404b540aSrobert   int use_zero_reg = 0;
2830*404b540aSrobert 
2831*404b540aSrobert   op[0] = operands[0];
2832*404b540aSrobert   op[1] = operands[1];
2833*404b540aSrobert   op[2] = operands[2];
2834*404b540aSrobert   op[3] = operands[3];
2835*404b540aSrobert   str[0] = 0;
2836*404b540aSrobert 
2837*404b540aSrobert   if (len)
2838*404b540aSrobert     *len = 1;
2839*404b540aSrobert 
2840*404b540aSrobert   if (GET_CODE (operands[2]) == CONST_INT)
2841*404b540aSrobert     {
2842*404b540aSrobert       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2843*404b540aSrobert       int count = INTVAL (operands[2]);
2844*404b540aSrobert       int max_len = 10;  /* If larger than this, always use a loop.  */
2845*404b540aSrobert 
2846*404b540aSrobert       if (count <= 0)
2847*404b540aSrobert 	{
2848*404b540aSrobert 	  if (len)
2849*404b540aSrobert 	    *len = 0;
2850*404b540aSrobert 	  return;
2851*404b540aSrobert 	}
2852*404b540aSrobert 
2853*404b540aSrobert       if (count < 8 && !scratch)
2854*404b540aSrobert 	use_zero_reg = 1;
2855*404b540aSrobert 
2856*404b540aSrobert       if (optimize_size)
2857*404b540aSrobert 	max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2858*404b540aSrobert 
2859*404b540aSrobert       if (t_len * count <= max_len)
2860*404b540aSrobert 	{
2861*404b540aSrobert 	  /* Output shifts inline with no loop - faster.  */
2862*404b540aSrobert 	  if (len)
2863*404b540aSrobert 	    *len = t_len * count;
2864*404b540aSrobert 	  else
2865*404b540aSrobert 	    {
2866*404b540aSrobert 	      while (count-- > 0)
2867*404b540aSrobert 		output_asm_insn (template, op);
2868*404b540aSrobert 	    }
2869*404b540aSrobert 
2870*404b540aSrobert 	  return;
2871*404b540aSrobert 	}
2872*404b540aSrobert 
2873*404b540aSrobert       if (scratch)
2874*404b540aSrobert 	{
2875*404b540aSrobert 	  if (!len)
2876*404b540aSrobert 	    strcat (str, AS2 (ldi,%3,%2));
2877*404b540aSrobert 	}
2878*404b540aSrobert       else if (use_zero_reg)
2879*404b540aSrobert 	{
2880*404b540aSrobert 	  /* Hack to save one word: use __zero_reg__ as loop counter.
2881*404b540aSrobert 	     Set one bit, then shift in a loop until it is 0 again.  */
2882*404b540aSrobert 
2883*404b540aSrobert 	  op[3] = zero_reg_rtx;
2884*404b540aSrobert 	  if (len)
2885*404b540aSrobert 	    *len = 2;
2886*404b540aSrobert 	  else
2887*404b540aSrobert 	    strcat (str, ("set" CR_TAB
2888*404b540aSrobert 			  AS2 (bld,%3,%2-1)));
2889*404b540aSrobert 	}
2890*404b540aSrobert       else
2891*404b540aSrobert 	{
2892*404b540aSrobert 	  /* No scratch register available, use one from LD_REGS (saved in
2893*404b540aSrobert 	     __tmp_reg__) that doesn't overlap with registers to shift.  */
2894*404b540aSrobert 
2895*404b540aSrobert 	  op[3] = gen_rtx_REG (QImode,
2896*404b540aSrobert 			   ((true_regnum (operands[0]) - 1) & 15) + 16);
2897*404b540aSrobert 	  op[4] = tmp_reg_rtx;
2898*404b540aSrobert 	  saved_in_tmp = 1;
2899*404b540aSrobert 
2900*404b540aSrobert 	  if (len)
2901*404b540aSrobert 	    *len = 3;  /* Includes "mov %3,%4" after the loop.  */
2902*404b540aSrobert 	  else
2903*404b540aSrobert 	    strcat (str, (AS2 (mov,%4,%3) CR_TAB
2904*404b540aSrobert 			  AS2 (ldi,%3,%2)));
2905*404b540aSrobert 	}
2906*404b540aSrobert 
2907*404b540aSrobert       second_label = 0;
2908*404b540aSrobert     }
2909*404b540aSrobert   else if (GET_CODE (operands[2]) == MEM)
2910*404b540aSrobert     {
2911*404b540aSrobert       rtx op_mov[10];
2912*404b540aSrobert 
2913*404b540aSrobert       op[3] = op_mov[0] = tmp_reg_rtx;
2914*404b540aSrobert       op_mov[1] = op[2];
2915*404b540aSrobert 
2916*404b540aSrobert       if (len)
2917*404b540aSrobert 	out_movqi_r_mr (insn, op_mov, len);
2918*404b540aSrobert       else
2919*404b540aSrobert 	output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
2920*404b540aSrobert     }
2921*404b540aSrobert   else if (register_operand (operands[2], QImode))
2922*404b540aSrobert     {
2923*404b540aSrobert       if (reg_unused_after (insn, operands[2]))
2924*404b540aSrobert 	op[3] = op[2];
2925*404b540aSrobert       else
2926*404b540aSrobert 	{
2927*404b540aSrobert 	  op[3] = tmp_reg_rtx;
2928*404b540aSrobert 	  if (!len)
2929*404b540aSrobert 	    strcat (str, (AS2 (mov,%3,%2) CR_TAB));
2930*404b540aSrobert 	}
2931*404b540aSrobert     }
2932*404b540aSrobert   else
2933*404b540aSrobert     fatal_insn ("bad shift insn:", insn);
2934*404b540aSrobert 
2935*404b540aSrobert   if (second_label)
2936*404b540aSrobert     {
2937*404b540aSrobert       if (len)
2938*404b540aSrobert 	++*len;
2939*404b540aSrobert       else
2940*404b540aSrobert 	strcat (str, AS1 (rjmp,2f));
2941*404b540aSrobert     }
2942*404b540aSrobert 
2943*404b540aSrobert   if (len)
2944*404b540aSrobert     *len += t_len + 2;  /* template + dec + brXX */
2945*404b540aSrobert   else
2946*404b540aSrobert     {
2947*404b540aSrobert       strcat (str, "\n1:\t");
2948*404b540aSrobert       strcat (str, template);
2949*404b540aSrobert       strcat (str, second_label ? "\n2:\t" : "\n\t");
2950*404b540aSrobert       strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
2951*404b540aSrobert       strcat (str, CR_TAB);
2952*404b540aSrobert       strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
2953*404b540aSrobert       if (saved_in_tmp)
2954*404b540aSrobert 	strcat (str, (CR_TAB AS2 (mov,%3,%4)));
2955*404b540aSrobert       output_asm_insn (str, op);
2956*404b540aSrobert     }
2957*404b540aSrobert }
2958*404b540aSrobert 
2959*404b540aSrobert 
2960*404b540aSrobert /* 8bit shift left ((char)x << i)   */
2961*404b540aSrobert 
2962*404b540aSrobert const char *
ashlqi3_out(rtx insn,rtx operands[],int * len)2963*404b540aSrobert ashlqi3_out (rtx insn, rtx operands[], int *len)
2964*404b540aSrobert {
2965*404b540aSrobert   if (GET_CODE (operands[2]) == CONST_INT)
2966*404b540aSrobert     {
2967*404b540aSrobert       int k;
2968*404b540aSrobert 
2969*404b540aSrobert       if (!len)
2970*404b540aSrobert 	len = &k;
2971*404b540aSrobert 
2972*404b540aSrobert       switch (INTVAL (operands[2]))
2973*404b540aSrobert 	{
2974*404b540aSrobert 	default:
2975*404b540aSrobert 	  if (INTVAL (operands[2]) < 8)
2976*404b540aSrobert 	    break;
2977*404b540aSrobert 
2978*404b540aSrobert 	  *len = 1;
2979*404b540aSrobert 	  return AS1 (clr,%0);
2980*404b540aSrobert 
2981*404b540aSrobert 	case 1:
2982*404b540aSrobert 	  *len = 1;
2983*404b540aSrobert 	  return AS1 (lsl,%0);
2984*404b540aSrobert 
2985*404b540aSrobert 	case 2:
2986*404b540aSrobert 	  *len = 2;
2987*404b540aSrobert 	  return (AS1 (lsl,%0) CR_TAB
2988*404b540aSrobert 		  AS1 (lsl,%0));
2989*404b540aSrobert 
2990*404b540aSrobert 	case 3:
2991*404b540aSrobert 	  *len = 3;
2992*404b540aSrobert 	  return (AS1 (lsl,%0) CR_TAB
2993*404b540aSrobert 		  AS1 (lsl,%0) CR_TAB
2994*404b540aSrobert 		  AS1 (lsl,%0));
2995*404b540aSrobert 
2996*404b540aSrobert 	case 4:
2997*404b540aSrobert 	  if (test_hard_reg_class (LD_REGS, operands[0]))
2998*404b540aSrobert 	    {
2999*404b540aSrobert 	      *len = 2;
3000*404b540aSrobert 	      return (AS1 (swap,%0) CR_TAB
3001*404b540aSrobert 		      AS2 (andi,%0,0xf0));
3002*404b540aSrobert 	    }
3003*404b540aSrobert 	  *len = 4;
3004*404b540aSrobert 	  return (AS1 (lsl,%0) CR_TAB
3005*404b540aSrobert 		  AS1 (lsl,%0) CR_TAB
3006*404b540aSrobert 		  AS1 (lsl,%0) CR_TAB
3007*404b540aSrobert 		  AS1 (lsl,%0));
3008*404b540aSrobert 
3009*404b540aSrobert 	case 5:
3010*404b540aSrobert 	  if (test_hard_reg_class (LD_REGS, operands[0]))
3011*404b540aSrobert 	    {
3012*404b540aSrobert 	      *len = 3;
3013*404b540aSrobert 	      return (AS1 (swap,%0) CR_TAB
3014*404b540aSrobert 		      AS1 (lsl,%0)  CR_TAB
3015*404b540aSrobert 		      AS2 (andi,%0,0xe0));
3016*404b540aSrobert 	    }
3017*404b540aSrobert 	  *len = 5;
3018*404b540aSrobert 	  return (AS1 (lsl,%0) CR_TAB
3019*404b540aSrobert 		  AS1 (lsl,%0) CR_TAB
3020*404b540aSrobert 		  AS1 (lsl,%0) CR_TAB
3021*404b540aSrobert 		  AS1 (lsl,%0) CR_TAB
3022*404b540aSrobert 		  AS1 (lsl,%0));
3023*404b540aSrobert 
3024*404b540aSrobert 	case 6:
3025*404b540aSrobert 	  if (test_hard_reg_class (LD_REGS, operands[0]))
3026*404b540aSrobert 	    {
3027*404b540aSrobert 	      *len = 4;
3028*404b540aSrobert 	      return (AS1 (swap,%0) CR_TAB
3029*404b540aSrobert 		      AS1 (lsl,%0)  CR_TAB
3030*404b540aSrobert 		      AS1 (lsl,%0)  CR_TAB
3031*404b540aSrobert 		      AS2 (andi,%0,0xc0));
3032*404b540aSrobert 	    }
3033*404b540aSrobert 	  *len = 6;
3034*404b540aSrobert 	  return (AS1 (lsl,%0) CR_TAB
3035*404b540aSrobert 		  AS1 (lsl,%0) CR_TAB
3036*404b540aSrobert 		  AS1 (lsl,%0) CR_TAB
3037*404b540aSrobert 		  AS1 (lsl,%0) CR_TAB
3038*404b540aSrobert 		  AS1 (lsl,%0) CR_TAB
3039*404b540aSrobert 		  AS1 (lsl,%0));
3040*404b540aSrobert 
3041*404b540aSrobert 	case 7:
3042*404b540aSrobert 	  *len = 3;
3043*404b540aSrobert 	  return (AS1 (ror,%0) CR_TAB
3044*404b540aSrobert 		  AS1 (clr,%0) CR_TAB
3045*404b540aSrobert 		  AS1 (ror,%0));
3046*404b540aSrobert 	}
3047*404b540aSrobert     }
3048*404b540aSrobert   else if (CONSTANT_P (operands[2]))
3049*404b540aSrobert     fatal_insn ("internal compiler error.  Incorrect shift:", insn);
3050*404b540aSrobert 
3051*404b540aSrobert   out_shift_with_cnt (AS1 (lsl,%0),
3052*404b540aSrobert 		      insn, operands, len, 1);
3053*404b540aSrobert   return "";
3054*404b540aSrobert }
3055*404b540aSrobert 
3056*404b540aSrobert 
3057*404b540aSrobert /* 16bit shift left ((short)x << i)   */
3058*404b540aSrobert 
3059*404b540aSrobert const char *
ashlhi3_out(rtx insn,rtx operands[],int * len)3060*404b540aSrobert ashlhi3_out (rtx insn, rtx operands[], int *len)
3061*404b540aSrobert {
3062*404b540aSrobert   if (GET_CODE (operands[2]) == CONST_INT)
3063*404b540aSrobert     {
3064*404b540aSrobert       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3065*404b540aSrobert       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3066*404b540aSrobert       int k;
3067*404b540aSrobert       int *t = len;
3068*404b540aSrobert 
3069*404b540aSrobert       if (!len)
3070*404b540aSrobert 	len = &k;
3071*404b540aSrobert 
3072*404b540aSrobert       switch (INTVAL (operands[2]))
3073*404b540aSrobert 	{
3074*404b540aSrobert 	default:
3075*404b540aSrobert 	  if (INTVAL (operands[2]) < 16)
3076*404b540aSrobert 	    break;
3077*404b540aSrobert 
3078*404b540aSrobert 	  *len = 2;
3079*404b540aSrobert 	  return (AS1 (clr,%B0) CR_TAB
3080*404b540aSrobert 		  AS1 (clr,%A0));
3081*404b540aSrobert 
3082*404b540aSrobert 	case 4:
3083*404b540aSrobert 	  if (optimize_size && scratch)
3084*404b540aSrobert 	    break;  /* 5 */
3085*404b540aSrobert 	  if (ldi_ok)
3086*404b540aSrobert 	    {
3087*404b540aSrobert 	      *len = 6;
3088*404b540aSrobert 	      return (AS1 (swap,%A0)      CR_TAB
3089*404b540aSrobert 		      AS1 (swap,%B0)      CR_TAB
3090*404b540aSrobert 		      AS2 (andi,%B0,0xf0) CR_TAB
3091*404b540aSrobert 		      AS2 (eor,%B0,%A0)   CR_TAB
3092*404b540aSrobert 		      AS2 (andi,%A0,0xf0) CR_TAB
3093*404b540aSrobert 		      AS2 (eor,%B0,%A0));
3094*404b540aSrobert 	    }
3095*404b540aSrobert 	  if (scratch)
3096*404b540aSrobert 	    {
3097*404b540aSrobert 	      *len = 7;
3098*404b540aSrobert 	      return (AS1 (swap,%A0)    CR_TAB
3099*404b540aSrobert 		      AS1 (swap,%B0)    CR_TAB
3100*404b540aSrobert 		      AS2 (ldi,%3,0xf0) CR_TAB
3101*404b540aSrobert 		      AS2 (and,%B0,%3)  CR_TAB
3102*404b540aSrobert 		      AS2 (eor,%B0,%A0) CR_TAB
3103*404b540aSrobert 		      AS2 (and,%A0,%3)  CR_TAB
3104*404b540aSrobert 		      AS2 (eor,%B0,%A0));
3105*404b540aSrobert 	    }
3106*404b540aSrobert 	  break;  /* optimize_size ? 6 : 8 */
3107*404b540aSrobert 
3108*404b540aSrobert 	case 5:
3109*404b540aSrobert 	  if (optimize_size)
3110*404b540aSrobert 	    break;  /* scratch ? 5 : 6 */
3111*404b540aSrobert 	  if (ldi_ok)
3112*404b540aSrobert 	    {
3113*404b540aSrobert 	      *len = 8;
3114*404b540aSrobert 	      return (AS1 (lsl,%A0)       CR_TAB
3115*404b540aSrobert 		      AS1 (rol,%B0)       CR_TAB
3116*404b540aSrobert 		      AS1 (swap,%A0)      CR_TAB
3117*404b540aSrobert 		      AS1 (swap,%B0)      CR_TAB
3118*404b540aSrobert 		      AS2 (andi,%B0,0xf0) CR_TAB
3119*404b540aSrobert 		      AS2 (eor,%B0,%A0)   CR_TAB
3120*404b540aSrobert 		      AS2 (andi,%A0,0xf0) CR_TAB
3121*404b540aSrobert 		      AS2 (eor,%B0,%A0));
3122*404b540aSrobert 	    }
3123*404b540aSrobert 	  if (scratch)
3124*404b540aSrobert 	    {
3125*404b540aSrobert 	      *len = 9;
3126*404b540aSrobert 	      return (AS1 (lsl,%A0)     CR_TAB
3127*404b540aSrobert 		      AS1 (rol,%B0)     CR_TAB
3128*404b540aSrobert 		      AS1 (swap,%A0)    CR_TAB
3129*404b540aSrobert 		      AS1 (swap,%B0)    CR_TAB
3130*404b540aSrobert 		      AS2 (ldi,%3,0xf0) CR_TAB
3131*404b540aSrobert 		      AS2 (and,%B0,%3)  CR_TAB
3132*404b540aSrobert 		      AS2 (eor,%B0,%A0) CR_TAB
3133*404b540aSrobert 		      AS2 (and,%A0,%3)  CR_TAB
3134*404b540aSrobert 		      AS2 (eor,%B0,%A0));
3135*404b540aSrobert 	    }
3136*404b540aSrobert 	  break;  /* 10 */
3137*404b540aSrobert 
3138*404b540aSrobert 	case 6:
3139*404b540aSrobert 	  if (optimize_size)
3140*404b540aSrobert 	    break;  /* scratch ? 5 : 6 */
3141*404b540aSrobert 	  *len = 9;
3142*404b540aSrobert 	  return (AS1 (clr,__tmp_reg__) CR_TAB
3143*404b540aSrobert 		  AS1 (lsr,%B0)         CR_TAB
3144*404b540aSrobert 		  AS1 (ror,%A0)         CR_TAB
3145*404b540aSrobert 		  AS1 (ror,__tmp_reg__) CR_TAB
3146*404b540aSrobert 		  AS1 (lsr,%B0)         CR_TAB
3147*404b540aSrobert 		  AS1 (ror,%A0)         CR_TAB
3148*404b540aSrobert 		  AS1 (ror,__tmp_reg__) CR_TAB
3149*404b540aSrobert 		  AS2 (mov,%B0,%A0)     CR_TAB
3150*404b540aSrobert 		  AS2 (mov,%A0,__tmp_reg__));
3151*404b540aSrobert 
3152*404b540aSrobert 	case 7:
3153*404b540aSrobert 	  *len = 5;
3154*404b540aSrobert 	  return (AS1 (lsr,%B0)     CR_TAB
3155*404b540aSrobert 		  AS2 (mov,%B0,%A0) CR_TAB
3156*404b540aSrobert 		  AS1 (clr,%A0)     CR_TAB
3157*404b540aSrobert 		  AS1 (ror,%B0)     CR_TAB
3158*404b540aSrobert 		  AS1 (ror,%A0));
3159*404b540aSrobert 
3160*404b540aSrobert 	case 8:
3161*404b540aSrobert 	  if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
3162*404b540aSrobert 	    return *len = 1, AS1 (clr,%A0);
3163*404b540aSrobert 	  else
3164*404b540aSrobert 	    return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3165*404b540aSrobert 			      AS1 (clr,%A0));
3166*404b540aSrobert 
3167*404b540aSrobert 	case 9:
3168*404b540aSrobert 	  *len = 3;
3169*404b540aSrobert 	  return (AS2 (mov,%B0,%A0) CR_TAB
3170*404b540aSrobert 		  AS1 (clr,%A0)     CR_TAB
3171*404b540aSrobert 		  AS1 (lsl,%B0));
3172*404b540aSrobert 
3173*404b540aSrobert 	case 10:
3174*404b540aSrobert 	  *len = 4;
3175*404b540aSrobert 	  return (AS2 (mov,%B0,%A0) CR_TAB
3176*404b540aSrobert 		  AS1 (clr,%A0)     CR_TAB
3177*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3178*404b540aSrobert 		  AS1 (lsl,%B0));
3179*404b540aSrobert 
3180*404b540aSrobert 	case 11:
3181*404b540aSrobert 	  *len = 5;
3182*404b540aSrobert 	  return (AS2 (mov,%B0,%A0) CR_TAB
3183*404b540aSrobert 		  AS1 (clr,%A0)     CR_TAB
3184*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3185*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3186*404b540aSrobert 		  AS1 (lsl,%B0));
3187*404b540aSrobert 
3188*404b540aSrobert 	case 12:
3189*404b540aSrobert 	  if (ldi_ok)
3190*404b540aSrobert 	    {
3191*404b540aSrobert 	      *len = 4;
3192*404b540aSrobert 	      return (AS2 (mov,%B0,%A0) CR_TAB
3193*404b540aSrobert 		      AS1 (clr,%A0)     CR_TAB
3194*404b540aSrobert 		      AS1 (swap,%B0)    CR_TAB
3195*404b540aSrobert 		      AS2 (andi,%B0,0xf0));
3196*404b540aSrobert 	    }
3197*404b540aSrobert 	  if (scratch)
3198*404b540aSrobert 	    {
3199*404b540aSrobert 	      *len = 5;
3200*404b540aSrobert 	      return (AS2 (mov,%B0,%A0) CR_TAB
3201*404b540aSrobert 		      AS1 (clr,%A0)     CR_TAB
3202*404b540aSrobert 		      AS1 (swap,%B0)    CR_TAB
3203*404b540aSrobert 		      AS2 (ldi,%3,0xf0) CR_TAB
3204*404b540aSrobert 		      AS2 (and,%B0,%3));
3205*404b540aSrobert 	    }
3206*404b540aSrobert 	  *len = 6;
3207*404b540aSrobert 	  return (AS2 (mov,%B0,%A0) CR_TAB
3208*404b540aSrobert 		  AS1 (clr,%A0)     CR_TAB
3209*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3210*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3211*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3212*404b540aSrobert 		  AS1 (lsl,%B0));
3213*404b540aSrobert 
3214*404b540aSrobert 	case 13:
3215*404b540aSrobert 	  if (ldi_ok)
3216*404b540aSrobert 	    {
3217*404b540aSrobert 	      *len = 5;
3218*404b540aSrobert 	      return (AS2 (mov,%B0,%A0) CR_TAB
3219*404b540aSrobert 		      AS1 (clr,%A0)     CR_TAB
3220*404b540aSrobert 		      AS1 (swap,%B0)    CR_TAB
3221*404b540aSrobert 		      AS1 (lsl,%B0)     CR_TAB
3222*404b540aSrobert 		      AS2 (andi,%B0,0xe0));
3223*404b540aSrobert 	    }
3224*404b540aSrobert 	  if (AVR_ENHANCED && scratch)
3225*404b540aSrobert 	    {
3226*404b540aSrobert 	      *len = 5;
3227*404b540aSrobert 	      return (AS2 (ldi,%3,0x20) CR_TAB
3228*404b540aSrobert 		      AS2 (mul,%A0,%3)  CR_TAB
3229*404b540aSrobert 		      AS2 (mov,%B0,r0)  CR_TAB
3230*404b540aSrobert 		      AS1 (clr,%A0)     CR_TAB
3231*404b540aSrobert 		      AS1 (clr,__zero_reg__));
3232*404b540aSrobert 	    }
3233*404b540aSrobert 	  if (optimize_size && scratch)
3234*404b540aSrobert 	    break;  /* 5 */
3235*404b540aSrobert 	  if (scratch)
3236*404b540aSrobert 	    {
3237*404b540aSrobert 	      *len = 6;
3238*404b540aSrobert 	      return (AS2 (mov,%B0,%A0) CR_TAB
3239*404b540aSrobert 		      AS1 (clr,%A0)     CR_TAB
3240*404b540aSrobert 		      AS1 (swap,%B0)    CR_TAB
3241*404b540aSrobert 		      AS1 (lsl,%B0)     CR_TAB
3242*404b540aSrobert 		      AS2 (ldi,%3,0xe0) CR_TAB
3243*404b540aSrobert 		      AS2 (and,%B0,%3));
3244*404b540aSrobert 	    }
3245*404b540aSrobert 	  if (AVR_ENHANCED)
3246*404b540aSrobert 	    {
3247*404b540aSrobert 	      *len = 6;
3248*404b540aSrobert 	      return ("set"            CR_TAB
3249*404b540aSrobert 		      AS2 (bld,r1,5)   CR_TAB
3250*404b540aSrobert 		      AS2 (mul,%A0,r1) CR_TAB
3251*404b540aSrobert 		      AS2 (mov,%B0,r0) CR_TAB
3252*404b540aSrobert 		      AS1 (clr,%A0)    CR_TAB
3253*404b540aSrobert 		      AS1 (clr,__zero_reg__));
3254*404b540aSrobert 	    }
3255*404b540aSrobert 	  *len = 7;
3256*404b540aSrobert 	  return (AS2 (mov,%B0,%A0) CR_TAB
3257*404b540aSrobert 		  AS1 (clr,%A0)     CR_TAB
3258*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3259*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3260*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3261*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3262*404b540aSrobert 		  AS1 (lsl,%B0));
3263*404b540aSrobert 
3264*404b540aSrobert 	case 14:
3265*404b540aSrobert 	  if (AVR_ENHANCED && ldi_ok)
3266*404b540aSrobert 	    {
3267*404b540aSrobert 	      *len = 5;
3268*404b540aSrobert 	      return (AS2 (ldi,%B0,0x40) CR_TAB
3269*404b540aSrobert 		      AS2 (mul,%A0,%B0)  CR_TAB
3270*404b540aSrobert 		      AS2 (mov,%B0,r0)   CR_TAB
3271*404b540aSrobert 		      AS1 (clr,%A0)      CR_TAB
3272*404b540aSrobert 		      AS1 (clr,__zero_reg__));
3273*404b540aSrobert 	    }
3274*404b540aSrobert 	  if (AVR_ENHANCED && scratch)
3275*404b540aSrobert 	    {
3276*404b540aSrobert 	      *len = 5;
3277*404b540aSrobert 	      return (AS2 (ldi,%3,0x40) CR_TAB
3278*404b540aSrobert 		      AS2 (mul,%A0,%3)  CR_TAB
3279*404b540aSrobert 		      AS2 (mov,%B0,r0)  CR_TAB
3280*404b540aSrobert 		      AS1 (clr,%A0)     CR_TAB
3281*404b540aSrobert 		      AS1 (clr,__zero_reg__));
3282*404b540aSrobert 	    }
3283*404b540aSrobert 	  if (optimize_size && ldi_ok)
3284*404b540aSrobert 	    {
3285*404b540aSrobert 	      *len = 5;
3286*404b540aSrobert 	      return (AS2 (mov,%B0,%A0) CR_TAB
3287*404b540aSrobert 		      AS2 (ldi,%A0,6) "\n1:\t"
3288*404b540aSrobert 		      AS1 (lsl,%B0)     CR_TAB
3289*404b540aSrobert 		      AS1 (dec,%A0)     CR_TAB
3290*404b540aSrobert 		      AS1 (brne,1b));
3291*404b540aSrobert 	    }
3292*404b540aSrobert 	  if (optimize_size && scratch)
3293*404b540aSrobert 	    break;  /* 5 */
3294*404b540aSrobert 	  *len = 6;
3295*404b540aSrobert 	  return (AS1 (clr,%B0) CR_TAB
3296*404b540aSrobert 		  AS1 (lsr,%A0) CR_TAB
3297*404b540aSrobert 		  AS1 (ror,%B0) CR_TAB
3298*404b540aSrobert 		  AS1 (lsr,%A0) CR_TAB
3299*404b540aSrobert 		  AS1 (ror,%B0) CR_TAB
3300*404b540aSrobert 		  AS1 (clr,%A0));
3301*404b540aSrobert 
3302*404b540aSrobert 	case 15:
3303*404b540aSrobert 	  *len = 4;
3304*404b540aSrobert 	  return (AS1 (clr,%B0) CR_TAB
3305*404b540aSrobert 		  AS1 (lsr,%A0) CR_TAB
3306*404b540aSrobert 		  AS1 (ror,%B0) CR_TAB
3307*404b540aSrobert 		  AS1 (clr,%A0));
3308*404b540aSrobert 	}
3309*404b540aSrobert       len = t;
3310*404b540aSrobert     }
3311*404b540aSrobert   out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3312*404b540aSrobert 		       AS1 (rol,%B0)),
3313*404b540aSrobert 		       insn, operands, len, 2);
3314*404b540aSrobert   return "";
3315*404b540aSrobert }
3316*404b540aSrobert 
3317*404b540aSrobert 
3318*404b540aSrobert /* 32bit shift left ((long)x << i)   */
3319*404b540aSrobert 
3320*404b540aSrobert const char *
ashlsi3_out(rtx insn,rtx operands[],int * len)3321*404b540aSrobert ashlsi3_out (rtx insn, rtx operands[], int *len)
3322*404b540aSrobert {
3323*404b540aSrobert   if (GET_CODE (operands[2]) == CONST_INT)
3324*404b540aSrobert     {
3325*404b540aSrobert       int k;
3326*404b540aSrobert       int *t = len;
3327*404b540aSrobert 
3328*404b540aSrobert       if (!len)
3329*404b540aSrobert 	len = &k;
3330*404b540aSrobert 
3331*404b540aSrobert       switch (INTVAL (operands[2]))
3332*404b540aSrobert 	{
3333*404b540aSrobert 	default:
3334*404b540aSrobert 	  if (INTVAL (operands[2]) < 32)
3335*404b540aSrobert 	    break;
3336*404b540aSrobert 
3337*404b540aSrobert 	  if (AVR_HAVE_MOVW)
3338*404b540aSrobert 	    return *len = 3, (AS1 (clr,%D0) CR_TAB
3339*404b540aSrobert 			      AS1 (clr,%C0) CR_TAB
3340*404b540aSrobert 			      AS2 (movw,%A0,%C0));
3341*404b540aSrobert 	  *len = 4;
3342*404b540aSrobert 	  return (AS1 (clr,%D0) CR_TAB
3343*404b540aSrobert 		  AS1 (clr,%C0) CR_TAB
3344*404b540aSrobert 		  AS1 (clr,%B0) CR_TAB
3345*404b540aSrobert 		  AS1 (clr,%A0));
3346*404b540aSrobert 
3347*404b540aSrobert 	case 8:
3348*404b540aSrobert 	  {
3349*404b540aSrobert 	    int reg0 = true_regnum (operands[0]);
3350*404b540aSrobert 	    int reg1 = true_regnum (operands[1]);
3351*404b540aSrobert 	    *len = 4;
3352*404b540aSrobert 	    if (reg0 >= reg1)
3353*404b540aSrobert 	      return (AS2 (mov,%D0,%C1)  CR_TAB
3354*404b540aSrobert 		      AS2 (mov,%C0,%B1)  CR_TAB
3355*404b540aSrobert 		      AS2 (mov,%B0,%A1)  CR_TAB
3356*404b540aSrobert 		      AS1 (clr,%A0));
3357*404b540aSrobert 	    else if (reg0 + 1 == reg1)
3358*404b540aSrobert 	      {
3359*404b540aSrobert 		*len = 1;
3360*404b540aSrobert 		return AS1 (clr,%A0);
3361*404b540aSrobert 	      }
3362*404b540aSrobert 	    else
3363*404b540aSrobert 	      return (AS1 (clr,%A0)      CR_TAB
3364*404b540aSrobert 		      AS2 (mov,%B0,%A1)  CR_TAB
3365*404b540aSrobert 		      AS2 (mov,%C0,%B1)  CR_TAB
3366*404b540aSrobert 		      AS2 (mov,%D0,%C1));
3367*404b540aSrobert 	  }
3368*404b540aSrobert 
3369*404b540aSrobert 	case 16:
3370*404b540aSrobert 	  {
3371*404b540aSrobert 	    int reg0 = true_regnum (operands[0]);
3372*404b540aSrobert 	    int reg1 = true_regnum (operands[1]);
3373*404b540aSrobert 	    *len = 4;
3374*404b540aSrobert 	    if (AVR_HAVE_MOVW && (reg0 + 2 != reg1))
3375*404b540aSrobert 	      {
3376*404b540aSrobert 		*len = 3;
3377*404b540aSrobert 		return (AS2 (movw,%C0,%A1) CR_TAB
3378*404b540aSrobert 			AS1 (clr,%B0)      CR_TAB
3379*404b540aSrobert 			AS1 (clr,%A0));
3380*404b540aSrobert 	      }
3381*404b540aSrobert 	    if (reg0 + 1 >= reg1)
3382*404b540aSrobert 	      return (AS2 (mov,%D0,%B1)  CR_TAB
3383*404b540aSrobert 		      AS2 (mov,%C0,%A1)  CR_TAB
3384*404b540aSrobert 		      AS1 (clr,%B0)      CR_TAB
3385*404b540aSrobert 		      AS1 (clr,%A0));
3386*404b540aSrobert 	    if (reg0 + 2 == reg1)
3387*404b540aSrobert 	      {
3388*404b540aSrobert 		*len = 2;
3389*404b540aSrobert 		return (AS1 (clr,%B0)      CR_TAB
3390*404b540aSrobert 			AS1 (clr,%A0));
3391*404b540aSrobert 	      }
3392*404b540aSrobert 	    else
3393*404b540aSrobert 	      return (AS2 (mov,%C0,%A1)  CR_TAB
3394*404b540aSrobert 		      AS2 (mov,%D0,%B1)  CR_TAB
3395*404b540aSrobert 		      AS1 (clr,%B0)      CR_TAB
3396*404b540aSrobert 		      AS1 (clr,%A0));
3397*404b540aSrobert 	  }
3398*404b540aSrobert 
3399*404b540aSrobert 	case 24:
3400*404b540aSrobert 	  *len = 4;
3401*404b540aSrobert 	  if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
3402*404b540aSrobert 	    return (AS2 (mov,%D0,%A1)  CR_TAB
3403*404b540aSrobert 		    AS1 (clr,%C0)      CR_TAB
3404*404b540aSrobert 		    AS1 (clr,%B0)      CR_TAB
3405*404b540aSrobert 		    AS1 (clr,%A0));
3406*404b540aSrobert 	  else
3407*404b540aSrobert 	    {
3408*404b540aSrobert 	      *len = 3;
3409*404b540aSrobert 	      return (AS1 (clr,%C0)      CR_TAB
3410*404b540aSrobert 		      AS1 (clr,%B0)      CR_TAB
3411*404b540aSrobert 		      AS1 (clr,%A0));
3412*404b540aSrobert 	    }
3413*404b540aSrobert 
3414*404b540aSrobert 	case 31:
3415*404b540aSrobert 	  *len = 6;
3416*404b540aSrobert 	  return (AS1 (clr,%D0) CR_TAB
3417*404b540aSrobert 		  AS1 (lsr,%A0) CR_TAB
3418*404b540aSrobert 		  AS1 (ror,%D0) CR_TAB
3419*404b540aSrobert 		  AS1 (clr,%C0) CR_TAB
3420*404b540aSrobert 		  AS1 (clr,%B0) CR_TAB
3421*404b540aSrobert 		  AS1 (clr,%A0));
3422*404b540aSrobert 	}
3423*404b540aSrobert       len = t;
3424*404b540aSrobert     }
3425*404b540aSrobert   out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3426*404b540aSrobert 		       AS1 (rol,%B0) CR_TAB
3427*404b540aSrobert 		       AS1 (rol,%C0) CR_TAB
3428*404b540aSrobert 		       AS1 (rol,%D0)),
3429*404b540aSrobert 		       insn, operands, len, 4);
3430*404b540aSrobert   return "";
3431*404b540aSrobert }
3432*404b540aSrobert 
3433*404b540aSrobert /* 8bit arithmetic shift right  ((signed char)x >> i) */
3434*404b540aSrobert 
3435*404b540aSrobert const char *
ashrqi3_out(rtx insn,rtx operands[],int * len)3436*404b540aSrobert ashrqi3_out (rtx insn, rtx operands[], int *len)
3437*404b540aSrobert {
3438*404b540aSrobert   if (GET_CODE (operands[2]) == CONST_INT)
3439*404b540aSrobert     {
3440*404b540aSrobert       int k;
3441*404b540aSrobert 
3442*404b540aSrobert       if (!len)
3443*404b540aSrobert 	len = &k;
3444*404b540aSrobert 
3445*404b540aSrobert       switch (INTVAL (operands[2]))
3446*404b540aSrobert 	{
3447*404b540aSrobert 	case 1:
3448*404b540aSrobert 	  *len = 1;
3449*404b540aSrobert 	  return AS1 (asr,%0);
3450*404b540aSrobert 
3451*404b540aSrobert 	case 2:
3452*404b540aSrobert 	  *len = 2;
3453*404b540aSrobert 	  return (AS1 (asr,%0) CR_TAB
3454*404b540aSrobert 		  AS1 (asr,%0));
3455*404b540aSrobert 
3456*404b540aSrobert 	case 3:
3457*404b540aSrobert 	  *len = 3;
3458*404b540aSrobert 	  return (AS1 (asr,%0) CR_TAB
3459*404b540aSrobert 		  AS1 (asr,%0) CR_TAB
3460*404b540aSrobert 		  AS1 (asr,%0));
3461*404b540aSrobert 
3462*404b540aSrobert 	case 4:
3463*404b540aSrobert 	  *len = 4;
3464*404b540aSrobert 	  return (AS1 (asr,%0) CR_TAB
3465*404b540aSrobert 		  AS1 (asr,%0) CR_TAB
3466*404b540aSrobert 		  AS1 (asr,%0) CR_TAB
3467*404b540aSrobert 		  AS1 (asr,%0));
3468*404b540aSrobert 
3469*404b540aSrobert 	case 5:
3470*404b540aSrobert 	  *len = 5;
3471*404b540aSrobert 	  return (AS1 (asr,%0) CR_TAB
3472*404b540aSrobert 		  AS1 (asr,%0) CR_TAB
3473*404b540aSrobert 		  AS1 (asr,%0) CR_TAB
3474*404b540aSrobert 		  AS1 (asr,%0) CR_TAB
3475*404b540aSrobert 		  AS1 (asr,%0));
3476*404b540aSrobert 
3477*404b540aSrobert 	case 6:
3478*404b540aSrobert 	  *len = 4;
3479*404b540aSrobert 	  return (AS2 (bst,%0,6)  CR_TAB
3480*404b540aSrobert 		  AS1 (lsl,%0)    CR_TAB
3481*404b540aSrobert 		  AS2 (sbc,%0,%0) CR_TAB
3482*404b540aSrobert 		  AS2 (bld,%0,0));
3483*404b540aSrobert 
3484*404b540aSrobert 	default:
3485*404b540aSrobert 	  if (INTVAL (operands[2]) < 8)
3486*404b540aSrobert 	    break;
3487*404b540aSrobert 
3488*404b540aSrobert 	  /* fall through */
3489*404b540aSrobert 
3490*404b540aSrobert 	case 7:
3491*404b540aSrobert 	  *len = 2;
3492*404b540aSrobert 	  return (AS1 (lsl,%0) CR_TAB
3493*404b540aSrobert 		  AS2 (sbc,%0,%0));
3494*404b540aSrobert 	}
3495*404b540aSrobert     }
3496*404b540aSrobert   else if (CONSTANT_P (operands[2]))
3497*404b540aSrobert     fatal_insn ("internal compiler error.  Incorrect shift:", insn);
3498*404b540aSrobert 
3499*404b540aSrobert   out_shift_with_cnt (AS1 (asr,%0),
3500*404b540aSrobert 		      insn, operands, len, 1);
3501*404b540aSrobert   return "";
3502*404b540aSrobert }
3503*404b540aSrobert 
3504*404b540aSrobert 
3505*404b540aSrobert /* 16bit arithmetic shift right  ((signed short)x >> i) */
3506*404b540aSrobert 
3507*404b540aSrobert const char *
ashrhi3_out(rtx insn,rtx operands[],int * len)3508*404b540aSrobert ashrhi3_out (rtx insn, rtx operands[], int *len)
3509*404b540aSrobert {
3510*404b540aSrobert   if (GET_CODE (operands[2]) == CONST_INT)
3511*404b540aSrobert     {
3512*404b540aSrobert       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3513*404b540aSrobert       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3514*404b540aSrobert       int k;
3515*404b540aSrobert       int *t = len;
3516*404b540aSrobert 
3517*404b540aSrobert       if (!len)
3518*404b540aSrobert 	len = &k;
3519*404b540aSrobert 
3520*404b540aSrobert       switch (INTVAL (operands[2]))
3521*404b540aSrobert 	{
3522*404b540aSrobert 	case 4:
3523*404b540aSrobert 	case 5:
3524*404b540aSrobert 	  /* XXX try to optimize this too? */
3525*404b540aSrobert 	  break;
3526*404b540aSrobert 
3527*404b540aSrobert 	case 6:
3528*404b540aSrobert 	  if (optimize_size)
3529*404b540aSrobert 	    break;  /* scratch ? 5 : 6 */
3530*404b540aSrobert 	  *len = 8;
3531*404b540aSrobert 	  return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3532*404b540aSrobert 		  AS2 (mov,%A0,%B0)         CR_TAB
3533*404b540aSrobert 		  AS1 (lsl,__tmp_reg__)     CR_TAB
3534*404b540aSrobert 		  AS1 (rol,%A0)             CR_TAB
3535*404b540aSrobert 		  AS2 (sbc,%B0,%B0)         CR_TAB
3536*404b540aSrobert 		  AS1 (lsl,__tmp_reg__)     CR_TAB
3537*404b540aSrobert 		  AS1 (rol,%A0)             CR_TAB
3538*404b540aSrobert 		  AS1 (rol,%B0));
3539*404b540aSrobert 
3540*404b540aSrobert 	case 7:
3541*404b540aSrobert 	  *len = 4;
3542*404b540aSrobert 	  return (AS1 (lsl,%A0)     CR_TAB
3543*404b540aSrobert 		  AS2 (mov,%A0,%B0) CR_TAB
3544*404b540aSrobert 		  AS1 (rol,%A0)     CR_TAB
3545*404b540aSrobert 		  AS2 (sbc,%B0,%B0));
3546*404b540aSrobert 
3547*404b540aSrobert 	case 8:
3548*404b540aSrobert 	  {
3549*404b540aSrobert 	    int reg0 = true_regnum (operands[0]);
3550*404b540aSrobert 	    int reg1 = true_regnum (operands[1]);
3551*404b540aSrobert 
3552*404b540aSrobert 	    if (reg0 == reg1)
3553*404b540aSrobert 	      return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3554*404b540aSrobert 				AS1 (lsl,%B0)     CR_TAB
3555*404b540aSrobert 				AS2 (sbc,%B0,%B0));
3556*404b540aSrobert 	    else if (reg0 == reg1 + 1)
3557*404b540aSrobert 	      return *len = 3, (AS1 (clr,%B0)    CR_TAB
3558*404b540aSrobert 				AS2 (sbrc,%A0,7) CR_TAB
3559*404b540aSrobert 				AS1 (dec,%B0));
3560*404b540aSrobert 
3561*404b540aSrobert 	    return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3562*404b540aSrobert 			      AS1 (clr,%B0)     CR_TAB
3563*404b540aSrobert 			      AS2 (sbrc,%A0,7)  CR_TAB
3564*404b540aSrobert 			      AS1 (dec,%B0));
3565*404b540aSrobert 	  }
3566*404b540aSrobert 
3567*404b540aSrobert 	case 9:
3568*404b540aSrobert 	  *len = 4;
3569*404b540aSrobert 	  return (AS2 (mov,%A0,%B0) CR_TAB
3570*404b540aSrobert 		  AS1 (lsl,%B0)      CR_TAB
3571*404b540aSrobert 		  AS2 (sbc,%B0,%B0) CR_TAB
3572*404b540aSrobert 		  AS1 (asr,%A0));
3573*404b540aSrobert 
3574*404b540aSrobert 	case 10:
3575*404b540aSrobert 	  *len = 5;
3576*404b540aSrobert 	  return (AS2 (mov,%A0,%B0) CR_TAB
3577*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3578*404b540aSrobert 		  AS2 (sbc,%B0,%B0) CR_TAB
3579*404b540aSrobert 		  AS1 (asr,%A0)     CR_TAB
3580*404b540aSrobert 		  AS1 (asr,%A0));
3581*404b540aSrobert 
3582*404b540aSrobert 	case 11:
3583*404b540aSrobert 	  if (AVR_ENHANCED && ldi_ok)
3584*404b540aSrobert 	    {
3585*404b540aSrobert 	      *len = 5;
3586*404b540aSrobert 	      return (AS2 (ldi,%A0,0x20) CR_TAB
3587*404b540aSrobert 		      AS2 (muls,%B0,%A0) CR_TAB
3588*404b540aSrobert 		      AS2 (mov,%A0,r1)   CR_TAB
3589*404b540aSrobert 		      AS2 (sbc,%B0,%B0)  CR_TAB
3590*404b540aSrobert 		      AS1 (clr,__zero_reg__));
3591*404b540aSrobert 	    }
3592*404b540aSrobert 	  if (optimize_size && scratch)
3593*404b540aSrobert 	    break;  /* 5 */
3594*404b540aSrobert 	  *len = 6;
3595*404b540aSrobert 	  return (AS2 (mov,%A0,%B0) CR_TAB
3596*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3597*404b540aSrobert 		  AS2 (sbc,%B0,%B0) CR_TAB
3598*404b540aSrobert 		  AS1 (asr,%A0)     CR_TAB
3599*404b540aSrobert 		  AS1 (asr,%A0)     CR_TAB
3600*404b540aSrobert 		  AS1 (asr,%A0));
3601*404b540aSrobert 
3602*404b540aSrobert 	case 12:
3603*404b540aSrobert 	  if (AVR_ENHANCED && ldi_ok)
3604*404b540aSrobert 	    {
3605*404b540aSrobert 	      *len = 5;
3606*404b540aSrobert 	      return (AS2 (ldi,%A0,0x10) CR_TAB
3607*404b540aSrobert 		      AS2 (muls,%B0,%A0) CR_TAB
3608*404b540aSrobert 		      AS2 (mov,%A0,r1)   CR_TAB
3609*404b540aSrobert 		      AS2 (sbc,%B0,%B0)  CR_TAB
3610*404b540aSrobert 		      AS1 (clr,__zero_reg__));
3611*404b540aSrobert 	    }
3612*404b540aSrobert 	  if (optimize_size && scratch)
3613*404b540aSrobert 	    break;  /* 5 */
3614*404b540aSrobert 	  *len = 7;
3615*404b540aSrobert 	  return (AS2 (mov,%A0,%B0) CR_TAB
3616*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3617*404b540aSrobert 		  AS2 (sbc,%B0,%B0) CR_TAB
3618*404b540aSrobert 		  AS1 (asr,%A0)     CR_TAB
3619*404b540aSrobert 		  AS1 (asr,%A0)     CR_TAB
3620*404b540aSrobert 		  AS1 (asr,%A0)     CR_TAB
3621*404b540aSrobert 		  AS1 (asr,%A0));
3622*404b540aSrobert 
3623*404b540aSrobert 	case 13:
3624*404b540aSrobert 	  if (AVR_ENHANCED && ldi_ok)
3625*404b540aSrobert 	    {
3626*404b540aSrobert 	      *len = 5;
3627*404b540aSrobert 	      return (AS2 (ldi,%A0,0x08) CR_TAB
3628*404b540aSrobert 		      AS2 (muls,%B0,%A0) CR_TAB
3629*404b540aSrobert 		      AS2 (mov,%A0,r1)   CR_TAB
3630*404b540aSrobert 		      AS2 (sbc,%B0,%B0)  CR_TAB
3631*404b540aSrobert 		      AS1 (clr,__zero_reg__));
3632*404b540aSrobert 	    }
3633*404b540aSrobert 	  if (optimize_size)
3634*404b540aSrobert 	    break;  /* scratch ? 5 : 7 */
3635*404b540aSrobert 	  *len = 8;
3636*404b540aSrobert 	  return (AS2 (mov,%A0,%B0) CR_TAB
3637*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3638*404b540aSrobert 		  AS2 (sbc,%B0,%B0) CR_TAB
3639*404b540aSrobert 		  AS1 (asr,%A0)     CR_TAB
3640*404b540aSrobert 		  AS1 (asr,%A0)     CR_TAB
3641*404b540aSrobert 		  AS1 (asr,%A0)     CR_TAB
3642*404b540aSrobert 		  AS1 (asr,%A0)     CR_TAB
3643*404b540aSrobert 		  AS1 (asr,%A0));
3644*404b540aSrobert 
3645*404b540aSrobert 	case 14:
3646*404b540aSrobert 	  *len = 5;
3647*404b540aSrobert 	  return (AS1 (lsl,%B0)     CR_TAB
3648*404b540aSrobert 		  AS2 (sbc,%A0,%A0) CR_TAB
3649*404b540aSrobert 		  AS1 (lsl,%B0)     CR_TAB
3650*404b540aSrobert 		  AS2 (mov,%B0,%A0) CR_TAB
3651*404b540aSrobert 		  AS1 (rol,%A0));
3652*404b540aSrobert 
3653*404b540aSrobert 	default:
3654*404b540aSrobert 	  if (INTVAL (operands[2]) < 16)
3655*404b540aSrobert 	    break;
3656*404b540aSrobert 
3657*404b540aSrobert 	  /* fall through */
3658*404b540aSrobert 
3659*404b540aSrobert 	case 15:
3660*404b540aSrobert 	  return *len = 3, (AS1 (lsl,%B0)     CR_TAB
3661*404b540aSrobert 			    AS2 (sbc,%A0,%A0) CR_TAB
3662*404b540aSrobert 			    AS2 (mov,%B0,%A0));
3663*404b540aSrobert 	}
3664*404b540aSrobert       len = t;
3665*404b540aSrobert     }
3666*404b540aSrobert   out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3667*404b540aSrobert 		       AS1 (ror,%A0)),
3668*404b540aSrobert 		       insn, operands, len, 2);
3669*404b540aSrobert   return "";
3670*404b540aSrobert }
3671*404b540aSrobert 
3672*404b540aSrobert 
3673*404b540aSrobert /* 32bit arithmetic shift right  ((signed long)x >> i) */
3674*404b540aSrobert 
3675*404b540aSrobert const char *
ashrsi3_out(rtx insn,rtx operands[],int * len)3676*404b540aSrobert ashrsi3_out (rtx insn, rtx operands[], int *len)
3677*404b540aSrobert {
3678*404b540aSrobert   if (GET_CODE (operands[2]) == CONST_INT)
3679*404b540aSrobert     {
3680*404b540aSrobert       int k;
3681*404b540aSrobert       int *t = len;
3682*404b540aSrobert 
3683*404b540aSrobert       if (!len)
3684*404b540aSrobert 	len = &k;
3685*404b540aSrobert 
3686*404b540aSrobert       switch (INTVAL (operands[2]))
3687*404b540aSrobert 	{
3688*404b540aSrobert 	case 8:
3689*404b540aSrobert 	  {
3690*404b540aSrobert 	    int reg0 = true_regnum (operands[0]);
3691*404b540aSrobert 	    int reg1 = true_regnum (operands[1]);
3692*404b540aSrobert 	    *len=6;
3693*404b540aSrobert 	    if (reg0 <= reg1)
3694*404b540aSrobert 	      return (AS2 (mov,%A0,%B1) CR_TAB
3695*404b540aSrobert 		      AS2 (mov,%B0,%C1) CR_TAB
3696*404b540aSrobert 		      AS2 (mov,%C0,%D1) CR_TAB
3697*404b540aSrobert 		      AS1 (clr,%D0)     CR_TAB
3698*404b540aSrobert 		      AS2 (sbrc,%C0,7)  CR_TAB
3699*404b540aSrobert 		      AS1 (dec,%D0));
3700*404b540aSrobert 	    else if (reg0 == reg1 + 1)
3701*404b540aSrobert 	      {
3702*404b540aSrobert 		*len = 3;
3703*404b540aSrobert 		return (AS1 (clr,%D0)     CR_TAB
3704*404b540aSrobert 			AS2 (sbrc,%C0,7)  CR_TAB
3705*404b540aSrobert 			AS1 (dec,%D0));
3706*404b540aSrobert 	      }
3707*404b540aSrobert 	    else
3708*404b540aSrobert 	      return (AS1 (clr,%D0)     CR_TAB
3709*404b540aSrobert 		      AS2 (sbrc,%D1,7)  CR_TAB
3710*404b540aSrobert 		      AS1 (dec,%D0)     CR_TAB
3711*404b540aSrobert 		      AS2 (mov,%C0,%D1) CR_TAB
3712*404b540aSrobert 		      AS2 (mov,%B0,%C1) CR_TAB
3713*404b540aSrobert 		      AS2 (mov,%A0,%B1));
3714*404b540aSrobert 	  }
3715*404b540aSrobert 
3716*404b540aSrobert 	case 16:
3717*404b540aSrobert 	  {
3718*404b540aSrobert 	    int reg0 = true_regnum (operands[0]);
3719*404b540aSrobert 	    int reg1 = true_regnum (operands[1]);
3720*404b540aSrobert 	    *len=6;
3721*404b540aSrobert 	    if (AVR_HAVE_MOVW && (reg0 != reg1 + 2))
3722*404b540aSrobert 	      {
3723*404b540aSrobert 		*len = 5;
3724*404b540aSrobert 		return (AS2 (movw,%A0,%C1) CR_TAB
3725*404b540aSrobert 			AS1 (clr,%D0)      CR_TAB
3726*404b540aSrobert 			AS2 (sbrc,%B0,7)   CR_TAB
3727*404b540aSrobert 			AS1 (com,%D0)      CR_TAB
3728*404b540aSrobert 			AS2 (mov,%C0,%D0));
3729*404b540aSrobert 	      }
3730*404b540aSrobert 	    if (reg0 <= reg1 + 1)
3731*404b540aSrobert 	      return (AS2 (mov,%A0,%C1) CR_TAB
3732*404b540aSrobert 		      AS2 (mov,%B0,%D1) CR_TAB
3733*404b540aSrobert 		      AS1 (clr,%D0)     CR_TAB
3734*404b540aSrobert 		      AS2 (sbrc,%B0,7)  CR_TAB
3735*404b540aSrobert 		      AS1 (com,%D0)     CR_TAB
3736*404b540aSrobert 		      AS2 (mov,%C0,%D0));
3737*404b540aSrobert 	    else if (reg0 == reg1 + 2)
3738*404b540aSrobert 	      return *len = 4, (AS1 (clr,%D0)     CR_TAB
3739*404b540aSrobert 				AS2 (sbrc,%B0,7)  CR_TAB
3740*404b540aSrobert 				AS1 (com,%D0)     CR_TAB
3741*404b540aSrobert 				AS2 (mov,%C0,%D0));
3742*404b540aSrobert 	    else
3743*404b540aSrobert 	      return (AS2 (mov,%B0,%D1) CR_TAB
3744*404b540aSrobert 		      AS2 (mov,%A0,%C1) CR_TAB
3745*404b540aSrobert 		      AS1 (clr,%D0)     CR_TAB
3746*404b540aSrobert 		      AS2 (sbrc,%B0,7)  CR_TAB
3747*404b540aSrobert 		      AS1 (com,%D0)     CR_TAB
3748*404b540aSrobert 		      AS2 (mov,%C0,%D0));
3749*404b540aSrobert 	  }
3750*404b540aSrobert 
3751*404b540aSrobert 	case 24:
3752*404b540aSrobert 	  if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
3753*404b540aSrobert 	    return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3754*404b540aSrobert 			      AS1 (clr,%D0)     CR_TAB
3755*404b540aSrobert 			      AS2 (sbrc,%A0,7)  CR_TAB
3756*404b540aSrobert 			      AS1 (com,%D0)     CR_TAB
3757*404b540aSrobert 			      AS2 (mov,%B0,%D0) CR_TAB
3758*404b540aSrobert 			      AS2 (mov,%C0,%D0));
3759*404b540aSrobert 	  else
3760*404b540aSrobert 	    return *len = 5, (AS1 (clr,%D0)     CR_TAB
3761*404b540aSrobert 			      AS2 (sbrc,%A0,7)  CR_TAB
3762*404b540aSrobert 			      AS1 (com,%D0)     CR_TAB
3763*404b540aSrobert 			      AS2 (mov,%B0,%D0) CR_TAB
3764*404b540aSrobert 			      AS2 (mov,%C0,%D0));
3765*404b540aSrobert 
3766*404b540aSrobert 	default:
3767*404b540aSrobert 	  if (INTVAL (operands[2]) < 32)
3768*404b540aSrobert 	    break;
3769*404b540aSrobert 
3770*404b540aSrobert 	  /* fall through */
3771*404b540aSrobert 
3772*404b540aSrobert 	case 31:
3773*404b540aSrobert 	  if (AVR_HAVE_MOVW)
3774*404b540aSrobert 	    return *len = 4, (AS1 (lsl,%D0)     CR_TAB
3775*404b540aSrobert 			      AS2 (sbc,%A0,%A0) CR_TAB
3776*404b540aSrobert 			      AS2 (mov,%B0,%A0) CR_TAB
3777*404b540aSrobert 			      AS2 (movw,%C0,%A0));
3778*404b540aSrobert 	  else
3779*404b540aSrobert 	    return *len = 5, (AS1 (lsl,%D0)     CR_TAB
3780*404b540aSrobert 			      AS2 (sbc,%A0,%A0) CR_TAB
3781*404b540aSrobert 			      AS2 (mov,%B0,%A0) CR_TAB
3782*404b540aSrobert 			      AS2 (mov,%C0,%A0) CR_TAB
3783*404b540aSrobert 			      AS2 (mov,%D0,%A0));
3784*404b540aSrobert 	}
3785*404b540aSrobert       len = t;
3786*404b540aSrobert     }
3787*404b540aSrobert   out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3788*404b540aSrobert 		       AS1 (ror,%C0) CR_TAB
3789*404b540aSrobert 		       AS1 (ror,%B0) CR_TAB
3790*404b540aSrobert 		       AS1 (ror,%A0)),
3791*404b540aSrobert 		       insn, operands, len, 4);
3792*404b540aSrobert   return "";
3793*404b540aSrobert }
3794*404b540aSrobert 
3795*404b540aSrobert /* 8bit logic shift right ((unsigned char)x >> i) */
3796*404b540aSrobert 
3797*404b540aSrobert const char *
lshrqi3_out(rtx insn,rtx operands[],int * len)3798*404b540aSrobert lshrqi3_out (rtx insn, rtx operands[], int *len)
3799*404b540aSrobert {
3800*404b540aSrobert   if (GET_CODE (operands[2]) == CONST_INT)
3801*404b540aSrobert     {
3802*404b540aSrobert       int k;
3803*404b540aSrobert 
3804*404b540aSrobert       if (!len)
3805*404b540aSrobert 	len = &k;
3806*404b540aSrobert 
3807*404b540aSrobert       switch (INTVAL (operands[2]))
3808*404b540aSrobert 	{
3809*404b540aSrobert 	default:
3810*404b540aSrobert 	  if (INTVAL (operands[2]) < 8)
3811*404b540aSrobert 	    break;
3812*404b540aSrobert 
3813*404b540aSrobert 	  *len = 1;
3814*404b540aSrobert 	  return AS1 (clr,%0);
3815*404b540aSrobert 
3816*404b540aSrobert 	case 1:
3817*404b540aSrobert 	  *len = 1;
3818*404b540aSrobert 	  return AS1 (lsr,%0);
3819*404b540aSrobert 
3820*404b540aSrobert 	case 2:
3821*404b540aSrobert 	  *len = 2;
3822*404b540aSrobert 	  return (AS1 (lsr,%0) CR_TAB
3823*404b540aSrobert 		  AS1 (lsr,%0));
3824*404b540aSrobert 	case 3:
3825*404b540aSrobert 	  *len = 3;
3826*404b540aSrobert 	  return (AS1 (lsr,%0) CR_TAB
3827*404b540aSrobert 		  AS1 (lsr,%0) CR_TAB
3828*404b540aSrobert 		  AS1 (lsr,%0));
3829*404b540aSrobert 
3830*404b540aSrobert 	case 4:
3831*404b540aSrobert 	  if (test_hard_reg_class (LD_REGS, operands[0]))
3832*404b540aSrobert 	    {
3833*404b540aSrobert 	      *len=2;
3834*404b540aSrobert 	      return (AS1 (swap,%0) CR_TAB
3835*404b540aSrobert 		      AS2 (andi,%0,0x0f));
3836*404b540aSrobert 	    }
3837*404b540aSrobert 	  *len = 4;
3838*404b540aSrobert 	  return (AS1 (lsr,%0) CR_TAB
3839*404b540aSrobert 		  AS1 (lsr,%0) CR_TAB
3840*404b540aSrobert 		  AS1 (lsr,%0) CR_TAB
3841*404b540aSrobert 		  AS1 (lsr,%0));
3842*404b540aSrobert 
3843*404b540aSrobert 	case 5:
3844*404b540aSrobert 	  if (test_hard_reg_class (LD_REGS, operands[0]))
3845*404b540aSrobert 	    {
3846*404b540aSrobert 	      *len = 3;
3847*404b540aSrobert 	      return (AS1 (swap,%0) CR_TAB
3848*404b540aSrobert 		      AS1 (lsr,%0)  CR_TAB
3849*404b540aSrobert 		      AS2 (andi,%0,0x7));
3850*404b540aSrobert 	    }
3851*404b540aSrobert 	  *len = 5;
3852*404b540aSrobert 	  return (AS1 (lsr,%0) CR_TAB
3853*404b540aSrobert 		  AS1 (lsr,%0) CR_TAB
3854*404b540aSrobert 		  AS1 (lsr,%0) CR_TAB
3855*404b540aSrobert 		  AS1 (lsr,%0) CR_TAB
3856*404b540aSrobert 		  AS1 (lsr,%0));
3857*404b540aSrobert 
3858*404b540aSrobert 	case 6:
3859*404b540aSrobert 	  if (test_hard_reg_class (LD_REGS, operands[0]))
3860*404b540aSrobert 	    {
3861*404b540aSrobert 	      *len = 4;
3862*404b540aSrobert 	      return (AS1 (swap,%0) CR_TAB
3863*404b540aSrobert 		      AS1 (lsr,%0)  CR_TAB
3864*404b540aSrobert 		      AS1 (lsr,%0)  CR_TAB
3865*404b540aSrobert 		      AS2 (andi,%0,0x3));
3866*404b540aSrobert 	    }
3867*404b540aSrobert 	  *len = 6;
3868*404b540aSrobert 	  return (AS1 (lsr,%0) CR_TAB
3869*404b540aSrobert 		  AS1 (lsr,%0) CR_TAB
3870*404b540aSrobert 		  AS1 (lsr,%0) CR_TAB
3871*404b540aSrobert 		  AS1 (lsr,%0) CR_TAB
3872*404b540aSrobert 		  AS1 (lsr,%0) CR_TAB
3873*404b540aSrobert 		  AS1 (lsr,%0));
3874*404b540aSrobert 
3875*404b540aSrobert 	case 7:
3876*404b540aSrobert 	  *len = 3;
3877*404b540aSrobert 	  return (AS1 (rol,%0) CR_TAB
3878*404b540aSrobert 		  AS1 (clr,%0) CR_TAB
3879*404b540aSrobert 		  AS1 (rol,%0));
3880*404b540aSrobert 	}
3881*404b540aSrobert     }
3882*404b540aSrobert   else if (CONSTANT_P (operands[2]))
3883*404b540aSrobert     fatal_insn ("internal compiler error.  Incorrect shift:", insn);
3884*404b540aSrobert 
3885*404b540aSrobert   out_shift_with_cnt (AS1 (lsr,%0),
3886*404b540aSrobert 		      insn, operands, len, 1);
3887*404b540aSrobert   return "";
3888*404b540aSrobert }
3889*404b540aSrobert 
3890*404b540aSrobert /* 16bit logic shift right ((unsigned short)x >> i) */
3891*404b540aSrobert 
3892*404b540aSrobert const char *
lshrhi3_out(rtx insn,rtx operands[],int * len)3893*404b540aSrobert lshrhi3_out (rtx insn, rtx operands[], int *len)
3894*404b540aSrobert {
3895*404b540aSrobert   if (GET_CODE (operands[2]) == CONST_INT)
3896*404b540aSrobert     {
3897*404b540aSrobert       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3898*404b540aSrobert       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
3899*404b540aSrobert       int k;
3900*404b540aSrobert       int *t = len;
3901*404b540aSrobert 
3902*404b540aSrobert       if (!len)
3903*404b540aSrobert 	len = &k;
3904*404b540aSrobert 
3905*404b540aSrobert       switch (INTVAL (operands[2]))
3906*404b540aSrobert 	{
3907*404b540aSrobert 	default:
3908*404b540aSrobert 	  if (INTVAL (operands[2]) < 16)
3909*404b540aSrobert 	    break;
3910*404b540aSrobert 
3911*404b540aSrobert 	  *len = 2;
3912*404b540aSrobert 	  return (AS1 (clr,%B0) CR_TAB
3913*404b540aSrobert 		  AS1 (clr,%A0));
3914*404b540aSrobert 
3915*404b540aSrobert 	case 4:
3916*404b540aSrobert 	  if (optimize_size && scratch)
3917*404b540aSrobert 	    break;  /* 5 */
3918*404b540aSrobert 	  if (ldi_ok)
3919*404b540aSrobert 	    {
3920*404b540aSrobert 	      *len = 6;
3921*404b540aSrobert 	      return (AS1 (swap,%B0)      CR_TAB
3922*404b540aSrobert 		      AS1 (swap,%A0)      CR_TAB
3923*404b540aSrobert 		      AS2 (andi,%A0,0x0f) CR_TAB
3924*404b540aSrobert 		      AS2 (eor,%A0,%B0)   CR_TAB
3925*404b540aSrobert 		      AS2 (andi,%B0,0x0f) CR_TAB
3926*404b540aSrobert 		      AS2 (eor,%A0,%B0));
3927*404b540aSrobert 	    }
3928*404b540aSrobert 	  if (scratch)
3929*404b540aSrobert 	    {
3930*404b540aSrobert 	      *len = 7;
3931*404b540aSrobert 	      return (AS1 (swap,%B0)    CR_TAB
3932*404b540aSrobert 		      AS1 (swap,%A0)    CR_TAB
3933*404b540aSrobert 		      AS2 (ldi,%3,0x0f) CR_TAB
3934*404b540aSrobert 		      AS2 (and,%A0,%3)  CR_TAB
3935*404b540aSrobert 		      AS2 (eor,%A0,%B0) CR_TAB
3936*404b540aSrobert 		      AS2 (and,%B0,%3)  CR_TAB
3937*404b540aSrobert 		      AS2 (eor,%A0,%B0));
3938*404b540aSrobert 	    }
3939*404b540aSrobert 	  break;  /* optimize_size ? 6 : 8 */
3940*404b540aSrobert 
3941*404b540aSrobert 	case 5:
3942*404b540aSrobert 	  if (optimize_size)
3943*404b540aSrobert 	    break;  /* scratch ? 5 : 6 */
3944*404b540aSrobert 	  if (ldi_ok)
3945*404b540aSrobert 	    {
3946*404b540aSrobert 	      *len = 8;
3947*404b540aSrobert 	      return (AS1 (lsr,%B0)       CR_TAB
3948*404b540aSrobert 		      AS1 (ror,%A0)       CR_TAB
3949*404b540aSrobert 		      AS1 (swap,%B0)      CR_TAB
3950*404b540aSrobert 		      AS1 (swap,%A0)      CR_TAB
3951*404b540aSrobert 		      AS2 (andi,%A0,0x0f) CR_TAB
3952*404b540aSrobert 		      AS2 (eor,%A0,%B0)   CR_TAB
3953*404b540aSrobert 		      AS2 (andi,%B0,0x0f) CR_TAB
3954*404b540aSrobert 		      AS2 (eor,%A0,%B0));
3955*404b540aSrobert 	    }
3956*404b540aSrobert 	  if (scratch)
3957*404b540aSrobert 	    {
3958*404b540aSrobert 	      *len = 9;
3959*404b540aSrobert 	      return (AS1 (lsr,%B0)     CR_TAB
3960*404b540aSrobert 		      AS1 (ror,%A0)     CR_TAB
3961*404b540aSrobert 		      AS1 (swap,%B0)    CR_TAB
3962*404b540aSrobert 		      AS1 (swap,%A0)    CR_TAB
3963*404b540aSrobert 		      AS2 (ldi,%3,0x0f) CR_TAB
3964*404b540aSrobert 		      AS2 (and,%A0,%3)  CR_TAB
3965*404b540aSrobert 		      AS2 (eor,%A0,%B0) CR_TAB
3966*404b540aSrobert 		      AS2 (and,%B0,%3)  CR_TAB
3967*404b540aSrobert 		      AS2 (eor,%A0,%B0));
3968*404b540aSrobert 	    }
3969*404b540aSrobert 	  break;  /* 10 */
3970*404b540aSrobert 
3971*404b540aSrobert 	case 6:
3972*404b540aSrobert 	  if (optimize_size)
3973*404b540aSrobert 	    break;  /* scratch ? 5 : 6 */
3974*404b540aSrobert 	  *len = 9;
3975*404b540aSrobert 	  return (AS1 (clr,__tmp_reg__) CR_TAB
3976*404b540aSrobert 		  AS1 (lsl,%A0)         CR_TAB
3977*404b540aSrobert 		  AS1 (rol,%B0)         CR_TAB
3978*404b540aSrobert 		  AS1 (rol,__tmp_reg__) CR_TAB
3979*404b540aSrobert 		  AS1 (lsl,%A0)         CR_TAB
3980*404b540aSrobert 		  AS1 (rol,%B0)         CR_TAB
3981*404b540aSrobert 		  AS1 (rol,__tmp_reg__) CR_TAB
3982*404b540aSrobert 		  AS2 (mov,%A0,%B0)     CR_TAB
3983*404b540aSrobert 		  AS2 (mov,%B0,__tmp_reg__));
3984*404b540aSrobert 
3985*404b540aSrobert 	case 7:
3986*404b540aSrobert 	  *len = 5;
3987*404b540aSrobert 	  return (AS1 (lsl,%A0)     CR_TAB
3988*404b540aSrobert 		  AS2 (mov,%A0,%B0) CR_TAB
3989*404b540aSrobert 		  AS1 (rol,%A0)     CR_TAB
3990*404b540aSrobert 		  AS2 (sbc,%B0,%B0) CR_TAB
3991*404b540aSrobert 		  AS1 (neg,%B0));
3992*404b540aSrobert 
3993*404b540aSrobert 	case 8:
3994*404b540aSrobert 	  if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
3995*404b540aSrobert 	    return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
3996*404b540aSrobert 			      AS1 (clr,%B0));
3997*404b540aSrobert 	  else
3998*404b540aSrobert 	    return *len = 1, AS1 (clr,%B0);
3999*404b540aSrobert 
4000*404b540aSrobert 	case 9:
4001*404b540aSrobert 	  *len = 3;
4002*404b540aSrobert 	  return (AS2 (mov,%A0,%B0) CR_TAB
4003*404b540aSrobert 		  AS1 (clr,%B0)     CR_TAB
4004*404b540aSrobert 		  AS1 (lsr,%A0));
4005*404b540aSrobert 
4006*404b540aSrobert 	case 10:
4007*404b540aSrobert 	  *len = 4;
4008*404b540aSrobert 	  return (AS2 (mov,%A0,%B0) CR_TAB
4009*404b540aSrobert 		  AS1 (clr,%B0)     CR_TAB
4010*404b540aSrobert 		  AS1 (lsr,%A0)     CR_TAB
4011*404b540aSrobert 		  AS1 (lsr,%A0));
4012*404b540aSrobert 
4013*404b540aSrobert 	case 11:
4014*404b540aSrobert 	  *len = 5;
4015*404b540aSrobert 	  return (AS2 (mov,%A0,%B0) CR_TAB
4016*404b540aSrobert 		  AS1 (clr,%B0)     CR_TAB
4017*404b540aSrobert 		  AS1 (lsr,%A0)     CR_TAB
4018*404b540aSrobert 		  AS1 (lsr,%A0)     CR_TAB
4019*404b540aSrobert 		  AS1 (lsr,%A0));
4020*404b540aSrobert 
4021*404b540aSrobert 	case 12:
4022*404b540aSrobert 	  if (ldi_ok)
4023*404b540aSrobert 	    {
4024*404b540aSrobert 	      *len = 4;
4025*404b540aSrobert 	      return (AS2 (mov,%A0,%B0) CR_TAB
4026*404b540aSrobert 		      AS1 (clr,%B0)     CR_TAB
4027*404b540aSrobert 		      AS1 (swap,%A0)    CR_TAB
4028*404b540aSrobert 		      AS2 (andi,%A0,0x0f));
4029*404b540aSrobert 	    }
4030*404b540aSrobert 	  if (scratch)
4031*404b540aSrobert 	    {
4032*404b540aSrobert 	      *len = 5;
4033*404b540aSrobert 	      return (AS2 (mov,%A0,%B0) CR_TAB
4034*404b540aSrobert 		      AS1 (clr,%B0)     CR_TAB
4035*404b540aSrobert 		      AS1 (swap,%A0)    CR_TAB
4036*404b540aSrobert 		      AS2 (ldi,%3,0x0f) CR_TAB
4037*404b540aSrobert 		      AS2 (and,%A0,%3));
4038*404b540aSrobert 	    }
4039*404b540aSrobert 	  *len = 6;
4040*404b540aSrobert 	  return (AS2 (mov,%A0,%B0) CR_TAB
4041*404b540aSrobert 		  AS1 (clr,%B0)     CR_TAB
4042*404b540aSrobert 		  AS1 (lsr,%A0)     CR_TAB
4043*404b540aSrobert 		  AS1 (lsr,%A0)     CR_TAB
4044*404b540aSrobert 		  AS1 (lsr,%A0)     CR_TAB
4045*404b540aSrobert 		  AS1 (lsr,%A0));
4046*404b540aSrobert 
4047*404b540aSrobert 	case 13:
4048*404b540aSrobert 	  if (ldi_ok)
4049*404b540aSrobert 	    {
4050*404b540aSrobert 	      *len = 5;
4051*404b540aSrobert 	      return (AS2 (mov,%A0,%B0) CR_TAB
4052*404b540aSrobert 		      AS1 (clr,%B0)     CR_TAB
4053*404b540aSrobert 		      AS1 (swap,%A0)    CR_TAB
4054*404b540aSrobert 		      AS1 (lsr,%A0)     CR_TAB
4055*404b540aSrobert 		      AS2 (andi,%A0,0x07));
4056*404b540aSrobert 	    }
4057*404b540aSrobert 	  if (AVR_ENHANCED && scratch)
4058*404b540aSrobert 	    {
4059*404b540aSrobert 	      *len = 5;
4060*404b540aSrobert 	      return (AS2 (ldi,%3,0x08) CR_TAB
4061*404b540aSrobert 		      AS2 (mul,%B0,%3)  CR_TAB
4062*404b540aSrobert 		      AS2 (mov,%A0,r1)  CR_TAB
4063*404b540aSrobert 		      AS1 (clr,%B0)     CR_TAB
4064*404b540aSrobert 		      AS1 (clr,__zero_reg__));
4065*404b540aSrobert 	    }
4066*404b540aSrobert 	  if (optimize_size && scratch)
4067*404b540aSrobert 	    break;  /* 5 */
4068*404b540aSrobert 	  if (scratch)
4069*404b540aSrobert 	    {
4070*404b540aSrobert 	      *len = 6;
4071*404b540aSrobert 	      return (AS2 (mov,%A0,%B0) CR_TAB
4072*404b540aSrobert 		      AS1 (clr,%B0)     CR_TAB
4073*404b540aSrobert 		      AS1 (swap,%A0)    CR_TAB
4074*404b540aSrobert 		      AS1 (lsr,%A0)     CR_TAB
4075*404b540aSrobert 		      AS2 (ldi,%3,0x07) CR_TAB
4076*404b540aSrobert 		      AS2 (and,%A0,%3));
4077*404b540aSrobert 	    }
4078*404b540aSrobert 	  if (AVR_ENHANCED)
4079*404b540aSrobert 	    {
4080*404b540aSrobert 	      *len = 6;
4081*404b540aSrobert 	      return ("set"            CR_TAB
4082*404b540aSrobert 		      AS2 (bld,r1,3)   CR_TAB
4083*404b540aSrobert 		      AS2 (mul,%B0,r1) CR_TAB
4084*404b540aSrobert 		      AS2 (mov,%A0,r1) CR_TAB
4085*404b540aSrobert 		      AS1 (clr,%B0)    CR_TAB
4086*404b540aSrobert 		      AS1 (clr,__zero_reg__));
4087*404b540aSrobert 	    }
4088*404b540aSrobert 	  *len = 7;
4089*404b540aSrobert 	  return (AS2 (mov,%A0,%B0) CR_TAB
4090*404b540aSrobert 		  AS1 (clr,%B0)     CR_TAB
4091*404b540aSrobert 		  AS1 (lsr,%A0)     CR_TAB
4092*404b540aSrobert 		  AS1 (lsr,%A0)     CR_TAB
4093*404b540aSrobert 		  AS1 (lsr,%A0)     CR_TAB
4094*404b540aSrobert 		  AS1 (lsr,%A0)     CR_TAB
4095*404b540aSrobert 		  AS1 (lsr,%A0));
4096*404b540aSrobert 
4097*404b540aSrobert 	case 14:
4098*404b540aSrobert 	  if (AVR_ENHANCED && ldi_ok)
4099*404b540aSrobert 	    {
4100*404b540aSrobert 	      *len = 5;
4101*404b540aSrobert 	      return (AS2 (ldi,%A0,0x04) CR_TAB
4102*404b540aSrobert 		      AS2 (mul,%B0,%A0)  CR_TAB
4103*404b540aSrobert 		      AS2 (mov,%A0,r1)   CR_TAB
4104*404b540aSrobert 		      AS1 (clr,%B0)      CR_TAB
4105*404b540aSrobert 		      AS1 (clr,__zero_reg__));
4106*404b540aSrobert 	    }
4107*404b540aSrobert 	  if (AVR_ENHANCED && scratch)
4108*404b540aSrobert 	    {
4109*404b540aSrobert 	      *len = 5;
4110*404b540aSrobert 	      return (AS2 (ldi,%3,0x04) CR_TAB
4111*404b540aSrobert 		      AS2 (mul,%B0,%3)  CR_TAB
4112*404b540aSrobert 		      AS2 (mov,%A0,r1)  CR_TAB
4113*404b540aSrobert 		      AS1 (clr,%B0)     CR_TAB
4114*404b540aSrobert 		      AS1 (clr,__zero_reg__));
4115*404b540aSrobert 	    }
4116*404b540aSrobert 	  if (optimize_size && ldi_ok)
4117*404b540aSrobert 	    {
4118*404b540aSrobert 	      *len = 5;
4119*404b540aSrobert 	      return (AS2 (mov,%A0,%B0) CR_TAB
4120*404b540aSrobert 		      AS2 (ldi,%B0,6) "\n1:\t"
4121*404b540aSrobert 		      AS1 (lsr,%A0)     CR_TAB
4122*404b540aSrobert 		      AS1 (dec,%B0)     CR_TAB
4123*404b540aSrobert 		      AS1 (brne,1b));
4124*404b540aSrobert 	    }
4125*404b540aSrobert 	  if (optimize_size && scratch)
4126*404b540aSrobert 	    break;  /* 5 */
4127*404b540aSrobert 	  *len = 6;
4128*404b540aSrobert 	  return (AS1 (clr,%A0) CR_TAB
4129*404b540aSrobert 		  AS1 (lsl,%B0) CR_TAB
4130*404b540aSrobert 		  AS1 (rol,%A0) CR_TAB
4131*404b540aSrobert 		  AS1 (lsl,%B0) CR_TAB
4132*404b540aSrobert 		  AS1 (rol,%A0) CR_TAB
4133*404b540aSrobert 		  AS1 (clr,%B0));
4134*404b540aSrobert 
4135*404b540aSrobert 	case 15:
4136*404b540aSrobert 	  *len = 4;
4137*404b540aSrobert 	  return (AS1 (clr,%A0) CR_TAB
4138*404b540aSrobert 		  AS1 (lsl,%B0) CR_TAB
4139*404b540aSrobert 		  AS1 (rol,%A0) CR_TAB
4140*404b540aSrobert 		  AS1 (clr,%B0));
4141*404b540aSrobert 	}
4142*404b540aSrobert       len = t;
4143*404b540aSrobert     }
4144*404b540aSrobert   out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4145*404b540aSrobert 		       AS1 (ror,%A0)),
4146*404b540aSrobert 		       insn, operands, len, 2);
4147*404b540aSrobert   return "";
4148*404b540aSrobert }
4149*404b540aSrobert 
4150*404b540aSrobert /* 32bit logic shift right ((unsigned int)x >> i) */
4151*404b540aSrobert 
4152*404b540aSrobert const char *
lshrsi3_out(rtx insn,rtx operands[],int * len)4153*404b540aSrobert lshrsi3_out (rtx insn, rtx operands[], int *len)
4154*404b540aSrobert {
4155*404b540aSrobert   if (GET_CODE (operands[2]) == CONST_INT)
4156*404b540aSrobert     {
4157*404b540aSrobert       int k;
4158*404b540aSrobert       int *t = len;
4159*404b540aSrobert 
4160*404b540aSrobert       if (!len)
4161*404b540aSrobert 	len = &k;
4162*404b540aSrobert 
4163*404b540aSrobert       switch (INTVAL (operands[2]))
4164*404b540aSrobert 	{
4165*404b540aSrobert 	default:
4166*404b540aSrobert 	  if (INTVAL (operands[2]) < 32)
4167*404b540aSrobert 	    break;
4168*404b540aSrobert 
4169*404b540aSrobert 	  if (AVR_HAVE_MOVW)
4170*404b540aSrobert 	    return *len = 3, (AS1 (clr,%D0) CR_TAB
4171*404b540aSrobert 			      AS1 (clr,%C0) CR_TAB
4172*404b540aSrobert 			      AS2 (movw,%A0,%C0));
4173*404b540aSrobert 	  *len = 4;
4174*404b540aSrobert 	  return (AS1 (clr,%D0) CR_TAB
4175*404b540aSrobert 		  AS1 (clr,%C0) CR_TAB
4176*404b540aSrobert 		  AS1 (clr,%B0) CR_TAB
4177*404b540aSrobert 		  AS1 (clr,%A0));
4178*404b540aSrobert 
4179*404b540aSrobert 	case 8:
4180*404b540aSrobert 	  {
4181*404b540aSrobert 	    int reg0 = true_regnum (operands[0]);
4182*404b540aSrobert 	    int reg1 = true_regnum (operands[1]);
4183*404b540aSrobert 	    *len = 4;
4184*404b540aSrobert 	    if (reg0 <= reg1)
4185*404b540aSrobert 	      return (AS2 (mov,%A0,%B1) CR_TAB
4186*404b540aSrobert 		      AS2 (mov,%B0,%C1) CR_TAB
4187*404b540aSrobert 		      AS2 (mov,%C0,%D1) CR_TAB
4188*404b540aSrobert 		      AS1 (clr,%D0));
4189*404b540aSrobert 	    else if (reg0 == reg1 + 1)
4190*404b540aSrobert 	      return *len = 1, AS1 (clr,%D0);
4191*404b540aSrobert 	    else
4192*404b540aSrobert 	      return (AS1 (clr,%D0)     CR_TAB
4193*404b540aSrobert 		      AS2 (mov,%C0,%D1) CR_TAB
4194*404b540aSrobert 		      AS2 (mov,%B0,%C1) CR_TAB
4195*404b540aSrobert 		      AS2 (mov,%A0,%B1));
4196*404b540aSrobert 	  }
4197*404b540aSrobert 
4198*404b540aSrobert 	case 16:
4199*404b540aSrobert 	  {
4200*404b540aSrobert 	    int reg0 = true_regnum (operands[0]);
4201*404b540aSrobert 	    int reg1 = true_regnum (operands[1]);
4202*404b540aSrobert 	    *len = 4;
4203*404b540aSrobert 	    if (AVR_HAVE_MOVW && (reg0 != reg1 + 2))
4204*404b540aSrobert 	      {
4205*404b540aSrobert 		*len = 3;
4206*404b540aSrobert 		return (AS2 (movw,%A0,%C1) CR_TAB
4207*404b540aSrobert 			AS1 (clr,%C0)      CR_TAB
4208*404b540aSrobert 			AS1 (clr,%D0));
4209*404b540aSrobert 	      }
4210*404b540aSrobert 	    if (reg0 <= reg1 + 1)
4211*404b540aSrobert 	      return (AS2 (mov,%A0,%C1) CR_TAB
4212*404b540aSrobert 		      AS2 (mov,%B0,%D1) CR_TAB
4213*404b540aSrobert 		      AS1 (clr,%C0)     CR_TAB
4214*404b540aSrobert 		      AS1 (clr,%D0));
4215*404b540aSrobert 	    else if (reg0 == reg1 + 2)
4216*404b540aSrobert 	      return *len = 2, (AS1 (clr,%C0)     CR_TAB
4217*404b540aSrobert 				AS1 (clr,%D0));
4218*404b540aSrobert 	    else
4219*404b540aSrobert 	      return (AS2 (mov,%B0,%D1) CR_TAB
4220*404b540aSrobert 		      AS2 (mov,%A0,%C1) CR_TAB
4221*404b540aSrobert 		      AS1 (clr,%C0)     CR_TAB
4222*404b540aSrobert 		      AS1 (clr,%D0));
4223*404b540aSrobert 	  }
4224*404b540aSrobert 
4225*404b540aSrobert 	case 24:
4226*404b540aSrobert 	  if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
4227*404b540aSrobert 	    return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4228*404b540aSrobert 			      AS1 (clr,%B0)     CR_TAB
4229*404b540aSrobert 			      AS1 (clr,%C0)     CR_TAB
4230*404b540aSrobert 			      AS1 (clr,%D0));
4231*404b540aSrobert 	  else
4232*404b540aSrobert 	    return *len = 3, (AS1 (clr,%B0)     CR_TAB
4233*404b540aSrobert 			      AS1 (clr,%C0)     CR_TAB
4234*404b540aSrobert 			      AS1 (clr,%D0));
4235*404b540aSrobert 
4236*404b540aSrobert 	case 31:
4237*404b540aSrobert 	  *len = 6;
4238*404b540aSrobert 	  return (AS1 (clr,%A0)    CR_TAB
4239*404b540aSrobert 		  AS2 (sbrc,%D0,7) CR_TAB
4240*404b540aSrobert 		  AS1 (inc,%A0)    CR_TAB
4241*404b540aSrobert 		  AS1 (clr,%B0)    CR_TAB
4242*404b540aSrobert 		  AS1 (clr,%C0)    CR_TAB
4243*404b540aSrobert 		  AS1 (clr,%D0));
4244*404b540aSrobert 	}
4245*404b540aSrobert       len = t;
4246*404b540aSrobert     }
4247*404b540aSrobert   out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4248*404b540aSrobert 		       AS1 (ror,%C0) CR_TAB
4249*404b540aSrobert 		       AS1 (ror,%B0) CR_TAB
4250*404b540aSrobert 		       AS1 (ror,%A0)),
4251*404b540aSrobert 		      insn, operands, len, 4);
4252*404b540aSrobert   return "";
4253*404b540aSrobert }
4254*404b540aSrobert 
4255*404b540aSrobert /* Modifies the length assigned to instruction INSN
4256*404b540aSrobert  LEN is the initially computed length of the insn.  */
4257*404b540aSrobert 
4258*404b540aSrobert int
adjust_insn_length(rtx insn,int len)4259*404b540aSrobert adjust_insn_length (rtx insn, int len)
4260*404b540aSrobert {
4261*404b540aSrobert   rtx patt = PATTERN (insn);
4262*404b540aSrobert   rtx set;
4263*404b540aSrobert 
4264*404b540aSrobert   if (GET_CODE (patt) == SET)
4265*404b540aSrobert     {
4266*404b540aSrobert       rtx op[10];
4267*404b540aSrobert       op[1] = SET_SRC (patt);
4268*404b540aSrobert       op[0] = SET_DEST (patt);
4269*404b540aSrobert       if (general_operand (op[1], VOIDmode)
4270*404b540aSrobert 	  && general_operand (op[0], VOIDmode))
4271*404b540aSrobert 	{
4272*404b540aSrobert 	  switch (GET_MODE (op[0]))
4273*404b540aSrobert 	    {
4274*404b540aSrobert 	    case QImode:
4275*404b540aSrobert 	      output_movqi (insn, op, &len);
4276*404b540aSrobert 	      break;
4277*404b540aSrobert 	    case HImode:
4278*404b540aSrobert 	      output_movhi (insn, op, &len);
4279*404b540aSrobert 	      break;
4280*404b540aSrobert 	    case SImode:
4281*404b540aSrobert 	    case SFmode:
4282*404b540aSrobert 	      output_movsisf (insn, op, &len);
4283*404b540aSrobert 	      break;
4284*404b540aSrobert 	    default:
4285*404b540aSrobert 	      break;
4286*404b540aSrobert 	    }
4287*404b540aSrobert 	}
4288*404b540aSrobert       else if (op[0] == cc0_rtx && REG_P (op[1]))
4289*404b540aSrobert 	{
4290*404b540aSrobert 	  switch (GET_MODE (op[1]))
4291*404b540aSrobert 	    {
4292*404b540aSrobert 	    case HImode: out_tsthi (insn,&len); break;
4293*404b540aSrobert 	    case SImode: out_tstsi (insn,&len); break;
4294*404b540aSrobert 	    default: break;
4295*404b540aSrobert 	    }
4296*404b540aSrobert 	}
4297*404b540aSrobert       else if (GET_CODE (op[1]) == AND)
4298*404b540aSrobert 	{
4299*404b540aSrobert 	  if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4300*404b540aSrobert 	    {
4301*404b540aSrobert 	      HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4302*404b540aSrobert 	      if (GET_MODE (op[1]) == SImode)
4303*404b540aSrobert 		len = (((mask & 0xff) != 0xff)
4304*404b540aSrobert 		       + ((mask & 0xff00) != 0xff00)
4305*404b540aSrobert 		       + ((mask & 0xff0000L) != 0xff0000L)
4306*404b540aSrobert 		       + ((mask & 0xff000000L) != 0xff000000L));
4307*404b540aSrobert 	      else if (GET_MODE (op[1]) == HImode)
4308*404b540aSrobert 		len = (((mask & 0xff) != 0xff)
4309*404b540aSrobert 		       + ((mask & 0xff00) != 0xff00));
4310*404b540aSrobert 	    }
4311*404b540aSrobert 	}
4312*404b540aSrobert       else if (GET_CODE (op[1]) == IOR)
4313*404b540aSrobert 	{
4314*404b540aSrobert 	  if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4315*404b540aSrobert 	    {
4316*404b540aSrobert 	      HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4317*404b540aSrobert 	      if (GET_MODE (op[1]) == SImode)
4318*404b540aSrobert 		len = (((mask & 0xff) != 0)
4319*404b540aSrobert 		       + ((mask & 0xff00) != 0)
4320*404b540aSrobert 		       + ((mask & 0xff0000L) != 0)
4321*404b540aSrobert 		       + ((mask & 0xff000000L) != 0));
4322*404b540aSrobert 	      else if (GET_MODE (op[1]) == HImode)
4323*404b540aSrobert 		len = (((mask & 0xff) != 0)
4324*404b540aSrobert 		       + ((mask & 0xff00) != 0));
4325*404b540aSrobert 	    }
4326*404b540aSrobert 	}
4327*404b540aSrobert     }
4328*404b540aSrobert   set = single_set (insn);
4329*404b540aSrobert   if (set)
4330*404b540aSrobert     {
4331*404b540aSrobert       rtx op[10];
4332*404b540aSrobert 
4333*404b540aSrobert       op[1] = SET_SRC (set);
4334*404b540aSrobert       op[0] = SET_DEST (set);
4335*404b540aSrobert 
4336*404b540aSrobert       if (GET_CODE (patt) == PARALLEL
4337*404b540aSrobert 	  && general_operand (op[1], VOIDmode)
4338*404b540aSrobert 	  && general_operand (op[0], VOIDmode))
4339*404b540aSrobert 	{
4340*404b540aSrobert 	  if (XVECLEN (patt, 0) == 2)
4341*404b540aSrobert 	    op[2] = XVECEXP (patt, 0, 1);
4342*404b540aSrobert 
4343*404b540aSrobert 	  switch (GET_MODE (op[0]))
4344*404b540aSrobert 	    {
4345*404b540aSrobert 	    case QImode:
4346*404b540aSrobert 	      len = 2;
4347*404b540aSrobert 	      break;
4348*404b540aSrobert 	    case HImode:
4349*404b540aSrobert 	      output_reload_inhi (insn, op, &len);
4350*404b540aSrobert 	      break;
4351*404b540aSrobert 	    case SImode:
4352*404b540aSrobert 	    case SFmode:
4353*404b540aSrobert 	      output_reload_insisf (insn, op, &len);
4354*404b540aSrobert 	      break;
4355*404b540aSrobert 	    default:
4356*404b540aSrobert 	      break;
4357*404b540aSrobert 	    }
4358*404b540aSrobert 	}
4359*404b540aSrobert       else if (GET_CODE (op[1]) == ASHIFT
4360*404b540aSrobert 	  || GET_CODE (op[1]) == ASHIFTRT
4361*404b540aSrobert 	  || GET_CODE (op[1]) == LSHIFTRT)
4362*404b540aSrobert 	{
4363*404b540aSrobert 	  rtx ops[10];
4364*404b540aSrobert 	  ops[0] = op[0];
4365*404b540aSrobert 	  ops[1] = XEXP (op[1],0);
4366*404b540aSrobert 	  ops[2] = XEXP (op[1],1);
4367*404b540aSrobert 	  switch (GET_CODE (op[1]))
4368*404b540aSrobert 	    {
4369*404b540aSrobert 	    case ASHIFT:
4370*404b540aSrobert 	      switch (GET_MODE (op[0]))
4371*404b540aSrobert 		{
4372*404b540aSrobert 		case QImode: ashlqi3_out (insn,ops,&len); break;
4373*404b540aSrobert 		case HImode: ashlhi3_out (insn,ops,&len); break;
4374*404b540aSrobert 		case SImode: ashlsi3_out (insn,ops,&len); break;
4375*404b540aSrobert 		default: break;
4376*404b540aSrobert 		}
4377*404b540aSrobert 	      break;
4378*404b540aSrobert 	    case ASHIFTRT:
4379*404b540aSrobert 	      switch (GET_MODE (op[0]))
4380*404b540aSrobert 		{
4381*404b540aSrobert 		case QImode: ashrqi3_out (insn,ops,&len); break;
4382*404b540aSrobert 		case HImode: ashrhi3_out (insn,ops,&len); break;
4383*404b540aSrobert 		case SImode: ashrsi3_out (insn,ops,&len); break;
4384*404b540aSrobert 		default: break;
4385*404b540aSrobert 		}
4386*404b540aSrobert 	      break;
4387*404b540aSrobert 	    case LSHIFTRT:
4388*404b540aSrobert 	      switch (GET_MODE (op[0]))
4389*404b540aSrobert 		{
4390*404b540aSrobert 		case QImode: lshrqi3_out (insn,ops,&len); break;
4391*404b540aSrobert 		case HImode: lshrhi3_out (insn,ops,&len); break;
4392*404b540aSrobert 		case SImode: lshrsi3_out (insn,ops,&len); break;
4393*404b540aSrobert 		default: break;
4394*404b540aSrobert 		}
4395*404b540aSrobert 	      break;
4396*404b540aSrobert 	    default:
4397*404b540aSrobert 	      break;
4398*404b540aSrobert 	    }
4399*404b540aSrobert 	}
4400*404b540aSrobert     }
4401*404b540aSrobert   return len;
4402*404b540aSrobert }
4403*404b540aSrobert 
4404*404b540aSrobert /* Return nonzero if register REG dead after INSN.  */
4405*404b540aSrobert 
4406*404b540aSrobert int
reg_unused_after(rtx insn,rtx reg)4407*404b540aSrobert reg_unused_after (rtx insn, rtx reg)
4408*404b540aSrobert {
4409*404b540aSrobert   return (dead_or_set_p (insn, reg)
4410*404b540aSrobert 	  || (REG_P(reg) && _reg_unused_after (insn, reg)));
4411*404b540aSrobert }
4412*404b540aSrobert 
4413*404b540aSrobert /* Return nonzero if REG is not used after INSN.
4414*404b540aSrobert    We assume REG is a reload reg, and therefore does
4415*404b540aSrobert    not live past labels.  It may live past calls or jumps though.  */
4416*404b540aSrobert 
4417*404b540aSrobert int
_reg_unused_after(rtx insn,rtx reg)4418*404b540aSrobert _reg_unused_after (rtx insn, rtx reg)
4419*404b540aSrobert {
4420*404b540aSrobert   enum rtx_code code;
4421*404b540aSrobert   rtx set;
4422*404b540aSrobert 
4423*404b540aSrobert   /* If the reg is set by this instruction, then it is safe for our
4424*404b540aSrobert      case.  Disregard the case where this is a store to memory, since
4425*404b540aSrobert      we are checking a register used in the store address.  */
4426*404b540aSrobert   set = single_set (insn);
4427*404b540aSrobert   if (set && GET_CODE (SET_DEST (set)) != MEM
4428*404b540aSrobert       && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4429*404b540aSrobert     return 1;
4430*404b540aSrobert 
4431*404b540aSrobert   while ((insn = NEXT_INSN (insn)))
4432*404b540aSrobert     {
4433*404b540aSrobert       rtx set;
4434*404b540aSrobert       code = GET_CODE (insn);
4435*404b540aSrobert 
4436*404b540aSrobert #if 0
4437*404b540aSrobert       /* If this is a label that existed before reload, then the register
4438*404b540aSrobert 	 if dead here.  However, if this is a label added by reorg, then
4439*404b540aSrobert 	 the register may still be live here.  We can't tell the difference,
4440*404b540aSrobert 	 so we just ignore labels completely.  */
4441*404b540aSrobert       if (code == CODE_LABEL)
4442*404b540aSrobert 	return 1;
4443*404b540aSrobert       /* else */
4444*404b540aSrobert #endif
4445*404b540aSrobert 
4446*404b540aSrobert       if (!INSN_P (insn))
4447*404b540aSrobert 	continue;
4448*404b540aSrobert 
4449*404b540aSrobert       if (code == JUMP_INSN)
4450*404b540aSrobert 	return 0;
4451*404b540aSrobert 
4452*404b540aSrobert       /* If this is a sequence, we must handle them all at once.
4453*404b540aSrobert 	 We could have for instance a call that sets the target register,
4454*404b540aSrobert 	 and an insn in a delay slot that uses the register.  In this case,
4455*404b540aSrobert 	 we must return 0.  */
4456*404b540aSrobert       else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4457*404b540aSrobert 	{
4458*404b540aSrobert 	  int i;
4459*404b540aSrobert 	  int retval = 0;
4460*404b540aSrobert 
4461*404b540aSrobert 	  for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4462*404b540aSrobert 	    {
4463*404b540aSrobert 	      rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4464*404b540aSrobert 	      rtx set = single_set (this_insn);
4465*404b540aSrobert 
4466*404b540aSrobert 	      if (GET_CODE (this_insn) == CALL_INSN)
4467*404b540aSrobert 		code = CALL_INSN;
4468*404b540aSrobert 	      else if (GET_CODE (this_insn) == JUMP_INSN)
4469*404b540aSrobert 		{
4470*404b540aSrobert 		  if (INSN_ANNULLED_BRANCH_P (this_insn))
4471*404b540aSrobert 		    return 0;
4472*404b540aSrobert 		  code = JUMP_INSN;
4473*404b540aSrobert 		}
4474*404b540aSrobert 
4475*404b540aSrobert 	      if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4476*404b540aSrobert 		return 0;
4477*404b540aSrobert 	      if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4478*404b540aSrobert 		{
4479*404b540aSrobert 		  if (GET_CODE (SET_DEST (set)) != MEM)
4480*404b540aSrobert 		    retval = 1;
4481*404b540aSrobert 		  else
4482*404b540aSrobert 		    return 0;
4483*404b540aSrobert 		}
4484*404b540aSrobert 	      if (set == 0
4485*404b540aSrobert 		  && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4486*404b540aSrobert 		return 0;
4487*404b540aSrobert 	    }
4488*404b540aSrobert 	  if (retval == 1)
4489*404b540aSrobert 	    return 1;
4490*404b540aSrobert 	  else if (code == JUMP_INSN)
4491*404b540aSrobert 	    return 0;
4492*404b540aSrobert 	}
4493*404b540aSrobert 
4494*404b540aSrobert       if (code == CALL_INSN)
4495*404b540aSrobert 	{
4496*404b540aSrobert 	  rtx tem;
4497*404b540aSrobert 	  for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4498*404b540aSrobert 	    if (GET_CODE (XEXP (tem, 0)) == USE
4499*404b540aSrobert 		&& REG_P (XEXP (XEXP (tem, 0), 0))
4500*404b540aSrobert 		&& reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4501*404b540aSrobert 	      return 0;
4502*404b540aSrobert 	  if (call_used_regs[REGNO (reg)])
4503*404b540aSrobert 	    return 1;
4504*404b540aSrobert 	}
4505*404b540aSrobert 
4506*404b540aSrobert       set = single_set (insn);
4507*404b540aSrobert 
4508*404b540aSrobert       if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4509*404b540aSrobert 	return 0;
4510*404b540aSrobert       if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4511*404b540aSrobert 	return GET_CODE (SET_DEST (set)) != MEM;
4512*404b540aSrobert       if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4513*404b540aSrobert 	return 0;
4514*404b540aSrobert     }
4515*404b540aSrobert   return 1;
4516*404b540aSrobert }
4517*404b540aSrobert 
4518*404b540aSrobert /* Target hook for assembling integer objects.  The AVR version needs
4519*404b540aSrobert    special handling for references to certain labels.  */
4520*404b540aSrobert 
4521*404b540aSrobert static bool
avr_assemble_integer(rtx x,unsigned int size,int aligned_p)4522*404b540aSrobert avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
4523*404b540aSrobert {
4524*404b540aSrobert   if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
4525*404b540aSrobert       && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
4526*404b540aSrobert 	  || GET_CODE (x) == LABEL_REF))
4527*404b540aSrobert     {
4528*404b540aSrobert       fputs ("\t.word\tpm(", asm_out_file);
4529*404b540aSrobert       output_addr_const (asm_out_file, x);
4530*404b540aSrobert       fputs (")\n", asm_out_file);
4531*404b540aSrobert       return true;
4532*404b540aSrobert     }
4533*404b540aSrobert   return default_assemble_integer (x, size, aligned_p);
4534*404b540aSrobert }
4535*404b540aSrobert 
4536*404b540aSrobert /* The routine used to output NUL terminated strings.  We use a special
4537*404b540aSrobert    version of this for most svr4 targets because doing so makes the
4538*404b540aSrobert    generated assembly code more compact (and thus faster to assemble)
4539*404b540aSrobert    as well as more readable, especially for targets like the i386
4540*404b540aSrobert    (where the only alternative is to output character sequences as
4541*404b540aSrobert    comma separated lists of numbers).  */
4542*404b540aSrobert 
4543*404b540aSrobert void
gas_output_limited_string(FILE * file,const char * str)4544*404b540aSrobert gas_output_limited_string(FILE *file, const char *str)
4545*404b540aSrobert {
4546*404b540aSrobert   const unsigned char *_limited_str = (unsigned char *) str;
4547*404b540aSrobert   unsigned ch;
4548*404b540aSrobert   fprintf (file, "%s\"", STRING_ASM_OP);
4549*404b540aSrobert   for (; (ch = *_limited_str); _limited_str++)
4550*404b540aSrobert     {
4551*404b540aSrobert       int escape;
4552*404b540aSrobert       switch (escape = ESCAPES[ch])
4553*404b540aSrobert 	{
4554*404b540aSrobert 	case 0:
4555*404b540aSrobert 	  putc (ch, file);
4556*404b540aSrobert 	  break;
4557*404b540aSrobert 	case 1:
4558*404b540aSrobert 	  fprintf (file, "\\%03o", ch);
4559*404b540aSrobert 	  break;
4560*404b540aSrobert 	default:
4561*404b540aSrobert 	  putc ('\\', file);
4562*404b540aSrobert 	  putc (escape, file);
4563*404b540aSrobert 	  break;
4564*404b540aSrobert 	}
4565*404b540aSrobert     }
4566*404b540aSrobert   fprintf (file, "\"\n");
4567*404b540aSrobert }
4568*404b540aSrobert 
4569*404b540aSrobert /* The routine used to output sequences of byte values.  We use a special
4570*404b540aSrobert    version of this for most svr4 targets because doing so makes the
4571*404b540aSrobert    generated assembly code more compact (and thus faster to assemble)
4572*404b540aSrobert    as well as more readable.  Note that if we find subparts of the
4573*404b540aSrobert    character sequence which end with NUL (and which are shorter than
4574*404b540aSrobert    STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING.  */
4575*404b540aSrobert 
4576*404b540aSrobert void
gas_output_ascii(FILE * file,const char * str,size_t length)4577*404b540aSrobert gas_output_ascii(FILE *file, const char *str, size_t length)
4578*404b540aSrobert {
4579*404b540aSrobert   const unsigned char *_ascii_bytes = (const unsigned char *) str;
4580*404b540aSrobert   const unsigned char *limit = _ascii_bytes + length;
4581*404b540aSrobert   unsigned bytes_in_chunk = 0;
4582*404b540aSrobert   for (; _ascii_bytes < limit; _ascii_bytes++)
4583*404b540aSrobert     {
4584*404b540aSrobert       const unsigned char *p;
4585*404b540aSrobert       if (bytes_in_chunk >= 60)
4586*404b540aSrobert 	{
4587*404b540aSrobert 	  fprintf (file, "\"\n");
4588*404b540aSrobert 	  bytes_in_chunk = 0;
4589*404b540aSrobert 	}
4590*404b540aSrobert       for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4591*404b540aSrobert 	continue;
4592*404b540aSrobert       if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4593*404b540aSrobert 	{
4594*404b540aSrobert 	  if (bytes_in_chunk > 0)
4595*404b540aSrobert 	    {
4596*404b540aSrobert 	      fprintf (file, "\"\n");
4597*404b540aSrobert 	      bytes_in_chunk = 0;
4598*404b540aSrobert 	    }
4599*404b540aSrobert 	  gas_output_limited_string (file, (char*)_ascii_bytes);
4600*404b540aSrobert 	  _ascii_bytes = p;
4601*404b540aSrobert 	}
4602*404b540aSrobert       else
4603*404b540aSrobert 	{
4604*404b540aSrobert 	  int escape;
4605*404b540aSrobert 	  unsigned ch;
4606*404b540aSrobert 	  if (bytes_in_chunk == 0)
4607*404b540aSrobert 	    fprintf (file, "\t.ascii\t\"");
4608*404b540aSrobert 	  switch (escape = ESCAPES[ch = *_ascii_bytes])
4609*404b540aSrobert 	    {
4610*404b540aSrobert 	    case 0:
4611*404b540aSrobert 	      putc (ch, file);
4612*404b540aSrobert 	      bytes_in_chunk++;
4613*404b540aSrobert 	      break;
4614*404b540aSrobert 	    case 1:
4615*404b540aSrobert 	      fprintf (file, "\\%03o", ch);
4616*404b540aSrobert 	      bytes_in_chunk += 4;
4617*404b540aSrobert 	      break;
4618*404b540aSrobert 	    default:
4619*404b540aSrobert 	      putc ('\\', file);
4620*404b540aSrobert 	      putc (escape, file);
4621*404b540aSrobert 	      bytes_in_chunk += 2;
4622*404b540aSrobert 	      break;
4623*404b540aSrobert 	    }
4624*404b540aSrobert 	}
4625*404b540aSrobert     }
4626*404b540aSrobert   if (bytes_in_chunk > 0)
4627*404b540aSrobert     fprintf (file, "\"\n");
4628*404b540aSrobert }
4629*404b540aSrobert 
4630*404b540aSrobert /* Return value is nonzero if pseudos that have been
4631*404b540aSrobert    assigned to registers of class CLASS would likely be spilled
4632*404b540aSrobert    because registers of CLASS are needed for spill registers.  */
4633*404b540aSrobert 
4634*404b540aSrobert enum reg_class
class_likely_spilled_p(int c)4635*404b540aSrobert class_likely_spilled_p (int c)
4636*404b540aSrobert {
4637*404b540aSrobert   return (c != ALL_REGS && c != ADDW_REGS);
4638*404b540aSrobert }
4639*404b540aSrobert 
4640*404b540aSrobert /* Valid attributes:
4641*404b540aSrobert    progmem - put data to program memory;
4642*404b540aSrobert    signal - make a function to be hardware interrupt. After function
4643*404b540aSrobert    prologue interrupts are disabled;
4644*404b540aSrobert    interrupt - make a function to be hardware interrupt. After function
4645*404b540aSrobert    prologue interrupts are enabled;
4646*404b540aSrobert    naked     - don't generate function prologue/epilogue and `ret' command.
4647*404b540aSrobert 
4648*404b540aSrobert    Only `progmem' attribute valid for type.  */
4649*404b540aSrobert 
4650*404b540aSrobert const struct attribute_spec avr_attribute_table[] =
4651*404b540aSrobert {
4652*404b540aSrobert   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4653*404b540aSrobert   { "progmem",   0, 0, false, false, false,  avr_handle_progmem_attribute },
4654*404b540aSrobert   { "signal",    0, 0, true,  false, false,  avr_handle_fndecl_attribute },
4655*404b540aSrobert   { "interrupt", 0, 0, true,  false, false,  avr_handle_fndecl_attribute },
4656*404b540aSrobert   { "naked",     0, 0, false, true,  true,   avr_handle_fntype_attribute },
4657*404b540aSrobert   { NULL,        0, 0, false, false, false, NULL }
4658*404b540aSrobert };
4659*404b540aSrobert 
4660*404b540aSrobert /* Handle a "progmem" attribute; arguments as in
4661*404b540aSrobert    struct attribute_spec.handler.  */
4662*404b540aSrobert static tree
avr_handle_progmem_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)4663*404b540aSrobert avr_handle_progmem_attribute (tree *node, tree name,
4664*404b540aSrobert 			      tree args ATTRIBUTE_UNUSED,
4665*404b540aSrobert 			      int flags ATTRIBUTE_UNUSED,
4666*404b540aSrobert 			      bool *no_add_attrs)
4667*404b540aSrobert {
4668*404b540aSrobert   if (DECL_P (*node))
4669*404b540aSrobert     {
4670*404b540aSrobert       if (TREE_CODE (*node) == TYPE_DECL)
4671*404b540aSrobert 	{
4672*404b540aSrobert 	  /* This is really a decl attribute, not a type attribute,
4673*404b540aSrobert 	     but try to handle it for GCC 3.0 backwards compatibility.  */
4674*404b540aSrobert 
4675*404b540aSrobert 	  tree type = TREE_TYPE (*node);
4676*404b540aSrobert 	  tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
4677*404b540aSrobert 	  tree newtype = build_type_attribute_variant (type, attr);
4678*404b540aSrobert 
4679*404b540aSrobert 	  TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
4680*404b540aSrobert 	  TREE_TYPE (*node) = newtype;
4681*404b540aSrobert 	  *no_add_attrs = true;
4682*404b540aSrobert 	}
4683*404b540aSrobert       else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
4684*404b540aSrobert 	{
4685*404b540aSrobert 	  if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
4686*404b540aSrobert 	    {
4687*404b540aSrobert 	      warning (0, "only initialized variables can be placed into "
4688*404b540aSrobert 		       "program memory area");
4689*404b540aSrobert 	      *no_add_attrs = true;
4690*404b540aSrobert 	    }
4691*404b540aSrobert 	}
4692*404b540aSrobert       else
4693*404b540aSrobert 	{
4694*404b540aSrobert 	  warning (OPT_Wattributes, "%qs attribute ignored",
4695*404b540aSrobert 		   IDENTIFIER_POINTER (name));
4696*404b540aSrobert 	  *no_add_attrs = true;
4697*404b540aSrobert 	}
4698*404b540aSrobert     }
4699*404b540aSrobert 
4700*404b540aSrobert   return NULL_TREE;
4701*404b540aSrobert }
4702*404b540aSrobert 
4703*404b540aSrobert /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4704*404b540aSrobert    struct attribute_spec.handler.  */
4705*404b540aSrobert 
4706*404b540aSrobert static tree
avr_handle_fndecl_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)4707*404b540aSrobert avr_handle_fndecl_attribute (tree *node, tree name,
4708*404b540aSrobert 			     tree args ATTRIBUTE_UNUSED,
4709*404b540aSrobert 			     int flags ATTRIBUTE_UNUSED,
4710*404b540aSrobert 			     bool *no_add_attrs)
4711*404b540aSrobert {
4712*404b540aSrobert   if (TREE_CODE (*node) != FUNCTION_DECL)
4713*404b540aSrobert     {
4714*404b540aSrobert       warning (OPT_Wattributes, "%qs attribute only applies to functions",
4715*404b540aSrobert 	       IDENTIFIER_POINTER (name));
4716*404b540aSrobert       *no_add_attrs = true;
4717*404b540aSrobert     }
4718*404b540aSrobert   else
4719*404b540aSrobert     {
4720*404b540aSrobert       const char *func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (*node));
4721*404b540aSrobert       const char *attr = IDENTIFIER_POINTER (name);
4722*404b540aSrobert 
4723*404b540aSrobert       /* If the function has the 'signal' or 'interrupt' attribute, test to
4724*404b540aSrobert          make sure that the name of the function is "__vector_NN" so as to
4725*404b540aSrobert          catch when the user misspells the interrupt vector name.  */
4726*404b540aSrobert 
4727*404b540aSrobert       if (strncmp (attr, "interrupt", strlen ("interrupt")) == 0)
4728*404b540aSrobert         {
4729*404b540aSrobert           if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
4730*404b540aSrobert             {
4731*404b540aSrobert               warning (0, "%qs appears to be a misspelled interrupt handler",
4732*404b540aSrobert                        func_name);
4733*404b540aSrobert             }
4734*404b540aSrobert         }
4735*404b540aSrobert       else if (strncmp (attr, "signal", strlen ("signal")) == 0)
4736*404b540aSrobert         {
4737*404b540aSrobert           if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
4738*404b540aSrobert             {
4739*404b540aSrobert               warning (0, "%qs appears to be a misspelled signal handler",
4740*404b540aSrobert                        func_name);
4741*404b540aSrobert             }
4742*404b540aSrobert         }
4743*404b540aSrobert     }
4744*404b540aSrobert 
4745*404b540aSrobert   return NULL_TREE;
4746*404b540aSrobert }
4747*404b540aSrobert 
4748*404b540aSrobert static tree
avr_handle_fntype_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)4749*404b540aSrobert avr_handle_fntype_attribute (tree *node, tree name,
4750*404b540aSrobert                              tree args ATTRIBUTE_UNUSED,
4751*404b540aSrobert                              int flags ATTRIBUTE_UNUSED,
4752*404b540aSrobert                              bool *no_add_attrs)
4753*404b540aSrobert {
4754*404b540aSrobert   if (TREE_CODE (*node) != FUNCTION_TYPE)
4755*404b540aSrobert     {
4756*404b540aSrobert       warning (OPT_Wattributes, "%qs attribute only applies to functions",
4757*404b540aSrobert 	       IDENTIFIER_POINTER (name));
4758*404b540aSrobert       *no_add_attrs = true;
4759*404b540aSrobert     }
4760*404b540aSrobert 
4761*404b540aSrobert   return NULL_TREE;
4762*404b540aSrobert }
4763*404b540aSrobert 
4764*404b540aSrobert /* Look for attribute `progmem' in DECL
4765*404b540aSrobert    if found return 1, otherwise 0.  */
4766*404b540aSrobert 
4767*404b540aSrobert int
avr_progmem_p(tree decl,tree attributes)4768*404b540aSrobert avr_progmem_p (tree decl, tree attributes)
4769*404b540aSrobert {
4770*404b540aSrobert   tree a;
4771*404b540aSrobert 
4772*404b540aSrobert   if (TREE_CODE (decl) != VAR_DECL)
4773*404b540aSrobert     return 0;
4774*404b540aSrobert 
4775*404b540aSrobert   if (NULL_TREE
4776*404b540aSrobert       != lookup_attribute ("progmem", attributes))
4777*404b540aSrobert     return 1;
4778*404b540aSrobert 
4779*404b540aSrobert   a=decl;
4780*404b540aSrobert   do
4781*404b540aSrobert     a = TREE_TYPE(a);
4782*404b540aSrobert   while (TREE_CODE (a) == ARRAY_TYPE);
4783*404b540aSrobert 
4784*404b540aSrobert   if (a == error_mark_node)
4785*404b540aSrobert     return 0;
4786*404b540aSrobert 
4787*404b540aSrobert   if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4788*404b540aSrobert     return 1;
4789*404b540aSrobert 
4790*404b540aSrobert   return 0;
4791*404b540aSrobert }
4792*404b540aSrobert 
4793*404b540aSrobert /* Add the section attribute if the variable is in progmem.  */
4794*404b540aSrobert 
4795*404b540aSrobert static void
avr_insert_attributes(tree node,tree * attributes)4796*404b540aSrobert avr_insert_attributes (tree node, tree *attributes)
4797*404b540aSrobert {
4798*404b540aSrobert   if (TREE_CODE (node) == VAR_DECL
4799*404b540aSrobert       && (TREE_STATIC (node) || DECL_EXTERNAL (node))
4800*404b540aSrobert       && avr_progmem_p (node, *attributes))
4801*404b540aSrobert     {
4802*404b540aSrobert       static const char dsec[] = ".progmem.data";
4803*404b540aSrobert       *attributes = tree_cons (get_identifier ("section"),
4804*404b540aSrobert 		build_tree_list (NULL, build_string (strlen (dsec), dsec)),
4805*404b540aSrobert 		*attributes);
4806*404b540aSrobert 
4807*404b540aSrobert       /* ??? This seems sketchy.  Why can't the user declare the
4808*404b540aSrobert 	 thing const in the first place?  */
4809*404b540aSrobert       TREE_READONLY (node) = 1;
4810*404b540aSrobert     }
4811*404b540aSrobert }
4812*404b540aSrobert 
4813*404b540aSrobert /* A get_unnamed_section callback for switching to progmem_section.  */
4814*404b540aSrobert 
4815*404b540aSrobert static void
avr_output_progmem_section_asm_op(const void * arg ATTRIBUTE_UNUSED)4816*404b540aSrobert avr_output_progmem_section_asm_op (const void *arg ATTRIBUTE_UNUSED)
4817*404b540aSrobert {
4818*404b540aSrobert   fprintf (asm_out_file,
4819*404b540aSrobert 	   "\t.section .progmem.gcc_sw_table, \"%s\", @progbits\n",
4820*404b540aSrobert 	   AVR_MEGA ? "a" : "ax");
4821*404b540aSrobert   /* Should already be aligned, this is just to be safe if it isn't.  */
4822*404b540aSrobert   fprintf (asm_out_file, "\t.p2align 1\n");
4823*404b540aSrobert }
4824*404b540aSrobert 
4825*404b540aSrobert /* Implement TARGET_ASM_INIT_SECTIONS.  */
4826*404b540aSrobert 
4827*404b540aSrobert static void
avr_asm_init_sections(void)4828*404b540aSrobert avr_asm_init_sections (void)
4829*404b540aSrobert {
4830*404b540aSrobert   progmem_section = get_unnamed_section (AVR_MEGA ? 0 : SECTION_CODE,
4831*404b540aSrobert 					 avr_output_progmem_section_asm_op,
4832*404b540aSrobert 					 NULL);
4833*404b540aSrobert   readonly_data_section = data_section;
4834*404b540aSrobert }
4835*404b540aSrobert 
4836*404b540aSrobert static unsigned int
avr_section_type_flags(tree decl,const char * name,int reloc)4837*404b540aSrobert avr_section_type_flags (tree decl, const char *name, int reloc)
4838*404b540aSrobert {
4839*404b540aSrobert   unsigned int flags = default_section_type_flags (decl, name, reloc);
4840*404b540aSrobert 
4841*404b540aSrobert   if (strncmp (name, ".noinit", 7) == 0)
4842*404b540aSrobert     {
4843*404b540aSrobert       if (decl && TREE_CODE (decl) == VAR_DECL
4844*404b540aSrobert 	  && DECL_INITIAL (decl) == NULL_TREE)
4845*404b540aSrobert 	flags |= SECTION_BSS;  /* @nobits */
4846*404b540aSrobert       else
4847*404b540aSrobert 	warning (0, "only uninitialized variables can be placed in the "
4848*404b540aSrobert 		 ".noinit section");
4849*404b540aSrobert     }
4850*404b540aSrobert 
4851*404b540aSrobert   return flags;
4852*404b540aSrobert }
4853*404b540aSrobert 
4854*404b540aSrobert /* Outputs some appropriate text to go at the start of an assembler
4855*404b540aSrobert    file.  */
4856*404b540aSrobert 
4857*404b540aSrobert static void
avr_file_start(void)4858*404b540aSrobert avr_file_start (void)
4859*404b540aSrobert {
4860*404b540aSrobert   if (avr_asm_only_p)
4861*404b540aSrobert     error ("MCU %qs supported for assembler only", avr_mcu_name);
4862*404b540aSrobert 
4863*404b540aSrobert   default_file_start ();
4864*404b540aSrobert 
4865*404b540aSrobert /*  fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);*/
4866*404b540aSrobert   fputs ("__SREG__ = 0x3f\n"
4867*404b540aSrobert 	 "__SP_H__ = 0x3e\n"
4868*404b540aSrobert 	 "__SP_L__ = 0x3d\n", asm_out_file);
4869*404b540aSrobert 
4870*404b540aSrobert   fputs ("__tmp_reg__ = 0\n"
4871*404b540aSrobert          "__zero_reg__ = 1\n", asm_out_file);
4872*404b540aSrobert 
4873*404b540aSrobert   /* FIXME: output these only if there is anything in the .data / .bss
4874*404b540aSrobert      sections - some code size could be saved by not linking in the
4875*404b540aSrobert      initialization code from libgcc if one or both sections are empty.  */
4876*404b540aSrobert   fputs ("\t.global __do_copy_data\n", asm_out_file);
4877*404b540aSrobert   fputs ("\t.global __do_clear_bss\n", asm_out_file);
4878*404b540aSrobert 
4879*404b540aSrobert   commands_in_file = 0;
4880*404b540aSrobert   commands_in_prologues = 0;
4881*404b540aSrobert   commands_in_epilogues = 0;
4882*404b540aSrobert }
4883*404b540aSrobert 
4884*404b540aSrobert /* Outputs to the stdio stream FILE some
4885*404b540aSrobert    appropriate text to go at the end of an assembler file.  */
4886*404b540aSrobert 
4887*404b540aSrobert static void
avr_file_end(void)4888*404b540aSrobert avr_file_end (void)
4889*404b540aSrobert {
4890*404b540aSrobert   fputs ("/* File ", asm_out_file);
4891*404b540aSrobert   output_quoted_string (asm_out_file, main_input_filename);
4892*404b540aSrobert   fprintf (asm_out_file,
4893*404b540aSrobert 	   ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4894*404b540aSrobert 	   commands_in_file,
4895*404b540aSrobert 	   commands_in_file,
4896*404b540aSrobert 	   commands_in_file - commands_in_prologues - commands_in_epilogues,
4897*404b540aSrobert 	   commands_in_prologues, commands_in_epilogues);
4898*404b540aSrobert }
4899*404b540aSrobert 
4900*404b540aSrobert /* Choose the order in which to allocate hard registers for
4901*404b540aSrobert    pseudo-registers local to a basic block.
4902*404b540aSrobert 
4903*404b540aSrobert    Store the desired register order in the array `reg_alloc_order'.
4904*404b540aSrobert    Element 0 should be the register to allocate first; element 1, the
4905*404b540aSrobert    next register; and so on.  */
4906*404b540aSrobert 
4907*404b540aSrobert void
order_regs_for_local_alloc(void)4908*404b540aSrobert order_regs_for_local_alloc (void)
4909*404b540aSrobert {
4910*404b540aSrobert   unsigned int i;
4911*404b540aSrobert   static const int order_0[] = {
4912*404b540aSrobert     24,25,
4913*404b540aSrobert     18,19,
4914*404b540aSrobert     20,21,
4915*404b540aSrobert     22,23,
4916*404b540aSrobert     30,31,
4917*404b540aSrobert     26,27,
4918*404b540aSrobert     28,29,
4919*404b540aSrobert     17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4920*404b540aSrobert     0,1,
4921*404b540aSrobert     32,33,34,35
4922*404b540aSrobert   };
4923*404b540aSrobert   static const int order_1[] = {
4924*404b540aSrobert     18,19,
4925*404b540aSrobert     20,21,
4926*404b540aSrobert     22,23,
4927*404b540aSrobert     24,25,
4928*404b540aSrobert     30,31,
4929*404b540aSrobert     26,27,
4930*404b540aSrobert     28,29,
4931*404b540aSrobert     17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4932*404b540aSrobert     0,1,
4933*404b540aSrobert     32,33,34,35
4934*404b540aSrobert   };
4935*404b540aSrobert   static const int order_2[] = {
4936*404b540aSrobert     25,24,
4937*404b540aSrobert     23,22,
4938*404b540aSrobert     21,20,
4939*404b540aSrobert     19,18,
4940*404b540aSrobert     30,31,
4941*404b540aSrobert     26,27,
4942*404b540aSrobert     28,29,
4943*404b540aSrobert     17,16,
4944*404b540aSrobert     15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4945*404b540aSrobert     1,0,
4946*404b540aSrobert     32,33,34,35
4947*404b540aSrobert   };
4948*404b540aSrobert 
4949*404b540aSrobert   const int *order = (TARGET_ORDER_1 ? order_1 :
4950*404b540aSrobert 		      TARGET_ORDER_2 ? order_2 :
4951*404b540aSrobert 		      order_0);
4952*404b540aSrobert   for (i=0; i < ARRAY_SIZE (order_0); ++i)
4953*404b540aSrobert       reg_alloc_order[i] = order[i];
4954*404b540aSrobert }
4955*404b540aSrobert 
4956*404b540aSrobert 
4957*404b540aSrobert /* Mutually recursive subroutine of avr_rtx_cost for calculating the
4958*404b540aSrobert    cost of an RTX operand given its context.  X is the rtx of the
4959*404b540aSrobert    operand, MODE is its mode, and OUTER is the rtx_code of this
4960*404b540aSrobert    operand's parent operator.  */
4961*404b540aSrobert 
4962*404b540aSrobert static int
avr_operand_rtx_cost(rtx x,enum machine_mode mode,enum rtx_code outer)4963*404b540aSrobert avr_operand_rtx_cost (rtx x, enum machine_mode mode, enum rtx_code outer)
4964*404b540aSrobert {
4965*404b540aSrobert   enum rtx_code code = GET_CODE (x);
4966*404b540aSrobert   int total;
4967*404b540aSrobert 
4968*404b540aSrobert   switch (code)
4969*404b540aSrobert     {
4970*404b540aSrobert     case REG:
4971*404b540aSrobert     case SUBREG:
4972*404b540aSrobert       return 0;
4973*404b540aSrobert 
4974*404b540aSrobert     case CONST_INT:
4975*404b540aSrobert     case CONST_DOUBLE:
4976*404b540aSrobert       return COSTS_N_INSNS (GET_MODE_SIZE (mode));
4977*404b540aSrobert 
4978*404b540aSrobert     default:
4979*404b540aSrobert       break;
4980*404b540aSrobert     }
4981*404b540aSrobert 
4982*404b540aSrobert   total = 0;
4983*404b540aSrobert   avr_rtx_costs (x, code, outer, &total);
4984*404b540aSrobert   return total;
4985*404b540aSrobert }
4986*404b540aSrobert 
4987*404b540aSrobert /* The AVR backend's rtx_cost function.  X is rtx expression whose cost
4988*404b540aSrobert    is to be calculated.  Return true if the complete cost has been
4989*404b540aSrobert    computed, and false if subexpressions should be scanned.  In either
4990*404b540aSrobert    case, *TOTAL contains the cost result.  */
4991*404b540aSrobert 
4992*404b540aSrobert static bool
avr_rtx_costs(rtx x,int code,int outer_code ATTRIBUTE_UNUSED,int * total)4993*404b540aSrobert avr_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
4994*404b540aSrobert {
4995*404b540aSrobert   enum machine_mode mode = GET_MODE (x);
4996*404b540aSrobert   HOST_WIDE_INT val;
4997*404b540aSrobert 
4998*404b540aSrobert   switch (code)
4999*404b540aSrobert     {
5000*404b540aSrobert     case CONST_INT:
5001*404b540aSrobert     case CONST_DOUBLE:
5002*404b540aSrobert       /* Immediate constants are as cheap as registers.  */
5003*404b540aSrobert       *total = 0;
5004*404b540aSrobert       return true;
5005*404b540aSrobert 
5006*404b540aSrobert     case MEM:
5007*404b540aSrobert     case CONST:
5008*404b540aSrobert     case LABEL_REF:
5009*404b540aSrobert     case SYMBOL_REF:
5010*404b540aSrobert       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
5011*404b540aSrobert       return true;
5012*404b540aSrobert 
5013*404b540aSrobert     case NEG:
5014*404b540aSrobert       switch (mode)
5015*404b540aSrobert 	{
5016*404b540aSrobert 	case QImode:
5017*404b540aSrobert 	case SFmode:
5018*404b540aSrobert 	  *total = COSTS_N_INSNS (1);
5019*404b540aSrobert 	  break;
5020*404b540aSrobert 
5021*404b540aSrobert 	case HImode:
5022*404b540aSrobert 	  *total = COSTS_N_INSNS (3);
5023*404b540aSrobert 	  break;
5024*404b540aSrobert 
5025*404b540aSrobert 	case SImode:
5026*404b540aSrobert 	  *total = COSTS_N_INSNS (7);
5027*404b540aSrobert 	  break;
5028*404b540aSrobert 
5029*404b540aSrobert 	default:
5030*404b540aSrobert 	  return false;
5031*404b540aSrobert 	}
5032*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5033*404b540aSrobert       return true;
5034*404b540aSrobert 
5035*404b540aSrobert     case ABS:
5036*404b540aSrobert       switch (mode)
5037*404b540aSrobert 	{
5038*404b540aSrobert 	case QImode:
5039*404b540aSrobert 	case SFmode:
5040*404b540aSrobert 	  *total = COSTS_N_INSNS (1);
5041*404b540aSrobert 	  break;
5042*404b540aSrobert 
5043*404b540aSrobert 	default:
5044*404b540aSrobert 	  return false;
5045*404b540aSrobert 	}
5046*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5047*404b540aSrobert       return true;
5048*404b540aSrobert 
5049*404b540aSrobert     case NOT:
5050*404b540aSrobert       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
5051*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5052*404b540aSrobert       return true;
5053*404b540aSrobert 
5054*404b540aSrobert     case ZERO_EXTEND:
5055*404b540aSrobert       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
5056*404b540aSrobert 			      - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
5057*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5058*404b540aSrobert       return true;
5059*404b540aSrobert 
5060*404b540aSrobert     case SIGN_EXTEND:
5061*404b540aSrobert       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
5062*404b540aSrobert 			      - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
5063*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5064*404b540aSrobert       return true;
5065*404b540aSrobert 
5066*404b540aSrobert     case PLUS:
5067*404b540aSrobert       switch (mode)
5068*404b540aSrobert 	{
5069*404b540aSrobert 	case QImode:
5070*404b540aSrobert 	  *total = COSTS_N_INSNS (1);
5071*404b540aSrobert 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5072*404b540aSrobert 	    *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5073*404b540aSrobert 	  break;
5074*404b540aSrobert 
5075*404b540aSrobert 	case HImode:
5076*404b540aSrobert 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5077*404b540aSrobert 	    {
5078*404b540aSrobert 	      *total = COSTS_N_INSNS (2);
5079*404b540aSrobert 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5080*404b540aSrobert 	    }
5081*404b540aSrobert 	  else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
5082*404b540aSrobert 	    *total = COSTS_N_INSNS (1);
5083*404b540aSrobert 	  else
5084*404b540aSrobert 	    *total = COSTS_N_INSNS (2);
5085*404b540aSrobert 	  break;
5086*404b540aSrobert 
5087*404b540aSrobert 	case SImode:
5088*404b540aSrobert 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5089*404b540aSrobert 	    {
5090*404b540aSrobert 	      *total = COSTS_N_INSNS (4);
5091*404b540aSrobert 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5092*404b540aSrobert 	    }
5093*404b540aSrobert 	  else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
5094*404b540aSrobert 	    *total = COSTS_N_INSNS (1);
5095*404b540aSrobert 	  else
5096*404b540aSrobert 	    *total = COSTS_N_INSNS (4);
5097*404b540aSrobert 	  break;
5098*404b540aSrobert 
5099*404b540aSrobert 	default:
5100*404b540aSrobert 	  return false;
5101*404b540aSrobert 	}
5102*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5103*404b540aSrobert       return true;
5104*404b540aSrobert 
5105*404b540aSrobert     case MINUS:
5106*404b540aSrobert     case AND:
5107*404b540aSrobert     case IOR:
5108*404b540aSrobert       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
5109*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5110*404b540aSrobert       if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5111*404b540aSrobert           *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5112*404b540aSrobert       return true;
5113*404b540aSrobert 
5114*404b540aSrobert     case XOR:
5115*404b540aSrobert       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
5116*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5117*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5118*404b540aSrobert       return true;
5119*404b540aSrobert 
5120*404b540aSrobert     case MULT:
5121*404b540aSrobert       switch (mode)
5122*404b540aSrobert 	{
5123*404b540aSrobert 	case QImode:
5124*404b540aSrobert 	  if (AVR_ENHANCED)
5125*404b540aSrobert 	    *total = COSTS_N_INSNS (optimize_size ? 3 : 4);
5126*404b540aSrobert 	  else if (optimize_size)
5127*404b540aSrobert 	    *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
5128*404b540aSrobert 	  else
5129*404b540aSrobert 	    return false;
5130*404b540aSrobert 	  break;
5131*404b540aSrobert 
5132*404b540aSrobert 	case HImode:
5133*404b540aSrobert 	  if (AVR_ENHANCED)
5134*404b540aSrobert 	    *total = COSTS_N_INSNS (optimize_size ? 7 : 10);
5135*404b540aSrobert 	  else if (optimize_size)
5136*404b540aSrobert 	    *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
5137*404b540aSrobert 	  else
5138*404b540aSrobert 	    return false;
5139*404b540aSrobert 	  break;
5140*404b540aSrobert 
5141*404b540aSrobert 	default:
5142*404b540aSrobert 	  return false;
5143*404b540aSrobert 	}
5144*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5145*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5146*404b540aSrobert       return true;
5147*404b540aSrobert 
5148*404b540aSrobert     case DIV:
5149*404b540aSrobert     case MOD:
5150*404b540aSrobert     case UDIV:
5151*404b540aSrobert     case UMOD:
5152*404b540aSrobert       if (optimize_size)
5153*404b540aSrobert 	*total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
5154*404b540aSrobert       else
5155*404b540aSrobert 	return false;
5156*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5157*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5158*404b540aSrobert       return true;
5159*404b540aSrobert 
5160*404b540aSrobert     case ASHIFT:
5161*404b540aSrobert       switch (mode)
5162*404b540aSrobert 	{
5163*404b540aSrobert 	case QImode:
5164*404b540aSrobert 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5165*404b540aSrobert 	    {
5166*404b540aSrobert 	      *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
5167*404b540aSrobert 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5168*404b540aSrobert 	    }
5169*404b540aSrobert 	  else
5170*404b540aSrobert 	    {
5171*404b540aSrobert 	      val = INTVAL (XEXP (x, 1));
5172*404b540aSrobert 	      if (val == 7)
5173*404b540aSrobert 		*total = COSTS_N_INSNS (3);
5174*404b540aSrobert 	      else if (val >= 0 && val <= 7)
5175*404b540aSrobert 		*total = COSTS_N_INSNS (val);
5176*404b540aSrobert 	      else
5177*404b540aSrobert 		*total = COSTS_N_INSNS (1);
5178*404b540aSrobert 	    }
5179*404b540aSrobert 	  break;
5180*404b540aSrobert 
5181*404b540aSrobert 	case HImode:
5182*404b540aSrobert 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5183*404b540aSrobert 	    {
5184*404b540aSrobert 	      *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5185*404b540aSrobert 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5186*404b540aSrobert 	    }
5187*404b540aSrobert 	  else
5188*404b540aSrobert 	    switch (INTVAL (XEXP (x, 1)))
5189*404b540aSrobert 	      {
5190*404b540aSrobert 	      case 0:
5191*404b540aSrobert 		*total = 0;
5192*404b540aSrobert 		break;
5193*404b540aSrobert 	      case 1:
5194*404b540aSrobert 	      case 8:
5195*404b540aSrobert 		*total = COSTS_N_INSNS (2);
5196*404b540aSrobert 		break;
5197*404b540aSrobert 	      case 9:
5198*404b540aSrobert 		*total = COSTS_N_INSNS (3);
5199*404b540aSrobert 		break;
5200*404b540aSrobert 	      case 2:
5201*404b540aSrobert 	      case 3:
5202*404b540aSrobert 	      case 10:
5203*404b540aSrobert 	      case 15:
5204*404b540aSrobert 		*total = COSTS_N_INSNS (4);
5205*404b540aSrobert 		break;
5206*404b540aSrobert 	      case 7:
5207*404b540aSrobert 	      case 11:
5208*404b540aSrobert 	      case 12:
5209*404b540aSrobert 		*total = COSTS_N_INSNS (5);
5210*404b540aSrobert 		break;
5211*404b540aSrobert 	      case 4:
5212*404b540aSrobert 		*total = COSTS_N_INSNS (optimize_size ? 5 : 8);
5213*404b540aSrobert 		break;
5214*404b540aSrobert 	      case 6:
5215*404b540aSrobert 		*total = COSTS_N_INSNS (optimize_size ? 5 : 9);
5216*404b540aSrobert 		break;
5217*404b540aSrobert 	      case 5:
5218*404b540aSrobert 		*total = COSTS_N_INSNS (optimize_size ? 5 : 10);
5219*404b540aSrobert 		break;
5220*404b540aSrobert 	      default:
5221*404b540aSrobert 	        *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5222*404b540aSrobert 	        *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5223*404b540aSrobert 	      }
5224*404b540aSrobert 	  break;
5225*404b540aSrobert 
5226*404b540aSrobert 	case SImode:
5227*404b540aSrobert 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5228*404b540aSrobert 	    {
5229*404b540aSrobert 	      *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5230*404b540aSrobert 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5231*404b540aSrobert 	    }
5232*404b540aSrobert 	  else
5233*404b540aSrobert 	    switch (INTVAL (XEXP (x, 1)))
5234*404b540aSrobert 	      {
5235*404b540aSrobert 	      case 0:
5236*404b540aSrobert 		*total = 0;
5237*404b540aSrobert 		break;
5238*404b540aSrobert 	      case 24:
5239*404b540aSrobert 		*total = COSTS_N_INSNS (3);
5240*404b540aSrobert 		break;
5241*404b540aSrobert 	      case 1:
5242*404b540aSrobert 	      case 8:
5243*404b540aSrobert 	      case 16:
5244*404b540aSrobert 		*total = COSTS_N_INSNS (4);
5245*404b540aSrobert 		break;
5246*404b540aSrobert 	      case 31:
5247*404b540aSrobert 		*total = COSTS_N_INSNS (6);
5248*404b540aSrobert 		break;
5249*404b540aSrobert 	      case 2:
5250*404b540aSrobert 		*total = COSTS_N_INSNS (optimize_size ? 7 : 8);
5251*404b540aSrobert 		break;
5252*404b540aSrobert 	      default:
5253*404b540aSrobert 		*total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5254*404b540aSrobert 		*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5255*404b540aSrobert 	      }
5256*404b540aSrobert 	  break;
5257*404b540aSrobert 
5258*404b540aSrobert 	default:
5259*404b540aSrobert 	  return false;
5260*404b540aSrobert 	}
5261*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5262*404b540aSrobert       return true;
5263*404b540aSrobert 
5264*404b540aSrobert     case ASHIFTRT:
5265*404b540aSrobert       switch (mode)
5266*404b540aSrobert 	{
5267*404b540aSrobert 	case QImode:
5268*404b540aSrobert 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5269*404b540aSrobert 	    {
5270*404b540aSrobert 	      *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
5271*404b540aSrobert 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5272*404b540aSrobert 	    }
5273*404b540aSrobert 	  else
5274*404b540aSrobert 	    {
5275*404b540aSrobert 	      val = INTVAL (XEXP (x, 1));
5276*404b540aSrobert 	      if (val == 6)
5277*404b540aSrobert 		*total = COSTS_N_INSNS (4);
5278*404b540aSrobert 	      else if (val == 7)
5279*404b540aSrobert 		*total = COSTS_N_INSNS (2);
5280*404b540aSrobert 	      else if (val >= 0 && val <= 7)
5281*404b540aSrobert 		*total = COSTS_N_INSNS (val);
5282*404b540aSrobert 	      else
5283*404b540aSrobert 		*total = COSTS_N_INSNS (1);
5284*404b540aSrobert 	    }
5285*404b540aSrobert 	  break;
5286*404b540aSrobert 
5287*404b540aSrobert 	case HImode:
5288*404b540aSrobert 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5289*404b540aSrobert 	    {
5290*404b540aSrobert 	      *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5291*404b540aSrobert 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5292*404b540aSrobert 	    }
5293*404b540aSrobert 	  else
5294*404b540aSrobert 	    switch (INTVAL (XEXP (x, 1)))
5295*404b540aSrobert 	      {
5296*404b540aSrobert 	      case 0:
5297*404b540aSrobert 		*total = 0;
5298*404b540aSrobert 		break;
5299*404b540aSrobert 	      case 1:
5300*404b540aSrobert 		*total = COSTS_N_INSNS (2);
5301*404b540aSrobert 		break;
5302*404b540aSrobert 	      case 15:
5303*404b540aSrobert 		*total = COSTS_N_INSNS (3);
5304*404b540aSrobert 		break;
5305*404b540aSrobert 	      case 2:
5306*404b540aSrobert 	      case 7:
5307*404b540aSrobert               case 8:
5308*404b540aSrobert               case 9:
5309*404b540aSrobert 		*total = COSTS_N_INSNS (4);
5310*404b540aSrobert 		break;
5311*404b540aSrobert               case 10:
5312*404b540aSrobert 	      case 14:
5313*404b540aSrobert 		*total = COSTS_N_INSNS (5);
5314*404b540aSrobert 		break;
5315*404b540aSrobert               case 11:
5316*404b540aSrobert                 *total = COSTS_N_INSNS (optimize_size ? 5 : 6);
5317*404b540aSrobert 		break;
5318*404b540aSrobert               case 12:
5319*404b540aSrobert                 *total = COSTS_N_INSNS (optimize_size ? 5 : 7);
5320*404b540aSrobert 		break;
5321*404b540aSrobert               case 6:
5322*404b540aSrobert 	      case 13:
5323*404b540aSrobert                 *total = COSTS_N_INSNS (optimize_size ? 5 : 8);
5324*404b540aSrobert 		break;
5325*404b540aSrobert 	      default:
5326*404b540aSrobert 	        *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5327*404b540aSrobert 	        *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5328*404b540aSrobert 	      }
5329*404b540aSrobert 	  break;
5330*404b540aSrobert 
5331*404b540aSrobert 	case SImode:
5332*404b540aSrobert 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5333*404b540aSrobert 	    {
5334*404b540aSrobert 	      *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5335*404b540aSrobert 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5336*404b540aSrobert 	    }
5337*404b540aSrobert 	  else
5338*404b540aSrobert 	    switch (INTVAL (XEXP (x, 1)))
5339*404b540aSrobert 	      {
5340*404b540aSrobert 	      case 0:
5341*404b540aSrobert 		*total = 0;
5342*404b540aSrobert 		break;
5343*404b540aSrobert 	      case 1:
5344*404b540aSrobert 		*total = COSTS_N_INSNS (4);
5345*404b540aSrobert 		break;
5346*404b540aSrobert 	      case 8:
5347*404b540aSrobert 	      case 16:
5348*404b540aSrobert 	      case 24:
5349*404b540aSrobert 		*total = COSTS_N_INSNS (6);
5350*404b540aSrobert 		break;
5351*404b540aSrobert 	      case 2:
5352*404b540aSrobert 		*total = COSTS_N_INSNS (optimize_size ? 7 : 8);
5353*404b540aSrobert 		break;
5354*404b540aSrobert 	      case 31:
5355*404b540aSrobert 		*total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
5356*404b540aSrobert 		break;
5357*404b540aSrobert 	      default:
5358*404b540aSrobert 		*total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5359*404b540aSrobert 		*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5360*404b540aSrobert 	      }
5361*404b540aSrobert 	  break;
5362*404b540aSrobert 
5363*404b540aSrobert 	default:
5364*404b540aSrobert 	  return false;
5365*404b540aSrobert 	}
5366*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5367*404b540aSrobert       return true;
5368*404b540aSrobert 
5369*404b540aSrobert     case LSHIFTRT:
5370*404b540aSrobert       switch (mode)
5371*404b540aSrobert 	{
5372*404b540aSrobert 	case QImode:
5373*404b540aSrobert 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5374*404b540aSrobert 	    {
5375*404b540aSrobert 	      *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
5376*404b540aSrobert 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5377*404b540aSrobert 	    }
5378*404b540aSrobert 	  else
5379*404b540aSrobert 	    {
5380*404b540aSrobert 	      val = INTVAL (XEXP (x, 1));
5381*404b540aSrobert 	      if (val == 7)
5382*404b540aSrobert 		*total = COSTS_N_INSNS (3);
5383*404b540aSrobert 	      else if (val >= 0 && val <= 7)
5384*404b540aSrobert 		*total = COSTS_N_INSNS (val);
5385*404b540aSrobert 	      else
5386*404b540aSrobert 		*total = COSTS_N_INSNS (1);
5387*404b540aSrobert 	    }
5388*404b540aSrobert 	  break;
5389*404b540aSrobert 
5390*404b540aSrobert 	case HImode:
5391*404b540aSrobert 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5392*404b540aSrobert 	    {
5393*404b540aSrobert 	      *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5394*404b540aSrobert 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5395*404b540aSrobert 	    }
5396*404b540aSrobert 	  else
5397*404b540aSrobert 	    switch (INTVAL (XEXP (x, 1)))
5398*404b540aSrobert 	      {
5399*404b540aSrobert 	      case 0:
5400*404b540aSrobert 		*total = 0;
5401*404b540aSrobert 		break;
5402*404b540aSrobert 	      case 1:
5403*404b540aSrobert 	      case 8:
5404*404b540aSrobert 		*total = COSTS_N_INSNS (2);
5405*404b540aSrobert 		break;
5406*404b540aSrobert 	      case 9:
5407*404b540aSrobert 		*total = COSTS_N_INSNS (3);
5408*404b540aSrobert 		break;
5409*404b540aSrobert 	      case 2:
5410*404b540aSrobert 	      case 10:
5411*404b540aSrobert 	      case 15:
5412*404b540aSrobert 		*total = COSTS_N_INSNS (4);
5413*404b540aSrobert 		break;
5414*404b540aSrobert 	      case 7:
5415*404b540aSrobert               case 11:
5416*404b540aSrobert 		*total = COSTS_N_INSNS (5);
5417*404b540aSrobert 		break;
5418*404b540aSrobert 	      case 3:
5419*404b540aSrobert 	      case 12:
5420*404b540aSrobert 	      case 13:
5421*404b540aSrobert 	      case 14:
5422*404b540aSrobert 		*total = COSTS_N_INSNS (optimize_size ? 5 : 6);
5423*404b540aSrobert 		break;
5424*404b540aSrobert 	      case 4:
5425*404b540aSrobert 		*total = COSTS_N_INSNS (optimize_size ? 5 : 7);
5426*404b540aSrobert 		break;
5427*404b540aSrobert 	      case 5:
5428*404b540aSrobert 	      case 6:
5429*404b540aSrobert 		*total = COSTS_N_INSNS (optimize_size ? 5 : 9);
5430*404b540aSrobert 		break;
5431*404b540aSrobert 	      default:
5432*404b540aSrobert 	        *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5433*404b540aSrobert 	        *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5434*404b540aSrobert 	      }
5435*404b540aSrobert 	  break;
5436*404b540aSrobert 
5437*404b540aSrobert 	case SImode:
5438*404b540aSrobert 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5439*404b540aSrobert 	    {
5440*404b540aSrobert 	      *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5441*404b540aSrobert 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5442*404b540aSrobert 	    }
5443*404b540aSrobert 	  else
5444*404b540aSrobert 	    switch (INTVAL (XEXP (x, 1)))
5445*404b540aSrobert 	      {
5446*404b540aSrobert 	      case 0:
5447*404b540aSrobert 		*total = 0;
5448*404b540aSrobert 		break;
5449*404b540aSrobert 	      case 1:
5450*404b540aSrobert 		*total = COSTS_N_INSNS (4);
5451*404b540aSrobert 		break;
5452*404b540aSrobert 	      case 2:
5453*404b540aSrobert 		*total = COSTS_N_INSNS (optimize_size ? 7 : 8);
5454*404b540aSrobert 		break;
5455*404b540aSrobert 	      case 8:
5456*404b540aSrobert 	      case 16:
5457*404b540aSrobert 	      case 24:
5458*404b540aSrobert 		*total = COSTS_N_INSNS (4);
5459*404b540aSrobert 		break;
5460*404b540aSrobert 	      case 31:
5461*404b540aSrobert 		*total = COSTS_N_INSNS (6);
5462*404b540aSrobert 		break;
5463*404b540aSrobert 	      default:
5464*404b540aSrobert 		*total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5465*404b540aSrobert 		*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5466*404b540aSrobert 	      }
5467*404b540aSrobert 	  break;
5468*404b540aSrobert 
5469*404b540aSrobert 	default:
5470*404b540aSrobert 	  return false;
5471*404b540aSrobert 	}
5472*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5473*404b540aSrobert       return true;
5474*404b540aSrobert 
5475*404b540aSrobert     case COMPARE:
5476*404b540aSrobert       switch (GET_MODE (XEXP (x, 0)))
5477*404b540aSrobert 	{
5478*404b540aSrobert 	case QImode:
5479*404b540aSrobert 	  *total = COSTS_N_INSNS (1);
5480*404b540aSrobert 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5481*404b540aSrobert 	    *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5482*404b540aSrobert 	  break;
5483*404b540aSrobert 
5484*404b540aSrobert         case HImode:
5485*404b540aSrobert 	  *total = COSTS_N_INSNS (2);
5486*404b540aSrobert 	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5487*404b540aSrobert             *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5488*404b540aSrobert 	  else if (INTVAL (XEXP (x, 1)) != 0)
5489*404b540aSrobert 	    *total += COSTS_N_INSNS (1);
5490*404b540aSrobert           break;
5491*404b540aSrobert 
5492*404b540aSrobert         case SImode:
5493*404b540aSrobert           *total = COSTS_N_INSNS (4);
5494*404b540aSrobert           if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5495*404b540aSrobert             *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5496*404b540aSrobert 	  else if (INTVAL (XEXP (x, 1)) != 0)
5497*404b540aSrobert 	    *total += COSTS_N_INSNS (3);
5498*404b540aSrobert           break;
5499*404b540aSrobert 
5500*404b540aSrobert 	default:
5501*404b540aSrobert 	  return false;
5502*404b540aSrobert 	}
5503*404b540aSrobert       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5504*404b540aSrobert       return true;
5505*404b540aSrobert 
5506*404b540aSrobert     default:
5507*404b540aSrobert       break;
5508*404b540aSrobert     }
5509*404b540aSrobert   return false;
5510*404b540aSrobert }
5511*404b540aSrobert 
5512*404b540aSrobert /* Calculate the cost of a memory address.  */
5513*404b540aSrobert 
5514*404b540aSrobert static int
avr_address_cost(rtx x)5515*404b540aSrobert avr_address_cost (rtx x)
5516*404b540aSrobert {
5517*404b540aSrobert   if (GET_CODE (x) == PLUS
5518*404b540aSrobert       && GET_CODE (XEXP (x,1)) == CONST_INT
5519*404b540aSrobert       && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
5520*404b540aSrobert       && INTVAL (XEXP (x,1)) >= 61)
5521*404b540aSrobert     return 18;
5522*404b540aSrobert   if (CONSTANT_ADDRESS_P (x))
5523*404b540aSrobert     {
5524*404b540aSrobert       if (avr_io_address_p (x, 1))
5525*404b540aSrobert 	return 2;
5526*404b540aSrobert       return 4;
5527*404b540aSrobert     }
5528*404b540aSrobert   return 4;
5529*404b540aSrobert }
5530*404b540aSrobert 
5531*404b540aSrobert /* Test for extra memory constraint 'Q'.
5532*404b540aSrobert    It's a memory address based on Y or Z pointer with valid displacement.  */
5533*404b540aSrobert 
5534*404b540aSrobert int
extra_constraint_Q(rtx x)5535*404b540aSrobert extra_constraint_Q (rtx x)
5536*404b540aSrobert {
5537*404b540aSrobert   if (GET_CODE (XEXP (x,0)) == PLUS
5538*404b540aSrobert       && REG_P (XEXP (XEXP (x,0), 0))
5539*404b540aSrobert       && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
5540*404b540aSrobert       && (INTVAL (XEXP (XEXP (x,0), 1))
5541*404b540aSrobert 	  <= MAX_LD_OFFSET (GET_MODE (x))))
5542*404b540aSrobert     {
5543*404b540aSrobert       rtx xx = XEXP (XEXP (x,0), 0);
5544*404b540aSrobert       int regno = REGNO (xx);
5545*404b540aSrobert       if (TARGET_ALL_DEBUG)
5546*404b540aSrobert 	{
5547*404b540aSrobert 	  fprintf (stderr, ("extra_constraint:\n"
5548*404b540aSrobert 			    "reload_completed: %d\n"
5549*404b540aSrobert 			    "reload_in_progress: %d\n"),
5550*404b540aSrobert 		   reload_completed, reload_in_progress);
5551*404b540aSrobert 	  debug_rtx (x);
5552*404b540aSrobert 	}
5553*404b540aSrobert       if (regno >= FIRST_PSEUDO_REGISTER)
5554*404b540aSrobert 	return 1;		/* allocate pseudos */
5555*404b540aSrobert       else if (regno == REG_Z || regno == REG_Y)
5556*404b540aSrobert 	return 1;		/* strictly check */
5557*404b540aSrobert       else if (xx == frame_pointer_rtx
5558*404b540aSrobert 	       || xx == arg_pointer_rtx)
5559*404b540aSrobert 	return 1;		/* XXX frame & arg pointer checks */
5560*404b540aSrobert     }
5561*404b540aSrobert   return 0;
5562*404b540aSrobert }
5563*404b540aSrobert 
5564*404b540aSrobert /* Convert condition code CONDITION to the valid AVR condition code.  */
5565*404b540aSrobert 
5566*404b540aSrobert RTX_CODE
avr_normalize_condition(RTX_CODE condition)5567*404b540aSrobert avr_normalize_condition (RTX_CODE condition)
5568*404b540aSrobert {
5569*404b540aSrobert   switch (condition)
5570*404b540aSrobert     {
5571*404b540aSrobert     case GT:
5572*404b540aSrobert       return GE;
5573*404b540aSrobert     case GTU:
5574*404b540aSrobert       return GEU;
5575*404b540aSrobert     case LE:
5576*404b540aSrobert       return LT;
5577*404b540aSrobert     case LEU:
5578*404b540aSrobert       return LTU;
5579*404b540aSrobert     default:
5580*404b540aSrobert       gcc_unreachable ();
5581*404b540aSrobert     }
5582*404b540aSrobert }
5583*404b540aSrobert 
5584*404b540aSrobert /* This function optimizes conditional jumps.  */
5585*404b540aSrobert 
5586*404b540aSrobert static void
avr_reorg(void)5587*404b540aSrobert avr_reorg (void)
5588*404b540aSrobert {
5589*404b540aSrobert   rtx insn, pattern;
5590*404b540aSrobert 
5591*404b540aSrobert   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5592*404b540aSrobert     {
5593*404b540aSrobert       if (! (GET_CODE (insn) == INSN
5594*404b540aSrobert 	     || GET_CODE (insn) == CALL_INSN
5595*404b540aSrobert 	     || GET_CODE (insn) == JUMP_INSN)
5596*404b540aSrobert 	  || !single_set (insn))
5597*404b540aSrobert 	continue;
5598*404b540aSrobert 
5599*404b540aSrobert       pattern = PATTERN (insn);
5600*404b540aSrobert 
5601*404b540aSrobert       if (GET_CODE (pattern) == PARALLEL)
5602*404b540aSrobert 	pattern = XVECEXP (pattern, 0, 0);
5603*404b540aSrobert       if (GET_CODE (pattern) == SET
5604*404b540aSrobert 	  && SET_DEST (pattern) == cc0_rtx
5605*404b540aSrobert 	  && compare_diff_p (insn))
5606*404b540aSrobert 	{
5607*404b540aSrobert 	  if (GET_CODE (SET_SRC (pattern)) == COMPARE)
5608*404b540aSrobert 	    {
5609*404b540aSrobert 	      /* Now we work under compare insn.  */
5610*404b540aSrobert 
5611*404b540aSrobert 	      pattern = SET_SRC (pattern);
5612*404b540aSrobert 	      if (true_regnum (XEXP (pattern,0)) >= 0
5613*404b540aSrobert 		  && true_regnum (XEXP (pattern,1)) >= 0 )
5614*404b540aSrobert 		{
5615*404b540aSrobert 		  rtx x = XEXP (pattern,0);
5616*404b540aSrobert 		  rtx next = next_real_insn (insn);
5617*404b540aSrobert 		  rtx pat = PATTERN (next);
5618*404b540aSrobert 		  rtx src = SET_SRC (pat);
5619*404b540aSrobert 		  rtx t = XEXP (src,0);
5620*404b540aSrobert 		  PUT_CODE (t, swap_condition (GET_CODE (t)));
5621*404b540aSrobert 		  XEXP (pattern,0) = XEXP (pattern,1);
5622*404b540aSrobert 		  XEXP (pattern,1) = x;
5623*404b540aSrobert 		  INSN_CODE (next) = -1;
5624*404b540aSrobert 		}
5625*404b540aSrobert 	      else if (true_regnum (XEXP (pattern,0)) >= 0
5626*404b540aSrobert 		       && GET_CODE (XEXP (pattern,1)) == CONST_INT)
5627*404b540aSrobert 		{
5628*404b540aSrobert 		  rtx x = XEXP (pattern,1);
5629*404b540aSrobert 		  rtx next = next_real_insn (insn);
5630*404b540aSrobert 		  rtx pat = PATTERN (next);
5631*404b540aSrobert 		  rtx src = SET_SRC (pat);
5632*404b540aSrobert 		  rtx t = XEXP (src,0);
5633*404b540aSrobert 		  enum machine_mode mode = GET_MODE (XEXP (pattern, 0));
5634*404b540aSrobert 
5635*404b540aSrobert 		  if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
5636*404b540aSrobert 		    {
5637*404b540aSrobert 		      XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
5638*404b540aSrobert 		      PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
5639*404b540aSrobert 		      INSN_CODE (next) = -1;
5640*404b540aSrobert 		      INSN_CODE (insn) = -1;
5641*404b540aSrobert 		    }
5642*404b540aSrobert 		}
5643*404b540aSrobert 	    }
5644*404b540aSrobert 	  else if (true_regnum (SET_SRC (pattern)) >= 0)
5645*404b540aSrobert 	    {
5646*404b540aSrobert 	      /* This is a tst insn */
5647*404b540aSrobert 	      rtx next = next_real_insn (insn);
5648*404b540aSrobert 	      rtx pat = PATTERN (next);
5649*404b540aSrobert 	      rtx src = SET_SRC (pat);
5650*404b540aSrobert 	      rtx t = XEXP (src,0);
5651*404b540aSrobert 
5652*404b540aSrobert 	      PUT_CODE (t, swap_condition (GET_CODE (t)));
5653*404b540aSrobert 	      SET_SRC (pattern) = gen_rtx_NEG (GET_MODE (SET_SRC (pattern)),
5654*404b540aSrobert 					       SET_SRC (pattern));
5655*404b540aSrobert 	      INSN_CODE (next) = -1;
5656*404b540aSrobert 	      INSN_CODE (insn) = -1;
5657*404b540aSrobert 	    }
5658*404b540aSrobert 	}
5659*404b540aSrobert     }
5660*404b540aSrobert }
5661*404b540aSrobert 
5662*404b540aSrobert /* Returns register number for function return value.*/
5663*404b540aSrobert 
5664*404b540aSrobert int
avr_ret_register(void)5665*404b540aSrobert avr_ret_register (void)
5666*404b540aSrobert {
5667*404b540aSrobert   return 24;
5668*404b540aSrobert }
5669*404b540aSrobert 
5670*404b540aSrobert /* Ceate an RTX representing the place where a
5671*404b540aSrobert    library function returns a value of mode MODE.  */
5672*404b540aSrobert 
5673*404b540aSrobert rtx
avr_libcall_value(enum machine_mode mode)5674*404b540aSrobert avr_libcall_value (enum machine_mode mode)
5675*404b540aSrobert {
5676*404b540aSrobert   int offs = GET_MODE_SIZE (mode);
5677*404b540aSrobert   if (offs < 2)
5678*404b540aSrobert     offs = 2;
5679*404b540aSrobert   return gen_rtx_REG (mode, RET_REGISTER + 2 - offs);
5680*404b540aSrobert }
5681*404b540aSrobert 
5682*404b540aSrobert /* Create an RTX representing the place where a
5683*404b540aSrobert    function returns a value of data type VALTYPE.  */
5684*404b540aSrobert 
5685*404b540aSrobert rtx
avr_function_value(tree type,tree func ATTRIBUTE_UNUSED)5686*404b540aSrobert avr_function_value (tree type, tree func ATTRIBUTE_UNUSED)
5687*404b540aSrobert {
5688*404b540aSrobert   unsigned int offs;
5689*404b540aSrobert 
5690*404b540aSrobert   if (TYPE_MODE (type) != BLKmode)
5691*404b540aSrobert     return avr_libcall_value (TYPE_MODE (type));
5692*404b540aSrobert 
5693*404b540aSrobert   offs = int_size_in_bytes (type);
5694*404b540aSrobert   if (offs < 2)
5695*404b540aSrobert     offs = 2;
5696*404b540aSrobert   if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5697*404b540aSrobert     offs = GET_MODE_SIZE (SImode);
5698*404b540aSrobert   else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5699*404b540aSrobert     offs = GET_MODE_SIZE (DImode);
5700*404b540aSrobert 
5701*404b540aSrobert   return gen_rtx_REG (BLKmode, RET_REGISTER + 2 - offs);
5702*404b540aSrobert }
5703*404b540aSrobert 
5704*404b540aSrobert /* Returns nonzero if the number MASK has only one bit set.  */
5705*404b540aSrobert 
5706*404b540aSrobert int
mask_one_bit_p(HOST_WIDE_INT mask)5707*404b540aSrobert mask_one_bit_p (HOST_WIDE_INT mask)
5708*404b540aSrobert {
5709*404b540aSrobert   int i;
5710*404b540aSrobert   unsigned HOST_WIDE_INT n=mask;
5711*404b540aSrobert   for (i = 0; i < 32; ++i)
5712*404b540aSrobert     {
5713*404b540aSrobert       if (n & 0x80000000L)
5714*404b540aSrobert 	{
5715*404b540aSrobert 	  if (n & 0x7fffffffL)
5716*404b540aSrobert 	    return 0;
5717*404b540aSrobert 	  else
5718*404b540aSrobert 	    return 32-i;
5719*404b540aSrobert 	}
5720*404b540aSrobert       n<<=1;
5721*404b540aSrobert     }
5722*404b540aSrobert   return 0;
5723*404b540aSrobert }
5724*404b540aSrobert 
5725*404b540aSrobert 
5726*404b540aSrobert /* Places additional restrictions on the register class to
5727*404b540aSrobert    use when it is necessary to copy value X into a register
5728*404b540aSrobert    in class CLASS.  */
5729*404b540aSrobert 
5730*404b540aSrobert enum reg_class
preferred_reload_class(rtx x ATTRIBUTE_UNUSED,enum reg_class class)5731*404b540aSrobert preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class class)
5732*404b540aSrobert {
5733*404b540aSrobert   return class;
5734*404b540aSrobert }
5735*404b540aSrobert 
5736*404b540aSrobert int
test_hard_reg_class(enum reg_class class,rtx x)5737*404b540aSrobert test_hard_reg_class (enum reg_class class, rtx x)
5738*404b540aSrobert {
5739*404b540aSrobert   int regno = true_regnum (x);
5740*404b540aSrobert   if (regno < 0)
5741*404b540aSrobert     return 0;
5742*404b540aSrobert 
5743*404b540aSrobert   if (TEST_HARD_REG_CLASS (class, regno))
5744*404b540aSrobert     return 1;
5745*404b540aSrobert 
5746*404b540aSrobert   return 0;
5747*404b540aSrobert }
5748*404b540aSrobert 
5749*404b540aSrobert 
5750*404b540aSrobert int
jump_over_one_insn_p(rtx insn,rtx dest)5751*404b540aSrobert jump_over_one_insn_p (rtx insn, rtx dest)
5752*404b540aSrobert {
5753*404b540aSrobert   int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5754*404b540aSrobert 		      ? XEXP (dest, 0)
5755*404b540aSrobert 		      : dest);
5756*404b540aSrobert   int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5757*404b540aSrobert   int dest_addr = INSN_ADDRESSES (uid);
5758*404b540aSrobert   return dest_addr - jump_addr == get_attr_length (insn) + 1;
5759*404b540aSrobert }
5760*404b540aSrobert 
5761*404b540aSrobert /* Returns 1 if a value of mode MODE can be stored starting with hard
5762*404b540aSrobert    register number REGNO.  On the enhanced core, anything larger than
5763*404b540aSrobert    1 byte must start in even numbered register for "movw" to work
5764*404b540aSrobert    (this way we don't have to check for odd registers everywhere).  */
5765*404b540aSrobert 
5766*404b540aSrobert int
avr_hard_regno_mode_ok(int regno,enum machine_mode mode)5767*404b540aSrobert avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
5768*404b540aSrobert {
5769*404b540aSrobert   /* The only thing that can go into registers r28:r29 is a Pmode.  */
5770*404b540aSrobert   if (regno == REG_Y && mode == Pmode)
5771*404b540aSrobert     return 1;
5772*404b540aSrobert 
5773*404b540aSrobert   /* Otherwise disallow all regno/mode combinations that span r28:r29.  */
5774*404b540aSrobert   if (regno <= (REG_Y + 1) && (regno + GET_MODE_SIZE (mode)) >= (REG_Y + 1))
5775*404b540aSrobert     return 0;
5776*404b540aSrobert 
5777*404b540aSrobert   if (mode == QImode)
5778*404b540aSrobert     return 1;
5779*404b540aSrobert 
5780*404b540aSrobert   /* Modes larger than QImode occupy consecutive registers.  */
5781*404b540aSrobert   if (regno + GET_MODE_SIZE (mode) > FIRST_PSEUDO_REGISTER)
5782*404b540aSrobert     return 0;
5783*404b540aSrobert 
5784*404b540aSrobert   /* All modes larger than QImode should start in an even register.  */
5785*404b540aSrobert   return !(regno & 1);
5786*404b540aSrobert }
5787*404b540aSrobert 
5788*404b540aSrobert /* Returns 1 if X is a valid address for an I/O register of size SIZE
5789*404b540aSrobert    (1 or 2).  Used for lds/sts -> in/out optimization.  Add 0x20 to SIZE
5790*404b540aSrobert    to check for the lower half of I/O space (for cbi/sbi/sbic/sbis).  */
5791*404b540aSrobert 
5792*404b540aSrobert int
avr_io_address_p(rtx x,int size)5793*404b540aSrobert avr_io_address_p (rtx x, int size)
5794*404b540aSrobert {
5795*404b540aSrobert   return (optimize > 0 && GET_CODE (x) == CONST_INT
5796*404b540aSrobert 	  && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
5797*404b540aSrobert }
5798*404b540aSrobert 
5799*404b540aSrobert /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2.  */
5800*404b540aSrobert 
5801*404b540aSrobert int
const_int_pow2_p(rtx x)5802*404b540aSrobert const_int_pow2_p (rtx x)
5803*404b540aSrobert {
5804*404b540aSrobert   if (GET_CODE (x) == CONST_INT)
5805*404b540aSrobert     {
5806*404b540aSrobert       HOST_WIDE_INT d = INTVAL (x);
5807*404b540aSrobert       HOST_WIDE_INT abs_d = (d >= 0) ? d : -d;
5808*404b540aSrobert       return exact_log2 (abs_d) + 1;
5809*404b540aSrobert     }
5810*404b540aSrobert   return 0;
5811*404b540aSrobert }
5812*404b540aSrobert 
5813*404b540aSrobert const char *
output_reload_inhi(rtx insn ATTRIBUTE_UNUSED,rtx * operands,int * len)5814*404b540aSrobert output_reload_inhi (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
5815*404b540aSrobert {
5816*404b540aSrobert   int tmp;
5817*404b540aSrobert   if (!len)
5818*404b540aSrobert     len = &tmp;
5819*404b540aSrobert 
5820*404b540aSrobert   if (GET_CODE (operands[1]) == CONST_INT)
5821*404b540aSrobert     {
5822*404b540aSrobert       int val = INTVAL (operands[1]);
5823*404b540aSrobert       if ((val & 0xff) == 0)
5824*404b540aSrobert 	{
5825*404b540aSrobert 	  *len = 3;
5826*404b540aSrobert 	  return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5827*404b540aSrobert 		  AS2 (ldi,%2,hi8(%1))       CR_TAB
5828*404b540aSrobert 		  AS2 (mov,%B0,%2));
5829*404b540aSrobert 	}
5830*404b540aSrobert       else if ((val & 0xff00) == 0)
5831*404b540aSrobert 	{
5832*404b540aSrobert 	  *len = 3;
5833*404b540aSrobert 	  return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5834*404b540aSrobert 		  AS2 (mov,%A0,%2)     CR_TAB
5835*404b540aSrobert 		  AS2 (mov,%B0,__zero_reg__));
5836*404b540aSrobert 	}
5837*404b540aSrobert       else if ((val & 0xff) == ((val & 0xff00) >> 8))
5838*404b540aSrobert 	{
5839*404b540aSrobert 	  *len = 3;
5840*404b540aSrobert 	  return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5841*404b540aSrobert 		  AS2 (mov,%A0,%2)     CR_TAB
5842*404b540aSrobert 		  AS2 (mov,%B0,%2));
5843*404b540aSrobert 	}
5844*404b540aSrobert     }
5845*404b540aSrobert   *len = 4;
5846*404b540aSrobert   return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5847*404b540aSrobert 	  AS2 (mov,%A0,%2)     CR_TAB
5848*404b540aSrobert 	  AS2 (ldi,%2,hi8(%1)) CR_TAB
5849*404b540aSrobert 	  AS2 (mov,%B0,%2));
5850*404b540aSrobert }
5851*404b540aSrobert 
5852*404b540aSrobert 
5853*404b540aSrobert const char *
output_reload_insisf(rtx insn ATTRIBUTE_UNUSED,rtx * operands,int * len)5854*404b540aSrobert output_reload_insisf (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
5855*404b540aSrobert {
5856*404b540aSrobert   rtx src = operands[1];
5857*404b540aSrobert   int cnst = (GET_CODE (src) == CONST_INT);
5858*404b540aSrobert 
5859*404b540aSrobert   if (len)
5860*404b540aSrobert     {
5861*404b540aSrobert       if (cnst)
5862*404b540aSrobert 	*len = 4 + ((INTVAL (src) & 0xff) != 0)
5863*404b540aSrobert 		+ ((INTVAL (src) & 0xff00) != 0)
5864*404b540aSrobert 		+ ((INTVAL (src) & 0xff0000) != 0)
5865*404b540aSrobert 		+ ((INTVAL (src) & 0xff000000) != 0);
5866*404b540aSrobert       else
5867*404b540aSrobert 	*len = 8;
5868*404b540aSrobert 
5869*404b540aSrobert       return "";
5870*404b540aSrobert     }
5871*404b540aSrobert 
5872*404b540aSrobert   if (cnst && ((INTVAL (src) & 0xff) == 0))
5873*404b540aSrobert     output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5874*404b540aSrobert   else
5875*404b540aSrobert     {
5876*404b540aSrobert       output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
5877*404b540aSrobert       output_asm_insn (AS2 (mov, %A0, %2), operands);
5878*404b540aSrobert     }
5879*404b540aSrobert   if (cnst && ((INTVAL (src) & 0xff00) == 0))
5880*404b540aSrobert     output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
5881*404b540aSrobert   else
5882*404b540aSrobert     {
5883*404b540aSrobert       output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
5884*404b540aSrobert       output_asm_insn (AS2 (mov, %B0, %2), operands);
5885*404b540aSrobert     }
5886*404b540aSrobert   if (cnst && ((INTVAL (src) & 0xff0000) == 0))
5887*404b540aSrobert     output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
5888*404b540aSrobert   else
5889*404b540aSrobert     {
5890*404b540aSrobert       output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
5891*404b540aSrobert       output_asm_insn (AS2 (mov, %C0, %2), operands);
5892*404b540aSrobert     }
5893*404b540aSrobert   if (cnst && ((INTVAL (src) & 0xff000000) == 0))
5894*404b540aSrobert     output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
5895*404b540aSrobert   else
5896*404b540aSrobert     {
5897*404b540aSrobert       output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5898*404b540aSrobert       output_asm_insn (AS2 (mov, %D0, %2), operands);
5899*404b540aSrobert     }
5900*404b540aSrobert   return "";
5901*404b540aSrobert }
5902*404b540aSrobert 
5903*404b540aSrobert void
avr_output_bld(rtx operands[],int bit_nr)5904*404b540aSrobert avr_output_bld (rtx operands[], int bit_nr)
5905*404b540aSrobert {
5906*404b540aSrobert   static char s[] = "bld %A0,0";
5907*404b540aSrobert 
5908*404b540aSrobert   s[5] = 'A' + (bit_nr >> 3);
5909*404b540aSrobert   s[8] = '0' + (bit_nr & 7);
5910*404b540aSrobert   output_asm_insn (s, operands);
5911*404b540aSrobert }
5912*404b540aSrobert 
5913*404b540aSrobert void
avr_output_addr_vec_elt(FILE * stream,int value)5914*404b540aSrobert avr_output_addr_vec_elt (FILE *stream, int value)
5915*404b540aSrobert {
5916*404b540aSrobert   switch_to_section (progmem_section);
5917*404b540aSrobert   if (AVR_MEGA)
5918*404b540aSrobert     fprintf (stream, "\t.word pm(.L%d)\n", value);
5919*404b540aSrobert   else
5920*404b540aSrobert     fprintf (stream, "\trjmp .L%d\n", value);
5921*404b540aSrobert 
5922*404b540aSrobert   jump_tables_size++;
5923*404b540aSrobert }
5924*404b540aSrobert 
5925*404b540aSrobert /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5926*404b540aSrobert    registers (for a define_peephole2) in the current function.  */
5927*404b540aSrobert 
5928*404b540aSrobert int
avr_peep2_scratch_safe(rtx scratch)5929*404b540aSrobert avr_peep2_scratch_safe (rtx scratch)
5930*404b540aSrobert {
5931*404b540aSrobert   if ((interrupt_function_p (current_function_decl)
5932*404b540aSrobert        || signal_function_p (current_function_decl))
5933*404b540aSrobert       && leaf_function_p ())
5934*404b540aSrobert     {
5935*404b540aSrobert       int first_reg = true_regnum (scratch);
5936*404b540aSrobert       int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
5937*404b540aSrobert       int reg;
5938*404b540aSrobert 
5939*404b540aSrobert       for (reg = first_reg; reg <= last_reg; reg++)
5940*404b540aSrobert 	{
5941*404b540aSrobert 	  if (!regs_ever_live[reg])
5942*404b540aSrobert 	    return 0;
5943*404b540aSrobert 	}
5944*404b540aSrobert     }
5945*404b540aSrobert   return 1;
5946*404b540aSrobert }
5947*404b540aSrobert 
5948*404b540aSrobert /* Output a branch that tests a single bit of a register (QI, HI or SImode)
5949*404b540aSrobert    or memory location in the I/O space (QImode only).
5950*404b540aSrobert 
5951*404b540aSrobert    Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5952*404b540aSrobert    Operand 1: register operand to test, or CONST_INT memory address.
5953*404b540aSrobert    Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5954*404b540aSrobert    Operand 3: label to jump to if the test is true.  */
5955*404b540aSrobert 
5956*404b540aSrobert const char *
avr_out_sbxx_branch(rtx insn,rtx operands[])5957*404b540aSrobert avr_out_sbxx_branch (rtx insn, rtx operands[])
5958*404b540aSrobert {
5959*404b540aSrobert   enum rtx_code comp = GET_CODE (operands[0]);
5960*404b540aSrobert   int long_jump = (get_attr_length (insn) >= 4);
5961*404b540aSrobert   int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
5962*404b540aSrobert 
5963*404b540aSrobert   if (comp == GE)
5964*404b540aSrobert     comp = EQ;
5965*404b540aSrobert   else if (comp == LT)
5966*404b540aSrobert     comp = NE;
5967*404b540aSrobert 
5968*404b540aSrobert   if (reverse)
5969*404b540aSrobert     comp = reverse_condition (comp);
5970*404b540aSrobert 
5971*404b540aSrobert   if (GET_CODE (operands[1]) == CONST_INT)
5972*404b540aSrobert     {
5973*404b540aSrobert       if (INTVAL (operands[1]) < 0x40)
5974*404b540aSrobert 	{
5975*404b540aSrobert 	  if (comp == EQ)
5976*404b540aSrobert 	    output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
5977*404b540aSrobert 	  else
5978*404b540aSrobert 	    output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
5979*404b540aSrobert 	}
5980*404b540aSrobert       else
5981*404b540aSrobert 	{
5982*404b540aSrobert 	  output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
5983*404b540aSrobert 	  if (comp == EQ)
5984*404b540aSrobert 	    output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
5985*404b540aSrobert 	  else
5986*404b540aSrobert 	    output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
5987*404b540aSrobert 	}
5988*404b540aSrobert     }
5989*404b540aSrobert   else  /* GET_CODE (operands[1]) == REG */
5990*404b540aSrobert     {
5991*404b540aSrobert       if (GET_MODE (operands[1]) == QImode)
5992*404b540aSrobert 	{
5993*404b540aSrobert 	  if (comp == EQ)
5994*404b540aSrobert 	    output_asm_insn (AS2 (sbrs,%1,%2), operands);
5995*404b540aSrobert 	  else
5996*404b540aSrobert 	    output_asm_insn (AS2 (sbrc,%1,%2), operands);
5997*404b540aSrobert 	}
5998*404b540aSrobert       else  /* HImode or SImode */
5999*404b540aSrobert 	{
6000*404b540aSrobert 	  static char buf[] = "sbrc %A1,0";
6001*404b540aSrobert 	  int bit_nr = exact_log2 (INTVAL (operands[2])
6002*404b540aSrobert 				   & GET_MODE_MASK (GET_MODE (operands[1])));
6003*404b540aSrobert 
6004*404b540aSrobert 	  buf[3] = (comp == EQ) ? 's' : 'c';
6005*404b540aSrobert 	  buf[6] = 'A' + (bit_nr >> 3);
6006*404b540aSrobert 	  buf[9] = '0' + (bit_nr & 7);
6007*404b540aSrobert 	  output_asm_insn (buf, operands);
6008*404b540aSrobert 	}
6009*404b540aSrobert     }
6010*404b540aSrobert 
6011*404b540aSrobert   if (long_jump)
6012*404b540aSrobert     return (AS1 (rjmp,.+4) CR_TAB
6013*404b540aSrobert 	    AS1 (jmp,%3));
6014*404b540aSrobert   if (!reverse)
6015*404b540aSrobert     return AS1 (rjmp,%3);
6016*404b540aSrobert   return "";
6017*404b540aSrobert }
6018*404b540aSrobert 
6019*404b540aSrobert /* Worker function for TARGET_ASM_CONSTRUCTOR.  */
6020*404b540aSrobert 
6021*404b540aSrobert static void
avr_asm_out_ctor(rtx symbol,int priority)6022*404b540aSrobert avr_asm_out_ctor (rtx symbol, int priority)
6023*404b540aSrobert {
6024*404b540aSrobert   fputs ("\t.global __do_global_ctors\n", asm_out_file);
6025*404b540aSrobert   default_ctor_section_asm_out_constructor (symbol, priority);
6026*404b540aSrobert }
6027*404b540aSrobert 
6028*404b540aSrobert /* Worker function for TARGET_ASM_DESTRUCTOR.  */
6029*404b540aSrobert 
6030*404b540aSrobert static void
avr_asm_out_dtor(rtx symbol,int priority)6031*404b540aSrobert avr_asm_out_dtor (rtx symbol, int priority)
6032*404b540aSrobert {
6033*404b540aSrobert   fputs ("\t.global __do_global_dtors\n", asm_out_file);
6034*404b540aSrobert   default_dtor_section_asm_out_destructor (symbol, priority);
6035*404b540aSrobert }
6036*404b540aSrobert 
6037*404b540aSrobert /* Worker function for TARGET_RETURN_IN_MEMORY.  */
6038*404b540aSrobert 
6039*404b540aSrobert static bool
avr_return_in_memory(tree type,tree fntype ATTRIBUTE_UNUSED)6040*404b540aSrobert avr_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
6041*404b540aSrobert {
6042*404b540aSrobert   if (TYPE_MODE (type) == BLKmode)
6043*404b540aSrobert     {
6044*404b540aSrobert       HOST_WIDE_INT size = int_size_in_bytes (type);
6045*404b540aSrobert       return (size == -1 || size > 8);
6046*404b540aSrobert     }
6047*404b540aSrobert   else
6048*404b540aSrobert     return false;
6049*404b540aSrobert }
6050*404b540aSrobert 
6051*404b540aSrobert #include "gt-avr.h"
6052