summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYunQiang Su <syq@debian.org>2022-05-16 09:47:11 +0800
committerGitHub <noreply@github.com>2022-05-15 21:47:11 -0400
commit2e825e219fa06d308b9a9863d70320606d67490d (patch)
tree8856f4954c263be74aebba36457a0e10d6c79e6c /src
parent1f1c33753b65a75216770928018e8932168e8908 (diff)
downloadlibffi-2e825e219fa06d308b9a9863d70320606d67490d.tar.gz
MIPS: fix some N32 test failure (#701)
Some go closure and pointer testcase fails. These failures is not introduced by the complex support code.
Diffstat (limited to 'src')
-rw-r--r--src/mips/ffi.c26
-rw-r--r--src/mips/ffitarget.h9
-rw-r--r--src/mips/n32.S93
3 files changed, 88 insertions, 40 deletions
diff --git a/src/mips/ffi.c b/src/mips/ffi.c
index 77bf3db..e704325 100644
--- a/src/mips/ffi.c
+++ b/src/mips/ffi.c
@@ -84,6 +84,8 @@ static void ffi_prep_args(char *stack,
memset(stack, 0, bytes);
#ifdef FFI_MIPS_N32
+ int soft_float = (ecif->cif->abi == FFI_N32_SOFT_FLOAT
+ || ecif->cif->abi == FFI_N64_SOFT_FLOAT);
/* If more than 8 double words are used, the remainder go
on the stack. We reorder stuff on the stack here to
support this easily. */
@@ -149,7 +151,7 @@ static void ffi_prep_args(char *stack,
if (type == FFI_TYPE_POINTER)
type = (ecif->cif->abi == FFI_N64
|| ecif->cif->abi == FFI_N64_SOFT_FLOAT)
- ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
+ ? FFI_TYPE_SINT64 : FFI_TYPE_UINT32;
if (i < 8 && (ecif->cif->abi == FFI_N32_SOFT_FLOAT
|| ecif->cif->abi == FFI_N64_SOFT_FLOAT))
@@ -204,9 +206,10 @@ static void ffi_prep_args(char *stack,
/* expand from 4+4 to 8+8 if pass with fpr reg */
/* argp will wind back to stack when we process all of reg args */
/* all var_args passed with gpr, should be expand */
- if((*p_arg)->elements[0]->type == FFI_TYPE_FLOAT
- && argp>=argp_f
- && i < ecif->cif->mips_nfixedargs)
+ if(!soft_float
+ && (*p_arg)->elements[0]->type == FFI_TYPE_FLOAT
+ && argp>=argp_f
+ && i < ecif->cif->mips_nfixedargs)
{
*(float *) argp = *(float *)(* p_argv);
argp += z;
@@ -644,7 +647,7 @@ static ffi_status ffi_prep_cif_machdep_int(ffi_cif *cif, unsigned nfixedargs)
case FFI_TYPE_POINTER:
if (cif->abi == FFI_N32_SOFT_FLOAT || cif->abi == FFI_N32)
- cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
+ cif->flags += FFI_TYPE_UINT32 << (FFI_FLAG_BITS * 8);
else
cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
break;
@@ -668,8 +671,9 @@ static ffi_status ffi_prep_cif_machdep_int(ffi_cif *cif, unsigned nfixedargs)
two doubles. */
if (soft_float)
{
- cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
- cif->flags += FFI_TYPE_SMALLSTRUCT2 << (4 + (FFI_FLAG_BITS * 8));
+ /* if ret is long double, the ret is given by v0 and a0, no idea why
+ * Let's us VOID | VOID | LONGDOUBLE for it*/
+ cif->flags += FFI_TYPE_LONGDOUBLE << (FFI_FLAG_BITS * 8);
}
else
{
@@ -694,6 +698,10 @@ static ffi_status ffi_prep_cif_machdep_int(ffi_cif *cif, unsigned nfixedargs)
case FFI_TYPE_INT:
type = FFI_TYPE_SMALLSTRUCT2;
break;
+ case FFI_TYPE_LONGDOUBLE:
+ type = FFI_TYPE_LONGDOUBLE;
+ break;
+ case FFI_TYPE_FLOAT:
default:
type = FFI_TYPE_SMALLSTRUCT;
}
@@ -1194,10 +1202,10 @@ ffi_closure_mips_inner_N32 (ffi_cif *cif,
/* The size of a pointer depends on the ABI */
if (type == FFI_TYPE_POINTER)
type = (cif->abi == FFI_N64 || cif->abi == FFI_N64_SOFT_FLOAT)
- ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
+ ? FFI_TYPE_SINT64 : FFI_TYPE_UINT32;
if (soft_float && type == FFI_TYPE_FLOAT)
- type = FFI_TYPE_UINT32;
+ type = FFI_TYPE_SINT32;
switch (type)
{
diff --git a/src/mips/ffitarget.h b/src/mips/ffitarget.h
index 61d04f9..294c3ba 100644
--- a/src/mips/ffitarget.h
+++ b/src/mips/ffitarget.h
@@ -112,10 +112,11 @@
#define FFI_TYPE_STRUCT_SMALL 93
#define FFI_TYPE_STRUCT_SMALL2 109
-#define FFI_TYPE_COMPLEX_II 95
-#define FFI_TYPE_COMPLEX_FF 47
-#define FFI_TYPE_COMPLEX_DD 63
-#define FFI_TYPE_COMPLEX_LDLD 79
+#define FFI_TYPE_COMPLEX_SMALL 95
+#define FFI_TYPE_COMPLEX_SMALL2 111
+#define FFI_TYPE_COMPLEX_FF 47
+#define FFI_TYPE_COMPLEX_DD 63
+#define FFI_TYPE_COMPLEX_LDLD 79
/* and for n32 soft float, add 16 * 2^4 */
#define FFI_TYPE_STRUCT_D_SOFT 317
diff --git a/src/mips/n32.S b/src/mips/n32.S
index f9bfa5a..e1938d1 100644
--- a/src/mips/n32.S
+++ b/src/mips/n32.S
@@ -236,14 +236,21 @@ callit:
# Shift the return type flag over
SRL t6, 8*FFI_FLAG_BITS
- beq t6, FFI_TYPE_SINT32, retint
- bne t6, FFI_TYPE_INT, retfloat
+ beq t6, FFI_TYPE_SINT32, retint
+ bne t6, FFI_TYPE_INT, retuint32
retint:
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
REG_S v0, 0(t4)
b epilogue
+retuint32:
+ bne t6, FFI_TYPE_UINT32, retfloat
+ jal t9
+ REG_L t4, 4*FFI_SIZEOF_ARG($fp)
+ sw v0, 0(t4)
+ b epilogue
+
retfloat:
#ifndef __mips_soft_float
bne t6, FFI_TYPE_FLOAT, retdouble
@@ -259,7 +266,7 @@ retdouble:
s.d $f0, 0(t4)
b epilogue
-retstruct_d:
+retstruct_d:
bne t6, FFI_TYPE_STRUCT_D, retstruct_f
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
@@ -346,7 +353,7 @@ retstruct_d_d_soft:
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
sd v0, 0(t4)
- sd v1, 8(t4)
+ sd a0, 8(t4) # not typo, it is a0, I have no idea, gcc does do it
b epilogue
retstruct_f_f_soft:
@@ -370,7 +377,7 @@ retstruct_f_d_soft:
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
sw v0, 0(t4)
- sd v1, 8(t4)
+ sd a0, 8(t4) # not typo, it is a0, I have no idea, gcc does do it
b epilogue
retstruct_small:
@@ -381,21 +388,37 @@ retstruct_small:
b epilogue
retstruct_small2:
- bne t6, FFI_TYPE_STRUCT_SMALL2, retcomplex_i_i
+ bne t6, FFI_TYPE_STRUCT_SMALL2, retlongdouble_soft
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
REG_S v0, 0(t4)
REG_S v1, 8(t4)
b epilogue
-retcomplex_i_i:
- bne t6, FFI_TYPE_COMPLEX_II, retstruct
+retlongdouble_soft:
+ bne t6, FFI_TYPE_LONGDOUBLE, retcomplex_small
jal t9
REG_L t4, 4*FFI_SIZEOF_ARG($fp)
REG_S v0, 0(t4)
+ REG_S a0, 8(t4) # not typo, it is a0, I have no idea, gcc does do it
b epilogue
-retstruct:
+retcomplex_small:
+ bne t6, FFI_TYPE_COMPLEX_SMALL, retcomplex_small2
+ jal t9
+ REG_L t4, 4*FFI_SIZEOF_ARG($fp)
+ REG_S v0, 0(t4)
+ b epilogue
+
+retcomplex_small2:
+ bne t6, FFI_TYPE_COMPLEX_SMALL2, retstruct
+ jal t9
+ REG_L t4, 4*FFI_SIZEOF_ARG($fp)
+ REG_S v0, 0(t4)
+ REG_S v1, 8(t4)
+ b epilogue
+
+retstruct:
noretval:
jal t9
@@ -489,8 +512,13 @@ ffi_go_closure_N32:
# Call ffi_closure_mips_inner_N32 to do the real work.
LA t9, ffi_closure_mips_inner_N32
+#if _MIPS_SIM==_ABIN32
+ lw a0, 4($15) # cif
+ lw a1, 8($15) # fun
+#else
REG_L a0, 8($15) # cif
REG_L a1, 16($15) # fun
+#endif
move a2, t7 # userdata=closure
ADDU a3, $sp, V0_OFF2 # rvalue
ADDU a4, $sp, A0_OFF2 # ar
@@ -558,10 +586,15 @@ $do_closure:
jalr t9
# Return flags are in v0
- bne v0, FFI_TYPE_SINT32, cls_retint
+ bne v0, FFI_TYPE_SINT32, cls_retuint32
lw v0, V0_OFF2($sp)
b cls_epilogue
+cls_retuint32:
+ bne v0, FFI_TYPE_UINT32, cls_retint
+ lwu v0, V0_OFF2($sp)
+ b cls_epilogue
+
cls_retint:
bne v0, FFI_TYPE_INT, cls_retfloat
REG_L v0, V0_OFF2($sp)
@@ -595,25 +628,12 @@ cls_retstruct_d_d:
b cls_epilogue
cls_retcomplex_d_d:
- bne v0, FFI_TYPE_COMPLEX_DD, cls_retcomplex_ld_ld
+ bne v0, FFI_TYPE_COMPLEX_DD, cls_retcomplex_f_f
l.d $f0, V0_OFF2($sp)
l.d $f2, V1_OFF2($sp)
b cls_epilogue
-cls_retcomplex_ld_ld:
- bne v0, FFI_TYPE_COMPLEX_LDLD, cls_retstruct_f_f
- REG_L t8, A0_OFF2($sp)
- REG_L t9, 16($sp)
- REG_S t9, 0(t8)
- REG_L t9, 24($sp)
- REG_S t9, 8(t8)
- REG_L t9, 32($sp)
- REG_S t9, 16(t8)
- REG_L t9, 40($sp)
- REG_S t9, 24(t8)
- b cls_epilogue
-
-cls_retstruct_f_f:
+cls_retstruct_f_f:
bne v0, FFI_TYPE_STRUCT_FF, cls_retcomplex_f_f
l.s $f0, V0_OFF2($sp)
l.s $f2, V1_OFF2($sp)
@@ -632,12 +652,31 @@ cls_retstruct_d_f:
b cls_epilogue
cls_retstruct_f_d:
- bne v0, FFI_TYPE_STRUCT_FD, cls_retstruct_small2
+ bne v0, FFI_TYPE_STRUCT_FD, cls_retcomplex_ld_ld
l.s $f0, V0_OFF2($sp)
l.d $f2, V1_OFF2($sp)
b cls_epilogue
+#else
+cls_longdouble_soft:
+ bne v0, FFI_TYPE_LONGDOUBLE, cls_retcomplex_ld_ld
+ REG_L v0, V0_OFF2($sp)
+ REG_L a0, V1_OFF2($sp) # not typo, it is a0, I have no idea, gcc does do it
+ b cls_epilogue
#endif
-
+
+cls_retcomplex_ld_ld:
+ bne v0, FFI_TYPE_COMPLEX_LDLD, cls_retstruct_small2
+ REG_L t8, A0_OFF2($sp)
+ REG_L t9, 16($sp)
+ REG_S t9, 0(t8)
+ REG_L t9, 24($sp)
+ REG_S t9, 8(t8)
+ REG_L t9, 32($sp)
+ REG_S t9, 16(t8)
+ REG_L t9, 40($sp)
+ REG_S t9, 24(t8)
+ b cls_epilogue
+
cls_retstruct_small2:
REG_L v0, V0_OFF2($sp)
REG_L v1, V1_OFF2($sp)