aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rs6000
diff options
context:
space:
mode:
authorsegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-17 20:58:12 +0000
committersegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-17 20:58:12 +0000
commitee645a3b86cbf1a4daa24da5cb21633ac66b66ce (patch)
treebf9cc8b3b7536e1431c8daf2fb9e0b35bbce462a /gcc/config/rs6000
parente4ee8a4804b8dfb51872616f028cdb49e9b587b1 (diff)
* config/rs6000/rs6000.c (rs6000_parallel_return): New function.
(rs6000_function_value): Use it. Handle SCmode and TCmode as well, for TARGET_32BIT && TARGET_POWERPC64. Fix another BITS_PER_WORD snafu. (rs6000_libcall_value): Use the new function. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@219804 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/rs6000')
-rw-r--r--gcc/config/rs6000/rs6000.c105
1 files changed, 45 insertions, 60 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 3926b079523..551181ba7a5 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -31583,6 +31583,29 @@ rs6000_complex_function_value (machine_mode mode)
return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2));
}
+/* Return an rtx describing a return value of MODE as a PARALLEL
+ in N_ELTS registers, each of mode ELT_MODE, starting at REGNO,
+ stride REG_STRIDE. */
+
+static rtx
+rs6000_parallel_return (machine_mode mode,
+ int n_elts, machine_mode elt_mode,
+ unsigned int regno, unsigned int reg_stride)
+{
+ rtx par = gen_rtx_PARALLEL (mode, rtvec_alloc (n_elts));
+
+ int i;
+ for (i = 0; i < n_elts; i++)
+ {
+ rtx r = gen_rtx_REG (elt_mode, regno);
+ rtx off = GEN_INT (i * GET_MODE_SIZE (elt_mode));
+ XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, r, off);
+ regno += reg_stride;
+ }
+
+ return par;
+}
+
/* Target hook for TARGET_FUNCTION_VALUE.
On the SPE, both FPs and vectors are returned in r3.
@@ -31618,12 +31641,12 @@ rs6000_function_value (const_tree valtype,
/* Otherwise fall through to standard ABI rules. */
}
+ mode = TYPE_MODE (valtype);
+
/* The ELFv2 ABI returns homogeneous VFP aggregates in registers. */
- if (rs6000_discover_homogeneous_aggregate (TYPE_MODE (valtype), valtype,
- &elt_mode, &n_elts))
+ if (rs6000_discover_homogeneous_aggregate (mode, valtype, &elt_mode, &n_elts))
{
- int first_reg, n_regs, i;
- rtx par;
+ int first_reg, n_regs;
if (SCALAR_FLOAT_MODE_P (elt_mode))
{
@@ -31637,53 +31660,25 @@ rs6000_function_value (const_tree valtype,
n_regs = 1;
}
- par = gen_rtx_PARALLEL (TYPE_MODE (valtype), rtvec_alloc (n_elts));
- for (i = 0; i < n_elts; i++)
- {
- rtx r = gen_rtx_REG (elt_mode, first_reg + i * n_regs);
- rtx off = GEN_INT (i * GET_MODE_SIZE (elt_mode));
- XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, r, off);
- }
-
- return par;
+ return rs6000_parallel_return (mode, n_elts, elt_mode, first_reg, n_regs);
}
- if (TARGET_32BIT && TARGET_POWERPC64 && TYPE_MODE (valtype) == DImode)
- {
- /* Long long return value need be split in -mpowerpc64, 32bit ABI. */
- return gen_rtx_PARALLEL (DImode,
- gen_rtvec (2,
- gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (SImode, GP_ARG_RETURN),
- const0_rtx),
- gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (SImode,
- GP_ARG_RETURN + 1),
- GEN_INT (4))));
- }
- if (TARGET_32BIT && TARGET_POWERPC64 && TYPE_MODE (valtype) == DCmode)
- {
- return gen_rtx_PARALLEL (DCmode,
- gen_rtvec (4,
- gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (SImode, GP_ARG_RETURN),
- const0_rtx),
- gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (SImode,
- GP_ARG_RETURN + 1),
- GEN_INT (4)),
- gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (SImode,
- GP_ARG_RETURN + 2),
- GEN_INT (8)),
- gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (SImode,
- GP_ARG_RETURN + 3),
- GEN_INT (12))));
- }
+ /* Some return value types need be split in -mpowerpc64, 32bit ABI. */
+ if (TARGET_32BIT && TARGET_POWERPC64)
+ switch (mode)
+ {
+ default:
+ break;
+ case DImode:
+ case SCmode:
+ case DCmode:
+ case TCmode:
+ int count = GET_MODE_SIZE (mode) / 4;
+ return rs6000_parallel_return (mode, count, SImode, GP_ARG_RETURN, 1);
+ }
- mode = TYPE_MODE (valtype);
- if ((INTEGRAL_TYPE_P (valtype) && GET_MODE_BITSIZE (mode) < BITS_PER_WORD)
+ if ((INTEGRAL_TYPE_P (valtype)
+ && GET_MODE_BITSIZE (mode) < (TARGET_32BIT ? 32 : 64))
|| POINTER_TYPE_P (valtype))
mode = TARGET_32BIT ? SImode : DImode;
@@ -31720,19 +31715,9 @@ rs6000_libcall_value (machine_mode mode)
{
unsigned int regno;
+ /* Long long return value need be split in -mpowerpc64, 32bit ABI. */
if (TARGET_32BIT && TARGET_POWERPC64 && mode == DImode)
- {
- /* Long long return value need be split in -mpowerpc64, 32bit ABI. */
- return gen_rtx_PARALLEL (DImode,
- gen_rtvec (2,
- gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (SImode, GP_ARG_RETURN),
- const0_rtx),
- gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (SImode,
- GP_ARG_RETURN + 1),
- GEN_INT (4))));
- }
+ return rs6000_parallel_return (mode, 2, SImode, GP_ARG_RETURN, 1);
if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
/* _Decimal128 must use an even/odd register pair. */