summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorRyan Houdek <Sonicadvance1@gmail.com>2015-08-31 10:55:45 -0500
committerRyan Houdek <Sonicadvance1@gmail.com>2015-08-31 10:55:45 -0500
commitd003934b8a2c1fcce52346cc2f3836f9e521e1bb (patch)
treeb287ebb2815cf61b41a8f22e1dfb923f628b0f57 /Source/Core
parent368867dba017d4d0f80f0d4a74218ddcf0f449a6 (diff)
parent8bf332cf089c04c3d427542ccbbf2df636e41396 (diff)
Merge pull request #2929 from Sonicadvance1/aarch64_optimize_gpr_flush
Aarch64 optimize gpr flush
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Common/Arm64Emitter.cpp8
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/Jit.cpp6
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.cpp53
-rw-r--r--Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.h8
4 files changed, 59 insertions, 16 deletions
diff --git a/Source/Core/Common/Arm64Emitter.cpp b/Source/Core/Common/Arm64Emitter.cpp
index 3a8303c2e3..385cb09b96 100644
--- a/Source/Core/Common/Arm64Emitter.cpp
+++ b/Source/Core/Common/Arm64Emitter.cpp
@@ -766,7 +766,7 @@ void ARM64XEmitter::EncodeLoadStorePair(u32 op, u32 load, IndexType type, ARM64R
switch (type)
{
- case INDEX_UNSIGNED:
+ case INDEX_SIGNED:
type_encode = 0b010;
break;
case INDEX_POST:
@@ -775,8 +775,8 @@ void ARM64XEmitter::EncodeLoadStorePair(u32 op, u32 load, IndexType type, ARM64R
case INDEX_PRE:
type_encode = 0b011;
break;
- case INDEX_SIGNED:
- _assert_msg_(DYNA_REC, false, "%s doesn't support INDEX_SIGNED!", __FUNCTION__);
+ case INDEX_UNSIGNED:
+ _assert_msg_(DYNA_REC, false, "%s doesn't support INDEX_UNSIGNED!", __FUNCTION__);
break;
}
@@ -1998,7 +1998,7 @@ void ARM64XEmitter::ABI_PushRegisters(BitSet32 registers)
reg_pair.push_back((ARM64Reg)(X0 + it));
if (reg_pair.size() == 2)
{
- STP(INDEX_UNSIGNED, reg_pair[0], reg_pair[1], SP, current_offset);
+ STP(INDEX_SIGNED, reg_pair[0], reg_pair[1], SP, current_offset);
reg_pair.clear();
current_offset += 16;
}
diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp
index 64ae021930..b165020a43 100644
--- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp
+++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp
@@ -478,10 +478,8 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
JitArm64Tables::CompileInstruction(ops[i]);
// If we have a register that will never be used again, flush it.
- for (int j : ~ops[i].gprInUse)
- gpr.StoreRegister(j);
- for (int j : ~ops[i].fprInUse)
- fpr.StoreRegister(j);
+ gpr.StoreRegisters(~ops[i].gprInUse);
+ fpr.StoreRegisters(~ops[i].fprInUse);
if (jo.memcheck && (opinfo->flags & FL_LOADSTORE))
{
diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.cpp
index c58a3cee46..4f539371ab 100644
--- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.cpp
+++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.cpp
@@ -126,8 +126,44 @@ void Arm64GPRCache::FlushRegister(u32 preg, bool maintain_state)
}
}
+void Arm64GPRCache::FlushRegisters(BitSet32 regs, bool maintain_state)
+{
+ for (int i = 0; i < 32; ++i)
+ {
+ if (regs[i])
+ {
+ if (i < 31 && regs[i + 1])
+ {
+ // We've got two guest registers in a row to store
+ OpArg& reg1 = m_guest_registers[i];
+ OpArg& reg2 = m_guest_registers[i + 1];
+ if (reg1.IsDirty() && reg2.IsDirty() &&
+ reg1.GetType() == REG_REG && reg2.GetType() == REG_REG)
+ {
+ ARM64Reg RX1 = R(i);
+ ARM64Reg RX2 = R(i + 1);
+
+ m_emit->STP(INDEX_SIGNED, RX1, RX2, X29, PPCSTATE_OFF(gpr[0]) + i * sizeof(u32));
+ if (!maintain_state)
+ {
+ UnlockRegister(RX1);
+ UnlockRegister(RX2);
+ reg1.Flush();
+ reg2.Flush();
+ }
+ ++i;
+ continue;
+ }
+ }
+
+ FlushRegister(i, maintain_state);
+ }
+ }
+}
+
void Arm64GPRCache::Flush(FlushMode mode, PPCAnalyst::CodeOp* op)
{
+ BitSet32 to_flush;
for (int i = 0; i < 32; ++i)
{
bool flush = true;
@@ -144,15 +180,12 @@ void Arm64GPRCache::Flush(FlushMode mode, PPCAnalyst::CodeOp* op)
{
// Has to be flushed if it isn't in a callee saved register
ARM64Reg host_reg = m_guest_registers[i].GetReg();
- if (flush || !IsCalleeSaved(host_reg))
- FlushRegister(i, mode == FLUSH_MAINTAIN_STATE);
- }
- else if (m_guest_registers[i].GetType() == REG_IMM)
- {
- if (flush)
- FlushRegister(i, mode == FLUSH_MAINTAIN_STATE);
+ flush = IsCalleeSaved(host_reg) ? flush : true;
}
+
+ to_flush[i] = flush;
}
+ FlushRegisters(to_flush, mode == FLUSH_MAINTAIN_STATE);
}
ARM64Reg Arm64GPRCache::R(u32 preg)
@@ -462,6 +495,12 @@ void Arm64FPRCache::FlushRegister(u32 preg, bool maintain_state)
}
}
+void Arm64FPRCache::FlushRegisters(BitSet32 regs, bool maintain_state)
+{
+ for (int j : regs)
+ FlushRegister(j, maintain_state);
+}
+
BitSet32 Arm64FPRCache::GetCallerSavedUsed()
{
BitSet32 registers(0);
diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.h b/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.h
index 433f0dad8f..084ab8c94a 100644
--- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.h
+++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_RegCache.h
@@ -141,7 +141,7 @@ public:
// Requires unlocking after done
ARM64Reg GetReg();
- void StoreRegister(u32 preg) { FlushRegister(preg, false); }
+ void StoreRegisters(BitSet32 regs) { FlushRegisters(regs, false); }
// Locks a register so a cache cannot use it
// Useful for function calls
@@ -185,6 +185,8 @@ protected:
virtual void FlushRegister(u32 preg, bool maintain_state) = 0;
+ virtual void FlushRegisters(BitSet32 regs, bool maintain_state) = 0;
+
// Get available host registers
u32 GetUnlockedRegisterCount();
@@ -248,6 +250,8 @@ protected:
void FlushRegister(u32 preg, bool maintain_state) override;
+ void FlushRegisters(BitSet32 regs, bool maintain_state) override;
+
private:
bool IsCalleeSaved(ARM64Reg reg);
@@ -280,6 +284,8 @@ protected:
void FlushRegister(u32 preg, bool maintain_state) override;
+ void FlushRegisters(BitSet32 regs, bool maintain_state) override;
+
private:
bool IsCalleeSaved(ARM64Reg reg);
};