diff options
author | Moxie Bot <bot@moxielogic.com> | 2020-02-24 10:29:20 -0500 |
---|---|---|
committer | Moxie Bot <bot@moxielogic.com> | 2020-02-24 10:29:20 -0500 |
commit | 8eb2d2b05626b1cbbed100725bc440709499e8a6 (patch) | |
tree | b71e350bbc76ee09c0d4c269d1a19d4cb38abe92 /src/pa | |
parent | be815544c1588c6ca70120361c168b196376aa56 (diff) | |
download | libffi-8eb2d2b05626b1cbbed100725bc440709499e8a6.tar.gz |
Revamp PA_LINUX and PA_HPUX target closures to use function descriptors.
2020-02-23 John David Anglin <danglin@gcc.gnu.org>
* include/ffi.h.in (FFI_CLOSURE_PTR, FFI_RESTORE_PTR): Define.
* src/closures.c (ffi_closure_alloc): Convert closure pointer
return by malloc to function pointer.
(ffi_closure_free): Convert function pointer back to malloc pointer.
* src/pa/ffi.c (ffi_closure_inner_pa32): Use union to double word
align return address on stack. Adjust statements referencing return
address. Convert closure argument from function pointer to standard
closure pointer.
(ffi_prep_closure_loc): Likewise convert closure argument back to
closure pointer. Remove assembler trampolines. Setup simulated
function descriptor as on ia64.
src/pa/ffitarget.h (FFI_TRAMPOLINE_SIZE): Reduce to 12.
src/pa/hpux32.S (ffi_closure_pa32): Retrieve closure pointer and real
gp from fake gp value in register %r19.
src/pa/linux.S (ffi_closure_pa32): Likewise.
Diffstat (limited to 'src/pa')
-rw-r--r-- | src/pa/ffi.c | 137 | ||||
-rw-r--r-- | src/pa/ffitarget.h | 7 | ||||
-rw-r--r-- | src/pa/hpux32.S | 6 | ||||
-rw-r--r-- | src/pa/linux.S | 6 |
4 files changed, 55 insertions, 101 deletions
diff --git a/src/pa/ffi.c b/src/pa/ffi.c index 4ce2bc6..95e6694 100644 --- a/src/pa/ffi.c +++ b/src/pa/ffi.c @@ -421,12 +421,15 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) ffi_cif *cif; void **avalue; void *rvalue; - UINT32 ret[2]; /* function can return up to 64-bits in registers */ + /* Functions can return up to 64-bits in registers. Return address + must be double word aligned. */ + union { double rd; UINT32 ret[2]; } u; ffi_type **p_arg; char *tmp; int i, avn; unsigned int slot = FIRST_ARG_SLOT; register UINT32 r28 asm("r28"); + ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure); cif = closure->cif; @@ -434,7 +437,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) if (cif->flags == FFI_TYPE_STRUCT) rvalue = (void *)r28; else - rvalue = &ret[0]; + rvalue = &u; avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG); avn = cif->nargs; @@ -529,35 +532,35 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) } /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avalue, closure->user_data); + (c->fun) (cif, rvalue, avalue, c->user_data); - debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0], - ret[1]); + debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", u.ret[0], + u.ret[1]); /* Store the result using the lower 2 bytes of the flags. */ switch (cif->flags) { case FFI_TYPE_UINT8: - *(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24); + *(stack - FIRST_ARG_SLOT) = (UINT8)(u.ret[0] >> 24); break; case FFI_TYPE_SINT8: - *(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24); + *(stack - FIRST_ARG_SLOT) = (SINT8)(u.ret[0] >> 24); break; case FFI_TYPE_UINT16: - *(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16); + *(stack - FIRST_ARG_SLOT) = (UINT16)(u.ret[0] >> 16); break; case FFI_TYPE_SINT16: - *(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16); + *(stack - FIRST_ARG_SLOT) = (SINT16)(u.ret[0] >> 16); break; case FFI_TYPE_INT: case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: - *(stack - FIRST_ARG_SLOT) = ret[0]; + *(stack - FIRST_ARG_SLOT) = u.ret[0]; break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: - *(stack - FIRST_ARG_SLOT) = ret[0]; - *(stack - FIRST_ARG_SLOT - 1) = ret[1]; + *(stack - FIRST_ARG_SLOT) = u.ret[0]; + *(stack - FIRST_ARG_SLOT - 1) = u.ret[1]; break; case FFI_TYPE_DOUBLE: @@ -577,7 +580,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) case FFI_TYPE_SMALL_STRUCT4: tmp = (void*)(stack - FIRST_ARG_SLOT); tmp += 4 - cif->rtype->size; - memcpy((void*)tmp, &ret[0], cif->rtype->size); + memcpy((void*)tmp, &u, cif->rtype->size); break; case FFI_TYPE_SMALL_STRUCT5: @@ -598,7 +601,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) } memset (ret2, 0, sizeof (ret2)); - memcpy ((char *)ret2 + off, ret, 8 - off); + memcpy ((char *)ret2 + off, &u, 8 - off); *(stack - FIRST_ARG_SLOT) = ret2[0]; *(stack - FIRST_ARG_SLOT - 1) = ret2[1]; @@ -630,89 +633,41 @@ ffi_prep_closure_loc (ffi_closure* closure, void *user_data, void *codeloc) { - UINT32 *tramp = (UINT32 *)(closure->tramp); -#ifdef PA_HPUX - UINT32 *tmp; -#endif + ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure); + + /* The layout of a function descriptor. A function pointer with the PLABEL + bit set points to a function descriptor. */ + struct pa32_fd + { + UINT32 code_pointer; + UINT32 gp; + }; + + struct ffi_pa32_trampoline_struct + { + UINT32 code_pointer; /* Pointer to ffi_closure_unix. */ + UINT32 fake_gp; /* Pointer to closure, installed as gp. */ + UINT32 real_gp; /* Real gp value. */ + }; + + struct ffi_pa32_trampoline_struct *tramp; + struct pa32_fd *fd; if (cif->abi != FFI_PA32) return FFI_BAD_ABI; - /* Make a small trampoline that will branch to our - handler function. Use PC-relative addressing. */ - -#ifdef PA_LINUX - tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */ - tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */ - tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */ - tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */ - tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */ - tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */ - tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */ - tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2); - - /* Flush d/icache -- have to flush up 2 two lines because of - alignment. */ - __asm__ volatile( - "fdc 0(%0)\n\t" - "fdc %1(%0)\n\t" - "fic 0(%%sr4, %0)\n\t" - "fic %1(%%sr4, %0)\n\t" - "sync\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n" - : - : "r"((unsigned long)tramp & ~31), - "r"(32 /* stride */) - : "memory"); -#endif + /* Get function descriptor address for ffi_closure_pa32. */ + fd = (struct pa32_fd *)((UINT32)ffi_closure_pa32 & ~3); -#ifdef PA_HPUX - tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */ - tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */ - tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */ - tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */ - tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */ - tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */ - tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */ - tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */ - tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */ - tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2); - - /* Flush d/icache -- have to flush three lines because of alignment. */ - __asm__ volatile( - "copy %1,%0\n\t" - "fdc,m %2(%0)\n\t" - "fdc,m %2(%0)\n\t" - "fdc,m %2(%0)\n\t" - "ldsid (%1),%0\n\t" - "mtsp %0,%%sr0\n\t" - "copy %1,%0\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "sync\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n" - : "=&r" ((unsigned long)tmp) - : "r" ((unsigned long)tramp & ~31), - "r" (32/* stride */) - : "memory"); -#endif + /* Setup trampoline. */ + tramp = (struct ffi_pa32_trampoline_struct *)c->tramp; + tramp->code_pointer = fd->code_pointer; + tramp->fake_gp = (UINT32)codeloc & ~3; + tramp->real_gp = fd->gp; - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; + c->cif = cif; + c->user_data = user_data; + c->fun = fun; return FFI_OK; } diff --git a/src/pa/ffitarget.h b/src/pa/ffitarget.h index fff4c6b..df1209e 100644 --- a/src/pa/ffitarget.h +++ b/src/pa/ffitarget.h @@ -68,12 +68,7 @@ typedef enum ffi_abi { #define FFI_CLOSURES 1 #define FFI_NATIVE_RAW_API 0 - -#ifdef PA_LINUX -#define FFI_TRAMPOLINE_SIZE 32 -#else -#define FFI_TRAMPOLINE_SIZE 40 -#endif +#define FFI_TRAMPOLINE_SIZE 12 #define FFI_TYPE_SMALL_STRUCT2 -1 #define FFI_TYPE_SMALL_STRUCT3 -2 diff --git a/src/pa/hpux32.S b/src/pa/hpux32.S index 40528ba..d0e5f69 100644 --- a/src/pa/hpux32.S +++ b/src/pa/hpux32.S @@ -259,7 +259,7 @@ L$done L$FE1 /* void ffi_closure_pa32(void); - Called with closure argument in %r21 */ + Called with closure argument in %r19 */ .SPACE $TEXT$ .SUBSPA $CODE$ @@ -285,7 +285,9 @@ L$CFI22 stw %arg2, -44(%r3) stw %arg3, -48(%r3) - copy %r21, %arg0 + /* Retrieve closure pointer and real gp. */ + copy %r19, %arg0 + ldw 8(%r19), %r19 bl ffi_closure_inner_pa32, %r2 copy %r3, %arg1 ldwm -64(%sp), %r3 diff --git a/src/pa/linux.S b/src/pa/linux.S index ab04c75..33ef0b1 100644 --- a/src/pa/linux.S +++ b/src/pa/linux.S @@ -252,7 +252,7 @@ ffi_call_pa32: .LFE1: /* void ffi_closure_pa32(void); - Called with closure argument in %r21 */ + Called with closure argument in %r19 */ .export ffi_closure_pa32,code .import ffi_closure_inner_pa32,code @@ -277,7 +277,9 @@ ffi_closure_pa32: stw %arg2, -44(%r3) stw %arg3, -48(%r3) - copy %r21, %arg0 + /* Retrieve closure pointer and real gp. */ + copy %r19, %arg0 + ldw 8(%r19), %r19 bl ffi_closure_inner_pa32, %r2 copy %r3, %arg1 |