Commit 436bd917 by Segher Boessenkool Committed by Segher Boessenkool

rs6000.c (rs6000_parallel_return): New function.

	* 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.

From-SVN: r219804
parent 3b97ab5a
2015-01-17 Segher Boessenkool <segher@kernel.crashing.org>
* 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.
2015-01-17 Sandra Loosemore <sandra@codesourcery.com> 2015-01-17 Sandra Loosemore <sandra@codesourcery.com>
* doc/invoke.texi ([-ftracer]): Remove duplicate option listing. * doc/invoke.texi ([-ftracer]): Remove duplicate option listing.
......
...@@ -31583,6 +31583,29 @@ rs6000_complex_function_value (machine_mode mode) ...@@ -31583,6 +31583,29 @@ rs6000_complex_function_value (machine_mode mode)
return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2)); 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. /* Target hook for TARGET_FUNCTION_VALUE.
On the SPE, both FPs and vectors are returned in r3. On the SPE, both FPs and vectors are returned in r3.
...@@ -31618,12 +31641,12 @@ rs6000_function_value (const_tree valtype, ...@@ -31618,12 +31641,12 @@ rs6000_function_value (const_tree valtype,
/* Otherwise fall through to standard ABI rules. */ /* Otherwise fall through to standard ABI rules. */
} }
mode = TYPE_MODE (valtype);
/* The ELFv2 ABI returns homogeneous VFP aggregates in registers. */ /* The ELFv2 ABI returns homogeneous VFP aggregates in registers. */
if (rs6000_discover_homogeneous_aggregate (TYPE_MODE (valtype), valtype, if (rs6000_discover_homogeneous_aggregate (mode, valtype, &elt_mode, &n_elts))
&elt_mode, &n_elts))
{ {
int first_reg, n_regs, i; int first_reg, n_regs;
rtx par;
if (SCALAR_FLOAT_MODE_P (elt_mode)) if (SCALAR_FLOAT_MODE_P (elt_mode))
{ {
...@@ -31637,53 +31660,25 @@ rs6000_function_value (const_tree valtype, ...@@ -31637,53 +31660,25 @@ rs6000_function_value (const_tree valtype,
n_regs = 1; n_regs = 1;
} }
par = gen_rtx_PARALLEL (TYPE_MODE (valtype), rtvec_alloc (n_elts)); return rs6000_parallel_return (mode, n_elts, elt_mode, first_reg, n_regs);
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;
} }
if (TARGET_32BIT && TARGET_POWERPC64 && TYPE_MODE (valtype) == DImode) /* Some return value types need be split in -mpowerpc64, 32bit ABI. */
{ if (TARGET_32BIT && TARGET_POWERPC64)
/* Long long return value need be split in -mpowerpc64, 32bit ABI. */ switch (mode)
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, default:
gen_rtvec (4, break;
gen_rtx_EXPR_LIST (VOIDmode, case DImode:
gen_rtx_REG (SImode, GP_ARG_RETURN), case SCmode:
const0_rtx), case DCmode:
gen_rtx_EXPR_LIST (VOIDmode, case TCmode:
gen_rtx_REG (SImode, int count = GET_MODE_SIZE (mode) / 4;
GP_ARG_RETURN + 1), return rs6000_parallel_return (mode, count, 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))));
} }
mode = TYPE_MODE (valtype); if ((INTEGRAL_TYPE_P (valtype)
if ((INTEGRAL_TYPE_P (valtype) && GET_MODE_BITSIZE (mode) < BITS_PER_WORD) && GET_MODE_BITSIZE (mode) < (TARGET_32BIT ? 32 : 64))
|| POINTER_TYPE_P (valtype)) || POINTER_TYPE_P (valtype))
mode = TARGET_32BIT ? SImode : DImode; mode = TARGET_32BIT ? SImode : DImode;
...@@ -31720,19 +31715,9 @@ rs6000_libcall_value (machine_mode mode) ...@@ -31720,19 +31715,9 @@ rs6000_libcall_value (machine_mode mode)
{ {
unsigned int regno; unsigned int regno;
if (TARGET_32BIT && TARGET_POWERPC64 && mode == DImode)
{
/* Long long return value need be split in -mpowerpc64, 32bit ABI. */ /* Long long return value need be split in -mpowerpc64, 32bit ABI. */
return gen_rtx_PARALLEL (DImode, if (TARGET_32BIT && TARGET_POWERPC64 && mode == DImode)
gen_rtvec (2, return rs6000_parallel_return (mode, 2, SImode, GP_ARG_RETURN, 1);
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 (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS) if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
/* _Decimal128 must use an even/odd register pair. */ /* _Decimal128 must use an even/odd register pair. */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment