diff --git a/src/capstone2llvmir/x86/x86.cpp b/src/capstone2llvmir/x86/x86.cpp index bd8eda5a1..9ac7e867d 100644 --- a/src/capstone2llvmir/x86/x86.cpp +++ b/src/capstone2llvmir/x86/x86.cpp @@ -1766,6 +1766,26 @@ void Capstone2LlvmIrTranslatorX86_impl::translateAnd(cs_insn* i, cs_x86* xi, llv } } +/** + * X86_INS_ANDN + */ +void Capstone2LlvmIrTranslatorX86_impl::translateAndN(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb) +{ + EXPECT_IS_TERNARY(i, xi, irb); + + std::tie(op0, op1, op2) = loadOpTernary(xi, irb); + + auto* andOp = irb.CreateAnd(irb.CreateNot(op1), op2); + storeRegister(X86_REG_AF, irb.getFalse(), irb); // undef + storeRegister(X86_REG_PF, irb.getFalse(), irb); // undef + storeRegister(X86_REG_OF, irb.getFalse(), irb); // cleared + storeRegister(X86_REG_CF, irb.getFalse(), irb); // cleared + storeRegister(X86_REG_ZF, generateZeroFlag(andOp, irb), irb); + storeRegister(X86_REG_ZF, generateSignFlag(andOp, irb), irb); + + storeOp(xi->operands[0], andOp, irb); +} + /** * X86_INS_BSF, X86_INS_BSR */ @@ -3329,6 +3349,35 @@ void Capstone2LlvmIrTranslatorX86_impl::translateShrd(cs_insn* i, cs_x86* xi, ll storeRegister(X86_REG_OF, ofV, bodyIrb); } +/** + * X86_INS_SHLX, X86_INS_SHRX, X86_INS_SARX + */ +void Capstone2LlvmIrTranslatorX86_impl::translateShiftX(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb) +{ + EXPECT_IS_TERNARY(i, xi, irb); + + std::tie(op0, op1, op2) = loadOpTernary(xi, irb); + + auto OpKind = [&] { + switch (i->id) + { + case X86_INS_SHR: return llvm::Instruction::BinaryOps::LShr; + case X86_INS_SAR: return llvm::Instruction::BinaryOps::AShr; + case X86_INS_SHL: return llvm::Instruction::BinaryOps::Shl; + default: assert(false); + } + }(); + + unsigned bitwidth = op0->getType()->getIntegerBitWidth(); + auto* is_overflow = irb.CreateICmpUGE(op2, llvm::ConstantInt::get(op1->getType(), bitwidth)); + auto* shift = irb.CreateBinOp(OpKind, op1, op2); + auto* res = irb.CreateSelect(is_overflow, llvm::ConstantInt::get(op2->getType(), 0), shift); + + // X variants of shifts have no flag impact + + storeOp(xi->operands[0], res, irb); +} + /** * X86_INS_RCR */ @@ -5394,5 +5443,28 @@ void Capstone2LlvmIrTranslatorX86_impl::translateRdtscp(cs_insn* i, cs_x86* xi, storeRegister(X86_REG_ECX, irb.CreateExtractValue(c, {2}), irb); } +void Capstone2LlvmIrTranslatorX86_impl::translateTzcntOrLzcnt(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb) +{ + EXPECT_IS_BINARY(i, xi, irb); + + std::tie(op0, op1) = loadOpBinary(xi, irb); + + storeRegister(X86_REG_CF, generateZeroFlag(op1, irb), irb); + + op0 = irb.CreateIntrinsic( + i->id == X86_INS_LZCNT ? llvm::Intrinsic::ctlz : llvm::Intrinsic::cttz, + {op1->getType()}, + {op1, irb.getFalse()}); + + storeRegister(X86_REG_OF, irb.getFalse(), irb); // undef + storeRegister(X86_REG_SF, irb.getFalse(), irb); // undef + storeRegister(X86_REG_PF, irb.getFalse(), irb); // undef + storeRegister(X86_REG_AF, irb.getFalse(), irb); // undef + + storeRegister(X86_REG_ZF, generateZeroFlag(op0, irb), irb); + + storeOp(xi->operands[0], op0, irb); +} + } // namespace capstone2llvmir } // namespace retdec diff --git a/src/capstone2llvmir/x86/x86_impl.h b/src/capstone2llvmir/x86/x86_impl.h index 866b0ad73..1a4c06712 100644 --- a/src/capstone2llvmir/x86/x86_impl.h +++ b/src/capstone2llvmir/x86/x86_impl.h @@ -233,6 +233,7 @@ class Capstone2LlvmIrTranslatorX86_impl : void translateAdc(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateAdd(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateAnd(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); + void translateAndN(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateBsf(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateBswap(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateBt(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); @@ -345,6 +346,7 @@ class Capstone2LlvmIrTranslatorX86_impl : void translateShiftRight(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateShld(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateShrd(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); + void translateShiftX(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateStc(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateStd(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateStoreString(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); @@ -352,6 +354,7 @@ class Capstone2LlvmIrTranslatorX86_impl : void translateXchg(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateXlatb(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateXor(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); + void translateTzcntOrLzcnt(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); }; } // namespace capstone2llvmir diff --git a/src/capstone2llvmir/x86/x86_init.cpp b/src/capstone2llvmir/x86/x86_init.cpp index ba85942ab..718b6aa06 100644 --- a/src/capstone2llvmir/x86/x86_init.cpp +++ b/src/capstone2llvmir/x86/x86_init.cpp @@ -637,7 +637,7 @@ Capstone2LlvmIrTranslatorX86_impl::_i2fm = {X86_INS_AESIMC, nullptr}, {X86_INS_AESKEYGENASSIST, nullptr}, {X86_INS_AND, &Capstone2LlvmIrTranslatorX86_impl::translateAnd}, - {X86_INS_ANDN, nullptr}, + {X86_INS_ANDN, &Capstone2LlvmIrTranslatorX86_impl::translateAndN}, {X86_INS_ANDNPD, nullptr}, {X86_INS_ANDNPS, nullptr}, {X86_INS_ANDPD, nullptr}, @@ -966,7 +966,7 @@ Capstone2LlvmIrTranslatorX86_impl::_i2fm = {X86_INS_LSS, &Capstone2LlvmIrTranslatorX86_impl::translateLoadFarPtr}, {X86_INS_LTR, nullptr}, {X86_INS_XADD, &Capstone2LlvmIrTranslatorX86_impl::translateAdd}, - {X86_INS_LZCNT, nullptr}, + {X86_INS_LZCNT, &Capstone2LlvmIrTranslatorX86_impl::translateTzcntOrLzcnt}, {X86_INS_MASKMOVDQU, nullptr}, {X86_INS_MAXPD, nullptr}, {X86_INS_MAXPS, nullptr}, @@ -1237,7 +1237,7 @@ Capstone2LlvmIrTranslatorX86_impl::_i2fm = {X86_INS_SAL, &Capstone2LlvmIrTranslatorX86_impl::translateShiftLeft}, {X86_INS_SALC, &Capstone2LlvmIrTranslatorX86_impl::translateSalc}, {X86_INS_SAR, &Capstone2LlvmIrTranslatorX86_impl::translateShiftRight}, - {X86_INS_SARX, nullptr}, + {X86_INS_SARX, &Capstone2LlvmIrTranslatorX86_impl::translateShiftX}, {X86_INS_SBB, &Capstone2LlvmIrTranslatorX86_impl::translateSbb}, {X86_INS_SCASB, &Capstone2LlvmIrTranslatorX86_impl::translateScanString}, {X86_INS_SCASD, &Capstone2LlvmIrTranslatorX86_impl::translateScanString}, @@ -1270,10 +1270,10 @@ Capstone2LlvmIrTranslatorX86_impl::_i2fm = {X86_INS_SHA256RNDS2, nullptr}, {X86_INS_SHL, &Capstone2LlvmIrTranslatorX86_impl::translateShiftLeft}, {X86_INS_SHLD, &Capstone2LlvmIrTranslatorX86_impl::translateShld}, - {X86_INS_SHLX, nullptr}, + {X86_INS_SHLX, &Capstone2LlvmIrTranslatorX86_impl::translateShiftX}, {X86_INS_SHR, &Capstone2LlvmIrTranslatorX86_impl::translateShiftRight}, {X86_INS_SHRD, &Capstone2LlvmIrTranslatorX86_impl::translateShrd}, - {X86_INS_SHRX, nullptr}, + {X86_INS_SHRX, &Capstone2LlvmIrTranslatorX86_impl::translateShiftX}, {X86_INS_SHUFPD, nullptr}, {X86_INS_SHUFPS, nullptr}, {X86_INS_SIDT, nullptr}, @@ -1320,7 +1320,7 @@ Capstone2LlvmIrTranslatorX86_impl::_i2fm = {X86_INS_TEST, &Capstone2LlvmIrTranslatorX86_impl::translateAnd}, {X86_INS_UD2, &Capstone2LlvmIrTranslatorX86_impl::translateNop}, {X86_INS_FTST, &Capstone2LlvmIrTranslatorX86_impl::translateFucomPop}, - {X86_INS_TZCNT, nullptr}, + {X86_INS_TZCNT, &Capstone2LlvmIrTranslatorX86_impl::translateTzcntOrLzcnt}, {X86_INS_TZMSK, nullptr}, {X86_INS_FUCOMPI, &Capstone2LlvmIrTranslatorX86_impl::translateFucomPop}, {X86_INS_FUCOMI, &Capstone2LlvmIrTranslatorX86_impl::translateFucomPop},