From 39dca114a945ec4f22b2a1f89a2bfd6434d433cd Mon Sep 17 00:00:00 2001 From: David Daney Date: Mon, 23 Aug 2004 16:49:17 +0000 Subject: [PATCH] re PR libffi/13141 (FAIL: InvokeReturn output - source compiled test ) 2004-08-23 David Daney PR libgcj/13141 * src/mips/ffitarget.h (FFI_O32_SOFT_FLOAT): New ABI. * src/mips/ffi.c (ffi_prep_args): Fix alignment calculation. (ffi_prep_cif_machdep): Handle FFI_O32_SOFT_FLOAT floating point parameters and return types. (ffi_call): Handle FFI_O32_SOFT_FLOAT ABI. (ffi_prep_closure): Ditto. (ffi_closure_mips_inner_O32): Handle FFI_O32_SOFT_FLOAT ABI, fix alignment calculations. * src/mips/o32.S (ffi_closure_O32): Don't use floating point instructions if FFI_O32_SOFT_FLOAT, make stack frame ABI compliant. From-SVN: r86429 --- libffi/ChangeLog | 14 +++++ libffi/src/mips/ffi.c | 102 ++++++++++++++++++++++++++---------- libffi/src/mips/ffitarget.h | 5 ++ libffi/src/mips/o32.S | 62 ++++++++++++++++------ 4 files changed, 139 insertions(+), 44 deletions(-) diff --git a/libffi/ChangeLog b/libffi/ChangeLog index 483e483343c..b33faeace23 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,3 +1,17 @@ +2004-08-23 David Daney + + PR libgcj/13141 + * src/mips/ffitarget.h (FFI_O32_SOFT_FLOAT): New ABI. + * src/mips/ffi.c (ffi_prep_args): Fix alignment calculation. + (ffi_prep_cif_machdep): Handle FFI_O32_SOFT_FLOAT floating point + parameters and return types. + (ffi_call): Handle FFI_O32_SOFT_FLOAT ABI. + (ffi_prep_closure): Ditto. + (ffi_closure_mips_inner_O32): Handle FFI_O32_SOFT_FLOAT ABI, fix + alignment calculations. + * src/mips/o32.S (ffi_closure_O32): Don't use floating point + instructions if FFI_O32_SOFT_FLOAT, make stack frame ABI compliant. + 2004-08-14 Casey Marshall * src/mips/ffi.c (ffi_pref_cif_machdep): set `cif->flags' to diff --git a/libffi/src/mips/ffi.c b/libffi/src/mips/ffi.c index e12922aa046..352226c7f54 100644 --- a/libffi/src/mips/ffi.c +++ b/libffi/src/mips/ffi.c @@ -85,10 +85,15 @@ static void ffi_prep_args(char *stack, for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++) { size_t z; + unsigned short a; /* Align if necessary */ - if (((*p_arg)->alignment - 1) & (unsigned) argp) { - argp = (char *) ALIGN(argp, (*p_arg)->alignment); + a = (*p_arg)->alignment; + if (a < FFI_SIZEOF_ARG) + a = FFI_SIZEOF_ARG; + + if ((a - 1) & (unsigned) argp) { + argp = (char *) ALIGN(argp, a); FIX_ARGP; } @@ -268,9 +273,11 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) cif->flags = 0; #if _MIPS_SIM == _ABIO32 - /* Set the flags necessary for O32 processing */ + /* Set the flags necessary for O32 processing. FFI_O32_SOFT_FLOAT + * does not have special handling for floating point args. + */ - if (cif->rtype->type != FFI_TYPE_STRUCT) + if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32) { if (cif->nargs > 0) { @@ -307,23 +314,49 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) } /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - case FFI_TYPE_STRUCT: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2); - break; - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2); - break; + if (cif->abi == FFI_O32_SOFT_FLOAT) + { + switch (cif->rtype->type) + { + case FFI_TYPE_VOID: + case FFI_TYPE_STRUCT: + cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2); + break; + + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_DOUBLE: + cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2); + break; - default: - cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2); - break; + case FFI_TYPE_FLOAT: + default: + cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2); + break; + } + } + else + { + /* FFI_O32 */ + switch (cif->rtype->type) + { + case FFI_TYPE_VOID: + case FFI_TYPE_STRUCT: + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2); + break; + + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2); + break; + + default: + cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2); + break; + } } #endif @@ -448,6 +481,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue) { #if _MIPS_SIM == _ABIO32 case FFI_O32: + case FFI_O32_SOFT_FLOAT: ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, fn); break; @@ -482,7 +516,7 @@ ffi_prep_closure (ffi_closure *closure, unsigned int ctx = (unsigned int) closure; #if defined(FFI_MIPS_O32) - FFI_ASSERT(cif->abi == FFI_O32); + FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT); fn = (unsigned int) ffi_closure_O32; #else /* FFI_MIPS_N32 */ FFI_ASSERT(cif->abi == FFI_N32); @@ -535,10 +569,10 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure, cif = closure->cif; avalue = alloca (cif->nargs * sizeof (void *)); - seen_int = 0; + seen_int = (cif->abi == FFI_O32_SOFT_FLOAT); argn = 0; - if (cif->flags == FFI_TYPE_STRUCT) + if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT) { rvalue = (void *) ar[0]; argn = 1; @@ -558,12 +592,7 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure, } else { - /* 8-byte arguments are always 8-byte aligned. */ - if (arg_types[i]->size == 8 && (argn & 0x1)) - argn++; - /* Float arguments take up two register slots. The float word - is the upper one. */ - if (argn == 2 && arg_types[i]->type == FFI_TYPE_FLOAT) + if (arg_types[i]->alignment == 8 && (argn & 0x1)) argn++; avalue[i] = ((char *) &ar[argn]); seen_int = 1; @@ -575,7 +604,22 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure, /* Invoke the closure. */ (closure->fun) (cif, rvalue, avalue, closure->user_data); - return cif->rtype->type; + if (cif->abi == FFI_O32_SOFT_FLOAT) + { + switch (cif->rtype->type) + { + case FFI_TYPE_FLOAT: + return FFI_TYPE_INT; + case FFI_TYPE_DOUBLE: + return FFI_TYPE_UINT64; + default: + return cif->rtype->type; + } + } + else + { + return cif->rtype->type; + } } #endif /* FFI_CLOSURES */ diff --git a/libffi/src/mips/ffitarget.h b/libffi/src/mips/ffitarget.h index 2e6fbaeec0a..6f28e700111 100644 --- a/libffi/src/mips/ffitarget.h +++ b/libffi/src/mips/ffitarget.h @@ -138,9 +138,14 @@ typedef enum ffi_abi { FFI_O32, FFI_N32, FFI_N64, + FFI_O32_SOFT_FLOAT, #ifdef FFI_MIPS_O32 +#ifdef __mips_soft_float + FFI_DEFAULT_ABI = FFI_O32_SOFT_FLOAT, +#else FFI_DEFAULT_ABI = FFI_O32, +#endif #else FFI_DEFAULT_ABI = FFI_N32, #endif diff --git a/libffi/src/mips/o32.S b/libffi/src/mips/o32.S index e2dfa8debdb..7391ce3fbfb 100644 --- a/libffi/src/mips/o32.S +++ b/libffi/src/mips/o32.S @@ -36,7 +36,6 @@ #define flags a3 #define SIZEOF_FRAME ( 4 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG ) -#define SIZEOF_FRAME2 ( 8 * FFI_SIZEOF_ARG + 2 * FFI_SIZEOF_ARG ) .text .align 2 @@ -188,7 +187,28 @@ $LFE0: /* ffi_closure_O32. Expects address of the passed-in ffi_closure in t0. Stores any arguments passed in registers onto the stack, then calls ffi_closure_mips_inner_O32, which - then decodes them. */ + then decodes them. + + Stack layout: + + 14 - Start of parameters, original sp + 13 - ra save + 12 - fp save + 11 - $16 (s0) save + 10 - cprestore + 9 - return value high (v1) + 8 - return value low (v0) + 7 - f14 (le high, be low) + 6 - f14 (le low, be high) + 5 - f12 (le high, be low) + 4 - f12 (le low, be high) + 3 - Called function a3 save + 2 - Called function a2 save + 1 - Called function a1 save + 0 - Called function a0 save our sp, fp point here + */ + +#define SIZEOF_FRAME2 ( 14 * FFI_SIZEOF_ARG ) .text .align 2 @@ -202,10 +222,10 @@ $LFB1: .cpload $25 .set reorder SUBU $sp, SIZEOF_FRAME2 - .cprestore SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG + .cprestore SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG $LCFI4: + REG_S $16, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp) # Save s0 REG_S $fp, SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer -$LCFI5: REG_S ra, SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) # Save return address $LCFI6: move $fp, $sp @@ -218,14 +238,21 @@ $LCFI7: REG_S $6, SIZEOF_FRAME2 + 2*FFI_SIZEOF_ARG($fp) REG_S $7, SIZEOF_FRAME2 + 3*FFI_SIZEOF_ARG($fp) + # Load ABI enum to $16 + REG_L $16, 20($8) # cif pointer follows tramp. + 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, SIZEOF_FRAME2 - 10*FFI_SIZEOF_ARG($fp) s.d $f14, SIZEOF_FRAME2 - 8*FFI_SIZEOF_ARG($fp) - +1: # Call ffi_closure_mips_inner_O32 to do the work. la $25, ffi_closure_mips_inner_O32 move $4, $8 # Pointer to the ffi_closure - addu $5, $fp, SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG + addu $5, $fp, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG addu $6, $fp, SIZEOF_FRAME2 + 0*FFI_SIZEOF_ARG addu $7, $fp, SIZEOF_FRAME2 - 10*FFI_SIZEOF_ARG jal $31, $25 @@ -235,28 +262,30 @@ $LCFI7: li $9, FFI_TYPE_VOID beq $8, $9, closure_done + li $13, 1 # FFI_O32 + bne $16, $13, 1f # Skip fp restore if FFI_O32_SOFT_FLOAT + li $9, FFI_TYPE_FLOAT - l.s $f0, SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG($fp) + l.s $f0, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp) beq $8, $9, closure_done li $9, FFI_TYPE_DOUBLE - l.d $f0, SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG($fp) + l.d $f0, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp) beq $8, $9, closure_done - +1: li $9, FFI_TYPE_SINT64 - REG_L $3, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($fp) + REG_L $3, SIZEOF_FRAME2 - 5*FFI_SIZEOF_ARG($fp) beq $8, $9, integer - li $9, FFI_TYPE_UINT64 - REG_L $3, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($fp) beq $8, $9, integer integer: - REG_L $2, SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG($fp) + REG_L $2, SIZEOF_FRAME2 - 6*FFI_SIZEOF_ARG($fp) closure_done: # Epilogue move $sp, $fp + REG_L $16, SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp) # Restore s0 REG_L $fp, SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) # Restore frame pointer REG_L ra, SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp) # Restore return address ADDU $sp, SIZEOF_FRAME2 @@ -319,10 +348,13 @@ $LASFDE1: .byte 0x4 # DW_CFA_advance_loc4 .4byte $LCFI4-$LFB1 .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 0x28 + .uleb128 0x38 .byte 0x4 # DW_CFA_advance_loc4 .4byte $LCFI6-$LCFI4 .byte 0x11 # DW_CFA_offset_extended_sf + .uleb128 0x10 # $16 + .sleb128 -3 # SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG($sp) + .byte 0x11 # DW_CFA_offset_extended_sf .uleb128 0x1e # $fp .sleb128 -2 # SIZEOF_FRAME2 - 2*FFI_SIZEOF_ARG($sp) .byte 0x11 # DW_CFA_offset_extended_sf @@ -332,7 +364,7 @@ $LASFDE1: .4byte $LCFI7-$LCFI6 .byte 0xc # DW_CFA_def_cfa .uleb128 0x1e - .uleb128 0x28 + .uleb128 0x38 .align 2 $LEFDE1: -- 2.30.2