diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/x86/arch_x86.cpp | 21 | ||||
| -rw-r--r-- | arch/x86/il.cpp | 80 | ||||
| -rw-r--r-- | arch/x86/il.h | 2 |
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 |
