aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2004-10-26 12:28:59 +0000
committerAldy Hernandez <aldyh@gcc.gnu.org>2004-10-26 12:28:59 +0000
commitf82f556dac8378f2c7e469b71e411ea721bc12e5 (patch)
tree0eed431f856523aba5fc164abfaa429854dfebfb
parent8db8c940f180e23567dab2fb34a27e272d27fe4c (diff)
downloadgcc-f82f556dac8378f2c7e469b71e411ea721bc12e5.zip
gcc-f82f556dac8378f2c7e469b71e411ea721bc12e5.tar.gz
gcc-f82f556dac8378f2c7e469b71e411ea721bc12e5.tar.bz2
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
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/config/rs6000/rs6000.c68
-rw-r--r--gcc/config/rs6000/rs6000.h7
3 files changed, 81 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 64fe9ab..bc2a4ec 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,22 @@
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>
+
* expr.c (emit_group_load): Handle floats.
(emit_group_store): Same.
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index adf4fec..6909859 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -3281,6 +3281,8 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
return false;
if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
return false;
+ if (TARGET_E500_DOUBLE && mode == DFmode)
+ return false;
x = XEXP (x, 1);
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_DOUBLE
&& CONSTANT_P (x)
- && ((TARGET_HARD_FLOAT && TARGET_FPRS)
- || (mode != DFmode || TARGET_E500_DOUBLE))
+ && ((TARGET_HARD_FLOAT && TARGET_FPRS) || mode != DFmode)
&& mode != DImode
&& 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
rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
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)
{
- int gregno = cum->sysv_gregno;
int n_words = rs6000_arg_size (mode, type);
/* SPE vectors are put in odd registers. */
@@ -4964,8 +5000,8 @@ rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
}
else
{
- if (cum->sysv_gregno <= GP_ARG_MAX_REG)
- return gen_rtx_REG (mode, cum->sysv_gregno);
+ if (gregno <= GP_ARG_MAX_REG)
+ return gen_rtx_REG (mode, gregno);
else
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);
}
}
- 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);
else if (abi == ABI_V4)
{
@@ -12543,9 +12581,15 @@ spe_func_has_64bit_regs_p (void)
rtx i;
i = PATTERN (insn);
- if (GET_CODE (i) == SET
- && SPE_VECTOR_MODE (GET_MODE (SET_SRC (i))))
- return true;
+ if (GET_CODE (i) == SET)
+ {
+ 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
&& ALTIVEC_VECTOR_MODE(mode))
regno = ALTIVEC_ARG_RETURN;
+ else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT && mode == DFmode)
+ return spe_build_register_parallel (DFmode, GP_ARG_RETURN);
else
regno = GP_ARG_RETURN;
@@ -18113,6 +18159,8 @@ rs6000_libcall_value (enum machine_mode mode)
regno = ALTIVEC_ARG_RETURN;
else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg)
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
regno = GP_ARG_RETURN;
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 0a209b6..a64d682 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -742,6 +742,7 @@ extern const char *rs6000_warn_altivec_long_switch;
that the object would ordinarily have. */
#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
((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)
/* Alignment of field after `int : 0' in a structure. */
@@ -774,9 +775,11 @@ extern const char *rs6000_warn_altivec_long_switch;
: (ALIGN))
/* 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) \
(TREE_CODE (TYPE) == VECTOR_TYPE ? (TARGET_SPE_ABI ? 64 : 128) \
+ : (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 \
: TREE_CODE (TYPE) == ARRAY_TYPE \
&& TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
&& (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
@@ -1433,6 +1436,8 @@ enum reg_class
? 0 \
: GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
? 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) \
? reg_classes_intersect_p (GENERAL_REGS, CLASS) \
: 0)