A32: Add hook_hint_instructions option

This commit is contained in:
MerryMage 2019-07-25 12:08:06 +01:00
parent 2f2a859615
commit 396116ee61
5 changed files with 60 additions and 8 deletions

View file

@ -24,21 +24,21 @@ enum class Exception {
/// An unpredictable instruction is to be executed. Implementation-defined behaviour should now happen. /// 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. /// This behaviour is up to the user of this library to define.
UnpredictableInstruction, 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, 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, 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, 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, WaitForEvent,
/// A YIELD instruction was executed. /// A YIELD instruction was executed. (Hint instruction.)
Yield, Yield,
/// A BKPT instruction was executed. /// A BKPT instruction was executed.
Breakpoint, Breakpoint,
/// A PLD instruction was executed. /// A PLD instruction was executed. (Hint instruction.)
PreloadData, PreloadData,
/// A PLDW instruction was executed. /// A PLDW instruction was executed. (Hint instruction.)
PreloadDataWithIntentToWrite, PreloadDataWithIntentToWrite,
}; };
@ -97,6 +97,10 @@ struct UserConfig {
// Coprocessors // Coprocessors
std::array<std::shared_ptr<Coprocessor>, 16> coprocessors; std::array<std::shared_ptr<Coprocessor>, 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 /// This option relates to translation. Generally when we run into an unpredictable
/// instruction the ExceptionRaised callback is called. If this is true, we define /// instruction the ExceptionRaised callback is called. If this is true, we define
/// definite behaviour for some unpredictable instructions. /// definite behaviour for some unpredictable instructions.

View file

@ -132,7 +132,7 @@ private:
PerformCacheInvalidation(); 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::A32GetSetElimination(ir_block);
Optimization::DeadCodeElimination(ir_block); Optimization::DeadCodeElimination(ir_block);
Optimization::A32ConstantMemoryReads(ir_block, config.callbacks); Optimization::A32ConstantMemoryReads(ir_block, config.callbacks);

View file

@ -13,6 +13,10 @@ bool ArmTranslatorVisitor::arm_PLD_imm([[maybe_unused]] bool add,
bool R, bool R,
[[maybe_unused]] Reg n, [[maybe_unused]] Reg n,
[[maybe_unused]] Imm<12> imm12) { [[maybe_unused]] Imm<12> imm12) {
if (!options.hook_hint_instructions) {
return true;
}
const auto exception = R ? Exception::PreloadData const auto exception = R ? Exception::PreloadData
: Exception::PreloadDataWithIntentToWrite; : Exception::PreloadDataWithIntentToWrite;
return RaiseException(exception); return RaiseException(exception);
@ -24,28 +28,52 @@ bool ArmTranslatorVisitor::arm_PLD_reg([[maybe_unused]] bool add,
[[maybe_unused]] Imm<5> imm5, [[maybe_unused]] Imm<5> imm5,
[[maybe_unused]] ShiftType shift, [[maybe_unused]] ShiftType shift,
[[maybe_unused]] Reg m) { [[maybe_unused]] Reg m) {
if (!options.hook_hint_instructions) {
return true;
}
const auto exception = R ? Exception::PreloadData const auto exception = R ? Exception::PreloadData
: Exception::PreloadDataWithIntentToWrite; : Exception::PreloadDataWithIntentToWrite;
return RaiseException(exception); return RaiseException(exception);
} }
bool ArmTranslatorVisitor::arm_SEV() { bool ArmTranslatorVisitor::arm_SEV() {
if (!options.hook_hint_instructions) {
return true;
}
return RaiseException(Exception::SendEvent); return RaiseException(Exception::SendEvent);
} }
bool ArmTranslatorVisitor::arm_SEVL() { bool ArmTranslatorVisitor::arm_SEVL() {
if (!options.hook_hint_instructions) {
return true;
}
return RaiseException(Exception::SendEventLocal); return RaiseException(Exception::SendEventLocal);
} }
bool ArmTranslatorVisitor::arm_WFE() { bool ArmTranslatorVisitor::arm_WFE() {
if (!options.hook_hint_instructions) {
return true;
}
return RaiseException(Exception::WaitForEvent); return RaiseException(Exception::WaitForEvent);
} }
bool ArmTranslatorVisitor::arm_WFI() { bool ArmTranslatorVisitor::arm_WFI() {
if (!options.hook_hint_instructions) {
return true;
}
return RaiseException(Exception::WaitForInterrupt); return RaiseException(Exception::WaitForInterrupt);
} }
bool ArmTranslatorVisitor::arm_YIELD() { bool ArmTranslatorVisitor::arm_YIELD() {
if (!options.hook_hint_instructions) {
return true;
}
return RaiseException(Exception::Yield); return RaiseException(Exception::Yield);
} }

View file

@ -643,26 +643,41 @@ bool ThumbTranslatorVisitor::thumb16_NOP() {
// SEV<c> // SEV<c>
bool ThumbTranslatorVisitor::thumb16_SEV() { bool ThumbTranslatorVisitor::thumb16_SEV() {
if (!options.hook_hint_instructions) {
return true;
}
return RaiseException(Exception::SendEvent); return RaiseException(Exception::SendEvent);
} }
// SEVL<c> // SEVL<c>
bool ThumbTranslatorVisitor::thumb16_SEVL() { bool ThumbTranslatorVisitor::thumb16_SEVL() {
if (!options.hook_hint_instructions) {
return true;
}
return RaiseException(Exception::SendEventLocal); return RaiseException(Exception::SendEventLocal);
} }
// WFE<c> // WFE<c>
bool ThumbTranslatorVisitor::thumb16_WFE() { bool ThumbTranslatorVisitor::thumb16_WFE() {
if (!options.hook_hint_instructions) {
return true;
}
return RaiseException(Exception::WaitForEvent); return RaiseException(Exception::WaitForEvent);
} }
// WFI<c> // WFI<c>
bool ThumbTranslatorVisitor::thumb16_WFI() { bool ThumbTranslatorVisitor::thumb16_WFI() {
if (!options.hook_hint_instructions) {
return true;
}
return RaiseException(Exception::WaitForInterrupt); return RaiseException(Exception::WaitForInterrupt);
} }
// YIELD<c> // YIELD<c>
bool ThumbTranslatorVisitor::thumb16_YIELD() { bool ThumbTranslatorVisitor::thumb16_YIELD() {
if (!options.hook_hint_instructions) {
return true;
}
return RaiseException(Exception::Yield); return RaiseException(Exception::Yield);
} }

View file

@ -22,6 +22,11 @@ struct TranslationOptions {
/// If this is false, the ExceptionRaised IR instruction is emitted. /// If this is false, the ExceptionRaised IR instruction is emitted.
/// If this is true, we define some behaviour for some instructions. /// If this is true, we define some behaviour for some instructions.
bool define_unpredictable_behaviour = false; 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;
}; };
/** /**