OSDN Git Service

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