OSDN Git Service

c25f8983a79002887df64e65d605e691ce147496
[pf3gnuchains/gcc-fork.git] / gcc / config / avr / avr.c
1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008,
3    2009, 2010, 2011 Free Software Foundation, Inc.
4    Contributed by Denis Chertykov (chertykov@gmail.com)
5
6    This file is part of GCC.
7
8    GCC is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3, or (at your option)
11    any later version.
12    
13    GCC is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with GCC; see the file COPYING3.  If not see
20    <http://www.gnu.org/licenses/>.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-attr.h"
32 #include "insn-codes.h"
33 #include "flags.h"
34 #include "reload.h"
35 #include "tree.h"
36 #include "output.h"
37 #include "expr.h"
38 #include "c-family/c-common.h"
39 #include "diagnostic-core.h"
40 #include "obstack.h"
41 #include "function.h"
42 #include "recog.h"
43 #include "optabs.h"
44 #include "ggc.h"
45 #include "langhooks.h"
46 #include "tm_p.h"
47 #include "target.h"
48 #include "target-def.h"
49 #include "params.h"
50 #include "df.h"
51
52 /* Maximal allowed offset for an address in the LD command */
53 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
54
55 /* Return true if STR starts with PREFIX and false, otherwise.  */
56 #define STR_PREFIX_P(STR,PREFIX) (0 == strncmp (STR, PREFIX, strlen (PREFIX)))
57
58 /* The 4 bits starting at SECTION_MACH_DEP are reserved to store the
59    address space where data is to be located.
60    As the only non-generic address spaces are all located in Flash,
61    this can be used to test if data shall go into some .progmem* section.
62    This must be the rightmost field of machine dependent section flags.  */
63 #define AVR_SECTION_PROGMEM (0xf * SECTION_MACH_DEP)
64
65 /* Similar 4-bit region for SYMBOL_REF_FLAGS.  */
66 #define AVR_SYMBOL_FLAG_PROGMEM (0xf * SYMBOL_FLAG_MACH_DEP)
67
68 /* Similar 4-bit region in SYMBOL_REF_FLAGS:
69    Set address-space AS in SYMBOL_REF_FLAGS of SYM  */
70 #define AVR_SYMBOL_SET_ADDR_SPACE(SYM,AS)                       \
71   do {                                                          \
72     SYMBOL_REF_FLAGS (sym) &= ~AVR_SYMBOL_FLAG_PROGMEM;         \
73     SYMBOL_REF_FLAGS (sym) |= (AS) * SYMBOL_FLAG_MACH_DEP;      \
74   } while (0)
75
76 /* Read address-space from SYMBOL_REF_FLAGS of SYM  */
77 #define AVR_SYMBOL_GET_ADDR_SPACE(SYM)                          \
78   ((SYMBOL_REF_FLAGS (sym) & AVR_SYMBOL_FLAG_PROGMEM)           \
79    / SYMBOL_FLAG_MACH_DEP)
80
81 /* Known address spaces.  The order must be the same as in the respective
82    enum from avr.h (or designated initialized must be used).  */
83 const avr_addrspace_t avr_addrspace[] =
84 {
85     { ADDR_SPACE_RAM,  0, 2, ""     ,   0 },
86     { ADDR_SPACE_FLASH,  1, 2, "__flash",   0 },
87     { ADDR_SPACE_FLASH1, 1, 2, "__flash1",  1 },
88     { ADDR_SPACE_FLASH2, 1, 2, "__flash2",  2 },
89     { ADDR_SPACE_FLASH3, 1, 2, "__flash3",  3 },
90     { ADDR_SPACE_FLASH4, 1, 2, "__flash4",  4 },
91     { ADDR_SPACE_FLASH5, 1, 2, "__flash5",  5 },
92     { ADDR_SPACE_MEMX, 1, 3, "__memx",  0 },
93     { 0              , 0, 0, NULL,      0 }
94 };
95
96 /* Map 64-k Flash segment to section prefix.  */
97 static const char* const progmem_section_prefix[6] =
98   {
99     ".progmem.data",
100     ".progmem1.data",
101     ".progmem2.data",
102     ".progmem3.data",
103     ".progmem4.data",
104     ".progmem5.data"
105   };
106
107 /* Holding RAM addresses of some SFRs used by the compiler and that
108    are unique over all devices in an architecture like 'avr4'.  */
109   
110 typedef struct
111 {
112   /* SREG: The pocessor status */
113   int sreg;
114
115   /* RAMPX, RAMPY, RAMPD and CCP of XMEGA */
116   int ccp;
117   int rampd;
118   int rampx;
119   int rampy;
120
121   /* RAMPZ: The high byte of 24-bit address used with ELPM */ 
122   int rampz;
123
124   /* SP: The stack pointer and its low and high byte */
125   int sp_l;
126   int sp_h;
127 } avr_addr_t;
128
129 static avr_addr_t avr_addr;
130
131
132 /* Prototypes for local helper functions.  */
133
134 static const char* out_movqi_r_mr (rtx, rtx[], int*);
135 static const char* out_movhi_r_mr (rtx, rtx[], int*);
136 static const char* out_movsi_r_mr (rtx, rtx[], int*);
137 static const char* out_movqi_mr_r (rtx, rtx[], int*);
138 static const char* out_movhi_mr_r (rtx, rtx[], int*);
139 static const char* out_movsi_mr_r (rtx, rtx[], int*);
140
141 static int avr_naked_function_p (tree);
142 static int interrupt_function_p (tree);
143 static int signal_function_p (tree);
144 static int avr_OS_task_function_p (tree);
145 static int avr_OS_main_function_p (tree);
146 static int avr_regs_to_save (HARD_REG_SET *);
147 static int get_sequence_length (rtx insns);
148 static int sequent_regs_live (void);
149 static const char *ptrreg_to_str (int);
150 static const char *cond_string (enum rtx_code);
151 static int avr_num_arg_regs (enum machine_mode, const_tree);
152 static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code,
153                                  int, bool);
154 static void output_reload_in_const (rtx*, rtx, int*, bool);
155 static struct machine_function * avr_init_machine_status (void);
156
157
158 /* Prototypes for hook implementors if needed before their implementation.  */
159
160 static bool avr_rtx_costs (rtx, int, int, int, int *, bool);
161
162
163 /* Allocate registers from r25 to r8 for parameters for function calls.  */
164 #define FIRST_CUM_REG 26
165
166 /* Implicit target register of LPM instruction (R0) */
167 extern GTY(()) rtx lpm_reg_rtx;
168 rtx lpm_reg_rtx;
169
170 /* (Implicit) address register of LPM instruction (R31:R30 = Z) */
171 extern GTY(()) rtx lpm_addr_reg_rtx;
172 rtx lpm_addr_reg_rtx;
173
174 /* Temporary register RTX (reg:QI TMP_REGNO) */
175 extern GTY(()) rtx tmp_reg_rtx;
176 rtx tmp_reg_rtx;
177
178 /* Zeroed register RTX (reg:QI ZERO_REGNO) */
179 extern GTY(()) rtx zero_reg_rtx;
180 rtx zero_reg_rtx;
181
182 /* RTXs for all general purpose registers as QImode */
183 extern GTY(()) rtx all_regs_rtx[32];
184 rtx all_regs_rtx[32];
185
186 /* SREG, the processor status */
187 extern GTY(()) rtx sreg_rtx;
188 rtx sreg_rtx;
189
190 /* RAMP* special function registers */
191 extern GTY(()) rtx rampd_rtx;
192 extern GTY(()) rtx rampx_rtx;
193 extern GTY(()) rtx rampy_rtx;
194 extern GTY(()) rtx rampz_rtx;
195 rtx rampd_rtx;
196 rtx rampx_rtx;
197 rtx rampy_rtx;
198 rtx rampz_rtx;
199
200 /* RTX containing the strings "" and "e", respectively */
201 static GTY(()) rtx xstring_empty;
202 static GTY(()) rtx xstring_e;
203
204 /* Preprocessor macros to define depending on MCU type.  */
205 const char *avr_extra_arch_macro;
206
207 /* Current architecture.  */
208 const struct base_arch_s *avr_current_arch;
209
210 /* Current device.  */
211 const struct mcu_type_s *avr_current_device;
212
213 /* Section to put switch tables in.  */
214 static GTY(()) section *progmem_swtable_section;
215
216 /* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
217    or to address space __flash*.  */
218 static GTY(()) section *progmem_section[6];
219
220 /* Condition for insns/expanders from avr-dimode.md.  */
221 bool avr_have_dimode = true;
222
223 /* To track if code will use .bss and/or .data.  */
224 bool avr_need_clear_bss_p = false;
225 bool avr_need_copy_data_p = false;
226
227 \f
228
229 /* Custom function to count number of set bits.  */
230
231 static inline int
232 avr_popcount (unsigned int val)
233 {
234   int pop = 0;
235
236   while (val)
237     {
238       val &= val-1;
239       pop++;
240     }
241
242   return pop;
243 }
244
245
246 /* Constraint helper function.  XVAL is a CONST_INT or a CONST_DOUBLE.
247    Return true if the least significant N_BYTES bytes of XVAL all have a
248    popcount in POP_MASK and false, otherwise.  POP_MASK represents a subset
249    of integers which contains an integer N iff bit N of POP_MASK is set.  */
250    
251 bool
252 avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
253 {
254   int i;
255
256   enum machine_mode mode = GET_MODE (xval);
257
258   if (VOIDmode == mode)
259     mode = SImode;
260
261   for (i = 0; i < n_bytes; i++)
262     {
263       rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
264       unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
265
266       if (0 == (pop_mask & (1 << avr_popcount (val8))))
267         return false;
268     }
269
270   return true;
271 }
272
273 static void
274 avr_option_override (void)
275 {
276   flag_delete_null_pointer_checks = 0;
277
278   /* caller-save.c looks for call-clobbered hard registers that are assigned
279      to pseudos that cross calls and tries so save-restore them around calls
280      in order to reduce the number of stack slots needed.
281
282      This might leads to situations where reload is no more able to cope
283      with the challenge of AVR's very few address registers and fails to
284      perform the requested spills.  */
285   
286   if (avr_strict_X)
287     flag_caller_saves = 0;
288
289   /* Unwind tables currently require a frame pointer for correctness,
290      see toplev.c:process_options().  */
291
292   if ((flag_unwind_tables
293        || flag_non_call_exceptions
294        || flag_asynchronous_unwind_tables)
295       && !ACCUMULATE_OUTGOING_ARGS)
296     {
297       flag_omit_frame_pointer = 0;
298     }
299
300   avr_current_device = &avr_mcu_types[avr_mcu_index];
301   avr_current_arch = &avr_arch_types[avr_current_device->arch];
302   avr_extra_arch_macro = avr_current_device->macro;
303   
304   /* RAM addresses of some SFRs common to all Devices in respective Arch. */
305
306   /* SREG: Status Register containing flags like I (global IRQ) */
307   avr_addr.sreg = 0x3F + avr_current_arch->sfr_offset;
308
309   /* RAMPZ: Address' high part when loading via ELPM */
310   avr_addr.rampz = 0x3B + avr_current_arch->sfr_offset;
311
312   avr_addr.rampy = 0x3A + avr_current_arch->sfr_offset;
313   avr_addr.rampx = 0x39 + avr_current_arch->sfr_offset;
314   avr_addr.rampd = 0x38 + avr_current_arch->sfr_offset;
315   avr_addr.ccp = 0x34 + avr_current_arch->sfr_offset;
316
317   /* SP: Stack Pointer (SP_H:SP_L) */
318   avr_addr.sp_l = 0x3D + avr_current_arch->sfr_offset;
319   avr_addr.sp_h = avr_addr.sp_l + 1;
320
321   init_machine_status = avr_init_machine_status;
322
323   avr_log_set_avr_log();
324 }
325
326 /* Function to set up the backend function structure.  */
327
328 static struct machine_function *
329 avr_init_machine_status (void)
330 {
331   return ggc_alloc_cleared_machine_function ();
332 }
333
334
335 /* Implement `INIT_EXPANDERS'.  */
336 /* The function works like a singleton.  */
337
338 void
339 avr_init_expanders (void)
340 {
341   int regno;
342
343   for (regno = 0; regno < 32; regno ++)
344     all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
345
346   lpm_reg_rtx  = all_regs_rtx[LPM_REGNO];
347   tmp_reg_rtx  = all_regs_rtx[TMP_REGNO];
348   zero_reg_rtx = all_regs_rtx[ZERO_REGNO];
349
350   lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
351
352   sreg_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg));
353   rampd_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampd));
354   rampx_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampx));
355   rampy_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampy));
356   rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampz));
357
358   xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
359   xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
360 }
361
362
363 /* Return register class for register R.  */
364
365 enum reg_class
366 avr_regno_reg_class (int r)
367 {
368   static const enum reg_class reg_class_tab[] =
369     {
370       R0_REG,
371       /* r1 - r15 */
372       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
373       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
374       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
375       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
376       /* r16 - r23 */
377       SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
378       SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
379       /* r24, r25 */
380       ADDW_REGS, ADDW_REGS,
381       /* X: r26, 27 */
382       POINTER_X_REGS, POINTER_X_REGS,
383       /* Y: r28, r29 */
384       POINTER_Y_REGS, POINTER_Y_REGS,
385       /* Z: r30, r31 */
386       POINTER_Z_REGS, POINTER_Z_REGS,
387       /* SP: SPL, SPH */
388       STACK_REG, STACK_REG
389     };
390
391   if (r <= 33)
392     return reg_class_tab[r];
393   
394   return ALL_REGS;
395 }
396
397
398 static bool
399 avr_scalar_mode_supported_p (enum machine_mode mode)
400 {
401   if (PSImode == mode)
402     return true;
403
404   return default_scalar_mode_supported_p (mode);
405 }
406
407
408 /* Return TRUE if DECL is a VAR_DECL located in Flash and FALSE, otherwise.  */
409
410 static bool
411 avr_decl_flash_p (tree decl)
412 {
413   if (TREE_CODE (decl) != VAR_DECL
414       || TREE_TYPE (decl) == error_mark_node)
415     {
416       return false;
417     }
418
419   return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
420 }
421
422
423 /* Return TRUE if DECL is a VAR_DECL located in the 24-bit Flash
424    address space and FALSE, otherwise.  */
425  
426 static bool
427 avr_decl_memx_p (tree decl)
428 {
429   if (TREE_CODE (decl) != VAR_DECL
430       || TREE_TYPE (decl) == error_mark_node)
431     {
432       return false;
433     }
434
435   return (ADDR_SPACE_MEMX == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
436 }
437
438
439 /* Return TRUE if X is a MEM rtx located in Flash and FALSE, otherwise.  */
440
441 bool
442 avr_mem_flash_p (rtx x)
443 {
444   return (MEM_P (x)
445           && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)));
446 }
447
448
449 /* Return TRUE if X is a MEM rtx located in the 24-bit Flash
450    address space and FALSE, otherwise.  */
451
452 bool
453 avr_mem_memx_p (rtx x)
454 {
455   return (MEM_P (x)
456           && ADDR_SPACE_MEMX == MEM_ADDR_SPACE (x));
457 }
458
459
460 /* A helper for the subsequent function attribute used to dig for
461    attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
462
463 static inline int
464 avr_lookup_function_attribute1 (const_tree func, const char *name)
465 {
466   if (FUNCTION_DECL == TREE_CODE (func))
467     {
468       if (NULL_TREE != lookup_attribute (name, DECL_ATTRIBUTES (func)))
469         {
470           return true;
471         }
472       
473       func = TREE_TYPE (func);
474     }
475
476   gcc_assert (TREE_CODE (func) == FUNCTION_TYPE
477               || TREE_CODE (func) == METHOD_TYPE);
478   
479   return NULL_TREE != lookup_attribute (name, TYPE_ATTRIBUTES (func));
480 }
481
482 /* Return nonzero if FUNC is a naked function.  */
483
484 static int
485 avr_naked_function_p (tree func)
486 {
487   return avr_lookup_function_attribute1 (func, "naked");
488 }
489
490 /* Return nonzero if FUNC is an interrupt function as specified
491    by the "interrupt" attribute.  */
492
493 static int
494 interrupt_function_p (tree func)
495 {
496   return avr_lookup_function_attribute1 (func, "interrupt");
497 }
498
499 /* Return nonzero if FUNC is a signal function as specified
500    by the "signal" attribute.  */
501
502 static int
503 signal_function_p (tree func)
504 {
505   return avr_lookup_function_attribute1 (func, "signal");
506 }
507
508 /* Return nonzero if FUNC is an OS_task function.  */
509
510 static int
511 avr_OS_task_function_p (tree func)
512 {
513   return avr_lookup_function_attribute1 (func, "OS_task");
514 }
515
516 /* Return nonzero if FUNC is an OS_main function.  */
517
518 static int
519 avr_OS_main_function_p (tree func)
520 {
521   return avr_lookup_function_attribute1 (func, "OS_main");
522 }
523
524
525 /* Implement `ACCUMULATE_OUTGOING_ARGS'.  */
526
527 int
528 avr_accumulate_outgoing_args (void)
529 {
530   if (!cfun)
531     return TARGET_ACCUMULATE_OUTGOING_ARGS;
532
533   /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
534         what offset is correct.  In some cases it is relative to
535         virtual_outgoing_args_rtx and in others it is relative to
536         virtual_stack_vars_rtx.  For example code see
537             gcc.c-torture/execute/built-in-setjmp.c
538             gcc.c-torture/execute/builtins/sprintf-chk.c   */
539   
540   return (TARGET_ACCUMULATE_OUTGOING_ARGS
541           && !(cfun->calls_setjmp
542                || cfun->has_nonlocal_label));
543 }
544
545
546 /* Report contribution of accumulated outgoing arguments to stack size.  */
547
548 static inline int
549 avr_outgoing_args_size (void)
550 {
551   return ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0;
552 }
553
554
555 /* Implement `STARTING_FRAME_OFFSET'.  */
556 /* This is the offset from the frame pointer register to the first stack slot
557    that contains a variable living in the frame.  */
558
559 int
560 avr_starting_frame_offset (void)
561 {
562   return 1 + avr_outgoing_args_size ();
563 }
564
565
566 /* Return the number of hard registers to push/pop in the prologue/epilogue
567    of the current function, and optionally store these registers in SET.  */
568
569 static int
570 avr_regs_to_save (HARD_REG_SET *set)
571 {
572   int reg, count;
573   int int_or_sig_p = (interrupt_function_p (current_function_decl)
574                       || signal_function_p (current_function_decl));
575
576   if (set)
577     CLEAR_HARD_REG_SET (*set);
578   count = 0;
579
580   /* No need to save any registers if the function never returns or 
581      has the "OS_task" or "OS_main" attribute.  */
582   if (TREE_THIS_VOLATILE (current_function_decl)
583       || cfun->machine->is_OS_task
584       || cfun->machine->is_OS_main)
585     return 0;
586
587   for (reg = 0; reg < 32; reg++)
588     {
589       /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
590          any global register variables.  */
591       if (fixed_regs[reg])
592         continue;
593
594       if ((int_or_sig_p && !current_function_is_leaf && call_used_regs[reg])
595           || (df_regs_ever_live_p (reg)
596               && (int_or_sig_p || !call_used_regs[reg])
597               /* Don't record frame pointer registers here.  They are treated
598                  indivitually in prologue.  */
599               && !(frame_pointer_needed
600                    && (reg == REG_Y || reg == (REG_Y+1)))))
601         {
602           if (set)
603             SET_HARD_REG_BIT (*set, reg);
604           count++;
605         }
606     }
607   return count;
608 }
609
610 /* Return true if register FROM can be eliminated via register TO.  */
611
612 static bool
613 avr_can_eliminate (const int from, const int to)
614 {
615   return ((from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
616           || (frame_pointer_needed && to == FRAME_POINTER_REGNUM)
617           || ((from == FRAME_POINTER_REGNUM 
618                || from == FRAME_POINTER_REGNUM + 1)
619               && !frame_pointer_needed));
620 }
621
622 /* Compute offset between arg_pointer and frame_pointer.  */
623
624 int
625 avr_initial_elimination_offset (int from, int to)
626 {
627   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
628     return 0;
629   else
630     {
631       int offset = frame_pointer_needed ? 2 : 0;
632       int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
633       
634       offset += avr_regs_to_save (NULL);
635       return (get_frame_size () + avr_outgoing_args_size()
636               + avr_pc_size + 1 + offset);
637     }
638 }
639
640 /* Actual start of frame is virtual_stack_vars_rtx this is offset from 
641    frame pointer by +STARTING_FRAME_OFFSET.
642    Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET
643    avoids creating add/sub of offset in nonlocal goto and setjmp.  */
644
645 static rtx
646 avr_builtin_setjmp_frame_value (void)
647 {
648   return gen_rtx_MINUS (Pmode, virtual_stack_vars_rtx, 
649                         gen_int_mode (STARTING_FRAME_OFFSET, Pmode));
650 }
651
652 /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3 byte PC).
653    This is return address of function.  */
654 rtx 
655 avr_return_addr_rtx (int count, rtx tem)
656 {
657   rtx r;
658     
659   /* Can only return this function's return address. Others not supported.  */
660   if (count)
661      return NULL;
662
663   if (AVR_3_BYTE_PC)
664     {
665       r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
666       warning (0, "'builtin_return_address' contains only 2 bytes of address");
667     }
668   else
669     r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
670
671   r = gen_rtx_PLUS (Pmode, tem, r);
672   r = gen_frame_mem (Pmode, memory_address (Pmode, r));
673   r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
674   return  r;
675 }
676
677 /* Return 1 if the function epilogue is just a single "ret".  */
678
679 int
680 avr_simple_epilogue (void)
681 {
682   return (! frame_pointer_needed
683           && get_frame_size () == 0
684           && avr_outgoing_args_size() == 0
685           && avr_regs_to_save (NULL) == 0
686           && ! interrupt_function_p (current_function_decl)
687           && ! signal_function_p (current_function_decl)
688           && ! avr_naked_function_p (current_function_decl)
689           && ! TREE_THIS_VOLATILE (current_function_decl));
690 }
691
692 /* This function checks sequence of live registers.  */
693
694 static int
695 sequent_regs_live (void)
696 {
697   int reg;
698   int live_seq=0;
699   int cur_seq=0;
700
701   for (reg = 0; reg < 18; ++reg)
702     {
703       if (fixed_regs[reg])
704         {
705           /* Don't recognize sequences that contain global register
706              variables.  */
707       
708           if (live_seq != 0)
709             return 0;
710           else
711             continue;
712         }
713       
714       if (!call_used_regs[reg])
715         {
716           if (df_regs_ever_live_p (reg))
717             {
718               ++live_seq;
719               ++cur_seq;
720             }
721           else
722             cur_seq = 0;
723         }
724     }
725
726   if (!frame_pointer_needed)
727     {
728       if (df_regs_ever_live_p (REG_Y))
729         {
730           ++live_seq;
731           ++cur_seq;
732         }
733       else
734         cur_seq = 0;
735
736       if (df_regs_ever_live_p (REG_Y+1))
737         {
738           ++live_seq;
739           ++cur_seq;
740         }
741       else
742         cur_seq = 0;
743     }
744   else
745     {
746       cur_seq += 2;
747       live_seq += 2;
748     }
749   return (cur_seq == live_seq) ? live_seq : 0;
750 }
751
752 /* Obtain the length sequence of insns.  */
753
754 int
755 get_sequence_length (rtx insns)
756 {
757   rtx insn;
758   int length;
759   
760   for (insn = insns, length = 0; insn; insn = NEXT_INSN (insn))
761     length += get_attr_length (insn);
762                 
763   return length;
764 }
765
766 /*  Implement INCOMING_RETURN_ADDR_RTX.  */
767
768 rtx
769 avr_incoming_return_addr_rtx (void)
770 {
771   /* The return address is at the top of the stack.  Note that the push
772      was via post-decrement, which means the actual address is off by one.  */
773   return gen_frame_mem (HImode, plus_constant (stack_pointer_rtx, 1));
774 }
775
776 /*  Helper for expand_prologue.  Emit a push of a byte register.  */
777
778 static void
779 emit_push_byte (unsigned regno, bool frame_related_p)
780 {
781   rtx mem, reg, insn;
782
783   mem = gen_rtx_POST_DEC (HImode, stack_pointer_rtx);
784   mem = gen_frame_mem (QImode, mem);
785   reg = gen_rtx_REG (QImode, regno);
786
787   insn = emit_insn (gen_rtx_SET (VOIDmode, mem, reg));
788   if (frame_related_p)
789     RTX_FRAME_RELATED_P (insn) = 1;
790
791   cfun->machine->stack_usage++;
792 }
793
794
795 /*  Helper for expand_prologue.  Emit a push of a SFR via tmp_reg.
796     SFR is a MEM representing the memory location of the SFR.
797     If CLR_P then clear the SFR after the push using zero_reg.  */
798
799 static void
800 emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p)
801 {
802   rtx insn;
803   
804   gcc_assert (MEM_P (sfr));
805
806   /* IN __tmp_reg__, IO(SFR) */
807   insn = emit_move_insn (tmp_reg_rtx, sfr);
808   if (frame_related_p)
809     RTX_FRAME_RELATED_P (insn) = 1;
810   
811   /* PUSH __tmp_reg__ */
812   emit_push_byte (TMP_REGNO, frame_related_p);
813
814   if (clr_p)
815     {
816       /* OUT IO(SFR), __zero_reg__ */
817       insn = emit_move_insn (sfr, const0_rtx);
818       if (frame_related_p)
819         RTX_FRAME_RELATED_P (insn) = 1;
820     }
821 }
822
823 static void
824 avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
825 {
826   rtx insn;
827   bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
828   int live_seq = sequent_regs_live ();
829
830   HOST_WIDE_INT size_max
831     = (HOST_WIDE_INT) GET_MODE_MASK (AVR_HAVE_8BIT_SP ? QImode : Pmode);
832
833   bool minimize = (TARGET_CALL_PROLOGUES
834                    && size < size_max
835                    && live_seq
836                    && !isr_p
837                    && !cfun->machine->is_OS_task
838                    && !cfun->machine->is_OS_main);
839   
840   if (minimize
841       && (frame_pointer_needed
842           || avr_outgoing_args_size() > 8
843           || (AVR_2_BYTE_PC && live_seq > 6)
844           || live_seq > 7)) 
845     {
846       rtx pattern;
847       int first_reg, reg, offset;
848
849       emit_move_insn (gen_rtx_REG (HImode, REG_X), 
850                       gen_int_mode (size, HImode));
851
852       pattern = gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
853                                          gen_int_mode (live_seq+size, HImode));
854       insn = emit_insn (pattern);
855       RTX_FRAME_RELATED_P (insn) = 1;
856
857       /* Describe the effect of the unspec_volatile call to prologue_saves.
858          Note that this formulation assumes that add_reg_note pushes the
859          notes to the front.  Thus we build them in the reverse order of
860          how we want dwarf2out to process them.  */
861
862       /* The function does always set frame_pointer_rtx, but whether that
863          is going to be permanent in the function is frame_pointer_needed.  */
864
865       add_reg_note (insn, REG_CFA_ADJUST_CFA,
866                     gen_rtx_SET (VOIDmode, (frame_pointer_needed
867                                             ? frame_pointer_rtx
868                                             : stack_pointer_rtx),
869                                  plus_constant (stack_pointer_rtx,
870                                                 -(size + live_seq))));
871
872       /* Note that live_seq always contains r28+r29, but the other
873          registers to be saved are all below 18.  */
874
875       first_reg = 18 - (live_seq - 2);
876
877       for (reg = 29, offset = -live_seq + 1;
878            reg >= first_reg;
879            reg = (reg == 28 ? 17 : reg - 1), ++offset)
880         {
881           rtx m, r;
882
883           m = gen_rtx_MEM (QImode, plus_constant (stack_pointer_rtx, offset));
884           r = gen_rtx_REG (QImode, reg);
885           add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (VOIDmode, m, r));
886         }
887
888       cfun->machine->stack_usage += size + live_seq;
889     }
890   else /* !minimize */
891     {
892       int reg;
893       
894       for (reg = 0; reg < 32; ++reg)
895         if (TEST_HARD_REG_BIT (set, reg))
896           emit_push_byte (reg, true);
897
898       if (frame_pointer_needed
899           && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
900         {
901           /* Push frame pointer.  Always be consistent about the
902              ordering of pushes -- epilogue_restores expects the
903              register pair to be pushed low byte first.  */
904           
905           emit_push_byte (REG_Y, true);
906           emit_push_byte (REG_Y + 1, true);
907         }
908           
909       if (frame_pointer_needed
910           && size == 0)
911         {
912           insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
913           RTX_FRAME_RELATED_P (insn) = 1;
914         }
915       
916       if (size != 0)
917         {
918           /*  Creating a frame can be done by direct manipulation of the
919               stack or via the frame pointer. These two methods are:
920                   fp =  sp
921                   fp -= size
922                   sp =  fp
923               or
924                   sp -= size
925                   fp =  sp    (*)
926               the optimum method depends on function type, stack and
927               frame size.  To avoid a complex logic, both methods are
928               tested and shortest is selected.
929
930               There is also the case where SIZE != 0 and no frame pointer is
931               needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
932               In that case, insn (*) is not needed in that case.
933               We use the X register as scratch. This is save because in X
934               is call-clobbered.
935                  In an interrupt routine, the case of SIZE != 0 together with
936               !frame_pointer_needed can only occur if the function is not a
937               leaf function and thus X has already been saved.  */
938               
939           int irq_state = -1;
940           HOST_WIDE_INT size_cfa = size;
941           rtx fp_plus_insns, fp, my_fp;
942
943           gcc_assert (frame_pointer_needed
944                       || !isr_p
945                       || !current_function_is_leaf);
946           
947           fp = my_fp = (frame_pointer_needed
948                         ? frame_pointer_rtx
949                         : gen_rtx_REG (Pmode, REG_X));
950           
951           if (AVR_HAVE_8BIT_SP)
952             {
953               /* The high byte (r29) does not change:
954                  Prefer SUBI (1 cycle) over SBIW (2 cycles, same size).  */
955
956               my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
957             }
958
959           /* Cut down size and avoid size = 0 so that we don't run
960              into ICE like PR52488 in the remainder.  */
961
962           if (size > size_max)
963             {
964               /* Don't error so that insane code from newlib still compiles
965                  and does not break building newlib.  As PR51345 is implemented
966                  now, there are multilib variants with -msp8.
967                  
968                  If user wants sanity checks he can use -Wstack-usage=
969                  or similar options.
970
971                  For CFA we emit the original, non-saturated size so that
972                  the generic machinery is aware of the real stack usage and
973                  will print the above diagnostic as expected.  */
974               
975               size = size_max;
976             }
977
978           size = trunc_int_for_mode (size, GET_MODE (my_fp));
979           
980           /************  Method 1: Adjust frame pointer  ************/
981           
982           start_sequence ();
983
984           /* Normally, the dwarf2out frame-related-expr interpreter does
985              not expect to have the CFA change once the frame pointer is
986              set up.  Thus, we avoid marking the move insn below and
987              instead indicate that the entire operation is complete after
988              the frame pointer subtraction is done.  */
989           
990           insn = emit_move_insn (fp, stack_pointer_rtx);
991           if (frame_pointer_needed)
992             {
993               RTX_FRAME_RELATED_P (insn) = 1;
994               add_reg_note (insn, REG_CFA_ADJUST_CFA,
995                             gen_rtx_SET (VOIDmode, fp, stack_pointer_rtx));
996             }
997
998           insn = emit_move_insn (my_fp, plus_constant (my_fp, -size));
999           if (frame_pointer_needed)
1000             {
1001               RTX_FRAME_RELATED_P (insn) = 1;
1002               add_reg_note (insn, REG_CFA_ADJUST_CFA,
1003                             gen_rtx_SET (VOIDmode, fp,
1004                                          plus_constant (fp, -size_cfa)));
1005             }
1006           
1007           /* Copy to stack pointer.  Note that since we've already
1008              changed the CFA to the frame pointer this operation
1009              need not be annotated if frame pointer is needed.
1010              Always move through unspec, see PR50063.
1011              For meaning of irq_state see movhi_sp_r insn.  */
1012
1013           if (cfun->machine->is_interrupt)
1014             irq_state = 1;
1015
1016           if (TARGET_NO_INTERRUPTS
1017               || cfun->machine->is_signal
1018               || cfun->machine->is_OS_main)
1019             irq_state = 0;
1020
1021           if (AVR_HAVE_8BIT_SP)
1022             irq_state = 2;
1023
1024           insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
1025                                             fp, GEN_INT (irq_state)));
1026           if (!frame_pointer_needed)
1027             {
1028               RTX_FRAME_RELATED_P (insn) = 1;
1029               add_reg_note (insn, REG_CFA_ADJUST_CFA,
1030                             gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1031                                          plus_constant (stack_pointer_rtx,
1032                                                         -size_cfa)));
1033             }
1034           
1035           fp_plus_insns = get_insns ();
1036           end_sequence ();
1037           
1038           /************  Method 2: Adjust Stack pointer  ************/
1039
1040           /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
1041              can only handle specific offsets.  */
1042           
1043           if (avr_sp_immediate_operand (gen_int_mode (-size, HImode), HImode))
1044             {
1045               rtx sp_plus_insns;
1046               
1047               start_sequence ();
1048
1049               insn = emit_move_insn (stack_pointer_rtx,
1050                                      plus_constant (stack_pointer_rtx, -size));
1051               RTX_FRAME_RELATED_P (insn) = 1;
1052               add_reg_note (insn, REG_CFA_ADJUST_CFA,
1053                             gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1054                                          plus_constant (stack_pointer_rtx,
1055                                                         -size_cfa)));
1056               if (frame_pointer_needed)
1057                 {
1058                   insn = emit_move_insn (fp, stack_pointer_rtx);
1059                   RTX_FRAME_RELATED_P (insn) = 1;
1060                 }
1061
1062               sp_plus_insns = get_insns ();
1063               end_sequence ();
1064
1065               /************ Use shortest method  ************/
1066                   
1067               emit_insn (get_sequence_length (sp_plus_insns)
1068                          < get_sequence_length (fp_plus_insns)
1069                          ? sp_plus_insns
1070                          : fp_plus_insns);
1071             }
1072           else
1073             {
1074               emit_insn (fp_plus_insns);
1075             }
1076
1077           cfun->machine->stack_usage += size_cfa;
1078         } /* !minimize && size != 0 */
1079     } /* !minimize */
1080 }
1081
1082
1083 /*  Output function prologue.  */
1084
1085 void
1086 expand_prologue (void)
1087 {
1088   HARD_REG_SET set;
1089   HOST_WIDE_INT size;
1090
1091   size = get_frame_size() + avr_outgoing_args_size();
1092   
1093   /* Init cfun->machine.  */
1094   cfun->machine->is_naked = avr_naked_function_p (current_function_decl);
1095   cfun->machine->is_interrupt = interrupt_function_p (current_function_decl);
1096   cfun->machine->is_signal = signal_function_p (current_function_decl);
1097   cfun->machine->is_OS_task = avr_OS_task_function_p (current_function_decl);
1098   cfun->machine->is_OS_main = avr_OS_main_function_p (current_function_decl);
1099   cfun->machine->stack_usage = 0;
1100   
1101   /* Prologue: naked.  */
1102   if (cfun->machine->is_naked)
1103     {
1104       return;
1105     }
1106
1107   avr_regs_to_save (&set);
1108
1109   if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1110     {
1111       /* Enable interrupts.  */
1112       if (cfun->machine->is_interrupt)
1113         emit_insn (gen_enable_interrupt ());
1114         
1115       /* Push zero reg.  */
1116       emit_push_byte (ZERO_REGNO, true);
1117
1118       /* Push tmp reg.  */
1119       emit_push_byte (TMP_REGNO, true);
1120
1121       /* Push SREG.  */
1122       /* ??? There's no dwarf2 column reserved for SREG.  */
1123       emit_push_sfr (sreg_rtx, false, false /* clr */);
1124
1125       /* Clear zero reg.  */
1126       emit_move_insn (zero_reg_rtx, const0_rtx);
1127
1128       /* Prevent any attempt to delete the setting of ZERO_REG!  */
1129       emit_use (zero_reg_rtx);
1130
1131       /* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
1132          ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z.  */
1133       
1134       if (AVR_HAVE_RAMPD)
1135         emit_push_sfr (rampd_rtx, false /* frame-related */, true /* clr */);
1136
1137       if (AVR_HAVE_RAMPX
1138           && TEST_HARD_REG_BIT (set, REG_X)
1139           && TEST_HARD_REG_BIT (set, REG_X + 1))
1140         {
1141           emit_push_sfr (rampx_rtx, false /* frame-related */, true /* clr */);
1142         }
1143
1144       if (AVR_HAVE_RAMPY
1145           && (frame_pointer_needed
1146               || (TEST_HARD_REG_BIT (set, REG_Y)
1147                   && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1148         {
1149           emit_push_sfr (rampy_rtx, false /* frame-related */, true /* clr */);
1150         }
1151
1152       if (AVR_HAVE_RAMPZ
1153           && TEST_HARD_REG_BIT (set, REG_Z)
1154           && TEST_HARD_REG_BIT (set, REG_Z + 1))
1155         {
1156           emit_push_sfr (rampz_rtx, false /* frame-related */, AVR_HAVE_RAMPD);
1157         }
1158     }  /* is_interrupt is_signal */
1159
1160   avr_prologue_setup_frame (size, set);
1161   
1162   if (flag_stack_usage_info)
1163     current_function_static_stack_size = cfun->machine->stack_usage;
1164 }
1165
1166 /* Output summary at end of function prologue.  */
1167
1168 static void
1169 avr_asm_function_end_prologue (FILE *file)
1170 {
1171   if (cfun->machine->is_naked)
1172     {
1173       fputs ("/* prologue: naked */\n", file);
1174     }
1175   else
1176     {
1177       if (cfun->machine->is_interrupt)
1178         {
1179           fputs ("/* prologue: Interrupt */\n", file);
1180         }
1181       else if (cfun->machine->is_signal)
1182         {
1183           fputs ("/* prologue: Signal */\n", file);
1184         }
1185       else
1186         fputs ("/* prologue: function */\n", file);
1187     }
1188
1189   if (ACCUMULATE_OUTGOING_ARGS)
1190     fprintf (file, "/* outgoing args size = %d */\n",
1191              avr_outgoing_args_size());
1192
1193   fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
1194                  get_frame_size());
1195   fprintf (file, "/* stack size = %d */\n",
1196                  cfun->machine->stack_usage);
1197   /* Create symbol stack offset here so all functions have it. Add 1 to stack
1198      usage for offset so that SP + .L__stack_offset = return address.  */
1199   fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
1200 }
1201
1202
1203 /* Implement EPILOGUE_USES.  */
1204
1205 int
1206 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
1207 {
1208   if (reload_completed 
1209       && cfun->machine
1210       && (cfun->machine->is_interrupt || cfun->machine->is_signal))
1211     return 1;
1212   return 0;
1213 }
1214
1215 /*  Helper for expand_epilogue.  Emit a pop of a byte register.  */
1216
1217 static void
1218 emit_pop_byte (unsigned regno)
1219 {
1220   rtx mem, reg;
1221
1222   mem = gen_rtx_PRE_INC (HImode, stack_pointer_rtx);
1223   mem = gen_frame_mem (QImode, mem);
1224   reg = gen_rtx_REG (QImode, regno);
1225
1226   emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
1227 }
1228
1229 /*  Output RTL epilogue.  */
1230
1231 void
1232 expand_epilogue (bool sibcall_p)
1233 {
1234   int reg;
1235   int live_seq;
1236   HARD_REG_SET set;      
1237   int minimize;
1238   HOST_WIDE_INT size;
1239   bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1240
1241   size = get_frame_size() + avr_outgoing_args_size();
1242   
1243   /* epilogue: naked  */
1244   if (cfun->machine->is_naked)
1245     {
1246       gcc_assert (!sibcall_p);
1247       
1248       emit_jump_insn (gen_return ());
1249       return;
1250     }
1251
1252   avr_regs_to_save (&set);
1253   live_seq = sequent_regs_live ();
1254   
1255   minimize = (TARGET_CALL_PROLOGUES
1256               && live_seq
1257               && !isr_p
1258               && !cfun->machine->is_OS_task
1259               && !cfun->machine->is_OS_main);
1260   
1261   if (minimize
1262       && (live_seq > 4
1263           || frame_pointer_needed
1264           || size))
1265     {
1266       /*  Get rid of frame.  */
1267       
1268       if (!frame_pointer_needed)
1269         {
1270           emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1271         }
1272
1273       if (size)
1274         {
1275           emit_move_insn (frame_pointer_rtx,
1276                           plus_constant (frame_pointer_rtx, size));
1277         }
1278         
1279       emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
1280       return;
1281     }
1282       
1283   if (size)
1284     {
1285       /* Try two methods to adjust stack and select shortest.  */
1286
1287       int irq_state = -1;
1288       rtx fp, my_fp;
1289       rtx fp_plus_insns;
1290       HOST_WIDE_INT size_max;
1291
1292       gcc_assert (frame_pointer_needed
1293                   || !isr_p
1294                   || !current_function_is_leaf);
1295       
1296       fp = my_fp = (frame_pointer_needed
1297                     ? frame_pointer_rtx
1298                     : gen_rtx_REG (Pmode, REG_X));
1299
1300       if (AVR_HAVE_8BIT_SP)
1301         {
1302           /* The high byte (r29) does not change:
1303              Prefer SUBI (1 cycle) over SBIW (2 cycles).  */
1304                   
1305           my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
1306         }
1307
1308       /* For rationale see comment in prologue generation.  */
1309
1310       size_max = (HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (my_fp));
1311       if (size > size_max)
1312         size = size_max;
1313       size = trunc_int_for_mode (size, GET_MODE (my_fp));
1314               
1315       /********** Method 1: Adjust fp register  **********/
1316               
1317       start_sequence ();
1318
1319       if (!frame_pointer_needed)
1320         emit_move_insn (fp, stack_pointer_rtx);
1321
1322       emit_move_insn (my_fp, plus_constant (my_fp, size));
1323
1324       /* Copy to stack pointer.  */
1325
1326       if (TARGET_NO_INTERRUPTS)
1327         irq_state = 0;
1328
1329       if (AVR_HAVE_8BIT_SP)
1330         irq_state = 2;
1331
1332       emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp,
1333                                  GEN_INT (irq_state)));
1334
1335       fp_plus_insns = get_insns ();
1336       end_sequence ();        
1337
1338       /********** Method 2: Adjust Stack pointer  **********/
1339       
1340       if (avr_sp_immediate_operand (gen_int_mode (size, HImode), HImode))
1341         {
1342           rtx sp_plus_insns;
1343
1344           start_sequence ();
1345
1346           emit_move_insn (stack_pointer_rtx,
1347                           plus_constant (stack_pointer_rtx, size));
1348
1349           sp_plus_insns = get_insns ();
1350           end_sequence ();
1351
1352           /************ Use shortest method  ************/
1353           
1354           emit_insn (get_sequence_length (sp_plus_insns)
1355                      < get_sequence_length (fp_plus_insns)
1356                      ? sp_plus_insns
1357                      : fp_plus_insns);
1358         }
1359       else
1360         emit_insn (fp_plus_insns);
1361     } /* size != 0 */
1362           
1363   if (frame_pointer_needed
1364       && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
1365     {
1366       /* Restore previous frame_pointer.  See expand_prologue for
1367          rationale for not using pophi.  */
1368               
1369       emit_pop_byte (REG_Y + 1);
1370       emit_pop_byte (REG_Y);
1371     }
1372
1373   /* Restore used registers.  */
1374   
1375   for (reg = 31; reg >= 0; --reg)
1376     if (TEST_HARD_REG_BIT (set, reg))
1377       emit_pop_byte (reg);
1378
1379   if (isr_p)
1380     {
1381       /* Restore RAMPZ/Y/X/D using tmp_reg as scratch.
1382          The conditions to restore them must be tha same as in prologue.  */
1383       
1384       if (AVR_HAVE_RAMPZ
1385           && TEST_HARD_REG_BIT (set, REG_Z)
1386           && TEST_HARD_REG_BIT (set, REG_Z + 1))
1387         {
1388           emit_pop_byte (TMP_REGNO);
1389           emit_move_insn (rampz_rtx, tmp_reg_rtx);
1390         }
1391
1392       if (AVR_HAVE_RAMPY
1393           && (frame_pointer_needed
1394               || (TEST_HARD_REG_BIT (set, REG_Y)
1395                   && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1396         {
1397           emit_pop_byte (TMP_REGNO);
1398           emit_move_insn (rampy_rtx, tmp_reg_rtx);
1399         }
1400
1401       if (AVR_HAVE_RAMPX
1402           && TEST_HARD_REG_BIT (set, REG_X)
1403           && TEST_HARD_REG_BIT (set, REG_X + 1))
1404         {
1405           emit_pop_byte (TMP_REGNO);
1406           emit_move_insn (rampx_rtx, tmp_reg_rtx);
1407         }
1408
1409       if (AVR_HAVE_RAMPD)
1410         {
1411           emit_pop_byte (TMP_REGNO);
1412           emit_move_insn (rampd_rtx, tmp_reg_rtx);
1413         }
1414
1415       /* Restore SREG using tmp_reg as scratch.  */
1416       
1417       emit_pop_byte (TMP_REGNO);
1418       emit_move_insn (sreg_rtx, tmp_reg_rtx);
1419
1420       /* Restore tmp REG.  */
1421       emit_pop_byte (TMP_REGNO);
1422
1423       /* Restore zero REG.  */
1424       emit_pop_byte (ZERO_REGNO);
1425     }
1426
1427   if (!sibcall_p)
1428     emit_jump_insn (gen_return ());
1429 }
1430
1431 /* Output summary messages at beginning of function epilogue.  */
1432
1433 static void
1434 avr_asm_function_begin_epilogue (FILE *file)
1435 {
1436   fprintf (file, "/* epilogue start */\n");
1437 }
1438
1439
1440 /* Implement TARGET_CANNOT_MODITY_JUMPS_P */
1441
1442 static bool
1443 avr_cannot_modify_jumps_p (void)
1444 {
1445
1446   /* Naked Functions must not have any instructions after
1447      their epilogue, see PR42240 */
1448      
1449   if (reload_completed
1450       && cfun->machine
1451       && cfun->machine->is_naked)
1452     {
1453       return true;
1454     }
1455
1456   return false;
1457 }
1458
1459
1460 /* Implement `TARGET_MODE_DEPENDENT_ADDRESS_P'.  */
1461
1462 /* FIXME:  PSImode addresses are not mode-dependent in themselves.
1463       This hook just serves to hack around PR rtl-optimization/52543 by
1464       claiming that PSImode addresses (which are used for the 24-bit
1465       address space __memx) were mode-dependent so that lower-subreg.s
1466       will skip these addresses.  See also the similar FIXME comment along
1467       with mov<mode> expanders in avr.md.  */
1468
1469 static bool
1470 avr_mode_dependent_address_p (const_rtx addr)
1471 {
1472   return GET_MODE (addr) != Pmode;
1473 }
1474
1475
1476 /* Helper function for `avr_legitimate_address_p'.  */
1477
1478 static inline bool
1479 avr_reg_ok_for_addr_p (rtx reg, addr_space_t as,
1480                        RTX_CODE outer_code, bool strict)
1481 {
1482   return (REG_P (reg)
1483           && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), QImode,
1484                                                  as, outer_code, UNKNOWN)
1485               || (!strict
1486                   && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
1487 }
1488
1489
1490 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
1491    machine for a memory operand of mode MODE.  */
1492
1493 static bool
1494 avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
1495 {
1496   bool ok = CONSTANT_ADDRESS_P (x);
1497   
1498   switch (GET_CODE (x))
1499     {
1500     case REG:
1501       ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
1502                                   MEM, strict);
1503
1504       if (strict
1505           && DImode == mode
1506           && REG_X == REGNO (x))
1507         {
1508           ok = false;
1509         }
1510       break;
1511
1512     case POST_INC:
1513     case PRE_DEC:
1514       ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
1515                                   GET_CODE (x), strict);
1516       break;
1517
1518     case PLUS:
1519       {
1520         rtx reg = XEXP (x, 0);
1521         rtx op1 = XEXP (x, 1);
1522         
1523         if (REG_P (reg)
1524             && CONST_INT_P (op1)
1525             && INTVAL (op1) >= 0)
1526           {
1527             bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
1528
1529             if (fit)
1530               {
1531                 ok = (! strict
1532                       || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
1533                                                 PLUS, strict));
1534           
1535                 if (reg == frame_pointer_rtx
1536                     || reg == arg_pointer_rtx)
1537                   {
1538                     ok = true;
1539                   }
1540               }
1541             else if (frame_pointer_needed
1542                      && reg == frame_pointer_rtx)
1543               {
1544                 ok = true;
1545               }
1546           }
1547       }
1548       break;
1549       
1550     default:
1551       break;
1552     }
1553   
1554   if (avr_log.legitimate_address_p)
1555     {
1556       avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
1557                  "reload_completed=%d reload_in_progress=%d %s:",
1558                  ok, mode, strict, reload_completed, reload_in_progress,
1559                  reg_renumber ? "(reg_renumber)" : "");
1560       
1561       if (GET_CODE (x) == PLUS
1562           && REG_P (XEXP (x, 0))
1563           && CONST_INT_P (XEXP (x, 1))
1564           && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
1565           && reg_renumber)
1566         {
1567           avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
1568                      true_regnum (XEXP (x, 0)));
1569         }
1570       
1571       avr_edump ("\n%r\n", x);
1572     }
1573   
1574   return ok;
1575 }
1576
1577
1578 /* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
1579    now only a helper for avr_addr_space_legitimize_address.  */
1580 /* Attempts to replace X with a valid
1581    memory address for an operand of mode MODE  */
1582
1583 static rtx
1584 avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
1585 {
1586   bool big_offset_p = false;
1587   
1588   x = oldx;
1589   
1590   if (GET_CODE (oldx) == PLUS
1591       && REG_P (XEXP (oldx, 0)))
1592     {
1593       if (REG_P (XEXP (oldx, 1)))
1594         x = force_reg (GET_MODE (oldx), oldx);
1595       else if (CONST_INT_P (XEXP (oldx, 1)))
1596         {
1597           int offs = INTVAL (XEXP (oldx, 1));
1598           if (frame_pointer_rtx != XEXP (oldx, 0)
1599               && offs > MAX_LD_OFFSET (mode))
1600             {
1601               big_offset_p = true;
1602               x = force_reg (GET_MODE (oldx), oldx);
1603             }
1604         }
1605     }
1606   
1607   if (avr_log.legitimize_address)
1608     {
1609       avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
1610
1611       if (x != oldx)
1612         avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
1613     }
1614
1615   return x;
1616 }
1617
1618
1619 /* Implement `LEGITIMIZE_RELOAD_ADDRESS'.  */
1620 /* This will allow register R26/27 to be used where it is no worse than normal
1621    base pointers R28/29 or R30/31.  For example, if base offset is greater
1622    than 63 bytes or for R++ or --R addressing.  */
1623
1624 rtx
1625 avr_legitimize_reload_address (rtx *px, enum machine_mode mode,
1626                                int opnum, int type, int addr_type,
1627                                int ind_levels ATTRIBUTE_UNUSED,
1628                                rtx (*mk_memloc)(rtx,int))
1629 {
1630   rtx x = *px;
1631   
1632   if (avr_log.legitimize_reload_address)
1633     avr_edump ("\n%?:%m %r\n", mode, x);
1634   
1635   if (1 && (GET_CODE (x) == POST_INC
1636             || GET_CODE (x) == PRE_DEC))
1637     {
1638       push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
1639                    POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
1640                    opnum, RELOAD_OTHER);
1641       
1642       if (avr_log.legitimize_reload_address)
1643         avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
1644                    POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
1645       
1646       return x;
1647     }
1648   
1649   if (GET_CODE (x) == PLUS
1650       && REG_P (XEXP (x, 0))
1651       && 0 == reg_equiv_constant (REGNO (XEXP (x, 0)))
1652       && CONST_INT_P (XEXP (x, 1))
1653       && INTVAL (XEXP (x, 1)) >= 1)
1654     {
1655       bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
1656       
1657       if (fit)
1658         {
1659           if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
1660             {
1661               int regno = REGNO (XEXP (x, 0));
1662               rtx mem = mk_memloc (x, regno);
1663               
1664               push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
1665                            POINTER_REGS, Pmode, VOIDmode, 0, 0,
1666                            1, addr_type);
1667               
1668               if (avr_log.legitimize_reload_address)
1669                 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
1670                            POINTER_REGS, XEXP (mem, 0), NULL_RTX);
1671               
1672               push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
1673                            BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
1674                            opnum, type);
1675               
1676               if (avr_log.legitimize_reload_address)
1677                 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
1678                            BASE_POINTER_REGS, mem, NULL_RTX);
1679               
1680               return x;
1681             }
1682         }
1683       else if (! (frame_pointer_needed
1684                   && XEXP (x, 0) == frame_pointer_rtx))
1685         {
1686           push_reload (x, NULL_RTX, px, NULL,
1687                        POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
1688                        opnum, type);
1689           
1690           if (avr_log.legitimize_reload_address)
1691             avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
1692                        POINTER_REGS, x, NULL_RTX);
1693           
1694           return x;
1695         }
1696     }
1697   
1698   return NULL_RTX;
1699 }
1700
1701
1702 /* Helper function to print assembler resp. track instruction
1703    sequence lengths.  Always return "".
1704    
1705    If PLEN == NULL:
1706        Output assembler code from template TPL with operands supplied
1707        by OPERANDS.  This is just forwarding to output_asm_insn.
1708    
1709    If PLEN != NULL:
1710        If N_WORDS >= 0  Add N_WORDS to *PLEN.
1711        If N_WORDS < 0   Set *PLEN to -N_WORDS.
1712        Don't output anything.
1713 */
1714
1715 static const char*
1716 avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
1717 {
1718   if (NULL == plen)
1719     {
1720       output_asm_insn (tpl, operands);
1721     }
1722   else
1723     {
1724       if (n_words < 0)
1725         *plen = -n_words;
1726       else
1727         *plen += n_words;
1728     }
1729
1730   return "";
1731 }
1732
1733
1734 /* Return a pointer register name as a string.  */
1735
1736 static const char *
1737 ptrreg_to_str (int regno)
1738 {
1739   switch (regno)
1740     {
1741     case REG_X: return "X";
1742     case REG_Y: return "Y";
1743     case REG_Z: return "Z";
1744     default:
1745       output_operand_lossage ("address operand requires constraint for"
1746                               " X, Y, or Z register");
1747     }
1748   return NULL;
1749 }
1750
1751 /* Return the condition name as a string.
1752    Used in conditional jump constructing  */
1753
1754 static const char *
1755 cond_string (enum rtx_code code)
1756 {
1757   switch (code)
1758     {
1759     case NE:
1760       return "ne";
1761     case EQ:
1762       return "eq";
1763     case GE:
1764       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1765         return "pl";
1766       else
1767         return "ge";
1768     case LT:
1769       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1770         return "mi";
1771       else
1772         return "lt";
1773     case GEU:
1774       return "sh";
1775     case LTU:
1776       return "lo";
1777     default:
1778       gcc_unreachable ();
1779     }
1780
1781   return "";
1782 }
1783
1784
1785 /* Implement `TARGET_PRINT_OPERAND_ADDRESS'.  */
1786 /* Output ADDR to FILE as address.  */
1787
1788 static void
1789 avr_print_operand_address (FILE *file, rtx addr)
1790 {
1791   switch (GET_CODE (addr))
1792     {
1793     case REG:
1794       fprintf (file, ptrreg_to_str (REGNO (addr)));
1795       break;
1796
1797     case PRE_DEC:
1798       fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1799       break;
1800
1801     case POST_INC:
1802       fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1803       break;
1804
1805     default:
1806       if (CONSTANT_ADDRESS_P (addr)
1807           && text_segment_operand (addr, VOIDmode))
1808         {
1809           rtx x = addr;
1810           if (GET_CODE (x) == CONST)
1811             x = XEXP (x, 0);
1812           if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x,1)) == CONST_INT)
1813             {
1814               /* Assembler gs() will implant word address. Make offset 
1815                  a byte offset inside gs() for assembler. This is 
1816                  needed because the more logical (constant+gs(sym)) is not 
1817                  accepted by gas. For 128K and lower devices this is ok.
1818                  For large devices it will create a Trampoline to offset
1819                  from symbol which may not be what the user really wanted.  */
1820               fprintf (file, "gs(");
1821               output_addr_const (file, XEXP (x,0));
1822               fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC ")",
1823                        2 * INTVAL (XEXP (x, 1)));
1824               if (AVR_3_BYTE_PC)
1825                 if (warning (0, "pointer offset from symbol maybe incorrect"))
1826                   {
1827                     output_addr_const (stderr, addr);
1828                     fprintf(stderr,"\n");
1829                   }
1830             }
1831           else
1832             {
1833               fprintf (file, "gs(");
1834               output_addr_const (file, addr);
1835               fprintf (file, ")");
1836             }
1837         }
1838       else
1839         output_addr_const (file, addr);
1840     }
1841 }
1842
1843
1844 /* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'.  */
1845
1846 static bool
1847 avr_print_operand_punct_valid_p (unsigned char code)
1848 {
1849   return code == '~' || code == '!';
1850 }
1851
1852
1853 /* Implement `TARGET_PRINT_OPERAND'.  */
1854 /* Output X as assembler operand to file FILE.
1855    For a description of supported %-codes, see top of avr.md.  */
1856
1857 static void
1858 avr_print_operand (FILE *file, rtx x, int code)
1859 {
1860   int abcd = 0;
1861
1862   if (code >= 'A' && code <= 'D')
1863     abcd = code - 'A';
1864
1865   if (code == '~')
1866     {
1867       if (!AVR_HAVE_JMP_CALL)
1868         fputc ('r', file);
1869     }
1870   else if (code == '!')
1871     {
1872       if (AVR_HAVE_EIJMP_EICALL)
1873         fputc ('e', file);
1874     }
1875   else if (code == 't'
1876            || code == 'T')
1877     {
1878       static int t_regno = -1;
1879       static int t_nbits = -1;
1880
1881       if (REG_P (x) && t_regno < 0 && code == 'T')
1882         {
1883           t_regno = REGNO (x);
1884           t_nbits = GET_MODE_BITSIZE (GET_MODE (x));
1885         }
1886       else if (CONST_INT_P (x) && t_regno >= 0
1887                && IN_RANGE (INTVAL (x), 0, t_nbits - 1))
1888         {
1889           int bpos = INTVAL (x);
1890
1891           fprintf (file, "%s", reg_names[t_regno + bpos / 8]);
1892           if (code == 'T')
1893             fprintf (file, ",%d", bpos % 8);
1894
1895           t_regno = -1;
1896         }
1897       else
1898         fatal_insn ("operands to %T/%t must be reg + const_int:", x);
1899     }
1900   else if (REG_P (x))
1901     {
1902       if (x == zero_reg_rtx)
1903         fprintf (file, "__zero_reg__");
1904       else
1905         fprintf (file, reg_names[true_regnum (x) + abcd]);
1906     }
1907   else if (CONST_INT_P (x))
1908     {
1909       HOST_WIDE_INT ival = INTVAL (x);
1910         
1911       if ('i' != code)
1912         fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival + abcd);
1913       else if (low_io_address_operand (x, VOIDmode)
1914                || high_io_address_operand (x, VOIDmode))
1915         {
1916           if (AVR_HAVE_RAMPZ && ival == avr_addr.rampz)
1917             fprintf (file, "__RAMPZ__");
1918           else if (AVR_HAVE_RAMPY && ival == avr_addr.rampy)
1919             fprintf (file, "__RAMPY__");
1920           else if (AVR_HAVE_RAMPX && ival == avr_addr.rampx)
1921             fprintf (file, "__RAMPX__");
1922           else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd)
1923             fprintf (file, "__RAMPD__");
1924           else if (AVR_XMEGA && ival == avr_addr.ccp)
1925             fprintf (file, "__CCP__");
1926           else if (ival == avr_addr.sreg)   fprintf (file, "__SREG__");
1927           else if (ival == avr_addr.sp_l)   fprintf (file, "__SP_L__");
1928           else if (ival == avr_addr.sp_h)   fprintf (file, "__SP_H__");
1929           else
1930             {
1931               fprintf (file, HOST_WIDE_INT_PRINT_HEX,
1932                        ival - avr_current_arch->sfr_offset);
1933             }
1934         }
1935       else
1936         fatal_insn ("bad address, not an I/O address:", x);
1937     }
1938   else if (MEM_P (x))
1939     {
1940       rtx addr = XEXP (x, 0);
1941       
1942       if (code == 'm')
1943         {
1944           if (!CONSTANT_P (addr))
1945             fatal_insn ("bad address, not a constant:", addr);
1946           /* Assembler template with m-code is data - not progmem section */
1947           if (text_segment_operand (addr, VOIDmode))
1948             if (warning (0, "accessing data memory with"
1949                          " program memory address"))
1950               {
1951                 output_addr_const (stderr, addr);
1952                 fprintf(stderr,"\n");
1953               }
1954           output_addr_const (file, addr);
1955         }
1956       else if (code == 'i')
1957         {
1958           avr_print_operand (file, addr, 'i');
1959         }
1960       else if (code == 'o')
1961         {
1962           if (GET_CODE (addr) != PLUS)
1963             fatal_insn ("bad address, not (reg+disp):", addr);
1964
1965           avr_print_operand (file, XEXP (addr, 1), 0);
1966         }
1967       else if (code == 'p' || code == 'r')
1968         {
1969           if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
1970             fatal_insn ("bad address, not post_inc or pre_dec:", addr);
1971           
1972           if (code == 'p')
1973             avr_print_operand_address (file, XEXP (addr, 0));  /* X, Y, Z */
1974           else
1975             avr_print_operand (file, XEXP (addr, 0), 0);  /* r26, r28, r30 */
1976         }
1977       else if (GET_CODE (addr) == PLUS)
1978         {
1979           avr_print_operand_address (file, XEXP (addr,0));
1980           if (REGNO (XEXP (addr, 0)) == REG_X)
1981             fatal_insn ("internal compiler error.  Bad address:"
1982                         ,addr);
1983           fputc ('+', file);
1984           avr_print_operand (file, XEXP (addr,1), code);
1985         }
1986       else
1987         avr_print_operand_address (file, addr);
1988     }
1989   else if (code == 'i')
1990     {
1991       fatal_insn ("bad address, not an I/O address:", x);
1992     }
1993   else if (code == 'x')
1994     {
1995       /* Constant progmem address - like used in jmp or call */
1996       if (0 == text_segment_operand (x, VOIDmode))
1997         if (warning (0, "accessing program memory"
1998                      " with data memory address"))
1999           {
2000             output_addr_const (stderr, x);
2001             fprintf(stderr,"\n");
2002           }
2003       /* Use normal symbol for direct address no linker trampoline needed */
2004       output_addr_const (file, x);
2005     }
2006   else if (GET_CODE (x) == CONST_DOUBLE)
2007     {
2008       long val;
2009       REAL_VALUE_TYPE rv;
2010       if (GET_MODE (x) != SFmode)
2011         fatal_insn ("internal compiler error.  Unknown mode:", x);
2012       REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
2013       REAL_VALUE_TO_TARGET_SINGLE (rv, val);
2014       fprintf (file, "0x%lx", val);
2015     }
2016   else if (GET_CODE (x) == CONST_STRING)
2017     fputs (XSTR (x, 0), file);
2018   else if (code == 'j')
2019     fputs (cond_string (GET_CODE (x)), file);
2020   else if (code == 'k')
2021     fputs (cond_string (reverse_condition (GET_CODE (x))), file);
2022   else
2023     avr_print_operand_address (file, x);
2024 }
2025
2026 /* Update the condition code in the INSN.  */
2027
2028 void
2029 notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
2030 {
2031   rtx set;
2032   enum attr_cc cc = get_attr_cc (insn);
2033   
2034   switch (cc)
2035     {
2036     default:
2037       break;
2038
2039     case CC_OUT_PLUS:
2040     case CC_OUT_PLUS_NOCLOBBER:
2041     case CC_LDI:
2042       {
2043         rtx *op = recog_data.operand;
2044         int len_dummy, icc;
2045         
2046         /* Extract insn's operands.  */
2047         extract_constrain_insn_cached (insn);
2048
2049         switch (cc)
2050           {
2051           default:
2052             gcc_unreachable();
2053             
2054           case CC_OUT_PLUS:
2055             avr_out_plus (op, &len_dummy, &icc);
2056             cc = (enum attr_cc) icc;
2057             break;
2058             
2059           case CC_OUT_PLUS_NOCLOBBER:
2060             avr_out_plus_noclobber (op, &len_dummy, &icc);
2061             cc = (enum attr_cc) icc;
2062             break;
2063
2064           case CC_LDI:
2065
2066             cc = (op[1] == CONST0_RTX (GET_MODE (op[0]))
2067                   && reg_overlap_mentioned_p (op[0], zero_reg_rtx))
2068               /* Loading zero-reg with 0 uses CLI and thus clobbers cc0.  */
2069               ? CC_CLOBBER
2070               /* Any other "r,rL" combination does not alter cc0.  */
2071               : CC_NONE;
2072             
2073             break;
2074           } /* inner switch */
2075
2076         break;
2077       }
2078     } /* outer swicth */
2079
2080   switch (cc)
2081     {
2082     default:
2083       /* Special values like CC_OUT_PLUS from above have been
2084          mapped to "standard" CC_* values so we never come here.  */
2085       
2086       gcc_unreachable();
2087       break;
2088       
2089     case CC_NONE:
2090       /* Insn does not affect CC at all.  */
2091       break;
2092
2093     case CC_SET_N:
2094       CC_STATUS_INIT;
2095       break;
2096
2097     case CC_SET_ZN:
2098       set = single_set (insn);
2099       CC_STATUS_INIT;
2100       if (set)
2101         {
2102           cc_status.flags |= CC_NO_OVERFLOW;
2103           cc_status.value1 = SET_DEST (set);
2104         }
2105       break;
2106
2107     case CC_SET_CZN:
2108       /* Insn sets the Z,N,C flags of CC to recog_operand[0].
2109          The V flag may or may not be known but that's ok because
2110          alter_cond will change tests to use EQ/NE.  */
2111       set = single_set (insn);
2112       CC_STATUS_INIT;
2113       if (set)
2114         {
2115           cc_status.value1 = SET_DEST (set);
2116           cc_status.flags |= CC_OVERFLOW_UNUSABLE;
2117         }
2118       break;
2119
2120     case CC_COMPARE:
2121       set = single_set (insn);
2122       CC_STATUS_INIT;
2123       if (set)
2124         cc_status.value1 = SET_SRC (set);
2125       break;
2126       
2127     case CC_CLOBBER:
2128       /* Insn doesn't leave CC in a usable state.  */
2129       CC_STATUS_INIT;
2130       break;
2131     }
2132 }
2133
2134 /* Choose mode for jump insn:
2135    1 - relative jump in range -63 <= x <= 62 ;
2136    2 - relative jump in range -2046 <= x <= 2045 ;
2137    3 - absolute jump (only for ATmega[16]03).  */
2138
2139 int
2140 avr_jump_mode (rtx x, rtx insn)
2141 {
2142   int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
2143                                             ? XEXP (x, 0) : x));
2144   int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
2145   int jump_distance = cur_addr - dest_addr;
2146   
2147   if (-63 <= jump_distance && jump_distance <= 62)
2148     return 1;
2149   else if (-2046 <= jump_distance && jump_distance <= 2045)
2150     return 2;
2151   else if (AVR_HAVE_JMP_CALL)
2152     return 3;
2153   
2154   return 2;
2155 }
2156
2157 /* return an AVR condition jump commands.
2158    X is a comparison RTX.
2159    LEN is a number returned by avr_jump_mode function.
2160    if REVERSE nonzero then condition code in X must be reversed.  */
2161
2162 const char *
2163 ret_cond_branch (rtx x, int len, int reverse)
2164 {
2165   RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
2166   
2167   switch (cond)
2168     {
2169     case GT:
2170       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2171         return (len == 1 ? ("breq .+2" CR_TAB
2172                             "brpl %0") :
2173                 len == 2 ? ("breq .+4" CR_TAB
2174                             "brmi .+2" CR_TAB
2175                             "rjmp %0") :
2176                 ("breq .+6" CR_TAB
2177                  "brmi .+4" CR_TAB
2178                  "jmp %0"));
2179           
2180       else
2181         return (len == 1 ? ("breq .+2" CR_TAB
2182                             "brge %0") :
2183                 len == 2 ? ("breq .+4" CR_TAB
2184                             "brlt .+2" CR_TAB
2185                             "rjmp %0") :
2186                 ("breq .+6" CR_TAB
2187                  "brlt .+4" CR_TAB
2188                  "jmp %0"));
2189     case GTU:
2190       return (len == 1 ? ("breq .+2" CR_TAB
2191                           "brsh %0") :
2192               len == 2 ? ("breq .+4" CR_TAB
2193                           "brlo .+2" CR_TAB
2194                           "rjmp %0") :
2195               ("breq .+6" CR_TAB
2196                "brlo .+4" CR_TAB
2197                "jmp %0"));
2198     case LE:
2199       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2200         return (len == 1 ? ("breq %0" CR_TAB
2201                             "brmi %0") :
2202                 len == 2 ? ("breq .+2" CR_TAB
2203                             "brpl .+2" CR_TAB
2204                             "rjmp %0") :
2205                 ("breq .+2" CR_TAB
2206                  "brpl .+4" CR_TAB
2207                  "jmp %0"));
2208       else
2209         return (len == 1 ? ("breq %0" CR_TAB
2210                             "brlt %0") :
2211                 len == 2 ? ("breq .+2" CR_TAB
2212                             "brge .+2" CR_TAB
2213                             "rjmp %0") :
2214                 ("breq .+2" CR_TAB
2215                  "brge .+4" CR_TAB
2216                  "jmp %0"));
2217     case LEU:
2218       return (len == 1 ? ("breq %0" CR_TAB
2219                           "brlo %0") :
2220               len == 2 ? ("breq .+2" CR_TAB
2221                           "brsh .+2" CR_TAB
2222                           "rjmp %0") :
2223               ("breq .+2" CR_TAB
2224                "brsh .+4" CR_TAB
2225                "jmp %0"));
2226     default:
2227       if (reverse)
2228         {
2229           switch (len)
2230             {
2231             case 1:
2232               return "br%k1 %0";
2233             case 2:
2234               return ("br%j1 .+2" CR_TAB
2235                       "rjmp %0");
2236             default:
2237               return ("br%j1 .+4" CR_TAB
2238                       "jmp %0");
2239             }
2240         }
2241       else
2242         {
2243           switch (len)
2244             {
2245             case 1:
2246               return "br%j1 %0";
2247             case 2:
2248               return ("br%k1 .+2" CR_TAB
2249                       "rjmp %0");
2250             default:
2251               return ("br%k1 .+4" CR_TAB
2252                       "jmp %0");
2253             }
2254         }
2255     }
2256   return "";
2257 }
2258
2259 /* Output insn cost for next insn.  */
2260
2261 void
2262 final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
2263                     int num_operands ATTRIBUTE_UNUSED)
2264 {
2265   if (avr_log.rtx_costs)
2266     {
2267       rtx set = single_set (insn);
2268
2269       if (set)
2270         fprintf (asm_out_file, "/* DEBUG: cost = %d.  */\n",
2271                  set_src_cost (SET_SRC (set), optimize_insn_for_speed_p ()));
2272       else
2273         fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d.  */\n",
2274                  rtx_cost (PATTERN (insn), INSN, 0,
2275                            optimize_insn_for_speed_p()));
2276     }
2277 }
2278
2279 /* Return 0 if undefined, 1 if always true or always false.  */
2280
2281 int
2282 avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE op, rtx x)
2283 {
2284   unsigned int max = (mode == QImode ? 0xff :
2285                       mode == HImode ? 0xffff :
2286                       mode == PSImode ? 0xffffff :
2287                       mode == SImode ? 0xffffffff : 0);
2288   if (max && op && GET_CODE (x) == CONST_INT)
2289     {
2290       if (unsigned_condition (op) != op)
2291         max >>= 1;
2292
2293       if (max != (INTVAL (x) & max)
2294           && INTVAL (x) != 0xff)
2295         return 1;
2296     }
2297   return 0;
2298 }
2299
2300
2301 /* Returns nonzero if REGNO is the number of a hard
2302    register in which function arguments are sometimes passed.  */
2303
2304 int
2305 function_arg_regno_p(int r)
2306 {
2307   return (r >= 8 && r <= 25);
2308 }
2309
2310 /* Initializing the variable cum for the state at the beginning
2311    of the argument list.  */
2312
2313 void
2314 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
2315                       tree fndecl ATTRIBUTE_UNUSED)
2316 {
2317   cum->nregs = 18;
2318   cum->regno = FIRST_CUM_REG;
2319   if (!libname && stdarg_p (fntype))
2320     cum->nregs = 0;
2321
2322   /* Assume the calle may be tail called */
2323   
2324   cfun->machine->sibcall_fails = 0;
2325 }
2326
2327 /* Returns the number of registers to allocate for a function argument.  */
2328
2329 static int
2330 avr_num_arg_regs (enum machine_mode mode, const_tree type)
2331 {
2332   int size;
2333
2334   if (mode == BLKmode)
2335     size = int_size_in_bytes (type);
2336   else
2337     size = GET_MODE_SIZE (mode);
2338
2339   /* Align all function arguments to start in even-numbered registers.
2340      Odd-sized arguments leave holes above them.  */
2341
2342   return (size + 1) & ~1;
2343 }
2344
2345 /* Controls whether a function argument is passed
2346    in a register, and which register.  */
2347
2348 static rtx
2349 avr_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
2350                   const_tree type, bool named ATTRIBUTE_UNUSED)
2351 {
2352   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2353   int bytes = avr_num_arg_regs (mode, type);
2354
2355   if (cum->nregs && bytes <= cum->nregs)
2356     return gen_rtx_REG (mode, cum->regno - bytes);
2357
2358   return NULL_RTX;
2359 }
2360
2361 /* Update the summarizer variable CUM to advance past an argument
2362    in the argument list.  */
2363    
2364 static void
2365 avr_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
2366                           const_tree type, bool named ATTRIBUTE_UNUSED)
2367 {
2368   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2369   int bytes = avr_num_arg_regs (mode, type);
2370
2371   cum->nregs -= bytes;
2372   cum->regno -= bytes;
2373
2374   /* A parameter is being passed in a call-saved register. As the original
2375      contents of these regs has to be restored before leaving the function,
2376      a function must not pass arguments in call-saved regs in order to get
2377      tail-called. */
2378   
2379   if (cum->regno >= 8
2380       && cum->nregs >= 0
2381       && !call_used_regs[cum->regno])
2382     {
2383       /* FIXME: We ship info on failing tail-call in struct machine_function.
2384          This uses internals of calls.c:expand_call() and the way args_so_far
2385          is used. targetm.function_ok_for_sibcall() needs to be extended to
2386          pass &args_so_far, too. At present, CUMULATIVE_ARGS is target
2387          dependent so that such an extension is not wanted. */
2388       
2389       cfun->machine->sibcall_fails = 1;
2390     }
2391
2392   /* Test if all registers needed by the ABI are actually available.  If the
2393      user has fixed a GPR needed to pass an argument, an (implicit) function
2394      call will clobber that fixed register.  See PR45099 for an example.  */
2395   
2396   if (cum->regno >= 8
2397       && cum->nregs >= 0)
2398     {
2399       int regno;
2400
2401       for (regno = cum->regno; regno < cum->regno + bytes; regno++)
2402         if (fixed_regs[regno])
2403           warning (0, "fixed register %s used to pass parameter to function",
2404                    reg_names[regno]);
2405     }
2406       
2407   if (cum->nregs <= 0)
2408     {
2409       cum->nregs = 0;
2410       cum->regno = FIRST_CUM_REG;
2411     }
2412 }
2413
2414 /* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
2415 /* Decide whether we can make a sibling call to a function.  DECL is the
2416    declaration of the function being targeted by the call and EXP is the
2417    CALL_EXPR representing the call. */
2418
2419 static bool
2420 avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
2421 {
2422   tree fntype_callee;
2423
2424   /* Tail-calling must fail if callee-saved regs are used to pass
2425      function args.  We must not tail-call when `epilogue_restores'
2426      is used.  Unfortunately, we cannot tell at this point if that
2427      actually will happen or not, and we cannot step back from
2428      tail-calling. Thus, we inhibit tail-calling with -mcall-prologues. */
2429   
2430   if (cfun->machine->sibcall_fails
2431       || TARGET_CALL_PROLOGUES)
2432     {
2433       return false;
2434     }
2435   
2436   fntype_callee = TREE_TYPE (CALL_EXPR_FN (exp_callee));
2437
2438   if (decl_callee)
2439     {
2440       decl_callee = TREE_TYPE (decl_callee);
2441     }
2442   else
2443     {
2444       decl_callee = fntype_callee;
2445       
2446       while (FUNCTION_TYPE != TREE_CODE (decl_callee)
2447              && METHOD_TYPE != TREE_CODE (decl_callee))
2448         {
2449           decl_callee = TREE_TYPE (decl_callee);
2450         }
2451     }
2452
2453   /* Ensure that caller and callee have compatible epilogues */
2454   
2455   if (interrupt_function_p (current_function_decl)
2456       || signal_function_p (current_function_decl)
2457       || avr_naked_function_p (decl_callee)
2458       || avr_naked_function_p (current_function_decl)
2459       /* FIXME: For OS_task and OS_main, we are over-conservative.
2460          This is due to missing documentation of these attributes
2461          and what they actually should do and should not do. */
2462       || (avr_OS_task_function_p (decl_callee)
2463           != avr_OS_task_function_p (current_function_decl))
2464       || (avr_OS_main_function_p (decl_callee)
2465           != avr_OS_main_function_p (current_function_decl)))
2466     {
2467       return false;
2468     }
2469  
2470   return true;
2471 }
2472
2473 /***********************************************************************
2474   Functions for outputting various mov's for a various modes
2475 ************************************************************************/
2476
2477 /* Return true if a value of mode MODE is read from flash by
2478    __load_* function from libgcc.  */
2479
2480 bool
2481 avr_load_libgcc_p (rtx op)
2482 {
2483   enum machine_mode mode = GET_MODE (op);
2484   int n_bytes = GET_MODE_SIZE (mode);
2485         
2486   return (n_bytes > 2
2487           && !AVR_HAVE_LPMX
2488           && MEM_P (op)
2489           && MEM_ADDR_SPACE (op) == ADDR_SPACE_FLASH);
2490 }
2491
2492 /* Return true if a value of mode MODE is read by __xload_* function.  */
2493
2494 bool
2495 avr_xload_libgcc_p (enum machine_mode mode)
2496 {
2497   int n_bytes = GET_MODE_SIZE (mode);
2498   
2499   return (n_bytes > 1
2500           || avr_current_device->n_flash > 1);
2501 }
2502
2503
2504 /* If PLEN == NULL: Ouput instructions to load a value from a memory location
2505    OP[1] in AS1 to register OP[0].
2506    If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
2507    Return "".  */
2508
2509 static const char*
2510 avr_out_lpm (rtx insn, rtx *op, int *plen)
2511 {
2512   rtx xop[3];
2513   rtx dest = op[0];
2514   rtx src = SET_SRC (single_set (insn));
2515   rtx addr;
2516   int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
2517   RTX_CODE code;
2518   addr_space_t as = MEM_ADDR_SPACE (src);
2519
2520   if (plen)
2521     *plen = 0;
2522   
2523   if (MEM_P (dest))
2524     {
2525       warning (0, "writing to address space %qs not supported",
2526                avr_addrspace[MEM_ADDR_SPACE (dest)].name);
2527       
2528       return "";
2529     }
2530
2531   addr = XEXP (src, 0);
2532   code = GET_CODE (addr);
2533
2534   gcc_assert (REG_P (dest));
2535   gcc_assert (REG == code || POST_INC == code);
2536
2537   /* Only 1-byte moves from __flash are representes as open coded
2538      mov insns.  All other loads from flash are not handled here but
2539      by some UNSPEC instead, see respective FIXME in machine description.  */
2540   
2541   gcc_assert (as == ADDR_SPACE_FLASH);
2542   gcc_assert (n_bytes == 1);
2543
2544   xop[0] = dest;
2545   xop[1] = lpm_addr_reg_rtx;
2546   xop[2] = lpm_reg_rtx;
2547
2548   switch (code)
2549     {
2550     default:
2551       gcc_unreachable();
2552
2553     case REG:
2554
2555       gcc_assert (REG_Z == REGNO (addr));
2556       
2557       return AVR_HAVE_LPMX
2558         ? avr_asm_len ("lpm %0,%a1", xop, plen, 1)
2559         : avr_asm_len ("lpm" CR_TAB
2560                        "mov %0,%2", xop, plen, 2);
2561       
2562     case POST_INC:
2563       
2564       gcc_assert (REG_Z == REGNO (XEXP (addr, 0)));
2565
2566       return AVR_HAVE_LPMX
2567         ? avr_asm_len ("lpm %0,%a1+", xop, plen, 1)
2568         : avr_asm_len ("lpm"        CR_TAB
2569                        "adiw %1, 1" CR_TAB
2570                        "mov %0,%2", xop, plen, 3);
2571     }
2572
2573   return "";
2574 }
2575
2576
2577 /* If PLEN == NULL: Ouput instructions to load $0 with a value from
2578    flash address $1:Z.  If $1 = 0 we can use LPM to read, otherwise
2579    use ELPM.
2580    If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
2581    Return "".  */
2582
2583 const char*
2584 avr_load_lpm (rtx insn, rtx *op, int *plen)
2585 {
2586   rtx xop[4];
2587   int n, n_bytes = GET_MODE_SIZE (GET_MODE (op[0]));
2588   rtx xsegment = op[1];
2589   bool clobber_z = PARALLEL == GET_CODE (PATTERN (insn));
2590   bool r30_in_tmp = false;
2591   
2592   if (plen)
2593     *plen = 0;
2594   
2595   xop[1] = lpm_addr_reg_rtx;
2596   xop[2] = lpm_reg_rtx;
2597   xop[3] = xstring_empty;
2598   
2599   /* Set RAMPZ as needed.  */
2600   
2601   if (REG_P (xsegment))
2602     {
2603       avr_asm_len ("out __RAMPZ__,%0", &xsegment, plen, 1);
2604       xop[3] = xstring_e;
2605     }
2606   
2607   /* Load the individual bytes from LSB to MSB.  */
2608   
2609   for (n = 0; n < n_bytes; n++)
2610     {
2611       xop[0] = all_regs_rtx[REGNO (op[0]) + n];
2612       
2613       if ((CONST_INT_P (xsegment) && AVR_HAVE_LPMX)
2614           || (REG_P (xsegment) && AVR_HAVE_ELPMX))
2615         {
2616           if (n == n_bytes-1)
2617             avr_asm_len ("%3lpm %0,%a1", xop, plen, 1);
2618           else if (REGNO (xop[0]) == REG_Z)
2619             {
2620               avr_asm_len ("%3lpm %2,%a1+", xop, plen, 1);
2621               r30_in_tmp = true;
2622             }
2623           else
2624             avr_asm_len ("%3lpm %0,%a1+", xop, plen, 1);
2625         }
2626       else
2627         {
2628           gcc_assert (clobber_z);
2629           
2630           avr_asm_len ("%3lpm" CR_TAB
2631                        "mov %0,%2", xop, plen, 2);
2632
2633           if (n != n_bytes-1)
2634             avr_asm_len ("adiw %1,1", xop, plen, 1);
2635         }
2636     }
2637   
2638   if (r30_in_tmp)
2639     avr_asm_len ("mov %1,%2", xop, plen, 1);
2640   
2641   if (!clobber_z
2642       && n_bytes > 1
2643       && !reg_unused_after (insn, lpm_addr_reg_rtx)
2644       && !reg_overlap_mentioned_p (op[0], lpm_addr_reg_rtx))
2645     {
2646       xop[2] = GEN_INT (n_bytes-1);
2647       avr_asm_len ("sbiw %1,%2", xop, plen, 1);
2648     }
2649   
2650   if (REG_P (xsegment) && AVR_HAVE_RAMPD)
2651     {
2652       /* Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM */
2653       
2654       avr_asm_len ("out __RAMPZ__,__zero_reg__", xop, plen, 1);
2655     }
2656
2657   return "";
2658 }
2659
2660
2661 /* Worker function for xload_8 insn.  */
2662
2663 const char*
2664 avr_out_xload (rtx insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
2665 {
2666   rtx xop[4];
2667
2668   xop[0] = op[0];
2669   xop[1] = op[1];
2670   xop[2] = lpm_addr_reg_rtx;
2671   xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
2672
2673   if (plen)
2674     *plen = 0;
2675
2676   avr_asm_len ("sbrc %1,7" CR_TAB
2677                "ld %3,%a2" CR_TAB
2678                "sbrs %1,7", xop, plen, 3);
2679
2680   avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, 1);
2681
2682   if (REGNO (xop[0]) != REGNO (xop[3]))
2683     avr_asm_len ("mov %0,%3", xop, plen, 1);
2684   
2685   return "";
2686 }
2687
2688
2689 const char*
2690 output_movqi (rtx insn, rtx operands[], int *real_l)
2691 {
2692   rtx dest = operands[0];
2693   rtx src = operands[1];
2694   
2695   if (avr_mem_flash_p (src)
2696       || avr_mem_flash_p (dest))
2697     {
2698       return avr_out_lpm (insn, operands, real_l);
2699     }
2700
2701   if (real_l)
2702     *real_l = 1;
2703   
2704   if (register_operand (dest, QImode))
2705     {
2706       if (register_operand (src, QImode)) /* mov r,r */
2707         {
2708           if (test_hard_reg_class (STACK_REG, dest))
2709             return "out %0,%1";
2710           else if (test_hard_reg_class (STACK_REG, src))
2711             return "in %0,%1";
2712           
2713           return "mov %0,%1";
2714         }
2715       else if (CONSTANT_P (src))
2716         {
2717           output_reload_in_const (operands, NULL_RTX, real_l, false);
2718           return "";
2719         }
2720       else if (MEM_P (src))
2721         return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
2722     }
2723   else if (MEM_P (dest))
2724     {
2725       rtx xop[2];
2726
2727       xop[0] = dest;
2728       xop[1] = src == const0_rtx ? zero_reg_rtx : src;
2729
2730       return out_movqi_mr_r (insn, xop, real_l);
2731     }
2732   return "";
2733 }
2734
2735
2736 const char *
2737 output_movhi (rtx insn, rtx xop[], int *plen)
2738 {
2739   rtx dest = xop[0];
2740   rtx src = xop[1];
2741
2742   gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 2);
2743   
2744   if (avr_mem_flash_p (src)
2745       || avr_mem_flash_p (dest))
2746     {
2747       return avr_out_lpm (insn, xop, plen);
2748     }
2749
2750   if (REG_P (dest))
2751     {
2752       if (REG_P (src)) /* mov r,r */
2753         {
2754           if (test_hard_reg_class (STACK_REG, dest))
2755             {
2756               if (AVR_HAVE_8BIT_SP)
2757                 return avr_asm_len ("out __SP_L__,%A1", xop, plen, -1);
2758
2759               if (AVR_XMEGA)
2760                 return avr_asm_len ("out __SP_L__,%A1" CR_TAB
2761                                     "out __SP_H__,%B1", xop, plen, -2);
2762               
2763               /* Use simple load of SP if no interrupts are  used.  */
2764               
2765               return TARGET_NO_INTERRUPTS
2766                 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
2767                                "out __SP_L__,%A1", xop, plen, -2)
2768
2769                 : avr_asm_len ("in __tmp_reg__,__SREG__"  CR_TAB
2770                                "cli"                      CR_TAB
2771                                "out __SP_H__,%B1"         CR_TAB
2772                                "out __SREG__,__tmp_reg__" CR_TAB
2773                                "out __SP_L__,%A1", xop, plen, -5);
2774             }
2775           else if (test_hard_reg_class (STACK_REG, src))
2776             {
2777               return !AVR_HAVE_SPH
2778                 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
2779                                "clr %B0", xop, plen, -2)
2780                 
2781                 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
2782                                "in %B0,__SP_H__", xop, plen, -2);
2783             }
2784
2785           return AVR_HAVE_MOVW
2786             ? avr_asm_len ("movw %0,%1", xop, plen, -1)
2787
2788             : avr_asm_len ("mov %A0,%A1" CR_TAB
2789                            "mov %B0,%B1", xop, plen, -2);
2790         } /* REG_P (src) */
2791       else if (CONSTANT_P (src))
2792         {
2793           return output_reload_inhi (xop, NULL, plen);
2794         }
2795       else if (MEM_P (src))
2796         {
2797           return out_movhi_r_mr (insn, xop, plen); /* mov r,m */
2798         }
2799     }
2800   else if (MEM_P (dest))
2801     {
2802       rtx xop[2];
2803
2804       xop[0] = dest;
2805       xop[1] = src == const0_rtx ? zero_reg_rtx : src;
2806
2807       return out_movhi_mr_r (insn, xop, plen);
2808     }
2809   
2810   fatal_insn ("invalid insn:", insn);
2811   
2812   return "";
2813 }
2814
2815 static const char*
2816 out_movqi_r_mr (rtx insn, rtx op[], int *plen)
2817 {
2818   rtx dest = op[0];
2819   rtx src = op[1];
2820   rtx x = XEXP (src, 0);
2821   
2822   if (CONSTANT_ADDRESS_P (x))
2823     {
2824       return optimize > 0 && io_address_operand (x, QImode)
2825         ? avr_asm_len ("in %0,%i1", op, plen, -1)
2826         : avr_asm_len ("lds %0,%m1", op, plen, -2);
2827     }
2828   else if (GET_CODE (x) == PLUS
2829            && REG_P (XEXP (x, 0))
2830            && CONST_INT_P (XEXP (x, 1)))
2831     {
2832       /* memory access by reg+disp */
2833
2834       int disp = INTVAL (XEXP (x, 1));
2835       
2836       if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
2837         {
2838           if (REGNO (XEXP (x, 0)) != REG_Y)
2839             fatal_insn ("incorrect insn:",insn);
2840
2841           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
2842             return avr_asm_len ("adiw r28,%o1-63" CR_TAB
2843                                 "ldd %0,Y+63"     CR_TAB
2844                                 "sbiw r28,%o1-63", op, plen, -3);
2845
2846           return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
2847                               "sbci r29,hi8(-%o1)" CR_TAB
2848                               "ld %0,Y"            CR_TAB
2849                               "subi r28,lo8(%o1)"  CR_TAB
2850                               "sbci r29,hi8(%o1)", op, plen, -5);
2851         }
2852       else if (REGNO (XEXP (x, 0)) == REG_X)
2853         {
2854           /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
2855              it but I have this situation with extremal optimizing options.  */
2856           
2857           avr_asm_len ("adiw r26,%o1" CR_TAB
2858                        "ld %0,X", op, plen, -2);
2859           
2860           if (!reg_overlap_mentioned_p (dest, XEXP (x,0))
2861               && !reg_unused_after (insn, XEXP (x,0)))
2862             {
2863               avr_asm_len ("sbiw r26,%o1", op, plen, 1);
2864             }
2865
2866           return "";
2867         }
2868
2869       return avr_asm_len ("ldd %0,%1", op, plen, -1);
2870     }
2871   
2872   return avr_asm_len ("ld %0,%1", op, plen, -1);
2873 }
2874
2875 static const char*
2876 out_movhi_r_mr (rtx insn, rtx op[], int *plen)
2877 {
2878   rtx dest = op[0];
2879   rtx src = op[1];
2880   rtx base = XEXP (src, 0);
2881   int reg_dest = true_regnum (dest);
2882   int reg_base = true_regnum (base);
2883   /* "volatile" forces reading low byte first, even if less efficient,
2884      for correct operation with 16-bit I/O registers.  */
2885   int mem_volatile_p = MEM_VOLATILE_P (src);
2886
2887   if (reg_base > 0)
2888     {
2889       if (reg_dest == reg_base)         /* R = (R) */
2890         return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
2891                             "ld %B0,%1"          CR_TAB
2892                             "mov %A0,__tmp_reg__", op, plen, -3);
2893
2894       if (reg_base != REG_X)
2895         return avr_asm_len ("ld %A0,%1" CR_TAB
2896                             "ldd %B0,%1+1", op, plen, -2);
2897       
2898       avr_asm_len ("ld %A0,X+" CR_TAB
2899                    "ld %B0,X", op, plen, -2);
2900           
2901       if (!reg_unused_after (insn, base))
2902         avr_asm_len ("sbiw r26,1", op, plen, 1);
2903
2904       return "";
2905     }
2906   else if (GET_CODE (base) == PLUS) /* (R + i) */
2907     {
2908       int disp = INTVAL (XEXP (base, 1));
2909       int reg_base = true_regnum (XEXP (base, 0));
2910       
2911       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
2912         {
2913           if (REGNO (XEXP (base, 0)) != REG_Y)
2914             fatal_insn ("incorrect insn:",insn);
2915           
2916           return disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))
2917             ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
2918                            "ldd %A0,Y+62"    CR_TAB
2919                            "ldd %B0,Y+63"    CR_TAB
2920                            "sbiw r28,%o1-62", op, plen, -4)
2921
2922             : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
2923                            "sbci r29,hi8(-%o1)" CR_TAB
2924                            "ld %A0,Y"           CR_TAB
2925                            "ldd %B0,Y+1"        CR_TAB
2926                            "subi r28,lo8(%o1)"  CR_TAB
2927                            "sbci r29,hi8(%o1)", op, plen, -6);
2928         }
2929
2930       /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
2931          it but I have this situation with extremal
2932          optimization options.  */
2933
2934       if (reg_base == REG_X)
2935         return reg_base == reg_dest
2936           ? avr_asm_len ("adiw r26,%o1"      CR_TAB
2937                          "ld __tmp_reg__,X+" CR_TAB
2938                          "ld %B0,X"          CR_TAB
2939                          "mov %A0,__tmp_reg__", op, plen, -4)
2940
2941           : avr_asm_len ("adiw r26,%o1" CR_TAB
2942                          "ld %A0,X+"    CR_TAB
2943                          "ld %B0,X"     CR_TAB
2944                          "sbiw r26,%o1+1", op, plen, -4);
2945
2946       return reg_base == reg_dest
2947         ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
2948                        "ldd %B0,%B1"         CR_TAB
2949                        "mov %A0,__tmp_reg__", op, plen, -3)
2950
2951         : avr_asm_len ("ldd %A0,%A1" CR_TAB
2952                        "ldd %B0,%B1", op, plen, -2);
2953     }
2954   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
2955     {
2956       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
2957         fatal_insn ("incorrect insn:", insn);
2958
2959       if (!mem_volatile_p)
2960         return avr_asm_len ("ld %B0,%1" CR_TAB
2961                             "ld %A0,%1", op, plen, -2);
2962       
2963       return REGNO (XEXP (base, 0)) == REG_X
2964         ? avr_asm_len ("sbiw r26,2"  CR_TAB
2965                        "ld %A0,X+"   CR_TAB
2966                        "ld %B0,X"    CR_TAB
2967                        "sbiw r26,1", op, plen, -4)
2968         
2969         : avr_asm_len ("sbiw %r1,2"  CR_TAB
2970                        "ld %A0,%p1"  CR_TAB
2971                        "ldd %B0,%p1+1", op, plen, -3);
2972     }
2973   else if (GET_CODE (base) == POST_INC) /* (R++) */
2974     {
2975       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
2976         fatal_insn ("incorrect insn:", insn);
2977
2978       return avr_asm_len ("ld %A0,%1"  CR_TAB
2979                           "ld %B0,%1", op, plen, -2);
2980     }
2981   else if (CONSTANT_ADDRESS_P (base))
2982     {
2983       return optimize > 0 && io_address_operand (base, HImode)
2984         ? avr_asm_len ("in %A0,%i1" CR_TAB
2985                        "in %B0,%i1+1", op, plen, -2)
2986
2987         : avr_asm_len ("lds %A0,%m1" CR_TAB
2988                        "lds %B0,%m1+1", op, plen, -4);
2989     }
2990   
2991   fatal_insn ("unknown move insn:",insn);
2992   return "";
2993 }
2994
2995 static const char*
2996 out_movsi_r_mr (rtx insn, rtx op[], int *l)
2997 {
2998   rtx dest = op[0];
2999   rtx src = op[1];
3000   rtx base = XEXP (src, 0);
3001   int reg_dest = true_regnum (dest);
3002   int reg_base = true_regnum (base);
3003   int tmp;
3004
3005   if (!l)
3006     l = &tmp;
3007   
3008   if (reg_base > 0)
3009     {
3010       if (reg_base == REG_X)        /* (R26) */
3011         {
3012           if (reg_dest == REG_X)
3013             /* "ld r26,-X" is undefined */
3014             return *l=7, ("adiw r26,3"        CR_TAB
3015                           "ld r29,X"          CR_TAB
3016                           "ld r28,-X"         CR_TAB
3017                           "ld __tmp_reg__,-X" CR_TAB
3018                           "sbiw r26,1"        CR_TAB
3019                           "ld r26,X"          CR_TAB
3020                           "mov r27,__tmp_reg__");
3021           else if (reg_dest == REG_X - 2)
3022             return *l=5, ("ld %A0,X+"          CR_TAB
3023                           "ld %B0,X+"          CR_TAB
3024                           "ld __tmp_reg__,X+"  CR_TAB
3025                           "ld %D0,X"           CR_TAB
3026                           "mov %C0,__tmp_reg__");
3027           else if (reg_unused_after (insn, base))
3028             return  *l=4, ("ld %A0,X+"  CR_TAB
3029                            "ld %B0,X+" CR_TAB
3030                            "ld %C0,X+" CR_TAB
3031                            "ld %D0,X");
3032           else
3033             return  *l=5, ("ld %A0,X+"  CR_TAB
3034                            "ld %B0,X+" CR_TAB
3035                            "ld %C0,X+" CR_TAB
3036                            "ld %D0,X"  CR_TAB
3037                            "sbiw r26,3");
3038         }
3039       else
3040         {
3041           if (reg_dest == reg_base)
3042             return *l=5, ("ldd %D0,%1+3" CR_TAB
3043                           "ldd %C0,%1+2" CR_TAB
3044                           "ldd __tmp_reg__,%1+1"  CR_TAB
3045                           "ld %A0,%1"  CR_TAB
3046                           "mov %B0,__tmp_reg__");
3047           else if (reg_base == reg_dest + 2)
3048             return *l=5, ("ld %A0,%1"             CR_TAB
3049                           "ldd %B0,%1+1"          CR_TAB
3050                           "ldd __tmp_reg__,%1+2"  CR_TAB
3051                           "ldd %D0,%1+3"          CR_TAB
3052                           "mov %C0,__tmp_reg__");
3053           else
3054             return *l=4, ("ld %A0,%1"    CR_TAB
3055                           "ldd %B0,%1+1" CR_TAB
3056                           "ldd %C0,%1+2" CR_TAB
3057                           "ldd %D0,%1+3");
3058         }
3059     }
3060   else if (GET_CODE (base) == PLUS) /* (R + i) */
3061     {
3062       int disp = INTVAL (XEXP (base, 1));
3063       
3064       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
3065         {
3066           if (REGNO (XEXP (base, 0)) != REG_Y)
3067             fatal_insn ("incorrect insn:",insn);
3068
3069           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
3070             return *l = 6, ("adiw r28,%o1-60" CR_TAB
3071                             "ldd %A0,Y+60"    CR_TAB
3072                             "ldd %B0,Y+61"    CR_TAB
3073                             "ldd %C0,Y+62"    CR_TAB
3074                             "ldd %D0,Y+63"    CR_TAB
3075                             "sbiw r28,%o1-60");
3076
3077           return *l = 8, ("subi r28,lo8(-%o1)" CR_TAB
3078                           "sbci r29,hi8(-%o1)" CR_TAB
3079                           "ld %A0,Y"           CR_TAB
3080                           "ldd %B0,Y+1"        CR_TAB
3081                           "ldd %C0,Y+2"        CR_TAB
3082                           "ldd %D0,Y+3"        CR_TAB
3083                           "subi r28,lo8(%o1)"  CR_TAB
3084                           "sbci r29,hi8(%o1)");
3085         }
3086
3087       reg_base = true_regnum (XEXP (base, 0));
3088       if (reg_base == REG_X)
3089         {
3090           /* R = (X + d) */
3091           if (reg_dest == REG_X)
3092             {
3093               *l = 7;
3094               /* "ld r26,-X" is undefined */
3095               return ("adiw r26,%o1+3"    CR_TAB
3096                       "ld r29,X"          CR_TAB
3097                       "ld r28,-X"         CR_TAB
3098                       "ld __tmp_reg__,-X" CR_TAB
3099                       "sbiw r26,1"        CR_TAB
3100                       "ld r26,X"          CR_TAB
3101                       "mov r27,__tmp_reg__");
3102             }
3103           *l = 6;
3104           if (reg_dest == REG_X - 2)
3105             return ("adiw r26,%o1"      CR_TAB
3106                     "ld r24,X+"         CR_TAB
3107                     "ld r25,X+"         CR_TAB
3108                     "ld __tmp_reg__,X+" CR_TAB
3109                     "ld r27,X"          CR_TAB
3110                     "mov r26,__tmp_reg__");
3111
3112           return ("adiw r26,%o1" CR_TAB
3113                   "ld %A0,X+"    CR_TAB
3114                   "ld %B0,X+"    CR_TAB
3115                   "ld %C0,X+"    CR_TAB
3116                   "ld %D0,X"     CR_TAB
3117                   "sbiw r26,%o1+3");
3118         }
3119       if (reg_dest == reg_base)
3120         return *l=5, ("ldd %D0,%D1"          CR_TAB
3121                       "ldd %C0,%C1"          CR_TAB
3122                       "ldd __tmp_reg__,%B1"  CR_TAB
3123                       "ldd %A0,%A1"          CR_TAB
3124                       "mov %B0,__tmp_reg__");
3125       else if (reg_dest == reg_base - 2)
3126         return *l=5, ("ldd %A0,%A1"          CR_TAB
3127                       "ldd %B0,%B1"          CR_TAB
3128                       "ldd __tmp_reg__,%C1"  CR_TAB
3129                       "ldd %D0,%D1"          CR_TAB
3130                       "mov %C0,__tmp_reg__");
3131       return *l=4, ("ldd %A0,%A1" CR_TAB
3132                     "ldd %B0,%B1" CR_TAB
3133                     "ldd %C0,%C1" CR_TAB
3134                     "ldd %D0,%D1");
3135     }
3136   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
3137     return *l=4, ("ld %D0,%1" CR_TAB
3138                   "ld %C0,%1" CR_TAB
3139                   "ld %B0,%1" CR_TAB
3140                   "ld %A0,%1");
3141   else if (GET_CODE (base) == POST_INC) /* (R++) */
3142     return *l=4, ("ld %A0,%1" CR_TAB
3143                   "ld %B0,%1" CR_TAB
3144                   "ld %C0,%1" CR_TAB
3145                   "ld %D0,%1");
3146   else if (CONSTANT_ADDRESS_P (base))
3147     return *l=8, ("lds %A0,%m1"   CR_TAB
3148                   "lds %B0,%m1+1" CR_TAB
3149                   "lds %C0,%m1+2" CR_TAB
3150                   "lds %D0,%m1+3");
3151     
3152   fatal_insn ("unknown move insn:",insn);
3153   return "";
3154 }
3155
3156 static const char*
3157 out_movsi_mr_r (rtx insn, rtx op[], int *l)
3158 {
3159   rtx dest = op[0];
3160   rtx src = op[1];
3161   rtx base = XEXP (dest, 0);
3162   int reg_base = true_regnum (base);
3163   int reg_src = true_regnum (src);
3164   int tmp;
3165   
3166   if (!l)
3167     l = &tmp;
3168   
3169   if (CONSTANT_ADDRESS_P (base))
3170     return *l=8,("sts %m0,%A1" CR_TAB
3171                  "sts %m0+1,%B1" CR_TAB
3172                  "sts %m0+2,%C1" CR_TAB
3173                  "sts %m0+3,%D1");
3174   if (reg_base > 0)                 /* (r) */
3175     {
3176       if (reg_base == REG_X)                /* (R26) */
3177         {
3178           if (reg_src == REG_X)
3179             {
3180               /* "st X+,r26" is undefined */
3181               if (reg_unused_after (insn, base))
3182                 return *l=6, ("mov __tmp_reg__,r27" CR_TAB
3183                               "st X,r26"            CR_TAB
3184                               "adiw r26,1"          CR_TAB
3185                               "st X+,__tmp_reg__"   CR_TAB
3186                               "st X+,r28"           CR_TAB
3187                               "st X,r29");
3188               else
3189                 return *l=7, ("mov __tmp_reg__,r27" CR_TAB
3190                               "st X,r26"            CR_TAB
3191                               "adiw r26,1"          CR_TAB
3192                               "st X+,__tmp_reg__"   CR_TAB
3193                               "st X+,r28"           CR_TAB
3194                               "st X,r29"            CR_TAB
3195                               "sbiw r26,3");
3196             }
3197           else if (reg_base == reg_src + 2)
3198             {
3199               if (reg_unused_after (insn, base))
3200                 return *l=7, ("mov __zero_reg__,%C1" CR_TAB
3201                               "mov __tmp_reg__,%D1"  CR_TAB
3202                               "st %0+,%A1"           CR_TAB
3203                               "st %0+,%B1"           CR_TAB
3204                               "st %0+,__zero_reg__"  CR_TAB
3205                               "st %0,__tmp_reg__"    CR_TAB
3206                               "clr __zero_reg__");
3207               else
3208                 return *l=8, ("mov __zero_reg__,%C1" CR_TAB
3209                               "mov __tmp_reg__,%D1"  CR_TAB
3210                               "st %0+,%A1"           CR_TAB
3211                               "st %0+,%B1"           CR_TAB
3212                               "st %0+,__zero_reg__"  CR_TAB
3213                               "st %0,__tmp_reg__"    CR_TAB
3214                               "clr __zero_reg__"     CR_TAB
3215                               "sbiw r26,3");
3216             }
3217           return *l=5, ("st %0+,%A1" CR_TAB
3218                         "st %0+,%B1" CR_TAB
3219                         "st %0+,%C1" CR_TAB
3220                         "st %0,%D1"  CR_TAB
3221                         "sbiw r26,3");
3222         }
3223       else
3224         return *l=4, ("st %0,%A1"    CR_TAB
3225                       "std %0+1,%B1" CR_TAB
3226                       "std %0+2,%C1" CR_TAB
3227                       "std %0+3,%D1");
3228     }
3229   else if (GET_CODE (base) == PLUS) /* (R + i) */
3230     {
3231       int disp = INTVAL (XEXP (base, 1));
3232       reg_base = REGNO (XEXP (base, 0));
3233       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
3234         {
3235           if (reg_base != REG_Y)
3236             fatal_insn ("incorrect insn:",insn);
3237
3238           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
3239             return *l = 6, ("adiw r28,%o0-60" CR_TAB
3240                             "std Y+60,%A1"    CR_TAB
3241                             "std Y+61,%B1"    CR_TAB
3242                             "std Y+62,%C1"    CR_TAB
3243                             "std Y+63,%D1"    CR_TAB
3244                             "sbiw r28,%o0-60");
3245
3246           return *l = 8, ("subi r28,lo8(-%o0)" CR_TAB
3247                           "sbci r29,hi8(-%o0)" CR_TAB
3248                           "st Y,%A1"           CR_TAB
3249                           "std Y+1,%B1"        CR_TAB
3250                           "std Y+2,%C1"        CR_TAB
3251                           "std Y+3,%D1"        CR_TAB
3252                           "subi r28,lo8(%o0)"  CR_TAB
3253                           "sbci r29,hi8(%o0)");
3254         }
3255       if (reg_base == REG_X)
3256         {
3257           /* (X + d) = R */
3258           if (reg_src == REG_X)
3259             {
3260               *l = 9;
3261               return ("mov __tmp_reg__,r26"  CR_TAB
3262                       "mov __zero_reg__,r27" CR_TAB
3263                       "adiw r26,%o0"         CR_TAB
3264                       "st X+,__tmp_reg__"    CR_TAB
3265                       "st X+,__zero_reg__"   CR_TAB
3266                       "st X+,r28"            CR_TAB
3267                       "st X,r29"             CR_TAB
3268                       "clr __zero_reg__"     CR_TAB
3269                       "sbiw r26,%o0+3");
3270             }
3271           else if (reg_src == REG_X - 2)
3272             {
3273               *l = 9;
3274               return ("mov __tmp_reg__,r26"  CR_TAB
3275                       "mov __zero_reg__,r27" CR_TAB
3276                       "adiw r26,%o0"         CR_TAB
3277                       "st X+,r24"            CR_TAB
3278                       "st X+,r25"            CR_TAB
3279                       "st X+,__tmp_reg__"    CR_TAB
3280                       "st X,__zero_reg__"    CR_TAB
3281                       "clr __zero_reg__"     CR_TAB
3282                       "sbiw r26,%o0+3");
3283             }
3284           *l = 6;
3285           return ("adiw r26,%o0" CR_TAB
3286                   "st X+,%A1"    CR_TAB
3287                   "st X+,%B1"    CR_TAB
3288                   "st X+,%C1"    CR_TAB
3289                   "st X,%D1"     CR_TAB
3290                   "sbiw r26,%o0+3");
3291         }
3292       return *l=4, ("std %A0,%A1" CR_TAB
3293                     "std %B0,%B1" CR_TAB
3294                     "std %C0,%C1" CR_TAB
3295                     "std %D0,%D1");
3296     }
3297   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
3298     return *l=4, ("st %0,%D1" CR_TAB
3299                   "st %0,%C1" CR_TAB
3300                   "st %0,%B1" CR_TAB
3301                   "st %0,%A1");
3302   else if (GET_CODE (base) == POST_INC) /* (R++) */
3303     return *l=4, ("st %0,%A1" CR_TAB
3304                   "st %0,%B1" CR_TAB
3305                   "st %0,%C1" CR_TAB
3306                   "st %0,%D1");
3307   fatal_insn ("unknown move insn:",insn);
3308   return "";
3309 }
3310
3311 const char *
3312 output_movsisf (rtx insn, rtx operands[], int *l)
3313 {
3314   int dummy;
3315   rtx dest = operands[0];
3316   rtx src = operands[1];
3317   int *real_l = l;
3318   
3319   if (avr_mem_flash_p (src)
3320       || avr_mem_flash_p (dest))
3321     {
3322       return avr_out_lpm (insn, operands, real_l);
3323     }
3324
3325   if (!l)
3326     l = &dummy;
3327   
3328   if (register_operand (dest, VOIDmode))
3329     {
3330       if (register_operand (src, VOIDmode)) /* mov r,r */
3331         {
3332           if (true_regnum (dest) > true_regnum (src))
3333             {
3334               if (AVR_HAVE_MOVW)
3335                 {
3336                   *l = 2;
3337                   return ("movw %C0,%C1" CR_TAB
3338                           "movw %A0,%A1");
3339                 }
3340               *l = 4;
3341               return ("mov %D0,%D1" CR_TAB
3342                       "mov %C0,%C1" CR_TAB
3343                       "mov %B0,%B1" CR_TAB
3344                       "mov %A0,%A1");
3345             }
3346           else
3347             {
3348               if (AVR_HAVE_MOVW)
3349                 {
3350                   *l = 2;
3351                   return ("movw %A0,%A1" CR_TAB
3352                           "movw %C0,%C1");
3353                 }
3354               *l = 4;
3355               return ("mov %A0,%A1" CR_TAB
3356                       "mov %B0,%B1" CR_TAB
3357                       "mov %C0,%C1" CR_TAB
3358                       "mov %D0,%D1");
3359             }
3360         }
3361       else if (CONSTANT_P (src))
3362         {
3363           return output_reload_insisf (operands, NULL_RTX, real_l);
3364         }
3365       else if (GET_CODE (src) == MEM)
3366         return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
3367     }
3368   else if (GET_CODE (dest) == MEM)
3369     {
3370       const char *templ;
3371
3372       if (src == CONST0_RTX (GET_MODE (dest)))
3373           operands[1] = zero_reg_rtx;
3374
3375       templ = out_movsi_mr_r (insn, operands, real_l);
3376
3377       if (!real_l)
3378         output_asm_insn (templ, operands);
3379
3380       operands[1] = src;
3381       return "";
3382     }
3383   fatal_insn ("invalid insn:", insn);
3384   return "";
3385 }
3386
3387
3388 /* Handle loads of 24-bit types from memory to register.  */
3389
3390 static const char*
3391 avr_out_load_psi (rtx insn, rtx *op, int *plen)
3392 {
3393   rtx dest = op[0];
3394   rtx src = op[1];
3395   rtx base = XEXP (src, 0);
3396   int reg_dest = true_regnum (dest);
3397   int reg_base = true_regnum (base);
3398   
3399   if (reg_base > 0)
3400     {
3401       if (reg_base == REG_X)        /* (R26) */
3402         {
3403           if (reg_dest == REG_X)
3404             /* "ld r26,-X" is undefined */
3405             return avr_asm_len ("adiw r26,2"        CR_TAB
3406                                 "ld r28,X"          CR_TAB
3407                                 "ld __tmp_reg__,-X" CR_TAB
3408                                 "sbiw r26,1"        CR_TAB
3409                                 "ld r26,X"          CR_TAB
3410                                 "mov r27,__tmp_reg__", op, plen, -6);
3411           else
3412             {
3413               avr_asm_len ("ld %A0,X+" CR_TAB
3414                            "ld %B0,X+" CR_TAB
3415                            "ld %C0,X", op, plen, -3);
3416
3417               if (reg_dest != REG_X - 2
3418                   && !reg_unused_after (insn, base))
3419                 {
3420                   avr_asm_len ("sbiw r26,2", op, plen, 1);
3421                 }
3422
3423               return "";
3424             }
3425         }
3426       else /* reg_base != REG_X */
3427         {
3428           if (reg_dest == reg_base)
3429             return avr_asm_len ("ldd %C0,%1+2"          CR_TAB
3430                                 "ldd __tmp_reg__,%1+1"  CR_TAB
3431                                 "ld  %A0,%1"            CR_TAB
3432                                 "mov %B0,__tmp_reg__", op, plen, -4);
3433           else
3434             return avr_asm_len ("ld  %A0,%1"    CR_TAB
3435                                 "ldd %B0,%1+1"  CR_TAB
3436                                 "ldd %C0,%1+2", op, plen, -3);
3437         }
3438     }
3439   else if (GET_CODE (base) == PLUS) /* (R + i) */
3440     {
3441       int disp = INTVAL (XEXP (base, 1));
3442       
3443       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
3444         {
3445           if (REGNO (XEXP (base, 0)) != REG_Y)
3446             fatal_insn ("incorrect insn:",insn);
3447
3448           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
3449             return avr_asm_len ("adiw r28,%o1-61" CR_TAB
3450                                 "ldd %A0,Y+61"    CR_TAB
3451                                 "ldd %B0,Y+62"    CR_TAB
3452                                 "ldd %C0,Y+63"    CR_TAB
3453                                 "sbiw r28,%o1-61", op, plen, -5);
3454
3455           return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
3456                               "sbci r29,hi8(-%o1)" CR_TAB
3457                               "ld  %A0,Y"           CR_TAB
3458                               "ldd %B0,Y+1"        CR_TAB
3459                               "ldd %C0,Y+2"        CR_TAB
3460                               "subi r28,lo8(%o1)"  CR_TAB
3461                               "sbci r29,hi8(%o1)", op, plen, -7);
3462         }
3463
3464       reg_base = true_regnum (XEXP (base, 0));
3465       if (reg_base == REG_X)
3466         {
3467           /* R = (X + d) */
3468           if (reg_dest == REG_X)
3469             {
3470               /* "ld r26,-X" is undefined */
3471               return avr_asm_len ("adiw r26,%o1+2"     CR_TAB
3472                                   "ld  r28,X"          CR_TAB
3473                                   "ld  __tmp_reg__,-X" CR_TAB
3474                                   "sbiw r26,1"         CR_TAB
3475                                   "ld  r26,X"          CR_TAB
3476                                   "mov r27,__tmp_reg__", op, plen, -6);
3477             }
3478           
3479             avr_asm_len ("adiw r26,%o1"      CR_TAB
3480                          "ld r24,X+"         CR_TAB
3481                          "ld r25,X+"         CR_TAB
3482                          "ld r26,X", op, plen, -4);
3483
3484             if (reg_dest != REG_X - 2)
3485               avr_asm_len ("sbiw r26,%o1+2", op, plen, 1);
3486
3487             return "";
3488         }
3489       
3490       if (reg_dest == reg_base)
3491         return avr_asm_len ("ldd %C0,%C1" CR_TAB
3492                             "ldd __tmp_reg__,%B1"  CR_TAB
3493                             "ldd %A0,%A1" CR_TAB
3494                             "mov %B0,__tmp_reg__", op, plen, -4);
3495
3496         return avr_asm_len ("ldd %A0,%A1" CR_TAB
3497                             "ldd %B0,%B1" CR_TAB
3498                             "ldd %C0,%C1", op, plen, -3);
3499     }
3500   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
3501     return avr_asm_len ("ld %C0,%1" CR_TAB
3502                         "ld %B0,%1" CR_TAB
3503                         "ld %A0,%1", op, plen, -3);
3504   else if (GET_CODE (base) == POST_INC) /* (R++) */
3505     return avr_asm_len ("ld %A0,%1" CR_TAB
3506                         "ld %B0,%1" CR_TAB
3507                         "ld %C0,%1", op, plen, -3);
3508
3509   else if (CONSTANT_ADDRESS_P (base))
3510     return avr_asm_len ("lds %A0,%m1" CR_TAB
3511                         "lds %B0,%m1+1" CR_TAB
3512                         "lds %C0,%m1+2", op, plen , -6);
3513   
3514   fatal_insn ("unknown move insn:",insn);
3515   return "";
3516 }
3517
3518 /* Handle store of 24-bit type from register or zero to memory.  */
3519
3520 static const char*
3521 avr_out_store_psi (rtx insn, rtx *op, int *plen)
3522 {
3523   rtx dest = op[0];
3524   rtx src = op[1];
3525   rtx base = XEXP (dest, 0);
3526   int reg_base = true_regnum (base);
3527   
3528   if (CONSTANT_ADDRESS_P (base))
3529     return avr_asm_len ("sts %m0,%A1"   CR_TAB
3530                         "sts %m0+1,%B1" CR_TAB
3531                         "sts %m0+2,%C1", op, plen, -6);
3532   
3533   if (reg_base > 0)                 /* (r) */
3534     {
3535       if (reg_base == REG_X)        /* (R26) */
3536         {
3537           gcc_assert (!reg_overlap_mentioned_p (base, src));
3538           
3539           avr_asm_len ("st %0+,%A1"  CR_TAB
3540                        "st %0+,%B1" CR_TAB
3541                        "st %0,%C1", op, plen, -3);
3542
3543           if (!reg_unused_after (insn, base))
3544             avr_asm_len ("sbiw r26,2", op, plen, 1);
3545
3546           return "";
3547         }
3548       else
3549         return avr_asm_len ("st %0,%A1"    CR_TAB
3550                             "std %0+1,%B1" CR_TAB
3551                             "std %0+2,%C1", op, plen, -3);
3552     }
3553   else if (GET_CODE (base) == PLUS) /* (R + i) */
3554     {
3555       int disp = INTVAL (XEXP (base, 1));
3556       reg_base = REGNO (XEXP (base, 0));
3557
3558       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
3559         {
3560           if (reg_base != REG_Y)
3561             fatal_insn ("incorrect insn:",insn);
3562
3563           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
3564             return avr_asm_len ("adiw r28,%o0-61" CR_TAB
3565                                 "std Y+61,%A1"    CR_TAB
3566                                 "std Y+62,%B1"    CR_TAB
3567                                 "std Y+63,%C1"    CR_TAB
3568                                 "sbiw r28,%o0-60", op, plen, -5);
3569
3570           return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
3571                               "sbci r29,hi8(-%o0)" CR_TAB
3572                               "st Y,%A1"           CR_TAB
3573                               "std Y+1,%B1"        CR_TAB
3574                               "std Y+2,%C1"        CR_TAB
3575                               "subi r28,lo8(%o0)"  CR_TAB
3576                               "sbci r29,hi8(%o0)", op, plen, -7);
3577         }
3578       if (reg_base == REG_X)
3579         {
3580           /* (X + d) = R */
3581           gcc_assert (!reg_overlap_mentioned_p (XEXP (base, 0), src));
3582           
3583           avr_asm_len ("adiw r26,%o0" CR_TAB
3584                        "st X+,%A1"    CR_TAB
3585                        "st X+,%B1"    CR_TAB
3586                        "st X,%C1", op, plen, -4);
3587
3588           if (!reg_unused_after (insn, XEXP (base, 0)))
3589             avr_asm_len ("sbiw r26,%o0+2", op, plen, 1);
3590
3591           return "";
3592         }
3593       
3594       return avr_asm_len ("std %A0,%A1" CR_TAB
3595                           "std %B0,%B1" CR_TAB
3596                           "std %C0,%C1", op, plen, -3);
3597     }
3598   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
3599     return avr_asm_len ("st %0,%C1" CR_TAB
3600                         "st %0,%B1" CR_TAB
3601                         "st %0,%A1", op, plen, -3);
3602   else if (GET_CODE (base) == POST_INC) /* (R++) */
3603     return avr_asm_len ("st %0,%A1" CR_TAB
3604                         "st %0,%B1" CR_TAB
3605                         "st %0,%C1", op, plen, -3);
3606
3607   fatal_insn ("unknown move insn:",insn);
3608   return "";
3609 }
3610
3611
3612 /* Move around 24-bit stuff.  */
3613
3614 const char *
3615 avr_out_movpsi (rtx insn, rtx *op, int *plen)
3616 {
3617   rtx dest = op[0];
3618   rtx src = op[1];
3619   
3620   if (avr_mem_flash_p (src)
3621       || avr_mem_flash_p (dest))
3622     {
3623       return avr_out_lpm (insn, op, plen);
3624     }
3625   
3626   if (register_operand (dest, VOIDmode))
3627     {
3628       if (register_operand (src, VOIDmode)) /* mov r,r */
3629         {
3630           if (true_regnum (dest) > true_regnum (src))
3631             {
3632               avr_asm_len ("mov %C0,%C1", op, plen, -1);
3633
3634               if (AVR_HAVE_MOVW)
3635                 return avr_asm_len ("movw %A0,%A1", op, plen, 1);
3636               else
3637                 return avr_asm_len ("mov %B0,%B1"  CR_TAB
3638                                     "mov %A0,%A1", op, plen, 2);
3639             }
3640           else
3641             {
3642               if (AVR_HAVE_MOVW)
3643                 avr_asm_len ("movw %A0,%A1", op, plen, -1);
3644               else
3645                 avr_asm_len ("mov %A0,%A1"  CR_TAB
3646                              "mov %B0,%B1", op, plen, -2);
3647               
3648               return avr_asm_len ("mov %C0,%C1", op, plen, 1);
3649             }
3650         }
3651       else if (CONSTANT_P (src))
3652         {
3653           return avr_out_reload_inpsi (op, NULL_RTX, plen);
3654         }
3655       else if (MEM_P (src))
3656         return avr_out_load_psi (insn, op, plen); /* mov r,m */
3657     }
3658   else if (MEM_P (dest))
3659     {
3660       rtx xop[2];
3661
3662       xop[0] = dest;
3663       xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3664       
3665       return avr_out_store_psi (insn, xop, plen);
3666     }
3667     
3668   fatal_insn ("invalid insn:", insn);
3669   return "";
3670 }
3671
3672
3673 static const char*
3674 out_movqi_mr_r (rtx insn, rtx op[], int *plen)
3675 {
3676   rtx dest = op[0];
3677   rtx src = op[1];
3678   rtx x = XEXP (dest, 0);
3679   
3680   if (CONSTANT_ADDRESS_P (x))
3681     {
3682       return optimize > 0 && io_address_operand (x, QImode)
3683         ? avr_asm_len ("out %i0,%1", op, plen, -1)
3684         : avr_asm_len ("sts %m0,%1", op, plen, -2);
3685     }
3686   else if (GET_CODE (x) == PLUS
3687            && REG_P (XEXP (x, 0))
3688            && CONST_INT_P (XEXP (x, 1)))
3689     {
3690       /* memory access by reg+disp */
3691
3692       int disp = INTVAL (XEXP (x, 1));
3693
3694       if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63)
3695         {
3696           if (REGNO (XEXP (x, 0)) != REG_Y)
3697             fatal_insn ("incorrect insn:",insn);
3698
3699           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
3700             return avr_asm_len ("adiw r28,%o0-63" CR_TAB
3701                                 "std Y+63,%1"     CR_TAB
3702                                 "sbiw r28,%o0-63", op, plen, -3);
3703
3704           return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
3705                               "sbci r29,hi8(-%o0)" CR_TAB
3706                               "st Y,%1"            CR_TAB
3707                               "subi r28,lo8(%o0)"  CR_TAB
3708                               "sbci r29,hi8(%o0)", op, plen, -5);
3709         }
3710       else if (REGNO (XEXP (x,0)) == REG_X)
3711         {
3712           if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
3713             {
3714               avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
3715                            "adiw r26,%o0"       CR_TAB
3716                            "st X,__tmp_reg__", op, plen, -3);
3717             }
3718           else
3719             {
3720               avr_asm_len ("adiw r26,%o0" CR_TAB
3721                            "st X,%1", op, plen, -2);
3722             }
3723           
3724           if (!reg_unused_after (insn, XEXP (x,0)))
3725             avr_asm_len ("sbiw r26,%o0", op, plen, 1);
3726
3727           return "";
3728         }
3729       
3730       return avr_asm_len ("std %0,%1", op, plen, -1);
3731     }
3732   
3733   return avr_asm_len ("st %0,%1", op, plen, -1);
3734 }
3735
3736
3737 /* Helper for the next function for XMEGA.  It does the same
3738    but with low byte first.  */
3739
3740 static const char*
3741 avr_out_movhi_mr_r_xmega (rtx insn, rtx op[], int *plen)
3742 {
3743   rtx dest = op[0];
3744   rtx src = op[1];
3745   rtx base = XEXP (dest, 0);
3746   int reg_base = true_regnum (base);
3747   int reg_src = true_regnum (src);
3748
3749   /* "volatile" forces writing low byte first, even if less efficient,
3750      for correct operation with 16-bit I/O registers like SP.  */
3751   int mem_volatile_p = MEM_VOLATILE_P (dest);
3752
3753   if (CONSTANT_ADDRESS_P (base))
3754     return optimize > 0 && io_address_operand (base, HImode)
3755       ? avr_asm_len ("out %i0,%A1" CR_TAB
3756                      "out %i0+1,%B1", op, plen, -2)
3757
3758       : avr_asm_len ("sts %m0,%A1" CR_TAB
3759                      "sts %m0+1,%B1", op, plen, -4);
3760   
3761   if (reg_base > 0)
3762     {
3763       if (reg_base != REG_X)
3764         return avr_asm_len ("st %0,%A1" CR_TAB
3765                             "std %0+1,%B1", op, plen, -2);
3766       
3767       if (reg_src == REG_X)
3768         /* "st X+,r26" and "st -X,r26" are undefined.  */
3769         avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
3770                      "st X,r26"            CR_TAB
3771                      "adiw r26,1"          CR_TAB
3772                      "st X,__tmp_reg__", op, plen, -4);
3773       else
3774         avr_asm_len ("st X+,%A1" CR_TAB
3775                      "st X,%B1", op, plen, -2);
3776
3777       return reg_unused_after (insn, base)
3778         ? ""
3779         : avr_asm_len ("sbiw r26,1", op, plen, 1);
3780     }
3781   else if (GET_CODE (base) == PLUS)
3782     {
3783       int disp = INTVAL (XEXP (base, 1));
3784       reg_base = REGNO (XEXP (base, 0));
3785       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
3786         {
3787           if (reg_base != REG_Y)
3788             fatal_insn ("incorrect insn:",insn);
3789           
3790           return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
3791             ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
3792                            "std Y+62,%A1"    CR_TAB
3793                            "std Y+63,%B1"    CR_TAB
3794                            "sbiw r28,%o0-62", op, plen, -4)
3795
3796             : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
3797                            "sbci r29,hi8(-%o0)" CR_TAB
3798                            "st Y,%A1"           CR_TAB
3799                            "std Y+1,%B1"        CR_TAB
3800                            "subi r28,lo8(%o0)"  CR_TAB
3801                            "sbci r29,hi8(%o0)", op, plen, -6);
3802         }
3803       
3804       if (reg_base != REG_X)
3805         return avr_asm_len ("std %A0,%A1" CR_TAB
3806                             "std %B0,%B1", op, plen, -2);
3807       /* (X + d) = R */
3808       return reg_src == REG_X
3809         ? avr_asm_len ("mov __tmp_reg__,r26"  CR_TAB
3810                        "mov __zero_reg__,r27" CR_TAB
3811                        "adiw r26,%o0"         CR_TAB
3812                        "st X+,__tmp_reg__"    CR_TAB
3813                        "st X,__zero_reg__"    CR_TAB
3814                        "clr __zero_reg__"     CR_TAB
3815                        "sbiw r26,%o0+1", op, plen, -7)
3816
3817         : avr_asm_len ("adiw r26,%o0" CR_TAB
3818                        "st X+,%A1"    CR_TAB
3819                        "st X,%B1"     CR_TAB
3820                        "sbiw r26,%o0+1", op, plen, -4);
3821     }
3822   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
3823     {
3824       if (!mem_volatile_p)
3825         return avr_asm_len ("st %0,%B1" CR_TAB
3826                             "st %0,%A1", op, plen, -2);
3827
3828       return REGNO (XEXP (base, 0)) == REG_X
3829         ? avr_asm_len ("sbiw r26,2"  CR_TAB
3830                        "st X+,%A1"   CR_TAB
3831                        "st X,%B1"    CR_TAB
3832                        "sbiw r26,1", op, plen, -4)
3833
3834         : avr_asm_len ("sbiw %r0,2"  CR_TAB
3835                        "st %p0,%A1"  CR_TAB
3836                        "std %p0+1,%B1", op, plen, -3);
3837     }
3838   else if (GET_CODE (base) == POST_INC) /* (R++) */
3839     {
3840       return avr_asm_len ("st %0,%A1"  CR_TAB
3841                           "st %0,%B1", op, plen, -2);
3842       
3843     }
3844   fatal_insn ("unknown move insn:",insn);
3845   return "";
3846 }
3847
3848
3849 static const char*
3850 out_movhi_mr_r (rtx insn, rtx op[], int *plen)
3851 {
3852   rtx dest = op[0];
3853   rtx src = op[1];
3854   rtx base = XEXP (dest, 0);
3855   int reg_base = true_regnum (base);
3856   int reg_src = true_regnum (src);
3857   int mem_volatile_p;
3858
3859   /* "volatile" forces writing high-byte first (no-xmega) resp.
3860      low-byte first (xmega) even if less efficient, for correct
3861      operation with 16-bit I/O registers like.  */
3862
3863   if (AVR_XMEGA)
3864     return avr_out_movhi_mr_r_xmega (insn, op, plen);
3865
3866   mem_volatile_p = MEM_VOLATILE_P (dest);
3867
3868   if (CONSTANT_ADDRESS_P (base))
3869     return optimize > 0 && io_address_operand (base, HImode)
3870       ? avr_asm_len ("out %i0+1,%B1" CR_TAB
3871                      "out %i0,%A1", op, plen, -2)
3872
3873       : avr_asm_len ("sts %m0+1,%B1" CR_TAB
3874                      "sts %m0,%A1", op, plen, -4);
3875   
3876   if (reg_base > 0)
3877     {
3878       if (reg_base != REG_X)
3879         return avr_asm_len ("std %0+1,%B1" CR_TAB
3880                             "st %0,%A1", op, plen, -2);
3881       
3882       if (reg_src == REG_X)
3883         /* "st X+,r26" and "st -X,r26" are undefined.  */
3884         return !mem_volatile_p && reg_unused_after (insn, src)
3885           ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
3886                          "st X,r26"            CR_TAB
3887                          "adiw r26,1"          CR_TAB
3888                          "st X,__tmp_reg__", op, plen, -4)
3889
3890           : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
3891                          "adiw r26,1"          CR_TAB
3892                          "st X,__tmp_reg__"    CR_TAB
3893                          "sbiw r26,1"          CR_TAB
3894                          "st X,r26", op, plen, -5);
3895       
3896       return !mem_volatile_p && reg_unused_after (insn, base)
3897         ? avr_asm_len ("st X+,%A1" CR_TAB
3898                        "st X,%B1", op, plen, -2)
3899         : avr_asm_len ("adiw r26,1" CR_TAB
3900                        "st X,%B1"   CR_TAB
3901                        "st -X,%A1", op, plen, -3);
3902     }
3903   else if (GET_CODE (base) == PLUS)
3904     {
3905       int disp = INTVAL (XEXP (base, 1));
3906       reg_base = REGNO (XEXP (base, 0));
3907       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
3908         {
3909           if (reg_base != REG_Y)
3910             fatal_insn ("incorrect insn:",insn);
3911           
3912           return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
3913             ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
3914                            "std Y+63,%B1"    CR_TAB
3915                            "std Y+62,%A1"    CR_TAB
3916                            "sbiw r28,%o0-62", op, plen, -4)
3917
3918             : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
3919                            "sbci r29,hi8(-%o0)" CR_TAB
3920                            "std Y+1,%B1"        CR_TAB
3921                            "st Y,%A1"           CR_TAB
3922                            "subi r28,lo8(%o0)"  CR_TAB
3923                            "sbci r29,hi8(%o0)", op, plen, -6);
3924         }
3925       
3926       if (reg_base != REG_X)
3927         return avr_asm_len ("std %B0,%B1" CR_TAB
3928                             "std %A0,%A1", op, plen, -2);
3929       /* (X + d) = R */
3930       return reg_src == REG_X
3931         ? avr_asm_len ("mov __tmp_reg__,r26"  CR_TAB
3932                        "mov __zero_reg__,r27" CR_TAB
3933                        "adiw r26,%o0+1"       CR_TAB
3934                        "st X,__zero_reg__"    CR_TAB
3935                        "st -X,__tmp_reg__"    CR_TAB
3936                        "clr __zero_reg__"     CR_TAB
3937                        "sbiw r26,%o0", op, plen, -7)
3938
3939         : avr_asm_len ("adiw r26,%o0+1" CR_TAB
3940                        "st X,%B1"       CR_TAB
3941                        "st -X,%A1"      CR_TAB
3942                        "sbiw r26,%o0", op, plen, -4);
3943     }
3944   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
3945     {
3946       return avr_asm_len ("st %0,%B1" CR_TAB
3947                           "st %0,%A1", op, plen, -2);
3948     }
3949   else if (GET_CODE (base) == POST_INC) /* (R++) */
3950     {
3951       if (!mem_volatile_p)
3952         return avr_asm_len ("st %0,%A1"  CR_TAB
3953                             "st %0,%B1", op, plen, -2);
3954       
3955       return REGNO (XEXP (base, 0)) == REG_X
3956         ? avr_asm_len ("adiw r26,1"  CR_TAB
3957                        "st X,%B1"    CR_TAB