diff options
author | Richard Henderson <rth@redhat.com> | 2000-12-09 23:13:18 -0800 |
---|---|---|
committer | Anthony Green <green@gcc.gnu.org> | 2000-12-10 07:13:18 +0000 |
commit | 3f67ba6e957d9d03126c0c241f592c4a94ad7440 (patch) | |
tree | 79170559bd34c678d6bd594b9a8884741a5f0cae /libffi/src | |
parent | bc38c7877529a30dc7fcd1b231041881c3d45a1e (diff) | |
download | gcc-3f67ba6e957d9d03126c0c241f592c4a94ad7440.zip gcc-3f67ba6e957d9d03126c0c241f592c4a94ad7440.tar.gz gcc-3f67ba6e957d9d03126c0c241f592c4a94ad7440.tar.bz2 |
Richards changes to the closure code for alpha
From-SVN: r38169
Diffstat (limited to 'libffi/src')
-rw-r--r-- | libffi/src/alpha/ffi.c | 20 | ||||
-rw-r--r-- | libffi/src/alpha/osf.S | 125 |
2 files changed, 121 insertions, 24 deletions
diff --git a/libffi/src/alpha/ffi.c b/libffi/src/alpha/ffi.c index 84ee849..29292e6 100644 --- a/libffi/src/alpha/ffi.c +++ b/libffi/src/alpha/ffi.c @@ -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 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); /* 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) /* Grab the addresses of the arguments from the stack frame. */ while (i < avn) { - switch ((*arg_types)->type) + switch (arg_types[i]->type) { case FFI_TYPE_SINT8: case FFI_TYPE_UINT8: @@ -214,7 +214,7 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp) case FFI_TYPE_UINT64: case FFI_TYPE_POINTER: case FFI_TYPE_STRUCT: - *avalue = &argp[argn]; + avalue[i] = &argp[argn]; break; case FFI_TYPE_FLOAT: @@ -223,27 +223,27 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp) /* Floats coming from registers need conversion from double back to float format. */ *(float *)&argp[argn - 6] = *(double *)&argp[argn - 6]; - *avalue = &argp[argn - 6]; + avalue[i] = &argp[argn - 6]; } else - *avalue = &argp[argn]; + avalue[i] = &argp[argn]; break; case FFI_TYPE_DOUBLE: - *avalue = &argp[argn - (argn < 6 ? 6 : 0)]; + avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)]; break; default: FFI_ASSERT(0); } - argn += ALIGN((*arg_types)->size, SIZEOF_ARG) / SIZEOF_ARG; - i++, arg_types++, avalue++; + argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG; + i++; } /* Invoke the closure. */ (closure->fun) (cif, rvalue, avalue, closure->user_data); - /* Tell ffi_closure_osf what register to put the return value in. */ - return cif->flags; + /* Tell ffi_closure_osf how to perform return type promotions. */ + return cif->rtype->type; } diff --git a/libffi/src/alpha/osf.S b/libffi/src/alpha/osf.S index 9ed37cb..fce089a 100644 --- a/libffi/src/alpha/osf.S +++ b/libffi/src/alpha/osf.S @@ -28,6 +28,7 @@ #define LIBFFI_ASM #include <ffi.h> + .arch ev6 .text /* ffi_call_osf (void *args, unsigned long bytes, unsigned flags, @@ -121,9 +122,9 @@ $retdouble: .ent ffi_closure_osf ffi_closure_osf: .frame $30, 16*8, $26, 0 - .mask 0x4000000, -14*8 + .mask 0x4000000, -16*8 ldgp $29, 0($27) - subq $30, 14*8, $30 + subq $30, 16*8, $30 stq $26, 0($30) .prologue 1 @@ -150,33 +151,129 @@ ffi_closure_osf: ldq $26, 0($30) # Load up the return value in the proper type. - cmpeq $0, FFI_TYPE_INT, $1 - bne $1, $loadint - cmpeq $0, FFI_TYPE_FLOAT, $2 - bne $2, $loadfloat - cmpeq $18, FFI_TYPE_DOUBLE, $3 - bne $3, $loaddouble + lda $1, $load_table + s4addq $0, $1, $1 + ldl $1, 0($1) + addq $1, $29, $1 + jmp $31, ($1), $load_32 + + .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 ret - .align 3 -$loadint: + .align 4 +$load_s8: +#ifdef __alpha_bwx__ + ldbu $0, 16($30) + sextb $0, $0 +#else 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 +#else + ldq $0, 16($30) + zapnot $0, 3, $0 +#endif addq $30, 16*8, $30 ret -$loadfloat: - lds $f0, 16($30) + .align 4 +$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 addq $30, 16*8, $30 ret -$loaddouble: - ldt $f0, 16($30) + .align 4 +$load_64: + ldq $0, 16($30) nop addq $30, 16*8, $30 ret .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 |