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.
/* 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))
{
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;
{
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. */