summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authordanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>2004-01-20 22:20:07 +0000
committerdanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>2004-01-20 22:20:07 +0000
commit6bcdc1fbcd9e38e9268a1dec33c1af9e742863e5 (patch)
tree2044ee040dc7f65cb0a9dacb1c92212e777d264a /gcc
parentc09425a054eba423ceb4a2382e93d7d9ea15f1c3 (diff)
downloadgcc-6bcdc1fbcd9e38e9268a1dec33c1af9e742863e5.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@76234 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/config/pa/pa-protos.h2
-rw-r--r--gcc/config/pa/pa.c213
-rw-r--r--gcc/config/pa/pa.h59
4 files changed, 219 insertions, 74 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 31d731b36be..b82d6fbf389 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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,
diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h
index 9bf5e97e32c..fd7636e3047 100644
--- a/gcc/config/pa/pa-protos.h
+++ b/gcc/config/pa/pa-protos.h
@@ -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);
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index bcb8329770c..3d3b1ae0733 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -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]);
+
+ /* 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;
+ }
+ }
+ }
- if (extend != NULL_RTX)
- emit_insn (gen_insv (operands[0], GEN_INT (32), const0_rtx,
- extend));
+ 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);
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index 312d58c4213..79e03d28db4 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -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.
-
- Reject LABEL_REFs if we're not using gas or the new HP assembler.
+/* A C expression that is nonzero if we are using 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; \
} \
} \