summaryrefslogtreecommitdiff
path: root/src/alpha
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2014-10-17 12:33:53 -0700
committerRichard Henderson <rth@twiddle.net>2014-11-12 09:30:59 +0100
commit32a26b75ba92665fa093b539318e83d916e3effb (patch)
treeaeaf5e4ea0e76e4198f42ce8c51da771dc22533f /src/alpha
parentc6352b664c31835b9527d747f8a29b4754cabb0e (diff)
downloadlibffi-32a26b75ba92665fa093b539318e83d916e3effb.tar.gz
alpha: Reorganize cif flags
Unties the backend from changes to FFI_TYPE_* constants, and allows compilation to succeed after the addition of FFI_TYPE_COMPLEX. Delete the hand-written unwind info.
Diffstat (limited to 'src/alpha')
-rw-r--r--src/alpha/ffi.c63
-rw-r--r--src/alpha/internal.h19
-rw-r--r--src/alpha/osf.S341
3 files changed, 160 insertions, 263 deletions
diff --git a/src/alpha/ffi.c b/src/alpha/ffi.c
index 192f691..519bd2c 100644
--- a/src/alpha/ffi.c
+++ b/src/alpha/ffi.c
@@ -28,6 +28,7 @@
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
+#include "internal.h"
/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
all further uses in this file will refer to the 128-bit type. */
@@ -48,6 +49,8 @@ extern void ffi_closure_osf(void) FFI_HIDDEN;
ffi_status
ffi_prep_cif_machdep(ffi_cif *cif)
{
+ int flags;
+
/* Adjust cif->bytes to represent a minimum 6 words for the temporary
register argument loading area. */
if (cif->bytes < 6*FFI_SIZEOF_ARG)
@@ -56,21 +59,46 @@ ffi_prep_cif_machdep(ffi_cif *cif)
/* Set the return type flag */
switch (cif->rtype->type)
{
- case FFI_TYPE_STRUCT:
+ case FFI_TYPE_VOID:
+ flags = ALPHA_FLAGS(ALPHA_ST_VOID, ALPHA_LD_VOID);
+ break;
+ case FFI_TYPE_INT:
+ case FFI_TYPE_UINT32:
+ case FFI_TYPE_SINT32:
+ flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT32);
+ break;
case FFI_TYPE_FLOAT:
+ flags = ALPHA_FLAGS(ALPHA_ST_FLOAT, ALPHA_LD_FLOAT);
+ break;
case FFI_TYPE_DOUBLE:
- cif->flags = cif->rtype->type;
+ flags = ALPHA_FLAGS(ALPHA_ST_DOUBLE, ALPHA_LD_DOUBLE);
+ break;
+ case FFI_TYPE_UINT8:
+ flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_UINT8);
+ break;
+ case FFI_TYPE_SINT8:
+ flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_SINT8);
+ break;
+ case FFI_TYPE_UINT16:
+ flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_UINT16);
+ break;
+ case FFI_TYPE_SINT16:
+ flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_SINT16);
+ break;
+ case FFI_TYPE_UINT64:
+ case FFI_TYPE_SINT64:
+ case FFI_TYPE_POINTER:
+ flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT64);
break;
-
case FFI_TYPE_LONGDOUBLE:
- /* 128-bit long double is returned in memory, like a struct. */
- cif->flags = FFI_TYPE_STRUCT;
+ case FFI_TYPE_STRUCT:
+ /* Passed in memory, with a hidden pointer. */
+ flags = ALPHA_RET_IN_MEM;
break;
-
default:
- cif->flags = FFI_TYPE_INT;
- break;
+ abort();
}
+ cif->flags = flags;
return FFI_OK;
}
@@ -80,20 +108,20 @@ void
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
unsigned long *stack, *argp;
- long i, avn;
+ long i, avn, flags = cif->flags;
ffi_type **arg_types;
/* 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->flags == FFI_TYPE_STRUCT)
+ if (rvalue == NULL && flags == ALPHA_RET_IN_MEM)
rvalue = alloca(cif->rtype->size);
/* Allocate the space for the arguments, plus 4 words of temp
space for ffi_call_osf. */
argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
- if (cif->flags == FFI_TYPE_STRUCT)
- *(void **) argp++ = rvalue;
+ if (flags == ALPHA_RET_IN_MEM)
+ *argp++ = (unsigned long)rvalue;
i = 0;
avn = cif->nargs;
@@ -166,7 +194,8 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
i++, arg_types++, avalue++;
}
- ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn);
+ flags = (flags >> ALPHA_ST_SHIFT) & 0xff;
+ ffi_call_osf(stack, cif->bytes, flags, rvalue, fn);
}
@@ -211,16 +240,16 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
ffi_cif *cif;
void **avalue;
ffi_type **arg_types;
- long i, avn, argn;
+ long i, avn, argn, flags;
cif = closure->cif;
avalue = alloca(cif->nargs * sizeof(void *));
-
+ flags = cif->flags;
argn = 0;
/* Copy the caller's structure return address to that the closure
returns the data directly to the caller. */
- if (cif->flags == FFI_TYPE_STRUCT)
+ if (flags == ALPHA_RET_IN_MEM)
{
rvalue = (void *) argp[0];
argn = 1;
@@ -284,5 +313,5 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
closure->fun (cif, rvalue, avalue, closure->user_data);
/* Tell ffi_closure_osf how to perform return type promotions. */
- return cif->rtype->type;
+ return (flags >> ALPHA_LD_SHIFT) & 0xff;
}
diff --git a/src/alpha/internal.h b/src/alpha/internal.h
new file mode 100644
index 0000000..664a2a6
--- /dev/null
+++ b/src/alpha/internal.h
@@ -0,0 +1,19 @@
+#define ALPHA_ST_VOID 0
+#define ALPHA_ST_INT 1
+#define ALPHA_ST_FLOAT 2
+#define ALPHA_ST_DOUBLE 3
+
+#define ALPHA_LD_VOID 0
+#define ALPHA_LD_INT64 1
+#define ALPHA_LD_INT32 2
+#define ALPHA_LD_UINT16 3
+#define ALPHA_LD_SINT16 4
+#define ALPHA_LD_UINT8 5
+#define ALPHA_LD_SINT8 6
+#define ALPHA_LD_FLOAT 7
+#define ALPHA_LD_DOUBLE 8
+
+#define ALPHA_ST_SHIFT 0
+#define ALPHA_LD_SHIFT 8
+#define ALPHA_RET_IN_MEM 0x10000
+#define ALPHA_FLAGS(S, L) (((L) << ALPHA_LD_SHIFT) | (S))
diff --git a/src/alpha/osf.S b/src/alpha/osf.S
index 6b9f4df..fb9c595 100644
--- a/src/alpha/osf.S
+++ b/src/alpha/osf.S
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------
- osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011 Red Hat
-
- Alpha/OSF Foreign Function Interface
+ osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011, 2014 Red Hat
+
+ Alpha/OSF Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -24,13 +24,21 @@
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
-#define LIBFFI_ASM
+#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
+#include <ffi_cfi.h>
+#include "internal.h"
.arch ev6
.text
+/* Aid in building a direct addressed jump table, 4 insns per entry. */
+.macro E index
+ .align 4
+ .org 99b + \index * 16
+.endm
+
/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
void *raddr, void (*fnaddr)(void));
@@ -38,7 +46,7 @@
for this function. This has been allocated by ffi_call. We also
deallocate some of the stack that has been alloca'd. */
- .align 3
+ .align 4
.globl ffi_call_osf
.ent ffi_call_osf
FFI_HIDDEN(ffi_call_osf)
@@ -46,15 +54,17 @@
ffi_call_osf:
.frame $15, 32, $26, 0
.mask 0x4008000, -32
-$LFB1:
+ cfi_startproc
addq $16,$17,$1
mov $16, $30
stq $26, 0($1)
stq $15, 8($1)
stq $18, 16($1)
mov $1, $15
-$LCFI1:
.prologue 0
+ cfi_def_cfa($15, 32)
+ cfi_rel_offset($26, 0)
+ cfi_rel_offset($15, 8)
stq $19, 24($1)
mov $20, $27
@@ -77,71 +87,61 @@ $LCFI1:
lda $30, 48($30)
jsr $26, ($27), 0
- ldgp $29, 0($26)
-
- # If the return value pointer is NULL, assume no return value.
- ldq $19, 24($15)
- ldq $18, 16($15)
+0:
+ ldah $29, 0($26) !gpdisp!1
+ ldq $2, 24($15)
+ lda $29, 0($29) !gpdisp!1
+ ldq $3, 16($15)
+ lda $1, 99f-0b($26)
ldq $26, 0($15)
-$LCFI2:
- beq $19, $noretval
-
- # Store the return value out in the proper type.
- cmpeq $18, FFI_TYPE_INT, $1
- bne $1, $retint
- cmpeq $18, FFI_TYPE_FLOAT, $2
- bne $2, $retfloat
- cmpeq $18, FFI_TYPE_DOUBLE, $3
- bne $3, $retdouble
-
- .align 3
-$noretval:
ldq $15, 8($15)
- ret
+ cfi_restore($26)
+ cfi_restore($15)
+ cfi_def_cfa($sp, 0)
+ cmoveq $2, ALPHA_ST_VOID, $3 # mash null return to void
+ addq $3, $3, $3
+ s8addq $3, $1, $1 # 99f + stcode * 16
+ jmp $31, ($1), $st_int
.align 4
-$retint:
- stq $0, 0($19)
- nop
- ldq $15, 8($15)
+99:
+E ALPHA_ST_VOID
ret
-
- .align 4
-$retfloat:
- sts $f0, 0($19)
- nop
- ldq $15, 8($15)
+E ALPHA_ST_INT
+$st_int:
+ stq $0, 0($2)
ret
-
- .align 4
-$retdouble:
- stt $f0, 0($19)
- nop
- ldq $15, 8($15)
+E ALPHA_ST_FLOAT
+ sts $f0, 0($2)
+ ret
+E ALPHA_ST_DOUBLE
+ stt $f0, 0($2)
ret
-$LFE1:
+ cfi_endproc
.end ffi_call_osf
/* ffi_closure_osf(...)
Receives the closure argument in $1. */
- .align 3
+#define CLOSURE_FS (16*8)
+
+ .align 4
.globl ffi_closure_osf
.ent ffi_closure_osf
FFI_HIDDEN(ffi_closure_osf)
ffi_closure_osf:
- .frame $30, 16*8, $26, 0
- .mask 0x4000000, -16*8
-$LFB2:
+ .frame $30, CLOSURE_FS, $26, 0
+ .mask 0x4000000, -CLOSURE_FS
+ cfi_startproc
ldgp $29, 0($27)
- subq $30, 16*8, $30
-$LCFI5:
+ subq $30, CLOSURE_FS, $30
+ cfi_adjust_cfa_offset(CLOSURE_FS)
stq $26, 0($30)
-$LCFI6:
.prologue 1
+ cfi_rel_offset($26, 0)
# Store all of the potential argument registers in va_list format.
stt $f16, 4*8($30)
@@ -162,225 +162,74 @@ $LCFI6:
lda $17, 2*8($30)
lda $18, 10*8($30)
jsr $26, ffi_closure_osf_inner
- ldgp $29, 0($26)
+0:
+ ldah $29, 0($26) !gpdisp!2
+ lda $2, 99f-0b($26)
+ s4addq $0, 0, $1 # ldcode * 4
+ ldq $0, 16($30) # preload return value
+ s4addq $1, $2, $1 # 99f + ldcode * 16
+ lda $29, 0($29) !gpdisp!2
ldq $26, 0($30)
-
- # Load up the return value in the proper type.
- lda $1, $load_table
- s4addq $0, $1, $1
- ldl $1, 0($1)
- addq $1, $29, $1
+ cfi_restore($26)
jmp $31, ($1), $load_32
- .align 4
-$load_none:
- addq $30, 16*8, $30
+.macro epilogue
+ addq $30, CLOSURE_FS, $30
+ cfi_adjust_cfa_offset(-CLOSURE_FS)
ret
+ .align 4
+ cfi_adjust_cfa_offset(CLOSURE_FS)
+.endm
.align 4
-$load_float:
- lds $f0, 16($30)
- nop
- addq $30, 16*8, $30
- ret
+99:
+E ALPHA_LD_VOID
+ epilogue
- .align 4
-$load_double:
- ldt $f0, 16($30)
- nop
- addq $30, 16*8, $30
- ret
+E ALPHA_LD_INT64
+ epilogue
- .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 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
+E ALPHA_LD_INT32
+$load_32:
+ sextl $0, $0
+ epilogue
- .align 4
-$load_u16:
-#ifdef __alpha_bwx__
- ldwu $0, 16($30)
- nop
-#else
- ldq $0, 16($30)
+E ALPHA_LD_UINT16
zapnot $0, 3, $0
-#endif
- addq $30, 16*8, $30
- ret
+ epilogue
- .align 4
-$load_s16:
+E ALPHA_LD_SINT16
#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
+ epilogue
- .align 4
-$load_32:
- ldl $0, 16($30)
- nop
- addq $30, 16*8, $30
- ret
+E ALPHA_LD_UINT8
+ and $0, 0xff, $0
+ epilogue
- .align 4
-$load_64:
- ldq $0, 16($30)
- nop
- addq $30, 16*8, $30
- ret
-$LFE2:
-
- .end ffi_closure_osf
-
-#ifdef __ELF__
-.section .rodata
+E ALPHA_LD_SINT8
+#ifdef __alpha_bwx__
+ sextb $0, $0
#else
-.rdata
-#endif
-$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_none # 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"
+ sll $0, 56, $0
+ sra $0, 56, $0
#endif
+ epilogue
-#ifdef __ELF__
-# define UA_SI .4byte
-# define FDE_ENCODING 0x1b /* pcrel sdata4 */
-# define FDE_ENCODE(X) .4byte X-.
-# define FDE_ARANGE(X) .4byte X
-#elif defined __osf__
-# define UA_SI .align 0; .long
-# define FDE_ENCODING 0x50 /* aligned absolute */
-# define FDE_ENCODE(X) .align 3; .quad X
-# define FDE_ARANGE(X) .align 0; .quad X
-#endif
+E ALPHA_LD_FLOAT
+ lds $f0, 16($sp)
+ epilogue
-#ifdef __ELF__
- .section .eh_frame,EH_FRAME_FLAGS,@progbits
-#elif defined __osf__
- .data
- .align 3
- .globl _GLOBAL__F_ffi_call_osf
-_GLOBAL__F_ffi_call_osf:
-#endif
-__FRAME_BEGIN__:
- UA_SI $LECIE1-$LSCIE1 # Length of Common Information Entry
-$LSCIE1:
- UA_SI 0x0 # CIE Identifier Tag
- .byte 0x1 # CIE Version
- .ascii "zR\0" # CIE Augmentation
- .byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
- .byte 0x78 # sleb128 -8; CIE Data Alignment Factor
- .byte 26 # CIE RA Column
- .byte 0x1 # uleb128 0x1; Augmentation size
- .byte FDE_ENCODING # FDE Encoding
- .byte 0xc # DW_CFA_def_cfa
- .byte 30 # uleb128 column 30
- .byte 0 # uleb128 offset 0
- .align 3
-$LECIE1:
-$LSFDE1:
- UA_SI $LEFDE1-$LASFDE1 # FDE Length
-$LASFDE1:
- UA_SI $LASFDE1-__FRAME_BEGIN__ # FDE CIE offset
- FDE_ENCODE($LFB1) # FDE initial location
- FDE_ARANGE($LFE1-$LFB1) # FDE address range
- .byte 0x0 # uleb128 0x0; Augmentation size
-
- .byte 0x4 # DW_CFA_advance_loc4
- UA_SI $LCFI1-$LFB1
- .byte 0x9a # DW_CFA_offset, column 26
- .byte 4 # uleb128 4*-8
- .byte 0x8f # DW_CFA_offset, column 15
- .byte 0x3 # uleb128 3*-8
- .byte 0xc # DW_CFA_def_cfa
- .byte 15 # uleb128 column 15
- .byte 32 # uleb128 offset 32
-
- .byte 0x4 # DW_CFA_advance_loc4
- UA_SI $LCFI2-$LCFI1
- .byte 0xda # DW_CFA_restore, column 26
- .align 3
-$LEFDE1:
-
-$LSFDE3:
- UA_SI $LEFDE3-$LASFDE3 # FDE Length
-$LASFDE3:
- UA_SI $LASFDE3-__FRAME_BEGIN__ # FDE CIE offset
- FDE_ENCODE($LFB2) # FDE initial location
- FDE_ARANGE($LFE2-$LFB2) # FDE address range
- .byte 0x0 # uleb128 0x0; Augmentation size
-
- .byte 0x4 # DW_CFA_advance_loc4
- UA_SI $LCFI5-$LFB2
- .byte 0xe # DW_CFA_def_cfa_offset
- .byte 0x80,0x1 # uleb128 128
-
- .byte 0x4 # DW_CFA_advance_loc4
- UA_SI $LCFI6-$LCFI5
- .byte 0x9a # DW_CFA_offset, column 26
- .byte 16 # uleb128 offset 16*-8
- .align 3
-$LEFDE3:
-#if defined __osf__
- .align 0
- .long 0 # End of Table
-#endif
+E ALPHA_LD_DOUBLE
+ ldt $f0, 16($sp)
+ epilogue
+
+ cfi_endproc
+ .end ffi_closure_osf
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",@progbits