VM: Refactor cpu-* to Factor style

db4
Erik Charlebois 2013-05-11 21:55:50 -04:00
parent 0cf7feba0b
commit fb34be6fa7
6 changed files with 139 additions and 155 deletions

View File

@ -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)
}

View File

@ -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 */

View File

@ -1,5 +1,4 @@
namespace factor
{
namespace factor {
#define FACTOR_CPU_STRING "x86.32"

View File

@ -1,5 +1,4 @@
namespace factor
{
namespace factor {
#define FACTOR_CPU_STRING "x86.64"

View File

@ -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;
}
}
}

View File

@ -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;
}
}