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 /* Setup the lisp stack. */
244 move reg_OCFP, reg_CFP
245 move reg_CFP, reg_CSP
246 addu reg_CSP, reg_CFP, 32
248 /* Set the pseudo-atomic flag. */
254 /* Convert the return address to an offset and save it on the stack. */
255 subu reg_NFP, reg_LIP, reg_CODE
256 addu reg_NFP, OTHER_POINTER_LOWTAG
257 sw reg_LRA, (reg_CFP)
258 sw reg_CODE, 4(reg_CFP)
261 /* Save LISP state. */
262 subu reg_A0, reg_ALLOC, 1
263 sw reg_A0, dynamic_space_free_pointer
264 sw reg_BSP, current_binding_stack_pointer
265 sw reg_CSP, current_control_stack_pointer
266 sw reg_CFP, current_control_frame_pointer
268 /* Mark us as in C land. */
269 sw reg_CSP, foreign_function_call_active
271 /* Check for interrupt */
278 /* Into C land we go. */
279 move t9, reg_CFUNC # reg_ALLOC
284 /* Pass 64bit return value to lisp land. */
285 move reg_NL0, v0 # reg_CFUNC
286 move reg_NL1, v1 # reg_NL4
289 * Clear boxed descriptor registers before allowing an interrupt.
290 * We can't rely on C saving some of those registers, they might
291 * have been GCed in the meanwhile.
300 li reg_LEXENV, 0 # t7
302 * reg_NFP and reg_OCFP are pointing to fixed locations and are
311 /* Turn on pseudo-atomic. */
317 /* Mark us as in Lisp land. */
318 sw zero, foreign_function_call_active
320 /* Load the allocation pointer, preserving the low-bit of alloc */
321 lw reg_BSP, dynamic_space_free_pointer
322 addu reg_ALLOC, reg_BSP
324 lw reg_BSP, current_binding_stack_pointer
326 /* Restore LRA & CODE */
327 lw reg_LRA, (reg_CFP)
328 lw reg_CODE, 4(reg_CFP)
329 subu reg_LIP, reg_NFP, OTHER_POINTER_LOWTAG
330 addu reg_LIP, reg_CODE
332 /* Check for interrupt */
339 /* Reset the lisp stack. */
340 /* Note: OCFP and CFP are in saved regs. */
341 move reg_CSP, reg_CFP
342 move reg_CFP, reg_OCFP
344 /* Return to LISP. */
349 * Trampolines follow the Lisp calling convention.
351 * The undefined-function trampoline.
353 .align 3 /* minimum alignment for a lisp object */
354 .word SIMPLE_FUN_HEADER_WIDETAG /* header */
355 .word undefined_tramp - SIMPLE_FUN_CODE_OFFSET /* self */
358 .word NIL /* arglist */
360 LEAF(undefined_tramp)
361 /* Point reg_CODE to the header and tag it as function, since
362 the debugger regards a function pointer in reg_CODE which
363 doesn't point to a code object as undefined function. */
364 lui reg_CODE, %hi(undefined_tramp)
365 addiu reg_CODE, %lo(undefined_tramp)
366 addiu reg_CODE, - 24 + FUN_POINTER_LOWTAG
369 break 0x0, trap_Cerror
370 /* Error data length. */
373 .byte UNDEFINED_FUN_ERROR
374 /* Magic value 254 means a 16bit little endian value follows.
375 See debug-var-io.lisp. */
377 /* reg_FDEFN is #14. */
378 .byte ((14 << 5) + sc_DescriptorReg) % 0x100
379 .byte ((14 << 5) + sc_DescriptorReg) / 0x100
382 1: lw reg_CODE, FDEFN_FUN_OFFSET(reg_FDEFN)
383 lw reg_LIP, SIMPLE_FUN_CODE_OFFSET(reg_CODE)
388 * The closure trampoline.
390 .align 5 /* common MIPS cacheline size */
393 .word SIMPLE_FUN_HEADER_WIDETAG /* header */
394 .word closure_tramp - SIMPLE_FUN_CODE_OFFSET /* self */
397 .word NIL /* arglist */
400 lw reg_LEXENV, FDEFN_FUN_OFFSET(reg_FDEFN)
401 lw reg_CODE, CLOSURE_FUN_OFFSET(reg_LEXENV)
402 addu reg_LIP, reg_CODE, SIMPLE_FUN_CODE_OFFSET
407 * Function-end breakpoint magic.
409 .align 3 /* minimum alignment for a lisp object */
411 .word RETURN_PC_HEADER_WIDETAG
412 LEAF(fun_end_breakpoint_guts)
413 b multiple_value_return
417 /* single value return */
419 move reg_OCFP, reg_CSP
428 multiple_value_return:
430 FEXPORT(fun_end_breakpoint_trap)
431 break trap_FunEndBreakpoint
432 b multiple_value_return
433 EXPORT(fun_end_breakpoint_end)
434 END(fun_end_breakpoint_guts)