A32: Add hook_hint_instructions option
This commit is contained in:
parent
2f2a859615
commit
396116ee61
5 changed files with 60 additions and 8 deletions
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue