/* { dg-do run { target { powerpc*-*-* && lp64 } } } */
/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
/* { dg-options "-O2" } */
-#include <stdarg.h>
-#include <signal.h>
-#include <stdio.h>
+
+typedef __builtin_va_list va_list;
+#define va_start(ap, arg) __builtin_va_start (ap, arg)
+#define va_arg(ap, type) __builtin_va_arg (ap, type)
/* Testcase to check for ABI compliance of parameter passing
for the PowerPC64 ABI.
double fprs[13];
} reg_parms_t;
-reg_parms_t gparms;
+volatile reg_parms_t gparms;
-/* Testcase could break on future gcc's, if parameter regs
- are changed before this asm. */
+/* Testcase could break on future gcc's, if parameter regs are changed
+ before this asm. To minimize the risk of that happening the test
+ consists of two sets of functions wih identical signatures:
+ foo, which does nothing except save function argument registers
+ to prevent them from getting clobbered (see PR65109),
+ foo_check, which verifies that the values of function registers
+ saved by foo match those passed to foo_check by the caller. */
#ifndef __MACH__
-#define save_parms(lparms) \
- asm volatile ("ld 11,gparms@got(2)\n\t" \
- "std 3,0(11)\n\t" \
- "std 4,8(11)\n\t" \
- "std 5,16(11)\n\t" \
- "std 6,24(11)\n\t" \
- "std 7,32(11)\n\t" \
- "std 8,40(11)\n\t" \
- "std 9,48(11)\n\t" \
- "std 10,56(11)\n\t" \
- "stfd 1,64(11)\n\t" \
- "stfd 2,72(11)\n\t" \
- "stfd 3,80(11)\n\t" \
- "stfd 4,88(11)\n\t" \
- "stfd 5,96(11)\n\t" \
- "stfd 6,104(11)\n\t" \
- "stfd 7,112(11)\n\t" \
- "stfd 8,120(11)\n\t" \
- "stfd 9,128(11)\n\t" \
- "stfd 10,136(11)\n\t" \
- "stfd 11,144(11)\n\t" \
- "stfd 12,152(11)\n\t" \
- "stfd 13,160(11)\n\t":::"11", "memory"); \
- lparms = gparms;
+#define save_parms() \
+ asm volatile ("ld 11,gparms@got(2)\n\t" \
+ "std 3,0(11)\n\t" \
+ "std 4,8(11)\n\t" \
+ "std 5,16(11)\n\t" \
+ "std 6,24(11)\n\t" \
+ "std 7,32(11)\n\t" \
+ "std 8,40(11)\n\t" \
+ "std 9,48(11)\n\t" \
+ "std 10,56(11)\n\t" \
+ "stfd 1,64(11)\n\t" \
+ "stfd 2,72(11)\n\t" \
+ "stfd 3,80(11)\n\t" \
+ "stfd 4,88(11)\n\t" \
+ "stfd 5,96(11)\n\t" \
+ "stfd 6,104(11)\n\t" \
+ "stfd 7,112(11)\n\t" \
+ "stfd 8,120(11)\n\t" \
+ "stfd 9,128(11)\n\t" \
+ "stfd 10,136(11)\n\t" \
+ "stfd 11,144(11)\n\t" \
+ "stfd 12,152(11)\n\t" \
+ "stfd 13,160(11)\n\t":::"11", "memory")
#else
-#define save_parms(lparms) \
- asm volatile ("ld r11,gparms@got(r2)\n\t" \
- "std r3,0(r11)\n\t" \
- "std r4,8(r11)\n\t" \
- "std r5,16(r11)\n\t" \
- "std r6,24(r11)\n\t" \
- "std r7,32(r11)\n\t" \
- "std r8,40(r11)\n\t" \
- "std r9,48(r11)\n\t" \
- "std r10,56(r11)\n\t" \
- "stfd f1,64(r11)\n\t" \
- "stfd f2,72(r11)\n\t" \
- "stfd f3,80(r11)\n\t" \
- "stfd f4,88(r11)\n\t" \
- "stfd f5,96(r11)\n\t" \
- "stfd f6,104(r11)\n\t" \
- "stfd f7,112(r11)\n\t" \
- "stfd f8,120(r11)\n\t" \
- "stfd f9,128(r11)\n\t" \
- "stfd f10,136(r11)\n\t" \
- "stfd f11,144(r11)\n\t" \
- "stfd f12,152(r11)\n\t" \
- "stfd f13,160(r11)\n\t":::"r11", "memory"); \
- lparms = gparms;
+#define save_parms() \
+ asm volatile ("ld r11,gparms@got(r2)\n\t" \
+ "std r3,0(r11)\n\t" \
+ "std r4,8(r11)\n\t" \
+ "std r5,16(r11)\n\t" \
+ "std r6,24(r11)\n\t" \
+ "std r7,32(r11)\n\t" \
+ "std r8,40(r11)\n\t" \
+ "std r9,48(r11)\n\t" \
+ "std r10,56(r11)\n\t" \
+ "stfd f1,64(r11)\n\t" \
+ "stfd f2,72(r11)\n\t" \
+ "stfd f3,80(r11)\n\t" \
+ "stfd f4,88(r11)\n\t" \
+ "stfd f5,96(r11)\n\t" \
+ "stfd f6,104(r11)\n\t" \
+ "stfd f7,112(r11)\n\t" \
+ "stfd f8,120(r11)\n\t" \
+ "stfd f9,128(r11)\n\t" \
+ "stfd f10,136(r11)\n\t" \
+ "stfd f11,144(r11)\n\t" \
+ "stfd f12,152(r11)\n\t" \
+ "stfd f13,160(r11)\n\t":::"r11", "memory")
#endif
+
/* Stackframe structure relevant for parameter passing. */
typedef union
{
*/
void __attribute__ ((noinline)) fcld (char *s, long l, double d)
{
- reg_parms_t lparms;
- save_parms (lparms);
+ save_parms ();
- if (s != (char *) lparms.gprs[0])
+}
+void __attribute__ ((noinline)) fcld_check (char *s, long l, double d)
+{
+ if (s != (char *) gparms.gprs[0])
abort ();
- if (l != lparms.gprs[1])
+ if (l != gparms.gprs[1])
abort ();
- if (d != lparms.fprs[0])
+ if (d != gparms.fprs[0])
abort ();
}
void __attribute__ ((noinline))
fcldi (char *s, long l, double d, signed int i)
{
- reg_parms_t lparms;
- save_parms (lparms);
+ save_parms ();
+}
- if (s != (char *) lparms.gprs[0])
+void __attribute__ ((noinline))
+fcldi_check (char *s, long l, double d, signed int i)
+{
+ if (s != (char *) gparms.gprs[0])
abort ();
- if (l != lparms.gprs[1])
+ if (l != gparms.gprs[1])
abort ();
- if (d != lparms.fprs[0])
+ if (d != gparms.fprs[0])
abort ();
- if ((signed long) i != lparms.gprs[3])
+ if ((signed long) i != gparms.gprs[3])
abort ();
}
void __attribute__ ((noinline))
fcldu (char *s, long l, float d, unsigned int i)
{
- reg_parms_t lparms;
- save_parms (lparms);
+ save_parms ();
+}
- if (s != (char *) lparms.gprs[0])
+void __attribute__ ((noinline))
+fcldu_check (char *s, long l, float d, unsigned int i)
+{
+ if (s != (char *) gparms.gprs[0])
abort ();
- if (l != lparms.gprs[1])
+ if (l != gparms.gprs[1])
abort ();
- if ((double) d != lparms.fprs[0])
+ if ((double) d != gparms.fprs[0])
abort ();
- if ((unsigned long) i != lparms.gprs[3])
+ if ((unsigned long) i != gparms.gprs[3])
abort ();
}
l : slot 1
d : slot 2
*/
-
void __attribute__ ((noinline)) fceld (char *s, ...)
+{
+ save_parms ();
+}
+
+void __attribute__ ((noinline)) fceld_check (char *s, ...)
{
stack_frame_t *sp;
- reg_parms_t lparms;
va_list arg;
double d;
long l;
- save_parms (lparms);
va_start (arg, s);
- if (s != (char *) lparms.gprs[0])
+ if (s != (char *) gparms.gprs[0])
abort ();
l = va_arg (arg, long);
l : slot 4
*/
void __attribute__ ((noinline)) fciiedl (char *s, int i, int j, ...)
+{
+ save_parms ();
+}
+
+void __attribute__ ((noinline)) fciiedl_check (char *s, int i, int j, ...)
{
stack_frame_t *sp;
- reg_parms_t lparms;
va_list arg;
double d;
long l;
- save_parms (lparms);
va_start (arg, j);
- if (s != (char *) lparms.gprs[0])
+ if (s != (char *) gparms.gprs[0])
abort ();
- if ((long) i != lparms.gprs[1])
+ if ((long) i != gparms.gprs[1])
abort ();
- if ((long) j != lparms.gprs[2])
+ if ((long) j != gparms.gprs[2])
abort ();
d = va_arg (arg, double);
void __attribute__ ((noinline))
fididisdsid (int c, double ff, int d, double ld, int f,
sparm s, double gg, sparm t, int e, double hh)
+{
+ save_parms ();
+}
+
+void
+fididisdsid_check (int c, double ff, int d, double ld, int f,
+ sparm s, double gg, sparm t, int e, double hh)
{
stack_frame_t *sp;
- reg_parms_t lparms;
double_t dx, dy;
- save_parms (lparms);
-
/* Parm 0: int. */
- if ((long) c != lparms.gprs[0])
+ if ((long) c != gparms.gprs[0])
abort ();
/* Parm 1: double. */
- if (ff != lparms.fprs[0])
+ if (ff != gparms.fprs[0])
abort ();
/* Parm 2: int. */
- if ((long) d != lparms.gprs[2])
+ if ((long) d != gparms.gprs[2])
abort ();
/* Parm 3: double. */
- if (ld != lparms.fprs[1])
+ if (ld != gparms.fprs[1])
abort ();
/* Parm 4: int. */
- if ((long) f != lparms.gprs[4])
+ if ((long) f != gparms.gprs[4])
abort ();
/* Parm 5: struct sparm. */
- dx.l = lparms.gprs[5];
- dy.l = lparms.gprs[6];
+ dx.l = gparms.gprs[5];
+ dy.l = gparms.gprs[6];
if (s.a != dx.i[0])
abort ();
abort ();
/* Parm 6: double. */
- if (gg != lparms.fprs[2])
+ if (gg != gparms.fprs[2])
abort ();
- sp = __builtin_frame_address (0);
- sp = sp->backchain;
+ sp = ((stack_frame_t*)__builtin_frame_address (0))->backchain;
/* Parm 7: struct sparm. */
dx.l = sp->slot[8].l;
/* Parm 9: double. */
- if (hh != lparms.fprs[3])
+ if (hh != gparms.fprs[3])
abort ();
}
{
char *s = "ii";
- fcld (s, 1, 1.0);
- fcldi (s, 1, 1.0, -2);
- fcldu (s, 1, 1.0, 2);
- fceld (s, 1, 1.0);
- fciiedl (s, 1, 2, 1.0, 3);
- fididisdsid (1, 1.0, 2, 2.0, -1, (sparm)
- {
- 3, 3.0}, 4.0, (sparm)
- {
- 5, 5.0}, 6, 7.0);
+#define ABI_CHECK(func, args) \
+ func args, func ## _check args
+
+ ABI_CHECK (fcld, (s, 1, 1.0));
+ ABI_CHECK (fcldi, (s, 1, 1.0, -2));
+ ABI_CHECK (fcldu, (s, 1, 1.0, 2));
+ ABI_CHECK (fceld, (s, 1, 1.0));
+ ABI_CHECK (fciiedl, (s, 1, 2, 1.0, 3));
+ ABI_CHECK (fididisdsid, (1, 1.0, 2, 2.0, -1,
+ (sparm){3, 3.0}, 4.0, (sparm){5, 5.0},
+ 6, 7.0));
+
return 0;
}