mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-05-09 03:58:06 +03:00
JitArm64: Guard against discarding a in lmw/stmw
If a_is_addr_base_reg is true, discarding a before the end of the instruction would result in the instruction being miscompiled.
This commit is contained in:
parent
e2472e4f50
commit
13a4f1b799
1 changed files with 28 additions and 2 deletions
|
@ -541,6 +541,19 @@ void JitArm64::lmw(UGeckoInstruction inst)
|
||||||
if (!a_is_addr_base_reg)
|
if (!a_is_addr_base_reg)
|
||||||
MOV(addr_base_reg, addr_reg);
|
MOV(addr_base_reg, addr_reg);
|
||||||
|
|
||||||
|
BitSet32 gprs_to_discard{};
|
||||||
|
if (!jo.memcheck)
|
||||||
|
{
|
||||||
|
gprs_to_discard = js.op->gprDiscardable;
|
||||||
|
if (gprs_to_discard[a])
|
||||||
|
{
|
||||||
|
if (a_is_addr_base_reg)
|
||||||
|
gprs_to_discard[a] = false;
|
||||||
|
else
|
||||||
|
gpr.DiscardRegisters(BitSet32{int(a)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BitSet32 gprs_to_flush = ~js.op->gprInUse & BitSet32(0xFFFFFFFFU << d);
|
BitSet32 gprs_to_flush = ~js.op->gprInUse & BitSet32(0xFFFFFFFFU << d);
|
||||||
if (!js.op->gprInUse[a])
|
if (!js.op->gprInUse[a])
|
||||||
{
|
{
|
||||||
|
@ -592,7 +605,7 @@ void JitArm64::lmw(UGeckoInstruction inst)
|
||||||
// after this instruction, flush registers that would be flushed after this instruction anyway.
|
// after this instruction, flush registers that would be flushed after this instruction anyway.
|
||||||
//
|
//
|
||||||
// We try to store two registers at a time when possible to let the register cache use STP.
|
// We try to store two registers at a time when possible to let the register cache use STP.
|
||||||
if (!jo.memcheck && js.op->gprDiscardable[i])
|
if (gprs_to_discard[i])
|
||||||
{
|
{
|
||||||
gpr.DiscardRegisters(BitSet32{int(i)});
|
gpr.DiscardRegisters(BitSet32{int(i)});
|
||||||
}
|
}
|
||||||
|
@ -645,6 +658,19 @@ void JitArm64::stmw(UGeckoInstruction inst)
|
||||||
if (!a_is_addr_base_reg)
|
if (!a_is_addr_base_reg)
|
||||||
MOV(addr_base_reg, addr_reg);
|
MOV(addr_base_reg, addr_reg);
|
||||||
|
|
||||||
|
BitSet32 gprs_to_discard{};
|
||||||
|
if (!jo.memcheck)
|
||||||
|
{
|
||||||
|
gprs_to_discard = js.op->gprDiscardable;
|
||||||
|
if (gprs_to_discard[a])
|
||||||
|
{
|
||||||
|
if (a_is_addr_base_reg)
|
||||||
|
gprs_to_discard[a] = false;
|
||||||
|
else
|
||||||
|
gpr.DiscardRegisters(BitSet32{int(a)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const BitSet32 dirty_gprs_to_flush_unmasked = ~js.op->gprInUse & gpr.GetDirtyGPRs();
|
const BitSet32 dirty_gprs_to_flush_unmasked = ~js.op->gprInUse & gpr.GetDirtyGPRs();
|
||||||
BitSet32 dirty_gprs_to_flush = dirty_gprs_to_flush_unmasked & BitSet32(0xFFFFFFFFU << s);
|
BitSet32 dirty_gprs_to_flush = dirty_gprs_to_flush_unmasked & BitSet32(0xFFFFFFFFU << s);
|
||||||
if (dirty_gprs_to_flush_unmasked[a])
|
if (dirty_gprs_to_flush_unmasked[a])
|
||||||
|
@ -692,7 +718,7 @@ void JitArm64::stmw(UGeckoInstruction inst)
|
||||||
// after this instruction, flush registers that would be flushed after this instruction anyway.
|
// after this instruction, flush registers that would be flushed after this instruction anyway.
|
||||||
//
|
//
|
||||||
// We try to store two registers at a time when possible to let the register cache use STP.
|
// We try to store two registers at a time when possible to let the register cache use STP.
|
||||||
if (!jo.memcheck && js.op->gprDiscardable[i])
|
if (gprs_to_discard[i])
|
||||||
{
|
{
|
||||||
gpr.DiscardRegisters(BitSet32{int(i)});
|
gpr.DiscardRegisters(BitSet32{int(i)});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue