Beispiel #1
0
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;
}
Beispiel #3
0
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);
   }
}