[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).
This commit is contained in:
parent
20fe7bc4b7
commit
4303f6b200
|
@ -2638,9 +2638,29 @@ void EmitAndNotXX(X64Emitter& e, const ARGS& i) {
|
||||||
e.mov(i.dest, i.src1.constant() & ~i.src2.constant());
|
e.mov(i.dest, i.src1.constant() & ~i.src2.constant());
|
||||||
} else {
|
} else {
|
||||||
// src1 constant.
|
// src1 constant.
|
||||||
e.mov(i.dest, i.src2.constant());
|
|
||||||
e.not_(i.dest);
|
// `and` instruction only supports up to 32-bit immediate constants
|
||||||
e.and_(i.dest, i.src1);
|
// 64-bit constants will need a temp register
|
||||||
|
if (i.dest.reg().getBit() == 64) {
|
||||||
|
auto temp = GetTempReg<typename decltype(i.src1)::reg_type>(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) {
|
} else if (i.src2.is_constant) {
|
||||||
// src2 constant.
|
// src2 constant.
|
||||||
|
|
Loading…
Reference in New Issue