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
This commit is contained in:
Richard Sandiford 2002-06-18 11:23:41 +00:00 committed by Richard Sandiford
parent d3beaf0a30
commit b24718388c
5 changed files with 208 additions and 173 deletions

View File

@ -1,3 +1,19 @@
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>
* cpplib.c (dtable): Update.

View File

@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */
#define GCC_MIPS_PROTOS_H
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_start PARAMS ((FILE *));
extern void iris6_asm_file_start PARAMS ((FILE *));
@ -86,6 +87,7 @@ extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *,
tree, rtx));
extern void gen_conditional_move 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 int mips_address_cost PARAMS ((rtx));
extern void mips_count_memory_refs PARAMS ((rtx, int));
@ -96,6 +98,7 @@ extern const char *mips_fill_delay_slot PARAMS ((const char *,
rtx));
extern const char *mips_move_1word PARAMS ((rtx *, rtx, int));
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,
enum block_move_type));
extern void override_options PARAMS ((void));

View File

@ -147,6 +147,28 @@ static void mips_select_rtx_section PARAMS ((enum machine_mode, rtx,
unsigned HOST_WIDE_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(()) {
/* Pseudo-reg holding the address of the current function when
generating embedded PIC code. Created by LEGITIMIZE_ADDRESS,
@ -156,6 +178,12 @@ struct machine_function GTY(()) {
/* Pseudo-reg holding the value of $28 in a mips16 function which
refers to GP relative global variables. */
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. */
@ -335,12 +363,6 @@ static enum machine_mode gpr_mode;
can support a given mode. */
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
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
@ -929,18 +951,18 @@ simple_memory_operand (op, mode)
getting this right is during delayed branch scheduling, so
don't need to check until then. The machine_dependent_reorg
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
would be better if we could take into account the location of
the instruction within the function, but we can't, because we
don't know where we are. */
if (TARGET_MIPS16
&& CONSTANT_POOL_ADDRESS_P (addr)
&& current_frame_info.insns_len > 0)
&& cfun->machine->insns_len > 0)
{
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)
return size < 4 * 0x100;
else if (GET_MODE_SIZE (mode) == 8)
@ -1695,11 +1717,11 @@ m16_usym8_4 (op, mode)
{
if (GET_CODE (op) == SYMBOL_REF
&& SYMBOL_REF_FLAG (op)
&& current_frame_info.insns_len > 0
&& cfun->machine->insns_len > 0
&& XSTR (op, 0)[0] == '*'
&& strncmp (XSTR (op, 0) + 1, LOCAL_LABEL_PREFIX,
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))
{
struct string_constant *l;
@ -1722,11 +1744,11 @@ m16_usym5_4 (op, mode)
{
if (GET_CODE (op) == SYMBOL_REF
&& SYMBOL_REF_FLAG (op)
&& current_frame_info.insns_len > 0
&& cfun->machine->insns_len > 0
&& XSTR (op, 0)[0] == '*'
&& strncmp (XSTR (op, 0) + 1, LOCAL_LABEL_PREFIX,
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))
{
struct string_constant *l;
@ -2399,7 +2421,30 @@ mips_move_1word (operands, insn, unsignedp)
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 */
@ -3444,6 +3489,36 @@ mips_gen_conditional_trap (operands)
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.
Generate load/stores as follows:
@ -5442,9 +5517,9 @@ mips_debugger_offset (addr, offset)
if (reg == stack_pointer_rtx || reg == 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 ())
: current_frame_info.total_size;
: cfun->machine->frame.total_size;
/* MIPS16 frame is smaller */
if (frame_pointer_needed && TARGET_MIPS16)
@ -6584,17 +6659,17 @@ compute_frame_size (size)
total_size = 32;
/* Save other computed information. */
current_frame_info.total_size = total_size;
current_frame_info.var_size = var_size;
current_frame_info.args_size = args_size;
current_frame_info.extra_size = extra_size;
current_frame_info.gp_reg_size = gp_reg_size;
current_frame_info.fp_reg_size = fp_reg_size;
current_frame_info.mask = mask;
current_frame_info.fmask = fmask;
current_frame_info.initialized = reload_completed;
current_frame_info.num_gp = gp_reg_size / UNITS_PER_WORD;
current_frame_info.num_fp = fp_reg_size / (FP_INC * UNITS_PER_FPREG);
cfun->machine->frame.total_size = total_size;
cfun->machine->frame.var_size = var_size;
cfun->machine->frame.args_size = args_size;
cfun->machine->frame.extra_size = extra_size;
cfun->machine->frame.gp_reg_size = gp_reg_size;
cfun->machine->frame.fp_reg_size = fp_reg_size;
cfun->machine->frame.mask = mask;
cfun->machine->frame.fmask = fmask;
cfun->machine->frame.initialized = reload_completed;
cfun->machine->frame.num_gp = gp_reg_size / UNITS_PER_WORD;
cfun->machine->frame.num_fp = fp_reg_size / (FP_INC * UNITS_PER_FPREG);
if (mask)
{
@ -6608,13 +6683,13 @@ compute_frame_size (size)
else
offset = total_size - GET_MODE_SIZE (gpr_mode);
current_frame_info.gp_sp_offset = offset;
current_frame_info.gp_save_offset = offset - total_size;
cfun->machine->frame.gp_sp_offset = offset;
cfun->machine->frame.gp_save_offset = offset - total_size;
}
else
{
current_frame_info.gp_sp_offset = 0;
current_frame_info.gp_save_offset = 0;
cfun->machine->frame.gp_sp_offset = 0;
cfun->machine->frame.gp_save_offset = 0;
}
if (fmask)
@ -6622,19 +6697,60 @@ compute_frame_size (size)
unsigned long offset = (args_size + extra_size + var_size
+ gp_reg_rounded + fp_reg_size
- FP_INC * UNITS_PER_FPREG);
current_frame_info.fp_sp_offset = offset;
current_frame_info.fp_save_offset = offset - total_size;
cfun->machine->frame.fp_sp_offset = offset;
cfun->machine->frame.fp_save_offset = offset - total_size;
}
else
{
current_frame_info.fp_sp_offset = 0;
current_frame_info.fp_save_offset = 0;
cfun->machine->frame.fp_sp_offset = 0;
cfun->machine->frame.fp_save_offset = 0;
}
/* Ok, we're done. */
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)
to save/restore registers.
@ -6731,8 +6847,8 @@ save_restore_insns (store_p, large_reg, large_offset)
rtx large_reg; /* register holding large offset constant or NULL */
long large_offset; /* large constant offset value */
{
long mask = current_frame_info.mask;
long fmask = current_frame_info.fmask;
long mask = cfun->machine->frame.mask;
long fmask = cfun->machine->frame.fmask;
long real_mask = mask;
int regno;
rtx base_reg_rtx;
@ -6769,9 +6885,9 @@ save_restore_insns (store_p, large_reg, large_offset)
the constant created in the prologue/epilogue to adjust the stack
frame. */
gp_offset = current_frame_info.gp_sp_offset;
gp_offset = cfun->machine->frame.gp_sp_offset;
end_offset
= gp_offset - (current_frame_info.gp_reg_size
= gp_offset - (cfun->machine->frame.gp_reg_size
- GET_MODE_SIZE (gpr_mode));
if (gp_offset < 0 || end_offset < 0)
@ -6879,8 +6995,8 @@ save_restore_insns (store_p, large_reg, large_offset)
if (fmask)
{
/* Pick which pointer to use as a base register. */
fp_offset = current_frame_info.fp_sp_offset;
end_offset = fp_offset - (current_frame_info.fp_reg_size
fp_offset = cfun->machine->frame.fp_sp_offset;
end_offset = fp_offset - (cfun->machine->frame.fp_reg_size
- UNITS_PER_FPVALUE);
if (fp_offset < 0 || end_offset < 0)
@ -6951,7 +7067,7 @@ mips_output_function_prologue (file, size)
#ifndef FUNCTION_NAME_ALREADY_DECLARED
const char *fnname;
#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
need the source filename more than once in the file, beyond what is
@ -7002,18 +7118,18 @@ mips_output_function_prologue (file, size)
? ((long) tsize - current_function_outgoing_args_size)
: (long) tsize),
reg_names[GP_REG_FIRST + 31],
current_frame_info.var_size,
current_frame_info.num_gp,
current_frame_info.num_fp,
cfun->machine->frame.var_size,
cfun->machine->frame.num_gp,
cfun->machine->frame.num_fp,
current_function_outgoing_args_size,
current_frame_info.extra_size);
cfun->machine->frame.extra_size);
/* .mask MASK, GPOFFSET; .fmask FPOFFSET */
fprintf (file, "\t.mask\t0x%08lx,%ld\n\t.fmask\t0x%08lx,%ld\n",
current_frame_info.mask,
current_frame_info.gp_save_offset,
current_frame_info.fmask,
current_frame_info.fp_save_offset);
cfun->machine->frame.mask,
cfun->machine->frame.gp_save_offset,
cfun->machine->frame.fmask,
cfun->machine->frame.fp_save_offset);
/* Require:
OLD_SP == *FRAMEREG + FRAMESIZE => can find old_sp from nominated FP reg.
@ -7022,9 +7138,9 @@ mips_output_function_prologue (file, size)
if (mips_entry && ! mips_can_use_return_insn ())
{
int save16 = BITSET_P (current_frame_info.mask, 16);
int save17 = BITSET_P (current_frame_info.mask, 17);
int save31 = BITSET_P (current_frame_info.mask, 31);
int save16 = BITSET_P (cfun->machine->frame.mask, 16);
int save17 = BITSET_P (cfun->machine->frame.mask, 17);
int save31 = BITSET_P (cfun->machine->frame.mask, 31);
int savearg = 0;
rtx insn;
@ -7146,7 +7262,7 @@ mips_output_function_prologue (file, size)
fprintf (file, "\t%s\t%s,%s,%ld\n",
(Pmode == DImode ? "dsubu" : "subu"),
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 ())
@ -7355,17 +7471,17 @@ mips_expand_prologue ()
which may return a floating point value. Set up a sequence
of instructions to do so. Later on we emit them at the right
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);
long gp_offset, base_offset;
gp_offset = current_frame_info.gp_sp_offset;
if (BITSET_P (current_frame_info.mask, 16))
gp_offset = cfun->machine->frame.gp_sp_offset;
if (BITSET_P (cfun->machine->frame.mask, 16))
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;
if (BITSET_P (current_frame_info.mask, 31))
if (BITSET_P (cfun->machine->frame.mask, 31))
gp_offset -= UNITS_PER_WORD;
if (tsize > 32767)
base_offset = tsize;
@ -7547,8 +7663,8 @@ mips_output_function_epilogue (file, size)
if (TARGET_STATS)
{
int num_gp_regs = current_frame_info.gp_reg_size / 4;
int num_fp_regs = current_frame_info.fp_reg_size / 8;
int num_gp_regs = cfun->machine->frame.gp_reg_size / 4;
int num_fp_regs = cfun->machine->frame.fp_reg_size / 8;
int num_regs = num_gp_regs + num_fp_regs;
const char *name = fnname;
@ -7560,10 +7676,10 @@ mips_output_function_epilogue (file, size)
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",
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_setjmp ? 'y' : 'n',
current_frame_info.total_size,
cfun->machine->frame.total_size,
current_function_outgoing_args_size, num_gp_regs, num_fp_regs,
dslots_load_total, dslots_load_filled,
dslots_jump_total, dslots_jump_filled,
@ -7584,7 +7700,6 @@ mips_output_function_epilogue (file, size)
num_refs[2] = 0;
mips_load_reg = 0;
mips_load_reg2 = 0;
current_frame_info = zero_frame_info;
while (string_constants != NULL)
{
@ -7610,7 +7725,7 @@ mips_output_function_epilogue (file, size)
void
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 tmp_rtx = (rtx)0;
@ -7679,7 +7794,7 @@ mips_expand_epilogue ()
are going to restore it, then we must emit a blockage insn to
prevent the scheduler from moving the restore out of the epilogue. */
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))))
emit_insn (gen_blockage ());
@ -7741,7 +7856,7 @@ mips_expand_epilogue ()
}
/* 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,
GP_REG_FIRST + 7)));
else
@ -7776,8 +7891,8 @@ mips_can_use_return_insn ()
&& GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
return 0;
if (current_frame_info.initialized)
return current_frame_info.total_size == 0;
if (cfun->machine->frame.initialized)
return cfun->machine->frame.total_size == 0;
return compute_frame_size (get_frame_size ()) == 0;
}
@ -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. */
current_frame_info.insns_len = insns_len;
cfun->machine->insns_len = insns_len;
pool_size = get_pool_size ();
if (insns_len + pool_size + mips_string_length < 0x8000)

View File

@ -2346,31 +2346,6 @@ extern enum reg_class mips_char_to_class[256];
#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
eliminate unneeded registers that point into the stack frame. If
it is not defined, the only elimination attempted by the compiler
@ -2442,47 +2417,8 @@ extern struct mips_frame_info current_frame_info;
&& (! TARGET_MIPS16 \
|| compute_frame_size (get_frame_size ()) < 32768)))))
/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It
specifies the initial difference between the specified pair of
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(); \
}
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
(OFFSET) = mips_initial_elimination_offset ((FROM), (TO))
/* If we generate an insn to push BYTES bytes,
this says how many the stack pointer really advances by.

View File

@ -10022,49 +10022,14 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2"
[(const_int 0)]
"
{
HOST_WIDE_INT gp_offset;
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]);
mips_set_return_address (operands[0], operands[1]);
DONE;
}")
(define_insn "exception_receiver"
[(unspec_volatile [(const_int 0)] UNSPEC_EH_RECEIVER)]
"TARGET_ABICALLS && (mips_abi == ABI_32 || mips_abi == ABI_O64)"
"*
{
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);
}"
"* return mips_restore_gp (operands, insn);"
[(set_attr "type" "load")
(set_attr "length" "8")])