diff --git a/include/dynarmic/A64/config.h b/include/dynarmic/A64/config.h index 7c7fe3bf..b4c56ec0 100644 --- a/include/dynarmic/A64/config.h +++ b/include/dynarmic/A64/config.h @@ -200,6 +200,10 @@ struct UserConfig { /// definite behaviour for some unpredictable instructions. bool define_unpredictable_behaviour = false; + /// This tells the translator a wall clock will be used, thus allowing it + /// to avoid writting certain unnecessary code only needed for cycle timers. + bool wall_clock_cntpct = false; + /// This enables the fast dispatcher. bool enable_fast_dispatch = true; diff --git a/src/backend/x64/a64_emit_x64.cpp b/src/backend/x64/a64_emit_x64.cpp index b5980039..34fa7e54 100644 --- a/src/backend/x64/a64_emit_x64.cpp +++ b/src/backend/x64/a64_emit_x64.cpp @@ -651,7 +651,9 @@ void A64EmitX64::EmitA64GetCNTFRQ(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64GetCNTPCT(A64EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(inst); - code.UpdateTicks(); + if (!conf.wall_clock_cntpct) { + code.UpdateTicks(); + } Devirtualize<&A64::UserCallbacks::GetCNTPCT>(conf.callbacks).EmitCall(code); } diff --git a/src/backend/x64/a64_interface.cpp b/src/backend/x64/a64_interface.cpp index 2986fcbe..cf58f281 100644 --- a/src/backend/x64/a64_interface.cpp +++ b/src/backend/x64/a64_interface.cpp @@ -233,7 +233,8 @@ private: // JIT Compile const auto get_code = [this](u64 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); }; - IR::Block ir_block = A64::Translate(A64::LocationDescriptor{current_location}, get_code, {conf.define_unpredictable_behaviour}); + IR::Block ir_block = A64::Translate(A64::LocationDescriptor{current_location}, get_code, + {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct}); Optimization::A64CallbackConfigPass(ir_block, conf); if (conf.enable_optimizations) { Optimization::A64GetSetElimination(ir_block); diff --git a/src/frontend/A64/translate/impl/system.cpp b/src/frontend/A64/translate/impl/system.cpp index 1bac82c2..d82abafe 100644 --- a/src/frontend/A64/translate/impl/system.cpp +++ b/src/frontend/A64/translate/impl/system.cpp @@ -120,7 +120,7 @@ bool TranslatorVisitor::MRS(Imm<1> o0, Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3 return true; case SystemRegisterEncoding::CNTPCT_EL0: // HACK: Ensure that this is the first instruction in the block it's emitted in, so the cycle count is most up-to-date. - if (!ir.block.empty()) { + if (!ir.block.empty() && !options.wall_clock_cntpct) { ir.block.CycleCount()--; ir.SetTerm(IR::Term::LinkBlock{*ir.current_location}); return false; diff --git a/src/frontend/A64/translate/translate.h b/src/frontend/A64/translate/translate.h index 73cf3bbe..355b94c7 100644 --- a/src/frontend/A64/translate/translate.h +++ b/src/frontend/A64/translate/translate.h @@ -26,6 +26,10 @@ struct TranslationOptions { /// If this is true, we define some behaviour for some instructions. bool define_unpredictable_behaviour = false; + /// This tells the translator a wall clock will be used, thus allowing it + /// to avoid writting certain unnecessary code only needed for cycle timers. + bool wall_clock_cntpct = false; + /// This changes what IR we emit when we translate a hint instruction. /// If this is false, we treat the instruction as a NOP. /// If this is true, we emit an ExceptionRaised instruction.