diff --git a/include/dynarmic/A32/config.h b/include/dynarmic/A32/config.h index d7af62c6..565e2a91 100644 --- a/include/dynarmic/A32/config.h +++ b/include/dynarmic/A32/config.h @@ -90,6 +90,8 @@ struct UserCallbacks { virtual void ExceptionRaised(VAddr pc, Exception exception) = 0; + virtual void InstructionSynchronizationBarrierRaised() {} + // Timing-related callbacks // ticks ticks have passed virtual void AddTicks(std::uint64_t ticks) = 0; @@ -164,6 +166,11 @@ struct UserConfig { // Coprocessors std::array, 16> coprocessors{}; + /// When set to true, UserCallbacks::InstructionSynchronizationBarrierRaised will be + /// called when an ISB instruction is executed. + /// When set to false, ISB will be treated as a NOP instruction. + bool hook_isb = false; + /// Hint instructions would cause ExceptionRaised to be called with the appropriate /// argument. bool hook_hint_instructions = false; diff --git a/src/backend/x64/a32_emit_x64.cpp b/src/backend/x64/a32_emit_x64.cpp index 099dfdd0..61d5fba7 100644 --- a/src/backend/x64/a32_emit_x64.cpp +++ b/src/backend/x64/a32_emit_x64.cpp @@ -720,10 +720,12 @@ void A32EmitX64::EmitA32DataMemoryBarrier(A32EmitContext&, IR::Inst*) { } void A32EmitX64::EmitA32InstructionSynchronizationBarrier(A32EmitContext& ctx, IR::Inst*) { - ctx.reg_alloc.HostCall(nullptr); + if (!conf.hook_isb) { + return; + } - code.mov(code.ABI_PARAM1, reinterpret_cast(jit_interface)); - code.CallLambda([](A32::Jit* jit) { jit->ClearCache(); }); + ctx.reg_alloc.HostCall(nullptr); + Devirtualize<&A32::UserCallbacks::InstructionSynchronizationBarrierRaised>(conf.callbacks).EmitCall(code); } void A32EmitX64::EmitA32BXWritePC(A32EmitContext& ctx, IR::Inst* inst) {