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
|
// 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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue