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 */
|
/* Low level routine for calling O32 functions */
|
||||||
extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int),
|
extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int),
|
||||||
extended_cif *, unsigned,
|
extended_cif *, unsigned,
|
||||||
unsigned, unsigned *, void (*)(void));
|
unsigned, unsigned *, void (*)(void), void *closure);
|
||||||
|
|
||||||
/* Low level routine for calling N32 functions */
|
/* Low level routine for calling N32 functions */
|
||||||
extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int),
|
extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int),
|
||||||
extended_cif *, unsigned,
|
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;
|
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:
|
||||||
case FFI_O32_SOFT_FLOAT:
|
case FFI_O32_SOFT_FLOAT:
|
||||||
ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
|
ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
|
||||||
cif->flags, ecif.rvalue, fn);
|
cif->flags, ecif.rvalue, fn, closure);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -642,7 +643,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
|
ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
|
||||||
cif->flags, rvalue_copy, fn);
|
cif->flags, rvalue_copy, fn, closure);
|
||||||
if (copy_rvalue)
|
if (copy_rvalue)
|
||||||
memcpy(ecif.rvalue, rvalue_copy + copy_offset, cif->rtype->size);
|
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 FFI_CLOSURES
|
||||||
#if defined(FFI_MIPS_O32)
|
#if defined(FFI_MIPS_O32)
|
||||||
extern void ffi_closure_O32(void);
|
extern void ffi_closure_O32(void);
|
||||||
@@ -762,17 +777,17 @@ ffi_prep_closure_loc (ffi_closure *closure,
|
|||||||
* Based on the similar routine for sparc.
|
* Based on the similar routine for sparc.
|
||||||
*/
|
*/
|
||||||
int
|
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,
|
void *rvalue, ffi_arg *ar,
|
||||||
double *fpr)
|
double *fpr)
|
||||||
{
|
{
|
||||||
ffi_cif *cif;
|
|
||||||
void **avaluep;
|
void **avaluep;
|
||||||
ffi_arg *avalue;
|
ffi_arg *avalue;
|
||||||
ffi_type **arg_types;
|
ffi_type **arg_types;
|
||||||
int i, avn, argn, seen_int;
|
int i, avn, argn, seen_int;
|
||||||
|
|
||||||
cif = closure->cif;
|
|
||||||
avalue = alloca (cif->nargs * sizeof (ffi_arg));
|
avalue = alloca (cif->nargs * sizeof (ffi_arg));
|
||||||
avaluep = 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. */
|
/* Invoke the closure. */
|
||||||
(closure->fun) (cif, rvalue, avaluep, closure->user_data);
|
fun(cif, rvalue, avaluep, user_data);
|
||||||
|
|
||||||
if (cif->abi == FFI_O32_SOFT_FLOAT)
|
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
|
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,
|
void *rvalue, ffi_arg *ar,
|
||||||
ffi_arg *fpr)
|
ffi_arg *fpr)
|
||||||
{
|
{
|
||||||
ffi_cif *cif;
|
|
||||||
void **avaluep;
|
void **avaluep;
|
||||||
ffi_arg *avalue;
|
ffi_arg *avalue;
|
||||||
ffi_type **arg_types;
|
ffi_type **arg_types;
|
||||||
@@ -928,7 +944,6 @@ ffi_closure_mips_inner_N32 (ffi_closure *closure,
|
|||||||
int soft_float;
|
int soft_float;
|
||||||
ffi_arg *argp;
|
ffi_arg *argp;
|
||||||
|
|
||||||
cif = closure->cif;
|
|
||||||
soft_float = cif->abi == FFI_N64_SOFT_FLOAT
|
soft_float = cif->abi == FFI_N64_SOFT_FLOAT
|
||||||
|| cif->abi == FFI_N32_SOFT_FLOAT;
|
|| cif->abi == FFI_N32_SOFT_FLOAT;
|
||||||
avalue = alloca (cif->nargs * sizeof (ffi_arg));
|
avalue = alloca (cif->nargs * sizeof (ffi_arg));
|
||||||
@@ -1040,11 +1055,48 @@ ffi_closure_mips_inner_N32 (ffi_closure *closure,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Invoke the 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);
|
return cif->flags >> (FFI_FLAG_BITS * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* FFI_MIPS_N32 */
|
#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 */
|
#endif /* FFI_CLOSURES */
|
||||||
|
|||||||
@@ -231,10 +231,12 @@ typedef enum ffi_abi {
|
|||||||
|
|
||||||
#if defined(FFI_MIPS_O32)
|
#if defined(FFI_MIPS_O32)
|
||||||
#define FFI_CLOSURES 1
|
#define FFI_CLOSURES 1
|
||||||
|
#define FFI_GO_CLOSURES 1
|
||||||
#define FFI_TRAMPOLINE_SIZE 20
|
#define FFI_TRAMPOLINE_SIZE 20
|
||||||
#else
|
#else
|
||||||
/* N32/N64. */
|
/* N32/N64. */
|
||||||
# define FFI_CLOSURES 1
|
# define FFI_CLOSURES 1
|
||||||
|
#define FFI_GO_CLOSURES 1
|
||||||
#if _MIPS_SIM==_ABI64
|
#if _MIPS_SIM==_ABI64
|
||||||
#define FFI_TRAMPOLINE_SIZE 52
|
#define FFI_TRAMPOLINE_SIZE 52
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#define flags a3
|
#define flags a3
|
||||||
#define raddr a4
|
#define raddr a4
|
||||||
#define fn a5
|
#define fn a5
|
||||||
|
#define closure a6
|
||||||
|
|
||||||
#define SIZEOF_FRAME ( 8 * FFI_SIZEOF_ARG )
|
#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 flags, 3*FFI_SIZEOF_ARG($fp) # flags
|
||||||
REG_S raddr, 4*FFI_SIZEOF_ARG($fp) # raddr
|
REG_S raddr, 4*FFI_SIZEOF_ARG($fp) # raddr
|
||||||
REG_S fn, 5*FFI_SIZEOF_ARG($fp) # fn
|
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
|
# Allocate at least 4 words in the argstack
|
||||||
move v0, bytes
|
move v0, bytes
|
||||||
@@ -198,6 +200,9 @@ callit:
|
|||||||
# Load the function pointer
|
# Load the function pointer
|
||||||
REG_L t9, 5*FFI_SIZEOF_ARG($fp)
|
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.
|
# If the return value pointer is NULL, assume no return value.
|
||||||
REG_L t5, 4*FFI_SIZEOF_ARG($fp)
|
REG_L t5, 4*FFI_SIZEOF_ARG($fp)
|
||||||
beqz t5, noretval
|
beqz t5, noretval
|
||||||
@@ -405,6 +410,38 @@ epilogue:
|
|||||||
#define RA_OFF2 (1 * FFI_SIZEOF_ARG)
|
#define RA_OFF2 (1 * FFI_SIZEOF_ARG)
|
||||||
#define GP_OFF2 (0 * 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
|
.align 2
|
||||||
.globl ffi_closure_N32
|
.globl ffi_closure_N32
|
||||||
.ent ffi_closure_N32
|
.ent ffi_closure_N32
|
||||||
@@ -418,14 +455,25 @@ ffi_closure_N32:
|
|||||||
.cpsetup t9, GP_OFF2, ffi_closure_N32
|
.cpsetup t9, GP_OFF2, ffi_closure_N32
|
||||||
REG_S ra, RA_OFF2($sp) # Save return address
|
REG_S ra, RA_OFF2($sp) # Save return address
|
||||||
.LCFI6:
|
.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 a0, A0_OFF2($sp)
|
||||||
REG_S a1, A1_OFF2($sp)
|
REG_S a1, A1_OFF2($sp)
|
||||||
REG_S a2, A2_OFF2($sp)
|
REG_S a2, A2_OFF2($sp)
|
||||||
REG_S a3, A3_OFF2($sp)
|
REG_S a3, A3_OFF2($sp)
|
||||||
REG_S a4, A4_OFF2($sp)
|
REG_S a4, A4_OFF2($sp)
|
||||||
REG_S a5, A5_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 a6, A6_OFF2($sp)
|
||||||
REG_S a7, A7_OFF2($sp)
|
REG_S a7, A7_OFF2($sp)
|
||||||
|
|
||||||
@@ -439,12 +487,6 @@ ffi_closure_N32:
|
|||||||
s.d $f18, F18_OFF2($sp)
|
s.d $f18, F18_OFF2($sp)
|
||||||
s.d $f19, F19_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
|
jalr t9
|
||||||
|
|
||||||
# Return flags are in v0
|
# Return flags are in v0
|
||||||
|
|||||||
@@ -132,6 +132,9 @@ pass_f_d:
|
|||||||
l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float
|
l.d $f14, 2*FFI_SIZEOF_ARG($sp) # passing double and float
|
||||||
|
|
||||||
call_it:
|
call_it:
|
||||||
|
# Load the static chain pointer
|
||||||
|
REG_L t7, SIZEOF_FRAME + 6*FFI_SIZEOF_ARG($fp)
|
||||||
|
|
||||||
# Load the function pointer
|
# Load the function pointer
|
||||||
REG_L t9, SIZEOF_FRAME + 5*FFI_SIZEOF_ARG($fp)
|
REG_L t9, SIZEOF_FRAME + 5*FFI_SIZEOF_ARG($fp)
|
||||||
|
|
||||||
@@ -204,13 +207,15 @@ $LFE0:
|
|||||||
-8 - f14 (le low, be high)
|
-8 - f14 (le low, be high)
|
||||||
-9 - f12 (le high, be low)
|
-9 - f12 (le high, be low)
|
||||||
-10 - f12 (le low, be high)
|
-10 - f12 (le low, be high)
|
||||||
-11 - Called function a3 save
|
-11 - Called function a5 save
|
||||||
-12 - Called function a2 save
|
-12 - Called function a4 save
|
||||||
-13 - Called function a1 save
|
-13 - Called function a3 save
|
||||||
-14 - Called function a0 save, our sp and fp point here
|
-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 A3_OFF2 (SIZEOF_FRAME2 + 3 * FFI_SIZEOF_ARG)
|
||||||
#define A2_OFF2 (SIZEOF_FRAME2 + 2 * FFI_SIZEOF_ARG)
|
#define A2_OFF2 (SIZEOF_FRAME2 + 2 * FFI_SIZEOF_ARG)
|
||||||
#define A1_OFF2 (SIZEOF_FRAME2 + 1 * 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_1_0_OFF2 (SIZEOF_FRAME2 - 8 * FFI_SIZEOF_ARG)
|
||||||
#define FA_0_1_OFF2 (SIZEOF_FRAME2 - 9 * 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 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
|
.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
|
.align 2
|
||||||
.globl ffi_closure_O32
|
.globl ffi_closure_O32
|
||||||
.ent ffi_closure_O32
|
.ent ffi_closure_O32
|
||||||
@@ -265,12 +323,21 @@ $LCFI7:
|
|||||||
s.d $f12, FA_0_0_OFF2($fp)
|
s.d $f12, FA_0_0_OFF2($fp)
|
||||||
s.d $f14, FA_1_0_OFF2($fp)
|
s.d $f14, FA_1_0_OFF2($fp)
|
||||||
1:
|
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
|
la t9, ffi_closure_mips_inner_O32
|
||||||
move a0, $12 # Pointer to the ffi_closure
|
# Call ffi_closure_mips_inner_O32 to do the work.
|
||||||
addu a1, $fp, V0_OFF2
|
|
||||||
addu a2, $fp, A0_OFF2
|
|
||||||
addu a3, $fp, FA_0_0_OFF2
|
|
||||||
jalr t9
|
jalr t9
|
||||||
|
|
||||||
# Load the return value into the appropriate register.
|
# Load the return value into the appropriate register.
|
||||||
|
|||||||
Reference in New Issue
Block a user