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