198 lines
6.3 KiB
ArmAsm
198 lines
6.3 KiB
ArmAsm
/* 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
|
|
|
|
/* The JIT compiles an 'mr r4,r1' in front of every primitive call, since a
|
|
word which was defined as a primitive will not change its definition for the
|
|
lifetime of the image -- adding new primitives requires a bootstrap. However,
|
|
an undefined word can certainly become defined,
|
|
|
|
DEFER: foo
|
|
...
|
|
: foo ... ;
|
|
|
|
And calls to non-primitives do not have this one-instruction prologue, so we
|
|
set the XT of undefined words to this symbol. */
|
|
DEF(void,undefined,(CELL word)):
|
|
mr r4,r1
|
|
b MANGLE(undefined_error)
|
|
|
|
DEF(void,dosym,(CELL word)):
|
|
stwu r3,4(r14) /* push word to stack */
|
|
blr /* return */
|
|
|
|
/* Here we have two entry points. The first one is taken when profiling is
|
|
enabled */
|
|
DEF(void,docol_profiling,(CELL word)):
|
|
lwz r4,25(r3) /* load profile-count slot */
|
|
addi r4,r4,8 /* increment count */
|
|
stw r4,25(r3) /* store profile-count slot */
|
|
DEF(void,docol,(CELL word)):
|
|
lwz r3,13(r3) /* load word-def slot */
|
|
JUMP_QUOT
|
|
|
|
/* 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 with word in r3 */
|
|
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
|