/* Return true if register FROM can be eliminated via register TO. */
static bool
-avr_can_eliminate (int from ATTRIBUTE_UNUSED, int to)
+avr_can_eliminate (const int from, const int to)
{
- return to == HARD_FRAME_POINTER_REGNUM;
+ return ((from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
+ || (frame_pointer_needed && to == FRAME_POINTER_REGNUM)
+ || ((from == FRAME_POINTER_REGNUM
+ || from == FRAME_POINTER_REGNUM + 1)
+ && !frame_pointer_needed));
}
/* Compute offset between arg_pointer and frame_pointer. */
int
-avr_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
+avr_initial_elimination_offset (int from, int to)
{
- int offset = 0;
-
- if (from == ARG_POINTER_REGNUM)
+ if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
+ return 0;
+ else
{
- offset += AVR_HAVE_EIJMP_EICALL ? 3 : 2;
- offset += frame_pointer_needed ? 2 : 0;
+ int offset = frame_pointer_needed ? 2 : 0;
+ int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
+
offset += avr_regs_to_save (NULL);
- offset += get_frame_size ();
- offset += 1; /* post-dec stack space */
+ return (get_frame_size () + avr_outgoing_args_size()
+ + avr_pc_size + 1 + offset);
}
-
- return offset;
}
/* Actual start of frame is virtual_stack_vars_rtx this is offset from
notes to the front. Thus we build them in the reverse order of
how we want dwarf2out to process them. */
- /* The function does always set hard_frame_pointer_rtx, but whether that
+ /* The function does always set frame_pointer_rtx, but whether that
is going to be permanent in the function is frame_pointer_needed. */
add_reg_note (insn, REG_CFA_ADJUST_CFA,
gen_rtx_SET (VOIDmode, (frame_pointer_needed
- ? hard_frame_pointer_rtx
+ ? frame_pointer_rtx
: stack_pointer_rtx),
plus_constant (stack_pointer_rtx,
-(size + live_seq))));
if (frame_pointer_needed
&& size == 0)
{
- insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
+ insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
}
|| !current_function_is_leaf);
fp = my_fp = (frame_pointer_needed
- ? hard_frame_pointer_rtx
+ ? frame_pointer_rtx
: gen_rtx_REG (Pmode, REG_X));
if (AVR_HAVE_8BIT_SP)
/* The high byte (r29) does not change:
Prefer SUBI (1 cycle) over ABIW (2 cycles, same size). */
- my_fp = all_regs_rtx[HARD_FRAME_POINTER_REGNUM];
+ my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
}
/************ Method 1: Adjust frame pointer ************/
if (!frame_pointer_needed)
{
- emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
+ emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
}
if (size)
{
- emit_move_insn (hard_frame_pointer_rtx,
- plus_constant (hard_frame_pointer_rtx, size));
+ emit_move_insn (frame_pointer_rtx,
+ plus_constant (frame_pointer_rtx, size));
}
emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
|| !current_function_is_leaf);
fp = my_fp = (frame_pointer_needed
- ? hard_frame_pointer_rtx
+ ? frame_pointer_rtx
: gen_rtx_REG (Pmode, REG_X));
if (AVR_HAVE_8BIT_SP)
/* The high byte (r29) does not change:
Prefer SUBI (1 cycle) over SBIW (2 cycles). */
- my_fp = all_regs_rtx[HARD_FRAME_POINTER_REGNUM];
+ my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
}
/********** Method 1: Adjust fp register **********/
memory address for an operand of mode MODE */
static rtx
-avr_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode)
+avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
{
+ bool big_offset_p = false;
+
+ x = oldx;
+
+ if (GET_CODE (oldx) == PLUS
+ && REG_P (XEXP (oldx, 0)))
+ {
+ if (REG_P (XEXP (oldx, 1)))
+ x = force_reg (GET_MODE (oldx), oldx);
+ else if (CONST_INT_P (XEXP (oldx, 1)))
+ {
+ int offs = INTVAL (XEXP (oldx, 1));
+ if (frame_pointer_rtx != XEXP (oldx, 0)
+ && offs > MAX_LD_OFFSET (mode))
+ {
+ big_offset_p = true;
+ x = force_reg (GET_MODE (oldx), oldx);
+ }
+ }
+ }
+
+ if (avr_log.legitimize_address)
+ {
+ avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
+
+ if (x != oldx)
+ avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
+ }
+
return x;
}
}
}
else if (! (frame_pointer_needed
- && XEXP (x, 0) == hard_frame_pointer_rtx))
+ && XEXP (x, 0) == frame_pointer_rtx))
{
push_reload (x, NULL_RTX, px, NULL,
POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
return ok;
}
-/* Returns the number of registers required to hold a value of MODE. */
-
-int
-avr_hard_regno_nregs (int regno, enum machine_mode mode)
-{
- /* The fake registers are designed to hold exactly a pointer. */
- if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM)
- return 1;
-
- return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
-}
-
-
/* Convert condition code CONDITION to the valid AVR condition code. */
RTX_CODE
int
avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
{
- /* The fake registers are designed to hold exactly a pointer. */
- if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM)
- return mode == Pmode;
-
/* NOTE: 8-bit values must not be disallowed for R28 or R29.
Disallowing QI et al. in these regs might lead to code like
(set (subreg:QI (reg:HI 28) n) ...)
return 0;
/* All modes larger than 8 bits should start in an even register. */
+
return !(regno & 1);
}
&& (regno == REG_X
|| regno == REG_Y
|| regno == REG_Z
- || regno == ARG_POINTER_REGNUM
- || regno == FRAME_POINTER_REGNUM))
+ || regno == ARG_POINTER_REGNUM))
{
ok = true;
}
if (regno == REG_X
|| regno == REG_Y
|| regno == REG_Z
- || regno == ARG_POINTER_REGNUM
- || regno == FRAME_POINTER_REGNUM)
+ || regno == ARG_POINTER_REGNUM)
{
ok = true;
}
#define FIRST_PSEUDO_REGISTER 36
-#define FIXED_REGISTERS { \
- 1,1,/* r0 r1 */ \
- 0,0,/* r2 r3 */ \
- 0,0,/* r4 r5 */ \
- 0,0,/* r6 r7 */ \
- 0,0,/* r8 r9 */ \
- 0,0,/* r10 r11 */ \
- 0,0,/* r12 r13 */ \
- 0,0,/* r14 r15 */ \
- 0,0,/* r16 r17 */ \
- 0,0,/* r18 r19 */ \
- 0,0,/* r20 r21 */ \
- 0,0,/* r22 r23 */ \
- 0,0,/* r24 r25 */ \
- 0,0,/* r26 r27 */ \
- 0,0,/* r28 r29 */ \
- 0,0,/* r30 r31 */ \
- 1,1,/* STACK */ \
- 1, /* arg pointer */ \
- 1 /* frame pointer */ }
+#define FIXED_REGISTERS {\
+ 1,1,/* r0 r1 */\
+ 0,0,/* r2 r3 */\
+ 0,0,/* r4 r5 */\
+ 0,0,/* r6 r7 */\
+ 0,0,/* r8 r9 */\
+ 0,0,/* r10 r11 */\
+ 0,0,/* r12 r13 */\
+ 0,0,/* r14 r15 */\
+ 0,0,/* r16 r17 */\
+ 0,0,/* r18 r19 */\
+ 0,0,/* r20 r21 */\
+ 0,0,/* r22 r23 */\
+ 0,0,/* r24 r25 */\
+ 0,0,/* r26 r27 */\
+ 0,0,/* r28 r29 */\
+ 0,0,/* r30 r31 */\
+ 1,1,/* STACK */\
+ 1,1 /* arg pointer */ }
#define CALL_USED_REGISTERS { \
1,1,/* r0 r1 */ \
- 0,0,/* r2 r3 */ \
- 0,0,/* r4 r5 */ \
- 0,0,/* r6 r7 */ \
- 0,0,/* r8 r9 */ \
- 0,0,/* r10 r11 */ \
- 0,0,/* r12 r13 */ \
- 0,0,/* r14 r15 */ \
- 0,0,/* r16 r17 */ \
- 1,1,/* r18 r19 */ \
- 1,1,/* r20 r21 */ \
- 1,1,/* r22 r23 */ \
- 1,1,/* r24 r25 */ \
- 1,1,/* r26 r27 */ \
- 0,0,/* r28 r29 */ \
- 1,1,/* r30 r31 */ \
- 1,1,/* STACK */ \
- 1, /* arg pointer */ \
- 1 /* frame pointer */ }
+ 0,0,/* r2 r3 */ \
+ 0,0,/* r4 r5 */ \
+ 0,0,/* r6 r7 */ \
+ 0,0,/* r8 r9 */ \
+ 0,0,/* r10 r11 */ \
+ 0,0,/* r12 r13 */ \
+ 0,0,/* r14 r15 */ \
+ 0,0,/* r16 r17 */ \
+ 1,1,/* r18 r19 */ \
+ 1,1,/* r20 r21 */ \
+ 1,1,/* r22 r23 */ \
+ 1,1,/* r24 r25 */ \
+ 1,1,/* r26 r27 */ \
+ 0,0,/* r28 r29 */ \
+ 1,1,/* r30 r31 */ \
+ 1,1,/* STACK */ \
+ 1,1 /* arg pointer */ }
#define REG_ALLOC_ORDER { \
24,25, \
#define ADJUST_REG_ALLOC_ORDER order_regs_for_local_alloc ()
-#define HARD_REGNO_NREGS(REGNO, MODE) avr_hard_regno_nregs(REGNO, MODE)
+#define HARD_REGNO_NREGS(REGNO, MODE) ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
#define HARD_REGNO_MODE_OK(REGNO, MODE) avr_hard_regno_mode_ok(REGNO, MODE)
{3 << REG_Z,0x00000000}, /* POINTER_Z_REGS, r30 - r31 */ \
{0x00000000,0x00000003}, /* STACK_REG, STACK */ \
{(3 << REG_Y) | (3 << REG_Z), \
- 0x0000000c}, /* BASE_POINTER_REGS, r28 - r31,ap,fp */ \
+ 0x00000000}, /* BASE_POINTER_REGS, r28 - r31 */ \
{(3 << REG_X) | (3 << REG_Y) | (3 << REG_Z), \
- 0x0000000c}, /* POINTER_REGS, r26 - r31 */ \
+ 0x00000000}, /* POINTER_REGS, r26 - r31 */ \
{(3 << REG_X) | (3 << REG_Y) | (3 << REG_Z) | (3 << REG_W), \
0x00000000}, /* ADDW_REGS, r24 - r31 */ \
{0x00ff0000,0x00000000}, /* SIMPLE_LD_REGS r16 - r23 */ \
{(3 << REG_X)|(3 << REG_Y)|(3 << REG_Z)|(3 << REG_W)|(0xff << 16), \
- 0x0000000c}, /* LD_REGS, r16 - r31 */ \
+ 0x00000000}, /* LD_REGS, r16 - r31 */ \
{0x0000ffff,0x00000000}, /* NO_LD_REGS r0 - r15 */ \
- {0xffffffff,0x0000000c}, /* GENERAL_REGS, r0 - r31 */ \
- {0xffffffff,0x0000000f} /* ALL_REGS */ \
+ {0xffffffff,0x00000000}, /* GENERAL_REGS, r0 - r31 */ \
+ {0xffffffff,0x00000003} /* ALL_REGS */ \
}
#define REGNO_REG_CLASS(R) avr_regno_reg_class(R)
#define STACK_POINTER_REGNUM 32
-#define HARD_FRAME_POINTER_REGNUM REG_Y
+#define FRAME_POINTER_REGNUM REG_Y
#define ARG_POINTER_REGNUM 34
-#define FRAME_POINTER_REGNUM 35
#define STATIC_CHAIN_REGNUM 2
#define ELIMINABLE_REGS { \
- { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
- { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \
- { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
- { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }}
+ {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
+ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM} \
+ ,{FRAME_POINTER_REGNUM+1,STACK_POINTER_REGNUM+1}}
-#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
OFFSET = avr_initial_elimination_offset (FROM, TO)
#define RETURN_ADDR_RTX(count, tem) avr_return_addr_rtx (count, tem)
"r8","r9","r10","r11","r12","r13","r14","r15", \
"r16","r17","r18","r19","r20","r21","r22","r23", \
"r24","r25","r26","r27","r28","r29","r30","r31", \
- "__SP_L__","__SP_H__","ap","fp"}
+ "__SP_L__","__SP_H__","argL","argH"}
#define FINAL_PRESCAN_INSN(insn, operand, nop) final_prescan_insn (insn, operand,nop)