diff --git a/FEXCore/Source/Interface/Core/ArchHelpers/Arm64Emitter.cpp b/FEXCore/Source/Interface/Core/ArchHelpers/Arm64Emitter.cpp index 2b50b2dd61..b79cde6e65 100644 --- a/FEXCore/Source/Interface/Core/ArchHelpers/Arm64Emitter.cpp +++ b/FEXCore/Source/Interface/Core/ArchHelpers/Arm64Emitter.cpp @@ -454,6 +454,17 @@ void Arm64Emitter::LoadConstant(ARMEmitter::Size s, ARMEmitter::Register Reg, ui } } + // If we can't handle negatives with the orr, try with movn+movk + if (Is64Bit && ((~Constant) >> 32) == 0) { + movn(s, Reg, (~Constant) & 0xFFFF); + movk(s, Reg, (Constant >> 16) & 0xFFFF, 16); + if (NOPPad) { + nop(); + nop(); + } + return; + } + // ADRP+ADD is specifically optimized in hardware // Check if we can use this auto PC = GetCursorAddress(); diff --git a/unittests/InstructionCountCI/FlagM/Secondary.json b/unittests/InstructionCountCI/FlagM/Secondary.json index 5e2e61ff26..e12e33122b 100644 --- a/unittests/InstructionCountCI/FlagM/Secondary.json +++ b/unittests/InstructionCountCI/FlagM/Secondary.json @@ -1008,6 +1008,19 @@ "ccmn xzr, #0, #nzCV, eq" ] }, + "imul rsi, rax, 0xffffffff8646c299": { + "ExpectedInstructionCount": 7, + "Comment": "0x0f 0xaf", + "ExpectedArm64ASM": [ + "mov x20, #0xffffffffffffc299", + "movk x20, #0x8646, lsl #16", + "smulh x21, x4, x20", + "mul x10, x4, x20", + "asr x20, x10, #63", + "cmp x21, x20", + "ccmn xzr, #0, #nzCV, eq" + ] + }, "cmpxchg cl, bl": { "ExpectedInstructionCount": 11, "ExpectedArm64ASM": [