mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-24 22:34:54 +00:00
JitArm64: Don't update dest reg when load triggers exception
Fixes a problem introduced in the previous commit.
This commit is contained in:
parent
ab1ceee16f
commit
96190887ce
4 changed files with 47 additions and 18 deletions
|
@ -498,14 +498,15 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external, bool always
|
||||||
B(dispatcher);
|
B(dispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitArm64::WriteConditionalExceptionExit(int exception)
|
void JitArm64::WriteConditionalExceptionExit(int exception, u64 increment_sp_on_exit)
|
||||||
{
|
{
|
||||||
ARM64Reg WA = gpr.GetReg();
|
ARM64Reg WA = gpr.GetReg();
|
||||||
WriteConditionalExceptionExit(exception, WA);
|
WriteConditionalExceptionExit(exception, WA, increment_sp_on_exit);
|
||||||
gpr.Unlock(WA);
|
gpr.Unlock(WA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitArm64::WriteConditionalExceptionExit(int exception, ARM64Reg temp_reg)
|
void JitArm64::WriteConditionalExceptionExit(int exception, ARM64Reg temp_reg,
|
||||||
|
u64 increment_sp_on_exit)
|
||||||
{
|
{
|
||||||
LDR(IndexType::Unsigned, temp_reg, PPC_REG, PPCSTATE_OFF(Exceptions));
|
LDR(IndexType::Unsigned, temp_reg, PPC_REG, PPCSTATE_OFF(Exceptions));
|
||||||
FixupBranch no_exception = TBZ(temp_reg, IntLog2(exception));
|
FixupBranch no_exception = TBZ(temp_reg, IntLog2(exception));
|
||||||
|
@ -519,6 +520,9 @@ void JitArm64::WriteConditionalExceptionExit(int exception, ARM64Reg temp_reg)
|
||||||
SetJumpTarget(handle_exception);
|
SetJumpTarget(handle_exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (increment_sp_on_exit != 0)
|
||||||
|
ADDI2R(ARM64Reg::SP, ARM64Reg::SP, increment_sp_on_exit, temp_reg);
|
||||||
|
|
||||||
gpr.Flush(FlushMode::MaintainState, temp_reg);
|
gpr.Flush(FlushMode::MaintainState, temp_reg);
|
||||||
fpr.Flush(FlushMode::MaintainState, ARM64Reg::INVALID_REG);
|
fpr.Flush(FlushMode::MaintainState, ARM64Reg::INVALID_REG);
|
||||||
|
|
||||||
|
|
|
@ -265,8 +265,9 @@ protected:
|
||||||
bool always_exception = false);
|
bool always_exception = false);
|
||||||
void WriteExceptionExit(Arm64Gen::ARM64Reg dest, bool only_external = false,
|
void WriteExceptionExit(Arm64Gen::ARM64Reg dest, bool only_external = false,
|
||||||
bool always_exception = false);
|
bool always_exception = false);
|
||||||
void WriteConditionalExceptionExit(int exception);
|
void WriteConditionalExceptionExit(int exception, u64 increment_sp_on_exit = 0);
|
||||||
void WriteConditionalExceptionExit(int exception, Arm64Gen::ARM64Reg temp_reg);
|
void WriteConditionalExceptionExit(int exception, Arm64Gen::ARM64Reg temp_reg,
|
||||||
|
u64 increment_sp_on_exit = 0);
|
||||||
void FakeLKExit(u32 exit_address_after_return);
|
void FakeLKExit(u32 exit_address_after_return);
|
||||||
void WriteBLRExit(Arm64Gen::ARM64Reg dest);
|
void WriteBLRExit(Arm64Gen::ARM64Reg dest);
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,8 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, AR
|
||||||
ARM64Reg addr, BitSet32 gprs_to_push, BitSet32 fprs_to_push,
|
ARM64Reg addr, BitSet32 gprs_to_push, BitSet32 fprs_to_push,
|
||||||
bool emitting_routine)
|
bool emitting_routine)
|
||||||
{
|
{
|
||||||
|
const u32 access_size = BackPatchInfo::GetFlagSize(flags);
|
||||||
|
|
||||||
bool in_far_code = false;
|
bool in_far_code = false;
|
||||||
const u8* fastmem_start = GetCodePtr();
|
const u8* fastmem_start = GetCodePtr();
|
||||||
std::optional<FixupBranch> slowmem_fixup;
|
std::optional<FixupBranch> slowmem_fixup;
|
||||||
|
@ -76,11 +78,11 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, AR
|
||||||
ARM64Reg temp = ARM64Reg::D0;
|
ARM64Reg temp = ARM64Reg::D0;
|
||||||
temp = ByteswapBeforeStore(this, &m_float_emit, temp, EncodeRegToDouble(RS), flags, true);
|
temp = ByteswapBeforeStore(this, &m_float_emit, temp, EncodeRegToDouble(RS), flags, true);
|
||||||
|
|
||||||
m_float_emit.STR(BackPatchInfo::GetFlagSize(flags), temp, MEM_REG, addr);
|
m_float_emit.STR(access_size, temp, MEM_REG, addr);
|
||||||
}
|
}
|
||||||
else if ((flags & BackPatchInfo::FLAG_LOAD) && (flags & BackPatchInfo::FLAG_FLOAT))
|
else if ((flags & BackPatchInfo::FLAG_LOAD) && (flags & BackPatchInfo::FLAG_FLOAT))
|
||||||
{
|
{
|
||||||
m_float_emit.LDR(BackPatchInfo::GetFlagSize(flags), EncodeRegToDouble(RS), MEM_REG, addr);
|
m_float_emit.LDR(access_size, EncodeRegToDouble(RS), MEM_REG, addr);
|
||||||
|
|
||||||
ByteswapAfterLoad(this, &m_float_emit, EncodeRegToDouble(RS), EncodeRegToDouble(RS), flags,
|
ByteswapAfterLoad(this, &m_float_emit, EncodeRegToDouble(RS), EncodeRegToDouble(RS), flags,
|
||||||
true, false);
|
true, false);
|
||||||
|
@ -139,12 +141,22 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, AR
|
||||||
if (slowmem_fixup)
|
if (slowmem_fixup)
|
||||||
SetJumpTarget(*slowmem_fixup);
|
SetJumpTarget(*slowmem_fixup);
|
||||||
|
|
||||||
|
const ARM64Reg temp_reg = flags & BackPatchInfo::FLAG_LOAD ? ARM64Reg::W30 : ARM64Reg::W0;
|
||||||
|
const int temp_reg_index = DecodeReg(temp_reg);
|
||||||
|
|
||||||
|
if (memcheck && (flags & BackPatchInfo::FLAG_LOAD))
|
||||||
|
{
|
||||||
|
ABI_PushRegisters(gprs_to_push & BitSet32{temp_reg_index});
|
||||||
|
ABI_PushRegisters(gprs_to_push & ~BitSet32{temp_reg_index});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ABI_PushRegisters(gprs_to_push);
|
ABI_PushRegisters(gprs_to_push);
|
||||||
|
}
|
||||||
m_float_emit.ABI_PushRegisters(fprs_to_push, ARM64Reg::X30);
|
m_float_emit.ABI_PushRegisters(fprs_to_push, ARM64Reg::X30);
|
||||||
|
|
||||||
if (flags & BackPatchInfo::FLAG_STORE)
|
if (flags & BackPatchInfo::FLAG_STORE)
|
||||||
{
|
{
|
||||||
const u32 access_size = BackPatchInfo::GetFlagSize(flags);
|
|
||||||
ARM64Reg src_reg = RS;
|
ARM64Reg src_reg = RS;
|
||||||
const ARM64Reg dst_reg = access_size == 64 ? ARM64Reg::X0 : ARM64Reg::W0;
|
const ARM64Reg dst_reg = access_size == 64 ? ARM64Reg::X0 : ARM64Reg::W0;
|
||||||
|
|
||||||
|
@ -188,8 +200,6 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, AR
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const u32 access_size = BackPatchInfo::GetFlagSize(flags);
|
|
||||||
|
|
||||||
if (access_size == 64)
|
if (access_size == 64)
|
||||||
MOVP2R(ARM64Reg::X8, &PowerPC::Read_U64);
|
MOVP2R(ARM64Reg::X8, &PowerPC::Read_U64);
|
||||||
else if (access_size == 32)
|
else if (access_size == 32)
|
||||||
|
@ -200,8 +210,24 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, AR
|
||||||
MOVP2R(ARM64Reg::X8, &PowerPC::Read_U8);
|
MOVP2R(ARM64Reg::X8, &PowerPC::Read_U8);
|
||||||
|
|
||||||
BLR(ARM64Reg::X8);
|
BLR(ARM64Reg::X8);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_float_emit.ABI_PopRegisters(fprs_to_push, ARM64Reg::X30);
|
||||||
|
if (memcheck && (flags & BackPatchInfo::FLAG_LOAD))
|
||||||
|
ABI_PopRegisters(gprs_to_push & ~BitSet32{temp_reg_index});
|
||||||
|
else
|
||||||
|
ABI_PopRegisters(gprs_to_push);
|
||||||
|
|
||||||
|
if (memcheck)
|
||||||
|
{
|
||||||
|
const u64 early_push_size = flags & BackPatchInfo::FLAG_LOAD ? 16 : 0;
|
||||||
|
WriteConditionalExceptionExit(EXCEPTION_DSI, temp_reg, early_push_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & BackPatchInfo::FLAG_LOAD)
|
||||||
|
{
|
||||||
ARM64Reg src_reg = access_size == 64 ? ARM64Reg::X0 : ARM64Reg::W0;
|
ARM64Reg src_reg = access_size == 64 ? ARM64Reg::X0 : ARM64Reg::W0;
|
||||||
|
ASSERT(!gprs_to_push[DecodeReg(src_reg)]);
|
||||||
|
|
||||||
if (flags & BackPatchInfo::FLAG_PAIR)
|
if (flags & BackPatchInfo::FLAG_PAIR)
|
||||||
{
|
{
|
||||||
|
@ -222,13 +248,10 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, AR
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteswapAfterLoad(this, &m_float_emit, RS, src_reg, flags, false, false);
|
ByteswapAfterLoad(this, &m_float_emit, RS, src_reg, flags, false, false);
|
||||||
}
|
|
||||||
|
|
||||||
m_float_emit.ABI_PopRegisters(fprs_to_push, ARM64Reg::X30);
|
|
||||||
ABI_PopRegisters(gprs_to_push);
|
|
||||||
|
|
||||||
if (memcheck)
|
if (memcheck)
|
||||||
WriteConditionalExceptionExit(EXCEPTION_DSI, ARM64Reg::W0);
|
ABI_PopRegisters(gprs_to_push & BitSet32{temp_reg_index});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_far_code)
|
if (in_far_code)
|
||||||
|
|
|
@ -113,6 +113,7 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o
|
||||||
BitSet32 regs_in_use = gpr.GetCallerSavedUsed();
|
BitSet32 regs_in_use = gpr.GetCallerSavedUsed();
|
||||||
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
|
BitSet32 fprs_in_use = fpr.GetCallerSavedUsed();
|
||||||
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
|
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
|
||||||
|
if (!jo.memcheck)
|
||||||
regs_in_use[DecodeReg(dest_reg)] = 0;
|
regs_in_use[DecodeReg(dest_reg)] = 0;
|
||||||
|
|
||||||
u32 access_size = BackPatchInfo::GetFlagSize(flags);
|
u32 access_size = BackPatchInfo::GetFlagSize(flags);
|
||||||
|
|
Loading…
Add table
Reference in a new issue