#include <tramp.h>
#include "internal.h"
-#if defined(_MSC_VER) && defined(_M_ARM)
+#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#endif
#else
-#ifndef _M_ARM
+#ifndef _WIN32
extern unsigned int ffi_arm_trampoline[2] FFI_HIDDEN;
#else
-extern unsigned int ffi_arm_trampoline[3] FFI_HIDDEN;
+// Declare this as an array of char, instead of array of int,
+// otherwise Clang optimizes out the "& 0xFFFFFFFE" for clearing
+// the thumb bit.
+extern unsigned char ffi_arm_trampoline[12] FFI_HIDDEN;
#endif
#endif
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_POINTER:
-#ifndef _MSC_VER
+#ifndef _WIN32
case FFI_TYPE_FLOAT:
#endif
*(UINT32 *)dst = *(UINT32 *)src;
break;
-#ifdef _MSC_VER
+#ifdef _WIN32
// casting a float* to a UINT32* doesn't work on Windows
case FFI_TYPE_FLOAT:
*(uintptr_t *)dst = 0;
#endif
/* Initialize the dynamic trampoline. */
-#ifndef _M_ARM
+#ifndef _WIN32
memcpy(closure->tramp, ffi_arm_trampoline, 8);
#else
// cast away function type so MSVC doesn't set the lower bit of the function pointer
#if defined (__QNX__)
msync(closure->tramp, 8, 0x1000000); /* clear data map */
msync(codeloc, 8, 0x1000000); /* clear insn map */
-#elif defined(_MSC_VER)
+#elif defined(_WIN32)
FlushInstructionCache(GetCurrentProcess(), closure->tramp, FFI_TRAMPOLINE_SIZE);
#else
__clear_cache(closure->tramp, closure->tramp + 8); /* clear data map */
__clear_cache(codeloc, codeloc + 8); /* clear insn map */
#endif
-#ifdef _M_ARM
+#ifdef _WIN32
*(void(**)(void))(closure->tramp + FFI_TRAMPOLINE_CLOSURE_FUNCTION) = closure_func;
#else
*(void (**)(void))(closure->tramp + 8) = closure_func;
FFI_SYSV,
FFI_VFP,
FFI_LAST_ABI,
-#if defined(__ARM_PCS_VFP) || defined(_M_ARM)
+#if defined(__ARM_PCS_VFP) || defined(_WIN32)
FFI_DEFAULT_ABI = FFI_VFP,
#else
FFI_DEFAULT_ABI = FFI_SYSV,
signed char vfp_args[16] \
#define FFI_TARGET_SPECIFIC_VARIADIC
-#ifndef _M_ARM
+#ifndef _WIN32
#define FFI_TARGET_HAS_COMPLEX_TYPE
#endif
#endif
#else
-#ifdef _MSC_VER
+#ifdef _WIN32
#define FFI_TRAMPOLINE_SIZE 16
#define FFI_TRAMPOLINE_CLOSURE_FUNCTION 12
#else
#define ARM_FUNC_END(name) \
SIZE(name)
+ .text
+ .syntax unified
+#if defined(_WIN32)
+ /* Windows on ARM is thumb-only */
+ .thumb
+#else
+ /* Keep the assembly in ARM mode in other cases, for simplicity
+ * (to avoid interworking issues). */
+#undef __thumb__
+ .arm
+#endif
+
/* Aid in defining a jump table with 8 bytes between entries. */
+#ifdef __thumb__
+/* In thumb mode, instructions can be shorter than expected in arm mode, so
+ * we need to align the start of each case. */
+# define E(index) .align 3
+#elif defined(__clang__)
/* ??? The clang assembler doesn't handle .if with symbolic expressions. */
-#ifdef __clang__
# define E(index)
#else
# define E(index) \
.endif
#endif
- .text
- .syntax unified
- .arm
#ifndef __clang__
/* We require interworking on LDM, which implies ARMv5T,
cfi_startproc
cmp r3, #3 @ load only d0 if possible
+ ite le
#ifdef __clang__
vldrle d0, [r0]
vldmgt r0, {d0-d7}
cfi_def_cfa_register(sp)
@ Store values stored in registers.
+#ifndef __thumb__
.align 3
add pc, pc, r3, lsl #3
nop
+#else
+ adr ip, 0f
+ add ip, ip, r3, lsl #3
+ mov pc, ip
+ .align 3
+#endif
0:
E(ARM_TYPE_VFP_S)
#ifdef __clang__
ARM_FUNC_START(ffi_closure_SYSV)
UNWIND(.fnstart)
cfi_startproc
+#ifdef _WIN32
+ ldmfd sp!, {r0, ip} @ restore fp (r0 is used for stack alignment)
+#endif
stmdb sp!, {r0-r3} @ save argument regs
cfi_adjust_cfa_offset(16)
@ Load values returned in registers.
add r2, sp, #8+64 @ load result
adr r3, CNAME(ffi_closure_ret)
+#ifndef __thumb__
add pc, r3, r0, lsl #3
+#else
+ add r3, r3, r0, lsl #3
+ mov pc, r3
+#endif
cfi_endproc
UNWIND(.fnend)
ARM_FUNC_END(ffi_closure_SYSV)
ARM_FUNC_START(ffi_closure_VFP)
UNWIND(.fnstart)
cfi_startproc
+#ifdef _WIN32
+ ldmfd sp!, {r0, ip} @ restore fp (r0 is used for stack alignment)
+#endif
stmdb sp!, {r0-r3} @ save argument regs
cfi_adjust_cfa_offset(16)
@ Load values returned in registers.
add r2, sp, #8+64 @ load result
adr r3, CNAME(ffi_closure_ret)
+#ifndef __thumb__
add pc, r3, r0, lsl #3
+#else
+ add r3, r3, r0, lsl #3
+ mov pc, r3
+#endif
cfi_endproc
UNWIND(.fnend)
ARM_FUNC_END(ffi_closure_VFP)
#else
ldc p10, cr0, [r2] @ vldr s0, [r2]
#endif
- ldm sp, {sp,pc}
+ b call_epilogue
E(ARM_TYPE_VFP_D)
#ifdef __clang__
vldr d0, [r2]
#else
ldc p11, cr0, [r2] @ vldr d0, [r2]
#endif
- ldm sp, {sp,pc}
+ b call_epilogue
E(ARM_TYPE_VFP_N)
#ifdef __clang__
vldm r2, {d0-d3}
#else
ldc p11, cr0, [r2], {8} @ vldm r2, {d0-d3}
#endif
- ldm sp, {sp,pc}
+ b call_epilogue
E(ARM_TYPE_INT64)
ldr r1, [r2, #4]
nop
E(ARM_TYPE_INT)
ldr r0, [r2]
- ldm sp, {sp,pc}
+ b call_epilogue
E(ARM_TYPE_VOID)
- ldm sp, {sp,pc}
+ b call_epilogue
nop
E(ARM_TYPE_STRUCT)
+ b call_epilogue
+call_epilogue:
+#ifndef __thumb__
ldm sp, {sp,pc}
+#else
+ ldm sp, {ip,lr}
+ mov sp, ip
+ bx lr
+#endif
cfi_endproc
ARM_FUNC_END(ffi_closure_ret)
ARM_FUNC_END(ffi_closure_trampoline_table_page)
#endif
+#elif defined(_WIN32)
+
+ARM_FUNC_START(ffi_arm_trampoline)
+0: adr ip, 0b
+ stmdb sp!, {r0, ip}
+ ldr pc, 1f
+1: .long 0
+ARM_FUNC_END(ffi_arm_trampoline)
+
#else
ARM_FUNC_START(ffi_arm_trampoline)