Back to index

plt-scheme  4.2.1
ffi_darwin.c
Go to the documentation of this file.
00001 /* -----------------------------------------------------------------------
00002    ffi_darwin.c
00003 
00004    Copyright (C) 1998 Geoffrey Keating
00005    Copyright (C) 2001 John Hornkvist
00006    Copyright (C) 2002, 2006, 2007 Free Software Foundation, Inc.
00007 
00008    FFI support for Darwin and AIX.
00009    
00010    Permission is hereby granted, free of charge, to any person obtaining
00011    a copy of this software and associated documentation files (the
00012    ``Software''), to deal in the Software without restriction, including
00013    without limitation the rights to use, copy, modify, merge, publish,
00014    distribute, sublicense, and/or sell copies of the Software, and to
00015    permit persons to whom the Software is furnished to do so, subject to
00016    the following conditions:
00017 
00018    The above copyright notice and this permission notice shall be included
00019    in all copies or substantial portions of the Software.
00020 
00021    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
00022    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00023    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00024    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
00025    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00026    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00027    OTHER DEALINGS IN THE SOFTWARE.
00028    ----------------------------------------------------------------------- */
00029 
00030 #include <ffi.h>
00031 #include <ffi_common.h>
00032 
00033 #include <stdlib.h>
00034 
00035 extern void ffi_closure_ASM(void);
00036 
00037 enum {
00038   /* The assembly depends on these exact flags.  */
00039   FLAG_RETURNS_NOTHING  = 1 << (31-30), /* These go in cr7  */
00040   FLAG_RETURNS_FP       = 1 << (31-29),
00041   FLAG_RETURNS_64BITS   = 1 << (31-28),
00042   FLAG_RETURNS_128BITS  = 1 << (31-31),
00043 
00044   FLAG_ARG_NEEDS_COPY   = 1 << (31- 7),
00045   FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI  */
00046   FLAG_4_GPR_ARGUMENTS  = 1 << (31- 5),
00047   FLAG_RETVAL_REFERENCE = 1 << (31- 4)
00048 };
00049 
00050 /* About the DARWIN ABI.  */
00051 enum {
00052   NUM_GPR_ARG_REGISTERS = 8,
00053   NUM_FPR_ARG_REGISTERS = 13
00054 };
00055 enum { ASM_NEEDS_REGISTERS = 4 };
00056 
00057 /* ffi_prep_args is called by the assembly routine once stack space
00058    has been allocated for the function's arguments.
00059 
00060    The stack layout we want looks like this:
00061 
00062    |   Return address from ffi_call_DARWIN      |       higher addresses
00063    |--------------------------------------------|
00064    |   Previous backchain pointer  4      |      stack pointer here
00065    |--------------------------------------------|<+ <<< on entry to
00066    |   Saved r28-r31               4*4    | |    ffi_call_DARWIN
00067    |--------------------------------------------| |
00068    |   Parameters             (at least 8*4=32) | |
00069    |--------------------------------------------| |
00070    |   Space for GPR2                   4       | |
00071    |--------------------------------------------| |     stack  |
00072    |   Reserved                       2*4       | |     grows  |
00073    |--------------------------------------------| |     down   V
00074    |   Space for callee's LR              4      | |
00075    |--------------------------------------------| |     lower addresses
00076    |   Saved CR                         4       | |
00077    |--------------------------------------------| |     stack pointer here
00078    |   Current backchain pointer   4      |-/    during
00079    |--------------------------------------------|   <<< ffi_call_DARWIN
00080 
00081    */
00082 
00083 void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
00084 {
00085   const unsigned bytes = ecif->cif->bytes;
00086   const unsigned flags = ecif->cif->flags;
00087 
00088   /* 'stacktop' points at the previous backchain pointer.  */
00089   unsigned *const stacktop = stack + (bytes / sizeof(unsigned));
00090 
00091   /* 'fpr_base' points at the space for fpr1, and grows upwards as
00092      we use FPR registers.  */
00093   double *fpr_base = (double*) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS;
00094   int fparg_count = 0;
00095 
00096 
00097   /* 'next_arg' grows up as we put parameters in it.  */
00098   unsigned *next_arg = stack + 6; /* 6 reserved positions.  */
00099 
00100   int i = ecif->cif->nargs;
00101   double double_tmp;
00102   void **p_argv = ecif->avalue;
00103   unsigned gprvalue;
00104   ffi_type** ptr = ecif->cif->arg_types;
00105   char *dest_cpy;
00106   unsigned size_al = 0;
00107 
00108   /* Check that everything starts aligned properly.  */
00109   FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0);
00110   FFI_ASSERT(((unsigned)(char *)stacktop & 0xF) == 0);
00111   FFI_ASSERT((bytes & 0xF) == 0);
00112 
00113   /* Deal with return values that are actually pass-by-reference.
00114      Rule:
00115      Return values are referenced by r3, so r4 is the first parameter.  */
00116 
00117   if (flags & FLAG_RETVAL_REFERENCE)
00118     *next_arg++ = (unsigned)(char *)ecif->rvalue;
00119 
00120   /* Now for the arguments.  */
00121   for (;
00122        i > 0;
00123        i--, ptr++, p_argv++)
00124     {
00125       switch ((*ptr)->type)
00126        {
00127        /* If a floating-point parameter appears before all of the general-
00128           purpose registers are filled, the corresponding GPRs that match
00129           the size of the floating-point parameter are skipped.  */
00130        case FFI_TYPE_FLOAT:
00131          double_tmp = *(float *)*p_argv;
00132          if (fparg_count >= NUM_FPR_ARG_REGISTERS)
00133            *(double *)next_arg = double_tmp;
00134          else
00135            *fpr_base++ = double_tmp;
00136          next_arg++;
00137          fparg_count++;
00138          FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
00139          break;
00140 
00141        case FFI_TYPE_DOUBLE:
00142          double_tmp = *(double *)*p_argv;
00143          if (fparg_count >= NUM_FPR_ARG_REGISTERS)
00144            *(double *)next_arg = double_tmp;
00145          else
00146            *fpr_base++ = double_tmp;
00147          next_arg += 2;
00148          fparg_count++;
00149          FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
00150          break;
00151 
00152 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
00153 
00154        case FFI_TYPE_LONGDOUBLE:
00155          double_tmp = ((double *)*p_argv)[0];
00156          if (fparg_count >= NUM_FPR_ARG_REGISTERS)
00157            *(double *)next_arg = double_tmp;
00158          else
00159            *fpr_base++ = double_tmp;
00160          next_arg += 2;
00161          fparg_count++;
00162          double_tmp = ((double *)*p_argv)[1];
00163          if (fparg_count >= NUM_FPR_ARG_REGISTERS)
00164            *(double *)next_arg = double_tmp;
00165          else
00166            *fpr_base++ = double_tmp;
00167          next_arg += 2;
00168          fparg_count++;
00169          FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
00170          break;
00171 #endif
00172        case FFI_TYPE_UINT64:
00173        case FFI_TYPE_SINT64:
00174          *(long long *)next_arg = *(long long *)*p_argv;
00175          next_arg+=2;
00176          break;
00177        case FFI_TYPE_UINT8:
00178          gprvalue = *(unsigned char *)*p_argv;
00179          goto putgpr;
00180        case FFI_TYPE_SINT8:
00181          gprvalue = *(signed char *)*p_argv;
00182          goto putgpr;
00183        case FFI_TYPE_UINT16:
00184          gprvalue = *(unsigned short *)*p_argv;
00185          goto putgpr;
00186        case FFI_TYPE_SINT16:
00187          gprvalue = *(signed short *)*p_argv;
00188          goto putgpr;
00189 
00190        case FFI_TYPE_STRUCT:
00191          dest_cpy = (char *) next_arg;
00192 
00193          /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
00194             SI 4 bytes) are aligned as if they were those modes.
00195             Structures with 3 byte in size are padded upwards.  */
00196          size_al = (*ptr)->size;
00197          /* If the first member of the struct is a double, then align
00198             the struct to double-word.
00199             Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3.  */
00200          if ((*ptr)->elements[0]->type == 3)
00201            size_al = ALIGN((*ptr)->size, 8);
00202          if (size_al < 3 && ecif->cif->abi == FFI_DARWIN)
00203            dest_cpy += 4 - size_al;
00204 
00205          memcpy((char *)dest_cpy, (char *)*p_argv, size_al);
00206          next_arg += (size_al + 3) / 4;
00207          break;
00208 
00209        case FFI_TYPE_INT:
00210        case FFI_TYPE_UINT32:
00211        case FFI_TYPE_SINT32:
00212        case FFI_TYPE_POINTER:
00213          gprvalue = *(unsigned *)*p_argv;
00214        putgpr:
00215          *next_arg++ = gprvalue;
00216          break;
00217        default:
00218          break;
00219        }
00220     }
00221 
00222   /* Check that we didn't overrun the stack...  */
00223   //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
00224   //FFI_ASSERT((unsigned *)fpr_base
00225   //        <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
00226   //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
00227 }
00228 
00229 /* Adjust the size of S to be correct for Darwin.
00230    On Darwin, the first field of a structure has natural alignment.  */
00231 
00232 static void
00233 darwin_adjust_aggregate_sizes (ffi_type *s)
00234 {
00235   int i;
00236 
00237   if (s->type != FFI_TYPE_STRUCT)
00238     return;
00239 
00240   s->size = 0;
00241   for (i = 0; s->elements[i] != NULL; i++)
00242     {
00243       ffi_type *p;
00244       int align;
00245       
00246       p = s->elements[i];
00247       darwin_adjust_aggregate_sizes (p);
00248       if (i == 0
00249          && (p->type == FFI_TYPE_UINT64
00250              || p->type == FFI_TYPE_SINT64
00251              || p->type == FFI_TYPE_DOUBLE
00252              || p->alignment == 8))
00253        align = 8;
00254       else if (p->alignment == 16 || p->alignment < 4)
00255        align = p->alignment;
00256       else
00257        align = 4;
00258       s->size = ALIGN(s->size, align) + p->size;
00259     }
00260   
00261   s->size = ALIGN(s->size, s->alignment);
00262   
00263   if (s->elements[0]->type == FFI_TYPE_UINT64
00264       || s->elements[0]->type == FFI_TYPE_SINT64
00265       || s->elements[0]->type == FFI_TYPE_DOUBLE
00266       || s->elements[0]->alignment == 8)
00267     s->alignment = s->alignment > 8 ? s->alignment : 8;
00268   /* Do not add additional tail padding.  */
00269 }
00270 
00271 /* Perform machine dependent cif processing.  */
00272 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
00273 {
00274   /* All this is for the DARWIN ABI.  */
00275   int i;
00276   ffi_type **ptr;
00277   unsigned bytes;
00278   int fparg_count = 0, intarg_count = 0;
00279   unsigned flags = 0;
00280   unsigned size_al = 0;
00281 
00282   /* All the machine-independent calculation of cif->bytes will be wrong.
00283      All the calculation of structure sizes will also be wrong.
00284      Redo the calculation for DARWIN.  */
00285 
00286   if (cif->abi == FFI_DARWIN)
00287     {
00288       darwin_adjust_aggregate_sizes (cif->rtype);
00289       for (i = 0; i < cif->nargs; i++)
00290        darwin_adjust_aggregate_sizes (cif->arg_types[i]);
00291     }
00292 
00293   /* Space for the frame pointer, callee's LR, CR, etc, and for
00294      the asm's temp regs.  */
00295 
00296   bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long);
00297 
00298   /* Return value handling.  The rules are as follows:
00299      - 32-bit (or less) integer values are returned in gpr3;
00300      - Structures of size <= 4 bytes also returned in gpr3;
00301      - 64-bit integer values and structures between 5 and 8 bytes are returned
00302        in gpr3 and gpr4;
00303      - Single/double FP values are returned in fpr1;
00304      - Long double FP (if not equivalent to double) values are returned in
00305        fpr1 and fpr2;
00306      - Larger structures values are allocated space and a pointer is passed
00307        as the first argument.  */
00308   switch (cif->rtype->type)
00309     {
00310 
00311 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
00312     case FFI_TYPE_LONGDOUBLE:
00313       flags |= FLAG_RETURNS_128BITS;
00314       flags |= FLAG_RETURNS_FP;
00315       break;
00316 #endif
00317 
00318     case FFI_TYPE_DOUBLE:
00319       flags |= FLAG_RETURNS_64BITS;
00320       /* Fall through.  */
00321     case FFI_TYPE_FLOAT:
00322       flags |= FLAG_RETURNS_FP;
00323       break;
00324 
00325     case FFI_TYPE_UINT64:
00326     case FFI_TYPE_SINT64:
00327       flags |= FLAG_RETURNS_64BITS;
00328       break;
00329 
00330     case FFI_TYPE_STRUCT:
00331       flags |= FLAG_RETVAL_REFERENCE;
00332       flags |= FLAG_RETURNS_NOTHING;
00333       intarg_count++;
00334       break;
00335     case FFI_TYPE_VOID:
00336       flags |= FLAG_RETURNS_NOTHING;
00337       break;
00338 
00339     default:
00340       /* Returns 32-bit integer, or similar.  Nothing to do here.  */
00341       break;
00342     }
00343 
00344   /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
00345      first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
00346      goes on the stack.  Structures are passed as a pointer to a copy of
00347      the structure. Stuff on the stack needs to keep proper alignment.  */
00348   for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
00349     {
00350       switch ((*ptr)->type)
00351        {
00352        case FFI_TYPE_FLOAT:
00353        case FFI_TYPE_DOUBLE:
00354          fparg_count++;
00355          /* If this FP arg is going on the stack, it must be
00356             8-byte-aligned.  */
00357          if (fparg_count > NUM_FPR_ARG_REGISTERS
00358              && intarg_count%2 != 0)
00359            intarg_count++;
00360          break;
00361 
00362 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
00363 
00364        case FFI_TYPE_LONGDOUBLE:
00365          fparg_count += 2;
00366          /* If this FP arg is going on the stack, it must be
00367             8-byte-aligned.  */
00368          if (fparg_count > NUM_FPR_ARG_REGISTERS
00369              && intarg_count%2 != 0)
00370            intarg_count++;
00371          intarg_count +=2;
00372          break;
00373 #endif
00374 
00375        case FFI_TYPE_UINT64:
00376        case FFI_TYPE_SINT64:
00377          /* 'long long' arguments are passed as two words, but
00378             either both words must fit in registers or both go
00379             on the stack.  If they go on the stack, they must
00380             be 8-byte-aligned.  */
00381          if (intarg_count == NUM_GPR_ARG_REGISTERS-1
00382              || (intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0))
00383            intarg_count++;
00384          intarg_count += 2;
00385          break;
00386 
00387        case FFI_TYPE_STRUCT:
00388          size_al = (*ptr)->size;
00389          /* If the first member of the struct is a double, then align
00390             the struct to double-word.
00391             Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3.  */
00392          if ((*ptr)->elements[0]->type == 3)
00393            size_al = ALIGN((*ptr)->size, 8);
00394          intarg_count += (size_al + 3) / 4;
00395          break;
00396 
00397        default:
00398          /* Everything else is passed as a 4-byte word in a GPR, either
00399             the object itself or a pointer to it.  */
00400          intarg_count++;
00401          break;
00402        }
00403     }
00404 
00405   if (fparg_count != 0)
00406     flags |= FLAG_FP_ARGUMENTS;
00407 
00408   /* Space for the FPR registers, if needed.  */
00409   if (fparg_count != 0)
00410     bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
00411 
00412   /* Stack space.  */
00413   if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS)
00414     bytes += (intarg_count + 2 * fparg_count) * sizeof(long);
00415   else
00416     bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
00417 
00418   /* The stack space allocated needs to be a multiple of 16 bytes.  */
00419   bytes = (bytes + 15) & ~0xF;
00420 
00421   cif->flags = flags;
00422   cif->bytes = bytes;
00423 
00424   return FFI_OK;
00425 }
00426 
00427 extern void ffi_call_AIX(extended_cif *, unsigned, unsigned, unsigned *,
00428                       void (*fn)(), void (*fn2)());
00429 extern void ffi_call_DARWIN(extended_cif *, unsigned, unsigned, unsigned *,
00430                          void (*fn)(), void (*fn2)());
00431 
00432 void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
00433 {
00434   extended_cif ecif;
00435 
00436   ecif.cif = cif;
00437   ecif.avalue = avalue;
00438 
00439   /* If the return value is a struct and we don't have a return
00440      value address then we need to make one.  */
00441 
00442   if ((rvalue == NULL) &&
00443       (cif->rtype->type == FFI_TYPE_STRUCT))
00444     {
00445       ecif.rvalue = alloca(cif->rtype->size);
00446     }
00447   else
00448     ecif.rvalue = rvalue;
00449 
00450   switch (cif->abi)
00451     {
00452     case FFI_AIX:
00453       ffi_call_AIX(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
00454                  ffi_prep_args);
00455       break;
00456     case FFI_DARWIN:
00457       ffi_call_DARWIN(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn,
00458                     ffi_prep_args);
00459       break;
00460     default:
00461       FFI_ASSERT(0);
00462       break;
00463     }
00464 }
00465 
00466 static void flush_icache(char *);
00467 static void flush_range(char *, int);
00468 
00469 /* The layout of a function descriptor.  A C function pointer really
00470    points to one of these.  */
00471 
00472 typedef struct aix_fd_struct {
00473   void *code_pointer;
00474   void *toc;
00475 } aix_fd;
00476 
00477 /* here I'd like to add the stack frame layout we use in darwin_closure.S
00478    and aix_clsoure.S
00479 
00480    SP previous -> +---------------------------------------+ <--- child frame
00481                 | back chain to caller 4                |
00482                 +---------------------------------------+ 4
00483                 | saved CR 4                            |
00484                 +---------------------------------------+ 8
00485                 | saved LR 4                            |
00486                 +---------------------------------------+ 12
00487                 | reserved for compilers 4              |
00488                 +---------------------------------------+ 16
00489                 | reserved for binders 4                |
00490                 +---------------------------------------+ 20
00491                 | saved TOC pointer 4                   |
00492                 +---------------------------------------+ 24
00493                 | always reserved 8*4=32 (previous GPRs)|
00494                 | according to the linkage convention   |
00495                 | from AIX                              |
00496                 +---------------------------------------+ 56
00497                 | our FPR area 13*8=104                 |
00498                 | f1                                    |
00499                 | .                                     |
00500                 | f13                                   |
00501                 +---------------------------------------+ 160
00502                 | result area 8                         |
00503                 +---------------------------------------+ 168
00504                 | alignement to the next multiple of 16 |
00505 SP current -->    +---------------------------------------+ 176 <- parent frame
00506                 | back chain to caller 4                |
00507                 +---------------------------------------+ 180
00508                 | saved CR 4                            |
00509                 +---------------------------------------+ 184
00510                 | saved LR 4                            |
00511                 +---------------------------------------+ 188
00512                 | reserved for compilers 4              |
00513                 +---------------------------------------+ 192
00514                 | reserved for binders 4                |
00515                 +---------------------------------------+ 196
00516                 | saved TOC pointer 4                   |
00517                 +---------------------------------------+ 200
00518                 | always reserved 8*4=32  we store our  |
00519                 | GPRs here                             |
00520                 | r3                                    |
00521                 | .                                     |
00522                 | r10                                   |
00523                 +---------------------------------------+ 232
00524                 | overflow part                         |
00525                 +---------------------------------------+ xxx
00526                 | ????                                  |
00527                 +---------------------------------------+ xxx
00528 
00529 */
00530 ffi_status
00531 ffi_prep_closure_loc (ffi_closure* closure,
00532                     ffi_cif* cif,
00533                     void (*fun)(ffi_cif*, void*, void**, void*),
00534                     void *user_data,
00535                     void *codeloc)
00536 {
00537   unsigned int *tramp;
00538   struct ffi_aix_trampoline_struct *tramp_aix;
00539   aix_fd *fd;
00540 
00541   switch (cif->abi)
00542     {
00543     case FFI_DARWIN:
00544 
00545       FFI_ASSERT (cif->abi == FFI_DARWIN);
00546 
00547       tramp = (unsigned int *) &closure->tramp[0];
00548       tramp[0] = 0x7c0802a6;  /*   mflr    r0  */
00549       tramp[1] = 0x429f000d;  /*   bcl-    20,4*cr7+so,0x10  */
00550       tramp[4] = 0x7d6802a6;  /*   mflr    r11  */
00551       tramp[5] = 0x818b0000;  /*   lwz     r12,0(r11) function address  */
00552       tramp[6] = 0x7c0803a6;  /*   mtlr    r0   */
00553       tramp[7] = 0x7d8903a6;  /*   mtctr   r12  */
00554       tramp[8] = 0x816b0004;  /*   lwz     r11,4(r11) static chain  */
00555       tramp[9] = 0x4e800420;  /*   bctr  */
00556       tramp[2] = (unsigned long) ffi_closure_ASM; /* function  */
00557       tramp[3] = (unsigned long) codeloc; /* context  */
00558 
00559       closure->cif = cif;
00560       closure->fun = fun;
00561       closure->user_data = user_data;
00562 
00563       /* Flush the icache. Only necessary on Darwin.  */
00564       flush_range(codeloc, FFI_TRAMPOLINE_SIZE);
00565 
00566       break;
00567 
00568     case FFI_AIX:
00569 
00570       tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp);
00571       fd = (aix_fd *)(void *)ffi_closure_ASM;
00572 
00573       FFI_ASSERT (cif->abi == FFI_AIX);
00574 
00575       tramp_aix->code_pointer = fd->code_pointer;
00576       tramp_aix->toc = fd->toc;
00577       tramp_aix->static_chain = codeloc;
00578       closure->cif = cif;
00579       closure->fun = fun;
00580       closure->user_data = user_data;
00581 
00582     default:
00583 
00584       FFI_ASSERT(0);
00585       break;
00586     }
00587   return FFI_OK;
00588 }
00589 
00590 static void
00591 flush_icache(char *addr)
00592 {
00593 #ifndef _AIX
00594   __asm__ volatile (
00595               "dcbf 0,%0\n"
00596               "\tsync\n"
00597               "\ticbi 0,%0\n"
00598               "\tsync\n"
00599               "\tisync"
00600               : : "r"(addr) : "memory");
00601 #endif
00602 }
00603 
00604 static void
00605 flush_range(char * addr1, int size)
00606 {
00607 #define MIN_LINE_SIZE 32
00608   int i;
00609   for (i = 0; i < size; i += MIN_LINE_SIZE)
00610     flush_icache(addr1+i);
00611   flush_icache(addr1+size-1);
00612 }
00613 
00614 typedef union
00615 {
00616   float f;
00617   double d;
00618 } ffi_dblfl;
00619 
00620 int ffi_closure_helper_DARWIN (ffi_closure*, void*,
00621                             unsigned long*, ffi_dblfl*);
00622 
00623 /* Basically the trampoline invokes ffi_closure_ASM, and on
00624    entry, r11 holds the address of the closure.
00625    After storing the registers that could possibly contain
00626    parameters to be passed into the stack frame and setting
00627    up space for a return value, ffi_closure_ASM invokes the
00628    following helper function to do most of the work.  */
00629 
00630 int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
00631                             unsigned long * pgr, ffi_dblfl * pfr)
00632 {
00633   /* rvalue is the pointer to space for return value in closure assembly
00634      pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
00635      pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM.  */
00636 
00637   typedef double ldbits[2];
00638 
00639   union ldu
00640   {
00641     ldbits lb;
00642     long double ld;
00643   };
00644 
00645   void **          avalue;
00646   ffi_type **      arg_types;
00647   long             i, avn;
00648   long             nf;   /* number of floating registers already used.  */
00649   long             ng;   /* number of general registers already used.  */
00650   ffi_cif *        cif;
00651   double           temp;
00652   unsigned         size_al;
00653   union ldu        temp_ld;
00654 
00655   cif = closure->cif;
00656   avalue = alloca(cif->nargs * sizeof(void *));
00657 
00658   nf = 0;
00659   ng = 0;
00660 
00661   /* Copy the caller's structure return value address so that the closure
00662      returns the data directly to the caller.  */
00663   if (cif->rtype->type == FFI_TYPE_STRUCT)
00664     {
00665       rvalue = (void *) *pgr;
00666       pgr++;
00667       ng++;
00668     }
00669 
00670   i = 0;
00671   avn = cif->nargs;
00672   arg_types = cif->arg_types;
00673 
00674   /* Grab the addresses of the arguments from the stack frame.  */
00675   while (i < avn)
00676     {
00677       switch (arg_types[i]->type)
00678        {
00679        case FFI_TYPE_SINT8:
00680        case FFI_TYPE_UINT8:
00681          avalue[i] = (char *) pgr + 3;
00682          ng++;
00683          pgr++;
00684          break;
00685 
00686        case FFI_TYPE_SINT16:
00687        case FFI_TYPE_UINT16:
00688          avalue[i] = (char *) pgr + 2;
00689          ng++;
00690          pgr++;
00691          break;
00692 
00693        case FFI_TYPE_SINT32:
00694        case FFI_TYPE_UINT32:
00695        case FFI_TYPE_POINTER:
00696          avalue[i] = pgr;
00697          ng++;
00698          pgr++;
00699          break;
00700 
00701        case FFI_TYPE_STRUCT:
00702          /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
00703             SI 4 bytes) are aligned as if they were those modes.  */
00704          size_al = arg_types[i]->size;
00705          /* If the first member of the struct is a double, then align
00706             the struct to double-word.
00707             Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3.  */
00708          if (arg_types[i]->elements[0]->type == 3)
00709            size_al = ALIGN(arg_types[i]->size, 8);
00710          if (size_al < 3 && cif->abi == FFI_DARWIN)
00711            avalue[i] = (void*) pgr + 4 - size_al;
00712          else
00713            avalue[i] = (void*) pgr;
00714          ng += (size_al + 3) / 4;
00715          pgr += (size_al + 3) / 4;
00716          break;
00717 
00718        case FFI_TYPE_SINT64:
00719        case FFI_TYPE_UINT64:
00720          /* Long long ints are passed in two gpr's.  */
00721          avalue[i] = pgr;
00722          ng += 2;
00723          pgr += 2;
00724          break;
00725 
00726        case FFI_TYPE_FLOAT:
00727          /* A float value consumes a GPR.
00728             There are 13 64bit floating point registers.  */
00729          if (nf < NUM_FPR_ARG_REGISTERS)
00730            {
00731              temp = pfr->d;
00732              pfr->f = (float)temp;
00733              avalue[i] = pfr;
00734              pfr++;
00735            }
00736          else
00737            {
00738              avalue[i] = pgr;
00739            }
00740          nf++;
00741          ng++;
00742          pgr++;
00743          break;
00744 
00745        case FFI_TYPE_DOUBLE:
00746          /* A double value consumes two GPRs.
00747             There are 13 64bit floating point registers.  */
00748          if (nf < NUM_FPR_ARG_REGISTERS)
00749            {
00750              avalue[i] = pfr;
00751              pfr++;
00752            }
00753          else
00754            {
00755              avalue[i] = pgr;
00756            }
00757          nf++;
00758          ng += 2;
00759          pgr += 2;
00760          break;
00761 
00762 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
00763 
00764        case FFI_TYPE_LONGDOUBLE:
00765          /* A long double value consumes four GPRs and two FPRs.
00766             There are 13 64bit floating point registers.  */
00767          if (nf < NUM_FPR_ARG_REGISTERS - 1)
00768            {
00769              avalue[i] = pfr;
00770              pfr += 2;
00771            }
00772          /* Here we have the situation where one part of the long double
00773             is stored in fpr13 and the other part is already on the stack.
00774             We use a union to pass the long double to avalue[i].  */
00775          else if (nf == NUM_FPR_ARG_REGISTERS - 1)
00776            {
00777              memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
00778              memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
00779              avalue[i] = &temp_ld.ld;
00780            }
00781          else
00782            {
00783              avalue[i] = pgr;
00784            }
00785          nf += 2;
00786          ng += 4;
00787          pgr += 4;
00788          break;
00789 #endif
00790        default:
00791          FFI_ASSERT(0);
00792        }
00793       i++;
00794     }
00795 
00796   (closure->fun) (cif, rvalue, avalue, closure->user_data);
00797 
00798   /* Tell ffi_closure_ASM to perform return type promotions.  */
00799   return cif->rtype->type;
00800 }