mirror of git://gcc.gnu.org/git/gcc.git
mips.c (mips_unspec_address_offset): Move earlier in file.
gcc/ * config/mips/mips.c (mips_unspec_address_offset): Move earlier in file. (mips_unspec_address, mips_unspec_offset_high): Likewise. (mips_ok_for_lazy_binding_p, mips_load_call_address): Likewise. (mips16_cfun_returns_in_fpr_p): Likewise. From-SVN: r138911
This commit is contained in:
parent
579725054c
commit
7462a71535
|
@ -1,3 +1,10 @@
|
||||||
|
2008-08-09 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
|
* config/mips/mips.c (mips_unspec_address_offset): Move earlier in file.
|
||||||
|
(mips_unspec_address, mips_unspec_offset_high): Likewise.
|
||||||
|
(mips_ok_for_lazy_binding_p, mips_load_call_address): Likewise.
|
||||||
|
(mips16_cfun_returns_in_fpr_p): Likewise.
|
||||||
|
|
||||||
2008-08-09 Richard Sandiford <rdsandiford@googlemail.com>
|
2008-08-09 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
* config/mips/mips.h (MASK_RETURN_ADDR): Expand commentary.
|
* config/mips/mips.h (MASK_RETURN_ADDR): Expand commentary.
|
||||||
|
|
|
@ -2261,6 +2261,51 @@ mips_emit_call_insn (rtx pattern, bool lazy_p)
|
||||||
return insn;
|
return insn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wrap symbol or label BASE in an UNSPEC address of type SYMBOL_TYPE,
|
||||||
|
then add CONST_INT OFFSET to the result. */
|
||||||
|
|
||||||
|
static rtx
|
||||||
|
mips_unspec_address_offset (rtx base, rtx offset,
|
||||||
|
enum mips_symbol_type symbol_type)
|
||||||
|
{
|
||||||
|
base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base),
|
||||||
|
UNSPEC_ADDRESS_FIRST + symbol_type);
|
||||||
|
if (offset != const0_rtx)
|
||||||
|
base = gen_rtx_PLUS (Pmode, base, offset);
|
||||||
|
return gen_rtx_CONST (Pmode, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return an UNSPEC address with underlying address ADDRESS and symbol
|
||||||
|
type SYMBOL_TYPE. */
|
||||||
|
|
||||||
|
rtx
|
||||||
|
mips_unspec_address (rtx address, enum mips_symbol_type symbol_type)
|
||||||
|
{
|
||||||
|
rtx base, offset;
|
||||||
|
|
||||||
|
split_const (address, &base, &offset);
|
||||||
|
return mips_unspec_address_offset (base, offset, symbol_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If mips_unspec_address (ADDR, SYMBOL_TYPE) is a 32-bit value, add the
|
||||||
|
high part to BASE and return the result. Just return BASE otherwise.
|
||||||
|
TEMP is as for mips_force_temporary.
|
||||||
|
|
||||||
|
The returned expression can be used as the first operand to a LO_SUM. */
|
||||||
|
|
||||||
|
static rtx
|
||||||
|
mips_unspec_offset_high (rtx temp, rtx base, rtx addr,
|
||||||
|
enum mips_symbol_type symbol_type)
|
||||||
|
{
|
||||||
|
if (mips_split_p[symbol_type])
|
||||||
|
{
|
||||||
|
addr = gen_rtx_HIGH (Pmode, mips_unspec_address (addr, symbol_type));
|
||||||
|
addr = mips_force_temporary (temp, addr);
|
||||||
|
base = mips_force_temporary (temp, gen_rtx_PLUS (Pmode, addr, base));
|
||||||
|
}
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return an instruction that copies $gp into register REG. We want
|
/* Return an instruction that copies $gp into register REG. We want
|
||||||
GCC to treat the register's value as constant, so that its value
|
GCC to treat the register's value as constant, so that its value
|
||||||
can be rematerialized on demand. */
|
can be rematerialized on demand. */
|
||||||
|
@ -2358,51 +2403,6 @@ mips_split_symbol (rtx temp, rtx addr, enum machine_mode mode, rtx *lo_sum_out)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wrap symbol or label BASE in an UNSPEC address of type SYMBOL_TYPE,
|
|
||||||
then add CONST_INT OFFSET to the result. */
|
|
||||||
|
|
||||||
static rtx
|
|
||||||
mips_unspec_address_offset (rtx base, rtx offset,
|
|
||||||
enum mips_symbol_type symbol_type)
|
|
||||||
{
|
|
||||||
base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base),
|
|
||||||
UNSPEC_ADDRESS_FIRST + symbol_type);
|
|
||||||
if (offset != const0_rtx)
|
|
||||||
base = gen_rtx_PLUS (Pmode, base, offset);
|
|
||||||
return gen_rtx_CONST (Pmode, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return an UNSPEC address with underlying address ADDRESS and symbol
|
|
||||||
type SYMBOL_TYPE. */
|
|
||||||
|
|
||||||
rtx
|
|
||||||
mips_unspec_address (rtx address, enum mips_symbol_type symbol_type)
|
|
||||||
{
|
|
||||||
rtx base, offset;
|
|
||||||
|
|
||||||
split_const (address, &base, &offset);
|
|
||||||
return mips_unspec_address_offset (base, offset, symbol_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If mips_unspec_address (ADDR, SYMBOL_TYPE) is a 32-bit value, add the
|
|
||||||
high part to BASE and return the result. Just return BASE otherwise.
|
|
||||||
TEMP is as for mips_force_temporary.
|
|
||||||
|
|
||||||
The returned expression can be used as the first operand to a LO_SUM. */
|
|
||||||
|
|
||||||
static rtx
|
|
||||||
mips_unspec_offset_high (rtx temp, rtx base, rtx addr,
|
|
||||||
enum mips_symbol_type symbol_type)
|
|
||||||
{
|
|
||||||
if (mips_split_p[symbol_type])
|
|
||||||
{
|
|
||||||
addr = gen_rtx_HIGH (Pmode, mips_unspec_address (addr, symbol_type));
|
|
||||||
addr = mips_force_temporary (temp, addr);
|
|
||||||
base = mips_force_temporary (temp, gen_rtx_PLUS (Pmode, addr, base));
|
|
||||||
}
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return a legitimate address for REG + OFFSET. TEMP is as for
|
/* Return a legitimate address for REG + OFFSET. TEMP is as for
|
||||||
mips_force_temporary; it is only needed when OFFSET is not a
|
mips_force_temporary; it is only needed when OFFSET is not a
|
||||||
SMALL_OPERAND. */
|
SMALL_OPERAND. */
|
||||||
|
@ -5208,6 +5208,49 @@ mips_end_function_definition (const char *name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if calls to X can use R_MIPS_CALL* relocations. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
mips_ok_for_lazy_binding_p (rtx x)
|
||||||
|
{
|
||||||
|
return (TARGET_USE_GOT
|
||||||
|
&& GET_CODE (x) == SYMBOL_REF
|
||||||
|
&& !mips_symbol_binds_local_p (x));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load function address ADDR into register DEST. SIBCALL_P is true
|
||||||
|
if the address is needed for a sibling call. Return true if we
|
||||||
|
used an explicit lazy-binding sequence. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
mips_load_call_address (rtx dest, rtx addr, bool sibcall_p)
|
||||||
|
{
|
||||||
|
/* If we're generating PIC, and this call is to a global function,
|
||||||
|
try to allow its address to be resolved lazily. This isn't
|
||||||
|
possible for sibcalls when $gp is call-saved because the value
|
||||||
|
of $gp on entry to the stub would be our caller's gp, not ours. */
|
||||||
|
if (TARGET_EXPLICIT_RELOCS
|
||||||
|
&& !(sibcall_p && TARGET_CALL_SAVED_GP)
|
||||||
|
&& mips_ok_for_lazy_binding_p (addr))
|
||||||
|
{
|
||||||
|
rtx high, lo_sum_symbol;
|
||||||
|
|
||||||
|
high = mips_unspec_offset_high (dest, pic_offset_table_rtx,
|
||||||
|
addr, SYMBOL_GOTOFF_CALL);
|
||||||
|
lo_sum_symbol = mips_unspec_address (addr, SYMBOL_GOTOFF_CALL);
|
||||||
|
if (Pmode == SImode)
|
||||||
|
emit_insn (gen_load_callsi (dest, high, lo_sum_symbol));
|
||||||
|
else
|
||||||
|
emit_insn (gen_load_calldi (dest, high, lo_sum_symbol));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mips_emit_move (dest, addr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* A chained list of functions for which mips16_build_call_stub has already
|
/* A chained list of functions for which mips16_build_call_stub has already
|
||||||
generated a stub. NAME is the name of the function and FP_RET_P is true
|
generated a stub. NAME is the name of the function and FP_RET_P is true
|
||||||
if the function returns a value in floating-point registers. */
|
if the function returns a value in floating-point registers. */
|
||||||
|
@ -5668,49 +5711,6 @@ mips16_build_call_stub (rtx retval, rtx fn, rtx args_size, int fp_code)
|
||||||
return insn;
|
return insn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true if calls to X can use R_MIPS_CALL* relocations. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
mips_ok_for_lazy_binding_p (rtx x)
|
|
||||||
{
|
|
||||||
return (TARGET_USE_GOT
|
|
||||||
&& GET_CODE (x) == SYMBOL_REF
|
|
||||||
&& !mips_symbol_binds_local_p (x));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load function address ADDR into register DEST. SIBCALL_P is true
|
|
||||||
if the address is needed for a sibling call. Return true if we
|
|
||||||
used an explicit lazy-binding sequence. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
mips_load_call_address (rtx dest, rtx addr, bool sibcall_p)
|
|
||||||
{
|
|
||||||
/* If we're generating PIC, and this call is to a global function,
|
|
||||||
try to allow its address to be resolved lazily. This isn't
|
|
||||||
possible for sibcalls when $gp is call-saved because the value
|
|
||||||
of $gp on entry to the stub would be our caller's gp, not ours. */
|
|
||||||
if (TARGET_EXPLICIT_RELOCS
|
|
||||||
&& !(sibcall_p && TARGET_CALL_SAVED_GP)
|
|
||||||
&& mips_ok_for_lazy_binding_p (addr))
|
|
||||||
{
|
|
||||||
rtx high, lo_sum_symbol;
|
|
||||||
|
|
||||||
high = mips_unspec_offset_high (dest, pic_offset_table_rtx,
|
|
||||||
addr, SYMBOL_GOTOFF_CALL);
|
|
||||||
lo_sum_symbol = mips_unspec_address (addr, SYMBOL_GOTOFF_CALL);
|
|
||||||
if (Pmode == SImode)
|
|
||||||
emit_insn (gen_load_callsi (dest, high, lo_sum_symbol));
|
|
||||||
else
|
|
||||||
emit_insn (gen_load_calldi (dest, high, lo_sum_symbol));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mips_emit_move (dest, addr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Expand a "call", "sibcall", "call_value" or "sibcall_value" instruction.
|
/* Expand a "call", "sibcall", "call_value" or "sibcall_value" instruction.
|
||||||
RESULT is where the result will go (null for "call"s and "sibcall"s),
|
RESULT is where the result will go (null for "call"s and "sibcall"s),
|
||||||
ADDR is the address of the function, ARGS_SIZE is the size of the
|
ADDR is the address of the function, ARGS_SIZE is the size of the
|
||||||
|
@ -7884,6 +7884,19 @@ mips_function_has_gp_insn (void)
|
||||||
return cfun->machine->has_gp_insn_p;
|
return cfun->machine->has_gp_insn_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if the current function returns its value in a floating-point
|
||||||
|
register in MIPS16 mode. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
mips16_cfun_returns_in_fpr_p (void)
|
||||||
|
{
|
||||||
|
tree return_type = DECL_RESULT (current_function_decl);
|
||||||
|
return (TARGET_MIPS16
|
||||||
|
&& TARGET_HARD_FLOAT_ABI
|
||||||
|
&& !aggregate_value_p (return_type, current_function_decl)
|
||||||
|
&& mips_return_mode_in_fpr_p (DECL_MODE (return_type)));
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the register that should be used as the global pointer
|
/* Return the register that should be used as the global pointer
|
||||||
within this function. Return 0 if the function doesn't need
|
within this function. Return 0 if the function doesn't need
|
||||||
a global pointer. */
|
a global pointer. */
|
||||||
|
@ -7942,19 +7955,6 @@ mips_global_pointer (void)
|
||||||
return GLOBAL_POINTER_REGNUM;
|
return GLOBAL_POINTER_REGNUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true if the current function returns its value in a floating-point
|
|
||||||
register in MIPS16 mode. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
mips16_cfun_returns_in_fpr_p (void)
|
|
||||||
{
|
|
||||||
tree return_type = DECL_RESULT (current_function_decl);
|
|
||||||
return (TARGET_MIPS16
|
|
||||||
&& TARGET_HARD_FLOAT_ABI
|
|
||||||
&& !aggregate_value_p (return_type, current_function_decl)
|
|
||||||
&& mips_return_mode_in_fpr_p (DECL_MODE (return_type)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return true if the current function must save register REGNO. */
|
/* Return true if the current function must save register REGNO. */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|
Loading…
Reference in New Issue