From 61125d6dd1a2b69095976b3970efeae61b6612c3 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Fri, 12 Jan 2018 19:34:25 +0000 Subject: [PATCH] A64/translate: Add TranslateSingleInstruction function --- src/frontend/A32/ir_emitter.h | 2 +- src/frontend/A32/translate/translate_arm.cpp | 11 +++---- .../translate/translate_arm/translate_arm.h | 2 +- .../A32/translate/translate_thumb.cpp | 11 +++---- src/frontend/A64/ir_emitter.h | 2 +- src/frontend/A64/translate/impl/impl.h | 2 +- src/frontend/A64/translate/translate.cpp | 29 +++++++++++++++---- src/frontend/A64/translate/translate.h | 11 ++++++- src/frontend/ir/ir_emitter.h | 4 +-- 9 files changed, 52 insertions(+), 22 deletions(-) diff --git a/src/frontend/A32/ir_emitter.h b/src/frontend/A32/ir_emitter.h index b8272867..44210dc9 100644 --- a/src/frontend/A32/ir_emitter.h +++ b/src/frontend/A32/ir_emitter.h @@ -26,7 +26,7 @@ namespace A32 { */ class IREmitter : public IR::IREmitter { public: - explicit IREmitter(LocationDescriptor descriptor) : IR::IREmitter(descriptor), current_location(descriptor) {} + explicit IREmitter(IR::Block& block, LocationDescriptor descriptor) : IR::IREmitter(block), current_location(descriptor) {} LocationDescriptor current_location; diff --git a/src/frontend/A32/translate/translate_arm.cpp b/src/frontend/A32/translate/translate_arm.cpp index 29405876..14cb593c 100644 --- a/src/frontend/A32/translate/translate_arm.cpp +++ b/src/frontend/A32/translate/translate_arm.cpp @@ -29,7 +29,8 @@ static bool CondCanContinue(ConditionalState cond_state, const A32::IREmitter& i } IR::Block TranslateArm(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) { - ArmTranslatorVisitor visitor{descriptor}; + IR::Block block{descriptor}; + ArmTranslatorVisitor visitor{block, descriptor}; bool should_continue = true; while (should_continue && CondCanContinue(visitor.cond_state, visitor.ir)) { @@ -49,7 +50,7 @@ IR::Block TranslateArm(LocationDescriptor descriptor, MemoryReadCodeFuncType mem } visitor.ir.current_location = visitor.ir.current_location.AdvancePC(4); - visitor.ir.block.CycleCount()++; + block.CycleCount()++; } if (visitor.cond_state == ConditionalState::Translating || visitor.cond_state == ConditionalState::Trailing) { @@ -58,11 +59,11 @@ IR::Block TranslateArm(LocationDescriptor descriptor, MemoryReadCodeFuncType mem } } - ASSERT_MSG(visitor.ir.block.HasTerminal(), "Terminal has not been set"); + ASSERT_MSG(block.HasTerminal(), "Terminal has not been set"); - visitor.ir.block.SetEndLocation(visitor.ir.current_location); + block.SetEndLocation(visitor.ir.current_location); - return std::move(visitor.ir.block); + return block; } bool ArmTranslatorVisitor::ConditionPassed(Cond cond) { diff --git a/src/frontend/A32/translate/translate_arm/translate_arm.h b/src/frontend/A32/translate/translate_arm/translate_arm.h index 03d9e2c7..4d1db30b 100644 --- a/src/frontend/A32/translate/translate_arm/translate_arm.h +++ b/src/frontend/A32/translate/translate_arm/translate_arm.h @@ -26,7 +26,7 @@ enum class ConditionalState { struct ArmTranslatorVisitor final { using instruction_return_type = bool; - explicit ArmTranslatorVisitor(LocationDescriptor descriptor) : ir(descriptor) { + explicit ArmTranslatorVisitor(IR::Block& block, LocationDescriptor descriptor) : ir(block, descriptor) { ASSERT_MSG(!descriptor.TFlag(), "The processor must be in Arm mode"); } diff --git a/src/frontend/A32/translate/translate_thumb.cpp b/src/frontend/A32/translate/translate_thumb.cpp index 2d5485b8..b9342eb3 100644 --- a/src/frontend/A32/translate/translate_thumb.cpp +++ b/src/frontend/A32/translate/translate_thumb.cpp @@ -23,7 +23,7 @@ namespace { struct ThumbTranslatorVisitor final { using instruction_return_type = bool; - explicit ThumbTranslatorVisitor(LocationDescriptor descriptor) : ir(descriptor) { + explicit ThumbTranslatorVisitor(IR::Block& block, LocationDescriptor descriptor) : ir(block, descriptor) { ASSERT_MSG(descriptor.TFlag(), "The processor must be in Thumb mode"); } @@ -878,7 +878,8 @@ std::tuple ReadThumbInstruction(u32 arm_pc, MemoryReadCodeFu } // local namespace IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) { - ThumbTranslatorVisitor visitor{descriptor}; + IR::Block block{descriptor}; + ThumbTranslatorVisitor visitor{block, descriptor}; bool should_continue = true; while (should_continue) { @@ -906,12 +907,12 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType m s32 advance_pc = (inst_size == ThumbInstSize::Thumb16) ? 2 : 4; visitor.ir.current_location = visitor.ir.current_location.AdvancePC(advance_pc); - visitor.ir.block.CycleCount()++; + block.CycleCount()++; } - visitor.ir.block.SetEndLocation(visitor.ir.current_location); + block.SetEndLocation(visitor.ir.current_location); - return std::move(visitor.ir.block); + return block; } } // namespace A32 diff --git a/src/frontend/A64/ir_emitter.h b/src/frontend/A64/ir_emitter.h index 1111cc04..53f2d488 100644 --- a/src/frontend/A64/ir_emitter.h +++ b/src/frontend/A64/ir_emitter.h @@ -24,7 +24,7 @@ namespace A64 { */ class IREmitter : public IR::IREmitter { public: - explicit IREmitter(LocationDescriptor descriptor) : IR::IREmitter(descriptor), current_location(descriptor) {} + explicit IREmitter(IR::Block& block, LocationDescriptor descriptor) : IR::IREmitter(block), current_location(descriptor) {} LocationDescriptor current_location; diff --git a/src/frontend/A64/translate/impl/impl.h b/src/frontend/A64/translate/impl/impl.h index 301c29e9..a7261063 100644 --- a/src/frontend/A64/translate/impl/impl.h +++ b/src/frontend/A64/translate/impl/impl.h @@ -27,7 +27,7 @@ enum class MemOp { struct TranslatorVisitor final { using instruction_return_type = bool; - explicit TranslatorVisitor(LocationDescriptor descriptor) : ir(descriptor) {} + explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor) : ir(block, descriptor) {} A64::IREmitter ir; diff --git a/src/frontend/A64/translate/translate.cpp b/src/frontend/A64/translate/translate.cpp index eb998a2b..1114a1b2 100644 --- a/src/frontend/A64/translate/translate.cpp +++ b/src/frontend/A64/translate/translate.cpp @@ -14,7 +14,8 @@ namespace Dynarmic { namespace A64 { IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) { - TranslatorVisitor visitor{descriptor}; + IR::Block block{descriptor}; + TranslatorVisitor visitor{block, descriptor}; bool should_continue = true; while (should_continue) { @@ -28,14 +29,32 @@ IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory } visitor.ir.current_location = visitor.ir.current_location.AdvancePC(4); - visitor.ir.block.CycleCount()++; + block.CycleCount()++; } - ASSERT_MSG(visitor.ir.block.HasTerminal(), "Terminal has not been set"); + ASSERT_MSG(block.HasTerminal(), "Terminal has not been set"); - visitor.ir.block.SetEndLocation(visitor.ir.current_location); + block.SetEndLocation(visitor.ir.current_location); - return std::move(visitor.ir.block); + return block; +} + +bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction) { + TranslatorVisitor visitor{block, descriptor}; + + bool should_continue = true; + if (auto decoder = Decode(instruction)) { + should_continue = decoder->call(visitor, instruction); + } else { + should_continue = visitor.InterpretThisInstruction(); + } + + visitor.ir.current_location = visitor.ir.current_location.AdvancePC(4); + block.CycleCount()++; + + block.SetEndLocation(visitor.ir.current_location); + + return should_continue; } } // namespace A64 diff --git a/src/frontend/A64/translate/translate.h b/src/frontend/A64/translate/translate.h index ba16e7ff..4fa6f9f9 100644 --- a/src/frontend/A64/translate/translate.h +++ b/src/frontend/A64/translate/translate.h @@ -23,11 +23,20 @@ using MemoryReadCodeFuncType = std::function; /** * 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, FPCR 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); +/** + * This function translates a single provided instruction into our intermediate representation. + * @param block The block to append the IR for the instruction to. + * @param descriptor The location of the instruction. Includes information like PC, FPCR state, &c. + * @param instruction The instruction to translate. + * @return The translated instruction translated to the intermediate representation. + */ +bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction); + } // namespace A64 } // namespace Dynarmic diff --git a/src/frontend/ir/ir_emitter.h b/src/frontend/ir/ir_emitter.h index da83a063..ca7490ec 100644 --- a/src/frontend/ir/ir_emitter.h +++ b/src/frontend/ir/ir_emitter.h @@ -60,9 +60,9 @@ struct ResultAndGE { */ class IREmitter { public: - explicit IREmitter(IR::LocationDescriptor descriptor) : block(descriptor) {} + explicit IREmitter(Block& block) : block(block) {} - Block block; + Block& block; void Unimplemented();