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 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 #ifdef FACTOR_64
#define FACTOR_CPU_STRING "ppc.64" #define FACTOR_CPU_STRING "ppc.64"
@ -7,7 +6,7 @@ namespace factor
#define FACTOR_CPU_STRING "ppc.32" #define FACTOR_CPU_STRING "ppc.32"
#endif #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: /* In the instruction sequence:
@ -18,9 +17,8 @@ namespace factor
the branch is one instruction. */ the branch is one instruction. */
static const fixnum xt_tail_pic_offset = 4; static const fixnum xt_tail_pic_offset = 4;
inline static void check_call_site(cell return_address) inline static void check_call_site(cell return_address) {
{ u32 insn = *(u32*)return_address;
u32 insn = *(u32 *)return_address;
/* Check that absolute bit is 0 */ /* Check that absolute bit is 0 */
FACTOR_ASSERT((insn & 0x2) == 0x0); FACTOR_ASSERT((insn & 0x2) == 0x0);
/* Check that instruction is branch */ /* Check that instruction is branch */
@ -29,41 +27,39 @@ inline static void check_call_site(cell return_address)
static const u32 b_mask = 0x3fffffc; static const u32 b_mask = 0x3fffffc;
inline static void *get_call_target(cell return_address) inline static void* get_call_target(cell return_address) {
{
return_address -= 4; return_address -= 4;
check_call_site(return_address); check_call_site(return_address);
u32 insn = *(u32 *)return_address; u32 insn = *(u32*)return_address;
u32 unsigned_addr = (insn & b_mask); u32 unsigned_addr = (insn & b_mask);
s32 signed_addr = (s32)(unsigned_addr << 6) >> 6; s32 signed_addr = (s32)(unsigned_addr << 6) >> 6;
return (void *)(signed_addr + return_address); return (void*)(signed_addr + return_address);
} }
inline static void set_call_target(cell return_address, void *target) inline static void set_call_target(cell return_address, void* target) {
{
return_address -= 4; return_address -= 4;
check_call_site(return_address); check_call_site(return_address);
u32 insn = *(u32 *)return_address; u32 insn = *(u32*)return_address;
fixnum relative_address = ((cell)target - return_address); fixnum relative_address = ((cell) target - return_address);
insn = ((insn & ~b_mask) | (relative_address & b_mask)); insn = ((insn & ~b_mask) | (relative_address & b_mask));
*(u32 *)return_address = insn; *(u32*)return_address = insn;
/* Flush the cache line containing the call we just patched */ /* Flush the cache line containing the call we just patched */
__asm__ __volatile__ ("icbi 0, %0\n" "sync\n"::"r" (return_address):); __asm__ __volatile__("icbi 0, %0\n"
"sync\n" ::"r"(return_address)
:);
} }
inline static bool tail_call_site_p(cell return_address) inline static bool tail_call_site_p(cell return_address) {
{
return_address -= 4; return_address -= 4;
u32 insn = *(u32 *)return_address; u32 insn = *(u32*)return_address;
return (insn & 0x1) == 0; return (insn & 0x1) == 0;
} }
inline static unsigned int fpu_status(unsigned int status) inline static unsigned int fpu_status(unsigned int status) {
{
unsigned int r = 0; unsigned int r = 0;
if (status & 0x20000000) if (status & 0x20000000)

View File

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

View File

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

View File

@ -1,27 +1,24 @@
#include "master.hpp" #include "master.hpp"
namespace factor namespace factor {
{
void factor_vm::dispatch_signal_handler(cell *sp, cell *pc, cell handler) void factor_vm::dispatch_signal_handler(cell* sp, cell* pc, cell handler) {
{ if (!code->seg->in_segment_p(*pc) ||
if (!code->seg->in_segment_p(*pc) || *sp < ctx->callstack_seg->start + stack_reserved) *sp < ctx->callstack_seg->start + stack_reserved) {
{
/* Fault came from foreign code or a callstack overflow, or we don't /* Fault came from foreign code or a callstack overflow, or we don't
have enough callstack room to try the resumable handler. Cut the have enough callstack room to try the resumable handler. Cut the
callstack down to the shallowest Factor stack frame that leaves room for 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 the signal handler to do its thing, and launch the handler without going
through the resumable subprimitive. */ through the resumable subprimitive. */
signal_resumable = false; signal_resumable = false;
void *frame_top = (void*)ctx->callstack_top; void* frame_top = (void*)ctx->callstack_top;
while(frame_top < ctx->callstack_bottom while (frame_top < ctx->callstack_bottom &&
&& (cell)frame_top < ctx->callstack_seg->start + stack_reserved) (cell) frame_top < ctx->callstack_seg->start + stack_reserved) {
{
frame_top = frame_predecessor(frame_top); frame_top = frame_predecessor(frame_top);
} }
*sp = (cell)frame_top; *sp = (cell) frame_top;
ctx->callstack_top = frame_top; ctx->callstack_top = frame_top;
*pc = handler; *pc = handler;
} else { } else {
@ -31,22 +28,21 @@ void factor_vm::dispatch_signal_handler(cell *sp, cell *pc, cell handler)
cell offset = *sp % 16; cell offset = *sp % 16;
signal_handler_addr = handler; signal_handler_addr = handler;
tagged<word> handler_word = tagged<word>(special_objects[SIGNAL_HANDLER_WORD]); tagged<word> handler_word =
tagged<word>(special_objects[SIGNAL_HANDLER_WORD]);
/* True stack frames are always 16-byte aligned. Leaf procedures /* 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) that don't create a stack frame will be out of alignment by sizeof(cell)
bytes. */ bytes. */
/* On architectures with a link register we would have to check for leafness /* 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 by matching the PC to a word. We should also use FRAME_RETURN_ADDRESS
of assuming the stack pointer is the right place to put the resume address. */ instead of assuming the stack pointer is the right place to put the
if (offset == 0) resume address. */
{ if (offset == 0) {
cell newsp = *sp - sizeof(cell); cell newsp = *sp - sizeof(cell);
*sp = newsp; *sp = newsp;
*(cell*)newsp = *pc; *(cell*)newsp = *pc;
} } else if (offset == 16 - sizeof(cell)) {
else if (offset == 16 - sizeof(cell))
{
// Make a fake frame for the leaf procedure // Make a fake frame for the leaf procedure
FACTOR_ASSERT(code->code_block_for_address(*pc) != NULL); FACTOR_ASSERT(code->code_block_for_address(*pc) != NULL);
@ -54,11 +50,10 @@ void factor_vm::dispatch_signal_handler(cell *sp, cell *pc, cell handler)
*(cell*)newsp = *pc; *(cell*)newsp = *pc;
*sp = newsp; *sp = newsp;
handler_word = tagged<word>(special_objects[LEAF_SIGNAL_HANDLER_WORD]); handler_word = tagged<word>(special_objects[LEAF_SIGNAL_HANDLER_WORD]);
} } else
else
FACTOR_ASSERT(false); 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) inline static void* frame_return_address(void* frame_top) {
{
return *(void**)frame_top; return *(void**)frame_top;
} }
inline static void set_frame_return_address(void *frame_top, void *return_address) inline static void set_frame_return_address(void* frame_top,
{ void* return_address) {
*(void**)frame_top = 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) {} inline static void flush_icache(cell start, cell len) {}
@ -28,42 +27,39 @@ static const fixnum xt_tail_pic_offset = 4 + 1;
static const unsigned char call_opcode = 0xe8; static const unsigned char call_opcode = 0xe8;
static const unsigned char jmp_opcode = 0xe9; static const unsigned char jmp_opcode = 0xe9;
inline static unsigned char call_site_opcode(cell return_address) inline static unsigned char call_site_opcode(cell return_address) {
{ return *(unsigned char*)(return_address - 5);
return *(unsigned char *)(return_address - 5);
} }
inline static void check_call_site(cell return_address) inline static void check_call_site(cell return_address) {
{
unsigned char opcode = call_site_opcode(return_address); unsigned char opcode = call_site_opcode(return_address);
FACTOR_ASSERT(opcode == call_opcode || opcode == jmp_opcode); FACTOR_ASSERT(opcode == call_opcode || opcode == jmp_opcode);
(void)opcode; // suppress warning when compiling without assertions (void) opcode; // suppress warning when compiling without assertions
} }
inline static void *get_call_target(cell return_address) inline static void* get_call_target(cell return_address) {
{
check_call_site(return_address); check_call_site(return_address);
return (void *)(*(int *)(return_address - 4) + return_address); return (void*)(*(int*)(return_address - 4) + return_address);
} }
inline static void set_call_target(cell return_address, void *target) inline static void set_call_target(cell return_address, void* target) {
{
check_call_site(return_address); check_call_site(return_address);
*(int *)(return_address - 4) = (u32)((cell)target - return_address); *(int*)(return_address - 4) = (u32)((cell) target - return_address);
} }
inline static bool tail_call_site_p(cell return_address) inline static bool tail_call_site_p(cell return_address) {
{ switch (call_site_opcode(return_address)) {
switch(call_site_opcode(return_address)) case jmp_opcode:
{ return true;
case jmp_opcode: return true; case call_opcode:
case call_opcode: return false; return false;
default: abort(); return false; default:
abort();
return false;
} }
} }
inline static unsigned int fpu_status(unsigned int status) inline static unsigned int fpu_status(unsigned int status) {
{
unsigned int r = 0; unsigned int r = 0;
if (status & 0x01) if (status & 0x01)