github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libffi/src/sparc/ffi64.c (about) 1 /* ----------------------------------------------------------------------- 2 ffi.c - Copyright (c) 2011, 2013 Anthony Green 3 Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc. 4 5 SPARC Foreign Function Interface 6 7 Permission is hereby granted, free of charge, to any person obtaining 8 a copy of this software and associated documentation files (the 9 ``Software''), to deal in the Software without restriction, including 10 without limitation the rights to use, copy, modify, merge, publish, 11 distribute, sublicense, and/or sell copies of the Software, and to 12 permit persons to whom the Software is furnished to do so, subject to 13 the following conditions: 14 15 The above copyright notice and this permission notice shall be included 16 in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 ----------------------------------------------------------------------- */ 27 28 #include <ffi.h> 29 #include <ffi_common.h> 30 #include <stdlib.h> 31 #include "internal.h" 32 33 /* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE; 34 all further uses in this file will refer to the 128-bit type. */ 35 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 36 # if FFI_TYPE_LONGDOUBLE != 4 37 # error FFI_TYPE_LONGDOUBLE out of date 38 # endif 39 #else 40 # undef FFI_TYPE_LONGDOUBLE 41 # define FFI_TYPE_LONGDOUBLE 4 42 #endif 43 44 #ifdef SPARC64 45 46 /* Flatten the contents of a structure to the parts that are passed in 47 floating point registers. The return is a bit mask wherein bit N 48 set means bytes [4*n, 4*n+3] are passed in %fN. 49 50 We encode both the (running) size (maximum 32) and mask (maxumum 255) 51 into one integer. The size is placed in the low byte, so that align 52 and addition work correctly. The mask is placed in the second byte. */ 53 54 static int 55 ffi_struct_float_mask (ffi_type *outer_type, int size_mask) 56 { 57 ffi_type **elts; 58 ffi_type *t; 59 60 if (outer_type->type == FFI_TYPE_COMPLEX) 61 { 62 int m = 0, tt = outer_type->elements[0]->type; 63 size_t z = outer_type->size; 64 65 if (tt == FFI_TYPE_FLOAT 66 || tt == FFI_TYPE_DOUBLE 67 || tt == FFI_TYPE_LONGDOUBLE) 68 m = (1 << (z / 4)) - 1; 69 return (m << 8) | z; 70 } 71 FFI_ASSERT (outer_type->type == FFI_TYPE_STRUCT); 72 73 for (elts = outer_type->elements; (t = *elts) != NULL; elts++) 74 { 75 size_t z = t->size; 76 int o, m, tt; 77 78 size_mask = ALIGN(size_mask, t->alignment); 79 switch (t->type) 80 { 81 case FFI_TYPE_STRUCT: 82 size_mask = ffi_struct_float_mask (t, size_mask); 83 continue; 84 case FFI_TYPE_COMPLEX: 85 tt = t->elements[0]->type; 86 if (tt != FFI_TYPE_FLOAT 87 && tt != FFI_TYPE_DOUBLE 88 && tt != FFI_TYPE_LONGDOUBLE) 89 break; 90 /* FALLTHRU */ 91 case FFI_TYPE_FLOAT: 92 case FFI_TYPE_DOUBLE: 93 case FFI_TYPE_LONGDOUBLE: 94 m = (1 << (z / 4)) - 1; /* compute mask for type */ 95 o = (size_mask >> 2) & 0x3f; /* extract word offset */ 96 size_mask |= m << (o + 8); /* insert mask into place */ 97 break; 98 } 99 size_mask += z; 100 } 101 102 size_mask = ALIGN(size_mask, outer_type->alignment); 103 FFI_ASSERT ((size_mask & 0xff) == outer_type->size); 104 105 return size_mask; 106 } 107 108 /* Merge floating point data into integer data. If the structure is 109 entirely floating point, simply return a pointer to the fp data. */ 110 111 static void * 112 ffi_struct_float_merge (int size_mask, void *vi, void *vf) 113 { 114 int size = size_mask & 0xff; 115 int mask = size_mask >> 8; 116 int n = size >> 2; 117 118 if (mask == 0) 119 return vi; 120 else if (mask == (1 << n) - 1) 121 return vf; 122 else 123 { 124 unsigned int *wi = vi, *wf = vf; 125 int i; 126 127 for (i = 0; i < n; ++i) 128 if ((mask >> i) & 1) 129 wi[i] = wf[i]; 130 131 return vi; 132 } 133 } 134 135 /* Similar, but place the data into VD in the end. */ 136 137 void FFI_HIDDEN 138 ffi_struct_float_copy (int size_mask, void *vd, void *vi, void *vf) 139 { 140 int size = size_mask & 0xff; 141 int mask = size_mask >> 8; 142 int n = size >> 2; 143 144 if (mask == 0) 145 ; 146 else if (mask == (1 << n) - 1) 147 vi = vf; 148 else 149 { 150 unsigned int *wd = vd, *wi = vi, *wf = vf; 151 int i; 152 153 for (i = 0; i < n; ++i) 154 wd[i] = ((mask >> i) & 1 ? wf : wi)[i]; 155 return; 156 } 157 memcpy (vd, vi, size); 158 } 159 160 /* Perform machine dependent cif processing */ 161 162 static ffi_status 163 ffi_prep_cif_machdep_core(ffi_cif *cif) 164 { 165 ffi_type *rtype = cif->rtype; 166 int rtt = rtype->type; 167 size_t bytes = 0; 168 int i, n, flags; 169 170 /* Set the return type flag */ 171 switch (rtt) 172 { 173 case FFI_TYPE_VOID: 174 flags = SPARC_RET_VOID; 175 break; 176 case FFI_TYPE_FLOAT: 177 flags = SPARC_RET_F_1; 178 break; 179 case FFI_TYPE_DOUBLE: 180 flags = SPARC_RET_F_2; 181 break; 182 case FFI_TYPE_LONGDOUBLE: 183 flags = SPARC_RET_F_4; 184 break; 185 186 case FFI_TYPE_COMPLEX: 187 case FFI_TYPE_STRUCT: 188 if (rtype->size > 32) 189 { 190 flags = SPARC_RET_VOID | SPARC_FLAG_RET_IN_MEM; 191 bytes = 8; 192 } 193 else 194 { 195 int size_mask = ffi_struct_float_mask (rtype, 0); 196 int word_size = (size_mask >> 2) & 0x3f; 197 int all_mask = (1 << word_size) - 1; 198 int fp_mask = size_mask >> 8; 199 200 flags = (size_mask << SPARC_SIZEMASK_SHIFT) | SPARC_RET_STRUCT; 201 202 /* For special cases of all-int or all-fp, we can return 203 the value directly without popping through a struct copy. */ 204 if (fp_mask == 0) 205 { 206 if (rtype->alignment >= 8) 207 { 208 if (rtype->size == 8) 209 flags = SPARC_RET_INT64; 210 else if (rtype->size == 16) 211 flags = SPARC_RET_INT128; 212 } 213 } 214 else if (fp_mask == all_mask) 215 switch (word_size) 216 { 217 case 1: flags = SPARC_RET_F_1; break; 218 case 2: flags = SPARC_RET_F_2; break; 219 case 3: flags = SP_V9_RET_F_3; break; 220 case 4: flags = SPARC_RET_F_4; break; 221 /* 5 word structures skipped; handled via RET_STRUCT. */ 222 case 6: flags = SPARC_RET_F_6; break; 223 /* 7 word structures skipped; handled via RET_STRUCT. */ 224 case 8: flags = SPARC_RET_F_8; break; 225 } 226 } 227 break; 228 229 case FFI_TYPE_SINT8: 230 flags = SPARC_RET_SINT8; 231 break; 232 case FFI_TYPE_UINT8: 233 flags = SPARC_RET_UINT8; 234 break; 235 case FFI_TYPE_SINT16: 236 flags = SPARC_RET_SINT16; 237 break; 238 case FFI_TYPE_UINT16: 239 flags = SPARC_RET_UINT16; 240 break; 241 case FFI_TYPE_INT: 242 case FFI_TYPE_SINT32: 243 flags = SP_V9_RET_SINT32; 244 break; 245 case FFI_TYPE_UINT32: 246 flags = SPARC_RET_UINT32; 247 break; 248 case FFI_TYPE_SINT64: 249 case FFI_TYPE_UINT64: 250 case FFI_TYPE_POINTER: 251 flags = SPARC_RET_INT64; 252 break; 253 254 default: 255 abort(); 256 } 257 258 bytes = 0; 259 for (i = 0, n = cif->nargs; i < n; ++i) 260 { 261 ffi_type *ty = cif->arg_types[i]; 262 size_t z = ty->size; 263 size_t a = ty->alignment; 264 265 switch (ty->type) 266 { 267 case FFI_TYPE_COMPLEX: 268 case FFI_TYPE_STRUCT: 269 /* Large structs passed by reference. */ 270 if (z > 16) 271 { 272 a = z = 8; 273 break; 274 } 275 /* Small structs may be passed in integer or fp regs or both. */ 276 if (bytes >= 16*8) 277 break; 278 if ((ffi_struct_float_mask (ty, 0) & 0xff00) == 0) 279 break; 280 /* FALLTHRU */ 281 case FFI_TYPE_FLOAT: 282 case FFI_TYPE_DOUBLE: 283 case FFI_TYPE_LONGDOUBLE: 284 flags |= SPARC_FLAG_FP_ARGS; 285 break; 286 } 287 bytes = ALIGN(bytes, a); 288 bytes += ALIGN(z, 8); 289 } 290 291 /* Sparc call frames require that space is allocated for 6 args, 292 even if they aren't used. Make that space if necessary. */ 293 if (bytes < 6 * 8) 294 bytes = 6 * 8; 295 296 /* The stack must be 2 word aligned, so round bytes up appropriately. */ 297 bytes = ALIGN(bytes, 16); 298 299 /* Include the call frame to prep_args. */ 300 bytes += 8*16 + 8*8; 301 302 cif->bytes = bytes; 303 cif->flags = flags; 304 return FFI_OK; 305 } 306 307 ffi_status FFI_HIDDEN 308 ffi_prep_cif_machdep(ffi_cif *cif) 309 { 310 cif->nfixedargs = cif->nargs; 311 return ffi_prep_cif_machdep_core(cif); 312 } 313 314 ffi_status FFI_HIDDEN 315 ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned nfixedargs, unsigned ntotalargs) 316 { 317 cif->nfixedargs = nfixedargs; 318 return ffi_prep_cif_machdep_core(cif); 319 } 320 321 extern void ffi_call_v9(ffi_cif *cif, void (*fn)(void), void *rvalue, 322 void **avalue, size_t bytes, void *closure) FFI_HIDDEN; 323 324 /* ffi_prep_args is called by the assembly routine once stack space 325 has been allocated for the function's arguments */ 326 327 int FFI_HIDDEN 328 ffi_prep_args_v9(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue) 329 { 330 ffi_type **p_arg; 331 int flags = cif->flags; 332 int i, nargs; 333 334 if (rvalue == NULL) 335 { 336 if (flags & SPARC_FLAG_RET_IN_MEM) 337 { 338 /* Since we pass the pointer to the callee, we need a value. 339 We allowed for this space in ffi_call, before ffi_call_v8 340 alloca'd the space. */ 341 rvalue = (char *)argp + cif->bytes; 342 } 343 else 344 { 345 /* Otherwise, we can ignore the return value. */ 346 flags = SPARC_RET_VOID; 347 } 348 } 349 350 #ifdef USING_PURIFY 351 /* Purify will probably complain in our assembly routine, 352 unless we zero out this memory. */ 353 memset(argp, 0, 6*8); 354 #endif 355 356 if (flags & SPARC_FLAG_RET_IN_MEM) 357 *argp++ = (unsigned long)rvalue; 358 359 p_arg = cif->arg_types; 360 for (i = 0, nargs = cif->nargs; i < nargs; i++) 361 { 362 ffi_type *ty = p_arg[i]; 363 void *a = avalue[i]; 364 size_t z; 365 366 switch (ty->type) 367 { 368 case FFI_TYPE_SINT8: 369 *argp++ = *(SINT8 *)a; 370 break; 371 case FFI_TYPE_UINT8: 372 *argp++ = *(UINT8 *)a; 373 break; 374 case FFI_TYPE_SINT16: 375 *argp++ = *(SINT16 *)a; 376 break; 377 case FFI_TYPE_UINT16: 378 *argp++ = *(UINT16 *)a; 379 break; 380 case FFI_TYPE_INT: 381 case FFI_TYPE_SINT32: 382 *argp++ = *(SINT32 *)a; 383 break; 384 case FFI_TYPE_UINT32: 385 case FFI_TYPE_FLOAT: 386 *argp++ = *(UINT32 *)a; 387 break; 388 case FFI_TYPE_SINT64: 389 case FFI_TYPE_UINT64: 390 case FFI_TYPE_POINTER: 391 case FFI_TYPE_DOUBLE: 392 *argp++ = *(UINT64 *)a; 393 break; 394 395 case FFI_TYPE_LONGDOUBLE: 396 case FFI_TYPE_COMPLEX: 397 case FFI_TYPE_STRUCT: 398 z = ty->size; 399 if (z > 16) 400 { 401 /* For structures larger than 16 bytes we pass reference. */ 402 *argp++ = (unsigned long)a; 403 break; 404 } 405 if (((unsigned long)argp & 15) && ty->alignment > 8) 406 argp++; 407 memcpy(argp, a, z); 408 argp += ALIGN(z, 8) / 8; 409 break; 410 411 default: 412 abort(); 413 } 414 } 415 416 return flags; 417 } 418 419 static void 420 ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue, 421 void **avalue, void *closure) 422 { 423 size_t bytes = cif->bytes; 424 425 FFI_ASSERT (cif->abi == FFI_V9); 426 427 if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_IN_MEM)) 428 bytes += ALIGN (cif->rtype->size, 16); 429 430 ffi_call_v9(cif, fn, rvalue, avalue, -bytes, closure); 431 } 432 433 void 434 ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) 435 { 436 ffi_call_int(cif, fn, rvalue, avalue, NULL); 437 } 438 439 void 440 ffi_call_go(ffi_cif *cif, void (*fn)(void), void *rvalue, 441 void **avalue, void *closure) 442 { 443 ffi_call_int(cif, fn, rvalue, avalue, closure); 444 } 445 446 #ifdef __GNUC__ 447 static inline void 448 ffi_flush_icache (void *p) 449 { 450 asm volatile ("flush %0; flush %0+8" : : "r" (p) : "memory"); 451 } 452 #else 453 extern void ffi_flush_icache (void *) FFI_HIDDEN; 454 #endif 455 456 extern void ffi_closure_v9(void) FFI_HIDDEN; 457 extern void ffi_go_closure_v9(void) FFI_HIDDEN; 458 459 ffi_status 460 ffi_prep_closure_loc (ffi_closure* closure, 461 ffi_cif* cif, 462 void (*fun)(ffi_cif*, void*, void**, void*), 463 void *user_data, 464 void *codeloc) 465 { 466 unsigned int *tramp = (unsigned int *) &closure->tramp[0]; 467 unsigned long fn; 468 469 if (cif->abi != FFI_V9) 470 return FFI_BAD_ABI; 471 472 /* Trampoline address is equal to the closure address. We take advantage 473 of that to reduce the trampoline size by 8 bytes. */ 474 fn = (unsigned long) ffi_closure_v9; 475 tramp[0] = 0x83414000; /* rd %pc, %g1 */ 476 tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */ 477 tramp[2] = 0x81c14000; /* jmp %g5 */ 478 tramp[3] = 0x01000000; /* nop */ 479 *((unsigned long *) &tramp[4]) = fn; 480 481 closure->cif = cif; 482 closure->fun = fun; 483 closure->user_data = user_data; 484 485 ffi_flush_icache (closure); 486 487 return FFI_OK; 488 } 489 490 ffi_status 491 ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, 492 void (*fun)(ffi_cif*, void*, void**, void*)) 493 { 494 if (cif->abi != FFI_V9) 495 return FFI_BAD_ABI; 496 497 closure->tramp = ffi_go_closure_v9; 498 closure->cif = cif; 499 closure->fun = fun; 500 501 return FFI_OK; 502 } 503 504 int FFI_HIDDEN 505 ffi_closure_sparc_inner_v9(ffi_cif *cif, 506 void (*fun)(ffi_cif*, void*, void**, void*), 507 void *user_data, void *rvalue, 508 unsigned long *gpr, unsigned long *fpr) 509 { 510 ffi_type **arg_types; 511 void **avalue; 512 int i, argn, argx, nargs, flags, nfixedargs; 513 514 arg_types = cif->arg_types; 515 nargs = cif->nargs; 516 flags = cif->flags; 517 nfixedargs = cif->nfixedargs; 518 519 avalue = alloca(nargs * sizeof(void *)); 520 521 /* Copy the caller's structure return address so that the closure 522 returns the data directly to the caller. */ 523 if (flags & SPARC_FLAG_RET_IN_MEM) 524 { 525 rvalue = (void *) gpr[0]; 526 /* Skip the structure return address. */ 527 argn = 1; 528 } 529 else 530 argn = 0; 531 532 /* Grab the addresses of the arguments from the stack frame. */ 533 for (i = 0; i < nargs; i++, argn = argx) 534 { 535 int named = i < nfixedargs; 536 ffi_type *ty = arg_types[i]; 537 void *a = &gpr[argn]; 538 size_t z; 539 540 argx = argn + 1; 541 switch (ty->type) 542 { 543 case FFI_TYPE_COMPLEX: 544 case FFI_TYPE_STRUCT: 545 z = ty->size; 546 if (z > 16) 547 a = *(void **)a; 548 else 549 { 550 argx = argn + ALIGN (z, 8) / 8; 551 if (named && argn < 16) 552 { 553 int size_mask = ffi_struct_float_mask (ty, 0); 554 int argn_mask = (0xffff00 >> argn) & 0xff00; 555 556 /* Eliminate fp registers off the end. */ 557 size_mask = (size_mask & 0xff) | (size_mask & argn_mask); 558 a = ffi_struct_float_merge (size_mask, gpr+argn, fpr+argn); 559 } 560 } 561 break; 562 563 case FFI_TYPE_LONGDOUBLE: 564 argn = ALIGN (argn, 2); 565 a = (named && argn < 16 ? fpr : gpr) + argn; 566 argx = argn + 2; 567 break; 568 case FFI_TYPE_DOUBLE: 569 if (named && argn < 16) 570 a = fpr + argn; 571 break; 572 case FFI_TYPE_FLOAT: 573 if (named && argn < 16) 574 a = fpr + argn; 575 a += 4; 576 break; 577 578 case FFI_TYPE_UINT64: 579 case FFI_TYPE_SINT64: 580 case FFI_TYPE_POINTER: 581 break; 582 case FFI_TYPE_INT: 583 case FFI_TYPE_UINT32: 584 case FFI_TYPE_SINT32: 585 a += 4; 586 break; 587 case FFI_TYPE_UINT16: 588 case FFI_TYPE_SINT16: 589 a += 6; 590 break; 591 case FFI_TYPE_UINT8: 592 case FFI_TYPE_SINT8: 593 a += 7; 594 break; 595 596 default: 597 abort(); 598 } 599 avalue[i] = a; 600 } 601 602 /* Invoke the closure. */ 603 fun (cif, rvalue, avalue, user_data); 604 605 /* Tell ffi_closure_sparc how to perform return type promotions. */ 606 return flags; 607 } 608 #endif /* SPARC64 */