/* Subroutines for insn-output.c for ATMEL AVR micro controllers
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008
- Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008,
+ 2009 Free Software Foundation, Inc.
Contributed by Denis Chertykov (denisc@overta.ru)
This file is part of GCC.
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
+#include "params.h"
#include "df.h"
/* Maximal allowed offset for an address in the LD command */
static int interrupt_function_p (tree);
static int signal_function_p (tree);
static int avr_OS_task_function_p (tree);
+static int avr_OS_main_function_p (tree);
static int avr_regs_to_save (HARD_REG_SET *);
+static int get_sequence_length (rtx insns);
static int sequent_regs_live (void);
static const char *ptrreg_to_str (int);
static const char *cond_string (enum rtx_code);
static void avr_file_end (void);
static void avr_asm_function_end_prologue (FILE *);
static void avr_asm_function_begin_epilogue (FILE *);
+static rtx avr_function_value (const_tree, const_tree, bool);
static void avr_insert_attributes (tree, tree *);
static void avr_asm_init_sections (void);
static unsigned int avr_section_type_flags (tree, const char *, int);
static void avr_reorg (void);
static void avr_asm_out_ctor (rtx, int);
static void avr_asm_out_dtor (rtx, int);
-static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code);
-static bool avr_rtx_costs (rtx, int, int, int *);
-static int avr_address_cost (rtx);
+static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code, bool);
+static bool avr_rtx_costs (rtx, int, int, int *, bool);
+static int avr_address_cost (rtx, bool);
static bool avr_return_in_memory (const_tree, const_tree);
static struct machine_function * avr_init_machine_status (void);
+static rtx avr_builtin_setjmp_frame_value (void);
+static bool avr_hard_regno_scratch_ok (unsigned int);
+
/* Allocate registers from r25 to r8 for parameters for function calls. */
#define FIRST_CUM_REG 26
static int last_insn_address = 0;
/* Preprocessor macros to define depending on MCU type. */
-const char *avr_base_arch_macro;
const char *avr_extra_arch_macro;
/* Current architecture. */
section *progmem_section;
-/* Core have 'MUL*' instructions. */
-int avr_have_mul_p = 0;
-
-/* Assembler only. */
-int avr_asm_only_p = 0;
-
-/* Core have 'MOVW' and 'LPM Rx,Z' instructions. */
-int avr_have_movw_lpmx_p = 0;
-
static const struct base_arch_s avr_arch_types[] = {
{ 1, 0, 0, 0, 0, 0, 0, 0, NULL }, /* unknown device specified */
{ 1, 0, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=1" },
{ "at90s8535", ARCH_AVR2, "__AVR_AT90S8535__" },
/* Classic + MOVW, <= 8K. */
{ "avr25", ARCH_AVR25, NULL },
+ { "ata6289", ARCH_AVR25, "__AVR_ATA6289__" },
{ "attiny13", ARCH_AVR25, "__AVR_ATtiny13__" },
+ { "attiny13a", ARCH_AVR25, "__AVR_ATtiny13A__" },
{ "attiny2313", ARCH_AVR25, "__AVR_ATtiny2313__" },
{ "attiny24", ARCH_AVR25, "__AVR_ATtiny24__" },
{ "attiny44", ARCH_AVR25, "__AVR_ATtiny44__" },
{ "attiny461", ARCH_AVR25, "__AVR_ATtiny461__" },
{ "attiny861", ARCH_AVR25, "__AVR_ATtiny861__" },
{ "attiny43u", ARCH_AVR25, "__AVR_ATtiny43U__" },
+ { "attiny87", ARCH_AVR25, "__AVR_ATtiny87__" },
{ "attiny48", ARCH_AVR25, "__AVR_ATtiny48__" },
{ "attiny88", ARCH_AVR25, "__AVR_ATtiny88__" },
{ "at86rf401", ARCH_AVR25, "__AVR_AT86RF401__" },
/* Classic, > 8K, <= 64K. */
{ "avr3", ARCH_AVR3, NULL },
- { "at43usb320", ARCH_AVR3, "__AVR_AT43USB320__" },
{ "at43usb355", ARCH_AVR3, "__AVR_AT43USB355__" },
{ "at76c711", ARCH_AVR3, "__AVR_AT76C711__" },
/* Classic, == 128K. */
{ "avr31", ARCH_AVR31, NULL },
{ "atmega103", ARCH_AVR31, "__AVR_ATmega103__" },
+ { "at43usb320", ARCH_AVR31, "__AVR_AT43USB320__" },
/* Classic + MOVW + JMP/CALL. */
{ "avr35", ARCH_AVR35, NULL },
{ "at90usb82", ARCH_AVR35, "__AVR_AT90USB82__" },
{ "at90usb162", ARCH_AVR35, "__AVR_AT90USB162__" },
+ { "attiny167", ARCH_AVR35, "__AVR_ATtiny167__" },
+ { "attiny327", ARCH_AVR35, "__AVR_ATtiny327__" },
/* Enhanced, <= 8K. */
{ "avr4", ARCH_AVR4, NULL },
{ "atmega8", ARCH_AVR4, "__AVR_ATmega8__" },
{ "atmega8515", ARCH_AVR4, "__AVR_ATmega8515__" },
{ "atmega8535", ARCH_AVR4, "__AVR_ATmega8535__" },
{ "atmega8hva", ARCH_AVR4, "__AVR_ATmega8HVA__" },
+ { "atmega4hvd", ARCH_AVR4, "__AVR_ATmega4HVD__" },
+ { "atmega8hvd", ARCH_AVR4, "__AVR_ATmega8HVD__" },
+ { "atmega8c1", ARCH_AVR4, "__AVR_ATmega8C1__" },
+ { "atmega8m1", ARCH_AVR4, "__AVR_ATmega8M1__" },
{ "at90pwm1", ARCH_AVR4, "__AVR_AT90PWM1__" },
{ "at90pwm2", ARCH_AVR4, "__AVR_AT90PWM2__" },
{ "at90pwm2b", ARCH_AVR4, "__AVR_AT90PWM2B__" },
{ "at90pwm3", ARCH_AVR4, "__AVR_AT90PWM3__" },
{ "at90pwm3b", ARCH_AVR4, "__AVR_AT90PWM3B__" },
+ { "at90pwm81", ARCH_AVR4, "__AVR_AT90PWM81__" },
/* Enhanced, > 8K, <= 64K. */
{ "avr5", ARCH_AVR5, NULL },
{ "atmega16", ARCH_AVR5, "__AVR_ATmega16__" },
{ "atmega329p", ARCH_AVR5, "__AVR_ATmega329P__" },
{ "atmega3290", ARCH_AVR5, "__AVR_ATmega3290__" },
{ "atmega3290p", ARCH_AVR5, "__AVR_ATmega3290P__" },
- { "atmega32hvb", ARCH_AVR5, "__AVR_ATmega32HVB__" },
{ "atmega406", ARCH_AVR5, "__AVR_ATmega406__" },
{ "atmega64", ARCH_AVR5, "__AVR_ATmega64__" },
{ "atmega640", ARCH_AVR5, "__AVR_ATmega640__" },
{ "atmega649", ARCH_AVR5, "__AVR_ATmega649__" },
{ "atmega6490", ARCH_AVR5, "__AVR_ATmega6490__" },
{ "atmega16hva", ARCH_AVR5, "__AVR_ATmega16HVA__" },
+ { "atmega16hvb", ARCH_AVR5, "__AVR_ATmega16HVB__" },
+ { "atmega32hvb", ARCH_AVR5, "__AVR_ATmega32HVB__" },
{ "at90can32", ARCH_AVR5, "__AVR_AT90CAN32__" },
{ "at90can64", ARCH_AVR5, "__AVR_AT90CAN64__" },
{ "at90pwm216", ARCH_AVR5, "__AVR_AT90PWM216__" },
{ "at90pwm316", ARCH_AVR5, "__AVR_AT90PWM316__" },
+ { "atmega16c1", ARCH_AVR5, "__AVR_ATmega16C1__" },
+ { "atmega32c1", ARCH_AVR5, "__AVR_ATmega32C1__" },
+ { "atmega64c1", ARCH_AVR5, "__AVR_ATmega64C1__" },
+ { "atmega16m1", ARCH_AVR5, "__AVR_ATmega16M1__" },
+ { "atmega32m1", ARCH_AVR5, "__AVR_ATmega32M1__" },
+ { "atmega64m1", ARCH_AVR5, "__AVR_ATmega64M1__" },
+ { "atmega16u4", ARCH_AVR5, "__AVR_ATmega16U4__" },
+ { "atmega32u4", ARCH_AVR5, "__AVR_ATmega32U4__" },
+ { "atmega32u6", ARCH_AVR5, "__AVR_ATmega32U6__" },
+ { "at90scr100", ARCH_AVR5, "__AVR_AT90SCR100__" },
{ "at90usb646", ARCH_AVR5, "__AVR_AT90USB646__" },
{ "at90usb647", ARCH_AVR5, "__AVR_AT90USB647__" },
{ "at94k", ARCH_AVR5, "__AVR_AT94K__" },
{ "atmega1280", ARCH_AVR51, "__AVR_ATmega1280__" },
{ "atmega1281", ARCH_AVR51, "__AVR_ATmega1281__" },
{ "atmega1284p", ARCH_AVR51, "__AVR_ATmega1284P__" },
+ { "atmega128rfa1", ARCH_AVR51, "__AVR_ATmega128RFA1__" },
{ "at90can128", ARCH_AVR51, "__AVR_AT90CAN128__" },
{ "at90usb1286", ARCH_AVR51, "__AVR_AT90USB1286__" },
{ "at90usb1287", ARCH_AVR51, "__AVR_AT90USB1287__" },
+ { "m3000f", ARCH_AVR51, "__AVR_M3000F__" },
+ { "m3000s", ARCH_AVR51, "__AVR_M3000S__" },
+ { "m3001b", ARCH_AVR51, "__AVR_M3001B__" },
/* 3-Byte PC. */
{ "avr6", ARCH_AVR6, NULL },
{ "atmega2560", ARCH_AVR6, "__AVR_ATmega2560__" },
#define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
#undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
#define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE avr_function_value
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE avr_attribute_table
#undef TARGET_ASM_FUNCTION_RODATA_SECTION
#undef TARGET_STRICT_ARGUMENT_NAMING
#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
+#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
+#define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
+
+#undef TARGET_HARD_REGNO_SCRATCH_OK
+#define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
void
avr_override_options (void)
{
const struct mcu_type_s *t;
- const struct base_arch_s *base;
flag_delete_null_pointer_checks = 0;
+ if (!PARAM_SET_P (PARAM_INLINE_CALL_COST))
+ set_param_value ("inline-call-cost", 5);
+
for (t = avr_mcu_types; t->name; t++)
if (strcmp (t->name, avr_mcu_name) == 0)
break;
}
avr_current_arch = &avr_arch_types[t->arch];
- base = &avr_arch_types[t->arch];
- avr_asm_only_p = base->asm_only;
- avr_have_mul_p = base->have_mul;
- avr_have_movw_lpmx_p = base->have_movw_lpmx;
- avr_base_arch_macro = base->macro;
avr_extra_arch_macro = t->macro;
if (optimize && !TARGET_NO_TABLEJUMP)
return a != NULL_TREE;
}
+/* Return nonzero if FUNC is a OS_main function. */
+
+static int
+avr_OS_main_function_p (tree func)
+{
+ tree a;
+
+ gcc_assert (TREE_CODE (func) == FUNCTION_DECL);
+
+ a = lookup_attribute ("OS_main", TYPE_ATTRIBUTES (TREE_TYPE (func)));
+ return a != NULL_TREE;
+}
+
/* Return the number of hard registers to push/pop in the prologue/epilogue
of the current function, and optionally store these registers in SET. */
int reg, count;
int int_or_sig_p = (interrupt_function_p (current_function_decl)
|| signal_function_p (current_function_decl));
- int leaf_func_p = leaf_function_p ();
+
+ if (!reload_completed)
+ cfun->machine->is_leaf = leaf_function_p ();
if (set)
CLEAR_HARD_REG_SET (*set);
count = 0;
/* No need to save any registers if the function never returns or
- is have "OS_task" attribute. */
+ is have "OS_task" or "OS_main" attribute. */
if (TREE_THIS_VOLATILE (current_function_decl)
- || cfun->machine->is_OS_task)
+ || cfun->machine->is_OS_task
+ || cfun->machine->is_OS_main)
return 0;
for (reg = 0; reg < 32; reg++)
if (fixed_regs[reg])
continue;
- if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
+ if ((int_or_sig_p && !cfun->machine->is_leaf && call_used_regs[reg])
|| (df_regs_ever_live_p (reg)
&& (int_or_sig_p || !call_used_regs[reg])
&& !(frame_pointer_needed
}
}
+/* Actual start of frame is virtual_stack_vars_rtx this is offset from
+ frame pointer by +STARTING_FRAME_OFFSET.
+ Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET
+ avoids creating add/sub of offset in nonlocal goto and setjmp. */
+
+rtx avr_builtin_setjmp_frame_value (void)
+{
+ return gen_rtx_MINUS (Pmode, virtual_stack_vars_rtx,
+ gen_int_mode (STARTING_FRAME_OFFSET, Pmode));
+}
+
/* Return 1 if the function epilogue is just a single "ret". */
int
return (cur_seq == live_seq) ? live_seq : 0;
}
+/* Obtain the length sequence of insns. */
+
+int
+get_sequence_length (rtx insns)
+{
+ rtx insn;
+ int length;
+
+ for (insn = insns, length = 0; insn; insn = NEXT_INSN (insn))
+ length += get_attr_length (insn);
+
+ return length;
+}
+
/* Output function prologue. */
void
cfun->machine->is_interrupt = interrupt_function_p (current_function_decl);
cfun->machine->is_signal = signal_function_p (current_function_decl);
cfun->machine->is_OS_task = avr_OS_task_function_p (current_function_decl);
+ cfun->machine->is_OS_main = avr_OS_main_function_p (current_function_decl);
/* Prologue: naked. */
if (cfun->machine->is_naked)
&& !cfun->machine->is_interrupt
&& !cfun->machine->is_signal
&& !cfun->machine->is_OS_task
+ && !cfun->machine->is_OS_main
&& live_seq);
if (cfun->machine->is_interrupt || cfun->machine->is_signal)
RTX_FRAME_RELATED_P (insn) = 1;
/* Prevent any attempt to delete the setting of ZERO_REG! */
- emit_insn (gen_rtx_USE (VOIDmode, zero_reg_rtx));
+ emit_use (zero_reg_rtx);
}
- if (minimize && (frame_pointer_needed || live_seq > 6))
+ if (minimize && (frame_pointer_needed
+ || (AVR_2_BYTE_PC && live_seq > 6)
+ || live_seq > 7))
{
insn = emit_move_insn (gen_rtx_REG (HImode, REG_X),
gen_int_mode (size, HImode));
}
if (frame_pointer_needed)
{
- if(!cfun->machine->is_OS_task)
+ if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
{
/* Push frame pointer. */
insn = emit_move_insn (pushword, frame_pointer_rtx);
To avoid a complex logic, both methods are tested and shortest
is selected. */
rtx myfp;
- /* First method. */
+ rtx fp_plus_insns;
+ rtx sp_plus_insns = NULL_RTX;
+
if (TARGET_TINY_STACK)
{
- if (size < -63 || size > 63)
- warning (0, "large frame pointer change (%d) with -mtiny-stack", size);
-
/* The high byte (r29) doesn't change - prefer 'subi' (1 cycle)
over 'sbiw' (2 cycles, same size). */
myfp = gen_rtx_REG (QImode, REGNO (frame_pointer_rtx));
/* Normal sized addition. */
myfp = frame_pointer_rtx;
}
- /* Calculate length. */
- int method1_length;
- method1_length =
- get_attr_length (gen_move_insn (frame_pointer_rtx, stack_pointer_rtx));
- method1_length +=
- get_attr_length (gen_move_insn (myfp,
- gen_rtx_PLUS (GET_MODE(myfp), myfp,
- gen_int_mode (-size,
- GET_MODE(myfp)))));
- method1_length +=
- get_attr_length (gen_move_insn (stack_pointer_rtx, frame_pointer_rtx));
-
+
+ /* Method 1-Adjust frame pointer. */
+ start_sequence ();
+
+ insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ insn =
+ emit_move_insn (myfp,
+ gen_rtx_PLUS (GET_MODE(myfp), myfp,
+ gen_int_mode (-size,
+ GET_MODE(myfp))));
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ /* Copy to stack pointer. */
+ if (TARGET_TINY_STACK)
+ {
+ insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else if (TARGET_NO_INTERRUPTS
+ || cfun->machine->is_signal
+ || cfun->machine->is_OS_main)
+ {
+ insn =
+ emit_insn (gen_movhi_sp_r_irq_off (stack_pointer_rtx,
+ frame_pointer_rtx));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else if (cfun->machine->is_interrupt)
+ {
+ insn = emit_insn (gen_movhi_sp_r_irq_on (stack_pointer_rtx,
+ frame_pointer_rtx));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else
+ {
+ insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ fp_plus_insns = get_insns ();
+ end_sequence ();
+
/* Method 2-Adjust Stack pointer. */
- int sp_plus_length = 0;
if (size <= 6)
{
- sp_plus_length =
- get_attr_length (gen_move_insn (stack_pointer_rtx,
- gen_rtx_PLUS (HImode, stack_pointer_rtx,
- gen_int_mode (-size,
- HImode))));
- sp_plus_length +=
- get_attr_length (gen_move_insn (frame_pointer_rtx, stack_pointer_rtx));
+ start_sequence ();
+
+ insn =
+ emit_move_insn (stack_pointer_rtx,
+ gen_rtx_PLUS (HImode,
+ stack_pointer_rtx,
+ gen_int_mode (-size,
+ HImode)));
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ insn =
+ emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ sp_plus_insns = get_insns ();
+ end_sequence ();
}
+
/* Use shortest method. */
- if (size <= 6 && (sp_plus_length < method1_length))
- {
- insn = emit_move_insn (stack_pointer_rtx,
- gen_rtx_PLUS (HImode, stack_pointer_rtx,
- gen_int_mode (-size, HImode)));
- RTX_FRAME_RELATED_P (insn) = 1;
- insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
+ if (size <= 6 && (get_sequence_length (sp_plus_insns)
+ < get_sequence_length (fp_plus_insns)))
+ emit_insn (sp_plus_insns);
else
- {
- insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
- insn = emit_move_insn (myfp,
- gen_rtx_PLUS (GET_MODE(myfp), myfp,
- gen_int_mode (-size, GET_MODE(myfp))));
- RTX_FRAME_RELATED_P (insn) = 1;
- insn = emit_move_insn ( stack_pointer_rtx, frame_pointer_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
+ emit_insn (fp_plus_insns);
}
}
}
&& !cfun->machine->is_interrupt
&& !cfun->machine->is_signal
&& !cfun->machine->is_OS_task
+ && !cfun->machine->is_OS_main
&& live_seq);
if (minimize && (frame_pointer_needed || live_seq > 4))
if (size)
{
/* Try two methods to adjust stack and select shortest. */
- int fp_plus_length;
+ rtx myfp;
+ rtx fp_plus_insns;
+ rtx sp_plus_insns = NULL_RTX;
+
+ if (TARGET_TINY_STACK)
+ {
+ /* The high byte (r29) doesn't change - prefer 'subi'
+ (1 cycle) over 'sbiw' (2 cycles, same size). */
+ myfp = gen_rtx_REG (QImode, REGNO (frame_pointer_rtx));
+ }
+ else
+ {
+ /* Normal sized addition. */
+ myfp = frame_pointer_rtx;
+ }
+
/* Method 1-Adjust frame pointer. */
- fp_plus_length =
- get_attr_length (gen_move_insn (frame_pointer_rtx,
- gen_rtx_PLUS (HImode, frame_pointer_rtx,
- gen_int_mode (size,
- HImode))));
- /* Copy to stack pointer. */
- fp_plus_length +=
- get_attr_length (gen_move_insn (stack_pointer_rtx, frame_pointer_rtx));
-
+ start_sequence ();
+
+ emit_move_insn (myfp,
+ gen_rtx_PLUS (HImode, myfp,
+ gen_int_mode (size,
+ GET_MODE(myfp))));
+
+ /* Copy to stack pointer. */
+ if (TARGET_TINY_STACK)
+ {
+ emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+ }
+ else if (TARGET_NO_INTERRUPTS
+ || cfun->machine->is_signal)
+ {
+ emit_insn (gen_movhi_sp_r_irq_off (stack_pointer_rtx,
+ frame_pointer_rtx));
+ }
+ else if (cfun->machine->is_interrupt)
+ {
+ emit_insn (gen_movhi_sp_r_irq_on (stack_pointer_rtx,
+ frame_pointer_rtx));
+ }
+ else
+ {
+ emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+ }
+
+ fp_plus_insns = get_insns ();
+ end_sequence ();
+
/* Method 2-Adjust Stack pointer. */
- int sp_plus_length = 0;
if (size <= 5)
{
- sp_plus_length =
- get_attr_length (gen_move_insn (stack_pointer_rtx,
- gen_rtx_PLUS (HImode, stack_pointer_rtx,
- gen_int_mode (size,
- HImode))));
+ start_sequence ();
+
+ emit_move_insn (stack_pointer_rtx,
+ gen_rtx_PLUS (HImode, stack_pointer_rtx,
+ gen_int_mode (size,
+ HImode)));
+
+ sp_plus_insns = get_insns ();
+ end_sequence ();
}
+
/* Use shortest method. */
- if (size <= 5 && (sp_plus_length < fp_plus_length))
- {
- emit_move_insn (stack_pointer_rtx,
- gen_rtx_PLUS (HImode, stack_pointer_rtx,
- gen_int_mode (size, HImode)));
- }
+ if (size <= 5 && (get_sequence_length (sp_plus_insns)
+ < get_sequence_length (fp_plus_insns)))
+ emit_insn (sp_plus_insns);
else
- {
- emit_move_insn (frame_pointer_rtx,
- gen_rtx_PLUS (HImode, frame_pointer_rtx,
- gen_int_mode (size, HImode)));
- /* Copy to stack pointer. */
- emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
- }
+ emit_insn (fp_plus_insns);
}
- if(!cfun->machine->is_OS_task)
+ if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
{
/* Restore previous frame_pointer. */
emit_insn (gen_pophi (frame_pointer_rtx));
true_regnum (XEXP (x, 0)));
debug_rtx (x);
}
+ if (!strict && GET_CODE (x) == SUBREG)
+ x = SUBREG_REG (x);
if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
: REG_OK_FOR_BASE_NOSTRICT_P (x)))
r = POINTER_REGS;
if (fit)
{
if (! strict
+ || REGNO (XEXP (x,0)) == REG_X
|| REGNO (XEXP (x,0)) == REG_Y
|| REGNO (XEXP (x,0)) == REG_Z)
r = BASE_POINTER_REGS;
class CLASS needed to hold a value of mode MODE. */
int
-class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,enum machine_mode mode)
+class_max_nregs (enum reg_class rclass ATTRIBUTE_UNUSED,enum machine_mode mode)
{
return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
}
fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
INSN_ADDRESSES (uid),
INSN_ADDRESSES (uid) - last_insn_address,
- rtx_cost (PATTERN (insn), INSN));
+ rtx_cost (PATTERN (insn), INSN, !optimize_size));
}
last_insn_address = INSN_ADDRESSES (uid);
}
/* Return 0 if undefined, 1 if always true or always false. */
int
-avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE operator, rtx x)
+avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE op, rtx x)
{
unsigned int max = (mode == QImode ? 0xff :
mode == HImode ? 0xffff :
mode == SImode ? 0xffffffff : 0);
- if (max && operator && GET_CODE (x) == CONST_INT)
+ if (max && op && GET_CODE (x) == CONST_INT)
{
- if (unsigned_condition (operator) != operator)
+ if (unsigned_condition (op) != op)
max >>= 1;
if (max != (INTVAL (x) & max)
}
else if (GET_CODE (dest) == MEM)
{
- const char *template;
+ const char *templ;
if (src == const0_rtx)
operands[1] = zero_reg_rtx;
- template = out_movqi_mr_r (insn, operands, real_l);
+ templ = out_movqi_mr_r (insn, operands, real_l);
if (!real_l)
- output_asm_insn (template, operands);
+ output_asm_insn (templ, operands);
operands[1] = src;
}
if (test_hard_reg_class (STACK_REG, dest))
{
if (TARGET_TINY_STACK)
- {
- *l = 1;
- return AS2 (out,__SP_L__,%A1);
- }
- /* Use simple load of stack pointer if no interrupts are used
- or inside main or signal function prologue where they disabled. */
- else if (TARGET_NO_INTERRUPTS
- || (reload_completed
- && cfun->machine->is_signal
- && prologue_epilogue_contains (insn)))
- {
- *l = 2;
- return (AS2 (out,__SP_H__,%B1) CR_TAB
- AS2 (out,__SP_L__,%A1));
- }
- /* In interrupt prolog we know interrupts are enabled. */
- else if (reload_completed
- && cfun->machine->is_interrupt
- && prologue_epilogue_contains (insn))
- {
- *l = 4;
- return ("cli" CR_TAB
- AS2 (out,__SP_H__,%B1) CR_TAB
- "sei" CR_TAB
- AS2 (out,__SP_L__,%A1));
- }
+ return *l = 1, AS2 (out,__SP_L__,%A1);
+ /* Use simple load of stack pointer if no interrupts are
+ used. */
+ else if (TARGET_NO_INTERRUPTS)
+ return *l = 2, (AS2 (out,__SP_H__,%B1) CR_TAB
+ AS2 (out,__SP_L__,%A1));
*l = 5;
return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
"cli" CR_TAB
}
else if (GET_CODE (dest) == MEM)
{
- const char *template;
+ const char *templ;
if (src == const0_rtx)
operands[1] = zero_reg_rtx;
- template = out_movhi_mr_r (insn, operands, real_l);
+ templ = out_movhi_mr_r (insn, operands, real_l);
if (!real_l)
- output_asm_insn (template, operands);
+ output_asm_insn (templ, operands);
operands[1] = src;
return "";
}
else if (GET_CODE (dest) == MEM)
{
- const char *template;
+ const char *templ;
if (src == const0_rtx)
operands[1] = zero_reg_rtx;
- template = out_movsi_mr_r (insn, operands, real_l);
+ templ = out_movsi_mr_r (insn, operands, real_l);
if (!real_l)
- output_asm_insn (template, operands);
+ output_asm_insn (templ, operands);
operands[1] = src;
return "";
carefully hand-optimized in ?sh??i3_out. */
void
-out_shift_with_cnt (const char *template, rtx insn, rtx operands[],
+out_shift_with_cnt (const char *templ, rtx insn, rtx operands[],
int *len, int t_len)
{
rtx op[10];
else
{
while (count-- > 0)
- output_asm_insn (template, op);
+ output_asm_insn (templ, op);
}
return;
else
{
strcat (str, "\n1:\t");
- strcat (str, template);
+ strcat (str, templ);
strcat (str, second_label ? "\n2:\t" : "\n\t");
strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
strcat (str, CR_TAB);
return default_assemble_integer (x, size, aligned_p);
}
+/* Worker function for ASM_DECLARE_FUNCTION_NAME. */
+
+void
+avr_asm_declare_function_name (FILE *file, const char *name, tree decl)
+{
+
+ /* If the function has the 'signal' or 'interrupt' attribute, test to
+ make sure that the name of the function is "__vector_NN" so as to
+ catch when the user misspells the interrupt vector name. */
+
+ if (cfun->machine->is_interrupt)
+ {
+ if (strncmp (name, "__vector", strlen ("__vector")) != 0)
+ {
+ warning_at (DECL_SOURCE_LOCATION (decl), 0,
+ "%qs appears to be a misspelled interrupt handler",
+ name);
+ }
+ }
+ else if (cfun->machine->is_signal)
+ {
+ if (strncmp (name, "__vector", strlen ("__vector")) != 0)
+ {
+ warning_at (DECL_SOURCE_LOCATION (decl), 0,
+ "%qs appears to be a misspelled signal handler",
+ name);
+ }
+ }
+
+ ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
+ ASM_OUTPUT_LABEL (file, name);
+}
+
/* The routine used to output NUL terminated strings. We use a special
version of this for most svr4 targets because doing so makes the
generated assembly code more compact (and thus faster to assemble)
{ "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
{ "naked", 0, 0, false, true, true, avr_handle_fntype_attribute },
{ "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute },
+ { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
- else
- {
- const char *func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (*node));
- const char *attr = IDENTIFIER_POINTER (name);
-
- /* If the function has the 'signal' or 'interrupt' attribute, test to
- make sure that the name of the function is "__vector_NN" so as to
- catch when the user misspells the interrupt vector name. */
-
- if (strncmp (attr, "interrupt", strlen ("interrupt")) == 0)
- {
- if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
- {
- warning (0, "%qs appears to be a misspelled interrupt handler",
- func_name);
- }
- }
- else if (strncmp (attr, "signal", strlen ("signal")) == 0)
- {
- if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
- {
- warning (0, "%qs appears to be a misspelled signal handler",
- func_name);
- }
- }
- }
return NULL_TREE;
}
static void
avr_file_start (void)
{
- if (avr_asm_only_p)
+ if (avr_current_arch->asm_only)
error ("MCU %qs supported for assembler only", avr_mcu_name);
default_file_start ();
operand's parent operator. */
static int
-avr_operand_rtx_cost (rtx x, enum machine_mode mode, enum rtx_code outer)
+avr_operand_rtx_cost (rtx x, enum machine_mode mode, enum rtx_code outer,
+ bool speed)
{
enum rtx_code code = GET_CODE (x);
int total;
}
total = 0;
- avr_rtx_costs (x, code, outer, &total);
+ avr_rtx_costs (x, code, outer, &total, speed);
return total;
}
case, *TOTAL contains the cost result. */
static bool
-avr_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
+avr_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
+ bool speed)
{
enum machine_mode mode = GET_MODE (x);
HOST_WIDE_INT val;
default:
return false;
}
- *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
return true;
case ABS:
default:
return false;
}
- *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
return true;
case NOT:
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
- *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
return true;
case ZERO_EXTEND:
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
- GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
- *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
return true;
case SIGN_EXTEND:
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
- GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
- *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
return true;
case PLUS:
case QImode:
*total = COSTS_N_INSNS (1);
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
break;
case HImode:
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
{
*total = COSTS_N_INSNS (2);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
*total = COSTS_N_INSNS (1);
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
{
*total = COSTS_N_INSNS (4);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
*total = COSTS_N_INSNS (1);
default:
return false;
}
- *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
return true;
case MINUS:
case AND:
case IOR:
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
- *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
return true;
case XOR:
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
- *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
return true;
case MULT:
{
case QImode:
if (AVR_HAVE_MUL)
- *total = COSTS_N_INSNS (optimize_size ? 3 : 4);
- else if (optimize_size)
+ *total = COSTS_N_INSNS (!speed ? 3 : 4);
+ else if (!speed)
*total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
else
return false;
case HImode:
if (AVR_HAVE_MUL)
- *total = COSTS_N_INSNS (optimize_size ? 7 : 10);
- else if (optimize_size)
+ *total = COSTS_N_INSNS (!speed ? 7 : 10);
+ else if (!speed)
*total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
else
return false;
default:
return false;
}
- *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
return true;
case DIV:
case MOD:
case UDIV:
case UMOD:
- if (optimize_size)
+ if (!speed)
*total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
else
return false;
- *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
return true;
+ case ROTATE:
+ switch (mode)
+ {
+ case QImode:
+ if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
+ *total = COSTS_N_INSNS (1);
+
+ break;
+
+ case HImode:
+ if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
+ *total = COSTS_N_INSNS (3);
+
+ break;
+
+ case SImode:
+ if (CONST_INT_P (XEXP (x, 1)))
+ switch (INTVAL (XEXP (x, 1)))
+ {
+ case 8:
+ case 24:
+ *total = COSTS_N_INSNS (5);
+ break;
+ case 16:
+ *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
+ break;
+ }
+ break;
+
+ default:
+ return false;
+ }
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
+ return true;
+
case ASHIFT:
switch (mode)
{
case QImode:
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
{
- *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 4 : 17);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
else
{
case HImode:
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
{
- *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 5 : 41);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
else
switch (INTVAL (XEXP (x, 1)))
*total = COSTS_N_INSNS (5);
break;
case 4:
- *total = COSTS_N_INSNS (optimize_size ? 5 : 8);
+ *total = COSTS_N_INSNS (!speed ? 5 : 8);
break;
case 6:
- *total = COSTS_N_INSNS (optimize_size ? 5 : 9);
+ *total = COSTS_N_INSNS (!speed ? 5 : 9);
break;
case 5:
- *total = COSTS_N_INSNS (optimize_size ? 5 : 10);
+ *total = COSTS_N_INSNS (!speed ? 5 : 10);
break;
default:
- *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 5 : 41);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
break;
case SImode:
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
{
- *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 7 : 113);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
else
switch (INTVAL (XEXP (x, 1)))
*total = COSTS_N_INSNS (6);
break;
case 2:
- *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
+ *total = COSTS_N_INSNS (!speed ? 7 : 8);
break;
default:
- *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 7 : 113);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
break;
default:
return false;
}
- *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
return true;
case ASHIFTRT:
case QImode:
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
{
- *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 4 : 17);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
else
{
case HImode:
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
{
- *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 5 : 41);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
else
switch (INTVAL (XEXP (x, 1)))
*total = COSTS_N_INSNS (5);
break;
case 11:
- *total = COSTS_N_INSNS (optimize_size ? 5 : 6);
+ *total = COSTS_N_INSNS (!speed ? 5 : 6);
break;
case 12:
- *total = COSTS_N_INSNS (optimize_size ? 5 : 7);
+ *total = COSTS_N_INSNS (!speed ? 5 : 7);
break;
case 6:
case 13:
- *total = COSTS_N_INSNS (optimize_size ? 5 : 8);
+ *total = COSTS_N_INSNS (!speed ? 5 : 8);
break;
default:
- *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 5 : 41);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
break;
case SImode:
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
{
- *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 7 : 113);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
else
switch (INTVAL (XEXP (x, 1)))
*total = COSTS_N_INSNS (6);
break;
case 2:
- *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
+ *total = COSTS_N_INSNS (!speed ? 7 : 8);
break;
case 31:
*total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
break;
default:
- *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 7 : 113);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
break;
default:
return false;
}
- *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
return true;
case LSHIFTRT:
case QImode:
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
{
- *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 4 : 17);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
else
{
case HImode:
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
{
- *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 5 : 41);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
else
switch (INTVAL (XEXP (x, 1)))
case 12:
case 13:
case 14:
- *total = COSTS_N_INSNS (optimize_size ? 5 : 6);
+ *total = COSTS_N_INSNS (!speed ? 5 : 6);
break;
case 4:
- *total = COSTS_N_INSNS (optimize_size ? 5 : 7);
+ *total = COSTS_N_INSNS (!speed ? 5 : 7);
break;
case 5:
case 6:
- *total = COSTS_N_INSNS (optimize_size ? 5 : 9);
+ *total = COSTS_N_INSNS (!speed ? 5 : 9);
break;
default:
- *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 5 : 41);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
break;
case SImode:
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
{
- *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 7 : 113);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
else
switch (INTVAL (XEXP (x, 1)))
*total = COSTS_N_INSNS (4);
break;
case 2:
- *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
+ *total = COSTS_N_INSNS (!speed ? 7 : 8);
break;
case 8:
case 16:
*total = COSTS_N_INSNS (6);
break;
default:
- *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total = COSTS_N_INSNS (!speed ? 7 : 113);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
}
break;
default:
return false;
}
- *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
return true;
case COMPARE:
case QImode:
*total = COSTS_N_INSNS (1);
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
break;
case HImode:
*total = COSTS_N_INSNS (2);
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
else if (INTVAL (XEXP (x, 1)) != 0)
*total += COSTS_N_INSNS (1);
break;
case SImode:
*total = COSTS_N_INSNS (4);
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, speed);
else if (INTVAL (XEXP (x, 1)) != 0)
*total += COSTS_N_INSNS (3);
break;
default:
return false;
}
- *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+ *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
return true;
default:
/* Calculate the cost of a memory address. */
static int
-avr_address_cost (rtx x)
+avr_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED)
{
if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x,1)) == CONST_INT
rtx t = XEXP (src,0);
PUT_CODE (t, swap_condition (GET_CODE (t)));
- SET_SRC (pattern) = gen_rtx_NEG (GET_MODE (SET_SRC (pattern)),
+ SET_SRC (pattern) = gen_rtx_COMPARE (GET_MODE (SET_SRC (pattern)), const0_rtx,
SET_SRC (pattern));
INSN_CODE (next) = -1;
INSN_CODE (insn) = -1;
function returns a value of data type VALTYPE. */
rtx
-avr_function_value (const_tree type, const_tree func ATTRIBUTE_UNUSED)
+avr_function_value (const_tree type,
+ const_tree func ATTRIBUTE_UNUSED,
+ bool outgoing ATTRIBUTE_UNUSED)
{
unsigned int offs;
in class CLASS. */
enum reg_class
-preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class class)
+preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class rclass)
{
- return class;
+ return rclass;
}
int
-test_hard_reg_class (enum reg_class class, rtx x)
+test_hard_reg_class (enum reg_class rclass, rtx x)
{
int regno = true_regnum (x);
if (regno < 0)
return 0;
- if (TEST_HARD_REG_CLASS (class, regno))
+ if (TEST_HARD_REG_CLASS (rclass, regno))
return 1;
return 0;
fprintf (stream, "\trjmp .L%d\n", value);
}
-/* Returns 1 if SCRATCH are safe to be allocated as a scratch
+/* Returns true if SCRATCH are safe to be allocated as a scratch
registers (for a define_peephole2) in the current function. */
+bool
+avr_hard_regno_scratch_ok (unsigned int regno)
+{
+ /* Interrupt functions can only use registers that have already been saved
+ by the prologue, even if they would normally be call-clobbered. */
+
+ if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
+ && !df_regs_ever_live_p (regno))
+ return false;
+
+ return true;
+}
+
+/* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
+
int
-avr_peep2_scratch_safe (rtx scratch)
+avr_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
+ unsigned int new_reg)
{
- if ((interrupt_function_p (current_function_decl)
- || signal_function_p (current_function_decl))
- && leaf_function_p ())
- {
- int first_reg = true_regnum (scratch);
- int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
- int reg;
+ /* Interrupt functions can only use registers that have already been
+ saved by the prologue, even if they would normally be
+ call-clobbered. */
+
+ if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
+ && !df_regs_ever_live_p (new_reg))
+ return 0;
- for (reg = first_reg; reg <= last_reg; reg++)
- {
- if (!df_regs_ever_live_p (reg))
- return 0;
- }
- }
return 1;
}