Back to index

plt-scheme  4.2.1
Defines | Functions
ffi.c File Reference
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
#include <stdio.h>

Go to the source code of this file.

Defines

#define ROUND_UP(v, a)   (((size_t)(v) + (a) - 1) & ~((a) - 1))
#define MIN_STACK_SIZE   64
#define FIRST_ARG_SLOT   9
#define DEBUG_LEVEL   0
#define fldw(addr, fpreg)   __asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
#define fstw(fpreg, addr)   __asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
#define fldd(addr, fpreg)   __asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
#define fstd(fpreg, addr)   __asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
#define debug(lvl, x...)   do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)

Functions

static int ffi_struct_type (ffi_type *t)
void ffi_prep_args_pa32 (UINT32 *stack, extended_cif *ecif, unsigned bytes)
static void ffi_size_stack_pa32 (ffi_cif *cif)
ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
void ffi_call_pa32 (void(*)(UINT32 *, extended_cif *, unsigned), extended_cif *, unsigned, unsigned, unsigned *, void(*fn)())
void ffi_call (ffi_cif *cif, void(*fn)(), void *rvalue, void **avalue)

Define Documentation

#define debug (   lvl,
  x... 
)    do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)

Definition at line 48 of file ffi.c.

#define DEBUG_LEVEL   0

Definition at line 37 of file ffi.c.

#define FIRST_ARG_SLOT   9

Definition at line 36 of file ffi.c.

#define fldd (   addr,
  fpreg 
)    __asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)

Definition at line 43 of file ffi.c.

#define fldw (   addr,
  fpreg 
)    __asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)

Definition at line 39 of file ffi.c.

#define fstd (   fpreg,
  addr 
)    __asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))

Definition at line 45 of file ffi.c.

#define fstw (   fpreg,
  addr 
)    __asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))

Definition at line 41 of file ffi.c.

#define MIN_STACK_SIZE   64

Definition at line 35 of file ffi.c.

#define ROUND_UP (   v,
  a 
)    (((size_t)(v) + (a) - 1) & ~((a) - 1))

Definition at line 33 of file ffi.c.


Function Documentation

void ffi_call ( ffi_cif *  cif,
void(*)()  fn,
void rvalue,
void **  avalue 
)

Definition at line 372 of file ffi.c.

{
  extended_cif ecif;

  ecif.cif = cif;
  ecif.avalue = avalue;

  /* If the return value is a struct and we don't have a return
     value address then we need to make one.  */

  if (rvalue == NULL
#ifdef PA_HPUX
      && (cif->rtype->type == FFI_TYPE_STRUCT
         || cif->rtype->type == FFI_TYPE_LONGDOUBLE))
#else
      && cif->rtype->type == FFI_TYPE_STRUCT)
#endif
    {
      ecif.rvalue = alloca(cif->rtype->size);
    }
  else
    ecif.rvalue = rvalue;


  switch (cif->abi)
    {
    case FFI_PA32:
      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);
      ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes,
                   cif->flags, ecif.rvalue, fn);
      break;

    default:
      FFI_ASSERT(0);
      break;
    }
}

Here is the call graph for this function:

void ffi_call_pa32 ( void(*)(UINT32 *, extended_cif *, unsigned)  ,
extended_cif ,
unsigned  ,
unsigned  ,
unsigned *  ,
void(*)()  fn 
)

Here is the caller graph for this function:

void ffi_prep_args_pa32 ( UINT32 *  stack,
extended_cif ecif,
unsigned  bytes 
)

Definition at line 138 of file ffi.c.

{
  register unsigned int i;
  register ffi_type **p_arg;
  register void **p_argv;
  unsigned int slot = FIRST_ARG_SLOT;
  char *dest_cpy;
  size_t len;

  debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack,
       ecif, bytes);

  p_arg = ecif->cif->arg_types;
  p_argv = ecif->avalue;

  for (i = 0; i < ecif->cif->nargs; i++)
    {
      int type = (*p_arg)->type;

      switch (type)
       {
       case FFI_TYPE_SINT8:
         *(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
         break;

       case FFI_TYPE_UINT8:
         *(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
         break;

       case FFI_TYPE_SINT16:
         *(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
         break;

       case FFI_TYPE_UINT16:
         *(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
         break;

       case FFI_TYPE_UINT32:
       case FFI_TYPE_SINT32:
       case FFI_TYPE_POINTER:
         debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv),
              slot);
         *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
         break;

       case FFI_TYPE_UINT64:
       case FFI_TYPE_SINT64:
         /* Align slot for 64-bit type.  */
         slot += (slot & 1) ? 1 : 2;
         *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
         break;

       case FFI_TYPE_FLOAT:
         /* First 4 args go in fr4L - fr7L.  */
         debug(3, "Storing UINT32(float) in slot %u\n", slot);
         *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
         switch (slot - FIRST_ARG_SLOT)
           {
           /* First 4 args go in fr4L - fr7L.  */
           case 0: fldw(stack - slot, fr4); break;
           case 1: fldw(stack - slot, fr5); break;
           case 2: fldw(stack - slot, fr6); break;
           case 3: fldw(stack - slot, fr7); break;
           }
         break;

       case FFI_TYPE_DOUBLE:
         /* Align slot for 64-bit type.  */
         slot += (slot & 1) ? 1 : 2;
         debug(3, "Storing UINT64(double) at slot %u\n", slot);
         *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
         switch (slot - FIRST_ARG_SLOT)
           {
             /* First 2 args go in fr5, fr7.  */
             case 1: fldd(stack - slot, fr5); break;
             case 3: fldd(stack - slot, fr7); break;
           }
         break;

#ifdef PA_HPUX
       case FFI_TYPE_LONGDOUBLE:
         /* Long doubles are passed in the same manner as structures
            larger than 8 bytes.  */
         *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
         break;
#endif

       case FFI_TYPE_STRUCT:

         /* Structs smaller or equal than 4 bytes are passed in one
            register. Structs smaller or equal 8 bytes are passed in two
            registers. Larger structures are passed by pointer.  */

         len = (*p_arg)->size;
         if (len <= 4)
           {
             dest_cpy = (char *)(stack - slot) + 4 - len;
             memcpy(dest_cpy, (char *)*p_argv, len);
           }
         else if (len <= 8)
           {
             slot += (slot & 1) ? 1 : 2;
             dest_cpy = (char *)(stack - slot) + 8 - len;
             memcpy(dest_cpy, (char *)*p_argv, len);
           }
         else
           *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
         break;

       default:
         FFI_ASSERT(0);
       }

      slot++;
      p_arg++;
      p_argv++;
    }

  /* Make sure we didn't mess up and scribble on the stack.  */
  {
    unsigned int n;

    debug(5, "Stack setup:\n");
    for (n = 0; n < (bytes + 3) / 4; n++)
      {
       if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
       debug(5, "%08x ", *(stack - n));
      }
    debug(5, "\n");
  }

  FFI_ASSERT(slot * 4 <= bytes);

  return;
}

Here is the caller graph for this function:

ffi_status ffi_prep_cif_machdep ( ffi_cif *  cif)

Definition at line 315 of file ffi.c.

{
  /* Set the return type flag */
  switch (cif->rtype->type)
    {
    case FFI_TYPE_VOID:
    case FFI_TYPE_FLOAT:
    case FFI_TYPE_DOUBLE:
      cif->flags = (unsigned) cif->rtype->type;
      break;

#ifdef PA_HPUX
    case FFI_TYPE_LONGDOUBLE:
      /* Long doubles are treated like a structure.  */
      cif->flags = FFI_TYPE_STRUCT;
      break;
#endif

    case FFI_TYPE_STRUCT:
      /* For the return type we have to check the size of the structures.
        If the size is smaller or equal 4 bytes, the result is given back
        in one register. If the size is smaller or equal 8 bytes than we
        return the result in two registers. But if the size is bigger than
        8 bytes, we work with pointers.  */
      cif->flags = ffi_struct_type(cif->rtype);
      break;

    case FFI_TYPE_UINT64:
    case FFI_TYPE_SINT64:
      cif->flags = FFI_TYPE_UINT64;
      break;

    default:
      cif->flags = FFI_TYPE_INT;
      break;
    }

  /* Lucky us, because of the unique PA ABI we get to do our
     own stack sizing.  */
  switch (cif->abi)
    {
    case FFI_PA32:
      ffi_size_stack_pa32(cif);
      break;

    default:
      FFI_ASSERT(0);
      break;
    }

  return FFI_OK;
}

Here is the call graph for this function:

static void ffi_size_stack_pa32 ( ffi_cif *  cif) [static]

Definition at line 274 of file ffi.c.

{
  ffi_type **ptr;
  int i;
  int z = 0; /* # stack slots */

  for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
    {
      int type = (*ptr)->type;

      switch (type)
       {
       case FFI_TYPE_DOUBLE:
       case FFI_TYPE_UINT64:
       case FFI_TYPE_SINT64:
         z += 2 + (z & 1); /* must start on even regs, so we may waste one */
         break;

#ifdef PA_HPUX
       case FFI_TYPE_LONGDOUBLE:
#endif
       case FFI_TYPE_STRUCT:
         z += 1; /* pass by ptr, callee will copy */
         break;

       default: /* <= 32-bit values */
         z++;
       }
    }

  /* We can fit up to 6 args in the default 64-byte stack frame,
     if we need more, we need more stack.  */
  if (z <= 6)
    cif->bytes = MIN_STACK_SIZE; /* min stack size */
  else
    cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);

  debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
}

Here is the caller graph for this function:

static int ffi_struct_type ( ffi_type *  t) [inline, static]

Definition at line 50 of file ffi.c.

{
  size_t sz = t->size;

  /* Small structure results are passed in registers,
     larger ones are passed by pointer.  Note that
     small structures of size 2, 4 and 8 differ from
     the corresponding integer types in that they have
     different alignment requirements.  */

  if (sz <= 1)
    return FFI_TYPE_UINT8;
  else if (sz == 2)
    return FFI_TYPE_SMALL_STRUCT2;
  else if (sz == 3)
    return FFI_TYPE_SMALL_STRUCT3;
  else if (sz == 4)
    return FFI_TYPE_SMALL_STRUCT4;
  else if (sz == 5)
    return FFI_TYPE_SMALL_STRUCT5;
  else if (sz == 6)
    return FFI_TYPE_SMALL_STRUCT6;
  else if (sz == 7)
    return FFI_TYPE_SMALL_STRUCT7;
  else if (sz <= 8)
    return FFI_TYPE_SMALL_STRUCT8;
  else
    return FFI_TYPE_STRUCT; /* else, we pass it by pointer.  */
}

Here is the caller graph for this function: