Merge a newer version of libffi_osx, based on the
version of libffi in OSX 10.6.1. This fixes issue6918
This commit is contained in:
parent
9f20d9d0ee
commit
16766d7cd6
|
@ -1,7 +1,7 @@
|
||||||
#if defined(__ppc__) || defined(__ppc64__)
|
#if defined(__ppc__) || defined(__ppc64__)
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------
|
/* -----------------------------------------------------------------------
|
||||||
darwin.S - Copyright (c) 2000 John Hornkvist
|
ppc-darwin.S - Copyright (c) 2000 John Hornkvist
|
||||||
Copyright (c) 2004 Free Software Foundation, Inc.
|
Copyright (c) 2004 Free Software Foundation, Inc.
|
||||||
|
|
||||||
PowerPC Assembly glue.
|
PowerPC Assembly glue.
|
||||||
|
@ -294,7 +294,7 @@ LSCIE1:
|
||||||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||||
.byte 0x41 ; CIE RA Column
|
.byte 0x41 ; CIE RA Column
|
||||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||||
.byte 0x90 ; FDE Encoding (indirect pcrel)
|
.byte 0x10 ; FDE Encoding (pcrel)
|
||||||
.byte 0xc ; DW_CFA_def_cfa
|
.byte 0xc ; DW_CFA_def_cfa
|
||||||
.byte 0x1 ; uleb128 0x1
|
.byte 0x1 ; uleb128 0x1
|
||||||
.byte 0x0 ; uleb128 0x0
|
.byte 0x0 ; uleb128 0x0
|
||||||
|
@ -308,7 +308,7 @@ LSFDE1:
|
||||||
|
|
||||||
LASFDE1:
|
LASFDE1:
|
||||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||||
.g_long LLFB0$non_lazy_ptr-. ; FDE initial location
|
.g_long LFB0-. ; FDE initial location
|
||||||
.set L$set$3,LFE1-LFB0
|
.set L$set$3,LFE1-LFB0
|
||||||
.g_long L$set$3 ; FDE address range
|
.g_long L$set$3 ; FDE address range
|
||||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||||
|
@ -338,10 +338,6 @@ LASFDE1:
|
||||||
.byte 0x1c ; uleb128 0x1c
|
.byte 0x1c ; uleb128 0x1c
|
||||||
.align LOG2_GPR_BYTES
|
.align LOG2_GPR_BYTES
|
||||||
LEFDE1:
|
LEFDE1:
|
||||||
.data
|
|
||||||
.align LOG2_GPR_BYTES
|
|
||||||
LLFB0$non_lazy_ptr:
|
|
||||||
.g_long LFB0
|
|
||||||
|
|
||||||
#if defined(__ppc64__)
|
#if defined(__ppc64__)
|
||||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
OTHER DEALINGS IN THE SOFTWARE.
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
----------------------------------------------------------------------- */
|
----------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
#define L(x) x
|
#define L(x) x
|
||||||
|
|
||||||
#define SF_ARG9 MODE_CHOICE(56,112)
|
#define SF_ARG9 MODE_CHOICE(56,112)
|
||||||
|
@ -57,7 +56,6 @@
|
||||||
((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\
|
((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\
|
||||||
(x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT)
|
(x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT)
|
||||||
|
|
||||||
|
|
||||||
#if !defined(LIBFFI_ASM)
|
#if !defined(LIBFFI_ASM)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -75,20 +73,6 @@ enum {
|
||||||
FLAG_RETVAL_REFERENCE = 1 << (31 - 4)
|
FLAG_RETVAL_REFERENCE = 1 << (31 - 4)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void ffi_prep_args(extended_cif* inEcif, unsigned *const stack);
|
|
||||||
|
|
||||||
typedef union
|
|
||||||
{
|
|
||||||
float f;
|
|
||||||
double d;
|
|
||||||
} ffi_dblfl;
|
|
||||||
|
|
||||||
int ffi_closure_helper_DARWIN( ffi_closure* closure,
|
|
||||||
void* rvalue, unsigned long* pgr,
|
|
||||||
ffi_dblfl* pfr);
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__ppc64__)
|
#if defined(__ppc64__)
|
||||||
void ffi64_struct_to_ram_form(const ffi_type*, const char*, unsigned int*,
|
void ffi64_struct_to_ram_form(const ffi_type*, const char*, unsigned int*,
|
||||||
const char*, unsigned int*, unsigned int*, char*, unsigned int*);
|
const char*, unsigned int*, unsigned int*, char*, unsigned int*);
|
||||||
|
@ -96,11 +80,6 @@ void ffi64_struct_to_reg_form(const ffi_type*, const char*, unsigned int*,
|
||||||
unsigned int*, char*, unsigned int*, char*, unsigned int*);
|
unsigned int*, char*, unsigned int*, char*, unsigned int*);
|
||||||
bool ffi64_stret_needs_ptr(const ffi_type* inType,
|
bool ffi64_stret_needs_ptr(const ffi_type* inType,
|
||||||
unsigned short*, unsigned short*);
|
unsigned short*, unsigned short*);
|
||||||
bool ffi64_struct_contains_fp(const ffi_type* inType);
|
|
||||||
unsigned int ffi64_data_size(const ffi_type* inType);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // !defined(LIBFFI_ASM)
|
#endif // !defined(LIBFFI_ASM)
|
|
@ -1,7 +1,7 @@
|
||||||
#if defined(__ppc__)
|
#if defined(__ppc__)
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------
|
/* -----------------------------------------------------------------------
|
||||||
darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
||||||
Inc. based on ppc_closure.S
|
Inc. based on ppc_closure.S
|
||||||
|
|
||||||
PowerPC Assembly glue.
|
PowerPC Assembly glue.
|
||||||
|
@ -43,8 +43,8 @@
|
||||||
|
|
||||||
_ffi_closure_ASM:
|
_ffi_closure_ASM:
|
||||||
LFB1:
|
LFB1:
|
||||||
mflr r0 /* extract return address */
|
mflr r0 // Save return address
|
||||||
stg r0,MODE_CHOICE(8,16)(r1) /* save return address */
|
stg r0,SF_RETURN(r1)
|
||||||
|
|
||||||
LCFI0:
|
LCFI0:
|
||||||
/* 24/48 bytes (Linkage Area)
|
/* 24/48 bytes (Linkage Area)
|
||||||
|
@ -54,7 +54,7 @@ LCFI0:
|
||||||
176/232 total bytes */
|
176/232 total bytes */
|
||||||
|
|
||||||
/* skip over caller save area and keep stack aligned to 16/32. */
|
/* skip over caller save area and keep stack aligned to 16/32. */
|
||||||
stgu r1,-SF_ROUND(MODE_CHOICE(176,248))(r1)
|
stgu r1,-SF_ROUND(176)(r1)
|
||||||
|
|
||||||
LCFI1:
|
LCFI1:
|
||||||
/* We want to build up an area for the parameters passed
|
/* We want to build up an area for the parameters passed
|
||||||
|
@ -67,58 +67,44 @@ LCFI1:
|
||||||
|
|
||||||
/* Save GPRs 3 - 10 (aligned to 4/8)
|
/* Save GPRs 3 - 10 (aligned to 4/8)
|
||||||
in the parents outgoing area. */
|
in the parents outgoing area. */
|
||||||
stg r3,MODE_CHOICE(200,304)(r1)
|
stg r3,200(r1)
|
||||||
stg r4,MODE_CHOICE(204,312)(r1)
|
stg r4,204(r1)
|
||||||
stg r5,MODE_CHOICE(208,320)(r1)
|
stg r5,208(r1)
|
||||||
stg r6,MODE_CHOICE(212,328)(r1)
|
stg r6,212(r1)
|
||||||
stg r7,MODE_CHOICE(216,336)(r1)
|
stg r7,216(r1)
|
||||||
stg r8,MODE_CHOICE(220,344)(r1)
|
stg r8,220(r1)
|
||||||
stg r9,MODE_CHOICE(224,352)(r1)
|
stg r9,224(r1)
|
||||||
stg r10,MODE_CHOICE(228,360)(r1)
|
stg r10,228(r1)
|
||||||
|
|
||||||
/* Save FPRs 1 - 13. (aligned to 8) */
|
/* Save FPRs 1 - 13. (aligned to 8) */
|
||||||
stfd f1,MODE_CHOICE(56,112)(r1)
|
stfd f1,56(r1)
|
||||||
stfd f2,MODE_CHOICE(64,120)(r1)
|
stfd f2,64(r1)
|
||||||
stfd f3,MODE_CHOICE(72,128)(r1)
|
stfd f3,72(r1)
|
||||||
stfd f4,MODE_CHOICE(80,136)(r1)
|
stfd f4,80(r1)
|
||||||
stfd f5,MODE_CHOICE(88,144)(r1)
|
stfd f5,88(r1)
|
||||||
stfd f6,MODE_CHOICE(96,152)(r1)
|
stfd f6,96(r1)
|
||||||
stfd f7,MODE_CHOICE(104,160)(r1)
|
stfd f7,104(r1)
|
||||||
stfd f8,MODE_CHOICE(112,168)(r1)
|
stfd f8,112(r1)
|
||||||
stfd f9,MODE_CHOICE(120,176)(r1)
|
stfd f9,120(r1)
|
||||||
stfd f10,MODE_CHOICE(128,184)(r1)
|
stfd f10,128(r1)
|
||||||
stfd f11,MODE_CHOICE(136,192)(r1)
|
stfd f11,136(r1)
|
||||||
stfd f12,MODE_CHOICE(144,200)(r1)
|
stfd f12,144(r1)
|
||||||
stfd f13,MODE_CHOICE(152,208)(r1)
|
stfd f13,152(r1)
|
||||||
|
|
||||||
/* Set up registers for the routine that actually does the work.
|
// Set up registers for the routine that actually does the work.
|
||||||
Get the context pointer from the trampoline. */
|
mr r3,r11 // context pointer from the trampoline
|
||||||
mr r3,r11
|
addi r4,r1,160 // result storage
|
||||||
|
addi r5,r1,200 // saved GPRs
|
||||||
/* Load the pointer to the result storage. */
|
addi r6,r1,56 // saved FPRs
|
||||||
/* current stack frame size - ((4/8 * 4) + saved registers) */
|
|
||||||
addi r4,r1,MODE_CHOICE(160,216)
|
|
||||||
|
|
||||||
/* Load the pointer to the saved gpr registers. */
|
|
||||||
addi r5,r1,MODE_CHOICE(200,304)
|
|
||||||
|
|
||||||
/* Load the pointer to the saved fpr registers. */
|
|
||||||
addi r6,r1,MODE_CHOICE(56,112)
|
|
||||||
|
|
||||||
/* Make the call. */
|
|
||||||
bl Lffi_closure_helper_DARWIN$stub
|
bl Lffi_closure_helper_DARWIN$stub
|
||||||
|
|
||||||
/* Now r3 contains the return type
|
/* Now r3 contains the return type. Use it to look up in a table
|
||||||
so use it to look up in a table
|
|
||||||
so we know how to deal with each type. */
|
so we know how to deal with each type. */
|
||||||
|
addi r5,r1,160 // Copy result storage pointer.
|
||||||
/* Look the proper starting point in table
|
bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
|
||||||
by using return type as offset. */
|
mflr r4 // Move to r4.
|
||||||
addi r5,r1,MODE_CHOICE(160,216) // Get pointer to results area.
|
slwi r3,r3,4 // Multiply return type by 16.
|
||||||
bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
|
add r3,r3,r4 // Add contents of table to table address.
|
||||||
mflr r4 // Move to r4.
|
|
||||||
slwi r3,r3,4 // Now multiply return type by 16.
|
|
||||||
add r3,r3,r4 // Add contents of table to table address.
|
|
||||||
mtctr r3
|
mtctr r3
|
||||||
bctr
|
bctr
|
||||||
|
|
||||||
|
@ -143,7 +129,7 @@ Lret_type0:
|
||||||
|
|
||||||
/* case FFI_TYPE_INT */
|
/* case FFI_TYPE_INT */
|
||||||
Lret_type1:
|
Lret_type1:
|
||||||
lwz r3,MODE_CHOICE(0,4)(r5)
|
lwz r3,0(r5)
|
||||||
b Lfinish
|
b Lfinish
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
|
@ -171,42 +157,42 @@ Lret_type4:
|
||||||
|
|
||||||
/* case FFI_TYPE_UINT8 */
|
/* case FFI_TYPE_UINT8 */
|
||||||
Lret_type5:
|
Lret_type5:
|
||||||
lbz r3,MODE_CHOICE(3,7)(r5)
|
lbz r3,3(r5)
|
||||||
b Lfinish
|
b Lfinish
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
|
|
||||||
/* case FFI_TYPE_SINT8 */
|
/* case FFI_TYPE_SINT8 */
|
||||||
Lret_type6:
|
Lret_type6:
|
||||||
lbz r3,MODE_CHOICE(3,7)(r5)
|
lbz r3,3(r5)
|
||||||
extsb r3,r3
|
extsb r3,r3
|
||||||
b Lfinish
|
b Lfinish
|
||||||
nop
|
nop
|
||||||
|
|
||||||
/* case FFI_TYPE_UINT16 */
|
/* case FFI_TYPE_UINT16 */
|
||||||
Lret_type7:
|
Lret_type7:
|
||||||
lhz r3,MODE_CHOICE(2,6)(r5)
|
lhz r3,2(r5)
|
||||||
b Lfinish
|
b Lfinish
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
|
|
||||||
/* case FFI_TYPE_SINT16 */
|
/* case FFI_TYPE_SINT16 */
|
||||||
Lret_type8:
|
Lret_type8:
|
||||||
lha r3,MODE_CHOICE(2,6)(r5)
|
lha r3,2(r5)
|
||||||
b Lfinish
|
b Lfinish
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
|
|
||||||
/* case FFI_TYPE_UINT32 */
|
/* case FFI_TYPE_UINT32 */
|
||||||
Lret_type9: // same as Lret_type1
|
Lret_type9: // same as Lret_type1
|
||||||
lwz r3,MODE_CHOICE(0,4)(r5)
|
lwz r3,0(r5)
|
||||||
b Lfinish
|
b Lfinish
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
|
|
||||||
/* case FFI_TYPE_SINT32 */
|
/* case FFI_TYPE_SINT32 */
|
||||||
Lret_type10: // same as Lret_type1
|
Lret_type10: // same as Lret_type1
|
||||||
lwz r3,MODE_CHOICE(0,4)(r5)
|
lwz r3,0(r5)
|
||||||
b Lfinish
|
b Lfinish
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
|
@ -227,7 +213,7 @@ Lret_type12: // same as Lret_type11
|
||||||
|
|
||||||
/* case FFI_TYPE_STRUCT */
|
/* case FFI_TYPE_STRUCT */
|
||||||
Lret_type13:
|
Lret_type13:
|
||||||
b MODE_CHOICE(Lfinish,Lret_struct)
|
b Lfinish
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
|
@ -239,12 +225,13 @@ Lret_type13:
|
||||||
// padded to 16 bytes.
|
// padded to 16 bytes.
|
||||||
Lret_type14:
|
Lret_type14:
|
||||||
lg r3,0(r5)
|
lg r3,0(r5)
|
||||||
|
// fall through
|
||||||
|
|
||||||
/* case done */
|
/* case done */
|
||||||
Lfinish:
|
Lfinish:
|
||||||
addi r1,r1,SF_ROUND(MODE_CHOICE(176,248)) // Restore stack pointer.
|
addi r1,r1,SF_ROUND(176) // Restore stack pointer.
|
||||||
lg r0,MODE_CHOICE(8,16)(r1) /* Get return address. */
|
lg r0,SF_RETURN(r1) // Restore return address.
|
||||||
mtlr r0 /* Reset link register. */
|
mtlr r0 // Restore link register.
|
||||||
blr
|
blr
|
||||||
|
|
||||||
/* END(ffi_closure_ASM) */
|
/* END(ffi_closure_ASM) */
|
||||||
|
@ -261,7 +248,7 @@ LSCIE1:
|
||||||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||||
.byte 0x41 ; CIE RA Column
|
.byte 0x41 ; CIE RA Column
|
||||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||||
.byte 0x90 ; FDE Encoding (indirect pcrel)
|
.byte 0x10 ; FDE Encoding (pcrel)
|
||||||
.byte 0xc ; DW_CFA_def_cfa
|
.byte 0xc ; DW_CFA_def_cfa
|
||||||
.byte 0x1 ; uleb128 0x1
|
.byte 0x1 ; uleb128 0x1
|
||||||
.byte 0x0 ; uleb128 0x0
|
.byte 0x0 ; uleb128 0x0
|
||||||
|
@ -275,7 +262,7 @@ LSFDE1:
|
||||||
|
|
||||||
LASFDE1:
|
LASFDE1:
|
||||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||||
.g_long LLFB1$non_lazy_ptr-. ; FDE initial location
|
.g_long LFB1-. ; FDE initial location
|
||||||
.set L$set$3,LFE1-LFB1
|
.set L$set$3,LFE1-LFB1
|
||||||
.g_long L$set$3 ; FDE address range
|
.g_long L$set$3 ; FDE address range
|
||||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||||
|
@ -317,9 +304,5 @@ L_ffi_closure_helper_DARWIN$lazy_ptr:
|
||||||
.indirect_symbol _ffi_closure_helper_DARWIN
|
.indirect_symbol _ffi_closure_helper_DARWIN
|
||||||
.g_long dyld_stub_binding_helper
|
.g_long dyld_stub_binding_helper
|
||||||
|
|
||||||
.data
|
|
||||||
.align LOG2_GPR_BYTES
|
|
||||||
LLFB1$non_lazy_ptr:
|
|
||||||
.g_long LFB1
|
|
||||||
|
|
||||||
#endif // __ppc__
|
#endif // __ppc__
|
||||||
|
|
|
@ -28,13 +28,13 @@
|
||||||
OTHER DEALINGS IN THE SOFTWARE.
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
----------------------------------------------------------------------- */
|
----------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include "ffi.h"
|
#include <ffi.h>
|
||||||
#include "ffi_common.h"
|
#include <ffi_common.h>
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "ppc-darwin.h"
|
#include <ppc-darwin.h>
|
||||||
#include <architecture/ppc/mode_independent_asm.h>
|
#include <architecture/ppc/mode_independent_asm.h>
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -42,17 +42,14 @@
|
||||||
#include <libkern/OSCacheControl.h> // for sys_icache_invalidate()
|
#include <libkern/OSCacheControl.h> // for sys_icache_invalidate()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* Explicit prototype instead of including a header to allow compilation
|
|
||||||
* on Tiger systems.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma weak sys_icache_invalidate
|
#pragma weak sys_icache_invalidate
|
||||||
extern void sys_icache_invalidate(void *start, size_t len);
|
extern void sys_icache_invalidate(void *start, size_t len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
extern void ffi_closure_ASM(void);
|
extern void ffi_closure_ASM(void);
|
||||||
|
|
||||||
// The layout of a function descriptor. A C function pointer really
|
// The layout of a function descriptor. A C function pointer really
|
||||||
|
@ -760,9 +757,7 @@ ffi_prep_closure(
|
||||||
|
|
||||||
// Flush the icache. Only necessary on Darwin.
|
// Flush the icache. Only necessary on Darwin.
|
||||||
#if defined(POWERPC_DARWIN)
|
#if defined(POWERPC_DARWIN)
|
||||||
if (sys_icache_invalidate) {
|
sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE);
|
||||||
sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE);
|
flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE);
|
||||||
#endif
|
#endif
|
||||||
|
@ -804,6 +799,12 @@ ffi_prep_closure(
|
||||||
} ldu;
|
} ldu;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
float f;
|
||||||
|
double d;
|
||||||
|
} ffi_dblfl;
|
||||||
|
|
||||||
/* The trampoline invokes ffi_closure_ASM, and on entry, r11 holds the
|
/* The trampoline invokes ffi_closure_ASM, and on entry, r11 holds the
|
||||||
address of the closure. After storing the registers that could possibly
|
address of the closure. After storing the registers that could possibly
|
||||||
contain parameters to be passed into the stack frame and setting up space
|
contain parameters to be passed into the stack frame and setting up space
|
||||||
|
@ -829,7 +830,7 @@ ffi_closure_helper_DARWIN(
|
||||||
unsigned int nf = 0; /* number of FPRs already used. */
|
unsigned int nf = 0; /* number of FPRs already used. */
|
||||||
unsigned int ng = 0; /* number of GPRs already used. */
|
unsigned int ng = 0; /* number of GPRs already used. */
|
||||||
ffi_cif* cif = closure->cif;
|
ffi_cif* cif = closure->cif;
|
||||||
unsigned int avn = cif->nargs;
|
long avn = cif->nargs;
|
||||||
void** avalue = alloca(cif->nargs * sizeof(void*));
|
void** avalue = alloca(cif->nargs * sizeof(void*));
|
||||||
ffi_type** arg_types = cif->arg_types;
|
ffi_type** arg_types = cif->arg_types;
|
||||||
|
|
||||||
|
@ -906,9 +907,9 @@ ffi_closure_helper_DARWIN(
|
||||||
size_al = ALIGN(arg_types[i]->size, 8);
|
size_al = ALIGN(arg_types[i]->size, 8);
|
||||||
|
|
||||||
if (size_al < 3)
|
if (size_al < 3)
|
||||||
avalue[i] = (char*)pgr + MODE_CHOICE(4,8) - size_al;
|
avalue[i] = (void*)pgr + MODE_CHOICE(4,8) - size_al;
|
||||||
else
|
else
|
||||||
avalue[i] = (char*)pgr;
|
avalue[i] = (void*)pgr;
|
||||||
|
|
||||||
ng += (size_al + 3) / sizeof(long);
|
ng += (size_al + 3) / sizeof(long);
|
||||||
pgr += (size_al + 3) / sizeof(long);
|
pgr += (size_al + 3) / sizeof(long);
|
||||||
|
@ -988,8 +989,8 @@ ffi_closure_helper_DARWIN(
|
||||||
We use a union to pass the long double to avalue[i]. */
|
We use a union to pass the long double to avalue[i]. */
|
||||||
else if (nf == NUM_FPR_ARG_REGISTERS - 1)
|
else if (nf == NUM_FPR_ARG_REGISTERS - 1)
|
||||||
{
|
{
|
||||||
memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
|
memcpy (&temp_ld.lb[0], pfr, sizeof(temp_ld.lb[0]));
|
||||||
memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
|
memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1]));
|
||||||
avalue[i] = &temp_ld.ld;
|
avalue[i] = &temp_ld.ld;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#if defined(__ppc64__)
|
#if defined(__ppc64__)
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------
|
/* -----------------------------------------------------------------------
|
||||||
darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
||||||
Inc. based on ppc_closure.S
|
Inc. based on ppc_closure.S
|
||||||
|
|
||||||
PowerPC Assembly glue.
|
PowerPC Assembly glue.
|
||||||
|
@ -297,8 +297,8 @@ Lret_struct:
|
||||||
|
|
||||||
// case done
|
// case done
|
||||||
Lfinish:
|
Lfinish:
|
||||||
lg r1,0(r1) // Restore stack pointer.
|
lg r1,0(r1) // Restore stack pointer.
|
||||||
ld r31,-8(r1) // Restore registers we used.
|
ld r31,-8(r1) // Restore registers we used.
|
||||||
ld r30,-16(r1)
|
ld r30,-16(r1)
|
||||||
lg r0,SF_RETURN(r1) // Get return address.
|
lg r0,SF_RETURN(r1) // Get return address.
|
||||||
mtlr r0 // Reset link register.
|
mtlr r0 // Reset link register.
|
||||||
|
@ -318,7 +318,7 @@ LSCIE1:
|
||||||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||||
.byte 0x41 ; CIE RA Column
|
.byte 0x41 ; CIE RA Column
|
||||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||||
.byte 0x90 ; FDE Encoding (indirect pcrel)
|
.byte 0x10 ; FDE Encoding (pcrel)
|
||||||
.byte 0xc ; DW_CFA_def_cfa
|
.byte 0xc ; DW_CFA_def_cfa
|
||||||
.byte 0x1 ; uleb128 0x1
|
.byte 0x1 ; uleb128 0x1
|
||||||
.byte 0x0 ; uleb128 0x0
|
.byte 0x0 ; uleb128 0x0
|
||||||
|
@ -332,7 +332,7 @@ LSFDE1:
|
||||||
|
|
||||||
LASFDE1:
|
LASFDE1:
|
||||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||||
.g_long LLFB1$non_lazy_ptr-. ; FDE initial location
|
.g_long LFB1-. ; FDE initial location
|
||||||
.set L$set$3,LFE1-LFB1
|
.set L$set$3,LFE1-LFB1
|
||||||
.g_long L$set$3 ; FDE address range
|
.g_long L$set$3 ; FDE address range
|
||||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||||
|
@ -374,11 +374,6 @@ L_ffi_closure_helper_DARWIN$lazy_ptr:
|
||||||
.indirect_symbol _ffi_closure_helper_DARWIN
|
.indirect_symbol _ffi_closure_helper_DARWIN
|
||||||
.g_long dyld_stub_binding_helper
|
.g_long dyld_stub_binding_helper
|
||||||
|
|
||||||
.data
|
|
||||||
.align LOG2_GPR_BYTES
|
|
||||||
LLFB1$non_lazy_ptr:
|
|
||||||
.g_long LFB1
|
|
||||||
|
|
||||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||||
.align LOG2_GPR_BYTES
|
.align LOG2_GPR_BYTES
|
||||||
|
|
||||||
|
|
|
@ -46,23 +46,20 @@
|
||||||
|
|
||||||
.globl _ffi_prep_args
|
.globl _ffi_prep_args
|
||||||
|
|
||||||
.align 4
|
.align 4
|
||||||
.globl _ffi_call_SYSV
|
.globl _ffi_call_SYSV
|
||||||
|
|
||||||
_ffi_call_SYSV:
|
_ffi_call_SYSV:
|
||||||
.LFB1:
|
LFB1:
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
.LCFI0:
|
LCFI0:
|
||||||
movl %esp,%ebp
|
movl %esp,%ebp
|
||||||
subl $8,%esp
|
LCFI1:
|
||||||
ASSERT_STACK_ALIGNED
|
subl $8,%esp
|
||||||
.LCFI1:
|
|
||||||
/* Make room for all of the new args. */
|
/* Make room for all of the new args. */
|
||||||
movl 16(%ebp),%ecx
|
movl 16(%ebp),%ecx
|
||||||
subl %ecx,%esp
|
subl %ecx,%esp
|
||||||
|
|
||||||
ASSERT_STACK_ALIGNED
|
|
||||||
|
|
||||||
movl %esp,%eax
|
movl %esp,%eax
|
||||||
|
|
||||||
/* Place all of the ffi_prep_args in position */
|
/* Place all of the ffi_prep_args in position */
|
||||||
|
@ -71,170 +68,349 @@ _ffi_call_SYSV:
|
||||||
pushl %eax
|
pushl %eax
|
||||||
call *8(%ebp)
|
call *8(%ebp)
|
||||||
|
|
||||||
ASSERT_STACK_ALIGNED
|
|
||||||
|
|
||||||
/* Return stack to previous state and call the function */
|
/* Return stack to previous state and call the function */
|
||||||
addl $16,%esp
|
addl $16,%esp
|
||||||
|
|
||||||
ASSERT_STACK_ALIGNED
|
|
||||||
|
|
||||||
call *28(%ebp)
|
call *28(%ebp)
|
||||||
|
|
||||||
/* XXX: return returns return with 'ret $4', that upsets the stack! */
|
/* Remove the space we pushed for the args */
|
||||||
movl 16(%ebp),%ecx
|
movl 16(%ebp),%ecx
|
||||||
addl %ecx,%esp
|
addl %ecx,%esp
|
||||||
|
|
||||||
|
|
||||||
/* Load %ecx with the return type code */
|
/* Load %ecx with the return type code */
|
||||||
movl 20(%ebp),%ecx
|
movl 20(%ebp),%ecx
|
||||||
|
|
||||||
|
|
||||||
/* If the return value pointer is NULL, assume no return value. */
|
/* If the return value pointer is NULL, assume no return value. */
|
||||||
cmpl $0,24(%ebp)
|
cmpl $0,24(%ebp)
|
||||||
jne retint
|
jne Lretint
|
||||||
|
|
||||||
/* Even if there is no space for the return value, we are
|
/* Even if there is no space for the return value, we are
|
||||||
obliged to handle floating-point values. */
|
obliged to handle floating-point values. */
|
||||||
cmpl $FFI_TYPE_FLOAT,%ecx
|
cmpl $FFI_TYPE_FLOAT,%ecx
|
||||||
jne noretval
|
jne Lnoretval
|
||||||
fstp %st(0)
|
fstp %st(0)
|
||||||
|
|
||||||
jmp epilogue
|
jmp Lepilogue
|
||||||
|
|
||||||
retint:
|
Lretint:
|
||||||
cmpl $FFI_TYPE_INT,%ecx
|
cmpl $FFI_TYPE_INT,%ecx
|
||||||
jne retfloat
|
jne Lretfloat
|
||||||
/* Load %ecx with the pointer to storage for the return value */
|
/* Load %ecx with the pointer to storage for the return value */
|
||||||
movl 24(%ebp),%ecx
|
movl 24(%ebp),%ecx
|
||||||
movl %eax,0(%ecx)
|
movl %eax,0(%ecx)
|
||||||
jmp epilogue
|
jmp Lepilogue
|
||||||
|
|
||||||
retfloat:
|
Lretfloat:
|
||||||
cmpl $FFI_TYPE_FLOAT,%ecx
|
cmpl $FFI_TYPE_FLOAT,%ecx
|
||||||
jne retdouble
|
jne Lretdouble
|
||||||
/* Load %ecx with the pointer to storage for the return value */
|
/* Load %ecx with the pointer to storage for the return value */
|
||||||
movl 24(%ebp),%ecx
|
movl 24(%ebp),%ecx
|
||||||
fstps (%ecx)
|
fstps (%ecx)
|
||||||
jmp epilogue
|
jmp Lepilogue
|
||||||
|
|
||||||
retdouble:
|
Lretdouble:
|
||||||
cmpl $FFI_TYPE_DOUBLE,%ecx
|
cmpl $FFI_TYPE_DOUBLE,%ecx
|
||||||
jne retlongdouble
|
jne Lretlongdouble
|
||||||
/* Load %ecx with the pointer to storage for the return value */
|
/* Load %ecx with the pointer to storage for the return value */
|
||||||
movl 24(%ebp),%ecx
|
movl 24(%ebp),%ecx
|
||||||
fstpl (%ecx)
|
fstpl (%ecx)
|
||||||
jmp epilogue
|
jmp Lepilogue
|
||||||
|
|
||||||
retlongdouble:
|
Lretlongdouble:
|
||||||
cmpl $FFI_TYPE_LONGDOUBLE,%ecx
|
cmpl $FFI_TYPE_LONGDOUBLE,%ecx
|
||||||
jne retint64
|
jne Lretint64
|
||||||
/* Load %ecx with the pointer to storage for the return value */
|
/* Load %ecx with the pointer to storage for the return value */
|
||||||
movl 24(%ebp),%ecx
|
movl 24(%ebp),%ecx
|
||||||
fstpt (%ecx)
|
fstpt (%ecx)
|
||||||
jmp epilogue
|
jmp Lepilogue
|
||||||
|
|
||||||
retint64:
|
Lretint64:
|
||||||
cmpl $FFI_TYPE_SINT64,%ecx
|
cmpl $FFI_TYPE_SINT64,%ecx
|
||||||
jne retstruct1b
|
jne Lretstruct1b
|
||||||
/* Load %ecx with the pointer to storage for the return value */
|
/* Load %ecx with the pointer to storage for the return value */
|
||||||
movl 24(%ebp),%ecx
|
movl 24(%ebp),%ecx
|
||||||
movl %eax,0(%ecx)
|
movl %eax,0(%ecx)
|
||||||
movl %edx,4(%ecx)
|
movl %edx,4(%ecx)
|
||||||
jmp epilogue
|
jmp Lepilogue
|
||||||
|
|
||||||
retstruct1b:
|
|
||||||
cmpl $FFI_TYPE_SINT8,%ecx
|
|
||||||
jne retstruct2b
|
|
||||||
movl 24(%ebp),%ecx
|
|
||||||
movb %al,0(%ecx)
|
|
||||||
jmp epilogue
|
|
||||||
|
|
||||||
retstruct2b:
|
|
||||||
cmpl $FFI_TYPE_SINT16,%ecx
|
|
||||||
jne retstruct
|
|
||||||
movl 24(%ebp),%ecx
|
|
||||||
movw %ax,0(%ecx)
|
|
||||||
jmp epilogue
|
|
||||||
|
|
||||||
retstruct:
|
Lretstruct1b:
|
||||||
cmpl $FFI_TYPE_STRUCT,%ecx
|
cmpl $FFI_TYPE_SINT8,%ecx
|
||||||
jne noretval
|
jne Lretstruct2b
|
||||||
|
/* Load %ecx with the pointer to storage for the return value */
|
||||||
|
movl 24(%ebp),%ecx
|
||||||
|
movb %al,0(%ecx)
|
||||||
|
jmp Lepilogue
|
||||||
|
|
||||||
|
Lretstruct2b:
|
||||||
|
cmpl $FFI_TYPE_SINT16,%ecx
|
||||||
|
jne Lretstruct
|
||||||
|
/* Load %ecx with the pointer to storage for the return value */
|
||||||
|
movl 24(%ebp),%ecx
|
||||||
|
movw %ax,0(%ecx)
|
||||||
|
jmp Lepilogue
|
||||||
|
|
||||||
|
Lretstruct:
|
||||||
|
cmpl $FFI_TYPE_STRUCT,%ecx
|
||||||
|
jne Lnoretval
|
||||||
/* Nothing to do! */
|
/* Nothing to do! */
|
||||||
|
addl $4,%esp
|
||||||
|
popl %ebp
|
||||||
|
ret
|
||||||
|
|
||||||
subl $4,%esp
|
Lnoretval:
|
||||||
|
Lepilogue:
|
||||||
ASSERT_STACK_ALIGNED
|
addl $8,%esp
|
||||||
|
|
||||||
addl $8,%esp
|
|
||||||
movl %ebp, %esp
|
|
||||||
popl %ebp
|
|
||||||
ret
|
|
||||||
|
|
||||||
noretval:
|
|
||||||
epilogue:
|
|
||||||
ASSERT_STACK_ALIGNED
|
|
||||||
addl $8, %esp
|
|
||||||
|
|
||||||
|
|
||||||
movl %ebp,%esp
|
movl %ebp,%esp
|
||||||
popl %ebp
|
popl %ebp
|
||||||
ret
|
ret
|
||||||
|
LFE1:
|
||||||
.ffi_call_SYSV_end:
|
.ffi_call_SYSV_end:
|
||||||
#if 0
|
|
||||||
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
|
.align 4
|
||||||
|
FFI_HIDDEN (ffi_closure_SYSV)
|
||||||
|
.globl _ffi_closure_SYSV
|
||||||
|
|
||||||
|
_ffi_closure_SYSV:
|
||||||
|
LFB2:
|
||||||
|
pushl %ebp
|
||||||
|
LCFI2:
|
||||||
|
movl %esp, %ebp
|
||||||
|
LCFI3:
|
||||||
|
subl $56, %esp
|
||||||
|
leal -40(%ebp), %edx
|
||||||
|
movl %edx, -12(%ebp) /* resp */
|
||||||
|
leal 8(%ebp), %edx
|
||||||
|
movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */
|
||||||
|
leal -12(%ebp), %edx
|
||||||
|
movl %edx, (%esp) /* &resp */
|
||||||
|
movl %ebx, 8(%esp)
|
||||||
|
LCFI7:
|
||||||
|
call L_ffi_closure_SYSV_inner$stub
|
||||||
|
movl 8(%esp), %ebx
|
||||||
|
movl -12(%ebp), %ecx
|
||||||
|
cmpl $FFI_TYPE_INT, %eax
|
||||||
|
je Lcls_retint
|
||||||
|
cmpl $FFI_TYPE_FLOAT, %eax
|
||||||
|
je Lcls_retfloat
|
||||||
|
cmpl $FFI_TYPE_DOUBLE, %eax
|
||||||
|
je Lcls_retdouble
|
||||||
|
cmpl $FFI_TYPE_LONGDOUBLE, %eax
|
||||||
|
je Lcls_retldouble
|
||||||
|
cmpl $FFI_TYPE_SINT64, %eax
|
||||||
|
je Lcls_retllong
|
||||||
|
cmpl $FFI_TYPE_SINT8, %eax
|
||||||
|
je Lcls_retstruct1
|
||||||
|
cmpl $FFI_TYPE_SINT16, %eax
|
||||||
|
je Lcls_retstruct2
|
||||||
|
cmpl $FFI_TYPE_STRUCT, %eax
|
||||||
|
je Lcls_retstruct
|
||||||
|
Lcls_epilogue:
|
||||||
|
movl %ebp, %esp
|
||||||
|
popl %ebp
|
||||||
|
ret
|
||||||
|
Lcls_retint:
|
||||||
|
movl (%ecx), %eax
|
||||||
|
jmp Lcls_epilogue
|
||||||
|
Lcls_retfloat:
|
||||||
|
flds (%ecx)
|
||||||
|
jmp Lcls_epilogue
|
||||||
|
Lcls_retdouble:
|
||||||
|
fldl (%ecx)
|
||||||
|
jmp Lcls_epilogue
|
||||||
|
Lcls_retldouble:
|
||||||
|
fldt (%ecx)
|
||||||
|
jmp Lcls_epilogue
|
||||||
|
Lcls_retllong:
|
||||||
|
movl (%ecx), %eax
|
||||||
|
movl 4(%ecx), %edx
|
||||||
|
jmp Lcls_epilogue
|
||||||
|
Lcls_retstruct1:
|
||||||
|
movsbl (%ecx), %eax
|
||||||
|
jmp Lcls_epilogue
|
||||||
|
Lcls_retstruct2:
|
||||||
|
movswl (%ecx), %eax
|
||||||
|
jmp Lcls_epilogue
|
||||||
|
Lcls_retstruct:
|
||||||
|
lea -8(%ebp),%esp
|
||||||
|
movl %ebp, %esp
|
||||||
|
popl %ebp
|
||||||
|
ret $4
|
||||||
|
LFE2:
|
||||||
|
|
||||||
|
#if !FFI_NO_RAW_API
|
||||||
|
|
||||||
|
#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
|
||||||
|
#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
|
||||||
|
#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
|
||||||
|
#define CIF_FLAGS_OFFSET 20
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
FFI_HIDDEN (ffi_closure_raw_SYSV)
|
||||||
|
.globl _ffi_closure_raw_SYSV
|
||||||
|
|
||||||
|
_ffi_closure_raw_SYSV:
|
||||||
|
LFB3:
|
||||||
|
pushl %ebp
|
||||||
|
LCFI4:
|
||||||
|
movl %esp, %ebp
|
||||||
|
LCFI5:
|
||||||
|
pushl %esi
|
||||||
|
LCFI6:
|
||||||
|
subl $36, %esp
|
||||||
|
movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
|
||||||
|
movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
|
||||||
|
movl %edx, 12(%esp) /* user_data */
|
||||||
|
leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */
|
||||||
|
movl %edx, 8(%esp) /* raw_args */
|
||||||
|
leal -24(%ebp), %edx
|
||||||
|
movl %edx, 4(%esp) /* &res */
|
||||||
|
movl %esi, (%esp) /* cif */
|
||||||
|
call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */
|
||||||
|
movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */
|
||||||
|
cmpl $FFI_TYPE_INT, %eax
|
||||||
|
je Lrcls_retint
|
||||||
|
cmpl $FFI_TYPE_FLOAT, %eax
|
||||||
|
je Lrcls_retfloat
|
||||||
|
cmpl $FFI_TYPE_DOUBLE, %eax
|
||||||
|
je Lrcls_retdouble
|
||||||
|
cmpl $FFI_TYPE_LONGDOUBLE, %eax
|
||||||
|
je Lrcls_retldouble
|
||||||
|
cmpl $FFI_TYPE_SINT64, %eax
|
||||||
|
je Lrcls_retllong
|
||||||
|
Lrcls_epilogue:
|
||||||
|
addl $36, %esp
|
||||||
|
popl %esi
|
||||||
|
popl %ebp
|
||||||
|
ret
|
||||||
|
Lrcls_retint:
|
||||||
|
movl -24(%ebp), %eax
|
||||||
|
jmp Lrcls_epilogue
|
||||||
|
Lrcls_retfloat:
|
||||||
|
flds -24(%ebp)
|
||||||
|
jmp Lrcls_epilogue
|
||||||
|
Lrcls_retdouble:
|
||||||
|
fldl -24(%ebp)
|
||||||
|
jmp Lrcls_epilogue
|
||||||
|
Lrcls_retldouble:
|
||||||
|
fldt -24(%ebp)
|
||||||
|
jmp Lrcls_epilogue
|
||||||
|
Lrcls_retllong:
|
||||||
|
movl -24(%ebp), %eax
|
||||||
|
movl -20(%ebp), %edx
|
||||||
|
jmp Lrcls_epilogue
|
||||||
|
LFE3:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
|
||||||
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
L_ffi_closure_SYSV_inner$stub:
|
||||||
.Lframe1:
|
.indirect_symbol _ffi_closure_SYSV_inner
|
||||||
.long .LECIE1-.LSCIE1 /* Length of Common Information Entry */
|
hlt ; hlt ; hlt ; hlt ; hlt
|
||||||
.LSCIE1:
|
|
||||||
.long 0x0 /* CIE Identifier Tag */
|
|
||||||
.byte 0x1 /* CIE Version */
|
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||||
#ifdef __PIC__
|
EH_frame1:
|
||||||
.ascii "zR\0" /* CIE Augmentation */
|
.set L$set$0,LECIE1-LSCIE1
|
||||||
#else
|
.long L$set$0
|
||||||
.ascii "\0" /* CIE Augmentation */
|
LSCIE1:
|
||||||
#endif
|
.long 0x0
|
||||||
.byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */
|
.byte 0x1
|
||||||
.byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */
|
.ascii "zR\0"
|
||||||
.byte 0x8 /* CIE RA Column */
|
.byte 0x1
|
||||||
#ifdef __PIC__
|
.byte 0x7c
|
||||||
.byte 0x1 /* .uleb128 0x1; Augmentation size */
|
.byte 0x8
|
||||||
.byte 0x1b /* FDE Encoding (pcrel sdata4) */
|
.byte 0x1
|
||||||
#endif
|
.byte 0x10
|
||||||
.byte 0xc /* DW_CFA_def_cfa */
|
.byte 0xc
|
||||||
.byte 0x4 /* .uleb128 0x4 */
|
.byte 0x5
|
||||||
.byte 0x4 /* .uleb128 0x4 */
|
.byte 0x4
|
||||||
.byte 0x88 /* DW_CFA_offset, column 0x8 */
|
.byte 0x88
|
||||||
.byte 0x1 /* .uleb128 0x1 */
|
.byte 0x1
|
||||||
.align 4
|
.align 2
|
||||||
.LECIE1:
|
LECIE1:
|
||||||
.LSFDE1:
|
.globl _ffi_call_SYSV.eh
|
||||||
.long .LEFDE1-.LASFDE1 /* FDE Length */
|
_ffi_call_SYSV.eh:
|
||||||
.LASFDE1:
|
LSFDE1:
|
||||||
.long .LASFDE1-.Lframe1 /* FDE CIE offset */
|
.set L$set$1,LEFDE1-LASFDE1
|
||||||
#ifdef __PIC__
|
.long L$set$1
|
||||||
.long .LFB1-. /* FDE initial location */
|
LASFDE1:
|
||||||
#else
|
.long LASFDE1-EH_frame1
|
||||||
.long .LFB1 /* FDE initial location */
|
.long LFB1-.
|
||||||
#endif
|
.set L$set$2,LFE1-LFB1
|
||||||
.long .ffi_call_SYSV_end-.LFB1 /* FDE address range */
|
.long L$set$2
|
||||||
#ifdef __PIC__
|
.byte 0x0
|
||||||
.byte 0x0 /* .uleb128 0x0; Augmentation size */
|
.byte 0x4
|
||||||
#endif
|
.set L$set$3,LCFI0-LFB1
|
||||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
.long L$set$3
|
||||||
.long .LCFI0-.LFB1
|
.byte 0xe
|
||||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
.byte 0x8
|
||||||
.byte 0x8 /* .uleb128 0x8 */
|
.byte 0x84
|
||||||
.byte 0x85 /* DW_CFA_offset, column 0x5 */
|
.byte 0x2
|
||||||
.byte 0x2 /* .uleb128 0x2 */
|
.byte 0x4
|
||||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
.set L$set$4,LCFI1-LCFI0
|
||||||
.long .LCFI1-.LCFI0
|
.long L$set$4
|
||||||
.byte 0xd /* DW_CFA_def_cfa_register */
|
.byte 0xd
|
||||||
.byte 0x5 /* .uleb128 0x5 */
|
.byte 0x4
|
||||||
.align 4
|
.align 2
|
||||||
.LEFDE1:
|
LEFDE1:
|
||||||
|
.globl _ffi_closure_SYSV.eh
|
||||||
|
_ffi_closure_SYSV.eh:
|
||||||
|
LSFDE2:
|
||||||
|
.set L$set$5,LEFDE2-LASFDE2
|
||||||
|
.long L$set$5
|
||||||
|
LASFDE2:
|
||||||
|
.long LASFDE2-EH_frame1
|
||||||
|
.long LFB2-.
|
||||||
|
.set L$set$6,LFE2-LFB2
|
||||||
|
.long L$set$6
|
||||||
|
.byte 0x0
|
||||||
|
.byte 0x4
|
||||||
|
.set L$set$7,LCFI2-LFB2
|
||||||
|
.long L$set$7
|
||||||
|
.byte 0xe
|
||||||
|
.byte 0x8
|
||||||
|
.byte 0x84
|
||||||
|
.byte 0x2
|
||||||
|
.byte 0x4
|
||||||
|
.set L$set$8,LCFI3-LCFI2
|
||||||
|
.long L$set$8
|
||||||
|
.byte 0xd
|
||||||
|
.byte 0x4
|
||||||
|
.align 2
|
||||||
|
LEFDE2:
|
||||||
|
|
||||||
|
#if !FFI_NO_RAW_API
|
||||||
|
|
||||||
|
.globl _ffi_closure_raw_SYSV.eh
|
||||||
|
_ffi_closure_raw_SYSV.eh:
|
||||||
|
LSFDE3:
|
||||||
|
.set L$set$10,LEFDE3-LASFDE3
|
||||||
|
.long L$set$10
|
||||||
|
LASFDE3:
|
||||||
|
.long LASFDE3-EH_frame1
|
||||||
|
.long LFB3-.
|
||||||
|
.set L$set$11,LFE3-LFB3
|
||||||
|
.long L$set$11
|
||||||
|
.byte 0x0
|
||||||
|
.byte 0x4
|
||||||
|
.set L$set$12,LCFI4-LFB3
|
||||||
|
.long L$set$12
|
||||||
|
.byte 0xe
|
||||||
|
.byte 0x8
|
||||||
|
.byte 0x84
|
||||||
|
.byte 0x2
|
||||||
|
.byte 0x4
|
||||||
|
.set L$set$13,LCFI5-LCFI4
|
||||||
|
.long L$set$13
|
||||||
|
.byte 0xd
|
||||||
|
.byte 0x4
|
||||||
|
.byte 0x4
|
||||||
|
.set L$set$14,LCFI6-LCFI5
|
||||||
|
.long L$set$14
|
||||||
|
.byte 0x85
|
||||||
|
.byte 0x3
|
||||||
|
.align 2
|
||||||
|
LEFDE3:
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* ifndef __x86_64__ */
|
#endif /* ifndef __x86_64__ */
|
||||||
|
|
|
@ -55,7 +55,7 @@ ffi_call_unix64(
|
||||||
/* Register class used for passing given 64bit part of the argument.
|
/* Register class used for passing given 64bit part of the argument.
|
||||||
These represent classes as documented by the PS ABI, with the exception
|
These represent classes as documented by the PS ABI, with the exception
|
||||||
of SSESF, SSEDF classes, that are basically SSE class, just gcc will
|
of SSESF, SSEDF classes, that are basically SSE class, just gcc will
|
||||||
use SF or DFmode move instead of DImode to avoid reformatting penalties.
|
use SF or DFmode move instead of DImode to avoid reformating penalties.
|
||||||
|
|
||||||
Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
|
Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
|
||||||
whenever possible (upper half does contain padding). */
|
whenever possible (upper half does contain padding). */
|
||||||
|
@ -621,4 +621,4 @@ ffi_closure_unix64_inner(
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __x86_64__ */
|
#endif /* __x86_64__ */
|
|
@ -27,543 +27,410 @@
|
||||||
OTHER DEALINGS IN THE SOFTWARE.
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
----------------------------------------------------------------------- */
|
----------------------------------------------------------------------- */
|
||||||
|
|
||||||
//#ifndef __x86_64__
|
|
||||||
|
|
||||||
#include <ffi.h>
|
#include <ffi.h>
|
||||||
#include <ffi_common.h>
|
#include <ffi_common.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
//void ffi_prep_args(char *stack, extended_cif *ecif);
|
|
||||||
|
|
||||||
static inline int
|
|
||||||
retval_on_stack(
|
|
||||||
ffi_type* tp)
|
|
||||||
{
|
|
||||||
if (tp->type == FFI_TYPE_STRUCT)
|
|
||||||
{
|
|
||||||
// int size = tp->size;
|
|
||||||
|
|
||||||
if (tp->size > 8)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
switch (tp->size)
|
|
||||||
{
|
|
||||||
case 1: case 2: case 4: case 8:
|
|
||||||
return 0;
|
|
||||||
default:
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ffi_prep_args is called by the assembly routine once stack space
|
/* ffi_prep_args is called by the assembly routine once stack space
|
||||||
has been allocated for the function's arguments */
|
has been allocated for the function's arguments */
|
||||||
/*@-exportheader@*/
|
|
||||||
extern void ffi_prep_args(char*, extended_cif*);
|
void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||||
void
|
|
||||||
ffi_prep_args(
|
|
||||||
char* stack,
|
|
||||||
extended_cif* ecif)
|
|
||||||
/*@=exportheader@*/
|
|
||||||
{
|
{
|
||||||
register unsigned int i;
|
register unsigned int i;
|
||||||
register void** p_argv = ecif->avalue;
|
register void **p_argv;
|
||||||
register char* argp = stack;
|
register char *argp;
|
||||||
register ffi_type** p_arg;
|
register ffi_type **p_arg;
|
||||||
|
|
||||||
if (retval_on_stack(ecif->cif->rtype))
|
argp = stack;
|
||||||
{
|
|
||||||
*(void**)argp = ecif->rvalue;
|
if (ecif->cif->flags == FFI_TYPE_STRUCT)
|
||||||
argp += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
p_arg = ecif->cif->arg_types;
|
|
||||||
|
|
||||||
for (i = ecif->cif->nargs; i > 0; i--, p_arg++, p_argv++)
|
|
||||||
{
|
{
|
||||||
size_t z = (*p_arg)->size;
|
*(void **) argp = ecif->rvalue;
|
||||||
|
argp += 4;
|
||||||
/* Align if necessary */
|
}
|
||||||
if ((sizeof(int) - 1) & (unsigned)argp)
|
|
||||||
argp = (char*)ALIGN(argp, sizeof(int));
|
p_argv = ecif->avalue;
|
||||||
|
|
||||||
if (z < sizeof(int))
|
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||||
{
|
i != 0;
|
||||||
z = sizeof(int);
|
i--, p_arg++)
|
||||||
|
{
|
||||||
switch ((*p_arg)->type)
|
size_t z;
|
||||||
{
|
|
||||||
case FFI_TYPE_SINT8:
|
/* Align if necessary */
|
||||||
*(signed int*)argp = (signed int)*(SINT8*)(*p_argv);
|
if ((sizeof(int) - 1) & (unsigned) argp)
|
||||||
break;
|
argp = (char *) ALIGN(argp, sizeof(int));
|
||||||
|
|
||||||
case FFI_TYPE_UINT8:
|
z = (*p_arg)->size;
|
||||||
*(unsigned int*)argp = (unsigned int)*(UINT8*)(*p_argv);
|
if (z < sizeof(int))
|
||||||
break;
|
{
|
||||||
|
z = sizeof(int);
|
||||||
case FFI_TYPE_SINT16:
|
switch ((*p_arg)->type)
|
||||||
*(signed int*)argp = (signed int)*(SINT16*)(*p_argv);
|
{
|
||||||
break;
|
case FFI_TYPE_SINT8:
|
||||||
|
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||||
case FFI_TYPE_UINT16:
|
break;
|
||||||
*(unsigned int*)argp = (unsigned int)*(UINT16*)(*p_argv);
|
|
||||||
break;
|
case FFI_TYPE_UINT8:
|
||||||
|
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||||
case FFI_TYPE_SINT32:
|
break;
|
||||||
*(signed int*)argp = (signed int)*(SINT32*)(*p_argv);
|
|
||||||
break;
|
case FFI_TYPE_SINT16:
|
||||||
|
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||||
case FFI_TYPE_UINT32:
|
break;
|
||||||
*(unsigned int*)argp = (unsigned int)*(UINT32*)(*p_argv);
|
|
||||||
break;
|
case FFI_TYPE_UINT16:
|
||||||
|
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||||
case FFI_TYPE_STRUCT:
|
break;
|
||||||
*(unsigned int*)argp = (unsigned int)*(UINT32*)(*p_argv);
|
|
||||||
break;
|
case FFI_TYPE_SINT32:
|
||||||
|
*(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
|
||||||
default:
|
break;
|
||||||
FFI_ASSERT(0);
|
|
||||||
break;
|
case FFI_TYPE_UINT32:
|
||||||
}
|
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||||
}
|
break;
|
||||||
else
|
|
||||||
memcpy(argp, *p_argv, z);
|
case FFI_TYPE_STRUCT:
|
||||||
|
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||||
argp += z;
|
break;
|
||||||
}
|
|
||||||
|
default:
|
||||||
|
FFI_ASSERT(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(argp, *p_argv, z);
|
||||||
|
}
|
||||||
|
p_argv++;
|
||||||
|
argp += z;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform machine dependent cif processing */
|
/* Perform machine dependent cif processing */
|
||||||
ffi_status
|
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||||
ffi_prep_cif_machdep(
|
|
||||||
ffi_cif* cif)
|
|
||||||
{
|
{
|
||||||
/* Set the return type flag */
|
/* Set the return type flag */
|
||||||
switch (cif->rtype->type)
|
switch (cif->rtype->type)
|
||||||
{
|
{
|
||||||
#if !defined(X86_WIN32) && !defined(X86_DARWIN)
|
case FFI_TYPE_VOID:
|
||||||
case FFI_TYPE_STRUCT:
|
#ifdef X86
|
||||||
|
case FFI_TYPE_STRUCT:
|
||||||
|
case FFI_TYPE_UINT8:
|
||||||
|
case FFI_TYPE_UINT16:
|
||||||
|
case FFI_TYPE_SINT8:
|
||||||
|
case FFI_TYPE_SINT16:
|
||||||
#endif
|
#endif
|
||||||
case FFI_TYPE_VOID:
|
|
||||||
case FFI_TYPE_SINT64:
|
case FFI_TYPE_SINT64:
|
||||||
case FFI_TYPE_FLOAT:
|
case FFI_TYPE_FLOAT:
|
||||||
case FFI_TYPE_DOUBLE:
|
case FFI_TYPE_DOUBLE:
|
||||||
case FFI_TYPE_LONGDOUBLE:
|
case FFI_TYPE_LONGDOUBLE:
|
||||||
cif->flags = (unsigned)cif->rtype->type;
|
cif->flags = (unsigned) cif->rtype->type;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FFI_TYPE_UINT64:
|
case FFI_TYPE_UINT64:
|
||||||
cif->flags = FFI_TYPE_SINT64;
|
cif->flags = FFI_TYPE_SINT64;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if defined(X86_WIN32) || defined(X86_DARWIN)
|
#ifndef X86
|
||||||
case FFI_TYPE_STRUCT:
|
case FFI_TYPE_STRUCT:
|
||||||
switch (cif->rtype->size)
|
if (cif->rtype->size == 1)
|
||||||
{
|
{
|
||||||
case 1:
|
cif->flags = FFI_TYPE_SINT8; /* same as char size */
|
||||||
cif->flags = FFI_TYPE_SINT8;
|
}
|
||||||
break;
|
else if (cif->rtype->size == 2)
|
||||||
|
{
|
||||||
case 2:
|
cif->flags = FFI_TYPE_SINT16; /* same as short size */
|
||||||
cif->flags = FFI_TYPE_SINT16;
|
}
|
||||||
break;
|
else if (cif->rtype->size == 4)
|
||||||
|
{
|
||||||
case 4:
|
cif->flags = FFI_TYPE_INT; /* same as int type */
|
||||||
cif->flags = FFI_TYPE_INT;
|
}
|
||||||
break;
|
else if (cif->rtype->size == 8)
|
||||||
|
{
|
||||||
case 8:
|
cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
|
||||||
cif->flags = FFI_TYPE_SINT64;
|
}
|
||||||
break;
|
else
|
||||||
|
{
|
||||||
default:
|
cif->flags = FFI_TYPE_STRUCT;
|
||||||
cif->flags = FFI_TYPE_STRUCT;
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cif->flags = FFI_TYPE_INT;
|
cif->flags = FFI_TYPE_INT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Darwin: The stack needs to be aligned to a multiple of 16 bytes */
|
#ifdef X86_DARWIN
|
||||||
cif->bytes = (cif->bytes + 15) & ~0xF;
|
cif->bytes = (cif->bytes + 15) & ~0xF;
|
||||||
|
#endif
|
||||||
return FFI_OK;
|
|
||||||
|
return FFI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@-declundef@*/
|
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||||
/*@-exportheader@*/
|
unsigned, unsigned, unsigned *, void (*fn)());
|
||||||
extern void
|
|
||||||
ffi_call_SYSV(
|
|
||||||
void (*)(char *, extended_cif *),
|
|
||||||
/*@out@*/ extended_cif* ,
|
|
||||||
unsigned ,
|
|
||||||
unsigned ,
|
|
||||||
/*@out@*/ unsigned* ,
|
|
||||||
void (*fn)(void));
|
|
||||||
/*@=declundef@*/
|
|
||||||
/*@=exportheader@*/
|
|
||||||
|
|
||||||
#ifdef X86_WIN32
|
#ifdef X86_WIN32
|
||||||
/*@-declundef@*/
|
extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
|
||||||
/*@-exportheader@*/
|
unsigned, unsigned, unsigned *, void (*fn)());
|
||||||
extern void
|
|
||||||
ffi_call_STDCALL(
|
|
||||||
void (char *, extended_cif *),
|
|
||||||
/*@out@*/ extended_cif* ,
|
|
||||||
unsigned ,
|
|
||||||
unsigned ,
|
|
||||||
/*@out@*/ unsigned* ,
|
|
||||||
void (*fn)(void));
|
|
||||||
/*@=declundef@*/
|
|
||||||
/*@=exportheader@*/
|
|
||||||
#endif /* X86_WIN32 */
|
#endif /* X86_WIN32 */
|
||||||
|
|
||||||
void
|
void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
||||||
ffi_call(
|
|
||||||
/*@dependent@*/ ffi_cif* cif,
|
|
||||||
void (*fn)(void),
|
|
||||||
/*@out@*/ void* rvalue,
|
|
||||||
/*@dependent@*/ void** avalue)
|
|
||||||
{
|
{
|
||||||
extended_cif ecif;
|
extended_cif ecif;
|
||||||
|
|
||||||
ecif.cif = cif;
|
ecif.cif = cif;
|
||||||
ecif.avalue = avalue;
|
ecif.avalue = avalue;
|
||||||
|
|
||||||
/* If the return value is a struct and we don't have a return
|
/* If the return value is a struct and we don't have a return */
|
||||||
value address then we need to make one. */
|
/* value address then we need to make one */
|
||||||
|
|
||||||
if ((rvalue == NULL) && retval_on_stack(cif->rtype))
|
if ((rvalue == NULL) &&
|
||||||
{
|
(cif->flags == FFI_TYPE_STRUCT))
|
||||||
/*@-sysunrecog@*/
|
{
|
||||||
ecif.rvalue = alloca(cif->rtype->size);
|
ecif.rvalue = alloca(cif->rtype->size);
|
||||||
/*@=sysunrecog@*/
|
}
|
||||||
}
|
else
|
||||||
else
|
ecif.rvalue = rvalue;
|
||||||
ecif.rvalue = rvalue;
|
|
||||||
|
|
||||||
switch (cif->abi)
|
switch (cif->abi)
|
||||||
{
|
{
|
||||||
case FFI_SYSV:
|
case FFI_SYSV:
|
||||||
/*@-usedef@*/
|
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
|
||||||
/* To avoid changing the assembly code make sure the size of the argument
|
fn);
|
||||||
block is a multiple of 16. Then add 8 to compensate for local variables
|
break;
|
||||||
in ffi_call_SYSV. */
|
|
||||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
|
|
||||||
cif->flags, ecif.rvalue, fn);
|
|
||||||
/*@=usedef@*/
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifdef X86_WIN32
|
#ifdef X86_WIN32
|
||||||
case FFI_STDCALL:
|
case FFI_STDCALL:
|
||||||
/*@-usedef@*/
|
ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
|
||||||
ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
|
ecif.rvalue, fn);
|
||||||
cif->flags, ecif.rvalue, fn);
|
break;
|
||||||
/*@=usedef@*/
|
|
||||||
break;
|
|
||||||
#endif /* X86_WIN32 */
|
#endif /* X86_WIN32 */
|
||||||
|
default:
|
||||||
default:
|
FFI_ASSERT(0);
|
||||||
FFI_ASSERT(0);
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** private members **/
|
/** private members **/
|
||||||
|
|
||||||
static void
|
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
|
||||||
ffi_closure_SYSV(
|
void** args, ffi_cif* cif);
|
||||||
ffi_closure* closure) __attribute__((regparm(1)));
|
void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
|
||||||
|
__attribute__ ((regparm(1)));
|
||||||
#if !FFI_NO_RAW_API
|
unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
|
||||||
static void
|
__attribute__ ((regparm(1)));
|
||||||
ffi_closure_raw_SYSV(
|
void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
|
||||||
ffi_raw_closure* closure) __attribute__((regparm(1)));
|
__attribute__ ((regparm(1)));
|
||||||
#endif
|
|
||||||
|
|
||||||
/*@-exportheader@*/
|
|
||||||
static inline
|
|
||||||
void
|
|
||||||
ffi_prep_incoming_args_SYSV(
|
|
||||||
char* stack,
|
|
||||||
void** rvalue,
|
|
||||||
void** avalue,
|
|
||||||
ffi_cif* cif)
|
|
||||||
/*@=exportheader@*/
|
|
||||||
{
|
|
||||||
register unsigned int i;
|
|
||||||
register void** p_argv = avalue;
|
|
||||||
register char* argp = stack;
|
|
||||||
register ffi_type** p_arg;
|
|
||||||
|
|
||||||
if (retval_on_stack(cif->rtype))
|
|
||||||
{
|
|
||||||
*rvalue = *(void**)argp;
|
|
||||||
argp += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = cif->nargs, p_arg = cif->arg_types; i > 0; i--, p_arg++, p_argv++)
|
|
||||||
{
|
|
||||||
// size_t z;
|
|
||||||
|
|
||||||
/* Align if necessary */
|
|
||||||
if ((sizeof(int) - 1) & (unsigned)argp)
|
|
||||||
argp = (char*)ALIGN(argp, sizeof(int));
|
|
||||||
|
|
||||||
// z = (*p_arg)->size;
|
|
||||||
|
|
||||||
/* because we're little endian, this is what it turns into. */
|
|
||||||
*p_argv = (void*)argp;
|
|
||||||
|
|
||||||
argp += (*p_arg)->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function is jumped to by the trampoline */
|
/* This function is jumped to by the trampoline */
|
||||||
__attribute__((regparm(1)))
|
|
||||||
static void
|
unsigned int FFI_HIDDEN
|
||||||
ffi_closure_SYSV(
|
ffi_closure_SYSV_inner (closure, respp, args)
|
||||||
ffi_closure* closure)
|
ffi_closure *closure;
|
||||||
|
void **respp;
|
||||||
|
void *args;
|
||||||
{
|
{
|
||||||
long double res;
|
// our various things...
|
||||||
ffi_cif* cif = closure->cif;
|
ffi_cif *cif;
|
||||||
void** arg_area = (void**)alloca(cif->nargs * sizeof(void*));
|
void **arg_area;
|
||||||
void* resp = (void*)&res;
|
|
||||||
void* args = __builtin_dwarf_cfa();
|
cif = closure->cif;
|
||||||
|
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
|
||||||
/* This call will initialize ARG_AREA, such that each
|
|
||||||
element in that array points to the corresponding
|
/* this call will initialize ARG_AREA, such that each
|
||||||
value on the stack; and if the function returns
|
* element in that array points to the corresponding
|
||||||
a structure, it will reset RESP to point to the
|
* value on the stack; and if the function returns
|
||||||
structure return address. */
|
* a structure, it will re-set RESP to point to the
|
||||||
ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
|
* structure return address. */
|
||||||
|
|
||||||
(closure->fun)(cif, resp, arg_area, closure->user_data);
|
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
|
||||||
|
|
||||||
/* now, do a generic return based on the value of rtype */
|
(closure->fun) (cif, *respp, arg_area, closure->user_data);
|
||||||
if (cif->flags == FFI_TYPE_INT)
|
|
||||||
asm("movl (%0),%%eax"
|
return cif->flags;
|
||||||
: : "r" (resp) : "eax");
|
|
||||||
else if (cif->flags == FFI_TYPE_FLOAT)
|
|
||||||
asm("flds (%0)"
|
|
||||||
: : "r" (resp) : "st");
|
|
||||||
else if (cif->flags == FFI_TYPE_DOUBLE)
|
|
||||||
asm("fldl (%0)"
|
|
||||||
: : "r" (resp) : "st", "st(1)");
|
|
||||||
else if (cif->flags == FFI_TYPE_LONGDOUBLE)
|
|
||||||
asm("fldt (%0)"
|
|
||||||
: : "r" (resp) : "st", "st(1)");
|
|
||||||
else if (cif->flags == FFI_TYPE_SINT64)
|
|
||||||
asm("movl 0(%0),%%eax;"
|
|
||||||
"movl 4(%0),%%edx"
|
|
||||||
: : "r" (resp)
|
|
||||||
: "eax", "edx");
|
|
||||||
|
|
||||||
#if defined(X86_WIN32) || defined(X86_DARWIN)
|
|
||||||
else if (cif->flags == FFI_TYPE_SINT8) /* 1-byte struct */
|
|
||||||
asm("movsbl (%0),%%eax"
|
|
||||||
: : "r" (resp) : "eax");
|
|
||||||
else if (cif->flags == FFI_TYPE_SINT16) /* 2-bytes struct */
|
|
||||||
asm("movswl (%0),%%eax"
|
|
||||||
: : "r" (resp) : "eax");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
else if (cif->flags == FFI_TYPE_STRUCT)
|
|
||||||
asm("lea -8(%ebp),%esp;"
|
|
||||||
"pop %esi;"
|
|
||||||
"pop %edi;"
|
|
||||||
"pop %ebp;"
|
|
||||||
"ret $4");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
|
||||||
|
ffi_cif *cif)
|
||||||
|
{
|
||||||
|
register unsigned int i;
|
||||||
|
register void **p_argv;
|
||||||
|
register char *argp;
|
||||||
|
register ffi_type **p_arg;
|
||||||
|
|
||||||
|
argp = stack;
|
||||||
|
|
||||||
|
if ( cif->flags == FFI_TYPE_STRUCT ) {
|
||||||
|
*rvalue = *(void **) argp;
|
||||||
|
argp += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_argv = avalue;
|
||||||
|
|
||||||
|
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
|
||||||
|
{
|
||||||
|
size_t z;
|
||||||
|
|
||||||
|
/* Align if necessary */
|
||||||
|
if ((sizeof(int) - 1) & (unsigned) argp) {
|
||||||
|
argp = (char *) ALIGN(argp, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
z = (*p_arg)->size;
|
||||||
|
|
||||||
|
/* because we're little endian, this is what it turns into. */
|
||||||
|
|
||||||
|
*p_argv = (void*) argp;
|
||||||
|
|
||||||
|
p_argv++;
|
||||||
|
argp += z;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
|
/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
|
||||||
#define FFI_INIT_TRAMPOLINE(TRAMP, FUN, CTX) \
|
|
||||||
({ \
|
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
|
||||||
unsigned char* __tramp = (unsigned char*)(TRAMP); \
|
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
||||||
unsigned int __fun = (unsigned int)(FUN); \
|
unsigned int __fun = (unsigned int)(FUN); \
|
||||||
unsigned int __ctx = (unsigned int)(CTX); \
|
unsigned int __ctx = (unsigned int)(CTX); \
|
||||||
unsigned int __dis = __fun - ((unsigned int)__tramp + FFI_TRAMPOLINE_SIZE); \
|
unsigned int __dis = __fun - (__ctx + FFI_TRAMPOLINE_SIZE); \
|
||||||
*(unsigned char*)&__tramp[0] = 0xb8; \
|
*(unsigned char*) &__tramp[0] = 0xb8; \
|
||||||
*(unsigned int*)&__tramp[1] = __ctx; /* movl __ctx, %eax */ \
|
*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
|
||||||
*(unsigned char*)&__tramp[5] = 0xe9; \
|
*(unsigned char *) &__tramp[5] = 0xe9; \
|
||||||
*(unsigned int*)&__tramp[6] = __dis; /* jmp __fun */ \
|
*(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
/* the cif must already be prep'ed */
|
/* the cif must already be prep'ed */
|
||||||
ffi_status
|
ffi_status
|
||||||
ffi_prep_closure(
|
ffi_prep_closure (ffi_closure* closure,
|
||||||
ffi_closure* closure,
|
ffi_cif* cif,
|
||||||
ffi_cif* cif,
|
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
void *user_data)
|
||||||
void* user_data)
|
|
||||||
{
|
{
|
||||||
// FFI_ASSERT(cif->abi == FFI_SYSV);
|
|
||||||
if (cif->abi != FFI_SYSV)
|
if (cif->abi != FFI_SYSV)
|
||||||
return FFI_BAD_ABI;
|
return FFI_BAD_ABI;
|
||||||
|
|
||||||
FFI_INIT_TRAMPOLINE(closure->tramp, &ffi_closure_SYSV, (void*)closure);
|
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
|
||||||
|
&ffi_closure_SYSV, \
|
||||||
closure->cif = cif;
|
(void*)closure);
|
||||||
closure->user_data = user_data;
|
|
||||||
closure->fun = fun;
|
closure->cif = cif;
|
||||||
|
closure->user_data = user_data;
|
||||||
return FFI_OK;
|
closure->fun = fun;
|
||||||
|
|
||||||
|
return FFI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------- Native raw API support -------------------------------- */
|
/* ------- Native raw API support -------------------------------- */
|
||||||
|
|
||||||
#if !FFI_NO_RAW_API
|
#if !FFI_NO_RAW_API
|
||||||
|
|
||||||
__attribute__((regparm(1)))
|
|
||||||
static void
|
|
||||||
ffi_closure_raw_SYSV(
|
|
||||||
ffi_raw_closure* closure)
|
|
||||||
{
|
|
||||||
long double res;
|
|
||||||
ffi_raw* raw_args = (ffi_raw*)__builtin_dwarf_cfa();
|
|
||||||
ffi_cif* cif = closure->cif;
|
|
||||||
unsigned short rtype = cif->flags;
|
|
||||||
void* resp = (void*)&res;
|
|
||||||
|
|
||||||
(closure->fun)(cif, resp, raw_args, closure->user_data);
|
|
||||||
|
|
||||||
/* now, do a generic return based on the value of rtype */
|
|
||||||
if (rtype == FFI_TYPE_INT)
|
|
||||||
asm("movl (%0),%%eax"
|
|
||||||
: : "r" (resp) : "eax");
|
|
||||||
else if (rtype == FFI_TYPE_FLOAT)
|
|
||||||
asm("flds (%0)"
|
|
||||||
: : "r" (resp) : "st");
|
|
||||||
else if (rtype == FFI_TYPE_DOUBLE)
|
|
||||||
asm("fldl (%0)"
|
|
||||||
: : "r" (resp) : "st", "st(1)");
|
|
||||||
else if (rtype == FFI_TYPE_LONGDOUBLE)
|
|
||||||
asm("fldt (%0)"
|
|
||||||
: : "r" (resp) : "st", "st(1)");
|
|
||||||
else if (rtype == FFI_TYPE_SINT64)
|
|
||||||
asm("movl 0(%0),%%eax;"
|
|
||||||
"movl 4(%0),%%edx"
|
|
||||||
: : "r" (resp) : "eax", "edx");
|
|
||||||
}
|
|
||||||
|
|
||||||
ffi_status
|
ffi_status
|
||||||
ffi_prep_raw_closure(
|
ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
|
||||||
ffi_raw_closure* closure,
|
ffi_cif* cif,
|
||||||
ffi_cif* cif,
|
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
void *user_data,
|
||||||
void* user_data)
|
void *codeloc)
|
||||||
{
|
{
|
||||||
// FFI_ASSERT (cif->abi == FFI_SYSV);
|
int i;
|
||||||
if (cif->abi != FFI_SYSV)
|
|
||||||
return FFI_BAD_ABI;
|
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||||
|
|
||||||
int i;
|
// we currently don't support certain kinds of arguments for raw
|
||||||
|
// closures. This should be implemented by a separate assembly language
|
||||||
/* We currently don't support certain kinds of arguments for raw
|
// routine, since it would require argument processing, something we
|
||||||
closures. This should be implemented by a separate assembly language
|
// don't do now for performance.
|
||||||
routine, since it would require argument processing, something we
|
|
||||||
don't do now for performance. */
|
for (i = cif->nargs-1; i >= 0; i--)
|
||||||
for (i = cif->nargs - 1; i >= 0; i--)
|
{
|
||||||
{
|
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
|
||||||
FFI_ASSERT(cif->arg_types[i]->type != FFI_TYPE_STRUCT);
|
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
|
||||||
FFI_ASSERT(cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
FFI_INIT_TRAMPOLINE(closure->tramp, &ffi_closure_raw_SYSV, (void*)closure);
|
FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
|
||||||
|
codeloc);
|
||||||
closure->cif = cif;
|
|
||||||
closure->user_data = user_data;
|
closure->cif = cif;
|
||||||
closure->fun = fun;
|
closure->user_data = user_data;
|
||||||
|
closure->fun = fun;
|
||||||
return FFI_OK;
|
|
||||||
|
return FFI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ffi_prep_args_raw(
|
ffi_prep_args_raw(char *stack, extended_cif *ecif)
|
||||||
char* stack,
|
|
||||||
extended_cif* ecif)
|
|
||||||
{
|
{
|
||||||
memcpy(stack, ecif->avalue, ecif->cif->bytes);
|
memcpy (stack, ecif->avalue, ecif->cif->bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We borrow this routine from libffi (it must be changed, though, to
|
/* we borrow this routine from libffi (it must be changed, though, to
|
||||||
actually call the function passed in the first argument. as of
|
* actually call the function passed in the first argument. as of
|
||||||
libffi-1.20, this is not the case.) */
|
* libffi-1.20, this is not the case.)
|
||||||
//extern void
|
*/
|
||||||
//ffi_call_SYSV(
|
|
||||||
// void (*)(char *, extended_cif *),
|
extern void
|
||||||
///*@out@*/ extended_cif* ,
|
ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned,
|
||||||
// unsigned ,
|
unsigned, unsigned *, void (*fn)());
|
||||||
// unsigned ,
|
|
||||||
//*@out@*/ unsigned* ,
|
|
||||||
// void (*fn)());
|
|
||||||
|
|
||||||
#ifdef X86_WIN32
|
#ifdef X86_WIN32
|
||||||
extern void
|
extern void
|
||||||
ffi_call_STDCALL(
|
ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
|
||||||
void (*)(char *, extended_cif *),
|
unsigned, unsigned *, void (*fn)());
|
||||||
/*@out@*/ extended_cif* ,
|
#endif /* X86_WIN32 */
|
||||||
unsigned ,
|
|
||||||
unsigned ,
|
|
||||||
/*@out@*/ unsigned* ,
|
|
||||||
void (*fn)());
|
|
||||||
#endif // X86_WIN32
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ffi_raw_call(
|
ffi_raw_call(ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *fake_avalue)
|
||||||
/*@dependent@*/ ffi_cif* cif,
|
|
||||||
void (*fn)(),
|
|
||||||
/*@out@*/ void* rvalue,
|
|
||||||
/*@dependent@*/ ffi_raw* fake_avalue)
|
|
||||||
{
|
{
|
||||||
extended_cif ecif;
|
extended_cif ecif;
|
||||||
void **avalue = (void **)fake_avalue;
|
void **avalue = (void **)fake_avalue;
|
||||||
|
|
||||||
ecif.cif = cif;
|
ecif.cif = cif;
|
||||||
ecif.avalue = avalue;
|
ecif.avalue = avalue;
|
||||||
|
|
||||||
/* If the return value is a struct and we don't have a return
|
/* If the return value is a struct and we don't have a return */
|
||||||
value address then we need to make one */
|
/* value address then we need to make one */
|
||||||
if ((rvalue == NULL) && retval_on_stack(cif->rtype))
|
|
||||||
{
|
if ((rvalue == NULL) &&
|
||||||
/*@-sysunrecog@*/
|
(cif->rtype->type == FFI_TYPE_STRUCT))
|
||||||
ecif.rvalue = alloca(cif->rtype->size);
|
{
|
||||||
/*@=sysunrecog@*/
|
ecif.rvalue = alloca(cif->rtype->size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ecif.rvalue = rvalue;
|
ecif.rvalue = rvalue;
|
||||||
|
|
||||||
switch (cif->abi)
|
|
||||||
{
|
switch (cif->abi)
|
||||||
case FFI_SYSV:
|
{
|
||||||
/*@-usedef@*/
|
case FFI_SYSV:
|
||||||
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes,
|
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
|
||||||
cif->flags, ecif.rvalue, fn);
|
ecif.rvalue, fn);
|
||||||
/*@=usedef@*/
|
break;
|
||||||
break;
|
|
||||||
#ifdef X86_WIN32
|
#ifdef X86_WIN32
|
||||||
case FFI_STDCALL:
|
case FFI_STDCALL:
|
||||||
/*@-usedef@*/
|
ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
|
||||||
ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes,
|
ecif.rvalue, fn);
|
||||||
cif->flags, ecif.rvalue, fn);
|
break;
|
||||||
/*@=usedef@*/
|
|
||||||
break;
|
|
||||||
#endif /* X86_WIN32 */
|
#endif /* X86_WIN32 */
|
||||||
default:
|
default:
|
||||||
FFI_ASSERT(0);
|
FFI_ASSERT(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !FFI_NO_RAW_API
|
#endif
|
||||||
//#endif // !__x86_64__
|
#endif // __i386__
|
||||||
#endif // __i386__
|
|
Loading…
Reference in New Issue