OSDN Git Service

Make -fdata-sections work for AVR port.
[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
3    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 2, 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 COPYING.  If not, write to
20    the Free Software Foundation, 59 Temple Place - Suite 330,
21    Boston, MA 02111-1307, USA.  */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "rtl.h"
28 #include "regs.h"
29 #include "hard-reg-set.h"
30 #include "real.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-attr.h"
34 #include "flags.h"
35 #include "reload.h"
36 #include "tree.h"
37 #include "output.h"
38 #include "expr.h"
39 #include "toplev.h"
40 #include "obstack.h"
41 #include "function.h"
42 #include "recog.h"
43 #include "ggc.h"
44 #include "tm_p.h"
45 #include "target.h"
46 #include "target-def.h"
47
48 /* Maximal allowed offset for an address in the LD command */
49 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
50
51 static int avr_naked_function_p (tree);
52 static int interrupt_function_p (tree);
53 static int signal_function_p (tree);
54 static int avr_regs_to_save (HARD_REG_SET *);
55 static int sequent_regs_live (void);
56 static const char *ptrreg_to_str (int);
57 static const char *cond_string (enum rtx_code);
58 static int avr_num_arg_regs (enum machine_mode, tree);
59 static int out_adj_frame_ptr (FILE *, int);
60 static int out_set_stack_ptr (FILE *, int, int);
61 static RTX_CODE compare_condition (rtx insn);
62 static int compare_sign_p (rtx insn);
63 static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *);
64 static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
65 const struct attribute_spec avr_attribute_table[];
66 static bool avr_assemble_integer (rtx, unsigned int, int);
67 static void avr_file_start (void);
68 static void avr_file_end (void);
69 static void avr_output_function_prologue (FILE *, HOST_WIDE_INT);
70 static void avr_output_function_epilogue (FILE *, HOST_WIDE_INT);
71 static void avr_insert_attributes (tree, tree *);
72 static unsigned int avr_section_type_flags (tree, const char *, int);
73
74 static void avr_reorg (void);
75 static void avr_asm_out_ctor (rtx, int);
76 static void avr_asm_out_dtor (rtx, int);
77 static int default_rtx_costs (rtx, enum rtx_code, enum rtx_code);
78 static bool avr_rtx_costs (rtx, int, int, int *);
79 static int avr_address_cost (rtx);
80 static bool avr_return_in_memory (tree, tree);
81
82 /* Allocate registers from r25 to r8 for parameters for function calls.  */
83 #define FIRST_CUM_REG 26
84
85 /* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */
86 static GTY(()) rtx tmp_reg_rtx;
87
88 /* Zeroed register RTX (gen_rtx_REG (QImode, ZERO_REGNO)) */
89 static GTY(()) rtx zero_reg_rtx;
90
91 /* AVR register names {"r0", "r1", ..., "r31"} */
92 static const char *const avr_regnames[] = REGISTER_NAMES;
93
94 /* This holds the last insn address.  */
95 static int last_insn_address = 0;
96
97 /* Commands count in the compiled file */
98 static int commands_in_file;
99
100 /* Commands in the functions prologues in the compiled file */
101 static int commands_in_prologues;
102
103 /* Commands in the functions epilogues in the compiled file */
104 static int commands_in_epilogues;
105
106 /* Prologue/Epilogue size in words */
107 static int prologue_size;
108 static int epilogue_size;
109
110 /* Size of all jump tables in the current function, in words.  */
111 static int jump_tables_size;
112
113 /* Initial stack value specified by the `-minit-stack=' option */
114 const char *avr_init_stack = "__stack";
115
116 /* Default MCU name */
117 const char *avr_mcu_name = "avr2";
118
119 /* Preprocessor macros to define depending on MCU type.  */
120 const char *avr_base_arch_macro;
121 const char *avr_extra_arch_macro;
122
123 /* More than 8K of program memory: use "call" and "jmp".  */
124 int avr_mega_p = 0;
125
126 /* Enhanced core: use "movw", "mul", ...  */
127 int avr_enhanced_p = 0;
128
129 /* Assembler only.  */
130 int avr_asm_only_p = 0;
131
132 struct base_arch_s {
133   int asm_only;
134   int enhanced;
135   int mega;
136   const char *const macro;
137 };
138
139 static const struct base_arch_s avr_arch_types[] = {
140   { 1, 0, 0, NULL },  /* unknown device specified */
141   { 1, 0, 0, "__AVR_ARCH__=1" },
142   { 0, 0, 0, "__AVR_ARCH__=2" },
143   { 0, 0, 1, "__AVR_ARCH__=3" },
144   { 0, 1, 0, "__AVR_ARCH__=4" },
145   { 0, 1, 1, "__AVR_ARCH__=5" }
146 };
147
148 struct mcu_type_s {
149   const char *const name;
150   int arch;  /* index in avr_arch_types[] */
151   /* Must lie outside user's namespace.  NULL == no macro.  */
152   const char *const macro;
153 };
154
155 /* List of all known AVR MCU types - if updated, it has to be kept
156    in sync in several places (FIXME: is there a better way?):
157     - here
158     - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
159     - t-avr (MULTILIB_MATCHES)
160     - gas/config/tc-avr.c
161     - avr-libc  */
162
163 static const struct mcu_type_s avr_mcu_types[] = {
164     /* Classic, <= 8K.  */
165   { "avr2",      2, NULL },
166   { "at90s2313", 2, "__AVR_AT90S2313__" },
167   { "at90s2323", 2, "__AVR_AT90S2323__" },
168   { "at90s2333", 2, "__AVR_AT90S2333__" },
169   { "at90s2343", 2, "__AVR_AT90S2343__" },
170   { "attiny22",  2, "__AVR_ATtiny22__" },
171   { "attiny26",  2, "__AVR_ATtiny26__" },
172   { "at90s4414", 2, "__AVR_AT90S4414__" },
173   { "at90s4433", 2, "__AVR_AT90S4433__" },
174   { "at90s4434", 2, "__AVR_AT90S4434__" },
175   { "at90s8515", 2, "__AVR_AT90S8515__" },
176   { "at90c8534", 2, "__AVR_AT90C8534__" },
177   { "at90s8535", 2, "__AVR_AT90S8535__" },
178   { "at86rf401", 2, "__AVR_AT86RF401__" },
179     /* Classic, > 8K.  */
180   { "avr3",      3, NULL },
181   { "atmega103", 3, "__AVR_ATmega103__" },
182   { "atmega603", 3, "__AVR_ATmega603__" },
183   { "at43usb320", 3, "__AVR_AT43USB320__" },
184   { "at43usb355", 3, "__AVR_AT43USB355__" },
185   { "at76c711",  3, "__AVR_AT76C711__" },
186     /* Enhanced, <= 8K.  */
187   { "avr4",      4, NULL },
188   { "atmega8",   4, "__AVR_ATmega8__" },
189   { "atmega8515", 4, "__AVR_ATmega8515__" },
190   { "atmega8535", 4, "__AVR_ATmega8535__" },
191     /* Enhanced, > 8K.  */
192   { "avr5",      5, NULL },
193   { "atmega16",  5, "__AVR_ATmega16__" },
194   { "atmega161", 5, "__AVR_ATmega161__" },
195   { "atmega162", 5, "__AVR_ATmega162__" },
196   { "atmega163", 5, "__AVR_ATmega163__" },
197   { "atmega169", 5, "__AVR_ATmega169__" },
198   { "atmega32",  5, "__AVR_ATmega32__" },
199   { "atmega323", 5, "__AVR_ATmega323__" },
200   { "atmega64",  5, "__AVR_ATmega64__" },
201   { "atmega128", 5, "__AVR_ATmega128__" },
202   { "at94k",     5, "__AVR_AT94K__" },
203     /* Assembler only.  */
204   { "avr1",      1, NULL },
205   { "at90s1200", 1, "__AVR_AT90S1200__" },
206   { "attiny11",  1, "__AVR_ATtiny11__" },
207   { "attiny12",  1, "__AVR_ATtiny12__" },
208   { "attiny15",  1, "__AVR_ATtiny15__" },
209   { "attiny28",  1, "__AVR_ATtiny28__" },
210   { NULL,        0, NULL }
211 };
212
213 int avr_case_values_threshold = 30000;
214 \f
215 /* Initialize the GCC target structure.  */
216 #undef TARGET_ASM_ALIGNED_HI_OP
217 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
218 #undef TARGET_ASM_INTEGER
219 #define TARGET_ASM_INTEGER avr_assemble_integer
220 #undef TARGET_ASM_FILE_START
221 #define TARGET_ASM_FILE_START avr_file_start
222 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
223 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
224 #undef TARGET_ASM_FILE_END
225 #define TARGET_ASM_FILE_END avr_file_end
226
227 #undef TARGET_ASM_FUNCTION_PROLOGUE
228 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
229 #undef TARGET_ASM_FUNCTION_EPILOGUE
230 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
231 #undef TARGET_ATTRIBUTE_TABLE
232 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
233 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
234 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
235 #undef TARGET_INSERT_ATTRIBUTES
236 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
237 #undef TARGET_SECTION_TYPE_FLAGS
238 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
239 #undef TARGET_RTX_COSTS
240 #define TARGET_RTX_COSTS avr_rtx_costs
241 #undef TARGET_ADDRESS_COST
242 #define TARGET_ADDRESS_COST avr_address_cost
243 #undef TARGET_MACHINE_DEPENDENT_REORG
244 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
245
246 #undef TARGET_RETURN_IN_MEMORY
247 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
248
249 #undef TARGET_STRICT_ARGUMENT_NAMING
250 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
251
252 struct gcc_target targetm = TARGET_INITIALIZER;
253 \f
254 void
255 avr_override_options (void)
256 {
257   const struct mcu_type_s *t;
258   const struct base_arch_s *base;
259
260   for (t = avr_mcu_types; t->name; t++)
261     if (strcmp (t->name, avr_mcu_name) == 0)
262       break;
263
264   if (!t->name)
265     {
266       fprintf (stderr, "unknown MCU `%s' specified\nKnown MCU names:\n",
267                avr_mcu_name);
268       for (t = avr_mcu_types; t->name; t++)
269         fprintf (stderr,"   %s\n", t->name);
270     }
271
272   base = &avr_arch_types[t->arch];
273   avr_asm_only_p = base->asm_only;
274   avr_enhanced_p = base->enhanced;
275   avr_mega_p = base->mega;
276   avr_base_arch_macro = base->macro;
277   avr_extra_arch_macro = t->macro;
278
279   if (optimize && !TARGET_NO_TABLEJUMP)
280     avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
281
282   tmp_reg_rtx  = gen_rtx_REG (QImode, TMP_REGNO);
283   zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO);
284 }
285
286 /*  return register class from register number.  */
287
288 static const int reg_class_tab[]={
289   GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
290   GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
291   GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
292   GENERAL_REGS, /* r0 - r15 */
293   LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
294   LD_REGS,                      /* r16 - 23 */
295   ADDW_REGS,ADDW_REGS,          /* r24,r25 */
296   POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
297   POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
298   POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
299   STACK_REG,STACK_REG           /* SPL,SPH */
300 };
301
302 /* Return register class for register R.  */
303
304 enum reg_class
305 avr_regno_reg_class (int r)
306 {
307   if (r <= 33)
308     return reg_class_tab[r];
309   return ALL_REGS;
310 }
311
312
313 /* A C expression which defines the machine-dependent operand
314    constraint letters for register classes.  If C is such a
315    letter, the value should be the register class corresponding to
316    it.  Otherwise, the value should be `NO_REGS'.  The register
317    letter `r', corresponding to class `GENERAL_REGS', will not be
318    passed to this macro; you do not need to handle it.  */
319
320 enum reg_class
321 avr_reg_class_from_letter  (int c)
322 {
323   switch (c)
324     {
325     case 't' : return R0_REG;
326     case 'b' : return BASE_POINTER_REGS;
327     case 'e' : return POINTER_REGS;
328     case 'w' : return ADDW_REGS;
329     case 'd' : return LD_REGS;
330     case 'l' : return NO_LD_REGS;
331     case 'a' : return SIMPLE_LD_REGS;
332     case 'x' : return POINTER_X_REGS;
333     case 'y' : return POINTER_Y_REGS;
334     case 'z' : return POINTER_Z_REGS;
335     case 'q' : return STACK_REG;
336     default: break;
337     }
338   return NO_REGS;
339 }
340
341 /* Return nonzero if FUNC is a naked function.  */
342
343 static int
344 avr_naked_function_p (tree func)
345 {
346   tree a;
347
348   if (TREE_CODE (func) != FUNCTION_DECL)
349     abort ();
350   
351   a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
352   return a != NULL_TREE;
353 }
354
355 /* Return nonzero if FUNC is an interrupt function as specified
356    by the "interrupt" attribute.  */
357
358 static int
359 interrupt_function_p (tree func)
360 {
361   tree a;
362
363   if (TREE_CODE (func) != FUNCTION_DECL)
364     return 0;
365
366   a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
367   return a != NULL_TREE;
368 }
369
370 /* Return nonzero if FUNC is a signal function as specified
371    by the "signal" attribute.  */
372
373 static int
374 signal_function_p (tree func)
375 {
376   tree a;
377
378   if (TREE_CODE (func) != FUNCTION_DECL)
379     return 0;
380
381   a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
382   return a != NULL_TREE;
383 }
384
385 /* Return the number of hard registers to push/pop in the prologue/epilogue
386    of the current function, and optionally store these registers in SET.  */
387
388 static int
389 avr_regs_to_save (HARD_REG_SET *set)
390 {
391   int reg, count;
392   int int_or_sig_p = (interrupt_function_p (current_function_decl)
393                       || signal_function_p (current_function_decl));
394   int leaf_func_p = leaf_function_p ();
395
396   if (set)
397     CLEAR_HARD_REG_SET (*set);
398   count = 0;
399
400   /* No need to save any registers if the function never returns.  */
401   if (TREE_THIS_VOLATILE (current_function_decl))
402     return 0;
403
404   for (reg = 0; reg < 32; reg++)
405     {
406       /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
407          any global register variables.  */
408       if (fixed_regs[reg])
409         continue;
410
411       if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
412           || (regs_ever_live[reg]
413               && (int_or_sig_p || !call_used_regs[reg])
414               && !(frame_pointer_needed
415                    && (reg == REG_Y || reg == (REG_Y+1)))))
416         {
417           if (set)
418             SET_HARD_REG_BIT (*set, reg);
419           count++;
420         }
421     }
422   return count;
423 }
424
425 /* Compute offset between arg_pointer and frame_pointer.  */
426
427 int
428 initial_elimination_offset (int from, int to)
429 {
430   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
431     return 0;
432   else
433     {
434       int offset = frame_pointer_needed ? 2 : 0;
435
436       offset += avr_regs_to_save (NULL);
437       return get_frame_size () + 2 + 1 + offset;
438     }
439 }
440
441 /* Return 1 if the function epilogue is just a single "ret".  */
442
443 int
444 avr_simple_epilogue (void)
445 {
446   return (! frame_pointer_needed
447           && get_frame_size () == 0
448           && avr_regs_to_save (NULL) == 0
449           && ! interrupt_function_p (current_function_decl)
450           && ! signal_function_p (current_function_decl)
451           && ! avr_naked_function_p (current_function_decl)
452           && ! MAIN_NAME_P (DECL_NAME (current_function_decl))
453           && ! TREE_THIS_VOLATILE (current_function_decl));
454 }
455
456 /* This function checks sequence of live registers.  */
457
458 static int
459 sequent_regs_live (void)
460 {
461   int reg;
462   int live_seq=0;
463   int cur_seq=0;
464
465   for (reg = 0; reg < 18; ++reg)
466     {
467       if (!call_used_regs[reg])
468         {
469           if (regs_ever_live[reg])
470             {
471               ++live_seq;
472               ++cur_seq;
473             }
474           else
475             cur_seq = 0;
476         }
477     }
478
479   if (!frame_pointer_needed)
480     {
481       if (regs_ever_live[REG_Y])
482         {
483           ++live_seq;
484           ++cur_seq;
485         }
486       else
487         cur_seq = 0;
488
489       if (regs_ever_live[REG_Y+1])
490         {
491           ++live_seq;
492           ++cur_seq;
493         }
494       else
495         cur_seq = 0;
496     }
497   else
498     {
499       cur_seq += 2;
500       live_seq += 2;
501     }
502   return (cur_seq == live_seq) ? live_seq : 0;
503 }
504
505
506 /* Output to FILE the asm instructions to adjust the frame pointer by
507    ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
508    (epilogue).  Returns the number of instructions generated.  */
509
510 static int
511 out_adj_frame_ptr (FILE *file, int adj)
512 {
513   int size = 0;
514
515   if (adj)
516     {
517       if (TARGET_TINY_STACK)
518         {
519           if (adj < -63 || adj > 63)
520             warning ("large frame pointer change (%d) with -mtiny-stack", adj);
521
522           /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
523              over "sbiw" (2 cycles, same size).  */
524
525           fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
526           size++;
527         }
528       else if (adj < -63 || adj > 63)
529         {
530           fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
531                           AS2 (sbci, r29, hi8(%d)) CR_TAB),
532                    adj, adj);
533           size += 2;
534         }
535       else if (adj < 0)
536         {
537           fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
538           size++;
539         }
540       else
541         {
542           fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
543           size++;
544         }
545     }
546   return size;
547 }
548
549
550 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
551    handling various cases of interrupt enable flag state BEFORE and AFTER
552    (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
553    Returns the number of instructions generated.  */
554
555 static int
556 out_set_stack_ptr (FILE *file, int before, int after)
557 {
558   int do_sph, do_cli, do_save, do_sei, lock_sph, size;
559
560   /* The logic here is so that -mno-interrupts actually means
561      "it is safe to write SPH in one instruction, then SPL in the
562      next instruction, without disabling interrupts first".
563      The after != -1 case (interrupt/signal) is not affected.  */
564
565   do_sph = !TARGET_TINY_STACK;
566   lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
567   do_cli = (before != 0 && (after == 0 || lock_sph));
568   do_save = (do_cli && before == -1 && after == -1);
569   do_sei = ((do_cli || before != 1) && after == 1);
570   size = 1;
571
572   if (do_save)
573     {
574       fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
575       size++;
576     }
577
578   if (do_cli)
579     {
580       fprintf (file, "cli" CR_TAB);
581       size++;
582     }
583
584   /* Do SPH first - maybe this will disable interrupts for one instruction
585      someday (a suggestion has been sent to avr@atmel.com for consideration
586      in future devices - that would make -mno-interrupts always safe).  */
587   if (do_sph)
588     {
589       fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
590       size++;
591     }
592
593   /* Set/restore the I flag now - interrupts will be really enabled only
594      after the next instruction.  This is not clearly documented, but
595      believed to be true for all AVR devices.  */
596   if (do_save)
597     {
598       fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
599       size++;
600     }
601   else if (do_sei)
602     {
603       fprintf (file, "sei" CR_TAB);
604       size++;
605     }
606
607   fprintf (file, AS2 (out, __SP_L__, r28) "\n");
608
609   return size;
610 }
611
612
613 /* Output function prologue.  */
614
615 static void
616 avr_output_function_prologue (FILE *file, HOST_WIDE_INT size)
617 {
618   int reg;
619   int interrupt_func_p;
620   int signal_func_p;
621   int main_p;
622   int live_seq;
623   int minimize;
624
625   last_insn_address = 0;
626   jump_tables_size = 0;
627   prologue_size = 0;
628   fprintf (file, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n",
629            size);
630
631   if (avr_naked_function_p (current_function_decl))
632     {
633       fputs ("/* prologue: naked */\n", file);
634       goto out;
635     }
636
637   interrupt_func_p = interrupt_function_p (current_function_decl);
638   signal_func_p = signal_function_p (current_function_decl);
639   main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
640   live_seq = sequent_regs_live ();
641   minimize = (TARGET_CALL_PROLOGUES
642               && !interrupt_func_p && !signal_func_p && live_seq);
643
644   if (interrupt_func_p)
645     {
646       fprintf (file,"\tsei\n");
647       ++prologue_size;
648     }
649   if (interrupt_func_p || signal_func_p)
650     {
651       fprintf (file, "\t"
652                AS1 (push,__zero_reg__)   CR_TAB
653                AS1 (push,__tmp_reg__)    CR_TAB
654                AS2 (in,__tmp_reg__,__SREG__) CR_TAB
655                AS1 (push,__tmp_reg__)    CR_TAB
656                AS1 (clr,__zero_reg__)    "\n");
657       prologue_size += 5;
658     }
659   if (main_p)
660     {
661       fprintf (file, ("\t" 
662                       AS1 (ldi,r28) ",lo8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
663                       AS1 (ldi,r29) ",hi8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
664                       AS2 (out,__SP_H__,r29)     CR_TAB
665                       AS2 (out,__SP_L__,r28) "\n"),
666                avr_init_stack, size, avr_init_stack, size);
667       
668       prologue_size += 4;
669     }
670   else if (minimize && (frame_pointer_needed || live_seq > 6)) 
671     {
672       const char *cfun_name = current_function_name ();
673       fprintf (file, ("\t"
674                       AS1 (ldi, r26) ",lo8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
675                       AS1 (ldi, r27) ",hi8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB), size, size);
676
677       fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB
678                       AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB),
679                cfun_name, cfun_name);
680       
681       prologue_size += 4;
682       
683       if (AVR_MEGA)
684         {
685           fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
686                    (18 - live_seq) * 2);
687           prologue_size += 2;
688         }
689       else
690         {
691           fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
692                    (18 - live_seq) * 2);
693           ++prologue_size;
694         }
695       fprintf (file, ".L_%s_body:\n", cfun_name);
696     }
697   else
698     {
699       HARD_REG_SET set;
700
701       prologue_size += avr_regs_to_save (&set);
702       for (reg = 0; reg < 32; ++reg)
703         {
704           if (TEST_HARD_REG_BIT (set, reg))
705             {
706               fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
707             }
708         }
709       if (frame_pointer_needed)
710         {
711           fprintf (file, "\t"
712                    AS1 (push,r28) CR_TAB
713                    AS1 (push,r29) CR_TAB
714                    AS2 (in,r28,__SP_L__) CR_TAB
715                    AS2 (in,r29,__SP_H__) "\n");
716           prologue_size += 4;
717           if (size)
718             {
719               fputs ("\t", file);
720               prologue_size += out_adj_frame_ptr (file, size);
721
722               if (interrupt_func_p)
723                 {
724                   prologue_size += out_set_stack_ptr (file, 1, 1);
725                 }
726               else if (signal_func_p)
727                 {
728                   prologue_size += out_set_stack_ptr (file, 0, 0);
729                 }
730               else
731                 {
732                   prologue_size += out_set_stack_ptr (file, -1, -1);
733                 }
734             }
735         }
736     }
737
738  out:
739   fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
740 }
741
742 /* Output function epilogue.  */
743
744 static void
745 avr_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
746 {
747   int reg;
748   int interrupt_func_p;
749   int signal_func_p;
750   int main_p;
751   int function_size;
752   int live_seq;
753   int minimize;
754   rtx last = get_last_nonnote_insn ();
755
756   function_size = jump_tables_size;
757   if (last)
758     {
759       rtx first = get_first_nonnote_insn ();
760       function_size += (INSN_ADDRESSES (INSN_UID (last)) -
761                         INSN_ADDRESSES (INSN_UID (first)));
762       function_size += get_attr_length (last);
763     }
764
765   fprintf (file, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n", size);
766   epilogue_size = 0;
767
768   if (avr_naked_function_p (current_function_decl))
769     {
770       fputs ("/* epilogue: naked */\n", file);
771       goto out;
772     }
773
774   if (last && GET_CODE (last) == BARRIER)
775     {
776       fputs ("/* epilogue: noreturn */\n", file);
777       goto out;
778     }
779
780   interrupt_func_p = interrupt_function_p (current_function_decl);
781   signal_func_p = signal_function_p (current_function_decl);
782   main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
783   live_seq = sequent_regs_live ();
784   minimize = (TARGET_CALL_PROLOGUES
785               && !interrupt_func_p && !signal_func_p && live_seq);
786   
787   if (main_p)
788     {
789       /* Return value from main() is already in the correct registers
790          (r25:r24) as the exit() argument.  */
791       if (AVR_MEGA)
792         {
793           fputs ("\t" AS1 (jmp,exit) "\n", file);
794           epilogue_size += 2;
795         }
796       else
797         {
798           fputs ("\t" AS1 (rjmp,exit) "\n", file);
799           ++epilogue_size;
800         }
801     }
802   else if (minimize && (frame_pointer_needed || live_seq > 4))
803     {
804       fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
805       ++epilogue_size;
806       if (frame_pointer_needed)
807         {
808           epilogue_size += out_adj_frame_ptr (file, -size);
809         }
810       else
811         {
812           fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
813                           AS2 (in , r29, __SP_H__) CR_TAB));
814           epilogue_size += 2;
815         }
816       
817       if (AVR_MEGA)
818         {
819           fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
820                    (18 - live_seq) * 2);
821           epilogue_size += 2;
822         }
823       else
824         {
825           fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
826                    (18 - live_seq) * 2);
827           ++epilogue_size;
828         }
829     }
830   else
831     {
832       HARD_REG_SET set;
833
834       if (frame_pointer_needed)
835         {
836           if (size)
837             {
838               fputs ("\t", file);
839               epilogue_size += out_adj_frame_ptr (file, -size);
840
841               if (interrupt_func_p || signal_func_p)
842                 {
843                   epilogue_size += out_set_stack_ptr (file, -1, 0);
844                 }
845               else
846                 {
847                   epilogue_size += out_set_stack_ptr (file, -1, -1);
848                 }
849             }
850           fprintf (file, "\t"
851                    AS1 (pop,r29) CR_TAB
852                    AS1 (pop,r28) "\n");
853           epilogue_size += 2;
854         }
855
856       epilogue_size += avr_regs_to_save (&set);
857       for (reg = 31; reg >= 0; --reg)
858         {
859           if (TEST_HARD_REG_BIT (set, reg))
860             {
861               fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
862             }
863         }
864
865       if (interrupt_func_p || signal_func_p)
866         {
867           fprintf (file, "\t"
868                    AS1 (pop,__tmp_reg__)      CR_TAB
869                    AS2 (out,__SREG__,__tmp_reg__) CR_TAB
870                    AS1 (pop,__tmp_reg__)      CR_TAB
871                    AS1 (pop,__zero_reg__)     "\n");
872           epilogue_size += 4;
873           fprintf (file, "\treti\n");
874         }
875       else
876         fprintf (file, "\tret\n");
877       ++epilogue_size;
878     }
879
880  out:
881   fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
882   fprintf (file, "/* function %s size %d (%d) */\n", current_function_name (),
883            prologue_size + function_size + epilogue_size, function_size);
884   commands_in_file += prologue_size + function_size + epilogue_size;
885   commands_in_prologues += prologue_size;
886   commands_in_epilogues += epilogue_size;
887 }
888
889
890 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
891    machine for a memory operand of mode MODE.  */
892
893 int
894 legitimate_address_p (enum machine_mode mode, rtx x, int strict)
895 {
896   enum reg_class r = NO_REGS;
897   
898   if (TARGET_ALL_DEBUG)
899     {
900       fprintf (stderr, "mode: (%s) %s %s %s %s:",
901                GET_MODE_NAME(mode),
902                strict ? "(strict)": "",
903                reload_completed ? "(reload_completed)": "",
904                reload_in_progress ? "(reload_in_progress)": "",
905                reg_renumber ? "(reg_renumber)" : "");
906       if (GET_CODE (x) == PLUS
907           && REG_P (XEXP (x, 0))
908           && GET_CODE (XEXP (x, 1)) == CONST_INT
909           && INTVAL (XEXP (x, 1)) >= 0
910           && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
911           && reg_renumber
912           )
913         fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
914                  true_regnum (XEXP (x, 0)));
915       debug_rtx (x);
916     }
917   if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
918                     : REG_OK_FOR_BASE_NOSTRICT_P (x)))
919     r = POINTER_REGS;
920   else if (CONSTANT_ADDRESS_P (x))
921     r = ALL_REGS;
922   else if (GET_CODE (x) == PLUS
923            && REG_P (XEXP (x, 0))
924            && GET_CODE (XEXP (x, 1)) == CONST_INT
925            && INTVAL (XEXP (x, 1)) >= 0)
926     {
927       int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
928       if (fit)
929         {
930           if (! strict
931               || REGNO (XEXP (x,0)) == REG_Y
932               || REGNO (XEXP (x,0)) == REG_Z)
933             r = BASE_POINTER_REGS;
934           if (XEXP (x,0) == frame_pointer_rtx
935               || XEXP (x,0) == arg_pointer_rtx)
936             r = BASE_POINTER_REGS;
937         }
938       else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
939         r = POINTER_Y_REGS;
940     }
941   else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
942            && REG_P (XEXP (x, 0))
943            && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
944                : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
945     {
946       r = POINTER_REGS;
947     }
948   if (TARGET_ALL_DEBUG)
949     {
950       fprintf (stderr, "   ret = %c\n", r);
951     }
952   return r == NO_REGS ? 0 : (int)r;
953 }
954
955 /* Attempts to replace X with a valid
956    memory address for an operand of mode MODE  */
957
958 rtx
959 legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
960 {
961   x = oldx;
962   if (TARGET_ALL_DEBUG)
963     {
964       fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
965       debug_rtx (oldx);
966     }
967   
968   if (GET_CODE (oldx) == PLUS
969       && REG_P (XEXP (oldx,0)))
970     {
971       if (REG_P (XEXP (oldx,1)))
972         x = force_reg (GET_MODE (oldx), oldx);
973       else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
974         {
975           int offs = INTVAL (XEXP (oldx,1));
976           if (frame_pointer_rtx != XEXP (oldx,0))
977             if (offs > MAX_LD_OFFSET (mode))
978               {
979                 if (TARGET_ALL_DEBUG)
980                   fprintf (stderr, "force_reg (big offset)\n");
981                 x = force_reg (GET_MODE (oldx), oldx);
982               }
983         }
984     }
985   return x;
986 }
987
988
989 /* Return a pointer register name as a string.  */
990
991 static const char *
992 ptrreg_to_str (int regno)
993 {
994   switch (regno)
995     {
996     case REG_X: return "X";
997     case REG_Y: return "Y";
998     case REG_Z: return "Z";
999     default:
1000       abort ();
1001     }
1002   return NULL;
1003 }
1004
1005 /* Return the condition name as a string.
1006    Used in conditional jump constructing  */
1007
1008 static const char *
1009 cond_string (enum rtx_code code)
1010 {
1011   switch (code)
1012     {
1013     case NE:
1014       return "ne";
1015     case EQ:
1016       return "eq";
1017     case GE:
1018       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1019         return "pl";
1020       else
1021         return "ge";
1022     case LT:
1023       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1024         return "mi";
1025       else
1026         return "lt";
1027     case GEU:
1028       return "sh";
1029     case LTU:
1030       return "lo";
1031     default:
1032       abort ();
1033     }
1034 }
1035
1036 /* Output ADDR to FILE as address.  */
1037
1038 void
1039 print_operand_address (FILE *file, rtx addr)
1040 {
1041   switch (GET_CODE (addr))
1042     {
1043     case REG:
1044       fprintf (file, ptrreg_to_str (REGNO (addr)));
1045       break;
1046
1047     case PRE_DEC:
1048       fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1049       break;
1050
1051     case POST_INC:
1052       fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1053       break;
1054
1055     default:
1056       if (CONSTANT_ADDRESS_P (addr)
1057           && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
1058               || GET_CODE (addr) == LABEL_REF))
1059         {
1060           fprintf (file, "pm(");
1061           output_addr_const (file,addr);
1062           fprintf (file ,")");
1063         }
1064       else
1065         output_addr_const (file, addr);
1066     }
1067 }
1068
1069
1070 /* Output X as assembler operand to file FILE.  */
1071      
1072 void
1073 print_operand (FILE *file, rtx x, int code)
1074 {
1075   int abcd = 0;
1076
1077   if (code >= 'A' && code <= 'D')
1078     abcd = code - 'A';
1079
1080   if (code == '~')
1081     {
1082       if (!AVR_MEGA)
1083         fputc ('r', file);
1084     }
1085   else if (REG_P (x))
1086     {
1087       if (x == zero_reg_rtx)
1088         fprintf (file, "__zero_reg__");
1089       else
1090         fprintf (file, reg_names[true_regnum (x) + abcd]);
1091     }
1092   else if (GET_CODE (x) == CONST_INT)
1093     fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
1094   else if (GET_CODE (x) == MEM)
1095     {
1096       rtx addr = XEXP (x,0);
1097
1098       if (CONSTANT_P (addr) && abcd)
1099         {
1100           fputc ('(', file);
1101           output_address (addr);
1102           fprintf (file, ")+%d", abcd);
1103         }
1104       else if (code == 'o')
1105         {
1106           if (GET_CODE (addr) != PLUS)
1107             fatal_insn ("bad address, not (reg+disp):", addr);
1108
1109           print_operand (file, XEXP (addr, 1), 0);
1110         }
1111       else if (GET_CODE (addr) == PLUS)
1112         {
1113           print_operand_address (file, XEXP (addr,0));
1114           if (REGNO (XEXP (addr, 0)) == REG_X)
1115             fatal_insn ("internal compiler error.  Bad address:"
1116                         ,addr);
1117           fputc ('+', file);
1118           print_operand (file, XEXP (addr,1), code);
1119         }
1120       else
1121         print_operand_address (file, addr);
1122     }
1123   else if (GET_CODE (x) == CONST_DOUBLE)
1124     {
1125       long val;
1126       REAL_VALUE_TYPE rv;
1127       if (GET_MODE (x) != SFmode)
1128         fatal_insn ("internal compiler error.  Unknown mode:", x);
1129       REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1130       REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1131       fprintf (file, "0x%lx", val);
1132     }
1133   else if (code == 'j')
1134     fputs (cond_string (GET_CODE (x)), file);
1135   else if (code == 'k')
1136     fputs (cond_string (reverse_condition (GET_CODE (x))), file);
1137   else
1138     print_operand_address (file, x);
1139 }
1140
1141 /* Recognize operand OP of mode MODE used in call instructions.  */
1142
1143 int
1144 call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1145 {
1146   if (GET_CODE (op) == MEM)
1147     {
1148       rtx inside = XEXP (op, 0);
1149       if (register_operand (inside, Pmode))
1150         return 1;
1151       if (CONSTANT_ADDRESS_P (inside))
1152         return 1;
1153     }
1154   return 0;
1155 }
1156
1157 /* Update the condition code in the INSN.  */
1158
1159 void
1160 notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
1161 {
1162   rtx set;
1163   
1164   switch (get_attr_cc (insn))
1165     {
1166     case CC_NONE:
1167       /* Insn does not affect CC at all.  */
1168       break;
1169
1170     case CC_SET_N:
1171       CC_STATUS_INIT;
1172       break;
1173
1174     case CC_SET_ZN:
1175       set = single_set (insn);
1176       CC_STATUS_INIT;
1177       if (set)
1178         {
1179           cc_status.flags |= CC_NO_OVERFLOW;
1180           cc_status.value1 = SET_DEST (set);
1181         }
1182       break;
1183
1184     case CC_SET_CZN:
1185       /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1186          The V flag may or may not be known but that's ok because
1187          alter_cond will change tests to use EQ/NE.  */
1188       set = single_set (insn);
1189       CC_STATUS_INIT;
1190       if (set)
1191         {
1192           cc_status.value1 = SET_DEST (set);
1193           cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1194         }
1195       break;
1196
1197     case CC_COMPARE:
1198       set = single_set (insn);
1199       CC_STATUS_INIT;
1200       if (set)
1201         cc_status.value1 = SET_SRC (set);
1202       break;
1203       
1204     case CC_CLOBBER:
1205       /* Insn doesn't leave CC in a usable state.  */
1206       CC_STATUS_INIT;
1207
1208       /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1209       set = single_set (insn);
1210       if (set)
1211         {
1212           rtx src = SET_SRC (set);
1213           
1214           if (GET_CODE (src) == ASHIFTRT
1215               && GET_MODE (src) == QImode)
1216             {
1217               rtx x = XEXP (src, 1);
1218
1219               if (GET_CODE (x) == CONST_INT
1220                   && INTVAL (x) != 6)
1221                 {
1222                   cc_status.value1 = SET_DEST (set);
1223                   cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1224                 }
1225             }
1226         }
1227       break;
1228     }
1229 }
1230
1231 /* Return maximum number of consecutive registers of
1232    class CLASS needed to hold a value of mode MODE.  */
1233
1234 int
1235 class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,enum machine_mode mode)
1236 {
1237   return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1238 }
1239
1240 /* Choose mode for jump insn:
1241    1 - relative jump in range -63 <= x <= 62 ;
1242    2 - relative jump in range -2046 <= x <= 2045 ;
1243    3 - absolute jump (only for ATmega[16]03).  */
1244
1245 int
1246 avr_jump_mode (rtx x, rtx insn)
1247 {
1248   int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1249                                             ? XEXP (x, 0) : x));
1250   int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
1251   int jump_distance = cur_addr - dest_addr;
1252   
1253   if (-63 <= jump_distance && jump_distance <= 62)
1254     return 1;
1255   else if (-2046 <= jump_distance && jump_distance <= 2045)
1256     return 2;
1257   else if (AVR_MEGA)
1258     return 3;
1259   
1260   return 2;
1261 }
1262
1263 /* return an AVR condition jump commands.
1264    X is a comparison RTX.
1265    LEN is a number returned by avr_jump_mode function.
1266    if REVERSE nonzero then condition code in X must be reversed.  */
1267
1268 const char *
1269 ret_cond_branch (rtx x, int len, int reverse)
1270 {
1271   RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1272   
1273   switch (cond)
1274     {
1275     case GT:
1276       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1277         return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1278                             AS1 (brpl,%0)) :
1279                 len == 2 ? (AS1 (breq,.+4) CR_TAB
1280                             AS1 (brmi,.+2) CR_TAB
1281                             AS1 (rjmp,%0)) :
1282                 (AS1 (breq,.+6) CR_TAB
1283                  AS1 (brmi,.+4) CR_TAB
1284                  AS1 (jmp,%0)));
1285           
1286       else
1287         return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1288                             AS1 (brge,%0)) :
1289                 len == 2 ? (AS1 (breq,.+4) CR_TAB
1290                             AS1 (brlt,.+2) CR_TAB
1291                             AS1 (rjmp,%0)) :
1292                 (AS1 (breq,.+6) CR_TAB
1293                  AS1 (brlt,.+4) CR_TAB
1294                  AS1 (jmp,%0)));
1295     case GTU:
1296       return (len == 1 ? (AS1 (breq,.+2) CR_TAB
1297                           AS1 (brsh,%0)) :
1298               len == 2 ? (AS1 (breq,.+4) CR_TAB
1299                           AS1 (brlo,.+2) CR_TAB
1300                           AS1 (rjmp,%0)) :
1301               (AS1 (breq,.+6) CR_TAB
1302                AS1 (brlo,.+4) CR_TAB
1303                AS1 (jmp,%0)));
1304     case LE:
1305       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1306         return (len == 1 ? (AS1 (breq,%0) CR_TAB
1307                             AS1 (brmi,%0)) :
1308                 len == 2 ? (AS1 (breq,.+2) CR_TAB
1309                             AS1 (brpl,.+2) CR_TAB
1310                             AS1 (rjmp,%0)) :
1311                 (AS1 (breq,.+2) CR_TAB
1312                  AS1 (brpl,.+4) CR_TAB
1313                  AS1 (jmp,%0)));
1314       else
1315         return (len == 1 ? (AS1 (breq,%0) CR_TAB
1316                             AS1 (brlt,%0)) :
1317                 len == 2 ? (AS1 (breq,.+2) CR_TAB
1318                             AS1 (brge,.+2) CR_TAB
1319                             AS1 (rjmp,%0)) :
1320                 (AS1 (breq,.+2) CR_TAB
1321                  AS1 (brge,.+4) CR_TAB
1322                  AS1 (jmp,%0)));
1323     case LEU:
1324       return (len == 1 ? (AS1 (breq,%0) CR_TAB
1325                           AS1 (brlo,%0)) :
1326               len == 2 ? (AS1 (breq,.+2) CR_TAB
1327                           AS1 (brsh,.+2) CR_TAB
1328                           AS1 (rjmp,%0)) :
1329               (AS1 (breq,.+2) CR_TAB
1330                AS1 (brsh,.+4) CR_TAB
1331                AS1 (jmp,%0)));
1332     default:
1333       if (reverse)
1334         {
1335           switch (len)
1336             {
1337             case 1:
1338               return AS1 (br%k1,%0);
1339             case 2:
1340               return (AS1 (br%j1,.+2) CR_TAB
1341                       AS1 (rjmp,%0));
1342             default:
1343               return (AS1 (br%j1,.+4) CR_TAB
1344                       AS1 (jmp,%0));
1345             }
1346         }
1347         else
1348           {
1349             switch (len)
1350               {
1351               case 1:
1352                 return AS1 (br%j1,%0);
1353               case 2:
1354                 return (AS1 (br%k1,.+2) CR_TAB
1355                         AS1 (rjmp,%0));
1356               default:
1357                 return (AS1 (br%k1,.+4) CR_TAB
1358                         AS1 (jmp,%0));
1359               }
1360           }
1361     }
1362   return "";
1363 }
1364
1365 /* Predicate function for immediate operand which fits to byte (8bit) */
1366
1367 int
1368 byte_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1369 {
1370   return (GET_CODE (op) == CONST_INT
1371           && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1372 }
1373
1374 /* Output all insn addresses and their sizes into the assembly language
1375    output file.  This is helpful for debugging whether the length attributes
1376    in the md file are correct.
1377    Output insn cost for next insn.  */
1378
1379 void
1380 final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
1381                     int num_operands ATTRIBUTE_UNUSED)
1382 {
1383   int uid = INSN_UID (insn);
1384
1385   if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1386     {
1387       fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1388                INSN_ADDRESSES (uid),
1389                INSN_ADDRESSES (uid) - last_insn_address,
1390                rtx_cost (PATTERN (insn), INSN));
1391     }
1392   last_insn_address = INSN_ADDRESSES (uid);
1393 }
1394
1395 /* Return 0 if undefined, 1 if always true or always false.  */
1396
1397 int
1398 avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE operator, rtx x)
1399 {
1400   unsigned int max = (mode == QImode ? 0xff :
1401                       mode == HImode ? 0xffff :
1402                       mode == SImode ? 0xffffffff : 0);
1403   if (max && operator && GET_CODE (x) == CONST_INT)
1404     {
1405       if (unsigned_condition (operator) != operator)
1406         max >>= 1;
1407
1408       if (max != (INTVAL (x) & max)
1409           && INTVAL (x) != 0xff)
1410         return 1;
1411     }
1412   return 0;
1413 }
1414
1415
1416 /* Returns nonzero if REGNO is the number of a hard
1417    register in which function arguments are sometimes passed.  */
1418
1419 int
1420 function_arg_regno_p(int r)
1421 {
1422   return (r >= 8 && r <= 25);
1423 }
1424
1425 /* Initializing the variable cum for the state at the beginning
1426    of the argument list.  */
1427
1428 void
1429 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
1430                       tree fndecl ATTRIBUTE_UNUSED)
1431 {
1432   cum->nregs = 18;
1433   cum->regno = FIRST_CUM_REG;
1434   if (!libname && fntype)
1435     {
1436       int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1437                     && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1438                         != void_type_node));
1439       if (stdarg)
1440         cum->nregs = 0;
1441     }
1442 }
1443
1444 /* Returns the number of registers to allocate for a function argument.  */
1445
1446 static int
1447 avr_num_arg_regs (enum machine_mode mode, tree type)
1448 {
1449   int size;
1450
1451   if (mode == BLKmode)
1452     size = int_size_in_bytes (type);
1453   else
1454     size = GET_MODE_SIZE (mode);
1455
1456   /* Align all function arguments to start in even-numbered registers.
1457      Odd-sized arguments leave holes above them.  */
1458
1459   return (size + 1) & ~1;
1460 }
1461
1462 /* Controls whether a function argument is passed
1463    in a register, and which register.  */
1464
1465 rtx
1466 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1467               int named ATTRIBUTE_UNUSED)
1468 {
1469   int bytes = avr_num_arg_regs (mode, type);
1470
1471   if (cum->nregs && bytes <= cum->nregs)
1472     return gen_rtx_REG (mode, cum->regno - bytes);
1473
1474   return NULL_RTX;
1475 }
1476
1477 /* Update the summarizer variable CUM to advance past an argument
1478    in the argument list.  */
1479    
1480 void
1481 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1482                       int named ATTRIBUTE_UNUSED)
1483 {
1484   int bytes = avr_num_arg_regs (mode, type);
1485
1486   cum->nregs -= bytes;
1487   cum->regno -= bytes;
1488
1489   if (cum->nregs <= 0)
1490     {
1491       cum->nregs = 0;
1492       cum->regno = FIRST_CUM_REG;
1493     }
1494 }
1495
1496 /***********************************************************************
1497   Functions for outputting various mov's for a various modes
1498 ************************************************************************/
1499 const char *
1500 output_movqi (rtx insn, rtx operands[], int *l)
1501 {
1502   int dummy;
1503   rtx dest = operands[0];
1504   rtx src = operands[1];
1505   int *real_l = l;
1506   
1507   if (!l)
1508     l = &dummy;
1509
1510   *l = 1;
1511   
1512   if (register_operand (dest, QImode))
1513     {
1514       if (register_operand (src, QImode)) /* mov r,r */
1515         {
1516           if (test_hard_reg_class (STACK_REG, dest))
1517             return AS2 (out,%0,%1);
1518           else if (test_hard_reg_class (STACK_REG, src))
1519             return AS2 (in,%0,%1);
1520           
1521           return AS2 (mov,%0,%1);
1522         }
1523       else if (CONSTANT_P (src))
1524         {
1525           if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1526             return AS2 (ldi,%0,lo8(%1));
1527           
1528           if (GET_CODE (src) == CONST_INT)
1529             {
1530               if (src == const0_rtx) /* mov r,L */
1531                 return AS1 (clr,%0);
1532               else if (src == const1_rtx)
1533                 {
1534                   *l = 2;
1535                   return (AS1 (clr,%0) CR_TAB
1536                           AS1 (inc,%0));
1537                 }
1538               else if (src == constm1_rtx)
1539                 {
1540                   /* Immediate constants -1 to any register */
1541                   *l = 2;
1542                   return (AS1 (clr,%0) CR_TAB
1543                           AS1 (dec,%0));
1544                 }
1545               else
1546                 {
1547                   int bit_nr = exact_log2 (INTVAL (src));
1548
1549                   if (bit_nr >= 0)
1550                     {
1551                       *l = 3;
1552                       if (!real_l)
1553                         output_asm_insn ((AS1 (clr,%0) CR_TAB
1554                                           "set"), operands);
1555                       if (!real_l)
1556                         avr_output_bld (operands, bit_nr);
1557
1558                       return "";
1559                     }
1560                 }
1561             }
1562           
1563           /* Last resort, larger than loading from memory.  */
1564           *l = 4;
1565           return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1566                   AS2 (ldi,r31,lo8(%1))     CR_TAB
1567                   AS2 (mov,%0,r31)          CR_TAB
1568                   AS2 (mov,r31,__tmp_reg__));
1569         }
1570       else if (GET_CODE (src) == MEM)
1571         return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1572     }
1573   else if (GET_CODE (dest) == MEM)
1574     {
1575       const char *template;
1576
1577       if (src == const0_rtx)
1578         operands[1] = zero_reg_rtx;
1579
1580       template = out_movqi_mr_r (insn, operands, real_l);
1581
1582       if (!real_l)
1583         output_asm_insn (template, operands);
1584
1585       operands[1] = src;
1586     }
1587   return "";
1588 }
1589
1590
1591 const char *
1592 output_movhi (rtx insn, rtx operands[], int *l)
1593 {
1594   int dummy;
1595   rtx dest = operands[0];
1596   rtx src = operands[1];
1597   int *real_l = l;
1598   
1599   if (!l)
1600     l = &dummy;
1601   
1602   if (register_operand (dest, HImode))
1603     {
1604       if (register_operand (src, HImode)) /* mov r,r */
1605         {
1606           if (test_hard_reg_class (STACK_REG, dest))
1607             {
1608               if (TARGET_TINY_STACK)
1609                 {
1610                   *l = 1;
1611                   return AS2 (out,__SP_L__,%A1);
1612                 }
1613               else if (TARGET_NO_INTERRUPTS)
1614                 {
1615                   *l = 2;
1616                   return (AS2 (out,__SP_H__,%B1) CR_TAB
1617                           AS2 (out,__SP_L__,%A1));
1618                 }
1619
1620               *l = 5;
1621               return (AS2 (in,__tmp_reg__,__SREG__)  CR_TAB
1622                       "cli"                          CR_TAB
1623                       AS2 (out,__SP_H__,%B1)         CR_TAB
1624                       AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1625                       AS2 (out,__SP_L__,%A1));
1626             }
1627           else if (test_hard_reg_class (STACK_REG, src))
1628             {
1629               *l = 2;   
1630               return (AS2 (in,%A0,__SP_L__) CR_TAB
1631                       AS2 (in,%B0,__SP_H__));
1632             }
1633
1634           if (AVR_ENHANCED)
1635             {
1636               *l = 1;
1637               return (AS2 (movw,%0,%1));
1638             }
1639
1640           if (true_regnum (dest) > true_regnum (src))
1641             {
1642               *l = 2;
1643               return (AS2 (mov,%B0,%B1) CR_TAB
1644                       AS2 (mov,%A0,%A1));
1645             }
1646           else
1647             {
1648               *l = 2;
1649               return (AS2 (mov,%A0,%A1) CR_TAB
1650                       AS2 (mov,%B0,%B1));
1651             }
1652         }
1653       else if (CONSTANT_P (src))
1654         {
1655           if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1656             {
1657               *l = 2;
1658               return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1659                       AS2 (ldi,%B0,hi8(%1)));
1660             }
1661           
1662           if (GET_CODE (src) == CONST_INT)
1663             {
1664               if (src == const0_rtx) /* mov r,L */
1665                 {
1666                   *l = 2;
1667                   return (AS1 (clr,%A0) CR_TAB
1668                           AS1 (clr,%B0));
1669                 }
1670               else if (src == const1_rtx)
1671                 {
1672                   *l = 3;
1673                   return (AS1 (clr,%A0) CR_TAB
1674                           AS1 (clr,%B0) CR_TAB
1675                           AS1 (inc,%A0));
1676                 }
1677               else if (src == constm1_rtx)
1678                 {
1679                   /* Immediate constants -1 to any register */
1680                   *l = 3;
1681                   return (AS1 (clr,%0)  CR_TAB
1682                           AS1 (dec,%A0) CR_TAB
1683                           AS2 (mov,%B0,%A0));
1684                 }
1685               else
1686                 {
1687                   int bit_nr = exact_log2 (INTVAL (src));
1688
1689                   if (bit_nr >= 0)
1690                     {
1691                       *l = 4;
1692                       if (!real_l)
1693                         output_asm_insn ((AS1 (clr,%A0) CR_TAB
1694                                           AS1 (clr,%B0) CR_TAB
1695                                           "set"), operands);
1696                       if (!real_l)
1697                         avr_output_bld (operands, bit_nr);
1698
1699                       return "";
1700                     }
1701                 }
1702
1703               if ((INTVAL (src) & 0xff) == 0)
1704                 {
1705                   *l = 5;
1706                   return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1707                           AS1 (clr,%A0)             CR_TAB
1708                           AS2 (ldi,r31,hi8(%1))     CR_TAB
1709                           AS2 (mov,%B0,r31)         CR_TAB
1710                           AS2 (mov,r31,__tmp_reg__));
1711                 }
1712               else if ((INTVAL (src) & 0xff00) == 0)
1713                 {
1714                   *l = 5;
1715                   return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1716                           AS2 (ldi,r31,lo8(%1))     CR_TAB
1717                           AS2 (mov,%A0,r31)         CR_TAB
1718                           AS1 (clr,%B0)             CR_TAB
1719                           AS2 (mov,r31,__tmp_reg__));
1720                 }
1721             }
1722           
1723           /* Last resort, equal to loading from memory.  */
1724           *l = 6;
1725           return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1726                   AS2 (ldi,r31,lo8(%1))     CR_TAB
1727                   AS2 (mov,%A0,r31)         CR_TAB
1728                   AS2 (ldi,r31,hi8(%1))     CR_TAB
1729                   AS2 (mov,%B0,r31)         CR_TAB
1730                   AS2 (mov,r31,__tmp_reg__));
1731         }
1732       else if (GET_CODE (src) == MEM)
1733         return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1734     }
1735   else if (GET_CODE (dest) == MEM)
1736     {
1737       const char *template;
1738
1739       if (src == const0_rtx)
1740         operands[1] = zero_reg_rtx;
1741
1742       template = out_movhi_mr_r (insn, operands, real_l);
1743
1744       if (!real_l)
1745         output_asm_insn (template, operands);
1746
1747       operands[1] = src;
1748       return "";
1749     }
1750   fatal_insn ("invalid insn:", insn);
1751   return "";
1752 }
1753
1754 const char *
1755 out_movqi_r_mr (rtx insn, rtx op[], int *l)
1756 {
1757   rtx dest = op[0];
1758   rtx src = op[1];
1759   rtx x = XEXP (src, 0);
1760   int dummy;
1761   
1762   if (!l)
1763     l = &dummy;
1764   
1765   if (CONSTANT_ADDRESS_P (x))
1766     {
1767       if (avr_io_address_p (x, 1))
1768         {
1769           *l = 1;
1770           return AS2 (in,%0,%1-0x20);
1771         }
1772       *l = 2;
1773       return AS2 (lds,%0,%1);
1774     }
1775   /* memory access by reg+disp */
1776   else if (GET_CODE (x) == PLUS
1777       && REG_P (XEXP (x,0))
1778       && GET_CODE (XEXP (x,1)) == CONST_INT)
1779     {
1780       if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
1781         {
1782           int disp = INTVAL (XEXP (x,1));
1783           if (REGNO (XEXP (x,0)) != REG_Y)
1784             fatal_insn ("incorrect insn:",insn);
1785
1786           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1787             return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1788                             AS2 (ldd,%0,Y+63)     CR_TAB
1789                             AS2 (sbiw,r28,%o1-63));
1790
1791           return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1792                           AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1793                           AS2 (ld,%0,Y)            CR_TAB
1794                           AS2 (subi,r28,lo8(%o1))  CR_TAB
1795                           AS2 (sbci,r29,hi8(%o1)));
1796         }
1797       else if (REGNO (XEXP (x,0)) == REG_X)
1798         {
1799           /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1800              it but I have this situation with extremal optimizing options.  */
1801           if (reg_overlap_mentioned_p (dest, XEXP (x,0))
1802               || reg_unused_after (insn, XEXP (x,0)))
1803             return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1804                             AS2 (ld,%0,X));
1805
1806           return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1807                           AS2 (ld,%0,X)      CR_TAB
1808                           AS2 (sbiw,r26,%o1));
1809         }
1810       *l = 1;
1811       return AS2 (ldd,%0,%1);
1812     }
1813   *l = 1;
1814   return AS2 (ld,%0,%1);
1815 }
1816
1817 const char *
1818 out_movhi_r_mr (rtx insn, rtx op[], int *l)
1819 {
1820   rtx dest = op[0];
1821   rtx src = op[1];
1822   rtx base = XEXP (src, 0);
1823   int reg_dest = true_regnum (dest);
1824   int reg_base = true_regnum (base);
1825   int tmp;
1826
1827   if (!l)
1828     l = &tmp;
1829
1830   if (reg_base > 0)
1831     {
1832       if (reg_dest == reg_base)         /* R = (R) */
1833         {
1834           *l = 3;
1835           return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1836                   AS2 (ld,%B0,%1) CR_TAB
1837                   AS2 (mov,%A0,__tmp_reg__));
1838         }
1839       else if (reg_base == REG_X)        /* (R26) */
1840         {
1841           if (reg_unused_after (insn, base))
1842             {
1843               *l = 2;
1844               return (AS2 (ld,%A0,X+) CR_TAB
1845                       AS2 (ld,%B0,X));
1846             }
1847           *l  = 3;
1848           return (AS2 (ld,%A0,X+) CR_TAB
1849                   AS2 (ld,%B0,X) CR_TAB
1850                   AS2 (sbiw,r26,1));
1851         }
1852       else                      /* (R)  */
1853         {
1854           *l = 2;
1855           return (AS2 (ld,%A0,%1)    CR_TAB
1856                   AS2 (ldd,%B0,%1+1));
1857         }
1858     }
1859   else if (GET_CODE (base) == PLUS) /* (R + i) */
1860     {
1861       int disp = INTVAL (XEXP (base, 1));
1862       int reg_base = true_regnum (XEXP (base, 0));
1863       
1864       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
1865         {
1866           if (REGNO (XEXP (base, 0)) != REG_Y)
1867             fatal_insn ("incorrect insn:",insn);
1868           
1869           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
1870             return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
1871                             AS2 (ldd,%A0,Y+62)    CR_TAB
1872                             AS2 (ldd,%B0,Y+63)    CR_TAB
1873                             AS2 (sbiw,r28,%o1-62));
1874
1875           return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1876                           AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1877                           AS2 (ld,%A0,Y)           CR_TAB
1878                           AS2 (ldd,%B0,Y+1)        CR_TAB
1879                           AS2 (subi,r28,lo8(%o1))  CR_TAB
1880                           AS2 (sbci,r29,hi8(%o1)));
1881         }
1882       if (reg_base == REG_X)
1883         {
1884           /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1885              it but I have this situation with extremal
1886              optimization options.  */
1887           
1888           *l = 4;
1889           if (reg_base == reg_dest)
1890             return (AS2 (adiw,r26,%o1)      CR_TAB
1891                     AS2 (ld,__tmp_reg__,X+) CR_TAB
1892                     AS2 (ld,%B0,X)          CR_TAB
1893                     AS2 (mov,%A0,__tmp_reg__));
1894
1895           return (AS2 (adiw,r26,%o1) CR_TAB
1896                   AS2 (ld,%A0,X+)    CR_TAB
1897                   AS2 (ld,%B0,X)     CR_TAB
1898                   AS2 (sbiw,r26,%o1+1));
1899         }
1900
1901       if (reg_base == reg_dest)
1902         {
1903           *l = 3;
1904           return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
1905                   AS2 (ldd,%B0,%B1)         CR_TAB
1906                   AS2 (mov,%A0,__tmp_reg__));
1907         }
1908       
1909       *l = 2;
1910       return (AS2 (ldd,%A0,%A1) CR_TAB
1911               AS2 (ldd,%B0,%B1));
1912     }
1913   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
1914     {
1915       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1916         fatal_insn ("incorrect insn:", insn);
1917
1918       *l = 2;
1919       return (AS2 (ld,%B0,%1) CR_TAB
1920               AS2 (ld,%A0,%1));
1921     }
1922   else if (GET_CODE (base) == POST_INC) /* (R++) */
1923     {
1924       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1925         fatal_insn ("incorrect insn:", insn);
1926
1927       *l = 2;
1928       return (AS2 (ld,%A0,%1)  CR_TAB
1929               AS2 (ld,%B0,%1));
1930     }
1931   else if (CONSTANT_ADDRESS_P (base))
1932     {
1933       if (avr_io_address_p (base, 2))
1934         {
1935           *l = 2;
1936           return (AS2 (in,%A0,%A1-0x20) CR_TAB
1937                   AS2 (in,%B0,%B1-0x20));
1938         }
1939       *l = 4;
1940       return (AS2 (lds,%A0,%A1) CR_TAB
1941               AS2 (lds,%B0,%B1));
1942     }
1943   
1944   fatal_insn ("unknown move insn:",insn);
1945   return "";
1946 }
1947
1948 const char *
1949 out_movsi_r_mr (rtx insn, rtx op[], int *l)
1950 {
1951   rtx dest = op[0];
1952   rtx src = op[1];
1953   rtx base = XEXP (src, 0);
1954   int reg_dest = true_regnum (dest);
1955   int reg_base = true_regnum (base);
1956   int tmp;
1957
1958   if (!l)
1959     l = &tmp;
1960   
1961   if (reg_base > 0)
1962     {
1963       if (reg_base == REG_X)        /* (R26) */
1964         {
1965           if (reg_dest == REG_X)
1966             /* "ld r26,-X" is undefined */
1967             return *l=7, (AS2 (adiw,r26,3)        CR_TAB
1968                           AS2 (ld,r29,X)          CR_TAB
1969                           AS2 (ld,r28,-X)         CR_TAB
1970                           AS2 (ld,__tmp_reg__,-X) CR_TAB
1971                           AS2 (sbiw,r26,1)        CR_TAB
1972                           AS2 (ld,r26,X)          CR_TAB
1973                           AS2 (mov,r27,__tmp_reg__));
1974           else if (reg_dest == REG_X - 2)
1975             return *l=5, (AS2 (ld,%A0,X+)  CR_TAB
1976                           AS2 (ld,%B0,X+) CR_TAB
1977                           AS2 (ld,__tmp_reg__,X+)  CR_TAB
1978                           AS2 (ld,%D0,X)  CR_TAB
1979                           AS2 (mov,%C0,__tmp_reg__));
1980           else if (reg_unused_after (insn, base))
1981             return  *l=4, (AS2 (ld,%A0,X+)  CR_TAB
1982                            AS2 (ld,%B0,X+) CR_TAB
1983                            AS2 (ld,%C0,X+) CR_TAB
1984                            AS2 (ld,%D0,X));
1985           else
1986             return  *l=5, (AS2 (ld,%A0,X+)  CR_TAB
1987                            AS2 (ld,%B0,X+) CR_TAB
1988                            AS2 (ld,%C0,X+) CR_TAB
1989                            AS2 (ld,%D0,X)  CR_TAB
1990                            AS2 (sbiw,r26,3));
1991         }
1992       else
1993         {
1994           if (reg_dest == reg_base)
1995             return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
1996                           AS2 (ldd,%C0,%1+2) CR_TAB
1997                           AS2 (ldd,__tmp_reg__,%1+1)  CR_TAB
1998                           AS2 (ld,%A0,%1)  CR_TAB
1999                           AS2 (mov,%B0,__tmp_reg__));
2000           else if (reg_base == reg_dest + 2)
2001             return *l=5, (AS2 (ld ,%A0,%1)    CR_TAB
2002                           AS2 (ldd,%B0,%1+1) CR_TAB
2003                           AS2 (ldd,__tmp_reg__,%1+2)  CR_TAB
2004                           AS2 (ldd,%D0,%1+3) CR_TAB
2005                           AS2 (mov,%C0,__tmp_reg__));
2006           else
2007             return *l=4, (AS2 (ld ,%A0,%1)   CR_TAB
2008                           AS2 (ldd,%B0,%1+1) CR_TAB
2009                           AS2 (ldd,%C0,%1+2) CR_TAB
2010                           AS2 (ldd,%D0,%1+3));
2011         }
2012     }
2013   else if (GET_CODE (base) == PLUS) /* (R + i) */
2014     {
2015       int disp = INTVAL (XEXP (base, 1));
2016       
2017       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2018         {
2019           if (REGNO (XEXP (base, 0)) != REG_Y)
2020             fatal_insn ("incorrect insn:",insn);
2021
2022           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2023             return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2024                             AS2 (ldd,%A0,Y+60)    CR_TAB
2025                             AS2 (ldd,%B0,Y+61)    CR_TAB
2026                             AS2 (ldd,%C0,Y+62)    CR_TAB
2027                             AS2 (ldd,%D0,Y+63)    CR_TAB
2028                             AS2 (sbiw,r28,%o1-60));
2029
2030           return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2031                           AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2032                           AS2 (ld,%A0,Y)           CR_TAB
2033                           AS2 (ldd,%B0,Y+1)        CR_TAB
2034                           AS2 (ldd,%C0,Y+2)        CR_TAB
2035                           AS2 (ldd,%D0,Y+3)        CR_TAB
2036                           AS2 (subi,r28,lo8(%o1))  CR_TAB
2037                           AS2 (sbci,r29,hi8(%o1)));
2038         }
2039
2040       reg_base = true_regnum (XEXP (base, 0));
2041       if (reg_base == REG_X)
2042         {
2043           /* R = (X + d) */
2044           if (reg_dest == REG_X)
2045             {
2046               *l = 7;
2047               /* "ld r26,-X" is undefined */
2048               return (AS2 (adiw,r26,%o1+3)    CR_TAB
2049                       AS2 (ld,r29,X)          CR_TAB
2050                       AS2 (ld,r28,-X)         CR_TAB
2051                       AS2 (ld,__tmp_reg__,-X) CR_TAB
2052                       AS2 (sbiw,r26,1)        CR_TAB
2053                       AS2 (ld,r26,X)          CR_TAB
2054                       AS2 (mov,r27,__tmp_reg__));
2055             }
2056           *l = 6;
2057           if (reg_dest == REG_X - 2)
2058             return (AS2 (adiw,r26,%o1)      CR_TAB
2059                     AS2 (ld,r24,X+)         CR_TAB
2060                     AS2 (ld,r25,X+)         CR_TAB
2061                     AS2 (ld,__tmp_reg__,X+) CR_TAB
2062                     AS2 (ld,r27,X)          CR_TAB
2063                     AS2 (mov,r26,__tmp_reg__));
2064
2065           return (AS2 (adiw,r26,%o1) CR_TAB
2066                   AS2 (ld,%A0,X+)    CR_TAB
2067                   AS2 (ld,%B0,X+)    CR_TAB
2068                   AS2 (ld,%C0,X+)    CR_TAB
2069                   AS2 (ld,%D0,X)     CR_TAB
2070                   AS2 (sbiw,r26,%o1+3));
2071         }
2072       if (reg_dest == reg_base)
2073         return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2074                       AS2 (ldd,%C0,%C1) CR_TAB
2075                       AS2 (ldd,__tmp_reg__,%B1)  CR_TAB
2076                       AS2 (ldd,%A0,%A1) CR_TAB
2077                       AS2 (mov,%B0,__tmp_reg__));
2078       else if (reg_dest == reg_base - 2)
2079         return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2080                       AS2 (ldd,%B0,%B1) CR_TAB
2081                       AS2 (ldd,__tmp_reg__,%C1)  CR_TAB
2082                       AS2 (ldd,%D0,%D1) CR_TAB
2083                       AS2 (mov,%C0,__tmp_reg__));
2084       return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2085                     AS2 (ldd,%B0,%B1) CR_TAB
2086                     AS2 (ldd,%C0,%C1) CR_TAB
2087                     AS2 (ldd,%D0,%D1));
2088     }
2089   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2090     return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2091                   AS2 (ld,%C0,%1) CR_TAB
2092                   AS2 (ld,%B0,%1) CR_TAB
2093                   AS2 (ld,%A0,%1));
2094   else if (GET_CODE (base) == POST_INC) /* (R++) */
2095     return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2096                   AS2 (ld,%B0,%1) CR_TAB
2097                   AS2 (ld,%C0,%1) CR_TAB
2098                   AS2 (ld,%D0,%1));
2099   else if (CONSTANT_ADDRESS_P (base))
2100       return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2101                     AS2 (lds,%B0,%B1) CR_TAB
2102                     AS2 (lds,%C0,%C1) CR_TAB
2103                     AS2 (lds,%D0,%D1));
2104     
2105   fatal_insn ("unknown move insn:",insn);
2106   return "";
2107 }
2108
2109 const char *
2110 out_movsi_mr_r (rtx insn, rtx op[], int *l)
2111 {
2112   rtx dest = op[0];
2113   rtx src = op[1];
2114   rtx base = XEXP (dest, 0);
2115   int reg_base = true_regnum (base);
2116   int reg_src = true_regnum (src);
2117   int tmp;
2118   
2119   if (!l)
2120     l = &tmp;
2121   
2122   if (CONSTANT_ADDRESS_P (base))
2123     return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2124                  AS2 (sts,%B0,%B1) CR_TAB
2125                  AS2 (sts,%C0,%C1) CR_TAB
2126                  AS2 (sts,%D0,%D1));
2127   if (reg_base > 0)                 /* (r) */
2128     {
2129       if (reg_base == REG_X)                /* (R26) */
2130         {
2131           if (reg_src == REG_X)
2132             {
2133               /* "st X+,r26" is undefined */
2134               if (reg_unused_after (insn, base))
2135                 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2136                               AS2 (st,X,r26)            CR_TAB
2137                               AS2 (adiw,r26,1)          CR_TAB
2138                               AS2 (st,X+,__tmp_reg__)   CR_TAB
2139                               AS2 (st,X+,r28)           CR_TAB
2140                               AS2 (st,X,r29));
2141               else
2142                 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2143                               AS2 (st,X,r26)            CR_TAB
2144                               AS2 (adiw,r26,1)          CR_TAB
2145                               AS2 (st,X+,__tmp_reg__)   CR_TAB
2146                               AS2 (st,X+,r28)           CR_TAB
2147                               AS2 (st,X,r29)            CR_TAB
2148                               AS2 (sbiw,r26,3));
2149             }
2150           else if (reg_base == reg_src + 2)
2151             {
2152               if (reg_unused_after (insn, base))
2153                 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2154                               AS2 (mov,__tmp_reg__,%D1) CR_TAB
2155                               AS2 (st,%0+,%A1) CR_TAB
2156                               AS2 (st,%0+,%B1) CR_TAB
2157                               AS2 (st,%0+,__zero_reg__)  CR_TAB
2158                               AS2 (st,%0,__tmp_reg__)   CR_TAB
2159                               AS1 (clr,__zero_reg__));
2160               else
2161                 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2162                               AS2 (mov,__tmp_reg__,%D1) CR_TAB
2163                               AS2 (st,%0+,%A1) CR_TAB
2164                               AS2 (st,%0+,%B1) CR_TAB
2165                               AS2 (st,%0+,__zero_reg__)  CR_TAB
2166                               AS2 (st,%0,__tmp_reg__)   CR_TAB
2167                               AS1 (clr,__zero_reg__)     CR_TAB
2168                               AS2 (sbiw,r26,3));
2169             }
2170           return *l=5, (AS2 (st,%0+,%A1)  CR_TAB
2171                         AS2 (st,%0+,%B1) CR_TAB
2172                         AS2 (st,%0+,%C1) CR_TAB
2173                         AS2 (st,%0,%D1)  CR_TAB
2174                         AS2 (sbiw,r26,3));
2175         }
2176       else
2177         return *l=4, (AS2 (st,%0,%A1)    CR_TAB
2178                       AS2 (std,%0+1,%B1) CR_TAB
2179                       AS2 (std,%0+2,%C1) CR_TAB
2180                       AS2 (std,%0+3,%D1));
2181     }
2182   else if (GET_CODE (base) == PLUS) /* (R + i) */
2183     {
2184       int disp = INTVAL (XEXP (base, 1));
2185       reg_base = REGNO (XEXP (base, 0));
2186       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2187         {
2188           if (reg_base != REG_Y)
2189             fatal_insn ("incorrect insn:",insn);
2190
2191           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2192             return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2193                             AS2 (std,Y+60,%A1)    CR_TAB
2194                             AS2 (std,Y+61,%B1)    CR_TAB
2195                             AS2 (std,Y+62,%C1)    CR_TAB
2196                             AS2 (std,Y+63,%D1)    CR_TAB
2197                             AS2 (sbiw,r28,%o0-60));
2198
2199           return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2200                           AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2201                           AS2 (st,Y,%A1)           CR_TAB
2202                           AS2 (std,Y+1,%B1)        CR_TAB
2203                           AS2 (std,Y+2,%C1)        CR_TAB
2204                           AS2 (std,Y+3,%D1)        CR_TAB
2205                           AS2 (subi,r28,lo8(%o0))  CR_TAB
2206                           AS2 (sbci,r29,hi8(%o0)));
2207         }
2208       if (reg_base == REG_X)
2209         {
2210           /* (X + d) = R */
2211           if (reg_src == REG_X)
2212             {
2213               *l = 9;
2214               return (AS2 (mov,__tmp_reg__,r26)  CR_TAB
2215                       AS2 (mov,__zero_reg__,r27) CR_TAB
2216                       AS2 (adiw,r26,%o0)         CR_TAB
2217                       AS2 (st,X+,__tmp_reg__)    CR_TAB
2218                       AS2 (st,X+,__zero_reg__)   CR_TAB
2219                       AS2 (st,X+,r28)            CR_TAB
2220                       AS2 (st,X,r29)             CR_TAB
2221                       AS1 (clr,__zero_reg__)     CR_TAB
2222                       AS2 (sbiw,r26,%o0+3));
2223             }
2224           else if (reg_src == REG_X - 2)
2225             {
2226               *l = 9;
2227               return (AS2 (mov,__tmp_reg__,r26)  CR_TAB
2228                       AS2 (mov,__zero_reg__,r27) CR_TAB
2229                       AS2 (adiw,r26,%o0)         CR_TAB
2230                       AS2 (st,X+,r24)            CR_TAB
2231                       AS2 (st,X+,r25)            CR_TAB
2232                       AS2 (st,X+,__tmp_reg__)    CR_TAB
2233                       AS2 (st,X,__zero_reg__)    CR_TAB
2234                       AS1 (clr,__zero_reg__)     CR_TAB
2235                       AS2 (sbiw,r26,%o0+3));
2236             }
2237           *l = 6;
2238           return (AS2 (adiw,r26,%o0) CR_TAB
2239                   AS2 (st,X+,%A1)    CR_TAB
2240                   AS2 (st,X+,%B1)    CR_TAB
2241                   AS2 (st,X+,%C1)    CR_TAB
2242                   AS2 (st,X,%D1)     CR_TAB
2243                   AS2 (sbiw,r26,%o0+3));
2244         }
2245       return *l=4, (AS2 (std,%A0,%A1)    CR_TAB
2246                     AS2 (std,%B0,%B1) CR_TAB
2247                     AS2 (std,%C0,%C1) CR_TAB
2248                     AS2 (std,%D0,%D1));
2249     }
2250   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2251     return *l=4, (AS2 (st,%0,%D1) CR_TAB
2252                   AS2 (st,%0,%C1) CR_TAB
2253                   AS2 (st,%0,%B1) CR_TAB
2254                   AS2 (st,%0,%A1));
2255   else if (GET_CODE (base) == POST_INC) /* (R++) */
2256     return *l=4, (AS2 (st,%0,%A1)  CR_TAB
2257                   AS2 (st,%0,%B1) CR_TAB
2258                   AS2 (st,%0,%C1) CR_TAB
2259                   AS2 (st,%0,%D1));
2260   fatal_insn ("unknown move insn:",insn);
2261   return "";
2262 }
2263
2264 const char *
2265 output_movsisf(rtx insn, rtx operands[], int *l)
2266 {
2267   int dummy;
2268   rtx dest = operands[0];
2269   rtx src = operands[1];
2270   int *real_l = l;
2271   
2272   if (!l)
2273     l = &dummy;
2274   
2275   if (register_operand (dest, VOIDmode))
2276     {
2277       if (register_operand (src, VOIDmode)) /* mov r,r */
2278         {
2279           if (true_regnum (dest) > true_regnum (src))
2280             {
2281               if (AVR_ENHANCED)
2282                 {
2283                   *l = 2;
2284                   return (AS2 (movw,%C0,%C1) CR_TAB
2285                           AS2 (movw,%A0,%A1));
2286                 }
2287               *l = 4;
2288               return (AS2 (mov,%D0,%D1) CR_TAB
2289                       AS2 (mov,%C0,%C1) CR_TAB
2290                       AS2 (mov,%B0,%B1) CR_TAB
2291                       AS2 (mov,%A0,%A1));
2292             }
2293           else
2294             {
2295               if (AVR_ENHANCED)
2296                 {
2297                   *l = 2;
2298                   return (AS2 (movw,%A0,%A1) CR_TAB
2299                           AS2 (movw,%C0,%C1));
2300                 }
2301               *l = 4;
2302               return (AS2 (mov,%A0,%A1) CR_TAB
2303                       AS2 (mov,%B0,%B1) CR_TAB
2304                       AS2 (mov,%C0,%C1) CR_TAB
2305                       AS2 (mov,%D0,%D1));
2306             }
2307         }
2308       else if (CONSTANT_P (src))
2309         {
2310           if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2311             {
2312               *l = 4;
2313               return (AS2 (ldi,%A0,lo8(%1))  CR_TAB
2314                       AS2 (ldi,%B0,hi8(%1))  CR_TAB
2315                       AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2316                       AS2 (ldi,%D0,hhi8(%1)));
2317             }
2318           
2319           if (GET_CODE (src) == CONST_INT)
2320             {
2321               const char *const clr_op0 =
2322                 AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
2323                                 AS1 (clr,%B0) CR_TAB
2324                                 AS2 (movw,%C0,%A0))
2325                              : (AS1 (clr,%A0) CR_TAB
2326                                 AS1 (clr,%B0) CR_TAB
2327                                 AS1 (clr,%C0) CR_TAB
2328                                 AS1 (clr,%D0));
2329
2330               if (src == const0_rtx) /* mov r,L */
2331                 {
2332                   *l = AVR_ENHANCED ? 3 : 4;
2333                   return clr_op0;
2334                 }
2335               else if (src == const1_rtx)
2336                 {
2337                   if (!real_l)
2338                     output_asm_insn (clr_op0, operands);
2339                   *l = AVR_ENHANCED ? 4 : 5;
2340                   return AS1 (inc,%A0);
2341                 }
2342               else if (src == constm1_rtx)
2343                 {
2344                   /* Immediate constants -1 to any register */
2345                   if (AVR_ENHANCED)
2346                     {
2347                       *l = 4;
2348                       return (AS1 (clr,%A0)     CR_TAB
2349                               AS1 (dec,%A0)     CR_TAB
2350                               AS2 (mov,%B0,%A0) CR_TAB
2351                               AS2 (movw,%C0,%A0));
2352                     }
2353                   *l = 5;
2354                   return (AS1 (clr,%A0)     CR_TAB
2355                           AS1 (dec,%A0)     CR_TAB
2356                           AS2 (mov,%B0,%A0) CR_TAB
2357                           AS2 (mov,%C0,%A0) CR_TAB
2358                           AS2 (mov,%D0,%A0));
2359                 }
2360               else
2361                 {
2362                   int bit_nr = exact_log2 (INTVAL (src));
2363
2364                   if (bit_nr >= 0)
2365                     {
2366                       *l = AVR_ENHANCED ? 5 : 6;
2367                       if (!real_l)
2368                         {
2369                           output_asm_insn (clr_op0, operands);
2370                           output_asm_insn ("set", operands);
2371                         }
2372                       if (!real_l)
2373                         avr_output_bld (operands, bit_nr);
2374
2375                       return "";
2376                     }
2377                 }
2378             }
2379           
2380           /* Last resort, better than loading from memory.  */
2381           *l = 10;
2382           return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2383                   AS2 (ldi,r31,lo8(%1))     CR_TAB
2384                   AS2 (mov,%A0,r31)         CR_TAB
2385                   AS2 (ldi,r31,hi8(%1))     CR_TAB
2386                   AS2 (mov,%B0,r31)         CR_TAB
2387                   AS2 (ldi,r31,hlo8(%1))    CR_TAB
2388                   AS2 (mov,%C0,r31)         CR_TAB
2389                   AS2 (ldi,r31,hhi8(%1))    CR_TAB
2390                   AS2 (mov,%D0,r31)         CR_TAB
2391                   AS2 (mov,r31,__tmp_reg__));
2392         }
2393       else if (GET_CODE (src) == MEM)
2394         return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2395     }
2396   else if (GET_CODE (dest) == MEM)
2397     {
2398       const char *template;
2399
2400       if (src == const0_rtx)
2401           operands[1] = zero_reg_rtx;
2402
2403       template = out_movsi_mr_r (insn, operands, real_l);
2404
2405       if (!real_l)
2406         output_asm_insn (template, operands);
2407
2408       operands[1] = src;
2409       return "";
2410     }
2411   fatal_insn ("invalid insn:", insn);
2412   return "";
2413 }
2414
2415 const char *
2416 out_movqi_mr_r (rtx insn, rtx op[], int *l)
2417 {
2418   rtx dest = op[0];
2419   rtx src = op[1];
2420   rtx x = XEXP (dest, 0);
2421   int dummy;
2422
2423   if (!l)
2424     l = &dummy;
2425   
2426   if (CONSTANT_ADDRESS_P (x))
2427     {
2428       if (avr_io_address_p (x, 1))
2429         {
2430           *l = 1;
2431           return AS2 (out,%0-0x20,%1);
2432         }
2433       *l = 2;
2434       return AS2 (sts,%0,%1);
2435     }
2436   /* memory access by reg+disp */
2437   else if (GET_CODE (x) == PLUS 
2438       && REG_P (XEXP (x,0))
2439       && GET_CODE (XEXP (x,1)) == CONST_INT)
2440     {
2441       if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
2442         {
2443           int disp = INTVAL (XEXP (x,1));
2444           if (REGNO (XEXP (x,0)) != REG_Y)
2445             fatal_insn ("incorrect insn:",insn);
2446
2447           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2448             return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2449                             AS2 (std,Y+63,%1)     CR_TAB
2450                             AS2 (sbiw,r28,%o0-63));
2451
2452           return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2453                           AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2454                           AS2 (st,Y,%1)            CR_TAB
2455                           AS2 (subi,r28,lo8(%o0))  CR_TAB
2456                           AS2 (sbci,r29,hi8(%o0)));
2457         }
2458       else if (REGNO (XEXP (x,0)) == REG_X)
2459         {
2460           if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
2461             {
2462               if (reg_unused_after (insn, XEXP (x,0)))
2463                 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2464                                 AS2 (adiw,r26,%o0)       CR_TAB
2465                                 AS2 (st,X,__tmp_reg__));
2466
2467               return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2468                               AS2 (adiw,r26,%o0)       CR_TAB
2469                               AS2 (st,X,__tmp_reg__)   CR_TAB
2470                               AS2 (sbiw,r26,%o0));
2471             }
2472           else
2473             {
2474               if (reg_unused_after (insn, XEXP (x,0)))
2475                 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2476                                 AS2 (st,X,%1));
2477
2478               return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2479                               AS2 (st,X,%1)      CR_TAB
2480                               AS2 (sbiw,r26,%o0));
2481             }
2482         }
2483       *l = 1;
2484       return AS2 (std,%0,%1);
2485     }
2486   *l = 1;
2487   return AS2 (st,%0,%1);
2488 }
2489
2490 const char *
2491 out_movhi_mr_r (rtx insn, rtx op[], int *l)
2492 {
2493   rtx dest = op[0];
2494   rtx src = op[1];
2495   rtx base = XEXP (dest, 0);
2496   int reg_base = true_regnum (base);
2497   int reg_src = true_regnum (src);
2498   int tmp;
2499   if (!l)
2500     l = &tmp;
2501   if (CONSTANT_ADDRESS_P (base))
2502     {
2503       if (avr_io_address_p (base, 2))
2504         {
2505           *l = 2;
2506           return (AS2 (out,%B0-0x20,%B1) CR_TAB
2507                   AS2 (out,%A0-0x20,%A1));
2508         }
2509       return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2510                       AS2 (sts,%A0,%A1));
2511     }
2512   if (reg_base > 0)
2513     {
2514       if (reg_base == REG_X)
2515         {
2516           if (reg_src == REG_X)
2517             {
2518               /* "st X+,r26" is undefined */
2519               if (reg_unused_after (insn, src))
2520                 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2521                               AS2 (st,X,r26)            CR_TAB
2522                               AS2 (adiw,r26,1)          CR_TAB
2523                               AS2 (st,X,__tmp_reg__));
2524               else
2525                 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2526                               AS2 (st,X,r26)            CR_TAB
2527                               AS2 (adiw,r26,1)          CR_TAB
2528                               AS2 (st,X,__tmp_reg__)    CR_TAB
2529                               AS2 (sbiw,r26,1));
2530             }
2531           else
2532             {
2533               if (reg_unused_after (insn, base))
2534                 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2535                               AS2 (st,X,%B1));
2536               else
2537                 return *l=3, (AS2 (st  ,X+,%A1) CR_TAB
2538                               AS2 (st  ,X,%B1) CR_TAB
2539                               AS2 (sbiw,r26,1));
2540             }
2541         }
2542       else
2543         return  *l=2, (AS2 (st ,%0,%A1)    CR_TAB
2544                        AS2 (std,%0+1,%B1));
2545     }
2546   else if (GET_CODE (base) == PLUS)
2547     {
2548       int disp = INTVAL (XEXP (base, 1));
2549       reg_base = REGNO (XEXP (base, 0));
2550       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
2551         {
2552           if (reg_base != REG_Y)
2553             fatal_insn ("incorrect insn:",insn);
2554
2555           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
2556             return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
2557                             AS2 (std,Y+62,%A1)    CR_TAB
2558                             AS2 (std,Y+63,%B1)    CR_TAB
2559                             AS2 (sbiw,r28,%o0-62));
2560
2561           return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2562                           AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2563                           AS2 (st,Y,%A1)           CR_TAB
2564                           AS2 (std,Y+1,%B1)        CR_TAB
2565                           AS2 (subi,r28,lo8(%o0))  CR_TAB
2566                           AS2 (sbci,r29,hi8(%o0)));
2567         }
2568       if (reg_base == REG_X)
2569         {
2570           /* (X + d) = R */
2571           if (reg_src == REG_X)
2572             {
2573               *l = 7;
2574               return (AS2 (mov,__tmp_reg__,r26)  CR_TAB
2575                       AS2 (mov,__zero_reg__,r27) CR_TAB
2576                       AS2 (adiw,r26,%o0)         CR_TAB
2577                       AS2 (st,X+,__tmp_reg__)    CR_TAB
2578                       AS2 (st,X,__zero_reg__)    CR_TAB
2579                       AS1 (clr,__zero_reg__)     CR_TAB
2580                       AS2 (sbiw,r26,%o0+1));
2581             }
2582           *l = 4;
2583           return (AS2 (adiw,r26,%o0) CR_TAB
2584                   AS2 (st,X+,%A1)    CR_TAB
2585                   AS2 (st,X,%B1)     CR_TAB
2586                   AS2 (sbiw,r26,%o0+1));
2587         }
2588       return *l=2, (AS2 (std,%A0,%A1)    CR_TAB
2589                     AS2 (std,%B0,%B1));
2590     }
2591   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2592     return *l=2, (AS2 (st,%0,%B1) CR_TAB
2593                   AS2 (st,%0,%A1));
2594   else if (GET_CODE (base) == POST_INC) /* (R++) */
2595     return *l=2, (AS2 (st,%0,%A1)  CR_TAB
2596                   AS2 (st,%0,%B1));
2597   fatal_insn ("unknown move insn:",insn);
2598   return "";
2599 }
2600
2601 /* Return 1 if frame pointer for current function required.  */
2602
2603 int
2604 frame_pointer_required_p (void)
2605 {
2606   return (current_function_calls_alloca
2607           || current_function_args_info.nregs == 0
2608           || get_frame_size () > 0);
2609 }
2610
2611 /* Returns the condition of compare insn INSN, or UNKNOWN.  */
2612
2613 static RTX_CODE
2614 compare_condition (rtx insn)
2615 {
2616   rtx next = next_real_insn (insn);
2617   RTX_CODE cond = UNKNOWN;
2618   if (next && GET_CODE (next) == JUMP_INSN)
2619     {
2620       rtx pat = PATTERN (next);
2621       rtx src = SET_SRC (pat);
2622       rtx t = XEXP (src, 0);
2623       cond = GET_CODE (t);
2624     }
2625   return cond;
2626 }
2627
2628 /* Returns nonzero if INSN is a tst insn that only tests the sign.  */
2629
2630 static int
2631 compare_sign_p (rtx insn)
2632 {
2633   RTX_CODE cond = compare_condition (insn);
2634   return (cond == GE || cond == LT);
2635 }
2636
2637 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2638    that needs to be swapped (GT, GTU, LE, LEU).  */
2639
2640 int
2641 compare_diff_p (rtx insn)
2642 {
2643   RTX_CODE cond = compare_condition (insn);
2644   return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2645 }
2646
2647 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition.  */
2648
2649 int
2650 compare_eq_p (rtx insn)
2651 {
2652   RTX_CODE cond = compare_condition (insn);
2653   return (cond == EQ || cond == NE);
2654 }
2655
2656
2657 /* Output test instruction for HImode.  */
2658
2659 const char *
2660 out_tsthi (rtx insn, int *l)
2661 {
2662   if (compare_sign_p (insn))
2663     {
2664       if (l) *l = 1;
2665       return AS1 (tst,%B0);
2666     }
2667   if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2668       && compare_eq_p (insn))
2669     {
2670       /* Faster than sbiw if we can clobber the operand.  */
2671       if (l) *l = 1;
2672       return AS2 (or,%A0,%B0);
2673     }
2674   if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2675     {
2676       if (l) *l = 1;
2677       return AS2 (sbiw,%0,0);
2678     }
2679   if (l) *l = 2;
2680   return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2681           AS2 (cpc,%B0,__zero_reg__));
2682 }
2683
2684
2685 /* Output test instruction for SImode.  */
2686
2687 const char *
2688 out_tstsi (rtx insn, int *l)
2689 {
2690   if (compare_sign_p (insn))
2691     {
2692       if (l) *l = 1;
2693       return AS1 (tst,%D0);
2694     }
2695   if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
2696     {
2697       if (l) *l = 3;
2698       return (AS2 (sbiw,%A0,0) CR_TAB
2699               AS2 (cpc,%C0,__zero_reg__) CR_TAB
2700               AS2 (cpc,%D0,__zero_reg__));
2701     }
2702   if (l) *l = 4;
2703   return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2704           AS2 (cpc,%B0,__zero_reg__) CR_TAB
2705           AS2 (cpc,%C0,__zero_reg__) CR_TAB
2706           AS2 (cpc,%D0,__zero_reg__));
2707 }
2708
2709
2710 /* Generate asm equivalent for various shifts.
2711    Shift count is a CONST_INT, MEM or REG.
2712    This only handles cases that are not already
2713    carefully hand-optimized in ?sh??i3_out.  */
2714
2715 void
2716 out_shift_with_cnt (const char *template, rtx insn, rtx operands[],
2717                     int *len, int t_len)
2718 {
2719   rtx op[10];
2720   char str[500];
2721   int second_label = 1;
2722   int saved_in_tmp = 0;
2723   int use_zero_reg = 0;
2724
2725   op[0] = operands[0];
2726   op[1] = operands[1];
2727   op[2] = operands[2];
2728   op[3] = operands[3];
2729   str[0] = 0;
2730
2731   if (len)
2732     *len = 1;
2733
2734   if (GET_CODE (operands[2]) == CONST_INT)
2735     {
2736       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2737       int count = INTVAL (operands[2]);
2738       int max_len = 10;  /* If larger than this, always use a loop.  */
2739
2740       if (count < 8 && !scratch)
2741         use_zero_reg = 1;
2742
2743       if (optimize_size)
2744         max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2745
2746       if (t_len * count <= max_len)
2747         {
2748           /* Output shifts inline with no loop - faster.  */
2749           if (len)
2750             *len = t_len * count;
2751           else
2752             {
2753               while (count-- > 0)
2754                 output_asm_insn (template, op);
2755             }
2756
2757           return;
2758         }
2759
2760       if (scratch)
2761         {
2762           if (!len)
2763             strcat (str, AS2 (ldi,%3,%2));
2764         }
2765       else if (use_zero_reg)
2766         {
2767           /* Hack to save one word: use __zero_reg__ as loop counter.
2768              Set one bit, then shift in a loop until it is 0 again.  */
2769
2770           op[3] = zero_reg_rtx;
2771           if (len)
2772             *len = 2;
2773           else
2774             strcat (str, ("set" CR_TAB
2775                           AS2 (bld,%3,%2-1)));
2776         }
2777       else
2778         {
2779           /* No scratch register available, use one from LD_REGS (saved in
2780              __tmp_reg__) that doesn't overlap with registers to shift.  */
2781
2782           op[3] = gen_rtx_REG (QImode,
2783                            ((true_regnum (operands[0]) - 1) & 15) + 16);
2784           op[4] = tmp_reg_rtx;
2785           saved_in_tmp = 1;
2786
2787           if (len)
2788             *len = 3;  /* Includes "mov %3,%4" after the loop.  */
2789           else
2790             strcat (str, (AS2 (mov,%4,%3) CR_TAB
2791                           AS2 (ldi,%3,%2)));
2792         }
2793
2794       second_label = 0;
2795     }
2796   else if (GET_CODE (operands[2]) == MEM)
2797     {
2798       rtx op_mov[10];
2799       
2800       op[3] = op_mov[0] = tmp_reg_rtx;
2801       op_mov[1] = op[2];
2802
2803       if (len)
2804         out_movqi_r_mr (insn, op_mov, len);
2805       else
2806         output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
2807     }
2808   else if (register_operand (operands[2], QImode))
2809     {
2810       if (reg_unused_after (insn, operands[2]))
2811         op[3] = op[2];
2812       else
2813         {
2814           op[3] = tmp_reg_rtx;
2815           if (!len)
2816             strcat (str, (AS2 (mov,%3,%2) CR_TAB));
2817         }
2818     }
2819   else
2820     fatal_insn ("bad shift insn:", insn);
2821
2822   if (second_label)
2823     {
2824       if (len)
2825         ++*len;
2826       else
2827         strcat (str, AS1 (rjmp,2f));
2828     }
2829
2830   if (len)
2831     *len += t_len + 2;  /* template + dec + brXX */
2832   else
2833     {
2834       strcat (str, "\n1:\t");
2835       strcat (str, template);
2836       strcat (str, second_label ? "\n2:\t" : "\n\t");
2837       strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
2838       strcat (str, CR_TAB);
2839       strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
2840       if (saved_in_tmp)
2841         strcat (str, (CR_TAB AS2 (mov,%3,%4)));
2842       output_asm_insn (str, op);
2843     }
2844 }
2845
2846
2847 /* 8bit shift left ((char)x << i)   */
2848
2849 const char *
2850 ashlqi3_out (rtx insn, rtx operands[], int *len)
2851 {
2852   if (GET_CODE (operands[2]) == CONST_INT)
2853     {
2854       int k;
2855
2856       if (!len)
2857         len = &k;
2858
2859       switch (INTVAL (operands[2]))
2860         {
2861         default:
2862           *len = 1;
2863           return AS1 (clr,%0);
2864           
2865         case 1:
2866           *len = 1;
2867           return AS1 (lsl,%0);
2868           
2869         case 2:
2870           *len = 2;
2871           return (AS1 (lsl,%0) CR_TAB
2872                   AS1 (lsl,%0));
2873
2874         case 3:
2875           *len = 3;
2876           return (AS1 (lsl,%0) CR_TAB
2877                   AS1 (lsl,%0) CR_TAB
2878                   AS1 (lsl,%0));
2879
2880         case 4:
2881           if (test_hard_reg_class (LD_REGS, operands[0]))
2882             {
2883               *len = 2;
2884               return (AS1 (swap,%0) CR_TAB
2885                       AS2 (andi,%0,0xf0));
2886             }
2887           *len = 4;
2888           return (AS1 (lsl,%0) CR_TAB
2889                   AS1 (lsl,%0) CR_TAB
2890                   AS1 (lsl,%0) CR_TAB
2891                   AS1 (lsl,%0));
2892
2893         case 5:
2894           if (test_hard_reg_class (LD_REGS, operands[0]))
2895             {
2896               *len = 3;
2897               return (AS1 (swap,%0) CR_TAB
2898                       AS1 (lsl,%0)  CR_TAB
2899                       AS2 (andi,%0,0xe0));
2900             }
2901           *len = 5;
2902           return (AS1 (lsl,%0) CR_TAB
2903                   AS1 (lsl,%0) CR_TAB
2904                   AS1 (lsl,%0) CR_TAB
2905                   AS1 (lsl,%0) CR_TAB
2906                   AS1 (lsl,%0));
2907
2908         case 6:
2909           if (test_hard_reg_class (LD_REGS, operands[0]))
2910             {
2911               *len = 4;
2912               return (AS1 (swap,%0) CR_TAB
2913                       AS1 (lsl,%0)  CR_TAB
2914                       AS1 (lsl,%0)  CR_TAB
2915                       AS2 (andi,%0,0xc0));
2916             }
2917           *len = 6;
2918           return (AS1 (lsl,%0) CR_TAB
2919                   AS1 (lsl,%0) CR_TAB
2920                   AS1 (lsl,%0) CR_TAB
2921                   AS1 (lsl,%0) CR_TAB
2922                   AS1 (lsl,%0) CR_TAB
2923                   AS1 (lsl,%0));
2924
2925         case 7:
2926           *len = 3;
2927           return (AS1 (ror,%0) CR_TAB
2928                   AS1 (clr,%0) CR_TAB
2929                   AS1 (ror,%0));
2930         }
2931     }
2932   else if (CONSTANT_P (operands[2]))
2933     fatal_insn ("internal compiler error.  Incorrect shift:", insn);
2934
2935   out_shift_with_cnt (AS1 (lsl,%0),
2936                       insn, operands, len, 1);
2937   return "";
2938 }
2939
2940
2941 /* 16bit shift left ((short)x << i)   */
2942
2943 const char *
2944 ashlhi3_out (rtx insn, rtx operands[], int *len)
2945 {
2946   if (GET_CODE (operands[2]) == CONST_INT)
2947     {
2948       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2949       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
2950       int k;
2951       int *t = len;
2952
2953       if (!len)
2954         len = &k;
2955       
2956       switch (INTVAL (operands[2]))
2957         {
2958         case 4:
2959           if (optimize_size && scratch)
2960             break;  /* 5 */
2961           if (ldi_ok)
2962             {
2963               *len = 6;
2964               return (AS1 (swap,%A0)      CR_TAB
2965                       AS1 (swap,%B0)      CR_TAB
2966                       AS2 (andi,%B0,0xf0) CR_TAB
2967                       AS2 (eor,%B0,%A0)   CR_TAB
2968                       AS2 (andi,%A0,0xf0) CR_TAB
2969                       AS2 (eor,%B0,%A0));
2970             }
2971           if (scratch)
2972             {
2973               *len = 7;
2974               return (AS1 (swap,%A0)    CR_TAB
2975                       AS1 (swap,%B0)    CR_TAB
2976                       AS2 (ldi,%3,0xf0) CR_TAB
2977                       AS2 (and,%B0,%3)  CR_TAB
2978                       AS2 (eor,%B0,%A0) CR_TAB
2979                       AS2 (and,%A0,%3)  CR_TAB
2980                       AS2 (eor,%B0,%A0));
2981             }
2982           break;  /* optimize_size ? 6 : 8 */
2983
2984         case 5:
2985           if (optimize_size)
2986             break;  /* scratch ? 5 : 6 */
2987           if (ldi_ok)
2988             {
2989               *len = 8;
2990               return (AS1 (lsl,%A0)       CR_TAB
2991                       AS1 (rol,%B0)       CR_TAB
2992                       AS1 (swap,%A0)      CR_TAB
2993                       AS1 (swap,%B0)      CR_TAB
2994                       AS2 (andi,%B0,0xf0) CR_TAB
2995                       AS2 (eor,%B0,%A0)   CR_TAB
2996                       AS2 (andi,%A0,0xf0) CR_TAB
2997                       AS2 (eor,%B0,%A0));
2998             }
2999           if (scratch)
3000             {
3001               *len = 9;
3002               return (AS1 (lsl,%A0)     CR_TAB
3003                       AS1 (rol,%B0)     CR_TAB
3004                       AS1 (swap,%A0)    CR_TAB
3005                       AS1 (swap,%B0)    CR_TAB
3006                       AS2 (ldi,%3,0xf0) CR_TAB
3007                       AS2 (and,%B0,%3)  CR_TAB
3008                       AS2 (eor,%B0,%A0) CR_TAB
3009                       AS2 (and,%A0,%3)  CR_TAB
3010                       AS2 (eor,%B0,%A0));
3011             }
3012           break;  /* 10 */
3013
3014         case 6:
3015           if (optimize_size)
3016             break;  /* scratch ? 5 : 6 */
3017           *len = 9;
3018           return (AS1 (clr,__tmp_reg__) CR_TAB
3019                   AS1 (lsr,%B0)         CR_TAB
3020                   AS1 (ror,%A0)         CR_TAB
3021                   AS1 (ror,__tmp_reg__) CR_TAB
3022                   AS1 (lsr,%B0)         CR_TAB
3023                   AS1 (ror,%A0)         CR_TAB
3024                   AS1 (ror,__tmp_reg__) CR_TAB
3025                   AS2 (mov,%B0,%A0)     CR_TAB
3026                   AS2 (mov,%A0,__tmp_reg__));
3027
3028         case 7:
3029           *len = 5;
3030           return (AS1 (lsr,%B0)     CR_TAB
3031                   AS2 (mov,%B0,%A0) CR_TAB
3032                   AS1 (clr,%A0)     CR_TAB
3033                   AS1 (ror,%B0)     CR_TAB
3034                   AS1 (ror,%A0));
3035
3036         case 8:
3037           if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
3038             return *len = 1, AS1 (clr,%A0);
3039           else
3040             return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3041                               AS1 (clr,%A0));
3042
3043         case 9:
3044           *len = 3;
3045           return (AS2 (mov,%B0,%A0) CR_TAB
3046                   AS1 (clr,%A0)     CR_TAB
3047                   AS1 (lsl,%B0));
3048
3049         case 10:
3050           *len = 4;
3051           return (AS2 (mov,%B0,%A0) CR_TAB
3052                   AS1 (clr,%A0)     CR_TAB
3053                   AS1 (lsl,%B0)     CR_TAB
3054                   AS1 (lsl,%B0));
3055
3056         case 11:
3057           *len = 5;
3058           return (AS2 (mov,%B0,%A0) CR_TAB
3059                   AS1 (clr,%A0)     CR_TAB
3060                   AS1 (lsl,%B0)     CR_TAB
3061                   AS1 (lsl,%B0)     CR_TAB
3062                   AS1 (lsl,%B0));
3063
3064         case 12:
3065           if (ldi_ok)
3066             {
3067               *len = 4;
3068               return (AS2 (mov,%B0,%A0) CR_TAB
3069                       AS1 (clr,%A0)     CR_TAB
3070                       AS1 (swap,%B0)    CR_TAB
3071                       AS2 (andi,%B0,0xf0));
3072             }
3073           if (scratch)
3074             {
3075               *len = 5;
3076               return (AS2 (mov,%B0,%A0) CR_TAB
3077                       AS1 (clr,%A0)     CR_TAB
3078                       AS1 (swap,%B0)    CR_TAB
3079                       AS2 (ldi,%3,0xf0) CR_TAB
3080                       AS2 (and,%B0,%3));
3081             }
3082           *len = 6;
3083           return (AS2 (mov,%B0,%A0) CR_TAB
3084                   AS1 (clr,%A0)     CR_TAB
3085                   AS1 (lsl,%B0)     CR_TAB
3086                   AS1 (lsl,%B0)     CR_TAB
3087                   AS1 (lsl,%B0)     CR_TAB
3088                   AS1 (lsl,%B0));
3089
3090         case 13:
3091           if (ldi_ok)
3092             {
3093               *len = 5;
3094               return (AS2 (mov,%B0,%A0) CR_TAB
3095                       AS1 (clr,%A0)     CR_TAB
3096                       AS1 (swap,%B0)    CR_TAB
3097                       AS1 (lsl,%B0)     CR_TAB
3098                       AS2 (andi,%B0,0xe0));
3099             }
3100           if (AVR_ENHANCED && scratch)
3101             {
3102               *len = 5;
3103               return (AS2 (ldi,%3,0x20) CR_TAB
3104                       AS2 (mul,%A0,%3)  CR_TAB
3105                       AS2 (mov,%B0,r0)  CR_TAB
3106                       AS1 (clr,%A0)     CR_TAB
3107                       AS1 (clr,__zero_reg__));
3108             }
3109           if (optimize_size && scratch)
3110             break;  /* 5 */
3111           if (scratch)
3112             {
3113               *len = 6;
3114               return (AS2 (mov,%B0,%A0) CR_TAB
3115                       AS1 (clr,%A0)     CR_TAB
3116                       AS1 (swap,%B0)    CR_TAB
3117                       AS1 (lsl,%B0)     CR_TAB
3118                       AS2 (ldi,%3,0xe0) CR_TAB
3119                       AS2 (and,%B0,%3));
3120             }
3121           if (AVR_ENHANCED)
3122             {
3123               *len = 6;
3124               return ("set"            CR_TAB
3125                       AS2 (bld,r1,5)   CR_TAB
3126                       AS2 (mul,%A0,r1) CR_TAB
3127                       AS2 (mov,%B0,r0) CR_TAB
3128                       AS1 (clr,%A0)    CR_TAB
3129                       AS1 (clr,__zero_reg__));
3130             }
3131           *len = 7;
3132           return (AS2 (mov,%B0,%A0) CR_TAB
3133                   AS1 (clr,%A0)     CR_TAB
3134                   AS1 (lsl,%B0)     CR_TAB
3135                   AS1 (lsl,%B0)     CR_TAB
3136                   AS1 (lsl,%B0)     CR_TAB
3137                   AS1 (lsl,%B0)     CR_TAB
3138                   AS1 (lsl,%B0));
3139
3140         case 14:
3141           if (AVR_ENHANCED && ldi_ok)
3142             {
3143               *len = 5;
3144               return (AS2 (ldi,%B0,0x40) CR_TAB
3145                       AS2 (mul,%A0,%B0)  CR_TAB
3146                       AS2 (mov,%B0,r0)   CR_TAB
3147                       AS1 (clr,%A0)      CR_TAB
3148                       AS1 (clr,__zero_reg__));
3149             }
3150           if (AVR_ENHANCED && scratch)
3151             {
3152               *len = 5;
3153               return (AS2 (ldi,%3,0x40) CR_TAB
3154                       AS2 (mul,%A0,%3)  CR_TAB
3155                       AS2 (mov,%B0,r0)  CR_TAB
3156                       AS1 (clr,%A0)     CR_TAB
3157                       AS1 (clr,__zero_reg__));
3158             }
3159           if (optimize_size && ldi_ok)
3160             {
3161               *len = 5;
3162               return (AS2 (mov,%B0,%A0) CR_TAB
3163                       AS2 (ldi,%A0,6) "\n1:\t"
3164                       AS1 (lsl,%B0)     CR_TAB
3165                       AS1 (dec,%A0)     CR_TAB
3166                       AS1 (brne,1b));
3167             }
3168           if (optimize_size && scratch)
3169             break;  /* 5 */
3170           *len = 6;
3171           return (AS1 (clr,%B0) CR_TAB
3172                   AS1 (lsr,%A0) CR_TAB
3173                   AS1 (ror,%B0) CR_TAB
3174                   AS1 (lsr,%A0) CR_TAB
3175                   AS1 (ror,%B0) CR_TAB
3176                   AS1 (clr,%A0));
3177
3178         case 15:
3179           *len = 4;
3180           return (AS1 (clr,%B0) CR_TAB
3181                   AS1 (lsr,%A0) CR_TAB
3182                   AS1 (ror,%B0) CR_TAB
3183                   AS1 (clr,%A0));
3184         }
3185       len = t;
3186     }
3187   out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3188                        AS1 (rol,%B0)),
3189                        insn, operands, len, 2);
3190   return "";
3191 }
3192
3193
3194 /* 32bit shift left ((long)x << i)   */
3195
3196 const char *
3197 ashlsi3_out (rtx insn, rtx operands[], int *len)
3198 {
3199   if (GET_CODE (operands[2]) == CONST_INT)
3200     {
3201       int k;
3202       int *t = len;
3203       
3204       if (!len)
3205         len = &k;
3206       
3207       switch (INTVAL (operands[2]))
3208         {
3209         case 8:
3210           {
3211             int reg0 = true_regnum (operands[0]);
3212             int reg1 = true_regnum (operands[1]);
3213             *len = 4;
3214             if (reg0 >= reg1)
3215               return (AS2 (mov,%D0,%C1)  CR_TAB
3216                       AS2 (mov,%C0,%B1)  CR_TAB
3217                       AS2 (mov,%B0,%A1)  CR_TAB
3218                       AS1 (clr,%A0));
3219             else if (reg0 + 1 == reg1)
3220               {
3221                 *len = 1;
3222                 return AS1 (clr,%A0);
3223               }
3224             else
3225               return (AS1 (clr,%A0)      CR_TAB
3226                       AS2 (mov,%B0,%A1)  CR_TAB
3227                       AS2 (mov,%C0,%B1)  CR_TAB
3228                       AS2 (mov,%D0,%C1));
3229           }
3230
3231         case 16:
3232           {
3233             int reg0 = true_regnum (operands[0]);
3234             int reg1 = true_regnum (operands[1]);
3235             *len = 4;
3236             if (AVR_ENHANCED && (reg0 + 2 != reg1))
3237               {
3238                 *len = 3;
3239                 return (AS2 (movw,%C0,%A1) CR_TAB
3240                         AS1 (clr,%B0)      CR_TAB
3241                         AS1 (clr,%A0));
3242               }
3243             if (reg0 + 1 >= reg1)
3244               return (AS2 (mov,%D0,%B1)  CR_TAB
3245                       AS2 (mov,%C0,%A1)  CR_TAB
3246                       AS1 (clr,%B0)      CR_TAB
3247                       AS1 (clr,%A0));
3248             if (reg0 + 2 == reg1)
3249               {
3250                 *len = 2;
3251                 return (AS1 (clr,%B0)      CR_TAB
3252                         AS1 (clr,%A0));
3253               }
3254             else
3255               return (AS2 (mov,%C0,%A1)  CR_TAB
3256                       AS2 (mov,%D0,%B1)  CR_TAB
3257                       AS1 (clr,%B0)      CR_TAB
3258                       AS1 (clr,%A0));
3259           }
3260
3261         case 24:
3262           *len = 4;
3263           if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
3264             return (AS2 (mov,%D0,%A1)  CR_TAB
3265                     AS1 (clr,%C0)      CR_TAB
3266                     AS1 (clr,%B0)      CR_TAB
3267                     AS1 (clr,%A0));
3268           else
3269             {
3270               *len = 3;
3271               return (AS1 (clr,%C0)      CR_TAB
3272                       AS1 (clr,%B0)      CR_TAB
3273                       AS1 (clr,%A0));
3274             }
3275
3276         case 31:
3277           *len = 6;
3278           return (AS1 (clr,%D0) CR_TAB
3279                   AS1 (lsr,%A0) CR_TAB
3280                   AS1 (ror,%D0) CR_TAB
3281                   AS1 (clr,%C0) CR_TAB
3282                   AS1 (clr,%B0) CR_TAB
3283                   AS1 (clr,%A0));
3284         }
3285       len = t;
3286     }
3287   out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3288                        AS1 (rol,%B0) CR_TAB
3289                        AS1 (rol,%C0) CR_TAB
3290                        AS1 (rol,%D0)),
3291                        insn, operands, len, 4);
3292   return "";
3293 }
3294
3295 /* 8bit arithmetic shift right  ((signed char)x >> i) */
3296
3297 const char *
3298 ashrqi3_out (rtx insn, rtx operands[], int *len)
3299 {
3300   if (GET_CODE (operands[2]) == CONST_INT)
3301     {
3302       int k;
3303
3304       if (!len)
3305         len = &k;
3306
3307       switch (INTVAL (operands[2]))
3308         {
3309         case 1:
3310           *len = 1;
3311           return AS1 (asr,%0);
3312
3313         case 2:
3314           *len = 2;
3315           return (AS1 (asr,%0) CR_TAB
3316                   AS1 (asr,%0));
3317
3318         case 3:
3319           *len = 3;
3320           return (AS1 (asr,%0) CR_TAB
3321                   AS1 (asr,%0) CR_TAB
3322                   AS1 (asr,%0));
3323
3324         case 4:
3325           *len = 4;
3326           return (AS1 (asr,%0) CR_TAB
3327                   AS1 (asr,%0) CR_TAB
3328                   AS1 (asr,%0) CR_TAB
3329                   AS1 (asr,%0));
3330
3331         case 5:
3332           *len = 5;
3333           return (AS1 (asr,%0) CR_TAB
3334                   AS1 (asr,%0) CR_TAB
3335                   AS1 (asr,%0) CR_TAB
3336                   AS1 (asr,%0) CR_TAB
3337                   AS1 (asr,%0));
3338
3339         case 6:
3340           *len = 4;
3341           return (AS2 (bst,%0,6)  CR_TAB
3342                   AS1 (lsl,%0)    CR_TAB
3343                   AS2 (sbc,%0,%0) CR_TAB
3344                   AS2 (bld,%0,0));
3345
3346         default:
3347         case 7:
3348           *len = 2;
3349           return (AS1 (lsl,%0) CR_TAB
3350                   AS2 (sbc,%0,%0));
3351         }