From 37aa3d129cdf43e5b843cfba74f719bb6f2ab319 Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Mon, 10 Jan 2022 13:37:19 -0800 Subject: [PATCH] [x64] Explicitly handle AND_NOT `dest == src1` This addresses a JIT-issue in the case that the `src1` and `dest` register are both the same. This issue only happens in the "generic" x86 path but not in the BMI1-accelerated path. Thanks Rick for the extensive debugging help. When `src1` and `dest` were the same, then the `addc` instruction at `82099A08` in title `584108FF` might emit the following assembly: ``` .text:82099A08 andc r11, r10, r11 | | Jitted | V 00000000A0011B15 mov rbx,r10 00000000A0011B18 not rbx 00000000A0011B1B and rbx,rbx ``` This was due to the src1 operand and the destination register being the same, which used to call the "else" case in the x64 emitter when it needs to be handled explicitly due to register aliasing/allocation. Addresses issue #1945 --- src/xenia/cpu/backend/x64/x64_sequences.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/xenia/cpu/backend/x64/x64_sequences.cc b/src/xenia/cpu/backend/x64/x64_sequences.cc index 638e63364..62f6e9a3f 100644 --- a/src/xenia/cpu/backend/x64/x64_sequences.cc +++ b/src/xenia/cpu/backend/x64/x64_sequences.cc @@ -2688,6 +2688,11 @@ void EmitAndNotXX(X64Emitter& e, const ARGS& i) { if (i.dest == i.src2) { e.not_(i.dest); e.and_(i.dest, i.src1); + } else if (i.dest == i.src1) { + auto temp = GetTempReg(e); + e.mov(temp, i.src2); + e.not_(temp); + e.and_(i.dest, temp); } else { e.mov(i.dest, i.src2); e.not_(i.dest);