/* Parts of this file were snarfed from SBCL src/runtime/ppc-assem.S, which is in the public domain. */ #include "asm.h" /* Note that the XT is passed to the quotation in r11 */ #define CALL_OR_JUMP_QUOT \ lwz r11,9(r3) /* load quotation-xt slot */ XX \ #define CALL_QUOT \ CALL_OR_JUMP_QUOT XX \ mtlr r11 /* prepare to call XT with quotation in r3 */ XX \ blrl /* go */ #define JUMP_QUOT \ CALL_OR_JUMP_QUOT XX \ mtctr r11 /* prepare to call XT with quotation in r3 */ XX \ bctr /* go */ #define PARAM_SIZE 32 #define SAVED_REGS_SIZE 96 #define FRAME (RESERVED_SIZE + PARAM_SIZE + SAVED_REGS_SIZE + 8) #if defined( __APPLE__) #define LR_SAVE 8 #define RESERVED_SIZE 24 #else #define LR_SAVE 4 #define RESERVED_SIZE 8 #endif #define SAVE_LR(reg) stw reg,(LR_SAVE + FRAME)(r1) #define LOAD_LR(reg) lwz reg,(LR_SAVE + FRAME)(r1) #define SAVE_AT(offset) (RESERVED_SIZE + PARAM_SIZE + 4 * offset) #define SAVE(register,offset) stw register,SAVE_AT(offset)(r1) #define RESTORE(register,offset) lwz register,SAVE_AT(offset)(r1) #define PROLOGUE \ mflr r0 XX /* get caller's return address */ \ stwu r1,-FRAME(r1) XX /* create a stack frame to hold non-volatile registers */ \ SAVE_LR(r0) #define EPILOGUE \ LOAD_LR(r0) XX \ lwz r1,0(r1) XX /* destroy the stack frame */ \ mtlr r0 /* get ready to return */ DEF(void,c_to_factor,(CELL quot)): PROLOGUE SAVE(r13,0) /* save GPRs */ /* don't save ds pointer */ /* don't save rs pointer */ SAVE(r16,3) SAVE(r17,4) SAVE(r18,5) SAVE(r19,6) SAVE(r20,7) SAVE(r21,8) SAVE(r22,9) SAVE(r23,10) SAVE(r24,11) SAVE(r25,12) SAVE(r26,13) SAVE(r27,14) SAVE(r28,15) SAVE(r29,16) SAVE(r30,17) SAVE(r31,18) SAVE(r3,19) /* save quotation since we're about to mangle it */ mr r3,r1 /* pass call stack pointer as an argument */ bl MANGLE(save_callstack_bottom) RESTORE(r3,19) /* restore quotation */ CALL_QUOT RESTORE(r31,18) /* restore GPRs */ RESTORE(r30,17) RESTORE(r29,16) RESTORE(r28,15) RESTORE(r27,14) RESTORE(r26,13) RESTORE(r25,12) RESTORE(r24,11) RESTORE(r23,10) RESTORE(r22,9) RESTORE(r21,8) RESTORE(r20,7) RESTORE(r19,6) RESTORE(r18,5) RESTORE(r17,4) RESTORE(r16,3) /* don't restore rs pointer */ /* don't restore ds pointer */ RESTORE(r13,0) EPILOGUE blr /* We must pass the XT to the quotation in r11. */ DEF(void,primitive_call,(void)): lwz r3,0(r14) /* load quotation from data stack */ subi r14,r14,4 /* pop quotation from data stack */ JUMP_QUOT /* We must preserve r4 here in case we're calling a primitive */ DEF(void,primitive_execute,(void)): lwz r3,0(r14) /* load word from data stack */ lwz r11,29(r3) /* load word-xt slot */ mtctr r11 /* prepare to call XT */ subi r14,r14,4 /* pop word from data stack */ bctr /* go */ /* We pass a function pointer to memcpy in r6 to work around a Mac OS X ABI limitation which would otherwise require us to do a bizzaro PC-relative trampoline to retrieve the function address */ DEF(void,set_callstack,(F_STACK_FRAME *to, F_STACK_FRAME *from, CELL length, void *memcpy)): sub r1,r3,r5 /* compute new stack pointer */ mr r3,r1 /* start of destination of memcpy() */ stwu r1,-64(r1) /* setup fake stack frame for memcpy() */ mtlr r6 /* prepare to call memcpy() */ blrl /* go */ lwz r1,0(r1) /* tear down fake stack frame */ lwz r0,LR_SAVE(r1) /* we have restored the stack; load return address */ mtlr r0 /* prepare to return to restored callstack */ blr /* go */ DEF(void,throw_impl,(CELL quot, F_STACK_FRAME *rewind_to)): mr r1,r4 /* compute new stack pointer */ lwz r0,LR_SAVE(r1) /* we have rewound the stack; load return address */ mtlr r0 JUMP_QUOT /* call the quotation */ DEF(void,lazy_jit_compile,(CELL quot)): mr r4,r1 /* save stack pointer */ PROLOGUE bl MANGLE(primitive_jit_compile) EPILOGUE JUMP_QUOT /* call the quotation */ /* Thanks to Joshua Grams for this code. On PowerPC processors, we must flush the instruction cache manually after writing to the code heap. */ DEF(void,flush_icache,(void *start, int len)): /* compute number of cache lines to flush */ add r4,r4,r3 clrrwi r3,r3,5 /* align addr to next lower cache line boundary */ sub r4,r4,r3 /* then n_lines = (len + 0x1f) / 0x20 */ addi r4,r4,0x1f srwi. r4,r4,5 /* note '.' suffix */ beqlr /* if n_lines == 0, just return. */ mtctr r4 /* flush cache lines */ 0: dcbf 0,r3 /* for each line... */ sync icbi 0,r3 addi r3,r3,0x20 bdnz 0b sync /* finish up */ isync blr