mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 13:41:05 +00:00
Basic disassembler
This commit is contained in:
parent
927e20fb6e
commit
26ff6094e2
@ -2,10 +2,14 @@ set(SRCS
|
|||||||
main.cpp
|
main.cpp
|
||||||
CodeGen.cpp
|
CodeGen.cpp
|
||||||
ModuleGen.cpp
|
ModuleGen.cpp
|
||||||
|
Disassembler.cpp
|
||||||
|
Instruction.cpp
|
||||||
)
|
)
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
CodeGen.h
|
CodeGen.h
|
||||||
ModuleGen.h
|
ModuleGen.h
|
||||||
|
Disassembler.h
|
||||||
|
Instruction.h
|
||||||
)
|
)
|
||||||
|
|
||||||
create_directory_groups(${SRCS} ${HEADERS})
|
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