Commit b2471838 by Richard Sandiford Committed by Richard Sandiford

mips-protos.h (mips_initial_elimination_offset): Declare.

	* config/mips/mips-protos.h (mips_initial_elimination_offset): Declare.
	(mips_set_return_address, mips_restore_gp): Declare.
	* config/mips/mips.h (struct mips_frame_info): Move to mips.c
	(current_frame_info): Remove.
	(INITIAL_ELIMINATION_OFFSET): Use mips_initial_elimination_offset.
	* config/mips/mips.c: Remove uses of current_frame_info.
	(struct mips_frame_info): Moved from mips.h.  Remove 'insns_len'.
	(struct machine_function): Add 'frame' and 'insns_len'.
	(current_frame_info, zero_frame_info): Remove.
	(mips_restore_gp, mips_set_return_address): New.
	(mips_initial_elimination_offset): New.
	* config/mips/mips.md (exception_receiver): Use mips_restore_gp.
	(eh_return define_split): Use mips_set_return_address.

From-SVN: r54738
parent d3beaf0a
2002-06-18 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips-protos.h (mips_initial_elimination_offset): Declare.
(mips_set_return_address, mips_restore_gp): Declare.
* config/mips/mips.h (struct mips_frame_info): Move to mips.c
(current_frame_info): Remove.
(INITIAL_ELIMINATION_OFFSET): Use mips_initial_elimination_offset.
* config/mips/mips.c: Remove uses of current_frame_info.
(struct mips_frame_info): Moved from mips.h. Remove 'insns_len'.
(struct machine_function): Add 'frame' and 'insns_len'.
(current_frame_info, zero_frame_info): Remove.
(mips_restore_gp, mips_set_return_address): New.
(mips_initial_elimination_offset): New.
* config/mips/mips.md (exception_receiver): Use mips_restore_gp.
(eh_return define_split): Use mips_set_return_address.
2002-06-18 Neil Booth <neil@daikokuya.demon.co.uk> 2002-06-18 Neil Booth <neil@daikokuya.demon.co.uk>
* cpplib.c (dtable): Update. * cpplib.c (dtable): Update.
......
...@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */
#define GCC_MIPS_PROTOS_H #define GCC_MIPS_PROTOS_H
extern HOST_WIDE_INT compute_frame_size PARAMS ((HOST_WIDE_INT)); extern HOST_WIDE_INT compute_frame_size PARAMS ((HOST_WIDE_INT));
extern int mips_initial_elimination_offset PARAMS ((int, int));
extern void mips_asm_file_end PARAMS ((FILE *)); extern void mips_asm_file_end PARAMS ((FILE *));
extern void mips_asm_file_start PARAMS ((FILE *)); extern void mips_asm_file_start PARAMS ((FILE *));
extern void iris6_asm_file_start PARAMS ((FILE *)); extern void iris6_asm_file_start PARAMS ((FILE *));
...@@ -86,6 +87,7 @@ extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, ...@@ -86,6 +87,7 @@ extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *,
tree, rtx)); tree, rtx));
extern void gen_conditional_move PARAMS ((rtx *)); extern void gen_conditional_move PARAMS ((rtx *));
extern void mips_gen_conditional_trap PARAMS ((rtx *)); extern void mips_gen_conditional_trap PARAMS ((rtx *));
extern void mips_set_return_address PARAMS ((rtx, rtx));
extern void machine_dependent_reorg PARAMS ((rtx)); extern void machine_dependent_reorg PARAMS ((rtx));
extern int mips_address_cost PARAMS ((rtx)); extern int mips_address_cost PARAMS ((rtx));
extern void mips_count_memory_refs PARAMS ((rtx, int)); extern void mips_count_memory_refs PARAMS ((rtx, int));
...@@ -96,6 +98,7 @@ extern const char *mips_fill_delay_slot PARAMS ((const char *, ...@@ -96,6 +98,7 @@ extern const char *mips_fill_delay_slot PARAMS ((const char *,
rtx)); rtx));
extern const char *mips_move_1word PARAMS ((rtx *, rtx, int)); extern const char *mips_move_1word PARAMS ((rtx *, rtx, int));
extern const char *mips_move_2words PARAMS ((rtx *, rtx)); extern const char *mips_move_2words PARAMS ((rtx *, rtx));
extern const char *mips_restore_gp PARAMS ((rtx *, rtx));
extern const char *output_block_move PARAMS ((rtx, rtx *, int, extern const char *output_block_move PARAMS ((rtx, rtx *, int,
enum block_move_type)); enum block_move_type));
extern void override_options PARAMS ((void)); extern void override_options PARAMS ((void));
......
...@@ -147,6 +147,28 @@ static void mips_select_rtx_section PARAMS ((enum machine_mode, rtx, ...@@ -147,6 +147,28 @@ static void mips_select_rtx_section PARAMS ((enum machine_mode, rtx,
unsigned HOST_WIDE_INT)); unsigned HOST_WIDE_INT));
static void mips_encode_section_info PARAMS ((tree, int)); static void mips_encode_section_info PARAMS ((tree, int));
/* Structure to be filled in by compute_frame_size with register
save masks, and offsets for the current function. */
struct mips_frame_info GTY(())
{
long total_size; /* # bytes that the entire frame takes up */
long var_size; /* # bytes that variables take up */
long args_size; /* # bytes that outgoing arguments take up */
long extra_size; /* # bytes of extra gunk */
int gp_reg_size; /* # bytes needed to store gp regs */
int fp_reg_size; /* # bytes needed to store fp regs */
long mask; /* mask of saved gp registers */
long fmask; /* mask of saved fp registers */
long gp_save_offset; /* offset from vfp to store gp registers */
long fp_save_offset; /* offset from vfp to store fp registers */
long gp_sp_offset; /* offset from new sp to store gp registers */
long fp_sp_offset; /* offset from new sp to store fp registers */
int initialized; /* != 0 if frame size already calculated */
int num_gp; /* number of gp registers saved */
int num_fp; /* number of fp registers saved */
};
struct machine_function GTY(()) { struct machine_function GTY(()) {
/* Pseudo-reg holding the address of the current function when /* Pseudo-reg holding the address of the current function when
generating embedded PIC code. Created by LEGITIMIZE_ADDRESS, generating embedded PIC code. Created by LEGITIMIZE_ADDRESS,
...@@ -156,6 +178,12 @@ struct machine_function GTY(()) { ...@@ -156,6 +178,12 @@ struct machine_function GTY(()) {
/* Pseudo-reg holding the value of $28 in a mips16 function which /* Pseudo-reg holding the value of $28 in a mips16 function which
refers to GP relative global variables. */ refers to GP relative global variables. */
rtx mips16_gp_pseudo_rtx; rtx mips16_gp_pseudo_rtx;
/* Current frame information, calculated by compute_frame_size. */
struct mips_frame_info frame;
/* Length of instructions in function; mips16 only. */
long insns_len;
}; };
/* Information about a single argument. */ /* Information about a single argument. */
...@@ -335,12 +363,6 @@ static enum machine_mode gpr_mode; ...@@ -335,12 +363,6 @@ static enum machine_mode gpr_mode;
can support a given mode. */ can support a given mode. */
char mips_hard_regno_mode_ok[(int)MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER]; char mips_hard_regno_mode_ok[(int)MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
/* Current frame information calculated by compute_frame_size. */
struct mips_frame_info current_frame_info;
/* Zero structure to initialize current_frame_info. */
struct mips_frame_info zero_frame_info;
/* The length of all strings seen when compiling for the mips16. This /* The length of all strings seen when compiling for the mips16. This
is used to tell how many strings are in the constant pool, so that is used to tell how many strings are in the constant pool, so that
we can see if we may have an overflow. This is reset each time the we can see if we may have an overflow. This is reset each time the
...@@ -929,18 +951,18 @@ simple_memory_operand (op, mode) ...@@ -929,18 +951,18 @@ simple_memory_operand (op, mode)
getting this right is during delayed branch scheduling, so getting this right is during delayed branch scheduling, so
don't need to check until then. The machine_dependent_reorg don't need to check until then. The machine_dependent_reorg
function will set the total length of the instructions used function will set the total length of the instructions used
in the function in current_frame_info. If that is small in the function (cfun->machine->insns_len). If that is small
enough, we know for sure that this is a small offset. It enough, we know for sure that this is a small offset. It
would be better if we could take into account the location of would be better if we could take into account the location of
the instruction within the function, but we can't, because we the instruction within the function, but we can't, because we
don't know where we are. */ don't know where we are. */
if (TARGET_MIPS16 if (TARGET_MIPS16
&& CONSTANT_POOL_ADDRESS_P (addr) && CONSTANT_POOL_ADDRESS_P (addr)
&& current_frame_info.insns_len > 0) && cfun->machine->insns_len > 0)
{ {
long size; long size;
size = current_frame_info.insns_len + get_pool_size (); size = cfun->machine->insns_len + get_pool_size ();
if (GET_MODE_SIZE (mode) == 4) if (GET_MODE_SIZE (mode) == 4)
return size < 4 * 0x100; return size < 4 * 0x100;
else if (GET_MODE_SIZE (mode) == 8) else if (GET_MODE_SIZE (mode) == 8)
...@@ -1695,11 +1717,11 @@ m16_usym8_4 (op, mode) ...@@ -1695,11 +1717,11 @@ m16_usym8_4 (op, mode)
{ {
if (GET_CODE (op) == SYMBOL_REF if (GET_CODE (op) == SYMBOL_REF
&& SYMBOL_REF_FLAG (op) && SYMBOL_REF_FLAG (op)
&& current_frame_info.insns_len > 0 && cfun->machine->insns_len > 0
&& XSTR (op, 0)[0] == '*' && XSTR (op, 0)[0] == '*'
&& strncmp (XSTR (op, 0) + 1, LOCAL_LABEL_PREFIX, && strncmp (XSTR (op, 0) + 1, LOCAL_LABEL_PREFIX,
sizeof LOCAL_LABEL_PREFIX - 1) == 0 sizeof LOCAL_LABEL_PREFIX - 1) == 0
&& (current_frame_info.insns_len + get_pool_size () + mips_string_length && (cfun->machine->insns_len + get_pool_size () + mips_string_length
< 4 * 0x100)) < 4 * 0x100))
{ {
struct string_constant *l; struct string_constant *l;
...@@ -1722,11 +1744,11 @@ m16_usym5_4 (op, mode) ...@@ -1722,11 +1744,11 @@ m16_usym5_4 (op, mode)
{ {
if (GET_CODE (op) == SYMBOL_REF if (GET_CODE (op) == SYMBOL_REF
&& SYMBOL_REF_FLAG (op) && SYMBOL_REF_FLAG (op)
&& current_frame_info.insns_len > 0 && cfun->machine->insns_len > 0
&& XSTR (op, 0)[0] == '*' && XSTR (op, 0)[0] == '*'
&& strncmp (XSTR (op, 0) + 1, LOCAL_LABEL_PREFIX, && strncmp (XSTR (op, 0) + 1, LOCAL_LABEL_PREFIX,
sizeof LOCAL_LABEL_PREFIX - 1) == 0 sizeof LOCAL_LABEL_PREFIX - 1) == 0
&& (current_frame_info.insns_len + get_pool_size () + mips_string_length && (cfun->machine->insns_len + get_pool_size () + mips_string_length
< 4 * 0x20)) < 4 * 0x20))
{ {
struct string_constant *l; struct string_constant *l;
...@@ -2399,7 +2421,30 @@ mips_move_1word (operands, insn, unsignedp) ...@@ -2399,7 +2421,30 @@ mips_move_1word (operands, insn, unsignedp)
return ret; return ret;
} }
/* Return instructions to restore the global pointer from the stack,
assuming TARGET_ABICALLS. Used by exception_receiver to set up
the GP for exception handlers.
OPERANDS is an array of operands whose contents are undefined
on entry. INSN is the exception_handler instruction. */
const char *
mips_restore_gp (operands, insn)
rtx *operands, insn;
{
rtx loc;
operands[0] = pic_offset_table_rtx;
if (frame_pointer_needed)
loc = hard_frame_pointer_rtx;
else
loc = stack_pointer_rtx;
loc = plus_constant (loc, cfun->machine->frame.args_size);
operands[1] = gen_rtx_MEM (Pmode, loc);
return mips_move_1word (operands, insn, 0);
}
/* Return the appropriate instructions to move 2 words */ /* Return the appropriate instructions to move 2 words */
...@@ -3444,6 +3489,36 @@ mips_gen_conditional_trap (operands) ...@@ -3444,6 +3489,36 @@ mips_gen_conditional_trap (operands)
operands[1])); operands[1]));
} }
/* Emit code to change the current function's return address to
ADDRESS. SCRATCH is available as a scratch register, if needed.
ADDRESS and SCRATCH are both word-mode GPRs. */
void
mips_set_return_address (address, scratch)
rtx address, scratch;
{
HOST_WIDE_INT gp_offset;
compute_frame_size (get_frame_size ());
if (((cfun->machine->frame.mask >> 31) & 1) == 0)
abort ();
gp_offset = cfun->machine->frame.gp_sp_offset;
/* Reduce SP + GP_OFSET to a legitimate address and put it in SCRATCH. */
if (gp_offset < 32768)
scratch = plus_constant (stack_pointer_rtx, gp_offset);
else
{
emit_move_insn (scratch, GEN_INT (gp_offset));
if (Pmode == DImode)
emit_insn (gen_adddi3 (scratch, scratch, stack_pointer_rtx));
else
emit_insn (gen_addsi3 (scratch, scratch, stack_pointer_rtx));
}
emit_move_insn (gen_rtx_MEM (GET_MODE (address), scratch), address);
}
/* Write a loop to move a constant number of bytes. /* Write a loop to move a constant number of bytes.
Generate load/stores as follows: Generate load/stores as follows:
...@@ -5442,9 +5517,9 @@ mips_debugger_offset (addr, offset) ...@@ -5442,9 +5517,9 @@ mips_debugger_offset (addr, offset)
if (reg == stack_pointer_rtx || reg == frame_pointer_rtx if (reg == stack_pointer_rtx || reg == frame_pointer_rtx
|| reg == hard_frame_pointer_rtx) || reg == hard_frame_pointer_rtx)
{ {
HOST_WIDE_INT frame_size = (!current_frame_info.initialized) HOST_WIDE_INT frame_size = (!cfun->machine->frame.initialized)
? compute_frame_size (get_frame_size ()) ? compute_frame_size (get_frame_size ())
: current_frame_info.total_size; : cfun->machine->frame.total_size;
/* MIPS16 frame is smaller */ /* MIPS16 frame is smaller */
if (frame_pointer_needed && TARGET_MIPS16) if (frame_pointer_needed && TARGET_MIPS16)
...@@ -6584,17 +6659,17 @@ compute_frame_size (size) ...@@ -6584,17 +6659,17 @@ compute_frame_size (size)
total_size = 32; total_size = 32;
/* Save other computed information. */ /* Save other computed information. */
current_frame_info.total_size = total_size; cfun->machine->frame.total_size = total_size;
current_frame_info.var_size = var_size; cfun->machine->frame.var_size = var_size;
current_frame_info.args_size = args_size; cfun->machine->frame.args_size = args_size;
current_frame_info.extra_size = extra_size; cfun->machine->frame.extra_size = extra_size;
current_frame_info.gp_reg_size = gp_reg_size; cfun->machine->frame.gp_reg_size = gp_reg_size;
current_frame_info.fp_reg_size = fp_reg_size; cfun->machine->frame.fp_reg_size = fp_reg_size;
current_frame_info.mask = mask; cfun->machine->frame.mask = mask;
current_frame_info.fmask = fmask; cfun->machine->frame.fmask = fmask;
current_frame_info.initialized = reload_completed; cfun->machine->frame.initialized = reload_completed;
current_frame_info.num_gp = gp_reg_size / UNITS_PER_WORD; cfun->machine->frame.num_gp = gp_reg_size / UNITS_PER_WORD;
current_frame_info.num_fp = fp_reg_size / (FP_INC * UNITS_PER_FPREG); cfun->machine->frame.num_fp = fp_reg_size / (FP_INC * UNITS_PER_FPREG);
if (mask) if (mask)
{ {
...@@ -6608,13 +6683,13 @@ compute_frame_size (size) ...@@ -6608,13 +6683,13 @@ compute_frame_size (size)
else else
offset = total_size - GET_MODE_SIZE (gpr_mode); offset = total_size - GET_MODE_SIZE (gpr_mode);
current_frame_info.gp_sp_offset = offset; cfun->machine->frame.gp_sp_offset = offset;
current_frame_info.gp_save_offset = offset - total_size; cfun->machine->frame.gp_save_offset = offset - total_size;
} }
else else
{ {
current_frame_info.gp_sp_offset = 0; cfun->machine->frame.gp_sp_offset = 0;
current_frame_info.gp_save_offset = 0; cfun->machine->frame.gp_save_offset = 0;
} }
if (fmask) if (fmask)
...@@ -6622,19 +6697,60 @@ compute_frame_size (size) ...@@ -6622,19 +6697,60 @@ compute_frame_size (size)
unsigned long offset = (args_size + extra_size + var_size unsigned long offset = (args_size + extra_size + var_size
+ gp_reg_rounded + fp_reg_size + gp_reg_rounded + fp_reg_size
- FP_INC * UNITS_PER_FPREG); - FP_INC * UNITS_PER_FPREG);
current_frame_info.fp_sp_offset = offset; cfun->machine->frame.fp_sp_offset = offset;
current_frame_info.fp_save_offset = offset - total_size; cfun->machine->frame.fp_save_offset = offset - total_size;
} }
else else
{ {
current_frame_info.fp_sp_offset = 0; cfun->machine->frame.fp_sp_offset = 0;
current_frame_info.fp_save_offset = 0; cfun->machine->frame.fp_save_offset = 0;
} }
/* Ok, we're done. */ /* Ok, we're done. */
return total_size; return total_size;
} }
/* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame
pointer, argument pointer, or return address pointer. TO is either
the stack pointer or hard frame pointer. */
int
mips_initial_elimination_offset (from, to)
int from, to;
{
int offset;
/* Set OFFSET to the offset from the stack pointer. */
switch (from)
{
case FRAME_POINTER_REGNUM:
offset = 0;
break;
case ARG_POINTER_REGNUM:
compute_frame_size (get_frame_size ());
offset = cfun->machine->frame.total_size;
if (mips_abi == ABI_N32 || mips_abi == ABI_64 || mips_abi == ABI_MEABI)
offset -= current_function_pretend_args_size;
break;
case RETURN_ADDRESS_POINTER_REGNUM:
compute_frame_size (get_frame_size ());
offset = cfun->machine->frame.gp_sp_offset;
if (BYTES_BIG_ENDIAN)
offset += UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT);
break;
default:
abort ();
}
if (TARGET_MIPS16 && to == HARD_FRAME_POINTER_REGNUM)
offset -= current_function_outgoing_args_size;
return offset;
}
/* Common code to emit the insns (or to write the instructions to a file) /* Common code to emit the insns (or to write the instructions to a file)
to save/restore registers. to save/restore registers.
...@@ -6731,8 +6847,8 @@ save_restore_insns (store_p, large_reg, large_offset) ...@@ -6731,8 +6847,8 @@ save_restore_insns (store_p, large_reg, large_offset)
rtx large_reg; /* register holding large offset constant or NULL */ rtx large_reg; /* register holding large offset constant or NULL */
long large_offset; /* large constant offset value */ long large_offset; /* large constant offset value */
{ {
long mask = current_frame_info.mask; long mask = cfun->machine->frame.mask;
long fmask = current_frame_info.fmask; long fmask = cfun->machine->frame.fmask;
long real_mask = mask; long real_mask = mask;
int regno; int regno;
rtx base_reg_rtx; rtx base_reg_rtx;
...@@ -6769,9 +6885,9 @@ save_restore_insns (store_p, large_reg, large_offset) ...@@ -6769,9 +6885,9 @@ save_restore_insns (store_p, large_reg, large_offset)
the constant created in the prologue/epilogue to adjust the stack the constant created in the prologue/epilogue to adjust the stack
frame. */ frame. */
gp_offset = current_frame_info.gp_sp_offset; gp_offset = cfun->machine->frame.gp_sp_offset;
end_offset end_offset
= gp_offset - (current_frame_info.gp_reg_size = gp_offset - (cfun->machine->frame.gp_reg_size
- GET_MODE_SIZE (gpr_mode)); - GET_MODE_SIZE (gpr_mode));
if (gp_offset < 0 || end_offset < 0) if (gp_offset < 0 || end_offset < 0)
...@@ -6879,8 +6995,8 @@ save_restore_insns (store_p, large_reg, large_offset) ...@@ -6879,8 +6995,8 @@ save_restore_insns (store_p, large_reg, large_offset)
if (fmask) if (fmask)
{ {
/* Pick which pointer to use as a base register. */ /* Pick which pointer to use as a base register. */
fp_offset = current_frame_info.fp_sp_offset; fp_offset = cfun->machine->frame.fp_sp_offset;
end_offset = fp_offset - (current_frame_info.fp_reg_size end_offset = fp_offset - (cfun->machine->frame.fp_reg_size
- UNITS_PER_FPVALUE); - UNITS_PER_FPVALUE);
if (fp_offset < 0 || end_offset < 0) if (fp_offset < 0 || end_offset < 0)
...@@ -6951,7 +7067,7 @@ mips_output_function_prologue (file, size) ...@@ -6951,7 +7067,7 @@ mips_output_function_prologue (file, size)
#ifndef FUNCTION_NAME_ALREADY_DECLARED #ifndef FUNCTION_NAME_ALREADY_DECLARED
const char *fnname; const char *fnname;
#endif #endif
HOST_WIDE_INT tsize = current_frame_info.total_size; HOST_WIDE_INT tsize = cfun->machine->frame.total_size;
/* ??? When is this really needed? At least the GNU assembler does not /* ??? When is this really needed? At least the GNU assembler does not
need the source filename more than once in the file, beyond what is need the source filename more than once in the file, beyond what is
...@@ -7002,18 +7118,18 @@ mips_output_function_prologue (file, size) ...@@ -7002,18 +7118,18 @@ mips_output_function_prologue (file, size)
? ((long) tsize - current_function_outgoing_args_size) ? ((long) tsize - current_function_outgoing_args_size)
: (long) tsize), : (long) tsize),
reg_names[GP_REG_FIRST + 31], reg_names[GP_REG_FIRST + 31],
current_frame_info.var_size, cfun->machine->frame.var_size,
current_frame_info.num_gp, cfun->machine->frame.num_gp,
current_frame_info.num_fp, cfun->machine->frame.num_fp,
current_function_outgoing_args_size, current_function_outgoing_args_size,
current_frame_info.extra_size); cfun->machine->frame.extra_size);
/* .mask MASK, GPOFFSET; .fmask FPOFFSET */ /* .mask MASK, GPOFFSET; .fmask FPOFFSET */
fprintf (file, "\t.mask\t0x%08lx,%ld\n\t.fmask\t0x%08lx,%ld\n", fprintf (file, "\t.mask\t0x%08lx,%ld\n\t.fmask\t0x%08lx,%ld\n",
current_frame_info.mask, cfun->machine->frame.mask,
current_frame_info.gp_save_offset, cfun->machine->frame.gp_save_offset,
current_frame_info.fmask, cfun->machine->frame.fmask,
current_frame_info.fp_save_offset); cfun->machine->frame.fp_save_offset);
/* Require: /* Require:
OLD_SP == *FRAMEREG + FRAMESIZE => can find old_sp from nominated FP reg. OLD_SP == *FRAMEREG + FRAMESIZE => can find old_sp from nominated FP reg.
...@@ -7022,9 +7138,9 @@ mips_output_function_prologue (file, size) ...@@ -7022,9 +7138,9 @@ mips_output_function_prologue (file, size)
if (mips_entry && ! mips_can_use_return_insn ()) if (mips_entry && ! mips_can_use_return_insn ())
{ {
int save16 = BITSET_P (current_frame_info.mask, 16); int save16 = BITSET_P (cfun->machine->frame.mask, 16);
int save17 = BITSET_P (current_frame_info.mask, 17); int save17 = BITSET_P (cfun->machine->frame.mask, 17);
int save31 = BITSET_P (current_frame_info.mask, 31); int save31 = BITSET_P (cfun->machine->frame.mask, 31);
int savearg = 0; int savearg = 0;
rtx insn; rtx insn;
...@@ -7146,7 +7262,7 @@ mips_output_function_prologue (file, size) ...@@ -7146,7 +7262,7 @@ mips_output_function_prologue (file, size)
fprintf (file, "\t%s\t%s,%s,%ld\n", fprintf (file, "\t%s\t%s,%s,%ld\n",
(Pmode == DImode ? "dsubu" : "subu"), (Pmode == DImode ? "dsubu" : "subu"),
sp_str, sp_str, (long) tsize); sp_str, sp_str, (long) tsize);
fprintf (file, "\t.cprestore %ld\n", current_frame_info.args_size); fprintf (file, "\t.cprestore %ld\n", cfun->machine->frame.args_size);
} }
if (dwarf2out_do_frame ()) if (dwarf2out_do_frame ())
...@@ -7355,17 +7471,17 @@ mips_expand_prologue () ...@@ -7355,17 +7471,17 @@ mips_expand_prologue ()
which may return a floating point value. Set up a sequence which may return a floating point value. Set up a sequence
of instructions to do so. Later on we emit them at the right of instructions to do so. Later on we emit them at the right
moment. */ moment. */
if (TARGET_MIPS16 && BITSET_P (current_frame_info.mask, 18)) if (TARGET_MIPS16 && BITSET_P (cfun->machine->frame.mask, 18))
{ {
rtx reg_rtx = gen_rtx (REG, gpr_mode, GP_REG_FIRST + 3); rtx reg_rtx = gen_rtx (REG, gpr_mode, GP_REG_FIRST + 3);
long gp_offset, base_offset; long gp_offset, base_offset;
gp_offset = current_frame_info.gp_sp_offset; gp_offset = cfun->machine->frame.gp_sp_offset;
if (BITSET_P (current_frame_info.mask, 16)) if (BITSET_P (cfun->machine->frame.mask, 16))
gp_offset -= UNITS_PER_WORD; gp_offset -= UNITS_PER_WORD;
if (BITSET_P (current_frame_info.mask, 17)) if (BITSET_P (cfun->machine->frame.mask, 17))
gp_offset -= UNITS_PER_WORD; gp_offset -= UNITS_PER_WORD;
if (BITSET_P (current_frame_info.mask, 31)) if (BITSET_P (cfun->machine->frame.mask, 31))
gp_offset -= UNITS_PER_WORD; gp_offset -= UNITS_PER_WORD;
if (tsize > 32767) if (tsize > 32767)
base_offset = tsize; base_offset = tsize;
...@@ -7547,8 +7663,8 @@ mips_output_function_epilogue (file, size) ...@@ -7547,8 +7663,8 @@ mips_output_function_epilogue (file, size)
if (TARGET_STATS) if (TARGET_STATS)
{ {
int num_gp_regs = current_frame_info.gp_reg_size / 4; int num_gp_regs = cfun->machine->frame.gp_reg_size / 4;
int num_fp_regs = current_frame_info.fp_reg_size / 8; int num_fp_regs = cfun->machine->frame.fp_reg_size / 8;
int num_regs = num_gp_regs + num_fp_regs; int num_regs = num_gp_regs + num_fp_regs;
const char *name = fnname; const char *name = fnname;
...@@ -7560,10 +7676,10 @@ mips_output_function_epilogue (file, size) ...@@ -7560,10 +7676,10 @@ mips_output_function_epilogue (file, size)
fprintf (stderr, fprintf (stderr,
"%-20s fp=%c leaf=%c alloca=%c setjmp=%c stack=%4ld arg=%3d reg=%2d/%d delay=%3d/%3dL %3d/%3dJ refs=%3d/%3d/%3d", "%-20s fp=%c leaf=%c alloca=%c setjmp=%c stack=%4ld arg=%3d reg=%2d/%d delay=%3d/%3dL %3d/%3dJ refs=%3d/%3d/%3d",
name, frame_pointer_needed ? 'y' : 'n', name, frame_pointer_needed ? 'y' : 'n',
(current_frame_info.mask & RA_MASK) != 0 ? 'n' : 'y', (cfun->machine->frame.mask & RA_MASK) != 0 ? 'n' : 'y',
current_function_calls_alloca ? 'y' : 'n', current_function_calls_alloca ? 'y' : 'n',
current_function_calls_setjmp ? 'y' : 'n', current_function_calls_setjmp ? 'y' : 'n',
current_frame_info.total_size, cfun->machine->frame.total_size,
current_function_outgoing_args_size, num_gp_regs, num_fp_regs, current_function_outgoing_args_size, num_gp_regs, num_fp_regs,
dslots_load_total, dslots_load_filled, dslots_load_total, dslots_load_filled,
dslots_jump_total, dslots_jump_filled, dslots_jump_total, dslots_jump_filled,
...@@ -7584,7 +7700,6 @@ mips_output_function_epilogue (file, size) ...@@ -7584,7 +7700,6 @@ mips_output_function_epilogue (file, size)
num_refs[2] = 0; num_refs[2] = 0;
mips_load_reg = 0; mips_load_reg = 0;
mips_load_reg2 = 0; mips_load_reg2 = 0;
current_frame_info = zero_frame_info;
while (string_constants != NULL) while (string_constants != NULL)
{ {
...@@ -7610,7 +7725,7 @@ mips_output_function_epilogue (file, size) ...@@ -7610,7 +7725,7 @@ mips_output_function_epilogue (file, size)
void void
mips_expand_epilogue () mips_expand_epilogue ()
{ {
HOST_WIDE_INT tsize = current_frame_info.total_size; HOST_WIDE_INT tsize = cfun->machine->frame.total_size;
rtx tsize_rtx = GEN_INT (tsize); rtx tsize_rtx = GEN_INT (tsize);
rtx tmp_rtx = (rtx)0; rtx tmp_rtx = (rtx)0;
...@@ -7679,7 +7794,7 @@ mips_expand_epilogue () ...@@ -7679,7 +7794,7 @@ mips_expand_epilogue ()
are going to restore it, then we must emit a blockage insn to are going to restore it, then we must emit a blockage insn to
prevent the scheduler from moving the restore out of the epilogue. */ prevent the scheduler from moving the restore out of the epilogue. */
else if (TARGET_ABICALLS && mips_abi != ABI_32 && mips_abi != ABI_O64 else if (TARGET_ABICALLS && mips_abi != ABI_32 && mips_abi != ABI_O64
&& (current_frame_info.mask && (cfun->machine->frame.mask
& (1L << (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST)))) & (1L << (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))))
emit_insn (gen_blockage ()); emit_insn (gen_blockage ());
...@@ -7741,7 +7856,7 @@ mips_expand_epilogue () ...@@ -7741,7 +7856,7 @@ mips_expand_epilogue ()
} }
/* The mips16 loads the return address into $7, not $31. */ /* The mips16 loads the return address into $7, not $31. */
if (TARGET_MIPS16 && (current_frame_info.mask & RA_MASK) != 0) if (TARGET_MIPS16 && (cfun->machine->frame.mask & RA_MASK) != 0)
emit_jump_insn (gen_return_internal (gen_rtx (REG, Pmode, emit_jump_insn (gen_return_internal (gen_rtx (REG, Pmode,
GP_REG_FIRST + 7))); GP_REG_FIRST + 7)));
else else
...@@ -7776,8 +7891,8 @@ mips_can_use_return_insn () ...@@ -7776,8 +7891,8 @@ mips_can_use_return_insn ()
&& GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE) && GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
return 0; return 0;
if (current_frame_info.initialized) if (cfun->machine->frame.initialized)
return current_frame_info.total_size == 0; return cfun->machine->frame.total_size == 0;
return compute_frame_size (get_frame_size ()) == 0; return compute_frame_size (get_frame_size ()) == 0;
} }
...@@ -9457,9 +9572,9 @@ machine_dependent_reorg (first) ...@@ -9457,9 +9572,9 @@ machine_dependent_reorg (first)
} }
} }
/* Store the original value of insns_len in current_frame_info, so /* Store the original value of insns_len in cfun->machine, so
that simple_memory_operand can look at it. */ that simple_memory_operand can look at it. */
current_frame_info.insns_len = insns_len; cfun->machine->insns_len = insns_len;
pool_size = get_pool_size (); pool_size = get_pool_size ();
if (insns_len + pool_size + mips_string_length < 0x8000) if (insns_len + pool_size + mips_string_length < 0x8000)
......
...@@ -2346,31 +2346,6 @@ extern enum reg_class mips_char_to_class[256]; ...@@ -2346,31 +2346,6 @@ extern enum reg_class mips_char_to_class[256];
#define TARGET_PTRMEMFUNC_VBIT_LOCATION ptrmemfunc_vbit_in_delta #define TARGET_PTRMEMFUNC_VBIT_LOCATION ptrmemfunc_vbit_in_delta
/* Structure to be filled in by compute_frame_size with register
save masks, and offsets for the current function. */
struct mips_frame_info
{
long total_size; /* # bytes that the entire frame takes up */
long var_size; /* # bytes that variables take up */
long args_size; /* # bytes that outgoing arguments take up */
long extra_size; /* # bytes of extra gunk */
int gp_reg_size; /* # bytes needed to store gp regs */
int fp_reg_size; /* # bytes needed to store fp regs */
long mask; /* mask of saved gp registers */
long fmask; /* mask of saved fp registers */
long gp_save_offset; /* offset from vfp to store gp registers */
long fp_save_offset; /* offset from vfp to store fp registers */
long gp_sp_offset; /* offset from new sp to store gp registers */
long fp_sp_offset; /* offset from new sp to store fp registers */
int initialized; /* != 0 if frame size already calculated */
int num_gp; /* number of gp registers saved */
int num_fp; /* number of fp registers saved */
long insns_len; /* length of insns; mips16 only */
};
extern struct mips_frame_info current_frame_info;
/* If defined, this macro specifies a table of register pairs used to /* If defined, this macro specifies a table of register pairs used to
eliminate unneeded registers that point into the stack frame. If eliminate unneeded registers that point into the stack frame. If
it is not defined, the only elimination attempted by the compiler it is not defined, the only elimination attempted by the compiler
...@@ -2442,47 +2417,8 @@ extern struct mips_frame_info current_frame_info; ...@@ -2442,47 +2417,8 @@ extern struct mips_frame_info current_frame_info;
&& (! TARGET_MIPS16 \ && (! TARGET_MIPS16 \
|| compute_frame_size (get_frame_size ()) < 32768))))) || compute_frame_size (get_frame_size ()) < 32768)))))
/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
specifies the initial difference between the specified pair of (OFFSET) = mips_initial_elimination_offset ((FROM), (TO))
registers. This macro must be defined if `ELIMINABLE_REGS' is
defined. */
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
{ compute_frame_size (get_frame_size ()); \
if (TARGET_MIPS16 && (FROM) == FRAME_POINTER_REGNUM \
&& (TO) == HARD_FRAME_POINTER_REGNUM) \
(OFFSET) = - current_function_outgoing_args_size; \
else if ((FROM) == FRAME_POINTER_REGNUM) \
(OFFSET) = 0; \
else if (TARGET_MIPS16 && (FROM) == ARG_POINTER_REGNUM \
&& (TO) == HARD_FRAME_POINTER_REGNUM) \
(OFFSET) = (current_frame_info.total_size \
- current_function_outgoing_args_size \
- ((mips_abi != ABI_32 \
&& mips_abi != ABI_O64 \
&& mips_abi != ABI_EABI) \
? current_function_pretend_args_size \
: 0)); \
else if ((FROM) == ARG_POINTER_REGNUM) \
(OFFSET) = (current_frame_info.total_size \
- ((mips_abi != ABI_32 \
&& mips_abi != ABI_O64 \
&& mips_abi != ABI_EABI) \
? current_function_pretend_args_size \
: 0)); \
/* Some ABIs store 64 bits to the stack, but Pmode is 32 bits, \
so we must add 4 bytes to the offset to get the right value. */ \
else if ((FROM) == RETURN_ADDRESS_POINTER_REGNUM) \
{ \
(OFFSET) = current_frame_info.gp_sp_offset \
+ ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT)) \
* (BYTES_BIG_ENDIAN != 0)); \
if (TARGET_MIPS16 && (TO) != STACK_POINTER_REGNUM) \
(OFFSET) -= current_function_outgoing_args_size; \
} \
else \
abort(); \
}
/* If we generate an insn to push BYTES bytes, /* If we generate an insn to push BYTES bytes,
this says how many the stack pointer really advances by. this says how many the stack pointer really advances by.
......
...@@ -10022,49 +10022,14 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2" ...@@ -10022,49 +10022,14 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2"
[(const_int 0)] [(const_int 0)]
" "
{ {
HOST_WIDE_INT gp_offset; mips_set_return_address (operands[0], operands[1]);
rtx base;
compute_frame_size (get_frame_size ());
if (((current_frame_info.mask >> 31) & 1) == 0)
abort ();
gp_offset = current_frame_info.gp_sp_offset;
if (gp_offset < 32768)
base = stack_pointer_rtx;
else
{
base = operands[1];
emit_move_insn (base, GEN_INT (gp_offset));
if (Pmode == DImode)
emit_insn (gen_adddi3 (base, base, stack_pointer_rtx));
else
emit_insn (gen_addsi3 (base, base, stack_pointer_rtx));
gp_offset = 0;
}
emit_move_insn (gen_rtx_MEM (GET_MODE (operands[0]),
plus_constant (base, gp_offset)),
operands[0]);
DONE; DONE;
}") }")
(define_insn "exception_receiver" (define_insn "exception_receiver"
[(unspec_volatile [(const_int 0)] UNSPEC_EH_RECEIVER)] [(unspec_volatile [(const_int 0)] UNSPEC_EH_RECEIVER)]
"TARGET_ABICALLS && (mips_abi == ABI_32 || mips_abi == ABI_O64)" "TARGET_ABICALLS && (mips_abi == ABI_32 || mips_abi == ABI_O64)"
"* "* return mips_restore_gp (operands, insn);"
{
rtx loc;
operands[0] = pic_offset_table_rtx;
if (frame_pointer_needed)
loc = hard_frame_pointer_rtx;
else
loc = stack_pointer_rtx;
loc = plus_constant (loc, current_frame_info.args_size);
operands[1] = gen_rtx_MEM (Pmode, loc);
return mips_move_1word (operands, insn, 0);
}"
[(set_attr "type" "load") [(set_attr "type" "load")
(set_attr "length" "8")]) (set_attr "length" "8")])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment