@@ -264,16 +264,37 @@ static void GenerateANDN(const ZydisDecodedOperand* operands, Xbyak::CodeGenerat
264
264
const auto src1 = ZydisToXbyakRegisterOperand (operands[1 ]);
265
265
const auto src2 = ZydisToXbyakOperand (operands[2 ]);
266
266
267
- const auto scratch = AllocateScratchRegister ({&dst, &src1, src2.get ()}, dst.getBit ());
267
+ // Check if src2 is a memory operand or a register different to dst.
268
+ // In those cases, we don't need to use a temporary register and are free to modify dst.
269
+ // In cases where dst and src2 are the same register, a temporary needs to be used to avoid
270
+ // modifying src2.
271
+ bool src2_uses_dst = false ;
272
+ if (src2->isMEM ()) {
273
+ const auto base = src2->getAddress ().getRegExp ().getBase ().getIdx ();
274
+ const auto index = src2->getAddress ().getRegExp ().getIndex ().getIdx ();
275
+ src2_uses_dst = base == dst.getIdx () || index == dst.getIdx ();
276
+ } else {
277
+ ASSERT (src2->isREG ());
278
+ src2_uses_dst = src2->getReg () == dst;
279
+ }
268
280
269
- SaveRegisters (c, {scratch});
281
+ if (!src2_uses_dst) {
282
+ if (dst != src1)
283
+ c.mov (dst, src1);
284
+ c.not_ (dst);
285
+ c.and_ (dst, *src2);
286
+ } else {
287
+ const auto scratch = AllocateScratchRegister ({&dst, &src1, src2.get ()}, dst.getBit ());
270
288
271
- c.mov (scratch, src1);
272
- c.not_ (scratch);
273
- c.and_ (scratch, *src2);
274
- c.mov (dst, scratch);
289
+ SaveRegisters (c, {scratch});
275
290
276
- RestoreRegisters (c, {scratch});
291
+ c.mov (scratch, src1);
292
+ c.not_ (scratch);
293
+ c.and_ (scratch, *src2);
294
+ c.mov (dst, scratch);
295
+
296
+ RestoreRegisters (c, {scratch});
297
+ }
277
298
}
278
299
279
300
static void GenerateBEXTR (const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
0 commit comments