rs6000.c (rs6000_hard_regno_nregs): Adjust for e500 doubles.
* config/rs6000/rs6000.c (rs6000_hard_regno_nregs): Adjust for e500 doubles. (spe_build_register_parallel): New. (rs6000_spe_function_arg): Handle e500 doubles. (function_arg): Same. (spe_func_has_64bit_regs_p): Same. (rs6000_function_value): Same. (rs6000_libcall_value): Same. (legitimate_lo_sum_address_p): Return false for e500 doubles. * config/rs6000/rs6000.h (LOCAL_ALIGNMENT): Adjust for e500 doubles. (DATA_ALIGNMENT): Same. (CANNOT_CHANGE_MODE_CLASS): Same. From-SVN: r89582
This commit is contained in:
parent
8db8c940f1
commit
f82f556dac
@ -1,3 +1,20 @@
|
|||||||
|
2004-10-26 Aldy Hernandez <aldyh@redhat.com>
|
||||||
|
|
||||||
|
* config/rs6000/rs6000.c (rs6000_hard_regno_nregs): Adjust for
|
||||||
|
e500 doubles.
|
||||||
|
(spe_build_register_parallel): New.
|
||||||
|
(rs6000_spe_function_arg): Handle e500 doubles.
|
||||||
|
(function_arg): Same.
|
||||||
|
(spe_func_has_64bit_regs_p): Same.
|
||||||
|
(rs6000_function_value): Same.
|
||||||
|
(rs6000_libcall_value): Same.
|
||||||
|
(legitimate_lo_sum_address_p): Return false for e500 doubles.
|
||||||
|
|
||||||
|
* config/rs6000/rs6000.h (LOCAL_ALIGNMENT): Adjust for e500
|
||||||
|
doubles.
|
||||||
|
(DATA_ALIGNMENT): Same.
|
||||||
|
(CANNOT_CHANGE_MODE_CLASS): Same.
|
||||||
|
|
||||||
2004-10-26 Aldy Hernandez <aldyh@redhat.com>
|
2004-10-26 Aldy Hernandez <aldyh@redhat.com>
|
||||||
|
|
||||||
* expr.c (emit_group_load): Handle floats.
|
* expr.c (emit_group_load): Handle floats.
|
||||||
|
@ -3281,6 +3281,8 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
|
|||||||
return false;
|
return false;
|
||||||
if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
|
if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
|
||||||
return false;
|
return false;
|
||||||
|
if (TARGET_E500_DOUBLE && mode == DFmode)
|
||||||
|
return false;
|
||||||
x = XEXP (x, 1);
|
x = XEXP (x, 1);
|
||||||
|
|
||||||
if (TARGET_ELF || TARGET_MACHO)
|
if (TARGET_ELF || TARGET_MACHO)
|
||||||
@ -3418,8 +3420,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
|
|||||||
&& GET_CODE (x) != CONST_INT
|
&& GET_CODE (x) != CONST_INT
|
||||||
&& GET_CODE (x) != CONST_DOUBLE
|
&& GET_CODE (x) != CONST_DOUBLE
|
||||||
&& CONSTANT_P (x)
|
&& CONSTANT_P (x)
|
||||||
&& ((TARGET_HARD_FLOAT && TARGET_FPRS)
|
&& ((TARGET_HARD_FLOAT && TARGET_FPRS) || mode != DFmode)
|
||||||
|| (mode != DFmode || TARGET_E500_DOUBLE))
|
|
||||||
&& mode != DImode
|
&& mode != DImode
|
||||||
&& mode != TImode)
|
&& mode != TImode)
|
||||||
{
|
{
|
||||||
@ -4933,15 +4934,50 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine where to put a SIMD argument on the SPE. */
|
static rtx
|
||||||
|
spe_build_register_parallel (enum machine_mode mode, int gregno)
|
||||||
|
{
|
||||||
|
rtx r1, r2;
|
||||||
|
enum machine_mode inner;
|
||||||
|
unsigned int inner_bytes;
|
||||||
|
|
||||||
|
if (mode == DFmode)
|
||||||
|
{
|
||||||
|
inner = SImode;
|
||||||
|
inner_bytes = 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
r1 = gen_rtx_REG (inner, gregno);
|
||||||
|
r1 = gen_rtx_EXPR_LIST (SImode, r1, const0_rtx);
|
||||||
|
r2 = gen_rtx_REG (inner, gregno + 1);
|
||||||
|
r2 = gen_rtx_EXPR_LIST (SImode, r2, GEN_INT (inner_bytes));
|
||||||
|
return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine where to put a SIMD argument on the SPE. */
|
||||||
static rtx
|
static rtx
|
||||||
rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
||||||
tree type)
|
tree type)
|
||||||
{
|
{
|
||||||
|
int gregno = cum->sysv_gregno;
|
||||||
|
|
||||||
|
/* On E500 v2, double arithmetic is done on the full 64-bit GPR, but
|
||||||
|
are passed and returned in a pair of GPRs for ABI compatability. */
|
||||||
|
if (TARGET_E500_DOUBLE && mode == DFmode)
|
||||||
|
{
|
||||||
|
/* Doubles go in an odd/even register pair (r5/r6, etc). */
|
||||||
|
gregno += (1 - gregno) & 1;
|
||||||
|
|
||||||
|
/* We do not split between registers and stack. */
|
||||||
|
if (gregno + 1 > GP_ARG_MAX_REG)
|
||||||
|
return NULL_RTX;
|
||||||
|
|
||||||
|
return spe_build_register_parallel (mode, gregno);
|
||||||
|
}
|
||||||
if (cum->stdarg)
|
if (cum->stdarg)
|
||||||
{
|
{
|
||||||
int gregno = cum->sysv_gregno;
|
|
||||||
int n_words = rs6000_arg_size (mode, type);
|
int n_words = rs6000_arg_size (mode, type);
|
||||||
|
|
||||||
/* SPE vectors are put in odd registers. */
|
/* SPE vectors are put in odd registers. */
|
||||||
@ -4964,8 +5000,8 @@ rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (cum->sysv_gregno <= GP_ARG_MAX_REG)
|
if (gregno <= GP_ARG_MAX_REG)
|
||||||
return gen_rtx_REG (mode, cum->sysv_gregno);
|
return gen_rtx_REG (mode, gregno);
|
||||||
else
|
else
|
||||||
return NULL_RTX;
|
return NULL_RTX;
|
||||||
}
|
}
|
||||||
@ -5144,7 +5180,9 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
|||||||
return gen_rtx_REG (part_mode, GP_ARG_MIN_REG + align_words);
|
return gen_rtx_REG (part_mode, GP_ARG_MIN_REG + align_words);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (TARGET_SPE_ABI && TARGET_SPE && SPE_VECTOR_MODE (mode))
|
else if (TARGET_SPE_ABI && TARGET_SPE
|
||||||
|
&& (SPE_VECTOR_MODE (mode)
|
||||||
|
|| (TARGET_E500_DOUBLE && mode == DFmode)))
|
||||||
return rs6000_spe_function_arg (cum, mode, type);
|
return rs6000_spe_function_arg (cum, mode, type);
|
||||||
else if (abi == ABI_V4)
|
else if (abi == ABI_V4)
|
||||||
{
|
{
|
||||||
@ -12543,9 +12581,15 @@ spe_func_has_64bit_regs_p (void)
|
|||||||
rtx i;
|
rtx i;
|
||||||
|
|
||||||
i = PATTERN (insn);
|
i = PATTERN (insn);
|
||||||
if (GET_CODE (i) == SET
|
if (GET_CODE (i) == SET)
|
||||||
&& SPE_VECTOR_MODE (GET_MODE (SET_SRC (i))))
|
{
|
||||||
return true;
|
enum machine_mode mode = GET_MODE (SET_SRC (i));
|
||||||
|
|
||||||
|
if (SPE_VECTOR_MODE (mode))
|
||||||
|
return true;
|
||||||
|
if (TARGET_E500_DOUBLE && mode == DFmode)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18078,6 +18122,8 @@ rs6000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
|
|||||||
&& TARGET_ALTIVEC && TARGET_ALTIVEC_ABI
|
&& TARGET_ALTIVEC && TARGET_ALTIVEC_ABI
|
||||||
&& ALTIVEC_VECTOR_MODE(mode))
|
&& ALTIVEC_VECTOR_MODE(mode))
|
||||||
regno = ALTIVEC_ARG_RETURN;
|
regno = ALTIVEC_ARG_RETURN;
|
||||||
|
else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT && mode == DFmode)
|
||||||
|
return spe_build_register_parallel (DFmode, GP_ARG_RETURN);
|
||||||
else
|
else
|
||||||
regno = GP_ARG_RETURN;
|
regno = GP_ARG_RETURN;
|
||||||
|
|
||||||
@ -18113,6 +18159,8 @@ rs6000_libcall_value (enum machine_mode mode)
|
|||||||
regno = ALTIVEC_ARG_RETURN;
|
regno = ALTIVEC_ARG_RETURN;
|
||||||
else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg)
|
else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg)
|
||||||
return rs6000_complex_function_value (mode);
|
return rs6000_complex_function_value (mode);
|
||||||
|
else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT && mode == DFmode)
|
||||||
|
return spe_build_register_parallel (DFmode, GP_ARG_RETURN);
|
||||||
else
|
else
|
||||||
regno = GP_ARG_RETURN;
|
regno = GP_ARG_RETURN;
|
||||||
|
|
||||||
|
@ -742,6 +742,7 @@ extern const char *rs6000_warn_altivec_long_switch;
|
|||||||
that the object would ordinarily have. */
|
that the object would ordinarily have. */
|
||||||
#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
|
#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
|
||||||
((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \
|
((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \
|
||||||
|
(TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 : \
|
||||||
(TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE) ? 64 : ALIGN)
|
(TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE) ? 64 : ALIGN)
|
||||||
|
|
||||||
/* Alignment of field after `int : 0' in a structure. */
|
/* Alignment of field after `int : 0' in a structure. */
|
||||||
@ -774,9 +775,11 @@ extern const char *rs6000_warn_altivec_long_switch;
|
|||||||
: (ALIGN))
|
: (ALIGN))
|
||||||
|
|
||||||
/* Make arrays of chars word-aligned for the same reasons.
|
/* Make arrays of chars word-aligned for the same reasons.
|
||||||
Align vectors to 128 bits. */
|
Align vectors to 128 bits. Align SPE vectors and E500 v2 doubles to
|
||||||
|
64 bits. */
|
||||||
#define DATA_ALIGNMENT(TYPE, ALIGN) \
|
#define DATA_ALIGNMENT(TYPE, ALIGN) \
|
||||||
(TREE_CODE (TYPE) == VECTOR_TYPE ? (TARGET_SPE_ABI ? 64 : 128) \
|
(TREE_CODE (TYPE) == VECTOR_TYPE ? (TARGET_SPE_ABI ? 64 : 128) \
|
||||||
|
: (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 \
|
||||||
: TREE_CODE (TYPE) == ARRAY_TYPE \
|
: TREE_CODE (TYPE) == ARRAY_TYPE \
|
||||||
&& TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
|
&& TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
|
||||||
&& (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
|
&& (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
|
||||||
@ -1433,6 +1436,8 @@ enum reg_class
|
|||||||
? 0 \
|
? 0 \
|
||||||
: GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
|
: GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
|
||||||
? reg_classes_intersect_p (FLOAT_REGS, CLASS) \
|
? reg_classes_intersect_p (FLOAT_REGS, CLASS) \
|
||||||
|
: (TARGET_E500_DOUBLE && (((TO) == DFmode) + ((FROM) == DFmode)) == 1) \
|
||||||
|
? reg_classes_intersect_p (GENERAL_REGS, CLASS) \
|
||||||
: (TARGET_SPE && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1) \
|
: (TARGET_SPE && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1) \
|
||||||
? reg_classes_intersect_p (GENERAL_REGS, CLASS) \
|
? reg_classes_intersect_p (GENERAL_REGS, CLASS) \
|
||||||
: 0)
|
: 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user