1/* ----------------------------------------------------------------------- 2 ffi.c - Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Kaz Kojima 3 Copyright (c) 2008 Red Hat, Inc. 4 5 SuperH 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 31#include <stdlib.h> 32 33#define NGREGARG 4 34#if defined(__SH4__) 35#define NFREGARG 8 36#endif 37 38#if defined(__HITACHI__) 39#define STRUCT_VALUE_ADDRESS_WITH_ARG 1 40#else 41#define STRUCT_VALUE_ADDRESS_WITH_ARG 0 42#endif 43 44/* If the structure has essentialy an unique element, return its type. */ 45static int 46simple_type (ffi_type *arg) 47{ 48 if (arg->type != FFI_TYPE_STRUCT) 49 return arg->type; 50 else if (arg->elements[1]) 51 return FFI_TYPE_STRUCT; 52 53 return simple_type (arg->elements[0]); 54} 55 56static int 57return_type (ffi_type *arg) 58{ 59 unsigned short type; 60 61 if (arg->type != FFI_TYPE_STRUCT) 62 return arg->type; 63 64 type = simple_type (arg->elements[0]); 65 if (! arg->elements[1]) 66 { 67 switch (type) 68 { 69 case FFI_TYPE_SINT8: 70 case FFI_TYPE_UINT8: 71 case FFI_TYPE_SINT16: 72 case FFI_TYPE_UINT16: 73 case FFI_TYPE_SINT32: 74 case FFI_TYPE_UINT32: 75 return FFI_TYPE_INT; 76 77 default: 78 return type; 79 } 80 } 81 82 /* gcc uses r0/r1 pair for some kind of structures. */ 83 if (arg->size <= 2 * sizeof (int)) 84 { 85 int i = 0; 86 ffi_type *e; 87 88 while ((e = arg->elements[i++])) 89 { 90 type = simple_type (e); 91 switch (type) 92 { 93 case FFI_TYPE_SINT32: 94 case FFI_TYPE_UINT32: 95 case FFI_TYPE_INT: 96 case FFI_TYPE_FLOAT: 97 return FFI_TYPE_UINT64; 98 99 default: 100 break; 101 } 102 } 103 } 104 105 return FFI_TYPE_STRUCT; 106} 107 108/* ffi_prep_args is called by the assembly routine once stack space 109 has been allocated for the function's arguments */ 110 111void ffi_prep_args(char *stack, extended_cif *ecif) 112{ 113 register unsigned int i; 114 register int tmp; 115 register unsigned int avn; 116 register void **p_argv; 117 register char *argp; 118 register ffi_type **p_arg; 119 int greg, ireg; 120#if defined(__SH4__) 121 int freg = 0; 122#endif 123 124 tmp = 0; 125 argp = stack; 126 127 if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT) 128 { 129 *(void **) argp = ecif->rvalue; 130 argp += 4; 131 ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0; 132 } 133 else 134 ireg = 0; 135 136 /* Set arguments for registers. */ 137 greg = ireg; 138 avn = ecif->cif->nargs; 139 p_argv = ecif->avalue; 140 141 for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++) 142 { 143 size_t z; 144 145 z = (*p_arg)->size; 146 if (z < sizeof(int)) 147 { 148 if (greg++ >= NGREGARG) 149 continue; 150 151 z = sizeof(int); 152 switch ((*p_arg)->type) 153 { 154 case FFI_TYPE_SINT8: 155 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); 156 break; 157 158 case FFI_TYPE_UINT8: 159 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); 160 break; 161 162 case FFI_TYPE_SINT16: 163 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); 164 break; 165 166 case FFI_TYPE_UINT16: 167 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); 168 break; 169 170 case FFI_TYPE_STRUCT: 171 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); 172 break; 173 174 default: 175 FFI_ASSERT(0); 176 } 177 argp += z; 178 } 179 else if (z == sizeof(int)) 180 { 181#if defined(__SH4__) 182 if ((*p_arg)->type == FFI_TYPE_FLOAT) 183 { 184 if (freg++ >= NFREGARG) 185 continue; 186 } 187 else 188#endif 189 { 190 if (greg++ >= NGREGARG) 191 continue; 192 } 193 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); 194 argp += z; 195 } 196#if defined(__SH4__) 197 else if ((*p_arg)->type == FFI_TYPE_DOUBLE) 198 { 199 if (freg + 1 >= NFREGARG) 200 continue; 201 freg = (freg + 1) & ~1; 202 freg += 2; 203 memcpy (argp, *p_argv, z); 204 argp += z; 205 } 206#endif 207 else 208 { 209 int n = (z + sizeof (int) - 1) / sizeof (int); 210#if defined(__SH4__) 211 if (greg + n - 1 >= NGREGARG) 212 continue; 213#else 214 if (greg >= NGREGARG) 215 continue; 216#endif 217 greg += n; 218 memcpy (argp, *p_argv, z); 219 argp += n * sizeof (int); 220 } 221 } 222 223 /* Set arguments on stack. */ 224 greg = ireg; 225#if defined(__SH4__) 226 freg = 0; 227#endif 228 p_argv = ecif->avalue; 229 230 for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++) 231 { 232 size_t z; 233 234 z = (*p_arg)->size; 235 if (z < sizeof(int)) 236 { 237 if (greg++ < NGREGARG) 238 continue; 239 240 z = sizeof(int); 241 switch ((*p_arg)->type) 242 { 243 case FFI_TYPE_SINT8: 244 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); 245 break; 246 247 case FFI_TYPE_UINT8: 248 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); 249 break; 250 251 case FFI_TYPE_SINT16: 252 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); 253 break; 254 255 case FFI_TYPE_UINT16: 256 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); 257 break; 258 259 case FFI_TYPE_STRUCT: 260 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); 261 break; 262 263 default: 264 FFI_ASSERT(0); 265 } 266 argp += z; 267 } 268 else if (z == sizeof(int)) 269 { 270#if defined(__SH4__) 271 if ((*p_arg)->type == FFI_TYPE_FLOAT) 272 { 273 if (freg++ < NFREGARG) 274 continue; 275 } 276 else 277#endif 278 { 279 if (greg++ < NGREGARG) 280 continue; 281 } 282 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); 283 argp += z; 284 } 285#if defined(__SH4__) 286 else if ((*p_arg)->type == FFI_TYPE_DOUBLE) 287 { 288 if (freg + 1 < NFREGARG) 289 { 290 freg = (freg + 1) & ~1; 291 freg += 2; 292 continue; 293 } 294 memcpy (argp, *p_argv, z); 295 argp += z; 296 } 297#endif 298 else 299 { 300 int n = (z + sizeof (int) - 1) / sizeof (int); 301 if (greg + n - 1 < NGREGARG) 302 { 303 greg += n; 304 continue; 305 } 306#if (! defined(__SH4__)) 307 else if (greg < NGREGARG) 308 { 309 greg = NGREGARG; 310 continue; 311 } 312#endif 313 memcpy (argp, *p_argv, z); 314 argp += n * sizeof (int); 315 } 316 } 317 318 return; 319} 320 321/* Perform machine dependent cif processing */ 322ffi_status ffi_prep_cif_machdep(ffi_cif *cif) 323{ 324 int i, j; 325 int size, type; 326 int n, m; 327 int greg; 328#if defined(__SH4__) 329 int freg = 0; 330#endif 331 332 cif->flags = 0; 333 334 greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) && 335 STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0; 336 337#if defined(__SH4__) 338 for (i = j = 0; i < cif->nargs && j < 12; i++) 339 { 340 type = (cif->arg_types)[i]->type; 341 switch (type) 342 { 343 case FFI_TYPE_FLOAT: 344 if (freg >= NFREGARG) 345 continue; 346 freg++; 347 cif->flags += ((cif->arg_types)[i]->type) << (2 * j); 348 j++; 349 break; 350 351 case FFI_TYPE_DOUBLE: 352 if ((freg + 1) >= NFREGARG) 353 continue; 354 freg = (freg + 1) & ~1; 355 freg += 2; 356 cif->flags += ((cif->arg_types)[i]->type) << (2 * j); 357 j++; 358 break; 359 360 default: 361 size = (cif->arg_types)[i]->size; 362 n = (size + sizeof (int) - 1) / sizeof (int); 363 if (greg + n - 1 >= NGREGARG) 364 continue; 365 greg += n; 366 for (m = 0; m < n; m++) 367 cif->flags += FFI_TYPE_INT << (2 * j++); 368 break; 369 } 370 } 371#else 372 for (i = j = 0; i < cif->nargs && j < 4; i++) 373 { 374 size = (cif->arg_types)[i]->size; 375 n = (size + sizeof (int) - 1) / sizeof (int); 376 if (greg >= NGREGARG) 377 continue; 378 else if (greg + n - 1 >= NGREGARG) 379 n = NGREGARG - greg; 380 greg += n; 381 for (m = 0; m < n; m++) 382 cif->flags += FFI_TYPE_INT << (2 * j++); 383 } 384#endif 385 386 /* Set the return type flag */ 387 switch (cif->rtype->type) 388 { 389 case FFI_TYPE_STRUCT: 390 cif->flags += (unsigned) (return_type (cif->rtype)) << 24; 391 break; 392 393 case FFI_TYPE_VOID: 394 case FFI_TYPE_FLOAT: 395 case FFI_TYPE_DOUBLE: 396 case FFI_TYPE_SINT64: 397 case FFI_TYPE_UINT64: 398 cif->flags += (unsigned) cif->rtype->type << 24; 399 break; 400 401 default: 402 cif->flags += FFI_TYPE_INT << 24; 403 break; 404 } 405 406 return FFI_OK; 407} 408 409extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, 410 unsigned, unsigned, unsigned *, void (*fn)(void)); 411 412void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) 413{ 414 extended_cif ecif; 415 UINT64 trvalue; 416 417 ecif.cif = cif; 418 ecif.avalue = avalue; 419 420 /* If the return value is a struct and we don't have a return */ 421 /* value address then we need to make one */ 422 423 if (cif->rtype->type == FFI_TYPE_STRUCT 424 && return_type (cif->rtype) != FFI_TYPE_STRUCT) 425 ecif.rvalue = &trvalue; 426 else if ((rvalue == NULL) && 427 (cif->rtype->type == FFI_TYPE_STRUCT)) 428 { 429 ecif.rvalue = alloca(cif->rtype->size); 430 } 431 else 432 ecif.rvalue = rvalue; 433 434 switch (cif->abi) 435 { 436 case FFI_SYSV: 437 ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, 438 fn); 439 break; 440 default: 441 FFI_ASSERT(0); 442 break; 443 } 444 445 if (rvalue 446 && cif->rtype->type == FFI_TYPE_STRUCT 447 && return_type (cif->rtype) != FFI_TYPE_STRUCT) 448 memcpy (rvalue, &trvalue, cif->rtype->size); 449} 450 451extern void ffi_closure_SYSV (void); 452#if defined(__SH4__) 453extern void __ic_invalidate (void *line); 454#endif 455 456ffi_status 457ffi_prep_closure_loc (ffi_closure* closure, 458 ffi_cif* cif, 459 void (*fun)(ffi_cif*, void*, void**, void*), 460 void *user_data, 461 void *codeloc) 462{ 463 unsigned int *tramp; 464 unsigned int insn; 465 466 FFI_ASSERT (cif->abi == FFI_GCC_SYSV); 467 468 tramp = (unsigned int *) &closure->tramp[0]; 469 /* Set T bit if the function returns a struct pointed with R2. */ 470 insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT 471 ? 0x0018 /* sett */ 472 : 0x0008 /* clrt */); 473 474#ifdef __LITTLE_ENDIAN__ 475 tramp[0] = 0xd301d102; 476 tramp[1] = 0x0000412b | (insn << 16); 477#else 478 tramp[0] = 0xd102d301; 479 tramp[1] = 0x412b0000 | insn; 480#endif 481 *(void **) &tramp[2] = (void *)codeloc; /* ctx */ 482 *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */ 483 484 closure->cif = cif; 485 closure->fun = fun; 486 closure->user_data = user_data; 487 488#if defined(__SH4__) 489 /* Flush the icache. */ 490 __ic_invalidate(codeloc); 491#endif 492 493 return FFI_OK; 494} 495 496/* Basically the trampoline invokes ffi_closure_SYSV, and on 497 * entry, r3 holds the address of the closure. 498 * After storing the registers that could possibly contain 499 * parameters to be passed into the stack frame and setting 500 * up space for a return value, ffi_closure_SYSV invokes the 501 * following helper function to do most of the work. 502 */ 503 504#ifdef __LITTLE_ENDIAN__ 505#define OFS_INT8 0 506#define OFS_INT16 0 507#else 508#define OFS_INT8 3 509#define OFS_INT16 2 510#endif 511 512int 513ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, 514 unsigned long *pgr, unsigned long *pfr, 515 unsigned long *pst) 516{ 517 void **avalue; 518 ffi_type **p_arg; 519 int i, avn; 520 int ireg, greg = 0; 521#if defined(__SH4__) 522 int freg = 0; 523#endif 524 ffi_cif *cif; 525 526 cif = closure->cif; 527 avalue = alloca(cif->nargs * sizeof(void *)); 528 529 /* Copy the caller's structure return value address so that the closure 530 returns the data directly to the caller. */ 531 if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG) 532 { 533 rvalue = (void *) *pgr++; 534 ireg = 1; 535 } 536 else 537 ireg = 0; 538 539 cif = closure->cif; 540 greg = ireg; 541 avn = cif->nargs; 542 543 /* Grab the addresses of the arguments from the stack frame. */ 544 for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) 545 { 546 size_t z; 547 548 z = (*p_arg)->size; 549 if (z < sizeof(int)) 550 { 551 if (greg++ >= NGREGARG) 552 continue; 553 554 z = sizeof(int); 555 switch ((*p_arg)->type) 556 { 557 case FFI_TYPE_SINT8: 558 case FFI_TYPE_UINT8: 559 avalue[i] = (((char *)pgr) + OFS_INT8); 560 break; 561 562 case FFI_TYPE_SINT16: 563 case FFI_TYPE_UINT16: 564 avalue[i] = (((char *)pgr) + OFS_INT16); 565 break; 566 567 case FFI_TYPE_STRUCT: 568 avalue[i] = pgr; 569 break; 570 571 default: 572 FFI_ASSERT(0); 573 } 574 pgr++; 575 } 576 else if (z == sizeof(int)) 577 { 578#if defined(__SH4__) 579 if ((*p_arg)->type == FFI_TYPE_FLOAT) 580 { 581 if (freg++ >= NFREGARG) 582 continue; 583 avalue[i] = pfr; 584 pfr++; 585 } 586 else 587#endif 588 { 589 if (greg++ >= NGREGARG) 590 continue; 591 avalue[i] = pgr; 592 pgr++; 593 } 594 } 595#if defined(__SH4__) 596 else if ((*p_arg)->type == FFI_TYPE_DOUBLE) 597 { 598 if (freg + 1 >= NFREGARG) 599 continue; 600 if (freg & 1) 601 pfr++; 602 freg = (freg + 1) & ~1; 603 freg += 2; 604 avalue[i] = pfr; 605 pfr += 2; 606 } 607#endif 608 else 609 { 610 int n = (z + sizeof (int) - 1) / sizeof (int); 611#if defined(__SH4__) 612 if (greg + n - 1 >= NGREGARG) 613 continue; 614#else 615 if (greg >= NGREGARG) 616 continue; 617#endif 618 greg += n; 619 avalue[i] = pgr; 620 pgr += n; 621 } 622 } 623 624 greg = ireg; 625#if defined(__SH4__) 626 freg = 0; 627#endif 628 629 for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) 630 { 631 size_t z; 632 633 z = (*p_arg)->size; 634 if (z < sizeof(int)) 635 { 636 if (greg++ < NGREGARG) 637 continue; 638 639 z = sizeof(int); 640 switch ((*p_arg)->type) 641 { 642 case FFI_TYPE_SINT8: 643 case FFI_TYPE_UINT8: 644 avalue[i] = (((char *)pst) + OFS_INT8); 645 break; 646 647 case FFI_TYPE_SINT16: 648 case FFI_TYPE_UINT16: 649 avalue[i] = (((char *)pst) + OFS_INT16); 650 break; 651 652 case FFI_TYPE_STRUCT: 653 avalue[i] = pst; 654 break; 655 656 default: 657 FFI_ASSERT(0); 658 } 659 pst++; 660 } 661 else if (z == sizeof(int)) 662 { 663#if defined(__SH4__) 664 if ((*p_arg)->type == FFI_TYPE_FLOAT) 665 { 666 if (freg++ < NFREGARG) 667 continue; 668 } 669 else 670#endif 671 { 672 if (greg++ < NGREGARG) 673 continue; 674 } 675 avalue[i] = pst; 676 pst++; 677 } 678#if defined(__SH4__) 679 else if ((*p_arg)->type == FFI_TYPE_DOUBLE) 680 { 681 if (freg + 1 < NFREGARG) 682 { 683 freg = (freg + 1) & ~1; 684 freg += 2; 685 continue; 686 } 687 avalue[i] = pst; 688 pst += 2; 689 } 690#endif 691 else 692 { 693 int n = (z + sizeof (int) - 1) / sizeof (int); 694 if (greg + n - 1 < NGREGARG) 695 { 696 greg += n; 697 continue; 698 } 699#if (! defined(__SH4__)) 700 else if (greg < NGREGARG) 701 { 702 greg += n; 703 pst += greg - NGREGARG; 704 continue; 705 } 706#endif 707 avalue[i] = pst; 708 pst += n; 709 } 710 } 711 712 (closure->fun) (cif, rvalue, avalue, closure->user_data); 713 714 /* Tell ffi_closure_SYSV how to perform return type promotions. */ 715 return return_type (cif->rtype); 716} 717