1/* { dg-do run { target powerpc64-*-linux* } } */ 2/* { dg-require-effective-target lp64 } */ 3/* { dg-options "-O2 -fprofile -mprofile-kernel -maltivec -mabi=altivec" } */ 4#include <stdarg.h> 5#include <signal.h> 6#include <altivec.h> 7#include <stdlib.h> 8 9/* Testcase to check for ABI compliance of parameter passing 10 for the PowerPC64 ABI. */ 11 12void __attribute__((no_instrument_function)) 13sig_ill_handler (int sig) 14{ 15 exit(0); 16} 17 18extern void abort (void); 19 20typedef struct 21{ 22 unsigned long gprs[8]; 23 double fprs[13]; 24 long pad; 25 vector int vrs[12]; 26} reg_parms_t; 27 28reg_parms_t gparms; 29 30/* _mcount call is done on Linux ppc64 early in the prologue. 31 my_mcount will provide a entry point _mcount, 32 which will save all register to gparms. 33 Note that _mcount need to restore lr to original value, 34 therefor use ctr to return. 35*/ 36 37void __attribute__((no_instrument_function)) 38my_mcount() 39{ 40 asm volatile (".type _mcount,@function\n\t" 41 ".globl _mcount\n\t" 42 "_mcount:\n\t" 43 "mflr 0\n\t" 44 "mtctr 0\n\t" 45 "ld 0,16(1)\n\t" 46 "mtlr 0\n\t" 47 "ld 11,gparms@got(2)\n\t" 48 "std 3,0(11)\n\t" 49 "std 4,8(11)\n\t" 50 "std 5,16(11)\n\t" 51 "std 6,24(11)\n\t" 52 "std 7,32(11)\n\t" 53 "std 8,40(11)\n\t" 54 "std 9,48(11)\n\t" 55 "std 10,56(11)\n\t" 56 "stfd 1,64(11)\n\t" 57 "stfd 2,72(11)\n\t" 58 "stfd 3,80(11)\n\t" 59 "stfd 4,88(11)\n\t" 60 "stfd 5,96(11)\n\t" 61 "stfd 6,104(11)\n\t" 62 "stfd 7,112(11)\n\t" 63 "stfd 8,120(11)\n\t" 64 "stfd 9,128(11)\n\t" 65 "stfd 10,136(11)\n\t" 66 "stfd 11,144(11)\n\t" 67 "stfd 12,152(11)\n\t" 68 "stfd 13,160(11)\n\t" 69 "li 3,176\n\t" 70 "stvx 2,3,11\n\t" 71 "addi 3,3,16\n\t" 72 "stvx 3,3,11\n\t" 73 "addi 3,3,16\n\t" 74 "stvx 4,3,11\n\t" 75 "addi 3,3,16\n\t" 76 "stvx 5,3,11\n\t" 77 "addi 3,3,16\n\t" 78 "stvx 6,3,11\n\t" 79 "addi 3,3,16\n\t" 80 "stvx 7,3,11\n\t" 81 "addi 3,3,16\n\t" 82 "stvx 8,3,11\n\t" 83 "addi 3,3,16\n\t" 84 "stvx 9,3,11\n\t" 85 "addi 3,3,16\n\t" 86 "stvx 10,3,11\n\t" 87 "addi 3,3,16\n\t" 88 "stvx 11,3,11\n\t" 89 "addi 3,3,16\n\t" 90 "stvx 12,3,11\n\t" 91 "addi 3,3,16\n\t" 92 "stvx 13,3,11\n\t" 93 "ld 3,0(11)\n\t" 94 "bctr"); 95} 96 97/* Stackframe structure relevant for parameter passing. */ 98typedef union 99{ 100 double d; 101 unsigned long l; 102 unsigned int i[2]; 103} parm_t; 104 105typedef struct sf 106{ 107 struct sf *backchain; 108 long a1; 109 long a2; 110 long a3; 111 long a4; 112 long a5; 113 parm_t slot[100]; 114} stack_frame_t; 115 116typedef union 117{ 118 unsigned int i[4]; 119 unsigned long l[2]; 120 vector int v; 121} vector_int_t; 122 123/* Paramter passing. 124 s : gpr 3 125 v : vpr 2 126 i : gpr 7 127*/ 128void __attribute__ ((noinline)) 129fcvi (char *s, vector int v, int i) 130{ 131 reg_parms_t lparms = gparms; 132 133 if (s != (char *) lparms.gprs[0]) 134 abort(); 135 136 if (!vec_all_eq (v, lparms.vrs[0])) 137 abort (); 138 139 if ((long) i != lparms.gprs[4]) 140 abort(); 141} 142/* Paramter passing. 143 s : gpr 3 144 v : vpr 2 145 w : vpr 3 146*/ 147 148void __attribute__ ((noinline)) 149fcvv (char *s, vector int v, vector int w) 150{ 151 vector int a, c = {6, 8, 10, 12}; 152 reg_parms_t lparms = gparms; 153 154 if (s != (char *) lparms.gprs[0]) 155 abort(); 156 157 if (!vec_all_eq (v, lparms.vrs[0])) 158 abort (); 159 160 if (!vec_all_eq (w, lparms.vrs[1])) 161 abort (); 162 163 a = vec_add (v,w); 164 165 if (!vec_all_eq (a, c)) 166 abort (); 167} 168 169/* Paramter passing. 170 s : gpr 3 171 i : gpr 4 172 v : vpr 2 173 w : vpr 3 174*/ 175void __attribute__ ((noinline)) 176fcivv (char *s, int i, vector int v, vector int w) 177{ 178 vector int a, c = {6, 8, 10, 12}; 179 reg_parms_t lparms = gparms; 180 181 if (s != (char *) lparms.gprs[0]) 182 abort(); 183 184 if ((long) i != lparms.gprs[1]) 185 abort(); 186 187 if (!vec_all_eq (v, lparms.vrs[0])) 188 abort (); 189 190 if (!vec_all_eq (w, lparms.vrs[1])) 191 abort (); 192 193 a = vec_add (v,w); 194 195 if (!vec_all_eq (a, c)) 196 abort (); 197} 198 199/* Paramter passing. 200 s : gpr 3 201 v : slot 2-3 202 w : slot 4-5 203*/ 204 205void __attribute__ ((noinline)) 206fcevv (char *s, ...) 207{ 208 vector int a, c = {6, 8, 10, 12}; 209 vector int v,w; 210 stack_frame_t *sp; 211 reg_parms_t lparms = gparms; 212 va_list arg; 213 214 va_start (arg, s); 215 216 if (s != (char *) lparms.gprs[0]) 217 abort(); 218 219 v = va_arg(arg, vector int); 220 w = va_arg(arg, vector int); 221 a = vec_add (v,w); 222 223 if (!vec_all_eq (a, c)) 224 abort (); 225 226 /* Go back one frame. */ 227 sp = __builtin_frame_address(0); 228 sp = sp->backchain; 229 230 if (sp->slot[2].l != 0x100000002ULL 231 || sp->slot[4].l != 0x500000006ULL) 232 abort(); 233} 234 235/* Paramter passing. 236 s : gpr 3 237 i : gpr 4 238 j : gpr 5 239 v : slot 4-5 240 w : slot 6-7 241*/ 242void __attribute__ ((noinline)) 243fciievv (char *s, int i, int j, ...) 244{ 245 vector int a, c = {6, 8, 10, 12}; 246 vector int v,w; 247 stack_frame_t *sp; 248 reg_parms_t lparms = gparms; 249 va_list arg; 250 251 va_start (arg, j); 252 253 if (s != (char *) lparms.gprs[0]) 254 abort(); 255 256 if ((long) i != lparms.gprs[1]) 257 abort(); 258 259 if ((long) j != lparms.gprs[2]) 260 abort(); 261 262 v = va_arg(arg, vector int); 263 w = va_arg(arg, vector int); 264 a = vec_add (v,w); 265 266 if (!vec_all_eq (a, c)) 267 abort (); 268 269 sp = __builtin_frame_address(0); 270 sp = sp->backchain; 271 272 if (sp->slot[4].l != 0x100000002ULL 273 || sp->slot[6].l != 0x500000006ULL) 274 abort(); 275} 276 277void __attribute__ ((noinline)) 278fcvevv (char *s, vector int x, ...) 279{ 280 vector int a, c = {7, 10, 13, 16}; 281 vector int v,w; 282 stack_frame_t *sp; 283 reg_parms_t lparms = gparms; 284 va_list arg; 285 286 va_start (arg, x); 287 288 v = va_arg(arg, vector int); 289 w = va_arg(arg, vector int); 290 291 a = vec_add (v,w); 292 a = vec_add (a, x); 293 294 if (!vec_all_eq (a, c)) 295 abort (); 296 297 sp = __builtin_frame_address(0); 298 sp = sp->backchain; 299 300 if (sp->slot[4].l != 0x100000002ULL 301 || sp->slot[6].l != 0x500000006ULL) 302 abort(); 303} 304 305int __attribute__((no_instrument_function, noinline)) 306main1() 307{ 308 char *s = "vv"; 309 vector int v = {1, 2, 3, 4}; 310 vector int w = {5, 6, 7, 8}; 311 312 fcvi (s, v, 2); 313 fcvv (s, v, w); 314 fcivv (s, 1, v, w); 315 fcevv (s, v, w); 316 fciievv (s, 1, 2, v, w); 317 fcvevv (s, v, v, w); 318 return 0; 319} 320 321int __attribute__((no_instrument_function)) 322main() 323{ 324 /* Exit on systems without altivec. */ 325 signal (SIGILL, sig_ill_handler); 326 /* Altivec instruction, 'vor %v0,%v0,%v0'. */ 327 asm volatile (".long 0x10000484"); 328 signal (SIGILL, SIG_DFL); 329 330 return main1 (); 331} 332 333/* Paramter passing. 334 Function called with no prototype. 335 s : gpr 3 336 v : vpr 2 gpr 5-6 337 w : vpr 3 gpr 7-8 338 x : vpr 4 gpr 9-10 339 y : vpr 5 slot 8-9 340*/ 341void 342fnp_cvvvv (char *s, vector int v, vector int w, 343 vector int x, vector int y) 344{ 345 vector int a, c = {12, 16, 20, 24}; 346 reg_parms_t lparms = gparms; 347 stack_frame_t *sp; 348 vector_int_t v0, v1, v2, v3; 349 350 if (s != (char *) lparms.gprs[0]) 351 abort(); 352 353 if (!vec_all_eq (v, lparms.vrs[0])) 354 abort (); 355 356 if (!vec_all_eq (w, lparms.vrs[1])) 357 abort (); 358 359 if (!vec_all_eq (x, lparms.vrs[2])) 360 abort (); 361 362 if (!vec_all_eq (y, lparms.vrs[3])) 363 abort (); 364 365 a = vec_add (v,w); 366 a = vec_add (a,x); 367 a = vec_add (a,y); 368 369 if (!vec_all_eq (a, c)) 370 abort (); 371 372 v0.v = lparms.vrs[0]; 373 v1.v = lparms.vrs[1]; 374 v2.v = lparms.vrs[2]; 375 v3.v = lparms.vrs[3]; 376 377 if (v0.l[0] != lparms.gprs[2]) 378 abort (); 379 380 if (v0.l[1] != lparms.gprs[3]) 381 abort (); 382 383 if (v1.l[0] != lparms.gprs[4]) 384 abort (); 385 386 if (v1.l[1] != lparms.gprs[5]) 387 abort (); 388 389 if (v2.l[0] != lparms.gprs[6]) 390 abort (); 391 392 if (v2.l[1] != lparms.gprs[7]) 393 abort (); 394 395 sp = __builtin_frame_address(0); 396 sp = sp->backchain; 397 398 if (sp->slot[8].l != v3.l[0]) 399 abort (); 400 401 if (sp->slot[9].l != v3.l[1]) 402 abort (); 403} 404 405