pa-protos.h (compute_frame_size): Use HOST_WIDE_INT for frame sizes.
* pa-protos.h (compute_frame_size): Use HOST_WIDE_INT for frame sizes. * pa.c (store_reg, store_reg_modify, load_reg, set_reg_plus_d): Likewise. Handle frames larger than 0x7fffffff on 64-bit ports. (emit_move_sequence): Check scratch_reg first in various if statements. Extend source simplification to handle all 64-bit CONST_INTs. (pa_output_function_prologue): Use HOST_WIDE_INT_PRINT_DEC for printing frame size. (hppa_expand_prologue, hppa_expand_epilogue): Use HOST_WIDE_INT for frame offset calculations. * pa.h (NEW_HP_ASSEMBLER): Add comment. (MAX_LEGIT_64BIT_CONST_INT, MIN_LEGIT_64BIT_CONST_INT, LEGITIMATE_64BIT_CONST_INT_P): Define. (LEGITIMATE_CONSTANT_P): Use LEGITIMATE_64BIT_CONST_INT_P. Treat any CONST_INT as legitimate during and after reload. (VAL_32_BITS_P, INT_32_BITS): Define. (LEGITIMIZE_RELOAD_ADDRESS): Handle large frame offsets. From-SVN: r76234
This commit is contained in:
parent
3e89ed8dd3
commit
a42952105e
@ -1,3 +1,22 @@
|
||||
2004-01-20 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
|
||||
|
||||
* pa-protos.h (compute_frame_size): Use HOST_WIDE_INT for frame sizes.
|
||||
* pa.c (store_reg, store_reg_modify, load_reg, set_reg_plus_d):
|
||||
Likewise. Handle frames larger than 0x7fffffff on 64-bit ports.
|
||||
(emit_move_sequence): Check scratch_reg first in various if statements.
|
||||
Extend source simplification to handle all 64-bit CONST_INTs.
|
||||
(pa_output_function_prologue): Use HOST_WIDE_INT_PRINT_DEC for printing
|
||||
frame size.
|
||||
(hppa_expand_prologue, hppa_expand_epilogue): Use HOST_WIDE_INT for
|
||||
frame offset calculations.
|
||||
* pa.h (NEW_HP_ASSEMBLER): Add comment.
|
||||
(MAX_LEGIT_64BIT_CONST_INT, MIN_LEGIT_64BIT_CONST_INT,
|
||||
LEGITIMATE_64BIT_CONST_INT_P): Define.
|
||||
(LEGITIMATE_CONSTANT_P): Use LEGITIMATE_64BIT_CONST_INT_P. Treat
|
||||
any CONST_INT as legitimate during and after reload.
|
||||
(VAL_32_BITS_P, INT_32_BITS): Define.
|
||||
(LEGITIMIZE_RELOAD_ADDRESS): Handle large frame offsets.
|
||||
|
||||
2004-01-20 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* emit-rtl.c (verify_rtx_sharing, copy_insn_1,
|
||||
|
@ -137,7 +137,7 @@ extern struct rtx_def *hppa_builtin_saveregs (void);
|
||||
|
||||
extern void override_options (void);
|
||||
extern void output_ascii (FILE *, const char *, int);
|
||||
extern int compute_frame_size (int, int *);
|
||||
extern HOST_WIDE_INT compute_frame_size (HOST_WIDE_INT, int *);
|
||||
extern int and_mask_p (unsigned HOST_WIDE_INT);
|
||||
extern int cint_ok_for_move (HOST_WIDE_INT);
|
||||
extern void hppa_expand_prologue (void);
|
||||
|
@ -107,10 +107,10 @@ static int compute_movstr_length (rtx);
|
||||
static int compute_clrstr_length (rtx);
|
||||
static bool pa_assemble_integer (rtx, unsigned int, int);
|
||||
static void remove_useless_addtr_insns (int);
|
||||
static void store_reg (int, int, int);
|
||||
static void store_reg_modify (int, int, int);
|
||||
static void load_reg (int, int, int);
|
||||
static void set_reg_plus_d (int, int, int, int);
|
||||
static void store_reg (int, HOST_WIDE_INT, int);
|
||||
static void store_reg_modify (int, int, HOST_WIDE_INT);
|
||||
static void load_reg (int, HOST_WIDE_INT, int);
|
||||
static void set_reg_plus_d (int, int, HOST_WIDE_INT, int);
|
||||
static void pa_output_function_prologue (FILE *, HOST_WIDE_INT);
|
||||
static void update_total_code_bytes (int);
|
||||
static void pa_output_function_epilogue (FILE *, HOST_WIDE_INT);
|
||||
@ -1552,13 +1552,13 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
|
||||
/* Handle secondary reloads for loads/stores of FP registers from
|
||||
REG+D addresses where D does not fit in 5 bits, including
|
||||
(subreg (mem (addr))) cases. */
|
||||
if (fp_reg_operand (operand0, mode)
|
||||
if (scratch_reg
|
||||
&& fp_reg_operand (operand0, mode)
|
||||
&& ((GET_CODE (operand1) == MEM
|
||||
&& !memory_address_p (DFmode, XEXP (operand1, 0)))
|
||||
|| ((GET_CODE (operand1) == SUBREG
|
||||
&& GET_CODE (XEXP (operand1, 0)) == MEM
|
||||
&& !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0)))))
|
||||
&& scratch_reg)
|
||||
&& !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0))))))
|
||||
{
|
||||
if (GET_CODE (operand1) == SUBREG)
|
||||
operand1 = XEXP (operand1, 0);
|
||||
@ -1585,14 +1585,14 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
|
||||
gen_rtx_MEM (mode, scratch_reg)));
|
||||
return 1;
|
||||
}
|
||||
else if (fp_reg_operand (operand1, mode)
|
||||
else if (scratch_reg
|
||||
&& fp_reg_operand (operand1, mode)
|
||||
&& ((GET_CODE (operand0) == MEM
|
||||
&& ! memory_address_p (DFmode, XEXP (operand0, 0)))
|
||||
|| ((GET_CODE (operand0) == SUBREG)
|
||||
&& GET_CODE (XEXP (operand0, 0)) == MEM
|
||||
&& !memory_address_p (DFmode,
|
||||
XEXP (XEXP (operand0, 0), 0))))
|
||||
&& scratch_reg)
|
||||
XEXP (XEXP (operand0, 0), 0)))))
|
||||
{
|
||||
if (GET_CODE (operand0) == SUBREG)
|
||||
operand0 = XEXP (operand0, 0);
|
||||
@ -1623,15 +1623,15 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
|
||||
/* Handle secondary reloads for loads of FP registers from constant
|
||||
expressions by forcing the constant into memory.
|
||||
|
||||
use scratch_reg to hold the address of the memory location.
|
||||
Use scratch_reg to hold the address of the memory location.
|
||||
|
||||
The proper fix is to change PREFERRED_RELOAD_CLASS to return
|
||||
NO_REGS when presented with a const_int and a register class
|
||||
containing only FP registers. Doing so unfortunately creates
|
||||
more problems than it solves. Fix this for 2.5. */
|
||||
else if (fp_reg_operand (operand0, mode)
|
||||
else if (scratch_reg
|
||||
&& CONSTANT_P (operand1)
|
||||
&& scratch_reg)
|
||||
&& fp_reg_operand (operand0, mode))
|
||||
{
|
||||
rtx xoperands[2];
|
||||
|
||||
@ -1653,14 +1653,14 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
|
||||
}
|
||||
/* Handle secondary reloads for SAR. These occur when trying to load
|
||||
the SAR from memory, FP register, or with a constant. */
|
||||
else if (GET_CODE (operand0) == REG
|
||||
else if (scratch_reg
|
||||
&& GET_CODE (operand0) == REG
|
||||
&& REGNO (operand0) < FIRST_PSEUDO_REGISTER
|
||||
&& REGNO_REG_CLASS (REGNO (operand0)) == SHIFT_REGS
|
||||
&& (GET_CODE (operand1) == MEM
|
||||
|| GET_CODE (operand1) == CONST_INT
|
||||
|| (GET_CODE (operand1) == REG
|
||||
&& FP_REG_CLASS_P (REGNO_REG_CLASS (REGNO (operand1)))))
|
||||
&& scratch_reg)
|
||||
&& FP_REG_CLASS_P (REGNO_REG_CLASS (REGNO (operand1))))))
|
||||
{
|
||||
/* D might not fit in 14 bits either; for such cases load D into
|
||||
scratch reg. */
|
||||
@ -1971,16 +1971,19 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
|
||||
return 1;
|
||||
}
|
||||
else if (GET_CODE (operand1) != CONST_INT
|
||||
|| ! cint_ok_for_move (INTVAL (operand1)))
|
||||
|| !cint_ok_for_move (INTVAL (operand1)))
|
||||
{
|
||||
rtx extend = NULL_RTX;
|
||||
rtx temp;
|
||||
rtx insn, temp;
|
||||
rtx op1 = operand1;
|
||||
HOST_WIDE_INT value = INTVAL (operand1);
|
||||
HOST_WIDE_INT insv = 0;
|
||||
int insert = 0;
|
||||
|
||||
if (TARGET_64BIT && GET_CODE (operand1) == CONST_INT
|
||||
if (TARGET_64BIT
|
||||
&& GET_CODE (operand1) == CONST_INT
|
||||
&& HOST_BITS_PER_WIDE_INT > 32
|
||||
&& GET_MODE_BITSIZE (GET_MODE (operand0)) > 32)
|
||||
{
|
||||
HOST_WIDE_INT val = INTVAL (operand1);
|
||||
HOST_WIDE_INT nval;
|
||||
|
||||
/* Extract the low order 32 bits of the value and sign extend.
|
||||
@ -1988,19 +1991,21 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
|
||||
can use the original value as-is. If the new value is
|
||||
different, we use it and insert the most-significant 32-bits
|
||||
of the original value into the final result. */
|
||||
nval = ((val & (((HOST_WIDE_INT) 2 << 31) - 1))
|
||||
nval = ((value & (((HOST_WIDE_INT) 2 << 31) - 1))
|
||||
^ ((HOST_WIDE_INT) 1 << 31)) - ((HOST_WIDE_INT) 1 << 31);
|
||||
if (val != nval)
|
||||
if (value != nval)
|
||||
{
|
||||
#if HOST_BITS_PER_WIDE_INT > 32
|
||||
extend = GEN_INT (val >> 32);
|
||||
insv = value >= 0 ? value >> 32 : ~(~value >> 32);
|
||||
#endif
|
||||
insert = 1;
|
||||
value = nval;
|
||||
operand1 = GEN_INT (nval);
|
||||
}
|
||||
}
|
||||
|
||||
if (reload_in_progress || reload_completed)
|
||||
temp = operand0;
|
||||
temp = scratch_reg ? scratch_reg : operand0;
|
||||
else
|
||||
temp = gen_reg_rtx (mode);
|
||||
|
||||
@ -2008,7 +2013,8 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
|
||||
because PLUS uses an 11-bit immediate and the insn sequence
|
||||
generated is not as efficient as the one using HIGH/LO_SUM. */
|
||||
if (GET_CODE (operand1) == CONST_INT
|
||||
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
|
||||
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
|
||||
&& !insert)
|
||||
{
|
||||
/* Directly break constant into high and low parts. This
|
||||
provides better optimization opportunities because various
|
||||
@ -2016,7 +2022,6 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
|
||||
We use a 14-bit signed low part except when the addition
|
||||
of 0x4000 to the high part might change the sign of the
|
||||
high part. */
|
||||
HOST_WIDE_INT value = INTVAL (operand1);
|
||||
HOST_WIDE_INT low = value & 0x3fff;
|
||||
HOST_WIDE_INT high = value & ~ 0x3fff;
|
||||
|
||||
@ -2040,11 +2045,60 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
|
||||
operands[1] = gen_rtx_LO_SUM (mode, temp, operand1);
|
||||
}
|
||||
|
||||
emit_move_insn (operands[0], operands[1]);
|
||||
insn = emit_move_insn (operands[0], operands[1]);
|
||||
|
||||
if (extend != NULL_RTX)
|
||||
emit_insn (gen_insv (operands[0], GEN_INT (32), const0_rtx,
|
||||
extend));
|
||||
/* Now insert the most significant 32 bits of the value
|
||||
into the register. When we don't have a second register
|
||||
available, it could take up to nine instructions to load
|
||||
a 64-bit integer constant. Prior to reload, we force
|
||||
constants that would take more than three instructions
|
||||
to load to the constant pool. During and after reload,
|
||||
we have to handle all possible values. */
|
||||
if (insert)
|
||||
{
|
||||
/* Use a HIGH/LO_SUM/INSV sequence if we have a second
|
||||
register and the value to be inserted is outside the
|
||||
range that can be loaded with three depdi instructions. */
|
||||
if (temp != operand0 && (insv >= 16384 || insv < -16384))
|
||||
{
|
||||
operand1 = GEN_INT (insv);
|
||||
|
||||
emit_insn (gen_rtx_SET (VOIDmode, temp,
|
||||
gen_rtx_HIGH (mode, operand1)));
|
||||
emit_move_insn (temp, gen_rtx_LO_SUM (mode, temp, operand1));
|
||||
emit_insn (gen_insv (operand0, GEN_INT (32),
|
||||
const0_rtx, temp));
|
||||
}
|
||||
else
|
||||
{
|
||||
int len = 5, pos = 27;
|
||||
|
||||
/* Insert the bits using the depdi instruction. */
|
||||
while (pos >= 0)
|
||||
{
|
||||
HOST_WIDE_INT v5 = ((insv & 31) ^ 16) - 16;
|
||||
HOST_WIDE_INT sign = v5 < 0;
|
||||
|
||||
/* Left extend the insertion. */
|
||||
insv = (insv >= 0 ? insv >> len : ~(~insv >> len));
|
||||
while (pos > 0 && (insv & 1) == sign)
|
||||
{
|
||||
insv = (insv >= 0 ? insv >> 1 : ~(~insv >> 1));
|
||||
len += 1;
|
||||
pos -= 1;
|
||||
}
|
||||
|
||||
emit_insn (gen_insv (operand0, GEN_INT (len),
|
||||
GEN_INT (pos), GEN_INT (v5)));
|
||||
|
||||
len = pos > 0 && pos < 5 ? pos : 5;
|
||||
pos -= len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
REG_NOTES (insn)
|
||||
= gen_rtx_EXPR_LIST (REG_EQUAL, op1, REG_NOTES (insn));
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -3334,8 +3388,8 @@ remove_useless_addtr_insns (int check_notes)
|
||||
/* Global variables set by output_function_prologue(). */
|
||||
/* Size of frame. Need to know this to emit return insns from
|
||||
leaf procedures. */
|
||||
static int actual_fsize;
|
||||
static int local_fsize, save_fregs;
|
||||
static HOST_WIDE_INT actual_fsize, local_fsize;
|
||||
static int save_fregs;
|
||||
|
||||
/* Emit RTL to store REG at the memory location specified by BASE+DISP.
|
||||
Handle case where DISP > 8k by using the add_high_const patterns.
|
||||
@ -3344,7 +3398,7 @@ static int local_fsize, save_fregs;
|
||||
in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/
|
||||
|
||||
static void
|
||||
store_reg (int reg, int disp, int base)
|
||||
store_reg (int reg, HOST_WIDE_INT disp, int base)
|
||||
{
|
||||
rtx insn, dest, src, basereg;
|
||||
|
||||
@ -3355,11 +3409,33 @@ store_reg (int reg, int disp, int base)
|
||||
dest = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
|
||||
insn = emit_move_insn (dest, src);
|
||||
}
|
||||
else if (TARGET_64BIT && !VAL_32_BITS_P (disp))
|
||||
{
|
||||
rtx delta = GEN_INT (disp);
|
||||
rtx tmpreg = gen_rtx_REG (Pmode, 1);
|
||||
|
||||
emit_move_insn (tmpreg, delta);
|
||||
emit_move_insn (tmpreg, gen_rtx_PLUS (Pmode, tmpreg, basereg));
|
||||
dest = gen_rtx_MEM (word_mode, tmpreg);
|
||||
insn = emit_move_insn (dest, src);
|
||||
if (DO_FRAME_NOTES)
|
||||
{
|
||||
REG_NOTES (insn)
|
||||
= gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
|
||||
gen_rtx_SET (VOIDmode,
|
||||
gen_rtx_MEM (word_mode,
|
||||
gen_rtx_PLUS (word_mode, basereg,
|
||||
delta)),
|
||||
src),
|
||||
REG_NOTES (insn));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx delta = GEN_INT (disp);
|
||||
rtx high = gen_rtx_PLUS (Pmode, basereg, gen_rtx_HIGH (Pmode, delta));
|
||||
rtx tmpreg = gen_rtx_REG (Pmode, 1);
|
||||
|
||||
emit_move_insn (tmpreg, high);
|
||||
dest = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta));
|
||||
insn = emit_move_insn (dest, src);
|
||||
@ -3384,11 +3460,11 @@ store_reg (int reg, int disp, int base)
|
||||
add MOD to BASE. MOD must be <= 8k. */
|
||||
|
||||
static void
|
||||
store_reg_modify (int base, int reg, int mod)
|
||||
store_reg_modify (int base, int reg, HOST_WIDE_INT mod)
|
||||
{
|
||||
rtx insn, basereg, srcreg, delta;
|
||||
|
||||
if (! VAL_14_BITS_P (mod))
|
||||
if (!VAL_14_BITS_P (mod))
|
||||
abort ();
|
||||
|
||||
basereg = gen_rtx_REG (Pmode, base);
|
||||
@ -3431,7 +3507,7 @@ store_reg_modify (int base, int reg, int mod)
|
||||
There is code in expand_hppa_{prologue,epilogue} that knows about this. */
|
||||
|
||||
static void
|
||||
set_reg_plus_d (int reg, int base, int disp, int note)
|
||||
set_reg_plus_d (int reg, int base, HOST_WIDE_INT disp, int note)
|
||||
{
|
||||
rtx insn;
|
||||
|
||||
@ -3440,25 +3516,35 @@ set_reg_plus_d (int reg, int base, int disp, int note)
|
||||
insn = emit_move_insn (gen_rtx_REG (Pmode, reg),
|
||||
plus_constant (gen_rtx_REG (Pmode, base), disp));
|
||||
}
|
||||
else if (TARGET_64BIT && !VAL_32_BITS_P (disp))
|
||||
{
|
||||
rtx basereg = gen_rtx_REG (Pmode, base);
|
||||
rtx delta = GEN_INT (disp);
|
||||
rtx tmpreg = gen_rtx_REG (Pmode, 1);
|
||||
|
||||
emit_move_insn (tmpreg, delta);
|
||||
insn = emit_move_insn (gen_rtx_REG (Pmode, reg),
|
||||
gen_rtx_PLUS (Pmode, tmpreg, basereg));
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx basereg = gen_rtx_REG (Pmode, base);
|
||||
rtx delta = GEN_INT (disp);
|
||||
rtx tmpreg = gen_rtx_REG (Pmode, 1);
|
||||
|
||||
emit_move_insn (gen_rtx_REG (Pmode, 1),
|
||||
emit_move_insn (tmpreg,
|
||||
gen_rtx_PLUS (Pmode, basereg,
|
||||
gen_rtx_HIGH (Pmode, delta)));
|
||||
insn = emit_move_insn (gen_rtx_REG (Pmode, reg),
|
||||
gen_rtx_LO_SUM (Pmode, gen_rtx_REG (Pmode, 1),
|
||||
delta));
|
||||
gen_rtx_LO_SUM (Pmode, tmpreg, delta));
|
||||
}
|
||||
|
||||
if (DO_FRAME_NOTES && note)
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
int
|
||||
compute_frame_size (int size, int *fregs_live)
|
||||
HOST_WIDE_INT
|
||||
compute_frame_size (HOST_WIDE_INT size, int *fregs_live)
|
||||
{
|
||||
int freg_saved = 0;
|
||||
int i, j;
|
||||
@ -3562,7 +3648,7 @@ pa_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
|
||||
/* hppa_expand_prologue does the dirty work now. We just need
|
||||
to output the assembler directives which denote the start
|
||||
of a function. */
|
||||
fprintf (file, "\t.CALLINFO FRAME=%d", actual_fsize);
|
||||
fprintf (file, "\t.CALLINFO FRAME=" HOST_WIDE_INT_PRINT_DEC, actual_fsize);
|
||||
if (regs_ever_live[2])
|
||||
fputs (",CALLS,SAVE_RP", file);
|
||||
else
|
||||
@ -3603,8 +3689,9 @@ void
|
||||
hppa_expand_prologue (void)
|
||||
{
|
||||
int merge_sp_adjust_with_store = 0;
|
||||
int size = get_frame_size ();
|
||||
int i, offset;
|
||||
HOST_WIDE_INT size = get_frame_size ();
|
||||
HOST_WIDE_INT offset;
|
||||
int i;
|
||||
rtx insn, tmpreg;
|
||||
|
||||
gr_saved = 0;
|
||||
@ -3668,8 +3755,8 @@ hppa_expand_prologue (void)
|
||||
So instead use stwm to store at *sp and post-increment the
|
||||
stack pointer as an atomic operation. Then increment sp to
|
||||
finish allocating the new frame. */
|
||||
int adjust1 = 8192 - 64;
|
||||
int adjust2 = actual_fsize - adjust1;
|
||||
HOST_WIDE_INT adjust1 = 8192 - 64;
|
||||
HOST_WIDE_INT adjust2 = actual_fsize - adjust1;
|
||||
|
||||
store_reg_modify (STACK_POINTER_REGNUM, 1, adjust1);
|
||||
set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
|
||||
@ -3901,26 +3988,39 @@ hppa_expand_prologue (void)
|
||||
Handle case where DISP > 8k by using the add_high_const patterns. */
|
||||
|
||||
static void
|
||||
load_reg (int reg, int disp, int base)
|
||||
load_reg (int reg, HOST_WIDE_INT disp, int base)
|
||||
{
|
||||
rtx src, dest, basereg;
|
||||
rtx dest = gen_rtx_REG (word_mode, reg);
|
||||
rtx basereg = gen_rtx_REG (Pmode, base);
|
||||
rtx src;
|
||||
|
||||
dest = gen_rtx_REG (word_mode, reg);
|
||||
basereg = gen_rtx_REG (Pmode, base);
|
||||
if (VAL_14_BITS_P (disp))
|
||||
src = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
|
||||
else if (TARGET_64BIT && !VAL_32_BITS_P (disp))
|
||||
{
|
||||
src = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
|
||||
emit_move_insn (dest, src);
|
||||
rtx delta = GEN_INT (disp);
|
||||
rtx tmpreg = gen_rtx_REG (Pmode, 1);
|
||||
|
||||
emit_move_insn (tmpreg, delta);
|
||||
if (TARGET_DISABLE_INDEXING)
|
||||
{
|
||||
emit_move_insn (tmpreg, gen_rtx_PLUS (Pmode, tmpreg, basereg));
|
||||
src = gen_rtx_MEM (word_mode, tmpreg);
|
||||
}
|
||||
else
|
||||
src = gen_rtx_MEM (word_mode, gen_rtx_PLUS (Pmode, tmpreg, basereg));
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx delta = GEN_INT (disp);
|
||||
rtx high = gen_rtx_PLUS (Pmode, basereg, gen_rtx_HIGH (Pmode, delta));
|
||||
rtx tmpreg = gen_rtx_REG (Pmode, 1);
|
||||
|
||||
emit_move_insn (tmpreg, high);
|
||||
src = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta));
|
||||
emit_move_insn (dest, src);
|
||||
}
|
||||
|
||||
emit_move_insn (dest, src);
|
||||
}
|
||||
|
||||
/* Update the total code bytes output to the text section. */
|
||||
@ -4006,9 +4106,10 @@ void
|
||||
hppa_expand_epilogue (void)
|
||||
{
|
||||
rtx tmpreg;
|
||||
int offset, i;
|
||||
HOST_WIDE_INT offset;
|
||||
HOST_WIDE_INT ret_off = 0;
|
||||
int i;
|
||||
int merge_sp_adjust_with_load = 0;
|
||||
int ret_off = 0;
|
||||
|
||||
/* We will use this often. */
|
||||
tmpreg = gen_rtx_REG (word_mode, 1);
|
||||
|
@ -646,7 +646,6 @@ extern struct rtx_def *hppa_pic_save_rtx (void);
|
||||
to IN. If it can be done directly NO_REGS is returned.
|
||||
|
||||
Avoid doing any work for the common case calls. */
|
||||
|
||||
#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
|
||||
((CLASS == BASE_REG_CLASS && GET_CODE (IN) == REG \
|
||||
&& REGNO (IN) < FIRST_PSEUDO_REGISTER) \
|
||||
@ -1223,16 +1222,36 @@ extern int may_call_alloca;
|
||||
|| GET_CODE (X) == HIGH) \
|
||||
&& (reload_in_progress || reload_completed || ! symbolic_expression_p (X)))
|
||||
|
||||
/* Include all constant integers and constant doubles, but not
|
||||
floating-point, except for floating-point zero.
|
||||
/* A C expression that is nonzero if we are using the new HP assembler. */
|
||||
|
||||
Reject LABEL_REFs if we're not using gas or the new HP assembler.
|
||||
|
||||
?!? For now also reject CONST_DOUBLES in 64bit mode. This will need
|
||||
further work. */
|
||||
#ifndef NEW_HP_ASSEMBLER
|
||||
#define NEW_HP_ASSEMBLER 0
|
||||
#endif
|
||||
|
||||
/* The macros below define the immediate range for CONST_INTS on
|
||||
the 64-bit port. Constants in this range can be loaded in three
|
||||
instructions using a ldil/ldo/depdi sequence. Constants outside
|
||||
this range are forced to the constant pool prior to reload. */
|
||||
|
||||
#define MAX_LEGIT_64BIT_CONST_INT ((HOST_WIDE_INT) 32 << 31)
|
||||
#define MIN_LEGIT_64BIT_CONST_INT ((HOST_WIDE_INT) -32 << 31)
|
||||
#define LEGITIMATE_64BIT_CONST_INT_P(X) \
|
||||
((X) >= MIN_LEGIT_64BIT_CONST_INT && (X) < MAX_LEGIT_64BIT_CONST_INT)
|
||||
|
||||
/* A C expression that is nonzero if X is a legitimate constant for an
|
||||
immediate operand.
|
||||
|
||||
We include all constant integers and constant doubles, but not
|
||||
floating-point, except for floating-point zero. We reject LABEL_REFs
|
||||
if we're not using gas or the new HP assembler.
|
||||
|
||||
In 64-bit mode, we reject CONST_DOUBLES. We also reject CONST_INTS
|
||||
that need more than three instructions to load prior to reload. This
|
||||
limit is somewhat arbitrary. It takes three instructions to load a
|
||||
CONST_INT from memory but two are memory accesses. It may be better
|
||||
to increase the allowed range for CONST_INTS. We may also be able
|
||||
to handle CONST_DOUBLES. */
|
||||
|
||||
#define LEGITIMATE_CONSTANT_P(X) \
|
||||
((GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \
|
||||
|| (X) == CONST0_RTX (GET_MODE (X))) \
|
||||
@ -1240,8 +1259,8 @@ extern int may_call_alloca;
|
||||
&& !(TARGET_64BIT && GET_CODE (X) == CONST_DOUBLE) \
|
||||
&& !(TARGET_64BIT && GET_CODE (X) == CONST_INT \
|
||||
&& !(HOST_BITS_PER_WIDE_INT <= 32 \
|
||||
|| (INTVAL (X) >= (HOST_WIDE_INT) -32 << 31 \
|
||||
&& INTVAL (X) < (HOST_WIDE_INT) 32 << 31) \
|
||||
|| (reload_in_progress || reload_completed) \
|
||||
|| LEGITIMATE_64BIT_CONST_INT_P (INTVAL (X)) \
|
||||
|| cint_ok_for_move (INTVAL (X)))) \
|
||||
&& !function_label_operand (X, VOIDmode))
|
||||
|
||||
@ -1425,6 +1444,15 @@ extern int may_call_alloca;
|
||||
#define VAL_14_BITS_P(X) ((unsigned HOST_WIDE_INT)(X) + 0x2000 < 0x4000)
|
||||
#define INT_14_BITS(X) VAL_14_BITS_P (INTVAL (X))
|
||||
|
||||
#if HOST_BITS_PER_WIDE_INT > 32
|
||||
#define VAL_32_BITS_P(X) \
|
||||
((unsigned HOST_WIDE_INT)(X) + ((unsigned HOST_WIDE_INT) 1 << 31) \
|
||||
< (unsigned HOST_WIDE_INT) 2 << 31)
|
||||
#else
|
||||
#define VAL_32_BITS_P(X) 1
|
||||
#endif
|
||||
#define INT_32_BITS(X) VAL_32_BITS_P (INTVAL (X))
|
||||
|
||||
/* These are the modes that we allow for scaled indexing. */
|
||||
#define MODE_OK_FOR_SCALED_INDEXING_P(MODE) \
|
||||
((TARGET_64BIT && (MODE) == DImode) \
|
||||
@ -1557,14 +1585,13 @@ extern int may_call_alloca;
|
||||
There may be more opportunities to improve code with this hook. */
|
||||
#define LEGITIMIZE_RELOAD_ADDRESS(AD, MODE, OPNUM, TYPE, IND, WIN) \
|
||||
do { \
|
||||
int offset, newoffset, mask; \
|
||||
long offset, newoffset, mask; \
|
||||
rtx new, temp = NULL_RTX; \
|
||||
\
|
||||
mask = (GET_MODE_CLASS (MODE) == MODE_FLOAT \
|
||||
? (TARGET_PA_20 && !TARGET_ELF32 ? 0x3fff : 0x1f) : 0x3fff); \
|
||||
\
|
||||
if (optimize \
|
||||
&& GET_CODE (AD) == PLUS) \
|
||||
if (optimize && GET_CODE (AD) == PLUS) \
|
||||
temp = simplify_binary_operation (PLUS, Pmode, \
|
||||
XEXP (AD, 0), XEXP (AD, 1)); \
|
||||
\
|
||||
@ -1583,16 +1610,14 @@ do { \
|
||||
else \
|
||||
newoffset = offset & ~mask; \
|
||||
\
|
||||
if (newoffset != 0 \
|
||||
&& VAL_14_BITS_P (newoffset)) \
|
||||
if (newoffset != 0 && VAL_14_BITS_P (newoffset)) \
|
||||
{ \
|
||||
\
|
||||
temp = gen_rtx_PLUS (Pmode, XEXP (new, 0), \
|
||||
GEN_INT (newoffset)); \
|
||||
AD = gen_rtx_PLUS (Pmode, temp, GEN_INT (offset - newoffset));\
|
||||
push_reload (XEXP (AD, 0), 0, &XEXP (AD, 0), 0, \
|
||||
BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, \
|
||||
(OPNUM), (TYPE)); \
|
||||
BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, \
|
||||
(OPNUM), (TYPE)); \
|
||||
goto WIN; \
|
||||
} \
|
||||
} \
|
||||
|
Loading…
Reference in New Issue
Block a user