OSDN Git Service

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