add support for go closure support on mips
This commit is contained in:
@@ -581,14 +581,15 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
/* Low level routine for calling O32 functions */
|
||||
extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int),
|
||||
extended_cif *, unsigned,
|
||||
unsigned, unsigned *, void (*)(void));
|
||||
unsigned, unsigned *, void (*)(void), void *closure);
|
||||
|
||||
/* Low level routine for calling N32 functions */
|
||||
extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int),
|
||||
extended_cif *, unsigned,
|
||||
unsigned, void *, void (*)(void));
|
||||
unsigned, void *, void (*)(void), void *closure);
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
void ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||
void **avalue, void *closure)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
@@ -610,7 +611,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
case FFI_O32:
|
||||
case FFI_O32_SOFT_FLOAT:
|
||||
ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
cif->flags, ecif.rvalue, fn, closure);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -642,7 +643,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
#endif
|
||||
}
|
||||
ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, rvalue_copy, fn);
|
||||
cif->flags, rvalue_copy, fn, closure);
|
||||
if (copy_rvalue)
|
||||
memcpy(ecif.rvalue, rvalue_copy + copy_offset, cif->rtype->size);
|
||||
}
|
||||
@@ -655,6 +656,20 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
ffi_call_int (cif, fn, rvalue, avalue, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||
void **avalue, void *closure)
|
||||
{
|
||||
ffi_call_int (cif, fn, rvalue, avalue, closure);
|
||||
}
|
||||
|
||||
|
||||
#if FFI_CLOSURES
|
||||
#if defined(FFI_MIPS_O32)
|
||||
extern void ffi_closure_O32(void);
|
||||
@@ -762,17 +777,17 @@ ffi_prep_closure_loc (ffi_closure *closure,
|
||||
* Based on the similar routine for sparc.
|
||||
*/
|
||||
int
|
||||
ffi_closure_mips_inner_O32 (ffi_closure *closure,
|
||||
ffi_closure_mips_inner_O32 (ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data;
|
||||
void *rvalue, ffi_arg *ar,
|
||||
double *fpr)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avaluep;
|
||||
ffi_arg *avalue;
|
||||
ffi_type **arg_types;
|
||||
int i, avn, argn, seen_int;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca (cif->nargs * sizeof (ffi_arg));
|
||||
avaluep = alloca (cif->nargs * sizeof (ffi_arg));
|
||||
|
||||
@@ -840,7 +855,7 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure,
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avaluep, closure->user_data);
|
||||
fun(cif, rvalue, avaluep, user_data);
|
||||
|
||||
if (cif->abi == FFI_O32_SOFT_FLOAT)
|
||||
{
|
||||
@@ -916,11 +931,12 @@ copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type,
|
||||
*
|
||||
*/
|
||||
int
|
||||
ffi_closure_mips_inner_N32 (ffi_closure *closure,
|
||||
ffi_closure_mips_inner_N32 (ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *rvalue, ffi_arg *ar,
|
||||
ffi_arg *fpr)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avaluep;
|
||||
ffi_arg *avalue;
|
||||
ffi_type **arg_types;
|
||||
@@ -928,7 +944,6 @@ ffi_closure_mips_inner_N32 (ffi_closure *closure,
|
||||
int soft_float;
|
||||
ffi_arg *argp;
|
||||
|
||||
cif = closure->cif;
|
||||
soft_float = cif->abi == FFI_N64_SOFT_FLOAT
|
||||
|| cif->abi == FFI_N32_SOFT_FLOAT;
|
||||
avalue = alloca (cif->nargs * sizeof (ffi_arg));
|
||||
@@ -1040,11 +1055,48 @@ ffi_closure_mips_inner_N32 (ffi_closure *closure,
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avaluep, closure->user_data);
|
||||
fun (cif, rvalue, avaluep, user_data);
|
||||
|
||||
return cif->flags >> (FFI_FLAG_BITS * 8);
|
||||
}
|
||||
|
||||
#endif /* FFI_MIPS_N32 */
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
extern void ffi_closure_O32(void);
|
||||
#else
|
||||
extern void ffi_closure_N32(void);
|
||||
#endif /* FFI_MIPS_O32 */
|
||||
|
||||
void
|
||||
ffi_status
|
||||
ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*))
|
||||
{
|
||||
void * fn;
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
if (cif->abi != FFI_O32 && cif->abi != FFI_O32_SOFT_FLOAT)
|
||||
return FFI_BAD_ABI;
|
||||
fn = ffi_go_closure_O32;
|
||||
#else
|
||||
#if _MIPS_SIM ==_ABIN32
|
||||
if (cif->abi != FFI_N32
|
||||
&& cif->abi != FFI_N32_SOFT_FLOAT)
|
||||
return FFI_BAD_ABI;
|
||||
#else
|
||||
if (cif->abi != FFI_N64
|
||||
&& cif->abi != FFI_N64_SOFT_FLOAT)
|
||||
return FFI_BAD_ABI;
|
||||
#endif
|
||||
fn = ffi_go_closure_N32;
|
||||
#endif /* FFI_MIPS_O32 */
|
||||
|
||||
closure->tramp = (void *)fn;
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
|
||||
@@ -231,10 +231,12 @@ typedef enum ffi_abi {
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_GO_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 20
|
||||
#else
|
||||
/* N32/N64. */
|
||||
# define FFI_CLOSURES 1
|
||||
#define FFI_GO_CLOSURES 1
|
||||
#if _MIPS_SIM==_ABI64
|
||||
#define FFI_TRAMPOLINE_SIZE 52
|
||||
#else
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#define flags a3
|
||||
#define raddr a4
|
||||
#define fn a5
|
||||
#define closure a6
|
||||
|
||||
#define SIZEOF_FRAME ( 8 * FFI_SIZEOF_ARG )
|
||||
|
||||
@@ -67,6 +68,7 @@ ffi_call_N32:
|
||||
REG_S flags, 3*FFI_SIZEOF_ARG($fp) # flags
|
||||
REG_S raddr, 4*FFI_SIZEOF_ARG($fp) # raddr
|
||||
REG_S fn, 5*FFI_SIZEOF_ARG($fp) # fn
|
||||
REG_S closure, 6*FFI_SIZEOF_ARG($fp) # closure
|
||||
|
||||
# Allocate at least 4 words in the argstack
|
||||
move v0, bytes
|
||||
@@ -198,6 +200,9 @@ callit:
|
||||
# Load the function pointer
|
||||
REG_L t9, 5*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# install the static chain(t7=$15)
|
||||
REG_L t7, 6*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# If the return value pointer is NULL, assume no return value.
|
||||
REG_L t5, 4*FFI_SIZEOF_ARG($fp)
|
||||
beqz t5, noretval
|
||||
@@ -405,6 +410,38 @@ epilogue:
|
||||
#define RA_OFF2 (1 * FFI_SIZEOF_ARG)
|
||||
#define GP_OFF2 (0 * FFI_SIZEOF_ARG)
|
||||
|
||||
.align 2
|
||||
.globl ffi_go_closure_N32
|
||||
.ent ffi_go_closure_N32
|
||||
ffi_go_closure_N32:
|
||||
.frame $sp, SIZEOF_FRAME2, ra
|
||||
.mask 0x90000000,-(SIZEOF_FRAME2 - RA_OFF2)
|
||||
.fmask 0x00000000,0
|
||||
SUBU $sp, SIZEOF_FRAME2
|
||||
|
||||
.cpsetup t9, GP_OFF2, ffi_closure_N32
|
||||
REG_S ra, RA_OFF2($sp) # Save return address
|
||||
|
||||
REG_S a0, A0_OFF2($sp)
|
||||
REG_S a1, A1_OFF2($sp)
|
||||
REG_S a2, A2_OFF2($sp)
|
||||
REG_S a3, A3_OFF2($sp)
|
||||
REG_S a4, A4_OFF2($sp)
|
||||
REG_S a5, A5_OFF2($sp)
|
||||
|
||||
# Call ffi_closure_mips_inner_N32 to do the real work.
|
||||
LA t9, ffi_closure_mips_inner_N32
|
||||
REG_L a0, FFI_SIZE_OF_ARG($15) # cif
|
||||
REG_L a1, 2*FFI_SIZE_OF_ARG($15) # fun
|
||||
mov a2, t7 # userdata=closure
|
||||
ADDU a3, $sp, V0_OFF2 # rvalue
|
||||
ADDU a4, $sp, A0_OFF2 # ar
|
||||
ADDU a5, $sp, F12_OFF2 # fpr
|
||||
|
||||
b $do_closure
|
||||
|
||||
.end ffi_go_closure_N32
|
||||
|
||||
.align 2
|
||||
.globl ffi_closure_N32
|
||||
.ent ffi_closure_N32
|
||||
@@ -418,14 +455,25 @@ ffi_closure_N32:
|
||||
.cpsetup t9, GP_OFF2, ffi_closure_N32
|
||||
REG_S ra, RA_OFF2($sp) # Save return address
|
||||
.LCFI6:
|
||||
# Store all possible argument registers. If there are more than
|
||||
# fit in registers, then they were stored on the stack.
|
||||
REG_S a0, A0_OFF2($sp)
|
||||
REG_S a1, A1_OFF2($sp)
|
||||
REG_S a2, A2_OFF2($sp)
|
||||
REG_S a3, A3_OFF2($sp)
|
||||
REG_S a4, A4_OFF2($sp)
|
||||
REG_S a5, A5_OFF2($sp)
|
||||
|
||||
# Call ffi_closure_mips_inner_N32 to do the real work.
|
||||
LA t9, ffi_closure_mips_inner_N32
|
||||
REG_L a0, FFI_TRAMPOLINE_SIZE($12) # cif
|
||||
REG_L a1, FFI_TRAMPOLINE_SIZE + FFI_SIZE_OF_ARG($12) # fun
|
||||
REG_L a2, FFI_TRAMPOLINE_SIZE + 2*FFI_SIZE_OF_ARG($12) # user_data
|
||||
ADDU a3, $sp, V0_OFF2
|
||||
ADDU a4, $sp, A0_OFF2
|
||||
ADDU a5, $sp, F12_OFF2
|
||||
|
||||
$do_closure:
|
||||
# Store all possible argument registers. If there are more than
|
||||
# fit in registers, then they were stored on the stack.
|
||||
REG_S a6, A6_OFF2($sp)
|
||||
REG_S a7, A7_OFF2($sp)
|
||||
|
||||
@@ -439,12 +487,6 @@ ffi_closure_N32:
|
||||
s.d $f18, F18_OFF2($sp)
|
||||
s.d $f19, F19_OFF2($sp)
|
||||
|
||||
# Call ffi_closure_mips_inner_N32 to do the real work.
|
||||
LA t9, ffi_closure_mips_inner_N32
|
||||
move a0, $12 # Pointer to the ffi_closure
|
||||
ADDU a1, $sp, V0_OFF2
|
||||
ADDU a2, $sp, A0_OFF2
|
||||
ADDU a3, $sp, F12_OFF2
|
||||
jalr t9
|
||||
|
||||
# Return flags are in v0
|
||||
|
||||
@@ -132,6 +132,9 @@ pass_f_d:
|
||||
l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float
|
||||
|
||||
call_it:
|
||||
# Load the static chain pointer
|
||||
REG_L t7, SIZEOF_FRAME + 6*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# Load the function pointer
|
||||
REG_L t9, SIZEOF_FRAME + 5*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
@@ -204,13 +207,15 @@ $LFE0:
|
||||
-8 - f14 (le low, be high)
|
||||
-9 - f12 (le high, be low)
|
||||
-10 - f12 (le low, be high)
|
||||
-11 - Called function a3 save
|
||||
-12 - Called function a2 save
|
||||
-13 - Called function a1 save
|
||||
-14 - Called function a0 save, our sp and fp point here
|
||||
-11 - Called function a5 save
|
||||
-12 - Called function a4 save
|
||||
-13 - Called function a3 save
|
||||
-14 - Called function a2 save
|
||||
-15 - Called function a1 save
|
||||
-16 - Called function a0 save, our sp and fp point here
|
||||
*/
|
||||
|
||||
#define SIZEOF_FRAME2 (14 * FFI_SIZEOF_ARG)
|
||||
#define SIZEOF_FRAME2 (16 * FFI_SIZEOF_ARG)
|
||||
#define A3_OFF2 (SIZEOF_FRAME2 + 3 * FFI_SIZEOF_ARG)
|
||||
#define A2_OFF2 (SIZEOF_FRAME2 + 2 * FFI_SIZEOF_ARG)
|
||||
#define A1_OFF2 (SIZEOF_FRAME2 + 1 * FFI_SIZEOF_ARG)
|
||||
@@ -225,8 +230,61 @@ $LFE0:
|
||||
#define FA_1_0_OFF2 (SIZEOF_FRAME2 - 8 * FFI_SIZEOF_ARG)
|
||||
#define FA_0_1_OFF2 (SIZEOF_FRAME2 - 9 * FFI_SIZEOF_ARG)
|
||||
#define FA_0_0_OFF2 (SIZEOF_FRAME2 - 10 * FFI_SIZEOF_ARG)
|
||||
#define CALLED_A5_OFF2 (SIZEOF_FRAME2 - 11 * FFI_SIZEOF_ARG)
|
||||
#define CALLED_A4_OFF2 (SIZEOF_FRAME2 - 12 * FFI_SIZEOF_ARG)
|
||||
|
||||
.text
|
||||
|
||||
.align 2
|
||||
.globl ffi_go_closure_O32
|
||||
.ent ffi_go_closure_O32
|
||||
ffi_go_closure_O32:
|
||||
# Prologue
|
||||
.frame $fp, SIZEOF_FRAME2, ra
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
.set reorder
|
||||
SUBU $sp, SIZEOF_FRAME2
|
||||
.cprestore GP_OFF2
|
||||
|
||||
REG_S $16, S0_OFF2($sp) # Save s0
|
||||
REG_S $fp, FP_OFF2($sp) # Save frame pointer
|
||||
REG_S ra, RA_OFF2($sp) # Save return address
|
||||
|
||||
move $fp, $sp
|
||||
|
||||
REG_S a0, A0_OFF2($fp)
|
||||
REG_S a1, A1_OFF2($fp)
|
||||
REG_S a2, A2_OFF2($fp)
|
||||
REG_S a3, A3_OFF2($fp)
|
||||
|
||||
# Load ABI enum to s0
|
||||
REG_L $16, 4($15) # cif
|
||||
REG_L $16, 0($16) # abi is first member.
|
||||
|
||||
li $13, 1 # FFI_O32
|
||||
bne $16, $13, 1f # Skip fp save if FFI_O32_SOFT_FLOAT
|
||||
|
||||
# Store all possible float/double registers.
|
||||
s.d $f12, FA_0_0_OFF2($fp)
|
||||
s.d $f14, FA_1_0_OFF2($fp)
|
||||
|
||||
# prepare arguments for ffi_closure_mips_inner_O32
|
||||
REG_L a0, 4($15) # cif
|
||||
REG_L a1, 8($15) # fun
|
||||
mov a2, $15 # user_data = go closure
|
||||
addu a3, $fp, V0_OFF2 # rvalue
|
||||
|
||||
addu t9, $fp, A0_OFF2 # ar
|
||||
REG_S t9, CALLED_A4_OFF2($fp)
|
||||
|
||||
addu t9, $fp, FA_0_0_OFF2 #fpr
|
||||
REG_S t9, CALLED_A5_OFF2($fp)
|
||||
|
||||
b $do_closure
|
||||
|
||||
.end ffi_go_closure_O32
|
||||
|
||||
.align 2
|
||||
.globl ffi_closure_O32
|
||||
.ent ffi_closure_O32
|
||||
@@ -265,12 +323,21 @@ $LCFI7:
|
||||
s.d $f12, FA_0_0_OFF2($fp)
|
||||
s.d $f14, FA_1_0_OFF2($fp)
|
||||
1:
|
||||
# Call ffi_closure_mips_inner_O32 to do the work.
|
||||
# prepare arguments for ffi_closure_mips_inner_O32
|
||||
REG_L a0, 20($12) # cif pointer follows tramp.
|
||||
REG_L a1, 24($12) # fun
|
||||
REG_L a2, 28($12) # user_data
|
||||
addu a3, $fp, V0_OFF2 # rvalue
|
||||
|
||||
addu t9, $fp, A0_OFF2 # ar
|
||||
REG_S t9, CALLED_A4_OFF2($fp)
|
||||
|
||||
addu t9, $fp, FA_0_0_OFF2 #fpr
|
||||
REG_S t9, CALLED_A5_OFF2($fp)
|
||||
|
||||
$do_closure:
|
||||
la t9, ffi_closure_mips_inner_O32
|
||||
move a0, $12 # Pointer to the ffi_closure
|
||||
addu a1, $fp, V0_OFF2
|
||||
addu a2, $fp, A0_OFF2
|
||||
addu a3, $fp, FA_0_0_OFF2
|
||||
# Call ffi_closure_mips_inner_O32 to do the work.
|
||||
jalr t9
|
||||
|
||||
# Load the return value into the appropriate register.
|
||||
|
||||
Reference in New Issue
Block a user