1/* { dg-do run { target powerpc64-*-linux* } } */
2/* { dg-require-effective-target lp64 } */
3/* { dg-options "-O2 -fprofile -mprofile-kernel -maltivec -mabi=altivec" } */
4#include <stdarg.h>
5#include <signal.h>
6#include <altivec.h>
7#include <stdlib.h>
8
9/* Testcase to check for ABI compliance of parameter passing
10   for the PowerPC64 ABI.  */
11
12void __attribute__((no_instrument_function))
13sig_ill_handler (int sig)
14{
15    exit(0);
16}
17
18extern void abort (void);
19
20typedef struct
21{
22  unsigned long gprs[8];
23  double fprs[13];
24  long pad;
25  vector int vrs[12];
26} reg_parms_t;
27
28reg_parms_t gparms;
29
30/* _mcount call is done on Linux ppc64 early in the prologue.
31   my_mcount will provide a entry point _mcount,
32   which will save all register to gparms.
33   Note that _mcount need to restore lr to original value,
34   therefor use ctr to return.
35*/
36
37void __attribute__((no_instrument_function))
38my_mcount()
39{
40  asm volatile (".type	_mcount,@function\n\t"
41		".globl	_mcount\n\t"
42		"_mcount:\n\t"
43                "mflr 0\n\t"
44                "mtctr 0\n\t"
45                "ld 0,16(1)\n\t"
46		"mtlr 0\n\t"
47		"ld 11,gparms@got(2)\n\t"
48		"std 3,0(11)\n\t"
49		"std 4,8(11)\n\t"
50		"std 5,16(11)\n\t"
51		"std 6,24(11)\n\t"
52		"std 7,32(11)\n\t"
53		"std 8,40(11)\n\t"
54		"std 9,48(11)\n\t"
55		"std 10,56(11)\n\t"
56		"stfd 1,64(11)\n\t"
57		"stfd 2,72(11)\n\t"
58		"stfd 3,80(11)\n\t"
59		"stfd 4,88(11)\n\t"
60		"stfd 5,96(11)\n\t"
61		"stfd 6,104(11)\n\t"
62		"stfd 7,112(11)\n\t"
63		"stfd 8,120(11)\n\t"
64		"stfd 9,128(11)\n\t"
65		"stfd 10,136(11)\n\t"
66		"stfd 11,144(11)\n\t"
67		"stfd 12,152(11)\n\t"
68		"stfd 13,160(11)\n\t"
69		"li 3,176\n\t"
70		"stvx 2,3,11\n\t"
71		"addi 3,3,16\n\t"
72		"stvx 3,3,11\n\t"
73		"addi 3,3,16\n\t"
74		"stvx 4,3,11\n\t"
75		"addi 3,3,16\n\t"
76		"stvx 5,3,11\n\t"
77		"addi 3,3,16\n\t"
78		"stvx 6,3,11\n\t"
79		"addi 3,3,16\n\t"
80		"stvx 7,3,11\n\t"
81		"addi 3,3,16\n\t"
82		"stvx 8,3,11\n\t"
83		"addi 3,3,16\n\t"
84		"stvx 9,3,11\n\t"
85		"addi 3,3,16\n\t"
86		"stvx 10,3,11\n\t"
87		"addi 3,3,16\n\t"
88		"stvx 11,3,11\n\t"
89		"addi 3,3,16\n\t"
90		"stvx 12,3,11\n\t"
91		"addi 3,3,16\n\t"
92		"stvx 13,3,11\n\t"
93		"ld 3,0(11)\n\t"
94		"bctr");
95}
96
97/* Stackframe structure relevant for parameter passing.  */
98typedef union
99{
100  double d;
101  unsigned long l;
102  unsigned int i[2];
103} parm_t;
104
105typedef struct sf
106{
107  struct sf *backchain;
108  long a1;
109  long a2;
110  long a3;
111  long a4;
112  long a5;
113  parm_t slot[100];
114} stack_frame_t;
115
116typedef union
117{
118  unsigned int i[4];
119  unsigned long l[2];
120  vector int v;
121} vector_int_t;
122
123/* Paramter passing.
124   s : gpr 3
125   v : vpr 2
126   i : gpr 7
127*/
128void __attribute__ ((noinline))
129fcvi (char *s, vector int v, int i)
130{
131  reg_parms_t lparms = gparms;
132
133  if (s != (char *) lparms.gprs[0])
134    abort();
135
136  if (!vec_all_eq (v, lparms.vrs[0]))
137    abort ();
138
139  if ((long) i != lparms.gprs[4])
140    abort();
141}
142/* Paramter passing.
143   s : gpr 3
144   v : vpr 2
145   w : vpr 3
146*/
147
148void __attribute__ ((noinline))
149fcvv (char *s, vector int v, vector int w)
150{
151  vector int a, c = {6, 8, 10, 12};
152  reg_parms_t lparms = gparms;
153
154  if (s != (char *) lparms.gprs[0])
155    abort();
156
157  if (!vec_all_eq (v, lparms.vrs[0]))
158    abort ();
159
160  if (!vec_all_eq (w, lparms.vrs[1]))
161    abort ();
162
163  a = vec_add (v,w);
164
165  if (!vec_all_eq (a, c))
166    abort ();
167}
168
169/* Paramter passing.
170   s : gpr 3
171   i : gpr 4
172   v : vpr 2
173   w : vpr 3
174*/
175void __attribute__ ((noinline))
176fcivv (char *s, int i, vector int v, vector int w)
177{
178  vector int a, c = {6, 8, 10, 12};
179  reg_parms_t lparms = gparms;
180
181  if (s != (char *) lparms.gprs[0])
182    abort();
183
184  if ((long) i != lparms.gprs[1])
185    abort();
186
187  if (!vec_all_eq (v, lparms.vrs[0]))
188    abort ();
189
190  if (!vec_all_eq (w, lparms.vrs[1]))
191    abort ();
192
193  a = vec_add (v,w);
194
195  if (!vec_all_eq (a, c))
196    abort ();
197}
198
199/* Paramter passing.
200   s : gpr 3
201   v : slot 2-3
202   w : slot 4-5
203*/
204
205void __attribute__ ((noinline))
206fcevv (char *s, ...)
207{
208  vector int a, c = {6, 8, 10, 12};
209  vector int v,w;
210  stack_frame_t *sp;
211  reg_parms_t lparms = gparms;
212  va_list arg;
213
214  va_start (arg, s);
215
216  if (s != (char *) lparms.gprs[0])
217    abort();
218
219  v = va_arg(arg, vector int);
220  w = va_arg(arg, vector int);
221  a = vec_add (v,w);
222
223  if (!vec_all_eq (a, c))
224    abort ();
225
226  /* Go back one frame.  */
227  sp = __builtin_frame_address(0);
228  sp = sp->backchain;
229
230  if (sp->slot[2].l != 0x100000002ULL
231      || sp->slot[4].l != 0x500000006ULL)
232    abort();
233}
234
235/* Paramter passing.
236   s : gpr 3
237   i : gpr 4
238   j : gpr 5
239   v : slot 4-5
240   w : slot 6-7
241*/
242void __attribute__ ((noinline))
243fciievv (char *s, int i, int j, ...)
244{
245  vector int a, c = {6, 8, 10, 12};
246  vector int v,w;
247  stack_frame_t *sp;
248  reg_parms_t lparms = gparms;
249  va_list arg;
250
251  va_start (arg, j);
252
253  if (s != (char *) lparms.gprs[0])
254    abort();
255
256  if ((long) i != lparms.gprs[1])
257    abort();
258
259  if ((long) j != lparms.gprs[2])
260    abort();
261
262  v = va_arg(arg, vector int);
263  w = va_arg(arg, vector int);
264  a = vec_add (v,w);
265
266  if (!vec_all_eq (a, c))
267    abort ();
268
269  sp = __builtin_frame_address(0);
270  sp = sp->backchain;
271
272  if (sp->slot[4].l != 0x100000002ULL
273      || sp->slot[6].l != 0x500000006ULL)
274    abort();
275}
276
277void __attribute__ ((noinline))
278fcvevv (char *s, vector int x, ...)
279{
280  vector int a, c = {7, 10, 13, 16};
281  vector int v,w;
282  stack_frame_t *sp;
283  reg_parms_t lparms = gparms;
284  va_list arg;
285
286  va_start (arg, x);
287
288  v = va_arg(arg, vector int);
289  w = va_arg(arg, vector int);
290
291  a = vec_add (v,w);
292  a = vec_add (a, x);
293
294  if (!vec_all_eq (a, c))
295    abort ();
296
297  sp = __builtin_frame_address(0);
298  sp = sp->backchain;
299
300  if (sp->slot[4].l != 0x100000002ULL
301      || sp->slot[6].l != 0x500000006ULL)
302    abort();
303}
304
305int __attribute__((no_instrument_function, noinline))
306main1()
307{
308  char *s = "vv";
309  vector int v = {1, 2, 3, 4};
310  vector int w = {5, 6, 7, 8};
311
312  fcvi (s, v, 2);
313  fcvv (s, v, w);
314  fcivv (s, 1, v, w);
315  fcevv (s, v, w);
316  fciievv (s, 1, 2, v, w);
317  fcvevv (s, v, v, w);
318  return 0;
319}
320
321int __attribute__((no_instrument_function))
322main()
323{
324  /* Exit on systems without altivec.  */
325  signal (SIGILL, sig_ill_handler);
326  /* Altivec instruction, 'vor %v0,%v0,%v0'.  */
327  asm volatile (".long 0x10000484");
328  signal (SIGILL, SIG_DFL);
329
330  return main1 ();
331}
332
333/* Paramter passing.
334   Function called with no prototype.
335   s : gpr 3
336   v : vpr 2 gpr 5-6
337   w : vpr 3 gpr 7-8
338   x : vpr 4 gpr 9-10
339   y : vpr 5 slot 8-9
340*/
341void
342fnp_cvvvv (char *s, vector int v, vector int w,
343	   vector int x, vector int y)
344{
345  vector int a, c = {12, 16, 20, 24};
346  reg_parms_t lparms = gparms;
347  stack_frame_t *sp;
348  vector_int_t v0, v1, v2, v3;
349
350  if (s != (char *) lparms.gprs[0])
351    abort();
352
353  if (!vec_all_eq (v, lparms.vrs[0]))
354    abort ();
355
356  if (!vec_all_eq (w, lparms.vrs[1]))
357    abort ();
358
359  if (!vec_all_eq (x, lparms.vrs[2]))
360    abort ();
361
362  if (!vec_all_eq (y, lparms.vrs[3]))
363    abort ();
364
365  a = vec_add (v,w);
366  a = vec_add (a,x);
367  a = vec_add (a,y);
368
369  if (!vec_all_eq (a, c))
370    abort ();
371
372  v0.v = lparms.vrs[0];
373  v1.v = lparms.vrs[1];
374  v2.v = lparms.vrs[2];
375  v3.v = lparms.vrs[3];
376
377  if (v0.l[0] != lparms.gprs[2])
378    abort ();
379
380  if (v0.l[1] != lparms.gprs[3])
381    abort ();
382
383  if (v1.l[0] != lparms.gprs[4])
384    abort ();
385
386  if (v1.l[1] != lparms.gprs[5])
387    abort ();
388
389  if (v2.l[0] != lparms.gprs[6])
390    abort ();
391
392  if (v2.l[1] != lparms.gprs[7])
393    abort ();
394
395  sp = __builtin_frame_address(0);
396  sp = sp->backchain;
397
398  if (sp->slot[8].l != v3.l[0])
399    abort ();
400
401  if (sp->slot[9].l != v3.l[1])
402    abort ();
403}
404
405