OSDN Git Service

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