summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoxie Bot <bot@moxielogic.com>2020-02-24 10:29:20 -0500
committerMoxie Bot <bot@moxielogic.com>2020-02-24 10:29:20 -0500
commit8eb2d2b05626b1cbbed100725bc440709499e8a6 (patch)
treeb71e350bbc76ee09c0d4c269d1a19d4cb38abe92
parentbe815544c1588c6ca70120361c168b196376aa56 (diff)
downloadlibffi-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.
-rw-r--r--include/ffi.h.in8
-rw-r--r--src/closures.c8
-rw-r--r--src/pa/ffi.c137
-rw-r--r--src/pa/ffitarget.h7
-rw-r--r--src/pa/hpux32.S6
-rw-r--r--src/pa/linux.S6
6 files changed, 67 insertions, 105 deletions
diff --git a/include/ffi.h.in b/include/ffi.h.in
index 71cc05c..38885b0 100644
--- a/include/ffi.h.in
+++ b/include/ffi.h.in
@@ -330,6 +330,14 @@ typedef struct {
FFI_API void *ffi_closure_alloc (size_t size, void **code);
FFI_API void ffi_closure_free (void *);
+#if defined(PA_LINUX) || defined(PA_HPUX)
+#define FFI_CLOSURE_PTR(X) ((void *)((unsigned int)(X) | 2))
+#define FFI_RESTORE_PTR(X) ((void *)((unsigned int)(X) & ~3))
+#else
+#define FFI_CLOSURE_PTR(X) (X)
+#define FFI_RESTORE_PTR(X) (X)
+#endif
+
FFI_API ffi_status
ffi_prep_closure (ffi_closure*,
ffi_cif *,
diff --git a/src/closures.c b/src/closures.c
index 5120021..047abcd 100644
--- a/src/closures.c
+++ b/src/closures.c
@@ -921,7 +921,7 @@ ffi_closure_alloc (size_t size, void **code)
if (!code)
return NULL;
- ptr = dlmalloc (size);
+ ptr = FFI_CLOSURE_PTR (dlmalloc (size));
if (ptr)
{
@@ -961,7 +961,7 @@ ffi_closure_free (void *ptr)
ptr = sub_segment_exec_offset (ptr, seg);
#endif
- dlfree (ptr);
+ dlfree (FFI_RESTORE_PTR (ptr));
}
# else /* ! FFI_MMAP_EXEC_WRIT */
@@ -977,13 +977,13 @@ ffi_closure_alloc (size_t size, void **code)
if (!code)
return NULL;
- return *code = malloc (size);
+ return *code = FFI_CLOSURE_PTR (malloc (size));
}
void
ffi_closure_free (void *ptr)
{
- free (ptr);
+ free (FFI_RESTORE_PTR (ptr));
}
void *
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