void FPURegCache::MapReg(const int i, bool doLoad, bool makeDirty) { pendingFlush = true; _assert_msg_(JIT, !regs[i].location.IsImm(), "WTF - load - imm"); if (!regs[i].away) { // Reg is at home in the memory register file. Let's pull it out. X64Reg xr = GetFreeXReg(); _assert_msg_(JIT, xr >= 0 && xr < NUM_X_FPREGS, "WTF - load - invalid reg"); xregs[xr].mipsReg = i; xregs[xr].dirty = makeDirty; OpArg newloc = ::Gen::R(xr); if (doLoad) { if (!regs[i].location.IsImm() && (regs[i].location.offset & 0x3)) { PanicAlert("WARNING - misaligned fp register location %i", i); } emit->MOVSS(xr, regs[i].location); } regs[i].location = newloc; regs[i].lane = 0; regs[i].away = true; } else if (regs[i].lane != 0) { // Well, darn. This means we need to flush it. // TODO: This could be more optimal. Also check flags. StoreFromRegister(i); MapReg(i, doLoad, makeDirty); } else { // There are no immediates in the FPR reg file, so we already had this in a register. Make dirty as necessary. xregs[RX(i)].dirty |= makeDirty; _assert_msg_(JIT, regs[i].location.IsSimpleReg(), "not loaded and not simple."); } Invariant(); }
bool FPURegCache::TryMapRegsVS(const u8 *v, VectorSize vsz, int flags) { const int n = GetNumVectorElements(vsz); if (!CanMapVS(v, vsz)) { return false; } if (IsMappedVS(v, vsz)) { // Already mapped then, perfect. Just mark dirty. if ((flags & MAP_DIRTY) != 0) xregs[VSX(v)].dirty = true; return true; } // At this point, some or all are in single regs or memory, and they're not locked there. if (n == 1) { // Single is easy, just map normally but track as a SIMD reg. // This way V/VS can warn about improper usage properly. MapRegV(v[0], flags); vregs[v[0]].lane = 1; if ((flags & MAP_DIRTY) != 0) xregs[VSX(v)].dirty = true; Invariant(); return true; } X64Reg xr; if ((flags & MAP_NOINIT) != MAP_NOINIT) { xr = LoadRegsVS(v, n); } else { xr = GetFreeXReg(); } // Victory, now let's clean up everything. OpArg newloc = Gen::R(xr); bool dirty = (flags & MAP_DIRTY) != 0; for (int i = 0; i < n; ++i) { MIPSCachedFPReg &vr = vregs[v[i]]; if (vr.away) { // Clear the xreg it was in before. X64Reg oldXReg = vr.location.GetSimpleReg(); xregs[oldXReg].mipsReg = -1; if (xregs[oldXReg].dirty) { // Inherit the "dirtiness" (ultimately set below for all regs.) dirty = true; xregs[oldXReg].dirty = false; } } xregs[xr].mipsRegs[i] = v[i] + 32; vr.location = newloc; vr.lane = i + 1; vr.away = true; } xregs[xr].dirty = dirty; Invariant(); return true; }
void FPURegCache::BindToRegister(const int i, bool doLoad, bool makeDirty) { _assert_msg_(DYNA_REC, !regs[i].location.IsImm(), "WTF - load - imm"); if (!regs[i].away) { // Reg is at home in the memory register file. Let's pull it out. X64Reg xr = GetFreeXReg(); _assert_msg_(DYNA_REC, xr < NUM_X_FPREGS, "WTF - load - invalid reg"); xregs[xr].mipsReg = i; xregs[xr].dirty = makeDirty; OpArg newloc = ::Gen::R(xr); if (doLoad) { if (!regs[i].location.IsImm() && (regs[i].location.offset & 0x3)) { PanicAlert("WARNING - misaligned fp register location %i", i); } emit->MOVSS(xr, regs[i].location); } regs[i].location = newloc; regs[i].away = true; } else { // There are no immediates in the FPR reg file, so we already had this in a register. Make dirty as necessary. xregs[RX(i)].dirty |= makeDirty; _assert_msg_(DYNA_REC, regs[i].location.IsSimpleReg(), "not loaded and not simple."); } }