1 #define LANGUAGE_ASSEMBLY
7 #include "genesis/simple-fun.h"
8 #include "genesis/fdefn.h"
9 #include "genesis/closure.h"
10 #include "genesis/funcallable-instance.h"
11 #include "genesis/static-symbols.h"
13 #ifdef LISP_FEATURE_DARWIN
14 #define CSYMBOL(x) _ ## x
19 #if defined LISP_FEATURE_DARWIN
20 #define FUNCDEF(x) .text @ \
24 #define GFUNCDEF(x) .globl _/**/x @ \
27 #define FUNCDEF(x) .text ; \
32 #define GFUNCDEF(x) .globl x ; \
36 #if defined LISP_FEATURE_DARWIN
39 #define SET_SIZE(x) .size x,.-x
42 /* Load a register from a global, using the register as an intermediary */
43 /* The register will be a fixnum for one instruction, so this is gc-safe */
45 #if defined LISP_FEATURE_DARWIN
46 #define load(reg,global) \
47 lis reg,ha16(global) @ \
48 lwz reg,lo16(global)(reg) ; Comment
49 #define store(reg,temp,global) \
50 lis temp,ha16(global) @\
51 stw reg,lo16(global)(temp) ; Comment
53 #define load(reg,global) \
54 lis reg,global@ha; lwz reg,global@l(reg)
55 #define store(reg,temp,global) \
56 lis temp,global@ha; stw reg,global@l(temp)
59 #define FIRST_SAVE_FPR 14 /* lowest-numbered non-volatile FPR */
60 #ifdef LISP_FEATURE_DARWIN
61 #define FIRST_SAVE_GPR 13 /* lowest-numbered non-volatile GPR */
62 #define NGPR_SAVE_BYTES(n) ((32-(n))*4)
63 #define FRAME_ARG_BYTES(n) (((((n)+6)*4)+15)&~15)
65 #define FIRST_SAVE_GPR 14 /* lowest-numbered non-volatile GPR */
66 #define NGPR_SAVE_BYTES(n) ((32-(~1&((n)+1)))*4)
67 #define FRAME_ARG_BYTES(n) (((((n)+2)*4)+15)&~15)
69 #define NFPR_SAVE_BYTES(n) ((32-(n))*8)
71 #ifdef LISP_FEATURE_DARWIN
72 #define FRAME_SIZE(first_g,first_f,out_arg_words,savecr) \
73 (NFPR_SAVE_BYTES(first_f)+ NGPR_SAVE_BYTES(first_g)+ FRAME_ARG_BYTES(out_arg_words))
74 #define SAVE_FPR(n) stfd f##n,-8*(32- n)(r11)
75 #define SAVE_GPR(n) stw r##n,-4*(32- n)(r11)
76 #define FULL_FRAME_SIZE (FRAME_SIZE(FIRST_SAVE_GPR,FIRST_SAVE_FPR,8,1)+15&~15)
77 #define RESTORE_FPR(n) lfd f##n,-8*(32- n)(r11)
78 #define RESTORE_GPR(n) lwz r##n,-4*(32- n)(r11)
80 #define FRAME_SIZE(first_g,first_f,out_arg_words,savecr) \
81 (NFPR_SAVE_BYTES(first_f)+ NGPR_SAVE_BYTES(first_g)+ FRAME_ARG_BYTES(out_arg_words+savecr))
82 #define SAVE_FPR(n) stfd n,-8*(32-(n))(11)
83 #define SAVE_GPR(n) stw n,-4*(32-(n))(11)
84 #define FULL_FRAME_SIZE FRAME_SIZE(FIRST_SAVE_GPR,FIRST_SAVE_FPR,0,1)
86 #define RESTORE_FPR(n) lfd n,-8*(32-(n))(11)
87 #define RESTORE_GPR(n) lwz n,-4*(32-(n))(11)
90 #ifdef LISP_FEATURE_DARWIN
91 #define C_FULL_PROLOG \
95 stw REG(0),4(REG(1)) @ \
97 stw REG(0),8(REG(1)) @ \
99 stwu REG(1),-FULL_FRAME_SIZE(REG(1)) @ \
118 la REG(11),-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(11)) @ \
140 #define C_FULL_EPILOG \
141 la REG(11),FULL_FRAME_SIZE-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(1)) @ \
161 la REG(11),NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(11)) @ \
180 lwz REG(1),0(REG(1)) @ \
181 lwz REG(0),4(REG(1)) @ \
183 lwz REG(0),8(REG(1)) @ \
188 #define C_FULL_PROLOG \
192 stwu 1,-FULL_FRAME_SIZE(1) ; \
211 la 11,-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(11) ; \
233 #define C_FULL_EPILOG \
236 la 11,FULL_FRAME_SIZE-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(1) ; \
255 la 11,NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(11) ; \
283 * Function to transfer control into lisp. The lisp object to invoke is
284 * passed as the first argument, which puts it in NL0
287 GFUNCDEF(call_into_lisp)
289 /* store(reg_POLL,11,saver2) */
290 /* Initialize tagged registers */
306 #ifdef LISP_FEATURE_DARWIN
307 lis reg_NULL,hi16(NIL)
308 ori reg_NULL,reg_NULL,lo16(NIL)
311 ori reg_NULL,reg_NULL,NIL@l
313 /* Turn on pseudo-atomic */
316 store(reg_ZERO,reg_NL4,CSYMBOL(foreign_function_call_active))
317 load(reg_NL4,CSYMBOL(dynamic_space_free_pointer))
318 add reg_ALLOC,reg_ALLOC,reg_NL4
319 load(reg_BSP,CSYMBOL(current_binding_stack_pointer))
320 load(reg_CSP,CSYMBOL(current_control_stack_pointer))
321 load(reg_OCFP,CSYMBOL(current_control_frame_pointer))
323 /* No longer atomic, and check for interrupt */
324 andi. reg_NL3, reg_ALLOC, 1
325 subi reg_ALLOC,reg_ALLOC,4
328 /* Pass in the arguments */
331 mr reg_LEXENV,reg_NL0
332 lwz reg_A0,0(reg_CFP)
333 lwz reg_A1,4(reg_CFP)
334 lwz reg_A2,8(reg_CFP)
335 lwz reg_A3,12(reg_CFP)
338 #ifdef LISP_FEATURE_DARWIN
339 lis reg_LRA,ha16(lra)
340 addi reg_LRA,reg_LRA,lo16(lra)
343 ori reg_LRA,reg_LRA,lra@l
345 addi reg_LRA,reg_LRA,OTHER_POINTER_LOWTAG
347 /* Function is an indirect closure */
348 lwz reg_CODE,SIMPLE_FUN_SELF_OFFSET(reg_LEXENV)
349 addi reg_LIP,reg_CODE,SIMPLE_FUN_CODE_OFFSET
351 slwi reg_NARGS,reg_NL2,2
356 .long RETURN_PC_HEADER_WIDETAG
358 /* Blow off any extra values. */
362 /* Return the one value. */
366 /* Turn on pseudo-atomic */
367 la reg_ALLOC,4(reg_ALLOC)
369 /* Store lisp state */
370 clrrwi reg_NL1,reg_ALLOC,3
371 store(reg_NL1,reg_NL2,CSYMBOL(dynamic_space_free_pointer))
372 /* store(reg_POLL,reg_NL2,poll_flag) */
373 /* load(reg_NL2,current_thread) */
374 store(reg_BSP,reg_NL2,CSYMBOL(current_binding_stack_pointer))
375 store(reg_CSP,reg_NL2,CSYMBOL(current_control_stack_pointer))
376 store(reg_CFP,reg_NL2,CSYMBOL(current_control_frame_pointer))
377 /* load(reg_POLL,saver2) */
379 /* No longer in Lisp. */
380 store(reg_NL1,reg_NL2,CSYMBOL(foreign_function_call_active))
382 /* Check for interrupt */
383 andi. reg_NL3, reg_ALLOC, 1
384 subi reg_ALLOC, reg_ALLOC, 4
390 SET_SIZE(call_into_lisp)
393 GFUNCDEF(call_into_c)
394 /* We're kind of low on unboxed, non-dedicated registers here:
395 most of the unboxed registers may have outgoing C args in them.
396 CFUNC is going to have to go in the CTR in a moment, anyway
397 so we'll free it up soon. reg_NFP is preserved by lisp if it
398 has a meaningful value in it, so we can use it. reg_NARGS is
399 free when it's not holding a copy of the "real" reg_NL3, which
400 gets tied up by the pseudo-atomic mechanism */
403 /* Build a lisp stack frame */
406 la reg_CSP,32(reg_CSP)
407 stw reg_OCFP,0(reg_CFP)
408 stw reg_CODE,8(reg_CFP)
409 /* The pseudo-atomic mechanism wants to use reg_NL3, but that
410 may be an outgoing C argument. Copy reg_NL3 to something that's
411 unboxed and -not- one of the C argument registers */
414 /* Turn on pseudo-atomic */
415 la reg_ALLOC,4(reg_ALLOC)
417 /* Convert the return address to an offset and save it on the stack. */
418 sub reg_NFP,reg_LIP,reg_CODE
419 la reg_NFP,OTHER_POINTER_LOWTAG(reg_NFP)
420 stw reg_NFP,4(reg_CFP)
422 /* Store Lisp state */
423 clrrwi reg_NFP,reg_ALLOC,3
424 store(reg_NFP,reg_CFUNC,CSYMBOL(dynamic_space_free_pointer))
425 /* load(reg_CFUNC,current_thread) */
427 store(reg_BSP,reg_CFUNC,CSYMBOL(current_binding_stack_pointer))
428 store(reg_CSP,reg_CFUNC,CSYMBOL(current_control_stack_pointer))
429 store(reg_CFP,reg_CFUNC,CSYMBOL(current_control_frame_pointer))
431 /* No longer in Lisp */
432 store(reg_CSP,reg_CFUNC,CSYMBOL(foreign_function_call_active))
433 /* load(reg_POLL,saver2) */
434 /* Disable pseudo-atomic; check pending interrupt */
435 andi. reg_NL3, reg_ALLOC, 1
436 subi reg_ALLOC, reg_ALLOC, 4
441 #ifdef LISP_FEATURE_DARWIN
442 /* PowerOpen (i.e. OS X) requires the callee address in r12
443 (a.k.a. CFUNC), so move it back there, too. */
449 /* Re-establish NIL */
450 #ifdef LISP_FEATURE_DARWIN
451 lis reg_NULL,hi16(NIL)
452 ori reg_NULL,reg_NULL,lo16(NIL)
455 ori reg_NULL,reg_NULL,NIL@l
460 /* If we GC'ed during the FF code (as the result of a callback ?)
461 the tagged lisp registers may now contain garbage (since the
462 registers were saved by C and not seen by the GC.) Put something
463 harmless in all such registers before allowing an interrupt */
467 /* reg_OCFP was pointing to a control stack frame & was preserved by C */
482 /* No long in foreign function call. */
483 store(reg_ZERO,reg_NL2,CSYMBOL(foreign_function_call_active))
485 /* The free pointer may have moved */
486 load(reg_NL4,CSYMBOL(dynamic_space_free_pointer))
487 add reg_ALLOC,reg_ALLOC,reg_NL4
489 /* The BSP wasn't preserved by C, so load it */
490 load(reg_BSP,CSYMBOL(current_binding_stack_pointer))
492 /* Other lisp stack/frame pointers were preserved by C.
493 I can't imagine why they'd have moved */
495 /* Get the return address back. */
496 lwz reg_LIP,4(reg_CFP)
497 lwz reg_CODE,8(reg_CFP)
498 add reg_LIP,reg_CODE,reg_LIP
499 la reg_LIP,-OTHER_POINTER_LOWTAG(reg_LIP)
501 /* No longer atomic */
502 andi. reg_NL3, reg_ALLOC, 1
503 subi reg_ALLOC, reg_ALLOC, 4
508 /* Reset the lisp stack. */
512 /* And back into Lisp. */
515 SET_SIZE(call_into_c)
517 GFUNCDEF(xundefined_tramp)
518 .globl CSYMBOL(undefined_tramp)
519 .long SIMPLE_FUN_HEADER_WIDETAG /* header */
520 .long CSYMBOL(undefined_tramp) - SIMPLE_FUN_CODE_OFFSET /* self */
523 .long NIL /* arglist */
526 CSYMBOL(undefined_tramp):
527 /* Point reg_CODE to the header and tag it as function, since
528 the debugger regards a function pointer in reg_CODE which
529 doesn't point to a code object as undefined function. */
530 bcl 20,31,.+4 /* get address of the next instruction */
531 mflr reg_CODE /* header 1 extra word back from here */
532 addi reg_CODE,reg_CODE,-(SIMPLE_FUN_CODE_OFFSET+4)
534 twllei reg_ZERO,trap_Cerror
536 .byte UNDEFINED_FUN_ERROR
537 .byte 254, sc_DescriptorReg+0x40, 1 /* 140? sparc says sc_descriptorReg */
538 /* This stuff is for the continuable error. I don't think there's
539 * any support for it on the lisp side */
541 1: lwz reg_CODE,FDEFN_RAW_ADDR_OFFSET(reg_FDEFN)
542 la reg_LIP,SIMPLE_FUN_CODE_OFFSET(reg_CODE)
548 SET_SIZE(xundefined_tramp)
550 GFUNCDEF(xclosure_tramp)
551 .globl CSYMBOL(closure_tramp)
552 CSYMBOL(closure_tramp):
553 lwz reg_LEXENV,FDEFN_FUN_OFFSET(reg_FDEFN)
554 lwz reg_CODE,CLOSURE_FUN_OFFSET(reg_LEXENV)
555 la reg_LIP,SIMPLE_FUN_CODE_OFFSET(reg_CODE)
559 SET_SIZE(xclosure_tramp)
561 GFUNCDEF(xfuncallable_instance_tramp)
562 .globl CSYMBOL(funcallable_instance_tramp)
563 .long SIMPLE_FUN_HEADER_WIDETAG
564 CSYMBOL(funcallable_instance_tramp) = . + 1
565 .long CSYMBOL(funcallable_instance_tramp)
571 lwz reg_LEXENV,FUNCALLABLE_INSTANCE_FUNCTION_OFFSET(reg_LEXENV)
572 lwz reg_FDEFN,CLOSURE_FUN_OFFSET(reg_LEXENV)
573 addi reg_LIP,reg_FDEFN,SIMPLE_FUN_CODE_OFFSET
576 SET_SIZE(funcallable_instance_tramp)
578 GFUNCDEF(fun_end_breakpoint_trap)
580 SET_SIZE(fun_end_breakpoint_trap)
582 GFUNCDEF(fun_end_breakpoint)
584 SET_SIZE(fun_end_breakpoint)
586 GFUNCDEF(fun_end_breakpoint_guts)
588 SET_SIZE(fun_end_breakpoint_guts)
590 GFUNCDEF(fun_end_breakpoint_end)
592 SET_SIZE(fun_end_breakpoint_end)
595 GFUNCDEF(ppc_flush_cache_line)
602 SET_SIZE(ppc_flush_cache_line)
604 GFUNCDEF(do_pending_interrupt)
605 twllei reg_ZERO, trap_PendingInterrupt
607 /* King Nato's branch has a nop here. Do we need this? */
608 SET_SIZE(do_pending_interrupt)
610 #if defined LISP_FEATURE_GENCGC
613 stfd FREG(1), 0(REG(3))
614 stfd FREG(2), 8(REG(3))
615 stfd FREG(3), 16(REG(3))
616 stfd FREG(4), 24(REG(3))
617 stfd FREG(5), 32(REG(3))
618 stfd FREG(6), 40(REG(3))
619 stfd FREG(7), 48(REG(3))
620 stfd FREG(8), 56(REG(3))
621 stfd FREG(9), 64(REG(3))
622 stfd FREG(10), 72(REG(3))
623 stfd FREG(11), 80(REG(3))
624 stfd FREG(12), 88(REG(3))
625 stfd FREG(13), 96(REG(3))
626 stfd FREG(14), 104(REG(3))
627 stfd FREG(15), 112(REG(3))
628 stfd FREG(16), 120(REG(3))
629 stfd FREG(17), 128(REG(3))
630 stfd FREG(18), 136(REG(3))
631 stfd FREG(19), 144(REG(3))
632 stfd FREG(20), 152(REG(3))
633 stfd FREG(21), 160(REG(3))
634 stfd FREG(22), 168(REG(3))
635 stfd FREG(23), 176(REG(3))
636 stfd FREG(24), 184(REG(3))
637 stfd FREG(25), 192(REG(3))
638 stfd FREG(26), 200(REG(3))
639 stfd FREG(27), 208(REG(3))
640 stfd FREG(28), 216(REG(3))
641 stfd FREG(29), 224(REG(3))
642 stfd FREG(30), 232(REG(3))
643 stfd FREG(31), 240(REG(3))
647 GFUNCDEF(fpu_restore)
648 lfd FREG(1), 0(REG(3))
649 lfd FREG(2), 8(REG(3))
650 lfd FREG(3), 16(REG(3))
651 lfd FREG(4), 24(REG(3))
652 lfd FREG(5), 32(REG(3))
653 lfd FREG(6), 40(REG(3))
654 lfd FREG(7), 48(REG(3))
655 lfd FREG(8), 56(REG(3))
656 lfd FREG(9), 64(REG(3))
657 lfd FREG(10), 72(REG(3))
658 lfd FREG(11), 80(REG(3))
659 lfd FREG(12), 88(REG(3))
660 lfd FREG(13), 96(REG(3))
661 lfd FREG(14), 104(REG(3))
662 lfd FREG(15), 112(REG(3))
663 lfd FREG(16), 120(REG(3))
664 lfd FREG(17), 128(REG(3))
665 lfd FREG(18), 136(REG(3))
666 lfd FREG(19), 144(REG(3))
667 lfd FREG(20), 152(REG(3))
668 lfd FREG(21), 160(REG(3))
669 lfd FREG(22), 168(REG(3))
670 lfd FREG(23), 176(REG(3))
671 lfd FREG(24), 184(REG(3))
672 lfd FREG(25), 192(REG(3))
673 lfd FREG(26), 200(REG(3))
674 lfd FREG(27), 208(REG(3))
675 lfd FREG(28), 216(REG(3))
676 lfd FREG(29), 224(REG(3))
677 lfd FREG(30), 232(REG(3))
678 lfd FREG(31), 240(REG(3))
680 SET_SIZE(fpu_restore)