(root)/
gcc-13.2.0/
libffi/
src/
pa/
ffi.c
       1  /* -----------------------------------------------------------------------
       2     ffi.c - (c) 2011 Anthony Green
       3             (c) 2008 Red Hat, Inc.
       4  	   (c) 2006 Free Software Foundation, Inc.
       5             (c) 2003-2004 Randolph Chung <tausq@debian.org>
       6             
       7     HPPA Foreign Function Interface
       8     HP-UX PA ABI support 
       9  
      10     Permission is hereby granted, free of charge, to any person obtaining
      11     a copy of this software and associated documentation files (the
      12     ``Software''), to deal in the Software without restriction, including
      13     without limitation the rights to use, copy, modify, merge, publish,
      14     distribute, sublicense, and/or sell copies of the Software, and to
      15     permit persons to whom the Software is furnished to do so, subject to
      16     the following conditions:
      17  
      18     The above copyright notice and this permission notice shall be included
      19     in all copies or substantial portions of the Software.
      20  
      21     THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
      22     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      23     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      24     NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
      25     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      26     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      27     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28     DEALINGS IN THE SOFTWARE.
      29     ----------------------------------------------------------------------- */
      30  
      31  #include <ffi.h>
      32  #include <ffi_common.h>
      33  
      34  #include <stdlib.h>
      35  #include <stdio.h>
      36  
      37  #define ROUND_UP(v, a)  (((size_t)(v) + (a) - 1) & ~((a) - 1))
      38  
      39  #define MIN_STACK_SIZE  64
      40  #define FIRST_ARG_SLOT  9
      41  #define DEBUG_LEVEL   0
      42  
      43  #define fldw(addr, fpreg) \
      44    __asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
      45  #define fstw(fpreg, addr) \
      46    __asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
      47  #define fldd(addr, fpreg) \
      48    __asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
      49  #define fstd(fpreg, addr) \
      50    __asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
      51  
      52  #define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
      53  
      54  static inline int ffi_struct_type(ffi_type *t)
      55  {
      56    size_t sz = t->size;
      57  
      58    /* Small structure results are passed in registers,
      59       larger ones are passed by pointer.  Note that
      60       small structures of size 2, 4 and 8 differ from
      61       the corresponding integer types in that they have
      62       different alignment requirements.  */
      63  
      64    if (sz <= 1)
      65      return FFI_TYPE_UINT8;
      66    else if (sz == 2)
      67      return FFI_TYPE_SMALL_STRUCT2;
      68    else if (sz == 3)
      69      return FFI_TYPE_SMALL_STRUCT3;
      70    else if (sz == 4)
      71      return FFI_TYPE_SMALL_STRUCT4;
      72    else if (sz == 5)
      73      return FFI_TYPE_SMALL_STRUCT5;
      74    else if (sz == 6)
      75      return FFI_TYPE_SMALL_STRUCT6;
      76    else if (sz == 7)
      77      return FFI_TYPE_SMALL_STRUCT7;
      78    else if (sz <= 8)
      79      return FFI_TYPE_SMALL_STRUCT8;
      80    else
      81      return FFI_TYPE_STRUCT; /* else, we pass it by pointer.  */
      82  }
      83  
      84  /* PA has a downward growing stack, which looks like this:
      85  
      86     Offset
      87  	[ Variable args ]
      88     SP = (4*(n+9))       arg word N
      89     ...
      90     SP-52                arg word 4
      91  	[ Fixed args ]
      92     SP-48                arg word 3
      93     SP-44                arg word 2
      94     SP-40                arg word 1
      95     SP-36                arg word 0
      96  	[ Frame marker ]
      97     ...
      98     SP-20                RP
      99     SP-4                 previous SP
     100  
     101     The first four argument words on the stack are reserved for use by
     102     the callee.  Instead, the general and floating registers replace
     103     the first four argument slots.  Non FP arguments are passed solely
     104     in the general registers.  FP arguments are passed in both general
     105     and floating registers when using libffi.
     106  
     107     Non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23.
     108     Non-FP 64-bit args are passed in register pairs, starting
     109     on an odd numbered register (i.e. r25+r26 and r23+r24).
     110     FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L.
     111     FP 64-bit arguments are passed in fr5 and fr7.
     112  
     113     The registers are allocated in the same manner as stack slots.
     114     This allows the callee to save its arguments on the stack if
     115     necessary:
     116  
     117     arg word 3 -> gr23 or fr7L
     118     arg word 2 -> gr24 or fr6L or fr7R
     119     arg word 1 -> gr25 or fr5L
     120     arg word 0 -> gr26 or fr4L or fr5R
     121  
     122     Note that fr4R and fr6R are never used for arguments (i.e.,
     123     doubles are not passed in fr4 or fr6).
     124  
     125     The rest of the arguments are passed on the stack starting at SP-52,
     126     but 64-bit arguments need to be aligned to an 8-byte boundary
     127  
     128     This means we can have holes either in the register allocation,
     129     or in the stack.  */
     130  
     131  /* ffi_prep_args is called by the assembly routine once stack space
     132     has been allocated for the function's arguments
     133  
     134     The following code will put everything into the stack frame
     135     (which was allocated by the asm routine), and on return
     136     the asm routine will load the arguments that should be
     137     passed by register into the appropriate registers
     138  
     139     NOTE: We load floating point args in this function... that means we
     140     assume gcc will not mess with fp regs in here.  */
     141  
     142  void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
     143  {
     144    register unsigned int i;
     145    register ffi_type **p_arg;
     146    register void **p_argv;
     147    unsigned int slot = FIRST_ARG_SLOT;
     148    char *dest_cpy;
     149    size_t len;
     150  
     151    debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack,
     152  	ecif, bytes);
     153  
     154    p_arg = ecif->cif->arg_types;
     155    p_argv = ecif->avalue;
     156  
     157    for (i = 0; i < ecif->cif->nargs; i++)
     158      {
     159        int type = (*p_arg)->type;
     160  
     161        switch (type)
     162  	{
     163  	case FFI_TYPE_SINT8:
     164  	  *(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
     165  	  break;
     166  
     167  	case FFI_TYPE_UINT8:
     168  	  *(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
     169  	  break;
     170  
     171  	case FFI_TYPE_SINT16:
     172  	  *(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
     173  	  break;
     174  
     175  	case FFI_TYPE_UINT16:
     176  	  *(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
     177  	  break;
     178  
     179  	case FFI_TYPE_UINT32:
     180  	case FFI_TYPE_SINT32:
     181  	case FFI_TYPE_POINTER:
     182  	  debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv),
     183  		slot);
     184  	  *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
     185  	  break;
     186  
     187  	case FFI_TYPE_UINT64:
     188  	case FFI_TYPE_SINT64:
     189  	  /* Align slot for 64-bit type.  */
     190  	  slot += (slot & 1) ? 1 : 2;
     191  	  *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
     192  	  break;
     193  
     194  	case FFI_TYPE_FLOAT:
     195  	  /* First 4 args go in fr4L - fr7L.  */
     196  	  debug(3, "Storing UINT32(float) in slot %u\n", slot);
     197  	  *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
     198  	  switch (slot - FIRST_ARG_SLOT)
     199  	    {
     200  	    /* First 4 args go in fr4L - fr7L.  */
     201  	    case 0: fldw(stack - slot, fr4); break;
     202  	    case 1: fldw(stack - slot, fr5); break;
     203  	    case 2: fldw(stack - slot, fr6); break;
     204  	    case 3: fldw(stack - slot, fr7); break;
     205  	    }
     206  	  break;
     207  
     208  	case FFI_TYPE_DOUBLE:
     209  	  /* Align slot for 64-bit type.  */
     210  	  slot += (slot & 1) ? 1 : 2;
     211  	  debug(3, "Storing UINT64(double) at slot %u\n", slot);
     212  	  *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
     213  	  switch (slot - FIRST_ARG_SLOT)
     214  	    {
     215  	      /* First 2 args go in fr5, fr7.  */
     216  	      case 1: fldd(stack - slot, fr5); break;
     217  	      case 3: fldd(stack - slot, fr7); break;
     218  	    }
     219  	  break;
     220  
     221  #ifdef PA_HPUX
     222  	case FFI_TYPE_LONGDOUBLE:
     223  	  /* Long doubles are passed in the same manner as structures
     224  	     larger than 8 bytes.  */
     225  	  *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
     226  	  break;
     227  #endif
     228  
     229  	case FFI_TYPE_STRUCT:
     230  
     231  	  /* Structs smaller or equal than 4 bytes are passed in one
     232  	     register. Structs smaller or equal 8 bytes are passed in two
     233  	     registers. Larger structures are passed by pointer.  */
     234  
     235  	  len = (*p_arg)->size;
     236  	  if (len <= 4)
     237  	    {
     238  	      dest_cpy = (char *)(stack - slot) + 4 - len;
     239  	      memcpy(dest_cpy, (char *)*p_argv, len);
     240  	    }
     241  	  else if (len <= 8)
     242  	    {
     243  	      slot += (slot & 1) ? 1 : 2;
     244  	      dest_cpy = (char *)(stack - slot) + 8 - len;
     245  	      memcpy(dest_cpy, (char *)*p_argv, len);
     246  	    }
     247  	  else
     248  	    *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
     249  	  break;
     250  
     251  	default:
     252  	  FFI_ASSERT(0);
     253  	}
     254  
     255        slot++;
     256        p_arg++;
     257        p_argv++;
     258      }
     259  
     260    /* Make sure we didn't mess up and scribble on the stack.  */
     261    {
     262      unsigned int n;
     263  
     264      debug(5, "Stack setup:\n");
     265      for (n = 0; n < (bytes + 3) / 4; n++)
     266        {
     267  	if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
     268  	debug(5, "%08x ", *(stack - n));
     269        }
     270      debug(5, "\n");
     271    }
     272  
     273    FFI_ASSERT(slot * 4 <= bytes);
     274  
     275    return;
     276  }
     277  
     278  static void ffi_size_stack_pa32(ffi_cif *cif)
     279  {
     280    ffi_type **ptr;
     281    int i;
     282    int z = 0; /* # stack slots */
     283  
     284    for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
     285      {
     286        int type = (*ptr)->type;
     287  
     288        switch (type)
     289  	{
     290  	case FFI_TYPE_DOUBLE:
     291  	case FFI_TYPE_UINT64:
     292  	case FFI_TYPE_SINT64:
     293  	  z += 2 + (z & 1); /* must start on even regs, so we may waste one */
     294  	  break;
     295  
     296  #ifdef PA_HPUX
     297  	case FFI_TYPE_LONGDOUBLE:
     298  #endif
     299  	case FFI_TYPE_STRUCT:
     300  	  z += 1; /* pass by ptr, callee will copy */
     301  	  break;
     302  
     303  	default: /* <= 32-bit values */
     304  	  z++;
     305  	}
     306      }
     307  
     308    /* We can fit up to 6 args in the default 64-byte stack frame,
     309       if we need more, we need more stack.  */
     310    if (z <= 6)
     311      cif->bytes = MIN_STACK_SIZE; /* min stack size */
     312    else
     313      cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);
     314  
     315    debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
     316  }
     317  
     318  /* Perform machine dependent cif processing.  */
     319  ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
     320  {
     321    /* Set the return type flag */
     322    switch (cif->rtype->type)
     323      {
     324      case FFI_TYPE_VOID:
     325      case FFI_TYPE_FLOAT:
     326      case FFI_TYPE_DOUBLE:
     327        cif->flags = (unsigned) cif->rtype->type;
     328        break;
     329  
     330  #ifdef PA_HPUX
     331      case FFI_TYPE_LONGDOUBLE:
     332        /* Long doubles are treated like a structure.  */
     333        cif->flags = FFI_TYPE_STRUCT;
     334        break;
     335  #endif
     336  
     337      case FFI_TYPE_STRUCT:
     338        /* For the return type we have to check the size of the structures.
     339  	 If the size is smaller or equal 4 bytes, the result is given back
     340  	 in one register. If the size is smaller or equal 8 bytes than we
     341  	 return the result in two registers. But if the size is bigger than
     342  	 8 bytes, we work with pointers.  */
     343        cif->flags = ffi_struct_type(cif->rtype);
     344        break;
     345  
     346      case FFI_TYPE_UINT64:
     347      case FFI_TYPE_SINT64:
     348        cif->flags = FFI_TYPE_UINT64;
     349        break;
     350  
     351      default:
     352        cif->flags = FFI_TYPE_INT;
     353        break;
     354      }
     355  
     356    /* Lucky us, because of the unique PA ABI we get to do our
     357       own stack sizing.  */
     358    switch (cif->abi)
     359      {
     360      case FFI_PA32:
     361        ffi_size_stack_pa32(cif);
     362        break;
     363  
     364      default:
     365        FFI_ASSERT(0);
     366        break;
     367      }
     368  
     369    return FFI_OK;
     370  }
     371  
     372  extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned),
     373  			  extended_cif *, unsigned, unsigned, unsigned *,
     374  			  void (*fn)(void));
     375  
     376  void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
     377  {
     378    extended_cif ecif;
     379  
     380    ecif.cif = cif;
     381    ecif.avalue = avalue;
     382  
     383    /* If the return value is a struct and we don't have a return
     384       value address then we need to make one.  */
     385  
     386    if (rvalue == NULL
     387  #ifdef PA_HPUX
     388        && (cif->rtype->type == FFI_TYPE_STRUCT
     389  	  || cif->rtype->type == FFI_TYPE_LONGDOUBLE))
     390  #else
     391        && cif->rtype->type == FFI_TYPE_STRUCT)
     392  #endif
     393      {
     394        ecif.rvalue = alloca(cif->rtype->size);
     395      }
     396    else
     397      ecif.rvalue = rvalue;
     398  
     399  
     400    switch (cif->abi)
     401      {
     402      case FFI_PA32:
     403        debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
     404        ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes,
     405  		     cif->flags, ecif.rvalue, fn);
     406        break;
     407  
     408      default:
     409        FFI_ASSERT(0);
     410        break;
     411      }
     412  }
     413  
     414  #if FFI_CLOSURES
     415  /* This is more-or-less an inverse of ffi_call -- we have arguments on
     416     the stack, and we need to fill them into a cif structure and invoke
     417     the user function. This really ought to be in asm to make sure
     418     the compiler doesn't do things we don't expect.  */
     419  ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
     420  {
     421    ffi_cif *cif;
     422    void **avalue;
     423    void *rvalue;
     424    /* Functions can return up to 64-bits in registers.  Return address
     425       must be double word aligned.  */
     426    union { double rd; UINT32 ret[2]; } u;
     427    ffi_type **p_arg;
     428    char *tmp;
     429    int i, avn;
     430    unsigned int slot = FIRST_ARG_SLOT;
     431    register UINT32 r28 asm("r28");
     432    ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure);
     433  
     434    cif = closure->cif;
     435  
     436    /* If returning via structure, callee will write to our pointer.  */
     437    if (cif->flags == FFI_TYPE_STRUCT)
     438      rvalue = (void *)r28;
     439    else
     440      rvalue = &u;
     441  
     442    avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
     443    avn = cif->nargs;
     444    p_arg = cif->arg_types;
     445  
     446    for (i = 0; i < avn; i++)
     447      {
     448        int type = (*p_arg)->type;
     449  
     450        switch (type)
     451  	{
     452  	case FFI_TYPE_SINT8:
     453  	case FFI_TYPE_UINT8:
     454  	case FFI_TYPE_SINT16:
     455  	case FFI_TYPE_UINT16:
     456  	case FFI_TYPE_SINT32:
     457  	case FFI_TYPE_UINT32:
     458  	case FFI_TYPE_POINTER:
     459  	  avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
     460  	  break;
     461  
     462  	case FFI_TYPE_SINT64:
     463  	case FFI_TYPE_UINT64:
     464  	  slot += (slot & 1) ? 1 : 2;
     465  	  avalue[i] = (void *)(stack - slot);
     466  	  break;
     467  
     468  	case FFI_TYPE_FLOAT:
     469  #ifdef PA_LINUX
     470  	  /* The closure call is indirect.  In Linux, floating point
     471  	     arguments in indirect calls with a prototype are passed
     472  	     in the floating point registers instead of the general
     473  	     registers.  So, we need to replace what was previously
     474  	     stored in the current slot with the value in the
     475  	     corresponding floating point register.  */
     476  	  switch (slot - FIRST_ARG_SLOT)
     477  	    {
     478  	    case 0: fstw(fr4, (void *)(stack - slot)); break;
     479  	    case 1: fstw(fr5, (void *)(stack - slot)); break;
     480  	    case 2: fstw(fr6, (void *)(stack - slot)); break;
     481  	    case 3: fstw(fr7, (void *)(stack - slot)); break;
     482  	    }
     483  #endif
     484  	  avalue[i] = (void *)(stack - slot);
     485  	  break;
     486  
     487  	case FFI_TYPE_DOUBLE:
     488  	  slot += (slot & 1) ? 1 : 2;
     489  #ifdef PA_LINUX
     490  	  /* See previous comment for FFI_TYPE_FLOAT.  */
     491  	  switch (slot - FIRST_ARG_SLOT)
     492  	    {
     493  	    case 1: fstd(fr5, (void *)(stack - slot)); break;
     494  	    case 3: fstd(fr7, (void *)(stack - slot)); break;
     495  	    }
     496  #endif
     497  	  avalue[i] = (void *)(stack - slot);
     498  	  break;
     499  
     500  #ifdef PA_HPUX
     501  	case FFI_TYPE_LONGDOUBLE:
     502  	  /* Long doubles are treated like a big structure.  */
     503  	  avalue[i] = (void *) *(stack - slot);
     504  	  break;
     505  #endif
     506  
     507  	case FFI_TYPE_STRUCT:
     508  	  /* Structs smaller or equal than 4 bytes are passed in one
     509  	     register. Structs smaller or equal 8 bytes are passed in two
     510  	     registers. Larger structures are passed by pointer.  */
     511  	  if((*p_arg)->size <= 4)
     512  	    {
     513  	      avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
     514  		(*p_arg)->size;
     515  	    }
     516  	  else if ((*p_arg)->size <= 8)
     517  	    {
     518  	      slot += (slot & 1) ? 1 : 2;
     519  	      avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
     520  		(*p_arg)->size;
     521  	    }
     522  	  else
     523  	    avalue[i] = (void *) *(stack - slot);
     524  	  break;
     525  
     526  	default:
     527  	  FFI_ASSERT(0);
     528  	}
     529  
     530        slot++;
     531        p_arg++;
     532      }
     533  
     534    /* Invoke the closure.  */
     535    (c->fun) (cif, rvalue, avalue, c->user_data);
     536  
     537    debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", u.ret[0],
     538  	u.ret[1]);
     539  
     540    /* Store the result using the lower 2 bytes of the flags.  */
     541    switch (cif->flags)
     542      {
     543      case FFI_TYPE_UINT8:
     544        *(stack - FIRST_ARG_SLOT) = (UINT8)(u.ret[0] >> 24);
     545        break;
     546      case FFI_TYPE_SINT8:
     547        *(stack - FIRST_ARG_SLOT) = (SINT8)(u.ret[0] >> 24);
     548        break;
     549      case FFI_TYPE_UINT16:
     550        *(stack - FIRST_ARG_SLOT) = (UINT16)(u.ret[0] >> 16);
     551        break;
     552      case FFI_TYPE_SINT16:
     553        *(stack - FIRST_ARG_SLOT) = (SINT16)(u.ret[0] >> 16);
     554        break;
     555      case FFI_TYPE_INT:
     556      case FFI_TYPE_SINT32:
     557      case FFI_TYPE_UINT32:
     558        *(stack - FIRST_ARG_SLOT) = u.ret[0];
     559        break;
     560      case FFI_TYPE_SINT64:
     561      case FFI_TYPE_UINT64:
     562        *(stack - FIRST_ARG_SLOT) = u.ret[0];
     563        *(stack - FIRST_ARG_SLOT - 1) = u.ret[1];
     564        break;
     565  
     566      case FFI_TYPE_DOUBLE:
     567        fldd(rvalue, fr4);
     568        break;
     569  
     570      case FFI_TYPE_FLOAT:
     571        fldw(rvalue, fr4);
     572        break;
     573  
     574      case FFI_TYPE_STRUCT:
     575        /* Don't need a return value, done by caller.  */
     576        break;
     577  
     578      case FFI_TYPE_SMALL_STRUCT2:
     579      case FFI_TYPE_SMALL_STRUCT3:
     580      case FFI_TYPE_SMALL_STRUCT4:
     581        tmp = (void*)(stack -  FIRST_ARG_SLOT);
     582        tmp += 4 - cif->rtype->size;
     583        memcpy((void*)tmp, &u, cif->rtype->size);
     584        break;
     585  
     586      case FFI_TYPE_SMALL_STRUCT5:
     587      case FFI_TYPE_SMALL_STRUCT6:
     588      case FFI_TYPE_SMALL_STRUCT7:
     589      case FFI_TYPE_SMALL_STRUCT8:
     590        {
     591  	unsigned int ret2[2];
     592  	int off;
     593  
     594  	/* Right justify ret[0] and ret[1] */
     595  	switch (cif->flags)
     596  	  {
     597  	    case FFI_TYPE_SMALL_STRUCT5: off = 3; break;
     598  	    case FFI_TYPE_SMALL_STRUCT6: off = 2; break;
     599  	    case FFI_TYPE_SMALL_STRUCT7: off = 1; break;
     600  	    default: off = 0; break;
     601  	  }
     602  
     603  	memset (ret2, 0, sizeof (ret2));
     604  	memcpy ((char *)ret2 + off, &u, 8 - off);
     605  
     606  	*(stack - FIRST_ARG_SLOT) = ret2[0];
     607  	*(stack - FIRST_ARG_SLOT - 1) = ret2[1];
     608        }
     609        break;
     610  
     611      case FFI_TYPE_POINTER:
     612      case FFI_TYPE_VOID:
     613        break;
     614  
     615      default:
     616        debug(0, "assert with cif->flags: %d\n",cif->flags);
     617        FFI_ASSERT(0);
     618        break;
     619      }
     620    return FFI_OK;
     621  }
     622  
     623  /* Fill in a closure to refer to the specified fun and user_data.
     624     cif specifies the argument and result types for fun.
     625     The cif must already be prep'ed.  */
     626  
     627  extern void ffi_closure_pa32(void);
     628  
     629  ffi_status
     630  ffi_prep_closure_loc (ffi_closure* closure,
     631  		      ffi_cif* cif,
     632  		      void (*fun)(ffi_cif*,void*,void**,void*),
     633  		      void *user_data,
     634  		      void *codeloc)
     635  {
     636    ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure);
     637  
     638    /* The layout of a function descriptor.  A function pointer with the PLABEL
     639       bit set points to a function descriptor.  */
     640    struct pa32_fd
     641    {
     642      UINT32 code_pointer;
     643      UINT32 gp;
     644    };
     645  
     646    struct ffi_pa32_trampoline_struct
     647    {
     648       UINT32 code_pointer;        /* Pointer to ffi_closure_unix.  */
     649       UINT32 fake_gp;             /* Pointer to closure, installed as gp.  */
     650       UINT32 real_gp;             /* Real gp value.  */
     651    };
     652  
     653    struct ffi_pa32_trampoline_struct *tramp;
     654    struct pa32_fd *fd;
     655  
     656    if (cif->abi != FFI_PA32)
     657      return FFI_BAD_ABI;
     658  
     659    /* Get function descriptor address for ffi_closure_pa32.  */
     660    fd = (struct pa32_fd *)((UINT32)ffi_closure_pa32 & ~3);
     661  
     662    /* Setup trampoline.  */
     663    tramp = (struct ffi_pa32_trampoline_struct *)c->tramp;
     664    tramp->code_pointer = fd->code_pointer;
     665    tramp->fake_gp = (UINT32)codeloc & ~3;
     666    tramp->real_gp = fd->gp;
     667  
     668    c->cif  = cif;
     669    c->user_data = user_data;
     670    c->fun  = fun;
     671  
     672    return FFI_OK;
     673  }
     674  #endif