2004-01-28 Kazu Hirata <kazu@cs.umass.edu>
+ * config/h8300/h8300.c (WORD_REG_USED): Use
+ HARD_FRAME_POINTER_REGNUM instead of FRAME_POINTER_REGNUM.
+ (compute_saved_regs): Likewise.
+ (h8300_expand_prologue): Likewise. Allocate locals after
+ saving registers.
+ (h8300_expand_epilogue): Use HARD_FRAME_POINTER_REGNUM instead
+ of FRAME_POINTER_REGNUM. Deallocate locals before saving
+ registers.
+ (h8300_initial_elimination_offset): Adjust for the new frame
+ layout, which swaps flips the order of locals and saved
+ registers.
+ * config/h8300/h8300.h (FIRST_PSEUDO_REGISTER): Change to 12.
+ (HARD_FRAME_POINTER_REGNUM): New.
+ (ELIMINABLE_REGS): Add an elimination rule from
+ FRAME_POINTER_REGNUM to HARD_FRAME_POINTER_REGNUM.
+ (REGISTER_NAMES): Add fp.
+ * config/h8300/h8300.md (FP_REG): Change to 11.
+ (HFP_REG): New.
+
+2004-01-28 Kazu Hirata <kazu@cs.umass.edu>
+
* genrecog.c (write_node): Remove a useless local variable.
2004-01-28 Ian Lance Taylor <ian@wasabisystems.com>
/* Save any call saved register that was used. */ \
|| (regs_ever_live[regno] && !call_used_regs[regno]) \
/* Save the frame pointer if it was used. */ \
- || (regno == FRAME_POINTER_REGNUM && regs_ever_live[regno]) \
+ || (regno == HARD_FRAME_POINTER_REGNUM && regs_ever_live[regno]) \
/* Save any register used in an interrupt handler. */ \
|| (h8300_current_function_interrupt_function_p () \
&& regs_ever_live[regno]) \
int regno;
/* Construct a bit vector of registers to be pushed/popped. */
- for (regno = 0; regno <= FRAME_POINTER_REGNUM; regno++)
+ for (regno = 0; regno <= HARD_FRAME_POINTER_REGNUM; regno++)
{
if (WORD_REG_USED (regno))
saved_regs |= 1 << regno;
/* Don't push/pop the frame pointer as it is treated separately. */
if (frame_pointer_needed)
- saved_regs &= ~(1 << FRAME_POINTER_REGNUM);
+ saved_regs &= ~(1 << HARD_FRAME_POINTER_REGNUM);
return saved_regs;
}
if (frame_pointer_needed)
{
/* Push fp. */
- push (FRAME_POINTER_REGNUM);
- emit_insn (gen_rtx_SET (Pmode, frame_pointer_rtx, stack_pointer_rtx));
+ push (HARD_FRAME_POINTER_REGNUM);
+ emit_insn (gen_rtx_SET (Pmode, hard_frame_pointer_rtx,
+ stack_pointer_rtx));
}
- /* Leave room for locals. */
- h8300_emit_stack_adjustment (-1, round_frame_size (get_frame_size ()));
-
/* Push the rest of the registers in ascending order. */
saved_regs = compute_saved_regs ();
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno += n_regs)
}
}
}
+
+ /* Leave room for locals. */
+ h8300_emit_stack_adjustment (-1, round_frame_size (get_frame_size ()));
}
int
rts instruction. */
return;
+ /* Deallocate locals. */
+ h8300_emit_stack_adjustment (1, round_frame_size (get_frame_size ()));
+
/* Pop the saved registers in descending order. */
saved_regs = compute_saved_regs ();
for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno -= n_regs)
}
}
- /* Deallocate locals. */
- h8300_emit_stack_adjustment (1, round_frame_size (get_frame_size ()));
-
/* Pop frame pointer if we had one. */
if (frame_pointer_needed)
- pop (FRAME_POINTER_REGNUM);
+ pop (HARD_FRAME_POINTER_REGNUM);
}
/* Return nonzero if the current function is an interrupt
int
h8300_initial_elimination_offset (int from, int to)
{
- int offset = 0;
/* The number of bytes that the return address takes on the stack. */
int pc_size = POINTER_SIZE / BITS_PER_UNIT;
- if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
- offset = pc_size + frame_pointer_needed * UNITS_PER_WORD;
- else if (from == RETURN_ADDRESS_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
- offset = frame_pointer_needed * UNITS_PER_WORD;
- else
- {
- int regno;
+ /* The number of bytes that the saved frame pointer takes on the stack. */
+ int fp_size = frame_pointer_needed * UNITS_PER_WORD;
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- if (WORD_REG_USED (regno))
- offset += UNITS_PER_WORD;
+ /* The number of bytes that the saved registers, excluding the frame
+ pointer, take on the stack. */
+ int saved_regs_size = 0;
- /* See the comments for get_frame_size. We need to round it up to
- STACK_BOUNDARY. */
+ /* The number of bytes that the locals takes on the stack. */
+ int frame_size = round_frame_size (get_frame_size ());
- offset += round_frame_size (get_frame_size ());
+ int regno;
- if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
- /* Skip saved PC. */
- offset += pc_size;
- }
+ for (regno = 0; regno <= HARD_FRAME_POINTER_REGNUM; regno++)
+ if (WORD_REG_USED (regno))
+ saved_regs_size += UNITS_PER_WORD;
- return offset;
+ /* Adjust saved_regs_size because the above loop took the frame
+ pointer int account. */
+ saved_regs_size -= fp_size;
+
+ if (to == HARD_FRAME_POINTER_REGNUM)
+ {
+ switch (from)
+ {
+ case ARG_POINTER_REGNUM:
+ return pc_size + fp_size;
+ case RETURN_ADDRESS_POINTER_REGNUM:
+ return fp_size;
+ case FRAME_POINTER_REGNUM:
+ return -saved_regs_size;
+ default:
+ abort ();
+ }
+ }
+ else if (to == STACK_POINTER_REGNUM)
+ {
+ switch (from)
+ {
+ case ARG_POINTER_REGNUM:
+ return pc_size + saved_regs_size + frame_size;
+ case RETURN_ADDRESS_POINTER_REGNUM:
+ return saved_regs_size + frame_size;
+ case FRAME_POINTER_REGNUM:
+ return frame_size;
+ default:
+ abort ();
+ }
+ }
+ else
+ abort ();
}
rtx
eliminated during reloading in favor of either the stack or frame
pointer. */
-#define FIRST_PSEUDO_REGISTER 11
+#define FIRST_PSEUDO_REGISTER 12
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator. */
#define STACK_POINTER_REGNUM SP_REG
/* Base register for access to local variables of the function. */
+#define HARD_FRAME_POINTER_REGNUM HFP_REG
+
+/* Base register for access to local variables of the function. */
#define FRAME_POINTER_REGNUM FP_REG
/* Value should be nonzero if functions must have frame pointers.
eliminated; they are replaced with either the stack or frame
pointer. */
-#define ELIMINABLE_REGS \
-{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
- { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM},\
- { RETURN_ADDRESS_POINTER_REGNUM, FRAME_POINTER_REGNUM},\
- { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
+#define ELIMINABLE_REGS \
+{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
+ { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
/* Given FROM and TO register numbers, say whether this elimination is allowed.
Frame pointer elimination is automatically handled.
This sequence is indexed by compiler's hard-register-number (see above). */
#define REGISTER_NAMES \
-{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "sp", "mac", "ap", "rap" }
+{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "sp", "mac", "ap", "rap", "fp" }
#define ADDITIONAL_REGISTER_NAMES \
{ {"er0", 0}, {"er1", 1}, {"er2", 2}, {"er3", 3}, {"er4", 4}, \