From d8cc9fb0b45ee3cbb3d5aa01492f6cc14dc63c5a Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sat, 7 Dec 2013 13:09:22 -0800 Subject: [PATCH] Register access (dynamic and static) wired up. --- src/alloy/backend/backend.h | 2 + src/alloy/backend/ivm/ivm_assembler.cc | 3 + src/alloy/backend/ivm/ivm_function.cc | 2 + src/alloy/backend/ivm/ivm_intcode.cc | 333 ++++++++++++++++++++++--- src/alloy/backend/ivm/ivm_intcode.h | 4 + src/alloy/runtime/register_access.h | 4 +- src/alloy/runtime/runtime.cc | 19 +- src/alloy/runtime/runtime.h | 8 +- 8 files changed, 337 insertions(+), 38 deletions(-) diff --git a/src/alloy/backend/backend.h b/src/alloy/backend/backend.h index 292195478..885844d3f 100644 --- a/src/alloy/backend/backend.h +++ b/src/alloy/backend/backend.h @@ -26,6 +26,8 @@ public: Backend(runtime::Runtime* runtime); virtual ~Backend(); + runtime::Runtime* runtime() const { return runtime_; } + virtual int Initialize(); virtual void* AllocThreadData(); diff --git a/src/alloy/backend/ivm/ivm_assembler.cc b/src/alloy/backend/ivm/ivm_assembler.cc index 3a39c9cb1..38a7d16bd 100644 --- a/src/alloy/backend/ivm/ivm_assembler.cc +++ b/src/alloy/backend/ivm/ivm_assembler.cc @@ -9,11 +9,13 @@ #include +#include #include #include #include #include #include +#include using namespace alloy; using namespace alloy::backend; @@ -55,6 +57,7 @@ int IVMAssembler::Assemble( IVMFunction* fn = new IVMFunction(symbol_info); TranslationContext ctx; + ctx.access_callbacks = backend_->runtime()->access_callbacks(); ctx.register_count = 0; ctx.intcode_count = 0; ctx.intcode_arena = &intcode_arena_; diff --git a/src/alloy/backend/ivm/ivm_function.cc b/src/alloy/backend/ivm/ivm_function.cc index 33fa4be1d..e4bcaca61 100644 --- a/src/alloy/backend/ivm/ivm_function.cc +++ b/src/alloy/backend/ivm/ivm_function.cc @@ -10,6 +10,7 @@ #include #include +#include #include using namespace alloy; @@ -43,6 +44,7 @@ int IVMFunction::CallImpl(ThreadState* thread_state) { ics.context = (uint8_t*)thread_state->raw_context(); ics.membase = thread_state->memory()->membase(); ics.did_carry = 0; + ics.access_callbacks = thread_state->runtime()->access_callbacks(); ics.thread_state = thread_state; ics.return_address = 0xBEBEBEBE; diff --git a/src/alloy/backend/ivm/ivm_intcode.cc b/src/alloy/backend/ivm/ivm_intcode.cc index 0e0b86f1d..2cb3b0304 100644 --- a/src/alloy/backend/ivm/ivm_intcode.cc +++ b/src/alloy/backend/ivm/ivm_intcode.cc @@ -158,6 +158,210 @@ int DispatchToC(TranslationContext& ctx, Instr* i, IntCodeFn fn) { 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(); + 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(); + 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) { 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 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", - *((int8_t*)(ics.membase + ics.rf[i->src1_reg].u32)), - *((uint8_t*)(ics.membase + ics.rf[i->src1_reg].u32)), - ics.rf[i->src1_reg].u32); + *((int8_t*)(ics.membase + address)), + *((uint8_t*)(ics.membase + address)), + address); 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; } 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", - *((int16_t*)(ics.membase + ics.rf[i->src1_reg].u32)), - *((uint16_t*)(ics.membase + ics.rf[i->src1_reg].u32)), - ics.rf[i->src1_reg].u32); + *((int16_t*)(ics.membase + address)), + *((uint16_t*)(ics.membase + address)), + address); 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; } 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", - *((int32_t*)(ics.membase + ics.rf[i->src1_reg].u32)), - *((uint32_t*)(ics.membase + ics.rf[i->src1_reg].u32)), - ics.rf[i->src1_reg].u32); + *((int32_t*)(ics.membase + address)), + *((uint32_t*)(ics.membase + address)), + address); 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; } uint32_t IntCode_LOAD_I64(IntCodeState& ics, const IntCode* i) { - DPRINT("%d (%X) = load.i64 %.8X\n", - *((int64_t*)(ics.membase + ics.rf[i->src1_reg].u32)), - *((uint64_t*)(ics.membase + ics.rf[i->src1_reg].u32)), - ics.rf[i->src1_reg].u32); + uint32_t address = ics.rf[i->src1_reg].u32; + if ((address & 0xFF000000) == 0x7F000000) { + return IntCode_LOAD_REGISTER_I64(ics, i); + } + DPRINT("%lld (%llX) = load.i64 %.8X\n", + *((int64_t*)(ics.membase + address)), + *((uint64_t*)(ics.membase + address)), + address); 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; } 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; } 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; } 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; } int Translate_LOAD(TranslationContext& ctx, Instr* i) { @@ -986,47 +1208,79 @@ int Translate_LOAD(TranslationContext& ctx, Instr* i) { IntCode_LOAD_F64, 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]); } 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", - 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(); - *((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; } 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", - 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(); - *((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; } 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", - 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(); - *((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; } uint32_t IntCode_STORE_I64(IntCodeState& ics, const IntCode* i) { - DPRINT("store.i64 %.8X = %d (%X)\n", - ics.rf[i->src1_reg].u32, ics.rf[i->src2_reg].i64, ics.rf[i->src2_reg].i64); + uint32_t address = ics.rf[i->src1_reg].u32; + 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(); - *((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; } 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; } 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; } 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; } int Translate_STORE(TranslationContext& ctx, Instr* i) { @@ -1039,6 +1293,19 @@ int Translate_STORE(TranslationContext& ctx, Instr* i) { IntCode_STORE_F64, 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]); } diff --git a/src/alloy/backend/ivm/ivm_intcode.h b/src/alloy/backend/ivm/ivm_intcode.h index 34eec0f5e..e80dd0ee2 100644 --- a/src/alloy/backend/ivm/ivm_intcode.h +++ b/src/alloy/backend/ivm/ivm_intcode.h @@ -14,6 +14,7 @@ #include #include +#include namespace alloy { namespace runtime { class ThreadState; } } @@ -43,6 +44,7 @@ typedef struct { uint8_t* context; uint8_t* membase; int8_t did_carry; + runtime::RegisterAccessCallbacks* access_callbacks; runtime::ThreadState* thread_state; uint64_t return_address; } IntCodeState; @@ -85,6 +87,8 @@ typedef struct LabelRef_s { typedef struct { + runtime::RegisterAccessCallbacks* access_callbacks; + uint32_t register_count; size_t intcode_count; Arena* intcode_arena; diff --git a/src/alloy/runtime/register_access.h b/src/alloy/runtime/register_access.h index c04467561..21e3f1549 100644 --- a/src/alloy/runtime/register_access.h +++ b/src/alloy/runtime/register_access.h @@ -21,11 +21,13 @@ typedef uint64_t (*RegisterReadCallback)(void* context, uint64_t addr); typedef void (*RegisterWriteCallback)(void* context, uint64_t addr, uint64_t value); -typedef struct { +typedef struct RegisterAccessCallbacks_s { void* context; RegisterHandlesCallback handles; RegisterReadCallback read; RegisterWriteCallback write; + + RegisterAccessCallbacks_s* next; } RegisterAccessCallbacks; diff --git a/src/alloy/runtime/runtime.cc b/src/alloy/runtime/runtime.cc index bb76b68b6..2ee5771ce 100644 --- a/src/alloy/runtime/runtime.cc +++ b/src/alloy/runtime/runtime.cc @@ -25,7 +25,8 @@ DEFINE_string(runtime_backend, "any", Runtime::Runtime(Memory* memory) : - memory_(memory), backend_(0), frontend_(0) { + memory_(memory), backend_(0), frontend_(0), + access_callbacks_(0) { tracing::Initialize(); modules_lock_ = AllocMutex(10000); } @@ -40,6 +41,14 @@ Runtime::~Runtime() { UnlockMutex(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 backend_; @@ -213,6 +222,10 @@ int Runtime::DemandFunction( 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; } diff --git a/src/alloy/runtime/runtime.h b/src/alloy/runtime/runtime.h index dcb2d1ea5..59ab27790 100644 --- a/src/alloy/runtime/runtime.h +++ b/src/alloy/runtime/runtime.h @@ -33,6 +33,9 @@ public: Memory* memory() const { return memory_; } frontend::Frontend* frontend() const { return frontend_; } backend::Backend* backend() const { return backend_; } + RegisterAccessCallbacks* access_callbacks() const { + return access_callbacks_; + } int Initialize(frontend::Frontend* frontend, backend::Backend* backend = 0); @@ -41,7 +44,8 @@ public: int LookupFunctionInfo(uint64_t address, FunctionInfo** out_symbol_info); 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); @@ -58,6 +62,8 @@ protected: Mutex* modules_lock_; typedef std::vector ModuleList; ModuleList modules_; + + RegisterAccessCallbacks* access_callbacks_; };