mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #10476 from unknownbrackets/arm64-jit
Statically allocate RA in arm64jit
This commit is contained in:
commit
f3ba540078
7 changed files with 44 additions and 30 deletions
|
@ -3736,6 +3736,7 @@ void ARM64XEmitter::CMPI2R(ARM64Reg Rn, u64 imm, ARM64Reg scratch) {
|
|||
}
|
||||
|
||||
bool ARM64XEmitter::TryADDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm) {
|
||||
s64 negated = Is64Bit(Rn) ? -(s64)imm : -(s32)(u32)imm;
|
||||
u32 val;
|
||||
bool shift;
|
||||
if (imm == 0) {
|
||||
|
@ -3745,12 +3746,16 @@ bool ARM64XEmitter::TryADDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm) {
|
|||
} else if (IsImmArithmetic(imm, &val, &shift)) {
|
||||
ADD(Rd, Rn, val, shift);
|
||||
return true;
|
||||
} else if (IsImmArithmetic((u64)negated, &val, &shift)) {
|
||||
SUB(Rd, Rn, val, shift);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ARM64XEmitter::TrySUBI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm) {
|
||||
s64 negated = Is64Bit(Rn) ? -(s64)imm : -(s32)(u32)imm;
|
||||
u32 val;
|
||||
bool shift;
|
||||
if (imm == 0) {
|
||||
|
@ -3760,6 +3765,9 @@ bool ARM64XEmitter::TrySUBI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm) {
|
|||
} else if (IsImmArithmetic(imm, &val, &shift)) {
|
||||
SUB(Rd, Rn, val, shift);
|
||||
return true;
|
||||
} else if (IsImmArithmetic((u64)negated, &val, &shift)) {
|
||||
ADD(Rd, Rn, val, shift);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -90,11 +90,7 @@ void Arm64Jit::Comp_IType(MIPSOpcode op) {
|
|||
ARM64Reg r32 = gpr.RPtr(rs);
|
||||
gpr.MarkDirty(r32);
|
||||
ARM64Reg r = EncodeRegTo64(r32);
|
||||
if (simm > 0) {
|
||||
ADDI2R(r, r, simm);
|
||||
} else {
|
||||
SUBI2R(r, r, -simm);
|
||||
}
|
||||
ADDI2R(r, r, simm);
|
||||
} else {
|
||||
if (simm >= 0) {
|
||||
CompImmLogic(rs, rt, simm, &ARM64XEmitter::ADD, &ARM64XEmitter::TryADDI2R, &EvalAdd);
|
||||
|
|
|
@ -536,7 +536,7 @@ void Arm64Jit::Comp_JumpReg(MIPSOpcode op)
|
|||
delaySlotIsNice = false;
|
||||
CONDITIONAL_NICE_DELAYSLOT;
|
||||
|
||||
ARM64Reg destReg = OTHERTEMPREG;
|
||||
ARM64Reg destReg = INVALID_REG;
|
||||
if (IsSyscall(delaySlotOp)) {
|
||||
gpr.MapReg(rs);
|
||||
MovToPC(gpr.R(rs)); // For syscall to be able to return.
|
||||
|
@ -574,7 +574,9 @@ void Arm64Jit::Comp_JumpReg(MIPSOpcode op)
|
|||
destReg = gpr.R(rs); // Safe because FlushAll doesn't change any regs
|
||||
FlushAll();
|
||||
} else {
|
||||
// Delay slot - this case is very rare, might be able to free up W24.
|
||||
// Since we can't be in a delay slot, should be safe to steal FLAGTEMPREG for a temp reg.
|
||||
// It will be saved, even if a function is called.
|
||||
destReg = FLAGTEMPREG;
|
||||
gpr.MapReg(rs);
|
||||
MOV(destReg, gpr.R(rs));
|
||||
if (andLink)
|
||||
|
|
|
@ -250,7 +250,7 @@ namespace MIPSComp {
|
|||
SetJumpTarget(skip);
|
||||
}
|
||||
|
||||
gpr.ReleaseSpillLocks();
|
||||
gpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
||||
void Arm64Jit::Comp_ITypeMem(MIPSOpcode op) {
|
||||
|
@ -311,7 +311,7 @@ namespace MIPSComp {
|
|||
gpr.MapRegAsPointer(rs);
|
||||
|
||||
// For a store, try to avoid mapping a reg if not needed.
|
||||
targetReg = load ? INVALID_REG : gpr.MapTempImm(rt);
|
||||
targetReg = load ? INVALID_REG : gpr.TryMapTempImm(rt);
|
||||
if (targetReg == INVALID_REG) {
|
||||
gpr.MapReg(rt, load ? MAP_NOINIT : 0);
|
||||
targetReg = gpr.R(rt);
|
||||
|
@ -327,12 +327,12 @@ namespace MIPSComp {
|
|||
case 41: STRH(INDEX_UNSIGNED, targetReg, gpr.RPtr(rs), offset); break;
|
||||
case 40: STRB(INDEX_UNSIGNED, targetReg, gpr.RPtr(rs), offset); break;
|
||||
}
|
||||
gpr.ReleaseSpillLocks();
|
||||
gpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!load && gpr.IsImm(rt) && gpr.MapTempImm(rt) != INVALID_REG) {
|
||||
if (!load && gpr.IsImm(rt) && gpr.TryMapTempImm(rt) != INVALID_REG) {
|
||||
// We're storing an immediate value, let's see if we can optimize rt.
|
||||
if (!gpr.IsImm(rs) || offset == 0) {
|
||||
// In this case, we're always going to need rs mapped, which may flush the temp imm.
|
||||
|
@ -340,7 +340,7 @@ namespace MIPSComp {
|
|||
gpr.MapIn(rs);
|
||||
}
|
||||
|
||||
targetReg = gpr.MapTempImm(rt);
|
||||
targetReg = gpr.TryMapTempImm(rt);
|
||||
}
|
||||
|
||||
if (gpr.IsImm(rs) && Memory::IsValidAddress(iaddr)) {
|
||||
|
|
|
@ -69,10 +69,10 @@ void Arm64RegCache::Start(MIPSAnalyst::AnalysisResults &stats) {
|
|||
const ARM64Reg *Arm64RegCache::GetMIPSAllocationOrder(int &count) {
|
||||
// See register alloc remarks in Arm64Asm.cpp
|
||||
|
||||
// W19-W22 are most suitable for static allocation. Those that are chosen for static allocation
|
||||
// W19-W23 are most suitable for static allocation. Those that are chosen for static allocation
|
||||
// should be omitted here and added in GetStaticAllocations.
|
||||
static const ARM64Reg allocationOrder[] = {
|
||||
W19, W20, W21, W22, W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15,
|
||||
W19, W20, W21, W22, W23, W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15,
|
||||
};
|
||||
static const ARM64Reg allocationOrderStaticAlloc[] = {
|
||||
W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15,
|
||||
|
@ -93,6 +93,7 @@ const Arm64RegCache::StaticAllocation *Arm64RegCache::GetStaticAllocations(int &
|
|||
{MIPS_REG_V0, W20},
|
||||
{MIPS_REG_V1, W22},
|
||||
{MIPS_REG_A0, W21},
|
||||
{MIPS_REG_RA, W23},
|
||||
};
|
||||
|
||||
if (jo_->useStaticAlloc) {
|
||||
|
@ -304,7 +305,7 @@ ARM64Reg Arm64RegCache::FindBestToSpill(bool unusedOnly, bool *clobbered) {
|
|||
return INVALID_REG;
|
||||
}
|
||||
|
||||
ARM64Reg Arm64RegCache::MapTempImm(MIPSGPReg r) {
|
||||
ARM64Reg Arm64RegCache::TryMapTempImm(MIPSGPReg r) {
|
||||
// If already mapped, no need for a temporary.
|
||||
if (IsMapped(r)) {
|
||||
return R(r);
|
||||
|
@ -459,7 +460,7 @@ void Arm64RegCache::MapInIn(MIPSGPReg rd, MIPSGPReg rs) {
|
|||
SpillLock(rd, rs);
|
||||
MapReg(rd);
|
||||
MapReg(rs);
|
||||
ReleaseSpillLocks();
|
||||
ReleaseSpillLock(rd, rs);
|
||||
}
|
||||
|
||||
void Arm64RegCache::MapDirtyIn(MIPSGPReg rd, MIPSGPReg rs, bool avoidLoad) {
|
||||
|
@ -467,7 +468,7 @@ void Arm64RegCache::MapDirtyIn(MIPSGPReg rd, MIPSGPReg rs, bool avoidLoad) {
|
|||
bool load = !avoidLoad || rd == rs;
|
||||
MapReg(rd, load ? MAP_DIRTY : MAP_NOINIT);
|
||||
MapReg(rs);
|
||||
ReleaseSpillLocks();
|
||||
ReleaseSpillLock(rd, rs);
|
||||
}
|
||||
|
||||
void Arm64RegCache::MapDirtyInIn(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, bool avoidLoad) {
|
||||
|
@ -476,7 +477,7 @@ void Arm64RegCache::MapDirtyInIn(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, bool
|
|||
MapReg(rd, load ? MAP_DIRTY : MAP_NOINIT);
|
||||
MapReg(rt);
|
||||
MapReg(rs);
|
||||
ReleaseSpillLocks();
|
||||
ReleaseSpillLock(rd, rs, rt);
|
||||
}
|
||||
|
||||
void Arm64RegCache::MapDirtyDirtyIn(MIPSGPReg rd1, MIPSGPReg rd2, MIPSGPReg rs, bool avoidLoad) {
|
||||
|
@ -486,7 +487,7 @@ void Arm64RegCache::MapDirtyDirtyIn(MIPSGPReg rd1, MIPSGPReg rd2, MIPSGPReg rs,
|
|||
MapReg(rd1, load1 ? MAP_DIRTY : MAP_NOINIT);
|
||||
MapReg(rd2, load2 ? MAP_DIRTY : MAP_NOINIT);
|
||||
MapReg(rs);
|
||||
ReleaseSpillLocks();
|
||||
ReleaseSpillLock(rd1, rd2, rs);
|
||||
}
|
||||
|
||||
void Arm64RegCache::MapDirtyDirtyInIn(MIPSGPReg rd1, MIPSGPReg rd2, MIPSGPReg rs, MIPSGPReg rt, bool avoidLoad) {
|
||||
|
@ -497,7 +498,7 @@ void Arm64RegCache::MapDirtyDirtyInIn(MIPSGPReg rd1, MIPSGPReg rd2, MIPSGPReg rs
|
|||
MapReg(rd2, load2 ? MAP_DIRTY : MAP_NOINIT);
|
||||
MapReg(rt);
|
||||
MapReg(rs);
|
||||
ReleaseSpillLocks();
|
||||
ReleaseSpillLock(rd1, rd2, rs, rt);
|
||||
}
|
||||
|
||||
void Arm64RegCache::FlushArmReg(ARM64Reg r) {
|
||||
|
@ -872,7 +873,7 @@ void Arm64RegCache::SpillLock(MIPSGPReg r1, MIPSGPReg r2, MIPSGPReg r3, MIPSGPRe
|
|||
if (r4 != MIPS_REG_INVALID) mr[r4].spillLock = true;
|
||||
}
|
||||
|
||||
void Arm64RegCache::ReleaseSpillLocks() {
|
||||
void Arm64RegCache::ReleaseSpillLocksAndDiscardTemps() {
|
||||
for (int i = 0; i < NUM_MIPSREG; i++) {
|
||||
if (!mr[i].isStatic)
|
||||
mr[i].spillLock = false;
|
||||
|
@ -882,9 +883,15 @@ void Arm64RegCache::ReleaseSpillLocks() {
|
|||
}
|
||||
}
|
||||
|
||||
void Arm64RegCache::ReleaseSpillLock(MIPSGPReg reg) {
|
||||
if (!mr[reg].isStatic)
|
||||
mr[reg].spillLock = false;
|
||||
void Arm64RegCache::ReleaseSpillLock(MIPSGPReg r1, MIPSGPReg r2, MIPSGPReg r3, MIPSGPReg r4) {
|
||||
if (!mr[r1].isStatic)
|
||||
mr[r1].spillLock = false;
|
||||
if (r2 != MIPS_REG_INVALID && !mr[r2].isStatic)
|
||||
mr[r2].spillLock = false;
|
||||
if (r3 != MIPS_REG_INVALID && !mr[r3].isStatic)
|
||||
mr[r3].spillLock = false;
|
||||
if (r4 != MIPS_REG_INVALID && !mr[r4].isStatic)
|
||||
mr[r4].spillLock = false;
|
||||
}
|
||||
|
||||
ARM64Reg Arm64RegCache::R(MIPSGPReg mipsReg) {
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
|
||||
namespace Arm64JitConstants {
|
||||
|
||||
const Arm64Gen::ARM64Reg DOWNCOUNTREG = Arm64Gen::W23;
|
||||
const Arm64Gen::ARM64Reg OTHERTEMPREG = Arm64Gen::W24;
|
||||
const Arm64Gen::ARM64Reg DOWNCOUNTREG = Arm64Gen::W24;
|
||||
const Arm64Gen::ARM64Reg FLAGTEMPREG = Arm64Gen::X25;
|
||||
const Arm64Gen::ARM64Reg JITBASEREG = Arm64Gen::X26;
|
||||
const Arm64Gen::ARM64Reg CTXREG = Arm64Gen::X27;
|
||||
|
@ -92,8 +91,8 @@ public:
|
|||
// Protect the arm register containing a MIPS register from spilling, to ensure that
|
||||
// it's being kept allocated.
|
||||
void SpillLock(MIPSGPReg reg, MIPSGPReg reg2 = MIPS_REG_INVALID, MIPSGPReg reg3 = MIPS_REG_INVALID, MIPSGPReg reg4 = MIPS_REG_INVALID);
|
||||
void ReleaseSpillLock(MIPSGPReg reg);
|
||||
void ReleaseSpillLocks();
|
||||
void ReleaseSpillLock(MIPSGPReg reg, MIPSGPReg reg2 = MIPS_REG_INVALID, MIPSGPReg reg3 = MIPS_REG_INVALID, MIPSGPReg reg4 = MIPS_REG_INVALID);
|
||||
void ReleaseSpillLocksAndDiscardTemps();
|
||||
|
||||
void SetImm(MIPSGPReg reg, u64 immVal);
|
||||
bool IsImm(MIPSGPReg reg) const;
|
||||
|
@ -102,7 +101,8 @@ public:
|
|||
// Optimally set a register to an imm value (possibly using another register.)
|
||||
void SetRegImm(Arm64Gen::ARM64Reg reg, u64 imm);
|
||||
|
||||
Arm64Gen::ARM64Reg MapTempImm(MIPSGPReg);
|
||||
// May fail and return INVALID_REG if it needs flushing.
|
||||
Arm64Gen::ARM64Reg TryMapTempImm(MIPSGPReg);
|
||||
|
||||
// Returns an ARM register containing the requested MIPS register.
|
||||
Arm64Gen::ARM64Reg MapReg(MIPSGPReg reg, int mapFlags = 0);
|
||||
|
|
|
@ -228,7 +228,8 @@ bool CtrlDisAsmView::getDisasmAddressText(u32 address, char* dest, bool abbrevia
|
|||
}
|
||||
} else {
|
||||
if (showData) {
|
||||
sprintf(dest, "%08X %08X", address, Memory::Read_Instruction(address, true).encoding);
|
||||
u32 encoding = Memory::IsValidAddress(address) ? Memory::Read_Instruction(address, true).encoding : 0;
|
||||
sprintf(dest, "%08X %08X", address, encoding);
|
||||
} else {
|
||||
sprintf(dest, "%08X", address);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue