Bugfixes and Support for some more registers

Zydis:
- Fixed operand-size of some instructions in 64-bit mode
- Fixed operand decoding of the "movq MM, GPR" instruction
- Added table-registers (GDRT, LDTR, IDTR, TR)
- Added test-registers (TR0..TR7)
- Added BNDCFG and BNDSTATUS registers
- Added MXCR register

InstructionEditor:
- The code-generator now eliminates duplicate instruction-definitions to optimize the size of the generated tables
- Fixed conflict indication for some operand type/encoding combinations
- Added conflict indication for X86Flags
This commit is contained in:
flobernd 2016-11-14 02:10:59 +01:00
parent 3f09ffca69
commit 58c73b2885
16 changed files with 108007 additions and 105986 deletions

View File

@ -142,11 +142,17 @@ begin
VirtualTreeView.Expanded[N1] := true; VirtualTreeView.Expanded[N1] := true;
N1 := AddCategory(Root, 'Special Registers'); N1 := AddCategory(Root, 'Special Registers');
AddRegisterRange(N1, regRFLAGS, regIP); AddRegisterRange(N1, regRFLAGS, regMXCSR);
N1 := AddCategory(Root, 'Segment Registers'); N1 := AddCategory(Root, 'Segment Registers');
AddRegisterRange(N1, regES, regFS); AddRegisterRange(N1, regES, regFS);
N1 := AddCategory(Root, 'Table Registers');
AddRegisterRange(N1, regGDTR, regTR);
N1 := AddCategory(Root, 'Test Registers');
AddRegisterRange(N1, regTR0, regTR7);
N1 := AddCategory(Root, 'Control Registers'); N1 := AddCategory(Root, 'Control Registers');
AddRegisterRange(N1, regCR0, regCR15); AddRegisterRange(N1, regCR0, regCR15);
@ -157,7 +163,7 @@ begin
AddRegisterRange(N1, regK0, regK7); AddRegisterRange(N1, regK0, regK7);
N1 := AddCategory(Root, 'Bound Registers'); N1 := AddCategory(Root, 'Bound Registers');
AddRegisterRange(N1, regBND0, regBND3); AddRegisterRange(N1, regBND0, regBNDSTATUS);
VirtualTreeView.Expanded[Root] := true; VirtualTreeView.Expanded[Root] := true;
finally finally

View File

@ -188,27 +188,12 @@
<Overwrite>true</Overwrite> <Overwrite>true</Overwrite>
</Platform> </Platform>
</DeployFile> </DeployFile>
<DeployClass Name="DependencyModule"> <DeployClass Name="ProjectiOSDeviceResourceRules">
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.dll;.bpl</Extensions>
</Platform>
<Platform Name="iOSDevice64"> <Platform Name="iOSDevice64">
<Operation>1</Operation> <Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform> </Platform>
<Platform Name="iOSDevice32"> <Platform Name="iOSDevice32">
<Operation>1</Operation> <Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="ProjectOSXResource"> <DeployClass Name="ProjectOSXResource">
@ -560,12 +545,27 @@
<Operation>1</Operation> <Operation>1</Operation>
</Platform> </Platform>
</DeployClass> </DeployClass>
<DeployClass Name="ProjectiOSDeviceResourceRules"> <DeployClass Name="DependencyModule">
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.dll;.bpl</Extensions>
</Platform>
<Platform Name="iOSDevice64"> <Platform Name="iOSDevice64">
<Operation>1</Operation> <Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform> </Platform>
<Platform Name="iOSDevice32"> <Platform Name="iOSDevice32">
<Operation>1</Operation> <Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform> </Platform>
</DeployClass> </DeployClass>
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/> <ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>

View File

@ -33,7 +33,7 @@ dxSkinOffice2013DarkGray=0
dxSkinOffice2013LightGray=0 dxSkinOffice2013LightGray=0
dxSkinOffice2013White=0 dxSkinOffice2013White=0
dxSkinPumpkin=0 dxSkinPumpkin=0
dxSkinSeven=1 dxSkinSeven=0
dxSkinSevenClassic=0 dxSkinSevenClassic=0
dxSkinSharp=0 dxSkinSharp=0
dxSkinSharpPlus=0 dxSkinSharpPlus=0

View File

@ -172,8 +172,9 @@ procedure TCodeGenerator.CreateInstructionDefinitionList(Editor: TInstructionEdi
var DefinitionList: TIndexedInstructionDefinitionList; var InstructionDefinitionCount: Integer; var DefinitionList: TIndexedInstructionDefinitionList; var InstructionDefinitionCount: Integer;
var InstructionDefinitionSize: Cardinal); var InstructionDefinitionSize: Cardinal);
var var
I: Integer;
List: TList<TInstructionDefinition>; List: TList<TInstructionDefinition>;
I, J: Integer;
B: Boolean;
Comparison: TComparison<TInstructionDefinition>; Comparison: TComparison<TInstructionDefinition>;
begin begin
List := TList<TInstructionDefinition>.Create; List := TList<TInstructionDefinition>.Create;
@ -181,7 +182,19 @@ begin
WorkStart('Indexing instruction definitions', 0, Editor.DefinitionCount * 2); WorkStart('Indexing instruction definitions', 0, Editor.DefinitionCount * 2);
for I := 0 to Editor.DefinitionCount - 1 do for I := 0 to Editor.DefinitionCount - 1 do
begin begin
List.Add(Editor.Definitions[I]); B := false;
for J := 0 to List.Count - 1 do
begin
if (Editor.Definitions[I].Equals(List[J], false, false)) then
begin
B := true;
Break;
end;
end;
if (not B) then
begin
List.Add(Editor.Definitions[I]);
end;
Work(I + 1); Work(I + 1);
end; end;
Comparison := Comparison :=

View File

@ -201,51 +201,55 @@ type
TX86Register = ( TX86Register = (
regNone, regNone,
// General purpose registers 64-bit // General purpose registers 64-bit
regRAX, regRCX, regRDX, regRBX, regRSP, regRBP, regRSI, regRDI, regRAX, regRCX, regRDX, regRBX, regRSP, regRBP, regRSI, regRDI,
regR8, regR9, regR10, regR11, regR12, regR13, regR14, regR15, regR8, regR9, regR10, regR11, regR12, regR13, regR14, regR15,
// General purpose registers 32-bit // General purpose registers 32-bit
regEAX, regECX, regEDX, regEBX, regESP, regEBP, regESI, regEDI, regEAX, regECX, regEDX, regEBX, regESP, regEBP, regESI, regEDI,
regR8D, regr9D, regR10D, regR11D, regR12D, regR13D, regR14D, regR15D, regR8D, regr9D, regR10D, regR11D, regR12D, regR13D, regR14D, regR15D,
// General purpose registers 16-bit // General purpose registers 16-bit
regAX, regCX, regDX, regBX, regSP, regBP, regSI, regDI, regAX, regCX, regDX, regBX, regSP, regBP, regSI, regDI,
regR8W, regR9W, regR10W, regR11W, regR12W, regR13W, regR14W, regR15W, regR8W, regR9W, regR10W, regR11W, regR12W, regR13W, regR14W, regR15W,
// General purpose registers 8-bit // General purpose registers 8-bit
regAL, regCL, regDL, regBL, regAH, regCH, regDH, regBH, regAL, regCL, regDL, regBL, regAH, regCH, regDH, regBH,
regSPL, regBPL, regSIL, regDIL, regSPL, regBPL, regSIL, regDIL,
regR8B, regR9B, regR10B, regR11B, regR12B, regR13B, regR14B, regR15B, regR8B, regR9B, regR10B, regR11B, regR12B, regR13B, regR14B, regR15B,
// Floating point legacy registers // Floating point legacy registers
regST0, regST1, regST2, regST3, regST4, regST5, regST6, regST7, regST0, regST1, regST2, regST3, regST4, regST5, regST6, regST7,
// Floating point multimedia registers // Floating point multimedia registers
regMM0, regMM1, regMM2, regMM3, regMM4, regMM5, regMM6, regMM7, regMM0, regMM1, regMM2, regMM3, regMM4, regMM5, regMM6, regMM7,
// Floating point vector registers 512-bit // Floating point vector registers 512-bit
regZMM0, regZMM1, regZMM2, regZMM3, regZMM4, regZMM5, regZMM6, regZMM7, regZMM0, regZMM1, regZMM2, regZMM3, regZMM4, regZMM5, regZMM6, regZMM7,
regZMM8, regZMM9, regZMM10, regZMM11, regZMM12, regZMM13, regZMM14, regZMM15, regZMM8, regZMM9, regZMM10, regZMM11, regZMM12, regZMM13, regZMM14, regZMM15,
regZMM16, regZMM17, regZMM18, regZMM19, regZMM20, regZMM21, regZMM22, regZMM23, regZMM16, regZMM17, regZMM18, regZMM19, regZMM20, regZMM21, regZMM22, regZMM23,
regZMM24, regZMM25, regZMM26, regZMM27, regZMM28, regZMM29, regZMM30, regZMM31, regZMM24, regZMM25, regZMM26, regZMM27, regZMM28, regZMM29, regZMM30, regZMM31,
// Floating point vector registers 256-bit // Floating point vector registers 256-bit
regYMM0, regYMM1, regYMM2, regYMM3, regYMM4, regYMM5, regYMM6, regYMM7, regYMM0, regYMM1, regYMM2, regYMM3, regYMM4, regYMM5, regYMM6, regYMM7,
regYMM8, regYMM9, regYMM10, regYMM11, regYMM12, regYMM13, regYMM14, regYMM15, regYMM8, regYMM9, regYMM10, regYMM11, regYMM12, regYMM13, regYMM14, regYMM15,
regYMM16, regYMM17, regYMM18, regYMM19, regYMM20, regYMM21, regYMM22, regYMM23, regYMM16, regYMM17, regYMM18, regYMM19, regYMM20, regYMM21, regYMM22, regYMM23,
regYMM24, regYMM25, regYMM26, regYMM27, regYMM28, regYMM29, regYMM30, regYMM31, regYMM24, regYMM25, regYMM26, regYMM27, regYMM28, regYMM29, regYMM30, regYMM31,
// Floating point vector registers 128-bit // Floating point vector registers 128-bit
regXMM0, regXMM1, regXMM2, regXMM3, regXMM4, regXMM5, regXMM6, regXMM7, regXMM0, regXMM1, regXMM2, regXMM3, regXMM4, regXMM5, regXMM6, regXMM7,
regXMM8, regXMM9, regXMM10, regXMM11, regXMM12, regXMM13, regXMM14, regXMM15, regXMM8, regXMM9, regXMM10, regXMM11, regXMM12, regXMM13, regXMM14, regXMM15,
regXMM16, regXMM17, regXMM18, regXMM19, regXMM20, regXMM21, regXMM22, regXMM23, regXMM16, regXMM17, regXMM18, regXMM19, regXMM20, regXMM21, regXMM22, regXMM23,
regXMM24, regXMM25, regXMM26, regXMM27, regXMM28, regXMM29, regXMM30, regXMM31, regXMM24, regXMM25, regXMM26, regXMM27, regXMM28, regXMM29, regXMM30, regXMM31,
// Special registers // Special registers
regRFLAGS, regEFLAGS, regFLAGS, regRIP, regEIP, regIP, regRFLAGS, regEFLAGS, regFLAGS, regRIP, regEIP, regIP, regMXCSR,
// Segment registers // Segment registers
regES, regCS, regSS, regDS, regGS, regFS, regES, regCS, regSS, regDS, regGS, regFS,
// Table registers
regGDTR, regLDTR, regIDTR, regTR,
// Test registers
regTR0, regTR1, regTR2, regTR3, regTR4, regTR5, regTR6, regTR7,
// Control registers // Control registers
regCR0, regCR1, regCR2, regCR3, regCR4, regCR5, regCR6, regCR7, regCR0, regCR1, regCR2, regCR3, regCR4, regCR5, regCR6, regCR7,
regCR8, regCR9, regCR10, regCR11, regCR12, regCR13, regCR14, regCR15, regCR8, regCR9, regCR10, regCR11, regCR12, regCR13, regCR14, regCR15,
// Debug registers // Debug registers
regDR0, regDR1, regDR2, regDR3, regDR4, regDR5, regDR6, regDR7, regDR0, regDR1, regDR2, regDR3, regDR4, regDR5, regDR6, regDR7,
regDR8, regDR9, regDR10, regDR11, regDR12, regDR13, regDR14, regDR15, regDR8, regDR9, regDR10, regDR11, regDR12, regDR13, regDR14, regDR15,
// Mask registers // Mask registers
regK0, regK1, regK2, regK3, regK4, regK5, regK6, regK7, regK0, regK1, regK2, regK3, regK4, regK5, regK6, regK7,
// Bounds registers // Bounds registers
regBND0, regBND1, regBND2, regBND3 regBND0, regBND1, regBND2, regBND3, regBNDCFG, regBNDSTATUS
); );
TX86RegisterSet = set of TX86Register; TX86RegisterSet = set of TX86Register;
@ -318,7 +322,9 @@ type
procedure SetID(const Value: TX86FlagValue); inline; procedure SetID(const Value: TX86FlagValue); inline;
strict private strict private
procedure Changed; inline; procedure Changed; inline;
private strict private
function GetConflictState: Boolean;
public // TODO: Make private again
procedure LoadFromJSON(JSON: PJSONVariantData; const FieldName: String); procedure LoadFromJSON(JSON: PJSONVariantData; const FieldName: String);
procedure SaveToJSON(JSON: PJSONVariantData; const FieldName: String); procedure SaveToJSON(JSON: PJSONVariantData; const FieldName: String);
protected protected
@ -327,6 +333,8 @@ type
constructor Create(Definition: TInstructionDefinition); constructor Create(Definition: TInstructionDefinition);
public public
function Equals(const Value: TX86Flags): Boolean; reintroduce; function Equals(const Value: TX86Flags): Boolean; reintroduce;
public
property HasConflicts: Boolean read GetConflictState;
published published
{ FLAGS } { FLAGS }
property FlagCF: TX86FlagValue read FCF write SetCF default fvUnused; property FlagCF: TX86FlagValue read FCF write SetCF default fvUnused;
@ -532,7 +540,10 @@ type
// This conflict is enforced by the user // This conflict is enforced by the user
idcForcedConflict, idcForcedConflict,
// The instruction-operands configuration is invalid // The instruction-operands configuration is invalid
idcOperands idcOperands,
// The FLAGS/EFLAGS/RFLAGS registers in the ImplicitRead or ImplicitWrite property do not
// match the given X86Flags configuration
idcX86Flags
); );
TInstructionDefinitionConflicts = set of TInstructionDefinitionConflict; TInstructionDefinitionConflicts = set of TInstructionDefinitionConflict;
@ -562,6 +573,7 @@ type
ifAcceptsREP, ifAcceptsREP,
ifAcceptsXACQUIRE, ifAcceptsXACQUIRE,
ifAcceptsXRELEASE, ifAcceptsXRELEASE,
ifAcceptsBranchHints,
ifAcceptsEVEXAAA, ifAcceptsEVEXAAA,
ifAcceptsEVEXZ, ifAcceptsEVEXZ,
ifIsPrivileged, ifIsPrivileged,
@ -616,7 +628,8 @@ type
procedure EndUpdate; inline; procedure EndUpdate; inline;
public public
function Equals(const Value: TInstructionDefinition; function Equals(const Value: TInstructionDefinition;
const CheckComment: Boolean = false): Boolean; reintroduce; CheckComment: Boolean = false;
CheckFilterRelatedAttributes: Boolean = true): Boolean; reintroduce;
public public
procedure LoadFromJSON(JSON: PJSONVariantData); procedure LoadFromJSON(JSON: PJSONVariantData);
procedure SaveToJSON(JSON: PJSONVariantData); procedure SaveToJSON(JSON: PJSONVariantData);
@ -1022,9 +1035,13 @@ const
'xmm16', 'xmm17', 'xmm18', 'xmm19', 'xmm20', 'xmm21', 'xmm22', 'xmm23', 'xmm16', 'xmm17', 'xmm18', 'xmm19', 'xmm20', 'xmm21', 'xmm22', 'xmm23',
'xmm24', 'xmm25', 'xmm26', 'xmm27', 'xmm28', 'xmm29', 'xmm30', 'xmm31', 'xmm24', 'xmm25', 'xmm26', 'xmm27', 'xmm28', 'xmm29', 'xmm30', 'xmm31',
// Special registers // Special registers
'rflags', 'eflags', 'flags', 'rip', 'eip', 'ip', 'rflags', 'eflags', 'flags', 'rip', 'eip', 'ip', 'mxcsr',
// Segment registers // Segment registers
'es', 'cs', 'ss', 'ds', 'gs', 'fs', 'es', 'cs', 'ss', 'ds', 'gs', 'fs',
// Table registers
'gdtr', 'ldtr', 'idtr', 'tr',
// Test registers
'tr0', 'tr1', 'tr2', 'tr3', 'tr4', 'tr5', 'tr6', 'tr7',
// Control registers // Control registers
'cr0', 'cr1', 'cr2', 'cr3', 'cr4', 'cr5', 'cr6', 'cr7', 'cr0', 'cr1', 'cr2', 'cr3', 'cr4', 'cr5', 'cr6', 'cr7',
'cr8', 'cr9', 'cr10', 'cr11', 'cr12', 'cr13', 'cr14', 'cr15', 'cr8', 'cr9', 'cr10', 'cr11', 'cr12', 'cr13', 'cr14', 'cr15',
@ -1034,7 +1051,7 @@ const
// Mask registers // Mask registers
'k0', 'k1', 'k2', 'k3', 'k4', 'k5', 'k6', 'k7', 'k0', 'k1', 'k2', 'k3', 'k4', 'k5', 'k6', 'k7',
// Bounds registers // Bounds registers
'bnd0', 'bnd1', 'bnd2', 'bnd3' 'bnd0', 'bnd1', 'bnd2', 'bnd3', 'bndcfg', 'bndstatus'
); );
{$ENDREGION} {$ENDREGION}
@ -1191,6 +1208,7 @@ const
'accepts_rep', 'accepts_rep',
'accepts_xacquire', 'accepts_xacquire',
'accepts_xrelease', 'accepts_xrelease',
'accepts_branch_hints',
'accepts_evex_aaa', 'accepts_evex_aaa',
'accepts_evex_z', 'accepts_evex_z',
'privileged', 'privileged',
@ -1648,6 +1666,9 @@ constructor TX86Flags.Create(Definition: TInstructionDefinition);
begin begin
inherited Create; inherited Create;
FDefinition := Definition; FDefinition := Definition;
// NOTE: Some instructions clear all flags in the FLAGS/EFLAGS/RFLAGS register except some.
// If you add a new flag field to this struct, you have to set it to fvReset for all these
// instructions
end; end;
function TX86Flags.Equals(const Value: TX86Flags): Boolean; function TX86Flags.Equals(const Value: TX86Flags): Boolean;
@ -1658,6 +1679,58 @@ begin
(Value.FAC = FAC) and (Value.FVIF = FVIF) and (Value.FVIP = FVIP) and (Value.FID = FID); (Value.FAC = FAC) and (Value.FVIF = FVIF) and (Value.FVIP = FVIP) and (Value.FID = FID);
end; end;
function TX86Flags.GetConflictState: Boolean;
var
F: array[0..14] of ^TX86FlagValue;
I: Integer;
RegsRead,
RegsWrite: TX86RegisterSet;
R: TX86Register;
begin
Exit(false); // TODO: Remove
Result := false;
F[ 0] := @FCF; F[ 1] := @FPF; F[ 2] := @FAF; F[ 3] := @FZF; F[ 4] := @FSF;
F[ 5] := @FTF; F[ 6] := @FIF; F[ 7] := @FDF; F[ 8] := @FOF; F[ 9] := @FRF;
F[10] := @FVM; F[11] := @FAC; F[12] := @FVIF; F[13] := @FVIP; F[14] := @FID;
RegsRead := [];
RegsWrite := [];
for I := Low(F) to High(F) do
begin
if (F[I]^ in [fvTested]) then
begin
if (I < 9) then
begin
// These flags are in the FLAGS register
Include(RegsRead, regFLAGS);
end else
begin
// These flags are in the EFLAGS register
Include(RegsRead, regEFLAGS);
end;
end;
if (F[I]^ in [fvModified, fvReset, fvSet, fvUndefined, fvPriorValue]) then
begin
if (I < 9) then
begin
// These flags are in the FLAGS register
Include(RegsWrite, regFLAGS);
end else
begin
// These flags are in the EFLAGS register
Include(RegsWrite, regEFLAGS);
end;
end;
end;
for R := regRFLAGS to regFLAGS do
begin
if ((R in RegsRead) xor (R in FDefinition.ImplicitRead.Registers)) or
((R in RegsWrite) xor (R in FDefinition.ImplicitWrite.Registers)) then
begin
Exit(true);
end;
end;
end;
procedure TX86Flags.LoadFromJSON(JSON: PJSONVariantData; const FieldName: String); procedure TX86Flags.LoadFromJSON(JSON: PJSONVariantData; const FieldName: String);
var var
C: PJSONVariantData; C: PJSONVariantData;
@ -1961,11 +2034,11 @@ begin
optRel8: optRel8:
Result := not (FEncoding in [opeImm8]); Result := not (FEncoding in [opeImm8]);
optRel16: optRel16:
Result := not (FEncoding in [opeImm16]); Result := not (FEncoding in [opeImm8, opeImm16]);
optRel32: optRel32:
Result := not (FEncoding in [opeImm32]); Result := not (FEncoding in [opeImm8, opeImm32]);
optRel64: optRel64:
Result := not (FEncoding in [opeImm64]); Result := not (FEncoding in [opeImm8, opeImm32, opeImm64]);
optPtr1616, optPtr1616,
optPtr1632, optPtr1632,
optPtr1664, optPtr1664,
@ -2379,36 +2452,7 @@ begin
end; end;
procedure TInstructionOperands.Changed; procedure TInstructionOperands.Changed;
{var
A: array[0..3] of TInstructionOperand;
I, J: Integer;
begin begin
FHasConflicts := false;
// Check for invalid operand order
A[0] := FOperandA; A[1] := FOperandB; A[2] := FOperandC; A[3] := FOperandD;
for I := High(A) downto Low(A) do
begin
if (A[I].OperandType <> otUnused) then
begin
for J := I downto Low(A) do
begin
if (A[J].OperandType = otUnused) then
begin
FHasConflicts := true;
Break;
end;
end;
end;
if (FHasConflicts) then
begin
Break;
end;
end; }
begin
// TODO: Determine Encoding
FDefinition.UpdateValues; FDefinition.UpdateValues;
end; end;
@ -2451,6 +2495,32 @@ var
I: Integer; I: Integer;
EncReg, EncRm, EncVVVV, EncAAA: Integer; EncReg, EncRm, EncVVVV, EncAAA: Integer;
begin begin
{var
A: array[0..3] of TInstructionOperand;
I, J: Integer;
begin
FHasConflicts := false;
// Check for invalid operand order
A[0] := FOperandA; A[1] := FOperandB; A[2] := FOperandC; A[3] := FOperandD;
for I := High(A) downto Low(A) do
begin
if (A[I].OperandType <> otUnused) then
begin
for J := I downto Low(A) do
begin
if (A[J].OperandType = otUnused) then
begin
FHasConflicts := true;
Break;
end;
end;
end;
if (FHasConflicts) then
begin
Break;
end;
end; }
Result := false; Result := false;
for I := Low(FOperands) to High(FOperands) do for I := Low(FOperands) to High(FOperands) do
begin begin
@ -2638,14 +2708,14 @@ begin
end; end;
function TInstructionDefinition.Equals(const Value: TInstructionDefinition; function TInstructionDefinition.Equals(const Value: TInstructionDefinition;
const CheckComment: Boolean): Boolean; CheckComment: Boolean; CheckFilterRelatedAttributes: Boolean): Boolean;
begin begin
Result := Result :=
(Value.FMnemonic = FMnemonic) and (Value.FEncoding = FEncoding) and (Value.FMnemonic = FMnemonic) and ((not CheckFilterRelatedAttributes) or
(Value.FOpcodeMap = FOpcodeMap) and (Value.FOpcode = FOpcode) and ((Value.FEncoding = FEncoding) and (Value.FOpcodeMap = FOpcodeMap) and
(Value.FExtensions.Equals(FExtensions)) and (Value.FCPUID.Equals(FCPUID)) and (Value.FOpcode = FOpcode) and (Value.FExtensions.Equals(FExtensions)))) and
(Value.FOperands.Equals(FOperands)) and (Value.FFlags = FFlags) and (Value.FCPUID.Equals(FCPUID)) and (Value.FOperands.Equals(FOperands)) and
(Value.FEVEXCD8Scale = FEVEXCD8Scale) and (Value.FFlags = FFlags) and (Value.FEVEXCD8Scale = FEVEXCD8Scale) and
(Value.FImplicitRead.Equals(FImplicitRead)) and (Value.FImplicitRead.Equals(FImplicitRead)) and
(Value.FImplicitWrite.Equals(FImplicitWrite)) and (Value.FX86Flags.Equals(FX86Flags)) and (Value.FImplicitWrite.Equals(FImplicitWrite)) and (Value.FX86Flags.Equals(FX86Flags)) and
((not CheckComment) or (Value.FComment = FComment)); ((not CheckComment) or (Value.FComment = FComment));
@ -2889,8 +2959,10 @@ begin
begin begin
Include(Conflicts, idcOperands); Include(Conflicts, idcOperands);
end; end;
// TODO: Check for X86Flag conflicts if (FX86Flags.HasConflicts) then
// [ ] EFLAGS in ImplicitRead / ImplicitWrite required or forbidden begin
Include(Conflicts, idcX86Flags);
end;
// TODO: Check for more conflicts // TODO: Check for more conflicts
if (FConflicts <> Conflicts) then if (FConflicts <> Conflicts) then
begin begin
@ -3239,20 +3311,20 @@ begin
FilterOrderDef[ 0] := TModrmModFilter; FilterOrderDef[ 0] := TModrmModFilter;
FilterOrderDef[ 1] := TModrmRegFilter; FilterOrderDef[ 1] := TModrmRegFilter;
FilterOrderDef[ 2] := TModrmRmFilter; FilterOrderDef[ 2] := TModrmRmFilter;
FilterOrderDef[ 3] := TRexWFilter; FilterOrderDef[ 3] := TModeFilter;
FilterOrderDef[ 4] := TOperandSizeFilter; FilterOrderDef[ 4] := TRexWFilter;
FilterOrderDef[ 5] := TAddressSizeFilter; FilterOrderDef[ 5] := TOperandSizeFilter;
FilterOrderDef[ 6] := TMandatoryPrefixFilter; FilterOrderDef[ 6] := TAddressSizeFilter;
FilterOrderDef[ 7] := TModeFilter; FilterOrderDef[ 7] := TMandatoryPrefixFilter;
// Specialized filter order for XOP instruction encoding // Specialized filter order for XOP instruction encoding
SetLength(FilterOrderXOP, 8); SetLength(FilterOrderXOP, 8);
FilterOrderXOP[ 0] := TModrmModFilter; FilterOrderXOP[ 0] := TModrmModFilter;
FilterOrderXOP[ 1] := TModrmRegFilter; FilterOrderXOP[ 1] := TModrmRegFilter;
FilterOrderXOP[ 2] := TModrmRmFilter; FilterOrderXOP[ 2] := TModrmRmFilter;
FilterOrderXOP[ 3] := TRexWFilter; FilterOrderXOP[ 3] := TModeFilter;
FilterOrderXOP[ 4] := TOperandSizeFilter; FilterOrderXOP[ 4] := TRexWFilter;
FilterOrderXOP[ 5] := TAddressSizeFilter; FilterOrderXOP[ 5] := TOperandSizeFilter;
FilterOrderXOP[ 6] := TModeFilter; FilterOrderXOP[ 6] := TAddressSizeFilter;
FilterOrderXOP[ 7] := TVexLFilter; FilterOrderXOP[ 7] := TVexLFilter;
// Specialized filter order for VEX instruction encoding // Specialized filter order for VEX instruction encoding
SetLength(FilterOrderVEX, 9); SetLength(FilterOrderVEX, 9);
@ -3260,10 +3332,10 @@ begin
FilterOrderVEX[ 1] := TModrmModFilter; FilterOrderVEX[ 1] := TModrmModFilter;
FilterOrderVEX[ 2] := TModrmRegFilter; FilterOrderVEX[ 2] := TModrmRegFilter;
FilterOrderVEX[ 3] := TModrmRmFilter; FilterOrderVEX[ 3] := TModrmRmFilter;
FilterOrderVEX[ 4] := TRexWFilter; FilterOrderVEX[ 4] := TModeFilter;
FilterOrderVEX[ 5] := TOperandSizeFilter; FilterOrderVEX[ 5] := TRexWFilter;
FilterOrderVEX[ 6] := TAddressSizeFilter; FilterOrderVEX[ 6] := TOperandSizeFilter;
FilterOrderVEX[ 7] := TModeFilter; FilterOrderVEX[ 7] := TAddressSizeFilter;
FilterOrderVEX[ 8] := TVexLFilter; FilterOrderVEX[ 8] := TVexLFilter;
// Specialized filter order for EVEX instruction encoding // Specialized filter order for EVEX instruction encoding
SetLength(FilterOrderEVEX, 11); SetLength(FilterOrderEVEX, 11);
@ -3271,10 +3343,10 @@ begin
FilterOrderEVEX[ 1] := TModrmModFilter; FilterOrderEVEX[ 1] := TModrmModFilter;
FilterOrderEVEX[ 2] := TModrmRegFilter; FilterOrderEVEX[ 2] := TModrmRegFilter;
FilterOrderEVEX[ 3] := TModrmRmFilter; FilterOrderEVEX[ 3] := TModrmRmFilter;
FilterOrderEVEX[ 4] := TRexWFilter; FilterOrderEVEX[ 4] := TModeFilter;
FilterOrderEVEX[ 5] := TOperandSizeFilter; FilterOrderEVEX[ 5] := TRexWFilter;
FilterOrderEVEX[ 6] := TAddressSizeFilter; FilterOrderEVEX[ 6] := TOperandSizeFilter;
FilterOrderEVEX[ 7] := TModeFilter; FilterOrderEVEX[ 7] := TAddressSizeFilter;
FilterOrderEVEX[ 8] := TEvexBFilter; FilterOrderEVEX[ 8] := TEvexBFilter;
FilterOrderEVEX[ 9] := TVexLFilter; FilterOrderEVEX[ 9] := TVexLFilter;
FilterOrderEVEX[10] := TEvexL2Filter; FilterOrderEVEX[10] := TEvexL2Filter;

File diff suppressed because it is too large Load Diff

View File

@ -139,136 +139,144 @@ typedef uint32_t ZydisPrefixFlags;
/** /**
* @brief The instruction has the rex-prefix (0x40 - 0x4F). * @brief The instruction has the rex-prefix (0x40 - 0x4F).
*/ */
#define ZYDIS_PREFIX_REX 0x00000001 #define ZYDIS_PREFIX_REX 0x00000001
/** /**
* @brief The instruction has the xop-prefix (0x8F). * @brief The instruction has the xop-prefix (0x8F).
*/ */
#define ZYDIS_PREFIX_XOP 0x00000002 #define ZYDIS_PREFIX_XOP 0x00000002
/** /**
* @brief The instruction has the vex-prefix (0xC4 or 0xC5). * @brief The instruction has the vex-prefix (0xC4 or 0xC5).
*/ */
#define ZYDIS_PREFIX_VEX 0x00000004 #define ZYDIS_PREFIX_VEX 0x00000004
/** /**
* @brief The instruction has the evex-prefix (0x62). * @brief The instruction has the evex-prefix (0x62).
*/ */
#define ZYDIS_PREFIX_EVEX 0x00000008 #define ZYDIS_PREFIX_EVEX 0x00000008
/** /**
* @brief The instruction has the lock-prefix (0x0F) * @brief The instruction has the lock-prefix (0x0F)
*/ */
#define ZYDIS_PREFIX_LOCK 0x00000010 #define ZYDIS_PREFIX_LOCK 0x00000010
/** /**
* @brief The instruction has the rep/repe/repz-prefix (0xF3) * @brief The instruction has the rep/repe/repz-prefix (0xF3)
*/ */
#define ZYDIS_PREFIX_REP 0x00000020 #define ZYDIS_PREFIX_REP 0x00000020
/** /**
* @brief The instruction has the rep/repe/repz-prefix (0xF3) * @brief The instruction has the rep/repe/repz-prefix (0xF3)
*/ */
#define ZYDIS_PREFIX_REPE 0x00000020 #define ZYDIS_PREFIX_REPE 0x00000020
/** /**
* @brief The instruction has the rep/repe/repz-prefix (0xF3) * @brief The instruction has the rep/repe/repz-prefix (0xF3)
*/ */
#define ZYDIS_PREFIX_REPZ 0x00000020 #define ZYDIS_PREFIX_REPZ 0x00000020
/** /**
* @brief The instruction has the repne/repnz-prefix (0xF2) * @brief The instruction has the repne/repnz-prefix (0xF2)
*/ */
#define ZYDIS_PREFIX_REPNE 0x00000040 #define ZYDIS_PREFIX_REPNE 0x00000040
/** /**
* @brief The instruction has the repne/repnz-prefix (0xF2) * @brief The instruction has the repne/repnz-prefix (0xF2)
*/ */
#define ZYDIS_PREFIX_REPNZ 0x00000040 #define ZYDIS_PREFIX_REPNZ 0x00000040
/** /**
* @brief The instruction has a segment-override prefix. * @brief The instruction has a segment-override prefix.
*/ */
#define ZYDIS_PREFIX_SEGMENT_MASK 0x00001F80 #define ZYDIS_PREFIX_SEGMENT_MASK 0x00001F80
/** /**
* @brief The instruction has the cs segment-override prefix (0x2E). * @brief The instruction has the cs segment-override prefix (0x2E).
*/ */
#define ZYDIS_PREFIX_SEGMENT_CS 0x00000080 #define ZYDIS_PREFIX_SEGMENT_CS 0x00000080
/** /**
* @brief The instruction has the ss segment-override prefix (0x36). * @brief The instruction has the ss segment-override prefix (0x36).
*/ */
#define ZYDIS_PREFIX_SEGMENT_SS 0x00000100 #define ZYDIS_PREFIX_SEGMENT_SS 0x00000100
/** /**
* @brief The instruction has the ds segment-override prefix (0x3E). * @brief The instruction has the ds segment-override prefix (0x3E).
*/ */
#define ZYDIS_PREFIX_SEGMENT_DS 0x00000200 #define ZYDIS_PREFIX_SEGMENT_DS 0x00000200
/** /**
* @brief The instruction has the es segment-override prefix (0x26). * @brief The instruction has the es segment-override prefix (0x26).
*/ */
#define ZYDIS_PREFIX_SEGMENT_ES 0x00000400 #define ZYDIS_PREFIX_SEGMENT_ES 0x00000400
/** /**
* @brief The instruction has the fs segment-override prefix (0x64). * @brief The instruction has the fs segment-override prefix (0x64).
*/ */
#define ZYDIS_PREFIX_SEGMENT_FS 0x00000800 #define ZYDIS_PREFIX_SEGMENT_FS 0x00000800
/** /**
* @brief The instruction has the gs segment-override prefix (0x65). * @brief The instruction has the gs segment-override prefix (0x65).
*/ */
#define ZYDIS_PREFIX_SEGMENT_GS 0x00001000 #define ZYDIS_PREFIX_SEGMENT_GS 0x00001000
/** /**
* @brief The instruction has the operand-size-override prefix (0x66). * @brief The instruction has the operand-size-override prefix (0x66).
*/ */
#define ZYDIS_PREFIX_OPERANDSIZE 0x00002000 #define ZYDIS_PREFIX_OPERANDSIZE 0x00002000
/** /**
* @brief The instruction has the address-size-override prefix (0x67). * @brief The instruction has the address-size-override prefix (0x67).
*/ */
#define ZYDIS_PREFIX_ADDRESSSIZE 0x00004000 #define ZYDIS_PREFIX_ADDRESSSIZE 0x00004000
/** /**
* @brief The instruction has the xacquire prefix (0xF2). * @brief The instruction has the xacquire prefix (0xF2).
*/ */
#define ZYDIS_PREFIX_XACQUIRE 0x00008000 #define ZYDIS_PREFIX_XACQUIRE 0x00008000
/** /**
* @brief The instruction has the xrelease prefix (0xF3). * @brief The instruction has the xrelease prefix (0xF3).
*/ */
#define ZYDIS_PREFIX_XRELEASE 0x00010000 #define ZYDIS_PREFIX_XRELEASE 0x00010000
/** /**
* @brief The instruction has the branch-not-taken hint (0x2E). * @brief The instruction has the branch-not-taken hint (0x2E).
*/ */
#define ZYDIS_PREFIX_BRANCH_NOT_TAKEN 0x00020000 #define ZYDIS_PREFIX_BRANCH_NOT_TAKEN 0x00020000
/** /**
* @brief The instruction has the branch-taken hint (0x3E). * @brief The instruction has the branch-taken hint (0x3E).
*/ */
#define ZYDIS_PREFIX_BRANCH_TAKEN 0x00040000 #define ZYDIS_PREFIX_BRANCH_TAKEN 0x00040000
/**
* @brief The instruction accepts the operand-size override prefix (0x66)
*/
#define ZYDIS_PREFIX_ACCEPTS_OPERANDSIZE 0x00080000
/**
* @brief The instruction accepts the adress-size override prefix (0x67)
*/
#define ZYDIS_PREFIX_ACCEPTS_ADDRESSSIZE 0x00100000
/** /**
* @brief The instruction accepts the lock-prefix. * @brief The instruction accepts the lock-prefix.
*/ */
#define ZYDIS_PREFIX_ACCEPTS_LOCK 0x00080000 #define ZYDIS_PREFIX_ACCEPTS_LOCK 0x00200000
/** /**
* @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz). * @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz).
*/ */
#define ZYDIS_PREFIX_ACCEPTS_REP 0x00100000 #define ZYDIS_PREFIX_ACCEPTS_REP 0x00400000
/** /**
* @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz). * @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz).
*/ */
#define ZYDIS_PREFIX_ACCEPTS_REPE 0x00100000 #define ZYDIS_PREFIX_ACCEPTS_REPE 0x00400000
/** /**
* @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz). * @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz).
*/ */
#define ZYDIS_PREFIX_ACCEPTS_REPZ 0x00100000 #define ZYDIS_PREFIX_ACCEPTS_REPZ 0x00400000
/** /**
* @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz). * @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz).
*/ */
#define ZYDIS_PREFIX_ACCEPTS_REPNE 0x00100000 #define ZYDIS_PREFIX_ACCEPTS_REPNE 0x00400000
/** /**
* @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz). * @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz).
*/ */
#define ZYDIS_PREFIX_ACCEPTS_REPNZ 0x00100000 #define ZYDIS_PREFIX_ACCEPTS_REPNZ 0x00400000
/** /**
* @brief The instruction has multiple prefixes of the first prefix-group (0x0F, 0xF3, 0xF2). * @brief The instruction has multiple prefixes of the first prefix-group (0x0F, 0xF3, 0xF2).
*/ */
#define ZYDIS_PREFIX_MULTIPLE_GRP1 0x01000000 #define ZYDIS_PREFIX_MULTIPLE_GRP1 0x00800000
/** /**
* @brief The instruction has multiple prefixes of the second prefix-group (0x2E, 0x36, * @brief The instruction has multiple prefixes of the second prefix-group (0x2E, 0x36,
* 0x3E, 0x26, 0x64, 0x65). * 0x3E, 0x26, 0x64, 0x65).
*/ */
#define ZYDIS_PREFIX_MULTIPLE_GRP2 0x02000000 #define ZYDIS_PREFIX_MULTIPLE_GRP2 0x01000000
/** /**
* @brief The instruction has multiple prefixes of the third prefix-group (0x66). * @brief The instruction has multiple prefixes of the third prefix-group (0x66).
*/ */
#define ZYDIS_PREFIX_MULTIPLE_GRP3 0x04000000 #define ZYDIS_PREFIX_MULTIPLE_GRP3 0x02000000
/** /**
* @brief The instruction has multiple prefixes of the fourth prefix-group (0x67). * @brief The instruction has multiple prefixes of the fourth prefix-group (0x67).
*/ */
#define ZYDIS_PREFIX_MULTIPLE_GRP4 0x08000000 #define ZYDIS_PREFIX_MULTIPLE_GRP4 0x04000000
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/* Instruction encoding */ /* Instruction encoding */
@ -537,6 +545,10 @@ typedef struct ZydisOperandInfo_
*/ */
struct struct
{ {
/**
* @brief The adress size (16, 32 or 64 bit).
*/
uint8_t addressSize;
/** /**
* @brief The segment register. * @brief The segment register.
*/ */
@ -649,7 +661,7 @@ typedef struct ZydisInstructionInfo_
/** /**
* @brief Prefix flags. * @brief Prefix flags.
*/ */
ZydisPrefixFlags prefixFlags; ZydisPrefixFlags prefixes;
/** /**
* @brief The instruction-mnemonic. * @brief The instruction-mnemonic.
*/ */
@ -682,14 +694,6 @@ typedef struct ZydisInstructionInfo_
* @brief Detailed info for all instruction operands. * @brief Detailed info for all instruction operands.
*/ */
ZydisOperandInfo operand[5]; ZydisOperandInfo operand[5];
/**
* @brief The operand mode (16, 32, 64).
*/
uint8_t operandMode;
/**
* @brief The address mode (16, 32, 64).
*/
uint8_t addressMode;
/** /**
* @brief Extended info for avx-related instructions. * @brief Extended info for avx-related instructions.
*/ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -106,10 +106,15 @@ enum ZydisRegisters
ZYDIS_REGISTER_XMM28, ZYDIS_REGISTER_XMM29, ZYDIS_REGISTER_XMM30, ZYDIS_REGISTER_XMM31, ZYDIS_REGISTER_XMM28, ZYDIS_REGISTER_XMM29, ZYDIS_REGISTER_XMM30, ZYDIS_REGISTER_XMM31,
// Special registers // Special registers
ZYDIS_REGISTER_RFLAGS, ZYDIS_REGISTER_EFLAGS, ZYDIS_REGISTER_FLAGS, ZYDIS_REGISTER_RIP, ZYDIS_REGISTER_RFLAGS, ZYDIS_REGISTER_EFLAGS, ZYDIS_REGISTER_FLAGS, ZYDIS_REGISTER_RIP,
ZYDIS_REGISTER_EIP, ZYDIS_REGISTER_IP, ZYDIS_REGISTER_EIP, ZYDIS_REGISTER_IP, ZYDIS_REGISTER_MXCSR,
// Segment registers // Segment registers
ZYDIS_REGISTER_ES, ZYDIS_REGISTER_SS, ZYDIS_REGISTER_CS, ZYDIS_REGISTER_DS, ZYDIS_REGISTER_ES, ZYDIS_REGISTER_SS, ZYDIS_REGISTER_CS, ZYDIS_REGISTER_DS,
ZYDIS_REGISTER_FS, ZYDIS_REGISTER_GS, ZYDIS_REGISTER_FS, ZYDIS_REGISTER_GS,
// Table registers
ZYDIS_REGISTER_GDTR, ZYDIS_REGISTER_LDTR, ZYDIS_REGISTER_IDTR, ZYDIS_REGISTER_TR,
// Test registers
ZYDIS_REGISTER_TR0, ZYDIS_REGISTER_TR1, ZYDIS_REGISTER_TR2, ZYDIS_REGISTER_TR3,
ZYDIS_REGISTER_TR4, ZYDIS_REGISTER_TR5, ZYDIS_REGISTER_TR6, ZYDIS_REGISTER_TR7,
// Control registers // Control registers
ZYDIS_REGISTER_CR0, ZYDIS_REGISTER_CR1, ZYDIS_REGISTER_CR2, ZYDIS_REGISTER_CR3, ZYDIS_REGISTER_CR0, ZYDIS_REGISTER_CR1, ZYDIS_REGISTER_CR2, ZYDIS_REGISTER_CR3,
ZYDIS_REGISTER_CR4, ZYDIS_REGISTER_CR5, ZYDIS_REGISTER_CR6, ZYDIS_REGISTER_CR7, ZYDIS_REGISTER_CR4, ZYDIS_REGISTER_CR5, ZYDIS_REGISTER_CR6, ZYDIS_REGISTER_CR7,
@ -124,7 +129,8 @@ enum ZydisRegisters
ZYDIS_REGISTER_K0, ZYDIS_REGISTER_K1, ZYDIS_REGISTER_K2, ZYDIS_REGISTER_K3, ZYDIS_REGISTER_K0, ZYDIS_REGISTER_K1, ZYDIS_REGISTER_K2, ZYDIS_REGISTER_K3,
ZYDIS_REGISTER_K4, ZYDIS_REGISTER_K5, ZYDIS_REGISTER_K6, ZYDIS_REGISTER_K7, ZYDIS_REGISTER_K4, ZYDIS_REGISTER_K5, ZYDIS_REGISTER_K6, ZYDIS_REGISTER_K7,
// Bounds registers // Bounds registers
ZYDIS_REGISTER_BND0, ZYDIS_REGISTER_BND1, ZYDIS_REGISTER_BND2, ZYDIS_REGISTER_BND3 ZYDIS_REGISTER_BND0, ZYDIS_REGISTER_BND1, ZYDIS_REGISTER_BND2, ZYDIS_REGISTER_BND3,
ZYDIS_REGISTER_BNDCFG, ZYDIS_REGISTER_BNDSTATUS
}; };
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
@ -139,7 +145,7 @@ typedef uint8_t ZydisRegisterClass;
*/ */
enum ZydisRegisterClasses enum ZydisRegisterClasses
{ {
ZYDIS_REGISTERCLASS_INVALID, ZYDIS_REGISTERCLASS_NONE,
ZYDIS_REGISTERCLASS_GENERAL_PURPOSE8, ZYDIS_REGISTERCLASS_GENERAL_PURPOSE8,
ZYDIS_REGISTERCLASS_GENERAL_PURPOSE16, ZYDIS_REGISTERCLASS_GENERAL_PURPOSE16,
ZYDIS_REGISTERCLASS_GENERAL_PURPOSE32, ZYDIS_REGISTERCLASS_GENERAL_PURPOSE32,
@ -152,6 +158,8 @@ enum ZydisRegisterClasses
ZYDIS_REGISTERCLASS_FLAGS, ZYDIS_REGISTERCLASS_FLAGS,
ZYDIS_REGISTERCLASS_IP, ZYDIS_REGISTERCLASS_IP,
ZYDIS_REGISTERCLASS_SEGMENT, ZYDIS_REGISTERCLASS_SEGMENT,
ZYDIS_REGISTERCLASS_TABLE,
ZYDIS_REGISTERCLASS_TEST,
ZYDIS_REGISTERCLASS_CONTROL, ZYDIS_REGISTERCLASS_CONTROL,
ZYDIS_REGISTERCLASS_DEBUG, ZYDIS_REGISTERCLASS_DEBUG,
ZYDIS_REGISTERCLASS_MASK, ZYDIS_REGISTERCLASS_MASK,
@ -184,6 +192,46 @@ enum ZydisRegisterSizes
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
/* Macros */
/* ============================================================================================== */
/**
* @brief Checks, if the given register is a general-purpose register.
*
* @param reg The register.
*/
#define ZYDIS_REGISTER_IS_GPR (reg) \
((ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE8) ||) \
(ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE16) || \
(ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE32))
/**
* @brief Checks, if the given register is a 8-bit general-purpose register.
*
* @param reg The register.
*/
#define ZYDIS_REGISTER_IS_GPR8 (reg) \
(ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE8)
/**
* @brief Checks, if the given register is a 16-bit general-purpose register.
*
* @param reg The register.
*/
#define ZYDIS_REGISTER_IS_GPR16 (reg) \
(ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE16)
/**
* @brief Checks, if the given register is a 32-bit general-purpose register.
*
* @param reg The register.
*/
#define ZYDIS_REGISTER_IS_GPR32 (reg) \
(ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE32)
// TODO: Add macros for all register-classes
/* ============================================================================================== */ /* ============================================================================================== */
/* Exported functions */ /* Exported functions */
/* ============================================================================================== */ /* ============================================================================================== */
@ -198,15 +246,6 @@ enum ZydisRegisterSizes
*/ */
ZYDIS_EXPORT ZydisRegister ZydisRegisterGetById(ZydisRegisterClass registerClass, uint8_t id); ZYDIS_EXPORT ZydisRegister ZydisRegisterGetById(ZydisRegisterClass registerClass, uint8_t id);
/**
* @brief Returns the specified register string.
*
* @param reg The register.
*
* @return The register string or @c NULL, if an invalid register was passed.
*/
ZYDIS_EXPORT const char* ZydisRegisterGetString(ZydisRegister reg);
/** /**
* @brief Returns the register-class of the specified register. * @brief Returns the register-class of the specified register.
* *
@ -226,166 +265,13 @@ ZYDIS_EXPORT ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg);
ZYDIS_EXPORT ZydisRegisterSize ZydisRegisterGetSize(ZydisRegister reg); ZYDIS_EXPORT ZydisRegisterSize ZydisRegisterGetSize(ZydisRegister reg);
/** /**
* @brief Checks if the specified register is a general purpose register. * @brief Returns the specified register string.
* *
* @param reg The register. * @param reg The register.
* *
* @return True, if the specified register is a general purpose register. * @return The register string or @c NULL, if an invalid register was passed.
*/ */
ZYDIS_EXPORT bool ZydisRegisterIsGPR(ZydisRegister reg); ZYDIS_EXPORT const char* ZydisRegisterGetString(ZydisRegister reg);
/**
* @brief Checks if the specified register is a 8-bit general purpose register.
*
* @param reg The register.
*
* @return True, if the specified register is a 8-bit general purpose register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsGPR8(ZydisRegister reg);
/**
* @brief Checks if the specified register is a 16-bit general purpose register.
*
* @param reg The register.
*
* @return True, if the specified register is a 16-bit general purpose register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsGPR16(ZydisRegister reg);
/**
* @brief Checks if the specified register is a 32-bit general purpose register.
*
* @param reg The register.
*
* @return True, if the specified register is a 32-bit general purpose register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsGPR32(ZydisRegister reg);
/**
* @brief Checks if the specified register is a 64-bit general purpose register.
*
* @param reg The register.
*
* @return True, if the specified register is a 64-bit general purpose register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsGPR64(ZydisRegister reg);
/**
* @brief Checks if the specified register is a legacy floating-point register.
*
* @param reg The register.
*
* @return True, if the specified register is a legacy floating-point register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsFPRegister(ZydisRegister reg);
/**
* @brief Checks if the specified register is a multi-media register.
*
* @param reg The register.
*
* @return True, if the specified register is a multi-media register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsMMRegister(ZydisRegister reg);
/**
* @brief Checks if the specified register is a vector register.
*
* @param reg The register.
*
* @return True, if the specified register is a vector register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsVR(ZydisRegister reg);
/**
* @brief Checks if the specified register is a 128-bit vector register.
*
* @param reg The register.
*
* @return True, if the specified register is a 128-bit vector register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsVR128(ZydisRegister reg);
/**
* @brief Checks if the specified register is a 256-bit vector register.
*
* @param reg The register.
*
* @return True, if the specified register is a 256-bit vector register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsVR256(ZydisRegister reg);
/**
* @brief Checks if the specified register is a 512-bit vector register.
*
* @param reg The register.
*
* @return True, if the specified register is a 512-bit vector register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsVR512(ZydisRegister reg);
/**
* @brief Checks if the specified register is a flags register.
*
* @param reg The register.
*
* @return True, if the specified register is a flags register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsFlagsRegister(ZydisRegister reg);
/**
* @brief Checks if the specified register is an instruction-pointer register.
*
* @param reg The register.
*
* @return True, if the specified register is a instruction-pointer register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsIPRegister(ZydisRegister reg);
/**
* @brief Checks if the specified register is a segment register.
*
* @param reg The register.
*
* @return True, if the specified register is a segment register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsSegmentRegister(ZydisRegister reg);
/**
* @brief Checks if the specified register is a control register.
*
* @param reg The register.
*
* @return True, if the specified register is a control register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsCR(ZydisRegister reg);
/**
* @brief Checks if the specified register is a debug register.
*
* @param reg The register.
*
* @return True, if the specified register is a debug register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsDR(ZydisRegister reg);
/**
* @brief Checks if the specified register is a mask register.
*
* @param reg The register.
*
* @return True, if the specified register is a mask register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsMaskRegister(ZydisRegister reg);
/**
* @brief Checks if the specified register is a bound register.
*
* @param reg The register.
*
* @return True, if the specified register is a bound register.
*/
ZYDIS_EXPORT bool ZydisRegisterIsBoundsRegister(ZydisRegister reg);
/* ============================================================================================== */ /* ============================================================================================== */

View File

@ -444,58 +444,58 @@ static ZydisDecoderStatus ZydisCollectOptionalPrefixes(ZydisInstructionDecoder*
switch (prefixByte) switch (prefixByte)
{ {
case 0xF0: case 0xF0:
info->prefixFlags |= ZYDIS_PREFIX_LOCK; info->prefixes |= ZYDIS_PREFIX_LOCK;
++groups[0]; ++groups[0];
break; break;
case 0xF2: case 0xF2:
// 0xF2 and 0xF3 are mutally exclusive. The one that comes later has precedence. // 0xF2 and 0xF3 are mutally exclusive. The one that comes later has precedence.
info->prefixFlags |= ZYDIS_PREFIX_REPNE; info->prefixes |= ZYDIS_PREFIX_REPNE;
info->prefixFlags &= ~ZYDIS_PREFIX_REP; info->prefixes &= ~ZYDIS_PREFIX_REP;
++groups[0]; ++groups[0];
break; break;
case 0xF3: case 0xF3:
// 0xF2 and 0xF3 are mutally exclusive. The one that comes later has precedence. // 0xF2 and 0xF3 are mutally exclusive. The one that comes later has precedence.
info->prefixFlags |= ZYDIS_PREFIX_REP; info->prefixes |= ZYDIS_PREFIX_REP;
info->prefixFlags &= ~ZYDIS_PREFIX_REPNE; info->prefixes &= ~ZYDIS_PREFIX_REPNE;
++groups[0]; ++groups[0];
break; break;
case 0x2E: case 0x2E:
info->prefixFlags |= ZYDIS_PREFIX_SEGMENT_CS; info->prefixes |= ZYDIS_PREFIX_SEGMENT_CS;
++groups[1]; ++groups[1];
break; break;
case 0x36: case 0x36:
info->prefixFlags |= ZYDIS_PREFIX_SEGMENT_SS; info->prefixes |= ZYDIS_PREFIX_SEGMENT_SS;
++groups[1]; ++groups[1];
break; break;
case 0x3E: case 0x3E:
info->prefixFlags |= ZYDIS_PREFIX_SEGMENT_DS; info->prefixes |= ZYDIS_PREFIX_SEGMENT_DS;
++groups[1]; ++groups[1];
break; break;
case 0x26: case 0x26:
info->prefixFlags |= ZYDIS_PREFIX_SEGMENT_ES; info->prefixes |= ZYDIS_PREFIX_SEGMENT_ES;
++groups[1]; ++groups[1];
break; break;
case 0x64: case 0x64:
info->prefixFlags |= ZYDIS_PREFIX_SEGMENT_FS; info->prefixes |= ZYDIS_PREFIX_SEGMENT_FS;
++groups[1]; ++groups[1];
break; break;
case 0x65: case 0x65:
info->prefixFlags |= ZYDIS_PREFIX_SEGMENT_GS; info->prefixes |= ZYDIS_PREFIX_SEGMENT_GS;
++groups[1]; ++groups[1];
break; break;
case 0x66: case 0x66:
info->prefixFlags |= ZYDIS_PREFIX_OPERANDSIZE; info->prefixes |= ZYDIS_PREFIX_OPERANDSIZE;
++groups[2]; ++groups[2];
break; break;
case 0x67: case 0x67:
info->prefixFlags |= ZYDIS_PREFIX_ADDRESSSIZE; info->prefixes |= ZYDIS_PREFIX_ADDRESSSIZE;
++groups[3]; ++groups[3];
break; break;
default: default:
if ((decoder->disassemblerMode == ZYDIS_DISASSEMBLER_MODE_64BIT) && if ((decoder->disassemblerMode == ZYDIS_DISASSEMBLER_MODE_64BIT) &&
(prefixByte & 0xF0) == 0x40) (prefixByte & 0xF0) == 0x40)
{ {
info->prefixFlags |= ZYDIS_PREFIX_REX; info->prefixes |= ZYDIS_PREFIX_REX;
info->details.rex.data[0] = prefixByte; info->details.rex.data[0] = prefixByte;
} else } else
{ {
@ -509,26 +509,26 @@ static ZydisDecoderStatus ZydisCollectOptionalPrefixes(ZydisInstructionDecoder*
} }
} while (!done); } while (!done);
if (info->prefixFlags & ZYDIS_PREFIX_REX) if (info->prefixes & ZYDIS_PREFIX_REX)
{ {
ZydisDecodeRexPrefix(info, info->details.rex.data[0]); ZydisDecodeRexPrefix(info, info->details.rex.data[0]);
} }
if (groups[0] > 1) if (groups[0] > 1)
{ {
info->prefixFlags |= ZYDIS_PREFIX_MULTIPLE_GRP1; info->prefixes |= ZYDIS_PREFIX_MULTIPLE_GRP1;
} }
if (groups[1] > 1) if (groups[1] > 1)
{ {
info->prefixFlags |= ZYDIS_PREFIX_MULTIPLE_GRP2; info->prefixes |= ZYDIS_PREFIX_MULTIPLE_GRP2;
} }
if (groups[2] > 1) if (groups[2] > 1)
{ {
info->prefixFlags |= ZYDIS_PREFIX_MULTIPLE_GRP3; info->prefixes |= ZYDIS_PREFIX_MULTIPLE_GRP3;
} }
if (groups[3] > 1) if (groups[3] > 1)
{ {
info->prefixFlags |= ZYDIS_PREFIX_MULTIPLE_GRP4; info->prefixes |= ZYDIS_PREFIX_MULTIPLE_GRP4;
} }
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
@ -661,7 +661,7 @@ static ZydisDecoderStatus ZydisDecodeOperandRegister(ZydisInstructionInfo* info,
operand->type = ZYDIS_OPERAND_TYPE_REGISTER; operand->type = ZYDIS_OPERAND_TYPE_REGISTER;
if (registerClass == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE8) if (registerClass == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE8)
{ {
if ((info->prefixFlags & ZYDIS_PREFIX_REX) && (registerId >= 4)) if ((info->prefixes & ZYDIS_PREFIX_REX) && (registerId >= 4))
{ {
operand->reg = ZYDIS_REGISTER_SPL + (registerId - 4); operand->reg = ZYDIS_REGISTER_SPL + (registerId - 4);
} else } else
@ -707,7 +707,22 @@ static ZydisDecoderStatus ZydisDecodeOperandModrmRm(ZydisInstructionDecoder* dec
} }
operand->type = ZYDIS_OPERAND_TYPE_MEMORY; operand->type = ZYDIS_OPERAND_TYPE_MEMORY;
uint8_t displacementSize = 0; uint8_t displacementSize = 0;
switch (info->addressMode) info->prefixes |= ZYDIS_PREFIX_ACCEPTS_ADDRESSSIZE;
switch (decoder->disassemblerMode)
{
case ZYDIS_DISASSEMBLER_MODE_16BIT:
operand->mem.addressSize = (info->prefixes & ZYDIS_PREFIX_ADDRESSSIZE) ? 32 : 16;
break;
case ZYDIS_DISASSEMBLER_MODE_32BIT:
operand->mem.addressSize = (info->prefixes & ZYDIS_PREFIX_ADDRESSSIZE) ? 16 : 32;
break;
case ZYDIS_DISASSEMBLER_MODE_64BIT:
operand->mem.addressSize = (info->prefixes & ZYDIS_PREFIX_ADDRESSSIZE) ? 32 : 64;
break;
default:
ZYDIS_UNREACHABLE;
}
switch (operand->mem.addressSize)
{ {
case 16: case 16:
{ {
@ -965,7 +980,7 @@ static ZydisDecoderStatus ZydisDecodeOperand(ZydisInstructionDecoder* decoder,
} }
// Register operands // Register operands
ZydisRegisterClass registerClass = ZYDIS_REGISTERCLASS_INVALID; ZydisRegisterClass registerClass = ZYDIS_REGISTERCLASS_NONE;
switch (type) switch (type)
{ {
case ZYDIS_SEM_OPERAND_TYPE_GPR8: case ZYDIS_SEM_OPERAND_TYPE_GPR8:
@ -1027,7 +1042,7 @@ static ZydisDecoderStatus ZydisDecodeOperand(ZydisInstructionDecoder* decoder,
default: default:
break; break;
} }
if (registerClass != ZYDIS_REGISTERCLASS_INVALID) if (registerClass != ZYDIS_REGISTERCLASS_NONE)
{ {
switch (encoding) switch (encoding)
{ {
@ -1119,15 +1134,15 @@ static ZydisDecoderStatus ZydisDecodeOperand(ZydisInstructionDecoder* decoder,
{ {
case ZYDIS_SEM_OPERAND_TYPE_MEM: case ZYDIS_SEM_OPERAND_TYPE_MEM:
operand->size = 0; operand->size = 0;
ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID)); ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE));
break; break;
case ZYDIS_SEM_OPERAND_TYPE_MEM8: case ZYDIS_SEM_OPERAND_TYPE_MEM8:
operand->size = 8; operand->size = 8;
ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID)); ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE));
break; break;
case ZYDIS_SEM_OPERAND_TYPE_MEM16: case ZYDIS_SEM_OPERAND_TYPE_MEM16:
operand->size = 16; operand->size = 16;
ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID)); ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE));
break; break;
case ZYDIS_SEM_OPERAND_TYPE_MEM32_BCST2: case ZYDIS_SEM_OPERAND_TYPE_MEM32_BCST2:
info->avx.broadcast = ZYDIS_AVX_BCSTMODE_2; info->avx.broadcast = ZYDIS_AVX_BCSTMODE_2;
@ -1148,7 +1163,7 @@ static ZydisDecoderStatus ZydisDecodeOperand(ZydisInstructionDecoder* decoder,
} }
case ZYDIS_SEM_OPERAND_TYPE_MEM32: case ZYDIS_SEM_OPERAND_TYPE_MEM32:
operand->size = 32; operand->size = 32;
ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID)); ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE));
break; break;
case ZYDIS_SEM_OPERAND_TYPE_MEM64_BCST2: case ZYDIS_SEM_OPERAND_TYPE_MEM64_BCST2:
info->avx.broadcast = ZYDIS_AVX_BCSTMODE_2; info->avx.broadcast = ZYDIS_AVX_BCSTMODE_2;
@ -1169,73 +1184,73 @@ static ZydisDecoderStatus ZydisDecodeOperand(ZydisInstructionDecoder* decoder,
} }
case ZYDIS_SEM_OPERAND_TYPE_MEM64: case ZYDIS_SEM_OPERAND_TYPE_MEM64:
operand->size = 64; operand->size = 64;
ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID)); ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE));
break; break;
case ZYDIS_SEM_OPERAND_TYPE_MEM80: case ZYDIS_SEM_OPERAND_TYPE_MEM80:
ZYDIS_ASSERT(evexCD8Scale == 0); ZYDIS_ASSERT(evexCD8Scale == 0);
operand->size = 80; operand->size = 80;
return ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID); return ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE);
case ZYDIS_SEM_OPERAND_TYPE_MEM112: case ZYDIS_SEM_OPERAND_TYPE_MEM112:
ZYDIS_ASSERT(evexCD8Scale == 0); ZYDIS_ASSERT(evexCD8Scale == 0);
operand->size = 112; operand->size = 112;
return ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID); return ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE);
case ZYDIS_SEM_OPERAND_TYPE_MEM128: case ZYDIS_SEM_OPERAND_TYPE_MEM128:
operand->size = 128; operand->size = 128;
ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID)); ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE));
break; break;
case ZYDIS_SEM_OPERAND_TYPE_MEM224: case ZYDIS_SEM_OPERAND_TYPE_MEM224:
ZYDIS_ASSERT(evexCD8Scale == 0); ZYDIS_ASSERT(evexCD8Scale == 0);
operand->size = 224; operand->size = 224;
return ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID); return ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE);
case ZYDIS_SEM_OPERAND_TYPE_MEM256: case ZYDIS_SEM_OPERAND_TYPE_MEM256:
operand->size = 256; operand->size = 256;
ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID)); ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE));
break; break;
case ZYDIS_SEM_OPERAND_TYPE_MEM512: case ZYDIS_SEM_OPERAND_TYPE_MEM512:
operand->size = 512; operand->size = 512;
ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID)); ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE));
break; break;
case ZYDIS_SEM_OPERAND_TYPE_M1616: case ZYDIS_SEM_OPERAND_TYPE_M1616:
ZYDIS_ASSERT(evexCD8Scale == 0); ZYDIS_ASSERT(evexCD8Scale == 0);
operand->size = 32; operand->size = 32;
return ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID); return ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE);
case ZYDIS_SEM_OPERAND_TYPE_M1632: case ZYDIS_SEM_OPERAND_TYPE_M1632:
ZYDIS_ASSERT(evexCD8Scale == 0); ZYDIS_ASSERT(evexCD8Scale == 0);
operand->size = 48; operand->size = 48;
return ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID); return ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE);
case ZYDIS_SEM_OPERAND_TYPE_M1664: case ZYDIS_SEM_OPERAND_TYPE_M1664:
ZYDIS_ASSERT(evexCD8Scale == 0); ZYDIS_ASSERT(evexCD8Scale == 0);
operand->size = 80; operand->size = 80;
return ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID); return ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE);
case ZYDIS_SEM_OPERAND_TYPE_MEM32_VSIBX: case ZYDIS_SEM_OPERAND_TYPE_MEM32_VSIBX:
vsibBaseRegister = ZYDIS_REGISTER_XMM0; vsibBaseRegister = ZYDIS_REGISTER_XMM0;
operand->size = 32; operand->size = 32;
ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID)); ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE));
break; break;
case ZYDIS_SEM_OPERAND_TYPE_MEM32_VSIBY: case ZYDIS_SEM_OPERAND_TYPE_MEM32_VSIBY:
vsibBaseRegister = ZYDIS_REGISTER_YMM0; vsibBaseRegister = ZYDIS_REGISTER_YMM0;
operand->size = 32; operand->size = 32;
ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID)); ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE));
break; break;
case ZYDIS_SEM_OPERAND_TYPE_MEM32_VSIBZ: case ZYDIS_SEM_OPERAND_TYPE_MEM32_VSIBZ:
vsibBaseRegister = ZYDIS_REGISTER_ZMM0; vsibBaseRegister = ZYDIS_REGISTER_ZMM0;
operand->size = 32; operand->size = 32;
ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID)); ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE));
break; break;
case ZYDIS_SEM_OPERAND_TYPE_MEM64_VSIBX: case ZYDIS_SEM_OPERAND_TYPE_MEM64_VSIBX:
vsibBaseRegister = ZYDIS_REGISTER_XMM0; vsibBaseRegister = ZYDIS_REGISTER_XMM0;
operand->size = 64; operand->size = 64;
ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID)); ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE));
break; break;
case ZYDIS_SEM_OPERAND_TYPE_MEM64_VSIBY: case ZYDIS_SEM_OPERAND_TYPE_MEM64_VSIBY:
vsibBaseRegister = ZYDIS_REGISTER_YMM0; vsibBaseRegister = ZYDIS_REGISTER_YMM0;
operand->size = 64; operand->size = 64;
ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID)); ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE));
break; break;
case ZYDIS_SEM_OPERAND_TYPE_MEM64_VSIBZ: case ZYDIS_SEM_OPERAND_TYPE_MEM64_VSIBZ:
vsibBaseRegister = ZYDIS_REGISTER_ZMM0; vsibBaseRegister = ZYDIS_REGISTER_ZMM0;
operand->size = 64; operand->size = 64;
ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_INVALID)); ZYDIS_CHECK(ZydisDecodeOperandModrmRm(decoder, info, operand, ZYDIS_REGISTERCLASS_NONE));
break; break;
default: default:
break; break;
@ -1255,7 +1270,7 @@ static ZydisDecoderStatus ZydisDecodeOperand(ZydisInstructionDecoder* decoder,
info->flags |= ZYDIS_INSTRUCTION_ERROR_INVALID_VSIB; info->flags |= ZYDIS_INSTRUCTION_ERROR_INVALID_VSIB;
return ZYDIS_STATUS_DECODER_INVALID_VSIB; return ZYDIS_STATUS_DECODER_INVALID_VSIB;
} }
switch (info->addressMode) switch (operand->mem.addressSize)
{ {
case 16: case 16:
info->flags |= ZYDIS_INSTRUCTION_ERROR_INVALID_VSIB; info->flags |= ZYDIS_INSTRUCTION_ERROR_INVALID_VSIB;
@ -1450,8 +1465,23 @@ static ZydisDecoderStatus ZydisDecodeOperand(ZydisInstructionDecoder* decoder,
} }
if (srcidx || dstidx) if (srcidx || dstidx)
{ {
registerClass = ZYDIS_REGISTERCLASS_INVALID; info->prefixes |= ZYDIS_PREFIX_ACCEPTS_ADDRESSSIZE;
switch (info->addressMode) switch (decoder->disassemblerMode)
{
case ZYDIS_DISASSEMBLER_MODE_16BIT:
operand->mem.addressSize = (info->prefixes & ZYDIS_PREFIX_ADDRESSSIZE) ? 32 : 16;
break;
case ZYDIS_DISASSEMBLER_MODE_32BIT:
operand->mem.addressSize = (info->prefixes & ZYDIS_PREFIX_ADDRESSSIZE) ? 16 : 32;
break;
case ZYDIS_DISASSEMBLER_MODE_64BIT:
operand->mem.addressSize = (info->prefixes & ZYDIS_PREFIX_ADDRESSSIZE) ? 32 : 64;
break;
default:
ZYDIS_UNREACHABLE;
}
registerClass = ZYDIS_REGISTERCLASS_NONE;
switch (operand->mem.addressSize)
{ {
case 16: case 16:
registerClass = ZYDIS_REGISTERCLASS_GENERAL_PURPOSE16; registerClass = ZYDIS_REGISTERCLASS_GENERAL_PURPOSE16;
@ -1528,27 +1558,27 @@ static ZydisDecoderStatus ZydisDecodeOperands(ZydisInstructionDecoder* decoder,
// Adjust segment register for memory operands // Adjust segment register for memory operands
if (info->operand[i].type == ZYDIS_OPERAND_TYPE_MEMORY) if (info->operand[i].type == ZYDIS_OPERAND_TYPE_MEMORY)
{ {
if (info->prefixFlags & ZYDIS_PREFIX_SEGMENT_CS) if (info->prefixes & ZYDIS_PREFIX_SEGMENT_CS)
{ {
info->operand[i].mem.segment = ZYDIS_REGISTER_CS; info->operand[i].mem.segment = ZYDIS_REGISTER_CS;
} else } else
if (info->prefixFlags & ZYDIS_PREFIX_SEGMENT_SS) if (info->prefixes & ZYDIS_PREFIX_SEGMENT_SS)
{ {
info->operand[i].mem.segment = ZYDIS_REGISTER_SS; info->operand[i].mem.segment = ZYDIS_REGISTER_SS;
} else } else
if (info->prefixFlags & ZYDIS_PREFIX_SEGMENT_DS) if (info->prefixes & ZYDIS_PREFIX_SEGMENT_DS)
{ {
info->operand[i].mem.segment = ZYDIS_REGISTER_DS; info->operand[i].mem.segment = ZYDIS_REGISTER_DS;
} else } else
if (info->prefixFlags & ZYDIS_PREFIX_SEGMENT_ES) if (info->prefixes & ZYDIS_PREFIX_SEGMENT_ES)
{ {
info->operand[i].mem.segment = ZYDIS_REGISTER_ES; info->operand[i].mem.segment = ZYDIS_REGISTER_ES;
} else } else
if (info->prefixFlags & ZYDIS_PREFIX_SEGMENT_FS) if (info->prefixes & ZYDIS_PREFIX_SEGMENT_FS)
{ {
info->operand[i].mem.segment = ZYDIS_REGISTER_FS; info->operand[i].mem.segment = ZYDIS_REGISTER_FS;
} else } else
if (info->prefixFlags & ZYDIS_PREFIX_SEGMENT_GS) if (info->prefixes & ZYDIS_PREFIX_SEGMENT_GS)
{ {
info->operand[i].mem.segment = ZYDIS_REGISTER_GS; info->operand[i].mem.segment = ZYDIS_REGISTER_GS;
} else } else
@ -1579,46 +1609,6 @@ static void ZydisFinalizeInstructionInfo(ZydisInstructionInfo* info)
// TODO: Encode all these things in the instruction definition // TODO: Encode all these things in the instruction definition
// Adjust operand-mode
/*if (info->mode == ZYDIS_DISASSEMBLER_MODE_64BIT)
{
if ((info->flags & ZYDIS_INSTRUCTION_RELATIVE) &&
(info->operand[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE))
{
info->operandMode = 64;
}
if (info->opcodeMap == ZYDIS_OPCODE_MAP_DEFAULT)
{
if ((info->opcode == 0xC2) || (info->opcode == 0xC3) || (info->opcode == 0xC4) ||
(info->opcode == 0xC5) || (info->opcode == 0xEA) ||
(info->opcode == 0x50) || (info->opcode == 0x51) || (info->opcode == 0x52) ||
(info->opcode == 0x53) || (info->opcode == 0x54) || (info->opcode == 0x55) ||
(info->opcode == 0x56) || (info->opcode == 0x57) || (info->opcode == 0x58) ||
(info->opcode == 0x59) || (info->opcode == 0x5A) || (info->opcode == 0x5B) ||
(info->opcode == 0x5C) || (info->opcode == 0x5D) || (info->opcode == 0x5E) ||
(info->opcode == 0x5F) || (info->opcode == 0x68) || (info->opcode == 0x6A) ||
(info->opcode == 0x8F) || (info->opcode == 0x9C) || (info->opcode == 0x9D) ||
(info->opcode == 0xC9))
{
info->operandMode = 64;
} else if (info->opcode == 0xFF)
{
if ((info->details.modrm.reg == 0x02) || (info->details.modrm.reg == 0x04) ||
(info->details.modrm.reg == 0x06))
{
info->operandMode = 64;
}
}
} else if (info->opcodeMap == ZYDIS_OPCODE_MAP_0F)
{
if ((info->opcode == 0xA0) || (info->opcode == 0xA1) || (info->opcode == 0xA8) ||
(info->opcode == 0xA9))
{
info->operandMode = 64;
}
}
}*/
// Adjust prefix flags // Adjust prefix flags
switch (info->mnemonic) switch (info->mnemonic)
{ {
@ -1643,7 +1633,7 @@ static void ZydisFinalizeInstructionInfo(ZydisInstructionInfo* info)
case ZYDIS_MNEMONIC_XCHG: case ZYDIS_MNEMONIC_XCHG:
if (info->operand[0].type == ZYDIS_OPERAND_TYPE_MEMORY) if (info->operand[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
{ {
info->prefixFlags |= ZYDIS_PREFIX_ACCEPTS_LOCK; info->prefixes |= ZYDIS_PREFIX_ACCEPTS_LOCK;
} }
break; break;
case ZYDIS_MNEMONIC_MOVSB: case ZYDIS_MNEMONIC_MOVSB:
@ -1672,7 +1662,7 @@ static void ZydisFinalizeInstructionInfo(ZydisInstructionInfo* info)
case ZYDIS_MNEMONIC_OUTSB: case ZYDIS_MNEMONIC_OUTSB:
case ZYDIS_MNEMONIC_OUTSW: case ZYDIS_MNEMONIC_OUTSW:
case ZYDIS_MNEMONIC_OUTSD: case ZYDIS_MNEMONIC_OUTSD:
info->prefixFlags |= ZYDIS_PREFIX_ACCEPTS_REP | ZYDIS_PREFIX_ACCEPTS_REPNE; info->prefixes |= ZYDIS_PREFIX_ACCEPTS_REP | ZYDIS_PREFIX_ACCEPTS_REPNE;
break; break;
case ZYDIS_MNEMONIC_JO: case ZYDIS_MNEMONIC_JO:
case ZYDIS_MNEMONIC_JNO: case ZYDIS_MNEMONIC_JNO:
@ -1693,44 +1683,44 @@ static void ZydisFinalizeInstructionInfo(ZydisInstructionInfo* info)
case ZYDIS_MNEMONIC_JCXZ: case ZYDIS_MNEMONIC_JCXZ:
case ZYDIS_MNEMONIC_JECXZ: case ZYDIS_MNEMONIC_JECXZ:
case ZYDIS_MNEMONIC_JRCXZ: case ZYDIS_MNEMONIC_JRCXZ:
if (info->prefixFlags & ZYDIS_PREFIX_SEGMENT_CS) if (info->prefixes & ZYDIS_PREFIX_SEGMENT_CS)
{ {
info->prefixFlags &= ~ZYDIS_PREFIX_SEGMENT_CS; info->prefixes &= ~ZYDIS_PREFIX_SEGMENT_CS;
info->prefixFlags |= ZYDIS_PREFIX_BRANCH_NOT_TAKEN; info->prefixes |= ZYDIS_PREFIX_BRANCH_NOT_TAKEN;
} else } else
if (info->prefixFlags & ZYDIS_PREFIX_SEGMENT_DS) if (info->prefixes & ZYDIS_PREFIX_SEGMENT_DS)
{ {
info->prefixFlags &= ~ZYDIS_PREFIX_SEGMENT_DS; info->prefixes &= ~ZYDIS_PREFIX_SEGMENT_DS;
info->prefixFlags |= ZYDIS_PREFIX_BRANCH_TAKEN; info->prefixes |= ZYDIS_PREFIX_BRANCH_TAKEN;
} }
break; break;
default: default:
break; break;
} }
if ((info->prefixFlags & ZYDIS_PREFIX_ACCEPTS_LOCK) && if ((info->prefixes & ZYDIS_PREFIX_ACCEPTS_LOCK) &&
((info->prefixFlags & ZYDIS_PREFIX_REP) || (info->prefixFlags & ZYDIS_PREFIX_REPNE))) ((info->prefixes & ZYDIS_PREFIX_REP) || (info->prefixes & ZYDIS_PREFIX_REPNE)))
{ {
if (info->mnemonic != ZYDIS_MNEMONIC_CMPXCHG16B) if (info->mnemonic != ZYDIS_MNEMONIC_CMPXCHG16B)
{ {
if ((info->prefixFlags & ZYDIS_PREFIX_LOCK) || (info->mnemonic == ZYDIS_MNEMONIC_XCHG)) if ((info->prefixes & ZYDIS_PREFIX_LOCK) || (info->mnemonic == ZYDIS_MNEMONIC_XCHG))
{ {
if (info->prefixFlags & ZYDIS_PREFIX_REPNE) if (info->prefixes & ZYDIS_PREFIX_REPNE)
{ {
info->prefixFlags &= ~ZYDIS_PREFIX_REPNE; info->prefixes &= ~ZYDIS_PREFIX_REPNE;
info->prefixFlags |= ZYDIS_PREFIX_XACQUIRE; info->prefixes |= ZYDIS_PREFIX_XACQUIRE;
} }
{ {
info->prefixFlags &= ~ZYDIS_PREFIX_REP; info->prefixes &= ~ZYDIS_PREFIX_REP;
info->prefixFlags |= ZYDIS_PREFIX_XRELEASE; info->prefixes |= ZYDIS_PREFIX_XRELEASE;
} }
} else } else
if ((info->mnemonic == ZYDIS_MNEMONIC_MOV) && ((info->opcode == 0x88) || if ((info->mnemonic == ZYDIS_MNEMONIC_MOV) && ((info->opcode == 0x88) ||
(info->opcode == 0x89) || (info->opcode == 0xC6) || (info->opcode == 0xC7))) (info->opcode == 0x89) || (info->opcode == 0xC6) || (info->opcode == 0xC7)))
{ {
if (info->prefixFlags & ZYDIS_PREFIX_REP) if (info->prefixes & ZYDIS_PREFIX_REP)
{ {
info->prefixFlags &= ~ZYDIS_PREFIX_REP; info->prefixes &= ~ZYDIS_PREFIX_REP;
info->prefixFlags |= ZYDIS_PREFIX_XRELEASE; info->prefixes |= ZYDIS_PREFIX_XRELEASE;
} }
} }
} }
@ -1784,7 +1774,7 @@ static ZydisDecoderStatus ZydisNodeHandlerOpcode(ZydisInstructionDecoder* decode
if ((decoder->disassemblerMode == ZYDIS_DISASSEMBLER_MODE_64BIT) || if ((decoder->disassemblerMode == ZYDIS_DISASSEMBLER_MODE_64BIT) ||
((nextInput & 0xF0) >= 0xC0)) ((nextInput & 0xF0) >= 0xC0))
{ {
if (info->prefixFlags & ZYDIS_PREFIX_REX) if (info->prefixes & ZYDIS_PREFIX_REX)
{ {
info->flags |= ZYDIS_INSTRUCTION_ERROR_ILLEGAL_REX; info->flags |= ZYDIS_INSTRUCTION_ERROR_ILLEGAL_REX;
return ZYDIS_STATUS_DECODER_ILLEGAL_REX; return ZYDIS_STATUS_DECODER_ILLEGAL_REX;
@ -1819,7 +1809,7 @@ static ZydisDecoderStatus ZydisNodeHandlerOpcode(ZydisInstructionDecoder* decode
case 0xC5: case 0xC5:
// Decode vex-prefix // Decode vex-prefix
info->encoding = ZYDIS_INSTRUCTION_ENCODING_VEX; info->encoding = ZYDIS_INSTRUCTION_ENCODING_VEX;
info->prefixFlags |= ZYDIS_PREFIX_VEX; info->prefixes |= ZYDIS_PREFIX_VEX;
if (!ZydisDecodeVexPrefix(info->opcode, prefixBytes[0], prefixBytes[1], if (!ZydisDecodeVexPrefix(info->opcode, prefixBytes[0], prefixBytes[1],
info)) info))
{ {
@ -1831,7 +1821,7 @@ static ZydisDecoderStatus ZydisNodeHandlerOpcode(ZydisInstructionDecoder* decode
case 0x62: case 0x62:
// Decode evex-prefix // Decode evex-prefix
info->encoding = ZYDIS_INSTRUCTION_ENCODING_EVEX; info->encoding = ZYDIS_INSTRUCTION_ENCODING_EVEX;
info->prefixFlags |= ZYDIS_PREFIX_EVEX; info->prefixes |= ZYDIS_PREFIX_EVEX;
if (!ZydisDecodeEvexPrefix(prefixBytes[0], prefixBytes[1], prefixBytes[2], if (!ZydisDecodeEvexPrefix(prefixBytes[0], prefixBytes[1], prefixBytes[2],
info)) info))
{ {
@ -1852,7 +1842,7 @@ static ZydisDecoderStatus ZydisNodeHandlerOpcode(ZydisInstructionDecoder* decode
ZYDIS_CHECK(ZydisInputPeek(decoder, info, &nextInput)); ZYDIS_CHECK(ZydisInputPeek(decoder, info, &nextInput));
if (((nextInput >> 0) & 0x1F) >= 8) if (((nextInput >> 0) & 0x1F) >= 8)
{ {
if (info->prefixFlags & ZYDIS_PREFIX_REX) if (info->prefixes & ZYDIS_PREFIX_REX)
{ {
info->flags |= ZYDIS_INSTRUCTION_ERROR_ILLEGAL_REX; info->flags |= ZYDIS_INSTRUCTION_ERROR_ILLEGAL_REX;
return ZYDIS_STATUS_DECODER_ILLEGAL_REX; return ZYDIS_STATUS_DECODER_ILLEGAL_REX;
@ -1864,7 +1854,7 @@ static ZydisDecoderStatus ZydisNodeHandlerOpcode(ZydisInstructionDecoder* decode
ZYDIS_CHECK(ZydisInputNext(decoder, info, &prefixBytes[1])); ZYDIS_CHECK(ZydisInputNext(decoder, info, &prefixBytes[1]));
// Decode xop-prefix // Decode xop-prefix
info->encoding = ZYDIS_INSTRUCTION_ENCODING_XOP; info->encoding = ZYDIS_INSTRUCTION_ENCODING_XOP;
info->prefixFlags |= ZYDIS_PREFIX_XOP; info->prefixes |= ZYDIS_PREFIX_XOP;
if (!ZydisDecodeXopPrefix(prefixBytes[0], prefixBytes[1], info)) if (!ZydisDecodeXopPrefix(prefixBytes[0], prefixBytes[1], info))
{ {
info->flags |= ZYDIS_INSTRUCTION_ERROR_MALFORMED_XOP; info->flags |= ZYDIS_INSTRUCTION_ERROR_MALFORMED_XOP;
@ -1980,18 +1970,18 @@ static ZydisDecoderStatus ZydisNodeHandlerMandatoryPrefix(ZydisInstructionInfo*
ZYDIS_ASSERT(info); ZYDIS_ASSERT(info);
ZYDIS_ASSERT(index); ZYDIS_ASSERT(index);
if (info->prefixFlags & ZYDIS_PREFIX_REP) if (info->prefixes & ZYDIS_PREFIX_REP)
{ {
*index = 2; *index = 2;
info->prefixFlags &= ~ ZYDIS_PREFIX_REP; // TODO: don't remove but mark as mandatory info->prefixes &= ~ ZYDIS_PREFIX_REP; // TODO: don't remove but mark as mandatory
} else if (info->prefixFlags & ZYDIS_PREFIX_REPNE) } else if (info->prefixes & ZYDIS_PREFIX_REPNE)
{ {
*index = 3; *index = 3;
info->prefixFlags &= ~ ZYDIS_PREFIX_REPNE; // TODO: don't remove but mark as mandatory info->prefixes &= ~ ZYDIS_PREFIX_REPNE; // TODO: don't remove but mark as mandatory
} else if (info->prefixFlags & ZYDIS_PREFIX_OPERANDSIZE) } else if (info->prefixes & ZYDIS_PREFIX_OPERANDSIZE)
{ {
*index = 1; *index = 1;
info->prefixFlags &= ~ ZYDIS_PREFIX_OPERANDSIZE; // TODO: don't remove but mark as mandatory info->prefixes &= ~ ZYDIS_PREFIX_OPERANDSIZE; // TODO: don't remove but mark as mandatory
} }
return ZYDIS_STATUS_DECODER_SUCCESS; return ZYDIS_STATUS_DECODER_SUCCESS;
} }
@ -2054,14 +2044,16 @@ static ZydisDecoderStatus ZydisNodeHandlerOperandSize(ZydisInstructionDecoder* d
ZYDIS_ASSERT(info); ZYDIS_ASSERT(info);
ZYDIS_ASSERT(index); ZYDIS_ASSERT(index);
info->prefixes |= ZYDIS_PREFIX_ACCEPTS_OPERANDSIZE;
switch (decoder->disassemblerMode) switch (decoder->disassemblerMode)
{ {
case ZYDIS_DISASSEMBLER_MODE_16BIT: case ZYDIS_DISASSEMBLER_MODE_16BIT:
*index = (info->prefixFlags & ZYDIS_PREFIX_OPERANDSIZE) ? 1 : 0; *index = (info->prefixes & ZYDIS_PREFIX_OPERANDSIZE) ? 1 : 0;
break; break;
case ZYDIS_DISASSEMBLER_MODE_32BIT: case ZYDIS_DISASSEMBLER_MODE_32BIT:
case ZYDIS_DISASSEMBLER_MODE_64BIT: case ZYDIS_DISASSEMBLER_MODE_64BIT:
*index = (info->prefixFlags & ZYDIS_PREFIX_OPERANDSIZE) ? 0 : 1; *index = (info->prefixes & ZYDIS_PREFIX_OPERANDSIZE) ? 0 : 1;
break; break;
default: default:
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
@ -2076,16 +2068,18 @@ static ZydisDecoderStatus ZydisNodeHandlerAddressSize(ZydisInstructionDecoder* d
ZYDIS_ASSERT(info); ZYDIS_ASSERT(info);
ZYDIS_ASSERT(index); ZYDIS_ASSERT(index);
info->prefixes |= ZYDIS_PREFIX_ACCEPTS_ADDRESSSIZE;
switch (decoder->disassemblerMode) switch (decoder->disassemblerMode)
{ {
case ZYDIS_DISASSEMBLER_MODE_16BIT: case ZYDIS_DISASSEMBLER_MODE_16BIT:
*index = (info->prefixFlags & ZYDIS_PREFIX_ADDRESSSIZE) ? 1 : 0; *index = (info->prefixes & ZYDIS_PREFIX_ADDRESSSIZE) ? 1 : 0;
break; break;
case ZYDIS_DISASSEMBLER_MODE_32BIT: case ZYDIS_DISASSEMBLER_MODE_32BIT:
*index = (info->prefixFlags & ZYDIS_PREFIX_ADDRESSSIZE) ? 0 : 1; *index = (info->prefixes & ZYDIS_PREFIX_ADDRESSSIZE) ? 0 : 1;
break; break;
case ZYDIS_DISASSEMBLER_MODE_64BIT: case ZYDIS_DISASSEMBLER_MODE_64BIT:
*index = (info->prefixFlags & ZYDIS_PREFIX_ADDRESSSIZE) ? 1 : 2; *index = (info->prefixes & ZYDIS_PREFIX_ADDRESSSIZE) ? 1 : 2;
break; break;
default: default:
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
@ -2227,36 +2221,6 @@ static ZydisDecoderStatus ZydisDecodeOpcode(ZydisInstructionDecoder* decoder,
//ZYDIS_ASSERT(definition); // TODO: Pointer? //ZYDIS_ASSERT(definition); // TODO: Pointer?
info->mnemonic = definition.mnemonic; info->mnemonic = definition.mnemonic;
// TODO: Check for (un)accepted prefixes
// Determine effective operand- and address-mode
switch (decoder->disassemblerMode)
{
case ZYDIS_DISASSEMBLER_MODE_16BIT:
info->addressMode = (info->prefixFlags & ZYDIS_PREFIX_ADDRESSSIZE) ? 32 : 16;
info->operandMode = (info->prefixFlags & ZYDIS_PREFIX_OPERANDSIZE) ? 32 : 16;
break;
case ZYDIS_DISASSEMBLER_MODE_32BIT:
info->addressMode = (info->prefixFlags & ZYDIS_PREFIX_ADDRESSSIZE) ? 16 : 32;
info->operandMode = (info->prefixFlags & ZYDIS_PREFIX_OPERANDSIZE) ? 16 : 32;
break;
case ZYDIS_DISASSEMBLER_MODE_64BIT:
info->addressMode = (info->prefixFlags & ZYDIS_PREFIX_ADDRESSSIZE) ? 32 : 64;
if (info->details.internal.w)
{
info->operandMode = 64;
} else if ((info->prefixFlags & ZYDIS_PREFIX_OPERANDSIZE))
{
info->operandMode = 16;
} else
{
info->operandMode = 32;
}
break;
default:
ZYDIS_UNREACHABLE;
}
if (info->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW) if (info->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW)
{ {
// Save input-buffer state and decode dummy operands // Save input-buffer state and decode dummy operands
@ -2529,8 +2493,6 @@ ZydisStatus ZydisDecoderDecodeNextInstruction(ZydisInstructionDecoder* decoder,
userData[5] = info->userData; userData[5] = info->userData;
memset(info, 0, sizeof(*info)); memset(info, 0, sizeof(*info));
info->mode = decoder->disassemblerMode; info->mode = decoder->disassemblerMode;
info->operandMode = (decoder->disassemblerMode == ZYDIS_DISASSEMBLER_MODE_16BIT) ? 16 : 32;
info->addressMode = decoder->disassemblerMode;
info->instrAddress = decoder->instructionPointer; info->instrAddress = decoder->instructionPointer;
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
{ {

View File

@ -196,22 +196,27 @@ static ZydisStatus ZydisBufferAppendAbsoluteAddress(const ZydisInstructionFormat
buffer, bufferLen, offset, false, "%s-0x%02llX", symbol, -symbolOffset); buffer, bufferLen, offset, false, "%s-0x%02llX", symbol, -symbolOffset);
} }
} }
if (info->operandMode == 16)
{
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%04X", address);
}
switch (info->mode) switch (info->mode)
{ {
case ZYDIS_DISASSEMBLER_MODE_16BIT: case ZYDIS_DISASSEMBLER_MODE_16BIT:
return ZydisBufferAppendFormat(buffer, bufferLen, offset, return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%04X", address); (formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%04X", address);
case ZYDIS_DISASSEMBLER_MODE_32BIT: case ZYDIS_DISASSEMBLER_MODE_32BIT:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%08lX", address);
case ZYDIS_DISASSEMBLER_MODE_64BIT: case ZYDIS_DISASSEMBLER_MODE_64BIT:
return ZydisBufferAppendFormat(buffer, bufferLen, offset, switch (operand->size)
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%016llX", address); {
case 16:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%04X", address);
case 32:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%08lX", address);
case 64:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%016llX", address);
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
default: default:
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
@ -335,9 +340,9 @@ static ZydisStatus ZydisBufferAppendOperandIntelMemory(const ZydisInstructionFor
{ {
if ((formatter->flags & ZYDIS_FORMATTER_FLAG_ALWAYS_DISPLAY_MEMORY_SEGMENT) || if ((formatter->flags & ZYDIS_FORMATTER_FLAG_ALWAYS_DISPLAY_MEMORY_SEGMENT) ||
(((operand->mem.segment != ZYDIS_REGISTER_DS) || (((operand->mem.segment != ZYDIS_REGISTER_DS) ||
(info->prefixFlags & ZYDIS_PREFIX_SEGMENT_DS)) && (info->prefixes & ZYDIS_PREFIX_SEGMENT_DS)) &&
((operand->mem.segment != ZYDIS_REGISTER_SS) || ((operand->mem.segment != ZYDIS_REGISTER_SS) ||
(info->prefixFlags & ZYDIS_PREFIX_SEGMENT_SS)))) (info->prefixes & ZYDIS_PREFIX_SEGMENT_SS))))
{ {
ZYDIS_CHECK(ZydisBufferAppendFormat(buffer, bufferLen, offset, ZYDIS_CHECK(ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "%s:", (formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "%s:",
@ -441,27 +446,27 @@ static ZydisStatus ZydisFormatterFormatInstructionIntel(ZydisInstructionFormatte
{ {
size_t offset = 0; size_t offset = 0;
if ((info->prefixFlags & ZYDIS_PREFIX_ACCEPTS_REPNE) && if ((info->prefixes & ZYDIS_PREFIX_ACCEPTS_REPNE) &&
(info->prefixFlags & ZYDIS_PREFIX_REPNE)) (info->prefixes & ZYDIS_PREFIX_REPNE))
{ {
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset, ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "repne ")); (formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "repne "));
} }
if ((info->prefixFlags & ZYDIS_PREFIX_ACCEPTS_REP) && (info->prefixFlags & ZYDIS_PREFIX_REP)) if ((info->prefixes & ZYDIS_PREFIX_ACCEPTS_REP) && (info->prefixes & ZYDIS_PREFIX_REP))
{ {
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset, ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "rep ")); (formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "rep "));
} }
if ((info->prefixFlags & ZYDIS_PREFIX_ACCEPTS_LOCK) && (info->prefixFlags & ZYDIS_PREFIX_LOCK)) if ((info->prefixes & ZYDIS_PREFIX_ACCEPTS_LOCK) && (info->prefixes & ZYDIS_PREFIX_LOCK))
{ {
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset, ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "lock ")); (formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "lock "));
} }
if (info->prefixFlags & ZYDIS_PREFIX_XACQUIRE) if (info->prefixes & ZYDIS_PREFIX_XACQUIRE)
{ {
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset, ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "xacquire ")); (formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "xacquire "));
} else if (info->prefixFlags & ZYDIS_PREFIX_XRELEASE) } else if (info->prefixes & ZYDIS_PREFIX_XRELEASE)
{ {
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset, ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "xrelease ")); (formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "xrelease "));

View File

@ -91,10 +91,15 @@ const char* registerStrings[] =
"xmm28", "xmm29", "xmm30", "xmm31", "xmm28", "xmm29", "xmm30", "xmm31",
// Special registers // Special registers
"rflags", "eflags", "flags", "rip", "rflags", "eflags", "flags", "rip",
"eip", "ip", "eip", "ip", "mxcsr",
// Segment registers // Segment registers
"es", "ss", "cs", "ds", "es", "ss", "cs", "ds",
"fs", "gs", "fs", "gs",
// Table registers
"gdtr", "ldtr", "idtr", "tr",
// Test registers
"tr0", "tr1", "tr2", "tr3",
"tr4", "tr5", "tr6", "tr7",
// Control registers // Control registers
"cr0", "cr1", "cr2", "cr3", "cr0", "cr1", "cr2", "cr3",
"cr4", "cr5", "cr6", "cr7", "cr4", "cr5", "cr6", "cr7",
@ -109,7 +114,8 @@ const char* registerStrings[] =
"k0", "k1", "k2", "k3", "k0", "k1", "k2", "k3",
"k4", "k5", "k6", "k7", "k4", "k5", "k6", "k7",
// Bounds registers // Bounds registers
"bnd0", "bnd1", "bnd2", "bnd3" "bnd0", "bnd1", "bnd2", "bnd3",
"bndcfg", "bndstatus"
}; };
/* ============================================================================================== */ /* ============================================================================================== */
@ -170,6 +176,11 @@ ZydisRegister ZydisRegisterGetById(ZydisRegisterClass registerClass, uint8_t id)
{ {
return ZYDIS_REGISTER_ES + id; return ZYDIS_REGISTER_ES + id;
} }
case ZYDIS_REGISTERCLASS_TEST:
if (id <= 7)
{
return ZYDIS_REGISTER_TR0 + id;
}
case ZYDIS_REGISTERCLASS_CONTROL: case ZYDIS_REGISTERCLASS_CONTROL:
if (id <= 15) if (id <= 15)
{ {
@ -190,11 +201,8 @@ ZydisRegister ZydisRegisterGetById(ZydisRegisterClass registerClass, uint8_t id)
{ {
return ZYDIS_REGISTER_BND0 + id; return ZYDIS_REGISTER_BND0 + id;
} }
case ZYDIS_REGISTERCLASS_FLAGS:
case ZYDIS_REGISTERCLASS_IP:
// These registers are unique
break;
default: default:
// The registers of the missing register-classes can not be encoded by the register-id.
break; break;
} }
return ZYDIS_REGISTER_NONE; return ZYDIS_REGISTER_NONE;
@ -255,6 +263,14 @@ ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg)
{ {
return ZYDIS_REGISTERCLASS_SEGMENT; return ZYDIS_REGISTERCLASS_SEGMENT;
} }
if ((reg >= ZYDIS_REGISTER_GDTR) && (reg <= ZYDIS_REGISTER_TR))
{
return ZYDIS_REGISTERCLASS_TABLE;
}
if ((reg >= ZYDIS_REGISTER_TR0) && (reg <= ZYDIS_REGISTER_TR7))
{
return ZYDIS_REGISTERCLASS_TEST;
}
if ((reg >= ZYDIS_REGISTER_CR0) && (reg <= ZYDIS_REGISTER_CR15)) if ((reg >= ZYDIS_REGISTER_CR0) && (reg <= ZYDIS_REGISTER_CR15))
{ {
return ZYDIS_REGISTERCLASS_CONTROL; return ZYDIS_REGISTERCLASS_CONTROL;
@ -267,11 +283,11 @@ ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg)
{ {
return ZYDIS_REGISTERCLASS_MASK; return ZYDIS_REGISTERCLASS_MASK;
} }
if ((reg >= ZYDIS_REGISTER_BND0) && (reg <= ZYDIS_REGISTER_BND3)) if ((reg >= ZYDIS_REGISTER_BND0) && (reg <= ZYDIS_REGISTER_BNDSTATUS))
{ {
return ZYDIS_REGISTERCLASS_BOUNDS; return ZYDIS_REGISTERCLASS_BOUNDS;
} }
return ZYDIS_REGISTERCLASS_INVALID; return ZYDIS_REGISTERCLASS_NONE;
} }
ZydisRegisterSize ZydisRegisterGetSize(ZydisRegister reg) ZydisRegisterSize ZydisRegisterGetSize(ZydisRegister reg)
@ -303,6 +319,10 @@ ZydisRegisterSize ZydisRegisterGetSize(ZydisRegister reg)
return ZYDIS_REGISTERSIZE_DYNAMIC; return ZYDIS_REGISTERSIZE_DYNAMIC;
case ZYDIS_REGISTERCLASS_SEGMENT: case ZYDIS_REGISTERCLASS_SEGMENT:
return ZYDIS_REGISTERSIZE_16; return ZYDIS_REGISTERSIZE_16;
case ZYDIS_REGISTERCLASS_TABLE:
return ZYDIS_REGISTERSIZE_DYNAMIC;
case ZYDIS_REGISTERCLASS_TEST:
return ZYDIS_REGISTERSIZE_INVALID; // TODO:
case ZYDIS_REGISTERCLASS_CONTROL: case ZYDIS_REGISTERCLASS_CONTROL:
return ZYDIS_REGISTERSIZE_DYNAMIC; return ZYDIS_REGISTERSIZE_DYNAMIC;
case ZYDIS_REGISTERCLASS_DEBUG: case ZYDIS_REGISTERCLASS_DEBUG:
@ -317,113 +337,4 @@ ZydisRegisterSize ZydisRegisterGetSize(ZydisRegister reg)
return ZYDIS_REGISTERSIZE_INVALID; return ZYDIS_REGISTERSIZE_INVALID;
} }
bool ZydisRegisterIsGPR(ZydisRegister reg)
{
switch (ZydisRegisterGetClass(reg))
{
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE64:
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE32:
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE16:
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE8:
return true;
default:
break;
}
return false;
}
bool ZydisRegisterIsGPR8(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE8);
}
bool ZydisRegisterIsGPR16(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE16);
}
bool ZydisRegisterIsGPR32(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE32);
}
bool ZydisRegisterIsGPR64(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE64);
}
bool ZydisRegisterIsFPRegister(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_FLOATING_POINT);
}
bool ZydisRegisterIsMMRegister(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_MULTIMEDIA);
}
bool ZydisRegisterIsVR(ZydisRegister reg)
{
switch (ZydisRegisterGetClass(reg))
{
case ZYDIS_REGISTERCLASS_VECTOR512:
case ZYDIS_REGISTERCLASS_VECTOR256:
case ZYDIS_REGISTERCLASS_VECTOR128:
return true;
default:
break;
}
return false;
}
bool ZydisRegisterIsVR128(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_VECTOR128);
}
bool ZydisRegisterIsVR256(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_VECTOR256);
}
bool ZydisRegisterIsVR512(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_VECTOR512);
}
bool ZydisRegisterIsFlagsRegister(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_FLAGS);
}
bool ZydisRegisterIsIPRegister(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_IP);
}
bool ZydisRegisterIsSegmentRegister(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_SEGMENT);
}
bool ZydisRegisterIsCR(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_CONTROL);
}
bool ZydisRegisterIsDR(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_DEBUG);
}
bool ZydisRegisterIsMaskRegister(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_MASK);
}
bool ZydisRegisterIsBoundsRegister(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_BOUNDS);
}
/* ============================================================================================== */ /* ============================================================================================== */

View File

@ -64,19 +64,23 @@ ZydisStatus ZydisUtilsCalcAbsoluteTargetAddress(const ZydisInstructionInfo* info
if (operand->imm.isSigned || operand->imm.isRelative) if (operand->imm.isSigned || operand->imm.isRelative)
{ {
*address = (uint64_t)((int64_t)info->instrPointer + operand->imm.value.sqword); *address = (uint64_t)((int64_t)info->instrPointer + operand->imm.value.sqword);
switch (info->operandMode) switch (operand->size)
{ {
case 16: case 16:
*address = (uint16_t)*address; *address = (uint16_t)*address;
break; break;
case 32: case 32:
assert((info->mode != ZYDIS_DISASSEMBLER_MODE_64BIT)); // TODO: Remove after fuzzing
if (info->mode != ZYDIS_DISASSEMBLER_MODE_64BIT) if (info->mode != ZYDIS_DISASSEMBLER_MODE_64BIT)
{ {
*address = (uint32_t)*address; *address = (uint32_t)*address;
} }
break; break;
default: case 64:
assert((info->mode == ZYDIS_DISASSEMBLER_MODE_64BIT)); // TODO: Remove after fuzzing
break; break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
} }
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
} }