364 lines
7.2 KiB
C
364 lines
7.2 KiB
C
/* { dg-do run { target powerpc64-*-* } } */
|
|
/* { dg-options "-O2" } */
|
|
#include <stdarg.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
|
|
/* Testcase to check for ABI compliance of parameter passing
|
|
for the PowerPC64 ABI.
|
|
Parameter passing of integral and floating point is tested. */
|
|
|
|
extern void abort (void);
|
|
|
|
typedef struct
|
|
{
|
|
unsigned long gprs[8];
|
|
double fprs[13];
|
|
} reg_parms_t;
|
|
|
|
reg_parms_t gparms;
|
|
|
|
|
|
/* Testcase could break on future gcc's, if parameter regs
|
|
are changed before this asm. */
|
|
|
|
#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;
|
|
#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;
|
|
#endif
|
|
|
|
/* Stackframe structure relevant for parameter passing. */
|
|
typedef union
|
|
{
|
|
double d;
|
|
unsigned long l;
|
|
unsigned int i[2];
|
|
} parm_t;
|
|
|
|
typedef struct sf
|
|
{
|
|
struct sf *backchain;
|
|
long a1;
|
|
long a2;
|
|
long a3;
|
|
long a4;
|
|
long a5;
|
|
parm_t slot[100];
|
|
} stack_frame_t;
|
|
|
|
|
|
/* Paramter passing.
|
|
s : gpr 3
|
|
l : gpr 4
|
|
d : fpr 1
|
|
*/
|
|
void __attribute__ ((noinline)) fcld (char *s, long l, double d)
|
|
{
|
|
reg_parms_t lparms;
|
|
save_parms (lparms);
|
|
|
|
if (s != (char *) lparms.gprs[0])
|
|
abort ();
|
|
|
|
if (l != lparms.gprs[1])
|
|
abort ();
|
|
|
|
if (d != lparms.fprs[0])
|
|
abort ();
|
|
}
|
|
|
|
/* Paramter passing.
|
|
s : gpr 3
|
|
l : gpr 4
|
|
d : fpr 2
|
|
i : gpr 5
|
|
*/
|
|
void __attribute__ ((noinline))
|
|
fcldi (char *s, long l, double d, signed int i)
|
|
{
|
|
reg_parms_t lparms;
|
|
save_parms (lparms);
|
|
|
|
if (s != (char *) lparms.gprs[0])
|
|
abort ();
|
|
|
|
if (l != lparms.gprs[1])
|
|
abort ();
|
|
|
|
if (d != lparms.fprs[0])
|
|
abort ();
|
|
|
|
if ((signed long) i != lparms.gprs[3])
|
|
abort ();
|
|
}
|
|
|
|
/* Paramter passing.
|
|
s : gpr 3
|
|
l : gpr 4
|
|
d : fpr 2
|
|
i : gpr 5
|
|
*/
|
|
void __attribute__ ((noinline))
|
|
fcldu (char *s, long l, float d, unsigned int i)
|
|
{
|
|
reg_parms_t lparms;
|
|
save_parms (lparms);
|
|
|
|
if (s != (char *) lparms.gprs[0])
|
|
abort ();
|
|
|
|
if (l != lparms.gprs[1])
|
|
abort ();
|
|
|
|
if ((double) d != lparms.fprs[0])
|
|
abort ();
|
|
|
|
if ((unsigned long) i != lparms.gprs[3])
|
|
abort ();
|
|
}
|
|
|
|
/* Paramter passing.
|
|
s : gpr 3
|
|
l : slot 1
|
|
d : slot 2
|
|
*/
|
|
|
|
void __attribute__ ((noinline)) fceld (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])
|
|
abort ();
|
|
|
|
l = va_arg (arg, long);
|
|
d = va_arg (arg, double);
|
|
|
|
/* Go back one frame. */
|
|
sp = __builtin_frame_address (0);
|
|
sp = sp->backchain;
|
|
|
|
if (sp->slot[1].l != l)
|
|
abort ();
|
|
|
|
if (sp->slot[2].d != d)
|
|
abort ();
|
|
}
|
|
|
|
/* Paramter passing.
|
|
s : gpr 3
|
|
i : gpr 4
|
|
j : gpr 5
|
|
d : slot 3
|
|
l : slot 4
|
|
*/
|
|
void __attribute__ ((noinline)) fciiedl (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])
|
|
abort ();
|
|
|
|
if ((long) i != lparms.gprs[1])
|
|
abort ();
|
|
|
|
if ((long) j != lparms.gprs[2])
|
|
abort ();
|
|
|
|
d = va_arg (arg, double);
|
|
l = va_arg (arg, long);
|
|
|
|
sp = __builtin_frame_address (0);
|
|
sp = sp->backchain;
|
|
|
|
if (sp->slot[3].d != d)
|
|
abort ();
|
|
|
|
if (sp->slot[4].l != l)
|
|
abort ();
|
|
}
|
|
|
|
/*
|
|
Parameter Register Offset in parameter save area
|
|
c r3 0-7 (not stored in parameter save area)
|
|
ff f1 8-15 (not stored)
|
|
d r5 16-23 (not stored)
|
|
ld f2 24-31 (not stored)
|
|
f r7 32-39 (not stored)
|
|
s r8,r9 40-55 (not stored)
|
|
gg f3 56-63 (not stored)
|
|
t (none) 64-79 (stored in parameter save area)
|
|
e (none) 80-87 (stored)
|
|
hh f4 88-95 (stored)
|
|
|
|
*/
|
|
|
|
typedef struct
|
|
{
|
|
int a;
|
|
double dd;
|
|
} sparm;
|
|
|
|
typedef union
|
|
{
|
|
int i[2];
|
|
long l;
|
|
double d;
|
|
} double_t;
|
|
|
|
/* Example from ABI documentation with slight changes.
|
|
Paramter passing.
|
|
c : gpr 3
|
|
ff : fpr 1
|
|
d : gpr 5
|
|
ld : fpr 2
|
|
f : gpr 7
|
|
s : gpr 8 - 9
|
|
gg : fpr 3
|
|
t : save area offset 64 - 79
|
|
e : save area offset 80 - 88
|
|
hh : fpr 4
|
|
*/
|
|
|
|
void __attribute__ ((noinline))
|
|
fididisdsid (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])
|
|
abort ();
|
|
|
|
/* Parm 1: double. */
|
|
if (ff != lparms.fprs[0])
|
|
abort ();
|
|
|
|
/* Parm 2: int. */
|
|
if ((long) d != lparms.gprs[2])
|
|
abort ();
|
|
|
|
/* Parm 3: double. */
|
|
if (ld != lparms.fprs[1])
|
|
abort ();
|
|
|
|
/* Parm 4: int. */
|
|
if ((long) f != lparms.gprs[4])
|
|
abort ();
|
|
|
|
/* Parm 5: struct sparm. */
|
|
dx.l = lparms.gprs[5];
|
|
dy.l = lparms.gprs[6];
|
|
|
|
if (s.a != dx.i[0])
|
|
abort ();
|
|
if (s.dd != dy.d)
|
|
abort ();
|
|
|
|
/* Parm 6: double. */
|
|
if (gg != lparms.fprs[2])
|
|
abort ();
|
|
|
|
sp = __builtin_frame_address (0);
|
|
sp = sp->backchain;
|
|
|
|
/* Parm 7: struct sparm. */
|
|
dx.l = sp->slot[8].l;
|
|
dy.l = sp->slot[9].l;
|
|
if (t.a != dx.i[0])
|
|
abort ();
|
|
if (t.dd != dy.d)
|
|
abort ();
|
|
|
|
/* Parm 8: int. */
|
|
if (e != sp->slot[10].l)
|
|
abort ();
|
|
|
|
/* Parm 9: double. */
|
|
|
|
if (hh != lparms.fprs[3])
|
|
abort ();
|
|
}
|
|
|
|
int
|
|
main ()
|
|
{
|
|
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);
|
|
return 0;
|
|
}
|