rs6000.c (rs6000_mixed_function_arg): Rewrite.
* config/rs6000/rs6000.c (rs6000_mixed_function_arg): Rewrite. (function_arg): Use rs6000_arg_size rather than CLASS_MAX_NREGS in calculating gpr size for altivec. Simplify and correct rs6000_mixed_function_arg calls. Call rs6000_mixed_function_arg for ABI_V4 gpr case too. Fix off-by-one error in long double reg test. Generate the correct PARALLEL to handle long double for ABI_AIX 32-bit. Use this for -m32 -mpowerpc64 fpr case too. (function_arg_partial_nregs): Align before calculating regs left. Don't return info on partial fprs when we need info on gprs. Correct long double fpr off-by-one error. From-SVN: r83951
This commit is contained in:
parent
cde0e59bf2
commit
ec6376abd7
@ -1,3 +1,16 @@
|
|||||||
|
2004-07-01 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* config/rs6000/rs6000.c (rs6000_mixed_function_arg): Rewrite.
|
||||||
|
(function_arg): Use rs6000_arg_size rather than CLASS_MAX_NREGS in
|
||||||
|
calculating gpr size for altivec. Simplify and correct
|
||||||
|
rs6000_mixed_function_arg calls. Call rs6000_mixed_function_arg
|
||||||
|
for ABI_V4 gpr case too. Fix off-by-one error in long double
|
||||||
|
reg test. Generate the correct PARALLEL to handle long double
|
||||||
|
for ABI_AIX 32-bit. Use this for -m32 -mpowerpc64 fpr case too.
|
||||||
|
(function_arg_partial_nregs): Align before calculating regs left.
|
||||||
|
Don't return info on partial fprs when we need info on gprs.
|
||||||
|
Correct long double fpr off-by-one error.
|
||||||
|
|
||||||
2004-06-30 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
|
2004-06-30 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
|
||||||
|
|
||||||
* pa-protos.h (prefetch_operand): Add prototype.
|
* pa-protos.h (prefetch_operand): Add prototype.
|
||||||
|
@ -425,8 +425,7 @@ static int rs6000_get_some_local_dynamic_name_1 (rtx *, void *);
|
|||||||
static rtx rs6000_complex_function_value (enum machine_mode);
|
static rtx rs6000_complex_function_value (enum machine_mode);
|
||||||
static rtx rs6000_spe_function_arg (CUMULATIVE_ARGS *,
|
static rtx rs6000_spe_function_arg (CUMULATIVE_ARGS *,
|
||||||
enum machine_mode, tree);
|
enum machine_mode, tree);
|
||||||
static rtx rs6000_mixed_function_arg (CUMULATIVE_ARGS *,
|
static rtx rs6000_mixed_function_arg (enum machine_mode, tree, int);
|
||||||
enum machine_mode, tree, int);
|
|
||||||
static void rs6000_move_block_from_reg (int regno, rtx x, int nregs);
|
static void rs6000_move_block_from_reg (int regno, rtx x, int nregs);
|
||||||
static void setup_incoming_varargs (CUMULATIVE_ARGS *,
|
static void setup_incoming_varargs (CUMULATIVE_ARGS *,
|
||||||
enum machine_mode, tree,
|
enum machine_mode, tree,
|
||||||
@ -4424,124 +4423,49 @@ rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
|||||||
/* Determine where to place an argument in 64-bit mode with 32-bit ABI. */
|
/* Determine where to place an argument in 64-bit mode with 32-bit ABI. */
|
||||||
|
|
||||||
static rtx
|
static rtx
|
||||||
rs6000_mixed_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
rs6000_mixed_function_arg (enum machine_mode mode, tree type, int align_words)
|
||||||
tree type, int align_words)
|
|
||||||
{
|
{
|
||||||
if (mode == DFmode)
|
int n_units;
|
||||||
{
|
int i, k;
|
||||||
/* -mpowerpc64 with 32bit ABI splits up a DFmode argument
|
rtx rvec[GP_ARG_NUM_REG + 1];
|
||||||
in vararg list into zero, one or two GPRs */
|
|
||||||
if (align_words >= GP_ARG_NUM_REG)
|
|
||||||
return gen_rtx_PARALLEL (DFmode,
|
|
||||||
gen_rtvec (2,
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
NULL_RTX, const0_rtx),
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (mode,
|
|
||||||
cum->fregno),
|
|
||||||
const0_rtx)));
|
|
||||||
else if (align_words + rs6000_arg_size (mode, type)
|
|
||||||
> GP_ARG_NUM_REG)
|
|
||||||
/* If this is partially on the stack, then we only
|
|
||||||
include the portion actually in registers here. */
|
|
||||||
return gen_rtx_PARALLEL (DFmode,
|
|
||||||
gen_rtvec (2,
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (SImode,
|
|
||||||
GP_ARG_MIN_REG
|
|
||||||
+ align_words),
|
|
||||||
const0_rtx),
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (mode,
|
|
||||||
cum->fregno),
|
|
||||||
const0_rtx)));
|
|
||||||
|
|
||||||
/* split a DFmode arg into two GPRs */
|
if (align_words >= GP_ARG_NUM_REG)
|
||||||
return gen_rtx_PARALLEL (DFmode,
|
return NULL_RTX;
|
||||||
gen_rtvec (3,
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (SImode,
|
|
||||||
GP_ARG_MIN_REG
|
|
||||||
+ align_words),
|
|
||||||
const0_rtx),
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (SImode,
|
|
||||||
GP_ARG_MIN_REG
|
|
||||||
+ align_words + 1),
|
|
||||||
GEN_INT (4)),
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (mode, cum->fregno),
|
|
||||||
const0_rtx)));
|
|
||||||
}
|
|
||||||
/* -mpowerpc64 with 32bit ABI splits up a DImode argument into one
|
|
||||||
or two GPRs */
|
|
||||||
else if (mode == DImode)
|
|
||||||
{
|
|
||||||
if (align_words < GP_ARG_NUM_REG - 1)
|
|
||||||
return gen_rtx_PARALLEL (DImode,
|
|
||||||
gen_rtvec (2,
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (SImode,
|
|
||||||
GP_ARG_MIN_REG
|
|
||||||
+ align_words),
|
|
||||||
const0_rtx),
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (SImode,
|
|
||||||
GP_ARG_MIN_REG
|
|
||||||
+ align_words + 1),
|
|
||||||
GEN_INT (4))));
|
|
||||||
else if (align_words == GP_ARG_NUM_REG - 1)
|
|
||||||
return gen_rtx_PARALLEL (DImode,
|
|
||||||
gen_rtvec (2,
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
NULL_RTX, const0_rtx),
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (SImode,
|
|
||||||
GP_ARG_MIN_REG
|
|
||||||
+ align_words),
|
|
||||||
const0_rtx)));
|
|
||||||
}
|
|
||||||
else if (ALTIVEC_VECTOR_MODE (mode) && align_words == GP_ARG_NUM_REG - 2)
|
|
||||||
{
|
|
||||||
/* Varargs vector regs must be saved in R9-R10. */
|
|
||||||
return gen_rtx_PARALLEL (mode,
|
|
||||||
gen_rtvec (3,
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
NULL_RTX, const0_rtx),
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (SImode,
|
|
||||||
GP_ARG_MIN_REG
|
|
||||||
+ align_words),
|
|
||||||
const0_rtx),
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (SImode,
|
|
||||||
GP_ARG_MIN_REG
|
|
||||||
+ align_words + 1),
|
|
||||||
GEN_INT (4))));
|
|
||||||
}
|
|
||||||
else if ((mode == BLKmode || ALTIVEC_VECTOR_MODE (mode))
|
|
||||||
&& align_words <= (GP_ARG_NUM_REG - 1))
|
|
||||||
{
|
|
||||||
/* AltiVec vector regs are saved in R5-R8. */
|
|
||||||
int k;
|
|
||||||
int size = int_size_in_bytes (type);
|
|
||||||
int no_units = ((size - 1) / 4) + 1;
|
|
||||||
int max_no_words = GP_ARG_NUM_REG - align_words;
|
|
||||||
int rtlvec_len = no_units < max_no_words ? no_units : max_no_words;
|
|
||||||
rtx *rtlvec = (rtx *) alloca (rtlvec_len * sizeof (rtx));
|
|
||||||
|
|
||||||
memset ((char *) rtlvec, 0, rtlvec_len * sizeof (rtx));
|
n_units = rs6000_arg_size (mode, type);
|
||||||
|
|
||||||
for (k=0; k < rtlvec_len; k++)
|
/* Optimize the simple case where the arg fits in one gpr, except in
|
||||||
rtlvec[k] = gen_rtx_EXPR_LIST (VOIDmode,
|
the case of BLKmode due to assign_parms assuming that registers are
|
||||||
gen_rtx_REG (SImode,
|
BITS_PER_WORD wide. */
|
||||||
GP_ARG_MIN_REG
|
if (n_units == 0
|
||||||
+ align_words + k),
|
|| (n_units == 1 && mode != BLKmode))
|
||||||
k == 0 ? const0_rtx : GEN_INT (k*4));
|
return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
|
||||||
|
|
||||||
return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rtlvec));
|
k = 0;
|
||||||
|
if (align_words + n_units > GP_ARG_NUM_REG)
|
||||||
|
/* Not all of the arg fits in gprs. Say that it goes in memory too,
|
||||||
|
using a magic NULL_RTX component.
|
||||||
|
FIXME: This is not strictly correct. Only some of the arg
|
||||||
|
belongs in memory, not all of it. However, there isn't any way
|
||||||
|
to do this currently, apart from building rtx descriptions for
|
||||||
|
the pieces of memory we want stored. Due to bugs in the generic
|
||||||
|
code we can't use the normal function_arg_partial_nregs scheme
|
||||||
|
with the PARALLEL arg description we emit here.
|
||||||
|
In any case, the code to store the whole arg to memory is often
|
||||||
|
more efficient than code to store pieces, and we know that space
|
||||||
|
is available in the right place for the whole arg. */
|
||||||
|
rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rtx r = gen_rtx_REG (SImode, GP_ARG_MIN_REG + align_words);
|
||||||
|
rtx off = GEN_INT (i++ * 4);
|
||||||
|
rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
|
||||||
}
|
}
|
||||||
return NULL_RTX;
|
while (++align_words < GP_ARG_NUM_REG && --n_units != 0);
|
||||||
|
|
||||||
|
return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine where to put an argument to a function.
|
/* Determine where to put an argument to a function.
|
||||||
@ -4636,8 +4560,8 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
|||||||
{
|
{
|
||||||
/* Vector parameters to varargs functions under AIX or Darwin
|
/* Vector parameters to varargs functions under AIX or Darwin
|
||||||
get passed in memory and possibly also in GPRs. */
|
get passed in memory and possibly also in GPRs. */
|
||||||
int align, align_words;
|
int align, align_words, n_words;
|
||||||
enum machine_mode part_mode = mode;
|
enum machine_mode part_mode;
|
||||||
|
|
||||||
/* Vector parameters must be 16-byte aligned. This places them at
|
/* Vector parameters must be 16-byte aligned. This places them at
|
||||||
2 mod 4 in terms of words in 32-bit mode, since the parameter
|
2 mod 4 in terms of words in 32-bit mode, since the parameter
|
||||||
@ -4653,20 +4577,20 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
|||||||
/* Out of registers? Memory, then. */
|
/* Out of registers? Memory, then. */
|
||||||
if (align_words >= GP_ARG_NUM_REG)
|
if (align_words >= GP_ARG_NUM_REG)
|
||||||
return NULL_RTX;
|
return NULL_RTX;
|
||||||
|
|
||||||
|
if (TARGET_32BIT && TARGET_POWERPC64)
|
||||||
|
return rs6000_mixed_function_arg (mode, type, align_words);
|
||||||
|
|
||||||
/* The vector value goes in GPRs. Only the part of the
|
/* The vector value goes in GPRs. Only the part of the
|
||||||
value in GPRs is reported here. */
|
value in GPRs is reported here. */
|
||||||
if (align_words + CLASS_MAX_NREGS (mode, GENERAL_REGS)
|
part_mode = mode;
|
||||||
> GP_ARG_NUM_REG)
|
n_words = rs6000_arg_size (mode, type);
|
||||||
|
if (align_words + n_words > GP_ARG_NUM_REG)
|
||||||
/* Fortunately, there are only two possibilities, the value
|
/* Fortunately, there are only two possibilities, the value
|
||||||
is either wholly in GPRs or half in GPRs and half not. */
|
is either wholly in GPRs or half in GPRs and half not. */
|
||||||
part_mode = DImode;
|
part_mode = DImode;
|
||||||
|
|
||||||
if (TARGET_32BIT
|
return gen_rtx_REG (part_mode, GP_ARG_MIN_REG + align_words);
|
||||||
&& (TARGET_POWERPC64 || (align_words == GP_ARG_NUM_REG - 2)))
|
|
||||||
return rs6000_mixed_function_arg (cum, part_mode, type, align_words);
|
|
||||||
else
|
|
||||||
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))
|
||||||
@ -4693,10 +4617,13 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
|||||||
gregno += (1 - gregno) & 1;
|
gregno += (1 - gregno) & 1;
|
||||||
|
|
||||||
/* Multi-reg args are not split between registers and stack. */
|
/* Multi-reg args are not split between registers and stack. */
|
||||||
if (gregno + n_words - 1 <= GP_ARG_MAX_REG)
|
if (gregno + n_words - 1 > GP_ARG_MAX_REG)
|
||||||
return gen_rtx_REG (mode, gregno);
|
|
||||||
else
|
|
||||||
return NULL_RTX;
|
return NULL_RTX;
|
||||||
|
|
||||||
|
if (TARGET_32BIT && TARGET_POWERPC64)
|
||||||
|
return rs6000_mixed_function_arg (mode, type,
|
||||||
|
gregno - GP_ARG_MIN_REG);
|
||||||
|
return gen_rtx_REG (mode, gregno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -4706,25 +4633,23 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
|||||||
|
|
||||||
if (USE_FP_FOR_ARG_P (cum, mode, type))
|
if (USE_FP_FOR_ARG_P (cum, mode, type))
|
||||||
{
|
{
|
||||||
rtx fpr[2];
|
rtx rvec[GP_ARG_NUM_REG + 1];
|
||||||
rtx *r;
|
rtx r;
|
||||||
|
int k;
|
||||||
bool needs_psave;
|
bool needs_psave;
|
||||||
enum machine_mode fmode = mode;
|
enum machine_mode fmode = mode;
|
||||||
int n;
|
|
||||||
unsigned long n_fpreg = (GET_MODE_SIZE (mode) + 7) >> 3;
|
unsigned long n_fpreg = (GET_MODE_SIZE (mode) + 7) >> 3;
|
||||||
|
|
||||||
if (cum->fregno + n_fpreg > FP_ARG_MAX_REG + 1)
|
if (cum->fregno + n_fpreg > FP_ARG_MAX_REG + 1)
|
||||||
{
|
{
|
||||||
/* Long double split over regs and memory. */
|
|
||||||
if (fmode == TFmode)
|
|
||||||
fmode = DFmode;
|
|
||||||
|
|
||||||
/* Currently, we only ever need one reg here because complex
|
/* Currently, we only ever need one reg here because complex
|
||||||
doubles are split. */
|
doubles are split. */
|
||||||
if (cum->fregno != FP_ARG_MAX_REG - 1)
|
if (cum->fregno != FP_ARG_MAX_REG || fmode != TFmode)
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
|
/* Long double split over regs and memory. */
|
||||||
|
fmode = DFmode;
|
||||||
}
|
}
|
||||||
fpr[1] = gen_rtx_REG (fmode, cum->fregno);
|
|
||||||
|
|
||||||
/* Do we also need to pass this arg in the parameter save
|
/* Do we also need to pass this arg in the parameter save
|
||||||
area? */
|
area? */
|
||||||
@ -4735,46 +4660,55 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
|||||||
&& align_words >= GP_ARG_NUM_REG)));
|
&& align_words >= GP_ARG_NUM_REG)));
|
||||||
|
|
||||||
if (!needs_psave && mode == fmode)
|
if (!needs_psave && mode == fmode)
|
||||||
return fpr[1];
|
return gen_rtx_REG (fmode, cum->fregno);
|
||||||
|
|
||||||
if (TARGET_32BIT && TARGET_POWERPC64
|
|
||||||
&& mode == DFmode && cum->stdarg)
|
|
||||||
return rs6000_mixed_function_arg (cum, mode, type, align_words);
|
|
||||||
|
|
||||||
/* Describe where this piece goes. */
|
|
||||||
r = fpr + 1;
|
|
||||||
*r = gen_rtx_EXPR_LIST (VOIDmode, *r, const0_rtx);
|
|
||||||
n = 1;
|
|
||||||
|
|
||||||
|
k = 0;
|
||||||
if (needs_psave)
|
if (needs_psave)
|
||||||
{
|
{
|
||||||
/* Now describe the part that goes in gprs or the stack.
|
/* Describe the part that goes in gprs or the stack.
|
||||||
This piece must come first, before the fprs. */
|
This piece must come first, before the fprs. */
|
||||||
rtx reg = NULL_RTX;
|
|
||||||
if (align_words < GP_ARG_NUM_REG)
|
if (align_words < GP_ARG_NUM_REG)
|
||||||
{
|
{
|
||||||
unsigned long n_words = rs6000_arg_size (mode, type);
|
unsigned long n_words = rs6000_arg_size (mode, type);
|
||||||
enum machine_mode rmode = mode;
|
|
||||||
|
|
||||||
if (align_words + n_words > GP_ARG_NUM_REG)
|
if (align_words + n_words > GP_ARG_NUM_REG
|
||||||
/* If this is partially on the stack, then we only
|
|| (TARGET_32BIT && TARGET_POWERPC64))
|
||||||
include the portion actually in registers here.
|
{
|
||||||
We know this can only be one register because
|
/* If this is partially on the stack, then we only
|
||||||
complex doubles are splt. */
|
include the portion actually in registers here. */
|
||||||
rmode = Pmode;
|
enum machine_mode rmode = TARGET_32BIT ? SImode : DImode;
|
||||||
reg = gen_rtx_REG (rmode, GP_ARG_MIN_REG + align_words);
|
rtx off;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
r = gen_rtx_REG (rmode,
|
||||||
|
GP_ARG_MIN_REG + align_words);
|
||||||
|
off = GEN_INT (k * GET_MODE_SIZE (rmode));
|
||||||
|
rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
|
||||||
|
}
|
||||||
|
while (++align_words < GP_ARG_NUM_REG && --n_words != 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The whole arg fits in gprs. */
|
||||||
|
r = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
|
||||||
|
rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, const0_rtx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*--r = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx);
|
else
|
||||||
++n;
|
/* It's entirely in memory. */
|
||||||
|
rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return gen_rtx_PARALLEL (mode, gen_rtvec_v (n, r));
|
/* Describe where this piece goes in the fprs. */
|
||||||
|
r = gen_rtx_REG (fmode, cum->fregno);
|
||||||
|
rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, const0_rtx);
|
||||||
|
|
||||||
|
return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec));
|
||||||
}
|
}
|
||||||
else if (align_words < GP_ARG_NUM_REG)
|
else if (align_words < GP_ARG_NUM_REG)
|
||||||
{
|
{
|
||||||
if (TARGET_32BIT && TARGET_POWERPC64
|
if (TARGET_32BIT && TARGET_POWERPC64)
|
||||||
&& (mode == DImode || mode == BLKmode))
|
return rs6000_mixed_function_arg (mode, type, align_words);
|
||||||
return rs6000_mixed_function_arg (cum, mode, type, align_words);
|
|
||||||
|
|
||||||
return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
|
return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
|
||||||
}
|
}
|
||||||
@ -4783,15 +4717,20 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For an arg passed partly in registers and partly in memory,
|
/* For an arg passed partly in registers and partly in memory, this is
|
||||||
this is the number of registers used.
|
the number of registers used. For args passed entirely in registers
|
||||||
For args passed entirely in registers or entirely in memory, zero. */
|
or entirely in memory, zero. When an arg is described by a PARALLEL,
|
||||||
|
perhaps using more than one register type, this function returns the
|
||||||
|
number of registers used by the first element of the PARALLEL. */
|
||||||
|
|
||||||
int
|
int
|
||||||
function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
||||||
tree type, int named)
|
tree type, int named)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
int align;
|
||||||
|
int parm_offset;
|
||||||
|
int align_words;
|
||||||
|
|
||||||
if (DEFAULT_ABI == ABI_V4)
|
if (DEFAULT_ABI == ABI_V4)
|
||||||
return 0;
|
return 0;
|
||||||
@ -4800,17 +4739,29 @@ function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
|||||||
&& cum->nargs_prototype >= 0)
|
&& cum->nargs_prototype >= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (USE_FP_FOR_ARG_P (cum, mode, type))
|
align = function_arg_boundary (mode, type) / PARM_BOUNDARY - 1;
|
||||||
|
parm_offset = TARGET_32BIT ? 2 : 0;
|
||||||
|
align_words = cum->words + ((parm_offset - cum->words) & align);
|
||||||
|
|
||||||
|
if (USE_FP_FOR_ARG_P (cum, mode, type)
|
||||||
|
/* If we are passing this arg in gprs as well, then this function
|
||||||
|
should return the number of gprs (or memory) partially passed,
|
||||||
|
*not* the number of fprs. */
|
||||||
|
&& !(type
|
||||||
|
&& (cum->nargs_prototype <= 0
|
||||||
|
|| (DEFAULT_ABI == ABI_AIX
|
||||||
|
&& TARGET_XL_CALL
|
||||||
|
&& align_words >= GP_ARG_NUM_REG))))
|
||||||
{
|
{
|
||||||
if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3) > FP_ARG_MAX_REG + 1)
|
if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3) > FP_ARG_MAX_REG + 1)
|
||||||
ret = FP_ARG_MAX_REG - cum->fregno;
|
ret = FP_ARG_MAX_REG + 1 - cum->fregno;
|
||||||
else if (cum->nargs_prototype >= 0)
|
else if (cum->nargs_prototype >= 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cum->words < GP_ARG_NUM_REG
|
if (align_words < GP_ARG_NUM_REG
|
||||||
&& GP_ARG_NUM_REG < cum->words + rs6000_arg_size (mode, type))
|
&& GP_ARG_NUM_REG < align_words + rs6000_arg_size (mode, type))
|
||||||
ret = GP_ARG_NUM_REG - cum->words;
|
ret = GP_ARG_NUM_REG - align_words;
|
||||||
|
|
||||||
if (ret != 0 && TARGET_DEBUG_ARG)
|
if (ret != 0 && TARGET_DEBUG_ARG)
|
||||||
fprintf (stderr, "function_arg_partial_nregs: %d\n", ret);
|
fprintf (stderr, "function_arg_partial_nregs: %d\n", ret);
|
||||||
|
Loading…
Reference in New Issue
Block a user