1*1fd5a2e1SPrashanth Swaminathan/* ----------------------------------------------------------------------- 2*1fd5a2e1SPrashanth Swaminathan sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc. 3*1fd5a2e1SPrashanth Swaminathan Copyright (c) 2011 Plausible Labs Cooperative, Inc. 4*1fd5a2e1SPrashanth Swaminathan 5*1fd5a2e1SPrashanth Swaminathan ARM Foreign Function Interface 6*1fd5a2e1SPrashanth Swaminathan 7*1fd5a2e1SPrashanth Swaminathan Permission is hereby granted, free of charge, to any person obtaining 8*1fd5a2e1SPrashanth Swaminathan a copy of this software and associated documentation files (the 9*1fd5a2e1SPrashanth Swaminathan ``Software''), to deal in the Software without restriction, including 10*1fd5a2e1SPrashanth Swaminathan without limitation the rights to use, copy, modify, merge, publish, 11*1fd5a2e1SPrashanth Swaminathan distribute, sublicense, and/or sell copies of the Software, and to 12*1fd5a2e1SPrashanth Swaminathan permit persons to whom the Software is furnished to do so, subject to 13*1fd5a2e1SPrashanth Swaminathan the following conditions: 14*1fd5a2e1SPrashanth Swaminathan 15*1fd5a2e1SPrashanth Swaminathan The above copyright notice and this permission notice shall be included 16*1fd5a2e1SPrashanth Swaminathan in all copies or substantial portions of the Software. 17*1fd5a2e1SPrashanth Swaminathan 18*1fd5a2e1SPrashanth Swaminathan THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 19*1fd5a2e1SPrashanth Swaminathan EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20*1fd5a2e1SPrashanth Swaminathan MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21*1fd5a2e1SPrashanth Swaminathan NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22*1fd5a2e1SPrashanth Swaminathan HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23*1fd5a2e1SPrashanth Swaminathan WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24*1fd5a2e1SPrashanth Swaminathan OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25*1fd5a2e1SPrashanth Swaminathan DEALINGS IN THE SOFTWARE. 26*1fd5a2e1SPrashanth Swaminathan ----------------------------------------------------------------------- */ 27*1fd5a2e1SPrashanth Swaminathan 28*1fd5a2e1SPrashanth Swaminathan#ifdef __arm__ 29*1fd5a2e1SPrashanth Swaminathan#define LIBFFI_ASM 30*1fd5a2e1SPrashanth Swaminathan#include <fficonfig.h> 31*1fd5a2e1SPrashanth Swaminathan#include <ffi.h> 32*1fd5a2e1SPrashanth Swaminathan#include <ffi_cfi.h> 33*1fd5a2e1SPrashanth Swaminathan#include "internal.h" 34*1fd5a2e1SPrashanth Swaminathan 35*1fd5a2e1SPrashanth Swaminathan/* GCC 4.8 provides __ARM_ARCH; construct it otherwise. */ 36*1fd5a2e1SPrashanth Swaminathan#ifndef __ARM_ARCH 37*1fd5a2e1SPrashanth Swaminathan# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ 38*1fd5a2e1SPrashanth Swaminathan || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ 39*1fd5a2e1SPrashanth Swaminathan || defined(__ARM_ARCH_7EM__) 40*1fd5a2e1SPrashanth Swaminathan# define __ARM_ARCH 7 41*1fd5a2e1SPrashanth Swaminathan# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ 42*1fd5a2e1SPrashanth Swaminathan || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \ 43*1fd5a2e1SPrashanth Swaminathan || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \ 44*1fd5a2e1SPrashanth Swaminathan || defined(__ARM_ARCH_6M__) 45*1fd5a2e1SPrashanth Swaminathan# define __ARM_ARCH 6 46*1fd5a2e1SPrashanth Swaminathan# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \ 47*1fd5a2e1SPrashanth Swaminathan || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \ 48*1fd5a2e1SPrashanth Swaminathan || defined(__ARM_ARCH_5TEJ__) 49*1fd5a2e1SPrashanth Swaminathan# define __ARM_ARCH 5 50*1fd5a2e1SPrashanth Swaminathan# else 51*1fd5a2e1SPrashanth Swaminathan# define __ARM_ARCH 4 52*1fd5a2e1SPrashanth Swaminathan# endif 53*1fd5a2e1SPrashanth Swaminathan#endif 54*1fd5a2e1SPrashanth Swaminathan 55*1fd5a2e1SPrashanth Swaminathan/* Conditionally compile unwinder directives. */ 56*1fd5a2e1SPrashanth Swaminathan#ifdef __ARM_EABI__ 57*1fd5a2e1SPrashanth Swaminathan# define UNWIND(...) __VA_ARGS__ 58*1fd5a2e1SPrashanth Swaminathan#else 59*1fd5a2e1SPrashanth Swaminathan# define UNWIND(...) 60*1fd5a2e1SPrashanth Swaminathan#endif 61*1fd5a2e1SPrashanth Swaminathan 62*1fd5a2e1SPrashanth Swaminathan#if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__ARM_EABI__) 63*1fd5a2e1SPrashanth Swaminathan .cfi_sections .debug_frame 64*1fd5a2e1SPrashanth Swaminathan#endif 65*1fd5a2e1SPrashanth Swaminathan 66*1fd5a2e1SPrashanth Swaminathan#define CONCAT(a, b) CONCAT2(a, b) 67*1fd5a2e1SPrashanth Swaminathan#define CONCAT2(a, b) a ## b 68*1fd5a2e1SPrashanth Swaminathan 69*1fd5a2e1SPrashanth Swaminathan#ifdef __USER_LABEL_PREFIX__ 70*1fd5a2e1SPrashanth Swaminathan# define CNAME(X) CONCAT (__USER_LABEL_PREFIX__, X) 71*1fd5a2e1SPrashanth Swaminathan#else 72*1fd5a2e1SPrashanth Swaminathan# define CNAME(X) X 73*1fd5a2e1SPrashanth Swaminathan#endif 74*1fd5a2e1SPrashanth Swaminathan#ifdef __ELF__ 75*1fd5a2e1SPrashanth Swaminathan# define SIZE(X) .size CNAME(X), . - CNAME(X) 76*1fd5a2e1SPrashanth Swaminathan# define TYPE(X, Y) .type CNAME(X), Y 77*1fd5a2e1SPrashanth Swaminathan#else 78*1fd5a2e1SPrashanth Swaminathan# define SIZE(X) 79*1fd5a2e1SPrashanth Swaminathan# define TYPE(X, Y) 80*1fd5a2e1SPrashanth Swaminathan#endif 81*1fd5a2e1SPrashanth Swaminathan 82*1fd5a2e1SPrashanth Swaminathan#define ARM_FUNC_START_LOCAL(name) \ 83*1fd5a2e1SPrashanth Swaminathan .align 3; \ 84*1fd5a2e1SPrashanth Swaminathan TYPE(CNAME(name), %function); \ 85*1fd5a2e1SPrashanth Swaminathan CNAME(name): 86*1fd5a2e1SPrashanth Swaminathan 87*1fd5a2e1SPrashanth Swaminathan#define ARM_FUNC_START(name) \ 88*1fd5a2e1SPrashanth Swaminathan .globl CNAME(name); \ 89*1fd5a2e1SPrashanth Swaminathan FFI_HIDDEN(CNAME(name)); \ 90*1fd5a2e1SPrashanth Swaminathan ARM_FUNC_START_LOCAL(name) 91*1fd5a2e1SPrashanth Swaminathan 92*1fd5a2e1SPrashanth Swaminathan#define ARM_FUNC_END(name) \ 93*1fd5a2e1SPrashanth Swaminathan SIZE(name) 94*1fd5a2e1SPrashanth Swaminathan 95*1fd5a2e1SPrashanth Swaminathan/* Aid in defining a jump table with 8 bytes between entries. */ 96*1fd5a2e1SPrashanth Swaminathan/* ??? The clang assembler doesn't handle .if with symbolic expressions. */ 97*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__ 98*1fd5a2e1SPrashanth Swaminathan# define E(index) 99*1fd5a2e1SPrashanth Swaminathan#else 100*1fd5a2e1SPrashanth Swaminathan# define E(index) \ 101*1fd5a2e1SPrashanth Swaminathan .if . - 0b - 8*index; \ 102*1fd5a2e1SPrashanth Swaminathan .error "type table out of sync"; \ 103*1fd5a2e1SPrashanth Swaminathan .endif 104*1fd5a2e1SPrashanth Swaminathan#endif 105*1fd5a2e1SPrashanth Swaminathan 106*1fd5a2e1SPrashanth Swaminathan .text 107*1fd5a2e1SPrashanth Swaminathan .syntax unified 108*1fd5a2e1SPrashanth Swaminathan .arm 109*1fd5a2e1SPrashanth Swaminathan 110*1fd5a2e1SPrashanth Swaminathan#ifndef __clang__ 111*1fd5a2e1SPrashanth Swaminathan /* We require interworking on LDM, which implies ARMv5T, 112*1fd5a2e1SPrashanth Swaminathan which implies the existance of BLX. */ 113*1fd5a2e1SPrashanth Swaminathan .arch armv5t 114*1fd5a2e1SPrashanth Swaminathan#endif 115*1fd5a2e1SPrashanth Swaminathan 116*1fd5a2e1SPrashanth Swaminathan /* Note that we use STC and LDC to encode VFP instructions, 117*1fd5a2e1SPrashanth Swaminathan so that we do not need ".fpu vfp", nor get that added to 118*1fd5a2e1SPrashanth Swaminathan the object file attributes. These will not be executed 119*1fd5a2e1SPrashanth Swaminathan unless the FFI_VFP abi is used. */ 120*1fd5a2e1SPrashanth Swaminathan 121*1fd5a2e1SPrashanth Swaminathan @ r0: stack 122*1fd5a2e1SPrashanth Swaminathan @ r1: frame 123*1fd5a2e1SPrashanth Swaminathan @ r2: fn 124*1fd5a2e1SPrashanth Swaminathan @ r3: vfp_used 125*1fd5a2e1SPrashanth Swaminathan 126*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_call_VFP) 127*1fd5a2e1SPrashanth Swaminathan UNWIND(.fnstart) 128*1fd5a2e1SPrashanth Swaminathan cfi_startproc 129*1fd5a2e1SPrashanth Swaminathan 130*1fd5a2e1SPrashanth Swaminathan cmp r3, #3 @ load only d0 if possible 131*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__ 132*1fd5a2e1SPrashanth Swaminathan vldrle d0, [sp] 133*1fd5a2e1SPrashanth Swaminathan vldmgt sp, {d0-d7} 134*1fd5a2e1SPrashanth Swaminathan#else 135*1fd5a2e1SPrashanth Swaminathan ldcle p11, cr0, [r0] @ vldrle d0, [sp] 136*1fd5a2e1SPrashanth Swaminathan ldcgt p11, cr0, [r0], {16} @ vldmgt sp, {d0-d7} 137*1fd5a2e1SPrashanth Swaminathan#endif 138*1fd5a2e1SPrashanth Swaminathan add r0, r0, #64 @ discard the vfp register args 139*1fd5a2e1SPrashanth Swaminathan /* FALLTHRU */ 140*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_call_VFP) 141*1fd5a2e1SPrashanth Swaminathan 142*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_call_SYSV) 143*1fd5a2e1SPrashanth Swaminathan stm r1, {fp, lr} 144*1fd5a2e1SPrashanth Swaminathan mov fp, r1 145*1fd5a2e1SPrashanth Swaminathan 146*1fd5a2e1SPrashanth Swaminathan @ This is a bit of a lie wrt the origin of the unwind info, but 147*1fd5a2e1SPrashanth Swaminathan @ now we've got the usual frame pointer and two saved registers. 148*1fd5a2e1SPrashanth Swaminathan UNWIND(.save {fp,lr}) 149*1fd5a2e1SPrashanth Swaminathan UNWIND(.setfp fp, sp) 150*1fd5a2e1SPrashanth Swaminathan cfi_def_cfa(fp, 8) 151*1fd5a2e1SPrashanth Swaminathan cfi_rel_offset(fp, 0) 152*1fd5a2e1SPrashanth Swaminathan cfi_rel_offset(lr, 4) 153*1fd5a2e1SPrashanth Swaminathan 154*1fd5a2e1SPrashanth Swaminathan mov sp, r0 @ install the stack pointer 155*1fd5a2e1SPrashanth Swaminathan mov lr, r2 @ move the fn pointer out of the way 156*1fd5a2e1SPrashanth Swaminathan ldr ip, [fp, #16] @ install the static chain 157*1fd5a2e1SPrashanth Swaminathan ldmia sp!, {r0-r3} @ move first 4 parameters in registers. 158*1fd5a2e1SPrashanth Swaminathan blx lr @ call fn 159*1fd5a2e1SPrashanth Swaminathan 160*1fd5a2e1SPrashanth Swaminathan @ Load r2 with the pointer to storage for the return value 161*1fd5a2e1SPrashanth Swaminathan @ Load r3 with the return type code 162*1fd5a2e1SPrashanth Swaminathan ldr r2, [fp, #8] 163*1fd5a2e1SPrashanth Swaminathan ldr r3, [fp, #12] 164*1fd5a2e1SPrashanth Swaminathan 165*1fd5a2e1SPrashanth Swaminathan @ Deallocate the stack with the arguments. 166*1fd5a2e1SPrashanth Swaminathan mov sp, fp 167*1fd5a2e1SPrashanth Swaminathan cfi_def_cfa_register(sp) 168*1fd5a2e1SPrashanth Swaminathan 169*1fd5a2e1SPrashanth Swaminathan @ Store values stored in registers. 170*1fd5a2e1SPrashanth Swaminathan .align 3 171*1fd5a2e1SPrashanth Swaminathan add pc, pc, r3, lsl #3 172*1fd5a2e1SPrashanth Swaminathan nop 173*1fd5a2e1SPrashanth Swaminathan0: 174*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_S) 175*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__ 176*1fd5a2e1SPrashanth Swaminathan vstr s0, [r2] 177*1fd5a2e1SPrashanth Swaminathan#else 178*1fd5a2e1SPrashanth Swaminathan stc p10, cr0, [r2] @ vstr s0, [r2] 179*1fd5a2e1SPrashanth Swaminathan#endif 180*1fd5a2e1SPrashanth Swaminathan pop {fp,pc} 181*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_D) 182*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__ 183*1fd5a2e1SPrashanth Swaminathan vstr d0, [r2] 184*1fd5a2e1SPrashanth Swaminathan#else 185*1fd5a2e1SPrashanth Swaminathan stc p11, cr0, [r2] @ vstr d0, [r2] 186*1fd5a2e1SPrashanth Swaminathan#endif 187*1fd5a2e1SPrashanth Swaminathan pop {fp,pc} 188*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_N) 189*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__ 190*1fd5a2e1SPrashanth Swaminathan vstm r2, {d0-d3} 191*1fd5a2e1SPrashanth Swaminathan#else 192*1fd5a2e1SPrashanth Swaminathan stc p11, cr0, [r2], {8} @ vstm r2, {d0-d3} 193*1fd5a2e1SPrashanth Swaminathan#endif 194*1fd5a2e1SPrashanth Swaminathan pop {fp,pc} 195*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_INT64) 196*1fd5a2e1SPrashanth Swaminathan str r1, [r2, #4] 197*1fd5a2e1SPrashanth Swaminathan nop 198*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_INT) 199*1fd5a2e1SPrashanth Swaminathan str r0, [r2] 200*1fd5a2e1SPrashanth Swaminathan pop {fp,pc} 201*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VOID) 202*1fd5a2e1SPrashanth Swaminathan pop {fp,pc} 203*1fd5a2e1SPrashanth Swaminathan nop 204*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_STRUCT) 205*1fd5a2e1SPrashanth Swaminathan pop {fp,pc} 206*1fd5a2e1SPrashanth Swaminathan 207*1fd5a2e1SPrashanth Swaminathan cfi_endproc 208*1fd5a2e1SPrashanth Swaminathan UNWIND(.fnend) 209*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_call_SYSV) 210*1fd5a2e1SPrashanth Swaminathan 211*1fd5a2e1SPrashanth Swaminathan 212*1fd5a2e1SPrashanth Swaminathan/* 213*1fd5a2e1SPrashanth Swaminathan int ffi_closure_inner_* (cif, fun, user_data, frame) 214*1fd5a2e1SPrashanth Swaminathan*/ 215*1fd5a2e1SPrashanth Swaminathan 216*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_go_closure_SYSV) 217*1fd5a2e1SPrashanth Swaminathan cfi_startproc 218*1fd5a2e1SPrashanth Swaminathan stmdb sp!, {r0-r3} @ save argument regs 219*1fd5a2e1SPrashanth Swaminathan cfi_adjust_cfa_offset(16) 220*1fd5a2e1SPrashanth Swaminathan ldr r0, [ip, #4] @ load cif 221*1fd5a2e1SPrashanth Swaminathan ldr r1, [ip, #8] @ load fun 222*1fd5a2e1SPrashanth Swaminathan mov r2, ip @ load user_data 223*1fd5a2e1SPrashanth Swaminathan b 0f 224*1fd5a2e1SPrashanth Swaminathan cfi_endproc 225*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_go_closure_SYSV) 226*1fd5a2e1SPrashanth Swaminathan 227*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_closure_SYSV) 228*1fd5a2e1SPrashanth Swaminathan UNWIND(.fnstart) 229*1fd5a2e1SPrashanth Swaminathan cfi_startproc 230*1fd5a2e1SPrashanth Swaminathan stmdb sp!, {r0-r3} @ save argument regs 231*1fd5a2e1SPrashanth Swaminathan cfi_adjust_cfa_offset(16) 232*1fd5a2e1SPrashanth Swaminathan 233*1fd5a2e1SPrashanth Swaminathan#if FFI_EXEC_TRAMPOLINE_TABLE 234*1fd5a2e1SPrashanth Swaminathan ldr ip, [ip] @ ip points to the config page, dereference to get the ffi_closure* 235*1fd5a2e1SPrashanth Swaminathan#endif 236*1fd5a2e1SPrashanth Swaminathan ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] @ load cif 237*1fd5a2e1SPrashanth Swaminathan ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] @ load fun 238*1fd5a2e1SPrashanth Swaminathan ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] @ load user_data 239*1fd5a2e1SPrashanth Swaminathan0: 240*1fd5a2e1SPrashanth Swaminathan add ip, sp, #16 @ compute entry sp 241*1fd5a2e1SPrashanth Swaminathan sub sp, sp, #64+32 @ allocate frame 242*1fd5a2e1SPrashanth Swaminathan cfi_adjust_cfa_offset(64+32) 243*1fd5a2e1SPrashanth Swaminathan stmdb sp!, {ip,lr} 244*1fd5a2e1SPrashanth Swaminathan 245*1fd5a2e1SPrashanth Swaminathan /* Remember that EABI unwind info only applies at call sites. 246*1fd5a2e1SPrashanth Swaminathan We need do nothing except note the save of the stack pointer 247*1fd5a2e1SPrashanth Swaminathan and the link registers. */ 248*1fd5a2e1SPrashanth Swaminathan UNWIND(.save {sp,lr}) 249*1fd5a2e1SPrashanth Swaminathan cfi_adjust_cfa_offset(8) 250*1fd5a2e1SPrashanth Swaminathan cfi_rel_offset(lr, 4) 251*1fd5a2e1SPrashanth Swaminathan 252*1fd5a2e1SPrashanth Swaminathan add r3, sp, #8 @ load frame 253*1fd5a2e1SPrashanth Swaminathan bl CNAME(ffi_closure_inner_SYSV) 254*1fd5a2e1SPrashanth Swaminathan 255*1fd5a2e1SPrashanth Swaminathan @ Load values returned in registers. 256*1fd5a2e1SPrashanth Swaminathan add r2, sp, #8+64 @ load result 257*1fd5a2e1SPrashanth Swaminathan adr r3, CNAME(ffi_closure_ret) 258*1fd5a2e1SPrashanth Swaminathan add pc, r3, r0, lsl #3 259*1fd5a2e1SPrashanth Swaminathan cfi_endproc 260*1fd5a2e1SPrashanth Swaminathan UNWIND(.fnend) 261*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_closure_SYSV) 262*1fd5a2e1SPrashanth Swaminathan 263*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_go_closure_VFP) 264*1fd5a2e1SPrashanth Swaminathan cfi_startproc 265*1fd5a2e1SPrashanth Swaminathan stmdb sp!, {r0-r3} @ save argument regs 266*1fd5a2e1SPrashanth Swaminathan cfi_adjust_cfa_offset(16) 267*1fd5a2e1SPrashanth Swaminathan ldr r0, [ip, #4] @ load cif 268*1fd5a2e1SPrashanth Swaminathan ldr r1, [ip, #8] @ load fun 269*1fd5a2e1SPrashanth Swaminathan mov r2, ip @ load user_data 270*1fd5a2e1SPrashanth Swaminathan b 0f 271*1fd5a2e1SPrashanth Swaminathan cfi_endproc 272*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_go_closure_VFP) 273*1fd5a2e1SPrashanth Swaminathan 274*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_closure_VFP) 275*1fd5a2e1SPrashanth Swaminathan UNWIND(.fnstart) 276*1fd5a2e1SPrashanth Swaminathan cfi_startproc 277*1fd5a2e1SPrashanth Swaminathan stmdb sp!, {r0-r3} @ save argument regs 278*1fd5a2e1SPrashanth Swaminathan cfi_adjust_cfa_offset(16) 279*1fd5a2e1SPrashanth Swaminathan 280*1fd5a2e1SPrashanth Swaminathan#if FFI_EXEC_TRAMPOLINE_TABLE 281*1fd5a2e1SPrashanth Swaminathan ldr ip, [ip] @ ip points to the config page, dereference to get the ffi_closure* 282*1fd5a2e1SPrashanth Swaminathan#endif 283*1fd5a2e1SPrashanth Swaminathan ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] @ load cif 284*1fd5a2e1SPrashanth Swaminathan ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] @ load fun 285*1fd5a2e1SPrashanth Swaminathan ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] @ load user_data 286*1fd5a2e1SPrashanth Swaminathan0: 287*1fd5a2e1SPrashanth Swaminathan add ip, sp, #16 288*1fd5a2e1SPrashanth Swaminathan sub sp, sp, #64+32 @ allocate frame 289*1fd5a2e1SPrashanth Swaminathan cfi_adjust_cfa_offset(64+32) 290*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__ 291*1fd5a2e1SPrashanth Swaminathan vstm sp, {d0-d7} 292*1fd5a2e1SPrashanth Swaminathan#else 293*1fd5a2e1SPrashanth Swaminathan stc p11, cr0, [sp], {16} @ vstm sp, {d0-d7} 294*1fd5a2e1SPrashanth Swaminathan#endif 295*1fd5a2e1SPrashanth Swaminathan stmdb sp!, {ip,lr} 296*1fd5a2e1SPrashanth Swaminathan 297*1fd5a2e1SPrashanth Swaminathan /* See above. */ 298*1fd5a2e1SPrashanth Swaminathan UNWIND(.save {sp,lr}) 299*1fd5a2e1SPrashanth Swaminathan cfi_adjust_cfa_offset(8) 300*1fd5a2e1SPrashanth Swaminathan cfi_rel_offset(lr, 4) 301*1fd5a2e1SPrashanth Swaminathan 302*1fd5a2e1SPrashanth Swaminathan add r3, sp, #8 @ load frame 303*1fd5a2e1SPrashanth Swaminathan bl CNAME(ffi_closure_inner_VFP) 304*1fd5a2e1SPrashanth Swaminathan 305*1fd5a2e1SPrashanth Swaminathan @ Load values returned in registers. 306*1fd5a2e1SPrashanth Swaminathan add r2, sp, #8+64 @ load result 307*1fd5a2e1SPrashanth Swaminathan adr r3, CNAME(ffi_closure_ret) 308*1fd5a2e1SPrashanth Swaminathan add pc, r3, r0, lsl #3 309*1fd5a2e1SPrashanth Swaminathan cfi_endproc 310*1fd5a2e1SPrashanth Swaminathan UNWIND(.fnend) 311*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_closure_VFP) 312*1fd5a2e1SPrashanth Swaminathan 313*1fd5a2e1SPrashanth Swaminathan/* Load values returned in registers for both closure entry points. 314*1fd5a2e1SPrashanth Swaminathan Note that we use LDM with SP in the register set. This is deprecated 315*1fd5a2e1SPrashanth Swaminathan by ARM, but not yet unpredictable. */ 316*1fd5a2e1SPrashanth Swaminathan 317*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START_LOCAL(ffi_closure_ret) 318*1fd5a2e1SPrashanth Swaminathan cfi_startproc 319*1fd5a2e1SPrashanth Swaminathan cfi_rel_offset(sp, 0) 320*1fd5a2e1SPrashanth Swaminathan cfi_rel_offset(lr, 4) 321*1fd5a2e1SPrashanth Swaminathan0: 322*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_S) 323*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__ 324*1fd5a2e1SPrashanth Swaminathan vldr s0, [r2] 325*1fd5a2e1SPrashanth Swaminathan#else 326*1fd5a2e1SPrashanth Swaminathan ldc p10, cr0, [r2] @ vldr s0, [r2] 327*1fd5a2e1SPrashanth Swaminathan#endif 328*1fd5a2e1SPrashanth Swaminathan ldm sp, {sp,pc} 329*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_D) 330*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__ 331*1fd5a2e1SPrashanth Swaminathan vldr d0, [r2] 332*1fd5a2e1SPrashanth Swaminathan#else 333*1fd5a2e1SPrashanth Swaminathan ldc p11, cr0, [r2] @ vldr d0, [r2] 334*1fd5a2e1SPrashanth Swaminathan#endif 335*1fd5a2e1SPrashanth Swaminathan ldm sp, {sp,pc} 336*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_N) 337*1fd5a2e1SPrashanth Swaminathan#ifdef __clang__ 338*1fd5a2e1SPrashanth Swaminathan vldm r2, {d0-d3} 339*1fd5a2e1SPrashanth Swaminathan#else 340*1fd5a2e1SPrashanth Swaminathan ldc p11, cr0, [r2], {8} @ vldm r2, {d0-d3} 341*1fd5a2e1SPrashanth Swaminathan#endif 342*1fd5a2e1SPrashanth Swaminathan ldm sp, {sp,pc} 343*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_INT64) 344*1fd5a2e1SPrashanth Swaminathan ldr r1, [r2, #4] 345*1fd5a2e1SPrashanth Swaminathan nop 346*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_INT) 347*1fd5a2e1SPrashanth Swaminathan ldr r0, [r2] 348*1fd5a2e1SPrashanth Swaminathan ldm sp, {sp,pc} 349*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VOID) 350*1fd5a2e1SPrashanth Swaminathan ldm sp, {sp,pc} 351*1fd5a2e1SPrashanth Swaminathan nop 352*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_STRUCT) 353*1fd5a2e1SPrashanth Swaminathan ldm sp, {sp,pc} 354*1fd5a2e1SPrashanth Swaminathan cfi_endproc 355*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_closure_ret) 356*1fd5a2e1SPrashanth Swaminathan 357*1fd5a2e1SPrashanth Swaminathan#if FFI_EXEC_TRAMPOLINE_TABLE 358*1fd5a2e1SPrashanth Swaminathan 359*1fd5a2e1SPrashanth Swaminathan#ifdef __MACH__ 360*1fd5a2e1SPrashanth Swaminathan#include <mach/machine/vm_param.h> 361*1fd5a2e1SPrashanth Swaminathan 362*1fd5a2e1SPrashanth Swaminathan.align PAGE_MAX_SHIFT 363*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_closure_trampoline_table_page) 364*1fd5a2e1SPrashanth Swaminathan.rept PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE 365*1fd5a2e1SPrashanth Swaminathan adr ip, #-PAGE_MAX_SIZE @ the config page is PAGE_MAX_SIZE behind the trampoline page 366*1fd5a2e1SPrashanth Swaminathan sub ip, #8 @ account for pc bias 367*1fd5a2e1SPrashanth Swaminathan ldr pc, [ip, #4] @ jump to ffi_closure_SYSV or ffi_closure_VFP 368*1fd5a2e1SPrashanth Swaminathan.endr 369*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_closure_trampoline_table_page) 370*1fd5a2e1SPrashanth Swaminathan#endif 371*1fd5a2e1SPrashanth Swaminathan 372*1fd5a2e1SPrashanth Swaminathan#else 373*1fd5a2e1SPrashanth Swaminathan 374*1fd5a2e1SPrashanth SwaminathanARM_FUNC_START(ffi_arm_trampoline) 375*1fd5a2e1SPrashanth Swaminathan0: adr ip, 0b 376*1fd5a2e1SPrashanth Swaminathan ldr pc, 1f 377*1fd5a2e1SPrashanth Swaminathan1: .long 0 378*1fd5a2e1SPrashanth SwaminathanARM_FUNC_END(ffi_arm_trampoline) 379*1fd5a2e1SPrashanth Swaminathan 380*1fd5a2e1SPrashanth Swaminathan#endif /* FFI_EXEC_TRAMPOLINE_TABLE */ 381*1fd5a2e1SPrashanth Swaminathan#endif /* __arm__ */ 382*1fd5a2e1SPrashanth Swaminathan 383*1fd5a2e1SPrashanth Swaminathan#if defined __ELF__ && defined __linux__ 384*1fd5a2e1SPrashanth Swaminathan .section .note.GNU-stack,"",%progbits 385*1fd5a2e1SPrashanth Swaminathan#endif 386