mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-16 18:40:57 +08:00
rs6000.h (USE_FP_FOR_ARG_P): Move to rs6000.c.
* config/rs6000/rs6000.h (USE_FP_FOR_ARG_P): Move to rs6000.c. (USE_ALTIVEC_FOR_ARG_P): Likewise. * config/rs6000/rs6000.c (USE_FP_FOR_ARG_P): Move from rs6000.h. Take a pointer as the CUM parameter. Update callers. (USE_ALTIVEC_FOR_ARG_P): Likewise. Also correct for Darwin/AIX 32-bit ABIs. (function_arg_advance): Use USE_ALTIVEC_FOR_ARG_P. Correct case of vector parameters as named arguments of stdarg function. (function_arg): Likewise. * config/rs6000/darwin.h (ASM_SPEC): Use -force_cpusubtype_ALL when -maltivec is specified, not the non-existent -faltivec. From-SVN: r73317
This commit is contained in:
parent
8c17530ef3
commit
2858f73ac1
@ -1,3 +1,18 @@
|
||||
2003-11-06 Geoffrey Keating <geoffk@apple.com>
|
||||
|
||||
* config/rs6000/rs6000.h (USE_FP_FOR_ARG_P): Move to rs6000.c.
|
||||
(USE_ALTIVEC_FOR_ARG_P): Likewise.
|
||||
* config/rs6000/rs6000.c (USE_FP_FOR_ARG_P): Move from rs6000.h.
|
||||
Take a pointer as the CUM parameter. Update callers.
|
||||
(USE_ALTIVEC_FOR_ARG_P): Likewise. Also correct for Darwin/AIX
|
||||
32-bit ABIs.
|
||||
(function_arg_advance): Use USE_ALTIVEC_FOR_ARG_P. Correct case
|
||||
of vector parameters as named arguments of stdarg function.
|
||||
(function_arg): Likewise.
|
||||
|
||||
* config/rs6000/darwin.h (ASM_SPEC): Use -force_cpusubtype_ALL when
|
||||
-maltivec is specified, not the non-existent -faltivec.
|
||||
|
||||
2003-11-06 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* config/s390/s390-protos.h (s390_function_value): Declare.
|
||||
|
@ -100,7 +100,7 @@ do { \
|
||||
|
||||
#define ASM_SPEC "-arch ppc \
|
||||
%{Zforce_cpusubtype_ALL:-force_cpusubtype_ALL} \
|
||||
%{!Zforce_cpusubtype_ALL:%{faltivec:-force_cpusubtype_ALL}}"
|
||||
%{!Zforce_cpusubtype_ALL:%{maltivec:-force_cpusubtype_ALL}}"
|
||||
|
||||
#undef SUBTARGET_EXTRA_SPECS
|
||||
#define SUBTARGET_EXTRA_SPECS \
|
||||
|
@ -3618,6 +3618,19 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
|
||||
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
|
||||
}
|
||||
|
||||
/* Nonzero if we can use a floating-point register to pass this arg. */
|
||||
#define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \
|
||||
(GET_MODE_CLASS (MODE) == MODE_FLOAT \
|
||||
&& (CUM)->fregno <= FP_ARG_MAX_REG \
|
||||
&& TARGET_HARD_FLOAT && TARGET_FPRS)
|
||||
|
||||
/* Nonzero if we can use an AltiVec register to pass this arg. */
|
||||
#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED) \
|
||||
(ALTIVEC_VECTOR_MODE (MODE) \
|
||||
&& (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \
|
||||
&& TARGET_ALTIVEC_ABI \
|
||||
&& (DEFAULT_ABI == ABI_V4 || (NAMED)))
|
||||
|
||||
/* Return a nonzero value to say to return the function value in
|
||||
memory, just as large structures are always returned. TYPE will be
|
||||
the data type of the value, and FNTYPE will be the type of the
|
||||
@ -3802,23 +3815,35 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
||||
|
||||
if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
|
||||
{
|
||||
if (named && cum->vregno <= ALTIVEC_ARG_MAX_REG)
|
||||
if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
|
||||
cum->vregno++;
|
||||
else
|
||||
|
||||
/* In variable-argument functions, vector arguments get GPRs allocated
|
||||
even if they are going to be passed in a vector register. */
|
||||
if (cum->stdarg && DEFAULT_ABI != ABI_V4)
|
||||
{
|
||||
int align;
|
||||
|
||||
/* Vector parameters must be 16-byte aligned. This places them at
|
||||
2 mod 4 in terms of words (on both ABIs). */
|
||||
align = ((6 - (cum->words & 3)) & 3);
|
||||
/* 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 save area starts at offset 24 from the
|
||||
stack. In 64-bit mode, they just have to start on an
|
||||
even word, since the parameter save area is 16-byte
|
||||
aligned. Space for GPRs is reserved even if the argument
|
||||
will be passed in memory. */
|
||||
if (TARGET_32BIT)
|
||||
align = ((6 - (cum->words & 3)) & 3);
|
||||
else
|
||||
align = cum->words & 1;
|
||||
cum->words += align + RS6000_ARG_SIZE (mode, type);
|
||||
|
||||
|
||||
if (TARGET_DEBUG_ARG)
|
||||
{
|
||||
fprintf (stderr, "function_adv: words = %2d, align=%d, ",
|
||||
cum->words, align);
|
||||
fprintf (stderr, "nargs = %4d, proto = %d, mode = %4s\n",
|
||||
cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode));
|
||||
cum->nargs_prototype, cum->prototype,
|
||||
GET_MODE_NAME (mode));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4099,40 +4124,43 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
||||
return GEN_INT (cum->call_cookie);
|
||||
}
|
||||
|
||||
if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
|
||||
if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
|
||||
return gen_rtx_REG (mode, cum->vregno);
|
||||
else if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
|
||||
{
|
||||
if (named && cum->vregno <= ALTIVEC_ARG_MAX_REG)
|
||||
return gen_rtx_REG (mode, cum->vregno);
|
||||
else if (named || abi == ABI_V4)
|
||||
if (named || abi == ABI_V4)
|
||||
return NULL_RTX;
|
||||
else
|
||||
{
|
||||
/* Vector parameters to varargs functions under AIX or Darwin
|
||||
get passed in memory and possibly also in GPRs. */
|
||||
int align, align_words;
|
||||
rtx reg;
|
||||
enum machine_mode part_mode = mode;
|
||||
|
||||
/* Vector parameters must be 16-byte aligned. This places them at
|
||||
2 mod 4 in terms of words. */
|
||||
align = ((6 - (cum->words & 3)) & 3);
|
||||
2 mod 4 in terms of words in 32-bit mode, since the parameter
|
||||
save area starts at offset 24 from the stack. In 64-bit mode,
|
||||
they just have to start on an even word, since the parameter
|
||||
save area is 16-byte aligned. */
|
||||
if (TARGET_32BIT)
|
||||
align = ((6 - (cum->words & 3)) & 3);
|
||||
else
|
||||
align = cum->words & 1;
|
||||
align_words = cum->words + align;
|
||||
|
||||
/* Out of registers? Memory, then. */
|
||||
if (align_words >= GP_ARG_NUM_REG)
|
||||
return NULL_RTX;
|
||||
|
||||
/* The vector value goes in both memory and GPRs. Varargs
|
||||
vector regs will always be saved in R5-R8 or R9-R12. */
|
||||
reg = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
|
||||
|
||||
return gen_rtx_PARALLEL (mode,
|
||||
gen_rtvec (2,
|
||||
gen_rtx_EXPR_LIST (VOIDmode,
|
||||
NULL_RTX,
|
||||
const0_rtx),
|
||||
gen_rtx_EXPR_LIST (VOIDmode,
|
||||
reg,
|
||||
const0_rtx)));
|
||||
/* The vector value goes in GPRs. Only the part of the
|
||||
value in GPRs is reported here. */
|
||||
if (align_words + CLASS_MAX_NREGS (mode, GENERAL_REGS)
|
||||
> GP_ARG_NUM_REG)
|
||||
/* Fortunately, there are only two possibilites, the value
|
||||
is either wholly in GPRs or half in GPRs and half not. */
|
||||
part_mode = DImode;
|
||||
|
||||
return gen_rtx_REG (part_mode, GP_ARG_MIN_REG + align_words);
|
||||
}
|
||||
}
|
||||
else if (TARGET_SPE_ABI && TARGET_SPE && SPE_VECTOR_MODE (mode))
|
||||
@ -4183,7 +4211,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
||||
&& (mode == DFmode || mode == DImode || mode == BLKmode))
|
||||
return rs6000_mixed_function_arg (cum, mode, type, align_words);
|
||||
|
||||
if (USE_FP_FOR_ARG_P (*cum, mode, type))
|
||||
if (USE_FP_FOR_ARG_P (cum, mode, type))
|
||||
{
|
||||
if (! type
|
||||
|| ((cum->nargs_prototype > 0)
|
||||
@ -4228,13 +4256,13 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
||||
|
||||
int
|
||||
function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
||||
tree type, int named ATTRIBUTE_UNUSED)
|
||||
tree type, int named)
|
||||
{
|
||||
if (DEFAULT_ABI == ABI_V4)
|
||||
return 0;
|
||||
|
||||
if (USE_FP_FOR_ARG_P (*cum, mode, type)
|
||||
|| USE_ALTIVEC_FOR_ARG_P (*cum, mode, type))
|
||||
if (USE_FP_FOR_ARG_P (cum, mode, type)
|
||||
|| USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
|
||||
{
|
||||
if (cum->nargs_prototype >= 0)
|
||||
return 0;
|
||||
|
@ -1800,18 +1800,6 @@ typedef struct rs6000_args
|
||||
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
|
||||
function_arg_advance (&CUM, MODE, TYPE, NAMED)
|
||||
|
||||
/* Nonzero if we can use a floating-point register to pass this arg. */
|
||||
#define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \
|
||||
(GET_MODE_CLASS (MODE) == MODE_FLOAT \
|
||||
&& (CUM).fregno <= FP_ARG_MAX_REG \
|
||||
&& TARGET_HARD_FLOAT && TARGET_FPRS)
|
||||
|
||||
/* Nonzero if we can use an AltiVec register to pass this arg. */
|
||||
#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE) \
|
||||
(ALTIVEC_VECTOR_MODE (MODE) \
|
||||
&& (CUM).vregno <= ALTIVEC_ARG_MAX_REG \
|
||||
&& TARGET_ALTIVEC_ABI)
|
||||
|
||||
/* Determine where to put an argument to a function.
|
||||
Value is zero to push the argument on the stack,
|
||||
or a hard register in which to store the argument.
|
||||
|
@ -1,3 +1,7 @@
|
||||
2003-11-06 Geoffrey Keating <geoffk@apple.com>
|
||||
|
||||
* gcc.dg/altivec-varargs-1.c: New test.
|
||||
|
||||
2003-11-05 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
* gcc.c-torture/compile/20031023-4.c: XFAIL on SPARC64
|
||||
|
74
gcc/testsuite/gcc.dg/altivec-varargs-1.c
Normal file
74
gcc/testsuite/gcc.dg/altivec-varargs-1.c
Normal file
@ -0,0 +1,74 @@
|
||||
/* { dg-do run { target powerpc*-*-darwin* powerpc*-*-*altivec* } } */
|
||||
/* { dg-options "-maltivec" } */
|
||||
/* This test requires altivec, which means it'll fail on Darwin running
|
||||
on G3. FIXME. */
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#define vector __attribute__((mode(V4SI)))
|
||||
|
||||
const vector unsigned int v1 = {10,11,12,13};
|
||||
const vector unsigned int v2 = {20,21,22,23};
|
||||
const vector unsigned int v3 = {30,31,32,33};
|
||||
const vector unsigned int v4 = {40,41,42,43};
|
||||
|
||||
void foo(vector unsigned int a, ...)
|
||||
{
|
||||
va_list args;
|
||||
vector unsigned int v;
|
||||
|
||||
va_start (args, a);
|
||||
if (memcmp (&a, &v1, sizeof (v)) != 0)
|
||||
abort ();
|
||||
v = va_arg (args, vector unsigned int);
|
||||
if (memcmp (&v, &v2, sizeof (v)) != 0)
|
||||
abort ();
|
||||
v = va_arg (args, vector unsigned int);
|
||||
if (memcmp (&v, &v3, sizeof (v)) != 0)
|
||||
abort ();
|
||||
v = va_arg (args, vector unsigned int);
|
||||
if (memcmp (&v, &v4, sizeof (v)) != 0)
|
||||
abort ();
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void bar(vector unsigned int a, ...)
|
||||
{
|
||||
va_list args;
|
||||
vector unsigned int v;
|
||||
int b;
|
||||
|
||||
va_start (args, a);
|
||||
if (memcmp (&a, &v1, sizeof (v)) != 0)
|
||||
abort ();
|
||||
b = va_arg (args, int);
|
||||
if (b != 2)
|
||||
abort ();
|
||||
v = va_arg (args, vector unsigned int);
|
||||
if (memcmp (&v, &v2, sizeof (v)) != 0)
|
||||
abort ();
|
||||
v = va_arg (args, vector unsigned int);
|
||||
if (memcmp (&v, &v3, sizeof (v)) != 0)
|
||||
abort ();
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* In this call, in the Darwin ABI, the first argument goes into v2
|
||||
the second one into r9-r10 and memory,
|
||||
and the next two in memory. */
|
||||
foo ((vector unsigned int){10,11,12,13},
|
||||
(vector unsigned int){20,21,22,23},
|
||||
(vector unsigned int){30,31,32,33},
|
||||
(vector unsigned int){40,41,42,43});
|
||||
/* In this call, in the Darwin ABI, the first argument goes into v2
|
||||
the second one into r9, then r10 is reserved and
|
||||
there are two words of padding in memory, and the next two arguments
|
||||
go after the padding. */
|
||||
bar ((vector unsigned int){10,11,12,13}, 2,
|
||||
(vector unsigned int){20,21,22,23},
|
||||
(vector unsigned int){30,31,32,33});
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user