From bad7cd12626426ba2f2a8d5db9ded2ba396b3015 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 19 Aug 2020 13:10:32 -0700 Subject: [PATCH] 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. --- .../Interface/Core/JIT/Arm64/AtomicOps.cpp | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/JIT/Arm64/AtomicOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/Arm64/AtomicOps.cpp index 5bdd39837..2e92b7bd2 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/AtomicOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/AtomicOps.cpp @@ -544,49 +544,54 @@ DEF_OP(AtomicSwap) { MemSrc = TMP1; } - mov(GetReg(Node), GetReg(Op->Header.Args[1].ID())); if (SupportsAtomics) { + mov(TMP2, GetReg(Op->Header.Args[1].ID())); switch (Op->Size) { - case 1: swplb(GetReg(Node), xzr, MemOperand(MemSrc)); break; - case 2: swplh(GetReg(Node), xzr, MemOperand(MemSrc)); break; - case 4: swpl(GetReg(Node), xzr, MemOperand(MemSrc)); break; - case 8: swpl(GetReg(Node), xzr, MemOperand(MemSrc)); break; + case 1: swplb(TMP2.W(), GetReg(Node), MemOperand(MemSrc)); break; + case 2: swplh(TMP2.W(), GetReg(Node), MemOperand(MemSrc)); break; + case 4: swpl(TMP2.W(), GetReg(Node), MemOperand(MemSrc)); break; + case 8: swpl(TMP2.X(), GetReg(Node), MemOperand(MemSrc)); break; default: LogMan::Msg::A("Unhandled Atomic size: %d", Op->Size); } } else { // TMP2-TMP3 + mov(TMP3, GetReg(Op->Header.Args[1].ID())); switch (Op->Size) { case 1: { aarch64::Label LoopTop; bind(&LoopTop); ldaxrb(TMP2.W(), MemOperand(MemSrc)); - stlxrb(TMP2.W(), GetReg(Node), MemOperand(MemSrc)); + stlxrb(TMP2.W(), TMP3.W(), MemOperand(MemSrc)); cbnz(TMP2.W(), &LoopTop); + uxtb(GetReg(Node), TMP3.W()); break; } case 2: { aarch64::Label LoopTop; bind(&LoopTop); ldaxrh(TMP2.W(), MemOperand(MemSrc)); - stlxrh(TMP2.W(), GetReg(Node), MemOperand(MemSrc)); + stlxrh(TMP2.W(), TMP3.W(), MemOperand(MemSrc)); cbnz(TMP2.W(), &LoopTop); + uxtw(GetReg(Node), TMP3.W()); break; } case 4: { aarch64::Label LoopTop; bind(&LoopTop); ldaxr(TMP2.W(), MemOperand(MemSrc)); - stlxr(TMP2.W(), GetReg(Node), MemOperand(MemSrc)); + stlxr(TMP2.W(), TMP3.W(), MemOperand(MemSrc)); cbnz(TMP2.W(), &LoopTop); + mov(GetReg(Node), TMP3.W()); break; } case 8: { aarch64::Label LoopTop; bind(&LoopTop); ldaxr(TMP2, MemOperand(MemSrc)); - stlxr(TMP2, GetReg(Node), MemOperand(MemSrc)); + stlxr(TMP2, TMP3.X(), MemOperand(MemSrc)); cbnz(TMP2, &LoopTop); + mov(GetReg(Node), TMP3.X()); break; } default: LogMan::Msg::A("Unhandled Atomic size: %d", Op->Size);