From 4303f6b200d991eb24be78d46065f36b8066eabf Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Thu, 6 Jan 2022 10:02:33 -0800 Subject: [PATCH] [x64] Fix OPCODE_AND_NOT src1-constant case Fix the the case where src1 is constant and src2 is non-constant causing an assert due to trying to call `.constant()` on the src2 operand. Interfaces with an issue Gliniak was encountering where title `4D53082D` encounters an assert. Also includes a BMI1-acceleration in the 64-bit case where a temporary register is needed(the `and` x86 instruction only supports immediate constants up to 32-bits). --- src/xenia/cpu/backend/x64/x64_sequences.cc | 26 +++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/xenia/cpu/backend/x64/x64_sequences.cc b/src/xenia/cpu/backend/x64/x64_sequences.cc index 15ddebef3..638e63364 100644 --- a/src/xenia/cpu/backend/x64/x64_sequences.cc +++ b/src/xenia/cpu/backend/x64/x64_sequences.cc @@ -2638,9 +2638,29 @@ void EmitAndNotXX(X64Emitter& e, const ARGS& i) { e.mov(i.dest, i.src1.constant() & ~i.src2.constant()); } else { // src1 constant. - e.mov(i.dest, i.src2.constant()); - e.not_(i.dest); - e.and_(i.dest, i.src1); + + // `and` instruction only supports up to 32-bit immediate constants + // 64-bit constants will need a temp register + if (i.dest.reg().getBit() == 64) { + auto temp = GetTempReg(e); + e.mov(temp, i.src1.constant()); + + if (e.IsFeatureEnabled(kX64EmitBMI1)) { + if (i.dest.reg().getBit() == 64) { + e.andn(i.dest.reg().cvt64(), i.src2.reg().cvt64(), temp.cvt64()); + } else { + e.andn(i.dest.reg().cvt32(), i.src2.reg().cvt32(), temp.cvt32()); + } + } else { + e.mov(i.dest, i.src2); + e.not_(i.dest); + e.and_(i.dest, temp); + } + } else { + e.mov(i.dest, i.src2); + e.not_(i.dest); + e.and_(i.dest, uint32_t(i.src1.constant())); + } } } else if (i.src2.is_constant) { // src2 constant.