diff --git a/src/binary_translation/CMakeLists.txt b/src/binary_translation/CMakeLists.txt index a71ba222f..435202191 100644 --- a/src/binary_translation/CMakeLists.txt +++ b/src/binary_translation/CMakeLists.txt @@ -3,17 +3,23 @@ set(SRCS CodeGen.cpp ModuleGen.cpp Disassembler.cpp - Instruction.cpp + + Instructions/Instruction.cpp + Instructions/DataProcessing.cpp ) set(HEADERS CodeGen.h ModuleGen.h Disassembler.h - Instruction.h + + Instructions/Types.h + Instructions/Instruction.h + Instructions/DataProcessing.h ) create_directory_groups(${SRCS} ${HEADERS}) +include_directories(.) add_executable(binary_translate ${SRCS} ${HEADERS}) target_link_libraries(binary_translate ${llvm_libs}) target_link_libraries(binary_translate core common video_core) diff --git a/src/binary_translation/Disassembler.cpp b/src/binary_translation/Disassembler.cpp index 1884c3a70..3a2e12182 100644 --- a/src/binary_translation/Disassembler.cpp +++ b/src/binary_translation/Disassembler.cpp @@ -1,5 +1,5 @@ #include "Disassembler.h" -#include "Instruction.h" +#include "Instructions/Instruction.h" #include std::vector g_read_functions; @@ -9,7 +9,7 @@ RegisterInstructionBase::RegisterInstructionBase(CreateFunctionType create_funct g_read_functions.push_back(create_function); } -std::unique_ptr Disassmbler::Disassemble(u32 instruction, u32 address) +std::unique_ptr Disassembler::Disassemble(u32 instruction, u32 address) { for (auto read_function : g_read_functions) { diff --git a/src/binary_translation/Disassembler.h b/src/binary_translation/Disassembler.h index aef3469a6..9987634e9 100644 --- a/src/binary_translation/Disassembler.h +++ b/src/binary_translation/Disassembler.h @@ -3,7 +3,7 @@ class Instruction; -class Disassmbler +class Disassembler { public: /* @@ -32,8 +32,8 @@ public: private: static Instruction *Create(u32 instruction, u32 address) { - auto result = new DerivedInstruction(instruction, address); - if (!result->Read()) + auto result = new DerivedInstruction(); + if (!result->Read(instruction, address)) { delete result; return nullptr; diff --git a/src/binary_translation/Instructions/DataProcessing.cpp b/src/binary_translation/Instructions/DataProcessing.cpp new file mode 100644 index 000000000..6151b37a2 --- /dev/null +++ b/src/binary_translation/Instructions/DataProcessing.cpp @@ -0,0 +1,15 @@ +#include "DataProcessing.h" +#include "Disassembler.h" + +static RegisterInstruction register_instruction; + +bool DataProcessing::Decode() +{ + if (ReadFields({ FieldDef<4>(&cond), FieldDef<3>(1), FieldDef<4>(&short_op), FieldDef<1>(&s), FieldDef<4>(&rn), + FieldDef<4>(&rd), FieldDef<12>(&imm12) })) + { + form = Form::Immediate; + return true; + } + return false; +} \ No newline at end of file diff --git a/src/binary_translation/Instructions/DataProcessing.h b/src/binary_translation/Instructions/DataProcessing.h new file mode 100644 index 000000000..056c6d12b --- /dev/null +++ b/src/binary_translation/Instructions/DataProcessing.h @@ -0,0 +1,36 @@ +#include "Instruction.h" +#include "Types.h" + +/* + * Data processing instructions + * ARMv7-A 5.2.1 (register), 5.2.2 (register-shifted register, 5.2.3 (immediate) + */ + +class DataProcessing : public Instruction +{ +public: + /* + * The 4 bit op types (1 = 0001x: BitwiseXor, etc...) + */ + enum class ShortOpType + { + BitwiseAnd = 0, BitwiseXor, Subtract, RevSubtract, Add, AddWithCarry, SubtractWithCarry, ReverseSubtractWithCarry, + // Compare, Test, Misc + BitwiseOr = 12, Move, BitwiseBitClear, BitwiseNot + }; + enum class Form + { + Register, RegisterShiftedRegister, Immediate + }; + +public: + virtual bool Decode() override; +private: + Form form; + Condition cond; + ShortOpType short_op; + bool s; + Register rn; + Register rd; + u32 imm12; +}; \ No newline at end of file diff --git a/src/binary_translation/Instruction.cpp b/src/binary_translation/Instructions/Instruction.cpp similarity index 85% rename from src/binary_translation/Instruction.cpp rename to src/binary_translation/Instructions/Instruction.cpp index f7960e36a..2ec84e3b3 100644 --- a/src/binary_translation/Instruction.cpp +++ b/src/binary_translation/Instructions/Instruction.cpp @@ -1,7 +1,7 @@ #include "Instruction.h" #include -Instruction::Instruction(u32 instruction, u32 address) : instruction(instruction), address(address) +Instruction::Instruction() { } @@ -9,6 +9,14 @@ Instruction::~Instruction() { } +bool Instruction::Read(u32 instruction, u32 address) +{ + this->instruction = instruction; + this->address = address; + // Call the read of derived class + return Decode(); +} + bool Instruction::ReadFields(const std::initializer_list &fields) { size_t total_bit_count = 0; diff --git a/src/binary_translation/Instruction.h b/src/binary_translation/Instructions/Instruction.h similarity index 91% rename from src/binary_translation/Instruction.h rename to src/binary_translation/Instructions/Instruction.h index c784d1f86..794b9721a 100644 --- a/src/binary_translation/Instruction.h +++ b/src/binary_translation/Instructions/Instruction.h @@ -7,15 +7,19 @@ class Instruction protected: class FieldDefObject; public: - Instruction(u32 instruction, u32 address); + Instruction(); virtual ~Instruction(); /* * Reads the instruction. * Returns true on success, or false otherwise */ - virtual bool Read() = 0; + bool Read(u32 instruction, u32 address); protected: + /* + * Derived classes should override this, and implement it by calling ReadFields + */ + virtual bool Decode() = 0; /* * Reads fields from the instruction * The fields come most significant first diff --git a/src/binary_translation/Instructions/Types.h b/src/binary_translation/Instructions/Types.h new file mode 100644 index 000000000..d9a272b5d --- /dev/null +++ b/src/binary_translation/Instructions/Types.h @@ -0,0 +1,14 @@ +/* + * A register in a broad sense: R0-R15, and flags + */ +enum class Register +{ + R0, R1, R2, R3, R4, R5, R6, R7, + R8, R9, R10, R11, R12, SP, LR, PC, + N, Z, C, V +}; + +enum class Condition +{ + EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, Invalid +}; \ No newline at end of file diff --git a/src/binary_translation/ModuleGen.cpp b/src/binary_translation/ModuleGen.cpp index 044681602..b34c631d1 100644 --- a/src/binary_translation/ModuleGen.cpp +++ b/src/binary_translation/ModuleGen.cpp @@ -1,4 +1,8 @@ #include "ModuleGen.h" +#include "Disassembler.h" +#include "core/loader/loader.h" +#include "core/mem_map.h" +#include "Instructions/Instruction.h" #include #include @@ -19,6 +23,8 @@ void ModuleGen::Run() GenerateGlobals(); GenerateCanRunFunction(); GenerateRunFunction(); + + GenerateBlocks(); } void ModuleGen::GenerateGlobals() @@ -49,4 +55,16 @@ void ModuleGen::GenerateRunFunction() ir_builder->SetInsertPoint(basic_block); ir_builder->CreateRetVoid(); +} + +void ModuleGen::GenerateBlocks() +{ + for (auto i = Loader::ROMCodeStart; i <= Loader::ROMCodeStart + Loader::ROMCodeSize - 4; i += 4) + { + auto instruction = Disassembler::Disassemble(Memory::Read32(i), i); + if (instruction != nullptr) + { + LOG_DEBUG(BinaryTranslator, "Instruction at %08x", i); + } + } } \ No newline at end of file diff --git a/src/binary_translation/ModuleGen.h b/src/binary_translation/ModuleGen.h index 1ed03fa47..a50721770 100644 --- a/src/binary_translation/ModuleGen.h +++ b/src/binary_translation/ModuleGen.h @@ -15,6 +15,7 @@ public: void GenerateGlobals(); void GenerateCanRunFunction(); void GenerateRunFunction(); + void GenerateBlocks(); private: std::unique_ptr> ir_builder; llvm::Module *module;