factor/vm/cpu-ppc.hpp

95 lines
2.4 KiB
C++
Raw Normal View History

2009-05-04 02:46:13 -04:00
namespace factor
{
2009-05-02 05:04:19 -04:00
#define FACTOR_CPU_STRING "ppc"
2009-05-06 16:39:03 -04:00
#define VM_ASM_API VM_C_API
2009-05-02 05:04:19 -04:00
2009-05-06 16:39:03 -04:00
register cell ds asm("r13");
register cell rs asm("r14");
2009-05-02 05:04:19 -04:00
/* In the instruction sequence:
LOAD32 r3,...
B blah
the offset from the immediate operand to LOAD32 to the instruction after
the branch is two instructions. */
static const fixnum xt_tail_pic_offset = 4 * 2;
2009-05-06 16:39:03 -04:00
inline static void check_call_site(cell return_address)
{
#ifdef FACTOR_DEBUG
cell insn = *(cell *)return_address;
/* Check that absolute bit is 0 */
assert((insn & 0x2) == 0x0);
/* Check that instruction is branch */
2009-05-06 16:39:03 -04:00
assert((insn >> 26) == 0x12);
#endif
}
static const cell b_mask = 0x3fffffc;
2009-05-06 16:39:03 -04:00
inline static void *get_call_target(cell return_address)
{
return_address -= sizeof(cell);
check_call_site(return_address);
2009-05-06 16:39:03 -04:00
cell insn = *(cell *)return_address;
2009-05-08 18:41:22 -04:00
cell unsigned_addr = (insn & b_mask);
2009-05-06 16:39:03 -04:00
fixnum signed_addr = (fixnum)(unsigned_addr << 6) >> 6;
return (void *)(signed_addr + return_address);
}
inline static void set_call_target(cell return_address, void *target)
{
return_address -= sizeof(cell);
check_call_site(return_address);
2009-05-06 16:39:03 -04:00
cell insn = *(cell *)return_address;
fixnum relative_address = ((cell)target - return_address);
2009-05-08 18:41:22 -04:00
insn = ((insn & ~b_mask) | (relative_address & b_mask));
2009-05-06 16:39:03 -04:00
*(cell *)return_address = insn;
/* Flush the cache line containing the call we just patched */
__asm__ __volatile__ ("icbi 0, %0\n" "sync\n"::"r" (return_address):);
}
inline static bool tail_call_site_p(cell return_address)
{
return_address -= sizeof(cell);
cell insn = *(cell *)return_address;
return (insn & 0x1) == 0;
}
inline static unsigned int fpu_status(unsigned int status)
{
unsigned int r = 0;
if (status & 0x20000000)
2009-09-14 04:09:03 -04:00
r |= FP_TRAP_INVALID_OPERATION;
if (status & 0x10000000)
2009-09-14 04:09:03 -04:00
r |= FP_TRAP_OVERFLOW;
if (status & 0x08000000)
2009-09-14 04:09:03 -04:00
r |= FP_TRAP_UNDERFLOW;
if (status & 0x04000000)
2009-09-14 04:09:03 -04:00
r |= FP_TRAP_ZERO_DIVIDE;
if (status & 0x02000000)
2009-09-14 04:09:03 -04:00
r |= FP_TRAP_INEXACT;
return r;
}
2009-05-06 16:39:03 -04:00
/* Defined in assembly */
VM_ASM_API void c_to_factor(cell quot, void *vm);
VM_ASM_API void throw_impl(cell quot, stack_frame *rewind, void *vm);
VM_ASM_API void lazy_jit_compile(cell quot, void *vm);
2009-05-06 16:39:03 -04:00
VM_ASM_API void flush_icache(cell start, cell len);
VM_ASM_API void set_callstack(stack_frame *to,
stack_frame *from,
cell length,
void *(*memcpy)(void*,const void*, size_t));
2009-05-04 02:46:13 -04:00
}