Internal changes and optimizations of the generated tables and the InstructionEditor

This commit is contained in:
flobernd 2016-11-22 18:12:05 +01:00
parent be56ef937d
commit 7f7cbd8dcd
16 changed files with 114453 additions and 113266 deletions

View File

@ -158,7 +158,7 @@ const
FILENAME_MNEMONICSTRINGS = 'MnemonicStrings.inc'; FILENAME_MNEMONICSTRINGS = 'MnemonicStrings.inc';
FILENAME_INSTRUCTIONDEFINITIONS = 'InstructionDefinitions.inc'; FILENAME_INSTRUCTIONDEFINITIONS = 'InstructionDefinitions.inc';
FILENAME_OPERANDDEFINITIONS = 'OperandDefinitions.inc'; FILENAME_OPERANDDEFINITIONS = 'OperandDefinitions.inc';
FILENAME_INTERNALSTRUCTS = 'InternalStructs.inc'; FILENAME_GENERATEDTYPES = 'GeneratedTypes.inc';
{ TCodeGenerator } { TCodeGenerator }
@ -562,8 +562,15 @@ begin
if (ifHasEvexSAE in Definition.Flags) then U := 'ZYDIS_EVEXB_FUNCTIONALITY_SAE'; if (ifHasEvexSAE in Definition.Flags) then U := 'ZYDIS_EVEXB_FUNCTIONALITY_SAE';
Buffer.Append(Format(' /*%.4x*/ ', [Index])); Buffer.Append(Format(' /*%.4x*/ ', [Index]));
Buffer.Append(Format('ZYDIS_MAKE_INSTRUCTIONDEFINITION(ZYDIS_MNEMONIC_%s, 0x%.4x, %s, %s, %s)', [ Buffer.Append(Format('{ ZYDIS_MNEMONIC_%s, 0x%.4x, %s, %s, %s, %d, %d, %d, %d, %d, %d, %d }', [
AnsiUpperCase(Definition.Mnemonic), O, U, S, T])); AnsiUpperCase(Definition.Mnemonic), O, U, S, T,
Byte(pfAcceptsLock in Definition.PrefixFlags),
Byte(pfAcceptsREP in Definition.PrefixFlags),
Byte(pfAcceptsREPEREPNE in Definition.PrefixFlags),
Byte(pfAcceptsXACQUIRE in Definition.PrefixFlags),
Byte(pfAcceptsXRELEASE in Definition.PrefixFlags),
Byte(pfAcceptsHLEWithoutLock in Definition.PrefixFlags),
Byte(pfAcceptsBranchHints in Definition.PrefixFlags)]));
end; end;
var var
@ -573,7 +580,7 @@ var
begin begin
Buffer := TStringBuffer.Create; Buffer := TStringBuffer.Create;
try try
Buffer.AppendLn('const ZydisInternalInstructionDefinition instructionDefinitions[] ='); Buffer.AppendLn('const ZydisInstructionDefinition instructionDefinitions[] =');
Buffer.AppendLn('{'); Buffer.AppendLn('{');
WorkStart('Generating instruction definitions', 0, Length(DefinitionList)); WorkStart('Generating instruction definitions', 0, Length(DefinitionList));
for I := Low(DefinitionList) to High(DefinitionList) do for I := Low(DefinitionList) to High(DefinitionList) do
@ -637,7 +644,7 @@ begin
end; end;
// Open the filter-array // Open the filter-array
Buffer.AppendLn(Format('const ZydisInternalInstructionTableNode filter%s[][%d] = ', [ Buffer.AppendLn(Format('const ZydisInstructionTableNode filter%s[][%d] = ', [
InstructionFilterClasses[I].GetDescription, InstructionFilterClasses[I].GetDescription,
Integer(InstructionFilterClasses[I].GetCapacity) - IndexShift])); Integer(InstructionFilterClasses[I].GetCapacity) - IndexShift]));
Buffer.AppendLn('{'); Buffer.AppendLn('{');
@ -943,7 +950,7 @@ begin
opaWrite : OperandAccessMode := 'WRITE'; opaWrite : OperandAccessMode := 'WRITE';
opaReadWrite : OperandAccessMode := 'READWRITE'; opaReadWrite : OperandAccessMode := 'READWRITE';
end; end;
Buffer.Append(Format('ZYDIS_MAKE_OPERANDDEFINITION(ZYDIS_SEM_OPERAND_TYPE_%s, ' + Buffer.Append(Format('ZYDIS_OPERAND_DEFINITION(ZYDIS_SEM_OPERAND_TYPE_%s, ' +
'ZYDIS_OPERAND_ENCODING_%s, ZYDIS_OPERAND_ACCESS_%s)', [ 'ZYDIS_OPERAND_ENCODING_%s, ZYDIS_OPERAND_ACCESS_%s)', [
OperandType, OperandEncoding, OperandAccessMode])); OperandType, OperandEncoding, OperandAccessMode]));
end; end;
@ -966,7 +973,7 @@ begin
// Generate operand-definition tables // Generate operand-definition tables
for I := Low(OperandMapping) to High(OperandMapping) do for I := Low(OperandMapping) to High(OperandMapping) do
begin begin
Buffer.AppendLn(Format('const ZydisInternalOperandDefinition operandDefinitions%d[][%d] =', Buffer.AppendLn(Format('const ZydisOperandDefinition operandDefinitions%d[][%d] =',
[I, I])); [I, I]));
Buffer.AppendLn('{'); Buffer.AppendLn('{');
for J := Low(OperandMapping[I]) to High(OperandMapping[I]) do for J := Low(OperandMapping[I]) to High(OperandMapping[I]) do
@ -996,7 +1003,7 @@ begin
Buffer.Append(Format(' /*%.4x*/ { ', [0])); Buffer.Append(Format(' /*%.4x*/ { ', [0]));
for K := 1 to I do for K := 1 to I do
begin begin
Buffer.Append('ZYDIS_MAKE_OPERANDDEFINITION(ZYDIS_SEM_OPERAND_TYPE_UNUSED, ' + Buffer.Append('ZYDIS_OPERAND_DEFINITION(ZYDIS_SEM_OPERAND_TYPE_UNUSED, ' +
'ZYDIS_OPERAND_ENCODING_NONE, ZYDIS_OPERAND_ACCESS_READ)'); 'ZYDIS_OPERAND_ENCODING_NONE, ZYDIS_OPERAND_ACCESS_READ)');
if (K <> I) then if (K <> I) then
begin begin

View File

@ -355,6 +355,38 @@ type
property FlagID: TX86FlagValue read FID write SetID default fvUnused; property FlagID: TX86FlagValue read FID write SetID default fvUnused;
end; end;
{TEVEXEncodingContext = (
ecNone,
ecBroadcast,
ecRoundingControl,
ecSuppressAllExceptions
);
TEVEXInformation = class(TPersistent)
strict private
FDefinition: TInstructionDefinition;
strict private
procedure Changed; inline;
strict private
function GetConflictState: Boolean;
private
procedure LoadFromJSON(JSON: PJSONVariantData; const FieldName: String);
procedure SaveToJSON(JSON: PJSONVariantData; const FieldName: String);
protected
procedure AssignTo(Dest: TPersistent); override;
protected
constructor Create(Definition: TInstructionDefinition);
public
function Equals(const Value: TX86Flags): Boolean; reintroduce;
public
property HasConflicts: Boolean read GetConflictState;
published
property EncodingContext: TEVEXEncodingContext;
property HasEvexAAA: Boolean;
property HasEvexZ: Boolean;
property CD8Scale: Cardinal;
end;}
TInstructionOperands = class; TInstructionOperands = class;
TOperandType = ( TOperandType = (
@ -542,6 +574,8 @@ type
idcForcedConflict, idcForcedConflict,
// The instruction-operands configuration is invalid // The instruction-operands configuration is invalid
idcOperands, idcOperands,
// The prefix-flags are invalid
idcPrefixFlags,
// The FLAGS/EFLAGS/RFLAGS registers in the ImplicitRead or ImplicitWrite property do not // The FLAGS/EFLAGS/RFLAGS registers in the ImplicitRead or ImplicitWrite property do not
// match the given X86Flags configuration // match the given X86Flags configuration
idcX86Flags idcX86Flags
@ -568,13 +602,19 @@ type
TOpcodeByte = type Byte; TOpcodeByte = type Byte;
TPrefixFlag = (
pfAcceptsLock,
pfAcceptsREP,
pfAcceptsREPEREPNE,
pfAcceptsXACQUIRE,
pfAcceptsXRELEASE,
pfAcceptsHLEWithoutLock,
pfAcceptsBranchHints
);
TPrefixFlags = set of TPrefixFlag;
TInstructionDefinitionFlag = ( TInstructionDefinitionFlag = (
ifForceConflict, ifForceConflict,
ifAcceptsLock,
ifAcceptsREP,
ifAcceptsXACQUIRE,
ifAcceptsXRELEASE,
ifAcceptsBranchHints,
ifAcceptsEVEXAAA, ifAcceptsEVEXAAA,
ifAcceptsEVEXZ, ifAcceptsEVEXZ,
ifIsPrivileged, ifIsPrivileged,
@ -601,6 +641,7 @@ type
FExtensions: TOpcodeExtensions; FExtensions: TOpcodeExtensions;
FCPUID: TCPUIDFeatureFlags; FCPUID: TCPUIDFeatureFlags;
FOperands: TInstructionOperands; FOperands: TInstructionOperands;
FPrefixFlags: TPrefixFlags;
FFlags: TInstructionDefinitionFlags; FFlags: TInstructionDefinitionFlags;
FImplicitRead: TX86Registers; FImplicitRead: TX86Registers;
FImplicitWrite: TX86Registers; FImplicitWrite: TX86Registers;
@ -613,6 +654,7 @@ type
procedure SetEncoding(const Value: TInstructionEncoding); inline; procedure SetEncoding(const Value: TInstructionEncoding); inline;
procedure SetOpcodeMap(const Value: TOpcodeMap); inline; procedure SetOpcodeMap(const Value: TOpcodeMap); inline;
procedure SetOpcode(const Value: TOpcodeByte); inline; procedure SetOpcode(const Value: TOpcodeByte); inline;
procedure SetPrefixFlags(const Value: TPrefixFlags); inline;
procedure SetFlags(const Value: TInstructionDefinitionFlags); inline; procedure SetFlags(const Value: TInstructionDefinitionFlags); inline;
procedure SetComment(const Value: String); inline; procedure SetComment(const Value: String); inline;
strict private strict private
@ -650,7 +692,8 @@ type
property OpcodeExtensions: TOpcodeExtensions read FExtensions; property OpcodeExtensions: TOpcodeExtensions read FExtensions;
property CPUID: TCPUIDFeatureFlags read FCPUID; property CPUID: TCPUIDFeatureFlags read FCPUID;
property Operands: TInstructionOperands read FOperands; property Operands: TInstructionOperands read FOperands;
property Flags: TInstructionDefinitionFlags read FFlags write SetFlags; property PrefixFlags: TPrefixFlags read FPrefixFlags write SetPrefixFlags default [];
property Flags: TInstructionDefinitionFlags read FFlags write SetFlags default [];
property ImplicitRead: TX86Registers read FImplicitRead; property ImplicitRead: TX86Registers read FImplicitRead;
property ImplicitWrite: TX86Registers read FImplicitWrite; property ImplicitWrite: TX86Registers read FImplicitWrite;
property X86Flags: TX86Flags read FX86Flags; property X86Flags: TX86Flags read FX86Flags;
@ -1204,13 +1247,18 @@ const
'xopa' 'xopa'
); );
SInstructionDefinitionFlag: array[TInstructionDefinitionFlag] of String = ( SPrefixFlag: array[TPrefixFlag] of String = (
'conflict',
'accepts_lock', 'accepts_lock',
'accepts_rep', 'accepts_rep',
'accepts_reperepne',
'accepts_xacquire', 'accepts_xacquire',
'accepts_xrelease', 'accepts_xrelease',
'accepts_branch_hints', 'accepts_hle_without_lock',
'accepts_branch_hints'
);
SInstructionDefinitionFlag: array[TInstructionDefinitionFlag] of String = (
'conflict',
'accepts_evex_aaa', 'accepts_evex_aaa',
'accepts_evex_z', 'accepts_evex_z',
'privileged', 'privileged',
@ -1223,7 +1271,7 @@ const
{$REGION 'Class: TJSONEnumHelper'} {$REGION 'Class: TJSONEnumHelper'}
type type
TJSONEnumHelper = record TJSONEnumHelper = record
private strict private
class function ReadString(JSON: PJSONVariantData; const Name, Default: String; class function ReadString(JSON: PJSONVariantData; const Name, Default: String;
const LowerCase: Boolean = true): String; static; inline; const LowerCase: Boolean = true): String; static; inline;
public public
@ -1259,6 +1307,116 @@ begin
end; end;
{$ENDREGION} {$ENDREGION}
{$REGION 'Class: TJSONSetHelper'}
type
TJSONSetHelper<TSet> = record
strict private
class procedure GetEnumBounds(var MinValue, MaxValue: Integer); static; inline;
public
class function ReadValue(JSON: PJSONVariantData; const Name: String;
const ElementStrings: array of String): TSet; static;
class procedure WriteValue(JSON: PJSONVariantData; const Name: String;
const ElementStrings: array of String; Value: TSet); static;
end;
class procedure TJSONSetHelper<TSet>.GetEnumBounds(var MinValue, MaxValue: Integer);
var
TypInfo: PTypeInfo;
TypData: PTypeData;
begin
TypInfo := TypeInfo(TSet);
{$IFDEF DEBUG}
if (TypInfo^.Kind <> tkSet) then
begin
raise Exception.Create('Invalid generic type.');
end;
{$ENDIF}
TypData := GetTypeData(GetTypeData(TypInfo)^.CompType^);
{$IFDEF DEBUG}
if (TypData^.MinValue <> 0) then
begin
raise Exception.Create('The enum-type needs to be zero-based.');
end;
if (TypData^.MaxValue > 255) then
begin
raise Exception.Create('The enum-type''s maximum value needs the be lower than 256.');
end;
{$ENDIF}
MinValue := TypData^.MinValue;
MaxValue := TypData^.MaxValue;
end;
class function TJSONSetHelper<TSet>.ReadValue(JSON: PJSONVariantData; const Name: String;
const ElementStrings: array of String): TSet;
type
TSetType = set of 0..255;
var
A: PJSONVariantData;
MinValue,
MaxValue: Integer;
I, J: Integer;
begin
GetEnumBounds(MinValue, MaxValue);
{$IFDEF DEBUG}
if (MaxValue <> High(ElementStrings)) then
begin
raise Exception.Create('The size of the string-array does not match the size of the enum-type');
end;
{$ENDIF}
FillChar(Pointer(@Result)^, SizeOf(TSet), #0);
A := JSON^.Data(Name);
if (Assigned(A)) then
begin
if (A^.Kind <> jvArray) then
begin
raise Exception.CreateFmt('The "%s" field is not a valid JSON array.', [Name]);
end;
for I := 0 to A^.Count - 1 do
begin
for J := MinValue to MaxValue do
begin
if (LowerCase(A^.Item[I]) = ElementStrings[J]) then
begin
Include(TSetType(Pointer(@Result)^), J);
Break;
end;
end;
end;
end;
end;
class procedure TJSONSetHelper<TSet>.WriteValue(JSON: PJSONVariantData; const Name: String;
const ElementStrings: array of String; Value: TSet);
type
TSetType = set of 0..255;
var
A: TJSONVariantData;
MinValue,
MaxValue: Integer;
I: Integer;
begin
GetEnumBounds(MinValue, MaxValue);
{$IFDEF DEBUG}
if (MaxValue <> High(ElementStrings)) then
begin
raise Exception.Create('The size of the string-array does not match the size of the enum-type');
end;
{$ENDIF}
A.Init;
for I := MinValue to MaxValue do
begin
if (I in TSetType(Pointer(@Value)^)) then
begin
A.AddValue(ElementStrings[I]);
end;
end;
if (A.Count > 0) then
begin
JSON^.AddNameValue(Name, Variant(A));
end;
end;
{$ENDREGION}
{$REGION 'Class: TOpcodeExtensions'} {$REGION 'Class: TOpcodeExtensions'}
procedure TOpcodeExtensions.AssignTo(Dest: TPersistent); procedure TOpcodeExtensions.AssignTo(Dest: TPersistent);
var var
@ -1301,10 +1459,8 @@ end;
procedure TOpcodeExtensions.LoadFromJSON(JSON: PJSONVariantData; const FieldName: String); procedure TOpcodeExtensions.LoadFromJSON(JSON: PJSONVariantData; const FieldName: String);
var var
V, A: PJSONVariantData; V: PJSONVariantData;
I: Integer; I: Integer;
F: TExtBitFilter;
BitFilters: TExtBitFilters;
begin begin
V := JSON.Data(FieldName); V := JSON.Data(FieldName);
if (Assigned(V)) then if (Assigned(V)) then
@ -1327,34 +1483,13 @@ begin
SetOperandSize(TExtOperandSize(I)); SetOperandSize(TExtOperandSize(I));
I := TJSONEnumHelper.ReadEnumValueFromString(V, 'adsize', SExtAddressSize); I := TJSONEnumHelper.ReadEnumValueFromString(V, 'adsize', SExtAddressSize);
SetAddressSize(TExtAddressSize(I)); SetAddressSize(TExtAddressSize(I));
A := V^.Data('bitfilters'); SetBitFilters(TJSONSetHelper<TExtBitFilters>.ReadValue(V, 'bitfilters', SExtBitFilter));
if (Assigned(A)) then
begin
if (A^.Kind <> jvArray) then
begin
raise Exception.Create('The "prefix_flags" field is not a valid JSON array.');
end;
BitFilters := [];
for I := 0 to A^.Count - 1 do
begin
for F := Low(SExtBitFilter) to High(SExtBitFilter) do
begin
if (LowerCase(A^.Item[I]) = SExtBitFilter[F]) then
begin
BitFilters := BitFilters + [F];
Break;
end;
end;
end;
SetBitFilters(BitFilters);
end;
end; end;
end; end;
procedure TOpcodeExtensions.SaveToJSON(JSON: PJSONVariantData; const FieldName: String); procedure TOpcodeExtensions.SaveToJSON(JSON: PJSONVariantData; const FieldName: String);
var var
V, A: TJSONVariantData; V: TJSONVariantData;
F: TExtBitFilter;
begin begin
V.Init; V.Init;
if (FMode <> imNeutral) then if (FMode <> imNeutral) then
@ -1371,15 +1506,7 @@ begin
V.AddNameValue('opsize', SExtOperandSize[FOperandSize]); V.AddNameValue('opsize', SExtOperandSize[FOperandSize]);
if (FAddressSize <> asNeutral) then if (FAddressSize <> asNeutral) then
V.AddNameValue('adsize', SExtAddressSize[FAddressSize]); V.AddNameValue('adsize', SExtAddressSize[FAddressSize]);
A.Init; TJSONSetHelper<TExtBitFilters>.WriteValue(@V, 'bitfilters', SExtBitFilter, FBitFilters);
for F in FBitFilters do
begin
A.AddValue(SExtBitFilter[F]);
end;
if (A.Count > 0) then
begin
V.AddNameValue('bitfilters', Variant(A));
end;
if (V.Count > 0) then if (V.Count > 0) then
begin begin
JSON^.AddNameValue(FieldName, Variant(V)); JSON^.AddNameValue(FieldName, Variant(V));
@ -1493,49 +1620,15 @@ begin
end; end;
procedure TCPUIDFeatureFlags.LoadFromJSON(JSON: PJSONVariantData; const FieldName: String); procedure TCPUIDFeatureFlags.LoadFromJSON(JSON: PJSONVariantData; const FieldName: String);
var
A: PJSONVariantData;
I: Integer;
C: TCPUIDFeatureFlag;
Value: TCPUIDFeatureFlagSet;
begin begin
A := JSON.Data(FieldName); SetFeatureFlags(
if (Assigned(A)) then TJSONSetHelper<TCPUIDFeatureFlagSet>.ReadValue(JSON, FieldName, SCPUIDFeatureFlag));
begin
if (A^.Kind <> jvArray) then
begin
raise Exception.CreateFmt('The "%s" field is not a valid JSON array.', [FieldName]);
end;
Value := [];
for I := 0 to A^.Count - 1 do
begin
for C := Low(SCPUIDFeatureFlag) to High(SCPUIDFeatureFlag) do
begin
if (LowerCase(A^.Item[I]) = SCPUIDFeatureFlag[C]) then
begin
Value := Value + [C];
Break;
end;
end;
end;
SetFeatureFlags(Value);
end;
end; end;
procedure TCPUIDFeatureFlags.SaveToJSON(JSON: PJSONVariantData; const FieldName: String); procedure TCPUIDFeatureFlags.SaveToJSON(JSON: PJSONVariantData; const FieldName: String);
var
A: TJSONVariantData;
C: TCPUIDFeatureFlag;
begin begin
A.Init; TJSONSetHelper<TCPUIDFeatureFlagSet>.WriteValue(
for C in FFeatureFlags do JSON, FieldName, SCPUIDFeatureFlag, FFeatureFlags);
begin
A.AddValue(SCPUIDFeatureFlag[C]);
end;
if (A.Count > 0) then
begin
JSON.AddNameValue(FieldName, Variant(A));
end;
end; end;
procedure TCPUIDFeatureFlags.SetFeatureFlags(const Value: TCPUIDFeatureFlagSet); procedure TCPUIDFeatureFlags.SetFeatureFlags(const Value: TCPUIDFeatureFlagSet);
@ -1577,49 +1670,13 @@ begin
end; end;
procedure TX86Registers.LoadFromJSON(JSON: PJSONVariantData; const FieldName: String); procedure TX86Registers.LoadFromJSON(JSON: PJSONVariantData; const FieldName: String);
var
A: PJSONVariantData;
I: Integer;
R: TX86Register;
Value: TX86RegisterSet;
begin begin
A := JSON^.Data(FieldName); SetRegisters(TJSONSetHelper<TX86RegisterSet>.ReadValue(JSON, FieldName, SX86Register));
if (Assigned(A)) then
begin
if (A^.Kind <> jvArray) then
begin
raise Exception.CreateFmt('The "%s" field is not a valid JSON array.', [FieldName]);
end;
Value := [];
for I := 0 to A^.Count - 1 do
begin
for R := Low(SX86Register) to High(SX86Register) do
begin
if (LowerCase(A^.Item[I]) = SX86Register[R]) then
begin
Value := Value + [R];
Break;
end;
end;
end;
SetRegisters(Value);
end;
end; end;
procedure TX86Registers.SaveToJSON(JSON: PJSONVariantData; const FieldName: String); procedure TX86Registers.SaveToJSON(JSON: PJSONVariantData; const FieldName: String);
var
A: TJSONVariantData;
R: TX86Register;
begin begin
A.Init; TJSONSetHelper<TX86RegisterSet>.WriteValue(JSON, FieldName, SX86Register, FRegisters);
for R in FRegisters do
begin
A.AddValue(SX86Register[R]);
end;
if (A.Count > 0) then
begin
JSON.AddNameValue(FieldName, Variant(A));
end;
end; end;
procedure TX86Registers.SetRegisters(const Value: TX86RegisterSet); procedure TX86Registers.SetRegisters(const Value: TX86RegisterSet);
@ -2480,7 +2537,7 @@ var
begin begin
for I := Low(FOperands) to High(FOperands) do for I := Low(FOperands) to High(FOperands) do
begin begin
if (Assigned(FOperands[I])) then FOperands[I].Free; FOperands[I].Free;
end; end;
inherited; inherited;
end; end;
@ -2683,12 +2740,12 @@ begin
end; end;
// Remove definition from the definition list // Remove definition from the definition list
FEditor.UnregisterDefinition(Self); FEditor.UnregisterDefinition(Self);
if (Assigned(FExtensions)) then FExtensions.Free; FExtensions.Free;
if (Assigned(FCPUID)) then FCPUID.Free; FCPUID.Free;
if (Assigned(FOperands)) then FOperands.Free; FOperands.Free;
if (Assigned(FImplicitRead)) then FImplicitRead.Free; FImplicitRead.Free;
if (Assigned(FImplicitWrite)) then FImplicitWrite.Free; FImplicitWrite.Free;
if (Assigned(FX86Flags)) then FX86Flags.Free; FX86Flags.Free;
inherited; inherited;
end; end;
@ -2735,9 +2792,6 @@ end;
procedure TInstructionDefinition.LoadFromJSON(JSON: PJSONVariantData); procedure TInstructionDefinition.LoadFromJSON(JSON: PJSONVariantData);
var var
I: Integer; I: Integer;
A: PJSONVariantData;
F: TInstructionDefinitionFlag;
Flags: TInstructionDefinitionFlags;
begin begin
BeginUpdate; BeginUpdate;
try try
@ -2764,27 +2818,9 @@ begin
FOperands.LoadFromJSON(JSON, 'operands'); FOperands.LoadFromJSON(JSON, 'operands');
FImplicitRead.LoadFromJSON(JSON, 'implicit_read'); FImplicitRead.LoadFromJSON(JSON, 'implicit_read');
FImplicitWrite.LoadFromJSON(JSON, 'implicit_write'); FImplicitWrite.LoadFromJSON(JSON, 'implicit_write');
A := JSON.Data('flags'); SetFlags(TJSONSetHelper<TInstructionDefinitionFlags>.ReadValue(
if (Assigned(A)) then JSON, 'flags', SInstructionDefinitionFlag));
begin SetPrefixFlags(TJSONSetHelper<TPrefixFlags>.ReadValue(JSON, 'prefix_flags', SPrefixFlag));
if (A^.Kind <> jvArray) then
begin
raise Exception.Create('The "flags" field is not a valid JSON array.');
end;
Flags := [];
for I := 0 to A^.Count - 1 do
begin
for F := Low(SInstructionDefinitionFlag) to High(SInstructionDefinitionFlag) do
begin
if (LowerCase(A^.Item[I]) = SInstructionDefinitionFlag[F]) then
begin
Flags := Flags + [F];
Break;
end;
end;
end;
SetFlags(Flags);
end;
FX86Flags.LoadFromJSON(JSON, 'x86flags'); FX86Flags.LoadFromJSON(JSON, 'x86flags');
FComment := JSON^.Value['comment']; FComment := JSON^.Value['comment'];
finally finally
@ -2793,9 +2829,6 @@ begin
end; end;
procedure TInstructionDefinition.SaveToJSON(JSON: PJSONVariantData); procedure TInstructionDefinition.SaveToJSON(JSON: PJSONVariantData);
var
A: TJSONVariantData;
F: TInstructionDefinitionFlag;
begin begin
JSON^.AddNameValue('mnemonic', FMnemonic); JSON^.AddNameValue('mnemonic', FMnemonic);
JSON^.AddNameValue('opcode', LowerCase(IntToHex(FOpcode, 2))); JSON^.AddNameValue('opcode', LowerCase(IntToHex(FOpcode, 2)));
@ -2806,15 +2839,9 @@ begin
FOperands.SaveToJSON(JSON, 'operands'); FOperands.SaveToJSON(JSON, 'operands');
FImplicitRead.SaveToJSON(JSON, 'implicit_read'); FImplicitRead.SaveToJSON(JSON, 'implicit_read');
FImplicitWrite.SaveToJSON(JSON, 'implicit_write'); FImplicitWrite.SaveToJSON(JSON, 'implicit_write');
A.Init; TJSONSetHelper<TInstructionDefinitionFlags>.WriteValue(JSON, 'flags',
for F in FFlags do SInstructionDefinitionFlag, FFlags);
begin TJSONSetHelper<TPrefixFlags>.WriteValue(JSON, 'prefix_flags', SPrefixFlag, FPrefixFlags);
A.AddValue(SInstructionDefinitionFlag[F]);
end;
if (A.Count > 0) then
begin
JSON^.AddNameValue('flags', Variant(A));
end;
FX86Flags.SaveToJSON(JSON, 'x86flags'); FX86Flags.SaveToJSON(JSON, 'x86flags');
if (FComment <> '') then if (FComment <> '') then
begin begin
@ -2946,6 +2973,15 @@ begin
end; end;
end; end;
procedure TInstructionDefinition.SetPrefixFlags(const Value: TPrefixFlags);
begin
if (FPrefixFlags <> Value) then
begin
FPrefixFlags := Value;
UpdateValues;
end;
end;
procedure TInstructionDefinition.Update; procedure TInstructionDefinition.Update;
begin begin
UpdatePosition; UpdatePosition;
@ -2965,6 +3001,33 @@ begin
begin begin
Include(Conflicts, idcOperands); Include(Conflicts, idcOperands);
end; end;
if ((pfAcceptsXACQUIRE in FPrefixFlags) or (pfAcceptsXRELEASE in FPrefixFlags)) and
(not ((pfAcceptsLock in FPrefixFlags) or (pfAcceptsHLEWithoutLock in FPrefixFlags))) then
begin
Include(Conflicts, idcPrefixFlags);
end;
if ((pfAcceptsXACQUIRE in FPrefixFlags) or (pfAcceptsXRELEASE in FPrefixFlags)) and
((pfAcceptsREP in FPrefixFlags) or (pfAcceptsREPEREPNE in FPrefixFlags)) then
begin
Include(Conflicts, idcPrefixFlags);
end;
if ((pfAcceptsLock in FPrefixFlags) or (pfAcceptsXACQUIRE in FPrefixFlags) or
(pfAcceptsXRELEASE in FPrefixFlags)) and (not (FOperands.Operands[0].OperandType in [
optMem8, optMem16, optMem32, optMem64, optMem128])) then
begin
Include(Conflicts, idcPrefixFlags);
end;
if ((pfAcceptsREP in FPrefixFlags) and (pfAcceptsREPEREPNE in FPrefixFlags)) then
begin
Include(Conflicts, idcPrefixFlags);
end;
if (pfAcceptsBranchHints in FPrefixFlags) and (not (FOperands.Operands[0].OperandType in [
optRel8, optRel16, optRel32, optRel64])) then
begin
Include(Conflicts, idcPrefixFlags);
end;
if (FX86Flags.HasConflicts) then if (FX86Flags.HasConflicts) then
begin begin
Include(Conflicts, idcX86Flags); Include(Conflicts, idcX86Flags);
@ -3071,7 +3134,7 @@ end;
destructor TInstructionFilter.Destroy; destructor TInstructionFilter.Destroy;
begin begin
Assert((FItemCount = 0) and (FParent = nil)); Assert((FItemCount = 0) and (FParent = nil));
if Assigned(FDefinitions) then if (Assigned(FDefinitions)) then
begin begin
Assert(FDefinitions.Count = 0); Assert(FDefinitions.Count = 0);
FDefinitions.Free; FDefinitions.Free;
@ -3865,11 +3928,23 @@ var
I: Integer; I: Integer;
JSONDefinitionList, JSONDefinition: TJSONVariantData; JSONDefinitionList, JSONDefinition: TJSONVariantData;
begin begin
// Sort definitions by mnemonic // Sort definitions
Comparison := Comparison :=
function(const Left, Right: TInstructionDefinition): Integer function(const Left, Right: TInstructionDefinition): Integer
begin begin
Result := CompareStr(Left.Mnemonic, Right.Mnemonic); Result := CompareStr(Left.Mnemonic, Right.Mnemonic);
if (Result = 0) then
begin
Result := Ord(Left.Encoding) - Ord(Right.Encoding);
end;
if (Result = 0) then
begin
Result := Ord(Left.OpcodeMap) - Ord(Right.OpcodeMap);
end;
if (Result = 0) then
begin
Result := Left.Opcode - Right.Opcode;
end;
end; end;
FDefinitions.Sort(TComparer<TInstructionDefinition>.Construct(Comparison)); FDefinitions.Sort(TComparer<TInstructionDefinition>.Construct(Comparison));
// Save to JSON // Save to JSON

File diff suppressed because it is too large Load Diff

View File

@ -247,36 +247,36 @@ typedef uint32_t ZydisPrefixFlags;
/** /**
* @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_PREFIXFLAG_ACCEPTS_REPE 0x00400000 #define ZYDIS_PREFIXFLAG_ACCEPTS_REPE 0x00800000
/** /**
* @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_PREFIXFLAG_ACCEPTS_REPZ 0x00400000 #define ZYDIS_PREFIXFLAG_ACCEPTS_REPZ 0x00800000
/** /**
* @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_PREFIXFLAG_ACCEPTS_REPNE 0x00400000 #define ZYDIS_PREFIXFLAG_ACCEPTS_REPNE 0x01000000
/** /**
* @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_PREFIXFLAG_ACCEPTS_REPNZ 0x00400000 #define ZYDIS_PREFIXFLAG_ACCEPTS_REPNZ 0x01000000
/** /**
* @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_PREFIXFLAG_MULTIPLE_GRP1 0x00800000 #define ZYDIS_PREFIXFLAG_MULTIPLE_GRP1 0x02000000
/** /**
* @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_PREFIXFLAG_MULTIPLE_GRP2 0x01000000 #define ZYDIS_PREFIXFLAG_MULTIPLE_GRP2 0x04000000
/** /**
* @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_PREFIXFLAG_MULTIPLE_GRP3 0x02000000 #define ZYDIS_PREFIXFLAG_MULTIPLE_GRP3 0x08000000
/** /**
* @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_PREFIXFLAG_MULTIPLE_GRP4 0x04000000 #define ZYDIS_PREFIXFLAG_MULTIPLE_GRP4 0x10000000
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/* Instruction encoding */ /* Instruction encoding */

View File

@ -0,0 +1,15 @@
typedef struct ZydisInstructionDefinition_
{
uint32_t mnemonic : 11;
uint32_t operandsId : 9;
uint32_t evexBFunctionality : 2;
uint32_t hasEvexAAA : 1;
uint32_t hasEvexZ : 1;
uint32_t acceptsLock : 1;
uint32_t acceptsREP : 1;
uint32_t acceptsREPEREPNE : 1;
uint32_t acceptsXACQUIRE : 1;
uint32_t acceptsXRELEASE : 1;
uint32_t acceptsHLEWithoutLock : 1;
uint32_t acceptsBranchHints : 1;
} ZydisInstructionDefinition;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -41,21 +41,69 @@ extern "C" {
/* ============================================================================================== */ /* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/* Instruction table */ /* Generated types */
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/** // MSVC does not like types other than (un-)signed int for bitfields
* @brief Defines the @c ZydisInstructionTableNode datatype. #ifdef ZYDIS_MSVC
*/ # pragma warning(push)
typedef void* ZydisInstructionTableNode; # pragma warning(disable:4214)
#endif
/* ---------------------------------------------------------------------------------------------- */ #pragma pack(push, 1)
/** /**
* @brief Defines the @c ZydisInstructionTableNodeType datatype. * @brief Defines the @c ZydisInstructionTableNodeType datatype.
*/ */
typedef uint8_t ZydisInstructionTableNodeType; typedef uint8_t ZydisInstructionTableNodeType;
/**
* @brief Defines the @c ZydisInstructionTableNodeValue datatype.
*/
typedef uint16_t ZydisInstructionTableNodeValue;
/**
* @brief Defines the @c ZydisInstructionTableNode struct.
*
* This struct is static for now, because its size is sufficient to encode up to 65535
* instruction filters (what is about 10 times more than we currently need).
*/
typedef struct ZydisInstructionTableNode_
{
ZydisInstructionTableNodeType type;
ZydisInstructionTableNodeValue value;
} ZydisInstructionTableNode;
/**
* @brief Defines the @c ZydisSemanticOperandType datatype.
*/
typedef uint8_t ZydisSemanticOperandType;
/**
* @brief Defines the @c ZydisOperandDefinition struct.
*
* This struct is static for now, because adding more operand-types oder encodings requires
* code changes anyways.
*/
typedef struct ZydisOperandDefinition_
{
ZydisSemanticOperandType type : 7;
ZydisOperandEncoding encoding : 5;
ZydisOperandAccess access : 2;
} ZydisOperandDefinition;
#include <Zydis/Internal/GeneratedTypes.inc>
#pragma pack(pop)
#ifdef ZYDIS_MSVC
# pragma warning(pop)
#endif
/* ---------------------------------------------------------------------------------------------- */
/* Instruction Table */
/* ---------------------------------------------------------------------------------------------- */
/** /**
* @brief Values that represent zydis instruction table node types. * @brief Values that represent zydis instruction table node types.
*/ */
@ -144,20 +192,10 @@ enum ZydisInstructionTableNodeTypes
ZYDIS_NODETYPE_FILTER_EVEXB = 0x14 ZYDIS_NODETYPE_FILTER_EVEXB = 0x14
}; };
/**
* @brief Defines the @c ZydisInstructionTableNodeValue datatype.
*/
typedef uint16_t ZydisInstructionTableNodeValue;
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/* Operand definition */ /* Operand definition */
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisSemanticOperandType datatype.
*/
typedef uint8_t ZydisSemanticOperandType;
/** /**
* @brief Values that represent semantic operand types. * @brief Values that represent semantic operand types.
*/ */
@ -246,34 +284,10 @@ enum ZydisSemanticOperandTypes
ZYDIS_SEM_OPERAND_TYPE_ST0 ZYDIS_SEM_OPERAND_TYPE_ST0
}; };
/**
* @brief Defines the @c ZydisOperandDefinition struct.
*/
typedef struct ZydisOperandDefinition_
{
/**
* @brief The semantic operand type.
*/
ZydisSemanticOperandType type;
/**
* @brief The operand encoding.
*/
ZydisOperandEncoding encoding;
/**
* @brief The operand access-mode.
*/
ZydisOperandAccess access;
} ZydisOperandDefinition;
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/* Instruction definition */ /* Instruction definition */
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisEvexBFunctionality datatype .
*/
typedef uint8_t ZydisEvexBFunctionality;
/** /**
* @brief Values that represent zydis evex.b-functionalities. * @brief Values that represent zydis evex.b-functionalities.
*/ */
@ -285,66 +299,18 @@ enum ZydisEvexBFunctionalities
ZYDIS_EVEXB_FUNCTIONALITY_SAE ZYDIS_EVEXB_FUNCTIONALITY_SAE
}; };
/**
* @brief Defines the @c ZydisInstructionDefinition struct.
*/
typedef struct ZydisInstructionDefinition_
{
/**
* @brief The instruction mnemonic.
*/
ZydisInstructionMnemonic mnemonic;
/**
* @brief The number of used operands.
*/
uint8_t operandCount;
/**
* @brief The operand-definitions.
*/
ZydisOperandDefinition operands[5];
/**
* @brief The evex.b functionality.
*/
ZydisEvexBFunctionality evexBFunctionality;
bool hasEvexAAA;
bool hasEvexZ;
} ZydisInstructionDefinition;
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */ /* ============================================================================================== */
/* Functions */ /* Functions */
/* ============================================================================================== */ /* ============================================================================================== */
/**
* @brief Returns the type of the specified instruction table node.
*
* @param node The node.
*
* @return The type of the specified instruction table node.
*/
ZYDIS_NO_EXPORT ZydisInstructionTableNodeType ZydisInstructionTableGetNodeType(
const ZydisInstructionTableNode node);
/**
* @brief Returns the value of the specified instruction table node.
*
* @param node The node.
*
* @return The value of the specified instruction table node.
*/
ZYDIS_NO_EXPORT ZydisInstructionTableNodeValue ZydisInstructionTableGetNodeValue(
const ZydisInstructionTableNode* node);
/* ---------------------------------------------------------------------------------------------- */
/** /**
* @brief Returns the root node of the instruction table. * @brief Returns the root node of the instruction table.
* *
* @return The root node of the instruction table. * @return The root node of the instruction table.
*/ */
ZYDIS_NO_EXPORT ZydisInstructionTableNode ZydisInstructionTableGetRootNode(); ZYDIS_NO_EXPORT const ZydisInstructionTableNode* ZydisInstructionTableGetRootNode();
/** /**
* @brief Returns the child node of @c parent specified by @c index. * @brief Returns the child node of @c parent specified by @c index.
@ -354,18 +320,25 @@ ZYDIS_NO_EXPORT ZydisInstructionTableNode ZydisInstructionTableGetRootNode();
* *
* @return The specified child node. * @return The specified child node.
*/ */
ZYDIS_NO_EXPORT ZydisInstructionTableNode ZydisInstructionTableGetChildNode( ZYDIS_NO_EXPORT const ZydisInstructionTableNode* ZydisInstructionTableGetChildNode(
const ZydisInstructionTableNode parent, uint16_t index); const ZydisInstructionTableNode* parent, uint16_t index);
/** /**
* @brief Returns the instruction definition that is linked to the given @c node. * @brief Returns the instruction- and operand-definition that is linked to the given @c node.
* *
* @param node The instruction definition node. * @param node The instruction definition node.
* @param definition A pointer to a variable that receives a pointer to the
* instruction-definition.
* @param operands A pointer to a variable that receives a pointer to the first
* operand-definition of the instruction.
* @param operandCount A pointer to a variable that receives the number of operand-definitions
* for the instruction.
* *
* @return Pointer to the instruction definition. * @return @c TRUE, if @c node contained a valid instruction-definition, @c FALSE if not.
*/ */
ZYDIS_NO_EXPORT ZydisInstructionDefinition ZydisInstructionDefinitionByNode( ZYDIS_NO_EXPORT bool ZydisInstructionTableGetDefinition(const ZydisInstructionTableNode* node,
const ZydisInstructionTableNode node); const ZydisInstructionDefinition** definition, const ZydisOperandDefinition** operands,
uint8_t* operandCount);
/* ============================================================================================== */ /* ============================================================================================== */

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

File diff suppressed because it is too large Load Diff

View File

@ -1527,33 +1527,34 @@ static ZydisDecoderStatus ZydisDecodeOperand(ZydisInstructionDecoder* decoder,
/** /**
* @brief Decodes all instruction-operands. * @brief Decodes all instruction-operands.
* *
* @param decoder A pointer to the @c ZydisInstructionDecoder decoder instance. * @param decoder A pointer to the @c ZydisInstructionDecoder decoder instance.
* @param info A pointer to the @c ZydisInstructionInfo struct. * @param info A pointer to the @c ZydisInstructionInfo struct.
* @param definition A pointer to the @c ZydisInstructionDefinition struct. * @param operands A pointer to the first operand-definition of the instruction.
* @param operandCount The number of operands.
* *
* @return A zydis decoder status code. * @return A zydis decoder status code.
*/ */
static ZydisDecoderStatus ZydisDecodeOperands(ZydisInstructionDecoder* decoder, static ZydisDecoderStatus ZydisDecodeOperands(ZydisInstructionDecoder* decoder,
ZydisInstructionInfo* info, const ZydisInstructionDefinition* definition) ZydisInstructionInfo* info, const ZydisOperandDefinition* operands, uint8_t operandCount)
{ {
ZYDIS_ASSERT(decoder); ZYDIS_ASSERT(decoder);
ZYDIS_ASSERT(info); ZYDIS_ASSERT(info);
ZYDIS_ASSERT(definition); ZYDIS_ASSERT(operands);
ZYDIS_ASSERT(definition->operandCount <= 6); ZYDIS_ASSERT(operandCount < 6);
info->operandCount = definition->operandCount; info->operandCount = operandCount;
for (int i = 0; i < definition->operandCount; ++i) for (int i = 0; i < operandCount; ++i)
{ {
ZydisSemanticOperandType type = definition->operands[i].type; ZydisSemanticOperandType type = operands[i].type;
if (type == ZYDIS_SEM_OPERAND_TYPE_UNUSED) if (type == ZYDIS_SEM_OPERAND_TYPE_UNUSED)
{ {
break; break;
} }
ZydisInstructionEncoding encoding = definition->operands[i].encoding; ZydisInstructionEncoding encoding = operands[i].encoding;
ZydisDecoderStatus status = ZydisDecoderStatus status =
ZydisDecodeOperand(decoder, info, &info->operand[i], type, encoding); ZydisDecodeOperand(decoder, info, &info->operand[i], type, encoding);
info->operand[i].encoding = encoding; info->operand[i].encoding = encoding;
info->operand[i].access = definition->operands[i].access; info->operand[i].access = operands[i].access;
if (status != ZYDIS_STATUS_DECODER_SUCCESS) if (status != ZYDIS_STATUS_DECODER_SUCCESS)
{ {
info->instrFlags |= ZYDIS_INSTRFLAG_ERROR_OPERANDS; info->instrFlags |= ZYDIS_INSTRFLAG_ERROR_OPERANDS;
@ -1607,129 +1608,86 @@ static ZydisDecoderStatus ZydisDecodeOperands(ZydisInstructionDecoder* decoder,
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
static void ZydisFinalizeInstructionInfo(ZydisInstructionInfo* info) /**
* @brief Finalizes the @c ZydisInstructionInfo struct by adding additional information.
*
* @param info A pointer to the @c ZydisInstructionInfo struct.
* @param definition A pointer to the @c ZydisInstructionDefinition struct.
*/
static void ZydisFinalizeInstructionInfo(ZydisInstructionInfo* info,
const ZydisInstructionDefinition* definition)
{ {
ZYDIS_ASSERT(info); ZYDIS_ASSERT(info);
ZYDIS_ASSERT(definition);
// TODO: Encode all these things in the instruction definition // Set prefix-flags
if (definition->acceptsLock)
// Adjust prefix flags
switch (info->mnemonic)
{ {
case ZYDIS_MNEMONIC_ADD: info->prefixFlags |= ZYDIS_PREFIXFLAG_ACCEPTS_LOCK;
case ZYDIS_MNEMONIC_ADC: }
case ZYDIS_MNEMONIC_AND: if (definition->acceptsREP)
case ZYDIS_MNEMONIC_BTC: {
case ZYDIS_MNEMONIC_BTR: info->prefixFlags |= ZYDIS_PREFIXFLAG_ACCEPTS_REP;
case ZYDIS_MNEMONIC_BTS: } else if (definition->acceptsREPEREPNE)
case ZYDIS_MNEMONIC_CMPXCHG: {
case ZYDIS_MNEMONIC_CMPXCHG8B: info->prefixFlags |= ZYDIS_PREFIXFLAG_ACCEPTS_REPE | ZYDIS_PREFIXFLAG_ACCEPTS_REPNE;
case ZYDIS_MNEMONIC_CMPXCHG16B: }
case ZYDIS_MNEMONIC_DEC: if ((info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_LOCK) || (definition->acceptsHLEWithoutLock))
case ZYDIS_MNEMONIC_INC: {
case ZYDIS_MNEMONIC_NEG: if (definition->acceptsXACQUIRE && (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_REPE))
case ZYDIS_MNEMONIC_NOT:
case ZYDIS_MNEMONIC_OR:
case ZYDIS_MNEMONIC_SBB:
case ZYDIS_MNEMONIC_SUB:
case ZYDIS_MNEMONIC_XOR:
case ZYDIS_MNEMONIC_XADD:
case ZYDIS_MNEMONIC_XCHG:
if (info->operand[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
{ {
info->prefixFlags |= ZYDIS_PREFIXFLAG_ACCEPTS_LOCK; info->prefixFlags |= ZYDIS_PREFIXFLAG_HAS_XACQUIRE;
info->prefixFlags &= ~ZYDIS_PREFIXFLAG_HAS_REPE;
}
if (definition->acceptsXRELEASE && (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_REPNE))
{
info->prefixFlags |= ZYDIS_PREFIXFLAG_HAS_XRELEASE;
info->prefixFlags &= ~ZYDIS_PREFIXFLAG_HAS_REPNE;
} }
break; }
case ZYDIS_MNEMONIC_MOVSB: if (definition->acceptsBranchHints)
case ZYDIS_MNEMONIC_MOVSW: {
case ZYDIS_MNEMONIC_MOVSD:
case ZYDIS_MNEMONIC_MOVSQ:
case ZYDIS_MNEMONIC_CMPS: // TODO: Only the string-instruction! We will use flags later.
case ZYDIS_MNEMONIC_SCASB:
case ZYDIS_MNEMONIC_SCASW:
case ZYDIS_MNEMONIC_SCASD:
case ZYDIS_MNEMONIC_SCASQ:
case ZYDIS_MNEMONIC_LODSB:
case ZYDIS_MNEMONIC_LODSW:
case ZYDIS_MNEMONIC_LODSD:
case ZYDIS_MNEMONIC_LODSQ:
case ZYDIS_MNEMONIC_STOSB:
case ZYDIS_MNEMONIC_STOSW:
case ZYDIS_MNEMONIC_STOSD:
case ZYDIS_MNEMONIC_STOSQ:
case ZYDIS_MNEMONIC_INSB:
case ZYDIS_MNEMONIC_INSW:
case ZYDIS_MNEMONIC_INSD:
case ZYDIS_MNEMONIC_OUTSB:
case ZYDIS_MNEMONIC_OUTSW:
case ZYDIS_MNEMONIC_OUTSD:
info->prefixFlags |= ZYDIS_PREFIXFLAG_ACCEPTS_REP | ZYDIS_PREFIXFLAG_ACCEPTS_REPNE;
break;
case ZYDIS_MNEMONIC_JO:
case ZYDIS_MNEMONIC_JNO:
case ZYDIS_MNEMONIC_JS:
case ZYDIS_MNEMONIC_JNS:
case ZYDIS_MNEMONIC_JE:
case ZYDIS_MNEMONIC_JNE:
case ZYDIS_MNEMONIC_JB:
case ZYDIS_MNEMONIC_JAE:
case ZYDIS_MNEMONIC_JBE:
case ZYDIS_MNEMONIC_JA:
case ZYDIS_MNEMONIC_JL:
case ZYDIS_MNEMONIC_JGE:
case ZYDIS_MNEMONIC_JLE:
case ZYDIS_MNEMONIC_JG:
case ZYDIS_MNEMONIC_JP:
case ZYDIS_MNEMONIC_JNP:
case ZYDIS_MNEMONIC_JCXZ:
case ZYDIS_MNEMONIC_JECXZ:
case ZYDIS_MNEMONIC_JRCXZ:
if (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_SEGMENT_CS) if (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_SEGMENT_CS)
{ {
info->prefixFlags &= ~ZYDIS_PREFIXFLAG_HAS_SEGMENT_CS;
info->prefixFlags |= ZYDIS_PREFIXFLAG_HAS_BRANCH_NOT_TAKEN; info->prefixFlags |= ZYDIS_PREFIXFLAG_HAS_BRANCH_NOT_TAKEN;
} else info->prefixFlags &= ~ZYDIS_PREFIXFLAG_HAS_SEGMENT_CS;
}
if (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_SEGMENT_DS) if (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_SEGMENT_DS)
{ {
info->prefixFlags |= ZYDIS_PREFIXFLAG_HAS_BRANCH_TAKEN;
info->prefixFlags &= ~ZYDIS_PREFIXFLAG_HAS_SEGMENT_DS; info->prefixFlags &= ~ZYDIS_PREFIXFLAG_HAS_SEGMENT_DS;
info->prefixFlags |= ZYDIS_PREFIXFLAG_HAS_BRANCH_TAKEN;
} }
break;
default:
break;
} }
if ((info->prefixFlags & ZYDIS_PREFIXFLAG_ACCEPTS_LOCK) &&
((info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_REP) || // Set AVX-512 info
(info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_REPNE))) if (info->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX)
{ {
if (info->mnemonic != ZYDIS_MNEMONIC_CMPXCHG16B) if (definition->hasEvexAAA && info->details.evex.aaa)
{ {
if ((info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_LOCK) || info->avx.maskRegister = ZYDIS_REGISTER_K0 + info->details.evex.aaa;
(info->mnemonic == ZYDIS_MNEMONIC_XCHG)) }
{ if (definition->hasEvexZ && info->details.evex.z)
if (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_REPNE) {
{ info->avx.maskMode = ZYDIS_AVX_MASKMODE_ZERO;
info->prefixFlags &= ~ZYDIS_PREFIXFLAG_HAS_REPNE; } else
info->prefixFlags |= ZYDIS_PREFIXFLAG_HAS_XACQUIRE; {
} info->avx.maskMode = ZYDIS_AVX_MASKMODE_MERGE;
{ }
info->prefixFlags &= ~ZYDIS_PREFIXFLAG_HAS_REP; switch (definition->evexBFunctionality)
info->prefixFlags |= ZYDIS_PREFIXFLAG_HAS_XRELEASE; {
} case ZYDIS_EVEXB_FUNCTIONALITY_BC:
} else break;
if ((info->mnemonic == ZYDIS_MNEMONIC_MOV) && ((info->opcode == 0x88) || case ZYDIS_EVEXB_FUNCTIONALITY_RC:
(info->opcode == 0x89) || (info->opcode == 0xC6) || (info->opcode == 0xC7))) info->avx.roundingMode =
{ (((info->details.evex.l2 & 0x01) << 1) | info->details.evex.l) + 1;
if (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_REP) case ZYDIS_EVEXB_FUNCTIONALITY_SAE:
{ info->avx.sae = true;
info->prefixFlags &= ~ZYDIS_PREFIXFLAG_HAS_REP; default:
info->prefixFlags |= ZYDIS_PREFIXFLAG_HAS_XRELEASE; info->avx.broadcast = ZYDIS_AVX_BCSTMODE_INVALID;
}
}
} }
} }
// Adjust instruction mnemonics // Replace XCHG rAX, rAX with NOP alias
if (info->mnemonic == ZYDIS_MNEMONIC_XCHG) if (info->mnemonic == ZYDIS_MNEMONIC_XCHG)
{ {
if (((info->operand[0].reg == ZYDIS_REGISTER_RAX) && if (((info->operand[0].reg == ZYDIS_REGISTER_RAX) &&
@ -2199,11 +2157,11 @@ static ZydisDecoderStatus ZydisDecodeOpcode(ZydisInstructionDecoder* decoder,
ZYDIS_ASSERT(info); ZYDIS_ASSERT(info);
// Iterate through the instruction table // Iterate through the instruction table
ZydisInstructionTableNode node = ZydisInstructionTableGetRootNode(); const ZydisInstructionTableNode* node = ZydisInstructionTableGetRootNode();
ZydisInstructionTableNodeType nodeType; ZydisInstructionTableNodeType nodeType;
do do
{ {
nodeType = ZydisInstructionTableGetNodeType(node); nodeType = node->type;
uint16_t index = 0; uint16_t index = 0;
ZydisDecoderStatus status = 0; ZydisDecoderStatus status = 0;
switch (nodeType) switch (nodeType)
@ -2220,16 +2178,22 @@ static ZydisDecoderStatus ZydisDecodeOpcode(ZydisInstructionDecoder* decoder,
case ZYDIS_NODETYPE_DEFINITION_4OP: case ZYDIS_NODETYPE_DEFINITION_4OP:
case ZYDIS_NODETYPE_DEFINITION_5OP: case ZYDIS_NODETYPE_DEFINITION_5OP:
{ {
const ZydisInstructionDefinition definition = ZydisInstructionDefinitionByNode(node); const ZydisInstructionDefinition* definition = NULL;
//ZYDIS_ASSERT(definition); // TODO: Pointer? const ZydisOperandDefinition* operands = NULL;
info->mnemonic = definition.mnemonic; uint8_t operandCount;
ZydisInstructionTableGetDefinition(node, &definition, &operands, &operandCount);
ZYDIS_ASSERT(definition);
ZYDIS_ASSERT(operands);
info->mnemonic = (ZydisInstructionMnemonic)definition->mnemonic;
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
uint8_t bufferPosRead = decoder->buffer.posRead; uint8_t bufferPosRead = decoder->buffer.posRead;
uint8_t length = info->length; uint8_t length = info->length;
ZYDIS_CHECK(ZydisDecodeOperands(decoder, info, &definition)); // TODO: Reference? ZYDIS_CHECK(ZydisDecodeOperands(decoder, info, operands, operandCount));
// Read actual 3dnow opcode // Read actual 3dnow opcode
ZYDIS_CHECK(ZydisInputNext(decoder, info, &info->opcode)); ZYDIS_CHECK(ZydisInputNext(decoder, info, &info->opcode));
// Restore input-buffer state // Restore input-buffer state
@ -2247,7 +2211,7 @@ static ZydisDecoderStatus ZydisDecodeOpcode(ZydisInstructionDecoder* decoder,
node = ZydisInstructionTableGetChildNode(node, 0x0F); node = ZydisInstructionTableGetChildNode(node, 0x0F);
node = ZydisInstructionTableGetChildNode(node, 0x0F); node = ZydisInstructionTableGetChildNode(node, 0x0F);
node = ZydisInstructionTableGetChildNode(node, info->opcode); node = ZydisInstructionTableGetChildNode(node, info->opcode);
if (ZydisInstructionTableGetNodeType(node) == ZYDIS_NODETYPE_INVALID) if (node->type == ZYDIS_NODETYPE_INVALID)
{ {
info->instrFlags |= ZYDIS_INSTRFLAG_ERROR_UNDEFINED; info->instrFlags |= ZYDIS_INSTRFLAG_ERROR_UNDEFINED;
return ZYDIS_STATUS_DECODER_UNDEFINED_INSTRUCTION; return ZYDIS_STATUS_DECODER_UNDEFINED_INSTRUCTION;
@ -2255,43 +2219,18 @@ static ZydisDecoderStatus ZydisDecodeOpcode(ZydisInstructionDecoder* decoder,
node = ZydisInstructionTableGetChildNode(node, node = ZydisInstructionTableGetChildNode(node,
(info->details.modrm.mod == 0x3) ? 1 : 0); (info->details.modrm.mod == 0x3) ? 1 : 0);
// Decode actual operands and fix the instruction-info // Decode actual operands and fix the instruction-info
ZydisInstructionDefinition definition2 = ZydisInstructionDefinitionByNode(node); ZydisInstructionTableGetDefinition(node, &definition, &operands, &operandCount);
//ZYDIS_ASSERT(definition); // TODO: Pointer ZYDIS_ASSERT(definition);
ZYDIS_CHECK(ZydisDecodeOperands(decoder, info, &definition2)); // TODO: Reference ZYDIS_ASSERT(operands);
info->mnemonic = definition2.mnemonic; ZYDIS_CHECK(ZydisDecodeOperands(decoder, info, operands, operandCount));
ZydisFinalizeInstructionInfo(info); info->mnemonic = (ZydisInstructionMnemonic)definition->mnemonic;
ZydisFinalizeInstructionInfo(info, definition);
return ZydisInputNext(decoder, info, &info->opcode); return ZydisInputNext(decoder, info, &info->opcode);
} }
ZYDIS_CHECK(ZydisDecodeOperands(decoder, info, &definition)); // TODO: Reference ZYDIS_CHECK(ZydisDecodeOperands(decoder, info, operands, operandCount));
ZydisFinalizeInstructionInfo(info); ZydisFinalizeInstructionInfo(info, definition);
if (info->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX)
{
if (definition.hasEvexAAA && info->details.evex.aaa)
{
info->avx.maskRegister = ZYDIS_REGISTER_K0 + info->details.evex.aaa;
}
if (definition.hasEvexZ && info->details.evex.z)
{
info->avx.maskMode = ZYDIS_AVX_MASKMODE_ZERO;
} else
{
info->avx.maskMode = ZYDIS_AVX_MASKMODE_MERGE;
}
switch (definition.evexBFunctionality)
{
case ZYDIS_EVEXB_FUNCTIONALITY_BC:
break;
case ZYDIS_EVEXB_FUNCTIONALITY_RC:
info->avx.roundingMode =
(((info->details.evex.l2 & 0x01) << 1) | info->details.evex.l) + 1;
case ZYDIS_EVEXB_FUNCTIONALITY_SAE:
info->avx.sae = true;
default:
info->avx.broadcast = ZYDIS_AVX_BCSTMODE_INVALID;
}
}
return ZYDIS_STATUS_DECODER_SUCCESS; return ZYDIS_STATUS_DECODER_SUCCESS;
} }
case ZYDIS_NODETYPE_FILTER_OPCODE: case ZYDIS_NODETYPE_FILTER_OPCODE:

View File

@ -440,18 +440,26 @@ static ZydisStatus ZydisFormatterFormatInstructionIntel(ZydisInstructionFormatte
{ {
size_t offset = 0; size_t offset = 0;
if ((info->prefixFlags & ZYDIS_PREFIXFLAG_ACCEPTS_REP) &&
(info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_REP))
{
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "rep "));
}
if ((info->prefixFlags & ZYDIS_PREFIXFLAG_ACCEPTS_REPE) &&
(info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_REPE))
{
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "repe "));
}
if ((info->prefixFlags & ZYDIS_PREFIXFLAG_ACCEPTS_REPNE) && if ((info->prefixFlags & ZYDIS_PREFIXFLAG_ACCEPTS_REPNE) &&
(info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_REPNE)) (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_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_PREFIXFLAG_ACCEPTS_REP) && (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_REP)) if ((info->prefixFlags & ZYDIS_PREFIXFLAG_ACCEPTS_LOCK) &&
{ (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_LOCK))
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "rep "));
}
if ((info->prefixFlags & ZYDIS_PREFIXFLAG_ACCEPTS_LOCK) && (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_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 "));

View File

@ -25,81 +25,12 @@
***************************************************************************************************/ ***************************************************************************************************/
#include <assert.h> #include <assert.h>
#include <string.h>
#include <Zydis/Internal/InstructionTable.h> #include <Zydis/Internal/InstructionTable.h>
/* ============================================================================================== */ /* ============================================================================================== */
/* Data tables */ /* Data tables */
/* ============================================================================================== */ /* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Generated types & Macros */
/* ---------------------------------------------------------------------------------------------- */
// TODO: Auto generate these structs and macros
typedef struct ZydisInternalInstructionTableNode_
{
ZydisInstructionTableNodeType type;
ZydisInstructionTableNodeValue value;
} ZydisInternalInstructionTableNode;
#define ZYDIS_MAKE_INSTRUCTIONTABLENODE(type, value) \
{ type, value }
#define ZYDIS_GET_INSTRUCTIONTABLENODE_TYPE(node) \
node.type
#define ZYDIS_GET_INSTRUCTIONTABLENODE_VALUE(node) \
node.value
//typedef struct ZydisInternalOperandDefinition_
//{
// unsigned int type : 8;
// unsigned int encoding : 8;
// unsigned int access : 2;
//} ZydisInternalOperandDefinition;
//
//#define ZYDIS_MAKE_OPERANDDEFINITION(type, encoding, access) \
// { type, encoding, access }
//#define ZYDIS_GET_OPERANDDEFINITION_TYPE(def) \
// (ZydisSemanticOperandType)def.type
//#define ZYDIS_GET_OPERANDDEFINITION_ENCODING(def) \
// (ZydisOperandEncoding)def.encoding
//#define ZYDIS_GET_OPERANDDEFINITION_ACCESS(def) \
// (ZydisOperandAccess)def.access
typedef uint8_t ZydisInternalOperandDefinition[2];
#define ZYDIS_MAKE_OPERANDDEFINITION(type, encoding, access) \
{ type, ((encoding & 0x3F) << 2) | (access & 0x03) }
#define ZYDIS_GET_OPERANDDEFINITION_TYPE(def) \
def[0]
#define ZYDIS_GET_OPERANDDEFINITION_ENCODING(def) \
((def[1] >> 2) & 0x3F)
#define ZYDIS_GET_OPERANDDEFINITION_ACCESS(def) \
(def[1] & 0x03)
typedef struct ZydisInternalInstructionDefinition_
{
unsigned int mnemonic : 11;
unsigned int operandRef : 9;
unsigned int evexBFunctionality : 2;
unsigned int hasEvexAAA : 1;
unsigned int hasEvexZ : 1;
} ZydisInternalInstructionDefinition;
#define ZYDIS_MAKE_INSTRUCTIONDEFINITION(mnemonic, operandRef, evexBFunctionality, hasEvexAAA, hasEvexZ) \
{ mnemonic, operandRef, evexBFunctionality, hasEvexAAA, hasEvexZ }
#define ZYDIS_GET_INSTRUCTIONDEFINITION_MNEMONIC(def) \
(ZydisInstructionMnemonic)def.mnemonic
#define ZYDIS_GET_INSTRUCTIONDEFINITION_OPERANDREF(def) \
def.operandRef
#define ZYDIS_GET_INSTRUCTIONDEFINITION_EVEXBFUNCTIONALITY(def) \
(ZydisEvexBFunctionality)def.evexBFunctionality
#define ZYDIS_GET_INSTRUCTIONDEFINITION_HASEVEXAAA(def) \
def.hasEvexAAA
#define ZYDIS_GET_INSTRUCTIONDEFINITION_HASEVEXZ(def) \
def.hasEvexZ
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/* Forward declarations */ /* Forward declarations */
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
@ -109,7 +40,7 @@ typedef struct ZydisInternalInstructionDefinition_
* *
* Indexed by the numeric value of the opcode. * Indexed by the numeric value of the opcode.
*/ */
extern const ZydisInternalInstructionTableNode filterOpcode[][256]; extern const ZydisInstructionTableNode filterOpcode[][256];
/** /**
* @brief Contains all vex-map filters. * @brief Contains all vex-map filters.
@ -132,7 +63,7 @@ extern const ZydisInternalInstructionTableNode filterOpcode[][256];
* E = F2_0F38 * E = F2_0F38
* F = F2_0F3A * F = F2_0F3A
*/ */
extern const ZydisInternalInstructionTableNode filterVEX[][16]; extern const ZydisInstructionTableNode filterVEX[][16];
/** /**
* @brief Contains all xop-map filters. * @brief Contains all xop-map filters.
@ -143,7 +74,7 @@ extern const ZydisInternalInstructionTableNode filterVEX[][16];
* 2 = xop9 * 2 = xop9
* 3 = xopA * 3 = xopA
*/ */
extern const ZydisInternalInstructionTableNode filterXOP[][4]; extern const ZydisInstructionTableNode filterXOP[][4];
/** /**
* @brief Contains all instruction-mode filters. * @brief Contains all instruction-mode filters.
@ -152,7 +83,7 @@ extern const ZydisInternalInstructionTableNode filterXOP[][4];
* 0 = 64 bit mode required * 0 = 64 bit mode required
* 1 = 64 bit mode excluded * 1 = 64 bit mode excluded
*/ */
extern const ZydisInternalInstructionTableNode filterMode[][2]; extern const ZydisInstructionTableNode filterMode[][2];
/** /**
* @brief Contains all mandatory-prefix switch tables. * @brief Contains all mandatory-prefix switch tables.
@ -163,7 +94,7 @@ extern const ZydisInternalInstructionTableNode filterMode[][2];
* 2 = F3 * 2 = F3
* 3 = F2 * 3 = F2
*/ */
extern const ZydisInternalInstructionTableNode filterMandatoryPrefix[][4]; extern const ZydisInstructionTableNode filterMandatoryPrefix[][4];
/** /**
* @brief Contains all modrm.mod filters. * @brief Contains all modrm.mod filters.
@ -172,21 +103,21 @@ extern const ZydisInternalInstructionTableNode filterMandatoryPrefix[][4];
* 0 = [modrm_mod == !11] = memory * 0 = [modrm_mod == !11] = memory
* 1 = [modrm_mod == 11] = register * 1 = [modrm_mod == 11] = register
*/ */
extern const ZydisInternalInstructionTableNode filterModrmMod[][2]; extern const ZydisInstructionTableNode filterModrmMod[][2];
/** /**
* @brief Contains all modrm.reg filters. * @brief Contains all modrm.reg filters.
* *
* Indexed by the numeric value of the modrm_reg field. * Indexed by the numeric value of the modrm_reg field.
*/ */
extern const ZydisInternalInstructionTableNode filterModrmReg[][8]; extern const ZydisInstructionTableNode filterModrmReg[][8];
/** /**
* @brief Contains all modrm.rm filters. * @brief Contains all modrm.rm filters.
* *
* Indexed by the numeric value of the modrm_rm field. * Indexed by the numeric value of the modrm_rm field.
*/ */
extern const ZydisInternalInstructionTableNode filterModrmRm[][8]; extern const ZydisInstructionTableNode filterModrmRm[][8];
/** /**
* @brief Contains all operand-size filters. * @brief Contains all operand-size filters.
@ -195,7 +126,7 @@ extern const ZydisInternalInstructionTableNode filterModrmRm[][8];
* 0 = 16bit = 0x66 prefix in 32 bit mode * 0 = 16bit = 0x66 prefix in 32 bit mode
* 1 = 32bit = 0x66 prefix in 16 bit mode * 1 = 32bit = 0x66 prefix in 16 bit mode
*/ */
extern const ZydisInternalInstructionTableNode filterOperandSize[][2]; extern const ZydisInstructionTableNode filterOperandSize[][2];
/** /**
* @brief Contains all address-size filters. * @brief Contains all address-size filters.
@ -205,207 +136,169 @@ extern const ZydisInternalInstructionTableNode filterOperandSize[][2];
* 1 = 32 * 1 = 32
* 2 = 64 * 2 = 64
*/ */
extern const ZydisInternalInstructionTableNode filterAddressSize[][3]; extern const ZydisInstructionTableNode filterAddressSize[][3];
/** /**
* @brief Contains all rex/vex/evex.w filters. * @brief Contains all rex/vex/evex.w filters.
* *
* Indexed by the numeric value of the rex/vex/evex.w field. * Indexed by the numeric value of the rex/vex/evex.w field.
*/ */
extern const ZydisInternalInstructionTableNode filterREXW[][2]; extern const ZydisInstructionTableNode filterREXW[][2];
/** /**
* @brief Contains all vex.l filters. * @brief Contains all vex.l filters.
* *
* Indexed by the numeric value of the vex/evex.l field. * Indexed by the numeric value of the vex/evex.l field.
*/ */
extern const ZydisInternalInstructionTableNode filterVEXL[][2]; extern const ZydisInstructionTableNode filterVEXL[][2];
/** /**
* @brief Contains all evex.l' filters. * @brief Contains all evex.l' filters.
* *
* Indexed by the numeric value of the evex.l' field. * Indexed by the numeric value of the evex.l' field.
*/ */
extern const ZydisInternalInstructionTableNode filterEVEXL2[][2]; extern const ZydisInstructionTableNode filterEVEXL2[][2];
/** /**
* @brief Contains all evex.b filters. * @brief Contains all evex.b filters.
* *
* Indexed by the numeric value of the evex.b field. * Indexed by the numeric value of the evex.b field.
*/ */
extern const ZydisInternalInstructionTableNode filterEVEXB[][2]; extern const ZydisInstructionTableNode filterEVEXB[][2];
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/** /**
* @brief Contains all operand-definitions with 1 operand. * @brief Contains all operand-definitions with 1 operand.
*/ */
extern const ZydisInternalOperandDefinition operandDefinitions1[][1]; extern const ZydisOperandDefinition operandDefinitions1[][1];
/** /**
* @brief Contains all operand-definitions with 2 operands. * @brief Contains all operand-definitions with 2 operands.
*/ */
extern const ZydisInternalOperandDefinition operandDefinitions2[][2]; extern const ZydisOperandDefinition operandDefinitions2[][2];
/** /**
* @brief Contains all operand-definitions with 3 operands. * @brief Contains all operand-definitions with 3 operands.
*/ */
extern const ZydisInternalOperandDefinition operandDefinitions3[][3]; extern const ZydisOperandDefinition operandDefinitions3[][3];
/** /**
* @brief Contains all operand-definitions with 4 operands. * @brief Contains all operand-definitions with 4 operands.
*/ */
extern const ZydisInternalOperandDefinition operandDefinitions4[][4]; extern const ZydisOperandDefinition operandDefinitions4[][4];
/** /**
* @brief Contains all operand-definitions with 5 operands. * @brief Contains all operand-definitions with 5 operands.
*/ */
extern const ZydisInternalOperandDefinition operandDefinitions5[][5]; extern const ZydisOperandDefinition operandDefinitions5[][5];
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/** /**
* @brief Contains all instruction-definitions. * @brief Contains all instruction-definitions.
*/ */
extern const ZydisInternalInstructionDefinition instructionDefinitions[]; extern const ZydisInstructionDefinition instructionDefinitions[];
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/* Functions */ /* Functions */
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
ZydisInstructionTableNodeType ZydisInstructionTableGetNodeType( const ZydisInstructionTableNode* ZydisInstructionTableGetRootNode()
const ZydisInstructionTableNode node)
{ {
return (ZydisInstructionTableNodeType) static const ZydisInstructionTableNode root = { ZYDIS_NODETYPE_FILTER_OPCODE, 0x00000000 };
ZYDIS_GET_INSTRUCTIONTABLENODE_TYPE((*(ZydisInternalInstructionTableNode*)node)); return &root;
} }
ZydisInstructionTableNodeValue ZydisInstructionTableGetNodeValue( const ZydisInstructionTableNode* ZydisInstructionTableGetChildNode(
const ZydisInstructionTableNode* node) const ZydisInstructionTableNode* parent, uint16_t index)
{ {
return (ZydisInstructionTableNodeValue) switch (parent->type)
ZYDIS_GET_INSTRUCTIONTABLENODE_VALUE((*(ZydisInternalInstructionTableNode*)node));
}
/* ---------------------------------------------------------------------------------------------- */
ZydisInstructionTableNode ZydisInstructionTableGetRootNode()
{
static const ZydisInternalInstructionTableNode root =
ZYDIS_MAKE_INSTRUCTIONTABLENODE(ZYDIS_NODETYPE_FILTER_OPCODE, 0x00000000);
return (ZydisInstructionTableNode)&root;
}
ZydisInstructionTableNode ZydisInstructionTableGetChildNode(
const ZydisInstructionTableNode parent, uint16_t index)
{
ZydisInstructionTableNodeType nodeType = ZydisInstructionTableGetNodeType(parent);
uint16_t tableIndex = ZydisInstructionTableGetNodeValue(parent);
switch (nodeType)
{ {
case ZYDIS_NODETYPE_FILTER_OPCODE: case ZYDIS_NODETYPE_FILTER_OPCODE:
ZYDIS_ASSERT(index < 256); ZYDIS_ASSERT(index < 256);
return (ZydisInstructionTableNode*)&filterOpcode[tableIndex][index]; return &filterOpcode[parent->value][index];
case ZYDIS_NODETYPE_FILTER_VEX: case ZYDIS_NODETYPE_FILTER_VEX:
ZYDIS_ASSERT(index < 16); ZYDIS_ASSERT(index < 16);
return (ZydisInstructionTableNode*)&filterVEX[tableIndex][index]; return &filterVEX[parent->value][index];
case ZYDIS_NODETYPE_FILTER_XOP: case ZYDIS_NODETYPE_FILTER_XOP:
ZYDIS_ASSERT(index < 4); ZYDIS_ASSERT(index < 4);
return (ZydisInstructionTableNode*)&filterXOP[tableIndex][index]; return &filterXOP[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MODE: case ZYDIS_NODETYPE_FILTER_MODE:
ZYDIS_ASSERT(index < 3); ZYDIS_ASSERT(index < 3);
return (ZydisInstructionTableNode*)&filterMode[tableIndex][index]; return &filterMode[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MANDATORYPREFIX: case ZYDIS_NODETYPE_FILTER_MANDATORYPREFIX:
ZYDIS_ASSERT(index < 4); ZYDIS_ASSERT(index < 4);
return (ZydisInstructionTableNode*)&filterMandatoryPrefix[tableIndex][index]; return &filterMandatoryPrefix[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MODRMMOD: case ZYDIS_NODETYPE_FILTER_MODRMMOD:
ZYDIS_ASSERT(index < 2); ZYDIS_ASSERT(index < 2);
return (ZydisInstructionTableNode*)&filterModrmMod[tableIndex][index]; return &filterModrmMod[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MODRMREG: case ZYDIS_NODETYPE_FILTER_MODRMREG:
ZYDIS_ASSERT(index < 8); ZYDIS_ASSERT(index < 8);
return (ZydisInstructionTableNode*)&filterModrmReg[tableIndex][index]; return &filterModrmReg[parent->value][index];
case ZYDIS_NODETYPE_FILTER_MODRMRM: case ZYDIS_NODETYPE_FILTER_MODRMRM:
ZYDIS_ASSERT(index < 8); ZYDIS_ASSERT(index < 8);
return (ZydisInstructionTableNode*)&filterModrmRm[tableIndex][index]; return &filterModrmRm[parent->value][index];
case ZYDIS_NODETYPE_FILTER_OPERANDSIZE: case ZYDIS_NODETYPE_FILTER_OPERANDSIZE:
ZYDIS_ASSERT(index < 2); ZYDIS_ASSERT(index < 2);
return (ZydisInstructionTableNode*)&filterOperandSize[tableIndex][index]; return &filterOperandSize[parent->value][index];
case ZYDIS_NODETYPE_FILTER_ADDRESSSIZE: case ZYDIS_NODETYPE_FILTER_ADDRESSSIZE:
ZYDIS_ASSERT(index < 3); ZYDIS_ASSERT(index < 3);
return (ZydisInstructionTableNode*)&filterAddressSize[tableIndex][index]; return &filterAddressSize[parent->value][index];
case ZYDIS_NODETYPE_FILTER_REXW: case ZYDIS_NODETYPE_FILTER_REXW:
ZYDIS_ASSERT(index < 2); ZYDIS_ASSERT(index < 2);
return (ZydisInstructionTableNode*)&filterREXW[tableIndex][index]; return &filterREXW[parent->value][index];
case ZYDIS_NODETYPE_FILTER_VEXL: case ZYDIS_NODETYPE_FILTER_VEXL:
ZYDIS_ASSERT(index < 2); ZYDIS_ASSERT(index < 2);
return (ZydisInstructionTableNode*)&filterVEXL[tableIndex][index]; return &filterVEXL[parent->value][index];
case ZYDIS_NODETYPE_FILTER_EVEXL2: case ZYDIS_NODETYPE_FILTER_EVEXL2:
ZYDIS_ASSERT(index < 2); ZYDIS_ASSERT(index < 2);
return (ZydisInstructionTableNode*)&filterEVEXL2[tableIndex][index]; return &filterEVEXL2[parent->value][index];
case ZYDIS_NODETYPE_FILTER_EVEXB: case ZYDIS_NODETYPE_FILTER_EVEXB:
ZYDIS_ASSERT(index < 2); ZYDIS_ASSERT(index < 2);
return (ZydisInstructionTableNode*)&filterEVEXB[tableIndex][index]; return &filterEVEXB[parent->value][index];
default: default:
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
} }
static const ZydisInternalInstructionTableNode invalid = static const ZydisInstructionTableNode invalid = { ZYDIS_NODETYPE_INVALID, 0x00000000 };
ZYDIS_MAKE_INSTRUCTIONTABLENODE(ZYDIS_NODETYPE_INVALID, 0x00000000); return &invalid;
return (ZydisInstructionTableNode)&invalid;
} }
ZydisInstructionDefinition ZydisInstructionDefinitionByNode( bool ZydisInstructionTableGetDefinition(const ZydisInstructionTableNode* node,
const ZydisInstructionTableNode node) const ZydisInstructionDefinition** definition, const ZydisOperandDefinition** operands,
uint8_t* operandCount)
{ {
ZydisInstructionDefinition result; *definition = &instructionDefinitions[node->value];
memset(&result, 0, sizeof(result)); switch (node->type)
const ZydisInternalInstructionDefinition* definition =
&instructionDefinitions[ZydisInstructionTableGetNodeValue(node)];
result.mnemonic = ZYDIS_GET_INSTRUCTIONDEFINITION_MNEMONIC((*definition));
result.evexBFunctionality = ZYDIS_GET_INSTRUCTIONDEFINITION_EVEXBFUNCTIONALITY((*definition));
result.hasEvexAAA = ZYDIS_GET_INSTRUCTIONDEFINITION_HASEVEXAAA((*definition));
result.hasEvexZ = ZYDIS_GET_INSTRUCTIONDEFINITION_HASEVEXZ((*definition));
const ZydisInternalOperandDefinition* operand = NULL;
switch (ZydisInstructionTableGetNodeType(node))
{ {
case ZYDIS_NODETYPE_DEFINITION_0OP: case ZYDIS_NODETYPE_DEFINITION_0OP:
result.operandCount = 0; *operandCount = 0;
break; break;
case ZYDIS_NODETYPE_DEFINITION_1OP: case ZYDIS_NODETYPE_DEFINITION_1OP:
result.operandCount = 1; *operandCount = 1;
operand = operandDefinitions1[ZYDIS_GET_INSTRUCTIONDEFINITION_OPERANDREF((*definition))]; *operands = operandDefinitions1[(*definition)->operandsId];
break; break;
case ZYDIS_NODETYPE_DEFINITION_2OP: case ZYDIS_NODETYPE_DEFINITION_2OP:
result.operandCount = 2; *operandCount = 2;
operand = operandDefinitions2[ZYDIS_GET_INSTRUCTIONDEFINITION_OPERANDREF((*definition))]; *operands = operandDefinitions2[(*definition)->operandsId];
break; break;
case ZYDIS_NODETYPE_DEFINITION_3OP: case ZYDIS_NODETYPE_DEFINITION_3OP:
result.operandCount = 3; *operandCount = 3;
operand = operandDefinitions3[ZYDIS_GET_INSTRUCTIONDEFINITION_OPERANDREF((*definition))]; *operands = operandDefinitions3[(*definition)->operandsId];
break; break;
case ZYDIS_NODETYPE_DEFINITION_4OP: case ZYDIS_NODETYPE_DEFINITION_4OP:
result.operandCount = 4; *operandCount = 4;
operand = operandDefinitions4[ZYDIS_GET_INSTRUCTIONDEFINITION_OPERANDREF((*definition))]; *operands = operandDefinitions4[(*definition)->operandsId];
break; break;
case ZYDIS_NODETYPE_DEFINITION_5OP: case ZYDIS_NODETYPE_DEFINITION_5OP:
result.operandCount = 5; *operandCount = 5;
operand = operandDefinitions5[ZYDIS_GET_INSTRUCTIONDEFINITION_OPERANDREF((*definition))]; *operands = operandDefinitions5[(*definition)->operandsId];
break; break;
default: default:
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
} return false;
if (result.operandCount > 0) }
{ return true;
for (int i = 0; i < result.operandCount; ++i)
{
result.operands[i].type = ZYDIS_GET_OPERANDDEFINITION_TYPE((*operand));
result.operands[i].encoding = ZYDIS_GET_OPERANDDEFINITION_ENCODING((*operand));
result.operands[i].access = ZYDIS_GET_OPERANDDEFINITION_ACCESS((*operand));
++operand;
}
}
return result;
} }
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
@ -413,7 +306,7 @@ ZydisInstructionDefinition ZydisInstructionDefinitionByNode(
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
#define ZYDIS_INVALID \ #define ZYDIS_INVALID \
ZYDIS_MAKE_INSTRUCTIONTABLENODE(ZYDIS_NODETYPE_INVALID, 0x00000000) { ZYDIS_NODETYPE_INVALID, 0x00000000 }
#define ZYDIS_FILTER(type, id) \ #define ZYDIS_FILTER(type, id) \
{ type, id } { type, id }
#define ZYDIS_DEFINITION_0OP(id) \ #define ZYDIS_DEFINITION_0OP(id) \
@ -440,15 +333,16 @@ ZydisInstructionDefinition ZydisInstructionDefinitionByNode(
#undef ZYDIS_DEFINITION_4OP #undef ZYDIS_DEFINITION_4OP
#undef ZYDIS_DEFINITION_5OP #undef ZYDIS_DEFINITION_5OP
#undef ZYDIS_MAKE_INSTRUCTIONTABLENODE
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/* Operand definitions */ /* Operand definitions */
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
#define ZYDIS_OPERAND_DEFINITION(type, encoding, access) \
{ type, encoding, access }
#include <Zydis/Internal/OperandDefinitions.inc> #include <Zydis/Internal/OperandDefinitions.inc>
#undef ZYDIS_MAKE_OPERANDDEFINITION #undef ZYDIS_OPERAND_DEFINITION
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/* Instruction definitions */ /* Instruction definitions */
@ -456,7 +350,4 @@ ZydisInstructionDefinition ZydisInstructionDefinitionByNode(
#include <Zydis/Internal/InstructionDefinitions.inc> #include <Zydis/Internal/InstructionDefinitions.inc>
#undef ZYDIS_MAKE_AVX512INFO
#undef ZYDIS_MAKE_INSTRUCTIONDEFINITION
/* ============================================================================================== */ /* ============================================================================================== */