summaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.target/powerpc/ppc64-abi-dfp-1.c
blob: 4e91b1bba26ad860fc5636ceb3cf6f3e5a3b7c35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
/* { dg-do run { target { powerpc64-*-* && { lp64 && dfprt } } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-options "-std=gnu99 -O2 -fno-strict-aliasing" } */

/* Testcase to check for ABI compliance of parameter passing
   for the PowerPC64 ELF ABI for decimal float values.  */

extern void abort (void);
int failcnt = 0;

/* Support compiling the test to report individual failures; default is
   to abort as soon as a check fails.  */
#ifdef DBG
#include <stdio.h>
#define FAILURE { printf ("failed at line %d\n", __LINE__); failcnt++; }
#else
#define FAILURE abort ();
#endif

typedef struct
{
  int pad;
  _Decimal32 d;
} d32parm_t;

typedef struct
{
  unsigned long gprs[8];
  double fprs[13];
} reg_parms_t;

reg_parms_t gparms;


/* Wrapper to save the GPRs and FPRs and then jump to the real function.  */
#if _CALL_ELF != 2
#define FUNC_START(NAME)						\
	"\t.globl\t" NAME "\n\t"					\
         ".section \".opd\",\"aw\"\n\t"					\
         ".align 3\n"							\
         NAME ":\n\t"							\
         ".quad .L." NAME ",.TOC.@tocbase,0\n\t"			\
         ".text\n\t"							\
         ".type " NAME ", @function\n"					\
         ".L." NAME ":\n\t"
#else
#define FUNC_START(NAME)						\
	"\t.globl\t" NAME "\n\t"					\
         ".text\n\t"							\
         NAME ":\n"							\
	"0:\taddis 2,12,(.TOC.-0b)@ha\n\t"				\
	"addi 2,2,(.TOC.-0b)@l\n\t"					\
	".localentry " NAME ",.-" NAME "\n\t"
#endif
#define WRAPPER(NAME)							\
__asm__ (FUNC_START (#NAME "_asm")					\
	 "ld 11,gparms@got(2)\n\t"					\
	 "std 3,0(11)\n\t"						\
	 "std 4,8(11)\n\t"						\
	 "std 5,16(11)\n\t"						\
	 "std 6,24(11)\n\t"						\
	 "std 7,32(11)\n\t"						\
	 "std 8,40(11)\n\t"						\
	 "std 9,48(11)\n\t"						\
	 "std 10,56(11)\n\t"						\
	 "stfd 1,64(11)\n\t"						\
	 "stfd 2,72(11)\n\t"						\
	 "stfd 3,80(11)\n\t"						\
	 "stfd 4,88(11)\n\t"						\
	 "stfd 5,96(11)\n\t"						\
	 "stfd 6,104(11)\n\t"						\
	 "stfd 7,112(11)\n\t"						\
	 "stfd 8,120(11)\n\t"						\
	 "stfd 9,128(11)\n\t"						\
	 "stfd 10,136(11)\n\t"						\
	 "stfd 11,144(11)\n\t"						\
	 "stfd 12,152(11)\n\t"						\
	 "stfd 13,160(11)\n\t"						\
	 "b " #NAME "\n\t"						\
	 ".long 0\n\t"							\
	 ".byte 0,0,0,0,0,0,0,0\n\t"					\
	 ".size " #NAME ",.-" #NAME "\n")

typedef struct sf
{
  struct sf *backchain;
  long a1;
  long a2;
  long a3;
#if _CALL_ELF != 2
  long a4;
  long a5;
#endif
  unsigned long slot[100];
} stack_frame_t;

extern void func0_asm (double, double, double, double, double, double,
		       double, double, double, double, double, double,
		       double, double, 
		       _Decimal64, _Decimal128, _Decimal64);

WRAPPER(func0);

/* Fill up floating point registers with double arguments, forcing
   decimal float arguments into the parameter save area.  */
void __attribute__ ((noinline))
func0 (double a1, double a2, double a3, double a4, double a5, double a6,
       double a7, double a8, double a9, double a10, double a11, double a12,
       double a13, double a14, 
       _Decimal64 a15, _Decimal128 a16, _Decimal64 a17)
{
  stack_frame_t *sp;

  sp = __builtin_frame_address (0);
  sp = sp->backchain;

  if (a1 != gparms.fprs[0]) FAILURE
  if (a2 != gparms.fprs[1]) FAILURE
  if (a3 != gparms.fprs[2]) FAILURE
  if (a4 != gparms.fprs[3]) FAILURE
  if (a5 != gparms.fprs[4]) FAILURE
  if (a6 != gparms.fprs[5]) FAILURE
  if (a7 != gparms.fprs[6]) FAILURE
  if (a8 != gparms.fprs[7]) FAILURE
  if (a9 != gparms.fprs[8]) FAILURE
  if (a10 != gparms.fprs[9]) FAILURE
  if (a11 != gparms.fprs[10]) FAILURE
  if (a12 != gparms.fprs[11]) FAILURE
  if (a13 != gparms.fprs[12]) FAILURE
  if (a14 != *(double *)&sp->slot[13]) FAILURE
  if (a15 != *(_Decimal64 *)&sp->slot[14]) FAILURE
  if (a16 != *(_Decimal128 *)&sp->slot[15]) FAILURE
  if (a17 != *(_Decimal64 *)&sp->slot[17]) FAILURE
}

extern void func1_asm (double, double, double, double, double, double,
		       double, double, double, double, double, double,
		       double, _Decimal128 );

WRAPPER(func1);

void __attribute__ ((noinline))
func1 (double a1, double a2, double a3, double a4, double a5, double a6,
       double a7, double a8, double a9, double a10, double a11, double a12,
       double a13, _Decimal128 a14)
{
  stack_frame_t *sp;

  sp = __builtin_frame_address (0);
  sp = sp->backchain;

  if (a1 != gparms.fprs[0]) FAILURE
  if (a2 != gparms.fprs[1]) FAILURE
  if (a3 != gparms.fprs[2]) FAILURE
  if (a4 != gparms.fprs[3]) FAILURE
  if (a5 != gparms.fprs[4]) FAILURE
  if (a6 != gparms.fprs[5]) FAILURE
  if (a7 != gparms.fprs[6]) FAILURE
  if (a8 != gparms.fprs[7]) FAILURE
  if (a9 != gparms.fprs[8]) FAILURE
  if (a10 != gparms.fprs[9]) FAILURE
  if (a11 != gparms.fprs[10]) FAILURE
  if (a12 != gparms.fprs[11]) FAILURE
  if (a13 != gparms.fprs[12]) FAILURE
  if (a14 != *(_Decimal128 *)&sp->slot[13]) FAILURE
}

extern void func2_asm (double, double, double, double, double, double,
		       double, double, double, double, double, double,
		       _Decimal128);

WRAPPER(func2);

void __attribute__ ((noinline))
func2 (double a1, double a2, double a3, double a4, double a5, double a6,
       double a7, double a8, double a9, double a10, double a11, double a12,
       _Decimal128 a13)
{
  stack_frame_t *sp;

  sp = __builtin_frame_address (0);
  sp = sp->backchain;

  if (a1 != gparms.fprs[0]) FAILURE
  if (a2 != gparms.fprs[1]) FAILURE
  if (a3 != gparms.fprs[2]) FAILURE
  if (a4 != gparms.fprs[3]) FAILURE
  if (a5 != gparms.fprs[4]) FAILURE
  if (a6 != gparms.fprs[5]) FAILURE
  if (a7 != gparms.fprs[6]) FAILURE
  if (a8 != gparms.fprs[7]) FAILURE
  if (a9 != gparms.fprs[8]) FAILURE
  if (a10 != gparms.fprs[9]) FAILURE
  if (a11 != gparms.fprs[10]) FAILURE
  if (a12 != gparms.fprs[11]) FAILURE
  if (a13 != *(_Decimal128 *)&sp->slot[12]) FAILURE
}

extern void func3_asm (_Decimal64, _Decimal128, _Decimal64, _Decimal128,
		       _Decimal64, _Decimal128, _Decimal64, _Decimal128,
		       _Decimal64, _Decimal128);

WRAPPER(func3);

void __attribute__ ((noinline))
func3 (_Decimal64 a1, _Decimal128 a2, _Decimal64 a3, _Decimal128 a4,
       _Decimal64 a5, _Decimal128 a6, _Decimal64 a7, _Decimal128 a8,
       _Decimal64 a9, _Decimal128 a10)
{
  stack_frame_t *sp;

  sp = __builtin_frame_address (0);
  sp = sp->backchain;

  if (a1 != *(_Decimal64 *)&gparms.fprs[0]) FAILURE	/* f1        */
  if (a2 != *(_Decimal128 *)&gparms.fprs[1]) FAILURE	/* f2 & f3   */
  if (a3 != *(_Decimal64 *)&gparms.fprs[3]) FAILURE	/* f4        */
  if (a4 != *(_Decimal128 *)&gparms.fprs[5]) FAILURE	/* f6 & f7   */
  if (a5 != *(_Decimal64 *)&gparms.fprs[7]) FAILURE	/* f8        */
  if (a6 != *(_Decimal128 *)&gparms.fprs[9]) FAILURE	/* f10 & f11 */
  if (a7 != *(_Decimal64 *)&gparms.fprs[11]) FAILURE	/* f12       */
  if (a8 != *(_Decimal128 *)&sp->slot[10]) FAILURE
  if (a9 != *(_Decimal64 *)&sp->slot[12]) FAILURE
  if (a10 != *(_Decimal128 *)&sp->slot[13]) FAILURE
}

extern void func4_asm (_Decimal128, _Decimal64, _Decimal128, _Decimal64,
		       _Decimal128, _Decimal64, _Decimal128, _Decimal64);

WRAPPER(func4);

void __attribute__ ((noinline))
func4 (_Decimal128 a1, _Decimal64 a2, _Decimal128 a3, _Decimal64 a4,
       _Decimal128 a5, _Decimal64 a6, _Decimal128 a7, _Decimal64 a8)
{
  stack_frame_t *sp;

  sp = __builtin_frame_address (0);
  sp = sp->backchain;

  if (a1 != *(_Decimal128 *)&gparms.fprs[1]) FAILURE	/* f2 & f3   */
  if (a2 != *(_Decimal64 *)&gparms.fprs[3]) FAILURE	/* f4        */
  if (a3 != *(_Decimal128 *)&gparms.fprs[5]) FAILURE	/* f6 & f7   */
  if (a4 != *(_Decimal64 *)&gparms.fprs[7]) FAILURE	/* f8        */
  if (a5 != *(_Decimal128 *)&gparms.fprs[9]) FAILURE	/* f10 & f11 */
  if (a6 != *(_Decimal64 *)&gparms.fprs[11]) FAILURE	/* f12       */
  if (a7 != *(_Decimal128 *)&sp->slot[9]) FAILURE
  if (a8 != *(_Decimal64 *)&sp->slot[11]) FAILURE
}

extern void func5_asm (_Decimal32, _Decimal32, _Decimal32, _Decimal32,
		       _Decimal32, _Decimal32, _Decimal32, _Decimal32,
		       _Decimal32, _Decimal32, _Decimal32, _Decimal32,
		       _Decimal32, _Decimal32, _Decimal32, _Decimal32);

WRAPPER(func5);

void __attribute__ ((noinline))
func5 (_Decimal32 a1, _Decimal32 a2, _Decimal32 a3, _Decimal32 a4,
       _Decimal32 a5, _Decimal32 a6, _Decimal32 a7, _Decimal32 a8,
       _Decimal32 a9, _Decimal32 a10, _Decimal32 a11, _Decimal32 a12,
       _Decimal32 a13, _Decimal32 a14, _Decimal32 a15, _Decimal32 a16)
{
  stack_frame_t *sp;

  sp = __builtin_frame_address (0);
  sp = sp->backchain;

  /* _Decimal32 is passed in the lower half of an FPR or parameter slot.  */
  if (a1 != ((d32parm_t *)&gparms.fprs[0])->d) FAILURE		/* f1  */
  if (a2 != ((d32parm_t *)&gparms.fprs[1])->d) FAILURE		/* f2  */
  if (a3 != ((d32parm_t *)&gparms.fprs[2])->d) FAILURE		/* f3  */
  if (a4 != ((d32parm_t *)&gparms.fprs[3])->d) FAILURE		/* f4  */
  if (a5 != ((d32parm_t *)&gparms.fprs[4])->d) FAILURE		/* f5  */
  if (a6 != ((d32parm_t *)&gparms.fprs[5])->d) FAILURE		/* f6  */
  if (a7 != ((d32parm_t *)&gparms.fprs[6])->d) FAILURE		/* f7  */
  if (a8 != ((d32parm_t *)&gparms.fprs[7])->d) FAILURE		/* f8  */
  if (a9 != ((d32parm_t *)&gparms.fprs[8])->d) FAILURE		/* f9  */
  if (a10 != ((d32parm_t *)&gparms.fprs[9])->d) FAILURE		/* f10 */
  if (a11 != ((d32parm_t *)&gparms.fprs[10])->d) FAILURE	/* f11 */
  if (a12 != ((d32parm_t *)&gparms.fprs[11])->d) FAILURE	/* f12 */
  if (a13 != ((d32parm_t *)&gparms.fprs[12])->d) FAILURE	/* f13 */
  if (a14 != ((d32parm_t *)&sp->slot[13])->d) FAILURE
  if (a15 != ((d32parm_t *)&sp->slot[14])->d) FAILURE
  if (a16 != ((d32parm_t *)&sp->slot[15])->d) FAILURE
}

extern void func6_asm (_Decimal32, _Decimal64, _Decimal128,
		       _Decimal32, _Decimal64, _Decimal128,
		       _Decimal32, _Decimal64, _Decimal128,
		       _Decimal32, _Decimal64, _Decimal128);

WRAPPER(func6);

void __attribute__ ((noinline))
func6 (_Decimal32 a1, _Decimal64 a2, _Decimal128 a3,
       _Decimal32 a4, _Decimal64 a5, _Decimal128 a6,
       _Decimal32 a7, _Decimal64 a8, _Decimal128 a9,
       _Decimal32 a10, _Decimal64 a11, _Decimal128 a12)
{
  stack_frame_t *sp;

  sp = __builtin_frame_address (0);
  sp = sp->backchain;

  if (a1 != ((d32parm_t *)&gparms.fprs[0])->d) FAILURE		/* f1        */
  if (a2 != *(_Decimal64 *)&gparms.fprs[1]) FAILURE		/* f2        */
  if (a3 != *(_Decimal128 *)&gparms.fprs[3]) FAILURE		/* f4 & f5   */
  if (a4 != ((d32parm_t *)&gparms.fprs[5])->d) FAILURE		/* f6        */
  if (a5 != *(_Decimal64 *)&gparms.fprs[6]) FAILURE		/* f7        */
  if (a6 != *(_Decimal128 *)&gparms.fprs[7]) FAILURE		/* f8 & f9   */
  if (a7 != ((d32parm_t *)&gparms.fprs[9])->d) FAILURE		/* f10       */
  if (a8 != *(_Decimal64 *)&gparms.fprs[10]) FAILURE		/* f11       */
  if (a9 != *(_Decimal128 *)&gparms.fprs[11]) FAILURE		/* f12 & f13 */
  if (a10 != ((d32parm_t *)&sp->slot[12])->d) FAILURE
  if (a11 != *(_Decimal64 *)&sp->slot[13]) FAILURE
}

int
main (void)
{
  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,
	     14.5, 15.2dd, 16.2dl, 17.2dd);
  func1_asm (101.5, 102.5, 103.5, 104.5, 105.5, 106.5, 107.5, 108.5, 109.5,
	     110.5, 111.5, 112.5, 113.5, 114.2dd);
  func2_asm (201.5, 202.5, 203.5, 204.5, 205.5, 206.5, 207.5, 208.5, 209.5,
	     210.5, 211.5, 212.5, 213.2dd);
  func3_asm (301.2dd, 302.2dl, 303.2dd, 304.2dl, 305.2dd, 306.2dl, 307.2dd,
	     308.2dl, 309.2dd, 310.2dl);
  func4_asm (401.2dl, 402.2dd, 403.2dl, 404.2dd, 405.2dl, 406.2dd, 407.2dl,
	     408.2dd);
#if 0
  /* _Decimal32 doesn't yet follow the ABI; enable this when it does.  */
  func5_asm (501.2df, 502.2df, 503.2df, 504.2df, 505.2df, 506.2df, 507.2df,
	     508.2df, 509.2df, 510.2df, 511.2df, 512.2df, 513.2df, 514.2df,
	     515.2df, 516.2df);
  func6_asm (601.2df, 602.2dd, 603.2dl, 604.2df, 605.2dd, 606.2dl,
	     607.2df, 608.2dd, 609.2dl, 610.2df, 611.2dd, 612.2dl);
#endif

  if (failcnt != 0)
    abort ();

  return 0;
}