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.
17 // Mark the object as not requiring an executable stack.
18 .section .note.GNU-stack,"",%progbits
21 #include "genesis/sbcl.h"
23 #include "genesis/closure.h"
24 #include "genesis/static-symbols.h"
25 #include "genesis/symbol.h"
61 * LEAF - declare leaf routine
63 #define LEAF(symbol) \
66 .type symbol,@function; \
68 symbol: .frame sp,0,ra
71 * NESTED - declare nested routine entry point
73 #define NESTED(symbol, framesize, rpc) \
76 .type symbol,@function; \
78 symbol: .frame sp, framesize, rpc
81 * END - mark end of function
83 #define END(function) \
85 .size function,.-function
88 * EXPORT - export definition of symbol
90 #define EXPORT(symbol) \
95 * FEXPORT - export definition of a function symbol
97 #define FEXPORT(symbol) \
99 .type symbol,@function; \
102 /* zero (or anything non-nil) -> atomic=true and NIL -> atomic=false */
103 #define BEGIN_PSEUDO_ATOMIC \
105 sw zero, (PSEUDO_ATOMIC_ATOMIC+SYMBOL_VALUE_OFFSET-NIL)(reg_NIL) ; \
107 #define END_PSEUDO_ATOMIC(temp) \
109 sw reg_NIL, (PSEUDO_ATOMIC_ATOMIC+SYMBOL_VALUE_OFFSET-NIL)(reg_NIL) ; \
110 lw temp, (PSEUDO_ATOMIC_INTERRUPTED+SYMBOL_VALUE_OFFSET-NIL)(reg_NIL) ; \
111 tne zero, temp, 0 ; \
117 * Function to transfer control into lisp.
119 #define framesize 16*4
120 NESTED(call_into_lisp, framesize, ra)
126 /* Save all the C regs. */
128 sw ra, framesize-8(sp)
129 sw s8, framesize-12(sp)
130 sw $gp, framesize-16(sp)
131 /* No .cprestore, we don't want automatic gp restoration. */
132 sw s7, framesize-20(sp)
133 sw s6, framesize-24(sp)
134 sw s5, framesize-28(sp)
135 sw s4, framesize-32(sp)
136 sw s3, framesize-36(sp)
137 sw s2, framesize-40(sp)
138 sw s1, framesize-44(sp)
139 sw s0, framesize-48(sp)
143 /* Clear unsaved boxed descriptor regs */
149 /* Load the rest of the LISP state. */
150 lw reg_BSP, current_binding_stack_pointer
151 lw reg_CSP, current_control_stack_pointer
152 lw reg_OCFP, current_control_frame_pointer
154 END_PSEUDO_ATOMIC(reg_NL4)
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_INSTS_OFFSET
175 /* Mark us as in Lisp land. */
176 sw zero, foreign_function_call_active
177 lw reg_CARDBASE, gc_card_mark
179 /* Jump into lisp land. */
184 lra: .word RETURN_PC_WIDETAG
186 /* Multiple value return spot, clear stack. */
187 move reg_CSP, reg_OCFP
190 /* Single value return spot. */
192 /* Nested lisp -> C calls may have clobbered gp. */
193 lw $gp, framesize-16(sp)
195 /* Mark us as in C land. */
196 sw reg_CSP, foreign_function_call_active
200 /* Save LISP state. */
201 sw reg_BSP, current_binding_stack_pointer
202 sw reg_CSP, current_control_stack_pointer
203 sw reg_CFP, current_control_frame_pointer
205 END_PSEUDO_ATOMIC(reg_NL4)
207 /* Pass one return value back to C land. For a 64bit value, we may
208 need to clobber v1 aka reg_NL4. */
209 move v0, reg_A0 # reg_CFUNC
210 move v1, reg_A1 # reg_NL4
213 lw ra, framesize-8(sp)
214 lw s8, framesize-12(sp)
215 lw s7, framesize-20(sp)
216 lw s6, framesize-24(sp)
217 lw s5, framesize-28(sp)
218 lw s4, framesize-32(sp)
219 lw s3, framesize-36(sp)
220 lw s2, framesize-40(sp)
221 lw s1, framesize-44(sp)
222 lw s0, framesize-48(sp)
224 /* Restore C stack. */
233 * Transfering control from Lisp into C
235 NESTED(call_into_c, 0, ra)
237 /* Setup the lisp stack. */
238 move reg_OCFP, reg_CFP
239 move reg_CFP, reg_CSP
240 addu reg_CSP, reg_CFP, 32
242 /* Mark us as in C land. */
243 sw reg_CSP, foreign_function_call_active
247 /* Convert the return address to an offset and save it on the stack. */
248 subu reg_NFP, reg_LIP, reg_CODE
249 addu reg_NFP, OTHER_POINTER_LOWTAG
250 sw reg_OCFP, (reg_CFP)
251 sw reg_NFP, 4(reg_CFP)
252 sw reg_CODE, 8(reg_CFP)
253 sw $gp, 12(reg_CFP) // should this be saved? on the control stack?
255 /* Save LISP state. */
256 sw reg_BSP, current_binding_stack_pointer
257 sw reg_CSP, current_control_stack_pointer
258 sw reg_CFP, current_control_frame_pointer
260 /* from the ABI: "When calling position independent functions
261 $25 must cotain the address of the called function." */
262 lw $25, (reg_CFUNC) /* linkage-table indirection */
264 END_PSEUDO_ATOMIC(reg_NL4)
266 /* Into C land we go. */
271 /* Pass 64bit return value to lisp land. */
272 move reg_NL0, v0 # reg_CFUNC
273 move reg_NL1, v1 # reg_NL4
276 * Clear boxed descriptor registers before allowing an interrupt.
277 * We can't rely on C saving some of those registers, they might
278 * have been GCed in the meanwhile.
287 li reg_LEXENV, 0 # t7
289 * reg_NFP and reg_OCFP are pointing to fixed locations and are
300 lw reg_BSP, current_binding_stack_pointer
303 lw reg_CODE, 8(reg_CFP)
304 /* Setup the return address */
305 subu reg_LIP, reg_NFP, OTHER_POINTER_LOWTAG
306 addu reg_LIP, reg_CODE
308 END_PSEUDO_ATOMIC(reg_NL4)
310 /* Reset the lisp stack. */
311 /* Note: OCFP and CFP are in saved regs. */
312 move reg_CSP, reg_CFP
313 move reg_CFP, reg_OCFP
315 /* Mark us as in Lisp land. */
316 sw zero, foreign_function_call_active
317 lw reg_CARDBASE, gc_card_mark
319 /* Return to LISP. */
324 * Function-end breakpoint magic. This is truely magic, the code is
325 * copied and has to be relocatable. It also needs a properly aligned
326 * header tag after the fun_end_breakpoint_guts symbol.
330 * For an explanation of the magic involved in function-end
331 * breakpoints, see the implementation in ppc-assem.S.
334 .align 3 /* minimum alignment for a lisp object */
335 LEAF(fun_end_breakpoint_guts)
337 .word (((CODE_SIZE+1)&~1)<<N_WIDETAG_BITS)|RETURN_PC_WIDETAG
338 b multiple_value_return
342 /* single value return */
344 move reg_OCFP, reg_CSP
353 multiple_value_return:
355 FEXPORT(fun_end_breakpoint_trap)
357 b multiple_value_return
358 break 0x0, trap_FunEndBreakpoint
360 EXPORT(fun_end_breakpoint_end)
361 END(fun_end_breakpoint_guts)
364 .align 3 /* minimum alignment for a lisp object */
365 LEAF(do_pending_interrupt)
366 break 0x0, trap_PendingInterrupt
368 END(do_pending_interrupt)