mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-25 16:00:12 +01:00
Fixes a potential crash in ARM64's AtomicSwap
When RA made the source address register be the same register as the destination register then we could have overwritten the address with the move. Use a temporary until we get RA constraints in place.
This commit is contained in:
1 parent
1e9d86ab09
commit
bad7cd1262
1 file changed
+14
-9
@@ -544,49 +544,54 @@ DEF_OP(AtomicSwap) {
|
||||
MemSrc = TMP1;
|
||||
}
|
||||
|
||||
mov(GetReg<RA_64>(Node), GetReg<RA_64>(Op->Header.Args[1].ID()));
|
||||
if (SupportsAtomics) {
|
||||
mov(TMP2, GetReg<RA_64>(Op->Header.Args[1].ID()));
|
||||
switch (Op->Size) {
|
||||
case 1: swplb(GetReg<RA_32>(Node), xzr, MemOperand(MemSrc)); break;
|
||||
case 2: swplh(GetReg<RA_32>(Node), xzr, MemOperand(MemSrc)); break;
|
||||
case 4: swpl(GetReg<RA_32>(Node), xzr, MemOperand(MemSrc)); break;
|
||||
case 8: swpl(GetReg<RA_64>(Node), xzr, MemOperand(MemSrc)); break;
|
||||
case 1: swplb(TMP2.W(), GetReg<RA_32>(Node), MemOperand(MemSrc)); break;
|
||||
case 2: swplh(TMP2.W(), GetReg<RA_32>(Node), MemOperand(MemSrc)); break;
|
||||
case 4: swpl(TMP2.W(), GetReg<RA_32>(Node), MemOperand(MemSrc)); break;
|
||||
case 8: swpl(TMP2.X(), GetReg<RA_64>(Node), MemOperand(MemSrc)); break;
|
||||
default: LogMan::Msg::A("Unhandled Atomic size: %d", Op->Size);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TMP2-TMP3
|
||||
mov(TMP3, GetReg<RA_64>(Op->Header.Args[1].ID()));
|
||||
switch (Op->Size) {
|
||||
case 1: {
|
||||
aarch64::Label LoopTop;
|
||||
bind(&LoopTop);
|
||||
ldaxrb(TMP2.W(), MemOperand(MemSrc));
|
||||
stlxrb(TMP2.W(), GetReg<RA_32>(Node), MemOperand(MemSrc));
|
||||
stlxrb(TMP2.W(), TMP3.W(), MemOperand(MemSrc));
|
||||
cbnz(TMP2.W(), &LoopTop);
|
||||
uxtb(GetReg<RA_64>(Node), TMP3.W());
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
aarch64::Label LoopTop;
|
||||
bind(&LoopTop);
|
||||
ldaxrh(TMP2.W(), MemOperand(MemSrc));
|
||||
stlxrh(TMP2.W(), GetReg<RA_32>(Node), MemOperand(MemSrc));
|
||||
stlxrh(TMP2.W(), TMP3.W(), MemOperand(MemSrc));
|
||||
cbnz(TMP2.W(), &LoopTop);
|
||||
uxtw(GetReg<RA_64>(Node), TMP3.W());
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
aarch64::Label LoopTop;
|
||||
bind(&LoopTop);
|
||||
ldaxr(TMP2.W(), MemOperand(MemSrc));
|
||||
stlxr(TMP2.W(), GetReg<RA_32>(Node), MemOperand(MemSrc));
|
||||
stlxr(TMP2.W(), TMP3.W(), MemOperand(MemSrc));
|
||||
cbnz(TMP2.W(), &LoopTop);
|
||||
mov(GetReg<RA_32>(Node), TMP3.W());
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
aarch64::Label LoopTop;
|
||||
bind(&LoopTop);
|
||||
ldaxr(TMP2, MemOperand(MemSrc));
|
||||
stlxr(TMP2, GetReg<RA_64>(Node), MemOperand(MemSrc));
|
||||
stlxr(TMP2, TMP3.X(), MemOperand(MemSrc));
|
||||
cbnz(TMP2, &LoopTop);
|
||||
mov(GetReg<RA_64>(Node), TMP3.X());
|
||||
break;
|
||||
}
|
||||
default: LogMan::Msg::A("Unhandled Atomic size: %d", Op->Size);
|
||||
|
||||
Reference in new issue
Block a user