OSDN Git Service

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