A32: Add define_unpredictable_behaviour option
This commit is contained in:
parent
b0abaa8312
commit
a12854857b
9 changed files with 31 additions and 16 deletions
|
@ -82,6 +82,11 @@ struct UserConfig {
|
|||
|
||||
// Coprocessors
|
||||
std::array<std::shared_ptr<Coprocessor>, 16> coprocessors;
|
||||
|
||||
/// 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.
|
||||
bool define_unpredictable_behaviour = false;
|
||||
};
|
||||
|
||||
} // namespace A32
|
||||
|
|
|
@ -131,7 +131,7 @@ private:
|
|||
PerformCacheInvalidation();
|
||||
}
|
||||
|
||||
IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, [this](u32 vaddr) { return config.callbacks->MemoryReadCode(vaddr); });
|
||||
IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, [this](u32 vaddr) { return config.callbacks->MemoryReadCode(vaddr); }, {config.define_unpredictable_behaviour});
|
||||
Optimization::A32GetSetElimination(ir_block);
|
||||
Optimization::DeadCodeElimination(ir_block);
|
||||
Optimization::A32ConstantMemoryReads(ir_block, config.callbacks);
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
|
||||
namespace Dynarmic::A32 {
|
||||
|
||||
IR::Block TranslateArm(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code);
|
||||
IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code);
|
||||
IR::Block TranslateArm(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, const TranslationOptions& options);
|
||||
IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, const TranslationOptions& options);
|
||||
|
||||
IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) {
|
||||
return (descriptor.TFlag() ? TranslateThumb : TranslateArm)(descriptor, memory_read_code);
|
||||
IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, const TranslationOptions& options) {
|
||||
return (descriptor.TFlag() ? TranslateThumb : TranslateArm)(descriptor, memory_read_code, options);
|
||||
}
|
||||
|
||||
bool TranslateSingleArmInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction);
|
||||
|
|
|
@ -17,13 +17,20 @@ class LocationDescriptor;
|
|||
|
||||
using MemoryReadCodeFuncType = std::function<u32(u32 vaddr)>;
|
||||
|
||||
struct TranslationOptions {
|
||||
/// This changes what IR we emit when we translate an unpredictable instruction.
|
||||
/// 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 function translates instructions in memory into our intermediate representation.
|
||||
* @param descriptor The starting location of the basic block. Includes information like PC, Thumb state, &c.
|
||||
* @param memory_read_code The function we should use to read emulated memory.
|
||||
* @return A translated basic block in the intermediate representation.
|
||||
*/
|
||||
IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code);
|
||||
IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, const TranslationOptions& options);
|
||||
|
||||
/**
|
||||
* This function translates a single provided instruction into our intermediate representation.
|
||||
|
|
|
@ -28,9 +28,9 @@ static bool CondCanContinue(ConditionalState cond_state, const A32::IREmitter& i
|
|||
return std::all_of(ir.block.begin(), ir.block.end(), [](const IR::Inst& inst) { return !inst.WritesToCPSR(); });
|
||||
}
|
||||
|
||||
IR::Block TranslateArm(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) {
|
||||
IR::Block TranslateArm(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, const TranslationOptions& options) {
|
||||
IR::Block block{descriptor};
|
||||
ArmTranslatorVisitor visitor{block, descriptor};
|
||||
ArmTranslatorVisitor visitor{block, descriptor, options};
|
||||
|
||||
bool should_continue = true;
|
||||
while (should_continue && CondCanContinue(visitor.cond_state, visitor.ir)) {
|
||||
|
@ -67,7 +67,7 @@ IR::Block TranslateArm(LocationDescriptor descriptor, MemoryReadCodeFuncType mem
|
|||
}
|
||||
|
||||
bool TranslateSingleArmInstruction(IR::Block& block, LocationDescriptor descriptor, u32 arm_instruction) {
|
||||
ArmTranslatorVisitor visitor{block, descriptor};
|
||||
ArmTranslatorVisitor visitor{block, descriptor, {}};
|
||||
|
||||
// TODO: Proper cond handling
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "common/bit_util.h"
|
||||
#include "frontend/A32/ir_emitter.h"
|
||||
#include "frontend/A32/location_descriptor.h"
|
||||
#include "frontend/A32/translate/translate.h"
|
||||
|
||||
namespace Dynarmic::A32 {
|
||||
|
||||
|
@ -26,12 +27,13 @@ enum class ConditionalState {
|
|||
struct ArmTranslatorVisitor final {
|
||||
using instruction_return_type = bool;
|
||||
|
||||
explicit ArmTranslatorVisitor(IR::Block& block, LocationDescriptor descriptor) : ir(block, descriptor) {
|
||||
explicit ArmTranslatorVisitor(IR::Block& block, LocationDescriptor descriptor, const TranslationOptions& options) : ir(block, descriptor), options(options) {
|
||||
ASSERT_MSG(!descriptor.TFlag(), "The processor must be in Arm mode");
|
||||
}
|
||||
|
||||
A32::IREmitter ir;
|
||||
ConditionalState cond_state = ConditionalState::None;
|
||||
TranslationOptions options;
|
||||
|
||||
bool ConditionPassed(Cond cond);
|
||||
bool InterpretThisInstruction();
|
||||
|
|
|
@ -21,11 +21,12 @@ namespace {
|
|||
struct ThumbTranslatorVisitor final {
|
||||
using instruction_return_type = bool;
|
||||
|
||||
explicit ThumbTranslatorVisitor(IR::Block& block, LocationDescriptor descriptor) : ir(block, descriptor) {
|
||||
explicit ThumbTranslatorVisitor(IR::Block& block, LocationDescriptor descriptor, const TranslationOptions& options) : ir(block, descriptor), options(options) {
|
||||
ASSERT_MSG(descriptor.TFlag(), "The processor must be in Thumb mode");
|
||||
}
|
||||
|
||||
A32::IREmitter ir;
|
||||
TranslationOptions options;
|
||||
|
||||
bool InterpretThisInstruction() {
|
||||
ir.SetTerm(IR::Term::Interpret(ir.current_location));
|
||||
|
@ -879,9 +880,9 @@ std::tuple<u32, ThumbInstSize> ReadThumbInstruction(u32 arm_pc, MemoryReadCodeFu
|
|||
|
||||
} // local namespace
|
||||
|
||||
IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) {
|
||||
IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, const TranslationOptions& options) {
|
||||
IR::Block block{descriptor};
|
||||
ThumbTranslatorVisitor visitor{block, descriptor};
|
||||
ThumbTranslatorVisitor visitor{block, descriptor, options};
|
||||
|
||||
bool should_continue = true;
|
||||
while (should_continue) {
|
||||
|
@ -913,7 +914,7 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType m
|
|||
}
|
||||
|
||||
bool TranslateSingleThumbInstruction(IR::Block& block, LocationDescriptor descriptor, u32 thumb_instruction) {
|
||||
ThumbTranslatorVisitor visitor{block, descriptor};
|
||||
ThumbTranslatorVisitor visitor{block, descriptor, {}};
|
||||
|
||||
const bool is_thumb_16 = IsThumb16(static_cast<u16>(thumb_instruction));
|
||||
bool should_continue = true;
|
||||
|
|
|
@ -193,7 +193,7 @@ void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_exe
|
|||
size_t num_insts = 0;
|
||||
while (num_insts < instructions_to_execute_count) {
|
||||
Dynarmic::A32::LocationDescriptor descriptor = {u32(num_insts * 4), Dynarmic::A32::PSR{}, Dynarmic::A32::FPSCR{}};
|
||||
Dynarmic::IR::Block ir_block = Dynarmic::A32::Translate(descriptor, [&test_env](u32 vaddr) { return test_env.MemoryReadCode(vaddr); });
|
||||
Dynarmic::IR::Block ir_block = Dynarmic::A32::Translate(descriptor, [&test_env](u32 vaddr) { return test_env.MemoryReadCode(vaddr); }, {});
|
||||
Dynarmic::Optimization::A32GetSetElimination(ir_block);
|
||||
Dynarmic::Optimization::DeadCodeElimination(ir_block);
|
||||
Dynarmic::Optimization::A32ConstantMemoryReads(ir_block, &test_env);
|
||||
|
|
|
@ -152,7 +152,7 @@ static void RunInstance(size_t run_number, ThumbTestEnv& test_env, ARMul_State&
|
|||
size_t num_insts = 0;
|
||||
while (num_insts < instructions_to_execute_count) {
|
||||
Dynarmic::A32::LocationDescriptor descriptor = {u32(num_insts * 4), cpsr, Dynarmic::A32::FPSCR{}};
|
||||
Dynarmic::IR::Block ir_block = Dynarmic::A32::Translate(descriptor, [&test_env](u32 vaddr) { return test_env.MemoryReadCode(vaddr); });
|
||||
Dynarmic::IR::Block ir_block = Dynarmic::A32::Translate(descriptor, [&test_env](u32 vaddr) { return test_env.MemoryReadCode(vaddr); }, {});
|
||||
Dynarmic::Optimization::A32GetSetElimination(ir_block);
|
||||
Dynarmic::Optimization::DeadCodeElimination(ir_block);
|
||||
Dynarmic::Optimization::A32ConstantMemoryReads(ir_block, &test_env);
|
||||
|
|
Loading…
Reference in a new issue