OSDN Git Service

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