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
This commit is contained in:
parent
3b97ab5aed
commit
436bd91737
@ -1,3 +1,11 @@
|
||||
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>
|
||||
|
||||
* doc/invoke.texi ([-ftracer]): Remove duplicate option listing.
|
||||
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user