1/* { dg-do run { target { powerpc64-*-* && { lp64 && dfprt } } } } */
2/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
3/* { dg-options "-std=gnu99 -O2 -fno-strict-aliasing" } */
4
5/* Testcase to check for ABI compliance of parameter passing
6   for the PowerPC64 ELF ABI for decimal float values.  */
7
8extern void abort (void);
9int failcnt = 0;
10
11/* Support compiling the test to report individual failures; default is
12   to abort as soon as a check fails.  */
13#ifdef DBG
14#include <stdio.h>
15#define FAILURE { printf ("failed at line %d\n", __LINE__); failcnt++; }
16#else
17#define FAILURE abort ();
18#endif
19
20typedef struct
21{
22  int pad;
23  _Decimal32 d;
24} d32parm_t;
25
26typedef struct
27{
28  unsigned long gprs[8];
29  double fprs[13];
30} reg_parms_t;
31
32reg_parms_t gparms;
33
34
35/* Wrapper to save the GPRs and FPRs and then jump to the real function.  */
36#define WRAPPER(NAME)							\
37__asm__ ("\t.globl\t" #NAME "_asm\n\t"					\
38	 ".section \".opd\",\"aw\"\n\t"					\
39	 ".align 3\n"							\
40	 #NAME "_asm:\n\t"						\
41	 ".quad .L." #NAME "_asm,.TOC.@tocbase,0\n\t"			\
42	 ".text\n\t"							\
43	 ".type " #NAME "_asm, @function\n"				\
44	 ".L." #NAME "_asm:\n\t"					\
45	 "ld 11,gparms@got(2)\n\t"					\
46	 "std 3,0(11)\n\t"						\
47	 "std 4,8(11)\n\t"						\
48	 "std 5,16(11)\n\t"						\
49	 "std 6,24(11)\n\t"						\
50	 "std 7,32(11)\n\t"						\
51	 "std 8,40(11)\n\t"						\
52	 "std 9,48(11)\n\t"						\
53	 "std 10,56(11)\n\t"						\
54	 "stfd 1,64(11)\n\t"						\
55	 "stfd 2,72(11)\n\t"						\
56	 "stfd 3,80(11)\n\t"						\
57	 "stfd 4,88(11)\n\t"						\
58	 "stfd 5,96(11)\n\t"						\
59	 "stfd 6,104(11)\n\t"						\
60	 "stfd 7,112(11)\n\t"						\
61	 "stfd 8,120(11)\n\t"						\
62	 "stfd 9,128(11)\n\t"						\
63	 "stfd 10,136(11)\n\t"						\
64	 "stfd 11,144(11)\n\t"						\
65	 "stfd 12,152(11)\n\t"						\
66	 "stfd 13,160(11)\n\t"						\
67	 "b " #NAME "\n\t"						\
68	 ".long 0\n\t"							\
69	 ".byte 0,0,0,0,0,0,0,0\n\t"					\
70	 ".size " #NAME ",.-" #NAME "\n")
71
72typedef struct sf
73{
74  struct sf *backchain;
75  long a1;
76  long a2;
77  long a3;
78  long a4;
79  long a5;
80  unsigned long slot[100];
81} stack_frame_t;
82
83extern void func0_asm (double, double, double, double, double, double,
84		       double, double, double, double, double, double,
85		       double, double,
86		       _Decimal64, _Decimal128, _Decimal64);
87
88WRAPPER(func0);
89
90/* Fill up floating point registers with double arguments, forcing
91   decimal float arguments into the parameter save area.  */
92void __attribute__ ((noinline))
93func0 (double a1, double a2, double a3, double a4, double a5, double a6,
94       double a7, double a8, double a9, double a10, double a11, double a12,
95       double a13, double a14,
96       _Decimal64 a15, _Decimal128 a16, _Decimal64 a17)
97{
98  stack_frame_t *sp;
99
100  sp = __builtin_frame_address (0);
101  sp = sp->backchain;
102
103  if (a1 != gparms.fprs[0]) FAILURE
104  if (a2 != gparms.fprs[1]) FAILURE
105  if (a3 != gparms.fprs[2]) FAILURE
106  if (a4 != gparms.fprs[3]) FAILURE
107  if (a5 != gparms.fprs[4]) FAILURE
108  if (a6 != gparms.fprs[5]) FAILURE
109  if (a7 != gparms.fprs[6]) FAILURE
110  if (a8 != gparms.fprs[7]) FAILURE
111  if (a9 != gparms.fprs[8]) FAILURE
112  if (a10 != gparms.fprs[9]) FAILURE
113  if (a11 != gparms.fprs[10]) FAILURE
114  if (a12 != gparms.fprs[11]) FAILURE
115  if (a13 != gparms.fprs[12]) FAILURE
116  if (a14 != *(double *)&sp->slot[13]) FAILURE
117  if (a15 != *(_Decimal64 *)&sp->slot[14]) FAILURE
118  if (a16 != *(_Decimal128 *)&sp->slot[15]) FAILURE
119  if (a17 != *(_Decimal64 *)&sp->slot[17]) FAILURE
120}
121
122extern void func1_asm (double, double, double, double, double, double,
123		       double, double, double, double, double, double,
124		       double, _Decimal128 );
125
126WRAPPER(func1);
127
128void __attribute__ ((noinline))
129func1 (double a1, double a2, double a3, double a4, double a5, double a6,
130       double a7, double a8, double a9, double a10, double a11, double a12,
131       double a13, _Decimal128 a14)
132{
133  stack_frame_t *sp;
134
135  sp = __builtin_frame_address (0);
136  sp = sp->backchain;
137
138  if (a1 != gparms.fprs[0]) FAILURE
139  if (a2 != gparms.fprs[1]) FAILURE
140  if (a3 != gparms.fprs[2]) FAILURE
141  if (a4 != gparms.fprs[3]) FAILURE
142  if (a5 != gparms.fprs[4]) FAILURE
143  if (a6 != gparms.fprs[5]) FAILURE
144  if (a7 != gparms.fprs[6]) FAILURE
145  if (a8 != gparms.fprs[7]) FAILURE
146  if (a9 != gparms.fprs[8]) FAILURE
147  if (a10 != gparms.fprs[9]) FAILURE
148  if (a11 != gparms.fprs[10]) FAILURE
149  if (a12 != gparms.fprs[11]) FAILURE
150  if (a13 != gparms.fprs[12]) FAILURE
151  if (a14 != *(_Decimal128 *)&sp->slot[13]) FAILURE
152}
153
154extern void func2_asm (double, double, double, double, double, double,
155		       double, double, double, double, double, double,
156		       _Decimal128);
157
158WRAPPER(func2);
159
160void __attribute__ ((noinline))
161func2 (double a1, double a2, double a3, double a4, double a5, double a6,
162       double a7, double a8, double a9, double a10, double a11, double a12,
163       _Decimal128 a13)
164{
165  stack_frame_t *sp;
166
167  sp = __builtin_frame_address (0);
168  sp = sp->backchain;
169
170  if (a1 != gparms.fprs[0]) FAILURE
171  if (a2 != gparms.fprs[1]) FAILURE
172  if (a3 != gparms.fprs[2]) FAILURE
173  if (a4 != gparms.fprs[3]) FAILURE
174  if (a5 != gparms.fprs[4]) FAILURE
175  if (a6 != gparms.fprs[5]) FAILURE
176  if (a7 != gparms.fprs[6]) FAILURE
177  if (a8 != gparms.fprs[7]) FAILURE
178  if (a9 != gparms.fprs[8]) FAILURE
179  if (a10 != gparms.fprs[9]) FAILURE
180  if (a11 != gparms.fprs[10]) FAILURE
181  if (a12 != gparms.fprs[11]) FAILURE
182  if (a13 != *(_Decimal128 *)&sp->slot[12]) FAILURE
183}
184
185extern void func3_asm (_Decimal64, _Decimal128, _Decimal64, _Decimal128,
186		       _Decimal64, _Decimal128, _Decimal64, _Decimal128,
187		       _Decimal64, _Decimal128);
188
189WRAPPER(func3);
190
191void __attribute__ ((noinline))
192func3 (_Decimal64 a1, _Decimal128 a2, _Decimal64 a3, _Decimal128 a4,
193       _Decimal64 a5, _Decimal128 a6, _Decimal64 a7, _Decimal128 a8,
194       _Decimal64 a9, _Decimal128 a10)
195{
196  stack_frame_t *sp;
197
198  sp = __builtin_frame_address (0);
199  sp = sp->backchain;
200
201  if (a1 != *(_Decimal64 *)&gparms.fprs[0]) FAILURE	/* f1        */
202  if (a2 != *(_Decimal128 *)&gparms.fprs[1]) FAILURE	/* f2 & f3   */
203  if (a3 != *(_Decimal64 *)&gparms.fprs[3]) FAILURE	/* f4        */
204  if (a4 != *(_Decimal128 *)&gparms.fprs[5]) FAILURE	/* f6 & f7   */
205  if (a5 != *(_Decimal64 *)&gparms.fprs[7]) FAILURE	/* f8        */
206  if (a6 != *(_Decimal128 *)&gparms.fprs[9]) FAILURE	/* f10 & f11 */
207  if (a7 != *(_Decimal64 *)&gparms.fprs[11]) FAILURE	/* f12       */
208  if (a8 != *(_Decimal128 *)&sp->slot[10]) FAILURE
209  if (a9 != *(_Decimal64 *)&sp->slot[12]) FAILURE
210  if (a10 != *(_Decimal128 *)&sp->slot[13]) FAILURE
211}
212
213extern void func4_asm (_Decimal128, _Decimal64, _Decimal128, _Decimal64,
214		       _Decimal128, _Decimal64, _Decimal128, _Decimal64);
215
216WRAPPER(func4);
217
218void __attribute__ ((noinline))
219func4 (_Decimal128 a1, _Decimal64 a2, _Decimal128 a3, _Decimal64 a4,
220       _Decimal128 a5, _Decimal64 a6, _Decimal128 a7, _Decimal64 a8)
221{
222  stack_frame_t *sp;
223
224  sp = __builtin_frame_address (0);
225  sp = sp->backchain;
226
227  if (a1 != *(_Decimal128 *)&gparms.fprs[1]) FAILURE	/* f2 & f3   */
228  if (a2 != *(_Decimal64 *)&gparms.fprs[3]) FAILURE	/* f4        */
229  if (a3 != *(_Decimal128 *)&gparms.fprs[5]) FAILURE	/* f6 & f7   */
230  if (a4 != *(_Decimal64 *)&gparms.fprs[7]) FAILURE	/* f8        */
231  if (a5 != *(_Decimal128 *)&gparms.fprs[9]) FAILURE	/* f10 & f11 */
232  if (a6 != *(_Decimal64 *)&gparms.fprs[11]) FAILURE	/* f12       */
233  if (a7 != *(_Decimal128 *)&sp->slot[9]) FAILURE
234  if (a8 != *(_Decimal64 *)&sp->slot[11]) FAILURE
235}
236
237extern void func5_asm (_Decimal32, _Decimal32, _Decimal32, _Decimal32,
238		       _Decimal32, _Decimal32, _Decimal32, _Decimal32,
239		       _Decimal32, _Decimal32, _Decimal32, _Decimal32,
240		       _Decimal32, _Decimal32, _Decimal32, _Decimal32);
241
242WRAPPER(func5);
243
244void __attribute__ ((noinline))
245func5 (_Decimal32 a1, _Decimal32 a2, _Decimal32 a3, _Decimal32 a4,
246       _Decimal32 a5, _Decimal32 a6, _Decimal32 a7, _Decimal32 a8,
247       _Decimal32 a9, _Decimal32 a10, _Decimal32 a11, _Decimal32 a12,
248       _Decimal32 a13, _Decimal32 a14, _Decimal32 a15, _Decimal32 a16)
249{
250  stack_frame_t *sp;
251
252  sp = __builtin_frame_address (0);
253  sp = sp->backchain;
254
255  /* _Decimal32 is passed in the lower half of an FPR or parameter slot.  */
256  if (a1 != ((d32parm_t *)&gparms.fprs[0])->d) FAILURE		/* f1  */
257  if (a2 != ((d32parm_t *)&gparms.fprs[1])->d) FAILURE		/* f2  */
258  if (a3 != ((d32parm_t *)&gparms.fprs[2])->d) FAILURE		/* f3  */
259  if (a4 != ((d32parm_t *)&gparms.fprs[3])->d) FAILURE		/* f4  */
260  if (a5 != ((d32parm_t *)&gparms.fprs[4])->d) FAILURE		/* f5  */
261  if (a6 != ((d32parm_t *)&gparms.fprs[5])->d) FAILURE		/* f6  */
262  if (a7 != ((d32parm_t *)&gparms.fprs[6])->d) FAILURE		/* f7  */
263  if (a8 != ((d32parm_t *)&gparms.fprs[7])->d) FAILURE		/* f8  */
264  if (a9 != ((d32parm_t *)&gparms.fprs[8])->d) FAILURE		/* f9  */
265  if (a10 != ((d32parm_t *)&gparms.fprs[9])->d) FAILURE		/* f10 */
266  if (a11 != ((d32parm_t *)&gparms.fprs[10])->d) FAILURE	/* f11 */
267  if (a12 != ((d32parm_t *)&gparms.fprs[11])->d) FAILURE	/* f12 */
268  if (a13 != ((d32parm_t *)&gparms.fprs[12])->d) FAILURE	/* f13 */
269  if (a14 != ((d32parm_t *)&sp->slot[13])->d) FAILURE
270  if (a15 != ((d32parm_t *)&sp->slot[14])->d) FAILURE
271  if (a16 != ((d32parm_t *)&sp->slot[15])->d) FAILURE
272}
273
274extern void func6_asm (_Decimal32, _Decimal64, _Decimal128,
275		       _Decimal32, _Decimal64, _Decimal128,
276		       _Decimal32, _Decimal64, _Decimal128,
277		       _Decimal32, _Decimal64, _Decimal128);
278
279WRAPPER(func6);
280
281void __attribute__ ((noinline))
282func6 (_Decimal32 a1, _Decimal64 a2, _Decimal128 a3,
283       _Decimal32 a4, _Decimal64 a5, _Decimal128 a6,
284       _Decimal32 a7, _Decimal64 a8, _Decimal128 a9,
285       _Decimal32 a10, _Decimal64 a11, _Decimal128 a12)
286{
287  stack_frame_t *sp;
288
289  sp = __builtin_frame_address (0);
290  sp = sp->backchain;
291
292  if (a1 != ((d32parm_t *)&gparms.fprs[0])->d) FAILURE		/* f1        */
293  if (a2 != *(_Decimal64 *)&gparms.fprs[1]) FAILURE		/* f2        */
294  if (a3 != *(_Decimal128 *)&gparms.fprs[3]) FAILURE		/* f4 & f5   */
295  if (a4 != ((d32parm_t *)&gparms.fprs[5])->d) FAILURE		/* f6        */
296  if (a5 != *(_Decimal64 *)&gparms.fprs[6]) FAILURE		/* f7        */
297  if (a6 != *(_Decimal128 *)&gparms.fprs[7]) FAILURE		/* f8 & f9   */
298  if (a7 != ((d32parm_t *)&gparms.fprs[9])->d) FAILURE		/* f10       */
299  if (a8 != *(_Decimal64 *)&gparms.fprs[10]) FAILURE		/* f11       */
300  if (a9 != *(_Decimal128 *)&gparms.fprs[11]) FAILURE		/* f12 & f13 */
301  if (a10 != ((d32parm_t *)&sp->slot[12])->d) FAILURE
302  if (a11 != *(_Decimal64 *)&sp->slot[13]) FAILURE
303}
304
305int
306main (void)
307{
308  func0_asm (1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5, 13.5,
309	     14.5, 15.2dd, 16.2dl, 17.2dd);
310  func1_asm (101.5, 102.5, 103.5, 104.5, 105.5, 106.5, 107.5, 108.5, 109.5,
311	     110.5, 111.5, 112.5, 113.5, 114.2dd);
312  func2_asm (201.5, 202.5, 203.5, 204.5, 205.5, 206.5, 207.5, 208.5, 209.5,
313	     210.5, 211.5, 212.5, 213.2dd);
314  func3_asm (301.2dd, 302.2dl, 303.2dd, 304.2dl, 305.2dd, 306.2dl, 307.2dd,
315	     308.2dl, 309.2dd, 310.2dl);
316  func4_asm (401.2dl, 402.2dd, 403.2dl, 404.2dd, 405.2dl, 406.2dd, 407.2dl,
317	     408.2dd);
318#if 0
319  /* _Decimal32 doesn't yet follow the ABI; enable this when it does.  */
320  func5_asm (501.2df, 502.2df, 503.2df, 504.2df, 505.2df, 506.2df, 507.2df,
321	     508.2df, 509.2df, 510.2df, 511.2df, 512.2df, 513.2df, 514.2df,
322	     515.2df, 516.2df);
323  func6_asm (601.2df, 602.2dd, 603.2dl, 604.2df, 605.2dd, 606.2dl,
324	     607.2df, 608.2dd, 609.2dl, 610.2df, 611.2dd, 612.2dl);
325#endif
326
327  if (failcnt != 0)
328    abort ();
329
330  return 0;
331}
332