OSDN Git Service

* include/ffi.h.in: Add closure defines for SPARC, SPARC64.
authorjsturm <jsturm@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 3 Jan 2003 23:08:56 +0000 (23:08 +0000)
committerjsturm <jsturm@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 3 Jan 2003 23:08:56 +0000 (23:08 +0000)
* src/ffitest.c (main): Use static storage for closure.
* src/sparc/ffi.c (ffi_prep_closure, ffi_closure_sparc_inner): New.
* src/sparc/v8.S (ffi_closure_v8): New.
* src/sparc/v9.S (ffi_closure_v9): New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@60857 138bc75d-0d04-0410-961f-82ee72b054a4

libffi/ChangeLog
libffi/include/ffi.h.in
libffi/src/ffitest.c
libffi/src/sparc/ffi.c
libffi/src/sparc/v8.S
libffi/src/sparc/v9.S

index 853784d..8690752 100644 (file)
@@ -1,3 +1,11 @@
+2003-01-03  Jeff Sturm  <jsturm@one-point.com>
+
+       * include/ffi.h.in: Add closure defines for SPARC, SPARC64.
+       * src/ffitest.c (main): Use static storage for closure.
+       * src/sparc/ffi.c (ffi_prep_closure, ffi_closure_sparc_inner): New.
+       * src/sparc/v8.S (ffi_closure_v8): New.
+       * src/sparc/v9.S (ffi_closure_v9): New.
+
 2002-11-10  Ranjit Mathew <rmathew@hotmail.com>
 
        * include/ffi.h.in: Added FFI_STDCALL ffi_type
index c660ede..bc15daa 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------*-C-*-
-   libffi @VERSION@ - Copyright (c) 1996-2002  Cygnus Solutions
+   libffi @VERSION@ - Copyright (c) 1996-2003  Cygnus Solutions
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
@@ -443,6 +443,18 @@ struct ffi_ia64_trampoline_struct {
 #define FFI_TRAMPOLINE_SIZE 24 /* see struct below */ 
 #define FFI_NATIVE_RAW_API 0
 
+#elif defined(SPARC64)
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 24
+#define FFI_NATIVE_RAW_API 0
+
+#elif defined(SPARC)
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 16
+#define FFI_NATIVE_RAW_API 0
+
 #elif defined(S390)
 
 #define FFI_CLOSURES 1
index da52831..0dd7688 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   ffitest.c - Copyright (c) 1996, 1997, 1998, 2002  Red Hat, Inc.
+   ffitest.c - Copyright (c) 1996, 1997, 1998, 2002, 2003  Red Hat, Inc.
 
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
@@ -1044,7 +1044,9 @@ int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
 # if FFI_CLOSURES
   /* A simple closure test */
     {
-      ffi_closure cl;
+      /* The closure must not be an automatic variable on
+        platforms (Solaris) that forbid stack execution by default. */
+      static ffi_closure cl;
       ffi_type * cl_arg_types[3];
 
       cl_arg_types[0] = &ffi_type_sint;
index dc97535..573fc84 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   ffi.c - Copyright (c) 1996 Cygnus Solutions
+   ffi.c - Copyright (c) 1996, 2003 Cygnus Solutions
    
    Sparc Foreign Function Interface 
 
 
 #include <stdlib.h>
 
+#ifdef SPARC64
+extern void ffi_closure_v9(void);
+#else
+extern void ffi_closure_v8(void);
+#endif
+
 /* ffi_prep_args is called by the assembly routine once stack space
    has been allocated for the function's arguments */
 
@@ -409,3 +415,101 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
     }
 
 }
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+                 ffi_cif* cif,
+                 void (*fun)(ffi_cif*, void*, void**, void*),
+                 void *user_data)
+{
+  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
+  unsigned long fn;
+  unsigned long ctx = (unsigned long) closure;
+
+#ifdef SPARC64
+  /* Trampoline address is equal to the closure address.  We take advantage
+     of that to reduce the trampoline size by 8 bytes. */
+  FFI_ASSERT (cif->abi == FFI_V9);
+  fn = (unsigned long) ffi_closure_v9;
+  tramp[0] = 0x83414000;       /* rd   %pc, %g1        */
+  tramp[1] = 0xca586010;       /* ldx  [%g1+16], %g5   */
+  tramp[2] = 0x81c14000;       /* jmp  %g5             */
+  tramp[3] = 0x01000000;       /* nop                  */
+  *((unsigned long *) &tramp[4]) = fn;
+#else
+  FFI_ASSERT (cif->abi == FFI_V8);
+  fn = (unsigned long) ffi_closure_v8;
+  tramp[0] = 0x03000000 | fn >> 10;    /* sethi %hi(fn), %g1   */
+  tramp[1] = 0x05000000 | ctx >> 10;   /* sethi %hi(ctx), %g2  */
+  tramp[2] = 0x81c06000 | (fn & 0x3ff);        /* jmp   %g1+%lo(fn)    */
+  tramp[3] = 0x8410a000 | (ctx & 0x3ff);/* or    %g2, %lo(ctx) */
+#endif
+
+  closure->cif = cif;
+  closure->fun = fun;
+  closure->user_data = user_data;
+
+  /* Flush the Icache.  FIXME: alignment isn't certain, assume 8 bytes */
+#ifdef SPARC64
+  asm volatile ("flush %0" : : "r" (closure) : "memory");
+  asm volatile ("flush %0" : : "r" (((char *) closure) + 8) : "memory");
+#else
+  asm volatile ("iflush        %0" : : "r" (closure) : "memory");
+  asm volatile ("iflush        %0" : : "r" (((char *) closure) + 8) : "memory");
+#endif
+
+  return FFI_OK;
+}
+
+int
+ffi_closure_sparc_inner(ffi_closure *closure,
+  void *rvalue, unsigned long *gpr, double *fpr)
+{
+  ffi_cif *cif;
+  void **avalue;
+  ffi_type **arg_types;
+  int i, avn, argn;
+
+  cif = closure->cif;
+  avalue = alloca(cif->nargs * sizeof(void *));
+
+  argn = 0;
+
+  /* Copy the caller's structure return address to that the closure
+     returns the data directly to the caller.  */
+  if (cif->flags == FFI_TYPE_STRUCT)
+    {
+      rvalue = (void *) gpr[0];
+      argn = 1;
+    }
+
+  i = 0;
+  avn = cif->nargs;
+  arg_types = cif->arg_types;
+  
+  /* Grab the addresses of the arguments from the stack frame.  */
+  while (i < avn)
+    {
+      /* Assume big-endian.  FIXME */
+      argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG;
+
+#ifdef SPARC64
+      if (i < 6 && (arg_types[i]->type == FFI_TYPE_FLOAT
+                || arg_types[i]->type == FFI_TYPE_DOUBLE
+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
+                || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
+#endif
+               ))
+        avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
+      else
+#endif
+        avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
+      i++;
+    }
+
+  /* Invoke the closure.  */
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  /* Tell ffi_closure_sparc how to perform return type promotions.  */
+  return cif->rtype->type;
+}
index d94fe03..299200a 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   v8.S - Copyright (c) 1996, 1997 Cygnus Solutions
+   v8.S - Copyright (c) 1996, 1997, 2003 Cygnus Solutions
    
    Sparc Foreign Function Interface 
 
@@ -94,6 +94,72 @@ longlong:
 .ffi_call_V8_end:
        .size   ffi_call_V8,.ffi_call_V8_end-ffi_call_V8
 
+
+#define        STACKFRAME      104     /* 16*4 register window +
+                                  1*4 struct return +  
+                                  6*4 args backing store +
+                                  3*4 locals */
+
+/* ffi_closure_v8(...)
+
+   Receives the closure argument in %g2.   */
+
+       .text
+       .align 8
+       .globl ffi_closure_v8
+
+ffi_closure_v8:
+       .register       %g2, #scratch
+.LLFB2:
+       save    %sp, -STACKFRAME, %sp
+.LLCFI1:
+
+       ! Store all of the potential argument registers in va_list format.
+       st      %i0, [%fp+68+0]
+       st      %i1, [%fp+68+4]
+       st      %i2, [%fp+68+8]
+       st      %i3, [%fp+68+12]
+       st      %i4, [%fp+68+16]
+       st      %i5, [%fp+68+20]
+
+       ! Call ffi_closure_sparc_inner to do the bulk of the work.
+       mov     %g2, %o0
+       add     %fp, -8, %o1
+       add     %fp,  68, %o2
+       call    ffi_closure_sparc_inner
+        mov    0, %o3
+
+       ! Load up the return value in the proper type.
+       cmp     %o0, FFI_TYPE_VOID
+       be      done1
+
+       cmp     %o0, FFI_TYPE_FLOAT
+       be,a    done1
+        ld     [%fp-8], %f0
+
+       cmp     %o0, FFI_TYPE_DOUBLE
+       be,a    done1
+        ldd    [%fp-8], %f0
+
+       cmp     %o0, FFI_TYPE_SINT64
+       be,a    integer
+        ld     [%fp-4], %i1
+
+       cmp     %o0, FFI_TYPE_UINT64
+       be,a    integer
+        ld     [%fp-4], %i1
+
+integer:
+       ld      [%fp-8], %i0
+
+done1:
+       ret
+        restore
+.LLFE2:
+
+.ffi_closure_v8_end:
+       .size   ffi_closure_v8,.ffi_closure_v8_end-ffi_closure_v8
+
 #ifdef SPARC64
 #define WS 8
 #define nword  xword
@@ -148,3 +214,26 @@ longlong:
        .byte   0x1f    ! uleb128 0x1f
        .align  WS
 .LLEFDE1:
+.LLSFDE2:
+       .uaword .LLEFDE2-.LLASFDE2      ! FDE Length
+.LLASFDE2:
+       .uaword .LLASFDE2-.LLframe1     ! FDE CIE offset
+#ifdef HAVE_AS_SPARC_UA_PCREL
+       .uaword %r_disp32(.LLFB2)
+       .uaword .LLFE2-.LLFB2   ! FDE address range
+#else
+       .align  WS
+       .nword  .LLFB2
+       .uanword .LLFE2-.LLFB2  ! FDE address range
+#endif
+       .byte   0x0     ! uleb128 0x0; Augmentation size
+       .byte   0x4     ! DW_CFA_advance_loc4
+       .uaword .LLCFI1-.LLFB2
+       .byte   0xd     ! DW_CFA_def_cfa_register
+       .byte   0x1e    ! uleb128 0x1e
+       .byte   0x2d    ! DW_CFA_GNU_window_save
+       .byte   0x9     ! DW_CFA_register
+       .byte   0xf     ! uleb128 0xf
+       .byte   0x1f    ! uleb128 0x1f
+       .align  WS
+.LLEFDE2:
index bd358c0..8dc9c90 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   v9.S - Copyright (c) 2000 Cygnus Solutions
+   v9.S - Copyright (c) 2000, 2003 Cygnus Solutions
    
    Sparc 64bit Foreign Function Interface 
 
@@ -99,7 +99,7 @@ _ffi_call_V9:
        cmp     %i3, FFI_TYPE_STRUCT
        be,pn   %icc, dostruct
 
-        cmp    %i3, FFI_TYPE_LONGDOUBLE
+       cmp     %i3, FFI_TYPE_LONGDOUBLE
        bne,pt  %icc, done
         nop
        std     %f0, [%i4+0]
@@ -125,6 +125,88 @@ dostruct:
 .ffi_call_V9_end:
        .size   ffi_call_V9,.ffi_call_V9_end-ffi_call_V9
 
+
+#define        STACKFRAME       240    /* 16*8 register window +
+                                  6*8 args backing store +
+                                  8*8 locals */
+#define        FP              %fp+STACK_BIAS
+
+/* ffi_closure_v9(...)
+
+   Receives the closure argument in %g1.   */
+
+       .text
+       .align 8
+       .globl ffi_closure_v9
+
+ffi_closure_v9:
+.LLFB2:
+       save    %sp, -STACKFRAME, %sp
+.LLCFI1:
+
+       ! Store all of the potential argument registers in va_list format.
+       stx     %i0, [FP+128+0]
+       stx     %i1, [FP+128+8]
+       stx     %i2, [FP+128+16]
+       stx     %i3, [FP+128+24]
+       stx     %i4, [FP+128+32]
+       stx     %i5, [FP+128+40]
+
+       ! Store possible floating point argument registers too.
+       std     %f0, [FP-48]
+       std     %f2, [FP-40]
+       std     %f4, [FP-32]
+       std     %f6, [FP-24]
+       std     %f8, [FP-16]
+       std     %f10, [FP-8]
+
+       ! Call ffi_closure_sparc_inner to do the bulk of the work.
+       mov     %g1, %o0
+       add     %fp, STACK_BIAS-64, %o1
+       add     %fp, STACK_BIAS+128, %o2
+       call    ffi_closure_sparc_inner
+        add    %fp, STACK_BIAS-48, %o3
+
+       ! Load up the return value in the proper type.
+       cmp     %o0, FFI_TYPE_VOID
+       be,pn   %icc, done1
+
+       cmp     %o0, FFI_TYPE_FLOAT
+       be,a,pn %icc, done1
+        ld     [FP-64], %f0
+
+       cmp     %o0, FFI_TYPE_DOUBLE
+       be,a,pn %icc, done1
+        ldd    [FP-64], %f0
+
+       cmp     %o0, FFI_TYPE_LONGDOUBLE
+       be,a,pn %icc, longdouble1
+        ldd    [FP-64], %f0
+
+       cmp     %o0, FFI_TYPE_STRUCT
+       be,pn   %icc, struct1
+
+       ! FFI_TYPE_UINT64 | FFI_TYPE_SINT64 | FFI_TYPE_POINTER
+       ldx     [FP-64], %i0
+
+done1:
+       ret
+        restore
+
+struct1:
+       ldx [FP-56], %i2
+       ret
+        restore
+
+longdouble1:
+       ldd     [FP-56], %f2
+       ret
+        restore
+.LLFE2:
+
+.ffi_closure_v9_end:
+       .size   ffi_closure_v9,.ffi_closure_v9_end-ffi_closure_v9
+
        .section        ".eh_frame",#alloc,#write
 .LLframe1:
        .uaword .LLECIE1-.LLSCIE1       ! Length of Common Information Entry
@@ -169,5 +251,27 @@ dostruct:
        .byte   0x1f    ! uleb128 0x1f
        .align 8
 .LLEFDE1:
-
+.LLSFDE2:
+       .uaword .LLEFDE2-.LLASFDE2      ! FDE Length
+.LLASFDE2:
+       .uaword .LLASFDE2-.LLframe1     ! FDE CIE offset
+#ifdef HAVE_AS_SPARC_UA_PCREL
+       .uaword %r_disp32(.LLFB2)
+       .uaword .LLFE2-.LLFB2           ! FDE address range
+#else
+       .align 8
+       .xword  .LLFB2
+       .uaxword        .LLFE2-.LLFB2   ! FDE address range
+#endif
+       .byte   0x0     ! uleb128 0x0; Augmentation size
+       .byte   0x4     ! DW_CFA_advance_loc4
+       .uaword .LLCFI1-.LLFB2
+       .byte   0xd     ! DW_CFA_def_cfa_register
+       .byte   0x1e    ! uleb128 0x1e
+       .byte   0x2d    ! DW_CFA_GNU_window_save
+       .byte   0x9     ! DW_CFA_register
+       .byte   0xf     ! uleb128 0xf
+       .byte   0x1f    ! uleb128 0x1f
+       .align 8
+.LLEFDE2:
 #endif