OSDN Git Service

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