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