OSDN Git Service

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