OSDN Git Service

* config/avr/avr.c (address_cost): renamed to avr_address_cost.
[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
44 static int    avr_naked_function_p PARAMS ((tree));
45 static int    interrupt_function_p PARAMS ((tree));
46 static int    signal_function_p    PARAMS ((tree));
47 static int    sequent_regs_live    PARAMS ((void));
48 static char * ptrreg_to_str        PARAMS ((int));
49 static char * cond_string          PARAMS ((enum rtx_code));
50
51
52 /* Allocate registers from r25 to r8 for parameters for function calls */
53 #define FIRST_CUM_REG 26
54
55 /* Temporary register RTX (gen_rtx (REG,QImode,TMP_REGNO)) */
56 rtx tmp_reg_rtx;
57
58 /* Zeroed register RTX (gen_rtx (REG,QImode,ZERO_REGNO)) */
59 rtx zero_reg_rtx;
60
61 /* AVR register names {"r0", "r1", ..., "r31"} */
62 char * avr_regnames[] = REGISTER_NAMES;
63
64 /* This holds the last insn address.  */
65 static int last_insn_address = 0;
66
67 /* Commands count in the compiled file */
68 static int commands_in_file;
69
70 /* Commands in the functions prologues in the compiled file */
71 static int commands_in_prologues;
72
73 /* Commands in the functions epilogues in the compiled file */
74 static int commands_in_epilogues;
75
76 /* Prologue/Epilogue size in words */
77 static int prologue_size;
78 static int epilogue_size;
79
80 /* Initial stack value specified by the `-minit-stack=' option */
81 const char *avr_ram_end = NULL;
82
83 /* Numeric representation */
84 static const char *initial_stack;
85
86 /* Default MCU name */
87 const char *avr_mcu_name = "at90s8515";
88
89 /* Default MCU */
90 struct mcu_type_s *avr_mcu_type;
91
92 /* MCU names, initial stack value, flag 'mega' */
93 static struct mcu_type_s mcu_types[] =
94 {{"at90s2313", 224-1, 0},
95  {"at90s2323", 224-1, 0},
96  {"at90s2333", 224-1, 0},
97  {"attiny22",  224-1, 0},
98  {"at90s2343", 224-1, 0},
99  {"at90s4433", 224-1, 0},
100  {"at90s4414", 0x15f, 0},
101  {"at90s4434", 0x15f, 0},
102  {"at90s8515", 0x25f, 0},
103  {"at90s8535", 0x25f, 0},
104  {"atmega603", 0x0fff,1},
105  {"atmega103", 0x0fff,1},
106  {NULL,0,0}};
107
108 /* Setup MCU */
109
110 void
111 avr_override_options (void)
112 {
113   for (avr_mcu_type = mcu_types; avr_mcu_type->name; ++avr_mcu_type)
114     if (strcmp (avr_mcu_type->name, avr_mcu_name) == 0)
115       break;
116   if (!avr_mcu_type->name)
117     {
118       int i;
119       fprintf (stderr,
120                "Wrong mcu `%s' specified\n"
121                "Allowed mcu's:\n", avr_mcu_name);
122       for (i = 0; mcu_types[i].name; ++i)
123         fprintf (stderr,"   %s\n", mcu_types[i].name);
124       fatal ("select right mcu name");
125     }
126 }
127
128 /* Initialize TMP_REG_RTX and ZERO_REG_RTX */
129 void
130 avr_init_once (void)
131 {
132   tmp_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
133   memset (tmp_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
134   PUT_CODE (tmp_reg_rtx, REG);
135   PUT_MODE (tmp_reg_rtx, QImode);
136   XINT (tmp_reg_rtx, 0) = TMP_REGNO;
137
138   zero_reg_rtx = xmalloc (sizeof (struct rtx_def) + 1 * sizeof (rtunion));
139   memset (zero_reg_rtx, 0, sizeof (struct rtx_def) + 1 * sizeof (rtunion));
140   PUT_CODE (zero_reg_rtx, REG);
141   PUT_MODE (zero_reg_rtx, QImode);
142   XINT (zero_reg_rtx, 0) = ZERO_REGNO;
143 }
144
145 /*  return register class from register number */
146
147 static int reg_class_tab[]={
148   GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
149   GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
150   GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
151   GENERAL_REGS, /* r0 - r15 */
152   LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
153   LD_REGS,                      /* r16 - 23 */
154   ADDW_REGS,ADDW_REGS,          /* r24,r25 */
155   POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
156   POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
157   POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
158   STACK_REG,STACK_REG           /* SPL,SPH */
159 };
160
161 /* Return register class for register R */
162
163 enum reg_class
164 avr_regno_reg_class (r)
165      int r;
166 {
167   if (r <= 33)
168     return reg_class_tab[r];
169   return ALL_REGS;
170 }
171
172
173 /* A C expression which defines the machine-dependent operand
174    constraint letters for register classes.  If C is such a
175    letter, the value should be the register class corresponding to
176    it.  Otherwise, the value should be `NO_REGS'.  The register
177    letter `r', corresponding to class `GENERAL_REGS', will not be
178    passed to this macro; you do not need to handle it.  */
179
180 enum reg_class
181 avr_reg_class_from_letter  (c)
182      int c;
183 {
184   switch (c)
185     {
186     case 't' : return R0_REG;
187     case 'b' : return BASE_POINTER_REGS;
188     case 'e' : return POINTER_REGS;
189     case 'w' : return ADDW_REGS;
190     case 'd' : return LD_REGS;
191     case 'l' : return NO_LD_REGS;
192     case 'a' : return SIMPLE_LD_REGS;
193     case 'x' : return POINTER_X_REGS;
194     case 'y' : return POINTER_Y_REGS;
195     case 'z' : return POINTER_Z_REGS;
196     case 'q' : return STACK_REG;
197     default: break;
198     }
199   return NO_REGS;
200 }
201
202 /* Return non-zero if FUNC is a naked function.  */
203
204 static int
205 avr_naked_function_p (func)
206      tree func;
207 {
208   tree a;
209
210   if (TREE_CODE (func) != FUNCTION_DECL)
211     abort ();
212   
213   a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
214   return a != NULL_TREE;
215 }
216
217 /* Return nonzero if FUNC is an interrupt function as specified
218    by the "interrupt" attribute.  */
219
220 static int
221 interrupt_function_p (func)
222      tree func;
223 {
224   tree a;
225
226   if (TREE_CODE (func) != FUNCTION_DECL)
227     return 0;
228
229   a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func));
230   return a != NULL_TREE;
231 }
232
233 /* Return nonzero if FUNC is an signal function as specified
234    by the "signal" attribute.  */
235
236 static int
237 signal_function_p (func)
238      tree func;
239 {
240   tree a;
241
242   if (TREE_CODE (func) != FUNCTION_DECL)
243     return 0;
244
245   a = lookup_attribute ("signal", DECL_MACHINE_ATTRIBUTES (func));
246   return a != NULL_TREE;
247 }
248
249 /* Compute offset between arg_pointer and frame_pointer */
250
251 int
252 initial_elimination_offset (from,to)
253      int from ATTRIBUTE_UNUSED;
254      int to ATTRIBUTE_UNUSED;
255 {
256   int reg;
257   int interrupt_func_p = interrupt_function_p (current_function_decl);
258   int signal_func_p = signal_function_p (current_function_decl);
259   int leaf_func_p = leaf_function_p ();
260   int offset= frame_pointer_needed ? 2 : 0;
261
262   for (reg = 0; reg < 32; ++reg)
263     {
264       if ((!leaf_func_p && (call_used_regs[reg]
265                             && (interrupt_func_p || signal_func_p)))
266           || (regs_ever_live[reg]
267               && (!call_used_regs[reg] || interrupt_func_p || signal_func_p)
268               && ! (frame_pointer_needed
269                     && (reg == REG_Y || reg == (REG_Y+1)))))
270         {
271           ++offset;
272         }
273     }
274   return get_frame_size () + 2 + 1 + offset;
275 }
276
277 /* This function checks sequence of live registers */
278
279 static int
280 sequent_regs_live ()
281 {
282   int reg;
283   int live_seq=0;
284   int cur_seq=0;
285
286   for (reg = 0; reg < 18; ++reg)
287     {
288       if (!call_used_regs[reg])
289         {
290           if (regs_ever_live[reg])
291             {
292               ++live_seq;
293               ++cur_seq;
294             }
295           else
296             cur_seq = 0;
297         }
298     }
299
300   if (!frame_pointer_needed)
301     {
302       if (regs_ever_live[REG_Y])
303         {
304           ++live_seq;
305           ++cur_seq;
306         }
307       else
308         cur_seq = 0;
309
310       if (regs_ever_live[REG_Y+1])
311         {
312           ++live_seq;
313           ++cur_seq;
314         }
315       else
316         cur_seq = 0;
317     }
318   else
319     {
320       cur_seq += 2;
321       live_seq += 2;
322     }
323   return (cur_seq == live_seq) ? live_seq : 0;
324 }
325
326
327 /* Output function prologue */
328
329 void
330 function_prologue (FILE *file, int size)
331 {
332   int reg;
333   int interrupt_func_p;
334   int signal_func_p;
335   int leaf_func_p;
336   int main_p;
337   int live_seq;
338   int minimize;
339   
340   if (avr_naked_function_p (current_function_decl))
341     {
342       fprintf (file, "/* prologue: naked */\n");
343       return;
344     }
345
346   interrupt_func_p = interrupt_function_p (current_function_decl);
347   signal_func_p = signal_function_p (current_function_decl);
348   leaf_func_p = leaf_function_p ();
349   main_p = ! strcmp ("main", current_function_name);
350   live_seq = sequent_regs_live ();
351   minimize = (TARGET_CALL_PROLOGUES
352               && !interrupt_func_p && !signal_func_p && live_seq);
353
354   last_insn_address = 0;
355   prologue_size = 0;
356   fprintf (file, "/* prologue: frame size=%d */\n", size);
357   
358   if (interrupt_func_p)
359     {
360       fprintf (file,"\tsei\n");
361       ++prologue_size;
362     }
363   if (interrupt_func_p | signal_func_p)
364     {
365       fprintf (file, "\t"
366                AS1 (push,__zero_reg__)   CR_TAB
367                AS1 (push,__tmp_reg__)    CR_TAB
368                AS2 (in,__tmp_reg__,__SREG__) CR_TAB
369                AS1 (push,__tmp_reg__)    CR_TAB
370                AS1 (clr,__zero_reg__)    "\n");
371       prologue_size += 5;
372     }
373   if (main_p)
374     {
375       fprintf (file, ("\t" 
376                       AS2 (ldi, r28, lo8(%s - %d)) CR_TAB
377                       AS2 (ldi, r29, hi8(%s - %d)) CR_TAB
378                       AS2 (out,__SP_L__,r28)       CR_TAB
379                       AS2 (out,__SP_H__,r29) "\n"),
380                initial_stack, size, initial_stack, size);
381       
382       prologue_size += 4;
383     }
384   else if (minimize && (frame_pointer_needed || live_seq > 6)) 
385     {
386       fprintf (file, ("\t"
387                       AS2 (ldi, r26, %d) CR_TAB
388                       AS2 (ldi, r27, %d) CR_TAB), size & 0xff, size / 0x100);
389
390       fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB
391                       AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB)
392                ,current_function_name, current_function_name);
393       
394       prologue_size += 4;
395       
396       if (AVR_MEGA)
397         {
398           fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
399                    (18 - live_seq) * 2);
400           prologue_size += 2;
401         }
402       else
403         {
404           fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
405                    (18 - live_seq) * 2);
406           ++prologue_size;
407         }
408       fprintf (file, ".L_%s_body:\n", current_function_name);
409     }
410   else
411     {
412       for (reg = 0; reg < 32; ++reg)
413         {
414           if ((!leaf_func_p
415                && (call_used_regs[reg]
416                    && (interrupt_func_p || signal_func_p)
417                    && !(reg == TMP_REGNO || reg == ZERO_REGNO)))
418               || (regs_ever_live[reg]
419                   && (!call_used_regs[reg]
420                       || interrupt_func_p || signal_func_p)
421                   && ! (frame_pointer_needed
422                         && (reg == REG_Y || reg == (REG_Y+1)))))
423             {
424               fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
425               ++prologue_size;
426             }
427         }
428       if (frame_pointer_needed)
429         {
430           {
431             fprintf (file, "\t"
432                      AS1 (push,r28) CR_TAB
433                      AS1 (push,r29) CR_TAB
434                      AS2 (in,r28,__SP_L__) CR_TAB
435                      AS2 (in,r29,__SP_H__) "\n");
436             prologue_size += 4;
437             if (size)
438               {
439                 if (size > 63)
440                   {
441                     fprintf (file, ("\t"
442                                     AS2 (subi,r28,%d) CR_TAB
443                                     AS2 (sbci,r29,%d) CR_TAB)
444                              , size & 0xff, size / 0x100);
445                     prologue_size += 2;
446                   }
447                 else
448                   {
449                     fprintf (file, "\t" AS2 (sbiw,r28,%d) CR_TAB, size);
450                     ++prologue_size;
451                   }
452                 if (interrupt_func_p)
453                   {
454                     fprintf (file,
455                              "cli" CR_TAB
456                              AS2 (out,__SP_L__,r28) CR_TAB
457                              "sei" CR_TAB
458                              AS2 (out,__SP_H__,r29) "\n");
459                     prologue_size += 4;
460                   }
461                 else if (signal_func_p || TARGET_NO_INTERRUPTS)
462                   {
463                     fprintf (file,
464                              AS2 (out,__SP_L__,r28) CR_TAB
465                              AS2 (out,__SP_H__,r29) "\n");
466                     prologue_size += 2;
467                   }
468                 else
469                   {
470                     fprintf (file,
471                              AS2 (in,__tmp_reg__,__SREG__) CR_TAB
472                              "cli" CR_TAB
473                              AS2 (out,__SP_L__,r28) CR_TAB
474                              AS2 (out,__SREG__,__tmp_reg__) CR_TAB
475                              AS2 (out,__SP_H__,r29) "\n");
476                     prologue_size += 5;
477                   }
478               }
479           }
480         }
481     }
482   fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
483 }
484
485 /* Output function epilogue */
486
487 void
488 function_epilogue (FILE *file, int size)
489 {
490   int reg;
491   int interrupt_func_p;
492   int signal_func_p;
493   int leaf_func_p;
494   int main_p;
495   int function_size;
496   int live_seq;
497   int minimize;
498
499   if (avr_naked_function_p (current_function_decl))
500     {
501       fprintf (file, "/* epilogue: naked */\n");
502       return;
503     }
504
505   interrupt_func_p = interrupt_function_p (current_function_decl);
506   signal_func_p = signal_function_p (current_function_decl);
507   leaf_func_p = leaf_function_p ();
508   main_p = ! strcmp ("main", current_function_name);
509   function_size = (insn_addresses[INSN_UID (get_last_insn ())]
510                    - insn_addresses[INSN_UID (get_insns ())]);
511   live_seq = sequent_regs_live ();
512   minimize = (TARGET_CALL_PROLOGUES
513               && !interrupt_func_p && !signal_func_p && live_seq);
514   
515   epilogue_size = 0;
516   fprintf (file, "/* epilogue: frame size=%d */\n", size);
517   if (main_p)
518     {
519       fprintf (file, "__stop_progIi__:\n\trjmp __stop_progIi__\n");
520       ++epilogue_size;
521     }
522   else if (minimize && (frame_pointer_needed || live_seq > 4))
523     {
524       fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
525       ++epilogue_size;
526       if (frame_pointer_needed)
527         {
528           if (size)
529             {
530               if (size > 63)
531                 {
532                   fprintf (file, AS2 (subi,r28,lo8(-%d)) CR_TAB, size);
533                   fprintf (file, AS2 (sbci,r29,hi8(-%d)) CR_TAB, size);
534                   epilogue_size += 2;
535                 }
536               else
537                 {
538                   fprintf (file, AS2 (adiw,r28,%d) CR_TAB, size);
539                   ++epilogue_size;
540                 }
541             }
542         }
543       else
544         {
545           fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
546                           AS2 (in , r29, __SP_H__) CR_TAB));
547           epilogue_size += 2;
548         }
549       
550       if (AVR_MEGA)
551         {
552           fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
553                    (18 - live_seq) * 2);
554           epilogue_size += 2;
555         }
556       else
557         {
558           fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
559                    (18 - live_seq) * 2);
560           ++epilogue_size;
561         }
562     }
563   else
564     {
565       if (frame_pointer_needed)
566         {
567           if (size)
568             {
569               if (size > 63)
570                 {
571                   fprintf (file, "\t" AS2 (subi,r28,lo8(-%d)) CR_TAB, size);
572                   fprintf (file, AS2 (sbci,r29,hi8(-%d)) CR_TAB, size);
573                   epilogue_size += 2;
574                 }
575               else
576                 {
577                   fprintf (file, "\t" AS2 (adiw,r28,%d) CR_TAB, size);
578                   ++epilogue_size;
579                 }
580               if (interrupt_func_p | signal_func_p)
581                 {
582                   fprintf (file,
583                            "cli" CR_TAB
584                            AS2 (out,__SP_L__,r28) CR_TAB
585                            AS2 (out,__SP_H__,r29) "\n");
586                   epilogue_size += 3;
587                 }
588               else if (TARGET_NO_INTERRUPTS)
589                 {
590                   fprintf (file,
591                            AS2 (out,__SP_L__,r28) CR_TAB
592                            AS2 (out,__SP_H__,r29) "\n");
593                   epilogue_size += 2;
594                 }
595               else
596                 {
597                   fprintf (file,
598                            AS2 (in,__tmp_reg__,__SREG__) CR_TAB
599                            "cli" CR_TAB
600                            AS2 (out,__SP_L__,r28) CR_TAB
601                            AS2 (out,__SREG__,__tmp_reg__) CR_TAB
602                            AS2 (out,__SP_H__,r29) "\n");
603                   epilogue_size += 5;
604                 }
605             }
606           fprintf (file, "\t"
607                    AS1 (pop,r29) CR_TAB
608                    AS1 (pop,r28) "\n");
609           epilogue_size += 2;
610         }
611
612       for (reg = 31; reg >= 0; --reg)
613         {
614           if ((!leaf_func_p
615                && (call_used_regs[reg]
616                    && (interrupt_func_p || signal_func_p)
617                    && !(reg == TMP_REGNO || reg == ZERO_REGNO)))
618               || (regs_ever_live[reg]
619                   && (!call_used_regs[reg]
620                       || interrupt_func_p || signal_func_p)
621                   && ! (frame_pointer_needed
622                         && (reg == REG_Y || reg == (REG_Y+1)))))
623             {
624               fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
625               ++epilogue_size;
626             }
627         }
628       
629       if (interrupt_func_p | signal_func_p)
630         {
631           fprintf (file, "\t"
632                    AS1 (pop,__tmp_reg__)      CR_TAB
633                    AS2 (out,__SREG__,__tmp_reg__) CR_TAB
634                    AS1 (pop,__tmp_reg__)      CR_TAB
635                    AS1 (pop,__zero_reg__)     "\n");
636           epilogue_size += 4;
637           fprintf (file, "\treti\n");
638         }
639       else
640         fprintf (file, "\tret\n");
641       ++epilogue_size;
642     }
643   
644   fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
645   fprintf (file, "/* function %s size %d (%d) */\n", current_function_name,
646            prologue_size + function_size + epilogue_size, function_size);
647   commands_in_file += prologue_size + function_size + epilogue_size;
648   commands_in_prologues += prologue_size;
649   commands_in_epilogues += epilogue_size;
650 }
651
652
653 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
654    machine for a memory operand of mode MODE.  */
655
656 int
657 legitimate_address_p (mode, x, strict)
658      enum machine_mode mode;
659      rtx x;
660      int strict;
661 {
662   int r = 0;
663   if (TARGET_ALL_DEBUG)
664     {
665       fprintf (stderr, "mode: (%s) %s %s %s %s:",
666                GET_MODE_NAME(mode),
667                strict ? "(strict)": "",
668                reload_completed ? "(reload_completed)": "",
669                reload_in_progress ? "(reload_in_progress)": "",
670                reg_renumber ? "(reg_renumber)" : "");
671       if (GET_CODE (x) == PLUS
672           && REG_P (XEXP (x, 0))
673           && GET_CODE (XEXP (x, 1)) == CONST_INT
674           && INTVAL (XEXP (x, 1)) >= 0
675           && INTVAL (XEXP (x, 1)) <= (64 - GET_MODE_SIZE (mode))
676           && reg_renumber
677           )
678         fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
679                  true_regnum (XEXP (x, 0)));
680       debug_rtx (x);
681     }
682   if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
683                     : REG_OK_FOR_BASE_NOSTRICT_P (x)))
684     r = 'R';
685   else if (CONSTANT_ADDRESS_P (x))
686     r = 'S';
687   else if (GET_CODE (x) == PLUS
688            && REG_P (XEXP (x, 0))
689            && GET_CODE (XEXP (x, 1)) == CONST_INT
690            && INTVAL (XEXP (x, 1)) >= 0)
691     {
692       int fit = INTVAL (XEXP (x, 1)) <= (64 - GET_MODE_SIZE (mode));
693       if (fit)
694         {
695           if (! strict
696               || REGNO (XEXP (x,0)) == REG_Y || REGNO (XEXP (x,0)) == REG_Z)
697               r = 'Q';
698           if (XEXP (x,0) == frame_pointer_rtx
699               || XEXP (x,0) == arg_pointer_rtx)
700             r = 'Q';
701         }
702       else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
703         r = 'U';
704     }
705   else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
706            && REG_P (XEXP (x, 0))
707            && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
708                : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
709     {
710       r = 'T';
711     }
712   if (TARGET_ALL_DEBUG)
713     {
714       fprintf (stderr, "   ret = %c\n", r);
715     }
716   return r;
717 }
718
719 /* Attempts to replace X with a valid
720    memory address for an operand of mode MODE  */
721
722 rtx
723 legitimize_address (x, oldx, mode)
724      rtx x;
725      rtx oldx;
726      enum machine_mode mode;
727 {
728   x = oldx;
729   if (TARGET_ALL_DEBUG)
730     {
731       fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
732       debug_rtx (oldx);
733     }
734   
735   if (GET_CODE (oldx) == PLUS
736       && REG_P (XEXP (oldx,0)))
737     {
738       if (REG_P (XEXP (oldx,1)))
739         x = force_reg (GET_MODE (oldx), oldx);
740       else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
741         {
742           int offs = INTVAL (XEXP (oldx,1));
743           if (frame_pointer_rtx != XEXP (oldx,0))
744             if (offs > 64 - GET_MODE_SIZE (mode))
745               {
746                 if (TARGET_ALL_DEBUG)
747                   fprintf (stderr, "force_reg (big offset)\n");
748                 x = force_reg (GET_MODE (oldx), oldx);
749               }
750         }
751     }
752   return x;
753 }
754
755
756 /* Return a pointer register name as a string */
757
758 static char *
759 ptrreg_to_str (regno)
760      int regno;
761 {
762   switch (regno)
763     {
764     case REG_X: return "X";
765     case REG_Y: return "Y";
766     case REG_Z: return "Z";
767     default:
768       fatal ("register r%d isn't a pointer\n", regno);
769     }
770   return NULL;
771 }
772
773 /* Return the condition name as a string.
774    Used in conditional jump constructing  */
775
776 static char *
777 cond_string (code)
778      enum rtx_code code;
779 {
780   switch (code)
781     {
782     case NE:
783       return "ne";
784     case EQ:
785       return "eq";
786     case GE:
787       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
788         return "pl";
789       else
790         return "ge";
791     case GT:
792       fatal ("Internal compiler bug: command `bgt'");
793     case LE:
794       fatal ("Internal compiler bug: command `ble'");
795     case LT:
796       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
797         return "mi";
798       else
799         return "lt";
800     case GEU:
801       return "sh";
802     case GTU:
803       fatal ("Internal compiler bug: command `bgtu'");
804     case LEU:
805       fatal ("Internal compiler bug: command `bleu'");
806     case LTU:
807       return "lo";
808     default:
809       abort ();
810     }
811 }
812
813 /* Output ADDR to FILE as address */
814
815 void
816 print_operand_address (file, addr)
817      FILE *file;
818      rtx addr;
819 {
820   switch (GET_CODE (addr))
821     {
822     case REG:
823       fprintf (file, ptrreg_to_str (REGNO (addr)));
824       break;
825
826     case PRE_DEC:
827       fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
828       break;
829
830     case POST_INC:
831       fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
832       break;
833
834     default:
835       if (CONSTANT_ADDRESS_P (addr)
836           && (SYMBOL_REF_FLAG (addr) || GET_CODE (addr) == LABEL_REF))
837         {
838           fprintf (file, "pm(");
839           output_addr_const (file,addr);
840           fprintf (file ,")");
841         }
842       else
843         output_addr_const (file, addr);
844     }
845 }
846
847
848 /* Output X as assembler operand to file FILE */
849      
850 void
851 print_operand (file, x, code)
852      FILE *file;
853      rtx x;
854      int code;
855 {
856   int abcd = 0;
857
858   if (code >= 'A' && code <= 'D')
859     abcd = code - 'A';
860
861   if (REG_P (x))
862     {
863       if (x == zero_reg_rtx)
864         fprintf (file,"__zero_reg__");
865       else
866         fprintf (file, reg_names[true_regnum (x) + abcd]);
867     }
868   else if (GET_CODE (x) == CONST_INT)
869     fprintf (file, "%d", INTVAL (x) + abcd);
870   else if (GET_CODE (x) == MEM)
871     {
872       rtx addr = XEXP (x,0);
873       if (code == 'K')
874         {
875           if (CONSTANT_P (addr))
876             putc ('s', file);
877           else if (GET_CODE (addr) == PLUS)
878             putc ('d', file);
879         }
880       else if (CONSTANT_P (addr) && abcd)
881         {
882           fputc ('(', file);
883           output_address (addr);
884           fprintf (file, ")+%d", abcd);
885         }
886       else if (GET_CODE (addr) == PLUS)
887         {
888           print_operand_address (file, XEXP (addr,0));
889           if (REGNO (XEXP (addr, 0)) == REG_X)
890             fatal_insn ("Internal compiler bug.\nBad address:"
891                         ,addr);
892           fputc ('+', file);
893           print_operand (file, XEXP (addr,1), code);
894         }
895       else
896         print_operand_address (file, addr);
897     }
898   else if (GET_CODE (x) == CONST_DOUBLE)
899     {
900       long val;
901       REAL_VALUE_TYPE rv;
902       if (GET_MODE (x) != SFmode)
903         fatal_insn ("Internal compiler bug. Unknown mode:", x);
904       REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
905       REAL_VALUE_TO_TARGET_SINGLE (rv, val);
906       asm_fprintf (file, "0x%x", val);
907     }
908   else if (code == 'j')
909     asm_fprintf (file, cond_string (GET_CODE (x)));
910   else if (code == 'k')
911     asm_fprintf (file, cond_string (reverse_condition (GET_CODE (x))));
912   else
913     print_operand_address (file, x);
914 }
915
916 /* Recognise operand OP of mode MODE used in call instructions */
917
918 int
919 call_insn_operand (op, mode)
920      rtx op;
921      enum machine_mode mode ATTRIBUTE_UNUSED;
922 {
923   if (GET_CODE (op) == MEM)
924     {
925       rtx inside = XEXP (op, 0);
926       if (register_operand (inside, Pmode))
927         return 1;
928       if (CONSTANT_ADDRESS_P (inside))
929         return 1;
930     }
931   return 0;
932 }
933
934 /* Update the condition code in the INSN.  */
935
936 void
937 notice_update_cc (body, insn)
938      rtx body ATTRIBUTE_UNUSED;
939      rtx insn;
940 {
941   switch (get_attr_cc (insn))
942     {
943     case CC_NONE:
944       /* Insn does not affect CC at all.  */
945       break;
946
947     case CC_SET_N:
948       CC_STATUS_INIT;
949       break;
950
951     case CC_SET_ZN:
952       {
953         rtx set = single_set (insn);
954         CC_STATUS_INIT;
955         if (set)
956           {
957             cc_status.flags |= CC_NO_OVERFLOW;
958             cc_status.value1 = SET_DEST (set);
959           }
960       }
961       break;
962
963     case CC_SET_CZN:
964       /* Insn sets the Z,N,C flags of CC to recog_operand[0].
965          The V flag may or may not be known but that's ok because
966          alter_cond will change tests to use EQ/NE.  */
967       {
968         rtx set = single_set (insn);
969         CC_STATUS_INIT;
970         if (set)
971           {
972             cc_status.value1 = SET_DEST (set);
973             cc_status.flags |= CC_OVERFLOW_UNUSABLE;
974           }
975       }
976       break;
977
978     case CC_COMPARE:
979       {
980         rtx set = single_set (insn);
981         CC_STATUS_INIT;
982         if (set)
983           cc_status.value1 = SET_SRC (set);
984       }
985       break;
986
987     case CC_CLOBBER:
988       /* Insn doesn't leave CC in a usable state.  */
989       CC_STATUS_INIT;
990       break;
991     }
992 }
993
994 /* Return maximum number of consecutive registers of
995    class CLASS needed to hold a value of mode MODE.  */
996
997 int
998 class_max_nregs (class, mode)
999      enum reg_class class ATTRIBUTE_UNUSED;
1000      enum machine_mode mode;
1001 {
1002   return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1003 }
1004
1005 /* Choose mode for jump insn:
1006    1 - relative jump in range -63 <= x <= 62 ;
1007    2 - relative jump in range -2046 <= x <= 2045 ;
1008    3 - absolute jump (only for ATmega[16]03).  */
1009
1010 int
1011 avr_jump_mode (x,insn)
1012      rtx x;                     /* jump operand */
1013      rtx insn;                  /* jump insn */
1014 {
1015   int dest_addr = insn_addresses[INSN_UID (GET_MODE (x) == LABEL_REF
1016                                            ? XEXP (x, 0) : x)];
1017   int cur_addr = insn_addresses[INSN_UID (insn)];
1018   int jump_distance = cur_addr - dest_addr;
1019   
1020   if (-63 <= jump_distance && jump_distance <= 62)
1021     return 1;
1022   else if (-2046 <= jump_distance && jump_distance <= 2045)
1023     return 2;
1024   else if (AVR_MEGA)
1025     return 3;
1026   
1027   return 2;
1028 }
1029
1030 /* return a AVR condition jump commands.
1031  LEN is a number returned by avr_jump_mode function.  */
1032
1033 char *
1034 ret_cond_branch (cond,len)
1035      RTX_CODE cond;
1036      int len;
1037 {
1038   switch (cond)
1039     {
1040     case GT:
1041       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1042         return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1043                             AS1 (brpl,%0)) :
1044                 len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1045                             AS1 (brmi,_PC_+2) CR_TAB
1046                             AS1 (rjmp,%0)) :
1047                 (AS1 (breq,_PC_+6) CR_TAB
1048                  AS1 (brmi,_PC_+4) CR_TAB
1049                  AS1 (jmp,%0)));
1050           
1051       else
1052         return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1053                             AS1 (brge,%0)) :
1054                 len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1055                             AS1 (brlt,_PC_+2) CR_TAB
1056                             AS1 (rjmp,%0)) :
1057                 (AS1 (breq,_PC_+6) CR_TAB
1058                  AS1 (brlt,_PC_+4) CR_TAB
1059                  AS1 (jmp,%0)));
1060     case GTU:
1061       return (len == 1 ? (AS1 (breq,_PC_+2) CR_TAB
1062                           AS1 (brsh,%0)) :
1063               len == 2 ? (AS1 (breq,_PC_+4) CR_TAB
1064                           AS1 (brlo,_PC_+2) CR_TAB
1065                           AS1 (rjmp,%0)) :
1066               (AS1 (breq,_PC_+6) CR_TAB
1067                AS1 (brlo,_PC_+4) CR_TAB
1068                AS1 (jmp,%0)));
1069     case LE:
1070       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1071         return (len == 1 ? (AS1 (breq,%0) CR_TAB
1072                             AS1 (brmi,%0)) :
1073                 len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1074                             AS1 (brpl,_PC_+2) CR_TAB
1075                             AS1 (rjmp,%0)) :
1076                 (AS1 (breq,_PC_+2) CR_TAB
1077                  AS1 (brpl,_PC_+4) CR_TAB
1078                  AS1 (jmp,%0)));
1079       else
1080         return (len == 1 ? (AS1 (breq,%0) CR_TAB
1081                             AS1 (brlt,%0)) :
1082                 len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1083                             AS1 (brge,_PC_+2) CR_TAB
1084                             AS1 (rjmp,%0)) :
1085                 (AS1 (breq,_PC_+2) CR_TAB
1086                  AS1 (brge,_PC_+4) CR_TAB
1087                  AS1 (jmp,%0)));
1088     case LEU:
1089       return (len == 1 ? (AS1 (breq,%0) CR_TAB
1090                           AS1 (brlo,%0)) :
1091               len == 2 ? (AS1 (breq,_PC_+2) CR_TAB
1092                           AS1 (brsh,_PC_+2) CR_TAB
1093                           AS1 (rjmp,%0)) :
1094               (AS1 (breq,_PC_+2) CR_TAB
1095                AS1 (brsh,_PC_+4) CR_TAB
1096                AS1 (jmp,%0)));
1097     default:
1098       switch (len)
1099         {
1100         case 1:
1101           return AS1 (br%j1,%0);
1102         case 2:
1103           return (AS1 (br%k1,_PC_+2) CR_TAB
1104                   AS1 (rjmp,%0));
1105         default:
1106           return (AS1 (br%k1,_PC_+4) CR_TAB
1107                   AS1 (jmp,%0));
1108         }
1109     }
1110   return "";
1111 }
1112
1113 /* Predicate function for immediate operand which fits to byte (8bit) */
1114
1115 int
1116 byte_immediate_operand (op, mode)
1117      register rtx op;
1118      enum machine_mode mode ATTRIBUTE_UNUSED;
1119 {
1120   return (GET_CODE (op) == CONST_INT
1121           && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1122 }
1123
1124 /* Output all insn addresses and their sizes into the assembly language
1125    output file.  This is helpful for debugging whether the length attributes
1126    in the md file are correct.
1127    Output insn cost for next insn.  */
1128
1129 void
1130 final_prescan_insn (insn, operand, num_operands)
1131      rtx insn, *operand ATTRIBUTE_UNUSED;
1132      int num_operands ATTRIBUTE_UNUSED;
1133 {
1134   int uid = INSN_UID (insn);
1135
1136   if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1137     {
1138       fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n", insn_addresses[uid],
1139                insn_addresses[uid] - last_insn_address,
1140                rtx_cost (PATTERN (insn),INSN));
1141     }
1142   last_insn_address = insn_addresses[uid];
1143
1144   if (TARGET_RTL_DUMP)
1145     {
1146       fprintf (asm_out_file, "/*****************\n");
1147       print_rtl_single (asm_out_file, insn);
1148       fprintf (asm_out_file, "*****************/\n");
1149     }
1150 }
1151
1152 /* return 1 if undefined,
1153    1 if always true or always false  */
1154
1155 int
1156 avr_simplify_comparision_p (mode, operator, x)
1157      enum machine_mode mode;
1158      RTX_CODE operator;
1159      rtx x;
1160 {
1161   unsigned int max = (mode == QImode ? 0xff :
1162                       mode == HImode ? 0xffff :
1163                       mode == SImode ? 0xffffffffU : 0);
1164   if (max && operator && GET_CODE (x) == CONST_INT)
1165     {
1166       if (unsigned_condition (operator) != operator)
1167         max >>= 1;
1168
1169       if (max != (INTVAL (x) & max)
1170           && INTVAL (x) != 0xff)
1171         return 1;
1172     }
1173   return 0;
1174 }
1175
1176
1177 /* Returns nonzero if REGNO is the number of a hard
1178    register in which function arguments are sometimes passed.  */
1179
1180 int
1181 function_arg_regno_p(r)
1182      int r;
1183 {
1184   return (r >= 8 && r <= 25);
1185 }
1186
1187 /* Initializing the variable cum for the state at the beginning
1188    of the argument list.  */
1189
1190 void
1191 init_cumulative_args (cum, fntype, libname, indirect)
1192      CUMULATIVE_ARGS *cum;
1193      tree fntype;
1194      rtx libname;
1195      int indirect ATTRIBUTE_UNUSED;
1196 {
1197   cum->nregs = 18;
1198   cum->regno = FIRST_CUM_REG;
1199   if (!libname)
1200     {
1201       int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1202                     && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1203                         != void_type_node));
1204       if (stdarg)
1205         cum->nregs = 0;
1206     }
1207 }
1208
1209 /* Controls whether a function argument is passed
1210    in a register, and which register. */
1211
1212 rtx
1213 function_arg (cum, mode, type, named)
1214      CUMULATIVE_ARGS *cum;
1215      enum machine_mode mode;
1216      tree type;
1217      int named ATTRIBUTE_UNUSED;
1218 {
1219   int bytes;
1220
1221   bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1222
1223   if (cum->nregs && bytes <= cum->nregs)
1224     return gen_rtx (REG, mode, cum->regno - bytes);
1225   return NULL_RTX;
1226 }
1227
1228 /* Update the summarizer variable CUM to advance past an argument
1229    in the argument list.  */
1230    
1231 void
1232 function_arg_advance (cum, mode, type, named)
1233      CUMULATIVE_ARGS *cum;      /* current arg information */
1234      enum machine_mode mode;    /* current arg mode */
1235      tree type;                 /* type of the argument or 0 if lib support */
1236      int named ATTRIBUTE_UNUSED; /* whether or not the argument was named */
1237 {
1238   int bytes;
1239
1240   bytes = (mode == BLKmode ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
1241   cum->nregs -= bytes;
1242   cum->regno -= bytes;
1243
1244   if (cum->nregs <= 0)
1245     {
1246       cum->nregs = 0;
1247       cum->regno = FIRST_CUM_REG;
1248     }
1249
1250   return;
1251 }
1252
1253 /***********************************************************************
1254   Functions for outputting various mov's for a various modes
1255 ************************************************************************/
1256 char *
1257 out_movqi_r_mr (insn, op, l)
1258      rtx insn;
1259      rtx op[];
1260      int *l; /* instruction length */
1261 {
1262   /* We handle CONSTANT_ADDRESS_P case in adjust_insn_length */
1263   if (l) *l=1;
1264   if (GET_CODE (op[1]) == MEM)
1265     {
1266       rtx x = XEXP (op[1],0);
1267       if (GET_CODE (x) == PLUS
1268           && REG_P (XEXP (x,0))
1269           && GET_CODE (XEXP (x,1)) == CONST_INT)
1270         {
1271           if((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (op[1]))) >= 63)
1272             {
1273               int disp = INTVAL (XEXP (x,1));
1274               if (REGNO (XEXP (x,0)) != REG_Y)
1275                 fatal_insn ("Incorrect insn:",insn);
1276               if (disp <= 63 + 64 - GET_MODE_SIZE (GET_MODE (op[1])))
1277                 {
1278                   if (l)
1279                     *l = 3;
1280                   else
1281                     {
1282                       op[4] = GEN_INT (disp - 63);
1283                       return (AS2 (adiw, r28, %4) CR_TAB
1284                               AS2 (ldd, %0,Y+63)  CR_TAB
1285                               AS2 (sbiw, r28, %4));
1286                     }
1287                 }
1288               else
1289                 {
1290                   op[4] = XEXP (x,1);
1291                   if (l)
1292                     *l = 5;
1293                   else
1294                     return (AS2 (subi, r28, lo8(-%4))  CR_TAB
1295                             AS2 (sbci, r29, hi8(-%4)) CR_TAB
1296                             AS2 (ld, %0,Y)              CR_TAB
1297                             AS2 (subi, r28, lo8(%4))   CR_TAB
1298                             AS2 (sbci, r29, hi8(%4)));
1299                 }
1300             }
1301           else if (REGNO (XEXP (x,0)) == REG_X)
1302             {
1303               /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1304                  it but I have this situation with extremal optimizing options
1305               */
1306               if (l)
1307                 *l=3;
1308               else
1309                 {
1310                   output_asm_insn (AS2 (adiw, r26, %0),&XEXP (x,1));
1311                   output_asm_insn (AS2 (ld ,%0,X),op);
1312                   if (!reg_overlap_mentioned_p (op[0],XEXP (x,0)))
1313                     output_asm_insn (AS2 (sbiw, r26, %0),&XEXP (x,1));
1314                 }
1315               return "";
1316             }
1317         }
1318     }
1319   return AS2 (ld%K1,%0,%1);
1320 }
1321
1322 char *
1323 out_movhi_r_mr (insn, op, l)
1324      rtx insn;
1325      rtx op[];
1326      int *l; /* instruction length */
1327 {
1328   int reg_dest = true_regnum (op[0]);
1329   int reg_base = true_regnum (XEXP (op[1],0));
1330   int len_p = 1,tmp;
1331   int *real_l=l;
1332
1333   if (!l)
1334     l = &tmp, len_p = 0;
1335
1336   if (reg_base > 0)
1337     {
1338       if (reg_dest == reg_base)         /* R = (R) */
1339         return *l=3, (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1340                       AS2 (ld,%B0,%1) CR_TAB
1341                       AS2 (mov,%A0,__tmp_reg__));
1342       else if (reg_base == REG_X)        /* (R26) */
1343         {
1344           if (reg_unused_after (insn, XEXP (op[1],0)))
1345             return *l=2, (AS2 (ld,%A0,X+) CR_TAB
1346                           AS2 (ld,%B0,X));
1347           else
1348             return *l=3, (AS2 (ld,%A0,X+) CR_TAB
1349                           AS2 (ld,%B0,X) CR_TAB
1350                           AS2 (sbiw,r26,1));
1351         }
1352       else                      /* (R)  */
1353         return  *l=2, (AS2 (ld,%A0,%1)    CR_TAB
1354                        AS2 (ldd,%B0,%1+1));
1355     }
1356   else if (GET_CODE (XEXP (op[1],0)) == PLUS) /* (R + i) */
1357     {
1358       int disp = INTVAL(XEXP (XEXP (op[1],0), 1));
1359       int reg_base = true_regnum (XEXP (XEXP (op[1],0), 0));
1360       
1361       if (disp > 64 - GET_MODE_SIZE (GET_MODE (op[1])))
1362         {
1363           rtx x = XEXP (op[1],0);
1364           if (REGNO (XEXP (x,0)) != REG_Y)
1365             fatal_insn ("Incorrect insn:",insn);
1366           if (disp <= 63 + 64 - GET_MODE_SIZE (GET_MODE (op[1])))
1367             {
1368               op[4] = GEN_INT (disp - 62);
1369               return *l=4, (AS2 (adiw, r28, %4) CR_TAB
1370                             AS2 (ldd, %A0,Y+62)       CR_TAB
1371                             AS2 (ldd, %B0,Y+63)     CR_TAB
1372                             AS2 (sbiw, r28, %4));
1373             }
1374           else
1375             {
1376               op[4] = XEXP (x,1);
1377               return *l=6, (AS2 (subi, r28, lo8(-%4))  CR_TAB
1378                             AS2 (sbci, r29, hi8(-%4)) CR_TAB
1379                             AS2 (ld, %A0,Y)             CR_TAB
1380                             AS2 (ldd, %B0,Y+1)          CR_TAB
1381                             AS2 (subi, r28, lo8(%4))   CR_TAB
1382                             AS2 (sbci, r29, hi8(%4)));
1383             }
1384         }
1385       if (reg_base == REG_X)
1386         {
1387           /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1388              it but I have this situation with extremal optimization options
1389            */
1390           rtx ops[1];
1391           ops[0] = XEXP (XEXP (op[1],0), 1);
1392           if (real_l)
1393             *l = 4;
1394           else if (reg_base == reg_dest)
1395             {
1396               output_asm_insn (AS2 (adiw, r26, %0), ops);
1397               output_asm_insn (AS2 (ld , __tmp_reg__, X+), op);
1398               output_asm_insn (AS2 (ld , %B0, X), op);
1399               output_asm_insn (AS2 (mov, %A0, __tmp_reg__),op);
1400             }
1401           else
1402             {
1403               output_asm_insn (AS2 (adiw, r26, %0), ops);
1404               output_asm_insn (AS2 (ld , %A0, X+), op);
1405               output_asm_insn (AS2 (ld , %B0, X), op);
1406               if (INTVAL (ops[0]) == 63)
1407                 {
1408                   output_asm_insn (AS2 (subi, r26, %0+1), ops);
1409                   output_asm_insn (AS2 (sbci, r26, 0), ops);
1410                 }
1411               else
1412                 output_asm_insn (AS2 (sbiw, r26, %0+1), ops);
1413             }
1414           return "";
1415         }
1416       
1417       if (reg_base == reg_dest) 
1418         return *l=3, (AS2 (ldd,__tmp_reg__,%A1)    CR_TAB
1419                       AS2 (ldd,%B0,%B1)   CR_TAB
1420                       AS2 (mov,%A0,__tmp_reg__));
1421       else
1422         return *l=2, (AS2 (ldd,%A0,%A1)    CR_TAB
1423                       AS2 (ldd,%B0,%B1));
1424     }
1425   else if (GET_CODE (XEXP (op[1],0)) == PRE_DEC) /* (--R) */
1426     {
1427       if (reg_overlap_mentioned_p (op[0], XEXP (XEXP (op[1],0),0)))
1428         {
1429           debug_rtx (insn);
1430           fatal ("Internal error. Incorrect insn.");
1431         }
1432       return *l=2, (AS2 (ld,%B0,%1) CR_TAB
1433                     AS2 (ld,%A0,%1));
1434     }
1435   else if (GET_CODE (XEXP (op[1],0)) == POST_INC) /* (R++) */
1436     {
1437       if (reg_overlap_mentioned_p (op[0], XEXP (XEXP (op[1],0),0)))
1438         {
1439           debug_rtx (insn);
1440           fatal ("Internal error. Incorrect insn.");
1441         }
1442       return *l=2, (AS2 (ld,%A0,%1)  CR_TAB
1443                     AS2 (ld,%B0,%1));
1444     }
1445   else if (CONSTANT_ADDRESS_P (XEXP (op[1],0)))
1446         return *l=4, (AS2 (lds,%A0,%A1) CR_TAB
1447                       AS2 (lds,%B0,%B1));
1448   fatal_insn ("Unknown move insn:",insn);
1449   return "";
1450 }
1451
1452 char *
1453 out_movsi_r_mr (insn,op,l)
1454      rtx insn;
1455      rtx op[];
1456      int *l; /* instruction length */
1457 {
1458   int reg_dest=true_regnum (op[0]);
1459   int reg_base=true_regnum (XEXP (op[1],0));
1460   int tmp;
1461   if (!l)
1462     l=&tmp;
1463   if (reg_base > 0)
1464     {
1465       if (reg_base == REG_X)        /* (R26) */
1466         {
1467           if (reg_dest == REG_X)
1468             return *l=6, (AS2 (adiw,r26,3) CR_TAB
1469                           AS2 (ld,%D0,X)  CR_TAB
1470                           AS2 (ld,%C0,-X) CR_TAB
1471                           AS2 (ld,__tmp_reg__,-X)  CR_TAB
1472                           AS2 (ld,%A0,-X)  CR_TAB
1473                           AS2 (mov,%B0,__tmp_reg__));
1474           else if (reg_dest == REG_X - 2)
1475             return *l=5, (AS2 (ld,%A0,X+)  CR_TAB
1476                           AS2 (ld,%B0,X+) CR_TAB
1477                           AS2 (ld,__tmp_reg__,X+)  CR_TAB
1478                           AS2 (ld,%D0,X)  CR_TAB
1479                           AS2 (mov,%C0,__tmp_reg__));
1480           else if (reg_unused_after (insn,XEXP (op[1],0)))
1481             return  *l=4, (AS2 (ld,%A0,X+)  CR_TAB
1482                            AS2 (ld,%B0,X+) CR_TAB
1483                            AS2 (ld,%C0,X+) CR_TAB
1484                            AS2 (ld,%D0,X));
1485           else
1486             return  *l=5, (AS2 (ld,%A0,X+)  CR_TAB
1487                            AS2 (ld,%B0,X+) CR_TAB
1488                            AS2 (ld,%C0,X+) CR_TAB
1489                            AS2 (ld,%D0,X)  CR_TAB
1490                            AS2 (sbiw,r26,3));
1491         }
1492       else
1493         {
1494           if (reg_dest == reg_base)
1495             return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
1496                           AS2 (ldd,%C0,%1+2) CR_TAB
1497                           AS2 (ldd,__tmp_reg__,%1+1)  CR_TAB
1498                           AS2 (ld,%A0,%1)  CR_TAB
1499                           AS2 (mov,%B0,__tmp_reg__));
1500           else if (reg_base == reg_dest + 2)
1501             return *l=5, (AS2 (ld ,%A0,%1)    CR_TAB
1502                           AS2 (ldd,%B0,%1+1) CR_TAB
1503                           AS2 (ldd,__tmp_reg__,%1+2)  CR_TAB
1504                           AS2 (ldd,%D0,%1+3) CR_TAB
1505                           AS2 (mov,%C0,__tmp_reg__));
1506           else
1507             return *l=4, (AS2 (ld ,%A0,%1)   CR_TAB
1508                           AS2 (ldd,%B0,%1+1) CR_TAB
1509                           AS2 (ldd,%C0,%1+2) CR_TAB
1510                           AS2 (ldd,%D0,%1+3));
1511         }
1512     }
1513   else if (GET_CODE (XEXP (op[1],0)) == PLUS) /* (R + i) */
1514     {
1515       int disp = INTVAL(XEXP (XEXP (op[1],0), 1));
1516       
1517       if (disp > 64 - GET_MODE_SIZE (GET_MODE (op[1])))
1518         {
1519           rtx x = XEXP (op[1],0);
1520           if (REGNO (XEXP (x,0)) != REG_Y)
1521             fatal_insn ("Incorrect insn:",insn);
1522           if (disp <= 63 + 64 - GET_MODE_SIZE (GET_MODE (op[1])))
1523             {
1524               op[4] = GEN_INT (disp - 60);
1525               return *l=6,(AS2 (adiw, r28, %4) CR_TAB
1526                            AS2 (ldd, %A0,Y+60)       CR_TAB
1527                            AS2 (ldd, %B0,Y+61)     CR_TAB
1528                            AS2 (ldd, %C0,Y+62)     CR_TAB
1529                            AS2 (ldd, %D0,Y+63)     CR_TAB
1530                            AS2 (sbiw, r28, %4));
1531             }
1532           else
1533             {
1534               op[4] = XEXP (x,1);
1535               return *l=8,(AS2 (subi, r28, lo8(-%4))  CR_TAB
1536                            AS2 (sbci, r29, hi8(-%4)) CR_TAB
1537                            AS2 (ld, %A0,Y)             CR_TAB
1538                            AS2 (ldd, %B0,Y+1)          CR_TAB
1539                            AS2 (ldd, %C0,Y+2)          CR_TAB
1540                            AS2 (ldd, %D0,Y+3)          CR_TAB
1541                            AS2 (subi, r28, lo8(%4))   CR_TAB
1542                            AS2 (sbci, r29, hi8(%4)));
1543             }
1544         }
1545
1546       reg_base = true_regnum (XEXP (XEXP (op[1],0), 0));
1547       if (reg_dest == reg_base)
1548         return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
1549                       AS2 (ldd,%C0,%C1) CR_TAB
1550                       AS2 (ldd,__tmp_reg__,%B1)  CR_TAB
1551                       AS2 (ldd,%A0,%A1) CR_TAB
1552                       AS2 (mov,%B0,__tmp_reg__));
1553       else if (reg_dest == reg_base - 2)
1554         return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
1555                       AS2 (ldd,%B0,%B1) CR_TAB
1556                       AS2 (ldd,__tmp_reg__,%C1)  CR_TAB
1557                       AS2 (ldd,%D0,%D1) CR_TAB
1558                       AS2 (mov,%C0,__tmp_reg__));
1559       return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
1560                     AS2 (ldd,%B0,%B1) CR_TAB
1561                     AS2 (ldd,%C0,%C1) CR_TAB
1562                     AS2 (ldd,%D0,%D1));
1563     }
1564   else if (GET_CODE (XEXP (op[1],0)) == PRE_DEC) /* (--R) */
1565     return *l=4, (AS2 (ld,%D0,%1) CR_TAB
1566                   AS2 (ld,%C0,%1) CR_TAB
1567                   AS2 (ld,%B0,%1) CR_TAB
1568                   AS2 (ld,%A0,%1));
1569   else if (GET_CODE (XEXP (op[1],0)) == POST_INC) /* (R++) */
1570     return *l=4, (AS2 (ld,%A0,%1) CR_TAB
1571                   AS2 (ld,%B0,%1) CR_TAB
1572                   AS2 (ld,%C0,%1) CR_TAB
1573                   AS2 (ld,%D0,%1));
1574   else if (CONSTANT_ADDRESS_P (XEXP (op[1],0)))
1575       return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
1576                     AS2 (lds,%B0,%B1) CR_TAB
1577                     AS2 (lds,%C0,%C1) CR_TAB
1578                     AS2 (lds,%D0,%D1));
1579     
1580   fatal_insn ("Unknown move insn:",insn);
1581   return "";
1582 }
1583
1584 char *
1585 out_movsi_mr_r (insn,op,l)
1586      rtx insn;
1587      rtx op[];
1588      int *l;
1589 {
1590   int reg_base = true_regnum (XEXP (op[0],0));
1591   int reg_dest = true_regnum (op[1]);
1592   int tmp;
1593   if (!l)
1594     l = &tmp;
1595   if (CONSTANT_ADDRESS_P (XEXP (op[0],0)))
1596     return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
1597                  AS2 (sts,%B0,%B1) CR_TAB
1598                  AS2 (sts,%C0,%C1) CR_TAB
1599                  AS2 (sts,%D0,%D1));
1600   if (reg_base > 0)                 /* (r) */
1601     {
1602       if (reg_base == REG_X)                /* (R26) */
1603         {
1604           if (reg_dest == REG_X)
1605             {
1606               if (reg_unused_after (insn,XEXP (op[0],0)))
1607                 return *l=5, (AS2 (mov,__tmp_reg__,%B1) CR_TAB
1608                               AS2 (st,%0+,%A1) CR_TAB
1609                               AS2 (st,%0+,__tmp_reg__)  CR_TAB
1610                               AS2 (st,%0+,%C1) CR_TAB
1611                               AS2 (st,%0,%D1));
1612               else
1613                 return *l=6, (AS2 (mov,__tmp_reg__,%B1) CR_TAB
1614                               AS2 (st,%0+,%A1) CR_TAB
1615                               AS2 (st,%0+,__tmp_reg__)  CR_TAB
1616                               AS2 (st,%0+,%C1) CR_TAB
1617                               AS2 (st,%0,%D1)  CR_TAB
1618                               AS2 (sbiw,r26,3));
1619             }
1620           else if (reg_base == reg_dest+2)
1621             {
1622               if (reg_unused_after (insn,XEXP (op[0],0)))
1623                 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
1624                               AS2 (mov,__tmp_reg__,%D1) CR_TAB
1625                               AS2 (st,%0+,%A1) CR_TAB
1626                               AS2 (st,%0+,%B1) CR_TAB
1627                               AS2 (st,%0+,__zero_reg__)  CR_TAB
1628                               AS2 (st,%0,__tmp_reg__)   CR_TAB
1629                               AS1 (clr,__zero_reg__));
1630               else
1631                 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
1632                               AS2 (mov,__tmp_reg__,%D1) CR_TAB
1633                               AS2 (st,%0+,%A1) CR_TAB
1634                               AS2 (st,%0+,%B1) CR_TAB
1635                               AS2 (st,%0+,__zero_reg__)  CR_TAB
1636                               AS2 (st,%0,__tmp_reg__)   CR_TAB
1637                               AS1 (clr,__zero_reg__)     CR_TAB
1638                               AS2 (sbiw,r26,3));
1639             }
1640           return *l=5, (AS2 (st,%0+,%A1)  CR_TAB
1641                         AS2 (st,%0+,%B1) CR_TAB
1642                         AS2 (st,%0+,%C1) CR_TAB
1643                         AS2 (st,%0,%D1)  CR_TAB
1644                         AS2 (sbiw,r26,3));
1645         }
1646       else
1647         return *l=4, (AS2 (st,%0,%A1)    CR_TAB
1648                       AS2 (std,%0+1,%B1) CR_TAB
1649                       AS2 (std,%0+2,%C1) CR_TAB
1650                       AS2 (std,%0+3,%D1));
1651     }
1652   else if (GET_CODE (XEXP (op[0],0)) == PLUS) /* (R + i) */
1653     {
1654       int disp = INTVAL(XEXP (XEXP (op[0],0), 1));
1655       if (disp > 64 - GET_MODE_SIZE (GET_MODE (op[0])))
1656         {
1657           rtx x = XEXP (op[0],0);
1658           if (REGNO (XEXP (x,0)) != REG_Y)
1659             fatal_insn ("Incorrect insn:",insn);
1660           if (disp <= 63 + 64 - GET_MODE_SIZE (GET_MODE (op[0])))
1661             {
1662               op[4] = GEN_INT (disp - 60);
1663               return *l=6,(AS2 (adiw, r28, %4) CR_TAB
1664                            AS2 (std, Y+60,%A1)       CR_TAB
1665                            AS2 (std, Y+61,%B1)     CR_TAB
1666                            AS2 (std, Y+62,%C1)     CR_TAB
1667                            AS2 (std, Y+63,%D1)     CR_TAB
1668                            AS2 (sbiw, r28, %4));
1669             }
1670           else
1671             {
1672               op[4] = XEXP (x,1);
1673               return *l=8,(AS2 (subi, r28, lo8(-%4))  CR_TAB
1674                            AS2 (sbci, r29, hi8(-%4)) CR_TAB
1675                            AS2 (st, Y,%A1)             CR_TAB
1676                            AS2 (std, Y+1,%B1)          CR_TAB
1677                            AS2 (std, Y+2,%C1)          CR_TAB
1678                            AS2 (std, Y+3,%D1)          CR_TAB
1679                            AS2 (subi, r28, lo8(%4))   CR_TAB
1680                            AS2 (sbci, r29, hi8(%4)));
1681             }
1682         }
1683       return *l=4, (AS2 (std,%A0,%A1)    CR_TAB
1684                     AS2 (std,%B0,%B1) CR_TAB
1685                     AS2 (std,%C0,%C1) CR_TAB
1686                     AS2 (std,%D0,%D1));
1687     }
1688   else if (GET_CODE (XEXP (op[0],0)) == PRE_DEC) /* (--R) */
1689     return *l=4, (AS2 (st,%0,%D1) CR_TAB
1690                   AS2 (st,%0,%C1) CR_TAB
1691                   AS2 (st,%0,%B1) CR_TAB
1692                   AS2 (st,%0,%A1));
1693   else if (GET_CODE (XEXP (op[0],0)) == POST_INC) /* (R++) */
1694     return *l=4, (AS2 (st,%0,%A1)  CR_TAB
1695                   AS2 (st,%0,%B1) CR_TAB
1696                   AS2 (st,%0,%C1) CR_TAB
1697                   AS2 (st,%0,%D1));
1698   fatal_insn ("Unknown move insn:",insn);
1699   return "";
1700 }
1701
1702 char *
1703 output_movsisf(insn, operands, which_alternative)
1704      rtx insn;
1705      rtx operands[];
1706      int which_alternative;
1707 {
1708   rtx link;
1709   switch (which_alternative)
1710     {
1711     case 0: /* mov r,r */
1712       if (true_regnum (operands[0]) > true_regnum (operands[1]))
1713         return (AS2 (mov,%D0,%D1) CR_TAB
1714                 AS2 (mov,%C0,%C1) CR_TAB
1715                 AS2 (mov,%B0,%B1) CR_TAB
1716                 AS2 (mov,%A0,%A1));
1717       else
1718         return (AS2 (mov,%A0,%A1) CR_TAB
1719                 AS2 (mov,%B0,%B1) CR_TAB
1720                 AS2 (mov,%C0,%C1) CR_TAB
1721                 AS2 (mov,%D0,%D1));
1722     case 1:  /* mov r,L */
1723       return (AS1 (clr,%A0) CR_TAB
1724               AS1 (clr,%B0) CR_TAB
1725               AS1 (clr,%C0) CR_TAB
1726               AS1 (clr,%D0));
1727     case 2: /* mov r,d */
1728       if (GET_MODE (operands[0]) == SImode
1729           && operands[1] == const1_rtx
1730           && (link = find_reg_note (insn, REG_WAS_0, 0))
1731           /* Make sure the insn that stored the 0 is still present.  */
1732           && ! INSN_DELETED_P (XEXP (link, 0))
1733           && GET_CODE (XEXP (link, 0)) != NOTE
1734           /* Make sure cross jumping didn't happen here.  */
1735           && no_labels_between_p (XEXP (link, 0), insn)
1736           /* Make sure the reg hasn't been clobbered.  */
1737           && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
1738       /* Fastest way to change a 0 to a 1.  */
1739         return AS1 (inc,%A0 ; reg_was_0);
1740       return (AS2 (ldi,%A0,lo8(%1))  CR_TAB
1741               AS2 (ldi,%B0,hi8(%1)) CR_TAB
1742               AS2 (ldi,%C0,hlo8(%1)) CR_TAB
1743               AS2 (ldi,%D0,hhi8(%1)));
1744     case 3: /* mov r,m*/
1745     case 5:
1746       return out_movsi_r_mr (insn, operands, NULL);
1747     case 4: /* mov m,r*/
1748     case 6:
1749       {
1750         rtx save1=NULL;
1751         if (operands[1] == const0_rtx)
1752           {
1753             save1 = operands[1];
1754             operands[1] = zero_reg_rtx;
1755           }
1756         output_asm_insn (out_movsi_mr_r (insn,operands,NULL), operands);
1757         if (save1)
1758           operands[1] = save1;
1759       }
1760     }
1761   return "";
1762 }
1763
1764 char *
1765 out_movqi_mr_r (insn, op, l)
1766      rtx insn;
1767      rtx op[];
1768      int *l; /* instruction length */
1769 {
1770   if (l) *l=1;
1771
1772   if (GET_CODE (op[0]) == MEM)
1773     {
1774       rtx x = XEXP (op[0],0);
1775       if (GET_CODE (x) == PLUS
1776           && REG_P (XEXP (x,0))
1777           && GET_CODE (XEXP (x,1)) == CONST_INT)
1778         {
1779           if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (op[0]))) >= 63)
1780             {
1781               int disp = INTVAL (XEXP (x,1));
1782               if (REGNO (XEXP (x,0)) != REG_Y)
1783                 fatal_insn ("Incorrect insn:",insn);
1784               if (disp <= 63 + 64 - GET_MODE_SIZE (GET_MODE (op[0])))
1785                 {
1786                   if (l)
1787                     *l = 3;
1788                   else
1789                     {
1790                       op[4] = GEN_INT (disp - 63);
1791                       return (AS2 (adiw, r28, %4) CR_TAB
1792                               AS2 (std, Y+63,%1)        CR_TAB
1793                               AS2 (sbiw, r28, %4));
1794                     }
1795                 }
1796               else
1797                 {
1798                   op[4] = XEXP (x,1);
1799                   if (l)
1800                     *l = 5;
1801                   else
1802                     return (AS2 (subi, r28, lo8(-%4))  CR_TAB
1803                             AS2 (sbci, r29, hi8(-%4)) CR_TAB
1804                             AS2 (st, Y,%1)              CR_TAB
1805                             AS2 (subi, r28, lo8(%4))   CR_TAB
1806                             AS2 (sbci, r29, hi8(%4)));
1807                 }
1808             }
1809           else if (REGNO (XEXP (x,0)) == REG_X)
1810             {
1811               if (l)
1812                 *l=4;
1813               else
1814                 {
1815                   int overlap_p = reg_overlap_mentioned_p (op[1],XEXP (x,0));
1816                   if (!overlap_p)
1817                     output_asm_insn (AS2 (mov, __tmp_reg__, %1),op);
1818                   output_asm_insn (AS2 (adiw, r26,%0),&XEXP (x,1));
1819                   if (overlap_p)
1820                     output_asm_insn (AS2 (st ,X,__tmp_reg__),op);
1821                   else
1822                     output_asm_insn (AS2 (st ,X,%1),op);
1823                   output_asm_insn (AS2 (sbiw ,r26,%0),&XEXP (x,1));
1824                 }
1825               return "";
1826             }
1827         }
1828     }
1829   return AS2 (st%K0, %0,%1);
1830 }
1831
1832 char *
1833 out_movhi_mr_r (insn,op,l)
1834      rtx insn;
1835      rtx op[];
1836      int *l;
1837 {
1838   int reg_base = true_regnum (XEXP (op[0],0));
1839   int reg_dest = true_regnum (op[1]);
1840   int tmp;
1841   if (!l)
1842     l = &tmp;
1843   if (CONSTANT_ADDRESS_P (XEXP (op[0],0)))
1844     return *l=4,(AS2 (sts,%A0,%A1) CR_TAB
1845                  AS2 (sts,%B0,%B1));
1846   if (reg_base > 0)
1847     {
1848       if (reg_base == REG_X)
1849         {
1850           if (reg_dest == REG_X)
1851             {
1852               if (reg_unused_after (insn, op[1]))
1853                 return *l=3, (AS2 (mov,__tmp_reg__,r27) CR_TAB
1854                               AS2 (st ,X+,r26) CR_TAB
1855                               AS2 (st ,X,__tmp_reg__));
1856               else
1857                 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
1858                               AS2 (st ,X+,r26) CR_TAB
1859                               AS2 (st ,X,__tmp_reg__)   CR_TAB
1860                               AS2 (sbiw,r26,1));
1861             }
1862           else
1863             {
1864               if (reg_unused_after (insn, XEXP (op[0],0)))
1865                 return *l=2, (AS2 (st,X+,%A1) CR_TAB
1866                               AS2 (st,X,%B1));
1867               else
1868                 return *l=3, (AS2 (st  ,X+,%A1) CR_TAB
1869                               AS2 (st  ,X,%B1) CR_TAB
1870                               AS2 (sbiw,r26,1));
1871             }
1872         }
1873       else
1874         return  *l=2, (AS2 (st ,%0,%A1)    CR_TAB
1875                        AS2 (std,%0+1,%B1));
1876     }
1877   else if (GET_CODE (XEXP (op[0],0)) == PLUS)
1878     {
1879       int disp = INTVAL(XEXP (XEXP (op[0],0), 1));
1880       if (disp > 64 - GET_MODE_SIZE (GET_MODE (op[0])))
1881         {
1882           rtx x = XEXP (op[0],0);
1883           if (REGNO (XEXP (x,0)) != REG_Y)
1884             fatal_insn ("Incorrect insn:",insn);
1885           if (disp <= 63 + 64 - GET_MODE_SIZE (GET_MODE (op[0])))
1886             {
1887               op[4] = GEN_INT (disp - 62);
1888               return *l=4,(AS2 (adiw, r28, %4) CR_TAB
1889                            AS2 (std, Y+62,%A1) CR_TAB
1890                            AS2 (std, Y+63,%B1) CR_TAB
1891                            AS2 (sbiw, r28, %4));
1892             }
1893           else
1894             {
1895               op[4] = XEXP (x,1);
1896               return *l=6,(AS2 (subi, r28, lo8(-%4))  CR_TAB
1897                            AS2 (sbci, r29, hi8(-%4)) CR_TAB
1898                            AS2 (st, Y,%A1)           CR_TAB
1899                            AS2 (std, Y+1,%B1)        CR_TAB
1900                            AS2 (subi, r28, lo8(%4))  CR_TAB
1901                            AS2 (sbci, r29, hi8(%4)));
1902             }
1903         }
1904       return *l=2, (AS2 (std,%A0,%A1)    CR_TAB
1905                     AS2 (std,%B0,%B1));
1906     }  
1907   else if (GET_CODE (XEXP (op[0],0)) == PRE_DEC) /* (--R) */
1908     return *l=2, (AS2 (st,%0,%B1) CR_TAB
1909                   AS2 (st,%0,%A1));
1910   else if (GET_CODE (XEXP (op[0],0)) == POST_INC) /* (R++) */
1911     return *l=2, (AS2 (st,%0,%A1)  CR_TAB
1912                   AS2 (st,%0,%B1));
1913   fatal_insn ("Unknown move insn:",insn);
1914   return "";
1915 }
1916
1917 /* Return 1 if frame pointer for current function required */
1918
1919 int
1920 frame_pointer_required_p(void)
1921 {
1922   return (current_function_calls_alloca
1923           || current_function_args_info.nregs == 0
1924           || current_function_varargs
1925           || get_frame_size () > 0);
1926 }
1927
1928 /* Return 1 if the next insn is a JUMP_INSN with condition (GT,LE,GTU,LTU)  */
1929
1930 int
1931 compare_diff_p (insn)
1932      rtx insn;
1933 {
1934   rtx next = next_real_insn (insn);
1935   RTX_CODE cond = UNKNOWN;
1936   if (GET_CODE (next) == JUMP_INSN)
1937     {
1938       rtx pat = PATTERN (next);
1939       rtx src = SET_SRC (pat);
1940       rtx t = XEXP (src,0);
1941       cond = GET_CODE (t);
1942     }
1943   return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
1944 }
1945
1946 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition */
1947
1948 int
1949 compare_eq_p (insn)
1950      rtx insn;
1951 {
1952   rtx next = next_real_insn (insn);
1953   RTX_CODE cond = UNKNOWN;
1954   if (GET_CODE (next) == JUMP_INSN)
1955     {
1956       rtx pat = PATTERN (next);
1957       rtx src = SET_SRC (pat);
1958       rtx t = XEXP (src,0);
1959       cond = GET_CODE (t);
1960     }
1961   return (cond == EQ || cond == NE);
1962 }
1963
1964
1965 /* Output test instruction for HImode */
1966
1967 char *
1968 out_tsthi (insn,l)
1969      rtx insn;
1970      int *l;
1971 {
1972   if (!compare_eq_p (insn))
1973     {
1974       if (l) *l = 1;
1975       return AS1 (tst,%B0);
1976     }
1977   if (TEST_HARD_REG_CLASS (ADDW_REGS, true_regnum (SET_SRC (PATTERN (insn)))))
1978     {
1979       if (l) *l = 1;
1980       return AS2 (sbiw,%0,0);
1981     }
1982   if (compare_eq_p (insn) && reg_unused_after (insn, SET_SRC (PATTERN (insn))))
1983     {
1984       if (l) *l = 1;
1985       return AS2 (or,%A0,%B0);
1986     }
1987   if (l) *l = 2;
1988   return (AS2 (cp,%A0,__zero_reg__) CR_TAB
1989           AS2 (cpc,%B0,__zero_reg__));
1990 }
1991
1992
1993 /* Output test instruction for SImode */
1994
1995 char *
1996 out_tstsi (insn,l)
1997      rtx insn;
1998      int *l;
1999 {
2000   if (!compare_eq_p (insn))
2001     {
2002       if (l) *l = 1;
2003       return AS1 (tst,%D0);
2004     }
2005   if (TEST_HARD_REG_CLASS (ADDW_REGS, true_regnum (SET_SRC (PATTERN (insn)))))
2006     {
2007       if (l) *l = 3;
2008       return (AS2 (sbiw,%A0,0) CR_TAB
2009               AS2 (cpc,%C0,__zero_reg__) CR_TAB
2010               AS2 (cpc,%D0,__zero_reg__));
2011     }
2012   if (l) *l = 4;
2013   return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2014           AS2 (cpc,%B0,__zero_reg__) CR_TAB
2015           AS2 (cpc,%C0,__zero_reg__) CR_TAB
2016           AS2 (cpc,%D0,__zero_reg__));
2017 }
2018
2019
2020 /* Generate asm equivalent for various shift's.
2021    Shift count are CONST_INT or REG.  */
2022
2023 void
2024 out_shift_with_cnt (template,insn,operands,len)
2025      char * template;
2026      rtx insn;
2027      rtx operands[];
2028      int *len;
2029 {
2030   rtx op[10];
2031   int l_hi=0;
2032   char str[300];
2033   op[0] = operands[0];
2034   op[1] = operands[1];
2035   op[2] = operands[2];
2036   op[3] = operands[3];
2037   str[0] = 0;
2038     
2039   if (CONSTANT_P (operands[2]))
2040     {
2041       if (len)
2042         ++*len;
2043       else
2044         strcat (str, "ldi %3,lo8(%2)");
2045     }
2046   else if (GET_CODE (operands[2]) == MEM)
2047     {
2048       int mov_len;
2049       rtx op_mov[10];
2050       l_hi = 1;
2051       if (len)
2052         *len = 2;
2053       op[3] = op_mov[0] = tmp_reg_rtx;
2054       op_mov[1] = op[2];
2055       
2056       if (!len)
2057         {
2058           output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
2059           strcat (str,(AS2 (or,%3,%3)    CR_TAB
2060                        AS1 (breq,L_hi%=)));
2061         }
2062       else
2063         {
2064           out_movqi_r_mr (insn, op_mov, &mov_len);
2065           *len += mov_len;
2066         }
2067     }
2068   else if (register_operand (operands[2],QImode))
2069     {
2070       l_hi = 1;
2071       if (len)
2072         *len += 2;
2073       else
2074         strcat (str, (AS2 (or,%2,%2) CR_TAB
2075                       AS1 (breq,L_hi%=)));
2076       
2077       if (reg_unused_after (insn, operands[2]))
2078         {
2079           op[3] = op[2];
2080         }
2081       else
2082         {
2083           op[3] = tmp_reg_rtx;
2084           if (len)
2085             ++*len;
2086           else
2087             strcat (str, CR_TAB "mov %3,%2");
2088         }
2089     }
2090   if (!len)
2091     {
2092       strcat (str,"\n\t");
2093       strcat (str, template);
2094       if (l_hi)
2095         strcat (str, "\nL_hi%=:");
2096       output_asm_insn (str, op);
2097     }
2098 }
2099
2100
2101 /* 8bit shift left ((char)x << i)   */
2102
2103 char *
2104 ashlqi3_out (insn,operands,len)
2105      rtx insn;
2106      rtx operands[];
2107      int *len;                  /* insn length (may be NULL) */
2108 {
2109   if (GET_CODE (operands[2]) == CONST_INT)
2110     {
2111       int k;
2112       int *t=len;
2113       if (!len)
2114         len = &k;
2115       switch (INTVAL (operands[2]))
2116         {
2117         default: len = t; break;
2118         case 1:
2119           *len=1;
2120           return AS1 (lsl,%0);
2121         case 2:
2122           *len=2;
2123           return (AS1 (lsl,%0) CR_TAB
2124                   AS1 (lsl,%0));
2125         case 3:
2126           *len=3;
2127           return (AS1 (lsl,%0) CR_TAB
2128                   AS1 (lsl,%0) CR_TAB
2129                   AS1 (lsl,%0));
2130         case 4:
2131           if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
2132             {
2133               *len=2;
2134               return (AS1 (swap,%0) CR_TAB
2135                       AS2 (andi,%0,0xf0));
2136             }
2137           *len=4;
2138           return (AS1 (lsl,%0) CR_TAB
2139                   AS1 (lsl,%0) CR_TAB
2140                   AS1 (lsl,%0) CR_TAB
2141                   AS1 (lsl,%0));
2142         case 5:
2143           if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
2144             {
2145               *len=3;
2146               return (AS1 (swap,%0) CR_TAB
2147                       AS1 (lsl,%0)  CR_TAB
2148                       AS2 (andi,%0,0xe0));
2149             }
2150           *len=5;
2151           return (AS1 (lsl,%0) CR_TAB
2152                   AS1 (lsl,%0) CR_TAB
2153                   AS1 (lsl,%0) CR_TAB
2154                   AS1 (lsl,%0) CR_TAB
2155                   AS1 (lsl,%0));
2156         case 6:
2157           if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
2158             {
2159               *len=4;
2160               return (AS1 (swap,%0) CR_TAB
2161                       AS1 (lsl,%0)  CR_TAB
2162                       AS1 (lsl,%0)  CR_TAB
2163                       AS2 (andi,%0,0xc0));
2164             }
2165           *len=6;
2166           return (AS1 (lsl,%0) CR_TAB
2167                   AS1 (lsl,%0) CR_TAB
2168                   AS1 (lsl,%0) CR_TAB
2169                   AS1 (lsl,%0) CR_TAB
2170                   AS1 (lsl,%0) CR_TAB
2171                   AS1 (lsl,%0));
2172         case 7:
2173           *len=3;
2174           return (AS1 (ror,%0) CR_TAB
2175                   AS1 (clr,%0) CR_TAB
2176                   AS1 (ror,%0));
2177         }
2178     }
2179   if (len)
2180     *len = 3;
2181   out_shift_with_cnt (AS1 (lsl,%0)      CR_TAB
2182                       AS1 (dec,%3)      CR_TAB
2183                       AS1 (brne,_PC_-6),
2184                       insn, operands, len);
2185   return "";
2186 }
2187
2188
2189 /* 16bit shift left ((short)x << i)   */
2190
2191 char *
2192 ashlhi3_out (insn,operands,len)
2193      rtx insn;
2194      rtx operands[];
2195      int *len;
2196 {
2197   if (GET_CODE (operands[2]) == CONST_INT)
2198     {
2199       int k;
2200       int *t=len;
2201       if (!len)
2202         len = &k;
2203       switch (INTVAL (operands[2]))
2204         {
2205         default: len = t; break;
2206         case 1:
2207           *len=2;
2208           return (AS1 (lsl,%A0) CR_TAB
2209                   AS1 (rol,%B0));
2210         case 2:
2211           *len=4;
2212           return (AS1 (lsl,%A0) CR_TAB
2213                   AS1 (rol,%B0) CR_TAB
2214                   AS1 (lsl,%0)  CR_TAB
2215                   AS1 (rol,%B0));
2216         case 8:
2217           if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
2218             return *len = 1, AS1 (clr,%A0);
2219           else
2220             return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
2221                               AS1 (clr,%A0));
2222         }
2223     }
2224   if (len)
2225     *len = 4;
2226   out_shift_with_cnt (AS1 (lsl,%0)  CR_TAB
2227                       AS1 (rol,%B0) CR_TAB
2228                       AS1 (dec,%3)  CR_TAB
2229                       AS1 (brne,_PC_-8),
2230                       insn, operands, len);
2231   return "";
2232 }
2233
2234
2235 /* 32bit shift left ((long)x << i)   */
2236
2237 char *
2238 ashlsi3_out (insn,operands,len)
2239      rtx insn;
2240      rtx operands[];
2241      int *len;
2242 {
2243   if (GET_CODE (operands[2]) == CONST_INT)
2244     {
2245       int k;
2246       int *t=len;
2247       if (!len)
2248         len = &k;
2249       switch (INTVAL (operands[2]))
2250         {
2251         default: len = t; break;
2252         case 1:
2253           *len=4;
2254           return (AS1 (lsl,%A0) CR_TAB
2255                   AS1 (rol,%B0) CR_TAB
2256                   AS1 (rol,%C0) CR_TAB
2257                   AS1 (rol,%D0));
2258         case 8:
2259           {
2260             int reg0 = true_regnum (operands[0]);
2261             int reg1 = true_regnum (operands[1]);
2262             *len=4;
2263             if (reg0 >= reg1)
2264               return (AS2 (mov,%D0,%C1)  CR_TAB
2265                       AS2 (mov,%C0,%B1)  CR_TAB
2266                       AS2 (mov,%B0,%A1)  CR_TAB
2267                       AS1 (clr,%A0));
2268             else if (reg0 + 1 == reg1)
2269               return *len = 1, AS1 (clr,%A0);
2270             else
2271               return (AS1 (clr,%A0)      CR_TAB
2272                       AS2 (mov,%B0,%A1)  CR_TAB
2273                       AS2 (mov,%C0,%B1)  CR_TAB
2274                       AS2 (mov,%D0,%C1));
2275           }
2276         case 16:
2277           {
2278             int reg0 = true_regnum (operands[0]);
2279             int reg1 = true_regnum (operands[1]);
2280             *len=4;
2281             if (reg0 + 1 >= reg1)
2282               return (AS2 (mov,%D0,%B1)  CR_TAB
2283                       AS2 (mov,%C0,%A1)  CR_TAB
2284                       AS1 (clr,%B0)      CR_TAB
2285                       AS1 (clr,%A0));
2286             if (reg0 + 2 == reg1)
2287               return *len = 2, (AS1 (clr,%B0)      CR_TAB
2288                                 AS1 (clr,%A0));
2289             else
2290               return (AS2 (mov,%C0,%A1)  CR_TAB
2291                       AS2 (mov,%D0,%B1)  CR_TAB
2292                       AS1 (clr,%B0)      CR_TAB
2293                       AS1 (clr,%A0));
2294           }
2295         case 24:
2296           *len=4;
2297           if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
2298             return (AS2 (mov,%D0,%A1)  CR_TAB
2299                     AS1 (clr,%C0)      CR_TAB
2300                     AS1 (clr,%B0)      CR_TAB
2301                     AS1 (clr,%A0));
2302           else
2303             return *len = 3, (AS1 (clr,%C0)      CR_TAB
2304                               AS1 (clr,%B0)      CR_TAB
2305                               AS1 (clr,%A0));
2306         }
2307     }
2308   if (len)
2309     *len = 6;
2310   out_shift_with_cnt (AS1 (lsl,%0)  CR_TAB
2311                       AS1 (rol,%B0) CR_TAB
2312                       AS1 (rol,%C0) CR_TAB
2313                       AS1 (rol,%D0) CR_TAB
2314                       AS1 (dec,%3)  CR_TAB
2315                       AS1 (brne,_PC_-12),
2316                       insn, operands, len);
2317   return "";
2318 }
2319
2320 /* 8bit arithmetic shift right  ((signed char)x >> i) */
2321
2322 char *
2323 ashrqi3_out (insn,operands,len)
2324      rtx insn;
2325      rtx operands[];
2326      int *len; /* insn length */
2327 {
2328   if (GET_CODE (operands[2]) == CONST_INT)
2329     {
2330       int *t=len;
2331       int k;
2332       if (!len)
2333         len = &k;
2334       switch (INTVAL (operands[2]))
2335         {
2336         default: len = t; break;
2337         case 1:
2338           *len=1;
2339           return AS1 (asr,%0);
2340         case 2:
2341           *len=2;
2342           return (AS1 (asr,%0) CR_TAB
2343                   AS1 (asr,%0));
2344         case 3:
2345           *len=3;
2346           return (AS1 (asr,%0) CR_TAB
2347                   AS1 (asr,%0) CR_TAB
2348                   AS1 (asr,%0));
2349         case 4:
2350           *len=4;
2351           return (AS1 (asr,%0) CR_TAB
2352                   AS1 (asr,%0) CR_TAB
2353                   AS1 (asr,%0) CR_TAB
2354                   AS1 (asr,%0));
2355         }
2356     }
2357   if (len)
2358     *len = 3;
2359   out_shift_with_cnt (AS1 (asr,%0) CR_TAB
2360                       AS1 (dec,%3) CR_TAB
2361                       AS1 (brne,_PC_-6),
2362                       insn, operands, len);
2363   return "";
2364 }
2365
2366
2367 /* 16bit arithmetic shift right  ((signed short)x >> i) */
2368
2369 char *
2370 ashrhi3_out (insn,operands,len)
2371      rtx insn;
2372      rtx operands[];
2373      int *len;
2374 {
2375   if (GET_CODE (operands[2]) == CONST_INT)
2376     {
2377       int k;
2378       int *t=len;
2379       if (!len)
2380         len = &k;
2381       switch (INTVAL (operands[2]))
2382         {
2383         default: len = t; break;
2384         case 1:
2385           *len=2;
2386           return (AS1 (asr,%B0) CR_TAB
2387                   AS1 (ror,%A0));
2388         case 2:
2389           *len=4;
2390           return (AS1 (asr,%B0)  CR_TAB
2391                   AS1 (ror,%A0) CR_TAB
2392                   AS1 (asr,%B0)  CR_TAB
2393                   AS1 (ror,%A0));
2394         case 8:
2395           if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
2396             return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
2397                               AS1 (clr,%B0)     CR_TAB
2398                               AS2 (sbrc,%A0,7)  CR_TAB
2399                               AS1 (dec,%B0));
2400           else
2401             return *len = 3, (AS1 (clr,%B0)     CR_TAB
2402                               AS2 (sbrc,%A0,7)  CR_TAB
2403                               AS1 (dec,%B0));
2404         }
2405     }
2406   if (len)
2407     *len = 4;
2408   out_shift_with_cnt (AS1 (asr,%B0) CR_TAB
2409                       AS1 (ror,%A0) CR_TAB
2410                       AS1 (dec,%3) CR_TAB
2411                       AS1 (brne,_PC_-8),
2412                       insn, operands, len);
2413   return "";
2414 }
2415
2416
2417 /* 32bit arithmetic shift right  ((signed long)x >> i) */
2418
2419 char *
2420 ashrsi3_out (insn,operands,len)
2421      rtx insn;
2422      rtx operands[];
2423      int *len;
2424 {
2425   if (GET_CODE (operands[2]) == CONST_INT)
2426     {
2427       int k;
2428       int *t = len;
2429       if (!len)
2430         len = &k;
2431       switch (INTVAL (operands[2]))
2432         {
2433         default: len = t; break;
2434         case 1:
2435           *len=4;
2436           return (AS1 (asr,%D0)  CR_TAB
2437                   AS1 (ror,%C0) CR_TAB
2438                   AS1 (ror,%B0) CR_TAB
2439                   AS1 (ror,%A0));
2440         case 8:
2441           {
2442             int reg0 = true_regnum (operands[0]);
2443             int reg1 = true_regnum (operands[1]);
2444             *len=6;
2445             if (reg0 <= reg1)
2446               return (AS2 (mov,%A0,%B1) CR_TAB
2447                       AS2 (mov,%B0,%C1) CR_TAB
2448                       AS2 (mov,%C0,%D1) CR_TAB
2449                       AS1 (clr,%D0)     CR_TAB
2450                       AS2 (sbrc,%C0,7)  CR_TAB
2451                       AS1 (dec,%D0));
2452             else if (reg0 == reg1 + 1)
2453               return *len = 3, (AS1 (clr,%D0)     CR_TAB
2454                                 AS2 (sbrc,%C0,7)  CR_TAB
2455                                 AS1 (dec,%D0));
2456             else
2457               return (AS1 (clr,%D0)     CR_TAB
2458                       AS2 (sbrc,%C0,7)  CR_TAB
2459                       AS1 (dec,%D0)     CR_TAB
2460                       AS2 (mov,%C0,%D1) CR_TAB
2461                       AS2 (mov,%B0,%C1) CR_TAB
2462                       AS2 (mov,%A0,%B1));
2463           }
2464         case 16:
2465           {
2466             int reg0 = true_regnum (operands[0]);
2467             int reg1 = true_regnum (operands[1]);
2468             *len=6;
2469             if (reg0 <= reg1 + 1)
2470               return (AS2 (mov,%A0,%C1) CR_TAB
2471                       AS2 (mov,%B0,%D1) CR_TAB
2472                       AS1 (clr,%D0)     CR_TAB
2473                       AS2 (sbrc,%B0,7)  CR_TAB
2474                       AS1 (com,%D0)     CR_TAB
2475                       AS2 (mov,%C0,%D0));
2476             else if (reg0 == reg1 + 2)
2477               return *len = 4, (AS1 (clr,%D0)     CR_TAB
2478                                 AS2 (sbrc,%B0,7)  CR_TAB
2479                                 AS1 (com,%D0)     CR_TAB
2480                                 AS2 (mov,%C0,%D0));
2481             else
2482               return (AS2 (mov,%B0,%D1) CR_TAB
2483                       AS2 (mov,%A0,%C1) CR_TAB
2484                       AS1 (clr,%D0)     CR_TAB
2485                       AS2 (sbrc,%B0,7)  CR_TAB
2486                       AS1 (com,%D0)     CR_TAB
2487                       AS2 (mov,%C0,%D0));
2488           }
2489         case 24:
2490           if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
2491             return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
2492                               AS1 (clr,%D0)     CR_TAB
2493                               AS2 (sbrc,%A0,7)  CR_TAB
2494                               AS1 (com,%D0)     CR_TAB
2495                               AS2 (mov,%B0,%D0) CR_TAB
2496                               AS2 (mov,%C0,%D0));
2497           else
2498             return *len = 5, (AS1 (clr,%D0)     CR_TAB
2499                               AS2 (sbrc,%A0,7)  CR_TAB
2500                               AS1 (com,%D0)     CR_TAB
2501                               AS2 (mov,%B0,%D0) CR_TAB
2502                               AS2 (mov,%C0,%D0));
2503         }
2504     }
2505   if (len)
2506     *len = 6;
2507   out_shift_with_cnt (AS1 (asr,%D0) CR_TAB
2508                       AS1 (ror,%C0) CR_TAB
2509                       AS1 (ror,%B0) CR_TAB
2510                       AS1 (ror,%A0) CR_TAB
2511                       AS1 (dec,%3) CR_TAB
2512                       AS1 (brne,_PC_-12),
2513                       insn, operands, len);
2514   return "";
2515 }
2516
2517 /* 8bit logic shift right ((unsigned char)x >> i) */
2518
2519 char *
2520 lshrqi3_out (insn,operands,len)
2521      rtx insn;
2522      rtx operands[];
2523      int *len;
2524 {
2525   if (GET_CODE (operands[2]) == CONST_INT)
2526     {
2527       int k;
2528       int *t=len;
2529       if (!len)
2530         len = &k;
2531       switch (INTVAL (operands[2]))
2532         {
2533         default: len = t; break;
2534         case 1:
2535           *len=1;
2536           return AS1 (lsr,%0);
2537         case 2:
2538           *len=2;
2539           return (AS1 (lsr,%0) CR_TAB
2540                   AS1 (lsr,%0));
2541         case 3:
2542           *len=3;
2543           return (AS1 (lsr,%0) CR_TAB
2544                   AS1 (lsr,%0) CR_TAB
2545                   AS1 (lsr,%0));
2546         case 4:
2547           if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
2548             {
2549               *len=2;
2550               return (AS1 (swap,%0) CR_TAB
2551                       AS2 (andi,%0,0x0f));
2552             }
2553           *len=4;
2554           return (AS1 (lsr,%0) CR_TAB
2555                   AS1 (lsr,%0) CR_TAB
2556                   AS1 (lsr,%0) CR_TAB
2557                   AS1 (lsr,%0));
2558         case 5:
2559           if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
2560             {
2561               *len=3;
2562               return (AS1 (swap,%0) CR_TAB
2563                       AS1 (lsr,%0)  CR_TAB
2564                       AS2 (andi,%0,0x7));
2565             }
2566           *len=5;
2567           return (AS1 (lsr,%0) CR_TAB
2568                   AS1 (lsr,%0) CR_TAB
2569                   AS1 (lsr,%0) CR_TAB
2570                   AS1 (lsr,%0) CR_TAB
2571                   AS1 (lsr,%0));
2572         case 6:
2573           if (TEST_HARD_REG_CLASS (LD_REGS, true_regnum (operands[0])))
2574             {
2575               *len=4;
2576               return (AS1 (swap,%0) CR_TAB
2577                       AS1 (lsr,%0)  CR_TAB
2578                       AS1 (lsr,%0)  CR_TAB
2579                       AS2 (andi,%0,0x3));
2580             }
2581           *len=6;
2582           return (AS1 (lsr,%0) CR_TAB
2583                   AS1 (lsr,%0) CR_TAB
2584                   AS1 (lsr,%0) CR_TAB
2585                   AS1 (lsr,%0) CR_TAB
2586                   AS1 (lsr,%0) CR_TAB
2587                   AS1 (lsr,%0));
2588         case 7:
2589           *len=3;
2590           return (AS1 (rol,%0) CR_TAB
2591                   AS1 (clr,%0) CR_TAB
2592                   AS1 (rol,%0));
2593         }
2594     }
2595   if (len)
2596     *len = 3;
2597   out_shift_with_cnt (AS1 (lsr,%0) CR_TAB
2598                       AS1 (dec,%3) CR_TAB
2599                       AS1 (brne,_PC_-6),
2600                       insn, operands, len);
2601   return "";
2602 }
2603
2604 /* 16bit logic shift right ((unsigned short)x >> i) */
2605
2606 char *
2607 lshrhi3_out (insn,operands,len)
2608      rtx insn;
2609      rtx operands[];
2610      int *len;
2611 {
2612   if (GET_CODE (operands[2]) == CONST_INT)
2613     {
2614       int k;
2615       int *t=len;
2616       if (!len)
2617         len = &k;
2618       switch (INTVAL (operands[2]))
2619         {
2620         default: len = t; break;
2621         case 1:
2622           *len=2;
2623           return (AS1 (lsr,%B0) CR_TAB
2624                   AS1 (ror,%A0));
2625         case 2:
2626           *len=4;
2627           return (AS1 (lsr,%B0)  CR_TAB
2628                   AS1 (ror,%A0)  CR_TAB
2629                   AS1 (lsr,%B0)  CR_TAB
2630                   AS1 (ror,%A0));
2631         case 8:
2632           if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
2633             return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
2634                               AS1 (clr,%B0));
2635           else
2636             return *len = 1, AS1 (clr,%B0);
2637             
2638         }
2639     }
2640   if (len)
2641     *len = 4;
2642   out_shift_with_cnt (AS1 (lsr,%B0) CR_TAB
2643                       AS1 (ror,%A0) CR_TAB
2644                       AS1 (dec,%3) CR_TAB
2645                       AS1 (brne,_PC_-8),
2646                       insn, operands, len);
2647   return "";
2648 }
2649
2650 /* 32bit logic shift right ((unsigned int)x >> i) */
2651
2652 char *
2653 lshrsi3_out (insn,operands,len)
2654      rtx insn;
2655      rtx operands[];
2656      int *len;
2657 {
2658   if (GET_CODE (operands[2]) == CONST_INT)
2659     {
2660       int k;
2661       int *t=len;
2662       if (!len)
2663         len = &k;
2664       switch (INTVAL (operands[2]))
2665         {
2666         default: len = t; break;
2667         case 1:
2668           *len=4;
2669           return (AS1 (lsr,%D0)  CR_TAB
2670                   AS1 (ror,%C0) CR_TAB
2671                   AS1 (ror,%B0) CR_TAB
2672                   AS1 (ror,%A0));
2673         case 8:
2674           {
2675             int reg0 = true_regnum (operands[0]);
2676             int reg1 = true_regnum (operands[1]);
2677             *len=4;
2678             if (reg0 <= reg1)
2679               return (AS2 (mov,%A0,%B1) CR_TAB
2680                       AS2 (mov,%B0,%C1) CR_TAB
2681                       AS2 (mov,%C0,%D1) CR_TAB
2682                       AS1 (clr,%D0));
2683             else if (reg0 == reg1 + 1)
2684               return *len = 1, AS1 (clr,%D0);
2685             else
2686               return (AS1 (clr,%D0)     CR_TAB
2687                       AS2 (mov,%C0,%D1) CR_TAB
2688                       AS2 (mov,%B0,%C1) CR_TAB
2689                       AS2 (mov,%A0,%B1)); 
2690           }
2691         case 16:
2692           {
2693             int reg0 = true_regnum (operands[0]);
2694             int reg1 = true_regnum (operands[1]);
2695             *len=4;
2696             if (reg0 <= reg1 + 1)
2697               return (AS2 (mov,%A0,%C1) CR_TAB
2698                       AS2 (mov,%B0,%D1) CR_TAB
2699                       AS1 (clr,%C0)     CR_TAB
2700                       AS1 (clr,%D0));
2701             else if (reg0 == reg1 + 2)
2702               return *len = 2, (AS1 (clr,%C0)     CR_TAB
2703                                 AS1 (clr,%D0));
2704             else
2705               return (AS2 (mov,%B0,%D1) CR_TAB
2706                       AS2 (mov,%A0,%C1) CR_TAB
2707                       AS1 (clr,%C0)     CR_TAB
2708                       AS1 (clr,%D0));
2709           }
2710         case 24:
2711           if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
2712             return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
2713                               AS1 (clr,%B0)     CR_TAB
2714                               AS1 (clr,%C0)     CR_TAB
2715                               AS1 (clr,%D0));
2716           else
2717             return *len = 3, (AS1 (clr,%B0)     CR_TAB
2718                               AS1 (clr,%C0)     CR_TAB
2719                               AS1 (clr,%D0));
2720         }
2721     }
2722   if (len)
2723     *len = 6;
2724   out_shift_with_cnt (AS1 (lsr,%D0) CR_TAB
2725                       AS1 (ror,%C0) CR_TAB
2726                       AS1 (ror,%B0) CR_TAB
2727                       AS1 (ror,%A0) CR_TAB
2728                       AS1 (dec,%3) CR_TAB
2729                       AS1 (brne,_PC_-12),
2730                       insn, operands, len);
2731   return "";
2732 }
2733
2734 /* Modifies the length assigned to instruction INSN
2735  LEN is the initially computed length of the insn.  */
2736
2737 int
2738 adjust_insn_length (insn,len)
2739      rtx insn;
2740      int len;
2741 {
2742   rtx patt = PATTERN (insn);
2743   rtx set;
2744   if (GET_CODE (patt) == SET)
2745     {
2746       rtx op[10];
2747       op[1] = SET_SRC (patt);
2748       op[0] = SET_DEST (patt);
2749       if (REG_P (op[0]) && GET_CODE (op[1]) == MEM)
2750         {
2751           if (CONSTANT_ADDRESS_P (XEXP (op[1],0)))
2752             switch (GET_MODE (op[0]))
2753               {
2754               case QImode: len = 2; break;
2755               case HImode: len = 4; break;
2756               case SImode:
2757               case SFmode: len = 8; break;
2758               default: break; 
2759               }
2760           else
2761             switch (GET_MODE (op[0]))
2762               {
2763               case QImode: out_movqi_r_mr (insn,op,&len); break;
2764               case HImode: out_movhi_r_mr (insn,op,&len); break;
2765               case SImode:
2766               case SFmode: out_movsi_r_mr (insn,op,&len); break;
2767               default: break;
2768               }
2769         }
2770       else if ((REG_P (op[1]) || const0_rtx == op[1])
2771                && GET_CODE (op[0]) == MEM)
2772         {
2773           if (CONSTANT_ADDRESS_P (XEXP (op[0],0)))
2774             switch (GET_MODE (op[0]))
2775               {
2776               case QImode: len = 2; break;
2777               case HImode: len = 4; break;
2778               case SImode:
2779               case SFmode: len = 8; break;
2780               default: break;
2781               }
2782           else if (GET_CODE (XEXP (op[0],0)) != POST_DEC)
2783             switch (GET_MODE (op[0]))
2784               {
2785               case QImode: out_movqi_mr_r (insn,op,&len); break;
2786               case HImode: out_movhi_mr_r (insn,op,&len); break;
2787               case SImode:
2788               case SFmode: out_movsi_mr_r (insn,op,&len); break;
2789               default: break;
2790               }
2791         }
2792       else if (op[0] == cc0_rtx && REG_P (op[1]))
2793         {
2794           switch (GET_MODE (op[1]))
2795             {
2796             case HImode: out_tsthi (insn,&len); break;
2797             case SImode: out_tstsi (insn,&len); break;
2798             default: break;
2799             }
2800         }
2801       else if (GET_CODE (op[1]) == AND)
2802         {
2803           if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
2804             {
2805               HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
2806               if (GET_MODE (op[1]) == SImode)
2807                 len = (((mask & 0xff) != 0xff)
2808                        + ((mask & 0xff00) != 0xff00)
2809                        + ((mask & 0xff0000UL) != 0xff0000UL)
2810                        + ((mask & 0xff000000UL) != 0xff000000UL));
2811               else if (GET_MODE (op[1]) == HImode)
2812                 len = (((mask & 0xff) != 0xff)
2813                        + ((mask & 0xff00) != 0xff00));
2814             }
2815         }
2816       else if (GET_CODE (op[1]) == IOR)
2817         {
2818           if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
2819             {
2820               HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
2821               if (GET_MODE (op[1]) == SImode)
2822                 len = (((mask & 0xff) == 0)
2823                        + ((mask & 0xff00) == 0)
2824                        + ((mask & 0xff0000UL) == 0)
2825                        + ((mask & 0xff000000UL) ==0));
2826               else if (GET_MODE (op[1]) == HImode)
2827                 len = (((mask & 0xff) == 0)
2828                        + ((mask & 0xff00) == 0));
2829             }
2830         }
2831     }
2832   set = single_set (insn);
2833   if (set)
2834     {
2835       rtx op[10];
2836       op[1] = SET_SRC (set);
2837       op[0] = SET_DEST (set);
2838       if (GET_CODE (op[1]) == ASHIFT
2839           || GET_CODE (op[1]) == ASHIFTRT
2840           || GET_CODE (op[1]) == LSHIFTRT)
2841         {
2842           rtx ops[10];
2843           ops[0] = op[0];
2844           ops[1] = XEXP (op[1],0);
2845           ops[2] = XEXP (op[1],1);
2846           switch (GET_CODE (op[1]))
2847             {
2848             case ASHIFT:
2849               switch (GET_MODE (op[0]))
2850                 {
2851                 case QImode: ashlqi3_out (insn,ops,&len); break;
2852                 case HImode: ashlhi3_out (insn,ops,&len); break;
2853                 case SImode: ashlsi3_out (insn,ops,&len); break;
2854                 default: break;
2855                 }
2856               break;
2857             case ASHIFTRT:
2858               switch (GET_MODE (op[0]))
2859                 {
2860                 case QImode: ashrqi3_out (insn,ops,&len); break;
2861                 case HImode: ashrhi3_out (insn,ops,&len); break;
2862                 case SImode: ashrsi3_out (insn,ops,&len); break;
2863                 default: break;
2864                 }
2865               break;
2866             case LSHIFTRT:
2867               switch (GET_MODE (op[0]))
2868                 {
2869                 case QImode: lshrqi3_out (insn,ops,&len); break;
2870                 case HImode: lshrhi3_out (insn,ops,&len); break;
2871                 case SImode: lshrsi3_out (insn,ops,&len); break;
2872                 default: break;
2873                 }
2874               break;
2875             default:
2876               break;
2877             }
2878         }
2879     }
2880   return len;
2881 }
2882
2883 /* Return non-zero if register REG dead after INSN */
2884
2885 int
2886 reg_unused_after (insn, reg)
2887      rtx insn;
2888      rtx reg;
2889 {
2890   return (0
2891           /* In egcs 1.1.x dead_or_set_p give buggy result after reload 
2892 #ifdef PRESERVE_DEATH_INFO_REGNO_P
2893           || dead_or_set_p (insn,reg)
2894 #endif
2895           */
2896           
2897           || (REG_P(reg) && _reg_unused_after (insn, reg)));
2898 }
2899
2900 /* Return non-zero if REG is not used after INSN.
2901    We assume REG is a reload reg, and therefore does
2902    not live past labels.  It may live past calls or jumps though.  */
2903
2904 int
2905 _reg_unused_after (insn, reg)
2906      rtx insn;
2907      rtx reg;
2908 {
2909   enum rtx_code code;
2910   rtx set;
2911
2912   /* If the reg is set by this instruction, then it is safe for our
2913      case.  Disregard the case where this is a store to memory, since
2914      we are checking a register used in the store address.  */
2915   set = single_set (insn);
2916   if (set && GET_CODE (SET_DEST (set)) != MEM
2917       && reg_overlap_mentioned_p (reg, SET_DEST (set)))
2918     return 1;
2919
2920   while ((insn = NEXT_INSN (insn)))
2921     {
2922       code = GET_CODE (insn);
2923
2924 #if 0
2925       /* If this is a label that existed before reload, then the register
2926          if dead here.  However, if this is a label added by reorg, then
2927          the register may still be live here.  We can't tell the difference,
2928          so we just ignore labels completely.  */
2929       if (code == CODE_LABEL)
2930         return 1;
2931       /* else */
2932 #endif
2933
2934       if (code == JUMP_INSN)
2935         return 0;
2936
2937       /* If this is a sequence, we must handle them all at once.
2938          We could have for instance a call that sets the target register,
2939          and a insn in a delay slot that uses the register.  In this case,
2940          we must return 0.  */
2941       else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
2942         {
2943           int i;
2944           int retval = 0;
2945
2946           for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
2947             {
2948               rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
2949               rtx set = single_set (this_insn);
2950
2951               if (GET_CODE (this_insn) == CALL_INSN)
2952                 code = CALL_INSN;
2953               else if (GET_CODE (this_insn) == JUMP_INSN)
2954                 {
2955                   if (INSN_ANNULLED_BRANCH_P (this_insn))
2956                     return 0;
2957                   code = JUMP_INSN;
2958                 }
2959
2960               if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
2961                 return 0;
2962               if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
2963                 {
2964                   if (GET_CODE (SET_DEST (set)) != MEM)
2965                     retval = 1;
2966                   else
2967                     return 0;
2968                 }
2969               if (set == 0
2970                   && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
2971                 return 0;
2972             }
2973           if (retval == 1)
2974             return 1;
2975           else if (code == JUMP_INSN)
2976             return 0;
2977         }
2978
2979       if (code == CALL_INSN)
2980         {
2981           rtx tem;
2982           for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
2983             if (GET_CODE (XEXP (tem, 0)) == USE
2984                 && REG_P (XEXP (XEXP (tem, 0), 0))
2985                 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
2986               return 0;
2987           if (call_used_regs[REGNO (reg)]) 
2988             return 1;
2989         }
2990
2991       if (GET_RTX_CLASS (code) == 'i')
2992         {
2993           rtx set = single_set (insn);
2994
2995           if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
2996             return 0;
2997           if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
2998             return GET_CODE (SET_DEST (set)) != MEM;
2999           if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
3000             return 0;
3001         }
3002     }
3003   return 1;
3004 }
3005
3006 /* Output rtx VALUE as .byte to file FILE */
3007
3008 void
3009 asm_output_char(file,value)
3010      FILE *file;
3011      rtx value;
3012 {
3013   fprintf (file, "\t.byte ");
3014   output_addr_const (file, value);
3015   fprintf (file, "\n");
3016 }
3017
3018
3019 /* Output VALUE as .byte to file FILE */
3020
3021 void
3022 asm_output_byte (file,value)
3023      FILE *file;
3024      char value;
3025 {
3026   fprintf (file, "\t.byte 0x%x\n",value & 0xff);
3027 }
3028
3029
3030 /* Output rtx VALUE as .word to file FILE */
3031
3032 void
3033 asm_output_short (file, value)
3034      FILE *file;
3035      rtx value;
3036 {
3037   if (SYMBOL_REF_FLAG (value) || GET_CODE (value) == LABEL_REF)
3038     {
3039       fprintf (file, "\t.word pm(");
3040       output_addr_const (file, (value));
3041       fprintf (file, ")\n");
3042     }
3043   else
3044     {
3045       fprintf (file, "\t.word ");
3046       output_addr_const (file, (value));
3047       fprintf (file, "\n");
3048     }
3049 }
3050
3051
3052 /* Output real N to file FILE */
3053
3054 void
3055 asm_output_float (file, n)
3056      FILE *file;
3057      REAL_VALUE_TYPE n;
3058 {
3059   long val;
3060   char dstr[100];
3061   
3062   REAL_VALUE_TO_TARGET_SINGLE (n, val);
3063   REAL_VALUE_TO_DECIMAL (n, "%g", dstr);
3064   fprintf (file, "\t.long 0x%08lx\t/* %s */\n",val, dstr);
3065 }
3066
3067 /* Sets section name for declaration DECL */
3068   
3069 void
3070 unique_section (decl, reloc)
3071      tree decl;
3072      int reloc ATTRIBUTE_UNUSED;
3073 {
3074   int len;
3075   char *name,*string;
3076   char *prefix;
3077   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
3078   /* Strip off any encoding in name.  */
3079   STRIP_NAME_ENCODING (name, name);
3080
3081   if (TREE_CODE (decl) == FUNCTION_DECL)
3082     {
3083       if (flag_function_sections)
3084         prefix = ".text.";
3085       else
3086         prefix = ".text";
3087     }
3088   else 
3089     fatal ("Strange situation: unique section is not a FUNCTION_DECL");
3090
3091   if (flag_function_sections)
3092     {
3093       len = strlen (name) + strlen (prefix);
3094       string = alloca (len + 1);
3095       sprintf (string, "%s%s", prefix, name);
3096       DECL_SECTION_NAME (decl) = build_string (len, string);
3097     }
3098 }
3099
3100
3101 /* Output section name to file FILE */
3102
3103 void
3104 asm_output_section_name(file, decl, name, reloc)
3105      FILE *file;
3106      tree decl ATTRIBUTE_UNUSED;
3107      const char *name;
3108      int reloc ATTRIBUTE_UNUSED;
3109 {
3110   fprintf (file, ".section %s\n", name);
3111 }
3112
3113
3114 /* The routine used to output NUL terminated strings.  We use a special
3115    version of this for most svr4 targets because doing so makes the
3116    generated assembly code more compact (and thus faster to assemble)
3117    as well as more readable, especially for targets like the i386
3118    (where the only alternative is to output character sequences as
3119    comma separated lists of numbers).   */
3120
3121 void
3122 gas_output_limited_string(file, str)
3123      FILE * file ATTRIBUTE_UNUSED;
3124      char * str;
3125 {
3126   unsigned char *_limited_str = (unsigned char *) str;
3127   unsigned ch;
3128   fprintf (file, "\t%s\t\"", STRING_ASM_OP);
3129   for (; (ch = *_limited_str); _limited_str++)
3130     {
3131       int escape;
3132       switch (escape = ESCAPES[ch])
3133         {
3134         case 0:
3135           putc (ch, file);
3136           break;
3137         case 1:
3138           fprintf (file, "\\%03o", ch);
3139           break;
3140         default:
3141           putc ('\\', file);
3142           putc (escape, file);
3143           break;
3144         }
3145     }
3146   fprintf (file, "\"\n");
3147 }
3148
3149 /* The routine used to output sequences of byte values.  We use a special
3150    version of this for most svr4 targets because doing so makes the
3151    generated assembly code more compact (and thus faster to assemble)
3152    as well as more readable.  Note that if we find subparts of the
3153    character sequence which end with NUL (and which are shorter than
3154    STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING.  */
3155
3156 void
3157 gas_output_ascii(file, str, length)
3158      FILE * file;
3159      char * str;
3160      size_t length;
3161 {
3162   unsigned char *_ascii_bytes = (unsigned char *) str;
3163   unsigned char *limit = _ascii_bytes + length;
3164   unsigned bytes_in_chunk = 0;
3165   for (; _ascii_bytes < limit; _ascii_bytes++)
3166     {
3167       register unsigned char *p;
3168       if (bytes_in_chunk >= 60)
3169         {
3170           fprintf (file, "\"\n");
3171           bytes_in_chunk = 0;
3172         }
3173       for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
3174         continue;
3175       if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
3176         {
3177           if (bytes_in_chunk > 0)
3178             {
3179               fprintf (file, "\"\n");
3180               bytes_in_chunk = 0;
3181             }
3182           gas_output_limited_string (file, _ascii_bytes);
3183           _ascii_bytes = p;
3184         }
3185       else
3186         {
3187           int escape;
3188           unsigned ch;
3189           if (bytes_in_chunk == 0)
3190             fprintf (file, "\t.ascii\t\"");
3191           switch (escape = ESCAPES[ch = *_ascii_bytes])
3192             {
3193             case 0:
3194               putc (ch, file);
3195               bytes_in_chunk++;
3196               break;
3197             case 1:
3198               fprintf (file, "\\%03o", ch);
3199               bytes_in_chunk += 4;
3200               break;
3201             default:
3202               putc ('\\', file);
3203               putc (escape, file);
3204               bytes_in_chunk += 2;
3205               break;
3206             }
3207         }
3208     }
3209   if (bytes_in_chunk > 0)
3210     fprintf (file, "\"\n");
3211 }
3212
3213 /* Return value is nonzero if pseudos that have been
3214    assigned to registers of class CLASS would likely be spilled
3215    because registers of CLASS are needed for spill registers.  */
3216
3217 enum reg_class
3218 class_likely_spilled_p(int c)
3219 {
3220   return (c != ALL_REGS && c != ADDW_REGS);
3221 }
3222
3223 /* Only `progmem' attribute valid for type.  */
3224
3225 int
3226 valid_machine_type_attribute(type, attributes, identifier, args)
3227      tree type ATTRIBUTE_UNUSED;
3228      tree attributes ATTRIBUTE_UNUSED;
3229      tree identifier;
3230      tree args ATTRIBUTE_UNUSED;
3231 {
3232   return is_attribute_p ("progmem", identifier);
3233 }
3234
3235 /* If IDENTIFIER with arguments ARGS is a valid machine specific
3236    attribute for DECL return 1.
3237    Valid attributes:
3238    progmem - put data to program memory;
3239    signal - make a function to be hardware interrupt. After function
3240    epilogue interrupts are disabled;
3241    interrupt - make a function to be hardware interrupt. After function
3242    epilogue interrupts are enabled;
3243    naked     - don't generate function prologue/epilogue and `ret' command.  */
3244
3245 int
3246 valid_machine_decl_attribute (decl, attributes, attr, args)
3247      tree decl;
3248      tree attributes ATTRIBUTE_UNUSED;
3249      tree attr;
3250      tree args ATTRIBUTE_UNUSED;
3251 {
3252   if (is_attribute_p ("interrupt", attr)
3253       || is_attribute_p ("signal", attr)
3254       || is_attribute_p ("naked", attr))
3255     return TREE_CODE (decl) == FUNCTION_DECL;
3256
3257   if (is_attribute_p ("progmem", attr)
3258       && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
3259     {
3260       if (DECL_INITIAL (decl) == NULL_TREE)
3261         {
3262           warning ("Only initialized variables can be placed into "
3263                    "program memory area.");
3264           return 0;
3265         }
3266       return 1;
3267     }
3268   return 0;
3269 }
3270
3271
3272 /* Look for attribute `progmem' in DECL
3273    founded - 1 otherwise 0 */
3274
3275 int
3276 avr_progmem_p (decl)
3277      tree decl;
3278 {
3279   tree a;
3280
3281   if (TREE_CODE (decl) != VAR_DECL)
3282     return 0;
3283
3284   if (NULL_TREE
3285       != lookup_attribute ("progmem", DECL_MACHINE_ATTRIBUTES (decl)))
3286     return 1;
3287
3288   a=decl;
3289   do
3290     a = TREE_TYPE(a);
3291   while (TREE_CODE (a) == ARRAY_TYPE);
3292
3293   if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
3294     return 1;
3295   
3296   return 0;
3297 }
3298
3299 /* Encode section information about tree DECL */
3300   
3301 void
3302 encode_section_info (decl)
3303      tree decl;
3304 {
3305   if (TREE_CODE (decl) == FUNCTION_DECL)
3306     SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
3307
3308   if ((TREE_STATIC (decl) || DECL_EXTERNAL (decl))
3309       && TREE_CODE (decl) == VAR_DECL
3310       && avr_progmem_p (decl))
3311     {
3312       char * dsec = ".progmem.data";
3313       DECL_SECTION_NAME (decl) = build_string (strlen (dsec), dsec);
3314     }
3315 }   
3316
3317 /* Outputs to the stdio stream FILE some
3318    appropriate text to go at the start of an assembler file.  */
3319
3320 void
3321 asm_file_start (file)
3322      FILE *file;
3323 {
3324   output_file_directive (file, main_input_filename);
3325   fprintf (file, "\t.arch %s\n", avr_mcu_type->name);
3326   fputs ("__SREG__ = 0x3f\n"
3327          "__SP_H__ = 0x3e\n"
3328          "__SP_L__ = 0x3d\n", file);
3329   
3330   if (avr_ram_end)
3331     initial_stack = avr_ram_end;
3332   else
3333     {
3334       static char buf[30];
3335       initial_stack = buf;
3336       sprintf (buf, "0x%x", avr_mcu_type->stack);
3337     }
3338   
3339   fputs ("__tmp_reg__ = 0\n" 
3340          "__zero_reg__ = 1\n"
3341          "_PC_ = 2\n", file);
3342   
3343   commands_in_file = 0;
3344   commands_in_prologues = 0;
3345   commands_in_epilogues = 0;
3346 }
3347
3348 /* Outputs to the stdio stream FILE some
3349    appropriate text to go at the end of an assembler file.  */
3350
3351 void
3352 asm_file_end (file)
3353      FILE *file;
3354 {
3355   fprintf (file,
3356            "/* File %s: code %4d (%4d), prologues %3d, epilogues %3d */\n",
3357            main_input_filename,
3358            commands_in_file,
3359            commands_in_file - commands_in_prologues - commands_in_epilogues,
3360            commands_in_prologues, commands_in_epilogues);
3361 }
3362
3363 /* Choose the order in which to allocate hard registers for
3364    pseudo-registers local to a basic block.
3365
3366    Store the desired register order in the array `reg_alloc_order'.
3367    Element 0 should be the register to allocate first; element 1, the
3368    next register; and so on.  */
3369
3370 void
3371 order_regs_for_local_alloc (void)
3372 {
3373   unsigned int i;
3374   int order_0[] = {
3375     24,25,
3376     18,19,
3377     20,21,
3378     22,23,
3379     30,31,
3380     26,27,
3381     28,29,
3382     17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
3383     0,1,
3384     32,33,34,35
3385   };
3386   int order_1[] = {
3387     18,19,
3388     20,21,
3389     22,23,
3390     24,25,
3391     30,31,
3392     26,27,
3393     28,29,
3394     17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
3395     0,1,
3396     32,33,34,35
3397   };
3398   int order_2[] = {
3399     25,24,
3400     23,22,
3401     21,20,
3402     19,18,
3403     30,31,
3404     26,27,
3405     28,29,
3406     17,16,
3407     15,14,13,12,11,10,9,8,7,6,5,4,3,2,
3408     1,0,
3409     32,33,34,35
3410   };
3411   
3412   int *order = (TARGET_ORDER_1 ? order_1 :
3413                 TARGET_ORDER_2 ? order_2 :
3414                 order_0);
3415   for (i=0; i < sizeof (order_0) / sizeof (order_0[0]); ++i)
3416       reg_alloc_order[i] = order[i];
3417 }
3418
3419 /* Calculate the cost of X code of the expression in which it is contained,
3420    found in OUTER_CODE */
3421
3422 int
3423 default_rtx_costs (X, code, outer_code)
3424      rtx X;
3425      enum rtx_code code;
3426      enum rtx_code outer_code;
3427 {
3428   int cost=0;
3429   switch (code)
3430     {
3431     case SYMBOL_REF:
3432     case LABEL_REF:
3433       cost = 2 * GET_MODE_SIZE (GET_MODE (X));
3434       break;
3435     case MEM:
3436       if (outer_code != SET)
3437         cost = 1;
3438       if (GET_CODE (XEXP (X,0)) == SYMBOL_REF)
3439         cost += 2 * GET_MODE_SIZE (GET_MODE (X));
3440       else
3441         cost += GET_MODE_SIZE (GET_MODE (X));
3442       break;
3443     case CONST_INT:
3444       cost = 0;
3445       break;
3446     case SIGN_EXTEND:
3447       if (outer_code == SET)
3448         cost = GET_MODE_SIZE (GET_MODE (X));
3449       else
3450         cost = -GET_MODE_SIZE (GET_MODE (X));
3451       break;
3452     case ZERO_EXTEND:
3453       if (outer_code == SET)
3454         cost = GET_MODE_SIZE (GET_MODE (X));
3455       else
3456         cost = -1;
3457       break;
3458     case PLUS:
3459     case MINUS:
3460       if (outer_code == SET)
3461         {
3462           if (X == stack_pointer_rtx)
3463             cost = -10;
3464           else if (GET_CODE (XEXP (X,1)) == CONST_INT)
3465             cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 :
3466                      GET_MODE_SIZE (GET_MODE (X)));
3467           else
3468             cost = GET_MODE_SIZE (GET_MODE (X));
3469         }
3470       break;
3471     case COMPARE:
3472       if (GET_CODE (XEXP (X,1)) == CONST_INT)
3473         cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0)));
3474       break;
3475     default:
3476       break;
3477     }
3478   return cost;
3479 }
3480
3481 /* Calculate the cost of a memory address */
3482
3483 int
3484 avr_address_cost (rtx x)
3485 {
3486   if (GET_CODE (x) == PLUS
3487       && GET_CODE (XEXP (x,1)) == CONST_INT
3488       && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
3489       && INTVAL (XEXP (x,1)) >= 61)
3490     return 18;
3491   if (CONSTANT_ADDRESS_P (x))
3492     return 4;
3493   return 4;
3494 }
3495
3496 /*  EXTRA_CONSTRAINT helper */
3497
3498 int
3499 extra_constraint (x,c)
3500      rtx x;
3501      char c;
3502 {
3503   if (c == 'Q'
3504       && GET_CODE (x) == MEM
3505       && GET_CODE (XEXP (x,0)) == PLUS)
3506     {
3507           if (TARGET_ALL_DEBUG)
3508             {
3509               fprintf (stderr, ("extra_constraint:\n"
3510                                 "reload_completed: %d\n"
3511                                 "reload_in_progress: %d\n"),
3512                        reload_completed, reload_in_progress);
3513               debug_rtx (x);
3514             }
3515       if (GET_CODE (x) == MEM
3516           && GET_CODE (XEXP (x,0)) == PLUS
3517           && REG_P (XEXP (XEXP (x,0), 0))
3518           && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
3519           && (INTVAL (XEXP (XEXP (x,0), 1))
3520               <= (64 - GET_MODE_SIZE (GET_MODE (x)))))
3521         {
3522           rtx xx = XEXP (XEXP (x,0), 0);
3523           int regno = REGNO (xx);
3524           if (TARGET_ALL_DEBUG)
3525             {
3526               fprintf (stderr, ("extra_constraint:\n"
3527                                 "reload_completed: %d\n"
3528                                 "reload_in_progress: %d\n"),
3529                        reload_completed, reload_in_progress);
3530               debug_rtx (x);
3531             }
3532           if (regno >= FIRST_PSEUDO_REGISTER)
3533             return 1;           /* allocate pseudos */
3534           else if (regno == REG_Z || regno == REG_Y)
3535             return 1;           /* strictly check */
3536           else if (xx == frame_pointer_rtx
3537                    || xx == arg_pointer_rtx)
3538             return 1;           /* XXX frame & arg pointer checks */
3539         }
3540     }
3541   return 0;
3542 }
3543
3544 /* Convert condition code CONDITION to the valid AVR condition code */
3545
3546 RTX_CODE
3547 avr_normalize_condition (condition)
3548      RTX_CODE condition;
3549 {
3550   switch (condition)
3551     {
3552     case GT:
3553       return GE;
3554     case GTU:
3555       return GEU;
3556     case LE:
3557       return LT;
3558     case LEU:
3559       return LTU;
3560     default:
3561       fatal ("Wrong condition: %s", GET_RTX_NAME (condition));
3562     }
3563 }
3564
3565 /* This fnction optimizes conditional jumps */
3566
3567 void
3568 machine_dependent_reorg (first_insn)
3569      rtx first_insn;
3570 {
3571   rtx insn, pattern;
3572   CC_STATUS_INIT;
3573   
3574   for (insn = first_insn; insn; insn = NEXT_INSN (insn))
3575     {
3576       if (! (insn == 0 || GET_CODE (insn) == INSN
3577              || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
3578           || !single_set (insn))
3579         continue;
3580
3581       pattern = PATTERN (insn);
3582
3583       cc_prev_status = cc_status;
3584       NOTICE_UPDATE_CC (pattern, insn);
3585       
3586       if (GET_CODE (pattern) == PARALLEL)
3587         pattern = XVECEXP (pattern, 0, 0);
3588       if (GET_CODE (pattern) == SET
3589           && SET_DEST (pattern) == cc0_rtx
3590           && compare_diff_p (insn))
3591         {
3592           if (GET_CODE (SET_SRC (pattern)) == COMPARE)
3593             {
3594               /* Now we work under compare insn */
3595               
3596               pattern = SET_SRC (pattern);
3597               if (true_regnum (XEXP (pattern,0)) >= 0
3598                   && true_regnum (XEXP (pattern,1)) >= 0 )
3599                 {
3600                   rtx x = XEXP (pattern,0);
3601                   rtx next = next_real_insn (insn);
3602                   rtx pat = PATTERN (next);
3603                   rtx src = SET_SRC (pat);
3604                   rtx t = XEXP (src,0);
3605                   PUT_CODE (t, swap_condition (GET_CODE (t)));
3606                   XEXP (pattern,0) = XEXP (pattern,1);
3607                   XEXP (pattern,1) = x;
3608                   INSN_CODE (next) = -1;
3609                 }
3610               else if (true_regnum (XEXP (pattern,0)) >= 0
3611                        && GET_CODE (XEXP (pattern,1)) == CONST_INT)
3612                 {
3613                   rtx x = XEXP (pattern,1);
3614                   rtx next = next_real_insn (insn);
3615                   rtx pat = PATTERN (next);
3616                   rtx src = SET_SRC (pat);
3617                   rtx t = XEXP (src,0);
3618
3619                   if (avr_simplify_comparision_p (GET_MODE (XEXP (pattern,0)),
3620                                                   GET_CODE (t), x))
3621                     {
3622                       XEXP (pattern,1) = GEN_INT (INTVAL (x)+1);
3623                       PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
3624                       INSN_CODE (next) = -1;
3625                       INSN_CODE (insn) = -1;
3626                     }
3627                 }
3628             }
3629           else if (true_regnum (SET_SRC (pattern)) >= 0)
3630             {
3631               /* This is a tst insn */
3632               rtx next = next_real_insn (insn);
3633               rtx pat = PATTERN (next);
3634               rtx src = SET_SRC (pat);
3635               rtx t = XEXP (src,0);
3636
3637               if (!(cc_prev_status.value1 != 0 && cc_status.value1 != 0
3638                      && rtx_equal_p (cc_status.value1, cc_prev_status.value1)))
3639                   {
3640                     PUT_CODE (t, swap_condition (GET_CODE (t)));
3641                     SET_SRC (pattern) = gen_rtx (NEG,
3642                                                  GET_MODE (SET_SRC (pattern)),
3643                                                  SET_SRC (pattern));
3644                     INSN_CODE (next) = -1;
3645                     INSN_CODE (insn) = -1;
3646                   }
3647             }
3648         }
3649     }
3650 }
3651
3652 /* Returns register number for function return value.*/
3653
3654 int
3655 avr_ret_register (void)
3656 {
3657   return 24;
3658 }
3659
3660 /* Ceate an RTX representing the place where a
3661    library function returns a value of mode MODE.  */
3662
3663 rtx
3664 avr_libcall_value (mode)
3665      enum machine_mode mode;
3666 {
3667   int offs = GET_MODE_SIZE (mode);
3668   if (offs < 2)
3669     offs = 2;
3670   return gen_rtx (REG, mode, RET_REGISTER + 2 - offs);
3671 }
3672
3673 /* Create an RTX representing the place where a
3674    function returns a value of data type VALTYPE.  */
3675
3676 rtx
3677 avr_function_value (type,func)
3678      tree type;
3679      tree func ATTRIBUTE_UNUSED;
3680 {
3681   int offs;
3682   if (TYPE_MODE (type) != BLKmode)
3683     return avr_libcall_value (TYPE_MODE (type));
3684   
3685   offs = int_size_in_bytes (type);
3686   if (offs < 2)
3687     offs = 2;
3688   if (offs > 2 && offs < GET_MODE_SIZE (SImode))
3689     offs = GET_MODE_SIZE (SImode);
3690   else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
3691     offs = GET_MODE_SIZE (DImode);
3692   
3693   return gen_rtx (REG, BLKmode, RET_REGISTER + 2 - offs);
3694 }
3695
3696 /* Returns non-zero if number MASK have only one setted bit */
3697
3698 int
3699 mask_one_bit_p (mask)
3700      HOST_WIDE_INT mask;
3701 {
3702   int i;
3703   unsigned HOST_WIDE_INT n=mask;
3704   for (i = 0; i < 32; ++i)
3705     {
3706       if (n & 0x80000000UL)
3707         {
3708           if (n & 0x7fffffffUL)
3709             return 0;
3710           else
3711             return 32-i;
3712         }
3713       n<<=1;
3714     }
3715   return 0; 
3716 }
3717
3718
3719 /* Places additional restrictions on the register class to
3720    use when it is necessary to copy value X into a register
3721    in class CLASS.  */
3722
3723 enum reg_class
3724 preferred_reload_class(x,class)
3725      rtx x;
3726      enum reg_class class;
3727 {
3728   if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0)
3729     return class;
3730   if (CONSTANT_P (x) && (class == NO_LD_REGS
3731                          || class == ALL_REGS
3732                          || class == GENERAL_REGS))
3733     {
3734       return LD_REGS;
3735     }
3736   return class;
3737 }
3738
3739 void
3740 debug_hard_reg_set (HARD_REG_SET set)
3741 {
3742   int i;
3743   for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
3744     {
3745       if (TEST_HARD_REG_BIT (set, i))
3746         {
3747           fprintf (stderr, "r%-2d ", i);
3748         }
3749     }
3750   fprintf (stderr, "\n");
3751 }
3752