From 2e825e219fa06d308b9a9863d70320606d67490d Mon Sep 17 00:00:00 2001 From: YunQiang Su Date: Mon, 16 May 2022 09:47:11 +0800 Subject: MIPS: fix some N32 test failure (#701) Some go closure and pointer testcase fails. These failures is not introduced by the complex support code. --- src/mips/ffi.c | 26 ++++++++++----- src/mips/ffitarget.h | 9 ++--- src/mips/n32.S | 93 +++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 88 insertions(+), 40 deletions(-) (limited to 'src') 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) -- cgit v1.2.1