mirror of
https://github.com/partic2/libffi
synced 2026-11-10 01:57:19 +00:00
It's way too different from the 32-bit ABIs with which it is currently associated. As seen from all of the existing XFAILs.
220 lines
4.3 KiB
ArmAsm
220 lines
4.3 KiB
ArmAsm
#define LIBFFI_ASM
|
|
#include <fficonfig.h>
|
|
#include <ffi.h>
|
|
#include <ffi_cfi.h>
|
|
|
|
#if defined(HAVE_AS_CFI_PSEUDO_OP)
|
|
.cfi_sections .debug_frame
|
|
#endif
|
|
|
|
#define arg0 %rcx
|
|
#define arg1 %rdx
|
|
#define arg2 %r8
|
|
#define arg3 %r9
|
|
|
|
#ifdef SYMBOL_UNDERSCORE
|
|
#define SYMBOL_NAME(name) _##name
|
|
#else
|
|
#define SYMBOL_NAME(name) name
|
|
#endif
|
|
|
|
.macro E which
|
|
.align 8
|
|
.org 0b + \which * 8
|
|
.endm
|
|
|
|
.text
|
|
|
|
/* ffi_call_win64 (void *stack, struct win64_call_frame *frame, void *r10)
|
|
|
|
Bit o trickiness here -- FRAME is the base of the stack frame
|
|
for this function. This has been allocated by ffi_call. We also
|
|
deallocate some of the stack that has been alloca'd. */
|
|
|
|
.align 8
|
|
.globl ffi_call_win64
|
|
|
|
.seh_proc ffi_call_win64
|
|
ffi_call_win64:
|
|
cfi_startproc
|
|
/* Set up the local stack frame and install it in rbp/rsp. */
|
|
movq (%rsp), %rax
|
|
movq %rbp, (arg1)
|
|
movq %rax, 8(arg1)
|
|
movq arg1, %rbp
|
|
cfi_def_cfa(%rbp, 16)
|
|
cfi_rel_offset(%rbp, 0)
|
|
.seh_pushreg %rbp
|
|
.seh_setframe %rbp, 0
|
|
.seh_endprologue
|
|
movq arg0, %rsp
|
|
|
|
movq arg2, %r10
|
|
|
|
/* Load all slots into both general and xmm registers. */
|
|
movq (%rsp), %rcx
|
|
movsd (%rsp), %xmm0
|
|
movq 8(%rsp), %rdx
|
|
movsd 8(%rsp), %xmm1
|
|
movq 16(%rsp), %r8
|
|
movsd 16(%rsp), %xmm2
|
|
movq 24(%rsp), %r9
|
|
movsd 24(%rsp), %xmm3
|
|
|
|
call *16(%rbp)
|
|
|
|
movl 24(%rbp), %ecx
|
|
movq 32(%rbp), %r8
|
|
leaq 0f(%rip), %r10
|
|
cmpl $FFI_TYPE_SMALL_STRUCT_4B, %ecx
|
|
leaq (%r10, %rcx, 8), %r10
|
|
ja 99f
|
|
jmp *%r10
|
|
|
|
/* Below, we're space constrained most of the time. Thus we eschew the
|
|
modern "mov, pop, ret" sequence (5 bytes) for "leave, ret" (2 bytes). */
|
|
.macro epilogue
|
|
leaveq
|
|
cfi_remember_state
|
|
cfi_def_cfa(%rsp, 8)
|
|
cfi_restore(%rbp)
|
|
ret
|
|
cfi_restore_state
|
|
.endm
|
|
|
|
.align 8
|
|
0:
|
|
E FFI_TYPE_VOID
|
|
epilogue
|
|
E FFI_TYPE_INT
|
|
movslq %eax, %rax
|
|
movq %rax, (%r8)
|
|
epilogue
|
|
E FFI_TYPE_FLOAT
|
|
movss %xmm0, (%r8)
|
|
epilogue
|
|
E FFI_TYPE_DOUBLE
|
|
movsd %xmm0, (%r8)
|
|
epilogue
|
|
E FFI_TYPE_LONGDOUBLE
|
|
call abort
|
|
E FFI_TYPE_UINT8
|
|
movzbl %al, %eax
|
|
movq %rax, (%r8)
|
|
epilogue
|
|
E FFI_TYPE_SINT8
|
|
movsbq %al, %rax
|
|
jmp 98f
|
|
E FFI_TYPE_UINT16
|
|
movzwl %ax, %eax
|
|
movq %rax, (%r8)
|
|
epilogue
|
|
E FFI_TYPE_SINT16
|
|
movswq %ax, %rax
|
|
jmp 98f
|
|
E FFI_TYPE_UINT32
|
|
movl %eax, %eax
|
|
movq %rax, (%r8)
|
|
epilogue
|
|
E FFI_TYPE_SINT32
|
|
movslq %eax, %rax
|
|
movq %rax, (%r8)
|
|
epilogue
|
|
E FFI_TYPE_UINT64
|
|
98: movq %rax, (%r8)
|
|
epilogue
|
|
E FFI_TYPE_SINT64
|
|
movq %rax, (%r8)
|
|
epilogue
|
|
E FFI_TYPE_STRUCT
|
|
epilogue
|
|
E FFI_TYPE_POINTER
|
|
movq %rax, (%r8)
|
|
epilogue
|
|
E FFI_TYPE_COMPLEX
|
|
call abort
|
|
E FFI_TYPE_SMALL_STRUCT_1B
|
|
movb %al, (%r8)
|
|
epilogue
|
|
E FFI_TYPE_SMALL_STRUCT_2B
|
|
movw %ax, (%r8)
|
|
epilogue
|
|
E FFI_TYPE_SMALL_STRUCT_4B
|
|
movl %eax, (%r8)
|
|
epilogue
|
|
|
|
.align 8
|
|
99: call abort
|
|
|
|
.purgem epilogue
|
|
|
|
cfi_endproc
|
|
.seh_endproc
|
|
|
|
|
|
/* 32 bytes of outgoing register stack space, 8 bytes of alignment,
|
|
16 bytes of result, 32 bytes of xmm registers. */
|
|
#define ffi_clo_FS (32+8+16+32)
|
|
#define ffi_clo_OFF_R (32+8)
|
|
#define ffi_clo_OFF_X (32+8+16)
|
|
|
|
.align 8
|
|
.globl ffi_go_closure_win64
|
|
|
|
.seh_proc ffi_go_closure_win64
|
|
ffi_go_closure_win64:
|
|
cfi_startproc
|
|
/* Save all integer arguments into the incoming reg stack space. */
|
|
movq arg0, 8(%rsp)
|
|
movq arg1, 16(%rsp)
|
|
movq arg2, 24(%rsp)
|
|
movq arg3, 32(%rsp)
|
|
|
|
movq 8(%r10), arg0 /* load cif */
|
|
movq 16(%r10), arg1 /* load fun */
|
|
movq %r10, arg2 /* closure is user_data */
|
|
jmp 0f
|
|
cfi_endproc
|
|
.seh_endproc
|
|
|
|
.align 8
|
|
.globl ffi_closure_win64
|
|
|
|
.seh_proc ffi_closure_win64
|
|
ffi_closure_win64:
|
|
cfi_startproc
|
|
/* Save all integer arguments into the incoming reg stack space. */
|
|
movq arg0, 8(%rsp)
|
|
movq arg1, 16(%rsp)
|
|
movq arg2, 24(%rsp)
|
|
movq arg3, 32(%rsp)
|
|
|
|
movq FFI_TRAMPOLINE_SIZE(%r10), arg0 /* load cif */
|
|
movq FFI_TRAMPOLINE_SIZE+8(%r10), arg1 /* load fun */
|
|
movq FFI_TRAMPOLINE_SIZE+16(%r10), arg2 /* load user_data */
|
|
0:
|
|
subq $ffi_clo_FS, %rsp
|
|
cfi_adjust_cfa_offset(ffi_clo_FS)
|
|
.seh_stackalloc ffi_clo_FS
|
|
.seh_endprologue
|
|
|
|
/* Save all sse arguments into the stack frame. */
|
|
movsd %xmm0, ffi_clo_OFF_X(%rsp)
|
|
movsd %xmm1, ffi_clo_OFF_X+8(%rsp)
|
|
movsd %xmm2, ffi_clo_OFF_X+16(%rsp)
|
|
movsd %xmm3, ffi_clo_OFF_X+24(%rsp)
|
|
|
|
leaq ffi_clo_OFF_R(%rsp), arg3
|
|
call ffi_closure_win64_inner
|
|
|
|
/* Load the result into both possible result registers. */
|
|
movq ffi_clo_OFF_R(%rsp), %rax
|
|
movsd ffi_clo_OFF_R(%rsp), %xmm0
|
|
|
|
addq $ffi_clo_FS, %rsp
|
|
cfi_adjust_cfa_offset(-ffi_clo_FS)
|
|
ret
|
|
|
|
cfi_endproc
|
|
.seh_endproc
|