Register access (dynamic and static) wired up.
This commit is contained in:
parent
e5d867a92f
commit
d8cc9fb0b4
|
@ -26,6 +26,8 @@ public:
|
||||||
Backend(runtime::Runtime* runtime);
|
Backend(runtime::Runtime* runtime);
|
||||||
virtual ~Backend();
|
virtual ~Backend();
|
||||||
|
|
||||||
|
runtime::Runtime* runtime() const { return runtime_; }
|
||||||
|
|
||||||
virtual int Initialize();
|
virtual int Initialize();
|
||||||
|
|
||||||
virtual void* AllocThreadData();
|
virtual void* AllocThreadData();
|
||||||
|
|
|
@ -9,11 +9,13 @@
|
||||||
|
|
||||||
#include <alloy/backend/ivm/ivm_assembler.h>
|
#include <alloy/backend/ivm/ivm_assembler.h>
|
||||||
|
|
||||||
|
#include <alloy/backend/backend.h>
|
||||||
#include <alloy/backend/tracing.h>
|
#include <alloy/backend/tracing.h>
|
||||||
#include <alloy/backend/ivm/ivm_intcode.h>
|
#include <alloy/backend/ivm/ivm_intcode.h>
|
||||||
#include <alloy/backend/ivm/ivm_function.h>
|
#include <alloy/backend/ivm/ivm_function.h>
|
||||||
#include <alloy/hir/function_builder.h>
|
#include <alloy/hir/function_builder.h>
|
||||||
#include <alloy/hir/label.h>
|
#include <alloy/hir/label.h>
|
||||||
|
#include <alloy/runtime/runtime.h>
|
||||||
|
|
||||||
using namespace alloy;
|
using namespace alloy;
|
||||||
using namespace alloy::backend;
|
using namespace alloy::backend;
|
||||||
|
@ -55,6 +57,7 @@ int IVMAssembler::Assemble(
|
||||||
IVMFunction* fn = new IVMFunction(symbol_info);
|
IVMFunction* fn = new IVMFunction(symbol_info);
|
||||||
|
|
||||||
TranslationContext ctx;
|
TranslationContext ctx;
|
||||||
|
ctx.access_callbacks = backend_->runtime()->access_callbacks();
|
||||||
ctx.register_count = 0;
|
ctx.register_count = 0;
|
||||||
ctx.intcode_count = 0;
|
ctx.intcode_count = 0;
|
||||||
ctx.intcode_arena = &intcode_arena_;
|
ctx.intcode_arena = &intcode_arena_;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <alloy/backend/ivm/ivm_function.h>
|
#include <alloy/backend/ivm/ivm_function.h>
|
||||||
|
|
||||||
#include <alloy/backend/tracing.h>
|
#include <alloy/backend/tracing.h>
|
||||||
|
#include <alloy/runtime/runtime.h>
|
||||||
#include <alloy/runtime/thread_state.h>
|
#include <alloy/runtime/thread_state.h>
|
||||||
|
|
||||||
using namespace alloy;
|
using namespace alloy;
|
||||||
|
@ -43,6 +44,7 @@ int IVMFunction::CallImpl(ThreadState* thread_state) {
|
||||||
ics.context = (uint8_t*)thread_state->raw_context();
|
ics.context = (uint8_t*)thread_state->raw_context();
|
||||||
ics.membase = thread_state->memory()->membase();
|
ics.membase = thread_state->memory()->membase();
|
||||||
ics.did_carry = 0;
|
ics.did_carry = 0;
|
||||||
|
ics.access_callbacks = thread_state->runtime()->access_callbacks();
|
||||||
ics.thread_state = thread_state;
|
ics.thread_state = thread_state;
|
||||||
ics.return_address = 0xBEBEBEBE;
|
ics.return_address = 0xBEBEBEBE;
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,210 @@ int DispatchToC(TranslationContext& ctx, Instr* i, IntCodeFn fn) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t IntCode_LOAD_REGISTER_I8(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = (RegisterAccessCallbacks*)
|
||||||
|
(i->src2_reg | ((uint64_t)i->src3_reg << 32));
|
||||||
|
ics.rf[i->dest_reg].i8 = (int8_t)cbs->read(cbs->context, address);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
uint32_t IntCode_LOAD_REGISTER_I16(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = (RegisterAccessCallbacks*)
|
||||||
|
(i->src2_reg | ((uint64_t)i->src3_reg << 32));
|
||||||
|
ics.rf[i->dest_reg].i16 = (int16_t)cbs->read(cbs->context, address);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
uint32_t IntCode_LOAD_REGISTER_I32(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = (RegisterAccessCallbacks*)
|
||||||
|
(i->src2_reg | ((uint64_t)i->src3_reg << 32));
|
||||||
|
ics.rf[i->dest_reg].i32 = (int32_t)cbs->read(cbs->context, address);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
uint32_t IntCode_LOAD_REGISTER_I64(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = (RegisterAccessCallbacks*)
|
||||||
|
(i->src2_reg | ((uint64_t)i->src3_reg << 32));
|
||||||
|
ics.rf[i->dest_reg].i64 = (int64_t)cbs->read(cbs->context, address);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
int DispatchRegisterRead(
|
||||||
|
TranslationContext& ctx, Instr* i, RegisterAccessCallbacks* cbs) {
|
||||||
|
static IntCodeFn fns[] = {
|
||||||
|
IntCode_LOAD_REGISTER_I8,
|
||||||
|
IntCode_LOAD_REGISTER_I16,
|
||||||
|
IntCode_LOAD_REGISTER_I32,
|
||||||
|
IntCode_LOAD_REGISTER_I64,
|
||||||
|
IntCode_INVALID_TYPE,
|
||||||
|
IntCode_INVALID_TYPE,
|
||||||
|
IntCode_INVALID_TYPE,
|
||||||
|
};
|
||||||
|
IntCodeFn fn = fns[i->dest->type];
|
||||||
|
XEASSERT(fn != IntCode_INVALID_TYPE);
|
||||||
|
uint32_t dest_reg = AllocDynamicRegister(ctx, i->dest);
|
||||||
|
uint32_t src1_reg = AllocOpRegister(ctx, OPCODE_SIG_TYPE_V, &i->src1);
|
||||||
|
ctx.intcode_count++;
|
||||||
|
IntCode* ic = ctx.intcode_arena->Alloc<IntCode>();
|
||||||
|
ic->intcode_fn = fn;
|
||||||
|
ic->flags = i->flags;
|
||||||
|
ic->dest_reg = dest_reg;
|
||||||
|
ic->src1_reg = src1_reg;
|
||||||
|
ic->src2_reg = (uint32_t)((uint64_t)cbs);
|
||||||
|
ic->src3_reg = (uint32_t)(((uint64_t)cbs) >> 32);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint32_t IntCode_LOAD_REGISTER_I8_DYNAMIC(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = ics.access_callbacks;
|
||||||
|
while (cbs) {
|
||||||
|
if (cbs->handles(cbs->context, address)) {
|
||||||
|
ics.rf[i->dest_reg].i8 = (int8_t)cbs->read(cbs->context, address);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
cbs = cbs->next;
|
||||||
|
}
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
uint32_t IntCode_LOAD_REGISTER_I16_DYNAMIC(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = ics.access_callbacks;
|
||||||
|
while (cbs) {
|
||||||
|
if (cbs->handles(cbs->context, address)) {
|
||||||
|
ics.rf[i->dest_reg].i16 = (int16_t)cbs->read(cbs->context, address);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
cbs = cbs->next;
|
||||||
|
}
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
uint32_t IntCode_LOAD_REGISTER_I32_DYNAMIC(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = ics.access_callbacks;
|
||||||
|
while (cbs) {
|
||||||
|
if (cbs->handles(cbs->context, address)) {
|
||||||
|
ics.rf[i->dest_reg].i32 = (int32_t)cbs->read(cbs->context, address);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
cbs = cbs->next;
|
||||||
|
}
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
uint32_t IntCode_LOAD_REGISTER_I64_DYNAMIC(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = ics.access_callbacks;
|
||||||
|
while (cbs) {
|
||||||
|
if (cbs->handles(cbs->context, address)) {
|
||||||
|
ics.rf[i->dest_reg].i64 = (int64_t)cbs->read(cbs->context, address);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
cbs = cbs->next;
|
||||||
|
}
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t IntCode_STORE_REGISTER_I8(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = (RegisterAccessCallbacks*)
|
||||||
|
(i->src3_reg | ((uint64_t)i->dest_reg << 32));
|
||||||
|
cbs->write(cbs->context, address, ics.rf[i->src2_reg].i64 & 0xFF);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
uint32_t IntCode_STORE_REGISTER_I16(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = (RegisterAccessCallbacks*)
|
||||||
|
(i->src3_reg | ((uint64_t)i->dest_reg << 32));
|
||||||
|
cbs->write(cbs->context, address, ics.rf[i->src2_reg].i64 & 0xFFFF);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
uint32_t IntCode_STORE_REGISTER_I32(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = (RegisterAccessCallbacks*)
|
||||||
|
(i->src3_reg | ((uint64_t)i->dest_reg << 32));
|
||||||
|
cbs->write(cbs->context, address, ics.rf[i->src2_reg].i64 & 0xFFFFFFFF);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
uint32_t IntCode_STORE_REGISTER_I64(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = (RegisterAccessCallbacks*)
|
||||||
|
(i->src3_reg | ((uint64_t)i->dest_reg << 32));
|
||||||
|
cbs->write(cbs->context, address, ics.rf[i->src2_reg].i64);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
int DispatchRegisterWrite(
|
||||||
|
TranslationContext& ctx, Instr* i, RegisterAccessCallbacks* cbs) {
|
||||||
|
static IntCodeFn fns[] = {
|
||||||
|
IntCode_STORE_REGISTER_I8,
|
||||||
|
IntCode_STORE_REGISTER_I16,
|
||||||
|
IntCode_STORE_REGISTER_I32,
|
||||||
|
IntCode_STORE_REGISTER_I64,
|
||||||
|
IntCode_INVALID_TYPE,
|
||||||
|
IntCode_INVALID_TYPE,
|
||||||
|
IntCode_INVALID_TYPE,
|
||||||
|
};
|
||||||
|
IntCodeFn fn = fns[i->src2.value->type];
|
||||||
|
XEASSERT(fn != IntCode_INVALID_TYPE);
|
||||||
|
uint32_t src1_reg = AllocOpRegister(ctx, OPCODE_SIG_TYPE_V, &i->src1);
|
||||||
|
uint32_t src2_reg = AllocOpRegister(ctx, OPCODE_SIG_TYPE_V, &i->src2);
|
||||||
|
ctx.intcode_count++;
|
||||||
|
IntCode* ic = ctx.intcode_arena->Alloc<IntCode>();
|
||||||
|
ic->intcode_fn = fn;
|
||||||
|
ic->flags = i->flags;
|
||||||
|
ic->dest_reg = (uint32_t)(((uint64_t)cbs) >> 32);
|
||||||
|
ic->src1_reg = src1_reg;
|
||||||
|
ic->src2_reg = src2_reg;
|
||||||
|
ic->src3_reg = (uint32_t)((uint64_t)cbs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint32_t IntCode_STORE_REGISTER_I8_DYNAMIC(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = ics.access_callbacks;
|
||||||
|
while (cbs) {
|
||||||
|
if (cbs->handles(cbs->context, address)) {
|
||||||
|
cbs->write(cbs->context, address, ics.rf[i->src2_reg].i64 & 0xFF);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
cbs = cbs->next;
|
||||||
|
}
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
uint32_t IntCode_STORE_REGISTER_I16_DYNAMIC(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = ics.access_callbacks;
|
||||||
|
while (cbs) {
|
||||||
|
if (cbs->handles(cbs->context, address)) {
|
||||||
|
cbs->write(cbs->context, address, ics.rf[i->src2_reg].i64 & 0xFFFF);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
cbs = cbs->next;
|
||||||
|
}
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
uint32_t IntCode_STORE_REGISTER_I32_DYNAMIC(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = ics.access_callbacks;
|
||||||
|
while (cbs) {
|
||||||
|
if (cbs->handles(cbs->context, address)) {
|
||||||
|
cbs->write(cbs->context, address, ics.rf[i->src2_reg].i64 & 0xFFFFFFFF);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
cbs = cbs->next;
|
||||||
|
}
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
uint32_t IntCode_STORE_REGISTER_I64_DYNAMIC(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint64_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
RegisterAccessCallbacks* cbs = ics.access_callbacks;
|
||||||
|
while (cbs) {
|
||||||
|
if (cbs->handles(cbs->context, address)) {
|
||||||
|
cbs->write(cbs->context, address, ics.rf[i->src2_reg].i64);
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
cbs = cbs->next;
|
||||||
|
}
|
||||||
|
return IA_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t IntCode_INVALID(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_INVALID(IntCodeState& ics, const IntCode* i) {
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
|
@ -928,52 +1132,70 @@ int Translate_STORE_CONTEXT(TranslationContext& ctx, Instr* i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t IntCode_LOAD_I8(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_LOAD_I8(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
if ((address & 0xFF000000) == 0x7F000000) {
|
||||||
|
return IntCode_LOAD_REGISTER_I8_DYNAMIC(ics, i);
|
||||||
|
}
|
||||||
DPRINT("%d (%X) = load.i8 %.8X\n",
|
DPRINT("%d (%X) = load.i8 %.8X\n",
|
||||||
*((int8_t*)(ics.membase + ics.rf[i->src1_reg].u32)),
|
*((int8_t*)(ics.membase + address)),
|
||||||
*((uint8_t*)(ics.membase + ics.rf[i->src1_reg].u32)),
|
*((uint8_t*)(ics.membase + address)),
|
||||||
ics.rf[i->src1_reg].u32);
|
address);
|
||||||
DFLUSH();
|
DFLUSH();
|
||||||
ics.rf[i->dest_reg].i8 = *((int8_t*)(ics.membase + ics.rf[i->src1_reg].u32));
|
ics.rf[i->dest_reg].i8 = *((int8_t*)(ics.membase + address));
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
uint32_t IntCode_LOAD_I16(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_LOAD_I16(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
if ((address & 0xFF000000) == 0x7F000000) {
|
||||||
|
return IntCode_LOAD_REGISTER_I16_DYNAMIC(ics, i);
|
||||||
|
}
|
||||||
DPRINT("%d (%X) = load.i16 %.8X\n",
|
DPRINT("%d (%X) = load.i16 %.8X\n",
|
||||||
*((int16_t*)(ics.membase + ics.rf[i->src1_reg].u32)),
|
*((int16_t*)(ics.membase + address)),
|
||||||
*((uint16_t*)(ics.membase + ics.rf[i->src1_reg].u32)),
|
*((uint16_t*)(ics.membase + address)),
|
||||||
ics.rf[i->src1_reg].u32);
|
address);
|
||||||
DFLUSH();
|
DFLUSH();
|
||||||
ics.rf[i->dest_reg].i16 = *((int16_t*)(ics.membase + ics.rf[i->src1_reg].u32));
|
ics.rf[i->dest_reg].i16 = *((int16_t*)(ics.membase + address));
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
uint32_t IntCode_LOAD_I32(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_LOAD_I32(IntCodeState& ics, const IntCode* i) {
|
||||||
DFLUSH();
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
if ((address & 0xFF000000) == 0x7F000000) {
|
||||||
|
return IntCode_LOAD_REGISTER_I32_DYNAMIC(ics, i);
|
||||||
|
}
|
||||||
DPRINT("%d (%X) = load.i32 %.8X\n",
|
DPRINT("%d (%X) = load.i32 %.8X\n",
|
||||||
*((int32_t*)(ics.membase + ics.rf[i->src1_reg].u32)),
|
*((int32_t*)(ics.membase + address)),
|
||||||
*((uint32_t*)(ics.membase + ics.rf[i->src1_reg].u32)),
|
*((uint32_t*)(ics.membase + address)),
|
||||||
ics.rf[i->src1_reg].u32);
|
address);
|
||||||
DFLUSH();
|
DFLUSH();
|
||||||
ics.rf[i->dest_reg].i32 = *((int32_t*)(ics.membase + ics.rf[i->src1_reg].u32));
|
ics.rf[i->dest_reg].i32 = *((int32_t*)(ics.membase + address));
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
uint32_t IntCode_LOAD_I64(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_LOAD_I64(IntCodeState& ics, const IntCode* i) {
|
||||||
DPRINT("%d (%X) = load.i64 %.8X\n",
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
*((int64_t*)(ics.membase + ics.rf[i->src1_reg].u32)),
|
if ((address & 0xFF000000) == 0x7F000000) {
|
||||||
*((uint64_t*)(ics.membase + ics.rf[i->src1_reg].u32)),
|
return IntCode_LOAD_REGISTER_I64(ics, i);
|
||||||
ics.rf[i->src1_reg].u32);
|
}
|
||||||
|
DPRINT("%lld (%llX) = load.i64 %.8X\n",
|
||||||
|
*((int64_t*)(ics.membase + address)),
|
||||||
|
*((uint64_t*)(ics.membase + address)),
|
||||||
|
address);
|
||||||
DFLUSH();
|
DFLUSH();
|
||||||
ics.rf[i->dest_reg].i64 = *((int64_t*)(ics.membase + ics.rf[i->src1_reg].u32));
|
ics.rf[i->dest_reg].i64 = *((int64_t*)(ics.membase + address));
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
uint32_t IntCode_LOAD_F32(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_LOAD_F32(IntCodeState& ics, const IntCode* i) {
|
||||||
ics.rf[i->dest_reg].f32 = *((float*)(ics.membase + ics.rf[i->src1_reg].u32));
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
ics.rf[i->dest_reg].f32 = *((float*)(ics.membase + address));
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
uint32_t IntCode_LOAD_F64(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_LOAD_F64(IntCodeState& ics, const IntCode* i) {
|
||||||
ics.rf[i->dest_reg].f64 = *((double*)(ics.membase + ics.rf[i->src1_reg].u32));
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
ics.rf[i->dest_reg].f64 = *((double*)(ics.membase + address));
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
uint32_t IntCode_LOAD_V128(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_LOAD_V128(IntCodeState& ics, const IntCode* i) {
|
||||||
ics.rf[i->dest_reg].v128 = *((vec128_t*)(ics.membase + (ics.rf[i->src1_reg].u32 & ~0xF)));
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
ics.rf[i->dest_reg].v128 = *((vec128_t*)(ics.membase + (address & ~0xF)));
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
int Translate_LOAD(TranslationContext& ctx, Instr* i) {
|
int Translate_LOAD(TranslationContext& ctx, Instr* i) {
|
||||||
|
@ -986,47 +1208,79 @@ int Translate_LOAD(TranslationContext& ctx, Instr* i) {
|
||||||
IntCode_LOAD_F64,
|
IntCode_LOAD_F64,
|
||||||
IntCode_LOAD_V128,
|
IntCode_LOAD_V128,
|
||||||
};
|
};
|
||||||
|
if (i->src1.value->IsConstant()) {
|
||||||
|
// Constant address - check register access callbacks.
|
||||||
|
// NOTE: we still will likely want to check on access in debug mode, as
|
||||||
|
// constant propagation may not have happened.
|
||||||
|
uint64_t address = i->src1.value->AsUint64();
|
||||||
|
RegisterAccessCallbacks* cbs = ctx.access_callbacks;
|
||||||
|
while (cbs) {
|
||||||
|
if (cbs->handles(cbs->context, address)) {
|
||||||
|
return DispatchRegisterRead(ctx, i, cbs);
|
||||||
|
}
|
||||||
|
cbs = cbs->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
return DispatchToC(ctx, i, fns[i->dest->type]);
|
return DispatchToC(ctx, i, fns[i->dest->type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t IntCode_STORE_I8(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_STORE_I8(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
if ((address & 0xFF000000) == 0x7F000000) {
|
||||||
|
return IntCode_STORE_REGISTER_I8_DYNAMIC(ics, i);
|
||||||
|
}
|
||||||
DPRINT("store.i8 %.8X = %d (%X)\n",
|
DPRINT("store.i8 %.8X = %d (%X)\n",
|
||||||
ics.rf[i->src1_reg].u32, ics.rf[i->src2_reg].i8, ics.rf[i->src2_reg].i8);
|
address, ics.rf[i->src2_reg].i8, ics.rf[i->src2_reg].i8);
|
||||||
DFLUSH();
|
DFLUSH();
|
||||||
*((int8_t*)(ics.membase + ics.rf[i->src1_reg].u32)) = ics.rf[i->src2_reg].i8;
|
*((int8_t*)(ics.membase + address)) = ics.rf[i->src2_reg].i8;
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
uint32_t IntCode_STORE_I16(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_STORE_I16(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
if ((address & 0xFF000000) == 0x7F000000) {
|
||||||
|
return IntCode_STORE_REGISTER_I16_DYNAMIC(ics, i);
|
||||||
|
}
|
||||||
DPRINT("store.i16 %.8X = %d (%X)\n",
|
DPRINT("store.i16 %.8X = %d (%X)\n",
|
||||||
ics.rf[i->src1_reg].u32, ics.rf[i->src2_reg].i16, ics.rf[i->src2_reg].i16);
|
address, ics.rf[i->src2_reg].i16, ics.rf[i->src2_reg].i16);
|
||||||
DFLUSH();
|
DFLUSH();
|
||||||
*((int16_t*)(ics.membase + ics.rf[i->src1_reg].u32)) = ics.rf[i->src2_reg].i16;
|
*((int16_t*)(ics.membase + address)) = ics.rf[i->src2_reg].i16;
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
uint32_t IntCode_STORE_I32(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_STORE_I32(IntCodeState& ics, const IntCode* i) {
|
||||||
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
if ((address & 0xFF000000) == 0x7F000000) {
|
||||||
|
return IntCode_STORE_REGISTER_I32_DYNAMIC(ics, i);
|
||||||
|
}
|
||||||
DPRINT("store.i32 %.8X = %d (%X)\n",
|
DPRINT("store.i32 %.8X = %d (%X)\n",
|
||||||
ics.rf[i->src1_reg].u32, ics.rf[i->src2_reg].i32, ics.rf[i->src2_reg].i32);
|
address, ics.rf[i->src2_reg].i32, ics.rf[i->src2_reg].i32);
|
||||||
DFLUSH();
|
DFLUSH();
|
||||||
*((int32_t*)(ics.membase + ics.rf[i->src1_reg].u32)) = ics.rf[i->src2_reg].i32;
|
*((int32_t*)(ics.membase + address)) = ics.rf[i->src2_reg].i32;
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
uint32_t IntCode_STORE_I64(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_STORE_I64(IntCodeState& ics, const IntCode* i) {
|
||||||
DPRINT("store.i64 %.8X = %d (%X)\n",
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
ics.rf[i->src1_reg].u32, ics.rf[i->src2_reg].i64, ics.rf[i->src2_reg].i64);
|
if ((address & 0xFF000000) == 0x7F000000) {
|
||||||
|
return IntCode_STORE_REGISTER_I64_DYNAMIC(ics, i);
|
||||||
|
}
|
||||||
|
DPRINT("store.i64 %.8X = %lld (%llX)\n",
|
||||||
|
address, ics.rf[i->src2_reg].i64, ics.rf[i->src2_reg].i64);
|
||||||
DFLUSH();
|
DFLUSH();
|
||||||
*((int64_t*)(ics.membase + ics.rf[i->src1_reg].u32)) = ics.rf[i->src2_reg].i64;
|
*((int64_t*)(ics.membase + address)) = ics.rf[i->src2_reg].i64;
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
uint32_t IntCode_STORE_F32(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_STORE_F32(IntCodeState& ics, const IntCode* i) {
|
||||||
*((float*)(ics.membase + ics.rf[i->src1_reg].u32)) = ics.rf[i->src2_reg].f32;
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
*((float*)(ics.membase + address)) = ics.rf[i->src2_reg].f32;
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
uint32_t IntCode_STORE_F64(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_STORE_F64(IntCodeState& ics, const IntCode* i) {
|
||||||
*((double*)(ics.membase + ics.rf[i->src1_reg].u32)) = ics.rf[i->src2_reg].f64;
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
*((double*)(ics.membase + address)) = ics.rf[i->src2_reg].f64;
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
uint32_t IntCode_STORE_V128(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_STORE_V128(IntCodeState& ics, const IntCode* i) {
|
||||||
*((vec128_t*)(ics.membase + (ics.rf[i->src1_reg].u32 & ~0xF))) = ics.rf[i->src2_reg].v128;
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
*((vec128_t*)(ics.membase + (address & ~0xF))) = ics.rf[i->src2_reg].v128;
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
int Translate_STORE(TranslationContext& ctx, Instr* i) {
|
int Translate_STORE(TranslationContext& ctx, Instr* i) {
|
||||||
|
@ -1039,6 +1293,19 @@ int Translate_STORE(TranslationContext& ctx, Instr* i) {
|
||||||
IntCode_STORE_F64,
|
IntCode_STORE_F64,
|
||||||
IntCode_STORE_V128,
|
IntCode_STORE_V128,
|
||||||
};
|
};
|
||||||
|
if (i->src1.value->IsConstant()) {
|
||||||
|
// Constant address - check register access callbacks.
|
||||||
|
// NOTE: we still will likely want to check on access in debug mode, as
|
||||||
|
// constant propagation may not have happened.
|
||||||
|
uint64_t address = i->src1.value->AsUint64();
|
||||||
|
RegisterAccessCallbacks* cbs = ctx.access_callbacks;
|
||||||
|
while (cbs) {
|
||||||
|
if (cbs->handles(cbs->context, address)) {
|
||||||
|
return DispatchRegisterWrite(ctx, i, cbs);
|
||||||
|
}
|
||||||
|
cbs = cbs->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
return DispatchToC(ctx, i, fns[i->src2.value->type]);
|
return DispatchToC(ctx, i, fns[i->src2.value->type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <alloy/hir/instr.h>
|
#include <alloy/hir/instr.h>
|
||||||
#include <alloy/hir/opcodes.h>
|
#include <alloy/hir/opcodes.h>
|
||||||
|
#include <alloy/runtime/register_access.h>
|
||||||
|
|
||||||
namespace alloy { namespace runtime { class ThreadState; } }
|
namespace alloy { namespace runtime { class ThreadState; } }
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ typedef struct {
|
||||||
uint8_t* context;
|
uint8_t* context;
|
||||||
uint8_t* membase;
|
uint8_t* membase;
|
||||||
int8_t did_carry;
|
int8_t did_carry;
|
||||||
|
runtime::RegisterAccessCallbacks* access_callbacks;
|
||||||
runtime::ThreadState* thread_state;
|
runtime::ThreadState* thread_state;
|
||||||
uint64_t return_address;
|
uint64_t return_address;
|
||||||
} IntCodeState;
|
} IntCodeState;
|
||||||
|
@ -85,6 +87,8 @@ typedef struct LabelRef_s {
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
runtime::RegisterAccessCallbacks* access_callbacks;
|
||||||
|
|
||||||
uint32_t register_count;
|
uint32_t register_count;
|
||||||
size_t intcode_count;
|
size_t intcode_count;
|
||||||
Arena* intcode_arena;
|
Arena* intcode_arena;
|
||||||
|
|
|
@ -21,11 +21,13 @@ typedef uint64_t (*RegisterReadCallback)(void* context, uint64_t addr);
|
||||||
typedef void (*RegisterWriteCallback)(void* context, uint64_t addr,
|
typedef void (*RegisterWriteCallback)(void* context, uint64_t addr,
|
||||||
uint64_t value);
|
uint64_t value);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct RegisterAccessCallbacks_s {
|
||||||
void* context;
|
void* context;
|
||||||
RegisterHandlesCallback handles;
|
RegisterHandlesCallback handles;
|
||||||
RegisterReadCallback read;
|
RegisterReadCallback read;
|
||||||
RegisterWriteCallback write;
|
RegisterWriteCallback write;
|
||||||
|
|
||||||
|
RegisterAccessCallbacks_s* next;
|
||||||
} RegisterAccessCallbacks;
|
} RegisterAccessCallbacks;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,8 @@ DEFINE_string(runtime_backend, "any",
|
||||||
|
|
||||||
|
|
||||||
Runtime::Runtime(Memory* memory) :
|
Runtime::Runtime(Memory* memory) :
|
||||||
memory_(memory), backend_(0), frontend_(0) {
|
memory_(memory), backend_(0), frontend_(0),
|
||||||
|
access_callbacks_(0) {
|
||||||
tracing::Initialize();
|
tracing::Initialize();
|
||||||
modules_lock_ = AllocMutex(10000);
|
modules_lock_ = AllocMutex(10000);
|
||||||
}
|
}
|
||||||
|
@ -40,6 +41,14 @@ Runtime::~Runtime() {
|
||||||
UnlockMutex(modules_lock_);
|
UnlockMutex(modules_lock_);
|
||||||
FreeMutex(modules_lock_);
|
FreeMutex(modules_lock_);
|
||||||
|
|
||||||
|
RegisterAccessCallbacks* cbs = access_callbacks_;
|
||||||
|
while (cbs) {
|
||||||
|
RegisterAccessCallbacks* next = cbs->next;
|
||||||
|
delete cbs;
|
||||||
|
cbs = next;
|
||||||
|
}
|
||||||
|
access_callbacks_ = NULL;
|
||||||
|
|
||||||
delete frontend_;
|
delete frontend_;
|
||||||
delete backend_;
|
delete backend_;
|
||||||
|
|
||||||
|
@ -213,6 +222,10 @@ int Runtime::DemandFunction(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Runtime::AddRegisterAccessCallbacks(RegisterAccessCallbacks callbacks) {
|
void Runtime::AddRegisterAccessCallbacks(
|
||||||
//
|
const RegisterAccessCallbacks& callbacks) {
|
||||||
|
RegisterAccessCallbacks* cbs = new RegisterAccessCallbacks();
|
||||||
|
xe_copy_struct(cbs, &callbacks, sizeof(callbacks));
|
||||||
|
cbs->next = access_callbacks_;
|
||||||
|
access_callbacks_ = cbs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,9 @@ public:
|
||||||
Memory* memory() const { return memory_; }
|
Memory* memory() const { return memory_; }
|
||||||
frontend::Frontend* frontend() const { return frontend_; }
|
frontend::Frontend* frontend() const { return frontend_; }
|
||||||
backend::Backend* backend() const { return backend_; }
|
backend::Backend* backend() const { return backend_; }
|
||||||
|
RegisterAccessCallbacks* access_callbacks() const {
|
||||||
|
return access_callbacks_;
|
||||||
|
}
|
||||||
|
|
||||||
int Initialize(frontend::Frontend* frontend, backend::Backend* backend = 0);
|
int Initialize(frontend::Frontend* frontend, backend::Backend* backend = 0);
|
||||||
|
|
||||||
|
@ -41,7 +44,8 @@ public:
|
||||||
int LookupFunctionInfo(uint64_t address, FunctionInfo** out_symbol_info);
|
int LookupFunctionInfo(uint64_t address, FunctionInfo** out_symbol_info);
|
||||||
int ResolveFunction(uint64_t address, Function** out_function);
|
int ResolveFunction(uint64_t address, Function** out_function);
|
||||||
|
|
||||||
void AddRegisterAccessCallbacks(RegisterAccessCallbacks callbacks);
|
void AddRegisterAccessCallbacks(
|
||||||
|
const RegisterAccessCallbacks& callbacks);
|
||||||
|
|
||||||
//uint32_t CreateCallback(void (*callback)(void* data), void* data);
|
//uint32_t CreateCallback(void (*callback)(void* data), void* data);
|
||||||
|
|
||||||
|
@ -58,6 +62,8 @@ protected:
|
||||||
Mutex* modules_lock_;
|
Mutex* modules_lock_;
|
||||||
typedef std::vector<Module*> ModuleList;
|
typedef std::vector<Module*> ModuleList;
|
||||||
ModuleList modules_;
|
ModuleList modules_;
|
||||||
|
|
||||||
|
RegisterAccessCallbacks* access_callbacks_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue