New class for machine state

This commit is contained in:
Dani Messerman 2015-04-30 22:53:43 +03:00
parent 49483c67ca
commit 3864675b6d
6 changed files with 112 additions and 46 deletions

View File

@ -4,6 +4,7 @@ set(SRCS
ModuleGen.cpp ModuleGen.cpp
Disassembler.cpp Disassembler.cpp
InstructionBlock.cpp InstructionBlock.cpp
MachineState.cpp
Instructions/Instruction.cpp Instructions/Instruction.cpp
Instructions/DataProcessing.cpp Instructions/DataProcessing.cpp
@ -13,6 +14,7 @@ set(HEADERS
ModuleGen.h ModuleGen.h
Disassembler.h Disassembler.h
InstructionBlock.h InstructionBlock.h
MachineState.h
Instructions/Types.h Instructions/Types.h
Instructions/Instruction.h Instructions/Instruction.h

View File

@ -3,6 +3,7 @@
#include "Instructions/Instruction.h" #include "Instructions/Instruction.h"
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#include "MachineState.h"
InstructionBlock::InstructionBlock(ModuleGen* module, Instruction* instruction) InstructionBlock::InstructionBlock(ModuleGen* module, Instruction* instruction)
: module(module), : module(module),
@ -33,14 +34,12 @@ void InstructionBlock::GenerateCode()
llvm::Value *InstructionBlock::Read(Register reg) llvm::Value *InstructionBlock::Read(Register reg)
{ {
auto ib = module->IrBuilder(); return module->Machine()->ReadRegiser(reg);
return ib->CreateAlignedLoad(module->GetRegisterPtr(reg), 4);
} }
llvm::Value *InstructionBlock::Write(Register reg, llvm::Value *value) llvm::Value *InstructionBlock::Write(Register reg, llvm::Value *value)
{ {
auto ib = module->IrBuilder(); return module->Machine()->WriteRegiser(reg, value);
return ib->CreateAlignedStore(value, module->GetRegisterPtr(reg), 4);
} }
size_t InstructionBlock::Address() size_t InstructionBlock::Address()

View 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);
}

View 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;
};

View File

@ -8,6 +8,7 @@
#include <llvm/IR/Function.h> #include <llvm/IR/Function.h>
#include <llvm/IR/GlobalVariable.h> #include <llvm/IR/GlobalVariable.h>
#include <stack> #include <stack>
#include "MachineState.h"
using namespace llvm; using namespace llvm;
@ -15,6 +16,7 @@ ModuleGen::ModuleGen(llvm::Module* module)
: module(module) : module(module)
{ {
ir_builder = make_unique<IRBuilder<>>(getGlobalContext()); ir_builder = make_unique<IRBuilder<>>(getGlobalContext());
machine = make_unique<MachineState>(this);
} }
ModuleGen::~ModuleGen() ModuleGen::~ModuleGen()
@ -39,32 +41,9 @@ void ModuleGen::Run()
GenerateBlockAddressArray(); 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() void ModuleGen::GenerateGlobals()
{ {
auto registers_global_initializer = ConstantPointerNull::get(IntegerType::getInt32PtrTy(getGlobalContext())); machine->GenerateGlobals();
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");
auto get_block_address_function_type = FunctionType::get(ir_builder->getInt8PtrTy(), ir_builder->getInt32Ty(), false); 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); 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); auto basic_block = BasicBlock::Create(getGlobalContext(), "Entry", can_run_function);
ir_builder->SetInsertPoint(basic_block); 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()))); 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->CreateBr(run_function_re_entry);
ir_builder->SetInsertPoint(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())); 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); 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) for (auto &block : instruction_blocks)
{ {
ir_builder->SetInsertPoint(block->GetExitBasicBlock()); 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); ir_builder->CreateBr(run_function_re_entry);
} }
} }

View File

@ -5,6 +5,7 @@
enum class Register; enum class Register;
class InstructionBlock; class InstructionBlock;
class MachineState;
namespace llvm namespace llvm
{ {
@ -19,11 +20,10 @@ public:
void Run(); void Run();
// Returns the address of a register or a flag
llvm::Value *GetRegisterPtr(Register reg);
llvm::IRBuilder<> *IrBuilder() { return ir_builder.get(); } llvm::IRBuilder<> *IrBuilder() { return ir_builder.get(); }
llvm::Module *Module() { return module; } llvm::Module *Module() { return module; }
MachineState *Machine() { return machine.get(); }
private: private:
// Generates the declarations of all the globals of the module // Generates the declarations of all the globals of the module
void GenerateGlobals(); void GenerateGlobals();
@ -42,21 +42,11 @@ private:
// Adds all the basic blocks of an instruction to the run function // Adds all the basic blocks of an instruction to the run function
void AddInstructionsToRunFunction(); void AddInstructionsToRunFunction();
std::unique_ptr<MachineState> machine;
std::unique_ptr<llvm::IRBuilder<>> ir_builder; std::unique_ptr<llvm::IRBuilder<>> ir_builder;
llvm::Module *module; 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_base;
size_t block_address_array_size; size_t block_address_array_size;
/* /*