summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorAvery <30564701+nullableVoidPtr@users.noreply.github.com>2026-02-24 14:52:19 +0800
committerGitHub <noreply@github.com>2026-02-23 22:52:19 -0800
commit3eda43f185a0411538745a99e251122e6a9192e0 (patch)
treee31b035427a37981ae847aa58d7b84669e60a829 /arch
parent13fccf3aff2cd0de371ac75fd2840c75bf9033f2 (diff)
[x86] Intel APX support (#6423)
Co-authored-by: Mason Reed <mason@vector35.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/CMakeLists.txt2
-rw-r--r--arch/x86/arch_x86.cpp80
-rw-r--r--arch/x86/il.cpp1201
3 files changed, 1031 insertions, 252 deletions
diff --git a/arch/x86/CMakeLists.txt b/arch/x86/CMakeLists.txt
index 70dd24cb..e888c0fd 100644
--- a/arch/x86/CMakeLists.txt
+++ b/arch/x86/CMakeLists.txt
@@ -47,7 +47,7 @@ target_include_directories(arch_x86
PRIVATE ${PROJECT_BINARY_DIR}/obj/include-private)
add_compile_definitions(XED_DECODER XED_AMD_ENABLED XED_VIA_ENABLED XED_AVX XED_SUPPORTS_AVX512
- XED_MPX XED_CET XED_SUPPORTS_SHA XED_SUPPORTS_WBNOINVD)
+ XED_MPX XED_CET XED_SUPPORTS_SHA XED_SUPPORTS_WBNOINVD XED_APX)
target_link_libraries(arch_x86 binaryninjaapi)
diff --git a/arch/x86/arch_x86.cpp b/arch/x86/arch_x86.cpp
index c58d1c56..a79163da 100644
--- a/arch/x86/arch_x86.cpp
+++ b/arch/x86/arch_x86.cpp
@@ -1423,6 +1423,7 @@ void X86CommonArchitecture::GetOperandTextBNIntel(const xed_decoded_inst_t* cons
break;
}
case XED_OPERAND_PTR:
+ case XED_OPERAND_ABSBR:
{
stringstream sstream;
sstream << "0x" << hex;
@@ -3282,6 +3283,8 @@ public:
XED_REG_RAX, XED_REG_RCX, XED_REG_RDX, XED_REG_RBX, // 64+
XED_REG_R8, XED_REG_R9, XED_REG_R10, XED_REG_R11, XED_REG_R12, XED_REG_R13, XED_REG_R14, XED_REG_R15, // 64+
+ XED_REG_R16, XED_REG_R17, XED_REG_R18, XED_REG_R19, XED_REG_R20, XED_REG_R21, XED_REG_R22, XED_REG_R23, // APX
+ XED_REG_R24, XED_REG_R25, XED_REG_R26, XED_REG_R27, XED_REG_R28, XED_REG_R29, XED_REG_R30, XED_REG_R31, // APX
XED_REG_BNDCFGU, XED_REG_BNDSTATUS, // 64 briefly. MPX control registers
XED_REG_K0, XED_REG_K1, XED_REG_K2, XED_REG_K3, XED_REG_K4, XED_REG_K5, XED_REG_K6, XED_REG_K7, // 64+ AVX bit-masking registers (also not confident in size)
@@ -3310,6 +3313,8 @@ public:
XED_REG_AH, XED_REG_CH, XED_REG_DH, XED_REG_BH, XED_REG_AL, XED_REG_CL, XED_REG_DL, XED_REG_BL, // 16+
XED_REG_SPL, XED_REG_BPL, XED_REG_SIL, XED_REG_DIL, // 64+
XED_REG_R8B, XED_REG_R9B, XED_REG_R10B, XED_REG_R11B, XED_REG_R12B, XED_REG_R13B, XED_REG_R14B, XED_REG_R15B, // 64+
+ XED_REG_R16B, XED_REG_R17B, XED_REG_R18B, XED_REG_R19B, XED_REG_R20B, XED_REG_R21B, XED_REG_R22B, XED_REG_R23B, // APX
+ XED_REG_R24B, XED_REG_R25B, XED_REG_R26B, XED_REG_R27B, XED_REG_R28B, XED_REG_R29B, XED_REG_R30B, XED_REG_R31B, // APX
// 16-Bit
XED_REG_IP, // 16+
@@ -3323,6 +3328,8 @@ public:
XED_REG_AX, XED_REG_CX, XED_REG_DX, XED_REG_BX, // 16+
XED_REG_R8W, XED_REG_R9W, XED_REG_R10W, XED_REG_R11W, XED_REG_R12W, XED_REG_R13W, XED_REG_R14W, XED_REG_R15W, // 64+
+ XED_REG_R16W, XED_REG_R17W, XED_REG_R18W, XED_REG_R19W, XED_REG_R20W, XED_REG_R21W, XED_REG_R22W, XED_REG_R23W, // APX
+ XED_REG_R24W, XED_REG_R25W, XED_REG_R26W, XED_REG_R27W, XED_REG_R28W, XED_REG_R29W, XED_REG_R30W, XED_REG_R31W, // APX
// 32-Bit
XED_REG_EIP, // 32+
@@ -3331,6 +3338,8 @@ public:
XED_REG_EAX, XED_REG_ECX, XED_REG_EDX, XED_REG_EBX, // 32+
XED_REG_R8D, XED_REG_R9D, XED_REG_R10D, XED_REG_R11D, XED_REG_R12D, XED_REG_R13D, XED_REG_R14D, XED_REG_R15D, // 64+
+ XED_REG_R16D, XED_REG_R17D, XED_REG_R18D, XED_REG_R19D, XED_REG_R20D, XED_REG_R21D, XED_REG_R22D, XED_REG_R23D, // APX
+ XED_REG_R24D, XED_REG_R25D, XED_REG_R26D, XED_REG_R27D, XED_REG_R28D, XED_REG_R29D, XED_REG_R30D, XED_REG_R31D, // APX
// 48-Bit (All 32+)
XED_REG_GDTR, // Global Descriptor Table Register
@@ -3350,6 +3359,8 @@ public:
XED_REG_RAX, XED_REG_RCX, XED_REG_RDX, XED_REG_RBX, // 64+
XED_REG_R8, XED_REG_R9, XED_REG_R10, XED_REG_R11, XED_REG_R12, XED_REG_R13, XED_REG_R14, XED_REG_R15, // 64+
+ XED_REG_R16, XED_REG_R17, XED_REG_R18, XED_REG_R19, XED_REG_R20, XED_REG_R21, XED_REG_R22, XED_REG_R23, // APX
+ XED_REG_R24, XED_REG_R25, XED_REG_R26, XED_REG_R27, XED_REG_R28, XED_REG_R29, XED_REG_R30, XED_REG_R31, // APX
XED_REG_BNDCFGU, XED_REG_BNDSTATUS, // 64 briefly. MPX control registers
XED_REG_K0, XED_REG_K1, XED_REG_K2, XED_REG_K3, XED_REG_K4, XED_REG_K5, XED_REG_K6, XED_REG_K7, // 64+ AVX bit-masking registers (also not confident in size)
@@ -3405,6 +3416,23 @@ public:
case XED_REG_R14B: return RegisterInfo(XED_REG_R14, 0, 1);
case XED_REG_R15B: return RegisterInfo(XED_REG_R15, 0, 1);
+ case XED_REG_R16B: return RegisterInfo(XED_REG_R16, 0, 1);
+ case XED_REG_R17B: return RegisterInfo(XED_REG_R17, 0, 1);
+ case XED_REG_R18B: return RegisterInfo(XED_REG_R18, 0, 1);
+ case XED_REG_R19B: return RegisterInfo(XED_REG_R19, 0, 1);
+ case XED_REG_R20B: return RegisterInfo(XED_REG_R20, 0, 1);
+ case XED_REG_R21B: return RegisterInfo(XED_REG_R21, 0, 1);
+ case XED_REG_R22B: return RegisterInfo(XED_REG_R22, 0, 1);
+ case XED_REG_R23B: return RegisterInfo(XED_REG_R23, 0, 1);
+ case XED_REG_R24B: return RegisterInfo(XED_REG_R24, 0, 1);
+ case XED_REG_R25B: return RegisterInfo(XED_REG_R25, 0, 1);
+ case XED_REG_R26B: return RegisterInfo(XED_REG_R26, 0, 1);
+ case XED_REG_R27B: return RegisterInfo(XED_REG_R27, 0, 1);
+ case XED_REG_R28B: return RegisterInfo(XED_REG_R28, 0, 1);
+ case XED_REG_R29B: return RegisterInfo(XED_REG_R29, 0, 1);
+ case XED_REG_R30B: return RegisterInfo(XED_REG_R30, 0, 1);
+ case XED_REG_R31B: return RegisterInfo(XED_REG_R31, 0, 1);
+
// 16-Bit
case XED_REG_IP: return RegisterInfo(XED_REG_RIP, 0, 2);
@@ -3435,6 +3463,23 @@ public:
case XED_REG_R14W: return RegisterInfo(XED_REG_R14, 0, 2);
case XED_REG_R15W: return RegisterInfo(XED_REG_R15, 0, 2);
+ case XED_REG_R16W: return RegisterInfo(XED_REG_R16, 0, 2);
+ case XED_REG_R17W: return RegisterInfo(XED_REG_R17, 0, 2);
+ case XED_REG_R18W: return RegisterInfo(XED_REG_R18, 0, 2);
+ case XED_REG_R19W: return RegisterInfo(XED_REG_R19, 0, 2);
+ case XED_REG_R20W: return RegisterInfo(XED_REG_R20, 0, 2);
+ case XED_REG_R21W: return RegisterInfo(XED_REG_R21, 0, 2);
+ case XED_REG_R22W: return RegisterInfo(XED_REG_R22, 0, 2);
+ case XED_REG_R23W: return RegisterInfo(XED_REG_R23, 0, 2);
+ case XED_REG_R24W: return RegisterInfo(XED_REG_R24, 0, 2);
+ case XED_REG_R25W: return RegisterInfo(XED_REG_R25, 0, 2);
+ case XED_REG_R26W: return RegisterInfo(XED_REG_R26, 0, 2);
+ case XED_REG_R27W: return RegisterInfo(XED_REG_R27, 0, 2);
+ case XED_REG_R28W: return RegisterInfo(XED_REG_R28, 0, 2);
+ case XED_REG_R29W: return RegisterInfo(XED_REG_R29, 0, 2);
+ case XED_REG_R30W: return RegisterInfo(XED_REG_R30, 0, 2);
+ case XED_REG_R31W: return RegisterInfo(XED_REG_R31, 0, 2);
+
// 32-Bit
case XED_REG_EIP: return RegisterInfo(XED_REG_RIP, 0, 4);
@@ -3472,6 +3517,23 @@ public:
case XED_REG_R14D: return RegisterInfo(XED_REG_R14, 0, 4, true);
case XED_REG_R15D: return RegisterInfo(XED_REG_R15, 0, 4, true);
+ case XED_REG_R16D: return RegisterInfo(XED_REG_R16, 0, 4, true);
+ case XED_REG_R17D: return RegisterInfo(XED_REG_R17, 0, 4, true);
+ case XED_REG_R18D: return RegisterInfo(XED_REG_R18, 0, 4, true);
+ case XED_REG_R19D: return RegisterInfo(XED_REG_R19, 0, 4, true);
+ case XED_REG_R20D: return RegisterInfo(XED_REG_R20, 0, 4, true);
+ case XED_REG_R21D: return RegisterInfo(XED_REG_R21, 0, 4, true);
+ case XED_REG_R22D: return RegisterInfo(XED_REG_R22, 0, 4, true);
+ case XED_REG_R23D: return RegisterInfo(XED_REG_R23, 0, 4, true);
+ case XED_REG_R24D: return RegisterInfo(XED_REG_R24, 0, 4, true);
+ case XED_REG_R25D: return RegisterInfo(XED_REG_R25, 0, 4, true);
+ case XED_REG_R26D: return RegisterInfo(XED_REG_R26, 0, 4, true);
+ case XED_REG_R27D: return RegisterInfo(XED_REG_R27, 0, 4, true);
+ case XED_REG_R28D: return RegisterInfo(XED_REG_R28, 0, 4, true);
+ case XED_REG_R29D: return RegisterInfo(XED_REG_R29, 0, 4, true);
+ case XED_REG_R30D: return RegisterInfo(XED_REG_R30, 0, 4, true);
+ case XED_REG_R31D: return RegisterInfo(XED_REG_R31, 0, 4, true);
+
// 48-Bit
case XED_REG_GDTR: return RegisterInfo(XED_REG_GDTR, 0, 6);
case XED_REG_LDTR: return RegisterInfo(XED_REG_LDTR, 0, 6);
@@ -3519,6 +3581,24 @@ public:
case XED_REG_R14: return RegisterInfo(XED_REG_R14, 0, 8);
case XED_REG_R15: return RegisterInfo(XED_REG_R15, 0, 8);
+ case XED_REG_R16: return RegisterInfo(XED_REG_R16, 0, 8);
+ case XED_REG_R17: return RegisterInfo(XED_REG_R17, 0, 8);
+ case XED_REG_R18: return RegisterInfo(XED_REG_R18, 0, 8);
+ case XED_REG_R19: return RegisterInfo(XED_REG_R19, 0, 8);
+ case XED_REG_R20: return RegisterInfo(XED_REG_R20, 0, 8);
+ case XED_REG_R21: return RegisterInfo(XED_REG_R21, 0, 8);
+ case XED_REG_R22: return RegisterInfo(XED_REG_R22, 0, 8);
+ case XED_REG_R23: return RegisterInfo(XED_REG_R23, 0, 8);
+ case XED_REG_R24: return RegisterInfo(XED_REG_R24, 0, 8);
+ case XED_REG_R25: return RegisterInfo(XED_REG_R25, 0, 8);
+ case XED_REG_R26: return RegisterInfo(XED_REG_R26, 0, 8);
+ case XED_REG_R27: return RegisterInfo(XED_REG_R27, 0, 8);
+ case XED_REG_R28: return RegisterInfo(XED_REG_R28, 0, 8);
+ case XED_REG_R29: return RegisterInfo(XED_REG_R29, 0, 8);
+ case XED_REG_R30: return RegisterInfo(XED_REG_R30, 0, 8);
+ case XED_REG_R31: return RegisterInfo(XED_REG_R31, 0, 8);
+
+
case XED_REG_BNDCFGU: return RegisterInfo(XED_REG_BNDCFGU, 0, 8);
case XED_REG_BNDSTATUS: return RegisterInfo(XED_REG_BNDSTATUS, 0, 8);
diff --git a/arch/x86/il.cpp b/arch/x86/il.cpp
index ba36190b..2c1cbd83 100644
--- a/arch/x86/il.cpp
+++ b/arch/x86/il.cpp
@@ -198,28 +198,21 @@ static size_t ReadILOperand(LowLevelILFunction& il, const xed_decoded_inst_t* co
sizeToRead = xed_decoded_inst_operand_length_bits(xedd, (unsigned)operand_index) / 8;
const unsigned int immediateSize = xed_decoded_inst_get_operand_width(xedd) / 8;
const int64_t relbr = xed_decoded_inst_get_branch_displacement(xedd) + addr + xed_decoded_inst_get_length(xedd);
+ const int64_t absbr = xed_decoded_inst_get_branch_displacement(xedd);
const xed_operand_enum_t op_name = xed_operand_name(xed_inst_operand(xed_decoded_inst_inst(xedd), (unsigned)operand_index));
const auto reg1 = xed_decoded_inst_get_reg(xedd, op_name);
const size_t addrSize = xed_decoded_inst_get_machine_mode_bits(xedd) / 8;
- switch (op_name)
- {
// Register cases
- case XED_OPERAND_REG0:
- case XED_OPERAND_REG1:
- case XED_OPERAND_REG2:
- case XED_OPERAND_REG3:
- case XED_OPERAND_REG4:
- case XED_OPERAND_REG5:
- case XED_OPERAND_REG6:
- case XED_OPERAND_REG7:
- case XED_OPERAND_REG8:
- case XED_OPERAND_BASE0:
- case XED_OPERAND_BASE1:
+ if (xed_operand_is_register(op_name) || xed_operand_is_memory_addressing_register(op_name))
+ {
if ((reg1 == XED_REG_RIP) || (reg1 == XED_REG_EIP) || (reg1 == XED_REG_IP))
return il.Operand(instruction_index, il.ConstPointer(sizeToRead, addr));
return il.Operand(instruction_index, il.Register(sizeToRead, (uint32_t)reg1));
+ }
+ switch (op_name)
+ {
// Immediates:
case XED_OPERAND_IMM0:
if (xed_decoded_inst_get_immediate_is_signed(xedd))
@@ -235,6 +228,8 @@ static size_t ReadILOperand(LowLevelILFunction& il, const xed_decoded_inst_t* co
case XED_OPERAND_PTR:
case XED_OPERAND_RELBR:
return il.Operand(instruction_index, il.ConstPointer(addrSize, relbr));
+ case XED_OPERAND_ABSBR:
+ return il.Operand(instruction_index, il.ConstPointer(addrSize, absbr));
// Memory Acesses
case XED_OPERAND_AGEN:
@@ -256,25 +251,16 @@ static size_t ReadFloatILOperand(LowLevelILFunction& il, const xed_decoded_inst_
const unsigned int operandSize = xed_decoded_inst_operand_length_bits(xedd, (unsigned)operand_index) / 8;
const xed_operand_enum_t op_name = xed_operand_name(xed_inst_operand(xed_decoded_inst_inst(xedd), (unsigned)operand_index));
- switch (op_name)
- {
// Register cases
- case XED_OPERAND_REG0:
- case XED_OPERAND_REG1:
- case XED_OPERAND_REG2:
- case XED_OPERAND_REG3:
- case XED_OPERAND_REG4:
- case XED_OPERAND_REG5:
- case XED_OPERAND_REG6:
- case XED_OPERAND_REG7:
- case XED_OPERAND_REG8:
- case XED_OPERAND_BASE0:
- case XED_OPERAND_BASE1:
+ if (xed_operand_is_register(op_name) || xed_operand_is_memory_addressing_register(op_name))
return il.Operand(instruction_index, il.Register(operandSize, (uint32_t)xed_decoded_inst_get_reg(xedd, op_name)));
+ switch (op_name)
+ {
// Immediates
case XED_OPERAND_IMM0:
case XED_OPERAND_PTR:
+ case XED_OPERAND_ABSBR:
case XED_OPERAND_RELBR:
if (xed_decoded_inst_get_immediate_is_signed(xedd))
return il.Operand(instruction_index, il.FloatConvert(opLen, il.FloatConstRaw(operandSize, xed_decoded_inst_get_signed_immediate(xedd))));
@@ -312,22 +298,12 @@ static size_t WriteILOperand(LowLevelILFunction& il, const xed_decoded_inst_t* c
const xed_operand_enum_t op_name = xed_operand_name(xed_inst_operand(xed_decoded_inst_inst(xedd), operand_index));
- switch (op_name)
- {
// Register cases
- case XED_OPERAND_REG0:
- case XED_OPERAND_REG1:
- case XED_OPERAND_REG2:
- case XED_OPERAND_REG3:
- case XED_OPERAND_REG4:
- case XED_OPERAND_REG5:
- case XED_OPERAND_REG6:
- case XED_OPERAND_REG7:
- case XED_OPERAND_REG8:
- case XED_OPERAND_BASE0:
- case XED_OPERAND_BASE1:
+ if (xed_operand_is_register(op_name) || xed_operand_is_memory_addressing_register(op_name))
return il.Operand(instruction_index, il.SetRegister(sizeToWrite, xed_decoded_inst_get_reg(xedd, op_name), value));
+ switch (op_name)
+ {
// Memory Accesses
case XED_OPERAND_AGEN:
case XED_OPERAND_MEM0:
@@ -446,13 +422,38 @@ static void Repeat(
static void CMovFlagCond(const int64_t addr, const xed_decoded_inst_t* xedd, LowLevelILFunction& il, BNLowLevelILFlagCondition flag)
{
- // keep the true branch but let the false branch goto doneLabel directly
- LowLevelILLabel trueLabel, doneLabel;
+ bool isCondFault = false;
+ bool isNdd = xed_decoded_inst_get_attribute(xedd, XED_ATTRIBUTE_APX_NDD);
+
+ switch (xed_decoded_inst_get_iclass(xedd))
+ {
+ case XED_ICLASS_CFCMOVB:
+ case XED_ICLASS_CFCMOVBE:
+ case XED_ICLASS_CFCMOVL:
+ case XED_ICLASS_CFCMOVLE:
+ case XED_ICLASS_CFCMOVNB:
+ case XED_ICLASS_CFCMOVNBE:
+ case XED_ICLASS_CFCMOVNL:
+ case XED_ICLASS_CFCMOVNLE:
+ case XED_ICLASS_CFCMOVNO:
+ case XED_ICLASS_CFCMOVNP:
+ case XED_ICLASS_CFCMOVNS:
+ case XED_ICLASS_CFCMOVNZ:
+ case XED_ICLASS_CFCMOVO:
+ case XED_ICLASS_CFCMOVP:
+ case XED_ICLASS_CFCMOVS:
+ case XED_ICLASS_CFCMOVZ:
+ isCondFault = true;
+ default:
+ break;
+ }
+
+ LowLevelILLabel trueLabel, falseLabel, doneLabel;
il.AddInstruction(
il.If(
il.FlagCondition(flag),
- trueLabel, doneLabel));
+ trueLabel, falseLabel));
il.MarkLabel(trueLabel);
@@ -461,14 +462,68 @@ static void CMovFlagCond(const int64_t addr, const xed_decoded_inst_t* xedd, Low
ReadILOperand(il, xedd, addr, 1, 1)));
il.AddInstruction(il.Goto(doneLabel));
+
+ il.MarkLabel(falseLabel);
+
+ if (isNdd)
+ {
+ il.AddInstruction(
+ WriteILOperand(il, xedd, addr, 0, 0,
+ ReadILOperand(il, xedd, addr, 2, 2)));
+ }
+ else if (isCondFault)
+ {
+ const xed_operand_enum_t op_name = xed_operand_name(xed_inst_operand(xed_decoded_inst_inst(xedd), 0));
+
+ // Register cases
+ if (xed_operand_is_register(op_name))
+ {
+ size_t addrSize = xed_decoded_inst_get_machine_mode_bits(xedd) / 8;
+ il.AddInstruction(
+ WriteILOperand(il, xedd, addr, 0, 0,
+ il.Const(addrSize, 0)));
+ }
+ else
+ {
+ il.AddInstruction(
+ WriteILOperand(il, xedd, addr, 0, 0,
+ ReadILOperand(il, xedd, addr, 1, 1)));
+ }
+ }
+
il.MarkLabel(doneLabel);
}
static void CMovFlagGroup(const int64_t addr, const xed_decoded_inst_t* xedd, LowLevelILFunction& il, uint32_t flag)
{
- // keep the true branch but let the false branch goto doneLabel directly
- LowLevelILLabel trueLabel, doneLabel;
+ bool isCondFault = false;
+ bool isNdd = xed_decoded_inst_get_attribute(xedd, XED_ATTRIBUTE_APX_NDD);
+
+ switch (xed_decoded_inst_get_iclass(xedd))
+ {
+ case XED_ICLASS_CFCMOVB:
+ case XED_ICLASS_CFCMOVBE:
+ case XED_ICLASS_CFCMOVL:
+ case XED_ICLASS_CFCMOVLE:
+ case XED_ICLASS_CFCMOVNB:
+ case XED_ICLASS_CFCMOVNBE:
+ case XED_ICLASS_CFCMOVNL:
+ case XED_ICLASS_CFCMOVNLE:
+ case XED_ICLASS_CFCMOVNO:
+ case XED_ICLASS_CFCMOVNP:
+ case XED_ICLASS_CFCMOVNS:
+ case XED_ICLASS_CFCMOVNZ:
+ case XED_ICLASS_CFCMOVO:
+ case XED_ICLASS_CFCMOVP:
+ case XED_ICLASS_CFCMOVS:
+ case XED_ICLASS_CFCMOVZ:
+ isCondFault = true;
+ default:
+ break;
+ }
+
+ LowLevelILLabel trueLabel, falseLabel, doneLabel;
il.AddInstruction(
il.If(
@@ -484,10 +539,122 @@ static void CMovFlagGroup(const int64_t addr, const xed_decoded_inst_t* xedd, Lo
ReadILOperand(il, xedd, addr, 1, 1)));
il.AddInstruction(il.Goto(doneLabel));
+
+ il.MarkLabel(falseLabel);
+
+ if (isNdd)
+ {
+ il.AddInstruction(
+ WriteILOperand(il, xedd, addr, 0, 0,
+ ReadILOperand(il, xedd, addr, 2, 2)));
+ }
+ else if (isCondFault)
+ {
+ const xed_operand_enum_t op_name = xed_operand_name(xed_inst_operand(xed_decoded_inst_inst(xedd), 0));
+
+ if (xed_operand_is_register(op_name) || xed_operand_is_memory_addressing_register(op_name))
+ {
+ size_t addrSize = xed_decoded_inst_get_machine_mode_bits(xedd) / 8;
+ il.AddInstruction(
+ WriteILOperand(il, xedd, addr, 0, 0,
+ il.Const(addrSize, 0)));
+ }
+ else
+ {
+ il.AddInstruction(
+ WriteILOperand(il, xedd, addr, 0, 0,
+ ReadILOperand(il, xedd, addr, 1, 1)));
+ }
+ }
+
+ il.MarkLabel(doneLabel);
+}
+
+static void AssignEvexDfv(const xed_decoded_inst_t* xedd, LowLevelILFunction& il)
+{
+ xed_flag_dfv_t defaultFlagValues;
+ if (!xed_flag_dfv_get_default_flags_values(
+ xed_decoded_inst_get_dfv_reg(xedd), &defaultFlagValues))
+ {
+ // TODO: better error handling
+ il.AddInstruction(il.Undefined());
+ return;
+ }
+
+ il.AddInstruction(
+ il.SetFlag(IL_FLAG_O,
+ il.Const(1, defaultFlagValues.s.of)));
+ il.AddInstruction(
+ il.SetFlag(IL_FLAG_S,
+ il.Const(1, defaultFlagValues.s.sf)));
+ il.AddInstruction(
+ il.SetFlag(IL_FLAG_Z,
+ il.Const(1, defaultFlagValues.s.zf)));
+ il.AddInstruction(
+ il.SetFlag(IL_FLAG_C,
+ il.Const(1, defaultFlagValues.s.cf)));
+ il.AddInstruction(
+ il.SetFlag(IL_FLAG_P,
+ il.Const(1, defaultFlagValues.s.cf)));
+ il.AddInstruction(
+ il.SetFlag(IL_FLAG_A,
+ il.Const(1, 0)));
+}
+
+
+static void ConditionalCmp(const int64_t addr, const xed_decoded_inst_t* xedd, LowLevelILFunction& il, uint32_t size, ExprId cond)
+{
+ LowLevelILLabel trueLabel, falseLabel, doneLabel;
+
+ il.AddInstruction(
+ il.If(
+ cond,
+ trueLabel, falseLabel
+ )
+ );
+
+ il.MarkLabel(trueLabel);
+
+ il.AddInstruction(
+ il.Sub(size,
+ ReadILOperand(il, xedd, addr, 0, 0),
+ ReadILOperand(il, xedd, addr, 1, 1),
+ IL_FLAGWRITE_ALL));
+ il.AddInstruction(il.Goto(doneLabel));
+
+ il.MarkLabel(falseLabel);
+ AssignEvexDfv(xedd, il);
+
il.MarkLabel(doneLabel);
}
+static void ConditionalTest(const int64_t addr, const xed_decoded_inst_t* xedd, LowLevelILFunction& il, uint32_t size, ExprId cond)
+{
+ LowLevelILLabel trueLabel, falseLabel, doneLabel;
+
+ il.AddInstruction(
+ il.If(
+ cond,
+ trueLabel, falseLabel
+ )
+ );
+
+ il.MarkLabel(trueLabel);
+
+ il.AddInstruction(
+ il.And(size,
+ ReadILOperand(il, xedd, addr, 0, 0),
+ ReadILOperand(il, xedd, addr, 1, 1),
+ IL_FLAGWRITE_ALL));
+ il.AddInstruction(il.Goto(doneLabel));
+
+ il.MarkLabel(falseLabel);
+ AssignEvexDfv(xedd, il);
+
+ il.MarkLabel(doneLabel);
+}
+
bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLevelILFunction& il, const xed_decoded_inst_t* const xedd)
{
LowLevelILLabel trueLabel, falseLabel, doneLabel, dirFlagSet, dirFlagClear, dirFlagDone, startLabel;
@@ -525,6 +692,11 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
const uint64_t immediateOne = xed_decoded_inst_get_unsigned_immediate(xedd);
const int64_t branchDestination = xed_decoded_inst_get_branch_displacement(xedd) + addr + instLen;
+ // Handle the NDD APX isa extension, this will require some classes to be lifted with an alternate operand location.
+ const bool newDataDestination = xed_decoded_inst_get_attribute(xedd, XED_ATTRIBUTE_APX_NDD);
+ const bool zeroUpper = xed_decoded_inst_is_apx_zu(xedd);
+ const bool noFlags = xed_decoded_inst_get_attribute(xedd, XED_ATTRIBUTE_APX_NF);
+
auto LiftAsIntrinsic = [& il, xi, xedd, addr, xedd_iForm] () mutable {
typedef struct
@@ -544,25 +716,13 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
xed_operand_enum_t op_name = xed_operand_name(op);
if (xed_operand_written(op))
{
- switch(op_name)
- {
- case XED_OPERAND_REG0:
- case XED_OPERAND_REG1:
- case XED_OPERAND_REG2:
- case XED_OPERAND_REG3:
- case XED_OPERAND_REG4:
- case XED_OPERAND_REG5:
- case XED_OPERAND_REG6:
- case XED_OPERAND_REG7:
- case XED_OPERAND_REG8:
- case XED_OPERAND_BASE0:
- case XED_OPERAND_BASE1:
+ if (xed_operand_is_register(op_name) || xed_operand_is_memory_addressing_register(op_name))
{
xed_reg_enum_t r = xed_decoded_inst_get_reg(xedd, op_name);
outputs.push_back(RegisterOrFlag::Register(r));
- break;
}
- default:
+ else
+ {
// The intrinsic system can only accept registers or flags as outputs,
// since it might be strange to write to an arbitrary ExprId.
// In order to handle intrinsics that write to memory, we create a temp IL register and
@@ -577,24 +737,11 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
memoryOperandWrites.push_back({i, operandWidth});
outputs.push_back(RegisterOrFlag::Register(LLIL_TEMP(numTempRegUsed)));
numTempRegUsed++;
- break;
}
}
if (xed_operand_read(op))
{
- switch(op_name)
- {
- case XED_OPERAND_REG0:
- case XED_OPERAND_REG1:
- case XED_OPERAND_REG2:
- case XED_OPERAND_REG3:
- case XED_OPERAND_REG4:
- case XED_OPERAND_REG5:
- case XED_OPERAND_REG6:
- case XED_OPERAND_REG7:
- case XED_OPERAND_REG8:
- case XED_OPERAND_BASE0:
- case XED_OPERAND_BASE1:
+ if (xed_operand_is_register(op_name) || xed_operand_is_memory_addressing_register(op_name))
{
// XED includes some things that are not actual registers in
// xed_reg_enum_t. We'll just omit those special cases here.
@@ -612,9 +759,6 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
break;
}
}
- default:
- break;
- }
parameters.push_back(ReadILOperand(il, xedd, addr, i, i));
}
@@ -635,51 +779,132 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
{
case XED_ICLASS_ADC_LOCK: // TODO: Add Lock construct
case XED_ICLASS_ADC:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.AddCarry(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL)));
+ il.AddCarry(opSize, left, right,
+ il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL)));
break;
+ }
case XED_ICLASS_ADCX:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.AddCarry(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- il.Flag(IL_FLAG_C), IL_FLAG_C)));
+ il.AddCarry(opSize, left, right,
+ il.Flag(IL_FLAG_C), IL_FLAG_C)));
break;
+ }
case XED_ICLASS_ADOX:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.AddCarry(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- il.Flag(IL_FLAG_O), IL_FLAG_O)));
+ il.AddCarry(opSize, left, right,
+ il.Flag(IL_FLAG_O), IL_FLAG_O)));
break;
+ }
case XED_ICLASS_ADD_LOCK: // TODO: Add Lock construct
case XED_ICLASS_ADD:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.Add(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- IL_FLAGWRITE_ALL)));
+ il.Add(opSize, left, right,
+ noFlags ? 0 : IL_FLAGWRITE_ALL)));
break;
+ }
case XED_ICLASS_AND_LOCK: // TODO: Add Lock construct
case XED_ICLASS_AND:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.And(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- IL_FLAGWRITE_ALL)));
+ il.And(opSize, left, right,
+ noFlags ? 0 : IL_FLAGWRITE_ALL)));
break;
+ }
+
case XED_ICLASS_PAND:
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
@@ -1267,78 +1492,95 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
break;
case XED_ICLASS_CMOVO:
+ case XED_ICLASS_CFCMOVO:
CMovFlagCond(addr, xedd, il, LLFC_O);
break;
case XED_ICLASS_CMOVNO:
+ case XED_ICLASS_CFCMOVNO:
CMovFlagCond(addr, xedd, il, LLFC_NO);
break;
case XED_ICLASS_CMOVB:
case XED_ICLASS_FCMOVB:
+ case XED_ICLASS_CFCMOVB:
CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_LT);
break;
case XED_ICLASS_CMOVNB:
case XED_ICLASS_FCMOVNB:
+ case XED_ICLASS_CFCMOVNB:
CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_GE);
break;
case XED_ICLASS_CMOVZ:
case XED_ICLASS_FCMOVE:
+ case XED_ICLASS_CFCMOVZ:
CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_E);
break;
case XED_ICLASS_CMOVNZ:
case XED_ICLASS_FCMOVNE:
+ case XED_ICLASS_CFCMOVNZ:
CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_NE);
break;
case XED_ICLASS_CMOVBE:
case XED_ICLASS_FCMOVBE:
+ case XED_ICLASS_CFCMOVBE:
CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_LE);
break;
case XED_ICLASS_CMOVNBE:
case XED_ICLASS_FCMOVNBE:
+ case XED_ICLASS_CFCMOVNBE:
CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_GT);
break;
case XED_ICLASS_CMOVS:
+ case XED_ICLASS_CFCMOVS:
CMovFlagCond(addr, xedd, il, LLFC_NEG);
break;
case XED_ICLASS_CMOVNS:
+ case XED_ICLASS_CFCMOVNS:
CMovFlagCond(addr, xedd, il, LLFC_POS);
break;
case XED_ICLASS_CMOVP:
case XED_ICLASS_FCMOVU:
+ case XED_ICLASS_CFCMOVP:
CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_PE);
break;
case XED_ICLASS_CMOVNP:
case XED_ICLASS_FCMOVNU:
+ case XED_ICLASS_CFCMOVNP:
CMovFlagGroup(addr, xedd, il, IL_FLAG_GROUP_PO);
break;
case XED_ICLASS_CMOVL:
+ case XED_ICLASS_CFCMOVL:
CMovFlagCond(addr, xedd, il, LLFC_SLT);
break;
case XED_ICLASS_CMOVNL:
+ case XED_ICLASS_CFCMOVNL:
CMovFlagCond(addr, xedd, il, LLFC_SGE);
break;
case XED_ICLASS_CMOVLE:
+ case XED_ICLASS_CFCMOVLE:
CMovFlagCond(addr, xedd, il, LLFC_SLE);
break;
case XED_ICLASS_CMOVNLE:
+ case XED_ICLASS_CFCMOVNLE:
CMovFlagCond(addr, xedd, il, LLFC_SGT);
break;
case XED_ICLASS_CMP:
+ case XED_ICLASS_CCMPT:
il.AddInstruction(
il.Sub(opOneLen,
ReadILOperand(il, xedd, addr, 0, 0),
@@ -1346,6 +1588,66 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
IL_FLAGWRITE_ALL));
break;
+ case XED_ICLASS_CCMPO:
+ ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_O));
+ break;
+
+ case XED_ICLASS_CCMPNO:
+ ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_NO));
+ break;
+
+ case XED_ICLASS_CCMPB:
+ ConditionalCmp(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_LT));
+ break;
+
+ case XED_ICLASS_CCMPNB:
+ ConditionalCmp(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_GE));
+ break;
+
+ case XED_ICLASS_CCMPZ:
+ ConditionalCmp(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_E));
+ break;
+
+ case XED_ICLASS_CCMPNZ:
+ ConditionalCmp(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_NE));
+ break;
+
+ case XED_ICLASS_CCMPBE:
+ ConditionalCmp(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_LE));
+ break;
+
+ case XED_ICLASS_CCMPNBE:
+ ConditionalCmp(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_GT));
+ break;
+
+ case XED_ICLASS_CCMPS:
+ ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_NEG));
+ break;
+
+ case XED_ICLASS_CCMPNS:
+ ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_POS));
+ break;
+
+ case XED_ICLASS_CCMPL:
+ ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SLT));
+ break;
+
+ case XED_ICLASS_CCMPNL:
+ ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SLT));
+ break;
+
+ case XED_ICLASS_CCMPLE:
+ ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SLE));
+ break;
+
+ case XED_ICLASS_CCMPNLE:
+ ConditionalCmp(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SGT));
+ break;
+
+ case XED_ICLASS_CCMPF:
+ AssignEvexDfv(xedd, il);
+ break;
+
case XED_ICLASS_REPE_CMPSQ:
case XED_ICLASS_REPNE_CMPSQ:
case XED_ICLASS_CMPSQ:
@@ -1470,17 +1772,34 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
case XED_ICLASS_DEC_LOCK: // TODO: Handle lock prefix
case XED_ICLASS_DEC:
+ {
+ ExprId src;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ src = ReadILOperand(il, xedd, addr, 0, 0);
+ }
+ else
+ {
+ // new data destination
+ src = ReadILOperand(il, xedd, addr, 1, 1);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.Sub(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
+ il.Sub(opSize,
+ src,
il.Const(opOneLen, 1),
- IL_FLAGWRITE_NOCARRY)
+ noFlags ? 0 : IL_FLAGWRITE_NOCARRY)
)
);
break;
+ }
case XED_ICLASS_DIV:
+ // TODO: flags set and handle noFlags?
il.AddInstruction(
il.SetRegister(opOneLen,
LLIL_TEMP(2),
@@ -1628,6 +1947,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
}
case XED_ICLASS_IDIV:
+ // TODO: flags set and handle noFlags?
switch (opOneLen)
{
case 1:
@@ -1765,7 +2085,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
il.MultDoublePrecSigned(1,
il.Register(1, XED_REG_AL),
ReadILOperand(il, xedd, addr, 0, 0),
- IL_FLAGWRITE_CO)));
+ noFlags ? 0 : IL_FLAGWRITE_CO)));
break;
case 2:
il.AddInstruction(
@@ -1775,7 +2095,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
il.MultDoublePrecSigned(2,
il.Register(2, XED_REG_AX),
ReadILOperand(il, xedd, addr, 0, 0),
- IL_FLAGWRITE_CO)));
+ noFlags ? 0 : IL_FLAGWRITE_CO)));
break;
case 4:
il.AddInstruction(
@@ -1785,7 +2105,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
il.MultDoublePrecSigned(4,
il.Register(4, XED_REG_EAX),
ReadILOperand(il, xedd, addr, 0, 0),
- IL_FLAGWRITE_CO)));
+ noFlags ? 0 : IL_FLAGWRITE_CO)));
break;
case 8:
il.AddInstruction(
@@ -1795,7 +2115,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
il.MultDoublePrecSigned(8,
il.Register(8, XED_REG_RAX),
ReadILOperand(il, xedd, addr, 0, 0),
- IL_FLAGWRITE_CO)));
+ noFlags ? 0 : IL_FLAGWRITE_CO)));
break;
default:
il.AddInstruction(il.Undefined());
@@ -1803,40 +2123,75 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
}
break;
- case XED_IFORM_IMUL_GPRv_GPRv:
- case XED_IFORM_IMUL_GPRv_MEMv:
+ case XED_IFORM_IMUL_GPRv_GPRv:
+ case XED_IFORM_IMUL_GPRv_MEMv:
+ {
+ ExprId left, right;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.Mult(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- IL_FLAGWRITE_CO)));
+ il.Mult(opOneLen, left, right,
+ IL_FLAGWRITE_CO)));
break;
+ }
- case XED_IFORM_IMUL_GPRv_GPRv_IMMb:
- case XED_IFORM_IMUL_GPRv_GPRv_IMMz:
- case XED_IFORM_IMUL_GPRv_MEMv_IMMb:
- case XED_IFORM_IMUL_GPRv_MEMv_IMMz:
+ case XED_IFORM_IMUL_GPRv_GPRv_IMMb:
+ case XED_IFORM_IMUL_GPRv_GPRv_IMMz:
+ case XED_IFORM_IMUL_GPRv_MEMv_IMMb:
+ case XED_IFORM_IMUL_GPRv_MEMv_IMMz:
default:
- il.AddInstruction(
- WriteILOperand(il, xedd, addr, 0, 0,
- il.Mult(opOneLen,
- ReadILOperand(il, xedd, addr, 1, 1),
- ReadILOperand(il, xedd, addr, 2, 2),
- IL_FLAGWRITE_CO)));
+ {
+ ExprId value = il.Mult(opOneLen,
+ ReadILOperand(il, xedd, addr, 1, 1),
+ ReadILOperand(il, xedd, addr, 2, 2),
+ IL_FLAGWRITE_CO);
+
+ if (zeroUpper && (opOneLen == 1 || opOneLen == 2))
+ value = il.ZeroExtend(8, value);
+
+ il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, value));
}
- break;
+ }
+ break;
case XED_ICLASS_INC_LOCK: // TODO: Handle lock prefix
case XED_ICLASS_INC:
+ {
+ ExprId src;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ src = ReadILOperand(il, xedd, addr, 0, 0);
+ }
+ else
+ {
+ // new data destination
+ src = ReadILOperand(il, xedd, addr, 1, 1);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.Add(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- il.Const(opOneLen, 1),
- IL_FLAGWRITE_NOCARRY)));
+ il.Add(opSize,
+ src,
+ il.Const(opSize, 1),
+ noFlags ? 0 : IL_FLAGWRITE_NOCARRY)));
break;
+ }
case XED_ICLASS_INT:
switch (immediateOne)
@@ -1858,6 +2213,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
break;
case XED_ICLASS_JMP:
+ case XED_ICLASS_JMPABS:
if (opOne_name == XED_OPERAND_RELBR)
{
BNLowLevelILLabel* label = il.GetLabelForAddress(arch, branchDestination);
@@ -2606,7 +2962,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
il.MultDoublePrecUnsigned(1,
il.Register(1, XED_REG_AL),
ReadILOperand(il, xedd, addr, 0, 0),
- IL_FLAGWRITE_CO)));
+ noFlags ? 0 : IL_FLAGWRITE_CO)));
break;
case 2:
il.AddInstruction(
@@ -2616,7 +2972,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
il.MultDoublePrecUnsigned(2,
il.Register(2, XED_REG_AX),
ReadILOperand(il, xedd, addr, 0, 0),
- IL_FLAGWRITE_CO)));
+ noFlags ? 0 : IL_FLAGWRITE_CO)));
break;
case 4:
il.AddInstruction(
@@ -2626,7 +2982,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
il.MultDoublePrecUnsigned(4,
il.Register(4, XED_REG_EAX),
ReadILOperand(il, xedd, addr, 0, 0),
- IL_FLAGWRITE_CO)));
+ noFlags ? 0 : IL_FLAGWRITE_CO)));
break;
case 8:
il.AddInstruction(
@@ -2636,7 +2992,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
il.MultDoublePrecUnsigned(8,
il.Register(8, XED_REG_RAX),
ReadILOperand(il, xedd, addr, 0, 0),
- IL_FLAGWRITE_CO)));
+ noFlags ? 0 : IL_FLAGWRITE_CO)));
break;
default:
il.AddInstruction(il.Undefined());
@@ -2646,12 +3002,27 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
case XED_ICLASS_NEG_LOCK: // TODO: Handle lock prefix
case XED_ICLASS_NEG:
+ {
+ ExprId src;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ src = ReadILOperand(il, xedd, addr, 0, 0);
+ }
+ else
+ {
+ // new data destination
+ src = ReadILOperand(il, xedd, addr, 1, 1);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.Neg(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- IL_FLAGWRITE_ALL)));
+ il.Neg(opSize, src,
+ noFlags ? 0 : IL_FLAGWRITE_ALL)));
break;
+ }
case XED_ICLASS_NOP:
case XED_ICLASS_NOP2:
@@ -2691,21 +3062,52 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
case XED_ICLASS_NOT_LOCK: // TODO: Handle lock prefix
case XED_ICLASS_NOT:
+ {
+ ExprId src;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ src = ReadILOperand(il, xedd, addr, 0, 0);
+ }
+ else
+ {
+ // new data destination
+ src = ReadILOperand(il, xedd, addr, 1, 1);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.Not(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0))));
+ il.Not(opSize, src)));
break;
+ }
case XED_ICLASS_OR_LOCK: // TODO: Handle lock prefix
case XED_ICLASS_OR:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.Or(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- IL_FLAGWRITE_ALL)));
+ il.Or(opSize, left, right,
+ noFlags ? 0 : IL_FLAGWRITE_ALL)));
break;
+ }
case XED_ICLASS_POR:
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
@@ -2728,7 +3130,18 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
0))); // VPOR doesn't modify flags
break;
+ case XED_ICLASS_POP2:
+ case XED_ICLASS_POP2P:
+ il.AddInstruction(
+ WriteILOperand(il, xedd, addr, 0, 0,
+ il.Pop(8)));
+ il.AddInstruction(
+ WriteILOperand(il, xedd, addr, 1, 1,
+ il.Pop(8)));
+ break;
+
case XED_ICLASS_POP:
+ case XED_ICLASS_POPP:
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
il.Pop(opOneLen)));
@@ -2859,7 +3272,14 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
);
break;
+ case XED_ICLASS_PUSH2:
+ case XED_ICLASS_PUSH2P:
+ il.AddInstruction(il.Push(8, ReadILOperand(il, xedd, addr, 0, 0)));
+ il.AddInstruction(il.Push(8, ReadILOperand(il, xedd, addr, 1, 1)));
+ break;
+
case XED_ICLASS_PUSH:
+ case XED_ICLASS_PUSHP:
{
// Whe the stack adjustment is different from the operand one size, zero-extend it. Note, a "push r16" in either
// x86 or x64 pushes the 2-byte register onto the stack, and there is no need to extend. See
@@ -2882,22 +3302,53 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
}
case XED_ICLASS_RCL:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.RotateLeftCarry(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL)));
+ il.RotateLeftCarry(opSize, left, right,
+ il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL)));
break;
-
+ }
case XED_ICLASS_RCR:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.RotateRightCarry(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL)));
+ il.RotateRightCarry(opSize, left, right,
+ il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL)));
break;
+ }
case XED_ICLASS_RET_NEAR:
if ((opOne_name != XED_OPERAND_IMM0) || (immediateOne == 0))
@@ -2917,23 +3368,53 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
break;
case XED_ICLASS_ROL:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.RotateLeft(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- IL_FLAGWRITE_ALL)));
+ il.RotateLeft(opSize, left, right,
+ noFlags ? 0 : IL_FLAGWRITE_ALL)));
break;
-
+ }
case XED_ICLASS_ROR:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.RotateRight(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- IL_FLAGWRITE_ALL)));
+ il.RotateRight(opSize, left, right,
+ noFlags ? 0 : IL_FLAGWRITE_ALL)));
break;
-
+ }
// there is no ROLX instruciton
case XED_ICLASS_RORX:
il.AddInstruction(
@@ -2945,13 +3426,29 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
break;
case XED_ICLASS_SAR:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.ArithShiftRight(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- IL_FLAGWRITE_ALL)));
+ il.ArithShiftRight(opSize, left, right,
+ noFlags ? 0 : IL_FLAGWRITE_ALL)));
break;
+ }
case XED_ICLASS_SARX:
il.AddInstruction(
@@ -2972,13 +3469,29 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
case XED_ICLASS_SBB_LOCK: // TODO: Handle lock prefix
case XED_ICLASS_SBB:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.SubBorrow(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL)));
+ il.SubBorrow(opSize, left, right,
+ il.Flag(IL_FLAG_C), IL_FLAGWRITE_ALL)));
break;
+ }
case XED_ICLASS_REPE_SCASB:
case XED_ICLASS_REPE_SCASD:
@@ -3041,88 +3554,148 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
}
case XED_ICLASS_SETO:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.Flag(IL_FLAG_O)));
- break;
-
case XED_ICLASS_SETNO:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.Not(0, il.Flag(IL_FLAG_O))));
- break;
-
case XED_ICLASS_SETB:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.Flag(IL_FLAG_C)));
- break;
-
case XED_ICLASS_SETNB:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagGroup(IL_FLAG_GROUP_GE)));
- break;
-
case XED_ICLASS_SETZ:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagGroup(IL_FLAG_GROUP_E)));
- break;
-
case XED_ICLASS_SETNZ:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagGroup(IL_FLAG_GROUP_NE)));
- break;
-
case XED_ICLASS_SETBE:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagGroup(IL_FLAG_GROUP_LE)));
- break;
-
case XED_ICLASS_SETNBE:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagGroup(IL_FLAG_GROUP_GT)));
- break;
-
case XED_ICLASS_SETS:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagCondition(LLFC_NEG)));
- break;
-
case XED_ICLASS_SETNS:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagCondition(LLFC_POS)));
- break;
-
case XED_ICLASS_SETP:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagGroup(IL_FLAG_GROUP_PE)));
- break;
-
case XED_ICLASS_SETNP:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagGroup(IL_FLAG_GROUP_PO)));
- break;
-
case XED_ICLASS_SETL:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagCondition(LLFC_SLT)));
- break;
-
case XED_ICLASS_SETNL:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagCondition(LLFC_SGE)));
- break;
-
case XED_ICLASS_SETLE:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagCondition(LLFC_SLE)));
- break;
-
case XED_ICLASS_SETNLE:
- il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, il.FlagCondition(LLFC_SGT)));
+ {
+ ExprId flag;
+ switch (xedd_iClass)
+ {
+ case XED_ICLASS_SETO:
+ flag = il.Flag(IL_FLAG_O);
+ break;
+ case XED_ICLASS_SETNO:
+ flag = il.Not(1, il.Flag(IL_FLAG_O));
+ break;
+ case XED_ICLASS_SETB:
+ flag = il.Flag(IL_FLAG_C);
+ break;
+
+ case XED_ICLASS_SETNB:
+ flag = il.FlagGroup(IL_FLAG_GROUP_GE);
+ break;
+
+ case XED_ICLASS_SETZ:
+ flag = il.FlagGroup(IL_FLAG_GROUP_E);
+ break;
+
+ case XED_ICLASS_SETNZ:
+ flag = il.FlagGroup(IL_FLAG_GROUP_NE);
+ break;
+
+ case XED_ICLASS_SETBE:
+ flag = il.FlagGroup(IL_FLAG_GROUP_LE);
+ break;
+
+ case XED_ICLASS_SETNBE:
+ flag = il.FlagGroup(IL_FLAG_GROUP_GT);
+ break;
+
+ case XED_ICLASS_SETS:
+ flag = il.FlagCondition(LLFC_NEG);
+ break;
+
+ case XED_ICLASS_SETNS:
+ flag = il.FlagCondition(LLFC_POS);
+ break;
+
+ case XED_ICLASS_SETP:
+ flag = il.FlagGroup(IL_FLAG_GROUP_PE);
+ break;
+
+ case XED_ICLASS_SETNP:
+ flag = il.FlagGroup(IL_FLAG_GROUP_PO);
+ break;
+
+ case XED_ICLASS_SETL:
+ flag = il.FlagCondition(LLFC_SLT);
+ break;
+
+ case XED_ICLASS_SETNL:
+ flag = il.FlagCondition(LLFC_SGE);
+ break;
+
+ case XED_ICLASS_SETLE:
+ flag = il.FlagCondition(LLFC_SLE);
+ break;
+
+ case XED_ICLASS_SETNLE:
+ flag = il.FlagCondition(LLFC_SGT);
+ break;
+ default:
+ break;
+ }
+
+ if (zeroUpper && xed_operand_is_register(opOne_name))
+ flag = il.ZeroExtend(8, flag);
+
+ il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, flag));
break;
+ }
case XED_ICLASS_SHL:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.ShiftLeft(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- IL_FLAGWRITE_ALL)));
+ il.ShiftLeft(opSize, left, right,
+ noFlags ? 0 : IL_FLAGWRITE_ALL)));
break;
+ }
// This is imprecise since it does NOT move the last shifted bit into CF
// the same problem also happens on SHL, SAR
case XED_ICLASS_SHR:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.LogicalShiftRight(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- IL_FLAGWRITE_ALL)));
+ il.LogicalShiftRight(opSize, left, right,
+ noFlags ? 0 : IL_FLAGWRITE_ALL)));
break;
+ }
case XED_ICLASS_SHLX:
il.AddInstruction(
@@ -3144,54 +3717,86 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
case XED_ICLASS_SHLD:
{
+ // TODO: Might need to swap for new data?
size_t opSize = opOneLen;
size_t mask = opSize == 4 ? 31 : 63;
// Shift left double: operand[0] = operand[0]:operand[1] << operand[3]
// this since we can't easily operation on a combined register we do it like this
// operand[0] = (operand[0] << operand[3]) | (operand[1] >> (63|32 - operand[3]))
- // One final cevate operand[3] must be masked with 63|32
+ // One final caveat operand[3] must be masked with 63|32
+ ExprId left, right, count;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+
+ count = il.And(opSize,
+ il.Const(1, mask),
+ ReadILOperand(il, xedd, addr, 2, 2));
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+
+ count = il.And(opSize,
+ il.Const(1, mask),
+ ReadILOperand(il, xedd, addr, 3, 3));
+ }
+
il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0,
il.Or(opSize,
- il.ShiftLeft(opSize,
- ReadILOperand(il, xedd, addr, 0, 0),
- il.And(opSize,
- il.Const(1, mask),
- ReadILOperand(il, xedd, addr, 2, 2)),
- IL_FLAGWRITE_ALL),
+ il.ShiftLeft(opSize, left, count,
+ noFlags ? 0 : IL_FLAGWRITE_ALL),
il.LogicalShiftRight(opSize,
- ReadILOperand(il, xedd, addr, 1, 1),
- il.Sub(opSize,
- il.And(opSize,
- il.Const(1, mask),
- ReadILOperand(il, xedd, addr, 2, 2)),
- il.Const(1, opSize * 8))))));
+ right,
+ il.Sub(opSize, count, il.Const(1, opSize * 8))))));
break;
}
case XED_ICLASS_SHRD:
{
+ // TODO: Might need to swap for new data?
size_t opSize = opOneLen;
size_t mask = opSize == 4 ? 31 : 63;
// Shift right double: operand[0] = operand[0]:operand[1] >> operand[3]
// this since we can't easily operation on a combined register we do it like this
// operand[0] = (operand[0] >> operand[3]) | (operand[1] << (63|31 - operand[3]))
- // One final cevate operand[3] must be masked with 63|31
+ // One final caveat operand[3] must be masked with 63|31
+ ExprId left, right, count;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+
+ count = il.And(opSize,
+ il.Const(1, mask),
+ ReadILOperand(il, xedd, addr, 2, 2));
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+
+ count = il.And(opSize,
+ il.Const(1, mask),
+ ReadILOperand(il, xedd, addr, 3, 3));
+ }
+
il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0,
il.Or(opSize,
il.LogicalShiftRight(opSize,
- ReadILOperand(il, xedd, addr, 0, 0),
- il.And(opSize,
- il.Const(1, mask),
- ReadILOperand(il, xedd, addr, 2, 2)),
- IL_FLAGWRITE_ALL),
+ left,
+ count,
+ noFlags ? 0 : IL_FLAGWRITE_ALL),
il.ShiftLeft(opSize,
- ReadILOperand(il, xedd, addr, 1, 1),
- il.Sub(opSize,
- il.Const(1, opSize * 8),
- il.And(opSize,
- il.Const(1, mask),
- ReadILOperand(il, xedd, addr, 2, 2)))))));
+ right,
+ il.Sub(opSize, il.Const(1, opSize * 8), count)))));
break;
}
case XED_ICLASS_STOSB:
@@ -3313,15 +3918,32 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
case XED_ICLASS_SUB_LOCK: // TODO: Handle lock prefix
case XED_ICLASS_SUB:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.Sub(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- IL_FLAGWRITE_ALL)));
+ il.Sub(opSize, left, right,
+ noFlags ? 0 : IL_FLAGWRITE_ALL)));
break;
+ }
case XED_ICLASS_TEST:
+ case XED_ICLASS_CTESTT:
il.AddInstruction(
il.And(opOneLen,
ReadILOperand(il, xedd, addr, 0, 0),
@@ -3367,6 +3989,66 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
);
break;
+ case XED_ICLASS_CTESTO:
+ ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_O));
+ break;
+
+ case XED_ICLASS_CTESTNO:
+ ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_NO));
+ break;
+
+ case XED_ICLASS_CTESTB:
+ ConditionalTest(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_LT));
+ break;
+
+ case XED_ICLASS_CTESTNB:
+ ConditionalTest(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_GE));
+ break;
+
+ case XED_ICLASS_CTESTZ:
+ ConditionalTest(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_E));
+ break;
+
+ case XED_ICLASS_CTESTNZ:
+ ConditionalTest(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_NE));
+ break;
+
+ case XED_ICLASS_CTESTBE:
+ ConditionalTest(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_LE));
+ break;
+
+ case XED_ICLASS_CTESTNBE:
+ ConditionalTest(addr, xedd, il, opOneLen, il.FlagGroup(IL_FLAG_GROUP_GT));
+ break;
+
+ case XED_ICLASS_CTESTS:
+ ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_NEG));
+ break;
+
+ case XED_ICLASS_CTESTNS:
+ ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_POS));
+ break;
+
+ case XED_ICLASS_CTESTL:
+ ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SLT));
+ break;
+
+ case XED_ICLASS_CTESTNL:
+ ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SLT));
+ break;
+
+ case XED_ICLASS_CTESTLE:
+ ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SLE));
+ break;
+
+ case XED_ICLASS_CTESTNLE:
+ ConditionalTest(addr, xedd, il, opOneLen, il.FlagCondition(LLFC_SGT));
+ break;
+
+ case XED_ICLASS_CTESTF:
+ AssignEvexDfv(xedd, il);
+ break;
+
case XED_ICLASS_XCHG:
il.AddInstruction(il.SetRegister(opOneLen, LLIL_TEMP(0), ReadILOperand(il, xedd, addr, 0, 0)));
il.AddInstruction(WriteILOperand(il, xedd, addr, 0, 0, ReadILOperand(il, xedd, addr, 1, 1)));
@@ -3500,13 +4182,30 @@ bool GetLowLevelILForInstruction(Architecture* arch, const uint64_t addr, LowLev
break;
case XED_ICLASS_XOR_LOCK: // TODO: Handle lock prefix
case XED_ICLASS_XOR:
+ {
+ ExprId left, right;
+ size_t opSize = opOneLen;
+ if (!newDataDestination)
+ {
+ // nothing special
+ left = ReadILOperand(il, xedd, addr, 0, 0);
+ right = ReadILOperand(il, xedd, addr, 1, 1);
+ }
+ else
+ {
+ // new data destination
+ left = ReadILOperand(il, xedd, addr, 1, 1);
+ right = ReadILOperand(il, xedd, addr, 2, 2);
+ opSize = opTwoLen;
+ }
+
il.AddInstruction(
WriteILOperand(il, xedd, addr, 0, 0,
- il.Xor(opOneLen,
- ReadILOperand(il, xedd, addr, 0, 0),
- ReadILOperand(il, xedd, addr, 1, 1),
- IL_FLAGWRITE_ALL)));
+ il.Xor(opSize, left, right,
+ noFlags ? 0 : IL_FLAGWRITE_ALL)));
break;
+ }
+
case XED_ICLASS_VPXOR:
if (xed_classify_avx512(xedd))
{