1*1fd5a2e1SPrashanth Swaminathan/* ----------------------------------------------------------------------- 2*1fd5a2e1SPrashanth Swaminathan tile.S - Copyright (c) 2011 Tilera Corp. 3*1fd5a2e1SPrashanth Swaminathan 4*1fd5a2e1SPrashanth Swaminathan Tilera TILEPro and TILE-Gx Foreign Function Interface 5*1fd5a2e1SPrashanth Swaminathan 6*1fd5a2e1SPrashanth Swaminathan Permission is hereby granted, free of charge, to any person obtaining 7*1fd5a2e1SPrashanth Swaminathan a copy of this software and associated documentation files (the 8*1fd5a2e1SPrashanth Swaminathan ``Software''), to deal in the Software without restriction, including 9*1fd5a2e1SPrashanth Swaminathan without limitation the rights to use, copy, modify, merge, publish, 10*1fd5a2e1SPrashanth Swaminathan distribute, sublicense, and/or sell copies of the Software, and to 11*1fd5a2e1SPrashanth Swaminathan permit persons to whom the Software is furnished to do so, subject to 12*1fd5a2e1SPrashanth Swaminathan the following conditions: 13*1fd5a2e1SPrashanth Swaminathan 14*1fd5a2e1SPrashanth Swaminathan The above copyright notice and this permission notice shall be included 15*1fd5a2e1SPrashanth Swaminathan in all copies or substantial portions of the Software. 16*1fd5a2e1SPrashanth Swaminathan 17*1fd5a2e1SPrashanth Swaminathan THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 18*1fd5a2e1SPrashanth Swaminathan EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19*1fd5a2e1SPrashanth Swaminathan MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20*1fd5a2e1SPrashanth Swaminathan NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21*1fd5a2e1SPrashanth Swaminathan HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22*1fd5a2e1SPrashanth Swaminathan WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23*1fd5a2e1SPrashanth Swaminathan OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24*1fd5a2e1SPrashanth Swaminathan DEALINGS IN THE SOFTWARE. 25*1fd5a2e1SPrashanth Swaminathan ----------------------------------------------------------------------- */ 26*1fd5a2e1SPrashanth Swaminathan 27*1fd5a2e1SPrashanth Swaminathan#define LIBFFI_ASM 28*1fd5a2e1SPrashanth Swaminathan#include <fficonfig.h> 29*1fd5a2e1SPrashanth Swaminathan#include <ffi.h> 30*1fd5a2e1SPrashanth Swaminathan 31*1fd5a2e1SPrashanth Swaminathan/* Number of bytes in a register. */ 32*1fd5a2e1SPrashanth Swaminathan#define REG_SIZE FFI_SIZEOF_ARG 33*1fd5a2e1SPrashanth Swaminathan 34*1fd5a2e1SPrashanth Swaminathan/* Number of bytes in stack linkage area for backtracing. 35*1fd5a2e1SPrashanth Swaminathan 36*1fd5a2e1SPrashanth Swaminathan A note about the ABI: on entry to a procedure, sp points to a stack 37*1fd5a2e1SPrashanth Swaminathan slot where it must spill the return address if it's not a leaf. 38*1fd5a2e1SPrashanth Swaminathan REG_SIZE bytes beyond that is a slot owned by the caller which 39*1fd5a2e1SPrashanth Swaminathan contains the sp value that the caller had when it was originally 40*1fd5a2e1SPrashanth Swaminathan entered (i.e. the caller's frame pointer). */ 41*1fd5a2e1SPrashanth Swaminathan#define LINKAGE_SIZE (2 * REG_SIZE) 42*1fd5a2e1SPrashanth Swaminathan 43*1fd5a2e1SPrashanth Swaminathan/* The first 10 registers are used to pass arguments and return values. */ 44*1fd5a2e1SPrashanth Swaminathan#define NUM_ARG_REGS 10 45*1fd5a2e1SPrashanth Swaminathan 46*1fd5a2e1SPrashanth Swaminathan#ifdef __tilegx__ 47*1fd5a2e1SPrashanth Swaminathan#define SW st 48*1fd5a2e1SPrashanth Swaminathan#define LW ld 49*1fd5a2e1SPrashanth Swaminathan#define BGZT bgtzt 50*1fd5a2e1SPrashanth Swaminathan#else 51*1fd5a2e1SPrashanth Swaminathan#define SW sw 52*1fd5a2e1SPrashanth Swaminathan#define LW lw 53*1fd5a2e1SPrashanth Swaminathan#define BGZT bgzt 54*1fd5a2e1SPrashanth Swaminathan#endif 55*1fd5a2e1SPrashanth Swaminathan 56*1fd5a2e1SPrashanth Swaminathan 57*1fd5a2e1SPrashanth Swaminathan/* void ffi_call_tile (int_reg_t reg_args[NUM_ARG_REGS], 58*1fd5a2e1SPrashanth Swaminathan const int_reg_t *stack_args, 59*1fd5a2e1SPrashanth Swaminathan unsigned long stack_args_bytes, 60*1fd5a2e1SPrashanth Swaminathan void (*fnaddr)(void)); 61*1fd5a2e1SPrashanth Swaminathan 62*1fd5a2e1SPrashanth Swaminathan On entry, REG_ARGS contain the outgoing register values, 63*1fd5a2e1SPrashanth Swaminathan and STACK_ARGS contains STACK_ARG_BYTES of additional values 64*1fd5a2e1SPrashanth Swaminathan to be passed on the stack. If STACK_ARG_BYTES is zero, then 65*1fd5a2e1SPrashanth Swaminathan STACK_ARGS is ignored. 66*1fd5a2e1SPrashanth Swaminathan 67*1fd5a2e1SPrashanth Swaminathan When the invoked function returns, the values of r0-r9 are 68*1fd5a2e1SPrashanth Swaminathan blindly stored back into REG_ARGS for the caller to examine. */ 69*1fd5a2e1SPrashanth Swaminathan 70*1fd5a2e1SPrashanth Swaminathan .section .text.ffi_call_tile, "ax", @progbits 71*1fd5a2e1SPrashanth Swaminathan .align 8 72*1fd5a2e1SPrashanth Swaminathan .globl ffi_call_tile 73*1fd5a2e1SPrashanth Swaminathan FFI_HIDDEN(ffi_call_tile) 74*1fd5a2e1SPrashanth Swaminathanffi_call_tile: 75*1fd5a2e1SPrashanth Swaminathan 76*1fd5a2e1SPrashanth Swaminathan/* Incoming arguments. */ 77*1fd5a2e1SPrashanth Swaminathan#define REG_ARGS r0 78*1fd5a2e1SPrashanth Swaminathan#define INCOMING_STACK_ARGS r1 79*1fd5a2e1SPrashanth Swaminathan#define STACK_ARG_BYTES r2 80*1fd5a2e1SPrashanth Swaminathan#define ORIG_FNADDR r3 81*1fd5a2e1SPrashanth Swaminathan 82*1fd5a2e1SPrashanth Swaminathan/* Temporary values. */ 83*1fd5a2e1SPrashanth Swaminathan#define FRAME_SIZE r10 84*1fd5a2e1SPrashanth Swaminathan#define TMP r11 85*1fd5a2e1SPrashanth Swaminathan#define TMP2 r12 86*1fd5a2e1SPrashanth Swaminathan#define OUTGOING_STACK_ARGS r13 87*1fd5a2e1SPrashanth Swaminathan#define REG_ADDR_PTR r14 88*1fd5a2e1SPrashanth Swaminathan#define RETURN_REG_ADDR r15 89*1fd5a2e1SPrashanth Swaminathan#define FNADDR r16 90*1fd5a2e1SPrashanth Swaminathan 91*1fd5a2e1SPrashanth Swaminathan .cfi_startproc 92*1fd5a2e1SPrashanth Swaminathan { 93*1fd5a2e1SPrashanth Swaminathan /* Save return address. */ 94*1fd5a2e1SPrashanth Swaminathan SW sp, lr 95*1fd5a2e1SPrashanth Swaminathan .cfi_offset lr, 0 96*1fd5a2e1SPrashanth Swaminathan /* Prepare to spill incoming r52. */ 97*1fd5a2e1SPrashanth Swaminathan addi TMP, sp, -REG_SIZE 98*1fd5a2e1SPrashanth Swaminathan /* Increase frame size to have room to spill r52 and REG_ARGS. 99*1fd5a2e1SPrashanth Swaminathan The +7 is to round up mod 8. */ 100*1fd5a2e1SPrashanth Swaminathan addi FRAME_SIZE, STACK_ARG_BYTES, \ 101*1fd5a2e1SPrashanth Swaminathan REG_SIZE + REG_SIZE + LINKAGE_SIZE + 7 102*1fd5a2e1SPrashanth Swaminathan } 103*1fd5a2e1SPrashanth Swaminathan { 104*1fd5a2e1SPrashanth Swaminathan /* Round stack frame size to a multiple of 8 to satisfy ABI. */ 105*1fd5a2e1SPrashanth Swaminathan andi FRAME_SIZE, FRAME_SIZE, -8 106*1fd5a2e1SPrashanth Swaminathan /* Compute where to spill REG_ARGS value. */ 107*1fd5a2e1SPrashanth Swaminathan addi TMP2, sp, -(REG_SIZE * 2) 108*1fd5a2e1SPrashanth Swaminathan } 109*1fd5a2e1SPrashanth Swaminathan { 110*1fd5a2e1SPrashanth Swaminathan /* Spill incoming r52. */ 111*1fd5a2e1SPrashanth Swaminathan SW TMP, r52 112*1fd5a2e1SPrashanth Swaminathan .cfi_offset r52, -REG_SIZE 113*1fd5a2e1SPrashanth Swaminathan /* Set up our frame pointer. */ 114*1fd5a2e1SPrashanth Swaminathan move r52, sp 115*1fd5a2e1SPrashanth Swaminathan .cfi_def_cfa_register r52 116*1fd5a2e1SPrashanth Swaminathan /* Push stack frame. */ 117*1fd5a2e1SPrashanth Swaminathan sub sp, sp, FRAME_SIZE 118*1fd5a2e1SPrashanth Swaminathan } 119*1fd5a2e1SPrashanth Swaminathan { 120*1fd5a2e1SPrashanth Swaminathan /* Prepare to set up stack linkage. */ 121*1fd5a2e1SPrashanth Swaminathan addi TMP, sp, REG_SIZE 122*1fd5a2e1SPrashanth Swaminathan /* Prepare to memcpy stack args. */ 123*1fd5a2e1SPrashanth Swaminathan addi OUTGOING_STACK_ARGS, sp, LINKAGE_SIZE 124*1fd5a2e1SPrashanth Swaminathan /* Save REG_ARGS which we will need after we call the subroutine. */ 125*1fd5a2e1SPrashanth Swaminathan SW TMP2, REG_ARGS 126*1fd5a2e1SPrashanth Swaminathan } 127*1fd5a2e1SPrashanth Swaminathan { 128*1fd5a2e1SPrashanth Swaminathan /* Set up linkage info to hold incoming stack pointer. */ 129*1fd5a2e1SPrashanth Swaminathan SW TMP, r52 130*1fd5a2e1SPrashanth Swaminathan } 131*1fd5a2e1SPrashanth Swaminathan { 132*1fd5a2e1SPrashanth Swaminathan /* Skip stack args memcpy if we don't have any stack args (common). */ 133*1fd5a2e1SPrashanth Swaminathan blezt STACK_ARG_BYTES, .Ldone_stack_args_memcpy 134*1fd5a2e1SPrashanth Swaminathan } 135*1fd5a2e1SPrashanth Swaminathan 136*1fd5a2e1SPrashanth Swaminathan.Lmemcpy_stack_args: 137*1fd5a2e1SPrashanth Swaminathan { 138*1fd5a2e1SPrashanth Swaminathan /* Load incoming argument from stack_args. */ 139*1fd5a2e1SPrashanth Swaminathan LW TMP, INCOMING_STACK_ARGS 140*1fd5a2e1SPrashanth Swaminathan addi INCOMING_STACK_ARGS, INCOMING_STACK_ARGS, REG_SIZE 141*1fd5a2e1SPrashanth Swaminathan } 142*1fd5a2e1SPrashanth Swaminathan { 143*1fd5a2e1SPrashanth Swaminathan /* Store stack argument into outgoing stack argument area. */ 144*1fd5a2e1SPrashanth Swaminathan SW OUTGOING_STACK_ARGS, TMP 145*1fd5a2e1SPrashanth Swaminathan addi OUTGOING_STACK_ARGS, OUTGOING_STACK_ARGS, REG_SIZE 146*1fd5a2e1SPrashanth Swaminathan addi STACK_ARG_BYTES, STACK_ARG_BYTES, -REG_SIZE 147*1fd5a2e1SPrashanth Swaminathan } 148*1fd5a2e1SPrashanth Swaminathan { 149*1fd5a2e1SPrashanth Swaminathan BGZT STACK_ARG_BYTES, .Lmemcpy_stack_args 150*1fd5a2e1SPrashanth Swaminathan } 151*1fd5a2e1SPrashanth Swaminathan.Ldone_stack_args_memcpy: 152*1fd5a2e1SPrashanth Swaminathan 153*1fd5a2e1SPrashanth Swaminathan { 154*1fd5a2e1SPrashanth Swaminathan /* Copy aside ORIG_FNADDR so we can overwrite its register. */ 155*1fd5a2e1SPrashanth Swaminathan move FNADDR, ORIG_FNADDR 156*1fd5a2e1SPrashanth Swaminathan /* Prepare to load argument registers. */ 157*1fd5a2e1SPrashanth Swaminathan addi REG_ADDR_PTR, r0, REG_SIZE 158*1fd5a2e1SPrashanth Swaminathan /* Load outgoing r0. */ 159*1fd5a2e1SPrashanth Swaminathan LW r0, r0 160*1fd5a2e1SPrashanth Swaminathan } 161*1fd5a2e1SPrashanth Swaminathan 162*1fd5a2e1SPrashanth Swaminathan /* Load up argument registers from the REG_ARGS array. */ 163*1fd5a2e1SPrashanth Swaminathan#define LOAD_REG(REG, PTR) \ 164*1fd5a2e1SPrashanth Swaminathan { \ 165*1fd5a2e1SPrashanth Swaminathan LW REG, PTR ; \ 166*1fd5a2e1SPrashanth Swaminathan addi PTR, PTR, REG_SIZE \ 167*1fd5a2e1SPrashanth Swaminathan } 168*1fd5a2e1SPrashanth Swaminathan 169*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r1, REG_ADDR_PTR) 170*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r2, REG_ADDR_PTR) 171*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r3, REG_ADDR_PTR) 172*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r4, REG_ADDR_PTR) 173*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r5, REG_ADDR_PTR) 174*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r6, REG_ADDR_PTR) 175*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r7, REG_ADDR_PTR) 176*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r8, REG_ADDR_PTR) 177*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r9, REG_ADDR_PTR) 178*1fd5a2e1SPrashanth Swaminathan 179*1fd5a2e1SPrashanth Swaminathan { 180*1fd5a2e1SPrashanth Swaminathan /* Call the subroutine. */ 181*1fd5a2e1SPrashanth Swaminathan jalr FNADDR 182*1fd5a2e1SPrashanth Swaminathan } 183*1fd5a2e1SPrashanth Swaminathan 184*1fd5a2e1SPrashanth Swaminathan { 185*1fd5a2e1SPrashanth Swaminathan /* Restore original lr. */ 186*1fd5a2e1SPrashanth Swaminathan LW lr, r52 187*1fd5a2e1SPrashanth Swaminathan /* Prepare to recover ARGS, which we spilled earlier. */ 188*1fd5a2e1SPrashanth Swaminathan addi TMP, r52, -(2 * REG_SIZE) 189*1fd5a2e1SPrashanth Swaminathan } 190*1fd5a2e1SPrashanth Swaminathan { 191*1fd5a2e1SPrashanth Swaminathan /* Restore ARGS, so we can fill it in with the return regs r0-r9. */ 192*1fd5a2e1SPrashanth Swaminathan LW RETURN_REG_ADDR, TMP 193*1fd5a2e1SPrashanth Swaminathan /* Prepare to restore original r52. */ 194*1fd5a2e1SPrashanth Swaminathan addi TMP, r52, -REG_SIZE 195*1fd5a2e1SPrashanth Swaminathan } 196*1fd5a2e1SPrashanth Swaminathan 197*1fd5a2e1SPrashanth Swaminathan { 198*1fd5a2e1SPrashanth Swaminathan /* Pop stack frame. */ 199*1fd5a2e1SPrashanth Swaminathan move sp, r52 200*1fd5a2e1SPrashanth Swaminathan /* Restore original r52. */ 201*1fd5a2e1SPrashanth Swaminathan LW r52, TMP 202*1fd5a2e1SPrashanth Swaminathan } 203*1fd5a2e1SPrashanth Swaminathan 204*1fd5a2e1SPrashanth Swaminathan#define STORE_REG(REG, PTR) \ 205*1fd5a2e1SPrashanth Swaminathan { \ 206*1fd5a2e1SPrashanth Swaminathan SW PTR, REG ; \ 207*1fd5a2e1SPrashanth Swaminathan addi PTR, PTR, REG_SIZE \ 208*1fd5a2e1SPrashanth Swaminathan } 209*1fd5a2e1SPrashanth Swaminathan 210*1fd5a2e1SPrashanth Swaminathan /* Return all register values by reference. */ 211*1fd5a2e1SPrashanth Swaminathan STORE_REG(r0, RETURN_REG_ADDR) 212*1fd5a2e1SPrashanth Swaminathan STORE_REG(r1, RETURN_REG_ADDR) 213*1fd5a2e1SPrashanth Swaminathan STORE_REG(r2, RETURN_REG_ADDR) 214*1fd5a2e1SPrashanth Swaminathan STORE_REG(r3, RETURN_REG_ADDR) 215*1fd5a2e1SPrashanth Swaminathan STORE_REG(r4, RETURN_REG_ADDR) 216*1fd5a2e1SPrashanth Swaminathan STORE_REG(r5, RETURN_REG_ADDR) 217*1fd5a2e1SPrashanth Swaminathan STORE_REG(r6, RETURN_REG_ADDR) 218*1fd5a2e1SPrashanth Swaminathan STORE_REG(r7, RETURN_REG_ADDR) 219*1fd5a2e1SPrashanth Swaminathan STORE_REG(r8, RETURN_REG_ADDR) 220*1fd5a2e1SPrashanth Swaminathan STORE_REG(r9, RETURN_REG_ADDR) 221*1fd5a2e1SPrashanth Swaminathan 222*1fd5a2e1SPrashanth Swaminathan { 223*1fd5a2e1SPrashanth Swaminathan jrp lr 224*1fd5a2e1SPrashanth Swaminathan } 225*1fd5a2e1SPrashanth Swaminathan 226*1fd5a2e1SPrashanth Swaminathan .cfi_endproc 227*1fd5a2e1SPrashanth Swaminathan .size ffi_call_tile, .-ffi_call_tile 228*1fd5a2e1SPrashanth Swaminathan 229*1fd5a2e1SPrashanth Swaminathan/* ffi_closure_tile(...) 230*1fd5a2e1SPrashanth Swaminathan 231*1fd5a2e1SPrashanth Swaminathan On entry, lr points to the closure plus 8 bytes, and r10 232*1fd5a2e1SPrashanth Swaminathan contains the actual return address. 233*1fd5a2e1SPrashanth Swaminathan 234*1fd5a2e1SPrashanth Swaminathan This function simply dumps all register parameters into a stack array 235*1fd5a2e1SPrashanth Swaminathan and passes the closure, the registers array, and the stack arguments 236*1fd5a2e1SPrashanth Swaminathan to C code that does all of the actual closure processing. */ 237*1fd5a2e1SPrashanth Swaminathan 238*1fd5a2e1SPrashanth Swaminathan .section .text.ffi_closure_tile, "ax", @progbits 239*1fd5a2e1SPrashanth Swaminathan .align 8 240*1fd5a2e1SPrashanth Swaminathan .globl ffi_closure_tile 241*1fd5a2e1SPrashanth Swaminathan FFI_HIDDEN(ffi_closure_tile) 242*1fd5a2e1SPrashanth Swaminathan 243*1fd5a2e1SPrashanth Swaminathan .cfi_startproc 244*1fd5a2e1SPrashanth Swaminathan/* Room to spill all NUM_ARG_REGS incoming registers, plus frame linkage. */ 245*1fd5a2e1SPrashanth Swaminathan#define CLOSURE_FRAME_SIZE (((NUM_ARG_REGS * REG_SIZE * 2 + LINKAGE_SIZE) + 7) & -8) 246*1fd5a2e1SPrashanth Swaminathanffi_closure_tile: 247*1fd5a2e1SPrashanth Swaminathan { 248*1fd5a2e1SPrashanth Swaminathan#ifdef __tilegx__ 249*1fd5a2e1SPrashanth Swaminathan st sp, lr 250*1fd5a2e1SPrashanth Swaminathan .cfi_offset lr, 0 251*1fd5a2e1SPrashanth Swaminathan#else 252*1fd5a2e1SPrashanth Swaminathan /* Save return address (in r10 due to closure stub wrapper). */ 253*1fd5a2e1SPrashanth Swaminathan SW sp, r10 254*1fd5a2e1SPrashanth Swaminathan .cfi_return_column r10 255*1fd5a2e1SPrashanth Swaminathan .cfi_offset r10, 0 256*1fd5a2e1SPrashanth Swaminathan#endif 257*1fd5a2e1SPrashanth Swaminathan /* Compute address for stack frame linkage. */ 258*1fd5a2e1SPrashanth Swaminathan addli r10, sp, -(CLOSURE_FRAME_SIZE - REG_SIZE) 259*1fd5a2e1SPrashanth Swaminathan } 260*1fd5a2e1SPrashanth Swaminathan { 261*1fd5a2e1SPrashanth Swaminathan /* Save incoming stack pointer in linkage area. */ 262*1fd5a2e1SPrashanth Swaminathan SW r10, sp 263*1fd5a2e1SPrashanth Swaminathan .cfi_offset sp, -(CLOSURE_FRAME_SIZE - REG_SIZE) 264*1fd5a2e1SPrashanth Swaminathan /* Push a new stack frame. */ 265*1fd5a2e1SPrashanth Swaminathan addli sp, sp, -CLOSURE_FRAME_SIZE 266*1fd5a2e1SPrashanth Swaminathan .cfi_adjust_cfa_offset CLOSURE_FRAME_SIZE 267*1fd5a2e1SPrashanth Swaminathan } 268*1fd5a2e1SPrashanth Swaminathan 269*1fd5a2e1SPrashanth Swaminathan { 270*1fd5a2e1SPrashanth Swaminathan /* Create pointer to where to start spilling registers. */ 271*1fd5a2e1SPrashanth Swaminathan addi r10, sp, LINKAGE_SIZE 272*1fd5a2e1SPrashanth Swaminathan } 273*1fd5a2e1SPrashanth Swaminathan 274*1fd5a2e1SPrashanth Swaminathan /* Spill all the incoming registers. */ 275*1fd5a2e1SPrashanth Swaminathan STORE_REG(r0, r10) 276*1fd5a2e1SPrashanth Swaminathan STORE_REG(r1, r10) 277*1fd5a2e1SPrashanth Swaminathan STORE_REG(r2, r10) 278*1fd5a2e1SPrashanth Swaminathan STORE_REG(r3, r10) 279*1fd5a2e1SPrashanth Swaminathan STORE_REG(r4, r10) 280*1fd5a2e1SPrashanth Swaminathan STORE_REG(r5, r10) 281*1fd5a2e1SPrashanth Swaminathan STORE_REG(r6, r10) 282*1fd5a2e1SPrashanth Swaminathan STORE_REG(r7, r10) 283*1fd5a2e1SPrashanth Swaminathan STORE_REG(r8, r10) 284*1fd5a2e1SPrashanth Swaminathan { 285*1fd5a2e1SPrashanth Swaminathan /* Save r9. */ 286*1fd5a2e1SPrashanth Swaminathan SW r10, r9 287*1fd5a2e1SPrashanth Swaminathan#ifdef __tilegx__ 288*1fd5a2e1SPrashanth Swaminathan /* Pointer to closure is passed in r11. */ 289*1fd5a2e1SPrashanth Swaminathan move r0, r11 290*1fd5a2e1SPrashanth Swaminathan#else 291*1fd5a2e1SPrashanth Swaminathan /* Compute pointer to the closure object. Because the closure 292*1fd5a2e1SPrashanth Swaminathan starts with a "jal ffi_closure_tile", we can just take the 293*1fd5a2e1SPrashanth Swaminathan value of lr (a phony return address pointing into the closure) 294*1fd5a2e1SPrashanth Swaminathan and subtract 8. */ 295*1fd5a2e1SPrashanth Swaminathan addi r0, lr, -8 296*1fd5a2e1SPrashanth Swaminathan#endif 297*1fd5a2e1SPrashanth Swaminathan /* Compute a pointer to the register arguments we just spilled. */ 298*1fd5a2e1SPrashanth Swaminathan addi r1, sp, LINKAGE_SIZE 299*1fd5a2e1SPrashanth Swaminathan } 300*1fd5a2e1SPrashanth Swaminathan { 301*1fd5a2e1SPrashanth Swaminathan /* Compute a pointer to the extra stack arguments (if any). */ 302*1fd5a2e1SPrashanth Swaminathan addli r2, sp, CLOSURE_FRAME_SIZE + LINKAGE_SIZE 303*1fd5a2e1SPrashanth Swaminathan /* Call C code to deal with all of the grotty details. */ 304*1fd5a2e1SPrashanth Swaminathan jal ffi_closure_tile_inner 305*1fd5a2e1SPrashanth Swaminathan } 306*1fd5a2e1SPrashanth Swaminathan { 307*1fd5a2e1SPrashanth Swaminathan addli r10, sp, CLOSURE_FRAME_SIZE 308*1fd5a2e1SPrashanth Swaminathan } 309*1fd5a2e1SPrashanth Swaminathan { 310*1fd5a2e1SPrashanth Swaminathan /* Restore the return address. */ 311*1fd5a2e1SPrashanth Swaminathan LW lr, r10 312*1fd5a2e1SPrashanth Swaminathan /* Compute pointer to registers array. */ 313*1fd5a2e1SPrashanth Swaminathan addli r10, sp, LINKAGE_SIZE + (NUM_ARG_REGS * REG_SIZE) 314*1fd5a2e1SPrashanth Swaminathan } 315*1fd5a2e1SPrashanth Swaminathan /* Return all the register values, which C code may have set. */ 316*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r0, r10) 317*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r1, r10) 318*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r2, r10) 319*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r3, r10) 320*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r4, r10) 321*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r5, r10) 322*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r6, r10) 323*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r7, r10) 324*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r8, r10) 325*1fd5a2e1SPrashanth Swaminathan LOAD_REG(r9, r10) 326*1fd5a2e1SPrashanth Swaminathan { 327*1fd5a2e1SPrashanth Swaminathan /* Pop the frame. */ 328*1fd5a2e1SPrashanth Swaminathan addli sp, sp, CLOSURE_FRAME_SIZE 329*1fd5a2e1SPrashanth Swaminathan jrp lr 330*1fd5a2e1SPrashanth Swaminathan } 331*1fd5a2e1SPrashanth Swaminathan 332*1fd5a2e1SPrashanth Swaminathan .cfi_endproc 333*1fd5a2e1SPrashanth Swaminathan .size ffi_closure_tile, . - ffi_closure_tile 334*1fd5a2e1SPrashanth Swaminathan 335*1fd5a2e1SPrashanth Swaminathan 336*1fd5a2e1SPrashanth Swaminathan/* What follows are code template instructions that get copied to the 337*1fd5a2e1SPrashanth Swaminathan closure trampoline by ffi_prep_closure_loc. The zeroed operands 338*1fd5a2e1SPrashanth Swaminathan get replaced by their proper values at runtime. */ 339*1fd5a2e1SPrashanth Swaminathan 340*1fd5a2e1SPrashanth Swaminathan .section .text.ffi_template_tramp_tile, "ax", @progbits 341*1fd5a2e1SPrashanth Swaminathan .align 8 342*1fd5a2e1SPrashanth Swaminathan .globl ffi_template_tramp_tile 343*1fd5a2e1SPrashanth Swaminathan FFI_HIDDEN(ffi_template_tramp_tile) 344*1fd5a2e1SPrashanth Swaminathanffi_template_tramp_tile: 345*1fd5a2e1SPrashanth Swaminathan#ifdef __tilegx__ 346*1fd5a2e1SPrashanth Swaminathan { 347*1fd5a2e1SPrashanth Swaminathan moveli r11, 0 /* backpatched to address of containing closure. */ 348*1fd5a2e1SPrashanth Swaminathan moveli r10, 0 /* backpatched to ffi_closure_tile. */ 349*1fd5a2e1SPrashanth Swaminathan } 350*1fd5a2e1SPrashanth Swaminathan /* Note: the following bundle gets generated multiple times 351*1fd5a2e1SPrashanth Swaminathan depending on the pointer value (esp. useful for -m32 mode). */ 352*1fd5a2e1SPrashanth Swaminathan { shl16insli r11, r11, 0 ; shl16insli r10, r10, 0 } 353*1fd5a2e1SPrashanth Swaminathan { info 2+8 /* for backtracer: -> pc in lr, frame size 0 */ ; jr r10 } 354*1fd5a2e1SPrashanth Swaminathan#else 355*1fd5a2e1SPrashanth Swaminathan /* 'jal .' yields a PC-relative offset of zero so we can OR in the 356*1fd5a2e1SPrashanth Swaminathan right offset at runtime. */ 357*1fd5a2e1SPrashanth Swaminathan { move r10, lr ; jal . /* ffi_closure_tile */ } 358*1fd5a2e1SPrashanth Swaminathan#endif 359*1fd5a2e1SPrashanth Swaminathan 360*1fd5a2e1SPrashanth Swaminathan .size ffi_template_tramp_tile, . - ffi_template_tramp_tile 361