Commit 3f67ba6e by Richard Henderson Committed by Anthony Green

Richards changes to the closure code for alpha

From-SVN: r38169
parent bc38c787
2000-12-07 Dec 8 11:23:29 2000 Richard Henderson <rth@redhat.com> 2000-12-09 Richard Henderson <rth@redhat.com>
* src/alpha/ffi.c (ffi_call): Simplify struct return test.
(ffi_closure_osf_inner): Index rather than increment avalue
and arg_types. Give ffi_closure_osf the raw return value type.
* src/alpha/osf.S (ffi_closure_osf): Handle return value type
promotion.
2000-12-07 Richard Henderson <rth@redhat.com>
* src/raw_api.c (ffi_translate_args): Fix typo. * src/raw_api.c (ffi_translate_args): Fix typo.
(ffi_prep_closure): Likewise. (ffi_prep_closure): Likewise.
......
...@@ -70,7 +70,7 @@ ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue) ...@@ -70,7 +70,7 @@ ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
/* If the return value is a struct and we don't have a return /* If the return value is a struct and we don't have a return
value address then we need to make one. */ value address then we need to make one. */
if (rvalue == NULL && cif->rtype->type == FFI_TYPE_STRUCT) if (rvalue == NULL && cif->flags == FFI_TYPE_STRUCT)
rvalue = alloca(cif->rtype->size); rvalue = alloca(cif->rtype->size);
/* Allocate the space for the arguments, plus 4 words of temp /* Allocate the space for the arguments, plus 4 words of temp
...@@ -202,7 +202,7 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp) ...@@ -202,7 +202,7 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
/* Grab the addresses of the arguments from the stack frame. */ /* Grab the addresses of the arguments from the stack frame. */
while (i < avn) while (i < avn)
{ {
switch ((*arg_types)->type) switch (arg_types[i]->type)
{ {
case FFI_TYPE_SINT8: case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8: case FFI_TYPE_UINT8:
...@@ -214,7 +214,7 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp) ...@@ -214,7 +214,7 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
case FFI_TYPE_UINT64: case FFI_TYPE_UINT64:
case FFI_TYPE_POINTER: case FFI_TYPE_POINTER:
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
*avalue = &argp[argn]; avalue[i] = &argp[argn];
break; break;
case FFI_TYPE_FLOAT: case FFI_TYPE_FLOAT:
...@@ -223,27 +223,27 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp) ...@@ -223,27 +223,27 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
/* Floats coming from registers need conversion from double /* Floats coming from registers need conversion from double
back to float format. */ back to float format. */
*(float *)&argp[argn - 6] = *(double *)&argp[argn - 6]; *(float *)&argp[argn - 6] = *(double *)&argp[argn - 6];
*avalue = &argp[argn - 6]; avalue[i] = &argp[argn - 6];
} }
else else
*avalue = &argp[argn]; avalue[i] = &argp[argn];
break; break;
case FFI_TYPE_DOUBLE: case FFI_TYPE_DOUBLE:
*avalue = &argp[argn - (argn < 6 ? 6 : 0)]; avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)];
break; break;
default: default:
FFI_ASSERT(0); FFI_ASSERT(0);
} }
argn += ALIGN((*arg_types)->size, SIZEOF_ARG) / SIZEOF_ARG; argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG;
i++, arg_types++, avalue++; i++;
} }
/* Invoke the closure. */ /* Invoke the closure. */
(closure->fun) (cif, rvalue, avalue, closure->user_data); (closure->fun) (cif, rvalue, avalue, closure->user_data);
/* Tell ffi_closure_osf what register to put the return value in. */ /* Tell ffi_closure_osf how to perform return type promotions. */
return cif->flags; return cif->rtype->type;
} }
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#define LIBFFI_ASM #define LIBFFI_ASM
#include <ffi.h> #include <ffi.h>
.arch ev6
.text .text
/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags, /* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
...@@ -121,9 +122,9 @@ $retdouble: ...@@ -121,9 +122,9 @@ $retdouble:
.ent ffi_closure_osf .ent ffi_closure_osf
ffi_closure_osf: ffi_closure_osf:
.frame $30, 16*8, $26, 0 .frame $30, 16*8, $26, 0
.mask 0x4000000, -14*8 .mask 0x4000000, -16*8
ldgp $29, 0($27) ldgp $29, 0($27)
subq $30, 14*8, $30 subq $30, 16*8, $30
stq $26, 0($30) stq $26, 0($30)
.prologue 1 .prologue 1
...@@ -150,33 +151,129 @@ ffi_closure_osf: ...@@ -150,33 +151,129 @@ ffi_closure_osf:
ldq $26, 0($30) ldq $26, 0($30)
# Load up the return value in the proper type. # Load up the return value in the proper type.
cmpeq $0, FFI_TYPE_INT, $1 lda $1, $load_table
bne $1, $loadint s4addq $0, $1, $1
cmpeq $0, FFI_TYPE_FLOAT, $2 ldl $1, 0($1)
bne $2, $loadfloat addq $1, $29, $1
cmpeq $18, FFI_TYPE_DOUBLE, $3 jmp $31, ($1), $load_32
bne $3, $loaddouble
.align 4
$load_none:
addq $30, 16*8, $30
ret
.align 4
$load_float:
lds $f0, 16($30)
nop
addq $30, 16*8, $30
ret
.align 4
$load_double:
ldt $f0, 16($30)
nop
addq $30, 16*8, $30
ret
.align 4
$load_u8:
#ifdef __alpha_bwx__
ldbu $0, 16($30)
nop
#else
ldq $0, 16($30)
and $0, 255, $0
#endif
addq $30, 16*8, $30 addq $30, 16*8, $30
ret ret
.align 3 .align 4
$loadint: $load_s8:
#ifdef __alpha_bwx__
ldbu $0, 16($30)
sextb $0, $0
#else
ldq $0, 16($30) ldq $0, 16($30)
sll $0, 56, $0
sra $0, 56, $0
#endif
addq $30, 16*8, $30
ret
.align 4
$load_u16:
#ifdef __alpha_bwx__
ldwu $0, 16($30)
nop nop
#else
ldq $0, 16($30)
zapnot $0, 3, $0
#endif
addq $30, 16*8, $30 addq $30, 16*8, $30
ret ret
$loadfloat: .align 4
lds $f0, 16($30) $load_s16:
#ifdef __alpha_bwx__
ldwu $0, 16($30)
sextw $0, $0
#else
ldq $0, 16($30)
sll $0, 48, $0
sra $0, 48, $0
#endif
addq $30, 16*8, $30
ret
.align 4
$load_32:
ldl $0, 16($30)
nop nop
addq $30, 16*8, $30 addq $30, 16*8, $30
ret ret
$loaddouble: .align 4
ldt $f0, 16($30) $load_64:
ldq $0, 16($30)
nop nop
addq $30, 16*8, $30 addq $30, 16*8, $30
ret ret
.end ffi_closure_osf .end ffi_closure_osf
.section .rodata
$load_table:
.gprel32 $load_none # FFI_TYPE_VOID
.gprel32 $load_32 # FFI_TYPE_INT
.gprel32 $load_float # FFI_TYPE_FLOAT
.gprel32 $load_double # FFI_TYPE_DOUBLE
.gprel32 $load_double # FFI_TYPE_LONGDOUBLE
.gprel32 $load_u8 # FFI_TYPE_UINT8
.gprel32 $load_s8 # FFI_TYPE_SINT8
.gprel32 $load_u16 # FFI_TYPE_UINT16
.gprel32 $load_s16 # FFI_TYPE_SINT16
.gprel32 $load_32 # FFI_TYPE_UINT32
.gprel32 $load_32 # FFI_TYPE_SINT32
.gprel32 $load_64 # FFI_TYPE_UINT64
.gprel32 $load_64 # FFI_TYPE_SINT64
.gprel32 $load_none # FFI_TYPE_STRUCT
.gprel32 $load_64 # FFI_TYPE_POINTER
/* Assert that the table above is in sync with ffi.h. */
#if FFI_TYPE_FLOAT != 2 \
|| FFI_TYPE_DOUBLE != 3 \
|| FFI_TYPE_UINT8 != 5 \
|| FFI_TYPE_SINT8 != 6 \
|| FFI_TYPE_UINT16 != 7 \
|| FFI_TYPE_SINT16 != 8 \
|| FFI_TYPE_UINT32 != 9 \
|| FFI_TYPE_SINT32 != 10 \
|| FFI_TYPE_UINT64 != 11 \
|| FFI_TYPE_SINT64 != 12 \
|| FFI_TYPE_STRUCT != 13 \
|| FFI_TYPE_POINTER != 14 \
|| FFI_TYPE_LAST != 14
#error "osf.S out of sync with ffi.h"
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment