A64/translate: Add TranslateSingleInstruction function

This commit is contained in:
MerryMage 2018-01-12 19:34:25 +00:00
parent aa74a8130b
commit 61125d6dd1
9 changed files with 52 additions and 22 deletions

View file

@ -26,7 +26,7 @@ namespace A32 {
*/ */
class IREmitter : public IR::IREmitter { class IREmitter : public IR::IREmitter {
public: 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; LocationDescriptor current_location;

View file

@ -29,7 +29,8 @@ static bool CondCanContinue(ConditionalState cond_state, const A32::IREmitter& i
} }
IR::Block TranslateArm(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) { IR::Block TranslateArm(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) {
ArmTranslatorVisitor visitor{descriptor}; IR::Block block{descriptor};
ArmTranslatorVisitor visitor{block, descriptor};
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)) {
@ -49,7 +50,7 @@ IR::Block TranslateArm(LocationDescriptor descriptor, MemoryReadCodeFuncType mem
} }
visitor.ir.current_location = visitor.ir.current_location.AdvancePC(4); 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) { 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) { bool ArmTranslatorVisitor::ConditionPassed(Cond cond) {

View file

@ -26,7 +26,7 @@ enum class ConditionalState {
struct ArmTranslatorVisitor final { struct ArmTranslatorVisitor final {
using instruction_return_type = bool; 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"); ASSERT_MSG(!descriptor.TFlag(), "The processor must be in Arm mode");
} }

View file

@ -23,7 +23,7 @@ namespace {
struct ThumbTranslatorVisitor final { struct ThumbTranslatorVisitor final {
using instruction_return_type = bool; 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"); ASSERT_MSG(descriptor.TFlag(), "The processor must be in Thumb mode");
} }
@ -878,7 +878,8 @@ 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) {
ThumbTranslatorVisitor visitor{descriptor}; IR::Block block{descriptor};
ThumbTranslatorVisitor visitor{block, descriptor};
bool should_continue = true; bool should_continue = true;
while (should_continue) { while (should_continue) {
@ -906,12 +907,12 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType m
s32 advance_pc = (inst_size == ThumbInstSize::Thumb16) ? 2 : 4; s32 advance_pc = (inst_size == ThumbInstSize::Thumb16) ? 2 : 4;
visitor.ir.current_location = visitor.ir.current_location.AdvancePC(advance_pc); 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 } // namespace A32

View file

@ -24,7 +24,7 @@ namespace A64 {
*/ */
class IREmitter : public IR::IREmitter { class IREmitter : public IR::IREmitter {
public: 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; LocationDescriptor current_location;

View file

@ -27,7 +27,7 @@ enum class MemOp {
struct TranslatorVisitor final { struct TranslatorVisitor final {
using instruction_return_type = bool; using instruction_return_type = bool;
explicit TranslatorVisitor(LocationDescriptor descriptor) : ir(descriptor) {} explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor) : ir(block, descriptor) {}
A64::IREmitter ir; A64::IREmitter ir;

View file

@ -14,7 +14,8 @@ namespace Dynarmic {
namespace A64 { namespace A64 {
IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) { IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code) {
TranslatorVisitor visitor{descriptor}; IR::Block block{descriptor};
TranslatorVisitor visitor{block, descriptor};
bool should_continue = true; bool should_continue = true;
while (should_continue) { 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.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<TranslatorVisitor>(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 } // namespace A64

View file

@ -23,11 +23,20 @@ using MemoryReadCodeFuncType = std::function<u32(u64 vaddr)>;
/** /**
* 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, FPCR 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);
/**
* 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 A64
} // namespace Dynarmic } // namespace Dynarmic

View file

@ -60,9 +60,9 @@ struct ResultAndGE {
*/ */
class IREmitter { class IREmitter {
public: public:
explicit IREmitter(IR::LocationDescriptor descriptor) : block(descriptor) {} explicit IREmitter(Block& block) : block(block) {}
Block block; Block& block;
void Unimplemented(); void Unimplemented();