void execute(ThreadState *state) { while (state->nia != cpu::CALLBACK_ADDR) { if (state->core->interrupt.load()) { cpu::gInterruptHandler(state->core, state); } // Interpreter Loop! state->cia = state->nia; state->nia = state->cia + 4; gDebugControl.maybeBreak(state->cia, state, gProcessor.getCoreID()); auto instr = mem::read<Instruction>(state->cia); auto data = gInstructionTable.decode(instr); if (!data) { gLog->error("Could not decode instruction at {:08x} = {:08x}", state->cia, instr.value); } assert(data); auto trace = traceInstructionStart(instr, data, state); auto fptr = sInstructionMap[static_cast<size_t>(data->id)]; if (!fptr) { gLog->error("Unimplemented interpreter instruction {}", data->name); } assert(fptr); fptr(state, instr); traceInstructionEnd(trace, instr, data, state); } }
Core * step_one(Core *core) { // Check if we hit any breakpoints if (testBreakpoint(core->nia)) { core->interrupt.fetch_or(DBGBREAK_INTERRUPT); this_core::checkInterrupts(); } auto cia = core->nia; core->cia = cia; core->nia = cia + 4; auto instr = mem::read<espresso::Instruction>(cia); auto data = espresso::decodeInstruction(instr); if (!data) { gLog->error("Could not decode instruction at {:08x} = {:08x}", cia, instr.value); } decaf_check(data); auto trace = traceInstructionStart(instr, data, core); auto fptr = sInstructionMap[static_cast<size_t>(data->id)]; if (!fptr) { gLog->error("Unimplemented interpreter instruction {}", data->name); } decaf_check(fptr); fptr(core, instr); if (data->id == InstructionID::kc) { // If this is a KC, there is the potential that we are running on a // different core now. Lets make sure that we are using the right one. core = this_core::state(); } decaf_check(core->cia == cia); traceInstructionEnd(trace, instr, data, core); return core; }
void Interpreter::execute(ThreadState *state) { bool hasJumped = false; bool forceJit = false; while (state->nia != CALLBACK_ADDR) { // TankTankTank decryptor fn //forceJit = state->nia >= 0x0250B648 && state->nia < 0x0250B8B8; // Handle interrupts gProcessor.handleInterrupt(); // JIT Attempt! if (forceJit || mJitMode == InterpJitMode::Enabled) { if (forceJit || state->nia != state->cia + 4) { // We jumped, try to enter JIT JitCode jitFn = gJitManager.get(state->nia); if (jitFn) { auto newNia = gJitManager.execute(state, jitFn); state->cia = 0; state->nia = newNia; continue; } } } // Interpreter Loop! state->cia = state->nia; state->nia = state->cia + 4; gDebugControl.maybeBreak(state->cia, state, gProcessor.getCoreID()); auto instr = gMemory.read<Instruction>(state->cia); auto data = gInstructionTable.decode(instr); if (!data) { gLog->error("Could not decode instruction at {:08x} = {:08x}", state->cia, instr.value); } assert(data); auto trace = traceInstructionStart(instr, data, state); auto fptr = sInstructionMap[static_cast<size_t>(data->id)]; if (!fptr) { gLog->error("Unimplemented interpreter instruction {}", data->name); } assert(fptr); if (mJitMode != InterpJitMode::Debug) { fptr(state, instr); } else { // Save original state for debugging ThreadState ostate = *state; // Save thread-state for JIT run. ThreadState jstate = *state; uint32_t jReserveBytes = 0; uint32_t jReserveAddress = 0; if (jstate.reserve) { jReserveAddress = jstate.reserveAddress; jReserveBytes = gMemory.read<uint32_t>(jReserveAddress); } // Fetch the JIT instruction block JitCode jitInstr = gJitManager.getSingle(ostate.cia); if (jitInstr == nullptr) { gLog->error("Failed to JIT debug instr {} @ {:08x}", data->name, ostate.cia); DebugBreak(); } // Execute with Interpreter fptr(state, instr); // Kernel calls are not stateless if (data->id != InstructionID::kc) { // Restore reserve data if (jReserveAddress != 0) { gMemory.write(jReserveAddress, jReserveBytes); } // Execute with JIT jstate.nia = gJitManager.execute(&jstate, jitInstr); // Ensure compliance! std::vector<std::string> errors; if (!dbgStateCmp(&jstate, state, errors)) { gLog->error("JIT Compliance errors w/ {} at {:08x}", data->name, ostate.cia); for (auto &err : errors) { gLog->error(err); } DebugBreak(); } } } traceInstructionEnd(trace, instr, data, state); } }