diff --git a/FEXCore/Source/Interface/Core/JIT/Arm64/AtomicOps.cpp b/FEXCore/Source/Interface/Core/JIT/Arm64/AtomicOps.cpp index 97487ffa3..0c0dc78dd 100644 --- a/FEXCore/Source/Interface/Core/JIT/Arm64/AtomicOps.cpp +++ b/FEXCore/Source/Interface/Core/JIT/Arm64/AtomicOps.cpp @@ -193,6 +193,33 @@ DEF_OP(AtomicAnd) { } } +DEF_OP(AtomicCLR) { + auto Op = IROp->C(); + uint8_t OpSize = IROp->Size; + LOGMAN_THROW_AA_FMT(OpSize == 8 || OpSize == 4 || OpSize == 2 || OpSize == 1, "Unexpected CAS size"); + + auto MemSrc = GetReg(Op->Addr.ID()); + auto Src = GetReg(Op->Value.ID()); + + const auto EmitSize = OpSize == 8 ? ARMEmitter::Size::i64Bit : ARMEmitter::Size::i32Bit; + const auto SubEmitSize = OpSize == 8 ? ARMEmitter::SubRegSize::i64Bit : + OpSize == 4 ? ARMEmitter::SubRegSize::i32Bit : + OpSize == 2 ? ARMEmitter::SubRegSize::i16Bit : + OpSize == 1 ? ARMEmitter::SubRegSize::i8Bit : ARMEmitter::SubRegSize::i8Bit; + + if (CTX->HostFeatures.SupportsAtomics) { + stclrl(SubEmitSize, Src, MemSrc); + } + else { + ARMEmitter::BackwardLabel LoopTop; + Bind(&LoopTop); + ldaxr(SubEmitSize, TMP2, MemSrc); + bic(EmitSize, TMP2, TMP2, Src); + stlxr(SubEmitSize, TMP2, TMP2, MemSrc); + cbnz(EmitSize, TMP2, &LoopTop); + } +} + DEF_OP(AtomicOr) { auto Op = IROp->C(); uint8_t OpSize = IROp->Size; @@ -247,6 +274,27 @@ DEF_OP(AtomicXor) { } } +DEF_OP(AtomicNeg) { + auto Op = IROp->C(); + uint8_t OpSize = IROp->Size; + LOGMAN_THROW_AA_FMT(OpSize == 8 || OpSize == 4 || OpSize == 2 || OpSize == 1, "Unexpected CAS size"); + + auto MemSrc = GetReg(Op->Addr.ID()); + + const auto EmitSize = OpSize == 8 ? ARMEmitter::Size::i64Bit : ARMEmitter::Size::i32Bit; + const auto SubEmitSize = OpSize == 8 ? ARMEmitter::SubRegSize::i64Bit : + OpSize == 4 ? ARMEmitter::SubRegSize::i32Bit : + OpSize == 2 ? ARMEmitter::SubRegSize::i16Bit : + OpSize == 1 ? ARMEmitter::SubRegSize::i8Bit : ARMEmitter::SubRegSize::i8Bit; + + ARMEmitter::BackwardLabel LoopTop; + Bind(&LoopTop); + ldaxr(SubEmitSize, TMP2, MemSrc); + neg(EmitSize, TMP3, TMP2); + stlxr(SubEmitSize, TMP4, TMP3, MemSrc); + cbnz(EmitSize, TMP4, &LoopTop); +} + DEF_OP(AtomicSwap) { auto Op = IROp->C(); uint8_t OpSize = IROp->Size; diff --git a/FEXCore/Source/Interface/IR/IR.json b/FEXCore/Source/Interface/IR/IR.json index 3c2361f70..64e0ebb8c 100644 --- a/FEXCore/Source/Interface/IR/IR.json +++ b/FEXCore/Source/Interface/IR/IR.json @@ -650,6 +650,15 @@ "Size == FEXCore::IR::OpSize::i8Bit || Size == FEXCore::IR::OpSize::i16Bit || Size == FEXCore::IR::OpSize::i32Bit || Size == FEXCore::IR::OpSize::i64Bit" ] }, + "AtomicCLR OpSize:#Size, GPR:$Value, GPR:$Addr": { + "HasSideEffects": true, + "Desc": ["Atomic integer binary clear" + ], + "DestSize": "Size", + "EmitValidation": [ + "Size == FEXCore::IR::OpSize::i8Bit || Size == FEXCore::IR::OpSize::i16Bit || Size == FEXCore::IR::OpSize::i32Bit || Size == FEXCore::IR::OpSize::i64Bit" + ] + }, "AtomicOr OpSize:#Size, GPR:$Value, GPR:$Addr": { "HasSideEffects": true, "Desc": ["Atomic integer or" @@ -668,6 +677,15 @@ "Size == FEXCore::IR::OpSize::i8Bit || Size == FEXCore::IR::OpSize::i16Bit || Size == FEXCore::IR::OpSize::i32Bit || Size == FEXCore::IR::OpSize::i64Bit" ] }, + "AtomicNeg OpSize:#Size, GPR:$Addr": { + "HasSideEffects": true, + "Desc": ["Atomic integer two's complement negate" + ], + "DestSize": "Size", + "EmitValidation": [ + "Size == FEXCore::IR::OpSize::i8Bit || Size == FEXCore::IR::OpSize::i16Bit || Size == FEXCore::IR::OpSize::i32Bit || Size == FEXCore::IR::OpSize::i64Bit" + ] + }, "GPR = AtomicSwap OpSize:#Size, GPR:$Value, GPR:$Addr": { "HasSideEffects": true, "Desc": ["Atomic integer swap"