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
927e20fb6e
commit
26ff6094e2
@ -2,10 +2,14 @@ set(SRCS
|
||||
main.cpp
|
||||
CodeGen.cpp
|
||||
ModuleGen.cpp
|
||||
Disassembler.cpp
|
||||
Instruction.cpp
|
||||
)
|
||||
set(HEADERS
|
||||
CodeGen.h
|
||||
ModuleGen.h
|
||||
Disassembler.h
|
||||
Instruction.h
|
||||
)
|
||||
|
||||
create_directory_groups(${SRCS} ${HEADERS})
|
||||
|
23
src/binary_translation/Disassembler.cpp
Normal file
23
src/binary_translation/Disassembler.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "Disassembler.h"
|
||||
#include "Instruction.h"
|
||||
#include <vector>
|
||||
|
||||
std::vector<RegisterInstructionBase::CreateFunctionType> g_read_functions;
|
||||
|
||||
RegisterInstructionBase::RegisterInstructionBase(CreateFunctionType create_function)
|
||||
{
|
||||
g_read_functions.push_back(create_function);
|
||||
}
|
||||
|
||||
std::unique_ptr<Instruction> Disassmbler::Disassemble(u32 instruction, u32 address)
|
||||
{
|
||||
for (auto read_function : g_read_functions)
|
||||
{
|
||||
auto result = read_function(instruction, address);
|
||||
if (result != nullptr)
|
||||
{
|
||||
return std::unique_ptr<Instruction>(result);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
43
src/binary_translation/Disassembler.h
Normal file
43
src/binary_translation/Disassembler.h
Normal file
@ -0,0 +1,43 @@
|
||||
#include "common/common_types.h"
|
||||
#include <memory>
|
||||
|
||||
class Instruction;
|
||||
|
||||
class Disassmbler
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Returns the instruction at address or null if unknown or not translatable
|
||||
* address is used for PC relative operations
|
||||
*/
|
||||
static std::unique_ptr<Instruction> Disassemble(u32 instruction, u32 address);
|
||||
};
|
||||
|
||||
class RegisterInstructionBase
|
||||
{
|
||||
public:
|
||||
typedef Instruction *(*CreateFunctionType)(u32 instruction, u32 address);
|
||||
|
||||
RegisterInstructionBase(CreateFunctionType create_function);
|
||||
};
|
||||
|
||||
/*
|
||||
* Instantiate this class in a source file to register instruction in the disassembler
|
||||
*/
|
||||
template<typename DerivedInstruction>
|
||||
class RegisterInstruction : RegisterInstructionBase
|
||||
{
|
||||
public:
|
||||
RegisterInstruction() : RegisterInstructionBase(&RegisterInstruction::Create) {}
|
||||
private:
|
||||
static Instruction *Create(u32 instruction, u32 address)
|
||||
{
|
||||
auto result = new DerivedInstruction(instruction, address);
|
||||
if (!result->Read())
|
||||
{
|
||||
delete result;
|
||||
return nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
52
src/binary_translation/Instruction.cpp
Normal file
52
src/binary_translation/Instruction.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include "Instruction.h"
|
||||
#include <cassert>
|
||||
|
||||
Instruction::Instruction(u32 instruction, u32 address) : instruction(instruction), address(address)
|
||||
{
|
||||
}
|
||||
|
||||
Instruction::~Instruction()
|
||||
{
|
||||
}
|
||||
|
||||
bool Instruction::ReadFields(const std::initializer_list<FieldDefObject> &fields)
|
||||
{
|
||||
size_t total_bit_count = 0;
|
||||
auto current_instruction = instruction;
|
||||
|
||||
for (auto &field : fields)
|
||||
{
|
||||
total_bit_count += field.BitCount();
|
||||
// Read the upper bits
|
||||
auto value = current_instruction >> (32 - field.BitCount());
|
||||
if (!field.Read(value)) return false;
|
||||
// Remove the upper bits
|
||||
current_instruction <<= field.BitCount();
|
||||
}
|
||||
assert(total_bit_count == 32);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Instruction::FieldDefObject::FieldDefObject(u32 bit_count, u32 const_value)
|
||||
: bit_count(bit_count), const_value(const_value), constant(true)
|
||||
{
|
||||
}
|
||||
|
||||
Instruction::FieldDefObject::FieldDefObject(u32 bit_count, void* field_address, WriteFunctionType write_function)
|
||||
: bit_count(bit_count), field_address(field_address), write_function(write_function), constant(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool Instruction::FieldDefObject::Read(u32 value) const
|
||||
{
|
||||
if (constant)
|
||||
{
|
||||
return value == const_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
write_function(value, field_address);
|
||||
return true;
|
||||
}
|
||||
}
|
87
src/binary_translation/Instruction.h
Normal file
87
src/binary_translation/Instruction.h
Normal file
@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
#include "common/common_types.h"
|
||||
#include <initializer_list>
|
||||
|
||||
class Instruction
|
||||
{
|
||||
protected:
|
||||
class FieldDefObject;
|
||||
public:
|
||||
Instruction(u32 instruction, u32 address);
|
||||
virtual ~Instruction();
|
||||
|
||||
/*
|
||||
* Reads the instruction.
|
||||
* Returns true on success, or false otherwise
|
||||
*/
|
||||
virtual bool Read() = 0;
|
||||
protected:
|
||||
/*
|
||||
* Reads fields from the instruction
|
||||
* The fields come most significant first
|
||||
*/
|
||||
bool ReadFields(const std::initializer_list<FieldDefObject> &fields);
|
||||
|
||||
/*
|
||||
* Creates a field definition for a constant
|
||||
*/
|
||||
template<size_t BitCount>
|
||||
static FieldDefObject FieldDef(u32 value);
|
||||
/*
|
||||
* Creates a field definition for a field
|
||||
*/
|
||||
template<size_t BitCount, typename Type>
|
||||
static FieldDefObject FieldDef(Type *field);
|
||||
|
||||
private:
|
||||
/*
|
||||
* Function used by FieldDefObject to write to a field
|
||||
*/
|
||||
template<typename Type>
|
||||
static void WriteFunction(u32 value, void *field_address);
|
||||
|
||||
// Instruction value
|
||||
u32 instruction;
|
||||
// Instruction address
|
||||
u32 address;
|
||||
};
|
||||
|
||||
/*
|
||||
* Object produced by FieldDef
|
||||
*/
|
||||
class Instruction::FieldDefObject
|
||||
{
|
||||
public:
|
||||
typedef void(*WriteFunctionType)(u32 value, void *field_address);
|
||||
public:
|
||||
// Constant
|
||||
FieldDefObject(u32 bit_count, u32 const_value);
|
||||
// Field
|
||||
FieldDefObject(u32 bit_count, void *field_address, WriteFunctionType write_function);
|
||||
bool Read(u32 value) const;
|
||||
u32 BitCount() const { return bit_count; }
|
||||
private:
|
||||
u32 bit_count;
|
||||
u32 const_value;
|
||||
void *field_address;
|
||||
WriteFunctionType write_function;
|
||||
bool constant;
|
||||
};
|
||||
|
||||
template <size_t BitCount>
|
||||
Instruction::FieldDefObject Instruction::FieldDef(u32 value)
|
||||
{
|
||||
return FieldDefObject(BitCount, value);
|
||||
}
|
||||
|
||||
template <size_t BitCount, typename Type>
|
||||
Instruction::FieldDefObject Instruction::FieldDef(Type* field)
|
||||
{
|
||||
return FieldDefObject(BitCount, field, &Instruction::WriteFunction<Type>);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void Instruction::WriteFunction(u32 value, void *field_address)
|
||||
{
|
||||
*static_cast<Type *>(field_address) = static_cast<Type>(value);
|
||||
}
|
Loading…
Reference in New Issue
Block a user