mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-06 04:35:29 +02:00
x86jit: Implement load/store.
This commit is contained in:
@@ -82,14 +82,54 @@ void X64JitBackend::CompIR_FStore(IRInst inst) {
|
||||
void X64JitBackend::CompIR_Load(IRInst inst) {
|
||||
CONDITIONAL_DISABLE;
|
||||
|
||||
regs_.SpillLockGPR(inst.dest, inst.src1);
|
||||
OpArg addrArg;
|
||||
if (inst.src1 == MIPS_REG_ZERO) {
|
||||
#ifdef MASKED_PSP_MEMORY
|
||||
inst.constant &= Memory::MEMVIEW32_MASK;
|
||||
#endif
|
||||
#if PPSSPP_ARCH(AMD64)
|
||||
addrArg = MDisp(MEMBASEREG, inst.constant & 0x7FFFFFFF);
|
||||
#else
|
||||
addrArg = M(Memory::base + inst.constant);
|
||||
#endif
|
||||
} else if (jo.cachePointers || regs_.IsGPRMappedAsPointer(inst.src1)) {
|
||||
X64Reg src1 = regs_.MapGPRAsPointer(inst.src1);
|
||||
addrArg = MDisp(src1, inst.constant & 0x7FFFFFFF);
|
||||
} else {
|
||||
regs_.MapGPR(inst.src1);
|
||||
addrArg = MComplex(MEMBASEREG, regs_.RX(inst.src1), SCALE_1, inst.constant & 0x7FFFFFFF);
|
||||
}
|
||||
// With NOINIT, MapReg won't subtract MEMBASEREG even if dest == src1.
|
||||
regs_.MapGPR(inst.dest, MIPSMap::NOINIT);
|
||||
|
||||
// TODO: Safe memory? Or enough to have crash handler + validate?
|
||||
|
||||
switch (inst.op) {
|
||||
case IROp::Load8:
|
||||
MOVZX(32, 8, regs_.RX(inst.dest), addrArg);
|
||||
break;
|
||||
|
||||
case IROp::Load8Ext:
|
||||
MOVSX(32, 8, regs_.RX(inst.dest), addrArg);
|
||||
break;
|
||||
|
||||
case IROp::Load16:
|
||||
MOVZX(32, 16, regs_.RX(inst.dest), addrArg);
|
||||
break;
|
||||
|
||||
case IROp::Load16Ext:
|
||||
MOVSX(32, 16, regs_.RX(inst.dest), addrArg);
|
||||
break;
|
||||
|
||||
case IROp::Load32:
|
||||
MOV(32, regs_.R(inst.dest), addrArg);
|
||||
break;
|
||||
|
||||
case IROp::Load32Linked:
|
||||
CompIR_Generic(inst);
|
||||
if (inst.dest != MIPS_REG_ZERO)
|
||||
MOV(32, regs_.R(inst.dest), addrArg);
|
||||
regs_.SetGPRImm(IRREG_LLBIT, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -117,11 +157,56 @@ void X64JitBackend::CompIR_LoadShift(IRInst inst) {
|
||||
void X64JitBackend::CompIR_Store(IRInst inst) {
|
||||
CONDITIONAL_DISABLE;
|
||||
|
||||
regs_.SpillLockGPR(inst.src3, inst.src1);
|
||||
OpArg addrArg;
|
||||
if (inst.src1 == MIPS_REG_ZERO) {
|
||||
#ifdef MASKED_PSP_MEMORY
|
||||
inst.constant &= Memory::MEMVIEW32_MASK;
|
||||
#endif
|
||||
#if PPSSPP_ARCH(AMD64)
|
||||
addrArg = MDisp(MEMBASEREG, inst.constant & 0x7FFFFFFF);
|
||||
#else
|
||||
addrArg = M(Memory::base + inst.constant);
|
||||
#endif
|
||||
} else if ((jo.cachePointers || regs_.IsGPRMappedAsPointer(inst.src1)) && inst.src3 != inst.src1) {
|
||||
X64Reg src1 = regs_.MapGPRAsPointer(inst.src1);
|
||||
addrArg = MDisp(src1, inst.constant & 0x7FFFFFFF);
|
||||
} else {
|
||||
regs_.MapGPR(inst.src1);
|
||||
addrArg = MComplex(MEMBASEREG, regs_.RX(inst.src1), SCALE_1, inst.constant & 0x7FFFFFFF);
|
||||
}
|
||||
|
||||
OpArg valueArg;
|
||||
X64Reg valueReg = regs_.TryMapTempImm(inst.src3);
|
||||
if (valueReg != INVALID_REG) {
|
||||
valueArg = R(valueReg);
|
||||
} else if (regs_.IsGPRImm(inst.src3)) {
|
||||
u32 imm = regs_.GetGPRImm(inst.src3);
|
||||
switch (inst.op) {
|
||||
case IROp::Store8: valueArg = Imm8((u8)imm); break;
|
||||
case IROp::Store16: valueArg = Imm16((u16)imm); break;
|
||||
case IROp::Store32: valueArg = Imm32(imm); break;
|
||||
default:
|
||||
INVALIDOP;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
valueArg = R(regs_.MapGPR(inst.src3));
|
||||
}
|
||||
|
||||
// TODO: Safe memory? Or enough to have crash handler + validate?
|
||||
|
||||
switch (inst.op) {
|
||||
case IROp::Store8:
|
||||
MOV(8, addrArg, valueArg);
|
||||
break;
|
||||
|
||||
case IROp::Store16:
|
||||
MOV(16, addrArg, valueArg);
|
||||
break;
|
||||
|
||||
case IROp::Store32:
|
||||
CompIR_Generic(inst);
|
||||
MOV(32, addrArg, valueArg);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -106,10 +106,6 @@ private:
|
||||
void CompIR_VecStore(IRInst inst) override;
|
||||
void CompIR_ValidateAddress(IRInst inst) override;
|
||||
|
||||
void SetScratch1ToSrc1Address(IRReg src1);
|
||||
// Modifies SCRATCH regs.
|
||||
int32_t AdjustForAddressOffset(Gen::X64Reg *reg, int32_t constant, int32_t range = 0);
|
||||
|
||||
JitOptions &jo;
|
||||
X64IRRegCache regs_;
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ X64Reg X64IRRegCache::TryMapTempImm(IRReg r) {
|
||||
_dbg_assert_(IsValidGPR(r));
|
||||
// If already mapped, no need for a temporary.
|
||||
if (IsGPRMapped(r)) {
|
||||
return R(r);
|
||||
return RX(r);
|
||||
}
|
||||
|
||||
if (mr[r].loc == MIPSLoc::IMM) {
|
||||
@@ -282,7 +282,15 @@ void X64IRRegCache::StoreRegValue(IRReg mreg, uint32_t imm) {
|
||||
emit_->MOV(32, MDisp(CTXREG, -128 + GetMipsRegOffset(mreg)), ::R(storeReg));
|
||||
}
|
||||
|
||||
X64Reg X64IRRegCache::R(IRReg mipsReg) {
|
||||
OpArg X64IRRegCache::R(IRReg mipsReg) {
|
||||
return ::R(RX(mipsReg));
|
||||
}
|
||||
|
||||
OpArg X64IRRegCache::F(IRReg mipsReg) {
|
||||
return ::R(FX(mipsReg));
|
||||
}
|
||||
|
||||
X64Reg X64IRRegCache::RX(IRReg mipsReg) {
|
||||
_dbg_assert_(IsValidGPR(mipsReg));
|
||||
_dbg_assert_(mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM);
|
||||
if (mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM) {
|
||||
@@ -293,7 +301,7 @@ X64Reg X64IRRegCache::R(IRReg mipsReg) {
|
||||
}
|
||||
}
|
||||
|
||||
X64Reg X64IRRegCache::RPtr(IRReg mipsReg) {
|
||||
X64Reg X64IRRegCache::RXPtr(IRReg mipsReg) {
|
||||
_dbg_assert_(IsValidGPR(mipsReg));
|
||||
_dbg_assert_(mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM || mr[mipsReg].loc == MIPSLoc::REG_AS_PTR);
|
||||
if (mr[mipsReg].loc == MIPSLoc::REG_AS_PTR) {
|
||||
@@ -313,7 +321,7 @@ X64Reg X64IRRegCache::RPtr(IRReg mipsReg) {
|
||||
}
|
||||
}
|
||||
|
||||
X64Reg X64IRRegCache::F(IRReg mipsReg) {
|
||||
X64Reg X64IRRegCache::FX(IRReg mipsReg) {
|
||||
_dbg_assert_(IsValidFPR(mipsReg));
|
||||
_dbg_assert_(mr[mipsReg + 32].loc == MIPSLoc::FREG);
|
||||
if (mr[mipsReg + 32].loc == MIPSLoc::FREG) {
|
||||
|
||||
@@ -58,9 +58,11 @@ public:
|
||||
|
||||
Gen::X64Reg GetAndLockTempR();
|
||||
|
||||
Gen::X64Reg R(IRReg preg); // Returns a cached register, while checking that it's NOT mapped as a pointer
|
||||
Gen::X64Reg RPtr(IRReg preg); // Returns a cached register, if it has been mapped as a pointer
|
||||
Gen::X64Reg F(IRReg preg);
|
||||
Gen::OpArg R(IRReg preg);
|
||||
Gen::OpArg F(IRReg preg);
|
||||
Gen::X64Reg RX(IRReg preg); // Returns a cached register, while checking that it's NOT mapped as a pointer
|
||||
Gen::X64Reg RXPtr(IRReg preg); // Returns a cached register, if it has been mapped as a pointer
|
||||
Gen::X64Reg FX(IRReg preg);
|
||||
|
||||
protected:
|
||||
const int *GetAllocationOrder(MIPSLoc type, int &count, int &base) const override;
|
||||
|
||||
Reference in New Issue
Block a user