Register access (dynamic and static) wired up.

This commit is contained in:
Ben Vanik
2013-12-07 13:09:22 -08:00
parent e5d867a92f
commit d8cc9fb0b4
8 changed files with 337 additions and 38 deletions

View File

@@ -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<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) {
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]);
}