4 #include "genesis/fdefn.h"
5 #include "genesis/closure.h"
6 #include "genesis/return-pc.h"
7 #include "genesis/simple-fun.h"
8 #include "genesis/static-symbols.h"
44 * LEAF - declare leaf routine
46 #define LEAF(symbol) \
49 .type symbol,@function; \
51 symbol: .frame sp,0,ra
54 * NESTED - declare nested routine entry point
56 #define NESTED(symbol, framesize, rpc) \
59 .type symbol,@function; \
61 symbol: .frame sp, framesize, rpc
64 * END - mark end of function
66 #define END(function) \
68 .size function,.-function
71 * EXPORT - export definition of symbol
73 #define EXPORT(symbol) \
78 * FEXPORT - export definition of a function symbol
80 #define FEXPORT(symbol) \
82 .type symbol,@function; \
89 * Function to transfer control into lisp.
91 #define framesize 16*4
92 NESTED(call_into_lisp, framesize, ra)
98 /* Save all the C regs. */
100 sw ra, framesize-8(sp)
101 sw s8, framesize-12(sp)
102 /* No .cprestore, we don't want automatic gp restauration. */
103 sw gp, framesize-16(sp)
104 sw s7, framesize-20(sp)
105 sw s6, framesize-24(sp)
106 sw s5, framesize-28(sp)
107 sw s4, framesize-32(sp)
108 sw s3, framesize-36(sp)
109 sw s2, framesize-40(sp)
110 sw s1, framesize-44(sp)
111 sw s0, framesize-48(sp)
115 /* Clear unsaved boxed descriptor regs */
119 /* Turn on pseudo-atomic. */
125 /* Mark us as in Lisp land. */
126 sw zero, foreign_function_call_active
128 /* Load the allocation pointer, preserving the low-bit of alloc */
129 lw reg_BSP, dynamic_space_free_pointer
130 addu reg_ALLOC, reg_BSP
132 /* Load the rest of the LISP state. */
133 lw reg_BSP, current_binding_stack_pointer
134 lw reg_CSP, current_control_stack_pointer
135 lw reg_OCFP, current_control_frame_pointer
137 /* Check for interrupt */
148 lw reg_A0, 0(reg_CFP)
149 lw reg_A1, 4(reg_CFP)
150 lw reg_A2, 8(reg_CFP)
151 lw reg_A3, 12(reg_CFP)
152 lw reg_A4, 16(reg_CFP)
153 lw reg_A5, 20(reg_CFP)
156 la reg_LRA, lra - RETURN_PC_RETURN_POINT_OFFSET
158 /* Indirect closure */
159 lw reg_CODE, CLOSURE_FUN_OFFSET(reg_LEXENV)
161 /* Jump into lisp land. */
162 addu reg_LIP, reg_CODE, SIMPLE_FUN_CODE_OFFSET
167 lra: .word RETURN_PC_HEADER_WIDETAG
169 /* Multiple value return spot, clear stack. */
170 move reg_CSP, reg_OCFP
173 /* Single value return spot. */
175 /* Nested lisp -> C calls may have clobbered gp. */
176 lw gp, framesize-16(sp)
178 /* Set the pseudo-atomic flag. */
183 /* Save LISP state. */
184 subu reg_NL0, reg_ALLOC, 1
185 sw reg_NL0, dynamic_space_free_pointer
186 sw reg_BSP, current_binding_stack_pointer
187 sw reg_CSP, current_control_stack_pointer
188 sw reg_CFP, current_control_frame_pointer
190 /* Mark us as in C land. */
191 sw reg_CSP, foreign_function_call_active
193 /* Check for interrupt */
200 /* Pass one return value back to C land. For a 64bit value, we may
201 need to clobber v1 aka reg_NL4. */
202 move v0, reg_A0 # reg_CFUNC
203 move v1, reg_A1 # reg_NL4
206 lw ra, framesize-8(sp)
207 lw s8, framesize-12(sp)
208 lw s7, framesize-20(sp)
209 lw s6, framesize-24(sp)
210 lw s5, framesize-28(sp)
211 lw s4, framesize-32(sp)
212 lw s3, framesize-36(sp)
213 lw s2, framesize-40(sp)
214 lw s1, framesize-44(sp)
215 lw s0, framesize-48(sp)
217 /* Restore C stack. */
226 * Transfering control from Lisp into C
228 NESTED(call_into_c, 0, ra)
229 /* The C stack frame was already set up from lisp, and the
230 argument registers as well. We have to fake the correct
231 gp value for this function, though. */
235 lui gp, %hi(_gp_disp)
236 addiu gp, %lo(_gp_disp)
237 lui reg_NL3, %hi(call_into_c)
238 addiu reg_NL3, %lo(call_into_c)
243 move reg_OCFP, reg_CFP
244 move reg_CFP, reg_CSP
245 addu reg_CSP, reg_CFP, 32
247 /* Set the pseudo-atomic flag. */
253 /* Convert the return address to an offset and save it on the stack. */
254 subu reg_NFP, reg_LIP, reg_CODE
255 addu reg_NFP, OTHER_POINTER_LOWTAG
256 sw reg_NFP, (reg_CFP)
257 sw reg_CODE, 4(reg_CFP)
260 /* Save LISP state. */
261 subu reg_A0, reg_ALLOC, 1
262 sw reg_A0, dynamic_space_free_pointer
263 sw reg_BSP, current_binding_stack_pointer
264 sw reg_CSP, current_control_stack_pointer
265 sw reg_CFP, current_control_frame_pointer
267 /* Mark us as in C land. */
268 sw reg_CSP, foreign_function_call_active
270 /* Check for interrupt */
277 /* Into C land we go. */
278 move t9, reg_CFUNC # reg_ALLOC
283 /* Pass 64bit return value to lisp land. */
284 move reg_NL0, v0 # reg_CFUNC
285 move reg_NL1, v1 # reg_NL4
287 /* Clear unsaved boxed descriptor regs before allowing an interrupt */
295 li reg_LEXENV, 0 # t7
299 /* Turn on pseudo-atomic. */
305 /* Mark us as in Lisp land. */
306 sw zero, foreign_function_call_active
308 /* Load the allocation pointer, preserving the low-bit of alloc */
309 lw reg_BSP, dynamic_space_free_pointer
310 addu reg_ALLOC, reg_BSP
312 lw reg_BSP, current_binding_stack_pointer
314 /* Restore LRA & CODE */
315 lw reg_LIP, (reg_CFP)
316 lw reg_CODE, 4(reg_CFP)
317 subu reg_LIP, OTHER_POINTER_LOWTAG
318 addu reg_LIP, reg_CODE
320 /* Check for interrupt */
327 /* Reset the lisp stack. */
328 /* Note: OCFP and CFP are in saved regs. */
329 move reg_CSP, reg_CFP
330 move reg_CFP, reg_OCFP
332 /* Return to LISP. */
337 * Trampolines follow the Lisp calling convention.
339 * The undefined-function trampoline.
342 .word SIMPLE_FUN_HEADER_WIDETAG /* header */
343 .word undefined_tramp - SIMPLE_FUN_CODE_OFFSET /* self */
346 .word NIL /* arglist */
348 LEAF(undefined_tramp)
351 .byte UNDEFINED_FUN_ERROR
353 .byte (0xc0 + sc_DescriptorReg)
359 * The closure trampoline.
362 .word SIMPLE_FUN_HEADER_WIDETAG /* header */
363 .word closure_tramp - SIMPLE_FUN_CODE_OFFSET /* self */
366 .word NIL /* arglist */
369 lw reg_LEXENV, FDEFN_FUN_OFFSET(reg_FDEFN)
370 lw reg_CODE, CLOSURE_FUN_OFFSET(reg_LEXENV)
371 addu reg_LIP, reg_CODE, SIMPLE_FUN_CODE_OFFSET
376 * Function-end breakpoint magic.
379 LEAF(fun_end_breakpoint_guts)
381 .word RETURN_PC_HEADER_WIDETAG
383 b multiple_value_return
387 move reg_OCFP, reg_CSP
396 multiple_value_return:
398 FEXPORT(fun_end_breakpoint_trap)
399 break trap_FunEndBreakpoint
400 b multiple_value_return
401 EXPORT(fun_end_breakpoint_end)
402 END(fun_end_breakpoint_guts)