diff --git a/src/capstone2llvmir/x86/x86.cpp b/src/capstone2llvmir/x86/x86.cpp index bd8eda5a1..1a6e5ae65 100644 --- a/src/capstone2llvmir/x86/x86.cpp +++ b/src/capstone2llvmir/x86/x86.cpp @@ -4,8 +4,6 @@ * @copyright (c) 2017 Avast Software, licensed under the MIT license */ -#include - #include "capstone2llvmir/x86/x86_impl.h" namespace retdec { @@ -2618,6 +2616,51 @@ void Capstone2LlvmIrTranslatorX86_impl::translateMul(cs_insn* i, cs_x86* xi, llv storeRegister(X86_REG_CF, f, irb); } +/** + * X86_INS_MULX + */ +void Capstone2LlvmIrTranslatorX86_impl::translateMulx(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb) +{ + EXPECT_IS_TERNARY(i, xi, irb); + + llvm::IntegerType* halfT = nullptr; + llvm::IntegerType* mulT = nullptr; + uint32_t otherOp = X86_REG_INVALID; + switch (xi->operands[0].size) { + case 4: + { + halfT = irb.getInt32Ty(); + mulT = irb.getInt64Ty(); + otherOp = X86_REG_EDX; + break; + } + case 8: + { + halfT = irb.getInt64Ty(); + mulT = irb.getInt128Ty(); + otherOp = X86_REG_RDX; + break; + } + default: + { + throw GenericError("Unhandled op size in translateMulx()."); + } + } + op0 = loadOp(xi->operands[2], irb, halfT); + op1 = loadRegister(otherOp, irb, halfT); + + op0 = irb.CreateZExt(op0, mulT); + op1 = irb.CreateZExt(op1, mulT); + + auto* mul = irb.CreateMul(op0, op1); + auto* l = irb.CreateTrunc(mul, halfT); + auto* h = irb.CreateTrunc(irb.CreateLShr(mul, halfT->getBitWidth()), halfT); + + // First operand is high destination register, second operand is low + storeRegister(xi->operands[1].reg, l, irb); + storeRegister(xi->operands[0].reg, h, irb); +} + /** * X86_INS_NEG */ diff --git a/src/capstone2llvmir/x86/x86_impl.h b/src/capstone2llvmir/x86/x86_impl.h index 866b0ad73..42ec19e94 100644 --- a/src/capstone2llvmir/x86/x86_impl.h +++ b/src/capstone2llvmir/x86/x86_impl.h @@ -318,6 +318,7 @@ class Capstone2LlvmIrTranslatorX86_impl : void translateMov(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateMoveString(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateMul(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); + void translateMulx(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateNeg(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateNop(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); void translateNot(cs_insn* i, cs_x86* xi, llvm::IRBuilder<>& irb); diff --git a/src/capstone2llvmir/x86/x86_init.cpp b/src/capstone2llvmir/x86/x86_init.cpp index ba85942ab..6b549d5e6 100644 --- a/src/capstone2llvmir/x86/x86_init.cpp +++ b/src/capstone2llvmir/x86/x86_init.cpp @@ -1106,7 +1106,7 @@ Capstone2LlvmIrTranslatorX86_impl::_i2fm = {X86_INS_MULPS, nullptr}, {X86_INS_MULSD, nullptr}, {X86_INS_MULSS, nullptr}, - {X86_INS_MULX, nullptr}, + {X86_INS_MULX, &Capstone2LlvmIrTranslatorX86_impl::translateMulx}, {X86_INS_FMUL, &Capstone2LlvmIrTranslatorX86_impl::translateFmul}, {X86_INS_FIMUL, &Capstone2LlvmIrTranslatorX86_impl::translateFmul}, {X86_INS_FMULP, &Capstone2LlvmIrTranslatorX86_impl::translateFmul},