0.9.17.8:
[sbcl.git] / src / runtime / ppc-assem.S
index 1135c8a..10f46d5 100644 (file)
@@ -3,34 +3,80 @@
 #include "sbcl.h" 
 #include "lispregs.h"
 #include "globals.h"
+
 #include "genesis/simple-fun.h"
 #include "genesis/fdefn.h"
 #include "genesis/closure.h"
+#include "genesis/funcallable-instance.h"
 #include "genesis/static-symbols.h"
 
+#ifdef LISP_FEATURE_DARWIN
+#define CSYMBOL(x) _ ## x
+#else
+#define CSYMBOL(x) x
+#endif
+
+#if defined LISP_FEATURE_DARWIN
+#define FUNCDEF(x)     .text @ \
+                       .align 3 @ \
+_##x:
+
+#define GFUNCDEF(x)    .globl _/**/x @ \
+       FUNCDEF(x)
+#else
 #define FUNCDEF(x)     .text ; \
                        .align 3 ; \
                        .type x,@function ; \
 x:
+
 #define GFUNCDEF(x)    .globl x ; \
        FUNCDEF(x)
+#endif
 
+#if defined LISP_FEATURE_DARWIN
+#define SET_SIZE(x)
+#else
 #define SET_SIZE(x) .size x,.-x
+#endif
 
 /* Load a register from a global, using the register as an intermediary */
 /* The register will be a fixnum for one instruction, so this is gc-safe */
 
+#if defined LISP_FEATURE_DARWIN
+#define load(reg,global) \
+       lis reg,ha16(global) @ \
+       lwz reg,lo16(global)(reg) ; Comment
+#define store(reg,temp,global) \
+       lis temp,ha16(global) @\
+       stw reg,lo16(global)(temp) ; Comment
+#else
 #define load(reg,global) \
        lis reg,global@ha; lwz reg,global@l(reg)
 #define store(reg,temp,global) \
        lis temp,global@ha; stw reg,global@l(temp)
+#endif
        
 #define        FIRST_SAVE_FPR  14      /* lowest-numbered non-volatile FPR */
+#ifdef LISP_FEATURE_DARWIN
+#define        FIRST_SAVE_GPR  13      /* lowest-numbered non-volatile GPR */
+#define NGPR_SAVE_BYTES(n) ((32-(n))*4)
+#define FRAME_ARG_BYTES(n)  (((((n)+6)*4)+15)&~15)
+#else
 #define        FIRST_SAVE_GPR  14      /* lowest-numbered non-volatile GPR */
-#define        NFPR_SAVE_BYTES(n) ((32-(n))*8)
 #define NGPR_SAVE_BYTES(n) ((32-(~1&((n)+1)))*4)
 #define FRAME_ARG_BYTES(n)  (((((n)+2)*4)+15)&~15)
+#endif
+#define        NFPR_SAVE_BYTES(n) ((32-(n))*8)
 
+#ifdef LISP_FEATURE_DARWIN
+#define FRAME_SIZE(first_g,first_f,out_arg_words,savecr) \
+(NFPR_SAVE_BYTES(first_f)+ NGPR_SAVE_BYTES(first_g)+ FRAME_ARG_BYTES(out_arg_words))
+#define SAVE_FPR(n) stfd f##n,-8*(32- n)(r11)
+#define SAVE_GPR(n) stw r##n,-4*(32- n)(r11)
+#define FULL_FRAME_SIZE (FRAME_SIZE(FIRST_SAVE_GPR,FIRST_SAVE_FPR,8,1)+15&~15)
+#define RESTORE_FPR(n) lfd f##n,-8*(32- n)(r11)
+#define RESTORE_GPR(n) lwz r##n,-4*(32- n)(r11)
+#else
 #define FRAME_SIZE(first_g,first_f,out_arg_words,savecr) \
 (NFPR_SAVE_BYTES(first_f)+ NGPR_SAVE_BYTES(first_g)+ FRAME_ARG_BYTES(out_arg_words+savecr))
 #define SAVE_FPR(n) stfd n,-8*(32-(n))(11)
@@ -39,6 +85,106 @@ x:
 
 #define RESTORE_FPR(n) lfd n,-8*(32-(n))(11)
 #define RESTORE_GPR(n) lwz n,-4*(32-(n))(11)
+#endif
+
+#ifdef LISP_FEATURE_DARWIN
+#define C_FULL_PROLOG \
+       nop @\
+       nop @ \
+       mfcr REG(0) @ \
+       stw REG(0),4(REG(1)) @ \
+       mflr REG(0) @ \
+       stw REG(0),8(REG(1)) @ \
+       mr REG(11),REG(1) @ \
+       stwu REG(1),-FULL_FRAME_SIZE(REG(1)) @ \
+       SAVE_FPR(14) @ \
+       SAVE_FPR(15) @ \
+       SAVE_FPR(16) @ \
+       SAVE_FPR(17) @ \
+       SAVE_FPR(18) @ \
+       SAVE_FPR(19) @ \
+       SAVE_FPR(20) @ \
+       SAVE_FPR(21) @ \
+       SAVE_FPR(22) @ \
+       SAVE_FPR(23) @ \
+       SAVE_FPR(24) @ \
+       SAVE_FPR(25) @ \
+       SAVE_FPR(26) @ \
+       SAVE_FPR(27) @ \
+       SAVE_FPR(28) @ \
+       SAVE_FPR(29) @ \
+       SAVE_FPR(30) @ \
+       SAVE_FPR(31) @ \
+       la REG(11),-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(11)) @ \
+       SAVE_GPR(13) @ \
+       SAVE_GPR(14) @ \
+       SAVE_GPR(15) @ \
+       SAVE_GPR(16) @ \
+       SAVE_GPR(17) @ \
+       SAVE_GPR(18) @ \
+       SAVE_GPR(19) @ \
+       SAVE_GPR(20) @ \
+       SAVE_GPR(21) @ \
+       SAVE_GPR(22) @ \
+       SAVE_GPR(23) @ \
+       SAVE_GPR(24) @ \
+       SAVE_GPR(25) @ \
+       SAVE_GPR(26) @ \
+       SAVE_GPR(27) @ \
+       SAVE_GPR(28) @ \
+       SAVE_GPR(29) @ \
+       SAVE_GPR(30) @ \
+       SAVE_GPR(31)
+
+
+#define C_FULL_EPILOG \
+       la REG(11),FULL_FRAME_SIZE-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(1)) @ \
+       RESTORE_GPR(13) @ \
+       RESTORE_GPR(14) @ \
+       RESTORE_GPR(15) @ \
+       RESTORE_GPR(16) @ \
+       RESTORE_GPR(17) @ \
+       RESTORE_GPR(18) @ \
+       RESTORE_GPR(19) @ \
+       RESTORE_GPR(20) @ \
+       RESTORE_GPR(21) @ \
+       RESTORE_GPR(22) @ \
+       RESTORE_GPR(23) @ \
+       RESTORE_GPR(24) @ \
+       RESTORE_GPR(25) @ \
+       RESTORE_GPR(26) @ \
+       RESTORE_GPR(27) @ \
+       RESTORE_GPR(28) @ \
+       RESTORE_GPR(29) @ \
+       RESTORE_GPR(30) @ \
+       RESTORE_GPR(31) @ \
+       la REG(11),NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(REG(11)) @ \
+       RESTORE_FPR(14) @ \
+       RESTORE_FPR(15) @ \
+       RESTORE_FPR(16) @ \
+       RESTORE_FPR(17) @ \
+       RESTORE_FPR(18) @ \
+       RESTORE_FPR(19) @ \
+       RESTORE_FPR(20) @ \
+       RESTORE_FPR(21) @ \
+       RESTORE_FPR(22) @ \
+       RESTORE_FPR(23) @ \
+       RESTORE_FPR(24) @ \
+       RESTORE_FPR(25) @ \
+       RESTORE_FPR(26) @ \
+       RESTORE_FPR(27) @ \
+       RESTORE_FPR(28) @ \
+       RESTORE_FPR(29) @ \
+       RESTORE_FPR(30) @ \
+       RESTORE_FPR(31) @ \
+       lwz REG(1),0(REG(1)) @ \
+       lwz REG(0),4(REG(1)) @ \
+       mtcr REG(0) @ \
+       lwz REG(0),8(REG(1)) @ \
+       mtlr REG(0) @ \
+       
+#else  
+
 #define C_FULL_PROLOG \
        mflr 0 ; \
        stw 0,4(1) ; \
@@ -80,10 +226,13 @@ x:
        SAVE_GPR(28) ; \
        SAVE_GPR(29) ; \
        SAVE_GPR(30) ; \
-       SAVE_GPR(31)
-
+       SAVE_GPR(31) ; \
+       mfcr 0  ; \
+       stw 0,8(1)
 
 #define C_FULL_EPILOG \
+       lwz 5,8(1) ; \
+       mtcrf 255,5 ; \
        la 11,FULL_FRAME_SIZE-NFPR_SAVE_BYTES(FIRST_SAVE_FPR)(1) ; \
        RESTORE_GPR(14) ; \
        RESTORE_GPR(15) ; \
@@ -126,8 +275,7 @@ x:
        lwz 0,4(1) ; \
        mtlr 0 ; \
        
-
-
+#endif
        
        .text
 
@@ -138,8 +286,6 @@ x:
 
        GFUNCDEF(call_into_lisp)
        C_FULL_PROLOG
-       mfcr 0
-       stw 0,8(1)
        /* store(reg_POLL,11,saver2) */
        /* Initialize tagged registers */
        li reg_ZERO,0
@@ -157,23 +303,27 @@ x:
        li reg_L1,0
        li reg_L2,0
        li reg_LIP,0
+#ifdef LISP_FEATURE_DARWIN     
+       lis reg_NULL,hi16(NIL)
+       ori reg_NULL,reg_NULL,lo16(NIL)
+#else
        lis reg_NULL,NIL@h
        ori reg_NULL,reg_NULL,NIL@l
-
+#endif
        /* Turn on pseudo-atomic */
 
-       li reg_NL3,-4
        li reg_ALLOC,4
-       store(reg_ZERO,reg_NL4,foreign_function_call_active)
-       load(reg_NL4,dynamic_space_free_pointer)
+       store(reg_ZERO,reg_NL4,CSYMBOL(foreign_function_call_active))
+       load(reg_NL4,CSYMBOL(dynamic_space_free_pointer))
        add reg_ALLOC,reg_ALLOC,reg_NL4
-       load(reg_BSP,current_binding_stack_pointer)
-       load(reg_CSP,current_control_stack_pointer)
-       load(reg_OCFP,current_control_frame_pointer)
+       load(reg_BSP,CSYMBOL(current_binding_stack_pointer))
+       load(reg_CSP,CSYMBOL(current_control_stack_pointer))
+       load(reg_OCFP,CSYMBOL(current_control_frame_pointer))
 
        /* No longer atomic, and check for interrupt */
-       add reg_ALLOC,reg_ALLOC,reg_NL3
-       twlti reg_ALLOC,0
+       andi. reg_NL3, reg_ALLOC, 1
+       subi reg_ALLOC,reg_ALLOC,4
+       twnei reg_NL3, 0
 
        /* Pass in the arguments */
 
@@ -185,8 +335,13 @@ x:
        lwz reg_A3,12(reg_CFP)
 
        /* Calculate LRA */
-       lis reg_LRA,lra@ha
-       addi reg_LRA,reg_LRA,lra@l
+#ifdef LISP_FEATURE_DARWIN
+       lis reg_LRA,ha16(lra)
+       addi reg_LRA,reg_LRA,lo16(lra)
+#else
+       lis reg_LRA,lra@h
+       ori reg_LRA,reg_LRA,lra@l
+#endif
        addi reg_LRA,reg_LRA,OTHER_POINTER_LOWTAG
 
        /* Function is an indirect closure */
@@ -206,32 +361,30 @@ lra:
 
        /* Return the one value. */
 
-       mr 3,reg_A0
+       mr REG(3),reg_A0
 
        /* Turn on  pseudo-atomic */
-       li reg_NL3,-4
        la reg_ALLOC,4(reg_ALLOC)
 
        /* Store lisp state */
        clrrwi reg_NL1,reg_ALLOC,3
-       store(reg_NL1,reg_NL2,dynamic_space_free_pointer)
+       store(reg_NL1,reg_NL2,CSYMBOL(dynamic_space_free_pointer))
        /* store(reg_POLL,reg_NL2,poll_flag) */
        /* load(reg_NL2,current_thread) */
-       store(reg_BSP,reg_NL2,current_binding_stack_pointer)
-       store(reg_CSP,reg_NL2,current_control_stack_pointer)
-       store(reg_CFP,reg_NL2,current_control_frame_pointer)
+       store(reg_BSP,reg_NL2,CSYMBOL(current_binding_stack_pointer))
+       store(reg_CSP,reg_NL2,CSYMBOL(current_control_stack_pointer))
+       store(reg_CFP,reg_NL2,CSYMBOL(current_control_frame_pointer))
        /* load(reg_POLL,saver2) */
 
        /* No longer in Lisp. */
-       store(reg_NL1,reg_NL2,foreign_function_call_active)
+       store(reg_NL1,reg_NL2,CSYMBOL(foreign_function_call_active))
 
        /* Check for interrupt */
-       add reg_ALLOC,reg_ALLOC,reg_NL3
-       twlti reg_ALLOC,0
-
+       andi. reg_NL3, reg_ALLOC, 1
+       subi reg_ALLOC, reg_ALLOC, 4
+       twnei reg_NL3,0
+       
        /* Back to C */
-       lwz 5,8(1)
-       mtcrf 255,5
        C_FULL_EPILOG
        blr
        SET_SIZE(call_into_lisp)
@@ -259,7 +412,6 @@ lra:
        mr reg_NARGS,reg_NL3
 
        /* Turn on pseudo-atomic */
-       li reg_NL3,-4
        la reg_ALLOC,4(reg_ALLOC)
 
        /* Convert the return address to an offset and save it on the stack. */
@@ -269,27 +421,39 @@ lra:
 
        /* Store Lisp state */
        clrrwi reg_NFP,reg_ALLOC,3
-       store(reg_NFP,reg_CFUNC,dynamic_space_free_pointer)
+       store(reg_NFP,reg_CFUNC,CSYMBOL(dynamic_space_free_pointer))
        /* load(reg_CFUNC,current_thread) */
        
-       store(reg_BSP,reg_CFUNC,current_binding_stack_pointer)
-       store(reg_CSP,reg_CFUNC,current_control_stack_pointer)
-       store(reg_CFP,reg_CFUNC,current_control_frame_pointer)
+       store(reg_BSP,reg_CFUNC,CSYMBOL(current_binding_stack_pointer))
+       store(reg_CSP,reg_CFUNC,CSYMBOL(current_control_stack_pointer))
+       store(reg_CFP,reg_CFUNC,CSYMBOL(current_control_frame_pointer))
 
        /* No longer in Lisp */
-       store(reg_CSP,reg_CFUNC,foreign_function_call_active)
+       store(reg_CSP,reg_CFUNC,CSYMBOL(foreign_function_call_active))
        /* load(reg_POLL,saver2) */
        /* Disable pseudo-atomic; check pending interrupt */
-       add reg_ALLOC,reg_ALLOC,reg_NL3
-       twlti reg_ALLOC,0
+       andi. reg_NL3, reg_ALLOC, 1
+       subi reg_ALLOC, reg_ALLOC, 4
+       twnei reg_NL3, 0
+
        mr reg_NL3,reg_NARGS
 
+#ifdef LISP_FEATURE_DARWIN
+       /* PowerOpen (i.e. OS X) requires the callee address in r12
+           (a.k.a. CFUNC), so move it back there, too. */
+       mfctr reg_CFUNC
+#endif
         /* Into C we go. */
        bctrl
 
        /* Re-establish NIL */
+#ifdef LISP_FEATURE_DARWIN
+       lis reg_NULL,hi16(NIL)
+       ori reg_NULL,reg_NULL,lo16(NIL)
+#else
        lis reg_NULL,NIL@h
        ori reg_NULL,reg_NULL,NIL@l
+#endif
        /* And reg_ZERO */
        li reg_ZERO,0
 
@@ -312,18 +476,18 @@ lra:
        li reg_LIP,0
 
        /* Atomic ... */
-       li reg_NL3,-4
+        li reg_NL3,-4        
        li reg_ALLOC,4
 
        /* No long in foreign function call. */
-       store(reg_ZERO,reg_NL2,foreign_function_call_active)
+       store(reg_ZERO,reg_NL2,CSYMBOL(foreign_function_call_active))
 
        /* The free pointer may have moved */
-       load(reg_NL4,dynamic_space_free_pointer)
+       load(reg_NL4,CSYMBOL(dynamic_space_free_pointer))
        add reg_ALLOC,reg_ALLOC,reg_NL4
 
        /* The BSP wasn't preserved by C, so load it */
-       load(reg_BSP,current_binding_stack_pointer)
+       load(reg_BSP,CSYMBOL(current_binding_stack_pointer))
 
        /* Other lisp stack/frame pointers were preserved by C.
        I can't imagine why they'd have moved */
@@ -335,8 +499,10 @@ lra:
        la reg_LIP,-OTHER_POINTER_LOWTAG(reg_LIP)
 
        /* No longer atomic */
-       add reg_ALLOC,reg_ALLOC,reg_NL3
-       twlti reg_ALLOC,0
+       andi. reg_NL3, reg_ALLOC, 1
+       subi reg_ALLOC, reg_ALLOC, 4
+       twnei reg_NL3, 0
+
        mtlr reg_LIP
        
        /* Reset the lisp stack. */
@@ -349,39 +515,27 @@ lra:
        SET_SIZE(call_into_c)
 
        GFUNCDEF(xundefined_tramp)
-       .globl undefined_tramp
-       .byte 0,0,0,SIMPLE_FUN_HEADER_WIDETAG
-       .byte 18<<2
-undefined_tramp:       
-       .byte 0,0,24
-       .long undefined_tramp
-       .long NIL
-       .long NIL
-       .long NIL
-       .long NIL
+       .globl CSYMBOL(undefined_tramp)
+CSYMBOL(undefined_tramp):      
        twllei reg_ZERO,trap_Cerror
        .byte 4
        .byte UNDEFINED_FUN_ERROR
        .byte 254, sc_DescriptorReg+0x40, 1     /* 140?  sparc says sc_descriptorReg */
+       /* This stuff is for the continuable error.  I don't think there's
+        * any support for it on the lisp side */
        .align 2
 1:     lwz reg_CODE,FDEFN_RAW_ADDR_OFFSET(reg_FDEFN)
        la reg_LIP,SIMPLE_FUN_CODE_OFFSET(reg_CODE)
        mtctr reg_LIP
        bctr
-       
+       mr reg_CSP,reg_CFP
+       b 1b
+
        SET_SIZE(xundefined_tramp)
 
        GFUNCDEF(xclosure_tramp)
-       .globl closure_tramp
-       .byte 0,0,0,SIMPLE_FUN_HEADER_WIDETAG
-       .byte 18<<2
-closure_tramp:
-       .byte 0,0,24
-       .long closure_tramp
-       .long NIL 
-       .long NIL
-       .long NIL
-       .long NIL
+       .globl CSYMBOL(closure_tramp)
+CSYMBOL(closure_tramp):
        lwz reg_LEXENV,FDEFN_FUN_OFFSET(reg_FDEFN)
        lwz reg_CODE,CLOSURE_FUN_OFFSET(reg_LEXENV)
        la reg_LIP,SIMPLE_FUN_CODE_OFFSET(reg_CODE)
@@ -390,6 +544,22 @@ closure_tramp:
 
        SET_SIZE(xclosure_tramp)
 
+       GFUNCDEF(xfuncallable_instance_tramp)
+       .globl CSYMBOL(funcallable_instance_tramp)
+       .long SIMPLE_FUN_HEADER_WIDETAG
+CSYMBOL(funcallable_instance_tramp) = . + 1
+       .long CSYMBOL(funcallable_instance_tramp)
+       .long NIL
+       .long NIL
+       .long NIL
+       .long NIL
+       lwz reg_LEXENV,FUNCALLABLE_INSTANCE_FUNCTION_OFFSET(reg_LEXENV)
+       lwz reg_FDEFN,CLOSURE_FUN_OFFSET(reg_LEXENV)
+       addi reg_LIP,reg_FDEFN,SIMPLE_FUN_CODE_OFFSET
+       mtctr reg_LIP
+       bctr
+       SET_SIZE(funcallable_instance_tramp)
+       
        GFUNCDEF(fun_end_breakpoint_trap)
        .long 0
        SET_SIZE(fun_end_breakpoint_trap)
@@ -408,11 +578,90 @@ closure_tramp:
 
 
        GFUNCDEF(ppc_flush_cache_line)
-       dcbf 0,3
+       dcbf 0,REG(3)
        sync
-       icbi 0,3
+       icbi 0,REG(3)
        sync
        isync
        blr
        SET_SIZE(ppc_flush_cache_line)
 
+        GFUNCDEF(do_pending_interrupt)
+       twllei  reg_ZERO, trap_PendingInterrupt
+       blr
+/* King Nato's branch has a nop here. Do we need this? */
+       SET_SIZE(do_pending_interrupt)
+       
+#if defined LISP_FEATURE_GENCGC
+
+        GFUNCDEF(fpu_save)
+        stfd   FREG(1), 0(REG(3))
+       stfd    FREG(2), 8(REG(3))
+       stfd    FREG(3), 16(REG(3))
+       stfd    FREG(4), 24(REG(3))
+       stfd    FREG(5), 32(REG(3))
+       stfd    FREG(6), 40(REG(3))
+       stfd    FREG(7), 48(REG(3))
+       stfd    FREG(8), 56(REG(3))
+       stfd    FREG(9), 64(REG(3))
+       stfd    FREG(10), 72(REG(3))
+       stfd    FREG(11), 80(REG(3))
+       stfd    FREG(12), 88(REG(3))
+       stfd    FREG(13), 96(REG(3))
+       stfd    FREG(14), 104(REG(3))
+       stfd    FREG(15), 112(REG(3))
+       stfd    FREG(16), 120(REG(3))
+       stfd    FREG(17), 128(REG(3))
+       stfd    FREG(18), 136(REG(3))
+       stfd    FREG(19), 144(REG(3))
+       stfd    FREG(20), 152(REG(3))
+       stfd    FREG(21), 160(REG(3))
+       stfd    FREG(22), 168(REG(3))
+       stfd    FREG(23), 176(REG(3))
+       stfd    FREG(24), 184(REG(3))
+       stfd    FREG(25), 192(REG(3))
+       stfd    FREG(26), 200(REG(3))
+       stfd    FREG(27), 208(REG(3))
+       stfd    FREG(28), 216(REG(3))
+       stfd    FREG(29), 224(REG(3))
+       stfd    FREG(30), 232(REG(3))
+       stfd    FREG(31), 240(REG(3))
+       blr
+       SET_SIZE(fpu_save)
+       
+       GFUNCDEF(fpu_restore)
+       lfd     FREG(1), 0(REG(3))
+       lfd     FREG(2), 8(REG(3))
+       lfd     FREG(3), 16(REG(3))
+       lfd     FREG(4), 24(REG(3))
+       lfd     FREG(5), 32(REG(3))
+       lfd     FREG(6), 40(REG(3))
+       lfd     FREG(7), 48(REG(3))
+       lfd     FREG(8), 56(REG(3))
+       lfd     FREG(9), 64(REG(3))
+       lfd     FREG(10), 72(REG(3))
+       lfd     FREG(11), 80(REG(3))
+       lfd     FREG(12), 88(REG(3))
+       lfd     FREG(13), 96(REG(3))
+       lfd     FREG(14), 104(REG(3))
+       lfd     FREG(15), 112(REG(3))
+       lfd     FREG(16), 120(REG(3))
+       lfd     FREG(17), 128(REG(3))
+       lfd     FREG(18), 136(REG(3))
+       lfd     FREG(19), 144(REG(3))
+       lfd     FREG(20), 152(REG(3))
+       lfd     FREG(21), 160(REG(3))
+       lfd     FREG(22), 168(REG(3))
+       lfd     FREG(23), 176(REG(3))
+       lfd     FREG(24), 184(REG(3))
+       lfd     FREG(25), 192(REG(3))
+       lfd     FREG(26), 200(REG(3))
+       lfd     FREG(27), 208(REG(3))
+       lfd     FREG(28), 216(REG(3))
+       lfd     FREG(29), 224(REG(3))
+       lfd     FREG(30), 232(REG(3))
+       lfd     FREG(31), 240(REG(3))
+        blr
+       SET_SIZE(fpu_restore)
+       
+#endif