2 * very-low-level utilities for runtime support
6 * This software is part of the SBCL system. See the README file for
9 * This software is derived from the CMU CL system, which was
10 * written at Carnegie Mellon University and released into the
11 * public domain. The software is in the public domain and is
12 * provided with absolutely no warranty. See the COPYING and CREDITS
13 * files for more information.
19 #include "genesis/fdefn.h"
20 #include "genesis/closure.h"
21 #include "genesis/funcallable-instance.h"
22 #include "genesis/simple-fun.h"
23 #include "genesis/static-symbols.h"
59 * LEAF - declare leaf routine
61 #define LEAF(symbol) \
64 .type symbol,@function; \
66 symbol: .frame sp,0,ra
69 * NESTED - declare nested routine entry point
71 #define NESTED(symbol, framesize, rpc) \
74 .type symbol,@function; \
76 symbol: .frame sp, framesize, rpc
79 * END - mark end of function
81 #define END(function) \
83 .size function,.-function
86 * EXPORT - export definition of symbol
88 #define EXPORT(symbol) \
93 * FEXPORT - export definition of a function symbol
95 #define FEXPORT(symbol) \
97 .type symbol,@function; \
104 * Function to transfer control into lisp.
106 #define framesize 16*4
107 NESTED(call_into_lisp, framesize, ra)
113 /* Save all the C regs. */
115 sw ra, framesize-8(sp)
116 sw s8, framesize-12(sp)
117 /* No .cprestore, we don't want automatic gp restauration. */
118 sw gp, framesize-16(sp)
119 sw s7, framesize-20(sp)
120 sw s6, framesize-24(sp)
121 sw s5, framesize-28(sp)
122 sw s4, framesize-32(sp)
123 sw s3, framesize-36(sp)
124 sw s2, framesize-40(sp)
125 sw s1, framesize-44(sp)
126 sw s0, framesize-48(sp)
130 /* Clear unsaved boxed descriptor regs */
134 /* Turn on pseudo-atomic. */
140 /* Load the allocation pointer, preserving the low-bit of alloc */
141 lw reg_BSP, dynamic_space_free_pointer
142 addu reg_ALLOC, reg_BSP
144 /* Load the rest of the LISP state. */
145 lw reg_BSP, current_binding_stack_pointer
146 lw reg_CSP, current_control_stack_pointer
147 lw reg_OCFP, current_control_frame_pointer
149 /* Check for interrupt */
153 break 0x0, trap_PendingInterrupt
160 lw reg_A0, 0(reg_CFP)
161 lw reg_A1, 4(reg_CFP)
162 lw reg_A2, 8(reg_CFP)
163 lw reg_A3, 12(reg_CFP)
164 lw reg_A4, 16(reg_CFP)
165 lw reg_A5, 20(reg_CFP)
168 la reg_LRA, lra + OTHER_POINTER_LOWTAG
170 /* Indirect closure */
171 lw reg_CODE, CLOSURE_FUN_OFFSET(reg_LEXENV)
173 addu reg_LIP, reg_CODE, SIMPLE_FUN_CODE_OFFSET
175 /* Mark us as in Lisp land. */
176 sw zero, foreign_function_call_active
178 /* Jump into lisp land. */
183 lra: .word RETURN_PC_HEADER_WIDETAG
185 /* Multiple value return spot, clear stack. */
186 move reg_CSP, reg_OCFP
189 /* Single value return spot. */
191 /* Nested lisp -> C calls may have clobbered gp. */
192 lw gp, framesize-16(sp)
194 /* Mark us as in C land. */
195 sw reg_CSP, foreign_function_call_active
197 /* Set the pseudo-atomic flag. */
202 /* Save LISP state. */
203 subu reg_NL0, reg_ALLOC, 1
204 sw reg_NL0, dynamic_space_free_pointer
205 sw reg_BSP, current_binding_stack_pointer
206 sw reg_CSP, current_control_stack_pointer
207 sw reg_CFP, current_control_frame_pointer
209 /* Check for interrupt */
213 break 0x0, trap_PendingInterrupt
216 /* Pass one return value back to C land. For a 64bit value, we may
217 need to clobber v1 aka reg_NL4. */
218 move v0, reg_A0 # reg_CFUNC
219 move v1, reg_A1 # reg_NL4
222 lw ra, framesize-8(sp)
223 lw s8, framesize-12(sp)
224 lw s7, framesize-20(sp)
225 lw s6, framesize-24(sp)
226 lw s5, framesize-28(sp)
227 lw s4, framesize-32(sp)
228 lw s3, framesize-36(sp)
229 lw s2, framesize-40(sp)
230 lw s1, framesize-44(sp)
231 lw s0, framesize-48(sp)
233 /* Restore C stack. */
242 * Transfering control from Lisp into C
244 NESTED(call_into_c, 0, ra)
245 /* The C stack frame was already set up from lisp, and the
246 argument registers as well. We have to fake the correct
247 gp value for this function, though. */
251 lui gp, %hi(_gp_disp)
252 addiu gp, %lo(_gp_disp)
253 lui reg_NL3, %hi(call_into_c)
254 addiu reg_NL3, %lo(call_into_c)
259 /* Setup the lisp stack. */
260 move reg_OCFP, reg_CFP
261 move reg_CFP, reg_CSP
262 addu reg_CSP, reg_CFP, 32
264 /* Mark us as in C land. */
265 sw reg_CSP, foreign_function_call_active
267 /* Set the pseudo-atomic flag. */
273 /* Convert the return address to an offset and save it on the stack. */
274 subu reg_NFP, reg_LIP, reg_CODE
275 addu reg_NFP, OTHER_POINTER_LOWTAG
276 sw reg_OCFP, (reg_CFP)
277 sw reg_NFP, 4(reg_CFP)
278 sw reg_CODE, 8(reg_CFP)
279 sw gp, 12(reg_CFP) // should this be saved? on the control stack?
281 /* Save LISP state. */
282 subu reg_A0, reg_ALLOC, 1
283 sw reg_A0, dynamic_space_free_pointer
284 sw reg_BSP, current_binding_stack_pointer
285 sw reg_CSP, current_control_stack_pointer
286 sw reg_CFP, current_control_frame_pointer
288 /* Check for interrupt */
292 break 0x0, trap_PendingInterrupt
295 /* Into C land we go. */
296 move t9, reg_CFUNC # reg_ALLOC
301 /* Pass 64bit return value to lisp land. */
302 move reg_NL0, v0 # reg_CFUNC
303 move reg_NL1, v1 # reg_NL4
306 * Clear boxed descriptor registers before allowing an interrupt.
307 * We can't rely on C saving some of those registers, they might
308 * have been GCed in the meanwhile.
317 li reg_LEXENV, 0 # t7
319 * reg_NFP and reg_OCFP are pointing to fixed locations and are
328 /* Turn on pseudo-atomic. */
334 /* Load the allocation pointer, preserving the low-bit of alloc */
335 lw reg_BSP, dynamic_space_free_pointer
336 addu reg_ALLOC, reg_BSP
338 lw reg_BSP, current_binding_stack_pointer
341 lw reg_CODE, 8(reg_CFP)
342 /* Setup the return address */
343 subu reg_LIP, reg_NFP, OTHER_POINTER_LOWTAG
344 addu reg_LIP, reg_CODE
346 /* Check for interrupt */
350 break 0x0, trap_PendingInterrupt
353 /* Reset the lisp stack. */
354 /* Note: OCFP and CFP are in saved regs. */
355 move reg_CSP, reg_CFP
356 move reg_CFP, reg_OCFP
358 /* Mark us as in Lisp land. */
359 sw zero, foreign_function_call_active
361 /* Return to LISP. */
366 * Function-end breakpoint magic. This is truely magic, the code is
367 * copied and has to be relocatable. It also needs a properly aligned
368 * header tag after the fun_end_breakpoint_guts symbol.
372 * For an explanation of the magic involved in function-end
373 * breakpoints, see the implementation in ppc-assem.S.
376 .align 3 /* minimum alignment for a lisp object */
377 LEAF(fun_end_breakpoint_guts)
379 .word RETURN_PC_HEADER_WIDETAG + 0x600
380 b multiple_value_return
384 /* single value return */
386 move reg_OCFP, reg_CSP
395 multiple_value_return:
397 FEXPORT(fun_end_breakpoint_trap)
399 b multiple_value_return
400 break 0x0, trap_FunEndBreakpoint
402 EXPORT(fun_end_breakpoint_end)
403 END(fun_end_breakpoint_guts)
406 .align 3 /* minimum alignment for a lisp object */
407 LEAF(do_pending_interrupt)
408 break 0x0, trap_PendingInterrupt
410 END(do_pending_interrupt)