Commit 551cc6fd by Richard Henderson Committed by Richard Henderson

alpha.c (some_operand): Accept HIGH.

	* config/alpha/alpha.c (some_operand): Accept HIGH.
	(input_operand): Likewise; accept simple references to globals.
	(alpha_const_ok_for_letter_p): New, outlined from alpha.h.
	(alpha_const_double_ok_for_letter_p): Likewise.
	(alpha_extra_constraint): Likewise.
	(alpha_preferred_reload_class): Likewise.  Do not force
	symbolic constants to memory.
	(alpha_legitimate_address_p): Accept simple references
	to small_symbolic_operand.
	(alpha_legitimize_address): New arg scratch.  Be prepared to be
	called when no_new_pseudos.  Emit simple symbolic references.
	Split integers into low, high, and rest.
	(alpha_expand_mov): Use alpha_legitimize_address.
	(some_small_symbolic_mem_operand): New.
	(split_small_symbolic_mem_operand): New.
	* config/alpha/alpha-protos.h: Update.
	* config/alpha/alpha.h (CONST_OK_FOR_LETTER_P): Out-line.
	(CONST_DOUBLE_OK_FOR_LETTER_P): Likewise.
	(EXTRA_CONSTRAINT): Likewise.
	(PREFERRED_RELOAD_CLASS): Likewise.
	(LEGITIMIZE_ADDRESS): Update for alpha_legitimize_address change.
	(PREDICATE_CODES): Update.
	* config/alpha/alpha.md: New post-reload splitters to convert
	simplfied symbolic operands to the form that references $29.
	(divide expanders): Use emit_move_insn, not gen_movdi_er_high_g.
	(movdi_er_nofix, movdi_er_fix): Accept any symbolic operand.

From-SVN: r48531
parent 1eaea054
2002-01-04 Richard Henderson <rth@redhat.com>
* config/alpha/alpha.c (some_operand): Accept HIGH.
(input_operand): Likewise; accept simple references to globals.
(alpha_const_ok_for_letter_p): New, outlined from alpha.h.
(alpha_const_double_ok_for_letter_p): Likewise.
(alpha_extra_constraint): Likewise.
(alpha_preferred_reload_class): Likewise. Do not force
symbolic constants to memory.
(alpha_legitimate_address_p): Accept simple references
to small_symbolic_operand.
(alpha_legitimize_address): New arg scratch. Be prepared to be
called when no_new_pseudos. Emit simple symbolic references.
Split integers into low, high, and rest.
(alpha_expand_mov): Use alpha_legitimize_address.
(some_small_symbolic_mem_operand): New.
(split_small_symbolic_mem_operand): New.
* config/alpha/alpha-protos.h: Update.
* config/alpha/alpha.h (CONST_OK_FOR_LETTER_P): Out-line.
(CONST_DOUBLE_OK_FOR_LETTER_P): Likewise.
(EXTRA_CONSTRAINT): Likewise.
(PREFERRED_RELOAD_CLASS): Likewise.
(LEGITIMIZE_ADDRESS): Update for alpha_legitimize_address change.
(PREDICATE_CODES): Update.
* config/alpha/alpha.md: New post-reload splitters to convert
simplfied symbolic operands to the form that references $29.
(divide expanders): Use emit_move_insn, not gen_movdi_er_high_g.
(movdi_er_nofix, movdi_er_fix): Accept any symbolic operand.
2002-01-03 Richard Henderson <rth@redhat.com> 2002-01-03 Richard Henderson <rth@redhat.com>
* local-alloc.c (function_invariant_p): Update commentary. * local-alloc.c (function_invariant_p): Update commentary.
......
...@@ -59,6 +59,7 @@ extern int current_file_function_operand PARAMS ((rtx, enum machine_mode)); ...@@ -59,6 +59,7 @@ extern int current_file_function_operand PARAMS ((rtx, enum machine_mode));
extern int direct_call_operand PARAMS ((rtx, enum machine_mode)); extern int direct_call_operand PARAMS ((rtx, enum machine_mode));
extern int local_symbolic_operand PARAMS ((rtx, enum machine_mode)); extern int local_symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int small_symbolic_operand PARAMS ((rtx, enum machine_mode)); extern int small_symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int some_small_symbolic_mem_operand PARAMS ((rtx, enum machine_mode));
extern int global_symbolic_operand PARAMS ((rtx, enum machine_mode)); extern int global_symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int call_operand PARAMS ((rtx, enum machine_mode)); extern int call_operand PARAMS ((rtx, enum machine_mode));
extern int symbolic_operand PARAMS ((rtx, enum machine_mode)); extern int symbolic_operand PARAMS ((rtx, enum machine_mode));
...@@ -77,6 +78,10 @@ extern int normal_memory_operand PARAMS ((rtx, enum machine_mode)); ...@@ -77,6 +78,10 @@ extern int normal_memory_operand PARAMS ((rtx, enum machine_mode));
extern int reg_no_subreg_operand PARAMS ((rtx, enum machine_mode)); extern int reg_no_subreg_operand PARAMS ((rtx, enum machine_mode));
extern int addition_operation PARAMS ((rtx, enum machine_mode)); extern int addition_operation PARAMS ((rtx, enum machine_mode));
extern bool alpha_const_ok_for_letter_p PARAMS ((HOST_WIDE_INT, int));
extern bool alpha_const_double_ok_for_letter_p PARAMS ((rtx, int));
extern bool alpha_extra_constraint PARAMS ((rtx, int));
extern rtx alpha_tablejump_addr_vec PARAMS ((rtx)); extern rtx alpha_tablejump_addr_vec PARAMS ((rtx));
extern rtx alpha_tablejump_best_label PARAMS ((rtx)); extern rtx alpha_tablejump_best_label PARAMS ((rtx));
...@@ -85,11 +90,16 @@ extern rtx alpha_legitimize_address PARAMS ((rtx, rtx, enum machine_mode)); ...@@ -85,11 +90,16 @@ extern rtx alpha_legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
extern rtx alpha_legitimize_reload_address PARAMS ((rtx, enum machine_mode, extern rtx alpha_legitimize_reload_address PARAMS ((rtx, enum machine_mode,
int, int, int)); int, int, int));
extern rtx split_small_symbolic_mem_operand PARAMS ((rtx));
extern void get_aligned_mem PARAMS ((rtx, rtx *, rtx *)); extern void get_aligned_mem PARAMS ((rtx, rtx *, rtx *));
extern rtx get_unaligned_address PARAMS ((rtx, int)); extern rtx get_unaligned_address PARAMS ((rtx, int));
extern enum reg_class alpha_preferred_reload_class PARAMS ((rtx,
enum reg_class));
extern enum reg_class secondary_reload_class PARAMS ((enum reg_class, extern enum reg_class secondary_reload_class PARAMS ((enum reg_class,
enum machine_mode, enum machine_mode,
rtx, int)); rtx, int));
extern void alpha_set_memflags PARAMS ((rtx, rtx)); extern void alpha_set_memflags PARAMS ((rtx, rtx));
extern rtx alpha_emit_set_const PARAMS ((rtx, enum machine_mode, extern rtx alpha_emit_set_const PARAMS ((rtx, enum machine_mode,
HOST_WIDE_INT, int)); HOST_WIDE_INT, int));
......
...@@ -768,7 +768,7 @@ some_operand (op, mode) ...@@ -768,7 +768,7 @@ some_operand (op, mode)
switch (GET_CODE (op)) switch (GET_CODE (op))
{ {
case REG: case MEM: case CONST_DOUBLE: case CONST_INT: case LABEL_REF: case REG: case MEM: case CONST_DOUBLE: case CONST_INT: case LABEL_REF:
case SYMBOL_REF: case CONST: case SYMBOL_REF: case CONST: case HIGH:
return 1; return 1;
case SUBREG: case SUBREG:
...@@ -816,11 +816,22 @@ input_operand (op, mode) ...@@ -816,11 +816,22 @@ input_operand (op, mode)
case SYMBOL_REF: case SYMBOL_REF:
case CONST: case CONST:
if (TARGET_EXPLICIT_RELOCS) if (TARGET_EXPLICIT_RELOCS)
return 0; {
/* We don't split symbolic operands into something unintelligable
until after reload, but we do not wish non-small, non-global
symbolic operands to be reconstructed from their high/lo_sum
form. */
return (small_symbolic_operand (op, mode)
|| global_symbolic_operand (op, mode));
}
/* This handles both the Windows/NT and OSF cases. */ /* This handles both the Windows/NT and OSF cases. */
return mode == ptr_mode || mode == DImode; return mode == ptr_mode || mode == DImode;
case HIGH:
return (TARGET_EXPLICIT_RELOCS
&& local_symbolic_operand (XEXP (op, 0), mode));
case REG: case REG:
case ADDRESSOF: case ADDRESSOF:
return 1; return 1;
...@@ -1354,6 +1365,100 @@ addition_operation (op, mode) ...@@ -1354,6 +1365,100 @@ addition_operation (op, mode)
return 0; return 0;
} }
/* Implements CONST_OK_FOR_LETTER_P. Return true if the value matches
the range defined for C in [I-P]. */
bool
alpha_const_ok_for_letter_p (value, c)
HOST_WIDE_INT value;
int c;
{
switch (c)
{
case 'I':
/* An unsigned 8 bit constant. */
return (unsigned HOST_WIDE_INT) value < 0x100;
case 'J':
/* The constant zero. */
return value == 0;
case 'K':
/* A signed 16 bit constant. */
return (unsigned HOST_WIDE_INT) (value + 0x8000) < 0x10000;
case 'L':
/* A shifted signed 16 bit constant appropriate for LDAH. */
return ((value & 0xffff) == 0
&& ((value) >> 31 == -1 || value >> 31 == 0));
case 'M':
/* A constant that can be AND'ed with using a ZAP insn. */
return zap_mask (value);
case 'N':
/* A complemented unsigned 8 bit constant. */
return (unsigned HOST_WIDE_INT) (~ value) < 0x100;
case 'O':
/* A negated unsigned 8 bit constant. */
return (unsigned HOST_WIDE_INT) (- value) < 0x100;
case 'P':
/* The constant 1, 2 or 3. */
return value == 1 || value == 2 || value == 3;
default:
return false;
}
}
/* Implements CONST_DOUBLE_OK_FOR_LETTER_P. Return true if VALUE
matches for C in [GH]. */
bool
alpha_const_double_ok_for_letter_p (value, c)
rtx value;
int c;
{
switch (c)
{
case 'G':
/* The floating point zero constant. */
return (GET_MODE_CLASS (GET_MODE (value)) == MODE_FLOAT
&& value == CONST0_RTX (GET_MODE (value)));
case 'H':
/* A valid operand of a ZAP insn. */
return (GET_MODE (value) == VOIDmode
&& zap_mask (CONST_DOUBLE_LOW (value))
&& zap_mask (CONST_DOUBLE_HIGH (value)));
default:
return false;
}
}
/* Implements CONST_DOUBLE_OK_FOR_LETTER_P. Return true if VALUE
matches for C. */
bool
alpha_extra_constraint (value, c)
rtx value;
int c;
{
switch (c)
{
case 'Q':
return normal_memory_operand (value, VOIDmode);
case 'R':
return direct_call_operand (value, Pmode);
case 'S':
return (GET_CODE (value) == CONST_INT
&& (unsigned HOST_WIDE_INT) INTVAL (value) < 64);
case 'T':
return GET_CODE (value) == HIGH;
case 'U':
return TARGET_ABI_UNICOSMK && symbolic_operand (value, VOIDmode);
default:
return false;
}
}
/* Return 1 if this function can directly return via $26. */ /* Return 1 if this function can directly return via $26. */
int int
...@@ -1628,28 +1733,35 @@ alpha_legitimate_address_p (mode, x, strict) ...@@ -1628,28 +1733,35 @@ alpha_legitimate_address_p (mode, x, strict)
return true; return true;
} }
/* If we're managing explicit relocations, LO_SUM is valid. */ /* If we're managing explicit relocations, LO_SUM is valid, as
else if (TARGET_EXPLICIT_RELOCS && GET_CODE (x) == LO_SUM) are small data symbols. */
else if (TARGET_EXPLICIT_RELOCS)
{ {
rtx ofs = XEXP (x, 1); if (small_symbolic_operand (x, Pmode))
x = XEXP (x, 0);
/* Discard non-paradoxical subregs. */
if (GET_CODE (x) == SUBREG
&& (GET_MODE_SIZE (GET_MODE (x))
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
x = SUBREG_REG (x);
/* Must have a valid base register. */
if (! (REG_P (x)
&& (strict
? STRICT_REG_OK_FOR_BASE_P (x)
: NONSTRICT_REG_OK_FOR_BASE_P (x))))
return false;
/* The symbol must be local. */
if (local_symbolic_operand (ofs, Pmode))
return true; return true;
if (GET_CODE (x) == LO_SUM)
{
rtx ofs = XEXP (x, 1);
x = XEXP (x, 0);
/* Discard non-paradoxical subregs. */
if (GET_CODE (x) == SUBREG
&& (GET_MODE_SIZE (GET_MODE (x))
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
x = SUBREG_REG (x);
/* Must have a valid base register. */
if (! (REG_P (x)
&& (strict
? STRICT_REG_OK_FOR_BASE_P (x)
: NONSTRICT_REG_OK_FOR_BASE_P (x))))
return false;
/* The symbol must be local. */
if (local_symbolic_operand (ofs, Pmode))
return true;
}
} }
return false; return false;
...@@ -1659,9 +1771,9 @@ alpha_legitimate_address_p (mode, x, strict) ...@@ -1659,9 +1771,9 @@ alpha_legitimate_address_p (mode, x, strict)
to be legitimate. If we find one, return the new, valid address. */ to be legitimate. If we find one, return the new, valid address. */
rtx rtx
alpha_legitimize_address (x, oldx, mode) alpha_legitimize_address (x, scratch, mode)
rtx x; rtx x;
rtx oldx ATTRIBUTE_UNUSED; rtx scratch;
enum machine_mode mode ATTRIBUTE_UNUSED; enum machine_mode mode ATTRIBUTE_UNUSED;
{ {
HOST_WIDE_INT addend; HOST_WIDE_INT addend;
...@@ -1683,7 +1795,8 @@ alpha_legitimize_address (x, oldx, mode) ...@@ -1683,7 +1795,8 @@ alpha_legitimize_address (x, oldx, mode)
part of the CONST_INT. Then load FOO plus any high-order part of the part of the CONST_INT. Then load FOO plus any high-order part of the
CONST_INT into a register. Our address is (plus reg low-part-const). CONST_INT into a register. Our address is (plus reg low-part-const).
This is done to reduce the number of GOT entries. */ This is done to reduce the number of GOT entries. */
if (GET_CODE (x) == CONST if (!no_new_pseudos
&& GET_CODE (x) == CONST
&& GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT) && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
{ {
...@@ -1695,7 +1808,8 @@ alpha_legitimize_address (x, oldx, mode) ...@@ -1695,7 +1808,8 @@ alpha_legitimize_address (x, oldx, mode)
/* If we have a (plus reg const), emit the load as in (2), then add /* If we have a (plus reg const), emit the load as in (2), then add
the two registers, and finally generate (plus reg low-part-const) as the two registers, and finally generate (plus reg low-part-const) as
our address. */ our address. */
if (GET_CODE (x) == PLUS if (!no_new_pseudos
&& GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 0)) == REG && GET_CODE (XEXP (x, 0)) == REG
&& GET_CODE (XEXP (x, 1)) == CONST && GET_CODE (XEXP (x, 1)) == CONST
&& GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS && GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS
...@@ -1711,33 +1825,18 @@ alpha_legitimize_address (x, oldx, mode) ...@@ -1711,33 +1825,18 @@ alpha_legitimize_address (x, oldx, mode)
/* If this is a local symbol, split the address into HIGH/LO_SUM parts. */ /* If this is a local symbol, split the address into HIGH/LO_SUM parts. */
if (TARGET_EXPLICIT_RELOCS && symbolic_operand (x, Pmode)) if (TARGET_EXPLICIT_RELOCS && symbolic_operand (x, Pmode))
{ {
rtx scratch;
if (local_symbolic_operand (x, Pmode)) if (local_symbolic_operand (x, Pmode))
{ {
if (small_symbolic_operand (x, Pmode)) if (small_symbolic_operand (x, Pmode))
scratch = pic_offset_table_rtx; return x;
else else
{ {
rtx insn, tmp; if (!no_new_pseudos)
scratch = gen_reg_rtx (Pmode);
scratch = gen_reg_rtx (Pmode); emit_insn (gen_rtx_SET (VOIDmode, scratch,
gen_rtx_HIGH (Pmode, x)));
tmp = gen_rtx_HIGH (Pmode, x); return gen_rtx_LO_SUM (Pmode, scratch, x);
tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp);
insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp));
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp,
REG_NOTES (insn));
} }
return gen_rtx_LO_SUM (Pmode, scratch, x);
}
else
{
scratch = gen_reg_rtx (Pmode);
emit_insn (gen_movdi_er_high_g (scratch, pic_offset_table_rtx,
x, const0_rtx));
/* ??? FIXME: Tag the use of scratch with a lituse. */
return scratch;
} }
} }
...@@ -1745,14 +1844,65 @@ alpha_legitimize_address (x, oldx, mode) ...@@ -1745,14 +1844,65 @@ alpha_legitimize_address (x, oldx, mode)
split_addend: split_addend:
{ {
HOST_WIDE_INT lowpart = (addend & 0xffff) - 2 * (addend & 0x8000); HOST_WIDE_INT low, high;
HOST_WIDE_INT highpart = addend - lowpart;
x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (highpart), low = ((addend & 0xffff) ^ 0x8000) - 0x8000;
NULL_RTX, 1, OPTAB_LIB_WIDEN); addend -= low;
return plus_constant (x, lowpart); high = ((addend & 0xffffffff) ^ 0x80000000) - 0x80000000;
addend -= high;
if (addend)
x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (addend),
(no_new_pseudos ? scratch : NULL_RTX),
1, OPTAB_LIB_WIDEN);
if (high)
x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (high),
(no_new_pseudos ? scratch : NULL_RTX),
1, OPTAB_LIB_WIDEN);
return plus_constant (x, low);
} }
} }
/* For TARGET_EXPLICIT_RELOCS, we don't obfuscate a SYMBOL_REF to a
small symbolic operand until after reload. At which point we need
to replace (mem (symbol_ref)) with (mem (lo_sum $29 symbol_ref))
so that sched2 has the proper dependency information. */
int
some_small_symbolic_mem_operand (x, mode)
rtx x;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
/* Get rid of SIGN_EXTEND, etc. */
while (GET_RTX_CLASS (GET_CODE (x)) == '1')
x = XEXP (x, 0);
return (GET_CODE (x) == MEM
&& small_symbolic_operand (XEXP (x, 0), Pmode));
}
rtx
split_small_symbolic_mem_operand (x)
rtx x;
{
rtx *p;
if (GET_CODE (x) == MEM)
{
rtx tmp = gen_rtx_LO_SUM (DImode, pic_offset_table_rtx, XEXP (x, 0));
return replace_equiv_address (x, tmp);
}
x = copy_rtx (x);
p = &x;
while (GET_RTX_CLASS (GET_CODE (*p)) == '1')
p = &XEXP (*p, 0);
*p = split_small_symbolic_mem_operand (*p);
return x;
}
/* Try a machine-dependent way of reloading an illegitimate address /* Try a machine-dependent way of reloading an illegitimate address
operand. If we find one, push the reload and return the new rtx. */ operand. If we find one, push the reload and return the new rtx. */
...@@ -1886,6 +2036,39 @@ get_unaligned_address (ref, extra_offset) ...@@ -1886,6 +2036,39 @@ get_unaligned_address (ref, extra_offset)
return plus_constant (base, offset + extra_offset); return plus_constant (base, offset + extra_offset);
} }
/* On the Alpha, all (non-symbolic) constants except zero go into
a floating-point register via memory. Note that we cannot
return anything that is not a subset of CLASS, and that some
symbolic constants cannot be dropped to memory. */
enum reg_class
alpha_preferred_reload_class(x, class)
rtx x;
enum reg_class class;
{
/* Zero is present in any register class. */
if (x == CONST0_RTX (GET_MODE (x)))
return class;
/* These sorts of constants we can easily drop to memory. */
if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
{
if (class == FLOAT_REGS)
return NO_REGS;
if (class == ALL_REGS)
return GENERAL_REGS;
return class;
}
/* All other kinds of constants should not (and in the case of HIGH
cannot) be dropped to memory -- instead we use a GENERAL_REGS
secondary reload. */
if (CONSTANT_P (x))
return (class == ALL_REGS ? GENERAL_REGS : class);
return class;
}
/* Loading and storing HImode or QImode values to and from memory /* Loading and storing HImode or QImode values to and from memory
usually requires a scratch register. The exceptions are loading usually requires a scratch register. The exceptions are loading
QImode and HImode from an aligned address to a general register QImode and HImode from an aligned address to a general register
...@@ -2294,36 +2477,15 @@ alpha_expand_mov (mode, operands) ...@@ -2294,36 +2477,15 @@ alpha_expand_mov (mode, operands)
&& ! reg_or_0_operand (operands[1], mode)) && ! reg_or_0_operand (operands[1], mode))
operands[1] = force_reg (mode, operands[1]); operands[1] = force_reg (mode, operands[1]);
if (TARGET_EXPLICIT_RELOCS && symbolic_operand (operands[1], mode)) /* Allow legitimize_address to perform some simplifications. */
if (symbolic_operand (operands[1], mode))
{ {
if (local_symbolic_operand (operands[1], mode)) rtx tmp = alpha_legitimize_address (operands[1], operands[0], mode);
if (tmp)
{ {
rtx scratch; operands[1] = tmp;
if (small_symbolic_operand (operands[1], Pmode))
scratch = pic_offset_table_rtx;
else
{
rtx insn, tmp;
scratch = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
tmp = gen_rtx_HIGH (Pmode, operands[1]);
tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp);
insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp));
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp,
REG_NOTES (insn));
}
operands[1] = gen_rtx_LO_SUM (Pmode, scratch, operands[1]);
return false; return false;
} }
else
{
emit_insn (gen_movdi_er_high_g (operands[0], pic_offset_table_rtx,
operands[1], const0_rtx));
return true;
}
} }
/* Early out for non-constants and valid constants. */ /* Early out for non-constants and valid constants. */
......
...@@ -812,17 +812,7 @@ enum reg_class { ...@@ -812,17 +812,7 @@ enum reg_class {
`O' is used for negated 8-bit constants. `O' is used for negated 8-bit constants.
`P' is used for the constants 1, 2 and 3. */ `P' is used for the constants 1, 2 and 3. */
#define CONST_OK_FOR_LETTER_P(VALUE, C) \ #define CONST_OK_FOR_LETTER_P alpha_const_ok_for_letter_p
((C) == 'I' ? (unsigned HOST_WIDE_INT) (VALUE) < 0x100 \
: (C) == 'J' ? (VALUE) == 0 \
: (C) == 'K' ? (unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000 \
: (C) == 'L' ? (((VALUE) & 0xffff) == 0 \
&& (((VALUE)) >> 31 == -1 || (VALUE) >> 31 == 0)) \
: (C) == 'M' ? zap_mask (VALUE) \
: (C) == 'N' ? (unsigned HOST_WIDE_INT) (~ (VALUE)) < 0x100 \
: (C) == 'O' ? (unsigned HOST_WIDE_INT) (- (VALUE)) < 0x100 \
: (C) == 'P' ? (VALUE) == 1 || (VALUE) == 2 || (VALUE) == 3 \
: 0)
/* Similar, but for floating or large integer constants, and defining letters /* Similar, but for floating or large integer constants, and defining letters
G and H. Here VALUE is the CONST_DOUBLE rtx itself. G and H. Here VALUE is the CONST_DOUBLE rtx itself.
...@@ -830,13 +820,7 @@ enum reg_class { ...@@ -830,13 +820,7 @@ enum reg_class {
For Alpha, `G' is the floating-point constant zero. `H' is a CONST_DOUBLE For Alpha, `G' is the floating-point constant zero. `H' is a CONST_DOUBLE
that is the operand of a ZAP insn. */ that is the operand of a ZAP insn. */
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ #define CONST_DOUBLE_OK_FOR_LETTER_P alpha_const_double_ok_for_letter_p
((C) == 'G' ? (GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_FLOAT \
&& (VALUE) == CONST0_RTX (GET_MODE (VALUE))) \
: (C) == 'H' ? (GET_MODE (VALUE) == VOIDmode \
&& zap_mask (CONST_DOUBLE_LOW (VALUE)) \
&& zap_mask (CONST_DOUBLE_HIGH (VALUE))) \
: 0)
/* Optional extra constraints for this machine. /* Optional extra constraints for this machine.
...@@ -848,31 +832,18 @@ enum reg_class { ...@@ -848,31 +832,18 @@ enum reg_class {
'S' is a 6-bit constant (valid for a shift insn). 'S' is a 6-bit constant (valid for a shift insn).
'T' is a HIGH.
'U' is a symbolic operand. */ 'U' is a symbolic operand. */
#define EXTRA_CONSTRAINT(OP, C) \ #define EXTRA_CONSTRAINT alpha_extra_constraint
((C) == 'Q' ? normal_memory_operand (OP, VOIDmode) \
: (C) == 'R' ? direct_call_operand (OP, Pmode) \
: (C) == 'S' ? (GET_CODE (OP) == CONST_INT \
&& (unsigned HOST_WIDE_INT) INTVAL (OP) < 64) \
: (C) == 'T' ? GET_CODE (OP) == HIGH \
: (TARGET_ABI_UNICOSMK && (C) == 'U') \
? symbolic_operand (OP, VOIDmode) \
: 0)
/* Given an rtx X being reloaded into a reg required to be /* Given an rtx X being reloaded into a reg required to be
in class CLASS, return the class of reg to actually use. in class CLASS, return the class of reg to actually use.
In general this is just CLASS; but on some machines In general this is just CLASS; but on some machines
in some cases it is preferable to use a more restrictive class. in some cases it is preferable to use a more restrictive class. */
On the Alpha, all constants except zero go into a floating-point
register via memory. */
#define PREFERRED_RELOAD_CLASS(X, CLASS) \ #define PREFERRED_RELOAD_CLASS alpha_preferred_reload_class
(CONSTANT_P (X) && (X) != const0_rtx && (X) != CONST0_RTX (GET_MODE (X)) \
? ((CLASS) == FLOAT_REGS || (CLASS) == NO_REGS ? NO_REGS \
: (CLASS) == ALL_REGS ? GENERAL_REGS : (CLASS)) \
: (CLASS))
/* Loading and storing HImode or QImode values to and from memory /* Loading and storing HImode or QImode values to and from memory
usually requires a scratch register. The exceptions are loading usually requires a scratch register. The exceptions are loading
...@@ -1479,14 +1450,14 @@ do { \ ...@@ -1479,14 +1450,14 @@ do { \
to be legitimate. If we find one, return the new, valid address. to be legitimate. If we find one, return the new, valid address.
This macro is used in only one place: `memory_address' in explow.c. */ This macro is used in only one place: `memory_address' in explow.c. */
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
do { \ do { \
rtx new_x = alpha_legitimize_address (X, OLDX, MODE); \ rtx new_x = alpha_legitimize_address (X, NULL_RTX, MODE); \
if (new_x) \ if (new_x) \
{ \ { \
X = new_x; \ X = new_x; \
goto WIN; \ goto WIN; \
} \ } \
} while (0) } while (0)
/* Try a machine-dependent way of reloading an illegitimate address /* Try a machine-dependent way of reloading an illegitimate address
...@@ -2117,9 +2088,9 @@ do { \ ...@@ -2117,9 +2088,9 @@ do { \
{"global_symbolic_operand", {SYMBOL_REF, CONST}}, \ {"global_symbolic_operand", {SYMBOL_REF, CONST}}, \
{"call_operand", {REG, SYMBOL_REF}}, \ {"call_operand", {REG, SYMBOL_REF}}, \
{"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \
SYMBOL_REF, CONST, LABEL_REF}}, \ SYMBOL_REF, CONST, LABEL_REF, HIGH}}, \
{"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \
SYMBOL_REF, CONST, LABEL_REF}}, \ SYMBOL_REF, CONST, LABEL_REF, HIGH}}, \
{"some_ni_operand", {SUBREG, REG, MEM}}, \ {"some_ni_operand", {SUBREG, REG, MEM}}, \
{"aligned_memory_operand", {MEM}}, \ {"aligned_memory_operand", {MEM}}, \
{"unaligned_memory_operand", {MEM}}, \ {"unaligned_memory_operand", {MEM}}, \
...@@ -2130,7 +2101,9 @@ do { \ ...@@ -2130,7 +2101,9 @@ do { \
{"reg_not_elim_operand", {SUBREG, REG}}, \ {"reg_not_elim_operand", {SUBREG, REG}}, \
{"reg_no_subreg_operand", {REG}}, \ {"reg_no_subreg_operand", {REG}}, \
{"addition_operation", {PLUS}}, \ {"addition_operation", {PLUS}}, \
{"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}}, {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}}, \
{"some_small_symbolic_mem_operand", {MEM, SIGN_EXTEND, ZERO_EXTEND, \
FLOAT_EXTEND}},
/* Define the `__builtin_va_list' type for the ABI. */ /* Define the `__builtin_va_list' type for the ABI. */
#define BUILD_VA_LIST_TYPE(VALIST) \ #define BUILD_VA_LIST_TYPE(VALIST) \
......
...@@ -649,6 +649,14 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" ...@@ -649,6 +649,14 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
"TARGET_EXPLICIT_RELOCS" "TARGET_EXPLICIT_RELOCS"
"ldah %0,%2(%1)\t\t!gprelhigh") "ldah %0,%2(%1)\t\t!gprelhigh")
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(high:DI (match_operand:DI 1 "local_symbolic_operand" "")))]
"TARGET_EXPLICIT_RELOCS && reload_completed"
[(set (match_dup 0)
(plus:DI (match_dup 2) (high:DI (match_dup 1))))]
"operands[2] = pic_offset_table_rtx;")
;; We used to expend quite a lot of effort choosing addq/subq/lda. ;; We used to expend quite a lot of effort choosing addq/subq/lda.
;; With complications like ;; With complications like
;; ;;
...@@ -1225,9 +1233,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" ...@@ -1225,9 +1233,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
default: default:
abort (); abort ();
} }
emit_insn (gen_movdi_er_high_g (operands[0], pic_offset_table_rtx, emit_move_insn (operands[0], gen_rtx_SYMBOL_REF (DImode, str));
gen_rtx_SYMBOL_REF (DImode, str),
const0_rtx));
} }
[(set_attr "type" "jsr") [(set_attr "type" "jsr")
(set_attr "length" "8")]) (set_attr "length" "8")])
...@@ -1290,9 +1296,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" ...@@ -1290,9 +1296,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
default: default:
abort (); abort ();
} }
emit_insn (gen_movdi_er_high_g (operands[0], pic_offset_table_rtx, emit_move_insn (operands[0], gen_rtx_SYMBOL_REF (DImode, str));
gen_rtx_SYMBOL_REF (DImode, str),
const0_rtx));
} }
[(set_attr "type" "jsr") [(set_attr "type" "jsr")
(set_attr "length" "8")]) (set_attr "length" "8")])
...@@ -5459,7 +5463,39 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" ...@@ -5459,7 +5463,39 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
return "lda %0,%2(%1)\t\t!gprellow"; return "lda %0,%2(%1)\t\t!gprellow";
}) })
(define_insn "movdi_er_high_g" (define_split
[(set (match_operand:DI 0 "register_operand" "")
(match_operand:DI 1 "small_symbolic_operand" ""))]
"TARGET_EXPLICIT_RELOCS && reload_completed"
[(set (match_dup 0)
(lo_sum:DI (match_dup 2) (match_dup 1)))]
"operands[2] = pic_offset_table_rtx;")
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(match_operand:DI 1 "local_symbolic_operand" ""))]
"TARGET_EXPLICIT_RELOCS && reload_completed"
[(set (match_dup 0)
(plus:DI (match_dup 2) (high:DI (match_dup 1))))
(set (match_dup 0)
(lo_sum:DI (match_dup 0) (match_dup 1)))]
"operands[2] = pic_offset_table_rtx;")
(define_split
[(set (match_operand 0 "some_small_symbolic_mem_operand" "")
(match_operand 1 "" ""))]
"TARGET_EXPLICIT_RELOCS && reload_completed"
[(set (match_dup 0) (match_dup 1))]
"operands[0] = split_small_symbolic_mem_operand (operands[0]);")
(define_split
[(set (match_operand 0 "" "")
(match_operand 1 "some_small_symbolic_mem_operand" ""))]
"TARGET_EXPLICIT_RELOCS && reload_completed"
[(set (match_dup 0) (match_dup 1))]
"operands[1] = split_small_symbolic_mem_operand (operands[1]);")
(define_insn "*movdi_er_high_g"
[(set (match_operand:DI 0 "register_operand" "=r") [(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(match_operand:DI 1 "register_operand" "r") (unspec:DI [(match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "global_symbolic_operand" "") (match_operand:DI 2 "global_symbolic_operand" "")
...@@ -5469,9 +5505,19 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" ...@@ -5469,9 +5505,19 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
"ldq %0,%2(%1)\t\t!literal" "ldq %0,%2(%1)\t\t!literal"
[(set_attr "type" "ldsym")]) [(set_attr "type" "ldsym")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(match_operand:DI 1 "global_symbolic_operand" ""))]
"TARGET_EXPLICIT_RELOCS && reload_completed"
[(set (match_dup 0)
(unspec:DI [(match_dup 2)
(match_dup 1)
(const_int 0)] UNSPEC_LITERAL))]
"operands[2] = pic_offset_table_rtx;")
(define_insn "*movdi_er_nofix" (define_insn "*movdi_er_nofix"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q") [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q")
(match_operand:DI 1 "input_operand" "rJ,K,L,T,m,rJ,*fJ,Q,*f"))] (match_operand:DI 1 "input_operand" "rJ,K,L,T,s,m,rJ,*fJ,Q,*f"))]
"TARGET_EXPLICIT_RELOCS && ! TARGET_FIX "TARGET_EXPLICIT_RELOCS && ! TARGET_FIX
&& (register_operand (operands[0], DImode) && (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))" || reg_or_0_operand (operands[1], DImode))"
...@@ -5479,13 +5525,14 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" ...@@ -5479,13 +5525,14 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
mov %r1,%0 mov %r1,%0
lda %0,%1($31) lda %0,%1($31)
ldah %0,%h1($31) ldah %0,%h1($31)
ldah %0,%H1 #
#
ldq%A1 %0,%1 ldq%A1 %0,%1
stq%A0 %r1,%0 stq%A0 %r1,%0
fmov %R1,%0 fmov %R1,%0
ldt %0,%1 ldt %0,%1
stt %R1,%0" stt %R1,%0"
[(set_attr "type" "ilog,iadd,iadd,iadd,ild,ist,fcpys,fld,fst")]) [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")])
;; The 'U' constraint matches symbolic operands on Unicos/Mk. Those should ;; The 'U' constraint matches symbolic operands on Unicos/Mk. Those should
;; have been split up by the rules above but we shouldn't reject the ;; have been split up by the rules above but we shouldn't reject the
...@@ -5512,8 +5559,10 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" ...@@ -5512,8 +5559,10 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(set_attr "length" "*,*,*,16,*,*,*,*,*,*")]) (set_attr "length" "*,*,*,16,*,*,*,*,*,*")])
(define_insn "*movdi_er_fix" (define_insn "*movdi_er_fix"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q,r,*f") [(set (match_operand:DI 0 "nonimmediate_operand"
(match_operand:DI 1 "input_operand" "rJ,K,L,T,m,rJ,*fJ,Q,*f,*f,r"))] "=r,r,r,r,r,r, m, *f,*f, Q, r,*f")
(match_operand:DI 1 "input_operand"
"rJ,K,L,T,s,m,rJ,*fJ, Q,*f,*f, r"))]
"TARGET_EXPLICIT_RELOCS && TARGET_FIX "TARGET_EXPLICIT_RELOCS && TARGET_FIX
&& (register_operand (operands[0], DImode) && (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))" || reg_or_0_operand (operands[1], DImode))"
...@@ -5521,7 +5570,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" ...@@ -5521,7 +5570,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
mov %r1,%0 mov %r1,%0
lda %0,%1($31) lda %0,%1($31)
ldah %0,%h1($31) ldah %0,%h1($31)
ldah %0,%H1 #
#
ldq%A1 %0,%1 ldq%A1 %0,%1
stq%A0 %r1,%0 stq%A0 %r1,%0
fmov %R1,%0 fmov %R1,%0
...@@ -5529,7 +5579,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" ...@@ -5529,7 +5579,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
stt %R1,%0 stt %R1,%0
ftoit %1,%0 ftoit %1,%0
itoft %1,%0" itoft %1,%0"
[(set_attr "type" "ilog,iadd,iadd,iadd,ild,ist,fcpys,fld,fst,ftoi,itof")]) [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst,ftoi,itof")])
(define_insn "*movdi_fix" (define_insn "*movdi_fix"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q,r,*f") [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q,r,*f")
......
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