in X86/X86RaisedValueTracker.cpp [508:1054]
bool X86RaisedValueTracker::testAndSetEflagSSAValue(unsigned int FlagBit,
const MachineInstr &MI,
Value *TestResultVal) {
assert((FlagBit >= X86RegisterUtils::EFLAGS::CF) &&
(FlagBit < X86RegisterUtils::EFLAGS::UNDEFINED) &&
"Unknown EFLAGS bit specified");
int MBBNo = MI.getParent()->getNumber();
MachineFunction &MF = x86MIRaiser->getMF();
LLVMContext &Ctx = MF.getFunction().getContext();
BasicBlock *RaisedBB =
x86MIRaiser->getRaisedBasicBlock(MF.getBlockNumbered(MBBNo));
unsigned int ResTyNumBits =
TestResultVal->getType()->getPrimitiveSizeInBits();
switch (FlagBit) {
case X86RegisterUtils::EFLAGS::ZF: {
Value *ZeroVal = ConstantInt::get(Ctx, APInt(ResTyNumBits, 0));
// Set ZF - test if TestVal is 0
Instruction *ZFTest =
new ICmpInst(CmpInst::Predicate::ICMP_EQ, TestResultVal, ZeroVal,
X86RegisterUtils::getEflagName(FlagBit));
RaisedBB->getInstList().push_back(ZFTest);
physRegDefsInMBB[FlagBit][MBBNo].second = ZFTest;
} break;
case X86RegisterUtils::EFLAGS::SF: {
Value *ZeroVal = ConstantInt::get(Ctx, APInt(ResTyNumBits, 0));
// Set SF - test if TestVal is signed
auto ShiftVal = ConstantInt::get(Ctx, APInt(ResTyNumBits, 1));
auto HighBitSetVal =
ConstantInt::get(Ctx, APInt(ResTyNumBits, ResTyNumBits - 1));
// Compute 1 << (ResTyNumBits - 1)
auto ShiftLeft = ConstantExpr::getShl(ShiftVal, HighBitSetVal, true, true);
// Create the instruction
// and SubInst, ShiftLeft
Instruction *AndInst =
BinaryOperator::CreateAnd(ShiftLeft, TestResultVal, "highbit");
RaisedBB->getInstList().push_back(AndInst);
// Compare result of logical and operation to find if bit 31 is set SF
// accordingly
Instruction *SFTest =
new ICmpInst(CmpInst::Predicate::ICMP_NE, AndInst, ZeroVal,
X86RegisterUtils::getEflagName(FlagBit));
RaisedBB->getInstList().push_back(SFTest);
physRegDefsInMBB[FlagBit][MBBNo].second = SFTest;
} break;
case X86RegisterUtils::EFLAGS::OF: {
auto IntrinsicOF = Intrinsic::not_intrinsic;
Value *TestArg[2];
Module *M = x86MIRaiser->getModuleRaiser()->getModule();
// If TestVal is a cast value, it is most likely cast to match the
// source of the compare instruction. Get to the value prior to casting.
CastInst *castInst = dyn_cast<CastInst>(TestResultVal);
while (castInst) {
TestResultVal = castInst->getOperand(0);
castInst = dyn_cast<CastInst>(TestResultVal);
}
Instruction *TestInst = dyn_cast<Instruction>(TestResultVal);
assert((TestInst != nullptr) && "Expect test producing instruction while "
"testing and setting of EFLAGS");
if ((x86MIRaiser->instrNameStartsWith(MI, "SUB")) ||
(x86MIRaiser->instrNameStartsWith(MI, "CMP")) ||
(x86MIRaiser->instrNameStartsWith(MI, "SBB"))) {
IntrinsicOF = Intrinsic::ssub_with_overflow;
TestArg[0] = TestInst->getOperand(0);
TestArg[1] = TestInst->getOperand(1);
assert((TestArg[0]->getType() == TestArg[1]->getType()) &&
"Differing types of test values unexpected");
// Construct a call to get overflow value upon comparison of test arg
// values
Function *ValueOF =
Intrinsic::getDeclaration(M, IntrinsicOF, TestArg[0]->getType());
CallInst *GetOF = CallInst::Create(
cast<FunctionType>(
cast<PointerType>(ValueOF->getType())->getElementType()),
ValueOF, ArrayRef<Value *>(TestArg));
RaisedBB->getInstList().push_back(GetOF);
// Extract OF and set it
physRegDefsInMBB[FlagBit][MBBNo].second =
ExtractValueInst::Create(GetOF, 1, "OF", RaisedBB);
} else if (x86MIRaiser->instrNameStartsWith(MI, "ADD")) {
IntrinsicOF = Intrinsic::sadd_with_overflow;
TestArg[0] = TestInst->getOperand(0);
TestArg[1] = TestInst->getOperand(1);
assert((TestArg[0]->getType() == TestArg[1]->getType()) &&
"Differing types of test values unexpected");
// Construct a call to get overflow value upon comparison of test arg
// values
Function *ValueOF =
Intrinsic::getDeclaration(M, IntrinsicOF, TestArg[0]->getType());
CallInst *GetOF = CallInst::Create(
cast<FunctionType>(
cast<PointerType>(ValueOF->getType())->getElementType()),
ValueOF, ArrayRef<Value *>(TestArg));
RaisedBB->getInstList().push_back(GetOF);
// Extract OF and set it
physRegDefsInMBB[FlagBit][MBBNo].second =
ExtractValueInst::Create(GetOF, 1, "OF", RaisedBB);
} else if (x86MIRaiser->instrNameStartsWith(MI, "ROL")) {
// OF flag is defined only for 1-bit rotates i.e., ROLr*1).
// It is undefined in all other cases. OF flag is set to the exclusive OR
// of CF after rotate and the most-significant bit of the result.
if ((MI.getNumExplicitOperands() == 2) &&
(MI.findTiedOperandIdx(1) == 0)) {
// CF flag receives a copy of the bit that was shifted from one end to
// the other. Find the least-significant bit, which is the bit shifted
// from the most-significant location.
// NOTE: CF computation is repeated here, just to be sure.
// Construct constant 1 of TestResultVal type
Value *OneValue = ConstantInt::get(TestResultVal->getType(), 1);
// Get LSB of TestResultVal using the instruction and TestResultVal, 1
Instruction *ResultLSB = BinaryOperator::CreateAnd(
TestResultVal, OneValue, "lsb-result", RaisedBB);
// Set ResultCF to 1 if LSB is 1, else to 0
Instruction *ResultCF = new ICmpInst(CmpInst::Predicate::ICMP_EQ,
ResultLSB, OneValue, "CF-RES");
// Insert compare instruction
RaisedBB->getInstList().push_back(ResultCF);
// Get most-significant bit of the result (i.e., TestResultVal)
auto ResultNumBits = TestResultVal->getType()->getPrimitiveSizeInBits();
// Construct a constant with only the most significant bit set
Value *LeftShift =
ConstantInt::get(TestResultVal->getType(), (ResultNumBits - 1));
// Get (1 << LeftShift)
Value *MSBSetConst = BinaryOperator::CreateShl(OneValue, LeftShift,
"MSB-CONST", RaisedBB);
// Get (TestResultVal & MSBSetConst) to get the most significant bit of
// TestResultVal
Instruction *ResultMSB = BinaryOperator::CreateAnd(
TestResultVal, MSBSetConst, "MSB-RES", RaisedBB);
// Check if MSB is non-zero
Value *ZeroValue = ConstantInt::get(ResultMSB->getType(), 0);
// Generate (ResultMSB != 0) to indicate MSB
Instruction *MSBIsSet = new ICmpInst(CmpInst::Predicate::ICMP_NE,
ResultMSB, ZeroValue, "MSB-SET");
RaisedBB->getInstList().push_back(dyn_cast<Instruction>(MSBIsSet));
// Generate XOR ResultCF, MSBIsSet to compute OF
Instruction *ResultOF =
BinaryOperator::CreateXor(ResultCF, MSBIsSet, "OF", RaisedBB);
physRegDefsInMBB[FlagBit][MBBNo].second = ResultOF;
}
} else if (x86MIRaiser->instrNameStartsWith(MI, "ROR")) {
// OF flag is defined only for 1-bit rotates i.e., RORr*1).
// It is undefined in all other cases. OF flag is set to the exclusive OR
// of the two most-significant bits of the result.
if ((MI.getNumExplicitOperands() == 2) &&
(MI.findTiedOperandIdx(1) == 0)) {
// Find most-significant bit of result.
Value *OneValue = ConstantInt::get(TestResultVal->getType(), 1);
// Get most-significant bit of the result (i.e., TestResultVal)
auto ResultNumBits = TestResultVal->getType()->getPrimitiveSizeInBits();
// Construct a constant with only the most significant bit set
Value *LeftShift =
ConstantInt::get(TestResultVal->getType(), (ResultNumBits - 1));
// Get (1 << LeftShift)
Value *BitSetConst = BinaryOperator::CreateShl(OneValue, LeftShift,
"MSB-CONST", RaisedBB);
// Get (TestResultVal & MSBSetConst) to get the most significant bit of
// TestResultVal
Instruction *BitSetResult = BinaryOperator::CreateAnd(
TestResultVal, BitSetConst, "MSB-RES", RaisedBB);
// Check if MSB is non-zero
Value *ZeroValue = ConstantInt::get(BitSetResult->getType(), 0);
// Generate (BitSetResult != 0) to indicate MSB
Instruction *MSBIsSet = new ICmpInst(
CmpInst::Predicate::ICMP_NE, BitSetResult, ZeroValue, "MSB-SET");
RaisedBB->getInstList().push_back(dyn_cast<Instruction>(MSBIsSet));
// Construct a constant with only the pre-MSB location set
LeftShift =
ConstantInt::get(TestResultVal->getType(), (ResultNumBits - 2));
// Get (1 << LeftShift)
BitSetConst = BinaryOperator::CreateShl(OneValue, LeftShift,
"Pre-MSB-CONST", RaisedBB);
// Get (TestResultVal & BitSetConst) to get the pre-most significant bit
// of TestResultVal
BitSetResult = BinaryOperator::CreateAnd(TestResultVal, BitSetConst,
"Pre-MSB-RES", RaisedBB);
// Check if pre-MSB is non-zero
// Generate (BitSetResult != 0) to indicate pre-MSB
Instruction *PreMSBIsSet =
new ICmpInst(CmpInst::Predicate::ICMP_NE, BitSetResult, ZeroValue,
"Pre-MSB-SET");
RaisedBB->getInstList().push_back(dyn_cast<Instruction>(PreMSBIsSet));
// Generate XOR MSBIsSet, PreMSBIsSet to compute OF
Instruction *ResultOF =
BinaryOperator::CreateXor(MSBIsSet, PreMSBIsSet, "OF", RaisedBB);
physRegDefsInMBB[FlagBit][MBBNo].second = ResultOF;
}
} else if (x86MIRaiser->instrNameStartsWith(MI, "TEST")) {
// Set CF to 0 and make type to i1
physRegDefsInMBB[FlagBit][MBBNo].second =
ConstantInt::get(Type::getInt1Ty(Ctx), 0);
} else {
LLVM_DEBUG(MI.dump());
assert(false && "*** EFLAGS update abstraction not handled yet");
}
} break;
case X86RegisterUtils::EFLAGS::PF: {
// PF is set if least-significant byte of the result contains an even number
// of 1 bits; else the flag is cleared.
Module *M = x86MIRaiser->getModuleRaiser()->getModule();
Value *SrcVal = TestResultVal;
if (SrcVal->getType()->isIntegerTy() &&
SrcVal->getType()->getIntegerBitWidth() > 8) {
// Get least-significant byte
Instruction *LSB = BinaryOperator::CreateAnd(
SrcVal, ConstantInt::get(SrcVal->getType(), 0xff));
RaisedBB->getInstList().push_back(LSB);
SrcVal = LSB;
}
Function *IntrinsicFunc =
Intrinsic::getDeclaration(M, Intrinsic::ctpop, SrcVal->getType());
Value *IntrinsicCallArgs[] = {SrcVal};
Instruction *ParityValue =
CallInst::Create(IntrinsicFunc, ArrayRef<Value *>(IntrinsicCallArgs));
// Add the intrinsic call instruction
RaisedBB->getInstList().push_back(ParityValue);
Instruction *ParityEvenBit = BinaryOperator::CreateAnd(
ParityValue, ConstantInt::get(ParityValue->getType(), 1));
RaisedBB->getInstList().push_back(ParityEvenBit);
// Test if ParityEvenBit is Zero
Value *ZeroValue =
ConstantInt::get(ParityEvenBit->getType(), 0, false /* isSigned */);
Instruction *PFTest = new ICmpInst(CmpInst::Predicate::ICMP_EQ,
ParityEvenBit, ZeroValue, "PF");
RaisedBB->getInstList().push_back(PFTest);
physRegDefsInMBB[FlagBit][MBBNo].second = PFTest;
} break;
case X86RegisterUtils::EFLAGS::CF: {
Module *M = x86MIRaiser->getModuleRaiser()->getModule();
Value *NewCF = nullptr;
// If TestVal is a cast value, it is most likely cast to match the
// source of the compare instruction. Get to the value prior to casting.
CastInst *castInst = dyn_cast<CastInst>(TestResultVal);
while (castInst) {
TestResultVal = castInst->getOperand(0);
castInst = dyn_cast<CastInst>(TestResultVal);
}
if (x86MIRaiser->instrNameStartsWith(MI, "NEG")) {
// Set CF to 0 if source operand is 0 else to 1
Instruction *TestInst = dyn_cast<Instruction>(TestResultVal);
assert((TestInst != nullptr) && "Expect test producing instruction while "
"testing and setting of EFLAGS");
// TestInst should be a sub 0, val instruction
assert((TestInst->getOpcode() == Instruction::Sub) &&
"Expect NEG to be raised as SUB");
// Get the arguments of the sub instruction that computes the neg
Value *TestArg[2];
TestArg[0] = TestInst->getOperand(0);
TestArg[1] = TestInst->getOperand(1);
assert((TestArg[0]->getType() == TestArg[1]->getType()) &&
"Differing types of test values not expected");
// A zero value of appropriate type
Value *ZeroVal =
ConstantFP::getZeroValueForNegation(TestArg[1]->getType());
assert(((TestArg[0] == ZeroVal)) &&
"Expected zero value of sub instruction while updating CF for NEG "
"instruction");
// Set ZF - test if TestVal is not equal to 0 - to get the CF bit value.
Instruction *CmpInst =
new ICmpInst(CmpInst::Predicate::ICMP_NE, TestArg[0], ZeroVal,
X86RegisterUtils::getEflagName(FlagBit));
RaisedBB->getInstList().push_back(CmpInst);
NewCF = CmpInst;
} else if ((x86MIRaiser->instrNameStartsWith(MI, "SUB")) ||
(x86MIRaiser->instrNameStartsWith(MI, "CMP")) ||
(x86MIRaiser->instrNameStartsWith(MI, "SBB"))) {
Value *TestArg[2];
Instruction *TestInst = dyn_cast<Instruction>(TestResultVal);
assert((TestInst != nullptr) && "Expect test producing instruction while "
"testing and setting of EFLAGS");
TestArg[0] = TestInst->getOperand(0);
TestArg[1] = TestInst->getOperand(1);
assert((TestArg[0]->getType() == TestArg[1]->getType()) &&
"Differing types of test values not expected");
// Construct a call to get carry flag value upon comparison of test arg
// values
Function *ValueCF = Intrinsic::getDeclaration(
M, Intrinsic::usub_with_overflow, TestArg[0]->getType());
CallInst *GetCF = CallInst::Create(
cast<FunctionType>(
cast<PointerType>(ValueCF->getType())->getElementType()),
ValueCF, ArrayRef<Value *>(TestArg));
RaisedBB->getInstList().push_back(GetCF);
// Extract flag-bit
NewCF = ExtractValueInst::Create(GetCF, 1, "CF", RaisedBB);
} else if (x86MIRaiser->instrNameStartsWith(MI, "ADD")) {
Value *TestArg[2];
Instruction *TestInst = dyn_cast<Instruction>(TestResultVal);
assert((TestInst != nullptr) && "Expect test producing instruction while "
"testing and setting of EFLAGS");
TestArg[0] = TestInst->getOperand(0);
TestArg[1] = TestInst->getOperand(1);
assert((TestArg[0]->getType() == TestArg[1]->getType()) &&
"Differing types of test values not expected");
// Construct a call to get carry flag value upon comparison of test arg
// values
Function *ValueCF = Intrinsic::getDeclaration(
M, Intrinsic::uadd_with_overflow, TestArg[0]->getType());
CallInst *GetCF = CallInst::Create(
cast<FunctionType>(
cast<PointerType>(ValueCF->getType())->getElementType()),
ValueCF, ArrayRef<Value *>(TestArg));
RaisedBB->getInstList().push_back(GetCF);
// Extract flag-bit
NewCF = ExtractValueInst::Create(GetCF, 1, "CF", RaisedBB);
} else if (x86MIRaiser->instrNameStartsWith(MI, "SHRD")) {
// TestInst should have been a call to intrinsic llvm.fshr.*
CallInst *IntrinsicCall = dyn_cast<CallInst>(TestResultVal);
assert((IntrinsicCall != nullptr) &&
(IntrinsicCall->getFunctionType()->getNumParams() == 3) &&
"Expected call instruction with three arguments not found");
Value *DstArgVal = IntrinsicCall->getArgOperand(1);
Value *CountArgVal = IntrinsicCall->getArgOperand(2);
// If count is 1 or greater, CF is filled with the last bit shifted out
// of destination operand.
Value *ZeroVal = ConstantInt::get(
Ctx, APInt(CountArgVal->getType()->getPrimitiveSizeInBits(), 0));
Instruction *CountValTest =
new ICmpInst(CmpInst::Predicate::ICMP_SGT, CountArgVal, ZeroVal,
"shrd_cf_count_cmp");
RaisedBB->getInstList().push_back(CountValTest);
// The last bit shifted out of destination operand is the
// least-significant N'th bit where N == CountVal. So get that value as
// follows:
// if (DestVal & (1 << N))
// CF = 1
// else
// CF = 0
Instruction *ShlInst =
BinaryOperator::CreateShl(ConstantInt::get(CountArgVal->getType(), 1),
CountArgVal, "shrd_cf_count_shift");
RaisedBB->getInstList().push_back(ShlInst);
Instruction *AndInst =
BinaryOperator::CreateAnd(DstArgVal, ShlInst, "shrd_cf_count_and");
RaisedBB->getInstList().push_back(AndInst);
// Is it Zero
Instruction *NewCFInst =
new ICmpInst(CmpInst::Predicate::ICMP_SGT, AndInst, ZeroVal,
"shrd_cf_count_shft_out");
RaisedBB->getInstList().push_back(NewCFInst);
Value *OldCF = physRegDefsInMBB[FlagBit][MBBNo].second;
if (OldCF == nullptr) {
// if CF is undefined, assume CF = 0
LLVMContext &Ctx(MF.getFunction().getContext());
OldCF = ConstantInt::get(Type::getInt1Ty(Ctx), 0);
}
// Select the value of CF based on Count value being > 0
Instruction *SelectCF =
SelectInst::Create(CountValTest, NewCFInst, OldCF, "shrd_cf_update");
RaisedBB->getInstList().push_back(SelectCF);
NewCF = SelectCF;
} else if (x86MIRaiser->instrNameStartsWith(MI, "SHL") ||
x86MIRaiser->instrNameStartsWith(MI, "SHR") ||
x86MIRaiser->instrNameStartsWith(MI, "SAR")) {
Value *DstArgVal = nullptr;
Value *CountArgVal = nullptr;
// If this is a funnel shift
if (x86MIRaiser->instrNameStartsWith(MI, "SHLD")) {
// TestInst should have been a call to intrinsic llvm.fshl.*
CallInst *IntrinsicCall = dyn_cast<CallInst>(TestResultVal);
assert((IntrinsicCall != nullptr) &&
(IntrinsicCall->getFunctionType()->getNumParams() == 3) &&
"Expected call instruction with three arguments not found");
DstArgVal = IntrinsicCall->getArgOperand(0);
CountArgVal = IntrinsicCall->getArgOperand(2);
} else {
// TestInst should have been shl/shr/sar instruction
BinaryOperator *BinOp = dyn_cast<BinaryOperator>(TestResultVal);
assert((BinOp != nullptr) && (BinOp->getNumOperands() == 2) &&
"Expected a shl binary operator with 2 operands");
DstArgVal = BinOp->getOperand(0);
CountArgVal = BinOp->getOperand(1);
}
// If count is 1 or greater, CF is filled with the last bit shifted out
// of destination operand.
Value *ZeroVal = ConstantInt::get(
Ctx, APInt(CountArgVal->getType()->getPrimitiveSizeInBits(), 0));
Instruction *CountValTest =
new ICmpInst(CmpInst::Predicate::ICMP_SGT, CountArgVal, ZeroVal,
"shrd_cf_count_cmp");
RaisedBB->getInstList().push_back(CountValTest);
// The last bit shifted out of destination operand is the
// least-significant N'th bit where TypeSize =
// DstArgVal->getType()->getPrimitiveSizeInBits()) and
// N == (TypeSize - CountVal).
// So get that value as follows:
// if (DestVal & (1 << N))
// CF = 1
// else
// CF = 0
Value *TypeSizeVal =
ConstantInt::get(CountArgVal->getType(),
DstArgVal->getType()->getPrimitiveSizeInBits());
Instruction *ShiftAmt =
BinaryOperator::CreateSub(TypeSizeVal, CountArgVal);
RaisedBB->getInstList().push_back(ShiftAmt);
// Shift 1 by ShiftAmt
Instruction *ShlInst =
BinaryOperator::CreateShl(ConstantInt::get(CountArgVal->getType(), 1),
ShiftAmt, "shld_cf_count_shift");
RaisedBB->getInstList().push_back(ShlInst);
Instruction *AndInst =
BinaryOperator::CreateAnd(DstArgVal, ShlInst, "shld_cf_count_and");
RaisedBB->getInstList().push_back(AndInst);
// Is it Zero
Instruction *NewCFInst =
new ICmpInst(CmpInst::Predicate::ICMP_SGT, AndInst, ZeroVal,
"shld_cf_count_shft_out");
RaisedBB->getInstList().push_back(NewCFInst);
Value *OldCF = physRegDefsInMBB[FlagBit][MBBNo].second;
if (OldCF == nullptr) {
// if CF is undefined, assume CF = 0
LLVMContext &Ctx(MF.getFunction().getContext());
OldCF = ConstantInt::get(Type::getInt1Ty(Ctx), 0);
}
// Select the value of CF based on Count value being > 0
Instruction *SelectCF =
SelectInst::Create(CountValTest, NewCFInst, OldCF, "shld_cf_update");
RaisedBB->getInstList().push_back(SelectCF);
NewCF = SelectCF;
} else if (x86MIRaiser->instrNameStartsWith(MI, "ROL")) {
// CF flag receives a copy of the bit that was shifted from one end to
// the other. Find the least-significant bit, which is the bit shifted
// from the most-significant location.
// NOTE: CF computation is repeated here, just to be sure.
// Construct constant 1 of TestResultVal type
Value *OneValue = ConstantInt::get(TestResultVal->getType(), 1);
// Get LSB of TestResultVal using the instruction and TestResultVal, 1
Instruction *ResultLSB = BinaryOperator::CreateAnd(
TestResultVal, OneValue, "lsb-result", RaisedBB);
// Set ResultCF to 1 if LSB is 1, else to 0
Instruction *ResultCF = new ICmpInst(CmpInst::Predicate::ICMP_EQ,
ResultLSB, OneValue, "CF-RES");
// Insert compare instruction
RaisedBB->getInstList().push_back(ResultCF);
NewCF = ResultCF;
} else if (x86MIRaiser->instrNameStartsWith(MI, "ROR")) {
// CF flag receives a copy of the bit that was shifted from one end to
// the other. Find the most-significant bit, which is the bit shifted
// from the least-significant location.
// Find most-significant bit of result.
Value *OneValue = ConstantInt::get(TestResultVal->getType(), 1);
// Get most-significant bit of the result (i.e., TestResultVal)
auto ResultNumBits = TestResultVal->getType()->getPrimitiveSizeInBits();
// Construct a constant with only the most significant bit set
Value *LeftShift =
ConstantInt::get(TestResultVal->getType(), (ResultNumBits - 1));
// Get (1 << LeftShift)
Value *BitSetConst =
BinaryOperator::CreateShl(OneValue, LeftShift, "MSB-CONST", RaisedBB);
// Get (TestResultVal & MSBSetConst) to get the most significant bit of
// TestResultVal
Instruction *BitSetResult = BinaryOperator::CreateAnd(
TestResultVal, BitSetConst, "MSB-RES", RaisedBB);
// Check if MSB is non-zero
Value *ZeroValue = ConstantInt::get(BitSetResult->getType(), 0);
// Generate (BitSetResult != 0) to indicate MSB
Instruction *MSBIsSet = new ICmpInst(CmpInst::Predicate::ICMP_NE,
BitSetResult, ZeroValue, "MSB-SET");
RaisedBB->getInstList().push_back(dyn_cast<Instruction>(MSBIsSet));
NewCF = MSBIsSet;
} else if (x86MIRaiser->instrNameStartsWith(MI, "IMUL")) {
// TestInst should have been mul instruction
BinaryOperator *TestInst = dyn_cast<BinaryOperator>(TestResultVal);
assert((TestInst != nullptr) && (TestInst->getNumOperands() == 2) &&
"Expected a mul binary operator with 2 operands");
Value *TestArg[2];
TestArg[0] = TestInst->getOperand(0);
TestArg[1] = TestInst->getOperand(1);
assert((TestArg[0]->getType() == TestArg[1]->getType()) &&
"Differing types of test values unexpected");
// Construct a call to get overflow value upon comparison of test arg
// values.
Function *ValueOF = Intrinsic::getDeclaration(
M, Intrinsic::smul_with_overflow, TestArg[0]->getType());
CallInst *GetOF = CallInst::Create(
cast<FunctionType>(
cast<PointerType>(ValueOF->getType())->getElementType()),
ValueOF, ArrayRef<Value *>(TestArg));
RaisedBB->getInstList().push_back(GetOF);
// Extract OF and set both OF and CF to the same value
auto NewOF = ExtractValueInst::Create(GetOF, 1, "OF", RaisedBB);
physRegDefsInMBB[EFLAGS::OF][MBBNo].second = NewOF;
NewCF = NewOF;
// Set OF to the same value of CF
physRegDefsInMBB[EFLAGS::OF][MBBNo].second = NewCF;
} else if (x86MIRaiser->instrNameStartsWith(MI, "TEST")) {
// Set CF to 0 and make type to i1
NewCF = ConstantInt::get(Type::getInt1Ty(Ctx), 0);
} else {
LLVM_DEBUG(MI.dump());
assert(false &&
"*** Abstraction of CF for the instruction not handled yet");
}
// Update CF.
assert((NewCF != nullptr) && "Value to update CF not found");
physRegDefsInMBB[FlagBit][MBBNo].second = NewCF;
} break;
// TODO: Add code to test for other flags
default:
assert(false && "Unhandled EFLAGS bit specified");
}
// EFLAGS bit size is 1
physRegDefsInMBB[FlagBit][MBBNo].first = 1;
return true;
}