Commit 326bc2de by Jeff Law

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
parent 6ce47c07
...@@ -611,9 +611,12 @@ hppa_legitimize_address (x, oldx, mode) ...@@ -611,9 +611,12 @@ hppa_legitimize_address (x, oldx, mode)
if (GET_CODE (x) == CONST) if (GET_CODE (x) == CONST)
x = XEXP (x, 0); 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 if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 1)) == CONST_INT && 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)) || GET_CODE (XEXP (x, 0)) == REG))
{ {
rtx int_part, ptr_reg; rtx int_part, ptr_reg;
...@@ -892,13 +895,32 @@ emit_move_sequence (operands, mode, scratch_reg) ...@@ -892,13 +895,32 @@ emit_move_sequence (operands, mode, scratch_reg)
cse and loop optimizations. */ cse and loop optimizations. */
else else
{ {
rtx temp, set; rtx temp, set, const_part = NULL;
if (reload_in_progress || reload_completed) if (reload_in_progress || reload_completed)
temp = scratch_reg ? scratch_reg : operand0; temp = scratch_reg ? scratch_reg : operand0;
else else
temp = gen_reg_rtx (mode); 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) if (ishighonly)
set = gen_rtx (SET, mode, operand0, temp); set = gen_rtx (SET, mode, operand0, temp);
else else
...@@ -910,6 +932,12 @@ emit_move_sequence (operands, mode, scratch_reg) ...@@ -910,6 +932,12 @@ emit_move_sequence (operands, mode, scratch_reg)
temp, temp,
gen_rtx (HIGH, mode, operand1))); gen_rtx (HIGH, mode, operand1)));
emit_insn (set); 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;
} }
return 1; return 1;
...@@ -3801,6 +3829,22 @@ function_label_operand (op, mode) ...@@ -3801,6 +3829,22 @@ function_label_operand (op, mode)
return GET_CODE (op) == SYMBOL_REF && FUNCTION_NAME_P (XSTR (op, 0)); 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 /* Returns 1 if the 6 operands specified in OPERANDS are suitable for
use in fmpyadd instructions. */ use in fmpyadd instructions. */
int int
......
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