VM: Refactor cpu-* to Factor style
parent
0cf7feba0b
commit
fb34be6fa7
|
@ -1,8 +1,7 @@
|
|||
namespace factor
|
||||
{
|
||||
namespace factor {
|
||||
|
||||
#define FACTOR_CPU_STRING "arm"
|
||||
|
||||
#define FRAME_RETURN_ADDRESS(frame,vm) *(XT *)(vm->frame_successor(frame) + 1)
|
||||
#define FRAME_RETURN_ADDRESS(frame, vm) *(XT*)(vm->frame_successor(frame) + 1)
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
namespace factor
|
||||
{
|
||||
namespace factor {
|
||||
|
||||
#ifdef FACTOR_64
|
||||
#define FACTOR_CPU_STRING "ppc.64"
|
||||
|
@ -7,7 +6,7 @@ namespace factor
|
|||
#define FACTOR_CPU_STRING "ppc.32"
|
||||
#endif
|
||||
|
||||
#define CALLSTACK_BOTTOM(ctx) (void *)(ctx->callstack_seg->end - 32)
|
||||
#define CALLSTACK_BOTTOM(ctx) (void*)(ctx->callstack_seg->end - 32)
|
||||
|
||||
/* In the instruction sequence:
|
||||
|
||||
|
@ -18,66 +17,63 @@ namespace factor
|
|||
the branch is one instruction. */
|
||||
static const fixnum xt_tail_pic_offset = 4;
|
||||
|
||||
inline static void check_call_site(cell return_address)
|
||||
{
|
||||
u32 insn = *(u32 *)return_address;
|
||||
/* Check that absolute bit is 0 */
|
||||
FACTOR_ASSERT((insn & 0x2) == 0x0);
|
||||
/* Check that instruction is branch */
|
||||
FACTOR_ASSERT((insn >> 26) == 0x12);
|
||||
inline static void check_call_site(cell return_address) {
|
||||
u32 insn = *(u32*)return_address;
|
||||
/* Check that absolute bit is 0 */
|
||||
FACTOR_ASSERT((insn & 0x2) == 0x0);
|
||||
/* Check that instruction is branch */
|
||||
FACTOR_ASSERT((insn >> 26) == 0x12);
|
||||
}
|
||||
|
||||
static const u32 b_mask = 0x3fffffc;
|
||||
|
||||
inline static void *get_call_target(cell return_address)
|
||||
{
|
||||
return_address -= 4;
|
||||
check_call_site(return_address);
|
||||
inline static void* get_call_target(cell return_address) {
|
||||
return_address -= 4;
|
||||
check_call_site(return_address);
|
||||
|
||||
u32 insn = *(u32 *)return_address;
|
||||
u32 unsigned_addr = (insn & b_mask);
|
||||
s32 signed_addr = (s32)(unsigned_addr << 6) >> 6;
|
||||
return (void *)(signed_addr + return_address);
|
||||
u32 insn = *(u32*)return_address;
|
||||
u32 unsigned_addr = (insn & b_mask);
|
||||
s32 signed_addr = (s32)(unsigned_addr << 6) >> 6;
|
||||
return (void*)(signed_addr + return_address);
|
||||
}
|
||||
|
||||
inline static void set_call_target(cell return_address, void *target)
|
||||
{
|
||||
return_address -= 4;
|
||||
check_call_site(return_address);
|
||||
inline static void set_call_target(cell return_address, void* target) {
|
||||
return_address -= 4;
|
||||
check_call_site(return_address);
|
||||
|
||||
u32 insn = *(u32 *)return_address;
|
||||
u32 insn = *(u32*)return_address;
|
||||
|
||||
fixnum relative_address = ((cell)target - return_address);
|
||||
insn = ((insn & ~b_mask) | (relative_address & b_mask));
|
||||
*(u32 *)return_address = insn;
|
||||
fixnum relative_address = ((cell) target - return_address);
|
||||
insn = ((insn & ~b_mask) | (relative_address & b_mask));
|
||||
*(u32*)return_address = insn;
|
||||
|
||||
/* Flush the cache line containing the call we just patched */
|
||||
__asm__ __volatile__ ("icbi 0, %0\n" "sync\n"::"r" (return_address):);
|
||||
/* 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 -= 4;
|
||||
u32 insn = *(u32 *)return_address;
|
||||
return (insn & 0x1) == 0;
|
||||
inline static bool tail_call_site_p(cell return_address) {
|
||||
return_address -= 4;
|
||||
u32 insn = *(u32*)return_address;
|
||||
return (insn & 0x1) == 0;
|
||||
}
|
||||
|
||||
inline static unsigned int fpu_status(unsigned int status)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
inline static unsigned int fpu_status(unsigned int status) {
|
||||
unsigned int r = 0;
|
||||
|
||||
if (status & 0x20000000)
|
||||
r |= FP_TRAP_INVALID_OPERATION;
|
||||
if (status & 0x10000000)
|
||||
r |= FP_TRAP_OVERFLOW;
|
||||
if (status & 0x08000000)
|
||||
r |= FP_TRAP_UNDERFLOW;
|
||||
if (status & 0x04000000)
|
||||
r |= FP_TRAP_ZERO_DIVIDE;
|
||||
if (status & 0x02000000)
|
||||
r |= FP_TRAP_INEXACT;
|
||||
if (status & 0x20000000)
|
||||
r |= FP_TRAP_INVALID_OPERATION;
|
||||
if (status & 0x10000000)
|
||||
r |= FP_TRAP_OVERFLOW;
|
||||
if (status & 0x08000000)
|
||||
r |= FP_TRAP_UNDERFLOW;
|
||||
if (status & 0x04000000)
|
||||
r |= FP_TRAP_ZERO_DIVIDE;
|
||||
if (status & 0x02000000)
|
||||
r |= FP_TRAP_INEXACT;
|
||||
|
||||
return r;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Defined in assembly */
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
namespace factor
|
||||
{
|
||||
namespace factor {
|
||||
|
||||
#define FACTOR_CPU_STRING "x86.32"
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
namespace factor
|
||||
{
|
||||
namespace factor {
|
||||
|
||||
#define FACTOR_CPU_STRING "x86.64"
|
||||
|
||||
|
|
101
vm/cpu-x86.cpp
101
vm/cpu-x86.cpp
|
@ -1,65 +1,60 @@
|
|||
#include "master.hpp"
|
||||
|
||||
namespace factor
|
||||
{
|
||||
namespace factor {
|
||||
|
||||
void factor_vm::dispatch_signal_handler(cell *sp, cell *pc, cell handler)
|
||||
{
|
||||
if (!code->seg->in_segment_p(*pc) || *sp < ctx->callstack_seg->start + stack_reserved)
|
||||
{
|
||||
/* Fault came from foreign code or a callstack overflow, or we don't
|
||||
have enough callstack room to try the resumable handler. Cut the
|
||||
callstack down to the shallowest Factor stack frame that leaves room for
|
||||
the signal handler to do its thing, and launch the handler without going
|
||||
through the resumable subprimitive. */
|
||||
signal_resumable = false;
|
||||
void *frame_top = (void*)ctx->callstack_top;
|
||||
void factor_vm::dispatch_signal_handler(cell* sp, cell* pc, cell handler) {
|
||||
if (!code->seg->in_segment_p(*pc) ||
|
||||
*sp < ctx->callstack_seg->start + stack_reserved) {
|
||||
/* Fault came from foreign code or a callstack overflow, or we don't
|
||||
have enough callstack room to try the resumable handler. Cut the
|
||||
callstack down to the shallowest Factor stack frame that leaves room for
|
||||
the signal handler to do its thing, and launch the handler without going
|
||||
through the resumable subprimitive. */
|
||||
signal_resumable = false;
|
||||
void* frame_top = (void*)ctx->callstack_top;
|
||||
|
||||
while(frame_top < ctx->callstack_bottom
|
||||
&& (cell)frame_top < ctx->callstack_seg->start + stack_reserved)
|
||||
{
|
||||
frame_top = frame_predecessor(frame_top);
|
||||
}
|
||||
while (frame_top < ctx->callstack_bottom &&
|
||||
(cell) frame_top < ctx->callstack_seg->start + stack_reserved) {
|
||||
frame_top = frame_predecessor(frame_top);
|
||||
}
|
||||
|
||||
*sp = (cell)frame_top;
|
||||
ctx->callstack_top = frame_top;
|
||||
*pc = handler;
|
||||
} else {
|
||||
signal_resumable = true;
|
||||
// Fault came from Factor, and we've got a good callstack. Route the signal
|
||||
// handler through the resumable signal handler subprimitive.
|
||||
cell offset = *sp % 16;
|
||||
*sp = (cell) frame_top;
|
||||
ctx->callstack_top = frame_top;
|
||||
*pc = handler;
|
||||
} else {
|
||||
signal_resumable = true;
|
||||
// Fault came from Factor, and we've got a good callstack. Route the signal
|
||||
// handler through the resumable signal handler subprimitive.
|
||||
cell offset = *sp % 16;
|
||||
|
||||
signal_handler_addr = handler;
|
||||
tagged<word> handler_word = tagged<word>(special_objects[SIGNAL_HANDLER_WORD]);
|
||||
signal_handler_addr = handler;
|
||||
tagged<word> handler_word =
|
||||
tagged<word>(special_objects[SIGNAL_HANDLER_WORD]);
|
||||
|
||||
/* True stack frames are always 16-byte aligned. Leaf procedures
|
||||
that don't create a stack frame will be out of alignment by sizeof(cell)
|
||||
bytes. */
|
||||
/* On architectures with a link register we would have to check for leafness
|
||||
by matching the PC to a word. We should also use FRAME_RETURN_ADDRESS instead
|
||||
of assuming the stack pointer is the right place to put the resume address. */
|
||||
if (offset == 0)
|
||||
{
|
||||
cell newsp = *sp - sizeof(cell);
|
||||
*sp = newsp;
|
||||
*(cell*)newsp = *pc;
|
||||
}
|
||||
else if (offset == 16 - sizeof(cell))
|
||||
{
|
||||
// Make a fake frame for the leaf procedure
|
||||
FACTOR_ASSERT(code->code_block_for_address(*pc) != NULL);
|
||||
/* True stack frames are always 16-byte aligned. Leaf procedures
|
||||
that don't create a stack frame will be out of alignment by sizeof(cell)
|
||||
bytes. */
|
||||
/* On architectures with a link register we would have to check for leafness
|
||||
by matching the PC to a word. We should also use FRAME_RETURN_ADDRESS
|
||||
instead of assuming the stack pointer is the right place to put the
|
||||
resume address. */
|
||||
if (offset == 0) {
|
||||
cell newsp = *sp - sizeof(cell);
|
||||
*sp = newsp;
|
||||
*(cell*)newsp = *pc;
|
||||
} else if (offset == 16 - sizeof(cell)) {
|
||||
// Make a fake frame for the leaf procedure
|
||||
FACTOR_ASSERT(code->code_block_for_address(*pc) != NULL);
|
||||
|
||||
cell newsp = *sp - LEAF_FRAME_SIZE;
|
||||
*(cell*)newsp = *pc;
|
||||
*sp = newsp;
|
||||
handler_word = tagged<word>(special_objects[LEAF_SIGNAL_HANDLER_WORD]);
|
||||
}
|
||||
else
|
||||
FACTOR_ASSERT(false);
|
||||
cell newsp = *sp - LEAF_FRAME_SIZE;
|
||||
*(cell*)newsp = *pc;
|
||||
*sp = newsp;
|
||||
handler_word = tagged<word>(special_objects[LEAF_SIGNAL_HANDLER_WORD]);
|
||||
} else
|
||||
FACTOR_ASSERT(false);
|
||||
|
||||
*pc = (cell)handler_word->entry_point;
|
||||
}
|
||||
*pc = (cell) handler_word->entry_point;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
namespace factor
|
||||
{
|
||||
namespace factor {
|
||||
|
||||
inline static void* frame_return_address(void *frame_top)
|
||||
{
|
||||
return *(void**)frame_top;
|
||||
inline static void* frame_return_address(void* frame_top) {
|
||||
return *(void**)frame_top;
|
||||
}
|
||||
|
||||
inline static void set_frame_return_address(void *frame_top, void *return_address)
|
||||
{
|
||||
*(void**)frame_top = return_address;
|
||||
inline static void set_frame_return_address(void* frame_top,
|
||||
void* return_address) {
|
||||
*(void**)frame_top = return_address;
|
||||
}
|
||||
|
||||
#define CALLSTACK_BOTTOM(ctx) (void *)(ctx->callstack_seg->end - sizeof(cell) * 5)
|
||||
#define CALLSTACK_BOTTOM(ctx) \
|
||||
(void*)(ctx->callstack_seg->end - sizeof(cell) * 5)
|
||||
|
||||
inline static void flush_icache(cell start, cell len) {}
|
||||
|
||||
|
@ -28,56 +27,53 @@ static const fixnum xt_tail_pic_offset = 4 + 1;
|
|||
static const unsigned char call_opcode = 0xe8;
|
||||
static const unsigned char jmp_opcode = 0xe9;
|
||||
|
||||
inline static unsigned char call_site_opcode(cell return_address)
|
||||
{
|
||||
return *(unsigned char *)(return_address - 5);
|
||||
inline static unsigned char call_site_opcode(cell return_address) {
|
||||
return *(unsigned char*)(return_address - 5);
|
||||
}
|
||||
|
||||
inline static void check_call_site(cell return_address)
|
||||
{
|
||||
unsigned char opcode = call_site_opcode(return_address);
|
||||
FACTOR_ASSERT(opcode == call_opcode || opcode == jmp_opcode);
|
||||
(void)opcode; // suppress warning when compiling without assertions
|
||||
inline static void check_call_site(cell return_address) {
|
||||
unsigned char opcode = call_site_opcode(return_address);
|
||||
FACTOR_ASSERT(opcode == call_opcode || opcode == jmp_opcode);
|
||||
(void) opcode; // suppress warning when compiling without assertions
|
||||
}
|
||||
|
||||
inline static void *get_call_target(cell return_address)
|
||||
{
|
||||
check_call_site(return_address);
|
||||
return (void *)(*(int *)(return_address - 4) + return_address);
|
||||
inline static void* get_call_target(cell return_address) {
|
||||
check_call_site(return_address);
|
||||
return (void*)(*(int*)(return_address - 4) + return_address);
|
||||
}
|
||||
|
||||
inline static void set_call_target(cell return_address, void *target)
|
||||
{
|
||||
check_call_site(return_address);
|
||||
*(int *)(return_address - 4) = (u32)((cell)target - return_address);
|
||||
inline static void set_call_target(cell return_address, void* target) {
|
||||
check_call_site(return_address);
|
||||
*(int*)(return_address - 4) = (u32)((cell) target - return_address);
|
||||
}
|
||||
|
||||
inline static bool tail_call_site_p(cell return_address)
|
||||
{
|
||||
switch(call_site_opcode(return_address))
|
||||
{
|
||||
case jmp_opcode: return true;
|
||||
case call_opcode: return false;
|
||||
default: abort(); return false;
|
||||
}
|
||||
inline static bool tail_call_site_p(cell return_address) {
|
||||
switch (call_site_opcode(return_address)) {
|
||||
case jmp_opcode:
|
||||
return true;
|
||||
case call_opcode:
|
||||
return false;
|
||||
default:
|
||||
abort();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline static unsigned int fpu_status(unsigned int status)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
if (status & 0x01)
|
||||
r |= FP_TRAP_INVALID_OPERATION;
|
||||
if (status & 0x04)
|
||||
r |= FP_TRAP_ZERO_DIVIDE;
|
||||
if (status & 0x08)
|
||||
r |= FP_TRAP_OVERFLOW;
|
||||
if (status & 0x10)
|
||||
r |= FP_TRAP_UNDERFLOW;
|
||||
if (status & 0x20)
|
||||
r |= FP_TRAP_INEXACT;
|
||||
inline static unsigned int fpu_status(unsigned int status) {
|
||||
unsigned int r = 0;
|
||||
|
||||
return r;
|
||||
if (status & 0x01)
|
||||
r |= FP_TRAP_INVALID_OPERATION;
|
||||
if (status & 0x04)
|
||||
r |= FP_TRAP_ZERO_DIVIDE;
|
||||
if (status & 0x08)
|
||||
r |= FP_TRAP_OVERFLOW;
|
||||
if (status & 0x10)
|
||||
r |= FP_TRAP_UNDERFLOW;
|
||||
if (status & 0x20)
|
||||
r |= FP_TRAP_INEXACT;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue