diff --git a/include/dynarmic/A64/config.h b/include/dynarmic/A64/config.h index 145c98f2..a00fb8c3 100644 --- a/include/dynarmic/A64/config.h +++ b/include/dynarmic/A64/config.h @@ -158,6 +158,11 @@ struct UserConfig { /// This is only used if page_table is not nullptr. bool silently_mirror_page_table = true; + /// 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; + // The below options relate to accuracy of floating-point emulation. /// Determines how accurate NaN handling is. diff --git a/src/backend_x64/a64_interface.cpp b/src/backend_x64/a64_interface.cpp index 9a7ebfc6..397f6f32 100644 --- a/src/backend_x64/a64_interface.cpp +++ b/src/backend_x64/a64_interface.cpp @@ -199,7 +199,8 @@ private: } // JIT Compile - IR::Block ir_block = A64::Translate(A64::LocationDescriptor{current_location}, [this](u64 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); }); + const auto get_code = [this](u64 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); }; + IR::Block ir_block = A64::Translate(A64::LocationDescriptor{current_location}, get_code, {conf.define_unpredictable_behaviour}); Optimization::A64CallbackConfigPass(ir_block, conf); Optimization::A64GetSetElimination(ir_block); Optimization::DeadCodeElimination(ir_block); diff --git a/src/frontend/A64/translate/impl/impl.h b/src/frontend/A64/translate/impl/impl.h index 68603c67..308b9f5b 100644 --- a/src/frontend/A64/translate/impl/impl.h +++ b/src/frontend/A64/translate/impl/impl.h @@ -11,6 +11,7 @@ #include "frontend/A64/imm.h" #include "frontend/A64/ir_emitter.h" #include "frontend/A64/location_descriptor.h" +#include "frontend/A64/translate/translate.h" #include "frontend/A64/types.h" namespace Dynarmic::A64 { @@ -26,9 +27,10 @@ enum class MemOp { struct TranslatorVisitor final { using instruction_return_type = bool; - explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor) : ir(block, descriptor) {} + explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor, TranslationOptions options) : ir(block, descriptor), options(std::move(options)) {} A64::IREmitter ir; + TranslationOptions options; bool InterpretThisInstruction(); bool UnpredictableInstruction(); diff --git a/src/frontend/A64/translate/translate.cpp b/src/frontend/A64/translate/translate.cpp index 7fd888a7..2c63b806 100644 --- a/src/frontend/A64/translate/translate.cpp +++ b/src/frontend/A64/translate/translate.cpp @@ -12,9 +12,9 @@ namespace Dynarmic::A64 { -IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) { +IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, TranslationOptions options) { IR::Block block{descriptor}; - TranslatorVisitor visitor{block, descriptor}; + TranslatorVisitor visitor{block, descriptor, std::move(options)}; bool should_continue = true; while (should_continue) { @@ -39,7 +39,7 @@ IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory } bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction) { - TranslatorVisitor visitor{block, descriptor}; + TranslatorVisitor visitor{block, descriptor, {}}; bool should_continue = true; if (auto decoder = Decode(instruction)) { diff --git a/src/frontend/A64/translate/translate.h b/src/frontend/A64/translate/translate.h index 4fa6f9f9..2781336c 100644 --- a/src/frontend/A64/translate/translate.h +++ b/src/frontend/A64/translate/translate.h @@ -21,13 +21,21 @@ class LocationDescriptor; using MemoryReadCodeFuncType = std::function; +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, FPCR state, &c. * @param memory_read_code The function we should use to read emulated memory. + * @param options Configure how instructions are translated. * @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, TranslationOptions options); /** * This function translates a single provided instruction into our intermediate representation.