summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/arch_x86.cpp21
-rw-r--r--arch/x86/il.cpp80
-rw-r--r--arch/x86/il.h2
3 files changed, 35 insertions, 68 deletions
diff --git a/arch/x86/arch_x86.cpp b/arch/x86/arch_x86.cpp
index bdd360bc..2d7d2309 100644
--- a/arch/x86/arch_x86.cpp
+++ b/arch/x86/arch_x86.cpp
@@ -2153,6 +2153,17 @@ size_t X86CommonArchitecture::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, s
}
}
+ // POPCNT sets ZF from the result and clears every other flag. ZF falls through to the default
+ // (result == 0) handling below.
+ if (flagWriteType == IL_FLAGWRITE_POPCNT && flag != IL_FLAG_Z)
+ return il.Const(0, 0);
+
+ // LZCNT/TZCNT set CF when the source is zero and ZF from the result. The remaining flags are
+ // undefined and are not written. ZF falls through to the default (result == 0) handling below.
+ if (flagWriteType == IL_FLAGWRITE_LZTZCNT && flag == IL_FLAG_C && operandCount >= 1)
+ return il.AddExpr(LLIL_CMP_E, size, 0,
+ il.GetExprForRegisterOrConstant(operands[0], size), il.AddExpr(LLIL_CONST, size, 0, 0));
+
if (flagWriteType == IL_FLAGWRITE_X87RND && flag == IL_FLAG_C1)
return il.Unimplemented();
@@ -2318,6 +2329,10 @@ string X86CommonArchitecture::GetFlagWriteTypeName(uint32_t flags)
return "x87rnd";
case IL_FLAGWRITE_VCOMI:
return "vcomi";
+ case IL_FLAGWRITE_POPCNT:
+ return "popcnt";
+ case IL_FLAGWRITE_LZTZCNT:
+ return "lztzcnt";
default:
return "";
}
@@ -2344,7 +2359,7 @@ vector<uint32_t> X86CommonArchitecture::GetAllFlagWriteTypes()
{
return vector<uint32_t> {IL_FLAGWRITE_ALL, IL_FLAGWRITE_NOCARRY, IL_FLAGWRITE_CO,
IL_FLAGWRITE_X87COM, IL_FLAGWRITE_X87COMI, IL_FLAGWRITE_X87C1Z, IL_FLAGWRITE_X87RND,
- IL_FLAGWRITE_VCOMI};
+ IL_FLAGWRITE_VCOMI, IL_FLAGWRITE_POPCNT, IL_FLAGWRITE_LZTZCNT};
}
BNFlagRole X86CommonArchitecture::GetFlagRole(uint32_t flag, uint32_t semClass)
@@ -2558,6 +2573,10 @@ vector<uint32_t> X86CommonArchitecture::GetFlagsWrittenByFlagWriteType(uint32_t
return vector<uint32_t>{ IL_FLAG_C1 };
case IL_FLAGWRITE_VCOMI:
return vector<uint32_t>{ IL_FLAG_C, IL_FLAG_P, IL_FLAG_A, IL_FLAG_Z, IL_FLAG_S, IL_FLAG_O };
+ case IL_FLAGWRITE_POPCNT:
+ return vector<uint32_t>{ IL_FLAG_C, IL_FLAG_P, IL_FLAG_A, IL_FLAG_Z, IL_FLAG_S, IL_FLAG_O };
+ case IL_FLAGWRITE_LZTZCNT:
+ return vector<uint32_t>{ IL_FLAG_C, IL_FLAG_Z };
default:
return vector<uint32_t>();
}
diff --git a/arch/x86/il.cpp b/arch/x86/il.cpp
index 692ee04e..fbc8a6b5 100644
--- a/arch/x86/il.cpp
+++ b/arch/x86/il.cpp
@@ -4870,81 +4870,27 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
il.AddInstruction(il.SetRegister(2, REG_X87_TOP, il.Add(2, il.Register(2, REG_X87_TOP), il.Const(2, 1))));
break;
- case XED_ICLASS_TZCNT:
- {
- if (opOneLen == 8)
- il.AddInstruction(
- il.Intrinsic(
- vector<RegisterOrFlag> { RegisterOrFlag::Register(regOne) },
- INTRINSIC_XED_IFORM_TZCNT_GPR64_GPRMEM64,
- vector<ExprId> { ReadILOperand(il, xedd, addr, 1, 1) } ));
- else if (opOneLen == 4)
- il.AddInstruction(
- il.Intrinsic(
- vector<RegisterOrFlag> { RegisterOrFlag::Register(regOne) },
- INTRINSIC_XED_IFORM_TZCNT_GPR32_GPRMEM32,
- vector<ExprId> { ReadILOperand(il, xedd, addr, 1, 1) } ));
- else
- il.AddInstruction(
- il.Intrinsic(
- vector<RegisterOrFlag> { RegisterOrFlag::Register(regOne) },
- INTRINSIC_XED_IFORM_TZCNT_GPR16_GPRMEM16,
- vector<ExprId> { ReadILOperand(il, xedd, addr, 1, 1) } ));
+ case XED_ICLASS_BSWAP:
+ // BSWAP reverses the bytes of its single register operand in place. x86 leaves the flags
+ // unaffected, matching the native operation.
+ il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0,
+ il.ByteSwap(opOneLen, ReadILOperand(il, xedd, addr, 0, 0))));
+ break;
+ case XED_ICLASS_TZCNT:
+ il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0,
+ il.CountTrailingZeros(opOneLen, ReadILOperand(il, xedd, addr, 1, 1), IL_FLAGWRITE_LZTZCNT)));
break;
- }
case XED_ICLASS_LZCNT:
- {
- if (opOneLen == 8)
- il.AddInstruction(
- il.Intrinsic(
- vector<RegisterOrFlag> { RegisterOrFlag::Register(regOne) },
- INTRINSIC_XED_IFORM_LZCNT_GPR64_GPRMEM64,
- vector<ExprId> { ReadILOperand(il, xedd, addr, 1, 1) }
- )
- );
- else if (opOneLen == 4)
- il.AddInstruction(
- il.Intrinsic(
- vector<RegisterOrFlag> { RegisterOrFlag::Register(regOne) },
- INTRINSIC_XED_IFORM_LZCNT_GPR32_GPRMEM32,
- vector<ExprId> { ReadILOperand(il, xedd, addr, 1, 1) } ));
- else
- il.AddInstruction(
- il.Intrinsic(
- vector<RegisterOrFlag> { RegisterOrFlag::Register(regOne) },
- INTRINSIC_XED_IFORM_LZCNT_GPR16_GPRMEM16,
- vector<ExprId> { ReadILOperand(il, xedd, addr, 1, 1) } ));
-
+ il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0,
+ il.CountLeadingZeros(opOneLen, ReadILOperand(il, xedd, addr, 1, 1), IL_FLAGWRITE_LZTZCNT)));
break;
- }
case XED_ICLASS_POPCNT:
- {
- if (opOneLen == 8)
- il.AddInstruction(
- il.Intrinsic(
- vector<RegisterOrFlag> { RegisterOrFlag::Register(regOne) },
- INTRINSIC_XED_IFORM_POPCNT_GPR64_GPRMEM64,
- vector<ExprId> { ReadILOperand(il, xedd, addr, 1, 1) }
- )
- );
- else if (opOneLen == 4)
- il.AddInstruction(
- il.Intrinsic(
- vector<RegisterOrFlag> { RegisterOrFlag::Register(regOne) },
- INTRINSIC_XED_IFORM_POPCNT_GPR32_GPRMEM32,
- vector<ExprId> { ReadILOperand(il, xedd, addr, 1, 1) } ));
- else
- il.AddInstruction(
- il.Intrinsic(
- vector<RegisterOrFlag> { RegisterOrFlag::Register(regOne) },
- INTRINSIC_XED_IFORM_POPCNT_GPR16_GPRMEM16,
- vector<ExprId> { ReadILOperand(il, xedd, addr, 1, 1) } ));
-
+ il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0,
+ il.PopulationCount(opOneLen, ReadILOperand(il, xedd, addr, 1, 1), IL_FLAGWRITE_POPCNT)));
break;
- }
default:
LiftAsIntrinsic();
diff --git a/arch/x86/il.h b/arch/x86/il.h
index 1bef0606..3bdd0799 100644
--- a/arch/x86/il.h
+++ b/arch/x86/il.h
@@ -50,6 +50,8 @@ struct DISASSEMBLY_OPTIONS
#define IL_FLAGWRITE_X87C1Z 6
#define IL_FLAGWRITE_X87RND 7
#define IL_FLAGWRITE_VCOMI 8
+#define IL_FLAGWRITE_POPCNT 9
+#define IL_FLAGWRITE_LZTZCNT 10
#define IL_FLAG_CLASS_INT 0 // Default
#define IL_FLAG_CLASS_X87COM 1