mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-03-02 11:08:27 +00:00
ARM64 regcache: Add support to "pointerify" registers. Use in load/store to cut down instructions.
This commit is contained in:
parent
0849e270ee
commit
ad648baa9c
@ -256,6 +256,32 @@ namespace MIPSComp
|
||||
case 40: //sb
|
||||
case 41: //sh
|
||||
case 43: //sw
|
||||
if (jo.cachePointers && g_Config.bFastMemory) {
|
||||
// ARM has smaller load/store immediate displacements than MIPS, 12 bits - and some memory ops only have 8 bits.
|
||||
int offsetRange = 0x3ff;
|
||||
if (o == 41 || o == 33 || o == 37 || o == 32)
|
||||
offsetRange = 0xff; // 8 bit offset only
|
||||
|
||||
if (!gpr.IsImm(rs) && rs != rt && (offset <= offsetRange) && offset >= 0) {
|
||||
gpr.SpillLock(rs, rt);
|
||||
gpr.MapRegAsPointer(rs);
|
||||
gpr.MapReg(rt, load ? MAP_NOINIT : 0);
|
||||
switch (o) {
|
||||
case 35: LDR(INDEX_UNSIGNED, gpr.R(rt), gpr.RPtr(rs), offset); break;
|
||||
case 37: LDRH(INDEX_UNSIGNED, gpr.R(rt), gpr.RPtr(rs), offset); break;
|
||||
case 33: LDRSH(INDEX_UNSIGNED, gpr.R(rt), gpr.RPtr(rs), offset); break;
|
||||
case 36: LDRB(INDEX_UNSIGNED, gpr.R(rt), gpr.RPtr(rs), offset); break;
|
||||
case 32: LDRSB(INDEX_UNSIGNED, gpr.R(rt), gpr.RPtr(rs), offset); break;
|
||||
// Store
|
||||
case 43: STR(INDEX_UNSIGNED, gpr.R(rt), gpr.RPtr(rs), offset); break;
|
||||
case 41: STRH(INDEX_UNSIGNED, gpr.R(rt), gpr.RPtr(rs), offset); break;
|
||||
case 40: STRB(INDEX_UNSIGNED, gpr.R(rt), gpr.RPtr(rs), offset); break;
|
||||
}
|
||||
gpr.ReleaseSpillLocks();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gpr.IsImm(rs) && Memory::IsValidAddress(iaddr)) {
|
||||
// TODO: Avoid mapping a register for the "zero" register, use R0 instead.
|
||||
|
||||
|
@ -1439,7 +1439,7 @@ namespace MIPSComp
|
||||
}
|
||||
|
||||
gpr.MapReg(MIPS_REG_VFPUCC, MAP_DIRTY);
|
||||
ANDI2R(gpr.R(MIPS_REG_VFPUCC), gpr.R(MIPS_REG_VFPUCC), ~affected_bits);
|
||||
ANDI2R(gpr.R(MIPS_REG_VFPUCC), gpr.R(MIPS_REG_VFPUCC), ~affected_bits, SCRATCH2);
|
||||
ORR(gpr.R(MIPS_REG_VFPUCC), gpr.R(MIPS_REG_VFPUCC), SCRATCH1);
|
||||
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
|
@ -308,7 +308,6 @@ const u8 *Arm64Jit::DoJit(u32 em_address, JitBlock *b)
|
||||
}
|
||||
|
||||
b->codeSize = GetCodePtr() - b->normalEntry;
|
||||
|
||||
if (logBlocks > 0 && dontLogBlocks == 0) {
|
||||
ILOG("=============== ARM (%d instructions -> %d bytes) ===============", js.numInstructions, b->codeSize);
|
||||
DisassembleArm64Print(b->normalEntry, GetCodePtr() - b->normalEntry);
|
||||
|
@ -40,6 +40,7 @@ void Arm64RegCache::Start(MIPSAnalyst::AnalysisResults &stats) {
|
||||
for (int i = 0; i < NUM_ARMREG; i++) {
|
||||
ar[i].mipsReg = MIPS_REG_INVALID;
|
||||
ar[i].isDirty = false;
|
||||
ar[i].pointerified = false;
|
||||
}
|
||||
for (int i = 0; i < NUM_MIPSREG; i++) {
|
||||
mr[i].loc = ML_MEM;
|
||||
@ -120,6 +121,7 @@ void Arm64RegCache::MapRegTo(ARM64Reg reg, MIPSGPReg mipsReg, int mapFlags) {
|
||||
}
|
||||
}
|
||||
ar[reg].mipsReg = mipsReg;
|
||||
ar[reg].pointerified = false;
|
||||
mr[mipsReg].reg = reg;
|
||||
}
|
||||
|
||||
@ -167,6 +169,8 @@ ARM64Reg Arm64RegCache::MapReg(MIPSGPReg mipsReg, int mapFlags) {
|
||||
// Mapping dirty means the old imm value is invalid.
|
||||
mr[mipsReg].loc = ML_ARMREG;
|
||||
ar[armReg].isDirty = true;
|
||||
// If reg is written to, pointerification is lost.
|
||||
ar[armReg].pointerified = false;
|
||||
}
|
||||
return (ARM64Reg)mr[mipsReg].reg;
|
||||
}
|
||||
@ -212,6 +216,24 @@ allocate:
|
||||
return INVALID_REG;
|
||||
}
|
||||
|
||||
Arm64Gen::ARM64Reg Arm64RegCache::MapRegAsPointer(MIPSGPReg reg) {
|
||||
ARM64Reg retval = INVALID_REG;
|
||||
if (mr[reg].loc != ML_ARMREG) {
|
||||
retval = MapReg(reg);
|
||||
}
|
||||
|
||||
if (mr[reg].loc == ML_ARMREG) {
|
||||
int a = DecodeReg(mr[reg].reg);
|
||||
if (!ar[a].pointerified) {
|
||||
emit_->MOVK(ARM64Reg(X0 + a), ((uint64_t)Memory::base) >> 32, SHIFT_32);
|
||||
ar[a].pointerified = true;
|
||||
}
|
||||
} else {
|
||||
ERROR_LOG(JIT, "MapRegAsPointer : MapReg failed to allocate a register?");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void Arm64RegCache::MapIn(MIPSGPReg rs) {
|
||||
MapReg(rs);
|
||||
}
|
||||
@ -285,6 +307,7 @@ void Arm64RegCache::FlushArmReg(ARM64Reg r) {
|
||||
}
|
||||
ar[r].isDirty = false;
|
||||
ar[r].mipsReg = MIPS_REG_INVALID;
|
||||
ar[r].pointerified = false;
|
||||
}
|
||||
|
||||
void Arm64RegCache::DiscardR(MIPSGPReg mipsReg) {
|
||||
@ -293,6 +316,7 @@ void Arm64RegCache::DiscardR(MIPSGPReg mipsReg) {
|
||||
ARM64Reg armReg = mr[mipsReg].reg;
|
||||
ar[armReg].isDirty = false;
|
||||
ar[armReg].mipsReg = MIPS_REG_INVALID;
|
||||
ar[armReg].pointerified = false;
|
||||
mr[mipsReg].reg = INVALID_REG;
|
||||
mr[mipsReg].loc = ML_MEM;
|
||||
mr[mipsReg].imm = 0;
|
||||
@ -425,3 +449,18 @@ ARM64Reg Arm64RegCache::R(MIPSGPReg mipsReg) {
|
||||
return INVALID_REG; // BAAAD
|
||||
}
|
||||
}
|
||||
|
||||
ARM64Reg Arm64RegCache::RPtr(MIPSGPReg mipsReg) {
|
||||
if (mr[mipsReg].loc == ML_ARMREG || mr[mipsReg].loc == ML_ARMREG_IMM) {
|
||||
int a = mr[mipsReg].reg;
|
||||
if (ar[a].pointerified) {
|
||||
return (ARM64Reg)mr[mipsReg].reg;
|
||||
} else {
|
||||
ERROR_LOG(JIT, "Tried to use a non-pointer register as a pointer");
|
||||
return INVALID_REG;
|
||||
}
|
||||
} else {
|
||||
ERROR_LOG_REPORT(JIT, "Reg %i not in arm reg. compilerPC = %08x", mipsReg, compilerPC_);
|
||||
return INVALID_REG; // BAAAD
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ typedef int MIPSReg;
|
||||
struct RegARM {
|
||||
MIPSGPReg mipsReg; // if -1, no mipsreg attached.
|
||||
bool isDirty; // Should the register be written back?
|
||||
bool pointerified; // Has used movk to move the memory base into the top part of the reg. Note - still usable as 32-bit reg!
|
||||
};
|
||||
|
||||
struct RegMIPS {
|
||||
@ -110,6 +111,7 @@ public:
|
||||
|
||||
// Returns an ARM register containing the requested MIPS register.
|
||||
Arm64Gen::ARM64Reg MapReg(MIPSGPReg reg, int mapFlags = 0);
|
||||
Arm64Gen::ARM64Reg MapRegAsPointer(MIPSGPReg reg);
|
||||
|
||||
bool IsMapped(MIPSGPReg reg);
|
||||
bool IsMappedAsPointer(MIPSGPReg reg);
|
||||
@ -127,6 +129,7 @@ public:
|
||||
void DiscardR(MIPSGPReg r);
|
||||
|
||||
Arm64Gen::ARM64Reg R(MIPSGPReg preg); // Returns a cached register, while checking that it's NOT mapped as a pointer
|
||||
Arm64Gen::ARM64Reg RPtr(MIPSGPReg preg); // Returns a cached register, if it has been mapped as a pointer
|
||||
|
||||
void SetEmitter(Arm64Gen::ARM64XEmitter *emitter) { emit_ = emitter; }
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user