EXTRA_DIST += Mkfiles/vc/modules/modules.vcproj
EXTRA_DIST += Mkfiles/vc/re2c/re2c.vcproj
EXTRA_DIST += Mkfiles/vc/re2c/run.bat
+EXTRA_DIST += Mkfiles/vc/gap/gap.vcproj
+EXTRA_DIST += Mkfiles/vc/gap/run.bat
EXTRA_DIST += Mkfiles/vc8/yasm.sln
EXTRA_DIST += Mkfiles/vc8/yasm.vcproj
EXTRA_DIST += Mkfiles/vc8/config.h
EXTRA_DIST += Mkfiles/vc8/modules/modules.vcproj
EXTRA_DIST += Mkfiles/vc8/re2c/re2c.vcproj
EXTRA_DIST += Mkfiles/vc8/re2c/run.bat
+EXTRA_DIST += Mkfiles/vc8/gap/gap.vcproj
+EXTRA_DIST += Mkfiles/vc8/gap/run.bat
# Until this gets fixed in automake
DISTCLEANFILES = libyasm/stamp-h libyasm/stamp-h[0-9]*
libyasm/intnum.o \
libyasm/linemgr.o \
libyasm/mergesort.o \
+ libyasm/phash.o \
libyasm/section.o \
libyasm/splitpath.o \
libyasm/strcasecmp.o \
modules/arch/x86/x86arch.o \
modules/arch/x86/x86bc.o \
modules/arch/x86/x86expr.o \
- x86id.o
+ modules/arch/x86/x86id.o
YASM_MODULES=arch_x86
MODULES_ARCH_LC3B_OBJS= \
$(BUILDCC) -o $@ $<
nasm-macros.c: modules/preprocs/nasm/standard.mac genmacro
- ./genmacro $<
+ ./genmacro modules/preprocs/nasm/standard.mac
modules/preprocs/nasm/nasm-pp.c: nasm-macros.c
$(BUILDCC) -o $@ $<
module.c: libyasm/module.in genmodule
- ./genmodule $< $(YASM_MODULES)
+ ./genmodule libyasm/module.in $(YASM_MODULES)
-x86id.c: modules/arch/x86/x86id.re re2c
- ./re2c -s -o $@ $<
+x86parse.c: modules/arch/x86/x86parse.gap gap
+ ./gap modules/arch/x86/x86parse.gap $@
+
+modules/arch/x86/x86id.c: x86parse.c
lc3bid.c: modules/arch/lc3b/lc3bid.re re2c
- ./re2c -s -o $@ $<
+ ./re2c -s -o $@ modules/arch/lc3b/lc3bid.re
gas-token.c: modules/parsers/gas/gas-token.re re2c
- ./re2c -b -o $@ $<
+ ./re2c -b -o $@ modules/parsers/gas/gas-token.re
nasm-token.c: modules/parsers/nasm/nasm-token.re re2c
- ./re2c -b -o $@ $<
+ ./re2c -b -o $@ modules/parsers/nasm/nasm-token.re
RE2C_SRCS= \
tools/re2c/main.c \
re2c: $(RE2C_SRCS)
$(BUILDCC) -I. -o re2c $(RE2C_SRCS)
+GAP_SRCS= \
+ tools/gap/gap.c \
+ tools/gap/perfect.c \
+ libyasm/phash.c \
+ libyasm/hamt.c \
+ libyasm/xmalloc.c \
+ libyasm/xstrdup.c
+
+gap: $(GAP_SRCS)
+ $(BUILDCC) -I. -o gap $(GAP_SRCS)
+
yasm: $(YASM_OBJS)
$(CC) -o yasm $(YASM_OBJS)
# NOTE: Needs a valid config.h for the platform being compiled on.
#
# This file should be customized to particular platforms by changing CC and
-# CFLAGS appropriately, along with writing a config.h for the platform and
-# placing it in a libyasm subdirectory.
+# CFLAGS appropriately, along with writing a config.h and _stdint.h for the
+# platform and placing them in a subdirectory of Mkfiles.
CFLAGS=-DHAVE_CONFIG_H -IMkfiles -I.
CC?=gcc
libyasm/intnum.o \
libyasm/linemgr.o \
libyasm/mergesort.o \
+ libyasm/phash.o \
libyasm/section.o \
libyasm/splitpath.o \
libyasm/strcasecmp.o \
modules/arch/x86/x86arch.o \
modules/arch/x86/x86bc.o \
modules/arch/x86/x86expr.o \
- x86id.o
+ modules/arch/x86/x86id.o
YASM_MODULES=arch_x86
MODULES_ARCH_LC3B_OBJS= \
$(BUILDCC) -o $@ $<
nasm-macros.c: modules/preprocs/nasm/standard.mac genmacro
- ./genmacro $<
+ ./genmacro modules/preprocs/nasm/standard.mac
modules/preprocs/nasm/nasm-pp.c: nasm-macros.c
$(BUILDCC) -o $@ $<
module.c: libyasm/module.in genmodule
- ./genmodule $< $(YASM_MODULES)
+ ./genmodule libyasm/module.in $(YASM_MODULES)
-x86id.c: modules/arch/x86/x86id.re re2c
- ./re2c -s -o $@ $<
+x86parse.c: modules/arch/x86/x86parse.gap gap
+ ./gap modules/arch/x86/x86parse.gap $@
+
+modules/arch/x86/x86id.c: x86parse.c
lc3bid.c: modules/arch/lc3b/lc3bid.re re2c
- ./re2c -s -o $@ $<
+ ./re2c -s -o $@ modules/arch/lc3b/lc3bid.re
gas-token.c: modules/parsers/gas/gas-token.re re2c
- ./re2c -b -o $@ $<
+ ./re2c -b -o $@ modules/parsers/gas/gas-token.re
nasm-token.c: modules/parsers/nasm/nasm-token.re re2c
- ./re2c -b -o $@ $<
+ ./re2c -b -o $@ modules/parsers/nasm/nasm-token.re
RE2C_SRCS= \
tools/re2c/main.c \
re2c: $(RE2C_SRCS)
$(BUILDCC) -I. -o re2c $(RE2C_SRCS)
+GAP_SRCS= \
+ tools/gap/gap.c \
+ tools/gap/perfect.c \
+ libyasm/phash.c \
+ libyasm/hamt.c \
+ libyasm/xmalloc.c \
+ libyasm/xstrdup.c
+
+gap: $(GAP_SRCS)
+ $(BUILDCC) -I. -o gap $(GAP_SRCS)
+
yasm: $(YASM_OBJS)
$(CC) -o yasm $(YASM_OBJS)
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="7.10"\r
+ Name="gap"\r
+ ProjectGUID="{5758BF4E-ABC4-11DA-B012-B622A1EF5492}"\r
+ RootNamespace="gap"\r
+ Keyword="Win32Proj">\r
+ <Platforms>\r
+ <Platform\r
+ Name="Win32"/>\r
+ </Platforms>\r
+ <Configurations>\r
+ <Configuration\r
+ Name="Debug|Win32"\r
+ OutputDirectory="Debug"\r
+ IntermediateDirectory="Debug"\r
+ ConfigurationType="1"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories="..,../../.."\r
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
+ MinimalRebuild="TRUE"\r
+ BasicRuntimeChecks="3"\r
+ RuntimeLibrary="5"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="3"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="4"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ OutputFile="$(OutDir)/gap.exe"\r
+ LinkIncremental="2"\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(OutDir)/gap.pdb"\r
+ SubSystem="1"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"\r
+ CommandLine="run.bat "$(TargetPath)""/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCXMLDataGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ <Tool\r
+ Name="VCManagedWrapperGeneratorTool"/>\r
+ <Tool\r
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory="Release"\r
+ IntermediateDirectory="Release"\r
+ ConfigurationType="1"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ AdditionalIncludeDirectories="..,../../.."\r
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+ RuntimeLibrary="4"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="3"\r
+ Detect64BitPortabilityProblems="TRUE"\r
+ DebugInformationFormat="3"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ OutputFile="$(OutDir)/gap.exe"\r
+ LinkIncremental="1"\r
+ GenerateDebugInformation="TRUE"\r
+ SubSystem="1"\r
+ OptimizeReferences="2"\r
+ EnableCOMDATFolding="2"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"\r
+ CommandLine="run.bat "$(TargetPath)""/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCXMLDataGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ <Tool\r
+ Name="VCManagedWrapperGeneratorTool"/>\r
+ <Tool\r
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+ </Configuration>\r
+ </Configurations>\r
+ <References>\r
+ </References>\r
+ <Files>\r
+ <Filter\r
+ Name="Source Files"\r
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+ UniqueIdentifier="{7D996CB2-ABC4-11DA-B012-B622A1EF5492}">\r
+ <File\r
+ RelativePath="..\..\..\tools\gap\gap.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\..\tools\gap\perfect.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\..\libyasm\phash.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\..\libyasm\hamt.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\..\libyasm\xmalloc.c">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\..\libyasm\xstrdup.c">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+ UniqueIdentifier="{85DD7A94-ABC4-11DA-B012-B622A1EF5492}">\r
+ <File\r
+ RelativePath="..\..\..\tools\gap\perfect.h">\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\..\tools\gap\standard.h">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Resource Files"\r
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"\r
+ UniqueIdentifier="{8EB9B268-ABC4-11DA-B012-B622A1EF5492}">\r
+ </Filter>\r
+ <File\r
+ RelativePath=".\run.bat">\r
+ </File>\r
+ </Files>\r
+ <Globals>\r
+ </Globals>\r
+</VisualStudioProject>\r
--- /dev/null
+cd ..\..\..\\r
+%1 modules\arch\x86\x86parse.gap x86parse.c\r
</FileConfiguration>\r
</File>\r
<File\r
- RelativePath="..\..\..\x86id.c">\r
+ RelativePath="..\..\..\modules\arch\x86\x86id.c">\r
<FileConfiguration\r
Name="Release|Win32">\r
<Tool\r
cd ..\..\..\\r
-%1 -s modules\arch\lc3b\lc3bid.re > lc3bid.c\r
-%1 -s modules\arch\x86\x86id.re > x86id.c\r
-%1 -s modules\parsers\nasm\nasm-token.re > nasm-token.c\r
-%1 -s modules\parsers\gas\gas-token.re > gas-token.c\r
+%1 -s -o lc3bid.c modules\arch\lc3b\lc3bid.re\r
+%1 -b -o nasm-token.c modules\parsers\nasm\nasm-token.re\r
+%1 -b -o gas-token.c modules\parsers\gas\gas-token.re\r
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "modules", "modules\modules.vcproj", "{D715A3D4-EFAA-442E-AD8B-5B4FF64E1DD6}"\r
ProjectSection(ProjectDependencies) = postProject\r
{3C58BE13-50A3-4583-984D-D8902B3D7713} = {3C58BE13-50A3-4583-984D-D8902B3D7713}\r
+ {5758BF4E-ABC4-11DA-B012-B622A1EF5492} = {5758BF4E-ABC4-11DA-B012-B622A1EF5492}\r
{29FE7874-1256-4AD6-B889-68E399DC9608} = {29FE7874-1256-4AD6-B889-68E399DC9608}\r
{225700A5-07B8-434E-AD61-555278BF6733} = {225700A5-07B8-434E-AD61-555278BF6733}\r
EndProjectSection\r
ProjectSection(ProjectDependencies) = postProject\r
EndProjectSection\r
EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gap", "gap\gap.vcproj", "{5758BF4E-ABC4-11DA-B012-B622A1EF5492}"\r
+ ProjectSection(ProjectDependencies) = postProject\r
+ EndProjectSection\r
+EndProject\r
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "genmodule", "genmodule\genmodule.vcproj", "{F0E8B707-00C5-4FF2-B8EF-7C39817132A0}"\r
ProjectSection(ProjectDependencies) = postProject\r
EndProjectSection\r
{3C58BE13-50A3-4583-984D-D8902B3D7713}.Debug.Build.0 = Debug|Win32\r
{3C58BE13-50A3-4583-984D-D8902B3D7713}.Release.ActiveCfg = Release|Win32\r
{3C58BE13-50A3-4583-984D-D8902B3D7713}.Release.Build.0 = Release|Win32\r
+ {5758BF4E-ABC4-11DA-B012-B622A1EF5492}.Debug.ActiveCfg = Debug|Win32\r
+ {5758BF4E-ABC4-11DA-B012-B622A1EF5492}.Debug.Build.0 = Debug|Win32\r
+ {5758BF4E-ABC4-11DA-B012-B622A1EF5492}.Release.ActiveCfg = Release|Win32\r
+ {5758BF4E-ABC4-11DA-B012-B622A1EF5492}.Release.Build.0 = Release|Win32\r
{F0E8B707-00C5-4FF2-B8EF-7C39817132A0}.Debug.ActiveCfg = Debug|Win32\r
{F0E8B707-00C5-4FF2-B8EF-7C39817132A0}.Debug.Build.0 = Debug|Win32\r
{F0E8B707-00C5-4FF2-B8EF-7C39817132A0}.Release.ActiveCfg = Release|Win32\r
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="8.00"\r
+ Name="gap"\r
+ ProjectGUID="{5758BF4E-ABC4-11DA-B012-B622A1EF5492}"\r
+ RootNamespace="gap"\r
+ Keyword="Win32Proj"\r
+ >\r
+ <Platforms>\r
+ <Platform\r
+ Name="Win32"\r
+ />\r
+ </Platforms>\r
+ <ToolFiles>\r
+ </ToolFiles>\r
+ <Configurations>\r
+ <Configuration\r
+ Name="Debug|Win32"\r
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ ConfigurationType="1"\r
+ CharacterSet="2"\r
+ >\r
+ <Tool\r
+ Name="VCPreBuildEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ />\r
+ <Tool\r
+ Name="VCXMLDataGeneratorTool"\r
+ />\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"\r
+ />\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories="..,../../.."\r
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
+ MinimalRebuild="true"\r
+ BasicRuntimeChecks="3"\r
+ RuntimeLibrary="1"\r
+ UsePrecompiledHeader="0"\r
+ ProgramDataBaseFileName="$(IntDir)\"\r
+ WarningLevel="3"\r
+ Detect64BitPortabilityProblems="true"\r
+ DebugInformationFormat="4"\r
+ CompileAs="0"\r
+ />\r
+ <Tool\r
+ Name="VCManagedResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ OutputFile="$(OutDir)/gap.exe"\r
+ LinkIncremental="2"\r
+ GenerateDebugInformation="true"\r
+ ProgramDatabaseFile="$(OutDir)\$(TargetName).pdb"\r
+ SubSystem="1"\r
+ TargetMachine="1"\r
+ />\r
+ <Tool\r
+ Name="VCALinkTool"\r
+ />\r
+ <Tool\r
+ Name="VCManifestTool"\r
+ />\r
+ <Tool\r
+ Name="VCXDCMakeTool"\r
+ />\r
+ <Tool\r
+ Name="VCBscMakeTool"\r
+ />\r
+ <Tool\r
+ Name="VCFxCopTool"\r
+ />\r
+ <Tool\r
+ Name="VCAppVerifierTool"\r
+ />\r
+ <Tool\r
+ Name="VCWebDeploymentTool"\r
+ />\r
+ <Tool\r
+ Name="VCPostBuildEventTool"\r
+ CommandLine="run.bat "$(TargetPath)""\r
+ />\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+ ConfigurationType="1"\r
+ CharacterSet="2"\r
+ >\r
+ <Tool\r
+ Name="VCPreBuildEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ />\r
+ <Tool\r
+ Name="VCXMLDataGeneratorTool"\r
+ />\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"\r
+ />\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="3"\r
+ AdditionalIncludeDirectories="..,../../.."\r
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"\r
+ RuntimeLibrary="0"\r
+ UsePrecompiledHeader="0"\r
+ ProgramDataBaseFileName="$(IntDir)\"\r
+ WarningLevel="3"\r
+ Detect64BitPortabilityProblems="true"\r
+ DebugInformationFormat="3"\r
+ CompileAs="0"\r
+ />\r
+ <Tool\r
+ Name="VCManagedResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ OutputFile="$(OutDir)/gap.exe"\r
+ LinkIncremental="1"\r
+ GenerateDebugInformation="false"\r
+ ProgramDatabaseFile="$(OutDir)\$(TargetName).pdb"\r
+ SubSystem="1"\r
+ OptimizeReferences="2"\r
+ EnableCOMDATFolding="2"\r
+ TargetMachine="1"\r
+ />\r
+ <Tool\r
+ Name="VCALinkTool"\r
+ />\r
+ <Tool\r
+ Name="VCManifestTool"\r
+ />\r
+ <Tool\r
+ Name="VCXDCMakeTool"\r
+ />\r
+ <Tool\r
+ Name="VCBscMakeTool"\r
+ />\r
+ <Tool\r
+ Name="VCFxCopTool"\r
+ />\r
+ <Tool\r
+ Name="VCAppVerifierTool"\r
+ />\r
+ <Tool\r
+ Name="VCWebDeploymentTool"\r
+ />\r
+ <Tool\r
+ Name="VCPostBuildEventTool"\r
+ CommandLine="run.bat "$(TargetPath)""\r
+ />\r
+ </Configuration>\r
+ </Configurations>\r
+ <References>\r
+ </References>\r
+ <Files>\r
+ <Filter\r
+ Name="Source Files"\r
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+ UniqueIdentifier="{7D996CB2-ABC4-11DA-B012-B622A1EF5492}"\r
+ >\r
+ <File\r
+ RelativePath="..\..\..\tools\gap\gap.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\..\tools\gap\perfect.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\..\libyasm\phash.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\..\libyasm\hamt.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\..\libyasm\xmalloc.c"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\..\libyasm\xstrdup.c"\r
+ >\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+ UniqueIdentifier="{85DD7A94-ABC4-11DA-B012-B622A1EF5492}"\r
+ >\r
+ <File\r
+ RelativePath="..\..\..\tools\gap\perfect.h"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\..\tools\gap\standard.h"\r
+ >\r
+ </File>\r
+ </Filter>\r
+ <File\r
+ RelativePath=".\run.bat"\r
+ >\r
+ </File>\r
+ </Files>\r
+ <Globals>\r
+ </Globals>\r
+</VisualStudioProject>\r
--- /dev/null
+cd ..\..\..\\r
+%1 modules\arch\x86\x86parse.gap x86parse.c\r
</FileConfiguration>\r
</File>\r
<File\r
- RelativePath="..\..\..\x86id.c"\r
+ RelativePath="..\..\..\modules\arch\x86\x86id.c"\r
>\r
</File>\r
</Filter>\r
cd ..\..\..\\r
-%1 -s modules\arch\lc3b\lc3bid.re > lc3bid.c\r
-%1 -s modules\arch\x86\x86id.re > x86id.c\r
-%1 -s modules\parsers\nasm\nasm-token.re > nasm-token.c\r
-%1 -s modules\parsers\gas\gas-token.re > gas-token.c\r
+%1 -s -o lc3bid.c modules\arch\lc3b\lc3bid.re\r
+%1 -b -o nasm-token.c modules\parsers\nasm\nasm-token.re\r
+%1 -b -o gas-token.c modules\parsers\gas\gas-token.re\r
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "modules", "modules\modules.vcproj", "{D715A3D4-EFAA-442E-AD8B-5B4FF64E1DD6}"\r
ProjectSection(ProjectDependencies) = postProject\r
{3C58BE13-50A3-4583-984D-D8902B3D7713} = {3C58BE13-50A3-4583-984D-D8902B3D7713}\r
+ {5758BF4E-ABC4-11DA-B012-B622A1EF5492} = {5758BF4E-ABC4-11DA-B012-B622A1EF5492}\r
{29FE7874-1256-4AD6-B889-68E399DC9608} = {29FE7874-1256-4AD6-B889-68E399DC9608}\r
{225700A5-07B8-434E-AD61-555278BF6733} = {225700A5-07B8-434E-AD61-555278BF6733}\r
EndProjectSection\r
EndProject\r
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "re2c", "re2c\re2c.vcproj", "{3C58BE13-50A3-4583-984D-D8902B3D7713}"\r
EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gap", "gap\gap.vcproj", "{5758BF4E-ABC4-11DA-B012-B622A1EF5492}"\r
+EndProject\r
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "genmodule", "genmodule\genmodule.vcproj", "{F0E8B707-00C5-4FF2-B8EF-7C39817132A0}"\r
EndProject\r
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{825AC694-358C-4D8D-92DE-33A2691978CE}"\r
{3C58BE13-50A3-4583-984D-D8902B3D7713}.Release|Win32.Build.0 = Release|Win32\r
{3C58BE13-50A3-4583-984D-D8902B3D7713}.Release|x64.ActiveCfg = Release|Win32\r
{3C58BE13-50A3-4583-984D-D8902B3D7713}.Release|x64.Build.0 = Release|Win32\r
+ {5758BF4E-ABC4-11DA-B012-B622A1EF5492}.Debug|Win32.ActiveCfg = Debug|Win32\r
+ {5758BF4E-ABC4-11DA-B012-B622A1EF5492}.Debug|Win32.Build.0 = Debug|Win32\r
+ {5758BF4E-ABC4-11DA-B012-B622A1EF5492}.Debug|x64.ActiveCfg = Debug|Win32\r
+ {5758BF4E-ABC4-11DA-B012-B622A1EF5492}.Debug|x64.Build.0 = Debug|Win32\r
+ {5758BF4E-ABC4-11DA-B012-B622A1EF5492}.Release|Win32.ActiveCfg = Release|Win32\r
+ {5758BF4E-ABC4-11DA-B012-B622A1EF5492}.Release|Win32.Build.0 = Release|Win32\r
+ {5758BF4E-ABC4-11DA-B012-B622A1EF5492}.Release|x64.ActiveCfg = Release|Win32\r
+ {5758BF4E-ABC4-11DA-B012-B622A1EF5492}.Release|x64.Build.0 = Release|Win32\r
{F0E8B707-00C5-4FF2-B8EF-7C39817132A0}.Debug|Win32.ActiveCfg = Debug|Win32\r
{F0E8B707-00C5-4FF2-B8EF-7C39817132A0}.Debug|Win32.Build.0 = Debug|Win32\r
{F0E8B707-00C5-4FF2-B8EF-7C39817132A0}.Debug|x64.ActiveCfg = Debug|Win32\r
libyasm_a_SOURCES += libyasm/errwarn.c
libyasm_a_SOURCES += libyasm/linemgr.c
libyasm_a_SOURCES += libyasm/assocdat.c
+libyasm_a_SOURCES += libyasm/phash.c
libyasm_a_SOURCES += libyasm/xmalloc.c
libyasm_a_SOURCES += libyasm/xstrdup.c
libyasm_a_SOURCES += libyasm/strcasecmp.c
modinclude_HEADERS += libyasm/valparam.h
modinclude_HEADERS += libyasm/compat-queue.h
modinclude_HEADERS += libyasm/assocdat.h
+modinclude_HEADERS += libyasm/phash.h
modinclude_HEADERS += libyasm/module.h
EXTRA_DIST += libyasm/tests/Makefile.inc
YASM_ARCH_CREATE_BAD_PARSER /**< Unrecognized parser name. */
} yasm_arch_create_error;
+/** Return values for yasm_arch_module::parse_check_insnprefix(). */
+typedef enum {
+ YASM_ARCH_NOTINSNPREFIX = 0, /**< Unrecognized */
+ YASM_ARCH_INSN, /**< An instruction */
+ YASM_ARCH_PREFIX /**< An instruction prefix */
+} yasm_arch_insnprefix;
+
+/** Types of registers / target modifiers that may be returned by
+ * yasm_arch_module::parse_check_regtmod().
+ */
+typedef enum {
+ YASM_ARCH_NOTREGTMOD = 0, /**< Unrecognized */
+ YASM_ARCH_REG, /**< A "normal" register */
+ YASM_ARCH_REGGROUP, /**< A group of indexable registers */
+ YASM_ARCH_SEGREG, /**< A segment register */
+ YASM_ARCH_TARGETMOD /**< A target modifier (for jumps) */
+} yasm_arch_regtmod;
+
/** An instruction operand (opaque type). */
typedef struct yasm_insn_operand yasm_insn_operand;
#ifdef YASM_LIB_INTERNAL
/** Module-level implementation of yasm_arch_parse_cpu().
* Call yasm_arch_parse_cpu() instead of calling this function.
*/
- void (*parse_cpu) (yasm_arch *arch, const char *cpuid,
+ void (*parse_cpu) (yasm_arch *arch, const char *cpuid, size_t cpuid_len,
unsigned long line);
- /** Module-level implementation of yasm_arch_parse_check_reg().
- * Call yasm_arch_parse_check_reg() instead of calling this function.
+ /** Module-level implementation of yasm_arch_parse_check_insnprefix().
+ * Call yasm_arch_parse_check_insnprefix() instead of calling this function.
*/
- int (*parse_check_reg)
- (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id,
- unsigned long line);
-
- /** Module-level implementation of yasm_arch_parse_check_reggroup().
- * Call yasm_arch_parse_check_reggroup() instead of calling this function.
- */
- int (*parse_check_reggroup)
- (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id,
- unsigned long line);
-
- /** Module-level implementation of yasm_arch_parse_check_segreg().
- * Call yasm_arch_parse_check_segreg() instead of calling this function.
- */
- int (*parse_check_segreg)
- (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id,
- unsigned long line);
-
- /** Module-level implementation of yasm_arch_parse_check_insn().
- * Call yasm_arch_parse_check_insn() instead of calling this function.
- */
- int (*parse_check_insn)
+ yasm_arch_insnprefix (*parse_check_insnprefix)
(yasm_arch *arch, /*@out@*/ unsigned long data[4], const char *id,
- unsigned long line);
+ size_t id_len, unsigned long line);
- /** Module-level implementation of yasm_arch_parse_check_prefix().
- * Call yasm_arch_parse_check_prefix() instead of calling this function.
+ /** Module-level implementation of yasm_arch_parse_check_regtmod().
+ * Call yasm_arch_parse_check_regtmod() instead of calling this function.
*/
- int (*parse_check_prefix)
- (yasm_arch *arch, /*@out@*/ unsigned long data[4], const char *id,
- unsigned long line);
-
- /** Module-level implementation of yasm_arch_parse_check_targetmod().
- * Call yasm_arch_parse_check_targetmod() instead of calling this function.
- */
- int (*parse_check_targetmod)
- (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id,
- unsigned long line);
+ yasm_arch_regtmod (*parse_check_regtmod)
+ (yasm_arch *arch, /*@out@*/ unsigned long *data, const char *id,
+ size_t id_len, unsigned long line);
/** Module-level implementation of yasm_arch_parse_directive().
* Call yasm_arch_parse_directive() instead of calling this function.
/** Switch available instructions/registers/etc based on a user-specified
* CPU identifier. Should modify behavior ONLY of parse_* functions! The
* bytecode and output functions should be able to handle any CPU.
- * \param arch architecture
- * \param cpuid cpu identifier as in the input file
- * \param line virtual line (from yasm_linemap)
+ * \param arch architecture
+ * \param cpuid cpu identifier as in the input file
+ * \param cpuid_len length of cpu identifier string
+ * \param line virtual line (from yasm_linemap)
*/
-void yasm_arch_parse_cpu(yasm_arch *arch, const char *cpuid,
+void yasm_arch_parse_cpu(yasm_arch *arch, const char *cpuid, size_t cpuid_len,
unsigned long line);
/** Check an generic identifier to see if it matches architecture specific
- * names for registers. Unrecognized identifiers should return 0
- * so they can be treated as normal symbols. Any additional data beyond
- * just the type (almost always necessary) should be returned into the
- * space provided by the data parameter.
- * \param arch architecture
- * \param data extra identification information (yasm_arch-specific)
- * [output]
- * \param id identifier as in the input file
- * \param line virtual line (from yasm_linemap)
- * \return 1 if id is a register, 0 if not.
- */
-int yasm_arch_parse_check_reg
- (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id,
- unsigned long line);
-
-/** Check an generic identifier to see if it matches architecture specific
- * names for register groups. Unrecognized identifiers should return 0
- * so they can be treated as normal symbols. Any additional data beyond
- * just the type (almost always necessary) should be returned into the
- * space provided by the data parameter.
- * \param arch architecture
- * \param data extra identification information (yasm_arch-specific)
- * [output]
- * \param id identifier as in the input file
- * \param line virtual line (from yasm_linemap)
- * \return 1 if id is a register, 0 if not.
- */
-int yasm_arch_parse_check_reggroup
- (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id,
- unsigned long line);
-
-/** Check an generic identifier to see if it matches architecture specific
- * names for segment registers. Unrecognized identifiers should return 0
- * so they can be treated as normal symbols. Any additional data beyond
- * just the type (almost always necessary) should be returned into the
- * space provided by the data parameter.
- * \param arch architecture
- * \param data extra identification information (yasm_arch-specific)
- * [output]
- * \param id identifier as in the input file
- * \param line virtual line (from yasm_linemap)
- * \return 1 if id is a register, 0 if not.
- */
-int yasm_arch_parse_check_segreg
- (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id,
- unsigned long line);
-
-/** Check an generic identifier to see if it matches architecture specific
- * names for instructions. Unrecognized identifiers should return 0
- * so they can be treated as normal symbols. Any additional data beyond
- * just the type (almost always necessary) should be returned into the
- * space provided by the data parameter.
- * \param arch architecture
- * \param data extra identification information (yasm_arch-specific)
- * [output]
- * \param id identifier as in the input file
- * \param line virtual line (from yasm_linemap)
- * \return 1 if id is a register, 0 if not.
- */
-int yasm_arch_parse_check_insn
- (yasm_arch *arch, /*@out@*/ unsigned long data[4], const char *id,
- unsigned long line);
-
-/** Check an generic identifier to see if it matches architecture specific
- * names for prefixes. Unrecognized identifiers should return 0
- * so they can be treated as normal symbols. Any additional data beyond
- * just the type (almost always necessary) should be returned into the
- * space provided by the data parameter.
- * \param arch architecture
- * \param data extra identification information (yasm_arch-specific)
- * [output]
- * \param id identifier as in the input file
- * \param line virtual line (from yasm_linemap)
- * \return 1 if id is a register, 0 if not.
- */
-int yasm_arch_parse_check_prefix
+ * names for instructions or instruction prefixes. Unrecognized identifiers
+ * should return #YASM_ARCH_NOTINSNPREFIX so they can be treated as normal
+ * symbols. Any additional data beyond just the type (almost always necessary)
+ * should be returned into the space provided by the data parameter.
+ * \param arch architecture
+ * \param data extra identification information (yasm_arch-specific)
+ * [output]
+ * \param id identifier as in the input file
+ * \param id_len length of id string
+ * \param line virtual line (from yasm_linemap)
+ * \return Identifier type (#YASM_ARCH_NOTINSNPREFIX if unrecognized)
+ */
+yasm_arch_insnprefix yasm_arch_parse_check_insnprefix
(yasm_arch *arch, /*@out@*/ unsigned long data[4], const char *id,
- unsigned long line);
+ size_t id_len, unsigned long line);
/** Check an generic identifier to see if it matches architecture specific
- * names for target modifiers. Unrecognized identifiers should return 0
- * so they can be treated as normal symbols. Any additional data beyond
- * just the type (almost always necessary) should be returned into the
- * space provided by the data parameter.
- * \param arch architecture
- * \param data extra identification information (yasm_arch-specific)
- * [output]
- * \param id identifier as in the input file
- * \param line virtual line (from yasm_linemap)
- * \return 1 if id is a register, 0 if not.
+ * names for registers or target modifiers. Unrecognized identifiers should
+ * return #YASM_ARCH_NOTREGTMOD. Any additional data beyond just the type
+ * (almost always necessary) should be returned into the space provided by the
+ * data parameter.
+ * \param arch architecture
+ * \param data extra identification information (yasm_arch-specific)
+ * [output]
+ * \param id identifier as in the input file
+ * \param id_len length of id string
+ * \param line virtual line (from yasm_linemap)
+ * \return Identifier type (#YASM_ARCH_NOTREGTMOD if unrecognized)
*/
-int yasm_arch_parse_check_targetmod
- (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id,
- unsigned long line);
+yasm_arch_regtmod yasm_arch_parse_check_regtmod
+ (yasm_arch *arch, /*@out@*/ unsigned long *data, const char *id,
+ size_t id_len, unsigned long line);
/** Handle architecture-specific directives.
* Should modify behavior ONLY of parse functions, much like parse_cpu().
((yasm_arch_base *)arch)->module->get_address_size(arch)
#define yasm_arch_set_var(arch, var, val) \
((yasm_arch_base *)arch)->module->set_var(arch, var, val)
-#define yasm_arch_parse_cpu(arch, cpuid, line) \
- ((yasm_arch_base *)arch)->module->parse_cpu(arch, cpuid, line)
-#define yasm_arch_parse_check_reg(arch, data, id, line) \
- ((yasm_arch_base *)arch)->module->parse_check_reg(arch, data, id, line)
-#define yasm_arch_parse_check_reggroup(arch, data, id, line) \
- ((yasm_arch_base *)arch)->module->parse_check_reggroup(arch, data, id, \
- line)
-#define yasm_arch_parse_check_segreg(arch, data, id, line) \
- ((yasm_arch_base *)arch)->module->parse_check_segreg(arch, data, id, line)
-#define yasm_arch_parse_check_insn(arch, data, id, line) \
- ((yasm_arch_base *)arch)->module->parse_check_insn(arch, data, id, line)
-#define yasm_arch_parse_check_prefix(arch, data, id, line) \
- ((yasm_arch_base *)arch)->module->parse_check_prefix(arch, data, id, line)
-#define yasm_arch_parse_check_targetmod(arch, data, id, line) \
- ((yasm_arch_base *)arch)->module->parse_check_targetmod(arch, data, id, \
- line)
+#define yasm_arch_parse_cpu(arch, cpuid, cpuid_len, line) \
+ ((yasm_arch_base *)arch)->module->parse_cpu(arch, cpuid, cpuid_len, line)
+#define yasm_arch_parse_check_insnprefix(arch, data, id, id_len, line) \
+ ((yasm_arch_base *)arch)->module->parse_check_insnprefix(arch, data, id, \
+ id_len, line)
+#define yasm_arch_parse_check_regtmod(arch, data, id, id_len, line) \
+ ((yasm_arch_base *)arch)->module->parse_check_regtmod(arch, data, id, \
+ id_len, line)
#define yasm_arch_parse_directive(arch, name, valparams, objext_valparams, \
object, line) \
((yasm_arch_base *)arch)->module->parse_directive \
--- /dev/null
+/* Modified for use with yasm by Peter Johnson. */
+#define YASM_LIB_INTERNAL
+#include "util.h"
+/*@unused@*/ RCSID("$Id$");
+
+/*
+--------------------------------------------------------------------
+lookupa.c, by Bob Jenkins, December 1996. Same as lookup2.c
+Use this code however you wish. Public Domain. No warranty.
+Source is http://burtleburtle.net/bob/c/lookupa.c
+--------------------------------------------------------------------
+*/
+#include "phash.h"
+
+#define ub4 unsigned long
+
+#define hashsize(n) ((ub4)1<<(n))
+#define hashmask(n) (hashsize(n)-1)
+
+/*
+--------------------------------------------------------------------
+mix -- mix 3 32-bit values reversibly.
+For every delta with one or two bit set, and the deltas of all three
+ high bits or all three low bits, whether the original value of a,b,c
+ is almost all zero or is uniformly distributed,
+* If mix() is run forward or backward, at least 32 bits in a,b,c
+ have at least 1/4 probability of changing.
+* If mix() is run forward, every bit of c will change between 1/3 and
+ 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
+mix() was built out of 36 single-cycle latency instructions in a
+ structure that could supported 2x parallelism, like so:
+ a -= b;
+ a -= c; x = (c>>13);
+ b -= c; a ^= x;
+ b -= a; x = (a<<8);
+ c -= a; b ^= x;
+ c -= b; x = (b>>13);
+ ...
+ Unfortunately, superscalar Pentiums and Sparcs can't take advantage
+ of that parallelism. They've also turned some of those single-cycle
+ latency instructions into multi-cycle latency instructions. Still,
+ this is the fastest good hash I could find. There were about 2^^68
+ to choose from. I only looked at a billion or so.
+--------------------------------------------------------------------
+*/
+#define mix(a,b,c) \
+{ \
+ a -= b; a -= c; a ^= (c>>13); \
+ b -= c; b -= a; b ^= (a<<8); \
+ c -= a; c -= b; c ^= (b>>13); \
+ a -= b; a -= c; a ^= (c>>12); \
+ b -= c; b -= a; b ^= (a<<16); \
+ c -= a; c -= b; c ^= (b>>5); \
+ a -= b; a -= c; a ^= (c>>3); \
+ b -= c; b -= a; b ^= (a<<10); \
+ c -= a; c -= b; c ^= (b>>15); \
+}
+
+/*
+--------------------------------------------------------------------
+lookup() -- hash a variable-length key into a 32-bit value
+ k : the key (the unaligned variable-length array of bytes)
+ len : the length of the key, counting by bytes
+ level : can be any 4-byte value
+Returns a 32-bit value. Every bit of the key affects every bit of
+the return value. Every 1-bit and 2-bit delta achieves avalanche.
+About 6len+35 instructions.
+
+The best hash table sizes are powers of 2. There is no need to do
+mod a prime (mod is sooo slow!). If you need less than 32 bits,
+use a bitmask. For example, if you need only 10 bits, do
+ h = (h & hashmask(10));
+In which case, the hash table should have hashsize(10) elements.
+
+If you are hashing n strings (ub1 **)k, do it like this:
+ for (i=0, h=0; i<n; ++i) h = lookup( k[i], len[i], h);
+
+By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
+code any way you wish, private, educational, or commercial.
+
+See http://burtleburtle.net/bob/hash/evahash.html
+Use for hash table lookup, or anything where one collision in 2^32 is
+acceptable. Do NOT use for cryptographic purposes.
+--------------------------------------------------------------------
+*/
+
+unsigned long
+phash_lookup(
+ register const char *sk, /* the key */
+ register unsigned long length, /* the length of the key */
+ register unsigned long level) /* the previous hash, or an arbitrary value */
+{
+ register unsigned long a,b,c,len;
+ register const unsigned char *k = (const unsigned char *)sk;
+
+ /* Set up the internal state */
+ len = length;
+ a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
+ c = level; /* the previous hash value */
+
+ /*---------------------------------------- handle most of the key */
+ while (len >= 12)
+ {
+ a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
+ b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
+ c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
+ mix(a,b,c);
+ k += 12; len -= 12;
+ }
+
+ /*------------------------------------- handle the last 11 bytes */
+ c += length;
+ switch(len) /* all the case statements fall through */
+ {
+ case 11: c+=((ub4)k[10]<<24);
+ case 10: c+=((ub4)k[9]<<16);
+ case 9 : c+=((ub4)k[8]<<8);
+ /* the first byte of c is reserved for the length */
+ case 8 : b+=((ub4)k[7]<<24);
+ case 7 : b+=((ub4)k[6]<<16);
+ case 6 : b+=((ub4)k[5]<<8);
+ case 5 : b+=k[4];
+ case 4 : a+=((ub4)k[3]<<24);
+ case 3 : a+=((ub4)k[2]<<16);
+ case 2 : a+=((ub4)k[1]<<8);
+ case 1 : a+=k[0];
+ /* case 0: nothing left to add */
+ }
+ mix(a,b,c);
+ /*-------------------------------------------- report the result */
+ return c;
+}
+
+
+/*
+--------------------------------------------------------------------
+mixc -- mixc 8 4-bit values as quickly and thoroughly as possible.
+Repeating mix() three times achieves avalanche.
+Repeating mix() four times eliminates all funnels and all
+ characteristics stronger than 2^{-11}.
+--------------------------------------------------------------------
+*/
+#define mixc(a,b,c,d,e,f,g,h) \
+{ \
+ a^=b<<11; d+=a; b+=c; \
+ b^=c>>2; e+=b; c+=d; \
+ c^=d<<8; f+=c; d+=e; \
+ d^=e>>16; g+=d; e+=f; \
+ e^=f<<10; h+=e; f+=g; \
+ f^=g>>4; a+=f; g+=h; \
+ g^=h<<8; b+=g; h+=a; \
+ h^=a>>9; c+=h; a+=b; \
+}
+
+/*
+--------------------------------------------------------------------
+checksum() -- hash a variable-length key into a 256-bit value
+ k : the key (the unaligned variable-length array of bytes)
+ len : the length of the key, counting by bytes
+ state : an array of CHECKSTATE 4-byte values (256 bits)
+The state is the checksum. Every bit of the key affects every bit of
+the state. There are no funnels. About 112+6.875len instructions.
+
+If you are hashing n strings (ub1 **)k, do it like this:
+ for (i=0; i<8; ++i) state[i] = 0x9e3779b9;
+ for (i=0, h=0; i<n; ++i) checksum( k[i], len[i], state);
+
+(c) Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
+code any way you wish, private, educational, or commercial, as long
+as this whole comment accompanies it.
+
+See http://burtleburtle.net/bob/hash/evahash.html
+Use to detect changes between revisions of documents, assuming nobody
+is trying to cause collisions. Do NOT use for cryptography.
+--------------------------------------------------------------------
+*/
+void
+phash_checksum(
+ register const unsigned char *k,
+ register unsigned long len,
+ register unsigned long *state)
+{
+ register unsigned long a,b,c,d,e,f,g,h,length;
+
+ /* Use the length and level; add in the golden ratio. */
+ length = len;
+ a=state[0]; b=state[1]; c=state[2]; d=state[3];
+ e=state[4]; f=state[5]; g=state[6]; h=state[7];
+
+ /*---------------------------------------- handle most of the key */
+ while (len >= 32)
+ {
+ a += (k[0] +(k[1]<<8) +(k[2]<<16) +(k[3]<<24));
+ b += (k[4] +(k[5]<<8) +(k[6]<<16) +(k[7]<<24));
+ c += (k[8] +(k[9]<<8) +(k[10]<<16)+(k[11]<<24));
+ d += (k[12]+(k[13]<<8)+(k[14]<<16)+(k[15]<<24));
+ e += (k[16]+(k[17]<<8)+(k[18]<<16)+(k[19]<<24));
+ f += (k[20]+(k[21]<<8)+(k[22]<<16)+(k[23]<<24));
+ g += (k[24]+(k[25]<<8)+(k[26]<<16)+(k[27]<<24));
+ h += (k[28]+(k[29]<<8)+(k[30]<<16)+(k[31]<<24));
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ k += 32; len -= 32;
+ }
+
+ /*------------------------------------- handle the last 31 bytes */
+ h += length;
+ switch(len)
+ {
+ case 31: h+=(k[30]<<24);
+ case 30: h+=(k[29]<<16);
+ case 29: h+=(k[28]<<8);
+ case 28: g+=(k[27]<<24);
+ case 27: g+=(k[26]<<16);
+ case 26: g+=(k[25]<<8);
+ case 25: g+=k[24];
+ case 24: f+=(k[23]<<24);
+ case 23: f+=(k[22]<<16);
+ case 22: f+=(k[21]<<8);
+ case 21: f+=k[20];
+ case 20: e+=(k[19]<<24);
+ case 19: e+=(k[18]<<16);
+ case 18: e+=(k[17]<<8);
+ case 17: e+=k[16];
+ case 16: d+=(k[15]<<24);
+ case 15: d+=(k[14]<<16);
+ case 14: d+=(k[13]<<8);
+ case 13: d+=k[12];
+ case 12: c+=(k[11]<<24);
+ case 11: c+=(k[10]<<16);
+ case 10: c+=(k[9]<<8);
+ case 9 : c+=k[8];
+ case 8 : b+=(k[7]<<24);
+ case 7 : b+=(k[6]<<16);
+ case 6 : b+=(k[5]<<8);
+ case 5 : b+=k[4];
+ case 4 : a+=(k[3]<<24);
+ case 3 : a+=(k[2]<<16);
+ case 2 : a+=(k[1]<<8);
+ case 1 : a+=k[0];
+ }
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+ mixc(a,b,c,d,e,f,g,h);
+
+ /*-------------------------------------------- report the result */
+ state[0]=a; state[1]=b; state[2]=c; state[3]=d;
+ state[4]=e; state[5]=f; state[6]=g; state[7]=h;
+}
--- /dev/null
+/* Modified for use with yasm by Peter Johnson.
+ * $Id$
+ */
+/*
+------------------------------------------------------------------------------
+By Bob Jenkins, September 1996.
+lookupa.h, a hash function for table lookup, same function as lookup.c.
+Use this code in any way you wish. Public Domain. It has no warranty.
+Source is http://burtleburtle.net/bob/c/lookupa.h
+------------------------------------------------------------------------------
+*/
+
+unsigned long phash_lookup(const char *k, unsigned long length,
+ unsigned long level);
+void phash_checksum(const unsigned char *k, unsigned long length,
+ unsigned long *state);
lc3b_get_address_size,
lc3b_set_var,
yasm_lc3b__parse_cpu,
- yasm_lc3b__parse_check_reg,
- yasm_lc3b__parse_check_reggroup,
- yasm_lc3b__parse_check_segreg,
- yasm_lc3b__parse_check_insn,
- yasm_lc3b__parse_check_prefix,
- yasm_lc3b__parse_check_targetmod,
+ yasm_lc3b__parse_check_insnprefix,
+ yasm_lc3b__parse_check_regtmod,
lc3b_parse_directive,
lc3b_get_fill,
yasm_lc3b__finalize_insn,
void yasm_lc3b__bc_transform_insn(yasm_bytecode *bc, lc3b_insn *insn);
-void yasm_lc3b__parse_cpu(yasm_arch *arch, const char *cpuid,
+void yasm_lc3b__parse_cpu(yasm_arch *arch, const char *cpuid, size_t cpuid_len,
unsigned long line);
-int yasm_lc3b__parse_check_reg
- (yasm_arch *arch, unsigned long data[1], const char *id,
+yasm_arch_insnprefix yasm_lc3b__parse_check_insnprefix
+ (yasm_arch *arch, unsigned long data[4], const char *id, size_t id_len,
unsigned long line);
-int yasm_lc3b__parse_check_reggroup
- (yasm_arch *arch, unsigned long data[1], const char *id,
- unsigned long line);
-int yasm_lc3b__parse_check_segreg
- (yasm_arch *arch, unsigned long data[1], const char *id,
- unsigned long line);
-int yasm_lc3b__parse_check_insn
- (yasm_arch *arch, unsigned long data[4], const char *id,
- unsigned long line);
-int yasm_lc3b__parse_check_prefix
- (yasm_arch *arch, unsigned long data[4], const char *id,
- unsigned long line);
-int yasm_lc3b__parse_check_targetmod
- (yasm_arch *arch, unsigned long data[1], const char *id,
+yasm_arch_regtmod yasm_lc3b__parse_check_regtmod
+ (yasm_arch *arch, unsigned long *data, const char *id, size_t id_len,
unsigned long line);
void yasm_lc3b__finalize_insn
#define RET_INSN(group, mod) do { \
DEF_INSN_DATA(group, mod); \
- return 1; \
+ return YASM_ARCH_INSN; \
} while (0)
/*
#define YYFILL(n) (void)(n)
void
-yasm_lc3b__parse_cpu(yasm_arch *arch, const char *id, unsigned long line)
+yasm_lc3b__parse_cpu(yasm_arch *arch, const char *cpuid, size_t cpuid_len,
+ unsigned long line)
{
}
-int
-yasm_lc3b__parse_check_reg(yasm_arch *arch, unsigned long data[1],
- const char *id, unsigned long line)
+yasm_arch_regtmod
+yasm_lc3b__parse_check_regtmod(yasm_arch *arch, unsigned long *data,
+ const char *id, size_t id_len,
+ unsigned long line)
{
const char *oid = id;
/*const char *marker;*/
/*!re2c
/* integer registers */
'r' [0-7] {
- data[0] = (oid[1]-'0');
- return 1;
+ *data = (oid[1]-'0');
+ return YASM_ARCH_REG;
}
/* catchalls */
[\001-\377]+ {
- return 0;
+ return YASM_ARCH_NOTREGTMOD;
}
[\000] {
- return 0;
+ return YASM_ARCH_NOTREGTMOD;
}
*/
}
-int
-yasm_lc3b__parse_check_reggroup(yasm_arch *arch, unsigned long data[1],
- const char *id, unsigned long line)
-{
- return 0;
-}
-
-int
-yasm_lc3b__parse_check_segreg(yasm_arch *arch, unsigned long data[1],
- const char *id, unsigned long line)
-{
- return 0;
-}
-
-int
-yasm_lc3b__parse_check_insn(yasm_arch *arch, unsigned long data[4],
- const char *id, unsigned long line)
+yasm_arch_insnprefix
+yasm_lc3b__parse_check_insnprefix(yasm_arch *arch, unsigned long data[4],
+ const char *id, size_t id_len,
+ unsigned long line)
{
/*const char *oid = id;*/
/*const char *marker;*/
/* catchalls */
[\001-\377]+ {
- return 0;
+ return YASM_ARCH_NOTINSNPREFIX;
}
[\000] {
- return 0;
+ return YASM_ARCH_NOTINSNPREFIX;
}
*/
}
-
-int
-yasm_lc3b__parse_check_prefix(yasm_arch *arch, unsigned long data[4],
- const char *id, unsigned long line)
-{
- return 0;
-}
-
-int
-yasm_lc3b__parse_check_targetmod(yasm_arch *arch, unsigned long data[1],
- const char *id, unsigned long line)
-{
- return 0;
-}
libyasm_a_SOURCES += modules/arch/x86/x86arch.h
libyasm_a_SOURCES += modules/arch/x86/x86bc.c
libyasm_a_SOURCES += modules/arch/x86/x86expr.c
-libyasm_a_SOURCES += x86id.c
+libyasm_a_SOURCES += modules/arch/x86/x86id.c
YASM_MODULES += arch_x86
-x86id.c: $(srcdir)/modules/arch/x86/x86id.re re2c$(EXEEXT)
- $(top_builddir)/re2c$(EXEEXT) -s -o $@ $(srcdir)/modules/arch/x86/x86id.re
+modules/arch/x86/x86id.c: x86parse.c
-BUILT_SOURCES += x86id.c
+EXTRA_DIST += modules/arch/x86/x86parse.gap
-CLEANFILES += x86id.c
+x86parse.c: $(srcdir)/modules/arch/x86/x86parse.gap gap$(EXEEXT)
+ $(top_builddir)/gap$(EXEEXT) $(srcdir)/modules/arch/x86/x86parse.gap $@
+
+BUILT_SOURCES += x86parse.c
+CLEANFILES += x86parse.c
EXTRA_DIST += modules/arch/x86/tests/Makefile.inc
-EXTRA_DIST += modules/arch/x86/x86id.re
include modules/arch/x86/tests/Makefile.inc
x86_get_address_size,
x86_set_var,
yasm_x86__parse_cpu,
- yasm_x86__parse_check_reg,
- yasm_x86__parse_check_reggroup,
- yasm_x86__parse_check_segreg,
- yasm_x86__parse_check_insn,
- yasm_x86__parse_check_prefix,
- yasm_x86__parse_check_targetmod,
+ yasm_x86__parse_check_insnprefix,
+ yasm_x86__parse_check_regtmod,
x86_parse_directive,
x86_get_fill,
yasm_x86__finalize_insn,
unsigned char *pcrel, unsigned char *rex,
yasm_calc_bc_dist_func calc_bc_dist);
-void yasm_x86__parse_cpu(yasm_arch *arch, const char *cpuid,
+void yasm_x86__parse_cpu(yasm_arch *arch, const char *cpuid, size_t cpuid_len,
unsigned long line);
-int yasm_x86__parse_check_reg
- (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id,
- unsigned long line);
-int yasm_x86__parse_check_reggroup
- (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id,
- unsigned long line);
-int yasm_x86__parse_check_segreg
- (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id,
- unsigned long line);
-int yasm_x86__parse_check_insn
+yasm_arch_insnprefix yasm_x86__parse_check_insnprefix
(yasm_arch *arch, /*@out@*/ unsigned long data[4], const char *id,
- unsigned long line);
-int yasm_x86__parse_check_prefix
- (yasm_arch *arch, /*@out@*/ unsigned long data[4], const char *id,
- unsigned long line);
-int yasm_x86__parse_check_targetmod
- (yasm_arch *arch, /*@out@*/ unsigned long data[1], const char *id,
- unsigned long line);
+ size_t id_len, unsigned long line);
+yasm_arch_regtmod yasm_x86__parse_check_regtmod
+ (yasm_arch *arch, /*@out@*/ unsigned long *data, const char *id,
+ size_t id_len, unsigned long line);
void yasm_x86__finalize_insn
(yasm_arch *arch, yasm_bytecode *bc, yasm_bytecode *prev_bc,
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <ctype.h>
#include <util.h>
RCSID("$Id$");
#define YASM_BC_INTERNAL
#define YASM_EXPR_INTERNAL
#include <libyasm.h>
+#include <libyasm/phash.h>
#include "modules/arch/x86/x86arch.h"
unsigned long operands[3];
} x86_insn_info;
-/* Define lexer arch-specific data with 0-3 modifiers.
- * This assumes arch_x86 is locally defined.
- */
-#define DEF_INSN_DATA(group, mod, cpu) do { \
- data[0] = (unsigned long)group##_insn; \
- data[1] = (((unsigned long)mod)<<8) | \
- ((unsigned char)(sizeof(group##_insn)/sizeof(x86_insn_info))); \
- data[2] = cpu; \
- } while (0)
-
/*
* General instruction groupings
*/
yasm_x86__bc_transform_insn(bc, insn);
}
+/* Static parse data structure for instructions */
+typedef struct insnprefix_parse_data {
+ const char *name;
-#define YYCTYPE char
-#define YYCURSOR id
-#define YYLIMIT id
-#define YYMARKER marker
-#define YYFILL(n) (void)(n)
-
-/*!re2c
- any = [\000-\377];
- A = [aA];
- B = [bB];
- C = [cC];
- D = [dD];
- E = [eE];
- F = [fF];
- G = [gG];
- H = [hH];
- I = [iI];
- J = [jJ];
- K = [kK];
- L = [lL];
- M = [mM];
- N = [nN];
- O = [oO];
- P = [pP];
- Q = [qQ];
- R = [rR];
- S = [sS];
- T = [tT];
- U = [uU];
- V = [vV];
- W = [wW];
- X = [xX];
- Y = [yY];
- Z = [zZ];
-*/
-
-void
-yasm_x86__parse_cpu(yasm_arch *arch, const char *id, unsigned long line)
-{
- yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
- /*const char *marker;*/
+ /* instruction parse group - NULL if prefix */
+ /*@null@*/ const x86_insn_info *group;
- /*!re2c
- /* The standard CPU names /set/ cpu_enabled. */
- "8086" {
- arch_x86->cpu_enabled = CPU_Priv;
- return;
- }
- ("80" | I)? "186" {
- arch_x86->cpu_enabled = CPU_186|CPU_Priv;
- return;
- }
- ("80" | I)? "286" {
- arch_x86->cpu_enabled = CPU_186|CPU_286|CPU_Priv;
- return;
- }
- ("80" | I)? "386" {
- arch_x86->cpu_enabled =
- CPU_186|CPU_286|CPU_386|CPU_SMM|CPU_Prot|CPU_Priv;
- return;
- }
- ("80" | I)? "486" {
- arch_x86->cpu_enabled =
- CPU_186|CPU_286|CPU_386|CPU_486|CPU_FPU|CPU_SMM|CPU_Prot|
- CPU_Priv;
- return;
- }
- (I? "586") | 'pentium' | 'p5' {
- arch_x86->cpu_enabled =
- CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_FPU|CPU_SMM|
- CPU_Prot|CPU_Priv;
- return;
- }
- (I? "686") | 'p6' | 'ppro' | 'pentiumpro' {
- arch_x86->cpu_enabled =
- CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|CPU_FPU|
- CPU_SMM|CPU_Prot|CPU_Priv;
- return;
- }
- ('p2') | ('pentium' "-"? ("2" | 'ii')) {
- arch_x86->cpu_enabled =
- CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|CPU_FPU|
- CPU_MMX|CPU_SMM|CPU_Prot|CPU_Priv;
- return;
- }
- ('p3') | ('pentium' "-"? ("3" | 'iii')) | 'katmai' {
- arch_x86->cpu_enabled =
- CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|CPU_P3|CPU_FPU|
- CPU_MMX|CPU_SSE|CPU_SMM|CPU_Prot|CPU_Priv;
- return;
- }
- ('p4') | ('pentium' "-"? ("4" | 'iv')) | 'williamette' {
- arch_x86->cpu_enabled =
- CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|CPU_P3|CPU_P4|
- CPU_FPU|CPU_MMX|CPU_SSE|CPU_SSE2|CPU_SMM|CPU_Prot|CPU_Priv;
- return;
- }
- ('ia' "-"? "64") | 'itanium' {
- arch_x86->cpu_enabled =
- CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|CPU_P3|CPU_P4|
- CPU_IA64|CPU_FPU|CPU_MMX|CPU_SSE|CPU_SSE2|CPU_SMM|CPU_Prot|
- CPU_Priv;
- return;
- }
- 'k6' {
- arch_x86->cpu_enabled =
- CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|CPU_K6|CPU_FPU|
- CPU_MMX|CPU_3DNow|CPU_SMM|CPU_Prot|CPU_Priv;
- return;
- }
- 'athlon' | 'k7' {
- arch_x86->cpu_enabled =
- CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|CPU_K6|
- CPU_Athlon|CPU_FPU|CPU_MMX|CPU_SSE|CPU_3DNow|CPU_SMM|CPU_Prot|
- CPU_Priv;
- return;
- }
- ('sledge'? 'hammer') | 'opteron' | ('athlon' "-"? "64") {
- arch_x86->cpu_enabled =
- CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|CPU_K6|
- CPU_Athlon|CPU_Hammer|CPU_FPU|CPU_MMX|CPU_SSE|CPU_SSE2|
- CPU_3DNow|CPU_SMM|CPU_Prot|CPU_Priv;
- return;
- }
- 'prescott' {
- arch_x86->cpu_enabled =
- CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|CPU_K6|
- CPU_Athlon|CPU_Hammer|CPU_FPU|CPU_MMX|CPU_SSE|CPU_SSE2|
- CPU_SSE3|CPU_3DNow|CPU_SMM|CPU_Prot|CPU_Priv;
- return;
- }
-
- /* Features have "no" versions to disable them, and only set/reset the
- * specific feature being changed. All other bits are left alone.
- */
- 'fpu' { arch_x86->cpu_enabled |= CPU_FPU; return; }
- 'nofpu' { arch_x86->cpu_enabled &= ~CPU_FPU; return; }
- 'mmx' { arch_x86->cpu_enabled |= CPU_MMX; return; }
- 'nommx' { arch_x86->cpu_enabled &= ~CPU_MMX; return; }
- 'sse' { arch_x86->cpu_enabled |= CPU_SSE; return; }
- 'nosse' { arch_x86->cpu_enabled &= ~CPU_SSE; return; }
- 'sse2' { arch_x86->cpu_enabled |= CPU_SSE2; return; }
- 'nosse2' { arch_x86->cpu_enabled &= ~CPU_SSE2; return; }
- 'sse3' { arch_x86->cpu_enabled |= CPU_SSE3; return; }
- 'nosse3' { arch_x86->cpu_enabled &= ~CPU_SSE3; return; }
- 'pni' { arch_x86->cpu_enabled |= CPU_SSE3; return; }
- 'nopni' { arch_x86->cpu_enabled &= ~CPU_SSE3; return; }
- '3dnow' { arch_x86->cpu_enabled |= CPU_3DNow; return; }
- 'no3dnow' { arch_x86->cpu_enabled &= ~CPU_3DNow; return; }
- 'cyrix' { arch_x86->cpu_enabled |= CPU_Cyrix; return; }
- 'nocyrix' { arch_x86->cpu_enabled &= ~CPU_Cyrix; return; }
- 'amd' { arch_x86->cpu_enabled |= CPU_AMD; return; }
- 'noamd' { arch_x86->cpu_enabled &= ~CPU_AMD; return; }
- 'smm' { arch_x86->cpu_enabled |= CPU_SMM; return; }
- 'nosmm' { arch_x86->cpu_enabled &= ~CPU_SMM; return; }
- 'prot' { arch_x86->cpu_enabled |= CPU_Prot; return; }
- 'noprot' { arch_x86->cpu_enabled &= ~CPU_Prot; return; }
- 'undoc' { arch_x86->cpu_enabled |= CPU_Undoc; return; }
- 'noundoc' { arch_x86->cpu_enabled &= ~CPU_Undoc; return; }
- 'obs' { arch_x86->cpu_enabled |= CPU_Obs; return; }
- 'noobs' { arch_x86->cpu_enabled &= ~CPU_Obs; return; }
- 'priv' { arch_x86->cpu_enabled |= CPU_Priv; return; }
- 'nopriv' { arch_x86->cpu_enabled &= ~CPU_Priv; return; }
- 'svm' { arch_x86->cpu_enabled |= CPU_SVM; return; }
- 'nosvm' { arch_x86->cpu_enabled &= ~CPU_SVM; return; }
- 'padlock' { arch_x86->cpu_enabled |= CPU_PadLock; return; }
- 'nopadlock' { arch_x86->cpu_enabled &= ~CPU_PadLock; return; }
-
- /* catchalls */
- [\001-\377]+ {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("unrecognized CPU identifier `%s'"), id);
- return;
- }
- [\000] {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("unrecognized CPU identifier `%s'"), id);
- return;
- }
- */
-}
-
-int
-yasm_x86__parse_check_targetmod(yasm_arch *arch, unsigned long data[1],
- const char *id, unsigned long line)
-{
- /*!re2c
- /* target modifiers */
- 'near' {
- data[0] = X86_NEAR;
- return 1;
- }
- 'short' {
- data[0] = X86_SHORT;
- return 1;
- }
- 'far' {
- data[0] = X86_FAR;
- return 1;
- }
- 'to' {
- data[0] = X86_TO;
- return 1;
- }
+ /* For instruction, modifier in upper 24 bits, number of elements in group
+ * in lower 8 bits.
+ * For prefix, prefix type.
+ */
+ unsigned long data1;
- /* catchalls */
- [\001-\377]+ {
- return 0;
- }
- [\000] {
- return 0;
- }
- */
- return 0;
-}
+ /* For instruction, cpu flags.
+ * For prefix, prefix value.
+ */
+ unsigned long data2;
+
+ /* suffix flags for instructions */
+ enum {
+ NONE = 0,
+ SUF_B = (MOD_GasSufB >> MOD_GasSuf_SHIFT),
+ SUF_W = (MOD_GasSufW >> MOD_GasSuf_SHIFT),
+ SUF_L = (MOD_GasSufL >> MOD_GasSuf_SHIFT),
+ SUF_Q = (MOD_GasSufQ >> MOD_GasSuf_SHIFT),
+ SUF_S = (MOD_GasSufS >> MOD_GasSuf_SHIFT),
+ WEAK = 0x80 /* Relaxed operand mode for GAS */
+ } flags;
+} insnprefix_parse_data;
+#define INSN(name, flags, group, mod, cpu) \
+ { name, group##_insn, (mod##UL<<8)|NELEMS(group##_insn), cpu, flags }
+#define PREFIX(name, type, value) \
+ { name, NULL, type, value, NONE }
+
+/* Static parse data structure for CPU feature flags */
+typedef struct cpu_parse_data {
+ const char *name;
-int
-yasm_x86__parse_check_prefix(yasm_arch *arch, unsigned long data[4],
- const char *id, unsigned long line)
+ unsigned long cpu;
+ enum {
+ CPU_MODE_VERBATIM,
+ CPU_MODE_SET,
+ CPU_MODE_CLEAR
+ } mode;
+} cpu_parse_data;
+
+typedef struct regtmod_parse_data {
+ const char *name;
+
+ unsigned long regtmod;
+} regtmod_parse_data;
+#define REG(name, type, index, bits) \
+ { name, (((unsigned long)YASM_ARCH_REG) << 24) | \
+ (((unsigned long)bits) << 16) | (type | index) }
+#define REGGROUP(name, group) \
+ { name, (((unsigned long)YASM_ARCH_REGGROUP) << 24) | (group) }
+#define SEGREG(name, prefix, num, bits) \
+ { name, (((unsigned long)YASM_ARCH_SEGREG) << 24) | \
+ (((unsigned long)bits) << 16) | (prefix << 8) | (num) }
+#define TARGETMOD(name, mod) \
+ { name, (((unsigned long)YASM_ARCH_TARGETMOD) << 24) | (mod) }
+
+/* Pull in all parse data */
+#include "x86parse.c"
+
+yasm_arch_insnprefix
+yasm_x86__parse_check_insnprefix(yasm_arch *arch, unsigned long data[4],
+ const char *id, size_t id_len,
+ unsigned long line)
{
yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
- const char *oid = id;
- /*!re2c
- /* operand size overrides */
- 'o16' | 'data16' | 'word' {
- if (oid[0] != 'o' && arch_x86->parser != X86_PARSER_GAS)
- return 0;
- data[0] = X86_OPERSIZE;
- data[1] = 16;
- return 1;
- }
- 'o32' | 'data32' | 'dword' {
- if (oid[0] != 'o' && arch_x86->parser != X86_PARSER_GAS)
- return 0;
- if (arch_x86->mode_bits == 64) {
- yasm__error(line,
- N_("Cannot override data size to 32 bits in 64-bit mode"));
- return 0;
- }
- data[0] = X86_OPERSIZE;
- data[1] = 32;
- return 1;
- }
- 'o64' | 'data64' | 'qword' {
- if (oid[0] != 'o' && arch_x86->parser != X86_PARSER_GAS)
- return 0;
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a prefix in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_OPERSIZE;
- data[1] = 64;
- return 1;
- }
- /* address size overrides */
- 'a16' | 'addr16' | 'aword' {
- if (oid[1] != '1' && arch_x86->parser != X86_PARSER_GAS)
- return 0;
- if (arch_x86->mode_bits == 64) {
- yasm__error(line,
- N_("Cannot override address size to 16 bits in 64-bit mode"));
- return 0;
- }
- data[0] = X86_ADDRSIZE;
- data[1] = 16;
- return 1;
- }
- 'a32' | 'addr32' | 'adword' {
- if (oid[1] != '3' && arch_x86->parser != X86_PARSER_GAS)
- return 0;
- data[0] = X86_ADDRSIZE;
- data[1] = 32;
- return 1;
- }
- 'a64' | 'addr64' | 'aqword' {
- if (oid[1] != '6' && arch_x86->parser != X86_PARSER_GAS)
- return 0;
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a prefix in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_ADDRSIZE;
- data[1] = 64;
- return 1;
- }
-
- /* instruction prefixes */
- 'lock' {
- data[0] = X86_LOCKREP;
- data[1] = 0xF0;
- return 1;
- }
- 'repn' ('e' | 'z') {
- data[0] = X86_LOCKREP;
- data[1] = 0xF2;
- return 1;
- }
- 'rep' ('e' | 'z')? {
- data[0] = X86_LOCKREP;
- data[1] = 0xF3;
- return 1;
- }
+ /*@null@*/ const insnprefix_parse_data *pdata;
+ size_t i;
+ static char lcaseid[16];
+
+ if (id_len > 15)
+ return YASM_ARCH_NOTINSNPREFIX;
+ for (i=0; i<id_len; i++)
+ lcaseid[i] = tolower(id[i]);
+ lcaseid[id_len] = '\0';
+
+ switch (arch_x86->parser) {
+ case X86_PARSER_NASM:
+ pdata = insnprefix_nasm_find(lcaseid, id_len);
+ break;
+ case X86_PARSER_GAS:
+ pdata = insnprefix_gas_find(lcaseid, id_len);
+ break;
+ default:
+ pdata = NULL;
+ }
+ if (!pdata)
+ return YASM_ARCH_NOTINSNPREFIX;
- /* other prefixes (limited to GAS-only at the moment) */
- /* Hint taken/not taken (for jumps */
- 'ht' {
- if (arch_x86->parser != X86_PARSER_GAS)
- return 0;
- data[0] = X86_SEGREG;
- data[1] = 0x3E;
- return 1;
- }
- 'hnt' {
- if (arch_x86->parser != X86_PARSER_GAS)
- return 0;
- data[0] = X86_SEGREG;
- data[1] = 0x2E;
- return 1;
- }
- /* REX byte explicit prefixes */
- 'rex' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x40;
- return 1;
- }
- 'rexz' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x41;
- return 1;
- }
- 'rexy' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x42;
- return 1;
- }
- 'rexyz' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x43;
- return 1;
- }
- 'rexx' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x44;
- return 1;
- }
- 'rexxz' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x45;
- return 1;
- }
- 'rexxy' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x46;
- return 1;
- }
- 'rexxyz' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x47;
- return 1;
- }
- 'rex64' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x48;
- return 1;
- }
- 'rex64z' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x49;
- return 1;
- }
- 'rex64y' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x4a;
- return 1;
- }
- 'rex64yz' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x4b;
- return 1;
- }
- 'rex64x' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x4c;
- return 1;
- }
- 'rex64xz' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x4d;
- return 1;
- }
- 'rex64xy' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x4e;
- return 1;
- }
- 'rex64xyz' {
- if (arch_x86->parser != X86_PARSER_GAS
- || arch_x86->mode_bits != 64)
- return 0;
- data[0] = X86_REX;
- data[1] = 0x4f;
- return 1;
- }
+ if (pdata->group) {
+ unsigned long cpu = pdata->data2;
- /* catchalls */
- [\001-\377]+ {
- return 0;
- }
- [\000] {
- return 0;
+ if ((cpu & CPU_64) && arch_x86->mode_bits != 64) {
+ yasm__warning(YASM_WARN_GENERAL, line,
+ N_("`%s' is an instruction in 64-bit mode"), id);
+ return YASM_ARCH_NOTINSNPREFIX;
+ }
+ if ((cpu & CPU_Not64) && arch_x86->mode_bits == 64) {
+ yasm__error(line, N_("`%s' invalid in 64-bit mode"), id);
+ data[0] = (unsigned long)not64_insn;
+ data[1] = NELEMS(not64_insn);
+ data[2] = CPU_Not64;
+ data[3] = arch_x86->mode_bits;
+ return YASM_ARCH_INSN;
+ }
+
+ data[0] = (unsigned long)pdata->group;
+ data[1] = pdata->data1;
+ data[2] = cpu;
+ data[3] = (((unsigned long)pdata->flags)<<8) | arch_x86->mode_bits;
+ return YASM_ARCH_INSN;
+ } else {
+ unsigned long type = pdata->data1;
+ unsigned long value = pdata->data2;
+
+ if (arch_x86->mode_bits == 64 && type == X86_OPERSIZE && value == 32) {
+ yasm__error(line,
+ N_("Cannot override data size to 32 bits in 64-bit mode"));
+ return YASM_ARCH_NOTINSNPREFIX;
+ }
+
+ if (arch_x86->mode_bits == 64 && type == X86_ADDRSIZE && value == 16) {
+ yasm__error(line,
+ N_("Cannot override address size to 16 bits in 64-bit mode"));
+ return YASM_ARCH_NOTINSNPREFIX;
+ }
+
+ if ((type == X86_REX ||
+ (value == 64 && (type == X86_OPERSIZE || type == X86_ADDRSIZE)))
+ && arch_x86->mode_bits != 64) {
+ yasm__warning(YASM_WARN_GENERAL, line,
+ N_("`%s' is a prefix in 64-bit mode"), id);
+ return YASM_ARCH_NOTINSNPREFIX;
}
- */
- return 0;
+ data[0] = type;
+ data[1] = value;
+ return YASM_ARCH_PREFIX;
+ }
}
-int
-yasm_x86__parse_check_reg(yasm_arch *arch, unsigned long data[1],
- const char *id, unsigned long line)
+void
+yasm_x86__parse_cpu(yasm_arch *arch, const char *cpuid, size_t cpuid_len,
+ unsigned long line)
{
yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
- const char *oid = id;
- /*!re2c
- /* control, debug, and test registers */
- 'cr' [02-48] {
- if (arch_x86->mode_bits != 64 && oid[2] == '8') {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_CRREG | (oid[2]-'0');
- return 1;
- }
- 'dr' [0-7] {
- data[0] = X86_DRREG | (oid[2]-'0');
- return 1;
- }
- 'tr' [0-7] {
- data[0] = X86_TRREG | (oid[2]-'0');
- return 1;
- }
-
- /* floating point, MMX, and SSE/SSE2 registers */
- 'st' [0-7] {
- data[0] = X86_FPUREG | (oid[2]-'0');
- return 1;
- }
- 'mm' [0-7] {
- data[0] = X86_MMXREG | (oid[2]-'0');
- return 1;
- }
- 'xmm' [0-9] {
- if (arch_x86->mode_bits != 64 &&
- (oid[3] == '8' || oid[3] == '9')) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_XMMREG | (oid[3]-'0');
- return 1;
- }
- 'xmm' "1" [0-5] {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_XMMREG | (10+oid[4]-'0');
- return 1;
- }
-
- /* integer registers */
- 'rax' {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG64 | 0;
- return 1;
- }
- 'rcx' {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG64 | 1;
- return 1;
- }
- 'rdx' {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG64 | 2;
- return 1;
- }
- 'rbx' {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG64 | 3;
- return 1;
- }
- 'rsp' {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG64 | 4;
- return 1;
- }
- 'rbp' {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG64 | 5;
- return 1;
- }
- 'rsi' {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG64 | 6;
- return 1;
- }
- 'rdi' {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG64 | 7;
- return 1;
- }
- R [8-9] {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG64 | (oid[1]-'0');
- return 1;
- }
- 'r1' [0-5] {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG64 | (10+oid[2]-'0');
- return 1;
- }
-
- 'eax' { data[0] = X86_REG32 | 0; return 1; }
- 'ecx' { data[0] = X86_REG32 | 1; return 1; }
- 'edx' { data[0] = X86_REG32 | 2; return 1; }
- 'ebx' { data[0] = X86_REG32 | 3; return 1; }
- 'esp' { data[0] = X86_REG32 | 4; return 1; }
- 'ebp' { data[0] = X86_REG32 | 5; return 1; }
- 'esi' { data[0] = X86_REG32 | 6; return 1; }
- 'edi' { data[0] = X86_REG32 | 7; return 1; }
- R [8-9] D {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG32 | (oid[1]-'0');
- return 1;
- }
- R "1" [0-5] D {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG32 | (10+oid[2]-'0');
- return 1;
- }
-
- 'ax' { data[0] = X86_REG16 | 0; return 1; }
- 'cx' { data[0] = X86_REG16 | 1; return 1; }
- 'dx' { data[0] = X86_REG16 | 2; return 1; }
- 'bx' { data[0] = X86_REG16 | 3; return 1; }
- 'sp' { data[0] = X86_REG16 | 4; return 1; }
- 'bp' { data[0] = X86_REG16 | 5; return 1; }
- 'si' { data[0] = X86_REG16 | 6; return 1; }
- 'di' { data[0] = X86_REG16 | 7; return 1; }
- R [8-9] W {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG16 | (oid[1]-'0');
- return 1;
- }
- R "1" [0-5] W {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG16 | (10+oid[2]-'0');
- return 1;
- }
-
- 'al' { data[0] = X86_REG8 | 0; return 1; }
- 'cl' { data[0] = X86_REG8 | 1; return 1; }
- 'dl' { data[0] = X86_REG8 | 2; return 1; }
- 'bl' { data[0] = X86_REG8 | 3; return 1; }
- 'ah' { data[0] = X86_REG8 | 4; return 1; }
- 'ch' { data[0] = X86_REG8 | 5; return 1; }
- 'dh' { data[0] = X86_REG8 | 6; return 1; }
- 'bh' { data[0] = X86_REG8 | 7; return 1; }
- 'spl' {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG8X | 4;
- return 1;
- }
- 'bpl' {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG8X | 5;
- return 1;
- }
- 'sil' {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG8X | 6;
- return 1;
- }
- 'dil' {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG8X | 7;
- return 1;
- }
- R [8-9] B {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG8 | (oid[1]-'0');
- return 1;
- }
- R "1" [0-5] B {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_REG8 | (10+oid[2]-'0');
- return 1;
- }
-
- /* RIP for 64-bit mode IP-relative offsets */
- 'rip' {
- if (arch_x86->mode_bits != 64) {
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is a register in 64-bit mode"), oid);
- return 0;
- }
- data[0] = X86_RIP;
- return 1;
- }
-
- /* catchalls */
- [\001-\377]+ {
- return 0;
- }
- [\000] {
- return 0;
- }
- */
- return 0;
-}
-
-int
-yasm_x86__parse_check_reggroup(yasm_arch *arch, unsigned long data[1],
- const char *id, unsigned long line)
-{
- /*const char *oid = id;*/
- /*!re2c
- /* floating point, MMX, and SSE/SSE2 registers */
- 'st' {
- data[0] = X86_FPUREG;
- return 1;
- }
- 'mm' {
- data[0] = X86_MMXREG;
- return 1;
- }
- 'xmm' {
- data[0] = X86_XMMREG;
- return 1;
- }
+ /*@null@*/ const cpu_parse_data *pdata;
+ size_t i;
+ static char lcaseid[16];
- /* catchalls */
- [\001-\377]+ {
- return 0;
- }
- [\000] {
- return 0;
- }
- */
- return 0;
-}
+ if (cpuid_len > 15)
+ return;
+ for (i=0; i<cpuid_len; i++)
+ lcaseid[i] = tolower(cpuid[i]);
+ lcaseid[cpuid_len] = '\0';
-int
-yasm_x86__parse_check_segreg(yasm_arch *arch, unsigned long data[1],
- const char *id, unsigned long line)
-{
- yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
- const char *oid = id;
- /*!re2c
- /* segment registers */
- 'es' {
- if (arch_x86->mode_bits == 64)
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' segment register ignored in 64-bit mode"), oid);
- data[0] = 0x2600;
- return 1;
- }
- 'cs' { data[0] = 0x2e01; return 1; }
- 'ss' {
- if (arch_x86->mode_bits == 64)
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' segment register ignored in 64-bit mode"), oid);
- data[0] = 0x3602;
- return 1;
- }
- 'ds' {
- if (arch_x86->mode_bits == 64)
- yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' segment register ignored in 64-bit mode"), oid);
- data[0] = 0x3e03;
- return 1;
- }
- 'fs' { data[0] = 0x6404; return 1; }
- 'gs' { data[0] = 0x6505; return 1; }
+ pdata = cpu_find(lcaseid, cpuid_len);
+ if (!pdata) {
+ yasm__warning(YASM_WARN_GENERAL, line,
+ N_("unrecognized CPU identifier `%s'"), cpuid);
+ return;
+ }
- /* catchalls */
- [\001-\377]+ {
- return 0;
- }
- [\000] {
- return 0;
- }
- */
- return 0;
+ switch (pdata->mode) {
+ case CPU_MODE_VERBATIM:
+ arch_x86->cpu_enabled = pdata->cpu;
+ break;
+ case CPU_MODE_SET:
+ arch_x86->cpu_enabled |= pdata->cpu;
+ break;
+ case CPU_MODE_CLEAR:
+ arch_x86->cpu_enabled &= ~pdata->cpu;
+ break;
+ }
}
-#define RET_INSN(nosuffixsize, group, mod, cpu) do { \
- suffix = (id-oid) > nosuffixsize; \
- DEF_INSN_DATA(group, mod, cpu); \
- goto done; \
- } while (0)
-
-/* No suffix version of RET_INSN */
-#define RET_INSN_NS(group, mod, cpu) do { \
- DEF_INSN_DATA(group, mod, cpu); \
- goto done; \
- } while (0)
-
-#define RET_INSN_GAS(nosuffixsize, group, mod, cpu) do { \
- if (arch_x86->parser != X86_PARSER_GAS) \
- return 0; \
- RET_INSN(nosuffixsize, group, mod, cpu); \
- } while (0)
-
-#define RET_INSN_NONGAS(nosuffixsize, group, mod, cpu) do { \
- if (arch_x86->parser == X86_PARSER_GAS) \
- return 0; \
- RET_INSN(nosuffixsize, group, mod, cpu); \
- } while (0)
-
-int
-yasm_x86__parse_check_insn(yasm_arch *arch, unsigned long data[4],
- const char *id, unsigned long line)
+yasm_arch_regtmod
+yasm_x86__parse_check_regtmod(yasm_arch *arch, unsigned long *data,
+ const char *id, size_t id_len, unsigned long line)
{
yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
- const char *oid = id;
- /*const char *marker;*/
- int suffix = 0;
- int not64 = 0;
- int warn64 = 0;
- int suffix_ofs = -1;
- char suffix_over = '\0';
-
- data[3] = arch_x86->mode_bits;
-
- /*!re2c
- /* instructions */
-
- /* Move */
- 'mov' [bBwWlL]? { RET_INSN(3, mov, 0, CPU_Any); }
- 'movabs' [bBwWlLqQ]? { RET_INSN_GAS(6, movabs, 0, CPU_Hammer|CPU_64); }
- /* Move with sign/zero extend */
- 'movsb' [wWlL] { suffix_ofs = -2; RET_INSN_GAS(4, movszx, 0xBE, CPU_386); }
- 'movswl' { suffix_ofs = -2; RET_INSN_GAS(4, movszx, 0xBE, CPU_386); }
- 'movs' [bBwW] Q {
- suffix_ofs = -2;
- warn64 = 1;
- RET_INSN_GAS(4, movszx, 0xBE, CPU_Hammer|CPU_64);
- }
- 'movsx' [bBwW]? { RET_INSN(5, movszx, 0xBE, CPU_386); }
- 'movslq' {
- suffix_ofs = -2;
- warn64 = 1;
- RET_INSN_GAS(4, movsxd, 0, CPU_Hammer|CPU_64);
- }
- 'movsxd' {
- warn64 = 1;
- RET_INSN_NONGAS(6, movsxd, 0, CPU_Hammer|CPU_64);
- }
- 'movzb' [wWlL] { suffix_ofs = -2; RET_INSN_GAS(4, movszx, 0xB6, CPU_386); }
- 'movzwl' { suffix_ofs = -2; RET_INSN_GAS(4, movszx, 0xB6, CPU_386); }
- 'movz' [bBwW] Q {
- suffix_ofs = -2;
- warn64 = 1;
- RET_INSN_GAS(4, movszx, 0xB6, CPU_Hammer|CPU_64);
- }
- 'movzx' { RET_INSN_NS(movszx, 0xB6, CPU_386); }
- /* Push instructions */
- 'push' [wWlLqQ]? { RET_INSN(4, push, 0, CPU_Any); }
- 'pusha' {
- not64 = 1;
- RET_INSN_NS(onebyte, 0x0060, CPU_186);
- }
- 'pushad' {
- not64 = 1;
- RET_INSN_NONGAS(6, onebyte, 0x2060, CPU_386);
- }
- 'pushal' {
- not64 = 1;
- RET_INSN_GAS(6, onebyte, 0x2060, CPU_386);
- }
- 'pushaw' {
- not64 = 1;
- RET_INSN_NS(onebyte, 0x1060, CPU_186);
- }
- /* Pop instructions */
- 'pop' [wWlLqQ]? { RET_INSN(3, pop, 0, CPU_Any); }
- 'popa' {
- not64 = 1;
- RET_INSN_NS(onebyte, 0x0061, CPU_186);
- }
- 'popad' {
- not64 = 1;
- RET_INSN_NONGAS(5, onebyte, 0x2061, CPU_386);
- }
- 'popal' {
- not64 = 1;
- RET_INSN_GAS(5, onebyte, 0x2061, CPU_386);
- }
- 'popaw' {
- not64 = 1;
- RET_INSN_NS(onebyte, 0x1061, CPU_186);
- }
- /* Exchange */
- 'xchg' [bBwWlLqQ]? { RET_INSN(4, xchg, 0, CPU_Any); }
- /* In/out from ports */
- 'in' [bBwWlL]? { RET_INSN(2, in, 0, CPU_Any); }
- 'out' [bBwWlL]? { RET_INSN(3, out, 0, CPU_Any); }
- /* Load effective address */
- 'lea' [wWlLqQ]? { RET_INSN(3, lea, 0, CPU_Any); }
- /* Load segment registers from memory */
- 'lds' [wWlL]? {
- not64 = 1;
- RET_INSN(3, ldes, 0xC5, CPU_Any);
- }
- 'les' [wWlL]? {
- not64 = 1;
- RET_INSN(3, ldes, 0xC4, CPU_Any);
- }
- 'lfs' [wWlL]? { RET_INSN(3, lfgss, 0xB4, CPU_386); }
- 'lgs' [wWlL]? { RET_INSN(3, lfgss, 0xB5, CPU_386); }
- 'lss' [wWlL]? { RET_INSN(3, lfgss, 0xB2, CPU_386); }
- /* Flags register instructions */
- 'clc' { RET_INSN_NS(onebyte, 0x00F8, CPU_Any); }
- 'cld' { RET_INSN_NS(onebyte, 0x00FC, CPU_Any); }
- 'cli' { RET_INSN_NS(onebyte, 0x00FA, CPU_Any); }
- 'clts' { RET_INSN_NS(twobyte, 0x0F06, CPU_286|CPU_Priv); }
- 'cmc' { RET_INSN_NS(onebyte, 0x00F5, CPU_Any); }
- 'lahf' { RET_INSN_NS(onebyte, 0x009F, CPU_Any); }
- 'sahf' { RET_INSN_NS(onebyte, 0x009E, CPU_Any); }
- 'pushf' { RET_INSN_NS(onebyte, 0x009C, CPU_Any); }
- 'pushfd' { RET_INSN_NONGAS(6, onebyte, 0x209C, CPU_386); }
- 'pushfl' { RET_INSN_GAS(6, onebyte, 0x209C, CPU_386); }
- 'pushfw' { RET_INSN_NS(onebyte, 0x109C, CPU_Any); }
- 'pushfq' {
- warn64 = 1;
- RET_INSN_NS(onebyte, 0x409C, CPU_Hammer|CPU_64);
- }
- 'popf' { RET_INSN_NS(onebyte, 0x40009D, CPU_Any); }
- 'popfd' {
- not64 = 1;
- RET_INSN_NONGAS(5, onebyte, 0x00209D, CPU_386);
- }
- 'popfl' {
- not64 = 1;
- RET_INSN_GAS(5, onebyte, 0x00209D, CPU_386);
- }
- 'popfw' { RET_INSN_NS(onebyte, 0x40109D, CPU_Any); }
- 'popfq' {
- warn64 = 1;
- RET_INSN_NS(onebyte, 0x40409D, CPU_Hammer|CPU_64);
- }
- 'stc' { RET_INSN_NS(onebyte, 0x00F9, CPU_Any); }
- 'std' { RET_INSN_NS(onebyte, 0x00FD, CPU_Any); }
- 'sti' { RET_INSN_NS(onebyte, 0x00FB, CPU_Any); }
- /* Arithmetic */
- 'add' [bBwWlLqQ]? { RET_INSN(3, arith, 0x0000, CPU_Any); }
- 'inc' [bBwWlLqQ]? { RET_INSN(3, incdec, 0x0040, CPU_Any); }
- 'sub' [bBwWlLqQ]? { RET_INSN(3, arith, 0x0528, CPU_Any); }
- 'dec' [bBwWlLqQ]? { RET_INSN(3, incdec, 0x0148, CPU_Any); }
- 'sbb' [bBwWlLqQ]? { RET_INSN(3, arith, 0x0318, CPU_Any); }
- 'cmp' [bBwWlLqQ]? { RET_INSN(3, arith, 0x0738, CPU_Any); }
- 'test' [bBwWlLqQ]? { RET_INSN(4, test, 0, CPU_Any); }
- 'and' [bBwWlLqQ]? { RET_INSN(3, arith, 0x0420, CPU_Any); }
- 'or' [bBwWlLqQ]? { RET_INSN(2, arith, 0x0108, CPU_Any); }
- 'xor' [bBwWlLqQ]? { RET_INSN(3, arith, 0x0630, CPU_Any); }
- 'adc' [bBwWlLqQ]? { RET_INSN(3, arith, 0x0210, CPU_Any); }
- 'neg' [bBwWlLqQ]? { RET_INSN(3, f6, 0x03, CPU_Any); }
- 'not' [bBwWlLqQ]? { RET_INSN(3, f6, 0x02, CPU_Any); }
- 'aaa' {
- not64 = 1;
- RET_INSN_NS(onebyte, 0x0037, CPU_Any);
- }
- 'aas' {
- not64 = 1;
- RET_INSN_NS(onebyte, 0x003F, CPU_Any);
- }
- 'daa' {
- not64 = 1;
- RET_INSN_NS(onebyte, 0x0027, CPU_Any);
- }
- 'das' {
- not64 = 1;
- RET_INSN_NS(onebyte, 0x002F, CPU_Any);
- }
- 'aad' {
- not64 = 1;
- RET_INSN_NS(aadm, 0x01, CPU_Any);
- }
- 'aam' {
- not64 = 1;
- RET_INSN_NS(aadm, 0x00, CPU_Any);
- }
- /* Conversion instructions */
- 'cbw' { RET_INSN_NS(onebyte, 0x1098, CPU_Any); }
- 'cwde' { RET_INSN_NS(onebyte, 0x2098, CPU_386); }
- 'cdqe' {
- warn64 = 1;
- RET_INSN_NS(onebyte, 0x4098, CPU_Hammer|CPU_64);
- }
- 'cwd' { RET_INSN_NS(onebyte, 0x1099, CPU_Any); }
- 'cdq' { RET_INSN_NS(onebyte, 0x2099, CPU_386); }
- 'cqo' {
- warn64 = 1;
- RET_INSN_NS(onebyte, 0x4099, CPU_Hammer|CPU_64);
- }
- /* Conversion instructions - GAS / AT&T naming */
- 'cbtw' { RET_INSN_GAS(4, onebyte, 0x1098, CPU_Any); }
- 'cwtl' { RET_INSN_GAS(4, onebyte, 0x2098, CPU_386); }
- 'cltq' {
- warn64 = 1;
- RET_INSN_GAS(4, onebyte, 0x4098, CPU_Hammer|CPU_64);
- }
- 'cwtd' { RET_INSN_GAS(4, onebyte, 0x1099, CPU_Any); }
- 'cltd' { RET_INSN_GAS(4, onebyte, 0x2099, CPU_386); }
- 'cqto' {
- warn64 = 1;
- RET_INSN_GAS(4, onebyte, 0x4099, CPU_Hammer|CPU_64);
- }
- /* Multiplication and division */
- 'mul' [bBwWlLqQ]? { RET_INSN(3, f6, 0x04, CPU_Any); }
- 'imul' [bBwWlLqQ]? { RET_INSN(4, imul, 0, CPU_Any); }
- 'div' [bBwWlLqQ]? { RET_INSN(3, div, 0x06, CPU_Any); }
- 'idiv' [bBwWlLqQ]? { RET_INSN(4, div, 0x07, CPU_Any); }
- /* Shifts */
- 'rol' [bBwWlLqQ]? { RET_INSN(3, shift, 0x00, CPU_Any); }
- 'ror' [bBwWlLqQ]? { RET_INSN(3, shift, 0x01, CPU_Any); }
- 'rcl' [bBwWlLqQ]? { RET_INSN(3, shift, 0x02, CPU_Any); }
- 'rcr' [bBwWlLqQ]? { RET_INSN(3, shift, 0x03, CPU_Any); }
- 'sal' [bBwWlLqQ]? { RET_INSN(3, shift, 0x04, CPU_Any); }
- 'shl' [bBwWlLqQ]? { RET_INSN(3, shift, 0x04, CPU_Any); }
- 'shr' [bBwWlLqQ]? { RET_INSN(3, shift, 0x05, CPU_Any); }
- 'sar' [bBwWlLqQ]? { RET_INSN(3, shift, 0x07, CPU_Any); }
- 'shld' [wWlLqQ]? { RET_INSN(4, shlrd, 0xA4, CPU_386); }
- 'shrd' [wWlLqQ]? { RET_INSN(4, shlrd, 0xAC, CPU_386); }
- /* Control transfer instructions (unconditional) */
- 'call' { RET_INSN(4, call, 0, CPU_Any); }
- 'jmp' { RET_INSN(3, jmp, 0, CPU_Any); }
- 'ret' { RET_INSN(3, retnf, 0x00C2, CPU_Any); }
- 'retw' { RET_INSN_GAS(3, retnf, 0x10C2, CPU_Any); }
- 'retl' {
- not64 = 1;
- RET_INSN_GAS(3, retnf, 0x00C2, CPU_Any);
- }
- 'retq' {
- warn64 = 1;
- RET_INSN_GAS(3, retnf, 0x00C2, CPU_Hammer|CPU_64);
- }
- 'retn' { RET_INSN_NONGAS(4, retnf, 0x00C2, CPU_Any); }
- 'retf' { RET_INSN_NONGAS(4, retnf, 0x40CA, CPU_Any); }
- 'lretw' { RET_INSN_GAS(4, retnf, 0x10CA, CPU_Any); }
- 'lretl' { RET_INSN_GAS(4, retnf, 0x00CA, CPU_Any); }
- 'lretq' {
- warn64 = 1;
- RET_INSN_GAS(4, retnf, 0x40CA, CPU_Any);
- }
- 'enter' [wWlLqQ]? { RET_INSN(5, enter, 0, CPU_186); }
- 'leave' { RET_INSN_NS(onebyte, 0x4000C9, CPU_186); }
- 'leave' [wW] { RET_INSN_GAS(6, onebyte, 0x0010C9, CPU_186); }
- 'leave' [lLqQ] { RET_INSN_GAS(6, onebyte, 0x4000C9, CPU_186); }
- /* Conditional jumps */
- 'jo' { RET_INSN_NS(jcc, 0x00, CPU_Any); }
- 'jno' { RET_INSN_NS(jcc, 0x01, CPU_Any); }
- 'jb' { RET_INSN_NS(jcc, 0x02, CPU_Any); }
- 'jc' { RET_INSN_NS(jcc, 0x02, CPU_Any); }
- 'jnae' { RET_INSN_NS(jcc, 0x02, CPU_Any); }
- 'jnb' { RET_INSN_NS(jcc, 0x03, CPU_Any); }
- 'jnc' { RET_INSN_NS(jcc, 0x03, CPU_Any); }
- 'jae' { RET_INSN_NS(jcc, 0x03, CPU_Any); }
- 'je' { RET_INSN_NS(jcc, 0x04, CPU_Any); }
- 'jz' { RET_INSN_NS(jcc, 0x04, CPU_Any); }
- 'jne' { RET_INSN_NS(jcc, 0x05, CPU_Any); }
- 'jnz' { RET_INSN_NS(jcc, 0x05, CPU_Any); }
- 'jbe' { RET_INSN_NS(jcc, 0x06, CPU_Any); }
- 'jna' { RET_INSN_NS(jcc, 0x06, CPU_Any); }
- 'jnbe' { RET_INSN_NS(jcc, 0x07, CPU_Any); }
- 'ja' { RET_INSN_NS(jcc, 0x07, CPU_Any); }
- 'js' { RET_INSN_NS(jcc, 0x08, CPU_Any); }
- 'jns' { RET_INSN_NS(jcc, 0x09, CPU_Any); }
- 'jp' { RET_INSN_NS(jcc, 0x0A, CPU_Any); }
- 'jpe' { RET_INSN_NS(jcc, 0x0A, CPU_Any); }
- 'jnp' { RET_INSN_NS(jcc, 0x0B, CPU_Any); }
- 'jpo' { RET_INSN_NS(jcc, 0x0B, CPU_Any); }
- 'jl' { RET_INSN_NS(jcc, 0x0C, CPU_Any); }
- 'jnge' { RET_INSN_NS(jcc, 0x0C, CPU_Any); }
- 'jnl' { RET_INSN_NS(jcc, 0x0D, CPU_Any); }
- 'jge' { RET_INSN_NS(jcc, 0x0D, CPU_Any); }
- 'jle' { RET_INSN_NS(jcc, 0x0E, CPU_Any); }
- 'jng' { RET_INSN_NS(jcc, 0x0E, CPU_Any); }
- 'jnle' { RET_INSN_NS(jcc, 0x0F, CPU_Any); }
- 'jg' { RET_INSN_NS(jcc, 0x0F, CPU_Any); }
- 'jcxz' { RET_INSN_NS(jcxz, 16, CPU_Any); }
- 'jecxz' { RET_INSN_NS(jcxz, 32, CPU_386); }
- 'jrcxz' {
- warn64 = 1;
- RET_INSN_NS(jcxz, 64, CPU_Hammer|CPU_64);
- }
- /* Loop instructions */
- 'loop' { RET_INSN_NS(loop, 0x02, CPU_Any); }
- 'loopz' { RET_INSN_NS(loop, 0x01, CPU_Any); }
- 'loope' { RET_INSN_NS(loop, 0x01, CPU_Any); }
- 'loopnz' { RET_INSN_NS(loop, 0x00, CPU_Any); }
- 'loopne' { RET_INSN_NS(loop, 0x00, CPU_Any); }
- /* Set byte on flag instructions */
- 'seto' B? { RET_INSN(4, setcc, 0x00, CPU_386); }
- 'setno' B? { RET_INSN(5, setcc, 0x01, CPU_386); }
- 'setb' B? { RET_INSN(4, setcc, 0x02, CPU_386); }
- 'setc' B? { RET_INSN(4, setcc, 0x02, CPU_386); }
- 'setnae' B? { RET_INSN(6, setcc, 0x02, CPU_386); }
- 'setnb' B? { RET_INSN(5, setcc, 0x03, CPU_386); }
- 'setnc' B? { RET_INSN(5, setcc, 0x03, CPU_386); }
- 'setae' B? { RET_INSN(5, setcc, 0x03, CPU_386); }
- 'sete' B? { RET_INSN(4, setcc, 0x04, CPU_386); }
- 'setz' B? { RET_INSN(4, setcc, 0x04, CPU_386); }
- 'setne' B? { RET_INSN(5, setcc, 0x05, CPU_386); }
- 'setnz' B? { RET_INSN(5, setcc, 0x05, CPU_386); }
- 'setbe' B? { RET_INSN(5, setcc, 0x06, CPU_386); }
- 'setna' B? { RET_INSN(5, setcc, 0x06, CPU_386); }
- 'setnbe' B? { RET_INSN(6, setcc, 0x07, CPU_386); }
- 'seta' B? { RET_INSN(4, setcc, 0x07, CPU_386); }
- 'sets' B? { RET_INSN(4, setcc, 0x08, CPU_386); }
- 'setns' B? { RET_INSN(5, setcc, 0x09, CPU_386); }
- 'setp' B? { RET_INSN(4, setcc, 0x0A, CPU_386); }
- 'setpe' B? { RET_INSN(5, setcc, 0x0A, CPU_386); }
- 'setnp' B? { RET_INSN(5, setcc, 0x0B, CPU_386); }
- 'setpo' B? { RET_INSN(5, setcc, 0x0B, CPU_386); }
- 'setl' B? { RET_INSN(4, setcc, 0x0C, CPU_386); }
- 'setnge' B? { RET_INSN(6, setcc, 0x0C, CPU_386); }
- 'setnl' B? { RET_INSN(5, setcc, 0x0D, CPU_386); }
- 'setge' B? { RET_INSN(5, setcc, 0x0D, CPU_386); }
- 'setle' B? { RET_INSN(5, setcc, 0x0E, CPU_386); }
- 'setng' B? { RET_INSN(5, setcc, 0x0E, CPU_386); }
- 'setnle' B? { RET_INSN(6, setcc, 0x0F, CPU_386); }
- 'setg' B? { RET_INSN(4, setcc, 0x0F, CPU_386); }
- /* String instructions. */
- 'cmpsb' { RET_INSN_NS(onebyte, 0x00A6, CPU_Any); }
- 'cmpsw' { RET_INSN_NS(onebyte, 0x10A7, CPU_Any); }
- 'cmpsd' { RET_INSN_NS(cmpsd, 0, CPU_Any); }
- 'cmpsl' { RET_INSN_GAS(5, onebyte, 0x20A7, CPU_386); }
- 'cmpsq' {
- warn64 = 1;
- RET_INSN_NS(onebyte, 0x40A7, CPU_Hammer|CPU_64);
- }
- 'insb' { RET_INSN_NS(onebyte, 0x006C, CPU_Any); }
- 'insw' { RET_INSN_NS(onebyte, 0x106D, CPU_Any); }
- 'insd' { RET_INSN_NONGAS(4, onebyte, 0x206D, CPU_386); }
- 'insl' { RET_INSN_GAS(4, onebyte, 0x206D, CPU_386); }
- 'outsb' { RET_INSN_NS(onebyte, 0x006E, CPU_Any); }
- 'outsw' { RET_INSN_NS(onebyte, 0x106F, CPU_Any); }
- 'outsd' { RET_INSN_NONGAS(5, onebyte, 0x206F, CPU_386); }
- 'outsl' { RET_INSN_GAS(5, onebyte, 0x206F, CPU_386); }
- 'lodsb' { RET_INSN_NS(onebyte, 0x00AC, CPU_Any); }
- 'lodsw' { RET_INSN_NS(onebyte, 0x10AD, CPU_Any); }
- 'lodsd' { RET_INSN_NONGAS(5, onebyte, 0x20AD, CPU_386); }
- 'lodsl' { RET_INSN_GAS(5, onebyte, 0x20AD, CPU_386); }
- 'lodsq' {
- warn64 = 1;
- RET_INSN_NS(onebyte, 0x40AD, CPU_Hammer|CPU_64);
- }
- 'movsb' { RET_INSN_NS(onebyte, 0x00A4, CPU_Any); }
- 'movsw' { RET_INSN_NS(onebyte, 0x10A5, CPU_Any); }
- 'movsd' { RET_INSN_NS(movsd, 0, CPU_Any); }
- 'movsl' { RET_INSN_GAS(5, onebyte, 0x20A5, CPU_386); }
- 'movsq' {
- warn64 = 1;
- RET_INSN_NS(onebyte, 0x40A5, CPU_Any);
- }
- /* smov alias for movs in GAS mode */
- 'smovb' { RET_INSN_GAS(5, onebyte, 0x00A4, CPU_Any); }
- 'smovw' { RET_INSN_GAS(5, onebyte, 0x10A5, CPU_Any); }
- 'smovl' { RET_INSN_GAS(5, onebyte, 0x20A5, CPU_386); }
- 'smovq' {
- warn64 = 1;
- RET_INSN_GAS(5, onebyte, 0x40A5, CPU_Any);
- }
- 'scasb' { RET_INSN_NS(onebyte, 0x00AE, CPU_Any); }
- 'scasw' { RET_INSN_NS(onebyte, 0x10AF, CPU_Any); }
- 'scasd' { RET_INSN_NONGAS(5, onebyte, 0x20AF, CPU_386); }
- 'scasl' { RET_INSN_GAS(5, onebyte, 0x20AF, CPU_386); }
- 'scasq' {
- warn64 = 1;
- RET_INSN_NS(onebyte, 0x40AF, CPU_Hammer|CPU_64);
- }
- /* ssca alias for scas in GAS mode */
- 'sscab' { RET_INSN_GAS(5, onebyte, 0x00AE, CPU_Any); }
- 'sscaw' { RET_INSN_GAS(5, onebyte, 0x10AF, CPU_Any); }
- 'sscal' { RET_INSN_GAS(5, onebyte, 0x20AF, CPU_386); }
- 'sscaq' {
- warn64 = 1;
- RET_INSN_GAS(5, onebyte, 0x40AF, CPU_Hammer|CPU_64);
- }
- 'stosb' { RET_INSN_NS(onebyte, 0x00AA, CPU_Any); }
- 'stosw' { RET_INSN_NS(onebyte, 0x10AB, CPU_Any); }
- 'stosd' { RET_INSN_NONGAS(5, onebyte, 0x20AB, CPU_386); }
- 'stosl' { RET_INSN_GAS(5, onebyte, 0x20AB, CPU_386); }
- 'stosq' {
- warn64 = 1;
- RET_INSN_NS(onebyte, 0x40AB, CPU_Hammer|CPU_64);
- }
- 'xlat' B? { RET_INSN(5, onebyte, 0x00D7, CPU_Any); }
- /* Bit manipulation */
- 'bsf' [wWlLqQ]? { RET_INSN(3, bsfr, 0xBC, CPU_386); }
- 'bsr' [wWlLqQ]? { RET_INSN(3, bsfr, 0xBD, CPU_386); }
- 'bt' [wWlLqQ]? { RET_INSN(2, bittest, 0x04A3, CPU_386); }
- 'btc' [wWlLqQ]? { RET_INSN(3, bittest, 0x07BB, CPU_386); }
- 'btr' [wWlLqQ]? { RET_INSN(3, bittest, 0x06B3, CPU_386); }
- 'bts' [wWlLqQ]? { RET_INSN(3, bittest, 0x05AB, CPU_386); }
- /* Interrupts and operating system instructions */
- 'int' { RET_INSN_NS(int, 0, CPU_Any); }
- 'int3' { RET_INSN_NS(onebyte, 0x00CC, CPU_Any); }
- 'int03' { RET_INSN_NONGAS(5, onebyte, 0x00CC, CPU_Any); }
- 'into' {
- not64 = 1;
- RET_INSN_NS(onebyte, 0x00CE, CPU_Any);
- }
- 'iret' { RET_INSN_NS(onebyte, 0x00CF, CPU_Any); }
- 'iretw' { RET_INSN_NS(onebyte, 0x10CF, CPU_Any); }
- 'iretd' { RET_INSN_NONGAS(5, onebyte, 0x20CF, CPU_386); }
- 'iretl' { RET_INSN_GAS(5, onebyte, 0x20CF, CPU_386); }
- 'iretq' {
- warn64 = 1;
- RET_INSN_NS(onebyte, 0x40CF, CPU_Hammer|CPU_64);
- }
- 'rsm' { RET_INSN_NS(twobyte, 0x0FAA, CPU_586|CPU_SMM); }
- 'bound' [wWlL]? {
- not64 = 1;
- RET_INSN(5, bound, 0, CPU_186);
- }
- 'hlt' { RET_INSN_NS(onebyte, 0x00F4, CPU_Priv); }
- 'nop' { RET_INSN_NS(onebyte, 0x0090, CPU_Any); }
- /* Protection control */
- 'arpl' W? {
- not64 = 1;
- RET_INSN(4, arpl, 0, CPU_286|CPU_Prot);
- }
- 'lar' [wWlLqQ]? { RET_INSN(3, bsfr, 0x02, CPU_286|CPU_Prot); }
- 'lgdt' [wWlLqQ]? { RET_INSN(4, twobytemem, 0x020F01, CPU_286|CPU_Priv); }
- 'lidt' [wWlLqQ]? { RET_INSN(4, twobytemem, 0x030F01, CPU_286|CPU_Priv); }
- 'lldt' W? { RET_INSN(4, prot286, 0x0200, CPU_286|CPU_Prot|CPU_Priv); }
- 'lmsw' W? { RET_INSN(4, prot286, 0x0601, CPU_286|CPU_Priv); }
- 'lsl' [wWlLqQ]? { RET_INSN(3, bsfr, 0x03, CPU_286|CPU_Prot); }
- 'ltr' W? { RET_INSN(3, prot286, 0x0300, CPU_286|CPU_Prot|CPU_Priv); }
- 'sgdt' [wWlLqQ]? { RET_INSN(4, twobytemem, 0x000F01, CPU_286|CPU_Priv); }
- 'sidt' [wWlLqQ]? { RET_INSN(4, twobytemem, 0x010F01, CPU_286|CPU_Priv); }
- 'sldt' [wWlLqQ]? { RET_INSN(4, sldtmsw, 0x0000, CPU_286); }
- 'smsw' [wWlLqQ]? { RET_INSN(4, sldtmsw, 0x0401, CPU_286); }
- 'str' [wWlLqQ]? { RET_INSN(3, str, 0, CPU_286|CPU_Prot); }
- 'verr' W? { RET_INSN(4, prot286, 0x0400, CPU_286|CPU_Prot); }
- 'verw' W? { RET_INSN(4, prot286, 0x0500, CPU_286|CPU_Prot); }
- /* Floating point instructions */
- 'fld' [lLsS]? { RET_INSN(3, fld, 0, CPU_FPU); }
- 'fldt' {
- data[3] |= 0x80 << 8;
- RET_INSN_GAS(4, fldstpt, 0x05, CPU_FPU);
- }
- 'fild' [lLqQsS]? { RET_INSN(4, fildstp, 0x050200, CPU_FPU); }
- 'fildll' { RET_INSN_GAS(6, fbldstp, 0x05, CPU_FPU); }
- 'fbld' { RET_INSN(4, fbldstp, 0x04, CPU_FPU); }
- 'fst' [lLsS]? { RET_INSN(3, fst, 0, CPU_FPU); }
- 'fist' [lLsS]? { RET_INSN(4, fiarith, 0x02DB, CPU_FPU); }
- 'fstp' [lLsS]? { RET_INSN(4, fstp, 0, CPU_FPU); }
- 'fstpt' {
- data[3] |= 0x80 << 8;
- RET_INSN_GAS(5, fldstpt, 0x07, CPU_FPU);
- }
- 'fistp' [lLqQsS]? { RET_INSN(5, fildstp, 0x070203, CPU_FPU); }
- 'fistpll' { RET_INSN_GAS(7, fbldstp, 0x07, CPU_FPU); }
- 'fbstp' { RET_INSN_NS(fbldstp, 0x06, CPU_FPU); }
- 'fxch' { RET_INSN_NS(fxch, 0, CPU_FPU); }
- 'fcom' [lLsS]? { RET_INSN(4, fcom, 0x02D0, CPU_FPU); }
- 'ficom' [lLsS]? { RET_INSN(5, fiarith, 0x02DA, CPU_FPU); }
- 'fcomp' [lLsS]? { RET_INSN(5, fcom, 0x03D8, CPU_FPU); }
- 'ficomp' [lLsS]? { RET_INSN(6, fiarith, 0x03DA, CPU_FPU); }
- 'fcompp' { RET_INSN_NS(twobyte, 0xDED9, CPU_FPU); }
- 'fucom' { RET_INSN_NS(fcom2, 0xDDE0, CPU_286|CPU_FPU); }
- 'fucomp' { RET_INSN_NS(fcom2, 0xDDE8, CPU_286|CPU_FPU); }
- 'fucompp' { RET_INSN_NS(twobyte, 0xDAE9, CPU_286|CPU_FPU); }
- 'ftst' { RET_INSN_NS(twobyte, 0xD9E4, CPU_FPU); }
- 'fxam' { RET_INSN_NS(twobyte, 0xD9E5, CPU_FPU); }
- 'fld1' { RET_INSN_NS(twobyte, 0xD9E8, CPU_FPU); }
- 'fldl2t' { RET_INSN_NS(twobyte, 0xD9E9, CPU_FPU); }
- 'fldl2e' { RET_INSN_NS(twobyte, 0xD9EA, CPU_FPU); }
- 'fldpi' { RET_INSN_NS(twobyte, 0xD9EB, CPU_FPU); }
- 'fldlg2' { RET_INSN_NS(twobyte, 0xD9EC, CPU_FPU); }
- 'fldln2' { RET_INSN_NS(twobyte, 0xD9ED, CPU_FPU); }
- 'fldz' { RET_INSN_NS(twobyte, 0xD9EE, CPU_FPU); }
- 'fadd' [lLsS]? { RET_INSN(4, farith, 0x00C0C0, CPU_FPU); }
- 'faddp' { RET_INSN_NS(farithp, 0xC0, CPU_FPU); }
- 'fiadd' [lLsS]? { RET_INSN(5, fiarith, 0x00DA, CPU_FPU); }
- 'fsub' [lLsS]? { RET_INSN(4, farith, 0x04E0E8, CPU_FPU); }
- 'fisub' [lLsS]? { RET_INSN(5, fiarith, 0x04DA, CPU_FPU); }
- 'fsubp' { RET_INSN_NS(farithp, 0xE8, CPU_FPU); }
- 'fsubr' [lLsS]? { RET_INSN(5, farith, 0x05E8E0, CPU_FPU); }
- 'fisubr' [lLsS]? { RET_INSN(6, fiarith, 0x05DA, CPU_FPU); }
- 'fsubrp' { RET_INSN_NS(farithp, 0xE0, CPU_FPU); }
- 'fmul' [lLsS]? { RET_INSN(4, farith, 0x01C8C8, CPU_FPU); }
- 'fimul' [lLsS]? { RET_INSN(5, fiarith, 0x01DA, CPU_FPU); }
- 'fmulp' { RET_INSN_NS(farithp, 0xC8, CPU_FPU); }
- 'fdiv' [lLsS]? { RET_INSN(4, farith, 0x06F0F8, CPU_FPU); }
- 'fidiv' [lLsS]? { RET_INSN(5, fiarith, 0x06DA, CPU_FPU); }
- 'fdivp' { RET_INSN_NS(farithp, 0xF8, CPU_FPU); }
- 'fdivr' [lLsS]? { RET_INSN(5, farith, 0x07F8F0, CPU_FPU); }
- 'fidivr' [lLsS]? { RET_INSN(6, fiarith, 0x07DA, CPU_FPU); }
- 'fdivrp' { RET_INSN_NS(farithp, 0xF0, CPU_FPU); }
- 'f2xm1' { RET_INSN_NS(twobyte, 0xD9F0, CPU_FPU); }
- 'fyl2x' { RET_INSN_NS(twobyte, 0xD9F1, CPU_FPU); }
- 'fptan' { RET_INSN_NS(twobyte, 0xD9F2, CPU_FPU); }
- 'fpatan' { RET_INSN_NS(twobyte, 0xD9F3, CPU_FPU); }
- 'fxtract' { RET_INSN_NS(twobyte, 0xD9F4, CPU_FPU); }
- 'fprem1' { RET_INSN_NS(twobyte, 0xD9F5, CPU_286|CPU_FPU); }
- 'fdecstp' { RET_INSN_NS(twobyte, 0xD9F6, CPU_FPU); }
- 'fincstp' { RET_INSN_NS(twobyte, 0xD9F7, CPU_FPU); }
- 'fprem' { RET_INSN_NS(twobyte, 0xD9F8, CPU_FPU); }
- 'fyl2xp1' { RET_INSN_NS(twobyte, 0xD9F9, CPU_FPU); }
- 'fsqrt' { RET_INSN_NS(twobyte, 0xD9FA, CPU_FPU); }
- 'fsincos' { RET_INSN_NS(twobyte, 0xD9FB, CPU_286|CPU_FPU); }
- 'frndint' { RET_INSN_NS(twobyte, 0xD9FC, CPU_FPU); }
- 'fscale' { RET_INSN_NS(twobyte, 0xD9FD, CPU_FPU); }
- 'fsin' { RET_INSN_NS(twobyte, 0xD9FE, CPU_286|CPU_FPU); }
- 'fcos' { RET_INSN_NS(twobyte, 0xD9FF, CPU_286|CPU_FPU); }
- 'fchs' { RET_INSN_NS(twobyte, 0xD9E0, CPU_FPU); }
- 'fabs' { RET_INSN_NS(twobyte, 0xD9E1, CPU_FPU); }
- 'fninit' { RET_INSN_NS(twobyte, 0xDBE3, CPU_FPU); }
- 'finit' { RET_INSN_NS(threebyte, 0x9BDBE3UL, CPU_FPU); }
- 'fldcw' W? { RET_INSN(5, fldnstcw, 0x05, CPU_FPU); }
- 'fnstcw' W? { RET_INSN(6, fldnstcw, 0x07, CPU_FPU); }
- 'fstcw' W? { RET_INSN(5, fstcw, 0, CPU_FPU); }
- 'fnstsw' W? { RET_INSN(6, fnstsw, 0, CPU_FPU); }
- 'fstsw' W? { RET_INSN(5, fstsw, 0, CPU_FPU); }
- 'fnclex' { RET_INSN_NS(twobyte, 0xDBE2, CPU_FPU); }
- 'fclex' { RET_INSN_NS(threebyte, 0x9BDBE2UL, CPU_FPU); }
- 'fnstenv' [lLsS]? { RET_INSN(7, onebytemem, 0x06D9, CPU_FPU); }
- 'fstenv' [lLsS]? { RET_INSN(6, twobytemem, 0x069BD9, CPU_FPU); }
- 'fldenv' [lLsS]? { RET_INSN(6, onebytemem, 0x04D9, CPU_FPU); }
- 'fnsave' [lLsS]? { RET_INSN(6, onebytemem, 0x06DD, CPU_FPU); }
- 'fsave' [lLsS]? { RET_INSN(5, twobytemem, 0x069BDD, CPU_FPU); }
- 'frstor' [lLsS]? { RET_INSN(6, onebytemem, 0x04DD, CPU_FPU); }
- 'ffree' { RET_INSN_NS(ffree, 0xDD, CPU_FPU); }
- 'ffreep' { RET_INSN_NS(ffree, 0xDF, CPU_686|CPU_FPU|CPU_Undoc); }
- 'fnop' { RET_INSN_NS(twobyte, 0xD9D0, CPU_FPU); }
- 'fwait' { RET_INSN_NS(onebyte, 0x009B, CPU_FPU); }
- /* Prefixes (should the others be here too? should wait be a prefix? */
- 'wait' { RET_INSN_NS(onebyte, 0x009B, CPU_Any); }
- /* 486 extensions */
- 'bswap' [lLqQ]? { RET_INSN(5, bswap, 0, CPU_486); }
- 'xadd' [bBwWlLqQ]? { RET_INSN(4, cmpxchgxadd, 0xC0, CPU_486); }
- 'cmpxchg' [bBwWlLqQ]? { RET_INSN(7, cmpxchgxadd, 0xB0, CPU_486); }
- 'cmpxchg486' { RET_INSN_NONGAS(10, cmpxchgxadd, 0xA6, CPU_486|CPU_Undoc); }
- 'invd' { RET_INSN_NS(twobyte, 0x0F08, CPU_486|CPU_Priv); }
- 'wbinvd' { RET_INSN_NS(twobyte, 0x0F09, CPU_486|CPU_Priv); }
- 'invlpg' { RET_INSN_NS(twobytemem, 0x070F01, CPU_486|CPU_Priv); }
- /* 586+ and late 486 extensions */
- 'cpuid' { RET_INSN_NS(twobyte, 0x0FA2, CPU_486); }
- /* Pentium extensions */
- 'wrmsr' { RET_INSN_NS(twobyte, 0x0F30, CPU_586|CPU_Priv); }
- 'rdtsc' { RET_INSN_NS(twobyte, 0x0F31, CPU_586); }
- 'rdmsr' { RET_INSN_NS(twobyte, 0x0F32, CPU_586|CPU_Priv); }
- 'cmpxchg8b' Q? { RET_INSN(9, cmpxchg8b, 0, CPU_586); }
- /* Pentium II/Pentium Pro extensions */
- 'sysenter' {
- not64 = 1;
- RET_INSN_NS(twobyte, 0x0F34, CPU_686);
- }
- 'sysexit' {
- not64 = 1;
- RET_INSN_NS(twobyte, 0x0F35, CPU_686|CPU_Priv);
- }
- 'fxsave' Q? { RET_INSN(6, twobytemem, 0x000FAE, CPU_686|CPU_FPU); }
- 'fxrstor' Q? { RET_INSN(7, twobytemem, 0x010FAE, CPU_686|CPU_FPU); }
- 'rdpmc' { RET_INSN_NS(twobyte, 0x0F33, CPU_686); }
- 'ud2' { RET_INSN_NS(twobyte, 0x0F0B, CPU_286); }
- 'ud1' { RET_INSN_NS(twobyte, 0x0FB9, CPU_286|CPU_Undoc); }
- 'cmovo' [wWlLqQ]? { RET_INSN(5, cmovcc, 0x00, CPU_686); }
- 'cmovno' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x01, CPU_686); }
- 'cmovb' [wWlLqQ]? { RET_INSN(5, cmovcc, 0x02, CPU_686); }
- 'cmovc' [wWlLqQ]? { RET_INSN(5, cmovcc, 0x02, CPU_686); }
- 'cmovnae' [wWlLqQ]? { RET_INSN(7, cmovcc, 0x02, CPU_686); }
- 'cmovnb' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x03, CPU_686); }
- 'cmovnc' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x03, CPU_686); }
- 'cmovae' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x03, CPU_686); }
- 'cmove' [wWlLqQ]? { RET_INSN(5, cmovcc, 0x04, CPU_686); }
- 'cmovz' [wWlLqQ]? { RET_INSN(5, cmovcc, 0x04, CPU_686); }
- 'cmovne' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x05, CPU_686); }
- 'cmovnz' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x05, CPU_686); }
- 'cmovbe' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x06, CPU_686); }
- 'cmovna' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x06, CPU_686); }
- 'cmovnbe' [wWlLqQ]? { RET_INSN(7, cmovcc, 0x07, CPU_686); }
- 'cmova' [wWlLqQ]? { RET_INSN(5, cmovcc, 0x07, CPU_686); }
- 'cmovs' [wWlLqQ]? { RET_INSN(5, cmovcc, 0x08, CPU_686); }
- 'cmovns' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x09, CPU_686); }
- 'cmovp' [wWlLqQ]? { RET_INSN(5, cmovcc, 0x0A, CPU_686); }
- 'cmovpe' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x0A, CPU_686); }
- 'cmovnp' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x0B, CPU_686); }
- 'cmovpo' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x0B, CPU_686); }
- 'cmovl' [wWlLqQ]? { RET_INSN(5, cmovcc, 0x0C, CPU_686); }
- 'cmovnge' [wWlLqQ]? { RET_INSN(7, cmovcc, 0x0C, CPU_686); }
- 'cmovnl' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x0D, CPU_686); }
- 'cmovge' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x0D, CPU_686); }
- 'cmovle' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x0E, CPU_686); }
- 'cmovng' [wWlLqQ]? { RET_INSN(6, cmovcc, 0x0E, CPU_686); }
- 'cmovnle' [wWlLqQ]? { RET_INSN(7, cmovcc, 0x0F, CPU_686); }
- 'cmovg' [wWlLqQ]? { RET_INSN(5, cmovcc, 0x0F, CPU_686); }
- 'fcmovb' { RET_INSN_NS(fcmovcc, 0xDAC0, CPU_686|CPU_FPU); }
- 'fcmove' { RET_INSN_NS(fcmovcc, 0xDAC8, CPU_686|CPU_FPU); }
- 'fcmovbe' { RET_INSN_NS(fcmovcc, 0xDAD0, CPU_686|CPU_FPU); }
- 'fcmovu' { RET_INSN_NS(fcmovcc, 0xDAD8, CPU_686|CPU_FPU); }
- 'fcmovnb' { RET_INSN_NS(fcmovcc, 0xDBC0, CPU_686|CPU_FPU); }
- 'fcmovne' { RET_INSN_NS(fcmovcc, 0xDBC8, CPU_686|CPU_FPU); }
- 'fcmovnbe' { RET_INSN_NS(fcmovcc, 0xDBD0, CPU_686|CPU_FPU); }
- 'fcmovnu' { RET_INSN_NS(fcmovcc, 0xDBD8, CPU_686|CPU_FPU); }
- 'fcomi' { RET_INSN_NS(fcom2, 0xDBF0, CPU_686|CPU_FPU); }
- 'fucomi' { RET_INSN_NS(fcom2, 0xDBE8, CPU_686|CPU_FPU); }
- 'fcomip' { RET_INSN_NS(fcom2, 0xDFF0, CPU_686|CPU_FPU); }
- 'fucomip' { RET_INSN_NS(fcom2, 0xDFE8, CPU_686|CPU_FPU); }
- /* Pentium4 extensions */
- 'movnti' [lLqQ]? { RET_INSN(6, movnti, 0, CPU_P4); }
- 'clflush' { RET_INSN_NS(clflush, 0, CPU_P3); }
- 'lfence' { RET_INSN_NS(threebyte, 0x0FAEE8, CPU_P3); }
- 'mfence' { RET_INSN_NS(threebyte, 0x0FAEF0, CPU_P3); }
- 'pause' { RET_INSN_NS(onebyte_prefix, 0xF390, CPU_P4); }
- /* MMX/SSE2 instructions */
- 'emms' { RET_INSN_NS(twobyte, 0x0F77, CPU_MMX); }
- 'movd' { RET_INSN_NS(movd, 0, CPU_MMX); }
- 'movq' {
- if (arch_x86->parser == X86_PARSER_GAS)
- RET_INSN(3, mov, 0, CPU_Any);
- else
- RET_INSN_NS(movq, 0, CPU_MMX);
- }
- 'packssdw' { RET_INSN_NS(mmxsse2, 0x6B, CPU_MMX); }
- 'packsswb' { RET_INSN_NS(mmxsse2, 0x63, CPU_MMX); }
- 'packuswb' { RET_INSN_NS(mmxsse2, 0x67, CPU_MMX); }
- 'paddb' { RET_INSN_NS(mmxsse2, 0xFC, CPU_MMX); }
- 'paddw' { RET_INSN_NS(mmxsse2, 0xFD, CPU_MMX); }
- 'paddd' { RET_INSN_NS(mmxsse2, 0xFE, CPU_MMX); }
- 'paddq' { RET_INSN_NS(mmxsse2, 0xD4, CPU_MMX); }
- 'paddsb' { RET_INSN_NS(mmxsse2, 0xEC, CPU_MMX); }
- 'paddsw' { RET_INSN_NS(mmxsse2, 0xED, CPU_MMX); }
- 'paddusb' { RET_INSN_NS(mmxsse2, 0xDC, CPU_MMX); }
- 'paddusw' { RET_INSN_NS(mmxsse2, 0xDD, CPU_MMX); }
- 'pand' { RET_INSN_NS(mmxsse2, 0xDB, CPU_MMX); }
- 'pandn' { RET_INSN_NS(mmxsse2, 0xDF, CPU_MMX); }
- 'pcmpeqb' { RET_INSN_NS(mmxsse2, 0x74, CPU_MMX); }
- 'pcmpeqw' { RET_INSN_NS(mmxsse2, 0x75, CPU_MMX); }
- 'pcmpeqd' { RET_INSN_NS(mmxsse2, 0x76, CPU_MMX); }
- 'pcmpgtb' { RET_INSN_NS(mmxsse2, 0x64, CPU_MMX); }
- 'pcmpgtw' { RET_INSN_NS(mmxsse2, 0x65, CPU_MMX); }
- 'pcmpgtd' { RET_INSN_NS(mmxsse2, 0x66, CPU_MMX); }
- 'pmaddwd' { RET_INSN_NS(mmxsse2, 0xF5, CPU_MMX); }
- 'pmulhw' { RET_INSN_NS(mmxsse2, 0xE5, CPU_MMX); }
- 'pmullw' { RET_INSN_NS(mmxsse2, 0xD5, CPU_MMX); }
- 'por' { RET_INSN_NS(mmxsse2, 0xEB, CPU_MMX); }
- 'psllw' { RET_INSN_NS(pshift, 0x0671F1, CPU_MMX); }
- 'pslld' { RET_INSN_NS(pshift, 0x0672F2, CPU_MMX); }
- 'psllq' { RET_INSN_NS(pshift, 0x0673F3, CPU_MMX); }
- 'psraw' { RET_INSN_NS(pshift, 0x0471E1, CPU_MMX); }
- 'psrad' { RET_INSN_NS(pshift, 0x0472E2, CPU_MMX); }
- 'psrlw' { RET_INSN_NS(pshift, 0x0271D1, CPU_MMX); }
- 'psrld' { RET_INSN_NS(pshift, 0x0272D2, CPU_MMX); }
- 'psrlq' { RET_INSN_NS(pshift, 0x0273D3, CPU_MMX); }
- 'psubb' { RET_INSN_NS(mmxsse2, 0xF8, CPU_MMX); }
- 'psubw' { RET_INSN_NS(mmxsse2, 0xF9, CPU_MMX); }
- 'psubd' { RET_INSN_NS(mmxsse2, 0xFA, CPU_MMX); }
- 'psubq' { RET_INSN_NS(mmxsse2, 0xFB, CPU_MMX); }
- 'psubsb' { RET_INSN_NS(mmxsse2, 0xE8, CPU_MMX); }
- 'psubsw' { RET_INSN_NS(mmxsse2, 0xE9, CPU_MMX); }
- 'psubusb' { RET_INSN_NS(mmxsse2, 0xD8, CPU_MMX); }
- 'psubusw' { RET_INSN_NS(mmxsse2, 0xD9, CPU_MMX); }
- 'punpckhbw' { RET_INSN_NS(mmxsse2, 0x68, CPU_MMX); }
- 'punpckhwd' { RET_INSN_NS(mmxsse2, 0x69, CPU_MMX); }
- 'punpckhdq' { RET_INSN_NS(mmxsse2, 0x6A, CPU_MMX); }
- 'punpcklbw' { RET_INSN_NS(mmxsse2, 0x60, CPU_MMX); }
- 'punpcklwd' { RET_INSN_NS(mmxsse2, 0x61, CPU_MMX); }
- 'punpckldq' { RET_INSN_NS(mmxsse2, 0x62, CPU_MMX); }
- 'pxor' { RET_INSN_NS(mmxsse2, 0xEF, CPU_MMX); }
- /* PIII (Katmai) new instructions / SIMD instructions */
- 'addps' { RET_INSN_NS(sseps, 0x58, CPU_SSE); }
- 'addss' { RET_INSN_NS(ssess, 0xF358, CPU_SSE); }
- 'andnps' { RET_INSN_NS(sseps, 0x55, CPU_SSE); }
- 'andps' { RET_INSN_NS(sseps, 0x54, CPU_SSE); }
- 'cmpeqps' { RET_INSN_NS(ssecmpps, 0x00, CPU_SSE); }
- 'cmpeqss' { RET_INSN_NS(ssecmpss, 0x00F3, CPU_SSE); }
- 'cmpleps' { RET_INSN_NS(ssecmpps, 0x02, CPU_SSE); }
- 'cmpless' { RET_INSN_NS(ssecmpss, 0x02F3, CPU_SSE); }
- 'cmpltps' { RET_INSN_NS(ssecmpps, 0x01, CPU_SSE); }
- 'cmpltss' { RET_INSN_NS(ssecmpss, 0x01F3, CPU_SSE); }
- 'cmpneqps' { RET_INSN_NS(ssecmpps, 0x04, CPU_SSE); }
- 'cmpneqss' { RET_INSN_NS(ssecmpss, 0x04F3, CPU_SSE); }
- 'cmpnleps' { RET_INSN_NS(ssecmpps, 0x06, CPU_SSE); }
- 'cmpnless' { RET_INSN_NS(ssecmpss, 0x06F3, CPU_SSE); }
- 'cmpnltps' { RET_INSN_NS(ssecmpps, 0x05, CPU_SSE); }
- 'cmpnltss' { RET_INSN_NS(ssecmpss, 0x05F3, CPU_SSE); }
- 'cmpordps' { RET_INSN_NS(ssecmpps, 0x07, CPU_SSE); }
- 'cmpordss' { RET_INSN_NS(ssecmpss, 0x07F3, CPU_SSE); }
- 'cmpunordps' { RET_INSN_NS(ssecmpps, 0x03, CPU_SSE); }
- 'cmpunordss' { RET_INSN_NS(ssecmpss, 0x03F3, CPU_SSE); }
- 'cmpps' { RET_INSN_NS(ssepsimm, 0xC2, CPU_SSE); }
- 'cmpss' { RET_INSN_NS(ssessimm, 0xF3C2, CPU_SSE); }
- 'comiss' { RET_INSN_NS(sseps, 0x2F, CPU_SSE); }
- 'cvtpi2ps' { RET_INSN_NS(cvt_xmm_mm_ps, 0x2A, CPU_SSE); }
- 'cvtps2pi' { RET_INSN_NS(cvt_mm_xmm64, 0x2D, CPU_SSE); }
- 'cvtsi2ss' [lLqQ]? { RET_INSN(8, cvt_xmm_rmx, 0xF32A, CPU_SSE); }
- 'cvtss2si' [lLqQ]? { RET_INSN(8, cvt_rx_xmm32, 0xF32D, CPU_SSE); }
- 'cvttps2pi' { RET_INSN_NS(cvt_mm_xmm64, 0x2C, CPU_SSE); }
- 'cvttss2si' [lLqQ]? { RET_INSN(9, cvt_rx_xmm32, 0xF32C, CPU_SSE); }
- 'divps' { RET_INSN_NS(sseps, 0x5E, CPU_SSE); }
- 'divss' { RET_INSN_NS(ssess, 0xF35E, CPU_SSE); }
- 'ldmxcsr' { RET_INSN_NS(ldstmxcsr, 0x02, CPU_SSE); }
- 'maskmovq' { RET_INSN_NS(maskmovq, 0, CPU_P3|CPU_MMX); }
- 'maxps' { RET_INSN_NS(sseps, 0x5F, CPU_SSE); }
- 'maxss' { RET_INSN_NS(ssess, 0xF35F, CPU_SSE); }
- 'minps' { RET_INSN_NS(sseps, 0x5D, CPU_SSE); }
- 'minss' { RET_INSN_NS(ssess, 0xF35D, CPU_SSE); }
- 'movaps' { RET_INSN_NS(movaups, 0x28, CPU_SSE); }
- 'movhlps' { RET_INSN_NS(movhllhps, 0x12, CPU_SSE); }
- 'movhps' { RET_INSN_NS(movhlps, 0x16, CPU_SSE); }
- 'movlhps' { RET_INSN_NS(movhllhps, 0x16, CPU_SSE); }
- 'movlps' { RET_INSN_NS(movhlps, 0x12, CPU_SSE); }
- 'movmskps' [lLqQ]? { RET_INSN(8, movmskps, 0, CPU_SSE); }
- 'movntps' { RET_INSN_NS(movntps, 0, CPU_SSE); }
- 'movntq' { RET_INSN_NS(movntq, 0, CPU_SSE); }
- 'movss' { RET_INSN_NS(movss, 0, CPU_SSE); }
- 'movups' { RET_INSN_NS(movaups, 0x10, CPU_SSE); }
- 'mulps' { RET_INSN_NS(sseps, 0x59, CPU_SSE); }
- 'mulss' { RET_INSN_NS(ssess, 0xF359, CPU_SSE); }
- 'orps' { RET_INSN_NS(sseps, 0x56, CPU_SSE); }
- 'pavgb' { RET_INSN_NS(mmxsse2, 0xE0, CPU_P3|CPU_MMX); }
- 'pavgw' { RET_INSN_NS(mmxsse2, 0xE3, CPU_P3|CPU_MMX); }
- 'pextrw' [lLqQ]? { RET_INSN(6, pextrw, 0, CPU_P3|CPU_MMX); }
- 'pinsrw' [lLqQ]? { RET_INSN(6, pinsrw, 0, CPU_P3|CPU_MMX); }
- 'pmaxsw' { RET_INSN_NS(mmxsse2, 0xEE, CPU_P3|CPU_MMX); }
- 'pmaxub' { RET_INSN_NS(mmxsse2, 0xDE, CPU_P3|CPU_MMX); }
- 'pminsw' { RET_INSN_NS(mmxsse2, 0xEA, CPU_P3|CPU_MMX); }
- 'pminub' { RET_INSN_NS(mmxsse2, 0xDA, CPU_P3|CPU_MMX); }
- 'pmovmskb' [lLqQ]? { RET_INSN(8, pmovmskb, 0, CPU_SSE); }
- 'pmulhuw' { RET_INSN_NS(mmxsse2, 0xE4, CPU_P3|CPU_MMX); }
- 'prefetchnta' { RET_INSN_NS(twobytemem, 0x000F18, CPU_P3); }
- 'prefetcht0' { RET_INSN_NS(twobytemem, 0x010F18, CPU_P3); }
- 'prefetcht1' { RET_INSN_NS(twobytemem, 0x020F18, CPU_P3); }
- 'prefetcht2' { RET_INSN_NS(twobytemem, 0x030F18, CPU_P3); }
- 'psadbw' { RET_INSN_NS(mmxsse2, 0xF6, CPU_P3|CPU_MMX); }
- 'pshufw' { RET_INSN_NS(pshufw, 0, CPU_P3|CPU_MMX); }
- 'rcpps' { RET_INSN_NS(sseps, 0x53, CPU_SSE); }
- 'rcpss' { RET_INSN_NS(ssess, 0xF353, CPU_SSE); }
- 'rsqrtps' { RET_INSN_NS(sseps, 0x52, CPU_SSE); }
- 'rsqrtss' { RET_INSN_NS(ssess, 0xF352, CPU_SSE); }
- 'sfence' { RET_INSN_NS(threebyte, 0x0FAEF8, CPU_P3); }
- 'shufps' { RET_INSN_NS(ssepsimm, 0xC6, CPU_SSE); }
- 'sqrtps' { RET_INSN_NS(sseps, 0x51, CPU_SSE); }
- 'sqrtss' { RET_INSN_NS(ssess, 0xF351, CPU_SSE); }
- 'stmxcsr' { RET_INSN_NS(ldstmxcsr, 0x03, CPU_SSE); }
- 'subps' { RET_INSN_NS(sseps, 0x5C, CPU_SSE); }
- 'subss' { RET_INSN_NS(ssess, 0xF35C, CPU_SSE); }
- 'ucomiss' { RET_INSN_NS(ssess, 0x2E, CPU_SSE); }
- 'unpckhps' { RET_INSN_NS(sseps, 0x15, CPU_SSE); }
- 'unpcklps' { RET_INSN_NS(sseps, 0x14, CPU_SSE); }
- 'xorps' { RET_INSN_NS(sseps, 0x57, CPU_SSE); }
- /* SSE2 instructions */
- 'addpd' { RET_INSN_NS(ssess, 0x6658, CPU_SSE2); }
- 'addsd' { RET_INSN_NS(ssess, 0xF258, CPU_SSE2); }
- 'andnpd' { RET_INSN_NS(ssess, 0x6655, CPU_SSE2); }
- 'andpd' { RET_INSN_NS(ssess, 0x6654, CPU_SSE2); }
- 'cmpeqpd' { RET_INSN_NS(ssecmpss, 0x0066, CPU_SSE2); }
- 'cmpeqsd' { RET_INSN_NS(ssecmpss, 0x00F2, CPU_SSE2); }
- 'cmplepd' { RET_INSN_NS(ssecmpss, 0x0266, CPU_SSE2); }
- 'cmplesd' { RET_INSN_NS(ssecmpss, 0x02F2, CPU_SSE2); }
- 'cmpltpd' { RET_INSN_NS(ssecmpss, 0x0166, CPU_SSE2); }
- 'cmpltsd' { RET_INSN_NS(ssecmpss, 0x01F2, CPU_SSE2); }
- 'cmpneqpd' { RET_INSN_NS(ssecmpss, 0x0466, CPU_SSE2); }
- 'cmpneqsd' { RET_INSN_NS(ssecmpss, 0x04F2, CPU_SSE2); }
- 'cmpnlepd' { RET_INSN_NS(ssecmpss, 0x0666, CPU_SSE2); }
- 'cmpnlesd' { RET_INSN_NS(ssecmpss, 0x06F2, CPU_SSE2); }
- 'cmpnltpd' { RET_INSN_NS(ssecmpss, 0x0566, CPU_SSE2); }
- 'cmpnltsd' { RET_INSN_NS(ssecmpss, 0x05F2, CPU_SSE2); }
- 'cmpordpd' { RET_INSN_NS(ssecmpss, 0x0766, CPU_SSE2); }
- 'cmpordsd' { RET_INSN_NS(ssecmpss, 0x07F2, CPU_SSE2); }
- 'cmpunordpd' { RET_INSN_NS(ssecmpss, 0x0366, CPU_SSE2); }
- 'cmpunordsd' { RET_INSN_NS(ssecmpss, 0x03F2, CPU_SSE2); }
- 'cmppd' { RET_INSN_NS(ssessimm, 0x66C2, CPU_SSE2); }
- /* C M P S D is in string instructions above */
- 'comisd' { RET_INSN_NS(ssess, 0x662F, CPU_SSE2); }
- 'cvtpi2pd' { RET_INSN_NS(cvt_xmm_mm_ss, 0x662A, CPU_SSE2); }
- 'cvtsi2sd' [lLqQ]? { RET_INSN(8, cvt_xmm_rmx, 0xF22A, CPU_SSE2); }
- 'divpd' { RET_INSN_NS(ssess, 0x665E, CPU_SSE2); }
- 'divsd' { RET_INSN_NS(ssess, 0xF25E, CPU_SSE2); }
- 'maxpd' { RET_INSN_NS(ssess, 0x665F, CPU_SSE2); }
- 'maxsd' { RET_INSN_NS(ssess, 0xF25F, CPU_SSE2); }
- 'minpd' { RET_INSN_NS(ssess, 0x665D, CPU_SSE2); }
- 'minsd' { RET_INSN_NS(ssess, 0xF25D, CPU_SSE2); }
- 'movapd' { RET_INSN_NS(movaupd, 0x28, CPU_SSE2); }
- 'movhpd' { RET_INSN_NS(movhlpd, 0x16, CPU_SSE2); }
- 'movlpd' { RET_INSN_NS(movhlpd, 0x12, CPU_SSE2); }
- 'movmskpd' [lLqQ]? { RET_INSN(8, movmskpd, 0, CPU_SSE2); }
- 'movntpd' { RET_INSN_NS(movntpddq, 0x2B, CPU_SSE2); }
- 'movntdq' { RET_INSN_NS(movntpddq, 0xE7, CPU_SSE2); }
- /* M O V S D is in string instructions above */
- 'movupd' { RET_INSN_NS(movaupd, 0x10, CPU_SSE2); }
- 'mulpd' { RET_INSN_NS(ssess, 0x6659, CPU_SSE2); }
- 'mulsd' { RET_INSN_NS(ssess, 0xF259, CPU_SSE2); }
- 'orpd' { RET_INSN_NS(ssess, 0x6656, CPU_SSE2); }
- 'shufpd' { RET_INSN_NS(ssessimm, 0x66C6, CPU_SSE2); }
- 'sqrtpd' { RET_INSN_NS(ssess, 0x6651, CPU_SSE2); }
- 'sqrtsd' { RET_INSN_NS(ssess, 0xF251, CPU_SSE2); }
- 'subpd' { RET_INSN_NS(ssess, 0x665C, CPU_SSE2); }
- 'subsd' { RET_INSN_NS(ssess, 0xF25C, CPU_SSE2); }
- 'ucomisd' { RET_INSN_NS(ssess, 0x662E, CPU_SSE2); }
- 'unpckhpd' { RET_INSN_NS(ssess, 0x6615, CPU_SSE2); }
- 'unpcklpd' { RET_INSN_NS(ssess, 0x6614, CPU_SSE2); }
- 'xorpd' { RET_INSN_NS(ssess, 0x6657, CPU_SSE2); }
- 'cvtdq2pd' { RET_INSN_NS(cvt_xmm_xmm64_ss, 0xF3E6, CPU_SSE2); }
- 'cvtpd2dq' { RET_INSN_NS(ssess, 0xF2E6, CPU_SSE2); }
- 'cvtdq2ps' { RET_INSN_NS(sseps, 0x5B, CPU_SSE2); }
- 'cvtpd2pi' { RET_INSN_NS(cvt_mm_xmm, 0x662D, CPU_SSE2); }
- 'cvtpd2ps' { RET_INSN_NS(ssess, 0x665A, CPU_SSE2); }
- 'cvtps2pd' { RET_INSN_NS(cvt_xmm_xmm64_ps, 0x5A, CPU_SSE2); }
- 'cvtps2dq' { RET_INSN_NS(ssess, 0x665B, CPU_SSE2); }
- 'cvtsd2si' [lLqQ]? { RET_INSN(8, cvt_rx_xmm64, 0xF22D, CPU_SSE2); }
- 'cvtsd2ss' { RET_INSN_NS(cvt_xmm_xmm64_ss, 0xF25A, CPU_SSE2); }
- /* P4 VMX Instructions */
- 'vmcall' { RET_INSN_NS(threebyte, 0x0F01C1, CPU_P4); }
- 'vmlaunch' { RET_INSN_NS(threebyte, 0x0F01C2, CPU_P4); }
- 'vmresume' { RET_INSN_NS(threebyte, 0x0F01C3, CPU_P4); }
- 'vmxoff' { RET_INSN_NS(threebyte, 0x0F01C4, CPU_P4); }
- 'vmread' [lLqQ]? { RET_INSN(6, vmxmemrd, 0x0F78, CPU_P4); }
- 'vmwrite' [lLqQ]? { RET_INSN(7, vmxmemwr, 0x0F79, CPU_P4); }
- 'vmptrld' { RET_INSN_NS(vmxtwobytemem, 0x06C7, CPU_P4); }
- 'vmptrst' { RET_INSN_NS(vmxtwobytemem, 0x07C7, CPU_P4); }
- 'vmclear' { RET_INSN_NS(vmxthreebytemem, 0x0666C7, CPU_P4); }
- 'vmxon' { RET_INSN_NS(vmxthreebytemem, 0x06F3C7, CPU_P4); }
- 'cvtss2sd' { RET_INSN_NS(cvt_xmm_xmm32, 0xF35A, CPU_SSE2); }
- 'cvttpd2pi' { RET_INSN_NS(cvt_mm_xmm, 0x662C, CPU_SSE2); }
- 'cvttsd2si' [lLqQ]? { RET_INSN(9, cvt_rx_xmm64, 0xF22C, CPU_SSE2); }
- 'cvttpd2dq' { RET_INSN_NS(ssess, 0x66E6, CPU_SSE2); }
- 'cvttps2dq' { RET_INSN_NS(ssess, 0xF35B, CPU_SSE2); }
- 'maskmovdqu' { RET_INSN_NS(maskmovdqu, 0, CPU_SSE2); }
- 'movdqa' { RET_INSN_NS(movdqau, 0x66, CPU_SSE2); }
- 'movdqu' { RET_INSN_NS(movdqau, 0xF3, CPU_SSE2); }
- 'movdq2q' { RET_INSN_NS(movdq2q, 0, CPU_SSE2); }
- 'movq2dq' { RET_INSN_NS(movq2dq, 0, CPU_SSE2); }
- 'pmuludq' { RET_INSN_NS(mmxsse2, 0xF4, CPU_SSE2); }
- 'pshufd' { RET_INSN_NS(ssessimm, 0x6670, CPU_SSE2); }
- 'pshufhw' { RET_INSN_NS(ssessimm, 0xF370, CPU_SSE2); }
- 'pshuflw' { RET_INSN_NS(ssessimm, 0xF270, CPU_SSE2); }
- 'pslldq' { RET_INSN_NS(pslrldq, 0x07, CPU_SSE2); }
- 'psrldq' { RET_INSN_NS(pslrldq, 0x03, CPU_SSE2); }
- 'punpckhqdq' { RET_INSN_NS(ssess, 0x666D, CPU_SSE2); }
- 'punpcklqdq' { RET_INSN_NS(ssess, 0x666C, CPU_SSE2); }
- /* SSE3 / PNI (Prescott New Instructions) instructions */
- 'addsubpd' { RET_INSN_NS(ssess, 0x66D0, CPU_SSE3); }
- 'addsubps' { RET_INSN_NS(ssess, 0xF2D0, CPU_SSE3); }
- 'fisttp' [sSlLqQ]? { RET_INSN(6, fildstp, 0x010001, CPU_SSE3); }
- 'fisttpll' {
- suffix_over='q';
- RET_INSN_GAS(8, fildstp, 0x07, CPU_FPU);
- }
- 'haddpd' { RET_INSN_NS(ssess, 0x667C, CPU_SSE3); }
- 'haddps' { RET_INSN_NS(ssess, 0xF27C, CPU_SSE3); }
- 'hsubpd' { RET_INSN_NS(ssess, 0x667D, CPU_SSE3); }
- 'hsubps' { RET_INSN_NS(ssess, 0xF27D, CPU_SSE3); }
- 'lddqu' { RET_INSN_NS(lddqu, 0, CPU_SSE3); }
- 'monitor' { RET_INSN_NS(threebyte, 0x0F01C8, CPU_SSE3); }
- 'movddup' { RET_INSN_NS(cvt_xmm_xmm64_ss, 0xF212, CPU_SSE3); }
- 'movshdup' { RET_INSN_NS(ssess, 0xF316, CPU_SSE3); }
- 'movsldup' { RET_INSN_NS(ssess, 0xF312, CPU_SSE3); }
- 'mwait' { RET_INSN_NS(threebyte, 0x0F01C9, CPU_SSE3); }
- /* AMD 3DNow! instructions */
- 'prefetch' { RET_INSN_NS(twobytemem, 0x000F0D, CPU_3DNow); }
- 'prefetchw' { RET_INSN_NS(twobytemem, 0x010F0D, CPU_3DNow); }
- 'femms' { RET_INSN_NS(twobyte, 0x0F0E, CPU_3DNow); }
- 'pavgusb' { RET_INSN_NS(now3d, 0xBF, CPU_3DNow); }
- 'pf2id' { RET_INSN_NS(now3d, 0x1D, CPU_3DNow); }
- 'pf2iw' { RET_INSN_NS(now3d, 0x1C, CPU_Athlon|CPU_3DNow); }
- 'pfacc' { RET_INSN_NS(now3d, 0xAE, CPU_3DNow); }
- 'pfadd' { RET_INSN_NS(now3d, 0x9E, CPU_3DNow); }
- 'pfcmpeq' { RET_INSN_NS(now3d, 0xB0, CPU_3DNow); }
- 'pfcmpge' { RET_INSN_NS(now3d, 0x90, CPU_3DNow); }
- 'pfcmpgt' { RET_INSN_NS(now3d, 0xA0, CPU_3DNow); }
- 'pfmax' { RET_INSN_NS(now3d, 0xA4, CPU_3DNow); }
- 'pfmin' { RET_INSN_NS(now3d, 0x94, CPU_3DNow); }
- 'pfmul' { RET_INSN_NS(now3d, 0xB4, CPU_3DNow); }
- 'pfnacc' { RET_INSN_NS(now3d, 0x8A, CPU_Athlon|CPU_3DNow); }
- 'pfpnacc' { RET_INSN_NS(now3d, 0x8E, CPU_Athlon|CPU_3DNow); }
- 'pfrcp' { RET_INSN_NS(now3d, 0x96, CPU_3DNow); }
- 'pfrcpit1' { RET_INSN_NS(now3d, 0xA6, CPU_3DNow); }
- 'pfrcpit2' { RET_INSN_NS(now3d, 0xB6, CPU_3DNow); }
- 'pfrsqit1' { RET_INSN_NS(now3d, 0xA7, CPU_3DNow); }
- 'pfrsqrt' { RET_INSN_NS(now3d, 0x97, CPU_3DNow); }
- 'pfsub' { RET_INSN_NS(now3d, 0x9A, CPU_3DNow); }
- 'pfsubr' { RET_INSN_NS(now3d, 0xAA, CPU_3DNow); }
- 'pi2fd' { RET_INSN_NS(now3d, 0x0D, CPU_3DNow); }
- 'pi2fw' { RET_INSN_NS(now3d, 0x0C, CPU_Athlon|CPU_3DNow); }
- 'pmulhrwa' { RET_INSN_NS(now3d, 0xB7, CPU_3DNow); }
- 'pswapd' { RET_INSN_NS(now3d, 0xBB, CPU_Athlon|CPU_3DNow); }
- /* AMD extensions */
- 'syscall' { RET_INSN_NS(twobyte, 0x0F05, CPU_686|CPU_AMD); }
- 'sysret' [lLqQ]? { RET_INSN(6, twobyte, 0x0F07, CPU_686|CPU_AMD|CPU_Priv); }
- /* AMD x86-64 extensions */
- 'swapgs' {
- warn64 = 1;
- RET_INSN_NS(threebyte, 0x0F01F8, CPU_Hammer|CPU_64);
- }
- 'rdtscp' { RET_INSN_NS(threebyte, 0x0F01F9, CPU_686|CPU_AMD|CPU_Priv); }
- /* AMD Pacifica (SVM) instructions */
- 'clgi' { RET_INSN_NS(threebyte, 0x0F01DD, CPU_Hammer|CPU_64|CPU_SVM); }
- 'invlpga' { RET_INSN_NS(invlpga, 0, CPU_Hammer|CPU_64|CPU_SVM); }
- 'skinit' { RET_INSN_NS(skinit, 0, CPU_Hammer|CPU_64|CPU_SVM); }
- 'stgi' { RET_INSN_NS(threebyte, 0x0F01DC, CPU_Hammer|CPU_64|CPU_SVM); }
- 'vmload' { RET_INSN_NS(svm_rax, 0xDA, CPU_Hammer|CPU_64|CPU_SVM); }
- 'vmmcall' { RET_INSN_NS(threebyte, 0x0F01D9, CPU_Hammer|CPU_64|CPU_SVM); }
- 'vmrun' { RET_INSN_NS(svm_rax, 0xD8, CPU_Hammer|CPU_64|CPU_SVM); }
- 'vmsave' { RET_INSN_NS(svm_rax, 0xDB, CPU_Hammer|CPU_64|CPU_SVM); }
- /* VIA PadLock instructions */
- 'xstore' ('rng')? { RET_INSN_NS(padlock, 0xC000A7, CPU_PadLock); }
- 'xcryptecb' { RET_INSN_NS(padlock, 0xC8F3A7, CPU_PadLock); }
- 'xcryptcbc' { RET_INSN_NS(padlock, 0xD0F3A7, CPU_PadLock); }
- 'xcryptctr' { RET_INSN_NS(padlock, 0xD8F3A7, CPU_PadLock); }
- 'xcryptcfb' { RET_INSN_NS(padlock, 0xE0F3A7, CPU_PadLock); }
- 'xcryptofb' { RET_INSN_NS(padlock, 0xE8F3A7, CPU_PadLock); }
- 'montmul' { RET_INSN_NS(padlock, 0xC0F3A6, CPU_PadLock); }
- 'xsha1' { RET_INSN_NS(padlock, 0xC8F3A6, CPU_PadLock); }
- 'xsha256' { RET_INSN_NS(padlock, 0xD0F3A6, CPU_PadLock); }
- /* Cyrix MMX instructions */
- 'paddsiw' { RET_INSN_NS(cyrixmmx, 0x51, CPU_Cyrix|CPU_MMX); }
- 'paveb' { RET_INSN_NS(cyrixmmx, 0x50, CPU_Cyrix|CPU_MMX); }
- 'pdistib' { RET_INSN_NS(cyrixmmx, 0x54, CPU_Cyrix|CPU_MMX); }
- 'pmachriw' { RET_INSN_NS(pmachriw, 0, CPU_Cyrix|CPU_MMX); }
- 'pmagw' { RET_INSN_NS(cyrixmmx, 0x52, CPU_Cyrix|CPU_MMX); }
- 'pmulhriw' { RET_INSN_NS(cyrixmmx, 0x5D, CPU_Cyrix|CPU_MMX); }
- 'pmulhrwc' { RET_INSN_NS(cyrixmmx, 0x59, CPU_Cyrix|CPU_MMX); }
- 'pmvgezb' { RET_INSN_NS(cyrixmmx, 0x5C, CPU_Cyrix|CPU_MMX); }
- 'pmvlzb' { RET_INSN_NS(cyrixmmx, 0x5B, CPU_Cyrix|CPU_MMX); }
- 'pmvnzb' { RET_INSN_NS(cyrixmmx, 0x5A, CPU_Cyrix|CPU_MMX); }
- 'pmvzb' { RET_INSN_NS(cyrixmmx, 0x58, CPU_Cyrix|CPU_MMX); }
- 'psubsiw' { RET_INSN_NS(cyrixmmx, 0x55, CPU_Cyrix|CPU_MMX); }
- /* Cyrix extensions */
- 'rdshr' { RET_INSN_NS(twobyte, 0x0F36, CPU_686|CPU_Cyrix|CPU_SMM); }
- 'rsdc' { RET_INSN_NS(rsdc, 0, CPU_486|CPU_Cyrix|CPU_SMM); }
- 'rsldt' { RET_INSN_NS(cyrixsmm, 0x7B, CPU_486|CPU_Cyrix|CPU_SMM); }
- 'rsts' { RET_INSN_NS(cyrixsmm, 0x7D, CPU_486|CPU_Cyrix|CPU_SMM); }
- 'svdc' { RET_INSN_NS(svdc, 0, CPU_486|CPU_Cyrix|CPU_SMM); }
- 'svldt' { RET_INSN_NS(cyrixsmm, 0x7A, CPU_486|CPU_Cyrix|CPU_SMM); }
- 'svts' { RET_INSN_NS(cyrixsmm, 0x7C, CPU_486|CPU_Cyrix|CPU_SMM); }
- 'smint' { RET_INSN_NS(twobyte, 0x0F38, CPU_686|CPU_Cyrix); }
- 'smintold' { RET_INSN_NS(twobyte, 0x0F7E, CPU_486|CPU_Cyrix|CPU_Obs); }
- 'wrshr' { RET_INSN_NS(twobyte, 0x0F37, CPU_686|CPU_Cyrix|CPU_SMM); }
- /* Obsolete/undocumented instructions */
- 'fsetpm' { RET_INSN_NS(twobyte, 0xDBE4, CPU_286|CPU_FPU|CPU_Obs); }
- 'ibts' { RET_INSN_NS(ibts, 0, CPU_386|CPU_Undoc|CPU_Obs); }
- 'loadall' { RET_INSN_NS(twobyte, 0x0F07, CPU_386|CPU_Undoc); }
- 'loadall286' { RET_INSN_NS(twobyte, 0x0F05, CPU_286|CPU_Undoc); }
- 'salc' {
- not64 = 1;
- RET_INSN_NS(onebyte, 0x00D6, CPU_Undoc);
- }
- 'smi' { RET_INSN_NS(onebyte, 0x00F1, CPU_386|CPU_Undoc); }
- 'umov' { RET_INSN_NS(umov, 0, CPU_386|CPU_Undoc); }
- 'xbts' { RET_INSN_NS(xbts, 0, CPU_386|CPU_Undoc|CPU_Obs); }
-
-
- /* catchalls */
- [\001-\377]+ {
- return 0;
- }
- [\000] {
- return 0;
- }
- */
-done:
- if (suffix) {
- /* If not using the GAS parser, no instructions have suffixes. */
- if (arch_x86->parser != X86_PARSER_GAS)
- return 0;
-
- if (suffix_over == '\0')
- suffix_over = id[suffix_ofs];
- /* Match suffixes */
- switch (suffix_over) {
- case 'b':
- case 'B':
- data[3] |= (MOD_GasSufB >> MOD_GasSuf_SHIFT) << 8;
- break;
- case 'w':
- case 'W':
- data[3] |= (MOD_GasSufW >> MOD_GasSuf_SHIFT) << 8;
- break;
- case 'l':
- case 'L':
- data[3] |= (MOD_GasSufL >> MOD_GasSuf_SHIFT) << 8;
- break;
- case 'q':
- case 'Q':
- data[3] |= (MOD_GasSufQ >> MOD_GasSuf_SHIFT) << 8;
- break;
- case 's':
- case 'S':
- data[3] |= (MOD_GasSufS >> MOD_GasSuf_SHIFT) << 8;
- break;
- default:
- yasm_internal_error(N_("unrecognized suffix"));
- }
- }
- if (warn64 && arch_x86->mode_bits != 64) {
+ /*@null@*/ const regtmod_parse_data *pdata;
+ size_t i;
+ static char lcaseid[8];
+ unsigned int bits;
+ yasm_arch_regtmod type;
+
+ if (id_len > 7)
+ return YASM_ARCH_NOTREGTMOD;
+ for (i=0; i<id_len; i++)
+ lcaseid[i] = tolower(id[i]);
+ lcaseid[id_len] = '\0';
+
+ pdata = regtmod_find(lcaseid, id_len);
+ if (!pdata)
+ return YASM_ARCH_NOTREGTMOD;
+
+ type = (yasm_arch_regtmod)(pdata->regtmod >> 24);
+ bits = (pdata->regtmod >> 16) & 0xFF;
+
+ if (type == YASM_ARCH_REG && bits != 0 && arch_x86->mode_bits != bits) {
yasm__warning(YASM_WARN_GENERAL, line,
- N_("`%s' is an instruction in 64-bit mode"),
- oid);
- return 0;
+ N_("`%s' is a register in %u-bit mode"), id, bits);
+ return YASM_ARCH_NOTREGTMOD;
}
- if (not64 && arch_x86->mode_bits == 64) {
- yasm__error(line, N_("`%s' invalid in 64-bit mode"), oid);
- DEF_INSN_DATA(not64, 0, CPU_Not64);
- return 1;
+
+ if (type == YASM_ARCH_SEGREG && bits != 0 && arch_x86->mode_bits == bits) {
+ yasm__warning(YASM_WARN_GENERAL, line,
+ N_("`%s' segment register ignored in %u-bit mode"), id,
+ bits);
}
- return 1;
+
+ *data = pdata->regtmod & 0x0000FFFFUL;
+ return type;
}
+
--- /dev/null
+# GAP (gen_arch_parse) input file for x86 architecture
+# $Id$
+
+# Configure GAP for x86 generation mode
+ARCH x86
+
+# Supported x86 parsers
+PARSERS nasm gas
+
+# INSN parameters:
+# - parser (- if any)
+# - base name of instruction
+# - if string, each character is an allowed GAS suffix
+# if defined name, value is GAS suffix mode set (no character suffix reqd)
+# - instruction group (sans _insn suffix)
+# - modifiers (up to 3 bytes)
+# - CPU flags
+#
+# The string mode of the second parameter is a shortcut for GAS forms, e.g.:
+# INSN - mov "bwl" mov 0 CPU_Any
+# is equivalent to:
+# INSN - mov NONE mov 0 CPU_Any
+# INSN gas movb SUF_B mov 0 CPU_Any
+# INSN gas movw SUF_W mov 0 CPU_Any
+# INSN gas movl SUF_L mov 0 CPU_Any
+
+# Move
+INSN - mov "bwl" mov 0 CPU_Any
+INSN gas movabs "bwlq" movabs 0 CPU_Hammer|CPU_64
+
+# Move with sign/zero extend
+INSN gas movsbw SUF_B movszx 0xBE CPU_386
+INSN gas movsbl SUF_B movszx 0xBE CPU_386
+INSN gas movswl SUF_W movszx 0xBE CPU_386
+INSN gas movsbq SUF_B movszx 0xBE CPU_Hammer|CPU_64
+INSN gas movswq SUF_W movszx 0xBE CPU_Hammer|CPU_64
+INSN - movsx "bw" movszx 0xBE CPU_386
+INSN gas movslq SUF_L movsxd 0 CPU_Hammer|CPU_64
+INSN nasm movsxd NONE movsxd 0 CPU_Hammer|CPU_64
+INSN gas movzbw SUF_B movszx 0xB6 CPU_386
+INSN gas movzbl SUF_B movszx 0xB6 CPU_386
+INSN gas movzwl SUF_W movszx 0xB6 CPU_386
+INSN gas movzbq SUF_B movszx 0xB6 CPU_Hammer|CPU_64
+INSN gas movzwq SUF_W movszx 0xB6 CPU_Hammer|CPU_64
+INSN - movzx NONE movszx 0xB6 CPU_386
+
+# Push instructions
+INSN - push "wlq" push 0 CPU_Any
+INSN - pusha NONE onebyte 0x0060 CPU_186|CPU_Not64
+INSN nasm pushad NONE onebyte 0x2060 CPU_386|CPU_Not64
+INSN gas pushal NONE onebyte 0x2060 CPU_386|CPU_Not64
+INSN - pushaw NONE onebyte 0x1060 CPU_186|CPU_Not64
+
+# Pop instructions
+INSN - pop "wlq" pop 0 CPU_Any
+INSN - popa NONE onebyte 0x0061 CPU_186|CPU_Not64
+INSN nasm popad NONE onebyte 0x2061 CPU_386|CPU_Not64
+INSN gas popal NONE onebyte 0x2061 CPU_386|CPU_Not64
+INSN - popaw NONE onebyte 0x1061 CPU_186|CPU_Not64
+
+# Exchange
+INSN - xchg "bwlq" xchg 0 CPU_Any
+
+# In/out from ports
+INSN - in "bwl" in 0 CPU_Any
+INSN - out "bwl" out 0 CPU_Any
+# Load effective address
+INSN - lea "wlq" lea 0 CPU_Any
+# Load segment registers from memory
+INSN - lds "wl" ldes 0xC5 CPU_Not64
+INSN - les "wl" ldes 0xC4 CPU_Not64
+INSN - lfs "wl" lfgss 0xB4 CPU_386
+INSN - lgs "wl" lfgss 0xB5 CPU_386
+INSN - lss "wl" lfgss 0xB2 CPU_386
+# Flags register instructions
+INSN - clc NONE onebyte 0x00F8 CPU_Any
+INSN - cld NONE onebyte 0x00FC CPU_Any
+INSN - cli NONE onebyte 0x00FA CPU_Any
+INSN - clts NONE twobyte 0x0F06 CPU_286|CPU_Priv
+INSN - cmc NONE onebyte 0x00F5 CPU_Any
+INSN - lahf NONE onebyte 0x009F CPU_Any
+INSN - sahf NONE onebyte 0x009E CPU_Any
+INSN - pushf NONE onebyte 0x009C CPU_Any
+INSN nasm pushfd NONE onebyte 0x209C CPU_386
+INSN gas pushfl NONE onebyte 0x209C CPU_386
+INSN - pushfw NONE onebyte 0x109C CPU_Any
+INSN - pushfq NONE onebyte 0x409C CPU_Hammer|CPU_64
+INSN - popf NONE onebyte 0x40009D CPU_Any
+INSN nasm popfd NONE onebyte 0x00209D CPU_386|CPU_Not64
+INSN gas popfl NONE onebyte 0x00209D CPU_386|CPU_Not64
+INSN - popfw NONE onebyte 0x40109D CPU_Any
+INSN - popfq NONE onebyte 0x40409D CPU_Hammer|CPU_64
+INSN - stc NONE onebyte 0x00F9 CPU_Any
+INSN - std NONE onebyte 0x00FD CPU_Any
+INSN - sti NONE onebyte 0x00FB CPU_Any
+# Arithmetic
+INSN - add "bwlq" arith 0x0000 CPU_Any
+INSN - inc "bwlq" incdec 0x0040 CPU_Any
+INSN - sub "bwlq" arith 0x0528 CPU_Any
+INSN - dec "bwlq" incdec 0x0148 CPU_Any
+INSN - sbb "bwlq" arith 0x0318 CPU_Any
+INSN - cmp "bwlq" arith 0x0738 CPU_Any
+INSN - test "bwlq" test 0 CPU_Any
+INSN - and "bwlq" arith 0x0420 CPU_Any
+INSN - or "bwlq" arith 0x0108 CPU_Any
+INSN - xor "bwlq" arith 0x0630 CPU_Any
+INSN - adc "bwlq" arith 0x0210 CPU_Any
+INSN - neg "bwlq" f6 0x03 CPU_Any
+INSN - not "bwlq" f6 0x02 CPU_Any
+INSN - aaa NONE onebyte 0x0037 CPU_Not64
+INSN - aas NONE onebyte 0x003F CPU_Not64
+INSN - daa NONE onebyte 0x0027 CPU_Not64
+INSN - das NONE onebyte 0x002F CPU_Not64
+INSN - aad NONE aadm 0x01 CPU_Not64
+INSN - aam NONE aadm 0x00 CPU_Not64
+# Conversion instructions
+INSN - cbw NONE onebyte 0x1098 CPU_Any
+INSN - cwde NONE onebyte 0x2098 CPU_386
+INSN - cdqe NONE onebyte 0x4098 CPU_Hammer|CPU_64
+INSN - cwd NONE onebyte 0x1099 CPU_Any
+INSN - cdq NONE onebyte 0x2099 CPU_386
+INSN - cqo NONE onebyte 0x4099 CPU_Hammer|CPU_64
+# Conversion instructions - GAS / AT&T naming
+INSN gas cbtw NONE onebyte 0x1098 CPU_Any
+INSN gas cwtl NONE onebyte 0x2098 CPU_386
+INSN gas cltq NONE onebyte 0x4098 CPU_Hammer|CPU_64
+INSN gas cwtd NONE onebyte 0x1099 CPU_Any
+INSN gas cltd NONE onebyte 0x2099 CPU_386
+INSN gas cqto NONE onebyte 0x4099 CPU_Hammer|CPU_64
+# Multiplication and division
+INSN - mul "bwlq" f6 0x04 CPU_Any
+INSN - imul "bwlq" imul 0 CPU_Any
+INSN - div "bwlq" div 0x06 CPU_Any
+INSN - idiv "bwlq" div 0x07 CPU_Any
+# Shifts
+INSN - rol "bwlq" shift 0x00 CPU_Any
+INSN - ror "bwlq" shift 0x01 CPU_Any
+INSN - rcl "bwlq" shift 0x02 CPU_Any
+INSN - rcr "bwlq" shift 0x03 CPU_Any
+INSN - sal "bwlq" shift 0x04 CPU_Any
+INSN - shl "bwlq" shift 0x04 CPU_Any
+INSN - shr "bwlq" shift 0x05 CPU_Any
+INSN - sar "bwlq" shift 0x07 CPU_Any
+INSN - shld "wlq" shlrd 0xA4 CPU_386
+INSN - shrd "wlq" shlrd 0xAC CPU_386
+# Control transfer instructions unconditional)
+INSN - call NONE call 0 CPU_Any
+INSN - jmp NONE jmp 0 CPU_Any
+INSN - ret NONE retnf 0x00C2 CPU_Any
+INSN gas retw NONE retnf 0x10C2 CPU_Any
+INSN gas retl NONE retnf 0x00C2 CPU_Not64
+INSN gas retq NONE retnf 0x00C2 CPU_Hammer|CPU_64
+INSN nasm retn NONE retnf 0x00C2 CPU_Any
+INSN nasm retf NONE retnf 0x40CA CPU_Any
+INSN gas lretw NONE retnf 0x10CA CPU_Any
+INSN gas lretl NONE retnf 0x00CA CPU_Any
+INSN gas lretq NONE retnf 0x40CA CPU_Hammer|CPU_64
+INSN - enter "wlq" enter 0 CPU_186
+INSN - leave NONE onebyte 0x4000C9 CPU_186
+INSN gas leavew NONE onebyte 0x0010C9 CPU_186
+INSN gas leavel NONE onebyte 0x4000C9 CPU_186
+INSN gas leaveq NONE onebyte 0x4000C9 CPU_Hammer|CPU_64
+# Conditional jumps
+INSN - jo NONE jcc 0x00 CPU_Any
+INSN - jno NONE jcc 0x01 CPU_Any
+INSN - jb NONE jcc 0x02 CPU_Any
+INSN - jc NONE jcc 0x02 CPU_Any
+INSN - jnae NONE jcc 0x02 CPU_Any
+INSN - jnb NONE jcc 0x03 CPU_Any
+INSN - jnc NONE jcc 0x03 CPU_Any
+INSN - jae NONE jcc 0x03 CPU_Any
+INSN - je NONE jcc 0x04 CPU_Any
+INSN - jz NONE jcc 0x04 CPU_Any
+INSN - jne NONE jcc 0x05 CPU_Any
+INSN - jnz NONE jcc 0x05 CPU_Any
+INSN - jbe NONE jcc 0x06 CPU_Any
+INSN - jna NONE jcc 0x06 CPU_Any
+INSN - jnbe NONE jcc 0x07 CPU_Any
+INSN - ja NONE jcc 0x07 CPU_Any
+INSN - js NONE jcc 0x08 CPU_Any
+INSN - jns NONE jcc 0x09 CPU_Any
+INSN - jp NONE jcc 0x0A CPU_Any
+INSN - jpe NONE jcc 0x0A CPU_Any
+INSN - jnp NONE jcc 0x0B CPU_Any
+INSN - jpo NONE jcc 0x0B CPU_Any
+INSN - jl NONE jcc 0x0C CPU_Any
+INSN - jnge NONE jcc 0x0C CPU_Any
+INSN - jnl NONE jcc 0x0D CPU_Any
+INSN - jge NONE jcc 0x0D CPU_Any
+INSN - jle NONE jcc 0x0E CPU_Any
+INSN - jng NONE jcc 0x0E CPU_Any
+INSN - jnle NONE jcc 0x0F CPU_Any
+INSN - jg NONE jcc 0x0F CPU_Any
+INSN - jcxz NONE jcxz 0x10 CPU_Any
+INSN - jecxz NONE jcxz 0x20 CPU_386
+INSN - jrcxz NONE jcxz 0x40 CPU_Hammer|CPU_64
+# Loop instructions
+INSN - loop NONE loop 0x02 CPU_Any
+INSN - loopz NONE loop 0x01 CPU_Any
+INSN - loope NONE loop 0x01 CPU_Any
+INSN - loopnz NONE loop 0x00 CPU_Any
+INSN - loopne NONE loop 0x00 CPU_Any
+# Set byte on flag instructions
+INSN - seto "b" setcc 0x00 CPU_386
+INSN - setno "b" setcc 0x01 CPU_386
+INSN - setb "b" setcc 0x02 CPU_386
+INSN - setc "b" setcc 0x02 CPU_386
+INSN - setnae "b" setcc 0x02 CPU_386
+INSN - setnb "b" setcc 0x03 CPU_386
+INSN - setnc "b" setcc 0x03 CPU_386
+INSN - setae "b" setcc 0x03 CPU_386
+INSN - sete "b" setcc 0x04 CPU_386
+INSN - setz "b" setcc 0x04 CPU_386
+INSN - setne "b" setcc 0x05 CPU_386
+INSN - setnz "b" setcc 0x05 CPU_386
+INSN - setbe "b" setcc 0x06 CPU_386
+INSN - setna "b" setcc 0x06 CPU_386
+INSN - setnbe "b" setcc 0x07 CPU_386
+INSN - seta "b" setcc 0x07 CPU_386
+INSN - sets "b" setcc 0x08 CPU_386
+INSN - setns "b" setcc 0x09 CPU_386
+INSN - setp "b" setcc 0x0A CPU_386
+INSN - setpe "b" setcc 0x0A CPU_386
+INSN - setnp "b" setcc 0x0B CPU_386
+INSN - setpo "b" setcc 0x0B CPU_386
+INSN - setl "b" setcc 0x0C CPU_386
+INSN - setnge "b" setcc 0x0C CPU_386
+INSN - setnl "b" setcc 0x0D CPU_386
+INSN - setge "b" setcc 0x0D CPU_386
+INSN - setle "b" setcc 0x0E CPU_386
+INSN - setng "b" setcc 0x0E CPU_386
+INSN - setnle "b" setcc 0x0F CPU_386
+INSN - setg "b" setcc 0x0F CPU_386
+# String instructions
+INSN - cmpsb NONE onebyte 0x00A6 CPU_Any
+INSN - cmpsw NONE onebyte 0x10A7 CPU_Any
+INSN - cmpsd NONE cmpsd 0 CPU_Any
+INSN gas cmpsl NONE onebyte 0x20A7 CPU_386
+INSN - cmpsq NONE onebyte 0x40A7 CPU_Hammer|CPU_64
+INSN - insb NONE onebyte 0x006C CPU_Any
+INSN - insw NONE onebyte 0x106D CPU_Any
+INSN nasm insd NONE onebyte 0x206D CPU_386
+INSN gas insl NONE onebyte 0x206D CPU_386
+INSN - outsb NONE onebyte 0x006E CPU_Any
+INSN - outsw NONE onebyte 0x106F CPU_Any
+INSN nasm outsd NONE onebyte 0x206F CPU_386
+INSN gas outsl NONE onebyte 0x206F CPU_386
+INSN - lodsb NONE onebyte 0x00AC CPU_Any
+INSN - lodsw NONE onebyte 0x10AD CPU_Any
+INSN nasm lodsd NONE onebyte 0x20AD CPU_386
+INSN gas lodsl NONE onebyte 0x20AD CPU_386
+INSN - lodsq NONE onebyte 0x40AD CPU_Hammer|CPU_64
+INSN - movsb NONE onebyte 0x00A4 CPU_Any
+INSN - movsw NONE onebyte 0x10A5 CPU_Any
+INSN - movsd NONE movsd 0 CPU_Any
+INSN gas movsl NONE onebyte 0x20A5 CPU_386
+INSN - movsq NONE onebyte 0x40A5 CPU_Hammer|CPU_64
+# smov alias for movs in GAS mode
+INSN gas smovb NONE onebyte 0x00A4 CPU_Any
+INSN gas smovw NONE onebyte 0x10A5 CPU_Any
+INSN gas smovl NONE onebyte 0x20A5 CPU_386
+INSN gas smovq NONE onebyte 0x40A5 CPU_Hammer|CPU_64
+INSN - scasb NONE onebyte 0x00AE CPU_Any
+INSN - scasw NONE onebyte 0x10AF CPU_Any
+INSN nasm scasd NONE onebyte 0x20AF CPU_386
+INSN gas scasl NONE onebyte 0x20AF CPU_386
+INSN - scasq NONE onebyte 0x40AF CPU_Hammer|CPU_64
+# ssca alias for scas in GAS mode
+INSN gas sscab NONE onebyte 0x00AE CPU_Any
+INSN gas sscaw NONE onebyte 0x10AF CPU_Any
+INSN gas sscal NONE onebyte 0x20AF CPU_386
+INSN gas sscaq NONE onebyte 0x40AF CPU_Hammer|CPU_64
+INSN - stosb NONE onebyte 0x00AA CPU_Any
+INSN - stosw NONE onebyte 0x10AB CPU_Any
+INSN nasm stosd NONE onebyte 0x20AB CPU_386
+INSN gas stosl NONE onebyte 0x20AB CPU_386
+INSN - stosq NONE onebyte 0x40AB CPU_Hammer|CPU_64
+INSN - xlatb NONE onebyte 0x00D7 CPU_Any
+# Bit manipulation
+INSN - bsf "wlq" bsfr 0xBC CPU_386
+INSN - bsr "wlq" bsfr 0xBD CPU_386
+INSN - bt "wlq" bittest 0x04A3 CPU_386
+INSN - btc "wlq" bittest 0x07BB CPU_386
+INSN - btr "wlq" bittest 0x06B3 CPU_386
+INSN - bts "wlq" bittest 0x05AB CPU_386
+# Interrupts and operating system instructions
+INSN - int NONE int 0 CPU_Any
+INSN - int3 NONE onebyte 0x00CC CPU_Any
+INSN nasm int03 NONE onebyte 0x00CC CPU_Any
+INSN - into NONE onebyte 0x00CE CPU_Not64
+INSN - iret NONE onebyte 0x00CF CPU_Any
+INSN - iretw NONE onebyte 0x10CF CPU_Any
+INSN nasm iretd NONE onebyte 0x20CF CPU_386
+INSN gas iretl NONE onebyte 0x20CF CPU_386
+INSN - iretq NONE onebyte 0x40CF CPU_Hammer|CPU_64
+INSN - rsm NONE twobyte 0x0FAA CPU_586|CPU_SMM
+INSN - bound "wl" bound 0 CPU_186|CPU_Not64
+INSN - hlt NONE onebyte 0x00F4 CPU_Priv
+INSN - nop NONE onebyte 0x0090 CPU_Any
+# Protection control
+INSN - arpl "w" arpl 0 CPU_286|CPU_Prot|CPU_Not64
+INSN - lar "wlq" bsfr 0x02 CPU_286|CPU_Prot
+INSN - lgdt "wlq" twobytemem 0x020F01 CPU_286|CPU_Priv
+INSN - lidt "wlq" twobytemem 0x030F01 CPU_286|CPU_Priv
+INSN - lldt "w" prot286 0x0200 CPU_286|CPU_Prot|CPU_Priv
+INSN - lmsw "w" prot286 0x0601 CPU_286|CPU_Priv
+INSN - lsl "wlq" bsfr 0x03 CPU_286|CPU_Prot
+INSN - ltr "w" prot286 0x0300 CPU_286|CPU_Prot|CPU_Priv
+INSN - sgdt "wlq" twobytemem 0x000F01 CPU_286|CPU_Priv
+INSN - sidt "wlq" twobytemem 0x010F01 CPU_286|CPU_Priv
+INSN - sldt "wlq" sldtmsw 0x0000 CPU_286
+INSN - smsw "wlq" sldtmsw 0x0401 CPU_286
+INSN - str "wlq" str 0 CPU_286|CPU_Prot
+INSN - verr "w" prot286 0x0400 CPU_286|CPU_Prot
+INSN - verw "w" prot286 0x0500 CPU_286|CPU_Prot
+# Floating point instructions
+INSN - fld "ls" fld 0 CPU_FPU
+INSN gas fldt WEAK fldstpt 0x05 CPU_FPU
+INSN - fild "lqs" fildstp 0x050200 CPU_FPU
+INSN gas fildll NONE fbldstp 0x05 CPU_FPU
+INSN - fbld NONE fbldstp 0x04 CPU_FPU
+INSN - fst "ls" fst 0 CPU_FPU
+INSN - fist "ls" fiarith 0x02DB CPU_FPU
+INSN - fstp "ls" fstp 0 CPU_FPU
+INSN gas fstpt WEAK fldstpt 0x07 CPU_FPU
+INSN - fistp "lqs" fildstp 0x070203 CPU_FPU
+INSN gas fistpll NONE fbldstp 0x07 CPU_FPU
+INSN - fbstp NONE fbldstp 0x06 CPU_FPU
+INSN - fxch NONE fxch 0 CPU_FPU
+INSN - fcom "ls" fcom 0x02D0 CPU_FPU
+INSN - ficom "ls" fiarith 0x02DA CPU_FPU
+INSN - fcomp "ls" fcom 0x03D8 CPU_FPU
+INSN - ficomp "ls" fiarith 0x03DA CPU_FPU
+INSN - fcompp NONE twobyte 0xDED9 CPU_FPU
+INSN - fucom NONE fcom2 0xDDE0 CPU_286|CPU_FPU
+INSN - fucomp NONE fcom2 0xDDE8 CPU_286|CPU_FPU
+INSN - fucompp NONE twobyte 0xDAE9 CPU_286|CPU_FPU
+INSN - ftst NONE twobyte 0xD9E4 CPU_FPU
+INSN - fxam NONE twobyte 0xD9E5 CPU_FPU
+INSN - fld1 NONE twobyte 0xD9E8 CPU_FPU
+INSN - fldl2t NONE twobyte 0xD9E9 CPU_FPU
+INSN - fldl2e NONE twobyte 0xD9EA CPU_FPU
+INSN - fldpi NONE twobyte 0xD9EB CPU_FPU
+INSN - fldlg2 NONE twobyte 0xD9EC CPU_FPU
+INSN - fldln2 NONE twobyte 0xD9ED CPU_FPU
+INSN - fldz NONE twobyte 0xD9EE CPU_FPU
+INSN - fadd "ls" farith 0x00C0C0 CPU_FPU
+INSN - faddp NONE farithp 0xC0 CPU_FPU
+INSN - fiadd "ls" fiarith 0x00DA CPU_FPU
+INSN - fsub "ls" farith 0x04E0E8 CPU_FPU
+INSN - fisub "ls" fiarith 0x04DA CPU_FPU
+INSN - fsubp NONE farithp 0xE8 CPU_FPU
+INSN - fsubr "ls" farith 0x05E8E0 CPU_FPU
+INSN - fisubr "ls" fiarith 0x05DA CPU_FPU
+INSN - fsubrp NONE farithp 0xE0 CPU_FPU
+INSN - fmul "ls" farith 0x01C8C8 CPU_FPU
+INSN - fimul "ls" fiarith 0x01DA CPU_FPU
+INSN - fmulp NONE farithp 0xC8 CPU_FPU
+INSN - fdiv "ls" farith 0x06F0F8 CPU_FPU
+INSN - fidiv "ls" fiarith 0x06DA CPU_FPU
+INSN - fdivp NONE farithp 0xF8 CPU_FPU
+INSN - fdivr "ls" farith 0x07F8F0 CPU_FPU
+INSN - fidivr "ls" fiarith 0x07DA CPU_FPU
+INSN - fdivrp NONE farithp 0xF0 CPU_FPU
+INSN - f2xm1 NONE twobyte 0xD9F0 CPU_FPU
+INSN - fyl2x NONE twobyte 0xD9F1 CPU_FPU
+INSN - fptan NONE twobyte 0xD9F2 CPU_FPU
+INSN - fpatan NONE twobyte 0xD9F3 CPU_FPU
+INSN - fxtract NONE twobyte 0xD9F4 CPU_FPU
+INSN - fprem1 NONE twobyte 0xD9F5 CPU_286|CPU_FPU
+INSN - fdecstp NONE twobyte 0xD9F6 CPU_FPU
+INSN - fincstp NONE twobyte 0xD9F7 CPU_FPU
+INSN - fprem NONE twobyte 0xD9F8 CPU_FPU
+INSN - fyl2xp1 NONE twobyte 0xD9F9 CPU_FPU
+INSN - fsqrt NONE twobyte 0xD9FA CPU_FPU
+INSN - fsincos NONE twobyte 0xD9FB CPU_286|CPU_FPU
+INSN - frndint NONE twobyte 0xD9FC CPU_FPU
+INSN - fscale NONE twobyte 0xD9FD CPU_FPU
+INSN - fsin NONE twobyte 0xD9FE CPU_286|CPU_FPU
+INSN - fcos NONE twobyte 0xD9FF CPU_286|CPU_FPU
+INSN - fchs NONE twobyte 0xD9E0 CPU_FPU
+INSN - fabs NONE twobyte 0xD9E1 CPU_FPU
+INSN - fninit NONE twobyte 0xDBE3 CPU_FPU
+INSN - finit NONE threebyte 0x9BDBE3 CPU_FPU
+INSN - fldcw "w" fldnstcw 0x05 CPU_FPU
+INSN - fnstcw "w" fldnstcw 0x07 CPU_FPU
+INSN - fstcw "w" fstcw 0 CPU_FPU
+INSN - fnstsw "w" fnstsw 0 CPU_FPU
+INSN - fstsw "w" fstsw 0 CPU_FPU
+INSN - fnclex NONE twobyte 0xDBE2 CPU_FPU
+INSN - fclex NONE threebyte 0x9BDBE2 CPU_FPU
+INSN - fnstenv "ls" onebytemem 0x06D9 CPU_FPU
+INSN - fstenv "ls" twobytemem 0x069BD9 CPU_FPU
+INSN - fldenv "ls" onebytemem 0x04D9 CPU_FPU
+INSN - fnsave "ls" onebytemem 0x06DD CPU_FPU
+INSN - fsave "ls" twobytemem 0x069BDD CPU_FPU
+INSN - frstor "ls" onebytemem 0x04DD CPU_FPU
+INSN - ffree NONE ffree 0xDD CPU_FPU
+INSN - ffreep NONE ffree 0xDF CPU_686|CPU_FPU|CPU_Undoc
+INSN - fnop NONE twobyte 0xD9D0 CPU_FPU
+INSN - fwait NONE onebyte 0x009B CPU_FPU
+# Prefixes should the others be here too? should wait be a prefix?
+INSN - wait NONE onebyte 0x009B CPU_Any
+# 486 extensions
+INSN - bswap "lq" bswap 0 CPU_486
+INSN - xadd "bwlq" cmpxchgxadd 0xC0 CPU_486
+INSN - cmpxchg "bwlq" cmpxchgxadd 0xB0 CPU_486
+INSN nasm cmpxchg486 NONE cmpxchgxadd 0xA6 CPU_486|CPU_Undoc
+INSN - invd NONE twobyte 0x0F08 CPU_486|CPU_Priv
+INSN - wbinvd NONE twobyte 0x0F09 CPU_486|CPU_Priv
+INSN - invlpg NONE twobytemem 0x070F01 CPU_486|CPU_Priv
+# 586+ and late 486 extensions
+INSN - cpuid NONE twobyte 0x0FA2 CPU_486
+# Pentium extensions
+INSN - wrmsr NONE twobyte 0x0F30 CPU_586|CPU_Priv
+INSN - rdtsc NONE twobyte 0x0F31 CPU_586
+INSN - rdmsr NONE twobyte 0x0F32 CPU_586|CPU_Priv
+INSN - cmpxchg8b "q" cmpxchg8b 0 CPU_586
+# Pentium II/Pentium Pro extensions
+INSN - sysenter NONE twobyte 0x0F34 CPU_686|CPU_Not64
+INSN - sysexit NONE twobyte 0x0F35 CPU_686|CPU_Priv|CPU_Not64
+INSN - fxsave "q" twobytemem 0x000FAE CPU_686|CPU_FPU
+INSN - fxrstor "q" twobytemem 0x010FAE CPU_686|CPU_FPU
+INSN - rdpmc NONE twobyte 0x0F33 CPU_686
+INSN - ud2 NONE twobyte 0x0F0B CPU_286
+INSN - ud1 NONE twobyte 0x0FB9 CPU_286|CPU_Undoc
+INSN - cmovo "wlq" cmovcc 0x00 CPU_686
+INSN - cmovno "wlq" cmovcc 0x01 CPU_686
+INSN - cmovb "wlq" cmovcc 0x02 CPU_686
+INSN - cmovc "wlq" cmovcc 0x02 CPU_686
+INSN - cmovnae "wlq" cmovcc 0x02 CPU_686
+INSN - cmovnb "wlq" cmovcc 0x03 CPU_686
+INSN - cmovnc "wlq" cmovcc 0x03 CPU_686
+INSN - cmovae "wlq" cmovcc 0x03 CPU_686
+INSN - cmove "wlq" cmovcc 0x04 CPU_686
+INSN - cmovz "wlq" cmovcc 0x04 CPU_686
+INSN - cmovne "wlq" cmovcc 0x05 CPU_686
+INSN - cmovnz "wlq" cmovcc 0x05 CPU_686
+INSN - cmovbe "wlq" cmovcc 0x06 CPU_686
+INSN - cmovna "wlq" cmovcc 0x06 CPU_686
+INSN - cmovnbe "wlq" cmovcc 0x07 CPU_686
+INSN - cmova "wlq" cmovcc 0x07 CPU_686
+INSN - cmovs "wlq" cmovcc 0x08 CPU_686
+INSN - cmovns "wlq" cmovcc 0x09 CPU_686
+INSN - cmovp "wlq" cmovcc 0x0A CPU_686
+INSN - cmovpe "wlq" cmovcc 0x0A CPU_686
+INSN - cmovnp "wlq" cmovcc 0x0B CPU_686
+INSN - cmovpo "wlq" cmovcc 0x0B CPU_686
+INSN - cmovl "wlq" cmovcc 0x0C CPU_686
+INSN - cmovnge "wlq" cmovcc 0x0C CPU_686
+INSN - cmovnl "wlq" cmovcc 0x0D CPU_686
+INSN - cmovge "wlq" cmovcc 0x0D CPU_686
+INSN - cmovle "wlq" cmovcc 0x0E CPU_686
+INSN - cmovng "wlq" cmovcc 0x0E CPU_686
+INSN - cmovnle "wlq" cmovcc 0x0F CPU_686
+INSN - cmovg "wlq" cmovcc 0x0F CPU_686
+INSN - fcmovb NONE fcmovcc 0xDAC0 CPU_686|CPU_FPU
+INSN - fcmove NONE fcmovcc 0xDAC8 CPU_686|CPU_FPU
+INSN - fcmovbe NONE fcmovcc 0xDAD0 CPU_686|CPU_FPU
+INSN - fcmovu NONE fcmovcc 0xDAD8 CPU_686|CPU_FPU
+INSN - fcmovnb NONE fcmovcc 0xDBC0 CPU_686|CPU_FPU
+INSN - fcmovne NONE fcmovcc 0xDBC8 CPU_686|CPU_FPU
+INSN - fcmovnbe NONE fcmovcc 0xDBD0 CPU_686|CPU_FPU
+INSN - fcmovnu NONE fcmovcc 0xDBD8 CPU_686|CPU_FPU
+INSN - fcomi NONE fcom2 0xDBF0 CPU_686|CPU_FPU
+INSN - fucomi NONE fcom2 0xDBE8 CPU_686|CPU_FPU
+INSN - fcomip NONE fcom2 0xDFF0 CPU_686|CPU_FPU
+INSN - fucomip NONE fcom2 0xDFE8 CPU_686|CPU_FPU
+# Pentium4 extensions
+INSN - movnti "lq" movnti 0 CPU_P4
+INSN - clflush NONE clflush 0 CPU_P3
+INSN - lfence NONE threebyte 0x0FAEE8 CPU_P3
+INSN - mfence NONE threebyte 0x0FAEF0 CPU_P3
+INSN - pause NONE onebyte_prefix 0xF390 CPU_P4
+# MMX/SSE2 instructions
+INSN - emms NONE twobyte 0x0F77 CPU_MMX
+INSN - movd NONE movd 0 CPU_MMX
+# For GAS movq must use standard mov instruction.
+# For NASM it can use a dedicated instruction.
+INSN gas movq SUF_Q mov 0 CPU_Any
+INSN nasm movq NONE movq 0 CPU_MMX
+INSN - packssdw NONE mmxsse2 0x6B CPU_MMX
+INSN - packsswb NONE mmxsse2 0x63 CPU_MMX
+INSN - packuswb NONE mmxsse2 0x67 CPU_MMX
+INSN - paddb NONE mmxsse2 0xFC CPU_MMX
+INSN - paddw NONE mmxsse2 0xFD CPU_MMX
+INSN - paddd NONE mmxsse2 0xFE CPU_MMX
+INSN - paddq NONE mmxsse2 0xD4 CPU_MMX
+INSN - paddsb NONE mmxsse2 0xEC CPU_MMX
+INSN - paddsw NONE mmxsse2 0xED CPU_MMX
+INSN - paddusb NONE mmxsse2 0xDC CPU_MMX
+INSN - paddusw NONE mmxsse2 0xDD CPU_MMX
+INSN - pand NONE mmxsse2 0xDB CPU_MMX
+INSN - pandn NONE mmxsse2 0xDF CPU_MMX
+INSN - pcmpeqb NONE mmxsse2 0x74 CPU_MMX
+INSN - pcmpeqw NONE mmxsse2 0x75 CPU_MMX
+INSN - pcmpeqd NONE mmxsse2 0x76 CPU_MMX
+INSN - pcmpgtb NONE mmxsse2 0x64 CPU_MMX
+INSN - pcmpgtw NONE mmxsse2 0x65 CPU_MMX
+INSN - pcmpgtd NONE mmxsse2 0x66 CPU_MMX
+INSN - pmaddwd NONE mmxsse2 0xF5 CPU_MMX
+INSN - pmulhw NONE mmxsse2 0xE5 CPU_MMX
+INSN - pmullw NONE mmxsse2 0xD5 CPU_MMX
+INSN - por NONE mmxsse2 0xEB CPU_MMX
+INSN - psllw NONE pshift 0x0671F1 CPU_MMX
+INSN - pslld NONE pshift 0x0672F2 CPU_MMX
+INSN - psllq NONE pshift 0x0673F3 CPU_MMX
+INSN - psraw NONE pshift 0x0471E1 CPU_MMX
+INSN - psrad NONE pshift 0x0472E2 CPU_MMX
+INSN - psrlw NONE pshift 0x0271D1 CPU_MMX
+INSN - psrld NONE pshift 0x0272D2 CPU_MMX
+INSN - psrlq NONE pshift 0x0273D3 CPU_MMX
+INSN - psubb NONE mmxsse2 0xF8 CPU_MMX
+INSN - psubw NONE mmxsse2 0xF9 CPU_MMX
+INSN - psubd NONE mmxsse2 0xFA CPU_MMX
+INSN - psubq NONE mmxsse2 0xFB CPU_MMX
+INSN - psubsb NONE mmxsse2 0xE8 CPU_MMX
+INSN - psubsw NONE mmxsse2 0xE9 CPU_MMX
+INSN - psubusb NONE mmxsse2 0xD8 CPU_MMX
+INSN - psubusw NONE mmxsse2 0xD9 CPU_MMX
+INSN - punpckhbw NONE mmxsse2 0x68 CPU_MMX
+INSN - punpckhwd NONE mmxsse2 0x69 CPU_MMX
+INSN - punpckhdq NONE mmxsse2 0x6A CPU_MMX
+INSN - punpcklbw NONE mmxsse2 0x60 CPU_MMX
+INSN - punpcklwd NONE mmxsse2 0x61 CPU_MMX
+INSN - punpckldq NONE mmxsse2 0x62 CPU_MMX
+INSN - pxor NONE mmxsse2 0xEF CPU_MMX
+# PIII Katmai new instructions / SIMD instructions
+INSN - addps NONE sseps 0x58 CPU_SSE
+INSN - addss NONE ssess 0xF358 CPU_SSE
+INSN - andnps NONE sseps 0x55 CPU_SSE
+INSN - andps NONE sseps 0x54 CPU_SSE
+INSN - cmpeqps NONE ssecmpps 0x00 CPU_SSE
+INSN - cmpeqss NONE ssecmpss 0x00F3 CPU_SSE
+INSN - cmpleps NONE ssecmpps 0x02 CPU_SSE
+INSN - cmpless NONE ssecmpss 0x02F3 CPU_SSE
+INSN - cmpltps NONE ssecmpps 0x01 CPU_SSE
+INSN - cmpltss NONE ssecmpss 0x01F3 CPU_SSE
+INSN - cmpneqps NONE ssecmpps 0x04 CPU_SSE
+INSN - cmpneqss NONE ssecmpss 0x04F3 CPU_SSE
+INSN - cmpnleps NONE ssecmpps 0x06 CPU_SSE
+INSN - cmpnless NONE ssecmpss 0x06F3 CPU_SSE
+INSN - cmpnltps NONE ssecmpps 0x05 CPU_SSE
+INSN - cmpnltss NONE ssecmpss 0x05F3 CPU_SSE
+INSN - cmpordps NONE ssecmpps 0x07 CPU_SSE
+INSN - cmpordss NONE ssecmpss 0x07F3 CPU_SSE
+INSN - cmpunordps NONE ssecmpps 0x03 CPU_SSE
+INSN - cmpunordss NONE ssecmpss 0x03F3 CPU_SSE
+INSN - cmpps NONE ssepsimm 0xC2 CPU_SSE
+INSN - cmpss NONE ssessimm 0xF3C2 CPU_SSE
+INSN - comiss NONE sseps 0x2F CPU_SSE
+INSN - cvtpi2ps NONE cvt_xmm_mm_ps 0x2A CPU_SSE
+INSN - cvtps2pi NONE cvt_mm_xmm64 0x2D CPU_SSE
+INSN - cvtsi2ss "lq" cvt_xmm_rmx 0xF32A CPU_SSE
+INSN - cvtss2si "lq" cvt_rx_xmm32 0xF32D CPU_SSE
+INSN - cvttps2pi NONE cvt_mm_xmm64 0x2C CPU_SSE
+INSN - cvttss2si "lq" cvt_rx_xmm32 0xF32C CPU_SSE
+INSN - divps NONE sseps 0x5E CPU_SSE
+INSN - divss NONE ssess 0xF35E CPU_SSE
+INSN - ldmxcsr NONE ldstmxcsr 0x02 CPU_SSE
+INSN - maskmovq NONE maskmovq 0 CPU_P3|CPU_MMX
+INSN - maxps NONE sseps 0x5F CPU_SSE
+INSN - maxss NONE ssess 0xF35F CPU_SSE
+INSN - minps NONE sseps 0x5D CPU_SSE
+INSN - minss NONE ssess 0xF35D CPU_SSE
+INSN - movaps NONE movaups 0x28 CPU_SSE
+INSN - movhlps NONE movhllhps 0x12 CPU_SSE
+INSN - movhps NONE movhlps 0x16 CPU_SSE
+INSN - movlhps NONE movhllhps 0x16 CPU_SSE
+INSN - movlps NONE movhlps 0x12 CPU_SSE
+INSN - movmskps "lq" movmskps 0 CPU_SSE
+INSN - movntps NONE movntps 0 CPU_SSE
+INSN - movntq NONE movntq 0 CPU_SSE
+INSN - movss NONE movss 0 CPU_SSE
+INSN - movups NONE movaups 0x10 CPU_SSE
+INSN - mulps NONE sseps 0x59 CPU_SSE
+INSN - mulss NONE ssess 0xF359 CPU_SSE
+INSN - orps NONE sseps 0x56 CPU_SSE
+INSN - pavgb NONE mmxsse2 0xE0 CPU_P3|CPU_MMX
+INSN - pavgw NONE mmxsse2 0xE3 CPU_P3|CPU_MMX
+INSN - pextrw "lq" pextrw 0 CPU_P3|CPU_MMX
+INSN - pinsrw "lq" pinsrw 0 CPU_P3|CPU_MMX
+INSN - pmaxsw NONE mmxsse2 0xEE CPU_P3|CPU_MMX
+INSN - pmaxub NONE mmxsse2 0xDE CPU_P3|CPU_MMX
+INSN - pminsw NONE mmxsse2 0xEA CPU_P3|CPU_MMX
+INSN - pminub NONE mmxsse2 0xDA CPU_P3|CPU_MMX
+INSN - pmovmskb "lq" pmovmskb 0 CPU_SSE
+INSN - pmulhuw NONE mmxsse2 0xE4 CPU_P3|CPU_MMX
+INSN - prefetchnta NONE twobytemem 0x000F18 CPU_P3
+INSN - prefetcht0 NONE twobytemem 0x010F18 CPU_P3
+INSN - prefetcht1 NONE twobytemem 0x020F18 CPU_P3
+INSN - prefetcht2 NONE twobytemem 0x030F18 CPU_P3
+INSN - psadbw NONE mmxsse2 0xF6 CPU_P3|CPU_MMX
+INSN - pshufw NONE pshufw 0 CPU_P3|CPU_MMX
+INSN - rcpps NONE sseps 0x53 CPU_SSE
+INSN - rcpss NONE ssess 0xF353 CPU_SSE
+INSN - rsqrtps NONE sseps 0x52 CPU_SSE
+INSN - rsqrtss NONE ssess 0xF352 CPU_SSE
+INSN - sfence NONE threebyte 0x0FAEF8 CPU_P3
+INSN - shufps NONE ssepsimm 0xC6 CPU_SSE
+INSN - sqrtps NONE sseps 0x51 CPU_SSE
+INSN - sqrtss NONE ssess 0xF351 CPU_SSE
+INSN - stmxcsr NONE ldstmxcsr 0x03 CPU_SSE
+INSN - subps NONE sseps 0x5C CPU_SSE
+INSN - subss NONE ssess 0xF35C CPU_SSE
+INSN - ucomiss NONE ssess 0x2E CPU_SSE
+INSN - unpckhps NONE sseps 0x15 CPU_SSE
+INSN - unpcklps NONE sseps 0x14 CPU_SSE
+INSN - xorps NONE sseps 0x57 CPU_SSE
+# SSE2 instructions
+INSN - addpd NONE ssess 0x6658 CPU_SSE2
+INSN - addsd NONE ssess 0xF258 CPU_SSE2
+INSN - andnpd NONE ssess 0x6655 CPU_SSE2
+INSN - andpd NONE ssess 0x6654 CPU_SSE2
+INSN - cmpeqpd NONE ssecmpss 0x0066 CPU_SSE2
+INSN - cmpeqsd NONE ssecmpss 0x00F2 CPU_SSE2
+INSN - cmplepd NONE ssecmpss 0x0266 CPU_SSE2
+INSN - cmplesd NONE ssecmpss 0x02F2 CPU_SSE2
+INSN - cmpltpd NONE ssecmpss 0x0166 CPU_SSE2
+INSN - cmpltsd NONE ssecmpss 0x01F2 CPU_SSE2
+INSN - cmpneqpd NONE ssecmpss 0x0466 CPU_SSE2
+INSN - cmpneqsd NONE ssecmpss 0x04F2 CPU_SSE2
+INSN - cmpnlepd NONE ssecmpss 0x0666 CPU_SSE2
+INSN - cmpnlesd NONE ssecmpss 0x06F2 CPU_SSE2
+INSN - cmpnltpd NONE ssecmpss 0x0566 CPU_SSE2
+INSN - cmpnltsd NONE ssecmpss 0x05F2 CPU_SSE2
+INSN - cmpordpd NONE ssecmpss 0x0766 CPU_SSE2
+INSN - cmpordsd NONE ssecmpss 0x07F2 CPU_SSE2
+INSN - cmpunordpd NONE ssecmpss 0x0366 CPU_SSE2
+INSN - cmpunordsd NONE ssecmpss 0x03F2 CPU_SSE2
+INSN - cmppd NONE ssessimm 0x66C2 CPU_SSE2
+# cmpsd is in string instructions above
+INSN - comisd NONE ssess 0x662F CPU_SSE2
+INSN - cvtpi2pd NONE cvt_xmm_mm_ss 0x662A CPU_SSE2
+INSN - cvtsi2sd "lq" cvt_xmm_rmx 0xF22A CPU_SSE2
+INSN - divpd NONE ssess 0x665E CPU_SSE2
+INSN - divsd NONE ssess 0xF25E CPU_SSE2
+INSN - maxpd NONE ssess 0x665F CPU_SSE2
+INSN - maxsd NONE ssess 0xF25F CPU_SSE2
+INSN - minpd NONE ssess 0x665D CPU_SSE2
+INSN - minsd NONE ssess 0xF25D CPU_SSE2
+INSN - movapd NONE movaupd 0x28 CPU_SSE2
+INSN - movhpd NONE movhlpd 0x16 CPU_SSE2
+INSN - movlpd NONE movhlpd 0x12 CPU_SSE2
+INSN - movmskpd "lq" movmskpd 0 CPU_SSE2
+INSN - movntpd NONE movntpddq 0x2B CPU_SSE2
+INSN - movntdq NONE movntpddq 0xE7 CPU_SSE2
+# movsd is in string instructions above
+INSN - movupd NONE movaupd 0x10 CPU_SSE2
+INSN - mulpd NONE ssess 0x6659 CPU_SSE2
+INSN - mulsd NONE ssess 0xF259 CPU_SSE2
+INSN - orpd NONE ssess 0x6656 CPU_SSE2
+INSN - shufpd NONE ssessimm 0x66C6 CPU_SSE2
+INSN - sqrtpd NONE ssess 0x6651 CPU_SSE2
+INSN - sqrtsd NONE ssess 0xF251 CPU_SSE2
+INSN - subpd NONE ssess 0x665C CPU_SSE2
+INSN - subsd NONE ssess 0xF25C CPU_SSE2
+INSN - ucomisd NONE ssess 0x662E CPU_SSE2
+INSN - unpckhpd NONE ssess 0x6615 CPU_SSE2
+INSN - unpcklpd NONE ssess 0x6614 CPU_SSE2
+INSN - xorpd NONE ssess 0x6657 CPU_SSE2
+INSN - cvtdq2pd NONE cvt_xmm_xmm64_ss 0xF3E6 CPU_SSE2
+INSN - cvtpd2dq NONE ssess 0xF2E6 CPU_SSE2
+INSN - cvtdq2ps NONE sseps 0x5B CPU_SSE2
+INSN - cvtpd2pi NONE cvt_mm_xmm 0x662D CPU_SSE2
+INSN - cvtpd2ps NONE ssess 0x665A CPU_SSE2
+INSN - cvtps2pd NONE cvt_xmm_xmm64_ps 0x5A CPU_SSE2
+INSN - cvtps2dq NONE ssess 0x665B CPU_SSE2
+INSN - cvtsd2si "lq" cvt_rx_xmm64 0xF22D CPU_SSE2
+INSN - cvtsd2ss NONE cvt_xmm_xmm64_ss 0xF25A CPU_SSE2
+# P4 VMX Instructions
+INSN - vmcall NONE threebyte 0x0F01C1 CPU_P4
+INSN - vmlaunch NONE threebyte 0x0F01C2 CPU_P4
+INSN - vmresume NONE threebyte 0x0F01C3 CPU_P4
+INSN - vmxoff NONE threebyte 0x0F01C4 CPU_P4
+INSN - vmread "lq" vmxmemrd 0x0F78 CPU_P4
+INSN - vmwrite "lq" vmxmemwr 0x0F79 CPU_P4
+INSN - vmptrld NONE vmxtwobytemem 0x06C7 CPU_P4
+INSN - vmptrst NONE vmxtwobytemem 0x07C7 CPU_P4
+INSN - vmclear NONE vmxthreebytemem 0x0666C7 CPU_P4
+INSN - vmxon NONE vmxthreebytemem 0x06F3C7 CPU_P4
+INSN - cvtss2sd NONE cvt_xmm_xmm32 0xF35A CPU_SSE2
+INSN - cvttpd2pi NONE cvt_mm_xmm 0x662C CPU_SSE2
+INSN - cvttsd2si "lq" cvt_rx_xmm64 0xF22C CPU_SSE2
+INSN - cvttpd2dq NONE ssess 0x66E6 CPU_SSE2
+INSN - cvttps2dq NONE ssess 0xF35B CPU_SSE2
+INSN - maskmovdqu NONE maskmovdqu 0 CPU_SSE2
+INSN - movdqa NONE movdqau 0x66 CPU_SSE2
+INSN - movdqu NONE movdqau 0xF3 CPU_SSE2
+INSN - movdq2q NONE movdq2q 0 CPU_SSE2
+INSN - movq2dq NONE movq2dq 0 CPU_SSE2
+INSN - pmuludq NONE mmxsse2 0xF4 CPU_SSE2
+INSN - pshufd NONE ssessimm 0x6670 CPU_SSE2
+INSN - pshufhw NONE ssessimm 0xF370 CPU_SSE2
+INSN - pshuflw NONE ssessimm 0xF270 CPU_SSE2
+INSN - pslldq NONE pslrldq 0x07 CPU_SSE2
+INSN - psrldq NONE pslrldq 0x03 CPU_SSE2
+INSN - punpckhqdq NONE ssess 0x666D CPU_SSE2
+INSN - punpcklqdq NONE ssess 0x666C CPU_SSE2
+# SSE3 / PNI Prescott New Instructions instructions
+INSN - addsubpd NONE ssess 0x66D0 CPU_SSE3
+INSN - addsubps NONE ssess 0xF2D0 CPU_SSE3
+INSN - fisttp "lqs" fildstp 0x010001 CPU_SSE3
+INSN gas fisttpll SUF_Q fildstp 0x07 CPU_FPU
+INSN - haddpd NONE ssess 0x667C CPU_SSE3
+INSN - haddps NONE ssess 0xF27C CPU_SSE3
+INSN - hsubpd NONE ssess 0x667D CPU_SSE3
+INSN - hsubps NONE ssess 0xF27D CPU_SSE3
+INSN - lddqu NONE lddqu 0 CPU_SSE3
+INSN - monitor NONE threebyte 0x0F01C8 CPU_SSE3
+INSN - movddup NONE cvt_xmm_xmm64_ss 0xF212 CPU_SSE3
+INSN - movshdup NONE ssess 0xF316 CPU_SSE3
+INSN - movsldup NONE ssess 0xF312 CPU_SSE3
+INSN - mwait NONE threebyte 0x0F01C9 CPU_SSE3
+# AMD 3DNow! instructions
+INSN - prefetch NONE twobytemem 0x000F0D CPU_3DNow
+INSN - prefetchw NONE twobytemem 0x010F0D CPU_3DNow
+INSN - femms NONE twobyte 0x0F0E CPU_3DNow
+INSN - pavgusb NONE now3d 0xBF CPU_3DNow
+INSN - pf2id NONE now3d 0x1D CPU_3DNow
+INSN - pf2iw NONE now3d 0x1C CPU_Athlon|CPU_3DNow
+INSN - pfacc NONE now3d 0xAE CPU_3DNow
+INSN - pfadd NONE now3d 0x9E CPU_3DNow
+INSN - pfcmpeq NONE now3d 0xB0 CPU_3DNow
+INSN - pfcmpge NONE now3d 0x90 CPU_3DNow
+INSN - pfcmpgt NONE now3d 0xA0 CPU_3DNow
+INSN - pfmax NONE now3d 0xA4 CPU_3DNow
+INSN - pfmin NONE now3d 0x94 CPU_3DNow
+INSN - pfmul NONE now3d 0xB4 CPU_3DNow
+INSN - pfnacc NONE now3d 0x8A CPU_Athlon|CPU_3DNow
+INSN - pfpnacc NONE now3d 0x8E CPU_Athlon|CPU_3DNow
+INSN - pfrcp NONE now3d 0x96 CPU_3DNow
+INSN - pfrcpit1 NONE now3d 0xA6 CPU_3DNow
+INSN - pfrcpit2 NONE now3d 0xB6 CPU_3DNow
+INSN - pfrsqit1 NONE now3d 0xA7 CPU_3DNow
+INSN - pfrsqrt NONE now3d 0x97 CPU_3DNow
+INSN - pfsub NONE now3d 0x9A CPU_3DNow
+INSN - pfsubr NONE now3d 0xAA CPU_3DNow
+INSN - pi2fd NONE now3d 0x0D CPU_3DNow
+INSN - pi2fw NONE now3d 0x0C CPU_Athlon|CPU_3DNow
+INSN - pmulhrwa NONE now3d 0xB7 CPU_3DNow
+INSN - pswapd NONE now3d 0xBB CPU_Athlon|CPU_3DNow
+# AMD extensions
+INSN - syscall NONE twobyte 0x0F05 CPU_686|CPU_AMD
+INSN - sysret "lq" twobyte 0x0F07 CPU_686|CPU_AMD|CPU_Priv
+# AMD x86-64 extensions
+INSN - swapgs NONE threebyte 0x0F01F8 CPU_Hammer|CPU_64
+INSN - rdtscp NONE threebyte 0x0F01F9 CPU_686|CPU_AMD|CPU_Priv
+# AMD Pacifica SVM instructions
+INSN - clgi NONE threebyte 0x0F01DD CPU_Hammer|CPU_64|CPU_SVM
+INSN - invlpga NONE invlpga 0 CPU_Hammer|CPU_64|CPU_SVM
+INSN - skinit NONE skinit 0 CPU_Hammer|CPU_64|CPU_SVM
+INSN - stgi NONE threebyte 0x0F01DC CPU_Hammer|CPU_64|CPU_SVM
+INSN - vmload NONE svm_rax 0xDA CPU_Hammer|CPU_64|CPU_SVM
+INSN - vmmcall NONE threebyte 0x0F01D9 CPU_Hammer|CPU_64|CPU_SVM
+INSN - vmrun NONE svm_rax 0xD8 CPU_Hammer|CPU_64|CPU_SVM
+INSN - vmsave NONE svm_rax 0xDB CPU_Hammer|CPU_64|CPU_SVM
+# VIA PadLock instructions
+INSN - xstore NONE padlock 0xC000A7 CPU_PadLock
+INSN - xstorerng NONE padlock 0xC000A7 CPU_PadLock
+INSN - xcryptecb NONE padlock 0xC8F3A7 CPU_PadLock
+INSN - xcryptcbc NONE padlock 0xD0F3A7 CPU_PadLock
+INSN - xcryptctr NONE padlock 0xD8F3A7 CPU_PadLock
+INSN - xcryptcfb NONE padlock 0xE0F3A7 CPU_PadLock
+INSN - xcryptofb NONE padlock 0xE8F3A7 CPU_PadLock
+INSN - montmul NONE padlock 0xC0F3A6 CPU_PadLock
+INSN - xsha1 NONE padlock 0xC8F3A6 CPU_PadLock
+INSN - xsha256 NONE padlock 0xD0F3A6 CPU_PadLock
+# Cyrix MMX instructions
+INSN - paddsiw NONE cyrixmmx 0x51 CPU_Cyrix|CPU_MMX
+INSN - paveb NONE cyrixmmx 0x50 CPU_Cyrix|CPU_MMX
+INSN - pdistib NONE cyrixmmx 0x54 CPU_Cyrix|CPU_MMX
+INSN - pmachriw NONE pmachriw 0 CPU_Cyrix|CPU_MMX
+INSN - pmagw NONE cyrixmmx 0x52 CPU_Cyrix|CPU_MMX
+INSN - pmulhriw NONE cyrixmmx 0x5D CPU_Cyrix|CPU_MMX
+INSN - pmulhrwc NONE cyrixmmx 0x59 CPU_Cyrix|CPU_MMX
+INSN - pmvgezb NONE cyrixmmx 0x5C CPU_Cyrix|CPU_MMX
+INSN - pmvlzb NONE cyrixmmx 0x5B CPU_Cyrix|CPU_MMX
+INSN - pmvnzb NONE cyrixmmx 0x5A CPU_Cyrix|CPU_MMX
+INSN - pmvzb NONE cyrixmmx 0x58 CPU_Cyrix|CPU_MMX
+INSN - psubsiw NONE cyrixmmx 0x55 CPU_Cyrix|CPU_MMX
+# Cyrix extensions
+INSN - rdshr NONE twobyte 0x0F36 CPU_686|CPU_Cyrix|CPU_SMM
+INSN - rsdc NONE rsdc 0 CPU_486|CPU_Cyrix|CPU_SMM
+INSN - rsldt NONE cyrixsmm 0x7B CPU_486|CPU_Cyrix|CPU_SMM
+INSN - rsts NONE cyrixsmm 0x7D CPU_486|CPU_Cyrix|CPU_SMM
+INSN - svdc NONE svdc 0 CPU_486|CPU_Cyrix|CPU_SMM
+INSN - svldt NONE cyrixsmm 0x7A CPU_486|CPU_Cyrix|CPU_SMM
+INSN - svts NONE cyrixsmm 0x7C CPU_486|CPU_Cyrix|CPU_SMM
+INSN - smint NONE twobyte 0x0F38 CPU_686|CPU_Cyrix
+INSN - smintold NONE twobyte 0x0F7E CPU_486|CPU_Cyrix|CPU_Obs
+INSN - wrshr NONE twobyte 0x0F37 CPU_686|CPU_Cyrix|CPU_SMM
+# Obsolete/undocumented instructions
+INSN - fsetpm NONE twobyte 0xDBE4 CPU_286|CPU_FPU|CPU_Obs
+INSN - ibts NONE ibts 0 CPU_386|CPU_Undoc|CPU_Obs
+INSN - loadall NONE twobyte 0x0F07 CPU_386|CPU_Undoc
+INSN - loadall286 NONE twobyte 0x0F05 CPU_286|CPU_Undoc
+INSN - salc NONE onebyte 0x00D6 CPU_Undoc|CPU_Not64
+INSN - smi NONE onebyte 0x00F1 CPU_386|CPU_Undoc
+INSN - umov NONE umov 0 CPU_386|CPU_Undoc
+INSN - xbts NONE xbts 0 CPU_386|CPU_Undoc|CPU_Obs
+
+
+# DEF_CPU parameters:
+# - CPU name
+# - CPU flags to set
+# DEF_CPU_ALIAS parameters:
+# - CPU alias name
+# - CPU base name
+# DEF_CPU_FEATURE parameters:
+# - CPU feature name
+# - CPU flag to set feature name alone or unset ("no" + feature name)
+
+# The standard CPU names /set/ cpu_enabled.
+CPU 8086 CPU_Priv
+CPU 186 CPU_186|CPU_Priv
+CPU_ALIAS 80186 186
+CPU_ALIAS i186 186
+CPU 286 CPU_186|CPU_286|CPU_Priv
+CPU_ALIAS 80286 286
+CPU_ALIAS i286 286
+CPU 386 CPU_186|CPU_286|CPU_386|CPU_SMM|CPU_Prot|CPU_Priv
+CPU_ALIAS 80386 386
+CPU_ALIAS i386 386
+CPU 486 CPU_186|CPU_286|CPU_386|CPU_486|CPU_FPU|CPU_SMM|\
+ CPU_Prot|CPU_Priv
+CPU_ALIAS 80486 486
+CPU_ALIAS i486 486
+CPU 586 CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_FPU|\
+ CPU_SMM|CPU_Prot|CPU_Priv
+CPU_ALIAS i586 586
+CPU_ALIAS pentium 586
+CPU_ALIAS p5 586
+CPU 686 CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
+ CPU_FPU|CPU_SMM|CPU_Prot|CPU_Priv
+CPU_ALIAS i686 686
+CPU_ALIAS p6 686
+CPU_ALIAS ppro 686
+CPU_ALIAS pentiumpro 686
+CPU p2 CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
+ CPU_FPU|CPU_MMX|CPU_SMM|CPU_Prot|CPU_Priv
+CPU_ALIAS pentium2 p2
+CPU_ALIAS pentium-2 p2
+CPU_ALIAS pentiumii p2
+CPU_ALIAS pentium-ii p2
+CPU p3 CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
+ CPU_P3|CPU_FPU|CPU_MMX|CPU_SSE|CPU_SMM|CPU_Prot|\
+ CPU_Priv
+CPU_ALIAS pentium3 p3
+CPU_ALIAS pentium-3 p3
+CPU_ALIAS pentiumiii p3
+CPU_ALIAS pentium-iii p3
+CPU_ALIAS katmai p3
+CPU p4 CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
+ CPU_P3|CPU_P4|CPU_FPU|CPU_MMX|CPU_SSE|CPU_SSE2|\
+ CPU_SMM|CPU_Prot|CPU_Priv
+CPU_ALIAS pentium4 p4
+CPU_ALIAS pentium-4 p4
+CPU_ALIAS pentiumiv p4
+CPU_ALIAS pentium-iv p4
+CPU_ALIAS williamette p4
+CPU ia64 CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
+ CPU_P3|CPU_P4|CPU_IA64|CPU_FPU|CPU_MMX|CPU_SSE|\
+ CPU_SSE2|CPU_SMM|CPU_Prot|CPU_Priv
+CPU_ALIAS ia-64 ia64
+CPU_ALIAS itanium ia64
+CPU k6 CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
+ CPU_K6|CPU_FPU|CPU_MMX|CPU_3DNow|CPU_SMM|CPU_Prot|\
+ CPU_Priv
+CPU k7 CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
+ CPU_K6|CPU_Athlon|CPU_FPU|CPU_MMX|CPU_SSE|CPU_3DNow|\
+ CPU_SMM|CPU_Prot|CPU_Priv
+CPU_ALIAS athlon k7
+CPU hammer CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
+ CPU_K6|CPU_Athlon|CPU_Hammer|CPU_FPU|CPU_MMX|\
+ CPU_SSE|CPU_SSE2|CPU_3DNow|CPU_SMM|CPU_Prot|\
+ CPU_Priv
+CPU_ALIAS sledgehammer hammer
+CPU_ALIAS opteron hammer
+CPU_ALIAS athlon64 hammer
+CPU_ALIAS athlon-64 hammer
+CPU prescott CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
+ CPU_K6|CPU_Athlon|CPU_Hammer|CPU_FPU|CPU_MMX|\
+ CPU_SSE|CPU_SSE2|CPU_SSE3|CPU_3DNow|CPU_SMM|\
+ CPU_Prot|CPU_Priv
+
+# Features have "no" versions to disable them, and only set/reset the
+# specific feature being changed. All other bits are left alone.
+
+CPU_FEATURE fpu CPU_FPU
+CPU_FEATURE mmx CPU_MMX
+CPU_FEATURE sse CPU_SSE
+CPU_FEATURE sse2 CPU_SSE2
+CPU_FEATURE sse3 CPU_SSE3
+#CPU_FEATURE pni CPU_PNI
+CPU_FEATURE 3dnow CPU_3DNow
+CPU_FEATURE cyrix CPU_Cyrix
+CPU_FEATURE amd CPU_AMD
+CPU_FEATURE smm CPU_SMM
+CPU_FEATURE prot CPU_Prot
+CPU_FEATURE undoc CPU_Undoc
+CPU_FEATURE obs CPU_Obs
+CPU_FEATURE priv CPU_Priv
+CPU_FEATURE svm CPU_SVM
+CPU_FEATURE padlock CPU_PadLock
+
+
+# TARGETMOD parameters:
+# - target modifier name
+# - modifier to return
+
+TARGETMOD near X86_NEAR
+TARGETMOD short X86_SHORT
+TARGETMOD far X86_FAR
+TARGETMOD to X86_TO
+
+
+# PREFIX parameters:
+# - parser
+# - prefix name
+# - prefix type
+# - prefix value
+
+# operand size overrides
+PREFIX nasm o16 X86_OPERSIZE 16
+PREFIX gas data16 X86_OPERSIZE 16
+PREFIX gas word X86_OPERSIZE 16
+PREFIX nasm o32 X86_OPERSIZE 32
+PREFIX gas data32 X86_OPERSIZE 32
+PREFIX gas dword X86_OPERSIZE 32
+PREFIX nasm o64 X86_OPERSIZE 64
+PREFIX gas data64 X86_OPERSIZE 64
+PREFIX gas qword X86_OPERSIZE 64
+
+# address size overrides
+PREFIX nasm a16 X86_ADDRSIZE 16
+PREFIX gas addr16 X86_ADDRSIZE 16
+PREFIX gas aword X86_ADDRSIZE 16
+PREFIX nasm a32 X86_ADDRSIZE 32
+PREFIX gas addr32 X86_ADDRSIZE 32
+PREFIX gas adword X86_ADDRSIZE 32
+PREFIX nasm a64 X86_ADDRSIZE 64
+PREFIX gas addr64 X86_ADDRSIZE 64
+PREFIX gas aqword X86_ADDRSIZE 64
+
+# instruction prefixes
+PREFIX - lock X86_LOCKREP 0xF0
+PREFIX - repne X86_LOCKREP 0xF2
+PREFIX - repnz X86_LOCKREP 0xF2
+PREFIX - rep X86_LOCKREP 0xF3
+PREFIX - repe X86_LOCKREP 0xF3
+PREFIX - repz X86_LOCKREP 0xF3
+
+# other prefixes, limited to GAS-only at the moment
+# Hint taken/not taken for jumps
+PREFIX gas ht X86_SEGREG 0x3E
+PREFIX gas hnt X86_SEGREG 0x2E
+
+# REX byte explicit prefixes
+PREFIX gas rex X86_REX 0x40
+PREFIX gas rexz X86_REX 0x41
+PREFIX gas rexy X86_REX 0x42
+PREFIX gas rexyz X86_REX 0x43
+PREFIX gas rexx X86_REX 0x44
+PREFIX gas rexxz X86_REX 0x45
+PREFIX gas rexxy X86_REX 0x46
+PREFIX gas rexxyz X86_REX 0x47
+PREFIX gas rex64 X86_REX 0x48
+PREFIX gas rex64z X86_REX 0x49
+PREFIX gas rex64y X86_REX 0x4A
+PREFIX gas rex64yz X86_REX 0x4B
+PREFIX gas rex64x X86_REX 0x4C
+PREFIX gas rex64xz X86_REX 0x4D
+PREFIX gas rex64xy X86_REX 0x4E
+PREFIX gas rex64xyz X86_REX 0x4F
+
+
+# REG parameters:
+# - register name
+# - register type
+# - register index
+# - required BITS setting (0 for any)
+#
+# REGGROUP parameters:
+# - register group name
+# - register group type
+#
+# SEGREG parameters:
+# - segment register name
+# - prefix encoding
+# - register encoding
+# - BITS in which the segment is ignored
+
+# control, debug, and test registers
+REG cr0 X86_CRREG 0 0
+REG cr2 X86_CRREG 2 0
+REG cr3 X86_CRREG 3 0
+REG cr4 X86_CRREG 4 0
+REG cr8 X86_CRREG 8 64
+
+REG dr0 X86_DRREG 0 0
+REG dr1 X86_DRREG 1 0
+REG dr2 X86_DRREG 2 0
+REG dr3 X86_DRREG 3 0
+REG dr4 X86_DRREG 4 0
+REG dr5 X86_DRREG 5 0
+REG dr6 X86_DRREG 6 0
+REG dr7 X86_DRREG 7 0
+
+REG tr0 X86_TRREG 0 0
+REG tr1 X86_TRREG 1 0
+REG tr2 X86_TRREG 2 0
+REG tr3 X86_TRREG 3 0
+REG tr4 X86_TRREG 4 0
+REG tr5 X86_TRREG 5 0
+REG tr6 X86_TRREG 6 0
+REG tr7 X86_TRREG 7 0
+
+# floating point, MMX, and SSE/SSE2 registers
+REG st0 X86_FPUREG 0 0
+REG st1 X86_FPUREG 1 0
+REG st2 X86_FPUREG 2 0
+REG st3 X86_FPUREG 3 0
+REG st4 X86_FPUREG 4 0
+REG st5 X86_FPUREG 5 0
+REG st6 X86_FPUREG 6 0
+REG st7 X86_FPUREG 7 0
+
+REG mm0 X86_MMXREG 0 0
+REG mm1 X86_MMXREG 1 0
+REG mm2 X86_MMXREG 2 0
+REG mm3 X86_MMXREG 3 0
+REG mm4 X86_MMXREG 4 0
+REG mm5 X86_MMXREG 5 0
+REG mm6 X86_MMXREG 6 0
+REG mm7 X86_MMXREG 7 0
+
+REG xmm0 X86_XMMREG 0 0
+REG xmm1 X86_XMMREG 1 0
+REG xmm2 X86_XMMREG 2 0
+REG xmm3 X86_XMMREG 3 0
+REG xmm4 X86_XMMREG 4 0
+REG xmm5 X86_XMMREG 5 0
+REG xmm6 X86_XMMREG 6 0
+REG xmm7 X86_XMMREG 7 0
+REG xmm8 X86_XMMREG 8 64
+REG xmm9 X86_XMMREG 9 64
+REG xmm10 X86_XMMREG 10 64
+REG xmm11 X86_XMMREG 11 64
+REG xmm12 X86_XMMREG 12 64
+REG xmm13 X86_XMMREG 13 64
+REG xmm14 X86_XMMREG 14 64
+REG xmm15 X86_XMMREG 15 64
+
+# integer registers
+REG rax X86_REG64 0 64
+REG rcx X86_REG64 1 64
+REG rdx X86_REG64 2 64
+REG rbx X86_REG64 3 64
+REG rsp X86_REG64 4 64
+REG rbp X86_REG64 5 64
+REG rsi X86_REG64 6 64
+REG rdi X86_REG64 7 64
+REG r8 X86_REG64 8 64
+REG r9 X86_REG64 9 64
+REG r10 X86_REG64 10 64
+REG r11 X86_REG64 11 64
+REG r12 X86_REG64 12 64
+REG r13 X86_REG64 13 64
+REG r14 X86_REG64 14 64
+REG r15 X86_REG64 15 64
+
+REG eax X86_REG32 0 0
+REG ecx X86_REG32 1 0
+REG edx X86_REG32 2 0
+REG ebx X86_REG32 3 0
+REG esp X86_REG32 4 0
+REG ebp X86_REG32 5 0
+REG esi X86_REG32 6 0
+REG edi X86_REG32 7 0
+REG r8d X86_REG32 8 64
+REG r9d X86_REG32 9 64
+REG r10d X86_REG32 10 64
+REG r11d X86_REG32 11 64
+REG r12d X86_REG32 12 64
+REG r13d X86_REG32 13 64
+REG r14d X86_REG32 14 64
+REG r15d X86_REG32 15 64
+
+REG ax X86_REG16 0 0
+REG cx X86_REG16 1 0
+REG dx X86_REG16 2 0
+REG bx X86_REG16 3 0
+REG sp X86_REG16 4 0
+REG bp X86_REG16 5 0
+REG si X86_REG16 6 0
+REG di X86_REG16 7 0
+REG r8w X86_REG16 8 64
+REG r9w X86_REG16 9 64
+REG r10w X86_REG16 10 64
+REG r11w X86_REG16 11 64
+REG r12w X86_REG16 12 64
+REG r13w X86_REG16 13 64
+REG r14w X86_REG16 14 64
+REG r15w X86_REG16 15 64
+
+REG al X86_REG8 0 0
+REG cl X86_REG8 1 0
+REG dl X86_REG8 2 0
+REG bl X86_REG8 3 0
+REG ah X86_REG8 4 0
+REG ch X86_REG8 5 0
+REG dh X86_REG8 6 0
+REG bh X86_REG8 7 0
+REG r8b X86_REG8 8 64
+REG r9b X86_REG8 9 64
+REG r10b X86_REG8 10 64
+REG r11b X86_REG8 11 64
+REG r12b X86_REG8 12 64
+REG r13b X86_REG8 13 64
+REG r14b X86_REG8 14 64
+REG r15b X86_REG8 15 64
+
+REG spl X86_REG8X 4 64
+REG bpl X86_REG8X 5 64
+REG sil X86_REG8X 6 64
+REG dil X86_REG8X 7 64
+
+REG rip X86_RIP 0 64
+
+# floating point, MMX, and SSE/SSE2 registers
+REGGROUP st X86_FPUREG
+REGGROUP mm X86_MMXREG
+REGGROUP xmm X86_XMMREG
+
+# segment registers
+SEGREG es 0x26 0x00 64
+SEGREG cs 0x2e 0x01 0
+SEGREG ss 0x36 0x02 64
+SEGREG ds 0x3e 0x03 64
+SEGREG fs 0x64 0x04 0
+SEGREG gs 0x65 0x05 0
+
[%][a-zA-Z0-9]+ {
savech = s->tok[TOKLEN];
s->tok[TOKLEN] = '\0';
- if (yasm_arch_parse_check_reg(parser_gas->arch, lvalp->arch_data,
- s->tok+1, cur_line)) {
- s->tok[TOKLEN] = savech;
- RETURN(REG);
- }
- if (yasm_arch_parse_check_reggroup(parser_gas->arch,
- lvalp->arch_data, s->tok+1,
- cur_line)) {
- s->tok[TOKLEN] = savech;
- RETURN(REGGROUP);
- }
- if (yasm_arch_parse_check_segreg(parser_gas->arch,
- lvalp->arch_data, s->tok+1,
- cur_line)) {
- s->tok[TOKLEN] = savech;
- RETURN(SEGREG);
+ switch (yasm_arch_parse_check_regtmod
+ (parser_gas->arch, lvalp->arch_data, s->tok+1, TOKLEN-1,
+ cur_line)) {
+ case YASM_ARCH_REG:
+ s->tok[TOKLEN] = savech;
+ RETURN(REG);
+ case YASM_ARCH_REGGROUP:
+ s->tok[TOKLEN] = savech;
+ RETURN(REGGROUP);
+ case YASM_ARCH_SEGREG:
+ s->tok[TOKLEN] = savech;
+ RETURN(SEGREG);
+ default:
+ break;
}
yasm__error(cur_line, N_("Unrecognized register name `%s'"),
s->tok);
if (parser_gas->state != INSTDIR) {
savech = s->tok[TOKLEN];
s->tok[TOKLEN] = '\0';
- if (yasm_arch_parse_check_insn(parser_gas->arch,
- lvalp->arch_data, s->tok,
- cur_line)) {
- s->tok[TOKLEN] = savech;
- parser_gas->state = INSTDIR;
- RETURN(INSN);
- }
- if (yasm_arch_parse_check_prefix(parser_gas->arch,
- lvalp->arch_data, s->tok,
- cur_line)) {
- s->tok[TOKLEN] = savech;
- RETURN(PREFIX);
+ switch (yasm_arch_parse_check_insnprefix
+ (parser_gas->arch, lvalp->arch_data, s->tok, TOKLEN,
+ cur_line)) {
+ case YASM_ARCH_INSN:
+ s->tok[TOKLEN] = savech;
+ parser_gas->state = INSTDIR;
+ RETURN(INSN);
+ case YASM_ARCH_PREFIX:
+ s->tok[TOKLEN] = savech;
+ RETURN(PREFIX);
+ default:
+ s->tok[TOKLEN] = savech;
}
- s->tok[TOKLEN] = savech;
}
/* Just an identifier, return as such. */
lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN);
} else if (yasm__strcasecmp(name, "cpu") == 0) {
yasm_vps_foreach(vp, valparams) {
if (vp->val)
- yasm_arch_parse_cpu(parser_nasm->arch, vp->val, line);
+ yasm_arch_parse_cpu(parser_nasm->arch, vp->val,
+ strlen(vp->val), line);
else if (vp->param) {
const yasm_intnum *intcpu;
intcpu = yasm_expr_get_intnum(&vp->param, NULL);
else {
char strcpu[16];
sprintf(strcpu, "%lu", yasm_intnum_get_uint(intcpu));
- yasm_arch_parse_cpu(parser_nasm->arch, strcpu, line);
+ yasm_arch_parse_cpu(parser_nasm->arch, strcpu,
+ strlen(strcpu), line);
}
}
}
DIRECTIVE,
DIRECTIVE2,
LINECHG,
- LINECHG2
+ LINECHG2,
+ INSTRUCTION
} state;
} yasm_parser_nasm;
[a-zA-Z_?][a-zA-Z0-9_$#@~.?]* {
savech = s->tok[TOKLEN];
s->tok[TOKLEN] = '\0';
- if (yasm_arch_parse_check_reg(parser_nasm->arch, lvalp->arch_data,
- s->tok, cur_line)) {
- s->tok[TOKLEN] = savech;
- RETURN(REG);
+ if (parser_nasm->state != INSTRUCTION)
+ switch (yasm_arch_parse_check_insnprefix
+ (parser_nasm->arch, lvalp->arch_data, s->tok, TOKLEN,
+ cur_line)) {
+ case YASM_ARCH_INSN:
+ parser_nasm->state = INSTRUCTION;
+ s->tok[TOKLEN] = savech;
+ RETURN(INSN);
+ case YASM_ARCH_PREFIX:
+ s->tok[TOKLEN] = savech;
+ RETURN(PREFIX);
+ default:
+ break;
+ }
+ switch (yasm_arch_parse_check_regtmod
+ (parser_nasm->arch, lvalp->arch_data, s->tok, TOKLEN,
+ cur_line)) {
+ case YASM_ARCH_REG:
+ s->tok[TOKLEN] = savech;
+ RETURN(REG);
+ case YASM_ARCH_SEGREG:
+ s->tok[TOKLEN] = savech;
+ RETURN(SEGREG);
+ case YASM_ARCH_TARGETMOD:
+ s->tok[TOKLEN] = savech;
+ RETURN(TARGETMOD);
+ default:
+ s->tok[TOKLEN] = savech;
}
- if (yasm_arch_parse_check_insn(parser_nasm->arch, lvalp->arch_data,
- s->tok, cur_line)) {
- s->tok[TOKLEN] = savech;
- RETURN(INSN);
- }
- if (yasm_arch_parse_check_segreg(parser_nasm->arch,
- lvalp->arch_data, s->tok,
- cur_line)) {
- s->tok[TOKLEN] = savech;
- RETURN(SEGREG);
- }
- if (yasm_arch_parse_check_prefix(parser_nasm->arch,
- lvalp->arch_data, s->tok,
- cur_line)) {
- s->tok[TOKLEN] = savech;
- RETURN(PREFIX);
- }
- if (yasm_arch_parse_check_targetmod(parser_nasm->arch,
- lvalp->arch_data, s->tok,
- cur_line)) {
- s->tok[TOKLEN] = savech;
- RETURN(TARGETMOD);
- }
- s->tok[TOKLEN] = savech;
/* Just an identifier, return as such. */
lvalp->str_val = yasm__xstrndup(s->tok, TOKLEN);
RETURN(ID);
frontends/yasm/yasm-options.c
frontends/yasm/yasm.c
+gas-bison.c
+gas-token.c
lc3bid.c
libyasm/bitvect.c
libyasm/bytecode.c
libyasm/floatnum.c
libyasm/hamt.c
libyasm/intnum.c
-libyasm/linemgr.c
libyasm/section.c
libyasm/symrec.c
libyasm/xmalloc.c
modules/arch/x86/x86arch.c
modules/arch/x86/x86bc.c
modules/arch/x86/x86expr.c
+modules/arch/x86/x86id.c
+modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c
+modules/dbgfmts/dwarf2/dwarf2-info.c
+modules/dbgfmts/dwarf2/dwarf2-line.c
+modules/dbgfmts/stabs/stabs-dbgfmt.c
+modules/listfmts/nasm/nasm-listfmt.c
modules/objfmts/bin/bin-objfmt.c
modules/objfmts/coff/coff-objfmt.c
modules/objfmts/dbg/dbg-objfmt.c
+modules/objfmts/elf/elf-objfmt.c
+modules/objfmts/elf/elf-x86-amd64.c
+modules/objfmts/elf/elf-x86-x86.c
+modules/objfmts/elf/elf.c
+modules/objfmts/xdf/xdf-objfmt.c
modules/optimizers/basic/basic-optimizer.c
+modules/parsers/gas/gas-parser.c
modules/preprocs/nasm/nasm-pp.c
-modules/preprocs/nasm/nasm-preproc.c
modules/preprocs/raw/raw-preproc.c
nasm-bison.c
nasm-token.c
-x86id.c
# $Id$
EXTRA_DIST += tools/re2c/Makefile.inc
+EXTRA_DIST += tools/gap/Makefile.inc
include tools/re2c/Makefile.inc
+include tools/gap/Makefile.inc
--- /dev/null
+# $Id$
+
+# These utility programs have to be built for BUILD host in cross-build.
+# This makes things rather non-standard automake
+
+noinst_PROGRAMS += gap
+
+gap_SOURCES =
+EXTRA_DIST += tools/gap/gap.c
+EXTRA_DIST += tools/gap/perfect.c
+EXTRA_DIST += tools/gap/perfect.h
+EXTRA_DIST += tools/gap/standard.h
+gap_LDADD = gap.$(OBJEXT)
+gap_LDADD += gap-perfect.$(OBJEXT)
+gap_LDADD += gap-phash.$(OBJEXT)
+gap_LDADD += gap-hamt.$(OBJEXT)
+gap_LDADD += gap-xmalloc.$(OBJEXT)
+gap_LDADD += gap-xstrdup.$(OBJEXT)
+gap_LINK = $(CCLD_FOR_BUILD) -o $@
+
+gap.$(OBJEXT): tools/gap/gap.c
+ $(CC_FOR_BUILD) $(DEFAULT_INCLUDES) $(INCLUDES) -g -c -o $@ `test -f tools/gap/gap.c || echo '$(srcdir)/'`tools/gap/gap.c
+
+gap-perfect.$(OBJEXT): tools/gap/perfect.c
+ $(CC_FOR_BUILD) $(DEFAULT_INCLUDES) $(INCLUDES) -g -c -o $@ `test -f tools/gap/perfect.c || echo '$(srcdir)/'`tools/gap/perfect.c
+
+gap-phash.$(OBJEXT): libyasm/phash.c
+ $(CC_FOR_BUILD) $(DEFAULT_INCLUDES) $(INCLUDES) -g -c -o $@ `test -f libyasm/phash.c || echo '$(srcdir)/'`libyasm/phash.c
+
+gap-hamt.$(OBJEXT): libyasm/hamt.c
+ $(CC_FOR_BUILD) $(DEFAULT_INCLUDES) $(INCLUDES) -g -c -o $@ `test -f libyasm/hamt.c || echo '$(srcdir)/'`libyasm/hamt.c
+
+gap-xmalloc.$(OBJEXT): libyasm/xmalloc.c
+ $(CC_FOR_BUILD) $(DEFAULT_INCLUDES) $(INCLUDES) -g -c -o $@ `test -f libyasm/xmalloc.c || echo '$(srcdir)/'`libyasm/xmalloc.c
+
+gap-xstrdup.$(OBJEXT): libyasm/xstrdup.c
+ $(CC_FOR_BUILD) $(DEFAULT_INCLUDES) $(INCLUDES) -g -c -o $@ `test -f libyasm/xstrdup.c || echo '$(srcdir)/'`libyasm/xstrdup.c
+
--- /dev/null
+/* $Id$
+ *
+ * Generate Arch Parser (GAP): generates ARCHparse.c from ARCHparse.gap.
+ *
+ * Copyright (C) 2006 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <string.h>
+#include "tools/gap/perfect.h"
+#include "libyasm/compat-queue.h"
+#include "libyasm/coretype.h"
+#include "libyasm/hamt.h"
+
+typedef STAILQ_HEAD(slist, sval) slist;
+typedef struct sval {
+ STAILQ_ENTRY(sval) link;
+ char *str;
+} sval;
+
+typedef struct dir {
+ char *name;
+ const char *func;
+ slist args;
+} dir;
+
+typedef STAILQ_HEAD(dir_byp_list, dir_byp) dir_byp_list;
+typedef struct dir_byp {
+ STAILQ_ENTRY(dir_byp) link;
+ /*@null@*/ char *parser;
+ HAMT *dirs;
+} dir_byp;
+
+typedef enum {
+ ARCH = 0,
+ PARSERS,
+ INSN,
+ CPU,
+ CPU_ALIAS,
+ CPU_FEATURE,
+ TARGETMOD,
+ PREFIX,
+ REG,
+ REGGROUP,
+ SEGREG,
+ NUM_DIRS
+} dir_type;
+
+typedef struct {
+ void (*parse_insn) (void); /* arch-specific parse_insn */
+ int multi_parser[NUM_DIRS]; /* whether it has an initial parser field */
+} arch_handler;
+
+static void x86_parse_insn(void);
+static const arch_handler arch_x86 = {
+ x86_parse_insn,
+ {0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0}
+};
+
+static struct {
+ const char *name;
+ const arch_handler *arch;
+} archs[] = {
+ {"x86", &arch_x86},
+};
+
+static char line[1024];
+static unsigned int cur_line = 0, next_line = 1;
+static int errors = 0;
+static const arch_handler *arch = NULL;
+
+/* Lists of directives, keyed by parser name */
+static dir_byp_list insnprefix_byp;
+static dir_byp_list cpu_byp;
+static dir_byp_list regtmod_byp;
+
+static void
+report_error(const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%u: ", cur_line);
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+ errors++;
+}
+
+void
+yasm__fatal(const char *message, ...)
+{
+ abort();
+}
+
+static void
+hamt_error(const char *file, unsigned int line, const char *message)
+{
+ abort();
+}
+
+void
+dup_slist(slist *out, slist *in)
+{
+ sval *sv;
+
+ STAILQ_INIT(out);
+ STAILQ_FOREACH(sv, in, link) {
+ sval *nsv = yasm_xmalloc(sizeof(sval));
+ nsv->str = yasm__xstrdup(sv->str);
+ STAILQ_INSERT_TAIL(out, nsv, link);
+ }
+}
+
+dir *
+dup_dir(dir *in)
+{
+ dir *out = yasm_xmalloc(sizeof(dir));
+ out->name = yasm__xstrdup(in->name);
+ out->func = in->func;
+ dup_slist(&out->args, &in->args);
+ return out;
+}
+
+static HAMT *
+get_dirs(dir_byp_list *byp, /*@null@*/ const char *parser)
+{
+ HAMT *found = NULL;
+ dir_byp *db;
+
+ if (STAILQ_EMPTY(byp)) {
+ report_error("PARSERS not yet specified");
+ return NULL;
+ }
+
+ STAILQ_FOREACH(db, byp, link) {
+ if ((!parser && !db->parser) ||
+ (parser && db->parser && strcmp(parser, db->parser) == 0)) {
+ found = db->dirs;
+ break;
+ }
+ }
+
+ return found;
+}
+
+/* Add a keyword/data to a slist of slist keyed by parser name.
+ * Returns nonzero on error.
+ */
+static int
+add_dir(dir_byp_list *byp, /*@null@*/ const char *parser, dir *d)
+{
+ HAMT *found = get_dirs(byp, parser);
+ dir *new;
+ int replace;
+
+ if (found) {
+ replace = 0;
+ new = HAMT_insert(found, d->name, d, &replace, free);
+ if (new != d) {
+ report_error("duplicate `%s'", d->name);
+ return 1;
+ }
+ return 0;
+ } else if (!parser) {
+ /* Add separately to all */
+ dir_byp *db;
+ int first = 1;
+ STAILQ_FOREACH(db, byp, link) {
+ if (!first)
+ d = dup_dir(d);
+ first = 0;
+ replace = 0;
+ new = HAMT_insert(db->dirs, d->name, d, &replace, free);
+ if (new != d) {
+ report_error("duplicate `%s'", d->name);
+ return 1;
+ }
+ }
+ return 0;
+ } else {
+ report_error("parser not found");
+ return 1;
+ }
+}
+
+static char *
+check_parser(dir_type type)
+{
+ char *parser = NULL;
+
+ if (arch->multi_parser[type]) {
+ parser = strtok(NULL, " \t\n");
+ if (strcmp(parser, "-") == 0)
+ parser = NULL;
+ }
+
+ return parser;
+}
+
+static void
+parse_args(slist *args)
+{
+ char *tok;
+ sval *sv;
+
+ STAILQ_INIT(args);
+
+ tok = strtok(NULL, " \t\n");
+ if (!tok) {
+ report_error("no args");
+ return;
+ }
+
+ while (tok) {
+ sv = yasm_xmalloc(sizeof(sval));
+ sv->str = yasm__xstrdup(tok);
+ STAILQ_INSERT_TAIL(args, sv, link);
+ tok = strtok(NULL, " \t\n");
+ }
+}
+
+static dir *
+parse_generic(dir_type type, const char *func, dir_byp_list *byp)
+{
+ char *parser = check_parser(type);
+ char *name = strtok(NULL, " \t\n");
+ dir *d = yasm_xmalloc(sizeof(dir));
+
+ d->name = yasm__xstrdup(name);
+ d->func = func;
+ parse_args(&d->args);
+
+ add_dir(byp, parser, d);
+ return d;
+}
+
+static void
+parse_arch(void)
+{
+ int i;
+ int found = 0;
+ char *tok = strtok(NULL, " \t\n");
+
+ if (!tok) {
+ report_error("ARCH requires an operand");
+ return;
+ }
+ for (i=0; i<sizeof(archs)/sizeof(archs[0]); i++) {
+ if (strcmp(archs[i].name, tok) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ report_error("unrecognized ARCH");
+ return;
+ }
+
+ arch = archs[i].arch;
+}
+
+static void
+parse_parsers(void)
+{
+ dir_byp *db;
+ char *tok;
+
+ if (!arch) {
+ report_error("ARCH not specified before PARSERS");
+ return;
+ }
+
+ tok = strtok(NULL, " \t\n");
+ if (!tok) {
+ report_error("no PARSERS parameter");
+ return;
+ }
+
+ while (tok) {
+ /* Insert into each slist of slist if broken out by parser */
+ if (arch->multi_parser[INSN] || arch->multi_parser[PREFIX]) {
+ db = yasm_xmalloc(sizeof(dir_byp));
+ db->parser = yasm__xstrdup(tok);
+ db->dirs = HAMT_create(hamt_error);
+
+ STAILQ_INSERT_TAIL(&insnprefix_byp, db, link);
+ }
+ if (arch->multi_parser[CPU] || arch->multi_parser[CPU_ALIAS] ||
+ arch->multi_parser[CPU_FEATURE]) {
+ db = yasm_xmalloc(sizeof(dir_byp));
+ db->parser = yasm__xstrdup(tok);
+ db->dirs = HAMT_create(hamt_error);
+
+ STAILQ_INSERT_TAIL(&cpu_byp, db, link);
+ }
+ if (arch->multi_parser[TARGETMOD] || arch->multi_parser[REG] ||
+ arch->multi_parser[REGGROUP] || arch->multi_parser[SEGREG]) {
+ db = yasm_xmalloc(sizeof(dir_byp));
+ db->parser = yasm__xstrdup(tok);
+ db->dirs = HAMT_create(hamt_error);
+
+ STAILQ_INSERT_TAIL(®tmod_byp, db, link);
+ }
+ tok = strtok(NULL, " \t\n");
+ }
+
+ /* Add NULL (global) versions if not already created */
+ if (STAILQ_EMPTY(&insnprefix_byp)) {
+ db = yasm_xmalloc(sizeof(dir_byp));
+ db->parser = NULL;
+ db->dirs = HAMT_create(hamt_error);
+
+ STAILQ_INSERT_TAIL(&insnprefix_byp, db, link);
+ }
+ if (STAILQ_EMPTY(&cpu_byp)) {
+ db = yasm_xmalloc(sizeof(dir_byp));
+ db->parser = NULL;
+ db->dirs = HAMT_create(hamt_error);
+
+ STAILQ_INSERT_TAIL(&cpu_byp, db, link);
+ }
+ if (STAILQ_EMPTY(®tmod_byp)) {
+ db = yasm_xmalloc(sizeof(dir_byp));
+ db->parser = NULL;
+ db->dirs = HAMT_create(hamt_error);
+
+ STAILQ_INSERT_TAIL(®tmod_byp, db, link);
+ }
+}
+
+static void
+x86_parse_insn(void)
+{
+ char *parser = check_parser(INSN);
+ char *bname = strtok(NULL, " \t\n");
+ char *suffix = strtok(NULL, " \t\n");
+ dir *d;
+ slist args;
+ sval *sv;
+
+ if (!suffix) {
+ report_error("INSN requires suffix");
+ return;
+ }
+
+ /* save the remainder of args */
+ parse_args(&args);
+
+ if (suffix[0] != '"') {
+ /* Just one instruction to generate */
+ sv = yasm_xmalloc(sizeof(sval));
+ sv->str = yasm__xstrdup(suffix);
+ STAILQ_INSERT_HEAD(&args, sv, link);
+
+ d = yasm_xmalloc(sizeof(dir));
+ d->name = yasm__xstrdup(bname);
+ d->func = "INSN";
+ d->args = args;
+ add_dir(&insnprefix_byp, parser, d);
+ } else {
+ /* Need to generate with suffixes for gas */
+ char *p;
+ char sufstr[6];
+ size_t bnamelen = strlen(bname);
+
+ strcpy(sufstr, "SUF_X");
+
+ for (p = &suffix[1]; *p != '"'; p++) {
+ sufstr[4] = toupper(*p);
+
+ d = yasm_xmalloc(sizeof(dir));
+
+ d->name = yasm_xmalloc(bnamelen+2);
+ strcpy(d->name, bname);
+ d->name[bnamelen] = tolower(*p);
+ d->name[bnamelen+1] = '\0';
+
+ d->func = "INSN";
+ dup_slist(&d->args, &args);
+
+ sv = yasm_xmalloc(sizeof(sval));
+ sv->str = yasm__xstrdup(sufstr);
+ STAILQ_INSERT_HEAD(&d->args, sv, link);
+
+ add_dir(&insnprefix_byp, "gas", d);
+ }
+
+ /* And finally the version sans suffix */
+ sv = yasm_xmalloc(sizeof(sval));
+ sv->str = yasm__xstrdup("NONE");
+ STAILQ_INSERT_HEAD(&args, sv, link);
+
+ d = yasm_xmalloc(sizeof(dir));
+ d->name = yasm__xstrdup(bname);
+ d->func = "INSN";
+ d->args = args;
+ add_dir(&insnprefix_byp, parser, d);
+ }
+}
+
+static void
+parse_insn(void)
+{
+ if (!arch) {
+ report_error("ARCH not defined prior to INSN");
+ return;
+ }
+ arch->parse_insn();
+}
+
+static void
+parse_cpu(void)
+{
+ dir *d = parse_generic(CPU, "CPU", &cpu_byp);
+ sval *sv = yasm_xmalloc(sizeof(sval));
+ sv->str = yasm__xstrdup("CPU_MODE_VERBATIM");
+ STAILQ_INSERT_TAIL(&d->args, sv, link);
+}
+
+static void
+parse_cpu_alias(void)
+{
+ char *parser = check_parser(CPU_ALIAS);
+ char *name = strtok(NULL, " \t\n");
+ char *alias = strtok(NULL, " \t\n");
+ HAMT *dirs = get_dirs(&cpu_byp, parser);
+ dir *aliasd, *d;
+
+ if (!alias) {
+ report_error("CPU_ALIAS requires an operand");
+ return;
+ }
+
+ aliasd = HAMT_search(dirs, alias);
+ if (!aliasd) {
+ report_error("could not find `%s'", alias);
+ return;
+ }
+
+ d = yasm_xmalloc(sizeof(dir));
+ d->name = yasm__xstrdup(name);
+ d->func = "CPU";
+ dup_slist(&d->args, &aliasd->args);
+
+ add_dir(&cpu_byp, parser, d);
+}
+
+static void
+parse_cpu_feature(void)
+{
+ char *parser = check_parser(CPU_FEATURE);
+ char *name = strtok(NULL, " \t\n");
+ dir *name_dir = yasm_xmalloc(sizeof(dir));
+ dir *noname_dir = yasm_xmalloc(sizeof(dir));
+ sval *sv;
+
+ name_dir->name = yasm__xstrdup(name);
+ name_dir->func = "CPU_FEATURE";
+ parse_args(&name_dir->args);
+
+ noname_dir->name = yasm_xmalloc(strlen(name)+3);
+ strcpy(noname_dir->name, "no");
+ strcat(noname_dir->name, name);
+ noname_dir->func = name_dir->func;
+ dup_slist(&noname_dir->args, &name_dir->args);
+
+ sv = yasm_xmalloc(sizeof(sval));
+ sv->str = yasm__xstrdup("CPU_MODE_SET");
+ STAILQ_INSERT_TAIL(&name_dir->args, sv, link);
+
+ sv = yasm_xmalloc(sizeof(sval));
+ sv->str = yasm__xstrdup("CPU_MODE_CLEAR");
+ STAILQ_INSERT_TAIL(&noname_dir->args, sv, link);
+
+ add_dir(&cpu_byp, parser, name_dir);
+ add_dir(&cpu_byp, parser, noname_dir);
+}
+
+static void
+parse_targetmod(void)
+{
+ parse_generic(TARGETMOD, "TARGETMOD", ®tmod_byp);
+}
+
+static void
+parse_prefix(void)
+{
+ parse_generic(PREFIX, "PREFIX", &insnprefix_byp);
+}
+
+static void
+parse_reg(void)
+{
+ parse_generic(REG, "REG", ®tmod_byp);
+}
+
+static void
+parse_reggroup(void)
+{
+ parse_generic(REGGROUP, "REGGROUP", ®tmod_byp);
+}
+
+static void
+parse_segreg(void)
+{
+ parse_generic(SEGREG, "SEGREG", ®tmod_byp);
+}
+
+/* make the c output for the perfect hash tab array */
+static void
+make_c_tab(
+ FILE *f,
+ const char *which,
+ const char *parser,
+ bstuff *tab, /* table indexed by b */
+ ub4 smax, /* range of scramble[] */
+ ub4 blen, /* b in 0..blen-1, power of 2 */
+ ub4 *scramble) /* used in final hash */
+{
+ ub4 i;
+ /* table for the mapping for the perfect hash */
+ if (blen >= USE_SCRAMBLE) {
+ /* A way to make the 1-byte values in tab bigger */
+ if (smax > UB2MAXVAL+1) {
+ fprintf(f, "static const unsigned long %s_", which);
+ if (parser)
+ fprintf(f, "%s_", parser);
+ fprintf(f, "scramble[] = {\n");
+ for (i=0; i<=UB1MAXVAL; i+=4)
+ fprintf(f, "0x%.8lx, 0x%.8lx, 0x%.8lx, 0x%.8lx,\n",
+ scramble[i+0], scramble[i+1], scramble[i+2], scramble[i+3]);
+ } else {
+ fprintf(f, "static const unsigned short %s_", which);
+ if (parser)
+ fprintf(f, "%s_", parser);
+ fprintf(f, "scramble[] = {\n");
+ for (i=0; i<=UB1MAXVAL; i+=8)
+ fprintf(f,
+"0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx,\n",
+ scramble[i+0], scramble[i+1], scramble[i+2], scramble[i+3],
+ scramble[i+4], scramble[i+5], scramble[i+6], scramble[i+7]);
+ }
+ fprintf(f, "};\n");
+ fprintf(f, "\n");
+ }
+
+ if (blen > 0) {
+ /* small adjustments to _a_ to make values distinct */
+ if (smax <= UB1MAXVAL+1 || blen >= USE_SCRAMBLE)
+ fprintf(f, "static const unsigned char %s_", which);
+ else
+ fprintf(f, "static const unsigned short %s_", which);
+ if (parser)
+ fprintf(f, "%s_", parser);
+ fprintf(f, "tab[] = {\n");
+
+ if (blen < 16) {
+ for (i=0; i<blen; ++i)
+ fprintf(f, "%3d,", scramble[tab[i].val_b]);
+ } else if (blen <= 1024) {
+ for (i=0; i<blen; i+=16)
+ fprintf(f, "%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,\n",
+ scramble[tab[i+0].val_b], scramble[tab[i+1].val_b],
+ scramble[tab[i+2].val_b], scramble[tab[i+3].val_b],
+ scramble[tab[i+4].val_b], scramble[tab[i+5].val_b],
+ scramble[tab[i+6].val_b], scramble[tab[i+7].val_b],
+ scramble[tab[i+8].val_b], scramble[tab[i+9].val_b],
+ scramble[tab[i+10].val_b], scramble[tab[i+11].val_b],
+ scramble[tab[i+12].val_b], scramble[tab[i+13].val_b],
+ scramble[tab[i+14].val_b], scramble[tab[i+15].val_b]);
+ } else if (blen < USE_SCRAMBLE) {
+ for (i=0; i<blen; i+=8)
+ fprintf(f, "%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,\n",
+ scramble[tab[i+0].val_b], scramble[tab[i+1].val_b],
+ scramble[tab[i+2].val_b], scramble[tab[i+3].val_b],
+ scramble[tab[i+4].val_b], scramble[tab[i+5].val_b],
+ scramble[tab[i+6].val_b], scramble[tab[i+7].val_b]);
+ } else {
+ for (i=0; i<blen; i+=16)
+ fprintf(f, "%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,\n",
+ tab[i+0].val_b, tab[i+1].val_b,
+ tab[i+2].val_b, tab[i+3].val_b,
+ tab[i+4].val_b, tab[i+5].val_b,
+ tab[i+6].val_b, tab[i+7].val_b,
+ tab[i+8].val_b, tab[i+9].val_b,
+ tab[i+10].val_b, tab[i+11].val_b,
+ tab[i+12].val_b, tab[i+13].val_b,
+ tab[i+14].val_b, tab[i+15].val_b);
+ }
+ fprintf(f, "};\n");
+ fprintf(f, "\n");
+ }
+}
+
+typedef struct perfect_add_key_data {
+ ub4 nkeys;
+ key *keys;
+} perfect_add_key_data;
+
+static int
+perfect_add_key(void *node, void *data)
+{
+ dir *d = (dir *)node;
+ perfect_add_key_data *pakd = (perfect_add_key_data *)data;
+ key *k = yasm_xmalloc(sizeof(key));
+
+ k->name_k = yasm__xstrdup(d->name);
+ k->len_k = strlen(d->name);
+ k->next_k = pakd->keys;
+ pakd->keys = k;
+ pakd->nkeys++;
+ return 0;
+}
+
+static void
+perfect_dir(FILE *out, const char *which, const char *parser, HAMT *dirs)
+{
+ perfect_add_key_data pakd;
+ hashform form;
+ bstuff *tab; /* table indexed by b */
+ hstuff *tabh; /* table indexed by hash value */
+ ub4 smax; /* scramble[] values in 0..smax-1, a power of 2 */
+ ub4 alen; /* a in 0..alen-1, a power of 2 */
+ ub4 blen; /* b in 0..blen-1, a power of 2 */
+ ub4 salt; /* a parameter to the hash function */
+ gencode final; /* code for final hash */
+ ub4 i;
+ ub4 scramble[SCRAMBLE_LEN]; /* used in final hash function */
+ char buf[10][80]; /* buffer for generated code */
+ char *buf2[10]; /* also for generated code */
+ int cpumode = strcmp(which, "cpu") == 0;
+
+ /* perfect hash configuration */
+ form.mode = NORMAL_HM;
+ form.hashtype = STRING_HT;
+ form.perfect = MINIMAL_HP;
+ form.speed = SLOW_HS;
+
+ /* set up code for final hash */
+ final.line = buf2;
+ final.used = 0;
+ final.len = 10;
+ for (i=0; i<10; i++)
+ final.line[i] = buf[i];
+
+ /* build list of keys */
+ pakd.nkeys = 0;
+ pakd.keys = NULL;
+ HAMT_traverse(dirs, &pakd, perfect_add_key);
+
+ /* find the hash */
+ findhash(&tab, &tabh, &alen, &blen, &salt, &final,
+ scramble, &smax, pakd.keys, pakd.nkeys, &form);
+
+ /* output the dir table: this should loop up to smax for NORMAL_HP,
+ * or up to pakd.nkeys for MINIMAL_HP.
+ */
+ fprintf(out, "static const %s_parse_data %s_", which, which);
+ if (parser)
+ fprintf(out, "%s_", parser);
+ fprintf(out, "pd[%lu] = {\n", pakd.nkeys);
+ for (i=0; i<pakd.nkeys; i++) {
+ if (tabh[i].key_h) {
+ dir *d = HAMT_search(dirs, tabh[i].key_h->name_k);
+ sval *sv;
+ if (!d) {
+ report_error("internal error: could not find `%s'",
+ tabh[i].key_h->name_k);
+ break;
+ }
+ if (cpumode)
+ fprintf(out, "{\"%s\",", d->name);
+ else
+ fprintf(out, "%s(\"%s\",", d->func, d->name);
+ STAILQ_FOREACH(sv, &d->args, link) {
+ fprintf(out, " %s", sv->str);
+ if (STAILQ_NEXT(sv, link))
+ fprintf(out, ",");
+ }
+ fprintf(out, cpumode ? "}" : ")");
+ } else
+ fprintf(out, " { NULL }");
+
+ if (i < pakd.nkeys-1)
+ fprintf(out, ",");
+ fprintf(out, "\n");
+ }
+ fprintf(out, "};\n");
+
+ /* output the hash tab[] array */
+ make_c_tab(out, which, parser, tab, smax, blen, scramble);
+
+ /* The hash function */
+ fprintf(out, "#define tab %s_", which);
+ if (parser)
+ fprintf(out, "%s_", parser);
+ fprintf(out, "tab\n");
+ fprintf(out, "static const %s_parse_data *\n%s_", which, which);
+ if (parser)
+ fprintf(out, "%s_", parser);
+ fprintf(out, "find(const char *key, size_t len)\n");
+ fprintf(out, "{\n");
+ fprintf(out, " const %s_parse_data *ret;\n", which);
+ for (i=0; i<final.used; ++i)
+ fprintf(out, final.line[i]);
+ fprintf(out, " if (rsl >= %lu) return NULL;\n", pakd.nkeys);
+ fprintf(out, " ret = &%s_", which);
+ if (parser)
+ fprintf(out, "%s_", parser);
+ fprintf(out, "pd[rsl];\n");
+ fprintf(out, " if (strcmp(key, ret->name) != 0) return NULL;\n");
+ fprintf(out, " return ret;\n");
+ fprintf(out, "}\n");
+ fprintf(out, "#undef tab\n\n");
+
+ free(tab);
+ free(tabh);
+}
+
+/* Get an entire "real" line from the input file by combining any
+ * \\\n continuations.
+ */
+static int get_line(FILE *in)
+{
+ char *p = line;
+ cur_line = next_line;
+
+ if (feof(in))
+ return 0;
+
+ while (p < &line[1023-128]) {
+ if (!fgets(p, 128, in))
+ return 1;
+ next_line++;
+ /* if continuation, strip out leading whitespace */
+ if (p > line) {
+ char *p2 = p;
+ while (isspace(*p2)) p2++;
+ if (p2 > p)
+ memmove(p, p2, strlen(p2)+1);
+ }
+ while (*p) p++;
+ if (p[-2] != '\\' || p[-1] != '\n') {
+ if (p[-1] == '\n')
+ p[-1] = '\0';
+ return 1;
+ }
+ p -= 2;
+ }
+}
+
+static struct {
+ const char *name;
+ int indx;
+ void (*handler) (void);
+} directives[] = {
+ {"ARCH", ARCH, parse_arch},
+ {"PARSERS", PARSERS, parse_parsers},
+ {"INSN", INSN, parse_insn},
+ {"CPU", CPU, parse_cpu},
+ {"CPU_ALIAS", CPU_ALIAS, parse_cpu_alias},
+ {"CPU_FEATURE", CPU_FEATURE, parse_cpu_feature},
+ {"TARGETMOD", TARGETMOD, parse_targetmod},
+ {"PREFIX", PREFIX, parse_prefix},
+ {"REG", REG, parse_reg},
+ {"REGGROUP", REGGROUP, parse_reggroup},
+ {"SEGREG", SEGREG, parse_segreg},
+};
+
+int
+main(int argc, char *argv[])
+{
+ FILE *in, *out;
+ int i, t;
+ int insn_numnongas = 0, insn_numgas = 0, insn_numcommon = 0;
+ int cpu_num = 0, cpu_numalias = 0, cpu_numfeature = 0;
+ int prefix_numnongas = 0, prefix_numgas = 0, prefix_numcommon = 0;
+ int reg_numcommon = 0, reg_num64 = 0, reg_numgroup = 0, reg_numseg = 0;
+ char *tok;
+ int count[NUM_DIRS];
+ dir_byp *db;
+
+ for (i=0; i<NUM_DIRS; i++)
+ count[i] = 0;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: gap <in> <out>\n");
+ return EXIT_FAILURE;
+ }
+
+ in = fopen(argv[1], "rt");
+ if (!in) {
+ fprintf(stderr, "Could not open `%s' for reading\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+
+ STAILQ_INIT(&insnprefix_byp);
+ STAILQ_INIT(&cpu_byp);
+ STAILQ_INIT(®tmod_byp);
+
+ /* Parse input file */
+ while (get_line(in)) {
+ int found;
+ /*printf("%s\n", line);*/
+ tok = strtok(line, " \t\n");
+ if (!tok)
+ continue;
+
+ /* Comments start with # as the first thing on a line */
+ if (tok[0] == '#')
+ continue;
+
+ /* Look for directive */
+ found = 0;
+ for (i=0; i<sizeof(directives)/sizeof(directives[0]); i++) {
+ if (strcmp(tok, directives[i].name) == 0) {
+ count[directives[i].indx]++;
+ directives[i].handler();
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ report_error("unknown directive `%s'\n", tok);
+ }
+
+ /* Output some informational statistics */
+ printf("Directives read:\n");
+ for (i=0; i<sizeof(directives)/sizeof(directives[0]); i++)
+ printf("\t%d\t%s\n", count[directives[i].indx], directives[i].name);
+
+ if (errors > 0)
+ return EXIT_FAILURE;
+
+ out = fopen(argv[2], "wt");
+ if (!out) {
+ fprintf(stderr, "Could not open `%s' for writing\n", argv[2]);
+ return EXIT_FAILURE;
+ }
+
+ /* Get perfect hashes for the three lists of directives */
+ STAILQ_FOREACH(db, &insnprefix_byp, link)
+ perfect_dir(out, "insnprefix", db->parser, db->dirs);
+ STAILQ_FOREACH(db, &cpu_byp, link)
+ perfect_dir(out, "cpu", db->parser, db->dirs);
+ STAILQ_FOREACH(db, ®tmod_byp, link)
+ perfect_dir(out, "regtmod", db->parser, db->dirs);
+
+ if (errors > 0)
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+}
+
--- /dev/null
+/* Modified for use with yasm by Peter Johnson.
+ * $Id$
+ */
+/*
+------------------------------------------------------------------------------
+perfect.c: code to generate code for a hash for perfect hashing.
+(c) Bob Jenkins, September 1996, December 1999
+You may use this code in any way you wish, and it is free. No warranty.
+I hereby place this in the public domain.
+Source is http://burtleburtle.net/bob/c/perfect.c
+
+This generates a minimal perfect hash function. That means, given a
+set of n keys, this determines a hash function that maps each of
+those keys into a value in 0..n-1 with no collisions.
+
+The perfect hash function first uses a normal hash function on the key
+to determine (a,b) such that the pair (a,b) is distinct for all
+keys, then it computes a^scramble[tab[b]] to get the final perfect hash.
+tab[] is an array of 1-byte values and scramble[] is a 256-term array of
+2-byte or 4-byte values. If there are n keys, the length of tab[] is a
+power of two between n/3 and n.
+
+I found the idea of computing distinct (a,b) values in "Practical minimal
+perfect hash functions for large databases", Fox, Heath, Chen, and Daoud,
+Communications of the ACM, January 1992. They found the idea in Chichelli
+(CACM Jan 1980). Beyond that, our methods differ.
+
+The key is hashed to a pair (a,b) where a in 0..*alen*-1 and b in
+0..*blen*-1. A fast hash function determines both a and b
+simultaneously. Any decent hash function is likely to produce
+hashes so that (a,b) is distinct for all pairs. I try the hash
+using different values of *salt* until all pairs are distinct.
+
+The final hash is (a XOR scramble[tab[b]]). *scramble* is a
+predetermined mapping of 0..255 into 0..smax-1. *tab* is an
+array that we fill in in such a way as to make the hash perfect.
+
+First we fill in all values of *tab* that are used by more than one
+key. We try all possible values for each position until one works.
+
+This leaves m unmapped keys and m values that something could hash to.
+If you treat unmapped keys as lefthand nodes and unused hash values
+as righthand nodes, and draw a line connecting each key to each hash
+value it could map to, you get a bipartite graph. We attempt to
+find a perfect matching in this graph. If we succeed, we have
+determined a perfect hash for the whole set of keys.
+
+*scramble* is used because (a^tab[i]) clusters keys around *a*.
+------------------------------------------------------------------------------
+*/
+
+#include "tools/gap/standard.h"
+#include "libyasm/coretype.h"
+#include "libyasm/phash.h"
+#include "tools/gap/perfect.h"
+
+#define CHECKSTATE 8
+
+/*
+------------------------------------------------------------------------------
+Find the mapping that will produce a perfect hash
+------------------------------------------------------------------------------
+*/
+
+/* return the ceiling of the log (base 2) of val */
+ub4 phash_log2(val)
+ub4 val;
+{
+ ub4 i;
+ for (i=0; ((ub4)1<<i) < val; ++i)
+ ;
+ return i;
+}
+
+/* compute p(x), where p is a permutation of 0..(1<<nbits)-1 */
+/* permute(0)=0. This is intended and useful. */
+static ub4 permute(x, nbits)
+ub4 x; /* input, a value in some range */
+ub4 nbits; /* input, number of bits in range */
+{
+ int i;
+ int mask = ((ub4)1<<nbits)-1; /* all ones */
+ int const2 = 1+nbits/2;
+ int const3 = 1+nbits/3;
+ int const4 = 1+nbits/4;
+ int const5 = 1+nbits/5;
+ for (i=0; i<20; ++i)
+ {
+ x = (x+(x<<const2)) & mask;
+ x = (x^(x>>const3));
+ x = (x+(x<<const4)) & mask;
+ x = (x^(x>>const5));
+ }
+ return x;
+}
+
+/* initialize scramble[] with distinct random values in 0..smax-1 */
+static void scrambleinit(scramble, smax)
+ub4 *scramble; /* hash is a^scramble[tab[b]] */
+ub4 smax; /* scramble values should be in 0..smax-1 */
+{
+ ub4 i;
+
+ /* fill scramble[] with distinct random integers in 0..smax-1 */
+ for (i=0; i<SCRAMBLE_LEN; ++i)
+ {
+ scramble[i] = permute(i, phash_log2(smax));
+ }
+}
+
+/*
+ * Check if key1 and key2 are the same.
+ * We already checked (a,b) are the same.
+ */
+static void checkdup(key1, key2, form)
+key *key1;
+key *key2;
+hashform *form;
+{
+ switch(form->hashtype)
+ {
+ case STRING_HT:
+ if ((key1->len_k == key2->len_k) &&
+ !memcmp(key1->name_k, key2->name_k, (size_t)key1->len_k))
+ {
+ fprintf(stderr, "perfect.c: Duplicates keys! %.*s\n",
+ key1->len_k, key1->name_k);
+ exit(EXIT_SUCCESS);
+ }
+ break;
+ case INT_HT:
+ if (key1->hash_k == key2->hash_k)
+ {
+ fprintf(stderr, "perfect.c: Duplicate keys! %.8lx\n", key1->hash_k);
+ exit(EXIT_SUCCESS);
+ }
+ break;
+ case AB_HT:
+ fprintf(stderr, "perfect.c: Duplicate keys! %.8lx %.8lx\n",
+ key1->a_k, key1->b_k);
+ exit(EXIT_SUCCESS);
+ break;
+ default:
+ fprintf(stderr, "perfect.c: Illegal hash type %ld\n", (ub4)form->hashtype);
+ exit(EXIT_SUCCESS);
+ break;
+ }
+}
+
+
+/*
+ * put keys in tabb according to key->b_k
+ * check if the initial hash might work
+ */
+static int inittab(tabb, blen, keys, form, complete)
+bstuff *tabb; /* output, list of keys with b for (a,b) */
+ub4 blen; /* length of tabb */
+key *keys; /* list of keys already hashed */
+hashform *form; /* user directives */
+int complete; /* TRUE means to complete init despite collisions */
+{
+ int nocollision = TRUE;
+ key *mykey;
+
+ memset((void *)tabb, 0, (size_t)(sizeof(bstuff)*blen));
+
+ /* Two keys with the same (a,b) guarantees a collision */
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ {
+ key *otherkey;
+
+ for (otherkey=tabb[mykey->b_k].list_b;
+ otherkey;
+ otherkey=otherkey->nextb_k)
+ {
+ if (mykey->a_k == otherkey->a_k)
+ {
+ nocollision = FALSE;
+ checkdup(mykey, otherkey, form);
+ if (!complete)
+ return FALSE;
+ }
+ }
+ ++tabb[mykey->b_k].listlen_b;
+ mykey->nextb_k = tabb[mykey->b_k].list_b;
+ tabb[mykey->b_k].list_b = mykey;
+ }
+
+ /* no two keys have the same (a,b) pair */
+ return nocollision;
+}
+
+
+/* Do the initial hash for normal mode (use lookup and checksum) */
+static void initnorm(keys, alen, blen, smax, salt, final)
+key *keys; /* list of all keys */
+ub4 alen; /* (a,b) has a in 0..alen-1, a power of 2 */
+ub4 blen; /* (a,b) has b in 0..blen-1, a power of 2 */
+ub4 smax; /* maximum range of computable hash values */
+ub4 salt; /* used to initialize the hash function */
+gencode *final; /* output, code for the final hash */
+{
+ key *mykey;
+ if (phash_log2(alen)+phash_log2(blen) > UB4BITS)
+ {
+ ub4 initlev = salt*0x9e3779b9; /* the golden ratio; an arbitrary value */
+
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ {
+ ub4 i, state[CHECKSTATE];
+ for (i=0; i<CHECKSTATE; ++i) state[i] = initlev;
+ phash_checksum( mykey->name_k, mykey->len_k, state);
+ mykey->a_k = state[0]&(alen-1);
+ mykey->b_k = state[1]&(blen-1);
+ }
+ final->used = 4;
+ sprintf(final->line[0],
+ " unsigned long i,state[CHECKSTATE],rsl;\n");
+ sprintf(final->line[1],
+ " for (i=0; i<CHECKSTATE; ++i) state[i]=0x%lx;\n",initlev);
+ sprintf(final->line[2],
+ " phash_checksum(key, len, state);\n");
+ sprintf(final->line[3],
+ " rsl = ((state[0]&0x%x)^scramble[tab[state[1]&0x%x]]);\n",
+ alen-1, blen-1);
+ }
+ else
+ {
+ ub4 loga = phash_log2(alen); /* log based 2 of blen */
+ ub4 initlev = salt*0x9e3779b9; /* the golden ratio; an arbitrary value */
+
+ for (mykey=keys; mykey; mykey=mykey->next_k)
+ {
+ ub4 hash = phash_lookup(mykey->name_k, mykey->len_k, initlev);
+ mykey->a_k = (loga > 0) ? hash>>(UB4BITS-loga) : 0;
+ mykey->b_k = (blen > 1) ? hash&(blen-1) : 0;
+ }
+ final->used = 2;
+ sprintf(final->line[0],
+ " unsigned long rsl, val = phash_lookup(key, len, 0x%lxUL);\n", initlev);
+ if (smax <= 1)
+ {
+ sprintf(final->line[1], " rsl = 0;\n");
+ }
+ else if (blen < USE_SCRAMBLE)
+ {
+ sprintf(final->line[1], " rsl = ((val>>%ld)^tab[val&0x%x]);\n",
+ UB4BITS-phash_log2(alen), blen-1);
+ }
+ else
+ {
+ sprintf(final->line[1], " rsl = ((val>>%ld)^scramble[tab[val&0x%x]]);\n",
+ UB4BITS-phash_log2(alen), blen-1);
+ }
+ }
+}
+
+
+
+/* Do initial hash for inline mode */
+static void initinl(keys, alen, blen, smax, salt, final)
+key *keys; /* list of all keys */
+ub4 alen; /* (a,b) has a in 0..alen-1, a power of 2 */
+ub4 blen; /* (a,b) has b in 0..blen-1, a power of 2 */
+ub4 smax; /* range of computable hash values */
+ub4 salt; /* used to initialize the hash function */
+gencode *final; /* generated code for final hash */
+{
+ key *mykey;
+ ub4 amask = alen-1;
+ ub4 blog = phash_log2(blen);
+ ub4 initval = salt*0x9e3779b9; /* the golden ratio; an arbitrary value */
+
+ /* It's more important to have b uniform than a, so b is the low bits */
+ for (mykey = keys; mykey != (key *)0; mykey = mykey->next_k)
+ {
+ ub4 hash = initval;
+ ub4 i;
+ for (i=0; i<mykey->len_k; ++i)
+ {
+ hash = (mykey->name_k[i] ^ hash) + ((hash<<(UB4BITS-6))+(hash>>6));
+ }
+ mykey->hash_k = hash;
+ mykey->a_k = (alen > 1) ? (hash & amask) : 0;
+ mykey->b_k = (blen > 1) ? (hash >> (UB4BITS-blog)) : 0;
+ }
+ final->used = 1;
+ if (smax <= 1)
+ {
+ sprintf(final->line[0], " unsigned long rsl = 0;\n");
+ }
+ else if (blen < USE_SCRAMBLE)
+ {
+ sprintf(final->line[0], " unsigned long rsl = ((val & 0x%lx) ^ tab[val >> %ld]);\n",
+ amask, UB4BITS-blog);
+ }
+ else
+ {
+ sprintf(final->line[0], " unsigned long rsl = ((val & 0x%lx) ^ scramble[tab[val >> %ld]]);\n",
+ amask, UB4BITS-blog);
+ }
+}
+
+
+/*
+ * Run a hash function on the key to get a and b
+ * Returns:
+ * 0: didn't find distinct (a,b) for all keys
+ * 1: found distinct (a,b) for all keys, put keys in tabb[]
+ * 2: found a perfect hash, no need to do any more work
+ */
+static ub4 initkey(keys, nkeys, tabb, alen, blen, smax, salt, form, final)
+key *keys; /* list of all keys */
+ub4 nkeys; /* total number of keys */
+bstuff *tabb; /* stuff indexed by b */
+ub4 alen; /* (a,b) has a in 0..alen-1, a power of 2 */
+ub4 blen; /* (a,b) has b in 0..blen-1, a power of 2 */
+ub4 smax; /* range of computable hash values */
+ub4 salt; /* used to initialize the hash function */
+hashform *form; /* user directives */
+gencode *final; /* code for final hash */
+{
+ ub4 finished;
+
+ /* Do the initial hash of the keys */
+ switch(form->mode)
+ {
+ case NORMAL_HM:
+ initnorm(keys, alen, blen, smax, salt, final);
+ break;
+ case INLINE_HM:
+ initinl(keys, alen, blen, smax, salt, final);
+ break;
+#if 0
+ case HEX_HM:
+ case DECIMAL_HM:
+ finished = inithex(keys, nkeys, alen, blen, smax, salt, final, form);
+ if (finished) return 2;
+ break;
+#endif
+ default:
+ fprintf(stderr, "fatal error: illegal mode\n");
+ exit(1);
+ }
+
+ if (nkeys <= 1)
+ {
+ final->used = 1;
+ sprintf(final->line[0], " unsigned long rsl = 0;\n");
+ return 2;
+ }
+
+ return inittab(tabb, blen, keys, form, FALSE);
+}
+
+/* Print an error message and exit if there are duplicates */
+static void duplicates(tabb, blen, keys, form)
+bstuff *tabb; /* array of lists of keys with the same b */
+ub4 blen; /* length of tabb, a power of 2 */
+key *keys;
+hashform *form; /* user directives */
+{
+ ub4 i;
+ key *key1;
+ key *key2;
+
+ (void)inittab(tabb, blen, keys, form, TRUE);
+
+ /* for each b, do nested loops through key list looking for duplicates */
+ for (i=0; i<blen; ++i)
+ for (key1=tabb[i].list_b; key1; key1=key1->nextb_k)
+ for (key2=key1->nextb_k; key2; key2=key2->nextb_k)
+ checkdup(key1, key2, form);
+}
+
+
+/* Try to apply an augmenting list */
+static int apply(tabb, tabh, tabq, blen, scramble, tail, rollback)
+bstuff *tabb;
+hstuff *tabh;
+qstuff *tabq;
+ub4 blen;
+ub4 *scramble;
+ub4 tail;
+int rollback; /* FALSE applies augmenting path, TRUE rolls back */
+{
+ ub4 hash;
+ key *mykey;
+ bstuff *pb;
+ ub4 child;
+ ub4 parent;
+ ub4 stabb; /* scramble[tab[b]] */
+
+ /* walk from child to parent */
+ for (child=tail-1; child; child=parent)
+ {
+ parent = tabq[child].parent_q; /* find child's parent */
+ pb = tabq[parent].b_q; /* find parent's list of siblings */
+
+ /* erase old hash values */
+ stabb = scramble[pb->val_b];
+ for (mykey=pb->list_b; mykey; mykey=mykey->nextb_k)
+ {
+ hash = mykey->a_k^stabb;
+ if (mykey == tabh[hash].key_h)
+ { /* erase hash for all of child's siblings */
+ tabh[hash].key_h = (key *)0;
+ }
+ }
+
+ /* change pb->val_b, which will change the hashes of all parent siblings */
+ pb->val_b = (rollback ? tabq[child].oldval_q : tabq[child].newval_q);
+
+ /* set new hash values */
+ stabb = scramble[pb->val_b];
+ for (mykey=pb->list_b; mykey; mykey=mykey->nextb_k)
+ {
+ hash = mykey->a_k^stabb;
+ if (rollback)
+ {
+ if (parent == 0) continue; /* root never had a hash */
+ }
+ else if (tabh[hash].key_h)
+ {
+ /* very rare: roll back any changes */
+ (void *)apply(tabb, tabh, tabq, blen, scramble, tail, TRUE);
+ return FALSE; /* failure, collision */
+ }
+ tabh[hash].key_h = mykey;
+ }
+ }
+ return TRUE;
+}
+
+
+/*
+-------------------------------------------------------------------------------
+augment(): Add item to the mapping.
+
+Construct a spanning tree of *b*s with *item* as root, where each
+parent can have all its hashes changed (by some new val_b) with
+at most one collision, and each child is the b of that collision.
+
+I got this from Tarjan's "Data Structures and Network Algorithms". The
+path from *item* to a *b* that can be remapped with no collision is
+an "augmenting path". Change values of tab[b] along the path so that
+the unmapped key gets mapped and the unused hash value gets used.
+
+Assuming 1 key per b, if m out of n hash values are still unused,
+you should expect the transitive closure to cover n/m nodes before
+an unused node is found. Sum(i=1..n)(n/i) is about nlogn, so expect
+this approach to take about nlogn time to map all single-key b's.
+-------------------------------------------------------------------------------
+*/
+static int augment(tabb, tabh, tabq, blen, scramble, smax, item, nkeys,
+ highwater, form)
+bstuff *tabb; /* stuff indexed by b */
+hstuff *tabh; /* which key is associated with which hash, indexed by hash */
+qstuff *tabq; /* queue of *b* values, this is the spanning tree */
+ub4 blen; /* length of tabb */
+ub4 *scramble; /* final hash is a^scramble[tab[b]] */
+ub4 smax; /* highest value in scramble */
+bstuff *item; /* &tabb[b] for the b to be mapped */
+ub4 nkeys; /* final hash must be in 0..nkeys-1 */
+ub4 highwater; /* a value higher than any now in tabb[].water_b */
+hashform *form; /* TRUE if we should do a minimal perfect hash */
+{
+ ub4 q; /* current position walking through the queue */
+ ub4 tail; /* tail of the queue. 0 is the head of the queue. */
+ ub4 limit=((blen < USE_SCRAMBLE) ? smax : UB1MAXVAL+1);
+ ub4 highhash = ((form->perfect == MINIMAL_HP) ? nkeys : smax);
+ int trans = (form->speed == SLOW_HS || form->perfect == MINIMAL_HP);
+
+ /* initialize the root of the spanning tree */
+ tabq[0].b_q = item;
+ tail = 1;
+
+ /* construct the spanning tree by walking the queue, add children to tail */
+ for (q=0; q<tail; ++q)
+ {
+ bstuff *myb = tabq[q].b_q; /* the b for this node */
+ ub4 i; /* possible value for myb->val_b */
+
+ if (!trans && (q == 1))
+ break; /* don't do transitive closure */
+
+ for (i=0; i<limit; ++i)
+ {
+ bstuff *childb = (bstuff *)0; /* the b that this i maps to */
+ key *mykey; /* for walking through myb's keys */
+
+ for (mykey = myb->list_b; mykey; mykey=mykey->nextb_k)
+ {
+ key *childkey;
+ ub4 hash = mykey->a_k^scramble[i];
+
+ if (hash >= highhash) break; /* out of bounds */
+ childkey = tabh[hash].key_h;
+
+ if (childkey)
+ {
+ bstuff *hitb = &tabb[childkey->b_k];
+
+ if (childb)
+ {
+ if (childb != hitb) break; /* hit at most one child b */
+ }
+ else
+ {
+ childb = hitb; /* remember this as childb */
+ if (childb->water_b == highwater) break; /* already explored */
+ }
+ }
+ }
+ if (mykey) continue; /* myb with i has multiple collisions */
+
+ /* add childb to the queue of reachable things */
+ if (childb) childb->water_b = highwater;
+ tabq[tail].b_q = childb;
+ tabq[tail].newval_q = i; /* how to make parent (myb) use this hash */
+ tabq[tail].oldval_q = myb->val_b; /* need this for rollback */
+ tabq[tail].parent_q = q;
+ ++tail;
+
+ if (!childb)
+ { /* found an *i* with no collisions? */
+ /* try to apply the augmenting path */
+ if (apply(tabb, tabh, tabq, blen, scramble, tail, FALSE))
+ return TRUE; /* success, item was added to the perfect hash */
+
+ --tail; /* don't know how to handle such a child! */
+ }
+ }
+ }
+ return FALSE;
+}
+
+
+/* find a mapping that makes this a perfect hash */
+static int perfect(tabb, tabh, tabq, blen, smax, scramble, nkeys, form)
+bstuff *tabb;
+hstuff *tabh;
+qstuff *tabq;
+ub4 blen;
+ub4 smax;
+ub4 *scramble;
+ub4 nkeys;
+hashform *form;
+{
+ ub4 maxkeys; /* maximum number of keys for any b */
+ ub4 i, j;
+
+ /* clear any state from previous attempts */
+ memset((void *)tabh, 0,
+ (size_t)(sizeof(hstuff)*
+ ((form->perfect == MINIMAL_HP) ? nkeys : smax)));
+ memset((void *)tabq, 0, (size_t)(sizeof(qstuff)*(blen+1)));
+
+ for (maxkeys=0,i=0; i<blen; ++i)
+ if (tabb[i].listlen_b > maxkeys)
+ maxkeys = tabb[i].listlen_b;
+
+ /* In descending order by number of keys, map all *b*s */
+ for (j=maxkeys; j>0; --j)
+ for (i=0; i<blen; ++i)
+ if (tabb[i].listlen_b == j)
+ if (!augment(tabb, tabh, tabq, blen, scramble, smax, &tabb[i], nkeys,
+ i+1, form))
+ {
+ printf("fail to map group of size %ld for tab size %ld\n", j, blen);
+ return FALSE;
+ }
+
+ /* Success! We found a perfect hash of all keys into 0..nkeys-1. */
+ return TRUE;
+}
+
+
+/*
+ * Simple case: user gave (a,b). No more mixing, no guessing alen or blen.
+ * This assumes a,b reside in (key->a_k, key->b_k), and final->form == AB_HK.
+ */
+static void hash_ab(tabb, alen, blen, salt, final,
+ scramble, smax, keys, nkeys, form)
+bstuff **tabb; /* output, tab[] of the perfect hash, length *blen */
+ub4 *alen; /* output, 0..alen-1 is range for a of (a,b) */
+ub4 *blen; /* output, 0..blen-1 is range for b of (a,b) */
+ub4 *salt; /* output, initializes initial hash */
+gencode *final; /* code for final hash */
+ub4 *scramble; /* input, hash = a^scramble[tab[b]] */
+ub4 *smax; /* input, scramble[i] in 0..smax-1 */
+key *keys; /* input, keys to hash */
+ub4 nkeys; /* input, number of keys being hashed */
+hashform *form; /* user directives */
+{
+ hstuff *tabh;
+ qstuff *tabq;
+ key *mykey;
+ ub4 i;
+ int used_tab;
+
+ /* initially make smax the first power of two bigger than nkeys */
+ *smax = ((ub4)1<<phash_log2(nkeys));
+ scrambleinit(scramble, *smax);
+
+ /* set *alen and *blen based on max A and B from user */
+ *alen = 1;
+ *blen = 1;
+ for (mykey = keys; mykey != (key *)0; mykey = mykey->next_k)
+ {
+ while (*alen <= mykey->a_k) *alen *= 2;
+ while (*blen <= mykey->b_k) *blen *= 2;
+ }
+ if (*alen > 2**smax)
+ {
+ fprintf(stderr,
+ "perfect.c: Can't deal with (A,B) having A bigger than twice \n");
+ fprintf(stderr,
+ " the smallest power of two greater or equal to any legal hash.\n");
+ exit(EXIT_SUCCESS);
+ }
+
+ /* allocate working memory */
+ *tabb = (bstuff *)yasm_xmalloc((size_t)(sizeof(bstuff)*(*blen)));
+ tabq = (qstuff *)yasm_xmalloc(sizeof(qstuff)*(*blen+1));
+ tabh = (hstuff *)yasm_xmalloc(sizeof(hstuff)*(form->perfect == MINIMAL_HP ?
+ nkeys : *smax));
+
+ /* check that (a,b) are distinct and put them in tabb indexed by b */
+ (void)inittab(*tabb, *blen, keys, form, FALSE);
+
+ /* try with smax */
+ if (!perfect(*tabb, tabh, tabq, *blen, *smax, scramble, nkeys, form))
+ {
+ if (form->perfect == MINIMAL_HP)
+ {
+ printf("fatal error: Cannot find perfect hash for user (A,B) pairs\n");
+ exit(EXIT_SUCCESS);
+ }
+ else
+ {
+ /* try with 2*smax */
+ free((void *)tabh);
+ *smax = *smax * 2;
+ scrambleinit(scramble, *smax);
+ tabh = (hstuff *)yasm_xmalloc(sizeof(hstuff)*(form->perfect == MINIMAL_HP ?
+ nkeys : *smax));
+ if (!perfect(*tabb, tabh, tabq, *blen, *smax, scramble, nkeys, form))
+ {
+ printf("fatal error: Cannot find perfect hash for user (A,B) pairs\n");
+ exit(EXIT_SUCCESS);
+ }
+ }
+ }
+
+ /* check if tab[] was really needed */
+ for (i=0; i<*blen; ++i)
+ {
+ if ((*tabb)[i].val_b != 0) break; /* assumes permute(0) == 0 */
+ }
+ used_tab = (i < *blen);
+
+ /* write the code for the perfect hash */
+ *salt = 1;
+ final->used = 1;
+ if (!used_tab)
+ {
+ sprintf(final->line[0], " unsigned long rsl = a;\n");
+ }
+ else if (*blen < USE_SCRAMBLE)
+ {
+ sprintf(final->line[0], " unsigned long rsl = (a ^ tab[b]);\n");
+ }
+ else
+ {
+ sprintf(final->line[0], " unsigned long rsl = (a ^ scramble[tab[b]]);\n");
+ }
+
+ printf("success, found a perfect hash\n");
+
+ free((void *)tabq);
+ free((void *)tabh);
+}
+
+
+/* guess initial values for alen and blen */
+static void initalen(alen, blen, smax, nkeys, form)
+ub4 *alen; /* output, initial alen */
+ub4 *blen; /* output, initial blen */
+ub4 *smax; /* input, power of two greater or equal to max hash value */
+ub4 nkeys; /* number of keys being hashed */
+hashform *form; /* user directives */
+{
+ /*
+ * Find initial *alen, *blen
+ * Initial alen and blen values were found empirically. Some factors:
+ *
+ * If smax<256 there is no scramble, so tab[b] needs to cover 0..smax-1.
+ *
+ * alen and blen must be powers of 2 because the values in 0..alen-1 and
+ * 0..blen-1 are produced by applying a bitmask to the initial hash function.
+ *
+ * alen must be less than smax, in fact less than nkeys, because otherwise
+ * there would often be no i such that a^scramble[i] is in 0..nkeys-1 for
+ * all the *a*s associated with a given *b*, so there would be no legal
+ * value to assign to tab[b]. This only matters when we're doing a minimal
+ * perfect hash.
+ *
+ * It takes around 800 trials to find distinct (a,b) with nkey=smax*(5/8)
+ * and alen*blen = smax*smax/32.
+ *
+ * Values of blen less than smax/4 never work, and smax/2 always works.
+ *
+ * We want blen as small as possible because it is the number of bytes in
+ * the huge array we must create for the perfect hash.
+ *
+ * When nkey <= smax*(5/8), blen=smax/4 works much more often with
+ * alen=smax/8 than with alen=smax/4. Above smax*(5/8), blen=smax/4
+ * doesn't seem to care whether alen=smax/8 or alen=smax/4. I think it
+ * has something to do with 5/8 = 1/8 * 5. For example examine 80000,
+ * 85000, and 90000 keys with different values of alen. This only matters
+ * if we're doing a minimal perfect hash.
+ *
+ * When alen*blen <= 1<<UB4BITS, the initial hash must produce one integer.
+ * Bigger than that it must produce two integers, which increases the
+ * cost of the hash per character hashed.
+ */
+ if (form->perfect == NORMAL_HP)
+ {
+ if ((form->speed == FAST_HS) && (nkeys > *smax*0.8))
+ {
+ *smax = *smax * 2;
+ }
+
+ *alen = ((form->hashtype==INT_HT) && *smax>131072) ?
+ ((ub4)1<<(UB4BITS-phash_log2(*blen))) : /* distinct keys => distinct (A,B) */
+ *smax; /* no reason to restrict alen to smax/2 */
+ if ((form->hashtype == INT_HT) && *smax < 32)
+ *blen = *smax; /* go for function speed not space */
+ else if (*smax/4 <= (1<<14))
+ *blen = ((nkeys <= *smax*0.56) ? *smax/32 :
+ (nkeys <= *smax*0.74) ? *smax/16 : *smax/8);
+ else
+ *blen = ((nkeys <= *smax*0.6) ? *smax/16 :
+ (nkeys <= *smax*0.8) ? *smax/8 : *smax/4);
+
+ if ((form->speed == FAST_HS) && (*blen < *smax/8))
+ *blen = *smax/8;
+
+ if (*alen < 1) *alen = 1;
+ if (*blen < 1) *blen = 1;
+ }
+ else
+ {
+ switch(phash_log2(*smax))
+ {
+ case 0:
+ *alen = 1;
+ *blen = 1;
+ case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
+ *alen = (form->perfect == NORMAL_HP) ? *smax : *smax/2;
+ *blen = *smax/2;
+ break;
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ if (form->speed == FAST_HS)
+ {
+ *alen = *smax/2;
+ *blen = *smax/4;
+ }
+ else if (*smax/4 < USE_SCRAMBLE)
+ {
+ *alen = ((nkeys <= *smax*0.52) ? *smax/8 : *smax/4);
+ *blen = ((nkeys <= *smax*0.52) ? *smax/8 : *smax/4);
+ }
+ else
+ {
+ *alen = ((nkeys <= *smax*(5.0/8.0)) ? *smax/8 :
+ (nkeys <= *smax*(3.0/4.0)) ? *smax/4 : *smax/2);
+ *blen = *smax/4; /* always give the small size a shot */
+ }
+ break;
+ case 18:
+ if (form->speed == FAST_HS)
+ {
+ *alen = *smax/2;
+ *blen = *smax/2;
+ }
+ else
+ {
+ *alen = *smax/8; /* never require the multiword hash */
+ *blen = (nkeys <= *smax*(5.0/8.0)) ? *smax/4 : *smax/2;
+ }
+ break;
+ case 19:
+ case 20:
+ *alen = (nkeys <= *smax*(5.0/8.0)) ? *smax/8 : *smax/2;
+ *blen = (nkeys <= *smax*(5.0/8.0)) ? *smax/4 : *smax/2;
+ break;
+ default:
+ *alen = *smax/2; /* just find a hash as quick as possible */
+ *blen = *smax/2; /* we'll be thrashing virtual memory at this size */
+ break;
+ }
+ }
+}
+
+/*
+** Try to find a perfect hash function.
+** Return the successful initializer for the initial hash.
+** Return 0 if no perfect hash could be found.
+*/
+void findhash(
+ bstuff **tabb, /* output, tab[] of the perfect hash, length *blen */
+ hstuff **tabh, /* output, table of keys indexed by hash value */
+ ub4 *alen, /* output, 0..alen-1 is range for a of (a,b) */
+ ub4 *blen, /* output, 0..blen-1 is range for b of (a,b) */
+ ub4 *salt, /* output, initializes initial hash */
+ gencode *final, /* code for final hash */
+ ub4 *scramble, /* input, hash = a^scramble[tab[b]] */
+ ub4 *smax, /* input, scramble[i] in 0..smax-1 */
+ key *keys, /* input, keys to hash */
+ ub4 nkeys, /* input, number of keys being hashed */
+ hashform *form) /* user directives */
+{
+ ub4 bad_initkey; /* how many times did initkey fail? */
+ ub4 bad_perfect; /* how many times did perfect fail? */
+ ub4 trysalt; /* trial initializer for initial hash */
+ ub4 maxalen;
+ qstuff *tabq; /* table of stuff indexed by queue value, used by augment */
+
+ /* The case of (A,B) supplied by the user is a special case */
+ if (form->hashtype == AB_HT)
+ {
+ hash_ab(tabb, alen, blen, salt, final,
+ scramble, smax, keys, nkeys, form);
+ return;
+ }
+
+ /* guess initial values for smax, alen and blen */
+ *smax = ((ub4)1<<phash_log2(nkeys));
+ initalen(alen, blen, smax, nkeys, form);
+
+ scrambleinit(scramble, *smax);
+
+ maxalen = (form->perfect == MINIMAL_HP) ? *smax/2 : *smax;
+
+ /* allocate working memory */
+ *tabb = (bstuff *)yasm_xmalloc((size_t)(sizeof(bstuff)*(*blen)));
+ tabq = (qstuff *)yasm_xmalloc(sizeof(qstuff)*(*blen+1));
+ *tabh = (hstuff *)yasm_xmalloc(sizeof(hstuff)*(form->perfect == MINIMAL_HP ?
+ nkeys : *smax));
+
+ /* Actually find the perfect hash */
+ *salt = 0;
+ bad_initkey = 0;
+ bad_perfect = 0;
+ for (trysalt=1; ; ++trysalt)
+ {
+ ub4 rslinit;
+ /* Try to find distinct (A,B) for all keys */
+
+ rslinit = initkey(keys, nkeys, *tabb, *alen, *blen, *smax, trysalt,
+ form, final);
+
+ if (rslinit == 2)
+ { /* initkey actually found a perfect hash, not just distinct (a,b) */
+ *salt = 1;
+ *blen = 0;
+ break;
+ }
+ else if (rslinit == 0)
+ {
+ /* didn't find distinct (a,b) */
+ if (++bad_initkey >= RETRY_INITKEY)
+ {
+ /* Try to put more bits in (A,B) to make distinct (A,B) more likely */
+ if (*alen < maxalen)
+ {
+ *alen *= 2;
+ }
+ else if (*blen < *smax)
+ {
+ *blen *= 2;
+ free(tabq);
+ free(*tabb);
+ *tabb = (bstuff *)yasm_xmalloc((size_t)(sizeof(bstuff)*(*blen)));
+ tabq = (qstuff *)yasm_xmalloc((size_t)(sizeof(qstuff)*(*blen+1)));
+ }
+ else
+ {
+ duplicates(*tabb, *blen, keys, form); /* check for duplicates */
+ printf("fatal error: Cannot perfect hash: cannot find distinct (A,B)\n");
+ exit(EXIT_SUCCESS);
+ }
+ bad_initkey = 0;
+ bad_perfect = 0;
+ }
+ continue; /* two keys have same (a,b) pair */
+ }
+
+ printf("found distinct (A,B) on attempt %ld\n", trysalt);
+
+ /* Given distinct (A,B) for all keys, build a perfect hash */
+ if (!perfect(*tabb, *tabh, tabq, *blen, *smax, scramble, nkeys, form))
+ {
+ if ((form->hashtype != INT_HT && ++bad_perfect >= RETRY_PERFECT) ||
+ (form->hashtype == INT_HT && ++bad_perfect >= RETRY_HEX))
+ {
+ if (*blen < *smax)
+ {
+ *blen *= 2;
+ free(*tabb);
+ free(tabq);
+ *tabb = (bstuff *)yasm_xmalloc((size_t)(sizeof(bstuff)*(*blen)));
+ tabq = (qstuff *)yasm_xmalloc((size_t)(sizeof(qstuff)*(*blen+1)));
+ --trysalt; /* we know this salt got distinct (A,B) */
+ }
+ else
+ {
+ printf("fatal error: Cannot perfect hash: cannot build tab[]\n");
+ exit(EXIT_SUCCESS);
+ }
+ bad_perfect = 0;
+ }
+ continue;
+ }
+
+ *salt = trysalt;
+ break;
+ }
+
+ printf("built perfect hash table of size %ld\n", *blen);
+
+ /* free working memory */
+ free((void *)tabq);
+}
+
+#if 0
+/*
+------------------------------------------------------------------------------
+Input/output type routines
+------------------------------------------------------------------------------
+*/
+
+/* get the list of keys */
+static void getkeys(keys, nkeys, textroot, keyroot, form)
+key **keys; /* list of all keys */
+ub4 *nkeys; /* number of keys */
+reroot *textroot; /* get space to store key text */
+reroot *keyroot; /* get space for keys */
+hashform *form; /* user directives */
+{
+ key *mykey;
+ char *mytext;
+ mytext = (char *)renew(textroot);
+ *keys = 0;
+ *nkeys = 0;
+ while (fgets(mytext, MAXKEYLEN, stdin))
+ {
+ mykey = (key *)renew(keyroot);
+ if (form->mode == AB_HM)
+ {
+ sscanf(mytext, "%lx %lx ", &mykey->a_k, &mykey->b_k);
+ }
+ else if (form->mode == ABDEC_HM)
+ {
+ sscanf(mytext, "%ld %ld ", &mykey->a_k, &mykey->b_k);
+ }
+ else if (form->mode == HEX_HM)
+ {
+ sscanf(mytext, "%lx ", &mykey->hash_k);
+ }
+ else if (form->mode == DECIMAL_HM)
+ {
+ sscanf(mytext, "%ld ", &mykey->hash_k);
+ }
+ else
+ {
+ mykey->name_k = (ub1 *)mytext;
+ mytext = (char *)renew(textroot);
+ mykey->len_k = (ub4)(strlen((char *)mykey->name_k)-1);
+ }
+ mykey->next_k = *keys;
+ *keys = mykey;
+ ++*nkeys;
+ }
+ redel(textroot, mytext);
+}
+
+/* make the .c file */
+static void make_c(tab, smax, blen, scramble, final, form)
+bstuff *tab; /* table indexed by b */
+ub4 smax; /* range of scramble[] */
+ub4 blen; /* b in 0..blen-1, power of 2 */
+ub4 *scramble; /* used in final hash */
+gencode *final; /* code for the final hash */
+hashform *form; /* user directives */
+{
+ ub4 i;
+ FILE *f;
+ f = fopen("phash.c", "w");
+ fprintf(f, "/* table for the mapping for the perfect hash */\n");
+ fprintf(f, "#include \"lookupa.h\"\n");
+ fprintf(f, "\n");
+ if (blen >= USE_SCRAMBLE)
+ {
+ fprintf(f, "/* A way to make the 1-byte values in tab bigger */\n");
+ if (smax > UB2MAXVAL+1)
+ {
+ fprintf(f, "unsigned long scramble[] = {\n");
+ for (i=0; i<=UB1MAXVAL; i+=4)
+ fprintf(f, "0x%.8lx, 0x%.8lx, 0x%.8lx, 0x%.8lx,\n",
+ scramble[i+0], scramble[i+1], scramble[i+2], scramble[i+3]);
+ }
+ else
+ {
+ fprintf(f, "unsigned short scramble[] = {\n");
+ for (i=0; i<=UB1MAXVAL; i+=8)
+ fprintf(f,
+"0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx, 0x%.4lx,\n",
+ scramble[i+0], scramble[i+1], scramble[i+2], scramble[i+3],
+ scramble[i+4], scramble[i+5], scramble[i+6], scramble[i+7]);
+ }
+ fprintf(f, "};\n");
+ fprintf(f, "\n");
+ }
+ if (blen > 0)
+ {
+ fprintf(f, "/* small adjustments to _a_ to make values distinct */\n");
+
+ if (smax <= UB1MAXVAL+1 || blen >= USE_SCRAMBLE)
+ fprintf(f, "unsigned char tab[] = {\n");
+ else
+ fprintf(f, "unsigned short tab[] = {\n");
+
+ if (blen < 16)
+ {
+ for (i=0; i<blen; ++i) fprintf(f, "%3d,", scramble[tab[i].val_b]);
+ }
+ else if (blen <= 1024)
+ {
+ for (i=0; i<blen; i+=16)
+ fprintf(f, "%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,\n",
+ scramble[tab[i+0].val_b], scramble[tab[i+1].val_b],
+ scramble[tab[i+2].val_b], scramble[tab[i+3].val_b],
+ scramble[tab[i+4].val_b], scramble[tab[i+5].val_b],
+ scramble[tab[i+6].val_b], scramble[tab[i+7].val_b],
+ scramble[tab[i+8].val_b], scramble[tab[i+9].val_b],
+ scramble[tab[i+10].val_b], scramble[tab[i+11].val_b],
+ scramble[tab[i+12].val_b], scramble[tab[i+13].val_b],
+ scramble[tab[i+14].val_b], scramble[tab[i+15].val_b]);
+ }
+ else if (blen < USE_SCRAMBLE)
+ {
+ for (i=0; i<blen; i+=8)
+ fprintf(f, "%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,\n",
+ scramble[tab[i+0].val_b], scramble[tab[i+1].val_b],
+ scramble[tab[i+2].val_b], scramble[tab[i+3].val_b],
+ scramble[tab[i+4].val_b], scramble[tab[i+5].val_b],
+ scramble[tab[i+6].val_b], scramble[tab[i+7].val_b]);
+ }
+ else
+ {
+ for (i=0; i<blen; i+=16)
+ fprintf(f, "%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,\n",
+ tab[i+0].val_b, tab[i+1].val_b,
+ tab[i+2].val_b, tab[i+3].val_b,
+ tab[i+4].val_b, tab[i+5].val_b,
+ tab[i+6].val_b, tab[i+7].val_b,
+ tab[i+8].val_b, tab[i+9].val_b,
+ tab[i+10].val_b, tab[i+11].val_b,
+ tab[i+12].val_b, tab[i+13].val_b,
+ tab[i+14].val_b, tab[i+15].val_b);
+ }
+ fprintf(f, "};\n");
+ fprintf(f, "\n");
+ }
+ fprintf(f, "/* The hash function */\n");
+ switch(form->mode)
+ {
+ case NORMAL_HM:
+ fprintf(f, "ub4 phash(key, len)\n");
+ fprintf(f, "char *key;\n");
+ fprintf(f, "int len;\n");
+ break;
+ case INLINE_HM:
+ case HEX_HM:
+ case DECIMAL_HM:
+ fprintf(f, "ub4 phash(val)\n");
+ fprintf(f, "ub4 val;\n");
+ break;
+ case AB_HM:
+ case ABDEC_HM:
+ fprintf(f, "ub4 phash(a,b)\n");
+ fprintf(f, "ub4 a;\n");
+ fprintf(f, "ub4 b;\n");
+ break;
+ }
+ fprintf(f, "{\n");
+ for (i=0; i<final->used; ++i)
+ fprintf(f, final->line[i]);
+ fprintf(f, " return rsl;\n");
+ fprintf(f, "}\n");
+ fprintf(f, "\n");
+ fclose(f);
+}
+
+/*
+------------------------------------------------------------------------------
+Read in the keys, find the hash, and write the .c and .h files
+------------------------------------------------------------------------------
+*/
+static void driver(form)
+hashform *form; /* user directives */
+{
+ ub4 nkeys; /* number of keys */
+ key *keys; /* head of list of keys */
+ bstuff *tab; /* table indexed by b */
+ ub4 smax; /* scramble[] values in 0..smax-1, a power of 2 */
+ ub4 alen; /* a in 0..alen-1, a power of 2 */
+ ub4 blen; /* b in 0..blen-1, a power of 2 */
+ ub4 salt; /* a parameter to the hash function */
+ reroot *textroot; /* MAXKEYLEN-character text lines */
+ reroot *keyroot; /* source of keys */
+ gencode final; /* code for final hash */
+ ub4 i;
+ ub4 scramble[SCRAMBLE_LEN]; /* used in final hash function */
+ char buf[10][80]; /* buffer for generated code */
+ char *buf2[10]; /* also for generated code */
+
+ /* set up memory sources */
+ textroot = remkroot((size_t)MAXKEYLEN);
+ keyroot = remkroot(sizeof(key));
+
+ /* set up code for final hash */
+ final.line = buf2;
+ final.used = 0;
+ final.len = 10;
+ for (i=0; i<10; ++i) final.line[i] = buf[i];
+
+ /* read in the list of keywords */
+ getkeys(&keys, &nkeys, textroot, keyroot, form);
+ printf("Read in %ld keys\n",nkeys);
+
+ /* find the hash */
+ findhash(&tab, &alen, &blen, &salt, &final,
+ scramble, &smax, keys, nkeys, form);
+
+ /* generate the phash.c file */
+ make_c(tab, smax, blen, scramble, &final, form);
+ printf("Wrote phash.c\n");
+
+ /* clean up memory sources */
+ refree(textroot);
+ refree(keyroot);
+ free((void *)tab);
+ printf("Cleaned up\n");
+}
+
+
+/* Interpret arguments and call the driver */
+/* See usage_error for the expected arguments */
+int main(argc, argv)
+int argc;
+char **argv;
+{
+ int mode_given = FALSE;
+ int minimal_given = FALSE;
+ int speed_given = FALSE;
+ hashform form;
+ char *c;
+
+ /* default behavior */
+ form.mode = NORMAL_HM;
+ form.hashtype = STRING_HT;
+ form.perfect = MINIMAL_HP;
+ form.speed = SLOW_HS;
+
+ /* Generate the [minimal] perfect hash */
+ driver(&form);
+
+ return EXIT_SUCCESS;
+}
+#endif
--- /dev/null
+/*
+------------------------------------------------------------------------------
+perfect.h: code to generate code for a hash for perfect hashing.
+(c) Bob Jenkins, September 1996
+You may use this code in any way you wish, and it is free. No warranty.
+I hereby place this in the public domain.
+Source is http://burtleburtle.net/bob/c/perfect.h
+------------------------------------------------------------------------------
+*/
+
+#ifndef STANDARD
+#include "standard.h"
+#endif
+
+#ifndef PERFECT
+#define PERFECT
+
+#define MAXKEYLEN 30 /* maximum length of a key */
+#define USE_SCRAMBLE 4096 /* use scramble if blen >= USE_SCRAMBLE */
+#define SCRAMBLE_LEN ((ub4)1<<16) /* length of *scramble* */
+#define RETRY_INITKEY 2048 /* number of times to try to find distinct (a,b) */
+#define RETRY_PERFECT 1 /* number of times to try to make a perfect hash */
+#define RETRY_HEX 200 /* RETRY_PERFECT when hex keys given */
+
+/* the generated code for the final hash, assumes initial hash is done */
+struct gencode
+{
+ char **line; /* array of text lines, 80 bytes apiece */
+ /*
+ * The code placed here must declare "ub4 rsl"
+ * and assign it the value of the perfect hash using the function inputs.
+ * Later code will be tacked on which returns rsl or manipulates it according
+ * to the user directives.
+ *
+ * This code is at the top of the routine; it may and must declare any
+ * local variables it needs.
+ *
+ * Each way of filling in **line should be given a comment that is a unique
+ * tag. A testcase named with that tag should also be found which tests
+ * the generated code.
+ */
+ ub4 len; /* number of lines available for final hash */
+ ub4 used; /* number of lines used by final hash */
+
+ ub4 lowbit; /* for HEX, lowest interesting bit */
+ ub4 highbit; /* for HEX, highest interesting bit */
+ ub4 diffbits; /* bits which differ for some key */
+ ub4 i,j,k,l,m,n,o; /* state machine used in hexn() */
+};
+typedef struct gencode gencode;
+
+/* user directives: perfect hash? minimal perfect hash? input is an int? */
+struct hashform
+{
+ enum {
+ NORMAL_HM, /* key is a string */
+ INLINE_HM, /* user will do initial hash, we must choose salt for them */
+ HEX_HM, /* key to be hashed is a hexidecimal 4-byte integer */
+ DECIMAL_HM, /* key to be hashed is a decimal 4-byte integer */
+ AB_HM, /* key to be hashed is "A B", where A and B are (A,B) in hex */
+ ABDEC_HM /* like AB_HM, but in decimal */
+ } mode;
+ enum {
+ STRING_HT, /* key is a string */
+ INT_HT, /* key is an integer */
+ AB_HT /* dunno what key is, but input is distinct (A,B) pair */
+ } hashtype;
+ enum {
+ NORMAL_HP, /* just find a perfect hash */
+ MINIMAL_HP /* find a minimal perfect hash */
+ } perfect;
+ enum {
+ FAST_HS, /* fast mode */
+ SLOW_HS /* slow mode */
+ } speed;
+};
+typedef struct hashform hashform;
+
+/* representation of a key */
+struct key
+{
+ ub1 *name_k; /* the actual key */
+ ub4 len_k; /* the length of the actual key */
+ ub4 hash_k; /* the initial hash value for this key */
+ struct key *next_k; /* next key */
+/* beyond this point is mapping-dependent */
+ ub4 a_k; /* a, of the key maps to (a,b) */
+ ub4 b_k; /* b, of the key maps to (a,b) */
+ struct key *nextb_k; /* next key with this b */
+};
+typedef struct key key;
+
+/* things indexed by b of original (a,b) pair */
+struct bstuff
+{
+ ub2 val_b; /* hash=a^tabb[b].val_b */
+ key *list_b; /* tabb[i].list_b is list of keys with b==i */
+ ub4 listlen_b; /* length of list_b */
+ ub4 water_b; /* high watermark of who has visited this map node */
+};
+typedef struct bstuff bstuff;
+
+/* things indexed by final hash value */
+struct hstuff
+{
+ key *key_h; /* tabh[i].key_h is the key with a hash of i */
+};
+typedef struct hstuff hstuff;
+
+/* things indexed by queue position */
+struct qstuff
+{
+ bstuff *b_q; /* b that currently occupies this hash */
+ ub4 parent_q; /* queue position of parent that could use this hash */
+ ub2 newval_q; /* what to change parent tab[b] to to use this hash */
+ ub2 oldval_q; /* original value of tab[b] */
+};
+typedef struct qstuff qstuff;
+
+/* return ceiling(log based 2 of x) */
+ub4 phash_log2(ub4 x);
+
+/* Given the keys, scramble[], and hash mode, find the perfect hash */
+void findhash(bstuff **tabb, hstuff **tabh, ub4 *alen, ub4 *blen, ub4 *salt,
+ gencode *final, ub4 *scramble, ub4 *smax, key *keys, ub4 nkeys,
+ hashform *form);
+
+/* private, but in a different file because it's excessively verbose */
+int inithex(key *keys, ub4 nkeys, ub4 alen, ub4 blen, ub4 smax, ub4 salt,
+ gencode *final, hashform *form);
+
+#endif /* PERFECT */
--- /dev/null
+/*
+------------------------------------------------------------------------------
+Standard definitions and types, Bob Jenkins
+------------------------------------------------------------------------------
+*/
+#ifndef STANDARD
+#define STANDARD
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+typedef unsigned long int ub4; /* unsigned 4-byte quantities */
+#define UB4BITS 32
+typedef unsigned short int ub2;
+#define UB2MAXVAL 0xffff
+typedef unsigned char ub1;
+#define UB1MAXVAL 0xff
+typedef int word; /* fastest type available */
+
+#define bis(target,mask) ((target) |= (mask))
+#define bic(target,mask) ((target) &= ~(mask))
+#define bit(target,mask) ((target) & (mask))
+#ifndef align
+# define align(a) (((ub4)a+(sizeof(void *)-1))&(~(sizeof(void *)-1)))
+#endif /* align */
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#endif /* STANDARD */