1 /* { dg-do run { target { powerpc*-*-* && lp64 } } } */
2 /* { dg-skip-if "" { *-*-darwin* } } */
3 /* { dg-options "-O2 -mno-pcrel" } */
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 */
fcld(char * s,long l,double d)110 void __attribute__ ((noinline)) fcld (char *s, long l, double d)
111 {
112   save_parms ();
113 
114 }
fcld_check(char * s,long l,double d)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))
fcldi(char * s,long l,double d,signed int i)134 fcldi (char *s, long l, double d, signed int i)
135 {
136   save_parms ();
137 }
138 
139 void __attribute__ ((noinline))
fcldi_check(char * s,long l,double d,signed int i)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))
fcldu(char * s,long l,float d,unsigned int i)162 fcldu (char *s, long l, float d, unsigned int i)
163 {
164   save_parms ();
165 }
166 
167 void __attribute__ ((noinline))
fcldu_check(char * s,long l,float d,unsigned int i)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 */
fceld(char * s,...)188 void __attribute__ ((noinline)) fceld (char *s, ...)
189 {
190   save_parms ();
191 }
192 
fceld_check(char * s,...)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 */
fciiedl(char * s,int i,int j,...)226 void __attribute__ ((noinline)) fciiedl (char *s, int i, int j, ...)
227 {
228   save_parms ();
229 }
230 
fciiedl_check(char * s,int i,int j,...)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))
fididisdsid(int c,double ff,int d,double ld,int f,sparm s,double gg,sparm t,int e,double hh)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
fididisdsid_check(int c,double ff,int d,double ld,int f,sparm s,double gg,sparm t,int e,double hh)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
main()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 }
390