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