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