diff options
author | jsturm <jsturm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-01-03 23:08:56 +0000 |
---|---|---|
committer | jsturm <jsturm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-01-03 23:08:56 +0000 |
commit | 0ef3e9c5d80295134b3c353c3a58cc64754d3ce5 (patch) | |
tree | 5d6ae28f882205c56e8f57b592354a04b05fc737 /libffi | |
parent | 51b29f53f1dbc51486c4ebcc48f2c49cc7a4a3cb (diff) | |
download | gcc-0ef3e9c5d80295134b3c353c3a58cc64754d3ce5.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@60857 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libffi')
-rw-r--r-- | libffi/ChangeLog | 8 | ||||
-rw-r--r-- | libffi/include/ffi.h.in | 14 | ||||
-rw-r--r-- | libffi/src/ffitest.c | 6 | ||||
-rw-r--r-- | libffi/src/sparc/ffi.c | 106 | ||||
-rw-r--r-- | libffi/src/sparc/v8.S | 91 | ||||
-rw-r--r-- | libffi/src/sparc/v9.S | 110 |
6 files changed, 327 insertions, 8 deletions
diff --git a/libffi/ChangeLog b/libffi/ChangeLog index 853784d3956..86907524263 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -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 diff --git a/libffi/include/ffi.h.in b/libffi/include/ffi.h.in index c660ede75af..bc15daace04 100644 --- a/libffi/include/ffi.h.in +++ b/libffi/include/ffi.h.in @@ -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 diff --git a/libffi/src/ffitest.c b/libffi/src/ffitest.c index da528317bb3..0dd7688dff5 100644 --- a/libffi/src/ffitest.c +++ b/libffi/src/ffitest.c @@ -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; diff --git a/libffi/src/sparc/ffi.c b/libffi/src/sparc/ffi.c index dc975356b4b..573fc84ee5a 100644 --- a/libffi/src/sparc/ffi.c +++ b/libffi/src/sparc/ffi.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 1996 Cygnus Solutions + ffi.c - Copyright (c) 1996, 2003 Cygnus Solutions Sparc Foreign Function Interface @@ -28,6 +28,12 @@ #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; +} diff --git a/libffi/src/sparc/v8.S b/libffi/src/sparc/v8.S index d94fe03d2aa..299200a089c 100644 --- a/libffi/src/sparc/v8.S +++ b/libffi/src/sparc/v8.S @@ -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: diff --git a/libffi/src/sparc/v9.S b/libffi/src/sparc/v9.S index bd358c0d84d..8dc9c90f661 100644 --- a/libffi/src/sparc/v9.S +++ b/libffi/src/sparc/v9.S @@ -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 |