1 #define LANGUAGE_ASSEMBLY
7 #include "genesis/simple-fun.h"
8 #include "genesis/fdefn.h"
9 #include "genesis/closure.h"
10 #include "genesis/static-symbols.h"
12 #ifdef LISP_FEATURE_DARWIN
13 #define CSYMBOL(x) _ ## x
18 #if defined LISP_FEATURE_DARWIN
19 #define FUNCDEF(x) .text @ \
23 #define GFUNCDEF(x) .globl _/**/x @ \
26 #define FUNCDEF(x) .text ; \
31 #define GFUNCDEF(x) .globl x ; \
35 #if defined LISP_FEATURE_DARWIN
38 #define SET_SIZE(x) .size x,.-x
41 /* Load a register from a global, using the register as an intermediary */
42 /* The register will be a fixnum for one instruction, so this is gc-safe */
44 #if defined LISP_FEATURE_DARWIN
45 #define load(reg,global) \
46 lis reg,ha16(global) @ \
47 lwz reg,lo16(global)(reg) ; Comment
48 #define store(reg,temp,global) \
49 lis temp,ha16(global) @\
50 stw reg,lo16(global)(temp) ; Comment
52 #define load(reg,global) \
53 lis reg,global@ha; lwz reg,global@l(reg)
54 #define store(reg,temp,global) \
55 lis temp,global@ha; stw reg,global@l(temp)
58 #define FIRST_SAVE_FPR 14 /* lowest-numbered non-volatile FPR */
59 #ifdef LISP_FEATURE_DARWIN
60 #define FIRST_SAVE_GPR 13 /* lowest-numbered non-volatile GPR */
61 #define NGPR_SAVE_BYTES(n) ((32-(n))*4)
62 #define FRAME_ARG_BYTES(n) (((((n)+6)*4)+15)&~15)
64 #define FIRST_SAVE_GPR 14 /* lowest-numbered non-volatile GPR */
65 #define NGPR_SAVE_BYTES(n) ((32-(~1&((n)+1)))*4)
66 #define FRAME_ARG_BYTES(n) (((((n)+2)*4)+15)&~15)
68 #define NFPR_SAVE_BYTES(n) ((32-(n))*8)
70 #ifdef LISP_FEATURE_DARWIN
71 #define FRAME_SIZE(first_g,first_f,out_arg_words,savecr) \
72 (NFPR_SAVE_BYTES(first_f)+ NGPR_SAVE_BYTES(first_g)+ FRAME_ARG_BYTES(out_arg_words))
73 #define SAVE_FPR(n) stfd f##n,-8*(32- n)(r11)
74 #define SAVE_GPR(n) stw r##n,-4*(32- n)(r11)
75 #define FULL_FRAME_SIZE (FRAME_SIZE(FIRST_SAVE_GPR,FIRST_SAVE_FPR,8,1)+15&~15)
76 #define RESTORE_FPR(n) lfd f##n,-8*(32- n)(r11)
77 #define RESTORE_GPR(n) lwz r##n,-4*(32- n)(r11)
79 #define FRAME_SIZE(first_g,first_f,out_arg_words,savecr) \
80 (NFPR_SAVE_BYTES(first_f)+ NGPR_SAVE_BYTES(first_g)+ FRAME_ARG_BYTES(out_arg_words+savecr))
81 #define SAVE_FPR(n) stfd n,-8*(32-(n))(11)
82 #define SAVE_GPR(n) stw n,-4*(32-(n))(11)
83 #define FULL_FRAME_SIZE FRAME_SIZE(FIRST_SAVE_GPR,FIRST_SAVE_FPR,0,1)
85 #define RESTORE_FPR(n) lfd n,-8*(32-(n))(11)
86 #define RESTORE_GPR(n) lwz n,-4*(32-(n))(11)
89 #ifdef LISP_FEATURE_DARWIN
90 #define C_FULL_PROLOG \
94 stw REG(0),4(REG(1)) @ \
96 stw REG(0),8(REG(1)) @ \
98 stwu REG(1),-FULL_FRAME_SIZE(REG(1)) @ \
117 la REG(11),-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(11)) @ \
139 #define C_FULL_EPILOG \
140 la REG(11),FULL_FRAME_SIZE-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(1)) @ \
160 la REG(11),NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(11)) @ \
179 lwz REG(1),0(REG(1)) @ \
180 lwz REG(0),4(REG(1)) @ \
182 lwz REG(0),8(REG(1)) @ \
187 #define C_FULL_PROLOG \
191 stwu 1,-FULL_FRAME_SIZE(1) ; \
210 la 11,-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(11) ; \
232 #define C_FULL_EPILOG \
235 la 11,FULL_FRAME_SIZE-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(1) ; \
254 la 11,NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(11) ; \
282 * Function to transfer control into lisp. The lisp object to invoke is
283 * passed as the first argument, which puts it in NL0
286 GFUNCDEF(call_into_lisp)
288 /* store(reg_POLL,11,saver2) */
289 /* Initialize tagged registers */
305 #ifdef LISP_FEATURE_DARWIN
306 lis reg_NULL,hi16(NIL)
307 ori reg_NULL,reg_NULL,lo16(NIL)
310 ori reg_NULL,reg_NULL,NIL@l
312 /* Turn on pseudo-atomic */
315 store(reg_ZERO,reg_NL4,CSYMBOL(foreign_function_call_active))
316 load(reg_NL4,CSYMBOL(dynamic_space_free_pointer))
317 add reg_ALLOC,reg_ALLOC,reg_NL4
318 load(reg_BSP,CSYMBOL(current_binding_stack_pointer))
319 load(reg_CSP,CSYMBOL(current_control_stack_pointer))
320 load(reg_OCFP,CSYMBOL(current_control_frame_pointer))
322 /* No longer atomic, and check for interrupt */
323 andi. reg_NL3, reg_ALLOC, 1
324 subi reg_ALLOC,reg_ALLOC,4
327 /* Pass in the arguments */
330 mr reg_LEXENV,reg_NL0
331 lwz reg_A0,0(reg_CFP)
332 lwz reg_A1,4(reg_CFP)
333 lwz reg_A2,8(reg_CFP)
334 lwz reg_A3,12(reg_CFP)
337 #ifdef LISP_FEATURE_DARWIN
338 lis reg_LRA,ha16(lra)
339 addi reg_LRA,reg_LRA,lo16(lra)
342 ori reg_LRA,reg_LRA,lra@l
344 addi reg_LRA,reg_LRA,OTHER_POINTER_LOWTAG
346 /* Function is an indirect closure */
347 lwz reg_CODE,SIMPLE_FUN_SELF_OFFSET(reg_LEXENV)
348 addi reg_LIP,reg_CODE,6*4-FUN_POINTER_LOWTAG
350 slwi reg_NARGS,reg_NL2,2
355 .long RETURN_PC_HEADER_WIDETAG
357 /* Blow off any extra values. */
361 /* Return the one value. */
365 /* Turn on pseudo-atomic */
366 la reg_ALLOC,4(reg_ALLOC)
368 /* Store lisp state */
369 clrrwi reg_NL1,reg_ALLOC,3
370 store(reg_NL1,reg_NL2,CSYMBOL(dynamic_space_free_pointer))
371 /* store(reg_POLL,reg_NL2,poll_flag) */
372 /* load(reg_NL2,current_thread) */
373 store(reg_BSP,reg_NL2,CSYMBOL(current_binding_stack_pointer))
374 store(reg_CSP,reg_NL2,CSYMBOL(current_control_stack_pointer))
375 store(reg_CFP,reg_NL2,CSYMBOL(current_control_frame_pointer))
376 /* load(reg_POLL,saver2) */
378 /* No longer in Lisp. */
379 store(reg_NL1,reg_NL2,CSYMBOL(foreign_function_call_active))
381 /* Check for interrupt */
382 andi. reg_NL3, reg_ALLOC, 1
383 subi reg_ALLOC, reg_ALLOC, 4
389 SET_SIZE(call_into_lisp)
392 GFUNCDEF(call_into_c)
393 /* We're kind of low on unboxed, non-dedicated registers here:
394 most of the unboxed registers may have outgoing C args in them.
395 CFUNC is going to have to go in the CTR in a moment, anyway
396 so we'll free it up soon. reg_NFP is preserved by lisp if it
397 has a meaningful value in it, so we can use it. reg_NARGS is
398 free when it's not holding a copy of the "real" reg_NL3, which
399 gets tied up by the pseudo-atomic mechanism */
402 /* Build a lisp stack frame */
405 la reg_CSP,32(reg_CSP)
406 stw reg_OCFP,0(reg_CFP)
407 stw reg_CODE,8(reg_CFP)
408 /* The pseudo-atomic mechanism wants to use reg_NL3, but that
409 may be an outgoing C argument. Copy reg_NL3 to something that's
410 unboxed and -not- one of the C argument registers */
413 /* Turn on pseudo-atomic */
414 la reg_ALLOC,4(reg_ALLOC)
416 /* Convert the return address to an offset and save it on the stack. */
417 sub reg_NFP,reg_LIP,reg_CODE
418 la reg_NFP,OTHER_POINTER_LOWTAG(reg_NFP)
419 stw reg_NFP,4(reg_CFP)
421 /* Store Lisp state */
422 clrrwi reg_NFP,reg_ALLOC,3
423 store(reg_NFP,reg_CFUNC,CSYMBOL(dynamic_space_free_pointer))
424 /* load(reg_CFUNC,current_thread) */
426 store(reg_BSP,reg_CFUNC,CSYMBOL(current_binding_stack_pointer))
427 store(reg_CSP,reg_CFUNC,CSYMBOL(current_control_stack_pointer))
428 store(reg_CFP,reg_CFUNC,CSYMBOL(current_control_frame_pointer))
430 /* No longer in Lisp */
431 store(reg_CSP,reg_CFUNC,CSYMBOL(foreign_function_call_active))
432 /* load(reg_POLL,saver2) */
433 /* Disable pseudo-atomic; check pending interrupt */
434 andi. reg_NL3, reg_ALLOC, 1
435 subi reg_ALLOC, reg_ALLOC, 4
440 #ifdef LISP_FEATURE_DARWIN
441 /* PowerOpen (i.e. OS X) requires the callee address in r12
442 (a.k.a. CFUNC), so move it back there, too. */
448 /* Re-establish NIL */
449 #ifdef LISP_FEATURE_DARWIN
450 lis reg_NULL,hi16(NIL)
451 ori reg_NULL,reg_NULL,lo16(NIL)
454 ori reg_NULL,reg_NULL,NIL@l
459 /* If we GC'ed during the FF code (as the result of a callback ?)
460 the tagged lisp registers may now contain garbage (since the
461 registers were saved by C and not seen by the GC.) Put something
462 harmless in all such registers before allowing an interrupt */
466 /* reg_OCFP was pointing to a control stack frame & was preserved by C */
481 /* No long in foreign function call. */
482 store(reg_ZERO,reg_NL2,CSYMBOL(foreign_function_call_active))
484 /* The free pointer may have moved */
485 load(reg_NL4,CSYMBOL(dynamic_space_free_pointer))
486 add reg_ALLOC,reg_ALLOC,reg_NL4
488 /* The BSP wasn't preserved by C, so load it */
489 load(reg_BSP,CSYMBOL(current_binding_stack_pointer))
491 /* Other lisp stack/frame pointers were preserved by C.
492 I can't imagine why they'd have moved */
494 /* Get the return address back. */
495 lwz reg_LIP,4(reg_CFP)
496 lwz reg_CODE,8(reg_CFP)
497 add reg_LIP,reg_CODE,reg_LIP
498 la reg_LIP,-OTHER_POINTER_LOWTAG(reg_LIP)
500 /* No longer atomic */
501 andi. reg_NL3, reg_ALLOC, 1
502 subi reg_ALLOC, reg_ALLOC, 4
507 /* Reset the lisp stack. */
511 /* And back into Lisp. */
514 SET_SIZE(call_into_c)
516 GFUNCDEF(xundefined_tramp)
517 .globl CSYMBOL(undefined_tramp)
518 .byte 0,0,0,SIMPLE_FUN_HEADER_WIDETAG
520 CSYMBOL(undefined_tramp):
522 .long CSYMBOL(undefined_tramp)
526 twllei reg_ZERO,trap_Cerror
528 .byte UNDEFINED_FUN_ERROR
529 .byte 254, sc_DescriptorReg+0x40, 1 /* 140? sparc says sc_descriptorReg */
531 1: lwz reg_CODE,FDEFN_RAW_ADDR_OFFSET(reg_FDEFN)
532 la reg_LIP,SIMPLE_FUN_CODE_OFFSET(reg_CODE)
538 SET_SIZE(xundefined_tramp)
540 GFUNCDEF(xclosure_tramp)
541 .globl CSYMBOL(closure_tramp)
542 .byte 0,0,0,SIMPLE_FUN_HEADER_WIDETAG
544 CSYMBOL(closure_tramp):
546 .long CSYMBOL(closure_tramp)
551 lwz reg_LEXENV,FDEFN_FUN_OFFSET(reg_FDEFN)
552 lwz reg_CODE,CLOSURE_FUN_OFFSET(reg_LEXENV)
553 la reg_LIP,SIMPLE_FUN_CODE_OFFSET(reg_CODE)
557 SET_SIZE(xclosure_tramp)
559 GFUNCDEF(fun_end_breakpoint_trap)
561 SET_SIZE(fun_end_breakpoint_trap)
563 GFUNCDEF(fun_end_breakpoint)
565 SET_SIZE(fun_end_breakpoint)
567 GFUNCDEF(fun_end_breakpoint_guts)
569 SET_SIZE(fun_end_breakpoint_guts)
571 GFUNCDEF(fun_end_breakpoint_end)
573 SET_SIZE(fun_end_breakpoint_end)
576 GFUNCDEF(ppc_flush_cache_line)
583 SET_SIZE(ppc_flush_cache_line)
585 GFUNCDEF(do_pending_interrupt)
586 twllei reg_ZERO, trap_PendingInterrupt
588 /* King Nato's branch has a nop here. Do we need this? */
589 SET_SIZE(do_pending_interrupt)
591 #if defined LISP_FEATURE_GENCGC
594 stfd FREG(1), 0(REG(3))
595 stfd FREG(2), 8(REG(3))
596 stfd FREG(3), 16(REG(3))
597 stfd FREG(4), 24(REG(3))
598 stfd FREG(5), 32(REG(3))
599 stfd FREG(6), 40(REG(3))
600 stfd FREG(7), 48(REG(3))
601 stfd FREG(8), 56(REG(3))
602 stfd FREG(9), 64(REG(3))
603 stfd FREG(10), 72(REG(3))
604 stfd FREG(11), 80(REG(3))
605 stfd FREG(12), 88(REG(3))
606 stfd FREG(13), 96(REG(3))
607 stfd FREG(14), 104(REG(3))
608 stfd FREG(15), 112(REG(3))
609 stfd FREG(16), 120(REG(3))
610 stfd FREG(17), 128(REG(3))
611 stfd FREG(18), 136(REG(3))
612 stfd FREG(19), 144(REG(3))
613 stfd FREG(20), 152(REG(3))
614 stfd FREG(21), 160(REG(3))
615 stfd FREG(22), 168(REG(3))
616 stfd FREG(23), 176(REG(3))
617 stfd FREG(24), 184(REG(3))
618 stfd FREG(25), 192(REG(3))
619 stfd FREG(26), 200(REG(3))
620 stfd FREG(27), 208(REG(3))
621 stfd FREG(28), 216(REG(3))
622 stfd FREG(29), 224(REG(3))
623 stfd FREG(30), 232(REG(3))
624 stfd FREG(31), 240(REG(3))
628 GFUNCDEF(fpu_restore)
629 lfd FREG(1), 0(REG(3))
630 lfd FREG(2), 8(REG(3))
631 lfd FREG(3), 16(REG(3))
632 lfd FREG(4), 24(REG(3))
633 lfd FREG(5), 32(REG(3))
634 lfd FREG(6), 40(REG(3))
635 lfd FREG(7), 48(REG(3))
636 lfd FREG(8), 56(REG(3))
637 lfd FREG(9), 64(REG(3))
638 lfd FREG(10), 72(REG(3))
639 lfd FREG(11), 80(REG(3))
640 lfd FREG(12), 88(REG(3))
641 lfd FREG(13), 96(REG(3))
642 lfd FREG(14), 104(REG(3))
643 lfd FREG(15), 112(REG(3))
644 lfd FREG(16), 120(REG(3))
645 lfd FREG(17), 128(REG(3))
646 lfd FREG(18), 136(REG(3))
647 lfd FREG(19), 144(REG(3))
648 lfd FREG(20), 152(REG(3))
649 lfd FREG(21), 160(REG(3))
650 lfd FREG(22), 168(REG(3))
651 lfd FREG(23), 176(REG(3))
652 lfd FREG(24), 184(REG(3))
653 lfd FREG(25), 192(REG(3))
654 lfd FREG(26), 200(REG(3))
655 lfd FREG(27), 208(REG(3))
656 lfd FREG(28), 216(REG(3))
657 lfd FREG(29), 224(REG(3))
658 lfd FREG(30), 232(REG(3))
659 lfd FREG(31), 240(REG(3))
661 SET_SIZE(fpu_restore)