A32: Add define_unpredictable_behaviour option

This commit is contained in:
MerryMage 2018-08-25 23:00:04 +01:00
parent b0abaa8312
commit a12854857b
9 changed files with 31 additions and 16 deletions

View file

@ -82,6 +82,11 @@ struct UserConfig {
// Coprocessors // Coprocessors
std::array<std::shared_ptr<Coprocessor>, 16> 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 } // namespace A32

View file

@ -131,7 +131,7 @@ private:
PerformCacheInvalidation(); 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::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

@ -10,11 +10,11 @@
namespace Dynarmic::A32 { namespace Dynarmic::A32 {
IR::Block TranslateArm(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); IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, const TranslationOptions& options);
IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) { IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, const TranslationOptions& options) {
return (descriptor.TFlag() ? TranslateThumb : TranslateArm)(descriptor, memory_read_code); return (descriptor.TFlag() ? TranslateThumb : TranslateArm)(descriptor, memory_read_code, options);
} }
bool TranslateSingleArmInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction); bool TranslateSingleArmInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction);

View file

@ -17,13 +17,20 @@ class LocationDescriptor;
using MemoryReadCodeFuncType = std::function<u32(u32 vaddr)>; 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. * 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 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. * @param memory_read_code The function we should use to read emulated memory.
* @return A translated basic block in the intermediate representation. * @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. * This function translates a single provided instruction into our intermediate representation.

View file

@ -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(); }); 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}; IR::Block block{descriptor};
ArmTranslatorVisitor visitor{block, descriptor}; ArmTranslatorVisitor visitor{block, descriptor, options};
bool should_continue = true; bool should_continue = true;
while (should_continue && CondCanContinue(visitor.cond_state, visitor.ir)) { 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) { bool TranslateSingleArmInstruction(IR::Block& block, LocationDescriptor descriptor, u32 arm_instruction) {
ArmTranslatorVisitor visitor{block, descriptor}; ArmTranslatorVisitor visitor{block, descriptor, {}};
// TODO: Proper cond handling // TODO: Proper cond handling

View file

@ -9,6 +9,7 @@
#include "common/bit_util.h" #include "common/bit_util.h"
#include "frontend/A32/ir_emitter.h" #include "frontend/A32/ir_emitter.h"
#include "frontend/A32/location_descriptor.h" #include "frontend/A32/location_descriptor.h"
#include "frontend/A32/translate/translate.h"
namespace Dynarmic::A32 { namespace Dynarmic::A32 {
@ -26,12 +27,13 @@ enum class ConditionalState {
struct ArmTranslatorVisitor final { struct ArmTranslatorVisitor final {
using instruction_return_type = bool; 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"); ASSERT_MSG(!descriptor.TFlag(), "The processor must be in Arm mode");
} }
A32::IREmitter ir; A32::IREmitter ir;
ConditionalState cond_state = ConditionalState::None; ConditionalState cond_state = ConditionalState::None;
TranslationOptions options;
bool ConditionPassed(Cond cond); bool ConditionPassed(Cond cond);
bool InterpretThisInstruction(); bool InterpretThisInstruction();

View file

@ -21,11 +21,12 @@ namespace {
struct ThumbTranslatorVisitor final { struct ThumbTranslatorVisitor final {
using instruction_return_type = bool; 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"); ASSERT_MSG(descriptor.TFlag(), "The processor must be in Thumb mode");
} }
A32::IREmitter ir; A32::IREmitter ir;
TranslationOptions options;
bool InterpretThisInstruction() { bool InterpretThisInstruction() {
ir.SetTerm(IR::Term::Interpret(ir.current_location)); ir.SetTerm(IR::Term::Interpret(ir.current_location));
@ -879,9 +880,9 @@ std::tuple<u32, ThumbInstSize> ReadThumbInstruction(u32 arm_pc, MemoryReadCodeFu
} // local namespace } // 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}; IR::Block block{descriptor};
ThumbTranslatorVisitor visitor{block, descriptor}; ThumbTranslatorVisitor visitor{block, descriptor, options};
bool should_continue = true; bool should_continue = true;
while (should_continue) { while (should_continue) {
@ -913,7 +914,7 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType m
} }
bool TranslateSingleThumbInstruction(IR::Block& block, LocationDescriptor descriptor, u32 thumb_instruction) { 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)); const bool is_thumb_16 = IsThumb16(static_cast<u16>(thumb_instruction));
bool should_continue = true; bool should_continue = true;

View file

@ -193,7 +193,7 @@ void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_exe
size_t num_insts = 0; size_t num_insts = 0;
while (num_insts < instructions_to_execute_count) { while (num_insts < instructions_to_execute_count) {
Dynarmic::A32::LocationDescriptor descriptor = {u32(num_insts * 4), Dynarmic::A32::PSR{}, Dynarmic::A32::FPSCR{}}; 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::A32GetSetElimination(ir_block);
Dynarmic::Optimization::DeadCodeElimination(ir_block); Dynarmic::Optimization::DeadCodeElimination(ir_block);
Dynarmic::Optimization::A32ConstantMemoryReads(ir_block, &test_env); Dynarmic::Optimization::A32ConstantMemoryReads(ir_block, &test_env);

View file

@ -152,7 +152,7 @@ static void RunInstance(size_t run_number, ThumbTestEnv& test_env, ARMul_State&
size_t num_insts = 0; size_t num_insts = 0;
while (num_insts < instructions_to_execute_count) { while (num_insts < instructions_to_execute_count) {
Dynarmic::A32::LocationDescriptor descriptor = {u32(num_insts * 4), cpsr, Dynarmic::A32::FPSCR{}}; 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::A32GetSetElimination(ir_block);
Dynarmic::Optimization::DeadCodeElimination(ir_block); Dynarmic::Optimization::DeadCodeElimination(ir_block);
Dynarmic::Optimization::A32ConstantMemoryReads(ir_block, &test_env); Dynarmic::Optimization::A32ConstantMemoryReads(ir_block, &test_env);