xref: /aosp_15_r20/external/libffi/src/tile/tile.S (revision 1fd5a2e1d639cd1ddf29dd0c484c123bbd850c21)
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