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