pa.c (hppa_legitimize_address): Do nothing with function label arithmetic.
* pa.c (hppa_legitimize_address): Do nothing with function label arithmetic. (emit_move_sequence): Split up function label arithmetic so that function's address is loaded first, then constant part is added to the function's address. (is_function_label_plus_const): New function. From-SVN: r7882
This commit is contained in:
parent
6ce47c075f
commit
326bc2de1d
@ -611,9 +611,12 @@ hppa_legitimize_address (x, oldx, mode)
|
||||
if (GET_CODE (x) == CONST)
|
||||
x = XEXP (x, 0);
|
||||
|
||||
/* Note we must reject symbols which represent function addresses
|
||||
since the assembler/linker can't handle arithmetic on plabels. */
|
||||
if (GET_CODE (x) == PLUS
|
||||
&& GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||
&& (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
|
||||
&& ((GET_CODE (XEXP (x, 0)) == SYMBOL_REF
|
||||
&& !FUNCTION_NAME_P (XSTR (XEXP (x, 0), 0)))
|
||||
|| GET_CODE (XEXP (x, 0)) == REG))
|
||||
{
|
||||
rtx int_part, ptr_reg;
|
||||
@ -892,13 +895,32 @@ emit_move_sequence (operands, mode, scratch_reg)
|
||||
cse and loop optimizations. */
|
||||
else
|
||||
{
|
||||
rtx temp, set;
|
||||
rtx temp, set, const_part = NULL;
|
||||
|
||||
if (reload_in_progress || reload_completed)
|
||||
temp = scratch_reg ? scratch_reg : operand0;
|
||||
else
|
||||
temp = gen_reg_rtx (mode);
|
||||
|
||||
/* Argh. The assembler and linker can't handle arithmetic
|
||||
involving plabels. We'll have to split up operand1 here
|
||||
if it's a function label involved in an arithmetic
|
||||
expression. Luckily, this only happens with addition
|
||||
of constants to plabels, which simplifies the test. */
|
||||
if (GET_CODE (operand1) == CONST
|
||||
&& GET_CODE (XEXP (operand1, 0)) == PLUS
|
||||
&& function_label_operand (XEXP (XEXP (operand1, 0), 0),
|
||||
Pmode))
|
||||
{
|
||||
/* Save away the constant part of the expression. */
|
||||
const_part = XEXP (XEXP (operand1, 0), 1);
|
||||
if (GET_CODE (const_part) != CONST_INT)
|
||||
abort ();
|
||||
|
||||
/* Set operand1 to just the SYMBOL_REF. */
|
||||
operand1 = XEXP (XEXP (operand1, 0), 0);
|
||||
}
|
||||
|
||||
if (ishighonly)
|
||||
set = gen_rtx (SET, mode, operand0, temp);
|
||||
else
|
||||
@ -910,6 +932,12 @@ emit_move_sequence (operands, mode, scratch_reg)
|
||||
temp,
|
||||
gen_rtx (HIGH, mode, operand1)));
|
||||
emit_insn (set);
|
||||
|
||||
/* Add back in the constant part if needed. */
|
||||
if (const_part != NULL)
|
||||
emit_insn (gen_rtx (SET, mode, operand0,
|
||||
plus_constant (operand0,
|
||||
XEXP (const_part, 0))));
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
@ -3794,13 +3822,29 @@ hppa_encode_label (sym)
|
||||
}
|
||||
|
||||
int
|
||||
function_label_operand (op, mode)
|
||||
function_label_operand (op, mode)
|
||||
rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
return GET_CODE (op) == SYMBOL_REF && FUNCTION_NAME_P (XSTR (op, 0));
|
||||
}
|
||||
|
||||
/* Returns 1 if OP is a function label involved in a simple addition
|
||||
with a constant. Used to keep certain patterns from matching
|
||||
during instruction combination. */
|
||||
int
|
||||
is_function_label_plus_const (op)
|
||||
rtx op;
|
||||
{
|
||||
/* Strip off any CONST. */
|
||||
if (GET_CODE (op) == CONST)
|
||||
op = XEXP (op, 0);
|
||||
|
||||
return (GET_CODE (op) == PLUS
|
||||
&& function_label_operand (XEXP (op, 0), Pmode)
|
||||
&& GET_CODE (XEXP (op, 1)) == CONST_INT);
|
||||
}
|
||||
|
||||
/* Returns 1 if the 6 operands specified in OPERANDS are suitable for
|
||||
use in fmpyadd instructions. */
|
||||
int
|
||||
|
Loading…
x
Reference in New Issue
Block a user