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