diff --git a/src/binary_translation/CMakeLists.txt b/src/binary_translation/CMakeLists.txt index 7f260b1d6..04379bb0c 100644 --- a/src/binary_translation/CMakeLists.txt +++ b/src/binary_translation/CMakeLists.txt @@ -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 diff --git a/src/binary_translation/InstructionBlock.cpp b/src/binary_translation/InstructionBlock.cpp index bb80284cb..9cf7ef91d 100644 --- a/src/binary_translation/InstructionBlock.cpp +++ b/src/binary_translation/InstructionBlock.cpp @@ -3,6 +3,7 @@ #include "Instructions/Instruction.h" #include #include +#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() diff --git a/src/binary_translation/MachineState.cpp b/src/binary_translation/MachineState.cpp new file mode 100644 index 000000000..e992dc1d5 --- /dev/null +++ b/src/binary_translation/MachineState.cpp @@ -0,0 +1,55 @@ +#include "MachineState.h" +#include "ModuleGen.h" +#include "Instructions/Types.h" +#include +#include +#include +#include + +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(reg)-static_cast(Register::R0); + } + else + { + global = flags_global; + index = static_cast(reg)-static_cast(Register::N); + } + auto base = module->IrBuilder()->CreateAlignedLoad(global, 4); + return module->IrBuilder()->CreateConstInBoundsGEP1_32(base, index); +} \ No newline at end of file diff --git a/src/binary_translation/MachineState.h b/src/binary_translation/MachineState.h new file mode 100644 index 000000000..515ce36e5 --- /dev/null +++ b/src/binary_translation/MachineState.h @@ -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; +}; \ No newline at end of file diff --git a/src/binary_translation/ModuleGen.cpp b/src/binary_translation/ModuleGen.cpp index a870d800e..51dc919b5 100644 --- a/src/binary_translation/ModuleGen.cpp +++ b/src/binary_translation/ModuleGen.cpp @@ -8,6 +8,7 @@ #include #include #include +#include "MachineState.h" using namespace llvm; @@ -15,6 +16,7 @@ ModuleGen::ModuleGen(llvm::Module* module) : module(module) { ir_builder = make_unique>(getGlobalContext()); + machine = make_unique(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(reg)-static_cast(Register::R0); - } - else - { - global = flags_global; - index = static_cast(reg)-static_cast(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); } } diff --git a/src/binary_translation/ModuleGen.h b/src/binary_translation/ModuleGen.h index fde2fffd3..a80936103 100644 --- a/src/binary_translation/ModuleGen.h +++ b/src/binary_translation/ModuleGen.h @@ -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 machine; + std::unique_ptr> 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; /*