mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 11:41:04 +00:00
New class for machine state
This commit is contained in:
parent
49483c67ca
commit
3864675b6d
@ -4,6 +4,7 @@ set(SRCS
|
||||
ModuleGen.cpp
|
||||
Disassembler.cpp
|
||||
InstructionBlock.cpp
|
||||
MachineState.cpp
|
||||
|
||||
Instructions/Instruction.cpp
|
||||
Instructions/DataProcessing.cpp
|
||||
@ -13,6 +14,7 @@ set(HEADERS
|
||||
ModuleGen.h
|
||||
Disassembler.h
|
||||
InstructionBlock.h
|
||||
MachineState.h
|
||||
|
||||
Instructions/Types.h
|
||||
Instructions/Instruction.h
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "Instructions/Instruction.h"
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include "MachineState.h"
|
||||
|
||||
InstructionBlock::InstructionBlock(ModuleGen* module, Instruction* instruction)
|
||||
: module(module),
|
||||
@ -33,14 +34,12 @@ void InstructionBlock::GenerateCode()
|
||||
|
||||
llvm::Value *InstructionBlock::Read(Register reg)
|
||||
{
|
||||
auto ib = module->IrBuilder();
|
||||
return ib->CreateAlignedLoad(module->GetRegisterPtr(reg), 4);
|
||||
return module->Machine()->ReadRegiser(reg);
|
||||
}
|
||||
|
||||
llvm::Value *InstructionBlock::Write(Register reg, llvm::Value *value)
|
||||
{
|
||||
auto ib = module->IrBuilder();
|
||||
return ib->CreateAlignedStore(value, module->GetRegisterPtr(reg), 4);
|
||||
return module->Machine()->WriteRegiser(reg, value);
|
||||
}
|
||||
|
||||
size_t InstructionBlock::Address()
|
||||
|
55
src/binary_translation/MachineState.cpp
Normal file
55
src/binary_translation/MachineState.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "MachineState.h"
|
||||
#include "ModuleGen.h"
|
||||
#include "Instructions/Types.h"
|
||||
#include <llvm/IR/GlobalValue.h>
|
||||
#include <llvm/IR/Constants.h>
|
||||
#include <llvm/IR/LLVMContext.h>
|
||||
#include <llvm/IR/GlobalVariable.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
MachineState::MachineState(ModuleGen *module) : module(module)
|
||||
{
|
||||
}
|
||||
|
||||
void MachineState::GenerateGlobals()
|
||||
{
|
||||
auto registers_global_initializer = ConstantPointerNull::get(IntegerType::getInt32PtrTy(getGlobalContext()));
|
||||
registers_global = new GlobalVariable(*module->Module(), registers_global_initializer->getType(),
|
||||
false, GlobalValue::ExternalLinkage, registers_global_initializer, "Registers");
|
||||
|
||||
// Flags is stored internally as i1* indexed in multiples of 4
|
||||
auto flags_global_initializer = ConstantPointerNull::get(IntegerType::getInt1PtrTy(getGlobalContext()));
|
||||
flags_global = new GlobalVariable(*module->Module(), flags_global_initializer->getType(),
|
||||
false, GlobalValue::ExternalLinkage, flags_global_initializer, "Flags");
|
||||
}
|
||||
|
||||
Value* MachineState::ReadRegiser(Register reg)
|
||||
{
|
||||
auto load = module->IrBuilder()->CreateLoad(GetRegisterPtr(reg));
|
||||
return load;
|
||||
}
|
||||
|
||||
Value* MachineState::WriteRegiser(Register reg, Value *value)
|
||||
{
|
||||
auto store = module->IrBuilder()->CreateAlignedStore(value, GetRegisterPtr(reg), 4);
|
||||
return store;
|
||||
}
|
||||
|
||||
Value *MachineState::GetRegisterPtr(Register reg)
|
||||
{
|
||||
Value *global;
|
||||
unsigned index;
|
||||
if (reg <= Register::PC)
|
||||
{
|
||||
global = registers_global;
|
||||
index = static_cast<unsigned>(reg)-static_cast<unsigned>(Register::R0);
|
||||
}
|
||||
else
|
||||
{
|
||||
global = flags_global;
|
||||
index = static_cast<unsigned>(reg)-static_cast<unsigned>(Register::N);
|
||||
}
|
||||
auto base = module->IrBuilder()->CreateAlignedLoad(global, 4);
|
||||
return module->IrBuilder()->CreateConstInBoundsGEP1_32(base, index);
|
||||
}
|
41
src/binary_translation/MachineState.h
Normal file
41
src/binary_translation/MachineState.h
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
enum class Register;
|
||||
class ModuleGen;
|
||||
|
||||
namespace llvm
|
||||
{
|
||||
class Value;
|
||||
class GlobalVariable;
|
||||
}
|
||||
|
||||
/*
|
||||
Contains all the machine state:
|
||||
Registers, Flags, Memory
|
||||
*/
|
||||
class MachineState
|
||||
{
|
||||
public:
|
||||
MachineState(ModuleGen *module);
|
||||
|
||||
void GenerateGlobals();
|
||||
llvm::Value *ReadRegiser(Register reg);
|
||||
llvm::Value *WriteRegiser(Register reg, llvm::Value *value);
|
||||
|
||||
private:
|
||||
// Returns the address of a register or a flag
|
||||
llvm::Value *GetRegisterPtr(Register reg);
|
||||
|
||||
ModuleGen *module;
|
||||
|
||||
/*
|
||||
* u32 *Registers;
|
||||
* The registers of the cpu
|
||||
*/
|
||||
llvm::GlobalVariable *registers_global;
|
||||
/*
|
||||
* u32 *Flags;
|
||||
* The flags of the cpu
|
||||
* Orderered N, Z, C, V
|
||||
*/
|
||||
llvm::GlobalVariable *flags_global;
|
||||
};
|
@ -8,6 +8,7 @@
|
||||
#include <llvm/IR/Function.h>
|
||||
#include <llvm/IR/GlobalVariable.h>
|
||||
#include <stack>
|
||||
#include "MachineState.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -15,6 +16,7 @@ ModuleGen::ModuleGen(llvm::Module* module)
|
||||
: module(module)
|
||||
{
|
||||
ir_builder = make_unique<IRBuilder<>>(getGlobalContext());
|
||||
machine = make_unique<MachineState>(this);
|
||||
}
|
||||
|
||||
ModuleGen::~ModuleGen()
|
||||
@ -39,32 +41,9 @@ void ModuleGen::Run()
|
||||
GenerateBlockAddressArray();
|
||||
}
|
||||
|
||||
Value *ModuleGen::GetRegisterPtr(Register reg)
|
||||
{
|
||||
Value *global;
|
||||
unsigned index;
|
||||
if (reg <= Register::PC)
|
||||
{
|
||||
global = registers_global;
|
||||
index = static_cast<unsigned>(reg)-static_cast<unsigned>(Register::R0);
|
||||
}
|
||||
else
|
||||
{
|
||||
global = flags_global;
|
||||
index = static_cast<unsigned>(reg)-static_cast<unsigned>(Register::N);
|
||||
}
|
||||
auto base = ir_builder->CreateAlignedLoad(global, 4);
|
||||
return ir_builder->CreateConstInBoundsGEP1_32(base, index);
|
||||
}
|
||||
|
||||
void ModuleGen::GenerateGlobals()
|
||||
{
|
||||
auto registers_global_initializer = ConstantPointerNull::get(IntegerType::getInt32PtrTy(getGlobalContext()));
|
||||
registers_global = new GlobalVariable(*module, registers_global_initializer->getType(), false, GlobalValue::ExternalLinkage, registers_global_initializer, "Registers");
|
||||
|
||||
// Flags is stored internally as i1* indexed in multiples of 4
|
||||
auto flags_global_initializer = ConstantPointerNull::get(IntegerType::getInt1PtrTy(getGlobalContext()));
|
||||
flags_global = new GlobalVariable(*module, flags_global_initializer->getType(), false, GlobalValue::ExternalLinkage, flags_global_initializer, "Flags");
|
||||
machine->GenerateGlobals();
|
||||
|
||||
auto get_block_address_function_type = FunctionType::get(ir_builder->getInt8PtrTy(), ir_builder->getInt32Ty(), false);
|
||||
get_block_address_function = Function::Create(get_block_address_function_type, GlobalValue::PrivateLinkage, "GetBlockAddress", module);
|
||||
@ -146,7 +125,7 @@ void ModuleGen::GenerateCanRunFunction()
|
||||
auto basic_block = BasicBlock::Create(getGlobalContext(), "Entry", can_run_function);
|
||||
|
||||
ir_builder->SetInsertPoint(basic_block);
|
||||
auto block_address = ir_builder->CreateCall(get_block_address_function, ir_builder->CreateAlignedLoad(GetRegisterPtr(Register::PC), 4));
|
||||
auto block_address = ir_builder->CreateCall(get_block_address_function, machine->ReadRegiser(Register::PC));
|
||||
ir_builder->CreateRet(ir_builder->CreateICmpNE(block_address, ConstantPointerNull::get(ir_builder->getInt8PtrTy())));
|
||||
}
|
||||
|
||||
@ -178,7 +157,7 @@ void ModuleGen::GenerateRunFunction()
|
||||
ir_builder->CreateBr(run_function_re_entry);
|
||||
|
||||
ir_builder->SetInsertPoint(run_function_re_entry);
|
||||
auto block_address = ir_builder->CreateCall(get_block_address_function, ir_builder->CreateAlignedLoad(GetRegisterPtr(Register::PC), 4));
|
||||
auto block_address = ir_builder->CreateCall(get_block_address_function, Machine()->ReadRegiser(Register::PC));
|
||||
auto block_present_pred = ir_builder->CreateICmpNE(block_address, ConstantPointerNull::get(ir_builder->getInt8PtrTy()));
|
||||
ir_builder->CreateCondBr(block_present_pred, block_present_basic_block, block_not_present_basic_block);
|
||||
|
||||
@ -227,7 +206,7 @@ void ModuleGen::GenerateInstructionsTermination()
|
||||
for (auto &block : instruction_blocks)
|
||||
{
|
||||
ir_builder->SetInsertPoint(block->GetExitBasicBlock());
|
||||
ir_builder->CreateAlignedStore(ir_builder->getInt32(block->Address() + 4), GetRegisterPtr(Register::PC), 4);
|
||||
Machine()->WriteRegiser(Register::PC, ir_builder->getInt32(block->Address() + 4));
|
||||
ir_builder->CreateBr(run_function_re_entry);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
enum class Register;
|
||||
|
||||
class InstructionBlock;
|
||||
class MachineState;
|
||||
|
||||
namespace llvm
|
||||
{
|
||||
@ -19,11 +20,10 @@ public:
|
||||
|
||||
void Run();
|
||||
|
||||
// Returns the address of a register or a flag
|
||||
llvm::Value *GetRegisterPtr(Register reg);
|
||||
|
||||
llvm::IRBuilder<> *IrBuilder() { return ir_builder.get(); }
|
||||
llvm::Module *Module() { return module; }
|
||||
MachineState *Machine() { return machine.get(); }
|
||||
|
||||
private:
|
||||
// Generates the declarations of all the globals of the module
|
||||
void GenerateGlobals();
|
||||
@ -42,21 +42,11 @@ private:
|
||||
// Adds all the basic blocks of an instruction to the run function
|
||||
void AddInstructionsToRunFunction();
|
||||
|
||||
std::unique_ptr<MachineState> machine;
|
||||
|
||||
std::unique_ptr<llvm::IRBuilder<>> ir_builder;
|
||||
llvm::Module *module;
|
||||
|
||||
/*
|
||||
* u32 *Registers;
|
||||
* The registers of the cpu
|
||||
*/
|
||||
llvm::GlobalVariable *registers_global;
|
||||
/*
|
||||
* u32 *Flags;
|
||||
* The flags of the cpu
|
||||
* Orderered N, Z, C, V
|
||||
*/
|
||||
llvm::GlobalVariable *flags_global;
|
||||
|
||||
size_t block_address_array_base;
|
||||
size_t block_address_array_size;
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user