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 Copyright (c) 2019 Microsoft Corporation. 5*1fd5a2e1SPrashanth Swaminathan 6*1fd5a2e1SPrashanth Swaminathan ARM Foreign Function Interface 7*1fd5a2e1SPrashanth Swaminathan 8*1fd5a2e1SPrashanth Swaminathan Permission is hereby granted, free of charge, to any person obtaining 9*1fd5a2e1SPrashanth Swaminathan a copy of this software and associated documentation files (the 10*1fd5a2e1SPrashanth Swaminathan ``Software''), to deal in the Software without restriction, including 11*1fd5a2e1SPrashanth Swaminathan without limitation the rights to use, copy, modify, merge, publish, 12*1fd5a2e1SPrashanth Swaminathan distribute, sublicense, and/or sell copies of the Software, and to 13*1fd5a2e1SPrashanth Swaminathan permit persons to whom the Software is furnished to do so, subject to 14*1fd5a2e1SPrashanth Swaminathan the following conditions: 15*1fd5a2e1SPrashanth Swaminathan 16*1fd5a2e1SPrashanth Swaminathan The above copyright notice and this permission notice shall be included 17*1fd5a2e1SPrashanth Swaminathan in all copies or substantial portions of the Software. 18*1fd5a2e1SPrashanth Swaminathan 19*1fd5a2e1SPrashanth Swaminathan THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 20*1fd5a2e1SPrashanth Swaminathan EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21*1fd5a2e1SPrashanth Swaminathan MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22*1fd5a2e1SPrashanth Swaminathan NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23*1fd5a2e1SPrashanth Swaminathan HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24*1fd5a2e1SPrashanth Swaminathan WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25*1fd5a2e1SPrashanth Swaminathan OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26*1fd5a2e1SPrashanth Swaminathan DEALINGS IN THE SOFTWARE. 27*1fd5a2e1SPrashanth Swaminathan ----------------------------------------------------------------------- */ 28*1fd5a2e1SPrashanth Swaminathan 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#include "ksarm.h" 35*1fd5a2e1SPrashanth Swaminathan 36*1fd5a2e1SPrashanth Swaminathan 37*1fd5a2e1SPrashanth Swaminathan ; 8 byte aligned AREA to support 8 byte aligned jump tables 38*1fd5a2e1SPrashanth Swaminathan MACRO 39*1fd5a2e1SPrashanth Swaminathan NESTED_ENTRY_FFI $FuncName, $AreaName, $ExceptHandler 40*1fd5a2e1SPrashanth Swaminathan 41*1fd5a2e1SPrashanth Swaminathan ; compute the function's labels 42*1fd5a2e1SPrashanth Swaminathan __DeriveFunctionLabels $FuncName 43*1fd5a2e1SPrashanth Swaminathan 44*1fd5a2e1SPrashanth Swaminathan ; determine the area we will put the function into 45*1fd5a2e1SPrashanth Swaminathan__FuncArea SETS "|.text|" 46*1fd5a2e1SPrashanth Swaminathan IF "$AreaName" != "" 47*1fd5a2e1SPrashanth Swaminathan__FuncArea SETS "$AreaName" 48*1fd5a2e1SPrashanth Swaminathan ENDIF 49*1fd5a2e1SPrashanth Swaminathan 50*1fd5a2e1SPrashanth Swaminathan ; set up the exception handler itself 51*1fd5a2e1SPrashanth Swaminathan__FuncExceptionHandler SETS "" 52*1fd5a2e1SPrashanth Swaminathan IF "$ExceptHandler" != "" 53*1fd5a2e1SPrashanth Swaminathan__FuncExceptionHandler SETS "|$ExceptHandler|" 54*1fd5a2e1SPrashanth Swaminathan ENDIF 55*1fd5a2e1SPrashanth Swaminathan 56*1fd5a2e1SPrashanth Swaminathan ; switch to the specified area, jump tables require 8 byte alignment 57*1fd5a2e1SPrashanth Swaminathan AREA $__FuncArea,CODE,CODEALIGN,ALIGN=3,READONLY 58*1fd5a2e1SPrashanth Swaminathan 59*1fd5a2e1SPrashanth Swaminathan ; export the function name 60*1fd5a2e1SPrashanth Swaminathan __ExportProc $FuncName 61*1fd5a2e1SPrashanth Swaminathan 62*1fd5a2e1SPrashanth Swaminathan ; flush any pending literal pool stuff 63*1fd5a2e1SPrashanth Swaminathan ROUT 64*1fd5a2e1SPrashanth Swaminathan 65*1fd5a2e1SPrashanth Swaminathan ; reset the state of the unwind code tracking 66*1fd5a2e1SPrashanth Swaminathan __ResetUnwindState 67*1fd5a2e1SPrashanth Swaminathan 68*1fd5a2e1SPrashanth Swaminathan MEND 69*1fd5a2e1SPrashanth Swaminathan 70*1fd5a2e1SPrashanth Swaminathan; MACRO 71*1fd5a2e1SPrashanth Swaminathan; TABLE_ENTRY $Type, $Table 72*1fd5a2e1SPrashanth Swaminathan;$Type_$Table 73*1fd5a2e1SPrashanth Swaminathan; MEND 74*1fd5a2e1SPrashanth Swaminathan 75*1fd5a2e1SPrashanth Swaminathan#define E(index,table) return_##index##_##table 76*1fd5a2e1SPrashanth Swaminathan 77*1fd5a2e1SPrashanth Swaminathan ; r0: stack 78*1fd5a2e1SPrashanth Swaminathan ; r1: frame 79*1fd5a2e1SPrashanth Swaminathan ; r2: fn 80*1fd5a2e1SPrashanth Swaminathan ; r3: vfp_used 81*1fd5a2e1SPrashanth Swaminathan 82*1fd5a2e1SPrashanth Swaminathan ; fake entry point exists only to generate exists only to 83*1fd5a2e1SPrashanth Swaminathan ; generate .pdata for exception unwinding 84*1fd5a2e1SPrashanth Swaminathan NESTED_ENTRY_FFI ffi_call_VFP_fake 85*1fd5a2e1SPrashanth Swaminathan PROLOG_PUSH {r11, lr} ; save fp and lr for unwind 86*1fd5a2e1SPrashanth Swaminathan 87*1fd5a2e1SPrashanth Swaminathan ALTERNATE_ENTRY ffi_call_VFP 88*1fd5a2e1SPrashanth Swaminathan cmp r3, #3 ; load only d0 if possible 89*1fd5a2e1SPrashanth Swaminathan vldrle d0, [r0] 90*1fd5a2e1SPrashanth Swaminathan vldmgt r0, {d0-d7} 91*1fd5a2e1SPrashanth Swaminathan add r0, r0, #64 ; discard the vfp register args 92*1fd5a2e1SPrashanth Swaminathan b ffi_call_SYSV 93*1fd5a2e1SPrashanth Swaminathan NESTED_END ffi_call_VFP_fake 94*1fd5a2e1SPrashanth Swaminathan 95*1fd5a2e1SPrashanth Swaminathan ; fake entry point exists only to generate exists only to 96*1fd5a2e1SPrashanth Swaminathan ; generate .pdata for exception unwinding 97*1fd5a2e1SPrashanth Swaminathan NESTED_ENTRY_FFI ffi_call_SYSV_fake 98*1fd5a2e1SPrashanth Swaminathan PROLOG_PUSH {r11, lr} ; save fp and lr for unwind 99*1fd5a2e1SPrashanth Swaminathan 100*1fd5a2e1SPrashanth Swaminathan ALTERNATE_ENTRY ffi_call_SYSV 101*1fd5a2e1SPrashanth Swaminathan stm r1, {fp, lr} 102*1fd5a2e1SPrashanth Swaminathan mov fp, r1 103*1fd5a2e1SPrashanth Swaminathan 104*1fd5a2e1SPrashanth Swaminathan mov sp, r0 ; install the stack pointer 105*1fd5a2e1SPrashanth Swaminathan mov lr, r2 ; move the fn pointer out of the way 106*1fd5a2e1SPrashanth Swaminathan ldr ip, [fp, #16] ; install the static chain 107*1fd5a2e1SPrashanth Swaminathan ldmia sp!, {r0-r3} ; move first 4 parameters in registers. 108*1fd5a2e1SPrashanth Swaminathan blx lr ; call fn 109*1fd5a2e1SPrashanth Swaminathan 110*1fd5a2e1SPrashanth Swaminathan ; Load r2 with the pointer to storage for the return value 111*1fd5a2e1SPrashanth Swaminathan ; Load r3 with the return type code 112*1fd5a2e1SPrashanth Swaminathan ldr r2, [fp, #8] 113*1fd5a2e1SPrashanth Swaminathan ldr r3, [fp, #12] 114*1fd5a2e1SPrashanth Swaminathan 115*1fd5a2e1SPrashanth Swaminathan ; Deallocate the stack with the arguments. 116*1fd5a2e1SPrashanth Swaminathan mov sp, fp 117*1fd5a2e1SPrashanth Swaminathan 118*1fd5a2e1SPrashanth Swaminathan ; Store values stored in registers. 119*1fd5a2e1SPrashanth Swaminathan ALIGN 8 120*1fd5a2e1SPrashanth Swaminathan lsl r3, #3 121*1fd5a2e1SPrashanth Swaminathan add r3, r3, pc 122*1fd5a2e1SPrashanth Swaminathan add r3, #8 123*1fd5a2e1SPrashanth Swaminathan mov pc, r3 124*1fd5a2e1SPrashanth Swaminathan 125*1fd5a2e1SPrashanth Swaminathan 126*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_S, ffi_call) 127*1fd5a2e1SPrashanth Swaminathan ALIGN 8 128*1fd5a2e1SPrashanth Swaminathan vstr s0, [r2] 129*1fd5a2e1SPrashanth Swaminathan pop {fp,pc} 130*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_D, ffi_call) 131*1fd5a2e1SPrashanth Swaminathan ALIGN 8 132*1fd5a2e1SPrashanth Swaminathan vstr d0, [r2] 133*1fd5a2e1SPrashanth Swaminathan pop {fp,pc} 134*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_N, ffi_call) 135*1fd5a2e1SPrashanth Swaminathan ALIGN 8 136*1fd5a2e1SPrashanth Swaminathan vstm r2, {d0-d3} 137*1fd5a2e1SPrashanth Swaminathan pop {fp,pc} 138*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_INT64, ffi_call) 139*1fd5a2e1SPrashanth Swaminathan ALIGN 8 140*1fd5a2e1SPrashanth Swaminathan str r1, [r2, #4] 141*1fd5a2e1SPrashanth Swaminathan nop 142*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_INT, ffi_call) 143*1fd5a2e1SPrashanth Swaminathan ALIGN 8 144*1fd5a2e1SPrashanth Swaminathan str r0, [r2] 145*1fd5a2e1SPrashanth Swaminathan pop {fp,pc} 146*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VOID, ffi_call) 147*1fd5a2e1SPrashanth Swaminathan ALIGN 8 148*1fd5a2e1SPrashanth Swaminathan pop {fp,pc} 149*1fd5a2e1SPrashanth Swaminathan nop 150*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_STRUCT, ffi_call) 151*1fd5a2e1SPrashanth Swaminathan ALIGN 8 152*1fd5a2e1SPrashanth Swaminathan cmp r3, #ARM_TYPE_STRUCT 153*1fd5a2e1SPrashanth Swaminathan pop {fp,pc} 154*1fd5a2e1SPrashanth Swaminathan NESTED_END ffi_call_SYSV_fake 155*1fd5a2e1SPrashanth Swaminathan 156*1fd5a2e1SPrashanth Swaminathan IMPORT |ffi_closure_inner_SYSV| 157*1fd5a2e1SPrashanth Swaminathan /* 158*1fd5a2e1SPrashanth Swaminathan int ffi_closure_inner_SYSV 159*1fd5a2e1SPrashanth Swaminathan ( 160*1fd5a2e1SPrashanth Swaminathan cif, ; r0 161*1fd5a2e1SPrashanth Swaminathan fun, ; r1 162*1fd5a2e1SPrashanth Swaminathan user_data, ; r2 163*1fd5a2e1SPrashanth Swaminathan frame ; r3 164*1fd5a2e1SPrashanth Swaminathan ) 165*1fd5a2e1SPrashanth Swaminathan */ 166*1fd5a2e1SPrashanth Swaminathan 167*1fd5a2e1SPrashanth Swaminathan NESTED_ENTRY_FFI ffi_go_closure_SYSV 168*1fd5a2e1SPrashanth Swaminathan stmdb sp!, {r0-r3} ; save argument regs 169*1fd5a2e1SPrashanth Swaminathan ldr r0, [ip, #4] ; load cif 170*1fd5a2e1SPrashanth Swaminathan ldr r1, [ip, #8] ; load fun 171*1fd5a2e1SPrashanth Swaminathan mov r2, ip ; load user_data 172*1fd5a2e1SPrashanth Swaminathan b ffi_go_closure_SYSV_0 173*1fd5a2e1SPrashanth Swaminathan NESTED_END ffi_go_closure_SYSV 174*1fd5a2e1SPrashanth Swaminathan 175*1fd5a2e1SPrashanth Swaminathan ; r3: ffi_closure 176*1fd5a2e1SPrashanth Swaminathan 177*1fd5a2e1SPrashanth Swaminathan ; fake entry point exists only to generate exists only to 178*1fd5a2e1SPrashanth Swaminathan ; generate .pdata for exception unwinding 179*1fd5a2e1SPrashanth Swaminathan NESTED_ENTRY_FFI ffi_closure_SYSV_fake 180*1fd5a2e1SPrashanth Swaminathan PROLOG_PUSH {r11, lr} ; save fp and lr for unwind 181*1fd5a2e1SPrashanth Swaminathan ALTERNATE_ENTRY ffi_closure_SYSV 182*1fd5a2e1SPrashanth Swaminathan ldmfd sp!, {ip,r0} ; restore fp (r0 is used for stack alignment) 183*1fd5a2e1SPrashanth Swaminathan stmdb sp!, {r0-r3} ; save argument regs 184*1fd5a2e1SPrashanth Swaminathan 185*1fd5a2e1SPrashanth Swaminathan ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] ; ffi_closure->cif 186*1fd5a2e1SPrashanth Swaminathan ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] ; ffi_closure->fun 187*1fd5a2e1SPrashanth Swaminathan ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] ; ffi_closure->user_data 188*1fd5a2e1SPrashanth Swaminathan 189*1fd5a2e1SPrashanth Swaminathan ALTERNATE_ENTRY ffi_go_closure_SYSV_0 190*1fd5a2e1SPrashanth Swaminathan add ip, sp, #16 ; compute entry sp 191*1fd5a2e1SPrashanth Swaminathan 192*1fd5a2e1SPrashanth Swaminathan sub sp, sp, #64+32 ; allocate frame parameter (sizeof(vfp_space) = 64, sizeof(result) = 32) 193*1fd5a2e1SPrashanth Swaminathan mov r3, sp ; set frame parameter 194*1fd5a2e1SPrashanth Swaminathan stmdb sp!, {ip,lr} 195*1fd5a2e1SPrashanth Swaminathan 196*1fd5a2e1SPrashanth Swaminathan bl ffi_closure_inner_SYSV ; call the Python closure 197*1fd5a2e1SPrashanth Swaminathan 198*1fd5a2e1SPrashanth Swaminathan ; Load values returned in registers. 199*1fd5a2e1SPrashanth Swaminathan add r2, sp, #64+8 ; address of closure_frame->result 200*1fd5a2e1SPrashanth Swaminathan bl ffi_closure_ret ; move result to correct register or memory for type 201*1fd5a2e1SPrashanth Swaminathan 202*1fd5a2e1SPrashanth Swaminathan ldmfd sp!, {ip,lr} 203*1fd5a2e1SPrashanth Swaminathan mov sp, ip ; restore stack pointer 204*1fd5a2e1SPrashanth Swaminathan mov pc, lr 205*1fd5a2e1SPrashanth Swaminathan NESTED_END ffi_closure_SYSV_fake 206*1fd5a2e1SPrashanth Swaminathan 207*1fd5a2e1SPrashanth Swaminathan IMPORT |ffi_closure_inner_VFP| 208*1fd5a2e1SPrashanth Swaminathan /* 209*1fd5a2e1SPrashanth Swaminathan int ffi_closure_inner_VFP 210*1fd5a2e1SPrashanth Swaminathan ( 211*1fd5a2e1SPrashanth Swaminathan cif, ; r0 212*1fd5a2e1SPrashanth Swaminathan fun, ; r1 213*1fd5a2e1SPrashanth Swaminathan user_data, ; r2 214*1fd5a2e1SPrashanth Swaminathan frame ; r3 215*1fd5a2e1SPrashanth Swaminathan ) 216*1fd5a2e1SPrashanth Swaminathan */ 217*1fd5a2e1SPrashanth Swaminathan 218*1fd5a2e1SPrashanth Swaminathan NESTED_ENTRY_FFI ffi_go_closure_VFP 219*1fd5a2e1SPrashanth Swaminathan stmdb sp!, {r0-r3} ; save argument regs 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 ffi_go_closure_VFP_0 224*1fd5a2e1SPrashanth Swaminathan NESTED_END ffi_go_closure_VFP 225*1fd5a2e1SPrashanth Swaminathan 226*1fd5a2e1SPrashanth Swaminathan ; fake entry point exists only to generate exists only to 227*1fd5a2e1SPrashanth Swaminathan ; generate .pdata for exception unwinding 228*1fd5a2e1SPrashanth Swaminathan ; r3: closure 229*1fd5a2e1SPrashanth Swaminathan NESTED_ENTRY_FFI ffi_closure_VFP_fake 230*1fd5a2e1SPrashanth Swaminathan PROLOG_PUSH {r11, lr} ; save fp and lr for unwind 231*1fd5a2e1SPrashanth Swaminathan 232*1fd5a2e1SPrashanth Swaminathan ALTERNATE_ENTRY ffi_closure_VFP 233*1fd5a2e1SPrashanth Swaminathan ldmfd sp!, {ip,r0} ; restore fp (r0 is used for stack alignment) 234*1fd5a2e1SPrashanth Swaminathan stmdb sp!, {r0-r3} ; save argument regs 235*1fd5a2e1SPrashanth Swaminathan 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 Swaminathan 240*1fd5a2e1SPrashanth Swaminathan ALTERNATE_ENTRY ffi_go_closure_VFP_0 241*1fd5a2e1SPrashanth Swaminathan add ip, sp, #16 ; compute entry sp 242*1fd5a2e1SPrashanth Swaminathan sub sp, sp, #32 ; save space for closure_frame->result 243*1fd5a2e1SPrashanth Swaminathan vstmdb sp!, {d0-d7} ; push closure_frame->vfp_space 244*1fd5a2e1SPrashanth Swaminathan 245*1fd5a2e1SPrashanth Swaminathan mov r3, sp ; save closure_frame 246*1fd5a2e1SPrashanth Swaminathan stmdb sp!, {ip,lr} 247*1fd5a2e1SPrashanth Swaminathan 248*1fd5a2e1SPrashanth Swaminathan bl ffi_closure_inner_VFP 249*1fd5a2e1SPrashanth Swaminathan 250*1fd5a2e1SPrashanth Swaminathan ; Load values returned in registers. 251*1fd5a2e1SPrashanth Swaminathan add r2, sp, #64+8 ; load result 252*1fd5a2e1SPrashanth Swaminathan bl ffi_closure_ret 253*1fd5a2e1SPrashanth Swaminathan ldmfd sp!, {ip,lr} 254*1fd5a2e1SPrashanth Swaminathan mov sp, ip ; restore stack pointer 255*1fd5a2e1SPrashanth Swaminathan mov pc, lr 256*1fd5a2e1SPrashanth Swaminathan NESTED_END ffi_closure_VFP_fake 257*1fd5a2e1SPrashanth Swaminathan 258*1fd5a2e1SPrashanth Swaminathan/* Load values returned in registers for both closure entry points. 259*1fd5a2e1SPrashanth Swaminathan Note that we use LDM with SP in the register set. This is deprecated 260*1fd5a2e1SPrashanth Swaminathan by ARM, but not yet unpredictable. */ 261*1fd5a2e1SPrashanth Swaminathan 262*1fd5a2e1SPrashanth Swaminathan NESTED_ENTRY_FFI ffi_closure_ret 263*1fd5a2e1SPrashanth Swaminathan stmdb sp!, {fp,lr} 264*1fd5a2e1SPrashanth Swaminathan 265*1fd5a2e1SPrashanth Swaminathan ALIGN 8 266*1fd5a2e1SPrashanth Swaminathan lsl r0, #3 267*1fd5a2e1SPrashanth Swaminathan add r0, r0, pc 268*1fd5a2e1SPrashanth Swaminathan add r0, #8 269*1fd5a2e1SPrashanth Swaminathan mov pc, r0 270*1fd5a2e1SPrashanth Swaminathan 271*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_S, ffi_closure) 272*1fd5a2e1SPrashanth Swaminathan ALIGN 8 273*1fd5a2e1SPrashanth Swaminathan vldr s0, [r2] 274*1fd5a2e1SPrashanth Swaminathan b call_epilogue 275*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_D, ffi_closure) 276*1fd5a2e1SPrashanth Swaminathan ALIGN 8 277*1fd5a2e1SPrashanth Swaminathan vldr d0, [r2] 278*1fd5a2e1SPrashanth Swaminathan b call_epilogue 279*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VFP_N, ffi_closure) 280*1fd5a2e1SPrashanth Swaminathan ALIGN 8 281*1fd5a2e1SPrashanth Swaminathan vldm r2, {d0-d3} 282*1fd5a2e1SPrashanth Swaminathan b call_epilogue 283*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_INT64, ffi_closure) 284*1fd5a2e1SPrashanth Swaminathan ALIGN 8 285*1fd5a2e1SPrashanth Swaminathan ldr r1, [r2, #4] 286*1fd5a2e1SPrashanth Swaminathan nop 287*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_INT, ffi_closure) 288*1fd5a2e1SPrashanth Swaminathan ALIGN 8 289*1fd5a2e1SPrashanth Swaminathan ldr r0, [r2] 290*1fd5a2e1SPrashanth Swaminathan b call_epilogue 291*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_VOID, ffi_closure) 292*1fd5a2e1SPrashanth Swaminathan ALIGN 8 293*1fd5a2e1SPrashanth Swaminathan b call_epilogue 294*1fd5a2e1SPrashanth Swaminathan nop 295*1fd5a2e1SPrashanth SwaminathanE(ARM_TYPE_STRUCT, ffi_closure) 296*1fd5a2e1SPrashanth Swaminathan ALIGN 8 297*1fd5a2e1SPrashanth Swaminathan b call_epilogue 298*1fd5a2e1SPrashanth Swaminathancall_epilogue 299*1fd5a2e1SPrashanth Swaminathan ldmfd sp!, {fp,pc} 300*1fd5a2e1SPrashanth Swaminathan NESTED_END ffi_closure_ret 301*1fd5a2e1SPrashanth Swaminathan 302*1fd5a2e1SPrashanth Swaminathan AREA |.trampoline|, DATA, THUMB, READONLY 303*1fd5a2e1SPrashanth Swaminathan EXPORT |ffi_arm_trampoline| 304*1fd5a2e1SPrashanth Swaminathan|ffi_arm_trampoline| DATA 305*1fd5a2e1SPrashanth Swaminathanthisproc adr ip, thisproc 306*1fd5a2e1SPrashanth Swaminathan stmdb sp!, {ip, r0} 307*1fd5a2e1SPrashanth Swaminathan ldr pc, [pc, #0] 308*1fd5a2e1SPrashanth Swaminathan DCD 0 309*1fd5a2e1SPrashanth Swaminathan ;ENDP 310*1fd5a2e1SPrashanth Swaminathan 311*1fd5a2e1SPrashanth Swaminathan END