aboutsummaryrefslogtreecommitdiff
path: root/libffi/src
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2000-12-09 23:13:18 -0800
committerAnthony Green <green@gcc.gnu.org>2000-12-10 07:13:18 +0000
commit3f67ba6e957d9d03126c0c241f592c4a94ad7440 (patch)
tree79170559bd34c678d6bd594b9a8884741a5f0cae /libffi/src
parentbc38c7877529a30dc7fcd1b231041881c3d45a1e (diff)
downloadgcc-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.c20
-rw-r--r--libffi/src/alpha/osf.S125
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