1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998-2013 Free Software Foundation, Inc.
3 Contributed by Denis Chertykov (chertykov@gmail.com)
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
27 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "conditions.h"
30 #include "insn-attr.h"
31 #include "insn-codes.h"
37 #include "c-family/c-common.h"
38 #include "diagnostic-core.h"
44 #include "langhooks.h"
47 #include "target-def.h"
51 /* Maximal allowed offset for an address in the LD command */
52 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
54 /* Return true if STR starts with PREFIX and false, otherwise. */
55 #define STR_PREFIX_P(STR,PREFIX) (0 == strncmp (STR, PREFIX, strlen (PREFIX)))
57 /* The 4 bits starting at SECTION_MACH_DEP are reserved to store the
58 address space where data is to be located.
59 As the only non-generic address spaces are all located in flash,
60 this can be used to test if data shall go into some .progmem* section.
61 This must be the rightmost field of machine dependent section flags. */
62 #define AVR_SECTION_PROGMEM (0xf * SECTION_MACH_DEP)
64 /* Similar 4-bit region for SYMBOL_REF_FLAGS. */
65 #define AVR_SYMBOL_FLAG_PROGMEM (0xf * SYMBOL_FLAG_MACH_DEP)
67 /* Similar 4-bit region in SYMBOL_REF_FLAGS:
68 Set address-space AS in SYMBOL_REF_FLAGS of SYM */
69 #define AVR_SYMBOL_SET_ADDR_SPACE(SYM,AS) \
71 SYMBOL_REF_FLAGS (sym) &= ~AVR_SYMBOL_FLAG_PROGMEM; \
72 SYMBOL_REF_FLAGS (sym) |= (AS) * SYMBOL_FLAG_MACH_DEP; \
75 /* Read address-space from SYMBOL_REF_FLAGS of SYM */
76 #define AVR_SYMBOL_GET_ADDR_SPACE(SYM) \
77 ((SYMBOL_REF_FLAGS (sym) & AVR_SYMBOL_FLAG_PROGMEM) \
78 / SYMBOL_FLAG_MACH_DEP)
80 /* Known address spaces. The order must be the same as in the respective
81 enum from avr.h (or designated initialized must be used). */
82 const avr_addrspace_t avr_addrspace
[ADDR_SPACE_COUNT
] =
84 { ADDR_SPACE_RAM
, 0, 2, "", 0, NULL
},
85 { ADDR_SPACE_FLASH
, 1, 2, "__flash", 0, ".progmem.data" },
86 { ADDR_SPACE_FLASH1
, 1, 2, "__flash1", 1, ".progmem1.data" },
87 { ADDR_SPACE_FLASH2
, 1, 2, "__flash2", 2, ".progmem2.data" },
88 { ADDR_SPACE_FLASH3
, 1, 2, "__flash3", 3, ".progmem3.data" },
89 { ADDR_SPACE_FLASH4
, 1, 2, "__flash4", 4, ".progmem4.data" },
90 { ADDR_SPACE_FLASH5
, 1, 2, "__flash5", 5, ".progmem5.data" },
91 { ADDR_SPACE_MEMX
, 1, 3, "__memx", 0, ".progmemx.data" },
95 /* Holding RAM addresses of some SFRs used by the compiler and that
96 are unique over all devices in an architecture like 'avr4'. */
100 /* SREG: The processor status */
103 /* RAMPX, RAMPY, RAMPD and CCP of XMEGA */
109 /* RAMPZ: The high byte of 24-bit address used with ELPM */
112 /* SP: The stack pointer and its low and high byte */
117 static avr_addr_t avr_addr
;
120 /* Prototypes for local helper functions. */
122 static const char* out_movqi_r_mr (rtx
, rtx
[], int*);
123 static const char* out_movhi_r_mr (rtx
, rtx
[], int*);
124 static const char* out_movsi_r_mr (rtx
, rtx
[], int*);
125 static const char* out_movqi_mr_r (rtx
, rtx
[], int*);
126 static const char* out_movhi_mr_r (rtx
, rtx
[], int*);
127 static const char* out_movsi_mr_r (rtx
, rtx
[], int*);
129 static int get_sequence_length (rtx insns
);
130 static int sequent_regs_live (void);
131 static const char *ptrreg_to_str (int);
132 static const char *cond_string (enum rtx_code
);
133 static int avr_num_arg_regs (enum machine_mode
, const_tree
);
134 static int avr_operand_rtx_cost (rtx
, enum machine_mode
, enum rtx_code
,
136 static void output_reload_in_const (rtx
*, rtx
, int*, bool);
137 static struct machine_function
* avr_init_machine_status (void);
140 /* Prototypes for hook implementors if needed before their implementation. */
142 static bool avr_rtx_costs (rtx
, int, int, int, int*, bool);
145 /* Allocate registers from r25 to r8 for parameters for function calls. */
146 #define FIRST_CUM_REG 26
148 /* Implicit target register of LPM instruction (R0) */
149 extern GTY(()) rtx lpm_reg_rtx
;
152 /* (Implicit) address register of LPM instruction (R31:R30 = Z) */
153 extern GTY(()) rtx lpm_addr_reg_rtx
;
154 rtx lpm_addr_reg_rtx
;
156 /* Temporary register RTX (reg:QI TMP_REGNO) */
157 extern GTY(()) rtx tmp_reg_rtx
;
160 /* Zeroed register RTX (reg:QI ZERO_REGNO) */
161 extern GTY(()) rtx zero_reg_rtx
;
164 /* RTXs for all general purpose registers as QImode */
165 extern GTY(()) rtx all_regs_rtx
[32];
166 rtx all_regs_rtx
[32];
168 /* SREG, the processor status */
169 extern GTY(()) rtx sreg_rtx
;
172 /* RAMP* special function registers */
173 extern GTY(()) rtx rampd_rtx
;
174 extern GTY(()) rtx rampx_rtx
;
175 extern GTY(()) rtx rampy_rtx
;
176 extern GTY(()) rtx rampz_rtx
;
182 /* RTX containing the strings "" and "e", respectively */
183 static GTY(()) rtx xstring_empty
;
184 static GTY(()) rtx xstring_e
;
186 /* Current architecture. */
187 const avr_arch_t
*avr_current_arch
;
189 /* Current device. */
190 const avr_mcu_t
*avr_current_device
;
192 /* Section to put switch tables in. */
193 static GTY(()) section
*progmem_swtable_section
;
195 /* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
196 or to address space __flash* or __memx. Only used as singletons inside
197 avr_asm_select_section, but it must not be local there because of GTY. */
198 static GTY(()) section
*progmem_section
[ADDR_SPACE_COUNT
];
200 /* Condition for insns/expanders from avr-dimode.md. */
201 bool avr_have_dimode
= true;
203 /* To track if code will use .bss and/or .data. */
204 bool avr_need_clear_bss_p
= false;
205 bool avr_need_copy_data_p
= false;
208 /* Transform UP into lowercase and write the result to LO.
209 You must provide enough space for LO. Return LO. */
212 avr_tolower (char *lo
, const char *up
)
216 for (; *up
; up
++, lo
++)
225 /* Custom function to count number of set bits. */
228 avr_popcount (unsigned int val
)
242 /* Constraint helper function. XVAL is a CONST_INT or a CONST_DOUBLE.
243 Return true if the least significant N_BYTES bytes of XVAL all have a
244 popcount in POP_MASK and false, otherwise. POP_MASK represents a subset
245 of integers which contains an integer N iff bit N of POP_MASK is set. */
248 avr_popcount_each_byte (rtx xval
, int n_bytes
, int pop_mask
)
252 enum machine_mode mode
= GET_MODE (xval
);
254 if (VOIDmode
== mode
)
257 for (i
= 0; i
< n_bytes
; i
++)
259 rtx xval8
= simplify_gen_subreg (QImode
, xval
, mode
, i
);
260 unsigned int val8
= UINTVAL (xval8
) & GET_MODE_MASK (QImode
);
262 if (0 == (pop_mask
& (1 << avr_popcount (val8
))))
270 /* Access some RTX as INT_MODE. If X is a CONST_FIXED we can get
271 the bit representation of X by "casting" it to CONST_INT. */
274 avr_to_int_mode (rtx x
)
276 enum machine_mode mode
= GET_MODE (x
);
278 return VOIDmode
== mode
280 : simplify_gen_subreg (int_mode_for_mode (mode
), x
, mode
, 0);
284 /* Implement `TARGET_OPTION_OVERRIDE'. */
287 avr_option_override (void)
289 flag_delete_null_pointer_checks
= 0;
291 /* caller-save.c looks for call-clobbered hard registers that are assigned
292 to pseudos that cross calls and tries so save-restore them around calls
293 in order to reduce the number of stack slots needed.
295 This might lead to situations where reload is no more able to cope
296 with the challenge of AVR's very few address registers and fails to
297 perform the requested spills. */
300 flag_caller_saves
= 0;
302 /* Unwind tables currently require a frame pointer for correctness,
303 see toplev.c:process_options(). */
305 if ((flag_unwind_tables
306 || flag_non_call_exceptions
307 || flag_asynchronous_unwind_tables
)
308 && !ACCUMULATE_OUTGOING_ARGS
)
310 flag_omit_frame_pointer
= 0;
313 avr_current_device
= &avr_mcu_types
[avr_mcu_index
];
314 avr_current_arch
= &avr_arch_types
[avr_current_device
->arch
];
316 /* RAM addresses of some SFRs common to all devices in respective arch. */
318 /* SREG: Status Register containing flags like I (global IRQ) */
319 avr_addr
.sreg
= 0x3F + avr_current_arch
->sfr_offset
;
321 /* RAMPZ: Address' high part when loading via ELPM */
322 avr_addr
.rampz
= 0x3B + avr_current_arch
->sfr_offset
;
324 avr_addr
.rampy
= 0x3A + avr_current_arch
->sfr_offset
;
325 avr_addr
.rampx
= 0x39 + avr_current_arch
->sfr_offset
;
326 avr_addr
.rampd
= 0x38 + avr_current_arch
->sfr_offset
;
327 avr_addr
.ccp
= 0x34 + avr_current_arch
->sfr_offset
;
329 /* SP: Stack Pointer (SP_H:SP_L) */
330 avr_addr
.sp_l
= 0x3D + avr_current_arch
->sfr_offset
;
331 avr_addr
.sp_h
= avr_addr
.sp_l
+ 1;
333 init_machine_status
= avr_init_machine_status
;
335 avr_log_set_avr_log();
338 /* Function to set up the backend function structure. */
340 static struct machine_function
*
341 avr_init_machine_status (void)
343 return ggc_alloc_cleared_machine_function ();
347 /* Implement `INIT_EXPANDERS'. */
348 /* The function works like a singleton. */
351 avr_init_expanders (void)
355 for (regno
= 0; regno
< 32; regno
++)
356 all_regs_rtx
[regno
] = gen_rtx_REG (QImode
, regno
);
358 lpm_reg_rtx
= all_regs_rtx
[LPM_REGNO
];
359 tmp_reg_rtx
= all_regs_rtx
[TMP_REGNO
];
360 zero_reg_rtx
= all_regs_rtx
[ZERO_REGNO
];
362 lpm_addr_reg_rtx
= gen_rtx_REG (HImode
, REG_Z
);
364 sreg_rtx
= gen_rtx_MEM (QImode
, GEN_INT (avr_addr
.sreg
));
365 rampd_rtx
= gen_rtx_MEM (QImode
, GEN_INT (avr_addr
.rampd
));
366 rampx_rtx
= gen_rtx_MEM (QImode
, GEN_INT (avr_addr
.rampx
));
367 rampy_rtx
= gen_rtx_MEM (QImode
, GEN_INT (avr_addr
.rampy
));
368 rampz_rtx
= gen_rtx_MEM (QImode
, GEN_INT (avr_addr
.rampz
));
370 xstring_empty
= gen_rtx_CONST_STRING (VOIDmode
, "");
371 xstring_e
= gen_rtx_CONST_STRING (VOIDmode
, "e");
375 /* Implement `REGNO_REG_CLASS'. */
376 /* Return register class for register R. */
379 avr_regno_reg_class (int r
)
381 static const enum reg_class reg_class_tab
[] =
385 NO_LD_REGS
, NO_LD_REGS
, NO_LD_REGS
,
386 NO_LD_REGS
, NO_LD_REGS
, NO_LD_REGS
, NO_LD_REGS
,
387 NO_LD_REGS
, NO_LD_REGS
, NO_LD_REGS
, NO_LD_REGS
,
388 NO_LD_REGS
, NO_LD_REGS
, NO_LD_REGS
, NO_LD_REGS
,
390 SIMPLE_LD_REGS
, SIMPLE_LD_REGS
, SIMPLE_LD_REGS
, SIMPLE_LD_REGS
,
391 SIMPLE_LD_REGS
, SIMPLE_LD_REGS
, SIMPLE_LD_REGS
, SIMPLE_LD_REGS
,
393 ADDW_REGS
, ADDW_REGS
,
395 POINTER_X_REGS
, POINTER_X_REGS
,
397 POINTER_Y_REGS
, POINTER_Y_REGS
,
399 POINTER_Z_REGS
, POINTER_Z_REGS
,
405 return reg_class_tab
[r
];
411 /* Implement `TARGET_SCALAR_MODE_SUPPORTED_P'. */
414 avr_scalar_mode_supported_p (enum machine_mode mode
)
416 if (ALL_FIXED_POINT_MODE_P (mode
))
422 return default_scalar_mode_supported_p (mode
);
426 /* Return TRUE if DECL is a VAR_DECL located in flash and FALSE, otherwise. */
429 avr_decl_flash_p (tree decl
)
431 if (TREE_CODE (decl
) != VAR_DECL
432 || TREE_TYPE (decl
) == error_mark_node
)
437 return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl
)));
441 /* Return TRUE if DECL is a VAR_DECL located in the 24-bit flash
442 address space and FALSE, otherwise. */
445 avr_decl_memx_p (tree decl
)
447 if (TREE_CODE (decl
) != VAR_DECL
448 || TREE_TYPE (decl
) == error_mark_node
)
453 return (ADDR_SPACE_MEMX
== TYPE_ADDR_SPACE (TREE_TYPE (decl
)));
457 /* Return TRUE if X is a MEM rtx located in flash and FALSE, otherwise. */
460 avr_mem_flash_p (rtx x
)
463 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x
)));
467 /* Return TRUE if X is a MEM rtx located in the 24-bit flash
468 address space and FALSE, otherwise. */
471 avr_mem_memx_p (rtx x
)
474 && ADDR_SPACE_MEMX
== MEM_ADDR_SPACE (x
));
478 /* A helper for the subsequent function attribute used to dig for
479 attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
482 avr_lookup_function_attribute1 (const_tree func
, const char *name
)
484 if (FUNCTION_DECL
== TREE_CODE (func
))
486 if (NULL_TREE
!= lookup_attribute (name
, DECL_ATTRIBUTES (func
)))
491 func
= TREE_TYPE (func
);
494 gcc_assert (TREE_CODE (func
) == FUNCTION_TYPE
495 || TREE_CODE (func
) == METHOD_TYPE
);
497 return NULL_TREE
!= lookup_attribute (name
, TYPE_ATTRIBUTES (func
));
500 /* Return nonzero if FUNC is a naked function. */
503 avr_naked_function_p (tree func
)
505 return avr_lookup_function_attribute1 (func
, "naked");
508 /* Return nonzero if FUNC is an interrupt function as specified
509 by the "interrupt" attribute. */
512 avr_interrupt_function_p (tree func
)
514 return avr_lookup_function_attribute1 (func
, "interrupt");
517 /* Return nonzero if FUNC is a signal function as specified
518 by the "signal" attribute. */
521 avr_signal_function_p (tree func
)
523 return avr_lookup_function_attribute1 (func
, "signal");
526 /* Return nonzero if FUNC is an OS_task function. */
529 avr_OS_task_function_p (tree func
)
531 return avr_lookup_function_attribute1 (func
, "OS_task");
534 /* Return nonzero if FUNC is an OS_main function. */
537 avr_OS_main_function_p (tree func
)
539 return avr_lookup_function_attribute1 (func
, "OS_main");
543 /* Implement `TARGET_SET_CURRENT_FUNCTION'. */
544 /* Sanity cheching for above function attributes. */
547 avr_set_current_function (tree decl
)
552 if (decl
== NULL_TREE
553 || current_function_decl
== NULL_TREE
554 || current_function_decl
== error_mark_node
556 || cfun
->machine
->attributes_checked_p
)
559 loc
= DECL_SOURCE_LOCATION (decl
);
561 cfun
->machine
->is_naked
= avr_naked_function_p (decl
);
562 cfun
->machine
->is_signal
= avr_signal_function_p (decl
);
563 cfun
->machine
->is_interrupt
= avr_interrupt_function_p (decl
);
564 cfun
->machine
->is_OS_task
= avr_OS_task_function_p (decl
);
565 cfun
->machine
->is_OS_main
= avr_OS_main_function_p (decl
);
567 isr
= cfun
->machine
->is_interrupt
? "interrupt" : "signal";
569 /* Too much attributes make no sense as they request conflicting features. */
571 if (cfun
->machine
->is_OS_task
+ cfun
->machine
->is_OS_main
572 + (cfun
->machine
->is_signal
|| cfun
->machine
->is_interrupt
) > 1)
573 error_at (loc
, "function attributes %qs, %qs and %qs are mutually"
574 " exclusive", "OS_task", "OS_main", isr
);
576 /* 'naked' will hide effects of 'OS_task' and 'OS_main'. */
578 if (cfun
->machine
->is_naked
579 && (cfun
->machine
->is_OS_task
|| cfun
->machine
->is_OS_main
))
580 warning_at (loc
, OPT_Wattributes
, "function attributes %qs and %qs have"
581 " no effect on %qs function", "OS_task", "OS_main", "naked");
583 if (cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
585 tree args
= TYPE_ARG_TYPES (TREE_TYPE (decl
));
586 tree ret
= TREE_TYPE (TREE_TYPE (decl
));
589 name
= DECL_ASSEMBLER_NAME_SET_P (decl
)
590 ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
))
591 : IDENTIFIER_POINTER (DECL_NAME (decl
));
593 /* Skip a leading '*' that might still prefix the assembler name,
594 e.g. in non-LTO runs. */
596 name
= default_strip_name_encoding (name
);
598 /* Silently ignore 'signal' if 'interrupt' is present. AVR-LibC startet
599 using this when it switched from SIGNAL and INTERRUPT to ISR. */
601 if (cfun
->machine
->is_interrupt
)
602 cfun
->machine
->is_signal
= 0;
604 /* Interrupt handlers must be void __vector (void) functions. */
606 if (args
&& TREE_CODE (TREE_VALUE (args
)) != VOID_TYPE
)
607 error_at (loc
, "%qs function cannot have arguments", isr
);
609 if (TREE_CODE (ret
) != VOID_TYPE
)
610 error_at (loc
, "%qs function cannot return a value", isr
);
612 /* If the function has the 'signal' or 'interrupt' attribute, ensure
613 that the name of the function is "__vector_NN" so as to catch
614 when the user misspells the vector name. */
616 if (!STR_PREFIX_P (name
, "__vector"))
617 warning_at (loc
, 0, "%qs appears to be a misspelled %s handler",
621 /* Don't print the above diagnostics more than once. */
623 cfun
->machine
->attributes_checked_p
= 1;
627 /* Implement `ACCUMULATE_OUTGOING_ARGS'. */
630 avr_accumulate_outgoing_args (void)
633 return TARGET_ACCUMULATE_OUTGOING_ARGS
;
635 /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
636 what offset is correct. In some cases it is relative to
637 virtual_outgoing_args_rtx and in others it is relative to
638 virtual_stack_vars_rtx. For example code see
639 gcc.c-torture/execute/built-in-setjmp.c
640 gcc.c-torture/execute/builtins/sprintf-chk.c */
642 return (TARGET_ACCUMULATE_OUTGOING_ARGS
643 && !(cfun
->calls_setjmp
644 || cfun
->has_nonlocal_label
));
648 /* Report contribution of accumulated outgoing arguments to stack size. */
651 avr_outgoing_args_size (void)
653 return ACCUMULATE_OUTGOING_ARGS
? crtl
->outgoing_args_size
: 0;
657 /* Implement `STARTING_FRAME_OFFSET'. */
658 /* This is the offset from the frame pointer register to the first stack slot
659 that contains a variable living in the frame. */
662 avr_starting_frame_offset (void)
664 return 1 + avr_outgoing_args_size ();
668 /* Return the number of hard registers to push/pop in the prologue/epilogue
669 of the current function, and optionally store these registers in SET. */
672 avr_regs_to_save (HARD_REG_SET
*set
)
675 int int_or_sig_p
= cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
;
678 CLEAR_HARD_REG_SET (*set
);
681 /* No need to save any registers if the function never returns or
682 has the "OS_task" or "OS_main" attribute. */
684 if (TREE_THIS_VOLATILE (current_function_decl
)
685 || cfun
->machine
->is_OS_task
686 || cfun
->machine
->is_OS_main
)
689 for (reg
= 0; reg
< 32; reg
++)
691 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
692 any global register variables. */
697 if ((int_or_sig_p
&& !crtl
->is_leaf
&& call_used_regs
[reg
])
698 || (df_regs_ever_live_p (reg
)
699 && (int_or_sig_p
|| !call_used_regs
[reg
])
700 /* Don't record frame pointer registers here. They are treated
701 indivitually in prologue. */
702 && !(frame_pointer_needed
703 && (reg
== REG_Y
|| reg
== (REG_Y
+1)))))
706 SET_HARD_REG_BIT (*set
, reg
);
714 /* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
717 avr_allocate_stack_slots_for_args (void)
719 return !cfun
->machine
->is_naked
;
723 /* Return true if register FROM can be eliminated via register TO. */
726 avr_can_eliminate (const int from
, const int to
)
728 return ((from
== ARG_POINTER_REGNUM
&& to
== FRAME_POINTER_REGNUM
)
729 || (frame_pointer_needed
&& to
== FRAME_POINTER_REGNUM
)
730 || ((from
== FRAME_POINTER_REGNUM
731 || from
== FRAME_POINTER_REGNUM
+ 1)
732 && !frame_pointer_needed
));
736 /* Implement `TARGET_WARN_FUNC_RETURN'. */
739 avr_warn_func_return (tree decl
)
741 /* Naked functions are implemented entirely in assembly, including the
742 return sequence, so suppress warnings about this. */
744 return !avr_naked_function_p (decl
);
747 /* Compute offset between arg_pointer and frame_pointer. */
750 avr_initial_elimination_offset (int from
, int to
)
752 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
756 int offset
= frame_pointer_needed
? 2 : 0;
757 int avr_pc_size
= AVR_HAVE_EIJMP_EICALL
? 3 : 2;
759 offset
+= avr_regs_to_save (NULL
);
760 return (get_frame_size () + avr_outgoing_args_size()
761 + avr_pc_size
+ 1 + offset
);
766 /* Helper for the function below. */
769 avr_adjust_type_node (tree
*node
, enum machine_mode mode
, int sat_p
)
771 *node
= make_node (FIXED_POINT_TYPE
);
772 TYPE_SATURATING (*node
) = sat_p
;
773 TYPE_UNSIGNED (*node
) = UNSIGNED_FIXED_POINT_MODE_P (mode
);
774 TYPE_IBIT (*node
) = GET_MODE_IBIT (mode
);
775 TYPE_FBIT (*node
) = GET_MODE_FBIT (mode
);
776 TYPE_PRECISION (*node
) = GET_MODE_BITSIZE (mode
);
777 TYPE_ALIGN (*node
) = 8;
778 SET_TYPE_MODE (*node
, mode
);
784 /* Implement `TARGET_BUILD_BUILTIN_VA_LIST'. */
787 avr_build_builtin_va_list (void)
789 /* avr-modes.def adjusts [U]TA to be 64-bit modes with 48 fractional bits.
790 This is more appropriate for the 8-bit machine AVR than 128-bit modes.
791 The ADJUST_IBIT/FBIT are handled in toplev:init_adjust_machine_modes()
792 which is auto-generated by genmodes, but the compiler assigns [U]DAmode
793 to the long long accum modes instead of the desired [U]TAmode.
795 Fix this now, right after node setup in tree.c:build_common_tree_nodes().
796 This must run before c-cppbuiltin.c:builtin_define_fixed_point_constants()
797 which built-in defines macros like __ULLACCUM_FBIT__ that are used by
798 libgcc to detect IBIT and FBIT. */
800 avr_adjust_type_node (&ta_type_node
, TAmode
, 0);
801 avr_adjust_type_node (&uta_type_node
, UTAmode
, 0);
802 avr_adjust_type_node (&sat_ta_type_node
, TAmode
, 1);
803 avr_adjust_type_node (&sat_uta_type_node
, UTAmode
, 1);
805 unsigned_long_long_accum_type_node
= uta_type_node
;
806 long_long_accum_type_node
= ta_type_node
;
807 sat_unsigned_long_long_accum_type_node
= sat_uta_type_node
;
808 sat_long_long_accum_type_node
= sat_ta_type_node
;
810 /* Dispatch to the default handler. */
812 return std_build_builtin_va_list ();
816 /* Implement `TARGET_BUILTIN_SETJMP_FRAME_VALUE'. */
817 /* Actual start of frame is virtual_stack_vars_rtx this is offset from
818 frame pointer by +STARTING_FRAME_OFFSET.
819 Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET
820 avoids creating add/sub of offset in nonlocal goto and setjmp. */
823 avr_builtin_setjmp_frame_value (void)
825 rtx xval
= gen_reg_rtx (Pmode
);
826 emit_insn (gen_subhi3 (xval
, virtual_stack_vars_rtx
,
827 gen_int_mode (STARTING_FRAME_OFFSET
, Pmode
)));
832 /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC).
833 This is return address of function. */
836 avr_return_addr_rtx (int count
, rtx tem
)
840 /* Can only return this function's return address. Others not supported. */
846 r
= gen_rtx_SYMBOL_REF (Pmode
, ".L__stack_usage+2");
847 warning (0, "%<builtin_return_address%> contains only 2 bytes"
851 r
= gen_rtx_SYMBOL_REF (Pmode
, ".L__stack_usage+1");
853 r
= gen_rtx_PLUS (Pmode
, tem
, r
);
854 r
= gen_frame_mem (Pmode
, memory_address (Pmode
, r
));
855 r
= gen_rtx_ROTATE (HImode
, r
, GEN_INT (8));
859 /* Return 1 if the function epilogue is just a single "ret". */
862 avr_simple_epilogue (void)
864 return (! frame_pointer_needed
865 && get_frame_size () == 0
866 && avr_outgoing_args_size() == 0
867 && avr_regs_to_save (NULL
) == 0
868 && ! cfun
->machine
->is_interrupt
869 && ! cfun
->machine
->is_signal
870 && ! cfun
->machine
->is_naked
871 && ! TREE_THIS_VOLATILE (current_function_decl
));
874 /* This function checks sequence of live registers. */
877 sequent_regs_live (void)
883 for (reg
= 0; reg
< 18; ++reg
)
887 /* Don't recognize sequences that contain global register
896 if (!call_used_regs
[reg
])
898 if (df_regs_ever_live_p (reg
))
908 if (!frame_pointer_needed
)
910 if (df_regs_ever_live_p (REG_Y
))
918 if (df_regs_ever_live_p (REG_Y
+1))
931 return (cur_seq
== live_seq
) ? live_seq
: 0;
934 /* Obtain the length sequence of insns. */
937 get_sequence_length (rtx insns
)
942 for (insn
= insns
, length
= 0; insn
; insn
= NEXT_INSN (insn
))
943 length
+= get_attr_length (insn
);
949 /* Implement `INCOMING_RETURN_ADDR_RTX'. */
952 avr_incoming_return_addr_rtx (void)
954 /* The return address is at the top of the stack. Note that the push
955 was via post-decrement, which means the actual address is off by one. */
956 return gen_frame_mem (HImode
, plus_constant (Pmode
, stack_pointer_rtx
, 1));
959 /* Helper for expand_prologue. Emit a push of a byte register. */
962 emit_push_byte (unsigned regno
, bool frame_related_p
)
966 mem
= gen_rtx_POST_DEC (HImode
, stack_pointer_rtx
);
967 mem
= gen_frame_mem (QImode
, mem
);
968 reg
= gen_rtx_REG (QImode
, regno
);
970 insn
= emit_insn (gen_rtx_SET (VOIDmode
, mem
, reg
));
972 RTX_FRAME_RELATED_P (insn
) = 1;
974 cfun
->machine
->stack_usage
++;
978 /* Helper for expand_prologue. Emit a push of a SFR via tmp_reg.
979 SFR is a MEM representing the memory location of the SFR.
980 If CLR_P then clear the SFR after the push using zero_reg. */
983 emit_push_sfr (rtx sfr
, bool frame_related_p
, bool clr_p
)
987 gcc_assert (MEM_P (sfr
));
989 /* IN __tmp_reg__, IO(SFR) */
990 insn
= emit_move_insn (tmp_reg_rtx
, sfr
);
992 RTX_FRAME_RELATED_P (insn
) = 1;
994 /* PUSH __tmp_reg__ */
995 emit_push_byte (TMP_REGNO
, frame_related_p
);
999 /* OUT IO(SFR), __zero_reg__ */
1000 insn
= emit_move_insn (sfr
, const0_rtx
);
1001 if (frame_related_p
)
1002 RTX_FRAME_RELATED_P (insn
) = 1;
1007 avr_prologue_setup_frame (HOST_WIDE_INT size
, HARD_REG_SET set
)
1010 bool isr_p
= cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
;
1011 int live_seq
= sequent_regs_live ();
1013 HOST_WIDE_INT size_max
1014 = (HOST_WIDE_INT
) GET_MODE_MASK (AVR_HAVE_8BIT_SP
? QImode
: Pmode
);
1016 bool minimize
= (TARGET_CALL_PROLOGUES
1020 && !cfun
->machine
->is_OS_task
1021 && !cfun
->machine
->is_OS_main
);
1024 && (frame_pointer_needed
1025 || avr_outgoing_args_size() > 8
1026 || (AVR_2_BYTE_PC
&& live_seq
> 6)
1030 int first_reg
, reg
, offset
;
1032 emit_move_insn (gen_rtx_REG (HImode
, REG_X
),
1033 gen_int_mode (size
, HImode
));
1035 pattern
= gen_call_prologue_saves (gen_int_mode (live_seq
, HImode
),
1036 gen_int_mode (live_seq
+size
, HImode
));
1037 insn
= emit_insn (pattern
);
1038 RTX_FRAME_RELATED_P (insn
) = 1;
1040 /* Describe the effect of the unspec_volatile call to prologue_saves.
1041 Note that this formulation assumes that add_reg_note pushes the
1042 notes to the front. Thus we build them in the reverse order of
1043 how we want dwarf2out to process them. */
1045 /* The function does always set frame_pointer_rtx, but whether that
1046 is going to be permanent in the function is frame_pointer_needed. */
1048 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
1049 gen_rtx_SET (VOIDmode
, (frame_pointer_needed
1051 : stack_pointer_rtx
),
1052 plus_constant (Pmode
, stack_pointer_rtx
,
1053 -(size
+ live_seq
))));
1055 /* Note that live_seq always contains r28+r29, but the other
1056 registers to be saved are all below 18. */
1058 first_reg
= 18 - (live_seq
- 2);
1060 for (reg
= 29, offset
= -live_seq
+ 1;
1062 reg
= (reg
== 28 ? 17 : reg
- 1), ++offset
)
1066 m
= gen_rtx_MEM (QImode
, plus_constant (Pmode
, stack_pointer_rtx
,
1068 r
= gen_rtx_REG (QImode
, reg
);
1069 add_reg_note (insn
, REG_CFA_OFFSET
, gen_rtx_SET (VOIDmode
, m
, r
));
1072 cfun
->machine
->stack_usage
+= size
+ live_seq
;
1074 else /* !minimize */
1078 for (reg
= 0; reg
< 32; ++reg
)
1079 if (TEST_HARD_REG_BIT (set
, reg
))
1080 emit_push_byte (reg
, true);
1082 if (frame_pointer_needed
1083 && (!(cfun
->machine
->is_OS_task
|| cfun
->machine
->is_OS_main
)))
1085 /* Push frame pointer. Always be consistent about the
1086 ordering of pushes -- epilogue_restores expects the
1087 register pair to be pushed low byte first. */
1089 emit_push_byte (REG_Y
, true);
1090 emit_push_byte (REG_Y
+ 1, true);
1093 if (frame_pointer_needed
1096 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
1097 RTX_FRAME_RELATED_P (insn
) = 1;
1102 /* Creating a frame can be done by direct manipulation of the
1103 stack or via the frame pointer. These two methods are:
1110 the optimum method depends on function type, stack and
1111 frame size. To avoid a complex logic, both methods are
1112 tested and shortest is selected.
1114 There is also the case where SIZE != 0 and no frame pointer is
1115 needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
1116 In that case, insn (*) is not needed in that case.
1117 We use the X register as scratch. This is save because in X
1119 In an interrupt routine, the case of SIZE != 0 together with
1120 !frame_pointer_needed can only occur if the function is not a
1121 leaf function and thus X has already been saved. */
1124 HOST_WIDE_INT size_cfa
= size
, neg_size
;
1125 rtx fp_plus_insns
, fp
, my_fp
;
1127 gcc_assert (frame_pointer_needed
1131 fp
= my_fp
= (frame_pointer_needed
1133 : gen_rtx_REG (Pmode
, REG_X
));
1135 if (AVR_HAVE_8BIT_SP
)
1137 /* The high byte (r29) does not change:
1138 Prefer SUBI (1 cycle) over SBIW (2 cycles, same size). */
1140 my_fp
= all_regs_rtx
[FRAME_POINTER_REGNUM
];
1143 /* Cut down size and avoid size = 0 so that we don't run
1144 into ICE like PR52488 in the remainder. */
1146 if (size
> size_max
)
1148 /* Don't error so that insane code from newlib still compiles
1149 and does not break building newlib. As PR51345 is implemented
1150 now, there are multilib variants with -msp8.
1152 If user wants sanity checks he can use -Wstack-usage=
1155 For CFA we emit the original, non-saturated size so that
1156 the generic machinery is aware of the real stack usage and
1157 will print the above diagnostic as expected. */
1162 size
= trunc_int_for_mode (size
, GET_MODE (my_fp
));
1163 neg_size
= trunc_int_for_mode (-size
, GET_MODE (my_fp
));
1165 /************ Method 1: Adjust frame pointer ************/
1169 /* Normally, the dwarf2out frame-related-expr interpreter does
1170 not expect to have the CFA change once the frame pointer is
1171 set up. Thus, we avoid marking the move insn below and
1172 instead indicate that the entire operation is complete after
1173 the frame pointer subtraction is done. */
1175 insn
= emit_move_insn (fp
, stack_pointer_rtx
);
1176 if (frame_pointer_needed
)
1178 RTX_FRAME_RELATED_P (insn
) = 1;
1179 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
1180 gen_rtx_SET (VOIDmode
, fp
, stack_pointer_rtx
));
1183 insn
= emit_move_insn (my_fp
, plus_constant (GET_MODE (my_fp
),
1186 if (frame_pointer_needed
)
1188 RTX_FRAME_RELATED_P (insn
) = 1;
1189 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
1190 gen_rtx_SET (VOIDmode
, fp
,
1191 plus_constant (Pmode
, fp
,
1195 /* Copy to stack pointer. Note that since we've already
1196 changed the CFA to the frame pointer this operation
1197 need not be annotated if frame pointer is needed.
1198 Always move through unspec, see PR50063.
1199 For meaning of irq_state see movhi_sp_r insn. */
1201 if (cfun
->machine
->is_interrupt
)
1204 if (TARGET_NO_INTERRUPTS
1205 || cfun
->machine
->is_signal
1206 || cfun
->machine
->is_OS_main
)
1209 if (AVR_HAVE_8BIT_SP
)
1212 insn
= emit_insn (gen_movhi_sp_r (stack_pointer_rtx
,
1213 fp
, GEN_INT (irq_state
)));
1214 if (!frame_pointer_needed
)
1216 RTX_FRAME_RELATED_P (insn
) = 1;
1217 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
1218 gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
1219 plus_constant (Pmode
,
1224 fp_plus_insns
= get_insns ();
1227 /************ Method 2: Adjust Stack pointer ************/
1229 /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
1230 can only handle specific offsets. */
1232 if (avr_sp_immediate_operand (gen_int_mode (-size
, HImode
), HImode
))
1238 insn
= emit_move_insn (stack_pointer_rtx
,
1239 plus_constant (Pmode
, stack_pointer_rtx
,
1241 RTX_FRAME_RELATED_P (insn
) = 1;
1242 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
1243 gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
1244 plus_constant (Pmode
,
1247 if (frame_pointer_needed
)
1249 insn
= emit_move_insn (fp
, stack_pointer_rtx
);
1250 RTX_FRAME_RELATED_P (insn
) = 1;
1253 sp_plus_insns
= get_insns ();
1256 /************ Use shortest method ************/
1258 emit_insn (get_sequence_length (sp_plus_insns
)
1259 < get_sequence_length (fp_plus_insns
)
1265 emit_insn (fp_plus_insns
);
1268 cfun
->machine
->stack_usage
+= size_cfa
;
1269 } /* !minimize && size != 0 */
1274 /* Output function prologue. */
1277 avr_expand_prologue (void)
1282 size
= get_frame_size() + avr_outgoing_args_size();
1284 cfun
->machine
->stack_usage
= 0;
1286 /* Prologue: naked. */
1287 if (cfun
->machine
->is_naked
)
1292 avr_regs_to_save (&set
);
1294 if (cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
1296 /* Enable interrupts. */
1297 if (cfun
->machine
->is_interrupt
)
1298 emit_insn (gen_enable_interrupt ());
1300 /* Push zero reg. */
1301 emit_push_byte (ZERO_REGNO
, true);
1304 emit_push_byte (TMP_REGNO
, true);
1307 /* ??? There's no dwarf2 column reserved for SREG. */
1308 emit_push_sfr (sreg_rtx
, false, false /* clr */);
1310 /* Clear zero reg. */
1311 emit_move_insn (zero_reg_rtx
, const0_rtx
);
1313 /* Prevent any attempt to delete the setting of ZERO_REG! */
1314 emit_use (zero_reg_rtx
);
1316 /* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
1317 ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z. */
1320 emit_push_sfr (rampd_rtx
, false /* frame-related */, true /* clr */);
1323 && TEST_HARD_REG_BIT (set
, REG_X
)
1324 && TEST_HARD_REG_BIT (set
, REG_X
+ 1))
1326 emit_push_sfr (rampx_rtx
, false /* frame-related */, true /* clr */);
1330 && (frame_pointer_needed
1331 || (TEST_HARD_REG_BIT (set
, REG_Y
)
1332 && TEST_HARD_REG_BIT (set
, REG_Y
+ 1))))
1334 emit_push_sfr (rampy_rtx
, false /* frame-related */, true /* clr */);
1338 && TEST_HARD_REG_BIT (set
, REG_Z
)
1339 && TEST_HARD_REG_BIT (set
, REG_Z
+ 1))
1341 emit_push_sfr (rampz_rtx
, false /* frame-related */, AVR_HAVE_RAMPD
);
1343 } /* is_interrupt is_signal */
1345 avr_prologue_setup_frame (size
, set
);
1347 if (flag_stack_usage_info
)
1348 current_function_static_stack_size
= cfun
->machine
->stack_usage
;
1352 /* Implement `TARGET_ASM_FUNCTION_END_PROLOGUE'. */
1353 /* Output summary at end of function prologue. */
1356 avr_asm_function_end_prologue (FILE *file
)
1358 if (cfun
->machine
->is_naked
)
1360 fputs ("/* prologue: naked */\n", file
);
1364 if (cfun
->machine
->is_interrupt
)
1366 fputs ("/* prologue: Interrupt */\n", file
);
1368 else if (cfun
->machine
->is_signal
)
1370 fputs ("/* prologue: Signal */\n", file
);
1373 fputs ("/* prologue: function */\n", file
);
1376 if (ACCUMULATE_OUTGOING_ARGS
)
1377 fprintf (file
, "/* outgoing args size = %d */\n",
1378 avr_outgoing_args_size());
1380 fprintf (file
, "/* frame size = " HOST_WIDE_INT_PRINT_DEC
" */\n",
1382 fprintf (file
, "/* stack size = %d */\n",
1383 cfun
->machine
->stack_usage
);
1384 /* Create symbol stack offset here so all functions have it. Add 1 to stack
1385 usage for offset so that SP + .L__stack_offset = return address. */
1386 fprintf (file
, ".L__stack_usage = %d\n", cfun
->machine
->stack_usage
);
1390 /* Implement `EPILOGUE_USES'. */
1393 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED
)
1395 if (reload_completed
1397 && (cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
))
1402 /* Helper for avr_expand_epilogue. Emit a pop of a byte register. */
1405 emit_pop_byte (unsigned regno
)
1409 mem
= gen_rtx_PRE_INC (HImode
, stack_pointer_rtx
);
1410 mem
= gen_frame_mem (QImode
, mem
);
1411 reg
= gen_rtx_REG (QImode
, regno
);
1413 emit_insn (gen_rtx_SET (VOIDmode
, reg
, mem
));
1416 /* Output RTL epilogue. */
1419 avr_expand_epilogue (bool sibcall_p
)
1426 bool isr_p
= cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
;
1428 size
= get_frame_size() + avr_outgoing_args_size();
1430 /* epilogue: naked */
1431 if (cfun
->machine
->is_naked
)
1433 gcc_assert (!sibcall_p
);
1435 emit_jump_insn (gen_return ());
1439 avr_regs_to_save (&set
);
1440 live_seq
= sequent_regs_live ();
1442 minimize
= (TARGET_CALL_PROLOGUES
1445 && !cfun
->machine
->is_OS_task
1446 && !cfun
->machine
->is_OS_main
);
1450 || frame_pointer_needed
1453 /* Get rid of frame. */
1455 if (!frame_pointer_needed
)
1457 emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
1462 emit_move_insn (frame_pointer_rtx
,
1463 plus_constant (Pmode
, frame_pointer_rtx
, size
));
1466 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq
, HImode
)));
1472 /* Try two methods to adjust stack and select shortest. */
1477 HOST_WIDE_INT size_max
;
1479 gcc_assert (frame_pointer_needed
1483 fp
= my_fp
= (frame_pointer_needed
1485 : gen_rtx_REG (Pmode
, REG_X
));
1487 if (AVR_HAVE_8BIT_SP
)
1489 /* The high byte (r29) does not change:
1490 Prefer SUBI (1 cycle) over SBIW (2 cycles). */
1492 my_fp
= all_regs_rtx
[FRAME_POINTER_REGNUM
];
1495 /* For rationale see comment in prologue generation. */
1497 size_max
= (HOST_WIDE_INT
) GET_MODE_MASK (GET_MODE (my_fp
));
1498 if (size
> size_max
)
1500 size
= trunc_int_for_mode (size
, GET_MODE (my_fp
));
1502 /********** Method 1: Adjust fp register **********/
1506 if (!frame_pointer_needed
)
1507 emit_move_insn (fp
, stack_pointer_rtx
);
1509 emit_move_insn (my_fp
, plus_constant (GET_MODE (my_fp
), my_fp
, size
));
1511 /* Copy to stack pointer. */
1513 if (TARGET_NO_INTERRUPTS
)
1516 if (AVR_HAVE_8BIT_SP
)
1519 emit_insn (gen_movhi_sp_r (stack_pointer_rtx
, fp
,
1520 GEN_INT (irq_state
)));
1522 fp_plus_insns
= get_insns ();
1525 /********** Method 2: Adjust Stack pointer **********/
1527 if (avr_sp_immediate_operand (gen_int_mode (size
, HImode
), HImode
))
1533 emit_move_insn (stack_pointer_rtx
,
1534 plus_constant (Pmode
, stack_pointer_rtx
, size
));
1536 sp_plus_insns
= get_insns ();
1539 /************ Use shortest method ************/
1541 emit_insn (get_sequence_length (sp_plus_insns
)
1542 < get_sequence_length (fp_plus_insns
)
1547 emit_insn (fp_plus_insns
);
1550 if (frame_pointer_needed
1551 && !(cfun
->machine
->is_OS_task
|| cfun
->machine
->is_OS_main
))
1553 /* Restore previous frame_pointer. See avr_expand_prologue for
1554 rationale for not using pophi. */
1556 emit_pop_byte (REG_Y
+ 1);
1557 emit_pop_byte (REG_Y
);
1560 /* Restore used registers. */
1562 for (reg
= 31; reg
>= 0; --reg
)
1563 if (TEST_HARD_REG_BIT (set
, reg
))
1564 emit_pop_byte (reg
);
1568 /* Restore RAMPZ/Y/X/D using tmp_reg as scratch.
1569 The conditions to restore them must be tha same as in prologue. */
1572 && TEST_HARD_REG_BIT (set
, REG_Z
)
1573 && TEST_HARD_REG_BIT (set
, REG_Z
+ 1))
1575 emit_pop_byte (TMP_REGNO
);
1576 emit_move_insn (rampz_rtx
, tmp_reg_rtx
);
1580 && (frame_pointer_needed
1581 || (TEST_HARD_REG_BIT (set
, REG_Y
)
1582 && TEST_HARD_REG_BIT (set
, REG_Y
+ 1))))
1584 emit_pop_byte (TMP_REGNO
);
1585 emit_move_insn (rampy_rtx
, tmp_reg_rtx
);
1589 && TEST_HARD_REG_BIT (set
, REG_X
)
1590 && TEST_HARD_REG_BIT (set
, REG_X
+ 1))
1592 emit_pop_byte (TMP_REGNO
);
1593 emit_move_insn (rampx_rtx
, tmp_reg_rtx
);
1598 emit_pop_byte (TMP_REGNO
);
1599 emit_move_insn (rampd_rtx
, tmp_reg_rtx
);
1602 /* Restore SREG using tmp_reg as scratch. */
1604 emit_pop_byte (TMP_REGNO
);
1605 emit_move_insn (sreg_rtx
, tmp_reg_rtx
);
1607 /* Restore tmp REG. */
1608 emit_pop_byte (TMP_REGNO
);
1610 /* Restore zero REG. */
1611 emit_pop_byte (ZERO_REGNO
);
1615 emit_jump_insn (gen_return ());
1619 /* Implement `TARGET_ASM_FUNCTION_BEGIN_EPILOGUE'. */
1622 avr_asm_function_begin_epilogue (FILE *file
)
1624 fprintf (file
, "/* epilogue start */\n");
1628 /* Implement `TARGET_CANNOT_MODITY_JUMPS_P'. */
1631 avr_cannot_modify_jumps_p (void)
1634 /* Naked Functions must not have any instructions after
1635 their epilogue, see PR42240 */
1637 if (reload_completed
1639 && cfun
->machine
->is_naked
)
1648 /* Implement `TARGET_MODE_DEPENDENT_ADDRESS_P'. */
1651 avr_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED
, addr_space_t as
)
1653 /* FIXME: Non-generic addresses are not mode-dependent in themselves.
1654 This hook just serves to hack around PR rtl-optimization/52543 by
1655 claiming that non-generic addresses were mode-dependent so that
1656 lower-subreg.c will skip these addresses. lower-subreg.c sets up fake
1657 RTXes to probe SET and MEM costs and assumes that MEM is always in the
1658 generic address space which is not true. */
1660 return !ADDR_SPACE_GENERIC_P (as
);
1664 /* Helper function for `avr_legitimate_address_p'. */
1667 avr_reg_ok_for_addr_p (rtx reg
, addr_space_t as
,
1668 RTX_CODE outer_code
, bool strict
)
1671 && (avr_regno_mode_code_ok_for_base_p (REGNO (reg
), QImode
,
1672 as
, outer_code
, UNKNOWN
)
1674 && REGNO (reg
) >= FIRST_PSEUDO_REGISTER
)));
1678 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
1679 machine for a memory operand of mode MODE. */
1682 avr_legitimate_address_p (enum machine_mode mode
, rtx x
, bool strict
)
1684 bool ok
= CONSTANT_ADDRESS_P (x
);
1686 switch (GET_CODE (x
))
1689 ok
= avr_reg_ok_for_addr_p (x
, ADDR_SPACE_GENERIC
,
1693 && GET_MODE_SIZE (mode
) > 4
1694 && REG_X
== REGNO (x
))
1702 ok
= avr_reg_ok_for_addr_p (XEXP (x
, 0), ADDR_SPACE_GENERIC
,
1703 GET_CODE (x
), strict
);
1708 rtx reg
= XEXP (x
, 0);
1709 rtx op1
= XEXP (x
, 1);
1712 && CONST_INT_P (op1
)
1713 && INTVAL (op1
) >= 0)
1715 bool fit
= IN_RANGE (INTVAL (op1
), 0, MAX_LD_OFFSET (mode
));
1720 || avr_reg_ok_for_addr_p (reg
, ADDR_SPACE_GENERIC
,
1723 if (reg
== frame_pointer_rtx
1724 || reg
== arg_pointer_rtx
)
1729 else if (frame_pointer_needed
1730 && reg
== frame_pointer_rtx
)
1742 if (avr_log
.legitimate_address_p
)
1744 avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
1745 "reload_completed=%d reload_in_progress=%d %s:",
1746 ok
, mode
, strict
, reload_completed
, reload_in_progress
,
1747 reg_renumber
? "(reg_renumber)" : "");
1749 if (GET_CODE (x
) == PLUS
1750 && REG_P (XEXP (x
, 0))
1751 && CONST_INT_P (XEXP (x
, 1))
1752 && IN_RANGE (INTVAL (XEXP (x
, 1)), 0, MAX_LD_OFFSET (mode
))
1755 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x
, 0)),
1756 true_regnum (XEXP (x
, 0)));
1759 avr_edump ("\n%r\n", x
);
1766 /* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
1767 now only a helper for avr_addr_space_legitimize_address. */
1768 /* Attempts to replace X with a valid
1769 memory address for an operand of mode MODE */
1772 avr_legitimize_address (rtx x
, rtx oldx
, enum machine_mode mode
)
1774 bool big_offset_p
= false;
1778 if (GET_CODE (oldx
) == PLUS
1779 && REG_P (XEXP (oldx
, 0)))
1781 if (REG_P (XEXP (oldx
, 1)))
1782 x
= force_reg (GET_MODE (oldx
), oldx
);
1783 else if (CONST_INT_P (XEXP (oldx
, 1)))
1785 int offs
= INTVAL (XEXP (oldx
, 1));
1786 if (frame_pointer_rtx
!= XEXP (oldx
, 0)
1787 && offs
> MAX_LD_OFFSET (mode
))
1789 big_offset_p
= true;
1790 x
= force_reg (GET_MODE (oldx
), oldx
);
1795 if (avr_log
.legitimize_address
)
1797 avr_edump ("\n%?: mode=%m\n %r\n", mode
, oldx
);
1800 avr_edump (" %s --> %r\n", big_offset_p
? "(big offset)" : "", x
);
1807 /* Implement `LEGITIMIZE_RELOAD_ADDRESS'. */
1808 /* This will allow register R26/27 to be used where it is no worse than normal
1809 base pointers R28/29 or R30/31. For example, if base offset is greater
1810 than 63 bytes or for R++ or --R addressing. */
1813 avr_legitimize_reload_address (rtx
*px
, enum machine_mode mode
,
1814 int opnum
, int type
, int addr_type
,
1815 int ind_levels ATTRIBUTE_UNUSED
,
1816 rtx (*mk_memloc
)(rtx
,int))
1820 if (avr_log
.legitimize_reload_address
)
1821 avr_edump ("\n%?:%m %r\n", mode
, x
);
1823 if (1 && (GET_CODE (x
) == POST_INC
1824 || GET_CODE (x
) == PRE_DEC
))
1826 push_reload (XEXP (x
, 0), XEXP (x
, 0), &XEXP (x
, 0), &XEXP (x
, 0),
1827 POINTER_REGS
, GET_MODE (x
), GET_MODE (x
), 0, 0,
1828 opnum
, RELOAD_OTHER
);
1830 if (avr_log
.legitimize_reload_address
)
1831 avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
1832 POINTER_REGS
, XEXP (x
, 0), XEXP (x
, 0));
1837 if (GET_CODE (x
) == PLUS
1838 && REG_P (XEXP (x
, 0))
1839 && 0 == reg_equiv_constant (REGNO (XEXP (x
, 0)))
1840 && CONST_INT_P (XEXP (x
, 1))
1841 && INTVAL (XEXP (x
, 1)) >= 1)
1843 bool fit
= INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
);
1847 if (reg_equiv_address (REGNO (XEXP (x
, 0))) != 0)
1849 int regno
= REGNO (XEXP (x
, 0));
1850 rtx mem
= mk_memloc (x
, regno
);
1852 push_reload (XEXP (mem
, 0), NULL_RTX
, &XEXP (mem
, 0), NULL
,
1853 POINTER_REGS
, Pmode
, VOIDmode
, 0, 0,
1854 1, (enum reload_type
) addr_type
);
1856 if (avr_log
.legitimize_reload_address
)
1857 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
1858 POINTER_REGS
, XEXP (mem
, 0), NULL_RTX
);
1860 push_reload (mem
, NULL_RTX
, &XEXP (x
, 0), NULL
,
1861 BASE_POINTER_REGS
, GET_MODE (x
), VOIDmode
, 0, 0,
1862 opnum
, (enum reload_type
) type
);
1864 if (avr_log
.legitimize_reload_address
)
1865 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
1866 BASE_POINTER_REGS
, mem
, NULL_RTX
);
1871 else if (! (frame_pointer_needed
1872 && XEXP (x
, 0) == frame_pointer_rtx
))
1874 push_reload (x
, NULL_RTX
, px
, NULL
,
1875 POINTER_REGS
, GET_MODE (x
), VOIDmode
, 0, 0,
1876 opnum
, (enum reload_type
) type
);
1878 if (avr_log
.legitimize_reload_address
)
1879 avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
1880 POINTER_REGS
, x
, NULL_RTX
);
1890 /* Implement `TARGET_SECONDARY_RELOAD' */
1893 avr_secondary_reload (bool in_p
, rtx x
,
1894 reg_class_t reload_class ATTRIBUTE_UNUSED
,
1895 enum machine_mode mode
, secondary_reload_info
*sri
)
1899 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x
))
1900 && ADDR_SPACE_MEMX
!= MEM_ADDR_SPACE (x
))
1902 /* For the non-generic 16-bit spaces we need a d-class scratch. */
1909 case QImode
: sri
->icode
= CODE_FOR_reload_inqi
; break;
1910 case QQmode
: sri
->icode
= CODE_FOR_reload_inqq
; break;
1911 case UQQmode
: sri
->icode
= CODE_FOR_reload_inuqq
; break;
1913 case HImode
: sri
->icode
= CODE_FOR_reload_inhi
; break;
1914 case HQmode
: sri
->icode
= CODE_FOR_reload_inhq
; break;
1915 case HAmode
: sri
->icode
= CODE_FOR_reload_inha
; break;
1916 case UHQmode
: sri
->icode
= CODE_FOR_reload_inuhq
; break;
1917 case UHAmode
: sri
->icode
= CODE_FOR_reload_inuha
; break;
1919 case PSImode
: sri
->icode
= CODE_FOR_reload_inpsi
; break;
1921 case SImode
: sri
->icode
= CODE_FOR_reload_insi
; break;
1922 case SFmode
: sri
->icode
= CODE_FOR_reload_insf
; break;
1923 case SQmode
: sri
->icode
= CODE_FOR_reload_insq
; break;
1924 case SAmode
: sri
->icode
= CODE_FOR_reload_insa
; break;
1925 case USQmode
: sri
->icode
= CODE_FOR_reload_inusq
; break;
1926 case USAmode
: sri
->icode
= CODE_FOR_reload_inusa
; break;
1934 /* Helper function to print assembler resp. track instruction
1935 sequence lengths. Always return "".
1938 Output assembler code from template TPL with operands supplied
1939 by OPERANDS. This is just forwarding to output_asm_insn.
1942 If N_WORDS >= 0 Add N_WORDS to *PLEN.
1943 If N_WORDS < 0 Set *PLEN to -N_WORDS.
1944 Don't output anything.
1948 avr_asm_len (const char* tpl
, rtx
* operands
, int* plen
, int n_words
)
1952 output_asm_insn (tpl
, operands
);
1966 /* Return a pointer register name as a string. */
1969 ptrreg_to_str (int regno
)
1973 case REG_X
: return "X";
1974 case REG_Y
: return "Y";
1975 case REG_Z
: return "Z";
1977 output_operand_lossage ("address operand requires constraint for"
1978 " X, Y, or Z register");
1983 /* Return the condition name as a string.
1984 Used in conditional jump constructing */
1987 cond_string (enum rtx_code code
)
1996 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
2001 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
2017 /* Implement `TARGET_PRINT_OPERAND_ADDRESS'. */
2018 /* Output ADDR to FILE as address. */
2021 avr_print_operand_address (FILE *file
, rtx addr
)
2023 switch (GET_CODE (addr
))
2026 fprintf (file
, ptrreg_to_str (REGNO (addr
)));
2030 fprintf (file
, "-%s", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
2034 fprintf (file
, "%s+", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
2038 if (CONSTANT_ADDRESS_P (addr
)
2039 && text_segment_operand (addr
, VOIDmode
))
2042 if (GET_CODE (x
) == CONST
)
2044 if (GET_CODE (x
) == PLUS
&& GET_CODE (XEXP (x
,1)) == CONST_INT
)
2046 /* Assembler gs() will implant word address. Make offset
2047 a byte offset inside gs() for assembler. This is
2048 needed because the more logical (constant+gs(sym)) is not
2049 accepted by gas. For 128K and smaller devices this is ok.
2050 For large devices it will create a trampoline to offset
2051 from symbol which may not be what the user really wanted. */
2053 fprintf (file
, "gs(");
2054 output_addr_const (file
, XEXP (x
,0));
2055 fprintf (file
, "+" HOST_WIDE_INT_PRINT_DEC
")",
2056 2 * INTVAL (XEXP (x
, 1)));
2058 if (warning (0, "pointer offset from symbol maybe incorrect"))
2060 output_addr_const (stderr
, addr
);
2061 fprintf(stderr
,"\n");
2066 fprintf (file
, "gs(");
2067 output_addr_const (file
, addr
);
2068 fprintf (file
, ")");
2072 output_addr_const (file
, addr
);
2077 /* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'. */
2080 avr_print_operand_punct_valid_p (unsigned char code
)
2082 return code
== '~' || code
== '!';
2086 /* Implement `TARGET_PRINT_OPERAND'. */
2087 /* Output X as assembler operand to file FILE.
2088 For a description of supported %-codes, see top of avr.md. */
2091 avr_print_operand (FILE *file
, rtx x
, int code
)
2095 if (code
>= 'A' && code
<= 'D')
2100 if (!AVR_HAVE_JMP_CALL
)
2103 else if (code
== '!')
2105 if (AVR_HAVE_EIJMP_EICALL
)
2108 else if (code
== 't'
2111 static int t_regno
= -1;
2112 static int t_nbits
= -1;
2114 if (REG_P (x
) && t_regno
< 0 && code
== 'T')
2116 t_regno
= REGNO (x
);
2117 t_nbits
= GET_MODE_BITSIZE (GET_MODE (x
));
2119 else if (CONST_INT_P (x
) && t_regno
>= 0
2120 && IN_RANGE (INTVAL (x
), 0, t_nbits
- 1))
2122 int bpos
= INTVAL (x
);
2124 fprintf (file
, "%s", reg_names
[t_regno
+ bpos
/ 8]);
2126 fprintf (file
, ",%d", bpos
% 8);
2131 fatal_insn ("operands to %T/%t must be reg + const_int:", x
);
2135 if (x
== zero_reg_rtx
)
2136 fprintf (file
, "__zero_reg__");
2137 else if (code
== 'r' && REGNO (x
) < 32)
2138 fprintf (file
, "%d", (int) REGNO (x
));
2140 fprintf (file
, reg_names
[REGNO (x
) + abcd
]);
2142 else if (CONST_INT_P (x
))
2144 HOST_WIDE_INT ival
= INTVAL (x
);
2147 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, ival
+ abcd
);
2148 else if (low_io_address_operand (x
, VOIDmode
)
2149 || high_io_address_operand (x
, VOIDmode
))
2151 if (AVR_HAVE_RAMPZ
&& ival
== avr_addr
.rampz
)
2152 fprintf (file
, "__RAMPZ__");
2153 else if (AVR_HAVE_RAMPY
&& ival
== avr_addr
.rampy
)
2154 fprintf (file
, "__RAMPY__");
2155 else if (AVR_HAVE_RAMPX
&& ival
== avr_addr
.rampx
)
2156 fprintf (file
, "__RAMPX__");
2157 else if (AVR_HAVE_RAMPD
&& ival
== avr_addr
.rampd
)
2158 fprintf (file
, "__RAMPD__");
2159 else if (AVR_XMEGA
&& ival
== avr_addr
.ccp
)
2160 fprintf (file
, "__CCP__");
2161 else if (ival
== avr_addr
.sreg
) fprintf (file
, "__SREG__");
2162 else if (ival
== avr_addr
.sp_l
) fprintf (file
, "__SP_L__");
2163 else if (ival
== avr_addr
.sp_h
) fprintf (file
, "__SP_H__");
2166 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
,
2167 ival
- avr_current_arch
->sfr_offset
);
2171 fatal_insn ("bad address, not an I/O address:", x
);
2175 rtx addr
= XEXP (x
, 0);
2179 if (!CONSTANT_P (addr
))
2180 fatal_insn ("bad address, not a constant:", addr
);
2181 /* Assembler template with m-code is data - not progmem section */
2182 if (text_segment_operand (addr
, VOIDmode
))
2183 if (warning (0, "accessing data memory with"
2184 " program memory address"))
2186 output_addr_const (stderr
, addr
);
2187 fprintf(stderr
,"\n");
2189 output_addr_const (file
, addr
);
2191 else if (code
== 'i')
2193 avr_print_operand (file
, addr
, 'i');
2195 else if (code
== 'o')
2197 if (GET_CODE (addr
) != PLUS
)
2198 fatal_insn ("bad address, not (reg+disp):", addr
);
2200 avr_print_operand (file
, XEXP (addr
, 1), 0);
2202 else if (code
== 'p' || code
== 'r')
2204 if (GET_CODE (addr
) != POST_INC
&& GET_CODE (addr
) != PRE_DEC
)
2205 fatal_insn ("bad address, not post_inc or pre_dec:", addr
);
2208 avr_print_operand_address (file
, XEXP (addr
, 0)); /* X, Y, Z */
2210 avr_print_operand (file
, XEXP (addr
, 0), 0); /* r26, r28, r30 */
2212 else if (GET_CODE (addr
) == PLUS
)
2214 avr_print_operand_address (file
, XEXP (addr
,0));
2215 if (REGNO (XEXP (addr
, 0)) == REG_X
)
2216 fatal_insn ("internal compiler error. Bad address:"
2219 avr_print_operand (file
, XEXP (addr
,1), code
);
2222 avr_print_operand_address (file
, addr
);
2224 else if (code
== 'i')
2226 fatal_insn ("bad address, not an I/O address:", x
);
2228 else if (code
== 'x')
2230 /* Constant progmem address - like used in jmp or call */
2231 if (0 == text_segment_operand (x
, VOIDmode
))
2232 if (warning (0, "accessing program memory"
2233 " with data memory address"))
2235 output_addr_const (stderr
, x
);
2236 fprintf(stderr
,"\n");
2238 /* Use normal symbol for direct address no linker trampoline needed */
2239 output_addr_const (file
, x
);
2241 else if (CONST_FIXED_P (x
))
2243 HOST_WIDE_INT ival
= INTVAL (avr_to_int_mode (x
));
2245 output_operand_lossage ("Unsupported code '%c' for fixed-point:",
2247 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, ival
);
2249 else if (GET_CODE (x
) == CONST_DOUBLE
)
2253 if (GET_MODE (x
) != SFmode
)
2254 fatal_insn ("internal compiler error. Unknown mode:", x
);
2255 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
2256 REAL_VALUE_TO_TARGET_SINGLE (rv
, val
);
2257 fprintf (file
, "0x%lx", val
);
2259 else if (GET_CODE (x
) == CONST_STRING
)
2260 fputs (XSTR (x
, 0), file
);
2261 else if (code
== 'j')
2262 fputs (cond_string (GET_CODE (x
)), file
);
2263 else if (code
== 'k')
2264 fputs (cond_string (reverse_condition (GET_CODE (x
))), file
);
2266 avr_print_operand_address (file
, x
);
2270 /* Worker function for `NOTICE_UPDATE_CC'. */
2271 /* Update the condition code in the INSN. */
2274 avr_notice_update_cc (rtx body ATTRIBUTE_UNUSED
, rtx insn
)
2277 enum attr_cc cc
= get_attr_cc (insn
);
2287 rtx
*op
= recog_data
.operand
;
2290 /* Extract insn's operands. */
2291 extract_constrain_insn_cached (insn
);
2299 avr_out_plus (insn
, op
, &len_dummy
, &icc
);
2300 cc
= (enum attr_cc
) icc
;
2305 cc
= (op
[1] == CONST0_RTX (GET_MODE (op
[0]))
2306 && reg_overlap_mentioned_p (op
[0], zero_reg_rtx
))
2307 /* Loading zero-reg with 0 uses CLR and thus clobbers cc0. */
2309 /* Any other "r,rL" combination does not alter cc0. */
2313 } /* inner switch */
2317 } /* outer swicth */
2322 /* Special values like CC_OUT_PLUS from above have been
2323 mapped to "standard" CC_* values so we never come here. */
2329 /* Insn does not affect CC at all. */
2337 set
= single_set (insn
);
2341 cc_status
.flags
|= CC_NO_OVERFLOW
;
2342 cc_status
.value1
= SET_DEST (set
);
2347 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
2348 The V flag may or may not be known but that's ok because
2349 alter_cond will change tests to use EQ/NE. */
2350 set
= single_set (insn
);
2354 cc_status
.value1
= SET_DEST (set
);
2355 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
2360 set
= single_set (insn
);
2363 cc_status
.value1
= SET_SRC (set
);
2367 /* Insn doesn't leave CC in a usable state. */
2373 /* Choose mode for jump insn:
2374 1 - relative jump in range -63 <= x <= 62 ;
2375 2 - relative jump in range -2046 <= x <= 2045 ;
2376 3 - absolute jump (only for ATmega[16]03). */
2379 avr_jump_mode (rtx x
, rtx insn
)
2381 int dest_addr
= INSN_ADDRESSES (INSN_UID (GET_CODE (x
) == LABEL_REF
2382 ? XEXP (x
, 0) : x
));
2383 int cur_addr
= INSN_ADDRESSES (INSN_UID (insn
));
2384 int jump_distance
= cur_addr
- dest_addr
;
2386 if (-63 <= jump_distance
&& jump_distance
<= 62)
2388 else if (-2046 <= jump_distance
&& jump_distance
<= 2045)
2390 else if (AVR_HAVE_JMP_CALL
)
2396 /* Return an AVR condition jump commands.
2397 X is a comparison RTX.
2398 LEN is a number returned by avr_jump_mode function.
2399 If REVERSE nonzero then condition code in X must be reversed. */
2402 ret_cond_branch (rtx x
, int len
, int reverse
)
2404 RTX_CODE cond
= reverse
? reverse_condition (GET_CODE (x
)) : GET_CODE (x
);
2409 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
2410 return (len
== 1 ? ("breq .+2" CR_TAB
2412 len
== 2 ? ("breq .+4" CR_TAB
2420 return (len
== 1 ? ("breq .+2" CR_TAB
2422 len
== 2 ? ("breq .+4" CR_TAB
2429 return (len
== 1 ? ("breq .+2" CR_TAB
2431 len
== 2 ? ("breq .+4" CR_TAB
2438 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
2439 return (len
== 1 ? ("breq %0" CR_TAB
2441 len
== 2 ? ("breq .+2" CR_TAB
2448 return (len
== 1 ? ("breq %0" CR_TAB
2450 len
== 2 ? ("breq .+2" CR_TAB
2457 return (len
== 1 ? ("breq %0" CR_TAB
2459 len
== 2 ? ("breq .+2" CR_TAB
2473 return ("br%j1 .+2" CR_TAB
2476 return ("br%j1 .+4" CR_TAB
2487 return ("br%k1 .+2" CR_TAB
2490 return ("br%k1 .+4" CR_TAB
2499 /* Worker function for `FINAL_PRESCAN_INSN'. */
2500 /* Output insn cost for next insn. */
2503 avr_final_prescan_insn (rtx insn
, rtx
*operand ATTRIBUTE_UNUSED
,
2504 int num_operands ATTRIBUTE_UNUSED
)
2506 if (avr_log
.rtx_costs
)
2508 rtx set
= single_set (insn
);
2511 fprintf (asm_out_file
, "/* DEBUG: cost = %d. */\n",
2512 set_src_cost (SET_SRC (set
), optimize_insn_for_speed_p ()));
2514 fprintf (asm_out_file
, "/* DEBUG: pattern-cost = %d. */\n",
2515 rtx_cost (PATTERN (insn
), INSN
, 0,
2516 optimize_insn_for_speed_p()));
2520 /* Return 0 if undefined, 1 if always true or always false. */
2523 avr_simplify_comparison_p (enum machine_mode mode
, RTX_CODE op
, rtx x
)
2525 unsigned int max
= (mode
== QImode
? 0xff :
2526 mode
== HImode
? 0xffff :
2527 mode
== PSImode
? 0xffffff :
2528 mode
== SImode
? 0xffffffff : 0);
2529 if (max
&& op
&& CONST_INT_P (x
))
2531 if (unsigned_condition (op
) != op
)
2534 if (max
!= (INTVAL (x
) & max
)
2535 && INTVAL (x
) != 0xff)
2542 /* Worker function for `FUNCTION_ARG_REGNO_P'. */
2543 /* Returns nonzero if REGNO is the number of a hard
2544 register in which function arguments are sometimes passed. */
2547 avr_function_arg_regno_p(int r
)
2549 return (r
>= 8 && r
<= 25);
2553 /* Worker function for `INIT_CUMULATIVE_ARGS'. */
2554 /* Initializing the variable cum for the state at the beginning
2555 of the argument list. */
2558 avr_init_cumulative_args (CUMULATIVE_ARGS
*cum
, tree fntype
, rtx libname
,
2559 tree fndecl ATTRIBUTE_UNUSED
)
2562 cum
->regno
= FIRST_CUM_REG
;
2563 if (!libname
&& stdarg_p (fntype
))
2566 /* Assume the calle may be tail called */
2568 cfun
->machine
->sibcall_fails
= 0;
2571 /* Returns the number of registers to allocate for a function argument. */
2574 avr_num_arg_regs (enum machine_mode mode
, const_tree type
)
2578 if (mode
== BLKmode
)
2579 size
= int_size_in_bytes (type
);
2581 size
= GET_MODE_SIZE (mode
);
2583 /* Align all function arguments to start in even-numbered registers.
2584 Odd-sized arguments leave holes above them. */
2586 return (size
+ 1) & ~1;
2590 /* Implement `TARGET_FUNCTION_ARG'. */
2591 /* Controls whether a function argument is passed
2592 in a register, and which register. */
2595 avr_function_arg (cumulative_args_t cum_v
, enum machine_mode mode
,
2596 const_tree type
, bool named ATTRIBUTE_UNUSED
)
2598 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2599 int bytes
= avr_num_arg_regs (mode
, type
);
2601 if (cum
->nregs
&& bytes
<= cum
->nregs
)
2602 return gen_rtx_REG (mode
, cum
->regno
- bytes
);
2608 /* Implement `TARGET_FUNCTION_ARG_ADVANCE'. */
2609 /* Update the summarizer variable CUM to advance past an argument
2610 in the argument list. */
2613 avr_function_arg_advance (cumulative_args_t cum_v
, enum machine_mode mode
,
2614 const_tree type
, bool named ATTRIBUTE_UNUSED
)
2616 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2617 int bytes
= avr_num_arg_regs (mode
, type
);
2619 cum
->nregs
-= bytes
;
2620 cum
->regno
-= bytes
;
2622 /* A parameter is being passed in a call-saved register. As the original
2623 contents of these regs has to be restored before leaving the function,
2624 a function must not pass arguments in call-saved regs in order to get
2629 && !call_used_regs
[cum
->regno
])
2631 /* FIXME: We ship info on failing tail-call in struct machine_function.
2632 This uses internals of calls.c:expand_call() and the way args_so_far
2633 is used. targetm.function_ok_for_sibcall() needs to be extended to
2634 pass &args_so_far, too. At present, CUMULATIVE_ARGS is target
2635 dependent so that such an extension is not wanted. */
2637 cfun
->machine
->sibcall_fails
= 1;
2640 /* Test if all registers needed by the ABI are actually available. If the
2641 user has fixed a GPR needed to pass an argument, an (implicit) function
2642 call will clobber that fixed register. See PR45099 for an example. */
2649 for (regno
= cum
->regno
; regno
< cum
->regno
+ bytes
; regno
++)
2650 if (fixed_regs
[regno
])
2651 warning (0, "fixed register %s used to pass parameter to function",
2655 if (cum
->nregs
<= 0)
2658 cum
->regno
= FIRST_CUM_REG
;
2662 /* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
2663 /* Decide whether we can make a sibling call to a function. DECL is the
2664 declaration of the function being targeted by the call and EXP is the
2665 CALL_EXPR representing the call. */
2668 avr_function_ok_for_sibcall (tree decl_callee
, tree exp_callee
)
2672 /* Tail-calling must fail if callee-saved regs are used to pass
2673 function args. We must not tail-call when `epilogue_restores'
2674 is used. Unfortunately, we cannot tell at this point if that
2675 actually will happen or not, and we cannot step back from
2676 tail-calling. Thus, we inhibit tail-calling with -mcall-prologues. */
2678 if (cfun
->machine
->sibcall_fails
2679 || TARGET_CALL_PROLOGUES
)
2684 fntype_callee
= TREE_TYPE (CALL_EXPR_FN (exp_callee
));
2688 decl_callee
= TREE_TYPE (decl_callee
);
2692 decl_callee
= fntype_callee
;
2694 while (FUNCTION_TYPE
!= TREE_CODE (decl_callee
)
2695 && METHOD_TYPE
!= TREE_CODE (decl_callee
))
2697 decl_callee
= TREE_TYPE (decl_callee
);
2701 /* Ensure that caller and callee have compatible epilogues */
2703 if (cfun
->machine
->is_interrupt
2704 || cfun
->machine
->is_signal
2705 || cfun
->machine
->is_naked
2706 || avr_naked_function_p (decl_callee
)
2707 /* FIXME: For OS_task and OS_main, this might be over-conservative. */
2708 || (avr_OS_task_function_p (decl_callee
)
2709 != cfun
->machine
->is_OS_task
)
2710 || (avr_OS_main_function_p (decl_callee
)
2711 != cfun
->machine
->is_OS_main
))
2719 /***********************************************************************
2720 Functions for outputting various mov's for a various modes
2721 ************************************************************************/
2723 /* Return true if a value of mode MODE is read from flash by
2724 __load_* function from libgcc. */
2727 avr_load_libgcc_p (rtx op
)
2729 enum machine_mode mode
= GET_MODE (op
);
2730 int n_bytes
= GET_MODE_SIZE (mode
);
2734 && avr_mem_flash_p (op
));
2737 /* Return true if a value of mode MODE is read by __xload_* function. */
2740 avr_xload_libgcc_p (enum machine_mode mode
)
2742 int n_bytes
= GET_MODE_SIZE (mode
);
2745 || avr_current_device
->n_flash
> 1);
2749 /* Fixme: This is a hack because secondary reloads don't works as expected.
2751 Find an unused d-register to be used as scratch in INSN.
2752 EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
2753 is a register, skip all possible return values that overlap EXCLUDE.
2754 The policy for the returned register is similar to that of
2755 `reg_unused_after', i.e. the returned register may overlap the SET_DEST
2758 Return a QImode d-register or NULL_RTX if nothing found. */
2761 avr_find_unused_d_reg (rtx insn
, rtx exclude
)
2764 bool isr_p
= (avr_interrupt_function_p (current_function_decl
)
2765 || avr_signal_function_p (current_function_decl
));
2767 for (regno
= 16; regno
< 32; regno
++)
2769 rtx reg
= all_regs_rtx
[regno
];
2772 && reg_overlap_mentioned_p (exclude
, reg
))
2773 || fixed_regs
[regno
])
2778 /* Try non-live register */
2780 if (!df_regs_ever_live_p (regno
)
2781 && (TREE_THIS_VOLATILE (current_function_decl
)
2782 || cfun
->machine
->is_OS_task
2783 || cfun
->machine
->is_OS_main
2784 || (!isr_p
&& call_used_regs
[regno
])))
2789 /* Any live register can be used if it is unused after.
2790 Prologue/epilogue will care for it as needed. */
2792 if (df_regs_ever_live_p (regno
)
2793 && reg_unused_after (insn
, reg
))
2803 /* Helper function for the next function in the case where only restricted
2804 version of LPM instruction is available. */
2807 avr_out_lpm_no_lpmx (rtx insn
, rtx
*xop
, int *plen
)
2811 int n_bytes
= GET_MODE_SIZE (GET_MODE (dest
));
2814 regno_dest
= REGNO (dest
);
2816 /* The implicit target register of LPM. */
2817 xop
[3] = lpm_reg_rtx
;
2819 switch (GET_CODE (addr
))
2826 gcc_assert (REG_Z
== REGNO (addr
));
2834 avr_asm_len ("%4lpm", xop
, plen
, 1);
2836 if (regno_dest
!= LPM_REGNO
)
2837 avr_asm_len ("mov %0,%3", xop
, plen
, 1);
2842 if (REGNO (dest
) == REG_Z
)
2843 return avr_asm_len ("%4lpm" CR_TAB
2848 "pop %A0", xop
, plen
, 6);
2850 avr_asm_len ("%4lpm" CR_TAB
2854 "mov %B0,%3", xop
, plen
, 5);
2856 if (!reg_unused_after (insn
, addr
))
2857 avr_asm_len ("sbiw %2,1", xop
, plen
, 1);
2866 gcc_assert (REG_Z
== REGNO (XEXP (addr
, 0))
2869 if (regno_dest
== LPM_REGNO
)
2870 avr_asm_len ("%4lpm" CR_TAB
2871 "adiw %2,1", xop
, plen
, 2);
2873 avr_asm_len ("%4lpm" CR_TAB
2875 "adiw %2,1", xop
, plen
, 3);
2878 avr_asm_len ("%4lpm" CR_TAB
2880 "adiw %2,1", xop
, plen
, 3);
2883 avr_asm_len ("%4lpm" CR_TAB
2885 "adiw %2,1", xop
, plen
, 3);
2888 avr_asm_len ("%4lpm" CR_TAB
2890 "adiw %2,1", xop
, plen
, 3);
2892 break; /* POST_INC */
2894 } /* switch CODE (addr) */
2900 /* If PLEN == NULL: Ouput instructions to load a value from a memory location
2901 OP[1] in AS1 to register OP[0].
2902 If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
2906 avr_out_lpm (rtx insn
, rtx
*op
, int *plen
)
2910 rtx src
= SET_SRC (single_set (insn
));
2912 int n_bytes
= GET_MODE_SIZE (GET_MODE (dest
));
2915 addr_space_t as
= MEM_ADDR_SPACE (src
);
2922 warning (0, "writing to address space %qs not supported",
2923 avr_addrspace
[MEM_ADDR_SPACE (dest
)].name
);
2928 addr
= XEXP (src
, 0);
2929 code
= GET_CODE (addr
);
2931 gcc_assert (REG_P (dest
));
2932 gcc_assert (REG
== code
|| POST_INC
== code
);
2936 xop
[2] = lpm_addr_reg_rtx
;
2937 xop
[4] = xstring_empty
;
2938 xop
[5] = tmp_reg_rtx
;
2939 xop
[6] = XEXP (rampz_rtx
, 0);
2941 segment
= avr_addrspace
[as
].segment
;
2943 /* Set RAMPZ as needed. */
2947 xop
[4] = GEN_INT (segment
);
2948 xop
[3] = avr_find_unused_d_reg (insn
, lpm_addr_reg_rtx
);
2950 if (xop
[3] != NULL_RTX
)
2952 avr_asm_len ("ldi %3,%4" CR_TAB
2953 "out %i6,%3", xop
, plen
, 2);
2955 else if (segment
== 1)
2957 avr_asm_len ("clr %5" CR_TAB
2959 "out %i6,%5", xop
, plen
, 3);
2963 avr_asm_len ("mov %5,%2" CR_TAB
2966 "mov %2,%5", xop
, plen
, 4);
2971 if (!AVR_HAVE_ELPMX
)
2972 return avr_out_lpm_no_lpmx (insn
, xop
, plen
);
2974 else if (!AVR_HAVE_LPMX
)
2976 return avr_out_lpm_no_lpmx (insn
, xop
, plen
);
2979 /* We have [E]LPMX: Output reading from Flash the comfortable way. */
2981 switch (GET_CODE (addr
))
2988 gcc_assert (REG_Z
== REGNO (addr
));
2996 return avr_asm_len ("%4lpm %0,%a2", xop
, plen
, 1);
2999 if (REGNO (dest
) == REG_Z
)
3000 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3001 "%4lpm %B0,%a2" CR_TAB
3002 "mov %A0,%5", xop
, plen
, 3);
3005 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3006 "%4lpm %B0,%a2", xop
, plen
, 2);
3008 if (!reg_unused_after (insn
, addr
))
3009 avr_asm_len ("sbiw %2,1", xop
, plen
, 1);
3016 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3017 "%4lpm %B0,%a2+" CR_TAB
3018 "%4lpm %C0,%a2", xop
, plen
, 3);
3020 if (!reg_unused_after (insn
, addr
))
3021 avr_asm_len ("sbiw %2,2", xop
, plen
, 1);
3027 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3028 "%4lpm %B0,%a2+", xop
, plen
, 2);
3030 if (REGNO (dest
) == REG_Z
- 2)
3031 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3032 "%4lpm %C0,%a2" CR_TAB
3033 "mov %D0,%5", xop
, plen
, 3);
3036 avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
3037 "%4lpm %D0,%a2", xop
, plen
, 2);
3039 if (!reg_unused_after (insn
, addr
))
3040 avr_asm_len ("sbiw %2,3", xop
, plen
, 1);
3050 gcc_assert (REG_Z
== REGNO (XEXP (addr
, 0))
3053 avr_asm_len ("%4lpm %A0,%a2+", xop
, plen
, 1);
3054 if (n_bytes
>= 2) avr_asm_len ("%4lpm %B0,%a2+", xop
, plen
, 1);
3055 if (n_bytes
>= 3) avr_asm_len ("%4lpm %C0,%a2+", xop
, plen
, 1);
3056 if (n_bytes
>= 4) avr_asm_len ("%4lpm %D0,%a2+", xop
, plen
, 1);
3058 break; /* POST_INC */
3060 } /* switch CODE (addr) */
3062 if (xop
[4] == xstring_e
&& AVR_HAVE_RAMPD
)
3064 /* Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM. */
3066 xop
[0] = zero_reg_rtx
;
3067 avr_asm_len ("out %i6,%0", xop
, plen
, 1);
3074 /* Worker function for xload_8 insn. */
3077 avr_out_xload (rtx insn ATTRIBUTE_UNUSED
, rtx
*op
, int *plen
)
3083 xop
[2] = lpm_addr_reg_rtx
;
3084 xop
[3] = AVR_HAVE_LPMX
? op
[0] : lpm_reg_rtx
;
3089 avr_asm_len ("sbrc %1,7" CR_TAB
3091 "sbrs %1,7", xop
, plen
, 3);
3093 avr_asm_len (AVR_HAVE_LPMX
? "lpm %3,%a2" : "lpm", xop
, plen
, 1);
3095 if (REGNO (xop
[0]) != REGNO (xop
[3]))
3096 avr_asm_len ("mov %0,%3", xop
, plen
, 1);
3103 output_movqi (rtx insn
, rtx operands
[], int *plen
)
3105 rtx dest
= operands
[0];
3106 rtx src
= operands
[1];
3108 if (avr_mem_flash_p (src
)
3109 || avr_mem_flash_p (dest
))
3111 return avr_out_lpm (insn
, operands
, plen
);
3114 gcc_assert (1 == GET_MODE_SIZE (GET_MODE (dest
)));
3118 if (REG_P (src
)) /* mov r,r */
3120 if (test_hard_reg_class (STACK_REG
, dest
))
3121 return avr_asm_len ("out %0,%1", operands
, plen
, -1);
3122 else if (test_hard_reg_class (STACK_REG
, src
))
3123 return avr_asm_len ("in %0,%1", operands
, plen
, -1);
3125 return avr_asm_len ("mov %0,%1", operands
, plen
, -1);
3127 else if (CONSTANT_P (src
))
3129 output_reload_in_const (operands
, NULL_RTX
, plen
, false);
3132 else if (MEM_P (src
))
3133 return out_movqi_r_mr (insn
, operands
, plen
); /* mov r,m */
3135 else if (MEM_P (dest
))
3140 xop
[1] = src
== CONST0_RTX (GET_MODE (dest
)) ? zero_reg_rtx
: src
;
3142 return out_movqi_mr_r (insn
, xop
, plen
);
3150 output_movhi (rtx insn
, rtx xop
[], int *plen
)
3155 gcc_assert (GET_MODE_SIZE (GET_MODE (dest
)) == 2);
3157 if (avr_mem_flash_p (src
)
3158 || avr_mem_flash_p (dest
))
3160 return avr_out_lpm (insn
, xop
, plen
);
3163 gcc_assert (2 == GET_MODE_SIZE (GET_MODE (dest
)));
3167 if (REG_P (src
)) /* mov r,r */
3169 if (test_hard_reg_class (STACK_REG
, dest
))
3171 if (AVR_HAVE_8BIT_SP
)
3172 return avr_asm_len ("out __SP_L__,%A1", xop
, plen
, -1);
3175 return avr_asm_len ("out __SP_L__,%A1" CR_TAB
3176 "out __SP_H__,%B1", xop
, plen
, -2);
3178 /* Use simple load of SP if no interrupts are used. */
3180 return TARGET_NO_INTERRUPTS
3181 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
3182 "out __SP_L__,%A1", xop
, plen
, -2)
3183 : avr_asm_len ("in __tmp_reg__,__SREG__" CR_TAB
3185 "out __SP_H__,%B1" CR_TAB
3186 "out __SREG__,__tmp_reg__" CR_TAB
3187 "out __SP_L__,%A1", xop
, plen
, -5);
3189 else if (test_hard_reg_class (STACK_REG
, src
))
3191 return !AVR_HAVE_SPH
3192 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
3193 "clr %B0", xop
, plen
, -2)
3195 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
3196 "in %B0,__SP_H__", xop
, plen
, -2);
3199 return AVR_HAVE_MOVW
3200 ? avr_asm_len ("movw %0,%1", xop
, plen
, -1)
3202 : avr_asm_len ("mov %A0,%A1" CR_TAB
3203 "mov %B0,%B1", xop
, plen
, -2);
3205 else if (CONSTANT_P (src
))
3207 return output_reload_inhi (xop
, NULL
, plen
);
3209 else if (MEM_P (src
))
3211 return out_movhi_r_mr (insn
, xop
, plen
); /* mov r,m */
3214 else if (MEM_P (dest
))
3219 xop
[1] = src
== CONST0_RTX (GET_MODE (dest
)) ? zero_reg_rtx
: src
;
3221 return out_movhi_mr_r (insn
, xop
, plen
);
3224 fatal_insn ("invalid insn:", insn
);
3230 out_movqi_r_mr (rtx insn
, rtx op
[], int *plen
)
3234 rtx x
= XEXP (src
, 0);
3236 if (CONSTANT_ADDRESS_P (x
))
3238 return optimize
> 0 && io_address_operand (x
, QImode
)
3239 ? avr_asm_len ("in %0,%i1", op
, plen
, -1)
3240 : avr_asm_len ("lds %0,%m1", op
, plen
, -2);
3242 else if (GET_CODE (x
) == PLUS
3243 && REG_P (XEXP (x
, 0))
3244 && CONST_INT_P (XEXP (x
, 1)))
3246 /* memory access by reg+disp */
3248 int disp
= INTVAL (XEXP (x
, 1));
3250 if (disp
- GET_MODE_SIZE (GET_MODE (src
)) >= 63)
3252 if (REGNO (XEXP (x
, 0)) != REG_Y
)
3253 fatal_insn ("incorrect insn:",insn
);
3255 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
3256 return avr_asm_len ("adiw r28,%o1-63" CR_TAB
3257 "ldd %0,Y+63" CR_TAB
3258 "sbiw r28,%o1-63", op
, plen
, -3);
3260 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
3261 "sbci r29,hi8(-%o1)" CR_TAB
3263 "subi r28,lo8(%o1)" CR_TAB
3264 "sbci r29,hi8(%o1)", op
, plen
, -5);
3266 else if (REGNO (XEXP (x
, 0)) == REG_X
)
3268 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
3269 it but I have this situation with extremal optimizing options. */
3271 avr_asm_len ("adiw r26,%o1" CR_TAB
3272 "ld %0,X", op
, plen
, -2);
3274 if (!reg_overlap_mentioned_p (dest
, XEXP (x
,0))
3275 && !reg_unused_after (insn
, XEXP (x
,0)))
3277 avr_asm_len ("sbiw r26,%o1", op
, plen
, 1);
3283 return avr_asm_len ("ldd %0,%1", op
, plen
, -1);
3286 return avr_asm_len ("ld %0,%1", op
, plen
, -1);
3290 out_movhi_r_mr (rtx insn
, rtx op
[], int *plen
)
3294 rtx base
= XEXP (src
, 0);
3295 int reg_dest
= true_regnum (dest
);
3296 int reg_base
= true_regnum (base
);
3297 /* "volatile" forces reading low byte first, even if less efficient,
3298 for correct operation with 16-bit I/O registers. */
3299 int mem_volatile_p
= MEM_VOLATILE_P (src
);
3303 if (reg_dest
== reg_base
) /* R = (R) */
3304 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
3306 "mov %A0,__tmp_reg__", op
, plen
, -3);
3308 if (reg_base
!= REG_X
)
3309 return avr_asm_len ("ld %A0,%1" CR_TAB
3310 "ldd %B0,%1+1", op
, plen
, -2);
3312 avr_asm_len ("ld %A0,X+" CR_TAB
3313 "ld %B0,X", op
, plen
, -2);
3315 if (!reg_unused_after (insn
, base
))
3316 avr_asm_len ("sbiw r26,1", op
, plen
, 1);
3320 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
3322 int disp
= INTVAL (XEXP (base
, 1));
3323 int reg_base
= true_regnum (XEXP (base
, 0));
3325 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
3327 if (REGNO (XEXP (base
, 0)) != REG_Y
)
3328 fatal_insn ("incorrect insn:",insn
);
3330 return disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
))
3331 ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
3332 "ldd %A0,Y+62" CR_TAB
3333 "ldd %B0,Y+63" CR_TAB
3334 "sbiw r28,%o1-62", op
, plen
, -4)
3336 : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
3337 "sbci r29,hi8(-%o1)" CR_TAB
3339 "ldd %B0,Y+1" CR_TAB
3340 "subi r28,lo8(%o1)" CR_TAB
3341 "sbci r29,hi8(%o1)", op
, plen
, -6);
3344 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
3345 it but I have this situation with extremal
3346 optimization options. */
3348 if (reg_base
== REG_X
)
3349 return reg_base
== reg_dest
3350 ? avr_asm_len ("adiw r26,%o1" CR_TAB
3351 "ld __tmp_reg__,X+" CR_TAB
3353 "mov %A0,__tmp_reg__", op
, plen
, -4)
3355 : avr_asm_len ("adiw r26,%o1" CR_TAB
3358 "sbiw r26,%o1+1", op
, plen
, -4);
3360 return reg_base
== reg_dest
3361 ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
3362 "ldd %B0,%B1" CR_TAB
3363 "mov %A0,__tmp_reg__", op
, plen
, -3)
3365 : avr_asm_len ("ldd %A0,%A1" CR_TAB
3366 "ldd %B0,%B1", op
, plen
, -2);
3368 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
3370 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
3371 fatal_insn ("incorrect insn:", insn
);
3373 if (!mem_volatile_p
)
3374 return avr_asm_len ("ld %B0,%1" CR_TAB
3375 "ld %A0,%1", op
, plen
, -2);
3377 return REGNO (XEXP (base
, 0)) == REG_X
3378 ? avr_asm_len ("sbiw r26,2" CR_TAB
3381 "sbiw r26,1", op
, plen
, -4)
3383 : avr_asm_len ("sbiw %r1,2" CR_TAB
3385 "ldd %B0,%p1+1", op
, plen
, -3);
3387 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
3389 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
3390 fatal_insn ("incorrect insn:", insn
);
3392 return avr_asm_len ("ld %A0,%1" CR_TAB
3393 "ld %B0,%1", op
, plen
, -2);
3395 else if (CONSTANT_ADDRESS_P (base
))
3397 return optimize
> 0 && io_address_operand (base
, HImode
)
3398 ? avr_asm_len ("in %A0,%i1" CR_TAB
3399 "in %B0,%i1+1", op
, plen
, -2)
3401 : avr_asm_len ("lds %A0,%m1" CR_TAB
3402 "lds %B0,%m1+1", op
, plen
, -4);
3405 fatal_insn ("unknown move insn:",insn
);
3410 out_movsi_r_mr (rtx insn
, rtx op
[], int *l
)
3414 rtx base
= XEXP (src
, 0);
3415 int reg_dest
= true_regnum (dest
);
3416 int reg_base
= true_regnum (base
);
3424 if (reg_base
== REG_X
) /* (R26) */
3426 if (reg_dest
== REG_X
)
3427 /* "ld r26,-X" is undefined */
3428 return *l
=7, ("adiw r26,3" CR_TAB
3431 "ld __tmp_reg__,-X" CR_TAB
3434 "mov r27,__tmp_reg__");
3435 else if (reg_dest
== REG_X
- 2)
3436 return *l
=5, ("ld %A0,X+" CR_TAB
3438 "ld __tmp_reg__,X+" CR_TAB
3440 "mov %C0,__tmp_reg__");
3441 else if (reg_unused_after (insn
, base
))
3442 return *l
=4, ("ld %A0,X+" CR_TAB
3447 return *l
=5, ("ld %A0,X+" CR_TAB
3455 if (reg_dest
== reg_base
)
3456 return *l
=5, ("ldd %D0,%1+3" CR_TAB
3457 "ldd %C0,%1+2" CR_TAB
3458 "ldd __tmp_reg__,%1+1" CR_TAB
3460 "mov %B0,__tmp_reg__");
3461 else if (reg_base
== reg_dest
+ 2)
3462 return *l
=5, ("ld %A0,%1" CR_TAB
3463 "ldd %B0,%1+1" CR_TAB
3464 "ldd __tmp_reg__,%1+2" CR_TAB
3465 "ldd %D0,%1+3" CR_TAB
3466 "mov %C0,__tmp_reg__");
3468 return *l
=4, ("ld %A0,%1" CR_TAB
3469 "ldd %B0,%1+1" CR_TAB
3470 "ldd %C0,%1+2" CR_TAB
3474 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
3476 int disp
= INTVAL (XEXP (base
, 1));
3478 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
3480 if (REGNO (XEXP (base
, 0)) != REG_Y
)
3481 fatal_insn ("incorrect insn:",insn
);
3483 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
3484 return *l
= 6, ("adiw r28,%o1-60" CR_TAB
3485 "ldd %A0,Y+60" CR_TAB
3486 "ldd %B0,Y+61" CR_TAB
3487 "ldd %C0,Y+62" CR_TAB
3488 "ldd %D0,Y+63" CR_TAB
3491 return *l
= 8, ("subi r28,lo8(-%o1)" CR_TAB
3492 "sbci r29,hi8(-%o1)" CR_TAB
3494 "ldd %B0,Y+1" CR_TAB
3495 "ldd %C0,Y+2" CR_TAB
3496 "ldd %D0,Y+3" CR_TAB
3497 "subi r28,lo8(%o1)" CR_TAB
3498 "sbci r29,hi8(%o1)");
3501 reg_base
= true_regnum (XEXP (base
, 0));
3502 if (reg_base
== REG_X
)
3505 if (reg_dest
== REG_X
)
3508 /* "ld r26,-X" is undefined */
3509 return ("adiw r26,%o1+3" CR_TAB
3512 "ld __tmp_reg__,-X" CR_TAB
3515 "mov r27,__tmp_reg__");
3518 if (reg_dest
== REG_X
- 2)
3519 return ("adiw r26,%o1" CR_TAB
3522 "ld __tmp_reg__,X+" CR_TAB
3524 "mov r26,__tmp_reg__");
3526 return ("adiw r26,%o1" CR_TAB
3533 if (reg_dest
== reg_base
)
3534 return *l
=5, ("ldd %D0,%D1" CR_TAB
3535 "ldd %C0,%C1" CR_TAB
3536 "ldd __tmp_reg__,%B1" CR_TAB
3537 "ldd %A0,%A1" CR_TAB
3538 "mov %B0,__tmp_reg__");
3539 else if (reg_dest
== reg_base
- 2)
3540 return *l
=5, ("ldd %A0,%A1" CR_TAB
3541 "ldd %B0,%B1" CR_TAB
3542 "ldd __tmp_reg__,%C1" CR_TAB
3543 "ldd %D0,%D1" CR_TAB
3544 "mov %C0,__tmp_reg__");
3545 return *l
=4, ("ldd %A0,%A1" CR_TAB
3546 "ldd %B0,%B1" CR_TAB
3547 "ldd %C0,%C1" CR_TAB
3550 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
3551 return *l
=4, ("ld %D0,%1" CR_TAB
3555 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
3556 return *l
=4, ("ld %A0,%1" CR_TAB
3560 else if (CONSTANT_ADDRESS_P (base
))
3561 return *l
=8, ("lds %A0,%m1" CR_TAB
3562 "lds %B0,%m1+1" CR_TAB
3563 "lds %C0,%m1+2" CR_TAB
3566 fatal_insn ("unknown move insn:",insn
);
3571 out_movsi_mr_r (rtx insn
, rtx op
[], int *l
)
3575 rtx base
= XEXP (dest
, 0);
3576 int reg_base
= true_regnum (base
);
3577 int reg_src
= true_regnum (src
);
3583 if (CONSTANT_ADDRESS_P (base
))
3584 return *l
=8,("sts %m0,%A1" CR_TAB
3585 "sts %m0+1,%B1" CR_TAB
3586 "sts %m0+2,%C1" CR_TAB
3588 if (reg_base
> 0) /* (r) */
3590 if (reg_base
== REG_X
) /* (R26) */
3592 if (reg_src
== REG_X
)
3594 /* "st X+,r26" is undefined */
3595 if (reg_unused_after (insn
, base
))
3596 return *l
=6, ("mov __tmp_reg__,r27" CR_TAB
3599 "st X+,__tmp_reg__" CR_TAB
3603 return *l
=7, ("mov __tmp_reg__,r27" CR_TAB
3606 "st X+,__tmp_reg__" CR_TAB
3611 else if (reg_base
== reg_src
+ 2)
3613 if (reg_unused_after (insn
, base
))
3614 return *l
=7, ("mov __zero_reg__,%C1" CR_TAB
3615 "mov __tmp_reg__,%D1" CR_TAB
3618 "st %0+,__zero_reg__" CR_TAB
3619 "st %0,__tmp_reg__" CR_TAB
3620 "clr __zero_reg__");
3622 return *l
=8, ("mov __zero_reg__,%C1" CR_TAB
3623 "mov __tmp_reg__,%D1" CR_TAB
3626 "st %0+,__zero_reg__" CR_TAB
3627 "st %0,__tmp_reg__" CR_TAB
3628 "clr __zero_reg__" CR_TAB
3631 return *l
=5, ("st %0+,%A1" CR_TAB
3638 return *l
=4, ("st %0,%A1" CR_TAB
3639 "std %0+1,%B1" CR_TAB
3640 "std %0+2,%C1" CR_TAB
3643 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
3645 int disp
= INTVAL (XEXP (base
, 1));
3646 reg_base
= REGNO (XEXP (base
, 0));
3647 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
3649 if (reg_base
!= REG_Y
)
3650 fatal_insn ("incorrect insn:",insn
);
3652 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
3653 return *l
= 6, ("adiw r28,%o0-60" CR_TAB
3654 "std Y+60,%A1" CR_TAB
3655 "std Y+61,%B1" CR_TAB
3656 "std Y+62,%C1" CR_TAB
3657 "std Y+63,%D1" CR_TAB
3660 return *l
= 8, ("subi r28,lo8(-%o0)" CR_TAB
3661 "sbci r29,hi8(-%o0)" CR_TAB
3663 "std Y+1,%B1" CR_TAB
3664 "std Y+2,%C1" CR_TAB
3665 "std Y+3,%D1" CR_TAB
3666 "subi r28,lo8(%o0)" CR_TAB
3667 "sbci r29,hi8(%o0)");
3669 if (reg_base
== REG_X
)
3672 if (reg_src
== REG_X
)
3675 return ("mov __tmp_reg__,r26" CR_TAB
3676 "mov __zero_reg__,r27" CR_TAB
3677 "adiw r26,%o0" CR_TAB
3678 "st X+,__tmp_reg__" CR_TAB
3679 "st X+,__zero_reg__" CR_TAB
3682 "clr __zero_reg__" CR_TAB
3685 else if (reg_src
== REG_X
- 2)
3688 return ("mov __tmp_reg__,r26" CR_TAB
3689 "mov __zero_reg__,r27" CR_TAB
3690 "adiw r26,%o0" CR_TAB
3693 "st X+,__tmp_reg__" CR_TAB
3694 "st X,__zero_reg__" CR_TAB
3695 "clr __zero_reg__" CR_TAB
3699 return ("adiw r26,%o0" CR_TAB
3706 return *l
=4, ("std %A0,%A1" CR_TAB
3707 "std %B0,%B1" CR_TAB
3708 "std %C0,%C1" CR_TAB
3711 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
3712 return *l
=4, ("st %0,%D1" CR_TAB
3716 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
3717 return *l
=4, ("st %0,%A1" CR_TAB
3721 fatal_insn ("unknown move insn:",insn
);
3726 output_movsisf (rtx insn
, rtx operands
[], int *l
)
3729 rtx dest
= operands
[0];
3730 rtx src
= operands
[1];
3733 if (avr_mem_flash_p (src
)
3734 || avr_mem_flash_p (dest
))
3736 return avr_out_lpm (insn
, operands
, real_l
);
3742 gcc_assert (4 == GET_MODE_SIZE (GET_MODE (dest
)));
3745 if (REG_P (src
)) /* mov r,r */
3747 if (true_regnum (dest
) > true_regnum (src
))
3752 return ("movw %C0,%C1" CR_TAB
3756 return ("mov %D0,%D1" CR_TAB
3757 "mov %C0,%C1" CR_TAB
3758 "mov %B0,%B1" CR_TAB
3766 return ("movw %A0,%A1" CR_TAB
3770 return ("mov %A0,%A1" CR_TAB
3771 "mov %B0,%B1" CR_TAB
3772 "mov %C0,%C1" CR_TAB
3776 else if (CONSTANT_P (src
))
3778 return output_reload_insisf (operands
, NULL_RTX
, real_l
);
3780 else if (MEM_P (src
))
3781 return out_movsi_r_mr (insn
, operands
, real_l
); /* mov r,m */
3783 else if (MEM_P (dest
))
3787 if (src
== CONST0_RTX (GET_MODE (dest
)))
3788 operands
[1] = zero_reg_rtx
;
3790 templ
= out_movsi_mr_r (insn
, operands
, real_l
);
3793 output_asm_insn (templ
, operands
);
3798 fatal_insn ("invalid insn:", insn
);
3803 /* Handle loads of 24-bit types from memory to register. */
3806 avr_out_load_psi (rtx insn
, rtx
*op
, int *plen
)
3810 rtx base
= XEXP (src
, 0);
3811 int reg_dest
= true_regnum (dest
);
3812 int reg_base
= true_regnum (base
);
3816 if (reg_base
== REG_X
) /* (R26) */
3818 if (reg_dest
== REG_X
)
3819 /* "ld r26,-X" is undefined */
3820 return avr_asm_len ("adiw r26,2" CR_TAB
3822 "ld __tmp_reg__,-X" CR_TAB
3825 "mov r27,__tmp_reg__", op
, plen
, -6);
3828 avr_asm_len ("ld %A0,X+" CR_TAB
3830 "ld %C0,X", op
, plen
, -3);
3832 if (reg_dest
!= REG_X
- 2
3833 && !reg_unused_after (insn
, base
))
3835 avr_asm_len ("sbiw r26,2", op
, plen
, 1);
3841 else /* reg_base != REG_X */
3843 if (reg_dest
== reg_base
)
3844 return avr_asm_len ("ldd %C0,%1+2" CR_TAB
3845 "ldd __tmp_reg__,%1+1" CR_TAB
3847 "mov %B0,__tmp_reg__", op
, plen
, -4);
3849 return avr_asm_len ("ld %A0,%1" CR_TAB
3850 "ldd %B0,%1+1" CR_TAB
3851 "ldd %C0,%1+2", op
, plen
, -3);
3854 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
3856 int disp
= INTVAL (XEXP (base
, 1));
3858 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
3860 if (REGNO (XEXP (base
, 0)) != REG_Y
)
3861 fatal_insn ("incorrect insn:",insn
);
3863 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
3864 return avr_asm_len ("adiw r28,%o1-61" CR_TAB
3865 "ldd %A0,Y+61" CR_TAB
3866 "ldd %B0,Y+62" CR_TAB
3867 "ldd %C0,Y+63" CR_TAB
3868 "sbiw r28,%o1-61", op
, plen
, -5);
3870 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
3871 "sbci r29,hi8(-%o1)" CR_TAB
3873 "ldd %B0,Y+1" CR_TAB
3874 "ldd %C0,Y+2" CR_TAB
3875 "subi r28,lo8(%o1)" CR_TAB
3876 "sbci r29,hi8(%o1)", op
, plen
, -7);
3879 reg_base
= true_regnum (XEXP (base
, 0));
3880 if (reg_base
== REG_X
)
3883 if (reg_dest
== REG_X
)
3885 /* "ld r26,-X" is undefined */
3886 return avr_asm_len ("adiw r26,%o1+2" CR_TAB
3888 "ld __tmp_reg__,-X" CR_TAB
3891 "mov r27,__tmp_reg__", op
, plen
, -6);
3894 avr_asm_len ("adiw r26,%o1" CR_TAB
3897 "ld %C0,X", op
, plen
, -4);
3899 if (reg_dest
!= REG_W
3900 && !reg_unused_after (insn
, XEXP (base
, 0)))
3901 avr_asm_len ("sbiw r26,%o1+2", op
, plen
, 1);
3906 if (reg_dest
== reg_base
)
3907 return avr_asm_len ("ldd %C0,%C1" CR_TAB
3908 "ldd __tmp_reg__,%B1" CR_TAB
3909 "ldd %A0,%A1" CR_TAB
3910 "mov %B0,__tmp_reg__", op
, plen
, -4);
3912 return avr_asm_len ("ldd %A0,%A1" CR_TAB
3913 "ldd %B0,%B1" CR_TAB
3914 "ldd %C0,%C1", op
, plen
, -3);
3916 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
3917 return avr_asm_len ("ld %C0,%1" CR_TAB
3919 "ld %A0,%1", op
, plen
, -3);
3920 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
3921 return avr_asm_len ("ld %A0,%1" CR_TAB
3923 "ld %C0,%1", op
, plen
, -3);
3925 else if (CONSTANT_ADDRESS_P (base
))
3926 return avr_asm_len ("lds %A0,%m1" CR_TAB
3927 "lds %B0,%m1+1" CR_TAB
3928 "lds %C0,%m1+2", op
, plen
, -6);
3930 fatal_insn ("unknown move insn:",insn
);
3934 /* Handle store of 24-bit type from register or zero to memory. */
3937 avr_out_store_psi (rtx insn
, rtx
*op
, int *plen
)
3941 rtx base
= XEXP (dest
, 0);
3942 int reg_base
= true_regnum (base
);
3944 if (CONSTANT_ADDRESS_P (base
))
3945 return avr_asm_len ("sts %m0,%A1" CR_TAB
3946 "sts %m0+1,%B1" CR_TAB
3947 "sts %m0+2,%C1", op
, plen
, -6);
3949 if (reg_base
> 0) /* (r) */
3951 if (reg_base
== REG_X
) /* (R26) */
3953 gcc_assert (!reg_overlap_mentioned_p (base
, src
));
3955 avr_asm_len ("st %0+,%A1" CR_TAB
3957 "st %0,%C1", op
, plen
, -3);
3959 if (!reg_unused_after (insn
, base
))
3960 avr_asm_len ("sbiw r26,2", op
, plen
, 1);
3965 return avr_asm_len ("st %0,%A1" CR_TAB
3966 "std %0+1,%B1" CR_TAB
3967 "std %0+2,%C1", op
, plen
, -3);
3969 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
3971 int disp
= INTVAL (XEXP (base
, 1));
3972 reg_base
= REGNO (XEXP (base
, 0));
3974 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
3976 if (reg_base
!= REG_Y
)
3977 fatal_insn ("incorrect insn:",insn
);
3979 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
3980 return avr_asm_len ("adiw r28,%o0-61" CR_TAB
3981 "std Y+61,%A1" CR_TAB
3982 "std Y+62,%B1" CR_TAB
3983 "std Y+63,%C1" CR_TAB
3984 "sbiw r28,%o0-60", op
, plen
, -5);
3986 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
3987 "sbci r29,hi8(-%o0)" CR_TAB
3989 "std Y+1,%B1" CR_TAB
3990 "std Y+2,%C1" CR_TAB
3991 "subi r28,lo8(%o0)" CR_TAB
3992 "sbci r29,hi8(%o0)", op
, plen
, -7);
3994 if (reg_base
== REG_X
)
3997 gcc_assert (!reg_overlap_mentioned_p (XEXP (base
, 0), src
));
3999 avr_asm_len ("adiw r26,%o0" CR_TAB
4002 "st X,%C1", op
, plen
, -4);
4004 if (!reg_unused_after (insn
, XEXP (base
, 0)))
4005 avr_asm_len ("sbiw r26,%o0+2", op
, plen
, 1);
4010 return avr_asm_len ("std %A0,%A1" CR_TAB
4011 "std %B0,%B1" CR_TAB
4012 "std %C0,%C1", op
, plen
, -3);
4014 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
4015 return avr_asm_len ("st %0,%C1" CR_TAB
4017 "st %0,%A1", op
, plen
, -3);
4018 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
4019 return avr_asm_len ("st %0,%A1" CR_TAB
4021 "st %0,%C1", op
, plen
, -3);
4023 fatal_insn ("unknown move insn:",insn
);
4028 /* Move around 24-bit stuff. */
4031 avr_out_movpsi (rtx insn
, rtx
*op
, int *plen
)
4036 if (avr_mem_flash_p (src
)
4037 || avr_mem_flash_p (dest
))
4039 return avr_out_lpm (insn
, op
, plen
);
4042 if (register_operand (dest
, VOIDmode
))
4044 if (register_operand (src
, VOIDmode
)) /* mov r,r */
4046 if (true_regnum (dest
) > true_regnum (src
))
4048 avr_asm_len ("mov %C0,%C1", op
, plen
, -1);
4051 return avr_asm_len ("movw %A0,%A1", op
, plen
, 1);
4053 return avr_asm_len ("mov %B0,%B1" CR_TAB
4054 "mov %A0,%A1", op
, plen
, 2);
4059 avr_asm_len ("movw %A0,%A1", op
, plen
, -1);
4061 avr_asm_len ("mov %A0,%A1" CR_TAB
4062 "mov %B0,%B1", op
, plen
, -2);
4064 return avr_asm_len ("mov %C0,%C1", op
, plen
, 1);
4067 else if (CONSTANT_P (src
))
4069 return avr_out_reload_inpsi (op
, NULL_RTX
, plen
);
4071 else if (MEM_P (src
))
4072 return avr_out_load_psi (insn
, op
, plen
); /* mov r,m */
4074 else if (MEM_P (dest
))
4079 xop
[1] = src
== CONST0_RTX (GET_MODE (dest
)) ? zero_reg_rtx
: src
;
4081 return avr_out_store_psi (insn
, xop
, plen
);
4084 fatal_insn ("invalid insn:", insn
);
4090 out_movqi_mr_r (rtx insn
, rtx op
[], int *plen
)
4094 rtx x
= XEXP (dest
, 0);
4096 if (CONSTANT_ADDRESS_P (x
))
4098 return optimize
> 0 && io_address_operand (x
, QImode
)
4099 ? avr_asm_len ("out %i0,%1", op
, plen
, -1)
4100 : avr_asm_len ("sts %m0,%1", op
, plen
, -2);
4102 else if (GET_CODE (x
) == PLUS
4103 && REG_P (XEXP (x
, 0))
4104 && CONST_INT_P (XEXP (x
, 1)))
4106 /* memory access by reg+disp */
4108 int disp
= INTVAL (XEXP (x
, 1));
4110 if (disp
- GET_MODE_SIZE (GET_MODE (dest
)) >= 63)
4112 if (REGNO (XEXP (x
, 0)) != REG_Y
)
4113 fatal_insn ("incorrect insn:",insn
);
4115 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
4116 return avr_asm_len ("adiw r28,%o0-63" CR_TAB
4117 "std Y+63,%1" CR_TAB
4118 "sbiw r28,%o0-63", op
, plen
, -3);
4120 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
4121 "sbci r29,hi8(-%o0)" CR_TAB
4123 "subi r28,lo8(%o0)" CR_TAB
4124 "sbci r29,hi8(%o0)", op
, plen
, -5);
4126 else if (REGNO (XEXP (x
,0)) == REG_X
)
4128 if (reg_overlap_mentioned_p (src
, XEXP (x
, 0)))
4130 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
4131 "adiw r26,%o0" CR_TAB
4132 "st X,__tmp_reg__", op
, plen
, -3);
4136 avr_asm_len ("adiw r26,%o0" CR_TAB
4137 "st X,%1", op
, plen
, -2);
4140 if (!reg_unused_after (insn
, XEXP (x
,0)))
4141 avr_asm_len ("sbiw r26,%o0", op
, plen
, 1);
4146 return avr_asm_len ("std %0,%1", op
, plen
, -1);
4149 return avr_asm_len ("st %0,%1", op
, plen
, -1);
4153 /* Helper for the next function for XMEGA. It does the same
4154 but with low byte first. */
4157 avr_out_movhi_mr_r_xmega (rtx insn
, rtx op
[], int *plen
)
4161 rtx base
= XEXP (dest
, 0);
4162 int reg_base
= true_regnum (base
);
4163 int reg_src
= true_regnum (src
);
4165 /* "volatile" forces writing low byte first, even if less efficient,
4166 for correct operation with 16-bit I/O registers like SP. */
4167 int mem_volatile_p
= MEM_VOLATILE_P (dest
);
4169 if (CONSTANT_ADDRESS_P (base
))
4170 return optimize
> 0 && io_address_operand (base
, HImode
)
4171 ? avr_asm_len ("out %i0,%A1" CR_TAB
4172 "out %i0+1,%B1", op
, plen
, -2)
4174 : avr_asm_len ("sts %m0,%A1" CR_TAB
4175 "sts %m0+1,%B1", op
, plen
, -4);
4179 if (reg_base
!= REG_X
)
4180 return avr_asm_len ("st %0,%A1" CR_TAB
4181 "std %0+1,%B1", op
, plen
, -2);
4183 if (reg_src
== REG_X
)
4184 /* "st X+,r26" and "st -X,r26" are undefined. */
4185 avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
4188 "st X,__tmp_reg__", op
, plen
, -4);
4190 avr_asm_len ("st X+,%A1" CR_TAB
4191 "st X,%B1", op
, plen
, -2);
4193 return reg_unused_after (insn
, base
)
4195 : avr_asm_len ("sbiw r26,1", op
, plen
, 1);
4197 else if (GET_CODE (base
) == PLUS
)
4199 int disp
= INTVAL (XEXP (base
, 1));
4200 reg_base
= REGNO (XEXP (base
, 0));
4201 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
4203 if (reg_base
!= REG_Y
)
4204 fatal_insn ("incorrect insn:",insn
);
4206 return disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
))
4207 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
4208 "std Y+62,%A1" CR_TAB
4209 "std Y+63,%B1" CR_TAB
4210 "sbiw r28,%o0-62", op
, plen
, -4)
4212 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
4213 "sbci r29,hi8(-%o0)" CR_TAB
4215 "std Y+1,%B1" CR_TAB
4216 "subi r28,lo8(%o0)" CR_TAB
4217 "sbci r29,hi8(%o0)", op
, plen
, -6);
4220 if (reg_base
!= REG_X
)
4221 return avr_asm_len ("std %A0,%A1" CR_TAB
4222 "std %B0,%B1", op
, plen
, -2);
4224 return reg_src
== REG_X
4225 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
4226 "mov __zero_reg__,r27" CR_TAB
4227 "adiw r26,%o0" CR_TAB
4228 "st X+,__tmp_reg__" CR_TAB
4229 "st X,__zero_reg__" CR_TAB
4230 "clr __zero_reg__" CR_TAB
4231 "sbiw r26,%o0+1", op
, plen
, -7)
4233 : avr_asm_len ("adiw r26,%o0" CR_TAB
4236 "sbiw r26,%o0+1", op
, plen
, -4);
4238 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
4240 if (!mem_volatile_p
)
4241 return avr_asm_len ("st %0,%B1" CR_TAB
4242 "st %0,%A1", op
, plen
, -2);
4244 return REGNO (XEXP (base
, 0)) == REG_X
4245 ? avr_asm_len ("sbiw r26,2" CR_TAB
4248 "sbiw r26,1", op
, plen
, -4)
4250 : avr_asm_len ("sbiw %r0,2" CR_TAB
4252 "std %p0+1,%B1", op
, plen
, -3);
4254 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
4256 return avr_asm_len ("st %0,%A1" CR_TAB
4257 "st %0,%B1", op
, plen
, -2);
4260 fatal_insn ("unknown move insn:",insn
);
4266 out_movhi_mr_r (rtx insn
, rtx op
[], int *plen
)
4270 rtx base
= XEXP (dest
, 0);
4271 int reg_base
= true_regnum (base
);
4272 int reg_src
= true_regnum (src
);
4275 /* "volatile" forces writing high-byte first (no-xmega) resp.
4276 low-byte first (xmega) even if less efficient, for correct
4277 operation with 16-bit I/O registers like. */
4280 return avr_out_movhi_mr_r_xmega (insn
, op
, plen
);
4282 mem_volatile_p
= MEM_VOLATILE_P (dest
);
4284 if (CONSTANT_ADDRESS_P (base
))
4285 return optimize
> 0 && io_address_operand (base
, HImode
)
4286 ? avr_asm_len ("out %i0+1,%B1" CR_TAB
4287 "out %i0,%A1", op
, plen
, -2)
4289 : avr_asm_len ("sts %m0+1,%B1" CR_TAB
4290 "sts %m0,%A1", op
, plen
, -4);
4294 if (reg_base
!= REG_X
)
4295 return avr_asm_len ("std %0+1,%B1" CR_TAB
4296 "st %0,%A1", op
, plen
, -2);
4298 if (reg_src
== REG_X
)
4299 /* "st X+,r26" and "st -X,r26" are undefined. */
4300 return !mem_volatile_p
&& reg_unused_after (insn
, src
)
4301 ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
4304 "st X,__tmp_reg__", op
, plen
, -4)
4306 : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
4308 "st X,__tmp_reg__" CR_TAB
4310 "st X,r26", op
, plen
, -5);
4312 return !mem_volatile_p
&& reg_unused_after (insn
, base
)
4313 ? avr_asm_len ("st X+,%A1" CR_TAB
4314 "st X,%B1", op
, plen
, -2)
4315 : avr_asm_len ("adiw r26,1" CR_TAB
4317 "st -X,%A1", op
, plen
, -3);
4319 else if (GET_CODE (base
) == PLUS
)
4321 int disp
= INTVAL (XEXP (base
, 1));
4322 reg_base
= REGNO (XEXP (base
, 0));
4323 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
4325 if (reg_base
!= REG_Y
)
4326 fatal_insn ("incorrect insn:",insn
);
4328 return disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
))
4329 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
4330 "std Y+63,%B1" CR_TAB
4331 "std Y+62,%A1" CR_TAB
4332 "sbiw r28,%o0-62", op
, plen
, -4)
4334 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
4335 "sbci r29,hi8(-%o0)" CR_TAB
4336 "std Y+1,%B1" CR_TAB
4338 "subi r28,lo8(%o0)" CR_TAB
4339 "sbci r29,hi8(%o0)", op
, plen
, -6);
4342 if (reg_base
!= REG_X
)
4343 return avr_asm_len ("std %B0,%B1" CR_TAB
4344 "std %A0,%A1", op
, plen
, -2);
4346 return reg_src
== REG_X
4347 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
4348 "mov __zero_reg__,r27" CR_TAB
4349 "adiw r26,%o0+1" CR_TAB
4350 "st X,__zero_reg__" CR_TAB
4351 "st -X,__tmp_reg__" CR_TAB
4352 "clr __zero_reg__" CR_TAB
4353 "sbiw r26,%o0", op
, plen
, -7)
4355 : avr_asm_len ("adiw r26,%o0+1" CR_TAB
4358 "sbiw r26,%o0", op
, plen
, -4);
4360 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
4362 return avr_asm_len ("st %0,%B1" CR_TAB
4363 "st %0,%A1", op
, plen
, -2);
4365 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
4367 if (!mem_volatile_p
)
4368 return avr_asm_len ("st %0,%A1" CR_TAB
4369 "st %0,%B1", op
, plen
, -2);
4371 return REGNO (XEXP (base
, 0)) == REG_X
4372 ? avr_asm_len ("adiw r26,1" CR_TAB
4375 "adiw r26,2", op
, plen
, -4)
4377 : avr_asm_len ("std %p0+1,%B1" CR_TAB
4379 "adiw %r0,2", op
, plen
, -3);
4381 fatal_insn ("unknown move insn:",insn
);
4385 /* Return 1 if frame pointer for current function required. */
4388 avr_frame_pointer_required_p (void)
4390 return (cfun
->calls_alloca
4391 || cfun
->calls_setjmp
4392 || cfun
->has_nonlocal_label
4393 || crtl
->args
.info
.nregs
== 0
4394 || get_frame_size () > 0);
4397 /* Returns the condition of compare insn INSN, or UNKNOWN. */
4400 compare_condition (rtx insn
)
4402 rtx next
= next_real_insn (insn
);
4404 if (next
&& JUMP_P (next
))
4406 rtx pat
= PATTERN (next
);
4407 rtx src
= SET_SRC (pat
);
4409 if (IF_THEN_ELSE
== GET_CODE (src
))
4410 return GET_CODE (XEXP (src
, 0));
4417 /* Returns true iff INSN is a tst insn that only tests the sign. */
4420 compare_sign_p (rtx insn
)
4422 RTX_CODE cond
= compare_condition (insn
);
4423 return (cond
== GE
|| cond
== LT
);
4427 /* Returns true iff the next insn is a JUMP_INSN with a condition
4428 that needs to be swapped (GT, GTU, LE, LEU). */
4431 compare_diff_p (rtx insn
)
4433 RTX_CODE cond
= compare_condition (insn
);
4434 return (cond
== GT
|| cond
== GTU
|| cond
== LE
|| cond
== LEU
) ? cond
: 0;
4437 /* Returns true iff INSN is a compare insn with the EQ or NE condition. */
4440 compare_eq_p (rtx insn
)
4442 RTX_CODE cond
= compare_condition (insn
);
4443 return (cond
== EQ
|| cond
== NE
);
4447 /* Output compare instruction
4449 compare (XOP[0], XOP[1])
4451 for a register XOP[0] and a compile-time constant XOP[1]. Return "".
4452 XOP[2] is an 8-bit scratch register as needed.
4454 PLEN == NULL: Output instructions.
4455 PLEN != NULL: Set *PLEN to the length (in words) of the sequence.
4456 Don't output anything. */
4459 avr_out_compare (rtx insn
, rtx
*xop
, int *plen
)
4461 /* Register to compare and value to compare against. */
4465 /* MODE of the comparison. */
4466 enum machine_mode mode
;
4468 /* Number of bytes to operate on. */
4469 int i
, n_bytes
= GET_MODE_SIZE (GET_MODE (xreg
));
4471 /* Value (0..0xff) held in clobber register xop[2] or -1 if unknown. */
4472 int clobber_val
= -1;
4474 /* Map fixed mode operands to integer operands with the same binary
4475 representation. They are easier to handle in the remainder. */
4477 if (CONST_FIXED_P (xval
))
4479 xreg
= avr_to_int_mode (xop
[0]);
4480 xval
= avr_to_int_mode (xop
[1]);
4483 mode
= GET_MODE (xreg
);
4485 gcc_assert (REG_P (xreg
));
4486 gcc_assert ((CONST_INT_P (xval
) && n_bytes
<= 4)
4487 || (const_double_operand (xval
, VOIDmode
) && n_bytes
== 8));
4492 /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
4493 against 0 by ORing the bytes. This is one instruction shorter.
4494 Notice that 64-bit comparisons are always against reg:ALL8 18 (ACC_A)
4495 and therefore don't use this. */
4497 if (!test_hard_reg_class (LD_REGS
, xreg
)
4498 && compare_eq_p (insn
)
4499 && reg_unused_after (insn
, xreg
))
4501 if (xval
== const1_rtx
)
4503 avr_asm_len ("dec %A0" CR_TAB
4504 "or %A0,%B0", xop
, plen
, 2);
4507 avr_asm_len ("or %A0,%C0", xop
, plen
, 1);
4510 avr_asm_len ("or %A0,%D0", xop
, plen
, 1);
4514 else if (xval
== constm1_rtx
)
4517 avr_asm_len ("and %A0,%D0", xop
, plen
, 1);
4520 avr_asm_len ("and %A0,%C0", xop
, plen
, 1);
4522 return avr_asm_len ("and %A0,%B0" CR_TAB
4523 "com %A0", xop
, plen
, 2);
4527 for (i
= 0; i
< n_bytes
; i
++)
4529 /* We compare byte-wise. */
4530 rtx reg8
= simplify_gen_subreg (QImode
, xreg
, mode
, i
);
4531 rtx xval8
= simplify_gen_subreg (QImode
, xval
, mode
, i
);
4533 /* 8-bit value to compare with this byte. */
4534 unsigned int val8
= UINTVAL (xval8
) & GET_MODE_MASK (QImode
);
4536 /* Registers R16..R31 can operate with immediate. */
4537 bool ld_reg_p
= test_hard_reg_class (LD_REGS
, reg8
);
4540 xop
[1] = gen_int_mode (val8
, QImode
);
4542 /* Word registers >= R24 can use SBIW/ADIW with 0..63. */
4545 && test_hard_reg_class (ADDW_REGS
, reg8
))
4547 int val16
= trunc_int_for_mode (INTVAL (xval
), HImode
);
4549 if (IN_RANGE (val16
, 0, 63)
4551 || reg_unused_after (insn
, xreg
)))
4553 avr_asm_len ("sbiw %0,%1", xop
, plen
, 1);
4559 && IN_RANGE (val16
, -63, -1)
4560 && compare_eq_p (insn
)
4561 && reg_unused_after (insn
, xreg
))
4563 return avr_asm_len ("adiw %0,%n1", xop
, plen
, 1);
4567 /* Comparing against 0 is easy. */
4572 ? "cp %0,__zero_reg__"
4573 : "cpc %0,__zero_reg__", xop
, plen
, 1);
4577 /* Upper registers can compare and subtract-with-carry immediates.
4578 Notice that compare instructions do the same as respective subtract
4579 instruction; the only difference is that comparisons don't write
4580 the result back to the target register. */
4586 avr_asm_len ("cpi %0,%1", xop
, plen
, 1);
4589 else if (reg_unused_after (insn
, xreg
))
4591 avr_asm_len ("sbci %0,%1", xop
, plen
, 1);
4596 /* Must load the value into the scratch register. */
4598 gcc_assert (REG_P (xop
[2]));
4600 if (clobber_val
!= (int) val8
)
4601 avr_asm_len ("ldi %2,%1", xop
, plen
, 1);
4602 clobber_val
= (int) val8
;
4606 : "cpc %0,%2", xop
, plen
, 1);
4613 /* Prepare operands of compare_const_di2 to be used with avr_out_compare. */
4616 avr_out_compare64 (rtx insn
, rtx
*op
, int *plen
)
4620 xop
[0] = gen_rtx_REG (DImode
, 18);
4624 return avr_out_compare (insn
, xop
, plen
);
4627 /* Output test instruction for HImode. */
4630 avr_out_tsthi (rtx insn
, rtx
*op
, int *plen
)
4632 if (compare_sign_p (insn
))
4634 avr_asm_len ("tst %B0", op
, plen
, -1);
4636 else if (reg_unused_after (insn
, op
[0])
4637 && compare_eq_p (insn
))
4639 /* Faster than sbiw if we can clobber the operand. */
4640 avr_asm_len ("or %A0,%B0", op
, plen
, -1);
4644 avr_out_compare (insn
, op
, plen
);
4651 /* Output test instruction for PSImode. */
4654 avr_out_tstpsi (rtx insn
, rtx
*op
, int *plen
)
4656 if (compare_sign_p (insn
))
4658 avr_asm_len ("tst %C0", op
, plen
, -1);
4660 else if (reg_unused_after (insn
, op
[0])
4661 && compare_eq_p (insn
))
4663 /* Faster than sbiw if we can clobber the operand. */
4664 avr_asm_len ("or %A0,%B0" CR_TAB
4665 "or %A0,%C0", op
, plen
, -2);
4669 avr_out_compare (insn
, op
, plen
);
4676 /* Output test instruction for SImode. */
4679 avr_out_tstsi (rtx insn
, rtx
*op
, int *plen
)
4681 if (compare_sign_p (insn
))
4683 avr_asm_len ("tst %D0", op
, plen
, -1);
4685 else if (reg_unused_after (insn
, op
[0])
4686 && compare_eq_p (insn
))
4688 /* Faster than sbiw if we can clobber the operand. */
4689 avr_asm_len ("or %A0,%B0" CR_TAB
4691 "or %A0,%D0", op
, plen
, -3);
4695 avr_out_compare (insn
, op
, plen
);
4702 /* Generate asm equivalent for various shifts. This only handles cases
4703 that are not already carefully hand-optimized in ?sh??i3_out.
4705 OPERANDS[0] resp. %0 in TEMPL is the operand to be shifted.
4706 OPERANDS[2] is the shift count as CONST_INT, MEM or REG.
4707 OPERANDS[3] is a QImode scratch register from LD regs if
4708 available and SCRATCH, otherwise (no scratch available)
4710 TEMPL is an assembler template that shifts by one position.
4711 T_LEN is the length of this template. */
4714 out_shift_with_cnt (const char *templ
, rtx insn
, rtx operands
[],
4715 int *plen
, int t_len
)
4717 bool second_label
= true;
4718 bool saved_in_tmp
= false;
4719 bool use_zero_reg
= false;
4722 op
[0] = operands
[0];
4723 op
[1] = operands
[1];
4724 op
[2] = operands
[2];
4725 op
[3] = operands
[3];
4730 if (CONST_INT_P (operands
[2]))
4732 bool scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
4733 && REG_P (operands
[3]));
4734 int count
= INTVAL (operands
[2]);
4735 int max_len
= 10; /* If larger than this, always use a loop. */
4740 if (count
< 8 && !scratch
)
4741 use_zero_reg
= true;
4744 max_len
= t_len
+ (scratch
? 3 : (use_zero_reg
? 4 : 5));
4746 if (t_len
* count
<= max_len
)
4748 /* Output shifts inline with no loop - faster. */
4751 avr_asm_len (templ
, op
, plen
, t_len
);
4758 avr_asm_len ("ldi %3,%2", op
, plen
, 1);
4760 else if (use_zero_reg
)
4762 /* Hack to save one word: use __zero_reg__ as loop counter.
4763 Set one bit, then shift in a loop until it is 0 again. */
4765 op
[3] = zero_reg_rtx
;
4767 avr_asm_len ("set" CR_TAB
4768 "bld %3,%2-1", op
, plen
, 2);
4772 /* No scratch register available, use one from LD_REGS (saved in
4773 __tmp_reg__) that doesn't overlap with registers to shift. */
4775 op
[3] = all_regs_rtx
[((REGNO (op
[0]) - 1) & 15) + 16];
4776 op
[4] = tmp_reg_rtx
;
4777 saved_in_tmp
= true;
4779 avr_asm_len ("mov %4,%3" CR_TAB
4780 "ldi %3,%2", op
, plen
, 2);
4783 second_label
= false;
4785 else if (MEM_P (op
[2]))
4789 op_mov
[0] = op
[3] = tmp_reg_rtx
;
4792 out_movqi_r_mr (insn
, op_mov
, plen
);
4794 else if (register_operand (op
[2], QImode
))
4798 if (!reg_unused_after (insn
, op
[2])
4799 || reg_overlap_mentioned_p (op
[0], op
[2]))
4801 op
[3] = tmp_reg_rtx
;
4802 avr_asm_len ("mov %3,%2", op
, plen
, 1);
4806 fatal_insn ("bad shift insn:", insn
);
4809 avr_asm_len ("rjmp 2f", op
, plen
, 1);
4811 avr_asm_len ("1:", op
, plen
, 0);
4812 avr_asm_len (templ
, op
, plen
, t_len
);
4815 avr_asm_len ("2:", op
, plen
, 0);
4817 avr_asm_len (use_zero_reg
? "lsr %3" : "dec %3", op
, plen
, 1);
4818 avr_asm_len (second_label
? "brpl 1b" : "brne 1b", op
, plen
, 1);
4821 avr_asm_len ("mov %3,%4", op
, plen
, 1);
4825 /* 8bit shift left ((char)x << i) */
4828 ashlqi3_out (rtx insn
, rtx operands
[], int *len
)
4830 if (GET_CODE (operands
[2]) == CONST_INT
)
4837 switch (INTVAL (operands
[2]))
4840 if (INTVAL (operands
[2]) < 8)
4852 return ("lsl %0" CR_TAB
4857 return ("lsl %0" CR_TAB
4862 if (test_hard_reg_class (LD_REGS
, operands
[0]))
4865 return ("swap %0" CR_TAB
4869 return ("lsl %0" CR_TAB
4875 if (test_hard_reg_class (LD_REGS
, operands
[0]))
4878 return ("swap %0" CR_TAB
4883 return ("lsl %0" CR_TAB
4890 if (test_hard_reg_class (LD_REGS
, operands
[0]))
4893 return ("swap %0" CR_TAB
4899 return ("lsl %0" CR_TAB
4908 return ("ror %0" CR_TAB
4913 else if (CONSTANT_P (operands
[2]))
4914 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
4916 out_shift_with_cnt ("lsl %0",
4917 insn
, operands
, len
, 1);
4922 /* 16bit shift left ((short)x << i) */
4925 ashlhi3_out (rtx insn
, rtx operands
[], int *len
)
4927 if (GET_CODE (operands
[2]) == CONST_INT
)
4929 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
4930 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
4937 switch (INTVAL (operands
[2]))
4940 if (INTVAL (operands
[2]) < 16)
4944 return ("clr %B0" CR_TAB
4948 if (optimize_size
&& scratch
)
4953 return ("swap %A0" CR_TAB
4955 "andi %B0,0xf0" CR_TAB
4956 "eor %B0,%A0" CR_TAB
4957 "andi %A0,0xf0" CR_TAB
4963 return ("swap %A0" CR_TAB
4965 "ldi %3,0xf0" CR_TAB
4967 "eor %B0,%A0" CR_TAB
4971 break; /* optimize_size ? 6 : 8 */
4975 break; /* scratch ? 5 : 6 */
4979 return ("lsl %A0" CR_TAB
4983 "andi %B0,0xf0" CR_TAB
4984 "eor %B0,%A0" CR_TAB
4985 "andi %A0,0xf0" CR_TAB
4991 return ("lsl %A0" CR_TAB
4995 "ldi %3,0xf0" CR_TAB
4997 "eor %B0,%A0" CR_TAB
5005 break; /* scratch ? 5 : 6 */
5007 return ("clr __tmp_reg__" CR_TAB
5010 "ror __tmp_reg__" CR_TAB
5013 "ror __tmp_reg__" CR_TAB
5014 "mov %B0,%A0" CR_TAB
5015 "mov %A0,__tmp_reg__");
5019 return ("lsr %B0" CR_TAB
5020 "mov %B0,%A0" CR_TAB
5026 return *len
= 2, ("mov %B0,%A1" CR_TAB
5031 return ("mov %B0,%A0" CR_TAB
5037 return ("mov %B0,%A0" CR_TAB
5044 return ("mov %B0,%A0" CR_TAB
5054 return ("mov %B0,%A0" CR_TAB
5062 return ("mov %B0,%A0" CR_TAB
5065 "ldi %3,0xf0" CR_TAB
5069 return ("mov %B0,%A0" CR_TAB
5080 return ("mov %B0,%A0" CR_TAB
5086 if (AVR_HAVE_MUL
&& scratch
)
5089 return ("ldi %3,0x20" CR_TAB
5093 "clr __zero_reg__");
5095 if (optimize_size
&& scratch
)
5100 return ("mov %B0,%A0" CR_TAB
5104 "ldi %3,0xe0" CR_TAB
5110 return ("set" CR_TAB
5115 "clr __zero_reg__");
5118 return ("mov %B0,%A0" CR_TAB
5127 if (AVR_HAVE_MUL
&& ldi_ok
)
5130 return ("ldi %B0,0x40" CR_TAB
5131 "mul %A0,%B0" CR_TAB
5134 "clr __zero_reg__");
5136 if (AVR_HAVE_MUL
&& scratch
)
5139 return ("ldi %3,0x40" CR_TAB
5143 "clr __zero_reg__");
5145 if (optimize_size
&& ldi_ok
)
5148 return ("mov %B0,%A0" CR_TAB
5149 "ldi %A0,6" "\n1:\t"
5154 if (optimize_size
&& scratch
)
5157 return ("clr %B0" CR_TAB
5166 return ("clr %B0" CR_TAB
5173 out_shift_with_cnt ("lsl %A0" CR_TAB
5174 "rol %B0", insn
, operands
, len
, 2);
5179 /* 24-bit shift left */
5182 avr_out_ashlpsi3 (rtx insn
, rtx
*op
, int *plen
)
5187 if (CONST_INT_P (op
[2]))
5189 switch (INTVAL (op
[2]))
5192 if (INTVAL (op
[2]) < 24)
5195 return avr_asm_len ("clr %A0" CR_TAB
5197 "clr %C0", op
, plen
, 3);
5201 int reg0
= REGNO (op
[0]);
5202 int reg1
= REGNO (op
[1]);
5205 return avr_asm_len ("mov %C0,%B1" CR_TAB
5206 "mov %B0,%A1" CR_TAB
5207 "clr %A0", op
, plen
, 3);
5209 return avr_asm_len ("clr %A0" CR_TAB
5210 "mov %B0,%A1" CR_TAB
5211 "mov %C0,%B1", op
, plen
, 3);
5216 int reg0
= REGNO (op
[0]);
5217 int reg1
= REGNO (op
[1]);
5219 if (reg0
+ 2 != reg1
)
5220 avr_asm_len ("mov %C0,%A0", op
, plen
, 1);
5222 return avr_asm_len ("clr %B0" CR_TAB
5223 "clr %A0", op
, plen
, 2);
5227 return avr_asm_len ("clr %C0" CR_TAB
5231 "clr %A0", op
, plen
, 5);
5235 out_shift_with_cnt ("lsl %A0" CR_TAB
5237 "rol %C0", insn
, op
, plen
, 3);
5242 /* 32bit shift left ((long)x << i) */
5245 ashlsi3_out (rtx insn
, rtx operands
[], int *len
)
5247 if (GET_CODE (operands
[2]) == CONST_INT
)
5255 switch (INTVAL (operands
[2]))
5258 if (INTVAL (operands
[2]) < 32)
5262 return *len
= 3, ("clr %D0" CR_TAB
5266 return ("clr %D0" CR_TAB
5273 int reg0
= true_regnum (operands
[0]);
5274 int reg1
= true_regnum (operands
[1]);
5277 return ("mov %D0,%C1" CR_TAB
5278 "mov %C0,%B1" CR_TAB
5279 "mov %B0,%A1" CR_TAB
5282 return ("clr %A0" CR_TAB
5283 "mov %B0,%A1" CR_TAB
5284 "mov %C0,%B1" CR_TAB
5290 int reg0
= true_regnum (operands
[0]);
5291 int reg1
= true_regnum (operands
[1]);
5292 if (reg0
+ 2 == reg1
)
5293 return *len
= 2, ("clr %B0" CR_TAB
5296 return *len
= 3, ("movw %C0,%A1" CR_TAB
5300 return *len
= 4, ("mov %C0,%A1" CR_TAB
5301 "mov %D0,%B1" CR_TAB
5308 return ("mov %D0,%A1" CR_TAB
5315 return ("clr %D0" CR_TAB
5324 out_shift_with_cnt ("lsl %A0" CR_TAB
5327 "rol %D0", insn
, operands
, len
, 4);
5331 /* 8bit arithmetic shift right ((signed char)x >> i) */
5334 ashrqi3_out (rtx insn
, rtx operands
[], int *len
)
5336 if (GET_CODE (operands
[2]) == CONST_INT
)
5343 switch (INTVAL (operands
[2]))
5351 return ("asr %0" CR_TAB
5356 return ("asr %0" CR_TAB
5362 return ("asr %0" CR_TAB
5369 return ("asr %0" CR_TAB
5377 return ("bst %0,6" CR_TAB
5383 if (INTVAL (operands
[2]) < 8)
5390 return ("lsl %0" CR_TAB
5394 else if (CONSTANT_P (operands
[2]))
5395 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
5397 out_shift_with_cnt ("asr %0",
5398 insn
, operands
, len
, 1);
5403 /* 16bit arithmetic shift right ((signed short)x >> i) */
5406 ashrhi3_out (rtx insn
, rtx operands
[], int *len
)
5408 if (GET_CODE (operands
[2]) == CONST_INT
)
5410 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
5411 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
5418 switch (INTVAL (operands
[2]))
5422 /* XXX try to optimize this too? */
5427 break; /* scratch ? 5 : 6 */
5429 return ("mov __tmp_reg__,%A0" CR_TAB
5430 "mov %A0,%B0" CR_TAB
5431 "lsl __tmp_reg__" CR_TAB
5433 "sbc %B0,%B0" CR_TAB
5434 "lsl __tmp_reg__" CR_TAB
5440 return ("lsl %A0" CR_TAB
5441 "mov %A0,%B0" CR_TAB
5447 int reg0
= true_regnum (operands
[0]);
5448 int reg1
= true_regnum (operands
[1]);
5451 return *len
= 3, ("mov %A0,%B0" CR_TAB
5455 return *len
= 4, ("mov %A0,%B1" CR_TAB
5463 return ("mov %A0,%B0" CR_TAB
5465 "sbc %B0,%B0" CR_TAB
5470 return ("mov %A0,%B0" CR_TAB
5472 "sbc %B0,%B0" CR_TAB
5477 if (AVR_HAVE_MUL
&& ldi_ok
)
5480 return ("ldi %A0,0x20" CR_TAB
5481 "muls %B0,%A0" CR_TAB
5483 "sbc %B0,%B0" CR_TAB
5484 "clr __zero_reg__");
5486 if (optimize_size
&& scratch
)
5489 return ("mov %A0,%B0" CR_TAB
5491 "sbc %B0,%B0" CR_TAB
5497 if (AVR_HAVE_MUL
&& ldi_ok
)
5500 return ("ldi %A0,0x10" CR_TAB
5501 "muls %B0,%A0" CR_TAB
5503 "sbc %B0,%B0" CR_TAB
5504 "clr __zero_reg__");
5506 if (optimize_size
&& scratch
)
5509 return ("mov %A0,%B0" CR_TAB
5511 "sbc %B0,%B0" CR_TAB
5518 if (AVR_HAVE_MUL
&& ldi_ok
)
5521 return ("ldi %A0,0x08" CR_TAB
5522 "muls %B0,%A0" CR_TAB
5524 "sbc %B0,%B0" CR_TAB
5525 "clr __zero_reg__");
5528 break; /* scratch ? 5 : 7 */
5530 return ("mov %A0,%B0" CR_TAB
5532 "sbc %B0,%B0" CR_TAB
5541 return ("lsl %B0" CR_TAB
5542 "sbc %A0,%A0" CR_TAB
5544 "mov %B0,%A0" CR_TAB
5548 if (INTVAL (operands
[2]) < 16)
5554 return *len
= 3, ("lsl %B0" CR_TAB
5555 "sbc %A0,%A0" CR_TAB
5560 out_shift_with_cnt ("asr %B0" CR_TAB
5561 "ror %A0", insn
, operands
, len
, 2);
5566 /* 24-bit arithmetic shift right */
5569 avr_out_ashrpsi3 (rtx insn
, rtx
*op
, int *plen
)
5571 int dest
= REGNO (op
[0]);
5572 int src
= REGNO (op
[1]);
5574 if (CONST_INT_P (op
[2]))
5579 switch (INTVAL (op
[2]))
5583 return avr_asm_len ("mov %A0,%B1" CR_TAB
5584 "mov %B0,%C1" CR_TAB
5587 "dec %C0", op
, plen
, 5);
5589 return avr_asm_len ("clr %C0" CR_TAB
5592 "mov %B0,%C1" CR_TAB
5593 "mov %A0,%B1", op
, plen
, 5);
5596 if (dest
!= src
+ 2)
5597 avr_asm_len ("mov %A0,%C1", op
, plen
, 1);
5599 return avr_asm_len ("clr %B0" CR_TAB
5602 "mov %C0,%B0", op
, plen
, 4);
5605 if (INTVAL (op
[2]) < 24)
5611 return avr_asm_len ("lsl %C0" CR_TAB
5612 "sbc %A0,%A0" CR_TAB
5613 "mov %B0,%A0" CR_TAB
5614 "mov %C0,%A0", op
, plen
, 4);
5618 out_shift_with_cnt ("asr %C0" CR_TAB
5620 "ror %A0", insn
, op
, plen
, 3);
5625 /* 32-bit arithmetic shift right ((signed long)x >> i) */
5628 ashrsi3_out (rtx insn
, rtx operands
[], int *len
)
5630 if (GET_CODE (operands
[2]) == CONST_INT
)
5638 switch (INTVAL (operands
[2]))
5642 int reg0
= true_regnum (operands
[0]);
5643 int reg1
= true_regnum (operands
[1]);
5646 return ("mov %A0,%B1" CR_TAB
5647 "mov %B0,%C1" CR_TAB
5648 "mov %C0,%D1" CR_TAB
5653 return ("clr %D0" CR_TAB
5656 "mov %C0,%D1" CR_TAB
5657 "mov %B0,%C1" CR_TAB
5663 int reg0
= true_regnum (operands
[0]);
5664 int reg1
= true_regnum (operands
[1]);
5666 if (reg0
== reg1
+ 2)
5667 return *len
= 4, ("clr %D0" CR_TAB
5672 return *len
= 5, ("movw %A0,%C1" CR_TAB
5678 return *len
= 6, ("mov %B0,%D1" CR_TAB
5679 "mov %A0,%C1" CR_TAB
5687 return *len
= 6, ("mov %A0,%D1" CR_TAB
5691 "mov %B0,%D0" CR_TAB
5695 if (INTVAL (operands
[2]) < 32)
5702 return *len
= 4, ("lsl %D0" CR_TAB
5703 "sbc %A0,%A0" CR_TAB
5704 "mov %B0,%A0" CR_TAB
5707 return *len
= 5, ("lsl %D0" CR_TAB
5708 "sbc %A0,%A0" CR_TAB
5709 "mov %B0,%A0" CR_TAB
5710 "mov %C0,%A0" CR_TAB
5715 out_shift_with_cnt ("asr %D0" CR_TAB
5718 "ror %A0", insn
, operands
, len
, 4);
5722 /* 8-bit logic shift right ((unsigned char)x >> i) */
5725 lshrqi3_out (rtx insn
, rtx operands
[], int *len
)
5727 if (GET_CODE (operands
[2]) == CONST_INT
)
5734 switch (INTVAL (operands
[2]))
5737 if (INTVAL (operands
[2]) < 8)
5749 return ("lsr %0" CR_TAB
5753 return ("lsr %0" CR_TAB
5758 if (test_hard_reg_class (LD_REGS
, operands
[0]))
5761 return ("swap %0" CR_TAB
5765 return ("lsr %0" CR_TAB
5771 if (test_hard_reg_class (LD_REGS
, operands
[0]))
5774 return ("swap %0" CR_TAB
5779 return ("lsr %0" CR_TAB
5786 if (test_hard_reg_class (LD_REGS
, operands
[0]))
5789 return ("swap %0" CR_TAB
5795 return ("lsr %0" CR_TAB
5804 return ("rol %0" CR_TAB
5809 else if (CONSTANT_P (operands
[2]))
5810 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
5812 out_shift_with_cnt ("lsr %0",
5813 insn
, operands
, len
, 1);
5817 /* 16-bit logic shift right ((unsigned short)x >> i) */
5820 lshrhi3_out (rtx insn
, rtx operands
[], int *len
)
5822 if (GET_CODE (operands
[2]) == CONST_INT
)
5824 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
5825 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
5832 switch (INTVAL (operands
[2]))
5835 if (INTVAL (operands
[2]) < 16)
5839 return ("clr %B0" CR_TAB
5843 if (optimize_size
&& scratch
)
5848 return ("swap %B0" CR_TAB
5850 "andi %A0,0x0f" CR_TAB
5851 "eor %A0,%B0" CR_TAB
5852 "andi %B0,0x0f" CR_TAB
5858 return ("swap %B0" CR_TAB
5860 "ldi %3,0x0f" CR_TAB
5862 "eor %A0,%B0" CR_TAB
5866 break; /* optimize_size ? 6 : 8 */
5870 break; /* scratch ? 5 : 6 */
5874 return ("lsr %B0" CR_TAB
5878 "andi %A0,0x0f" CR_TAB
5879 "eor %A0,%B0" CR_TAB
5880 "andi %B0,0x0f" CR_TAB
5886 return ("lsr %B0" CR_TAB
5890 "ldi %3,0x0f" CR_TAB
5892 "eor %A0,%B0" CR_TAB
5900 break; /* scratch ? 5 : 6 */
5902 return ("clr __tmp_reg__" CR_TAB
5905 "rol __tmp_reg__" CR_TAB
5908 "rol __tmp_reg__" CR_TAB
5909 "mov %A0,%B0" CR_TAB
5910 "mov %B0,__tmp_reg__");
5914 return ("lsl %A0" CR_TAB
5915 "mov %A0,%B0" CR_TAB
5917 "sbc %B0,%B0" CR_TAB
5921 return *len
= 2, ("mov %A0,%B1" CR_TAB
5926 return ("mov %A0,%B0" CR_TAB
5932 return ("mov %A0,%B0" CR_TAB
5939 return ("mov %A0,%B0" CR_TAB
5949 return ("mov %A0,%B0" CR_TAB
5957 return ("mov %A0,%B0" CR_TAB
5960 "ldi %3,0x0f" CR_TAB
5964 return ("mov %A0,%B0" CR_TAB
5975 return ("mov %A0,%B0" CR_TAB
5981 if (AVR_HAVE_MUL
&& scratch
)
5984 return ("ldi %3,0x08" CR_TAB
5988 "clr __zero_reg__");
5990 if (optimize_size
&& scratch
)
5995 return ("mov %A0,%B0" CR_TAB
5999 "ldi %3,0x07" CR_TAB
6005 return ("set" CR_TAB
6010 "clr __zero_reg__");
6013 return ("mov %A0,%B0" CR_TAB
6022 if (AVR_HAVE_MUL
&& ldi_ok
)
6025 return ("ldi %A0,0x04" CR_TAB
6026 "mul %B0,%A0" CR_TAB
6029 "clr __zero_reg__");
6031 if (AVR_HAVE_MUL
&& scratch
)
6034 return ("ldi %3,0x04" CR_TAB
6038 "clr __zero_reg__");
6040 if (optimize_size
&& ldi_ok
)
6043 return ("mov %A0,%B0" CR_TAB
6044 "ldi %B0,6" "\n1:\t"
6049 if (optimize_size
&& scratch
)
6052 return ("clr %A0" CR_TAB
6061 return ("clr %A0" CR_TAB
6068 out_shift_with_cnt ("lsr %B0" CR_TAB
6069 "ror %A0", insn
, operands
, len
, 2);
6074 /* 24-bit logic shift right */
6077 avr_out_lshrpsi3 (rtx insn
, rtx
*op
, int *plen
)
6079 int dest
= REGNO (op
[0]);
6080 int src
= REGNO (op
[1]);
6082 if (CONST_INT_P (op
[2]))
6087 switch (INTVAL (op
[2]))
6091 return avr_asm_len ("mov %A0,%B1" CR_TAB
6092 "mov %B0,%C1" CR_TAB
6093 "clr %C0", op
, plen
, 3);
6095 return avr_asm_len ("clr %C0" CR_TAB
6096 "mov %B0,%C1" CR_TAB
6097 "mov %A0,%B1", op
, plen
, 3);
6100 if (dest
!= src
+ 2)
6101 avr_asm_len ("mov %A0,%C1", op
, plen
, 1);
6103 return avr_asm_len ("clr %B0" CR_TAB
6104 "clr %C0", op
, plen
, 2);
6107 if (INTVAL (op
[2]) < 24)
6113 return avr_asm_len ("clr %A0" CR_TAB
6117 "clr %C0", op
, plen
, 5);
6121 out_shift_with_cnt ("lsr %C0" CR_TAB
6123 "ror %A0", insn
, op
, plen
, 3);
6128 /* 32-bit logic shift right ((unsigned int)x >> i) */
6131 lshrsi3_out (rtx insn
, rtx operands
[], int *len
)
6133 if (GET_CODE (operands
[2]) == CONST_INT
)
6141 switch (INTVAL (operands
[2]))
6144 if (INTVAL (operands
[2]) < 32)
6148 return *len
= 3, ("clr %D0" CR_TAB
6152 return ("clr %D0" CR_TAB
6159 int reg0
= true_regnum (operands
[0]);
6160 int reg1
= true_regnum (operands
[1]);
6163 return ("mov %A0,%B1" CR_TAB
6164 "mov %B0,%C1" CR_TAB
6165 "mov %C0,%D1" CR_TAB
6168 return ("clr %D0" CR_TAB
6169 "mov %C0,%D1" CR_TAB
6170 "mov %B0,%C1" CR_TAB
6176 int reg0
= true_regnum (operands
[0]);
6177 int reg1
= true_regnum (operands
[1]);
6179 if (reg0
== reg1
+ 2)
6180 return *len
= 2, ("clr %C0" CR_TAB
6183 return *len
= 3, ("movw %A0,%C1" CR_TAB
6187 return *len
= 4, ("mov %B0,%D1" CR_TAB
6188 "mov %A0,%C1" CR_TAB
6194 return *len
= 4, ("mov %A0,%D1" CR_TAB
6201 return ("clr %A0" CR_TAB
6210 out_shift_with_cnt ("lsr %D0" CR_TAB
6213 "ror %A0", insn
, operands
, len
, 4);
6218 /* Output addition of register XOP[0] and compile time constant XOP[2].
6219 CODE == PLUS: perform addition by using ADD instructions or
6220 CODE == MINUS: perform addition by using SUB instructions:
6222 XOP[0] = XOP[0] + XOP[2]
6224 Or perform addition/subtraction with register XOP[2] depending on CODE:
6226 XOP[0] = XOP[0] +/- XOP[2]
6228 If PLEN == NULL, print assembler instructions to perform the operation;
6229 otherwise, set *PLEN to the length of the instruction sequence (in words)
6230 printed with PLEN == NULL. XOP[3] is an 8-bit scratch register or NULL_RTX.
6231 Set *PCC to effect on cc0 according to respective CC_* insn attribute.
6233 CODE_SAT == UNKNOWN: Perform ordinary, non-saturating operation.
6234 CODE_SAT != UNKNOWN: Perform operation and saturate according to CODE_SAT.
6235 If CODE_SAT != UNKNOWN then SIGN contains the sign of the summand resp.
6236 the subtrahend in the original insn, provided it is a compile time constant.
6237 In all other cases, SIGN is 0.
6239 If OUT_LABEL is true, print the final 0: label which is needed for
6240 saturated addition / subtraction. The only case where OUT_LABEL = false
6241 is useful is for saturated addition / subtraction performed during
6242 fixed-point rounding, cf. `avr_out_round'. */
6245 avr_out_plus_1 (rtx
*xop
, int *plen
, enum rtx_code code
, int *pcc
,
6246 enum rtx_code code_sat
, int sign
, bool out_label
)
6248 /* MODE of the operation. */
6249 enum machine_mode mode
= GET_MODE (xop
[0]);
6251 /* INT_MODE of the same size. */
6252 enum machine_mode imode
= int_mode_for_mode (mode
);
6254 /* Number of bytes to operate on. */
6255 int i
, n_bytes
= GET_MODE_SIZE (mode
);
6257 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
6258 int clobber_val
= -1;
6260 /* op[0]: 8-bit destination register
6261 op[1]: 8-bit const int
6262 op[2]: 8-bit scratch register */
6265 /* Started the operation? Before starting the operation we may skip
6266 adding 0. This is no more true after the operation started because
6267 carry must be taken into account. */
6268 bool started
= false;
6270 /* Value to add. There are two ways to add VAL: R += VAL and R -= -VAL. */
6273 /* Output a BRVC instruction. Only needed with saturation. */
6274 bool out_brvc
= true;
6281 *pcc
= MINUS
== code
? (int) CC_SET_CZN
: (int) CC_SET_N
;
6283 for (i
= 0; i
< n_bytes
; i
++)
6285 /* We operate byte-wise on the destination. */
6286 op
[0] = simplify_gen_subreg (QImode
, xop
[0], mode
, i
);
6287 op
[1] = simplify_gen_subreg (QImode
, xop
[2], mode
, i
);
6290 avr_asm_len (code
== PLUS
? "add %0,%1" : "sub %0,%1",
6293 avr_asm_len (code
== PLUS
? "adc %0,%1" : "sbc %0,%1",
6297 if (reg_overlap_mentioned_p (xop
[0], xop
[2]))
6299 gcc_assert (REGNO (xop
[0]) == REGNO (xop
[2]));
6308 /* Except in the case of ADIW with 16-bit register (see below)
6309 addition does not set cc0 in a usable way. */
6311 *pcc
= (MINUS
== code
) ? CC_SET_CZN
: CC_CLOBBER
;
6313 if (CONST_FIXED_P (xval
))
6314 xval
= avr_to_int_mode (xval
);
6316 /* Adding/Subtracting zero is a no-op. */
6318 if (xval
== const0_rtx
)
6325 xval
= simplify_unary_operation (NEG
, imode
, xval
, imode
);
6329 if (SS_PLUS
== code_sat
&& MINUS
== code
6331 && 0x80 == (INTVAL (simplify_gen_subreg (QImode
, xval
, imode
, n_bytes
-1))
6332 & GET_MODE_MASK (QImode
)))
6334 /* We compute x + 0x80 by means of SUB instructions. We negated the
6335 constant subtrahend above and are left with x - (-128) so that we
6336 need something like SUBI r,128 which does not exist because SUBI sets
6337 V according to the sign of the subtrahend. Notice the only case
6338 where this must be done is when NEG overflowed in case [2s] because
6339 the V computation needs the right sign of the subtrahend. */
6341 rtx msb
= simplify_gen_subreg (QImode
, xop
[0], mode
, n_bytes
-1);
6343 avr_asm_len ("subi %0,128" CR_TAB
6344 "brmi 0f", &msb
, plen
, 2);
6350 for (i
= 0; i
< n_bytes
; i
++)
6352 /* We operate byte-wise on the destination. */
6353 rtx reg8
= simplify_gen_subreg (QImode
, xop
[0], mode
, i
);
6354 rtx xval8
= simplify_gen_subreg (QImode
, xval
, imode
, i
);
6356 /* 8-bit value to operate with this byte. */
6357 unsigned int val8
= UINTVAL (xval8
) & GET_MODE_MASK (QImode
);
6359 /* Registers R16..R31 can operate with immediate. */
6360 bool ld_reg_p
= test_hard_reg_class (LD_REGS
, reg8
);
6363 op
[1] = gen_int_mode (val8
, QImode
);
6365 /* To get usable cc0 no low-bytes must have been skipped. */
6373 && test_hard_reg_class (ADDW_REGS
, reg8
))
6375 rtx xval16
= simplify_gen_subreg (HImode
, xval
, imode
, i
);
6376 unsigned int val16
= UINTVAL (xval16
) & GET_MODE_MASK (HImode
);
6378 /* Registers R24, X, Y, Z can use ADIW/SBIW with constants < 64
6379 i.e. operate word-wise. */
6386 avr_asm_len (code
== PLUS
? "adiw %0,%1" : "sbiw %0,%1",
6389 if (n_bytes
== 2 && PLUS
== code
)
6401 avr_asm_len (code
== PLUS
6402 ? "adc %0,__zero_reg__" : "sbc %0,__zero_reg__",
6406 else if ((val8
== 1 || val8
== 0xff)
6407 && UNKNOWN
== code_sat
6409 && i
== n_bytes
- 1)
6411 avr_asm_len ((code
== PLUS
) ^ (val8
== 1) ? "dec %0" : "inc %0",
6420 gcc_assert (plen
!= NULL
|| (op
[2] && REG_P (op
[2])));
6422 if (plen
!= NULL
&& UNKNOWN
!= code_sat
)
6424 /* This belongs to the x + 0x80 corner case. The code with
6425 ADD instruction is not smaller, thus make this case
6426 expensive so that the caller won't pick it. */
6432 if (clobber_val
!= (int) val8
)
6433 avr_asm_len ("ldi %2,%1", op
, plen
, 1);
6434 clobber_val
= (int) val8
;
6436 avr_asm_len (started
? "adc %0,%2" : "add %0,%2", op
, plen
, 1);
6443 avr_asm_len (started
? "sbci %0,%1" : "subi %0,%1", op
, plen
, 1);
6446 gcc_assert (plen
!= NULL
|| REG_P (op
[2]));
6448 if (clobber_val
!= (int) val8
)
6449 avr_asm_len ("ldi %2,%1", op
, plen
, 1);
6450 clobber_val
= (int) val8
;
6452 avr_asm_len (started
? "sbc %0,%2" : "sub %0,%2", op
, plen
, 1);
6464 } /* for all sub-bytes */
6468 if (UNKNOWN
== code_sat
)
6471 *pcc
= (int) CC_CLOBBER
;
6473 /* Vanilla addition/subtraction is done. We are left with saturation.
6475 We have to compute A = A <op> B where A is a register and
6476 B is a register or a non-zero compile time constant CONST.
6477 A is register class "r" if unsigned && B is REG. Otherwise, A is in "d".
6478 B stands for the original operand $2 in INSN. In the case of B = CONST,
6479 SIGN in { -1, 1 } is the sign of B. Otherwise, SIGN is 0.
6481 CODE is the instruction flavor we use in the asm sequence to perform <op>.
6485 operation | code | sat if | b is | sat value | case
6486 -----------------+-------+----------+--------------+-----------+-------
6487 + as a + b | add | C == 1 | const, reg | u+ = 0xff | [1u]
6488 + as a - (-b) | sub | C == 0 | const | u+ = 0xff | [2u]
6489 - as a - b | sub | C == 1 | const, reg | u- = 0 | [3u]
6490 - as a + (-b) | add | C == 0 | const | u- = 0 | [4u]
6494 operation | code | sat if | b is | sat value | case
6495 -----------------+-------+----------+--------------+-----------+-------
6496 + as a + b | add | V == 1 | const, reg | s+ | [1s]
6497 + as a - (-b) | sub | V == 1 | const | s+ | [2s]
6498 - as a - b | sub | V == 1 | const, reg | s- | [3s]
6499 - as a + (-b) | add | V == 1 | const | s- | [4s]
6501 s+ = b < 0 ? -0x80 : 0x7f
6502 s- = b < 0 ? 0x7f : -0x80
6504 The cases a - b actually perform a - (-(-b)) if B is CONST.
6507 op
[0] = simplify_gen_subreg (QImode
, xop
[0], mode
, n_bytes
-1);
6509 ? simplify_gen_subreg (QImode
, xop
[0], mode
, n_bytes
-2)
6512 bool need_copy
= true;
6513 int len_call
= 1 + AVR_HAVE_JMP_CALL
;
6524 avr_asm_len ("brvc 0f", op
, plen
, 1);
6526 if (reg_overlap_mentioned_p (xop
[0], xop
[2]))
6531 avr_asm_len ("ldi %0,0x7f" CR_TAB
6532 "adc %0,__zero_reg__", op
, plen
, 2);
6534 avr_asm_len ("ldi %0,0x7f" CR_TAB
6535 "ldi %1,0xff" CR_TAB
6536 "adc %1,__zero_reg__" CR_TAB
6537 "adc %0,__zero_reg__", op
, plen
, 4);
6539 else if (sign
== 0 && PLUS
== code
)
6543 op
[2] = simplify_gen_subreg (QImode
, xop
[2], mode
, n_bytes
-1);
6546 avr_asm_len ("ldi %0,0x80" CR_TAB
6548 "dec %0", op
, plen
, 3);
6550 avr_asm_len ("ldi %0,0x80" CR_TAB
6553 "sbci %0,0", op
, plen
, 4);
6555 else if (sign
== 0 && MINUS
== code
)
6559 op
[2] = simplify_gen_subreg (QImode
, xop
[2], mode
, n_bytes
-1);
6562 avr_asm_len ("ldi %0,0x7f" CR_TAB
6564 "inc %0", op
, plen
, 3);
6566 avr_asm_len ("ldi %0,0x7f" CR_TAB
6569 "sbci %0,-1", op
, plen
, 4);
6571 else if ((sign
< 0) ^ (SS_MINUS
== code_sat
))
6573 /* [1s,const,B < 0] [2s,B < 0] */
6574 /* [3s,const,B > 0] [4s,B > 0] */
6578 avr_asm_len ("%~call __clr_8", op
, plen
, len_call
);
6582 avr_asm_len ("ldi %0,0x80", op
, plen
, 1);
6583 if (n_bytes
> 1 && need_copy
)
6584 avr_asm_len ("clr %1", op
, plen
, 1);
6586 else if ((sign
> 0) ^ (SS_MINUS
== code_sat
))
6588 /* [1s,const,B > 0] [2s,B > 0] */
6589 /* [3s,const,B < 0] [4s,B < 0] */
6593 avr_asm_len ("sec" CR_TAB
6594 "%~call __sbc_8", op
, plen
, 1 + len_call
);
6598 avr_asm_len ("ldi %0,0x7f", op
, plen
, 1);
6599 if (n_bytes
> 1 && need_copy
)
6600 avr_asm_len ("ldi %1,0xff", op
, plen
, 1);
6610 avr_asm_len (PLUS
== code
? "brcc 0f" : "brcs 0f", op
, plen
, 1);
6615 avr_asm_len ("sec", op
, plen
, 1);
6616 avr_asm_len ("%~call __sbc_8", op
, plen
, len_call
);
6622 if (MINUS
== code
&& !test_hard_reg_class (LD_REGS
, op
[0]))
6623 avr_asm_len ("sec" CR_TAB
"sbc %0,%0", op
, plen
, 2);
6625 avr_asm_len (PLUS
== code
? "sbc %0,%0" : "ldi %0,0xff",
6628 break; /* US_PLUS */
6633 avr_asm_len (PLUS
== code
? "brcs 0f" : "brcc 0f", op
, plen
, 1);
6637 avr_asm_len ("%~call __clr_8", op
, plen
, len_call
);
6641 avr_asm_len ("clr %0", op
, plen
, 1);
6646 /* We set the MSB in the unsigned case and the 2 MSBs in the signed case.
6647 Now copy the right value to the LSBs. */
6649 if (need_copy
&& n_bytes
> 1)
6651 if (US_MINUS
== code_sat
|| US_PLUS
== code_sat
)
6653 avr_asm_len ("mov %1,%0", op
, plen
, 1);
6659 avr_asm_len ("movw %0,%1", op
, plen
, 1);
6661 avr_asm_len ("mov %A0,%1" CR_TAB
6662 "mov %B0,%1", op
, plen
, 2);
6665 else if (n_bytes
> 2)
6668 avr_asm_len ("mov %A0,%1" CR_TAB
6669 "mov %B0,%1", op
, plen
, 2);
6673 if (need_copy
&& n_bytes
== 8)
6676 avr_asm_len ("movw %r0+2,%0" CR_TAB
6677 "movw %r0+4,%0", xop
, plen
, 2);
6679 avr_asm_len ("mov %r0+2,%0" CR_TAB
6680 "mov %r0+3,%0" CR_TAB
6681 "mov %r0+4,%0" CR_TAB
6682 "mov %r0+5,%0", xop
, plen
, 4);
6686 avr_asm_len ("0:", op
, plen
, 0);
6690 /* Output addition/subtraction of register XOP[0] and a constant XOP[2] that
6691 is ont a compile-time constant:
6693 XOP[0] = XOP[0] +/- XOP[2]
6695 This is a helper for the function below. The only insns that need this
6696 are additions/subtraction for pointer modes, i.e. HImode and PSImode. */
6699 avr_out_plus_symbol (rtx
*xop
, enum rtx_code code
, int *plen
, int *pcc
)
6701 enum machine_mode mode
= GET_MODE (xop
[0]);
6703 /* Only pointer modes want to add symbols. */
6705 gcc_assert (mode
== HImode
|| mode
== PSImode
);
6707 *pcc
= MINUS
== code
? (int) CC_SET_CZN
: (int) CC_SET_N
;
6709 avr_asm_len (PLUS
== code
6710 ? "subi %A0,lo8(-(%2))" CR_TAB
"sbci %B0,hi8(-(%2))"
6711 : "subi %A0,lo8(%2)" CR_TAB
"sbci %B0,hi8(%2)",
6714 if (PSImode
== mode
)
6715 avr_asm_len (PLUS
== code
6716 ? "sbci %C0,hlo8(-(%2))"
6717 : "sbci %C0,hlo8(%2)", xop
, plen
, 1);
6722 /* Prepare operands of addition/subtraction to be used with avr_out_plus_1.
6724 INSN is a single_set insn or an insn pattern with a binary operation as
6725 SET_SRC that is one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
6727 XOP are the operands of INSN. In the case of 64-bit operations with
6728 constant XOP[] has just one element: The summand/subtrahend in XOP[0].
6729 The non-saturating insns up to 32 bits may or may not supply a "d" class
6732 If PLEN == NULL output the instructions.
6733 If PLEN != NULL set *PLEN to the length of the sequence in words.
6735 PCC is a pointer to store the instructions' effect on cc0.
6738 PLEN and PCC default to NULL.
6740 OUT_LABEL defaults to TRUE. For a description, see AVR_OUT_PLUS_1.
6745 avr_out_plus (rtx insn
, rtx
*xop
, int *plen
, int *pcc
, bool out_label
)
6747 int cc_plus
, cc_minus
, cc_dummy
;
6748 int len_plus
, len_minus
;
6750 rtx xpattern
= INSN_P (insn
) ? single_set (insn
) : insn
;
6751 rtx xdest
= SET_DEST (xpattern
);
6752 enum machine_mode mode
= GET_MODE (xdest
);
6753 enum machine_mode imode
= int_mode_for_mode (mode
);
6754 int n_bytes
= GET_MODE_SIZE (mode
);
6755 enum rtx_code code_sat
= GET_CODE (SET_SRC (xpattern
));
6757 = (PLUS
== code_sat
|| SS_PLUS
== code_sat
|| US_PLUS
== code_sat
6763 /* PLUS and MINUS don't saturate: Use modular wrap-around. */
6765 if (PLUS
== code_sat
|| MINUS
== code_sat
)
6768 if (n_bytes
<= 4 && REG_P (xop
[2]))
6770 avr_out_plus_1 (xop
, plen
, code
, pcc
, code_sat
, 0, out_label
);
6776 op
[0] = gen_rtx_REG (DImode
, ACC_A
);
6777 op
[1] = gen_rtx_REG (DImode
, ACC_A
);
6778 op
[2] = avr_to_int_mode (xop
[0]);
6783 && !CONST_INT_P (xop
[2])
6784 && !CONST_FIXED_P (xop
[2]))
6786 return avr_out_plus_symbol (xop
, code
, plen
, pcc
);
6789 op
[0] = avr_to_int_mode (xop
[0]);
6790 op
[1] = avr_to_int_mode (xop
[1]);
6791 op
[2] = avr_to_int_mode (xop
[2]);
6794 /* Saturations and 64-bit operations don't have a clobber operand.
6795 For the other cases, the caller will provide a proper XOP[3]. */
6797 xpattern
= INSN_P (insn
) ? PATTERN (insn
) : insn
;
6798 op
[3] = PARALLEL
== GET_CODE (xpattern
) ? xop
[3] : NULL_RTX
;
6800 /* Saturation will need the sign of the original operand. */
6802 rtx xmsb
= simplify_gen_subreg (QImode
, op
[2], imode
, n_bytes
-1);
6803 int sign
= INTVAL (xmsb
) < 0 ? -1 : 1;
6805 /* If we subtract and the subtrahend is a constant, then negate it
6806 so that avr_out_plus_1 can be used. */
6809 op
[2] = simplify_unary_operation (NEG
, imode
, op
[2], imode
);
6811 /* Work out the shortest sequence. */
6813 avr_out_plus_1 (op
, &len_minus
, MINUS
, &cc_minus
, code_sat
, sign
, out_label
);
6814 avr_out_plus_1 (op
, &len_plus
, PLUS
, &cc_plus
, code_sat
, sign
, out_label
);
6818 *plen
= (len_minus
<= len_plus
) ? len_minus
: len_plus
;
6819 *pcc
= (len_minus
<= len_plus
) ? cc_minus
: cc_plus
;
6821 else if (len_minus
<= len_plus
)
6822 avr_out_plus_1 (op
, NULL
, MINUS
, pcc
, code_sat
, sign
, out_label
);
6824 avr_out_plus_1 (op
, NULL
, PLUS
, pcc
, code_sat
, sign
, out_label
);
6830 /* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
6831 time constant XOP[2]:
6833 XOP[0] = XOP[0] <op> XOP[2]
6835 and return "". If PLEN == NULL, print assembler instructions to perform the
6836 operation; otherwise, set *PLEN to the length of the instruction sequence
6837 (in words) printed with PLEN == NULL. XOP[3] is either an 8-bit clobber
6838 register or SCRATCH if no clobber register is needed for the operation.
6839 INSN is an INSN_P or a pattern of an insn. */
6842 avr_out_bitop (rtx insn
, rtx
*xop
, int *plen
)
6844 /* CODE and MODE of the operation. */
6845 rtx xpattern
= INSN_P (insn
) ? single_set (insn
) : insn
;
6846 enum rtx_code code
= GET_CODE (SET_SRC (xpattern
));
6847 enum machine_mode mode
= GET_MODE (xop
[0]);
6849 /* Number of bytes to operate on. */
6850 int i
, n_bytes
= GET_MODE_SIZE (mode
);
6852 /* Value of T-flag (0 or 1) or -1 if unknow. */
6855 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
6856 int clobber_val
= -1;
6858 /* op[0]: 8-bit destination register
6859 op[1]: 8-bit const int
6860 op[2]: 8-bit clobber register or SCRATCH
6861 op[3]: 8-bit register containing 0xff or NULL_RTX */
6870 for (i
= 0; i
< n_bytes
; i
++)
6872 /* We operate byte-wise on the destination. */
6873 rtx reg8
= simplify_gen_subreg (QImode
, xop
[0], mode
, i
);
6874 rtx xval8
= simplify_gen_subreg (QImode
, xop
[2], mode
, i
);
6876 /* 8-bit value to operate with this byte. */
6877 unsigned int val8
= UINTVAL (xval8
) & GET_MODE_MASK (QImode
);
6879 /* Number of bits set in the current byte of the constant. */
6880 int pop8
= avr_popcount (val8
);
6882 /* Registers R16..R31 can operate with immediate. */
6883 bool ld_reg_p
= test_hard_reg_class (LD_REGS
, reg8
);
6886 op
[1] = GEN_INT (val8
);
6895 avr_asm_len ("ori %0,%1", op
, plen
, 1);
6899 avr_asm_len ("set", op
, plen
, 1);
6902 op
[1] = GEN_INT (exact_log2 (val8
));
6903 avr_asm_len ("bld %0,%1", op
, plen
, 1);
6907 if (op
[3] != NULL_RTX
)
6908 avr_asm_len ("mov %0,%3", op
, plen
, 1);
6910 avr_asm_len ("clr %0" CR_TAB
6911 "dec %0", op
, plen
, 2);
6917 if (clobber_val
!= (int) val8
)
6918 avr_asm_len ("ldi %2,%1", op
, plen
, 1);
6919 clobber_val
= (int) val8
;
6921 avr_asm_len ("or %0,%2", op
, plen
, 1);
6931 avr_asm_len ("clr %0", op
, plen
, 1);
6933 avr_asm_len ("andi %0,%1", op
, plen
, 1);
6937 avr_asm_len ("clt", op
, plen
, 1);
6940 op
[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode
) & ~val8
));
6941 avr_asm_len ("bld %0,%1", op
, plen
, 1);
6945 if (clobber_val
!= (int) val8
)
6946 avr_asm_len ("ldi %2,%1", op
, plen
, 1);
6947 clobber_val
= (int) val8
;
6949 avr_asm_len ("and %0,%2", op
, plen
, 1);
6959 avr_asm_len ("com %0", op
, plen
, 1);
6960 else if (ld_reg_p
&& val8
== (1 << 7))
6961 avr_asm_len ("subi %0,%1", op
, plen
, 1);
6964 if (clobber_val
!= (int) val8
)
6965 avr_asm_len ("ldi %2,%1", op
, plen
, 1);
6966 clobber_val
= (int) val8
;
6968 avr_asm_len ("eor %0,%2", op
, plen
, 1);
6974 /* Unknown rtx_code */
6977 } /* for all sub-bytes */
6983 /* PLEN == NULL: Output code to add CONST_INT OP[0] to SP.
6984 PLEN != NULL: Set *PLEN to the length of that sequence.
6988 avr_out_addto_sp (rtx
*op
, int *plen
)
6990 int pc_len
= AVR_2_BYTE_PC
? 2 : 3;
6991 int addend
= INTVAL (op
[0]);
6998 if (flag_verbose_asm
|| flag_print_asm_name
)
6999 avr_asm_len (ASM_COMMENT_START
"SP -= %n0", op
, plen
, 0);
7001 while (addend
<= -pc_len
)
7004 avr_asm_len ("rcall .", op
, plen
, 1);
7007 while (addend
++ < 0)
7008 avr_asm_len ("push __zero_reg__", op
, plen
, 1);
7010 else if (addend
> 0)
7012 if (flag_verbose_asm
|| flag_print_asm_name
)
7013 avr_asm_len (ASM_COMMENT_START
"SP += %0", op
, plen
, 0);
7015 while (addend
-- > 0)
7016 avr_asm_len ("pop __tmp_reg__", op
, plen
, 1);
7023 /* Outputs instructions needed for fixed point type conversion.
7024 This includes converting between any fixed point type, as well
7025 as converting to any integer type. Conversion between integer
7026 types is not supported.
7028 Converting signed fractional types requires a bit shift if converting
7029 to or from any unsigned fractional type because the decimal place is
7030 shifted by 1 bit. When the destination is a signed fractional, the sign
7031 is stored in either the carry or T bit. */
7034 avr_out_fract (rtx insn
, rtx operands
[], bool intsigned
, int *plen
)
7038 RTX_CODE shift
= UNKNOWN
;
7039 bool sign_in_carry
= false;
7040 bool msb_in_carry
= false;
7041 bool lsb_in_carry
= false;
7042 const char *code_ashift
= "lsl %0";
7045 #define MAY_CLOBBER(RR) \
7046 /* Shorthand used below. */ \
7048 && IN_RANGE (RR, dest.regno_msb - sign_bytes + 1, dest.regno_msb)) \
7049 || (reg_unused_after (insn, all_regs_rtx[RR]) \
7050 && !IN_RANGE (RR, dest.regno, dest.regno_msb)))
7054 /* bytes : Length of operand in bytes.
7055 ibyte : Length of integral part in bytes.
7056 fbyte, fbit : Length of fractional part in bytes, bits. */
7059 unsigned fbit
, bytes
, ibyte
, fbyte
;
7060 unsigned regno
, regno_msb
;
7061 } dest
, src
, *val
[2] = { &dest
, &src
};
7066 /* Step 0: Determine information on source and destination operand we
7067 ====== will need in the remainder. */
7069 for (i
= 0; i
< sizeof (val
) / sizeof (*val
); i
++)
7071 enum machine_mode mode
;
7073 xop
[i
] = operands
[i
];
7075 mode
= GET_MODE (xop
[i
]);
7077 val
[i
]->bytes
= GET_MODE_SIZE (mode
);
7078 val
[i
]->regno
= REGNO (xop
[i
]);
7079 val
[i
]->regno_msb
= REGNO (xop
[i
]) + val
[i
]->bytes
- 1;
7081 if (SCALAR_INT_MODE_P (mode
))
7083 val
[i
]->sbit
= intsigned
;
7086 else if (ALL_SCALAR_FIXED_POINT_MODE_P (mode
))
7088 val
[i
]->sbit
= SIGNED_SCALAR_FIXED_POINT_MODE_P (mode
);
7089 val
[i
]->fbit
= GET_MODE_FBIT (mode
);
7092 fatal_insn ("unsupported fixed-point conversion", insn
);
7094 val
[i
]->fbyte
= (1 + val
[i
]->fbit
) / BITS_PER_UNIT
;
7095 val
[i
]->ibyte
= val
[i
]->bytes
- val
[i
]->fbyte
;
7098 // Byte offset of the decimal point taking into account different place
7099 // of the decimal point in input and output and different register numbers
7100 // of input and output.
7101 int offset
= dest
.regno
- src
.regno
+ dest
.fbyte
- src
.fbyte
;
7103 // Number of destination bytes that will come from sign / zero extension.
7104 int sign_bytes
= (dest
.ibyte
- src
.ibyte
) * (dest
.ibyte
> src
.ibyte
);
7106 // Number of bytes at the low end to be filled with zeros.
7107 int zero_bytes
= (dest
.fbyte
- src
.fbyte
) * (dest
.fbyte
> src
.fbyte
);
7109 // Do we have a 16-Bit register that is cleared?
7110 rtx clrw
= NULL_RTX
;
7112 bool sign_extend
= src
.sbit
&& sign_bytes
;
7114 if (0 == dest
.fbit
% 8 && 7 == src
.fbit
% 8)
7116 else if (7 == dest
.fbit
% 8 && 0 == src
.fbit
% 8)
7118 else if (dest
.fbit
% 8 == src
.fbit
% 8)
7123 /* Step 1: Clear bytes at the low end and copy payload bits from source
7124 ====== to destination. */
7126 int step
= offset
< 0 ? 1 : -1;
7127 unsigned d0
= offset
< 0 ? dest
.regno
: dest
.regno_msb
;
7129 // We leared at least that number of registers.
7132 for (; d0
>= dest
.regno
&& d0
<= dest
.regno_msb
; d0
+= step
)
7134 // Next regno of destination is needed for MOVW
7135 unsigned d1
= d0
+ step
;
7137 // Current and next regno of source
7138 signed s0
= d0
- offset
;
7139 signed s1
= s0
+ step
;
7141 // Must current resp. next regno be CLRed? This applies to the low
7142 // bytes of the destination that have no associated source bytes.
7143 bool clr0
= s0
< (signed) src
.regno
;
7144 bool clr1
= s1
< (signed) src
.regno
&& d1
>= dest
.regno
;
7146 // First gather what code to emit (if any) and additional step to
7147 // apply if a MOVW is in use. xop[2] is destination rtx and xop[3]
7148 // is the source rtx for the current loop iteration.
7149 const char *code
= NULL
;
7154 if (AVR_HAVE_MOVW
&& clr1
&& clrw
)
7156 xop
[2] = all_regs_rtx
[d0
& ~1];
7158 code
= "movw %2,%3";
7163 xop
[2] = all_regs_rtx
[d0
];
7168 && d0
% 2 == (step
> 0))
7170 clrw
= all_regs_rtx
[d0
& ~1];
7174 else if (offset
&& s0
<= (signed) src
.regno_msb
)
7176 int movw
= AVR_HAVE_MOVW
&& offset
% 2 == 0
7177 && d0
% 2 == (offset
> 0)
7178 && d1
<= dest
.regno_msb
&& d1
>= dest
.regno
7179 && s1
<= (signed) src
.regno_msb
&& s1
>= (signed) src
.regno
;
7181 xop
[2] = all_regs_rtx
[d0
& ~movw
];
7182 xop
[3] = all_regs_rtx
[s0
& ~movw
];
7183 code
= movw
? "movw %2,%3" : "mov %2,%3";
7184 stepw
= step
* movw
;
7189 if (sign_extend
&& shift
!= ASHIFT
&& !sign_in_carry
7190 && (d0
== src
.regno_msb
|| d0
+ stepw
== src
.regno_msb
))
7192 /* We are going to override the sign bit. If we sign-extend,
7193 store the sign in the Carry flag. This is not needed if
7194 the destination will be ASHIFT is the remainder because
7195 the ASHIFT will set Carry without extra instruction. */
7197 avr_asm_len ("lsl %0", &all_regs_rtx
[src
.regno_msb
], plen
, 1);
7198 sign_in_carry
= true;
7201 unsigned src_msb
= dest
.regno_msb
- sign_bytes
- offset
+ 1;
7203 if (!sign_extend
&& shift
== ASHIFTRT
&& !msb_in_carry
7204 && src
.ibyte
> dest
.ibyte
7205 && (d0
== src_msb
|| d0
+ stepw
== src_msb
))
7207 /* We are going to override the MSB. If we shift right,
7208 store the MSB in the Carry flag. This is only needed if
7209 we don't sign-extend becaue with sign-extension the MSB
7210 (the sign) will be produced by the sign extension. */
7212 avr_asm_len ("lsr %0", &all_regs_rtx
[src_msb
], plen
, 1);
7213 msb_in_carry
= true;
7216 unsigned src_lsb
= dest
.regno
- offset
-1;
7218 if (shift
== ASHIFT
&& src
.fbyte
> dest
.fbyte
&& !lsb_in_carry
7219 && (d0
== src_lsb
|| d0
+ stepw
== src_lsb
))
7221 /* We are going to override the new LSB; store it into carry. */
7223 avr_asm_len ("lsl %0", &all_regs_rtx
[src_lsb
], plen
, 1);
7224 code_ashift
= "rol %0";
7225 lsb_in_carry
= true;
7228 avr_asm_len (code
, xop
, plen
, 1);
7233 /* Step 2: Shift destination left by 1 bit position. This might be needed
7234 ====== for signed input and unsigned output. */
7236 if (shift
== ASHIFT
&& src
.fbyte
> dest
.fbyte
&& !lsb_in_carry
)
7238 unsigned s0
= dest
.regno
- offset
-1;
7240 if (MAY_CLOBBER (s0
))
7241 avr_asm_len ("lsl %0", &all_regs_rtx
[s0
], plen
, 1);
7243 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
7244 "lsl __tmp_reg__", &all_regs_rtx
[s0
], plen
, 2);
7246 code_ashift
= "rol %0";
7247 lsb_in_carry
= true;
7250 if (shift
== ASHIFT
)
7252 for (d0
= dest
.regno
+ zero_bytes
;
7253 d0
<= dest
.regno_msb
- sign_bytes
; d0
++)
7255 avr_asm_len (code_ashift
, &all_regs_rtx
[d0
], plen
, 1);
7256 code_ashift
= "rol %0";
7259 lsb_in_carry
= false;
7260 sign_in_carry
= true;
7263 /* Step 4a: Store MSB in carry if we don't already have it or will produce
7264 ======= it in sign-extension below. */
7266 if (!sign_extend
&& shift
== ASHIFTRT
&& !msb_in_carry
7267 && src
.ibyte
> dest
.ibyte
)
7269 unsigned s0
= dest
.regno_msb
- sign_bytes
- offset
+ 1;
7271 if (MAY_CLOBBER (s0
))
7272 avr_asm_len ("lsr %0", &all_regs_rtx
[s0
], plen
, 1);
7274 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
7275 "lsr __tmp_reg__", &all_regs_rtx
[s0
], plen
, 2);
7277 msb_in_carry
= true;
7280 /* Step 3: Sign-extend or zero-extend the destination as needed.
7283 if (sign_extend
&& !sign_in_carry
)
7285 unsigned s0
= src
.regno_msb
;
7287 if (MAY_CLOBBER (s0
))
7288 avr_asm_len ("lsl %0", &all_regs_rtx
[s0
], plen
, 1);
7290 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
7291 "lsl __tmp_reg__", &all_regs_rtx
[s0
], plen
, 2);
7293 sign_in_carry
= true;
7296 gcc_assert (sign_in_carry
+ msb_in_carry
+ lsb_in_carry
<= 1);
7298 unsigned copies
= 0;
7299 rtx movw
= sign_extend
? NULL_RTX
: clrw
;
7301 for (d0
= dest
.regno_msb
- sign_bytes
+ 1; d0
<= dest
.regno_msb
; d0
++)
7303 if (AVR_HAVE_MOVW
&& movw
7304 && d0
% 2 == 0 && d0
+ 1 <= dest
.regno_msb
)
7306 xop
[2] = all_regs_rtx
[d0
];
7308 avr_asm_len ("movw %2,%3", xop
, plen
, 1);
7313 avr_asm_len (sign_extend
? "sbc %0,%0" : "clr %0",
7314 &all_regs_rtx
[d0
], plen
, 1);
7316 if (++copies
>= 2 && !movw
&& d0
% 2 == 1)
7317 movw
= all_regs_rtx
[d0
-1];
7322 /* Step 4: Right shift the destination. This might be needed for
7323 ====== conversions from unsigned to signed. */
7325 if (shift
== ASHIFTRT
)
7327 const char *code_ashiftrt
= "lsr %0";
7329 if (sign_extend
|| msb_in_carry
)
7330 code_ashiftrt
= "ror %0";
7332 if (src
.sbit
&& src
.ibyte
== dest
.ibyte
)
7333 code_ashiftrt
= "asr %0";
7335 for (d0
= dest
.regno_msb
- sign_bytes
;
7336 d0
>= dest
.regno
+ zero_bytes
- 1 && d0
>= dest
.regno
; d0
--)
7338 avr_asm_len (code_ashiftrt
, &all_regs_rtx
[d0
], plen
, 1);
7339 code_ashiftrt
= "ror %0";
7349 /* Output fixed-point rounding. XOP[0] = XOP[1] is the operand to round.
7350 XOP[2] is the rounding point, a CONST_INT. The function prints the
7351 instruction sequence if PLEN = NULL and computes the length in words
7352 of the sequence if PLEN != NULL. Most of this function deals with
7353 preparing operands for calls to `avr_out_plus' and `avr_out_bitop'. */
7356 avr_out_round (rtx insn ATTRIBUTE_UNUSED
, rtx
*xop
, int *plen
)
7358 enum machine_mode mode
= GET_MODE (xop
[0]);
7359 enum machine_mode imode
= int_mode_for_mode (mode
);
7360 // The smallest fractional bit not cleared by the rounding is 2^(-RP).
7361 int fbit
= (int) GET_MODE_FBIT (mode
);
7362 double_int i_add
= double_int_zero
.set_bit (fbit
-1 - INTVAL (xop
[2]));
7363 // Lengths of PLUS and AND parts.
7364 int len_add
= 0, *plen_add
= plen
? &len_add
: NULL
;
7365 int len_and
= 0, *plen_and
= plen
? &len_and
: NULL
;
7367 // Add-Saturate 1/2 * 2^(-RP). Don't print the label "0:" when printing
7368 // the saturated addition so that we can emit the "rjmp 1f" before the
7371 rtx xadd
= const_fixed_from_double_int (i_add
, mode
);
7372 rtx xpattern
, xsrc
, op
[4];
7374 xsrc
= SIGNED_FIXED_POINT_MODE_P (mode
)
7375 ? gen_rtx_SS_PLUS (mode
, xop
[1], xadd
)
7376 : gen_rtx_US_PLUS (mode
, xop
[1], xadd
);
7377 xpattern
= gen_rtx_SET (VOIDmode
, xop
[0], xsrc
);
7382 avr_out_plus (xpattern
, op
, plen_add
, NULL
, false /* Don't print "0:" */);
7384 avr_asm_len ("rjmp 1f" CR_TAB
7385 "0:", NULL
, plen_add
, 1);
7387 // Keep all bits from RP and higher: ... 2^(-RP)
7388 // Clear all bits from RP+1 and lower: 2^(-RP-1) ...
7389 // Rounding point ^^^^^^^
7390 // Added above ^^^^^^^^^
7391 rtx xreg
= simplify_gen_subreg (imode
, xop
[0], mode
, 0);
7392 rtx xmask
= immed_double_int_const (-i_add
- i_add
, imode
);
7394 xpattern
= gen_rtx_SET (VOIDmode
, xreg
, gen_rtx_AND (imode
, xreg
, xmask
));
7399 op
[3] = gen_rtx_SCRATCH (QImode
);
7400 avr_out_bitop (xpattern
, op
, plen_and
);
7401 avr_asm_len ("1:", NULL
, plen
, 0);
7404 *plen
= len_add
+ len_and
;
7410 /* Create RTL split patterns for byte sized rotate expressions. This
7411 produces a series of move instructions and considers overlap situations.
7412 Overlapping non-HImode operands need a scratch register. */
7415 avr_rotate_bytes (rtx operands
[])
7418 enum machine_mode mode
= GET_MODE (operands
[0]);
7419 bool overlapped
= reg_overlap_mentioned_p (operands
[0], operands
[1]);
7420 bool same_reg
= rtx_equal_p (operands
[0], operands
[1]);
7421 int num
= INTVAL (operands
[2]);
7422 rtx scratch
= operands
[3];
7423 /* Work out if byte or word move is needed. Odd byte rotates need QImode.
7424 Word move if no scratch is needed, otherwise use size of scratch. */
7425 enum machine_mode move_mode
= QImode
;
7426 int move_size
, offset
, size
;
7430 else if ((mode
== SImode
&& !same_reg
) || !overlapped
)
7433 move_mode
= GET_MODE (scratch
);
7435 /* Force DI rotate to use QI moves since other DI moves are currently split
7436 into QI moves so forward propagation works better. */
7439 /* Make scratch smaller if needed. */
7440 if (SCRATCH
!= GET_CODE (scratch
)
7441 && HImode
== GET_MODE (scratch
)
7442 && QImode
== move_mode
)
7443 scratch
= simplify_gen_subreg (move_mode
, scratch
, HImode
, 0);
7445 move_size
= GET_MODE_SIZE (move_mode
);
7446 /* Number of bytes/words to rotate. */
7447 offset
= (num
>> 3) / move_size
;
7448 /* Number of moves needed. */
7449 size
= GET_MODE_SIZE (mode
) / move_size
;
7450 /* Himode byte swap is special case to avoid a scratch register. */
7451 if (mode
== HImode
&& same_reg
)
7453 /* HImode byte swap, using xor. This is as quick as using scratch. */
7455 src
= simplify_gen_subreg (move_mode
, operands
[1], mode
, 0);
7456 dst
= simplify_gen_subreg (move_mode
, operands
[0], mode
, 1);
7457 if (!rtx_equal_p (dst
, src
))
7459 emit_move_insn (dst
, gen_rtx_XOR (QImode
, dst
, src
));
7460 emit_move_insn (src
, gen_rtx_XOR (QImode
, src
, dst
));
7461 emit_move_insn (dst
, gen_rtx_XOR (QImode
, dst
, src
));
7466 #define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode) */
7467 /* Create linked list of moves to determine move order. */
7471 } move
[MAX_SIZE
+ 8];
7474 gcc_assert (size
<= MAX_SIZE
);
7475 /* Generate list of subreg moves. */
7476 for (i
= 0; i
< size
; i
++)
7479 int to
= (from
+ offset
) % size
;
7480 move
[i
].src
= simplify_gen_subreg (move_mode
, operands
[1],
7481 mode
, from
* move_size
);
7482 move
[i
].dst
= simplify_gen_subreg (move_mode
, operands
[0],
7483 mode
, to
* move_size
);
7486 /* Mark dependence where a dst of one move is the src of another move.
7487 The first move is a conflict as it must wait until second is
7488 performed. We ignore moves to self - we catch this later. */
7490 for (i
= 0; i
< size
; i
++)
7491 if (reg_overlap_mentioned_p (move
[i
].dst
, operands
[1]))
7492 for (j
= 0; j
< size
; j
++)
7493 if (j
!= i
&& rtx_equal_p (move
[j
].src
, move
[i
].dst
))
7495 /* The dst of move i is the src of move j. */
7502 /* Go through move list and perform non-conflicting moves. As each
7503 non-overlapping move is made, it may remove other conflicts
7504 so the process is repeated until no conflicts remain. */
7509 /* Emit move where dst is not also a src or we have used that
7511 for (i
= 0; i
< size
; i
++)
7512 if (move
[i
].src
!= NULL_RTX
)
7514 if (move
[i
].links
== -1
7515 || move
[move
[i
].links
].src
== NULL_RTX
)
7518 /* Ignore NOP moves to self. */
7519 if (!rtx_equal_p (move
[i
].dst
, move
[i
].src
))
7520 emit_move_insn (move
[i
].dst
, move
[i
].src
);
7522 /* Remove conflict from list. */
7523 move
[i
].src
= NULL_RTX
;
7529 /* Check for deadlock. This is when no moves occurred and we have
7530 at least one blocked move. */
7531 if (moves
== 0 && blocked
!= -1)
7533 /* Need to use scratch register to break deadlock.
7534 Add move to put dst of blocked move into scratch.
7535 When this move occurs, it will break chain deadlock.
7536 The scratch register is substituted for real move. */
7538 gcc_assert (SCRATCH
!= GET_CODE (scratch
));
7540 move
[size
].src
= move
[blocked
].dst
;
7541 move
[size
].dst
= scratch
;
7542 /* Scratch move is never blocked. */
7543 move
[size
].links
= -1;
7544 /* Make sure we have valid link. */
7545 gcc_assert (move
[blocked
].links
!= -1);
7546 /* Replace src of blocking move with scratch reg. */
7547 move
[move
[blocked
].links
].src
= scratch
;
7548 /* Make dependent on scratch move occuring. */
7549 move
[blocked
].links
= size
;
7553 while (blocked
!= -1);
7559 /* Worker function for `ADJUST_INSN_LENGTH'. */
7560 /* Modifies the length assigned to instruction INSN
7561 LEN is the initially computed length of the insn. */
7564 avr_adjust_insn_length (rtx insn
, int len
)
7566 rtx
*op
= recog_data
.operand
;
7567 enum attr_adjust_len adjust_len
;
7569 /* Some complex insns don't need length adjustment and therefore
7570 the length need not/must not be adjusted for these insns.
7571 It is easier to state this in an insn attribute "adjust_len" than
7572 to clutter up code here... */
7574 if (-1 == recog_memoized (insn
))
7579 /* Read from insn attribute "adjust_len" if/how length is to be adjusted. */
7581 adjust_len
= get_attr_adjust_len (insn
);
7583 if (adjust_len
== ADJUST_LEN_NO
)
7585 /* Nothing to adjust: The length from attribute "length" is fine.
7586 This is the default. */
7591 /* Extract insn's operands. */
7593 extract_constrain_insn_cached (insn
);
7595 /* Dispatch to right function. */
7599 case ADJUST_LEN_RELOAD_IN16
: output_reload_inhi (op
, op
[2], &len
); break;
7600 case ADJUST_LEN_RELOAD_IN24
: avr_out_reload_inpsi (op
, op
[2], &len
); break;
7601 case ADJUST_LEN_RELOAD_IN32
: output_reload_insisf (op
, op
[2], &len
); break;
7603 case ADJUST_LEN_OUT_BITOP
: avr_out_bitop (insn
, op
, &len
); break;
7605 case ADJUST_LEN_PLUS
: avr_out_plus (insn
, op
, &len
); break;
7606 case ADJUST_LEN_ADDTO_SP
: avr_out_addto_sp (op
, &len
); break;
7608 case ADJUST_LEN_MOV8
: output_movqi (insn
, op
, &len
); break;
7609 case ADJUST_LEN_MOV16
: output_movhi (insn
, op
, &len
); break;
7610 case ADJUST_LEN_MOV24
: avr_out_movpsi (insn
, op
, &len
); break;
7611 case ADJUST_LEN_MOV32
: output_movsisf (insn
, op
, &len
); break;
7612 case ADJUST_LEN_MOVMEM
: avr_out_movmem (insn
, op
, &len
); break;
7613 case ADJUST_LEN_XLOAD
: avr_out_xload (insn
, op
, &len
); break;
7614 case ADJUST_LEN_LPM
: avr_out_lpm (insn
, op
, &len
); break;
7616 case ADJUST_LEN_SFRACT
: avr_out_fract (insn
, op
, true, &len
); break;
7617 case ADJUST_LEN_UFRACT
: avr_out_fract (insn
, op
, false, &len
); break;
7618 case ADJUST_LEN_ROUND
: avr_out_round (insn
, op
, &len
); break;
7620 case ADJUST_LEN_TSTHI
: avr_out_tsthi (insn
, op
, &len
); break;
7621 case ADJUST_LEN_TSTPSI
: avr_out_tstpsi (insn
, op
, &len
); break;
7622 case ADJUST_LEN_TSTSI
: avr_out_tstsi (insn
, op
, &len
); break;
7623 case ADJUST_LEN_COMPARE
: avr_out_compare (insn
, op
, &len
); break;
7624 case ADJUST_LEN_COMPARE64
: avr_out_compare64 (insn
, op
, &len
); break;
7626 case ADJUST_LEN_LSHRQI
: lshrqi3_out (insn
, op
, &len
); break;
7627 case ADJUST_LEN_LSHRHI
: lshrhi3_out (insn
, op
, &len
); break;
7628 case ADJUST_LEN_LSHRSI
: lshrsi3_out (insn
, op
, &len
); break;
7630 case ADJUST_LEN_ASHRQI
: ashrqi3_out (insn
, op
, &len
); break;
7631 case ADJUST_LEN_ASHRHI
: ashrhi3_out (insn
, op
, &len
); break;
7632 case ADJUST_LEN_ASHRSI
: ashrsi3_out (insn
, op
, &len
); break;
7634 case ADJUST_LEN_ASHLQI
: ashlqi3_out (insn
, op
, &len
); break;
7635 case ADJUST_LEN_ASHLHI
: ashlhi3_out (insn
, op
, &len
); break;
7636 case ADJUST_LEN_ASHLSI
: ashlsi3_out (insn
, op
, &len
); break;
7638 case ADJUST_LEN_ASHLPSI
: avr_out_ashlpsi3 (insn
, op
, &len
); break;
7639 case ADJUST_LEN_ASHRPSI
: avr_out_ashrpsi3 (insn
, op
, &len
); break;
7640 case ADJUST_LEN_LSHRPSI
: avr_out_lshrpsi3 (insn
, op
, &len
); break;
7642 case ADJUST_LEN_CALL
: len
= AVR_HAVE_JMP_CALL
? 2 : 1; break;
7644 case ADJUST_LEN_INSERT_BITS
: avr_out_insert_bits (op
, &len
); break;
7653 /* Return nonzero if register REG dead after INSN. */
7656 reg_unused_after (rtx insn
, rtx reg
)
7658 return (dead_or_set_p (insn
, reg
)
7659 || (REG_P(reg
) && _reg_unused_after (insn
, reg
)));
7662 /* Return nonzero if REG is not used after INSN.
7663 We assume REG is a reload reg, and therefore does
7664 not live past labels. It may live past calls or jumps though. */
7667 _reg_unused_after (rtx insn
, rtx reg
)
7672 /* If the reg is set by this instruction, then it is safe for our
7673 case. Disregard the case where this is a store to memory, since
7674 we are checking a register used in the store address. */
7675 set
= single_set (insn
);
7676 if (set
&& GET_CODE (SET_DEST (set
)) != MEM
7677 && reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
7680 while ((insn
= NEXT_INSN (insn
)))
7683 code
= GET_CODE (insn
);
7686 /* If this is a label that existed before reload, then the register
7687 if dead here. However, if this is a label added by reorg, then
7688 the register may still be live here. We can't tell the difference,
7689 so we just ignore labels completely. */
7690 if (code
== CODE_LABEL
)
7698 if (code
== JUMP_INSN
)
7701 /* If this is a sequence, we must handle them all at once.
7702 We could have for instance a call that sets the target register,
7703 and an insn in a delay slot that uses the register. In this case,
7704 we must return 0. */
7705 else if (code
== INSN
&& GET_CODE (PATTERN (insn
)) == SEQUENCE
)
7710 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
7712 rtx this_insn
= XVECEXP (PATTERN (insn
), 0, i
);
7713 rtx set
= single_set (this_insn
);
7715 if (GET_CODE (this_insn
) == CALL_INSN
)
7717 else if (GET_CODE (this_insn
) == JUMP_INSN
)
7719 if (INSN_ANNULLED_BRANCH_P (this_insn
))
7724 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
7726 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
7728 if (GET_CODE (SET_DEST (set
)) != MEM
)
7734 && reg_overlap_mentioned_p (reg
, PATTERN (this_insn
)))
7739 else if (code
== JUMP_INSN
)
7743 if (code
== CALL_INSN
)
7746 for (tem
= CALL_INSN_FUNCTION_USAGE (insn
); tem
; tem
= XEXP (tem
, 1))
7747 if (GET_CODE (XEXP (tem
, 0)) == USE
7748 && REG_P (XEXP (XEXP (tem
, 0), 0))
7749 && reg_overlap_mentioned_p (reg
, XEXP (XEXP (tem
, 0), 0)))
7751 if (call_used_regs
[REGNO (reg
)])
7755 set
= single_set (insn
);
7757 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
7759 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
7760 return GET_CODE (SET_DEST (set
)) != MEM
;
7761 if (set
== 0 && reg_overlap_mentioned_p (reg
, PATTERN (insn
)))
7768 /* Implement `TARGET_ASM_INTEGER'. */
7769 /* Target hook for assembling integer objects. The AVR version needs
7770 special handling for references to certain labels. */
7773 avr_assemble_integer (rtx x
, unsigned int size
, int aligned_p
)
7775 if (size
== POINTER_SIZE
/ BITS_PER_UNIT
&& aligned_p
7776 && text_segment_operand (x
, VOIDmode
))
7778 fputs ("\t.word\tgs(", asm_out_file
);
7779 output_addr_const (asm_out_file
, x
);
7780 fputs (")\n", asm_out_file
);
7784 else if (GET_MODE (x
) == PSImode
)
7786 /* This needs binutils 2.23+, see PR binutils/13503 */
7788 fputs ("\t.byte\tlo8(", asm_out_file
);
7789 output_addr_const (asm_out_file
, x
);
7790 fputs (")" ASM_COMMENT_START
"need binutils PR13503\n", asm_out_file
);
7792 fputs ("\t.byte\thi8(", asm_out_file
);
7793 output_addr_const (asm_out_file
, x
);
7794 fputs (")" ASM_COMMENT_START
"need binutils PR13503\n", asm_out_file
);
7796 fputs ("\t.byte\thh8(", asm_out_file
);
7797 output_addr_const (asm_out_file
, x
);
7798 fputs (")" ASM_COMMENT_START
"need binutils PR13503\n", asm_out_file
);
7802 else if (CONST_FIXED_P (x
))
7806 /* varasm fails to handle big fixed modes that don't fit in hwi. */
7808 for (n
= 0; n
< size
; n
++)
7810 rtx xn
= simplify_gen_subreg (QImode
, x
, GET_MODE (x
), n
);
7811 default_assemble_integer (xn
, 1, aligned_p
);
7817 return default_assemble_integer (x
, size
, aligned_p
);
7821 /* Implement `TARGET_CLASS_LIKELY_SPILLED_P'. */
7822 /* Return value is nonzero if pseudos that have been
7823 assigned to registers of class CLASS would likely be spilled
7824 because registers of CLASS are needed for spill registers. */
7827 avr_class_likely_spilled_p (reg_class_t c
)
7829 return (c
!= ALL_REGS
&& c
!= ADDW_REGS
);
7833 /* Valid attributes:
7834 progmem - Put data to program memory.
7835 signal - Make a function to be hardware interrupt.
7836 After function prologue interrupts remain disabled.
7837 interrupt - Make a function to be hardware interrupt. Before function
7838 prologue interrupts are enabled by means of SEI.
7839 naked - Don't generate function prologue/epilogue and RET
7842 /* Handle a "progmem" attribute; arguments as in
7843 struct attribute_spec.handler. */
7846 avr_handle_progmem_attribute (tree
*node
, tree name
,
7847 tree args ATTRIBUTE_UNUSED
,
7848 int flags ATTRIBUTE_UNUSED
,
7853 if (TREE_CODE (*node
) == TYPE_DECL
)
7855 /* This is really a decl attribute, not a type attribute,
7856 but try to handle it for GCC 3.0 backwards compatibility. */
7858 tree type
= TREE_TYPE (*node
);
7859 tree attr
= tree_cons (name
, args
, TYPE_ATTRIBUTES (type
));
7860 tree newtype
= build_type_attribute_variant (type
, attr
);
7862 TYPE_MAIN_VARIANT (newtype
) = TYPE_MAIN_VARIANT (type
);
7863 TREE_TYPE (*node
) = newtype
;
7864 *no_add_attrs
= true;
7866 else if (TREE_STATIC (*node
) || DECL_EXTERNAL (*node
))
7868 *no_add_attrs
= false;
7872 warning (OPT_Wattributes
, "%qE attribute ignored",
7874 *no_add_attrs
= true;
7881 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
7882 struct attribute_spec.handler. */
7885 avr_handle_fndecl_attribute (tree
*node
, tree name
,
7886 tree args ATTRIBUTE_UNUSED
,
7887 int flags ATTRIBUTE_UNUSED
,
7890 if (TREE_CODE (*node
) != FUNCTION_DECL
)
7892 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
7894 *no_add_attrs
= true;
7901 avr_handle_fntype_attribute (tree
*node
, tree name
,
7902 tree args ATTRIBUTE_UNUSED
,
7903 int flags ATTRIBUTE_UNUSED
,
7906 if (TREE_CODE (*node
) != FUNCTION_TYPE
)
7908 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
7910 *no_add_attrs
= true;
7917 /* AVR attributes. */
7918 static const struct attribute_spec
7919 avr_attribute_table
[] =
7921 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
7922 affects_type_identity } */
7923 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute
,
7925 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute
,
7927 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute
,
7929 { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute
,
7931 { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute
,
7933 { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute
,
7935 { NULL
, 0, 0, false, false, false, NULL
, false }
7939 /* Look if DECL shall be placed in program memory space by
7940 means of attribute `progmem' or some address-space qualifier.
7941 Return non-zero if DECL is data that must end up in Flash and
7942 zero if the data lives in RAM (.bss, .data, .rodata, ...).
7944 Return 2 if DECL is located in 24-bit flash address-space
7945 Return 1 if DECL is located in 16-bit flash address-space
7946 Return -1 if attribute `progmem' occurs in DECL or ATTRIBUTES
7947 Return 0 otherwise */
7950 avr_progmem_p (tree decl
, tree attributes
)
7954 if (TREE_CODE (decl
) != VAR_DECL
)
7957 if (avr_decl_memx_p (decl
))
7960 if (avr_decl_flash_p (decl
))
7964 != lookup_attribute ("progmem", attributes
))
7971 while (TREE_CODE (a
) == ARRAY_TYPE
);
7973 if (a
== error_mark_node
)
7976 if (NULL_TREE
!= lookup_attribute ("progmem", TYPE_ATTRIBUTES (a
)))
7983 /* Scan type TYP for pointer references to address space ASn.
7984 Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
7985 the AS are also declared to be CONST.
7986 Otherwise, return the respective address space, i.e. a value != 0. */
7989 avr_nonconst_pointer_addrspace (tree typ
)
7991 while (ARRAY_TYPE
== TREE_CODE (typ
))
7992 typ
= TREE_TYPE (typ
);
7994 if (POINTER_TYPE_P (typ
))
7997 tree target
= TREE_TYPE (typ
);
7999 /* Pointer to function: Test the function's return type. */
8001 if (FUNCTION_TYPE
== TREE_CODE (target
))
8002 return avr_nonconst_pointer_addrspace (TREE_TYPE (target
));
8004 /* "Ordinary" pointers... */
8006 while (TREE_CODE (target
) == ARRAY_TYPE
)
8007 target
= TREE_TYPE (target
);
8009 /* Pointers to non-generic address space must be const.
8010 Refuse address spaces outside the device's flash. */
8012 as
= TYPE_ADDR_SPACE (target
);
8014 if (!ADDR_SPACE_GENERIC_P (as
)
8015 && (!TYPE_READONLY (target
)
8016 || avr_addrspace
[as
].segment
>= avr_current_device
->n_flash
))
8021 /* Scan pointer's target type. */
8023 return avr_nonconst_pointer_addrspace (target
);
8026 return ADDR_SPACE_GENERIC
;
8030 /* Sanity check NODE so that all pointers targeting non-generic address spaces
8031 go along with CONST qualifier. Writing to these address spaces should
8032 be detected and complained about as early as possible. */
8035 avr_pgm_check_var_decl (tree node
)
8037 const char *reason
= NULL
;
8039 addr_space_t as
= ADDR_SPACE_GENERIC
;
8041 gcc_assert (as
== 0);
8043 if (avr_log
.progmem
)
8044 avr_edump ("%?: %t\n", node
);
8046 switch (TREE_CODE (node
))
8052 if (as
= avr_nonconst_pointer_addrspace (TREE_TYPE (node
)), as
)
8053 reason
= "variable";
8057 if (as
= avr_nonconst_pointer_addrspace (TREE_TYPE (node
)), as
)
8058 reason
= "function parameter";
8062 if (as
= avr_nonconst_pointer_addrspace (TREE_TYPE (node
)), as
)
8063 reason
= "structure field";
8067 if (as
= avr_nonconst_pointer_addrspace (TREE_TYPE (TREE_TYPE (node
))),
8069 reason
= "return type of function";
8073 if (as
= avr_nonconst_pointer_addrspace (node
), as
)
8080 if (avr_addrspace
[as
].segment
>= avr_current_device
->n_flash
)
8083 error ("%qT uses address space %qs beyond flash of %qs",
8084 node
, avr_addrspace
[as
].name
, avr_current_device
->name
);
8086 error ("%s %q+D uses address space %qs beyond flash of %qs",
8087 reason
, node
, avr_addrspace
[as
].name
,
8088 avr_current_device
->name
);
8093 error ("pointer targeting address space %qs must be const in %qT",
8094 avr_addrspace
[as
].name
, node
);
8096 error ("pointer targeting address space %qs must be const"
8098 avr_addrspace
[as
].name
, reason
, node
);
8102 return reason
== NULL
;
8106 /* Add the section attribute if the variable is in progmem. */
8109 avr_insert_attributes (tree node
, tree
*attributes
)
8111 avr_pgm_check_var_decl (node
);
8113 if (TREE_CODE (node
) == VAR_DECL
8114 && (TREE_STATIC (node
) || DECL_EXTERNAL (node
))
8115 && avr_progmem_p (node
, *attributes
))
8120 /* For C++, we have to peel arrays in order to get correct
8121 determination of readonlyness. */
8124 node0
= TREE_TYPE (node0
);
8125 while (TREE_CODE (node0
) == ARRAY_TYPE
);
8127 if (error_mark_node
== node0
)
8130 as
= TYPE_ADDR_SPACE (TREE_TYPE (node
));
8132 if (avr_addrspace
[as
].segment
>= avr_current_device
->n_flash
)
8134 error ("variable %q+D located in address space %qs"
8135 " beyond flash of %qs",
8136 node
, avr_addrspace
[as
].name
, avr_current_device
->name
);
8139 if (!TYPE_READONLY (node0
)
8140 && !TREE_READONLY (node
))
8142 const char *reason
= "__attribute__((progmem))";
8144 if (!ADDR_SPACE_GENERIC_P (as
))
8145 reason
= avr_addrspace
[as
].name
;
8147 if (avr_log
.progmem
)
8148 avr_edump ("\n%?: %t\n%t\n", node
, node0
);
8150 error ("variable %q+D must be const in order to be put into"
8151 " read-only section by means of %qs", node
, reason
);
8157 /* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'. */
8158 /* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'. */
8159 /* Track need of __do_clear_bss. */
8162 avr_asm_output_aligned_decl_common (FILE * stream
,
8163 const_tree decl ATTRIBUTE_UNUSED
,
8165 unsigned HOST_WIDE_INT size
,
8166 unsigned int align
, bool local_p
)
8168 /* __gnu_lto_v1 etc. are just markers for the linker injected by toplev.c.
8169 There is no need to trigger __do_clear_bss code for them. */
8171 if (!STR_PREFIX_P (name
, "__gnu_lto"))
8172 avr_need_clear_bss_p
= true;
8175 ASM_OUTPUT_ALIGNED_LOCAL (stream
, name
, size
, align
);
8177 ASM_OUTPUT_ALIGNED_COMMON (stream
, name
, size
, align
);
8181 /* Unnamed section callback for data_section
8182 to track need of __do_copy_data. */
8185 avr_output_data_section_asm_op (const void *data
)
8187 avr_need_copy_data_p
= true;
8189 /* Dispatch to default. */
8190 output_section_asm_op (data
);
8194 /* Unnamed section callback for bss_section
8195 to track need of __do_clear_bss. */
8198 avr_output_bss_section_asm_op (const void *data
)
8200 avr_need_clear_bss_p
= true;
8202 /* Dispatch to default. */
8203 output_section_asm_op (data
);
8207 /* Unnamed section callback for progmem*.data sections. */
8210 avr_output_progmem_section_asm_op (const void *data
)
8212 fprintf (asm_out_file
, "\t.section\t%s,\"a\",@progbits\n",
8213 (const char*) data
);
8217 /* Implement `TARGET_ASM_INIT_SECTIONS'. */
8220 avr_asm_init_sections (void)
8222 /* Set up a section for jump tables. Alignment is handled by
8223 ASM_OUTPUT_BEFORE_CASE_LABEL. */
8225 if (AVR_HAVE_JMP_CALL
)
8227 progmem_swtable_section
8228 = get_unnamed_section (0, output_section_asm_op
,
8229 "\t.section\t.progmem.gcc_sw_table"
8230 ",\"a\",@progbits");
8234 progmem_swtable_section
8235 = get_unnamed_section (SECTION_CODE
, output_section_asm_op
,
8236 "\t.section\t.progmem.gcc_sw_table"
8237 ",\"ax\",@progbits");
8240 /* Override section callbacks to keep track of `avr_need_clear_bss_p'
8241 resp. `avr_need_copy_data_p'. */
8243 readonly_data_section
->unnamed
.callback
= avr_output_data_section_asm_op
;
8244 data_section
->unnamed
.callback
= avr_output_data_section_asm_op
;
8245 bss_section
->unnamed
.callback
= avr_output_bss_section_asm_op
;
8249 /* Implement `TARGET_ASM_FUNCTION_RODATA_SECTION'. */
8252 avr_asm_function_rodata_section (tree decl
)
8254 /* If a function is unused and optimized out by -ffunction-sections
8255 and --gc-sections, ensure that the same will happen for its jump
8256 tables by putting them into individual sections. */
8261 /* Get the frodata section from the default function in varasm.c
8262 but treat function-associated data-like jump tables as code
8263 rather than as user defined data. AVR has no constant pools. */
8265 int fdata
= flag_data_sections
;
8267 flag_data_sections
= flag_function_sections
;
8268 frodata
= default_function_rodata_section (decl
);
8269 flag_data_sections
= fdata
;
8270 flags
= frodata
->common
.flags
;
8273 if (frodata
!= readonly_data_section
8274 && flags
& SECTION_NAMED
)
8276 /* Adjust section flags and replace section name prefix. */
8280 static const char* const prefix
[] =
8282 ".rodata", ".progmem.gcc_sw_table",
8283 ".gnu.linkonce.r.", ".gnu.linkonce.t."
8286 for (i
= 0; i
< sizeof (prefix
) / sizeof (*prefix
); i
+= 2)
8288 const char * old_prefix
= prefix
[i
];
8289 const char * new_prefix
= prefix
[i
+1];
8290 const char * name
= frodata
->named
.name
;
8292 if (STR_PREFIX_P (name
, old_prefix
))
8294 const char *rname
= ACONCAT ((new_prefix
,
8295 name
+ strlen (old_prefix
), NULL
));
8296 flags
&= ~SECTION_CODE
;
8297 flags
|= AVR_HAVE_JMP_CALL
? 0 : SECTION_CODE
;
8299 return get_section (rname
, flags
, frodata
->named
.decl
);
8304 return progmem_swtable_section
;
8308 /* Implement `TARGET_ASM_NAMED_SECTION'. */
8309 /* Track need of __do_clear_bss, __do_copy_data for named sections. */
8312 avr_asm_named_section (const char *name
, unsigned int flags
, tree decl
)
8314 if (flags
& AVR_SECTION_PROGMEM
)
8316 addr_space_t as
= (flags
& AVR_SECTION_PROGMEM
) / SECTION_MACH_DEP
;
8317 const char *old_prefix
= ".rodata";
8318 const char *new_prefix
= avr_addrspace
[as
].section_name
;
8320 if (STR_PREFIX_P (name
, old_prefix
))
8322 const char *sname
= ACONCAT ((new_prefix
,
8323 name
+ strlen (old_prefix
), NULL
));
8324 default_elf_asm_named_section (sname
, flags
, decl
);
8328 default_elf_asm_named_section (new_prefix
, flags
, decl
);
8332 if (!avr_need_copy_data_p
)
8333 avr_need_copy_data_p
= (STR_PREFIX_P (name
, ".data")
8334 || STR_PREFIX_P (name
, ".rodata")
8335 || STR_PREFIX_P (name
, ".gnu.linkonce.d"));
8337 if (!avr_need_clear_bss_p
)
8338 avr_need_clear_bss_p
= STR_PREFIX_P (name
, ".bss");
8340 default_elf_asm_named_section (name
, flags
, decl
);
8344 /* Implement `TARGET_SECTION_TYPE_FLAGS'. */
8347 avr_section_type_flags (tree decl
, const char *name
, int reloc
)
8349 unsigned int flags
= default_section_type_flags (decl
, name
, reloc
);
8351 if (STR_PREFIX_P (name
, ".noinit"))
8353 if (decl
&& TREE_CODE (decl
) == VAR_DECL
8354 && DECL_INITIAL (decl
) == NULL_TREE
)
8355 flags
|= SECTION_BSS
; /* @nobits */
8357 warning (0, "only uninitialized variables can be placed in the "
8361 if (decl
&& DECL_P (decl
)
8362 && avr_progmem_p (decl
, DECL_ATTRIBUTES (decl
)))
8364 addr_space_t as
= TYPE_ADDR_SPACE (TREE_TYPE (decl
));
8366 /* Attribute progmem puts data in generic address space.
8367 Set section flags as if it was in __flash to get the right
8368 section prefix in the remainder. */
8370 if (ADDR_SPACE_GENERIC_P (as
))
8371 as
= ADDR_SPACE_FLASH
;
8373 flags
|= as
* SECTION_MACH_DEP
;
8374 flags
&= ~SECTION_WRITE
;
8375 flags
&= ~SECTION_BSS
;
8382 /* Implement `TARGET_ENCODE_SECTION_INFO'. */
8385 avr_encode_section_info (tree decl
, rtx rtl
, int new_decl_p
)
8387 /* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
8388 readily available, see PR34734. So we postpone the warning
8389 about uninitialized data in program memory section until here. */
8392 && decl
&& DECL_P (decl
)
8393 && NULL_TREE
== DECL_INITIAL (decl
)
8394 && !DECL_EXTERNAL (decl
)
8395 && avr_progmem_p (decl
, DECL_ATTRIBUTES (decl
)))
8397 warning (OPT_Wuninitialized
,
8398 "uninitialized variable %q+D put into "
8399 "program memory area", decl
);
8402 default_encode_section_info (decl
, rtl
, new_decl_p
);
8404 if (decl
&& DECL_P (decl
)
8405 && TREE_CODE (decl
) != FUNCTION_DECL
8407 && SYMBOL_REF
== GET_CODE (XEXP (rtl
, 0)))
8409 rtx sym
= XEXP (rtl
, 0);
8410 addr_space_t as
= TYPE_ADDR_SPACE (TREE_TYPE (decl
));
8412 /* PSTR strings are in generic space but located in flash:
8413 patch address space. */
8415 if (-1 == avr_progmem_p (decl
, DECL_ATTRIBUTES (decl
)))
8416 as
= ADDR_SPACE_FLASH
;
8418 AVR_SYMBOL_SET_ADDR_SPACE (sym
, as
);
8423 /* Implement `TARGET_ASM_SELECT_SECTION' */
8426 avr_asm_select_section (tree decl
, int reloc
, unsigned HOST_WIDE_INT align
)
8428 section
* sect
= default_elf_select_section (decl
, reloc
, align
);
8430 if (decl
&& DECL_P (decl
)
8431 && avr_progmem_p (decl
, DECL_ATTRIBUTES (decl
)))
8433 addr_space_t as
= TYPE_ADDR_SPACE (TREE_TYPE (decl
));
8435 /* __progmem__ goes in generic space but shall be allocated to
8438 if (ADDR_SPACE_GENERIC_P (as
))
8439 as
= ADDR_SPACE_FLASH
;
8441 if (sect
->common
.flags
& SECTION_NAMED
)
8443 const char * name
= sect
->named
.name
;
8444 const char * old_prefix
= ".rodata";
8445 const char * new_prefix
= avr_addrspace
[as
].section_name
;
8447 if (STR_PREFIX_P (name
, old_prefix
))
8449 const char *sname
= ACONCAT ((new_prefix
,
8450 name
+ strlen (old_prefix
), NULL
));
8451 return get_section (sname
, sect
->common
.flags
, sect
->named
.decl
);
8455 if (!progmem_section
[as
])
8458 = get_unnamed_section (0, avr_output_progmem_section_asm_op
,
8459 avr_addrspace
[as
].section_name
);
8462 return progmem_section
[as
];
8468 /* Implement `TARGET_ASM_FILE_START'. */
8469 /* Outputs some text at the start of each assembler file. */
8472 avr_file_start (void)
8474 int sfr_offset
= avr_current_arch
->sfr_offset
;
8476 if (avr_current_arch
->asm_only
)
8477 error ("MCU %qs supported for assembler only", avr_current_device
->name
);
8479 default_file_start ();
8481 /* Print I/O addresses of some SFRs used with IN and OUT. */
8484 fprintf (asm_out_file
, "__SP_H__ = 0x%02x\n", avr_addr
.sp_h
- sfr_offset
);
8486 fprintf (asm_out_file
, "__SP_L__ = 0x%02x\n", avr_addr
.sp_l
- sfr_offset
);
8487 fprintf (asm_out_file
, "__SREG__ = 0x%02x\n", avr_addr
.sreg
- sfr_offset
);
8489 fprintf (asm_out_file
, "__RAMPZ__ = 0x%02x\n", avr_addr
.rampz
- sfr_offset
);
8491 fprintf (asm_out_file
, "__RAMPY__ = 0x%02x\n", avr_addr
.rampy
- sfr_offset
);
8493 fprintf (asm_out_file
, "__RAMPX__ = 0x%02x\n", avr_addr
.rampx
- sfr_offset
);
8495 fprintf (asm_out_file
, "__RAMPD__ = 0x%02x\n", avr_addr
.rampd
- sfr_offset
);
8497 fprintf (asm_out_file
, "__CCP__ = 0x%02x\n", avr_addr
.ccp
- sfr_offset
);
8498 fprintf (asm_out_file
, "__tmp_reg__ = %d\n", TMP_REGNO
);
8499 fprintf (asm_out_file
, "__zero_reg__ = %d\n", ZERO_REGNO
);
8503 /* Implement `TARGET_ASM_FILE_END'. */
8504 /* Outputs to the stdio stream FILE some
8505 appropriate text to go at the end of an assembler file. */
8510 /* Output these only if there is anything in the
8511 .data* / .rodata* / .gnu.linkonce.* resp. .bss* or COMMON
8512 input section(s) - some code size can be saved by not
8513 linking in the initialization code from libgcc if resp.
8514 sections are empty, see PR18145. */
8516 if (avr_need_copy_data_p
)
8517 fputs (".global __do_copy_data\n", asm_out_file
);
8519 if (avr_need_clear_bss_p
)
8520 fputs (".global __do_clear_bss\n", asm_out_file
);
8524 /* Worker function for `ADJUST_REG_ALLOC_ORDER'. */
8525 /* Choose the order in which to allocate hard registers for
8526 pseudo-registers local to a basic block.
8528 Store the desired register order in the array `reg_alloc_order'.
8529 Element 0 should be the register to allocate first; element 1, the
8530 next register; and so on. */
8533 avr_adjust_reg_alloc_order (void)
8536 static const int order_0
[] =
8539 18, 19, 20, 21, 22, 23,
8542 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
8546 static const int order_1
[] =
8548 18, 19, 20, 21, 22, 23, 24, 25,
8551 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
8555 static const int order_2
[] =
8557 25, 24, 23, 22, 21, 20, 19, 18,
8560 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
8565 const int *order
= (TARGET_ORDER_1
? order_1
:
8566 TARGET_ORDER_2
? order_2
:
8568 for (i
= 0; i
< ARRAY_SIZE (order_0
); ++i
)
8569 reg_alloc_order
[i
] = order
[i
];
8573 /* Implement `TARGET_REGISTER_MOVE_COST' */
8576 avr_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED
,
8577 reg_class_t from
, reg_class_t to
)
8579 return (from
== STACK_REG
? 6
8580 : to
== STACK_REG
? 12
8585 /* Implement `TARGET_MEMORY_MOVE_COST' */
8588 avr_memory_move_cost (enum machine_mode mode
,
8589 reg_class_t rclass ATTRIBUTE_UNUSED
,
8590 bool in ATTRIBUTE_UNUSED
)
8592 return (mode
== QImode
? 2
8593 : mode
== HImode
? 4
8594 : mode
== SImode
? 8
8595 : mode
== SFmode
? 8
8600 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
8601 cost of an RTX operand given its context. X is the rtx of the
8602 operand, MODE is its mode, and OUTER is the rtx_code of this
8603 operand's parent operator. */
8606 avr_operand_rtx_cost (rtx x
, enum machine_mode mode
, enum rtx_code outer
,
8607 int opno
, bool speed
)
8609 enum rtx_code code
= GET_CODE (x
);
8621 return COSTS_N_INSNS (GET_MODE_SIZE (mode
));
8628 avr_rtx_costs (x
, code
, outer
, opno
, &total
, speed
);
8632 /* Worker function for AVR backend's rtx_cost function.
8633 X is rtx expression whose cost is to be calculated.
8634 Return true if the complete cost has been computed.
8635 Return false if subexpressions should be scanned.
8636 In either case, *TOTAL contains the cost result. */
8639 avr_rtx_costs_1 (rtx x
, int codearg
, int outer_code ATTRIBUTE_UNUSED
,
8640 int opno ATTRIBUTE_UNUSED
, int *total
, bool speed
)
8642 enum rtx_code code
= (enum rtx_code
) codearg
;
8643 enum machine_mode mode
= GET_MODE (x
);
8654 /* Immediate constants are as cheap as registers. */
8659 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
8667 *total
= COSTS_N_INSNS (1);
8673 *total
= COSTS_N_INSNS (2 * GET_MODE_SIZE (mode
) - 1);
8679 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
8687 *total
= COSTS_N_INSNS (1);
8693 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
8697 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
8698 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
8702 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
)
8703 - GET_MODE_SIZE (GET_MODE (XEXP (x
, 0))));
8704 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
8708 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) + 2
8709 - GET_MODE_SIZE (GET_MODE (XEXP (x
, 0))));
8710 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
8718 && MULT
== GET_CODE (XEXP (x
, 0))
8719 && register_operand (XEXP (x
, 1), QImode
))
8722 *total
= COSTS_N_INSNS (speed
? 4 : 3);
8723 /* multiply-add with constant: will be split and load constant. */
8724 if (CONST_INT_P (XEXP (XEXP (x
, 0), 1)))
8725 *total
= COSTS_N_INSNS (1) + *total
;
8728 *total
= COSTS_N_INSNS (1);
8729 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
8730 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1, speed
);
8735 && (MULT
== GET_CODE (XEXP (x
, 0))
8736 || ASHIFT
== GET_CODE (XEXP (x
, 0)))
8737 && register_operand (XEXP (x
, 1), HImode
)
8738 && (ZERO_EXTEND
== GET_CODE (XEXP (XEXP (x
, 0), 0))
8739 || SIGN_EXTEND
== GET_CODE (XEXP (XEXP (x
, 0), 0))))
8742 *total
= COSTS_N_INSNS (speed
? 5 : 4);
8743 /* multiply-add with constant: will be split and load constant. */
8744 if (CONST_INT_P (XEXP (XEXP (x
, 0), 1)))
8745 *total
= COSTS_N_INSNS (1) + *total
;
8748 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
8750 *total
= COSTS_N_INSNS (2);
8751 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
8754 else if (INTVAL (XEXP (x
, 1)) >= -63 && INTVAL (XEXP (x
, 1)) <= 63)
8755 *total
= COSTS_N_INSNS (1);
8757 *total
= COSTS_N_INSNS (2);
8761 if (!CONST_INT_P (XEXP (x
, 1)))
8763 *total
= COSTS_N_INSNS (3);
8764 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
8767 else if (INTVAL (XEXP (x
, 1)) >= -63 && INTVAL (XEXP (x
, 1)) <= 63)
8768 *total
= COSTS_N_INSNS (2);
8770 *total
= COSTS_N_INSNS (3);
8774 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
8776 *total
= COSTS_N_INSNS (4);
8777 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
8780 else if (INTVAL (XEXP (x
, 1)) >= -63 && INTVAL (XEXP (x
, 1)) <= 63)
8781 *total
= COSTS_N_INSNS (1);
8783 *total
= COSTS_N_INSNS (4);
8789 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
8795 && register_operand (XEXP (x
, 0), QImode
)
8796 && MULT
== GET_CODE (XEXP (x
, 1)))
8799 *total
= COSTS_N_INSNS (speed
? 4 : 3);
8800 /* multiply-sub with constant: will be split and load constant. */
8801 if (CONST_INT_P (XEXP (XEXP (x
, 1), 1)))
8802 *total
= COSTS_N_INSNS (1) + *total
;
8807 && register_operand (XEXP (x
, 0), HImode
)
8808 && (MULT
== GET_CODE (XEXP (x
, 1))
8809 || ASHIFT
== GET_CODE (XEXP (x
, 1)))
8810 && (ZERO_EXTEND
== GET_CODE (XEXP (XEXP (x
, 1), 0))
8811 || SIGN_EXTEND
== GET_CODE (XEXP (XEXP (x
, 1), 0))))
8814 *total
= COSTS_N_INSNS (speed
? 5 : 4);
8815 /* multiply-sub with constant: will be split and load constant. */
8816 if (CONST_INT_P (XEXP (XEXP (x
, 1), 1)))
8817 *total
= COSTS_N_INSNS (1) + *total
;
8823 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
8824 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
8825 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
8826 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1, speed
);
8830 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
8831 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
8832 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1, speed
);
8840 *total
= COSTS_N_INSNS (!speed
? 3 : 4);
8842 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 2 : 1);
8850 rtx op0
= XEXP (x
, 0);
8851 rtx op1
= XEXP (x
, 1);
8852 enum rtx_code code0
= GET_CODE (op0
);
8853 enum rtx_code code1
= GET_CODE (op1
);
8854 bool ex0
= SIGN_EXTEND
== code0
|| ZERO_EXTEND
== code0
;
8855 bool ex1
= SIGN_EXTEND
== code1
|| ZERO_EXTEND
== code1
;
8858 && (u8_operand (op1
, HImode
)
8859 || s8_operand (op1
, HImode
)))
8861 *total
= COSTS_N_INSNS (!speed
? 4 : 6);
8865 && register_operand (op1
, HImode
))
8867 *total
= COSTS_N_INSNS (!speed
? 5 : 8);
8870 else if (ex0
|| ex1
)
8872 *total
= COSTS_N_INSNS (!speed
? 3 : 5);
8875 else if (register_operand (op0
, HImode
)
8876 && (u8_operand (op1
, HImode
)
8877 || s8_operand (op1
, HImode
)))
8879 *total
= COSTS_N_INSNS (!speed
? 6 : 9);
8883 *total
= COSTS_N_INSNS (!speed
? 7 : 10);
8886 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 2 : 1);
8893 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 2 : 1);
8903 /* Add some additional costs besides CALL like moves etc. */
8905 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 5 : 4);
8909 /* Just a rough estimate. Even with -O2 we don't want bulky
8910 code expanded inline. */
8912 *total
= COSTS_N_INSNS (25);
8918 *total
= COSTS_N_INSNS (300);
8920 /* Add some additional costs besides CALL like moves etc. */
8921 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 5 : 4);
8929 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
8930 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1, speed
);
8938 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 2 : 1);
8940 *total
= COSTS_N_INSNS (15 * GET_MODE_SIZE (mode
));
8941 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
8942 /* For div/mod with const-int divisor we have at least the cost of
8943 loading the divisor. */
8944 if (CONST_INT_P (XEXP (x
, 1)))
8945 *total
+= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
8946 /* Add some overall penaly for clobbering and moving around registers */
8947 *total
+= COSTS_N_INSNS (2);
8954 if (CONST_INT_P (XEXP (x
, 1)) && INTVAL (XEXP (x
, 1)) == 4)
8955 *total
= COSTS_N_INSNS (1);
8960 if (CONST_INT_P (XEXP (x
, 1)) && INTVAL (XEXP (x
, 1)) == 8)
8961 *total
= COSTS_N_INSNS (3);
8966 if (CONST_INT_P (XEXP (x
, 1)))
8967 switch (INTVAL (XEXP (x
, 1)))
8971 *total
= COSTS_N_INSNS (5);
8974 *total
= COSTS_N_INSNS (AVR_HAVE_MOVW
? 4 : 6);
8982 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
8989 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
8991 *total
= COSTS_N_INSNS (!speed
? 4 : 17);
8992 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
8997 val
= INTVAL (XEXP (x
, 1));
8999 *total
= COSTS_N_INSNS (3);
9000 else if (val
>= 0 && val
<= 7)
9001 *total
= COSTS_N_INSNS (val
);
9003 *total
= COSTS_N_INSNS (1);
9010 if (const_2_to_7_operand (XEXP (x
, 1), HImode
)
9011 && (SIGN_EXTEND
== GET_CODE (XEXP (x
, 0))
9012 || ZERO_EXTEND
== GET_CODE (XEXP (x
, 0))))
9014 *total
= COSTS_N_INSNS (!speed
? 4 : 6);
9019 if (const1_rtx
== (XEXP (x
, 1))
9020 && SIGN_EXTEND
== GET_CODE (XEXP (x
, 0)))
9022 *total
= COSTS_N_INSNS (2);
9026 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
9028 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
9029 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
9033 switch (INTVAL (XEXP (x
, 1)))
9040 *total
= COSTS_N_INSNS (2);
9043 *total
= COSTS_N_INSNS (3);
9049 *total
= COSTS_N_INSNS (4);
9054 *total
= COSTS_N_INSNS (5);
9057 *total
= COSTS_N_INSNS (!speed
? 5 : 8);
9060 *total
= COSTS_N_INSNS (!speed
? 5 : 9);
9063 *total
= COSTS_N_INSNS (!speed
? 5 : 10);
9066 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
9067 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
9073 if (!CONST_INT_P (XEXP (x
, 1)))
9075 *total
= COSTS_N_INSNS (!speed
? 6 : 73);
9078 switch (INTVAL (XEXP (x
, 1)))
9086 *total
= COSTS_N_INSNS (3);
9089 *total
= COSTS_N_INSNS (5);
9092 *total
= COSTS_N_INSNS (!speed
? 5 : 3 * INTVAL (XEXP (x
, 1)));
9098 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
9100 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
9101 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
9105 switch (INTVAL (XEXP (x
, 1)))
9111 *total
= COSTS_N_INSNS (3);
9116 *total
= COSTS_N_INSNS (4);
9119 *total
= COSTS_N_INSNS (6);
9122 *total
= COSTS_N_INSNS (!speed
? 7 : 8);
9125 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
9126 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
9134 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
9141 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
9143 *total
= COSTS_N_INSNS (!speed
? 4 : 17);
9144 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
9149 val
= INTVAL (XEXP (x
, 1));
9151 *total
= COSTS_N_INSNS (4);
9153 *total
= COSTS_N_INSNS (2);
9154 else if (val
>= 0 && val
<= 7)
9155 *total
= COSTS_N_INSNS (val
);
9157 *total
= COSTS_N_INSNS (1);
9162 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
9164 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
9165 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
9169 switch (INTVAL (XEXP (x
, 1)))
9175 *total
= COSTS_N_INSNS (2);
9178 *total
= COSTS_N_INSNS (3);
9184 *total
= COSTS_N_INSNS (4);
9188 *total
= COSTS_N_INSNS (5);
9191 *total
= COSTS_N_INSNS (!speed
? 5 : 6);
9194 *total
= COSTS_N_INSNS (!speed
? 5 : 7);
9198 *total
= COSTS_N_INSNS (!speed
? 5 : 8);
9201 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
9202 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
9208 if (!CONST_INT_P (XEXP (x
, 1)))
9210 *total
= COSTS_N_INSNS (!speed
? 6 : 73);
9213 switch (INTVAL (XEXP (x
, 1)))
9219 *total
= COSTS_N_INSNS (3);
9223 *total
= COSTS_N_INSNS (5);
9226 *total
= COSTS_N_INSNS (4);
9229 *total
= COSTS_N_INSNS (!speed
? 5 : 3 * INTVAL (XEXP (x
, 1)));
9235 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
9237 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
9238 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
9242 switch (INTVAL (XEXP (x
, 1)))
9248 *total
= COSTS_N_INSNS (4);
9253 *total
= COSTS_N_INSNS (6);
9256 *total
= COSTS_N_INSNS (!speed
? 7 : 8);
9259 *total
= COSTS_N_INSNS (AVR_HAVE_MOVW
? 4 : 5);
9262 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
9263 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
9271 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
9278 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
9280 *total
= COSTS_N_INSNS (!speed
? 4 : 17);
9281 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
9286 val
= INTVAL (XEXP (x
, 1));
9288 *total
= COSTS_N_INSNS (3);
9289 else if (val
>= 0 && val
<= 7)
9290 *total
= COSTS_N_INSNS (val
);
9292 *total
= COSTS_N_INSNS (1);
9297 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
9299 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
9300 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
9304 switch (INTVAL (XEXP (x
, 1)))
9311 *total
= COSTS_N_INSNS (2);
9314 *total
= COSTS_N_INSNS (3);
9319 *total
= COSTS_N_INSNS (4);
9323 *total
= COSTS_N_INSNS (5);
9329 *total
= COSTS_N_INSNS (!speed
? 5 : 6);
9332 *total
= COSTS_N_INSNS (!speed
? 5 : 7);
9336 *total
= COSTS_N_INSNS (!speed
? 5 : 9);
9339 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
9340 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
9346 if (!CONST_INT_P (XEXP (x
, 1)))
9348 *total
= COSTS_N_INSNS (!speed
? 6 : 73);
9351 switch (INTVAL (XEXP (x
, 1)))
9359 *total
= COSTS_N_INSNS (3);
9362 *total
= COSTS_N_INSNS (5);
9365 *total
= COSTS_N_INSNS (!speed
? 5 : 3 * INTVAL (XEXP (x
, 1)));
9371 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
9373 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
9374 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
9378 switch (INTVAL (XEXP (x
, 1)))
9384 *total
= COSTS_N_INSNS (4);
9387 *total
= COSTS_N_INSNS (!speed
? 7 : 8);
9392 *total
= COSTS_N_INSNS (4);
9395 *total
= COSTS_N_INSNS (6);
9398 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
9399 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
9407 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
9411 switch (GET_MODE (XEXP (x
, 0)))
9414 *total
= COSTS_N_INSNS (1);
9415 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
9416 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1, speed
);
9420 *total
= COSTS_N_INSNS (2);
9421 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
9422 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1, speed
);
9423 else if (INTVAL (XEXP (x
, 1)) != 0)
9424 *total
+= COSTS_N_INSNS (1);
9428 *total
= COSTS_N_INSNS (3);
9429 if (CONST_INT_P (XEXP (x
, 1)) && INTVAL (XEXP (x
, 1)) != 0)
9430 *total
+= COSTS_N_INSNS (2);
9434 *total
= COSTS_N_INSNS (4);
9435 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
9436 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1, speed
);
9437 else if (INTVAL (XEXP (x
, 1)) != 0)
9438 *total
+= COSTS_N_INSNS (3);
9444 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
9449 && LSHIFTRT
== GET_CODE (XEXP (x
, 0))
9450 && MULT
== GET_CODE (XEXP (XEXP (x
, 0), 0))
9451 && CONST_INT_P (XEXP (XEXP (x
, 0), 1)))
9453 if (QImode
== mode
|| HImode
== mode
)
9455 *total
= COSTS_N_INSNS (2);
9468 /* Implement `TARGET_RTX_COSTS'. */
9471 avr_rtx_costs (rtx x
, int codearg
, int outer_code
,
9472 int opno
, int *total
, bool speed
)
9474 bool done
= avr_rtx_costs_1 (x
, codearg
, outer_code
,
9475 opno
, total
, speed
);
9477 if (avr_log
.rtx_costs
)
9479 avr_edump ("\n%?=%b (%s) total=%d, outer=%C:\n%r\n",
9480 done
, speed
? "speed" : "size", *total
, outer_code
, x
);
9487 /* Implement `TARGET_ADDRESS_COST'. */
9490 avr_address_cost (rtx x
, enum machine_mode mode ATTRIBUTE_UNUSED
,
9491 addr_space_t as ATTRIBUTE_UNUSED
,
9492 bool speed ATTRIBUTE_UNUSED
)
9496 if (GET_CODE (x
) == PLUS
9497 && CONST_INT_P (XEXP (x
, 1))
9498 && (REG_P (XEXP (x
, 0))
9499 || GET_CODE (XEXP (x
, 0)) == SUBREG
))
9501 if (INTVAL (XEXP (x
, 1)) >= 61)
9504 else if (CONSTANT_ADDRESS_P (x
))
9507 && io_address_operand (x
, QImode
))
9511 if (avr_log
.address_cost
)
9512 avr_edump ("\n%?: %d = %r\n", cost
, x
);
9517 /* Test for extra memory constraint 'Q'.
9518 It's a memory address based on Y or Z pointer with valid displacement. */
9521 extra_constraint_Q (rtx x
)
9525 if (GET_CODE (XEXP (x
,0)) == PLUS
9526 && REG_P (XEXP (XEXP (x
,0), 0))
9527 && GET_CODE (XEXP (XEXP (x
,0), 1)) == CONST_INT
9528 && (INTVAL (XEXP (XEXP (x
,0), 1))
9529 <= MAX_LD_OFFSET (GET_MODE (x
))))
9531 rtx xx
= XEXP (XEXP (x
,0), 0);
9532 int regno
= REGNO (xx
);
9534 ok
= (/* allocate pseudos */
9535 regno
>= FIRST_PSEUDO_REGISTER
9536 /* strictly check */
9537 || regno
== REG_Z
|| regno
== REG_Y
9538 /* XXX frame & arg pointer checks */
9539 || xx
== frame_pointer_rtx
9540 || xx
== arg_pointer_rtx
);
9542 if (avr_log
.constraints
)
9543 avr_edump ("\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n",
9544 ok
, reload_completed
, reload_in_progress
, x
);
9550 /* Convert condition code CONDITION to the valid AVR condition code. */
9553 avr_normalize_condition (RTX_CODE condition
)
9570 /* Helper function for `avr_reorg'. */
9573 avr_compare_pattern (rtx insn
)
9575 rtx pattern
= single_set (insn
);
9578 && NONJUMP_INSN_P (insn
)
9579 && SET_DEST (pattern
) == cc0_rtx
9580 && GET_CODE (SET_SRC (pattern
)) == COMPARE
)
9582 enum machine_mode mode0
= GET_MODE (XEXP (SET_SRC (pattern
), 0));
9583 enum machine_mode mode1
= GET_MODE (XEXP (SET_SRC (pattern
), 1));
9585 /* The 64-bit comparisons have fixed operands ACC_A and ACC_B.
9586 They must not be swapped, thus skip them. */
9588 if ((mode0
== VOIDmode
|| GET_MODE_SIZE (mode0
) <= 4)
9589 && (mode1
== VOIDmode
|| GET_MODE_SIZE (mode1
) <= 4))
9596 /* Helper function for `avr_reorg'. */
9598 /* Expansion of switch/case decision trees leads to code like
9600 cc0 = compare (Reg, Num)
9604 cc0 = compare (Reg, Num)
9608 The second comparison is superfluous and can be deleted.
9609 The second jump condition can be transformed from a
9610 "difficult" one to a "simple" one because "cc0 > 0" and
9611 "cc0 >= 0" will have the same effect here.
9613 This function relies on the way switch/case is being expaned
9614 as binary decision tree. For example code see PR 49903.
9616 Return TRUE if optimization performed.
9617 Return FALSE if nothing changed.
9619 INSN1 is a comparison, i.e. avr_compare_pattern != 0.
9621 We don't want to do this in text peephole because it is
9622 tedious to work out jump offsets there and the second comparison
9623 might have been transormed by `avr_reorg'.
9625 RTL peephole won't do because peephole2 does not scan across
9629 avr_reorg_remove_redundant_compare (rtx insn1
)
9631 rtx comp1
, ifelse1
, xcond1
, branch1
;
9632 rtx comp2
, ifelse2
, xcond2
, branch2
, insn2
;
9634 rtx jump
, target
, cond
;
9636 /* Look out for: compare1 - branch1 - compare2 - branch2 */
9638 branch1
= next_nonnote_nondebug_insn (insn1
);
9639 if (!branch1
|| !JUMP_P (branch1
))
9642 insn2
= next_nonnote_nondebug_insn (branch1
);
9643 if (!insn2
|| !avr_compare_pattern (insn2
))
9646 branch2
= next_nonnote_nondebug_insn (insn2
);
9647 if (!branch2
|| !JUMP_P (branch2
))
9650 comp1
= avr_compare_pattern (insn1
);
9651 comp2
= avr_compare_pattern (insn2
);
9652 xcond1
= single_set (branch1
);
9653 xcond2
= single_set (branch2
);
9655 if (!comp1
|| !comp2
9656 || !rtx_equal_p (comp1
, comp2
)
9657 || !xcond1
|| SET_DEST (xcond1
) != pc_rtx
9658 || !xcond2
|| SET_DEST (xcond2
) != pc_rtx
9659 || IF_THEN_ELSE
!= GET_CODE (SET_SRC (xcond1
))
9660 || IF_THEN_ELSE
!= GET_CODE (SET_SRC (xcond2
)))
9665 comp1
= SET_SRC (comp1
);
9666 ifelse1
= SET_SRC (xcond1
);
9667 ifelse2
= SET_SRC (xcond2
);
9669 /* comp<n> is COMPARE now and ifelse<n> is IF_THEN_ELSE. */
9671 if (EQ
!= GET_CODE (XEXP (ifelse1
, 0))
9672 || !REG_P (XEXP (comp1
, 0))
9673 || !CONST_INT_P (XEXP (comp1
, 1))
9674 || XEXP (ifelse1
, 2) != pc_rtx
9675 || XEXP (ifelse2
, 2) != pc_rtx
9676 || LABEL_REF
!= GET_CODE (XEXP (ifelse1
, 1))
9677 || LABEL_REF
!= GET_CODE (XEXP (ifelse2
, 1))
9678 || !COMPARISON_P (XEXP (ifelse2
, 0))
9679 || cc0_rtx
!= XEXP (XEXP (ifelse1
, 0), 0)
9680 || cc0_rtx
!= XEXP (XEXP (ifelse2
, 0), 0)
9681 || const0_rtx
!= XEXP (XEXP (ifelse1
, 0), 1)
9682 || const0_rtx
!= XEXP (XEXP (ifelse2
, 0), 1))
9687 /* We filtered the insn sequence to look like
9693 (if_then_else (eq (cc0)
9702 (if_then_else (CODE (cc0)
9708 code
= GET_CODE (XEXP (ifelse2
, 0));
9710 /* Map GT/GTU to GE/GEU which is easier for AVR.
9711 The first two instructions compare/branch on EQ
9712 so we may replace the difficult
9714 if (x == VAL) goto L1;
9715 if (x > VAL) goto L2;
9719 if (x == VAL) goto L1;
9720 if (x >= VAL) goto L2;
9722 Similarly, replace LE/LEU by LT/LTU. */
9733 code
= avr_normalize_condition (code
);
9740 /* Wrap the branches into UNSPECs so they won't be changed or
9741 optimized in the remainder. */
9743 target
= XEXP (XEXP (ifelse1
, 1), 0);
9744 cond
= XEXP (ifelse1
, 0);
9745 jump
= emit_jump_insn_after (gen_branch_unspec (target
, cond
), insn1
);
9747 JUMP_LABEL (jump
) = JUMP_LABEL (branch1
);
9749 target
= XEXP (XEXP (ifelse2
, 1), 0);
9750 cond
= gen_rtx_fmt_ee (code
, VOIDmode
, cc0_rtx
, const0_rtx
);
9751 jump
= emit_jump_insn_after (gen_branch_unspec (target
, cond
), insn2
);
9753 JUMP_LABEL (jump
) = JUMP_LABEL (branch2
);
9755 /* The comparisons in insn1 and insn2 are exactly the same;
9756 insn2 is superfluous so delete it. */
9758 delete_insn (insn2
);
9759 delete_insn (branch1
);
9760 delete_insn (branch2
);
9766 /* Implement `TARGET_MACHINE_DEPENDENT_REORG'. */
9767 /* Optimize conditional jumps. */
9772 rtx insn
= get_insns();
9774 for (insn
= next_real_insn (insn
); insn
; insn
= next_real_insn (insn
))
9776 rtx pattern
= avr_compare_pattern (insn
);
9782 && avr_reorg_remove_redundant_compare (insn
))
9787 if (compare_diff_p (insn
))
9789 /* Now we work under compare insn with difficult branch. */
9791 rtx next
= next_real_insn (insn
);
9792 rtx pat
= PATTERN (next
);
9794 pattern
= SET_SRC (pattern
);
9796 if (true_regnum (XEXP (pattern
, 0)) >= 0
9797 && true_regnum (XEXP (pattern
, 1)) >= 0)
9799 rtx x
= XEXP (pattern
, 0);
9800 rtx src
= SET_SRC (pat
);
9801 rtx t
= XEXP (src
,0);
9802 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
9803 XEXP (pattern
, 0) = XEXP (pattern
, 1);
9804 XEXP (pattern
, 1) = x
;
9805 INSN_CODE (next
) = -1;
9807 else if (true_regnum (XEXP (pattern
, 0)) >= 0
9808 && XEXP (pattern
, 1) == const0_rtx
)
9810 /* This is a tst insn, we can reverse it. */
9811 rtx src
= SET_SRC (pat
);
9812 rtx t
= XEXP (src
,0);
9814 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
9815 XEXP (pattern
, 1) = XEXP (pattern
, 0);
9816 XEXP (pattern
, 0) = const0_rtx
;
9817 INSN_CODE (next
) = -1;
9818 INSN_CODE (insn
) = -1;
9820 else if (true_regnum (XEXP (pattern
, 0)) >= 0
9821 && CONST_INT_P (XEXP (pattern
, 1)))
9823 rtx x
= XEXP (pattern
, 1);
9824 rtx src
= SET_SRC (pat
);
9825 rtx t
= XEXP (src
,0);
9826 enum machine_mode mode
= GET_MODE (XEXP (pattern
, 0));
9828 if (avr_simplify_comparison_p (mode
, GET_CODE (t
), x
))
9830 XEXP (pattern
, 1) = gen_int_mode (INTVAL (x
) + 1, mode
);
9831 PUT_CODE (t
, avr_normalize_condition (GET_CODE (t
)));
9832 INSN_CODE (next
) = -1;
9833 INSN_CODE (insn
) = -1;
9840 /* Returns register number for function return value.*/
9842 static inline unsigned int
9843 avr_ret_register (void)
9849 /* Implement `TARGET_FUNCTION_VALUE_REGNO_P'. */
9852 avr_function_value_regno_p (const unsigned int regno
)
9854 return (regno
== avr_ret_register ());
9858 /* Implement `TARGET_LIBCALL_VALUE'. */
9859 /* Create an RTX representing the place where a
9860 library function returns a value of mode MODE. */
9863 avr_libcall_value (enum machine_mode mode
,
9864 const_rtx func ATTRIBUTE_UNUSED
)
9866 int offs
= GET_MODE_SIZE (mode
);
9869 offs
= (offs
+ 1) & ~1;
9871 return gen_rtx_REG (mode
, avr_ret_register () + 2 - offs
);
9875 /* Implement `TARGET_FUNCTION_VALUE'. */
9876 /* Create an RTX representing the place where a
9877 function returns a value of data type VALTYPE. */
9880 avr_function_value (const_tree type
,
9881 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
9882 bool outgoing ATTRIBUTE_UNUSED
)
9886 if (TYPE_MODE (type
) != BLKmode
)
9887 return avr_libcall_value (TYPE_MODE (type
), NULL_RTX
);
9889 offs
= int_size_in_bytes (type
);
9892 if (offs
> 2 && offs
< GET_MODE_SIZE (SImode
))
9893 offs
= GET_MODE_SIZE (SImode
);
9894 else if (offs
> GET_MODE_SIZE (SImode
) && offs
< GET_MODE_SIZE (DImode
))
9895 offs
= GET_MODE_SIZE (DImode
);
9897 return gen_rtx_REG (BLKmode
, avr_ret_register () + 2 - offs
);
9901 test_hard_reg_class (enum reg_class rclass
, rtx x
)
9903 int regno
= true_regnum (x
);
9907 if (TEST_HARD_REG_CLASS (rclass
, regno
))
9914 /* Helper for jump_over_one_insn_p: Test if INSN is a 2-word instruction
9915 and thus is suitable to be skipped by CPSE, SBRC, etc. */
9918 avr_2word_insn_p (rtx insn
)
9920 if (avr_current_device
->errata_skip
9922 || 2 != get_attr_length (insn
))
9927 switch (INSN_CODE (insn
))
9932 case CODE_FOR_movqi_insn
:
9933 case CODE_FOR_movuqq_insn
:
9934 case CODE_FOR_movqq_insn
:
9936 rtx set
= single_set (insn
);
9937 rtx src
= SET_SRC (set
);
9938 rtx dest
= SET_DEST (set
);
9940 /* Factor out LDS and STS from movqi_insn. */
9943 && (REG_P (src
) || src
== CONST0_RTX (GET_MODE (dest
))))
9945 return CONSTANT_ADDRESS_P (XEXP (dest
, 0));
9947 else if (REG_P (dest
)
9950 return CONSTANT_ADDRESS_P (XEXP (src
, 0));
9956 case CODE_FOR_call_insn
:
9957 case CODE_FOR_call_value_insn
:
9964 jump_over_one_insn_p (rtx insn
, rtx dest
)
9966 int uid
= INSN_UID (GET_CODE (dest
) == LABEL_REF
9969 int jump_addr
= INSN_ADDRESSES (INSN_UID (insn
));
9970 int dest_addr
= INSN_ADDRESSES (uid
);
9971 int jump_offset
= dest_addr
- jump_addr
- get_attr_length (insn
);
9973 return (jump_offset
== 1
9974 || (jump_offset
== 2
9975 && avr_2word_insn_p (next_active_insn (insn
))));
9979 /* Worker function for `HARD_REGNO_MODE_OK'. */
9980 /* Returns 1 if a value of mode MODE can be stored starting with hard
9981 register number REGNO. On the enhanced core, anything larger than
9982 1 byte must start in even numbered register for "movw" to work
9983 (this way we don't have to check for odd registers everywhere). */
9986 avr_hard_regno_mode_ok (int regno
, enum machine_mode mode
)
9988 /* NOTE: 8-bit values must not be disallowed for R28 or R29.
9989 Disallowing QI et al. in these regs might lead to code like
9990 (set (subreg:QI (reg:HI 28) n) ...)
9991 which will result in wrong code because reload does not
9992 handle SUBREGs of hard regsisters like this.
9993 This could be fixed in reload. However, it appears
9994 that fixing reload is not wanted by reload people. */
9996 /* Any GENERAL_REGS register can hold 8-bit values. */
9998 if (GET_MODE_SIZE (mode
) == 1)
10001 /* FIXME: Ideally, the following test is not needed.
10002 However, it turned out that it can reduce the number
10003 of spill fails. AVR and it's poor endowment with
10004 address registers is extreme stress test for reload. */
10006 if (GET_MODE_SIZE (mode
) >= 4
10010 /* All modes larger than 8 bits should start in an even register. */
10012 return !(regno
& 1);
10016 /* Implement `HARD_REGNO_CALL_PART_CLOBBERED'. */
10019 avr_hard_regno_call_part_clobbered (unsigned regno
, enum machine_mode mode
)
10021 /* FIXME: This hook gets called with MODE:REGNO combinations that don't
10022 represent valid hard registers like, e.g. HI:29. Returning TRUE
10023 for such registers can lead to performance degradation as mentioned
10024 in PR53595. Thus, report invalid hard registers as FALSE. */
10026 if (!avr_hard_regno_mode_ok (regno
, mode
))
10029 /* Return true if any of the following boundaries is crossed:
10030 17/18, 27/28 and 29/30. */
10032 return ((regno
< 18 && regno
+ GET_MODE_SIZE (mode
) > 18)
10033 || (regno
< REG_Y
&& regno
+ GET_MODE_SIZE (mode
) > REG_Y
)
10034 || (regno
< REG_Z
&& regno
+ GET_MODE_SIZE (mode
) > REG_Z
));
10038 /* Implement `MODE_CODE_BASE_REG_CLASS'. */
10041 avr_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED
,
10042 addr_space_t as
, RTX_CODE outer_code
,
10043 RTX_CODE index_code ATTRIBUTE_UNUSED
)
10045 if (!ADDR_SPACE_GENERIC_P (as
))
10047 return POINTER_Z_REGS
;
10051 return reload_completed
? BASE_POINTER_REGS
: POINTER_REGS
;
10053 return PLUS
== outer_code
? BASE_POINTER_REGS
: POINTER_REGS
;
10057 /* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'. */
10060 avr_regno_mode_code_ok_for_base_p (int regno
,
10061 enum machine_mode mode ATTRIBUTE_UNUSED
,
10062 addr_space_t as ATTRIBUTE_UNUSED
,
10063 RTX_CODE outer_code
,
10064 RTX_CODE index_code ATTRIBUTE_UNUSED
)
10068 if (!ADDR_SPACE_GENERIC_P (as
))
10070 if (regno
< FIRST_PSEUDO_REGISTER
10078 regno
= reg_renumber
[regno
];
10080 if (regno
== REG_Z
)
10089 if (regno
< FIRST_PSEUDO_REGISTER
10093 || regno
== ARG_POINTER_REGNUM
))
10097 else if (reg_renumber
)
10099 regno
= reg_renumber
[regno
];
10104 || regno
== ARG_POINTER_REGNUM
)
10111 && PLUS
== outer_code
10121 /* A helper for `output_reload_insisf' and `output_reload_inhi'. */
10122 /* Set 32-bit register OP[0] to compile-time constant OP[1].
10123 CLOBBER_REG is a QI clobber register or NULL_RTX.
10124 LEN == NULL: output instructions.
10125 LEN != NULL: set *LEN to the length of the instruction sequence
10126 (in words) printed with LEN = NULL.
10127 If CLEAR_P is true, OP[0] had been cleard to Zero already.
10128 If CLEAR_P is false, nothing is known about OP[0].
10130 The effect on cc0 is as follows:
10132 Load 0 to any register except ZERO_REG : NONE
10133 Load ld register with any value : NONE
10134 Anything else: : CLOBBER */
10137 output_reload_in_const (rtx
*op
, rtx clobber_reg
, int *len
, bool clear_p
)
10141 rtx xval
, xdest
[4];
10143 int clobber_val
= 1234;
10144 bool cooked_clobber_p
= false;
10145 bool set_p
= false;
10146 enum machine_mode mode
= GET_MODE (dest
);
10147 int n
, n_bytes
= GET_MODE_SIZE (mode
);
10149 gcc_assert (REG_P (dest
)
10150 && CONSTANT_P (src
));
10155 /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
10156 but has some subregs that are in LD_REGS. Use the MSB (REG:QI 17). */
10158 if (REGNO (dest
) < 16
10159 && REGNO (dest
) + GET_MODE_SIZE (mode
) > 16)
10161 clobber_reg
= all_regs_rtx
[REGNO (dest
) + n_bytes
- 1];
10164 /* We might need a clobber reg but don't have one. Look at the value to
10165 be loaded more closely. A clobber is only needed if it is a symbol
10166 or contains a byte that is neither 0, -1 or a power of 2. */
10168 if (NULL_RTX
== clobber_reg
10169 && !test_hard_reg_class (LD_REGS
, dest
)
10170 && (! (CONST_INT_P (src
) || CONST_FIXED_P (src
) || CONST_DOUBLE_P (src
))
10171 || !avr_popcount_each_byte (src
, n_bytes
,
10172 (1 << 0) | (1 << 1) | (1 << 8))))
10174 /* We have no clobber register but need one. Cook one up.
10175 That's cheaper than loading from constant pool. */
10177 cooked_clobber_p
= true;
10178 clobber_reg
= all_regs_rtx
[REG_Z
+ 1];
10179 avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg
, len
, 1);
10182 /* Now start filling DEST from LSB to MSB. */
10184 for (n
= 0; n
< n_bytes
; n
++)
10187 bool done_byte
= false;
10191 /* Crop the n-th destination byte. */
10193 xdest
[n
] = simplify_gen_subreg (QImode
, dest
, mode
, n
);
10194 ldreg_p
= test_hard_reg_class (LD_REGS
, xdest
[n
]);
10196 if (!CONST_INT_P (src
)
10197 && !CONST_FIXED_P (src
)
10198 && !CONST_DOUBLE_P (src
))
10200 static const char* const asm_code
[][2] =
10202 { "ldi %2,lo8(%1)" CR_TAB
"mov %0,%2", "ldi %0,lo8(%1)" },
10203 { "ldi %2,hi8(%1)" CR_TAB
"mov %0,%2", "ldi %0,hi8(%1)" },
10204 { "ldi %2,hlo8(%1)" CR_TAB
"mov %0,%2", "ldi %0,hlo8(%1)" },
10205 { "ldi %2,hhi8(%1)" CR_TAB
"mov %0,%2", "ldi %0,hhi8(%1)" }
10210 xop
[2] = clobber_reg
;
10212 avr_asm_len (asm_code
[n
][ldreg_p
], xop
, len
, ldreg_p
? 1 : 2);
10217 /* Crop the n-th source byte. */
10219 xval
= simplify_gen_subreg (QImode
, src
, mode
, n
);
10220 ival
[n
] = INTVAL (xval
);
10222 /* Look if we can reuse the low word by means of MOVW. */
10228 rtx lo16
= simplify_gen_subreg (HImode
, src
, mode
, 0);
10229 rtx hi16
= simplify_gen_subreg (HImode
, src
, mode
, 2);
10231 if (INTVAL (lo16
) == INTVAL (hi16
))
10233 if (0 != INTVAL (lo16
)
10236 avr_asm_len ("movw %C0,%A0", &op
[0], len
, 1);
10243 /* Don't use CLR so that cc0 is set as expected. */
10248 avr_asm_len (ldreg_p
? "ldi %0,0"
10249 : ZERO_REGNO
== REGNO (xdest
[n
]) ? "clr %0"
10250 : "mov %0,__zero_reg__",
10251 &xdest
[n
], len
, 1);
10255 if (clobber_val
== ival
[n
]
10256 && REGNO (clobber_reg
) == REGNO (xdest
[n
]))
10261 /* LD_REGS can use LDI to move a constant value */
10267 avr_asm_len ("ldi %0,lo8(%1)", xop
, len
, 1);
10271 /* Try to reuse value already loaded in some lower byte. */
10273 for (j
= 0; j
< n
; j
++)
10274 if (ival
[j
] == ival
[n
])
10279 avr_asm_len ("mov %0,%1", xop
, len
, 1);
10287 /* Need no clobber reg for -1: Use CLR/DEC */
10292 avr_asm_len ("clr %0", &xdest
[n
], len
, 1);
10294 avr_asm_len ("dec %0", &xdest
[n
], len
, 1);
10297 else if (1 == ival
[n
])
10300 avr_asm_len ("clr %0", &xdest
[n
], len
, 1);
10302 avr_asm_len ("inc %0", &xdest
[n
], len
, 1);
10306 /* Use T flag or INC to manage powers of 2 if we have
10309 if (NULL_RTX
== clobber_reg
10310 && single_one_operand (xval
, QImode
))
10313 xop
[1] = GEN_INT (exact_log2 (ival
[n
] & GET_MODE_MASK (QImode
)));
10315 gcc_assert (constm1_rtx
!= xop
[1]);
10320 avr_asm_len ("set", xop
, len
, 1);
10324 avr_asm_len ("clr %0", xop
, len
, 1);
10326 avr_asm_len ("bld %0,%1", xop
, len
, 1);
10330 /* We actually need the LD_REGS clobber reg. */
10332 gcc_assert (NULL_RTX
!= clobber_reg
);
10336 xop
[2] = clobber_reg
;
10337 clobber_val
= ival
[n
];
10339 avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
10340 "mov %0,%2", xop
, len
, 2);
10343 /* If we cooked up a clobber reg above, restore it. */
10345 if (cooked_clobber_p
)
10347 avr_asm_len ("mov %0,__tmp_reg__", &clobber_reg
, len
, 1);
10352 /* Reload the constant OP[1] into the HI register OP[0].
10353 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
10354 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
10355 need a clobber reg or have to cook one up.
10357 PLEN == NULL: Output instructions.
10358 PLEN != NULL: Output nothing. Set *PLEN to number of words occupied
10359 by the insns printed.
10364 output_reload_inhi (rtx
*op
, rtx clobber_reg
, int *plen
)
10366 output_reload_in_const (op
, clobber_reg
, plen
, false);
10371 /* Reload a SI or SF compile time constant OP[1] into the register OP[0].
10372 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
10373 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
10374 need a clobber reg or have to cook one up.
10376 LEN == NULL: Output instructions.
10378 LEN != NULL: Output nothing. Set *LEN to number of words occupied
10379 by the insns printed.
10384 output_reload_insisf (rtx
*op
, rtx clobber_reg
, int *len
)
10387 && !test_hard_reg_class (LD_REGS
, op
[0])
10388 && (CONST_INT_P (op
[1])
10389 || CONST_FIXED_P (op
[1])
10390 || CONST_DOUBLE_P (op
[1])))
10392 int len_clr
, len_noclr
;
10394 /* In some cases it is better to clear the destination beforehand, e.g.
10396 CLR R2 CLR R3 MOVW R4,R2 INC R2
10400 CLR R2 INC R2 CLR R3 CLR R4 CLR R5
10402 We find it too tedious to work that out in the print function.
10403 Instead, we call the print function twice to get the lengths of
10404 both methods and use the shortest one. */
10406 output_reload_in_const (op
, clobber_reg
, &len_clr
, true);
10407 output_reload_in_const (op
, clobber_reg
, &len_noclr
, false);
10409 if (len_noclr
- len_clr
== 4)
10411 /* Default needs 4 CLR instructions: clear register beforehand. */
10413 avr_asm_len ("mov %A0,__zero_reg__" CR_TAB
10414 "mov %B0,__zero_reg__" CR_TAB
10415 "movw %C0,%A0", &op
[0], len
, 3);
10417 output_reload_in_const (op
, clobber_reg
, len
, true);
10426 /* Default: destination not pre-cleared. */
10428 output_reload_in_const (op
, clobber_reg
, len
, false);
10433 avr_out_reload_inpsi (rtx
*op
, rtx clobber_reg
, int *len
)
10435 output_reload_in_const (op
, clobber_reg
, len
, false);
10440 /* Worker function for `ASM_OUTPUT_ADDR_VEC_ELT'. */
10443 avr_output_addr_vec_elt (FILE *stream
, int value
)
10445 if (AVR_HAVE_JMP_CALL
)
10446 fprintf (stream
, "\t.word gs(.L%d)\n", value
);
10448 fprintf (stream
, "\trjmp .L%d\n", value
);
10452 /* Implement `TARGET_HARD_REGNO_SCRATCH_OK'. */
10453 /* Returns true if SCRATCH are safe to be allocated as a scratch
10454 registers (for a define_peephole2) in the current function. */
10457 avr_hard_regno_scratch_ok (unsigned int regno
)
10459 /* Interrupt functions can only use registers that have already been saved
10460 by the prologue, even if they would normally be call-clobbered. */
10462 if ((cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
10463 && !df_regs_ever_live_p (regno
))
10466 /* Don't allow hard registers that might be part of the frame pointer.
10467 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
10468 and don't care for a frame pointer that spans more than one register. */
10470 if ((!reload_completed
|| frame_pointer_needed
)
10471 && (regno
== REG_Y
|| regno
== REG_Y
+ 1))
10480 /* Worker function for `HARD_REGNO_RENAME_OK'. */
10481 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
10484 avr_hard_regno_rename_ok (unsigned int old_reg
,
10485 unsigned int new_reg
)
10487 /* Interrupt functions can only use registers that have already been
10488 saved by the prologue, even if they would normally be
10491 if ((cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
10492 && !df_regs_ever_live_p (new_reg
))
10495 /* Don't allow hard registers that might be part of the frame pointer.
10496 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
10497 and don't care for a frame pointer that spans more than one register. */
10499 if ((!reload_completed
|| frame_pointer_needed
)
10500 && (old_reg
== REG_Y
|| old_reg
== REG_Y
+ 1
10501 || new_reg
== REG_Y
|| new_reg
== REG_Y
+ 1))
10509 /* Output a branch that tests a single bit of a register (QI, HI, SI or DImode)
10510 or memory location in the I/O space (QImode only).
10512 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
10513 Operand 1: register operand to test, or CONST_INT memory address.
10514 Operand 2: bit number.
10515 Operand 3: label to jump to if the test is true. */
10518 avr_out_sbxx_branch (rtx insn
, rtx operands
[])
10520 enum rtx_code comp
= GET_CODE (operands
[0]);
10521 bool long_jump
= get_attr_length (insn
) >= 4;
10522 bool reverse
= long_jump
|| jump_over_one_insn_p (insn
, operands
[3]);
10526 else if (comp
== LT
)
10530 comp
= reverse_condition (comp
);
10532 switch (GET_CODE (operands
[1]))
10539 if (low_io_address_operand (operands
[1], QImode
))
10542 output_asm_insn ("sbis %i1,%2", operands
);
10544 output_asm_insn ("sbic %i1,%2", operands
);
10548 output_asm_insn ("in __tmp_reg__,%i1", operands
);
10550 output_asm_insn ("sbrs __tmp_reg__,%2", operands
);
10552 output_asm_insn ("sbrc __tmp_reg__,%2", operands
);
10555 break; /* CONST_INT */
10560 output_asm_insn ("sbrs %T1%T2", operands
);
10562 output_asm_insn ("sbrc %T1%T2", operands
);
10568 return ("rjmp .+4" CR_TAB
10577 /* Worker function for `TARGET_ASM_CONSTRUCTOR'. */
10580 avr_asm_out_ctor (rtx symbol
, int priority
)
10582 fputs ("\t.global __do_global_ctors\n", asm_out_file
);
10583 default_ctor_section_asm_out_constructor (symbol
, priority
);
10587 /* Worker function for `TARGET_ASM_DESTRUCTOR'. */
10590 avr_asm_out_dtor (rtx symbol
, int priority
)
10592 fputs ("\t.global __do_global_dtors\n", asm_out_file
);
10593 default_dtor_section_asm_out_destructor (symbol
, priority
);
10597 /* Worker function for `TARGET_RETURN_IN_MEMORY'. */
10600 avr_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
10602 if (TYPE_MODE (type
) == BLKmode
)
10604 HOST_WIDE_INT size
= int_size_in_bytes (type
);
10605 return (size
== -1 || size
> 8);
10612 /* Implement `CASE_VALUES_THRESHOLD'. */
10613 /* Supply the default for --param case-values-threshold=0 */
10615 static unsigned int
10616 avr_case_values_threshold (void)
10618 /* The exact break-even point between a jump table and an if-else tree
10619 depends on several factors not available here like, e.g. if 8-bit
10620 comparisons can be used in the if-else tree or not, on the
10621 range of the case values, if the case value can be reused, on the
10622 register allocation, etc. '7' appears to be a good choice. */
10628 /* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'. */
10630 static enum machine_mode
10631 avr_addr_space_address_mode (addr_space_t as
)
10633 return avr_addrspace
[as
].pointer_size
== 3 ? PSImode
: HImode
;
10637 /* Implement `TARGET_ADDR_SPACE_POINTER_MODE'. */
10639 static enum machine_mode
10640 avr_addr_space_pointer_mode (addr_space_t as
)
10642 return avr_addr_space_address_mode (as
);
10646 /* Helper for following function. */
10649 avr_reg_ok_for_pgm_addr (rtx reg
, bool strict
)
10651 gcc_assert (REG_P (reg
));
10655 return REGNO (reg
) == REG_Z
;
10658 /* Avoid combine to propagate hard regs. */
10660 if (can_create_pseudo_p()
10661 && REGNO (reg
) < REG_Z
)
10670 /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'. */
10673 avr_addr_space_legitimate_address_p (enum machine_mode mode
, rtx x
,
10674 bool strict
, addr_space_t as
)
10683 case ADDR_SPACE_GENERIC
:
10684 return avr_legitimate_address_p (mode
, x
, strict
);
10686 case ADDR_SPACE_FLASH
:
10687 case ADDR_SPACE_FLASH1
:
10688 case ADDR_SPACE_FLASH2
:
10689 case ADDR_SPACE_FLASH3
:
10690 case ADDR_SPACE_FLASH4
:
10691 case ADDR_SPACE_FLASH5
:
10693 switch (GET_CODE (x
))
10696 ok
= avr_reg_ok_for_pgm_addr (x
, strict
);
10700 ok
= avr_reg_ok_for_pgm_addr (XEXP (x
, 0), strict
);
10709 case ADDR_SPACE_MEMX
:
10712 && can_create_pseudo_p());
10714 if (LO_SUM
== GET_CODE (x
))
10716 rtx hi
= XEXP (x
, 0);
10717 rtx lo
= XEXP (x
, 1);
10720 && (!strict
|| REGNO (hi
) < FIRST_PSEUDO_REGISTER
)
10722 && REGNO (lo
) == REG_Z
);
10728 if (avr_log
.legitimate_address_p
)
10730 avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
10731 "reload_completed=%d reload_in_progress=%d %s:",
10732 ok
, mode
, strict
, reload_completed
, reload_in_progress
,
10733 reg_renumber
? "(reg_renumber)" : "");
10735 if (GET_CODE (x
) == PLUS
10736 && REG_P (XEXP (x
, 0))
10737 && CONST_INT_P (XEXP (x
, 1))
10738 && IN_RANGE (INTVAL (XEXP (x
, 1)), 0, MAX_LD_OFFSET (mode
))
10741 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x
, 0)),
10742 true_regnum (XEXP (x
, 0)));
10745 avr_edump ("\n%r\n", x
);
10752 /* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'. */
10755 avr_addr_space_legitimize_address (rtx x
, rtx old_x
,
10756 enum machine_mode mode
, addr_space_t as
)
10758 if (ADDR_SPACE_GENERIC_P (as
))
10759 return avr_legitimize_address (x
, old_x
, mode
);
10761 if (avr_log
.legitimize_address
)
10763 avr_edump ("\n%?: mode=%m\n %r\n", mode
, old_x
);
10770 /* Implement `TARGET_ADDR_SPACE_CONVERT'. */
10773 avr_addr_space_convert (rtx src
, tree type_from
, tree type_to
)
10775 addr_space_t as_from
= TYPE_ADDR_SPACE (TREE_TYPE (type_from
));
10776 addr_space_t as_to
= TYPE_ADDR_SPACE (TREE_TYPE (type_to
));
10778 if (avr_log
.progmem
)
10779 avr_edump ("\n%!: op = %r\nfrom = %t\nto = %t\n",
10780 src
, type_from
, type_to
);
10782 /* Up-casting from 16-bit to 24-bit pointer. */
10784 if (as_from
!= ADDR_SPACE_MEMX
10785 && as_to
== ADDR_SPACE_MEMX
)
10789 rtx reg
= gen_reg_rtx (PSImode
);
10791 while (CONST
== GET_CODE (sym
) || PLUS
== GET_CODE (sym
))
10792 sym
= XEXP (sym
, 0);
10794 /* Look at symbol flags: avr_encode_section_info set the flags
10795 also if attribute progmem was seen so that we get the right
10796 promotion for, e.g. PSTR-like strings that reside in generic space
10797 but are located in flash. In that case we patch the incoming
10800 if (SYMBOL_REF
== GET_CODE (sym
)
10801 && ADDR_SPACE_FLASH
== AVR_SYMBOL_GET_ADDR_SPACE (sym
))
10803 as_from
= ADDR_SPACE_FLASH
;
10806 /* Linearize memory: RAM has bit 23 set. */
10808 msb
= ADDR_SPACE_GENERIC_P (as_from
)
10810 : avr_addrspace
[as_from
].segment
;
10812 src
= force_reg (Pmode
, src
);
10814 emit_insn (msb
== 0
10815 ? gen_zero_extendhipsi2 (reg
, src
)
10816 : gen_n_extendhipsi2 (reg
, gen_int_mode (msb
, QImode
), src
));
10821 /* Down-casting from 24-bit to 16-bit throws away the high byte. */
10823 if (as_from
== ADDR_SPACE_MEMX
10824 && as_to
!= ADDR_SPACE_MEMX
)
10826 rtx new_src
= gen_reg_rtx (Pmode
);
10828 src
= force_reg (PSImode
, src
);
10830 emit_move_insn (new_src
,
10831 simplify_gen_subreg (Pmode
, src
, PSImode
, 0));
10839 /* Implement `TARGET_ADDR_SPACE_SUBSET_P'. */
10842 avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED
,
10843 addr_space_t superset ATTRIBUTE_UNUSED
)
10845 /* Allow any kind of pointer mess. */
10851 /* Implement `TARGET_CONVERT_TO_TYPE'. */
10854 avr_convert_to_type (tree type
, tree expr
)
10856 /* Print a diagnose for pointer conversion that changes the address
10857 space of the pointer target to a non-enclosing address space,
10858 provided -Waddr-space-convert is on.
10860 FIXME: Filter out cases where the target object is known to
10861 be located in the right memory, like in
10863 (const __flash*) PSTR ("text")
10865 Also try to distinguish between explicit casts requested by
10866 the user and implicit casts like
10868 void f (const __flash char*);
10870 void g (const char *p)
10872 f ((const __flash*) p);
10875 under the assumption that an explicit casts means that the user
10876 knows what he is doing, e.g. interface with PSTR or old style
10877 code with progmem and pgm_read_xxx.
10880 if (avr_warn_addr_space_convert
10881 && expr
!= error_mark_node
10882 && POINTER_TYPE_P (type
)
10883 && POINTER_TYPE_P (TREE_TYPE (expr
)))
10885 addr_space_t as_old
= TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr
)));
10886 addr_space_t as_new
= TYPE_ADDR_SPACE (TREE_TYPE (type
));
10888 if (avr_log
.progmem
)
10889 avr_edump ("%?: type = %t\nexpr = %t\n\n", type
, expr
);
10891 if (as_new
!= ADDR_SPACE_MEMX
10892 && as_new
!= as_old
)
10894 location_t loc
= EXPR_LOCATION (expr
);
10895 const char *name_old
= avr_addrspace
[as_old
].name
;
10896 const char *name_new
= avr_addrspace
[as_new
].name
;
10898 warning (OPT_Waddr_space_convert
,
10899 "conversion from address space %qs to address space %qs",
10900 ADDR_SPACE_GENERIC_P (as_old
) ? "generic" : name_old
,
10901 ADDR_SPACE_GENERIC_P (as_new
) ? "generic" : name_new
);
10903 return fold_build1_loc (loc
, ADDR_SPACE_CONVERT_EXPR
, type
, expr
);
10911 /* Worker function for movmemhi expander.
10912 XOP[0] Destination as MEM:BLK
10914 XOP[2] # Bytes to copy
10916 Return TRUE if the expansion is accomplished.
10917 Return FALSE if the operand compination is not supported. */
10920 avr_emit_movmemhi (rtx
*xop
)
10922 HOST_WIDE_INT count
;
10923 enum machine_mode loop_mode
;
10924 addr_space_t as
= MEM_ADDR_SPACE (xop
[1]);
10925 rtx loop_reg
, addr1
, a_src
, a_dest
, insn
, xas
;
10926 rtx a_hi8
= NULL_RTX
;
10928 if (avr_mem_flash_p (xop
[0]))
10931 if (!CONST_INT_P (xop
[2]))
10934 count
= INTVAL (xop
[2]);
10938 a_src
= XEXP (xop
[1], 0);
10939 a_dest
= XEXP (xop
[0], 0);
10941 if (PSImode
== GET_MODE (a_src
))
10943 gcc_assert (as
== ADDR_SPACE_MEMX
);
10945 loop_mode
= (count
< 0x100) ? QImode
: HImode
;
10946 loop_reg
= gen_rtx_REG (loop_mode
, 24);
10947 emit_move_insn (loop_reg
, gen_int_mode (count
, loop_mode
));
10949 addr1
= simplify_gen_subreg (HImode
, a_src
, PSImode
, 0);
10950 a_hi8
= simplify_gen_subreg (QImode
, a_src
, PSImode
, 2);
10954 int segment
= avr_addrspace
[as
].segment
;
10957 && avr_current_device
->n_flash
> 1)
10959 a_hi8
= GEN_INT (segment
);
10960 emit_move_insn (rampz_rtx
, a_hi8
= copy_to_mode_reg (QImode
, a_hi8
));
10962 else if (!ADDR_SPACE_GENERIC_P (as
))
10964 as
= ADDR_SPACE_FLASH
;
10969 loop_mode
= (count
<= 0x100) ? QImode
: HImode
;
10970 loop_reg
= copy_to_mode_reg (loop_mode
, gen_int_mode (count
, loop_mode
));
10973 xas
= GEN_INT (as
);
10975 /* FIXME: Register allocator might come up with spill fails if it is left
10976 on its own. Thus, we allocate the pointer registers by hand:
10978 X = destination address */
10980 emit_move_insn (lpm_addr_reg_rtx
, addr1
);
10981 emit_move_insn (gen_rtx_REG (HImode
, REG_X
), a_dest
);
10983 /* FIXME: Register allocator does a bad job and might spill address
10984 register(s) inside the loop leading to additional move instruction
10985 to/from stack which could clobber tmp_reg. Thus, do *not* emit
10986 load and store as separate insns. Instead, we perform the copy
10987 by means of one monolithic insn. */
10989 gcc_assert (TMP_REGNO
== LPM_REGNO
);
10991 if (as
!= ADDR_SPACE_MEMX
)
10993 /* Load instruction ([E]LPM or LD) is known at compile time:
10994 Do the copy-loop inline. */
10996 rtx (*fun
) (rtx
, rtx
, rtx
)
10997 = QImode
== loop_mode
? gen_movmem_qi
: gen_movmem_hi
;
10999 insn
= fun (xas
, loop_reg
, loop_reg
);
11003 rtx (*fun
) (rtx
, rtx
)
11004 = QImode
== loop_mode
? gen_movmemx_qi
: gen_movmemx_hi
;
11006 emit_move_insn (gen_rtx_REG (QImode
, 23), a_hi8
);
11008 insn
= fun (xas
, GEN_INT (avr_addr
.rampz
));
11011 set_mem_addr_space (SET_SRC (XVECEXP (insn
, 0, 0)), as
);
11018 /* Print assembler for movmem_qi, movmem_hi insns...
11020 $1, $2 : Loop register
11022 X : Destination address
11026 avr_out_movmem (rtx insn ATTRIBUTE_UNUSED
, rtx
*op
, int *plen
)
11028 addr_space_t as
= (addr_space_t
) INTVAL (op
[0]);
11029 enum machine_mode loop_mode
= GET_MODE (op
[1]);
11030 bool sbiw_p
= test_hard_reg_class (ADDW_REGS
, op
[1]);
11038 xop
[2] = tmp_reg_rtx
;
11042 avr_asm_len ("0:", xop
, plen
, 0);
11044 /* Load with post-increment */
11051 case ADDR_SPACE_GENERIC
:
11053 avr_asm_len ("ld %2,Z+", xop
, plen
, 1);
11056 case ADDR_SPACE_FLASH
:
11059 avr_asm_len ("lpm %2,Z+", xop
, plen
, 1);
11061 avr_asm_len ("lpm" CR_TAB
11062 "adiw r30,1", xop
, plen
, 2);
11065 case ADDR_SPACE_FLASH1
:
11066 case ADDR_SPACE_FLASH2
:
11067 case ADDR_SPACE_FLASH3
:
11068 case ADDR_SPACE_FLASH4
:
11069 case ADDR_SPACE_FLASH5
:
11071 if (AVR_HAVE_ELPMX
)
11072 avr_asm_len ("elpm %2,Z+", xop
, plen
, 1);
11074 avr_asm_len ("elpm" CR_TAB
11075 "adiw r30,1", xop
, plen
, 2);
11079 /* Store with post-increment */
11081 avr_asm_len ("st X+,%2", xop
, plen
, 1);
11083 /* Decrement loop-counter and set Z-flag */
11085 if (QImode
== loop_mode
)
11087 avr_asm_len ("dec %1", xop
, plen
, 1);
11091 avr_asm_len ("sbiw %1,1", xop
, plen
, 1);
11095 avr_asm_len ("subi %A1,1" CR_TAB
11096 "sbci %B1,0", xop
, plen
, 2);
11099 /* Loop until zero */
11101 return avr_asm_len ("brne 0b", xop
, plen
, 1);
11106 /* Helper for __builtin_avr_delay_cycles */
11109 avr_mem_clobber (void)
11111 rtx mem
= gen_rtx_MEM (BLKmode
, gen_rtx_SCRATCH (Pmode
));
11112 MEM_VOLATILE_P (mem
) = 1;
11117 avr_expand_delay_cycles (rtx operands0
)
11119 unsigned HOST_WIDE_INT cycles
= UINTVAL (operands0
) & GET_MODE_MASK (SImode
);
11120 unsigned HOST_WIDE_INT cycles_used
;
11121 unsigned HOST_WIDE_INT loop_count
;
11123 if (IN_RANGE (cycles
, 83886082, 0xFFFFFFFF))
11125 loop_count
= ((cycles
- 9) / 6) + 1;
11126 cycles_used
= ((loop_count
- 1) * 6) + 9;
11127 emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count
, SImode
),
11128 avr_mem_clobber()));
11129 cycles
-= cycles_used
;
11132 if (IN_RANGE (cycles
, 262145, 83886081))
11134 loop_count
= ((cycles
- 7) / 5) + 1;
11135 if (loop_count
> 0xFFFFFF)
11136 loop_count
= 0xFFFFFF;
11137 cycles_used
= ((loop_count
- 1) * 5) + 7;
11138 emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count
, SImode
),
11139 avr_mem_clobber()));
11140 cycles
-= cycles_used
;
11143 if (IN_RANGE (cycles
, 768, 262144))
11145 loop_count
= ((cycles
- 5) / 4) + 1;
11146 if (loop_count
> 0xFFFF)
11147 loop_count
= 0xFFFF;
11148 cycles_used
= ((loop_count
- 1) * 4) + 5;
11149 emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count
, HImode
),
11150 avr_mem_clobber()));
11151 cycles
-= cycles_used
;
11154 if (IN_RANGE (cycles
, 6, 767))
11156 loop_count
= cycles
/ 3;
11157 if (loop_count
> 255)
11159 cycles_used
= loop_count
* 3;
11160 emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count
, QImode
),
11161 avr_mem_clobber()));
11162 cycles
-= cycles_used
;
11165 while (cycles
>= 2)
11167 emit_insn (gen_nopv (GEN_INT(2)));
11173 emit_insn (gen_nopv (GEN_INT(1)));
11179 /* Return VAL * BASE + DIGIT. BASE = 0 is shortcut for BASE = 2^{32} */
11182 avr_double_int_push_digit (double_int val
, int base
,
11183 unsigned HOST_WIDE_INT digit
)
11186 ? val
.llshift (32, 64)
11187 : val
* double_int::from_uhwi (base
);
11189 return val
+ double_int::from_uhwi (digit
);
11193 /* Compute the image of x under f, i.e. perform x --> f(x) */
11196 avr_map (double_int f
, int x
)
11198 return 0xf & f
.lrshift (4*x
, 64).to_uhwi ();
11202 /* Return some metrics of map A. */
11206 /* Number of fixed points in { 0 ... 7 } */
11209 /* Size of preimage of non-fixed points in { 0 ... 7 } */
11212 /* Mask representing the fixed points in { 0 ... 7 } */
11213 MAP_MASK_FIXED_0_7
,
11215 /* Size of the preimage of { 0 ... 7 } */
11218 /* Mask that represents the preimage of { f } */
11219 MAP_MASK_PREIMAGE_F
11223 avr_map_metric (double_int a
, int mode
)
11225 unsigned i
, metric
= 0;
11227 for (i
= 0; i
< 8; i
++)
11229 unsigned ai
= avr_map (a
, i
);
11231 if (mode
== MAP_FIXED_0_7
)
11233 else if (mode
== MAP_NONFIXED_0_7
)
11234 metric
+= ai
< 8 && ai
!= i
;
11235 else if (mode
== MAP_MASK_FIXED_0_7
)
11236 metric
|= ((unsigned) (ai
== i
)) << i
;
11237 else if (mode
== MAP_PREIMAGE_0_7
)
11239 else if (mode
== MAP_MASK_PREIMAGE_F
)
11240 metric
|= ((unsigned) (ai
== 0xf)) << i
;
11249 /* Return true if IVAL has a 0xf in its hexadecimal representation
11250 and false, otherwise. Only nibbles 0..7 are taken into account.
11251 Used as constraint helper for C0f and Cxf. */
11254 avr_has_nibble_0xf (rtx ival
)
11256 return 0 != avr_map_metric (rtx_to_double_int (ival
), MAP_MASK_PREIMAGE_F
);
11260 /* We have a set of bits that are mapped by a function F.
11261 Try to decompose F by means of a second function G so that
11267 cost (F o G^-1) + cost (G) < cost (F)
11269 Example: Suppose builtin insert_bits supplies us with the map
11270 F = 0x3210ffff. Instead of doing 4 bit insertions to get the high
11271 nibble of the result, we can just as well rotate the bits before inserting
11272 them and use the map 0x7654ffff which is cheaper than the original map.
11273 For this example G = G^-1 = 0x32107654 and F o G^-1 = 0x7654ffff. */
11277 /* tree code of binary function G */
11278 enum tree_code code
;
11280 /* The constant second argument of G */
11283 /* G^-1, the inverse of G (*, arg) */
11286 /* The cost of appplying G (*, arg) */
11289 /* The composition F o G^-1 (*, arg) for some function F */
11292 /* For debug purpose only */
11296 static const avr_map_op_t avr_map_op
[] =
11298 { LROTATE_EXPR
, 0, 0x76543210, 0, { 0, 0 }, "id" },
11299 { LROTATE_EXPR
, 1, 0x07654321, 2, { 0, 0 }, "<<<" },
11300 { LROTATE_EXPR
, 2, 0x10765432, 4, { 0, 0 }, "<<<" },
11301 { LROTATE_EXPR
, 3, 0x21076543, 4, { 0, 0 }, "<<<" },
11302 { LROTATE_EXPR
, 4, 0x32107654, 1, { 0, 0 }, "<<<" },
11303 { LROTATE_EXPR
, 5, 0x43210765, 3, { 0, 0 }, "<<<" },
11304 { LROTATE_EXPR
, 6, 0x54321076, 5, { 0, 0 }, "<<<" },
11305 { LROTATE_EXPR
, 7, 0x65432107, 3, { 0, 0 }, "<<<" },
11306 { RSHIFT_EXPR
, 1, 0x6543210c, 1, { 0, 0 }, ">>" },
11307 { RSHIFT_EXPR
, 1, 0x7543210c, 1, { 0, 0 }, ">>" },
11308 { RSHIFT_EXPR
, 2, 0x543210cc, 2, { 0, 0 }, ">>" },
11309 { RSHIFT_EXPR
, 2, 0x643210cc, 2, { 0, 0 }, ">>" },
11310 { RSHIFT_EXPR
, 2, 0x743210cc, 2, { 0, 0 }, ">>" },
11311 { LSHIFT_EXPR
, 1, 0xc7654321, 1, { 0, 0 }, "<<" },
11312 { LSHIFT_EXPR
, 2, 0xcc765432, 2, { 0, 0 }, "<<" }
11316 /* Try to decompose F as F = (F o G^-1) o G as described above.
11317 The result is a struct representing F o G^-1 and G.
11318 If result.cost < 0 then such a decomposition does not exist. */
11320 static avr_map_op_t
11321 avr_map_decompose (double_int f
, const avr_map_op_t
*g
, bool val_const_p
)
11324 bool val_used_p
= 0 != avr_map_metric (f
, MAP_MASK_PREIMAGE_F
);
11325 avr_map_op_t f_ginv
= *g
;
11326 double_int ginv
= double_int::from_uhwi (g
->ginv
);
11330 /* Step 1: Computing F o G^-1 */
11332 for (i
= 7; i
>= 0; i
--)
11334 int x
= avr_map (f
, i
);
11338 x
= avr_map (ginv
, x
);
11340 /* The bit is no element of the image of G: no avail (cost = -1) */
11346 f_ginv
.map
= avr_double_int_push_digit (f_ginv
.map
, 16, x
);
11349 /* Step 2: Compute the cost of the operations.
11350 The overall cost of doing an operation prior to the insertion is
11351 the cost of the insertion plus the cost of the operation. */
11353 /* Step 2a: Compute cost of F o G^-1 */
11355 if (0 == avr_map_metric (f_ginv
.map
, MAP_NONFIXED_0_7
))
11357 /* The mapping consists only of fixed points and can be folded
11358 to AND/OR logic in the remainder. Reasonable cost is 3. */
11360 f_ginv
.cost
= 2 + (val_used_p
&& !val_const_p
);
11366 /* Get the cost of the insn by calling the output worker with some
11367 fake values. Mimic effect of reloading xop[3]: Unused operands
11368 are mapped to 0 and used operands are reloaded to xop[0]. */
11370 xop
[0] = all_regs_rtx
[24];
11371 xop
[1] = gen_int_mode (f_ginv
.map
.to_uhwi (), SImode
);
11372 xop
[2] = all_regs_rtx
[25];
11373 xop
[3] = val_used_p
? xop
[0] : const0_rtx
;
11375 avr_out_insert_bits (xop
, &f_ginv
.cost
);
11377 f_ginv
.cost
+= val_const_p
&& val_used_p
? 1 : 0;
11380 /* Step 2b: Add cost of G */
11382 f_ginv
.cost
+= g
->cost
;
11384 if (avr_log
.builtin
)
11385 avr_edump (" %s%d=%d", g
->str
, g
->arg
, f_ginv
.cost
);
11391 /* Insert bits from XOP[1] into XOP[0] according to MAP.
11392 XOP[0] and XOP[1] don't overlap.
11393 If FIXP_P = true: Move all bits according to MAP using BLD/BST sequences.
11394 If FIXP_P = false: Just move the bit if its position in the destination
11395 is different to its source position. */
11398 avr_move_bits (rtx
*xop
, double_int map
, bool fixp_p
, int *plen
)
11402 /* T-flag contains this bit of the source, i.e. of XOP[1] */
11403 int t_bit_src
= -1;
11405 /* We order the operations according to the requested source bit b. */
11407 for (b
= 0; b
< 8; b
++)
11408 for (bit_dest
= 0; bit_dest
< 8; bit_dest
++)
11410 int bit_src
= avr_map (map
, bit_dest
);
11414 /* Same position: No need to copy as requested by FIXP_P. */
11415 || (bit_dest
== bit_src
&& !fixp_p
))
11418 if (t_bit_src
!= bit_src
)
11420 /* Source bit is not yet in T: Store it to T. */
11422 t_bit_src
= bit_src
;
11424 xop
[3] = GEN_INT (bit_src
);
11425 avr_asm_len ("bst %T1%T3", xop
, plen
, 1);
11428 /* Load destination bit with T. */
11430 xop
[3] = GEN_INT (bit_dest
);
11431 avr_asm_len ("bld %T0%T3", xop
, plen
, 1);
11436 /* PLEN == 0: Print assembler code for `insert_bits'.
11437 PLEN != 0: Compute code length in bytes.
11440 OP[1]: The mapping composed of nibbles. If nibble no. N is
11441 0: Bit N of result is copied from bit OP[2].0
11443 7: Bit N of result is copied from bit OP[2].7
11444 0xf: Bit N of result is copied from bit OP[3].N
11445 OP[2]: Bits to be inserted
11446 OP[3]: Target value */
11449 avr_out_insert_bits (rtx
*op
, int *plen
)
11451 double_int map
= rtx_to_double_int (op
[1]);
11452 unsigned mask_fixed
;
11453 bool fixp_p
= true;
11460 gcc_assert (REG_P (xop
[2]) || CONST_INT_P (xop
[2]));
11464 else if (flag_print_asm_name
)
11465 fprintf (asm_out_file
,
11466 ASM_COMMENT_START
"map = 0x%08" HOST_LONG_FORMAT
"x\n",
11467 map
.to_uhwi () & GET_MODE_MASK (SImode
));
11469 /* If MAP has fixed points it might be better to initialize the result
11470 with the bits to be inserted instead of moving all bits by hand. */
11472 mask_fixed
= avr_map_metric (map
, MAP_MASK_FIXED_0_7
);
11474 if (REGNO (xop
[0]) == REGNO (xop
[1]))
11476 /* Avoid early-clobber conflicts */
11478 avr_asm_len ("mov __tmp_reg__,%1", xop
, plen
, 1);
11479 xop
[1] = tmp_reg_rtx
;
11483 if (avr_map_metric (map
, MAP_MASK_PREIMAGE_F
))
11485 /* XOP[2] is used and reloaded to XOP[0] already */
11487 int n_fix
= 0, n_nofix
= 0;
11489 gcc_assert (REG_P (xop
[2]));
11491 /* Get the code size of the bit insertions; once with all bits
11492 moved and once with fixed points omitted. */
11494 avr_move_bits (xop
, map
, true, &n_fix
);
11495 avr_move_bits (xop
, map
, false, &n_nofix
);
11497 if (fixp_p
&& n_fix
- n_nofix
> 3)
11499 xop
[3] = gen_int_mode (~mask_fixed
, QImode
);
11501 avr_asm_len ("eor %0,%1" CR_TAB
11502 "andi %0,%3" CR_TAB
11503 "eor %0,%1", xop
, plen
, 3);
11509 /* XOP[2] is unused */
11511 if (fixp_p
&& mask_fixed
)
11513 avr_asm_len ("mov %0,%1", xop
, plen
, 1);
11518 /* Move/insert remaining bits. */
11520 avr_move_bits (xop
, map
, fixp_p
, plen
);
11526 /* IDs for all the AVR builtins. */
11528 enum avr_builtin_id
11530 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
11531 AVR_BUILTIN_ ## NAME,
11532 #include "builtins.def"
11538 struct GTY(()) avr_builtin_description
11540 enum insn_code icode
;
11546 /* Notice that avr_bdesc[] and avr_builtin_id are initialized in such a way
11547 that a built-in's ID can be used to access the built-in by means of
11550 static GTY(()) struct avr_builtin_description
11551 avr_bdesc
[AVR_BUILTIN_COUNT
] =
11553 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME) \
11554 { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
11555 #include "builtins.def"
11560 /* Implement `TARGET_BUILTIN_DECL'. */
11563 avr_builtin_decl (unsigned id
, bool initialize_p ATTRIBUTE_UNUSED
)
11565 if (id
< AVR_BUILTIN_COUNT
)
11566 return avr_bdesc
[id
].fndecl
;
11568 return error_mark_node
;
11573 avr_init_builtin_int24 (void)
11575 tree int24_type
= make_signed_type (GET_MODE_BITSIZE (PSImode
));
11576 tree uint24_type
= make_unsigned_type (GET_MODE_BITSIZE (PSImode
));
11578 lang_hooks
.types
.register_builtin_type (int24_type
, "__int24");
11579 lang_hooks
.types
.register_builtin_type (uint24_type
, "__uint24");
11583 /* Implement `TARGET_INIT_BUILTINS' */
11584 /* Set up all builtin functions for this target. */
11587 avr_init_builtins (void)
11589 tree void_ftype_void
11590 = build_function_type_list (void_type_node
, NULL_TREE
);
11591 tree uchar_ftype_uchar
11592 = build_function_type_list (unsigned_char_type_node
,
11593 unsigned_char_type_node
,
11595 tree uint_ftype_uchar_uchar
11596 = build_function_type_list (unsigned_type_node
,
11597 unsigned_char_type_node
,
11598 unsigned_char_type_node
,
11600 tree int_ftype_char_char
11601 = build_function_type_list (integer_type_node
,
11605 tree int_ftype_char_uchar
11606 = build_function_type_list (integer_type_node
,
11608 unsigned_char_type_node
,
11610 tree void_ftype_ulong
11611 = build_function_type_list (void_type_node
,
11612 long_unsigned_type_node
,
11615 tree uchar_ftype_ulong_uchar_uchar
11616 = build_function_type_list (unsigned_char_type_node
,
11617 long_unsigned_type_node
,
11618 unsigned_char_type_node
,
11619 unsigned_char_type_node
,
11622 tree const_memx_void_node
11623 = build_qualified_type (void_type_node
,
11625 | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_MEMX
));
11627 tree const_memx_ptr_type_node
11628 = build_pointer_type_for_mode (const_memx_void_node
, PSImode
, false);
11630 tree char_ftype_const_memx_ptr
11631 = build_function_type_list (char_type_node
,
11632 const_memx_ptr_type_node
,
11636 lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
11638 #define FX_FTYPE_FX(fx) \
11639 tree fx##r_ftype_##fx##r \
11640 = build_function_type_list (node_##fx##r, node_##fx##r, NULL); \
11641 tree fx##k_ftype_##fx##k \
11642 = build_function_type_list (node_##fx##k, node_##fx##k, NULL)
11644 #define FX_FTYPE_FX_INT(fx) \
11645 tree fx##r_ftype_##fx##r_int \
11646 = build_function_type_list (node_##fx##r, node_##fx##r, \
11647 integer_type_node, NULL); \
11648 tree fx##k_ftype_##fx##k_int \
11649 = build_function_type_list (node_##fx##k, node_##fx##k, \
11650 integer_type_node, NULL)
11652 #define INT_FTYPE_FX(fx) \
11653 tree int_ftype_##fx##r \
11654 = build_function_type_list (integer_type_node, node_##fx##r, NULL); \
11655 tree int_ftype_##fx##k \
11656 = build_function_type_list (integer_type_node, node_##fx##k, NULL)
11658 #define INTX_FTYPE_FX(fx) \
11659 tree int##fx##r_ftype_##fx##r \
11660 = build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \
11661 tree int##fx##k_ftype_##fx##k \
11662 = build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL)
11664 #define FX_FTYPE_INTX(fx) \
11665 tree fx##r_ftype_int##fx##r \
11666 = build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \
11667 tree fx##k_ftype_int##fx##k \
11668 = build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL)
11670 tree node_hr
= short_fract_type_node
;
11671 tree node_nr
= fract_type_node
;
11672 tree node_lr
= long_fract_type_node
;
11673 tree node_llr
= long_long_fract_type_node
;
11675 tree node_uhr
= unsigned_short_fract_type_node
;
11676 tree node_unr
= unsigned_fract_type_node
;
11677 tree node_ulr
= unsigned_long_fract_type_node
;
11678 tree node_ullr
= unsigned_long_long_fract_type_node
;
11680 tree node_hk
= short_accum_type_node
;
11681 tree node_nk
= accum_type_node
;
11682 tree node_lk
= long_accum_type_node
;
11683 tree node_llk
= long_long_accum_type_node
;
11685 tree node_uhk
= unsigned_short_accum_type_node
;
11686 tree node_unk
= unsigned_accum_type_node
;
11687 tree node_ulk
= unsigned_long_accum_type_node
;
11688 tree node_ullk
= unsigned_long_long_accum_type_node
;
11691 /* For absfx builtins. */
11698 /* For roundfx builtins. */
11700 FX_FTYPE_FX_INT (h
);
11701 FX_FTYPE_FX_INT (n
);
11702 FX_FTYPE_FX_INT (l
);
11703 FX_FTYPE_FX_INT (ll
);
11705 FX_FTYPE_FX_INT (uh
);
11706 FX_FTYPE_FX_INT (un
);
11707 FX_FTYPE_FX_INT (ul
);
11708 FX_FTYPE_FX_INT (ull
);
11710 /* For countlsfx builtins. */
11720 INT_FTYPE_FX (ull
);
11722 /* For bitsfx builtins. */
11727 INTX_FTYPE_FX (ll
);
11729 INTX_FTYPE_FX (uh
);
11730 INTX_FTYPE_FX (un
);
11731 INTX_FTYPE_FX (ul
);
11732 INTX_FTYPE_FX (ull
);
11734 /* For fxbits builtins. */
11739 FX_FTYPE_INTX (ll
);
11741 FX_FTYPE_INTX (uh
);
11742 FX_FTYPE_INTX (un
);
11743 FX_FTYPE_INTX (ul
);
11744 FX_FTYPE_INTX (ull
);
11747 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
11749 int id = AVR_BUILTIN_ ## NAME; \
11750 const char *Name = "__builtin_avr_" #NAME; \
11751 char *name = (char*) alloca (1 + strlen (Name)); \
11753 gcc_assert (id < AVR_BUILTIN_COUNT); \
11754 avr_bdesc[id].fndecl \
11755 = add_builtin_function (avr_tolower (name, Name), TYPE, id, \
11756 BUILT_IN_MD, LIBNAME, NULL_TREE); \
11758 #include "builtins.def"
11761 avr_init_builtin_int24 ();
11765 /* Subroutine of avr_expand_builtin to expand vanilla builtins
11766 with non-void result and 1 ... 3 arguments. */
11769 avr_default_expand_builtin (enum insn_code icode
, tree exp
, rtx target
)
11772 int n
, n_args
= call_expr_nargs (exp
);
11773 enum machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
11775 gcc_assert (n_args
>= 1 && n_args
<= 3);
11777 if (target
== NULL_RTX
11778 || GET_MODE (target
) != tmode
11779 || !insn_data
[icode
].operand
[0].predicate (target
, tmode
))
11781 target
= gen_reg_rtx (tmode
);
11784 for (n
= 0; n
< n_args
; n
++)
11786 tree arg
= CALL_EXPR_ARG (exp
, n
);
11787 rtx op
= expand_expr (arg
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
11788 enum machine_mode opmode
= GET_MODE (op
);
11789 enum machine_mode mode
= insn_data
[icode
].operand
[n
+1].mode
;
11791 if ((opmode
== SImode
|| opmode
== VOIDmode
) && mode
== HImode
)
11794 op
= gen_lowpart (HImode
, op
);
11797 /* In case the insn wants input operands in modes different from
11798 the result, abort. */
11800 gcc_assert (opmode
== mode
|| opmode
== VOIDmode
);
11802 if (!insn_data
[icode
].operand
[n
+1].predicate (op
, mode
))
11803 op
= copy_to_mode_reg (mode
, op
);
11810 case 1: pat
= GEN_FCN (icode
) (target
, xop
[0]); break;
11811 case 2: pat
= GEN_FCN (icode
) (target
, xop
[0], xop
[1]); break;
11812 case 3: pat
= GEN_FCN (icode
) (target
, xop
[0], xop
[1], xop
[2]); break;
11818 if (pat
== NULL_RTX
)
11827 /* Implement `TARGET_EXPAND_BUILTIN'. */
11828 /* Expand an expression EXP that calls a built-in function,
11829 with result going to TARGET if that's convenient
11830 (and in mode MODE if that's convenient).
11831 SUBTARGET may be used as the target for computing one of EXP's operands.
11832 IGNORE is nonzero if the value is to be ignored. */
11835 avr_expand_builtin (tree exp
, rtx target
,
11836 rtx subtarget ATTRIBUTE_UNUSED
,
11837 enum machine_mode mode ATTRIBUTE_UNUSED
,
11840 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
11841 const char *bname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
11842 unsigned int id
= DECL_FUNCTION_CODE (fndecl
);
11843 const struct avr_builtin_description
*d
= &avr_bdesc
[id
];
11847 gcc_assert (id
< AVR_BUILTIN_COUNT
);
11851 case AVR_BUILTIN_NOP
:
11852 emit_insn (gen_nopv (GEN_INT(1)));
11855 case AVR_BUILTIN_DELAY_CYCLES
:
11857 arg0
= CALL_EXPR_ARG (exp
, 0);
11858 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
11860 if (!CONST_INT_P (op0
))
11861 error ("%s expects a compile time integer constant", bname
);
11863 avr_expand_delay_cycles (op0
);
11868 case AVR_BUILTIN_INSERT_BITS
:
11870 arg0
= CALL_EXPR_ARG (exp
, 0);
11871 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
11873 if (!CONST_INT_P (op0
))
11875 error ("%s expects a compile time long integer constant"
11876 " as first argument", bname
);
11883 case AVR_BUILTIN_ROUNDHR
: case AVR_BUILTIN_ROUNDUHR
:
11884 case AVR_BUILTIN_ROUNDR
: case AVR_BUILTIN_ROUNDUR
:
11885 case AVR_BUILTIN_ROUNDLR
: case AVR_BUILTIN_ROUNDULR
:
11886 case AVR_BUILTIN_ROUNDLLR
: case AVR_BUILTIN_ROUNDULLR
:
11888 case AVR_BUILTIN_ROUNDHK
: case AVR_BUILTIN_ROUNDUHK
:
11889 case AVR_BUILTIN_ROUNDK
: case AVR_BUILTIN_ROUNDUK
:
11890 case AVR_BUILTIN_ROUNDLK
: case AVR_BUILTIN_ROUNDULK
:
11891 case AVR_BUILTIN_ROUNDLLK
: case AVR_BUILTIN_ROUNDULLK
:
11893 /* Warn about odd rounding. Rounding points >= FBIT will have
11896 if (TREE_CODE (CALL_EXPR_ARG (exp
, 1)) != INTEGER_CST
)
11899 int rbit
= (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp
, 1));
11901 if (rbit
>= (int) GET_MODE_FBIT (mode
))
11903 warning (OPT_Wextra
, "rounding to %d bits has no effect for "
11904 "fixed-point value with %d fractional bits",
11905 rbit
, GET_MODE_FBIT (mode
));
11907 return expand_expr (CALL_EXPR_ARG (exp
, 0), NULL_RTX
, mode
,
11910 else if (rbit
<= - (int) GET_MODE_IBIT (mode
))
11912 warning (0, "rounding result will always be 0");
11913 return CONST0_RTX (mode
);
11916 /* The rounding points RP satisfies now: -IBIT < RP < FBIT.
11918 TR 18037 only specifies results for RP > 0. However, the
11919 remaining cases of -IBIT < RP <= 0 can easily be supported
11920 without any additional overhead. */
11925 /* No fold found and no insn: Call support function from libgcc. */
11927 if (d
->icode
== CODE_FOR_nothing
11928 && DECL_ASSEMBLER_NAME (get_callee_fndecl (exp
)) != NULL_TREE
)
11930 return expand_call (exp
, target
, ignore
);
11933 /* No special treatment needed: vanilla expand. */
11935 gcc_assert (d
->icode
!= CODE_FOR_nothing
);
11936 gcc_assert (d
->n_args
== call_expr_nargs (exp
));
11938 if (d
->n_args
== 0)
11940 emit_insn ((GEN_FCN (d
->icode
)) (target
));
11944 return avr_default_expand_builtin (d
->icode
, exp
, target
);
11948 /* Helper for `avr_fold_builtin' that folds absfx (FIXED_CST). */
11951 avr_fold_absfx (tree tval
)
11953 if (FIXED_CST
!= TREE_CODE (tval
))
11956 /* Our fixed-points have no padding: Use double_int payload directly. */
11958 FIXED_VALUE_TYPE fval
= TREE_FIXED_CST (tval
);
11959 unsigned int bits
= GET_MODE_BITSIZE (fval
.mode
);
11960 double_int ival
= fval
.data
.sext (bits
);
11962 if (!ival
.is_negative())
11965 /* ISO/IEC TR 18037, 7.18a.6.2: The absfx functions are saturating. */
11967 fval
.data
= (ival
== double_int::min_value (bits
, false).sext (bits
))
11968 ? double_int::max_value (bits
, false)
11971 return build_fixed (TREE_TYPE (tval
), fval
);
11975 /* Implement `TARGET_FOLD_BUILTIN'. */
11978 avr_fold_builtin (tree fndecl
, int n_args ATTRIBUTE_UNUSED
, tree
*arg
,
11979 bool ignore ATTRIBUTE_UNUSED
)
11981 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
11982 tree val_type
= TREE_TYPE (TREE_TYPE (fndecl
));
11992 case AVR_BUILTIN_SWAP
:
11994 return fold_build2 (LROTATE_EXPR
, val_type
, arg
[0],
11995 build_int_cst (val_type
, 4));
11998 case AVR_BUILTIN_ABSHR
:
11999 case AVR_BUILTIN_ABSR
:
12000 case AVR_BUILTIN_ABSLR
:
12001 case AVR_BUILTIN_ABSLLR
:
12003 case AVR_BUILTIN_ABSHK
:
12004 case AVR_BUILTIN_ABSK
:
12005 case AVR_BUILTIN_ABSLK
:
12006 case AVR_BUILTIN_ABSLLK
:
12007 /* GCC is not good with folding ABS for fixed-point. Do it by hand. */
12009 return avr_fold_absfx (arg
[0]);
12011 case AVR_BUILTIN_BITSHR
: case AVR_BUILTIN_HRBITS
:
12012 case AVR_BUILTIN_BITSHK
: case AVR_BUILTIN_HKBITS
:
12013 case AVR_BUILTIN_BITSUHR
: case AVR_BUILTIN_UHRBITS
:
12014 case AVR_BUILTIN_BITSUHK
: case AVR_BUILTIN_UHKBITS
:
12016 case AVR_BUILTIN_BITSR
: case AVR_BUILTIN_RBITS
:
12017 case AVR_BUILTIN_BITSK
: case AVR_BUILTIN_KBITS
:
12018 case AVR_BUILTIN_BITSUR
: case AVR_BUILTIN_URBITS
:
12019 case AVR_BUILTIN_BITSUK
: case AVR_BUILTIN_UKBITS
:
12021 case AVR_BUILTIN_BITSLR
: case AVR_BUILTIN_LRBITS
:
12022 case AVR_BUILTIN_BITSLK
: case AVR_BUILTIN_LKBITS
:
12023 case AVR_BUILTIN_BITSULR
: case AVR_BUILTIN_ULRBITS
:
12024 case AVR_BUILTIN_BITSULK
: case AVR_BUILTIN_ULKBITS
:
12026 case AVR_BUILTIN_BITSLLR
: case AVR_BUILTIN_LLRBITS
:
12027 case AVR_BUILTIN_BITSLLK
: case AVR_BUILTIN_LLKBITS
:
12028 case AVR_BUILTIN_BITSULLR
: case AVR_BUILTIN_ULLRBITS
:
12029 case AVR_BUILTIN_BITSULLK
: case AVR_BUILTIN_ULLKBITS
:
12031 gcc_assert (TYPE_PRECISION (val_type
)
12032 == TYPE_PRECISION (TREE_TYPE (arg
[0])));
12034 return build1 (VIEW_CONVERT_EXPR
, val_type
, arg
[0]);
12036 case AVR_BUILTIN_INSERT_BITS
:
12038 tree tbits
= arg
[1];
12039 tree tval
= arg
[2];
12041 tree map_type
= TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl
)));
12043 bool changed
= false;
12045 avr_map_op_t best_g
;
12047 if (TREE_CODE (arg
[0]) != INTEGER_CST
)
12049 /* No constant as first argument: Don't fold this and run into
12050 error in avr_expand_builtin. */
12055 map
= tree_to_double_int (arg
[0]);
12056 tmap
= double_int_to_tree (map_type
, map
);
12058 if (TREE_CODE (tval
) != INTEGER_CST
12059 && 0 == avr_map_metric (map
, MAP_MASK_PREIMAGE_F
))
12061 /* There are no F in the map, i.e. 3rd operand is unused.
12062 Replace that argument with some constant to render
12063 respective input unused. */
12065 tval
= build_int_cst (val_type
, 0);
12069 if (TREE_CODE (tbits
) != INTEGER_CST
12070 && 0 == avr_map_metric (map
, MAP_PREIMAGE_0_7
))
12072 /* Similar for the bits to be inserted. If they are unused,
12073 we can just as well pass 0. */
12075 tbits
= build_int_cst (val_type
, 0);
12078 if (TREE_CODE (tbits
) == INTEGER_CST
)
12080 /* Inserting bits known at compile time is easy and can be
12081 performed by AND and OR with appropriate masks. */
12083 int bits
= TREE_INT_CST_LOW (tbits
);
12084 int mask_ior
= 0, mask_and
= 0xff;
12086 for (i
= 0; i
< 8; i
++)
12088 int mi
= avr_map (map
, i
);
12092 if (bits
& (1 << mi
)) mask_ior
|= (1 << i
);
12093 else mask_and
&= ~(1 << i
);
12097 tval
= fold_build2 (BIT_IOR_EXPR
, val_type
, tval
,
12098 build_int_cst (val_type
, mask_ior
));
12099 return fold_build2 (BIT_AND_EXPR
, val_type
, tval
,
12100 build_int_cst (val_type
, mask_and
));
12104 return build_call_expr (fndecl
, 3, tmap
, tbits
, tval
);
12106 /* If bits don't change their position we can use vanilla logic
12107 to merge the two arguments. */
12109 if (0 == avr_map_metric (map
, MAP_NONFIXED_0_7
))
12111 int mask_f
= avr_map_metric (map
, MAP_MASK_PREIMAGE_F
);
12112 tree tres
, tmask
= build_int_cst (val_type
, mask_f
^ 0xff);
12114 tres
= fold_build2 (BIT_XOR_EXPR
, val_type
, tbits
, tval
);
12115 tres
= fold_build2 (BIT_AND_EXPR
, val_type
, tres
, tmask
);
12116 return fold_build2 (BIT_XOR_EXPR
, val_type
, tres
, tval
);
12119 /* Try to decomposing map to reduce overall cost. */
12121 if (avr_log
.builtin
)
12122 avr_edump ("\n%?: %X\n%?: ROL cost: ", map
);
12124 best_g
= avr_map_op
[0];
12125 best_g
.cost
= 1000;
12127 for (i
= 0; i
< sizeof (avr_map_op
) / sizeof (*avr_map_op
); i
++)
12130 = avr_map_decompose (map
, avr_map_op
+ i
,
12131 TREE_CODE (tval
) == INTEGER_CST
);
12133 if (g
.cost
>= 0 && g
.cost
< best_g
.cost
)
12137 if (avr_log
.builtin
)
12140 if (best_g
.arg
== 0)
12141 /* No optimization found */
12144 /* Apply operation G to the 2nd argument. */
12146 if (avr_log
.builtin
)
12147 avr_edump ("%?: using OP(%s%d, %X) cost %d\n",
12148 best_g
.str
, best_g
.arg
, best_g
.map
, best_g
.cost
);
12150 /* Do right-shifts arithmetically: They copy the MSB instead of
12151 shifting in a non-usable value (0) as with logic right-shift. */
12153 tbits
= fold_convert (signed_char_type_node
, tbits
);
12154 tbits
= fold_build2 (best_g
.code
, signed_char_type_node
, tbits
,
12155 build_int_cst (val_type
, best_g
.arg
));
12156 tbits
= fold_convert (val_type
, tbits
);
12158 /* Use map o G^-1 instead of original map to undo the effect of G. */
12160 tmap
= double_int_to_tree (map_type
, best_g
.map
);
12162 return build_call_expr (fndecl
, 3, tmap
, tbits
, tval
);
12163 } /* AVR_BUILTIN_INSERT_BITS */
12171 /* Initialize the GCC target structure. */
12173 #undef TARGET_ASM_ALIGNED_HI_OP
12174 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
12175 #undef TARGET_ASM_ALIGNED_SI_OP
12176 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
12177 #undef TARGET_ASM_UNALIGNED_HI_OP
12178 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
12179 #undef TARGET_ASM_UNALIGNED_SI_OP
12180 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
12181 #undef TARGET_ASM_INTEGER
12182 #define TARGET_ASM_INTEGER avr_assemble_integer
12183 #undef TARGET_ASM_FILE_START
12184 #define TARGET_ASM_FILE_START avr_file_start
12185 #undef TARGET_ASM_FILE_END
12186 #define TARGET_ASM_FILE_END avr_file_end
12188 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
12189 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
12190 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
12191 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
12193 #undef TARGET_FUNCTION_VALUE
12194 #define TARGET_FUNCTION_VALUE avr_function_value
12195 #undef TARGET_LIBCALL_VALUE
12196 #define TARGET_LIBCALL_VALUE avr_libcall_value
12197 #undef TARGET_FUNCTION_VALUE_REGNO_P
12198 #define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
12200 #undef TARGET_ATTRIBUTE_TABLE
12201 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
12202 #undef TARGET_INSERT_ATTRIBUTES
12203 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
12204 #undef TARGET_SECTION_TYPE_FLAGS
12205 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
12207 #undef TARGET_ASM_NAMED_SECTION
12208 #define TARGET_ASM_NAMED_SECTION avr_asm_named_section
12209 #undef TARGET_ASM_INIT_SECTIONS
12210 #define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
12211 #undef TARGET_ENCODE_SECTION_INFO
12212 #define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
12213 #undef TARGET_ASM_SELECT_SECTION
12214 #define TARGET_ASM_SELECT_SECTION avr_asm_select_section
12216 #undef TARGET_REGISTER_MOVE_COST
12217 #define TARGET_REGISTER_MOVE_COST avr_register_move_cost
12218 #undef TARGET_MEMORY_MOVE_COST
12219 #define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
12220 #undef TARGET_RTX_COSTS
12221 #define TARGET_RTX_COSTS avr_rtx_costs
12222 #undef TARGET_ADDRESS_COST
12223 #define TARGET_ADDRESS_COST avr_address_cost
12224 #undef TARGET_MACHINE_DEPENDENT_REORG
12225 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
12226 #undef TARGET_FUNCTION_ARG
12227 #define TARGET_FUNCTION_ARG avr_function_arg
12228 #undef TARGET_FUNCTION_ARG_ADVANCE
12229 #define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
12231 #undef TARGET_SET_CURRENT_FUNCTION
12232 #define TARGET_SET_CURRENT_FUNCTION avr_set_current_function
12234 #undef TARGET_RETURN_IN_MEMORY
12235 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
12237 #undef TARGET_STRICT_ARGUMENT_NAMING
12238 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
12240 #undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
12241 #define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
12243 #undef TARGET_HARD_REGNO_SCRATCH_OK
12244 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
12245 #undef TARGET_CASE_VALUES_THRESHOLD
12246 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
12248 #undef TARGET_FRAME_POINTER_REQUIRED
12249 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
12250 #undef TARGET_CAN_ELIMINATE
12251 #define TARGET_CAN_ELIMINATE avr_can_eliminate
12253 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
12254 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS avr_allocate_stack_slots_for_args
12256 #undef TARGET_WARN_FUNC_RETURN
12257 #define TARGET_WARN_FUNC_RETURN avr_warn_func_return
12259 #undef TARGET_CLASS_LIKELY_SPILLED_P
12260 #define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
12262 #undef TARGET_OPTION_OVERRIDE
12263 #define TARGET_OPTION_OVERRIDE avr_option_override
12265 #undef TARGET_CANNOT_MODIFY_JUMPS_P
12266 #define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
12268 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
12269 #define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
12271 #undef TARGET_INIT_BUILTINS
12272 #define TARGET_INIT_BUILTINS avr_init_builtins
12274 #undef TARGET_BUILTIN_DECL
12275 #define TARGET_BUILTIN_DECL avr_builtin_decl
12277 #undef TARGET_EXPAND_BUILTIN
12278 #define TARGET_EXPAND_BUILTIN avr_expand_builtin
12280 #undef TARGET_FOLD_BUILTIN
12281 #define TARGET_FOLD_BUILTIN avr_fold_builtin
12283 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
12284 #define TARGET_ASM_FUNCTION_RODATA_SECTION avr_asm_function_rodata_section
12286 #undef TARGET_SCALAR_MODE_SUPPORTED_P
12287 #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
12289 #undef TARGET_BUILD_BUILTIN_VA_LIST
12290 #define TARGET_BUILD_BUILTIN_VA_LIST avr_build_builtin_va_list
12292 #undef TARGET_FIXED_POINT_SUPPORTED_P
12293 #define TARGET_FIXED_POINT_SUPPORTED_P hook_bool_void_true
12295 #undef TARGET_CONVERT_TO_TYPE
12296 #define TARGET_CONVERT_TO_TYPE avr_convert_to_type
12298 #undef TARGET_ADDR_SPACE_SUBSET_P
12299 #define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
12301 #undef TARGET_ADDR_SPACE_CONVERT
12302 #define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
12304 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
12305 #define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
12307 #undef TARGET_ADDR_SPACE_POINTER_MODE
12308 #define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
12310 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
12311 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
12312 avr_addr_space_legitimate_address_p
12314 #undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
12315 #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
12317 #undef TARGET_MODE_DEPENDENT_ADDRESS_P
12318 #define TARGET_MODE_DEPENDENT_ADDRESS_P avr_mode_dependent_address_p
12320 #undef TARGET_SECONDARY_RELOAD
12321 #define TARGET_SECONDARY_RELOAD avr_secondary_reload
12323 #undef TARGET_PRINT_OPERAND
12324 #define TARGET_PRINT_OPERAND avr_print_operand
12325 #undef TARGET_PRINT_OPERAND_ADDRESS
12326 #define TARGET_PRINT_OPERAND_ADDRESS avr_print_operand_address
12327 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
12328 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P avr_print_operand_punct_valid_p
12330 struct gcc_target targetm
= TARGET_INITIALIZER
;
12333 #include "gt-avr.h"