mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 12:01:04 +00:00
Basic disassembler
This commit is contained in:
parent
26ff6094e2
commit
a91f373f36
@ -3,17 +3,23 @@ set(SRCS
|
|||||||
CodeGen.cpp
|
CodeGen.cpp
|
||||||
ModuleGen.cpp
|
ModuleGen.cpp
|
||||||
Disassembler.cpp
|
Disassembler.cpp
|
||||||
Instruction.cpp
|
|
||||||
|
Instructions/Instruction.cpp
|
||||||
|
Instructions/DataProcessing.cpp
|
||||||
)
|
)
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
CodeGen.h
|
CodeGen.h
|
||||||
ModuleGen.h
|
ModuleGen.h
|
||||||
Disassembler.h
|
Disassembler.h
|
||||||
Instruction.h
|
|
||||||
|
Instructions/Types.h
|
||||||
|
Instructions/Instruction.h
|
||||||
|
Instructions/DataProcessing.h
|
||||||
)
|
)
|
||||||
|
|
||||||
create_directory_groups(${SRCS} ${HEADERS})
|
create_directory_groups(${SRCS} ${HEADERS})
|
||||||
|
|
||||||
|
include_directories(.)
|
||||||
add_executable(binary_translate ${SRCS} ${HEADERS})
|
add_executable(binary_translate ${SRCS} ${HEADERS})
|
||||||
target_link_libraries(binary_translate ${llvm_libs})
|
target_link_libraries(binary_translate ${llvm_libs})
|
||||||
target_link_libraries(binary_translate core common video_core)
|
target_link_libraries(binary_translate core common video_core)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "Disassembler.h"
|
#include "Disassembler.h"
|
||||||
#include "Instruction.h"
|
#include "Instructions/Instruction.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
std::vector<RegisterInstructionBase::CreateFunctionType> g_read_functions;
|
std::vector<RegisterInstructionBase::CreateFunctionType> g_read_functions;
|
||||||
@ -9,7 +9,7 @@ RegisterInstructionBase::RegisterInstructionBase(CreateFunctionType create_funct
|
|||||||
g_read_functions.push_back(create_function);
|
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)
|
for (auto read_function : g_read_functions)
|
||||||
{
|
{
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
class Instruction;
|
class Instruction;
|
||||||
|
|
||||||
class Disassmbler
|
class Disassembler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*
|
/*
|
||||||
@ -32,8 +32,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
static Instruction *Create(u32 instruction, u32 address)
|
static Instruction *Create(u32 instruction, u32 address)
|
||||||
{
|
{
|
||||||
auto result = new DerivedInstruction(instruction, address);
|
auto result = new DerivedInstruction();
|
||||||
if (!result->Read())
|
if (!result->Read(instruction, address))
|
||||||
{
|
{
|
||||||
delete result;
|
delete result;
|
||||||
return nullptr;
|
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 "Instruction.h"
|
||||||
#include <cassert>
|
#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)
|
bool Instruction::ReadFields(const std::initializer_list<FieldDefObject> &fields)
|
||||||
{
|
{
|
||||||
size_t total_bit_count = 0;
|
size_t total_bit_count = 0;
|
@ -7,15 +7,19 @@ class Instruction
|
|||||||
protected:
|
protected:
|
||||||
class FieldDefObject;
|
class FieldDefObject;
|
||||||
public:
|
public:
|
||||||
Instruction(u32 instruction, u32 address);
|
Instruction();
|
||||||
virtual ~Instruction();
|
virtual ~Instruction();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reads the instruction.
|
* Reads the instruction.
|
||||||
* Returns true on success, or false otherwise
|
* Returns true on success, or false otherwise
|
||||||
*/
|
*/
|
||||||
virtual bool Read() = 0;
|
bool Read(u32 instruction, u32 address);
|
||||||
protected:
|
protected:
|
||||||
|
/*
|
||||||
|
* Derived classes should override this, and implement it by calling ReadFields
|
||||||
|
*/
|
||||||
|
virtual bool Decode() = 0;
|
||||||
/*
|
/*
|
||||||
* Reads fields from the instruction
|
* Reads fields from the instruction
|
||||||
* The fields come most significant first
|
* 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 "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/Function.h>
|
||||||
#include <llvm/IR/GlobalVariable.h>
|
#include <llvm/IR/GlobalVariable.h>
|
||||||
|
|
||||||
@ -19,6 +23,8 @@ void ModuleGen::Run()
|
|||||||
GenerateGlobals();
|
GenerateGlobals();
|
||||||
GenerateCanRunFunction();
|
GenerateCanRunFunction();
|
||||||
GenerateRunFunction();
|
GenerateRunFunction();
|
||||||
|
|
||||||
|
GenerateBlocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleGen::GenerateGlobals()
|
void ModuleGen::GenerateGlobals()
|
||||||
@ -49,4 +55,16 @@ void ModuleGen::GenerateRunFunction()
|
|||||||
|
|
||||||
ir_builder->SetInsertPoint(basic_block);
|
ir_builder->SetInsertPoint(basic_block);
|
||||||
ir_builder->CreateRetVoid();
|
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 GenerateGlobals();
|
||||||
void GenerateCanRunFunction();
|
void GenerateCanRunFunction();
|
||||||
void GenerateRunFunction();
|
void GenerateRunFunction();
|
||||||
|
void GenerateBlocks();
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<llvm::IRBuilder<>> ir_builder;
|
std::unique_ptr<llvm::IRBuilder<>> ir_builder;
|
||||||
llvm::Module *module;
|
llvm::Module *module;
|
||||||
|
Loading…
Reference in New Issue
Block a user