summaryrefslogtreecommitdiff
path: root/libffi
diff options
context:
space:
mode:
Diffstat (limited to 'libffi')
-rw-r--r--libffi/ChangeLog10
-rw-r--r--libffi/src/alpha/ffi.c20
-rw-r--r--libffi/src/alpha/osf.S125
3 files changed, 130 insertions, 25 deletions
diff --git a/libffi/ChangeLog b/libffi/ChangeLog
index 71dad419174..bd2e83ce05b 100644
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,4 +1,12 @@
-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.
(ffi_prep_closure): Likewise.
diff --git a/libffi/src/alpha/ffi.c b/libffi/src/alpha/ffi.c
index 84ee8494e3d..29292e6abe6 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 9ed37cbb00e..fce089ac05d 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