1/* { dg-do run { target { powerpc*-*-* && lp64 } } } */ 2/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */ 3/* { dg-options "-O2" } */ 4 5typedef __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 13extern void abort (void); 14 15typedef struct 16{ 17 unsigned long gprs[8]; 18 double fprs[13]; 19} reg_parms_t; 20 21volatile 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. */ 84typedef union 85{ 86 double d; 87 unsigned long l; 88 unsigned int i[2]; 89} parm_t; 90 91typedef 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*/ 110void __attribute__ ((noinline)) fcld (char *s, long l, double d) 111{ 112 save_parms (); 113 114} 115void __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*/ 133void __attribute__ ((noinline)) 134fcldi (char *s, long l, double d, signed int i) 135{ 136 save_parms (); 137} 138 139void __attribute__ ((noinline)) 140fcldi_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*/ 161void __attribute__ ((noinline)) 162fcldu (char *s, long l, float d, unsigned int i) 163{ 164 save_parms (); 165} 166 167void __attribute__ ((noinline)) 168fcldu_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*/ 188void __attribute__ ((noinline)) fceld (char *s, ...) 189{ 190 save_parms (); 191} 192 193void __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*/ 226void __attribute__ ((noinline)) fciiedl (char *s, int i, int j, ...) 227{ 228 save_parms (); 229} 230 231void __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/* 263Parameter Register Offset in parameter save area 264c r3 0-7 (not stored in parameter save area) 265ff f1 8-15 (not stored) 266d r5 16-23 (not stored) 267ld f2 24-31 (not stored) 268f r7 32-39 (not stored) 269s r8,r9 40-55 (not stored) 270gg f3 56-63 (not stored) 271t (none) 64-79 (stored in parameter save area) 272e (none) 80-87 (stored) 273hh f4 88-95 (stored) 274 275*/ 276 277typedef struct 278{ 279 int a; 280 double dd; 281} sparm; 282 283typedef 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 304void __attribute__ ((noinline)) 305fididisdsid (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 311void 312fididisdsid_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 371int 372main () 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