diff --git a/bddisasm/bddisasm.c b/bddisasm/bddisasm.c
index 22bc236..1b232c3 100644
--- a/bddisasm/bddisasm.c
+++ b/bddisasm/bddisasm.c
@@ -1719,6 +1719,7 @@ NdParseOperand(
operand->Info.Register.Type = ND_REG_SEG;
operand->Info.Register.Size = (ND_REG_SIZE)size;
operand->Info.Register.Reg = NDR_CS;
+ Instrux->CsAccess |= operand->Access.Access;
break;
case ND_OPT_SEG_SS:
@@ -4101,6 +4102,18 @@ NdDecodeWithContext(
Instrux->IsCetTracked = ND_HAS_CETT(Instrux) && ((!ND_DNT_SUPPORT(Instrux)) ||
(Instrux->Seg != ND_PREFIX_G2_NO_TRACK));
+ // Fill in branch information.
+ if (!!(Instrux->RipAccess & ND_ACCESS_ANY_WRITE))
+ {
+ Instrux->BranchInfo.IsBranch = 1;
+ Instrux->BranchInfo.IsConditional = Instrux->Category == ND_CAT_COND_BR;
+ // Indirect branches are those which get their target address from a register or memory, including RET familly.
+ Instrux->BranchInfo.IsIndirect = ((!Instrux->Operands[0].Flags.IsDefault) &&
+ (Instrux->Operands[0].Type == ND_OP_REG) || (Instrux->Operands[0].Type == ND_OP_MEM)) ||
+ (Instrux->Category == ND_CAT_RET);
+ Instrux->BranchInfo.IsFar = !!(Instrux->CsAccess & ND_ACCESS_ANY_WRITE);
+ }
+
// Do instruction validations. These checks are made in order to filter out encodings that would normally
// be invalid and would generate #UD.
status = NdValidateInstruction(Instrux);
@@ -4145,212 +4158,9 @@ NdDecode(
}
-
-
-//
-// NdIsInstruxRipRelative
-//
-bool
-NdIsInstruxRipRelative(
- const INSTRUX *Instrux
- )
-//
-// Provided for backwards compatibility with existing code that uses disasm 1.0
-//
-{
- if (NULL == Instrux)
- {
- return false;
- }
- else
- {
- return Instrux->IsRipRelative;
- }
-}
-
-
//
-// NdGetFullAccessMap
+// NdInitContext
//
-NDSTATUS
-NdGetFullAccessMap(
- const INSTRUX *Instrux,
- ND_ACCESS_MAP *AccessMap
- )
-{
- uint32_t i;
- const ND_OPERAND *pOp;
-
- // pre-init
- i = 0;
- pOp = NULL;
-
- // validate
- if (NULL == Instrux)
- {
- return ND_STATUS_INVALID_PARAMETER;
- }
-
- if (NULL == AccessMap)
- {
- return ND_STATUS_INVALID_PARAMETER;
- }
-
- for (i = 0; i < Instrux->OperandsCount; i++)
- {
- pOp = &Instrux->Operands[i];
-
- if (ND_OP_MEM == pOp->Type)
- {
- if (pOp->Info.Memory.IsStack)
- {
- AccessMap->StackAccess |= pOp->Access.Access;
- AccessMap->GprAccess[NDR_RSP] |= ND_ACCESS_READ|ND_ACCESS_WRITE;
- AccessMap->SegAccess[NDR_SS] |= ND_ACCESS_READ;
- }
- else
- {
- AccessMap->MemAccess |= pOp->Access.Access;
-
- if (pOp->Info.Memory.HasSeg)
- {
- AccessMap->SegAccess[pOp->Info.Memory.Seg] |= ND_ACCESS_READ;
- }
-
- if (pOp->Info.Memory.HasBase)
- {
- AccessMap->GprAccess[pOp->Info.Memory.Base] |= ND_ACCESS_READ;
- }
-
- if (pOp->Info.Memory.HasIndex)
- {
- if (pOp->Info.Memory.IsVsib)
- {
- AccessMap->SseAccess[pOp->Info.Memory.Index] |= ND_ACCESS_READ;
- }
- else
- {
- AccessMap->GprAccess[pOp->Info.Memory.Index] |= ND_ACCESS_READ;
- }
- }
- }
- }
- else if (ND_OP_REG == pOp->Type)
- {
- switch (pOp->Info.Register.Type)
- {
- case ND_REG_GPR:
- {
- uint32_t k;
-
- for (k = 0; k < pOp->Info.Register.Count; k++)
- {
- AccessMap->GprAccess[pOp->Info.Register.Reg + k] |= pOp->Access.Access;
- }
- }
- break;
- case ND_REG_SEG:
- AccessMap->SegAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
- break;
- case ND_REG_FPU:
- AccessMap->FpuAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
- break;
- case ND_REG_MMX:
- AccessMap->MmxAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
- break;
- case ND_REG_SSE:
- {
- uint32_t k;
-
- for (k = 0; k < pOp->Info.Register.Count; k++)
- {
- AccessMap->SseAccess[pOp->Info.Register.Reg + k] |= pOp->Access.Access;
- }
- }
- break;
- case ND_REG_CR:
- AccessMap->CrAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
- break;
- case ND_REG_DR:
- AccessMap->DrAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
- break;
- case ND_REG_TR:
- AccessMap->TrAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
- break;
- case ND_REG_BND:
- AccessMap->BndAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
- break;
- case ND_REG_MSK:
- AccessMap->MskAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
- break;
- case ND_REG_SYS:
- AccessMap->SysAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
- break;
- case ND_REG_X87:
- AccessMap->X87Access[pOp->Info.Register.Reg] |= pOp->Access.Access;
- break;
- case ND_REG_FLG:
- AccessMap->FlagsAccess |= pOp->Access.Access;
- break;
- case ND_REG_RIP:
- AccessMap->RipAccess |= pOp->Access.Access;
- break;
- case ND_REG_MXCSR:
- AccessMap->MxcsrAccess |= pOp->Access.Access;
- break;
- case ND_REG_PKRU:
- AccessMap->PkruAccess |= pOp->Access.Access;
- break;
- case ND_REG_SSP:
- AccessMap->SspAccess |= pOp->Access.Access;
- break;
- default:
- break;
- }
- }
- else if (ND_OP_BANK == Instrux->Operands[i].Type)
- {
- uint8_t j;
-
- // Bank registers access. This needs special handling. Note that LOADALL/LOADALLD is not supported, as
- // it is too old and it's not valid since the good old 486.
- if (ND_INS_FNSAVE == Instrux->Instruction)
- {
- for (j = 0; j < ND_MAX_FPU_REGS; j++)
- {
- AccessMap->FpuAccess[j] |= ND_ACCESS_READ;
- }
- }
- else if (ND_INS_FRSTOR == Instrux->Instruction)
- {
- for (j = 0; j < ND_MAX_FPU_REGS; j++)
- {
- AccessMap->FpuAccess[j] |= ND_ACCESS_WRITE;
- }
- }
-
- if ((ND_INS_XSAVE == Instrux->Instruction) || (ND_INS_XSAVEOPT == Instrux->Instruction) ||
- (ND_INS_XSAVES == Instrux->Instruction) || (ND_INS_XSAVEC == Instrux->Instruction))
- {
- for (j = 0; j < ND_MAX_SSE_REGS; j++)
- {
- AccessMap->SseAccess[j] |= ND_ACCESS_READ;
- }
- }
- else if ((ND_INS_XRSTOR == Instrux->Instruction) || (ND_INS_XRSTORS == Instrux->Instruction))
- {
- for (j = 0; j < ND_MAX_SSE_REGS; j++)
- {
- AccessMap->SseAccess[j] |= ND_ACCESS_WRITE;
- }
- }
- }
- }
-
- return ND_STATUS_SUCCESS;
-}
-
-
void
NdInitContext(
ND_CONTEXT *Context
diff --git a/bddisasm/bddisasm.vcxproj b/bddisasm/bddisasm.vcxproj
index ae1cbf3..abcd197 100644
--- a/bddisasm/bddisasm.vcxproj
+++ b/bddisasm/bddisasm.vcxproj
@@ -421,6 +421,7 @@
+
NotUsing
diff --git a/bddisasm/bddisasm.vcxproj.filters b/bddisasm/bddisasm.vcxproj.filters
index b4de484..b8052d0 100644
--- a/bddisasm/bddisasm.vcxproj.filters
+++ b/bddisasm/bddisasm.vcxproj.filters
@@ -30,6 +30,9 @@
Source Files
+
+ Source Files
+
diff --git a/bddisasm/bdhelpers.c b/bddisasm/bdhelpers.c
new file mode 100644
index 0000000..72ba1b0
--- /dev/null
+++ b/bddisasm/bdhelpers.c
@@ -0,0 +1,321 @@
+#include "include/nd_crt.h"
+#include "../inc/bddisasm.h"
+
+
+//
+// NdIsInstruxRipRelative
+//
+bool
+NdIsInstruxRipRelative(
+ const INSTRUX *Instrux
+ )
+//
+// Provided for backwards compatibility with existing code that uses disasm 1.0
+//
+{
+ if (NULL == Instrux)
+ {
+ return false;
+ }
+ else
+ {
+ return Instrux->IsRipRelative;
+ }
+}
+
+
+//
+// NdGetFullAccessMap
+//
+NDSTATUS
+NdGetFullAccessMap(
+ const INSTRUX *Instrux,
+ ND_ACCESS_MAP *AccessMap
+ )
+{
+ uint32_t i;
+ const ND_OPERAND *pOp;
+
+ // pre-init
+ i = 0;
+ pOp = NULL;
+
+ // validate
+ if (NULL == Instrux)
+ {
+ return ND_STATUS_INVALID_PARAMETER;
+ }
+
+ if (NULL == AccessMap)
+ {
+ return ND_STATUS_INVALID_PARAMETER;
+ }
+
+ for (i = 0; i < Instrux->OperandsCount; i++)
+ {
+ pOp = &Instrux->Operands[i];
+
+ if (ND_OP_MEM == pOp->Type)
+ {
+ if (pOp->Info.Memory.IsStack)
+ {
+ AccessMap->StackAccess |= pOp->Access.Access;
+ AccessMap->GprAccess[NDR_RSP] |= ND_ACCESS_READ|ND_ACCESS_WRITE;
+ AccessMap->SegAccess[NDR_SS] |= ND_ACCESS_READ;
+ }
+ else
+ {
+ AccessMap->MemAccess |= pOp->Access.Access;
+
+ if (pOp->Info.Memory.HasSeg)
+ {
+ AccessMap->SegAccess[pOp->Info.Memory.Seg] |= ND_ACCESS_READ;
+ }
+
+ if (pOp->Info.Memory.HasBase)
+ {
+ AccessMap->GprAccess[pOp->Info.Memory.Base] |= ND_ACCESS_READ;
+ }
+
+ if (pOp->Info.Memory.HasIndex)
+ {
+ if (pOp->Info.Memory.IsVsib)
+ {
+ AccessMap->SseAccess[pOp->Info.Memory.Index] |= ND_ACCESS_READ;
+ }
+ else
+ {
+ AccessMap->GprAccess[pOp->Info.Memory.Index] |= ND_ACCESS_READ;
+ }
+ }
+ }
+ }
+ else if (ND_OP_REG == pOp->Type)
+ {
+ switch (pOp->Info.Register.Type)
+ {
+ case ND_REG_GPR:
+ {
+ uint32_t k;
+
+ for (k = 0; k < pOp->Info.Register.Count; k++)
+ {
+ AccessMap->GprAccess[pOp->Info.Register.Reg + k] |= pOp->Access.Access;
+ }
+ }
+ break;
+ case ND_REG_SEG:
+ AccessMap->SegAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
+ break;
+ case ND_REG_FPU:
+ AccessMap->FpuAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
+ break;
+ case ND_REG_MMX:
+ AccessMap->MmxAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
+ break;
+ case ND_REG_SSE:
+ {
+ uint32_t k;
+
+ for (k = 0; k < pOp->Info.Register.Count; k++)
+ {
+ AccessMap->SseAccess[pOp->Info.Register.Reg + k] |= pOp->Access.Access;
+ }
+ }
+ break;
+ case ND_REG_CR:
+ AccessMap->CrAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
+ break;
+ case ND_REG_DR:
+ AccessMap->DrAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
+ break;
+ case ND_REG_TR:
+ AccessMap->TrAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
+ break;
+ case ND_REG_BND:
+ AccessMap->BndAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
+ break;
+ case ND_REG_MSK:
+ AccessMap->MskAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
+ break;
+ case ND_REG_SYS:
+ AccessMap->SysAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
+ break;
+ case ND_REG_X87:
+ AccessMap->X87Access[pOp->Info.Register.Reg] |= pOp->Access.Access;
+ break;
+ case ND_REG_FLG:
+ AccessMap->FlagsAccess |= pOp->Access.Access;
+ break;
+ case ND_REG_RIP:
+ AccessMap->RipAccess |= pOp->Access.Access;
+ break;
+ case ND_REG_MXCSR:
+ AccessMap->MxcsrAccess |= pOp->Access.Access;
+ break;
+ case ND_REG_PKRU:
+ AccessMap->PkruAccess |= pOp->Access.Access;
+ break;
+ case ND_REG_SSP:
+ AccessMap->SspAccess |= pOp->Access.Access;
+ break;
+ case ND_REG_TILE:
+ AccessMap->TmmAccess[pOp->Info.Register.Reg] |= pOp->Access.Access;
+ break;
+ default:
+ break;
+ }
+ }
+ else if (ND_OP_BANK == Instrux->Operands[i].Type)
+ {
+ uint8_t j;
+
+ // Bank registers access. This needs special handling. Note that LOADALL/LOADALLD is not supported, as
+ // it is too old and it's not valid since the good old 486.
+ if (ND_INS_FNSAVE == Instrux->Instruction)
+ {
+ for (j = 0; j < ND_MAX_FPU_REGS; j++)
+ {
+ AccessMap->FpuAccess[j] |= ND_ACCESS_READ;
+ }
+ }
+ else if (ND_INS_FRSTOR == Instrux->Instruction)
+ {
+ for (j = 0; j < ND_MAX_FPU_REGS; j++)
+ {
+ AccessMap->FpuAccess[j] |= ND_ACCESS_WRITE;
+ }
+ }
+
+ if ((ND_INS_XSAVE == Instrux->Instruction) || (ND_INS_XSAVEOPT == Instrux->Instruction) ||
+ (ND_INS_XSAVES == Instrux->Instruction) || (ND_INS_XSAVEC == Instrux->Instruction))
+ {
+ for (j = 0; j < ND_MAX_SSE_REGS; j++)
+ {
+ AccessMap->SseAccess[j] |= ND_ACCESS_READ;
+ }
+ }
+ else if ((ND_INS_XRSTOR == Instrux->Instruction) || (ND_INS_XRSTORS == Instrux->Instruction))
+ {
+ for (j = 0; j < ND_MAX_SSE_REGS; j++)
+ {
+ AccessMap->SseAccess[j] |= ND_ACCESS_WRITE;
+ }
+ }
+ }
+ }
+
+ return ND_STATUS_SUCCESS;
+}
+
+
+//
+// NdGetOperandRlut
+//
+NDSTATUS
+NdGetOperandRlut(
+ INSTRUX *Instrux,
+ ND_OPERAND_RLUT *Rlut
+ )
+{
+ if (NULL == Instrux)
+ {
+ return ND_STATUS_INVALID_PARAMETER;
+ }
+
+ if (NULL == Rlut)
+ {
+ return ND_STATUS_INVALID_PARAMETER;
+ }
+
+ // Initialize the RLUT.
+ nd_memset(Rlut, 0, sizeof(*Rlut));
+
+ for (uint8_t i = 0; i < Instrux->OperandsCount; i++)
+ {
+ if (!!(Instrux->Operands[i].Access.Access & ND_ACCESS_ANY_WRITE))
+ {
+ // We only care about the first 2 destination operands.
+ if (Rlut->Dst1 == NULL)
+ {
+ Rlut->Dst1 = &Instrux->Operands[i];
+ }
+ else if (Rlut->Dst2 == NULL)
+ {
+ Rlut->Dst2 = &Instrux->Operands[i];
+ }
+ }
+
+ if (!!(Instrux->Operands[i].Access.Access & ND_ACCESS_ANY_READ))
+ {
+ // We only care about the first 4 source operands.
+ if (Rlut->Src1 == NULL)
+ {
+ Rlut->Src1 = &Instrux->Operands[i];
+ }
+ else if (Rlut->Src2 == NULL)
+ {
+ Rlut->Src2 = &Instrux->Operands[i];
+ }
+ else if (Rlut->Src3 == NULL)
+ {
+ Rlut->Src3 = &Instrux->Operands[i];
+ }
+ else if (Rlut->Src4 == NULL)
+ {
+ Rlut->Src4 = &Instrux->Operands[i];
+ }
+ }
+
+ if (Instrux->Operands[i].Type == ND_OP_MEM)
+ {
+ // We only care about the first 2 memory operands.
+ if (Rlut->Mem1 == NULL)
+ {
+ Rlut->Mem1 = &Instrux->Operands[i];
+ }
+ else if (Rlut->Mem2 == NULL)
+ {
+ Rlut->Mem2 = &Instrux->Operands[i];
+ }
+
+ if (Instrux->Operands[i].Info.Memory.IsStack)
+ {
+ Rlut->Stack = &Instrux->Operands[i];
+ }
+ }
+
+ if (Instrux->Operands[i].Type == ND_OP_REG && Instrux->Operands->Flags.IsDefault)
+ {
+ switch (Instrux->Operands[i].Info.Register.Type)
+ {
+ case ND_REG_FLG:
+ Rlut->Flags = &Instrux->Operands[i];
+ break;
+ case ND_REG_RIP:
+ Rlut->Rip = &Instrux->Operands[i];;
+ break;
+ case ND_REG_SEG:
+ if (Instrux->Operands[i].Info.Register.Reg == NDR_CS)
+ {
+ Rlut->Cs = &Instrux->Operands[i];
+ }
+ else if (Instrux->Operands[i].Info.Register.Reg == NDR_SS)
+ {
+ Rlut->Ss = &Instrux->Operands[i];
+ }
+ break;
+ case ND_REG_GPR:
+ if (Instrux->Operands[i].Info.Register.Reg < 8)
+ {
+ *(&Rlut->Rax + Instrux->Operands[i].Info.Register.Reg) = &Instrux->Operands[i];
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return ND_STATUS_SUCCESS;
+}
\ No newline at end of file
diff --git a/bddisasm/include/instructions.h b/bddisasm/include/instructions.h
index e476a02..5b41a93 100644
--- a/bddisasm/include/instructions.h
+++ b/bddisasm/include/instructions.h
@@ -3983,7 +3983,7 @@ const ND_INSTRUCTION gInstructions[2701] =
// Pos:239 Instruction:"ERETS" Encoding:"0xF2 0x0F 0x01 /0xCA"/""
{
- ND_INS_ERETS, ND_CAT_FRED, ND_SET_FRED, 169,
+ ND_INS_ERETS, ND_CAT_RET, ND_SET_FRED, 169,
0,
ND_MOD_R0|ND_MOD_LONG|ND_MOD_VMXR|ND_MOD_VMXN|ND_MOD_VMXR_SEAM|ND_MOD_VMXN_SEAM|ND_MOD_VMX_OFF|ND_MOD_SMM|ND_MOD_SMM_OFF|ND_MOD_SGX_OFF|ND_MOD_TSX_OFF,
0, ND_OPS_CNT(0, 5), 0, 0, 0, 0, 0, 0, ND_FLAG_F64|ND_FLAG_MODRM|ND_FLAG_O64, ND_CFF_FRED,
@@ -4002,7 +4002,7 @@ const ND_INSTRUCTION gInstructions[2701] =
// Pos:240 Instruction:"ERETU" Encoding:"0xF3 0x0F 0x01 /0xCA"/""
{
- ND_INS_ERETU, ND_CAT_FRED, ND_SET_FRED, 170,
+ ND_INS_ERETU, ND_CAT_RET, ND_SET_FRED, 170,
0,
ND_MOD_R0|ND_MOD_LONG|ND_MOD_VMXR|ND_MOD_VMXN|ND_MOD_VMXR_SEAM|ND_MOD_VMXN_SEAM|ND_MOD_VMX_OFF|ND_MOD_SMM|ND_MOD_SMM_OFF|ND_MOD_SGX_OFF|ND_MOD_TSX_OFF,
0, ND_OPS_CNT(0, 9), 0, 0, 0, 0, 0, 0, ND_FLAG_F64|ND_FLAG_MODRM|ND_FLAG_O64, ND_CFF_FRED,
@@ -22273,7 +22273,7 @@ const ND_INSTRUCTION gInstructions[2701] =
// Pos:1349 Instruction:"UIRET" Encoding:"0xF3 0x0F 0x01 /0xEC"/""
{
- ND_INS_UIRET, ND_CAT_UINTR, ND_SET_UINTR, 810,
+ ND_INS_UIRET, ND_CAT_RET, ND_SET_UINTR, 810,
0,
ND_MOD_R0|ND_MOD_R1|ND_MOD_R2|ND_MOD_R3|ND_MOD_LONG|ND_MOD_VMXR|ND_MOD_VMXN|ND_MOD_VMXR_SEAM|ND_MOD_VMXN_SEAM|ND_MOD_VMX_OFF|ND_MOD_SMM|ND_MOD_SMM_OFF|ND_MOD_SGX_OFF|ND_MOD_TSX_OFF,
0, ND_OPS_CNT(0, 6), 0, 0, 0, 0, 0, 0, ND_FLAG_F64|ND_FLAG_MODRM|ND_FLAG_O64, ND_CFF_UINTR,
@@ -30955,7 +30955,7 @@ const ND_INSTRUCTION gInstructions[2701] =
{
ND_INS_VMCALL, ND_CAT_VTX, ND_SET_VTX, 1160,
0,
- ND_MOD_R0|ND_MOD_R1|ND_MOD_R2|ND_MOD_R3|ND_MOD_REAL|ND_MOD_V8086|ND_MOD_PROT|ND_MOD_COMPAT|ND_MOD_LONG|ND_MOD_VMXR|ND_MOD_VMXN|ND_MOD_VMXR_SEAM|ND_MOD_VMXN_SEAM|ND_MOD_SMM|ND_MOD_SMM_OFF|ND_MOD_SGX_OFF|ND_MOD_TSX|ND_MOD_TSX_OFF,
+ ND_MOD_R0|ND_MOD_R1|ND_MOD_R2|ND_MOD_R3|ND_MOD_REAL|ND_MOD_V8086|ND_MOD_PROT|ND_MOD_COMPAT|ND_MOD_LONG|ND_MOD_VMXR|ND_MOD_VMXN|ND_MOD_VMXR_SEAM|ND_MOD_VMXN_SEAM|ND_MOD_SMM|ND_MOD_SMM_OFF|ND_MOD_SGX_OFF|ND_MOD_TSX_OFF,
0, ND_OPS_CNT(0, 0), 0, 0, 0, 0, 0, 0, ND_FLAG_MODRM, ND_CFF_VTX,
0,
0,
@@ -44744,13 +44744,14 @@ const ND_INSTRUCTION gInstructions[2701] =
ND_INS_XABORT, ND_CAT_UNCOND_BR, ND_SET_TSX, 1661,
0,
ND_MOD_R0|ND_MOD_R1|ND_MOD_R2|ND_MOD_R3|ND_MOD_REAL|ND_MOD_V8086|ND_MOD_PROT|ND_MOD_COMPAT|ND_MOD_LONG|ND_MOD_VMXR|ND_MOD_VMXN|ND_MOD_VMXR_SEAM|ND_MOD_VMXN_SEAM|ND_MOD_VMX_OFF|ND_MOD_SMM|ND_MOD_SMM_OFF|ND_MOD_SGX|ND_MOD_SGX_OFF|ND_MOD_TSX_OFF,
- 0, ND_OPS_CNT(1, 1), 0, 0, 0, 0, 0, 0, ND_FLAG_MODRM, ND_CFF_RTM,
+ 0, ND_OPS_CNT(1, 2), 0, 0, 0, 0, 0, 0, ND_FLAG_MODRM, ND_CFF_RTM,
0,
0,
0,
0,
{
OP(ND_OPT_I, ND_OPS_b, 0, ND_OPA_R, 0, 0),
+ OP(ND_OPT_RIP, ND_OPS_yf, ND_OPF_DEFAULT, ND_OPA_W, 0, 0),
OP(ND_OPT_GPR_rAX, ND_OPS_d, ND_OPF_DEFAULT, ND_OPA_RCW, 0, 0),
},
},
@@ -45046,13 +45047,13 @@ const ND_INSTRUCTION gInstructions[2701] =
ND_INS_XEND, ND_CAT_COND_BR, ND_SET_TSX, 1670,
0,
ND_MOD_ANY,
- 0, ND_OPS_CNT(0, 0), 0, 0, 0, 0, 0, 0, ND_FLAG_MODRM, ND_CFF_RTM,
+ 0, ND_OPS_CNT(0, 1), 0, 0, 0, 0, 0, 0, ND_FLAG_MODRM, ND_CFF_RTM,
0,
0,
0,
0,
{
- 0
+ OP(ND_OPT_RIP, ND_OPS_yf, ND_OPF_DEFAULT, ND_OPA_CW, 0, 0),
},
},
diff --git a/bddisasm/include/nd_crt.h b/bddisasm/include/nd_crt.h
index b1281cd..c95dd66 100644
--- a/bddisasm/include/nd_crt.h
+++ b/bddisasm/include/nd_crt.h
@@ -12,8 +12,7 @@
#endif
#if defined(_MSC_VER)
-
-typedef char * va_list;
+#include
# ifndef _ADDRESSOF
# ifdef __cplusplus
@@ -27,8 +26,6 @@ typedef char * va_list;
# if defined(AMD64) || defined(WIN64)
-extern void __cdecl __va_start(__out va_list *, ...); // is this exported by VC compiler?
-
# define _crt_va_start(ap, x) ( __va_start(&ap, x) )
# define _crt_va_arg(ap, t) ( ( sizeof(t) > sizeof(QWORD) || ( sizeof(t) & (sizeof(t) - 1) ) != 0 ) \
? **(t **)( ( ap += sizeof(QWORD) ) - sizeof(QWORD) ) \
diff --git a/bddisasm_test/basic/tsx_64.result b/bddisasm_test/basic/tsx_64.result
index 0b8862f..601852a 100644
--- a/bddisasm_test/basic/tsx_64.result
+++ b/bddisasm_test/basic/tsx_64.result
@@ -46,7 +46,8 @@
HLE: no, XACQUIRE only: no, XRELEASE only: no
BND: no, BHINT: no, DNT: no
Operand: 0, Acc: R-, Type: Immediate, Size: 1, RawSize: 1, Encoding: I
- Operand: 1, Acc: RCW, Type: Register, Size: 4, RawSize: 4, Encoding: S, RegType: General Purpose, RegSize: 4, RegId: 0, RegCount: 1
+ Operand: 1, Acc: -W, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: IP, RegSize: 8, RegId: 0, RegCount: 1
+ Operand: 2, Acc: RCW, Type: Register, Size: 4, RawSize: 4, Encoding: S, RegType: General Purpose, RegSize: 4, RegId: 0, RegCount: 1
000000000000000C 0f01d5 XEND
DSIZE: 32, ASIZE: 64, VLEN: -
@@ -61,6 +62,7 @@
REP: no, REPcc: no, LOCK: no
HLE: no, XACQUIRE only: no, XRELEASE only: no
BND: no, BHINT: no, DNT: no
+ Operand: 0, Acc: CW, Type: Register, Size: 8, RawSize: 8, Encoding: S, RegType: IP, RegSize: 8, RegId: 0, RegCount: 1
000000000000000F f20f01e8 XSUSLDTRK
DSIZE: 32, ASIZE: 64, VLEN: -
diff --git a/bddisasm_test/basic/vmx_64.result b/bddisasm_test/basic/vmx_64.result
index ef8a4bd..622bafa 100644
--- a/bddisasm_test/basic/vmx_64.result
+++ b/bddisasm_test/basic/vmx_64.result
@@ -5,7 +5,7 @@
Valid modes
R0: yes, R1: yes, R2: yes, R3: yes
Real: yes, V8086: yes, Prot: yes, Compat: yes, Long: yes
- SMM on: yes, SMM off: yes, SGX on: no, SGX off: yes, TSX on: yes, TSX off: yes
+ SMM on: yes, SMM off: yes, SGX on: no, SGX off: yes, TSX on: no, TSX off: yes
VMXRoot: yes, VMXNonRoot: yes, VMXRoot SEAM: yes, VMXNonRoot SEAM: yes, VMX off: no
Valid prefixes
REP: no, REPcc: no, LOCK: no
diff --git a/bddisasm_test/fred/fred_64.result b/bddisasm_test/fred/fred_64.result
index 9b1b763..05b03ae 100644
--- a/bddisasm_test/fred/fred_64.result
+++ b/bddisasm_test/fred/fred_64.result
@@ -1,6 +1,6 @@
0000000000000000 f30f01ca ERETU
DSIZE: 64, ASIZE: 64, VLEN: -
- ISA Set: FRED, Ins cat: FRED, CET tracked: no
+ ISA Set: FRED, Ins cat: RET, CET tracked: no
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 17
FLAGS access
Entire register
@@ -26,7 +26,7 @@
0000000000000004 f20f01ca ERETS
DSIZE: 64, ASIZE: 64, VLEN: -
- ISA Set: FRED, Ins cat: FRED, CET tracked: no
+ ISA Set: FRED, Ins cat: RET, CET tracked: no
CPUID leaf: 0x00000007, sub-leaf: 0x00000001, reg: eax, bit: 17
FLAGS access
Entire register
diff --git a/bddisasm_test/uintr/uintr_64.result b/bddisasm_test/uintr/uintr_64.result
index bda44b5..69081e4 100644
--- a/bddisasm_test/uintr/uintr_64.result
+++ b/bddisasm_test/uintr/uintr_64.result
@@ -1,6 +1,6 @@
0000000000000000 f30f01ec UIRET
DSIZE: 64, ASIZE: 64, VLEN: -
- ISA Set: UINTR, Ins cat: UINTR, CET tracked: no
+ ISA Set: UINTR, Ins cat: RET, CET tracked: no
CPUID leaf: 0x00000007, sub-leaf: 0x00000000, reg: edx, bit: 5
FLAGS access
Entire register
diff --git a/bindings/pybddisasm/setup.py b/bindings/pybddisasm/setup.py
index 7125bb4..1d5834f 100644
--- a/bindings/pybddisasm/setup.py
+++ b/bindings/pybddisasm/setup.py
@@ -12,7 +12,7 @@ from setuptools import find_packages, setup, Command, Extension, Distribution
from codecs import open
VERSION = (0, 1, 3)
-LIBRARY_VERSION = (1, 34, 5)
+LIBRARY_VERSION = (1, 34, 7)
LIBRARY_INSTRUX_SIZE = 864
packages = ['pybddisasm']
diff --git a/inc/bddisasm.h b/inc/bddisasm.h
index 8928f3f..e4400d3 100644
--- a/inc/bddisasm.h
+++ b/inc/bddisasm.h
@@ -669,35 +669,6 @@ typedef enum _ND_EX_TYPE_AMX
} ND_EX_TYPE_AMX;
-//
-// Operands access map. Contains every register except for MSR & XCR, includes memory, flags, RIP, stack.
-// Use NdGetFullAccessMap to populate this structure.
-//
-typedef struct _ND_ACCESS_MAP
-{
- uint8_t RipAccess;
- uint8_t FlagsAccess;
- uint8_t StackAccess;
- uint8_t MemAccess;
- uint8_t MxcsrAccess;
- uint8_t PkruAccess;
- uint8_t SspAccess;
- uint8_t GprAccess[ND_MAX_GPR_REGS];
- uint8_t SegAccess[ND_MAX_SEG_REGS];
- uint8_t FpuAccess[ND_MAX_FPU_REGS];
- uint8_t MmxAccess[ND_MAX_MMX_REGS];
- uint8_t SseAccess[ND_MAX_SSE_REGS];
- uint8_t CrAccess [ND_MAX_CR_REGS ];
- uint8_t DrAccess [ND_MAX_DR_REGS ];
- uint8_t TrAccess [ND_MAX_TR_REGS ];
- uint8_t BndAccess[ND_MAX_BND_REGS];
- uint8_t MskAccess[ND_MAX_MSK_REGS];
- uint8_t SysAccess[ND_MAX_SYS_REGS];
- uint8_t X87Access[ND_MAX_X87_REGS];
-} ND_ACCESS_MAP, *PND_ACCESS_MAP;
-
-
-
//
// Operand access mode.
//
@@ -1231,6 +1202,18 @@ typedef struct _ND_FPU_FLAGS
} ND_FPU_FLAGS, *PND_FPU_FLAGS;
+//
+// Branch information.
+//
+typedef struct _ND_BRANCH_INFO
+{
+ uint8_t IsBranch : 1;
+ uint8_t IsConditional : 1;
+ uint8_t IsIndirect : 1;
+ uint8_t IsFar : 1;
+} ND_BRANCH_INFO;
+
+
//
// Describes a decoded instruction. All the possible information about the instruction is contained in this structure.
// You don't have to call any other APIs to gather any more info about it.
@@ -1394,10 +1377,13 @@ typedef struct _INSTRUX
ND_OPERAND Operands[ND_MAX_OPERAND]; // Instruction operands.
// As extracted from the operands themselves.
+ uint8_t CsAccess; // CS access mode (read/write). Includes only implicit CS accesses.
uint8_t RipAccess; // RIP access mode (read/write).
uint8_t StackAccess; // Stack access mode (push/pop).
uint8_t MemoryAccess; // Memory access mode (read/write, including stack or shadow stack).
+ ND_BRANCH_INFO BranchInfo; // Branch information.
+
struct
{
uint8_t RegAccess; // RFLAGS access mode (read/write), as per the entire register.
@@ -1429,11 +1415,9 @@ typedef struct _INSTRUX
ND_VALID_MODES ValidModes; // Valid CPU modes for the instruction.
ND_VALID_PREFIXES ValidPrefixes; // Indicates which prefixes are valid for this instruction.
ND_VALID_DECORATORS ValidDecorators; // What decorators are accepted by the instruction.
- uint8_t Reserved1[3]; // Padding purpose. Aligns the mnemonic to 8 bytes.
char Mnemonic[ND_MAX_MNEMONIC_LENGTH]; // Instruction mnemonic.
uint8_t OpCodeBytes[3]; // Opcode bytes - escape codes and main op code
uint8_t PrimaryOpCode; // Main/nominal opcode
- uint32_t Reserved2; // Padding purpose. Aligns the InstructionBytes to 16 bytes.
uint8_t InstructionBytes[16]; // The entire instruction.
} INSTRUX, *PINSTRUX;
@@ -1454,6 +1438,76 @@ typedef struct _ND_CONTEXT
} ND_CONTEXT;
+//
+// Operands access map. Contains every register except for MSR & XCR, includes memory, flags, RIP, stack.
+// Use NdGetFullAccessMap to populate this structure.
+//
+typedef struct _ND_ACCESS_MAP
+{
+ uint8_t RipAccess;
+ uint8_t FlagsAccess;
+ uint8_t StackAccess;
+ uint8_t MemAccess;
+ uint8_t MxcsrAccess;
+ uint8_t PkruAccess;
+ uint8_t SspAccess;
+ uint8_t GprAccess[ND_MAX_GPR_REGS];
+ uint8_t SegAccess[ND_MAX_SEG_REGS];
+ uint8_t FpuAccess[ND_MAX_FPU_REGS];
+ uint8_t MmxAccess[ND_MAX_MMX_REGS];
+ uint8_t SseAccess[ND_MAX_SSE_REGS];
+ uint8_t CrAccess [ND_MAX_CR_REGS ];
+ uint8_t DrAccess [ND_MAX_DR_REGS ];
+ uint8_t TrAccess [ND_MAX_TR_REGS ];
+ uint8_t BndAccess[ND_MAX_BND_REGS];
+ uint8_t MskAccess[ND_MAX_MSK_REGS];
+ uint8_t TmmAccess[ND_MAX_TILE_REGS];
+ uint8_t SysAccess[ND_MAX_SYS_REGS];
+ uint8_t X87Access[ND_MAX_X87_REGS];
+} ND_ACCESS_MAP, *PND_ACCESS_MAP;
+
+
+//
+// Operand reverse-lookup table. Each entry inside this structure contains the pointer to the relevant operand.
+// Some rules govern this special structure:
+// - It is not generated by default. The user must call NdGetOperandRlut manually to fill in this structure.
+// - This structure holds pointers inside the INSTRUX provided to the NdGetOperandRlut function; please make sure
+// you call NdGetOperandRlut again if the INSTRUX is relocated, as all the pointers will dangle.
+// - Not all the operand types have a corresponding entry in ND_OPERAND_RLUT, only the usual ones.
+// - Some operands may have multiple entries in ND_OPERAND_RLUT - for example, RMW (read-modify-write) instructions
+// will have Dst1 and Src1 pointing to the same operand.
+// - The implicit registers entries in ND_OPERAND_RLUT will point to the operand which is of that type, and implicit;
+// for example, ND_OPERAND_RLUT.Rax will be NULL for `add rax, rcx`, since in this case, `rax` is not an implicit
+// operand. For `cpuid`, however, ND_OPERAND_RLUT.Rax will point to the implicit `eax` register.
+// Use NdGetOperandRlut to populate this structure.
+//
+typedef struct _ND_OPERAND_RLUT
+{
+ PND_OPERAND Dst1; // First destination operand.
+ PND_OPERAND Dst2; // Second destination operand.
+ PND_OPERAND Src1; // First source operand.
+ PND_OPERAND Src2; // Second source operand.
+ PND_OPERAND Src3; // Third source operand.
+ PND_OPERAND Src4; // Fourth source operand.
+ PND_OPERAND Mem1; // First memory operand.
+ PND_OPERAND Mem2; // Second memory operand.
+ PND_OPERAND Stack; // Stack operand.
+ PND_OPERAND Flags; // Flags register operand.
+ PND_OPERAND Rip; // Instruction Pointer register operand.
+ PND_OPERAND Cs; // Implicit CS operand.
+ PND_OPERAND Ss; // Implicit SS operand.
+ PND_OPERAND Rax; // Implicit accumulator register operand.
+ PND_OPERAND Rcx; // Implicit counter register operand.
+ PND_OPERAND Rdx; // Implicit data register operand
+ PND_OPERAND Rbx; // Implicit base address register operand.
+ PND_OPERAND Rsp; // Implicit stack pointer operand.
+ PND_OPERAND Rbp; // Implicit base pointer operand.
+ PND_OPERAND Rsi; // Implicit source index operand.
+ PND_OPERAND Rdi; // Implicit destination index operand.
+} ND_OPERAND_RLUT;
+
+
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -1560,6 +1614,15 @@ NdGetFullAccessMap(
ND_ACCESS_MAP *AccessMap
);
+//
+// Returns an operand reverse-lookup. One can use the Rlut to quickly reference different kinds of operands in INSTRUX.
+//
+NDSTATUS
+NdGetOperandRlut(
+ INSTRUX *Instrux,
+ ND_OPERAND_RLUT *Rlut
+ );
+
//
// Initialize the decoder context.
//
diff --git a/inc/constants.h b/inc/constants.h
index d0df420..df0c062 100644
--- a/inc/constants.h
+++ b/inc/constants.h
@@ -1758,7 +1758,6 @@ typedef enum _ND_INS_TYPE
ND_CAT_EXPAND,
ND_CAT_FLAGOP,
ND_CAT_FMA4,
- ND_CAT_FRED,
ND_CAT_GATHER,
ND_CAT_GFNI,
ND_CAT_HRESET,
diff --git a/inc/version.h b/inc/version.h
index 48c1909..a29ad5d 100644
--- a/inc/version.h
+++ b/inc/version.h
@@ -7,6 +7,6 @@
#define DISASM_VERSION_MAJOR 1
#define DISASM_VERSION_MINOR 34
-#define DISASM_VERSION_REVISION 5
+#define DISASM_VERSION_REVISION 7
#endif // DISASM_VER_H
diff --git a/isagenerator/instructions/table_0F.dat b/isagenerator/instructions/table_0F.dat
index 93cd187..ae0b214 100644
--- a/isagenerator/instructions/table_0F.dat
+++ b/isagenerator/instructions/table_0F.dat
@@ -22,7 +22,7 @@ LMSW Ew CR0 [ 0x0F 0x01 /6
INVLPG Mb nil [ 0x0F 0x01 /7:mem] s:I486REAL, t:SYSTEM, w:R, a:AG, m:KERNEL|NOV86
RSTORSSP Mq SSP [ 0xF3 0x0F 0x01 /5:mem] s:CET_SS, t:CET, a:SHS, w:RW|RW, f:CF=m|ZF=0|PF=0|AF=0|OF=0|SF=0
ENCLV nil EAX,RBX,RCX,RDX [ NP 0x0F 0x01 /0xC0] s:SGX, t:SGX, w:R|CRW|CRW|CRW, m:KERNEL|NOSMM|NOTSX|VMX
-VMCALL nil nil [ NP 0x0F 0x01 /0xC1] s:VTX, t:VTX, m:VMX|NOSGX
+VMCALL nil nil [ NP 0x0F 0x01 /0xC1] s:VTX, t:VTX, m:VMX|NOTSX|NOSGX
VMLAUNCH nil Fv [ NP 0x0F 0x01 /0xC2] s:VTX, t:VTX, w:W, f:VMX, m:VMXROOT
VMRESUME nil Fv [ NP 0x0F 0x01 /0xC3] s:VTX, t:VTX, w:W, f:VMX, m:VMXROOT
VMXOFF nil Fv [ NP 0x0F 0x01 /0xC4] s:VTX, t:VTX, w:W, f:VMX, m:VMXROOT
@@ -30,8 +30,8 @@ PCONFIG nil EAX,RBX,RCX,RDX [ NP 0x0F 0x01 /0
MONITOR nil pAXb,ECX,EDX [ NP 0x0F 0x01 /0xC8] s:SSE3, t:MISC, w:R|R|R, i:MONITOR, m:KERNEL|NOV86
MWAIT nil EAX,ECX [ NP 0x0F 0x01 /0xC9] s:SSE3, t:MISC, w:RW|R, i:MONITOR, m:KERNEL|NOV86
CLAC nil Fv [ NP 0x0F 0x01 /0xCA] s:SMAP, t:SMAP, w:W, f:AC=0, m:KERNEL|NOV86
-ERETU nil rIP,Fv,rSP,CS,SS,Kv5,SSP,GSBASE,KGSBASE [0xF3 0x0F 0x01 /0xCA] s:FRED, t:FRED, w:W|W|W|W|W|R|CRCW|RW|RW, m:KERNEL|O64|NOTSX, a:F64
-ERETS nil rIP,Fv,rSP,Kv5,SSP [ 0xF2 0x0F 0x01 /0xCA] s:FRED, t:FRED, w:W|W|W|R|CRCW, m:KERNEL|O64|NOTSX, a:F64
+ERETU nil rIP,Fv,rSP,CS,SS,Kv5,SSP,GSBASE,KGSBASE [0xF3 0x0F 0x01 /0xCA] s:FRED, t:RET, w:W|W|W|W|W|R|CRCW|RW|RW, m:KERNEL|O64|NOTSX, a:F64
+ERETS nil rIP,Fv,rSP,Kv5,SSP [ 0xF2 0x0F 0x01 /0xCA] s:FRED, t:RET, w:W|W|W|R|CRCW, m:KERNEL|O64|NOTSX, a:F64
STAC nil Fv [ NP 0x0F 0x01 /0xCB] s:SMAP, t:SMAP, w:W, f:AC=1, m:KERNEL|NOV86
TDCALL nil nil [ 0x66 0x0F 0x01 /0xCC] s:TDX, t:TDX, m:KERNEL|VMXNROOT
SEAMRET nil nil [ 0x66 0x0F 0x01 /0xCD] s:TDX, t:TDX, f:VMX, m:SEAMR
@@ -41,7 +41,7 @@ ENCLS nil EAX,RBX,RCX,RDX [ NP 0x0F 0x01 /0
XGETBV nil ECX,EDX,EAX,XCR [ NP 0x0F 0x01 /0xD0] s:XSAVE, t:XSAVE, w:R|W|W|R
XSETBV nil ECX,EDX,EAX,XCR [ NP 0x0F 0x01 /0xD1] s:XSAVE, t:XSAVE, w:R|R|R|W, m:KERNEL
VMFUNC nil nil [ NP 0x0F 0x01 /0xD4] s:VTX, t:VTX, m:VMX|NOSGX
-XEND nil nil [ NP 0x0F 0x01 /0xD5] s:TSX, t:COND_BR, i:RTM
+XEND nil yIP [ NP 0x0F 0x01 /0xD5] s:TSX, t:COND_BR, w:CW, i:RTM
XTEST nil Fv [ NP 0x0F 0x01 /0xD6] s:TSX, t:LOGIC, w:W, i:RTM, f:CF=0|PF=0|AF=0|ZF=m|SF=0|OF=0
ENCLU nil EAX,RBX,RCX,RDX [ NP 0x0F 0x01 /0xD7] s:SGX, t:SGX, w:R|CRW|CRW|CRW, m:USER|NOSMM|NOTSX
VMRUN nil rAX [ 0x0F 0x01 /0xD8] s:SVM, t:SYSTEM, w:R, m:VMXROOT
@@ -60,7 +60,7 @@ SETSSBSY nil SHS0,SSP [ 0xF3 0x0F 0x01 /0
XSUSLDTRK nil nil [ 0xF2 0x0F 0x01 /0xE8] s:TSXLDTRK, t:MISC
XRESLDTRK nil nil [ 0xF2 0x0F 0x01 /0xE9] s:TSXLDTRK, t:MISC
SAVEPREVSSP nil SHSS,SSP [ 0xF3 0x0F 0x01 /0xEA] s:CET_SS, t:CET, w:RW|R, f:CF=t
-UIRET nil rIP,Fv,sSP,UIF,Kv3,SHS1 [ 0xF3 0x0F 0x01 /0xEC] s:UINTR, t:UINTR, a:F64, w:W|W|W|W|R|R, m:O64|NOTSX|NOSGX
+UIRET nil rIP,Fv,sSP,UIF,Kv3,SHS1 [ 0xF3 0x0F 0x01 /0xEC] s:UINTR, t:RET, a:F64, w:W|W|W|W|R|R, m:O64|NOTSX|NOSGX
TESTUI nil UIF,Fv [ 0xF3 0x0F 0x01 /0xED] s:UINTR, t:UINTR, w:R|W, f:UINTR, m:O64|NOSGX
RDPKRU nil EDX,EAX,ECX,PKRU [ NP 0x0F 0x01 /0xEE] s:PKU, t:MISC, w:W|W|R|R
CLUI nil UIF [ 0xF3 0x0F 0x01 /0xEE] s:UINTR, t:UINTR, w:W, m:O64|NOTSX|NOSGX
diff --git a/isagenerator/instructions/table_base.dat b/isagenerator/instructions/table_base.dat
index 20faaa7..9bb00a9 100644
--- a/isagenerator/instructions/table_base.dat
+++ b/isagenerator/instructions/table_base.dat
@@ -331,7 +331,7 @@ RETN nil rIP,Kv,SHS1 [ 0xC3] s:I86
LES Gz,Mp ES [ 0xC4 /r:mem] s:I86, t:SEGOP, w:W|R|W, m:NO64|NOSGX
LDS Gz,Mp DS [ 0xC5 /r:mem] s:I86, t:SEGOP, w:W|R|W, m:NO64|NOSGX
MOV Eb,Ib nil [ 0xC6 /0 ib] s:I86, t:DATAXFER, w:W|R, p:XRELEASE|HLEWOL
-XABORT Ib EAX [ 0xC6 /0xF8 ib] s:TSX, t:UNCOND_BR, w:R|RCW, i:RTM, m:NOTSX
+XABORT Ib yIP,EAX [ 0xC6 /0xF8 ib] s:TSX, t:UNCOND_BR, w:R|W|RCW, i:RTM
MOV Ev,Iz nil [ 0xC7 /0 iz] s:I86, t:DATAXFER, w:W|R, a:OP2SEXO1, p:XRELEASE|HLEWOL
XBEGIN Jz yIP,EAX [ 0xC7 /0xF8 cz] s:TSX, t:COND_BR, w:R|RCW|CW, i:RTM
ENTER Iw,Ib rBP,sSP,Kv [ 0xC8 iw ib] s:I186, t:MISC, w:R|R|RW|RW|W, a:D64