diff --git a/include/dynarmic/A32/config.h b/include/dynarmic/A32/config.h index e2824a41..54c96be7 100644 --- a/include/dynarmic/A32/config.h +++ b/include/dynarmic/A32/config.h @@ -24,21 +24,21 @@ enum class Exception { /// An unpredictable instruction is to be executed. Implementation-defined behaviour should now happen. /// This behaviour is up to the user of this library to define. UnpredictableInstruction, - /// A SEV instruction was executed. The event register of all PEs should be set. + /// A SEV instruction was executed. The event register of all PEs should be set. (Hint instruction.) SendEvent, - /// A SEVL instruction was executed. The event register of the current PE should be set. + /// A SEVL instruction was executed. The event register of the current PE should be set. (Hint instruction.) SendEventLocal, - /// A WFI instruction was executed. You may now enter a low-power state. + /// A WFI instruction was executed. You may now enter a low-power state. (Hint instruction.) WaitForInterrupt, - /// A WFE instruction was executed. You may now enter a low-power state if the event register is clear. + /// A WFE instruction was executed. You may now enter a low-power state if the event register is clear. (Hint instruction.) WaitForEvent, - /// A YIELD instruction was executed. + /// A YIELD instruction was executed. (Hint instruction.) Yield, /// A BKPT instruction was executed. Breakpoint, - /// A PLD instruction was executed. + /// A PLD instruction was executed. (Hint instruction.) PreloadData, - /// A PLDW instruction was executed. + /// A PLDW instruction was executed. (Hint instruction.) PreloadDataWithIntentToWrite, }; @@ -97,6 +97,10 @@ struct UserConfig { // Coprocessors std::array, 16> coprocessors; + /// Hint instructions would cause ExceptionRaised to be called with the appropriate + /// argument. + bool hook_hint_instructions = false; + /// This option relates to translation. Generally when we run into an unpredictable /// instruction the ExceptionRaised callback is called. If this is true, we define /// definite behaviour for some unpredictable instructions. diff --git a/src/backend/x64/a32_interface.cpp b/src/backend/x64/a32_interface.cpp index 08569706..6f4141a4 100644 --- a/src/backend/x64/a32_interface.cpp +++ b/src/backend/x64/a32_interface.cpp @@ -132,7 +132,7 @@ private: PerformCacheInvalidation(); } - IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, [this](u32 vaddr) { return config.callbacks->MemoryReadCode(vaddr); }, {config.define_unpredictable_behaviour}); + IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, [this](u32 vaddr) { return config.callbacks->MemoryReadCode(vaddr); }, {config.define_unpredictable_behaviour, config.hook_hint_instructions}); Optimization::A32GetSetElimination(ir_block); Optimization::DeadCodeElimination(ir_block); Optimization::A32ConstantMemoryReads(ir_block, config.callbacks); diff --git a/src/frontend/A32/translate/impl/hint.cpp b/src/frontend/A32/translate/impl/hint.cpp index 701efbd5..9617699c 100644 --- a/src/frontend/A32/translate/impl/hint.cpp +++ b/src/frontend/A32/translate/impl/hint.cpp @@ -13,6 +13,10 @@ bool ArmTranslatorVisitor::arm_PLD_imm([[maybe_unused]] bool add, bool R, [[maybe_unused]] Reg n, [[maybe_unused]] Imm<12> imm12) { + if (!options.hook_hint_instructions) { + return true; + } + const auto exception = R ? Exception::PreloadData : Exception::PreloadDataWithIntentToWrite; return RaiseException(exception); @@ -24,28 +28,52 @@ bool ArmTranslatorVisitor::arm_PLD_reg([[maybe_unused]] bool add, [[maybe_unused]] Imm<5> imm5, [[maybe_unused]] ShiftType shift, [[maybe_unused]] Reg m) { + if (!options.hook_hint_instructions) { + return true; + } + const auto exception = R ? Exception::PreloadData : Exception::PreloadDataWithIntentToWrite; return RaiseException(exception); } bool ArmTranslatorVisitor::arm_SEV() { + if (!options.hook_hint_instructions) { + return true; + } + return RaiseException(Exception::SendEvent); } bool ArmTranslatorVisitor::arm_SEVL() { + if (!options.hook_hint_instructions) { + return true; + } + return RaiseException(Exception::SendEventLocal); } bool ArmTranslatorVisitor::arm_WFE() { + if (!options.hook_hint_instructions) { + return true; + } + return RaiseException(Exception::WaitForEvent); } bool ArmTranslatorVisitor::arm_WFI() { + if (!options.hook_hint_instructions) { + return true; + } + return RaiseException(Exception::WaitForInterrupt); } bool ArmTranslatorVisitor::arm_YIELD() { + if (!options.hook_hint_instructions) { + return true; + } + return RaiseException(Exception::Yield); } diff --git a/src/frontend/A32/translate/impl/thumb16.cpp b/src/frontend/A32/translate/impl/thumb16.cpp index 0a09283c..9d70b1ea 100644 --- a/src/frontend/A32/translate/impl/thumb16.cpp +++ b/src/frontend/A32/translate/impl/thumb16.cpp @@ -643,26 +643,41 @@ bool ThumbTranslatorVisitor::thumb16_NOP() { // SEV bool ThumbTranslatorVisitor::thumb16_SEV() { + if (!options.hook_hint_instructions) { + return true; + } return RaiseException(Exception::SendEvent); } // SEVL bool ThumbTranslatorVisitor::thumb16_SEVL() { + if (!options.hook_hint_instructions) { + return true; + } return RaiseException(Exception::SendEventLocal); } // WFE bool ThumbTranslatorVisitor::thumb16_WFE() { + if (!options.hook_hint_instructions) { + return true; + } return RaiseException(Exception::WaitForEvent); } // WFI bool ThumbTranslatorVisitor::thumb16_WFI() { + if (!options.hook_hint_instructions) { + return true; + } return RaiseException(Exception::WaitForInterrupt); } // YIELD bool ThumbTranslatorVisitor::thumb16_YIELD() { + if (!options.hook_hint_instructions) { + return true; + } return RaiseException(Exception::Yield); } diff --git a/src/frontend/A32/translate/translate.h b/src/frontend/A32/translate/translate.h index ef9b2b2c..ba699555 100644 --- a/src/frontend/A32/translate/translate.h +++ b/src/frontend/A32/translate/translate.h @@ -22,6 +22,11 @@ struct TranslationOptions { /// If this is false, the ExceptionRaised IR instruction is emitted. /// If this is true, we define some behaviour for some instructions. bool define_unpredictable_behaviour = 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. + bool hook_hint_instructions = true; }; /**