diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 2fa10608be..12662a1e30 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -1205,7 +1205,7 @@ extern void ppu_initialize(const ppu_module& info) sha1_finish(&ctx, output); // Version, module name and hash: vX-liblv2.sprx-0123456789ABCDEF.obj - fmt::append(obj_name, "v1%s-%016X-%s.obj", part.name, reinterpret_cast&>(output), jit.cpu()); + fmt::append(obj_name, "v2%s-%016X-%s.obj", part.name, reinterpret_cast&>(output), jit.cpu()); } if (Emu.IsStopped()) @@ -1352,7 +1352,7 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co Emu.CallAfter([=]() { - dlg->Create("Compiling PPU module " + obj_name + "\nPlease wait..."); + dlg->Create("Compiling PPU module:\n" + obj_name + "\nPlease wait..."); }); // Translate functions diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 7cea21ce0c..8b416edb6b 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -38,11 +38,23 @@ public: f64 fpr[32] = {}; // Floating Point Registers v128 vr[32] = {}; // Vector Registers - alignas(16) bool cr[32] = {}; // Condition Registers (abstract representation) + alignas(16) bool cr[32] = {}; // Condition Registers (unpacked) + + alignas(16) struct // Floating-Point Status and Control Register (unpacked) + { + // TODO + bool _start[16]{}; + bool fl{}; // FPCC.FL + bool fg{}; // FPCC.FG + bool fe{}; // FPCC.FE + bool fu{}; // FPCC.FU + bool _end[12]{}; + } + fpscr; u64 lr{}; // Link Register u64 ctr{}; // Counter Register - u32 vrsave{0xffffffff}; // VR Save Register (almost unused) + u32 vrsave{0xffffffff}; // VR Save Register u32 cia{}; // Current Instruction Address // Pack CR bits @@ -111,15 +123,6 @@ public: */ bool nj = true; - struct // Floating-Point Status and Control Register (abstract representation) - { - bool fl{}; // FPCC.FL - bool fg{}; // FPCC.FG - bool fe{}; // FPCC.FE - bool fu{}; // FPCC.FU - } - fpscr; - u32 raddr{0}; // Reservation addr u64 rtime{0}; u64 rdata{0}; // Reservation data diff --git a/rpcs3/Emu/Cell/PPUTranslator.cpp b/rpcs3/Emu/Cell/PPUTranslator.cpp index e5544273dc..cecf161762 100644 --- a/rpcs3/Emu/Cell/PPUTranslator.cpp +++ b/rpcs3/Emu/Cell/PPUTranslator.cpp @@ -85,11 +85,12 @@ PPUTranslator::PPUTranslator(LLVMContext& context, Module* module, u64 base) thread_struct.insert(thread_struct.end(), 32, GetType()); // fpr[0..31] thread_struct.insert(thread_struct.end(), 32, GetType()); // vr[0..31] thread_struct.insert(thread_struct.end(), 32, GetType()); // cr[0..31] + thread_struct.insert(thread_struct.end(), 32, GetType()); // fpscr thread_struct.insert(thread_struct.end(), 2, GetType()); // lr, ctr thread_struct.insert(thread_struct.end(), 2, GetType()); // vrsave, cia thread_struct.insert(thread_struct.end(), 3, GetType()); // so, ov, ca thread_struct.insert(thread_struct.end(), 1, GetType()); // cnt - thread_struct.insert(thread_struct.end(), 6, GetType()); // sat, nj, FPCC + thread_struct.insert(thread_struct.end(), 2, GetType()); // sat, nj m_thread_type = StructType::create(m_context, thread_struct, "context_t"); @@ -122,19 +123,24 @@ Function* PPUTranslator::Translate(const ppu_function& info) std::fill(std::begin(m_globals), std::end(m_globals), nullptr); std::fill(std::begin(m_locals), std::end(m_locals), nullptr); - std::fill(std::begin(m_writes), std::end(m_writes), false); - std::fill(std::begin(m_reads), std::end(m_reads), false); - /* Create builders */ IRBuilder<> irb(m_entry = BasicBlock::Create(m_context, "__entry", m_function)); m_ir = &irb; - m_body = BasicBlock::Create(m_context, "__body", m_function); - irb.SetInsertPoint(m_body); - - /* Create context variables */ m_thread = &*m_function->getArgumentList().begin(); m_base_loaded = m_ir->CreateLoad(m_base); + m_body = BasicBlock::Create(m_context, "__body", m_function); + + // Check status register in the entry block + const auto vstate = m_ir->CreateLoad(m_ir->CreateStructGEP(nullptr, m_thread, 1), true); + const auto vcheck = BasicBlock::Create(m_context, "__test", m_function); + m_ir->CreateCondBr(m_ir->CreateIsNull(vstate), m_body, vcheck, m_md_likely); + + // Create tail call to the check function + m_ir->SetInsertPoint(vcheck); + Call(GetType(), "__check", m_thread, m_ir->getInt64(m_start_addr)); + m_ir->CreateRetVoid(); + m_ir->SetInsertPoint(m_body); // Process blocks const auto block = std::make_pair(info.addr, info.size); @@ -211,61 +217,54 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect) m_ir->CreateRetVoid(); } -void PPUTranslator::FlushRegisters() +Value* PPUTranslator::RegInit(Value*& local) { - if (m_entry->getTerminator()) + const auto index = ::narrow(&local - m_locals); + + if (!m_globals[index]) { - return; + // Initialize global, will be written in FlushRegisters + m_globals[index] = m_ir->CreateStructGEP(nullptr, m_thread, index); } - auto process = [&](Value*& local, u32 index) + return m_globals[index]; +} + +Value* PPUTranslator::RegLoad(Value*& local) +{ + const uint index = ::narrow(&local - m_locals); + + if (local) { - // Create pointer to the global variable - m_ir->SetInsertPoint(m_entry); - const auto ptr = m_ir->CreateStructGEP(nullptr, m_thread, index); + // Simple load + assert(!m_globals[index] || m_globals[index]->getType() == local->getType()->getPointerTo()); + return local; + } - // Load variable if necessary - if (m_reads[&local - m_locals]) + // Load from the global value + local = m_ir->CreateLoad(m_ir->CreateStructGEP(nullptr, m_thread, index)); + return local; +} + +void PPUTranslator::RegStore(llvm::Value* value, llvm::Value*& local) +{ + const auto glb = RegInit(local); + assert(glb->getType() == value->getType()->getPointerTo()); + local = value; +} + +void PPUTranslator::FlushRegisters() +{ + for (auto& local : m_locals) + { + const uint index = ::narrow(&local - m_locals); + + if (local && m_globals[index]) { - m_ir->CreateStore(m_ir->CreateLoad(ptr), local); + // Store value if necessary + m_ir->CreateStore(local, m_globals[index]); } - - m_ir->SetInsertPoint(m_body); - - // Store variable if necessary - if (m_writes[&local - m_locals]) - { - m_ir->CreateStore(m_ir->CreateLoad(local), ptr); - } - - // Save global - m_globals[&local - m_locals] = ptr; - }; - - - for (u32 i = 0; i < 32; i++) if (m_gpr[i]) process(m_gpr[i], 3 + i); - for (u32 i = 0; i < 32; i++) if (m_fpr[i]) process(m_fpr[i], 35 + i); - for (u32 i = 0; i < 32; i++) if (m_vr[i]) process(m_vr[i], 67 + i); - for (u32 i = 0; i < 32; i++) if (m_cr[i]) process(m_cr[i], 99 + i); - if (m_lr) process(m_lr, 131); - if (m_ctr) process(m_ctr, 132); - if (m_vrsave) process(m_vrsave, 133); - if (m_so) process(m_so, 135); - if (m_ov) process(m_ov, 136); - if (m_ca) process(m_ca, 137); - if (m_cnt) process(m_cnt, 138); - if (m_sat) process(m_sat, 139); - if (m_nj) process(m_nj, 140); - for (u32 i = 16; i < 20; i++) if (m_fc[i]) process(m_fc[i], 141 + i - 16); - - m_ir->SetInsertPoint(m_entry); - const auto vstate = m_ir->CreateLoad(m_ir->CreateStructGEP(nullptr, m_thread, 1), true); - const auto vcheck = BasicBlock::Create(m_context, "__test", m_function); - m_ir->CreateCondBr(m_ir->CreateIsNull(vstate), m_body, vcheck, m_md_likely); - m_ir->SetInsertPoint(vcheck); - Call(GetType(), "__check", m_thread, m_ir->getInt64(m_start_addr)); - m_ir->CreateRetVoid(); - m_ir->SetInsertPoint(m_body); + } } Value* PPUTranslator::Solid(Value* value) @@ -482,15 +481,15 @@ void PPUTranslator::CompilationError(const std::string& error) void PPUTranslator::MFVSCR(ppu_opcode_t op) { - const auto vscr = m_ir->CreateOr(ZExt(RegLoad(m_sat), GetType()), m_ir->CreateShl(ZExt(RegLoad(m_nj), GetType()), 16)); + const auto vscr = m_ir->CreateOr(ZExt(RegLoad(m_sat), GetType()), m_ir->CreateShl(ZExt(RegLoad(m_nj), GetType()), 16)); SetVr(op.vd, m_ir->CreateInsertElement(ConstantVector::getSplat(4, m_ir->getInt32(0)), vscr, m_ir->getInt32(m_is_be ? 3 : 0))); } void PPUTranslator::MTVSCR(ppu_opcode_t op) { const auto vscr = m_ir->CreateExtractElement(GetVr(op.vb, VrType::vi32), m_ir->getInt32(m_is_be ? 3 : 0)); - RegStore(Trunc(m_ir->CreateLShr(vscr, 16), GetType()), m_nj); - RegStore(Trunc(vscr, GetType()), m_sat); + RegStore(Trunc(m_ir->CreateLShr(vscr, 16), GetType()), m_nj); + RegStore(Trunc(vscr, GetType()), m_sat); } void PPUTranslator::VADDCUW(ppu_opcode_t op) @@ -1612,7 +1611,7 @@ void PPUTranslator::BC(ppu_opcode_t op) { if (op.lk) { - RegInit(m_lr); + RegInit(m_lr); } const u64 target = (op.aa ? 0 : m_current_addr) + op.bt14; @@ -1635,8 +1634,8 @@ void PPUTranslator::SC(ppu_opcode_t op) } const auto num = GetGpr(11); + RegStore(m_ir->getInt32(m_current_addr), m_cia); FlushRegisters(); - m_ir->CreateStore(m_ir->getInt32(m_current_addr), m_ir->CreateStructGEP(nullptr, m_thread, 134)); Call(GetType(), op.lev ? "__lv1call" : "__syscall", m_thread, num); m_ir->CreateRetVoid(); } @@ -1647,7 +1646,7 @@ void PPUTranslator::B(ppu_opcode_t op) if (op.lk) { - RegStore(m_ir->getInt64(m_current_addr + 4), m_lr); + RegStore(m_ir->getInt64(m_current_addr + 4), m_lr); } FlushRegisters(); @@ -1665,7 +1664,9 @@ void PPUTranslator::MCRF(ppu_opcode_t op) void PPUTranslator::BCLR(ppu_opcode_t op) { - const auto target = RegLoad(m_lr); + RegInit(m_lr); + + const auto target = RegLoad(m_lr); UseCondition(CheckBranchProbability(op.bo), CheckBranchCondition(op.bo, op.bi)); @@ -1730,10 +1731,10 @@ void PPUTranslator::BCCTR(ppu_opcode_t op) { if (op.lk) { - RegInit(m_lr); + RegInit(m_lr); } - const auto target = RegLoad(m_ctr); + const auto target = RegLoad(m_ctr); UseCondition(CheckBranchProbability(op.bo | 0x4), CheckBranchCondition(op.bo | 0x4, op.bi)); @@ -2589,19 +2590,19 @@ void PPUTranslator::MFSPR(ppu_opcode_t op) switch (const u32 n = (op.spr >> 5) | ((op.spr & 0x1f) << 5)) { case 0x001: // MFXER - result = ZExt(RegLoad(m_cnt), GetType()); - result = m_ir->CreateOr(result, m_ir->CreateShl(ZExt(RegLoad(m_so), GetType()), 29)); - result = m_ir->CreateOr(result, m_ir->CreateShl(ZExt(RegLoad(m_ov), GetType()), 30)); - result = m_ir->CreateOr(result, m_ir->CreateShl(ZExt(RegLoad(m_ca), GetType()), 31)); + result = ZExt(RegLoad(m_cnt), GetType()); + result = m_ir->CreateOr(result, m_ir->CreateShl(ZExt(RegLoad(m_so), GetType()), 29)); + result = m_ir->CreateOr(result, m_ir->CreateShl(ZExt(RegLoad(m_ov), GetType()), 30)); + result = m_ir->CreateOr(result, m_ir->CreateShl(ZExt(RegLoad(m_ca), GetType()), 31)); break; case 0x008: // MFLR - result = RegLoad(m_lr); + result = RegLoad(m_lr); break; case 0x009: // MFCTR - result = RegLoad(m_ctr); + result = RegLoad(m_ctr); break; case 0x100: - result = ZExt(RegLoad(m_vrsave)); + result = ZExt(RegLoad(m_vrsave)); break; case 0x10C: // MFTB result = Call(GetType(), m_pure_attr, "__get_tb"); @@ -2733,19 +2734,19 @@ void PPUTranslator::MTSPR(ppu_opcode_t op) switch (const u32 n = (op.spr >> 5) | ((op.spr & 0x1f) << 5)) { case 0x001: // MTXER - RegStore(Trunc(m_ir->CreateLShr(value, 31), GetType()), m_ca); - RegStore(Trunc(m_ir->CreateLShr(value, 30), GetType()), m_ov); - RegStore(Trunc(m_ir->CreateLShr(value, 29), GetType()), m_so); - RegStore(Trunc(value, GetType()), m_cnt); + RegStore(Trunc(m_ir->CreateLShr(value, 31), GetType()), m_ca); + RegStore(Trunc(m_ir->CreateLShr(value, 30), GetType()), m_ov); + RegStore(Trunc(m_ir->CreateLShr(value, 29), GetType()), m_so); + RegStore(Trunc(value, GetType()), m_cnt); break; case 0x008: // MTLR - RegStore(value, m_lr); + RegStore(value, m_lr); break; case 0x009: // MTCTR - RegStore(value, m_ctr); + RegStore(value, m_ctr); break; case 0x100: - RegStore(Trunc(value), m_vrsave); + RegStore(Trunc(value), m_vrsave); break; default: Call(GetType(), fmt::format("__mtspr_%u", n), value); @@ -2799,7 +2800,7 @@ void PPUTranslator::LDBRX(ppu_opcode_t op) void PPUTranslator::LSWX(ppu_opcode_t op) { - Call(GetType(), "__lswx", m_ir->getInt32(op.rd), RegLoad(m_cnt), op.ra ? m_ir->CreateAdd(GetGpr(op.ra), GetGpr(op.rb)) : GetGpr(op.rb)); + Call(GetType(), "__lswx", m_ir->getInt32(op.rd), RegLoad(m_cnt), op.ra ? m_ir->CreateAdd(GetGpr(op.ra), GetGpr(op.rb)) : GetGpr(op.rb)); } void PPUTranslator::LWBRX(ppu_opcode_t op) @@ -2912,7 +2913,7 @@ void PPUTranslator::STDBRX(ppu_opcode_t op) void PPUTranslator::STSWX(ppu_opcode_t op) { - Call(GetType(), "__stswx", m_ir->getInt32(op.rs), RegLoad(m_cnt), op.ra ? m_ir->CreateAdd(GetGpr(op.ra), GetGpr(op.rb)) : GetGpr(op.rb)); + Call(GetType(), "__stswx", m_ir->getInt32(op.rs), RegLoad(m_cnt), op.ra ? m_ir->CreateAdd(GetGpr(op.ra), GetGpr(op.rb)) : GetGpr(op.rb)); } void PPUTranslator::STWBRX(ppu_opcode_t op) @@ -3503,7 +3504,7 @@ void PPUTranslator::MFFS(ppu_opcode_t op) for (u32 i = 16; i < 20; i++) { - result = m_ir->CreateOr(result, m_ir->CreateShl(ZExt(RegLoad(m_fc[i]), GetType()), i ^ 31)); + result = m_ir->CreateOr(result, m_ir->CreateShl(ZExt(RegLoad(m_fc[i]), GetType()), i ^ 31)); } SetFpr(op.frd, result); @@ -3845,17 +3846,17 @@ void PPUTranslator::UNK(ppu_opcode_t op) Value* PPUTranslator::GetGpr(u32 r, u32 num_bits) { - return m_ir->CreateTrunc(RegLoad(m_gpr[r]), m_ir->getIntNTy(num_bits)); + return m_ir->CreateTrunc(RegLoad(m_gpr[r]), m_ir->getIntNTy(num_bits)); } void PPUTranslator::SetGpr(u32 r, Value* value) { - RegStore(m_ir->CreateZExt(value, GetType()), m_gpr[r]); + RegStore(m_ir->CreateZExt(value, GetType()), m_gpr[r]); } Value* PPUTranslator::GetFpr(u32 r, u32 bits, bool as_int) { - const auto value = RegLoad(m_fpr[r]); + const auto value = RegLoad(m_fpr[r]); if (!as_int && bits == 64) { @@ -3878,16 +3879,12 @@ void PPUTranslator::SetFpr(u32 r, Value* val) val->getType() == GetType() ? m_ir->CreateBitCast(val, GetType()) : val->getType() == GetType() ? m_ir->CreateFPExt(val, GetType()) : val; - RegStore(f64_val, m_fpr[r]); + RegStore(f64_val, m_fpr[r]); } Value* PPUTranslator::GetVr(u32 vr, VrType type) { - RegInit(m_vr[vr]); - - m_reads[&m_vr[vr] - m_locals] = true; - - const auto value = m_ir->CreateAlignedLoad(m_vr[vr], 16); + const auto value = RegLoad(m_vr[vr]); switch (type) { @@ -3903,10 +3900,6 @@ Value* PPUTranslator::GetVr(u32 vr, VrType type) void PPUTranslator::SetVr(u32 vr, Value* value) { - RegInit(m_vr[vr]); - - m_writes[&m_vr[vr] - m_locals] = true; - const auto type = value->getType(); const auto size = type->getPrimitiveSizeInBits(); @@ -3924,17 +3917,17 @@ void PPUTranslator::SetVr(u32 vr, Value* value) } } - m_ir->CreateAlignedStore(m_ir->CreateBitCast(value, GetType()), m_vr[vr], 16); + RegStore(m_ir->CreateBitCast(value, GetType()), m_vr[vr]); } Value* PPUTranslator::GetCrb(u32 crb) { - return RegLoad(m_cr[crb]); + return RegLoad(m_cr[crb]); } void PPUTranslator::SetCrb(u32 crb, Value* value) { - RegStore(value, m_cr[crb]); + RegStore(value, m_cr[crb]); } void PPUTranslator::SetCrField(u32 group, Value* lt, Value* gt, Value* eq, Value* so) @@ -3942,7 +3935,7 @@ void PPUTranslator::SetCrField(u32 group, Value* lt, Value* gt, Value* eq, Value SetCrb(group * 4 + 0, lt ? lt : GetUndef()); SetCrb(group * 4 + 1, gt ? gt : GetUndef()); SetCrb(group * 4 + 2, eq ? eq : GetUndef()); - SetCrb(group * 4 + 3, so ? so : RegLoad(m_so)); + SetCrb(group * 4 + 3, so ? so : RegLoad(m_so)); } void PPUTranslator::SetCrFieldSignedCmp(u32 n, Value* a, Value* b) @@ -4039,7 +4032,7 @@ Value* PPUTranslator::GetFPSCRBit(u32 n) } // Get bit - const auto value = RegLoad(m_fc[n]); + const auto value = RegLoad(m_fc[n]); //if (n == 0 || (n >= 3 && n <= 12) || (n >= 21 && n <= 23)) //{ @@ -4072,28 +4065,28 @@ void PPUTranslator::SetFPSCRBit(u32 n, Value* value, bool update_fx) //if (n >= 30) CompilationError("SetFPSCRBit: RN bit"); // Store the bit - RegStore(value, m_fc[n]); + RegStore(value, m_fc[n]); } Value* PPUTranslator::GetCarry() { - return RegLoad(m_ca); + return RegLoad(m_ca); } void PPUTranslator::SetCarry(Value* bit) { - RegStore(bit, m_ca); + RegStore(bit, m_ca); } void PPUTranslator::SetOverflow(Value* bit) { - RegStore(bit, m_ov); - RegStore(m_ir->CreateOr(RegLoad(m_so), bit), m_so); + RegStore(bit, m_ov); + RegStore(m_ir->CreateOr(RegLoad(m_so), bit), m_so); } void PPUTranslator::SetSat(Value* bit) { - RegStore(m_ir->CreateOr(RegLoad(m_sat), bit), m_sat); + RegStore(m_ir->CreateOr(RegLoad(m_sat), bit), m_sat); } Value* PPUTranslator::CheckTrapCondition(u32 to, Value* left, Value* right) @@ -4121,10 +4114,10 @@ Value* PPUTranslator::CheckBranchCondition(u32 bo, u32 bi) const bool bo3 = (bo & 0x02) != 0; // Decrement counter if necessary - const auto ctr = bo2 ? nullptr : m_ir->CreateSub(RegLoad(m_ctr), m_ir->getInt64(1)); + const auto ctr = bo2 ? nullptr : m_ir->CreateSub(RegLoad(m_ctr), m_ir->getInt64(1)); // Store counter if necessary - if (ctr) RegStore(ctr, m_ctr); + if (ctr) RegStore(ctr, m_ctr); // Generate counter condition const auto use_ctr = bo2 ? nullptr : m_ir->CreateICmp(bo3 ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE, ctr, m_ir->getInt64(0)); diff --git a/rpcs3/Emu/Cell/PPUTranslator.h b/rpcs3/Emu/Cell/PPUTranslator.h index 8f33f0020b..4a2cfa5567 100644 --- a/rpcs3/Emu/Cell/PPUTranslator.h +++ b/rpcs3/Emu/Cell/PPUTranslator.h @@ -150,59 +150,30 @@ class PPUTranslator final //: public CPUTranslator // Thread context struct llvm::StructType* m_thread_type; - llvm::Value* m_globals[169]; - llvm::Value* m_locals[169]; - llvm::Value** const m_gpr = m_locals + 0; - llvm::Value** const m_fpr = m_locals + 32; - llvm::Value** const m_vr = m_locals + 64; - llvm::Value** const m_cr = m_locals + 96; - llvm::Value** const m_fc = m_locals + 128; - - std::array m_writes; - std::array m_reads; + llvm::Value* m_globals[173]; + llvm::Value* m_locals[173]; + llvm::Value** const m_gpr = m_locals + 3; + llvm::Value** const m_fpr = m_locals + 35; + llvm::Value** const m_vr = m_locals + 67; + llvm::Value** const m_cr = m_locals + 99; + llvm::Value** const m_fc = m_locals + 131; // FPSCR bits (used partially) #define DEF_VALUE(loc, glb, pos)\ llvm::Value*& loc = m_locals[pos];\ llvm::Value*& glb = m_globals[pos]; - DEF_VALUE(m_lr, m_g_lr, 160); - DEF_VALUE(m_ctr, m_g_ctr, 161); // CTR register (counter) - DEF_VALUE(m_vrsave, m_g_vrsave, 162); - DEF_VALUE(m_so, m_g_so, 163); // XER.SO bit, summary overflow - DEF_VALUE(m_ov, m_g_ov, 164); // XER.OV bit, overflow flag - DEF_VALUE(m_ca, m_g_ca, 165); // XER.CA bit, carry flag - DEF_VALUE(m_cnt, m_g_cnt, 166); - DEF_VALUE(m_nj, m_g_nj, 167); // VSCR.NJ bit, non-Java mode - DEF_VALUE(m_sat, m_g_sat, 168); // VSCR.SAT bit, sticky saturation flag + DEF_VALUE(m_lr, m_g_lr, 163); // LR, Link Register + DEF_VALUE(m_ctr, m_g_ctr, 164); // CTR, Counter Register + DEF_VALUE(m_vrsave, m_g_vrsave, 165); + DEF_VALUE(m_cia, m_g_cia, 166); + DEF_VALUE(m_so, m_g_so, 167); // XER.SO bit, summary overflow + DEF_VALUE(m_ov, m_g_ov, 168); // XER.OV bit, overflow flag + DEF_VALUE(m_ca, m_g_ca, 169); // XER.CA bit, carry flag + DEF_VALUE(m_cnt, m_g_cnt, 170); // XER.CNT + DEF_VALUE(m_sat, m_g_sat, 171); // VSCR.SAT bit, sticky saturation flag + DEF_VALUE(m_nj, m_g_nj, 172); // VSCR.NJ bit, non-Java mode #undef DEF_VALUE - - template - void RegInit(llvm::Value*& local) - { - if (!local) - { - local = new llvm::AllocaInst(GetType(), nullptr, sizeof(T)); - m_entry->getInstList().push_back(llvm::cast(local)); - } - } - - template - llvm::Value* RegLoad(llvm::Value*& local) - { - RegInit(local); - m_reads.at(&local - m_locals) = true; - return m_ir->CreateLoad(local); - } - - template - void RegStore(llvm::Value* value, llvm::Value*& local) - { - RegInit(local); - m_writes.at(&local - m_locals) = true; - m_ir->CreateStore(value, local); - } - public: // Change integer size for integer or integer vector type (by 2^degree) @@ -220,6 +191,15 @@ public: // Emit function call void CallFunction(u64 target, llvm::Value* indirect = nullptr); + // Initialize global for writing + llvm::Value* RegInit(llvm::Value*& local); + + // Load last register value + llvm::Value* RegLoad(llvm::Value*& local); + + // Store register value locally + void RegStore(llvm::Value* value, llvm::Value*& local); + // Write global registers void FlushRegisters();