ffi.c (ffi_pref_cif_machdep): set `cif->flags' to contain `FFI_TYPE_UINT64' as return type for any 64-bit...
2004-08-14 Casey Marshall <csm@gnu.org> * src/mips/ffi.c (ffi_pref_cif_machdep): set `cif->flags' to contain `FFI_TYPE_UINT64' as return type for any 64-bit integer (O32 ABI only). (ffi_prep_closure): new function. (ffi_closure_mips_inner_O32): new function. * src/mips/ffitarget.h: Define `FFI_CLOSURES' and `FFI_TRAMPOLINE_SIZE' appropriately if the ABI is o32. * src/mips/o32.S (ffi_call_O32): add labels for .eh_frame. Return 64 bit integers correctly. (ffi_closure_O32): new function. Added DWARF-2 unwind info for both functions. From-SVN: r86019
This commit is contained in:
parent
53fb4de375
commit
b790003ae6
|
@ -1,3 +1,17 @@
|
|||
2004-08-14 Casey Marshall <csm@gnu.org>
|
||||
|
||||
* src/mips/ffi.c (ffi_pref_cif_machdep): set `cif->flags' to
|
||||
contain `FFI_TYPE_UINT64' as return type for any 64-bit
|
||||
integer (O32 ABI only).
|
||||
(ffi_prep_closure): new function.
|
||||
(ffi_closure_mips_inner_O32): new function.
|
||||
* src/mips/ffitarget.h: Define `FFI_CLOSURES' and
|
||||
`FFI_TRAMPOLINE_SIZE' appropriately if the ABI is o32.
|
||||
* src/mips/o32.S (ffi_call_O32): add labels for .eh_frame. Return
|
||||
64 bit integers correctly.
|
||||
(ffi_closure_O32): new function.
|
||||
Added DWARF-2 unwind info for both functions.
|
||||
|
||||
2004-08-10 Andrew Haley <aph@redhat.com>
|
||||
|
||||
* src/x86/ffi64.c (ffi_prep_args ): 8-align all stack arguments.
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/cachectl.h>
|
||||
|
||||
#if _MIPS_SIM == _ABIN32
|
||||
#define FIX_ARGP \
|
||||
|
@ -314,6 +315,11 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
|||
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);
|
||||
|
@ -459,3 +465,117 @@ void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES /* N32 not implemented yet, FFI_CLOSURES not defined */
|
||||
#if defined(FFI_MIPS_O32)
|
||||
extern void ffi_closure_O32(void);
|
||||
#endif /* FFI_MIPS_O32 */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure *closure,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data)
|
||||
{
|
||||
unsigned int *tramp = (unsigned int *) &closure->tramp[0];
|
||||
unsigned int fn;
|
||||
unsigned int ctx = (unsigned int) closure;
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
FFI_ASSERT(cif->abi == FFI_O32);
|
||||
fn = (unsigned int) ffi_closure_O32;
|
||||
#else /* FFI_MIPS_N32 */
|
||||
FFI_ASSERT(cif->abi == FFI_N32);
|
||||
FFI_ASSERT(!"not implemented");
|
||||
#endif /* FFI_MIPS_O32 */
|
||||
|
||||
tramp[0] = 0x3c190000 | (fn >> 16); /* lui $25,high(fn) */
|
||||
tramp[1] = 0x3c080000 | (ctx >> 16); /* lui $8,high(ctx) */
|
||||
tramp[2] = 0x37390000 | (fn & 0xffff); /* ori $25,low(fn) */
|
||||
tramp[3] = 0x03200008; /* jr $25 */
|
||||
tramp[4] = 0x35080000 | (ctx & 0xffff); /* ori $8,low(ctx) */
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
/* XXX this is available on Linux, but anything else? */
|
||||
cacheflush (tramp, FFI_TRAMPOLINE_SIZE, ICACHE);
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decodes the arguments to a function, which will be stored on the
|
||||
* stack. AR is the pointer to the beginning of the integer arguments
|
||||
* (and, depending upon the arguments, some floating-point arguments
|
||||
* as well). FPR is a pointer to the area where floating point
|
||||
* registers have been saved, if any.
|
||||
*
|
||||
* RVALUE is the location where the function return value will be
|
||||
* stored. CLOSURE is the prepared closure to invoke.
|
||||
*
|
||||
* This function should only be called from assembly, which is in
|
||||
* turn called from a trampoline.
|
||||
*
|
||||
* Returns the function return type.
|
||||
*
|
||||
* Based on the similar routine for sparc.
|
||||
*/
|
||||
int
|
||||
ffi_closure_mips_inner_O32 (ffi_closure *closure,
|
||||
void *rvalue, unsigned long *ar,
|
||||
double *fpr)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avalue;
|
||||
ffi_type **arg_types;
|
||||
int i, avn, argn, seen_int;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca (cif->nargs * sizeof (void *));
|
||||
|
||||
seen_int = 0;
|
||||
argn = 0;
|
||||
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
{
|
||||
rvalue = (void *) ar[0];
|
||||
argn = 1;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
while (i < avn)
|
||||
{
|
||||
if (i < 2 && !seen_int &&
|
||||
(arg_types[i]->type == FFI_TYPE_FLOAT ||
|
||||
arg_types[i]->type == FFI_TYPE_DOUBLE))
|
||||
{
|
||||
avalue[i] = ((char *) &fpr[i]);
|
||||
}
|
||||
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)
|
||||
argn++;
|
||||
avalue[i] = ((char *) &ar[argn]);
|
||||
seen_int = 1;
|
||||
}
|
||||
argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
return cif->rtype->type;
|
||||
}
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
|
|
|
@ -153,7 +153,13 @@ typedef enum ffi_abi {
|
|||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#if defined(FFI_MIPS_O32)
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TRAMPOLINE_SIZE 20
|
||||
#else
|
||||
/* N32/N64 not implemented yet. */
|
||||
#define FFI_CLOSURES 0
|
||||
#endif /* FFI_MIPS_O32 */
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,19 +36,24 @@
|
|||
#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
|
||||
.globl ffi_call_O32
|
||||
.ent ffi_call_O32
|
||||
ffi_call_O32:
|
||||
|
||||
$LFB0:
|
||||
# Prologue
|
||||
SUBU $sp, SIZEOF_FRAME # Frame size
|
||||
$LCFI0:
|
||||
REG_S $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer
|
||||
$LCFI1:
|
||||
REG_S ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Save return address
|
||||
$LCFI2:
|
||||
move $fp, $sp
|
||||
|
||||
$LCFI3:
|
||||
move t9, callback # callback function pointer
|
||||
REG_S flags, SIZEOF_FRAME + 3*FFI_SIZEOF_ARG($fp) # flags
|
||||
|
||||
|
@ -136,12 +141,21 @@ call_it:
|
|||
REG_L t1, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
beqz t1, noretval
|
||||
|
||||
bne t2, FFI_TYPE_INT, retfloat
|
||||
bne t2, FFI_TYPE_INT, retlonglong
|
||||
jal t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
retlonglong:
|
||||
# Really any 64-bit int, signed or not.
|
||||
bne t2, FFI_TYPE_UINT64, retfloat
|
||||
jal t9
|
||||
REG_L t0, SIZEOF_FRAME + 4*FFI_SIZEOF_ARG($fp)
|
||||
REG_S v1, 4(t0)
|
||||
REG_S v0, 0(t0)
|
||||
b epilogue
|
||||
|
||||
retfloat:
|
||||
bne t2, FFI_TYPE_FLOAT, retdouble
|
||||
jal t9
|
||||
|
@ -167,6 +181,159 @@ epilogue:
|
|||
ADDU $sp, SIZEOF_FRAME # Fix stack pointer
|
||||
j ra
|
||||
|
||||
$LFE0:
|
||||
.end ffi_call_O32
|
||||
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl ffi_closure_O32
|
||||
.ent ffi_closure_O32
|
||||
ffi_closure_O32:
|
||||
$LFB1:
|
||||
# Prologue
|
||||
.frame $fp, SIZEOF_FRAME2, $31
|
||||
.set noreorder
|
||||
.cpload $25
|
||||
.set reorder
|
||||
SUBU $sp, SIZEOF_FRAME2
|
||||
.cprestore SIZEOF_FRAME2 - 3*FFI_SIZEOF_ARG
|
||||
$LCFI4:
|
||||
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
|
||||
|
||||
$LCFI7:
|
||||
# Store all possible argument registers. If there are more than
|
||||
# four arguments, then they should be stored above where we put $7.
|
||||
REG_S $4, SIZEOF_FRAME2 + 0*FFI_SIZEOF_ARG($fp)
|
||||
REG_S $5, SIZEOF_FRAME2 + 1*FFI_SIZEOF_ARG($fp)
|
||||
REG_S $6, SIZEOF_FRAME2 + 2*FFI_SIZEOF_ARG($fp)
|
||||
REG_S $7, SIZEOF_FRAME2 + 3*FFI_SIZEOF_ARG($fp)
|
||||
|
||||
# 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)
|
||||
|
||||
# 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 $6, $fp, SIZEOF_FRAME2 + 0*FFI_SIZEOF_ARG
|
||||
addu $7, $fp, SIZEOF_FRAME2 - 10*FFI_SIZEOF_ARG
|
||||
jal $31, $25
|
||||
|
||||
# Load the return value into the appropriate register.
|
||||
move $8, $2
|
||||
li $9, FFI_TYPE_VOID
|
||||
beq $8, $9, closure_done
|
||||
|
||||
li $9, FFI_TYPE_FLOAT
|
||||
l.s $f0, SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG($fp)
|
||||
beq $8, $9, closure_done
|
||||
|
||||
li $9, FFI_TYPE_DOUBLE
|
||||
l.d $f0, SIZEOF_FRAME2 - 4*FFI_SIZEOF_ARG($fp)
|
||||
beq $8, $9, closure_done
|
||||
|
||||
li $9, FFI_TYPE_SINT64
|
||||
REG_L $3, SIZEOF_FRAME2 - 3*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)
|
||||
|
||||
closure_done:
|
||||
# Epilogue
|
||||
move $sp, $fp
|
||||
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
|
||||
j ra
|
||||
$LFE1:
|
||||
.end ffi_closure_O32
|
||||
|
||||
/* DWARF-2 unwind info. */
|
||||
|
||||
.section .eh_frame,"a",@progbits
|
||||
$Lframe0:
|
||||
.4byte $LECIE0-$LSCIE0 # Length of Common Information Entry
|
||||
$LSCIE0:
|
||||
.4byte 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.uleb128 0x1 # CIE Code Alignment Factor
|
||||
.sleb128 4 # CIE Data Alignment Factor
|
||||
.byte 0x1f # CIE RA Column
|
||||
.uleb128 0x1 # Augmentation size
|
||||
.byte 0x1b # FDE Encoding (pcrel sdata4)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1d
|
||||
.uleb128 0x0
|
||||
.align 2
|
||||
$LECIE0:
|
||||
$LSFDE0:
|
||||
.4byte $LEFDE0-$LASFDE0 # FDE Length
|
||||
$LASFDE0:
|
||||
.4byte $LASFDE0-$Lframe0 # FDE CIE offset
|
||||
.4byte $LFB0-. # FDE initial location
|
||||
.4byte $LFE0-$LFB0 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI0-$LFB0
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0x18
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI2-$LCFI0
|
||||
.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
|
||||
.uleb128 0x1f # $ra
|
||||
.sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI3-$LCFI2
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x18
|
||||
.align 2
|
||||
$LEFDE0:
|
||||
$LSFDE1:
|
||||
.4byte $LEFDE1-$LASFDE1 # FDE Length
|
||||
$LASFDE1:
|
||||
.4byte $LASFDE1-$Lframe0 # FDE CIE offset
|
||||
.4byte $LFB1-. # FDE initial location
|
||||
.4byte $LFE1-$LFB1 # FDE address range
|
||||
.uleb128 0x0 # Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI4-$LFB1
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.uleb128 0x28
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI6-$LCFI4
|
||||
.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
|
||||
.uleb128 0x1f # $ra
|
||||
.sleb128 -1 # SIZEOF_FRAME2 - 1*FFI_SIZEOF_ARG($sp)
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.4byte $LCFI7-$LCFI6
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.uleb128 0x1e
|
||||
.uleb128 0x28
|
||||
.align 2
|
||||
$LEFDE1:
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue