mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 11:31:04 +00:00
Basic disassembler
This commit is contained in:
parent
26ff6094e2
commit
a91f373f36
@ -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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "Disassembler.h"
|
||||
#include "Instruction.h"
|
||||
#include "Instructions/Instruction.h"
|
||||
#include <vector>
|
||||
|
||||
std::vector<RegisterInstructionBase::CreateFunctionType> g_read_functions;
|
||||
@ -9,7 +9,7 @@ RegisterInstructionBase::RegisterInstructionBase(CreateFunctionType create_funct
|
||||
g_read_functions.push_back(create_function);
|
||||
}
|
||||
|
||||
std::unique_ptr<Instruction> Disassmbler::Disassemble(u32 instruction, u32 address)
|
||||
std::unique_ptr<Instruction> Disassembler::Disassemble(u32 instruction, u32 address)
|
||||
{
|
||||
for (auto read_function : g_read_functions)
|
||||
{
|
||||
|
@ -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;
|
||||
|
15
src/binary_translation/Instructions/DataProcessing.cpp
Normal file
15
src/binary_translation/Instructions/DataProcessing.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "DataProcessing.h"
|
||||
#include "Disassembler.h"
|
||||
|
||||
static RegisterInstruction<DataProcessing> 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;
|
||||
}
|
36
src/binary_translation/Instructions/DataProcessing.h
Normal file
36
src/binary_translation/Instructions/DataProcessing.h
Normal file
@ -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;
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
#include "Instruction.h"
|
||||
#include <cassert>
|
||||
|
||||
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<FieldDefObject> &fields)
|
||||
{
|
||||
size_t total_bit_count = 0;
|
@ -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
|
14
src/binary_translation/Instructions/Types.h
Normal file
14
src/binary_translation/Instructions/Types.h
Normal file
@ -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
|
||||
};
|
@ -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 <llvm/IR/Function.h>
|
||||
#include <llvm/IR/GlobalVariable.h>
|
||||
|
||||
@ -19,6 +23,8 @@ void ModuleGen::Run()
|
||||
GenerateGlobals();
|
||||
GenerateCanRunFunction();
|
||||
GenerateRunFunction();
|
||||
|
||||
GenerateBlocks();
|
||||
}
|
||||
|
||||
void ModuleGen::GenerateGlobals()
|
||||
@ -50,3 +56,15 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ public:
|
||||
void GenerateGlobals();
|
||||
void GenerateCanRunFunction();
|
||||
void GenerateRunFunction();
|
||||
void GenerateBlocks();
|
||||
private:
|
||||
std::unique_ptr<llvm::IRBuilder<>> ir_builder;
|
||||
llvm::Module *module;
|
||||
|
Loading…
Reference in New Issue
Block a user