|
View:
New views
3 Messages
—
Rating Filter:
Alert me
|
|
|
[Patch,libffi] Add MIPS64 soft-float support to libffi.libffi is lacking support for the mips64 soft-float ABIs. In addition
be being annoying in and of itself, it also causes libjava failures. The patch adds soft-float support for both n32 and n64 ABIs. Quite a bit of code had to be touched as the rules for passing structures containing floating point elements are a slightly complex. While working on the patch I noticed that we were failing a bunch if pointer passing test cases that where recently added. It turns out that the original closure support for returning pointers was incorrect and this was unmasked by the new test cases. I wrapped fixes for this into the patch as well (Yes, I know it is technically a no-no). The change to ffi_java_raw_to_rvalue() is needed with with the fixed closure pointer return. I would like to add that I think there is still incorrect handling for values of most types on big-endian systems in java_raw_api.c, but since the java interpreter only uses a couple of types, the problematical cases are never used. The end result is that all libffi tests except for some long double things now pass at -O0. There are a couple of floating point failures with optimization turned on, but they look like they may be issues with libgcc's soft-float support. The long double FAILures seem to be due to lack of support in my glibc's printf. Tested on mips64-unknown-linux-gnu soft-float with both n32 and n64 ABIs with no regressions. Currently testing mips64-unknown-linux-gnu hard-float n32 and n64. OK to commit given the hard-float testing is good? 2009-08-28 David Daney <ddaney@...> * src/java_raw_api.c (ffi_java_raw_to_rvalue): Remove special handling for FFI_TYPE_POINTER. * src/mips/ffitarget.h (FFI_TYPE_STRUCT_D_SOFT, FFI_TYPE_STRUCT_F_SOFT, FFI_TYPE_STRUCT_DD_SOFT, FFI_TYPE_STRUCT_FF_SOFT, FFI_TYPE_STRUCT_FD_SOFT, FFI_TYPE_STRUCT_DF_SOFT, FFI_TYPE_STRUCT_SOFT): New defines. (FFI_N32_SOFT_FLOAT, FFI_N64_SOFT_FLOAT): New ffi_abi enumerations. (enum ffi_abi): Set FFI_DEFAULT_ABI for soft-float. * src/mips/n32.S (ffi_call_N32): Add handling for soft-float structure and pointer returns. (ffi_closure_N32): Add handling for pointer returns. * src/mips/ffi.c (ffi_prep_args, calc_n32_struct_flags, calc_n32_return_struct_flags): Handle soft-float. (ffi_prep_cif_machdep): Handle soft-float, fix pointer handling. (ffi_call_N32): Declare proper argument types. (ffi_call, copy_struct_N32, ffi_closure_mips_inner_N32): Handle soft-float. Index: src/java_raw_api.c =================================================================== --- src/java_raw_api.c (revision 151156) +++ src/java_raw_api.c (working copy) @@ -276,9 +276,6 @@ ffi_java_raw_to_rvalue (ffi_cif *cif, vo case FFI_TYPE_SINT16: case FFI_TYPE_SINT32: case FFI_TYPE_INT: -#if FFI_SIZEOF_JAVA_RAW == 4 - case FFI_TYPE_POINTER: -#endif *(SINT64 *)rvalue >>= 32; break; Index: src/mips/ffitarget.h =================================================================== --- src/mips/ffitarget.h (revision 151156) +++ src/mips/ffitarget.h (working copy) @@ -95,6 +95,15 @@ #define FFI_TYPE_STRUCT_DF 189 #define FFI_TYPE_STRUCT_SMALL 93 #define FFI_TYPE_STRUCT_SMALL2 109 + +/* and for n32 soft float, add 16 * 2^4 */ +#define FFI_TYPE_STRUCT_D_SOFT 317 +#define FFI_TYPE_STRUCT_F_SOFT 301 +#define FFI_TYPE_STRUCT_DD_SOFT 509 +#define FFI_TYPE_STRUCT_FF_SOFT 429 +#define FFI_TYPE_STRUCT_FD_SOFT 493 +#define FFI_TYPE_STRUCT_DF_SOFT 445 +#define FFI_TYPE_STRUCT_SOFT 16 #endif #ifdef LIBFFI_ASM @@ -161,6 +170,8 @@ typedef enum ffi_abi { FFI_N32, FFI_N64, FFI_O32_SOFT_FLOAT, + FFI_N32_SOFT_FLOAT, + FFI_N64_SOFT_FLOAT, #ifdef FFI_MIPS_O32 #ifdef __mips_soft_float @@ -170,9 +181,17 @@ typedef enum ffi_abi { #endif #else # if _MIPS_SIM==_ABI64 +# ifdef __mips_soft_float + FFI_DEFAULT_ABI = FFI_N64_SOFT_FLOAT, +# else FFI_DEFAULT_ABI = FFI_N64, +# endif # else +# ifdef __mips_soft_float + FFI_DEFAULT_ABI = FFI_N32_SOFT_FLOAT, +# else FFI_DEFAULT_ABI = FFI_N32, +# endif # endif #endif Index: src/mips/n32.S =================================================================== --- src/mips/n32.S (revision 151156) +++ src/mips/n32.S (working copy) @@ -217,8 +217,10 @@ 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 +retint: jal t9 REG_L t4, 4*FFI_SIZEOF_ARG($fp) REG_S v0, 0(t4) @@ -277,12 +279,58 @@ retstruct_d_f: b epilogue retstruct_f_d: - bne t6, FFI_TYPE_STRUCT_FD, retstruct_small + bne t6, FFI_TYPE_STRUCT_FD, retstruct_d_soft jal t9 REG_L t4, 4*FFI_SIZEOF_ARG($fp) s.s $f0, 0(t4) s.d $f2, 8(t4) b epilogue + +retstruct_d_soft: + bne t6, FFI_TYPE_STRUCT_D_SOFT, retstruct_f_soft + jal t9 + REG_L t4, 4*FFI_SIZEOF_ARG($fp) + sd v0, 0(t4) + b epilogue + +retstruct_f_soft: + bne t6, FFI_TYPE_STRUCT_F_SOFT, retstruct_d_d_soft + jal t9 + REG_L t4, 4*FFI_SIZEOF_ARG($fp) + sw v0, 0(t4) + b epilogue + +retstruct_d_d_soft: + bne t6, FFI_TYPE_STRUCT_DD_SOFT, retstruct_f_f_soft + jal t9 + REG_L t4, 4*FFI_SIZEOF_ARG($fp) + sd v0, 0(t4) + sd v1, 8(t4) + b epilogue + +retstruct_f_f_soft: + bne t6, FFI_TYPE_STRUCT_FF_SOFT, retstruct_d_f_soft + jal t9 + REG_L t4, 4*FFI_SIZEOF_ARG($fp) + sw v0, 0(t4) + sw v1, 4(t4) + b epilogue + +retstruct_d_f_soft: + bne t6, FFI_TYPE_STRUCT_DF_SOFT, retstruct_f_d_soft + jal t9 + REG_L t4, 4*FFI_SIZEOF_ARG($fp) + sd v0, 0(t4) + sw v1, 8(t4) + b epilogue + +retstruct_f_d_soft: + bne t6, FFI_TYPE_STRUCT_FD_SOFT, retstruct_small + jal t9 + REG_L t4, 4*FFI_SIZEOF_ARG($fp) + sw v0, 0(t4) + sd v1, 8(t4) + b epilogue retstruct_small: bne t6, FFI_TYPE_STRUCT_SMALL, retstruct_small2 @@ -413,6 +461,11 @@ ffi_closure_N32: jalr t9 # Return flags are in v0 + bne v0, FFI_TYPE_SINT32, cls_retint + lw v0, V0_OFF2($sp) + b cls_epilogue + +cls_retint: bne v0, FFI_TYPE_INT, cls_retfloat REG_L v0, V0_OFF2($sp) b cls_epilogue Index: src/mips/ffi.c =================================================================== --- src/mips/ffi.c (revision 151156) +++ src/mips/ffi.c (working copy) @@ -99,7 +99,7 @@ static void ffi_prep_args(char *stack, p_argv = ecif->avalue; - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++) + for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; i++, p_arg++) { size_t z; unsigned int a; @@ -123,9 +123,25 @@ static void ffi_prep_args(char *stack, /* The size of a pointer depends on the ABI */ if (type == FFI_TYPE_POINTER) - type = - (ecif->cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32; + type = (ecif->cif->abi == FFI_N64 + || ecif->cif->abi == FFI_N64_SOFT_FLOAT) + ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32; + if (i < 8 && (ecif->cif->abi == FFI_N32_SOFT_FLOAT + || ecif->cif->abi == FFI_N64_SOFT_FLOAT)) + { + switch (type) + { + case FFI_TYPE_FLOAT: + type = FFI_TYPE_UINT32; + break; + case FFI_TYPE_DOUBLE: + type = FFI_TYPE_UINT64; + break; + default: + break; + } + } switch (type) { case FFI_TYPE_SINT8: @@ -205,13 +221,17 @@ static void ffi_prep_args(char *stack, definitions and generates the appropriate flags. */ static unsigned -calc_n32_struct_flags(ffi_type *arg, unsigned *loc, unsigned *arg_reg) +calc_n32_struct_flags(int soft_float, ffi_type *arg, + unsigned *loc, unsigned *arg_reg) { unsigned flags = 0; unsigned index = 0; ffi_type *e; + if (soft_float) + return 0; + while ((e = arg->elements[index])) { /* Align this object. */ @@ -236,7 +256,7 @@ calc_n32_struct_flags(ffi_type *arg, uns } static unsigned -calc_n32_return_struct_flags(ffi_type *arg) +calc_n32_return_struct_flags(int soft_float, ffi_type *arg) { unsigned flags = 0; unsigned small = FFI_TYPE_SMALLSTRUCT; @@ -256,6 +276,7 @@ calc_n32_return_struct_flags(ffi_type *a small = FFI_TYPE_SMALLSTRUCT2; e = arg->elements[0]; + if (e->type == FFI_TYPE_DOUBLE) flags = FFI_TYPE_DOUBLE; else if (e->type == FFI_TYPE_FLOAT) @@ -276,6 +297,8 @@ calc_n32_return_struct_flags(ffi_type *a floats! This must be passed the old way. */ return small; } + if (soft_float) + flags += FFI_TYPE_STRUCT_SOFT; } else if (!flags) @@ -382,16 +405,19 @@ ffi_status ffi_prep_cif_machdep(ffi_cif #ifdef FFI_MIPS_N32 /* Set the flags necessary for N32 processing */ { + int type; unsigned arg_reg = 0; unsigned loc = 0; unsigned count = (cif->nargs < 8) ? cif->nargs : 8; unsigned index = 0; unsigned struct_flags = 0; + int soft_float = (cif->abi == FFI_N32_SOFT_FLOAT + || cif->abi == FFI_N64_SOFT_FLOAT); if (cif->rtype->type == FFI_TYPE_STRUCT) { - struct_flags = calc_n32_return_struct_flags(cif->rtype); + struct_flags = calc_n32_return_struct_flags(soft_float, cif->rtype); if (struct_flags == 0) { @@ -411,7 +437,22 @@ ffi_status ffi_prep_cif_machdep(ffi_cif while (count-- > 0 && arg_reg < 8) { - switch ((cif->arg_types)[index]->type) + type = (cif->arg_types)[index]->type; + if (soft_float) + { + switch (type) + { + case FFI_TYPE_FLOAT: + type = FFI_TYPE_UINT32; + break; + case FFI_TYPE_DOUBLE: + type = FFI_TYPE_UINT64; + break; + default: + break; + } + } + switch (type) { case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: @@ -423,17 +464,25 @@ ffi_status ffi_prep_cif_machdep(ffi_cif /* Align it. */ arg_reg = ALIGN(arg_reg, 2); /* Treat it as two adjacent doubles. */ - cif->flags += - (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS)); - arg_reg++; - cif->flags += - (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS)); - arg_reg++; + if (soft_float) + { + arg_reg += 2; + } + else + { + cif->flags += + (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS)); + arg_reg++; + cif->flags += + (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS)); + arg_reg++; + } break; case FFI_TYPE_STRUCT: loc = arg_reg * FFI_SIZEOF_ARG; - cif->flags += calc_n32_struct_flags((cif->arg_types)[index], + cif->flags += calc_n32_struct_flags(soft_float, + (cif->arg_types)[index], &loc, &arg_reg); break; @@ -469,17 +518,43 @@ ffi_status ffi_prep_cif_machdep(ffi_cif case FFI_TYPE_VOID: /* Do nothing, 'cause FFI_TYPE_VOID is 0 */ break; - + + case FFI_TYPE_POINTER: + if (cif->abi == FFI_N32_SOFT_FLOAT || cif->abi == FFI_N32) + cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8); + else + cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8); + break; + case FFI_TYPE_FLOAT: + if (soft_float) + { + cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8); + break; + } + /* else fall through */ case FFI_TYPE_DOUBLE: - cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8); + if (soft_float) + cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8); + else + cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8); break; + case FFI_TYPE_LONGDOUBLE: /* Long double is returned as if it were a struct containing two doubles. */ - cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8); - cif->flags += (FFI_TYPE_DOUBLE + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS)) - << (4 + (FFI_FLAG_BITS * 8)); + if (soft_float) + { + cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8); + cif->flags += FFI_TYPE_SMALLSTRUCT2 << (4 + (FFI_FLAG_BITS * 8)); + } + else + { + cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8); + cif->flags += (FFI_TYPE_DOUBLE + + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS)) + << (4 + (FFI_FLAG_BITS * 8)); + } break; default: cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8); @@ -499,7 +574,7 @@ extern int ffi_call_O32(void (*)(char *, /* Low level routine for calling N32 functions */ extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int), extended_cif *, unsigned, - unsigned, unsigned *, void (*)(void)); + unsigned, void *, void (*)(void)); void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { @@ -529,10 +604,13 @@ void ffi_call(ffi_cif *cif, void (*fn)(v #ifdef FFI_MIPS_N32 case FFI_N32: + case FFI_N32_SOFT_FLOAT: case FFI_N64: + case FFI_N64_SOFT_FLOAT: { int copy_rvalue = 0; - void *rvalue_copy = ecif.rvalue; + int copy_offset = 0; + char *rvalue_copy = ecif.rvalue; if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16) { /* For structures smaller than 16 bytes we clobber memory @@ -541,10 +619,20 @@ void ffi_call(ffi_cif *cif, void (*fn)(v rvalue_copy = alloca(16); copy_rvalue = 1; } + else if (cif->rtype->type == FFI_TYPE_FLOAT + && (cif->abi == FFI_N64_SOFT_FLOAT + || cif->abi == FFI_N32_SOFT_FLOAT)) + { + rvalue_copy = alloca (8); + copy_rvalue = 1; +#ifdef __MIPSEB__ + copy_offset = 4; +#endif + } ffi_call_N32(ffi_prep_args, &ecif, cif->bytes, cif->flags, rvalue_copy, fn); if (copy_rvalue) - memcpy(ecif.rvalue, rvalue_copy, cif->rtype->size); + memcpy(ecif.rvalue, rvalue_copy + copy_offset, cif->rtype->size); } break; #endif @@ -755,7 +843,7 @@ ffi_closure_mips_inner_O32 (ffi_closure static void copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type, int argn, unsigned arg_offset, ffi_arg *ar, - ffi_arg *fpr) + ffi_arg *fpr, int soft_float) { ffi_type **elt_typep = type->elements; while(*elt_typep) @@ -777,7 +865,7 @@ copy_struct_N32(char *target, unsigned o tp = target + offset; - if (elt_type->type == FFI_TYPE_DOUBLE) + if (elt_type->type == FFI_TYPE_DOUBLE && !soft_float) *(double *)tp = *(double *)fpp; else memcpy(tp, argp + arg_offset, elt_type->size); @@ -815,8 +903,12 @@ ffi_closure_mips_inner_N32 (ffi_closure ffi_arg *avalue; ffi_type **arg_types; int i, avn, argn; + 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)); avaluep = alloca (cif->nargs * sizeof (ffi_arg)); @@ -839,9 +931,9 @@ ffi_closure_mips_inner_N32 (ffi_closure while (i < avn) { if (arg_types[i]->type == FFI_TYPE_FLOAT - || arg_types[i]->type == FFI_TYPE_DOUBLE) + || arg_types[i]->type == FFI_TYPE_DOUBLE) { - ffi_arg *argp = argn >= 8 ? ar + argn : fpr + argn; + argp = (argn >= 8 || soft_float) ? ar + argn : fpr + argn; #ifdef __MIPSEB__ if (arg_types[i]->type == FFI_TYPE_FLOAT && argn < 8) avaluep[i] = ((char *) argp) + sizeof (float); @@ -856,11 +948,15 @@ ffi_closure_mips_inner_N32 (ffi_closure if (arg_types[i]->alignment > sizeof(ffi_arg)) argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg)); - ffi_arg *argp = ar + argn; + argp = ar + argn; /* The size of a pointer depends on the ABI */ if (type == FFI_TYPE_POINTER) - type = (cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32; + type = (cif->abi == FFI_N64 || cif->abi == FFI_N64_SOFT_FLOAT) + ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32; + + if (soft_float && type == FFI_TYPE_FLOAT) + type = FFI_TYPE_UINT32; switch (type) { @@ -901,7 +997,7 @@ ffi_closure_mips_inner_N32 (ffi_closure it was passed in registers. */ avaluep[i] = alloca(arg_types[i]->size); copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i], - argn, 0, ar, fpr); + argn, 0, ar, fpr, soft_float); break; } |
|
|
Re: [Patch,libffi] Add MIPS64 soft-float support to libffi.David Daney wrote:
> libffi is lacking support for the mips64 soft-float ABIs. In addition > be being annoying in and of itself, it also causes libjava failures. > > The patch adds soft-float support for both n32 and n64 ABIs. Quite a > bit of code had to be touched as the rules for passing structures > containing floating point elements are a slightly complex. > > While working on the patch I noticed that we were failing a bunch if > pointer passing test cases that where recently added. It turns out > that the original closure support for returning pointers was incorrect > and this was unmasked by the new test cases. I wrapped fixes for this > into the patch as well (Yes, I know it is technically a no-no). The > change to ffi_java_raw_to_rvalue() is needed with with the fixed > closure pointer return. > > I would like to add that I think there is still incorrect handling for > values of most types on big-endian systems in java_raw_api.c, but > since the java interpreter only uses a couple of types, the > problematical cases are never used. > > The end result is that all libffi tests except for some long double > things now pass at -O0. There are a couple of floating point failures > with optimization turned on, but they look like they may be issues > with libgcc's soft-float support. The long double FAILures seem to > be due to lack of support in my glibc's printf. > > > Tested on mips64-unknown-linux-gnu soft-float with both n32 and n64 > ABIs with no regressions. Currently testing mips64-unknown-linux-gnu > hard-float n32 and n64. > > OK to commit given the hard-float testing is good? I'll move the patch to the libffi repository once I see your commit. AG |
|
|
Re: [Patch,libffi] Add MIPS64 soft-float support to libffi.Anthony Green wrote:
> David Daney wrote: >> libffi is lacking support for the mips64 soft-float ABIs. In addition >> be being annoying in and of itself, it also causes libjava failures. >> >> The patch adds soft-float support for both n32 and n64 ABIs. Quite a >> bit of code had to be touched as the rules for passing structures >> containing floating point elements are a slightly complex. >> >> While working on the patch I noticed that we were failing a bunch if >> pointer passing test cases that where recently added. It turns out >> that the original closure support for returning pointers was incorrect >> and this was unmasked by the new test cases. I wrapped fixes for this >> into the patch as well (Yes, I know it is technically a no-no). The >> change to ffi_java_raw_to_rvalue() is needed with with the fixed >> closure pointer return. >> >> I would like to add that I think there is still incorrect handling for >> values of most types on big-endian systems in java_raw_api.c, but >> since the java interpreter only uses a couple of types, the >> problematical cases are never used. >> >> The end result is that all libffi tests except for some long double >> things now pass at -O0. There are a couple of floating point failures >> with optimization turned on, but they look like they may be issues >> with libgcc's soft-float support. The long double FAILures seem to >> be due to lack of support in my glibc's printf. >> >> >> Tested on mips64-unknown-linux-gnu soft-float with both n32 and n64 >> ABIs with no regressions. Currently testing mips64-unknown-linux-gnu >> hard-float n32 and n64. >> >> OK to commit given the hard-float testing is good? > Thanks David. Please commit once you've confirmed good test results. > I'll move the patch to the libffi repository once I see your commit. > Now committed (r151726). Sorry for the delay, but my O2 is not the fastest machine and I was too lazy to put a hard float filesystem on my fast machines. David Daney |
| Free embeddable forum powered by Nabble | Forum Help |