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)
6 This file is part of GCC.
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)
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.
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/>. */
24 #include "coretypes.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"
38 #include "c-family/c-common.h"
39 #include "diagnostic-core.h"
45 #include "langhooks.h"
48 #include "target-def.h"
52 /* Maximal allowed offset for an address in the LD command */
53 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
55 /* Return true if STR starts with PREFIX and false, otherwise. */
56 #define STR_PREFIX_P(STR,PREFIX) (0 == strncmp (STR, PREFIX, strlen (PREFIX)))
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)
65 /* Known address spaces. The order must be the same as in the respective
66 enum from avr.h (or designated initialized must be used). */
67 const avr_addrspace_t avr_addrspace[] =
69 { ADDR_SPACE_RAM, 0, 2, "" , 0 },
70 { ADDR_SPACE_PGM, 1, 2, "__pgm", 0 },
71 { ADDR_SPACE_PGM1, 1, 2, "__pgm1", 1 },
72 { ADDR_SPACE_PGM2, 1, 2, "__pgm2", 2 },
73 { ADDR_SPACE_PGM3, 1, 2, "__pgm3", 3 },
74 { ADDR_SPACE_PGM4, 1, 2, "__pgm4", 4 },
75 { ADDR_SPACE_PGM5, 1, 2, "__pgm5", 5 },
76 { ADDR_SPACE_PGMX, 1, 3, "__pgmx", 0 },
80 /* Map 64-k Flash segment to section prefix. */
81 static const char* const progmem_section_prefix[6] =
92 /* Prototypes for local helper functions. */
94 static const char* out_movqi_r_mr (rtx, rtx[], int*);
95 static const char* out_movhi_r_mr (rtx, rtx[], int*);
96 static const char* out_movsi_r_mr (rtx, rtx[], int*);
97 static const char* out_movqi_mr_r (rtx, rtx[], int*);
98 static const char* out_movhi_mr_r (rtx, rtx[], int*);
99 static const char* out_movsi_mr_r (rtx, rtx[], int*);
101 static int avr_naked_function_p (tree);
102 static int interrupt_function_p (tree);
103 static int signal_function_p (tree);
104 static int avr_OS_task_function_p (tree);
105 static int avr_OS_main_function_p (tree);
106 static int avr_regs_to_save (HARD_REG_SET *);
107 static int get_sequence_length (rtx insns);
108 static int sequent_regs_live (void);
109 static const char *ptrreg_to_str (int);
110 static const char *cond_string (enum rtx_code);
111 static int avr_num_arg_regs (enum machine_mode, const_tree);
112 static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code,
114 static void output_reload_in_const (rtx*, rtx, int*, bool);
115 static struct machine_function * avr_init_machine_status (void);
118 /* Prototypes for hook implementors if needed before their implementation. */
120 static bool avr_rtx_costs (rtx, int, int, int, int *, bool);
123 /* Allocate registers from r25 to r8 for parameters for function calls. */
124 #define FIRST_CUM_REG 26
126 /* Implicit target register of LPM instruction (R0) */
127 static GTY(()) rtx lpm_reg_rtx;
129 /* (Implicit) address register of LPM instruction (R31:R30 = Z) */
130 static GTY(()) rtx lpm_addr_reg_rtx;
132 /* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */
133 static GTY(()) rtx tmp_reg_rtx;
135 /* Zeroed register RTX (gen_rtx_REG (QImode, ZERO_REGNO)) */
136 static GTY(()) rtx zero_reg_rtx;
138 /* RAMPZ special function register */
139 static GTY(()) rtx rampz_rtx;
141 /* RTX containing the strings "" and "e", respectively */
142 static GTY(()) rtx xstring_empty;
143 static GTY(()) rtx xstring_e;
145 /* RTXs for all general purpose registers as QImode */
146 static GTY(()) rtx all_regs_rtx[32];
148 /* AVR register names {"r0", "r1", ..., "r31"} */
149 static const char *const avr_regnames[] = REGISTER_NAMES;
151 /* Preprocessor macros to define depending on MCU type. */
152 const char *avr_extra_arch_macro;
154 /* Current architecture. */
155 const struct base_arch_s *avr_current_arch;
157 /* Current device. */
158 const struct mcu_type_s *avr_current_device;
160 /* Section to put switch tables in. */
161 static GTY(()) section *progmem_swtable_section;
163 /* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
164 or to address space __pgm*. */
165 static GTY(()) section *progmem_section[6];
167 /* Condition for insns/expanders from avr-dimode.md. */
168 bool avr_have_dimode = true;
170 /* To track if code will use .bss and/or .data. */
171 bool avr_need_clear_bss_p = false;
172 bool avr_need_copy_data_p = false;
175 /* Initialize the GCC target structure. */
176 #undef TARGET_ASM_ALIGNED_HI_OP
177 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
178 #undef TARGET_ASM_ALIGNED_SI_OP
179 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
180 #undef TARGET_ASM_UNALIGNED_HI_OP
181 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
182 #undef TARGET_ASM_UNALIGNED_SI_OP
183 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
184 #undef TARGET_ASM_INTEGER
185 #define TARGET_ASM_INTEGER avr_assemble_integer
186 #undef TARGET_ASM_FILE_START
187 #define TARGET_ASM_FILE_START avr_file_start
188 #undef TARGET_ASM_FILE_END
189 #define TARGET_ASM_FILE_END avr_file_end
191 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
192 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
193 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
194 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
196 #undef TARGET_FUNCTION_VALUE
197 #define TARGET_FUNCTION_VALUE avr_function_value
198 #undef TARGET_LIBCALL_VALUE
199 #define TARGET_LIBCALL_VALUE avr_libcall_value
200 #undef TARGET_FUNCTION_VALUE_REGNO_P
201 #define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
203 #undef TARGET_ATTRIBUTE_TABLE
204 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
205 #undef TARGET_INSERT_ATTRIBUTES
206 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
207 #undef TARGET_SECTION_TYPE_FLAGS
208 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
210 #undef TARGET_ASM_NAMED_SECTION
211 #define TARGET_ASM_NAMED_SECTION avr_asm_named_section
212 #undef TARGET_ASM_INIT_SECTIONS
213 #define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
214 #undef TARGET_ENCODE_SECTION_INFO
215 #define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
216 #undef TARGET_ASM_SELECT_SECTION
217 #define TARGET_ASM_SELECT_SECTION avr_asm_select_section
219 #undef TARGET_REGISTER_MOVE_COST
220 #define TARGET_REGISTER_MOVE_COST avr_register_move_cost
221 #undef TARGET_MEMORY_MOVE_COST
222 #define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
223 #undef TARGET_RTX_COSTS
224 #define TARGET_RTX_COSTS avr_rtx_costs
225 #undef TARGET_ADDRESS_COST
226 #define TARGET_ADDRESS_COST avr_address_cost
227 #undef TARGET_MACHINE_DEPENDENT_REORG
228 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
229 #undef TARGET_FUNCTION_ARG
230 #define TARGET_FUNCTION_ARG avr_function_arg
231 #undef TARGET_FUNCTION_ARG_ADVANCE
232 #define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
234 #undef TARGET_RETURN_IN_MEMORY
235 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
237 #undef TARGET_STRICT_ARGUMENT_NAMING
238 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
240 #undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
241 #define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
243 #undef TARGET_HARD_REGNO_SCRATCH_OK
244 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
245 #undef TARGET_CASE_VALUES_THRESHOLD
246 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
248 #undef TARGET_FRAME_POINTER_REQUIRED
249 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
250 #undef TARGET_CAN_ELIMINATE
251 #define TARGET_CAN_ELIMINATE avr_can_eliminate
253 #undef TARGET_CLASS_LIKELY_SPILLED_P
254 #define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
256 #undef TARGET_OPTION_OVERRIDE
257 #define TARGET_OPTION_OVERRIDE avr_option_override
259 #undef TARGET_CANNOT_MODIFY_JUMPS_P
260 #define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
262 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
263 #define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
265 #undef TARGET_INIT_BUILTINS
266 #define TARGET_INIT_BUILTINS avr_init_builtins
268 #undef TARGET_EXPAND_BUILTIN
269 #define TARGET_EXPAND_BUILTIN avr_expand_builtin
271 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
272 #define TARGET_ASM_FUNCTION_RODATA_SECTION avr_asm_function_rodata_section
274 #undef TARGET_SCALAR_MODE_SUPPORTED_P
275 #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
277 #undef TARGET_ADDR_SPACE_SUBSET_P
278 #define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
280 #undef TARGET_ADDR_SPACE_CONVERT
281 #define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
283 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
284 #define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
286 #undef TARGET_ADDR_SPACE_POINTER_MODE
287 #define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
289 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
290 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P avr_addr_space_legitimate_address_p
292 #undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
293 #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
295 #undef TARGET_PRINT_OPERAND
296 #define TARGET_PRINT_OPERAND avr_print_operand
297 #undef TARGET_PRINT_OPERAND_ADDRESS
298 #define TARGET_PRINT_OPERAND_ADDRESS avr_print_operand_address
299 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
300 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P avr_print_operand_punct_valid_p
304 /* Custom function to replace string prefix.
306 Return a ggc-allocated string with strlen (OLD_PREFIX) characters removed
307 from the start of OLD_STR and then prepended with NEW_PREFIX. */
309 static inline const char*
310 avr_replace_prefix (const char *old_str,
311 const char *old_prefix, const char *new_prefix)
314 size_t len = strlen (old_str) + strlen (new_prefix) - strlen (old_prefix);
316 gcc_assert (strlen (old_prefix) <= strlen (old_str));
318 /* Unfortunately, ggc_alloc_string returns a const char* and thus cannot be
321 new_str = (char*) ggc_alloc_atomic (1 + len);
323 strcat (stpcpy (new_str, new_prefix), old_str + strlen (old_prefix));
325 return (const char*) new_str;
329 /* Custom function to count number of set bits. */
332 avr_popcount (unsigned int val)
346 /* Constraint helper function. XVAL is a CONST_INT or a CONST_DOUBLE.
347 Return true if the least significant N_BYTES bytes of XVAL all have a
348 popcount in POP_MASK and false, otherwise. POP_MASK represents a subset
349 of integers which contains an integer N iff bit N of POP_MASK is set. */
352 avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
356 enum machine_mode mode = GET_MODE (xval);
358 if (VOIDmode == mode)
361 for (i = 0; i < n_bytes; i++)
363 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
364 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
366 if (0 == (pop_mask & (1 << avr_popcount (val8))))
374 avr_option_override (void)
376 flag_delete_null_pointer_checks = 0;
378 /* caller-save.c looks for call-clobbered hard registers that are assigned
379 to pseudos that cross calls and tries so save-restore them around calls
380 in order to reduce the number of stack slots needed.
382 This might leads to situations where reload is no more able to cope
383 with the challenge of AVR's very few address registers and fails to
384 perform the requested spills. */
387 flag_caller_saves = 0;
389 /* Unwind tables currently require a frame pointer for correctness,
390 see toplev.c:process_options(). */
392 if ((flag_unwind_tables
393 || flag_non_call_exceptions
394 || flag_asynchronous_unwind_tables)
395 && !ACCUMULATE_OUTGOING_ARGS)
397 flag_omit_frame_pointer = 0;
400 avr_current_device = &avr_mcu_types[avr_mcu_index];
401 avr_current_arch = &avr_arch_types[avr_current_device->arch];
402 avr_extra_arch_macro = avr_current_device->macro;
404 init_machine_status = avr_init_machine_status;
406 avr_log_set_avr_log();
409 /* Function to set up the backend function structure. */
411 static struct machine_function *
412 avr_init_machine_status (void)
414 return ggc_alloc_cleared_machine_function ();
418 /* Implement `INIT_EXPANDERS'. */
419 /* The function works like a singleton. */
422 avr_init_expanders (void)
426 static bool done = false;
433 for (regno = 0; regno < 32; regno ++)
434 all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
436 lpm_reg_rtx = all_regs_rtx[LPM_REGNO];
437 tmp_reg_rtx = all_regs_rtx[TMP_REGNO];
438 zero_reg_rtx = all_regs_rtx[ZERO_REGNO];
440 lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
442 rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (RAMPZ_ADDR));
444 xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
445 xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
449 /* Return register class for register R. */
452 avr_regno_reg_class (int r)
454 static const enum reg_class reg_class_tab[] =
458 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
459 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
460 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
461 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
463 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
464 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
466 ADDW_REGS, ADDW_REGS,
468 POINTER_X_REGS, POINTER_X_REGS,
470 POINTER_Y_REGS, POINTER_Y_REGS,
472 POINTER_Z_REGS, POINTER_Z_REGS,
478 return reg_class_tab[r];
485 avr_scalar_mode_supported_p (enum machine_mode mode)
490 return default_scalar_mode_supported_p (mode);
494 /* Return TRUE if DECL is a VAR_DECL located in Flash and FALSE, otherwise. */
497 avr_decl_pgm_p (tree decl)
499 if (TREE_CODE (decl) != VAR_DECL
500 || TREE_TYPE (decl) == error_mark_node)
505 return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
509 /* Return TRUE if DECL is a VAR_DECL located in the 24-bit Flash
510 address space and FALSE, otherwise. */
513 avr_decl_pgmx_p (tree decl)
515 if (TREE_CODE (decl) != VAR_DECL
516 || TREE_TYPE (decl) == error_mark_node)
521 return (ADDR_SPACE_PGMX == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
525 /* Return TRUE if X is a MEM rtx located in Flash and FALSE, otherwise. */
528 avr_mem_pgm_p (rtx x)
531 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)));
535 /* Return TRUE if X is a MEM rtx located in the 24-bit Flash
536 address space and FALSE, otherwise. */
539 avr_mem_pgmx_p (rtx x)
542 && ADDR_SPACE_PGMX == MEM_ADDR_SPACE (x));
546 /* A helper for the subsequent function attribute used to dig for
547 attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
550 avr_lookup_function_attribute1 (const_tree func, const char *name)
552 if (FUNCTION_DECL == TREE_CODE (func))
554 if (NULL_TREE != lookup_attribute (name, DECL_ATTRIBUTES (func)))
559 func = TREE_TYPE (func);
562 gcc_assert (TREE_CODE (func) == FUNCTION_TYPE
563 || TREE_CODE (func) == METHOD_TYPE);
565 return NULL_TREE != lookup_attribute (name, TYPE_ATTRIBUTES (func));
568 /* Return nonzero if FUNC is a naked function. */
571 avr_naked_function_p (tree func)
573 return avr_lookup_function_attribute1 (func, "naked");
576 /* Return nonzero if FUNC is an interrupt function as specified
577 by the "interrupt" attribute. */
580 interrupt_function_p (tree func)
582 return avr_lookup_function_attribute1 (func, "interrupt");
585 /* Return nonzero if FUNC is a signal function as specified
586 by the "signal" attribute. */
589 signal_function_p (tree func)
591 return avr_lookup_function_attribute1 (func, "signal");
594 /* Return nonzero if FUNC is an OS_task function. */
597 avr_OS_task_function_p (tree func)
599 return avr_lookup_function_attribute1 (func, "OS_task");
602 /* Return nonzero if FUNC is an OS_main function. */
605 avr_OS_main_function_p (tree func)
607 return avr_lookup_function_attribute1 (func, "OS_main");
611 /* Implement `ACCUMULATE_OUTGOING_ARGS'. */
613 avr_accumulate_outgoing_args (void)
616 return TARGET_ACCUMULATE_OUTGOING_ARGS;
618 /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
619 what offset is correct. In some cases it is relative to
620 virtual_outgoing_args_rtx and in others it is relative to
621 virtual_stack_vars_rtx. For example code see
622 gcc.c-torture/execute/built-in-setjmp.c
623 gcc.c-torture/execute/builtins/sprintf-chk.c */
625 return (TARGET_ACCUMULATE_OUTGOING_ARGS
626 && !(cfun->calls_setjmp
627 || cfun->has_nonlocal_label));
631 /* Report contribution of accumulated outgoing arguments to stack size. */
634 avr_outgoing_args_size (void)
636 return ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0;
640 /* Implement `STARTING_FRAME_OFFSET'. */
641 /* This is the offset from the frame pointer register to the first stack slot
642 that contains a variable living in the frame. */
645 avr_starting_frame_offset (void)
647 return 1 + avr_outgoing_args_size ();
651 /* Return the number of hard registers to push/pop in the prologue/epilogue
652 of the current function, and optionally store these registers in SET. */
655 avr_regs_to_save (HARD_REG_SET *set)
658 int int_or_sig_p = (interrupt_function_p (current_function_decl)
659 || signal_function_p (current_function_decl));
662 CLEAR_HARD_REG_SET (*set);
665 /* No need to save any registers if the function never returns or
666 has the "OS_task" or "OS_main" attribute. */
667 if (TREE_THIS_VOLATILE (current_function_decl)
668 || cfun->machine->is_OS_task
669 || cfun->machine->is_OS_main)
672 for (reg = 0; reg < 32; reg++)
674 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
675 any global register variables. */
679 if ((int_or_sig_p && !current_function_is_leaf && call_used_regs[reg])
680 || (df_regs_ever_live_p (reg)
681 && (int_or_sig_p || !call_used_regs[reg])
682 /* Don't record frame pointer registers here. They are treated
683 indivitually in prologue. */
684 && !(frame_pointer_needed
685 && (reg == REG_Y || reg == (REG_Y+1)))))
688 SET_HARD_REG_BIT (*set, reg);
695 /* Return true if register FROM can be eliminated via register TO. */
698 avr_can_eliminate (const int from, const int to)
700 return ((from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
701 || (frame_pointer_needed && to == FRAME_POINTER_REGNUM)
702 || ((from == FRAME_POINTER_REGNUM
703 || from == FRAME_POINTER_REGNUM + 1)
704 && !frame_pointer_needed));
707 /* Compute offset between arg_pointer and frame_pointer. */
710 avr_initial_elimination_offset (int from, int to)
712 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
716 int offset = frame_pointer_needed ? 2 : 0;
717 int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
719 offset += avr_regs_to_save (NULL);
720 return (get_frame_size () + avr_outgoing_args_size()
721 + avr_pc_size + 1 + offset);
725 /* Actual start of frame is virtual_stack_vars_rtx this is offset from
726 frame pointer by +STARTING_FRAME_OFFSET.
727 Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET
728 avoids creating add/sub of offset in nonlocal goto and setjmp. */
731 avr_builtin_setjmp_frame_value (void)
733 return gen_rtx_MINUS (Pmode, virtual_stack_vars_rtx,
734 gen_int_mode (STARTING_FRAME_OFFSET, Pmode));
737 /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3 byte PC).
738 This is return address of function. */
740 avr_return_addr_rtx (int count, rtx tem)
744 /* Can only return this function's return address. Others not supported. */
750 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
751 warning (0, "'builtin_return_address' contains only 2 bytes of address");
754 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
756 r = gen_rtx_PLUS (Pmode, tem, r);
757 r = gen_frame_mem (Pmode, memory_address (Pmode, r));
758 r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
762 /* Return 1 if the function epilogue is just a single "ret". */
765 avr_simple_epilogue (void)
767 return (! frame_pointer_needed
768 && get_frame_size () == 0
769 && avr_outgoing_args_size() == 0
770 && avr_regs_to_save (NULL) == 0
771 && ! interrupt_function_p (current_function_decl)
772 && ! signal_function_p (current_function_decl)
773 && ! avr_naked_function_p (current_function_decl)
774 && ! TREE_THIS_VOLATILE (current_function_decl));
777 /* This function checks sequence of live registers. */
780 sequent_regs_live (void)
786 for (reg = 0; reg < 18; ++reg)
790 /* Don't recognize sequences that contain global register
799 if (!call_used_regs[reg])
801 if (df_regs_ever_live_p (reg))
811 if (!frame_pointer_needed)
813 if (df_regs_ever_live_p (REG_Y))
821 if (df_regs_ever_live_p (REG_Y+1))
834 return (cur_seq == live_seq) ? live_seq : 0;
837 /* Obtain the length sequence of insns. */
840 get_sequence_length (rtx insns)
845 for (insn = insns, length = 0; insn; insn = NEXT_INSN (insn))
846 length += get_attr_length (insn);
851 /* Implement INCOMING_RETURN_ADDR_RTX. */
854 avr_incoming_return_addr_rtx (void)
856 /* The return address is at the top of the stack. Note that the push
857 was via post-decrement, which means the actual address is off by one. */
858 return gen_frame_mem (HImode, plus_constant (stack_pointer_rtx, 1));
861 /* Helper for expand_prologue. Emit a push of a byte register. */
864 emit_push_byte (unsigned regno, bool frame_related_p)
868 mem = gen_rtx_POST_DEC (HImode, stack_pointer_rtx);
869 mem = gen_frame_mem (QImode, mem);
870 reg = gen_rtx_REG (QImode, regno);
872 insn = emit_insn (gen_rtx_SET (VOIDmode, mem, reg));
874 RTX_FRAME_RELATED_P (insn) = 1;
876 cfun->machine->stack_usage++;
880 avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
883 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
884 int live_seq = sequent_regs_live ();
886 bool minimize = (TARGET_CALL_PROLOGUES
889 && !cfun->machine->is_OS_task
890 && !cfun->machine->is_OS_main);
893 && (frame_pointer_needed
894 || avr_outgoing_args_size() > 8
895 || (AVR_2_BYTE_PC && live_seq > 6)
899 int first_reg, reg, offset;
901 emit_move_insn (gen_rtx_REG (HImode, REG_X),
902 gen_int_mode (size, HImode));
904 pattern = gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
905 gen_int_mode (live_seq+size, HImode));
906 insn = emit_insn (pattern);
907 RTX_FRAME_RELATED_P (insn) = 1;
909 /* Describe the effect of the unspec_volatile call to prologue_saves.
910 Note that this formulation assumes that add_reg_note pushes the
911 notes to the front. Thus we build them in the reverse order of
912 how we want dwarf2out to process them. */
914 /* The function does always set frame_pointer_rtx, but whether that
915 is going to be permanent in the function is frame_pointer_needed. */
917 add_reg_note (insn, REG_CFA_ADJUST_CFA,
918 gen_rtx_SET (VOIDmode, (frame_pointer_needed
920 : stack_pointer_rtx),
921 plus_constant (stack_pointer_rtx,
922 -(size + live_seq))));
924 /* Note that live_seq always contains r28+r29, but the other
925 registers to be saved are all below 18. */
927 first_reg = 18 - (live_seq - 2);
929 for (reg = 29, offset = -live_seq + 1;
931 reg = (reg == 28 ? 17 : reg - 1), ++offset)
935 m = gen_rtx_MEM (QImode, plus_constant (stack_pointer_rtx, offset));
936 r = gen_rtx_REG (QImode, reg);
937 add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (VOIDmode, m, r));
940 cfun->machine->stack_usage += size + live_seq;
946 for (reg = 0; reg < 32; ++reg)
947 if (TEST_HARD_REG_BIT (set, reg))
948 emit_push_byte (reg, true);
950 if (frame_pointer_needed
951 && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
953 /* Push frame pointer. Always be consistent about the
954 ordering of pushes -- epilogue_restores expects the
955 register pair to be pushed low byte first. */
957 emit_push_byte (REG_Y, true);
958 emit_push_byte (REG_Y + 1, true);
961 if (frame_pointer_needed
964 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
965 RTX_FRAME_RELATED_P (insn) = 1;
970 /* Creating a frame can be done by direct manipulation of the
971 stack or via the frame pointer. These two methods are:
978 the optimum method depends on function type, stack and
979 frame size. To avoid a complex logic, both methods are
980 tested and shortest is selected.
982 There is also the case where SIZE != 0 and no frame pointer is
983 needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
984 In that case, insn (*) is not needed in that case.
985 We use the X register as scratch. This is save because in X
987 In an interrupt routine, the case of SIZE != 0 together with
988 !frame_pointer_needed can only occur if the function is not a
989 leaf function and thus X has already been saved. */
991 rtx fp_plus_insns, fp, my_fp;
992 rtx sp_minus_size = plus_constant (stack_pointer_rtx, -size);
994 gcc_assert (frame_pointer_needed
996 || !current_function_is_leaf);
998 fp = my_fp = (frame_pointer_needed
1000 : gen_rtx_REG (Pmode, REG_X));
1002 if (AVR_HAVE_8BIT_SP)
1004 /* The high byte (r29) does not change:
1005 Prefer SUBI (1 cycle) over ABIW (2 cycles, same size). */
1007 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
1010 /************ Method 1: Adjust frame pointer ************/
1014 /* Normally, the dwarf2out frame-related-expr interpreter does
1015 not expect to have the CFA change once the frame pointer is
1016 set up. Thus, we avoid marking the move insn below and
1017 instead indicate that the entire operation is complete after
1018 the frame pointer subtraction is done. */
1020 insn = emit_move_insn (fp, stack_pointer_rtx);
1021 if (!frame_pointer_needed)
1022 RTX_FRAME_RELATED_P (insn) = 1;
1024 insn = emit_move_insn (my_fp, plus_constant (my_fp, -size));
1025 RTX_FRAME_RELATED_P (insn) = 1;
1027 if (frame_pointer_needed)
1029 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1030 gen_rtx_SET (VOIDmode, fp, sp_minus_size));
1033 /* Copy to stack pointer. Note that since we've already
1034 changed the CFA to the frame pointer this operation
1035 need not be annotated if frame pointer is needed. */
1037 if (AVR_HAVE_8BIT_SP)
1039 insn = emit_move_insn (stack_pointer_rtx, fp);
1041 else if (TARGET_NO_INTERRUPTS
1043 || cfun->machine->is_OS_main)
1045 rtx irqs_are_on = GEN_INT (!!cfun->machine->is_interrupt);
1047 insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
1052 insn = emit_move_insn (stack_pointer_rtx, fp);
1055 if (!frame_pointer_needed)
1056 RTX_FRAME_RELATED_P (insn) = 1;
1058 fp_plus_insns = get_insns ();
1061 /************ Method 2: Adjust Stack pointer ************/
1063 /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
1064 can only handle specific offsets. */
1066 if (avr_sp_immediate_operand (gen_int_mode (-size, HImode), HImode))
1072 insn = emit_move_insn (stack_pointer_rtx, sp_minus_size);
1073 RTX_FRAME_RELATED_P (insn) = 1;
1075 if (frame_pointer_needed)
1077 insn = emit_move_insn (fp, stack_pointer_rtx);
1078 RTX_FRAME_RELATED_P (insn) = 1;
1081 sp_plus_insns = get_insns ();
1084 /************ Use shortest method ************/
1086 emit_insn (get_sequence_length (sp_plus_insns)
1087 < get_sequence_length (fp_plus_insns)
1093 emit_insn (fp_plus_insns);
1096 cfun->machine->stack_usage += size;
1097 } /* !minimize && size != 0 */
1102 /* Output function prologue. */
1105 expand_prologue (void)
1110 size = get_frame_size() + avr_outgoing_args_size();
1112 /* Init cfun->machine. */
1113 cfun->machine->is_naked = avr_naked_function_p (current_function_decl);
1114 cfun->machine->is_interrupt = interrupt_function_p (current_function_decl);
1115 cfun->machine->is_signal = signal_function_p (current_function_decl);
1116 cfun->machine->is_OS_task = avr_OS_task_function_p (current_function_decl);
1117 cfun->machine->is_OS_main = avr_OS_main_function_p (current_function_decl);
1118 cfun->machine->stack_usage = 0;
1120 /* Prologue: naked. */
1121 if (cfun->machine->is_naked)
1126 avr_regs_to_save (&set);
1128 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1130 /* Enable interrupts. */
1131 if (cfun->machine->is_interrupt)
1132 emit_insn (gen_enable_interrupt ());
1134 /* Push zero reg. */
1135 emit_push_byte (ZERO_REGNO, true);
1138 emit_push_byte (TMP_REGNO, true);
1141 /* ??? There's no dwarf2 column reserved for SREG. */
1142 emit_move_insn (tmp_reg_rtx, gen_rtx_MEM (QImode, GEN_INT (SREG_ADDR)));
1143 emit_push_byte (TMP_REGNO, false);
1146 /* ??? There's no dwarf2 column reserved for RAMPZ. */
1148 && TEST_HARD_REG_BIT (set, REG_Z)
1149 && TEST_HARD_REG_BIT (set, REG_Z + 1))
1151 emit_move_insn (tmp_reg_rtx, rampz_rtx);
1152 emit_push_byte (TMP_REGNO, false);
1155 /* Clear zero reg. */
1156 emit_move_insn (zero_reg_rtx, const0_rtx);
1158 /* Prevent any attempt to delete the setting of ZERO_REG! */
1159 emit_use (zero_reg_rtx);
1162 avr_prologue_setup_frame (size, set);
1164 if (flag_stack_usage_info)
1165 current_function_static_stack_size = cfun->machine->stack_usage;
1168 /* Output summary at end of function prologue. */
1171 avr_asm_function_end_prologue (FILE *file)
1173 if (cfun->machine->is_naked)
1175 fputs ("/* prologue: naked */\n", file);
1179 if (cfun->machine->is_interrupt)
1181 fputs ("/* prologue: Interrupt */\n", file);
1183 else if (cfun->machine->is_signal)
1185 fputs ("/* prologue: Signal */\n", file);
1188 fputs ("/* prologue: function */\n", file);
1191 if (ACCUMULATE_OUTGOING_ARGS)
1192 fprintf (file, "/* outgoing args size = %d */\n",
1193 avr_outgoing_args_size());
1195 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
1197 fprintf (file, "/* stack size = %d */\n",
1198 cfun->machine->stack_usage);
1199 /* Create symbol stack offset here so all functions have it. Add 1 to stack
1200 usage for offset so that SP + .L__stack_offset = return address. */
1201 fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
1205 /* Implement EPILOGUE_USES. */
1208 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
1210 if (reload_completed
1212 && (cfun->machine->is_interrupt || cfun->machine->is_signal))
1217 /* Helper for expand_epilogue. Emit a pop of a byte register. */
1220 emit_pop_byte (unsigned regno)
1224 mem = gen_rtx_PRE_INC (HImode, stack_pointer_rtx);
1225 mem = gen_frame_mem (QImode, mem);
1226 reg = gen_rtx_REG (QImode, regno);
1228 emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
1231 /* Output RTL epilogue. */
1234 expand_epilogue (bool sibcall_p)
1241 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1243 size = get_frame_size() + avr_outgoing_args_size();
1245 /* epilogue: naked */
1246 if (cfun->machine->is_naked)
1248 gcc_assert (!sibcall_p);
1250 emit_jump_insn (gen_return ());
1254 avr_regs_to_save (&set);
1255 live_seq = sequent_regs_live ();
1257 minimize = (TARGET_CALL_PROLOGUES
1260 && !cfun->machine->is_OS_task
1261 && !cfun->machine->is_OS_main);
1265 || frame_pointer_needed
1268 /* Get rid of frame. */
1270 if (!frame_pointer_needed)
1272 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1277 emit_move_insn (frame_pointer_rtx,
1278 plus_constant (frame_pointer_rtx, size));
1281 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
1287 /* Try two methods to adjust stack and select shortest. */
1292 gcc_assert (frame_pointer_needed
1294 || !current_function_is_leaf);
1296 fp = my_fp = (frame_pointer_needed
1298 : gen_rtx_REG (Pmode, REG_X));
1300 if (AVR_HAVE_8BIT_SP)
1302 /* The high byte (r29) does not change:
1303 Prefer SUBI (1 cycle) over SBIW (2 cycles). */
1305 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
1308 /********** Method 1: Adjust fp register **********/
1312 if (!frame_pointer_needed)
1313 emit_move_insn (fp, stack_pointer_rtx);
1315 emit_move_insn (my_fp, plus_constant (my_fp, size));
1317 /* Copy to stack pointer. */
1319 if (AVR_HAVE_8BIT_SP)
1321 emit_move_insn (stack_pointer_rtx, fp);
1323 else if (TARGET_NO_INTERRUPTS
1325 || cfun->machine->is_OS_main)
1327 rtx irqs_are_on = GEN_INT (!!cfun->machine->is_interrupt);
1329 emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp, irqs_are_on));
1333 emit_move_insn (stack_pointer_rtx, fp);
1336 fp_plus_insns = get_insns ();
1339 /********** Method 2: Adjust Stack pointer **********/
1341 if (avr_sp_immediate_operand (gen_int_mode (size, HImode), HImode))
1347 emit_move_insn (stack_pointer_rtx,
1348 plus_constant (stack_pointer_rtx, size));
1350 sp_plus_insns = get_insns ();
1353 /************ Use shortest method ************/
1355 emit_insn (get_sequence_length (sp_plus_insns)
1356 < get_sequence_length (fp_plus_insns)
1361 emit_insn (fp_plus_insns);
1364 if (frame_pointer_needed
1365 && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
1367 /* Restore previous frame_pointer. See expand_prologue for
1368 rationale for not using pophi. */
1370 emit_pop_byte (REG_Y + 1);
1371 emit_pop_byte (REG_Y);
1374 /* Restore used registers. */
1376 for (reg = 31; reg >= 0; --reg)
1377 if (TEST_HARD_REG_BIT (set, reg))
1378 emit_pop_byte (reg);
1382 /* Restore RAMPZ using tmp reg as scratch. */
1385 && TEST_HARD_REG_BIT (set, REG_Z)
1386 && TEST_HARD_REG_BIT (set, REG_Z + 1))
1388 emit_pop_byte (TMP_REGNO);
1389 emit_move_insn (rampz_rtx, tmp_reg_rtx);
1392 /* Restore SREG using tmp reg as scratch. */
1394 emit_pop_byte (TMP_REGNO);
1395 emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (SREG_ADDR)),
1398 /* Restore tmp REG. */
1399 emit_pop_byte (TMP_REGNO);
1401 /* Restore zero REG. */
1402 emit_pop_byte (ZERO_REGNO);
1406 emit_jump_insn (gen_return ());
1409 /* Output summary messages at beginning of function epilogue. */
1412 avr_asm_function_begin_epilogue (FILE *file)
1414 fprintf (file, "/* epilogue start */\n");
1418 /* Implement TARGET_CANNOT_MODITY_JUMPS_P */
1421 avr_cannot_modify_jumps_p (void)
1424 /* Naked Functions must not have any instructions after
1425 their epilogue, see PR42240 */
1427 if (reload_completed
1429 && cfun->machine->is_naked)
1438 /* Helper function for `avr_legitimate_address_p'. */
1441 avr_reg_ok_for_addr_p (rtx reg, addr_space_t as,
1442 RTX_CODE outer_code, bool strict)
1445 && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), QImode,
1446 as, outer_code, UNKNOWN)
1448 && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
1452 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
1453 machine for a memory operand of mode MODE. */
1456 avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
1458 bool ok = CONSTANT_ADDRESS_P (x);
1460 switch (GET_CODE (x))
1463 ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
1468 && REG_X == REGNO (x))
1476 ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
1477 GET_CODE (x), strict);
1482 rtx reg = XEXP (x, 0);
1483 rtx op1 = XEXP (x, 1);
1486 && CONST_INT_P (op1)
1487 && INTVAL (op1) >= 0)
1489 bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
1494 || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
1497 if (reg == frame_pointer_rtx
1498 || reg == arg_pointer_rtx)
1503 else if (frame_pointer_needed
1504 && reg == frame_pointer_rtx)
1516 if (avr_log.legitimate_address_p)
1518 avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
1519 "reload_completed=%d reload_in_progress=%d %s:",
1520 ok, mode, strict, reload_completed, reload_in_progress,
1521 reg_renumber ? "(reg_renumber)" : "");
1523 if (GET_CODE (x) == PLUS
1524 && REG_P (XEXP (x, 0))
1525 && CONST_INT_P (XEXP (x, 1))
1526 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
1529 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
1530 true_regnum (XEXP (x, 0)));
1533 avr_edump ("\n%r\n", x);
1540 /* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
1541 now only a helper for avr_addr_space_legitimize_address. */
1542 /* Attempts to replace X with a valid
1543 memory address for an operand of mode MODE */
1546 avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
1548 bool big_offset_p = false;
1552 if (GET_CODE (oldx) == PLUS
1553 && REG_P (XEXP (oldx, 0)))
1555 if (REG_P (XEXP (oldx, 1)))
1556 x = force_reg (GET_MODE (oldx), oldx);
1557 else if (CONST_INT_P (XEXP (oldx, 1)))
1559 int offs = INTVAL (XEXP (oldx, 1));
1560 if (frame_pointer_rtx != XEXP (oldx, 0)
1561 && offs > MAX_LD_OFFSET (mode))
1563 big_offset_p = true;
1564 x = force_reg (GET_MODE (oldx), oldx);
1569 if (avr_log.legitimize_address)
1571 avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
1574 avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
1581 /* Implement `LEGITIMIZE_RELOAD_ADDRESS'. */
1582 /* This will allow register R26/27 to be used where it is no worse than normal
1583 base pointers R28/29 or R30/31. For example, if base offset is greater
1584 than 63 bytes or for R++ or --R addressing. */
1587 avr_legitimize_reload_address (rtx *px, enum machine_mode mode,
1588 int opnum, int type, int addr_type,
1589 int ind_levels ATTRIBUTE_UNUSED,
1590 rtx (*mk_memloc)(rtx,int))
1594 if (avr_log.legitimize_reload_address)
1595 avr_edump ("\n%?:%m %r\n", mode, x);
1597 if (1 && (GET_CODE (x) == POST_INC
1598 || GET_CODE (x) == PRE_DEC))
1600 push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
1601 POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
1602 opnum, RELOAD_OTHER);
1604 if (avr_log.legitimize_reload_address)
1605 avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
1606 POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
1611 if (GET_CODE (x) == PLUS
1612 && REG_P (XEXP (x, 0))
1613 && 0 == reg_equiv_constant (REGNO (XEXP (x, 0)))
1614 && CONST_INT_P (XEXP (x, 1))
1615 && INTVAL (XEXP (x, 1)) >= 1)
1617 bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
1621 if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
1623 int regno = REGNO (XEXP (x, 0));
1624 rtx mem = mk_memloc (x, regno);
1626 push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
1627 POINTER_REGS, Pmode, VOIDmode, 0, 0,
1630 if (avr_log.legitimize_reload_address)
1631 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
1632 POINTER_REGS, XEXP (mem, 0), NULL_RTX);
1634 push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
1635 BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
1638 if (avr_log.legitimize_reload_address)
1639 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
1640 BASE_POINTER_REGS, mem, NULL_RTX);
1645 else if (! (frame_pointer_needed
1646 && XEXP (x, 0) == frame_pointer_rtx))
1648 push_reload (x, NULL_RTX, px, NULL,
1649 POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
1652 if (avr_log.legitimize_reload_address)
1653 avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
1654 POINTER_REGS, x, NULL_RTX);
1664 /* Helper function to print assembler resp. track instruction
1665 sequence lengths. Always return "".
1668 Output assembler code from template TPL with operands supplied
1669 by OPERANDS. This is just forwarding to output_asm_insn.
1672 If N_WORDS >= 0 Add N_WORDS to *PLEN.
1673 If N_WORDS < 0 Set *PLEN to -N_WORDS.
1674 Don't output anything.
1678 avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
1682 output_asm_insn (tpl, operands);
1696 /* Return a pointer register name as a string. */
1699 ptrreg_to_str (int regno)
1703 case REG_X: return "X";
1704 case REG_Y: return "Y";
1705 case REG_Z: return "Z";
1707 output_operand_lossage ("address operand requires constraint for"
1708 " X, Y, or Z register");
1713 /* Return the condition name as a string.
1714 Used in conditional jump constructing */
1717 cond_string (enum rtx_code code)
1726 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1731 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1747 /* Implement `TARGET_PRINT_OPERAND_ADDRESS'. */
1748 /* Output ADDR to FILE as address. */
1751 avr_print_operand_address (FILE *file, rtx addr)
1753 switch (GET_CODE (addr))
1756 fprintf (file, ptrreg_to_str (REGNO (addr)));
1760 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1764 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1768 if (CONSTANT_ADDRESS_P (addr)
1769 && text_segment_operand (addr, VOIDmode))
1772 if (GET_CODE (x) == CONST)
1774 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x,1)) == CONST_INT)
1776 /* Assembler gs() will implant word address. Make offset
1777 a byte offset inside gs() for assembler. This is
1778 needed because the more logical (constant+gs(sym)) is not
1779 accepted by gas. For 128K and lower devices this is ok.
1780 For large devices it will create a Trampoline to offset
1781 from symbol which may not be what the user really wanted. */
1782 fprintf (file, "gs(");
1783 output_addr_const (file, XEXP (x,0));
1784 fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC ")",
1785 2 * INTVAL (XEXP (x, 1)));
1787 if (warning (0, "pointer offset from symbol maybe incorrect"))
1789 output_addr_const (stderr, addr);
1790 fprintf(stderr,"\n");
1795 fprintf (file, "gs(");
1796 output_addr_const (file, addr);
1797 fprintf (file, ")");
1801 output_addr_const (file, addr);
1806 /* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'. */
1809 avr_print_operand_punct_valid_p (unsigned char code)
1811 return code == '~' || code == '!';
1815 /* Implement `TARGET_PRINT_OPERAND'. */
1816 /* Output X as assembler operand to file FILE.
1817 For a description of supported %-codes, see top of avr.md. */
1820 avr_print_operand (FILE *file, rtx x, int code)
1824 if (code >= 'A' && code <= 'D')
1829 if (!AVR_HAVE_JMP_CALL)
1832 else if (code == '!')
1834 if (AVR_HAVE_EIJMP_EICALL)
1837 else if (code == 't'
1840 static int t_regno = -1;
1841 static int t_nbits = -1;
1843 if (REG_P (x) && t_regno < 0 && code == 'T')
1845 t_regno = REGNO (x);
1846 t_nbits = GET_MODE_BITSIZE (GET_MODE (x));
1848 else if (CONST_INT_P (x) && t_regno >= 0
1849 && IN_RANGE (INTVAL (x), 0, t_nbits - 1))
1851 int bpos = INTVAL (x);
1853 fprintf (file, "%s", reg_names[t_regno + bpos / 8]);
1855 fprintf (file, ",%d", bpos % 8);
1860 fatal_insn ("operands to %T/%t must be reg + const_int:", x);
1864 if (x == zero_reg_rtx)
1865 fprintf (file, "__zero_reg__");
1867 fprintf (file, reg_names[true_regnum (x) + abcd]);
1869 else if (CONST_INT_P (x))
1871 HOST_WIDE_INT ival = INTVAL (x);
1874 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival + abcd);
1875 else if (low_io_address_operand (x, VOIDmode)
1876 || high_io_address_operand (x, VOIDmode))
1880 case RAMPZ_ADDR: fprintf (file, "__RAMPZ__"); break;
1881 case SREG_ADDR: fprintf (file, "__SREG__"); break;
1882 case SP_ADDR: fprintf (file, "__SP_L__"); break;
1883 case SP_ADDR+1: fprintf (file, "__SP_H__"); break;
1886 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
1887 ival - avr_current_arch->sfr_offset);
1892 fatal_insn ("bad address, not an I/O address:", x);
1896 rtx addr = XEXP (x, 0);
1900 if (!CONSTANT_P (addr))
1901 fatal_insn ("bad address, not a constant:", addr);
1902 /* Assembler template with m-code is data - not progmem section */
1903 if (text_segment_operand (addr, VOIDmode))
1904 if (warning (0, "accessing data memory with"
1905 " program memory address"))
1907 output_addr_const (stderr, addr);
1908 fprintf(stderr,"\n");
1910 output_addr_const (file, addr);
1912 else if (code == 'i')
1914 avr_print_operand (file, addr, 'i');
1916 else if (code == 'o')
1918 if (GET_CODE (addr) != PLUS)
1919 fatal_insn ("bad address, not (reg+disp):", addr);
1921 avr_print_operand (file, XEXP (addr, 1), 0);
1923 else if (code == 'p' || code == 'r')
1925 if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
1926 fatal_insn ("bad address, not post_inc or pre_dec:", addr);
1929 avr_print_operand_address (file, XEXP (addr, 0)); /* X, Y, Z */
1931 avr_print_operand (file, XEXP (addr, 0), 0); /* r26, r28, r30 */
1933 else if (GET_CODE (addr) == PLUS)
1935 avr_print_operand_address (file, XEXP (addr,0));
1936 if (REGNO (XEXP (addr, 0)) == REG_X)
1937 fatal_insn ("internal compiler error. Bad address:"
1940 avr_print_operand (file, XEXP (addr,1), code);
1943 avr_print_operand_address (file, addr);
1945 else if (code == 'i')
1947 fatal_insn ("bad address, not an I/O address:", x);
1949 else if (code == 'x')
1951 /* Constant progmem address - like used in jmp or call */
1952 if (0 == text_segment_operand (x, VOIDmode))
1953 if (warning (0, "accessing program memory"
1954 " with data memory address"))
1956 output_addr_const (stderr, x);
1957 fprintf(stderr,"\n");
1959 /* Use normal symbol for direct address no linker trampoline needed */
1960 output_addr_const (file, x);
1962 else if (GET_CODE (x) == CONST_DOUBLE)
1966 if (GET_MODE (x) != SFmode)
1967 fatal_insn ("internal compiler error. Unknown mode:", x);
1968 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1969 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1970 fprintf (file, "0x%lx", val);
1972 else if (GET_CODE (x) == CONST_STRING)
1973 fputs (XSTR (x, 0), file);
1974 else if (code == 'j')
1975 fputs (cond_string (GET_CODE (x)), file);
1976 else if (code == 'k')
1977 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
1979 avr_print_operand_address (file, x);
1982 /* Update the condition code in the INSN. */
1985 notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
1988 enum attr_cc cc = get_attr_cc (insn);
1996 case CC_OUT_PLUS_NOCLOBBER:
1999 rtx *op = recog_data.operand;
2002 /* Extract insn's operands. */
2003 extract_constrain_insn_cached (insn);
2011 avr_out_plus (op, &len_dummy, &icc);
2012 cc = (enum attr_cc) icc;
2015 case CC_OUT_PLUS_NOCLOBBER:
2016 avr_out_plus_noclobber (op, &len_dummy, &icc);
2017 cc = (enum attr_cc) icc;
2022 cc = (op[1] == CONST0_RTX (GET_MODE (op[0]))
2023 && reg_overlap_mentioned_p (op[0], zero_reg_rtx))
2024 /* Loading zero-reg with 0 uses CLI and thus clobbers cc0. */
2026 /* Any other "r,rL" combination does not alter cc0. */
2030 } /* inner switch */
2034 } /* outer swicth */
2039 /* Special values like CC_OUT_PLUS from above have been
2040 mapped to "standard" CC_* values so we never come here. */
2046 /* Insn does not affect CC at all. */
2054 set = single_set (insn);
2058 cc_status.flags |= CC_NO_OVERFLOW;
2059 cc_status.value1 = SET_DEST (set);
2064 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
2065 The V flag may or may not be known but that's ok because
2066 alter_cond will change tests to use EQ/NE. */
2067 set = single_set (insn);
2071 cc_status.value1 = SET_DEST (set);
2072 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
2077 set = single_set (insn);
2080 cc_status.value1 = SET_SRC (set);
2084 /* Insn doesn't leave CC in a usable state. */
2090 /* Choose mode for jump insn:
2091 1 - relative jump in range -63 <= x <= 62 ;
2092 2 - relative jump in range -2046 <= x <= 2045 ;
2093 3 - absolute jump (only for ATmega[16]03). */
2096 avr_jump_mode (rtx x, rtx insn)
2098 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
2099 ? XEXP (x, 0) : x));
2100 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
2101 int jump_distance = cur_addr - dest_addr;
2103 if (-63 <= jump_distance && jump_distance <= 62)
2105 else if (-2046 <= jump_distance && jump_distance <= 2045)
2107 else if (AVR_HAVE_JMP_CALL)
2113 /* return an AVR condition jump commands.
2114 X is a comparison RTX.
2115 LEN is a number returned by avr_jump_mode function.
2116 if REVERSE nonzero then condition code in X must be reversed. */
2119 ret_cond_branch (rtx x, int len, int reverse)
2121 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
2126 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2127 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
2129 len == 2 ? (AS1 (breq,.+4) CR_TAB
2130 AS1 (brmi,.+2) CR_TAB
2132 (AS1 (breq,.+6) CR_TAB
2133 AS1 (brmi,.+4) CR_TAB
2137 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
2139 len == 2 ? (AS1 (breq,.+4) CR_TAB
2140 AS1 (brlt,.+2) CR_TAB
2142 (AS1 (breq,.+6) CR_TAB
2143 AS1 (brlt,.+4) CR_TAB
2146 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
2148 len == 2 ? (AS1 (breq,.+4) CR_TAB
2149 AS1 (brlo,.+2) CR_TAB
2151 (AS1 (breq,.+6) CR_TAB
2152 AS1 (brlo,.+4) CR_TAB
2155 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2156 return (len == 1 ? (AS1 (breq,%0) CR_TAB
2158 len == 2 ? (AS1 (breq,.+2) CR_TAB
2159 AS1 (brpl,.+2) CR_TAB
2161 (AS1 (breq,.+2) CR_TAB
2162 AS1 (brpl,.+4) CR_TAB
2165 return (len == 1 ? (AS1 (breq,%0) CR_TAB
2167 len == 2 ? (AS1 (breq,.+2) CR_TAB
2168 AS1 (brge,.+2) CR_TAB
2170 (AS1 (breq,.+2) CR_TAB
2171 AS1 (brge,.+4) CR_TAB
2174 return (len == 1 ? (AS1 (breq,%0) CR_TAB
2176 len == 2 ? (AS1 (breq,.+2) CR_TAB
2177 AS1 (brsh,.+2) CR_TAB
2179 (AS1 (breq,.+2) CR_TAB
2180 AS1 (brsh,.+4) CR_TAB
2188 return AS1 (br%k1,%0);
2190 return (AS1 (br%j1,.+2) CR_TAB
2193 return (AS1 (br%j1,.+4) CR_TAB
2202 return AS1 (br%j1,%0);
2204 return (AS1 (br%k1,.+2) CR_TAB
2207 return (AS1 (br%k1,.+4) CR_TAB
2215 /* Output insn cost for next insn. */
2218 final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
2219 int num_operands ATTRIBUTE_UNUSED)
2221 if (avr_log.rtx_costs)
2223 rtx set = single_set (insn);
2226 fprintf (asm_out_file, "/* DEBUG: cost = %d. */\n",
2227 set_src_cost (SET_SRC (set), optimize_insn_for_speed_p ()));
2229 fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d. */\n",
2230 rtx_cost (PATTERN (insn), INSN, 0,
2231 optimize_insn_for_speed_p()));
2235 /* Return 0 if undefined, 1 if always true or always false. */
2238 avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE op, rtx x)
2240 unsigned int max = (mode == QImode ? 0xff :
2241 mode == HImode ? 0xffff :
2242 mode == PSImode ? 0xffffff :
2243 mode == SImode ? 0xffffffff : 0);
2244 if (max && op && GET_CODE (x) == CONST_INT)
2246 if (unsigned_condition (op) != op)
2249 if (max != (INTVAL (x) & max)
2250 && INTVAL (x) != 0xff)
2257 /* Returns nonzero if REGNO is the number of a hard
2258 register in which function arguments are sometimes passed. */
2261 function_arg_regno_p(int r)
2263 return (r >= 8 && r <= 25);
2266 /* Initializing the variable cum for the state at the beginning
2267 of the argument list. */
2270 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
2271 tree fndecl ATTRIBUTE_UNUSED)
2274 cum->regno = FIRST_CUM_REG;
2275 if (!libname && stdarg_p (fntype))
2278 /* Assume the calle may be tail called */
2280 cfun->machine->sibcall_fails = 0;
2283 /* Returns the number of registers to allocate for a function argument. */
2286 avr_num_arg_regs (enum machine_mode mode, const_tree type)
2290 if (mode == BLKmode)
2291 size = int_size_in_bytes (type);
2293 size = GET_MODE_SIZE (mode);
2295 /* Align all function arguments to start in even-numbered registers.
2296 Odd-sized arguments leave holes above them. */
2298 return (size + 1) & ~1;
2301 /* Controls whether a function argument is passed
2302 in a register, and which register. */
2305 avr_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
2306 const_tree type, bool named ATTRIBUTE_UNUSED)
2308 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2309 int bytes = avr_num_arg_regs (mode, type);
2311 if (cum->nregs && bytes <= cum->nregs)
2312 return gen_rtx_REG (mode, cum->regno - bytes);
2317 /* Update the summarizer variable CUM to advance past an argument
2318 in the argument list. */
2321 avr_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
2322 const_tree type, bool named ATTRIBUTE_UNUSED)
2324 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2325 int bytes = avr_num_arg_regs (mode, type);
2327 cum->nregs -= bytes;
2328 cum->regno -= bytes;
2330 /* A parameter is being passed in a call-saved register. As the original
2331 contents of these regs has to be restored before leaving the function,
2332 a function must not pass arguments in call-saved regs in order to get
2337 && !call_used_regs[cum->regno])
2339 /* FIXME: We ship info on failing tail-call in struct machine_function.
2340 This uses internals of calls.c:expand_call() and the way args_so_far
2341 is used. targetm.function_ok_for_sibcall() needs to be extended to
2342 pass &args_so_far, too. At present, CUMULATIVE_ARGS is target
2343 dependent so that such an extension is not wanted. */
2345 cfun->machine->sibcall_fails = 1;
2348 /* Test if all registers needed by the ABI are actually available. If the
2349 user has fixed a GPR needed to pass an argument, an (implicit) function
2350 call will clobber that fixed register. See PR45099 for an example. */
2357 for (regno = cum->regno; regno < cum->regno + bytes; regno++)
2358 if (fixed_regs[regno])
2359 warning (0, "fixed register %s used to pass parameter to function",
2363 if (cum->nregs <= 0)
2366 cum->regno = FIRST_CUM_REG;
2370 /* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
2371 /* Decide whether we can make a sibling call to a function. DECL is the
2372 declaration of the function being targeted by the call and EXP is the
2373 CALL_EXPR representing the call. */
2376 avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
2380 /* Tail-calling must fail if callee-saved regs are used to pass
2381 function args. We must not tail-call when `epilogue_restores'
2382 is used. Unfortunately, we cannot tell at this point if that
2383 actually will happen or not, and we cannot step back from
2384 tail-calling. Thus, we inhibit tail-calling with -mcall-prologues. */
2386 if (cfun->machine->sibcall_fails
2387 || TARGET_CALL_PROLOGUES)
2392 fntype_callee = TREE_TYPE (CALL_EXPR_FN (exp_callee));
2396 decl_callee = TREE_TYPE (decl_callee);
2400 decl_callee = fntype_callee;
2402 while (FUNCTION_TYPE != TREE_CODE (decl_callee)
2403 && METHOD_TYPE != TREE_CODE (decl_callee))
2405 decl_callee = TREE_TYPE (decl_callee);
2409 /* Ensure that caller and callee have compatible epilogues */
2411 if (interrupt_function_p (current_function_decl)
2412 || signal_function_p (current_function_decl)
2413 || avr_naked_function_p (decl_callee)
2414 || avr_naked_function_p (current_function_decl)
2415 /* FIXME: For OS_task and OS_main, we are over-conservative.
2416 This is due to missing documentation of these attributes
2417 and what they actually should do and should not do. */
2418 || (avr_OS_task_function_p (decl_callee)
2419 != avr_OS_task_function_p (current_function_decl))
2420 || (avr_OS_main_function_p (decl_callee)
2421 != avr_OS_main_function_p (current_function_decl)))
2429 /***********************************************************************
2430 Functions for outputting various mov's for a various modes
2431 ************************************************************************/
2433 /* Return true if a value of mode MODE is read from flash by
2434 __load_* function from libgcc. */
2437 avr_load_libgcc_p (rtx op)
2439 enum machine_mode mode = GET_MODE (op);
2440 int n_bytes = GET_MODE_SIZE (mode);
2444 && avr_mem_pgm_p (op));
2447 /* Return true if a value of mode MODE is read by __xload_* function. */
2450 avr_xload_libgcc_p (enum machine_mode mode)
2452 int n_bytes = GET_MODE_SIZE (mode);
2455 && avr_current_arch->n_segments > 1
2456 && !AVR_HAVE_ELPMX);
2460 /* Find an unused d-register to be used as scratch in INSN.
2461 EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
2462 is a register, skip all possible return values that overlap EXCLUDE.
2463 The policy for the returned register is similar to that of
2464 `reg_unused_after', i.e. the returned register may overlap the SET_DEST
2467 Return a QImode d-register or NULL_RTX if nothing found. */
2470 avr_find_unused_d_reg (rtx insn, rtx exclude)
2473 bool isr_p = (interrupt_function_p (current_function_decl)
2474 || signal_function_p (current_function_decl));
2476 for (regno = 16; regno < 32; regno++)
2478 rtx reg = all_regs_rtx[regno];
2481 && reg_overlap_mentioned_p (exclude, reg))
2482 || fixed_regs[regno])
2487 /* Try non-live register */
2489 if (!df_regs_ever_live_p (regno)
2490 && (TREE_THIS_VOLATILE (current_function_decl)
2491 || cfun->machine->is_OS_task
2492 || cfun->machine->is_OS_main
2493 || (!isr_p && call_used_regs[regno])))
2498 /* Any live register can be used if it is unused after.
2499 Prologue/epilogue will care for it as needed. */
2501 if (df_regs_ever_live_p (regno)
2502 && reg_unused_after (insn, reg))
2512 /* Helper function for the next function in the case where only restricted
2513 version of LPM instruction is available. */
2516 avr_out_lpm_no_lpmx (rtx insn, rtx *xop, int *plen)
2520 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
2523 regno_dest = REGNO (dest);
2525 /* The implicit target register of LPM. */
2526 xop[3] = lpm_reg_rtx;
2528 switch (GET_CODE (addr))
2535 gcc_assert (REG_Z == REGNO (addr));
2543 avr_asm_len ("%4lpm", xop, plen, 1);
2545 if (regno_dest != LPM_REGNO)
2546 avr_asm_len ("mov %0,%3", xop, plen, 1);
2551 if (REGNO (dest) == REG_Z)
2552 return avr_asm_len ("%4lpm" CR_TAB
2557 "pop %A0", xop, plen, 6);
2559 avr_asm_len ("%4lpm" CR_TAB
2563 "mov %B0,%3", xop, plen, 5);
2565 if (!reg_unused_after (insn, addr))
2566 avr_asm_len ("sbiw %2,1", xop, plen, 1);
2575 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
2578 if (regno_dest == LPM_REGNO)
2579 avr_asm_len ("%4lpm" CR_TAB
2580 "adiw %2,1", xop, plen, 2);
2582 avr_asm_len ("%4lpm" CR_TAB
2584 "adiw %2,1", xop, plen, 3);
2587 avr_asm_len ("%4lpm" CR_TAB
2589 "adiw %2,1", xop, plen, 3);
2592 avr_asm_len ("%4lpm" CR_TAB
2594 "adiw %2,1", xop, plen, 3);
2597 avr_asm_len ("%4lpm" CR_TAB
2599 "adiw %2,1", xop, plen, 3);
2601 break; /* POST_INC */
2603 } /* switch CODE (addr) */
2609 /* If PLEN == NULL: Ouput instructions to load a value from a memory location
2610 OP[1] in AS1 to register OP[0].
2611 If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
2615 avr_out_lpm (rtx insn, rtx *op, int *plen)
2619 rtx src = SET_SRC (single_set (insn));
2621 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
2633 warning (0, "writing to address space %qs not supported",
2634 avr_addrspace[MEM_ADDR_SPACE (dest)].name);
2639 as = MEM_ADDR_SPACE (src);
2641 addr = XEXP (src, 0);
2642 code = GET_CODE (addr);
2644 gcc_assert (REG_P (dest));
2646 if (as == ADDR_SPACE_PGMX)
2648 /* We are called from avr_out_xload because someone wrote
2649 __pgmx on a device with just one flash segment. */
2651 gcc_assert (LO_SUM == code);
2653 addr = XEXP (addr, 1);
2656 gcc_assert (REG == code || POST_INC == code);
2660 xop[2] = lpm_addr_reg_rtx;
2661 xop[4] = xstring_empty;
2662 xop[5] = tmp_reg_rtx;
2664 regno_dest = REGNO (dest);
2666 /* Cut down segment number to a number the device actually supports.
2667 We do this late to preserve the address space's name for diagnostics. */
2669 segment = avr_addrspace[as].segment % avr_current_arch->n_segments;
2671 /* Set RAMPZ as needed. */
2675 xop[4] = GEN_INT (segment);
2677 if (xop[3] = avr_find_unused_d_reg (insn, lpm_addr_reg_rtx),
2680 avr_asm_len ("ldi %3,%4" CR_TAB
2681 "out __RAMPZ__,%3", xop, plen, 2);
2683 else if (segment == 1)
2685 avr_asm_len ("clr %5" CR_TAB
2687 "out __RAMPZ__,%5", xop, plen, 3);
2691 avr_asm_len ("mov %5,%2" CR_TAB
2693 "out __RAMPZ__,%2" CR_TAB
2694 "mov %2,%5", xop, plen, 4);
2699 if (!AVR_HAVE_ELPMX)
2700 return avr_out_lpm_no_lpmx (insn, xop, plen);
2702 else if (!AVR_HAVE_LPMX)
2704 return avr_out_lpm_no_lpmx (insn, xop, plen);
2707 /* We have [E]LPMX: Output reading from Flash the comfortable way. */
2709 switch (GET_CODE (addr))
2716 gcc_assert (REG_Z == REGNO (addr));
2724 return avr_asm_len ("%4lpm %0,%a2", xop, plen, 1);
2727 if (REGNO (dest) == REG_Z)
2728 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
2729 "%4lpm %B0,%a2" CR_TAB
2730 "mov %A0,%5", xop, plen, 3);
2733 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
2734 "%4lpm %B0,%a2", xop, plen, 2);
2736 if (!reg_unused_after (insn, addr))
2737 avr_asm_len ("sbiw %2,1", xop, plen, 1);
2744 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
2745 "%4lpm %B0,%a2+" CR_TAB
2746 "%4lpm %C0,%a2", xop, plen, 3);
2748 if (!reg_unused_after (insn, addr))
2749 avr_asm_len ("sbiw %2,2", xop, plen, 1);
2755 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
2756 "%4lpm %B0,%a2+", xop, plen, 2);
2758 if (REGNO (dest) == REG_Z - 2)
2759 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
2760 "%4lpm %C0,%a2" CR_TAB
2761 "mov %D0,%5", xop, plen, 3);
2764 avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
2765 "%4lpm %D0,%a2", xop, plen, 2);
2767 if (!reg_unused_after (insn, addr))
2768 avr_asm_len ("sbiw %2,3", xop, plen, 1);
2778 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
2781 avr_asm_len ("%4lpm %A0,%a2+", xop, plen, 1);
2782 if (n_bytes >= 2) avr_asm_len ("%4lpm %B0,%a2+", xop, plen, 1);
2783 if (n_bytes >= 3) avr_asm_len ("%4lpm %C0,%a2+", xop, plen, 1);
2784 if (n_bytes >= 4) avr_asm_len ("%4lpm %D0,%a2+", xop, plen, 1);
2786 break; /* POST_INC */
2788 } /* switch CODE (addr) */
2794 /* Worker function for xload_<mode> and xload_8 insns. */
2797 avr_out_xload (rtx insn, rtx *op, int *plen)
2801 int n_bytes = GET_MODE_SIZE (GET_MODE (reg));
2802 unsigned int regno = REGNO (reg);
2804 if (avr_current_arch->n_segments == 1)
2805 return avr_out_lpm (insn, op, plen);
2809 xop[2] = lpm_addr_reg_rtx;
2810 xop[3] = lpm_reg_rtx;
2811 xop[4] = tmp_reg_rtx;
2813 avr_asm_len ("out __RAMPZ__,%1", xop, plen, -1);
2818 return avr_asm_len ("elpm %0,%a2", xop, plen, 1);
2820 return avr_asm_len ("elpm" CR_TAB
2821 "mov %0,%3", xop, plen, 2);
2824 gcc_assert (AVR_HAVE_ELPMX);
2826 if (!reg_overlap_mentioned_p (reg, lpm_addr_reg_rtx))
2828 /* Insn clobbers the Z-register so we can use post-increment. */
2830 avr_asm_len ("elpm %A0,%a2+", xop, plen, 1);
2831 if (n_bytes >= 2) avr_asm_len ("elpm %B0,%a2+", xop, plen, 1);
2832 if (n_bytes >= 3) avr_asm_len ("elpm %C0,%a2+", xop, plen, 1);
2833 if (n_bytes >= 4) avr_asm_len ("elpm %D0,%a2+", xop, plen, 1);
2844 gcc_assert (regno == REGNO (lpm_addr_reg_rtx));
2846 return avr_asm_len ("elpm %4,%a2+" CR_TAB
2847 "elpm %B0,%a2" CR_TAB
2848 "mov %A0,%4", xop, plen, 3);
2852 gcc_assert (regno + 2 == REGNO (lpm_addr_reg_rtx));
2854 avr_asm_len ("elpm %A0,%a2+" CR_TAB
2855 "elpm %B0,%a2+", xop, plen, 2);
2858 return avr_asm_len ("elpm %C0,%a2", xop, plen, 1);
2860 return avr_asm_len ("elpm %4,%a2+" CR_TAB
2861 "elpm %D0,%a2" CR_TAB
2862 "mov %C0,%4", xop, plen, 3);
2870 output_movqi (rtx insn, rtx operands[], int *l)
2873 rtx dest = operands[0];
2874 rtx src = operands[1];
2877 if (avr_mem_pgm_p (src)
2878 || avr_mem_pgm_p (dest))
2880 return avr_out_lpm (insn, operands, real_l);
2888 if (register_operand (dest, QImode))
2890 if (register_operand (src, QImode)) /* mov r,r */
2892 if (test_hard_reg_class (STACK_REG, dest))
2893 return AS2 (out,%0,%1);
2894 else if (test_hard_reg_class (STACK_REG, src))
2895 return AS2 (in,%0,%1);
2897 return AS2 (mov,%0,%1);
2899 else if (CONSTANT_P (src))
2901 output_reload_in_const (operands, NULL_RTX, real_l, false);
2904 else if (GET_CODE (src) == MEM)
2905 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
2907 else if (GET_CODE (dest) == MEM)
2912 xop[1] = src == const0_rtx ? zero_reg_rtx : src;
2914 return out_movqi_mr_r (insn, xop, real_l);
2921 output_movhi (rtx insn, rtx xop[], int *plen)
2926 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 2);
2928 if (avr_mem_pgm_p (src)
2929 || avr_mem_pgm_p (dest))
2931 return avr_out_lpm (insn, xop, plen);
2936 if (REG_P (src)) /* mov r,r */
2938 if (test_hard_reg_class (STACK_REG, dest))
2940 if (AVR_HAVE_8BIT_SP)
2941 return avr_asm_len ("out __SP_L__,%A1", xop, plen, -1);
2943 /* Use simple load of SP if no interrupts are used. */
2945 return TARGET_NO_INTERRUPTS
2946 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
2947 "out __SP_L__,%A1", xop, plen, -2)
2949 : avr_asm_len ("in __tmp_reg__,__SREG__" CR_TAB
2951 "out __SP_H__,%B1" CR_TAB
2952 "out __SREG__,__tmp_reg__" CR_TAB
2953 "out __SP_L__,%A1", xop, plen, -5);
2955 else if (test_hard_reg_class (STACK_REG, src))
2957 return AVR_HAVE_8BIT_SP
2958 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
2959 "clr %B0", xop, plen, -2)
2961 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
2962 "in %B0,__SP_H__", xop, plen, -2);
2965 return AVR_HAVE_MOVW
2966 ? avr_asm_len ("movw %0,%1", xop, plen, -1)
2968 : avr_asm_len ("mov %A0,%A1" CR_TAB
2969 "mov %B0,%B1", xop, plen, -2);
2971 else if (CONSTANT_P (src))
2973 return output_reload_inhi (xop, NULL, plen);
2975 else if (MEM_P (src))
2977 return out_movhi_r_mr (insn, xop, plen); /* mov r,m */
2980 else if (MEM_P (dest))
2985 xop[1] = src == const0_rtx ? zero_reg_rtx : src;
2987 return out_movhi_mr_r (insn, xop, plen);
2990 fatal_insn ("invalid insn:", insn);
2996 out_movqi_r_mr (rtx insn, rtx op[], int *plen)
3000 rtx x = XEXP (src, 0);
3002 if (CONSTANT_ADDRESS_P (x))
3004 return optimize > 0 && io_address_operand (x, QImode)
3005 ? avr_asm_len ("in %0,%i1", op, plen, -1)
3006 : avr_asm_len ("lds %0,%m1", op, plen, -2);
3008 else if (GET_CODE (x) == PLUS
3009 && REG_P (XEXP (x, 0))
3010 && CONST_INT_P (XEXP (x, 1)))
3012 /* memory access by reg+disp */
3014 int disp = INTVAL (XEXP (x, 1));
3016 if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
3018 if (REGNO (XEXP (x, 0)) != REG_Y)
3019 fatal_insn ("incorrect insn:",insn);
3021 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
3022 return avr_asm_len ("adiw r28,%o1-63" CR_TAB
3023 "ldd %0,Y+63" CR_TAB
3024 "sbiw r28,%o1-63", op, plen, -3);
3026 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
3027 "sbci r29,hi8(-%o1)" CR_TAB
3029 "subi r28,lo8(%o1)" CR_TAB
3030 "sbci r29,hi8(%o1)", op, plen, -5);
3032 else if (REGNO (XEXP (x, 0)) == REG_X)
3034 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
3035 it but I have this situation with extremal optimizing options. */
3037 avr_asm_len ("adiw r26,%o1" CR_TAB
3038 "ld %0,X", op, plen, -2);
3040 if (!reg_overlap_mentioned_p (dest, XEXP (x,0))
3041 && !reg_unused_after (insn, XEXP (x,0)))
3043 avr_asm_len ("sbiw r26,%o1", op, plen, 1);
3049 return avr_asm_len ("ldd %0,%1", op, plen, -1);
3052 return avr_asm_len ("ld %0,%1", op, plen, -1);
3056 out_movhi_r_mr (rtx insn, rtx op[], int *plen)
3060 rtx base = XEXP (src, 0);
3061 int reg_dest = true_regnum (dest);
3062 int reg_base = true_regnum (base);
3063 /* "volatile" forces reading low byte first, even if less efficient,
3064 for correct operation with 16-bit I/O registers. */
3065 int mem_volatile_p = MEM_VOLATILE_P (src);
3069 if (reg_dest == reg_base) /* R = (R) */
3070 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
3072 "mov %A0,__tmp_reg__", op, plen, -3);
3074 if (reg_base != REG_X)
3075 return avr_asm_len ("ld %A0,%1" CR_TAB
3076 "ldd %B0,%1+1", op, plen, -2);
3078 avr_asm_len ("ld %A0,X+" CR_TAB
3079 "ld %B0,X", op, plen, -2);
3081 if (!reg_unused_after (insn, base))
3082 avr_asm_len ("sbiw r26,1", op, plen, 1);
3086 else if (GET_CODE (base) == PLUS) /* (R + i) */
3088 int disp = INTVAL (XEXP (base, 1));
3089 int reg_base = true_regnum (XEXP (base, 0));
3091 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
3093 if (REGNO (XEXP (base, 0)) != REG_Y)
3094 fatal_insn ("incorrect insn:",insn);
3096 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))
3097 ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
3098 "ldd %A0,Y+62" CR_TAB
3099 "ldd %B0,Y+63" CR_TAB
3100 "sbiw r28,%o1-62", op, plen, -4)
3102 : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
3103 "sbci r29,hi8(-%o1)" CR_TAB
3105 "ldd %B0,Y+1" CR_TAB
3106 "subi r28,lo8(%o1)" CR_TAB
3107 "sbci r29,hi8(%o1)", op, plen, -6);
3110 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
3111 it but I have this situation with extremal
3112 optimization options. */
3114 if (reg_base == REG_X)
3115 return reg_base == reg_dest
3116 ? avr_asm_len ("adiw r26,%o1" CR_TAB
3117 "ld __tmp_reg__,X+" CR_TAB
3119 "mov %A0,__tmp_reg__", op, plen, -4)
3121 : avr_asm_len ("adiw r26,%o1" CR_TAB
3124 "sbiw r26,%o1+1", op, plen, -4);
3126 return reg_base == reg_dest
3127 ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
3128 "ldd %B0,%B1" CR_TAB
3129 "mov %A0,__tmp_reg__", op, plen, -3)
3131 : avr_asm_len ("ldd %A0,%A1" CR_TAB
3132 "ldd %B0,%B1", op, plen, -2);
3134 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
3136 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
3137 fatal_insn ("incorrect insn:", insn);
3139 if (!mem_volatile_p)
3140 return avr_asm_len ("ld %B0,%1" CR_TAB
3141 "ld %A0,%1", op, plen, -2);
3143 return REGNO (XEXP (base, 0)) == REG_X
3144 ? avr_asm_len ("sbiw r26,2" CR_TAB
3147 "sbiw r26,1", op, plen, -4)
3149 : avr_asm_len ("sbiw %r1,2" CR_TAB
3151 "ldd %B0,%p1+1", op, plen, -3);
3153 else if (GET_CODE (base) == POST_INC) /* (R++) */
3155 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
3156 fatal_insn ("incorrect insn:", insn);
3158 return avr_asm_len ("ld %A0,%1" CR_TAB
3159 "ld %B0,%1", op, plen, -2);
3161 else if (CONSTANT_ADDRESS_P (base))
3163 return optimize > 0 && io_address_operand (base, HImode)
3164 ? avr_asm_len ("in %A0,%i1" CR_TAB
3165 "in %B0,%i1+1", op, plen, -2)
3167 : avr_asm_len ("lds %A0,%m1" CR_TAB
3168 "lds %B0,%m1+1", op, plen, -4);
3171 fatal_insn ("unknown move insn:",insn);
3176 out_movsi_r_mr (rtx insn, rtx op[], int *l)
3180 rtx base = XEXP (src, 0);
3181 int reg_dest = true_regnum (dest);
3182 int reg_base = true_regnum (base);
3190 if (reg_base == REG_X) /* (R26) */
3192 if (reg_dest == REG_X)
3193 /* "ld r26,-X" is undefined */
3194 return *l=7, (AS2 (adiw,r26,3) CR_TAB
3195 AS2 (ld,r29,X) CR_TAB
3196 AS2 (ld,r28,-X) CR_TAB
3197 AS2 (ld,__tmp_reg__,-X) CR_TAB
3198 AS2 (sbiw,r26,1) CR_TAB
3199 AS2 (ld,r26,X) CR_TAB
3200 AS2 (mov,r27,__tmp_reg__));
3201 else if (reg_dest == REG_X - 2)
3202 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
3203 AS2 (ld,%B0,X+) CR_TAB
3204 AS2 (ld,__tmp_reg__,X+) CR_TAB
3205 AS2 (ld,%D0,X) CR_TAB
3206 AS2 (mov,%C0,__tmp_reg__));
3207 else if (reg_unused_after (insn, base))
3208 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
3209 AS2 (ld,%B0,X+) CR_TAB
3210 AS2 (ld,%C0,X+) CR_TAB
3213 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
3214 AS2 (ld,%B0,X+) CR_TAB
3215 AS2 (ld,%C0,X+) CR_TAB
3216 AS2 (ld,%D0,X) CR_TAB
3221 if (reg_dest == reg_base)
3222 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
3223 AS2 (ldd,%C0,%1+2) CR_TAB
3224 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
3225 AS2 (ld,%A0,%1) CR_TAB
3226 AS2 (mov,%B0,__tmp_reg__));
3227 else if (reg_base == reg_dest + 2)
3228 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
3229 AS2 (ldd,%B0,%1+1) CR_TAB
3230 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
3231 AS2 (ldd,%D0,%1+3) CR_TAB
3232 AS2 (mov,%C0,__tmp_reg__));
3234 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
3235 AS2 (ldd,%B0,%1+1) CR_TAB
3236 AS2 (ldd,%C0,%1+2) CR_TAB
3237 AS2 (ldd,%D0,%1+3));
3240 else if (GET_CODE (base) == PLUS) /* (R + i) */
3242 int disp = INTVAL (XEXP (base, 1));
3244 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
3246 if (REGNO (XEXP (base, 0)) != REG_Y)
3247 fatal_insn ("incorrect insn:",insn);
3249 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
3250 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
3251 AS2 (ldd,%A0,Y+60) CR_TAB
3252 AS2 (ldd,%B0,Y+61) CR_TAB
3253 AS2 (ldd,%C0,Y+62) CR_TAB
3254 AS2 (ldd,%D0,Y+63) CR_TAB
3255 AS2 (sbiw,r28,%o1-60));
3257 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
3258 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
3259 AS2 (ld,%A0,Y) CR_TAB
3260 AS2 (ldd,%B0,Y+1) CR_TAB
3261 AS2 (ldd,%C0,Y+2) CR_TAB
3262 AS2 (ldd,%D0,Y+3) CR_TAB
3263 AS2 (subi,r28,lo8(%o1)) CR_TAB
3264 AS2 (sbci,r29,hi8(%o1)));
3267 reg_base = true_regnum (XEXP (base, 0));
3268 if (reg_base == REG_X)
3271 if (reg_dest == REG_X)
3274 /* "ld r26,-X" is undefined */
3275 return (AS2 (adiw,r26,%o1+3) CR_TAB
3276 AS2 (ld,r29,X) CR_TAB
3277 AS2 (ld,r28,-X) CR_TAB
3278 AS2 (ld,__tmp_reg__,-X) CR_TAB
3279 AS2 (sbiw,r26,1) CR_TAB
3280 AS2 (ld,r26,X) CR_TAB
3281 AS2 (mov,r27,__tmp_reg__));
3284 if (reg_dest == REG_X - 2)
3285 return (AS2 (adiw,r26,%o1) CR_TAB
3286 AS2 (ld,r24,X+) CR_TAB
3287 AS2 (ld,r25,X+) CR_TAB
3288 AS2 (ld,__tmp_reg__,X+) CR_TAB
3289 AS2 (ld,r27,X) CR_TAB
3290 AS2 (mov,r26,__tmp_reg__));
3292 return (AS2 (adiw,r26,%o1) CR_TAB
3293 AS2 (ld,%A0,X+) CR_TAB
3294 AS2 (ld,%B0,X+) CR_TAB
3295 AS2 (ld,%C0,X+) CR_TAB
3296 AS2 (ld,%D0,X) CR_TAB
3297 AS2 (sbiw,r26,%o1+3));
3299 if (reg_dest == reg_base)
3300 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
3301 AS2 (ldd,%C0,%C1) CR_TAB
3302 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
3303 AS2 (ldd,%A0,%A1) CR_TAB
3304 AS2 (mov,%B0,__tmp_reg__));
3305 else if (reg_dest == reg_base - 2)
3306 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
3307 AS2 (ldd,%B0,%B1) CR_TAB
3308 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
3309 AS2 (ldd,%D0,%D1) CR_TAB
3310 AS2 (mov,%C0,__tmp_reg__));
3311 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
3312 AS2 (ldd,%B0,%B1) CR_TAB
3313 AS2 (ldd,%C0,%C1) CR_TAB
3316 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
3317 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
3318 AS2 (ld,%C0,%1) CR_TAB
3319 AS2 (ld,%B0,%1) CR_TAB
3321 else if (GET_CODE (base) == POST_INC) /* (R++) */
3322 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
3323 AS2 (ld,%B0,%1) CR_TAB
3324 AS2 (ld,%C0,%1) CR_TAB
3326 else if (CONSTANT_ADDRESS_P (base))
3327 return *l=8, (AS2 (lds,%A0,%m1) CR_TAB
3328 AS2 (lds,%B0,%m1+1) CR_TAB
3329 AS2 (lds,%C0,%m1+2) CR_TAB
3330 AS2 (lds,%D0,%m1+3));
3332 fatal_insn ("unknown move insn:",insn);
3337 out_movsi_mr_r (rtx insn, rtx op[], int *l)
3341 rtx base = XEXP (dest, 0);
3342 int reg_base = true_regnum (base);
3343 int reg_src = true_regnum (src);
3349 if (CONSTANT_ADDRESS_P (base))
3350 return *l=8,(AS2 (sts,%m0,%A1) CR_TAB
3351 AS2 (sts,%m0+1,%B1) CR_TAB
3352 AS2 (sts,%m0+2,%C1) CR_TAB
3353 AS2 (sts,%m0+3,%D1));
3354 if (reg_base > 0) /* (r) */
3356 if (reg_base == REG_X) /* (R26) */
3358 if (reg_src == REG_X)
3360 /* "st X+,r26" is undefined */
3361 if (reg_unused_after (insn, base))
3362 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
3363 AS2 (st,X,r26) CR_TAB
3364 AS2 (adiw,r26,1) CR_TAB
3365 AS2 (st,X+,__tmp_reg__) CR_TAB
3366 AS2 (st,X+,r28) CR_TAB
3369 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
3370 AS2 (st,X,r26) CR_TAB
3371 AS2 (adiw,r26,1) CR_TAB
3372 AS2 (st,X+,__tmp_reg__) CR_TAB
3373 AS2 (st,X+,r28) CR_TAB
3374 AS2 (st,X,r29) CR_TAB
3377 else if (reg_base == reg_src + 2)
3379 if (reg_unused_after (insn, base))
3380 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
3381 AS2 (mov,__tmp_reg__,%D1) CR_TAB
3382 AS2 (st,%0+,%A1) CR_TAB
3383 AS2 (st,%0+,%B1) CR_TAB
3384 AS2 (st,%0+,__zero_reg__) CR_TAB
3385 AS2 (st,%0,__tmp_reg__) CR_TAB
3386 AS1 (clr,__zero_reg__));
3388 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
3389 AS2 (mov,__tmp_reg__,%D1) CR_TAB
3390 AS2 (st,%0+,%A1) CR_TAB
3391 AS2 (st,%0+,%B1) CR_TAB
3392 AS2 (st,%0+,__zero_reg__) CR_TAB
3393 AS2 (st,%0,__tmp_reg__) CR_TAB
3394 AS1 (clr,__zero_reg__) CR_TAB
3397 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
3398 AS2 (st,%0+,%B1) CR_TAB
3399 AS2 (st,%0+,%C1) CR_TAB
3400 AS2 (st,%0,%D1) CR_TAB
3404 return *l=4, (AS2 (st,%0,%A1) CR_TAB
3405 AS2 (std,%0+1,%B1) CR_TAB
3406 AS2 (std,%0+2,%C1) CR_TAB
3407 AS2 (std,%0+3,%D1));
3409 else if (GET_CODE (base) == PLUS) /* (R + i) */
3411 int disp = INTVAL (XEXP (base, 1));
3412 reg_base = REGNO (XEXP (base, 0));
3413 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
3415 if (reg_base != REG_Y)
3416 fatal_insn ("incorrect insn:",insn);
3418 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
3419 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
3420 AS2 (std,Y+60,%A1) CR_TAB
3421 AS2 (std,Y+61,%B1) CR_TAB
3422 AS2 (std,Y+62,%C1) CR_TAB
3423 AS2 (std,Y+63,%D1) CR_TAB
3424 AS2 (sbiw,r28,%o0-60));
3426 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
3427 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
3428 AS2 (st,Y,%A1) CR_TAB
3429 AS2 (std,Y+1,%B1) CR_TAB
3430 AS2 (std,Y+2,%C1) CR_TAB
3431 AS2 (std,Y+3,%D1) CR_TAB
3432 AS2 (subi,r28,lo8(%o0)) CR_TAB
3433 AS2 (sbci,r29,hi8(%o0)));
3435 if (reg_base == REG_X)
3438 if (reg_src == REG_X)
3441 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
3442 AS2 (mov,__zero_reg__,r27) CR_TAB
3443 AS2 (adiw,r26,%o0) CR_TAB
3444 AS2 (st,X+,__tmp_reg__) CR_TAB
3445 AS2 (st,X+,__zero_reg__) CR_TAB
3446 AS2 (st,X+,r28) CR_TAB
3447 AS2 (st,X,r29) CR_TAB
3448 AS1 (clr,__zero_reg__) CR_TAB
3449 AS2 (sbiw,r26,%o0+3));
3451 else if (reg_src == REG_X - 2)
3454 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
3455 AS2 (mov,__zero_reg__,r27) CR_TAB
3456 AS2 (adiw,r26,%o0) CR_TAB
3457 AS2 (st,X+,r24) CR_TAB
3458 AS2 (st,X+,r25) CR_TAB
3459 AS2 (st,X+,__tmp_reg__) CR_TAB
3460 AS2 (st,X,__zero_reg__) CR_TAB
3461 AS1 (clr,__zero_reg__) CR_TAB
3462 AS2 (sbiw,r26,%o0+3));