re PR target/32889 (ICE in delete_output_reload, at reload1.c:7926)
PR middle-end/32889 PR target/34091 * pa.md: Consolidate HImode and QImode move patterns into one pattern each, eliminating floating-point alternatives. * pa-protos.h (pa_cannot_change_mode_class, pa_modes_tieable_p): Declare functions. * pa-64.h (SECONDARY_MEMORY_NEEDED): Define here. * pa.c (pa_secondary_reload): Use an intermediate general register for copies to/from floating-point register classes. Simplify code SHIFT_REGS class. Provide additional comments. (pa_cannot_change_mode_class, pa_modes_tieable_p): New functions. * pa.h (MODES_TIEABLE_P): Use pa_modes_tieable_p. (SECONDARY_MEMORY_NEEDED): Delete define. (INT14_OK_STRICT): Define. (MODE_OK_FOR_SCALED_INDEXING_P): Allow SFmode and DFmode when using soft float. (MODE_OK_FOR_UNSCALED_INDEXING_P): Likewise. (GO_IF_LEGITIMATE_ADDRESS): Use INT14_OK_STRICT in REG+D case for SFmode and DFmode. (LEGITIMIZE_RELOAD_ADDRESS): Use INT14_OK_STRICT in mask selection. Align DImode offsets when generating 64-bit code. * pa32-regs.h (VALID_FP_MODE_P): Remove QImode and HImode. (CANNOT_CHANGE_MODE_CLASS): Define. * pa64-regs.h (VALID_FP_MODE_P): Remove QImode and HImode. (CANNOT_CHANGE_MODE_CLASS): Define using pa_cannot_change_mode_class. From-SVN: r130725
This commit is contained in:
parent
fad0afd7d7
commit
6982c5d4c8
@ -1,3 +1,31 @@
|
|||||||
|
2007-12-09 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
|
||||||
|
|
||||||
|
PR middle-end/32889
|
||||||
|
PR target/34091
|
||||||
|
* pa.md: Consolidate HImode and QImode move patterns into one pattern
|
||||||
|
each, eliminating floating-point alternatives.
|
||||||
|
* pa-protos.h (pa_cannot_change_mode_class, pa_modes_tieable_p):
|
||||||
|
Declare functions.
|
||||||
|
* pa-64.h (SECONDARY_MEMORY_NEEDED): Define here.
|
||||||
|
* pa.c (pa_secondary_reload): Use an intermediate general register
|
||||||
|
for copies to/from floating-point register classes. Simplify code
|
||||||
|
SHIFT_REGS class. Provide additional comments.
|
||||||
|
(pa_cannot_change_mode_class, pa_modes_tieable_p): New functions.
|
||||||
|
* pa.h (MODES_TIEABLE_P): Use pa_modes_tieable_p.
|
||||||
|
(SECONDARY_MEMORY_NEEDED): Delete define.
|
||||||
|
(INT14_OK_STRICT): Define.
|
||||||
|
(MODE_OK_FOR_SCALED_INDEXING_P): Allow SFmode and DFmode when using
|
||||||
|
soft float.
|
||||||
|
(MODE_OK_FOR_UNSCALED_INDEXING_P): Likewise.
|
||||||
|
(GO_IF_LEGITIMATE_ADDRESS): Use INT14_OK_STRICT in REG+D case for
|
||||||
|
SFmode and DFmode.
|
||||||
|
(LEGITIMIZE_RELOAD_ADDRESS): Use INT14_OK_STRICT in mask selection.
|
||||||
|
Align DImode offsets when generating 64-bit code.
|
||||||
|
* pa32-regs.h (VALID_FP_MODE_P): Remove QImode and HImode.
|
||||||
|
(CANNOT_CHANGE_MODE_CLASS): Define.
|
||||||
|
* pa64-regs.h (VALID_FP_MODE_P): Remove QImode and HImode.
|
||||||
|
(CANNOT_CHANGE_MODE_CLASS): Define using pa_cannot_change_mode_class.
|
||||||
|
|
||||||
2007-12-09 Jakub Jelinek <jakub@redhat.com>
|
2007-12-09 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR fortran/22244
|
PR fortran/22244
|
||||||
|
@ -84,3 +84,17 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
want aggregates padded down. */
|
want aggregates padded down. */
|
||||||
|
|
||||||
#define PAD_VARARGS_DOWN (!AGGREGATE_TYPE_P (type))
|
#define PAD_VARARGS_DOWN (!AGGREGATE_TYPE_P (type))
|
||||||
|
|
||||||
|
/* In the PA architecture, it is not possible to directly move data
|
||||||
|
between GENERAL_REGS and FP_REGS. On the 32-bit port, we use the
|
||||||
|
location at SP-16 because PA 1.X only supports 5-bit immediates for
|
||||||
|
floating-point loads and stores. We don't expose this location in
|
||||||
|
the RTL to avoid scheduling related problems. For example, the
|
||||||
|
store and load could be separated by a call to a pure or const
|
||||||
|
function which has no frame and this function might also use SP-16.
|
||||||
|
We have 14-bit immediates on the 64-bit port, so we use secondary
|
||||||
|
memory for the copies. */
|
||||||
|
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
|
||||||
|
(MAYBE_FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2) \
|
||||||
|
|| MAYBE_FP_REG_CLASS_P (CLASS2) != FP_REG_CLASS_P (CLASS1))
|
||||||
|
|
||||||
|
@ -172,6 +172,9 @@ extern void pa_asm_output_aligned_local (FILE *, const char *,
|
|||||||
unsigned HOST_WIDE_INT,
|
unsigned HOST_WIDE_INT,
|
||||||
unsigned int);
|
unsigned int);
|
||||||
extern void pa_hpux_asm_output_external (FILE *, tree, const char *);
|
extern void pa_hpux_asm_output_external (FILE *, tree, const char *);
|
||||||
|
extern bool pa_cannot_change_mode_class (enum machine_mode, enum machine_mode,
|
||||||
|
enum reg_class);
|
||||||
|
extern bool pa_modes_tieable_p (enum machine_mode, enum machine_mode);
|
||||||
|
|
||||||
extern const int magic_milli[];
|
extern const int magic_milli[];
|
||||||
extern int shadd_constant_p (int);
|
extern int shadd_constant_p (int);
|
||||||
|
@ -5687,12 +5687,49 @@ pa_secondary_reload (bool in_p, rtx x, enum reg_class class,
|
|||||||
if (regno >= FIRST_PSEUDO_REGISTER || GET_CODE (x) == SUBREG)
|
if (regno >= FIRST_PSEUDO_REGISTER || GET_CODE (x) == SUBREG)
|
||||||
regno = true_regnum (x);
|
regno = true_regnum (x);
|
||||||
|
|
||||||
/* Handle out of range displacement for integer mode loads/stores of
|
/* In order to allow 14-bit displacements in integer loads and stores,
|
||||||
FP registers. */
|
we need to prevent reload from generating out of range integer mode
|
||||||
if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
|
loads and stores to the floating point registers. Previously, we
|
||||||
&& GET_MODE_CLASS (mode) == MODE_INT
|
used to call for a secondary reload and have emit_move_sequence()
|
||||||
&& FP_REG_CLASS_P (class))
|
fix the instruction sequence. However, reload occasionally wouldn't
|
||||||
|| (class == SHIFT_REGS && (regno <= 0 || regno >= 32)))
|
generate the reload and we would end up with an invalid REG+D memory
|
||||||
|
address. So, now we use an intermediate general register for most
|
||||||
|
memory loads and stores. */
|
||||||
|
if ((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
|
||||||
|
&& GET_MODE_CLASS (mode) == MODE_INT
|
||||||
|
&& FP_REG_CLASS_P (class))
|
||||||
|
{
|
||||||
|
/* Reload passes (mem:SI (reg/f:DI 30 %r30) when it wants to check
|
||||||
|
the secondary reload needed for a pseudo. It never passes a
|
||||||
|
REG+D address. */
|
||||||
|
if (GET_CODE (x) == MEM)
|
||||||
|
{
|
||||||
|
x = XEXP (x, 0);
|
||||||
|
|
||||||
|
/* We don't need an intermediate for indexed and LO_SUM DLT
|
||||||
|
memory addresses. When INT14_OK_STRICT is true, it might
|
||||||
|
appear that we could directly allow register indirect
|
||||||
|
memory addresses. However, this doesn't work because we
|
||||||
|
don't support SUBREGs in floating-point register copies
|
||||||
|
and reload doesn't tell us when it's going to use a SUBREG. */
|
||||||
|
if (IS_INDEX_ADDR_P (x)
|
||||||
|
|| IS_LO_SUM_DLT_ADDR_P (x))
|
||||||
|
return NO_REGS;
|
||||||
|
|
||||||
|
/* Otherwise, we need an intermediate general register. */
|
||||||
|
return GENERAL_REGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Request a secondary reload with a general scratch register
|
||||||
|
for everthing else. ??? Could symbolic operands be handled
|
||||||
|
directly when generating non-pic PA 2.0 code? */
|
||||||
|
sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
|
||||||
|
return NO_REGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We need a secondary register (GPR) for copies between the SAR
|
||||||
|
and anything other than a general register. */
|
||||||
|
if (class == SHIFT_REGS && (regno <= 0 || regno >= 32))
|
||||||
{
|
{
|
||||||
sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
|
sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
|
||||||
return NO_REGS;
|
return NO_REGS;
|
||||||
@ -5701,16 +5738,15 @@ pa_secondary_reload (bool in_p, rtx x, enum reg_class class,
|
|||||||
/* A SAR<->FP register copy requires a secondary register (GPR) as
|
/* A SAR<->FP register copy requires a secondary register (GPR) as
|
||||||
well as secondary memory. */
|
well as secondary memory. */
|
||||||
if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER
|
if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER
|
||||||
&& ((REGNO_REG_CLASS (regno) == SHIFT_REGS && FP_REG_CLASS_P (class))
|
&& (REGNO_REG_CLASS (regno) == SHIFT_REGS
|
||||||
|| (class == SHIFT_REGS
|
&& FP_REG_CLASS_P (class)))
|
||||||
&& FP_REG_CLASS_P (REGNO_REG_CLASS (regno)))))
|
|
||||||
{
|
{
|
||||||
sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
|
sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
|
||||||
return NO_REGS;
|
return NO_REGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Secondary reloads of symbolic operands require %r1 as a scratch
|
/* Secondary reloads of symbolic operands require %r1 as a scratch
|
||||||
register when we're generating PIC code and the operand isn't
|
register when we're generating PIC code and when the operand isn't
|
||||||
readonly. */
|
readonly. */
|
||||||
if (GET_CODE (x) == HIGH)
|
if (GET_CODE (x) == HIGH)
|
||||||
x = XEXP (x, 0);
|
x = XEXP (x, 0);
|
||||||
@ -9570,4 +9606,62 @@ pa_hpux_file_end (void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Return true if a change from mode FROM to mode TO for a register
|
||||||
|
in register class CLASS is invalid. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
pa_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
|
||||||
|
enum reg_class class)
|
||||||
|
{
|
||||||
|
if (from == to)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Reject changes to/from complex and vector modes. */
|
||||||
|
if (COMPLEX_MODE_P (from) || VECTOR_MODE_P (from)
|
||||||
|
|| COMPLEX_MODE_P (to) || VECTOR_MODE_P (to))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (GET_MODE_SIZE (from) == GET_MODE_SIZE (to))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* There is no way to load QImode or HImode values directly from
|
||||||
|
memory. SImode loads to the FP registers are not zero extended.
|
||||||
|
On the 64-bit target, this conflicts with the definition of
|
||||||
|
LOAD_EXTEND_OP. Thus, we can't allow changing between modes
|
||||||
|
with different sizes in the floating-point registers. */
|
||||||
|
if (MAYBE_FP_REG_CLASS_P (class))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* HARD_REGNO_MODE_OK places modes with sizes larger than a word
|
||||||
|
in specific sets of registers. Thus, we cannot allow changing
|
||||||
|
to a larger mode when it's larger than a word. */
|
||||||
|
if (GET_MODE_SIZE (to) > UNITS_PER_WORD
|
||||||
|
&& GET_MODE_SIZE (to) > GET_MODE_SIZE (from))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns TRUE if it is a good idea to tie two pseudo registers
|
||||||
|
when one has mode MODE1 and one has mode MODE2.
|
||||||
|
If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
|
||||||
|
for any hard reg, then this must be FALSE for correct output.
|
||||||
|
|
||||||
|
We should return FALSE for QImode and HImode because these modes
|
||||||
|
are not ok in the floating-point registers. However, this prevents
|
||||||
|
tieing these modes to SImode and DImode in the general registers.
|
||||||
|
So, this isn't a good idea. We rely on HARD_REGNO_MODE_OK and
|
||||||
|
CANNOT_CHANGE_MODE_CLASS to prevent these modes from being used
|
||||||
|
in the floating-point registers. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
pa_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
|
||||||
|
{
|
||||||
|
/* Don't tie modes in different classes. */
|
||||||
|
if (GET_MODE_CLASS (mode1) != GET_MODE_CLASS (mode2))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#include "gt-pa.h"
|
#include "gt-pa.h"
|
||||||
|
@ -349,7 +349,7 @@ typedef struct machine_function GTY(())
|
|||||||
If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
|
If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
|
||||||
for any hard reg, then this must be 0 for correct output. */
|
for any hard reg, then this must be 0 for correct output. */
|
||||||
#define MODES_TIEABLE_P(MODE1, MODE2) \
|
#define MODES_TIEABLE_P(MODE1, MODE2) \
|
||||||
(GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
|
pa_modes_tieable_p (MODE1, MODE2)
|
||||||
|
|
||||||
/* Specify the registers used for certain standard purposes.
|
/* Specify the registers used for certain standard purposes.
|
||||||
The values of these macros are register numbers. */
|
The values of these macros are register numbers. */
|
||||||
@ -497,17 +497,6 @@ extern struct rtx_def *hppa_pic_save_rtx (void);
|
|||||||
#define MAYBE_FP_REG_CLASS_P(CLASS) \
|
#define MAYBE_FP_REG_CLASS_P(CLASS) \
|
||||||
reg_classes_intersect_p ((CLASS), FP_REGS)
|
reg_classes_intersect_p ((CLASS), FP_REGS)
|
||||||
|
|
||||||
/* On the PA it is not possible to directly move data between
|
|
||||||
GENERAL_REGS and FP_REGS. On the 32-bit port, we use the
|
|
||||||
location at SP-16. We don't expose this location in the RTL to
|
|
||||||
avoid scheduling related problems. For example, the store and
|
|
||||||
load could be separated by a call to a pure or const function
|
|
||||||
which has no frame and uses SP-16. */
|
|
||||||
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
|
|
||||||
(TARGET_64BIT \
|
|
||||||
&& (MAYBE_FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2) \
|
|
||||||
|| MAYBE_FP_REG_CLASS_P (CLASS2) != FP_REG_CLASS_P (CLASS1)))
|
|
||||||
|
|
||||||
|
|
||||||
/* Stack layout; function entry, exit and calling. */
|
/* Stack layout; function entry, exit and calling. */
|
||||||
|
|
||||||
@ -1116,6 +1105,24 @@ extern int may_call_alloca;
|
|||||||
&& REG_OK_FOR_BASE_P (XEXP (OP, 0)) \
|
&& REG_OK_FOR_BASE_P (XEXP (OP, 0)) \
|
||||||
&& GET_CODE (XEXP (OP, 1)) == UNSPEC)
|
&& GET_CODE (XEXP (OP, 1)) == UNSPEC)
|
||||||
|
|
||||||
|
/* Nonzero if 14-bit offsets can be used for all loads and stores.
|
||||||
|
This is not possible when generating PA 1.x code as floating point
|
||||||
|
loads and stores only support 5-bit offsets. Note that we do not
|
||||||
|
forbid the use of 14-bit offsets in GO_IF_LEGITIMATE_ADDRESS.
|
||||||
|
Instead, we use pa_secondary_reload() to reload integer mode
|
||||||
|
REG+D memory addresses used in floating point loads and stores.
|
||||||
|
|
||||||
|
FIXME: the ELF32 linker clobbers the LSB of the FP register number
|
||||||
|
in PA 2.0 floating-point insns with long displacements. This is
|
||||||
|
because R_PARISC_DPREL14WR and other relocations like it are not
|
||||||
|
yet supported by GNU ld. For now, we reject long displacements
|
||||||
|
on this target. */
|
||||||
|
|
||||||
|
#define INT14_OK_STRICT \
|
||||||
|
(TARGET_SOFT_FLOAT \
|
||||||
|
|| TARGET_DISABLE_FPREGS \
|
||||||
|
|| (TARGET_PA_20 && !TARGET_ELF32))
|
||||||
|
|
||||||
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
|
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
|
||||||
and check its validity for a certain class.
|
and check its validity for a certain class.
|
||||||
We have two alternate definitions for each of them.
|
We have two alternate definitions for each of them.
|
||||||
@ -1134,16 +1141,18 @@ extern int may_call_alloca;
|
|||||||
/* Nonzero if X is a hard reg that can be used as an index
|
/* Nonzero if X is a hard reg that can be used as an index
|
||||||
or if it is a pseudo reg. */
|
or if it is a pseudo reg. */
|
||||||
#define REG_OK_FOR_INDEX_P(X) \
|
#define REG_OK_FOR_INDEX_P(X) \
|
||||||
(REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
|
(REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
|
||||||
|
|
||||||
/* Nonzero if X is a hard reg that can be used as a base reg
|
/* Nonzero if X is a hard reg that can be used as a base reg
|
||||||
or if it is a pseudo reg. */
|
or if it is a pseudo reg. */
|
||||||
#define REG_OK_FOR_BASE_P(X) \
|
#define REG_OK_FOR_BASE_P(X) \
|
||||||
(REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
|
(REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* Nonzero if X is a hard reg that can be used as an index. */
|
/* Nonzero if X is a hard reg that can be used as an index. */
|
||||||
#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
|
#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
|
||||||
|
|
||||||
/* Nonzero if X is a hard reg that can be used as a base reg. */
|
/* Nonzero if X is a hard reg that can be used as a base reg. */
|
||||||
#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
|
#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
|
||||||
|
|
||||||
@ -1195,11 +1204,7 @@ extern int may_call_alloca;
|
|||||||
|
|
||||||
We treat a SYMBOL_REF as legitimate if it is part of the current
|
We treat a SYMBOL_REF as legitimate if it is part of the current
|
||||||
function's constant-pool, because such addresses can actually be
|
function's constant-pool, because such addresses can actually be
|
||||||
output as REG+SMALLINT.
|
output as REG+SMALLINT. */
|
||||||
|
|
||||||
Note we only allow 5-bit immediates for access to a constant address;
|
|
||||||
doing so avoids losing for loading/storing a FP register at an address
|
|
||||||
which will not fit in 5 bits. */
|
|
||||||
|
|
||||||
#define VAL_5_BITS_P(X) ((unsigned HOST_WIDE_INT)(X) + 0x10 < 0x20)
|
#define VAL_5_BITS_P(X) ((unsigned HOST_WIDE_INT)(X) + 0x10 < 0x20)
|
||||||
#define INT_5_BITS(X) VAL_5_BITS_P (INTVAL (X))
|
#define INT_5_BITS(X) VAL_5_BITS_P (INTVAL (X))
|
||||||
@ -1227,7 +1232,8 @@ extern int may_call_alloca;
|
|||||||
((TARGET_64BIT && (MODE) == DImode) \
|
((TARGET_64BIT && (MODE) == DImode) \
|
||||||
|| (MODE) == SImode \
|
|| (MODE) == SImode \
|
||||||
|| (MODE) == HImode \
|
|| (MODE) == HImode \
|
||||||
|| (!TARGET_SOFT_FLOAT && ((MODE) == DFmode || (MODE) == SFmode)))
|
|| (MODE) == SFmode \
|
||||||
|
|| (MODE) == DFmode)
|
||||||
|
|
||||||
/* These are the modes that we allow for unscaled indexing. */
|
/* These are the modes that we allow for unscaled indexing. */
|
||||||
#define MODE_OK_FOR_UNSCALED_INDEXING_P(MODE) \
|
#define MODE_OK_FOR_UNSCALED_INDEXING_P(MODE) \
|
||||||
@ -1235,7 +1241,8 @@ extern int may_call_alloca;
|
|||||||
|| (MODE) == SImode \
|
|| (MODE) == SImode \
|
||||||
|| (MODE) == HImode \
|
|| (MODE) == HImode \
|
||||||
|| (MODE) == QImode \
|
|| (MODE) == QImode \
|
||||||
|| (!TARGET_SOFT_FLOAT && ((MODE) == DFmode || (MODE) == SFmode)))
|
|| (MODE) == SFmode \
|
||||||
|
|| (MODE) == DFmode)
|
||||||
|
|
||||||
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
|
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
|
||||||
{ \
|
{ \
|
||||||
@ -1269,20 +1276,10 @@ extern int may_call_alloca;
|
|||||||
|| (INTVAL (index) % 8) == 0)) \
|
|| (INTVAL (index) % 8) == 0)) \
|
||||||
/* Similarly, the base register for SFmode/DFmode \
|
/* Similarly, the base register for SFmode/DFmode \
|
||||||
loads and stores with long displacements must \
|
loads and stores with long displacements must \
|
||||||
be aligned. \
|
be aligned. */ \
|
||||||
\
|
|
||||||
FIXME: the ELF32 linker clobbers the LSB of \
|
|
||||||
the FP register number in PA 2.0 floating-point \
|
|
||||||
insns with long displacements. This is because \
|
|
||||||
R_PARISC_DPREL14WR and other relocations like \
|
|
||||||
it are not supported. For now, we reject long \
|
|
||||||
displacements on this target. */ \
|
|
||||||
|| (((MODE) == SFmode || (MODE) == DFmode) \
|
|| (((MODE) == SFmode || (MODE) == DFmode) \
|
||||||
&& (TARGET_SOFT_FLOAT \
|
&& INT14_OK_STRICT \
|
||||||
|| (TARGET_PA_20 \
|
&& (INTVAL (index) % GET_MODE_SIZE (MODE)) == 0))) \
|
||||||
&& !TARGET_ELF32 \
|
|
||||||
&& (INTVAL (index) \
|
|
||||||
% GET_MODE_SIZE (MODE)) == 0))))) \
|
|
||||||
|| INT_5_BITS (index))) \
|
|| INT_5_BITS (index))) \
|
||||||
goto ADDR; \
|
goto ADDR; \
|
||||||
if (!TARGET_DISABLE_INDEXING \
|
if (!TARGET_DISABLE_INDEXING \
|
||||||
@ -1382,7 +1379,7 @@ do { \
|
|||||||
rtx new, temp = NULL_RTX; \
|
rtx new, temp = NULL_RTX; \
|
||||||
\
|
\
|
||||||
mask = (GET_MODE_CLASS (MODE) == MODE_FLOAT \
|
mask = (GET_MODE_CLASS (MODE) == MODE_FLOAT \
|
||||||
? (TARGET_PA_20 && !TARGET_ELF32 ? 0x3fff : 0x1f) : 0x3fff); \
|
? (INT14_OK_STRICT ? 0x3fff : 0x1f) : 0x3fff); \
|
||||||
\
|
\
|
||||||
if (optimize && GET_CODE (AD) == PLUS) \
|
if (optimize && GET_CODE (AD) == PLUS) \
|
||||||
temp = simplify_binary_operation (PLUS, Pmode, \
|
temp = simplify_binary_operation (PLUS, Pmode, \
|
||||||
@ -1404,9 +1401,10 @@ do { \
|
|||||||
newoffset = offset & ~mask; \
|
newoffset = offset & ~mask; \
|
||||||
\
|
\
|
||||||
/* Ensure that long displacements are aligned. */ \
|
/* Ensure that long displacements are aligned. */ \
|
||||||
if (!VAL_5_BITS_P (newoffset) \
|
if (mask == 0x3fff \
|
||||||
&& GET_MODE_CLASS (MODE) == MODE_FLOAT) \
|
&& (GET_MODE_CLASS (MODE) == MODE_FLOAT \
|
||||||
newoffset &= ~(GET_MODE_SIZE (MODE) -1); \
|
|| (TARGET_64BIT && (MODE) == DImode))) \
|
||||||
|
newoffset &= ~(GET_MODE_SIZE (MODE) - 1); \
|
||||||
\
|
\
|
||||||
if (newoffset != 0 && VAL_14_BITS_P (newoffset)) \
|
if (newoffset != 0 && VAL_14_BITS_P (newoffset)) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -3181,62 +3181,13 @@
|
|||||||
DONE;
|
DONE;
|
||||||
}")
|
}")
|
||||||
|
|
||||||
(define_insn ""
|
|
||||||
[(set (match_operand:HI 0 "move_dest_operand"
|
|
||||||
"=r,r,r,r,r,Q,!*q,!r,!*f,?r,?*f")
|
|
||||||
(match_operand:HI 1 "move_src_operand"
|
|
||||||
"r,J,N,K,RQ,rM,!rM,!*q,!*fM,*f,r"))]
|
|
||||||
"(register_operand (operands[0], HImode)
|
|
||||||
|| reg_or_0_operand (operands[1], HImode))
|
|
||||||
&& !TARGET_SOFT_FLOAT
|
|
||||||
&& !TARGET_64BIT"
|
|
||||||
"@
|
|
||||||
copy %1,%0
|
|
||||||
ldi %1,%0
|
|
||||||
ldil L'%1,%0
|
|
||||||
{zdepi|depwi,z} %Z1,%0
|
|
||||||
ldh%M1 %1,%0
|
|
||||||
sth%M0 %r1,%0
|
|
||||||
mtsar %r1
|
|
||||||
{mfctl|mfctl,w} %sar,%0
|
|
||||||
fcpy,sgl %f1,%0
|
|
||||||
{fstws|fstw} %1,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0
|
|
||||||
{stws|stw} %1,-16(%%sp)\n\t{fldws|fldw} -16(%%sp),%0"
|
|
||||||
[(set_attr "type" "move,move,move,shift,load,store,move,move,move,fpstore_load,store_fpload")
|
|
||||||
(set_attr "pa_combine_type" "addmove")
|
|
||||||
(set_attr "length" "4,4,4,4,4,4,4,4,4,8,8")])
|
|
||||||
|
|
||||||
(define_insn ""
|
|
||||||
[(set (match_operand:HI 0 "move_dest_operand"
|
|
||||||
"=r,r,r,r,r,Q,!*q,!r,!*f")
|
|
||||||
(match_operand:HI 1 "move_src_operand"
|
|
||||||
"r,J,N,K,RQ,rM,!rM,!*q,!*fM"))]
|
|
||||||
"(register_operand (operands[0], HImode)
|
|
||||||
|| reg_or_0_operand (operands[1], HImode))
|
|
||||||
&& !TARGET_SOFT_FLOAT
|
|
||||||
&& TARGET_64BIT"
|
|
||||||
"@
|
|
||||||
copy %1,%0
|
|
||||||
ldi %1,%0
|
|
||||||
ldil L'%1,%0
|
|
||||||
{zdepi|depwi,z} %Z1,%0
|
|
||||||
ldh%M1 %1,%0
|
|
||||||
sth%M0 %r1,%0
|
|
||||||
mtsar %r1
|
|
||||||
{mfctl|mfctl,w} %sar,%0
|
|
||||||
fcpy,sgl %f1,%0"
|
|
||||||
[(set_attr "type" "move,move,move,shift,load,store,move,move,move")
|
|
||||||
(set_attr "pa_combine_type" "addmove")
|
|
||||||
(set_attr "length" "4,4,4,4,4,4,4,4,4")])
|
|
||||||
|
|
||||||
(define_insn ""
|
(define_insn ""
|
||||||
[(set (match_operand:HI 0 "move_dest_operand"
|
[(set (match_operand:HI 0 "move_dest_operand"
|
||||||
"=r,r,r,r,r,Q,!*q,!r")
|
"=r,r,r,r,r,Q,!*q,!r")
|
||||||
(match_operand:HI 1 "move_src_operand"
|
(match_operand:HI 1 "move_src_operand"
|
||||||
"r,J,N,K,RQ,rM,!rM,!*q"))]
|
"r,J,N,K,RQ,rM,!rM,!*q"))]
|
||||||
"(register_operand (operands[0], HImode)
|
"(register_operand (operands[0], HImode)
|
||||||
|| reg_or_0_operand (operands[1], HImode))
|
|| reg_or_0_operand (operands[1], HImode))"
|
||||||
&& TARGET_SOFT_FLOAT"
|
|
||||||
"@
|
"@
|
||||||
copy %1,%0
|
copy %1,%0
|
||||||
ldi %1,%0
|
ldi %1,%0
|
||||||
@ -3354,62 +3305,13 @@
|
|||||||
DONE;
|
DONE;
|
||||||
}")
|
}")
|
||||||
|
|
||||||
(define_insn ""
|
|
||||||
[(set (match_operand:QI 0 "move_dest_operand"
|
|
||||||
"=r,r,r,r,r,Q,!*q,!r,!*f,?r,?*f")
|
|
||||||
(match_operand:QI 1 "move_src_operand"
|
|
||||||
"r,J,N,K,RQ,rM,!rM,!*q,!*fM,*f,r"))]
|
|
||||||
"(register_operand (operands[0], QImode)
|
|
||||||
|| reg_or_0_operand (operands[1], QImode))
|
|
||||||
&& !TARGET_SOFT_FLOAT
|
|
||||||
&& !TARGET_64BIT"
|
|
||||||
"@
|
|
||||||
copy %1,%0
|
|
||||||
ldi %1,%0
|
|
||||||
ldil L'%1,%0
|
|
||||||
{zdepi|depwi,z} %Z1,%0
|
|
||||||
ldb%M1 %1,%0
|
|
||||||
stb%M0 %r1,%0
|
|
||||||
mtsar %r1
|
|
||||||
{mfctl|mfctl,w} %%sar,%0
|
|
||||||
fcpy,sgl %f1,%0
|
|
||||||
{fstws|fstw} %1,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0
|
|
||||||
{stws|stw} %1,-16(%%sp)\n\t{fldws|fldw} -16(%%sp),%0"
|
|
||||||
[(set_attr "type" "move,move,move,shift,load,store,move,move,move,fpstore_load,store_fpload")
|
|
||||||
(set_attr "pa_combine_type" "addmove")
|
|
||||||
(set_attr "length" "4,4,4,4,4,4,4,4,4,8,8")])
|
|
||||||
|
|
||||||
(define_insn ""
|
|
||||||
[(set (match_operand:QI 0 "move_dest_operand"
|
|
||||||
"=r,r,r,r,r,Q,!*q,!r,!*f")
|
|
||||||
(match_operand:QI 1 "move_src_operand"
|
|
||||||
"r,J,N,K,RQ,rM,!rM,!*q,!*fM"))]
|
|
||||||
"(register_operand (operands[0], QImode)
|
|
||||||
|| reg_or_0_operand (operands[1], QImode))
|
|
||||||
&& !TARGET_SOFT_FLOAT
|
|
||||||
&& TARGET_64BIT"
|
|
||||||
"@
|
|
||||||
copy %1,%0
|
|
||||||
ldi %1,%0
|
|
||||||
ldil L'%1,%0
|
|
||||||
{zdepi|depwi,z} %Z1,%0
|
|
||||||
ldb%M1 %1,%0
|
|
||||||
stb%M0 %r1,%0
|
|
||||||
mtsar %r1
|
|
||||||
{mfctl|mfctl,w} %%sar,%0
|
|
||||||
fcpy,sgl %f1,%0"
|
|
||||||
[(set_attr "type" "move,move,move,shift,load,store,move,move,move")
|
|
||||||
(set_attr "pa_combine_type" "addmove")
|
|
||||||
(set_attr "length" "4,4,4,4,4,4,4,4,4")])
|
|
||||||
|
|
||||||
(define_insn ""
|
(define_insn ""
|
||||||
[(set (match_operand:QI 0 "move_dest_operand"
|
[(set (match_operand:QI 0 "move_dest_operand"
|
||||||
"=r,r,r,r,r,Q,!*q,!r")
|
"=r,r,r,r,r,Q,!*q,!r")
|
||||||
(match_operand:QI 1 "move_src_operand"
|
(match_operand:QI 1 "move_src_operand"
|
||||||
"r,J,N,K,RQ,rM,!rM,!*q"))]
|
"r,J,N,K,RQ,rM,!rM,!*q"))]
|
||||||
"(register_operand (operands[0], QImode)
|
"(register_operand (operands[0], QImode)
|
||||||
|| reg_or_0_operand (operands[1], QImode))
|
|| reg_or_0_operand (operands[1], QImode))"
|
||||||
&& TARGET_SOFT_FLOAT"
|
|
||||||
"@
|
"@
|
||||||
copy %1,%0
|
copy %1,%0
|
||||||
ldi %1,%0
|
ldi %1,%0
|
||||||
|
@ -172,8 +172,7 @@
|
|||||||
#define VALID_FP_MODE_P(MODE) \
|
#define VALID_FP_MODE_P(MODE) \
|
||||||
((MODE) == SFmode || (MODE) == DFmode \
|
((MODE) == SFmode || (MODE) == DFmode \
|
||||||
|| (MODE) == SCmode || (MODE) == DCmode \
|
|| (MODE) == SCmode || (MODE) == DCmode \
|
||||||
|| (MODE) == QImode || (MODE) == HImode || (MODE) == SImode \
|
|| (MODE) == SImode || (TARGET_PA_11 && (MODE) == DImode))
|
||||||
|| (TARGET_PA_11 && (MODE) == DImode))
|
|
||||||
|
|
||||||
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
|
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
|
||||||
|
|
||||||
@ -288,6 +287,11 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS,
|
|||||||
{0x00000000, 0x00000000, 0x01000000}, /* SHIFT_REGS */ \
|
{0x00000000, 0x00000000, 0x01000000}, /* SHIFT_REGS */ \
|
||||||
{0xfffffffe, 0xffffffff, 0x01ffffff}} /* ALL_REGS */
|
{0xfffffffe, 0xffffffff, 0x01ffffff}} /* ALL_REGS */
|
||||||
|
|
||||||
|
/* Defines invalid mode changes. */
|
||||||
|
|
||||||
|
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
|
||||||
|
pa_cannot_change_mode_class (FROM, TO, CLASS)
|
||||||
|
|
||||||
/* Return the class number of the smallest class containing
|
/* Return the class number of the smallest class containing
|
||||||
reg number REGNO. This could be a conditional expression
|
reg number REGNO. This could be a conditional expression
|
||||||
or could index an array. */
|
or could index an array. */
|
||||||
|
@ -156,8 +156,7 @@ along with GCC; see the file COPYING3. If not see
|
|||||||
#define VALID_FP_MODE_P(MODE) \
|
#define VALID_FP_MODE_P(MODE) \
|
||||||
((MODE) == SFmode || (MODE) == DFmode \
|
((MODE) == SFmode || (MODE) == DFmode \
|
||||||
|| (MODE) == SCmode || (MODE) == DCmode \
|
|| (MODE) == SCmode || (MODE) == DCmode \
|
||||||
|| (MODE) == QImode || (MODE) == HImode || (MODE) == SImode \
|
|| (MODE) == SImode || (MODE) == DImode)
|
||||||
|| (MODE) == DImode)
|
|
||||||
|
|
||||||
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
|
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
|
||||||
On the HP-PA, the cpu registers can hold any mode. We
|
On the HP-PA, the cpu registers can hold any mode. We
|
||||||
@ -242,17 +241,10 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS,
|
|||||||
{0x00000000, 0x10000000}, /* SHIFT_REGS */ \
|
{0x00000000, 0x10000000}, /* SHIFT_REGS */ \
|
||||||
{0xfffffffe, 0x1fffffff}} /* ALL_REGS */
|
{0xfffffffe, 0x1fffffff}} /* ALL_REGS */
|
||||||
|
|
||||||
/* Defines invalid mode changes.
|
/* Defines invalid mode changes. */
|
||||||
|
|
||||||
SImode loads to floating-point registers are not zero-extended.
|
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
|
||||||
The definition for LOAD_EXTEND_OP specifies that integer loads
|
pa_cannot_change_mode_class (FROM, TO, CLASS)
|
||||||
narrower than BITS_PER_WORD will be zero-extended. As a result,
|
|
||||||
we inhibit changes from SImode unless they are to a mode that is
|
|
||||||
identical in size. */
|
|
||||||
|
|
||||||
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
|
|
||||||
((FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
|
|
||||||
? reg_classes_intersect_p (CLASS, FP_REGS) : 0)
|
|
||||||
|
|
||||||
/* Return the class number of the smallest class containing
|
/* Return the class number of the smallest class containing
|
||||||
reg number REGNO. This could be a conditional expression
|
reg number REGNO. This could be a conditional expression
|
||||||
|
Loading…
Reference in New Issue
Block a user