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