Commit e245bd81 by Richard Sandiford Committed by Richard Sandiford

mips-protos.h (enum mips_symbol_type): Move from mips.h.

	* config/mips/mips-protos.h (enum mips_symbol_type): Move from mips.h.
	(NUM_SYMBOL_TYPES): Likewise.
	(SYMBOL_64_HIGH, SYMBOL_64_MID, SYMBOL_64_LOW): New symbol types.
	(mips_unspec_address): Declare.
	(mips_gotoff_page, mips_gotoff_global): Delete.
	* config/mips/mips.h (PREDICATE_CODES): Add general_symbolic_operand.
	* config/mips/mips.c (enum mips_symbol_type, NUM_SYMBOL_TYPES): Delete.
	(mips_symbolic_constant_p, mips_symbolic_address_p)
	(mips_symbol_insns): Handle new symbol types.
	(general_symbolic_operand): New predicate.
	(mips_unspec_address): Make extern.
	(mips_gotoff_page, mips_gotoff_global): Delete.
	(override_options): Allow -mabi=64 -mno-abicalls -mexplicit-relocs.
	Handle new symbol types.
	* config/mips/mips.md (*lea_high64, *lea64): New patterns.
	(*xgot_hi[sd]i, *xgot_lo[sd]i, *got_disp[sd]i, *got_disp[sd]i): Call
	mips_unspec_address directly.
	* doc/invoke.texi: Remove the -mabi=64 -mno-abicalls exception from
	the documentation of -mexplicit-relocs.

From-SVN: r78718
parent d0fe5ad3
2004-03-01 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips-protos.h (enum mips_symbol_type): Move from mips.h.
(NUM_SYMBOL_TYPES): Likewise.
(SYMBOL_64_HIGH, SYMBOL_64_MID, SYMBOL_64_LOW): New symbol types.
(mips_unspec_address): Declare.
(mips_gotoff_page, mips_gotoff_global): Delete.
* config/mips/mips.h (PREDICATE_CODES): Add general_symbolic_operand.
* config/mips/mips.c (enum mips_symbol_type, NUM_SYMBOL_TYPES): Delete.
(mips_symbolic_constant_p, mips_symbolic_address_p)
(mips_symbol_insns): Handle new symbol types.
(general_symbolic_operand): New predicate.
(mips_unspec_address): Make extern.
(mips_gotoff_page, mips_gotoff_global): Delete.
(override_options): Allow -mabi=64 -mno-abicalls -mexplicit-relocs.
Handle new symbol types.
* config/mips/mips.md (*lea_high64, *lea64): New patterns.
(*xgot_hi[sd]i, *xgot_lo[sd]i, *got_disp[sd]i, *got_disp[sd]i): Call
mips_unspec_address directly.
* doc/invoke.texi: Remove the -mabi=64 -mno-abicalls exception from
the documentation of -mexplicit-relocs.
2004-03-01 Jeff Law <law@redhat.com>
* fold-const.c (fold): An equality comparison of a non-weak object
......
......@@ -26,15 +26,76 @@ Boston, MA 02111-1307, USA. */
#ifndef GCC_MIPS_PROTOS_H
#define GCC_MIPS_PROTOS_H
/* Classifies a SYMBOL_REF, LABEL_REF or UNSPEC address.
SYMBOL_GENERAL
Used when none of the below apply.
SYMBOL_SMALL_DATA
The symbol refers to something in a small data section.
SYMBOL_CONSTANT_POOL
The symbol refers to something in the mips16 constant pool.
SYMBOL_GOT_LOCAL
The symbol refers to local data that will be found using
the global offset table.
SYMBOL_GOT_GLOBAL
Likewise non-local data.
SYMBOL_GOTOFF_PAGE
An UNSPEC wrapper around a SYMBOL_GOT_LOCAL. It represents the
offset from _gp of a GOT page entry.
SYMBOL_GOTOFF_GLOBAL
An UNSPEC wrapper around a SYMBOL_GOT_GLOBAL. It represents the
the offset from _gp of the symbol's GOT entry.
SYMBOL_GOTOFF_CALL
Like SYMBOL_GOTOFF_GLOBAL, but used when calling a global function.
The GOT entry is allowed to point to a stub rather than to the
function itself.
SYMBOL_GOTOFF_LOADGP
An UNSPEC wrapper around a function's address. It represents the
offset of _gp from the start of the function.
SYMBOL_64_HIGH
For a 64-bit symbolic address X, this is the value of
(%highest(X) << 16) + %higher(X).
SYMBOL_64_MID
For a 64-bit symbolic address X, this is the value of
(%higher(X) << 16) + %hi(X).
SYMBOL_64_LOW
For a 64-bit symbolic address X, this is the value of
(%hi(X) << 16) + %lo(X). */
enum mips_symbol_type {
SYMBOL_GENERAL,
SYMBOL_SMALL_DATA,
SYMBOL_CONSTANT_POOL,
SYMBOL_GOT_LOCAL,
SYMBOL_GOT_GLOBAL,
SYMBOL_GOTOFF_PAGE,
SYMBOL_GOTOFF_GLOBAL,
SYMBOL_GOTOFF_CALL,
SYMBOL_GOTOFF_LOADGP,
SYMBOL_64_HIGH,
SYMBOL_64_MID,
SYMBOL_64_LOW
};
#define NUM_SYMBOL_TYPES (SYMBOL_64_LOW + 1)
extern int mips_regno_mode_ok_for_base_p (int, enum machine_mode, int);
extern int mips_address_insns (rtx, enum machine_mode);
extern int mips_const_insns (rtx);
extern int mips_fetch_insns (rtx);
extern int mips_idiv_insns (void);
extern bool mips_legitimate_address_p (enum machine_mode, rtx, int);
extern rtx mips_unspec_address (rtx, enum mips_symbol_type);
extern bool mips_legitimize_address (rtx *, enum machine_mode);
extern rtx mips_gotoff_page (rtx);
extern rtx mips_gotoff_global (rtx);
extern bool mips_legitimize_move (enum machine_mode, rtx, rtx);
extern int m16_uimm3_b (rtx, enum machine_mode);
......
......@@ -105,53 +105,6 @@ enum internal_test {
multi-instruction addu sequence. Use 0x7fe0 to work around this. */
#define MIPS_MAX_FIRST_STACK_STEP (TARGET_MIPS16 ? 0x100 : 0x7fe0)
/* Classifies a SYMBOL_REF, LABEL_REF or UNSPEC address.
SYMBOL_GENERAL
Used when none of the below apply.
SYMBOL_SMALL_DATA
The symbol refers to something in a small data section.
SYMBOL_CONSTANT_POOL
The symbol refers to something in the mips16 constant pool.
SYMBOL_GOT_LOCAL
The symbol refers to local data that will be found using
the global offset table.
SYMBOL_GOT_GLOBAL
Likewise non-local data.
SYMBOL_GOTOFF_PAGE
An UNSPEC wrapper around a SYMBOL_GOT_LOCAL. It represents the
offset from _gp of a GOT page entry.
SYMBOL_GOTOFF_GLOBAL
An UNSPEC wrapper around a SYMBOL_GOT_GLOBAL. It represents the
the offset from _gp of the symbol's GOT entry.
SYMBOL_GOTOFF_CALL
Like SYMBOL_GOTOFF_GLOBAL, but used when calling a global function.
The GOT entry is allowed to point to a stub rather than to the
function itself.
SYMBOL_GOTOFF_LOADGP
An UNSPEC wrapper around a function's address. It represents the
offset of _gp from the start of the function. */
enum mips_symbol_type {
SYMBOL_GENERAL,
SYMBOL_SMALL_DATA,
SYMBOL_CONSTANT_POOL,
SYMBOL_GOT_LOCAL,
SYMBOL_GOT_GLOBAL,
SYMBOL_GOTOFF_PAGE,
SYMBOL_GOTOFF_GLOBAL,
SYMBOL_GOTOFF_CALL,
SYMBOL_GOTOFF_LOADGP
};
#define NUM_SYMBOL_TYPES (SYMBOL_GOTOFF_LOADGP + 1)
/* Classifies an address.
......@@ -196,7 +149,6 @@ static int mips_symbol_insns (enum mips_symbol_type);
static bool mips16_unextended_reference_p (enum machine_mode mode, rtx, rtx);
static rtx mips_force_temporary (rtx, rtx);
static rtx mips_split_symbol (rtx, rtx);
static rtx mips_unspec_address (rtx, enum mips_symbol_type);
static rtx mips_unspec_offset_high (rtx, rtx, rtx, enum mips_symbol_type);
static rtx mips_add_offset (rtx, HOST_WIDE_INT);
static unsigned int mips_build_shift (struct mips_integer_op *, HOST_WIDE_INT);
......@@ -951,6 +903,9 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
switch (*symbol_type)
{
case SYMBOL_GENERAL:
case SYMBOL_64_HIGH:
case SYMBOL_64_MID:
case SYMBOL_64_LOW:
/* If the target has 64-bit pointers and the object file only
supports 32-bit symbols, the values of those symbols will be
sign-extended. In this case we can't allow an arbitrary offset
......@@ -1068,6 +1023,9 @@ mips_symbolic_address_p (enum mips_symbol_type symbol_type,
case SYMBOL_GOTOFF_GLOBAL:
case SYMBOL_GOTOFF_CALL:
case SYMBOL_GOTOFF_LOADGP:
case SYMBOL_64_HIGH:
case SYMBOL_64_MID:
case SYMBOL_64_LOW:
return true;
}
abort ();
......@@ -1191,6 +1149,9 @@ mips_symbol_insns (enum mips_symbol_type type)
case SYMBOL_GOTOFF_GLOBAL:
case SYMBOL_GOTOFF_CALL:
case SYMBOL_GOTOFF_LOADGP:
case SYMBOL_64_HIGH:
case SYMBOL_64_MID:
case SYMBOL_64_LOW:
/* Check whether the offset is a 16- or 32-bit value. */
return mips_split_p[type] ? 2 : 1;
}
......@@ -1637,6 +1598,19 @@ symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
}
/* Return true if OP is a symbolic constant of type SYMBOL_GENERAL. */
int
general_symbolic_operand (rtx op, enum machine_mode mode)
{
enum mips_symbol_type symbol_type;
return ((mode == VOIDmode || mode == GET_MODE (op))
&& mips_symbolic_constant_p (op, &symbol_type)
&& symbol_type == SYMBOL_GENERAL);
}
/* Return true if we're generating PIC and OP is a global symbol. */
int
......@@ -1728,7 +1702,7 @@ mips_split_symbol (rtx temp, rtx addr)
/* Return an UNSPEC address with underlying address ADDRESS and symbol
type SYMBOL_TYPE. */
static rtx
rtx
mips_unspec_address (rtx address, enum mips_symbol_type symbol_type)
{
rtx base;
......@@ -1761,25 +1735,6 @@ mips_unspec_offset_high (rtx temp, rtx base, rtx addr,
}
/* Return the offset of a GOT page entry for local address ADDR. */
rtx
mips_gotoff_page (rtx addr)
{
return mips_unspec_address (addr, SYMBOL_GOTOFF_PAGE);
}
/* Return the offset of ADDR's GOT entry from _gp. ADDR is a
global_got_operand. */
rtx
mips_gotoff_global (rtx addr)
{
return mips_unspec_address (addr, SYMBOL_GOTOFF_GLOBAL);
}
/* Return a legitimate address for REG + OFFSET. This function will
create a temporary register if OFFSET is not a SMALL_OPERAND. */
......@@ -4861,15 +4816,6 @@ override_options (void)
else
mips_split_addresses = 0;
/* -mexplicit-relocs doesn't yet support non-PIC n64. We don't know
how to generate %highest/%higher/%hi/%lo sequences. */
if (mips_abi == ABI_64 && !TARGET_ABICALLS)
{
if ((target_flags_explicit & target_flags & MASK_EXPLICIT_RELOCS) != 0)
sorry ("non-PIC n64 with explicit relocations");
target_flags &= ~MASK_EXPLICIT_RELOCS;
}
/* Explicit relocations for "old" ABIs are a GNU extension. Unless
the user has said otherwise, assume that they are not available
with assemblers other than gas. */
......@@ -5065,11 +5011,34 @@ override_options (void)
/* Function to allocate machine-dependent function status. */
init_machine_status = &mips_init_machine_status;
if (TARGET_EXPLICIT_RELOCS || mips_split_addresses)
if (ABI_HAS_64BIT_SYMBOLS)
{
mips_split_p[SYMBOL_GENERAL] = true;
mips_hi_relocs[SYMBOL_GENERAL] = "%hi(";
mips_lo_relocs[SYMBOL_GENERAL] = "%lo(";
if (TARGET_EXPLICIT_RELOCS)
{
mips_split_p[SYMBOL_64_HIGH] = true;
mips_hi_relocs[SYMBOL_64_HIGH] = "%highest(";
mips_lo_relocs[SYMBOL_64_HIGH] = "%higher(";
mips_split_p[SYMBOL_64_MID] = true;
mips_hi_relocs[SYMBOL_64_MID] = "%higher(";
mips_lo_relocs[SYMBOL_64_MID] = "%hi(";
mips_split_p[SYMBOL_64_LOW] = true;
mips_hi_relocs[SYMBOL_64_LOW] = "%hi(";
mips_lo_relocs[SYMBOL_64_LOW] = "%lo(";
mips_split_p[SYMBOL_GENERAL] = true;
mips_lo_relocs[SYMBOL_GENERAL] = "%lo(";
}
}
else
{
if (TARGET_EXPLICIT_RELOCS || mips_split_addresses)
{
mips_split_p[SYMBOL_GENERAL] = true;
mips_hi_relocs[SYMBOL_GENERAL] = "%hi(";
mips_lo_relocs[SYMBOL_GENERAL] = "%lo(";
}
}
if (TARGET_MIPS16)
......
......@@ -2698,6 +2698,7 @@ typedef struct mips_args {
#define PREDICATE_CODES \
{"uns_arith_operand", { REG, CONST_INT, SUBREG, ADDRESSOF }}, \
{"symbolic_operand", { CONST, SYMBOL_REF, LABEL_REF }}, \
{"general_symbolic_operand", { CONST, SYMBOL_REF, LABEL_REF }}, \
{"global_got_operand", { CONST, SYMBOL_REF, LABEL_REF }}, \
{"local_got_operand", { CONST, SYMBOL_REF, LABEL_REF }}, \
{"const_arith_operand", { CONST_INT }}, \
......
......@@ -4233,6 +4233,67 @@ dsrl\t%3,%3,1\n\
[(set_attr "type" "store")
(set_attr "mode" "DI")])
;; An instruction to calculate the high part of a 64-bit SYMBOL_GENERAL.
;; The required value is:
;;
;; (%highest(op1) << 48) + (%higher(op1) << 32) + (%hi(op1) << 16)
;;
;; which translates to:
;;
;; lui op0,%highest(op1)
;; daddiu op0,op0,%higher(op1)
;; dsll op0,op0,16
;; daddiu op0,op0,%hi(op1)
;; dsll op0,op0,16
(define_insn_and_split "*lea_high64"
[(set (match_operand:DI 0 "register_operand" "=d")
(high:DI (match_operand:DI 1 "general_symbolic_operand" "")))]
"TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS"
"#"
"&& reload_completed"
[(set (match_dup 0) (high:DI (match_dup 2)))
(set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 2)))
(set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16)))
(set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 3)))
(set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16)))]
{
operands[2] = mips_unspec_address (operands[1], SYMBOL_64_HIGH);
operands[3] = mips_unspec_address (operands[1], SYMBOL_64_MID);
}
[(set_attr "length" "20")])
;; On most targets, the expansion of (lo_sum (high X) X) for a 64-bit
;; SYMBOL_GENERAL X will take 6 cycles. This next pattern allows combine
;; to merge the HIGH and LO_SUM parts of a move if the HIGH part is only
;; used once. We can then use the sequence:
;;
;; lui op0,%highest(op1)
;; lui op2,%hi(op1)
;; daddiu op0,op0,%higher(op1)
;; daddiu op2,op2,%lo(op1)
;; dsll32 op0,op0,0
;; daddu op0,op0,op2
;;
;; which takes 4 cycles on most superscalar targets.
(define_insn_and_split "*lea64"
[(set (match_operand:DI 0 "register_operand" "=d")
(match_operand:DI 1 "general_symbolic_operand" ""))
(clobber (match_scratch:DI 2 "=&d"))]
"TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS && cse_not_expected"
"#"
"&& reload_completed"
[(set (match_dup 0) (high:DI (match_dup 3)))
(set (match_dup 2) (high:DI (match_dup 4)))
(set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 3)))
(set (match_dup 2) (lo_sum:DI (match_dup 2) (match_dup 4)))
(set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32)))
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))]
{
operands[3] = mips_unspec_address (operands[1], SYMBOL_64_HIGH);
operands[4] = mips_unspec_address (operands[1], SYMBOL_64_LOW);
}
[(set_attr "length" "24")])
;; Insns to fetch a global symbol from a big GOT.
(define_insn_and_split "*xgot_hisi"
......@@ -4244,7 +4305,7 @@ dsrl\t%3,%3,1\n\
[(set (match_dup 0) (high:SI (match_dup 2)))
(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
{
operands[2] = mips_gotoff_global (operands[1]);
operands[2] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL);
operands[3] = pic_offset_table_rtx;
}
[(set_attr "got" "xgot_high")])
......@@ -4258,7 +4319,7 @@ dsrl\t%3,%3,1\n\
"&& reload_completed"
[(set (match_dup 0)
(unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_LOAD_GOT))]
{ operands[3] = mips_gotoff_global (operands[2]); }
{ operands[3] = mips_unspec_address (operands[2], SYMBOL_GOTOFF_GLOBAL); }
[(set_attr "got" "load")])
(define_insn_and_split "*xgot_hidi"
......@@ -4270,7 +4331,7 @@ dsrl\t%3,%3,1\n\
[(set (match_dup 0) (high:DI (match_dup 2)))
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
{
operands[2] = mips_gotoff_global (operands[1]);
operands[2] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL);
operands[3] = pic_offset_table_rtx;
}
[(set_attr "got" "xgot_high")])
......@@ -4284,7 +4345,7 @@ dsrl\t%3,%3,1\n\
"&& reload_completed"
[(set (match_dup 0)
(unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_LOAD_GOT))]
{ operands[3] = mips_gotoff_global (operands[2]); }
{ operands[3] = mips_unspec_address (operands[2], SYMBOL_GOTOFF_GLOBAL); }
[(set_attr "got" "load")])
;; Insns to fetch a global symbol from a normal GOT.
......@@ -4299,7 +4360,7 @@ dsrl\t%3,%3,1\n\
(unspec:SI [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))]
{
operands[2] = pic_offset_table_rtx;
operands[3] = mips_gotoff_global (operands[1]);
operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL);
}
[(set_attr "got" "load")])
......@@ -4313,7 +4374,7 @@ dsrl\t%3,%3,1\n\
(unspec:DI [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))]
{
operands[2] = pic_offset_table_rtx;
operands[3] = mips_gotoff_global (operands[1]);
operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL);
}
[(set_attr "got" "load")])
......@@ -4329,7 +4390,7 @@ dsrl\t%3,%3,1\n\
(unspec:SI [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))]
{
operands[2] = pic_offset_table_rtx;
operands[3] = mips_gotoff_page (operands[1]);
operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_PAGE);
}
[(set_attr "got" "load")])
......@@ -4343,7 +4404,7 @@ dsrl\t%3,%3,1\n\
(unspec:DI [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))]
{
operands[2] = pic_offset_table_rtx;
operands[3] = mips_gotoff_page (operands[1]);
operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_PAGE);
}
[(set_attr "got" "load")])
......
......@@ -7966,24 +7966,14 @@ Use (do not use) assembler relocation operators when dealing with symbolic
addresses. The alternative, selected by @option{-mno-explicit-relocs},
is to use assembler macros instead.
@option{-mexplicit-relocs} is usually the default if GCC was
configured to use an assembler that supports relocation operators.
However, there are two exceptions:
@itemize @bullet
@item
GCC is not yet able to generate explicit relocations for the combination
of @option{-mabi=64} and @option{-mno-abicalls}. This will be addressed
in a future release.
@item
The combination of @option{-mabicalls} and @option{-fno-unit-at-a-time}
@option{-mexplicit-relocs} is usually the default if GCC was configured
to use an assembler that supports relocation operators. However, the
combination of @option{-mabicalls} and @option{-fno-unit-at-a-time}
implies @option{-mno-explicit-relocs} unless explicitly overridden.
This is because, when generating abicalls, the choice of relocation
depends on whether a symbol is local or global. In some rare cases,
GCC will not be able to decide this until the whole compilation unit
has been read.
@end itemize
@item -mrnames
@itemx -mno-rnames
......
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