1 #define LANGUAGE_ASSEMBLY
8 #define FUNCDEF(x) .text ; \
12 #define GFUNCDEF(x) .globl x ; \
15 #define SET_SIZE(x) .size x,.-x
17 /* Load a register from a global, using the register as an intermediary */
18 /* The register will be a fixnum for one instruction, so this is gc-safe */
20 #define load(reg,global) \
21 lis reg,global@ha; lwz reg,global@l(reg)
22 #define store(reg,temp,global) \
23 lis temp,global@ha; stw reg,global@l(temp)
25 #define FIRST_SAVE_FPR 14 /* lowest-numbered non-volatile FPR */
26 #define FIRST_SAVE_GPR 14 /* lowest-numbered non-volatile GPR */
27 #define NFPR_SAVE_BYTES(n) ((32-(n))*8)
28 #define NGPR_SAVE_BYTES(n) ((32-(~1&((n)+1)))*4)
29 #define FRAME_ARG_BYTES(n) (((((n)+2)*4)+15)&~15)
31 #define FRAME_SIZE(first_g,first_f,out_arg_words,savecr) \
32 (NFPR_SAVE_BYTES(first_f)+ NGPR_SAVE_BYTES(first_g)+ FRAME_ARG_BYTES(out_arg_words+savecr))
33 #define SAVE_FPR(n) stfd n,-8*(32-(n))(11)
34 #define SAVE_GPR(n) stw n,-4*(32-(n))(11)
35 #define FULL_FRAME_SIZE FRAME_SIZE(FIRST_SAVE_GPR,FIRST_SAVE_FPR,0,1)
37 #define RESTORE_FPR(n) lfd n,-8*(32-(n))(11)
38 #define RESTORE_GPR(n) lwz n,-4*(32-(n))(11)
39 #define C_FULL_PROLOG \
43 stwu 1,-FULL_FRAME_SIZE(1) ; \
62 la 11,-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(11) ; \
83 #define C_FULL_EPILOG \
84 la 11,FULL_FRAME_SIZE-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(1) ; \
103 la 11,NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(11) ; \
132 * Function to transfer control into lisp. The lisp object to invoke is
133 * passed as the first argument, which puts it in NL0
136 GFUNCDEF(call_into_lisp)
140 /* store(reg_POLL,11,saver2) */
141 /* Initialize tagged registers */
158 ori reg_NULL,reg_NULL,NIL@l
160 /* Turn on pseudo-atomic */
164 store(reg_ZERO,reg_NL4,foreign_function_call_active)
165 load(reg_NL4,dynamic_space_free_pointer)
166 add reg_ALLOC,reg_ALLOC,reg_NL4
167 load(reg_BSP,current_binding_stack_pointer)
168 load(reg_CSP,current_control_stack_pointer)
169 load(reg_OCFP,current_control_frame_pointer)
171 /* No longer atomic, and check for interrupt */
172 add reg_ALLOC,reg_ALLOC,reg_NL3
175 /* Pass in the arguments */
178 mr reg_LEXENV,reg_NL0
179 lwz reg_A0,0(reg_CFP)
180 lwz reg_A1,4(reg_CFP)
181 lwz reg_A2,8(reg_CFP)
182 lwz reg_A3,12(reg_CFP)
186 addi reg_LRA,reg_LRA,lra@l
187 addi reg_LRA,reg_LRA,OTHER_POINTER_LOWTAG
189 /* Function is an indirect closure */
190 lwz reg_CODE,SIMPLE_FUN_SELF_OFFSET(reg_LEXENV)
191 addi reg_LIP,reg_CODE,6*4-FUN_POINTER_LOWTAG
193 slwi reg_NARGS,reg_NL2,2
198 .long RETURN_PC_HEADER_WIDETAG
200 /* Blow off any extra values. */
204 /* Return the one value. */
208 /* Turn on pseudo-atomic */
210 la reg_ALLOC,4(reg_ALLOC)
212 /* Store lisp state */
213 clrrwi reg_NL1,reg_ALLOC,3
214 store(reg_NL1,reg_NL2,dynamic_space_free_pointer)
215 /* store(reg_POLL,reg_NL2,poll_flag) */
216 /* load(reg_NL2,current_thread) */
217 store(reg_BSP,reg_NL2,current_binding_stack_pointer)
218 store(reg_CSP,reg_NL2,current_control_stack_pointer)
219 store(reg_CFP,reg_NL2,current_control_frame_pointer)
220 /* load(reg_POLL,saver2) */
222 /* No longer in Lisp. */
223 store(reg_NL1,reg_NL2,foreign_function_call_active)
225 /* Check for interrupt */
226 add reg_ALLOC,reg_ALLOC,reg_NL3
234 SET_SIZE(call_into_lisp)
237 GFUNCDEF(call_into_c)
238 /* We're kind of low on unboxed, non-dedicated registers here:
239 most of the unboxed registers may have outgoing C args in them.
240 CFUNC is going to have to go in the CTR in a moment, anyway
241 so we'll free it up soon. reg_NFP is preserved by lisp if it
242 has a meaningful value in it, so we can use it. reg_NARGS is
243 free when it's not holding a copy of the "real" reg_NL3, which
244 gets tied up by the pseudo-atomic mechanism */
247 /* Build a lisp stack frame */
250 la reg_CSP,32(reg_CSP)
251 stw reg_OCFP,0(reg_CFP)
252 stw reg_CODE,8(reg_CFP)
253 /* The pseudo-atomic mechanism wants to use reg_NL3, but that
254 may be an outgoing C argument. Copy reg_NL3 to something that's
255 unboxed and -not- one of the C argument registers */
258 /* Turn on pseudo-atomic */
260 la reg_ALLOC,4(reg_ALLOC)
262 /* Convert the return address to an offset and save it on the stack. */
263 sub reg_NFP,reg_LIP,reg_CODE
264 la reg_NFP,OTHER_POINTER_LOWTAG(reg_NFP)
265 stw reg_NFP,4(reg_CFP)
267 /* Store Lisp state */
268 clrrwi reg_NFP,reg_ALLOC,3
269 store(reg_NFP,reg_CFUNC,dynamic_space_free_pointer)
270 /* load(reg_CFUNC,current_thread) */
272 store(reg_BSP,reg_CFUNC,current_binding_stack_pointer)
273 store(reg_CSP,reg_CFUNC,current_control_stack_pointer)
274 store(reg_CFP,reg_CFUNC,current_control_frame_pointer)
276 /* No longer in Lisp */
277 store(reg_CSP,reg_CFUNC,foreign_function_call_active)
278 /* load(reg_POLL,saver2) */
279 /* Disable pseudo-atomic; check pending interrupt */
280 add reg_ALLOC,reg_ALLOC,reg_NL3
287 /* Re-establish NIL */
289 ori reg_NULL,reg_NULL,NIL@l
293 /* If we GC'ed during the FF code (as the result of a callback ?)
294 the tagged lisp registers may now contain garbage (since the
295 registers were saved by C and not seen by the GC.) Put something
296 harmless in all such registers before allowing an interrupt */
300 /* reg_OCFP was pointing to a control stack frame & was preserved by C */
315 /* No long in foreign function call. */
316 store(reg_ZERO,reg_NL2,foreign_function_call_active)
318 /* The free pointer may have moved */
319 load(reg_NL4,dynamic_space_free_pointer)
320 add reg_ALLOC,reg_ALLOC,reg_NL4
322 /* The BSP wasn't preserved by C, so load it */
323 load(reg_BSP,current_binding_stack_pointer)
325 /* Other lisp stack/frame pointers were preserved by C.
326 I can't imagine why they'd have moved */
328 /* Get the return address back. */
329 lwz reg_LIP,4(reg_CFP)
330 lwz reg_CODE,8(reg_CFP)
331 add reg_LIP,reg_CODE,reg_LIP
332 la reg_LIP,-OTHER_POINTER_LOWTAG(reg_LIP)
334 /* No longer atomic */
335 add reg_ALLOC,reg_ALLOC,reg_NL3
339 /* Reset the lisp stack. */
343 /* And back into Lisp. */
346 SET_SIZE(call_into_c)
348 GFUNCDEF(xundefined_tramp)
349 .globl undefined_tramp
350 .byte 0,0,0,SIMPLE_FUN_HEADER_WIDETAG /* type_FunctionHeader */
355 .long undefined_tramp
360 twllei reg_ZERO,trap_Cerror
362 .byte UNDEFINED_FUN_ERROR
363 .byte 254, 140, 2 /* 140? sparc says sc_descriptorReg */
365 1: lwz reg_CODE,FDEFN_RAW_ADDR_OFFSET(reg_FDEFN)
366 la reg_LIP,SIMPLE_FUN_CODE_OFFSET(reg_CODE)
370 SET_SIZE(xundefined_tramp)
372 GFUNCDEF(xclosure_tramp)
374 .byte 0,0,0,SIMPLE_FUN_HEADER_WIDETAG
383 lwz reg_LEXENV,FDEFN_FUN_OFFSET(reg_FDEFN)
384 lwz reg_CODE,CLOSURE_FUN_OFFSET(reg_LEXENV)
385 la reg_LIP,SIMPLE_FUN_CODE_OFFSET(reg_CODE)
389 SET_SIZE(xclosure_tramp)
391 GFUNCDEF(fun_end_breakpoint_trap)
393 SET_SIZE(fun_end_breakpoint_trap)
395 GFUNCDEF(fun_end_breakpoint)
397 SET_SIZE(fun_end_breakpoint)
399 GFUNCDEF(fun_end_breakpoint_guts)
401 SET_SIZE(fun_end_breakpoint_guts)
403 GFUNCDEF(fun_end_breakpoint_end)
405 SET_SIZE(fun_end_breakpoint_end)
408 GFUNCDEF(ppc_flush_cache_line)
415 SET_SIZE(ppc_flush_cache_line)