OSDN Git Service

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