diff --git a/include/dynarmic/A64/config.h b/include/dynarmic/A64/config.h index e6f48ef6..6a029d97 100644 --- a/include/dynarmic/A64/config.h +++ b/include/dynarmic/A64/config.h @@ -110,6 +110,7 @@ struct UserCallbacks { virtual void ExceptionRaised(VAddr pc, Exception exception) = 0; virtual void DataCacheOperationRaised(DataCacheOperation /*op*/, VAddr /*value*/) {} + virtual void InstructionSynchronizationBarrierRaised() {} // Timing-related callbacks // ticks ticks have passed @@ -153,6 +154,11 @@ struct UserConfig { /// Executing DC ZVA in this mode will result in zeros being written to memory. bool hook_data_cache_operations = false; + /// 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; + /// When set to true, UserCallbacks::ExceptionRaised will be called when any hint /// instruction is executed. bool hook_hint_instructions = false; diff --git a/src/backend/x64/a64_emit_x64.cpp b/src/backend/x64/a64_emit_x64.cpp index c8be6fe1..c89f4e91 100644 --- a/src/backend/x64/a64_emit_x64.cpp +++ b/src/backend/x64/a64_emit_x64.cpp @@ -659,11 +659,13 @@ void A64EmitX64::EmitA64DataMemoryBarrier(A64EmitContext&, IR::Inst*) { code.lfence(); } -void A64EmitX64::EmitA64InstructionSynchronizationBarrier(A64EmitContext& ctx, IR::Inst* ) { - ctx.reg_alloc.HostCall(nullptr); +void A64EmitX64::EmitA64InstructionSynchronizationBarrier(A64EmitContext& ctx, IR::Inst*) { + if (!conf.hook_isb) { + return; + } - code.mov(code.ABI_PARAM1, reinterpret_cast(jit_interface)); - code.CallLambda([](A64::Jit* jit) { jit->ClearCache(); }); + ctx.reg_alloc.HostCall(nullptr); + Devirtualize<&A64::UserCallbacks::InstructionSynchronizationBarrierRaised>(conf.callbacks).EmitCall(code); } void A64EmitX64::EmitA64GetCNTFRQ(A64EmitContext& ctx, IR::Inst* inst) {