#include "MachineState.h" #include "ModuleGen.h" #include "Instructions/Types.h" #include #include #include #include #include "TBAA.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"); auto memory_read_32_signature = FunctionType::get(IntegerType::getInt32Ty(getGlobalContext()), IntegerType::getInt32Ty(getGlobalContext()), false); auto memory_read_32_ptr = PointerType::get(memory_read_32_signature, 0); auto memory_read_32_initializer = ConstantPointerNull::get(memory_read_32_ptr); memory_read_32_global = new GlobalVariable(*module->Module(), memory_read_32_ptr, false, GlobalValue::ExternalLinkage, memory_read_32_initializer, "Memory::Read32"); } 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)) * 4; } auto base = module->IrBuilder()->CreateAlignedLoad(global, 4); module->GetTBAA()->TagConst(base); return module->IrBuilder()->CreateConstInBoundsGEP1_32(base, index); } Value* MachineState::ReadRegiser(Register reg) { auto load = module->IrBuilder()->CreateAlignedLoad(GetRegisterPtr(reg), 4); module->GetTBAA()->TagRegister(load, reg); return load; } Value* MachineState::WriteRegiser(Register reg, Value *value) { auto store = module->IrBuilder()->CreateAlignedStore(value, GetRegisterPtr(reg), 4); module->GetTBAA()->TagRegister(store, reg); return store; } Value* MachineState::ConditionPassed(Condition cond) { auto ir_builder = module->IrBuilder(); Value *pred = nullptr; auto not = false; switch (cond) { case Condition::NE: case Condition::CC: case Condition::PL: case Condition::VC: case Condition::LS: case Condition::LT: case Condition::LE: not = true; cond = (Condition)((int)cond - 1); } switch (cond) { case Condition::EQ: pred = ReadRegiser(Register::Z); break; case Condition::CS: pred = ReadRegiser(Register::C); break; case Condition::MI: pred = ReadRegiser(Register::N); break; case Condition::VS: pred = ReadRegiser(Register::V); break; case Condition::HI: pred = ir_builder->CreateAnd(ReadRegiser(Register::C), ir_builder->CreateNot(ReadRegiser(Register::Z))); break; case Condition::GE: pred = ir_builder->CreateICmpEQ(ReadRegiser(Register::N), ReadRegiser(Register::V)); break; case Condition::GT: pred = ir_builder->CreateAnd(ir_builder->CreateNot(ReadRegiser(Register::Z)), ir_builder->CreateICmpEQ(ReadRegiser(Register::N), ReadRegiser(Register::V))); break; case Condition::AL: pred = ir_builder->getInt1(true); default: assert(false, "Invalid condition"); } if (not) pred = ir_builder->CreateNot(pred); return pred; } llvm::Value* MachineState::ReadMemory32(llvm::Value* address) { auto ir_builder = module->IrBuilder(); auto memory_read_32 = ir_builder->CreateLoad(memory_read_32_global); module->GetTBAA()->TagConst(memory_read_32); auto call = ir_builder->CreateCall(memory_read_32, address); call->setOnlyReadsMemory(); module->GetTBAA()->TagMemory(call); return call; }