mips-protos.h (mips16_gp_pseudo_reg): Remove.
* config/mips/mips-protos.h (mips16_gp_pseudo_reg): Remove. * config/mips/mips.h (LEGITIMATE_CONSTANT_P): Remove orphaned comment. * config/mips/mips.c (mips_reloc_offset_ok_p): New function. (mips_classify_constant): Use it. (mips_splittable_symbol_p): Add an offset argument. (mips_classify_address): Adjust call accordingly. (mips_legitimize_symbol): Handle sdata references with LO_SUM rather than a relocation unspec. Update call to mips_splittable_symbol_p. Generalize the code that copes with symbols + invalid offsets. (print_operand): Allow '%R' to be applied to small data addresses. (mips_reloc_string): Remove RELOC_GPREL16. (mips_sdata_pointer): Renamed from mips16_gp_pseudo_reg. Return $gp for TARGET_EXPLICIT_RELOCS. Return null if we can't use gp-relative relocation operators. * config/mips/mips.md (RELOC_GPREL16): Remove. Shuffle other reloc constants accordingly. From-SVN: r71876
This commit is contained in:
parent
c67e6e1492
commit
d34053edb7
@ -1,3 +1,22 @@
|
||||
2003-09-28 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* config/mips/mips-protos.h (mips16_gp_pseudo_reg): Remove.
|
||||
* config/mips/mips.h (LEGITIMATE_CONSTANT_P): Remove orphaned comment.
|
||||
* config/mips/mips.c (mips_reloc_offset_ok_p): New function.
|
||||
(mips_classify_constant): Use it.
|
||||
(mips_splittable_symbol_p): Add an offset argument.
|
||||
(mips_classify_address): Adjust call accordingly.
|
||||
(mips_legitimize_symbol): Handle sdata references with LO_SUM rather
|
||||
than a relocation unspec. Update call to mips_splittable_symbol_p.
|
||||
Generalize the code that copes with symbols + invalid offsets.
|
||||
(print_operand): Allow '%R' to be applied to small data addresses.
|
||||
(mips_reloc_string): Remove RELOC_GPREL16.
|
||||
(mips_sdata_pointer): Renamed from mips16_gp_pseudo_reg. Return $gp
|
||||
for TARGET_EXPLICIT_RELOCS. Return null if we can't use gp-relative
|
||||
relocation operators.
|
||||
* config/mips/mips.md (RELOC_GPREL16): Remove. Shuffle other reloc
|
||||
constants accordingly.
|
||||
|
||||
2003-09-27 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* toplev.c (flag_evaluation_order): New global variable.
|
||||
|
@ -128,7 +128,6 @@ extern enum reg_class mips_secondary_reload_class (enum reg_class,
|
||||
rtx, int);
|
||||
extern int mips_class_max_nregs (enum reg_class, enum machine_mode);
|
||||
extern bool mips_valid_pointer_mode (enum machine_mode);
|
||||
extern struct rtx_def *mips16_gp_pseudo_reg (void);
|
||||
extern int build_mips16_call_stub (rtx, rtx, rtx, int);
|
||||
extern int mips_register_move_cost (enum machine_mode, enum reg_class,
|
||||
enum reg_class);
|
||||
|
@ -170,6 +170,8 @@ struct mips_arg_info;
|
||||
struct mips_constant_info;
|
||||
struct mips_address_info;
|
||||
struct mips_integer_op;
|
||||
|
||||
static bool mips_reloc_offset_ok_p (int, HOST_WIDE_INT);
|
||||
static enum mips_constant_type
|
||||
mips_classify_constant (struct mips_constant_info *, rtx);
|
||||
static enum mips_symbol_type mips_classify_symbol (rtx);
|
||||
@ -179,7 +181,7 @@ static bool mips_symbolic_address_p (rtx, HOST_WIDE_INT,
|
||||
static enum mips_address_type
|
||||
mips_classify_address (struct mips_address_info *, rtx,
|
||||
enum machine_mode, int, int);
|
||||
static bool mips_splittable_symbol_p (enum mips_symbol_type);
|
||||
static bool mips_splittable_symbol_p (enum mips_symbol_type, HOST_WIDE_INT);
|
||||
static int mips_symbol_insns (enum mips_symbol_type);
|
||||
static bool mips16_unextended_reference_p (enum machine_mode mode, rtx, rtx);
|
||||
static rtx mips_reloc (rtx, int);
|
||||
@ -235,6 +237,7 @@ static void mips_select_section (tree, int, unsigned HOST_WIDE_INT)
|
||||
ATTRIBUTE_UNUSED;
|
||||
static bool mips_in_small_data_p (tree);
|
||||
static void mips_encode_section_info (tree, rtx, int);
|
||||
static rtx mips_sdata_pointer (void);
|
||||
static void mips16_fp_args (FILE *, int, int);
|
||||
static void build_mips16_function_stub (FILE *);
|
||||
static void mips16_optimize_gp (void);
|
||||
@ -785,6 +788,40 @@ const struct mips_cpu_info mips_cpu_info_table[] = {
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Return true if RELOC is a valid relocation number and OFFSET can be
|
||||
added to the relocation symbol.
|
||||
|
||||
Note that OFFSET might not refer to part of the object. For example,
|
||||
in an expression like x[i - 0x12345], we might try to take the address
|
||||
of "x - 0x12345". */
|
||||
|
||||
static bool
|
||||
mips_reloc_offset_ok_p (int reloc, HOST_WIDE_INT offset)
|
||||
{
|
||||
switch (reloc)
|
||||
{
|
||||
case RELOC_GOT_PAGE:
|
||||
/* The linker should provide enough page entries to cope with
|
||||
16-bit offsets from a valid segment address. */
|
||||
return SMALL_OPERAND (offset);
|
||||
|
||||
case RELOC_GOT_HI:
|
||||
case RELOC_GOT_LO:
|
||||
case RELOC_GOT_DISP:
|
||||
case RELOC_CALL16:
|
||||
case RELOC_CALL_HI:
|
||||
case RELOC_CALL_LO:
|
||||
case RELOC_LOADGP_HI:
|
||||
case RELOC_LOADGP_LO:
|
||||
/* These relocations should be applied to bare symbols only. */
|
||||
return offset == 0;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If X is one of the constants described by mips_constant_type,
|
||||
store its components in INFO and return its type. */
|
||||
|
||||
@ -806,25 +843,10 @@ mips_classify_constant (struct mips_constant_info *info, rtx x)
|
||||
x = XEXP (x, 0);
|
||||
}
|
||||
info->symbol = x;
|
||||
if (GET_CODE (x) == UNSPEC)
|
||||
switch (XINT (x, 1))
|
||||
{
|
||||
case RELOC_GPREL16:
|
||||
case RELOC_GOT_PAGE:
|
||||
/* These relocations can be applied to symbols with offsets. */
|
||||
return CONSTANT_RELOC;
|
||||
|
||||
case RELOC_GOT_HI:
|
||||
case RELOC_GOT_LO:
|
||||
case RELOC_GOT_DISP:
|
||||
case RELOC_CALL16:
|
||||
case RELOC_CALL_HI:
|
||||
case RELOC_CALL_LO:
|
||||
case RELOC_LOADGP_HI:
|
||||
case RELOC_LOADGP_LO:
|
||||
/* These relocations should be applied to bare symbols only. */
|
||||
return (info->offset == 0 ? CONSTANT_RELOC : CONSTANT_NONE);
|
||||
}
|
||||
if (GET_CODE (x) == UNSPEC
|
||||
&& mips_reloc_offset_ok_p (XINT (x, 1), info->offset))
|
||||
return CONSTANT_RELOC;
|
||||
}
|
||||
if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
|
||||
return CONSTANT_SYMBOLIC;
|
||||
@ -997,7 +1019,8 @@ mips_classify_address (struct mips_address_info *info, rtx x,
|
||||
&& mips_valid_base_register_p (XEXP (x, 0), mode, strict)
|
||||
&& (mips_classify_constant (&info->c, XEXP (x, 1))
|
||||
== CONSTANT_SYMBOLIC)
|
||||
&& mips_splittable_symbol_p (mips_classify_symbol (info->c.symbol)))
|
||||
&& mips_splittable_symbol_p (mips_classify_symbol (info->c.symbol),
|
||||
info->c.offset))
|
||||
{
|
||||
info->reg = XEXP (x, 0);
|
||||
info->offset = XEXP (x, 1);
|
||||
@ -1027,16 +1050,28 @@ mips_classify_address (struct mips_address_info *info, rtx x,
|
||||
}
|
||||
|
||||
/* Return true if symbols of the given type can be split into a
|
||||
HIGH/LO_SUM pair. */
|
||||
high part and a LO_SUM. In the case of small data symbols,
|
||||
the high part will be $gp. */
|
||||
|
||||
static bool
|
||||
mips_splittable_symbol_p (enum mips_symbol_type type)
|
||||
mips_splittable_symbol_p (enum mips_symbol_type type, HOST_WIDE_INT offset)
|
||||
{
|
||||
if (TARGET_EXPLICIT_RELOCS)
|
||||
return (type == SYMBOL_GENERAL || type == SYMBOL_GOT_LOCAL);
|
||||
if (mips_split_addresses)
|
||||
return (type == SYMBOL_GENERAL);
|
||||
return false;
|
||||
switch (type)
|
||||
{
|
||||
case SYMBOL_GENERAL:
|
||||
return TARGET_EXPLICIT_RELOCS || mips_split_addresses;
|
||||
|
||||
case SYMBOL_GOT_LOCAL:
|
||||
return TARGET_EXPLICIT_RELOCS && SMALL_OPERAND (offset);
|
||||
|
||||
case SYMBOL_SMALL_DATA:
|
||||
return ((TARGET_EXPLICIT_RELOCS || TARGET_MIPS16)
|
||||
&& (offset == 0
|
||||
|| (offset > 0 && offset <= mips_section_threshold)));
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1642,6 +1677,7 @@ mips_emit_high (rtx dest, rtx addr)
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
/* See if *XLOC is a symbolic constant that can be reduced in some way.
|
||||
If it is, set *XLOC to the reduced expression and return true.
|
||||
The new expression will be both a legitimate address and a legitimate
|
||||
@ -1663,46 +1699,27 @@ mips_legitimize_symbol (rtx dest, rtx *xloc, int offsetable_p)
|
||||
|
||||
symbol_type = mips_classify_symbol (c.symbol);
|
||||
|
||||
/* Convert a mips16 reference to the small data section into
|
||||
an address of the form:
|
||||
|
||||
(plus BASE (const (plus (unspec [SYMBOL] UNSPEC_GPREL) OFFSET)))
|
||||
|
||||
BASE is the pseudo created by mips16_gp_pseudo_reg.
|
||||
The (const ...) may include an offset. */
|
||||
if (TARGET_MIPS16
|
||||
&& symbol_type == SYMBOL_SMALL_DATA
|
||||
&& !no_new_pseudos)
|
||||
/* If a non-offsetable address is OK, try splitting it into a
|
||||
high part and a LO_SUM. */
|
||||
if (!offsetable_p && mips_splittable_symbol_p (symbol_type, c.offset))
|
||||
{
|
||||
*xloc = gen_rtx_PLUS (Pmode, mips16_gp_pseudo_reg (),
|
||||
mips_reloc (*xloc, RELOC_GPREL16));
|
||||
return true;
|
||||
if (symbol_type == SYMBOL_SMALL_DATA)
|
||||
x = mips_sdata_pointer ();
|
||||
else
|
||||
x = mips_emit_high (dest, *xloc);
|
||||
if (x != 0)
|
||||
{
|
||||
*xloc = gen_rtx_LO_SUM (Pmode, x, copy_rtx (*xloc));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Likewise for normal-mode code. In this case we can use $gp
|
||||
as a base register. */
|
||||
/* If the offset is nonzero, move the symbol into a register (always valid)
|
||||
and add the constant in afterwards. This requires an extra temporary if
|
||||
the offset isn't a signed 16-bit number.
|
||||
|
||||
For mips16, it's better to force the constant into memory instead. */
|
||||
if (!TARGET_MIPS16
|
||||
&& TARGET_EXPLICIT_RELOCS
|
||||
&& symbol_type == SYMBOL_SMALL_DATA)
|
||||
{
|
||||
*xloc = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
|
||||
mips_reloc (*xloc, RELOC_GPREL16));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If a non-offsetable address is OK, convert general symbols into
|
||||
a HIGH/LO_SUM pair. */
|
||||
if (!offsetable_p && mips_splittable_symbol_p (symbol_type))
|
||||
{
|
||||
x = mips_emit_high (dest, *xloc);
|
||||
*xloc = gen_rtx_LO_SUM (Pmode, x, copy_rtx (*xloc));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If generating PIC, and ADDR is a global symbol with an offset,
|
||||
load the symbol into a register and apply the offset separately.
|
||||
We need a temporary when adding large offsets. */
|
||||
if (symbol_type == SYMBOL_GOT_GLOBAL
|
||||
&& c.offset != 0
|
||||
&& (SMALL_OPERAND (c.offset) || dest == 0))
|
||||
{
|
||||
@ -5257,17 +5274,7 @@ print_operand (FILE *file, rtx op, int letter)
|
||||
|
||||
code = GET_CODE (op);
|
||||
|
||||
if (letter == 'R')
|
||||
{
|
||||
if (TARGET_ABICALLS && TARGET_NEWABI)
|
||||
fputs ("%got_ofst(", file);
|
||||
else
|
||||
fputs ("%lo(", file);
|
||||
output_addr_const (file, op);
|
||||
fputc (')', file);
|
||||
}
|
||||
|
||||
else if (letter == 'h')
|
||||
if (letter == 'h')
|
||||
{
|
||||
if (GET_CODE (op) != HIGH)
|
||||
abort ();
|
||||
@ -5403,8 +5410,22 @@ print_operand (FILE *file, rtx op, int letter)
|
||||
else
|
||||
switch (mips_classify_constant (&c, op))
|
||||
{
|
||||
case CONSTANT_NONE:
|
||||
case CONSTANT_SYMBOLIC:
|
||||
if (letter == 'R')
|
||||
{
|
||||
if (mips_classify_symbol (c.symbol) == SYMBOL_SMALL_DATA)
|
||||
fputs (TARGET_MIPS16 ? "%gprel(" : "%gp_rel(", file);
|
||||
else if (TARGET_ABICALLS && TARGET_NEWABI)
|
||||
fputs ("%got_ofst(", file);
|
||||
else
|
||||
fputs ("%lo(", file);
|
||||
output_addr_const (file, op);
|
||||
fputc (')', file);
|
||||
break;
|
||||
}
|
||||
/* ... fall through ... */
|
||||
|
||||
case CONSTANT_NONE:
|
||||
output_addr_const (file, op);
|
||||
break;
|
||||
|
||||
@ -5430,7 +5451,6 @@ mips_reloc_string (int reloc)
|
||||
{
|
||||
switch (reloc)
|
||||
{
|
||||
case RELOC_GPREL16: return (TARGET_MIPS16 ? "%gprel(" : "%gp_rel(");
|
||||
case RELOC_GOT_HI: return "%got_hi(";
|
||||
case RELOC_GOT_LO: return "%got_lo(";
|
||||
case RELOC_GOT_PAGE: return (TARGET_NEWABI ? "%got_page(" : "%got(");
|
||||
@ -7768,13 +7788,22 @@ mips_valid_pointer_mode (enum machine_mode mode)
|
||||
}
|
||||
|
||||
|
||||
/* For each mips16 function which refers to GP relative symbols, we
|
||||
/* If we can access small data directly (using gp-relative relocation
|
||||
operators) return the small data pointer, otherwise return null.
|
||||
|
||||
For each mips16 function which refers to GP relative symbols, we
|
||||
use a pseudo register, initialized at the start of the function, to
|
||||
hold the $gp value. */
|
||||
|
||||
rtx
|
||||
mips16_gp_pseudo_reg (void)
|
||||
static rtx
|
||||
mips_sdata_pointer (void)
|
||||
{
|
||||
if (TARGET_EXPLICIT_RELOCS)
|
||||
return pic_offset_table_rtx;
|
||||
|
||||
if (!TARGET_MIPS16 || no_new_pseudos)
|
||||
return 0;
|
||||
|
||||
if (cfun->machine->mips16_gp_pseudo_rtx == NULL_RTX)
|
||||
{
|
||||
rtx const_gp;
|
||||
|
@ -2605,20 +2605,6 @@ typedef struct mips_args {
|
||||
#define CONSTANT_ADDRESS_P(X) \
|
||||
(CONSTANT_P (X) && mips_legitimate_address_p (SImode, X, 0))
|
||||
|
||||
|
||||
/* Nonzero if the constant value X is a legitimate general operand.
|
||||
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
|
||||
|
||||
At present, GAS doesn't understand li.[sd], so don't allow it
|
||||
to be generated at present. Also, the MIPS assembler does not
|
||||
grok li.d Infinity. */
|
||||
|
||||
/* ??? SGI Irix 6 assembler fails for CONST address, so reject them.
|
||||
Note that the Irix 6 assembler problem may already be fixed.
|
||||
Note also that the GET_CODE (X) == CONST test catches the mips16
|
||||
gp pseudo reg (see mips16_gp_pseudo_reg) deciding it is not
|
||||
a LEGITIMATE_CONSTANT. If we ever want mips16 and ABI_N32 or
|
||||
ABI_64 to work together, we'll need to fix this. */
|
||||
#define LEGITIMATE_CONSTANT_P(X) (mips_const_insns (X) > 0)
|
||||
|
||||
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
|
||||
|
@ -58,16 +58,15 @@
|
||||
;; are really only available for n32 and n64. However, it is convenient
|
||||
;; to reuse them for SVR4 PIC, where they represent the local and global
|
||||
;; forms of R_MIPS_GOT16.
|
||||
(RELOC_GPREL16 100)
|
||||
(RELOC_GOT_HI 101)
|
||||
(RELOC_GOT_LO 102)
|
||||
(RELOC_GOT_PAGE 103)
|
||||
(RELOC_GOT_DISP 104)
|
||||
(RELOC_CALL16 105)
|
||||
(RELOC_CALL_HI 106)
|
||||
(RELOC_CALL_LO 107)
|
||||
(RELOC_LOADGP_HI 108)
|
||||
(RELOC_LOADGP_LO 109)])
|
||||
(RELOC_GOT_HI 100)
|
||||
(RELOC_GOT_LO 101)
|
||||
(RELOC_GOT_PAGE 102)
|
||||
(RELOC_GOT_DISP 103)
|
||||
(RELOC_CALL16 104)
|
||||
(RELOC_CALL_HI 105)
|
||||
(RELOC_CALL_LO 106)
|
||||
(RELOC_LOADGP_HI 107)
|
||||
(RELOC_LOADGP_LO 108)])
|
||||
|
||||
;; ....................
|
||||
;;
|
||||
|
@ -1,3 +1,8 @@
|
||||
2003-09-28 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* gcc.c-torture/execute/20030928-1.c: New test.
|
||||
* gcc.dg/torture/mips-sdata-1.c (f): Refer to x[0] rather than x[3].
|
||||
|
||||
2003-09-27 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
* g++.dg/opt/unroll1.C: New test.
|
||||
|
32
gcc/testsuite/gcc.c-torture/execute/20030928-1.c
Normal file
32
gcc/testsuite/gcc.c-torture/execute/20030928-1.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include <limits.h>
|
||||
|
||||
#if INT_MAX <= 32767
|
||||
int main () { exit (0); }
|
||||
#else
|
||||
void get_addrs (const char**x, int *y)
|
||||
{
|
||||
x[0] = "a1111" + (y[0] - 0x10000) * 2;
|
||||
x[1] = "a1112" + (y[1] - 0x20000) * 2;
|
||||
x[2] = "a1113" + (y[2] - 0x30000) * 2;
|
||||
x[3] = "a1114" + (y[3] - 0x40000) * 2;
|
||||
x[4] = "a1115" + (y[4] - 0x50000) * 2;
|
||||
x[5] = "a1116" + (y[5] - 0x60000) * 2;
|
||||
x[6] = "a1117" + (y[6] - 0x70000) * 2;
|
||||
x[7] = "a1118" + (y[7] - 0x80000) * 2;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
const char *x[8];
|
||||
int y[8];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
y[i] = 0x10000 * (i + 1);
|
||||
get_addrs (x, y);
|
||||
for (i = 0; i < 8; i++)
|
||||
if (*x[i] != 'a')
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
||||
#endif
|
@ -5,6 +5,6 @@
|
||||
struct s { int x[4]; };
|
||||
struct s my_struct __attribute__((__section__(".sdata")));
|
||||
|
||||
int f() { return my_struct.x[3]; }
|
||||
int f() { return my_struct.x[0]; }
|
||||
|
||||
/* { dg-final { scan-assembler {gp_?rel\(my_struct} } } */
|
||||
|
Loading…
Reference in New Issue
Block a user