re PR target/65109 (r220674 causes FAIL: gcc.target/powerpc/ppc64-abi-1.c execution...
[gcc.git] / gcc / testsuite / gcc.target / powerpc / ppc64-abi-1.c
1 /* { dg-do run { target { powerpc*-*-* && lp64 } } } */
2 /* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
3 /* { dg-options "-O2" } */
4
5 typedef __builtin_va_list va_list;
6 #define va_start(ap, arg) __builtin_va_start (ap, arg)
7 #define va_arg(ap, type) __builtin_va_arg (ap, type)
8
9 /* Testcase to check for ABI compliance of parameter passing
10 for the PowerPC64 ABI.
11 Parameter passing of integral and floating point is tested. */
12
13 extern void abort (void);
14
15 typedef struct
16 {
17 unsigned long gprs[8];
18 double fprs[13];
19 } reg_parms_t;
20
21 volatile reg_parms_t gparms;
22
23
24 /* Testcase could break on future gcc's, if parameter regs are changed
25 before this asm. To minimize the risk of that happening the test
26 consists of two sets of functions wih identical signatures:
27 foo, which does nothing except save function argument registers
28 to prevent them from getting clobbered (see PR65109),
29 foo_check, which verifies that the values of function registers
30 saved by foo match those passed to foo_check by the caller. */
31
32 #ifndef __MACH__
33 #define save_parms() \
34 asm volatile ("ld 11,gparms@got(2)\n\t" \
35 "std 3,0(11)\n\t" \
36 "std 4,8(11)\n\t" \
37 "std 5,16(11)\n\t" \
38 "std 6,24(11)\n\t" \
39 "std 7,32(11)\n\t" \
40 "std 8,40(11)\n\t" \
41 "std 9,48(11)\n\t" \
42 "std 10,56(11)\n\t" \
43 "stfd 1,64(11)\n\t" \
44 "stfd 2,72(11)\n\t" \
45 "stfd 3,80(11)\n\t" \
46 "stfd 4,88(11)\n\t" \
47 "stfd 5,96(11)\n\t" \
48 "stfd 6,104(11)\n\t" \
49 "stfd 7,112(11)\n\t" \
50 "stfd 8,120(11)\n\t" \
51 "stfd 9,128(11)\n\t" \
52 "stfd 10,136(11)\n\t" \
53 "stfd 11,144(11)\n\t" \
54 "stfd 12,152(11)\n\t" \
55 "stfd 13,160(11)\n\t":::"11", "memory")
56 #else
57 #define save_parms() \
58 asm volatile ("ld r11,gparms@got(r2)\n\t" \
59 "std r3,0(r11)\n\t" \
60 "std r4,8(r11)\n\t" \
61 "std r5,16(r11)\n\t" \
62 "std r6,24(r11)\n\t" \
63 "std r7,32(r11)\n\t" \
64 "std r8,40(r11)\n\t" \
65 "std r9,48(r11)\n\t" \
66 "std r10,56(r11)\n\t" \
67 "stfd f1,64(r11)\n\t" \
68 "stfd f2,72(r11)\n\t" \
69 "stfd f3,80(r11)\n\t" \
70 "stfd f4,88(r11)\n\t" \
71 "stfd f5,96(r11)\n\t" \
72 "stfd f6,104(r11)\n\t" \
73 "stfd f7,112(r11)\n\t" \
74 "stfd f8,120(r11)\n\t" \
75 "stfd f9,128(r11)\n\t" \
76 "stfd f10,136(r11)\n\t" \
77 "stfd f11,144(r11)\n\t" \
78 "stfd f12,152(r11)\n\t" \
79 "stfd f13,160(r11)\n\t":::"r11", "memory")
80 #endif
81
82
83 /* Stackframe structure relevant for parameter passing. */
84 typedef union
85 {
86 double d;
87 unsigned long l;
88 unsigned int i[2];
89 } parm_t;
90
91 typedef struct sf
92 {
93 struct sf *backchain;
94 long a1;
95 long a2;
96 long a3;
97 #if _CALL_ELF != 2
98 long a4;
99 long a5;
100 #endif
101 parm_t slot[100];
102 } stack_frame_t;
103
104
105 /* Paramter passing.
106 s : gpr 3
107 l : gpr 4
108 d : fpr 1
109 */
110 void __attribute__ ((noinline)) fcld (char *s, long l, double d)
111 {
112 save_parms ();
113
114 }
115 void __attribute__ ((noinline)) fcld_check (char *s, long l, double d)
116 {
117 if (s != (char *) gparms.gprs[0])
118 abort ();
119
120 if (l != gparms.gprs[1])
121 abort ();
122
123 if (d != gparms.fprs[0])
124 abort ();
125 }
126
127 /* Paramter passing.
128 s : gpr 3
129 l : gpr 4
130 d : fpr 2
131 i : gpr 5
132 */
133 void __attribute__ ((noinline))
134 fcldi (char *s, long l, double d, signed int i)
135 {
136 save_parms ();
137 }
138
139 void __attribute__ ((noinline))
140 fcldi_check (char *s, long l, double d, signed int i)
141 {
142 if (s != (char *) gparms.gprs[0])
143 abort ();
144
145 if (l != gparms.gprs[1])
146 abort ();
147
148 if (d != gparms.fprs[0])
149 abort ();
150
151 if ((signed long) i != gparms.gprs[3])
152 abort ();
153 }
154
155 /* Paramter passing.
156 s : gpr 3
157 l : gpr 4
158 d : fpr 2
159 i : gpr 5
160 */
161 void __attribute__ ((noinline))
162 fcldu (char *s, long l, float d, unsigned int i)
163 {
164 save_parms ();
165 }
166
167 void __attribute__ ((noinline))
168 fcldu_check (char *s, long l, float d, unsigned int i)
169 {
170 if (s != (char *) gparms.gprs[0])
171 abort ();
172
173 if (l != gparms.gprs[1])
174 abort ();
175
176 if ((double) d != gparms.fprs[0])
177 abort ();
178
179 if ((unsigned long) i != gparms.gprs[3])
180 abort ();
181 }
182
183 /* Paramter passing.
184 s : gpr 3
185 l : slot 1
186 d : slot 2
187 */
188 void __attribute__ ((noinline)) fceld (char *s, ...)
189 {
190 save_parms ();
191 }
192
193 void __attribute__ ((noinline)) fceld_check (char *s, ...)
194 {
195 stack_frame_t *sp;
196 va_list arg;
197 double d;
198 long l;
199
200 va_start (arg, s);
201
202 if (s != (char *) gparms.gprs[0])
203 abort ();
204
205 l = va_arg (arg, long);
206 d = va_arg (arg, double);
207
208 /* Go back one frame. */
209 sp = __builtin_frame_address (0);
210 sp = sp->backchain;
211
212 if (sp->slot[1].l != l)
213 abort ();
214
215 if (sp->slot[2].d != d)
216 abort ();
217 }
218
219 /* Paramter passing.
220 s : gpr 3
221 i : gpr 4
222 j : gpr 5
223 d : slot 3
224 l : slot 4
225 */
226 void __attribute__ ((noinline)) fciiedl (char *s, int i, int j, ...)
227 {
228 save_parms ();
229 }
230
231 void __attribute__ ((noinline)) fciiedl_check (char *s, int i, int j, ...)
232 {
233 stack_frame_t *sp;
234 va_list arg;
235 double d;
236 long l;
237
238 va_start (arg, j);
239
240 if (s != (char *) gparms.gprs[0])
241 abort ();
242
243 if ((long) i != gparms.gprs[1])
244 abort ();
245
246 if ((long) j != gparms.gprs[2])
247 abort ();
248
249 d = va_arg (arg, double);
250 l = va_arg (arg, long);
251
252 sp = __builtin_frame_address (0);
253 sp = sp->backchain;
254
255 if (sp->slot[3].d != d)
256 abort ();
257
258 if (sp->slot[4].l != l)
259 abort ();
260 }
261
262 /*
263 Parameter Register Offset in parameter save area
264 c r3 0-7 (not stored in parameter save area)
265 ff f1 8-15 (not stored)
266 d r5 16-23 (not stored)
267 ld f2 24-31 (not stored)
268 f r7 32-39 (not stored)
269 s r8,r9 40-55 (not stored)
270 gg f3 56-63 (not stored)
271 t (none) 64-79 (stored in parameter save area)
272 e (none) 80-87 (stored)
273 hh f4 88-95 (stored)
274
275 */
276
277 typedef struct
278 {
279 int a;
280 double dd;
281 } sparm;
282
283 typedef union
284 {
285 int i[2];
286 long l;
287 double d;
288 } double_t;
289
290 /* Example from ABI documentation with slight changes.
291 Paramter passing.
292 c : gpr 3
293 ff : fpr 1
294 d : gpr 5
295 ld : fpr 2
296 f : gpr 7
297 s : gpr 8 - 9
298 gg : fpr 3
299 t : save area offset 64 - 79
300 e : save area offset 80 - 88
301 hh : fpr 4
302 */
303
304 void __attribute__ ((noinline))
305 fididisdsid (int c, double ff, int d, double ld, int f,
306 sparm s, double gg, sparm t, int e, double hh)
307 {
308 save_parms ();
309 }
310
311 void
312 fididisdsid_check (int c, double ff, int d, double ld, int f,
313 sparm s, double gg, sparm t, int e, double hh)
314 {
315 stack_frame_t *sp;
316 double_t dx, dy;
317
318 /* Parm 0: int. */
319 if ((long) c != gparms.gprs[0])
320 abort ();
321
322 /* Parm 1: double. */
323 if (ff != gparms.fprs[0])
324 abort ();
325
326 /* Parm 2: int. */
327 if ((long) d != gparms.gprs[2])
328 abort ();
329
330 /* Parm 3: double. */
331 if (ld != gparms.fprs[1])
332 abort ();
333
334 /* Parm 4: int. */
335 if ((long) f != gparms.gprs[4])
336 abort ();
337
338 /* Parm 5: struct sparm. */
339 dx.l = gparms.gprs[5];
340 dy.l = gparms.gprs[6];
341
342 if (s.a != dx.i[0])
343 abort ();
344 if (s.dd != dy.d)
345 abort ();
346
347 /* Parm 6: double. */
348 if (gg != gparms.fprs[2])
349 abort ();
350
351 sp = ((stack_frame_t*)__builtin_frame_address (0))->backchain;
352
353 /* Parm 7: struct sparm. */
354 dx.l = sp->slot[8].l;
355 dy.l = sp->slot[9].l;
356 if (t.a != dx.i[0])
357 abort ();
358 if (t.dd != dy.d)
359 abort ();
360
361 /* Parm 8: int. */
362 if (e != sp->slot[10].l)
363 abort ();
364
365 /* Parm 9: double. */
366
367 if (hh != gparms.fprs[3])
368 abort ();
369 }
370
371 int
372 main ()
373 {
374 char *s = "ii";
375
376 #define ABI_CHECK(func, args) \
377 func args, func ## _check args
378
379 ABI_CHECK (fcld, (s, 1, 1.0));
380 ABI_CHECK (fcldi, (s, 1, 1.0, -2));
381 ABI_CHECK (fcldu, (s, 1, 1.0, 2));
382 ABI_CHECK (fceld, (s, 1, 1.0));
383 ABI_CHECK (fciiedl, (s, 1, 2, 1.0, 3));
384 ABI_CHECK (fididisdsid, (1, 1.0, 2, 2.0, -1,
385 (sparm){3, 3.0}, 4.0, (sparm){5, 5.0},
386 6, 7.0));
387
388 return 0;
389 }