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 
11 void __attribute__((no_instrument_function))
sig_ill_handler(int sig)12 sig_ill_handler (int sig)
13 {
14     exit(0);
15 }
16 
17 extern void abort (void);
18 
19 typedef struct
20 {
21   unsigned long gprs[8];
22   double fprs[13];
23   long pad;
24   vector int vrs[12];
25 } reg_parms_t;
26 
27 reg_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 
36 void __attribute__((no_instrument_function))
my_mcount()37 my_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.  */
97 typedef union
98 {
99   double d;
100   unsigned long l;
101   unsigned int i[2];
102 } parm_t;
103 
104 typedef struct sf
105 {
106   struct sf *backchain;
107   long a1;
108   long a2;
109   long a3;
110 #if _CALL_ELF != 2
111   long a4;
112   long a5;
113 #endif
114   parm_t slot[100];
115 } stack_frame_t;
116 
117 typedef union
118 {
119   unsigned int i[4];
120   unsigned long l[2];
121   vector int v;
122 } vector_int_t;
123 
124 #ifdef __LITTLE_ENDIAN__
125 #define MAKE_SLOT(x, y) ((long)x | ((long)y << 32))
126 #else
127 #define MAKE_SLOT(x, y) ((long)y | ((long)x << 32))
128 #endif
129 
130 /* Paramter passing.
131    s : gpr 3
132    v : vpr 2
133    i : gpr 7
134 */
135 void __attribute__ ((noinline))
fcvi(char * s,vector int v,int i)136 fcvi (char *s, vector int v, int i)
137 {
138   reg_parms_t lparms = gparms;
139 
140   if (s != (char *) lparms.gprs[0])
141     abort();
142 
143   if (!vec_all_eq (v, lparms.vrs[0]))
144     abort ();
145 
146   if ((long) i != lparms.gprs[4])
147     abort();
148 }
149 /* Paramter passing.
150    s : gpr 3
151    v : vpr 2
152    w : vpr 3
153 */
154 
155 void __attribute__ ((noinline))
fcvv(char * s,vector int v,vector int w)156 fcvv (char *s, vector int v, vector int w)
157 {
158   vector int a, c = {6, 8, 10, 12};
159   reg_parms_t lparms = gparms;
160 
161   if (s != (char *) lparms.gprs[0])
162     abort();
163 
164   if (!vec_all_eq (v, lparms.vrs[0]))
165     abort ();
166 
167   if (!vec_all_eq (w, lparms.vrs[1]))
168     abort ();
169 
170   a = vec_add (v,w);
171 
172   if (!vec_all_eq (a, c))
173     abort ();
174 }
175 
176 /* Paramter passing.
177    s : gpr 3
178    i : gpr 4
179    v : vpr 2
180    w : vpr 3
181 */
182 void __attribute__ ((noinline))
fcivv(char * s,int i,vector int v,vector int w)183 fcivv (char *s, int i, vector int v, vector int w)
184 {
185   vector int a, c = {6, 8, 10, 12};
186   reg_parms_t lparms = gparms;
187 
188   if (s != (char *) lparms.gprs[0])
189     abort();
190 
191   if ((long) i != lparms.gprs[1])
192     abort();
193 
194   if (!vec_all_eq (v, lparms.vrs[0]))
195     abort ();
196 
197   if (!vec_all_eq (w, lparms.vrs[1]))
198     abort ();
199 
200   a = vec_add (v,w);
201 
202   if (!vec_all_eq (a, c))
203     abort ();
204 }
205 
206 /* Paramter passing.
207    s : gpr 3
208    v : slot 2-3
209    w : slot 4-5
210 */
211 
212 void __attribute__ ((noinline))
fcevv(char * s,...)213 fcevv (char *s, ...)
214 {
215   vector int a, c = {6, 8, 10, 12};
216   vector int v,w;
217   stack_frame_t *sp;
218   reg_parms_t lparms = gparms;
219   va_list arg;
220 
221   va_start (arg, s);
222 
223   if (s != (char *) lparms.gprs[0])
224     abort();
225 
226   v = va_arg(arg, vector int);
227   w = va_arg(arg, vector int);
228   a = vec_add (v,w);
229 
230   if (!vec_all_eq (a, c))
231     abort ();
232 
233   /* Go back one frame.  */
234   sp = __builtin_frame_address(0);
235   sp = sp->backchain;
236 
237   if (sp->slot[2].l != MAKE_SLOT (1, 2)
238       || sp->slot[4].l !=  MAKE_SLOT (5, 6))
239     abort();
240 }
241 
242 /* Paramter passing.
243    s : gpr 3
244    i : gpr 4
245    j : gpr 5
246    v : slot 4-5
247    w : slot 6-7
248 */
249 void __attribute__ ((noinline))
fciievv(char * s,int i,int j,...)250 fciievv (char *s, int i, int j, ...)
251 {
252   vector int a, c = {6, 8, 10, 12};
253   vector int v,w;
254   stack_frame_t *sp;
255   reg_parms_t lparms = gparms;
256   va_list arg;
257 
258   va_start (arg, j);
259 
260   if (s != (char *) lparms.gprs[0])
261     abort();
262 
263   if ((long) i != lparms.gprs[1])
264     abort();
265 
266   if ((long) j != lparms.gprs[2])
267     abort();
268 
269   v = va_arg(arg, vector int);
270   w = va_arg(arg, vector int);
271   a = vec_add (v,w);
272 
273   if (!vec_all_eq (a, c))
274     abort ();
275 
276   sp = __builtin_frame_address(0);
277   sp = sp->backchain;
278 
279   if (sp->slot[4].l != MAKE_SLOT (1, 2)
280       || sp->slot[6].l !=  MAKE_SLOT (5, 6))
281     abort();
282 }
283 
284 void __attribute__ ((noinline))
fcvevv(char * s,vector int x,...)285 fcvevv (char *s, vector int x, ...)
286 {
287   vector int a, c = {7, 10, 13, 16};
288   vector int v,w;
289   stack_frame_t *sp;
290   reg_parms_t lparms = gparms;
291   va_list arg;
292 
293   va_start (arg, x);
294 
295   v = va_arg(arg, vector int);
296   w = va_arg(arg, vector int);
297 
298   a = vec_add (v,w);
299   a = vec_add (a, x);
300 
301   if (!vec_all_eq (a, c))
302     abort ();
303 
304   sp = __builtin_frame_address(0);
305   sp = sp->backchain;
306 
307   if (sp->slot[4].l != MAKE_SLOT (1, 2)
308       || sp->slot[6].l !=  MAKE_SLOT (5, 6))
309     abort();
310 }
311 
312 int __attribute__((no_instrument_function, noinline))
main1()313 main1()
314 {
315   char *s = "vv";
316   vector int v = {1, 2, 3, 4};
317   vector int w = {5, 6, 7, 8};
318 
319   fcvi (s, v, 2);
320   fcvv (s, v, w);
321   fcivv (s, 1, v, w);
322   fcevv (s, v, w);
323   fciievv (s, 1, 2, v, w);
324   fcvevv (s, v, v, w);
325   return 0;
326 }
327 
328 int __attribute__((no_instrument_function))
main()329 main()
330 {
331   /* Exit on systems without altivec.  */
332   signal (SIGILL, sig_ill_handler);
333   /* Altivec instruction, 'vor %v0,%v0,%v0'.  */
334   asm volatile (".long 0x10000484");
335   signal (SIGILL, SIG_DFL);
336 
337   return main1 ();
338 }
339 
340 /* Paramter passing.
341    Function called with no prototype.
342    s : gpr 3
343    v : vpr 2 gpr 5-6
344    w : vpr 3 gpr 7-8
345    x : vpr 4 gpr 9-10
346    y : vpr 5 slot 8-9
347 */
348 void
fnp_cvvvv(char * s,vector int v,vector int w,vector int x,vector int y)349 fnp_cvvvv (char *s, vector int v, vector int w,
350 	   vector int x, vector int y)
351 {
352   vector int a, c = {12, 16, 20, 24};
353   reg_parms_t lparms = gparms;
354   stack_frame_t *sp;
355   vector_int_t v0, v1, v2, v3;
356 
357   if (s != (char *) lparms.gprs[0])
358     abort();
359 
360   if (!vec_all_eq (v, lparms.vrs[0]))
361     abort ();
362 
363   if (!vec_all_eq (w, lparms.vrs[1]))
364     abort ();
365 
366   if (!vec_all_eq (x, lparms.vrs[2]))
367     abort ();
368 
369   if (!vec_all_eq (y, lparms.vrs[3]))
370     abort ();
371 
372   a = vec_add (v,w);
373   a = vec_add (a,x);
374   a = vec_add (a,y);
375 
376   if (!vec_all_eq (a, c))
377     abort ();
378 
379   v0.v = lparms.vrs[0];
380   v1.v = lparms.vrs[1];
381   v2.v = lparms.vrs[2];
382   v3.v = lparms.vrs[3];
383 
384   if (v0.l[0] != lparms.gprs[2])
385     abort ();
386 
387   if (v0.l[1] != lparms.gprs[3])
388     abort ();
389 
390   if (v1.l[0] != lparms.gprs[4])
391     abort ();
392 
393   if (v1.l[1] != lparms.gprs[5])
394     abort ();
395 
396   if (v2.l[0] != lparms.gprs[6])
397     abort ();
398 
399   if (v2.l[1] != lparms.gprs[7])
400     abort ();
401 
402   sp = __builtin_frame_address(0);
403   sp = sp->backchain;
404 
405   if (sp->slot[8].l != v3.l[0])
406     abort ();
407 
408   if (sp->slot[9].l != v3.l[1])
409     abort ();
410 }
411 
412