MIPS: fix some N32 test failure (#701) Some go closure and pointer testcase fails. These failures is not introduced by the complex support code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
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)