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 /* Load the allocation pointer, preserving the low-bit of alloc */
126 lw reg_BSP, dynamic_space_free_pointer
127 addu reg_ALLOC, reg_BSP
129 /* Load the rest of the LISP state. */
130 lw reg_BSP, current_binding_stack_pointer
131 lw reg_CSP, current_control_stack_pointer
132 lw reg_OCFP, current_control_frame_pointer
134 /* Check for interrupt */
145 lw reg_A0, 0(reg_CFP)
146 lw reg_A1, 4(reg_CFP)
147 lw reg_A2, 8(reg_CFP)
148 lw reg_A3, 12(reg_CFP)
149 lw reg_A4, 16(reg_CFP)
150 lw reg_A5, 20(reg_CFP)
153 la reg_LRA, lra - RETURN_PC_RETURN_POINT_OFFSET
155 /* Indirect closure */
156 lw reg_CODE, CLOSURE_FUN_OFFSET(reg_LEXENV)
158 addu reg_LIP, reg_CODE, SIMPLE_FUN_CODE_OFFSET
160 /* Mark us as in Lisp land. */
161 sw zero, foreign_function_call_active
163 /* Jump into lisp land. */
168 lra: .word RETURN_PC_HEADER_WIDETAG
170 /* Multiple value return spot, clear stack. */
171 move reg_CSP, reg_OCFP
174 /* Single value return spot. */
176 /* Nested lisp -> C calls may have clobbered gp. */
177 lw gp, framesize-16(sp)
179 /* Set the pseudo-atomic flag. */
184 /* Mark us as in C land. */
185 sw reg_CSP, foreign_function_call_active
187 /* Save LISP state. */
188 subu reg_NL0, reg_ALLOC, 1
189 sw reg_NL0, dynamic_space_free_pointer
190 sw reg_BSP, current_binding_stack_pointer
191 sw reg_CSP, current_control_stack_pointer
192 sw reg_CFP, current_control_frame_pointer
194 /* Check for interrupt */
201 /* Pass one return value back to C land. For a 64bit value, we may
202 need to clobber v1 aka reg_NL4. */
203 move v0, reg_A0 # reg_CFUNC
204 move v1, reg_A1 # reg_NL4
207 lw ra, framesize-8(sp)
208 lw s8, framesize-12(sp)
209 lw s7, framesize-20(sp)
210 lw s6, framesize-24(sp)
211 lw s5, framesize-28(sp)
212 lw s4, framesize-32(sp)
213 lw s3, framesize-36(sp)
214 lw s2, framesize-40(sp)
215 lw s1, framesize-44(sp)
216 lw s0, framesize-48(sp)
218 /* Restore C stack. */
227 * Transfering control from Lisp into C
229 NESTED(call_into_c, 0, ra)
230 /* The C stack frame was already set up from lisp, and the
231 argument registers as well. We have to fake the correct
232 gp value for this function, though. */
236 lui gp, %hi(_gp_disp)
237 addiu gp, %lo(_gp_disp)
238 lui reg_NL3, %hi(call_into_c)
239 addiu reg_NL3, %lo(call_into_c)
244 /* Setup the lisp stack. */
245 move reg_OCFP, reg_CFP
246 move reg_CFP, reg_CSP
247 addu reg_CSP, reg_CFP, 32
249 /* Set the pseudo-atomic flag. */
255 /* Mark us as in C land. */
256 sw reg_CSP, foreign_function_call_active
258 /* Convert the return address to an offset and save it on the stack. */
259 subu reg_NFP, reg_LIP, reg_CODE
260 addu reg_NFP, OTHER_POINTER_LOWTAG
261 sw reg_LRA, (reg_CFP)
262 sw reg_CODE, 4(reg_CFP)
265 /* Save LISP state. */
266 subu reg_A0, reg_ALLOC, 1
267 sw reg_A0, dynamic_space_free_pointer
268 sw reg_BSP, current_binding_stack_pointer
269 sw reg_CSP, current_control_stack_pointer
270 sw reg_CFP, current_control_frame_pointer
272 /* Check for interrupt */
279 /* Into C land we go. */
280 move t9, reg_CFUNC # reg_ALLOC
285 /* Pass 64bit return value to lisp land. */
286 move reg_NL0, v0 # reg_CFUNC
287 move reg_NL1, v1 # reg_NL4
290 * Clear boxed descriptor registers before allowing an interrupt.
291 * We can't rely on C saving some of those registers, they might
292 * have been GCed in the meanwhile.
301 li reg_LEXENV, 0 # t7
303 * reg_NFP and reg_OCFP are pointing to fixed locations and are
312 /* Turn on pseudo-atomic. */
318 /* Load the allocation pointer, preserving the low-bit of alloc */
319 lw reg_BSP, dynamic_space_free_pointer
320 addu reg_ALLOC, reg_BSP
322 lw reg_BSP, current_binding_stack_pointer
324 /* Restore LRA & CODE */
325 lw reg_LRA, (reg_CFP)
326 lw reg_CODE, 4(reg_CFP)
327 subu reg_LIP, reg_NFP, OTHER_POINTER_LOWTAG
328 addu reg_LIP, reg_CODE
330 /* Check for interrupt */
337 /* Reset the lisp stack. */
338 /* Note: OCFP and CFP are in saved regs. */
339 move reg_CSP, reg_CFP
340 move reg_CFP, reg_OCFP
342 /* Mark us as in Lisp land. */
343 sw zero, foreign_function_call_active
345 /* Return to LISP. */
350 * Trampolines follow the Lisp calling convention.
352 * The undefined-function trampoline.
354 .align 3 /* minimum alignment for a lisp object */
355 .word SIMPLE_FUN_HEADER_WIDETAG /* header */
356 .word undefined_tramp - SIMPLE_FUN_CODE_OFFSET /* self */
359 .word NIL /* arglist */
361 LEAF(undefined_tramp)
362 /* Point reg_CODE to the header and tag it as function, since
363 the debugger regards a function pointer in reg_CODE which
364 doesn't point to a code object as undefined function. */
365 lui reg_CODE, %hi(undefined_tramp)
366 addiu reg_CODE, %lo(undefined_tramp)
367 addiu reg_CODE, - 24 + FUN_POINTER_LOWTAG
370 break 0x0, trap_Cerror
371 /* Error data length. */
374 .byte UNDEFINED_FUN_ERROR
375 /* Magic value 254 means a 16bit little endian value follows.
376 See debug-var-io.lisp. */
378 /* reg_FDEFN is #14. */
379 .byte ((14 << 5) + sc_DescriptorReg) % 0x100
380 .byte ((14 << 5) + sc_DescriptorReg) / 0x100
383 1: lw reg_CODE, FDEFN_FUN_OFFSET(reg_FDEFN)
384 lw reg_LIP, SIMPLE_FUN_CODE_OFFSET(reg_CODE)
389 * The closure trampoline.
391 .align 5 /* common MIPS cacheline size */
394 .word SIMPLE_FUN_HEADER_WIDETAG /* header */
395 .word closure_tramp - SIMPLE_FUN_CODE_OFFSET /* self */
398 .word NIL /* arglist */
401 lw reg_LEXENV, FDEFN_FUN_OFFSET(reg_FDEFN)
402 lw reg_CODE, CLOSURE_FUN_OFFSET(reg_LEXENV)
403 addu reg_LIP, reg_CODE, SIMPLE_FUN_CODE_OFFSET
408 * Function-end breakpoint magic. This is truely magic, the code is
409 * copied and has to be relocatable. It also needs a properly aligned
410 * header tag after the fun_end_breakpoint_guts symbol.
412 .align 3 /* minimum alignment for a lisp object */
413 LEAF(fun_end_breakpoint_guts)
415 .word RETURN_PC_HEADER_WIDETAG
416 b multiple_value_return
420 /* single value return */
422 move reg_OCFP, reg_CSP
431 multiple_value_return:
433 FEXPORT(fun_end_breakpoint_trap)
434 break 0x0, trap_FunEndBreakpoint
435 b multiple_value_return
436 EXPORT(fun_end_breakpoint_end)
437 END(fun_end_breakpoint_guts)