aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeoffrey Keating <geoffk@apple.com>2003-11-06 21:52:36 +0000
committerGeoffrey Keating <geoffk@gcc.gnu.org>2003-11-06 21:52:36 +0000
commit2858f73ac1ea6ce3ea2841412bbcca0a4457d939 (patch)
treec287691f13ab129d28d129a7659cd182d4d7dae7
parent8c17530ef3d7a0e4db6706df5507ace7714ad56d (diff)
downloadgcc-2858f73ac1ea6ce3ea2841412bbcca0a4457d939.zip
gcc-2858f73ac1ea6ce3ea2841412bbcca0a4457d939.tar.gz
gcc-2858f73ac1ea6ce3ea2841412bbcca0a4457d939.tar.bz2
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
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/config/rs6000/darwin.h2
-rw-r--r--gcc/config/rs6000/rs6000.c88
-rw-r--r--gcc/config/rs6000/rs6000.h12
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/altivec-varargs-1.c74
6 files changed, 152 insertions, 43 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9279d35..f889c2c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h
index e417e0d..929290f 100644
--- a/gcc/config/rs6000/darwin.h
+++ b/gcc/config/rs6000/darwin.h
@@ -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 \
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index ad0169a..9a0efb0 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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;
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 95078ec..ce38901 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -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.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5c7cea5..8390d01 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.dg/altivec-varargs-1.c b/gcc/testsuite/gcc.dg/altivec-varargs-1.c
new file mode 100644
index 0000000..b866500
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/altivec-varargs-1.c
@@ -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;
+}