OSDN Git Service

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