1/* { dg-do run { target { powerpc_fprs && { ilp32 && dfprt } } } } */
2/* { dg-options "-std=gnu99 -O2 -fno-strict-aliasing" } */
3
4/* Testcase to check for ABI compliance of parameter passing
5   for the PowerPC ELF ABI for decimal float values.  */
6
7extern void abort (void);
8int failcnt = 0;
9
10/* Support compiling the test to report individual failures; default is
11   to abort as soon as a check fails.  */
12#ifdef DBG
13#include <stdio.h>
14#define FAILURE { printf ("failed at line %d\n", __LINE__); failcnt++; }
15#else
16#define FAILURE abort ();
17#endif
18
19typedef struct
20{
21  int pad;
22  _Decimal32 d;
23} d32parm_t;
24
25typedef struct
26{
27  unsigned int gprs[8];
28  double fprs[8];
29} reg_parms_t;
30
31reg_parms_t gparms;
32
33typedef struct sf
34{
35  struct sf *backchain;
36  int a1;
37  unsigned int slot[200];
38} stack_frame_t;
39
40/* Wrapper to save the GPRs and FPRs and then jump to the real function.  */
41#define WRAPPER(NAME)							\
42__asm__ ("\t.globl\t" #NAME "_asm\n\t"					\
43	 ".text\n\t"							\
44	 ".type " #NAME "_asm, @function\n"				\
45	 #NAME "_asm:\n\t"						\
46	 "lis 11,gparms@ha\n\t"						\
47	 "la 11,gparms@l(11)\n\t"					\
48	 "st 3,0(11)\n\t"						\
49	 "st 4,4(11)\n\t"						\
50	 "st 5,8(11)\n\t"						\
51	 "st 6,12(11)\n\t"						\
52	 "st 7,16(11)\n\t"						\
53	 "st 8,20(11)\n\t"						\
54	 "st 9,24(11)\n\t"						\
55	 "st 10,28(11)\n\t"						\
56	 "stfd 1,32(11)\n\t"						\
57	 "stfd 2,40(11)\n\t"						\
58	 "stfd 3,48(11)\n\t"						\
59	 "stfd 4,56(11)\n\t"						\
60	 "stfd 5,64(11)\n\t"						\
61	 "stfd 6,72(11)\n\t"						\
62	 "stfd 7,80(11)\n\t"						\
63	 "stfd 8,88(11)\n\t"						\
64	 "b " #NAME "\n\t"						\
65	 ".size " #NAME ",.-" #NAME "\n")
66
67/* Fill up floating point registers with double arguments, forcing
68   decimal float arguments into the parameter save area.  */
69extern void func0_asm (double, double, double, double, double,
70		       double, double, double, _Decimal64, _Decimal128);
71
72WRAPPER(func0);
73
74void __attribute__ ((noinline))
75func0 (double a1, double a2, double a3, double a4, double a5,
76       double a6, double a7, double a8, _Decimal64 a9, _Decimal128 a10)
77{
78  stack_frame_t *sp;
79
80  sp = __builtin_frame_address (0);
81  sp = sp->backchain;
82
83  if (a1 != gparms.fprs[0]) FAILURE
84  if (a2 != gparms.fprs[1]) FAILURE
85  if (a3 != gparms.fprs[2]) FAILURE
86  if (a4 != gparms.fprs[3]) FAILURE
87  if (a5 != gparms.fprs[4]) FAILURE
88  if (a6 != gparms.fprs[5]) FAILURE
89  if (a7 != gparms.fprs[6]) FAILURE
90  if (a8 != gparms.fprs[7]) FAILURE
91  if (a9 != *(_Decimal64 *)&sp->slot[0]) FAILURE
92  if (a10 != *(_Decimal128 *)&sp->slot[2]) FAILURE
93}
94
95/* Alternate 64-bit and 128-bit decimal float arguments, checking that
96   _Decimal128 is always passed in even/odd register pairs.  */
97extern void func1_asm (_Decimal64, _Decimal128, _Decimal64, _Decimal128,
98		       _Decimal64, _Decimal128, _Decimal64, _Decimal128);
99
100WRAPPER(func1);
101
102void __attribute__ ((noinline))
103func1 (_Decimal64 a1, _Decimal128 a2, _Decimal64 a3, _Decimal128 a4,
104       _Decimal64 a5, _Decimal128 a6, _Decimal64 a7, _Decimal128 a8)
105{
106  stack_frame_t *sp;
107
108  sp = __builtin_frame_address (0);
109  sp = sp->backchain;
110
111  if (a1 != *(_Decimal64 *)&gparms.fprs[0]) FAILURE	/* f1 */
112  if (a2 != *(_Decimal128 *)&gparms.fprs[1]) FAILURE	/* f2 & f3 */
113  if (a3 != *(_Decimal64 *)&gparms.fprs[3]) FAILURE	/* f4 */
114  if (a4 != *(_Decimal128 *)&gparms.fprs[5]) FAILURE	/* f6 & f7 */
115  if (a5 != *(_Decimal64 *)&gparms.fprs[7]) FAILURE	/* f8 */
116  if (a6 != *(_Decimal128 *)&sp->slot[0]) FAILURE
117  if (a7 != *(_Decimal64 *)&sp->slot[4]) FAILURE
118  if (a8 != *(_Decimal128 *)&sp->slot[6]) FAILURE
119}
120
121extern void func2_asm (_Decimal128, _Decimal64, _Decimal128, _Decimal64,
122		       _Decimal128, _Decimal64, _Decimal128, _Decimal64);
123
124WRAPPER(func2);
125
126void __attribute__ ((noinline))
127func2 (_Decimal128 a1, _Decimal64 a2, _Decimal128 a3, _Decimal64 a4,
128       _Decimal128 a5, _Decimal64 a6, _Decimal128 a7, _Decimal64 a8)
129{
130  stack_frame_t *sp;
131
132  sp = __builtin_frame_address (0);
133  sp = sp->backchain;
134
135  if (a1 != *(_Decimal128 *)&gparms.fprs[1]) FAILURE	/* f2 & f3 */
136  if (a2 != *(_Decimal64 *)&gparms.fprs[3]) FAILURE	/* f4 */
137  if (a3 != *(_Decimal128 *)&gparms.fprs[5]) FAILURE	/* f6 & f7 */
138  if (a4 != *(_Decimal64 *)&gparms.fprs[7]) FAILURE	/* f8 */
139  if (a5 != *(_Decimal128 *)&sp->slot[0]) FAILURE
140  if (a6 != *(_Decimal64 *)&sp->slot[4]) FAILURE
141  if (a7 != *(_Decimal128 *)&sp->slot[6]) FAILURE
142  if (a8 != *(_Decimal64 *)&sp->slot[10]) FAILURE
143}
144
145extern void func3_asm (_Decimal64, _Decimal128, _Decimal64, _Decimal128,
146		       _Decimal64);
147
148WRAPPER(func3);
149
150void __attribute__ ((noinline))
151func3 (_Decimal64 a1, _Decimal128 a2, _Decimal64 a3, _Decimal128 a4,
152       _Decimal64 a5)
153{
154  stack_frame_t *sp;
155
156  sp = __builtin_frame_address (0);
157  sp = sp->backchain;
158
159  if (a1 != *(_Decimal64 *)&gparms.fprs[0]) FAILURE	/* f1 */
160  if (a2 != *(_Decimal128 *)&gparms.fprs[1]) FAILURE	/* f2 & f3 */
161  if (a3 != *(_Decimal64 *)&gparms.fprs[3]) FAILURE	/* f4 */
162  if (a4 != *(_Decimal128 *)&gparms.fprs[5]) FAILURE	/* f6 & f7 */
163  if (a5 != *(_Decimal128 *)&sp->slot[0]) FAILURE
164}
165
166extern void func4_asm (_Decimal32, _Decimal32, _Decimal32, _Decimal32,
167		       _Decimal32, _Decimal32, _Decimal32, _Decimal32,
168		       _Decimal32, _Decimal32, _Decimal32, _Decimal32,
169		       _Decimal32, _Decimal32, _Decimal32, _Decimal32);
170
171WRAPPER(func4);
172
173void __attribute__ ((noinline))
174func4 (_Decimal32 a1, _Decimal32 a2, _Decimal32 a3, _Decimal32 a4,
175       _Decimal32 a5, _Decimal32 a6, _Decimal32 a7, _Decimal32 a8,
176       _Decimal32 a9, _Decimal32 a10, _Decimal32 a11, _Decimal32 a12,
177       _Decimal32 a13, _Decimal32 a14, _Decimal32 a15, _Decimal32 a16)
178{
179  stack_frame_t *sp;
180
181  sp = __builtin_frame_address (0);
182  sp = sp->backchain;
183
184  /* _Decimal32 is passed in the lower half of an FPR, or in parameter slot.  */
185  if (a1 != ((d32parm_t *)&gparms.fprs[0])->d) FAILURE		/* f1  */
186  if (a2 != ((d32parm_t *)&gparms.fprs[1])->d) FAILURE		/* f2  */
187  if (a3 != ((d32parm_t *)&gparms.fprs[2])->d) FAILURE		/* f3  */
188  if (a4 != ((d32parm_t *)&gparms.fprs[3])->d) FAILURE		/* f4  */
189  if (a5 != ((d32parm_t *)&gparms.fprs[4])->d) FAILURE		/* f5  */
190  if (a6 != ((d32parm_t *)&gparms.fprs[5])->d) FAILURE		/* f6  */
191  if (a7 != ((d32parm_t *)&gparms.fprs[6])->d) FAILURE		/* f7  */
192  if (a8 != ((d32parm_t *)&gparms.fprs[7])->d) FAILURE		/* f8  */
193  if (a9 != *(_Decimal32 *)&sp->slot[0]) FAILURE
194  if (a10 != *(_Decimal32 *)&sp->slot[1]) FAILURE
195  if (a11 != *(_Decimal32 *)&sp->slot[2]) FAILURE
196  if (a12 != *(_Decimal32 *)&sp->slot[3]) FAILURE
197  if (a13 != *(_Decimal32 *)&sp->slot[4]) FAILURE
198  if (a14 != *(_Decimal32 *)&sp->slot[5]) FAILURE
199  if (a15 != *(_Decimal32 *)&sp->slot[6]) FAILURE
200  if (a16 != *(_Decimal32 *)&sp->slot[7]) FAILURE
201}
202
203extern void func5_asm (_Decimal32, _Decimal64, _Decimal128,
204		       _Decimal32, _Decimal64, _Decimal128,
205		       _Decimal32, _Decimal64, _Decimal128,
206		       _Decimal32, _Decimal64, _Decimal128);
207
208WRAPPER(func5);
209
210void __attribute__ ((noinline))
211func5 (_Decimal32 a1, _Decimal64 a2, _Decimal128 a3,
212       _Decimal32 a4, _Decimal64 a5, _Decimal128 a6,
213       _Decimal32 a7, _Decimal64 a8, _Decimal128 a9,
214       _Decimal32 a10, _Decimal64 a11, _Decimal128 a12)
215{
216  stack_frame_t *sp;
217
218  sp = __builtin_frame_address (0);
219  sp = sp->backchain;
220
221  if (a1 != ((d32parm_t *)&gparms.fprs[0])->d) FAILURE		/* f1      */
222  if (a2 != *(_Decimal64 *)&gparms.fprs[1]) FAILURE		/* f2      */
223  if (a3 != *(_Decimal128 *)&gparms.fprs[3]) FAILURE		/* f4 & f5 */
224  if (a4 != ((d32parm_t *)&gparms.fprs[5])->d) FAILURE		/* f6      */
225  if (a5 != *(_Decimal64 *)&gparms.fprs[6]) FAILURE		/* f7      */
226
227  if (a6 != *(_Decimal128 *)&sp->slot[0]) FAILURE
228  if (a7 != *(_Decimal32 *)&sp->slot[4]) FAILURE
229  if (a8 != *(_Decimal64 *)&sp->slot[6]) FAILURE
230  if (a9 != *(_Decimal128 *)&sp->slot[8]) FAILURE
231  if (a10 != *(_Decimal32 *)&sp->slot[12]) FAILURE
232  if (a11 != *(_Decimal64 *)&sp->slot[14]) FAILURE
233  if (a12 != *(_Decimal128 *)&sp->slot[16]) FAILURE
234}
235
236int
237main ()
238{
239  func0_asm (1., 2., 3., 4., 5., 6., 7., 8., 9.dd, 10.dl);
240  func1_asm (1.dd, 2.dl, 3.dd, 4.dl, 5.dd, 6.dl, 7.dd, 8.dl);
241  func2_asm (1.dl, 2.dd, 3.dl, 4.dd, 5.dl, 6.dd, 7.dl, 8.dd);
242  func3_asm (1.dd, 2.dl, 3.dd, 4.dl, 5.dl);
243  func4_asm (501.2df, 502.2df, 503.2df, 504.2df, 505.2df, 506.2df, 507.2df,
244	     508.2df, 509.2df, 510.2df, 511.2df, 512.2df, 513.2df, 514.2df,
245	     515.2df, 516.2df);
246  func5_asm (601.2df, 602.2dd, 603.2dl, 604.2df, 605.2dd, 606.2dl,
247	     607.2df, 608.2dd, 609.2dl, 610.2df, 611.2dd, 612.2dl);
248
249  if (failcnt != 0)
250    abort ();
251
252  return 0;
253}
254