aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/yasm
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/tools/yasm
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/tools/yasm')
-rw-r--r--contrib/tools/yasm/bin/ya.make120
-rw-r--r--contrib/tools/yasm/config-osx-linux.h48
-rw-r--r--contrib/tools/yasm/config-win.h48
-rw-r--r--contrib/tools/yasm/config.h7
-rw-r--r--contrib/tools/yasm/frontends/tasm/license.c65
-rw-r--r--contrib/tools/yasm/frontends/tasm/tasm-options.c127
-rw-r--r--contrib/tools/yasm/frontends/tasm/tasm-options.h69
-rw-r--r--contrib/tools/yasm/frontends/tasm/tasm.c1009
-rw-r--r--contrib/tools/yasm/frontends/vsyasm/license.c65
-rw-r--r--contrib/tools/yasm/frontends/vsyasm/vsyasm.c1424
-rw-r--r--contrib/tools/yasm/frontends/yasm/license.c65
-rw-r--r--contrib/tools/yasm/frontends/yasm/yasm-options.c216
-rw-r--r--contrib/tools/yasm/frontends/yasm/yasm-options.h75
-rw-r--r--contrib/tools/yasm/frontends/yasm/yasm-plugin.c126
-rw-r--r--contrib/tools/yasm/frontends/yasm/yasm-plugin.h34
-rw-r--r--contrib/tools/yasm/frontends/yasm/yasm.c1454
-rw-r--r--contrib/tools/yasm/libyasm-stdint.h46
-rw-r--r--contrib/tools/yasm/libyasm.h75
-rw-r--r--contrib/tools/yasm/libyasm/arch.h495
-rw-r--r--contrib/tools/yasm/libyasm/assocdat.c138
-rw-r--r--contrib/tools/yasm/libyasm/assocdat.h76
-rw-r--r--contrib/tools/yasm/libyasm/bc-align.c245
-rw-r--r--contrib/tools/yasm/libyasm/bc-data.c600
-rw-r--r--contrib/tools/yasm/libyasm/bc-incbin.c265
-rw-r--r--contrib/tools/yasm/libyasm/bc-org.c152
-rw-r--r--contrib/tools/yasm/libyasm/bc-reserve.c152
-rw-r--r--contrib/tools/yasm/libyasm/bitvect.c4045
-rw-r--r--contrib/tools/yasm/libyasm/bitvect.h666
-rw-r--r--contrib/tools/yasm/libyasm/bytecode.c386
-rw-r--r--contrib/tools/yasm/libyasm/bytecode.h638
-rw-r--r--contrib/tools/yasm/libyasm/cmake-module.c126
-rw-r--r--contrib/tools/yasm/libyasm/compat-queue.h456
-rw-r--r--contrib/tools/yasm/libyasm/coretype.h393
-rw-r--r--contrib/tools/yasm/libyasm/dbgfmt.h131
-rw-r--r--contrib/tools/yasm/libyasm/errwarn.c537
-rw-r--r--contrib/tools/yasm/libyasm/errwarn.h351
-rw-r--r--contrib/tools/yasm/libyasm/expr.c1516
-rw-r--r--contrib/tools/yasm/libyasm/expr.h388
-rw-r--r--contrib/tools/yasm/libyasm/file.c672
-rw-r--r--contrib/tools/yasm/libyasm/file.h525
-rw-r--r--contrib/tools/yasm/libyasm/floatnum.c760
-rw-r--r--contrib/tools/yasm/libyasm/floatnum.h131
-rw-r--r--contrib/tools/yasm/libyasm/genmodule.c228
-rw-r--r--contrib/tools/yasm/libyasm/hamt.c421
-rw-r--r--contrib/tools/yasm/libyasm/hamt.h123
-rw-r--r--contrib/tools/yasm/libyasm/insn.c295
-rw-r--r--contrib/tools/yasm/libyasm/insn.h269
-rw-r--r--contrib/tools/yasm/libyasm/intnum.c1096
-rw-r--r--contrib/tools/yasm/libyasm/intnum.h340
-rw-r--r--contrib/tools/yasm/libyasm/inttree.c891
-rw-r--r--contrib/tools/yasm/libyasm/inttree.h70
-rw-r--r--contrib/tools/yasm/libyasm/linemap.c293
-rw-r--r--contrib/tools/yasm/libyasm/linemap.h141
-rw-r--r--contrib/tools/yasm/libyasm/listfmt.h124
-rw-r--r--contrib/tools/yasm/libyasm/md5.c309
-rw-r--r--contrib/tools/yasm/libyasm/md5.h32
-rw-r--r--contrib/tools/yasm/libyasm/mergesort.c361
-rw-r--r--contrib/tools/yasm/libyasm/module.h82
-rw-r--r--contrib/tools/yasm/libyasm/objfmt.h225
-rw-r--r--contrib/tools/yasm/libyasm/parser.h67
-rw-r--r--contrib/tools/yasm/libyasm/phash.c268
-rw-r--r--contrib/tools/yasm/libyasm/phash.h19
-rw-r--r--contrib/tools/yasm/libyasm/preproc.h210
-rw-r--r--contrib/tools/yasm/libyasm/replace_path.c54
-rw-r--r--contrib/tools/yasm/libyasm/section.c1585
-rw-r--r--contrib/tools/yasm/libyasm/section.h384
-rw-r--r--contrib/tools/yasm/libyasm/strcasecmp.c94
-rw-r--r--contrib/tools/yasm/libyasm/strsep.c85
-rw-r--r--contrib/tools/yasm/libyasm/symrec.c714
-rw-r--r--contrib/tools/yasm/libyasm/symrec.h437
-rw-r--r--contrib/tools/yasm/libyasm/valparam.c385
-rw-r--r--contrib/tools/yasm/libyasm/valparam.h408
-rw-r--r--contrib/tools/yasm/libyasm/value.c771
-rw-r--r--contrib/tools/yasm/libyasm/value.h172
-rw-r--r--contrib/tools/yasm/libyasm/xmalloc.c114
-rw-r--r--contrib/tools/yasm/libyasm/xstrdup.c68
-rw-r--r--contrib/tools/yasm/modules/arch/lc3b/lc3barch.c212
-rw-r--r--contrib/tools/yasm/modules/arch/lc3b/lc3barch.h70
-rw-r--r--contrib/tools/yasm/modules/arch/lc3b/lc3bbc.c249
-rw-r--r--contrib/tools/yasm/modules/arch/x86/x86arch.c633
-rw-r--r--contrib/tools/yasm/modules/arch/x86/x86arch.h336
-rw-r--r--contrib/tools/yasm/modules/arch/x86/x86bc.c1062
-rw-r--r--contrib/tools/yasm/modules/arch/x86/x86expr.c1061
-rw-r--r--contrib/tools/yasm/modules/arch/x86/x86id.c1951
-rw-r--r--contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.c107
-rw-r--r--contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.h58
-rw-r--r--contrib/tools/yasm/modules/dbgfmts/codeview/cv-symline.c1102
-rw-r--r--contrib/tools/yasm/modules/dbgfmts/codeview/cv-type.c778
-rw-r--r--contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-aranges.c125
-rw-r--r--contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c348
-rw-r--r--contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.h131
-rw-r--r--contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-info.c438
-rw-r--r--contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-line.c1156
-rw-r--r--contrib/tools/yasm/modules/dbgfmts/null/null-dbgfmt.c64
-rw-r--r--contrib/tools/yasm/modules/dbgfmts/stabs/stabs-dbgfmt.c511
-rw-r--r--contrib/tools/yasm/modules/gas-token.c1407
-rw-r--r--contrib/tools/yasm/modules/init_plugin.c86
-rw-r--r--contrib/tools/yasm/modules/lc3bid.c915
-rw-r--r--contrib/tools/yasm/modules/listfmts/nasm/nasm-listfmt.c301
-rw-r--r--contrib/tools/yasm/modules/nasm-macros.c94
-rw-r--r--contrib/tools/yasm/modules/nasm-token.c3217
-rw-r--r--contrib/tools/yasm/modules/nasm-version.c15
-rw-r--r--contrib/tools/yasm/modules/objfmts/bin/bin-objfmt.c1972
-rw-r--r--contrib/tools/yasm/modules/objfmts/coff/coff-objfmt.c2522
-rw-r--r--contrib/tools/yasm/modules/objfmts/coff/coff-objfmt.h77
-rw-r--r--contrib/tools/yasm/modules/objfmts/coff/win64-except.c559
-rw-r--r--contrib/tools/yasm/modules/objfmts/dbg/dbg-objfmt.c183
-rw-r--r--contrib/tools/yasm/modules/objfmts/elf/elf-machine.h108
-rw-r--r--contrib/tools/yasm/modules/objfmts/elf/elf-objfmt.c1403
-rw-r--r--contrib/tools/yasm/modules/objfmts/elf/elf-x86-amd64.c256
-rw-r--r--contrib/tools/yasm/modules/objfmts/elf/elf-x86-x32.c251
-rw-r--r--contrib/tools/yasm/modules/objfmts/elf/elf-x86-x86.c242
-rw-r--r--contrib/tools/yasm/modules/objfmts/elf/elf.c960
-rw-r--r--contrib/tools/yasm/modules/objfmts/elf/elf.h532
-rw-r--r--contrib/tools/yasm/modules/objfmts/macho/macho-objfmt.c1620
-rw-r--r--contrib/tools/yasm/modules/objfmts/rdf/rdf-objfmt.c1088
-rw-r--r--contrib/tools/yasm/modules/objfmts/xdf/xdf-objfmt.c842
-rw-r--r--contrib/tools/yasm/modules/parsers/gas/gas-parse-intel.c90
-rw-r--r--contrib/tools/yasm/modules/parsers/gas/gas-parse.c1766
-rw-r--r--contrib/tools/yasm/modules/parsers/gas/gas-parser.c133
-rw-r--r--contrib/tools/yasm/modules/parsers/gas/gas-parser.h163
-rw-r--r--contrib/tools/yasm/modules/parsers/nasm/nasm-parse.c1680
-rw-r--r--contrib/tools/yasm/modules/parsers/nasm/nasm-parser-struct.h85
-rw-r--r--contrib/tools/yasm/modules/parsers/nasm/nasm-parser.c140
-rw-r--r--contrib/tools/yasm/modules/parsers/nasm/nasm-parser.h123
-rw-r--r--contrib/tools/yasm/modules/preprocs/cpp/cpp-preproc.c402
-rw-r--r--contrib/tools/yasm/modules/preprocs/gas/gas-eval.c444
-rw-r--r--contrib/tools/yasm/modules/preprocs/gas/gas-eval.h120
-rw-r--r--contrib/tools/yasm/modules/preprocs/gas/gas-preproc.c1409
-rw-r--r--contrib/tools/yasm/modules/preprocs/nasm/genversion.c81
-rw-r--r--contrib/tools/yasm/modules/preprocs/nasm/nasm-eval.c441
-rw-r--r--contrib/tools/yasm/modules/preprocs/nasm/nasm-eval.h18
-rw-r--r--contrib/tools/yasm/modules/preprocs/nasm/nasm-pp.c5317
-rw-r--r--contrib/tools/yasm/modules/preprocs/nasm/nasm-pp.h22
-rw-r--r--contrib/tools/yasm/modules/preprocs/nasm/nasm-preproc.c342
-rw-r--r--contrib/tools/yasm/modules/preprocs/nasm/nasm.h283
-rw-r--r--contrib/tools/yasm/modules/preprocs/nasm/nasmlib.c201
-rw-r--r--contrib/tools/yasm/modules/preprocs/nasm/nasmlib.h60
-rw-r--r--contrib/tools/yasm/modules/preprocs/raw/raw-preproc.c169
-rw-r--r--contrib/tools/yasm/modules/win64-gas.c65
-rw-r--r--contrib/tools/yasm/modules/win64-nasm.c65
-rw-r--r--contrib/tools/yasm/modules/x86cpu.c481
-rw-r--r--contrib/tools/yasm/modules/x86insn_gas.c2154
-rw-r--r--contrib/tools/yasm/modules/x86insn_nasm.c1506
-rw-r--r--contrib/tools/yasm/modules/x86insns.c2424
-rw-r--r--contrib/tools/yasm/modules/x86regtmod.c261
-rw-r--r--contrib/tools/yasm/util.h167
-rw-r--r--contrib/tools/yasm/ya.make24
148 files changed, 79730 insertions, 0 deletions
diff --git a/contrib/tools/yasm/bin/ya.make b/contrib/tools/yasm/bin/ya.make
new file mode 100644
index 0000000000..96ca75c53e
--- /dev/null
+++ b/contrib/tools/yasm/bin/ya.make
@@ -0,0 +1,120 @@
+OWNER(
+ somov
+ g:contrib
+ g:ymake
+)
+
+PROGRAM(yasm)
+
+IF (MUSL)
+ PEERDIR(contrib/libs/musl_extra)
+ PEERDIR(contrib/libs/jemalloc)
+ DISABLE(USE_ASMLIB)
+ NO_RUNTIME()
+ ENABLE(MUSL_LITE)
+ELSE()
+ NO_PLATFORM()
+ENDIF()
+
+NO_CLANG_COVERAGE()
+NO_COMPILER_WARNINGS()
+NO_UTIL()
+
+ALLOCATOR(FAKE)
+
+ADDINCL(
+ contrib/tools/yasm
+ contrib/tools/yasm/frontends/yasm
+ contrib/tools/yasm/modules
+)
+
+CFLAGS(
+ -DHAVE_CONFIG_H
+ -DYASM_LIB_SOURCE
+)
+
+SRCDIR(contrib/tools/yasm)
+
+SRCS(
+ frontends/yasm/yasm-options.c
+ frontends/yasm/yasm.c
+ libyasm/assocdat.c
+ libyasm/bc-align.c
+ libyasm/bc-data.c
+ libyasm/bc-incbin.c
+ libyasm/bc-org.c
+ libyasm/bc-reserve.c
+ libyasm/bitvect.c
+ libyasm/bytecode.c
+ libyasm/cmake-module.c
+ libyasm/errwarn.c
+ libyasm/expr.c
+ libyasm/file.c
+ libyasm/floatnum.c
+ libyasm/hamt.c
+ libyasm/insn.c
+ libyasm/intnum.c
+ libyasm/inttree.c
+ libyasm/linemap.c
+ libyasm/md5.c
+ libyasm/mergesort.c
+ libyasm/phash.c
+ libyasm/replace_path.c
+ libyasm/section.c
+ libyasm/strcasecmp.c
+ libyasm/strsep.c
+ libyasm/symrec.c
+ libyasm/valparam.c
+ libyasm/value.c
+ libyasm/xmalloc.c
+ libyasm/xstrdup.c
+ modules/arch/lc3b/lc3barch.c
+ modules/arch/lc3b/lc3bbc.c
+ modules/arch/x86/x86arch.c
+ modules/arch/x86/x86bc.c
+ modules/arch/x86/x86expr.c
+ modules/arch/x86/x86id.c
+ modules/dbgfmts/codeview/cv-dbgfmt.c
+ modules/dbgfmts/codeview/cv-symline.c
+ modules/dbgfmts/codeview/cv-type.c
+ modules/dbgfmts/dwarf2/dwarf2-aranges.c
+ modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c
+ modules/dbgfmts/dwarf2/dwarf2-info.c
+ modules/dbgfmts/dwarf2/dwarf2-line.c
+ modules/dbgfmts/null/null-dbgfmt.c
+ modules/dbgfmts/stabs/stabs-dbgfmt.c
+ modules/gas-token.c
+ modules/init_plugin.c
+ modules/lc3bid.c
+ modules/listfmts/nasm/nasm-listfmt.c
+ modules/nasm-token.c
+ modules/objfmts/bin/bin-objfmt.c
+ modules/objfmts/coff/coff-objfmt.c
+ modules/objfmts/coff/win64-except.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-x32.c
+ modules/objfmts/elf/elf-x86-x86.c
+ modules/objfmts/elf/elf.c
+ modules/objfmts/macho/macho-objfmt.c
+ modules/objfmts/rdf/rdf-objfmt.c
+ modules/objfmts/xdf/xdf-objfmt.c
+ modules/parsers/gas/gas-parse-intel.c
+ modules/parsers/gas/gas-parse.c
+ modules/parsers/gas/gas-parser.c
+ modules/parsers/nasm/nasm-parse.c
+ modules/parsers/nasm/nasm-parser.c
+ modules/preprocs/cpp/cpp-preproc.c
+ modules/preprocs/gas/gas-eval.c
+ modules/preprocs/gas/gas-preproc.c
+ modules/preprocs/nasm/nasm-eval.c
+ modules/preprocs/nasm/nasm-pp.c
+ modules/preprocs/nasm/nasm-preproc.c
+ modules/preprocs/nasm/nasmlib.c
+ modules/preprocs/raw/raw-preproc.c
+ modules/x86cpu.c
+ modules/x86regtmod.c
+)
+
+END()
diff --git a/contrib/tools/yasm/config-osx-linux.h b/contrib/tools/yasm/config-osx-linux.h
new file mode 100644
index 0000000000..7096e2a4c9
--- /dev/null
+++ b/contrib/tools/yasm/config-osx-linux.h
@@ -0,0 +1,48 @@
+/* config.h. Generated by cmake from config.h.cmake */
+
+#define CMAKE_BUILD 1
+
+/* Define if shared libs are being built */
+/* #undef BUILD_SHARED_LIBS */
+
+/* Define if messsage translations are enabled */
+/* #undef ENABLE_NLS */
+
+/* */
+#undef HAVE_GETTEXT
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#define HAVE_LIBGEN_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <direct.h> header file. */
+/* #undef HAVE_DIRECT_H */
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `toascii' function. */
+#define HAVE_TOASCII 1
+
+/* Name of package */
+#define PACKAGE "yasm"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bug-yasm@tortall.net"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "yasm"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "yasm 1.3.0"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.3.0"
+
+#define VERSION PACKAGE_VERSION
+
+/* Command name to run C preprocessor */
+#define CPP_PROG "/usr/bin/cpp"
+
diff --git a/contrib/tools/yasm/config-win.h b/contrib/tools/yasm/config-win.h
new file mode 100644
index 0000000000..b924e3ebfd
--- /dev/null
+++ b/contrib/tools/yasm/config-win.h
@@ -0,0 +1,48 @@
+/* config.h. Generated by cmake from config.h.cmake */
+
+#define CMAKE_BUILD 1
+
+/* Define if shared libs are being built */
+/* #undef BUILD_SHARED_LIBS */
+
+/* Define if messsage translations are enabled */
+/* #undef ENABLE_NLS */
+
+/* */
+#undef HAVE_GETTEXT
+
+/* Define to 1 if you have the <libgen.h> header file. */
+/* #undef HAVE_LIBGEN_H */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+/* #undef HAVE_UNISTD_H */
+
+/* Define to 1 if you have the <direct.h> header file. */
+#define HAVE_DIRECT_H 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `toascii' function. */
+/* #undef HAVE_TOASCII */
+
+/* Name of package */
+#define PACKAGE "yasm"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bug-yasm@tortall.net"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "yasm"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "yasm 1.3.0"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.3.0"
+
+#define VERSION PACKAGE_VERSION
+
+/* Command name to run C preprocessor */
+#define CPP_PROG "CPP_PROG-NOTFOUND"
+
diff --git a/contrib/tools/yasm/config.h b/contrib/tools/yasm/config.h
new file mode 100644
index 0000000000..862e891cbd
--- /dev/null
+++ b/contrib/tools/yasm/config.h
@@ -0,0 +1,7 @@
+#if defined(__APPLE__) && defined(__x86_64__)
+# include "config-osx-linux.h"
+#elif defined(_MSC_VER) && defined(_M_X64)
+# include "config-win.h"
+#else
+# include "config-osx-linux.h"
+#endif
diff --git a/contrib/tools/yasm/frontends/tasm/license.c b/contrib/tools/yasm/frontends/tasm/license.c
new file mode 100644
index 0000000000..35c5a04137
--- /dev/null
+++ b/contrib/tools/yasm/frontends/tasm/license.c
@@ -0,0 +1,65 @@
+/* This file auto-generated from COPYING by genstring.py - don't edit it */
+
+static const char* license_msg[] = {
+ "Yasm is Copyright (c) 2001-2014 Peter Johnson and other Yasm developers.",
+ "",
+ "Yasm developers and/or contributors include:",
+ "Peter Johnson",
+ "Michael Urman",
+ "Brian Gladman (Visual Studio build files, other fixes)",
+ "Stanislav Karchebny (options parser)",
+ "Mathieu Monnier (SSE4 instruction patches, NASM preprocessor additions)",
+ "Anonymous \"NASM64\" developer (NASM preprocessor fixes)",
+ "Stephen Polkowski (x86 instruction patches)",
+ "Henryk Richter (Mach-O object format)",
+ "Ben Skeggs (patches, bug reports)",
+ "Alexei Svitkine (GAS preprocessor)",
+ "Samuel Thibault (TASM parser and frontend)",
+ "",
+ "-----------------------------------",
+ "Yasm licensing overview and summary",
+ "-----------------------------------",
+ "",
+ "Note: This document does not provide legal advice nor is it the actual",
+ "license of any part of Yasm. See the individual licenses for complete",
+ "details. Consult a lawyer for legal advice.",
+ "",
+ "The primary license of Yasm is the 2-clause BSD license. Please use this",
+ "license if you plan on submitting code to the project.",
+ "",
+ "Yasm has absolutely no warranty; not even for merchantibility or fitness",
+ "for a particular purpose.",
+ "",
+ "-------",
+ "Libyasm",
+ "-------",
+ "Libyasm is 2-clause or 3-clause BSD licensed, with the exception of",
+ "bitvect, which is triple-licensed under the Artistic license, GPL, and",
+ "LGPL. Libyasm is thus GPL and LGPL compatible. In addition, this also",
+ "means that libyasm is free for binary-only distribution as long as the",
+ "terms of the 3-clause BSD license and Artistic license (as it applies to",
+ "bitvect) are fulfilled.",
+ "",
+ "-------",
+ "Modules",
+ "-------",
+ "The modules are 2-clause or 3-clause BSD licensed.",
+ "",
+ "---------",
+ "Frontends",
+ "---------",
+ "The frontends are 2-clause BSD licensed.",
+ "",
+ "-------------",
+ "License Texts",
+ "-------------",
+ "The full text of all licenses are provided in separate files in the source",
+ "distribution. Each source file may include the entire license (in the case",
+ "of the BSD and Artistic licenses), or may reference the GPL or LGPL license",
+ "file.",
+ "",
+ "BSD.txt - 2-clause and 3-clause BSD licenses",
+ "Artistic.txt - Artistic license",
+ "GNU_GPL-2.0 - GNU General Public License",
+ "GNU_LGPL-2.0 - GNU Library General Public License",
+};
diff --git a/contrib/tools/yasm/frontends/tasm/tasm-options.c b/contrib/tools/yasm/frontends/tasm/tasm-options.c
new file mode 100644
index 0000000000..57c3bdfd15
--- /dev/null
+++ b/contrib/tools/yasm/frontends/tasm/tasm-options.c
@@ -0,0 +1,127 @@
+/*
+ * Generic Options Support Header File
+ *
+ * Copyright (c) 2001 Stanislav Karchebny <berk@madfire.net>
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of other contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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 <util.h>
+#include <ctype.h>
+
+#include "tasm-options.h"
+
+
+#ifdef __DEBUG__
+#define DEBUG(x) fprintf ## x ;
+#else
+#define DEBUG(x)
+#endif
+
+
+/* Options Parser */
+int
+parse_cmdline(int argc, char **argv, opt_option *options, size_t nopts,
+ void (*print_error) (const char *fmt, ...))
+{
+ int errors = 0, warnings = 0;
+ size_t i;
+ int got_it;
+
+ DEBUG((stderr, "parse_cmdline: entered\n"));
+
+ fail:
+ while (--argc) {
+ argv++;
+
+ if (argv[0][0] == '/' && argv[0][1]) { /* opt */
+ got_it = 0;
+ for (i = 0; i < nopts; i++) {
+ char *cmd = &argv[0][1];
+ size_t len = strlen(options[i].opt);
+ if (yasm__strncasecmp(cmd, options[i].opt, len) == 0) {
+ char *param;
+
+ param = &argv[0][1+len];
+ if (options[i].takes_param) {
+ if (param[0] == '\0') {
+ print_error(
+ _("option `-%c' needs an argument!"),
+ options[i].opt);
+ errors++;
+ goto fail;
+ } else {
+ argc--;
+ argv++;
+ }
+ } else
+ param = NULL;
+
+ if (!options[i].handler(cmd, param, options[i].extra))
+ got_it = 1;
+ break;
+ }
+ }
+ if (!got_it) {
+ print_error(_("warning: unrecognized option `%s'"),
+ argv[0]);
+ warnings++;
+ }
+ } else { /* not an option, then it should be a file or something */
+
+ if (not_an_option_handler(argv[0]))
+ errors++;
+ }
+ }
+
+ DEBUG((stderr, "parse_cmdline: finished\n"));
+ return errors;
+}
+
+void
+help_msg(const char *msg, const char *tail, opt_option *options, size_t nopts)
+{
+ char optbuf[100];
+ size_t i;
+
+ printf("%s", gettext(msg));
+
+ for (i = 0; i < nopts; i++) {
+ optbuf[0] = 0;
+
+ if (options[i].takes_param) {
+ if (options[i].opt)
+ sprintf(optbuf, "/%s <%s>", options[i].opt,
+ options[i].param_desc ? options[i].
+ param_desc : _("param"));
+ } else {
+ if (options[i].opt)
+ sprintf(optbuf, "/%s", options[i].opt);
+ }
+
+ printf(" %-22s %s\n", optbuf, gettext(options[i].description));
+ }
+
+ printf("%s", gettext(tail));
+}
diff --git a/contrib/tools/yasm/frontends/tasm/tasm-options.h b/contrib/tools/yasm/frontends/tasm/tasm-options.h
new file mode 100644
index 0000000000..082409fc24
--- /dev/null
+++ b/contrib/tools/yasm/frontends/tasm/tasm-options.h
@@ -0,0 +1,69 @@
+/*
+ * Generic Options Support Header File
+ *
+ * Copyright (c) 2001 Stanislav Karchebny <berk@madfire.net>
+ *
+ * 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.
+ */
+#ifndef TASM_OPTIONS_H
+#define TASM_OPTIONS_H
+
+/* an option structure
+ * operate on either -sopt, --lopt, -sopt <val> or --lopt=<val>
+ */
+typedef struct opt_option_s
+{
+ /* option */
+ const char *opt;
+
+ /* !=0 if option requires parameter, 0 if not */
+ int takes_param;
+
+ int (*handler) (char *cmd, /*@null@*/ char *param, int extra);
+ int extra; /* extra value for handler */
+
+ /* description to use in help_msg() */
+ /*@observer@*/ const char *description;
+
+ /* optional description for the param taken (NULL if not present) */
+ /* (short - will be printed after option sopt/lopt) */
+ /*@observer@*/ /*@null@*/ const char *param_desc;
+} opt_option;
+
+/* handle everything that is not an option */
+int not_an_option_handler(char *param);
+
+/* parse command line calling handlers when appropriate
+ * argc, argv - pass directly from main(argc,argv)
+ * options - array of options
+ * nopts - options count
+ */
+int parse_cmdline(int argc, char **argv, opt_option *options, size_t nopts,
+ void (*print_error) (const char *fmt, ...));
+
+/* display help message msg followed by list of options in options and followed
+ * by tail
+ */
+void help_msg(const char *msg, const char *tail, opt_option *options,
+ size_t nopts);
+
+#endif
diff --git a/contrib/tools/yasm/frontends/tasm/tasm.c b/contrib/tools/yasm/frontends/tasm/tasm.c
new file mode 100644
index 0000000000..58954b6457
--- /dev/null
+++ b/contrib/tools/yasm/frontends/tasm/tasm.c
@@ -0,0 +1,1009 @@
+/*
+ * Program entry point, command line parsing
+ *
+ * Copyright (C) 2001-2008 Peter Johnson
+ * Copyright (C) 2007-2008 Samuel Thibault
+ *
+ * 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 <util.h>
+
+#include <ctype.h>
+#include <libyasm/compat-queue.h>
+#include <libyasm/bitvect.h>
+#include <libyasm.h>
+
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
+
+#include "tasm-options.h"
+
+#if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
+#include "yasm-plugin.h"
+#endif
+
+#include "license.c"
+
+#define DEFAULT_OBJFMT_MODULE "bin"
+
+#if defined(CMAKE_BUILD) && !defined(BUILD_SHARED_LIBS)
+void yasm_init_plugin(void);
+#endif
+
+/*@null@*/ /*@only@*/ static char *obj_filename = NULL, *in_filename = NULL;
+/*@null@*/ /*@only@*/ static char *list_filename = NULL, *xref_filename = NULL;
+/*@null@*/ /*@only@*/ static char *machine_name = NULL;
+static int special_options = 0;
+static int segment_ordering = 0;
+static int cross_reference = 0;
+static int floating_point = 0;
+static int listing = 0;
+static int expanded_listing = 0;
+static int case_sensitivity = 0;
+static int valid_length = -1;
+/*@null@*/ /*@dependent@*/ static yasm_arch *cur_arch = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_arch_module *
+ cur_arch_module = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_parser_module *
+ cur_parser_module = NULL;
+/*@null@*/ /*@dependent@*/ static yasm_preproc *cur_preproc = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_preproc_module *
+ cur_preproc_module = NULL;
+/*@null@*/ static char *objfmt_keyword = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_objfmt_module *
+ cur_objfmt_module = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_dbgfmt_module *
+ cur_dbgfmt_module = NULL;
+/*@null@*/ /*@dependent@*/ static yasm_listfmt *cur_listfmt = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_listfmt_module *
+ cur_listfmt_module = NULL;
+static int warning_error = 0; /* warnings being treated as errors */
+static FILE *errfile;
+/*@null@*/ /*@only@*/ static char *error_filename = NULL;
+
+/*@null@*/ /*@dependent@*/ static FILE *open_file(const char *filename,
+ const char *mode);
+static void check_errors(/*@only@*/ yasm_errwarns *errwarns,
+ /*@only@*/ yasm_object *object,
+ /*@only@*/ yasm_linemap *linemap);
+static void cleanup(/*@null@*/ /*@only@*/ yasm_object *object);
+
+/* Forward declarations: cmd line parser handlers */
+static int opt_special_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_segment_ordering_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_cross_reference_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_floating_point_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_ignore(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_listing_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_case_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_valid_length_handler(char *cmd, /*@null@*/ char *param, int extra);
+
+static int opt_warning_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_preproc_option(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_exe_handler(char *cmd, /*@null@*/ char *param, int extra);
+
+static /*@only@*/ char *replace_extension(const char *orig, /*@null@*/
+ const char *ext, const char *def);
+static void print_error(const char *fmt, ...);
+
+static /*@exits@*/ void handle_yasm_int_error(const char *file,
+ unsigned int line,
+ const char *message);
+static /*@exits@*/ void handle_yasm_fatal(const char *message, va_list va);
+static const char *handle_yasm_gettext(const char *msgid);
+static void print_yasm_error(const char *filename, unsigned long line,
+ const char *msg, /*@null@*/ const char *xref_fn,
+ unsigned long xref_line,
+ /*@null@*/ const char *xref_msg);
+static void print_yasm_warning(const char *filename, unsigned long line,
+ const char *msg);
+
+static void apply_preproc_builtins(void);
+static void apply_preproc_standard_macros(const yasm_stdmac *stdmacs);
+static void apply_preproc_saved_options(void);
+static void print_list_keyword_desc(const char *name, const char *keyword);
+
+/* values for special_options */
+#define SPECIAL_SHOW_HELP 0x01
+#define SPECIAL_SHOW_VERSION 0x02
+#define SPECIAL_SHOW_LICENSE 0x04
+
+#define SEGMENT_ORDERING_ALPHABETIC 0x01
+#define SEGMENT_ORDERING_SOURCE 0x02
+
+#define FP_EMULATED 0x01
+#define FP_REAL 0x02
+
+#define CASE_ALL 0x01
+#define CASE_GLOBALS 0x02
+#define CASE_NONE 0x04
+
+#define DEBUG_FULL 0x01
+#define DEBUG_LINES 0x02
+#define DEBUG_NONE 0x04
+
+/* command line options */
+static opt_option options[] =
+{
+ { "version", 0, opt_special_handler, SPECIAL_SHOW_VERSION,
+ N_("show version text"), NULL },
+ { "license", 0, opt_special_handler, SPECIAL_SHOW_LICENSE,
+ N_("show license text"), NULL },
+ { "a", 0, opt_segment_ordering_handler, SEGMENT_ORDERING_ALPHABETIC,
+ N_("Alphabetic segment ordering"), NULL },
+ { "s", 0, opt_segment_ordering_handler, SEGMENT_ORDERING_SOURCE,
+ N_("Source segment ordering"), NULL },
+
+ { "c", 0, opt_cross_reference_handler, 0,
+ N_("Generate cross-reference in listing"), NULL },
+
+ { "d", 1, opt_preproc_option, 2,
+ N_("pre-define a macro, optionally to value"), N_("macro[=value]") },
+
+ { "e", 0, opt_floating_point_handler, FP_EMULATED,
+ N_("Emulated floating-point instructions (not supported)"), NULL },
+ { "r", 0, opt_floating_point_handler, FP_REAL,
+ N_("Real floating-point instructions"), NULL },
+
+ { "h", 0, opt_special_handler, SPECIAL_SHOW_HELP,
+ N_("show help text"), NULL },
+ { "?", 0, opt_special_handler, SPECIAL_SHOW_HELP,
+ N_("show help text"), NULL },
+
+ { "i", 1, opt_preproc_option, 0,
+ N_("add include path"), N_("path") },
+
+ { "j", 1, opt_ignore, 0,
+ N_("Jam in an assemble directive CMD (eg. /jIDEAL) (not supported)"), NULL },
+
+ { "k", 1, opt_ignore, 0,
+ N_("Hash table capacity (ignored)"), N_("# symbols") },
+
+ { "l", 0, opt_listing_handler, 0,
+ N_("Generate listing"), N_("l=normal listing, la=expanded listing") },
+
+ { "ml", 0, opt_case_handler, CASE_ALL,
+ N_("Case sensitivity on all symbols"), NULL },
+ { "mx", 0, opt_case_handler, CASE_GLOBALS,
+ N_("Case sensitivity on global symbols"), NULL },
+ { "mu", 0, opt_case_handler, CASE_NONE,
+ N_("No case sensitivity on symbols"), NULL },
+ { "mv", 0, opt_valid_length_handler, 0,
+ N_("Set maximum valid length for symbols"), N_("length") },
+
+ { "m", 1, opt_ignore, 0,
+ N_("Allow multiple passes to resolve forward reference (ignored)"), N_("number of passes") },
+
+ { "n", 0, opt_ignore, 0,
+ N_("Suppress symbol tables in listing"), NULL },
+
+ { "o", 0, opt_ignore, 0,
+ N_("Object code"), N_("os: standard, o: standard w/overlays, op: Phar Lap, oi: IBM") },
+
+ { "p", 0, opt_ignore, 0,
+ N_("Check for code segment overrides in protected mode"), NULL },
+ { "q", 0, opt_ignore, 0,
+ N_("Suppress OBJ records not needed for linking (ignored)"), NULL },
+ { "t", 0, opt_ignore, 0,
+ N_("Suppress messages if successful assembly"), NULL },
+ { "u", 0, opt_ignore, 0,
+ N_("Set version emulation"), N_("Version") },
+ { "w", 1, opt_warning_handler, 0,
+ N_("Set warning level"), N_("w0=none, w1=w2=warnings on, w-xxx/w+xxx=disable/enable warning xxx") },
+ { "x", 0, opt_ignore, 0,
+ N_("Include false conditionals in listing"), NULL },
+ { "zi", 0, opt_ignore, DEBUG_FULL,
+ N_("Full debug info"), NULL },
+ { "zd", 0, opt_ignore, DEBUG_LINES,
+ N_("Line numbers debug info"), NULL },
+ { "zn", 0, opt_ignore, DEBUG_NONE,
+ N_("No debug info"), NULL },
+ { "z", 0, opt_ignore, 0,
+ N_("Display source line with error message (ignored)"), NULL },
+
+ { "b", 0, opt_exe_handler, 0,
+ N_("Build a (very) basic .exe file"), NULL },
+};
+
+/* version message */
+/*@observer@*/ static const char *version_msg[] = {
+ PACKAGE_STRING,
+ "Compiled on " __DATE__ ".",
+ "Copyright (c) 2001-2010 Peter Johnson and other Yasm developers.",
+ "Run yasm --license for licensing overview and summary."
+};
+
+/* help messages */
+/*@observer@*/ static const char *help_head = N_(
+ "usage: tasm [option]* source [,object] [,listing] [,xref] \n"
+ "Options:\n");
+/*@observer@*/ static const char *help_tail = N_(
+ "\n"
+ "source is asm source to be assembled.\n"
+ "\n"
+ "Sample invocation:\n"
+ " tasm /zi source.asm\n"
+ "\n"
+ "Report bugs to bug-yasm@tortall.net\n");
+
+/* parsed command line storage until appropriate modules have been loaded */
+typedef STAILQ_HEAD(constcharparam_head, constcharparam) constcharparam_head;
+
+typedef struct constcharparam {
+ STAILQ_ENTRY(constcharparam) link;
+ const char *param;
+ int id;
+} constcharparam;
+
+static constcharparam_head preproc_options;
+
+static int
+do_assemble(void)
+{
+ yasm_object *object;
+ const char *base_filename;
+ /*@null@*/ FILE *obj = NULL;
+ yasm_arch_create_error arch_error;
+ yasm_linemap *linemap;
+ yasm_errwarns *errwarns = yasm_errwarns_create();
+ int i, matched;
+
+ /* Initialize line map */
+ linemap = yasm_linemap_create();
+ yasm_linemap_set(linemap, in_filename, 0, 1, 1);
+
+ /* determine the object filename if not specified */
+ if (!obj_filename) {
+ if (in_filename == NULL)
+ /* Default to yasm.out if no obj filename specified */
+ obj_filename = yasm__xstrdup("yasm.out");
+ else {
+ /* replace (or add) extension to base filename */
+ yasm__splitpath(in_filename, &base_filename);
+ if (base_filename[0] == '\0')
+ obj_filename = yasm__xstrdup("yasm.out");
+ else
+ obj_filename = replace_extension(base_filename,
+ "obj",
+ "yasm.out");
+ }
+ }
+
+ cur_arch = yasm_arch_create(cur_arch_module, machine_name,
+ cur_parser_module->keyword, &arch_error);
+ if (!cur_arch) {
+ switch (arch_error) {
+ case YASM_ARCH_CREATE_BAD_MACHINE:
+ print_error(_("%s: `%s' is not a valid %s for %s `%s'"),
+ _("FATAL"), machine_name, _("machine"),
+ _("architecture"), cur_arch_module->keyword);
+ break;
+ case YASM_ARCH_CREATE_BAD_PARSER:
+ print_error(_("%s: `%s' is not a valid %s for %s `%s'"),
+ _("FATAL"), cur_parser_module->keyword,
+ _("parser"), _("architecture"),
+ cur_arch_module->keyword);
+ break;
+ default:
+ print_error(_("%s: unknown architecture error"), _("FATAL"));
+ }
+
+ return EXIT_FAILURE;
+ }
+
+ /* Create object */
+ object = yasm_object_create(in_filename, obj_filename, cur_arch,
+ cur_objfmt_module, cur_dbgfmt_module);
+ if (!object) {
+ yasm_error_class eclass;
+ unsigned long xrefline;
+ /*@only@*/ /*@null@*/ char *estr, *xrefstr;
+
+ yasm_error_fetch(&eclass, &estr, &xrefline, &xrefstr);
+ print_error("%s: %s", _("FATAL"), estr);
+ yasm_xfree(estr);
+ yasm_xfree(xrefstr);
+
+ cleanup(object);
+ return EXIT_FAILURE;
+ }
+
+ /* Get a fresh copy of objfmt_module as it may have changed. */
+ cur_objfmt_module = ((yasm_objfmt_base *)object->objfmt)->module;
+
+ /* Check to see if the requested preprocessor is in the allowed list
+ * for the active parser.
+ */
+ matched = 0;
+ for (i=0; cur_parser_module->preproc_keywords[i]; i++)
+ if (yasm__strcasecmp(cur_parser_module->preproc_keywords[i],
+ cur_preproc_module->keyword) == 0)
+ matched = 1;
+ if (!matched) {
+ print_error(_("%s: `%s' is not a valid %s for %s `%s'"), _("FATAL"),
+ cur_preproc_module->keyword, _("preprocessor"),
+ _("parser"), cur_parser_module->keyword);
+ cleanup(object);
+ return EXIT_FAILURE;
+ }
+
+ cur_preproc = yasm_preproc_create(cur_preproc_module, in_filename,
+ object->symtab, linemap, errwarns);
+
+ apply_preproc_builtins();
+ apply_preproc_standard_macros(cur_parser_module->stdmacs);
+ apply_preproc_standard_macros(cur_objfmt_module->stdmacs);
+ apply_preproc_saved_options();
+
+ /* Get initial x86 BITS setting from object format */
+ if (strcmp(cur_arch_module->keyword, "x86") == 0) {
+ yasm_arch_set_var(cur_arch, "mode_bits",
+ cur_objfmt_module->default_x86_mode_bits);
+ }
+
+ /* Parse! */
+ cur_parser_module->do_parse(object, cur_preproc, list_filename != NULL,
+ linemap, errwarns);
+
+ check_errors(errwarns, object, linemap);
+
+ /* Finalize parse */
+ yasm_object_finalize(object, errwarns);
+ check_errors(errwarns, object, linemap);
+
+ /* Optimize */
+ yasm_object_optimize(object, errwarns);
+ check_errors(errwarns, object, linemap);
+
+ /* generate any debugging information */
+ yasm_dbgfmt_generate(object, linemap, errwarns);
+ check_errors(errwarns, object, linemap);
+
+ /* open the object file for output (if not already opened by dbg objfmt) */
+ if (!obj && strcmp(cur_objfmt_module->keyword, "dbg") != 0) {
+ obj = open_file(obj_filename, "wb");
+ if (!obj) {
+ cleanup(object);
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Write the object file */
+ yasm_objfmt_output(object, obj?obj:stderr,
+ strcmp(cur_dbgfmt_module->keyword, "null"), errwarns);
+
+ /* Close object file */
+ if (obj)
+ fclose(obj);
+
+ /* If we had an error at this point, we also need to delete the output
+ * object file (to make sure it's not left newer than the source).
+ */
+ if (yasm_errwarns_num_errors(errwarns, warning_error) > 0)
+ remove(obj_filename);
+ check_errors(errwarns, object, linemap);
+
+ /* Open and write the list file */
+ if (list_filename) {
+ FILE *list = open_file(list_filename, "wt");
+ if (!list) {
+ cleanup(object);
+ return EXIT_FAILURE;
+ }
+ /* Initialize the list format */
+ cur_listfmt = yasm_listfmt_create(cur_listfmt_module, in_filename,
+ obj_filename);
+ yasm_listfmt_output(cur_listfmt, list, linemap, cur_arch);
+ fclose(list);
+ }
+
+ yasm_errwarns_output_all(errwarns, linemap, warning_error,
+ print_yasm_error, print_yasm_warning);
+
+ yasm_linemap_destroy(linemap);
+ yasm_errwarns_destroy(errwarns);
+ cleanup(object);
+ return EXIT_SUCCESS;
+}
+
+/* main function */
+/*@-globstate -unrecog@*/
+int
+main(int argc, char *argv[])
+{
+ size_t i;
+
+ errfile = stderr;
+
+#if defined(HAVE_SETLOCALE) && defined(HAVE_LC_MESSAGES)
+ setlocale(LC_MESSAGES, "");
+#endif
+#if defined(LOCALEDIR)
+ bindtextdomain(PACKAGE, LOCALEDIR);
+#endif
+ textdomain(PACKAGE);
+
+ /* Initialize errwarn handling */
+ yasm_internal_error_ = handle_yasm_int_error;
+ yasm_fatal = handle_yasm_fatal;
+ yasm_gettext_hook = handle_yasm_gettext;
+ yasm_errwarn_initialize();
+
+ /* Initialize BitVector (needed for intnum/floatnum). */
+ if (BitVector_Boot() != ErrCode_Ok) {
+ print_error(_("%s: could not initialize BitVector"), _("FATAL"));
+ return EXIT_FAILURE;
+ }
+
+ /* Initialize intnum and floatnum */
+ yasm_intnum_initialize();
+ yasm_floatnum_initialize();
+
+#ifdef CMAKE_BUILD
+ /* Load standard modules */
+#ifdef BUILD_SHARED_LIBS
+ if (!load_plugin("yasmstd")) {
+ print_error(_("%s: could not load standard modules"), _("FATAL"));
+ return EXIT_FAILURE;
+ }
+#else
+ yasm_init_plugin();
+#endif
+#endif
+
+ /* Initialize parameter storage */
+ STAILQ_INIT(&preproc_options);
+
+ if (parse_cmdline(argc, argv, options, NELEMS(options), print_error))
+ return EXIT_FAILURE;
+
+ switch (special_options) {
+ case SPECIAL_SHOW_HELP:
+ /* Does gettext calls internally */
+ help_msg(help_head, help_tail, options, NELEMS(options));
+ return EXIT_SUCCESS;
+ case SPECIAL_SHOW_VERSION:
+ for (i=0; i<NELEMS(version_msg); i++)
+ printf("%s\n", version_msg[i]);
+ return EXIT_SUCCESS;
+ case SPECIAL_SHOW_LICENSE:
+ for (i=0; i<NELEMS(license_msg); i++)
+ printf("%s\n", license_msg[i]);
+ return EXIT_SUCCESS;
+ }
+
+ /* Open error file if specified. */
+ if (error_filename) {
+ errfile = open_file(error_filename, "wt");
+ if (!errfile)
+ return EXIT_FAILURE;
+ }
+
+ /* If not already specified, default to bin as the object format. */
+ if (!cur_objfmt_module) {
+ if (!objfmt_keyword)
+ objfmt_keyword = yasm__xstrdup(DEFAULT_OBJFMT_MODULE);
+ cur_objfmt_module = yasm_load_objfmt(objfmt_keyword);
+ if (!cur_objfmt_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("object format"));
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* TASM's architecture is x86 */
+ cur_arch_module = yasm_load_arch("x86");
+ if (!cur_arch_module) {
+ print_error(_("%s: could not load %s"), _("FATAL"),
+ _("architecture"));
+ return EXIT_FAILURE;
+ }
+ machine_name =
+ yasm__xstrdup(cur_arch_module->default_machine_keyword);
+
+ /* Check for arch help */
+ if (machine_name && strcmp(machine_name, "help") == 0) {
+ const yasm_arch_machine *m = cur_arch_module->machines;
+ printf(_("Available %s for %s `%s':\n"), _("machines"),
+ _("architecture"), cur_arch_module->keyword);
+ while (m->keyword && m->name) {
+ print_list_keyword_desc(m->name, m->keyword);
+ m++;
+ }
+ return EXIT_SUCCESS;
+ }
+
+ cur_parser_module = yasm_load_parser("tasm");
+ if (!cur_parser_module) {
+ print_error(_("%s: could not load %s"), _("FATAL"),
+ _("parser"));
+ cleanup(NULL);
+ return EXIT_FAILURE;
+ }
+
+ /* If not already specified, default to the parser's default preproc. */
+ if (!cur_preproc_module) {
+ cur_preproc_module =
+ yasm_load_preproc(cur_parser_module->default_preproc_keyword);
+ if (!cur_preproc_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("preprocessor"));
+ cleanup(NULL);
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Determine input filename and open input file. */
+ if (!in_filename) {
+ print_error(_("No input files specified"));
+ return EXIT_FAILURE;
+ }
+
+ /* If list file enabled, make sure we have a list format loaded. */
+ if (list_filename) {
+ /* use nasm as the list format. */
+ cur_listfmt_module = yasm_load_listfmt("nasm");
+ }
+
+ /* If not already specified, default to null as the debug format. */
+ if (!cur_dbgfmt_module) {
+ cur_dbgfmt_module = yasm_load_dbgfmt("null");
+ if (!cur_dbgfmt_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("debug format"));
+ return EXIT_FAILURE;
+ }
+ }
+
+ return do_assemble();
+}
+/*@=globstate =unrecog@*/
+
+/* Open the object file. Returns 0 on failure. */
+static FILE *
+open_file(const char *filename, const char *mode)
+{
+ FILE *f;
+
+ f = fopen(filename, mode);
+ if (!f)
+ print_error(_("could not open file `%s'"), filename);
+ return f;
+}
+
+static void
+check_errors(yasm_errwarns *errwarns, yasm_object *object,
+ yasm_linemap *linemap)
+{
+ if (yasm_errwarns_num_errors(errwarns, warning_error) > 0) {
+ yasm_errwarns_output_all(errwarns, linemap, warning_error,
+ print_yasm_error, print_yasm_warning);
+ yasm_linemap_destroy(linemap);
+ yasm_errwarns_destroy(errwarns);
+ cleanup(object);
+ exit(EXIT_FAILURE);
+ }
+}
+
+/* Define DO_FREE to 1 to enable deallocation of all data structures.
+ * Useful for detecting memory leaks, but slows down execution unnecessarily
+ * (as the OS will free everything we miss here).
+ */
+#define DO_FREE 1
+
+/* Cleans up all allocated structures. */
+static void
+cleanup(yasm_object *object)
+{
+ if (DO_FREE) {
+ if (cur_listfmt)
+ yasm_listfmt_destroy(cur_listfmt);
+ if (cur_preproc)
+ yasm_preproc_destroy(cur_preproc);
+ if (object)
+ yasm_object_destroy(object);
+
+ yasm_floatnum_cleanup();
+ yasm_intnum_cleanup();
+
+ yasm_errwarn_cleanup();
+
+ BitVector_Shutdown();
+ }
+
+ if (DO_FREE) {
+ if (in_filename)
+ yasm_xfree(in_filename);
+ if (obj_filename)
+ yasm_xfree(obj_filename);
+ if (list_filename)
+ yasm_xfree(list_filename);
+ if (xref_filename)
+ yasm_xfree(xref_filename);
+ if (machine_name)
+ yasm_xfree(machine_name);
+ if (objfmt_keyword)
+ yasm_xfree(objfmt_keyword);
+ }
+
+ if (errfile != stderr && errfile != stdout)
+ fclose(errfile);
+#if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
+ unload_plugins();
+#endif
+}
+
+/*
+ * Command line options handlers
+ */
+static char ** const filenames[] = {
+ &in_filename, &obj_filename, &list_filename, &xref_filename, NULL
+}, ** const * cur_filename = &filenames[0];
+
+static int filename_handler(char *param) {
+ if (!*cur_filename) {
+ print_error(_("error: too many files on command line."));
+ return 1;
+ }
+
+ if (*param)
+ **cur_filename = yasm__xstrdup(param);
+
+ return 0;
+}
+int
+not_an_option_handler(char *param) {
+ char *c, *d = param;
+
+ while ((c = strchr(d, ','))) {
+ *c = '\0';
+ if (filename_handler(d))
+ return 1;
+ d = c + 1;
+ cur_filename++;
+ }
+ filename_handler(d);
+ return 0;
+}
+
+static int
+opt_special_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+ if (special_options == 0)
+ special_options = extra;
+ return 0;
+}
+
+static int
+opt_segment_ordering_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+ segment_ordering = extra;
+ return 0;
+}
+
+static int
+opt_cross_reference_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+ cross_reference = 1;
+ return 0;
+}
+
+static int
+opt_floating_point_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+ floating_point = extra;
+ return 0;
+}
+
+static int
+opt_ignore(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+ return 0;
+}
+
+static int
+opt_listing_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+ if (param && param[0]) {
+ if (param[0] != 'a')
+ return 1;
+ expanded_listing = 1;
+ }
+ listing = 1;
+ return 0;
+}
+
+static int
+opt_case_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+ case_sensitivity = extra;
+ return 0;
+}
+
+static int
+opt_valid_length_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+ valid_length = atoi(param);
+ return 0;
+}
+
+static int
+opt_warning_handler(char *cmd, /*@unused@*/ char *param, int extra)
+{
+ /* is it disabling the warning instead of enabling? */
+ void (*action)(yasm_warn_class wclass) = NULL;
+
+ if (cmd[0] == '0') {
+ /* /w0, disable warnings */
+ yasm_warn_disable_all();
+ return 0;
+ }
+
+ if (cmd[0] == '1' || cmd[0] == '2') {
+ /* /w[12], enable warnings */
+ yasm_warn_enable(YASM_WARN_UNREC_CHAR);
+ yasm_warn_enable(YASM_WARN_ORPHAN_LABEL);
+ yasm_warn_enable(YASM_WARN_UNINIT_CONTENTS);
+ return 0;
+ }
+
+ /* detect no- prefix to disable the warning */
+ if (cmd[0] == '-') {
+ action = yasm_warn_disable;
+ } else if (cmd[0] == '+') {
+ action = yasm_warn_enable;
+ } else return 1;
+
+ /* skip past '+/-' */
+ cmd++;
+
+ if (cmd[0] == '\0')
+ /* just /w- or /w+, so definitely not valid */
+ return 1;
+ else if (strcmp(cmd, "error") == 0)
+ warning_error = (action == yasm_warn_enable);
+ else if (strcmp(cmd, "unrecognized-char") == 0)
+ action(YASM_WARN_UNREC_CHAR);
+ else if (strcmp(cmd, "orphan-labels") == 0)
+ action(YASM_WARN_ORPHAN_LABEL);
+ else if (strcmp(cmd, "uninit-contents") == 0)
+ action(YASM_WARN_UNINIT_CONTENTS);
+ else if (strcmp(cmd, "size-override") == 0)
+ action(YASM_WARN_SIZE_OVERRIDE);
+ else
+ return 1;
+
+ return 0;
+}
+
+static int
+opt_preproc_option(/*@unused@*/ char *cmd, char *param, int extra)
+{
+ constcharparam *cp;
+ cp = yasm_xmalloc(sizeof(constcharparam));
+ cp->param = param;
+ cp->id = extra;
+ STAILQ_INSERT_TAIL(&preproc_options, cp, link);
+ return 0;
+}
+
+static int
+opt_exe_handler(char *cmd, /*@unused@*/ char *param, int extra)
+{
+ objfmt_keyword = yasm__xstrdup("dosexe");
+ return 0;
+}
+
+static void
+apply_preproc_builtins()
+{
+ char *predef;
+
+ if (!objfmt_keyword)
+ objfmt_keyword = yasm__xstrdup(DEFAULT_OBJFMT_MODULE);
+
+ /* Define standard YASM assembly-time macro constants */
+ predef = yasm_xmalloc(strlen("__YASM_OBJFMT__=")
+ + strlen(objfmt_keyword) + 1);
+ strcpy(predef, "__YASM_OBJFMT__=");
+ strcat(predef, objfmt_keyword);
+ yasm_preproc_define_builtin(cur_preproc, predef);
+ yasm_xfree(predef);
+}
+
+static void
+apply_preproc_standard_macros(const yasm_stdmac *stdmacs)
+{
+ int i, matched;
+
+ if (!stdmacs)
+ return;
+
+ matched = -1;
+ for (i=0; stdmacs[i].parser; i++)
+ if (yasm__strcasecmp(stdmacs[i].parser,
+ cur_parser_module->keyword) == 0 &&
+ yasm__strcasecmp(stdmacs[i].preproc,
+ cur_preproc_module->keyword) == 0)
+ matched = i;
+ if (matched >= 0 && stdmacs[matched].macros)
+ yasm_preproc_add_standard(cur_preproc, stdmacs[matched].macros);
+}
+
+static void
+apply_preproc_saved_options()
+{
+ constcharparam *cp, *cpnext;
+
+ void (*funcs[3])(yasm_preproc *, const char *);
+ funcs[0] = cur_preproc_module->add_include_file;
+ funcs[1] = cur_preproc_module->predefine_macro;
+ funcs[2] = cur_preproc_module->undefine_macro;
+
+ STAILQ_FOREACH(cp, &preproc_options, link) {
+ if (0 <= cp->id && cp->id < 3 && funcs[cp->id])
+ funcs[cp->id](cur_preproc, cp->param);
+ }
+
+ cp = STAILQ_FIRST(&preproc_options);
+ while (cp != NULL) {
+ cpnext = STAILQ_NEXT(cp, link);
+ yasm_xfree(cp);
+ cp = cpnext;
+ }
+ STAILQ_INIT(&preproc_options);
+}
+
+/* Replace extension on a filename (or append one if none is present).
+ * If output filename would be identical to input (same extension out as in),
+ * returns (copy of) def.
+ * A NULL ext means the trailing '.' should NOT be included, whereas a "" ext
+ * means the trailing '.' should be included.
+ */
+static char *
+replace_extension(const char *orig, /*@null@*/ const char *ext,
+ const char *def)
+{
+ char *out, *outext;
+ size_t deflen, outlen;
+
+ /* allocate enough space for full existing name + extension */
+ outlen = strlen(orig) + 2;
+ if (ext)
+ outlen += strlen(ext) + 1;
+ deflen = strlen(def) + 1;
+ if (outlen < deflen)
+ outlen = deflen;
+ out = yasm_xmalloc(outlen);
+
+ strcpy(out, orig);
+ outext = strrchr(out, '.');
+ if (outext) {
+ /* Existing extension: make sure it's not the same as the replacement
+ * (as we don't want to overwrite the source file).
+ */
+ outext++; /* advance past '.' */
+ if (ext && strcmp(outext, ext) == 0) {
+ outext = NULL; /* indicate default should be used */
+ print_error(
+ _("file name already ends in `.%s': output will be in `%s'"),
+ ext, def);
+ }
+ } else {
+ /* No extension: make sure the output extension is not empty
+ * (again, we don't want to overwrite the source file).
+ */
+ if (!ext)
+ print_error(
+ _("file name already has no extension: output will be in `%s'"),
+ def);
+ else {
+ outext = strrchr(out, '\0'); /* point to end of the string */
+ *outext++ = '.'; /* append '.' */
+ }
+ }
+
+ /* replace extension or use default name */
+ if (outext) {
+ if (!ext) {
+ /* Back up and replace '.' with string terminator */
+ outext--;
+ *outext = '\0';
+ } else
+ strcpy(outext, ext);
+ } else
+ strcpy(out, def);
+
+ return out;
+}
+
+void
+print_list_keyword_desc(const char *name, const char *keyword)
+{
+ printf("%4s%-12s%s\n", "", keyword, name);
+}
+
+static void
+print_error(const char *fmt, ...)
+{
+ va_list va;
+ fprintf(errfile, "tasm: ");
+ va_start(va, fmt);
+ vfprintf(errfile, fmt, va);
+ va_end(va);
+ fputc('\n', errfile);
+}
+
+static /*@exits@*/ void
+handle_yasm_int_error(const char *file, unsigned int line, const char *message)
+{
+ fprintf(stderr, _("INTERNAL ERROR at %s, line %u: %s\n"), file, line,
+ gettext(message));
+#ifdef HAVE_ABORT
+ abort();
+#else
+ exit(EXIT_FAILURE);
+#endif
+}
+
+static /*@exits@*/ void
+handle_yasm_fatal(const char *fmt, va_list va)
+{
+ fprintf(errfile, "**%s**: ", _("Fatal"));
+ vfprintf(errfile, gettext(fmt), va);
+ fputc('\n', errfile);
+ exit(EXIT_FAILURE);
+}
+
+static const char *
+handle_yasm_gettext(const char *msgid)
+{
+ return gettext(msgid);
+}
+
+static void
+print_yasm_error(const char *filename, unsigned long line, const char *msg,
+ const char *xref_fn, unsigned long xref_line,
+ const char *xref_msg)
+{
+ if (line)
+ fprintf(errfile, "**%s** %s(%lu) %s\n", _("Error"), filename, line, msg);
+ else
+ fprintf(errfile, "**%s** %s %s\n", _("Error"), filename, msg);
+
+ if (/* xref_fn && */ xref_msg) {
+ if (xref_line)
+ fprintf(errfile, "**%s** %s(%lu) %s\n", _("Error"), filename, xref_line, xref_msg);
+ else
+ fprintf(errfile, "**%s** %s %s\n", _("Error"), filename, xref_msg);
+ }
+}
+
+static void
+print_yasm_warning(const char *filename, unsigned long line, const char *msg)
+{
+ if (line)
+ fprintf(errfile, "*%s* %s(%lu) %s\n", _("Warning"), filename, line, msg);
+ else
+ fprintf(errfile, "*%s* %s %s\n", _("Warning"), filename, msg);
+}
diff --git a/contrib/tools/yasm/frontends/vsyasm/license.c b/contrib/tools/yasm/frontends/vsyasm/license.c
new file mode 100644
index 0000000000..35c5a04137
--- /dev/null
+++ b/contrib/tools/yasm/frontends/vsyasm/license.c
@@ -0,0 +1,65 @@
+/* This file auto-generated from COPYING by genstring.py - don't edit it */
+
+static const char* license_msg[] = {
+ "Yasm is Copyright (c) 2001-2014 Peter Johnson and other Yasm developers.",
+ "",
+ "Yasm developers and/or contributors include:",
+ "Peter Johnson",
+ "Michael Urman",
+ "Brian Gladman (Visual Studio build files, other fixes)",
+ "Stanislav Karchebny (options parser)",
+ "Mathieu Monnier (SSE4 instruction patches, NASM preprocessor additions)",
+ "Anonymous \"NASM64\" developer (NASM preprocessor fixes)",
+ "Stephen Polkowski (x86 instruction patches)",
+ "Henryk Richter (Mach-O object format)",
+ "Ben Skeggs (patches, bug reports)",
+ "Alexei Svitkine (GAS preprocessor)",
+ "Samuel Thibault (TASM parser and frontend)",
+ "",
+ "-----------------------------------",
+ "Yasm licensing overview and summary",
+ "-----------------------------------",
+ "",
+ "Note: This document does not provide legal advice nor is it the actual",
+ "license of any part of Yasm. See the individual licenses for complete",
+ "details. Consult a lawyer for legal advice.",
+ "",
+ "The primary license of Yasm is the 2-clause BSD license. Please use this",
+ "license if you plan on submitting code to the project.",
+ "",
+ "Yasm has absolutely no warranty; not even for merchantibility or fitness",
+ "for a particular purpose.",
+ "",
+ "-------",
+ "Libyasm",
+ "-------",
+ "Libyasm is 2-clause or 3-clause BSD licensed, with the exception of",
+ "bitvect, which is triple-licensed under the Artistic license, GPL, and",
+ "LGPL. Libyasm is thus GPL and LGPL compatible. In addition, this also",
+ "means that libyasm is free for binary-only distribution as long as the",
+ "terms of the 3-clause BSD license and Artistic license (as it applies to",
+ "bitvect) are fulfilled.",
+ "",
+ "-------",
+ "Modules",
+ "-------",
+ "The modules are 2-clause or 3-clause BSD licensed.",
+ "",
+ "---------",
+ "Frontends",
+ "---------",
+ "The frontends are 2-clause BSD licensed.",
+ "",
+ "-------------",
+ "License Texts",
+ "-------------",
+ "The full text of all licenses are provided in separate files in the source",
+ "distribution. Each source file may include the entire license (in the case",
+ "of the BSD and Artistic licenses), or may reference the GPL or LGPL license",
+ "file.",
+ "",
+ "BSD.txt - 2-clause and 3-clause BSD licenses",
+ "Artistic.txt - Artistic license",
+ "GNU_GPL-2.0 - GNU General Public License",
+ "GNU_LGPL-2.0 - GNU Library General Public License",
+};
diff --git a/contrib/tools/yasm/frontends/vsyasm/vsyasm.c b/contrib/tools/yasm/frontends/vsyasm/vsyasm.c
new file mode 100644
index 0000000000..905145fa15
--- /dev/null
+++ b/contrib/tools/yasm/frontends/vsyasm/vsyasm.c
@@ -0,0 +1,1424 @@
+/*
+ * Program entry point, command line parsing
+ *
+ * Copyright (C) 2001-2007 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 <util.h>
+
+#include <ctype.h>
+#include <libyasm/compat-queue.h>
+#include <libyasm/bitvect.h>
+#include <libyasm.h>
+
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
+
+#include "frontends/yasm/yasm-options.h"
+
+#if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
+#include "frontends/yasm/yasm-plugin.h"
+#endif
+
+#include "license.c"
+
+#if defined(CMAKE_BUILD) && !defined(BUILD_SHARED_LIBS)
+void yasm_init_plugin(void);
+#endif
+
+/*@null@*/ /*@only@*/ static char *objdir_pathname = NULL;
+/*@null@*/ /*@only@*/ static char *global_prefix = NULL, *global_suffix = NULL;
+/*@null@*/ /*@only@*/ static char *listdir_pathname = NULL;
+/*@null@*/ /*@only@*/ static char *mapdir_pathname = NULL;
+/*@null@*/ /*@only@*/ static char *objext = NULL;
+/*@null@*/ /*@only@*/ static char *listext = NULL, *mapext = NULL;
+/*@null@*/ /*@only@*/ static char *machine_name = NULL;
+static int special_options = 0;
+/*@null@*/ /*@dependent@*/ static const yasm_arch_module *
+ cur_arch_module = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_parser_module *
+ cur_parser_module = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_preproc_module *
+ cur_preproc_module = NULL;
+/*@null@*/ static char *objfmt_keyword = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_objfmt_module *
+ cur_objfmt_module = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_dbgfmt_module *
+ cur_dbgfmt_module = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_listfmt_module *
+ cur_listfmt_module = NULL;
+static unsigned int force_strict = 0;
+static int warning_error = 0; /* warnings being treated as errors */
+static FILE *errfile;
+/*@null@*/ /*@only@*/ static char *error_filename = NULL;
+static enum {
+ EWSTYLE_GNU = 0,
+ EWSTYLE_VC
+} ewmsg_style = EWSTYLE_GNU;
+
+/*@null@*/ /*@dependent@*/ static FILE *open_file(const char *filename,
+ const char *mode);
+static int check_errors(/*@only@*/ yasm_errwarns *errwarns,
+ /*@only@*/ yasm_object *object,
+ /*@only@*/ yasm_linemap *linemap,
+ /*@only@*/ yasm_preproc *preproc,
+ /*@only@*/ yasm_arch *arch);
+static void cleanup(void);
+static void free_input_filenames(void);
+
+/* Forward declarations: cmd line parser handlers */
+static int opt_special_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_arch_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_parser_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_preproc_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_objfmt_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_dbgfmt_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_listfmt_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_listdir_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_objdir_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_mapdir_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_listext_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_objext_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_mapext_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_machine_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_strict_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_warning_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_error_file(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_error_stdout(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_include_option(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_preproc_option(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_ewmsg_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_prefix_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_suffix_handler(char *cmd, /*@null@*/ char *param, int extra);
+#if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
+static int opt_plugin_handler(char *cmd, /*@null@*/ char *param, int extra);
+#endif
+
+static /*@only@*/ char *replace_extension(const char *orig, /*@null@*/
+ const char *ext);
+static void print_error(const char *fmt, ...);
+
+static /*@exits@*/ void handle_yasm_int_error(const char *file,
+ unsigned int line,
+ const char *message);
+static /*@exits@*/ void handle_yasm_fatal(const char *message, va_list va);
+static const char *handle_yasm_gettext(const char *msgid);
+static void print_yasm_error(const char *filename, unsigned long line,
+ const char *msg, /*@null@*/ const char *xref_fn,
+ unsigned long xref_line,
+ /*@null@*/ const char *xref_msg);
+static void print_yasm_warning(const char *filename, unsigned long line,
+ const char *msg);
+
+static void apply_preproc_builtins(yasm_preproc *preproc);
+static void apply_preproc_standard_macros(yasm_preproc *preproc,
+ const yasm_stdmac *stdmacs);
+static void apply_preproc_saved_options(yasm_preproc *preproc);
+static void free_preproc_saved_options(void);
+static void print_list_keyword_desc(const char *name, const char *keyword);
+
+/* values for special_options */
+#define SPECIAL_SHOW_HELP 0x01
+#define SPECIAL_SHOW_VERSION 0x02
+#define SPECIAL_SHOW_LICENSE 0x04
+#define SPECIAL_LISTED 0x08
+
+/* command line options */
+static opt_option options[] =
+{
+ { 0, "version", 0, opt_special_handler, SPECIAL_SHOW_VERSION,
+ N_("show version text"), NULL },
+ { 0, "license", 0, opt_special_handler, SPECIAL_SHOW_LICENSE,
+ N_("show license text"), NULL },
+ { 'h', "help", 0, opt_special_handler, SPECIAL_SHOW_HELP,
+ N_("show help text"), NULL },
+ { 'a', "arch", 1, opt_arch_handler, 0,
+ N_("select architecture (list with -a help)"), N_("arch") },
+ { 'p', "parser", 1, opt_parser_handler, 0,
+ N_("select parser (list with -p help)"), N_("parser") },
+ { 'r', "preproc", 1, opt_preproc_handler, 0,
+ N_("select preprocessor (list with -r help)"), N_("preproc") },
+ { 'f', "oformat", 1, opt_objfmt_handler, 0,
+ N_("select object format (list with -f help)"), N_("format") },
+ { 'g', "dformat", 1, opt_dbgfmt_handler, 0,
+ N_("select debugging format (list with -g help)"), N_("debug") },
+ { 'L', "lformat", 1, opt_listfmt_handler, 0,
+ N_("select list format (list with -L help)"), N_("list") },
+ { 'l', "list", 1, opt_listdir_handler, 0,
+ N_("name of list-file output directory"), N_("pathname") },
+ { 'o', "objdir", 1, opt_objdir_handler, 0,
+ N_("name of object-file output directory"), N_("pathname") },
+ { 0, "mapdir", 1, opt_mapdir_handler, 0,
+ N_("name of map-file output directory"), N_("pathname") },
+ { 0, "listext", 1, opt_listext_handler, 0,
+ N_("list-file extension (default `lst')"), N_("ext") },
+ { 0, "objext", 1, opt_objext_handler, 0,
+ N_("object-file extension (default is by object format)"), N_("ext") },
+ { 0, "mapext", 1, opt_mapext_handler, 0,
+ N_("map-file extension (default `map')"), N_("ext") },
+ { 'm', "machine", 1, opt_machine_handler, 0,
+ N_("select machine (list with -m help)"), N_("machine") },
+ { 0, "force-strict", 0, opt_strict_handler, 0,
+ N_("treat all sized operands as if `strict' was used"), NULL },
+ { 'w', NULL, 0, opt_warning_handler, 1,
+ N_("inhibits warning messages"), NULL },
+ { 'W', NULL, 0, opt_warning_handler, 0,
+ N_("enables/disables warning"), NULL },
+ { 'E', NULL, 1, opt_error_file, 0,
+ N_("redirect error messages to file"), N_("file") },
+ { 's', NULL, 0, opt_error_stdout, 0,
+ N_("redirect error messages to stdout"), NULL },
+ { 'i', NULL, 1, opt_include_option, 0,
+ N_("add include path"), N_("path") },
+ { 'I', NULL, 1, opt_include_option, 0,
+ N_("add include path"), N_("path") },
+ { 'P', NULL, 1, opt_preproc_option, 0,
+ N_("pre-include file"), N_("filename") },
+ { 'd', NULL, 1, opt_preproc_option, 1,
+ N_("pre-define a macro, optionally to value"), N_("macro[=value]") },
+ { 'D', NULL, 1, opt_preproc_option, 1,
+ N_("pre-define a macro, optionally to value"), N_("macro[=value]") },
+ { 'u', NULL, 1, opt_preproc_option, 2,
+ N_("undefine a macro"), N_("macro") },
+ { 'U', NULL, 1, opt_preproc_option, 2,
+ N_("undefine a macro"), N_("macro") },
+ { 'X', NULL, 1, opt_ewmsg_handler, 0,
+ N_("select error/warning message style (`gnu' or `vc')"), N_("style") },
+ { 0, "prefix", 1, opt_prefix_handler, 0,
+ N_("prepend argument to name of all external symbols"), N_("prefix") },
+ { 0, "suffix", 1, opt_suffix_handler, 0,
+ N_("append argument to name of all external symbols"), N_("suffix") },
+ { 0, "postfix", 1, opt_suffix_handler, 0,
+ N_("append argument to name of all external symbols"), N_("suffix") },
+#if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
+ { 'N', "plugin", 1, opt_plugin_handler, 0,
+ N_("load plugin module"), N_("plugin") },
+#endif
+};
+
+/* version message */
+/*@observer@*/ static const char *version_msg[] = {
+ PACKAGE_STRING,
+ "Compiled on " __DATE__ ".",
+ "Copyright (c) 2001-2010 Peter Johnson and other Yasm developers.",
+ "Run yasm --license for licensing overview and summary."
+};
+
+/* help messages */
+/*@observer@*/ static const char *help_head = N_(
+ "usage: vsyasm [option]* file...\n"
+ "Options:\n");
+/*@observer@*/ static const char *help_tail = N_(
+ "\n"
+ "Files are asm sources to be assembled.\n"
+ "\n"
+ "Sample invocation:\n"
+ " vsyasm -f win64 -o objdir source1.asm source2.asm\n"
+ "\n"
+ "All options apply to all files.\n"
+ "\n"
+ "Report bugs to bug-yasm@tortall.net\n");
+
+/* parsed command line storage until appropriate modules have been loaded */
+typedef STAILQ_HEAD(constcharparam_head, constcharparam) constcharparam_head;
+
+typedef struct constcharparam {
+ STAILQ_ENTRY(constcharparam) link;
+ const char *param;
+ int id;
+} constcharparam;
+
+static constcharparam_head preproc_options;
+static constcharparam_head input_files;
+static int num_input_files = 0;
+
+static int
+do_assemble(const char *in_filename)
+{
+ yasm_object *object;
+ const char *base_filename;
+ char *fn = NULL;
+ char *obj_filename, *list_filename = NULL, *map_filename = NULL;
+ /*@null@*/ FILE *obj = NULL;
+ yasm_arch_create_error arch_error;
+ yasm_linemap *linemap;
+ yasm_arch *arch = NULL;
+ yasm_preproc *preproc = NULL;
+ yasm_errwarns *errwarns = yasm_errwarns_create();
+ int i, matched;
+
+ /* Initialize line map */
+ linemap = yasm_linemap_create();
+ yasm_linemap_set(linemap, in_filename, 0, 1, 1);
+
+ /* determine the output filenames */
+ /* replace (or add) extension to base filename */
+ yasm__splitpath(in_filename, &base_filename);
+ if (base_filename[0] != '\0')
+ fn = replace_extension(base_filename, objext);
+ if (!fn)
+ {
+ print_error(_("could not determine output filename for `%s'"),
+ in_filename);
+ return EXIT_FAILURE;
+ }
+ obj_filename = yasm__combpath(objdir_pathname, fn);
+ yasm_xfree(fn);
+
+ if (listdir_pathname) {
+ fn = replace_extension(base_filename, listext);
+ if (!fn)
+ {
+ print_error(_("could not determine list filename for `%s'"),
+ in_filename);
+ return EXIT_FAILURE;
+ }
+ list_filename = yasm__combpath(listdir_pathname, fn);
+ yasm_xfree(fn);
+ }
+
+ if (mapdir_pathname) {
+ fn = replace_extension(base_filename, mapext);
+ if (!fn)
+ {
+ print_error(_("could not determine map filename for `%s'"),
+ in_filename);
+ return EXIT_FAILURE;
+ }
+ map_filename = yasm__combpath(mapdir_pathname, fn);
+ yasm_xfree(fn);
+ }
+
+ /* Set up architecture using machine and parser. */
+ if (!machine_name) {
+ /* If we're using x86 and the default objfmt bits is 64, default the
+ * machine to amd64. When we get more arches with multiple machines,
+ * we should do this in a more modular fashion.
+ */
+ if (strcmp(cur_arch_module->keyword, "x86") == 0 &&
+ cur_objfmt_module->default_x86_mode_bits == 64)
+ machine_name = yasm__xstrdup("amd64");
+ else
+ machine_name =
+ yasm__xstrdup(cur_arch_module->default_machine_keyword);
+ }
+
+ arch = yasm_arch_create(cur_arch_module, machine_name,
+ cur_parser_module->keyword, &arch_error);
+ if (!arch) {
+ switch (arch_error) {
+ case YASM_ARCH_CREATE_BAD_MACHINE:
+ print_error(_("%s: `%s' is not a valid %s for %s `%s'"),
+ _("FATAL"), machine_name, _("machine"),
+ _("architecture"), cur_arch_module->keyword);
+ break;
+ case YASM_ARCH_CREATE_BAD_PARSER:
+ print_error(_("%s: `%s' is not a valid %s for %s `%s'"),
+ _("FATAL"), cur_parser_module->keyword,
+ _("parser"), _("architecture"),
+ cur_arch_module->keyword);
+ break;
+ default:
+ print_error(_("%s: unknown architecture error"), _("FATAL"));
+ }
+
+ return EXIT_FAILURE;
+ }
+
+ /* Create object */
+ object = yasm_object_create(in_filename, obj_filename, arch,
+ cur_objfmt_module, cur_dbgfmt_module);
+ if (!object) {
+ yasm_error_class eclass;
+ unsigned long xrefline;
+ /*@only@*/ /*@null@*/ char *estr, *xrefstr;
+
+ yasm_error_fetch(&eclass, &estr, &xrefline, &xrefstr);
+ print_error("%s: %s", _("FATAL"), estr);
+ yasm_xfree(estr);
+ yasm_xfree(xrefstr);
+ return EXIT_FAILURE;
+ }
+
+ /* Get a fresh copy of objfmt_module as it may have changed. */
+ cur_objfmt_module = ((yasm_objfmt_base *)object->objfmt)->module;
+
+ /* Check to see if the requested preprocessor is in the allowed list
+ * for the active parser.
+ */
+ matched = 0;
+ for (i=0; cur_parser_module->preproc_keywords[i]; i++)
+ if (yasm__strcasecmp(cur_parser_module->preproc_keywords[i],
+ cur_preproc_module->keyword) == 0)
+ matched = 1;
+ if (!matched) {
+ print_error(_("%s: `%s' is not a valid %s for %s `%s'"), _("FATAL"),
+ cur_preproc_module->keyword, _("preprocessor"),
+ _("parser"), cur_parser_module->keyword);
+ yasm_object_destroy(object);
+ return EXIT_FAILURE;
+ }
+
+ if (global_prefix)
+ yasm_object_set_global_prefix(object, global_prefix);
+ if (global_suffix)
+ yasm_object_set_global_suffix(object, global_suffix);
+
+ preproc = yasm_preproc_create(cur_preproc_module, in_filename,
+ object->symtab, linemap, errwarns);
+
+ apply_preproc_builtins(preproc);
+ apply_preproc_standard_macros(preproc, cur_parser_module->stdmacs);
+ apply_preproc_standard_macros(preproc, cur_objfmt_module->stdmacs);
+ apply_preproc_saved_options(preproc);
+
+ /* Get initial x86 BITS setting from object format */
+ if (strcmp(cur_arch_module->keyword, "x86") == 0) {
+ yasm_arch_set_var(arch, "mode_bits",
+ cur_objfmt_module->default_x86_mode_bits);
+ }
+
+ yasm_arch_set_var(arch, "force_strict", force_strict);
+
+ /* Try to enable the map file via a map NASM directive. This is
+ * somewhat of a hack.
+ */
+ if (map_filename) {
+ const yasm_directive *dir = &cur_objfmt_module->directives[0];
+ matched = 0;
+ for (; dir && dir->name; dir++) {
+ if (yasm__strcasecmp(dir->name, "map") == 0 &&
+ yasm__strcasecmp(dir->parser, "nasm") == 0) {
+ yasm_valparamhead vps;
+ yasm_valparam *vp;
+ matched = 1;
+ yasm_vps_initialize(&vps);
+ vp = yasm_vp_create_string(NULL, yasm__xstrdup(map_filename));
+ yasm_vps_append(&vps, vp);
+ dir->handler(object, &vps, NULL, 0);
+ yasm_vps_delete(&vps);
+ }
+ }
+ if (!matched) {
+ print_error(
+ _("warning: object format `%s' does not support map files"),
+ cur_objfmt_module->keyword);
+ }
+ }
+
+ /* Parse! */
+ cur_parser_module->do_parse(object, preproc, list_filename != NULL,
+ linemap, errwarns);
+
+ if (check_errors(errwarns, object, linemap, preproc, arch) == EXIT_FAILURE)
+ return EXIT_FAILURE;
+
+ /* Finalize parse */
+ yasm_object_finalize(object, errwarns);
+ if (check_errors(errwarns, object, linemap, preproc, arch) == EXIT_FAILURE)
+ return EXIT_FAILURE;
+
+ /* Optimize */
+ yasm_object_optimize(object, errwarns);
+ if (check_errors(errwarns, object, linemap, preproc, arch) == EXIT_FAILURE)
+ return EXIT_FAILURE;
+
+ /* generate any debugging information */
+ yasm_dbgfmt_generate(object, linemap, errwarns);
+ if (check_errors(errwarns, object, linemap, preproc, arch) == EXIT_FAILURE)
+ return EXIT_FAILURE;
+
+ /* open the object file for output (if not already opened by dbg objfmt) */
+ if (!obj && strcmp(cur_objfmt_module->keyword, "dbg") != 0) {
+ obj = open_file(obj_filename, "wb");
+ if (!obj) {
+ yasm_preproc_destroy(preproc);
+ yasm_object_destroy(object);
+ yasm_linemap_destroy(linemap);
+ yasm_errwarns_destroy(errwarns);
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Write the object file */
+ yasm_objfmt_output(object, obj?obj:stderr,
+ strcmp(cur_dbgfmt_module->keyword, "null"), errwarns);
+
+ /* Close object file */
+ if (obj)
+ fclose(obj);
+
+ /* If we had an error at this point, we also need to delete the output
+ * object file (to make sure it's not left newer than the source).
+ */
+ if (yasm_errwarns_num_errors(errwarns, warning_error) > 0)
+ remove(obj_filename);
+ if (check_errors(errwarns, object, linemap, preproc, arch) == EXIT_FAILURE)
+ return EXIT_FAILURE;
+
+ /* Open and write the list file */
+ if (list_filename) {
+ yasm_listfmt *cur_listfmt;
+ FILE *list = open_file(list_filename, "wt");
+ if (!list) {
+ yasm_preproc_destroy(preproc);
+ yasm_object_destroy(object);
+ yasm_linemap_destroy(linemap);
+ yasm_errwarns_destroy(errwarns);
+ return EXIT_FAILURE;
+ }
+ /* Initialize the list format */
+ cur_listfmt = yasm_listfmt_create(cur_listfmt_module, in_filename,
+ obj_filename);
+ yasm_listfmt_output(cur_listfmt, list, linemap, arch);
+ yasm_listfmt_destroy(cur_listfmt);
+ fclose(list);
+ }
+
+ yasm_errwarns_output_all(errwarns, linemap, warning_error,
+ print_yasm_error, print_yasm_warning);
+
+ yasm_preproc_destroy(preproc);
+ yasm_object_destroy(object);
+ yasm_linemap_destroy(linemap);
+ yasm_errwarns_destroy(errwarns);
+
+ yasm_xfree(obj_filename);
+ yasm_xfree(map_filename);
+ yasm_xfree(list_filename);
+ return EXIT_SUCCESS;
+}
+
+/* main function */
+/*@-globstate -unrecog@*/
+int
+main(int argc, char *argv[])
+{
+ size_t i;
+ constcharparam *infile;
+
+ errfile = stderr;
+
+#if defined(HAVE_SETLOCALE) && defined(HAVE_LC_MESSAGES)
+ setlocale(LC_MESSAGES, "");
+#endif
+#if defined(LOCALEDIR)
+ bindtextdomain(PACKAGE, LOCALEDIR);
+#endif
+ textdomain(PACKAGE);
+
+ /* Initialize errwarn handling */
+ yasm_internal_error_ = handle_yasm_int_error;
+ yasm_fatal = handle_yasm_fatal;
+ yasm_gettext_hook = handle_yasm_gettext;
+ yasm_errwarn_initialize();
+
+ /* Initialize BitVector (needed for intnum/floatnum). */
+ if (BitVector_Boot() != ErrCode_Ok) {
+ print_error(_("%s: could not initialize BitVector"), _("FATAL"));
+ return EXIT_FAILURE;
+ }
+
+ /* Initialize intnum and floatnum */
+ yasm_intnum_initialize();
+ yasm_floatnum_initialize();
+
+#ifdef CMAKE_BUILD
+ /* Load standard modules */
+#ifdef BUILD_SHARED_LIBS
+ if (!load_plugin("yasmstd")) {
+ print_error(_("%s: could not load standard modules"), _("FATAL"));
+ return EXIT_FAILURE;
+ }
+#else
+ yasm_init_plugin();
+#endif
+#endif
+
+ /* Initialize parameter storage */
+ STAILQ_INIT(&preproc_options);
+ STAILQ_INIT(&input_files);
+
+ if (parse_cmdline(argc, argv, options, NELEMS(options), print_error))
+ return EXIT_FAILURE;
+
+ switch (special_options) {
+ case SPECIAL_SHOW_HELP:
+ /* Does gettext calls internally */
+ help_msg(help_head, help_tail, options, NELEMS(options));
+ return EXIT_SUCCESS;
+ case SPECIAL_SHOW_VERSION:
+ for (i=0; i<NELEMS(version_msg); i++)
+ printf("%s\n", version_msg[i]);
+ return EXIT_SUCCESS;
+ case SPECIAL_SHOW_LICENSE:
+ for (i=0; i<NELEMS(license_msg); i++)
+ printf("%s\n", license_msg[i]);
+ return EXIT_SUCCESS;
+ case SPECIAL_LISTED:
+ /* Printed out earlier */
+ return EXIT_SUCCESS;
+ }
+
+ /* Open error file if specified. */
+ if (error_filename) {
+ int j;
+ errfile = open_file(error_filename, "wt");
+ if (!errfile)
+ return EXIT_FAILURE;
+
+ /* Print command line as first line in error file. */
+ for (j=0; j<argc; j++)
+ fprintf(errfile, "%s%c", argv[j], (j==argc-1) ? '\n' : ' ');
+ }
+
+ /* If not already specified, default to win32 as the object format. */
+ if (!cur_objfmt_module) {
+ if (!objfmt_keyword)
+ objfmt_keyword = yasm__xstrdup("win32");
+ cur_objfmt_module = yasm_load_objfmt(objfmt_keyword);
+ if (!cur_objfmt_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("object format"));
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Default to x86 as the architecture */
+ if (!cur_arch_module) {
+ cur_arch_module = yasm_load_arch("x86");
+ if (!cur_arch_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("architecture"));
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Check for arch help */
+ if (machine_name && strcmp(machine_name, "help") == 0) {
+ const yasm_arch_machine *m = cur_arch_module->machines;
+ printf(_("Available %s for %s `%s':\n"), _("machines"),
+ _("architecture"), cur_arch_module->keyword);
+ while (m->keyword && m->name) {
+ print_list_keyword_desc(m->name, m->keyword);
+ m++;
+ }
+ return EXIT_SUCCESS;
+ }
+
+ /* Default to NASM as the parser */
+ if (!cur_parser_module) {
+ cur_parser_module = yasm_load_parser("nasm");
+ if (!cur_parser_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("parser"));
+ cleanup();
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* If not already specified, default to the parser's default preproc. */
+ if (!cur_preproc_module) {
+ cur_preproc_module =
+ yasm_load_preproc(cur_parser_module->default_preproc_keyword);
+ if (!cur_preproc_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("preprocessor"));
+ cleanup();
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Determine input filenames. */
+ if (STAILQ_EMPTY(&input_files)) {
+ print_error(_("No input files specified"));
+ return EXIT_FAILURE;
+ }
+
+ /* If list file enabled, make sure we have a list format loaded. */
+ if (listdir_pathname) {
+ /* If not already specified, default to nasm as the list format. */
+ if (!cur_listfmt_module) {
+ cur_listfmt_module = yasm_load_listfmt("nasm");
+ if (!cur_listfmt_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("list format"));
+ return EXIT_FAILURE;
+ }
+ }
+ }
+
+ /* If not already specified, default to null as the debug format. */
+ if (!cur_dbgfmt_module) {
+ cur_dbgfmt_module = yasm_load_dbgfmt("null");
+ if (!cur_dbgfmt_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("debug format"));
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* If not already specified, output to the current directory. */
+ if (!objdir_pathname)
+ objdir_pathname = yasm__xstrdup("./");
+ else if ((i = yasm__createpath(objdir_pathname)) > 0 &&
+ num_input_files > 1) {
+ objdir_pathname[i] = '/';
+ objdir_pathname[i+1] = '\0';
+ }
+
+ /* Create other output directories if necessary */
+ if (listdir_pathname && (i = yasm__createpath(listdir_pathname)) > 0 &&
+ num_input_files > 1) {
+ listdir_pathname[i] = '/';
+ listdir_pathname[i+1] = '\0';
+ }
+ if (mapdir_pathname && (i = yasm__createpath(mapdir_pathname)) > 0 &&
+ num_input_files > 1) {
+ mapdir_pathname[i] = '/';
+ mapdir_pathname[i+1] = '\0';
+ }
+
+ /* If not already specified, set file extensions */
+ if (!objext && cur_objfmt_module->extension)
+ objext = yasm__xstrdup(cur_objfmt_module->extension);
+ if (!listext)
+ listext = yasm__xstrdup("lst");
+ if (!mapext)
+ mapext = yasm__xstrdup("map");
+
+ /* Assemble each input file. Terminate on first error. */
+ STAILQ_FOREACH(infile, &input_files, link)
+ {
+ if (do_assemble(infile->param) == EXIT_FAILURE) {
+ cleanup();
+ return EXIT_FAILURE;
+ }
+ }
+ cleanup();
+ return EXIT_SUCCESS;
+}
+/*@=globstate =unrecog@*/
+
+/* Open the object file. Returns 0 on failure. */
+static FILE *
+open_file(const char *filename, const char *mode)
+{
+ FILE *f;
+
+ f = fopen(filename, mode);
+ if (!f)
+ print_error(_("could not open file `%s'"), filename);
+ return f;
+}
+
+static int
+check_errors(yasm_errwarns *errwarns, yasm_object *object,
+ yasm_linemap *linemap, yasm_preproc *preproc, yasm_arch *arch)
+{
+ if (yasm_errwarns_num_errors(errwarns, warning_error) > 0) {
+ yasm_errwarns_output_all(errwarns, linemap, warning_error,
+ print_yasm_error, print_yasm_warning);
+ yasm_preproc_destroy(preproc);
+ yasm_object_destroy(object);
+ yasm_linemap_destroy(linemap);
+ yasm_errwarns_destroy(errwarns);
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+/* Define DO_FREE to 1 to enable deallocation of all data structures.
+ * Useful for detecting memory leaks, but slows down execution unnecessarily
+ * (as the OS will free everything we miss here).
+ */
+#define DO_FREE 1
+
+/* Cleans up all allocated structures. */
+static void
+cleanup(void)
+{
+ if (DO_FREE) {
+ yasm_floatnum_cleanup();
+ yasm_intnum_cleanup();
+
+ yasm_errwarn_cleanup();
+
+ BitVector_Shutdown();
+ }
+
+ if (DO_FREE) {
+ free_input_filenames();
+ if (objdir_pathname)
+ yasm_xfree(objdir_pathname);
+ if (listdir_pathname)
+ yasm_xfree(listdir_pathname);
+ if (mapdir_pathname)
+ yasm_xfree(mapdir_pathname);
+ if (objext)
+ yasm_xfree(objext);
+ if (listext)
+ yasm_xfree(listext);
+ if (mapext)
+ yasm_xfree(mapext);
+ if (machine_name)
+ yasm_xfree(machine_name);
+ if (objfmt_keyword)
+ yasm_xfree(objfmt_keyword);
+ free_preproc_saved_options();
+ }
+
+ if (errfile != stderr && errfile != stdout)
+ fclose(errfile);
+#if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
+ unload_plugins();
+#endif
+}
+
+static void
+free_input_filenames(void)
+{
+ constcharparam *cp, *cpnext;
+ cp = STAILQ_FIRST(&input_files);
+ while (cp != NULL) {
+ cpnext = STAILQ_NEXT(cp, link);
+ yasm_xfree(cp);
+ cp = cpnext;
+ }
+ STAILQ_INIT(&input_files);
+}
+
+/*
+ * Command line options handlers
+ */
+int
+not_an_option_handler(char *param)
+{
+ constcharparam *cp;
+ cp = yasm_xmalloc(sizeof(constcharparam));
+ cp->param = param;
+ cp->id = 0;
+ STAILQ_INSERT_TAIL(&input_files, cp, link);
+ ++num_input_files;
+ return 0;
+}
+
+int
+other_option_handler(char *option)
+{
+ /* Accept, but ignore, -O and -Onnn, for compatibility with NASM. */
+ if (option[0] == '-' && option[1] == 'O') {
+ int n = 2;
+ for (;;) {
+ if (option[n] == '\0')
+ return 0;
+ if (!isdigit(option[n]))
+ return 1;
+ n++;
+ }
+ }
+ return 1;
+}
+
+static int
+opt_special_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+ if (special_options == 0)
+ special_options = extra;
+ return 0;
+}
+
+static int
+opt_arch_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ assert(param != NULL);
+ cur_arch_module = yasm_load_arch(param);
+ if (!cur_arch_module) {
+ if (!strcmp("help", param)) {
+ printf(_("Available yasm %s:\n"), _("architectures"));
+ yasm_list_arch(print_list_keyword_desc);
+ special_options = SPECIAL_LISTED;
+ return 0;
+ }
+ print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
+ _("architecture"), param);
+ exit(EXIT_FAILURE);
+ }
+ return 0;
+}
+
+static int
+opt_parser_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ assert(param != NULL);
+ cur_parser_module = yasm_load_parser(param);
+ if (!cur_parser_module) {
+ if (!strcmp("help", param)) {
+ printf(_("Available yasm %s:\n"), _("parsers"));
+ yasm_list_parser(print_list_keyword_desc);
+ special_options = SPECIAL_LISTED;
+ return 0;
+ }
+ print_error(_("%s: unrecognized %s `%s'"), _("FATAL"), _("parser"),
+ param);
+ exit(EXIT_FAILURE);
+ }
+ return 0;
+}
+
+static int
+opt_preproc_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ assert(param != NULL);
+ cur_preproc_module = yasm_load_preproc(param);
+ if (!cur_preproc_module) {
+ if (!strcmp("help", param)) {
+ printf(_("Available yasm %s:\n"), _("preprocessors"));
+ yasm_list_preproc(print_list_keyword_desc);
+ special_options = SPECIAL_LISTED;
+ return 0;
+ }
+ print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
+ _("preprocessor"), param);
+ exit(EXIT_FAILURE);
+ }
+ return 0;
+}
+
+static int
+opt_objfmt_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ size_t i;
+ assert(param != NULL);
+ cur_objfmt_module = yasm_load_objfmt(param);
+ if (!cur_objfmt_module) {
+ if (!strcmp("help", param)) {
+ printf(_("Available yasm %s:\n"), _("object formats"));
+ yasm_list_objfmt(print_list_keyword_desc);
+ special_options = SPECIAL_LISTED;
+ return 0;
+ }
+ print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
+ _("object format"), param);
+ exit(EXIT_FAILURE);
+ }
+ if (objfmt_keyword)
+ yasm_xfree(objfmt_keyword);
+ objfmt_keyword = yasm__xstrdup(param);
+ for (i=0; i<strlen(objfmt_keyword); i++)
+ objfmt_keyword[i] = tolower(objfmt_keyword[i]);
+ return 0;
+}
+
+static int
+opt_dbgfmt_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ assert(param != NULL);
+ cur_dbgfmt_module = yasm_load_dbgfmt(param);
+ if (!cur_dbgfmt_module) {
+ if (!strcmp("help", param)) {
+ printf(_("Available yasm %s:\n"), _("debug formats"));
+ yasm_list_dbgfmt(print_list_keyword_desc);
+ special_options = SPECIAL_LISTED;
+ return 0;
+ }
+ print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
+ _("debug format"), param);
+ exit(EXIT_FAILURE);
+ }
+ return 0;
+}
+
+static int
+opt_listfmt_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ assert(param != NULL);
+ cur_listfmt_module = yasm_load_listfmt(param);
+ if (!cur_listfmt_module) {
+ if (!strcmp("help", param)) {
+ printf(_("Available yasm %s:\n"), _("list formats"));
+ yasm_list_listfmt(print_list_keyword_desc);
+ special_options = SPECIAL_LISTED;
+ return 0;
+ }
+ print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
+ _("list format"), param);
+ exit(EXIT_FAILURE);
+ }
+ return 0;
+}
+
+static int
+opt_listdir_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ if (listdir_pathname) {
+ print_error(
+ _("warning: can output to only one list dir, last specified used"));
+ yasm_xfree(listdir_pathname);
+ }
+
+ assert(param != NULL);
+ listdir_pathname = yasm_xmalloc(strlen(param)+2);
+ strcpy(listdir_pathname, param);
+
+ return 0;
+}
+
+static int
+opt_objdir_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ if (objdir_pathname) {
+ print_error(
+ _("warning: can output to only one object dir, last specified used"));
+ yasm_xfree(objdir_pathname);
+ }
+
+ assert(param != NULL);
+ objdir_pathname = yasm_xmalloc(strlen(param)+2);
+ strcpy(objdir_pathname, param);
+
+ return 0;
+}
+
+static int
+opt_mapdir_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ if (mapdir_pathname) {
+ print_error(
+ _("warning: can output to only one map file, last specified used"));
+ yasm_xfree(mapdir_pathname);
+ }
+
+ assert(param != NULL);
+ mapdir_pathname = yasm_xmalloc(strlen(param)+2);
+ strcpy(mapdir_pathname, param);
+
+ return 0;
+}
+
+static int
+opt_listext_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ if (listext) {
+ print_error(
+ _("warning: can set only one list extension, last specified used"));
+ yasm_xfree(listext);
+ }
+ assert(param != NULL);
+ listext = yasm__xstrdup(param);
+ return 0;
+}
+
+static int
+opt_objext_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ if (objext) {
+ print_error(
+ _("warning: can set only one object extension, last specified used"));
+ yasm_xfree(objext);
+ }
+ assert(param != NULL);
+ objext = yasm__xstrdup(param);
+ return 0;
+}
+
+static int
+opt_mapext_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ if (mapext) {
+ print_error(
+ _("warning: can set only one map extension, last specified used"));
+ yasm_xfree(mapext);
+ }
+ assert(param != NULL);
+ mapext = yasm__xstrdup(param);
+ return 0;
+}
+
+static int
+opt_machine_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ if (machine_name)
+ yasm_xfree(machine_name);
+
+ assert(param != NULL);
+ machine_name = yasm__xstrdup(param);
+
+ return 0;
+}
+
+static int
+opt_strict_handler(/*@unused@*/ char *cmd,
+ /*@unused@*/ /*@null@*/ char *param,
+ /*@unused@*/ int extra)
+{
+ force_strict = 1;
+ return 0;
+}
+
+static int
+opt_warning_handler(char *cmd, /*@unused@*/ char *param, int extra)
+{
+ /* is it disabling the warning instead of enabling? */
+ void (*action)(yasm_warn_class wclass) = yasm_warn_enable;
+
+ if (extra == 1) {
+ /* -w, disable warnings */
+ yasm_warn_disable_all();
+ return 0;
+ }
+
+ /* skip past 'W' */
+ cmd++;
+
+ /* detect no- prefix to disable the warning */
+ if (cmd[0] == 'n' && cmd[1] == 'o' && cmd[2] == '-') {
+ action = yasm_warn_disable;
+ cmd += 3; /* skip past it to get to the warning name */
+ }
+
+ if (cmd[0] == '\0')
+ /* just -W or -Wno-, so definitely not valid */
+ return 1;
+ else if (strcmp(cmd, "error") == 0)
+ warning_error = (action == yasm_warn_enable);
+ else if (strcmp(cmd, "unrecognized-char") == 0)
+ action(YASM_WARN_UNREC_CHAR);
+ else if (strcmp(cmd, "orphan-labels") == 0)
+ action(YASM_WARN_ORPHAN_LABEL);
+ else if (strcmp(cmd, "uninit-contents") == 0)
+ action(YASM_WARN_UNINIT_CONTENTS);
+ else if (strcmp(cmd, "size-override") == 0)
+ action(YASM_WARN_SIZE_OVERRIDE);
+ else
+ return 1;
+
+ return 0;
+}
+
+static int
+opt_error_file(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ if (error_filename) {
+ print_error(
+ _("warning: can output to only one error file, last specified used"));
+ yasm_xfree(error_filename);
+ }
+
+ assert(param != NULL);
+ error_filename = yasm__xstrdup(param);
+
+ return 0;
+}
+
+static int
+opt_error_stdout(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
+ /*@unused@*/ int extra)
+{
+ /* Clear any specified error filename */
+ if (error_filename) {
+ yasm_xfree(error_filename);
+ error_filename = NULL;
+ }
+ errfile = stdout;
+ return 0;
+}
+
+static int
+opt_include_option(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ yasm_add_include_path(param);
+ return 0;
+}
+
+static int
+opt_preproc_option(/*@unused@*/ char *cmd, char *param, int extra)
+{
+ constcharparam *cp;
+ cp = yasm_xmalloc(sizeof(constcharparam));
+ cp->param = param;
+ cp->id = extra;
+ STAILQ_INSERT_TAIL(&preproc_options, cp, link);
+ return 0;
+}
+
+static int
+opt_ewmsg_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ if (yasm__strcasecmp(param, "gnu") == 0 ||
+ yasm__strcasecmp(param, "gcc") == 0) {
+ ewmsg_style = EWSTYLE_GNU;
+ } else if (yasm__strcasecmp(param, "vc") == 0) {
+ ewmsg_style = EWSTYLE_VC;
+ } else
+ print_error(_("warning: unrecognized message style `%s'"), param);
+
+ return 0;
+}
+
+static int
+opt_prefix_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ if (global_prefix)
+ yasm_xfree(global_prefix);
+
+ assert(param != NULL);
+ global_prefix = yasm__xstrdup(param);
+
+ return 0;
+}
+
+static int
+opt_suffix_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ if (global_suffix)
+ yasm_xfree(global_suffix);
+
+ assert(param != NULL);
+ global_suffix = yasm__xstrdup(param);
+
+ return 0;
+}
+
+#if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
+static int
+opt_plugin_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ if (!load_plugin(param))
+ print_error(_("warning: could not load plugin `%s'"), param);
+ return 0;
+}
+#endif
+
+static void
+apply_preproc_builtins(yasm_preproc *preproc)
+{
+ char *predef;
+
+ /* Define standard YASM assembly-time macro constants */
+ predef = yasm_xmalloc(strlen("__YASM_OBJFMT__=")
+ + strlen(objfmt_keyword) + 1);
+ strcpy(predef, "__YASM_OBJFMT__=");
+ strcat(predef, objfmt_keyword);
+ yasm_preproc_define_builtin(preproc, predef);
+ yasm_xfree(predef);
+}
+
+static void
+apply_preproc_standard_macros(yasm_preproc *preproc, const yasm_stdmac *stdmacs)
+{
+ int i, matched;
+
+ if (!stdmacs)
+ return;
+
+ matched = -1;
+ for (i=0; stdmacs[i].parser; i++)
+ if (yasm__strcasecmp(stdmacs[i].parser,
+ cur_parser_module->keyword) == 0 &&
+ yasm__strcasecmp(stdmacs[i].preproc,
+ cur_preproc_module->keyword) == 0)
+ matched = i;
+ if (matched >= 0 && stdmacs[matched].macros)
+ yasm_preproc_add_standard(preproc, stdmacs[matched].macros);
+}
+
+static void
+apply_preproc_saved_options(yasm_preproc *preproc)
+{
+ constcharparam *cp;
+
+ void (*funcs[3])(yasm_preproc *, const char *);
+ funcs[0] = cur_preproc_module->add_include_file;
+ funcs[1] = cur_preproc_module->predefine_macro;
+ funcs[2] = cur_preproc_module->undefine_macro;
+
+ STAILQ_FOREACH(cp, &preproc_options, link) {
+ if (0 <= cp->id && cp->id < 3 && funcs[cp->id])
+ funcs[cp->id](preproc, cp->param);
+ }
+}
+
+static void
+free_preproc_saved_options(void)
+{
+ constcharparam *cp, *cpnext;
+ cp = STAILQ_FIRST(&preproc_options);
+ while (cp != NULL) {
+ cpnext = STAILQ_NEXT(cp, link);
+ yasm_xfree(cp);
+ cp = cpnext;
+ }
+ STAILQ_INIT(&preproc_options);
+}
+
+/* Replace extension on a filename (or append one if none is present).
+ * If output filename would be identical to input (same extension out as in),
+ * returns NULL.
+ * A NULL ext means the trailing '.' should NOT be included, whereas a "" ext
+ * means the trailing '.' should be included.
+ */
+static char *
+replace_extension(const char *orig, /*@null@*/ const char *ext)
+{
+ char *out, *outext;
+ size_t outlen;
+
+ /* allocate enough space for full existing name + extension */
+ outlen = strlen(orig) + 2;
+ if (ext)
+ outlen += strlen(ext) + 1;
+ out = yasm_xmalloc(outlen);
+
+ strcpy(out, orig);
+ outext = strrchr(out, '.');
+ if (outext) {
+ /* Existing extension: make sure it's not the same as the replacement
+ * (as we don't want to overwrite the source file).
+ */
+ outext++; /* advance past '.' */
+ if (ext && strcmp(outext, ext) == 0) {
+ outext = NULL; /* indicate default should be used */
+ print_error(_("file name already ends in `.%s'"), ext);
+ }
+ } else {
+ /* No extension: make sure the output extension is not empty
+ * (again, we don't want to overwrite the source file).
+ */
+ if (!ext) {
+ outext = NULL;
+ print_error(_("file name already has no extension"));
+ } else {
+ outext = strrchr(out, '\0'); /* point to end of the string */
+ *outext++ = '.'; /* append '.' */
+ }
+ }
+
+ /* replace extension or use default name */
+ if (outext) {
+ if (!ext) {
+ /* Back up and replace '.' with string terminator */
+ outext--;
+ *outext = '\0';
+ } else
+ strcpy(outext, ext);
+ } else
+ return NULL;
+
+ return out;
+}
+
+void
+print_list_keyword_desc(const char *name, const char *keyword)
+{
+ printf("%4s%-12s%s\n", "", keyword, name);
+}
+
+static void
+print_error(const char *fmt, ...)
+{
+ va_list va;
+ fprintf(errfile, "vsyasm: ");
+ va_start(va, fmt);
+ vfprintf(errfile, fmt, va);
+ va_end(va);
+ fputc('\n', errfile);
+}
+
+static /*@exits@*/ void
+handle_yasm_int_error(const char *file, unsigned int line, const char *message)
+{
+ fprintf(stderr, _("INTERNAL ERROR at %s, line %u: %s\n"), file, line,
+ gettext(message));
+#ifdef HAVE_ABORT
+ abort();
+#else
+ exit(EXIT_FAILURE);
+#endif
+}
+
+static /*@exits@*/ void
+handle_yasm_fatal(const char *fmt, va_list va)
+{
+ fprintf(errfile, "vsyasm: %s: ", _("FATAL"));
+ vfprintf(errfile, gettext(fmt), va);
+ fputc('\n', errfile);
+ exit(EXIT_FAILURE);
+}
+
+static const char *
+handle_yasm_gettext(const char *msgid)
+{
+ return gettext(msgid);
+}
+
+static const char *fmt[2] = {
+ "%s:%lu: %s%s\n", /* GNU */
+ "%s(%lu) : %s%s\n" /* VC */
+};
+
+static const char *fmt_noline[2] = {
+ "%s: %s%s\n", /* GNU */
+ "%s : %s%s\n" /* VC */
+};
+
+static void
+print_yasm_error(const char *filename, unsigned long line, const char *msg,
+ const char *xref_fn, unsigned long xref_line,
+ const char *xref_msg)
+{
+ if (line)
+ fprintf(errfile, fmt[ewmsg_style], filename, line, _("error: "), msg);
+ else
+ fprintf(errfile, fmt_noline[ewmsg_style], filename, _("error: "), msg);
+
+ if (xref_fn && xref_msg) {
+ if (xref_line)
+ fprintf(errfile, fmt[ewmsg_style], xref_fn, xref_line, _("error: "),
+ xref_msg);
+ else
+ fprintf(errfile, fmt_noline[ewmsg_style], xref_fn, _("error: "),
+ xref_msg);
+ }
+}
+
+static void
+print_yasm_warning(const char *filename, unsigned long line, const char *msg)
+{
+ if (line)
+ fprintf(errfile, fmt[ewmsg_style], filename, line, _("warning: "),
+ msg);
+ else
+ fprintf(errfile, fmt_noline[ewmsg_style], filename, _("warning: "),
+ msg);
+}
diff --git a/contrib/tools/yasm/frontends/yasm/license.c b/contrib/tools/yasm/frontends/yasm/license.c
new file mode 100644
index 0000000000..35c5a04137
--- /dev/null
+++ b/contrib/tools/yasm/frontends/yasm/license.c
@@ -0,0 +1,65 @@
+/* This file auto-generated from COPYING by genstring.py - don't edit it */
+
+static const char* license_msg[] = {
+ "Yasm is Copyright (c) 2001-2014 Peter Johnson and other Yasm developers.",
+ "",
+ "Yasm developers and/or contributors include:",
+ "Peter Johnson",
+ "Michael Urman",
+ "Brian Gladman (Visual Studio build files, other fixes)",
+ "Stanislav Karchebny (options parser)",
+ "Mathieu Monnier (SSE4 instruction patches, NASM preprocessor additions)",
+ "Anonymous \"NASM64\" developer (NASM preprocessor fixes)",
+ "Stephen Polkowski (x86 instruction patches)",
+ "Henryk Richter (Mach-O object format)",
+ "Ben Skeggs (patches, bug reports)",
+ "Alexei Svitkine (GAS preprocessor)",
+ "Samuel Thibault (TASM parser and frontend)",
+ "",
+ "-----------------------------------",
+ "Yasm licensing overview and summary",
+ "-----------------------------------",
+ "",
+ "Note: This document does not provide legal advice nor is it the actual",
+ "license of any part of Yasm. See the individual licenses for complete",
+ "details. Consult a lawyer for legal advice.",
+ "",
+ "The primary license of Yasm is the 2-clause BSD license. Please use this",
+ "license if you plan on submitting code to the project.",
+ "",
+ "Yasm has absolutely no warranty; not even for merchantibility or fitness",
+ "for a particular purpose.",
+ "",
+ "-------",
+ "Libyasm",
+ "-------",
+ "Libyasm is 2-clause or 3-clause BSD licensed, with the exception of",
+ "bitvect, which is triple-licensed under the Artistic license, GPL, and",
+ "LGPL. Libyasm is thus GPL and LGPL compatible. In addition, this also",
+ "means that libyasm is free for binary-only distribution as long as the",
+ "terms of the 3-clause BSD license and Artistic license (as it applies to",
+ "bitvect) are fulfilled.",
+ "",
+ "-------",
+ "Modules",
+ "-------",
+ "The modules are 2-clause or 3-clause BSD licensed.",
+ "",
+ "---------",
+ "Frontends",
+ "---------",
+ "The frontends are 2-clause BSD licensed.",
+ "",
+ "-------------",
+ "License Texts",
+ "-------------",
+ "The full text of all licenses are provided in separate files in the source",
+ "distribution. Each source file may include the entire license (in the case",
+ "of the BSD and Artistic licenses), or may reference the GPL or LGPL license",
+ "file.",
+ "",
+ "BSD.txt - 2-clause and 3-clause BSD licenses",
+ "Artistic.txt - Artistic license",
+ "GNU_GPL-2.0 - GNU General Public License",
+ "GNU_LGPL-2.0 - GNU Library General Public License",
+};
diff --git a/contrib/tools/yasm/frontends/yasm/yasm-options.c b/contrib/tools/yasm/frontends/yasm/yasm-options.c
new file mode 100644
index 0000000000..eff6ba9a00
--- /dev/null
+++ b/contrib/tools/yasm/frontends/yasm/yasm-options.c
@@ -0,0 +1,216 @@
+/*
+ * Generic Options Support Header File
+ *
+ * Copyright (c) 2001 Stanislav Karchebny <berk@madfire.net>
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of other contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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 <util.h>
+#include <ctype.h>
+
+#include "yasm-options.h"
+
+
+#ifdef __DEBUG__
+#define DEBUG(x) fprintf ## x ;
+#else
+#define DEBUG(x)
+#endif
+
+
+/* Options Parser */
+int
+parse_cmdline(int argc, char **argv, opt_option *options, size_t nopts,
+ void (*print_error) (const char *fmt, ...))
+{
+ int errors = 0, warnings = 0;
+ size_t i;
+ int got_it;
+
+ DEBUG((stderr, "parse_cmdline: entered\n"));
+
+ fail:
+ while (--argc) {
+ argv++;
+
+ if (argv[0][0] == '-') { /* opt */
+ got_it = 0;
+ if (argv[0][1] == '-') { /* lopt */
+ if (argv[0][2] == '\0') { /* --, end of options */
+ /* Handle rest of args as non-options */
+ while (--argc) {
+ argv++;
+ if (not_an_option_handler(argv[0]))
+ errors++;
+ }
+ return errors;
+ }
+
+ for (i = 0; i < nopts; i++) {
+ size_t optlen;
+ if (options[i].lopt &&
+ strncmp(&argv[0][2], options[i].lopt,
+ (optlen = strlen(options[i].lopt))) == 0) {
+ char *param;
+ char c = argv[0][2 + optlen];
+
+ if (c != '\0' && c != '=' && !isspace(c))
+ continue;
+
+ if (options[i].takes_param) {
+ param = strchr(&argv[0][2], '=');
+ if (!param) {
+ print_error(
+ _("option `--%s' needs an argument!"),
+ options[i].lopt);
+ errors++;
+ goto fail;
+ } else {
+ *param = '\0';
+ param++;
+ }
+ } else
+ param = NULL;
+
+ if (!options[i].
+ handler(&argv[0][2], param, options[i].extra))
+ got_it = 1;
+ break;
+ }
+ }
+ if (!got_it && !other_option_handler(argv[0]))
+ got_it = 1;
+ if (!got_it) {
+ print_error(_("warning: unrecognized option `%s'"),
+ argv[0]);
+ warnings++;
+ }
+ } else if (argv[0][1] == '\0') { /* just -, is non-option */
+ if (not_an_option_handler(argv[0]))
+ errors++;
+ } else { /* sopt */
+ for (i = 0; i < nopts; i++) {
+ if (argv[0][1] == options[i].sopt) {
+ char *cmd = &argv[0][1];
+ char *param;
+
+ if (options[i].takes_param) {
+ param = argv[1];
+ if (argv[0][2] != '\0')
+ param = &argv[0][2];
+ else if (param == NULL || *param == '-') {
+ print_error(
+ _("option `-%c' needs an argument!"),
+ options[i].sopt);
+ errors++;
+ goto fail;
+ } else {
+ argc--;
+ argv++;
+ }
+ } else
+ param = NULL;
+
+ if (!options[i].handler(cmd, param, options[i].extra))
+ got_it = 1;
+ break;
+ }
+ }
+ if (!got_it && !other_option_handler(argv[0]))
+ got_it = 1;
+ if (!got_it) {
+ print_error(_("warning: unrecognized option `%s'"),
+ argv[0]);
+ warnings++;
+ }
+ }
+ } else { /* not an option, then it should be a file or something */
+
+ if (not_an_option_handler(argv[0]))
+ errors++;
+ }
+ }
+
+ DEBUG((stderr, "parse_cmdline: finished\n"));
+ return errors;
+}
+
+void
+help_msg(const char *msg, const char *tail, opt_option *options, size_t nopts)
+{
+ char optbuf[100], optopt[100];
+ size_t i;
+
+ printf("%s", gettext(msg));
+
+ for (i = 0; i < nopts; i++) {
+ size_t shortopt_len = 0;
+ size_t longopt_len = 0;
+
+ optbuf[0] = 0;
+ optopt[0] = 0;
+
+ if (options[i].takes_param) {
+ if (options[i].sopt) {
+ sprintf(optbuf, "-%c <%s>", options[i].sopt,
+ options[i].param_desc ? options[i].
+ param_desc : _("param"));
+ shortopt_len = strlen(optbuf);
+ }
+ if (options[i].sopt && options[i].lopt)
+ strcat(optbuf, ", ");
+ if (options[i].lopt) {
+ sprintf(optopt, "--%s=<%s>", options[i].lopt,
+ options[i].param_desc ? options[i].
+ param_desc : _("param"));
+ strcat(optbuf, optopt);
+ longopt_len = strlen(optbuf);
+ }
+ } else {
+ if (options[i].sopt) {
+ sprintf(optbuf, "-%c", options[i].sopt);
+ shortopt_len = strlen(optbuf);
+ }
+ if (options[i].sopt && options[i].lopt)
+ strcat(optbuf, ", ");
+ if (options[i].lopt) {
+ sprintf(optopt, "--%s", options[i].lopt);
+ strcat(optbuf, optopt);
+ longopt_len = strlen(optbuf);
+ }
+ }
+
+ /* split [-s <desc>], [--long <desc>] if it destroys columns */
+ if (shortopt_len && longopt_len && longopt_len > 22) {
+ optbuf[shortopt_len] = '\0';
+ printf(" %-22s %s\n", optopt, gettext(options[i].description));
+ printf(" %s\n", optbuf);
+ }
+ else
+ printf(" %-22s %s\n", optbuf, gettext(options[i].description));
+ }
+
+ printf("%s", gettext(tail));
+}
diff --git a/contrib/tools/yasm/frontends/yasm/yasm-options.h b/contrib/tools/yasm/frontends/yasm/yasm-options.h
new file mode 100644
index 0000000000..63c4fbeae1
--- /dev/null
+++ b/contrib/tools/yasm/frontends/yasm/yasm-options.h
@@ -0,0 +1,75 @@
+/*
+ * Generic Options Support Header File
+ *
+ * Copyright (c) 2001 Stanislav Karchebny <berk@madfire.net>
+ *
+ * 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.
+ */
+#ifndef YASM_OPTIONS_H
+#define YASM_OPTIONS_H
+
+/* an option structure
+ * operate on either -sopt, --lopt, -sopt <val> or --lopt=<val>
+ */
+typedef struct opt_option_s
+{
+ /* short option letter if present, 0 otherwise */
+ char sopt;
+
+ /* long option name if present, NULL otherwise */
+ /*@null@*/ const char *lopt;
+
+ /* !=0 if option requires parameter, 0 if not */
+ int takes_param;
+
+ int (*handler) (char *cmd, /*@null@*/ char *param, int extra);
+ int extra; /* extra value for handler */
+
+ /* description to use in help_msg() */
+ /*@observer@*/ const char *description;
+
+ /* optional description for the param taken (NULL if not present) */
+ /* (short - will be printed after option sopt/lopt) */
+ /*@observer@*/ /*@null@*/ const char *param_desc;
+} opt_option;
+
+/* handle everything that is not an option */
+int not_an_option_handler(char *param);
+
+/* handle possibly other special-case options; no parameters allowed */
+int other_option_handler(char *option);
+
+/* parse command line calling handlers when appropriate
+ * argc, argv - pass directly from main(argc,argv)
+ * options - array of options
+ * nopts - options count
+ */
+int parse_cmdline(int argc, char **argv, opt_option *options, size_t nopts,
+ void (*print_error) (const char *fmt, ...));
+
+/* display help message msg followed by list of options in options and followed
+ * by tail
+ */
+void help_msg(const char *msg, const char *tail, opt_option *options,
+ size_t nopts);
+
+#endif
diff --git a/contrib/tools/yasm/frontends/yasm/yasm-plugin.c b/contrib/tools/yasm/frontends/yasm/yasm-plugin.c
new file mode 100644
index 0000000000..c64edc32f0
--- /dev/null
+++ b/contrib/tools/yasm/frontends/yasm/yasm-plugin.c
@@ -0,0 +1,126 @@
+/*
+ * Semi-portable (Windows and Unix) plugin loading
+ *
+ * Copyright (C) 2008 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 <util.h>
+
+#include <string.h>
+
+#include "libyasm-stdint.h"
+#include "yasm-plugin.h"
+
+#if defined(_MSC_VER)
+#include <windows.h>
+#elif defined(__GNUC__)
+#include <dlfcn.h>
+#endif
+
+static void **loaded_plugins = NULL;
+static int num_loaded_plugins = 0;
+
+static void *
+load_dll(const char *name)
+{
+#if defined(_MSC_VER)
+ return LoadLibrary(name);
+#elif defined(__GNUC__)
+ return dlopen(name, RTLD_NOW);
+#else
+ return NULL;
+#endif
+}
+
+int
+load_plugin(const char *name)
+{
+ char *path;
+ void *lib = NULL;
+ void (*init_plugin) (void) = NULL;
+
+ /* Load library */
+
+ path = yasm_xmalloc(strlen(name)+10);
+#if defined(_MSC_VER)
+ strcpy(path, name);
+ strcat(path, ".dll");
+ lib = load_dll(path);
+#elif defined(__GNUC__)
+ strcpy(path, "lib");
+ strcat(path, name);
+ strcat(path, ".so");
+ lib = load_dll(path);
+ if (!lib) {
+ strcpy(path, name);
+ strcat(path, ".so");
+ lib = load_dll(path);
+ }
+#endif
+ yasm_xfree(path);
+ if (!lib)
+ lib = load_dll(name);
+
+ if (!lib)
+ return 0; /* Didn't load successfully */
+
+ /* Add to array of loaded plugins */
+ loaded_plugins =
+ yasm_xrealloc(loaded_plugins, (num_loaded_plugins+1)*sizeof(void *));
+ loaded_plugins[num_loaded_plugins] = lib;
+ num_loaded_plugins++;
+
+ /* Get yasm_init_plugin() function and run it */
+
+#if defined(_MSC_VER)
+ init_plugin =
+ (void (*)(void))GetProcAddress((HINSTANCE)lib, "yasm_init_plugin");
+#elif defined(__GNUC__)
+ init_plugin = (void (*)(void))(uintptr_t)dlsym(lib, "yasm_init_plugin");
+#endif
+
+ if (!init_plugin)
+ return 0; /* Didn't load successfully */
+
+ init_plugin();
+ return 1;
+}
+
+void
+unload_plugins(void)
+{
+ int i;
+
+ if (!loaded_plugins)
+ return;
+
+ for (i = 0; i < num_loaded_plugins; i++) {
+#if defined(_MSC_VER)
+ FreeLibrary((HINSTANCE)loaded_plugins[i]);
+#elif defined(__GNUC__)
+ dlclose(loaded_plugins[i]);
+#endif
+ }
+ yasm_xfree(loaded_plugins);
+ num_loaded_plugins = 0;
+}
diff --git a/contrib/tools/yasm/frontends/yasm/yasm-plugin.h b/contrib/tools/yasm/frontends/yasm/yasm-plugin.h
new file mode 100644
index 0000000000..efb1bf513a
--- /dev/null
+++ b/contrib/tools/yasm/frontends/yasm/yasm-plugin.h
@@ -0,0 +1,34 @@
+/*
+ * Semi-portable (Windows and Unix) plugin loading
+ *
+ * Copyright (C) 2008 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.
+ */
+#ifndef YASM_PLUGIN_H
+#define YASM_PLUGIN_H
+
+/* Load a plugin. Returns 0 on failure. */
+int load_plugin(const char *name);
+void unload_plugins(void);
+
+#endif
diff --git a/contrib/tools/yasm/frontends/yasm/yasm.c b/contrib/tools/yasm/frontends/yasm/yasm.c
new file mode 100644
index 0000000000..2bd08890df
--- /dev/null
+++ b/contrib/tools/yasm/frontends/yasm/yasm.c
@@ -0,0 +1,1454 @@
+/*
+ * Program entry point, command line parsing
+ *
+ * Copyright (C) 2001-2007 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 <util.h>
+
+#include <ctype.h>
+#include <libyasm/compat-queue.h>
+#include <libyasm/bitvect.h>
+#include <libyasm.h>
+
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
+
+#include "yasm-options.h"
+
+#if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
+#include "yasm-plugin.h"
+#endif
+
+#include "license.c"
+
+/* Preprocess-only buffer size */
+#define PREPROC_BUF_SIZE 16384
+
+/*@null@*/ /*@only@*/ static char *obj_filename = NULL, *in_filename = NULL;
+/*@null@*/ /*@only@*/ static char *global_prefix = NULL, *global_suffix = NULL;
+/*@null@*/ /*@only@*/ static char *list_filename = NULL, *map_filename = NULL;
+/*@null@*/ /*@only@*/ static char *machine_name = NULL;
+static char **replace_params;
+static int replace_size = 0;
+static int replace_capacity = 0;
+static int special_options = 0;
+/*@null@*/ /*@dependent@*/ static yasm_arch *cur_arch = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_arch_module *
+ cur_arch_module = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_parser_module *
+ cur_parser_module = NULL;
+/*@null@*/ /*@dependent@*/ static yasm_preproc *cur_preproc = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_preproc_module *
+ cur_preproc_module = NULL;
+/*@null@*/ static char *objfmt_keyword = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_objfmt_module *
+ cur_objfmt_module = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_dbgfmt_module *
+ cur_dbgfmt_module = NULL;
+/*@null@*/ /*@dependent@*/ static yasm_listfmt *cur_listfmt = NULL;
+/*@null@*/ /*@dependent@*/ static const yasm_listfmt_module *
+ cur_listfmt_module = NULL;
+static int preproc_only = 0;
+static unsigned int force_strict = 0;
+static int generate_make_dependencies = 0;
+static int warning_error = 0; /* warnings being treated as errors */
+static FILE *errfile;
+/*@null@*/ /*@only@*/ static char *error_filename = NULL;
+static enum {
+ EWSTYLE_GNU = 0,
+ EWSTYLE_VC
+} ewmsg_style = EWSTYLE_GNU;
+
+/*@null@*/ /*@dependent@*/ static FILE *open_file(const char *filename,
+ const char *mode);
+static void check_errors(/*@only@*/ yasm_errwarns *errwarns,
+ /*@only@*/ yasm_object *object,
+ /*@only@*/ yasm_linemap *linemap);
+static void cleanup(/*@null@*/ /*@only@*/ yasm_object *object);
+
+/* Forward declarations: cmd line parser handlers */
+static int opt_special_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_arch_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_parser_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_preproc_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_objfmt_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_dbgfmt_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_listfmt_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_listfile_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_objfile_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_mapfile_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_machine_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_strict_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_warning_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_error_file(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_error_stdout(char *cmd, /*@null@*/ char *param, int extra);
+static int preproc_only_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_include_option(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_preproc_option(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_ewmsg_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_makedep_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_prefix_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_replace_handler(char *cmd, /*@null@*/ char *param, int extra);
+static int opt_suffix_handler(char *cmd, /*@null@*/ char *param, int extra);
+#if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
+static int opt_plugin_handler(char *cmd, /*@null@*/ char *param, int extra);
+#endif
+
+#if defined(CMAKE_BUILD) && !defined(BUILD_SHARED_LIBS)
+void yasm_init_plugin(void);
+void yasm_plugin_set_replace(const char* replace[], int size);
+#endif
+
+static /*@only@*/ char *replace_extension(const char *orig, /*@null@*/
+ const char *ext, const char *def);
+static void print_error(const char *fmt, ...);
+
+static /*@exits@*/ void handle_yasm_int_error(const char *file,
+ unsigned int line,
+ const char *message);
+static /*@exits@*/ void handle_yasm_fatal(const char *message, va_list va);
+static const char *handle_yasm_gettext(const char *msgid);
+static void print_yasm_error(const char *filename, unsigned long line,
+ const char *msg, /*@null@*/ const char *xref_fn,
+ unsigned long xref_line,
+ /*@null@*/ const char *xref_msg);
+static void print_yasm_warning(const char *filename, unsigned long line,
+ const char *msg);
+
+static void apply_preproc_builtins(void);
+static void apply_preproc_standard_macros(const yasm_stdmac *stdmacs);
+static void apply_preproc_saved_options(void);
+static void print_list_keyword_desc(const char *name, const char *keyword);
+
+/* values for special_options */
+#define SPECIAL_SHOW_HELP 0x01
+#define SPECIAL_SHOW_VERSION 0x02
+#define SPECIAL_SHOW_LICENSE 0x04
+#define SPECIAL_LISTED 0x08
+
+/* command line options */
+static opt_option options[] =
+{
+ { 0, "version", 0, opt_special_handler, SPECIAL_SHOW_VERSION,
+ N_("show version text"), NULL },
+ { 0, "license", 0, opt_special_handler, SPECIAL_SHOW_LICENSE,
+ N_("show license text"), NULL },
+ { 'h', "help", 0, opt_special_handler, SPECIAL_SHOW_HELP,
+ N_("show help text"), NULL },
+ { 'a', "arch", 1, opt_arch_handler, 0,
+ N_("select architecture (list with -a help)"), N_("arch") },
+ { 'p', "parser", 1, opt_parser_handler, 0,
+ N_("select parser (list with -p help)"), N_("parser") },
+ { 'r', "preproc", 1, opt_preproc_handler, 0,
+ N_("select preprocessor (list with -r help)"), N_("preproc") },
+ { 'f', "oformat", 1, opt_objfmt_handler, 0,
+ N_("select object format (list with -f help)"), N_("format") },
+ { 'g', "dformat", 1, opt_dbgfmt_handler, 0,
+ N_("select debugging format (list with -g help)"), N_("debug") },
+ { 'L', "lformat", 1, opt_listfmt_handler, 0,
+ N_("select list format (list with -L help)"), N_("list") },
+ { 'l', "list", 1, opt_listfile_handler, 0,
+ N_("name of list-file output"), N_("listfile") },
+ { 'o', "objfile", 1, opt_objfile_handler, 0,
+ N_("name of object-file output"), N_("filename") },
+ { 0, "mapfile", 1, opt_mapfile_handler, 0,
+ N_("name of map-file output"), N_("filename") },
+ { 'm', "machine", 1, opt_machine_handler, 0,
+ N_("select machine (list with -m help)"), N_("machine") },
+ { 0, "force-strict", 0, opt_strict_handler, 0,
+ N_("treat all sized operands as if `strict' was used"), NULL },
+ { 'w', NULL, 0, opt_warning_handler, 1,
+ N_("inhibits warning messages"), NULL },
+ { 'W', NULL, 0, opt_warning_handler, 0,
+ N_("enables/disables warning"), NULL },
+ { 'M', NULL, 0, opt_makedep_handler, 0,
+ N_("generate Makefile dependencies on stdout"), NULL },
+ { 'E', NULL, 1, opt_error_file, 0,
+ N_("redirect error messages to file"), N_("file") },
+ { 's', NULL, 0, opt_error_stdout, 0,
+ N_("redirect error messages to stdout"), NULL },
+ { 'e', "preproc-only", 0, preproc_only_handler, 0,
+ N_("preprocess only (writes output to stdout by default)"), NULL },
+ { 'i', NULL, 1, opt_include_option, 0,
+ N_("add include path"), N_("path") },
+ { 'I', NULL, 1, opt_include_option, 0,
+ N_("add include path"), N_("path") },
+ { 'P', NULL, 1, opt_preproc_option, 0,
+ N_("pre-include file"), N_("filename") },
+ { 'd', NULL, 1, opt_preproc_option, 1,
+ N_("pre-define a macro, optionally to value"), N_("macro[=value]") },
+ { 'D', NULL, 1, opt_preproc_option, 1,
+ N_("pre-define a macro, optionally to value"), N_("macro[=value]") },
+ { 'u', NULL, 1, opt_preproc_option, 2,
+ N_("undefine a macro"), N_("macro") },
+ { 'U', NULL, 1, opt_preproc_option, 2,
+ N_("undefine a macro"), N_("macro") },
+ { 'X', NULL, 1, opt_ewmsg_handler, 0,
+ N_("select error/warning message style (`gnu' or `vc')"), N_("style") },
+ { 0, "prefix", 1, opt_prefix_handler, 0,
+ N_("prepend argument to name of all external symbols"), N_("prefix") },
+ { 0, "suffix", 1, opt_suffix_handler, 0,
+ N_("append argument to name of all external symbols"), N_("suffix") },
+ { 0, "postfix", 1, opt_suffix_handler, 0,
+ N_("append argument to name of all external symbols"), N_("suffix") },
+#if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
+ { 'N', "plugin", 1, opt_plugin_handler, 0,
+ N_("load plugin module"), N_("plugin") },
+#endif
+ { 0, "replace", 1, opt_replace_handler, 0,
+ N_("replace names"), N_("replace") },
+};
+
+/* version message */
+/*@observer@*/ static const char *version_msg[] = {
+ PACKAGE_STRING,
+ "Compiled on " __DATE__ ".",
+ "Copyright (c) 2001-2014 Peter Johnson and other Yasm developers.",
+ "Run yasm --license for licensing overview and summary."
+};
+
+/* help messages */
+/*@observer@*/ static const char *help_head = N_(
+ "usage: yasm [option]* file\n"
+ "Options:\n");
+/*@observer@*/ static const char *help_tail = N_(
+ "\n"
+ "Files are asm sources to be assembled.\n"
+ "\n"
+ "Sample invocation:\n"
+ " yasm -f elf -o object.o source.asm\n"
+ "\n"
+ "Report bugs to bug-yasm@tortall.net\n");
+
+/* parsed command line storage until appropriate modules have been loaded */
+typedef STAILQ_HEAD(constcharparam_head, constcharparam) constcharparam_head;
+
+typedef struct constcharparam {
+ STAILQ_ENTRY(constcharparam) link;
+ const char *param;
+ int id;
+} constcharparam;
+
+static constcharparam_head preproc_options;
+
+static int
+do_preproc_only(void)
+{
+ yasm_linemap *linemap;
+ char *preproc_buf;
+ size_t got;
+ const char *base_filename;
+ FILE *out = NULL;
+ yasm_errwarns *errwarns = yasm_errwarns_create();
+
+ /* Initialize line map */
+ linemap = yasm_linemap_create();
+ yasm_linemap_set(linemap, in_filename, 0, 1, 1);
+
+ /* Default output to stdout if not specified or generating dependency
+ makefiles */
+ if (!obj_filename || generate_make_dependencies) {
+ out = stdout;
+
+ /* determine the object filename if not specified, but we need a
+ file name for the makefile rule */
+ if (generate_make_dependencies && !obj_filename) {
+ if (in_filename == NULL)
+ /* Default to yasm.out if no obj filename specified */
+ obj_filename = yasm__xstrdup("yasm.out");
+ else {
+ /* replace (or add) extension to base filename */
+ yasm__splitpath(in_filename, &base_filename);
+ if (base_filename[0] == '\0')
+ obj_filename = yasm__xstrdup("yasm.out");
+ else
+ obj_filename = replace_extension(base_filename,
+ cur_objfmt_module->extension, "yasm.out");
+ }
+ }
+ } else {
+ /* Open output (object) file */
+ out = open_file(obj_filename, "wt");
+ if (!out)
+ return EXIT_FAILURE;
+ }
+
+ /* Create preprocessor */
+ cur_preproc = yasm_preproc_create(cur_preproc_module, in_filename, NULL,
+ linemap, errwarns);
+
+ /* Apply macros */
+ apply_preproc_builtins();
+ apply_preproc_standard_macros(cur_parser_module->stdmacs);
+ apply_preproc_standard_macros(cur_objfmt_module->stdmacs);
+ apply_preproc_saved_options();
+
+ /* Pre-process until done */
+ if (generate_make_dependencies) {
+ size_t totlen;
+
+ preproc_buf = yasm_xmalloc(PREPROC_BUF_SIZE);
+
+ fprintf(stdout, "%s: %s", obj_filename, in_filename);
+ totlen = strlen(obj_filename)+2+strlen(in_filename);
+
+ while ((got = yasm_preproc_get_included_file(cur_preproc, preproc_buf,
+ PREPROC_BUF_SIZE)) != 0) {
+ totlen += got;
+ if (totlen > 72) {
+ fputs(" \\\n ", stdout);
+ totlen = 2;
+ }
+ fputc(' ', stdout);
+ fwrite(preproc_buf, got, 1, stdout);
+ }
+ fputc('\n', stdout);
+ yasm_xfree(preproc_buf);
+ } else {
+ while ((preproc_buf = yasm_preproc_get_line(cur_preproc)) != NULL) {
+ fputs(preproc_buf, out);
+ fputc('\n', out);
+ yasm_xfree(preproc_buf);
+ }
+ }
+
+ if (out != stdout)
+ fclose(out);
+
+ if (yasm_errwarns_num_errors(errwarns, warning_error) > 0) {
+ yasm_errwarns_output_all(errwarns, linemap, warning_error,
+ print_yasm_error, print_yasm_warning);
+ if (out != stdout)
+ remove(obj_filename);
+ yasm_linemap_destroy(linemap);
+ yasm_errwarns_destroy(errwarns);
+ cleanup(NULL);
+ return EXIT_FAILURE;
+ }
+
+ yasm_errwarns_output_all(errwarns, linemap, warning_error,
+ print_yasm_error, print_yasm_warning);
+ yasm_linemap_destroy(linemap);
+ yasm_errwarns_destroy(errwarns);
+ cleanup(NULL);
+ return EXIT_SUCCESS;
+}
+
+static int
+do_assemble(void)
+{
+ yasm_object *object;
+ const char *base_filename;
+ /*@null@*/ FILE *obj = NULL;
+ yasm_arch_create_error arch_error;
+ yasm_linemap *linemap;
+ yasm_errwarns *errwarns = yasm_errwarns_create();
+ int i, matched;
+ const char *machine;
+
+ /* Initialize line map */
+ linemap = yasm_linemap_create();
+ yasm_linemap_set(linemap, in_filename, 0, 1, 1);
+
+ /* determine the object filename if not specified */
+ if (!obj_filename) {
+ if (in_filename == NULL)
+ /* Default to yasm.out if no obj filename specified */
+ obj_filename = yasm__xstrdup("yasm.out");
+ else {
+ /* replace (or add) extension to base filename */
+ yasm__splitpath(in_filename, &base_filename);
+ if (base_filename[0] == '\0')
+ obj_filename = yasm__xstrdup("yasm.out");
+ else
+ obj_filename = replace_extension(base_filename,
+ cur_objfmt_module->extension,
+ "yasm.out");
+ }
+ }
+
+ /* Set up architecture using machine and parser. */
+ if (!machine_name) {
+ /* If we're using x86 and the default objfmt bits is 64, default the
+ * machine to amd64. When we get more arches with multiple machines,
+ * we should do this in a more modular fashion.
+ */
+ if (strcmp(cur_arch_module->keyword, "x86") == 0 &&
+ cur_objfmt_module->default_x86_mode_bits == 64)
+ machine_name = yasm__xstrdup("amd64");
+ else
+ machine_name =
+ yasm__xstrdup(cur_arch_module->default_machine_keyword);
+ }
+
+ /* If we're using amd64 and the default objfmt is elfx32, change the
+ * machine to "x32".
+ */
+ if (strcmp(machine_name, "amd64") == 0 &&
+ strcmp(cur_objfmt_module->keyword, "elfx32") == 0)
+ machine = "x32";
+ else
+ machine = machine_name;
+
+ cur_arch = yasm_arch_create(cur_arch_module, machine,
+ cur_parser_module->keyword, &arch_error);
+ if (!cur_arch) {
+ switch (arch_error) {
+ case YASM_ARCH_CREATE_BAD_MACHINE:
+ print_error(_("%s: `%s' is not a valid %s for %s `%s'"),
+ _("FATAL"), machine_name, _("machine"),
+ _("architecture"), cur_arch_module->keyword);
+ break;
+ case YASM_ARCH_CREATE_BAD_PARSER:
+ print_error(_("%s: `%s' is not a valid %s for %s `%s'"),
+ _("FATAL"), cur_parser_module->keyword,
+ _("parser"), _("architecture"),
+ cur_arch_module->keyword);
+ break;
+ default:
+ print_error(_("%s: unknown architecture error"), _("FATAL"));
+ }
+
+ return EXIT_FAILURE;
+ }
+
+ /* Create object */
+ object = yasm_object_create(in_filename, obj_filename, cur_arch,
+ cur_objfmt_module, cur_dbgfmt_module);
+ if (!object) {
+ yasm_error_class eclass;
+ unsigned long xrefline;
+ /*@only@*/ /*@null@*/ char *estr, *xrefstr;
+
+ yasm_error_fetch(&eclass, &estr, &xrefline, &xrefstr);
+ print_error("%s: %s", _("FATAL"), estr);
+ yasm_xfree(estr);
+ yasm_xfree(xrefstr);
+
+ cleanup(object);
+ return EXIT_FAILURE;
+ }
+
+ /* Get a fresh copy of objfmt_module as it may have changed. */
+ cur_objfmt_module = ((yasm_objfmt_base *)object->objfmt)->module;
+
+ /* Check to see if the requested preprocessor is in the allowed list
+ * for the active parser.
+ */
+ matched = 0;
+ for (i=0; cur_parser_module->preproc_keywords[i]; i++)
+ {
+ if (yasm__strcasecmp(cur_parser_module->preproc_keywords[i],
+ cur_preproc_module->keyword) == 0) {
+ matched = 1;
+ break;
+ }
+ }
+
+ if (!matched) {
+ print_error(_("%s: `%s' is not a valid %s for %s `%s'"), _("FATAL"),
+ cur_preproc_module->keyword, _("preprocessor"),
+ _("parser"), cur_parser_module->keyword);
+ cleanup(object);
+ return EXIT_FAILURE;
+ }
+
+ if (global_prefix)
+ yasm_object_set_global_prefix(object, global_prefix);
+ if (global_suffix)
+ yasm_object_set_global_suffix(object, global_suffix);
+
+ cur_preproc = yasm_preproc_create(cur_preproc_module, in_filename,
+ object->symtab, linemap, errwarns);
+
+ apply_preproc_builtins();
+ apply_preproc_standard_macros(cur_parser_module->stdmacs);
+ apply_preproc_standard_macros(cur_objfmt_module->stdmacs);
+ apply_preproc_saved_options();
+
+ /* Get initial x86 BITS setting from object format */
+ if (strcmp(cur_arch_module->keyword, "x86") == 0) {
+ yasm_arch_set_var(cur_arch, "mode_bits",
+ cur_objfmt_module->default_x86_mode_bits);
+ }
+
+ yasm_arch_set_var(cur_arch, "force_strict", force_strict);
+
+ /* Try to enable the map file via a map NASM directive. This is
+ * somewhat of a hack.
+ */
+ if (map_filename) {
+ const yasm_directive *dir = &cur_objfmt_module->directives[0];
+ matched = 0;
+ for (; dir && dir->name; dir++) {
+ if (yasm__strcasecmp(dir->name, "map") == 0 &&
+ yasm__strcasecmp(dir->parser, "nasm") == 0) {
+ yasm_valparamhead vps;
+ yasm_valparam *vp;
+ matched = 1;
+ yasm_vps_initialize(&vps);
+ vp = yasm_vp_create_string(NULL, yasm__xstrdup(map_filename));
+ yasm_vps_append(&vps, vp);
+ dir->handler(object, &vps, NULL, 0);
+ yasm_vps_delete(&vps);
+ }
+ }
+ if (!matched) {
+ print_error(
+ _("warning: object format `%s' does not support map files"),
+ cur_objfmt_module->keyword);
+ }
+ }
+
+ /* Parse! */
+ cur_parser_module->do_parse(object, cur_preproc, list_filename != NULL,
+ linemap, errwarns);
+
+ check_errors(errwarns, object, linemap);
+
+ /* Finalize parse */
+ yasm_object_finalize(object, errwarns);
+ check_errors(errwarns, object, linemap);
+
+ /* Optimize */
+ yasm_object_optimize(object, errwarns);
+ check_errors(errwarns, object, linemap);
+
+ /* generate any debugging information */
+ yasm_dbgfmt_generate(object, linemap, errwarns);
+ check_errors(errwarns, object, linemap);
+
+ /* open the object file for output (if not already opened by dbg objfmt) */
+ if (!obj && strcmp(cur_objfmt_module->keyword, "dbg") != 0) {
+ obj = open_file(obj_filename, "wb");
+ if (!obj) {
+ cleanup(object);
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Write the object file */
+ yasm_objfmt_output(object, obj?obj:stderr,
+ strcmp(cur_dbgfmt_module->keyword, "null"), errwarns);
+
+ /* Close object file */
+ if (obj)
+ fclose(obj);
+
+ /* If we had an error at this point, we also need to delete the output
+ * object file (to make sure it's not left newer than the source).
+ */
+ if (yasm_errwarns_num_errors(errwarns, warning_error) > 0)
+ remove(obj_filename);
+ check_errors(errwarns, object, linemap);
+
+ /* Open and write the list file */
+ if (list_filename) {
+ FILE *list = open_file(list_filename, "wt");
+ if (!list) {
+ cleanup(object);
+ return EXIT_FAILURE;
+ }
+ /* Initialize the list format */
+ cur_listfmt = yasm_listfmt_create(cur_listfmt_module, in_filename,
+ obj_filename);
+ yasm_listfmt_output(cur_listfmt, list, linemap, cur_arch);
+ fclose(list);
+ }
+
+ yasm_errwarns_output_all(errwarns, linemap, warning_error,
+ print_yasm_error, print_yasm_warning);
+
+ yasm_linemap_destroy(linemap);
+ yasm_errwarns_destroy(errwarns);
+ cleanup(object);
+ return EXIT_SUCCESS;
+}
+
+/* main function */
+/*@-globstate -unrecog@*/
+int
+main(int argc, char *argv[])
+{
+ size_t i;
+
+ errfile = stderr;
+
+#if defined(HAVE_SETLOCALE) && defined(HAVE_LC_MESSAGES)
+ setlocale(LC_MESSAGES, "");
+#endif
+#if defined(LOCALEDIR)
+ bindtextdomain(PACKAGE, LOCALEDIR);
+#endif
+ textdomain(PACKAGE);
+
+ /* Initialize errwarn handling */
+ yasm_internal_error_ = handle_yasm_int_error;
+ yasm_fatal = handle_yasm_fatal;
+ yasm_gettext_hook = handle_yasm_gettext;
+ yasm_errwarn_initialize();
+
+ /* Initialize BitVector (needed for intnum/floatnum). */
+ if (BitVector_Boot() != ErrCode_Ok) {
+ print_error(_("%s: could not initialize BitVector"), _("FATAL"));
+ return EXIT_FAILURE;
+ }
+
+ /* Initialize intnum and floatnum */
+ yasm_intnum_initialize();
+ yasm_floatnum_initialize();
+
+#ifdef CMAKE_BUILD
+ /* Load standard modules */
+#ifdef BUILD_SHARED_LIBS
+ if (!load_plugin("yasmstd")) {
+ print_error(_("%s: could not load standard modules"), _("FATAL"));
+ return EXIT_FAILURE;
+ }
+#else
+ yasm_init_plugin();
+#endif
+#endif
+
+ /* Initialize parameter storage */
+ STAILQ_INIT(&preproc_options);
+
+ if (parse_cmdline(argc, argv, options, NELEMS(options), print_error))
+ return EXIT_FAILURE;
+
+ switch (special_options) {
+ case SPECIAL_SHOW_HELP:
+ /* Does gettext calls internally */
+ help_msg(help_head, help_tail, options, NELEMS(options));
+ return EXIT_SUCCESS;
+ case SPECIAL_SHOW_VERSION:
+ for (i=0; i<NELEMS(version_msg); i++)
+ printf("%s\n", version_msg[i]);
+ return EXIT_SUCCESS;
+ case SPECIAL_SHOW_LICENSE:
+ for (i=0; i<NELEMS(license_msg); i++)
+ printf("%s\n", license_msg[i]);
+ return EXIT_SUCCESS;
+ case SPECIAL_LISTED:
+ /* Printed out earlier */
+ return EXIT_SUCCESS;
+ }
+
+ /* Open error file if specified. */
+ if (error_filename) {
+ errfile = open_file(error_filename, "wt");
+ if (!errfile)
+ return EXIT_FAILURE;
+ }
+
+#if defined(CMAKE_BUILD) && !defined(BUILD_SHARED_LIBS)
+ yasm_plugin_set_replace(replace_params, replace_size);
+#endif
+
+ /* If not already specified, default to bin as the object format. */
+ if (!cur_objfmt_module) {
+ if (!objfmt_keyword)
+ objfmt_keyword = yasm__xstrdup("bin");
+ cur_objfmt_module = yasm_load_objfmt(objfmt_keyword);
+ if (!cur_objfmt_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("object format"));
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Default to x86 as the architecture */
+ if (!cur_arch_module) {
+ cur_arch_module = yasm_load_arch("x86");
+ if (!cur_arch_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("architecture"));
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Check for arch help */
+ if (machine_name && strcmp(machine_name, "help") == 0) {
+ const yasm_arch_machine *m = cur_arch_module->machines;
+ printf(_("Available %s for %s `%s':\n"), _("machines"),
+ _("architecture"), cur_arch_module->keyword);
+ while (m->keyword && m->name) {
+ print_list_keyword_desc(m->name, m->keyword);
+ m++;
+ }
+ return EXIT_SUCCESS;
+ }
+
+ /* Default to NASM as the parser */
+ if (!cur_parser_module) {
+ cur_parser_module = yasm_load_parser("nasm");
+ if (!cur_parser_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("parser"));
+ cleanup(NULL);
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* If not already specified, default to the parser's default preproc. */
+ if (!cur_preproc_module) {
+ cur_preproc_module =
+ yasm_load_preproc(cur_parser_module->default_preproc_keyword);
+ if (!cur_preproc_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("preprocessor"));
+ cleanup(NULL);
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Determine input filename and open input file. */
+ if (!in_filename) {
+ print_error(_("No input files specified"));
+ return EXIT_FAILURE;
+ }
+
+ /* handle preproc-only case here */
+ if (preproc_only)
+ return do_preproc_only();
+
+ /* If list file enabled, make sure we have a list format loaded. */
+ if (list_filename) {
+ /* If not already specified, default to nasm as the list format. */
+ if (!cur_listfmt_module) {
+ cur_listfmt_module = yasm_load_listfmt("nasm");
+ if (!cur_listfmt_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("list format"));
+ return EXIT_FAILURE;
+ }
+ }
+ }
+
+ /* If not already specified, default to null as the debug format. */
+ if (!cur_dbgfmt_module) {
+ cur_dbgfmt_module = yasm_load_dbgfmt("null");
+ if (!cur_dbgfmt_module) {
+ print_error(_("%s: could not load default %s"), _("FATAL"),
+ _("debug format"));
+ return EXIT_FAILURE;
+ }
+ }
+
+ return do_assemble();
+}
+/*@=globstate =unrecog@*/
+
+/* Open the object file. Returns 0 on failure. */
+static FILE *
+open_file(const char *filename, const char *mode)
+{
+ FILE *f;
+
+ f = fopen(filename, mode);
+ if (!f)
+ print_error(_("could not open file `%s'"), filename);
+ return f;
+}
+
+static void
+check_errors(yasm_errwarns *errwarns, yasm_object *object,
+ yasm_linemap *linemap)
+{
+ if (yasm_errwarns_num_errors(errwarns, warning_error) > 0) {
+ yasm_errwarns_output_all(errwarns, linemap, warning_error,
+ print_yasm_error, print_yasm_warning);
+ yasm_linemap_destroy(linemap);
+ yasm_errwarns_destroy(errwarns);
+ cleanup(object);
+ exit(EXIT_FAILURE);
+ }
+}
+
+/* Define DO_FREE to 1 to enable deallocation of all data structures.
+ * Useful for detecting memory leaks, but slows down execution unnecessarily
+ * (as the OS will free everything we miss here).
+ */
+#define DO_FREE 1
+
+/* Cleans up all allocated structures. */
+static void
+cleanup(yasm_object *object)
+{
+ if (DO_FREE) {
+ if (cur_listfmt)
+ yasm_listfmt_destroy(cur_listfmt);
+ if (cur_preproc)
+ yasm_preproc_destroy(cur_preproc);
+ if (object)
+ yasm_object_destroy(object);
+
+ yasm_floatnum_cleanup();
+ yasm_intnum_cleanup();
+
+ yasm_errwarn_cleanup();
+
+ BitVector_Shutdown();
+ }
+
+ if (DO_FREE) {
+ if (in_filename)
+ yasm_xfree(in_filename);
+ if (obj_filename)
+ yasm_xfree(obj_filename);
+ if (list_filename)
+ yasm_xfree(list_filename);
+ if (map_filename)
+ yasm_xfree(map_filename);
+ if (machine_name)
+ yasm_xfree(machine_name);
+ if (objfmt_keyword)
+ yasm_xfree(objfmt_keyword);
+ }
+
+ if (errfile != stderr && errfile != stdout)
+ fclose(errfile);
+#if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
+ unload_plugins();
+#endif
+}
+
+/*
+ * Command line options handlers
+ */
+int
+not_an_option_handler(char *param)
+{
+ if (in_filename) {
+ print_error(
+ _("warning: can open only one input file, only the last file will be processed"));
+ yasm_xfree(in_filename);
+ }
+
+ in_filename = yasm__xstrdup(param);
+
+ return 0;
+}
+
+int
+other_option_handler(char *option)
+{
+ /* Accept, but ignore, -O and -Onnn, for compatibility with NASM. */
+ if (option[0] == '-' && option[1] == 'O') {
+ int n = 2;
+ for (;;) {
+ if (option[n] == '\0')
+ return 0;
+ if (!isdigit(option[n]))
+ return 1;
+ n++;
+ }
+ }
+ return 1;
+}
+
+static int
+opt_special_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
+{
+ if (special_options == 0)
+ special_options = extra;
+ return 0;
+}
+
+static int
+opt_arch_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ assert(param != NULL);
+ cur_arch_module = yasm_load_arch(param);
+ if (!cur_arch_module) {
+ if (!strcmp("help", param)) {
+ printf(_("Available yasm %s:\n"), _("architectures"));
+ yasm_list_arch(print_list_keyword_desc);
+ special_options = SPECIAL_LISTED;
+ return 0;
+ }
+ print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
+ _("architecture"), param);
+ exit(EXIT_FAILURE);
+ }
+ return 0;
+}
+
+static int
+opt_parser_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ assert(param != NULL);
+ cur_parser_module = yasm_load_parser(param);
+ if (!cur_parser_module) {
+ if (!strcmp("help", param)) {
+ printf(_("Available yasm %s:\n"), _("parsers"));
+ yasm_list_parser(print_list_keyword_desc);
+ special_options = SPECIAL_LISTED;
+ return 0;
+ }
+ print_error(_("%s: unrecognized %s `%s'"), _("FATAL"), _("parser"),
+ param);
+ exit(EXIT_FAILURE);
+ }
+ return 0;
+}
+
+static int
+opt_preproc_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ assert(param != NULL);
+ cur_preproc_module = yasm_load_preproc(param);
+ if (!cur_preproc_module) {
+ if (!strcmp("help", param)) {
+ printf(_("Available yasm %s:\n"), _("preprocessors"));
+ yasm_list_preproc(print_list_keyword_desc);
+ special_options = SPECIAL_LISTED;
+ return 0;
+ }
+ print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
+ _("preprocessor"), param);
+ exit(EXIT_FAILURE);
+ }
+ return 0;
+}
+
+static int
+opt_objfmt_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ size_t i;
+ assert(param != NULL);
+ cur_objfmt_module = yasm_load_objfmt(param);
+ if (!cur_objfmt_module) {
+ if (!strcmp("help", param)) {
+ printf(_("Available yasm %s:\n"), _("object formats"));
+ yasm_list_objfmt(print_list_keyword_desc);
+ special_options = SPECIAL_LISTED;
+ return 0;
+ }
+ print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
+ _("object format"), param);
+ exit(EXIT_FAILURE);
+ }
+ if (objfmt_keyword)
+ yasm_xfree(objfmt_keyword);
+ objfmt_keyword = yasm__xstrdup(param);
+ for (i=0; i<strlen(objfmt_keyword); i++)
+ objfmt_keyword[i] = tolower(objfmt_keyword[i]);
+ return 0;
+}
+
+static int
+opt_dbgfmt_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ assert(param != NULL);
+ cur_dbgfmt_module = yasm_load_dbgfmt(param);
+ if (!cur_dbgfmt_module) {
+ if (!strcmp("help", param)) {
+ printf(_("Available yasm %s:\n"), _("debug formats"));
+ yasm_list_dbgfmt(print_list_keyword_desc);
+ special_options = SPECIAL_LISTED;
+ return 0;
+ }
+ print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
+ _("debug format"), param);
+ exit(EXIT_FAILURE);
+ }
+ return 0;
+}
+
+static int
+opt_listfmt_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ assert(param != NULL);
+ cur_listfmt_module = yasm_load_listfmt(param);
+ if (!cur_listfmt_module) {
+ if (!strcmp("help", param)) {
+ printf(_("Available yasm %s:\n"), _("list formats"));
+ yasm_list_listfmt(print_list_keyword_desc);
+ special_options = SPECIAL_LISTED;
+ return 0;
+ }
+ print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
+ _("list format"), param);
+ exit(EXIT_FAILURE);
+ }
+ return 0;
+}
+
+static int
+opt_listfile_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ if (list_filename) {
+ print_error(
+ _("warning: can output to only one list file, last specified used"));
+ yasm_xfree(list_filename);
+ }
+
+ assert(param != NULL);
+ list_filename = yasm__xstrdup(param);
+
+ return 0;
+}
+
+static int
+opt_objfile_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ if (obj_filename) {
+ print_error(
+ _("warning: can output to only one object file, last specified used"));
+ yasm_xfree(obj_filename);
+ }
+
+ assert(param != NULL);
+ obj_filename = yasm__xstrdup(param);
+
+ return 0;
+}
+
+static int
+opt_mapfile_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ if (map_filename) {
+ print_error(
+ _("warning: can output to only one map file, last specified used"));
+ yasm_xfree(map_filename);
+ }
+
+ assert(param != NULL);
+ map_filename = yasm__xstrdup(param);
+
+ return 0;
+}
+
+static int
+opt_machine_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ if (machine_name)
+ yasm_xfree(machine_name);
+
+ assert(param != NULL);
+ machine_name = yasm__xstrdup(param);
+
+ return 0;
+}
+
+static int
+opt_strict_handler(/*@unused@*/ char *cmd,
+ /*@unused@*/ /*@null@*/ char *param,
+ /*@unused@*/ int extra)
+{
+ force_strict = 1;
+ return 0;
+}
+
+static int
+opt_warning_handler(char *cmd, /*@unused@*/ char *param, int extra)
+{
+ /* is it disabling the warning instead of enabling? */
+ void (*action)(yasm_warn_class wclass) = yasm_warn_enable;
+
+ if (extra == 1) {
+ /* -w, disable warnings */
+ yasm_warn_disable_all();
+ return 0;
+ }
+
+ /* skip past 'W' */
+ cmd++;
+
+ /* detect no- prefix to disable the warning */
+ if (cmd[0] == 'n' && cmd[1] == 'o' && cmd[2] == '-') {
+ action = yasm_warn_disable;
+ cmd += 3; /* skip past it to get to the warning name */
+ }
+
+ if (cmd[0] == '\0')
+ /* just -W or -Wno-, so definitely not valid */
+ return 1;
+ else if (strcmp(cmd, "error") == 0)
+ warning_error = (action == yasm_warn_enable);
+ else if (strcmp(cmd, "unrecognized-char") == 0)
+ action(YASM_WARN_UNREC_CHAR);
+ else if (strcmp(cmd, "orphan-labels") == 0)
+ action(YASM_WARN_ORPHAN_LABEL);
+ else if (strcmp(cmd, "uninit-contents") == 0)
+ action(YASM_WARN_UNINIT_CONTENTS);
+ else if (strcmp(cmd, "size-override") == 0)
+ action(YASM_WARN_SIZE_OVERRIDE);
+ else
+ return 1;
+
+ return 0;
+}
+
+static int
+opt_error_file(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ if (error_filename) {
+ print_error(
+ _("warning: can output to only one error file, last specified used"));
+ yasm_xfree(error_filename);
+ }
+
+ assert(param != NULL);
+ error_filename = yasm__xstrdup(param);
+
+ return 0;
+}
+
+static int
+opt_error_stdout(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
+ /*@unused@*/ int extra)
+{
+ /* Clear any specified error filename */
+ if (error_filename) {
+ yasm_xfree(error_filename);
+ error_filename = NULL;
+ }
+ errfile = stdout;
+ return 0;
+}
+
+static int
+preproc_only_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
+ /*@unused@*/ int extra)
+{
+ preproc_only = 1;
+ return 0;
+}
+
+static int
+opt_include_option(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ yasm_add_include_path(param);
+ return 0;
+}
+
+static int
+opt_preproc_option(/*@unused@*/ char *cmd, char *param, int extra)
+{
+ constcharparam *cp;
+ cp = yasm_xmalloc(sizeof(constcharparam));
+ cp->param = param;
+ cp->id = extra;
+ STAILQ_INSERT_TAIL(&preproc_options, cp, link);
+ return 0;
+}
+
+static int
+opt_ewmsg_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ if (yasm__strcasecmp(param, "gnu") == 0 ||
+ yasm__strcasecmp(param, "gcc") == 0) {
+ ewmsg_style = EWSTYLE_GNU;
+ } else if (yasm__strcasecmp(param, "vc") == 0) {
+ ewmsg_style = EWSTYLE_VC;
+ } else
+ print_error(_("warning: unrecognized message style `%s'"), param);
+
+ return 0;
+}
+
+static int
+opt_makedep_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
+ /*@unused@*/ int extra)
+{
+ /* Also set preproc_only to 1, we don't want to generate code */
+ preproc_only = 1;
+ generate_make_dependencies = 1;
+
+ return 0;
+}
+
+static int
+opt_prefix_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ if (global_prefix)
+ yasm_xfree(global_prefix);
+
+ assert(param != NULL);
+ global_prefix = yasm__xstrdup(param);
+
+ return 0;
+}
+
+static void
+opt_free_replace(void)
+{
+ yasm_xfree(replace_params);
+ replace_capacity = 0;
+ replace_size = 0;
+}
+
+static int
+opt_replace_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ if (replace_capacity == 0) {
+ atexit(opt_free_replace);
+ }
+ if (replace_size == replace_capacity) {
+ replace_capacity += 10;
+ replace_params = yasm_xrealloc(replace_params, replace_capacity);
+ }
+
+ assert(param != NULL);
+ replace_params[replace_size] = yasm__xstrdup(param);
+ ++replace_size;
+
+ return 0;
+}
+
+static int
+opt_suffix_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
+{
+ if (global_suffix)
+ yasm_xfree(global_suffix);
+
+ assert(param != NULL);
+ global_suffix = yasm__xstrdup(param);
+
+ return 0;
+}
+
+#if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
+static int
+opt_plugin_handler(/*@unused@*/ char *cmd, char *param,
+ /*@unused@*/ int extra)
+{
+ if (!load_plugin(param))
+ print_error(_("warning: could not load plugin `%s'"), param);
+ return 0;
+}
+#endif
+
+static void
+apply_preproc_builtins()
+{
+ char *predef;
+
+ /* Define standard YASM assembly-time macro constants */
+ predef = yasm_xmalloc(strlen("__YASM_OBJFMT__=")
+ + strlen(objfmt_keyword) + 1);
+ strcpy(predef, "__YASM_OBJFMT__=");
+ strcat(predef, objfmt_keyword);
+ yasm_preproc_define_builtin(cur_preproc, predef);
+ yasm_xfree(predef);
+}
+
+static void
+apply_preproc_standard_macros(const yasm_stdmac *stdmacs)
+{
+ int i, matched;
+
+ if (!stdmacs)
+ return;
+
+ matched = -1;
+ for (i=0; stdmacs[i].parser; i++)
+ if (yasm__strcasecmp(stdmacs[i].parser,
+ cur_parser_module->keyword) == 0 &&
+ yasm__strcasecmp(stdmacs[i].preproc,
+ cur_preproc_module->keyword) == 0)
+ matched = i;
+ if (matched >= 0 && stdmacs[matched].macros)
+ yasm_preproc_add_standard(cur_preproc, stdmacs[matched].macros);
+}
+
+static void
+apply_preproc_saved_options()
+{
+ constcharparam *cp, *cpnext;
+
+ void (*funcs[3])(yasm_preproc *, const char *);
+ funcs[0] = cur_preproc_module->add_include_file;
+ funcs[1] = cur_preproc_module->predefine_macro;
+ funcs[2] = cur_preproc_module->undefine_macro;
+
+ STAILQ_FOREACH(cp, &preproc_options, link) {
+ if (0 <= cp->id && cp->id < 3 && funcs[cp->id])
+ funcs[cp->id](cur_preproc, cp->param);
+ }
+
+ cp = STAILQ_FIRST(&preproc_options);
+ while (cp != NULL) {
+ cpnext = STAILQ_NEXT(cp, link);
+ yasm_xfree(cp);
+ cp = cpnext;
+ }
+ STAILQ_INIT(&preproc_options);
+}
+
+/* Replace extension on a filename (or append one if none is present).
+ * If output filename would be identical to input (same extension out as in),
+ * returns (copy of) def.
+ * A NULL ext means the trailing '.' should NOT be included, whereas a "" ext
+ * means the trailing '.' should be included.
+ */
+static char *
+replace_extension(const char *orig, /*@null@*/ const char *ext,
+ const char *def)
+{
+ char *out, *outext;
+ size_t deflen, outlen;
+
+ /* allocate enough space for full existing name + extension */
+ outlen = strlen(orig) + 2;
+ if (ext)
+ outlen += strlen(ext) + 1;
+ deflen = strlen(def) + 1;
+ if (outlen < deflen)
+ outlen = deflen;
+ out = yasm_xmalloc(outlen);
+
+ strcpy(out, orig);
+ outext = strrchr(out, '.');
+ if (outext) {
+ /* Existing extension: make sure it's not the same as the replacement
+ * (as we don't want to overwrite the source file).
+ */
+ outext++; /* advance past '.' */
+ if (ext && strcmp(outext, ext) == 0) {
+ outext = NULL; /* indicate default should be used */
+ print_error(
+ _("file name already ends in `.%s': output will be in `%s'"),
+ ext, def);
+ }
+ } else {
+ /* No extension: make sure the output extension is not empty
+ * (again, we don't want to overwrite the source file).
+ */
+ if (!ext)
+ print_error(
+ _("file name already has no extension: output will be in `%s'"),
+ def);
+ else {
+ outext = strrchr(out, '\0'); /* point to end of the string */
+ *outext++ = '.'; /* append '.' */
+ }
+ }
+
+ /* replace extension or use default name */
+ if (outext) {
+ if (!ext) {
+ /* Back up and replace '.' with string terminator */
+ outext--;
+ *outext = '\0';
+ } else
+ strcpy(outext, ext);
+ } else
+ strcpy(out, def);
+
+ return out;
+}
+
+void
+print_list_keyword_desc(const char *name, const char *keyword)
+{
+ printf("%4s%-12s%s\n", "", keyword, name);
+}
+
+static void
+print_error(const char *fmt, ...)
+{
+ va_list va;
+ fprintf(errfile, "yasm: ");
+ va_start(va, fmt);
+ vfprintf(errfile, fmt, va);
+ va_end(va);
+ fputc('\n', errfile);
+}
+
+static /*@exits@*/ void
+handle_yasm_int_error(const char *file, unsigned int line, const char *message)
+{
+ fprintf(stderr, _("INTERNAL ERROR at %s, line %u: %s\n"), file, line,
+ gettext(message));
+#ifdef HAVE_ABORT
+ abort();
+#else
+ exit(EXIT_FAILURE);
+#endif
+}
+
+static /*@exits@*/ void
+handle_yasm_fatal(const char *fmt, va_list va)
+{
+ fprintf(errfile, "yasm: %s: ", _("FATAL"));
+ vfprintf(errfile, gettext(fmt), va);
+ fputc('\n', errfile);
+ exit(EXIT_FAILURE);
+}
+
+static const char *
+handle_yasm_gettext(const char *msgid)
+{
+ return gettext(msgid);
+}
+
+static const char *fmt[2] = {
+ "%s:%lu: %s%s\n", /* GNU */
+ "%s(%lu) : %s%s\n" /* VC */
+};
+
+static const char *fmt_noline[2] = {
+ "%s: %s%s\n", /* GNU */
+ "%s : %s%s\n" /* VC */
+};
+
+static void
+print_yasm_error(const char *filename, unsigned long line, const char *msg,
+ const char *xref_fn, unsigned long xref_line,
+ const char *xref_msg)
+{
+ if (line)
+ fprintf(errfile, fmt[ewmsg_style], filename, line, _("error: "), msg);
+ else
+ fprintf(errfile, fmt_noline[ewmsg_style], filename, _("error: "), msg);
+
+ if (xref_fn && xref_msg) {
+ if (xref_line)
+ fprintf(errfile, fmt[ewmsg_style], xref_fn, xref_line, _("error: "),
+ xref_msg);
+ else
+ fprintf(errfile, fmt_noline[ewmsg_style], xref_fn, _("error: "),
+ xref_msg);
+ }
+}
+
+static void
+print_yasm_warning(const char *filename, unsigned long line, const char *msg)
+{
+ if (line)
+ fprintf(errfile, fmt[ewmsg_style], filename, line, _("warning: "),
+ msg);
+ else
+ fprintf(errfile, fmt_noline[ewmsg_style], filename, _("warning: "),
+ msg);
+}
diff --git a/contrib/tools/yasm/libyasm-stdint.h b/contrib/tools/yasm/libyasm-stdint.h
new file mode 100644
index 0000000000..a2a08a9417
--- /dev/null
+++ b/contrib/tools/yasm/libyasm-stdint.h
@@ -0,0 +1,46 @@
+#ifndef YASM_STDINT_H
+#define YASM_STDINT_H
+
+#define HAVE_STDINT_H
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#elif defined(_MSC_VER)
+
+#ifndef _UINTPTR_T_DEFINED
+#ifdef _WIN64
+#include <vadefs.h>
+#else
+typedef unsigned long uintptr_t;
+#endif
+#define _UINTPTR_T_DEFINED
+#endif
+
+#else
+typedef unsigned long uintptr_t;
+#endif
+
+#ifndef BUILD_SHARED_LIBS
+/* #undef BUILD_SHARED_LIBS */
+#define BUILD_SHARED_LIBS_UNDEF
+#endif
+
+#ifndef YASM_LIB_DECL
+# if defined(BUILD_SHARED_LIBS) && defined(_MSC_VER)
+# ifdef YASM_LIB_SOURCE
+# define YASM_LIB_DECL __declspec(dllexport)
+# else
+# define YASM_LIB_DECL __declspec(dllimport)
+# endif
+# else
+# define YASM_LIB_DECL
+# endif
+#endif
+
+#undef HAVE_STDINT_H
+#ifdef BUILD_SHARED_LIBS_UNDEF
+#undef BUILD_SHARED_LIBS
+#undef BUILD_SHARED_LIBS_UNDEF
+#endif
+
+#endif
diff --git a/contrib/tools/yasm/libyasm.h b/contrib/tools/yasm/libyasm.h
new file mode 100644
index 0000000000..f52c133b39
--- /dev/null
+++ b/contrib/tools/yasm/libyasm.h
@@ -0,0 +1,75 @@
+/**
+ * \file libyasm.h
+ * \brief YASM library primary header file.
+ *
+ * \license
+ * Copyright (C) 2003-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_LIB_H
+#define YASM_LIB_H
+
+#ifdef YASM_PYXELATOR
+typedef struct __FILE FILE;
+typedef struct __va_list va_list;
+typedef unsigned long size_t;
+typedef unsigned long uintptr_t;
+#else
+#include <stdio.h>
+#include <stdarg.h>
+#include <libyasm-stdint.h>
+#endif
+
+#include <libyasm/compat-queue.h>
+
+#include <libyasm/coretype.h>
+#include <libyasm/valparam.h>
+
+#include <libyasm/linemap.h>
+
+#include <libyasm/errwarn.h>
+#include <libyasm/intnum.h>
+#include <libyasm/floatnum.h>
+#include <libyasm/expr.h>
+#include <libyasm/value.h>
+#include <libyasm/symrec.h>
+
+#include <libyasm/bytecode.h>
+#include <libyasm/section.h>
+#include <libyasm/insn.h>
+
+#include <libyasm/arch.h>
+#include <libyasm/dbgfmt.h>
+#include <libyasm/objfmt.h>
+#include <libyasm/listfmt.h>
+#include <libyasm/parser.h>
+#include <libyasm/preproc.h>
+
+#include <libyasm/file.h>
+#include <libyasm/module.h>
+
+#include <libyasm/hamt.h>
+#include <libyasm/md5.h>
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/arch.h b/contrib/tools/yasm/libyasm/arch.h
new file mode 100644
index 0000000000..3da9f9fca3
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/arch.h
@@ -0,0 +1,495 @@
+/**
+ * \file libyasm/arch.h
+ * \brief YASM architecture interface.
+ *
+ * \license
+ * Copyright (C) 2002-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_ARCH_H
+#define YASM_ARCH_H
+
+/** Errors that may be returned by yasm_arch_module::create(). */
+typedef enum yasm_arch_create_error {
+ YASM_ARCH_CREATE_OK = 0, /**< No error. */
+ YASM_ARCH_CREATE_BAD_MACHINE, /**< Unrecognized machine name. */
+ 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_insnprefix {
+ 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_regtmod {
+ 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;
+
+#ifndef YASM_DOXYGEN
+/** Base #yasm_arch structure. Must be present as the first element in any
+ * #yasm_arch implementation.
+ */
+typedef struct yasm_arch_base {
+ /** #yasm_arch_module implementation for this architecture. */
+ const struct yasm_arch_module *module;
+} yasm_arch_base;
+#endif
+
+/** YASM machine subtype. A number of different machine types may be
+ * associated with a single architecture. These may be specific CPU's, but
+ * the ABI used to interface with the architecture should be the primary
+ * differentiator between machines. Some object formats (ELF) use the machine
+ * to determine parameters within the generated output.
+ */
+typedef struct yasm_arch_machine {
+ /** One-line description of the machine. */
+ const char *name;
+
+ /** Keyword used to select machine. */
+ const char *keyword;
+} yasm_arch_machine;
+
+/** YASM architecture module interface.
+ * \note All "data" in parser-related functions (yasm_arch_parse_*) needs to
+ * start the parse initialized to 0 to make it okay for a parser-related
+ * function to use/check previously stored data to see if it's been
+ * called before on the same piece of data.
+ */
+typedef struct yasm_arch_module {
+ /** One-line description of the architecture.
+ * Call yasm_arch_name() to get the name of a particular #yasm_arch.
+ */
+ const char *name;
+
+ /** Keyword used to select architecture.
+ * Call yasm_arch_keyword() to get the keyword of a particular #yasm_arch.
+ */
+ const char *keyword;
+
+ /** NULL-terminated list of directives. NULL if none. */
+ /*@null@*/ const yasm_directive *directives;
+
+ /** Create architecture.
+ * Module-level implementation of yasm_arch_create().
+ * Call yasm_arch_create() instead of calling this function.
+ */
+ /*@only@*/ yasm_arch * (*create) (const char *machine, const char *parser,
+ /*@out@*/ yasm_arch_create_error *error);
+
+ /** Module-level implementation of yasm_arch_destroy().
+ * Call yasm_arch_destroy() instead of calling this function.
+ */
+ void (*destroy) (/*@only@*/ yasm_arch *arch);
+
+ /** Module-level implementation of yasm_arch_get_machine().
+ * Call yasm_arch_get_machine() instead of calling this function.
+ */
+ const char * (*get_machine) (const yasm_arch *arch);
+
+ /** Module-level implementation of yasm_arch_get_address_size().
+ * Call yasm_arch_get_address_size() instead of calling this function.
+ */
+ unsigned int (*get_address_size) (const yasm_arch *arch);
+
+ /** Module-level implementation of yasm_arch_set_var().
+ * Call yasm_arch_set_var() instead of calling this function.
+ */
+ int (*set_var) (yasm_arch *arch, const char *var, unsigned long val);
+
+ /** Module-level implementation of yasm_arch_parse_check_insnprefix().
+ * Call yasm_arch_parse_check_insnprefix() instead of calling this function.
+ */
+ yasm_arch_insnprefix (*parse_check_insnprefix)
+ (yasm_arch *arch, const char *id, size_t id_len, unsigned long line,
+ /*@out@*/ /*@only@*/ yasm_bytecode **bc, /*@out@*/ uintptr_t *prefix);
+
+ /** Module-level implementation of yasm_arch_parse_check_regtmod().
+ * Call yasm_arch_parse_check_regtmod() instead of calling this function.
+ */
+ yasm_arch_regtmod (*parse_check_regtmod)
+ (yasm_arch *arch, const char *id, size_t id_len,
+ /*@out@*/ uintptr_t *data);
+
+ /** Module-level implementation of yasm_arch_get_fill().
+ * Call yasm_arch_get_fill() instead of calling this function.
+ */
+ const unsigned char ** (*get_fill) (const yasm_arch *arch);
+
+ /** Module-level implementation of yasm_arch_floatnum_tobytes().
+ * Call yasm_arch_floatnum_tobytes() instead of calling this function.
+ */
+ int (*floatnum_tobytes) (yasm_arch *arch, const yasm_floatnum *flt,
+ unsigned char *buf, size_t destsize,
+ size_t valsize, size_t shift, int warn);
+
+ /** Module-level implementation of yasm_arch_intnum_tobytes().
+ * Call yasm_arch_intnum_tobytes() instead of calling this function.
+ */
+ int (*intnum_tobytes) (yasm_arch *arch, const yasm_intnum *intn,
+ unsigned char *buf, size_t destsize, size_t valsize,
+ int shift, const yasm_bytecode *bc,
+ int warn);
+
+ /** Module-level implementation of yasm_arch_get_reg_size().
+ * Call yasm_arch_get_reg_size() instead of calling this function.
+ */
+ unsigned int (*get_reg_size) (yasm_arch *arch, uintptr_t reg);
+
+ /** Module-level implementation of yasm_arch_reggroup_get_reg().
+ * Call yasm_arch_reggroup_get_reg() instead of calling this function.
+ */
+ uintptr_t (*reggroup_get_reg) (yasm_arch *arch, uintptr_t reggroup,
+ unsigned long regindex);
+
+ /** Module-level implementation of yasm_arch_reg_print().
+ * Call yasm_arch_reg_print() instead of calling this function.
+ */
+ void (*reg_print) (yasm_arch *arch, uintptr_t reg, FILE *f);
+
+ /** Module-level implementation of yasm_arch_segreg_print().
+ * Call yasm_arch_segreg_print() instead of calling this function.
+ */
+ void (*segreg_print) (yasm_arch *arch, uintptr_t segreg, FILE *f);
+
+ /** Module-level implementation of yasm_arch_ea_create().
+ * Call yasm_arch_ea_create() instead of calling this function.
+ */
+ yasm_effaddr * (*ea_create) (yasm_arch *arch, /*@keep@*/ yasm_expr *e);
+
+ /** Module-level implementation of yasm_arch_ea_destroy().
+ * Call yasm_arch_ea_destroy() instead of calling this function.
+ */
+ void (*ea_destroy) (/*@only@*/ yasm_effaddr *ea);
+
+ /** Module-level implementation of yasm_arch_ea_print().
+ * Call yasm_arch_ea_print() instead of calling this function.
+ */
+ void (*ea_print) (const yasm_effaddr *ea, FILE *f, int indent_level);
+
+ /** Module-level implementation of yasm_arch_create_empty_insn().
+ * Call yasm_arch_create_empty_insn() instead of calling this function.
+ */
+ /*@only@*/ yasm_bytecode * (*create_empty_insn) (yasm_arch *arch,
+ unsigned long line);
+
+ /** NULL-terminated list of machines for this architecture.
+ * Call yasm_arch_get_machine() to get the active machine of a particular
+ * #yasm_arch.
+ */
+ const yasm_arch_machine *machines;
+
+ /** Default machine keyword.
+ * Call yasm_arch_get_machine() to get the active machine of a particular
+ * #yasm_arch.
+ */
+ const char *default_machine_keyword;
+
+ /** Canonical "word" size in bits.
+ * Call yasm_arch_wordsize() to get the word size of a particular
+ * #yasm_arch.
+ */
+ unsigned int wordsize;
+
+ /** Worst case minimum instruction length in bytes.
+ * Call yasm_arch_min_insn_len() to get the minimum instruction length of
+ * a particular #yasm_arch.
+ */
+ unsigned int min_insn_len;
+} yasm_arch_module;
+
+/** Get the one-line description of an architecture.
+ * \param arch architecture
+ * \return One-line description of architecture.
+ */
+const char *yasm_arch_name(const yasm_arch *arch);
+
+/** Get the keyword used to select an architecture.
+ * \param arch architecture
+ * \return Architecture keyword.
+ */
+const char *yasm_arch_keyword(const yasm_arch *arch);
+
+/** Get the word size of an architecture.
+ * \param arch architecture
+ * \return Word size (in bits).
+ */
+unsigned int yasm_arch_wordsize(const yasm_arch *arch);
+
+/** Get the minimum instruction length of an architecture.
+ * \param arch architecture
+ * \return Minimum instruction length (in bytes).
+ */
+unsigned int yasm_arch_min_insn_len(const yasm_arch *arch);
+
+/** Create architecture.
+ * \param module architecture module
+ * \param machine keyword of machine in use (must be one listed in
+ * #yasm_arch_module.machines)
+ * \param parser keyword of parser in use
+ * \param error error return value
+ * \return NULL on error (error returned in error parameter), otherwise new
+ * architecture.
+ */
+/*@only@*/ yasm_arch *yasm_arch_create(const yasm_arch_module *module,
+ const char *machine, const char *parser,
+ /*@out@*/ yasm_arch_create_error *error);
+
+/** Clean up, free any architecture-allocated memory.
+ * \param arch architecture
+ */
+void yasm_arch_destroy(/*@only@*/ yasm_arch *arch);
+
+/** Get architecture's active machine name.
+ * \param arch architecture
+ * \return Active machine name.
+ */
+const char *yasm_arch_get_machine(const yasm_arch *arch);
+
+/** Get architecture's active address size, in bits.
+ * \param arch architecture
+ * \return Active address size (in bits).
+ */
+unsigned int yasm_arch_get_address_size(const yasm_arch *arch);
+
+/** Set any arch-specific variables. For example, "mode_bits" in x86.
+ * \param arch architecture
+ * \param var variable name
+ * \param val value to set
+ * \return Zero on success, non-zero on failure (variable does not exist).
+ */
+int yasm_arch_set_var(yasm_arch *arch, const char *var, unsigned long val);
+
+/** Check an generic identifier to see if it matches architecture specific
+ * 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 id identifier as in the input file
+ * \param id_len length of id string
+ * \param line virtual line
+ * \param bc for instructions, yasm_insn-based bytecode is returned
+ * (and NULL otherwise)
+ * \param prefix for prefixes, yasm_arch-specific value is returned
+ * (and 0 otherwise)
+ * \return Identifier type (#YASM_ARCH_NOTINSNPREFIX if unrecognized)
+ */
+yasm_arch_insnprefix yasm_arch_parse_check_insnprefix
+ (yasm_arch *arch, const char *id, size_t id_len, unsigned long line,
+ /*@out@*/ /*@only@*/ yasm_bytecode **bc, /*@out@*/ uintptr_t *prefix);
+
+/** Check an generic identifier to see if it matches architecture specific
+ * 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 id identifier as in the input file
+ * \param id_len length of id string
+ * \param data extra identification information (yasm_arch-specific)
+ * [output]
+ * \return Identifier type (#YASM_ARCH_NOTREGTMOD if unrecognized)
+ */
+yasm_arch_regtmod yasm_arch_parse_check_regtmod
+ (yasm_arch *arch, const char *id, size_t id_len,
+ /*@out@*/ uintptr_t *data);
+
+/** Get NOP fill patterns for 1-15 bytes of fill.
+ * \param arch architecture
+ * \return 16-entry array of arrays; [0] is unused, [1] - [15] point to arrays
+ * of 1-15 bytes (respectively) in length.
+ */
+const unsigned char **yasm_arch_get_fill(const yasm_arch *arch);
+
+/** Output #yasm_floatnum to buffer. Puts the value into the least
+ * significant bits of the destination, or may be shifted into more
+ * significant bits by the shift parameter. The destination bits are
+ * cleared before being set.
+ * Architecture-specific because of endianness.
+ * \param arch architecture
+ * \param flt floating point value
+ * \param buf buffer to write into
+ * \param destsize destination size (in bytes)
+ * \param valsize size (in bits)
+ * \param shift left shift (in bits)
+ * \param warn enables standard overflow/underflow warnings
+ * \return Nonzero on error.
+ */
+int yasm_arch_floatnum_tobytes(yasm_arch *arch, const yasm_floatnum *flt,
+ unsigned char *buf, size_t destsize,
+ size_t valsize, size_t shift, int warn);
+
+/** Output #yasm_intnum to buffer. Puts the value into the least
+ * significant bits of the destination, or may be shifted into more
+ * significant bits by the shift parameter. The destination bits are
+ * cleared before being set.
+ * \param arch architecture
+ * \param intn integer value
+ * \param buf buffer to write into
+ * \param destsize destination size (in bytes)
+ * \param valsize size (in bits)
+ * \param shift left shift (in bits); may be negative to specify right
+ * shift (standard warnings include truncation to boundary)
+ * \param bc bytecode being output ("parent" of value)
+ * \param warn enables standard warnings (value doesn't fit into
+ * valsize bits)
+ * \return Nonzero on error.
+ */
+int yasm_arch_intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn,
+ unsigned char *buf, size_t destsize,
+ size_t valsize, int shift,
+ const yasm_bytecode *bc, int warn);
+
+/** Get the equivalent size of a register in bits.
+ * \param arch architecture
+ * \param reg register
+ * \return 0 if there is no suitable equivalent size, otherwise the size.
+ */
+unsigned int yasm_arch_get_reg_size(yasm_arch *arch, uintptr_t reg);
+
+/** Get a specific register of a register group, based on the register
+ * group and the index within the group.
+ * \param arch architecture
+ * \param reggroup register group
+ * \param regindex register index
+ * \return 0 if regindex is not valid for that register group, otherwise the
+ * specific register value.
+ */
+uintptr_t yasm_arch_reggroup_get_reg(yasm_arch *arch, uintptr_t reggroup,
+ unsigned long regindex);
+
+/** Print a register. For debugging purposes.
+ * \param arch architecture
+ * \param reg register
+ * \param f file
+ */
+void yasm_arch_reg_print(yasm_arch *arch, uintptr_t reg, FILE *f);
+
+/** Print a segment register. For debugging purposes.
+ * \param arch architecture
+ * \param segreg segment register
+ * \param f file
+ */
+void yasm_arch_segreg_print(yasm_arch *arch, uintptr_t segreg, FILE *f);
+
+/** Create an effective address from an expression.
+ * \param arch architecture
+ * \param e expression (kept, do not delete)
+ * \return Newly allocated effective address.
+ */
+yasm_effaddr *yasm_arch_ea_create(yasm_arch *arch, /*@keep@*/ yasm_expr *e);
+
+/** Delete (free allocated memory for) an effective address.
+ * \param arch architecture
+ * \param ea effective address (only pointer to it).
+ */
+void yasm_arch_ea_destroy(yasm_arch *arch, /*@only@*/ yasm_effaddr *ea);
+
+/** Print an effective address. For debugging purposes.
+ * \param arch architecture
+ * \param ea effective address
+ * \param f file
+ * \param indent_level indentation level
+ */
+void yasm_arch_ea_print(const yasm_arch *arch, const yasm_effaddr *ea,
+ FILE *f, int indent_level);
+
+/** Create a bytecode that represents a single empty (0 length) instruction.
+ * This is used for handling solitary prefixes.
+ * \param arch architecture
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ */
+/*@only@*/ yasm_bytecode *yasm_arch_create_empty_insn(yasm_arch *arch,
+ unsigned long line);
+
+#ifndef YASM_DOXYGEN
+
+/* Inline macro implementations for arch functions */
+
+#define yasm_arch_name(arch) \
+ (((yasm_arch_base *)arch)->module->name)
+#define yasm_arch_keyword(arch) \
+ (((yasm_arch_base *)arch)->module->keyword)
+#define yasm_arch_wordsize(arch) \
+ (((yasm_arch_base *)arch)->module->wordsize)
+#define yasm_arch_min_insn_len(arch) \
+ (((yasm_arch_base *)arch)->module->min_insn_len)
+
+#define yasm_arch_create(module, machine, parser, error) \
+ module->create(machine, parser, error)
+
+#define yasm_arch_destroy(arch) \
+ ((yasm_arch_base *)arch)->module->destroy(arch)
+#define yasm_arch_get_machine(arch) \
+ ((yasm_arch_base *)arch)->module->get_machine(arch)
+#define yasm_arch_get_address_size(arch) \
+ ((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_check_insnprefix(arch, id, id_len, line, bc, prefix) \
+ ((yasm_arch_base *)arch)->module->parse_check_insnprefix \
+ (arch, id, id_len, line, bc, prefix)
+#define yasm_arch_parse_check_regtmod(arch, id, id_len, data) \
+ ((yasm_arch_base *)arch)->module->parse_check_regtmod \
+ (arch, id, id_len, data)
+#define yasm_arch_get_fill(arch) \
+ ((yasm_arch_base *)arch)->module->get_fill(arch)
+#define yasm_arch_floatnum_tobytes(arch, flt, buf, destsize, valsize, shift, \
+ warn) \
+ ((yasm_arch_base *)arch)->module->floatnum_tobytes \
+ (arch, flt, buf, destsize, valsize, shift, warn)
+#define yasm_arch_intnum_tobytes(arch, intn, buf, destsize, valsize, shift, \
+ bc, warn) \
+ ((yasm_arch_base *)arch)->module->intnum_tobytes \
+ (arch, intn, buf, destsize, valsize, shift, bc, warn)
+#define yasm_arch_get_reg_size(arch, reg) \
+ ((yasm_arch_base *)arch)->module->get_reg_size(arch, reg)
+#define yasm_arch_reggroup_get_reg(arch, regg, regi) \
+ ((yasm_arch_base *)arch)->module->reggroup_get_reg(arch, regg, regi)
+#define yasm_arch_reg_print(arch, reg, f) \
+ ((yasm_arch_base *)arch)->module->reg_print(arch, reg, f)
+#define yasm_arch_segreg_print(arch, segreg, f) \
+ ((yasm_arch_base *)arch)->module->segreg_print(arch, segreg, f)
+#define yasm_arch_ea_create(arch, e) \
+ ((yasm_arch_base *)arch)->module->ea_create(arch, e)
+#define yasm_arch_ea_destroy(arch, ea) \
+ ((yasm_arch_base *)arch)->module->ea_destroy(ea)
+#define yasm_arch_ea_print(arch, ea, f, i) \
+ ((yasm_arch_base *)arch)->module->ea_print(ea, f, i)
+#define yasm_arch_create_empty_insn(arch, line) \
+ ((yasm_arch_base *)arch)->module->create_empty_insn(arch, line)
+
+#endif
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/assocdat.c b/contrib/tools/yasm/libyasm/assocdat.c
new file mode 100644
index 0000000000..560093685e
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/assocdat.c
@@ -0,0 +1,138 @@
+/*
+ * YASM associated data storage (libyasm internal use)
+ *
+ * Copyright (C) 2003-2007 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 "util.h"
+
+#include "coretype.h"
+#include "assocdat.h"
+
+
+typedef struct assoc_data_item {
+ const yasm_assoc_data_callback *callback;
+ void *data;
+} assoc_data_item;
+
+struct yasm__assoc_data {
+ assoc_data_item *vector;
+ size_t size;
+ size_t alloc;
+};
+
+
+yasm__assoc_data *
+yasm__assoc_data_create(void)
+{
+ yasm__assoc_data *assoc_data = yasm_xmalloc(sizeof(yasm__assoc_data));
+
+ assoc_data->size = 0;
+ assoc_data->alloc = 2;
+ assoc_data->vector = yasm_xmalloc(assoc_data->alloc *
+ sizeof(assoc_data_item));
+
+ return assoc_data;
+}
+
+void *
+yasm__assoc_data_get(yasm__assoc_data *assoc_data,
+ const yasm_assoc_data_callback *callback)
+{
+ size_t i;
+
+ if (!assoc_data)
+ return NULL;
+
+ for (i=0; i<assoc_data->size; i++) {
+ if (assoc_data->vector[i].callback == callback)
+ return assoc_data->vector[i].data;
+ }
+ return NULL;
+}
+
+yasm__assoc_data *
+yasm__assoc_data_add(yasm__assoc_data *assoc_data_arg,
+ const yasm_assoc_data_callback *callback, void *data)
+{
+ yasm__assoc_data *assoc_data;
+ assoc_data_item *item = NULL;
+ size_t i;
+
+ /* Create a new assoc_data if necessary */
+ if (assoc_data_arg)
+ assoc_data = assoc_data_arg;
+ else
+ assoc_data = yasm__assoc_data_create();
+
+ /* See if there's already assocated data for this callback */
+ for (i=0; i<assoc_data->size; i++) {
+ if (assoc_data->vector[i].callback == callback) {
+ item = &assoc_data->vector[i];
+ break;
+ }
+ }
+
+ /* No? Then append a new one */
+ if (!item) {
+ assoc_data->size++;
+ if (assoc_data->size > assoc_data->alloc) {
+ assoc_data->alloc *= 2;
+ assoc_data->vector =
+ yasm_xrealloc(assoc_data->vector,
+ assoc_data->alloc * sizeof(assoc_data_item));
+ }
+ item = &assoc_data->vector[assoc_data->size-1];
+ item->callback = callback;
+ item->data = NULL;
+ }
+
+ /* Delete existing data (if any) */
+ if (item->data && item->data != data)
+ item->callback->destroy(item->data);
+
+ item->data = data;
+
+ return assoc_data;
+}
+
+void
+yasm__assoc_data_destroy(yasm__assoc_data *assoc_data)
+{
+ size_t i;
+
+ if (!assoc_data)
+ return;
+
+ for (i=0; i<assoc_data->size; i++)
+ assoc_data->vector[i].callback->destroy(assoc_data->vector[i].data);
+ yasm_xfree(assoc_data->vector);
+ yasm_xfree(assoc_data);
+}
+
+void
+yasm__assoc_data_print(const yasm__assoc_data *assoc_data, FILE *f,
+ int indent_level)
+{
+ /*TODO*/
+}
diff --git a/contrib/tools/yasm/libyasm/assocdat.h b/contrib/tools/yasm/libyasm/assocdat.h
new file mode 100644
index 0000000000..cf42386775
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/assocdat.h
@@ -0,0 +1,76 @@
+/**
+ * \file assocdat.h
+ * \brief YASM associated data storage (libyasm internal use)
+ *
+ * \license
+ * Copyright (C) 2003-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_ASSOCDAT_H
+#define YASM_ASSOCDAT_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Associated data container. */
+typedef struct yasm__assoc_data yasm__assoc_data;
+
+/** Create an associated data container. */
+YASM_LIB_DECL
+/*@only@*/ yasm__assoc_data *yasm__assoc_data_create(void);
+
+/** Get associated data for a data callback.
+ * \param assoc_data container of associated data
+ * \param callback callback used when adding data
+ * \return Associated data (NULL if none).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ void *yasm__assoc_data_get
+ (/*@null@*/ yasm__assoc_data *assoc_data,
+ const yasm_assoc_data_callback *callback);
+
+/** Add associated data to a associated data container.
+ * \attention Deletes any existing associated data for that data callback.
+ * \param assoc_data container of associated data
+ * \param callback callback
+ * \param data data to associate
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm__assoc_data *yasm__assoc_data_add
+ (/*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data,
+ const yasm_assoc_data_callback *callback,
+ /*@only@*/ /*@null@*/ void *data);
+
+/** Destroy all associated data in a container. */
+YASM_LIB_DECL
+void yasm__assoc_data_destroy
+ (/*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data);
+
+/** Print all associated data in a container. */
+YASM_LIB_DECL
+void yasm__assoc_data_print(const yasm__assoc_data *assoc_data, FILE *f,
+ int indent_level);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/bc-align.c b/contrib/tools/yasm/libyasm/bc-align.c
new file mode 100644
index 0000000000..2a47882ef0
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/bc-align.c
@@ -0,0 +1,245 @@
+/*
+ * Align bytecode
+ *
+ * Copyright (C) 2005-2007 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 "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+
+#include "bytecode.h"
+
+
+typedef struct bytecode_align {
+ /*@only@*/ yasm_expr *boundary; /* alignment boundary */
+
+ /* What to fill intervening locations with, NULL if using code_fill */
+ /*@only@*/ /*@null@*/ yasm_expr *fill;
+
+ /* Maximum number of bytes to skip, NULL if no maximum. */
+ /*@only@*/ /*@null@*/ yasm_expr *maxskip;
+
+ /* Code fill, NULL if using 0 fill */
+ /*@null@*/ const unsigned char **code_fill;
+} bytecode_align;
+
+static void bc_align_destroy(void *contents);
+static void bc_align_print(const void *contents, FILE *f, int indent_level);
+static void bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static int bc_align_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data);
+static int bc_align_expand(yasm_bytecode *bc, int span, long old_val,
+ long new_val, /*@out@*/ long *neg_thres,
+ /*@out@*/ long *pos_thres);
+static int bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_align_callback = {
+ bc_align_destroy,
+ bc_align_print,
+ bc_align_finalize,
+ NULL,
+ bc_align_calc_len,
+ bc_align_expand,
+ bc_align_tobytes,
+ YASM_BC_SPECIAL_OFFSET
+};
+
+
+static void
+bc_align_destroy(void *contents)
+{
+ bytecode_align *align = (bytecode_align *)contents;
+ if (align->boundary)
+ yasm_expr_destroy(align->boundary);
+ if (align->fill)
+ yasm_expr_destroy(align->fill);
+ if (align->maxskip)
+ yasm_expr_destroy(align->maxskip);
+ yasm_xfree(contents);
+}
+
+static void
+bc_align_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_align *align = (const bytecode_align *)contents;
+ fprintf(f, "%*s_Align_\n", indent_level, "");
+ fprintf(f, "%*sBoundary=", indent_level, "");
+ yasm_expr_print(align->boundary, f);
+ fprintf(f, "\n%*sFill=", indent_level, "");
+ yasm_expr_print(align->fill, f);
+ fprintf(f, "\n%*sMax Skip=", indent_level, "");
+ yasm_expr_print(align->maxskip, f);
+ fprintf(f, "\n");
+}
+
+static void
+bc_align_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_align *align = (bytecode_align *)bc->contents;
+ if (!yasm_expr_get_intnum(&align->boundary, 0))
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("align boundary must be a constant"));
+ if (align->fill && !yasm_expr_get_intnum(&align->fill, 0))
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("align fill must be a constant"));
+ if (align->maxskip && !yasm_expr_get_intnum(&align->maxskip, 0))
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("align maximum skip must be a constant"));
+}
+
+static int
+bc_align_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ long neg_thres = 0;
+ long pos_thres = 0;
+
+ if (bc_align_expand(bc, 0, 0, (long)bc->offset, &neg_thres,
+ &pos_thres) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+bc_align_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
+{
+ bytecode_align *align = (bytecode_align *)bc->contents;
+ unsigned long end;
+ unsigned long boundary =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, 0));
+
+ if (boundary == 0) {
+ bc->len = 0;
+ *pos_thres = new_val;
+ return 0;
+ }
+
+ end = (unsigned long)new_val;
+ if ((unsigned long)new_val & (boundary-1))
+ end = ((unsigned long)new_val & ~(boundary-1)) + boundary;
+
+ *pos_thres = (long)end;
+ bc->len = end - (unsigned long)new_val;
+
+ if (align->maxskip) {
+ unsigned long maxskip =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, 0));
+ if (bc->len > maxskip) {
+ *pos_thres = (long)end-maxskip-1;
+ bc->len = 0;
+ }
+ }
+ return 1;
+}
+
+static int
+bc_align_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ bytecode_align *align = (bytecode_align *)bc->contents;
+ unsigned long len;
+ unsigned long boundary =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->boundary, 0));
+
+ if (boundary == 0)
+ return 0;
+ else {
+ unsigned long end = bc->offset;
+ if (bc->offset & (boundary-1))
+ end = (bc->offset & ~(boundary-1)) + boundary;
+ len = end - bc->offset;
+ if (len == 0)
+ return 0;
+ if (align->maxskip) {
+ unsigned long maxskip =
+ yasm_intnum_get_uint(yasm_expr_get_intnum(&align->maxskip, 0));
+ if (len > maxskip)
+ return 0;
+ }
+ }
+
+ if (align->fill) {
+ unsigned long v;
+ v = yasm_intnum_get_uint(yasm_expr_get_intnum(&align->fill, 0));
+ memset(*bufp, (int)v, len);
+ *bufp += len;
+ } else if (align->code_fill) {
+ unsigned long maxlen = 15;
+ while (!align->code_fill[maxlen] && maxlen>0)
+ maxlen--;
+ if (maxlen == 0) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("could not find any code alignment size"));
+ return 1;
+ }
+
+ /* Fill with maximum code fill as much as possible */
+ while (len > maxlen) {
+ memcpy(*bufp, align->code_fill[maxlen], maxlen);
+ *bufp += maxlen;
+ len -= maxlen;
+ }
+
+ if (!align->code_fill[len]) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("invalid alignment size %d"), len);
+ return 1;
+ }
+ /* Handle rest of code fill */
+ memcpy(*bufp, align->code_fill[len], len);
+ *bufp += len;
+ } else {
+ /* Just fill with 0 */
+ memset(*bufp, 0, len);
+ *bufp += len;
+ }
+ return 0;
+}
+
+yasm_bytecode *
+yasm_bc_create_align(yasm_expr *boundary, yasm_expr *fill,
+ yasm_expr *maxskip, const unsigned char **code_fill,
+ unsigned long line)
+{
+ bytecode_align *align = yasm_xmalloc(sizeof(bytecode_align));
+
+ align->boundary = boundary;
+ align->fill = fill;
+ align->maxskip = maxskip;
+ align->code_fill = code_fill;
+
+ return yasm_bc_create_common(&bc_align_callback, align, line);
+}
diff --git a/contrib/tools/yasm/libyasm/bc-data.c b/contrib/tools/yasm/libyasm/bc-data.c
new file mode 100644
index 0000000000..ebbdd6f97d
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/bc-data.c
@@ -0,0 +1,600 @@
+/*
+ * Data (and LEB128) bytecode
+ *
+ * Copyright (C) 2001-2007 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 "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+#include "arch.h"
+
+
+struct yasm_dataval {
+ /*@reldef@*/ STAILQ_ENTRY(yasm_dataval) link;
+
+ enum { DV_EMPTY, DV_VALUE, DV_RAW, DV_ULEB128, DV_SLEB128, DV_RESERVE }
+ type;
+
+ union {
+ yasm_value val;
+ struct {
+ /*@only@*/ unsigned char *contents;
+ unsigned long len;
+ } raw;
+ } data;
+
+ /* number of times data is repeated, NULL=1. */
+ /*@only@*/ /*@null@*/ yasm_expr *multiple;
+};
+
+typedef struct bytecode_data {
+ /* converted data (linked list) */
+ yasm_datavalhead datahead;
+
+ int item_size;
+} bytecode_data;
+
+static void bc_data_destroy(void *contents);
+static void bc_data_print(const void *contents, FILE *f, int indent_level);
+static void bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static int bc_data_item_size(yasm_bytecode *bc);
+static int bc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data);
+static int bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_data_callback = {
+ bc_data_destroy,
+ bc_data_print,
+ bc_data_finalize,
+ bc_data_item_size,
+ bc_data_calc_len,
+ yasm_bc_expand_common,
+ bc_data_tobytes,
+ 0
+};
+
+
+static void
+bc_data_destroy(void *contents)
+{
+ bytecode_data *bc_data = (bytecode_data *)contents;
+ yasm_dvs_delete(&bc_data->datahead);
+ yasm_xfree(contents);
+}
+
+static void
+bc_data_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_data *bc_data = (const bytecode_data *)contents;
+ fprintf(f, "%*s_Data_\n", indent_level, "");
+ fprintf(f, "%*sElements:\n", indent_level+1, "");
+ yasm_dvs_print(&bc_data->datahead, f, indent_level+2);
+}
+
+static void
+bc_data_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_data *bc_data = (bytecode_data *)bc->contents;
+ yasm_dataval *dv;
+ yasm_intnum *intn;
+
+ /* Convert values from simple expr to value. */
+ STAILQ_FOREACH(dv, &bc_data->datahead, link) {
+ switch (dv->type) {
+ case DV_VALUE:
+ if (yasm_value_finalize(&dv->data.val, prev_bc)) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("data expression too complex"));
+ return;
+ }
+ break;
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
+ if (!intn) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("LEB128 requires constant values"));
+ return;
+ }
+ /* Warn for negative values in unsigned environment.
+ * This could be an error instead: the likelihood this is
+ * desired is very low!
+ */
+ if (yasm_intnum_sign(intn) == -1 && dv->type == DV_ULEB128)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("negative value in unsigned LEB128"));
+ break;
+ default:
+ break;
+ }
+ if (dv->multiple) {
+ yasm_value val;
+ if (yasm_value_finalize_expr(&val, dv->multiple, prev_bc, 0))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("multiple expression too complex"));
+ else if (val.rel)
+ yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
+ N_("multiple expression not absolute"));
+ dv->multiple = val.abs;
+ }
+ }
+}
+
+static int
+bc_data_item_size(yasm_bytecode *bc)
+{
+ bytecode_data *bc_data = (bytecode_data *)bc->contents;
+ return bc_data->item_size;
+}
+
+static int
+bc_data_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ bytecode_data *bc_data = (bytecode_data *)bc->contents;
+ yasm_dataval *dv;
+ yasm_intnum *intn;
+ unsigned long len = 0;
+ unsigned long multiple;
+
+ /* Count up element sizes, rounding up string length. */
+ STAILQ_FOREACH(dv, &bc_data->datahead, link) {
+ switch (dv->type) {
+ case DV_EMPTY:
+ len = 0;
+ break;
+ case DV_VALUE:
+ len = dv->data.val.size/8;
+ break;
+ case DV_RAW:
+ len = dv->data.raw.len;
+ break;
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
+ if (!intn)
+ yasm_internal_error(N_("non-constant in data_tobytes"));
+ len = yasm_intnum_size_leb128(intn, dv->type == DV_SLEB128);
+ break;
+ case DV_RESERVE:
+ len = dv->data.val.size/8;
+ break;
+ }
+
+ if (!yasm_dv_get_multiple(dv, &multiple))
+ len *= multiple;
+
+ bc->len += len;
+ }
+
+ return 0;
+}
+
+static int
+bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ bytecode_data *bc_data = (bytecode_data *)bc->contents;
+ yasm_dataval *dv;
+ yasm_intnum *intn;
+ unsigned int val_len;
+ unsigned long multiple, i;
+
+ STAILQ_FOREACH(dv, &bc_data->datahead, link) {
+ if (yasm_dv_get_multiple(dv, &multiple) || multiple == 0)
+ continue;
+ switch (dv->type) {
+ case DV_EMPTY:
+ break;
+ case DV_VALUE:
+ val_len = dv->data.val.size/8;
+ for (i=0; i<multiple; i++) {
+ if (output_value(&dv->data.val, *bufp, val_len,
+ (unsigned long)(*bufp-bufstart), bc, 1,
+ d))
+ return 1;
+ *bufp += val_len;
+ }
+ break;
+ case DV_RAW:
+ for (i=0; i<multiple; i++) {
+ memcpy(*bufp, dv->data.raw.contents, dv->data.raw.len);
+ *bufp += dv->data.raw.len;
+ }
+ break;
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, 234);
+ if (!intn)
+ yasm_internal_error(N_("non-constant in data_tobytes"));
+ for (i=0; i<multiple; i++) {
+ *bufp +=
+ yasm_intnum_get_leb128(intn, *bufp,
+ dv->type == DV_SLEB128);
+ }
+ case DV_RESERVE:
+ val_len = dv->data.val.size/8;
+ for (i=0; i<multiple; i++) {
+ memset(*bufp, 0, val_len);
+ *bufp += val_len;
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+yasm_bytecode *
+yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
+ int append_zero, yasm_arch *arch, unsigned long line)
+{
+ bytecode_data *data = yasm_xmalloc(sizeof(bytecode_data));
+ yasm_bytecode *bc = yasm_bc_create_common(&bc_data_callback, data, line);
+ yasm_dataval *dv, *dv2, *dvo;
+ yasm_intnum *intn;
+ unsigned long len = 0, rlen, i;
+
+
+ yasm_dvs_initialize(&data->datahead);
+ data->item_size = size;
+
+ /* Prescan input data for length, etc. Careful: this needs to be
+ * precisely paired with the second loop.
+ */
+ STAILQ_FOREACH(dv, datahead, link) {
+ if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
+ /* Flush previous data */
+ dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
+ STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+ len = 0;
+ }
+ switch (dv->type) {
+ case DV_EMPTY:
+ break;
+ case DV_VALUE:
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
+ if (intn && dv->type == DV_VALUE && (arch || size == 1))
+ len += size;
+ else if (intn && dv->type == DV_ULEB128)
+ len += yasm_intnum_size_leb128(intn, 0);
+ else if (intn && dv->type == DV_SLEB128)
+ len += yasm_intnum_size_leb128(intn, 1);
+ else {
+ if (len > 0) {
+ /* Create bytecode for all previous len */
+ dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
+ STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+ len = 0;
+ }
+
+ /* Create bytecode for this value */
+ dvo = yasm_xmalloc(sizeof(yasm_dataval));
+ STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+ dvo->multiple = dv->multiple;
+ }
+ break;
+ case DV_RAW:
+ rlen = dv->data.raw.len;
+ /* find count, rounding up to nearest multiple of size */
+ rlen = (rlen + size - 1) / size;
+ len += rlen*size;
+ break;
+ case DV_RESERVE:
+ len += size;
+ break;
+ }
+
+ if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
+ /* Flush this data */
+ dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
+ STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+ dvo->multiple = dv->multiple;
+ len = 0;
+ }
+
+ if (append_zero)
+ len++;
+ }
+
+ /* Create final dataval for any trailing length */
+ if (len > 0) {
+ dvo = yasm_dv_create_raw(yasm_xmalloc(len), len);
+ STAILQ_INSERT_TAIL(&data->datahead, dvo, link);
+ }
+
+ /* Second iteration: copy data and delete input datavals. */
+ dv = STAILQ_FIRST(datahead);
+ dvo = STAILQ_FIRST(&data->datahead);
+ len = 0;
+ while (dv && dvo) {
+ if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
+ dvo = STAILQ_NEXT(dvo, link);
+ len = 0;
+ }
+ switch (dv->type) {
+ case DV_EMPTY:
+ break;
+ case DV_VALUE:
+ case DV_ULEB128:
+ case DV_SLEB128:
+ intn = yasm_expr_get_intnum(&dv->data.val.abs, 0);
+ if (intn && dv->type == DV_VALUE && (arch || size == 1)) {
+ if (size == 1)
+ yasm_intnum_get_sized(intn,
+ &dvo->data.raw.contents[len],
+ 1, 8, 0, 0, 1);
+ else
+ yasm_arch_intnum_tobytes(arch, intn,
+ &dvo->data.raw.contents[len],
+ size, size*8, 0, bc, 1);
+ yasm_value_delete(&dv->data.val);
+ len += size;
+ } else if (intn && dv->type == DV_ULEB128) {
+ len += yasm_intnum_get_leb128(intn,
+ &dvo->data.raw.contents[len],
+ 0);
+ yasm_value_delete(&dv->data.val);
+ } else if (intn && dv->type == DV_SLEB128) {
+ len += yasm_intnum_get_leb128(intn,
+ &dvo->data.raw.contents[len],
+ 1);
+ yasm_value_delete(&dv->data.val);
+ } else {
+ if (len > 0)
+ dvo = STAILQ_NEXT(dvo, link);
+ dvo->type = dv->type;
+ dvo->data.val = dv->data.val; /* structure copy */
+ dvo->data.val.size = size*8; /* remember size */
+ dvo = STAILQ_NEXT(dvo, link);
+ len = 0;
+ }
+ break;
+ case DV_RAW:
+ rlen = dv->data.raw.len;
+ memcpy(&dvo->data.raw.contents[len], dv->data.raw.contents,
+ rlen);
+ yasm_xfree(dv->data.raw.contents);
+ len += rlen;
+ /* pad with 0's to nearest multiple of size */
+ rlen %= size;
+ if (rlen > 0) {
+ rlen = size-rlen;
+ for (i=0; i<rlen; i++)
+ dvo->data.raw.contents[len++] = 0;
+ }
+ break;
+ case DV_RESERVE:
+ memset(&dvo->data.raw.contents[len], 0, size);
+ len += size;
+ break;
+ }
+
+ if (dv->multiple && dv->type != DV_EMPTY && len > 0) {
+ dvo = STAILQ_NEXT(dvo, link);
+ len = 0;
+ }
+
+ if (append_zero)
+ dvo->data.raw.contents[len++] = 0;
+ dv2 = STAILQ_NEXT(dv, link);
+ yasm_xfree(dv);
+ dv = dv2;
+ }
+
+ return bc;
+}
+
+yasm_bytecode *
+yasm_bc_create_leb128(yasm_datavalhead *datahead, int sign, unsigned long line)
+{
+ yasm_dataval *dv;
+
+ /* Convert all values into LEB type, error on strings/raws */
+ STAILQ_FOREACH(dv, datahead, link) {
+ switch (dv->type) {
+ case DV_VALUE:
+ dv->type = sign ? DV_SLEB128 : DV_ULEB128;
+ break;
+ case DV_RAW:
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("LEB128 does not allow string constants"));
+ break;
+ default:
+ break;
+ }
+ }
+
+ return yasm_bc_create_data(datahead, 0, 0, 0, line);
+}
+
+yasm_dataval *
+yasm_dv_create_expr(yasm_expr *e)
+{
+ yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
+
+ retval->type = DV_VALUE;
+ yasm_value_initialize(&retval->data.val, e, 0);
+ retval->multiple = NULL;
+
+ return retval;
+}
+
+yasm_dataval *
+yasm_dv_create_raw(unsigned char *contents, unsigned long len)
+{
+ yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
+
+ retval->type = DV_RAW;
+ retval->data.raw.contents = contents;
+ retval->data.raw.len = len;
+ retval->multiple = NULL;
+
+ return retval;
+}
+
+yasm_dataval *
+yasm_dv_create_reserve(void)
+{
+ yasm_dataval *retval = yasm_xmalloc(sizeof(yasm_dataval));
+
+ retval->type = DV_RESERVE;
+ retval->multiple = NULL;
+
+ return retval;
+}
+
+yasm_value *
+yasm_dv_get_value(yasm_dataval *dv)
+{
+ if (dv->type != DV_VALUE)
+ return NULL;
+ return &dv->data.val;
+}
+
+void
+yasm_dv_set_multiple(yasm_dataval *dv, yasm_expr *e)
+{
+ if (dv->multiple)
+ dv->multiple = yasm_expr_create_tree( dv->multiple, YASM_EXPR_MUL, e,
+ e->line);
+ else
+ dv->multiple = e;
+}
+
+int
+yasm_dv_get_multiple(yasm_dataval *dv, unsigned long *multiple)
+{
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+
+ *multiple = 1;
+ if (dv->multiple) {
+ num = yasm_expr_get_intnum(&dv->multiple, 0);
+ if (!num) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("could not determine multiple"));
+ return 1;
+ }
+ if (yasm_intnum_sign(num) < 0) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
+ return 1;
+ }
+ *multiple = yasm_intnum_get_uint(num);
+ }
+ return 0;
+}
+
+void
+yasm_dvs_delete(yasm_datavalhead *headp)
+{
+ yasm_dataval *cur, *next;
+
+ cur = STAILQ_FIRST(headp);
+ while (cur) {
+ next = STAILQ_NEXT(cur, link);
+ switch (cur->type) {
+ case DV_VALUE:
+ yasm_value_delete(&cur->data.val);
+ break;
+ case DV_RAW:
+ yasm_xfree(cur->data.raw.contents);
+ break;
+ default:
+ break;
+ }
+ if (cur->multiple)
+ yasm_expr_destroy(cur->multiple);
+ yasm_xfree(cur);
+ cur = next;
+ }
+ STAILQ_INIT(headp);
+}
+
+yasm_dataval *
+yasm_dvs_append(yasm_datavalhead *headp, yasm_dataval *dv)
+{
+ if (dv) {
+ STAILQ_INSERT_TAIL(headp, dv, link);
+ return dv;
+ }
+ return (yasm_dataval *)NULL;
+}
+
+void
+yasm_dvs_print(const yasm_datavalhead *head, FILE *f, int indent_level)
+{
+ yasm_dataval *cur;
+ unsigned long i;
+
+ STAILQ_FOREACH(cur, head, link) {
+ fprintf(f, "%*sMultiple=", indent_level, "");
+ if (!cur->multiple)
+ fprintf(f, "nil (1)");
+ else
+ yasm_expr_print(cur->multiple, f);
+ switch (cur->type) {
+ case DV_EMPTY:
+ fprintf(f, "%*sEmpty\n", indent_level, "");
+ break;
+ case DV_VALUE:
+ fprintf(f, "%*sValue:\n", indent_level, "");
+ yasm_value_print(&cur->data.val, f, indent_level+1);
+ break;
+ case DV_RAW:
+ fprintf(f, "%*sLength=%lu\n", indent_level, "",
+ cur->data.raw.len);
+ fprintf(f, "%*sBytes=[", indent_level, "");
+ for (i=0; i<cur->data.raw.len; i++)
+ fprintf(f, "0x%02x, ", cur->data.raw.contents[i]);
+ fprintf(f, "]\n");
+ break;
+ case DV_ULEB128:
+ fprintf(f, "%*sULEB128 value:\n", indent_level, "");
+ yasm_value_print(&cur->data.val, f, indent_level+1);
+ break;
+ case DV_SLEB128:
+ fprintf(f, "%*sSLEB128 value:\n", indent_level, "");
+ yasm_value_print(&cur->data.val, f, indent_level+1);
+ break;
+ case DV_RESERVE:
+ fprintf(f, "%*sReserved\n", indent_level, "");
+ break;
+ }
+ }
+}
diff --git a/contrib/tools/yasm/libyasm/bc-incbin.c b/contrib/tools/yasm/libyasm/bc-incbin.c
new file mode 100644
index 0000000000..a8fec7d6ce
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/bc-incbin.c
@@ -0,0 +1,265 @@
+/*
+ * Incbin bytecode
+ *
+ * Copyright (C) 2001-2007 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 "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+
+#include "linemap.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+
+#include "file.h"
+
+
+typedef struct bytecode_incbin {
+ /*@only@*/ char *filename; /* file to include data from */
+ const char *from; /* filename of what contained incbin */
+
+ /* starting offset to read from (NULL=0) */
+ /*@only@*/ /*@null@*/ yasm_expr *start;
+
+ /* maximum number of bytes to read (NULL=no limit) */
+ /*@only@*/ /*@null@*/ yasm_expr *maxlen;
+} bytecode_incbin;
+
+static void bc_incbin_destroy(void *contents);
+static void bc_incbin_print(const void *contents, FILE *f, int indent_level);
+static void bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static int bc_incbin_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data);
+static int bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_incbin_callback = {
+ bc_incbin_destroy,
+ bc_incbin_print,
+ bc_incbin_finalize,
+ NULL,
+ bc_incbin_calc_len,
+ yasm_bc_expand_common,
+ bc_incbin_tobytes,
+ 0
+};
+
+
+static void
+bc_incbin_destroy(void *contents)
+{
+ bytecode_incbin *incbin = (bytecode_incbin *)contents;
+ yasm_xfree(incbin->filename);
+ yasm_expr_destroy(incbin->start);
+ yasm_expr_destroy(incbin->maxlen);
+ yasm_xfree(contents);
+}
+
+static void
+bc_incbin_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_incbin *incbin = (const bytecode_incbin *)contents;
+ fprintf(f, "%*s_IncBin_\n", indent_level, "");
+ fprintf(f, "%*sFilename=`%s'\n", indent_level, "",
+ incbin->filename);
+ fprintf(f, "%*sStart=", indent_level, "");
+ if (!incbin->start)
+ fprintf(f, "nil (0)");
+ else
+ yasm_expr_print(incbin->start, f);
+ fprintf(f, "%*sMax Len=", indent_level, "");
+ if (!incbin->maxlen)
+ fprintf(f, "nil (unlimited)");
+ else
+ yasm_expr_print(incbin->maxlen, f);
+ fprintf(f, "\n");
+}
+
+static void
+bc_incbin_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
+ yasm_value val;
+
+ if (yasm_value_finalize_expr(&val, incbin->start, prev_bc, 0))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("start expression too complex"));
+ else if (val.rel)
+ yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
+ N_("start expression not absolute"));
+ incbin->start = val.abs;
+
+ if (yasm_value_finalize_expr(&val, incbin->maxlen, prev_bc, 0))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("maximum length expression too complex"));
+ else if (val.rel)
+ yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
+ N_("maximum length expression not absolute"));
+ incbin->maxlen = val.abs;
+}
+
+static int
+bc_incbin_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
+ FILE *f;
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+ unsigned long start = 0, maxlen = 0xFFFFFFFFUL, flen;
+
+ /* Try to convert start to integer value */
+ if (incbin->start) {
+ num = yasm_expr_get_intnum(&incbin->start, 0);
+ if (num)
+ start = yasm_intnum_get_uint(num);
+ if (!num) {
+ /* FIXME */
+ yasm_error_set(YASM_ERROR_NOT_IMPLEMENTED,
+ N_("incbin does not yet understand non-constant"));
+ return -1;
+ }
+ }
+
+ /* Try to convert maxlen to integer value */
+ if (incbin->maxlen) {
+ num = yasm_expr_get_intnum(&incbin->maxlen, 0);
+ if (num)
+ maxlen = yasm_intnum_get_uint(num);
+ if (!num) {
+ /* FIXME */
+ yasm_error_set(YASM_ERROR_NOT_IMPLEMENTED,
+ N_("incbin does not yet understand non-constant"));
+ return -1;
+ }
+ }
+
+ /* Open file and determine its length */
+ f = yasm_fopen_include(incbin->filename, incbin->from, "rb", NULL);
+ if (!f) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("`incbin': unable to open file `%s'"),
+ incbin->filename);
+ return -1;
+ }
+ if (fseek(f, 0L, SEEK_END) < 0) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("`incbin': unable to seek on file `%s'"),
+ incbin->filename);
+ return -1;
+ }
+ flen = (unsigned long)ftell(f);
+ fclose(f);
+
+ /* Compute length of incbin from start, maxlen, and len */
+ if (start > flen) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("`incbin': start past end of file `%s'"),
+ incbin->filename);
+ start = flen;
+ }
+ flen -= start;
+ if (incbin->maxlen)
+ if (maxlen < flen)
+ flen = maxlen;
+ bc->len += flen;
+ return 0;
+}
+
+static int
+bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
+ FILE *f;
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+ unsigned long start = 0;
+
+ /* Convert start to integer value */
+ if (incbin->start) {
+ num = yasm_expr_get_intnum(&incbin->start, 0);
+ if (!num)
+ yasm_internal_error(
+ N_("could not determine start in bc_tobytes_incbin"));
+ start = yasm_intnum_get_uint(num);
+ }
+
+ /* Open file */
+ f = yasm_fopen_include(incbin->filename, incbin->from, "rb", NULL);
+ if (!f) {
+ yasm_error_set(YASM_ERROR_IO, N_("`incbin': unable to open file `%s'"),
+ incbin->filename);
+ return 1;
+ }
+
+ /* Seek to start of data */
+ if (fseek(f, (long)start, SEEK_SET) < 0) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("`incbin': unable to seek on file `%s'"),
+ incbin->filename);
+ fclose(f);
+ return 1;
+ }
+
+ /* Read len bytes */
+ if (fread(*bufp, 1, (size_t)bc->len, f) < (size_t)bc->len) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("`incbin': unable to read %lu bytes from file `%s'"),
+ bc->len, incbin->filename);
+ fclose(f);
+ return 1;
+ }
+
+ *bufp += bc->len;
+ fclose(f);
+ return 0;
+}
+
+yasm_bytecode *
+yasm_bc_create_incbin(char *filename, yasm_expr *start, yasm_expr *maxlen,
+ yasm_linemap *linemap, unsigned long line)
+{
+ bytecode_incbin *incbin = yasm_xmalloc(sizeof(bytecode_incbin));
+ unsigned long xline;
+
+ /* Find from filename based on line number */
+ yasm_linemap_lookup(linemap, line, &incbin->from, &xline);
+
+ /*@-mustfree@*/
+ incbin->filename = filename;
+ incbin->start = start;
+ incbin->maxlen = maxlen;
+ /*@=mustfree@*/
+
+ return yasm_bc_create_common(&bc_incbin_callback, incbin, line);
+}
diff --git a/contrib/tools/yasm/libyasm/bc-org.c b/contrib/tools/yasm/libyasm/bc-org.c
new file mode 100644
index 0000000000..7ef96c8412
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/bc-org.c
@@ -0,0 +1,152 @@
+/*
+ * ORG bytecode
+ *
+ * Copyright (C) 2005-2007 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 "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+#include "file.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+
+
+typedef struct bytecode_org {
+ unsigned long start; /* target starting offset within section */
+ unsigned long fill; /* fill value */
+} bytecode_org;
+
+static void bc_org_destroy(void *contents);
+static void bc_org_print(const void *contents, FILE *f, int indent_level);
+static void bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static int bc_org_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data);
+static int bc_org_expand(yasm_bytecode *bc, int span, long old_val,
+ long new_val, /*@out@*/ long *neg_thres,
+ /*@out@*/ long *pos_thres);
+static int bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_org_callback = {
+ bc_org_destroy,
+ bc_org_print,
+ bc_org_finalize,
+ NULL,
+ bc_org_calc_len,
+ bc_org_expand,
+ bc_org_tobytes,
+ YASM_BC_SPECIAL_OFFSET
+};
+
+
+static void
+bc_org_destroy(void *contents)
+{
+ yasm_xfree(contents);
+}
+
+static void
+bc_org_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_org *org = (const bytecode_org *)contents;
+ fprintf(f, "%*s_Org_\n", indent_level, "");
+ fprintf(f, "%*sStart=%lu\n", indent_level, "", org->start);
+}
+
+static void
+bc_org_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+}
+
+static int
+bc_org_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ bytecode_org *org = (bytecode_org *)bc->contents;
+ long neg_thres = 0;
+ long pos_thres = org->start;
+
+ if (bc_org_expand(bc, 0, 0, (long)bc->offset, &neg_thres, &pos_thres) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+bc_org_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
+{
+ bytecode_org *org = (bytecode_org *)bc->contents;
+
+ /* Check for overrun */
+ if ((unsigned long)new_val > org->start) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("ORG overlap with already existing data"));
+ return -1;
+ }
+
+ /* Generate space to start offset */
+ bc->len = org->start - new_val;
+ return 1;
+}
+
+static int
+bc_org_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ bytecode_org *org = (bytecode_org *)bc->contents;
+ unsigned long len, i;
+
+ /* Sanity check for overrun */
+ if (bc->offset > org->start) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("ORG overlap with already existing data"));
+ return 1;
+ }
+ len = org->start - bc->offset;
+ for (i=0; i<len; i++)
+ YASM_WRITE_8(*bufp, org->fill); /* XXX: handle more than 8 bit? */
+ return 0;
+}
+
+yasm_bytecode *
+yasm_bc_create_org(unsigned long start, unsigned long fill, unsigned long line)
+{
+ bytecode_org *org = yasm_xmalloc(sizeof(bytecode_org));
+
+ org->start = start;
+ org->fill = fill;
+
+ return yasm_bc_create_common(&bc_org_callback, org, line);
+}
diff --git a/contrib/tools/yasm/libyasm/bc-reserve.c b/contrib/tools/yasm/libyasm/bc-reserve.c
new file mode 100644
index 0000000000..197175b4e5
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/bc-reserve.c
@@ -0,0 +1,152 @@
+/*
+ * Bytecode utility functions
+ *
+ * Copyright (C) 2001-2007 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 "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+
+
+typedef struct bytecode_reserve {
+ /*@only@*/ /*@null@*/ yasm_expr *numitems; /* number of items to reserve */
+ unsigned int itemsize; /* size of each item (in bytes) */
+} bytecode_reserve;
+
+static void bc_reserve_destroy(void *contents);
+static void bc_reserve_print(const void *contents, FILE *f, int indent_level);
+static void bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+static int bc_reserve_elem_size(yasm_bytecode *bc);
+static int bc_reserve_calc_len(yasm_bytecode *bc,
+ yasm_bc_add_span_func add_span,
+ void *add_span_data);
+static int bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static const yasm_bytecode_callback bc_reserve_callback = {
+ bc_reserve_destroy,
+ bc_reserve_print,
+ bc_reserve_finalize,
+ bc_reserve_elem_size,
+ bc_reserve_calc_len,
+ yasm_bc_expand_common,
+ bc_reserve_tobytes,
+ YASM_BC_SPECIAL_RESERVE
+};
+
+
+static void
+bc_reserve_destroy(void *contents)
+{
+ bytecode_reserve *reserve = (bytecode_reserve *)contents;
+ yasm_expr_destroy(reserve->numitems);
+ yasm_xfree(contents);
+}
+
+static void
+bc_reserve_print(const void *contents, FILE *f, int indent_level)
+{
+ const bytecode_reserve *reserve = (const bytecode_reserve *)contents;
+ fprintf(f, "%*s_Reserve_\n", indent_level, "");
+ fprintf(f, "%*sNum Items=", indent_level, "");
+ yasm_expr_print(reserve->numitems, f);
+ fprintf(f, "\n%*sItem Size=%u\n", indent_level, "", reserve->itemsize);
+}
+
+static void
+bc_reserve_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
+ /* multiply reserve expression into multiple */
+ if (!bc->multiple)
+ bc->multiple = reserve->numitems;
+ else
+ bc->multiple = yasm_expr_create_tree(bc->multiple, YASM_EXPR_MUL,
+ reserve->numitems, bc->line);
+ reserve->numitems = NULL;
+}
+
+static int
+bc_reserve_elem_size(yasm_bytecode *bc)
+{
+ bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
+ return reserve->itemsize;
+}
+
+static int
+bc_reserve_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
+ bc->len += reserve->itemsize;
+ return 0;
+}
+
+static int
+bc_reserve_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ yasm_internal_error(N_("bc_reserve_tobytes called"));
+ /*@notreached@*/
+ return 1;
+}
+
+yasm_bytecode *
+yasm_bc_create_reserve(yasm_expr *numitems, unsigned int itemsize,
+ unsigned long line)
+{
+ bytecode_reserve *reserve = yasm_xmalloc(sizeof(bytecode_reserve));
+
+ /*@-mustfree@*/
+ reserve->numitems = numitems;
+ /*@=mustfree@*/
+ reserve->itemsize = itemsize;
+
+ return yasm_bc_create_common(&bc_reserve_callback, reserve, line);
+}
+
+const yasm_expr *
+yasm_bc_reserve_numitems(yasm_bytecode *bc, unsigned int *itemsize)
+{
+ bytecode_reserve *reserve;
+
+ if (bc->callback != &bc_reserve_callback)
+ return NULL;
+
+ reserve = (bytecode_reserve *)bc->contents;
+ *itemsize = reserve->itemsize;
+ return reserve->numitems;
+}
diff --git a/contrib/tools/yasm/libyasm/bitvect.c b/contrib/tools/yasm/libyasm/bitvect.c
new file mode 100644
index 0000000000..dfb08252b0
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/bitvect.c
@@ -0,0 +1,4045 @@
+#include "util.h"
+
+#include "coretype.h"
+
+/*****************************************************************************/
+/* MODULE NAME: BitVector.c MODULE TYPE: (adt) */
+/*****************************************************************************/
+/* MODULE IMPORTS: */
+/*****************************************************************************/
+#include <ctype.h> /* MODULE TYPE: (sys) */
+#include <limits.h> /* MODULE TYPE: (sys) */
+#include <string.h> /* MODULE TYPE: (sys) */
+/*****************************************************************************/
+/* MODULE INTERFACE: */
+/*****************************************************************************/
+#include "bitvect.h"
+
+/* ToolBox.h */
+#define and && /* logical (boolean) operators: lower case */
+#define or ||
+#define not !
+
+#define AND & /* binary (bitwise) operators: UPPER CASE */
+#define OR |
+#define XOR ^
+#define NOT ~
+#define SHL <<
+#define SHR >>
+
+#ifdef ENABLE_MODULO
+#define mod % /* arithmetic operators */
+#endif
+
+#define blockdef(name,size) unsigned char name[size]
+#define blocktypedef(name,size) typedef unsigned char name[size]
+
+/*****************************************************************************/
+/* MODULE RESOURCES: */
+/*****************************************************************************/
+
+#define bits_(BitVector) *(BitVector-3)
+#define size_(BitVector) *(BitVector-2)
+#define mask_(BitVector) *(BitVector-1)
+
+#define ERRCODE_TYPE "sizeof(word) > sizeof(size_t)"
+#define ERRCODE_BITS "bits(word) != sizeof(word)*8"
+#define ERRCODE_WORD "bits(word) < 16"
+#define ERRCODE_LONG "bits(word) > bits(long)"
+#define ERRCODE_POWR "bits(word) != 2^x"
+#define ERRCODE_LOGA "bits(word) != 2^ld(bits(word))"
+#define ERRCODE_NULL "unable to allocate memory"
+#define ERRCODE_INDX "index out of range"
+#define ERRCODE_ORDR "minimum > maximum index"
+#define ERRCODE_SIZE "bit vector size mismatch"
+#define ERRCODE_PARS "input string syntax error"
+#define ERRCODE_OVFL "numeric overflow error"
+#define ERRCODE_SAME "result vector(s) must be distinct"
+#define ERRCODE_EXPO "exponent must be positive"
+#define ERRCODE_ZERO "division by zero error"
+#define ERRCODE_OOPS "unexpected internal error - please contact author"
+
+const N_int BitVector_BYTENORM[256] =
+{
+ 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03,
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, /* 0x00 */
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x10 */
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x20 */
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x30 */
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x40 */
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x50 */
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x60 */
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0x70 */
+ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x80 */
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x90 */
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0xA0 */
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xB0 */
+ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0xC0 */
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xD0 */
+ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xE0 */
+ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
+ 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08 /* 0xF0 */
+};
+
+/*****************************************************************************/
+/* MODULE IMPLEMENTATION: */
+/*****************************************************************************/
+
+ /**********************************************/
+ /* global implementation-intrinsic constants: */
+ /**********************************************/
+
+#define BIT_VECTOR_HIDDEN_WORDS 3
+
+ /*****************************************************************/
+ /* global machine-dependent constants (set by "BitVector_Boot"): */
+ /*****************************************************************/
+
+static N_word BITS; /* = # of bits in machine word (must be power of 2) */
+static N_word MODMASK; /* = BITS - 1 (mask for calculating modulo BITS) */
+static N_word LOGBITS; /* = ld(BITS) (logarithmus dualis) */
+static N_word FACTOR; /* = ld(BITS / 8) (ld of # of bytes) */
+
+static N_word LSB = 1; /* = mask for least significant bit */
+static N_word MSB; /* = mask for most significant bit */
+
+static N_word LONGBITS; /* = # of bits in unsigned long */
+
+static N_word LOG10; /* = logarithm to base 10 of BITS - 1 */
+static N_word EXP10; /* = largest possible power of 10 in signed int */
+
+ /********************************************************************/
+ /* global bit mask table for fast access (set by "BitVector_Boot"): */
+ /********************************************************************/
+
+static wordptr BITMASKTAB;
+
+ /*****************************/
+ /* global macro definitions: */
+ /*****************************/
+
+#define BIT_VECTOR_ZERO_WORDS(target,count) \
+ while (count-- > 0) *target++ = 0;
+
+#define BIT_VECTOR_FILL_WORDS(target,fill,count) \
+ while (count-- > 0) *target++ = fill;
+
+#define BIT_VECTOR_FLIP_WORDS(target,flip,count) \
+ while (count-- > 0) *target++ ^= flip;
+
+#define BIT_VECTOR_COPY_WORDS(target,source,count) \
+ while (count-- > 0) *target++ = *source++;
+
+#define BIT_VECTOR_BACK_WORDS(target,source,count) \
+ { target += count; source += count; while (count-- > 0) *--target = *--source; }
+
+#define BIT_VECTOR_CLR_BIT(address,index) \
+ *(address+(index>>LOGBITS)) &= NOT BITMASKTAB[index AND MODMASK];
+
+#define BIT_VECTOR_SET_BIT(address,index) \
+ *(address+(index>>LOGBITS)) |= BITMASKTAB[index AND MODMASK];
+
+#define BIT_VECTOR_TST_BIT(address,index) \
+ ((*(address+(index>>LOGBITS)) AND BITMASKTAB[index AND MODMASK]) != 0)
+
+#define BIT_VECTOR_FLP_BIT(address,index,mask) \
+ (mask = BITMASKTAB[index AND MODMASK]), \
+ (((*(addr+(index>>LOGBITS)) ^= mask) AND mask) != 0)
+
+#define BIT_VECTOR_DIGITIZE(type,value,digit) \
+ value = (type) ((digit = value) / 10); \
+ digit -= value * 10; \
+ digit += (type) '0';
+
+ /*********************************************************/
+ /* private low-level functions (potentially dangerous!): */
+ /*********************************************************/
+
+static N_word power10(N_word x)
+{
+ N_word y = 1;
+
+ while (x-- > 0) y *= 10;
+ return(y);
+}
+
+static void BIT_VECTOR_zro_words(wordptr addr, N_word count)
+{
+ BIT_VECTOR_ZERO_WORDS(addr,count)
+}
+
+static void BIT_VECTOR_cpy_words(wordptr target, wordptr source, N_word count)
+{
+ BIT_VECTOR_COPY_WORDS(target,source,count)
+}
+
+static void BIT_VECTOR_mov_words(wordptr target, wordptr source, N_word count)
+{
+ if (target != source)
+ {
+ if (target < source) BIT_VECTOR_COPY_WORDS(target,source,count)
+ else BIT_VECTOR_BACK_WORDS(target,source,count)
+ }
+}
+
+static void BIT_VECTOR_ins_words(wordptr addr, N_word total, N_word count,
+ boolean clear)
+{
+ N_word length;
+
+ if ((total > 0) and (count > 0))
+ {
+ if (count > total) count = total;
+ length = total - count;
+ if (length > 0) BIT_VECTOR_mov_words(addr+count,addr,length);
+ if (clear) BIT_VECTOR_zro_words(addr,count);
+ }
+}
+
+static void BIT_VECTOR_del_words(wordptr addr, N_word total, N_word count,
+ boolean clear)
+{
+ N_word length;
+
+ if ((total > 0) and (count > 0))
+ {
+ if (count > total) count = total;
+ length = total - count;
+ if (length > 0) BIT_VECTOR_mov_words(addr,addr+count,length);
+ if (clear) BIT_VECTOR_zro_words(addr+length,count);
+ }
+}
+
+static void BIT_VECTOR_reverse(charptr string, N_word length)
+{
+ charptr last;
+ N_char temp;
+
+ if (length > 1)
+ {
+ last = string + length - 1;
+ while (string < last)
+ {
+ temp = *string;
+ *string = *last;
+ *last = temp;
+ string++;
+ last--;
+ }
+ }
+}
+
+static N_word BIT_VECTOR_int2str(charptr string, N_word value)
+{
+ N_word length;
+ N_word digit;
+ charptr work;
+
+ work = string;
+ if (value > 0)
+ {
+ length = 0;
+ while (value > 0)
+ {
+ BIT_VECTOR_DIGITIZE(N_word,value,digit)
+ *work++ = (N_char) digit;
+ length++;
+ }
+ BIT_VECTOR_reverse(string,length);
+ }
+ else
+ {
+ length = 1;
+ *work++ = (N_char) '0';
+ }
+ return(length);
+}
+
+static N_word BIT_VECTOR_str2int(charptr string, N_word *value)
+{
+ N_word length;
+ N_word digit;
+
+ *value = 0;
+ length = 0;
+ digit = (N_word) *string++;
+ /* separate because isdigit() is likely a macro! */
+ while (isdigit((int)digit) != 0)
+ {
+ length++;
+ digit -= (N_word) '0';
+ if (*value) *value *= 10;
+ *value += digit;
+ digit = (N_word) *string++;
+ }
+ return(length);
+}
+
+ /********************************************/
+ /* routine to convert error code to string: */
+ /********************************************/
+
+const char * BitVector_Error(ErrCode error)
+{
+ switch (error)
+ {
+ case ErrCode_Ok: return( NULL ); break;
+ case ErrCode_Type: return( ERRCODE_TYPE ); break;
+ case ErrCode_Bits: return( ERRCODE_BITS ); break;
+ case ErrCode_Word: return( ERRCODE_WORD ); break;
+ case ErrCode_Long: return( ERRCODE_LONG ); break;
+ case ErrCode_Powr: return( ERRCODE_POWR ); break;
+ case ErrCode_Loga: return( ERRCODE_LOGA ); break;
+ case ErrCode_Null: return( ERRCODE_NULL ); break;
+ case ErrCode_Indx: return( ERRCODE_INDX ); break;
+ case ErrCode_Ordr: return( ERRCODE_ORDR ); break;
+ case ErrCode_Size: return( ERRCODE_SIZE ); break;
+ case ErrCode_Pars: return( ERRCODE_PARS ); break;
+ case ErrCode_Ovfl: return( ERRCODE_OVFL ); break;
+ case ErrCode_Same: return( ERRCODE_SAME ); break;
+ case ErrCode_Expo: return( ERRCODE_EXPO ); break;
+ case ErrCode_Zero: return( ERRCODE_ZERO ); break;
+ default: return( ERRCODE_OOPS ); break;
+ }
+}
+
+ /*****************************************/
+ /* automatic self-configuration routine: */
+ /*****************************************/
+
+ /*******************************************************/
+ /* */
+ /* MUST be called once prior to any other function */
+ /* to initialize the machine dependent constants */
+ /* of this package! (But call only ONCE, or you */
+ /* will suffer memory leaks!) */
+ /* */
+ /*******************************************************/
+
+ErrCode BitVector_Boot(void)
+{
+ N_long longsample = 1L;
+ N_word sample = LSB;
+ N_word lsb;
+
+ if (sizeof(N_word) > sizeof(size_t)) return(ErrCode_Type);
+
+ BITS = 1;
+ while (sample <<= 1) BITS++; /* determine # of bits in a machine word */
+
+ if (BITS != (sizeof(N_word) << 3)) return(ErrCode_Bits);
+
+ if (BITS < 16) return(ErrCode_Word);
+
+ LONGBITS = 1;
+ while (longsample <<= 1) LONGBITS++; /* = # of bits in an unsigned long */
+
+ if (BITS > LONGBITS) return(ErrCode_Long);
+
+ LOGBITS = 0;
+ sample = BITS;
+ lsb = (sample AND LSB);
+ while ((sample >>= 1) and (not lsb))
+ {
+ LOGBITS++;
+ lsb = (sample AND LSB);
+ }
+
+ if (sample) return(ErrCode_Powr); /* # of bits is not a power of 2! */
+
+ if (BITS != (LSB << LOGBITS)) return(ErrCode_Loga);
+
+ MODMASK = BITS - 1;
+ FACTOR = LOGBITS - 3; /* ld(BITS / 8) = ld(BITS) - ld(8) = ld(BITS) - 3 */
+ MSB = (LSB << MODMASK);
+
+ BITMASKTAB = (wordptr) yasm_xmalloc((size_t) (BITS << FACTOR));
+
+ if (BITMASKTAB == NULL) return(ErrCode_Null);
+
+ for ( sample = 0; sample < BITS; sample++ )
+ {
+ BITMASKTAB[sample] = (LSB << sample);
+ }
+
+ LOG10 = (N_word) (MODMASK * 0.30103); /* = (BITS - 1) * ( ln 2 / ln 10 ) */
+ EXP10 = power10(LOG10);
+
+ return(ErrCode_Ok);
+}
+
+void BitVector_Shutdown(void)
+{
+ if (BITMASKTAB) yasm_xfree(BITMASKTAB);
+}
+
+N_word BitVector_Size(N_int bits) /* bit vector size (# of words) */
+{
+ N_word size;
+
+ size = bits >> LOGBITS;
+ if (bits AND MODMASK) size++;
+ return(size);
+}
+
+N_word BitVector_Mask(N_int bits) /* bit vector mask (unused bits) */
+{
+ N_word mask;
+
+ mask = bits AND MODMASK;
+ if (mask) mask = (N_word) ~(~0L << mask); else mask = (N_word) ~0L;
+ return(mask);
+}
+
+const char * BitVector_Version(void)
+{
+ return("6.4");
+}
+
+N_int BitVector_Word_Bits(void)
+{
+ return(BITS);
+}
+
+N_int BitVector_Long_Bits(void)
+{
+ return(LONGBITS);
+}
+
+/********************************************************************/
+/* */
+/* WARNING: Do not "free()" constant character strings, i.e., */
+/* don't call "BitVector_Dispose()" for strings returned */
+/* by "BitVector_Error()" or "BitVector_Version()"! */
+/* */
+/* ONLY call this function for strings allocated with "malloc()", */
+/* i.e., the strings returned by the functions "BitVector_to_*()" */
+/* and "BitVector_Block_Read()"! */
+/* */
+/********************************************************************/
+
+void BitVector_Dispose(charptr string) /* free string */
+{
+ if (string != NULL) yasm_xfree((voidptr) string);
+}
+
+void BitVector_Destroy(wordptr addr) /* free bitvec */
+{
+ if (addr != NULL)
+ {
+ addr -= BIT_VECTOR_HIDDEN_WORDS;
+ yasm_xfree((voidptr) addr);
+ }
+}
+
+void BitVector_Destroy_List(listptr list, N_int count) /* free list */
+{
+ listptr slot;
+
+ if (list != NULL)
+ {
+ slot = list;
+ while (count-- > 0)
+ {
+ BitVector_Destroy(*slot++);
+ }
+ free((voidptr) list);
+ }
+}
+
+wordptr BitVector_Create(N_int bits, boolean clear) /* malloc */
+{
+ N_word size;
+ N_word mask;
+ N_word bytes;
+ wordptr addr;
+ wordptr zero;
+
+ size = BitVector_Size(bits);
+ mask = BitVector_Mask(bits);
+ bytes = (size + BIT_VECTOR_HIDDEN_WORDS) << FACTOR;
+ addr = (wordptr) yasm_xmalloc((size_t) bytes);
+ if (addr != NULL)
+ {
+ *addr++ = bits;
+ *addr++ = size;
+ *addr++ = mask;
+ if (clear)
+ {
+ zero = addr;
+ BIT_VECTOR_ZERO_WORDS(zero,size)
+ }
+ }
+ return(addr);
+}
+
+listptr BitVector_Create_List(N_int bits, boolean clear, N_int count)
+{
+ listptr list = NULL;
+ listptr slot;
+ wordptr addr;
+ N_int i;
+
+ if (count > 0)
+ {
+ list = (listptr) malloc(sizeof(wordptr) * count);
+ if (list != NULL)
+ {
+ slot = list;
+ for ( i = 0; i < count; i++ )
+ {
+ addr = BitVector_Create(bits,clear);
+ if (addr == NULL)
+ {
+ BitVector_Destroy_List(list,i);
+ return(NULL);
+ }
+ *slot++ = addr;
+ }
+ }
+ }
+ return(list);
+}
+
+wordptr BitVector_Resize(wordptr oldaddr, N_int bits) /* realloc */
+{
+ N_word bytes;
+ N_word oldsize;
+ N_word oldmask;
+ N_word newsize;
+ N_word newmask;
+ wordptr newaddr;
+ wordptr source;
+ wordptr target;
+
+ oldsize = size_(oldaddr);
+ oldmask = mask_(oldaddr);
+ newsize = BitVector_Size(bits);
+ newmask = BitVector_Mask(bits);
+ if (oldsize > 0) *(oldaddr+oldsize-1) &= oldmask;
+ if (newsize <= oldsize)
+ {
+ newaddr = oldaddr;
+ bits_(newaddr) = bits;
+ size_(newaddr) = newsize;
+ mask_(newaddr) = newmask;
+ if (newsize > 0) *(newaddr+newsize-1) &= newmask;
+ }
+ else
+ {
+ bytes = (newsize + BIT_VECTOR_HIDDEN_WORDS) << FACTOR;
+ newaddr = (wordptr) yasm_xmalloc((size_t) bytes);
+ if (newaddr != NULL)
+ {
+ *newaddr++ = bits;
+ *newaddr++ = newsize;
+ *newaddr++ = newmask;
+ target = newaddr;
+ source = oldaddr;
+ newsize -= oldsize;
+ BIT_VECTOR_COPY_WORDS(target,source,oldsize)
+ BIT_VECTOR_ZERO_WORDS(target,newsize)
+ }
+ BitVector_Destroy(oldaddr);
+ }
+ return(newaddr);
+}
+
+wordptr BitVector_Shadow(wordptr addr) /* makes new, same size but empty */
+{
+ return( BitVector_Create(bits_(addr),true) );
+}
+
+wordptr BitVector_Clone(wordptr addr) /* makes exact duplicate */
+{
+ N_word bits;
+ wordptr twin;
+
+ bits = bits_(addr);
+ twin = BitVector_Create(bits,false);
+ if ((twin != NULL) and (bits > 0))
+ BIT_VECTOR_cpy_words(twin,addr,size_(addr));
+ return(twin);
+}
+
+wordptr BitVector_Concat(wordptr X, wordptr Y) /* returns concatenation */
+{
+ /* BEWARE that X = most significant part, Y = least significant part! */
+
+ N_word bitsX;
+ N_word bitsY;
+ N_word bitsZ;
+ wordptr Z;
+
+ bitsX = bits_(X);
+ bitsY = bits_(Y);
+ bitsZ = bitsX + bitsY;
+ Z = BitVector_Create(bitsZ,false);
+ if ((Z != NULL) and (bitsZ > 0))
+ {
+ BIT_VECTOR_cpy_words(Z,Y,size_(Y));
+ BitVector_Interval_Copy(Z,X,bitsY,0,bitsX);
+ *(Z+size_(Z)-1) &= mask_(Z);
+ }
+ return(Z);
+}
+
+void BitVector_Copy(wordptr X, wordptr Y) /* X = Y */
+{
+ N_word sizeX = size_(X);
+ N_word sizeY = size_(Y);
+ N_word maskX = mask_(X);
+ N_word maskY = mask_(Y);
+ N_word fill = 0;
+ wordptr lastX;
+ wordptr lastY;
+
+ if ((X != Y) and (sizeX > 0))
+ {
+ lastX = X + sizeX - 1;
+ if (sizeY > 0)
+ {
+ lastY = Y + sizeY - 1;
+ if ( (*lastY AND (maskY AND NOT (maskY >> 1))) == 0 ) *lastY &= maskY;
+ else
+ {
+ fill = (N_word) ~0L;
+ *lastY |= NOT maskY;
+ }
+ while ((sizeX > 0) and (sizeY > 0))
+ {
+ *X++ = *Y++;
+ sizeX--;
+ sizeY--;
+ }
+ *lastY &= maskY;
+ }
+ while (sizeX-- > 0) *X++ = fill;
+ *lastX &= maskX;
+ }
+}
+
+void BitVector_Empty(wordptr addr) /* X = {} clr all */
+{
+ N_word size = size_(addr);
+
+ BIT_VECTOR_ZERO_WORDS(addr,size)
+}
+
+void BitVector_Fill(wordptr addr) /* X = ~{} set all */
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word fill = (N_word) ~0L;
+
+ if (size > 0)
+ {
+ BIT_VECTOR_FILL_WORDS(addr,fill,size)
+ *(--addr) &= mask;
+ }
+}
+
+void BitVector_Flip(wordptr addr) /* X = ~X flip all */
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word flip = (N_word) ~0L;
+
+ if (size > 0)
+ {
+ BIT_VECTOR_FLIP_WORDS(addr,flip,size)
+ *(--addr) &= mask;
+ }
+}
+
+void BitVector_Primes(wordptr addr)
+{
+ N_word bits = bits_(addr);
+ N_word size = size_(addr);
+ wordptr work;
+ N_word temp;
+ N_word i,j;
+
+ if (size > 0)
+ {
+ temp = 0xAAAA;
+ i = BITS >> 4;
+ while (--i > 0)
+ {
+ temp <<= 16;
+ temp |= 0xAAAA;
+ }
+ i = size;
+ work = addr;
+ *work++ = temp XOR 0x0006;
+ while (--i > 0) *work++ = temp;
+ for ( i = 3; (j = i * i) < bits; i += 2 )
+ {
+ for ( ; j < bits; j += i ) BIT_VECTOR_CLR_BIT(addr,j)
+ }
+ *(addr+size-1) &= mask_(addr);
+ }
+}
+
+void BitVector_Reverse(wordptr X, wordptr Y)
+{
+ N_word bits = bits_(X);
+ N_word mask;
+ N_word bit;
+ N_word value;
+
+ if (bits > 0)
+ {
+ if (X == Y) BitVector_Interval_Reverse(X,0,bits-1);
+ else if (bits == bits_(Y))
+ {
+/* mask = mask_(Y); */
+/* mask &= NOT (mask >> 1); */
+ mask = BITMASKTAB[(bits-1) AND MODMASK];
+ Y += size_(Y) - 1;
+ value = 0;
+ bit = LSB;
+ while (bits-- > 0)
+ {
+ if ((*Y AND mask) != 0)
+ {
+ value |= bit;
+ }
+ if (not (mask >>= 1))
+ {
+ Y--;
+ mask = MSB;
+ }
+ if (not (bit <<= 1))
+ {
+ *X++ = value;
+ value = 0;
+ bit = LSB;
+ }
+ }
+ if (bit > LSB) *X = value;
+ }
+ }
+}
+
+void BitVector_Interval_Empty(wordptr addr, N_int lower, N_int upper)
+{ /* X = X \ [lower..upper] */
+ N_word bits = bits_(addr);
+ N_word size = size_(addr);
+ wordptr loaddr;
+ wordptr hiaddr;
+ N_word lobase;
+ N_word hibase;
+ N_word lomask;
+ N_word himask;
+ N_word diff;
+
+ if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
+ {
+ lobase = lower >> LOGBITS;
+ hibase = upper >> LOGBITS;
+ diff = hibase - lobase;
+ loaddr = addr + lobase;
+ hiaddr = addr + hibase;
+
+ lomask = (N_word) (~0L << (lower AND MODMASK));
+ himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
+
+ if (diff == 0)
+ {
+ *loaddr &= NOT (lomask AND himask);
+ }
+ else
+ {
+ *loaddr++ &= NOT lomask;
+ while (--diff > 0)
+ {
+ *loaddr++ = 0;
+ }
+ *hiaddr &= NOT himask;
+ }
+ }
+}
+
+void BitVector_Interval_Fill(wordptr addr, N_int lower, N_int upper)
+{ /* X = X + [lower..upper] */
+ N_word bits = bits_(addr);
+ N_word size = size_(addr);
+ N_word fill = (N_word) ~0L;
+ wordptr loaddr;
+ wordptr hiaddr;
+ N_word lobase;
+ N_word hibase;
+ N_word lomask;
+ N_word himask;
+ N_word diff;
+
+ if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
+ {
+ lobase = lower >> LOGBITS;
+ hibase = upper >> LOGBITS;
+ diff = hibase - lobase;
+ loaddr = addr + lobase;
+ hiaddr = addr + hibase;
+
+ lomask = (N_word) (~0L << (lower AND MODMASK));
+ himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
+
+ if (diff == 0)
+ {
+ *loaddr |= (lomask AND himask);
+ }
+ else
+ {
+ *loaddr++ |= lomask;
+ while (--diff > 0)
+ {
+ *loaddr++ = fill;
+ }
+ *hiaddr |= himask;
+ }
+ *(addr+size-1) &= mask_(addr);
+ }
+}
+
+void BitVector_Interval_Flip(wordptr addr, N_int lower, N_int upper)
+{ /* X = X ^ [lower..upper] */
+ N_word bits = bits_(addr);
+ N_word size = size_(addr);
+ N_word flip = (N_word) ~0L;
+ wordptr loaddr;
+ wordptr hiaddr;
+ N_word lobase;
+ N_word hibase;
+ N_word lomask;
+ N_word himask;
+ N_word diff;
+
+ if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
+ {
+ lobase = lower >> LOGBITS;
+ hibase = upper >> LOGBITS;
+ diff = hibase - lobase;
+ loaddr = addr + lobase;
+ hiaddr = addr + hibase;
+
+ lomask = (N_word) (~0L << (lower AND MODMASK));
+ himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
+
+ if (diff == 0)
+ {
+ *loaddr ^= (lomask AND himask);
+ }
+ else
+ {
+ *loaddr++ ^= lomask;
+ while (--diff > 0)
+ {
+ *loaddr++ ^= flip;
+ }
+ *hiaddr ^= himask;
+ }
+ *(addr+size-1) &= mask_(addr);
+ }
+}
+
+void BitVector_Interval_Reverse(wordptr addr, N_int lower, N_int upper)
+{
+ N_word bits = bits_(addr);
+ wordptr loaddr;
+ wordptr hiaddr;
+ N_word lomask;
+ N_word himask;
+
+ if ((bits > 0) and (lower < bits) and (upper < bits) and (lower < upper))
+ {
+ loaddr = addr + (lower >> LOGBITS);
+ hiaddr = addr + (upper >> LOGBITS);
+ lomask = BITMASKTAB[lower AND MODMASK];
+ himask = BITMASKTAB[upper AND MODMASK];
+ for ( bits = upper - lower + 1; bits > 1; bits -= 2 )
+ {
+ if (((*loaddr AND lomask) != 0) XOR ((*hiaddr AND himask) != 0))
+ {
+ *loaddr ^= lomask; /* swap bits only if they differ! */
+ *hiaddr ^= himask;
+ }
+ if (not (lomask <<= 1))
+ {
+ lomask = LSB;
+ loaddr++;
+ }
+ if (not (himask >>= 1))
+ {
+ himask = MSB;
+ hiaddr--;
+ }
+ }
+ }
+}
+
+boolean BitVector_interval_scan_inc(wordptr addr, N_int start,
+ N_intptr min, N_intptr max)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word offset;
+ N_word bitmask;
+ N_word value;
+ boolean empty;
+
+ if ((size == 0) or (start >= bits_(addr))) return(FALSE);
+
+ *min = start;
+ *max = start;
+
+ offset = start >> LOGBITS;
+
+ *(addr+size-1) &= mask;
+
+ addr += offset;
+ size -= offset;
+
+ bitmask = BITMASKTAB[start AND MODMASK];
+ mask = NOT (bitmask OR (bitmask - 1));
+
+ value = *addr++;
+ if ((value AND bitmask) == 0)
+ {
+ value &= mask;
+ if (value == 0)
+ {
+ offset++;
+ empty = TRUE;
+ while (empty and (--size > 0))
+ {
+ if ((value = *addr++)) empty = false; else offset++;
+ }
+ if (empty) return(FALSE);
+ }
+ start = offset << LOGBITS;
+ bitmask = LSB;
+ mask = value;
+ while (not (mask AND LSB))
+ {
+ bitmask <<= 1;
+ mask >>= 1;
+ start++;
+ }
+ mask = NOT (bitmask OR (bitmask - 1));
+ *min = start;
+ *max = start;
+ }
+ value = NOT value;
+ value &= mask;
+ if (value == 0)
+ {
+ offset++;
+ empty = TRUE;
+ while (empty and (--size > 0))
+ {
+ if ((value = NOT *addr++)) empty = false; else offset++;
+ }
+ if (empty) value = LSB;
+ }
+ start = offset << LOGBITS;
+ while (not (value AND LSB))
+ {
+ value >>= 1;
+ start++;
+ }
+ *max = --start;
+ return(TRUE);
+}
+
+boolean BitVector_interval_scan_dec(wordptr addr, N_int start,
+ N_intptr min, N_intptr max)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word offset;
+ N_word bitmask;
+ N_word value;
+ boolean empty;
+
+ if ((size == 0) or (start >= bits_(addr))) return(FALSE);
+
+ *min = start;
+ *max = start;
+
+ offset = start >> LOGBITS;
+
+ if (offset >= size) return(FALSE);
+
+ *(addr+size-1) &= mask;
+
+ addr += offset;
+ size = ++offset;
+
+ bitmask = BITMASKTAB[start AND MODMASK];
+ mask = (bitmask - 1);
+
+ value = *addr--;
+ if ((value AND bitmask) == 0)
+ {
+ value &= mask;
+ if (value == 0)
+ {
+ offset--;
+ empty = TRUE;
+ while (empty and (--size > 0))
+ {
+ if ((value = *addr--)) empty = false; else offset--;
+ }
+ if (empty) return(FALSE);
+ }
+ start = offset << LOGBITS;
+ bitmask = MSB;
+ mask = value;
+ while (not (mask AND MSB))
+ {
+ bitmask >>= 1;
+ mask <<= 1;
+ start--;
+ }
+ mask = (bitmask - 1);
+ *max = --start;
+ *min = start;
+ }
+ value = NOT value;
+ value &= mask;
+ if (value == 0)
+ {
+ offset--;
+ empty = TRUE;
+ while (empty and (--size > 0))
+ {
+ if ((value = NOT *addr--)) empty = false; else offset--;
+ }
+ if (empty) value = MSB;
+ }
+ start = offset << LOGBITS;
+ while (not (value AND MSB))
+ {
+ value <<= 1;
+ start--;
+ }
+ *min = start;
+ return(TRUE);
+}
+
+void BitVector_Interval_Copy(wordptr X, wordptr Y, N_int Xoffset,
+ N_int Yoffset, N_int length)
+{
+ N_word bitsX = bits_(X);
+ N_word bitsY = bits_(Y);
+ N_word source = 0; /* silence compiler warning */
+ N_word target = 0; /* silence compiler warning */
+ N_word s_lo_base;
+ N_word s_hi_base;
+ N_word s_lo_bit;
+ N_word s_hi_bit;
+ N_word s_base;
+ N_word s_lower = 0; /* silence compiler warning */
+ N_word s_upper = 0; /* silence compiler warning */
+ N_word s_bits;
+ N_word s_min;
+ N_word s_max;
+ N_word t_lo_base;
+ N_word t_hi_base;
+ N_word t_lo_bit;
+ N_word t_hi_bit;
+ N_word t_base;
+ N_word t_lower = 0; /* silence compiler warning */
+ N_word t_upper = 0; /* silence compiler warning */
+ N_word t_bits;
+ N_word t_min;
+ N_word mask;
+ N_word bits;
+ N_word sel;
+ boolean ascending;
+ boolean notfirst;
+ wordptr Z = X;
+
+ if ((length > 0) and (Xoffset < bitsX) and (Yoffset < bitsY))
+ {
+ if ((Xoffset + length) > bitsX) length = bitsX - Xoffset;
+ if ((Yoffset + length) > bitsY) length = bitsY - Yoffset;
+
+ ascending = (Xoffset <= Yoffset);
+
+ s_lo_base = Yoffset >> LOGBITS;
+ s_lo_bit = Yoffset AND MODMASK;
+ Yoffset += --length;
+ s_hi_base = Yoffset >> LOGBITS;
+ s_hi_bit = Yoffset AND MODMASK;
+
+ t_lo_base = Xoffset >> LOGBITS;
+ t_lo_bit = Xoffset AND MODMASK;
+ Xoffset += length;
+ t_hi_base = Xoffset >> LOGBITS;
+ t_hi_bit = Xoffset AND MODMASK;
+
+ if (ascending)
+ {
+ s_base = s_lo_base;
+ t_base = t_lo_base;
+ }
+ else
+ {
+ s_base = s_hi_base;
+ t_base = t_hi_base;
+ }
+ s_bits = 0;
+ t_bits = 0;
+ Y += s_base;
+ X += t_base;
+ notfirst = FALSE;
+ while (TRUE)
+ {
+ if (t_bits == 0)
+ {
+ if (notfirst)
+ {
+ *X = target;
+ if (ascending)
+ {
+ if (t_base == t_hi_base) break;
+ t_base++;
+ X++;
+ }
+ else
+ {
+ if (t_base == t_lo_base) break;
+ t_base--;
+ X--;
+ }
+ }
+ sel = ((t_base == t_hi_base) << 1) OR (t_base == t_lo_base);
+ switch (sel)
+ {
+ case 0:
+ t_lower = 0;
+ t_upper = BITS - 1;
+ t_bits = BITS;
+ target = 0;
+ break;
+ case 1:
+ t_lower = t_lo_bit;
+ t_upper = BITS - 1;
+ t_bits = BITS - t_lo_bit;
+ mask = (N_word) (~0L << t_lower);
+ target = *X AND NOT mask;
+ break;
+ case 2:
+ t_lower = 0;
+ t_upper = t_hi_bit;
+ t_bits = t_hi_bit + 1;
+ mask = (N_word) ((~0L << t_upper) << 1);
+ target = *X AND mask;
+ break;
+ case 3:
+ t_lower = t_lo_bit;
+ t_upper = t_hi_bit;
+ t_bits = t_hi_bit - t_lo_bit + 1;
+ mask = (N_word) (~0L << t_lower);
+ mask &= (N_word) ~((~0L << t_upper) << 1);
+ target = *X AND NOT mask;
+ break;
+ }
+ }
+ if (s_bits == 0)
+ {
+ if (notfirst)
+ {
+ if (ascending)
+ {
+ if (s_base == s_hi_base) break;
+ s_base++;
+ Y++;
+ }
+ else
+ {
+ if (s_base == s_lo_base) break;
+ s_base--;
+ Y--;
+ }
+ }
+ source = *Y;
+ sel = ((s_base == s_hi_base) << 1) OR (s_base == s_lo_base);
+ switch (sel)
+ {
+ case 0:
+ s_lower = 0;
+ s_upper = BITS - 1;
+ s_bits = BITS;
+ break;
+ case 1:
+ s_lower = s_lo_bit;
+ s_upper = BITS - 1;
+ s_bits = BITS - s_lo_bit;
+ break;
+ case 2:
+ s_lower = 0;
+ s_upper = s_hi_bit;
+ s_bits = s_hi_bit + 1;
+ break;
+ case 3:
+ s_lower = s_lo_bit;
+ s_upper = s_hi_bit;
+ s_bits = s_hi_bit - s_lo_bit + 1;
+ break;
+ }
+ }
+ notfirst = TRUE;
+ if (s_bits > t_bits)
+ {
+ bits = t_bits - 1;
+ if (ascending)
+ {
+ s_min = s_lower;
+ s_max = s_lower + bits;
+ }
+ else
+ {
+ s_max = s_upper;
+ s_min = s_upper - bits;
+ }
+ t_min = t_lower;
+ }
+ else
+ {
+ bits = s_bits - 1;
+ if (ascending) t_min = t_lower;
+ else t_min = t_upper - bits;
+ s_min = s_lower;
+ s_max = s_upper;
+ }
+ bits++;
+ mask = (N_word) (~0L << s_min);
+ mask &= (N_word) ~((~0L << s_max) << 1);
+ if (s_min == t_min) target |= (source AND mask);
+ else
+ {
+ if (s_min < t_min) target |= (source AND mask) << (t_min-s_min);
+ else target |= (source AND mask) >> (s_min-t_min);
+ }
+ if (ascending)
+ {
+ s_lower += bits;
+ t_lower += bits;
+ }
+ else
+ {
+ s_upper -= bits;
+ t_upper -= bits;
+ }
+ s_bits -= bits;
+ t_bits -= bits;
+ }
+ *(Z+size_(Z)-1) &= mask_(Z);
+ }
+}
+
+
+wordptr BitVector_Interval_Substitute(wordptr X, wordptr Y,
+ N_int Xoffset, N_int Xlength,
+ N_int Yoffset, N_int Ylength)
+{
+ N_word Xbits = bits_(X);
+ N_word Ybits = bits_(Y);
+ N_word limit;
+ N_word diff;
+
+ if ((Xoffset <= Xbits) and (Yoffset <= Ybits))
+ {
+ limit = Xoffset + Xlength;
+ if (limit > Xbits)
+ {
+ limit = Xbits;
+ Xlength = Xbits - Xoffset;
+ }
+ if ((Yoffset + Ylength) > Ybits)
+ {
+ Ylength = Ybits - Yoffset;
+ }
+ if (Xlength == Ylength)
+ {
+ if ((Ylength > 0) and ((X != Y) or (Xoffset != Yoffset)))
+ {
+ BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+ }
+ }
+ else /* Xlength != Ylength */
+ {
+ if (Xlength > Ylength)
+ {
+ diff = Xlength - Ylength;
+ if (Ylength > 0) BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+ if (limit < Xbits) BitVector_Delete(X,Xoffset+Ylength,diff,FALSE);
+ if ((X = BitVector_Resize(X,Xbits-diff)) == NULL) return(NULL);
+ }
+ else /* Ylength > Xlength ==> Ylength > 0 */
+ {
+ diff = Ylength - Xlength;
+ if (X != Y)
+ {
+ if ((X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL);
+ if (limit < Xbits) BitVector_Insert(X,limit,diff,FALSE);
+ BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+ }
+ else /* in-place */
+ {
+ if ((Y = X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL);
+ if (limit >= Xbits)
+ {
+ BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+ }
+ else /* limit < Xbits */
+ {
+ BitVector_Insert(X,limit,diff,FALSE);
+ if ((Yoffset+Ylength) <= limit)
+ {
+ BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+ }
+ else /* overlaps or lies above critical area */
+ {
+ if (limit <= Yoffset)
+ {
+ Yoffset += diff;
+ BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+ }
+ else /* Yoffset < limit */
+ {
+ Xlength = limit - Yoffset;
+ BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Xlength);
+ Yoffset = Xoffset + Ylength; /* = limit + diff */
+ Xoffset += Xlength;
+ Ylength -= Xlength;
+ BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return(X);
+}
+
+boolean BitVector_is_empty(wordptr addr) /* X == {} ? */
+{
+ N_word size = size_(addr);
+ boolean r = TRUE;
+
+ if (size > 0)
+ {
+ *(addr+size-1) &= mask_(addr);
+ while (r and (size-- > 0)) r = ( *addr++ == 0 );
+ }
+ return(r);
+}
+
+boolean BitVector_is_full(wordptr addr) /* X == ~{} ? */
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ boolean r = FALSE;
+ wordptr last;
+
+ if (size > 0)
+ {
+ r = TRUE;
+ last = addr + size - 1;
+ *last |= NOT mask;
+ while (r and (size-- > 0)) r = ( NOT *addr++ == 0 );
+ *last &= mask;
+ }
+ return(r);
+}
+
+boolean BitVector_equal(wordptr X, wordptr Y) /* X == Y ? */
+{
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+ boolean r = FALSE;
+
+ if (bits_(X) == bits_(Y))
+ {
+ r = TRUE;
+ if (size > 0)
+ {
+ *(X+size-1) &= mask;
+ *(Y+size-1) &= mask;
+ while (r and (size-- > 0)) r = (*X++ == *Y++);
+ }
+ }
+ return(r);
+}
+
+Z_int BitVector_Lexicompare(wordptr X, wordptr Y) /* X <,=,> Y ? */
+{ /* unsigned */
+ N_word bitsX = bits_(X);
+ N_word bitsY = bits_(Y);
+ N_word size = size_(X);
+ boolean r = TRUE;
+
+ if (bitsX == bitsY)
+ {
+ if (size > 0)
+ {
+ X += size;
+ Y += size;
+ while (r and (size-- > 0)) r = (*(--X) == *(--Y));
+ }
+ if (r) return((Z_int) 0);
+ else
+ {
+ if (*X < *Y) return((Z_int) -1); else return((Z_int) 1);
+ }
+ }
+ else
+ {
+ if (bitsX < bitsY) return((Z_int) -1); else return((Z_int) 1);
+ }
+}
+
+Z_int BitVector_Compare(wordptr X, wordptr Y) /* X <,=,> Y ? */
+{ /* signed */
+ N_word bitsX = bits_(X);
+ N_word bitsY = bits_(Y);
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+ N_word sign;
+ boolean r = TRUE;
+
+ if (bitsX == bitsY)
+ {
+ if (size > 0)
+ {
+ X += size;
+ Y += size;
+ mask &= NOT (mask >> 1);
+ if ((sign = (*(X-1) AND mask)) != (*(Y-1) AND mask))
+ {
+ if (sign) return((Z_int) -1); else return((Z_int) 1);
+ }
+ while (r and (size-- > 0)) r = (*(--X) == *(--Y));
+ }
+ if (r) return((Z_int) 0);
+ else
+ {
+ if (*X < *Y) return((Z_int) -1); else return((Z_int) 1);
+ }
+ }
+ else
+ {
+ if (bitsX < bitsY) return((Z_int) -1); else return((Z_int) 1);
+ }
+}
+
+charptr BitVector_to_Hex(wordptr addr)
+{
+ N_word bits = bits_(addr);
+ N_word size = size_(addr);
+ N_word value;
+ N_word count;
+ N_word digit;
+ N_word length;
+ charptr string;
+
+ length = bits >> 2;
+ if (bits AND 0x0003) length++;
+ string = (charptr) yasm_xmalloc((size_t) (length+1));
+ if (string == NULL) return(NULL);
+ string += length;
+ *string = (N_char) '\0';
+ if (size > 0)
+ {
+ *(addr+size-1) &= mask_(addr);
+ while ((size-- > 0) and (length > 0))
+ {
+ value = *addr++;
+ count = BITS >> 2;
+ while ((count-- > 0) and (length > 0))
+ {
+ digit = value AND 0x000F;
+ if (digit > 9) digit += (N_word) 'A' - 10;
+ else digit += (N_word) '0';
+ *(--string) = (N_char) digit; length--;
+ if ((count > 0) and (length > 0)) value >>= 4;
+ }
+ }
+ }
+ return(string);
+}
+
+ErrCode BitVector_from_Hex(wordptr addr, charptr string)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ boolean ok = TRUE;
+ size_t length;
+ N_word value;
+ N_word count;
+ int digit;
+
+ if (size > 0)
+ {
+ length = strlen((char *) string);
+ string += length;
+ while (size-- > 0)
+ {
+ value = 0;
+ for ( count = 0; (ok and (length > 0) and (count < BITS)); count += 4 )
+ {
+ digit = (int) *(--string); length--;
+ /* separate because toupper() is likely a macro! */
+ digit = toupper(digit);
+ if (digit == '_')
+ count -= 4;
+ else if ((ok = (isxdigit(digit) != 0)))
+ {
+ if (digit >= (int) 'A') digit -= (int) 'A' - 10;
+ else digit -= (int) '0';
+ value |= (((N_word) digit) << count);
+ }
+ }
+ *addr++ = value;
+ }
+ *(--addr) &= mask;
+ }
+ if (ok) return(ErrCode_Ok);
+ else return(ErrCode_Pars);
+}
+
+ErrCode BitVector_from_Oct(wordptr addr, charptr string)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ boolean ok = TRUE;
+ size_t length;
+ N_word value;
+ N_word value_fill = 0;
+ N_word count;
+ Z_word count_fill = 0;
+ int digit = 0;
+
+ if (size > 0)
+ {
+ length = strlen((char *) string);
+ string += length;
+ while (size-- > 0)
+ {
+ value = value_fill;
+ for ( count = count_fill; (ok and (length > 0) and (count < BITS)); count += 3 )
+ {
+ digit = (int) *(--string); length--;
+ if (digit == '_')
+ count -= 3;
+ else if ((ok = (isdigit(digit) && digit != '8' && digit != '9')) != 0)
+ {
+ digit -= (int) '0';
+ value |= (((N_word) digit) << count);
+ }
+ }
+ count_fill = (Z_word)count-(Z_word)BITS;
+ if (count_fill > 0)
+ value_fill = (((N_word) digit) >> (3-count_fill));
+ else
+ value_fill = 0;
+ *addr++ = value;
+ }
+ *(--addr) &= mask;
+ }
+ if (ok) return(ErrCode_Ok);
+ else return(ErrCode_Pars);
+}
+
+charptr BitVector_to_Bin(wordptr addr)
+{
+ N_word size = size_(addr);
+ N_word value;
+ N_word count;
+ N_word digit;
+ N_word length;
+ charptr string;
+
+ length = bits_(addr);
+ string = (charptr) yasm_xmalloc((size_t) (length+1));
+ if (string == NULL) return(NULL);
+ string += length;
+ *string = (N_char) '\0';
+ if (size > 0)
+ {
+ *(addr+size-1) &= mask_(addr);
+ while (size-- > 0)
+ {
+ value = *addr++;
+ count = BITS;
+ if (count > length) count = length;
+ while (count-- > 0)
+ {
+ digit = value AND 0x0001;
+ digit += (N_word) '0';
+ *(--string) = (N_char) digit; length--;
+ if (count > 0) value >>= 1;
+ }
+ }
+ }
+ return(string);
+}
+
+ErrCode BitVector_from_Bin(wordptr addr, charptr string)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ boolean ok = TRUE;
+ size_t length;
+ N_word value;
+ N_word count;
+ int digit;
+
+ if (size > 0)
+ {
+ length = strlen((char *) string);
+ string += length;
+ while (size-- > 0)
+ {
+ value = 0;
+ for ( count = 0; (ok and (length > 0) and (count < BITS)); count++ )
+ {
+ digit = (int) *(--string); length--;
+ switch (digit)
+ {
+ case (int) '0':
+ break;
+ case (int) '1':
+ value |= BITMASKTAB[count];
+ break;
+ case (int) '_':
+ count--;
+ break;
+ default:
+ ok = FALSE;
+ break;
+ }
+ }
+ *addr++ = value;
+ }
+ *(--addr) &= mask;
+ }
+ if (ok) return(ErrCode_Ok);
+ else return(ErrCode_Pars);
+}
+
+charptr BitVector_to_Dec(wordptr addr)
+{
+ N_word bits = bits_(addr);
+ N_word length;
+ N_word digits;
+ N_word count;
+ N_word q;
+ N_word r;
+ boolean loop;
+ charptr result;
+ charptr string;
+ wordptr quot;
+ wordptr rest;
+ wordptr temp;
+ wordptr base;
+ Z_int sign;
+
+ length = (N_word) (bits / 3.3); /* digits = bits * ln(2) / ln(10) */
+ length += 2; /* compensate for truncating & provide space for minus sign */
+ result = (charptr) yasm_xmalloc((size_t) (length+1)); /* remember the '\0'! */
+ if (result == NULL) return(NULL);
+ string = result;
+ sign = BitVector_Sign(addr);
+ if ((bits < 4) or (sign == 0))
+ {
+ if (bits > 0) digits = *addr; else digits = (N_word) 0;
+ if (sign < 0) digits = ((N_word)(-((Z_word)digits))) AND mask_(addr);
+ *string++ = (N_char) digits + (N_char) '0';
+ digits = 1;
+ }
+ else
+ {
+ quot = BitVector_Create(bits,FALSE);
+ if (quot == NULL)
+ {
+ BitVector_Dispose(result);
+ return(NULL);
+ }
+ rest = BitVector_Create(bits,FALSE);
+ if (rest == NULL)
+ {
+ BitVector_Dispose(result);
+ BitVector_Destroy(quot);
+ return(NULL);
+ }
+ temp = BitVector_Create(bits,FALSE);
+ if (temp == NULL)
+ {
+ BitVector_Dispose(result);
+ BitVector_Destroy(quot);
+ BitVector_Destroy(rest);
+ return(NULL);
+ }
+ base = BitVector_Create(bits,TRUE);
+ if (base == NULL)
+ {
+ BitVector_Dispose(result);
+ BitVector_Destroy(quot);
+ BitVector_Destroy(rest);
+ BitVector_Destroy(temp);
+ return(NULL);
+ }
+ if (sign < 0) BitVector_Negate(quot,addr);
+ else BitVector_Copy(quot,addr);
+ digits = 0;
+ *base = EXP10;
+ loop = (bits >= BITS);
+ do
+ {
+ if (loop)
+ {
+ BitVector_Copy(temp,quot);
+ if (BitVector_Div_Pos(quot,temp,base,rest))
+ {
+ BitVector_Dispose(result); /* emergency exit */
+ BitVector_Destroy(quot);
+ BitVector_Destroy(rest); /* should never occur */
+ BitVector_Destroy(temp); /* under normal operation */
+ BitVector_Destroy(base);
+ return(NULL);
+ }
+ loop = not BitVector_is_empty(quot);
+ q = *rest;
+ }
+ else q = *quot;
+ count = LOG10;
+ while (((loop and (count-- > 0)) or ((not loop) and (q != 0))) and
+ (digits < length))
+ {
+ if (q != 0)
+ {
+ BIT_VECTOR_DIGITIZE(N_word,q,r)
+ }
+ else r = (N_word) '0';
+ *string++ = (N_char) r;
+ digits++;
+ }
+ }
+ while (loop and (digits < length));
+ BitVector_Destroy(quot);
+ BitVector_Destroy(rest);
+ BitVector_Destroy(temp);
+ BitVector_Destroy(base);
+ }
+ if ((sign < 0) and (digits < length))
+ {
+ *string++ = (N_char) '-';
+ digits++;
+ }
+ *string = (N_char) '\0';
+ BIT_VECTOR_reverse(result,digits);
+ return(result);
+}
+
+struct BitVector_from_Dec_static_data {
+ wordptr term;
+ wordptr base;
+ wordptr prod;
+ wordptr rank;
+ wordptr temp;
+};
+
+BitVector_from_Dec_static_data *BitVector_from_Dec_static_Boot(N_word bits)
+{
+ BitVector_from_Dec_static_data *data;
+
+ data = yasm_xmalloc(sizeof(BitVector_from_Dec_static_data));
+
+ if (bits > 0)
+ {
+ data->term = BitVector_Create(BITS,FALSE);
+ data->base = BitVector_Create(BITS,FALSE);
+ data->prod = BitVector_Create(bits,FALSE);
+ data->rank = BitVector_Create(bits,FALSE);
+ data->temp = BitVector_Create(bits,FALSE);
+ } else {
+ data->term = NULL;
+ data->base = NULL;
+ data->prod = NULL;
+ data->rank = NULL;
+ data->temp = NULL;
+ }
+ return data;
+}
+
+void BitVector_from_Dec_static_Shutdown(BitVector_from_Dec_static_data *data)
+{
+ if (data) {
+ BitVector_Destroy(data->term);
+ BitVector_Destroy(data->base);
+ BitVector_Destroy(data->prod);
+ BitVector_Destroy(data->rank);
+ BitVector_Destroy(data->temp);
+ }
+ yasm_xfree(data);
+}
+
+ErrCode BitVector_from_Dec_static(BitVector_from_Dec_static_data *data,
+ wordptr addr, charptr string)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bits = bits_(addr);
+ N_word mask = mask_(addr);
+ boolean init = (bits > BITS);
+ boolean minus;
+ boolean shift;
+ boolean carry;
+ wordptr term;
+ wordptr base;
+ wordptr prod;
+ wordptr rank;
+ wordptr temp;
+ N_word accu;
+ N_word powr;
+ N_word count;
+ size_t length;
+ int digit;
+
+ if (bits > 0)
+ {
+ term = data->term;
+ base = data->base;
+ prod = data->prod;
+ rank = data->rank;
+ temp = data->temp;
+
+ length = strlen((char *) string);
+ if (length == 0) return(ErrCode_Pars);
+ digit = (int) *string;
+ if ((minus = (digit == (int) '-')) or
+ (digit == (int) '+'))
+ {
+ string++;
+ if (--length == 0) return(ErrCode_Pars);
+ }
+ string += length;
+ if (init)
+ {
+ BitVector_Empty(prod);
+ BitVector_Empty(rank);
+ }
+ BitVector_Empty(addr);
+ *base = EXP10;
+ shift = FALSE;
+ while ((not error) and (length > 0))
+ {
+ accu = 0;
+ powr = 1;
+ count = LOG10;
+ while ((not error) and (length > 0) and (count-- > 0))
+ {
+ digit = (int) *(--string); length--;
+ /* separate because isdigit() is likely a macro! */
+ if (isdigit(digit) != 0)
+ {
+ accu += ((N_word) digit - (N_word) '0') * powr;
+ powr *= 10;
+ }
+ else error = ErrCode_Pars;
+ }
+ if (not error)
+ {
+ if (shift)
+ {
+ *term = accu;
+ BitVector_Copy(temp,rank);
+ error = BitVector_Mul_Pos(prod,temp,term,FALSE);
+ }
+ else
+ {
+ *prod = accu;
+ if ((not init) and ((accu AND NOT mask) != 0)) error = ErrCode_Ovfl;
+ }
+ if (not error)
+ {
+ carry = FALSE;
+ BitVector_compute(addr,addr,prod,FALSE,&carry);
+ /* ignores sign change (= overflow) but not */
+ /* numbers too large (= carry) for resulting bit vector */
+ if (carry) error = ErrCode_Ovfl;
+ else
+ {
+ if (length > 0)
+ {
+ if (shift)
+ {
+ BitVector_Copy(temp,rank);
+ error = BitVector_Mul_Pos(rank,temp,base,FALSE);
+ }
+ else
+ {
+ *rank = *base;
+ shift = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (not error and minus)
+ {
+ BitVector_Negate(addr,addr);
+ if ((*(addr + size_(addr) - 1) AND mask AND NOT (mask >> 1)) == 0)
+ error = ErrCode_Ovfl;
+ }
+ }
+ return(error);
+}
+
+ErrCode BitVector_from_Dec(wordptr addr, charptr string)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bits = bits_(addr);
+ N_word mask = mask_(addr);
+ boolean init = (bits > BITS);
+ boolean minus;
+ boolean shift;
+ boolean carry;
+ wordptr term;
+ wordptr base;
+ wordptr prod;
+ wordptr rank;
+ wordptr temp;
+ N_word accu;
+ N_word powr;
+ N_word count;
+ size_t length;
+ int digit;
+
+ if (bits > 0)
+ {
+ length = strlen((char *) string);
+ if (length == 0) return(ErrCode_Pars);
+ digit = (int) *string;
+ if ((minus = (digit == (int) '-')) or
+ (digit == (int) '+'))
+ {
+ string++;
+ if (--length == 0) return(ErrCode_Pars);
+ }
+ string += length;
+ term = BitVector_Create(BITS,FALSE);
+ if (term == NULL)
+ {
+ return(ErrCode_Null);
+ }
+ base = BitVector_Create(BITS,FALSE);
+ if (base == NULL)
+ {
+ BitVector_Destroy(term);
+ return(ErrCode_Null);
+ }
+ prod = BitVector_Create(bits,init);
+ if (prod == NULL)
+ {
+ BitVector_Destroy(term);
+ BitVector_Destroy(base);
+ return(ErrCode_Null);
+ }
+ rank = BitVector_Create(bits,init);
+ if (rank == NULL)
+ {
+ BitVector_Destroy(term);
+ BitVector_Destroy(base);
+ BitVector_Destroy(prod);
+ return(ErrCode_Null);
+ }
+ temp = BitVector_Create(bits,FALSE);
+ if (temp == NULL)
+ {
+ BitVector_Destroy(term);
+ BitVector_Destroy(base);
+ BitVector_Destroy(prod);
+ BitVector_Destroy(rank);
+ return(ErrCode_Null);
+ }
+ BitVector_Empty(addr);
+ *base = EXP10;
+ shift = FALSE;
+ while ((not error) and (length > 0))
+ {
+ accu = 0;
+ powr = 1;
+ count = LOG10;
+ while ((not error) and (length > 0) and (count-- > 0))
+ {
+ digit = (int) *(--string); length--;
+ /* separate because isdigit() is likely a macro! */
+ if (isdigit(digit) != 0)
+ {
+ accu += ((N_word) digit - (N_word) '0') * powr;
+ powr *= 10;
+ }
+ else error = ErrCode_Pars;
+ }
+ if (not error)
+ {
+ if (shift)
+ {
+ *term = accu;
+ BitVector_Copy(temp,rank);
+ error = BitVector_Mul_Pos(prod,temp,term,FALSE);
+ }
+ else
+ {
+ *prod = accu;
+ if ((not init) and ((accu AND NOT mask) != 0)) error = ErrCode_Ovfl;
+ }
+ if (not error)
+ {
+ carry = FALSE;
+ BitVector_compute(addr,addr,prod,FALSE,&carry);
+ /* ignores sign change (= overflow) but not */
+ /* numbers too large (= carry) for resulting bit vector */
+ if (carry) error = ErrCode_Ovfl;
+ else
+ {
+ if (length > 0)
+ {
+ if (shift)
+ {
+ BitVector_Copy(temp,rank);
+ error = BitVector_Mul_Pos(rank,temp,base,FALSE);
+ }
+ else
+ {
+ *rank = *base;
+ shift = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ BitVector_Destroy(term);
+ BitVector_Destroy(base);
+ BitVector_Destroy(prod);
+ BitVector_Destroy(rank);
+ BitVector_Destroy(temp);
+ if (not error and minus)
+ {
+ BitVector_Negate(addr,addr);
+ if ((*(addr + size_(addr) - 1) AND mask AND NOT (mask >> 1)) == 0)
+ error = ErrCode_Ovfl;
+ }
+ }
+ return(error);
+}
+
+charptr BitVector_to_Enum(wordptr addr)
+{
+ N_word bits = bits_(addr);
+ N_word sample;
+ N_word length;
+ N_word digits;
+ N_word factor;
+ N_word power;
+ N_word start;
+ N_word min;
+ N_word max;
+ charptr string;
+ charptr target;
+ boolean comma;
+
+ if (bits > 0)
+ {
+ sample = bits - 1; /* greatest possible index */
+ length = 2; /* account for index 0 and terminating '\0' */
+ digits = 1; /* account for intervening dashes and commas */
+ factor = 1;
+ power = 10;
+ while (sample >= (power-1))
+ {
+ length += ++digits * factor * 6; /* 9,90,900,9000,... (9*2/3 = 6) */
+ factor = power;
+ power *= 10;
+ }
+ if (sample > --factor)
+ {
+ sample -= factor;
+ factor = (N_word) ( sample / 3 );
+ factor = (factor << 1) + (sample - (factor * 3));
+ length += ++digits * factor;
+ }
+ }
+ else length = 1;
+ string = (charptr) yasm_xmalloc((size_t) length);
+ if (string == NULL) return(NULL);
+ start = 0;
+ comma = FALSE;
+ target = string;
+ while ((start < bits) and BitVector_interval_scan_inc(addr,start,&min,&max))
+ {
+ start = max + 2;
+ if (comma) *target++ = (N_char) ',';
+ if (min == max)
+ {
+ target += BIT_VECTOR_int2str(target,min);
+ }
+ else
+ {
+ if (min+1 == max)
+ {
+ target += BIT_VECTOR_int2str(target,min);
+ *target++ = (N_char) ',';
+ target += BIT_VECTOR_int2str(target,max);
+ }
+ else
+ {
+ target += BIT_VECTOR_int2str(target,min);
+ *target++ = (N_char) '-';
+ target += BIT_VECTOR_int2str(target,max);
+ }
+ }
+ comma = TRUE;
+ }
+ *target = (N_char) '\0';
+ return(string);
+}
+
+ErrCode BitVector_from_Enum(wordptr addr, charptr string)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bits = bits_(addr);
+ N_word state = 1;
+ N_word token;
+ N_word indx = 0; /* silence compiler warning */
+ N_word start = 0; /* silence compiler warning */
+
+ if (bits > 0)
+ {
+ BitVector_Empty(addr);
+ while ((not error) and (state != 0))
+ {
+ token = (N_word) *string;
+ /* separate because isdigit() is likely a macro! */
+ if (isdigit((int)token) != 0)
+ {
+ string += BIT_VECTOR_str2int(string,&indx);
+ if (indx < bits) token = (N_word) '0';
+ else error = ErrCode_Indx;
+ }
+ else string++;
+ if (not error)
+ switch (state)
+ {
+ case 1:
+ switch (token)
+ {
+ case (N_word) '0':
+ state = 2;
+ break;
+ case (N_word) '\0':
+ state = 0;
+ break;
+ default:
+ error = ErrCode_Pars;
+ break;
+ }
+ break;
+ case 2:
+ switch (token)
+ {
+ case (N_word) '-':
+ start = indx;
+ state = 3;
+ break;
+ case (N_word) ',':
+ BIT_VECTOR_SET_BIT(addr,indx)
+ state = 5;
+ break;
+ case (N_word) '\0':
+ BIT_VECTOR_SET_BIT(addr,indx)
+ state = 0;
+ break;
+ default:
+ error = ErrCode_Pars;
+ break;
+ }
+ break;
+ case 3:
+ switch (token)
+ {
+ case (N_word) '0':
+ if (start < indx)
+ BitVector_Interval_Fill(addr,start,indx);
+ else if (start == indx)
+ BIT_VECTOR_SET_BIT(addr,indx)
+ else error = ErrCode_Ordr;
+ state = 4;
+ break;
+ default:
+ error = ErrCode_Pars;
+ break;
+ }
+ break;
+ case 4:
+ switch (token)
+ {
+ case (N_word) ',':
+ state = 5;
+ break;
+ case (N_word) '\0':
+ state = 0;
+ break;
+ default:
+ error = ErrCode_Pars;
+ break;
+ }
+ break;
+ case 5:
+ switch (token)
+ {
+ case (N_word) '0':
+ state = 2;
+ break;
+ default:
+ error = ErrCode_Pars;
+ break;
+ }
+ break;
+ }
+ }
+ }
+ return(error);
+}
+
+void BitVector_Bit_Off(wordptr addr, N_int indx) /* X = X \ {x} */
+{
+ if (indx < bits_(addr)) BIT_VECTOR_CLR_BIT(addr,indx)
+}
+
+void BitVector_Bit_On(wordptr addr, N_int indx) /* X = X + {x} */
+{
+ if (indx < bits_(addr)) BIT_VECTOR_SET_BIT(addr,indx)
+}
+
+boolean BitVector_bit_flip(wordptr addr, N_int indx) /* X=(X+{x})\(X*{x}) */
+{
+ N_word mask;
+
+ if (indx < bits_(addr)) return( BIT_VECTOR_FLP_BIT(addr,indx,mask) );
+ else return( FALSE );
+}
+
+boolean BitVector_bit_test(wordptr addr, N_int indx) /* {x} in X ? */
+{
+ if (indx < bits_(addr)) return( BIT_VECTOR_TST_BIT(addr,indx) );
+ else return( FALSE );
+}
+
+void BitVector_Bit_Copy(wordptr addr, N_int indx, boolean bit)
+{
+ if (indx < bits_(addr))
+ {
+ if (bit) BIT_VECTOR_SET_BIT(addr,indx)
+ else BIT_VECTOR_CLR_BIT(addr,indx)
+ }
+}
+
+void BitVector_LSB(wordptr addr, boolean bit)
+{
+ if (bits_(addr) > 0)
+ {
+ if (bit) *addr |= LSB;
+ else *addr &= NOT LSB;
+ }
+}
+
+void BitVector_MSB(wordptr addr, boolean bit)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+
+ if (size-- > 0)
+ {
+ if (bit) *(addr+size) |= mask AND NOT (mask >> 1);
+ else *(addr+size) &= NOT mask OR (mask >> 1);
+ }
+}
+
+boolean BitVector_lsb_(wordptr addr)
+{
+ if (size_(addr) > 0) return( (*addr AND LSB) != 0 );
+ else return( FALSE );
+}
+
+boolean BitVector_msb_(wordptr addr)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+
+ if (size-- > 0)
+ return( (*(addr+size) AND (mask AND NOT (mask >> 1))) != 0 );
+ else
+ return( FALSE );
+}
+
+boolean BitVector_rotate_left(wordptr addr)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word msb;
+ boolean carry_in;
+ boolean carry_out = FALSE;
+
+ if (size > 0)
+ {
+ msb = mask AND NOT (mask >> 1);
+ carry_in = ((*(addr+size-1) AND msb) != 0);
+ while (size-- > 1)
+ {
+ carry_out = ((*addr AND MSB) != 0);
+ *addr <<= 1;
+ if (carry_in) *addr |= LSB;
+ carry_in = carry_out;
+ addr++;
+ }
+ carry_out = ((*addr AND msb) != 0);
+ *addr <<= 1;
+ if (carry_in) *addr |= LSB;
+ *addr &= mask;
+ }
+ return(carry_out);
+}
+
+boolean BitVector_rotate_right(wordptr addr)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word msb;
+ boolean carry_in;
+ boolean carry_out = FALSE;
+
+ if (size > 0)
+ {
+ msb = mask AND NOT (mask >> 1);
+ carry_in = ((*addr AND LSB) != 0);
+ addr += size-1;
+ *addr &= mask;
+ carry_out = ((*addr AND LSB) != 0);
+ *addr >>= 1;
+ if (carry_in) *addr |= msb;
+ carry_in = carry_out;
+ addr--;
+ size--;
+ while (size-- > 0)
+ {
+ carry_out = ((*addr AND LSB) != 0);
+ *addr >>= 1;
+ if (carry_in) *addr |= MSB;
+ carry_in = carry_out;
+ addr--;
+ }
+ }
+ return(carry_out);
+}
+
+boolean BitVector_shift_left(wordptr addr, boolean carry_in)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word msb;
+ boolean carry_out = carry_in;
+
+ if (size > 0)
+ {
+ msb = mask AND NOT (mask >> 1);
+ while (size-- > 1)
+ {
+ carry_out = ((*addr AND MSB) != 0);
+ *addr <<= 1;
+ if (carry_in) *addr |= LSB;
+ carry_in = carry_out;
+ addr++;
+ }
+ carry_out = ((*addr AND msb) != 0);
+ *addr <<= 1;
+ if (carry_in) *addr |= LSB;
+ *addr &= mask;
+ }
+ return(carry_out);
+}
+
+boolean BitVector_shift_right(wordptr addr, boolean carry_in)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word msb;
+ boolean carry_out = carry_in;
+
+ if (size > 0)
+ {
+ msb = mask AND NOT (mask >> 1);
+ addr += size-1;
+ *addr &= mask;
+ carry_out = ((*addr AND LSB) != 0);
+ *addr >>= 1;
+ if (carry_in) *addr |= msb;
+ carry_in = carry_out;
+ addr--;
+ size--;
+ while (size-- > 0)
+ {
+ carry_out = ((*addr AND LSB) != 0);
+ *addr >>= 1;
+ if (carry_in) *addr |= MSB;
+ carry_in = carry_out;
+ addr--;
+ }
+ }
+ return(carry_out);
+}
+
+void BitVector_Move_Left(wordptr addr, N_int bits)
+{
+ N_word count;
+ N_word words;
+
+ if (bits > 0)
+ {
+ count = bits AND MODMASK;
+ words = bits >> LOGBITS;
+ if (bits >= bits_(addr)) BitVector_Empty(addr);
+ else
+ {
+ while (count-- > 0) BitVector_shift_left(addr,0);
+ BitVector_Word_Insert(addr,0,words,TRUE);
+ }
+ }
+}
+
+void BitVector_Move_Right(wordptr addr, N_int bits)
+{
+ N_word count;
+ N_word words;
+
+ if (bits > 0)
+ {
+ count = bits AND MODMASK;
+ words = bits >> LOGBITS;
+ if (bits >= bits_(addr)) BitVector_Empty(addr);
+ else
+ {
+ while (count-- > 0) BitVector_shift_right(addr,0);
+ BitVector_Word_Delete(addr,0,words,TRUE);
+ }
+ }
+}
+
+void BitVector_Insert(wordptr addr, N_int offset, N_int count, boolean clear)
+{
+ N_word bits = bits_(addr);
+ N_word last;
+
+ if ((count > 0) and (offset < bits))
+ {
+ last = offset + count;
+ if (last < bits)
+ {
+ BitVector_Interval_Copy(addr,addr,last,offset,(bits-last));
+ }
+ else last = bits;
+ if (clear) BitVector_Interval_Empty(addr,offset,(last-1));
+ }
+}
+
+void BitVector_Delete(wordptr addr, N_int offset, N_int count, boolean clear)
+{
+ N_word bits = bits_(addr);
+ N_word last;
+
+ if ((count > 0) and (offset < bits))
+ {
+ last = offset + count;
+ if (last < bits)
+ {
+ BitVector_Interval_Copy(addr,addr,offset,last,(bits-last));
+ }
+ else count = bits - offset;
+ if (clear) BitVector_Interval_Empty(addr,(bits-count),(bits-1));
+ }
+}
+
+boolean BitVector_increment(wordptr addr) /* X++ */
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ wordptr last = addr + size - 1;
+ boolean carry = TRUE;
+
+ if (size > 0)
+ {
+ *last |= NOT mask;
+ while (carry and (size-- > 0))
+ {
+ carry = (++(*addr++) == 0);
+ }
+ *last &= mask;
+ }
+ return(carry);
+}
+
+boolean BitVector_decrement(wordptr addr) /* X-- */
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ wordptr last = addr + size - 1;
+ boolean carry = TRUE;
+
+ if (size > 0)
+ {
+ *last &= mask;
+ while (carry and (size-- > 0))
+ {
+ carry = (*addr == 0);
+ --(*addr++);
+ }
+ *last &= mask;
+ }
+ return(carry);
+}
+
+boolean BitVector_compute(wordptr X, wordptr Y, wordptr Z, boolean minus, boolean *carry)
+{
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+ N_word vv = 0;
+ N_word cc;
+ N_word mm;
+ N_word yy;
+ N_word zz;
+ N_word lo;
+ N_word hi;
+
+ if (size > 0)
+ {
+ if (minus) cc = (*carry == 0);
+ else cc = (*carry != 0);
+ /* deal with (size-1) least significant full words first: */
+ while (--size > 0)
+ {
+ yy = *Y++;
+ if (minus) zz = (N_word) NOT ( Z ? *Z++ : 0 );
+ else zz = (N_word) ( Z ? *Z++ : 0 );
+ lo = (yy AND LSB) + (zz AND LSB) + cc;
+ hi = (yy >> 1) + (zz >> 1) + (lo >> 1);
+ cc = ((hi AND MSB) != 0);
+ *X++ = (hi << 1) OR (lo AND LSB);
+ }
+ /* deal with most significant word (may be used only partially): */
+ yy = *Y AND mask;
+ if (minus) zz = (N_word) NOT ( Z ? *Z : 0 );
+ else zz = (N_word) ( Z ? *Z : 0 );
+ zz &= mask;
+ if (mask == LSB) /* special case, only one bit used */
+ {
+ vv = cc;
+ lo = yy + zz + cc;
+ cc = (lo >> 1);
+ vv ^= cc;
+ *X = lo AND LSB;
+ }
+ else
+ {
+ if (NOT mask) /* not all bits are used, but more than one */
+ {
+ mm = (mask >> 1);
+ vv = (yy AND mm) + (zz AND mm) + cc;
+ mm = mask AND NOT mm;
+ lo = yy + zz + cc;
+ cc = (lo >> 1);
+ vv ^= cc;
+ vv &= mm;
+ cc &= mm;
+ *X = lo AND mask;
+ }
+ else /* other special case, all bits are used */
+ {
+ mm = NOT MSB;
+ lo = (yy AND mm) + (zz AND mm) + cc;
+ vv = lo AND MSB;
+ hi = ((yy AND MSB) >> 1) + ((zz AND MSB) >> 1) + (vv >> 1);
+ cc = hi AND MSB;
+ vv ^= cc;
+ *X = (hi << 1) OR (lo AND mm);
+ }
+ }
+ if (minus) *carry = (cc == 0);
+ else *carry = (cc != 0);
+ }
+ return(vv != 0);
+}
+
+boolean BitVector_add(wordptr X, wordptr Y, wordptr Z, boolean *carry)
+{
+ return(BitVector_compute(X,Y,Z,FALSE,carry));
+}
+
+boolean BitVector_sub(wordptr X, wordptr Y, wordptr Z, boolean *carry)
+{
+ return(BitVector_compute(X,Y,Z,TRUE,carry));
+}
+
+boolean BitVector_inc(wordptr X, wordptr Y)
+{
+ boolean carry = TRUE;
+
+ return(BitVector_compute(X,Y,NULL,FALSE,&carry));
+}
+
+boolean BitVector_dec(wordptr X, wordptr Y)
+{
+ boolean carry = TRUE;
+
+ return(BitVector_compute(X,Y,NULL,TRUE,&carry));
+}
+
+void BitVector_Negate(wordptr X, wordptr Y)
+{
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+ boolean carry = TRUE;
+
+ if (size > 0)
+ {
+ while (size-- > 0)
+ {
+ *X = NOT *Y++;
+ if (carry)
+ {
+ carry = (++(*X) == 0);
+ }
+ X++;
+ }
+ *(--X) &= mask;
+ }
+}
+
+void BitVector_Absolute(wordptr X, wordptr Y)
+{
+ N_word size = size_(Y);
+ N_word mask = mask_(Y);
+
+ if (size > 0)
+ {
+ if (*(Y+size-1) AND (mask AND NOT (mask >> 1))) BitVector_Negate(X,Y);
+ else BitVector_Copy(X,Y);
+ }
+}
+
+Z_int BitVector_Sign(wordptr addr)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ wordptr last = addr + size - 1;
+ boolean r = TRUE;
+
+ if (size > 0)
+ {
+ *last &= mask;
+ while (r and (size-- > 0)) r = ( *addr++ == 0 );
+ }
+ if (r) return((Z_int) 0);
+ else
+ {
+ if (*last AND (mask AND NOT (mask >> 1))) return((Z_int) -1);
+ else return((Z_int) 1);
+ }
+}
+
+ErrCode BitVector_Mul_Pos(wordptr X, wordptr Y, wordptr Z, boolean strict)
+{
+ N_word mask;
+ N_word limit;
+ N_word count;
+ Z_long last;
+ wordptr sign;
+ boolean carry;
+ boolean overflow;
+ boolean ok = TRUE;
+
+ /*
+ Requirements:
+ - X, Y and Z must be distinct
+ - X and Y must have equal sizes (whereas Z may be any size!)
+ - Z should always contain the SMALLER of the two factors Y and Z
+ Constraints:
+ - The contents of Y (and of X, of course) are destroyed
+ (only Z is preserved!)
+ */
+
+ if ((X == Y) or (X == Z) or (Y == Z)) return(ErrCode_Same);
+ if (bits_(X) != bits_(Y)) return(ErrCode_Size);
+ BitVector_Empty(X);
+ if (BitVector_is_empty(Y)) return(ErrCode_Ok); /* exit also taken if bits_(Y)==0 */
+ if ((last = Set_Max(Z)) < 0L) return(ErrCode_Ok);
+ limit = (N_word) last;
+ sign = Y + size_(Y) - 1;
+ mask = mask_(Y);
+ *sign &= mask;
+ mask &= NOT (mask >> 1);
+ for ( count = 0; (ok and (count <= limit)); count++ )
+ {
+ if ( BIT_VECTOR_TST_BIT(Z,count) )
+ {
+ carry = false;
+ overflow = BitVector_compute(X,X,Y,false,&carry);
+ if (strict) ok = not (carry or overflow);
+ else ok = not carry;
+ }
+ if (ok and (count < limit))
+ {
+ carry = BitVector_shift_left(Y,0);
+ if (strict)
+ {
+ overflow = ((*sign AND mask) != 0);
+ ok = not (carry or overflow);
+ }
+ else ok = not carry;
+ }
+ }
+ if (ok) return(ErrCode_Ok); else return(ErrCode_Ovfl);
+}
+
+ErrCode BitVector_Multiply(wordptr X, wordptr Y, wordptr Z)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bit_x = bits_(X);
+ N_word bit_y = bits_(Y);
+ N_word bit_z = bits_(Z);
+ N_word size;
+ N_word mask;
+ N_word msb;
+ wordptr ptr_y;
+ wordptr ptr_z;
+ boolean sgn_x;
+ boolean sgn_y;
+ boolean sgn_z;
+ boolean zero;
+ wordptr A;
+ wordptr B;
+
+ /*
+ Requirements:
+ - Y and Z must have equal sizes
+ - X must have at least the same size as Y and Z but may be larger (!)
+ Features:
+ - The contents of Y and Z are preserved
+ - X may be identical with Y or Z (or both!)
+ (in-place multiplication is possible!)
+ */
+
+ if ((bit_y != bit_z) or (bit_x < bit_y)) return(ErrCode_Size);
+ if (BitVector_is_empty(Y) or BitVector_is_empty(Z))
+ {
+ BitVector_Empty(X);
+ }
+ else
+ {
+ A = BitVector_Create(bit_y,FALSE);
+ if (A == NULL) return(ErrCode_Null);
+ B = BitVector_Create(bit_z,FALSE);
+ if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
+ size = size_(Y);
+ mask = mask_(Y);
+ msb = (mask AND NOT (mask >> 1));
+ sgn_y = (((*(Y+size-1) &= mask) AND msb) != 0);
+ sgn_z = (((*(Z+size-1) &= mask) AND msb) != 0);
+ sgn_x = sgn_y XOR sgn_z;
+ if (sgn_y) BitVector_Negate(A,Y); else BitVector_Copy(A,Y);
+ if (sgn_z) BitVector_Negate(B,Z); else BitVector_Copy(B,Z);
+ ptr_y = A + size;
+ ptr_z = B + size;
+ zero = TRUE;
+ while (zero and (size-- > 0))
+ {
+ zero &= (*(--ptr_y) == 0);
+ zero &= (*(--ptr_z) == 0);
+ }
+ if (*ptr_y > *ptr_z)
+ {
+ if (bit_x > bit_y)
+ {
+ A = BitVector_Resize(A,bit_x);
+ if (A == NULL) { BitVector_Destroy(B); return(ErrCode_Null); }
+ }
+ error = BitVector_Mul_Pos(X,A,B,TRUE);
+ }
+ else
+ {
+ if (bit_x > bit_z)
+ {
+ B = BitVector_Resize(B,bit_x);
+ if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
+ }
+ error = BitVector_Mul_Pos(X,B,A,TRUE);
+ }
+ if ((not error) and sgn_x) BitVector_Negate(X,X);
+ BitVector_Destroy(A);
+ BitVector_Destroy(B);
+ }
+ return(error);
+}
+
+ErrCode BitVector_Div_Pos(wordptr Q, wordptr X, wordptr Y, wordptr R)
+{
+ N_word bits = bits_(Q);
+ N_word mask;
+ wordptr addr;
+ Z_long last;
+ boolean flag;
+ boolean copy = FALSE; /* flags whether valid rest is in R (0) or X (1) */
+
+ /*
+ Requirements:
+ - All bit vectors must have equal sizes
+ - Q, X, Y and R must all be distinct bit vectors
+ - Y must be non-zero (of course!)
+ Constraints:
+ - The contents of X (and Q and R, of course) are destroyed
+ (only Y is preserved!)
+ */
+
+ if ((bits != bits_(X)) or (bits != bits_(Y)) or (bits != bits_(R)))
+ return(ErrCode_Size);
+ if ((Q == X) or (Q == Y) or (Q == R) or (X == Y) or (X == R) or (Y == R))
+ return(ErrCode_Same);
+ if (BitVector_is_empty(Y))
+ return(ErrCode_Zero);
+
+ BitVector_Empty(R);
+ BitVector_Copy(Q,X);
+ if ((last = Set_Max(Q)) < 0L) return(ErrCode_Ok);
+ bits = (N_word) ++last;
+ while (bits-- > 0)
+ {
+ addr = Q + (bits >> LOGBITS);
+ mask = BITMASKTAB[bits AND MODMASK];
+ flag = ((*addr AND mask) != 0);
+ if (copy)
+ {
+ BitVector_shift_left(X,flag);
+ flag = FALSE;
+ BitVector_compute(R,X,Y,TRUE,&flag);
+ }
+ else
+ {
+ BitVector_shift_left(R,flag);
+ flag = FALSE;
+ BitVector_compute(X,R,Y,TRUE,&flag);
+ }
+ if (flag) *addr &= NOT mask;
+ else
+ {
+ *addr |= mask;
+ copy = not copy;
+ }
+ }
+ if (copy) BitVector_Copy(R,X);
+ return(ErrCode_Ok);
+}
+
+ErrCode BitVector_Divide(wordptr Q, wordptr X, wordptr Y, wordptr R)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bits = bits_(Q);
+ N_word size = size_(Q);
+ N_word mask = mask_(Q);
+ N_word msb = (mask AND NOT (mask >> 1));
+ boolean sgn_q;
+ boolean sgn_x;
+ boolean sgn_y;
+ wordptr A;
+ wordptr B;
+
+ /*
+ Requirements:
+ - All bit vectors must have equal sizes
+ - Q and R must be two distinct bit vectors
+ - Y must be non-zero (of course!)
+ Features:
+ - The contents of X and Y are preserved
+ - Q may be identical with X or Y (or both)
+ (in-place division is possible!)
+ - R may be identical with X or Y (or both)
+ (but not identical with Q!)
+ */
+
+ if ((bits != bits_(X)) or (bits != bits_(Y)) or (bits != bits_(R)))
+ return(ErrCode_Size);
+ if (Q == R)
+ return(ErrCode_Same);
+ if (BitVector_is_empty(Y))
+ return(ErrCode_Zero);
+
+ if (BitVector_is_empty(X))
+ {
+ BitVector_Empty(Q);
+ BitVector_Empty(R);
+ }
+ else
+ {
+ A = BitVector_Create(bits,FALSE);
+ if (A == NULL) return(ErrCode_Null);
+ B = BitVector_Create(bits,FALSE);
+ if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
+ size--;
+ sgn_x = (((*(X+size) &= mask) AND msb) != 0);
+ sgn_y = (((*(Y+size) &= mask) AND msb) != 0);
+ sgn_q = sgn_x XOR sgn_y;
+ if (sgn_x) BitVector_Negate(A,X); else BitVector_Copy(A,X);
+ if (sgn_y) BitVector_Negate(B,Y); else BitVector_Copy(B,Y);
+ if (not (error = BitVector_Div_Pos(Q,A,B,R)))
+ {
+ if (sgn_q) BitVector_Negate(Q,Q);
+ if (sgn_x) BitVector_Negate(R,R);
+ }
+ BitVector_Destroy(A);
+ BitVector_Destroy(B);
+ }
+ return(error);
+}
+
+ErrCode BitVector_GCD(wordptr X, wordptr Y, wordptr Z)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bits = bits_(X);
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+ N_word msb = (mask AND NOT (mask >> 1));
+ boolean sgn_a;
+ boolean sgn_b;
+ boolean sgn_r;
+ wordptr Q;
+ wordptr R;
+ wordptr A;
+ wordptr B;
+ wordptr T;
+
+ /*
+ Requirements:
+ - All bit vectors must have equal sizes
+ Features:
+ - The contents of Y and Z are preserved
+ - X may be identical with Y or Z (or both)
+ (in-place is possible!)
+ - GCD(0,z) == GCD(z,0) == z
+ - negative values are handled correctly
+ */
+
+ if ((bits != bits_(Y)) or (bits != bits_(Z))) return(ErrCode_Size);
+ if (BitVector_is_empty(Y))
+ {
+ if (X != Z) BitVector_Copy(X,Z);
+ return(ErrCode_Ok);
+ }
+ if (BitVector_is_empty(Z))
+ {
+ if (X != Y) BitVector_Copy(X,Y);
+ return(ErrCode_Ok);
+ }
+ Q = BitVector_Create(bits,false);
+ if (Q == NULL)
+ {
+ return(ErrCode_Null);
+ }
+ R = BitVector_Create(bits,FALSE);
+ if (R == NULL)
+ {
+ BitVector_Destroy(Q);
+ return(ErrCode_Null);
+ }
+ A = BitVector_Create(bits,FALSE);
+ if (A == NULL)
+ {
+ BitVector_Destroy(Q);
+ BitVector_Destroy(R);
+ return(ErrCode_Null);
+ }
+ B = BitVector_Create(bits,FALSE);
+ if (B == NULL)
+ {
+ BitVector_Destroy(Q);
+ BitVector_Destroy(R);
+ BitVector_Destroy(A);
+ return(ErrCode_Null);
+ }
+ size--;
+ sgn_a = (((*(Y+size) &= mask) AND msb) != 0);
+ sgn_b = (((*(Z+size) &= mask) AND msb) != 0);
+ if (sgn_a) BitVector_Negate(A,Y); else BitVector_Copy(A,Y);
+ if (sgn_b) BitVector_Negate(B,Z); else BitVector_Copy(B,Z);
+ while (not error)
+ {
+ if (not (error = BitVector_Div_Pos(Q,A,B,R)))
+ {
+ if (BitVector_is_empty(R)) break;
+ T = A; sgn_r = sgn_a;
+ A = B; sgn_a = sgn_b;
+ B = R; sgn_b = sgn_r;
+ R = T;
+ }
+ }
+ if (not error)
+ {
+ if (sgn_b) BitVector_Negate(X,B); else BitVector_Copy(X,B);
+ }
+ BitVector_Destroy(Q);
+ BitVector_Destroy(R);
+ BitVector_Destroy(A);
+ BitVector_Destroy(B);
+ return(error);
+}
+
+ErrCode BitVector_GCD2(wordptr U, wordptr V, wordptr W, wordptr X, wordptr Y)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bits = bits_(U);
+ N_word size = size_(U);
+ N_word mask = mask_(U);
+ N_word msb = (mask AND NOT (mask >> 1));
+ boolean minus;
+ boolean carry;
+ boolean sgn_q;
+ boolean sgn_r;
+ boolean sgn_a;
+ boolean sgn_b;
+ boolean sgn_x;
+ boolean sgn_y;
+ listptr L;
+ wordptr Q;
+ wordptr R;
+ wordptr A;
+ wordptr B;
+ wordptr T;
+ wordptr X1;
+ wordptr X2;
+ wordptr X3;
+ wordptr Y1;
+ wordptr Y2;
+ wordptr Y3;
+ wordptr Z;
+
+ /*
+ Requirements:
+ - All bit vectors must have equal sizes
+ - U, V, and W must all be distinct bit vectors
+ Features:
+ - The contents of X and Y are preserved
+ - U, V and W may be identical with X or Y (or both,
+ provided that U, V and W are mutually distinct)
+ (i.e., in-place is possible!)
+ - GCD(0,z) == GCD(z,0) == z
+ - negative values are handled correctly
+ */
+
+ if ((bits != bits_(V)) or
+ (bits != bits_(W)) or
+ (bits != bits_(X)) or
+ (bits != bits_(Y)))
+ {
+ return(ErrCode_Size);
+ }
+ if ((U == V) or (U == W) or (V == W))
+ {
+ return(ErrCode_Same);
+ }
+ if (BitVector_is_empty(X))
+ {
+ if (U != Y) BitVector_Copy(U,Y);
+ BitVector_Empty(V);
+ BitVector_Empty(W);
+ *W = 1;
+ return(ErrCode_Ok);
+ }
+ if (BitVector_is_empty(Y))
+ {
+ if (U != X) BitVector_Copy(U,X);
+ BitVector_Empty(V);
+ BitVector_Empty(W);
+ *V = 1;
+ return(ErrCode_Ok);
+ }
+ if ((L = BitVector_Create_List(bits,false,11)) == NULL)
+ {
+ return(ErrCode_Null);
+ }
+ Q = L[0];
+ R = L[1];
+ A = L[2];
+ B = L[3];
+ X1 = L[4];
+ X2 = L[5];
+ X3 = L[6];
+ Y1 = L[7];
+ Y2 = L[8];
+ Y3 = L[9];
+ Z = L[10];
+ size--;
+ sgn_a = (((*(X+size) &= mask) AND msb) != 0);
+ sgn_b = (((*(Y+size) &= mask) AND msb) != 0);
+ if (sgn_a) BitVector_Negate(A,X); else BitVector_Copy(A,X);
+ if (sgn_b) BitVector_Negate(B,Y); else BitVector_Copy(B,Y);
+ BitVector_Empty(X1);
+ BitVector_Empty(X2);
+ *X1 = 1;
+ BitVector_Empty(Y1);
+ BitVector_Empty(Y2);
+ *Y2 = 1;
+ sgn_x = false;
+ sgn_y = false;
+ while (not error)
+ {
+ if ((error = BitVector_Div_Pos(Q,A,B,R)))
+ {
+ break;
+ }
+ if (BitVector_is_empty(R))
+ {
+ break;
+ }
+ sgn_q = sgn_a XOR sgn_b;
+
+ if (sgn_x) BitVector_Negate(Z,X2); else BitVector_Copy(Z,X2);
+ if ((error = BitVector_Mul_Pos(X3,Z,Q,true)))
+ {
+ break;
+ }
+ minus = not (sgn_x XOR sgn_q);
+ carry = 0;
+ if (BitVector_compute(X3,X1,X3,minus,&carry))
+ {
+ error = ErrCode_Ovfl;
+ break;
+ }
+ sgn_x = (((*(X3+size) &= mask) AND msb) != 0);
+
+ if (sgn_y) BitVector_Negate(Z,Y2); else BitVector_Copy(Z,Y2);
+ if ((error = BitVector_Mul_Pos(Y3,Z,Q,true)))
+ {
+ break;
+ }
+ minus = not (sgn_y XOR sgn_q);
+ carry = 0;
+ if (BitVector_compute(Y3,Y1,Y3,minus,&carry))
+ {
+ error = ErrCode_Ovfl;
+ break;
+ }
+ sgn_y = (((*(Y3+size) &= mask) AND msb) != 0);
+
+ T = A; sgn_r = sgn_a;
+ A = B; sgn_a = sgn_b;
+ B = R; sgn_b = sgn_r;
+ R = T;
+
+ T = X1;
+ X1 = X2;
+ X2 = X3;
+ X3 = T;
+
+ T = Y1;
+ Y1 = Y2;
+ Y2 = Y3;
+ Y3 = T;
+ }
+ if (not error)
+ {
+ if (sgn_b) BitVector_Negate(U,B); else BitVector_Copy(U,B);
+ BitVector_Copy(V,X2);
+ BitVector_Copy(W,Y2);
+ }
+ BitVector_Destroy_List(L,11);
+ return(error);
+}
+
+ErrCode BitVector_Power(wordptr X, wordptr Y, wordptr Z)
+{
+ ErrCode error = ErrCode_Ok;
+ N_word bits = bits_(X);
+ boolean first = TRUE;
+ Z_long last;
+ N_word limit;
+ N_word count;
+ wordptr T;
+
+ /*
+ Requirements:
+ - X must have at least the same size as Y but may be larger (!)
+ - X may not be identical with Z
+ - Z must be positive
+ Features:
+ - The contents of Y and Z are preserved
+ */
+
+ if (X == Z) return(ErrCode_Same);
+ if (bits < bits_(Y)) return(ErrCode_Size);
+ if (BitVector_msb_(Z)) return(ErrCode_Expo);
+ if ((last = Set_Max(Z)) < 0L)
+ {
+ if (bits < 2) return(ErrCode_Ovfl);
+ BitVector_Empty(X);
+ *X |= LSB;
+ return(ErrCode_Ok); /* anything ^ 0 == 1 */
+ }
+ if (BitVector_is_empty(Y))
+ {
+ if (X != Y) BitVector_Empty(X);
+ return(ErrCode_Ok); /* 0 ^ anything not zero == 0 */
+ }
+ T = BitVector_Create(bits,FALSE);
+ if (T == NULL) return(ErrCode_Null);
+ limit = (N_word) last;
+ for ( count = 0; ((!error) and (count <= limit)); count++ )
+ {
+ if ( BIT_VECTOR_TST_BIT(Z,count) )
+ {
+ if (first)
+ {
+ first = FALSE;
+ if (count) { BitVector_Copy(X,T); }
+ else { if (X != Y) BitVector_Copy(X,Y); }
+ }
+ else error = BitVector_Multiply(X,T,X); /* order important because T > X */
+ }
+ if ((!error) and (count < limit))
+ {
+ if (count) error = BitVector_Multiply(T,T,T);
+ else error = BitVector_Multiply(T,Y,Y);
+ }
+ }
+ BitVector_Destroy(T);
+ return(error);
+}
+
+void BitVector_Block_Store(wordptr addr, charptr buffer, N_int length)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ N_word value;
+ N_word count;
+
+ /* provide translation for independence of endian-ness: */
+ if (size > 0)
+ {
+ while (size-- > 0)
+ {
+ value = 0;
+ for ( count = 0; (length > 0) and (count < BITS); count += 8 )
+ {
+ value |= (((N_word) *buffer++) << count); length--;
+ }
+ *addr++ = value;
+ }
+ *(--addr) &= mask;
+ }
+}
+
+charptr BitVector_Block_Read(wordptr addr, N_intptr length)
+{
+ N_word size = size_(addr);
+ N_word value;
+ N_word count;
+ charptr buffer;
+ charptr target;
+
+ /* provide translation for independence of endian-ness: */
+ *length = size << FACTOR;
+ buffer = (charptr) yasm_xmalloc((size_t) ((*length)+1));
+ if (buffer == NULL) return(NULL);
+ target = buffer;
+ if (size > 0)
+ {
+ *(addr+size-1) &= mask_(addr);
+ while (size-- > 0)
+ {
+ value = *addr++;
+ count = BITS >> 3;
+ while (count-- > 0)
+ {
+ *target++ = (N_char) (value AND 0x00FF);
+ if (count > 0) value >>= 8;
+ }
+ }
+ }
+ *target = (N_char) '\0';
+ return(buffer);
+}
+
+void BitVector_Word_Store(wordptr addr, N_int offset, N_int value)
+{
+ N_word size = size_(addr);
+
+ if (size > 0)
+ {
+ if (offset < size) *(addr+offset) = value;
+ *(addr+size-1) &= mask_(addr);
+ }
+}
+
+N_int BitVector_Word_Read(wordptr addr, N_int offset)
+{
+ N_word size = size_(addr);
+
+ if (size > 0)
+ {
+ *(addr+size-1) &= mask_(addr);
+ if (offset < size) return( *(addr+offset) );
+ }
+ return( (N_int) 0 );
+}
+
+void BitVector_Word_Insert(wordptr addr, N_int offset, N_int count,
+ boolean clear)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ wordptr last = addr+size-1;
+
+ if (size > 0)
+ {
+ *last &= mask;
+ if (offset > size) offset = size;
+ BIT_VECTOR_ins_words(addr+offset,size-offset,count,clear);
+ *last &= mask;
+ }
+}
+
+void BitVector_Word_Delete(wordptr addr, N_int offset, N_int count,
+ boolean clear)
+{
+ N_word size = size_(addr);
+ N_word mask = mask_(addr);
+ wordptr last = addr+size-1;
+
+ if (size > 0)
+ {
+ *last &= mask;
+ if (offset > size) offset = size;
+ BIT_VECTOR_del_words(addr+offset,size-offset,count,clear);
+ *last &= mask;
+ }
+}
+
+void BitVector_Chunk_Store(wordptr addr, N_int chunksize, N_int offset,
+ N_long value)
+{
+ N_word bits = bits_(addr);
+ N_word mask;
+ N_word temp;
+
+ if ((chunksize > 0) and (offset < bits))
+ {
+ if (chunksize > LONGBITS) chunksize = LONGBITS;
+ if ((offset + chunksize) > bits) chunksize = bits - offset;
+ addr += offset >> LOGBITS;
+ offset &= MODMASK;
+ while (chunksize > 0)
+ {
+ mask = (N_word) (~0L << offset);
+ bits = offset + chunksize;
+ if (bits < BITS)
+ {
+ mask &= (N_word) ~(~0L << bits);
+ bits = chunksize;
+ }
+ else bits = BITS - offset;
+ temp = (N_word) (value << offset);
+ temp &= mask;
+ *addr &= NOT mask;
+ *addr++ |= temp;
+ value >>= bits;
+ chunksize -= bits;
+ offset = 0;
+ }
+ }
+}
+
+N_long BitVector_Chunk_Read(wordptr addr, N_int chunksize, N_int offset)
+{
+ N_word bits = bits_(addr);
+ N_word chunkbits = 0;
+ N_long value = 0L;
+ N_long temp;
+ N_word mask;
+
+ if ((chunksize > 0) and (offset < bits))
+ {
+ if (chunksize > LONGBITS) chunksize = LONGBITS;
+ if ((offset + chunksize) > bits) chunksize = bits - offset;
+ addr += offset >> LOGBITS;
+ offset &= MODMASK;
+ while (chunksize > 0)
+ {
+ bits = offset + chunksize;
+ if (bits < BITS)
+ {
+ mask = (N_word) ~(~0L << bits);
+ bits = chunksize;
+ }
+ else
+ {
+ mask = (N_word) ~0L;
+ bits = BITS - offset;
+ }
+ temp = (N_long) ((*addr++ AND mask) >> offset);
+ value |= temp << chunkbits;
+ chunkbits += bits;
+ chunksize -= bits;
+ offset = 0;
+ }
+ }
+ return(value);
+}
+
+ /*******************/
+ /* set operations: */
+ /*******************/
+
+void Set_Union(wordptr X, wordptr Y, wordptr Z) /* X = Y + Z */
+{
+ N_word bits = bits_(X);
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+
+ if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
+ {
+ while (size-- > 0) *X++ = *Y++ OR *Z++;
+ *(--X) &= mask;
+ }
+}
+
+void Set_Intersection(wordptr X, wordptr Y, wordptr Z) /* X = Y * Z */
+{
+ N_word bits = bits_(X);
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+
+ if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
+ {
+ while (size-- > 0) *X++ = *Y++ AND *Z++;
+ *(--X) &= mask;
+ }
+}
+
+void Set_Difference(wordptr X, wordptr Y, wordptr Z) /* X = Y \ Z */
+{
+ N_word bits = bits_(X);
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+
+ if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
+ {
+ while (size-- > 0) *X++ = *Y++ AND NOT *Z++;
+ *(--X) &= mask;
+ }
+}
+
+void Set_ExclusiveOr(wordptr X, wordptr Y, wordptr Z) /* X=(Y+Z)\(Y*Z) */
+{
+ N_word bits = bits_(X);
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+
+ if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
+ {
+ while (size-- > 0) *X++ = *Y++ XOR *Z++;
+ *(--X) &= mask;
+ }
+}
+
+void Set_Complement(wordptr X, wordptr Y) /* X = ~Y */
+{
+ N_word size = size_(X);
+ N_word mask = mask_(X);
+
+ if ((size > 0) and (bits_(X) == bits_(Y)))
+ {
+ while (size-- > 0) *X++ = NOT *Y++;
+ *(--X) &= mask;
+ }
+}
+
+ /******************/
+ /* set functions: */
+ /******************/
+
+boolean Set_subset(wordptr X, wordptr Y) /* X subset Y ? */
+{
+ N_word size = size_(X);
+ boolean r = FALSE;
+
+ if ((size > 0) and (bits_(X) == bits_(Y)))
+ {
+ r = TRUE;
+ while (r and (size-- > 0)) r = ((*X++ AND NOT *Y++) == 0);
+ }
+ return(r);
+}
+
+N_int Set_Norm(wordptr addr) /* = | X | */
+{
+ byteptr byte;
+ N_word bytes;
+ N_int n;
+
+ byte = (byteptr) addr;
+ bytes = size_(addr) << FACTOR;
+ n = 0;
+ while (bytes-- > 0)
+ {
+ n += BitVector_BYTENORM[*byte++];
+ }
+ return(n);
+}
+
+N_int Set_Norm2(wordptr addr) /* = | X | */
+{
+ N_word size = size_(addr);
+ N_word w0,w1;
+ N_int n,k;
+
+ n = 0;
+ while (size-- > 0)
+ {
+ k = 0;
+ w1 = NOT (w0 = *addr++);
+ while (w0 and w1)
+ {
+ w0 &= w0 - 1;
+ w1 &= w1 - 1;
+ k++;
+ }
+ if (w0 == 0) n += k;
+ else n += BITS - k;
+ }
+ return(n);
+}
+
+N_int Set_Norm3(wordptr addr) /* = | X | */
+{
+ N_word size = size_(addr);
+ N_int count = 0;
+ N_word c;
+
+ while (size-- > 0)
+ {
+ c = *addr++;
+ while (c)
+ {
+ c &= c - 1;
+ count++;
+ }
+ }
+ return(count);
+}
+
+Z_long Set_Min(wordptr addr) /* = min(X) */
+{
+ boolean empty = TRUE;
+ N_word size = size_(addr);
+ N_word i = 0;
+ N_word c = 0; /* silence compiler warning */
+
+ while (empty and (size-- > 0))
+ {
+ if ((c = *addr++)) empty = false; else i++;
+ }
+ if (empty) return((Z_long) LONG_MAX); /* plus infinity */
+ i <<= LOGBITS;
+ while (not (c AND LSB))
+ {
+ c >>= 1;
+ i++;
+ }
+ return((Z_long) i);
+}
+
+Z_long Set_Max(wordptr addr) /* = max(X) */
+{
+ boolean empty = TRUE;
+ N_word size = size_(addr);
+ N_word i = size;
+ N_word c = 0; /* silence compiler warning */
+
+ addr += size-1;
+ while (empty and (size-- > 0))
+ {
+ if ((c = *addr--)) empty = false; else i--;
+ }
+ if (empty) return((Z_long) LONG_MIN); /* minus infinity */
+ i <<= LOGBITS;
+ while (not (c AND MSB))
+ {
+ c <<= 1;
+ i--;
+ }
+ return((Z_long) --i);
+}
+
+ /**********************************/
+ /* matrix-of-booleans operations: */
+ /**********************************/
+
+void Matrix_Multiplication(wordptr X, N_int rowsX, N_int colsX,
+ wordptr Y, N_int rowsY, N_int colsY,
+ wordptr Z, N_int rowsZ, N_int colsZ)
+{
+ N_word i;
+ N_word j;
+ N_word k;
+ N_word indxX;
+ N_word indxY;
+ N_word indxZ;
+ N_word termX;
+ N_word termY;
+ N_word sum;
+
+ if ((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and
+ (bits_(X) == rowsX*colsX) and
+ (bits_(Y) == rowsY*colsY) and
+ (bits_(Z) == rowsZ*colsZ))
+ {
+ for ( i = 0; i < rowsY; i++ )
+ {
+ termX = i * colsX;
+ termY = i * colsY;
+ for ( j = 0; j < colsZ; j++ )
+ {
+ indxX = termX + j;
+ sum = 0;
+ for ( k = 0; k < colsY; k++ )
+ {
+ indxY = termY + k;
+ indxZ = k * colsZ + j;
+ if ( BIT_VECTOR_TST_BIT(Y,indxY) &&
+ BIT_VECTOR_TST_BIT(Z,indxZ) ) sum ^= 1;
+ }
+ if (sum) BIT_VECTOR_SET_BIT(X,indxX)
+ else BIT_VECTOR_CLR_BIT(X,indxX)
+ }
+ }
+ }
+}
+
+void Matrix_Product(wordptr X, N_int rowsX, N_int colsX,
+ wordptr Y, N_int rowsY, N_int colsY,
+ wordptr Z, N_int rowsZ, N_int colsZ)
+{
+ N_word i;
+ N_word j;
+ N_word k;
+ N_word indxX;
+ N_word indxY;
+ N_word indxZ;
+ N_word termX;
+ N_word termY;
+ N_word sum;
+
+ if ((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and
+ (bits_(X) == rowsX*colsX) and
+ (bits_(Y) == rowsY*colsY) and
+ (bits_(Z) == rowsZ*colsZ))
+ {
+ for ( i = 0; i < rowsY; i++ )
+ {
+ termX = i * colsX;
+ termY = i * colsY;
+ for ( j = 0; j < colsZ; j++ )
+ {
+ indxX = termX + j;
+ sum = 0;
+ for ( k = 0; k < colsY; k++ )
+ {
+ indxY = termY + k;
+ indxZ = k * colsZ + j;
+ if ( BIT_VECTOR_TST_BIT(Y,indxY) &&
+ BIT_VECTOR_TST_BIT(Z,indxZ) ) sum |= 1;
+ }
+ if (sum) BIT_VECTOR_SET_BIT(X,indxX)
+ else BIT_VECTOR_CLR_BIT(X,indxX)
+ }
+ }
+ }
+}
+
+void Matrix_Closure(wordptr addr, N_int rows, N_int cols)
+{
+ N_word i;
+ N_word j;
+ N_word k;
+ N_word ii;
+ N_word ij;
+ N_word ik;
+ N_word kj;
+ N_word termi;
+ N_word termk;
+
+ if ((rows == cols) and (bits_(addr) == rows*cols))
+ {
+ for ( i = 0; i < rows; i++ )
+ {
+ ii = i * cols + i;
+ BIT_VECTOR_SET_BIT(addr,ii)
+ }
+ for ( k = 0; k < rows; k++ )
+ {
+ termk = k * cols;
+ for ( i = 0; i < rows; i++ )
+ {
+ termi = i * cols;
+ ik = termi + k;
+ for ( j = 0; j < rows; j++ )
+ {
+ ij = termi + j;
+ kj = termk + j;
+ if ( BIT_VECTOR_TST_BIT(addr,ik) &&
+ BIT_VECTOR_TST_BIT(addr,kj) )
+ BIT_VECTOR_SET_BIT(addr,ij)
+ }
+ }
+ }
+ }
+}
+
+void Matrix_Transpose(wordptr X, N_int rowsX, N_int colsX,
+ wordptr Y, N_int rowsY, N_int colsY)
+{
+ N_word i;
+ N_word j;
+ N_word ii;
+ N_word ij;
+ N_word ji;
+ N_word addii;
+ N_word addij;
+ N_word addji;
+ N_word bitii;
+ N_word bitij;
+ N_word bitji;
+ N_word termi;
+ N_word termj;
+ boolean swap;
+
+ /* BEWARE that "in-place" is ONLY possible if the matrix is quadratic!! */
+
+ if ((rowsX == colsY) and (colsX == rowsY) and
+ (bits_(X) == rowsX*colsX) and
+ (bits_(Y) == rowsY*colsY))
+ {
+ if (rowsY == colsY) /* in-place is possible! */
+ {
+ for ( i = 0; i < rowsY; i++ )
+ {
+ termi = i * colsY;
+ for ( j = 0; j < i; j++ )
+ {
+ termj = j * colsX;
+ ij = termi + j;
+ ji = termj + i;
+ addij = ij >> LOGBITS;
+ addji = ji >> LOGBITS;
+ bitij = BITMASKTAB[ij AND MODMASK];
+ bitji = BITMASKTAB[ji AND MODMASK];
+ swap = ((*(Y+addij) AND bitij) != 0);
+ if ((*(Y+addji) AND bitji) != 0)
+ *(X+addij) |= bitij;
+ else
+ *(X+addij) &= NOT bitij;
+ if (swap)
+ *(X+addji) |= bitji;
+ else
+ *(X+addji) &= NOT bitji;
+ }
+ ii = termi + i;
+ addii = ii >> LOGBITS;
+ bitii = BITMASKTAB[ii AND MODMASK];
+ if ((*(Y+addii) AND bitii) != 0)
+ *(X+addii) |= bitii;
+ else
+ *(X+addii) &= NOT bitii;
+ }
+ }
+ else /* rowsX != colsX, in-place is NOT possible! */
+ {
+ for ( i = 0; i < rowsY; i++ )
+ {
+ termi = i * colsY;
+ for ( j = 0; j < colsY; j++ )
+ {
+ termj = j * colsX;
+ ij = termi + j;
+ ji = termj + i;
+ addij = ij >> LOGBITS;
+ addji = ji >> LOGBITS;
+ bitij = BITMASKTAB[ij AND MODMASK];
+ bitji = BITMASKTAB[ji AND MODMASK];
+ if ((*(Y+addij) AND bitij) != 0)
+ *(X+addji) |= bitji;
+ else
+ *(X+addji) &= NOT bitji;
+ }
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+/* VERSION: 6.4 */
+/*****************************************************************************/
+/* VERSION HISTORY: */
+/*****************************************************************************/
+/* */
+/* Version 6.4 03.10.04 Added C++ comp. directives. Improved "Norm()". */
+/* Version 6.3 28.09.02 Added "Create_List()" and "GCD2()". */
+/* Version 6.2 15.09.02 Overhauled error handling. Fixed "GCD()". */
+/* Version 6.1 08.10.01 Make VMS linker happy: _lsb,_msb => _lsb_,_msb_ */
+/* Version 6.0 08.10.00 Corrected overflow handling. */
+/* Version 5.8 14.07.00 Added "Power()". Changed "Copy()". */
+/* Version 5.7 19.05.99 Quickened "Div_Pos()". Added "Product()". */
+/* Version 5.6 02.11.98 Leading zeros eliminated in "to_Hex()". */
+/* Version 5.5 21.09.98 Fixed bug of uninitialized "error" in Multiply. */
+/* Version 5.4 07.09.98 Fixed bug of uninitialized "error" in Divide. */
+/* Version 5.3 12.05.98 Improved Norm. Completed history. */
+/* Version 5.2 31.03.98 Improved Norm. */
+/* Version 5.1 09.03.98 No changes. */
+/* Version 5.0 01.03.98 Major additions and rewrite. */
+/* Version 4.2 16.07.97 Added is_empty, is_full. */
+/* Version 4.1 30.06.97 Added word-ins/del, move-left/right, inc/dec. */
+/* Version 4.0 23.04.97 Rewrite. Added bit shift and bool. matrix ops. */
+/* Version 3.2 04.02.97 Added interval methods. */
+/* Version 3.1 21.01.97 Fixed bug on 64 bit machines. */
+/* Version 3.0 12.01.97 Added flip. */
+/* Version 2.0 14.12.96 Efficiency and consistency improvements. */
+/* Version 1.1 08.01.96 Added Resize and ExclusiveOr. */
+/* Version 1.0 14.12.95 First version under UNIX (with Perl module). */
+/* Version 0.9 01.11.93 First version of C library under MS-DOS. */
+/* Version 0.1 ??.??.89 First version in Turbo Pascal under CP/M. */
+/* */
+/*****************************************************************************/
+/* AUTHOR: */
+/*****************************************************************************/
+/* */
+/* Steffen Beyer */
+/* mailto:sb@engelschall.com */
+/* http://www.engelschall.com/u/sb/download/ */
+/* */
+/*****************************************************************************/
+/* COPYRIGHT: */
+/*****************************************************************************/
+/* */
+/* Copyright (c) 1995 - 2004 by Steffen Beyer. */
+/* All rights reserved. */
+/* */
+/*****************************************************************************/
+/* LICENSE: */
+/*****************************************************************************/
+/* This package is free software; you can use, modify and redistribute */
+/* it under the same terms as Perl itself, i.e., under the terms of */
+/* the "Artistic License" or the "GNU General Public License". */
+/* */
+/* The C library at the core of this Perl module can additionally */
+/* be used, modified and redistributed under the terms of the */
+/* "GNU Library General Public License". */
+/* */
+/*****************************************************************************/
+/* ARTISTIC LICENSE: */
+/*****************************************************************************/
+/*
+ The "Artistic License"
+
+ Preamble
+
+The intent of this document is to state the conditions under which a
+Package may be copied, such that the Copyright Holder maintains some
+semblance of artistic control over the development of the package,
+while giving the users of the package the right to use and distribute
+the Package in a more-or-less customary fashion, plus the right to make
+reasonable modifications.
+
+Definitions:
+
+ "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes
+ of the Copyright Holder as specified below.
+
+ "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package.
+
+ "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ "Reasonable copying fee" is whatever you can justify on the
+ basis of media cost, duplication charges, time of people involved,
+ and so on. (You will not be required to justify it to the
+ Copyright Holder, but only to the computing community at large
+ as a market that must bear the fee.)
+
+ "Freely Available" means that no fee is charged for the item
+ itself, though there may be fees involved in handling the item.
+ It also means that recipients of the item may redistribute it
+ under the same conditions they received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications
+derived from the Public Domain or from the Copyright Holder. A Package
+modified in such a way shall still be considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and
+when you changed that file, and provided that you do at least ONE of the
+following:
+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or
+ an equivalent medium, or placing the modifications on a major archive
+ site such as uunet.uu.net, or by allowing the Copyright Holder to include
+ your modifications in the Standard Version of the Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict
+ with standard executables, which must also be provided, and provide
+ a separate manual page for each non-standard executable that clearly
+ documents how it differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+4. You may distribute the programs of this Package in object code or
+executable form, provided that you do at least ONE of the following:
+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where
+ to get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of
+ the Package with your modifications.
+
+ c) give non-standard executables non-standard names, and clearly
+ document the differences in manual pages (or equivalent), together
+ with instructions on where to get the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+5. You may charge a reasonable copying fee for any distribution of this
+Package. You may charge any fee you choose for support of this
+Package. You may not charge a fee for this Package itself. However,
+you may distribute this Package in aggregate with other (possibly
+commercial) programs as part of a larger (possibly commercial) software
+distribution provided that you do not advertise this Package as a
+product of your own. You may embed this Package's interpreter within
+an executable of yours (by linking); this shall be construed as a mere
+form of aggregation, provided that the complete Standard Version of the
+interpreter is so embedded.
+
+6. The scripts and library files supplied as input to or produced as
+output from the programs of this Package do not automatically fall
+under the copyright of this Package, but belong to whoever generated
+them, and may be sold commercially, and may be aggregated with this
+Package. If such scripts or library files are aggregated with this
+Package via the so-called "undump" or "unexec" methods of producing a
+binary executable image, then distribution of such an image shall
+neither be construed as a distribution of this Package nor shall it
+fall under the restrictions of Paragraphs 3 and 4, provided that you do
+not represent such an executable image as a Standard Version of this
+Package.
+
+7. C subroutines (or comparably compiled subroutines in other
+languages) supplied by you and linked into this Package in order to
+emulate subroutines and variables of the language defined by this
+Package shall not be considered part of this Package, but are the
+equivalent of input as in Paragraph 6, provided these subroutines do
+not change the language in any way that would cause it to fail the
+regression tests for the language.
+
+8. Aggregation of this Package with a commercial distribution is always
+permitted provided that the use of this Package is embedded; that is,
+when no overt attempt is made to make this Package's interfaces visible
+to the end user of the commercial distribution. Such use shall not be
+construed as a distribution of this Package.
+
+9. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ The End
+*/
+/*****************************************************************************/
+/* GNU GENERAL PUBLIC LICENSE: */
+/*****************************************************************************/
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the */
+/* Free Software Foundation, Inc., */
+/* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* */
+/*****************************************************************************/
+/* GNU LIBRARY GENERAL PUBLIC LICENSE: */
+/*****************************************************************************/
+/* This library is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU Library General Public */
+/* License as published by the Free Software Foundation; either */
+/* version 2 of the License, or (at your option) any later version. */
+/* */
+/* This library is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
+/* Library General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU Library General Public */
+/* License along with this library; if not, write to the */
+/* Free Software Foundation, Inc., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/* or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0 */
+/* */
+/*****************************************************************************/
diff --git a/contrib/tools/yasm/libyasm/bitvect.h b/contrib/tools/yasm/libyasm/bitvect.h
new file mode 100644
index 0000000000..3aee3a5319
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/bitvect.h
@@ -0,0 +1,666 @@
+#ifndef YASM_BITVECT_H
+#define YASM_BITVECT_H
+/*****************************************************************************/
+/* MODULE NAME: BitVector.h MODULE TYPE: (adt) */
+/*****************************************************************************/
+/* MODULE IMPORTS: */
+/*****************************************************************************/
+
+/* ToolBox.h */
+/*****************************************************************************/
+/* NOTE: The type names that have been chosen here are somewhat weird on */
+/* purpose, in order to avoid name clashes with system header files */
+/* and your own application(s) which might - directly or indirectly - */
+/* include this definitions file. */
+/*****************************************************************************/
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+typedef unsigned char N_char;
+typedef unsigned char N_byte;
+typedef unsigned short N_short;
+typedef unsigned short N_shortword;
+typedef unsigned int N_int;
+typedef unsigned int N_word;
+typedef unsigned long N_long;
+typedef unsigned long N_longword;
+
+/* Mnemonic 1: The natural numbers, N = { 0, 1, 2, 3, ... } */
+/* Mnemonic 2: Nnnn = u_N_signed, _N_ot signed */
+
+typedef signed char Z_char;
+typedef signed char Z_byte;
+typedef signed short Z_short;
+typedef signed short Z_shortword;
+typedef signed int Z_int;
+typedef signed int Z_word;
+typedef signed long Z_long;
+typedef signed long Z_longword;
+
+/* Mnemonic 1: The whole numbers, Z = { 0, -1, 1, -2, 2, -3, 3, ... } */
+/* Mnemonic 2: Zzzz = Ssss_igned */
+
+typedef void *voidptr;
+typedef N_char *charptr;
+typedef N_byte *byteptr;
+typedef N_short *shortptr;
+typedef N_shortword *shortwordptr;
+typedef N_int *intptr;
+typedef N_word *wordptr;
+typedef N_long *longptr;
+typedef N_longword *longwordptr;
+
+typedef N_char *N_charptr;
+typedef N_byte *N_byteptr;
+typedef N_short *N_shortptr;
+typedef N_shortword *N_shortwordptr;
+typedef N_int *N_intptr;
+typedef N_word *N_wordptr;
+typedef N_long *N_longptr;
+typedef N_longword *N_longwordptr;
+
+typedef Z_char *Z_charptr;
+typedef Z_byte *Z_byteptr;
+typedef Z_short *Z_shortptr;
+typedef Z_shortword *Z_shortwordptr;
+typedef Z_int *Z_intptr;
+typedef Z_word *Z_wordptr;
+typedef Z_long *Z_longptr;
+typedef Z_longword *Z_longwordptr;
+
+#ifndef FALSE
+#define FALSE (0!=0)
+#endif
+
+#ifndef TRUE
+#define TRUE (0==0)
+#endif
+
+#ifdef __cplusplus
+ typedef bool boolean;
+#else
+ #ifdef MACOS_TRADITIONAL
+ #define boolean Boolean
+ #else
+ typedef enum boolean { false = FALSE, true = TRUE } boolean;
+ #endif
+#endif
+
+/*****************************************************************************/
+/* MODULE INTERFACE: */
+/*****************************************************************************/
+
+typedef enum ErrCode
+ {
+ ErrCode_Ok = 0, /* everything went allright */
+
+ ErrCode_Type, /* types word and size_t have incompatible sizes */
+ ErrCode_Bits, /* bits of word and sizeof(word) are inconsistent */
+ ErrCode_Word, /* size of word is less than 16 bits */
+ ErrCode_Long, /* size of word is greater than size of long */
+ ErrCode_Powr, /* number of bits of word is not a power of two */
+ ErrCode_Loga, /* error in calculation of logarithm */
+
+ ErrCode_Null, /* unable to allocate memory */
+
+ ErrCode_Indx, /* index out of range */
+ ErrCode_Ordr, /* minimum > maximum index */
+ ErrCode_Size, /* bit vector size mismatch */
+ ErrCode_Pars, /* input string syntax error */
+ ErrCode_Ovfl, /* numeric overflow error */
+ ErrCode_Same, /* operands must be distinct */
+ ErrCode_Expo, /* exponent must be positive */
+ ErrCode_Zero /* division by zero error */
+ } ErrCode;
+
+typedef wordptr *listptr;
+
+/* ===> MISCELLANEOUS BASIC FUNCTIONS: <=== */
+
+YASM_LIB_DECL
+const char * BitVector_Error (ErrCode error); /* return string for err code */
+
+YASM_LIB_DECL
+ErrCode BitVector_Boot (void); /* 0 = ok, 1..7 = error */
+YASM_LIB_DECL
+void BitVector_Shutdown (void); /* undo Boot */
+
+YASM_LIB_DECL
+N_word BitVector_Size (N_int bits); /* bit vector size (# of words) */
+YASM_LIB_DECL
+N_word BitVector_Mask (N_int bits); /* bit vector mask (unused bits) */
+
+/* ===> CLASS METHODS: <=== */
+
+YASM_LIB_DECL
+const char * BitVector_Version (void); /* returns version string */
+
+YASM_LIB_DECL
+N_int BitVector_Word_Bits (void); /* return # of bits in machine word */
+YASM_LIB_DECL
+N_int BitVector_Long_Bits (void); /* return # of bits in unsigned long */
+
+/* ===> CONSTRUCTOR METHODS: <=== */
+
+YASM_LIB_DECL
+/*@only@*/ wordptr BitVector_Create (N_int bits, boolean clear); /* malloc */
+YASM_LIB_DECL
+listptr BitVector_Create_List(N_int bits, boolean clear, N_int count);
+
+YASM_LIB_DECL
+wordptr BitVector_Resize (wordptr oldaddr, N_int bits); /* realloc */
+
+YASM_LIB_DECL
+wordptr BitVector_Shadow (wordptr addr); /* make new same size but empty */
+YASM_LIB_DECL
+wordptr BitVector_Clone (wordptr addr); /* make exact duplicate */
+
+YASM_LIB_DECL
+wordptr BitVector_Concat (wordptr X, wordptr Y); /* return concatenation */
+
+/* ===> DESTRUCTOR METHODS: <=== */
+
+YASM_LIB_DECL
+void BitVector_Dispose (/*@only@*/ /*@out@*/ charptr string); /* string */
+YASM_LIB_DECL
+void BitVector_Destroy (/*@only@*/ wordptr addr); /* bitvec */
+YASM_LIB_DECL
+void BitVector_Destroy_List (listptr list, N_int count); /* list */
+
+/* ===> OBJECT METHODS: <=== */
+
+/* ===> bit vector copy function: */
+
+YASM_LIB_DECL
+void BitVector_Copy (wordptr X, wordptr Y); /* X = Y */
+
+/* ===> bit vector initialization: */
+
+YASM_LIB_DECL
+void BitVector_Empty (wordptr addr); /* X = {} */
+YASM_LIB_DECL
+void BitVector_Fill (wordptr addr); /* X = ~{} */
+YASM_LIB_DECL
+void BitVector_Flip (wordptr addr); /* X = ~X */
+
+YASM_LIB_DECL
+void BitVector_Primes (wordptr addr);
+
+/* ===> miscellaneous functions: */
+
+YASM_LIB_DECL
+void BitVector_Reverse (wordptr X, wordptr Y);
+
+/* ===> bit vector interval operations and functions: */
+
+YASM_LIB_DECL
+void BitVector_Interval_Empty (/*@out@*/ wordptr addr, N_int lower, N_int upper);
+YASM_LIB_DECL
+void BitVector_Interval_Fill (/*@out@*/ wordptr addr, N_int lower, N_int upper);
+YASM_LIB_DECL
+void BitVector_Interval_Flip (/*@out@*/ wordptr addr, N_int lower, N_int upper);
+YASM_LIB_DECL
+void BitVector_Interval_Reverse (/*@out@*/ wordptr addr, N_int lower, N_int upper);
+
+YASM_LIB_DECL
+boolean BitVector_interval_scan_inc (wordptr addr, N_int start,
+ N_intptr min, N_intptr max);
+YASM_LIB_DECL
+boolean BitVector_interval_scan_dec (wordptr addr, N_int start,
+ N_intptr min, N_intptr max);
+
+YASM_LIB_DECL
+void BitVector_Interval_Copy (/*@out@*/ wordptr X, wordptr Y, N_int Xoffset,
+ N_int Yoffset, N_int length);
+
+YASM_LIB_DECL
+wordptr BitVector_Interval_Substitute(/*@out@*/ wordptr X, wordptr Y,
+ N_int Xoffset, N_int Xlength,
+ N_int Yoffset, N_int Ylength);
+
+/* ===> bit vector test functions: */
+
+YASM_LIB_DECL
+boolean BitVector_is_empty (wordptr addr); /* X == {} ? */
+YASM_LIB_DECL
+boolean BitVector_is_full (wordptr addr); /* X == ~{} ? */
+
+YASM_LIB_DECL
+boolean BitVector_equal (wordptr X, wordptr Y); /* X == Y ? */
+YASM_LIB_DECL
+Z_int BitVector_Lexicompare(wordptr X, wordptr Y); /* X <,=,> Y ? */
+YASM_LIB_DECL
+Z_int BitVector_Compare (wordptr X, wordptr Y); /* X <,=,> Y ? */
+
+/* ===> bit vector string conversion functions: */
+
+YASM_LIB_DECL
+/*@only@*/ charptr BitVector_to_Hex (wordptr addr);
+YASM_LIB_DECL
+ErrCode BitVector_from_Hex (/*@out@*/wordptr addr, charptr string);
+
+YASM_LIB_DECL
+ErrCode BitVector_from_Oct(/*@out@*/ wordptr addr, charptr string);
+
+YASM_LIB_DECL
+/*@only@*/ charptr BitVector_to_Bin (wordptr addr);
+YASM_LIB_DECL
+ErrCode BitVector_from_Bin (/*@out@*/ wordptr addr, charptr string);
+
+YASM_LIB_DECL
+/*@only@*/ charptr BitVector_to_Dec (wordptr addr);
+YASM_LIB_DECL
+ErrCode BitVector_from_Dec (/*@out@*/ wordptr addr, charptr string);
+
+typedef struct BitVector_from_Dec_static_data BitVector_from_Dec_static_data;
+YASM_LIB_DECL
+BitVector_from_Dec_static_data *BitVector_from_Dec_static_Boot(N_word bits);
+YASM_LIB_DECL
+void BitVector_from_Dec_static_Shutdown(/*@null@*/ BitVector_from_Dec_static_data *data);
+YASM_LIB_DECL
+ErrCode BitVector_from_Dec_static(BitVector_from_Dec_static_data *data,
+ /*@out@*/ wordptr addr, charptr string);
+
+YASM_LIB_DECL
+/*@only@*/ charptr BitVector_to_Enum (wordptr addr);
+YASM_LIB_DECL
+ErrCode BitVector_from_Enum (/*@out@*/ wordptr addr, charptr string);
+
+/* ===> bit vector bit operations, functions & tests: */
+
+YASM_LIB_DECL
+void BitVector_Bit_Off (/*@out@*/ wordptr addr, N_int indx); /* X = X \ {x} */
+YASM_LIB_DECL
+void BitVector_Bit_On (/*@out@*/ wordptr addr, N_int indx); /* X = X + {x} */
+YASM_LIB_DECL
+boolean BitVector_bit_flip (/*@out@*/ wordptr addr, N_int indx); /* (X+{x})\(X*{x}) */
+
+YASM_LIB_DECL
+boolean BitVector_bit_test (wordptr addr, N_int indx); /* {x} in X ? */
+
+YASM_LIB_DECL
+void BitVector_Bit_Copy (/*@out@*/ wordptr addr, N_int indx, boolean bit);
+
+/* ===> bit vector bit shift & rotate functions: */
+
+YASM_LIB_DECL
+void BitVector_LSB (/*@out@*/ wordptr addr, boolean bit);
+YASM_LIB_DECL
+void BitVector_MSB (/*@out@*/ wordptr addr, boolean bit);
+YASM_LIB_DECL
+boolean BitVector_lsb_ (wordptr addr);
+YASM_LIB_DECL
+boolean BitVector_msb_ (wordptr addr);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_rotate_left (wordptr addr);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_rotate_right (wordptr addr);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_shift_left (wordptr addr, boolean carry_in);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_shift_right (wordptr addr, boolean carry_in);
+YASM_LIB_DECL
+void BitVector_Move_Left (wordptr addr, N_int bits);
+YASM_LIB_DECL
+void BitVector_Move_Right (wordptr addr, N_int bits);
+
+/* ===> bit vector insert/delete bits: */
+
+YASM_LIB_DECL
+void BitVector_Insert (wordptr addr, N_int offset, N_int count,
+ boolean clear);
+YASM_LIB_DECL
+void BitVector_Delete (wordptr addr, N_int offset, N_int count,
+ boolean clear);
+
+/* ===> bit vector arithmetic: */
+
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_increment (wordptr addr); /* X++ */
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_decrement (wordptr addr); /* X-- */
+
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_compute (wordptr X, wordptr Y, wordptr Z, boolean minus,
+ boolean *carry);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_add (wordptr X, wordptr Y, wordptr Z, boolean *carry);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_sub (wordptr X, wordptr Y, wordptr Z, boolean *carry);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_inc (wordptr X, wordptr Y);
+YASM_LIB_DECL
+boolean /*@alt void@*/ BitVector_dec (wordptr X, wordptr Y);
+
+YASM_LIB_DECL
+void BitVector_Negate (wordptr X, wordptr Y);
+YASM_LIB_DECL
+void BitVector_Absolute (wordptr X, wordptr Y);
+YASM_LIB_DECL
+Z_int BitVector_Sign (wordptr addr);
+YASM_LIB_DECL
+ErrCode BitVector_Mul_Pos (wordptr X, wordptr Y, wordptr Z, boolean strict);
+YASM_LIB_DECL
+ErrCode BitVector_Multiply (wordptr X, wordptr Y, wordptr Z);
+YASM_LIB_DECL
+ErrCode BitVector_Div_Pos (wordptr Q, wordptr X, wordptr Y, wordptr R);
+YASM_LIB_DECL
+ErrCode BitVector_Divide (wordptr Q, wordptr X, wordptr Y, wordptr R);
+YASM_LIB_DECL
+ErrCode BitVector_GCD (wordptr X, wordptr Y, wordptr Z);
+YASM_LIB_DECL
+ErrCode BitVector_GCD2 (wordptr U, wordptr V, wordptr W, /* O */
+ wordptr X, wordptr Y); /* I */
+YASM_LIB_DECL
+ErrCode BitVector_Power (wordptr X, wordptr Y, wordptr Z);
+
+/* ===> direct memory access functions: */
+
+YASM_LIB_DECL
+void BitVector_Block_Store(wordptr addr, charptr buffer, N_int length);
+YASM_LIB_DECL
+charptr BitVector_Block_Read (wordptr addr, /*@out@*/ N_intptr length);
+
+/* ===> word array functions: */
+
+YASM_LIB_DECL
+void BitVector_Word_Store (wordptr addr, N_int offset, N_int value);
+YASM_LIB_DECL
+N_int BitVector_Word_Read (wordptr addr, N_int offset);
+
+YASM_LIB_DECL
+void BitVector_Word_Insert(wordptr addr, N_int offset, N_int count,
+ boolean clear);
+YASM_LIB_DECL
+void BitVector_Word_Delete(wordptr addr, N_int offset, N_int count,
+ boolean clear);
+
+/* ===> arbitrary size chunk functions: */
+
+YASM_LIB_DECL
+void BitVector_Chunk_Store(wordptr addr, N_int chunksize,
+ N_int offset, N_long value);
+YASM_LIB_DECL
+N_long BitVector_Chunk_Read (wordptr addr, N_int chunksize,
+ N_int offset);
+
+/* ===> set operations: */
+
+YASM_LIB_DECL
+void Set_Union (wordptr X, wordptr Y, wordptr Z); /* X = Y + Z */
+YASM_LIB_DECL
+void Set_Intersection (wordptr X, wordptr Y, wordptr Z); /* X = Y * Z */
+YASM_LIB_DECL
+void Set_Difference (wordptr X, wordptr Y, wordptr Z); /* X = Y \ Z */
+YASM_LIB_DECL
+void Set_ExclusiveOr (wordptr X, wordptr Y, wordptr Z); /*(Y+Z)\(Y*Z)*/
+YASM_LIB_DECL
+void Set_Complement (wordptr X, wordptr Y); /* X = ~Y */
+
+/* ===> set functions: */
+
+YASM_LIB_DECL
+boolean Set_subset (wordptr X, wordptr Y); /* X in Y ? */
+
+YASM_LIB_DECL
+N_int Set_Norm (wordptr addr); /* = | X | */
+YASM_LIB_DECL
+N_int Set_Norm2 (wordptr addr); /* = | X | */
+YASM_LIB_DECL
+N_int Set_Norm3 (wordptr addr); /* = | X | */
+YASM_LIB_DECL
+Z_long Set_Min (wordptr addr); /* = min(X) */
+YASM_LIB_DECL
+Z_long Set_Max (wordptr addr); /* = max(X) */
+
+/* ===> matrix-of-booleans operations: */
+
+YASM_LIB_DECL
+void Matrix_Multiplication(wordptr X, N_int rowsX, N_int colsX,
+ wordptr Y, N_int rowsY, N_int colsY,
+ wordptr Z, N_int rowsZ, N_int colsZ);
+
+YASM_LIB_DECL
+void Matrix_Product (wordptr X, N_int rowsX, N_int colsX,
+ wordptr Y, N_int rowsY, N_int colsY,
+ wordptr Z, N_int rowsZ, N_int colsZ);
+
+YASM_LIB_DECL
+void Matrix_Closure (wordptr addr, N_int rows, N_int cols);
+
+YASM_LIB_DECL
+void Matrix_Transpose (wordptr X, N_int rowsX, N_int colsX,
+ wordptr Y, N_int rowsY, N_int colsY);
+
+/*****************************************************************************/
+/* VERSION: 6.4 */
+/*****************************************************************************/
+/* VERSION HISTORY: */
+/*****************************************************************************/
+/* */
+/* Version 6.4 03.10.04 Added C++ comp. directives. Improved "Norm()". */
+/* Version 6.3 28.09.02 Added "Create_List()" and "GCD2()". */
+/* Version 6.2 15.09.02 Overhauled error handling. Fixed "GCD()". */
+/* Version 6.1 08.10.01 Make VMS linker happy: _lsb,_msb => _lsb_,_msb_ */
+/* Version 6.0 08.10.00 Corrected overflow handling. */
+/* Version 5.8 14.07.00 Added "Power()". Changed "Copy()". */
+/* Version 5.7 19.05.99 Quickened "Div_Pos()". Added "Product()". */
+/* Version 5.6 02.11.98 Leading zeros eliminated in "to_Hex()". */
+/* Version 5.5 21.09.98 Fixed bug of uninitialized "error" in Multiply. */
+/* Version 5.4 07.09.98 Fixed bug of uninitialized "error" in Divide. */
+/* Version 5.3 12.05.98 Improved Norm. Completed history. */
+/* Version 5.2 31.03.98 Improved Norm. */
+/* Version 5.1 09.03.98 No changes. */
+/* Version 5.0 01.03.98 Major additions and rewrite. */
+/* Version 4.2 16.07.97 Added is_empty, is_full. */
+/* Version 4.1 30.06.97 Added word-ins/del, move-left/right, inc/dec. */
+/* Version 4.0 23.04.97 Rewrite. Added bit shift and bool. matrix ops. */
+/* Version 3.2 04.02.97 Added interval methods. */
+/* Version 3.1 21.01.97 Fixed bug on 64 bit machines. */
+/* Version 3.0 12.01.97 Added flip. */
+/* Version 2.0 14.12.96 Efficiency and consistency improvements. */
+/* Version 1.1 08.01.96 Added Resize and ExclusiveOr. */
+/* Version 1.0 14.12.95 First version under UNIX (with Perl module). */
+/* Version 0.9 01.11.93 First version of C library under MS-DOS. */
+/* Version 0.1 ??.??.89 First version in Turbo Pascal under CP/M. */
+/* */
+/*****************************************************************************/
+/* AUTHOR: */
+/*****************************************************************************/
+/* */
+/* Steffen Beyer */
+/* mailto:sb@engelschall.com */
+/* http://www.engelschall.com/u/sb/download/ */
+/* */
+/*****************************************************************************/
+/* COPYRIGHT: */
+/*****************************************************************************/
+/* */
+/* Copyright (c) 1995 - 2004 by Steffen Beyer. */
+/* All rights reserved. */
+/* */
+/*****************************************************************************/
+/* LICENSE: */
+/*****************************************************************************/
+/* This package is free software; you can use, modify and redistribute */
+/* it under the same terms as Perl itself, i.e., under the terms of */
+/* the "Artistic License" or the "GNU General Public License". */
+/* */
+/* The C library at the core of this Perl module can additionally */
+/* be used, modified and redistributed under the terms of the */
+/* "GNU Library General Public License". */
+/* */
+/*****************************************************************************/
+/* ARTISTIC LICENSE: */
+/*****************************************************************************/
+/*
+ The "Artistic License"
+
+ Preamble
+
+The intent of this document is to state the conditions under which a
+Package may be copied, such that the Copyright Holder maintains some
+semblance of artistic control over the development of the package,
+while giving the users of the package the right to use and distribute
+the Package in a more-or-less customary fashion, plus the right to make
+reasonable modifications.
+
+Definitions:
+
+ "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes
+ of the Copyright Holder as specified below.
+
+ "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package.
+
+ "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ "Reasonable copying fee" is whatever you can justify on the
+ basis of media cost, duplication charges, time of people involved,
+ and so on. (You will not be required to justify it to the
+ Copyright Holder, but only to the computing community at large
+ as a market that must bear the fee.)
+
+ "Freely Available" means that no fee is charged for the item
+ itself, though there may be fees involved in handling the item.
+ It also means that recipients of the item may redistribute it
+ under the same conditions they received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications
+derived from the Public Domain or from the Copyright Holder. A Package
+modified in such a way shall still be considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and
+when you changed that file, and provided that you do at least ONE of the
+following:
+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or
+ an equivalent medium, or placing the modifications on a major archive
+ site such as uunet.uu.net, or by allowing the Copyright Holder to include
+ your modifications in the Standard Version of the Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict
+ with standard executables, which must also be provided, and provide
+ a separate manual page for each non-standard executable that clearly
+ documents how it differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+4. You may distribute the programs of this Package in object code or
+executable form, provided that you do at least ONE of the following:
+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where
+ to get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of
+ the Package with your modifications.
+
+ c) give non-standard executables non-standard names, and clearly
+ document the differences in manual pages (or equivalent), together
+ with instructions on where to get the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+5. You may charge a reasonable copying fee for any distribution of this
+Package. You may charge any fee you choose for support of this
+Package. You may not charge a fee for this Package itself. However,
+you may distribute this Package in aggregate with other (possibly
+commercial) programs as part of a larger (possibly commercial) software
+distribution provided that you do not advertise this Package as a
+product of your own. You may embed this Package's interpreter within
+an executable of yours (by linking); this shall be construed as a mere
+form of aggregation, provided that the complete Standard Version of the
+interpreter is so embedded.
+
+6. The scripts and library files supplied as input to or produced as
+output from the programs of this Package do not automatically fall
+under the copyright of this Package, but belong to whoever generated
+them, and may be sold commercially, and may be aggregated with this
+Package. If such scripts or library files are aggregated with this
+Package via the so-called "undump" or "unexec" methods of producing a
+binary executable image, then distribution of such an image shall
+neither be construed as a distribution of this Package nor shall it
+fall under the restrictions of Paragraphs 3 and 4, provided that you do
+not represent such an executable image as a Standard Version of this
+Package.
+
+7. C subroutines (or comparably compiled subroutines in other
+languages) supplied by you and linked into this Package in order to
+emulate subroutines and variables of the language defined by this
+Package shall not be considered part of this Package, but are the
+equivalent of input as in Paragraph 6, provided these subroutines do
+not change the language in any way that would cause it to fail the
+regression tests for the language.
+
+8. Aggregation of this Package with a commercial distribution is always
+permitted provided that the use of this Package is embedded; that is,
+when no overt attempt is made to make this Package's interfaces visible
+to the end user of the commercial distribution. Such use shall not be
+construed as a distribution of this Package.
+
+9. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ The End
+*/
+/*****************************************************************************/
+/* GNU GENERAL PUBLIC LICENSE: */
+/*****************************************************************************/
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the */
+/* Free Software Foundation, Inc., */
+/* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* */
+/*****************************************************************************/
+/* GNU LIBRARY GENERAL PUBLIC LICENSE: */
+/*****************************************************************************/
+/* */
+/* This library is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU Library General Public */
+/* License as published by the Free Software Foundation; either */
+/* version 2 of the License, or (at your option) any later version. */
+/* */
+/* This library is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
+/* Library General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU Library General Public */
+/* License along with this library; if not, write to the */
+/* Free Software Foundation, Inc., */
+/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/* */
+/* or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0 */
+/* */
+/*****************************************************************************/
+#endif
diff --git a/contrib/tools/yasm/libyasm/bytecode.c b/contrib/tools/yasm/libyasm/bytecode.c
new file mode 100644
index 0000000000..f864bae0aa
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/bytecode.c
@@ -0,0 +1,386 @@
+/*
+ * Bytecode utility functions
+ *
+ * Copyright (C) 2001-2007 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 "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+#include "symrec.h"
+
+#include "bytecode.h"
+
+
+void
+yasm_bc_set_multiple(yasm_bytecode *bc, yasm_expr *e)
+{
+ if (bc->multiple)
+ bc->multiple = yasm_expr_create_tree(bc->multiple, YASM_EXPR_MUL, e,
+ e->line);
+ else
+ bc->multiple = e;
+}
+
+void
+yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+}
+
+int
+yasm_bc_calc_len_common(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ yasm_internal_error(N_("bytecode length cannot be calculated"));
+ /*@unreached@*/
+ return 0;
+}
+
+int
+yasm_bc_expand_common(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
+{
+ yasm_internal_error(N_("bytecode does not have any dependent spans"));
+ /*@unreached@*/
+ return 0;
+}
+
+int
+yasm_bc_tobytes_common(yasm_bytecode *bc, unsigned char **buf,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc)
+{
+ yasm_internal_error(N_("bytecode cannot be converted to bytes"));
+ /*@unreached@*/
+ return 0;
+}
+
+void
+yasm_bc_transform(yasm_bytecode *bc, const yasm_bytecode_callback *callback,
+ void *contents)
+{
+ if (bc->callback)
+ bc->callback->destroy(bc->contents);
+ bc->callback = callback;
+ bc->contents = contents;
+}
+
+yasm_bytecode *
+yasm_bc_create_common(const yasm_bytecode_callback *callback, void *contents,
+ unsigned long line)
+{
+ yasm_bytecode *bc = yasm_xmalloc(sizeof(yasm_bytecode));
+
+ bc->callback = callback;
+ bc->section = NULL;
+ bc->multiple = (yasm_expr *)NULL;
+ bc->len = 0;
+ bc->mult_int = 1;
+ bc->line = line;
+ bc->offset = ~0UL; /* obviously incorrect / uninitialized value */
+ bc->symrecs = NULL;
+ bc->contents = contents;
+
+ return bc;
+}
+
+yasm_section *
+yasm_bc_get_section(yasm_bytecode *bc)
+{
+ return bc->section;
+}
+
+void
+yasm_bc__add_symrec(yasm_bytecode *bc, yasm_symrec *sym)
+{
+ if (!bc->symrecs) {
+ bc->symrecs = yasm_xmalloc(2*sizeof(yasm_symrec *));
+ bc->symrecs[0] = sym;
+ bc->symrecs[1] = NULL;
+ } else {
+ /* Very inefficient implementation for large numbers of symbols. But
+ * that would be very unusual, so use the simple algorithm instead.
+ */
+ size_t count = 1;
+ while (bc->symrecs[count])
+ count++;
+ bc->symrecs = yasm_xrealloc(bc->symrecs,
+ (count+2)*sizeof(yasm_symrec *));
+ bc->symrecs[count] = sym;
+ bc->symrecs[count+1] = NULL;
+ }
+}
+
+void
+yasm_bc_destroy(yasm_bytecode *bc)
+{
+ if (!bc)
+ return;
+
+ if (bc->callback)
+ bc->callback->destroy(bc->contents);
+ yasm_expr_destroy(bc->multiple);
+ if (bc->symrecs)
+ yasm_xfree(bc->symrecs);
+ yasm_xfree(bc);
+}
+
+void
+yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level)
+{
+ if (!bc->callback)
+ fprintf(f, "%*s_Empty_\n", indent_level, "");
+ else
+ bc->callback->print(bc->contents, f, indent_level);
+ fprintf(f, "%*sMultiple=", indent_level, "");
+ if (!bc->multiple)
+ fprintf(f, "nil (1)");
+ else
+ yasm_expr_print(bc->multiple, f);
+ fprintf(f, "\n%*sLength=%lu\n", indent_level, "", bc->len);
+ fprintf(f, "%*sLine Index=%lu\n", indent_level, "", bc->line);
+ fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset);
+}
+
+void
+yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ if (bc->callback)
+ bc->callback->finalize(bc, prev_bc);
+ if (bc->multiple) {
+ yasm_value val;
+
+ if (yasm_value_finalize_expr(&val, bc->multiple, prev_bc, 0))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("multiple expression too complex"));
+ else if (val.rel)
+ yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
+ N_("multiple expression not absolute"));
+ /* Finalize creates NULL output if value=0, but bc->multiple is NULL
+ * if value=1 (this difference is to make the common case small).
+ * However, this means we need to set bc->multiple explicitly to 0
+ * here if val.abs is NULL.
+ */
+ if (val.abs)
+ bc->multiple = val.abs;
+ else
+ bc->multiple = yasm_expr_create_ident(
+ yasm_expr_int(yasm_intnum_create_uint(0)), bc->line);
+ }
+}
+
+/*@null@*/ yasm_intnum *
+yasm_calc_bc_dist(yasm_bytecode *precbc1, yasm_bytecode *precbc2)
+{
+ unsigned long dist2, dist1;
+ yasm_intnum *intn;
+
+ if (precbc1->section != precbc2->section)
+ return NULL;
+
+ dist1 = yasm_bc_next_offset(precbc1);
+ dist2 = yasm_bc_next_offset(precbc2);
+ if (dist2 < dist1) {
+ intn = yasm_intnum_create_uint(dist1 - dist2);
+ yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
+ return intn;
+ }
+ dist2 -= dist1;
+ return yasm_intnum_create_uint(dist2);
+}
+
+unsigned long
+yasm_bc_next_offset(yasm_bytecode *precbc)
+{
+ return precbc->offset + precbc->len*precbc->mult_int;
+}
+
+int
+yasm_bc_elem_size(yasm_bytecode *bc)
+{
+ if (!bc->callback) {
+ yasm_internal_error(N_("got empty bytecode in yasm_bc_elem_size"));
+ return 0;
+ } else if (!bc->callback->elem_size)
+ return 0;
+ else
+ return bc->callback->elem_size(bc);
+}
+
+int
+yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ int retval = 0;
+
+ bc->len = 0;
+
+ if (!bc->callback)
+ yasm_internal_error(N_("got empty bytecode in yasm_bc_calc_len"));
+ else
+ retval = bc->callback->calc_len(bc, add_span, add_span_data);
+
+ /* Check for multiples */
+ bc->mult_int = 1;
+ if (bc->multiple) {
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+
+ num = yasm_expr_get_intnum(&bc->multiple, 0);
+ if (num) {
+ if (yasm_intnum_sign(num) < 0) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
+ retval = -1;
+ } else
+ bc->mult_int = yasm_intnum_get_int(num);
+ } else {
+ if (yasm_expr__contains(bc->multiple, YASM_EXPR_FLOAT)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("expression must not contain floating point value"));
+ retval = -1;
+ } else {
+ yasm_value value;
+ yasm_value_initialize(&value, bc->multiple, 0);
+ add_span(add_span_data, bc, 0, &value, 0, 0);
+ bc->mult_int = 0; /* assume 0 to start */
+ }
+ }
+ }
+
+ /* If we got an error somewhere along the line, clear out any calc len */
+ if (retval < 0)
+ bc->len = 0;
+
+ return retval;
+}
+
+int
+yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
+{
+ if (span == 0) {
+ bc->mult_int = new_val;
+ return 1;
+ }
+ if (!bc->callback) {
+ yasm_internal_error(N_("got empty bytecode in yasm_bc_expand"));
+ /*@unreached@*/
+ return -1;
+ } else
+ return bc->callback->expand(bc, span, old_val, new_val, neg_thres,
+ pos_thres);
+}
+
+/*@null@*/ /*@only@*/ unsigned char *
+yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize,
+ /*@out@*/ int *gap, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc)
+ /*@sets *buf@*/
+{
+ /*@only@*/ /*@null@*/ unsigned char *mybuf = NULL;
+ unsigned char *bufstart;
+ unsigned char *origbuf, *destbuf;
+ long i;
+ int error = 0;
+
+ long mult;
+ if (yasm_bc_get_multiple(bc, &mult, 1) || mult == 0) {
+ *bufsize = 0;
+ return NULL;
+ }
+ bc->mult_int = mult;
+
+ /* special case for reserve bytecodes */
+ if (bc->callback->special == YASM_BC_SPECIAL_RESERVE) {
+ *bufsize = bc->len*bc->mult_int;
+ *gap = 1;
+ return NULL; /* we didn't allocate a buffer */
+ }
+ *gap = 0;
+
+ if (*bufsize < bc->len*bc->mult_int) {
+ mybuf = yasm_xmalloc(bc->len*bc->mult_int);
+ destbuf = mybuf;
+ } else
+ destbuf = buf;
+ bufstart = destbuf;
+
+ *bufsize = bc->len*bc->mult_int;
+
+ if (!bc->callback)
+ yasm_internal_error(N_("got empty bytecode in bc_tobytes"));
+ else for (i=0; i<bc->mult_int; i++) {
+ origbuf = destbuf;
+ error = bc->callback->tobytes(bc, &destbuf, bufstart, d, output_value,
+ output_reloc);
+
+ if (!error && ((unsigned long)(destbuf - origbuf) != bc->len))
+ yasm_internal_error(
+ N_("written length does not match optimized length"));
+ }
+
+ return mybuf;
+}
+
+int
+yasm_bc_get_multiple(yasm_bytecode *bc, long *multiple, int calc_bc_dist)
+{
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
+
+ *multiple = 1;
+ if (bc->multiple) {
+ num = yasm_expr_get_intnum(&bc->multiple, calc_bc_dist);
+ if (!num) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("could not determine multiple"));
+ return 1;
+ }
+ if (yasm_intnum_sign(num) < 0) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
+ return 1;
+ }
+ *multiple = yasm_intnum_get_int(num);
+ }
+ return 0;
+}
+
+const yasm_expr *
+yasm_bc_get_multiple_expr(const yasm_bytecode *bc)
+{
+ return bc->multiple;
+}
+
+yasm_insn *
+yasm_bc_get_insn(yasm_bytecode *bc)
+{
+ if (bc->callback->special != YASM_BC_SPECIAL_INSN)
+ return NULL;
+ return (yasm_insn *)bc->contents;
+}
diff --git a/contrib/tools/yasm/libyasm/bytecode.h b/contrib/tools/yasm/libyasm/bytecode.h
new file mode 100644
index 0000000000..47cd26244b
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/bytecode.h
@@ -0,0 +1,638 @@
+/**
+ * \file libyasm/bytecode.h
+ * \brief YASM bytecode interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_BYTECODE_H
+#define YASM_BYTECODE_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** A data value (opaque type). */
+typedef struct yasm_dataval yasm_dataval;
+/** A list of data values. */
+typedef struct yasm_datavalhead yasm_datavalhead;
+
+/** Linked list of data values. */
+/*@reldef@*/ STAILQ_HEAD(yasm_datavalhead, yasm_dataval);
+
+/** Add a dependent span for a bytecode.
+ * \param add_span_data add_span_data passed into bc_calc_len()
+ * \param bc bytecode containing span
+ * \param id non-zero identifier for span; may be any non-zero value
+ * if <0, expand is called for any change;
+ * if >0, expand is only called when exceeds threshold
+ * \param value dependent value for bytecode expansion
+ * \param neg_thres negative threshold for long/short decision
+ * \param pos_thres positive threshold for long/short decision
+ */
+typedef void (*yasm_bc_add_span_func)
+ (void *add_span_data, yasm_bytecode *bc, int id, const yasm_value *value,
+ long neg_thres, long pos_thres);
+
+/** Bytecode callback structure. Any implementation of a specific bytecode
+ * must implement these functions and this callback structure. The bytecode
+ * implementation-specific data is stored in #yasm_bytecode.contents.
+ */
+typedef struct yasm_bytecode_callback {
+ /** Destroys the implementation-specific data.
+ * Called from yasm_bc_destroy().
+ * \param contents #yasm_bytecode.contents
+ */
+ void (*destroy) (/*@only@*/ void *contents);
+
+ /** Prints the implementation-specific data (for debugging purposes).
+ * Called from yasm_bc_print().
+ * \param contents #yasm_bytecode.contents
+ * \param f file
+ * \param indent_level indentation level
+ */
+ void (*print) (const void *contents, FILE *f, int indent_level);
+
+ /** Finalizes the bytecode after parsing. Called from yasm_bc_finalize().
+ * A generic fill-in for this is yasm_bc_finalize_common().
+ * \param bc bytecode
+ * \param prev_bc bytecode directly preceding bc
+ */
+ void (*finalize) (yasm_bytecode *bc, yasm_bytecode *prev_bc);
+
+ /** Return elements size of a data bytecode.
+ * This function should return the size of each elements of a data
+ * bytecode, for proper dereference of symbols attached to it.
+ * \param bc bytecode
+ * \return 0 if element size is unknown.
+ */
+ int (*elem_size) (yasm_bytecode *bc);
+
+ /** Calculates the minimum size of a bytecode.
+ * Called from yasm_bc_calc_len().
+ * A generic fill-in for this is yasm_bc_calc_len_common(), but as this
+ * function internal errors when called, be very careful when using it!
+ * This function should simply add to bc->len and not set it directly
+ * (it's initialized by yasm_bc_calc_len() prior to passing control to
+ * this function).
+ *
+ * \param bc bytecode
+ * \param add_span function to call to add a span
+ * \param add_span_data extra data to be passed to add_span function
+ * \return 0 if no error occurred, nonzero if there was an error
+ * recognized (and output) during execution.
+ * \note May store to bytecode updated expressions.
+ */
+ int (*calc_len) (yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data);
+
+ /** Recalculates the bytecode's length based on an expanded span length.
+ * Called from yasm_bc_expand().
+ * A generic fill-in for this is yasm_bc_expand_common(), but as this
+ * function internal errors when called, if used, ensure that calc_len()
+ * never adds a span.
+ * This function should simply add to bc->len to increase the length by
+ * a delta amount.
+ * \param bc bytecode
+ * \param span span ID (as given to add_span in calc_len)
+ * \param old_val previous span value
+ * \param new_val new span value
+ * \param neg_thres negative threshold for long/short decision
+ * (returned)
+ * \param pos_thres positive threshold for long/short decision
+ * (returned)
+ * \return 0 if bc no longer dependent on this span's length, negative if
+ * there was an error recognized (and output) during execution,
+ * and positive if bc size may increase for this span further
+ * based on the new negative and positive thresholds returned.
+ * \note May store to bytecode updated expressions.
+ */
+ int (*expand) (yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres);
+
+ /** Convert a bytecode into its byte representation.
+ * Called from yasm_bc_tobytes().
+ * A generic fill-in for this is yasm_bc_tobytes_common(), but as this
+ * function internal errors when called, be very careful when using it!
+ * \param bc bytecode
+ * \param bufp byte representation destination buffer;
+ * should be incremented as it's written to,
+ * so that on return its delta from the
+ * passed-in buf matches the bytecode length
+ * (it's okay not to do this if an error
+ * indication is returned)
+ * \param bufstart For calculating the correct offset parameter for
+ * the \a output_value calls: *bufp - bufstart.
+ * \param d data to pass to each call to
+ * output_value/output_reloc
+ * \param output_value function to call to convert values into their byte
+ * representation
+ * \param output_reloc function to call to output relocation entries
+ * for a single sym
+ * \return Nonzero on error, 0 on success.
+ * \note May result in non-reversible changes to the bytecode, but it's
+ * preferable if calling this function twice would result in the
+ * same output.
+ */
+ int (*tobytes) (yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+ /** Special bytecode classifications. Most bytecode types should use
+ * #YASM_BC_SPECIAL_NONE. Others cause special handling to kick in
+ * in various parts of yasm.
+ */
+ enum yasm_bytecode_special_type {
+ YASM_BC_SPECIAL_NONE = 0,
+
+ /** Bytecode reserves space instead of outputting data. */
+ YASM_BC_SPECIAL_RESERVE,
+
+ /** Adjusts offset instead of calculating len. */
+ YASM_BC_SPECIAL_OFFSET,
+
+ /** Instruction bytecode. */
+ YASM_BC_SPECIAL_INSN
+ } special;
+} yasm_bytecode_callback;
+
+/** A bytecode. */
+struct yasm_bytecode {
+ /** Bytecodes are stored as a singly linked list, with tail insertion.
+ * \see section.h (#yasm_section).
+ */
+ /*@reldef@*/ STAILQ_ENTRY(yasm_bytecode) link;
+
+ /** The bytecode callback structure for this bytecode. May be NULL
+ * during partial initialization.
+ */
+ /*@null@*/ const yasm_bytecode_callback *callback;
+
+ /** Pointer to section containing bytecode; NULL if not part of a
+ * section.
+ */
+ /*@dependent@*/ /*@null@*/ yasm_section *section;
+
+ /** Number of times bytecode is repeated.
+ * NULL=1 (to save space in the common case).
+ */
+ /*@only@*/ /*@null@*/ yasm_expr *multiple;
+
+ /** Total length of entire bytecode (not including multiple copies). */
+ unsigned long len;
+
+ /** Number of copies, integer version. */
+ long mult_int;
+
+ /** Line number where bytecode was defined. */
+ unsigned long line;
+
+ /** Offset of bytecode from beginning of its section.
+ * 0-based, ~0UL (e.g. all 1 bits) if unknown.
+ */
+ unsigned long offset;
+
+ /** Unique integer index of bytecode. Used during optimization. */
+ unsigned long bc_index;
+
+ /** NULL-terminated array of labels that point to this bytecode (as the
+ * bytecode previous to the label). NULL if no labels point here.
+ */
+ /*@null@*/ yasm_symrec **symrecs;
+
+ /** Implementation-specific data (type identified by callback). */
+ void *contents;
+};
+
+/** Create a bytecode of any specified type.
+ * \param callback bytecode callback functions, if NULL, creates empty
+ * bytecode (may not be resolved or output)
+ * \param contents type-specific data
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode of the specified type.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_bytecode *yasm_bc_create_common
+ (/*@null@*/ const yasm_bytecode_callback *callback,
+ /*@only@*/ /*@null@*/ void *contents, unsigned long line);
+
+/** Transform a bytecode of any type into a different type.
+ * \param bc bytecode to transform
+ * \param callback new bytecode callback function
+ * \param contents new type-specific data
+ */
+YASM_LIB_DECL
+void yasm_bc_transform(yasm_bytecode *bc,
+ const yasm_bytecode_callback *callback,
+ void *contents);
+
+/** Common bytecode callback finalize function, for where no finalization
+ * is ever required for this type of bytecode.
+ */
+YASM_LIB_DECL
+void yasm_bc_finalize_common(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+
+/** Common bytecode callback calc_len function, for where the bytecode has
+ * no calculatable length. Causes an internal error if called.
+ */
+YASM_LIB_DECL
+int yasm_bc_calc_len_common(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data);
+
+/** Common bytecode callback expand function, for where the bytecode is
+ * always short (calc_len never calls add_span). Causes an internal
+ * error if called.
+ */
+YASM_LIB_DECL
+int yasm_bc_expand_common
+ (yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres);
+
+/** Common bytecode callback tobytes function, for where the bytecode
+ * cannot be converted to bytes. Causes an internal error if called.
+ */
+YASM_LIB_DECL
+int yasm_bc_tobytes_common
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+/** Get the next bytecode in a linked list of bytecodes.
+ * \param bc bytecode
+ * \return Next bytecode.
+ */
+#define yasm_bc__next(bc) STAILQ_NEXT(bc, link)
+
+/** Set multiple field of a bytecode.
+ * A bytecode can be repeated a number of times when output. This function
+ * sets that multiple.
+ * \param bc bytecode
+ * \param e multiple (kept, do not free)
+ */
+YASM_LIB_DECL
+void yasm_bc_set_multiple(yasm_bytecode *bc, /*@keep@*/ yasm_expr *e);
+
+/** Create a bytecode containing data value(s).
+ * \param datahead list of data values (kept, do not free)
+ * \param size storage size (in bytes) for each data value
+ * \param append_zero append a single zero byte after each data value
+ * (if non-zero)
+ * \param arch architecture (optional); if provided, data items
+ * are directly simplified to bytes if possible
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_bytecode *yasm_bc_create_data
+ (yasm_datavalhead *datahead, unsigned int size, int append_zero,
+ /*@null@*/ yasm_arch *arch, unsigned long line);
+
+/** Create a bytecode containing LEB128-encoded data value(s).
+ * \param datahead list of data values (kept, do not free)
+ * \param sign signedness (1=signed, 0=unsigned) of each data value
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_bytecode *yasm_bc_create_leb128
+ (yasm_datavalhead *datahead, int sign, unsigned long line);
+
+/** Create a bytecode reserving space.
+ * \param numitems number of reserve "items" (kept, do not free)
+ * \param itemsize reserved size (in bytes) for each item
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_bytecode *yasm_bc_create_reserve
+ (/*@only@*/ yasm_expr *numitems, unsigned int itemsize,
+ unsigned long line);
+
+/** Get the number of items and itemsize for a reserve bytecode. If bc
+ * is not a reserve bytecode, returns NULL.
+ * \param bc bytecode
+ * \param itemsize reserved size (in bytes) for each item (returned)
+ * \return NULL if bc is not a reserve bytecode, otherwise an expression
+ * for the number of items to reserve.
+ */
+YASM_LIB_DECL
+/*@null@*/ const yasm_expr *yasm_bc_reserve_numitems
+ (yasm_bytecode *bc, /*@out@*/ unsigned int *itemsize);
+
+/** Create a bytecode that includes a binary file verbatim.
+ * \param filename path to binary file (kept, do not free)
+ * \param start starting location in file (in bytes) to read data from
+ * (kept, do not free); may be NULL to indicate 0
+ * \param maxlen maximum number of bytes to read from the file (kept, do
+ * do not free); may be NULL to indicate no maximum
+ * \param linemap line mapping repository
+ * \param line virtual line (from yasm_linemap) for the bytecode
+ * \return Newly allocated bytecode.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_bytecode *yasm_bc_create_incbin
+ (/*@only@*/ char *filename, /*@only@*/ /*@null@*/ yasm_expr *start,
+ /*@only@*/ /*@null@*/ yasm_expr *maxlen, yasm_linemap *linemap,
+ unsigned long line);
+
+/** Create a bytecode that aligns the following bytecode to a boundary.
+ * \param boundary byte alignment (must be a power of two)
+ * \param fill fill data (if NULL, code_fill or 0 is used)
+ * \param maxskip maximum number of bytes to skip
+ * \param code_fill code fill data (if NULL, 0 is used)
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ * \note The precedence on generated fill is as follows:
+ * - from fill parameter (if not NULL)
+ * - from code_fill parameter (if not NULL)
+ * - 0
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_bytecode *yasm_bc_create_align
+ (/*@keep@*/ yasm_expr *boundary, /*@keep@*/ /*@null@*/ yasm_expr *fill,
+ /*@keep@*/ /*@null@*/ yasm_expr *maxskip,
+ /*@null@*/ const unsigned char **code_fill, unsigned long line);
+
+/** Create a bytecode that puts the following bytecode at a fixed section
+ * offset.
+ * \param start section offset of following bytecode
+ * \param fill fill value
+ * \param line virtual line (from yasm_linemap)
+ * \return Newly allocated bytecode.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_bytecode *yasm_bc_create_org
+ (unsigned long start, unsigned long fill, unsigned long line);
+
+/** Get the section that contains a particular bytecode.
+ * \param bc bytecode
+ * \return Section containing bc (can be NULL if bytecode is not part of a
+ * section).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ yasm_section *yasm_bc_get_section
+ (yasm_bytecode *bc);
+
+/** Add to the list of symrecs that reference a bytecode. For symrec use
+ * only.
+ * \param bc bytecode
+ * \param sym symbol
+ */
+YASM_LIB_DECL
+void yasm_bc__add_symrec(yasm_bytecode *bc, /*@dependent@*/ yasm_symrec *sym);
+
+/** Delete (free allocated memory for) a bytecode.
+ * \param bc bytecode (only pointer to it); may be NULL
+ */
+YASM_LIB_DECL
+void yasm_bc_destroy(/*@only@*/ /*@null@*/ yasm_bytecode *bc);
+
+/** Print a bytecode. For debugging purposes.
+ * \param f file
+ * \param indent_level indentation level
+ * \param bc bytecode
+ */
+YASM_LIB_DECL
+void yasm_bc_print(const yasm_bytecode *bc, FILE *f, int indent_level);
+
+/** Finalize a bytecode after parsing.
+ * \param bc bytecode
+ * \param prev_bc bytecode directly preceding bc in a list of bytecodes
+ */
+YASM_LIB_DECL
+void yasm_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+
+/** Determine the distance between the starting offsets of two bytecodes.
+ * \param precbc1 preceding bytecode to the first bytecode
+ * \param precbc2 preceding bytecode to the second bytecode
+ * \return Distance in bytes between the two bytecodes (bc2-bc1), or NULL if
+ * the distance was indeterminate.
+ * \warning Only valid /after/ optimization.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@only@*/ yasm_intnum *yasm_calc_bc_dist
+ (yasm_bytecode *precbc1, yasm_bytecode *precbc2);
+
+/** Get the offset of the next bytecode (the next bytecode doesn't have to
+ * actually exist).
+ * \param precbc preceding bytecode
+ * \return Offset of the next bytecode in bytes.
+ * \warning Only valid /after/ optimization.
+ */
+YASM_LIB_DECL
+unsigned long yasm_bc_next_offset(yasm_bytecode *precbc);
+
+/** Return elemens size of a data bytecode.
+ * Returns the size of each elements of a data bytecode, for proper dereference
+ * of symbols attached to it.
+ * \param bc bytecode
+ * \return 0 if element size is unknown
+ */
+YASM_LIB_DECL
+int yasm_bc_elem_size(yasm_bytecode *bc);
+
+/** Resolve EQUs in a bytecode and calculate its minimum size.
+ * Generates dependent bytecode spans for cases where, if the length spanned
+ * increases, it could cause the bytecode size to increase.
+ * Any bytecode multiple is NOT included in the length or spans generation;
+ * this must be handled at a higher level.
+ * \param bc bytecode
+ * \param add_span function to call to add a span
+ * \param add_span_data extra data to be passed to add_span function
+ * \return 0 if no error occurred, nonzero if there was an error recognized
+ * (and output) during execution.
+ * \note May store to bytecode updated expressions and the short length.
+ */
+YASM_LIB_DECL
+int yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data);
+
+/** Recalculate a bytecode's length based on an expanded span length.
+ * \param bc bytecode
+ * \param span span ID (as given to yasm_bc_add_span_func in
+ * yasm_bc_calc_len)
+ * \param old_val previous span value
+ * \param new_val new span value
+ * \param neg_thres negative threshold for long/short decision (returned)
+ * \param pos_thres positive threshold for long/short decision (returned)
+ * \return 0 if bc no longer dependent on this span's length, negative if
+ * there was an error recognized (and output) during execution, and
+ * positive if bc size may increase for this span further based on the
+ * new negative and positive thresholds returned.
+ * \note May store to bytecode updated expressions and the updated length.
+ */
+YASM_LIB_DECL
+int yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres);
+
+/** Convert a bytecode into its byte representation.
+ * \param bc bytecode
+ * \param buf byte representation destination buffer
+ * \param bufsize size of buf (in bytes) prior to call; size of the
+ * generated data after call
+ * \param gap if nonzero, indicates the data does not really need to
+ * exist in the object file; if nonzero, contents of buf
+ * are undefined [output]
+ * \param d data to pass to each call to output_value/output_reloc
+ * \param output_value function to call to convert values into their byte
+ * representation
+ * \param output_reloc function to call to output relocation entries
+ * for a single sym
+ * \return Newly allocated buffer that should be used instead of buf for
+ * reading the byte representation, or NULL if buf was big enough to
+ * hold the entire byte representation.
+ * \note Calling twice on the same bytecode may \em not produce the same
+ * results on the second call, as calling this function may result in
+ * non-reversible changes to the bytecode.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@only@*/ unsigned char *yasm_bc_tobytes
+ (yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize,
+ /*@out@*/ int *gap, void *d, yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc)
+ /*@sets *buf@*/;
+
+/** Get the bytecode multiple value as an integer.
+ * \param bc bytecode
+ * \param multiple multiple value (output)
+ * \param calc_bc_dist nonzero if distances between bytecodes should be
+ * calculated, 0 if error should be returned in this case
+ * \return 1 on error (set with yasm_error_set), 0 on success.
+ */
+YASM_LIB_DECL
+int yasm_bc_get_multiple(yasm_bytecode *bc, /*@out@*/ long *multiple,
+ int calc_bc_dist);
+
+/** Get the bytecode multiple value as an expression.
+ * \param bc bytecode
+ * \return Bytecode multiple, NULL if =1.
+ */
+YASM_LIB_DECL
+const yasm_expr *yasm_bc_get_multiple_expr(const yasm_bytecode *bc);
+
+/** Get a #yasm_insn structure from an instruction bytecode (if possible).
+ * \param bc bytecode
+ * \return Instruction details if bytecode is an instruction bytecode,
+ * otherwise NULL.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ yasm_insn *yasm_bc_get_insn(yasm_bytecode *bc);
+
+/** Create a new data value from an expression.
+ * \param expn expression
+ * \return Newly allocated data value.
+ */
+YASM_LIB_DECL
+yasm_dataval *yasm_dv_create_expr(/*@keep@*/ yasm_expr *expn);
+
+/** Create a new data value from a string.
+ * \param contents string (may contain NULs)
+ * \param len length of string
+ * \return Newly allocated data value.
+ */
+YASM_LIB_DECL
+yasm_dataval *yasm_dv_create_string(/*@keep@*/ char *contents, size_t len);
+
+/** Create a new data value from raw bytes data.
+ * \param contents raw data (may contain NULs)
+ * \param len length
+ * \return Newly allocated data value.
+ */
+YASM_LIB_DECL
+yasm_dataval *yasm_dv_create_raw(/*@keep@*/ unsigned char *contents,
+ unsigned long len);
+
+/** Create a new uninitialized data value.
+ * \return Newly allocated data value.
+ */
+YASM_LIB_DECL
+yasm_dataval *yasm_dv_create_reserve(void);
+
+#ifndef YASM_DOXYGEN
+#define yasm_dv_create_string(s, l) yasm_dv_create_raw((unsigned char *)(s), \
+ (unsigned long)(l))
+#endif
+
+/** Get the underlying value of a data value.
+ * \param dv data value
+ * \return Value, or null if non-value (e.g. string or raw).
+ */
+YASM_LIB_DECL
+yasm_value *yasm_dv_get_value(yasm_dataval *dv);
+
+/** Set multiple field of a data value.
+ * A data value can be repeated a number of times when output. This function
+ * sets that multiple.
+ * \param dv data value
+ * \param e multiple (kept, do not free)
+ */
+YASM_LIB_DECL
+void yasm_dv_set_multiple(yasm_dataval *dv, /*@keep@*/ yasm_expr *e);
+
+/** Get the data value multiple value as an unsigned long integer.
+ * \param dv data value
+ * \param multiple multiple value (output)
+ * \return 1 on error (set with yasm_error_set), 0 on success.
+ */
+YASM_LIB_DECL
+int yasm_dv_get_multiple(yasm_dataval *dv, /*@out@*/ unsigned long *multiple);
+
+/** Initialize a list of data values.
+ * \param headp list of data values
+ */
+void yasm_dvs_initialize(yasm_datavalhead *headp);
+#ifndef YASM_DOXYGEN
+#define yasm_dvs_initialize(headp) STAILQ_INIT(headp)
+#endif
+
+/** Delete (free allocated memory for) a list of data values.
+ * \param headp list of data values
+ */
+YASM_LIB_DECL
+void yasm_dvs_delete(yasm_datavalhead *headp);
+
+/** Add data value to the end of a list of data values.
+ * \note Does not make a copy of the data value; so don't pass this function
+ * static or local variables, and discard the dv pointer after calling
+ * this function.
+ * \param headp data value list
+ * \param dv data value (may be NULL)
+ * \return If data value was actually appended (it wasn't NULL), the data
+ * value; otherwise NULL.
+ */
+YASM_LIB_DECL
+/*@null@*/ yasm_dataval *yasm_dvs_append
+ (yasm_datavalhead *headp, /*@returned@*/ /*@null@*/ yasm_dataval *dv);
+
+/** Print a data value list. For debugging purposes.
+ * \param f file
+ * \param indent_level indentation level
+ * \param headp data value list
+ */
+YASM_LIB_DECL
+void yasm_dvs_print(const yasm_datavalhead *headp, FILE *f, int indent_level);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/cmake-module.c b/contrib/tools/yasm/libyasm/cmake-module.c
new file mode 100644
index 0000000000..2ee39ca88f
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/cmake-module.c
@@ -0,0 +1,126 @@
+/*
+ * YASM module loader
+ *
+ * Copyright (C) 2004-2007 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 <util.h>
+
+#include <libyasm.h>
+
+
+typedef struct loaded_module {
+ const char *keyword; /* module keyword */
+ void *data; /* associated data */
+} loaded_module;
+
+static HAMT *loaded_modules[] = {NULL, NULL, NULL, NULL, NULL, NULL};
+
+static void
+load_module_destroy(/*@only@*/ void *data)
+{
+ /* do nothing */
+}
+
+void *
+yasm_load_module(yasm_module_type type, const char *keyword)
+{
+ if (!loaded_modules[type])
+ return NULL;
+ return HAMT_search(loaded_modules[type], keyword);
+}
+
+void
+yasm_register_module(yasm_module_type type, const char *keyword, void *data)
+{
+ int replace = 1;
+
+ assert(type < sizeof(loaded_modules));
+
+ if (!loaded_modules[type])
+ loaded_modules[type] = HAMT_create(0, yasm_internal_error_);
+
+ HAMT_insert(loaded_modules[type], keyword, data, &replace,
+ load_module_destroy);
+}
+
+typedef struct {
+ yasm_module_type type;
+ void (*printfunc) (const char *name, const char *keyword);
+} list_one_data;
+
+static int
+yasm_list_one_module(void *node, void *d)
+{
+ list_one_data *data = (list_one_data *)d;
+ yasm_arch_module *arch;
+ yasm_dbgfmt_module *dbgfmt;
+ yasm_objfmt_module *objfmt;
+ yasm_listfmt_module *listfmt;
+ yasm_parser_module *parser;
+ yasm_preproc_module *preproc;
+
+ switch (data->type) {
+ case YASM_MODULE_ARCH:
+ arch = node;
+ data->printfunc(arch->name, arch->keyword);
+ break;
+ case YASM_MODULE_DBGFMT:
+ dbgfmt = node;
+ data->printfunc(dbgfmt->name, dbgfmt->keyword);
+ break;
+ case YASM_MODULE_OBJFMT:
+ objfmt = node;
+ data->printfunc(objfmt->name, objfmt->keyword);
+ break;
+ case YASM_MODULE_LISTFMT:
+ listfmt = node;
+ data->printfunc(listfmt->name, listfmt->keyword);
+ break;
+ case YASM_MODULE_PARSER:
+ parser = node;
+ data->printfunc(parser->name, parser->keyword);
+ break;
+ case YASM_MODULE_PREPROC:
+ preproc = node;
+ data->printfunc(preproc->name, preproc->keyword);
+ break;
+ }
+ return 0;
+}
+
+void
+yasm_list_modules(yasm_module_type type,
+ void (*printfunc) (const char *name, const char *keyword))
+{
+ list_one_data data;
+
+ /* Go through available list, and try to load each one */
+ if (!loaded_modules[type])
+ return;
+
+ data.type = type;
+ data.printfunc = printfunc;
+
+ HAMT_traverse(loaded_modules[type], &data, yasm_list_one_module);
+}
diff --git a/contrib/tools/yasm/libyasm/compat-queue.h b/contrib/tools/yasm/libyasm/compat-queue.h
new file mode 100644
index 0000000000..da9eff4694
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/compat-queue.h
@@ -0,0 +1,456 @@
+/*
+ * <sys/queue.h> implementation for systems that don't have it.
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND 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 REGENTS OR 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.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.4 2001/03/31 03:33:39 hsu Exp $
+ */
+
+#ifndef SYS_QUEUE_H
+#define SYS_QUEUE_H
+
+/*
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ * SLIST LIST STAILQ TAILQ
+ * _HEAD + + + +
+ * _HEAD_INITIALIZER + + + +
+ * _ENTRY + + + +
+ * _INIT + + + +
+ * _EMPTY + + + +
+ * _FIRST + + + +
+ * _NEXT + + + +
+ * _PREV - - - +
+ * _LAST - - + +
+ * _FOREACH + + + +
+ * _FOREACH_SAFE + + + +
+ * _FOREACH_REVERSE - - - +
+ * _FOREACH_REVERSE_SAFE - - - +
+ * _INSERT_HEAD + + + +
+ * _INSERT_BEFORE - + - +
+ * _INSERT_AFTER + + + +
+ * _INSERT_TAIL - - + +
+ * _CONCAT - - + +
+ * _REMOVE_HEAD + - + -
+ * _REMOVE + + + +
+ *
+ */
+
+/*
+ * Singly-linked List declarations.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+
+#define SLIST_FIRST(head) ((head)->slh_first)
+
+#define SLIST_FOREACH(var, head, field) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var); \
+ (var) = SLIST_NEXT((var), field))
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
+ for ((varp) = &SLIST_FIRST((head)); \
+ ((var) = *(varp)) != NULL; \
+ (varp) = &SLIST_NEXT((var), field))
+
+#define SLIST_INIT(head) do { \
+ SLIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
+ SLIST_NEXT((slistelm), field) = (elm); \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
+ SLIST_FIRST((head)) = (elm); \
+} while (0)
+
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if (SLIST_FIRST((head)) == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = SLIST_FIRST((head)); \
+ while (SLIST_NEXT(curelm, field) != (elm)) \
+ curelm = SLIST_NEXT(curelm, field); \
+ SLIST_NEXT(curelm, field) = \
+ SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
+ } \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first;/* first element */ \
+ struct type **stqh_last;/* addr of last next element */ \
+}
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (0)
+
+#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
+
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for((var) = STAILQ_FIRST((head)); \
+ (var); \
+ (var) = STAILQ_NEXT((var), field))
+
+
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = STAILQ_FIRST((head)); \
+ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define STAILQ_INIT(head) do { \
+ STAILQ_FIRST((head)) = NULL; \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_NEXT((tqelm), field) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_FIRST((head)) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ STAILQ_NEXT((elm), field) = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+} while (0)
+
+#define STAILQ_LAST(head, type, field) \
+ (STAILQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *) \
+ ((char *)((head)->stqh_last) - offsetof(struct type, field))))
+
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ if (STAILQ_FIRST((head)) == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = STAILQ_FIRST((head)); \
+ while (STAILQ_NEXT(curelm, field) != (elm)) \
+ curelm = STAILQ_NEXT(curelm, field); \
+ if ((STAILQ_NEXT(curelm, field) = \
+ STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
+ (head)->stqh_last = &STAILQ_NEXT((curelm), field);\
+ } \
+} while (0)
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if ((STAILQ_FIRST((head)) = \
+ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
+ if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+/*
+ * List declarations.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+
+#define LIST_EMPTY(head) ((head)->lh_first == NULL)
+
+#define LIST_FIRST(head) ((head)->lh_first)
+
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = LIST_FIRST((head)); \
+ (var); \
+ (var) = LIST_NEXT((var), field))
+
+#define LIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = LIST_FIRST((head)); \
+ (var) && ((tvar) = LIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define LIST_INIT(head) do { \
+ LIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+ LIST_NEXT((listelm), field)->field.le_prev = \
+ &LIST_NEXT((elm), field); \
+ LIST_NEXT((listelm), field) = (elm); \
+ (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
+} while (0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ LIST_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
+ LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+ LIST_FIRST((head)) = (elm); \
+ (elm)->field.le_prev = &LIST_FIRST((head)); \
+} while (0)
+
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_REMOVE(elm, field) do { \
+ if (LIST_NEXT((elm), field) != NULL) \
+ LIST_NEXT((elm), field)->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = LIST_NEXT((elm), field); \
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+}
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+}
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ } \
+} while (0)
+
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var); \
+ (var) = TAILQ_NEXT((var), field))
+
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var); \
+ (var) = TAILQ_PREV((var), headname, field))
+
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
+ (var) = (tvar))
+
+#define TAILQ_INIT(head) do { \
+ TAILQ_FIRST((head)) = NULL; \
+ (head)->tqh_last = &TAILQ_FIRST((head)); \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else { \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ } \
+ TAILQ_NEXT((listelm), field) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ TAILQ_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
+ TAILQ_FIRST((head))->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ TAILQ_FIRST((head)) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ TAILQ_NEXT((elm), field) = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+} while (0)
+
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field)) != NULL) \
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else { \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ } \
+ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
+} while (0)
+
+#endif /* !SYS_QUEUE_H */
diff --git a/contrib/tools/yasm/libyasm/coretype.h b/contrib/tools/yasm/libyasm/coretype.h
new file mode 100644
index 0000000000..624e3c445c
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/coretype.h
@@ -0,0 +1,393 @@
+/**
+ * \file libyasm/coretype.h
+ * \brief YASM core types and utility functions.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_CORETYPE_H
+#define YASM_CORETYPE_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Architecture instance (mostly opaque type). \see arch.h for details. */
+typedef struct yasm_arch yasm_arch;
+/** Preprocessor interface. \see preproc.h for details. */
+typedef struct yasm_preproc yasm_preproc;
+/** Parser instance (mostly opaque type). \see parser.h for details. */
+typedef struct yasm_parser yasm_parser;
+/** Object format interface. \see objfmt.h for details. */
+typedef struct yasm_objfmt yasm_objfmt;
+/** Debug format interface. \see dbgfmt.h for details. */
+typedef struct yasm_dbgfmt yasm_dbgfmt;
+/** List format interface. \see listfmt.h for details. */
+typedef struct yasm_listfmt yasm_listfmt;
+
+/** Object format module interface. \see objfmt.h for details. */
+typedef struct yasm_objfmt_module yasm_objfmt_module;
+/** Debug format module interface. \see dbgfmt.h for details. */
+typedef struct yasm_dbgfmt_module yasm_dbgfmt_module;
+
+/** Standard macro structure for modules that allows association of a set of
+ * standard macros with a parser/preprocessor combination.
+ * A NULL-terminated array of these structures is used in a number of module
+ * interfaces.
+ */
+typedef struct yasm_stdmac {
+ const char *parser; /**< Parser keyword */
+ const char *preproc; /**< Preprocessor keyword */
+
+ /** NULL-terminated array of standard macros. May be NULL if no standard
+ * macros should be added for this preprocessor.
+ */
+ const char **macros;
+} yasm_stdmac;
+
+/** YASM associated data callback structure. Many data structures can have
+ * arbitrary data associated with them.
+ */
+typedef struct yasm_assoc_data_callback {
+ /** Free memory allocated for associated data.
+ * \param data associated data
+ */
+ void (*destroy) (/*@only@*/ void *data);
+
+ /** Print a description of allocated data. For debugging purposes.
+ * \param data associated data
+ * \param f output file
+ * \param indent_level indentation level
+ */
+ void (*print) (void *data, FILE *f, int indent_level);
+} yasm_assoc_data_callback;
+
+/** Set of collected error/warnings (opaque type).
+ * \see errwarn.h for details.
+ */
+typedef struct yasm_errwarns yasm_errwarns;
+
+/** Bytecode. \see bytecode.h for details and related functions. */
+typedef struct yasm_bytecode yasm_bytecode;
+
+/** Object. \see section.h for details and related functions. */
+typedef struct yasm_object yasm_object;
+
+/** Section (opaque type). \see section.h for related functions. */
+typedef struct yasm_section yasm_section;
+
+/** Symbol table (opaque type). \see symrec.h for related functions. */
+typedef struct yasm_symtab yasm_symtab;
+
+/** Symbol record (opaque type). \see symrec.h for related functions. */
+typedef struct yasm_symrec yasm_symrec;
+
+/** Expression. \see expr.h for details and related functions. */
+typedef struct yasm_expr yasm_expr;
+/** Integer value (opaque type). \see intnum.h for related functions. */
+typedef struct yasm_intnum yasm_intnum;
+/** Floating point value (opaque type).
+ * \see floatnum.h for related functions.
+ */
+typedef struct yasm_floatnum yasm_floatnum;
+
+/** A value. May be absolute or relative. Outside the parser, yasm_expr
+ * should only be used for absolute exprs. Anything that could contain
+ * a relocatable value should use this structure instead.
+ * \see value.h for related functions.
+ */
+typedef struct yasm_value {
+ /** The absolute portion of the value. May contain *differences* between
+ * symrecs but not standalone symrecs. May be NULL if there is no
+ * absolute portion (e.g. the absolute portion is 0).
+ */
+ /*@null@*/ /*@only@*/ yasm_expr *abs;
+
+ /** The relative portion of the value. This is the portion that may
+ * need to generate a relocation. May be NULL if no relative portion.
+ */
+ /*@null@*/ /*@dependent@*/ yasm_symrec *rel;
+
+ /** What the relative portion is in reference to. NULL if the default. */
+ /*@null@*/ /*@dependent@*/ yasm_symrec *wrt;
+
+ /** If the segment of the relative portion should be used, not the
+ * relative portion itself. Boolean.
+ */
+ unsigned int seg_of : 1;
+
+ /** If the relative portion of the value should be shifted right
+ * (supported only by a few object formats). If just the absolute portion
+ * should be shifted, that must be in the abs expr, not here!
+ */
+ unsigned int rshift : 7;
+
+ /** Indicates the relative portion of the value should be relocated
+ * relative to the current assembly position rather than relative to the
+ * section start. "Current assembly position" here refers to the starting
+ * address of the bytecode containing this value. Boolean.
+ */
+ unsigned int curpos_rel : 1;
+
+ /** Indicates that curpos_rel was set due to IP-relative relocation;
+ * in some objfmt/arch combinations (e.g. win64/x86-amd64) this info
+ * is needed to generate special relocations.
+ */
+ unsigned int ip_rel : 1;
+
+ /** Indicates the value is a jump target address (rather than a simple
+ * data address). In some objfmt/arch combinations (e.g. macho/amd64)
+ * this info is needed to generate special relocations.
+ */
+ unsigned int jump_target : 1;
+
+ /** Indicates the relative portion of the value should be relocated
+ * relative to its own section start rather than relative to the
+ * section start of the bytecode containing this value. E.g. the value
+ * resulting from the relative portion should be the offset from its
+ * section start. Boolean.
+ */
+ unsigned int section_rel : 1;
+
+ /** Indicates overflow warnings have been disabled for this value. */
+ unsigned int no_warn : 1;
+
+ /** Sign of the value. Nonzero if the final value should be treated as
+ * signed, 0 if it should be treated as signed.
+ */
+ unsigned int sign : 1;
+
+ /** Size of the value, in bits. */
+ unsigned int size : 8;
+} yasm_value;
+
+/** Maximum value of #yasm_value.rshift */
+#define YASM_VALUE_RSHIFT_MAX 127
+
+/** Line number mapping repository (opaque type). \see linemap.h for related
+ * functions.
+ */
+typedef struct yasm_linemap yasm_linemap;
+
+/** Value/parameter pair (opaque type).
+ * \see valparam.h for related functions.
+ */
+typedef struct yasm_valparam yasm_valparam;
+/** List of value/parameters (opaque type).
+ * \see valparam.h for related functions.
+ */
+typedef struct yasm_valparamhead yasm_valparamhead;
+/** Directive list entry.
+ * \see valparam.h for details and related functions.
+ */
+typedef struct yasm_directive yasm_directive;
+
+/** An effective address.
+ * \see insn.h for related functions.
+ */
+typedef struct yasm_effaddr yasm_effaddr;
+
+/** An instruction.
+ * \see insn.h for related functions.
+ */
+typedef struct yasm_insn yasm_insn;
+
+/** Expression operators usable in #yasm_expr expressions. */
+typedef enum yasm_expr_op {
+ YASM_EXPR_IDENT, /**< No operation, just a value. */
+ YASM_EXPR_ADD, /**< Arithmetic addition (+). */
+ YASM_EXPR_SUB, /**< Arithmetic subtraction (-). */
+ YASM_EXPR_MUL, /**< Arithmetic multiplication (*). */
+ YASM_EXPR_DIV, /**< Arithmetic unsigned division. */
+ YASM_EXPR_SIGNDIV, /**< Arithmetic signed division. */
+ YASM_EXPR_MOD, /**< Arithmetic unsigned modulus. */
+ YASM_EXPR_SIGNMOD, /**< Arithmetic signed modulus. */
+ YASM_EXPR_NEG, /**< Arithmetic negation (-). */
+ YASM_EXPR_NOT, /**< Bitwise negation. */
+ YASM_EXPR_OR, /**< Bitwise OR. */
+ YASM_EXPR_AND, /**< Bitwise AND. */
+ YASM_EXPR_XOR, /**< Bitwise XOR. */
+ YASM_EXPR_XNOR, /**< Bitwise XNOR. */
+ YASM_EXPR_NOR, /**< Bitwise NOR. */
+ YASM_EXPR_SHL, /**< Shift left (logical). */
+ YASM_EXPR_SHR, /**< Shift right (logical). */
+ YASM_EXPR_LOR, /**< Logical OR. */
+ YASM_EXPR_LAND, /**< Logical AND. */
+ YASM_EXPR_LNOT, /**< Logical negation. */
+ YASM_EXPR_LXOR, /**< Logical XOR. */
+ YASM_EXPR_LXNOR, /**< Logical XNOR. */
+ YASM_EXPR_LNOR, /**< Logical NOR. */
+ YASM_EXPR_LT, /**< Less than comparison. */
+ YASM_EXPR_GT, /**< Greater than comparison. */
+ YASM_EXPR_EQ, /**< Equality comparison. */
+ YASM_EXPR_LE, /**< Less than or equal to comparison. */
+ YASM_EXPR_GE, /**< Greater than or equal to comparison. */
+ YASM_EXPR_NE, /**< Not equal comparison. */
+ YASM_EXPR_NONNUM, /**< Start of non-numeric operations (not an op). */
+ YASM_EXPR_SEG, /**< SEG operator (gets segment portion of address). */
+ YASM_EXPR_WRT, /**< WRT operator (gets offset of address relative to
+ * some other segment). */
+ YASM_EXPR_SEGOFF /**< The ':' in segment:offset. */
+} yasm_expr_op;
+
+/** Convert yasm_value to its byte representation. Usually implemented by
+ * object formats to keep track of relocations and verify legal expressions.
+ * Must put the value into the least significant bits of the destination,
+ * unless shifted into more significant bits by the shift parameter. The
+ * destination bits must be cleared before being set.
+ * \param value value
+ * \param buf buffer for byte representation
+ * \param destsize destination size (in bytes)
+ * \param offset offset (in bytes) of the expr contents from the start
+ * of the bytecode (needed for relative)
+ * \param bc current bytecode (usually passed into higher-level
+ * calling function)
+ * \param warn enables standard warnings: zero for none;
+ * nonzero for overflow/underflow floating point warnings
+ * \param d objfmt-specific data (passed into higher-level calling
+ * function)
+ * \return Nonzero if an error occurred, 0 otherwise.
+ */
+typedef int (*yasm_output_value_func)
+ (yasm_value *value, /*@out@*/ unsigned char *buf, unsigned int destsize,
+ unsigned long offset, yasm_bytecode *bc, int warn, /*@null@*/ void *d);
+
+/** Convert a symbol reference to its byte representation. Usually implemented
+ * by object formats and debug formats to keep track of relocations generated
+ * by themselves.
+ * \param sym symbol
+ * \param bc current bytecode (usually passed into higher-level
+ * calling function)
+ * \param buf buffer for byte representation
+ * \param destsize destination size (in bytes)
+ * \param valsize size (in bits)
+ * \param warn enables standard warnings: zero for none;
+ * nonzero for overflow/underflow floating point warnings;
+ * negative for signed integer warnings,
+ * positive for unsigned integer warnings
+ * \param d objfmt-specific data (passed into higher-level calling
+ * function)
+ * \return Nonzero if an error occurred, 0 otherwise.
+ */
+typedef int (*yasm_output_reloc_func)
+ (yasm_symrec *sym, yasm_bytecode *bc, unsigned char *buf,
+ unsigned int destsize, unsigned int valsize, int warn, void *d);
+
+/** Sort an array using merge sort algorithm.
+ * \internal
+ * \param base base of array
+ * \param nmemb number of elements in array
+ * \param size size of each array element
+ * \param compar element comparison function
+ */
+YASM_LIB_DECL
+int yasm__mergesort(void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *));
+
+/** Separate string by delimiters.
+ * \internal
+ * \param stringp string
+ * \param delim set of 1 or more delimiters
+ * \return First/next substring.
+ */
+YASM_LIB_DECL
+/*@null@*/ char *yasm__strsep(char **stringp, const char *delim);
+
+/** Compare two strings, ignoring case differences.
+ * \internal
+ * \param s1 string 1
+ * \param s2 string 2
+ * \return 0 if strings are equal, -1 if s1<s2, 1 if s1>s2.
+ */
+YASM_LIB_DECL
+int yasm__strcasecmp(const char *s1, const char *s2);
+
+/** Compare portion of two strings, ignoring case differences.
+ * \internal
+ * \param s1 string 1
+ * \param s2 string 2
+ * \param n maximum number of characters to compare
+ * \return 0 if strings are equal, -1 if s1<s2, 1 if s1>s2.
+ */
+YASM_LIB_DECL
+int yasm__strncasecmp(const char *s1, const char *s2, size_t n);
+
+/** strdup() implementation using yasm_xmalloc().
+ * \internal
+ * \param str string
+ * \return Newly allocated duplicate string.
+ */
+YASM_LIB_DECL
+/*@only@*/ char *yasm__xstrdup(const char *str);
+
+/** strndup() implementation using yasm_xmalloc().
+ * \internal
+ * \param str string
+ * \param max maximum number of characters to copy
+ * \return Newly allocated duplicate string.
+ */
+YASM_LIB_DECL
+/*@only@*/ char *yasm__xstrndup(const char *str, size_t max);
+
+/** Error-checking memory allocation. A default implementation is provided
+ * that calls yasm_fatal() on allocation errors.
+ * A replacement should \em never return NULL.
+ * \param size number of bytes to allocate
+ * \return Allocated memory block.
+ */
+YASM_LIB_DECL
+extern /*@only@*/ /*@out@*/ void * (*yasm_xmalloc) (size_t size);
+
+/** Error-checking memory allocation (with clear-to-0). A default
+ * implementation is provided that calls yasm_fatal() on allocation errors.
+ * A replacement should \em never return NULL.
+ * \param size number of elements to allocate
+ * \param elsize size (in bytes) of each element
+ * \return Allocated and cleared memory block.
+ */
+YASM_LIB_DECL
+extern /*@only@*/ void * (*yasm_xcalloc) (size_t nelem, size_t elsize);
+
+/** Error-checking memory reallocation. A default implementation is provided
+ * that calls yasm_fatal() on allocation errors. A replacement should
+ * \em never return NULL.
+ * \param oldmem memory block to resize
+ * \param elsize new size, in bytes
+ * \return Re-allocated memory block.
+ */
+YASM_LIB_DECL
+extern /*@only@*/ void * (*yasm_xrealloc)
+ (/*@only@*/ /*@out@*/ /*@returned@*/ /*@null@*/ void *oldmem, size_t size)
+ /*@modifies oldmem@*/;
+
+/** Error-checking memory deallocation. A default implementation is provided
+ * that calls yasm_fatal() on allocation errors.
+ * \param p memory block to free
+ */
+YASM_LIB_DECL
+extern void (*yasm_xfree) (/*@only@*/ /*@out@*/ /*@null@*/ void *p)
+ /*@modifies p@*/;
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/dbgfmt.h b/contrib/tools/yasm/libyasm/dbgfmt.h
new file mode 100644
index 0000000000..2e5ea867ee
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/dbgfmt.h
@@ -0,0 +1,131 @@
+/**
+ * \file libyasm/dbgfmt.h
+ * \brief YASM debug format interface.
+ *
+ * \license
+ * Copyright (C) 2002-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_DBGFMT_H
+#define YASM_DBGFMT_H
+
+#ifndef YASM_DOXYGEN
+/** Base #yasm_dbgfmt structure. Must be present as the first element in any
+ * #yasm_dbgfmt implementation.
+ */
+typedef struct yasm_dbgfmt_base {
+ /** #yasm_dbgfmt_module implementation for this debug format. */
+ const struct yasm_dbgfmt_module *module;
+} yasm_dbgfmt_base;
+#endif
+
+/** Debug format module interface. */
+struct yasm_dbgfmt_module {
+ /** One-line description of the debug format. */
+ const char *name;
+
+ /** Keyword used to select debug format. */
+ const char *keyword;
+
+ /** NULL-terminated list of directives. NULL if none. */
+ /*@null@*/ const yasm_directive *directives;
+
+ /** Create debug format.
+ * Module-level implementation of yasm_dbgfmt_create().
+ * The filenames are provided solely for informational purposes.
+ * \param object object
+ * \return NULL if object format does not provide needed support.
+ */
+ /*@null@*/ /*@only@*/ yasm_dbgfmt * (*create) (yasm_object *object);
+
+ /** Module-level implementation of yasm_dbgfmt_destroy().
+ * Call yasm_dbgfmt_destroy() instead of calling this function.
+ */
+ void (*destroy) (/*@only@*/ yasm_dbgfmt *dbgfmt);
+
+ /** Module-level implementation of yasm_dbgfmt_generate().
+ * Call yasm_dbgfmt_generate() instead of calling this function.
+ */
+ void (*generate) (yasm_object *object, yasm_linemap *linemap,
+ yasm_errwarns *errwarns);
+
+ /**
+ * --replace params
+ */
+ const char** replace_map;
+ /**
+ * Number of elements in replace_map
+ */
+ int replace_map_size;
+};
+
+/** Get the keyword used to select a debug format.
+ * \param dbgfmt debug format
+ * \return keyword
+ */
+const char *yasm_dbgfmt_keyword(const yasm_dbgfmt *dbgfmt);
+
+/** Initialize debug output for use. Must call before any other debug
+ * format functions. The filenames are provided solely for informational
+ * purposes.
+ * \param module debug format module
+ * \param object object to generate debugging information for
+ * \return NULL if object format does not provide needed support.
+ */
+/*@null@*/ /*@only@*/ yasm_dbgfmt *yasm_dbgfmt_create
+ (const yasm_dbgfmt_module *module, yasm_object *object);
+
+/** Cleans up any allocated debug format memory.
+ * \param dbgfmt debug format
+ */
+void yasm_dbgfmt_destroy(/*@only@*/ yasm_dbgfmt *dbgfmt);
+
+/** Generate debugging information bytecodes.
+ * \param object object
+ * \param linemap virtual/physical line mapping
+ * \param errwarns error/warning set
+ * \note Errors and warnings are stored into errwarns.
+ */
+void yasm_dbgfmt_generate(yasm_object *object, yasm_linemap *linemap,
+ yasm_errwarns *errwarns);
+
+#ifndef YASM_DOXYGEN
+
+/* Inline macro implementations for dbgfmt functions */
+
+#define yasm_dbgfmt_keyword(dbgfmt) \
+ (((yasm_dbgfmt_base *)dbgfmt)->module->keyword)
+
+#define yasm_dbgfmt_create(module, object) \
+ module->create(object)
+
+#define yasm_dbgfmt_destroy(dbgfmt) \
+ ((yasm_dbgfmt_base *)dbgfmt)->module->destroy(dbgfmt)
+#define yasm_dbgfmt_generate(object, linemap, ews) \
+ ((yasm_dbgfmt_base *)((object)->dbgfmt))->module->generate \
+ (object, linemap, ews)
+
+#endif
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/errwarn.c b/contrib/tools/yasm/libyasm/errwarn.c
new file mode 100644
index 0000000000..f759cf8f71
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/errwarn.c
@@ -0,0 +1,537 @@
+/*
+ * Error and warning reporting and related functions.
+ *
+ * Copyright (C) 2001-2007 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 "util.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include "coretype.h"
+
+#include "linemap.h"
+#include "errwarn.h"
+
+
+#define MSG_MAXSIZE 1024
+
+#if !defined(HAVE_TOASCII) || defined(lint)
+# define toascii(c) ((c) & 0x7F)
+#endif
+
+/* Default handlers for replacable functions */
+static /*@exits@*/ void def_internal_error_
+ (const char *file, unsigned int line, const char *message);
+static /*@exits@*/ void def_fatal(const char *message, va_list va);
+static const char *def_gettext_hook(const char *msgid);
+
+/* Storage for errwarn's "extern" functions */
+/*@exits@*/ void (*yasm_internal_error_)
+ (const char *file, unsigned int line, const char *message)
+ = def_internal_error_;
+/*@exits@*/ void (*yasm_fatal) (const char *message, va_list va) = def_fatal;
+const char * (*yasm_gettext_hook) (const char *msgid) = def_gettext_hook;
+
+/* Error indicator */
+/* yasm_eclass is not static so that yasm_error_occurred macro can access it */
+yasm_error_class yasm_eclass;
+static /*@only@*/ /*@null@*/ char *yasm_estr;
+static unsigned long yasm_exrefline;
+static /*@only@*/ /*@null@*/ char *yasm_exrefstr;
+
+/* Warning indicator */
+typedef struct warn {
+ /*@reldef@*/ STAILQ_ENTRY(warn) link;
+
+ yasm_warn_class wclass;
+ /*@owned@*/ /*@null@*/ char *wstr;
+} warn;
+static STAILQ_HEAD(warn_head, warn) yasm_warns;
+
+/* Enabled warnings. See errwarn.h for a list. */
+static unsigned long warn_class_enabled;
+
+typedef struct errwarn_data {
+ /*@reldef@*/ SLIST_ENTRY(errwarn_data) link;
+
+ enum { WE_UNKNOWN, WE_ERROR, WE_WARNING, WE_PARSERERROR } type;
+
+ unsigned long line;
+ unsigned long xrefline;
+ /*@owned@*/ char *msg;
+ /*@owned@*/ char *xrefmsg;
+} errwarn_data;
+
+struct yasm_errwarns {
+ /*@reldef@*/ SLIST_HEAD(errwarn_head, errwarn_data) errwarns;
+
+ /* Total error count */
+ unsigned int ecount;
+
+ /* Total warning count */
+ unsigned int wcount;
+
+ /* Last inserted error/warning. Used to speed up insertions. */
+ /*@null@*/ errwarn_data *previous_we;
+};
+
+/* Static buffer for use by conv_unprint(). */
+static char unprint[5];
+
+
+static const char *
+def_gettext_hook(const char *msgid)
+{
+ return msgid;
+}
+
+void
+yasm_errwarn_initialize(void)
+{
+ /* Default enabled warnings. See errwarn.h for a list. */
+ warn_class_enabled =
+ (1UL<<YASM_WARN_GENERAL) | (1UL<<YASM_WARN_UNREC_CHAR) |
+ (1UL<<YASM_WARN_PREPROC) | (0UL<<YASM_WARN_ORPHAN_LABEL) |
+ (1UL<<YASM_WARN_UNINIT_CONTENTS) | (0UL<<YASM_WARN_SIZE_OVERRIDE) |
+ (1UL<<YASM_WARN_IMPLICIT_SIZE_OVERRIDE);
+
+ yasm_eclass = YASM_ERROR_NONE;
+ yasm_estr = NULL;
+ yasm_exrefline = 0;
+ yasm_exrefstr = NULL;
+
+ STAILQ_INIT(&yasm_warns);
+}
+
+void
+yasm_errwarn_cleanup(void)
+{
+ yasm_error_clear();
+ yasm_warn_clear();
+}
+
+/* Convert a possibly unprintable character into a printable string, using
+ * standard cat(1) convention for unprintable characters.
+ */
+char *
+yasm__conv_unprint(int ch)
+{
+ int pos = 0;
+
+ if (((ch & ~0x7F) != 0) /*!isascii(ch)*/ && !isprint(ch)) {
+ unprint[pos++] = 'M';
+ unprint[pos++] = '-';
+ ch &= toascii(ch);
+ }
+ if (iscntrl(ch)) {
+ unprint[pos++] = '^';
+ unprint[pos++] = (ch == '\177') ? '?' : ch | 0100;
+ } else
+ unprint[pos++] = ch;
+ unprint[pos] = '\0';
+
+ return unprint;
+}
+
+/* Report an internal error. Essentially a fatal error with trace info.
+ * Exit immediately because it's essentially an assert() trap.
+ */
+static void
+def_internal_error_(const char *file, unsigned int line, const char *message)
+{
+ fprintf(stderr,
+ yasm_gettext_hook(N_("INTERNAL ERROR at %s, line %u: %s\n")),
+ file, line, yasm_gettext_hook(message));
+#ifdef HAVE_ABORT
+ abort();
+#else
+ exit(EXIT_FAILURE);
+#endif
+}
+
+/* Report a fatal error. These are unrecoverable (such as running out of
+ * memory), so just exit immediately.
+ */
+static void
+def_fatal(const char *fmt, va_list va)
+{
+ fprintf(stderr, "%s: ", yasm_gettext_hook(N_("FATAL")));
+ vfprintf(stderr, yasm_gettext_hook(fmt), va);
+ fputc('\n', stderr);
+ exit(EXIT_FAILURE);
+}
+
+/* Create an errwarn structure in the correct linked list location.
+ * If replace_parser_error is nonzero, overwrites the last error if its
+ * type is WE_PARSERERROR.
+ */
+static errwarn_data *
+errwarn_data_new(yasm_errwarns *errwarns, unsigned long line,
+ int replace_parser_error)
+{
+ errwarn_data *first, *next, *ins_we, *we;
+ enum { INS_NONE, INS_HEAD, INS_AFTER } action = INS_NONE;
+
+ /* Find the entry with either line=line or the last one with line<line.
+ * Start with the last entry added to speed the search.
+ */
+ ins_we = errwarns->previous_we;
+ first = SLIST_FIRST(&errwarns->errwarns);
+ if (!ins_we || !first)
+ action = INS_HEAD;
+ while (action == INS_NONE) {
+ next = SLIST_NEXT(ins_we, link);
+ if (line < ins_we->line) {
+ if (ins_we == first)
+ action = INS_HEAD;
+ else
+ ins_we = first;
+ } else if (!next)
+ action = INS_AFTER;
+ else if (line >= ins_we->line && line < next->line)
+ action = INS_AFTER;
+ else
+ ins_we = next;
+ }
+
+ if (replace_parser_error && ins_we && ins_we->type == WE_PARSERERROR) {
+ /* overwrite last error */
+ we = ins_we;
+ } else {
+ /* add a new error */
+ we = yasm_xmalloc(sizeof(errwarn_data));
+
+ we->type = WE_UNKNOWN;
+ we->line = line;
+ we->xrefline = 0;
+ we->msg = NULL;
+ we->xrefmsg = NULL;
+
+ if (action == INS_HEAD)
+ SLIST_INSERT_HEAD(&errwarns->errwarns, we, link);
+ else if (action == INS_AFTER) {
+ assert(ins_we != NULL);
+ SLIST_INSERT_AFTER(ins_we, we, link);
+ } else
+ yasm_internal_error(N_("Unexpected errwarn insert action"));
+ }
+
+ /* Remember previous err/warn */
+ errwarns->previous_we = we;
+
+ return we;
+}
+
+void
+yasm_error_clear(void)
+{
+ if (yasm_estr)
+ yasm_xfree(yasm_estr);
+ if (yasm_exrefstr)
+ yasm_xfree(yasm_exrefstr);
+ yasm_eclass = YASM_ERROR_NONE;
+ yasm_estr = NULL;
+ yasm_exrefline = 0;
+ yasm_exrefstr = NULL;
+}
+
+int
+yasm_error_matches(yasm_error_class eclass)
+{
+ if (yasm_eclass == YASM_ERROR_NONE)
+ return eclass == YASM_ERROR_NONE;
+ if (yasm_eclass == YASM_ERROR_GENERAL)
+ return eclass == YASM_ERROR_GENERAL;
+ return (yasm_eclass & eclass) == eclass;
+}
+
+void
+yasm_error_set_va(yasm_error_class eclass, const char *format, va_list va)
+{
+ if (yasm_eclass != YASM_ERROR_NONE)
+ return;
+
+ yasm_eclass = eclass;
+ yasm_estr = yasm_xmalloc(MSG_MAXSIZE+1);
+#ifdef HAVE_VSNPRINTF
+ vsnprintf(yasm_estr, MSG_MAXSIZE, yasm_gettext_hook(format), va);
+#else
+ vsprintf(yasm_estr, yasm_gettext_hook(format), va);
+#endif
+}
+
+void
+yasm_error_set(yasm_error_class eclass, const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+ yasm_error_set_va(eclass, format, va);
+ va_end(va);
+}
+
+void
+yasm_error_set_xref_va(unsigned long xrefline, const char *format, va_list va)
+{
+ if (yasm_eclass != YASM_ERROR_NONE)
+ return;
+
+ yasm_exrefline = xrefline;
+
+ yasm_exrefstr = yasm_xmalloc(MSG_MAXSIZE+1);
+#ifdef HAVE_VSNPRINTF
+ vsnprintf(yasm_exrefstr, MSG_MAXSIZE, yasm_gettext_hook(format), va);
+#else
+ vsprintf(yasm_exrefstr, yasm_gettext_hook(format), va);
+#endif
+}
+
+void
+yasm_error_set_xref(unsigned long xrefline, const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+ yasm_error_set_xref_va(xrefline, format, va);
+ va_end(va);
+}
+
+void
+yasm_error_fetch(yasm_error_class *eclass, char **str, unsigned long *xrefline,
+ char **xrefstr)
+{
+ *eclass = yasm_eclass;
+ *str = yasm_estr;
+ *xrefline = yasm_exrefline;
+ *xrefstr = yasm_exrefstr;
+ yasm_eclass = YASM_ERROR_NONE;
+ yasm_estr = NULL;
+ yasm_exrefline = 0;
+ yasm_exrefstr = NULL;
+}
+
+void yasm_warn_clear(void)
+{
+ /* Delete all error/warnings */
+ while (!STAILQ_EMPTY(&yasm_warns)) {
+ warn *w = STAILQ_FIRST(&yasm_warns);
+
+ if (w->wstr)
+ yasm_xfree(w->wstr);
+
+ STAILQ_REMOVE_HEAD(&yasm_warns, link);
+ yasm_xfree(w);
+ }
+}
+
+yasm_warn_class
+yasm_warn_occurred(void)
+{
+ if (STAILQ_EMPTY(&yasm_warns))
+ return YASM_WARN_NONE;
+ return STAILQ_FIRST(&yasm_warns)->wclass;
+}
+
+void
+yasm_warn_set_va(yasm_warn_class wclass, const char *format, va_list va)
+{
+ warn *w;
+
+ if (!(warn_class_enabled & (1UL<<wclass)))
+ return; /* warning is part of disabled class */
+
+ w = yasm_xmalloc(sizeof(warn));
+ w->wclass = wclass;
+ w->wstr = yasm_xmalloc(MSG_MAXSIZE+1);
+#ifdef HAVE_VSNPRINTF
+ vsnprintf(w->wstr, MSG_MAXSIZE, yasm_gettext_hook(format), va);
+#else
+ vsprintf(w->wstr, yasm_gettext_hook(format), va);
+#endif
+ STAILQ_INSERT_TAIL(&yasm_warns, w, link);
+}
+
+void
+yasm_warn_set(yasm_warn_class wclass, const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+ yasm_warn_set_va(wclass, format, va);
+ va_end(va);
+}
+
+void
+yasm_warn_fetch(yasm_warn_class *wclass, char **str)
+{
+ warn *w = STAILQ_FIRST(&yasm_warns);
+
+ if (!w) {
+ *wclass = YASM_WARN_NONE;
+ *str = NULL;
+ return;
+ }
+
+ *wclass = w->wclass;
+ *str = w->wstr;
+
+ STAILQ_REMOVE_HEAD(&yasm_warns, link);
+ yasm_xfree(w);
+}
+
+void
+yasm_warn_enable(yasm_warn_class num)
+{
+ warn_class_enabled |= (1UL<<num);
+}
+
+void
+yasm_warn_disable(yasm_warn_class num)
+{
+ warn_class_enabled &= ~(1UL<<num);
+}
+
+void
+yasm_warn_disable_all(void)
+{
+ warn_class_enabled = 0;
+}
+
+yasm_errwarns *
+yasm_errwarns_create(void)
+{
+ yasm_errwarns *errwarns = yasm_xmalloc(sizeof(yasm_errwarns));
+ SLIST_INIT(&errwarns->errwarns);
+ errwarns->ecount = 0;
+ errwarns->wcount = 0;
+ errwarns->previous_we = NULL;
+ return errwarns;
+}
+
+void
+yasm_errwarns_destroy(yasm_errwarns *errwarns)
+{
+ errwarn_data *we;
+
+ /* Delete all error/warnings */
+ while (!SLIST_EMPTY(&errwarns->errwarns)) {
+ we = SLIST_FIRST(&errwarns->errwarns);
+ if (we->msg)
+ yasm_xfree(we->msg);
+ if (we->xrefmsg)
+ yasm_xfree(we->xrefmsg);
+
+ SLIST_REMOVE_HEAD(&errwarns->errwarns, link);
+ yasm_xfree(we);
+ }
+
+ yasm_xfree(errwarns);
+}
+
+void
+yasm_errwarn_propagate(yasm_errwarns *errwarns, unsigned long line)
+{
+ if (yasm_eclass != YASM_ERROR_NONE) {
+ errwarn_data *we = errwarn_data_new(errwarns, line, 1);
+ yasm_error_class eclass;
+
+ yasm_error_fetch(&eclass, &we->msg, &we->xrefline, &we->xrefmsg);
+ if (eclass != YASM_ERROR_GENERAL
+ && (eclass & YASM_ERROR_PARSE) == YASM_ERROR_PARSE)
+ we->type = WE_PARSERERROR;
+ else
+ we->type = WE_ERROR;
+ errwarns->ecount++;
+ }
+
+ while (!STAILQ_EMPTY(&yasm_warns)) {
+ errwarn_data *we = errwarn_data_new(errwarns, line, 0);
+ yasm_warn_class wclass;
+
+ yasm_warn_fetch(&wclass, &we->msg);
+ we->type = WE_WARNING;
+ errwarns->wcount++;
+ }
+}
+
+unsigned int
+yasm_errwarns_num_errors(yasm_errwarns *errwarns, int warning_as_error)
+{
+ if (warning_as_error)
+ return errwarns->ecount+errwarns->wcount;
+ else
+ return errwarns->ecount;
+}
+
+void
+yasm_errwarns_output_all(yasm_errwarns *errwarns, yasm_linemap *lm,
+ int warning_as_error,
+ yasm_print_error_func print_error,
+ yasm_print_warning_func print_warning)
+{
+ errwarn_data *we;
+ const char *filename, *xref_filename;
+ unsigned long line, xref_line;
+
+ /* If we're treating warnings as errors, tell the user about it. */
+ if (warning_as_error && warning_as_error != 2) {
+ print_error("", 0,
+ yasm_gettext_hook(N_("warnings being treated as errors")),
+ NULL, 0, NULL);
+ warning_as_error = 2;
+ }
+
+ /* Output error/warnings. */
+ SLIST_FOREACH(we, &errwarns->errwarns, link) {
+ /* Output error/warning */
+ yasm_linemap_lookup(lm, we->line, &filename, &line);
+ if (we->xrefline)
+ yasm_linemap_lookup(lm, we->xrefline, &xref_filename, &xref_line);
+ else {
+ xref_filename = NULL;
+ xref_line = 0;
+ }
+ if (we->type == WE_ERROR || we->type == WE_PARSERERROR)
+ print_error(filename, line, we->msg, xref_filename, xref_line,
+ we->xrefmsg);
+ else
+ print_warning(filename, line, we->msg);
+ }
+}
+
+void
+yasm__fatal(const char *message, ...)
+{
+ va_list va;
+ va_start(va, message);
+ yasm_fatal(message, va);
+ /*@notreached@*/
+ va_end(va);
+}
+
+void
+yasm__fatal_missing_input_file(const char *message, const char *filename)
+{
+ fprintf(stderr, "%s: %s %s (%s)\n", yasm_gettext_hook(N_("FATAL")), yasm_gettext_hook(message), strerror(errno), yasm_gettext_hook(filename));
+ exit(EXIT_FAILURE);
+}
diff --git a/contrib/tools/yasm/libyasm/errwarn.h b/contrib/tools/yasm/libyasm/errwarn.h
new file mode 100644
index 0000000000..f8e4f10ec3
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/errwarn.h
@@ -0,0 +1,351 @@
+/**
+ * \file libyasm/errwarn.h
+ * \brief YASM error and warning reporting interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_ERRWARN_H
+#define YASM_ERRWARN_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Warning classes (that may be enabled/disabled). */
+typedef enum yasm_warn_class {
+ YASM_WARN_NONE = 0, /**< No warning */
+ YASM_WARN_GENERAL, /**< Non-specific warnings */
+ YASM_WARN_UNREC_CHAR, /**< Unrecognized characters (while tokenizing) */
+ YASM_WARN_PREPROC, /**< Preprocessor warnings */
+ YASM_WARN_ORPHAN_LABEL, /**< Label alone on a line without a colon */
+ YASM_WARN_UNINIT_CONTENTS, /**< Uninitialized space in code/data section */
+ YASM_WARN_SIZE_OVERRIDE,/**< Double size override */
+ YASM_WARN_IMPLICIT_SIZE_OVERRIDE /**< Implicit size override */
+} yasm_warn_class;
+
+/** Error classes. Bitmask-based to support limited subclassing. */
+typedef enum yasm_error_class {
+ YASM_ERROR_NONE = 0x0000, /**< No error */
+ YASM_ERROR_GENERAL = 0xFFFF, /**< Non-specific */
+ YASM_ERROR_ARITHMETIC = 0x0001, /**< Arithmetic error (general) */
+ YASM_ERROR_OVERFLOW = 0x8001, /**< Arithmetic overflow */
+ YASM_ERROR_FLOATING_POINT = 0x4001, /**< Floating point error */
+ YASM_ERROR_ZERO_DIVISION = 0x2001, /**< Divide-by-zero */
+ YASM_ERROR_ASSERTION = 0x0002, /**< Assertion error */
+ YASM_ERROR_VALUE = 0x0004, /**< Value inappropriate
+ * (e.g. not in range) */
+ YASM_ERROR_NOT_ABSOLUTE = 0x8004, /**< Absolute expression required */
+ YASM_ERROR_TOO_COMPLEX = 0x4004, /**< Expression too complex */
+ YASM_ERROR_NOT_CONSTANT = 0x2004, /**< Constant expression required */
+ YASM_ERROR_IO = 0x0008, /**< I/O error */
+ YASM_ERROR_NOT_IMPLEMENTED = 0x0010, /**< Not implemented error */
+ YASM_ERROR_TYPE = 0x0020, /**< Type error */
+ YASM_ERROR_SYNTAX = 0x0040, /**< Syntax error */
+ YASM_ERROR_PARSE = 0x8040 /**< Parser error */
+} yasm_error_class;
+
+/** Initialize any internal data structures. */
+YASM_LIB_DECL
+void yasm_errwarn_initialize(void);
+
+/** Clean up any memory allocated by yasm_errwarn_initialize() or other
+ * functions.
+ */
+YASM_LIB_DECL
+void yasm_errwarn_cleanup(void);
+
+/** Reporting point of internal errors. These are usually due to sanity
+ * check failures in the code.
+ * \warning This function must NOT return to calling code; exit or longjmp
+ * instead.
+ * \param file source file (ala __FILE__)
+ * \param line source line (ala __LINE__)
+ * \param message internal error message
+ */
+YASM_LIB_DECL
+extern /*@exits@*/ void (*yasm_internal_error_)
+ (const char *file, unsigned int line, const char *message);
+
+/** Easily-callable version of yasm_internal_error_(). Automatically uses
+ * __FILE__ and __LINE__ as the file and line.
+ * \param message internal error message
+ */
+#define yasm_internal_error(message) \
+ yasm_internal_error_(__FILE__, __LINE__, message)
+
+/** Reporting point of fatal errors.
+ * \warning This function must NOT return to calling code; exit or longjmp
+ * instead.
+ * \param message fatal error message
+ * \param va va_list argument list for message
+ */
+YASM_LIB_DECL
+extern /*@exits@*/ void (*yasm_fatal) (const char *message, va_list va);
+
+/** Reporting point of fatal errors, with variable arguments (internal only).
+ * \warning This function calls #yasm_fatal, and thus does not return to the
+ * calling code.
+ * \param message fatal error message
+ * \param ... argument list for message
+ */
+YASM_LIB_DECL
+/*@exits@*/ void yasm__fatal(const char *message, ...);
+
+YASM_LIB_DECL
+/*@exits@*/ void yasm__fatal_missing_input_file(const char *message, const char *filename);
+
+/** Unconditionally clear the error indicator, freeing any associated data.
+ * Has no effect if the error indicator is not set.
+ */
+YASM_LIB_DECL
+void yasm_error_clear(void);
+
+/** Get the error indicator. YASM_ERROR_NONE is returned if no error has
+ * been set. Note that as YASM_ERROR_NONE is 0, the return value can also
+ * be treated as a boolean value.
+ * \return Current error indicator.
+ */
+yasm_error_class yasm_error_occurred(void);
+
+/** Check the error indicator against an error class. To check if any error
+ * has been set, check against the YASM_ERROR_GENERAL class. This function
+ * properly checks error subclasses.
+ * \param eclass base error class to check against
+ * \return Nonzero if error indicator is set and a subclass of eclass, 0
+ * otherwise.
+ */
+YASM_LIB_DECL
+int yasm_error_matches(yasm_error_class eclass);
+
+#ifndef YASM_DOXYGEN
+YASM_LIB_DECL
+extern yasm_error_class yasm_eclass;
+#define yasm_error_occurred() yasm_eclass
+#endif
+
+/** Set the error indicator (va_list version). Has no effect if the error
+ * indicator is already set.
+ * \param eclass error class
+ * \param format printf format string
+ * \param va argument list for format
+ */
+YASM_LIB_DECL
+void yasm_error_set_va(yasm_error_class eclass, const char *format, va_list va);
+
+/** Set the error indicator. Has no effect if the error indicator is already
+ * set.
+ * \param eclass error class
+ * \param format printf format string
+ * \param ... argument list for format
+ */
+YASM_LIB_DECL
+void yasm_error_set(yasm_error_class eclass, const char *format, ...)
+ /*@printflike@*/;
+
+/** Set a cross-reference for a new error (va_list version). Has no effect
+ * if the error indicator is already set (e.g. with yasm_error_set()). This
+ * function must be called prior to its corresponding yasm_error_set() call.
+ * \param xrefline virtual line to cross-reference to (should not be 0)
+ * \param format printf format string
+ * \param va argument list for format
+ */
+YASM_LIB_DECL
+void yasm_error_set_xref_va(unsigned long xrefline, const char *format,
+ va_list va);
+
+/** Set a cross-reference for a new error. Has no effect if the error
+ * indicator is already set (e.g. with yasm_error_set()). This function
+ * must be called prior to its corresponding yasm_error_set() call.
+ * \param xrefline virtual line to cross-reference to (should not be 0)
+ * \param format printf format string
+ * \param ... argument list for format
+ */
+YASM_LIB_DECL
+void yasm_error_set_xref(unsigned long xrefline, const char *format, ...)
+ /*@printflike@*/;
+
+/** Fetch the error indicator and all associated data. If the error
+ * indicator is set, the output pointers are set to the current error
+ * indicator values, and the error indicator is cleared.
+ * The code using this function is then responsible for yasm_xfree()'ing
+ * str and xrefstr (if non-NULL). If the error indicator is not set,
+ * all output values are set to 0 (including eclass, which is set to
+ * YASM_ERROR_NONE).
+ * \param eclass error class (output)
+ * \param str error message
+ * \param xrefline virtual line used for cross-referencing (0 if no xref)
+ * \param xrefstr cross-reference error message (NULL if no xref)
+ */
+YASM_LIB_DECL
+void yasm_error_fetch(/*@out@*/ yasm_error_class *eclass,
+ /*@out@*/ /*@only@*/ /*@null@*/ char **str,
+ /*@out@*/ unsigned long *xrefline,
+ /*@out@*/ /*@only@*/ /*@null@*/ char **xrefstr);
+
+/** Unconditionally clear all warning indicators, freeing any associated data.
+ * Has no effect if no warning indicators have been set.
+ */
+YASM_LIB_DECL
+void yasm_warn_clear(void);
+
+/** Get the first warning indicator. YASM_WARN_NONE is returned if no warning
+ * has been set. Note that as YASM_WARN_NONE is 0, the return value can also
+ * be treated as a boolean value.
+ * \return First warning indicator.
+ */
+YASM_LIB_DECL
+yasm_warn_class yasm_warn_occurred(void);
+
+/** Add a warning indicator (va_list version).
+ * \param wclass warning class
+ * \param format printf format string
+ * \param va argument list for format
+ */
+YASM_LIB_DECL
+void yasm_warn_set_va(yasm_warn_class wclass, const char *format, va_list va);
+
+/** Add a warning indicator.
+ * \param wclass warning class
+ * \param format printf format string
+ * \param ... argument list for format
+ */
+YASM_LIB_DECL
+void yasm_warn_set(yasm_warn_class wclass, const char *format, ...)
+ /*@printflike@*/;
+
+/** Fetch the first warning indicator and all associated data. If there
+ * is at least one warning indicator, the output pointers are set to the
+ * first warning indicator values, and first warning indicator is removed.
+ * The code using this function is then responsible for yasm_xfree()'ing
+ * str and xrefstr (if non-NULL). If there is no warning indicator set,
+ * all output values are set to 0 (including wclass, which is set to
+ * YASM_WARN_NONE).
+ * \param wclass warning class (output)
+ * \param str warning message
+ */
+YASM_LIB_DECL
+void yasm_warn_fetch(/*@out@*/ yasm_warn_class *wclass,
+ /*@out@*/ /*@only@*/ char **str);
+
+/** Enable a class of warnings.
+ * \param wclass warning class
+ */
+YASM_LIB_DECL
+void yasm_warn_enable(yasm_warn_class wclass);
+
+/** Disable a class of warnings.
+ * \param wclass warning class
+ */
+YASM_LIB_DECL
+void yasm_warn_disable(yasm_warn_class wclass);
+
+/** Disable all classes of warnings. */
+YASM_LIB_DECL
+void yasm_warn_disable_all(void);
+
+/** Create an error/warning set for collection of multiple error/warnings.
+ * \return Newly allocated set.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_errwarns *yasm_errwarns_create(void);
+
+/** Destroy an error/warning set.
+ * \param errwarns error/warning set
+ */
+YASM_LIB_DECL
+void yasm_errwarns_destroy(/*@only@*/ yasm_errwarns *errwarns);
+
+/** Propagate error indicator and warning indicator(s) to an error/warning set.
+ * Has no effect if the error indicator and warning indicator are not set.
+ * Does not print immediately; yasm_errwarn_output_all() outputs
+ * accumulated errors and warnings.
+ * Generally multiple errors on the same line will be reported, but errors
+ * of class YASM_ERROR_PARSE will get overwritten by any other class on the
+ * same line.
+ * \param errwarns error/warning set
+ * \param line virtual line
+ */
+YASM_LIB_DECL
+void yasm_errwarn_propagate(yasm_errwarns *errwarns, unsigned long line);
+
+/** Get total number of errors logged.
+ * \param errwarns error/warning set
+ * \param warning_as_error if nonzero, warnings are treated as errors.
+ * \return Number of errors.
+ */
+YASM_LIB_DECL
+unsigned int yasm_errwarns_num_errors(yasm_errwarns *errwarns,
+ int warning_as_error);
+
+/** Print out an error.
+ * \param fn filename of source file
+ * \param line line number
+ * \param msg error message
+ * \param xref_fn cross-referenced source filename
+ * \param xref_line cross-referenced line number
+ * \param xref_msg cross-referenced error message
+ */
+typedef void (*yasm_print_error_func)
+ (const char *fn, unsigned long line, const char *msg,
+ /*@null@*/ const char *xref_fn, unsigned long xref_line,
+ /*@null@*/ const char *xref_msg);
+
+/** Print out a warning.
+ * \param fn filename of source file
+ * \param line line number
+ * \param msg warning message
+ */
+typedef void (*yasm_print_warning_func)
+ (const char *fn, unsigned long line, const char *msg);
+
+/** Outputs error/warning set in sorted order (sorted by virtual line number).
+ * \param errwarns error/warning set
+ * \param lm line map (to convert virtual lines into filename/line pairs)
+ * \param warning_as_error if nonzero, treat warnings as errors.
+ * \param print_error function called to print out errors
+ * \param print_warning function called to print out warnings
+ */
+YASM_LIB_DECL
+void yasm_errwarns_output_all
+ (yasm_errwarns *errwarns, yasm_linemap *lm, int warning_as_error,
+ yasm_print_error_func print_error, yasm_print_warning_func print_warning);
+
+/** Convert a possibly unprintable character into a printable string.
+ * \internal
+ * \param ch possibly unprintable character
+ * \return Printable string representation (static buffer).
+ */
+YASM_LIB_DECL
+char *yasm__conv_unprint(int ch);
+
+/** Hook for library users to map to gettext() if GNU gettext is being used.
+ * \param msgid message catalog identifier
+ * \return Translated message.
+ */
+YASM_LIB_DECL
+extern const char * (*yasm_gettext_hook) (const char *msgid);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/expr.c b/contrib/tools/yasm/libyasm/expr.c
new file mode 100644
index 0000000000..c2c868ede2
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/expr.c
@@ -0,0 +1,1516 @@
+/*
+ * Expression handling
+ *
+ * Copyright (C) 2001-2007 Michael Urman, 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 "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+#include "bitvect.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "floatnum.h"
+#include "expr.h"
+#include "symrec.h"
+
+#include "bytecode.h"
+#include "section.h"
+
+#include "arch.h"
+
+
+static /*@only@*/ yasm_expr *expr_level_op
+ (/*@returned@*/ /*@only@*/ yasm_expr *e, int fold_const,
+ int simplify_ident, int simplify_reg_mul);
+static int expr_traverse_nodes_post(/*@null@*/ yasm_expr *e,
+ /*@null@*/ void *d,
+ int (*func) (/*@null@*/ yasm_expr *e,
+ /*@null@*/ void *d));
+static void expr_delete_term(yasm_expr__item *term, int recurse);
+
+/* Bitmap of used items. We should really never need more than 2 at a time,
+ * so 31 is pretty much overkill.
+ */
+static unsigned long itempool_used = 0;
+static yasm_expr__item itempool[31];
+
+/* allocate a new expression node, with children as defined.
+ * If it's a unary operator, put the element in left and set right=NULL. */
+/*@-compmempass@*/
+yasm_expr *
+yasm_expr_create(yasm_expr_op op, yasm_expr__item *left,
+ yasm_expr__item *right, unsigned long line)
+{
+ yasm_expr *ptr, *sube;
+ unsigned long z;
+ ptr = yasm_xmalloc(sizeof(yasm_expr));
+
+ ptr->op = op;
+ ptr->numterms = 0;
+ ptr->terms[0].type = YASM_EXPR_NONE;
+ ptr->terms[1].type = YASM_EXPR_NONE;
+ if (left) {
+ ptr->terms[0] = *left; /* structure copy */
+ z = (unsigned long)(left-itempool);
+ if (z>=31)
+ yasm_internal_error(N_("could not find expritem in pool"));
+ itempool_used &= ~(1<<z);
+ ptr->numterms++;
+
+ /* Search downward until we find something *other* than an
+ * IDENT, then bring it up to the current level.
+ */
+ while (ptr->terms[0].type == YASM_EXPR_EXPR &&
+ ptr->terms[0].data.expn->op == YASM_EXPR_IDENT) {
+ sube = ptr->terms[0].data.expn;
+ ptr->terms[0] = sube->terms[0]; /* structure copy */
+ /*@-usereleased@*/
+ yasm_xfree(sube);
+ /*@=usereleased@*/
+ }
+ } else {
+ yasm_internal_error(N_("Right side of expression must exist"));
+ }
+
+ if (right) {
+ ptr->terms[1] = *right; /* structure copy */
+ z = (unsigned long)(right-itempool);
+ if (z>=31)
+ yasm_internal_error(N_("could not find expritem in pool"));
+ itempool_used &= ~(1<<z);
+ ptr->numterms++;
+
+ /* Search downward until we find something *other* than an
+ * IDENT, then bring it up to the current level.
+ */
+ while (ptr->terms[1].type == YASM_EXPR_EXPR &&
+ ptr->terms[1].data.expn->op == YASM_EXPR_IDENT) {
+ sube = ptr->terms[1].data.expn;
+ ptr->terms[1] = sube->terms[0]; /* structure copy */
+ /*@-usereleased@*/
+ yasm_xfree(sube);
+ /*@=usereleased@*/
+ }
+ }
+
+ ptr->line = line;
+
+ return expr_level_op(ptr, 1, 1, 0);
+}
+/*@=compmempass@*/
+
+/* helpers */
+static yasm_expr__item *
+expr_get_item(void)
+{
+ int z = 0;
+ unsigned long v = itempool_used & 0x7fffffff;
+
+ while (v & 1) {
+ v >>= 1;
+ z++;
+ }
+ if (z>=31)
+ yasm_internal_error(N_("too many expritems"));
+ itempool_used |= 1<<z;
+ return &itempool[z];
+}
+
+yasm_expr__item *
+yasm_expr_precbc(yasm_bytecode *precbc)
+{
+ yasm_expr__item *e = expr_get_item();
+ e->type = YASM_EXPR_PRECBC;
+ e->data.precbc = precbc;
+ return e;
+}
+
+yasm_expr__item *
+yasm_expr_sym(yasm_symrec *s)
+{
+ yasm_expr__item *e = expr_get_item();
+ e->type = YASM_EXPR_SYM;
+ e->data.sym = s;
+ return e;
+}
+
+yasm_expr__item *
+yasm_expr_expr(yasm_expr *x)
+{
+ yasm_expr__item *e = expr_get_item();
+ e->type = YASM_EXPR_EXPR;
+ e->data.expn = x;
+ return e;
+}
+
+yasm_expr__item *
+yasm_expr_int(yasm_intnum *i)
+{
+ yasm_expr__item *e = expr_get_item();
+ e->type = YASM_EXPR_INT;
+ e->data.intn = i;
+ return e;
+}
+
+yasm_expr__item *
+yasm_expr_float(yasm_floatnum *f)
+{
+ yasm_expr__item *e = expr_get_item();
+ e->type = YASM_EXPR_FLOAT;
+ e->data.flt = f;
+ return e;
+}
+
+yasm_expr__item *
+yasm_expr_reg(uintptr_t reg)
+{
+ yasm_expr__item *e = expr_get_item();
+ e->type = YASM_EXPR_REG;
+ e->data.reg = reg;
+ return e;
+}
+
+/* Transforms instances of symrec-symrec [symrec+(-1*symrec)] into single
+ * expritems if possible. Uses a simple n^2 algorithm because n is usually
+ * quite small. Also works for precbc-precbc (or symrec-precbc,
+ * precbc-symrec).
+ */
+static /*@only@*/ yasm_expr *
+expr_xform_bc_dist_base(/*@returned@*/ /*@only@*/ yasm_expr *e,
+ /*@null@*/ void *cbd,
+ int (*callback) (yasm_expr__item *ei,
+ yasm_bytecode *precbc,
+ yasm_bytecode *precbc2,
+ void *cbd))
+{
+ int i;
+ /*@dependent@*/ yasm_section *sect;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
+ int numterms;
+
+ /* Handle symrec-symrec in ADD exprs by looking for (-1*symrec) and
+ * symrec term pairs (where both symrecs are in the same segment).
+ */
+ if (e->op != YASM_EXPR_ADD)
+ return e;
+
+ for (i=0; i<e->numterms; i++) {
+ int j;
+ yasm_expr *sube;
+ yasm_intnum *intn;
+ yasm_symrec *sym = NULL;
+ /*@dependent@*/ yasm_section *sect2;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc2;
+
+ /* First look for an (-1*symrec) term */
+ if (e->terms[i].type != YASM_EXPR_EXPR)
+ continue;
+ sube = e->terms[i].data.expn;
+ if (sube->op != YASM_EXPR_MUL || sube->numterms != 2)
+ continue;
+
+ if (sube->terms[0].type == YASM_EXPR_INT &&
+ (sube->terms[1].type == YASM_EXPR_SYM ||
+ sube->terms[1].type == YASM_EXPR_PRECBC)) {
+ intn = sube->terms[0].data.intn;
+ if (sube->terms[1].type == YASM_EXPR_PRECBC)
+ precbc = sube->terms[1].data.precbc;
+ else
+ sym = sube->terms[1].data.sym;
+ } else if ((sube->terms[0].type == YASM_EXPR_SYM ||
+ sube->terms[0].type == YASM_EXPR_PRECBC) &&
+ sube->terms[1].type == YASM_EXPR_INT) {
+ if (sube->terms[0].type == YASM_EXPR_PRECBC)
+ precbc = sube->terms[0].data.precbc;
+ else
+ sym = sube->terms[0].data.sym;
+ intn = sube->terms[1].data.intn;
+ } else
+ continue;
+
+ if (!yasm_intnum_is_neg1(intn))
+ continue;
+
+ if (sym && !yasm_symrec_get_label(sym, &precbc))
+ continue;
+ sect2 = yasm_bc_get_section(precbc);
+
+ /* Now look for a symrec term in the same segment */
+ for (j=0; j<e->numterms; j++) {
+ if (((e->terms[j].type == YASM_EXPR_SYM &&
+ yasm_symrec_get_label(e->terms[j].data.sym, &precbc2)) ||
+ (e->terms[j].type == YASM_EXPR_PRECBC &&
+ (precbc2 = e->terms[j].data.precbc))) &&
+ (sect = yasm_bc_get_section(precbc2)) &&
+ sect == sect2 &&
+ callback(&e->terms[j], precbc, precbc2, cbd)) {
+ /* Delete the matching (-1*symrec) term */
+ yasm_expr_destroy(sube);
+ e->terms[i].type = YASM_EXPR_NONE;
+ break; /* stop looking for matching symrec term */
+ }
+ }
+ }
+
+ /* Clean up any deleted (EXPR_NONE) terms */
+ numterms = 0;
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type != YASM_EXPR_NONE)
+ e->terms[numterms++] = e->terms[i]; /* structure copy */
+ }
+ if (e->numterms != numterms) {
+ e->numterms = numterms;
+ e = yasm_xrealloc(e, sizeof(yasm_expr)+((numterms<2) ? 0 :
+ sizeof(yasm_expr__item)*(numterms-2)));
+ if (numterms == 1)
+ e->op = YASM_EXPR_IDENT;
+ }
+
+ return e;
+}
+
+static int
+expr_xform_bc_dist_cb(yasm_expr__item *ei, yasm_bytecode *precbc,
+ yasm_bytecode *precbc2, /*@null@*/ void *d)
+{
+ yasm_intnum *dist = yasm_calc_bc_dist(precbc, precbc2);
+ if (!dist)
+ return 0;
+ /* Change the term to an integer */
+ ei->type = YASM_EXPR_INT;
+ ei->data.intn = dist;
+ return 1;
+}
+
+/* Transforms instances of symrec-symrec [symrec+(-1*symrec)] into integers if
+ * possible.
+ */
+static /*@only@*/ yasm_expr *
+expr_xform_bc_dist(/*@returned@*/ /*@only@*/ yasm_expr *e)
+{
+ return expr_xform_bc_dist_base(e, NULL, expr_xform_bc_dist_cb);
+}
+
+typedef struct bc_dist_subst_cbd {
+ void (*callback) (unsigned int subst, yasm_bytecode *precbc,
+ yasm_bytecode *precbc2, void *cbd);
+ void *cbd;
+ unsigned int subst;
+} bc_dist_subst_cbd;
+
+static int
+expr_bc_dist_subst_cb(yasm_expr__item *ei, yasm_bytecode *precbc,
+ yasm_bytecode *precbc2, /*@null@*/ void *d)
+{
+ bc_dist_subst_cbd *my_cbd = d;
+ assert(my_cbd != NULL);
+ /* Call higher-level callback */
+ my_cbd->callback(my_cbd->subst, precbc, precbc2, my_cbd->cbd);
+ /* Change the term to an subst */
+ ei->type = YASM_EXPR_SUBST;
+ ei->data.subst = my_cbd->subst;
+ my_cbd->subst++;
+ return 1;
+}
+
+static yasm_expr *
+expr_xform_bc_dist_subst(yasm_expr *e, void *d)
+{
+ return expr_xform_bc_dist_base(e, d, expr_bc_dist_subst_cb);
+}
+
+int
+yasm_expr__bc_dist_subst(yasm_expr **ep, void *cbd,
+ void (*callback) (unsigned int subst,
+ yasm_bytecode *precbc,
+ yasm_bytecode *precbc2,
+ void *cbd))
+{
+ bc_dist_subst_cbd my_cbd; /* callback info for low-level callback */
+ my_cbd.callback = callback;
+ my_cbd.cbd = cbd;
+ my_cbd.subst = 0;
+ *ep = yasm_expr__level_tree(*ep, 1, 1, 1, 0, &expr_xform_bc_dist_subst,
+ &my_cbd);
+ return my_cbd.subst;
+}
+
+/* Negate just a single ExprItem by building a -1*ei subexpression */
+static void
+expr_xform_neg_item(yasm_expr *e, yasm_expr__item *ei)
+{
+ yasm_expr *sube = yasm_xmalloc(sizeof(yasm_expr));
+
+ /* Build -1*ei subexpression */
+ sube->op = YASM_EXPR_MUL;
+ sube->line = e->line;
+ sube->numterms = 2;
+ sube->terms[0].type = YASM_EXPR_INT;
+ sube->terms[0].data.intn = yasm_intnum_create_int(-1);
+ sube->terms[1] = *ei; /* structure copy */
+
+ /* Replace original ExprItem with subexp */
+ ei->type = YASM_EXPR_EXPR;
+ ei->data.expn = sube;
+}
+
+/* Negates e by multiplying by -1, with distribution over lower-precedence
+ * operators (eg ADD) and special handling to simplify result w/ADD, NEG, and
+ * others.
+ *
+ * Returns a possibly reallocated e.
+ */
+static /*@only@*/ yasm_expr *
+expr_xform_neg_helper(/*@returned@*/ /*@only@*/ yasm_expr *e)
+{
+ yasm_expr *ne;
+ int i;
+
+ switch (e->op) {
+ case YASM_EXPR_ADD:
+ /* distribute (recursively if expr) over terms */
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_EXPR)
+ e->terms[i].data.expn =
+ expr_xform_neg_helper(e->terms[i].data.expn);
+ else
+ expr_xform_neg_item(e, &e->terms[i]);
+ }
+ break;
+ case YASM_EXPR_SUB:
+ /* change op to ADD, and recursively negate left side (if expr) */
+ e->op = YASM_EXPR_ADD;
+ if (e->terms[0].type == YASM_EXPR_EXPR)
+ e->terms[0].data.expn =
+ expr_xform_neg_helper(e->terms[0].data.expn);
+ else
+ expr_xform_neg_item(e, &e->terms[0]);
+ break;
+ case YASM_EXPR_NEG:
+ /* Negating a negated value? Make it an IDENT. */
+ e->op = YASM_EXPR_IDENT;
+ break;
+ case YASM_EXPR_IDENT:
+ /* Negating an ident? Change it into a MUL w/ -1 if there's no
+ * floatnums present below; if there ARE floatnums, recurse.
+ */
+ if (e->terms[0].type == YASM_EXPR_FLOAT)
+ yasm_floatnum_calc(e->terms[0].data.flt, YASM_EXPR_NEG, NULL);
+ else if (e->terms[0].type == YASM_EXPR_INT)
+ yasm_intnum_calc(e->terms[0].data.intn, YASM_EXPR_NEG, NULL);
+ else if (e->terms[0].type == YASM_EXPR_EXPR &&
+ yasm_expr__contains(e->terms[0].data.expn, YASM_EXPR_FLOAT))
+ expr_xform_neg_helper(e->terms[0].data.expn);
+ else {
+ e->op = YASM_EXPR_MUL;
+ e->numterms = 2;
+ e->terms[1].type = YASM_EXPR_INT;
+ e->terms[1].data.intn = yasm_intnum_create_int(-1);
+ }
+ break;
+ default:
+ /* Everything else. MUL will be combined when it's leveled.
+ * Make a new expr (to replace e) with -1*e.
+ */
+ ne = yasm_xmalloc(sizeof(yasm_expr));
+ ne->op = YASM_EXPR_MUL;
+ ne->line = e->line;
+ ne->numterms = 2;
+ ne->terms[0].type = YASM_EXPR_INT;
+ ne->terms[0].data.intn = yasm_intnum_create_int(-1);
+ ne->terms[1].type = YASM_EXPR_EXPR;
+ ne->terms[1].data.expn = e;
+ return ne;
+ }
+ return e;
+}
+
+/* Transforms negatives into expressions that are easier to combine:
+ * -x -> -1*x
+ * a-b -> a+(-1*b)
+ *
+ * Call post-order on an expression tree to transform the entire tree.
+ *
+ * Returns a possibly reallocated e.
+ */
+static /*@only@*/ yasm_expr *
+expr_xform_neg(/*@returned@*/ /*@only@*/ yasm_expr *e)
+{
+ switch (e->op) {
+ case YASM_EXPR_NEG:
+ /* Turn -x into -1*x */
+ e->op = YASM_EXPR_IDENT;
+ return expr_xform_neg_helper(e);
+ case YASM_EXPR_SUB:
+ /* Turn a-b into a+(-1*b) */
+
+ /* change op to ADD, and recursively negate right side (if expr) */
+ e->op = YASM_EXPR_ADD;
+ if (e->terms[1].type == YASM_EXPR_EXPR)
+ e->terms[1].data.expn =
+ expr_xform_neg_helper(e->terms[1].data.expn);
+ else
+ expr_xform_neg_item(e, &e->terms[1]);
+ break;
+ default:
+ break;
+ }
+
+ return e;
+}
+
+/* Look for simple identities that make the entire result constant:
+ * 0*&x, -1|x, etc.
+ */
+static int
+expr_is_constant(yasm_expr_op op, yasm_intnum *intn)
+{
+ int iszero = yasm_intnum_is_zero(intn);
+ return ((iszero && op == YASM_EXPR_MUL) ||
+ (iszero && op == YASM_EXPR_AND) ||
+ (iszero && op == YASM_EXPR_LAND) ||
+ (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_OR));
+}
+
+/* Look for simple "left" identities like 0+x, 1*x, etc. */
+static int
+expr_can_destroy_int_left(yasm_expr_op op, yasm_intnum *intn)
+{
+ int iszero = yasm_intnum_is_zero(intn);
+ return ((yasm_intnum_is_pos1(intn) && op == YASM_EXPR_MUL) ||
+ (iszero && op == YASM_EXPR_ADD) ||
+ (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_AND) ||
+ (!iszero && op == YASM_EXPR_LAND) ||
+ (iszero && op == YASM_EXPR_OR) ||
+ (iszero && op == YASM_EXPR_LOR));
+}
+
+/* Look for simple "right" identities like x+|-0, x*&/1 */
+static int
+expr_can_destroy_int_right(yasm_expr_op op, yasm_intnum *intn)
+{
+ int iszero = yasm_intnum_is_zero(intn);
+ int ispos1 = yasm_intnum_is_pos1(intn);
+ return ((ispos1 && op == YASM_EXPR_MUL) ||
+ (ispos1 && op == YASM_EXPR_DIV) ||
+ (iszero && op == YASM_EXPR_ADD) ||
+ (iszero && op == YASM_EXPR_SUB) ||
+ (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_AND) ||
+ (!iszero && op == YASM_EXPR_LAND) ||
+ (iszero && op == YASM_EXPR_OR) ||
+ (iszero && op == YASM_EXPR_LOR) ||
+ (iszero && op == YASM_EXPR_SHL) ||
+ (iszero && op == YASM_EXPR_SHR));
+}
+
+/* Check for and simplify identities. Returns new number of expr terms.
+ * Sets e->op = EXPR_IDENT if numterms ends up being 1.
+ * Uses numterms parameter instead of e->numterms for basis of "new" number
+ * of terms.
+ * Assumes int_term is *only* integer term in e.
+ * NOTE: Really designed to only be used by expr_level_op().
+ */
+static int
+expr_simplify_identity(yasm_expr *e, int numterms, int *int_term,
+ int simplify_reg_mul)
+{
+ int i;
+ int save_numterms;
+
+ /* Don't do this step if it's 1*REG. Save and restore numterms so
+ * yasm_expr__contains() works correctly.
+ */
+ save_numterms = e->numterms;
+ e->numterms = numterms;
+ if (simplify_reg_mul || e->op != YASM_EXPR_MUL
+ || !yasm_intnum_is_pos1(e->terms[*int_term].data.intn)
+ || !yasm_expr__contains(e, YASM_EXPR_REG)) {
+ /* Check for simple identities that delete the intnum.
+ * Don't delete if the intnum is the only thing in the expn.
+ */
+ if ((*int_term == 0 && numterms > 1 &&
+ expr_can_destroy_int_left(e->op, e->terms[0].data.intn)) ||
+ (*int_term > 0 &&
+ expr_can_destroy_int_right(e->op,
+ e->terms[*int_term].data.intn))) {
+ /* Delete the intnum */
+ yasm_intnum_destroy(e->terms[*int_term].data.intn);
+
+ /* Slide everything to its right over by 1 */
+ if (*int_term != numterms-1) /* if it wasn't last.. */
+ memmove(&e->terms[*int_term], &e->terms[*int_term+1],
+ (numterms-1-*int_term)*sizeof(yasm_expr__item));
+
+ /* Update numterms */
+ numterms--;
+ *int_term = -1; /* no longer an int term */
+ }
+ }
+ e->numterms = save_numterms;
+
+ /* Check for simple identites that delete everything BUT the intnum.
+ * Don't bother if the intnum is the only thing in the expn.
+ */
+ if (numterms > 1 && *int_term != -1 &&
+ expr_is_constant(e->op, e->terms[*int_term].data.intn)) {
+ /* Loop through, deleting everything but the integer term */
+ for (i=0; i<e->numterms; i++)
+ if (i != *int_term)
+ expr_delete_term(&e->terms[i], 1);
+
+ /* Move integer term to the first term (if not already there) */
+ if (*int_term != 0)
+ e->terms[0] = e->terms[*int_term]; /* structure copy */
+
+ /* Set numterms to 1 */
+ numterms = 1;
+ }
+
+ /* Compute NOT, NEG, and LNOT on single intnum. */
+ if (numterms == 1 && *int_term == 0 &&
+ (e->op == YASM_EXPR_NOT || e->op == YASM_EXPR_NEG ||
+ e->op == YASM_EXPR_LNOT))
+ yasm_intnum_calc(e->terms[0].data.intn, e->op, NULL);
+
+ /* Change expression to IDENT if possible. */
+ if (numterms == 1)
+ e->op = YASM_EXPR_IDENT;
+
+ /* Return the updated numterms */
+ return numterms;
+}
+
+/* Levels the expression tree starting at e. Eg:
+ * a+(b+c) -> a+b+c
+ * (a+b)+(c+d) -> a+b+c+d
+ * Naturally, only levels operators that allow more than two operand terms.
+ * NOTE: only does *one* level of leveling (no recursion). Should be called
+ * post-order on a tree to combine deeper levels.
+ * Also brings up any IDENT values into the current level (for ALL operators).
+ * Folds (combines by evaluation) *integer* constant values if fold_const != 0.
+ *
+ * Returns a possibly reallocated e.
+ */
+/*@-mustfree@*/
+static /*@only@*/ yasm_expr *
+expr_level_op(/*@returned@*/ /*@only@*/ yasm_expr *e, int fold_const,
+ int simplify_ident, int simplify_reg_mul)
+{
+ int i, j, o, fold_numterms, level_numterms, level_fold_numterms;
+ int first_int_term = -1;
+
+ /* Determine how many operands will need to be brought up (for leveling).
+ * Go ahead and bring up any IDENT'ed values.
+ */
+ while (e->op == YASM_EXPR_IDENT && e->terms[0].type == YASM_EXPR_EXPR) {
+ yasm_expr *sube = e->terms[0].data.expn;
+ yasm_xfree(e);
+ e = sube;
+ }
+
+ /* If non-numeric expression, don't fold constants. */
+ if (e->op > YASM_EXPR_NONNUM)
+ fold_const = 0;
+
+ level_numterms = e->numterms;
+ level_fold_numterms = 0;
+ for (i=0; i<e->numterms; i++) {
+ /* Search downward until we find something *other* than an
+ * IDENT, then bring it up to the current level.
+ */
+ while (e->terms[i].type == YASM_EXPR_EXPR &&
+ e->terms[i].data.expn->op == YASM_EXPR_IDENT) {
+ yasm_expr *sube = e->terms[i].data.expn;
+ e->terms[i] = sube->terms[0];
+ yasm_xfree(sube);
+ }
+
+ if (e->terms[i].type == YASM_EXPR_EXPR &&
+ e->terms[i].data.expn->op == e->op) {
+ /* It's an expression w/the same operator, add in its numterms.
+ * But don't forget to subtract one for the expr itself!
+ */
+ level_numterms += e->terms[i].data.expn->numterms - 1;
+
+ /* If we're folding constants, count up the number of constants
+ * that will be merged in.
+ */
+ if (fold_const)
+ for (j=0; j<e->terms[i].data.expn->numterms; j++)
+ if (e->terms[i].data.expn->terms[j].type ==
+ YASM_EXPR_INT)
+ level_fold_numterms++;
+ }
+
+ /* Find the first integer term (if one is present) if we're folding
+ * constants.
+ */
+ if (fold_const && first_int_term == -1 &&
+ e->terms[i].type == YASM_EXPR_INT)
+ first_int_term = i;
+ }
+
+ /* Look for other integer terms if there's one and combine.
+ * Also eliminate empty spaces when combining and adjust numterms
+ * variables.
+ */
+ fold_numterms = e->numterms;
+ if (first_int_term != -1) {
+ for (i=first_int_term+1, o=first_int_term+1; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_INT) {
+ yasm_intnum_calc(e->terms[first_int_term].data.intn, e->op,
+ e->terms[i].data.intn);
+ fold_numterms--;
+ level_numterms--;
+ /* make sure to delete folded intnum */
+ yasm_intnum_destroy(e->terms[i].data.intn);
+ } else if (o != i) {
+ /* copy term if it changed places */
+ e->terms[o++] = e->terms[i];
+ } else
+ o++;
+ }
+
+ if (simplify_ident) {
+ int new_fold_numterms;
+ /* Simplify identities and make IDENT if possible. */
+ new_fold_numterms =
+ expr_simplify_identity(e, fold_numterms, &first_int_term,
+ simplify_reg_mul);
+ level_numterms -= fold_numterms-new_fold_numterms;
+ fold_numterms = new_fold_numterms;
+ }
+ if (fold_numterms == 1)
+ e->op = YASM_EXPR_IDENT;
+ }
+
+ /* Only level operators that allow more than two operand terms.
+ * Also don't bother leveling if it's not necessary to bring up any terms.
+ */
+ if ((e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_MUL &&
+ e->op != YASM_EXPR_OR && e->op != YASM_EXPR_AND &&
+ e->op != YASM_EXPR_LOR && e->op != YASM_EXPR_LAND &&
+ e->op != YASM_EXPR_LXOR && e->op != YASM_EXPR_XOR) ||
+ level_numterms <= fold_numterms) {
+ /* Downsize e if necessary */
+ if (fold_numterms < e->numterms && e->numterms > 2)
+ e = yasm_xrealloc(e, sizeof(yasm_expr)+((fold_numterms<2) ? 0 :
+ sizeof(yasm_expr__item)*(fold_numterms-2)));
+ /* Update numterms */
+ e->numterms = fold_numterms;
+ return e;
+ }
+
+ /* Adjust numterms for constant folding from terms being "pulled up".
+ * Careful: if there's no integer term in e, then save space for it.
+ */
+ if (fold_const) {
+ level_numterms -= level_fold_numterms;
+ if (first_int_term == -1 && level_fold_numterms != 0)
+ level_numterms++;
+ }
+
+ /* Alloc more (or conceivably less, but not usually) space for e */
+ e = yasm_xrealloc(e, sizeof(yasm_expr)+((level_numterms<2) ? 0 :
+ sizeof(yasm_expr__item)*(level_numterms-2)));
+
+ /* Copy up ExprItem's. Iterate from right to left to keep the same
+ * ordering as was present originally.
+ * Combine integer terms as necessary.
+ */
+ for (i=fold_numterms-1, o=level_numterms-1; i>=0; i--) {
+ if (e->terms[i].type == YASM_EXPR_EXPR &&
+ e->terms[i].data.expn->op == e->op) {
+ /* bring up subexpression */
+ yasm_expr *sube = e->terms[i].data.expn;
+
+ /* copy terms right to left */
+ for (j=sube->numterms-1; j>=0; j--) {
+ if (fold_const && sube->terms[j].type == YASM_EXPR_INT) {
+ /* Need to fold it in.. but if there's no int term already,
+ * just copy into a new one.
+ */
+ if (first_int_term == -1) {
+ first_int_term = o--;
+ e->terms[first_int_term] = sube->terms[j]; /* struc */
+ } else {
+ yasm_intnum_calc(e->terms[first_int_term].data.intn,
+ e->op, sube->terms[j].data.intn);
+ /* make sure to delete folded intnum */
+ yasm_intnum_destroy(sube->terms[j].data.intn);
+ }
+ } else {
+ if (o == first_int_term)
+ o--;
+ e->terms[o--] = sube->terms[j]; /* structure copy */
+ }
+ }
+
+ /* delete subexpression, but *don't delete nodes* (as we've just
+ * copied them!)
+ */
+ yasm_xfree(sube);
+ } else if (o != i) {
+ /* copy operand if it changed places */
+ if (o == first_int_term)
+ o--;
+ e->terms[o] = e->terms[i];
+ /* If we moved the first_int_term, change first_int_num too */
+ if (i == first_int_term)
+ first_int_term = o;
+ o--;
+ } else
+ o--;
+ }
+
+ /* Simplify identities, make IDENT if possible, and save to e->numterms. */
+ if (simplify_ident && first_int_term != -1) {
+ e->numterms = expr_simplify_identity(e, level_numterms,
+ &first_int_term, simplify_reg_mul);
+ } else {
+ e->numterms = level_numterms;
+ if (level_numterms == 1)
+ e->op = YASM_EXPR_IDENT;
+ }
+
+ return e;
+}
+/*@=mustfree@*/
+
+typedef SLIST_HEAD(yasm__exprhead, yasm__exprentry) yasm__exprhead;
+typedef struct yasm__exprentry {
+ /*@reldef@*/ SLIST_ENTRY(yasm__exprentry) next;
+ /*@null@*/ const yasm_expr *e;
+} yasm__exprentry;
+
+static yasm_expr *
+expr_expand_equ(yasm_expr *e, yasm__exprhead *eh)
+{
+ int i;
+ yasm__exprentry ee;
+
+ /* traverse terms */
+ for (i=0; i<e->numterms; i++) {
+ const yasm_expr *equ_expr;
+
+ /* Expand equ's. */
+ if (e->terms[i].type == YASM_EXPR_SYM &&
+ (equ_expr = yasm_symrec_get_equ(e->terms[i].data.sym))) {
+ yasm__exprentry *np;
+
+ /* Check for circular reference */
+ SLIST_FOREACH(np, eh, next) {
+ if (np->e == equ_expr) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("circular reference detected"));
+ return e;
+ }
+ }
+
+ e->terms[i].type = YASM_EXPR_EXPR;
+ e->terms[i].data.expn = yasm_expr_copy(equ_expr);
+
+ /* Remember we saw this equ and recurse */
+ ee.e = equ_expr;
+ SLIST_INSERT_HEAD(eh, &ee, next);
+ e->terms[i].data.expn = expr_expand_equ(e->terms[i].data.expn, eh);
+ SLIST_REMOVE_HEAD(eh, next);
+ } else if (e->terms[i].type == YASM_EXPR_EXPR)
+ /* Recurse */
+ e->terms[i].data.expn = expr_expand_equ(e->terms[i].data.expn, eh);
+ }
+
+ return e;
+}
+
+static yasm_expr *
+expr_level_tree(yasm_expr *e, int fold_const, int simplify_ident,
+ int simplify_reg_mul, int calc_bc_dist,
+ yasm_expr_xform_func expr_xform_extra,
+ void *expr_xform_extra_data)
+{
+ int i;
+
+ e = expr_xform_neg(e);
+
+ /* traverse terms */
+ for (i=0; i<e->numterms; i++) {
+ /* Recurse */
+ if (e->terms[i].type == YASM_EXPR_EXPR)
+ e->terms[i].data.expn =
+ expr_level_tree(e->terms[i].data.expn, fold_const,
+ simplify_ident, simplify_reg_mul, calc_bc_dist,
+ expr_xform_extra, expr_xform_extra_data);
+ }
+
+ /* Check for SEG of SEG:OFF, if we match, simplify to just the segment */
+ if (e->op == YASM_EXPR_SEG && e->terms[0].type == YASM_EXPR_EXPR &&
+ e->terms[0].data.expn->op == YASM_EXPR_SEGOFF) {
+ e->op = YASM_EXPR_IDENT;
+ e->terms[0].data.expn->op = YASM_EXPR_IDENT;
+ /* Destroy the second (offset) term */
+ e->terms[0].data.expn->numterms = 1;
+ expr_delete_term(&e->terms[0].data.expn->terms[1], 1);
+ }
+
+ /* do callback */
+ e = expr_level_op(e, fold_const, simplify_ident, simplify_reg_mul);
+ if (calc_bc_dist || expr_xform_extra) {
+ if (calc_bc_dist)
+ e = expr_xform_bc_dist(e);
+ if (expr_xform_extra)
+ e = expr_xform_extra(e, expr_xform_extra_data);
+ e = expr_level_tree(e, fold_const, simplify_ident, simplify_reg_mul,
+ 0, NULL, NULL);
+ }
+ return e;
+}
+
+/* Level an entire expn tree, expanding equ's as we go */
+yasm_expr *
+yasm_expr__level_tree(yasm_expr *e, int fold_const, int simplify_ident,
+ int simplify_reg_mul, int calc_bc_dist,
+ yasm_expr_xform_func expr_xform_extra,
+ void *expr_xform_extra_data)
+{
+ yasm__exprhead eh;
+ SLIST_INIT(&eh);
+
+ if (!e)
+ return 0;
+
+ e = expr_expand_equ(e, &eh);
+ e = expr_level_tree(e, fold_const, simplify_ident, simplify_reg_mul,
+ calc_bc_dist, expr_xform_extra, expr_xform_extra_data);
+
+ return e;
+}
+
+/* Comparison function for expr_order_terms().
+ * Assumes ExprType enum is in canonical order.
+ */
+static int
+expr_order_terms_compare(const void *va, const void *vb)
+{
+ const yasm_expr__item *a = va, *b = vb;
+ return (a->type - b->type);
+}
+
+/* Reorder terms of e into canonical order. Only reorders if reordering
+ * doesn't change meaning of expression. (eg, doesn't reorder SUB).
+ * Canonical order: REG, INT, FLOAT, SYM, EXPR.
+ * Multiple terms of a single type are kept in the same order as in
+ * the original expression.
+ * NOTE: Only performs reordering on *one* level (no recursion).
+ */
+void
+yasm_expr__order_terms(yasm_expr *e)
+{
+ /* don't bother reordering if only one element */
+ if (e->numterms == 1)
+ return;
+
+ /* only reorder some types of operations */
+ switch (e->op) {
+ case YASM_EXPR_ADD:
+ case YASM_EXPR_MUL:
+ case YASM_EXPR_OR:
+ case YASM_EXPR_AND:
+ case YASM_EXPR_XOR:
+ case YASM_EXPR_LOR:
+ case YASM_EXPR_LAND:
+ case YASM_EXPR_LXOR:
+ /* Use mergesort to sort. It's fast on already sorted values and a
+ * stable sort (multiple terms of same type are kept in the same
+ * order).
+ */
+ yasm__mergesort(e->terms, (size_t)e->numterms,
+ sizeof(yasm_expr__item), expr_order_terms_compare);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+expr_item_copy(yasm_expr__item *dest, const yasm_expr__item *src)
+{
+ dest->type = src->type;
+ switch (src->type) {
+ case YASM_EXPR_SYM:
+ /* Symbols don't need to be copied */
+ dest->data.sym = src->data.sym;
+ break;
+ case YASM_EXPR_PRECBC:
+ /* Nor do direct bytecode references */
+ dest->data.precbc = src->data.precbc;
+ break;
+ case YASM_EXPR_EXPR:
+ dest->data.expn = yasm_expr__copy_except(src->data.expn, -1);
+ break;
+ case YASM_EXPR_INT:
+ dest->data.intn = yasm_intnum_copy(src->data.intn);
+ break;
+ case YASM_EXPR_FLOAT:
+ dest->data.flt = yasm_floatnum_copy(src->data.flt);
+ break;
+ case YASM_EXPR_REG:
+ dest->data.reg = src->data.reg;
+ break;
+ case YASM_EXPR_SUBST:
+ dest->data.subst = src->data.subst;
+ break;
+ default:
+ break;
+ }
+}
+
+/* Copy entire expression EXCEPT for index "except" at *top level only*. */
+yasm_expr *
+yasm_expr__copy_except(const yasm_expr *e, int except)
+{
+ yasm_expr *n;
+ int i;
+
+ n = yasm_xmalloc(sizeof(yasm_expr) +
+ sizeof(yasm_expr__item)*(e->numterms<2?0:e->numterms-2));
+
+ n->op = e->op;
+ n->line = e->line;
+ n->numterms = e->numterms;
+ for (i=0; i<e->numterms; i++) {
+ if (i != except)
+ expr_item_copy(&n->terms[i], &e->terms[i]);
+ }
+
+ return n;
+}
+
+static void
+expr_delete_term(yasm_expr__item *term, int recurse)
+{
+ switch (term->type) {
+ case YASM_EXPR_INT:
+ yasm_intnum_destroy(term->data.intn);
+ break;
+ case YASM_EXPR_FLOAT:
+ yasm_floatnum_destroy(term->data.flt);
+ break;
+ case YASM_EXPR_EXPR:
+ if (recurse)
+ yasm_expr_destroy(term->data.expn);
+ break;
+ default:
+ break;
+ }
+}
+
+static int
+expr_destroy_each(/*@only@*/ yasm_expr *e, /*@unused@*/ void *d)
+{
+ int i;
+ for (i=0; i<e->numterms; i++)
+ expr_delete_term(&e->terms[i], 0);
+ yasm_xfree(e); /* free ourselves */
+ return 0; /* don't stop recursion */
+}
+
+/*@-mustfree@*/
+void
+yasm_expr_destroy(yasm_expr *e)
+{
+ expr_traverse_nodes_post(e, NULL, expr_destroy_each);
+}
+/*@=mustfree@*/
+
+int
+yasm_expr_is_op(const yasm_expr *e, yasm_expr_op op)
+{
+ return (e->op == op);
+}
+
+static int
+expr_contains_callback(const yasm_expr__item *ei, void *d)
+{
+ yasm_expr__type *t = d;
+ return (ei->type & *t);
+}
+
+int
+yasm_expr__contains(const yasm_expr *e, yasm_expr__type t)
+{
+ return yasm_expr__traverse_leaves_in_const(e, &t, expr_contains_callback);
+}
+
+typedef struct subst_cbd {
+ unsigned int num_items;
+ const yasm_expr__item *items;
+} subst_cbd;
+
+static int
+expr_subst_callback(yasm_expr__item *ei, void *d)
+{
+ subst_cbd *cbd = d;
+ if (ei->type != YASM_EXPR_SUBST)
+ return 0;
+ if (ei->data.subst >= cbd->num_items)
+ return 1; /* error */
+ expr_item_copy(ei, &cbd->items[ei->data.subst]);
+ return 0;
+}
+
+int
+yasm_expr__subst(yasm_expr *e, unsigned int num_items,
+ const yasm_expr__item *items)
+{
+ subst_cbd cbd;
+ cbd.num_items = num_items;
+ cbd.items = items;
+ return yasm_expr__traverse_leaves_in(e, &cbd, expr_subst_callback);
+}
+
+/* Traverse over expression tree, calling func for each operation AFTER the
+ * branches (if expressions) have been traversed (eg, postorder
+ * traversal). The data pointer d is passed to each func call.
+ *
+ * Stops early (and returns 1) if func returns 1. Otherwise returns 0.
+ */
+static int
+expr_traverse_nodes_post(yasm_expr *e, void *d,
+ int (*func) (/*@null@*/ yasm_expr *e,
+ /*@null@*/ void *d))
+{
+ int i;
+
+ if (!e)
+ return 0;
+
+ /* traverse terms */
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_EXPR &&
+ expr_traverse_nodes_post(e->terms[i].data.expn, d, func))
+ return 1;
+ }
+
+ /* do callback */
+ return func(e, d);
+}
+
+/* Traverse over expression tree in order, calling func for each leaf
+ * (non-operation). The data pointer d is passed to each func call.
+ *
+ * Stops early (and returns 1) if func returns 1. Otherwise returns 0.
+ */
+int
+yasm_expr__traverse_leaves_in_const(const yasm_expr *e, void *d,
+ int (*func) (/*@null@*/ const yasm_expr__item *ei, /*@null@*/ void *d))
+{
+ int i;
+
+ if (!e)
+ return 0;
+
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_EXPR) {
+ if (yasm_expr__traverse_leaves_in_const(e->terms[i].data.expn, d,
+ func))
+ return 1;
+ } else {
+ if (func(&e->terms[i], d))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Traverse over expression tree in order, calling func for each leaf
+ * (non-operation). The data pointer d is passed to each func call.
+ *
+ * Stops early (and returns 1) if func returns 1. Otherwise returns 0.
+ */
+int
+yasm_expr__traverse_leaves_in(yasm_expr *e, void *d,
+ int (*func) (/*@null@*/ yasm_expr__item *ei, /*@null@*/ void *d))
+{
+ int i;
+
+ if (!e)
+ return 0;
+
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_EXPR) {
+ if (yasm_expr__traverse_leaves_in(e->terms[i].data.expn, d, func))
+ return 1;
+ } else {
+ if (func(&e->terms[i], d))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+yasm_expr *
+yasm_expr_extract_deep_segoff(yasm_expr **ep)
+{
+ yasm_expr *retval;
+ yasm_expr *e = *ep;
+ int i;
+
+ /* Try to extract at this level */
+ retval = yasm_expr_extract_segoff(ep);
+ if (retval)
+ return retval;
+
+ /* Not at this level? Search any expr children. */
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_EXPR) {
+ retval = yasm_expr_extract_deep_segoff(&e->terms[i].data.expn);
+ if (retval)
+ return retval;
+ }
+ }
+
+ /* Didn't find one */
+ return NULL;
+}
+
+yasm_expr *
+yasm_expr_extract_segoff(yasm_expr **ep)
+{
+ yasm_expr *retval;
+ yasm_expr *e = *ep;
+
+ /* If not SEG:OFF, we can't do this transformation */
+ if (e->op != YASM_EXPR_SEGOFF)
+ return NULL;
+
+ /* Extract the SEG portion out to its own expression */
+ if (e->terms[0].type == YASM_EXPR_EXPR)
+ retval = e->terms[0].data.expn;
+ else {
+ /* Need to build IDENT expression to hold non-expression contents */
+ retval = yasm_xmalloc(sizeof(yasm_expr));
+ retval->op = YASM_EXPR_IDENT;
+ retval->numterms = 1;
+ retval->terms[0] = e->terms[0]; /* structure copy */
+ }
+
+ /* Delete the SEG: portion by changing the expression into an IDENT */
+ e->op = YASM_EXPR_IDENT;
+ e->numterms = 1;
+ e->terms[0] = e->terms[1]; /* structure copy */
+
+ return retval;
+}
+
+yasm_expr *
+yasm_expr_extract_wrt(yasm_expr **ep)
+{
+ yasm_expr *retval;
+ yasm_expr *e = *ep;
+
+ /* If not WRT, we can't do this transformation */
+ if (e->op != YASM_EXPR_WRT)
+ return NULL;
+
+ /* Extract the right side portion out to its own expression */
+ if (e->terms[1].type == YASM_EXPR_EXPR)
+ retval = e->terms[1].data.expn;
+ else {
+ /* Need to build IDENT expression to hold non-expression contents */
+ retval = yasm_xmalloc(sizeof(yasm_expr));
+ retval->op = YASM_EXPR_IDENT;
+ retval->numterms = 1;
+ retval->terms[0] = e->terms[1]; /* structure copy */
+ }
+
+ /* Delete the right side portion by changing the expr into an IDENT */
+ e->op = YASM_EXPR_IDENT;
+ e->numterms = 1;
+
+ return retval;
+}
+
+/*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/
+yasm_intnum *
+yasm_expr_get_intnum(yasm_expr **ep, int calc_bc_dist)
+{
+ *ep = yasm_expr_simplify(*ep, calc_bc_dist);
+
+ if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_INT)
+ return (*ep)->terms[0].data.intn;
+ else
+ return (yasm_intnum *)NULL;
+}
+/*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/
+
+/*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/
+const yasm_symrec *
+yasm_expr_get_symrec(yasm_expr **ep, int simplify)
+{
+ if (simplify)
+ *ep = yasm_expr_simplify(*ep, 0);
+
+ if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_SYM)
+ return (*ep)->terms[0].data.sym;
+ else
+ return (yasm_symrec *)NULL;
+}
+/*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/
+
+/*@-unqualifiedtrans -nullderef -nullstate -onlytrans@*/
+const uintptr_t *
+yasm_expr_get_reg(yasm_expr **ep, int simplify)
+{
+ if (simplify)
+ *ep = yasm_expr_simplify(*ep, 0);
+
+ if ((*ep)->op == YASM_EXPR_IDENT && (*ep)->terms[0].type == YASM_EXPR_REG)
+ return &((*ep)->terms[0].data.reg);
+ else
+ return NULL;
+}
+/*@=unqualifiedtrans =nullderef -nullstate -onlytrans@*/
+
+void
+yasm_expr_print(const yasm_expr *e, FILE *f)
+{
+ char opstr[8];
+ int i;
+
+ if (!e) {
+ fprintf(f, "(nil)");
+ return;
+ }
+
+ switch (e->op) {
+ case YASM_EXPR_ADD:
+ strcpy(opstr, "+");
+ break;
+ case YASM_EXPR_SUB:
+ strcpy(opstr, "-");
+ break;
+ case YASM_EXPR_MUL:
+ strcpy(opstr, "*");
+ break;
+ case YASM_EXPR_DIV:
+ strcpy(opstr, "/");
+ break;
+ case YASM_EXPR_SIGNDIV:
+ strcpy(opstr, "//");
+ break;
+ case YASM_EXPR_MOD:
+ strcpy(opstr, "%");
+ break;
+ case YASM_EXPR_SIGNMOD:
+ strcpy(opstr, "%%");
+ break;
+ case YASM_EXPR_NEG:
+ fprintf(f, "-");
+ opstr[0] = 0;
+ break;
+ case YASM_EXPR_NOT:
+ fprintf(f, "~");
+ opstr[0] = 0;
+ break;
+ case YASM_EXPR_OR:
+ strcpy(opstr, "|");
+ break;
+ case YASM_EXPR_AND:
+ strcpy(opstr, "&");
+ break;
+ case YASM_EXPR_XOR:
+ strcpy(opstr, "^");
+ break;
+ case YASM_EXPR_XNOR:
+ strcpy(opstr, "XNOR");
+ break;
+ case YASM_EXPR_NOR:
+ strcpy(opstr, "NOR");
+ break;
+ case YASM_EXPR_SHL:
+ strcpy(opstr, "<<");
+ break;
+ case YASM_EXPR_SHR:
+ strcpy(opstr, ">>");
+ break;
+ case YASM_EXPR_LOR:
+ strcpy(opstr, "||");
+ break;
+ case YASM_EXPR_LAND:
+ strcpy(opstr, "&&");
+ break;
+ case YASM_EXPR_LNOT:
+ strcpy(opstr, "!");
+ break;
+ case YASM_EXPR_LXOR:
+ strcpy(opstr, "^^");
+ break;
+ case YASM_EXPR_LXNOR:
+ strcpy(opstr, "LXNOR");
+ break;
+ case YASM_EXPR_LNOR:
+ strcpy(opstr, "LNOR");
+ break;
+ case YASM_EXPR_LT:
+ strcpy(opstr, "<");
+ break;
+ case YASM_EXPR_GT:
+ strcpy(opstr, ">");
+ break;
+ case YASM_EXPR_LE:
+ strcpy(opstr, "<=");
+ break;
+ case YASM_EXPR_GE:
+ strcpy(opstr, ">=");
+ break;
+ case YASM_EXPR_NE:
+ strcpy(opstr, "!=");
+ break;
+ case YASM_EXPR_EQ:
+ strcpy(opstr, "==");
+ break;
+ case YASM_EXPR_SEG:
+ fprintf(f, "SEG ");
+ opstr[0] = 0;
+ break;
+ case YASM_EXPR_WRT:
+ strcpy(opstr, " WRT ");
+ break;
+ case YASM_EXPR_SEGOFF:
+ strcpy(opstr, ":");
+ break;
+ case YASM_EXPR_IDENT:
+ opstr[0] = 0;
+ break;
+ default:
+ strcpy(opstr, " !UNK! ");
+ break;
+ }
+ for (i=0; i<e->numterms; i++) {
+ switch (e->terms[i].type) {
+ case YASM_EXPR_PRECBC:
+ fprintf(f, "{%lx}",
+ yasm_bc_next_offset(e->terms[i].data.precbc));
+ break;
+ case YASM_EXPR_SYM:
+ fprintf(f, "%s", yasm_symrec_get_name(e->terms[i].data.sym));
+ break;
+ case YASM_EXPR_EXPR:
+ fprintf(f, "(");
+ yasm_expr_print(e->terms[i].data.expn, f);
+ fprintf(f, ")");
+ break;
+ case YASM_EXPR_INT:
+ yasm_intnum_print(e->terms[i].data.intn, f);
+ break;
+ case YASM_EXPR_FLOAT:
+ yasm_floatnum_print(e->terms[i].data.flt, f);
+ break;
+ case YASM_EXPR_REG:
+ /* FIXME */
+ /*yasm_arch_reg_print(arch, e->terms[i].data.reg, f);*/
+ break;
+ case YASM_EXPR_SUBST:
+ fprintf(f, "[%u]", e->terms[i].data.subst);
+ break;
+ case YASM_EXPR_NONE:
+ break;
+ }
+ if (i < e->numterms-1)
+ fprintf(f, "%s", opstr);
+ }
+}
+
+unsigned int
+yasm_expr_size(const yasm_expr *e)
+{
+ int i;
+ int seen = 0;
+ unsigned int size = 0, newsize;
+
+ if (e->op == YASM_EXPR_IDENT) {
+ if (e->terms[0].type == YASM_EXPR_SYM)
+ return yasm_symrec_get_size(e->terms[0].data.sym);
+ return 0;
+ }
+ if (e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_SUB)
+ return 0;
+
+ for (i=0; i<e->numterms; i++) {
+ newsize = 0;
+ switch (e->terms[i].type) {
+ case YASM_EXPR_EXPR:
+ newsize = yasm_expr_size(e->terms[i].data.expn);
+ break;
+ case YASM_EXPR_SYM:
+ newsize = yasm_symrec_get_size(e->terms[i].data.sym);
+ break;
+ default:
+ break;
+ }
+ if (newsize) {
+ size = newsize;
+ if (seen)
+ /* either sum of idents (?!) or substract of idents */
+ return 0;
+ seen = 1;
+ }
+ }
+ /* exactly one offset */
+ return size;
+}
+
+const char *
+yasm_expr_segment(const yasm_expr *e)
+{
+ int i;
+ int seen = 0;
+ const char *segment = NULL;
+
+ if (e->op == YASM_EXPR_IDENT) {
+ if (e->terms[0].type == YASM_EXPR_SYM)
+ return yasm_symrec_get_segment(e->terms[0].data.sym);
+ return NULL;
+ }
+ if (e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_SUB)
+ return NULL;
+
+ for (i=0; i<e->numterms; i++) {
+ if ((e->op == YASM_EXPR_ADD || !i) &&
+ e->terms[i].type == YASM_EXPR_EXPR) {
+ if ((segment = yasm_expr_segment(e->terms[i].data.expn))) {
+ if (seen) {
+ /* either sum of idents (?!) or substract of idents */
+ return NULL;
+ }
+ seen = 1;
+ }
+ }
+ }
+ /* exactly one offset */
+ return segment;
+}
diff --git a/contrib/tools/yasm/libyasm/expr.h b/contrib/tools/yasm/libyasm/expr.h
new file mode 100644
index 0000000000..0de62dfed7
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/expr.h
@@ -0,0 +1,388 @@
+/**
+ * \file libyasm/expr.h
+ * \brief YASM expression interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Michael Urman, Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_EXPR_H
+#define YASM_EXPR_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Type of an expression item. Types are listed in canonical sorting order.
+ * See expr_order_terms().
+ * Note #YASM_EXPR_PRECBC must be used carefully (in a-b pairs), as only
+ * symrecs can become the relative term in a #yasm_value.
+ */
+typedef enum yasm_expr__type {
+ YASM_EXPR_NONE = 0, /**< Nothing */
+ YASM_EXPR_REG = 1<<0, /**< Register */
+ YASM_EXPR_INT = 1<<1, /**< Integer value */
+ YASM_EXPR_SUBST = 1<<2, /**< Substitution placeholder */
+ YASM_EXPR_FLOAT = 1<<3, /**< Floating point value */
+ YASM_EXPR_SYM = 1<<4, /**< Symbol */
+ YASM_EXPR_PRECBC = 1<<5,/**< Direct bytecode ref (rather than via sym) */
+ YASM_EXPR_EXPR = 1<<6 /**< Subexpression */
+} yasm_expr__type;
+
+/** Expression item. */
+typedef struct yasm_expr__item {
+ yasm_expr__type type; /**< Type */
+
+ /** Expression item data. Correct value depends on type. */
+ union {
+ yasm_bytecode *precbc; /**< Direct bytecode ref (YASM_EXPR_PRECBC) */
+ yasm_symrec *sym; /**< Symbol (YASM_EXPR_SYM) */
+ yasm_expr *expn; /**< Subexpression (YASM_EXPR_EXPR) */
+ yasm_intnum *intn; /**< Integer value (YASM_EXPR_INT) */
+ yasm_floatnum *flt; /**< Floating point value (YASM_EXPR_FLOAT) */
+ uintptr_t reg; /**< Register (YASM_EXPR_REG) */
+ unsigned int subst; /**< Subst placeholder (YASM_EXPR_SUBST) */
+ } data;
+} yasm_expr__item;
+
+/** Expression. */
+struct yasm_expr {
+ yasm_expr_op op; /**< Operation. */
+ unsigned long line; /**< Line number where expression was defined. */
+ int numterms; /**< Number of terms in the expression. */
+
+ /** Terms of the expression. Structure may be extended to include more
+ * terms, as some operations may allow more than two operand terms
+ * (ADD, MUL, OR, AND, XOR).
+ */
+ yasm_expr__item terms[2];
+};
+
+/** Create a new expression e=a op b.
+ * \param op operation
+ * \param a expression item a
+ * \param b expression item b (optional depending on op)
+ * \param line virtual line (where expression defined)
+ * \return Newly allocated expression.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_expr *yasm_expr_create
+ (yasm_expr_op op, /*@only@*/ yasm_expr__item *a,
+ /*@only@*/ /*@null@*/ yasm_expr__item *b, unsigned long line);
+
+/** Create a new preceding-bytecode expression item.
+ * \param precbc preceding bytecode
+ * \return Newly allocated expression item.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_expr__item *yasm_expr_precbc(/*@keep@*/ yasm_bytecode *precbc);
+
+/** Create a new symbol expression item.
+ * \param sym symbol
+ * \return Newly allocated expression item.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_expr__item *yasm_expr_sym(/*@keep@*/ yasm_symrec *sym);
+
+/** Create a new expression expression item.
+ * \param e expression
+ * \return Newly allocated expression item.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_expr__item *yasm_expr_expr(/*@keep@*/ yasm_expr *e);
+
+/** Create a new intnum expression item.
+ * \param intn intnum
+ * \return Newly allocated expression item.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_expr__item *yasm_expr_int(/*@keep@*/ yasm_intnum *intn);
+
+/** Create a new floatnum expression item.
+ * \param flt floatnum
+ * \return Newly allocated expression item.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_expr__item *yasm_expr_float(/*@keep@*/ yasm_floatnum *flt);
+
+/** Create a new register expression item.
+ * \param reg register
+ * \return Newly allocated expression item.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_expr__item *yasm_expr_reg(uintptr_t reg);
+
+/** Create a new expression tree e=l op r.
+ * \param l expression for left side of new expression
+ * \param o operation
+ * \param r expression for right side of new expression
+ * \param i line index
+ * \return Newly allocated expression.
+ */
+#define yasm_expr_create_tree(l,o,r,i) \
+ yasm_expr_create ((o), yasm_expr_expr(l), yasm_expr_expr(r), i)
+
+/** Create a new expression branch e=op r.
+ * \param o operation
+ * \param r expression for right side of new expression
+ * \param i line index
+ * \return Newly allocated expression.
+ */
+#define yasm_expr_create_branch(o,r,i) \
+ yasm_expr_create ((o), yasm_expr_expr(r), (yasm_expr__item *)NULL, i)
+
+/** Create a new expression identity e=r.
+ * \param r expression for identity within new expression
+ * \param i line index
+ * \return Newly allocated expression.
+ */
+#define yasm_expr_create_ident(r,i) \
+ yasm_expr_create (YASM_EXPR_IDENT, (r), (yasm_expr__item *)NULL, i)
+
+/** Duplicate an expression.
+ * \param e expression
+ * \return Newly allocated expression identical to e.
+ */
+yasm_expr *yasm_expr_copy(const yasm_expr *e);
+#ifndef YASM_DOXYGEN
+#define yasm_expr_copy(e) yasm_expr__copy_except(e, -1)
+#endif
+
+/** Destroy (free allocated memory for) an expression.
+ * \param e expression
+ */
+YASM_LIB_DECL
+void yasm_expr_destroy(/*@only@*/ /*@null@*/ yasm_expr *e);
+
+/** Determine if an expression is a specified operation (at the top level).
+ * \param e expression
+ * \param op operator
+ * \return Nonzero if the expression was the specified operation at the top
+ * level, zero otherwise.
+ */
+YASM_LIB_DECL
+int yasm_expr_is_op(const yasm_expr *e, yasm_expr_op op);
+
+/** Extra transformation function for yasm_expr__level_tree().
+ * \param e expression being simplified
+ * \param d data provided as expr_xform_extra_data to
+ * yasm_expr__level_tree()
+ * \return Transformed e.
+ */
+typedef /*@only@*/ yasm_expr * (*yasm_expr_xform_func)
+ (/*@returned@*/ /*@only@*/ yasm_expr *e, /*@null@*/ void *d);
+
+/** Level an entire expression tree.
+ * \internal
+ * \param e expression
+ * \param fold_const enable constant folding if nonzero
+ * \param simplify_ident simplify identities
+ * \param simplify_reg_mul simplify REG*1 identities
+ * \param calc_bc_dist nonzero if distances between bytecodes should be
+ * calculated, 0 if they should be left intact
+ * \param expr_xform_extra extra transformation function
+ * \param expr_xform_extra_data data to pass to expr_xform_extra
+ * \return Leveled expression.
+ */
+YASM_LIB_DECL
+/*@only@*/ /*@null@*/ yasm_expr *yasm_expr__level_tree
+ (/*@returned@*/ /*@only@*/ /*@null@*/ yasm_expr *e, int fold_const,
+ int simplify_ident, int simplify_reg_mul, int calc_bc_dist,
+ /*@null@*/ yasm_expr_xform_func expr_xform_extra,
+ /*@null@*/ void *expr_xform_extra_data);
+
+/** Simplify an expression as much as possible. Eliminates extraneous
+ * branches and simplifies integer-only subexpressions. Simplified version
+ * of yasm_expr__level_tree().
+ * \param e expression
+ * \param cbd if distance between bytecodes should be calculated
+ * \return Simplified expression.
+ */
+#define yasm_expr_simplify(e, cbd) \
+ yasm_expr__level_tree(e, 1, 1, 1, cbd, NULL, NULL)
+
+/** Extract the segment portion of an expression containing SEG:OFF, leaving
+ * the offset.
+ * \param ep expression (pointer to)
+ * \return NULL if unable to extract a segment (expr does not contain a
+ * YASM_EXPR_SEGOFF operator), otherwise the segment expression.
+ * The input expression is modified such that on return, it's the
+ * offset expression.
+ */
+YASM_LIB_DECL
+/*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_deep_segoff(yasm_expr **ep);
+
+/** Extract the segment portion of a SEG:OFF expression, leaving the offset.
+ * \param ep expression (pointer to)
+ * \return NULL if unable to extract a segment (YASM_EXPR_SEGOFF not the
+ * top-level operator), otherwise the segment expression. The input
+ * expression is modified such that on return, it's the offset
+ * expression.
+ */
+YASM_LIB_DECL
+/*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_segoff(yasm_expr **ep);
+
+/** Extract the right portion (y) of a x WRT y expression, leaving the left
+ * portion (x).
+ * \param ep expression (pointer to)
+ * \return NULL if unable to extract (YASM_EXPR_WRT not the top-level
+ * operator), otherwise the right side of the WRT expression. The
+ * input expression is modified such that on return, it's the left side
+ * of the WRT expression.
+ */
+YASM_LIB_DECL
+/*@only@*/ /*@null@*/ yasm_expr *yasm_expr_extract_wrt(yasm_expr **ep);
+
+/** Get the integer value of an expression if it's just an integer.
+ * \param ep expression (pointer to)
+ * \param calc_bc_dist nonzero if distances between bytecodes should be
+ * calculated, 0 if NULL should be returned in this case
+ * \return NULL if the expression is too complex (contains anything other than
+ * integers, ie floats, non-valued labels, registers); otherwise the
+ * intnum value of the expression.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ yasm_intnum *yasm_expr_get_intnum
+ (yasm_expr **ep, int calc_bc_dist);
+
+/** Get the symbol value of an expression if it's just a symbol.
+ * \param ep expression (pointer to)
+ * \param simplify if nonzero, simplify the expression first
+ * \return NULL if the expression is too complex; otherwise the symbol value of
+ * the expression.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ const yasm_symrec *yasm_expr_get_symrec
+ (yasm_expr **ep, int simplify);
+
+/** Get the register value of an expression if it's just a register.
+ * \param ep expression (pointer to)
+ * \param simplify if nonzero, simplify the expression first
+ * \return NULL if the expression is too complex; otherwise the register value
+ * of the expression.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ const uintptr_t *yasm_expr_get_reg
+ (yasm_expr **ep, int simplify);
+
+/** Print an expression. For debugging purposes.
+ * \param e expression
+ * \param f file
+ */
+YASM_LIB_DECL
+void yasm_expr_print(/*@null@*/ const yasm_expr *e, FILE *f);
+
+/** Return the size of an expression, if the user provided it
+ * \param e expression
+ */
+YASM_LIB_DECL
+unsigned int yasm_expr_size(const yasm_expr *e);
+
+/** Return the segment of an expression, if the user provided it
+ * \param e expression
+ */
+YASM_LIB_DECL
+const char *yasm_expr_segment(const yasm_expr *e);
+
+/** Traverse over expression tree in order (const version).
+ * Calls func for each leaf (non-operation).
+ * \param e expression
+ * \param d data passed to each call to func
+ * \param func callback function
+ * \return Stops early (and returns 1) if func returns 1.
+ * Otherwise returns 0.
+ */
+YASM_LIB_DECL
+int yasm_expr__traverse_leaves_in_const
+ (const yasm_expr *e, /*@null@*/ void *d,
+ int (*func) (/*@null@*/ const yasm_expr__item *ei, /*@null@*/ void *d));
+
+/** Traverse over expression tree in order.
+ * Calls func for each leaf (non-operation).
+ * \param e expression
+ * \param d data passed to each call to func
+ * \param func callback function
+ * \return Stops early (and returns 1) if func returns 1.
+ * Otherwise returns 0.
+ */
+YASM_LIB_DECL
+int yasm_expr__traverse_leaves_in
+ (yasm_expr *e, /*@null@*/ void *d,
+ int (*func) (/*@null@*/ yasm_expr__item *ei, /*@null@*/ void *d));
+
+/** Reorder terms of e into canonical order. Only reorders if reordering
+ * doesn't change meaning of expression. (eg, doesn't reorder SUB).
+ * Canonical order: REG, INT, FLOAT, SYM, EXPR.
+ * Multiple terms of a single type are kept in the same order as in
+ * the original expression.
+ * \param e expression
+ * \note Only performs reordering on *one* level (no recursion).
+ */
+YASM_LIB_DECL
+void yasm_expr__order_terms(yasm_expr *e);
+
+/** Copy entire expression EXCEPT for index "except" at *top level only*.
+ * \param e expression
+ * \param except term index not to copy; -1 to copy all terms
+ * \return Newly allocated copy of expression.
+ */
+YASM_LIB_DECL
+yasm_expr *yasm_expr__copy_except(const yasm_expr *e, int except);
+
+/** Test if expression contains an item. Searches recursively into
+ * subexpressions.
+ * \param e expression
+ * \param t type of item to look for
+ * \return Nonzero if expression contains an item of type t, zero if not.
+ */
+YASM_LIB_DECL
+int yasm_expr__contains(const yasm_expr *e, yasm_expr__type t);
+
+/** Transform symrec-symrec terms in expression into #YASM_EXPR_SUBST items.
+ * Calls the callback function for each symrec-symrec term.
+ * \param ep expression (pointer to)
+ * \param cbd callback data passed to callback function
+ * \param callback callback function: given subst index for bytecode
+ * pair, bytecode pair (bc2-bc1), and cbd (callback data)
+ * \return Number of transformations made.
+ */
+YASM_LIB_DECL
+int yasm_expr__bc_dist_subst(yasm_expr **ep, void *cbd,
+ void (*callback) (unsigned int subst,
+ yasm_bytecode *precbc,
+ yasm_bytecode *precbc2,
+ void *cbd));
+
+/** Substitute items into expr YASM_EXPR_SUBST items (by index). Items are
+ * copied, so caller is responsible for freeing array of items.
+ * \param e expression
+ * \param num_items number of items in items array
+ * \param items items array
+ * \return 1 on error (index out of range).
+ */
+YASM_LIB_DECL
+int yasm_expr__subst(yasm_expr *e, unsigned int num_items,
+ const yasm_expr__item *items);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/file.c b/contrib/tools/yasm/libyasm/file.c
new file mode 100644
index 0000000000..fc7dab6c17
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/file.c
@@ -0,0 +1,672 @@
+/*
+ * File helper functions.
+ *
+ * Copyright (C) 2001-2007 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 <util.h>
+
+/* Need either unistd.h or direct.h to prototype getcwd() and mkdir() */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
+#endif
+
+#ifdef _WIN32
+#include <io.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+
+#include "errwarn.h"
+#include "file.h"
+
+#define BSIZE 8192 /* Fill block size */
+
+
+void
+yasm_scanner_initialize(yasm_scanner *s)
+{
+ s->bot = NULL;
+ s->tok = NULL;
+ s->ptr = NULL;
+ s->cur = NULL;
+ s->lim = NULL;
+ s->top = NULL;
+ s->eof = NULL;
+}
+
+void
+yasm_scanner_delete(yasm_scanner *s)
+{
+ if (s->bot) {
+ yasm_xfree(s->bot);
+ s->bot = NULL;
+ }
+}
+
+int
+yasm_fill_helper(yasm_scanner *s, unsigned char **cursor,
+ size_t (*input_func) (void *d, unsigned char *buf,
+ size_t max),
+ void *input_func_data)
+{
+ size_t cnt;
+ int first = 0;
+
+ if (s->eof)
+ return 0;
+
+ cnt = s->tok - s->bot;
+ if (cnt > 0) {
+ memmove(s->bot, s->tok, (size_t)(s->lim - s->tok));
+ s->tok = s->bot;
+ s->ptr -= cnt;
+ *cursor -= cnt;
+ s->lim -= cnt;
+ }
+ if (!s->bot)
+ first = 1;
+ if ((s->top - s->lim) < BSIZE) {
+ unsigned char *buf = yasm_xmalloc((size_t)(s->lim - s->bot) + BSIZE);
+ memcpy(buf, s->tok, (size_t)(s->lim - s->tok));
+ s->tok = buf;
+ s->ptr = &buf[s->ptr - s->bot];
+ *cursor = &buf[*cursor - s->bot];
+ s->lim = &buf[s->lim - s->bot];
+ s->top = &s->lim[BSIZE];
+ if (s->bot)
+ yasm_xfree(s->bot);
+ s->bot = buf;
+ }
+ if ((cnt = input_func(input_func_data, s->lim, BSIZE)) == 0) {
+ s->eof = &s->lim[cnt];
+ *s->eof++ = '\n';
+ }
+ s->lim += cnt;
+ return first;
+}
+
+void
+yasm_unescape_cstring(unsigned char *str, size_t *len)
+{
+ unsigned char *s = str;
+ unsigned char *o = str;
+ unsigned char t[4];
+
+ while ((size_t)(s-str)<*len) {
+ if (*s == '\\' && (size_t)(&s[1]-str)<*len) {
+ s++;
+ switch (*s) {
+ case 'b': *o = '\b'; s++; break;
+ case 'f': *o = '\f'; s++; break;
+ case 'n': *o = '\n'; s++; break;
+ case 'r': *o = '\r'; s++; break;
+ case 't': *o = '\t'; s++; break;
+ case 'x':
+ /* hex escape; grab last two digits */
+ s++;
+ while ((size_t)(&s[2]-str)<*len && isxdigit(s[0])
+ && isxdigit(s[1]) && isxdigit(s[2]))
+ s++;
+ if ((size_t)(s-str)<*len && isxdigit(*s)) {
+ t[0] = *s++;
+ t[1] = '\0';
+ t[2] = '\0';
+ if ((size_t)(s-str)<*len && isxdigit(*s))
+ t[1] = *s++;
+ *o = (unsigned char)strtoul((char *)t, NULL, 16);
+ } else
+ *o = '\0';
+ break;
+ default:
+ if (isdigit(*s)) {
+ int warn = 0;
+ /* octal escape */
+ if (*s > '7')
+ warn = 1;
+ *o = *s++ - '0';
+ if ((size_t)(s-str)<*len && isdigit(*s)) {
+ if (*s > '7')
+ warn = 1;
+ *o <<= 3;
+ *o += *s++ - '0';
+ if ((size_t)(s-str)<*len && isdigit(*s)) {
+ if (*s > '7')
+ warn = 1;
+ *o <<= 3;
+ *o += *s++ - '0';
+ }
+ }
+ if (warn)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("octal value out of range"));
+ } else
+ *o = *s++;
+ break;
+ }
+ o++;
+ } else
+ *o++ = *s++;
+ }
+ *len = o-str;
+}
+
+size_t
+yasm__splitpath_unix(const char *path, /*@out@*/ const char **tail)
+{
+ const char *s;
+ s = strrchr(path, '/');
+ if (!s) {
+ /* No head */
+ *tail = path;
+ return 0;
+ }
+ *tail = s+1;
+ /* Strip trailing ./ on path */
+ while ((s-1)>=path && *(s-1) == '.' && *s == '/'
+ && !((s-2)>=path && *(s-2) == '.'))
+ s -= 2;
+ /* Strip trailing slashes on path (except leading) */
+ while (s>path && *s == '/')
+ s--;
+ /* Return length of head */
+ return s-path+1;
+}
+
+size_t
+yasm__splitpath_win(const char *path, /*@out@*/ const char **tail)
+{
+ const char *basepath = path;
+ const char *s;
+
+ /* split off drive letter first, if any */
+ if (isalpha(path[0]) && path[1] == ':')
+ basepath += 2;
+
+ s = basepath;
+ while (*s != '\0')
+ s++;
+ while (s >= basepath && *s != '\\' && *s != '/')
+ s--;
+ if (s < basepath) {
+ *tail = basepath;
+ if (path == basepath)
+ return 0; /* No head */
+ else
+ return 2; /* Drive letter is head */
+ }
+ *tail = s+1;
+ /* Strip trailing .\ or ./ on path */
+ while ((s-1)>=basepath && *(s-1) == '.' && (*s == '/' || *s == '\\')
+ && !((s-2)>=basepath && *(s-2) == '.'))
+ s -= 2;
+ /* Strip trailing slashes on path (except leading) */
+ while (s>basepath && (*s == '/' || *s == '\\'))
+ s--;
+ /* Return length of head */
+ return s-path+1;
+}
+
+char *
+yasm__getcwd(void)
+{
+ char *buf;
+ size_t size;
+
+ size = 1024;
+ buf = yasm_xmalloc(size);
+
+ if (getenv("YASM_TEST_SUITE")) {
+ strcpy(buf, "./");
+ return buf;
+ }
+
+ while (getcwd(buf, size-1) == NULL) {
+ if (errno != ERANGE) {
+ yasm__fatal(N_("could not determine current working directory"));
+ yasm_xfree(buf);
+ return NULL;
+ }
+ size *= 2;
+ buf = yasm_xrealloc(buf, size);
+ }
+
+ /* append a '/' if not already present */
+ size = strlen(buf);
+ if (buf[size-1] != '\\' && buf[size-1] != '/') {
+ buf[size] = '/';
+ buf[size+1] = '\0';
+ }
+ return buf;
+}
+
+char *
+yasm__abspath(const char *path)
+{
+ char *curdir, *abspath;
+
+ curdir = yasm__getcwd();
+ abspath = yasm__combpath(curdir, path);
+ yasm_xfree(curdir);
+
+ return abspath;
+}
+
+char *
+yasm__combpath_unix(const char *from, const char *to)
+{
+ const char *tail;
+ size_t pathlen, i, j;
+ char *out;
+
+ if (to[0] == '/') {
+ /* absolute "to" */
+ out = yasm_xmalloc(strlen(to)+1);
+ /* Combine any double slashes when copying */
+ for (j=0; *to; to++) {
+ if (*to == '/' && *(to+1) == '/')
+ continue;
+ out[j++] = *to;
+ }
+ out[j++] = '\0';
+ return out;
+ }
+
+ /* Get path component; note this strips trailing slash */
+ pathlen = yasm__splitpath_unix(from, &tail);
+
+ out = yasm_xmalloc(pathlen+strlen(to)+2); /* worst case maximum len */
+
+ /* Combine any double slashes when copying */
+ for (i=0, j=0; i<pathlen; i++) {
+ if (i<pathlen-1 && from[i] == '/' && from[i+1] == '/')
+ continue;
+ out[j++] = from[i];
+ }
+ pathlen = j;
+
+ /* Add trailing slash back in */
+ if (pathlen > 0 && out[pathlen-1] != '/')
+ out[pathlen++] = '/';
+
+ /* Now scan from left to right through "to", stripping off "." and "..";
+ * if we see "..", back up one directory in out unless last directory in
+ * out is also "..".
+ *
+ * Note this does NOT back through ..'s in the "from" path; this is just
+ * as well as that could skip symlinks (e.g. "foo/bar/.." might not be
+ * the same as "foo").
+ */
+ for (;;) {
+ if (to[0] == '.' && to[1] == '/') {
+ to += 2; /* current directory */
+ while (*to == '/')
+ to++; /* strip off any additional slashes */
+ } else if (pathlen == 0)
+ break; /* no more "from" path left, we're done */
+ else if (to[0] == '.' && to[1] == '.' && to[2] == '/') {
+ if (pathlen >= 3 && out[pathlen-1] == '/' && out[pathlen-2] == '.'
+ && out[pathlen-3] == '.') {
+ /* can't ".." against a "..", so we're done. */
+ break;
+ }
+
+ to += 3; /* throw away "../" */
+ while (*to == '/')
+ to++; /* strip off any additional slashes */
+
+ /* and back out last directory in "out" if not already at root */
+ if (pathlen > 1) {
+ pathlen--; /* strip off trailing '/' */
+ while (pathlen > 0 && out[pathlen-1] != '/')
+ pathlen--;
+ }
+ } else
+ break;
+ }
+
+ /* Copy "to" to tail of output, and we're done */
+ /* Combine any double slashes when copying */
+ for (j=pathlen; *to; to++) {
+ if (*to == '/' && *(to+1) == '/')
+ continue;
+ out[j++] = *to;
+ }
+ out[j++] = '\0';
+
+ return out;
+}
+
+char *
+yasm__combpath_win(const char *from, const char *to)
+{
+ const char *tail;
+ size_t pathlen, i, j;
+ char *out;
+
+ if ((isalpha(to[0]) && to[1] == ':') || (to[0] == '/' || to[0] == '\\')) {
+ /* absolute or drive letter "to" */
+ out = yasm_xmalloc(strlen(to)+1);
+ /* Combine any double slashes when copying */
+ for (j=0; *to; to++) {
+ if ((*to == '/' || *to == '\\')
+ && (*(to+1) == '/' || *(to+1) == '\\'))
+ continue;
+ if (*to == '/')
+ out[j++] = '\\';
+ else
+ out[j++] = *to;
+ }
+ out[j++] = '\0';
+ return out;
+ }
+
+ /* Get path component; note this strips trailing slash */
+ pathlen = yasm__splitpath_win(from, &tail);
+
+ out = yasm_xmalloc(pathlen+strlen(to)+2); /* worst case maximum len */
+
+ /* Combine any double slashes when copying */
+ for (i=0, j=0; i<pathlen; i++) {
+ if (i<pathlen-1 && (from[i] == '/' || from[i] == '\\')
+ && (from[i+1] == '/' || from[i+1] == '\\'))
+ continue;
+ if (from[i] == '/')
+ out[j++] = '\\';
+ else
+ out[j++] = from[i];
+ }
+ pathlen = j;
+
+ /* Add trailing slash back in, unless it's only a raw drive letter */
+ if (pathlen > 0 && out[pathlen-1] != '\\'
+ && !(pathlen == 2 && isalpha(out[0]) && out[1] == ':'))
+ out[pathlen++] = '\\';
+
+ /* Now scan from left to right through "to", stripping off "." and "..";
+ * if we see "..", back up one directory in out unless last directory in
+ * out is also "..".
+ *
+ * Note this does NOT back through ..'s in the "from" path; this is just
+ * as well as that could skip symlinks (e.g. "foo/bar/.." might not be
+ * the same as "foo").
+ */
+ for (;;) {
+ if (to[0] == '.' && (to[1] == '/' || to[1] == '\\')) {
+ to += 2; /* current directory */
+ while (*to == '/' || *to == '\\')
+ to++; /* strip off any additional slashes */
+ } else if (pathlen == 0
+ || (pathlen == 2 && isalpha(out[0]) && out[1] == ':'))
+ break; /* no more "from" path left, we're done */
+ else if (to[0] == '.' && to[1] == '.'
+ && (to[2] == '/' || to[2] == '\\')) {
+ if (pathlen >= 3 && out[pathlen-1] == '\\'
+ && out[pathlen-2] == '.' && out[pathlen-3] == '.') {
+ /* can't ".." against a "..", so we're done. */
+ break;
+ }
+
+ to += 3; /* throw away "../" (or "..\") */
+ while (*to == '/' || *to == '\\')
+ to++; /* strip off any additional slashes */
+
+ /* and back out last directory in "out" if not already at root */
+ if (pathlen > 1) {
+ pathlen--; /* strip off trailing '/' */
+ while (pathlen > 0 && out[pathlen-1] != '\\')
+ pathlen--;
+ }
+ } else
+ break;
+ }
+
+ /* Copy "to" to tail of output, and we're done */
+ /* Combine any double slashes when copying */
+ for (j=pathlen; *to; to++) {
+ if ((*to == '/' || *to == '\\') && (*(to+1) == '/' || *(to+1) == '\\'))
+ continue;
+ if (*to == '/')
+ out[j++] = '\\';
+ else
+ out[j++] = *to;
+ }
+ out[j++] = '\0';
+
+ return out;
+}
+
+size_t
+yasm__createpath_common(const char *path, int win)
+{
+ const char *pp = path, *pe;
+ char *ts, *tp;
+ size_t len, lth;
+
+ lth = len = strlen(path);
+ ts = tp = (char *) malloc(len + 1);
+ pe = pp + len;
+ while (pe > pp) {
+ if ((win && *pe == '\\') || *pe == '/')
+ break;
+ --pe;
+ --lth;
+ }
+
+ while (pp <= pe) {
+ if (pp == pe || (win && *pp == '\\') || *pp == '/') {
+#ifdef _WIN32
+ struct _finddata_t fi;
+ intptr_t h;
+#elif defined(HAVE_SYS_STAT_H)
+ struct stat fi;
+#endif
+ *tp = '\0';
+
+#ifdef _WIN32
+ h = _findfirst(ts, &fi);
+ if (h != -1) {
+ if (fi.attrib != _A_SUBDIR) {
+ _findclose(h);
+ break;
+ }
+ } else if (errno == ENOENT) {
+ if (_mkdir(ts) == -1) {
+ _findclose(h);
+ lth = -1;
+ break;
+ }
+ }
+ _findclose(h);
+#elif defined(HAVE_SYS_STAT_H)
+ if (stat(ts, &fi) != -1) {
+ if (!S_ISDIR(fi.st_mode))
+ break;
+ } else if (errno == ENOENT) {
+ if (mkdir(ts, 0755) == -1) {
+ lth = 0;
+ break;
+ }
+ }
+#else
+ break;
+#endif
+ }
+ *tp++ = *pp++;
+ }
+ free(ts);
+ return lth;
+}
+
+typedef struct incpath {
+ STAILQ_ENTRY(incpath) link;
+ /*@owned@*/ char *path;
+} incpath;
+
+STAILQ_HEAD(incpath_head, incpath) incpaths = STAILQ_HEAD_INITIALIZER(incpaths);
+
+FILE *
+yasm_fopen_include(const char *iname, const char *from, const char *mode,
+ char **oname)
+{
+ FILE *f;
+ char *combine;
+ incpath *np;
+
+ /* Try directly relative to from first, then each of the include paths */
+ if (from) {
+ combine = yasm__combpath(from, iname);
+ f = fopen(combine, mode);
+ if (f) {
+ if (oname)
+ *oname = combine;
+ else
+ yasm_xfree(combine);
+ return f;
+ }
+ yasm_xfree(combine);
+ }
+
+ STAILQ_FOREACH(np, &incpaths, link) {
+ combine = yasm__combpath(np->path, iname);
+ f = fopen(combine, mode);
+ if (f) {
+ if (oname)
+ *oname = combine;
+ else
+ yasm_xfree(combine);
+ return f;
+ }
+ yasm_xfree(combine);
+ }
+
+ if (oname)
+ *oname = NULL;
+ return NULL;
+}
+
+void
+yasm_delete_include_paths(void)
+{
+ incpath *n1, *n2;
+
+ n1 = STAILQ_FIRST(&incpaths);
+ while (n1) {
+ n2 = STAILQ_NEXT(n1, link);
+ yasm_xfree(n1->path);
+ yasm_xfree(n1);
+ n1 = n2;
+ }
+ STAILQ_INIT(&incpaths);
+}
+
+const char *
+yasm_get_include_dir(void **iter)
+{
+ incpath *p = (incpath *)*iter;
+
+ if (!p)
+ p = STAILQ_FIRST(&incpaths);
+ else
+ p = STAILQ_NEXT(p, link);
+
+ *iter = p;
+ if (p)
+ return p->path;
+ else
+ return NULL;
+}
+
+void
+yasm_add_include_path(const char *path)
+{
+ incpath *np = yasm_xmalloc(sizeof(incpath));
+ size_t len = strlen(path);
+
+ np->path = yasm_xmalloc(len+2);
+ memcpy(np->path, path, len+1);
+ /* Add trailing slash if it is missing */
+ if (path[len-1] != '\\' && path[len-1] != '/') {
+ np->path[len] = '/';
+ np->path[len+1] = '\0';
+ }
+
+ STAILQ_INSERT_TAIL(&incpaths, np, link);
+}
+
+size_t
+yasm_fwrite_16_l(unsigned short val, FILE *f)
+{
+ if (fputc(val & 0xFF, f) == EOF)
+ return 0;
+ if (fputc((val >> 8) & 0xFF, f) == EOF)
+ return 0;
+ return 1;
+}
+
+size_t
+yasm_fwrite_32_l(unsigned long val, FILE *f)
+{
+ if (fputc((int)(val & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)((val >> 8) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)((val >> 16) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)((val >> 24) & 0xFF), f) == EOF)
+ return 0;
+ return 1;
+}
+
+size_t
+yasm_fwrite_16_b(unsigned short val, FILE *f)
+{
+ if (fputc((val >> 8) & 0xFF, f) == EOF)
+ return 0;
+ if (fputc(val & 0xFF, f) == EOF)
+ return 0;
+ return 1;
+}
+
+size_t
+yasm_fwrite_32_b(unsigned long val, FILE *f)
+{
+ if (fputc((int)((val >> 24) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)((val >> 16) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)((val >> 8) & 0xFF), f) == EOF)
+ return 0;
+ if (fputc((int)(val & 0xFF), f) == EOF)
+ return 0;
+ return 1;
+}
diff --git a/contrib/tools/yasm/libyasm/file.h b/contrib/tools/yasm/libyasm/file.h
new file mode 100644
index 0000000000..1e9b87b0d5
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/file.h
@@ -0,0 +1,525 @@
+/**
+ * \file libyasm/file.h
+ * \brief YASM file helpers.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_FILE_H
+#define YASM_FILE_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Re2c scanner state. */
+typedef struct yasm_scanner {
+ unsigned char *bot; /**< Bottom of scan buffer */
+ unsigned char *tok; /**< Start of token */
+ unsigned char *ptr; /**< Scan marker */
+ unsigned char *cur; /**< Cursor (1 past end of token) */
+ unsigned char *lim; /**< Limit of good data */
+ unsigned char *top; /**< Top of scan buffer */
+ unsigned char *eof; /**< End of file */
+} yasm_scanner;
+
+/** Initialize scanner state.
+ * \param scanner Re2c scanner state
+ */
+YASM_LIB_DECL
+void yasm_scanner_initialize(yasm_scanner *scanner);
+
+/** Frees any memory used by scanner state; does not free state itself.
+ * \param scanner Re2c scanner state
+ */
+YASM_LIB_DECL
+void yasm_scanner_delete(yasm_scanner *scanner);
+
+/** Fill a scanner state structure with data coming from an input function.
+ * \param scanner Re2c scanner state
+ * \param cursor Re2c scan cursor
+ * \param input_func Input function to read data; takes buffer and maximum
+ * number of bytes, returns number of bytes read.
+ * \param input_func_data Data to pass as the first parameter to input_func
+ * \return 1 if this was the first time this function was called on this
+ * scanner state, 0 otherwise.
+ */
+YASM_LIB_DECL
+int yasm_fill_helper
+ (yasm_scanner *scanner, unsigned char **cursor,
+ size_t (*input_func) (void *d, unsigned char *buf, size_t max),
+ void *input_func_data);
+
+/** Unescape a string with C-style escapes. Handles b, f, n, r, t, and hex
+ * and octal escapes. String is updated in-place.
+ * Edge cases:
+ * - hex escapes: reads as many hex digits as possible, takes last 2 as value.
+ * - oct escapes: takes up to 3 digits 0-9 and scales appropriately, with
+ * warning.
+ * \param str C-style string (updated in place)
+ * \param len length of string (updated with new length)
+ */
+YASM_LIB_DECL
+void yasm_unescape_cstring(unsigned char *str, size_t *len);
+
+/** Split a UNIX pathname into head (directory) and tail (base filename)
+ * portions.
+ * \internal
+ * \param path pathname
+ * \param tail (returned) base filename
+ * \return Length of head (directory).
+ */
+YASM_LIB_DECL
+size_t yasm__splitpath_unix(const char *path, /*@out@*/ const char **tail);
+
+/** Split a Windows pathname into head (directory) and tail (base filename)
+ * portions.
+ * \internal
+ * \param path pathname
+ * \param tail (returned) base filename
+ * \return Length of head (directory).
+ */
+YASM_LIB_DECL
+size_t yasm__splitpath_win(const char *path, /*@out@*/ const char **tail);
+
+/** Split a pathname into head (directory) and tail (base filename) portions.
+ * Unless otherwise defined, defaults to yasm__splitpath_unix().
+ * \internal
+ * \param path pathname
+ * \param tail (returned) base filename
+ * \return Length of head (directory).
+ */
+#ifndef yasm__splitpath
+# if defined (_WIN32) || defined (WIN32) || defined (__MSDOS__) || \
+ defined (__DJGPP__) || defined (__OS2__)
+# define yasm__splitpath(path, tail) yasm__splitpath_win(path, tail)
+# else
+# define yasm__splitpath(path, tail) yasm__splitpath_unix(path, tail)
+# endif
+#endif
+
+/** Get the current working directory.
+ * \internal
+ * \return Current working directory pathname (newly allocated).
+ */
+YASM_LIB_DECL
+/*@only@*/ char *yasm__getcwd(void);
+
+/** Convert a relative or absolute pathname into an absolute pathname.
+ * \internal
+ * \param path pathname
+ * \return Absolute version of path (newly allocated).
+ */
+YASM_LIB_DECL
+/*@only@*/ char *yasm__abspath(const char *path);
+
+/** Build a UNIX pathname that is equivalent to accessing the "to" pathname
+ * when you're in the directory containing "from". Result is relative if both
+ * from and to are relative.
+ * \internal
+ * \param from from pathname
+ * \param to to pathname
+ * \return Combined path (newly allocated).
+ */
+YASM_LIB_DECL
+char *yasm__combpath_unix(const char *from, const char *to);
+
+/** Build a Windows pathname that is equivalent to accessing the "to" pathname
+ * when you're in the directory containing "from". Result is relative if both
+ * from and to are relative.
+ * \internal
+ * \param from from pathname
+ * \param to to pathname
+ * \return Combined path (newly allocated).
+ */
+YASM_LIB_DECL
+char *yasm__combpath_win(const char *from, const char *to);
+
+/** Build a pathname that is equivalent to accessing the "to" pathname
+ * when you're in the directory containing "from". Result is relative if both
+ * from and to are relative.
+ * Unless otherwise defined, defaults to yasm__combpath_unix().
+ * \internal
+ * \param from from pathname
+ * \param to to pathname
+ * \return Combined path (newly allocated).
+ */
+#ifndef yasm__combpath
+# if defined (_WIN32) || defined (WIN32) || defined (__MSDOS__) || \
+ defined (__DJGPP__) || defined (__OS2__)
+# define yasm__combpath(from, to) yasm__combpath_win(from, to)
+# else
+# define yasm__combpath(from, to) yasm__combpath_unix(from, to)
+# endif
+#endif
+
+/** Recursively create tree of directories needed for pathname.
+ * \internal
+ * \param path pathname
+ * \param win handle windows paths
+ * \return Length of directory portion of pathname.
+ */
+YASM_LIB_DECL
+size_t yasm__createpath_common(const char *path, int win);
+
+/** Recursively create tree of directories needed for pathname.
+ * Unless otherwise defined, defaults to yasm__createpath_unix().
+ * \internal
+ * \param path pathname
+ * \return Length of directory portion of pathname.
+ */
+#ifndef yasm__createpath
+# if defined (_WIN32) || defined (WIN32) || defined (__MSDOS__) || \
+ defined (__DJGPP__) || defined (__OS2__)
+# define yasm__createpath(path) yasm__createpath_common(path, 1)
+# else
+# define yasm__createpath(path) yasm__createpath_common(path, 0)
+# endif
+#endif
+
+/** Try to find and open an include file, searching through include paths.
+ * First iname is looked for relative to the directory containing "from", then
+ * it's looked for relative to each of the include paths.
+ *
+ * All pathnames may be either absolute or relative; from, oname, and
+ * include paths, if relative, are relative from the current working directory.
+ *
+ * First match wins; the full pathname (newly allocated) to the opened file
+ * is saved into oname, and the fopen'ed FILE * is returned. If not found,
+ * NULL is returned.
+ *
+ * \param iname file to include
+ * \param from file doing the including
+ * \param mode fopen mode string
+ * \param oname full pathname of included file (may be relative). NULL
+ * may be passed if this is unwanted.
+ * \return fopen'ed include file, or NULL if not found.
+ */
+YASM_LIB_DECL
+/*@null@*/ FILE *yasm_fopen_include
+ (const char *iname, const char *from, const char *mode,
+ /*@null@*/ /*@out@*/ /*@only@*/ char **oname);
+
+/** Delete any stored include paths added by yasm_add_include_path().
+ */
+YASM_LIB_DECL
+void yasm_delete_include_paths(void);
+
+/** Iterate through include paths.
+*/
+YASM_LIB_DECL
+const char * yasm_get_include_dir(void **iter);
+
+/** Add an include path for use by yasm_fopen_include().
+ * If path is relative, it is treated by yasm_fopen_include() as relative to
+ * the current working directory.
+ *
+ * \param path path to add
+ */
+YASM_LIB_DECL
+void yasm_add_include_path(const char *path);
+
+/** Write an 8-bit value to a buffer, incrementing buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 8-bit value
+ */
+#define YASM_WRITE_8(ptr, val) \
+ *((ptr)++) = (unsigned char)((val) & 0xFF)
+
+/** Write a 16-bit value to a buffer in little endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_WRITE_16_L(ptr, val) \
+ do { \
+ *((ptr)++) = (unsigned char)((val) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
+ } while (0)
+
+/** Write a 32-bit value to a buffer in little endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_WRITE_32_L(ptr, val) \
+ do { \
+ *((ptr)++) = (unsigned char)((val) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 16) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 24) & 0xFF); \
+ } while (0)
+
+/** Write a 16-bit value to a buffer in big endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_WRITE_16_B(ptr, val) \
+ do { \
+ *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)++) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
+/** Write a 32-bit value to a buffer in big endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_WRITE_32_B(ptr, val) \
+ do { \
+ *((ptr)++) = (unsigned char)(((val) >> 24) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 16) & 0xFF); \
+ *((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)++) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
+
+/** Write an 8-bit value to a buffer. Does not increment buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 8-bit value
+ */
+#define YASM_SAVE_8(ptr, val) \
+ *(ptr) = (unsigned char)((val) & 0xFF)
+
+/** Write a 16-bit value to a buffer in little endian. Does not increment
+ * buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_SAVE_16_L(ptr, val) \
+ do { \
+ *(ptr) = (unsigned char)((val) & 0xFF); \
+ *((ptr)+1) = (unsigned char)(((val) >> 8) & 0xFF); \
+ } while (0)
+
+/** Write a 32-bit value to a buffer in little endian. Does not increment
+ * buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_SAVE_32_L(ptr, val) \
+ do { \
+ *(ptr) = (unsigned char)((val) & 0xFF); \
+ *((ptr)+1) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)+2) = (unsigned char)(((val) >> 16) & 0xFF); \
+ *((ptr)+3) = (unsigned char)(((val) >> 24) & 0xFF); \
+ } while (0)
+
+/** Write a 16-bit value to a buffer in big endian. Does not increment buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_SAVE_16_B(ptr, val) \
+ do { \
+ *(ptr) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)+1) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
+/** Write a 32-bit value to a buffer in big endian. Does not increment buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_SAVE_32_B(ptr, val) \
+ do { \
+ *(ptr) = (unsigned char)(((val) >> 24) & 0xFF); \
+ *((ptr)+1) = (unsigned char)(((val) >> 16) & 0xFF); \
+ *((ptr)+2) = (unsigned char)(((val) >> 8) & 0xFF); \
+ *((ptr)+3) = (unsigned char)((val) & 0xFF); \
+ } while (0)
+
+/** Direct-to-file version of YASM_SAVE_16_L().
+ * \note Using the macro multiple times with a single fwrite() call will
+ * probably be faster than calling this function many times.
+ * \param val 16-bit value
+ * \param f file
+ * \return 1 if the write was successful, 0 if not (just like fwrite()).
+ */
+YASM_LIB_DECL
+size_t yasm_fwrite_16_l(unsigned short val, FILE *f);
+
+/** Direct-to-file version of YASM_SAVE_32_L().
+ * \note Using the macro multiple times with a single fwrite() call will
+ * probably be faster than calling this function many times.
+ * \param val 32-bit value
+ * \param f file
+ * \return 1 if the write was successful, 0 if not (just like fwrite()).
+ */
+YASM_LIB_DECL
+size_t yasm_fwrite_32_l(unsigned long val, FILE *f);
+
+/** Direct-to-file version of YASM_SAVE_16_B().
+ * \note Using the macro multiple times with a single fwrite() call will
+ * probably be faster than calling this function many times.
+ * \param val 16-bit value
+ * \param f file
+ * \return 1 if the write was successful, 0 if not (just like fwrite()).
+ */
+YASM_LIB_DECL
+size_t yasm_fwrite_16_b(unsigned short val, FILE *f);
+
+/** Direct-to-file version of YASM_SAVE_32_B().
+ * \note Using the macro multiple times with a single fwrite() call will
+ * probably be faster than calling this function many times.
+ * \param val 32-bit value
+ * \param f file
+ * \return 1 if the write was successful, 0 if not (just like fwrite()).
+ */
+YASM_LIB_DECL
+size_t yasm_fwrite_32_b(unsigned long val, FILE *f);
+
+/** Read an 8-bit value from a buffer, incrementing buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 8-bit value
+ */
+#define YASM_READ_8(val, ptr) \
+ (val) = *((ptr)++) & 0xFF
+
+/** Read a 16-bit value from a buffer in little endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_READ_16_L(val, ptr) \
+ do { \
+ (val) = *((ptr)++) & 0xFF; \
+ (val) |= (*((ptr)++) & 0xFF) << 8; \
+ } while (0)
+
+/** Read a 32-bit value from a buffer in little endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_READ_32_L(val, ptr) \
+ do { \
+ (val) = *((ptr)++) & 0xFF; \
+ (val) |= (*((ptr)++) & 0xFF) << 8; \
+ (val) |= (*((ptr)++) & 0xFF) << 16; \
+ (val) |= (*((ptr)++) & 0xFF) << 24; \
+ } while (0)
+
+/** Read a 16-bit value from a buffer in big endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_READ_16_B(val, ptr) \
+ do { \
+ (val) = (*((ptr)++) & 0xFF) << 8; \
+ (val) |= *((ptr)++) & 0xFF; \
+ } while (0)
+
+/** Read a 32-bit value from a buffer in big endian, incrementing buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_READ_32_B(val, ptr) \
+ do { \
+ (val) = (*((ptr)++) & 0xFF) << 24; \
+ (val) |= (*((ptr)++) & 0xFF) << 16; \
+ (val) |= (*((ptr)++) & 0xFF) << 8; \
+ (val) |= *((ptr)++) & 0xFF; \
+ } while (0)
+
+/** Read an 8-bit value from a buffer. Does not increment buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 8-bit value
+ */
+#define YASM_LOAD_8(val, ptr) \
+ (val) = *(ptr) & 0xFF
+
+/** Read a 16-bit value from a buffer in little endian. Does not increment
+ * buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_LOAD_16_L(val, ptr) \
+ do { \
+ (val) = *(ptr) & 0xFF; \
+ (val) |= (*((ptr)+1) & 0xFF) << 8; \
+ } while (0)
+
+/** Read a 32-bit value from a buffer in little endian. Does not increment
+ * buffer pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_LOAD_32_L(val, ptr) \
+ do { \
+ (val) = (unsigned long)(*(ptr) & 0xFF); \
+ (val) |= (unsigned long)((*((ptr)+1) & 0xFF) << 8); \
+ (val) |= (unsigned long)((*((ptr)+2) & 0xFF) << 16); \
+ (val) |= (unsigned long)((*((ptr)+3) & 0xFF) << 24); \
+ } while (0)
+
+/** Read a 16-bit value from a buffer in big endian. Does not increment buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 16-bit value
+ */
+#define YASM_LOAD_16_B(val, ptr) \
+ do { \
+ (val) = (*(ptr) & 0xFF) << 8; \
+ (val) |= *((ptr)+1) & 0xFF; \
+ } while (0)
+
+/** Read a 32-bit value from a buffer in big endian. Does not increment buffer
+ * pointer.
+ * \note Only works properly if ptr is an (unsigned char *).
+ * \param ptr buffer
+ * \param val 32-bit value
+ */
+#define YASM_LOAD_32_B(val, ptr) \
+ do { \
+ (val) = (unsigned long)((*(ptr) & 0xFF) << 24); \
+ (val) |= (unsigned long)((*((ptr)+1) & 0xFF) << 16); \
+ (val) |= (unsigned long)((*((ptr)+2) & 0xFF) << 8); \
+ (val) |= (unsigned long)(*((ptr)+3) & 0xFF); \
+ } while (0)
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/floatnum.c b/contrib/tools/yasm/libyasm/floatnum.c
new file mode 100644
index 0000000000..ab67c2b2e4
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/floatnum.c
@@ -0,0 +1,760 @@
+/*
+ * Floating point number functions.
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
+ *
+ * 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 "util.h"
+
+#include <ctype.h>
+
+#include "coretype.h"
+#include "bitvect.h"
+#include "file.h"
+
+#include "errwarn.h"
+#include "floatnum.h"
+
+
+/* 97-bit internal floating point format:
+ * 0000000s eeeeeeee eeeeeeee m.....................................m
+ * Sign exponent mantissa (80 bits)
+ * 79 0
+ *
+ * Only L.O. bit of Sign byte is significant. The rest is zero.
+ * Exponent is bias 32767.
+ * Mantissa does NOT have an implied one bit (it's explicit).
+ */
+struct yasm_floatnum {
+ /*@only@*/ wordptr mantissa; /* Allocated to MANT_BITS bits */
+ unsigned short exponent;
+ unsigned char sign;
+ unsigned char flags;
+};
+
+/* constants describing parameters of internal floating point format */
+#define MANT_BITS 80
+#define MANT_BYTES 10
+#define MANT_SIGDIGITS 24
+#define EXP_BIAS 0x7FFF
+#define EXP_INF 0xFFFF
+#define EXP_MAX 0xFFFE
+#define EXP_MIN 1
+#define EXP_ZERO 0
+
+/* Flag settings for flags field */
+#define FLAG_ISZERO 1<<0
+
+/* Note this structure integrates the floatnum structure */
+typedef struct POT_Entry_s {
+ yasm_floatnum f;
+ int dec_exponent;
+} POT_Entry;
+
+/* "Source" for POT_Entry. */
+typedef struct POT_Entry_Source_s {
+ unsigned char mantissa[MANT_BYTES]; /* little endian mantissa */
+ unsigned short exponent; /* Bias 32767 exponent */
+} POT_Entry_Source;
+
+/* Power of ten tables used by the floating point I/O routines.
+ * The POT_Table? arrays are built from the POT_Table?_Source arrays at
+ * runtime by POT_Table_Init().
+ */
+
+/* This table contains the powers of ten raised to negative powers of two:
+ *
+ * entry[12-n] = 10 ** (-2 ** n) for 0 <= n <= 12.
+ * entry[13] = 1.0
+ */
+static /*@only@*/ POT_Entry *POT_TableN;
+static POT_Entry_Source POT_TableN_Source[] = {
+ {{0xe3,0x2d,0xde,0x9f,0xce,0xd2,0xc8,0x04,0xdd,0xa6},0x4ad8}, /* 1e-4096 */
+ {{0x25,0x49,0xe4,0x2d,0x36,0x34,0x4f,0x53,0xae,0xce},0x656b}, /* 1e-2048 */
+ {{0xa6,0x87,0xbd,0xc0,0x57,0xda,0xa5,0x82,0xa6,0xa2},0x72b5}, /* 1e-1024 */
+ {{0x33,0x71,0x1c,0xd2,0x23,0xdb,0x32,0xee,0x49,0x90},0x795a}, /* 1e-512 */
+ {{0x91,0xfa,0x39,0x19,0x7a,0x63,0x25,0x43,0x31,0xc0},0x7cac}, /* 1e-256 */
+ {{0x7d,0xac,0xa0,0xe4,0xbc,0x64,0x7c,0x46,0xd0,0xdd},0x7e55}, /* 1e-128 */
+ {{0x24,0x3f,0xa5,0xe9,0x39,0xa5,0x27,0xea,0x7f,0xa8},0x7f2a}, /* 1e-64 */
+ {{0xde,0x67,0xba,0x94,0x39,0x45,0xad,0x1e,0xb1,0xcf},0x7f94}, /* 1e-32 */
+ {{0x2f,0x4c,0x5b,0xe1,0x4d,0xc4,0xbe,0x94,0x95,0xe6},0x7fc9}, /* 1e-16 */
+ {{0xc2,0xfd,0xfc,0xce,0x61,0x84,0x11,0x77,0xcc,0xab},0x7fe4}, /* 1e-8 */
+ {{0xc3,0xd3,0x2b,0x65,0x19,0xe2,0x58,0x17,0xb7,0xd1},0x7ff1}, /* 1e-4 */
+ {{0x71,0x3d,0x0a,0xd7,0xa3,0x70,0x3d,0x0a,0xd7,0xa3},0x7ff8}, /* 1e-2 */
+ {{0xcd,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc},0x7ffb}, /* 1e-1 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80},0x7fff}, /* 1e-0 */
+};
+
+/* This table contains the powers of ten raised to positive powers of two:
+ *
+ * entry[12-n] = 10 ** (2 ** n) for 0 <= n <= 12.
+ * entry[13] = 1.0
+ * entry[-1] = entry[0];
+ *
+ * There is a -1 entry since it is possible for the algorithm to back up
+ * before the table. This -1 entry is created at runtime by duplicating the
+ * 0 entry.
+ */
+static /*@only@*/ POT_Entry *POT_TableP;
+static POT_Entry_Source POT_TableP_Source[] = {
+ {{0x4c,0xc9,0x9a,0x97,0x20,0x8a,0x02,0x52,0x60,0xc4},0xb525}, /* 1e+4096 */
+ {{0x4d,0xa7,0xe4,0x5d,0x3d,0xc5,0x5d,0x3b,0x8b,0x9e},0x9a92}, /* 1e+2048 */
+ {{0x0d,0x65,0x17,0x0c,0x75,0x81,0x86,0x75,0x76,0xc9},0x8d48}, /* 1e+1024 */
+ {{0x65,0xcc,0xc6,0x91,0x0e,0xa6,0xae,0xa0,0x19,0xe3},0x86a3}, /* 1e+512 */
+ {{0xbc,0xdd,0x8d,0xde,0xf9,0x9d,0xfb,0xeb,0x7e,0xaa},0x8351}, /* 1e+256 */
+ {{0x6f,0xc6,0xdf,0x8c,0xe9,0x80,0xc9,0x47,0xba,0x93},0x81a8}, /* 1e+128 */
+ {{0xbf,0x3c,0xd5,0xa6,0xcf,0xff,0x49,0x1f,0x78,0xc2},0x80d3}, /* 1e+64 */
+ {{0x20,0xf0,0x9d,0xb5,0x70,0x2b,0xa8,0xad,0xc5,0x9d},0x8069}, /* 1e+32 */
+ {{0x00,0x00,0x00,0x00,0x00,0x04,0xbf,0xc9,0x1b,0x8e},0x8034}, /* 1e+16 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xbc,0xbe},0x8019}, /* 1e+8 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x9c},0x800c}, /* 1e+4 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8},0x8005}, /* 1e+2 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0},0x8002}, /* 1e+1 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80},0x7fff}, /* 1e+0 */
+};
+
+
+static void
+POT_Table_Init_Entry(/*@out@*/ POT_Entry *e, POT_Entry_Source *s, int dec_exp)
+{
+ /* Save decimal exponent */
+ e->dec_exponent = dec_exp;
+
+ /* Initialize mantissa */
+ e->f.mantissa = BitVector_Create(MANT_BITS, FALSE);
+ BitVector_Block_Store(e->f.mantissa, s->mantissa, MANT_BYTES);
+
+ /* Initialize exponent */
+ e->f.exponent = s->exponent;
+
+ /* Set sign to 0 (positive) */
+ e->f.sign = 0;
+
+ /* Clear flags */
+ e->f.flags = 0;
+}
+
+/*@-compdef@*/
+void
+yasm_floatnum_initialize(void)
+/*@globals undef POT_TableN, undef POT_TableP, POT_TableP_Source,
+ POT_TableN_Source @*/
+{
+ int dec_exp = 1;
+ int i;
+
+ /* Allocate space for two POT tables */
+ POT_TableN = yasm_xmalloc(14*sizeof(POT_Entry));
+ POT_TableP = yasm_xmalloc(15*sizeof(POT_Entry)); /* note 1 extra for -1 */
+
+ /* Initialize entry[0..12] */
+ for (i=12; i>=0; i--) {
+ POT_Table_Init_Entry(&POT_TableN[i], &POT_TableN_Source[i], 0-dec_exp);
+ POT_Table_Init_Entry(&POT_TableP[i+1], &POT_TableP_Source[i], dec_exp);
+ dec_exp *= 2; /* Update decimal exponent */
+ }
+
+ /* Initialize entry[13] */
+ POT_Table_Init_Entry(&POT_TableN[13], &POT_TableN_Source[13], 0);
+ POT_Table_Init_Entry(&POT_TableP[14], &POT_TableP_Source[13], 0);
+
+ /* Initialize entry[-1] for POT_TableP */
+ POT_Table_Init_Entry(&POT_TableP[0], &POT_TableP_Source[0], 4096);
+
+ /* Offset POT_TableP so that [0] becomes [-1] */
+ POT_TableP++;
+}
+/*@=compdef@*/
+
+/*@-globstate@*/
+void
+yasm_floatnum_cleanup(void)
+{
+ int i;
+
+ /* Un-offset POT_TableP */
+ POT_TableP--;
+
+ for (i=0; i<14; i++) {
+ BitVector_Destroy(POT_TableN[i].f.mantissa);
+ BitVector_Destroy(POT_TableP[i].f.mantissa);
+ }
+ BitVector_Destroy(POT_TableP[14].f.mantissa);
+
+ yasm_xfree(POT_TableN);
+ yasm_xfree(POT_TableP);
+}
+/*@=globstate@*/
+
+static void
+floatnum_normalize(yasm_floatnum *flt)
+{
+ long norm_amt;
+
+ if (BitVector_is_empty(flt->mantissa)) {
+ flt->exponent = 0;
+ return;
+ }
+
+ /* Look for the highest set bit, shift to make it the MSB, and adjust
+ * exponent. Don't let exponent go negative. */
+ norm_amt = (MANT_BITS-1)-Set_Max(flt->mantissa);
+ if (norm_amt > (long)flt->exponent)
+ norm_amt = (long)flt->exponent;
+ BitVector_Move_Left(flt->mantissa, (N_int)norm_amt);
+ flt->exponent -= (unsigned short)norm_amt;
+}
+
+/* acc *= op */
+static void
+floatnum_mul(yasm_floatnum *acc, const yasm_floatnum *op)
+{
+ long expon;
+ wordptr product, op1, op2;
+ long norm_amt;
+
+ /* Compute the new sign */
+ acc->sign ^= op->sign;
+
+ /* Check for multiply by 0 */
+ if (BitVector_is_empty(acc->mantissa) || BitVector_is_empty(op->mantissa)) {
+ BitVector_Empty(acc->mantissa);
+ acc->exponent = EXP_ZERO;
+ return;
+ }
+
+ /* Add exponents, checking for overflow/underflow. */
+ expon = (((int)acc->exponent)-EXP_BIAS) + (((int)op->exponent)-EXP_BIAS);
+ expon += EXP_BIAS;
+ if (expon > EXP_MAX) {
+ /* Overflow; return infinity. */
+ BitVector_Empty(acc->mantissa);
+ acc->exponent = EXP_INF;
+ return;
+ } else if (expon < EXP_MIN) {
+ /* Underflow; return zero. */
+ BitVector_Empty(acc->mantissa);
+ acc->exponent = EXP_ZERO;
+ return;
+ }
+
+ /* Add one to the final exponent, as the multiply shifts one extra time. */
+ acc->exponent = (unsigned short)(expon+1);
+
+ /* Allocate space for the multiply result */
+ product = BitVector_Create((N_int)((MANT_BITS+1)*2), FALSE);
+
+ /* Allocate 1-bit-longer fields to force the operands to be unsigned */
+ op1 = BitVector_Create((N_int)(MANT_BITS+1), FALSE);
+ op2 = BitVector_Create((N_int)(MANT_BITS+1), FALSE);
+
+ /* Make the operands unsigned after copying from original operands */
+ BitVector_Copy(op1, acc->mantissa);
+ BitVector_MSB(op1, 0);
+ BitVector_Copy(op2, op->mantissa);
+ BitVector_MSB(op2, 0);
+
+ /* Compute the product of the mantissas */
+ BitVector_Multiply(product, op1, op2);
+
+ /* Normalize the product. Note: we know the product is non-zero because
+ * both of the original operands were non-zero.
+ *
+ * Look for the highest set bit, shift to make it the MSB, and adjust
+ * exponent. Don't let exponent go negative.
+ */
+ norm_amt = (MANT_BITS*2-1)-Set_Max(product);
+ if (norm_amt > (long)acc->exponent)
+ norm_amt = (long)acc->exponent;
+ BitVector_Move_Left(product, (N_int)norm_amt);
+ acc->exponent -= (unsigned short)norm_amt;
+
+ /* Store the highest bits of the result */
+ BitVector_Interval_Copy(acc->mantissa, product, 0, MANT_BITS, MANT_BITS);
+
+ /* Free allocated variables */
+ BitVector_Destroy(product);
+ BitVector_Destroy(op1);
+ BitVector_Destroy(op2);
+}
+
+yasm_floatnum *
+yasm_floatnum_create(const char *str)
+{
+ yasm_floatnum *flt;
+ int dec_exponent, dec_exp_add; /* decimal (powers of 10) exponent */
+ int POT_index;
+ wordptr operand[2];
+ int sig_digits;
+ int decimal_pt;
+ boolean carry;
+
+ flt = yasm_xmalloc(sizeof(yasm_floatnum));
+
+ flt->mantissa = BitVector_Create(MANT_BITS, TRUE);
+
+ /* allocate and initialize calculation variables */
+ operand[0] = BitVector_Create(MANT_BITS, TRUE);
+ operand[1] = BitVector_Create(MANT_BITS, TRUE);
+ dec_exponent = 0;
+ sig_digits = 0;
+ decimal_pt = 1;
+
+ /* set initial flags to 0 */
+ flt->flags = 0;
+
+ /* check for + or - character and skip */
+ if (*str == '-') {
+ flt->sign = 1;
+ str++;
+ } else if (*str == '+') {
+ flt->sign = 0;
+ str++;
+ } else
+ flt->sign = 0;
+
+ /* eliminate any leading zeros (which do not count as significant digits) */
+ while (*str == '0')
+ str++;
+
+ /* When we reach the end of the leading zeros, first check for a decimal
+ * point. If the number is of the form "0---0.0000" we need to get rid
+ * of the zeros after the decimal point and not count them as significant
+ * digits.
+ */
+ if (*str == '.') {
+ str++;
+ while (*str == '0') {
+ str++;
+ dec_exponent--;
+ }
+ } else {
+ /* The number is of the form "yyy.xxxx" (where y <> 0). */
+ while (isdigit(*str)) {
+ /* See if we've processed more than the max significant digits: */
+ if (sig_digits < MANT_SIGDIGITS) {
+ /* Multiply mantissa by 10 [x = (x<<1)+(x<<3)] */
+ BitVector_shift_left(flt->mantissa, 0);
+ BitVector_Copy(operand[0], flt->mantissa);
+ BitVector_Move_Left(flt->mantissa, 2);
+ carry = 0;
+ BitVector_add(operand[1], operand[0], flt->mantissa, &carry);
+
+ /* Add in current digit */
+ BitVector_Empty(operand[0]);
+ BitVector_Chunk_Store(operand[0], 4, 0, (N_long)(*str-'0'));
+ carry = 0;
+ BitVector_add(flt->mantissa, operand[1], operand[0], &carry);
+ } else {
+ /* Can't integrate more digits with mantissa, so instead just
+ * raise by a power of ten.
+ */
+ dec_exponent++;
+ }
+ sig_digits++;
+ str++;
+ }
+
+ if (*str == '.')
+ str++;
+ else
+ decimal_pt = 0;
+ }
+
+ if (decimal_pt) {
+ /* Process the digits to the right of the decimal point. */
+ while (isdigit(*str)) {
+ /* See if we've processed more than 19 significant digits: */
+ if (sig_digits < 19) {
+ /* Raise by a power of ten */
+ dec_exponent--;
+
+ /* Multiply mantissa by 10 [x = (x<<1)+(x<<3)] */
+ BitVector_shift_left(flt->mantissa, 0);
+ BitVector_Copy(operand[0], flt->mantissa);
+ BitVector_Move_Left(flt->mantissa, 2);
+ carry = 0;
+ BitVector_add(operand[1], operand[0], flt->mantissa, &carry);
+
+ /* Add in current digit */
+ BitVector_Empty(operand[0]);
+ BitVector_Chunk_Store(operand[0], 4, 0, (N_long)(*str-'0'));
+ carry = 0;
+ BitVector_add(flt->mantissa, operand[1], operand[0], &carry);
+ }
+ sig_digits++;
+ str++;
+ }
+ }
+
+ if (*str == 'e' || *str == 'E') {
+ str++;
+ /* We just saw the "E" character, now read in the exponent value and
+ * add it into dec_exponent.
+ */
+ dec_exp_add = 0;
+ sscanf(str, "%d", &dec_exp_add);
+ dec_exponent += dec_exp_add;
+ }
+
+ /* Free calculation variables. */
+ BitVector_Destroy(operand[1]);
+ BitVector_Destroy(operand[0]);
+
+ /* Normalize the number, checking for 0 first. */
+ if (BitVector_is_empty(flt->mantissa)) {
+ /* Mantissa is 0, zero exponent too. */
+ flt->exponent = 0;
+ /* Set zero flag so output functions don't see 0 value as underflow. */
+ flt->flags |= FLAG_ISZERO;
+ /* Return 0 value. */
+ return flt;
+ }
+ /* Exponent if already norm. */
+ flt->exponent = (unsigned short)(0x7FFF+(MANT_BITS-1));
+ floatnum_normalize(flt);
+
+ /* The number is normalized. Now multiply by 10 the number of times
+ * specified in DecExponent. This uses the power of ten tables to speed
+ * up this operation (and make it more accurate).
+ */
+ if (dec_exponent > 0) {
+ POT_index = 0;
+ /* Until we hit 1.0 or finish exponent or overflow */
+ while ((POT_index < 14) && (dec_exponent != 0) &&
+ (flt->exponent != EXP_INF)) {
+ /* Find the first power of ten in the table which is just less than
+ * the exponent.
+ */
+ while (dec_exponent < POT_TableP[POT_index].dec_exponent)
+ POT_index++;
+
+ if (POT_index < 14) {
+ /* Subtract out what we're multiplying in from exponent */
+ dec_exponent -= POT_TableP[POT_index].dec_exponent;
+
+ /* Multiply by current power of 10 */
+ floatnum_mul(flt, &POT_TableP[POT_index].f);
+ }
+ }
+ } else if (dec_exponent < 0) {
+ POT_index = 0;
+ /* Until we hit 1.0 or finish exponent or underflow */
+ while ((POT_index < 14) && (dec_exponent != 0) &&
+ (flt->exponent != EXP_ZERO)) {
+ /* Find the first power of ten in the table which is just less than
+ * the exponent.
+ */
+ while (dec_exponent > POT_TableN[POT_index].dec_exponent)
+ POT_index++;
+
+ if (POT_index < 14) {
+ /* Subtract out what we're multiplying in from exponent */
+ dec_exponent -= POT_TableN[POT_index].dec_exponent;
+
+ /* Multiply by current power of 10 */
+ floatnum_mul(flt, &POT_TableN[POT_index].f);
+ }
+ }
+ }
+
+ /* Round the result. (Don't round underflow or overflow). Also don't
+ * increment if this would cause the mantissa to wrap.
+ */
+ if ((flt->exponent != EXP_INF) && (flt->exponent != EXP_ZERO) &&
+ !BitVector_is_full(flt->mantissa))
+ BitVector_increment(flt->mantissa);
+
+ return flt;
+}
+
+yasm_floatnum *
+yasm_floatnum_copy(const yasm_floatnum *flt)
+{
+ yasm_floatnum *f = yasm_xmalloc(sizeof(yasm_floatnum));
+
+ f->mantissa = BitVector_Clone(flt->mantissa);
+ f->exponent = flt->exponent;
+ f->sign = flt->sign;
+ f->flags = flt->flags;
+
+ return f;
+}
+
+void
+yasm_floatnum_destroy(yasm_floatnum *flt)
+{
+ BitVector_Destroy(flt->mantissa);
+ yasm_xfree(flt);
+}
+
+int
+yasm_floatnum_calc(yasm_floatnum *acc, yasm_expr_op op,
+ /*@unused@*/ yasm_floatnum *operand)
+{
+ if (op != YASM_EXPR_NEG) {
+ yasm_error_set(YASM_ERROR_FLOATING_POINT,
+ N_("Unsupported floating-point arithmetic operation"));
+ return 1;
+ }
+ acc->sign ^= 1;
+ return 0;
+}
+
+int
+yasm_floatnum_get_int(const yasm_floatnum *flt, unsigned long *ret_val)
+{
+ unsigned char t[4];
+
+ if (yasm_floatnum_get_sized(flt, t, 4, 32, 0, 0, 0)) {
+ *ret_val = 0xDEADBEEFUL; /* Obviously incorrect return value */
+ return 1;
+ }
+
+ YASM_LOAD_32_L(*ret_val, &t[0]);
+ return 0;
+}
+
+/* Function used by conversion routines to actually perform the conversion.
+ *
+ * ptr -> the array to return the little-endian floating point value into.
+ * flt -> the floating point value to convert.
+ * byte_size -> the size in bytes of the output format.
+ * mant_bits -> the size in bits of the output mantissa.
+ * implicit1 -> does the output format have an implicit 1? 1=yes, 0=no.
+ * exp_bits -> the size in bits of the output exponent.
+ *
+ * Returns 0 on success, 1 if overflow, -1 if underflow.
+ */
+static int
+floatnum_get_common(const yasm_floatnum *flt, /*@out@*/ unsigned char *ptr,
+ N_int byte_size, N_int mant_bits, int implicit1,
+ N_int exp_bits)
+{
+ long exponent = (long)flt->exponent;
+ wordptr output;
+ charptr buf;
+ unsigned int len;
+ unsigned int overflow = 0, underflow = 0;
+ int retval = 0;
+ long exp_bias = (1<<(exp_bits-1))-1;
+ long exp_inf = (1<<exp_bits)-1;
+
+ output = BitVector_Create(byte_size*8, TRUE);
+
+ /* copy mantissa */
+ BitVector_Interval_Copy(output, flt->mantissa, 0,
+ (N_int)((MANT_BITS-implicit1)-mant_bits),
+ mant_bits);
+
+ /* round mantissa */
+ if (BitVector_bit_test(flt->mantissa, (MANT_BITS-implicit1)-(mant_bits+1)))
+ BitVector_increment(output);
+
+ if (BitVector_bit_test(output, mant_bits)) {
+ /* overflowed, so zero mantissa (and set explicit bit if necessary) */
+ BitVector_Empty(output);
+ BitVector_Bit_Copy(output, mant_bits-1, !implicit1);
+ /* and up the exponent (checking for overflow) */
+ if (exponent+1 >= EXP_INF)
+ overflow = 1;
+ else
+ exponent++;
+ }
+
+ /* adjust the exponent to the output bias, checking for overflow */
+ exponent -= EXP_BIAS-exp_bias;
+ if (exponent >= exp_inf)
+ overflow = 1;
+ else if (exponent <= 0)
+ underflow = 1;
+
+ /* underflow and overflow both set!? */
+ if (underflow && overflow)
+ yasm_internal_error(N_("Both underflow and overflow set"));
+
+ /* check for underflow or overflow and set up appropriate output */
+ if (underflow) {
+ BitVector_Empty(output);
+ exponent = 0;
+ if (!(flt->flags & FLAG_ISZERO))
+ retval = -1;
+ } else if (overflow) {
+ BitVector_Empty(output);
+ exponent = exp_inf;
+ retval = 1;
+ }
+
+ /* move exponent into place */
+ BitVector_Chunk_Store(output, exp_bits, mant_bits, (N_long)exponent);
+
+ /* merge in sign bit */
+ BitVector_Bit_Copy(output, byte_size*8-1, flt->sign);
+
+ /* get little-endian bytes */
+ buf = BitVector_Block_Read(output, &len);
+ if (len < byte_size)
+ yasm_internal_error(
+ N_("Byte length of BitVector does not match bit length"));
+
+ /* copy to output */
+ memcpy(ptr, buf, byte_size*sizeof(unsigned char));
+
+ /* free allocated resources */
+ yasm_xfree(buf);
+
+ BitVector_Destroy(output);
+
+ return retval;
+}
+
+/* IEEE-754r "half precision" format:
+ * 16 bits:
+ * 15 9 Bit 0
+ * | | |
+ * seee eemm mmmm mmmm
+ *
+ * e = bias 15 exponent
+ * s = sign bit
+ * m = mantissa bits, bit 10 is an implied one bit.
+ *
+ * IEEE-754 (Intel) "single precision" format:
+ * 32 bits:
+ * Bit 31 Bit 22 Bit 0
+ * | | |
+ * seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
+ *
+ * e = bias 127 exponent
+ * s = sign bit
+ * m = mantissa bits, bit 23 is an implied one bit.
+ *
+ * IEEE-754 (Intel) "double precision" format:
+ * 64 bits:
+ * bit 63 bit 51 bit 0
+ * | | |
+ * seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
+ *
+ * e = bias 1023 exponent.
+ * s = sign bit.
+ * m = mantissa bits. Bit 52 is an implied one bit.
+ *
+ * IEEE-754 (Intel) "extended precision" format:
+ * 80 bits:
+ * bit 79 bit 63 bit 0
+ * | | |
+ * seeeeeee eeeeeeee mmmmmmmm m...m m...m m...m m...m m...m
+ *
+ * e = bias 16383 exponent
+ * m = 64 bit mantissa with NO implied bit!
+ * s = sign (for mantissa)
+ */
+int
+yasm_floatnum_get_sized(const yasm_floatnum *flt, unsigned char *ptr,
+ size_t destsize, size_t valsize, size_t shift,
+ int bigendian, int warn)
+{
+ int retval;
+ if (destsize*8 != valsize || shift>0 || bigendian) {
+ /* TODO */
+ yasm_internal_error(N_("unsupported floatnum functionality"));
+ }
+ switch (destsize) {
+ case 2:
+ retval = floatnum_get_common(flt, ptr, 2, 10, 1, 5);
+ break;
+ case 4:
+ retval = floatnum_get_common(flt, ptr, 4, 23, 1, 8);
+ break;
+ case 8:
+ retval = floatnum_get_common(flt, ptr, 8, 52, 1, 11);
+ break;
+ case 10:
+ retval = floatnum_get_common(flt, ptr, 10, 64, 0, 15);
+ break;
+ default:
+ yasm_internal_error(N_("Invalid float conversion size"));
+ /*@notreached@*/
+ return 1;
+ }
+ if (warn) {
+ if (retval < 0)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("underflow in floating point expression"));
+ else if (retval > 0)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("overflow in floating point expression"));
+ }
+ return retval;
+}
+
+/* 1 if the size is valid, 0 if it isn't */
+int
+yasm_floatnum_check_size(/*@unused@*/ const yasm_floatnum *flt, size_t size)
+{
+ switch (size) {
+ case 16:
+ case 32:
+ case 64:
+ case 80:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+void
+yasm_floatnum_print(const yasm_floatnum *flt, FILE *f)
+{
+ unsigned char out[10];
+ unsigned char *str;
+ int i;
+
+ /* Internal format */
+ str = BitVector_to_Hex(flt->mantissa);
+ fprintf(f, "%c %s *2^%04x\n", flt->sign?'-':'+', (char *)str,
+ flt->exponent);
+ yasm_xfree(str);
+
+ /* 32-bit (single precision) format */
+ fprintf(f, "32-bit: %d: ",
+ yasm_floatnum_get_sized(flt, out, 4, 32, 0, 0, 0));
+ for (i=0; i<4; i++)
+ fprintf(f, "%02x ", out[i]);
+ fprintf(f, "\n");
+
+ /* 64-bit (double precision) format */
+ fprintf(f, "64-bit: %d: ",
+ yasm_floatnum_get_sized(flt, out, 8, 64, 0, 0, 0));
+ for (i=0; i<8; i++)
+ fprintf(f, "%02x ", out[i]);
+ fprintf(f, "\n");
+
+ /* 80-bit (extended precision) format */
+ fprintf(f, "80-bit: %d: ",
+ yasm_floatnum_get_sized(flt, out, 10, 80, 0, 0, 0));
+ for (i=0; i<10; i++)
+ fprintf(f, "%02x ", out[i]);
+ fprintf(f, "\n");
+}
diff --git a/contrib/tools/yasm/libyasm/floatnum.h b/contrib/tools/yasm/libyasm/floatnum.h
new file mode 100644
index 0000000000..d2c7042097
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/floatnum.h
@@ -0,0 +1,131 @@
+/**
+ * \file libyasm/floatnum.h
+ * \brief YASM floating point (IEEE) interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_FLOATNUM_H
+#define YASM_FLOATNUM_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Initialize floatnum internal data structures. */
+YASM_LIB_DECL
+void yasm_floatnum_initialize(void);
+
+/** Clean up internal floatnum allocations. */
+YASM_LIB_DECL
+void yasm_floatnum_cleanup(void);
+
+/** Create a new floatnum from a decimal string. The input string must be in
+ * standard C representation ([+-]123.456e[-+]789).
+ * \param str floating point decimal string
+ * \return Newly allocated floatnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_floatnum *yasm_floatnum_create(const char *str);
+
+/** Duplicate a floatnum.
+ * \param flt floatnum
+ * \return Newly allocated floatnum with the same value as flt.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_floatnum *yasm_floatnum_copy(const yasm_floatnum *flt);
+
+/** Destroy (free allocated memory for) a floatnum.
+ * \param flt floatnum
+ */
+YASM_LIB_DECL
+void yasm_floatnum_destroy(/*@only@*/ yasm_floatnum *flt);
+
+/** Floating point calculation function: acc = acc op operand.
+ * \note Not all operations in yasm_expr_op may be supported; unsupported
+ * operations will result in an error.
+ * \param acc floatnum accumulator
+ * \param op operation
+ * \param operand floatnum operand
+ * \return Nonzero on error.
+ */
+YASM_LIB_DECL
+int yasm_floatnum_calc(yasm_floatnum *acc, yasm_expr_op op,
+ yasm_floatnum *operand);
+
+/** Convert a floatnum to single-precision and return as 32-bit value.
+ * The 32-bit value is a "standard" C value (eg, of unknown endian).
+ * \param flt floatnum
+ * \param ret_val pointer to storage for 32-bit output
+ * \return Nonzero if flt can't fit into single precision: -1 if underflow
+ * occurred, 1 if overflow occurred.
+ */
+YASM_LIB_DECL
+int yasm_floatnum_get_int(const yasm_floatnum *flt,
+ /*@out@*/ unsigned long *ret_val);
+
+/** Output a #yasm_floatnum to buffer in little-endian or big-endian. Puts the
+ * value into the least significant bits of the destination, or may be shifted
+ * into more significant bits by the shift parameter. The destination bits are
+ * cleared before being set. [0] should be the first byte output to the file.
+ * \note Not all sizes are valid. Currently, only 32 (single-precision), 64
+ * (double-precision), and 80 (extended-precision) are valid sizes.
+ * Use yasm_floatnum_check_size() to check for supported sizes.
+ * \param flt floatnum
+ * \param ptr pointer to storage for size bytes of output
+ * \param destsize destination size (in bytes)
+ * \param valsize size (in bits)
+ * \param shift left shift (in bits)
+ * \param bigendian endianness (nonzero=big, zero=little)
+ * \param warn enables standard overflow/underflow warnings
+ * \return Nonzero if flt can't fit into the specified precision: -1 if
+ * underflow occurred, 1 if overflow occurred.
+ */
+YASM_LIB_DECL
+int yasm_floatnum_get_sized(const yasm_floatnum *flt, unsigned char *ptr,
+ size_t destsize, size_t valsize, size_t shift,
+ int bigendian, int warn);
+
+/** Basic check to see if size is valid for flt conversion (using
+ * yasm_floatnum_get_sized()). Doesn't actually check for underflow/overflow
+ * but rather checks for size=32,64,80
+ * (at present).
+ * \param flt floatnum
+ * \param size number of bits of output space
+ * \return 1 if valid size, 0 if invalid size.
+ */
+YASM_LIB_DECL
+int yasm_floatnum_check_size(const yasm_floatnum *flt, size_t size);
+
+/** Print various representations of a floatnum. For debugging purposes only.
+ * \param f file
+ * \param flt floatnum
+ */
+YASM_LIB_DECL
+void yasm_floatnum_print(const yasm_floatnum *flt, FILE *f);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/genmodule.c b/contrib/tools/yasm/libyasm/genmodule.c
new file mode 100644
index 0000000000..867d93a5b2
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/genmodule.c
@@ -0,0 +1,228 @@
+/*
+ *
+ * Generate module.c from module.in and Makefile.am or Makefile.
+ *
+ * Copyright (C) 2004-2007 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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "compat-queue.h"
+
+#define OUTPUT "module.c"
+#define MAXNAME 128
+#define MAXLINE 1024
+#define MAXMODULES 128
+#define MAXINCLUDES 256
+
+typedef struct include {
+ STAILQ_ENTRY(include) link;
+ char *filename;
+} include;
+
+int
+main(int argc, char *argv[])
+{
+ FILE *in, *out;
+ char *str;
+ int i;
+ size_t len;
+ char *strp;
+ char *modules[MAXMODULES];
+ int num_modules = 0;
+ STAILQ_HEAD(includehead, include) includes =
+ STAILQ_HEAD_INITIALIZER(includes);
+ include *inc;
+ int isam = 0;
+ int linecont = 0;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s <module.in> <Makefile[.am]>\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ str = malloc(MAXLINE);
+
+ /* Starting with initial input Makefile, look for include <file> or
+ * YASM_MODULES += <module>. Note this currently doesn't handle
+ * a relative starting path.
+ */
+ len = strlen(argv[2]);
+ inc = malloc(sizeof(include));
+ inc->filename = malloc(len+1);
+ strcpy(inc->filename, argv[2]);
+ STAILQ_INSERT_TAIL(&includes, inc, link);
+
+ isam = argv[2][len-2] == 'a' && argv[2][len-1] == 'm';
+
+ while (!STAILQ_EMPTY(&includes)) {
+ inc = STAILQ_FIRST(&includes);
+ STAILQ_REMOVE_HEAD(&includes, link);
+ in = fopen(inc->filename, "rt");
+ if (!in) {
+ fprintf(stderr, "Could not open `%s'.\n", inc->filename);
+ return EXIT_FAILURE;
+ }
+ free(inc->filename);
+ free(inc);
+
+ while (fgets(str, MAXLINE, in)) {
+ /* Strip off any trailing whitespace */
+ len = strlen(str);
+ if (len > 0) {
+ strp = &str[len-1];
+ while (len > 0 && isspace(*strp)) {
+ *strp-- = '\0';
+ len--;
+ }
+ }
+
+ strp = str;
+
+ /* Skip whitespace */
+ while (isspace(*strp))
+ strp++;
+
+ /* Skip comments */
+ if (*strp == '#')
+ continue;
+
+ /* If line continuation, skip to continue copy */
+ if (linecont)
+ goto keepgoing;
+
+ /* Check for include if original input is .am file */
+ if (isam && strncmp(strp, "include", 7) == 0 && isspace(strp[7])) {
+ strp += 7;
+ while (isspace(*strp))
+ strp++;
+ /* Build new include and add to end of list */
+ inc = malloc(sizeof(include));
+ inc->filename = malloc(strlen(strp)+1);
+ strcpy(inc->filename, strp);
+ STAILQ_INSERT_TAIL(&includes, inc, link);
+ continue;
+ }
+
+ /* Check for YASM_MODULES = or += */
+ if (strncmp(strp, "YASM_MODULES", 12) != 0)
+ continue;
+ strp += 12;
+ while (isspace(*strp))
+ strp++;
+ if (strncmp(strp, "+=", 2) != 0 && *strp != '=')
+ continue;
+ if (*strp == '+')
+ strp++;
+ strp++;
+ while (isspace(*strp))
+ strp++;
+
+keepgoing:
+ /* Check for continuation */
+ if (len > 0 && str[len-1] == '\\') {
+ str[len-1] = '\0';
+ while (isspace(*strp))
+ *strp-- = '\0';
+ linecont = 1;
+ } else
+ linecont = 0;
+
+ while (*strp != '\0') {
+ /* Copy module name */
+ modules[num_modules] = malloc(MAXNAME);
+ len = 0;
+ while (*strp != '\0' && !isspace(*strp))
+ modules[num_modules][len++] = *strp++;
+ modules[num_modules][len] = '\0';
+ num_modules++;
+
+ while (isspace(*strp))
+ strp++;
+ }
+ }
+ fclose(in);
+ }
+
+ out = fopen(OUTPUT, "wt");
+
+ if (!out) {
+ fprintf(stderr, "Could not open `%s'.\n", OUTPUT);
+ return EXIT_FAILURE;
+ }
+
+ fprintf(out, "/* This file auto-generated by genmodule.c"
+ " - don't edit it */\n\n");
+
+ in = fopen(argv[1], "rt");
+ if (!in) {
+ fprintf(stderr, "Could not open `%s'.\n", argv[1]);
+ fclose(out);
+ remove(OUTPUT);
+ return EXIT_FAILURE;
+ }
+
+ len = 0;
+ while (fgets(str, MAXLINE, in)) {
+ if (strncmp(str, "MODULES_", 8) == 0) {
+ len = 0;
+ strp = str+8;
+ while (*strp != '\0' && *strp != '_') {
+ len++;
+ strp++;
+ }
+ *strp = '\0';
+
+ for (i=0; i<num_modules; i++) {
+ if (strncmp(modules[i], str+8, len) == 0) {
+ fprintf(out, " {\"%s\", &yasm_%s_LTX_%s},\n",
+ modules[i]+len+1, modules[i]+len+1, str+8);
+ }
+ }
+ } else if (strncmp(str, "EXTERN_LIST", 11) == 0) {
+ for (i=0; i<num_modules; i++) {
+ strcpy(str, modules[i]);
+ strp = str;
+ while (*strp != '\0' && *strp != '_')
+ strp++;
+ *strp++ = '\0';
+
+ fprintf(out, "extern yasm_%s_module yasm_%s_LTX_%s;\n",
+ str, strp, str);
+ }
+ } else
+ fputs(str, out);
+ }
+
+ fclose(in);
+ fclose(out);
+
+ for (i=0; i<num_modules; i++)
+ free(modules[i]);
+ free(str);
+
+ return EXIT_SUCCESS;
+}
diff --git a/contrib/tools/yasm/libyasm/hamt.c b/contrib/tools/yasm/libyasm/hamt.c
new file mode 100644
index 0000000000..59b7592109
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/hamt.c
@@ -0,0 +1,421 @@
+/*
+ * Hash Array Mapped Trie (HAMT) implementation
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Based on the paper "Ideal Hash Tries" by Phil Bagwell [2000].
+ * One algorithmic change from that described in the paper: we use the LSB's
+ * of the key to index the root table and move upward in the key rather than
+ * use the MSBs as described in the paper. The LSBs have more entropy.
+ *
+ * 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 "util.h"
+
+#include <ctype.h>
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+#include "hamt.h"
+
+struct HAMTEntry {
+ STAILQ_ENTRY(HAMTEntry) next; /* next hash table entry */
+ /*@dependent@*/ const char *str; /* string being hashed */
+ /*@owned@*/ void *data; /* data pointer being stored */
+};
+
+typedef struct HAMTNode {
+ unsigned long BitMapKey; /* 32 bits, bitmap or hash key */
+ uintptr_t BaseValue; /* Base of HAMTNode list or value */
+} HAMTNode;
+
+struct HAMT {
+ STAILQ_HEAD(HAMTEntryHead, HAMTEntry) entries;
+ HAMTNode *root;
+ /*@exits@*/ void (*error_func) (const char *file, unsigned int line,
+ const char *message);
+ unsigned long (*HashKey) (const char *key);
+ unsigned long (*ReHashKey) (const char *key, int Level);
+ int (*CmpKey) (const char *s1, const char *s2);
+};
+
+/* XXX make a portable version of this. This depends on the pointer being
+ * 4 or 2-byte aligned (as it uses the LSB of the pointer variable to store
+ * the subtrie flag!
+ */
+#define IsSubTrie(n) ((n)->BaseValue & 1)
+#define SetSubTrie(h, n, v) do { \
+ if ((uintptr_t)(v) & 1) \
+ h->error_func(__FILE__, __LINE__, \
+ N_("Subtrie is seen as subtrie before flag is set (misaligned?)")); \
+ (n)->BaseValue = (uintptr_t)(v) | 1; \
+ } while (0)
+#define SetValue(h, n, v) do { \
+ if ((uintptr_t)(v) & 1) \
+ h->error_func(__FILE__, __LINE__, \
+ N_("Value is seen as subtrie (misaligned?)")); \
+ (n)->BaseValue = (uintptr_t)(v); \
+ } while (0)
+#define GetSubTrie(n) (HAMTNode *)(((n)->BaseValue | 1) ^ 1)
+
+static unsigned long
+HashKey(const char *key)
+{
+ unsigned long a=31415, b=27183, vHash;
+ for (vHash=0; *key; key++, a*=b)
+ vHash = a*vHash + *key;
+ return vHash;
+}
+
+static unsigned long
+ReHashKey(const char *key, int Level)
+{
+ unsigned long a=31415, b=27183, vHash;
+ for (vHash=0; *key; key++, a*=b)
+ vHash = a*vHash*(unsigned long)Level + *key;
+ return vHash;
+}
+
+static unsigned long
+HashKey_nocase(const char *key)
+{
+ unsigned long a=31415, b=27183, vHash;
+ for (vHash=0; *key; key++, a*=b)
+ vHash = a*vHash + tolower(*key);
+ return vHash;
+}
+
+static unsigned long
+ReHashKey_nocase(const char *key, int Level)
+{
+ unsigned long a=31415, b=27183, vHash;
+ for (vHash=0; *key; key++, a*=b)
+ vHash = a*vHash*(unsigned long)Level + tolower(*key);
+ return vHash;
+}
+
+HAMT *
+HAMT_create(int nocase, /*@exits@*/ void (*error_func)
+ (const char *file, unsigned int line, const char *message))
+{
+ /*@out@*/ HAMT *hamt = yasm_xmalloc(sizeof(HAMT));
+ int i;
+
+ STAILQ_INIT(&hamt->entries);
+ hamt->root = yasm_xmalloc(32*sizeof(HAMTNode));
+
+ for (i=0; i<32; i++) {
+ hamt->root[i].BitMapKey = 0;
+ hamt->root[i].BaseValue = 0;
+ }
+
+ hamt->error_func = error_func;
+ if (nocase) {
+ hamt->HashKey = HashKey_nocase;
+ hamt->ReHashKey = ReHashKey_nocase;
+ hamt->CmpKey = yasm__strcasecmp;
+ } else {
+ hamt->HashKey = HashKey;
+ hamt->ReHashKey = ReHashKey;
+ hamt->CmpKey = strcmp;
+ }
+
+ return hamt;
+}
+
+static void
+HAMT_delete_trie(HAMTNode *node)
+{
+ if (IsSubTrie(node)) {
+ unsigned long i, Size;
+
+ /* Count total number of bits in bitmap to determine size */
+ BitCount(Size, node->BitMapKey);
+ Size &= 0x1F;
+ if (Size == 0)
+ Size = 32;
+
+ for (i=0; i<Size; i++)
+ HAMT_delete_trie(&(GetSubTrie(node))[i]);
+ yasm_xfree(GetSubTrie(node));
+ }
+}
+
+void
+HAMT_destroy(HAMT *hamt, void (*deletefunc) (/*@only@*/ void *data))
+{
+ int i;
+
+ /* delete entries */
+ while (!STAILQ_EMPTY(&hamt->entries)) {
+ HAMTEntry *entry;
+ entry = STAILQ_FIRST(&hamt->entries);
+ STAILQ_REMOVE_HEAD(&hamt->entries, next);
+ deletefunc(entry->data);
+ yasm_xfree(entry);
+ }
+
+ /* delete trie */
+ for (i=0; i<32; i++)
+ HAMT_delete_trie(&hamt->root[i]);
+
+ yasm_xfree(hamt->root);
+ yasm_xfree(hamt);
+}
+
+int
+HAMT_traverse(HAMT *hamt, void *d,
+ int (*func) (/*@dependent@*/ /*@null@*/ void *node,
+ /*@null@*/ void *d))
+{
+ HAMTEntry *entry;
+ STAILQ_FOREACH(entry, &hamt->entries, next) {
+ int retval = func(entry->data, d);
+ if (retval != 0)
+ return retval;
+ }
+ return 0;
+}
+
+const HAMTEntry *
+HAMT_first(const HAMT *hamt)
+{
+ return STAILQ_FIRST(&hamt->entries);
+}
+
+const HAMTEntry *
+HAMT_next(const HAMTEntry *prev)
+{
+ return STAILQ_NEXT(prev, next);
+}
+
+void *
+HAMTEntry_get_data(const HAMTEntry *entry)
+{
+ return entry->data;
+}
+
+/*@-temptrans -kepttrans -mustfree@*/
+void *
+HAMT_insert(HAMT *hamt, const char *str, void *data, int *replace,
+ void (*deletefunc) (/*@only@*/ void *data))
+{
+ HAMTNode *node, *newnodes;
+ HAMTEntry *entry;
+ unsigned long key, keypart, Map;
+ int keypartbits = 0;
+ int level = 0;
+
+ key = hamt->HashKey(str);
+ keypart = key & 0x1F;
+ node = &hamt->root[keypart];
+
+ if (!node->BaseValue) {
+ node->BitMapKey = key;
+ entry = yasm_xmalloc(sizeof(HAMTEntry));
+ entry->str = str;
+ entry->data = data;
+ STAILQ_INSERT_TAIL(&hamt->entries, entry, next);
+ SetValue(hamt, node, entry);
+ if (IsSubTrie(node))
+ hamt->error_func(__FILE__, __LINE__,
+ N_("Data is seen as subtrie (misaligned?)"));
+ *replace = 1;
+ return data;
+ }
+
+ for (;;) {
+ if (!(IsSubTrie(node))) {
+ if (node->BitMapKey == key
+ && hamt->CmpKey(((HAMTEntry *)(node->BaseValue))->str,
+ str) == 0) {
+ /*@-branchstate@*/
+ if (*replace) {
+ deletefunc(((HAMTEntry *)(node->BaseValue))->data);
+ ((HAMTEntry *)(node->BaseValue))->str = str;
+ ((HAMTEntry *)(node->BaseValue))->data = data;
+ } else
+ deletefunc(data);
+ /*@=branchstate@*/
+ return ((HAMTEntry *)(node->BaseValue))->data;
+ } else {
+ unsigned long key2 = node->BitMapKey;
+ /* build tree downward until keys differ */
+ for (;;) {
+ unsigned long keypart2;
+
+ /* replace node with subtrie */
+ keypartbits += 5;
+ if (keypartbits > 30) {
+ /* Exceeded 32 bits: rehash */
+ key = hamt->ReHashKey(str, level);
+ key2 = hamt->ReHashKey(
+ ((HAMTEntry *)(node->BaseValue))->str, level);
+ keypartbits = 0;
+ }
+ keypart = (key >> keypartbits) & 0x1F;
+ keypart2 = (key2 >> keypartbits) & 0x1F;
+
+ if (keypart == keypart2) {
+ /* Still equal, build one-node subtrie and continue
+ * downward.
+ */
+ newnodes = yasm_xmalloc(sizeof(HAMTNode));
+ newnodes[0].BitMapKey = key2;
+ newnodes[0].BaseValue = node->BaseValue;
+ node->BitMapKey = 1<<keypart;
+ SetSubTrie(hamt, node, newnodes);
+ node = &newnodes[0];
+ level++;
+ } else {
+ /* partitioned: allocate two-node subtrie */
+ newnodes = yasm_xmalloc(2*sizeof(HAMTNode));
+
+ entry = yasm_xmalloc(sizeof(HAMTEntry));
+ entry->str = str;
+ entry->data = data;
+ STAILQ_INSERT_TAIL(&hamt->entries, entry, next);
+
+ /* Copy nodes into subtrie based on order */
+ if (keypart2 < keypart) {
+ newnodes[0].BitMapKey = key2;
+ newnodes[0].BaseValue = node->BaseValue;
+ newnodes[1].BitMapKey = key;
+ SetValue(hamt, &newnodes[1], entry);
+ } else {
+ newnodes[0].BitMapKey = key;
+ SetValue(hamt, &newnodes[0], entry);
+ newnodes[1].BitMapKey = key2;
+ newnodes[1].BaseValue = node->BaseValue;
+ }
+
+ /* Set bits in bitmap corresponding to keys */
+ node->BitMapKey = (1UL<<keypart) | (1UL<<keypart2);
+ SetSubTrie(hamt, node, newnodes);
+ *replace = 1;
+ return data;
+ }
+ }
+ }
+ }
+
+ /* Subtrie: look up in bitmap */
+ keypartbits += 5;
+ if (keypartbits > 30) {
+ /* Exceeded 32 bits of current key: rehash */
+ key = hamt->ReHashKey(str, level);
+ keypartbits = 0;
+ }
+ keypart = (key >> keypartbits) & 0x1F;
+ if (!(node->BitMapKey & (1<<keypart))) {
+ /* bit is 0 in bitmap -> add node to table */
+ unsigned long Size;
+
+ /* set bit to 1 */
+ node->BitMapKey |= 1<<keypart;
+
+ /* Count total number of bits in bitmap to determine new size */
+ BitCount(Size, node->BitMapKey);
+ Size &= 0x1F;
+ if (Size == 0)
+ Size = 32;
+ newnodes = yasm_xmalloc(Size*sizeof(HAMTNode));
+
+ /* Count bits below to find where to insert new node at */
+ BitCount(Map, node->BitMapKey & ~((~0UL)<<keypart));
+ Map &= 0x1F; /* Clamp to <32 */
+ /* Copy existing nodes leaving gap for new node */
+ memcpy(newnodes, GetSubTrie(node), Map*sizeof(HAMTNode));
+ memcpy(&newnodes[Map+1], &(GetSubTrie(node))[Map],
+ (Size-Map-1)*sizeof(HAMTNode));
+ /* Delete old subtrie */
+ yasm_xfree(GetSubTrie(node));
+ /* Set up new node */
+ newnodes[Map].BitMapKey = key;
+ entry = yasm_xmalloc(sizeof(HAMTEntry));
+ entry->str = str;
+ entry->data = data;
+ STAILQ_INSERT_TAIL(&hamt->entries, entry, next);
+ SetValue(hamt, &newnodes[Map], entry);
+ SetSubTrie(hamt, node, newnodes);
+
+ *replace = 1;
+ return data;
+ }
+
+ /* Count bits below */
+ BitCount(Map, node->BitMapKey & ~((~0UL)<<keypart));
+ Map &= 0x1F; /* Clamp to <32 */
+
+ /* Go down a level */
+ level++;
+ node = &(GetSubTrie(node))[Map];
+ }
+}
+/*@=temptrans =kepttrans =mustfree@*/
+
+void *
+HAMT_search(HAMT *hamt, const char *str)
+{
+ HAMTNode *node;
+ unsigned long key, keypart, Map;
+ int keypartbits = 0;
+ int level = 0;
+
+ key = hamt->HashKey(str);
+ keypart = key & 0x1F;
+ node = &hamt->root[keypart];
+
+ if (!node->BaseValue)
+ return NULL;
+
+ for (;;) {
+ if (!(IsSubTrie(node))) {
+ if (node->BitMapKey == key
+ && hamt->CmpKey(((HAMTEntry *)(node->BaseValue))->str,
+ str) == 0)
+ return ((HAMTEntry *)(node->BaseValue))->data;
+ else
+ return NULL;
+ }
+
+ /* Subtree: look up in bitmap */
+ keypartbits += 5;
+ if (keypartbits > 30) {
+ /* Exceeded 32 bits of current key: rehash */
+ key = hamt->ReHashKey(str, level);
+ keypartbits = 0;
+ }
+ keypart = (key >> keypartbits) & 0x1F;
+ if (!(node->BitMapKey & (1<<keypart)))
+ return NULL; /* bit is 0 in bitmap -> no match */
+
+ /* Count bits below */
+ BitCount(Map, node->BitMapKey & ~((~0UL)<<keypart));
+ Map &= 0x1F; /* Clamp to <32 */
+
+ /* Go down a level */
+ level++;
+ node = &(GetSubTrie(node))[Map];
+ }
+}
+
diff --git a/contrib/tools/yasm/libyasm/hamt.h b/contrib/tools/yasm/libyasm/hamt.h
new file mode 100644
index 0000000000..1ce9b77536
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/hamt.h
@@ -0,0 +1,123 @@
+/**
+ * \file libyasm/hamt.h
+ * \brief Hash Array Mapped Trie (HAMT) functions.
+ *
+ * \license
+ * Copyright (C) 2001-2007 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.
+ * \endlicense
+ */
+#ifndef YASM_HAMT_H
+#define YASM_HAMT_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Hash array mapped trie data structure (opaque type). */
+typedef struct HAMT HAMT;
+/** Hash array mapped trie entry (opaque type). */
+typedef struct HAMTEntry HAMTEntry;
+
+/** Create new, empty, HAMT. error_func() is called when an internal error is
+ * encountered--it should NOT return to the calling function.
+ * \param nocase nonzero if HAMT should be case-insensitive
+ * \param error_func function called on internal error
+ * \return New, empty, hash array mapped trie.
+ */
+YASM_LIB_DECL
+HAMT *HAMT_create(int nocase, /*@exits@*/ void (*error_func)
+ (const char *file, unsigned int line, const char *message));
+
+/** Delete HAMT and all data associated with it. Uses deletefunc() to delete
+ * each data item.
+ * \param hamt Hash array mapped trie
+ * \param deletefunc Data deletion function
+ */
+YASM_LIB_DECL
+void HAMT_destroy(/*@only@*/ HAMT *hamt,
+ void (*deletefunc) (/*@only@*/ void *data));
+
+/** Insert key into HAMT, associating it with data.
+ * If the key is not present in the HAMT, inserts it, sets *replace to 1, and
+ * returns the data passed in.
+ * If the key is already present and *replace is 0, deletes the data passed
+ * in using deletefunc() and returns the data currently associated with the
+ * key.
+ * If the key is already present and *replace is 1, deletes the data currently
+ * associated with the key using deletefunc() and replaces it with the data
+ * passed in.
+ * \param hamt Hash array mapped trie
+ * \param str Key
+ * \param data Data to associate with key
+ * \param replace See above description
+ * \param deletefunc Data deletion function if data is replaced
+ * \return Data now associated with key.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ void *HAMT_insert(HAMT *hamt, /*@dependent@*/ const char *str,
+ /*@only@*/ void *data, int *replace,
+ void (*deletefunc) (/*@only@*/ void *data));
+
+/** Search for the data associated with a key in the HAMT.
+ * \param hamt Hash array mapped trie
+ * \param str Key
+ * \return NULL if key/data not present in HAMT, otherwise associated data.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ void *HAMT_search(HAMT *hamt, const char *str);
+
+/** Traverse over all keys in HAMT, calling function on each data item.
+ * \param hamt Hash array mapped trie
+ * \param d Data to pass to each call to func.
+ * \param func Function to call
+ * \return Stops early (and returns func's return value) if func returns a
+ * nonzero value; otherwise 0.
+ */
+YASM_LIB_DECL
+int HAMT_traverse(HAMT *hamt, /*@null@*/ void *d,
+ int (*func) (/*@dependent@*/ /*@null@*/ void *node,
+ /*@null@*/ void *d));
+
+/** Get the first entry in a HAMT.
+ * \param hamt Hash array mapped trie
+ * \return First entry in HAMT, or NULL if HAMT is empty.
+ */
+YASM_LIB_DECL
+const HAMTEntry *HAMT_first(const HAMT *hamt);
+
+/** Get the next entry in a HAMT.
+ * \param prev Previous entry in HAMT
+ * \return Next entry in HAMT, or NULL if no more entries.
+ */
+YASM_LIB_DECL
+/*@null@*/ const HAMTEntry *HAMT_next(const HAMTEntry *prev);
+
+/** Get the corresponding data for a HAMT entry.
+ * \param entry HAMT entry (as returned by HAMT_first() and HAMT_next())
+ * \return Corresponding data item.
+ */
+YASM_LIB_DECL
+void *HAMTEntry_get_data(const HAMTEntry *entry);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/insn.c b/contrib/tools/yasm/libyasm/insn.c
new file mode 100644
index 0000000000..8f7a4c1978
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/insn.c
@@ -0,0 +1,295 @@
+/*
+ * Mnemonic instruction bytecode
+ *
+ * Copyright (C) 2005-2007 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 "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+
+#include "errwarn.h"
+#include "expr.h"
+#include "value.h"
+
+#include "bytecode.h"
+#include "insn.h"
+#include "arch.h"
+
+
+void
+yasm_ea_set_segreg(yasm_effaddr *ea, uintptr_t segreg)
+{
+ if (!ea)
+ return;
+
+ if (segreg != 0 && ea->segreg != 0)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("multiple segment overrides, using leftmost"));
+
+ ea->segreg = segreg;
+}
+
+yasm_insn_operand *
+yasm_operand_create_reg(uintptr_t reg)
+{
+ yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
+
+ retval->type = YASM_INSN__OPERAND_REG;
+ retval->data.reg = reg;
+ retval->seg = 0;
+ retval->targetmod = 0;
+ retval->size = 0;
+ retval->deref = 0;
+ retval->strict = 0;
+
+ return retval;
+}
+
+yasm_insn_operand *
+yasm_operand_create_segreg(uintptr_t segreg)
+{
+ yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
+
+ retval->type = YASM_INSN__OPERAND_SEGREG;
+ retval->data.reg = segreg;
+ retval->seg = 0;
+ retval->targetmod = 0;
+ retval->size = 0;
+ retval->deref = 0;
+ retval->strict = 0;
+
+ return retval;
+}
+
+yasm_insn_operand *
+yasm_operand_create_mem(/*@only@*/ yasm_effaddr *ea)
+{
+ yasm_insn_operand *retval = yasm_xmalloc(sizeof(yasm_insn_operand));
+
+ retval->type = YASM_INSN__OPERAND_MEMORY;
+ retval->data.ea = ea;
+ retval->seg = 0;
+ retval->targetmod = 0;
+ retval->size = 0;
+ retval->deref = 0;
+ retval->strict = 0;
+ retval->size = ea->data_len * 8;
+
+ return retval;
+}
+
+yasm_insn_operand *
+yasm_operand_create_imm(/*@only@*/ yasm_expr *val)
+{
+ yasm_insn_operand *retval;
+ const uintptr_t *reg;
+
+ reg = yasm_expr_get_reg(&val, 0);
+ if (reg) {
+ retval = yasm_operand_create_reg(*reg);
+ yasm_expr_destroy(val);
+ } else {
+ retval = yasm_xmalloc(sizeof(yasm_insn_operand));
+ retval->type = YASM_INSN__OPERAND_IMM;
+ retval->data.val = val;
+ retval->seg = 0;
+ retval->targetmod = 0;
+ retval->size = 0;
+ retval->deref = 0;
+ retval->strict = 0;
+ }
+
+ return retval;
+}
+
+yasm_insn_operand *
+yasm_insn_ops_append(yasm_insn *insn, yasm_insn_operand *op)
+{
+ if (op) {
+ insn->num_operands++;
+ STAILQ_INSERT_TAIL(&insn->operands, op, link);
+ return op;
+ }
+ return (yasm_insn_operand *)NULL;
+}
+
+void
+yasm_insn_add_prefix(yasm_insn *insn, uintptr_t prefix)
+{
+ insn->prefixes =
+ yasm_xrealloc(insn->prefixes,
+ (insn->num_prefixes+1)*sizeof(uintptr_t));
+ insn->prefixes[insn->num_prefixes] = prefix;
+ insn->num_prefixes++;
+}
+
+void
+yasm_insn_add_seg_prefix(yasm_insn *insn, uintptr_t segreg)
+{
+ insn->segregs =
+ yasm_xrealloc(insn->segregs, (insn->num_segregs+1)*sizeof(uintptr_t));
+ insn->segregs[insn->num_segregs] = segreg;
+ insn->num_segregs++;
+}
+
+void
+yasm_insn_initialize(yasm_insn *insn)
+{
+ STAILQ_INIT(&insn->operands);
+
+ insn->prefixes = NULL;
+ insn->segregs = NULL;
+
+ insn->num_operands = 0;
+ insn->num_prefixes = 0;
+ insn->num_segregs = 0;
+}
+
+void
+yasm_insn_delete(yasm_insn *insn,
+ void (*ea_destroy) (/*@only@*/ yasm_effaddr *))
+{
+ if (insn->num_operands > 0) {
+ yasm_insn_operand *cur, *next;
+
+ cur = STAILQ_FIRST(&insn->operands);
+ while (cur) {
+ next = STAILQ_NEXT(cur, link);
+ switch (cur->type) {
+ case YASM_INSN__OPERAND_MEMORY:
+ ea_destroy(cur->data.ea);
+ break;
+ case YASM_INSN__OPERAND_IMM:
+ yasm_expr_destroy(cur->data.val);
+ break;
+ default:
+ break;
+ }
+ yasm_xfree(cur);
+ cur = next;
+ }
+ }
+ if (insn->num_prefixes > 0)
+ yasm_xfree(insn->prefixes);
+ if (insn->num_segregs > 0)
+ yasm_xfree(insn->segregs);
+}
+
+void
+yasm_insn_print(const yasm_insn *insn, FILE *f, int indent_level)
+{
+ const yasm_insn_operand *op;
+
+ STAILQ_FOREACH (op, &insn->operands, link) {
+ switch (op->type) {
+ case YASM_INSN__OPERAND_REG:
+ fprintf(f, "%*sReg=", indent_level, "");
+ /*yasm_arch_reg_print(arch, op->data.reg, f);*/
+ fprintf(f, "\n");
+ break;
+ case YASM_INSN__OPERAND_SEGREG:
+ fprintf(f, "%*sSegReg=", indent_level, "");
+ /*yasm_arch_segreg_print(arch, op->data.reg, f);*/
+ fprintf(f, "\n");
+ break;
+ case YASM_INSN__OPERAND_MEMORY:
+ fprintf(f, "%*sMemory=\n", indent_level, "");
+ /*yasm_arch_ea_print(arch, op->data.ea, f, indent_level);*/
+ break;
+ case YASM_INSN__OPERAND_IMM:
+ fprintf(f, "%*sImm=", indent_level, "");
+ yasm_expr_print(op->data.val, f);
+ fprintf(f, "\n");
+ break;
+ }
+ fprintf(f, "%*sTargetMod=%lx\n", indent_level+1, "",
+ (unsigned long)op->targetmod);
+ fprintf(f, "%*sSize=%u\n", indent_level+1, "", op->size);
+ fprintf(f, "%*sDeref=%d, Strict=%d\n", indent_level+1, "",
+ (int)op->deref, (int)op->strict);
+ }
+}
+
+void
+yasm_insn_finalize(yasm_insn *insn)
+{
+ unsigned int i;
+ yasm_insn_operand *op;
+ yasm_error_class eclass;
+ char *str, *xrefstr;
+ unsigned long xrefline;
+
+ /* Simplify the operands' expressions first. */
+ for (i = 0, op = yasm_insn_ops_first(insn);
+ op && i<insn->num_operands; op = yasm_insn_op_next(op), i++) {
+ /* Check operand type */
+ switch (op->type) {
+ case YASM_INSN__OPERAND_MEMORY:
+ /* Don't get over-ambitious here; some archs' memory expr
+ * parser are sensitive to the presence of *1, etc, so don't
+ * simplify reg*1 identities.
+ */
+ if (op->data.ea)
+ op->data.ea->disp.abs =
+ yasm_expr__level_tree(op->data.ea->disp.abs, 1, 1, 0,
+ 0, NULL, NULL);
+ if (yasm_error_occurred()) {
+ /* Add a pointer to where it was used to the error */
+ yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr);
+ if (xrefstr) {
+ yasm_error_set_xref(xrefline, "%s", xrefstr);
+ yasm_xfree(xrefstr);
+ }
+ if (str) {
+ yasm_error_set(eclass, "%s in memory expression", str);
+ yasm_xfree(str);
+ }
+ return;
+ }
+ break;
+ case YASM_INSN__OPERAND_IMM:
+ op->data.val =
+ yasm_expr__level_tree(op->data.val, 1, 1, 1, 0, NULL,
+ NULL);
+ if (yasm_error_occurred()) {
+ /* Add a pointer to where it was used to the error */
+ yasm_error_fetch(&eclass, &str, &xrefline, &xrefstr);
+ if (xrefstr) {
+ yasm_error_set_xref(xrefline, "%s", xrefstr);
+ yasm_xfree(xrefstr);
+ }
+ if (str) {
+ yasm_error_set(eclass, "%s in immediate expression",
+ str);
+ yasm_xfree(str);
+ }
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/contrib/tools/yasm/libyasm/insn.h b/contrib/tools/yasm/libyasm/insn.h
new file mode 100644
index 0000000000..d2d175d039
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/insn.h
@@ -0,0 +1,269 @@
+/**
+ * \file libyasm/insn.h
+ * \brief YASM mnenomic instruction.
+ *
+ * \license
+ * Copyright (C) 2002-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_INSN_H
+#define YASM_INSN_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Base structure for an effective address. As with all base
+ * structures, must be present as the first element in any
+ * #yasm_arch implementation of an effective address.
+ */
+struct yasm_effaddr {
+ yasm_value disp; /**< address displacement */
+
+ /** Segment register override (0 if none). */
+ uintptr_t segreg;
+
+ /** 1 if length of disp must be >0. */
+ unsigned int need_nonzero_len:1;
+
+ /** 1 if a displacement should be present in the output. */
+ unsigned int need_disp:1;
+
+ /** 1 if reg*2 should not be split into reg+reg. (0 if not).
+ * This flag indicates (for architectures that support complex effective
+ * addresses such as x86) if various types of complex effective addresses
+ * can be split into different forms in order to minimize instruction
+ * length.
+ */
+ unsigned int nosplit:1;
+
+ /** 1 if effective address is /definitely/ an effective address.
+ * This is used in e.g. the GAS parser to differentiate
+ * between "expr" (which might or might not be an effective address) and
+ * "expr(,1)" (which is definitely an effective address).
+ */
+ unsigned int strong:1;
+
+ /** 1 if effective address is forced PC-relative. */
+ unsigned int pc_rel:1;
+
+ /** 1 if effective address is forced non-PC-relative. */
+ unsigned int not_pc_rel:1;
+
+ /** length of pointed data (in bytes), 0 if unknown. */
+ unsigned int data_len;
+};
+
+/** An instruction operand (opaque type). */
+typedef struct yasm_insn_operand yasm_insn_operand;
+
+/** The type of an instruction operand. */
+typedef enum yasm_insn_operand_type {
+ YASM_INSN__OPERAND_REG = 1, /**< A register. */
+ YASM_INSN__OPERAND_SEGREG, /**< A segment register. */
+ YASM_INSN__OPERAND_MEMORY, /**< An effective address
+ * (memory reference). */
+ YASM_INSN__OPERAND_IMM /**< An immediate or jump target. */
+} yasm_insn_operand_type;
+
+/** An instruction operand. */
+struct yasm_insn_operand {
+ /** Link for building linked list of operands. \internal */
+ /*@reldef@*/ STAILQ_ENTRY(yasm_insn_operand) link;
+
+ /** Operand data. */
+ union {
+ uintptr_t reg; /**< Arch data for reg/segreg. */
+ yasm_effaddr *ea; /**< Effective address for memory references. */
+ yasm_expr *val; /**< Value of immediate or jump target. */
+ } data;
+
+ yasm_expr *seg; /**< Segment expression */
+
+ uintptr_t targetmod; /**< Arch target modifier, 0 if none. */
+
+ /** Specified size of the operand, in bits. 0 if not user-specified. */
+ unsigned int size:16;
+
+ /** Nonzero if dereference. Used for "*foo" in GAS.
+ * The reason for this is that by default in GAS, an unprefixed value
+ * is a memory address, except for jumps/calls, in which case it needs a
+ * "*" prefix to become a memory address (otherwise it's an immediate).
+ * This isn't knowable in the parser stage, so the parser sets this flag
+ * to indicate the "*" prefix has been used, and the arch needs to adjust
+ * the operand type appropriately depending on the instruction type.
+ */
+ unsigned int deref:1;
+
+ /** Nonzero if strict. Used for "strict foo" in NASM.
+ * This is used to inhibit optimization on otherwise "sized" values.
+ * For example, the user may just want to be explicit with the size on
+ * "push dword 4", but not actually want to force the immediate size to
+ * 4 bytes (rather wanting the optimizer to optimize it down to 1 byte as
+ * though "dword" was not specified). To indicate the immediate should
+ * actually be forced to 4 bytes, the user needs to write
+ * "push strict dword 4", which sets this flag.
+ */
+ unsigned int strict:1;
+
+ /** Operand type. */
+ unsigned int type:4;
+};
+
+/** Base structure for "instruction" bytecodes. These are the mnenomic
+ * (rather than raw) representation of instructions. As with all base
+ * structures, must be present as the first element in any
+ * #yasm_arch implementation of mnenomic instruction bytecodes.
+ */
+struct yasm_insn {
+ /** Linked list of operands. */
+ /*@reldef@*/ STAILQ_HEAD(yasm_insn_operands, yasm_insn_operand) operands;
+
+ /** Array of prefixes. */
+ /*@null@*/ uintptr_t *prefixes;
+
+ /** Array of segment prefixes. */
+ /*@null@*/ uintptr_t *segregs;
+
+ unsigned int num_operands; /**< Number of operands. */
+ unsigned int num_prefixes; /**< Number of prefixes. */
+ unsigned int num_segregs; /**< Number of segment prefixes. */
+};
+
+/** Set segment override for an effective address.
+ * Some architectures (such as x86) support segment overrides on effective
+ * addresses. A override of an override will result in a warning.
+ * \param ea effective address
+ * \param segreg segment register (0 if none)
+ */
+YASM_LIB_DECL
+void yasm_ea_set_segreg(yasm_effaddr *ea, uintptr_t segreg);
+
+/** Create an instruction operand from a register.
+ * \param reg register
+ * \return Newly allocated operand.
+ */
+YASM_LIB_DECL
+yasm_insn_operand *yasm_operand_create_reg(uintptr_t reg);
+
+/** Create an instruction operand from a segment register.
+ * \param segreg segment register
+ * \return Newly allocated operand.
+ */
+YASM_LIB_DECL
+yasm_insn_operand *yasm_operand_create_segreg(uintptr_t segreg);
+
+/** Create an instruction operand from an effective address.
+ * \param ea effective address
+ * \return Newly allocated operand.
+ */
+YASM_LIB_DECL
+yasm_insn_operand *yasm_operand_create_mem(/*@only@*/ yasm_effaddr *ea);
+
+/** Create an instruction operand from an immediate expression.
+ * Looks for cases of a single register and creates a register variant of
+ * #yasm_insn_operand.
+ * \param val immediate expression
+ * \return Newly allocated operand.
+ */
+YASM_LIB_DECL
+yasm_insn_operand *yasm_operand_create_imm(/*@only@*/ yasm_expr *val);
+
+/** Get the first operand in an instruction.
+ * \param insn instruction
+ * \return First operand (NULL if no operands).
+ */
+yasm_insn_operand *yasm_insn_ops_first(yasm_insn *insn);
+#define yasm_insn_ops_first(insn) STAILQ_FIRST(&((insn)->operands))
+
+/** Get the next operand in an instruction.
+ * \param op previous operand
+ * \return Next operand (NULL if op was the last operand).
+ */
+yasm_insn_operand *yasm_insn_op_next(yasm_insn_operand *op);
+#define yasm_insn_op_next(cur) STAILQ_NEXT(cur, link)
+
+/** Add operand to the end of an instruction.
+ * \note Does not make a copy of the operand; so don't pass this function
+ * static or local variables, and discard the op pointer after calling
+ * this function.
+ * \param insn instruction
+ * \param op operand (may be NULL)
+ * \return If operand was actually appended (it wasn't NULL), the operand;
+ * otherwise NULL.
+ */
+YASM_LIB_DECL
+/*@null@*/ yasm_insn_operand *yasm_insn_ops_append
+ (yasm_insn *insn,
+ /*@returned@*/ /*@null@*/ yasm_insn_operand *op);
+
+/** Associate a prefix with an instruction.
+ * \param insn instruction
+ * \param prefix data that identifies the prefix
+ */
+YASM_LIB_DECL
+void yasm_insn_add_prefix(yasm_insn *insn, uintptr_t prefix);
+
+/** Associate a segment prefix with an instruction.
+ * \param insn instruction
+ * \param segreg data that identifies the segment register
+ */
+YASM_LIB_DECL
+void yasm_insn_add_seg_prefix(yasm_insn *insn, uintptr_t segreg);
+
+/** Initialize the common parts of an instruction.
+ * \internal For use by yasm_arch implementations only.
+ * \param insn instruction
+ */
+YASM_LIB_DECL
+void yasm_insn_initialize(/*@out@*/ yasm_insn *insn);
+
+/** Delete the common parts of an instruction.
+ * \internal For use by yasm_arch implementations only.
+ * \param insn instruction
+ * \param content if nonzero, deletes content of each operand
+ * \param arch architecture
+ */
+YASM_LIB_DECL
+void yasm_insn_delete(yasm_insn *insn,
+ void (*ea_destroy) (/*@only@*/ yasm_effaddr *));
+
+/** Print a list of instruction operands. For debugging purposes.
+ * \internal For use by yasm_arch implementations only.
+ * \param insn instruction
+ * \param f file
+ * \param indent_level indentation level
+ * \param arch architecture
+ */
+YASM_LIB_DECL
+void yasm_insn_print(const yasm_insn *insn, FILE *f, int indent_level);
+
+/** Finalize the common parts of an instruction.
+ * \internal For use by yasm_arch implementations only.
+ * \param insn instruction
+ */
+YASM_LIB_DECL
+void yasm_insn_finalize(yasm_insn *insn);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/intnum.c b/contrib/tools/yasm/libyasm/intnum.c
new file mode 100644
index 0000000000..6feba33481
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/intnum.c
@@ -0,0 +1,1096 @@
+/*
+ * Integer number functions.
+ *
+ * Copyright (C) 2001-2007 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 "util.h"
+
+#include <ctype.h>
+#include <limits.h>
+
+#include "coretype.h"
+#include "bitvect.h"
+#include "file.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+
+
+/* "Native" "word" size for intnum calculations. */
+#define BITVECT_NATIVE_SIZE 256
+
+struct yasm_intnum {
+ union val {
+ long l; /* integer value (for integers <32 bits) */
+ wordptr bv; /* bit vector (for integers >=32 bits) */
+ } val;
+ enum { INTNUM_L, INTNUM_BV } type;
+};
+
+/* static bitvect used for conversions */
+static /*@only@*/ wordptr conv_bv;
+
+/* static bitvects used for computation */
+static /*@only@*/ wordptr result, spare, op1static, op2static;
+
+static /*@only@*/ BitVector_from_Dec_static_data *from_dec_data;
+
+
+void
+yasm_intnum_initialize(void)
+{
+ conv_bv = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
+ result = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
+ spare = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
+ op1static = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
+ op2static = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
+ from_dec_data = BitVector_from_Dec_static_Boot(BITVECT_NATIVE_SIZE);
+}
+
+void
+yasm_intnum_cleanup(void)
+{
+ BitVector_from_Dec_static_Shutdown(from_dec_data);
+ BitVector_Destroy(op2static);
+ BitVector_Destroy(op1static);
+ BitVector_Destroy(spare);
+ BitVector_Destroy(result);
+ BitVector_Destroy(conv_bv);
+}
+
+/* Compress a bitvector into intnum storage.
+ * If saved as a bitvector, clones the passed bitvector.
+ * Can modify the passed bitvector.
+ */
+static void
+intnum_frombv(/*@out@*/ yasm_intnum *intn, wordptr bv)
+{
+ if (Set_Max(bv) < 31) {
+ intn->type = INTNUM_L;
+ intn->val.l = (long)BitVector_Chunk_Read(bv, 31, 0);
+ } else if (BitVector_msb_(bv)) {
+ /* Negative, negate and see if we'll fit into a long. */
+ unsigned long ul;
+ BitVector_Negate(bv, bv);
+ if (Set_Max(bv) >= 32 ||
+ ((ul = BitVector_Chunk_Read(bv, 32, 0)) & 0x80000000)) {
+ /* too negative */
+ BitVector_Negate(bv, bv);
+ intn->type = INTNUM_BV;
+ intn->val.bv = BitVector_Clone(bv);
+ } else {
+ intn->type = INTNUM_L;
+ intn->val.l = -((long)ul);
+ }
+ } else {
+ intn->type = INTNUM_BV;
+ intn->val.bv = BitVector_Clone(bv);
+ }
+}
+
+/* If intnum is a BV, returns its bitvector directly.
+ * If not, converts into passed bv and returns that instead.
+ */
+static wordptr
+intnum_tobv(/*@returned@*/ wordptr bv, const yasm_intnum *intn)
+{
+ if (intn->type == INTNUM_BV)
+ return intn->val.bv;
+
+ BitVector_Empty(bv);
+ if (intn->val.l >= 0)
+ BitVector_Chunk_Store(bv, 32, 0, (unsigned long)intn->val.l);
+ else {
+ BitVector_Chunk_Store(bv, 32, 0, (unsigned long)-intn->val.l);
+ BitVector_Negate(bv, bv);
+ }
+ return bv;
+}
+
+yasm_intnum *
+yasm_intnum_create_dec(char *str)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+
+ switch (BitVector_from_Dec_static(from_dec_data, conv_bv,
+ (unsigned char *)str)) {
+ case ErrCode_Pars:
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid decimal literal"));
+ break;
+ case ErrCode_Ovfl:
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Numeric constant too large for internal format"));
+ break;
+ default:
+ break;
+ }
+ intnum_frombv(intn, conv_bv);
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_bin(char *str)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+
+ switch (BitVector_from_Bin(conv_bv, (unsigned char *)str)) {
+ case ErrCode_Pars:
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid binary literal"));
+ break;
+ case ErrCode_Ovfl:
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Numeric constant too large for internal format"));
+ break;
+ default:
+ break;
+ }
+ intnum_frombv(intn, conv_bv);
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_oct(char *str)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+
+ switch (BitVector_from_Oct(conv_bv, (unsigned char *)str)) {
+ case ErrCode_Pars:
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid octal literal"));
+ break;
+ case ErrCode_Ovfl:
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Numeric constant too large for internal format"));
+ break;
+ default:
+ break;
+ }
+ intnum_frombv(intn, conv_bv);
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_hex(char *str)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+
+ switch (BitVector_from_Hex(conv_bv, (unsigned char *)str)) {
+ case ErrCode_Pars:
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid hex literal"));
+ break;
+ case ErrCode_Ovfl:
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Numeric constant too large for internal format"));
+ break;
+ default:
+ break;
+ }
+ intnum_frombv(intn, conv_bv);
+ return intn;
+}
+
+/*@-usedef -compdef -uniondef@*/
+yasm_intnum *
+yasm_intnum_create_charconst_nasm(const char *str)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+ size_t len = strlen(str);
+
+ if(len*8 > BITVECT_NATIVE_SIZE)
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Character constant too large for internal format"));
+
+ /* be conservative in choosing bitvect in case MSB is set */
+ if (len > 3) {
+ BitVector_Empty(conv_bv);
+ intn->type = INTNUM_BV;
+ } else {
+ intn->val.l = 0;
+ intn->type = INTNUM_L;
+ }
+
+ switch (len) {
+ case 3:
+ intn->val.l |= ((unsigned long)str[2]) & 0xff;
+ intn->val.l <<= 8;
+ /*@fallthrough@*/
+ case 2:
+ intn->val.l |= ((unsigned long)str[1]) & 0xff;
+ intn->val.l <<= 8;
+ /*@fallthrough@*/
+ case 1:
+ intn->val.l |= ((unsigned long)str[0]) & 0xff;
+ case 0:
+ break;
+ default:
+ /* >=32 bit conversion */
+ while (len) {
+ BitVector_Move_Left(conv_bv, 8);
+ BitVector_Chunk_Store(conv_bv, 8, 0,
+ ((unsigned long)str[--len]) & 0xff);
+ }
+ intn->val.bv = BitVector_Clone(conv_bv);
+ }
+
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_charconst_tasm(const char *str)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+ size_t len = strlen(str);
+ size_t i;
+
+ if(len*8 > BITVECT_NATIVE_SIZE)
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Character constant too large for internal format"));
+
+ /* be conservative in choosing bitvect in case MSB is set */
+ if (len > 3) {
+ BitVector_Empty(conv_bv);
+ intn->type = INTNUM_BV;
+ } else {
+ intn->val.l = 0;
+ intn->type = INTNUM_L;
+ }
+
+ /* tasm uses big endian notation */
+ i = 0;
+ switch (len) {
+ case 3:
+ intn->val.l |= ((unsigned long)str[i++]) & 0xff;
+ intn->val.l <<= 8;
+ /*@fallthrough@*/
+ case 2:
+ intn->val.l |= ((unsigned long)str[i++]) & 0xff;
+ intn->val.l <<= 8;
+ /*@fallthrough@*/
+ case 1:
+ intn->val.l |= ((unsigned long)str[i++]) & 0xff;
+ case 0:
+ break;
+ default:
+ /* >=32 bit conversion */
+ while (i < len) {
+ BitVector_Chunk_Store(conv_bv, 8, (len-i-1)*8,
+ ((unsigned long)str[i]) & 0xff);
+ i++;
+ }
+ intn->val.bv = BitVector_Clone(conv_bv);
+ }
+
+ return intn;
+}
+/*@=usedef =compdef =uniondef@*/
+
+yasm_intnum *
+yasm_intnum_create_uint(unsigned long i)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+
+ if (i > LONG_MAX) {
+ /* Too big, store as bitvector */
+ intn->val.bv = BitVector_Create(BITVECT_NATIVE_SIZE, TRUE);
+ intn->type = INTNUM_BV;
+ BitVector_Chunk_Store(intn->val.bv, 32, 0, i);
+ } else {
+ intn->val.l = (long)i;
+ intn->type = INTNUM_L;
+ }
+
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_int(long i)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+
+ intn->val.l = i;
+ intn->type = INTNUM_L;
+
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_leb128(const unsigned char *ptr, int sign,
+ unsigned long *size)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+ const unsigned char *ptr_orig = ptr;
+ unsigned long i = 0;
+
+ BitVector_Empty(conv_bv);
+ for (;;) {
+ BitVector_Chunk_Store(conv_bv, 7, i, *ptr);
+ i += 7;
+ if ((*ptr & 0x80) != 0x80)
+ break;
+ ptr++;
+ }
+
+ *size = (unsigned long)(ptr-ptr_orig)+1;
+
+ if(i > BITVECT_NATIVE_SIZE)
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Numeric constant too large for internal format"));
+ else if (sign && (*ptr & 0x40) == 0x40)
+ BitVector_Interval_Fill(conv_bv, i, BITVECT_NATIVE_SIZE-1);
+
+ intnum_frombv(intn, conv_bv);
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_create_sized(unsigned char *ptr, int sign, size_t srcsize,
+ int bigendian)
+{
+ yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
+ unsigned long i = 0;
+
+ if (srcsize*8 > BITVECT_NATIVE_SIZE)
+ yasm_error_set(YASM_ERROR_OVERFLOW,
+ N_("Numeric constant too large for internal format"));
+
+ /* Read the buffer into a bitvect */
+ BitVector_Empty(conv_bv);
+ if (bigendian) {
+ /* TODO */
+ yasm_internal_error(N_("big endian not implemented"));
+ } else {
+ for (i = 0; i < srcsize; i++)
+ BitVector_Chunk_Store(conv_bv, 8, i*8, ptr[i]);
+ }
+
+ /* Sign extend if needed */
+ if (srcsize*8 < BITVECT_NATIVE_SIZE && sign && (ptr[i-1] & 0x80) == 0x80)
+ BitVector_Interval_Fill(conv_bv, i*8, BITVECT_NATIVE_SIZE-1);
+
+ intnum_frombv(intn, conv_bv);
+ return intn;
+}
+
+yasm_intnum *
+yasm_intnum_copy(const yasm_intnum *intn)
+{
+ yasm_intnum *n = yasm_xmalloc(sizeof(yasm_intnum));
+
+ switch (intn->type) {
+ case INTNUM_L:
+ n->val.l = intn->val.l;
+ break;
+ case INTNUM_BV:
+ n->val.bv = BitVector_Clone(intn->val.bv);
+ break;
+ }
+ n->type = intn->type;
+
+ return n;
+}
+
+void
+yasm_intnum_destroy(yasm_intnum *intn)
+{
+ if (intn->type == INTNUM_BV)
+ BitVector_Destroy(intn->val.bv);
+ yasm_xfree(intn);
+}
+
+/*@-nullderef -nullpass -branchstate@*/
+int
+yasm_intnum_calc(yasm_intnum *acc, yasm_expr_op op, yasm_intnum *operand)
+{
+ boolean carry = 0;
+ wordptr op1, op2 = NULL;
+ N_int count;
+
+ /* Always do computations with in full bit vector.
+ * Bit vector results must be calculated through intermediate storage.
+ */
+ op1 = intnum_tobv(op1static, acc);
+ if (operand)
+ op2 = intnum_tobv(op2static, operand);
+
+ if (!operand && op != YASM_EXPR_NEG && op != YASM_EXPR_NOT &&
+ op != YASM_EXPR_LNOT) {
+ yasm_error_set(YASM_ERROR_ARITHMETIC,
+ N_("operation needs an operand"));
+ BitVector_Empty(result);
+ return 1;
+ }
+
+ /* A operation does a bitvector computation if result is allocated. */
+ switch (op) {
+ case YASM_EXPR_ADD:
+ BitVector_add(result, op1, op2, &carry);
+ break;
+ case YASM_EXPR_SUB:
+ BitVector_sub(result, op1, op2, &carry);
+ break;
+ case YASM_EXPR_MUL:
+ BitVector_Multiply(result, op1, op2);
+ break;
+ case YASM_EXPR_DIV:
+ /* TODO: make sure op1 and op2 are unsigned */
+ if (BitVector_is_empty(op2)) {
+ yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
+ BitVector_Empty(result);
+ return 1;
+ } else
+ BitVector_Divide(result, op1, op2, spare);
+ break;
+ case YASM_EXPR_SIGNDIV:
+ if (BitVector_is_empty(op2)) {
+ yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
+ BitVector_Empty(result);
+ return 1;
+ } else
+ BitVector_Divide(result, op1, op2, spare);
+ break;
+ case YASM_EXPR_MOD:
+ /* TODO: make sure op1 and op2 are unsigned */
+ if (BitVector_is_empty(op2)) {
+ yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
+ BitVector_Empty(result);
+ return 1;
+ } else
+ BitVector_Divide(spare, op1, op2, result);
+ break;
+ case YASM_EXPR_SIGNMOD:
+ if (BitVector_is_empty(op2)) {
+ yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
+ BitVector_Empty(result);
+ return 1;
+ } else
+ BitVector_Divide(spare, op1, op2, result);
+ break;
+ case YASM_EXPR_NEG:
+ BitVector_Negate(result, op1);
+ break;
+ case YASM_EXPR_NOT:
+ Set_Complement(result, op1);
+ break;
+ case YASM_EXPR_OR:
+ Set_Union(result, op1, op2);
+ break;
+ case YASM_EXPR_AND:
+ Set_Intersection(result, op1, op2);
+ break;
+ case YASM_EXPR_XOR:
+ Set_ExclusiveOr(result, op1, op2);
+ break;
+ case YASM_EXPR_XNOR:
+ Set_ExclusiveOr(result, op1, op2);
+ Set_Complement(result, result);
+ break;
+ case YASM_EXPR_NOR:
+ Set_Union(result, op1, op2);
+ Set_Complement(result, result);
+ break;
+ case YASM_EXPR_SHL:
+ if (operand->type == INTNUM_L && operand->val.l >= 0) {
+ BitVector_Copy(result, op1);
+ BitVector_Move_Left(result, (N_int)operand->val.l);
+ } else /* don't even bother, just zero result */
+ BitVector_Empty(result);
+ break;
+ case YASM_EXPR_SHR:
+ if (operand->type == INTNUM_L && operand->val.l >= 0) {
+ BitVector_Copy(result, op1);
+ carry = BitVector_msb_(op1);
+ count = (N_int)operand->val.l;
+ while (count-- > 0)
+ BitVector_shift_right(result, carry);
+ } else /* don't even bother, just zero result */
+ BitVector_Empty(result);
+ break;
+ case YASM_EXPR_LOR:
+ BitVector_Empty(result);
+ BitVector_LSB(result, !BitVector_is_empty(op1) ||
+ !BitVector_is_empty(op2));
+ break;
+ case YASM_EXPR_LAND:
+ BitVector_Empty(result);
+ BitVector_LSB(result, !BitVector_is_empty(op1) &&
+ !BitVector_is_empty(op2));
+ break;
+ case YASM_EXPR_LNOT:
+ BitVector_Empty(result);
+ BitVector_LSB(result, BitVector_is_empty(op1));
+ break;
+ case YASM_EXPR_LXOR:
+ BitVector_Empty(result);
+ BitVector_LSB(result, !BitVector_is_empty(op1) ^
+ !BitVector_is_empty(op2));
+ break;
+ case YASM_EXPR_LXNOR:
+ BitVector_Empty(result);
+ BitVector_LSB(result, !(!BitVector_is_empty(op1) ^
+ !BitVector_is_empty(op2)));
+ break;
+ case YASM_EXPR_LNOR:
+ BitVector_Empty(result);
+ BitVector_LSB(result, !(!BitVector_is_empty(op1) ||
+ !BitVector_is_empty(op2)));
+ break;
+ case YASM_EXPR_EQ:
+ BitVector_Empty(result);
+ BitVector_LSB(result, BitVector_equal(op1, op2));
+ break;
+ case YASM_EXPR_LT:
+ BitVector_Empty(result);
+ BitVector_LSB(result, BitVector_Compare(op1, op2) < 0);
+ break;
+ case YASM_EXPR_GT:
+ BitVector_Empty(result);
+ BitVector_LSB(result, BitVector_Compare(op1, op2) > 0);
+ break;
+ case YASM_EXPR_LE:
+ BitVector_Empty(result);
+ BitVector_LSB(result, BitVector_Compare(op1, op2) <= 0);
+ break;
+ case YASM_EXPR_GE:
+ BitVector_Empty(result);
+ BitVector_LSB(result, BitVector_Compare(op1, op2) >= 0);
+ break;
+ case YASM_EXPR_NE:
+ BitVector_Empty(result);
+ BitVector_LSB(result, !BitVector_equal(op1, op2));
+ break;
+ case YASM_EXPR_SEG:
+ yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
+ "SEG");
+ break;
+ case YASM_EXPR_WRT:
+ yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
+ "WRT");
+ break;
+ case YASM_EXPR_SEGOFF:
+ yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
+ ":");
+ break;
+ case YASM_EXPR_IDENT:
+ if (result)
+ BitVector_Copy(result, op1);
+ break;
+ default:
+ yasm_error_set(YASM_ERROR_ARITHMETIC,
+ N_("invalid operation in intnum calculation"));
+ BitVector_Empty(result);
+ return 1;
+ }
+
+ /* Try to fit the result into 32 bits if possible */
+ if (acc->type == INTNUM_BV)
+ BitVector_Destroy(acc->val.bv);
+ intnum_frombv(acc, result);
+ return 0;
+}
+/*@=nullderef =nullpass =branchstate@*/
+
+int
+yasm_intnum_compare(const yasm_intnum *intn1, const yasm_intnum *intn2)
+{
+ wordptr op1, op2;
+
+ if (intn1->type == INTNUM_L && intn2->type == INTNUM_L) {
+ if (intn1->val.l < intn2->val.l)
+ return -1;
+ if (intn1->val.l > intn2->val.l)
+ return 1;
+ return 0;
+ }
+
+ op1 = intnum_tobv(op1static, intn1);
+ op2 = intnum_tobv(op2static, intn2);
+ return BitVector_Compare(op1, op2);
+}
+
+void
+yasm_intnum_zero(yasm_intnum *intn)
+{
+ yasm_intnum_set_int(intn, 0);
+}
+
+void
+yasm_intnum_set(yasm_intnum *intn, const yasm_intnum *val)
+{
+ if (intn->type == val->type) {
+ switch (val->type) {
+ case INTNUM_L:
+ intn->val.l = val->val.l;
+ break;
+ case INTNUM_BV:
+ BitVector_Copy(intn->val.bv, val->val.bv);
+ break;
+ }
+ } else {
+ switch (val->type) {
+ case INTNUM_L:
+ BitVector_Destroy(intn->val.bv);
+ intn->val.l = val->val.l;
+ break;
+ case INTNUM_BV:
+ intn->val.bv = BitVector_Clone(val->val.bv);
+ break;
+ }
+ intn->type = val->type;
+ }
+}
+
+void
+yasm_intnum_set_uint(yasm_intnum *intn, unsigned long val)
+{
+ if (val > LONG_MAX) {
+ if (intn->type != INTNUM_BV) {
+ intn->val.bv = BitVector_Create(BITVECT_NATIVE_SIZE, TRUE);
+ intn->type = INTNUM_BV;
+ }
+ BitVector_Chunk_Store(intn->val.bv, 32, 0, val);
+ } else {
+ if (intn->type == INTNUM_BV) {
+ BitVector_Destroy(intn->val.bv);
+ intn->type = INTNUM_L;
+ }
+ intn->val.l = (long)val;
+ }
+}
+
+void
+yasm_intnum_set_int(yasm_intnum *intn, long val)
+{
+ if (intn->type == INTNUM_BV)
+ BitVector_Destroy(intn->val.bv);
+ intn->type = INTNUM_L;
+ intn->val.l = val;
+}
+
+int
+yasm_intnum_is_zero(const yasm_intnum *intn)
+{
+ return (intn->type == INTNUM_L && intn->val.l == 0);
+}
+
+int
+yasm_intnum_is_pos1(const yasm_intnum *intn)
+{
+ return (intn->type == INTNUM_L && intn->val.l == 1);
+}
+
+int
+yasm_intnum_is_neg1(const yasm_intnum *intn)
+{
+ return (intn->type == INTNUM_L && intn->val.l == -1);
+}
+
+int
+yasm_intnum_sign(const yasm_intnum *intn)
+{
+ if (intn->type == INTNUM_L) {
+ if (intn->val.l == 0)
+ return 0;
+ else if (intn->val.l < 0)
+ return -1;
+ else
+ return 1;
+ } else
+ return BitVector_Sign(intn->val.bv);
+}
+
+unsigned long
+yasm_intnum_get_uint(const yasm_intnum *intn)
+{
+ switch (intn->type) {
+ case INTNUM_L:
+ if (intn->val.l < 0)
+ return 0;
+ return (unsigned long)intn->val.l;
+ case INTNUM_BV:
+ if (BitVector_msb_(intn->val.bv))
+ return 0;
+ if (Set_Max(intn->val.bv) > 32)
+ return ULONG_MAX;
+ return BitVector_Chunk_Read(intn->val.bv, 32, 0);
+ default:
+ yasm_internal_error(N_("unknown intnum type"));
+ /*@notreached@*/
+ return 0;
+ }
+}
+
+long
+yasm_intnum_get_int(const yasm_intnum *intn)
+{
+ switch (intn->type) {
+ case INTNUM_L:
+ return intn->val.l;
+ case INTNUM_BV:
+ if (BitVector_msb_(intn->val.bv)) {
+ /* it's negative: negate the bitvector to get a positive
+ * number, then negate the positive number.
+ */
+ unsigned long ul;
+
+ BitVector_Negate(conv_bv, intn->val.bv);
+ if (Set_Max(conv_bv) >= 32) {
+ /* too negative */
+ return LONG_MIN;
+ }
+ ul = BitVector_Chunk_Read(conv_bv, 32, 0);
+ /* check for too negative */
+ return (ul & 0x80000000) ? LONG_MIN : -((long)ul);
+ }
+
+ /* it's positive, and since it's a BV, it must be >0x7FFFFFFF */
+ return LONG_MAX;
+ default:
+ yasm_internal_error(N_("unknown intnum type"));
+ /*@notreached@*/
+ return 0;
+ }
+}
+
+void
+yasm_intnum_get_sized(const yasm_intnum *intn, unsigned char *ptr,
+ size_t destsize, size_t valsize, int shift,
+ int bigendian, int warn)
+{
+ wordptr op1 = op1static, op2;
+ unsigned char *buf;
+ unsigned int len;
+ size_t rshift = shift < 0 ? (size_t)(-shift) : 0;
+ int carry_in;
+
+ /* Currently don't support destinations larger than our native size */
+ if (destsize*8 > BITVECT_NATIVE_SIZE)
+ yasm_internal_error(N_("destination too large"));
+
+ /* General size warnings */
+ if (warn<0 && !yasm_intnum_check_size(intn, valsize, rshift, 1))
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("value does not fit in signed %d bit field"),
+ valsize);
+ if (warn>0 && !yasm_intnum_check_size(intn, valsize, rshift, 2))
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("value does not fit in %d bit field"), valsize);
+
+ /* Read the original data into a bitvect */
+ if (bigendian) {
+ /* TODO */
+ yasm_internal_error(N_("big endian not implemented"));
+ } else
+ BitVector_Block_Store(op1, ptr, (N_int)destsize);
+
+ /* If not already a bitvect, convert value to be written to a bitvect */
+ op2 = intnum_tobv(op2static, intn);
+
+ /* Check low bits if right shifting and warnings enabled */
+ if (warn && rshift > 0) {
+ BitVector_Copy(conv_bv, op2);
+ BitVector_Move_Left(conv_bv, (N_int)(BITVECT_NATIVE_SIZE-rshift));
+ if (!BitVector_is_empty(conv_bv))
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("misaligned value, truncating to boundary"));
+ }
+
+ /* Shift right if needed */
+ if (rshift > 0) {
+ carry_in = BitVector_msb_(op2);
+ while (rshift-- > 0)
+ BitVector_shift_right(op2, carry_in);
+ shift = 0;
+ }
+
+ /* Write the new value into the destination bitvect */
+ BitVector_Interval_Copy(op1, op2, (unsigned int)shift, 0, (N_int)valsize);
+
+ /* Write out the new data */
+ buf = BitVector_Block_Read(op1, &len);
+ if (bigendian) {
+ /* TODO */
+ yasm_internal_error(N_("big endian not implemented"));
+ } else
+ memcpy(ptr, buf, destsize);
+ yasm_xfree(buf);
+}
+
+/* Return 1 if okay size, 0 if not */
+int
+yasm_intnum_check_size(const yasm_intnum *intn, size_t size, size_t rshift,
+ int rangetype)
+{
+ wordptr val;
+
+ /* If not already a bitvect, convert value to a bitvect */
+ if (intn->type == INTNUM_BV) {
+ if (rshift > 0) {
+ val = conv_bv;
+ BitVector_Copy(val, intn->val.bv);
+ } else
+ val = intn->val.bv;
+ } else
+ val = intnum_tobv(conv_bv, intn);
+
+ if (size >= BITVECT_NATIVE_SIZE)
+ return 1;
+
+ if (rshift > 0) {
+ int carry_in = BitVector_msb_(val);
+ while (rshift-- > 0)
+ BitVector_shift_right(val, carry_in);
+ }
+
+ if (rangetype > 0) {
+ if (BitVector_msb_(val)) {
+ /* it's negative */
+ int retval;
+
+ BitVector_Negate(conv_bv, val);
+ BitVector_dec(conv_bv, conv_bv);
+ retval = Set_Max(conv_bv) < (long)size-1;
+
+ return retval;
+ }
+
+ if (rangetype == 1)
+ size--;
+ }
+ return (Set_Max(val) < (long)size);
+}
+
+int
+yasm_intnum_in_range(const yasm_intnum *intn, long low, long high)
+{
+ wordptr val = intnum_tobv(result, intn);
+ wordptr lval = op1static;
+ wordptr hval = op2static;
+
+ /* Convert high and low to bitvects */
+ BitVector_Empty(lval);
+ if (low >= 0)
+ BitVector_Chunk_Store(lval, 32, 0, (unsigned long)low);
+ else {
+ BitVector_Chunk_Store(lval, 32, 0, (unsigned long)(-low));
+ BitVector_Negate(lval, lval);
+ }
+
+ BitVector_Empty(hval);
+ if (high >= 0)
+ BitVector_Chunk_Store(hval, 32, 0, (unsigned long)high);
+ else {
+ BitVector_Chunk_Store(hval, 32, 0, (unsigned long)(-high));
+ BitVector_Negate(hval, hval);
+ }
+
+ /* Compare! */
+ return (BitVector_Compare(val, lval) >= 0
+ && BitVector_Compare(val, hval) <= 0);
+}
+
+static unsigned long
+get_leb128(wordptr val, unsigned char *ptr, int sign)
+{
+ unsigned long i, size;
+ unsigned char *ptr_orig = ptr;
+
+ if (sign) {
+ /* Signed mode */
+ if (BitVector_msb_(val)) {
+ /* Negative */
+ BitVector_Negate(conv_bv, val);
+ size = Set_Max(conv_bv)+2;
+ } else {
+ /* Positive */
+ size = Set_Max(val)+2;
+ }
+ } else {
+ /* Unsigned mode */
+ size = Set_Max(val)+1;
+ }
+
+ /* Positive/Unsigned write */
+ for (i=0; i<size; i += 7) {
+ *ptr = (unsigned char)BitVector_Chunk_Read(val, 7, i);
+ *ptr |= 0x80;
+ ptr++;
+ }
+ *(ptr-1) &= 0x7F; /* Clear MSB of last byte */
+ return (unsigned long)(ptr-ptr_orig);
+}
+
+static unsigned long
+size_leb128(wordptr val, int sign)
+{
+ if (sign) {
+ /* Signed mode */
+ if (BitVector_msb_(val)) {
+ /* Negative */
+ BitVector_Negate(conv_bv, val);
+ return (Set_Max(conv_bv)+8)/7;
+ } else {
+ /* Positive */
+ return (Set_Max(val)+8)/7;
+ }
+ } else {
+ /* Unsigned mode */
+ return (Set_Max(val)+7)/7;
+ }
+}
+
+unsigned long
+yasm_intnum_get_leb128(const yasm_intnum *intn, unsigned char *ptr, int sign)
+{
+ wordptr val;
+
+ /* Shortcut 0 */
+ if (intn->type == INTNUM_L && intn->val.l == 0) {
+ *ptr = 0;
+ return 1;
+ }
+
+ /* If not already a bitvect, convert value to be written to a bitvect */
+ val = intnum_tobv(op1static, intn);
+
+ return get_leb128(val, ptr, sign);
+}
+
+unsigned long
+yasm_intnum_size_leb128(const yasm_intnum *intn, int sign)
+{
+ wordptr val;
+
+ /* Shortcut 0 */
+ if (intn->type == INTNUM_L && intn->val.l == 0) {
+ return 1;
+ }
+
+ /* If not already a bitvect, convert value to a bitvect */
+ val = intnum_tobv(op1static, intn);
+
+ return size_leb128(val, sign);
+}
+
+unsigned long
+yasm_get_sleb128(long v, unsigned char *ptr)
+{
+ wordptr val = op1static;
+
+ /* Shortcut 0 */
+ if (v == 0) {
+ *ptr = 0;
+ return 1;
+ }
+
+ BitVector_Empty(val);
+ if (v >= 0)
+ BitVector_Chunk_Store(val, 32, 0, (unsigned long)v);
+ else {
+ BitVector_Chunk_Store(val, 32, 0, (unsigned long)(-v));
+ BitVector_Negate(val, val);
+ }
+ return get_leb128(val, ptr, 1);
+}
+
+unsigned long
+yasm_size_sleb128(long v)
+{
+ wordptr val = op1static;
+
+ if (v == 0)
+ return 1;
+
+ BitVector_Empty(val);
+ if (v >= 0)
+ BitVector_Chunk_Store(val, 32, 0, (unsigned long)v);
+ else {
+ BitVector_Chunk_Store(val, 32, 0, (unsigned long)(-v));
+ BitVector_Negate(val, val);
+ }
+ return size_leb128(val, 1);
+}
+
+unsigned long
+yasm_get_uleb128(unsigned long v, unsigned char *ptr)
+{
+ wordptr val = op1static;
+
+ /* Shortcut 0 */
+ if (v == 0) {
+ *ptr = 0;
+ return 1;
+ }
+
+ BitVector_Empty(val);
+ BitVector_Chunk_Store(val, 32, 0, v);
+ return get_leb128(val, ptr, 0);
+}
+
+unsigned long
+yasm_size_uleb128(unsigned long v)
+{
+ wordptr val = op1static;
+
+ if (v == 0)
+ return 1;
+
+ BitVector_Empty(val);
+ BitVector_Chunk_Store(val, 32, 0, v);
+ return size_leb128(val, 0);
+}
+
+char *
+yasm_intnum_get_str(const yasm_intnum *intn)
+{
+ unsigned char *s;
+
+ switch (intn->type) {
+ case INTNUM_L:
+ s = yasm_xmalloc(16);
+ sprintf((char *)s, "%ld", intn->val.l);
+ return (char *)s;
+ break;
+ case INTNUM_BV:
+ return (char *)BitVector_to_Dec(intn->val.bv);
+ break;
+ }
+ /*@notreached@*/
+ return NULL;
+}
+
+void
+yasm_intnum_print(const yasm_intnum *intn, FILE *f)
+{
+ unsigned char *s;
+
+ switch (intn->type) {
+ case INTNUM_L:
+ fprintf(f, "0x%lx", intn->val.l);
+ break;
+ case INTNUM_BV:
+ s = BitVector_to_Hex(intn->val.bv);
+ fprintf(f, "0x%s", (char *)s);
+ yasm_xfree(s);
+ break;
+ }
+}
diff --git a/contrib/tools/yasm/libyasm/intnum.h b/contrib/tools/yasm/libyasm/intnum.h
new file mode 100644
index 0000000000..bec832cf31
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/intnum.h
@@ -0,0 +1,340 @@
+/**
+ * \file libyasm/intnum.h
+ * \brief YASM integer number interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_INTNUM_H
+#define YASM_INTNUM_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Initialize intnum internal data structures. */
+YASM_LIB_DECL
+void yasm_intnum_initialize(void);
+
+/** Clean up internal intnum allocations. */
+YASM_LIB_DECL
+void yasm_intnum_cleanup(void);
+
+/** Create a new intnum from a decimal string.
+ * \param str decimal string
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_dec(char *str);
+
+/** Create a new intnum from a binary string.
+ * \param str binary string
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_bin(char *str);
+
+/** Create a new intnum from an octal string.
+ * \param str octal string
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_oct(char *str);
+
+/** Create a new intnum from a hexidecimal string.
+ * \param str hexidecimal string
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_hex(char *str);
+
+/** Convert character constant to integer value, using NASM rules. NASM syntax
+ * supports automatic conversion from strings such as 'abcd' to a 32-bit
+ * integer value (little endian order). This function performs those conversions.
+ * \param str character constant string
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_charconst_nasm(const char *str);
+
+/** Convert character constant to integer value, using TASM rules. TASM syntax
+ * supports automatic conversion from strings such as 'abcd' to a 32-bit
+ * integer value (big endian order). This function performs those conversions.
+ * \param str character constant string
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_charconst_tasm(const char *str);
+
+/** Create a new intnum from an unsigned integer value.
+ * \param i unsigned integer value
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_uint(unsigned long i);
+
+/** Create a new intnum from an signed integer value.
+ * \param i signed integer value
+ * \return Newly allocated intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_int(long i);
+
+/** Create a new intnum from LEB128-encoded form.
+ * \param ptr pointer to start of LEB128 encoded form
+ * \param sign signed (1) or unsigned (0) LEB128 format
+ * \param size number of bytes read from ptr (output)
+ * \return Newly allocated intnum. Number of bytes read returned into
+ * bytes_read parameter.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_leb128
+ (const unsigned char *ptr, int sign, /*@out@*/ unsigned long *size);
+
+/** Create a new intnum from a little-endian or big-endian buffer.
+ * In little endian, the LSB is in ptr[0].
+ * \param ptr pointer to start of buffer
+ * \param sign signed (1) or unsigned (0) source
+ * \param srcsize source buffer size (in bytes)
+ * \param bigendian endianness (nonzero=big, zero=little)
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_create_sized
+ (unsigned char *ptr, int sign, size_t srcsize, int bigendian);
+
+/** Duplicate an intnum.
+ * \param intn intnum
+ * \return Newly allocated intnum with the same value as intn.
+ */
+YASM_LIB_DECL
+/*@only@*/ yasm_intnum *yasm_intnum_copy(const yasm_intnum *intn);
+
+/** Destroy (free allocated memory for) an intnum.
+ * \param intn intnum
+ */
+YASM_LIB_DECL
+void yasm_intnum_destroy(/*@only@*/ yasm_intnum *intn);
+
+/** Floating point calculation function: acc = acc op operand.
+ * \note Not all operations in yasm_expr_op may be supported; unsupported
+ * operations will result in an error.
+ * \param acc intnum accumulator
+ * \param op operation
+ * \param operand intnum operand
+ * \return Nonzero if error occurred.
+ */
+YASM_LIB_DECL
+int yasm_intnum_calc(yasm_intnum *acc, yasm_expr_op op, yasm_intnum *operand);
+
+/** Compare two intnums.
+ * \param intn1 first intnum
+ * \param intn2 second intnum
+ * \return -1 if intn1 < intn2, 0 if intn1 == intn2, 1 if intn1 > intn2.
+ */
+YASM_LIB_DECL
+int yasm_intnum_compare(const yasm_intnum *intn1, const yasm_intnum *intn2);
+
+/** Zero an intnum.
+ * \param intn intnum
+ */
+YASM_LIB_DECL
+void yasm_intnum_zero(yasm_intnum *intn);
+
+/** Set an intnum to the value of another intnum.
+ * \param intn intnum
+ * \param val intnum to get value from
+ */
+YASM_LIB_DECL
+void yasm_intnum_set(yasm_intnum *intn, const yasm_intnum *val);
+
+/** Set an intnum to an unsigned integer.
+ * \param intn intnum
+ * \param val integer value
+ */
+YASM_LIB_DECL
+void yasm_intnum_set_uint(yasm_intnum *intn, unsigned long val);
+
+/** Set an intnum to an signed integer.
+ * \param intn intnum
+ * \param val integer value
+ */
+YASM_LIB_DECL
+void yasm_intnum_set_int(yasm_intnum *intn, long val);
+
+/** Simple value check for 0.
+ * \param acc intnum
+ * \return Nonzero if acc==0.
+ */
+YASM_LIB_DECL
+int yasm_intnum_is_zero(const yasm_intnum *acc);
+
+/** Simple value check for 1.
+ * \param acc intnum
+ * \return Nonzero if acc==1.
+ */
+YASM_LIB_DECL
+int yasm_intnum_is_pos1(const yasm_intnum *acc);
+
+/** Simple value check for -1.
+ * \param acc intnum
+ * \return Nonzero if acc==-1.
+ */
+YASM_LIB_DECL
+int yasm_intnum_is_neg1(const yasm_intnum *acc);
+
+/** Simple sign check.
+ * \param acc intnum
+ * \return -1 if negative, 0 if zero, +1 if positive
+ */
+YASM_LIB_DECL
+int yasm_intnum_sign(const yasm_intnum *acc);
+
+/** Convert an intnum to an unsigned 32-bit value. The value is in "standard"
+ * C format (eg, of unknown endian).
+ * \note Parameter intnum is truncated to fit into 32 bits. Use
+ * intnum_check_size() to check for overflow.
+ * \param intn intnum
+ * \return Unsigned 32-bit value of intn.
+ */
+YASM_LIB_DECL
+unsigned long yasm_intnum_get_uint(const yasm_intnum *intn);
+
+/** Convert an intnum to a signed 32-bit value. The value is in "standard" C
+ * format (eg, of unknown endian).
+ * \note Parameter intnum is truncated to fit into 32 bits. Use
+ * intnum_check_size() to check for overflow.
+ * \param intn intnum
+ * \return Signed 32-bit value of intn.
+ */
+YASM_LIB_DECL
+long yasm_intnum_get_int(const yasm_intnum *intn);
+
+/** Output #yasm_intnum to buffer in little-endian or big-endian. Puts the
+ * value into the least significant bits of the destination, or may be shifted
+ * into more significant bits by the shift parameter. The destination bits are
+ * cleared before being set. [0] should be the first byte output to the file.
+ * \param intn intnum
+ * \param ptr pointer to storage for size bytes of output
+ * \param destsize destination size (in bytes)
+ * \param valsize size (in bits)
+ * \param shift left shift (in bits); may be negative to specify right
+ * shift (standard warnings include truncation to boundary)
+ * \param bigendian endianness (nonzero=big, zero=little)
+ * \param warn enables standard warnings (value doesn't fit into valsize
+ * bits): <0=signed warnings, >0=unsigned warnings, 0=no warn
+ */
+YASM_LIB_DECL
+void yasm_intnum_get_sized(const yasm_intnum *intn, unsigned char *ptr,
+ size_t destsize, size_t valsize, int shift,
+ int bigendian, int warn);
+
+/** Check to see if intnum will fit without overflow into size bits.
+ * \param intn intnum
+ * \param size number of bits of output space
+ * \param rshift right shift
+ * \param rangetype signed/unsigned range selection:
+ * 0 => (0, unsigned max);
+ * 1 => (signed min, signed max);
+ * 2 => (signed min, unsigned max)
+ * \return Nonzero if intnum will fit.
+ */
+YASM_LIB_DECL
+int yasm_intnum_check_size(const yasm_intnum *intn, size_t size,
+ size_t rshift, int rangetype);
+
+/** Check to see if intnum will fit into a particular numeric range.
+ * \param intn intnum
+ * \param low low end of range (inclusive)
+ * \param high high end of range (inclusive)
+ * \return Nonzero if intnum is within range.
+ */
+YASM_LIB_DECL
+int yasm_intnum_in_range(const yasm_intnum *intn, long low, long high);
+
+/** Output #yasm_intnum to buffer in LEB128-encoded form.
+ * \param intn intnum
+ * \param ptr pointer to storage for output bytes
+ * \param sign signedness of LEB128 encoding (0=unsigned, 1=signed)
+ * \return Number of bytes generated.
+ */
+YASM_LIB_DECL
+unsigned long yasm_intnum_get_leb128(const yasm_intnum *intn,
+ unsigned char *ptr, int sign);
+
+/** Calculate number of bytes LEB128-encoded form of #yasm_intnum will take.
+ * \param intn intnum
+ * \param sign signedness of LEB128 encoding (0=unsigned, 1=signed)
+ * \return Number of bytes.
+ */
+YASM_LIB_DECL
+unsigned long yasm_intnum_size_leb128(const yasm_intnum *intn, int sign);
+
+/** Output integer to buffer in signed LEB128-encoded form.
+ * \param v integer
+ * \param ptr pointer to storage for output bytes
+ * \return Number of bytes generated.
+ */
+YASM_LIB_DECL
+unsigned long yasm_get_sleb128(long v, unsigned char *ptr);
+
+/** Calculate number of bytes signed LEB128-encoded form of integer will take.
+ * \param v integer
+ * \return Number of bytes.
+ */
+YASM_LIB_DECL
+unsigned long yasm_size_sleb128(long v);
+
+/** Output integer to buffer in unsigned LEB128-encoded form.
+ * \param v integer
+ * \param ptr pointer to storage for output bytes
+ * \return Number of bytes generated.
+ */
+YASM_LIB_DECL
+unsigned long yasm_get_uleb128(unsigned long v, unsigned char *ptr);
+
+/** Calculate number of bytes unsigned LEB128-encoded form of integer will take.
+ * \param v integer
+ * \return Number of bytes.
+ */
+YASM_LIB_DECL
+unsigned long yasm_size_uleb128(unsigned long v);
+
+/** Get an intnum as a signed decimal string. The returned string will
+ * contain a leading '-' if the intnum is negative.
+ * \param intn intnum
+ * \return Newly allocated string containing the decimal representation of
+ * the intnum.
+ */
+YASM_LIB_DECL
+/*@only@*/ char *yasm_intnum_get_str(const yasm_intnum *intn);
+
+/** Print an intnum. For debugging purposes.
+ * \param f file
+ * \param intn intnum
+ */
+YASM_LIB_DECL
+void yasm_intnum_print(const yasm_intnum *intn, FILE *f);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/inttree.c b/contrib/tools/yasm/libyasm/inttree.c
new file mode 100644
index 0000000000..2ae10e9b9c
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/inttree.c
@@ -0,0 +1,891 @@
+#include "util.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <math.h>
+#include "coretype.h"
+#include "inttree.h"
+
+#define VERIFY(condition) \
+if (!(condition)) { \
+fprintf(stderr, "Assumption \"%s\"\nFailed in file %s: at line:%i\n", \
+#condition,__FILE__,__LINE__); \
+abort();}
+
+/*#define DEBUG_ASSERT 1*/
+
+#ifdef DEBUG_ASSERT
+static void Assert(int assertion, const char *error)
+{
+ if (!assertion) {
+ fprintf(stderr, "Assertion Failed: %s\n", error);
+ abort();
+ }
+}
+#endif
+
+/* If the symbol CHECK_INTERVAL_TREE_ASSUMPTIONS is defined then the
+ * code does a lot of extra checking to make sure certain assumptions
+ * are satisfied. This only needs to be done if you suspect bugs are
+ * present or if you make significant changes and want to make sure
+ * your changes didn't mess anything up.
+ */
+/*#define CHECK_INTERVAL_TREE_ASSUMPTIONS 1*/
+
+static IntervalTreeNode *ITN_create(long low, long high, void *data);
+
+static void LeftRotate(IntervalTree *, IntervalTreeNode *);
+static void RightRotate(IntervalTree *, IntervalTreeNode *);
+static void TreeInsertHelp(IntervalTree *, IntervalTreeNode *);
+static void TreePrintHelper(const IntervalTree *, IntervalTreeNode *);
+static void FixUpMaxHigh(IntervalTree *, IntervalTreeNode *);
+static void DeleteFixUp(IntervalTree *, IntervalTreeNode *);
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+static void CheckMaxHighFields(const IntervalTree *, IntervalTreeNode *);
+static int CheckMaxHighFieldsHelper(const IntervalTree *, IntervalTreeNode *y,
+ const int currentHigh, int match);
+static void IT_CheckAssumptions(const IntervalTree *);
+#endif
+
+/* define a function to find the maximum of two objects. */
+#define ITMax(a, b) ( (a > b) ? a : b )
+
+IntervalTreeNode *
+ITN_create(long low, long high, void *data)
+{
+ IntervalTreeNode *itn = yasm_xmalloc(sizeof(IntervalTreeNode));
+ itn->data = data;
+ if (low < high) {
+ itn->low = low;
+ itn->high = high;
+ } else {
+ itn->low = high;
+ itn->high = low;
+ }
+ itn->maxHigh = high;
+ return itn;
+}
+
+IntervalTree *
+IT_create(void)
+{
+ IntervalTree *it = yasm_xmalloc(sizeof(IntervalTree));
+
+ it->nil = ITN_create(LONG_MIN, LONG_MIN, NULL);
+ it->nil->left = it->nil;
+ it->nil->right = it->nil;
+ it->nil->parent = it->nil;
+ it->nil->red = 0;
+
+ it->root = ITN_create(LONG_MAX, LONG_MAX, NULL);
+ it->root->left = it->nil;
+ it->root->right = it->nil;
+ it->root->parent = it->nil;
+ it->root->red = 0;
+
+ /* the following are used for the Enumerate function */
+ it->recursionNodeStackSize = 128;
+ it->recursionNodeStack = (it_recursion_node *)
+ yasm_xmalloc(it->recursionNodeStackSize*sizeof(it_recursion_node));
+ it->recursionNodeStackTop = 1;
+ it->recursionNodeStack[0].start_node = NULL;
+
+ return it;
+}
+
+/***********************************************************************/
+/* FUNCTION: LeftRotate */
+/**/
+/* INPUTS: the node to rotate on */
+/**/
+/* OUTPUT: None */
+/**/
+/* Modifies Input: this, x */
+/**/
+/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */
+/* Cormen, Leiserson, Rivest (Chapter 14). Basically this */
+/* makes the parent of x be to the left of x, x the parent of */
+/* its parent before the rotation and fixes other pointers */
+/* accordingly. Also updates the maxHigh fields of x and y */
+/* after rotation. */
+/***********************************************************************/
+
+static void
+LeftRotate(IntervalTree *it, IntervalTreeNode *x)
+{
+ IntervalTreeNode *y;
+
+ /* I originally wrote this function to use the sentinel for
+ * nil to avoid checking for nil. However this introduces a
+ * very subtle bug because sometimes this function modifies
+ * the parent pointer of nil. This can be a problem if a
+ * function which calls LeftRotate also uses the nil sentinel
+ * and expects the nil sentinel's parent pointer to be unchanged
+ * after calling this function. For example, when DeleteFixUP
+ * calls LeftRotate it expects the parent pointer of nil to be
+ * unchanged.
+ */
+
+ y=x->right;
+ x->right=y->left;
+
+ if (y->left != it->nil)
+ y->left->parent=x; /* used to use sentinel here */
+ /* and do an unconditional assignment instead of testing for nil */
+
+ y->parent=x->parent;
+
+ /* Instead of checking if x->parent is the root as in the book, we
+ * count on the root sentinel to implicitly take care of this case
+ */
+ if (x == x->parent->left)
+ x->parent->left=y;
+ else
+ x->parent->right=y;
+ y->left=x;
+ x->parent=y;
+
+ x->maxHigh=ITMax(x->left->maxHigh,ITMax(x->right->maxHigh,x->high));
+ y->maxHigh=ITMax(x->maxHigh,ITMax(y->right->maxHigh,y->high));
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ IT_CheckAssumptions(it);
+#elif defined(DEBUG_ASSERT)
+ Assert(!it->nil->red,"nil not red in ITLeftRotate");
+ Assert((it->nil->maxHigh=LONG_MIN),
+ "nil->maxHigh != LONG_MIN in ITLeftRotate");
+#endif
+}
+
+
+/***********************************************************************/
+/* FUNCTION: RightRotate */
+/**/
+/* INPUTS: node to rotate on */
+/**/
+/* OUTPUT: None */
+/**/
+/* Modifies Input?: this, y */
+/**/
+/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */
+/* Cormen, Leiserson, Rivest (Chapter 14). Basically this */
+/* makes the parent of x be to the left of x, x the parent of */
+/* its parent before the rotation and fixes other pointers */
+/* accordingly. Also updates the maxHigh fields of x and y */
+/* after rotation. */
+/***********************************************************************/
+
+
+static void
+RightRotate(IntervalTree *it, IntervalTreeNode *y)
+{
+ IntervalTreeNode *x;
+
+ /* I originally wrote this function to use the sentinel for
+ * nil to avoid checking for nil. However this introduces a
+ * very subtle bug because sometimes this function modifies
+ * the parent pointer of nil. This can be a problem if a
+ * function which calls LeftRotate also uses the nil sentinel
+ * and expects the nil sentinel's parent pointer to be unchanged
+ * after calling this function. For example, when DeleteFixUP
+ * calls LeftRotate it expects the parent pointer of nil to be
+ * unchanged.
+ */
+
+ x=y->left;
+ y->left=x->right;
+
+ if (it->nil != x->right)
+ x->right->parent=y; /*used to use sentinel here */
+ /* and do an unconditional assignment instead of testing for nil */
+
+ /* Instead of checking if x->parent is the root as in the book, we
+ * count on the root sentinel to implicitly take care of this case
+ */
+ x->parent=y->parent;
+ if (y == y->parent->left)
+ y->parent->left=x;
+ else
+ y->parent->right=x;
+ x->right=y;
+ y->parent=x;
+
+ y->maxHigh=ITMax(y->left->maxHigh,ITMax(y->right->maxHigh,y->high));
+ x->maxHigh=ITMax(x->left->maxHigh,ITMax(y->maxHigh,x->high));
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ IT_CheckAssumptions(it);
+#elif defined(DEBUG_ASSERT)
+ Assert(!it->nil->red,"nil not red in ITRightRotate");
+ Assert((it->nil->maxHigh=LONG_MIN),
+ "nil->maxHigh != LONG_MIN in ITRightRotate");
+#endif
+}
+
+/***********************************************************************/
+/* FUNCTION: TreeInsertHelp */
+/**/
+/* INPUTS: z is the node to insert */
+/**/
+/* OUTPUT: none */
+/**/
+/* Modifies Input: this, z */
+/**/
+/* EFFECTS: Inserts z into the tree as if it were a regular binary tree */
+/* using the algorithm described in _Introduction_To_Algorithms_ */
+/* by Cormen et al. This funciton is only intended to be called */
+/* by the InsertTree function and not by the user */
+/***********************************************************************/
+
+static void
+TreeInsertHelp(IntervalTree *it, IntervalTreeNode *z)
+{
+ /* This function should only be called by InsertITTree (see above) */
+ IntervalTreeNode* x;
+ IntervalTreeNode* y;
+
+ z->left=z->right=it->nil;
+ y=it->root;
+ x=it->root->left;
+ while( x != it->nil) {
+ y=x;
+ if (x->low > z->low)
+ x=x->left;
+ else /* x->low <= z->low */
+ x=x->right;
+ }
+ z->parent=y;
+ if ((y == it->root) || (y->low > z->low))
+ y->left=z;
+ else
+ y->right=z;
+
+#if defined(DEBUG_ASSERT)
+ Assert(!it->nil->red,"nil not red in ITTreeInsertHelp");
+ Assert((it->nil->maxHigh=INT_MIN),
+ "nil->maxHigh != INT_MIN in ITTreeInsertHelp");
+#endif
+}
+
+
+/***********************************************************************/
+/* FUNCTION: FixUpMaxHigh */
+/**/
+/* INPUTS: x is the node to start from*/
+/**/
+/* OUTPUT: none */
+/**/
+/* Modifies Input: this */
+/**/
+/* EFFECTS: Travels up to the root fixing the maxHigh fields after */
+/* an insertion or deletion */
+/***********************************************************************/
+
+static void
+FixUpMaxHigh(IntervalTree *it, IntervalTreeNode *x)
+{
+ while(x != it->root) {
+ x->maxHigh=ITMax(x->high,ITMax(x->left->maxHigh,x->right->maxHigh));
+ x=x->parent;
+ }
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ IT_CheckAssumptions(it);
+#endif
+}
+
+/* Before calling InsertNode the node x should have its key set */
+
+/***********************************************************************/
+/* FUNCTION: InsertNode */
+/**/
+/* INPUTS: newInterval is the interval to insert*/
+/**/
+/* OUTPUT: This function returns a pointer to the newly inserted node */
+/* which is guarunteed to be valid until this node is deleted. */
+/* What this means is if another data structure stores this */
+/* pointer then the tree does not need to be searched when this */
+/* is to be deleted. */
+/**/
+/* Modifies Input: tree */
+/**/
+/* EFFECTS: Creates a node node which contains the appropriate key and */
+/* info pointers and inserts it into the tree. */
+/***********************************************************************/
+
+IntervalTreeNode *
+IT_insert(IntervalTree *it, long low, long high, void *data)
+{
+ IntervalTreeNode *x, *y, *newNode;
+
+ x = ITN_create(low, high, data);
+ TreeInsertHelp(it, x);
+ FixUpMaxHigh(it, x->parent);
+ newNode = x;
+ x->red=1;
+ while(x->parent->red) { /* use sentinel instead of checking for root */
+ if (x->parent == x->parent->parent->left) {
+ y=x->parent->parent->right;
+ if (y->red) {
+ x->parent->red=0;
+ y->red=0;
+ x->parent->parent->red=1;
+ x=x->parent->parent;
+ } else {
+ if (x == x->parent->right) {
+ x=x->parent;
+ LeftRotate(it, x);
+ }
+ x->parent->red=0;
+ x->parent->parent->red=1;
+ RightRotate(it, x->parent->parent);
+ }
+ } else { /* case for x->parent == x->parent->parent->right */
+ /* this part is just like the section above with */
+ /* left and right interchanged */
+ y=x->parent->parent->left;
+ if (y->red) {
+ x->parent->red=0;
+ y->red=0;
+ x->parent->parent->red=1;
+ x=x->parent->parent;
+ } else {
+ if (x == x->parent->left) {
+ x=x->parent;
+ RightRotate(it, x);
+ }
+ x->parent->red=0;
+ x->parent->parent->red=1;
+ LeftRotate(it, x->parent->parent);
+ }
+ }
+ }
+ it->root->left->red=0;
+
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ IT_CheckAssumptions(it);
+#elif defined(DEBUG_ASSERT)
+ Assert(!it->nil->red,"nil not red in ITTreeInsert");
+ Assert(!it->root->red,"root not red in ITTreeInsert");
+ Assert((it->nil->maxHigh=LONG_MIN),
+ "nil->maxHigh != LONG_MIN in ITTreeInsert");
+#endif
+ return newNode;
+}
+
+/***********************************************************************/
+/* FUNCTION: GetSuccessorOf */
+/**/
+/* INPUTS: x is the node we want the succesor of */
+/**/
+/* OUTPUT: This function returns the successor of x or NULL if no */
+/* successor exists. */
+/**/
+/* Modifies Input: none */
+/**/
+/* Note: uses the algorithm in _Introduction_To_Algorithms_ */
+/***********************************************************************/
+
+IntervalTreeNode *
+IT_get_successor(const IntervalTree *it, IntervalTreeNode *x)
+{
+ IntervalTreeNode *y;
+
+ if (it->nil != (y = x->right)) { /* assignment to y is intentional */
+ while(y->left != it->nil) /* returns the minium of the right subtree of x */
+ y=y->left;
+ return y;
+ } else {
+ y=x->parent;
+ while(x == y->right) { /* sentinel used instead of checking for nil */
+ x=y;
+ y=y->parent;
+ }
+ if (y == it->root)
+ return(it->nil);
+ return y;
+ }
+}
+
+/***********************************************************************/
+/* FUNCTION: GetPredecessorOf */
+/**/
+/* INPUTS: x is the node to get predecessor of */
+/**/
+/* OUTPUT: This function returns the predecessor of x or NULL if no */
+/* predecessor exists. */
+/**/
+/* Modifies Input: none */
+/**/
+/* Note: uses the algorithm in _Introduction_To_Algorithms_ */
+/***********************************************************************/
+
+IntervalTreeNode *
+IT_get_predecessor(const IntervalTree *it, IntervalTreeNode *x)
+{
+ IntervalTreeNode *y;
+
+ if (it->nil != (y = x->left)) { /* assignment to y is intentional */
+ while(y->right != it->nil) /* returns the maximum of the left subtree of x */
+ y=y->right;
+ return y;
+ } else {
+ y=x->parent;
+ while(x == y->left) {
+ if (y == it->root)
+ return(it->nil);
+ x=y;
+ y=y->parent;
+ }
+ return y;
+ }
+}
+
+/***********************************************************************/
+/* FUNCTION: Print */
+/**/
+/* INPUTS: none */
+/**/
+/* OUTPUT: none */
+/**/
+/* EFFECTS: This function recursively prints the nodes of the tree */
+/* inorder. */
+/**/
+/* Modifies Input: none */
+/**/
+/* Note: This function should only be called from ITTreePrint */
+/***********************************************************************/
+
+static void
+ITN_print(const IntervalTreeNode *itn, IntervalTreeNode *nil,
+ IntervalTreeNode *root)
+{
+ printf(", l=%li, h=%li, mH=%li", itn->low, itn->high, itn->maxHigh);
+ printf(" l->low=");
+ if (itn->left == nil)
+ printf("NULL");
+ else
+ printf("%li", itn->left->low);
+ printf(" r->low=");
+ if (itn->right == nil)
+ printf("NULL");
+ else
+ printf("%li", itn->right->low);
+ printf(" p->low=");
+ if (itn->parent == root)
+ printf("NULL");
+ else
+ printf("%li", itn->parent->low);
+ printf(" red=%i\n", itn->red);
+}
+
+static void
+TreePrintHelper(const IntervalTree *it, IntervalTreeNode *x)
+{
+ if (x != it->nil) {
+ TreePrintHelper(it, x->left);
+ ITN_print(x, it->nil, it->root);
+ TreePrintHelper(it, x->right);
+ }
+}
+
+void
+IT_destroy(IntervalTree *it)
+{
+ IntervalTreeNode *x = it->root->left;
+ SLIST_HEAD(node_head, nodeent)
+ stuffToFree = SLIST_HEAD_INITIALIZER(stuffToFree);
+ struct nodeent {
+ SLIST_ENTRY(nodeent) link;
+ struct IntervalTreeNode *node;
+ } *np;
+
+ if (x != it->nil) {
+ if (x->left != it->nil) {
+ np = yasm_xmalloc(sizeof(struct nodeent));
+ np->node = x->left;
+ SLIST_INSERT_HEAD(&stuffToFree, np, link);
+ }
+ if (x->right != it->nil) {
+ np = yasm_xmalloc(sizeof(struct nodeent));
+ np->node = x->right;
+ SLIST_INSERT_HEAD(&stuffToFree, np, link);
+ }
+ yasm_xfree(x);
+ while (!SLIST_EMPTY(&stuffToFree)) {
+ np = SLIST_FIRST(&stuffToFree);
+ x = np->node;
+ SLIST_REMOVE_HEAD(&stuffToFree, link);
+ yasm_xfree(np);
+
+ if (x->left != it->nil) {
+ np = yasm_xmalloc(sizeof(struct nodeent));
+ np->node = x->left;
+ SLIST_INSERT_HEAD(&stuffToFree, np, link);
+ }
+ if (x->right != it->nil) {
+ np = yasm_xmalloc(sizeof(struct nodeent));
+ np->node = x->right;
+ SLIST_INSERT_HEAD(&stuffToFree, np, link);
+ }
+ yasm_xfree(x);
+ }
+ }
+
+ yasm_xfree(it->nil);
+ yasm_xfree(it->root);
+ yasm_xfree(it->recursionNodeStack);
+ yasm_xfree(it);
+}
+
+
+/***********************************************************************/
+/* FUNCTION: Print */
+/**/
+/* INPUTS: none */
+/**/
+/* OUTPUT: none */
+/**/
+/* EFFECT: This function recursively prints the nodes of the tree */
+/* inorder. */
+/**/
+/* Modifies Input: none */
+/**/
+/***********************************************************************/
+
+void
+IT_print(const IntervalTree *it)
+{
+ TreePrintHelper(it, it->root->left);
+}
+
+/***********************************************************************/
+/* FUNCTION: DeleteFixUp */
+/**/
+/* INPUTS: x is the child of the spliced */
+/* out node in DeleteNode. */
+/**/
+/* OUTPUT: none */
+/**/
+/* EFFECT: Performs rotations and changes colors to restore red-black */
+/* properties after a node is deleted */
+/**/
+/* Modifies Input: this, x */
+/**/
+/* The algorithm from this function is from _Introduction_To_Algorithms_ */
+/***********************************************************************/
+
+static void
+DeleteFixUp(IntervalTree *it, IntervalTreeNode *x)
+{
+ IntervalTreeNode *w;
+ IntervalTreeNode *rootLeft = it->root->left;
+
+ while ((!x->red) && (rootLeft != x)) {
+ if (x == x->parent->left) {
+ w=x->parent->right;
+ if (w->red) {
+ w->red=0;
+ x->parent->red=1;
+ LeftRotate(it, x->parent);
+ w=x->parent->right;
+ }
+ if ( (!w->right->red) && (!w->left->red) ) {
+ w->red=1;
+ x=x->parent;
+ } else {
+ if (!w->right->red) {
+ w->left->red=0;
+ w->red=1;
+ RightRotate(it, w);
+ w=x->parent->right;
+ }
+ w->red=x->parent->red;
+ x->parent->red=0;
+ w->right->red=0;
+ LeftRotate(it, x->parent);
+ x=rootLeft; /* this is to exit while loop */
+ }
+ } else { /* the code below is has left and right switched from above */
+ w=x->parent->left;
+ if (w->red) {
+ w->red=0;
+ x->parent->red=1;
+ RightRotate(it, x->parent);
+ w=x->parent->left;
+ }
+ if ((!w->right->red) && (!w->left->red)) {
+ w->red=1;
+ x=x->parent;
+ } else {
+ if (!w->left->red) {
+ w->right->red=0;
+ w->red=1;
+ LeftRotate(it, w);
+ w=x->parent->left;
+ }
+ w->red=x->parent->red;
+ x->parent->red=0;
+ w->left->red=0;
+ RightRotate(it, x->parent);
+ x=rootLeft; /* this is to exit while loop */
+ }
+ }
+ }
+ x->red=0;
+
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ IT_CheckAssumptions(it);
+#elif defined(DEBUG_ASSERT)
+ Assert(!it->nil->red,"nil not black in ITDeleteFixUp");
+ Assert((it->nil->maxHigh=LONG_MIN),
+ "nil->maxHigh != LONG_MIN in ITDeleteFixUp");
+#endif
+}
+
+
+/***********************************************************************/
+/* FUNCTION: DeleteNode */
+/**/
+/* INPUTS: tree is the tree to delete node z from */
+/**/
+/* OUTPUT: returns the Interval stored at deleted node */
+/**/
+/* EFFECT: Deletes z from tree and but don't call destructor */
+/* Then calls FixUpMaxHigh to fix maxHigh fields then calls */
+/* ITDeleteFixUp to restore red-black properties */
+/**/
+/* Modifies Input: z */
+/**/
+/* The algorithm from this function is from _Introduction_To_Algorithms_ */
+/***********************************************************************/
+
+void *
+IT_delete_node(IntervalTree *it, IntervalTreeNode *z, long *low, long *high)
+{
+ IntervalTreeNode *x, *y;
+ void *returnValue = z->data;
+ if (low)
+ *low = z->low;
+ if (high)
+ *high = z->high;
+
+ y= ((z->left == it->nil) || (z->right == it->nil)) ?
+ z : IT_get_successor(it, z);
+ x= (y->left == it->nil) ? y->right : y->left;
+ if (it->root == (x->parent = y->parent))
+ /* assignment of y->p to x->p is intentional */
+ it->root->left=x;
+ else {
+ if (y == y->parent->left)
+ y->parent->left=x;
+ else
+ y->parent->right=x;
+ }
+ if (y != z) { /* y should not be nil in this case */
+
+#ifdef DEBUG_ASSERT
+ Assert( (y!=it->nil),"y is nil in DeleteNode \n");
+#endif
+ /* y is the node to splice out and x is its child */
+
+ y->maxHigh = INT_MIN;
+ y->left=z->left;
+ y->right=z->right;
+ y->parent=z->parent;
+ z->left->parent=z->right->parent=y;
+ if (z == z->parent->left)
+ z->parent->left=y;
+ else
+ z->parent->right=y;
+ FixUpMaxHigh(it, x->parent);
+ if (!(y->red)) {
+ y->red = z->red;
+ DeleteFixUp(it, x);
+ } else
+ y->red = z->red;
+ yasm_xfree(z);
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ IT_CheckAssumptions(it);
+#elif defined(DEBUG_ASSERT)
+ Assert(!it->nil->red,"nil not black in ITDelete");
+ Assert((it->nil->maxHigh=LONG_MIN),"nil->maxHigh != LONG_MIN in ITDelete");
+#endif
+ } else {
+ FixUpMaxHigh(it, x->parent);
+ if (!(y->red))
+ DeleteFixUp(it, x);
+ yasm_xfree(y);
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ IT_CheckAssumptions(it);
+#elif defined(DEBUG_ASSERT)
+ Assert(!it->nil->red,"nil not black in ITDelete");
+ Assert((it->nil->maxHigh=LONG_MIN),"nil->maxHigh != LONG_MIN in ITDelete");
+#endif
+ }
+ return returnValue;
+}
+
+
+/***********************************************************************/
+/* FUNCTION: Overlap */
+/**/
+/* INPUTS: [a1,a2] and [b1,b2] are the low and high endpoints of two */
+/* closed intervals. */
+/**/
+/* OUTPUT: stack containing pointers to the nodes between [low,high] */
+/**/
+/* Modifies Input: none */
+/**/
+/* EFFECT: returns 1 if the intervals overlap, and 0 otherwise */
+/***********************************************************************/
+
+static int
+Overlap(int a1, int a2, int b1, int b2)
+{
+ if (a1 <= b1)
+ return (b1 <= a2);
+ else
+ return (a1 <= b2);
+}
+
+
+/***********************************************************************/
+/* FUNCTION: Enumerate */
+/**/
+/* INPUTS: tree is the tree to look for intervals overlapping the */
+/* closed interval [low,high] */
+/**/
+/* OUTPUT: stack containing pointers to the nodes overlapping */
+/* [low,high] */
+/**/
+/* Modifies Input: none */
+/**/
+/* EFFECT: Returns a stack containing pointers to nodes containing */
+/* intervals which overlap [low,high] in O(max(N,k*log(N))) */
+/* where N is the number of intervals in the tree and k is */
+/* the number of overlapping intervals */
+/**/
+/* Note: This basic idea for this function comes from the */
+/* _Introduction_To_Algorithms_ book by Cormen et al, but */
+/* modifications were made to return all overlapping intervals */
+/* instead of just the first overlapping interval as in the */
+/* book. The natural way to do this would require recursive */
+/* calls of a basic search function. I translated the */
+/* recursive version into an interative version with a stack */
+/* as described below. */
+/***********************************************************************/
+
+
+
+/* The basic idea for the function below is to take the IntervalSearch
+ * function from the book and modify to find all overlapping intervals
+ * instead of just one. This means that any time we take the left
+ * branch down the tree we must also check the right branch if and only if
+ * we find an overlapping interval in that left branch. Note this is a
+ * recursive condition because if we go left at the root then go left
+ * again at the first left child and find an overlap in the left subtree
+ * of the left child of root we must recursively check the right subtree
+ * of the left child of root as well as the right child of root.
+ */
+void
+IT_enumerate(IntervalTree *it, long low, long high, void *cbd,
+ void (*callback) (IntervalTreeNode *node, void *cbd))
+{
+ IntervalTreeNode *x=it->root->left;
+ int stuffToDo = (x != it->nil);
+
+ /* Possible speed up: add min field to prune right searches */
+
+#ifdef DEBUG_ASSERT
+ Assert((it->recursionNodeStackTop == 1),
+ "recursionStack not empty when entering IntervalTree::Enumerate");
+#endif
+ it->currentParent = 0;
+
+ while (stuffToDo) {
+ if (Overlap(low,high,x->low,x->high) ) {
+ callback(x, cbd);
+ it->recursionNodeStack[it->currentParent].tryRightBranch=1;
+ }
+ if(x->left->maxHigh >= low) { /* implies x != nil */
+ if (it->recursionNodeStackTop == it->recursionNodeStackSize) {
+ it->recursionNodeStackSize *= 2;
+ it->recursionNodeStack = (it_recursion_node *)
+ yasm_xrealloc(it->recursionNodeStack,
+ it->recursionNodeStackSize * sizeof(it_recursion_node));
+ }
+ it->recursionNodeStack[it->recursionNodeStackTop].start_node = x;
+ it->recursionNodeStack[it->recursionNodeStackTop].tryRightBranch = 0;
+ it->recursionNodeStack[it->recursionNodeStackTop].parentIndex = it->currentParent;
+ it->currentParent = it->recursionNodeStackTop++;
+ x = x->left;
+ } else {
+ x = x->right;
+ }
+ stuffToDo = (x != it->nil);
+ while (!stuffToDo && (it->recursionNodeStackTop > 1)) {
+ if (it->recursionNodeStack[--it->recursionNodeStackTop].tryRightBranch) {
+ x=it->recursionNodeStack[it->recursionNodeStackTop].start_node->right;
+ it->currentParent=it->recursionNodeStack[it->recursionNodeStackTop].parentIndex;
+ it->recursionNodeStack[it->currentParent].tryRightBranch=1;
+ stuffToDo = (x != it->nil);
+ }
+ }
+ }
+#ifdef DEBUG_ASSERT
+ Assert((it->recursionNodeStackTop == 1),
+ "recursionStack not empty when exiting IntervalTree::Enumerate");
+#endif
+}
+
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+
+static int
+CheckMaxHighFieldsHelper(const IntervalTree *it, IntervalTreeNode *y,
+ int currentHigh, int match)
+{
+ if (y != it->nil) {
+ match = CheckMaxHighFieldsHelper(it, y->left, currentHigh, match) ?
+ 1 : match;
+ VERIFY(y->high <= currentHigh);
+ if (y->high == currentHigh)
+ match = 1;
+ match = CheckMaxHighFieldsHelper(it, y->right, currentHigh, match) ?
+ 1 : match;
+ }
+ return match;
+}
+
+
+
+/* Make sure the maxHigh fields for everything makes sense. *
+ * If something is wrong, print a warning and exit */
+static void
+CheckMaxHighFields(const IntervalTree *it, IntervalTreeNode *x)
+{
+ if (x != it->nil) {
+ CheckMaxHighFields(it, x->left);
+ if(!(CheckMaxHighFieldsHelper(it, x, x->maxHigh, 0) > 0)) {
+ fprintf(stderr, "error found in CheckMaxHighFields.\n");
+ abort();
+ }
+ CheckMaxHighFields(it, x->right);
+ }
+}
+
+static void
+IT_CheckAssumptions(const IntervalTree *it)
+{
+ VERIFY(it->nil->low == INT_MIN);
+ VERIFY(it->nil->high == INT_MIN);
+ VERIFY(it->nil->maxHigh == INT_MIN);
+ VERIFY(it->root->low == INT_MAX);
+ VERIFY(it->root->high == INT_MAX);
+ VERIFY(it->root->maxHigh == INT_MAX);
+ VERIFY(it->nil->data == NULL);
+ VERIFY(it->root->data == NULL);
+ VERIFY(it->nil->red == 0);
+ VERIFY(it->root->red == 0);
+ CheckMaxHighFields(it, it->root->left);
+}
+#endif
+
diff --git a/contrib/tools/yasm/libyasm/inttree.h b/contrib/tools/yasm/libyasm/inttree.h
new file mode 100644
index 0000000000..f7a7651512
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/inttree.h
@@ -0,0 +1,70 @@
+#ifndef YASM_INTTREE_H
+#define YASM_INTTREE_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/* The interval_tree.h and interval_tree.cc files contain code for
+ * interval trees implemented using red-black-trees as described in
+ * the book _Introduction_To_Algorithms_ by Cormen, Leisserson,
+ * and Rivest.
+ */
+
+typedef struct IntervalTreeNode {
+ struct IntervalTreeNode *left, *right, *parent;
+ void *data;
+ long low;
+ long high;
+ long maxHigh;
+ int red; /* if red=0 then the node is black */
+} IntervalTreeNode;
+
+typedef struct it_recursion_node {
+ /* This structure stores the information needed when we take the
+ * right branch in searching for intervals but possibly come back
+ * and check the left branch as well.
+ */
+ IntervalTreeNode *start_node;
+ unsigned int parentIndex;
+ int tryRightBranch;
+} it_recursion_node;
+
+typedef struct IntervalTree {
+ /* A sentinel is used for root and for nil. These sentinels are
+ * created when ITTreeCreate is called. root->left should always
+ * point to the node which is the root of the tree. nil points to a
+ * node which should always be black but has aribtrary children and
+ * parent and no key or info. The point of using these sentinels is so
+ * that the root and nil nodes do not require special cases in the code
+ */
+ IntervalTreeNode *root;
+ IntervalTreeNode *nil;
+
+/*private:*/
+ unsigned int recursionNodeStackSize;
+ it_recursion_node * recursionNodeStack;
+ unsigned int currentParent;
+ unsigned int recursionNodeStackTop;
+} IntervalTree;
+
+YASM_LIB_DECL
+IntervalTree *IT_create(void);
+YASM_LIB_DECL
+void IT_destroy(IntervalTree *);
+YASM_LIB_DECL
+void IT_print(const IntervalTree *);
+YASM_LIB_DECL
+void *IT_delete_node(IntervalTree *, IntervalTreeNode *, long *low,
+ long *high);
+YASM_LIB_DECL
+IntervalTreeNode *IT_insert(IntervalTree *, long low, long high, void *data);
+YASM_LIB_DECL
+IntervalTreeNode *IT_get_predecessor(const IntervalTree *, IntervalTreeNode *);
+YASM_LIB_DECL
+IntervalTreeNode *IT_get_successor(const IntervalTree *, IntervalTreeNode *);
+YASM_LIB_DECL
+void IT_enumerate(IntervalTree *, long low, long high, void *cbd,
+ void (*callback) (IntervalTreeNode *node, void *cbd));
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/linemap.c b/contrib/tools/yasm/libyasm/linemap.c
new file mode 100644
index 0000000000..42201d3c07
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/linemap.c
@@ -0,0 +1,293 @@
+/*
+ * YASM assembler virtual line mapping handling (for parse stage)
+ *
+ * Copyright (C) 2002-2007 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 "util.h"
+
+#include "coretype.h"
+#include "hamt.h"
+
+#include "errwarn.h"
+#include "linemap.h"
+
+
+typedef struct line_mapping {
+ /* monotonically increasing virtual line */
+ unsigned long line;
+
+ /* related info */
+ /* "original" source filename */
+ /*@null@*/ /*@dependent@*/ const char *filename;
+ /* "original" source base line number */
+ unsigned long file_line;
+ /* "original" source line number increment (for following lines) */
+ unsigned long line_inc;
+} line_mapping;
+
+typedef struct line_source_info {
+ /* first bytecode on line; NULL if no bytecodes on line */
+ /*@null@*/ /*@dependent@*/ yasm_bytecode *bc;
+
+ /* source code line */
+ /*@owned@*/ char *source;
+} line_source_info;
+
+struct yasm_linemap {
+ /* Shared storage for filenames */
+ /*@only@*/ /*@null@*/ HAMT *filenames;
+
+ /* Current virtual line number. */
+ unsigned long current;
+
+ /* Mappings from virtual to physical line numbers */
+ struct line_mapping *map_vector;
+ unsigned long map_size;
+ unsigned long map_allocated;
+
+ /* Bytecode and source line information */
+ /*@only@*/ line_source_info *source_info;
+ size_t source_info_size;
+};
+
+static void
+filename_delete_one(/*@only@*/ void *d)
+{
+ yasm_xfree(d);
+}
+
+void
+yasm_linemap_set(yasm_linemap *linemap, const char *filename,
+ unsigned long virtual_line, unsigned long file_line,
+ unsigned long line_inc)
+{
+ char *copy;
+ unsigned long i;
+ int replace = 0;
+ line_mapping *mapping = NULL;
+
+ if (virtual_line == 0) {
+ virtual_line = linemap->current;
+ }
+
+ /* Replace all existing mappings that have line numbers >= this one. */
+ for (i = linemap->map_size; i > 0; i--) {
+ if (linemap->map_vector[i-1].line < virtual_line) {
+ if (i < linemap->map_size) {
+ mapping = &linemap->map_vector[i];
+ linemap->map_size = i + 1;
+ }
+ break;
+ }
+ }
+
+ if (mapping == NULL) {
+ /* Create a new mapping in the map */
+ if (linemap->map_size >= linemap->map_allocated) {
+ /* allocate another size bins when full for 2x space */
+ linemap->map_vector = yasm_xrealloc(linemap->map_vector,
+ 2*linemap->map_allocated*sizeof(line_mapping));
+ linemap->map_allocated *= 2;
+ }
+ mapping = &linemap->map_vector[linemap->map_size];
+ linemap->map_size++;
+ }
+
+ /* Fill it */
+
+ if (!filename) {
+ if (linemap->map_size >= 2)
+ mapping->filename =
+ linemap->map_vector[linemap->map_size-2].filename;
+ else
+ filename = "unknown";
+ }
+ if (filename) {
+ /* Copy the filename (via shared storage) */
+ copy = yasm__xstrdup(filename);
+ /*@-aliasunique@*/
+ mapping->filename = HAMT_insert(linemap->filenames, copy, copy,
+ &replace, filename_delete_one);
+ /*@=aliasunique@*/
+ }
+
+ mapping->line = virtual_line;
+ mapping->file_line = file_line;
+ mapping->line_inc = line_inc;
+}
+
+unsigned long
+yasm_linemap_poke(yasm_linemap *linemap, const char *filename,
+ unsigned long file_line)
+{
+ unsigned long line;
+ line_mapping *mapping;
+
+ linemap->current++;
+ yasm_linemap_set(linemap, filename, 0, file_line, 0);
+
+ mapping = &linemap->map_vector[linemap->map_size-1];
+
+ line = linemap->current;
+
+ linemap->current++;
+ yasm_linemap_set(linemap, mapping->filename, 0,
+ mapping->file_line +
+ mapping->line_inc*(linemap->current-2-mapping->line),
+ mapping->line_inc);
+
+ return line;
+}
+
+yasm_linemap *
+yasm_linemap_create(void)
+{
+ size_t i;
+ yasm_linemap *linemap = yasm_xmalloc(sizeof(yasm_linemap));
+
+ linemap->filenames = HAMT_create(0, yasm_internal_error_);
+
+ linemap->current = 1;
+
+ /* initialize mapping vector */
+ linemap->map_vector = yasm_xmalloc(8*sizeof(line_mapping));
+ linemap->map_size = 0;
+ linemap->map_allocated = 8;
+
+ /* initialize source line information array */
+ linemap->source_info_size = 2;
+ linemap->source_info = yasm_xmalloc(linemap->source_info_size *
+ sizeof(line_source_info));
+ for (i=0; i<linemap->source_info_size; i++) {
+ linemap->source_info[i].bc = NULL;
+ linemap->source_info[i].source = NULL;
+ }
+
+ return linemap;
+}
+
+void
+yasm_linemap_destroy(yasm_linemap *linemap)
+{
+ size_t i;
+ for (i=0; i<linemap->source_info_size; i++) {
+ if (linemap->source_info[i].source)
+ yasm_xfree(linemap->source_info[i].source);
+ }
+ yasm_xfree(linemap->source_info);
+
+ yasm_xfree(linemap->map_vector);
+
+ if (linemap->filenames)
+ HAMT_destroy(linemap->filenames, filename_delete_one);
+
+ yasm_xfree(linemap);
+}
+
+unsigned long
+yasm_linemap_get_current(yasm_linemap *linemap)
+{
+ return linemap->current;
+}
+
+void
+yasm_linemap_add_source(yasm_linemap *linemap, yasm_bytecode *bc,
+ const char *source)
+{
+ size_t i;
+
+ while (linemap->current > linemap->source_info_size) {
+ /* allocate another size bins when full for 2x space */
+ linemap->source_info = yasm_xrealloc(linemap->source_info,
+ 2*linemap->source_info_size*sizeof(line_source_info));
+ for (i=linemap->source_info_size; i<linemap->source_info_size*2; i++) {
+ linemap->source_info[i].bc = NULL;
+ linemap->source_info[i].source = NULL;
+ }
+ linemap->source_info_size *= 2;
+ }
+
+ /* Delete existing info for that line (if any) */
+ if (linemap->source_info[linemap->current-1].source)
+ yasm_xfree(linemap->source_info[linemap->current-1].source);
+
+ linemap->source_info[linemap->current-1].bc = bc;
+ linemap->source_info[linemap->current-1].source = yasm__xstrdup(source);
+}
+
+unsigned long
+yasm_linemap_goto_next(yasm_linemap *linemap)
+{
+ return ++(linemap->current);
+}
+
+void
+yasm_linemap_lookup(yasm_linemap *linemap, unsigned long line,
+ const char **filename, unsigned long *file_line)
+{
+ line_mapping *mapping;
+ unsigned long vindex, step;
+
+ assert(line <= linemap->current);
+
+ /* Binary search through map to find highest line_index <= index */
+ vindex = 0;
+ /* start step as the greatest power of 2 <= size */
+ step = 1;
+ while (step*2<=linemap->map_size)
+ step*=2;
+ while (step>0) {
+ if (vindex+step < linemap->map_size
+ && linemap->map_vector[vindex+step].line <= line)
+ vindex += step;
+ step /= 2;
+ }
+ mapping = &linemap->map_vector[vindex];
+
+ *filename = mapping->filename;
+ *file_line = (line ? mapping->file_line + mapping->line_inc*(line-mapping->line) : 0);
+}
+
+int
+yasm_linemap_traverse_filenames(yasm_linemap *linemap, /*@null@*/ void *d,
+ int (*func) (const char *filename, void *d))
+{
+ return HAMT_traverse(linemap->filenames, d, (int (*) (void *, void *))func);
+}
+
+int
+yasm_linemap_get_source(yasm_linemap *linemap, unsigned long line,
+ yasm_bytecode **bcp, const char **sourcep)
+{
+ if (line > linemap->source_info_size) {
+ *bcp = NULL;
+ *sourcep = NULL;
+ return 1;
+ }
+
+ *bcp = linemap->source_info[line-1].bc;
+ *sourcep = linemap->source_info[line-1].source;
+
+ return (!(*sourcep));
+}
diff --git a/contrib/tools/yasm/libyasm/linemap.h b/contrib/tools/yasm/libyasm/linemap.h
new file mode 100644
index 0000000000..1c5aa4626a
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/linemap.h
@@ -0,0 +1,141 @@
+/**
+ * \file libyasm/linemap.h
+ * \brief YASM virtual line mapping interface.
+ *
+ * \license
+ * Copyright (C) 2002-2007 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.
+ * \endlicense
+ */
+#ifndef YASM_LINEMAP_H
+#define YASM_LINEMAP_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Create a new line mapping repository.
+ * \return New repository.
+ */
+YASM_LIB_DECL
+yasm_linemap *yasm_linemap_create(void);
+
+/** Clean up any memory allocated for a repository.
+ * \param linemap line mapping repository
+ */
+YASM_LIB_DECL
+void yasm_linemap_destroy(yasm_linemap *linemap);
+
+/** Get the current line position in a repository.
+ * \param linemap line mapping repository
+ * \return Current virtual line.
+ */
+YASM_LIB_DECL
+unsigned long yasm_linemap_get_current(yasm_linemap *linemap);
+
+/** Get bytecode and source line information, if any, for a virtual line.
+ * \param linemap line mapping repository
+ * \param line virtual line
+ * \param bcp pointer to return bytecode into
+ * \param sourcep pointer to return source code line pointer into
+ * \return Zero if source line information available for line, nonzero if not.
+ * \note If source line information is not available, bcp and sourcep targets
+ * are set to NULL.
+ */
+YASM_LIB_DECL
+int yasm_linemap_get_source(yasm_linemap *linemap, unsigned long line,
+ /*@null@*/ yasm_bytecode **bcp,
+ const char **sourcep);
+
+/** Add bytecode and source line information to the current virtual line.
+ * \attention Deletes any existing bytecode and source line information for
+ * the current virtual line.
+ * \param linemap line mapping repository
+ * \param bc bytecode (if any)
+ * \param source source code line
+ * \note The source code line pointer is NOT kept, it is strdup'ed.
+ */
+YASM_LIB_DECL
+void yasm_linemap_add_source(yasm_linemap *linemap,
+ /*@null@*/ yasm_bytecode *bc,
+ const char *source);
+
+/** Go to the next line (increments the current virtual line).
+ * \param linemap line mapping repository
+ * \return The current (new) virtual line.
+ */
+YASM_LIB_DECL
+unsigned long yasm_linemap_goto_next(yasm_linemap *linemap);
+
+/** Set a new file/line physical association starting point at the specified
+ * virtual line. line_inc indicates how much the "real" line is incremented
+ * by for each virtual line increment (0 is perfectly legal).
+ * \param linemap line mapping repository
+ * \param filename physical file name (if NULL, not changed)
+ * \param virtual_line virtual line number (if 0, linemap->current is used)
+ * \param file_line physical line number
+ * \param line_inc line increment
+ */
+YASM_LIB_DECL
+void yasm_linemap_set(yasm_linemap *linemap, /*@null@*/ const char *filename,
+ unsigned long virtual_line, unsigned long file_line,
+ unsigned long line_inc);
+
+/** Poke a single file/line association, restoring the original physical
+ * association starting point. Caution: increments the current virtual line
+ * twice.
+ * \param linemap line mapping repository
+ * \param filename physical file name (if NULL, not changed)
+ * \param file_line physical line number
+ * \return The virtual line number of the poked association.
+ */
+YASM_LIB_DECL
+unsigned long yasm_linemap_poke(yasm_linemap *linemap,
+ /*@null@*/ const char *filename,
+ unsigned long file_line);
+
+/** Look up the associated physical file and line for a virtual line.
+ * \param linemap line mapping repository
+ * \param line virtual line
+ * \param filename physical file name (output)
+ * \param file_line physical line number (output)
+ */
+YASM_LIB_DECL
+void yasm_linemap_lookup(yasm_linemap *linemap, unsigned long line,
+ /*@out@*/ const char **filename,
+ /*@out@*/ unsigned long *file_line);
+
+/** Traverses all filenames used in a linemap, calling a function on each
+ * filename.
+ * \param linemap line mapping repository
+ * \param d data pointer passed to func on each call
+ * \param func function
+ * \return Stops early (and returns func's return value) if func returns a
+ * nonzero value; otherwise 0.
+ */
+YASM_LIB_DECL
+int yasm_linemap_traverse_filenames
+ (yasm_linemap *linemap, /*@null@*/ void *d,
+ int (*func) (const char *filename, void *d));
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/listfmt.h b/contrib/tools/yasm/libyasm/listfmt.h
new file mode 100644
index 0000000000..945f28e58b
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/listfmt.h
@@ -0,0 +1,124 @@
+/**
+ * \file libyasm/listfmt.h
+ * \brief YASM list format interface.
+ *
+ * \license
+ * Copyright (C) 2004-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_LISTFMT_H
+#define YASM_LISTFMT_H
+
+#ifndef YASM_DOXYGEN
+/** Base #yasm_listfmt structure. Must be present as the first element in any
+ * #yasm_listfmt implementation.
+ */
+typedef struct yasm_listfmt_base {
+ /** #yasm_listfmt_module implementation for this list format. */
+ const struct yasm_listfmt_module *module;
+} yasm_listfmt_base;
+#endif
+
+/** YASM list format module interface. */
+typedef struct yasm_listfmt_module {
+ /** One-line description of the list format. */
+ const char *name;
+
+ /** Keyword used to select list format. */
+ const char *keyword;
+
+ /** Create list format.
+ * Module-level implementation of yasm_listfmt_create().
+ * The filenames are provided solely for informational purposes.
+ * \param in_filename primary input filename
+ * \param obj_filename object filename
+ * \return NULL if unable to initialize.
+ */
+ /*@null@*/ /*@only@*/ yasm_listfmt * (*create)
+ (const char *in_filename, const char *obj_filename);
+
+ /** Module-level implementation of yasm_listfmt_destroy().
+ * Call yasm_listfmt_destroy() instead of calling this function.
+ */
+ void (*destroy) (/*@only@*/ yasm_listfmt *listfmt);
+
+ /** Module-level implementation of yasm_listfmt_output().
+ * Call yasm_listfmt_output() instead of calling this function.
+ */
+ void (*output) (yasm_listfmt *listfmt, FILE *f, yasm_linemap *linemap,
+ yasm_arch *arch);
+} yasm_listfmt_module;
+
+/** Get the keyword used to select a list format.
+ * \param listfmt list format
+ * \return keyword
+ */
+const char *yasm_listfmt_keyword(const yasm_listfmt *listfmt);
+
+/** Initialize list format for use. Must call before any other list
+ * format functions. The filenames are provided solely for informational
+ * purposes.
+ * \param module list format module
+ * \param in_filename primary input filename
+ * \param obj_filename object filename
+ * \return NULL if object format does not provide needed support.
+ */
+/*@null@*/ /*@only@*/ yasm_listfmt *yasm_listfmt_create
+ (const yasm_listfmt_module *module, const char *in_filename,
+ const char *obj_filename);
+
+/** Cleans up any allocated list format memory.
+ * \param listfmt list format
+ */
+void yasm_listfmt_destroy(/*@only@*/ yasm_listfmt *listfmt);
+
+/** Write out list to the list file.
+ * This function may call all read-only yasm_* functions as necessary.
+ * \param listfmt list format
+ * \param f output list file
+ * \param linemap line mapping repository
+ * \param arch architecture
+ */
+void yasm_listfmt_output(yasm_listfmt *listfmt, FILE *f,
+ yasm_linemap *linemap, yasm_arch *arch);
+
+#ifndef YASM_DOXYGEN
+
+/* Inline macro implementations for listfmt functions */
+
+#define yasm_listfmt_keyword(listfmt) \
+ (((yasm_listfmt_base *)listfmt)->module->keyword)
+
+#define yasm_listfmt_create(module, in_filename, obj_filename) \
+ module->create(in_filename, obj_filename)
+
+#define yasm_listfmt_destroy(listfmt) \
+ ((yasm_listfmt_base *)listfmt)->module->destroy(listfmt)
+
+#define yasm_listfmt_output(listfmt, f, linemap, a) \
+ ((yasm_listfmt_base *)listfmt)->module->output(listfmt, f, linemap, a)
+
+#endif
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/md5.c b/contrib/tools/yasm/libyasm/md5.c
new file mode 100644
index 0000000000..b009842f5c
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/md5.c
@@ -0,0 +1,309 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
+ not require an integer type which is exactly 32 bits. This work
+ draws on the changes for the same purpose by Tatu Ylonen
+ <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
+ that code, there is no copyright issue. I hereby disclaim
+ copyright in any changes I have made; this code remains in the
+ public domain. */
+
+/* Note regarding cvs_* namespace: this avoids potential conflicts
+ with libraries such as some versions of Kerberos. No particular
+ need to worry about whether the system supplies an MD5 library, as
+ this file is only about 3k of object code. */
+
+#include <util.h>
+
+#include "md5.h"
+
+/* Little-endian byte-swapping routines. Note that these do not
+ depend on the size of datatypes such as cvs_uint32, nor do they require
+ us to detect the endianness of the machine we are running on. It
+ is possible they should be macros for speed, but I would be
+ surprised if they were a performance bottleneck for MD5. */
+
+static unsigned long
+getu32(const unsigned char *addr)
+{
+ return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
+ | addr[1]) << 8 | addr[0];
+}
+
+static void
+putu32(unsigned long data, unsigned char *addr)
+{
+ addr[0] = (unsigned char)data;
+ addr[1] = (unsigned char)(data >> 8);
+ addr[2] = (unsigned char)(data >> 16);
+ addr[3] = (unsigned char)(data >> 24);
+}
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+yasm_md5_init(yasm_md5_context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+yasm_md5_update(yasm_md5_context *ctx, unsigned char const *buf,
+ unsigned long len)
+{
+ unsigned long t;
+
+ /* Update bitcount */
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = (t + ((unsigned long)len << 3)) & 0xffffffff) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if ( t ) {
+ unsigned char *p = ctx->in + t;
+
+ t = 64-t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ yasm_md5_transform (ctx->buf, ctx->in);
+ buf += t;
+ len -= t;
+ }
+
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ yasm_md5_transform (ctx->buf, ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+yasm_md5_final(unsigned char digest[16], yasm_md5_context *ctx)
+{
+ unsigned count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ yasm_md5_transform (ctx->buf, ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count-8);
+ }
+
+ /* Append length in bits and transform */
+ putu32(ctx->bits[0], ctx->in + 56);
+ putu32(ctx->bits[1], ctx->in + 60);
+
+ yasm_md5_transform (ctx->buf, ctx->in);
+ putu32(ctx->buf[0], digest);
+ putu32(ctx->buf[1], digest + 4);
+ putu32(ctx->buf[2], digest + 8);
+ putu32(ctx->buf[3], digest + 12);
+ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
+}
+
+#ifndef ASM_MD5
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void
+yasm_md5_transform(unsigned long buf[4], const unsigned char inraw[64])
+{
+ unsigned long a, b, c, d;
+ unsigned long in[16];
+ int i;
+
+ for (i = 0; i < 16; ++i)
+ in[i] = getu32 (inraw + 4 * i);
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+#endif
+
+#ifdef TEST
+/* Simple test program. Can use it to manually run the tests from
+ RFC1321 for example. */
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+ yasm_md5_context context;
+ unsigned char checksum[16];
+ int i;
+ int j;
+
+ if (argc < 2)
+ {
+ fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
+ exit (1);
+ }
+ for (j = 1; j < argc; ++j)
+ {
+ printf ("MD5 (\"%s\") = ", argv[j]);
+ yasm_md5_init (&context);
+ yasm_md5_update (&context, argv[j], strlen (argv[j]));
+ yasm_md5_final (checksum, &context);
+ for (i = 0; i < 16; i++)
+ {
+ printf ("%02x", (unsigned int) checksum[i]);
+ }
+ printf ("\n");
+ }
+ return 0;
+}
+#endif /* TEST */
diff --git a/contrib/tools/yasm/libyasm/md5.h b/contrib/tools/yasm/libyasm/md5.h
new file mode 100644
index 0000000000..7872fda7a1
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/md5.h
@@ -0,0 +1,32 @@
+/* See md5.c for explanation and copyright information. */
+
+#ifndef YASM_MD5_H
+#define YASM_MD5_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/* Unlike previous versions of this code, uint32 need not be exactly
+ 32 bits, merely 32 bits or more. Choosing a data type which is 32
+ bits instead of 64 is not important; speed is considerably more
+ important. ANSI guarantees that "unsigned long" will be big enough,
+ and always using it seems to have few disadvantages. */
+
+typedef struct yasm_md5_context {
+ unsigned long buf[4];
+ unsigned long bits[2];
+ unsigned char in[64];
+} yasm_md5_context;
+
+YASM_LIB_DECL
+void yasm_md5_init(yasm_md5_context *context);
+YASM_LIB_DECL
+void yasm_md5_update(yasm_md5_context *context, unsigned char const *buf,
+ unsigned long len);
+YASM_LIB_DECL
+void yasm_md5_final(unsigned char digest[16], yasm_md5_context *context);
+YASM_LIB_DECL
+void yasm_md5_transform(unsigned long buf[4], const unsigned char in[64]);
+
+#endif /* !YASM_MD5_H */
diff --git a/contrib/tools/yasm/libyasm/mergesort.c b/contrib/tools/yasm/libyasm/mergesort.c
new file mode 100644
index 0000000000..3eeaa8273b
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/mergesort.c
@@ -0,0 +1,361 @@
+/*
+ * mergesort() implementation for systems that don't have it.
+ *
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Peter McIlroy.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND 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 REGENTS OR 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 "util.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)merge.c 8.2 (Berkeley) 2/14/94";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef HAVE_MERGESORT
+#undef yasm__mergesort
+#endif
+
+#ifndef HAVE_MERGESORT
+/*
+ * Hybrid exponential search/linear search merge sort with hybrid
+ * natural/pairwise first pass. Requires about .3% more comparisons
+ * for random data than LSMS with pairwise first pass alone.
+ * It works for objects as small as two bytes.
+ */
+
+#define NATURAL
+#define THRESHOLD 16 /* Best choice for natural merge cut-off. */
+
+/* #define NATURAL to get hybrid natural merge.
+ * (The default is pairwise merging.)
+ */
+
+#include <errno.h>
+#include <string.h>
+
+static void setup(unsigned char *, unsigned char *, size_t, size_t,
+ int (*)(const void *, const void *));
+static void insertionsort(unsigned char *, size_t, size_t,
+ int (*)(const void *, const void *));
+
+#define ISIZE sizeof(int)
+#define PSIZE sizeof(unsigned char *)
+#define ICOPY_LIST(src, dst, last) \
+ do \
+ *(int*)dst = *(int*)src, src += ISIZE, dst += ISIZE; \
+ while(src < last)
+#define ICOPY_ELT(src, dst, i) \
+ do \
+ *(int*) dst = *(int*) src, src += ISIZE, dst += ISIZE; \
+ while (i -= ISIZE)
+
+#define CCOPY_LIST(src, dst, last) \
+ do \
+ *dst++ = *src++; \
+ while (src < last)
+#define CCOPY_ELT(src, dst, i) \
+ do \
+ *dst++ = *src++; \
+ while (i -= 1)
+
+/*
+ * Find the next possible pointer head. (Trickery for forcing an array
+ * to do double duty as a linked list when objects do not align with word
+ * boundaries.
+ */
+/* Assumption: PSIZE is a power of 2. */
+#define EVAL(p) (unsigned char **) \
+ ((unsigned char *)0 + \
+ (((unsigned char *)p + PSIZE - 1 - (unsigned char *) 0) & ~(PSIZE - 1)))
+#endif /*HAVE_MERGESORT*/
+
+/*
+ * Arguments are as for qsort.
+ */
+int
+yasm__mergesort(void *base, size_t nmemb, size_t size,
+ int (*cmp)(const void *, const void *))
+{
+#ifdef HAVE_MERGESORT
+ return mergesort(base, nmemb, size, cmp);
+#else
+ size_t i;
+ int sense;
+ int big, iflag;
+ unsigned char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
+ unsigned char *list2, *list1, *p2, *p, *last, **p1;
+
+ if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */
+#ifdef EINVAL
+ errno = EINVAL;
+#endif
+ return (-1);
+ }
+
+ if (nmemb == 0)
+ return (0);
+
+ /*
+ * XXX
+ * Stupid subtraction for the Cray.
+ */
+ iflag = 0;
+ if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
+ iflag = 1;
+
+ if ((list2 = yasm_xmalloc(nmemb * size + PSIZE)) == NULL)
+ return (-1);
+
+ list1 = base;
+ setup(list1, list2, nmemb, size, cmp);
+ last = list2 + nmemb * size;
+ i = 0;
+ big = 0;
+ while (*EVAL(list2) != last) {
+ l2 = list1;
+ p1 = EVAL(list1);
+ for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) {
+ p2 = *EVAL(p2);
+ f1 = l2;
+ f2 = l1 = list1 + (p2 - list2);
+ if (p2 != last)
+ p2 = *EVAL(p2);
+ l2 = list1 + (p2 - list2);
+ while (f1 < l1 && f2 < l2) {
+ if ((*cmp)(f1, f2) <= 0) {
+ q = f2;
+ b = f1, t = l1;
+ sense = -1;
+ } else {
+ q = f1;
+ b = f2, t = l2;
+ sense = 0;
+ }
+ if (!big) { /* here i = 0 */
+ while ((b += size) < t && cmp(q, b) >sense)
+ if (++i == 6) {
+ big = 1;
+ goto EXPONENTIAL;
+ }
+ } else {
+EXPONENTIAL: for (i = size; ; i <<= 1)
+ if ((p = (b + i)) >= t) {
+ if ((p = t - size) > b &&
+ (*cmp)(q, p) <= sense)
+ t = p;
+ else
+ b = p;
+ break;
+ } else if ((*cmp)(q, p) <= sense) {
+ t = p;
+ if (i == size)
+ big = 0;
+ goto FASTCASE;
+ } else
+ b = p;
+ while (t > b+size) {
+ i = (((t - b) / size) >> 1) * size;
+ if ((*cmp)(q, p = b + i) <= sense)
+ t = p;
+ else
+ b = p;
+ }
+ goto COPY;
+FASTCASE: while (i > size)
+ if ((*cmp)(q,
+ p = b + (i >>= 1)) <= sense)
+ t = p;
+ else
+ b = p;
+COPY: b = t;
+ }
+ i = size;
+ if (q == f1) {
+ if (iflag) {
+ ICOPY_LIST(f2, tp2, b);
+ ICOPY_ELT(f1, tp2, i);
+ } else {
+ CCOPY_LIST(f2, tp2, b);
+ CCOPY_ELT(f1, tp2, i);
+ }
+ } else {
+ if (iflag) {
+ ICOPY_LIST(f1, tp2, b);
+ ICOPY_ELT(f2, tp2, i);
+ } else {
+ CCOPY_LIST(f1, tp2, b);
+ CCOPY_ELT(f2, tp2, i);
+ }
+ }
+ }
+ if (f2 < l2) {
+ if (iflag)
+ ICOPY_LIST(f2, tp2, l2);
+ else
+ CCOPY_LIST(f2, tp2, l2);
+ } else if (f1 < l1) {
+ if (iflag)
+ ICOPY_LIST(f1, tp2, l1);
+ else
+ CCOPY_LIST(f1, tp2, l1);
+ }
+ *p1 = l2;
+ }
+ tp2 = list1; /* swap list1, list2 */
+ list1 = list2;
+ list2 = tp2;
+ last = list2 + nmemb*size;
+ }
+ if (base == list2) {
+ memmove(list2, list1, nmemb*size);
+ list2 = list1;
+ }
+ yasm_xfree(list2);
+ return (0);
+#endif /*HAVE_MERGESORT*/
+}
+
+#ifndef HAVE_MERGESORT
+
+#define swap(a, b) { \
+ s = b; \
+ i = size; \
+ do { \
+ tmp = *a; *a++ = *s; *s++ = tmp; \
+ } while (--i); \
+ a -= size; \
+ }
+#define reverse(bot, top) { \
+ s = top; \
+ do { \
+ i = size; \
+ do { \
+ tmp = *bot; *bot++ = *s; *s++ = tmp; \
+ } while (--i); \
+ s -= size2; \
+ } while(bot < s); \
+}
+
+/*
+ * Optional hybrid natural/pairwise first pass. Eats up list1 in runs of
+ * increasing order, list2 in a corresponding linked list. Checks for runs
+ * when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL
+ * is defined. Otherwise simple pairwise merging is used.)
+ */
+void
+setup(unsigned char *list1, unsigned char *list2, size_t n, size_t size,
+ int (*cmp)(const void *, const void *))
+{
+ size_t i;
+ unsigned int tmp;
+ int length, sense;
+ size_t size2;
+ unsigned char *f1, *f2, *s, *l2, *last, *p2;
+
+ size2 = size*2;
+ if (n <= 5) {
+ insertionsort(list1, n, size, cmp);
+ *EVAL(list2) = (unsigned char*) list2 + n*size;
+ return;
+ }
+ /*
+ * Avoid running pointers out of bounds; limit n to evens
+ * for simplicity.
+ */
+ i = 4 + (n & 1);
+ insertionsort(list1 + (n - i) * size, i, size, cmp);
+ last = list1 + size * (n - i);
+ *EVAL(list2 + (last - list1)) = list2 + n * size;
+
+#ifdef NATURAL
+ p2 = list2;
+ f1 = list1;
+ sense = (cmp(f1, f1 + size) > 0);
+ for (; f1 < last; sense = !sense) {
+ length = 2;
+ /* Find pairs with same sense. */
+ for (f2 = f1 + size2; f2 < last; f2 += size2) {
+ if ((cmp(f2, f2+ size) > 0) != sense)
+ break;
+ length += 2;
+ }
+ if (length < THRESHOLD) { /* Pairwise merge */
+ do {
+ p2 = *EVAL(p2) = f1 + size2 - list1 + list2;
+ if (sense > 0)
+ swap (f1, f1 + size);
+ } while ((f1 += size2) < f2);
+ } else { /* Natural merge */
+ l2 = f2;
+ for (f2 = f1 + size2; f2 < l2; f2 += size2) {
+ if ((cmp(f2-size, f2) > 0) != sense) {
+ p2 = *EVAL(p2) = f2 - list1 + list2;
+ if (sense > 0)
+ reverse(f1, f2-size);
+ f1 = f2;
+ }
+ }
+ if (sense > 0)
+ reverse (f1, f2-size);
+ f1 = f2;
+ if (f2 < last || cmp(f2 - size, f2) > 0)
+ p2 = *EVAL(p2) = f2 - list1 + list2;
+ else
+ p2 = *EVAL(p2) = list2 + n*size;
+ }
+ }
+#else /* pairwise merge only. */
+ for (f1 = list1, p2 = list2; f1 < last; f1 += size2) {
+ p2 = *EVAL(p2) = p2 + size2;
+ if (cmp (f1, f1 + size) > 0)
+ swap(f1, f1 + size);
+ }
+#endif /* NATURAL */
+}
+
+/*
+ * This is to avoid out-of-bounds addresses in sorting the
+ * last 4 elements.
+ */
+static void
+insertionsort(unsigned char *a, size_t n, size_t size,
+ int (*cmp)(const void *, const void *))
+{
+ unsigned char *ai, *s, *t, *u, tmp;
+ size_t i;
+
+ for (ai = a+size; --n >= 1; ai += size)
+ for (t = ai; t > a; t -= size) {
+ u = t - size;
+ if (cmp(u, t) <= 0)
+ break;
+ swap(u, t);
+ }
+}
+#endif /*HAVE_MERGESORT*/
diff --git a/contrib/tools/yasm/libyasm/module.h b/contrib/tools/yasm/libyasm/module.h
new file mode 100644
index 0000000000..220017deec
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/module.h
@@ -0,0 +1,82 @@
+/*
+ * YASM module loader header file
+ *
+ * Copyright (C) 2002-2007 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.
+ */
+#ifndef YASM_MODULE_H
+#define YASM_MODULE_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+typedef enum yasm_module_type {
+ YASM_MODULE_ARCH = 0,
+ YASM_MODULE_DBGFMT,
+ YASM_MODULE_OBJFMT,
+ YASM_MODULE_LISTFMT,
+ YASM_MODULE_PARSER,
+ YASM_MODULE_PREPROC
+} yasm_module_type;
+
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ void *yasm_load_module
+ (yasm_module_type type, const char *keyword);
+
+#define yasm_load_arch(keyword) \
+ yasm_load_module(YASM_MODULE_ARCH, keyword)
+#define yasm_load_dbgfmt(keyword) \
+ yasm_load_module(YASM_MODULE_DBGFMT, keyword)
+#define yasm_load_objfmt(keyword) \
+ yasm_load_module(YASM_MODULE_OBJFMT, keyword)
+#define yasm_load_listfmt(keyword) \
+ yasm_load_module(YASM_MODULE_LISTFMT, keyword)
+#define yasm_load_parser(keyword) \
+ yasm_load_module(YASM_MODULE_PARSER, keyword)
+#define yasm_load_preproc(keyword) \
+ yasm_load_module(YASM_MODULE_PREPROC, keyword)
+
+YASM_LIB_DECL
+void yasm_list_modules
+ (yasm_module_type type,
+ void (*printfunc) (const char *name, const char *keyword));
+
+#define yasm_list_arch(func) \
+ yasm_list_modules(YASM_MODULE_ARCH, func)
+#define yasm_list_dbgfmt(func) \
+ yasm_list_modules(YASM_MODULE_DBGFMT, func)
+#define yasm_list_objfmt(func) \
+ yasm_list_modules(YASM_MODULE_OBJFMT, func)
+#define yasm_list_listfmt(func) \
+ yasm_list_modules(YASM_MODULE_LISTFMT, func)
+#define yasm_list_parser(func) \
+ yasm_list_modules(YASM_MODULE_PARSER, func)
+#define yasm_list_preproc(func) \
+ yasm_list_modules(YASM_MODULE_PREPROC, func)
+
+YASM_LIB_DECL
+void yasm_register_module(yasm_module_type type, const char *keyword,
+ void *data);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/objfmt.h b/contrib/tools/yasm/libyasm/objfmt.h
new file mode 100644
index 0000000000..a8b5f8a161
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/objfmt.h
@@ -0,0 +1,225 @@
+/**
+ * \file libyasm/objfmt.h
+ * \brief YASM object format module interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_OBJFMT_H
+#define YASM_OBJFMT_H
+
+#ifndef YASM_DOXYGEN
+/** Base #yasm_objfmt structure. Must be present as the first element in any
+ * #yasm_objfmt implementation.
+ */
+typedef struct yasm_objfmt_base {
+ /** #yasm_objfmt_module implementation for this object format. */
+ const struct yasm_objfmt_module *module;
+} yasm_objfmt_base;
+#endif
+
+/** Object format module interface. */
+struct yasm_objfmt_module {
+ /** One-line description of the object format. */
+ const char *name;
+
+ /** Keyword used to select object format. */
+ const char *keyword;
+
+ /** Default output file extension (without the '.').
+ * NULL means no extension, with no '.', while "" includes the '.'.
+ */
+ /*@null@*/ const char *extension;
+
+ /** Default (starting) x86 BITS setting. This only appies to the x86
+ * architecture; other architectures ignore this setting.
+ */
+ const unsigned char default_x86_mode_bits;
+
+ /** If @ signs should be legal in identifiers. */
+ const unsigned char id_at_ok;
+
+ /** NULL-terminated list of debug format (yasm_dbgfmt) keywords that are
+ * valid to use with this object format. The null debug format
+ * (null_dbgfmt, "null") should always be in this list so it's possible to
+ * have no debug output.
+ */
+ const char **dbgfmt_keywords;
+
+ /** Default debug format keyword (set even if there's only one available to
+ * use).
+ */
+ const char *default_dbgfmt_keyword;
+
+ /** NULL-terminated list of directives. NULL if none. */
+ /*@null@*/ const yasm_directive *directives;
+
+ /** NULL-terminated list of standard macro lookups. NULL if none. */
+ const yasm_stdmac *stdmacs;
+
+ /** Create object format.
+ * Module-level implementation of yasm_objfmt_create().
+ * Call yasm_objfmt_create() instead of calling this function.
+ * \param object object
+ * \param a architecture in use
+ * \return NULL if architecture/machine combination not supported.
+ */
+ /*@null@*/ /*@only@*/ yasm_objfmt * (*create) (yasm_object *object);
+
+ /** Module-level implementation of yasm_objfmt_output().
+ * Call yasm_objfmt_output() instead of calling this function.
+ */
+ void (*output) (yasm_object *o, FILE *f, int all_syms,
+ yasm_errwarns *errwarns);
+
+ /** Module-level implementation of yasm_objfmt_destroy().
+ * Call yasm_objfmt_destroy() instead of calling this function.
+ */
+ void (*destroy) (/*@only@*/ yasm_objfmt *objfmt);
+
+ /** Module-level implementation of yasm_objfmt_add_default_section().
+ * Call yasm_objfmt_add_default_section() instead of calling this function.
+ */
+ yasm_section * (*add_default_section) (yasm_object *object);
+
+ /** Module-level implementation of yasm_objfmt_init_new_section().
+ * Call yasm_objfmt_init_new_section() instead of calling this function.
+ */
+ void (*init_new_section) (yasm_section *section, unsigned long line);
+
+ /** Module-level implementation of yasm_objfmt_section_switch().
+ * Call yasm_objfmt_section_switch() instead of calling this function.
+ */
+ /*@observer@*/ /*@null@*/ yasm_section *
+ (*section_switch)(yasm_object *object, yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *objext_valparams,
+ unsigned long line);
+
+ /** Module-level implementation of yasm_objfmt_get_special_sym().
+ * Call yasm_objfmt_get_special_sym() instead of calling this function.
+ */
+ /*@observer@*/ /*@null@*/ yasm_symrec *
+ (*get_special_sym)(yasm_object *object, const char *name,
+ const char *parser);
+
+ /**
+ * --replace params
+ */
+ const char** replace_map;
+ /**
+ * Number of elements in replace_map
+ */
+ int replace_map_size;
+};
+
+/** Create object format.
+ * \param module object format module
+ * \param object object
+ * \return NULL if architecture/machine combination not supported.
+ */
+/*@null@*/ /*@only@*/ yasm_objfmt *yasm_objfmt_create
+ (const yasm_objfmt_module *module, yasm_object *object);
+
+/** Write out (post-optimized) sections to the object file.
+ * This function may call yasm_symrec_* functions as necessary (including
+ * yasm_symrec_traverse()) to retrieve symbolic information.
+ * \param object object
+ * \param f output object file
+ * \param all_syms if nonzero, all symbols should be included in
+ * the object file
+ * \param errwarns error/warning set
+ * \note Errors and warnings are stored into errwarns.
+ */
+void yasm_objfmt_output(yasm_object *object, FILE *f, int all_syms,
+ yasm_errwarns *errwarns);
+
+/** Cleans up any allocated object format memory.
+ * \param objfmt object format
+ */
+void yasm_objfmt_destroy(/*@only@*/ yasm_objfmt *objfmt);
+
+/** Add a default section to an object.
+ * \param object object
+ * \return Default section.
+ */
+yasm_section *yasm_objfmt_add_default_section(yasm_object *object);
+
+/** Initialize the object-format specific portion of a section. Called
+ * by yasm_object_get_general(); in general should not be directly called.
+ * \param section section
+ * \param line virtual line (from yasm_linemap)
+ */
+void yasm_objfmt_init_new_section(yasm_object *object, unsigned long line);
+
+/** Switch object file sections. The first val of the valparams should
+ * be the section name. Calls yasm_object_get_general() to actually get
+ * the section.
+ * \param object object
+ * \param valparams value/parameters
+ * \param objext_valparams object format-specific value/parameters
+ * \param line virtual line (from yasm_linemap)
+ * \return NULL on error, otherwise new section.
+ */
+/*@observer@*/ /*@null@*/ yasm_section *yasm_objfmt_section_switch
+ (yasm_object *object, yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *objext_valparams, unsigned long line);
+
+/** Get a special symbol. Special symbols are generally used to generate
+ * special relocation types via the WRT mechanism.
+ * \param object object
+ * \param name symbol name (not including any parser-specific prefix)
+ * \param parser parser keyword
+ * \return NULL if unrecognized, otherwise special symbol.
+ */
+/*@observer@*/ /*@null@*/ yasm_symrec *yasm_objfmt_get_special_sym
+ (yasm_object *object, const char *name, const char *parser);
+
+#ifndef YASM_DOXYGEN
+
+/* Inline macro implementations for objfmt functions */
+
+#define yasm_objfmt_create(module, object) module->create(object)
+
+#define yasm_objfmt_output(object, f, all_syms, ews) \
+ ((yasm_objfmt_base *)((object)->objfmt))->module->output \
+ (object, f, all_syms, ews)
+#define yasm_objfmt_destroy(objfmt) \
+ ((yasm_objfmt_base *)objfmt)->module->destroy(objfmt)
+#define yasm_objfmt_section_switch(object, vpms, oe_vpms, line) \
+ ((yasm_objfmt_base *)((object)->objfmt))->module->section_switch \
+ (object, vpms, oe_vpms, line)
+#define yasm_objfmt_add_default_section(object) \
+ ((yasm_objfmt_base *)((object)->objfmt))->module->add_default_section \
+ (object)
+#define yasm_objfmt_init_new_section(section, line) \
+ ((yasm_objfmt_base *)((object)->objfmt))->module->init_new_section \
+ (section, line)
+#define yasm_objfmt_get_special_sym(object, name, parser) \
+ ((yasm_objfmt_base *)((object)->objfmt))->module->get_special_sym \
+ (object, name, parser)
+
+#endif
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/parser.h b/contrib/tools/yasm/libyasm/parser.h
new file mode 100644
index 0000000000..93d4d33232
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/parser.h
@@ -0,0 +1,67 @@
+/**
+ * \file libyasm/parser.h
+ * \brief YASM parser module interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 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.
+ * \endlicense
+ */
+#ifndef YASM_PARSER_H
+#define YASM_PARSER_H
+
+/** YASM parser module interface. The "front end" of the assembler. */
+typedef struct yasm_parser_module {
+ /** One-line description of the parser */
+ const char *name;
+
+ /** Keyword used to select parser on the command line */
+ const char *keyword;
+
+ /** NULL-terminated list of preprocessors that are valid to use with this
+ * parser. The raw preprocessor (raw_preproc) should always be in this
+ * list so it's always possible to have no preprocessing done.
+ */
+ const char **preproc_keywords;
+
+ /** Default preprocessor. */
+ const char *default_preproc_keyword;
+
+ /** NULL-terminated list of standard macro lookups. NULL if none. */
+ const yasm_stdmac *stdmacs;
+
+ /** Parse a source file into an object.
+ * \param object object to parse into (already created)
+ * \param pp preprocessor
+ * \param save_input nonzero if the parser should save the original
+ * lines of source into the object's linemap (via
+ * yasm_linemap_add_data()).
+ * \param errwarns error/warning set
+ * \note Parse errors and warnings are stored into errwarns.
+ */
+ void (*do_parse)
+ (yasm_object *object, yasm_preproc *pp, int save_input,
+ yasm_linemap *linemap, yasm_errwarns *errwarns);
+} yasm_parser_module;
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/phash.c b/contrib/tools/yasm/libyasm/phash.c
new file mode 100644
index 0000000000..29e073aae1
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/phash.c
@@ -0,0 +1,268 @@
+/* Modified for use with yasm by Peter Johnson. */
+#include "util.h"
+
+/*
+--------------------------------------------------------------------
+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); \
+ a &= 0xffffffff; \
+ b -= c; b -= a; b ^= (a<<8); \
+ b &= 0xffffffff; \
+ c -= a; c -= b; c ^= (b>>13); \
+ c &= 0xffffffff; \
+ a -= b; a -= c; a ^= (c>>12); \
+ a &= 0xffffffff; \
+ b -= c; b -= a; b ^= (a<<16); \
+ b &= 0xffffffff; \
+ c -= a; c -= b; c ^= (b>>5); \
+ c &= 0xffffffff; \
+ a -= b; a -= c; a ^= (c>>3); \
+ a &= 0xffffffff; \
+ b -= c; b -= a; b ^= (a<<10); \
+ b &= 0xffffffff; \
+ c -= a; c -= b; c ^= (b>>15); \
+ c &= 0xffffffff; \
+}
+
+/*
+--------------------------------------------------------------------
+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 size_t length, /* the length of the key */
+ register unsigned long level) /* the previous hash, or an arbitrary value */
+{
+ unsigned long a,b,c;
+ size_t len;
+ 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));
+ a &= 0xffffffff;
+ b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
+ b &= 0xffffffff;
+ c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
+ c &= 0xffffffff;
+ mix(a,b,c);
+ k += 12; len -= 12;
+ }
+
+ /*------------------------------------- handle the last 11 bytes */
+ c += (ub4)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);
+ c &= 0xffffffff;
+ /* 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];
+ b &= 0xffffffff;
+ 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];
+ a &= 0xffffffff;
+ /* 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 char *sk,
+ register size_t len,
+ register unsigned long *state)
+{
+ unsigned long a,b,c,d,e,f,g,h;
+ size_t length;
+ const unsigned char *k = (const unsigned char *)sk;
+
+ /* 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 += (ub4)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;
+}
diff --git a/contrib/tools/yasm/libyasm/phash.h b/contrib/tools/yasm/libyasm/phash.h
new file mode 100644
index 0000000000..2273a5df20
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/phash.h
@@ -0,0 +1,19 @@
+/* Modified for use with yasm by Peter Johnson. */
+/*
+------------------------------------------------------------------------------
+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
+------------------------------------------------------------------------------
+*/
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+YASM_LIB_DECL
+unsigned long phash_lookup(const char *k, size_t length,
+ unsigned long level);
+YASM_LIB_DECL
+void phash_checksum(const char *k, size_t length, unsigned long *state);
diff --git a/contrib/tools/yasm/libyasm/preproc.h b/contrib/tools/yasm/libyasm/preproc.h
new file mode 100644
index 0000000000..751b19e4b0
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/preproc.h
@@ -0,0 +1,210 @@
+/**
+ * \file libyasm/preproc.h
+ * \brief YASM preprocessor module interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 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.
+ * \endlicense
+ */
+#ifndef YASM_PREPROC_H
+#define YASM_PREPROC_H
+
+#ifndef YASM_DOXYGEN
+/** Base #yasm_preproc structure. Must be present as the first element in any
+ * #yasm_preproc implementation.
+ */
+typedef struct yasm_preproc_base {
+ /** #yasm_preproc_module implementation for this preprocessor. */
+ const struct yasm_preproc_module *module;
+} yasm_preproc_base;
+#endif
+
+/** YASM preprocesor module interface. */
+typedef struct yasm_preproc_module {
+ /** One-line description of the preprocessor. */
+ const char *name;
+
+ /** Keyword used to select preprocessor on the command line. */
+ const char *keyword;
+
+ /** Create preprocessor.
+ * Module-level implementation of yasm_preproc_create().
+ * Call yasm_preproc_create() instead of calling this function.
+ *
+ * \param in_filename initial starting filename, or "-" to read from
+ * stdin
+ * \param symtab symbol table (may be NULL if none)
+ * \param lm line mapping repository
+ * \param errwarns error/warnning set.
+ * \return New preprocessor.
+ *
+ * \note Any preprocessor errors and warnings are stored into errwarns.
+ */
+ /*@only@*/ yasm_preproc * (*create) (const char *in_filename,
+ yasm_symtab *symtab,
+ yasm_linemap *lm,
+ yasm_errwarns *errwarns);
+
+ /** Module-level implementation of yasm_preproc_destroy().
+ * Call yasm_preproc_destroy() instead of calling this function.
+ */
+ void (*destroy) (/*@only@*/ yasm_preproc *preproc);
+
+ /** Module-level implementation of yasm_preproc_get_line().
+ * Call yasm_preproc_get_line() instead of calling this function.
+ */
+ char * (*get_line) (yasm_preproc *preproc);
+
+ /** Module-level implementation of yasm_preproc_get_included_file().
+ * Call yasm_preproc_get_included_file() instead of calling this function.
+ */
+ size_t (*get_included_file) (yasm_preproc *preproc, /*@out@*/ char *buf,
+ size_t max_size);
+
+ /** Module-level implementation of yasm_preproc_add_include_file().
+ * Call yasm_preproc_add_include_file() instead of calling this function.
+ */
+ void (*add_include_file) (yasm_preproc *preproc, const char *filename);
+
+ /** Module-level implementation of yasm_preproc_predefine_macro().
+ * Call yasm_preproc_predefine_macro() instead of calling this function.
+ */
+ void (*predefine_macro) (yasm_preproc *preproc, const char *macronameval);
+
+ /** Module-level implementation of yasm_preproc_undefine_macro().
+ * Call yasm_preproc_undefine_macro() instead of calling this function.
+ */
+ void (*undefine_macro) (yasm_preproc *preproc, const char *macroname);
+
+ /** Module-level implementation of yasm_preproc_builtin_define().
+ * Call yasm_preproc_builtin_define() instead of calling this function.
+ */
+ void (*define_builtin) (yasm_preproc *preproc, const char *macronameval);
+
+ /** Module-level implementation of yasm_preproc_add_standard().
+ * Call yasm_preproc_add_standard() instead of calling this function.
+ */
+ void (*add_standard) (yasm_preproc *preproc, const char **macros);
+} yasm_preproc_module;
+
+/** Initialize preprocessor.
+ * The preprocessor needs access to the object format module to find out
+ * any output format specific macros.
+ * \param module preprocessor module
+ * \param in_filename initial starting filename, or "-" to read from stdin
+ * \param symtab symbol table (may be NULL if none)
+ * \param lm line mapping repository
+ * \param errwarns error/warning set
+ * \return New preprocessor.
+ * \note Errors/warnings are stored into errwarns.
+ */
+/*@only@*/ yasm_preproc *yasm_preproc_create
+ (yasm_preproc_module *module, const char *in_filename,
+ yasm_symtab *symtab, yasm_linemap *lm, yasm_errwarns *errwarns);
+
+/** Cleans up any allocated preproc memory.
+ * \param preproc preprocessor
+ */
+void yasm_preproc_destroy(/*@only@*/ yasm_preproc *preproc);
+
+/** Gets a single line of preprocessed source code.
+ * \param preproc preprocessor
+ * \return Allocated line of code, without the trailing \n.
+ */
+char *yasm_preproc_get_line(yasm_preproc *preproc);
+
+/** Get the next filename included by the source code.
+ * \param preproc preprocessor
+ * \param buf destination buffer for filename
+ * \param max_size maximum number of bytes that can be returned in buf
+ * \return Actual number of bytes returned in buf.
+ */
+size_t yasm_preproc_get_included_file(yasm_preproc *preproc,
+ /*@out@*/ char *buf, size_t max_size);
+
+/** Pre-include a file.
+ * \param preproc preprocessor
+ * \param filename filename
+ */
+void yasm_preproc_add_include_file(yasm_preproc *preproc,
+ const char *filename);
+
+/** Pre-define a macro.
+ * \param preproc preprocessor
+ * \param macronameval "name=value" string
+ */
+void yasm_preproc_predefine_macro(yasm_preproc *preproc,
+ const char *macronameval);
+
+/** Un-define a macro.
+ * \param preproc preprocessor
+ * \param macroname macro name
+ */
+void yasm_preproc_undefine_macro(yasm_preproc *preproc, const char *macroname);
+
+/** Define a builtin macro, preprocessed before the "standard" macros.
+ * \param preproc preprocessor
+ * \param macronameval "name=value" string
+ */
+void yasm_preproc_define_builtin(yasm_preproc *preproc,
+ const char *macronameval);
+
+/** Define additional standard macros, preprocessed after the builtins but
+ * prior to any user-defined macros.
+ * \param preproc preprocessor
+ * \param macros NULL-terminated array of macro strings
+ */
+void yasm_preproc_add_standard(yasm_preproc *preproc,
+ const char **macros);
+
+#ifndef YASM_DOXYGEN
+
+/* Inline macro implementations for preproc functions */
+
+#define yasm_preproc_create(module, in_filename, symtab, lm, ews) \
+ module->create(in_filename, symtab, lm, ews)
+
+#define yasm_preproc_destroy(preproc) \
+ ((yasm_preproc_base *)preproc)->module->destroy(preproc)
+#define yasm_preproc_get_line(preproc) \
+ ((yasm_preproc_base *)preproc)->module->get_line(preproc)
+#define yasm_preproc_get_included_file(preproc, buf, max_size) \
+ ((yasm_preproc_base *)preproc)->module->get_included_file(preproc, buf, max_size)
+#define yasm_preproc_add_include_file(preproc, filename) \
+ ((yasm_preproc_base *)preproc)->module->add_include_file(preproc, filename)
+#define yasm_preproc_predefine_macro(preproc, macronameval) \
+ ((yasm_preproc_base *)preproc)->module->predefine_macro(preproc, \
+ macronameval)
+#define yasm_preproc_undefine_macro(preproc, macroname) \
+ ((yasm_preproc_base *)preproc)->module->undefine_macro(preproc, macroname)
+#define yasm_preproc_define_builtin(preproc, macronameval) \
+ ((yasm_preproc_base *)preproc)->module->define_builtin(preproc, \
+ macronameval)
+#define yasm_preproc_add_standard(preproc, macros) \
+ ((yasm_preproc_base *)preproc)->module->add_standard(preproc, \
+ macros)
+
+#endif
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/replace_path.c b/contrib/tools/yasm/libyasm/replace_path.c
new file mode 100644
index 0000000000..0deba70a6b
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/replace_path.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1988, 1993, 2019
+ * The Regents of the University of California. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND 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 REGENTS OR 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 "util.h"
+
+char * yasm_replace_path(const char* replace_map[], int size, const char* str, int pref_len) {
+ int i;
+ for (i=0; i<size; i++) {
+ const char* pos = strchr(replace_map[i], '=');
+ if (!pos) {
+ continue;
+ }
+ int repl_size = pos - replace_map[i];
+ if (pref_len < repl_size) {
+ continue;
+ }
+ if (strncmp(replace_map[i], str, repl_size)) {
+ continue;
+ }
+ int subs_size = strlen(replace_map[i]) - (repl_size + 1);
+ int size = subs_size + pref_len - repl_size + 1;
+ char* out = yasm_xmalloc(size);
+ strncpy(out, pos + 1, subs_size);
+ strncpy(out + subs_size, str + repl_size, pref_len - repl_size);
+ out[size - 1] = '\0';
+ return out;
+ }
+ return yasm__xstrndup(str, pref_len);
+}
diff --git a/contrib/tools/yasm/libyasm/section.c b/contrib/tools/yasm/libyasm/section.c
new file mode 100644
index 0000000000..729d7770a4
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/section.c
@@ -0,0 +1,1585 @@
+/*
+ * Section utility functions
+ *
+ * Copyright (C) 2001-2007 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 "util.h"
+
+#include <limits.h>
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+#include "hamt.h"
+#include "valparam.h"
+#include "assocdat.h"
+
+#include "linemap.h"
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "value.h"
+#include "symrec.h"
+
+#include "bytecode.h"
+#include "arch.h"
+#include "section.h"
+
+#include "dbgfmt.h"
+#include "objfmt.h"
+
+#include "inttree.h"
+
+
+struct yasm_section {
+ /*@reldef@*/ STAILQ_ENTRY(yasm_section) link;
+
+ /*@dependent@*/ yasm_object *object; /* Pointer to parent object */
+
+ /*@owned@*/ char *name; /* strdup()'ed name (given by user) */
+
+ /* associated data; NULL if none */
+ /*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data;
+
+ unsigned long align; /* Section alignment */
+
+ unsigned long opt_flags; /* storage for optimizer flags */
+
+ int code; /* section contains code (instructions) */
+ int res_only; /* allow only resb family of bytecodes? */
+ int def; /* "default" section, e.g. not specified by
+ using section directive */
+
+ /* the bytecodes for the section's contents */
+ /*@reldef@*/ STAILQ_HEAD(yasm_bytecodehead, yasm_bytecode) bcs;
+
+ /* the relocations for the section */
+ /*@reldef@*/ STAILQ_HEAD(yasm_relochead, yasm_reloc) relocs;
+
+ void (*destroy_reloc) (/*@only@*/ void *reloc);
+};
+
+static void yasm_section_destroy(/*@only@*/ yasm_section *sect);
+
+/* Wrapper around directive for HAMT insertion */
+typedef struct yasm_directive_wrap {
+ const yasm_directive *directive;
+} yasm_directive_wrap;
+
+/*
+ * Standard "builtin" object directives.
+ */
+
+static void
+dir_extern(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ yasm_symrec *sym;
+ sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_EXTERN,
+ line);
+ if (objext_valparams) {
+ yasm_valparamhead *vps = yasm_vps_create();
+ *vps = *objext_valparams; /* structure copy */
+ yasm_vps_initialize(objext_valparams); /* don't double-free */
+ yasm_symrec_set_objext_valparams(sym, vps);
+ }
+}
+
+static void
+dir_global(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ yasm_symrec *sym;
+ sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_GLOBAL,
+ line);
+ if (objext_valparams) {
+ yasm_valparamhead *vps = yasm_vps_create();
+ *vps = *objext_valparams; /* structure copy */
+ yasm_vps_initialize(objext_valparams); /* don't double-free */
+ yasm_symrec_set_objext_valparams(sym, vps);
+ }
+}
+
+static void
+dir_common(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ yasm_valparam *vp2 = yasm_vps_next(vp);
+ yasm_expr *size = yasm_vp_expr(vp2, object->symtab, line);
+ yasm_symrec *sym;
+
+ if (!size) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("no size specified in %s declaration"), "COMMON");
+ return;
+ }
+ sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_COMMON,
+ line);
+ yasm_symrec_set_common_size(sym, size);
+ if (objext_valparams) {
+ yasm_valparamhead *vps = yasm_vps_create();
+ *vps = *objext_valparams; /* structure copy */
+ yasm_vps_initialize(objext_valparams); /* don't double-free */
+ yasm_symrec_set_objext_valparams(sym, vps);
+ }
+}
+
+static void
+dir_section(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_section *new_section =
+ yasm_objfmt_section_switch(object, valparams, objext_valparams, line);
+ if (new_section)
+ object->cur_section = new_section;
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("invalid argument to directive `%s'"), "SECTION");
+}
+
+static const yasm_directive object_directives[] = {
+ { ".extern", "gas", dir_extern, YASM_DIR_ID_REQUIRED },
+ { ".global", "gas", dir_global, YASM_DIR_ID_REQUIRED },
+ { ".globl", "gas", dir_global, YASM_DIR_ID_REQUIRED },
+ { "extern", "nasm", dir_extern, YASM_DIR_ID_REQUIRED },
+ { "global", "nasm", dir_global, YASM_DIR_ID_REQUIRED },
+ { "common", "nasm", dir_common, YASM_DIR_ID_REQUIRED },
+ { "section", "nasm", dir_section, YASM_DIR_ARG_REQUIRED },
+ { "segment", "nasm", dir_section, YASM_DIR_ARG_REQUIRED },
+ { NULL, NULL, NULL, 0 }
+};
+
+static void
+directive_level2_delete(/*@only@*/ void *data)
+{
+ yasm_xfree(data);
+}
+
+static void
+directive_level1_delete(/*@only@*/ void *data)
+{
+ HAMT_destroy(data, directive_level2_delete);
+}
+
+static void
+directives_add(yasm_object *object, /*@null@*/ const yasm_directive *dir)
+{
+ if (!dir)
+ return;
+
+ while (dir->name) {
+ HAMT *level2 = HAMT_search(object->directives, dir->parser);
+ int replace;
+ yasm_directive_wrap *wrap = yasm_xmalloc(sizeof(yasm_directive_wrap));
+
+ if (!level2) {
+ replace = 0;
+ level2 = HAMT_insert(object->directives, dir->parser,
+ HAMT_create(1, yasm_internal_error_),
+ &replace, directive_level1_delete);
+ }
+ replace = 0;
+ wrap->directive = dir;
+ HAMT_insert(level2, dir->name, wrap, &replace,
+ directive_level2_delete);
+ dir++;
+ }
+}
+
+/*@-compdestroy@*/
+yasm_object *
+yasm_object_create(const char *src_filename, const char *obj_filename,
+ /*@kept@*/ yasm_arch *arch,
+ const yasm_objfmt_module *objfmt_module,
+ const yasm_dbgfmt_module *dbgfmt_module)
+{
+ yasm_object *object = yasm_xmalloc(sizeof(yasm_object));
+ int matched, i;
+
+ object->src_filename = yasm__xstrdup(src_filename);
+ object->deb_filename = NULL;
+ object->obj_filename = yasm__xstrdup(obj_filename);
+
+ /* No prefix/suffix */
+ object->global_prefix = yasm__xstrdup("");
+ object->global_suffix = yasm__xstrdup("");
+
+ /* Create empty symbol table */
+ object->symtab = yasm_symtab_create();
+
+ /* Initialize sections linked list */
+ STAILQ_INIT(&object->sections);
+
+ /* Create directives HAMT */
+ object->directives = HAMT_create(1, yasm_internal_error_);
+
+ /* Initialize the target architecture */
+ object->arch = arch;
+
+ /* Initialize things to NULL in case of error */
+ object->dbgfmt = NULL;
+
+ /* Initialize the object format */
+ object->objfmt = yasm_objfmt_create(objfmt_module, object);
+ if (!object->objfmt) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("object format `%s' does not support architecture `%s' machine `%s'"),
+ objfmt_module->keyword, ((yasm_arch_base *)arch)->module->keyword,
+ yasm_arch_get_machine(arch));
+ goto error;
+ }
+
+ /* Get a fresh copy of objfmt_module as it may have changed. */
+ objfmt_module = ((yasm_objfmt_base *)object->objfmt)->module;
+
+ /* Add an initial "default" section to object */
+ object->cur_section = yasm_objfmt_add_default_section(object);
+
+ /* Check to see if the requested debug format is in the allowed list
+ * for the active object format.
+ */
+ matched = 0;
+ for (i=0; objfmt_module->dbgfmt_keywords[i]; i++) {
+ if (yasm__strcasecmp(objfmt_module->dbgfmt_keywords[i],
+ dbgfmt_module->keyword) == 0) {
+ matched = 1;
+ break;
+ }
+ }
+
+ if (!matched) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("`%s' is not a valid debug format for object format `%s'"),
+ dbgfmt_module->keyword, objfmt_module->keyword);
+ goto error;
+ }
+
+ /* Initialize the debug format */
+ object->dbgfmt = yasm_dbgfmt_create(dbgfmt_module, object);
+ if (!object->dbgfmt) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("debug format `%s' does not work with object format `%s'"),
+ dbgfmt_module->keyword, objfmt_module->keyword);
+ goto error;
+ }
+
+ /* Add directives to HAMT. Note ordering here determines priority. */
+ directives_add(object,
+ ((yasm_objfmt_base *)object->objfmt)->module->directives);
+ directives_add(object,
+ ((yasm_dbgfmt_base *)object->dbgfmt)->module->directives);
+ directives_add(object,
+ ((yasm_arch_base *)object->arch)->module->directives);
+ directives_add(object, object_directives);
+
+ return object;
+
+error:
+ yasm_object_destroy(object);
+ return NULL;
+}
+/*@=compdestroy@*/
+
+/*@-onlytrans@*/
+yasm_section *
+yasm_object_get_general(yasm_object *object, const char *name,
+ unsigned long align, int code, int res_only,
+ int *isnew, unsigned long line)
+{
+ yasm_section *s;
+ yasm_bytecode *bc;
+
+ /* Search through current sections to see if we already have one with
+ * that name.
+ */
+ STAILQ_FOREACH(s, &object->sections, link) {
+ if (strcmp(s->name, name) == 0) {
+ *isnew = 0;
+ return s;
+ }
+ }
+
+ /* No: we have to allocate and create a new one. */
+
+ /* Okay, the name is valid; now allocate and initialize */
+ s = yasm_xcalloc(1, sizeof(yasm_section));
+ STAILQ_INSERT_TAIL(&object->sections, s, link);
+
+ s->object = object;
+ s->name = yasm__xstrdup(name);
+ s->assoc_data = NULL;
+ s->align = align;
+
+ /* Initialize bytecodes with one empty bytecode (acts as "prior" for first
+ * real bytecode in section.
+ */
+ STAILQ_INIT(&s->bcs);
+ bc = yasm_bc_create_common(NULL, NULL, 0);
+ bc->section = s;
+ bc->offset = 0;
+ STAILQ_INSERT_TAIL(&s->bcs, bc, link);
+
+ /* Initialize relocs */
+ STAILQ_INIT(&s->relocs);
+ s->destroy_reloc = NULL;
+
+ s->code = code;
+ s->res_only = res_only;
+ s->def = 0;
+
+ /* Initialize object format specific data */
+ yasm_objfmt_init_new_section(s, line);
+
+ *isnew = 1;
+ return s;
+}
+/*@=onlytrans@*/
+
+int
+yasm_object_directive(yasm_object *object, const char *name,
+ const char *parser, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams,
+ unsigned long line)
+{
+ HAMT *level2;
+ yasm_directive_wrap *wrap;
+
+ level2 = HAMT_search(object->directives, parser);
+ if (!level2)
+ return 1;
+
+ wrap = HAMT_search(level2, name);
+ if (!wrap)
+ return 1;
+
+ yasm_call_directive(wrap->directive, object, valparams, objext_valparams,
+ line);
+ return 0;
+}
+
+void
+yasm_object_set_source_fn(yasm_object *object, const char *src_filename)
+{
+ yasm_xfree(object->src_filename);
+ object->src_filename = yasm__xstrdup(src_filename);
+ yasm_xfree(object->deb_filename);
+ object->deb_filename = NULL;
+}
+
+void
+yasm_object_set_global_prefix(yasm_object *object, const char *prefix)
+{
+ yasm_xfree(object->global_prefix);
+ object->global_prefix = yasm__xstrdup(prefix);
+}
+
+void
+yasm_object_set_global_suffix(yasm_object *object, const char *suffix)
+{
+ yasm_xfree(object->global_suffix);
+ object->global_suffix = yasm__xstrdup(suffix);
+}
+
+int
+yasm_section_is_code(yasm_section *sect)
+{
+ return sect->code;
+}
+
+unsigned long
+yasm_section_get_opt_flags(const yasm_section *sect)
+{
+ return sect->opt_flags;
+}
+
+void
+yasm_section_set_opt_flags(yasm_section *sect, unsigned long opt_flags)
+{
+ sect->opt_flags = opt_flags;
+}
+
+int
+yasm_section_is_default(const yasm_section *sect)
+{
+ return sect->def;
+}
+
+void
+yasm_section_set_default(yasm_section *sect, int def)
+{
+ sect->def = def;
+}
+
+yasm_object *
+yasm_section_get_object(const yasm_section *sect)
+{
+ return sect->object;
+}
+
+void *
+yasm_section_get_data(yasm_section *sect,
+ const yasm_assoc_data_callback *callback)
+{
+ return yasm__assoc_data_get(sect->assoc_data, callback);
+}
+
+void
+yasm_section_add_data(yasm_section *sect,
+ const yasm_assoc_data_callback *callback, void *data)
+{
+ sect->assoc_data = yasm__assoc_data_add(sect->assoc_data, callback, data);
+}
+
+void
+yasm_object_destroy(yasm_object *object)
+{
+ yasm_section *cur, *next;
+
+ /* Delete object format, debug format, and arch. This can be called
+ * due to an error in yasm_object_create(), so look out for NULLs.
+ */
+ if (object->objfmt)
+ yasm_objfmt_destroy(object->objfmt);
+ if (object->dbgfmt)
+ yasm_dbgfmt_destroy(object->dbgfmt);
+
+ /* Delete sections */
+ cur = STAILQ_FIRST(&object->sections);
+ while (cur) {
+ next = STAILQ_NEXT(cur, link);
+ yasm_section_destroy(cur);
+ cur = next;
+ }
+
+ /* Delete directives HAMT */
+ HAMT_destroy(object->directives, directive_level1_delete);
+
+ /* Delete prefix/suffix */
+ yasm_xfree(object->global_prefix);
+ yasm_xfree(object->global_suffix);
+
+ /* Delete associated filenames */
+ yasm_xfree(object->src_filename);
+ yasm_xfree(object->deb_filename);
+ yasm_xfree(object->obj_filename);
+
+ /* Delete symbol table */
+ yasm_symtab_destroy(object->symtab);
+
+ /* Delete architecture */
+ if (object->arch)
+ yasm_arch_destroy(object->arch);
+
+ yasm_xfree(object);
+}
+
+void
+yasm_object_print(const yasm_object *object, FILE *f, int indent_level)
+{
+ yasm_section *cur;
+
+ /* Print symbol table */
+ fprintf(f, "%*sSymbol Table:\n", indent_level, "");
+ yasm_symtab_print(object->symtab, f, indent_level+1);
+
+ /* Print sections and bytecodes */
+ STAILQ_FOREACH(cur, &object->sections, link) {
+ fprintf(f, "%*sSection:\n", indent_level, "");
+ yasm_section_print(cur, f, indent_level+1, 1);
+ }
+}
+
+void
+yasm_object_finalize(yasm_object *object, yasm_errwarns *errwarns)
+{
+ yasm_section *sect;
+
+ /* Iterate through sections */
+ STAILQ_FOREACH(sect, &object->sections, link) {
+ yasm_bytecode *cur = STAILQ_FIRST(&sect->bcs);
+ yasm_bytecode *prev;
+
+ /* Skip our locally created empty bytecode first. */
+ prev = cur;
+ cur = STAILQ_NEXT(cur, link);
+
+ /* Iterate through the remainder, if any. */
+ while (cur) {
+ /* Finalize */
+ yasm_bc_finalize(cur, prev);
+ yasm_errwarn_propagate(errwarns, cur->line);
+ prev = cur;
+ cur = STAILQ_NEXT(cur, link);
+ }
+ }
+}
+
+int
+yasm_object_sections_traverse(yasm_object *object, /*@null@*/ void *d,
+ int (*func) (yasm_section *sect,
+ /*@null@*/ void *d))
+{
+ yasm_section *cur;
+
+ STAILQ_FOREACH(cur, &object->sections, link) {
+ int retval = func(cur, d);
+ if (retval != 0)
+ return retval;
+ }
+ return 0;
+}
+
+/*@-onlytrans@*/
+yasm_section *
+yasm_object_find_general(yasm_object *object, const char *name)
+{
+ yasm_section *cur;
+
+ STAILQ_FOREACH(cur, &object->sections, link) {
+ if (strcmp(cur->name, name) == 0)
+ return cur;
+ }
+ return NULL;
+}
+/*@=onlytrans@*/
+
+void
+yasm_section_add_reloc(yasm_section *sect, yasm_reloc *reloc,
+ void (*destroy_func) (/*@only@*/ void *reloc))
+{
+ STAILQ_INSERT_TAIL(&sect->relocs, reloc, link);
+ if (!destroy_func)
+ yasm_internal_error(N_("NULL destroy function given to add_reloc"));
+ else if (sect->destroy_reloc && destroy_func != sect->destroy_reloc)
+ yasm_internal_error(N_("different destroy function given to add_reloc"));
+ sect->destroy_reloc = destroy_func;
+}
+
+/*@null@*/ yasm_reloc *
+yasm_section_relocs_first(yasm_section *sect)
+{
+ return STAILQ_FIRST(&sect->relocs);
+}
+
+#undef yasm_section_reloc_next
+/*@null@*/ yasm_reloc *
+yasm_section_reloc_next(yasm_reloc *reloc)
+{
+ return STAILQ_NEXT(reloc, link);
+}
+
+void
+yasm_reloc_get(yasm_reloc *reloc, yasm_intnum **addrp, yasm_symrec **symp)
+{
+ *addrp = reloc->addr;
+ *symp = reloc->sym;
+}
+
+
+yasm_bytecode *
+yasm_section_bcs_first(yasm_section *sect)
+{
+ return STAILQ_FIRST(&sect->bcs);
+}
+
+yasm_bytecode *
+yasm_section_bcs_last(yasm_section *sect)
+{
+ return STAILQ_LAST(&sect->bcs, yasm_bytecode, link);
+}
+
+yasm_bytecode *
+yasm_section_bcs_append(yasm_section *sect, yasm_bytecode *bc)
+{
+ if (bc) {
+ if (bc->callback) {
+ bc->section = sect; /* record parent section */
+ STAILQ_INSERT_TAIL(&sect->bcs, bc, link);
+ return bc;
+ } else
+ yasm_xfree(bc);
+ }
+ return (yasm_bytecode *)NULL;
+}
+
+int
+yasm_section_bcs_traverse(yasm_section *sect,
+ /*@null@*/ yasm_errwarns *errwarns,
+ /*@null@*/ void *d,
+ int (*func) (yasm_bytecode *bc, /*@null@*/ void *d))
+{
+ yasm_bytecode *cur = STAILQ_FIRST(&sect->bcs);
+
+ /* Skip our locally created empty bytecode first. */
+ cur = STAILQ_NEXT(cur, link);
+
+ /* Iterate through the remainder, if any. */
+ while (cur) {
+ int retval = func(cur, d);
+ if (errwarns)
+ yasm_errwarn_propagate(errwarns, cur->line);
+ if (retval != 0)
+ return retval;
+ cur = STAILQ_NEXT(cur, link);
+ }
+ return 0;
+}
+
+const char *
+yasm_section_get_name(const yasm_section *sect)
+{
+ return sect->name;
+}
+
+void
+yasm_section_set_align(yasm_section *sect, unsigned long align,
+ unsigned long line)
+{
+ sect->align = align;
+}
+
+unsigned long
+yasm_section_get_align(const yasm_section *sect)
+{
+ return sect->align;
+}
+
+static void
+yasm_section_destroy(yasm_section *sect)
+{
+ yasm_bytecode *cur, *next;
+ yasm_reloc *r_cur, *r_next;
+
+ if (!sect)
+ return;
+
+ yasm_xfree(sect->name);
+ yasm__assoc_data_destroy(sect->assoc_data);
+
+ /* Delete bytecodes */
+ cur = STAILQ_FIRST(&sect->bcs);
+ while (cur) {
+ next = STAILQ_NEXT(cur, link);
+ yasm_bc_destroy(cur);
+ cur = next;
+ }
+
+ /* Delete relocations */
+ r_cur = STAILQ_FIRST(&sect->relocs);
+ while (r_cur) {
+ r_next = STAILQ_NEXT(r_cur, link);
+ yasm_intnum_destroy(r_cur->addr);
+ sect->destroy_reloc(r_cur);
+ r_cur = r_next;
+ }
+
+ yasm_xfree(sect);
+}
+
+void
+yasm_section_print(const yasm_section *sect, FILE *f, int indent_level,
+ int print_bcs)
+{
+ if (!sect) {
+ fprintf(f, "%*s(none)\n", indent_level, "");
+ return;
+ }
+
+ fprintf(f, "%*sname=%s\n", indent_level, "", sect->name);
+
+ if (sect->assoc_data) {
+ fprintf(f, "%*sAssociated data:\n", indent_level, "");
+ yasm__assoc_data_print(sect->assoc_data, f, indent_level+1);
+ }
+
+ if (print_bcs) {
+ yasm_bytecode *cur;
+
+ fprintf(f, "%*sBytecodes:\n", indent_level, "");
+
+ STAILQ_FOREACH(cur, &sect->bcs, link) {
+ fprintf(f, "%*sNext Bytecode:\n", indent_level+1, "");
+ yasm_bc_print(cur, f, indent_level+2);
+ }
+ }
+}
+
+/*
+ * Robertson (1977) optimizer
+ * Based (somewhat loosely) on the algorithm given in:
+ * MRC Technical Summary Report # 1779
+ * CODE GENERATION FOR SHORT/LONG ADDRESS MACHINES
+ * Edward L. Robertson
+ * Mathematics Research Center
+ * University of Wisconsin-Madison
+ * 610 Walnut Street
+ * Madison, Wisconsin 53706
+ * August 1977
+ *
+ * Key components of algorithm:
+ * - start assuming all short forms
+ * - build spans for short->long transition dependencies
+ * - if a long form is needed, walk the dependencies and update
+ * Major differences from Robertson's algorithm:
+ * - detection of cycles
+ * - any difference of two locations is allowed
+ * - handling of alignment/org gaps (offset setting)
+ * - handling of multiples
+ *
+ * Data structures:
+ * - Interval tree to store spans and associated data
+ * - Queues QA and QB
+ *
+ * Each span keeps track of:
+ * - Associated bytecode (bytecode that depends on the span length)
+ * - Active/inactive state (starts out active)
+ * - Sign (negative/positive; negative being "backwards" in address)
+ * - Current length in bytes
+ * - New length in bytes
+ * - Negative/Positive thresholds
+ * - Span ID (unique within each bytecode)
+ *
+ * How org and align and any other offset-based bytecodes are handled:
+ *
+ * Some portions are critical values that must not depend on any bytecode
+ * offset (either relative or absolute).
+ *
+ * All offset-setters (ORG and ALIGN) are put into a linked list in section
+ * order (e.g. increasing offset order). Each span keeps track of the next
+ * offset-setter following the span's associated bytecode.
+ *
+ * When a bytecode is expanded, the next offset-setter is examined. The
+ * offset-setter may be able to absorb the expansion (e.g. any offset
+ * following it would not change), or it may have to move forward (in the
+ * case of align) or error (in the case of org). If it has to move forward,
+ * following offset-setters must also be examined for absorption or moving
+ * forward. In either case, the ongoing offset is updated as well as the
+ * lengths of any spans dependent on the offset-setter.
+ *
+ * Alignment/ORG value is critical value.
+ * Cannot be combined with TIMES.
+ *
+ * How times is handled:
+ *
+ * TIMES: Handled separately from bytecode "raw" size. If not span-dependent,
+ * trivial (just multiplied in at any bytecode size increase). Span
+ * dependent times update on any change (span ID 0). If the resultant
+ * next bytecode offset would be less than the old next bytecode offset,
+ * error. Otherwise increase offset and update dependent spans.
+ *
+ * To reduce interval tree size, a first expansion pass is performed
+ * before the spans are added to the tree.
+ *
+ * Basic algorithm outline:
+ *
+ * 1. Initialization:
+ * a. Number bytecodes sequentially (via bc_index) and calculate offsets
+ * of all bytecodes assuming minimum length, building a list of all
+ * dependent spans as we go.
+ * "minimum" here means absolute minimum:
+ * - align/org (offset-based) bumps offset as normal
+ * - times values (with span-dependent values) assumed to be 0
+ * b. Iterate over spans. Set span length based on bytecode offsets
+ * determined in 1a. If span is "certainly" long because the span
+ * is an absolute reference to another section (or external) or the
+ * distance calculated based on the minimum length is greater than the
+ * span's threshold, expand the span's bytecode, and if no further
+ * expansion can result, mark span as inactive.
+ * c. Iterate over bytecodes to update all bytecode offsets based on new
+ * (expanded) lengths calculated in 1b.
+ * d. Iterate over active spans. Add span to interval tree. Update span's
+ * length based on new bytecode offsets determined in 1c. If span's
+ * length exceeds long threshold, add that span to Q.
+ * 2. Main loop:
+ * While Q not empty:
+ * Expand BC dependent on span at head of Q (and remove span from Q).
+ * Update span:
+ * If BC no longer dependent on span, mark span as inactive.
+ * If BC has new thresholds for span, update span.
+ * If BC increased in size, for each active span that contains BC:
+ * Increase span length by difference between short and long BC length.
+ * If span exceeds long threshold (or is flagged to recalculate on any
+ * change), add it to tail of Q.
+ * 3. Final pass over bytecodes to generate final offsets.
+ */
+
+typedef struct yasm_span yasm_span;
+
+typedef struct yasm_offset_setter {
+ /* Linked list in section order (e.g. offset order) */
+ /*@reldef@*/ STAILQ_ENTRY(yasm_offset_setter) link;
+
+ /*@dependent@*/ yasm_bytecode *bc;
+
+ unsigned long cur_val, new_val;
+ unsigned long thres;
+} yasm_offset_setter;
+
+typedef struct yasm_span_term {
+ yasm_bytecode *precbc, *precbc2;
+ yasm_span *span; /* span this term is a member of */
+ long cur_val, new_val;
+ unsigned int subst;
+} yasm_span_term;
+
+struct yasm_span {
+ /*@reldef@*/ TAILQ_ENTRY(yasm_span) link; /* for allocation tracking */
+ /*@reldef@*/ STAILQ_ENTRY(yasm_span) linkq; /* for Q */
+
+ /*@dependent@*/ yasm_bytecode *bc;
+
+ yasm_value depval;
+
+ /* span term for relative portion of value */
+ yasm_span_term *rel_term;
+ /* span terms in absolute portion of value */
+ yasm_span_term *terms;
+ yasm_expr__item *items;
+ unsigned int num_terms;
+
+ long cur_val;
+ long new_val;
+
+ long neg_thres;
+ long pos_thres;
+
+ int id;
+
+ int active;
+
+ /* NULL-terminated array of spans that led to this span. Used only for
+ * checking for circular references (cycles) with id=0 spans.
+ */
+ yasm_span **backtrace;
+ int backtrace_size;
+
+ /* First offset setter following this span's bytecode */
+ yasm_offset_setter *os;
+};
+
+typedef struct optimize_data {
+ /*@reldef@*/ TAILQ_HEAD(yasm_span_head, yasm_span) spans;
+ /*@reldef@*/ STAILQ_HEAD(yasm_span_shead, yasm_span) QA, QB;
+ /*@only@*/ IntervalTree *itree;
+ /*@reldef@*/ STAILQ_HEAD(offset_setters_head, yasm_offset_setter)
+ offset_setters;
+ long len_diff; /* used only for optimize_term_expand */
+ yasm_span *span; /* used only for check_cycle */
+ yasm_offset_setter *os;
+} optimize_data;
+
+static yasm_span *
+create_span(yasm_bytecode *bc, int id, /*@null@*/ const yasm_value *value,
+ long neg_thres, long pos_thres, yasm_offset_setter *os)
+{
+ yasm_span *span = yasm_xmalloc(sizeof(yasm_span));
+
+ span->bc = bc;
+ if (value)
+ yasm_value_init_copy(&span->depval, value);
+ else
+ yasm_value_initialize(&span->depval, NULL, 0);
+ span->rel_term = NULL;
+ span->terms = NULL;
+ span->items = NULL;
+ span->num_terms = 0;
+ span->cur_val = 0;
+ span->new_val = 0;
+ span->neg_thres = neg_thres;
+ span->pos_thres = pos_thres;
+ span->id = id;
+ span->active = 1;
+ span->backtrace = NULL;
+ span->backtrace_size = 0;
+ span->os = os;
+
+ return span;
+}
+
+static void
+optimize_add_span(void *add_span_data, yasm_bytecode *bc, int id,
+ const yasm_value *value, long neg_thres, long pos_thres)
+{
+ optimize_data *optd = (optimize_data *)add_span_data;
+ yasm_span *span;
+ span = create_span(bc, id, value, neg_thres, pos_thres, optd->os);
+ TAILQ_INSERT_TAIL(&optd->spans, span, link);
+}
+
+static void
+add_span_term(unsigned int subst, yasm_bytecode *precbc,
+ yasm_bytecode *precbc2, void *d)
+{
+ yasm_span *span = d;
+ yasm_intnum *intn;
+
+ if (subst >= span->num_terms) {
+ /* Linear expansion since total number is essentially always small */
+ span->num_terms = subst+1;
+ span->terms = yasm_xrealloc(span->terms,
+ span->num_terms*sizeof(yasm_span_term));
+ }
+ span->terms[subst].precbc = precbc;
+ span->terms[subst].precbc2 = precbc2;
+ span->terms[subst].span = span;
+ span->terms[subst].subst = subst;
+
+ intn = yasm_calc_bc_dist(precbc, precbc2);
+ if (!intn)
+ yasm_internal_error(N_("could not calculate bc distance"));
+ span->terms[subst].cur_val = 0;
+ span->terms[subst].new_val = yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
+}
+
+static void
+span_create_terms(yasm_span *span)
+{
+ unsigned int i;
+
+ /* Split out sym-sym terms in absolute portion of dependent value */
+ if (span->depval.abs) {
+ span->num_terms = yasm_expr__bc_dist_subst(&span->depval.abs, span,
+ add_span_term);
+ if (span->num_terms > 0) {
+ span->items = yasm_xmalloc(span->num_terms*sizeof(yasm_expr__item));
+ for (i=0; i<span->num_terms; i++) {
+ /* Create items with dummy value */
+ span->items[i].type = YASM_EXPR_INT;
+ span->items[i].data.intn = yasm_intnum_create_int(0);
+
+ /* Check for circular references */
+ if (span->id <= 0 &&
+ ((span->bc->bc_index > span->terms[i].precbc->bc_index &&
+ span->bc->bc_index <= span->terms[i].precbc2->bc_index) ||
+ (span->bc->bc_index > span->terms[i].precbc2->bc_index &&
+ span->bc->bc_index <= span->terms[i].precbc->bc_index)))
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("circular reference detected"));
+ }
+ }
+ }
+
+ /* Create term for relative portion of dependent value */
+ if (span->depval.rel) {
+ yasm_bytecode *rel_precbc;
+ int sym_local;
+
+ sym_local = yasm_symrec_get_label(span->depval.rel, &rel_precbc);
+ if (span->depval.wrt || span->depval.seg_of || span->depval.section_rel
+ || !sym_local)
+ return; /* we can't handle SEG, WRT, or external symbols */
+ if (rel_precbc->section != span->bc->section)
+ return; /* not in this section */
+ if (!span->depval.curpos_rel)
+ return; /* not PC-relative */
+
+ span->rel_term = yasm_xmalloc(sizeof(yasm_span_term));
+ span->rel_term->precbc = NULL;
+ span->rel_term->precbc2 = rel_precbc;
+ span->rel_term->span = span;
+ span->rel_term->subst = ~0U;
+
+ span->rel_term->cur_val = 0;
+ span->rel_term->new_val = yasm_bc_next_offset(rel_precbc) -
+ span->bc->offset;
+ }
+}
+
+/* Recalculate span value based on current span replacement values.
+ * Returns 1 if span needs expansion (e.g. exceeded thresholds).
+ */
+static int
+recalc_normal_span(yasm_span *span)
+{
+ span->new_val = 0;
+
+ if (span->depval.abs) {
+ yasm_expr *abs_copy = yasm_expr_copy(span->depval.abs);
+ /*@null@*/ /*@dependent@*/ yasm_intnum *num;
+
+ /* Update sym-sym terms and substitute back into expr */
+ unsigned int i;
+ for (i=0; i<span->num_terms; i++)
+ yasm_intnum_set_int(span->items[i].data.intn,
+ span->terms[i].new_val);
+ yasm_expr__subst(abs_copy, span->num_terms, span->items);
+ num = yasm_expr_get_intnum(&abs_copy, 0);
+ if (num)
+ span->new_val = yasm_intnum_get_int(num);
+ else
+ span->new_val = LONG_MAX; /* too complex; force to longest form */
+ yasm_expr_destroy(abs_copy);
+ }
+
+ if (span->rel_term) {
+ if (span->new_val != LONG_MAX && span->rel_term->new_val != LONG_MAX)
+ span->new_val += span->rel_term->new_val >> span->depval.rshift;
+ else
+ span->new_val = LONG_MAX; /* too complex; force to longest form */
+ } else if (span->depval.rel)
+ span->new_val = LONG_MAX; /* too complex; force to longest form */
+
+ if (span->new_val == LONG_MAX)
+ span->active = 0;
+
+ /* If id<=0, flag update on any change */
+ if (span->id <= 0)
+ return (span->new_val != span->cur_val);
+
+ return (span->new_val < span->neg_thres
+ || span->new_val > span->pos_thres);
+}
+
+/* Updates all bytecode offsets. For offset-based bytecodes, calls expand
+ * to determine new length.
+ */
+static int
+update_all_bc_offsets(yasm_object *object, yasm_errwarns *errwarns)
+{
+ yasm_section *sect;
+ int saw_error = 0;
+
+ STAILQ_FOREACH(sect, &object->sections, link) {
+ unsigned long offset = 0;
+
+ yasm_bytecode *bc = STAILQ_FIRST(&sect->bcs);
+ yasm_bytecode *prevbc;
+
+ /* Skip our locally created empty bytecode first. */
+ prevbc = bc;
+ bc = STAILQ_NEXT(bc, link);
+
+ /* Iterate through the remainder, if any. */
+ while (bc) {
+ if (bc->callback->special == YASM_BC_SPECIAL_OFFSET) {
+ /* Recalculate/adjust len of offset-based bytecodes here */
+ long neg_thres = 0;
+ long pos_thres = (long)yasm_bc_next_offset(bc);
+ int retval = yasm_bc_expand(bc, 1, 0,
+ (long)yasm_bc_next_offset(prevbc),
+ &neg_thres, &pos_thres);
+ yasm_errwarn_propagate(errwarns, bc->line);
+ if (retval < 0)
+ saw_error = 1;
+ }
+ bc->offset = offset;
+ offset += bc->len*bc->mult_int;
+ prevbc = bc;
+ bc = STAILQ_NEXT(bc, link);
+ }
+ }
+ return saw_error;
+}
+
+static void
+span_destroy(/*@only@*/ yasm_span *span)
+{
+ unsigned int i;
+
+ yasm_value_delete(&span->depval);
+ if (span->rel_term)
+ yasm_xfree(span->rel_term);
+ if (span->terms)
+ yasm_xfree(span->terms);
+ if (span->items) {
+ for (i=0; i<span->num_terms; i++)
+ yasm_intnum_destroy(span->items[i].data.intn);
+ yasm_xfree(span->items);
+ }
+ if (span->backtrace)
+ yasm_xfree(span->backtrace);
+ yasm_xfree(span);
+}
+
+static void
+optimize_cleanup(optimize_data *optd)
+{
+ yasm_span *s1, *s2;
+ yasm_offset_setter *os1, *os2;
+
+ IT_destroy(optd->itree);
+
+ s1 = TAILQ_FIRST(&optd->spans);
+ while (s1) {
+ s2 = TAILQ_NEXT(s1, link);
+ span_destroy(s1);
+ s1 = s2;
+ }
+
+ os1 = STAILQ_FIRST(&optd->offset_setters);
+ while (os1) {
+ os2 = STAILQ_NEXT(os1, link);
+ yasm_xfree(os1);
+ os1 = os2;
+ }
+}
+
+static void
+optimize_itree_add(IntervalTree *itree, yasm_span *span, yasm_span_term *term)
+{
+ long precbc_index, precbc2_index;
+ unsigned long low, high;
+
+ /* Update term length */
+ if (term->precbc)
+ precbc_index = term->precbc->bc_index;
+ else
+ precbc_index = span->bc->bc_index-1;
+
+ if (term->precbc2)
+ precbc2_index = term->precbc2->bc_index;
+ else
+ precbc2_index = span->bc->bc_index-1;
+
+ if (precbc_index < precbc2_index) {
+ low = precbc_index+1;
+ high = precbc2_index;
+ } else if (precbc_index > precbc2_index) {
+ low = precbc2_index+1;
+ high = precbc_index;
+ } else
+ return; /* difference is same bc - always 0! */
+
+ IT_insert(itree, (long)low, (long)high, term);
+}
+
+static void
+check_cycle(IntervalTreeNode *node, void *d)
+{
+ optimize_data *optd = d;
+ yasm_span_term *term = node->data;
+ yasm_span *depspan = term->span;
+ int i;
+ int depspan_bt_alloc;
+
+ /* Only check for cycles in id=0 spans */
+ if (depspan->id > 0)
+ return;
+
+ /* Check for a circular reference by looking to see if this dependent
+ * span is in our backtrace.
+ */
+ if (optd->span->backtrace) {
+ for (i=0; i<optd->span->backtrace_size; i++) {
+ if (optd->span->backtrace[i] == depspan)
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("circular reference detected"));
+ }
+ }
+
+ /* Add our complete backtrace and ourselves to backtrace of dependent
+ * span.
+ */
+ if (!depspan->backtrace) {
+ depspan->backtrace = yasm_xmalloc((optd->span->backtrace_size+1)*
+ sizeof(yasm_span *));
+ if (optd->span->backtrace_size > 0)
+ memcpy(depspan->backtrace, optd->span->backtrace,
+ optd->span->backtrace_size*sizeof(yasm_span *));
+ depspan->backtrace[optd->span->backtrace_size] = optd->span;
+ depspan->backtrace_size = optd->span->backtrace_size+1;
+ return;
+ }
+
+ /* Add our complete backtrace, checking for duplicates */
+ depspan_bt_alloc = depspan->backtrace_size;
+ for (i=0; i<optd->span->backtrace_size; i++) {
+ int present = 0;
+ int j;
+ for (j=0; j<depspan->backtrace_size; j++) {
+ if (optd->span->backtrace[i] == optd->span->backtrace[j]) {
+ present = 1;
+ break;
+ }
+ }
+ if (present)
+ continue;
+ /* Not already in array; add it. */
+ if (depspan->backtrace_size >= depspan_bt_alloc)
+ {
+ depspan_bt_alloc *= 2;
+ depspan->backtrace =
+ yasm_xrealloc(depspan->backtrace,
+ depspan_bt_alloc*sizeof(yasm_span *));
+ }
+ depspan->backtrace[depspan->backtrace_size] = optd->span->backtrace[i];
+ depspan->backtrace_size++;
+ }
+
+ /* Add ourselves. */
+ if (depspan->backtrace_size >= depspan_bt_alloc)
+ {
+ depspan_bt_alloc++;
+ depspan->backtrace =
+ yasm_xrealloc(depspan->backtrace,
+ depspan_bt_alloc*sizeof(yasm_span *));
+ }
+ depspan->backtrace[depspan->backtrace_size] = optd->span;
+ depspan->backtrace_size++;
+}
+
+static void
+optimize_term_expand(IntervalTreeNode *node, void *d)
+{
+ optimize_data *optd = d;
+ yasm_span_term *term = node->data;
+ yasm_span *span = term->span;
+ long len_diff = optd->len_diff;
+ long precbc_index, precbc2_index;
+
+ /* Don't expand inactive spans */
+ if (!span->active)
+ return;
+
+ /* Update term length */
+ if (term->precbc)
+ precbc_index = term->precbc->bc_index;
+ else
+ precbc_index = span->bc->bc_index-1;
+
+ if (term->precbc2)
+ precbc2_index = term->precbc2->bc_index;
+ else
+ precbc2_index = span->bc->bc_index-1;
+
+ if (precbc_index < precbc2_index)
+ term->new_val += len_diff;
+ else
+ term->new_val -= len_diff;
+
+ /* If already on Q, don't re-add */
+ if (span->active == 2)
+ return;
+
+ /* Update term and check against thresholds */
+ if (!recalc_normal_span(span))
+ return; /* didn't exceed thresholds, we're done */
+
+ /* Exceeded thresholds, need to add to Q for expansion */
+ if (span->id <= 0)
+ STAILQ_INSERT_TAIL(&optd->QA, span, linkq);
+ else
+ STAILQ_INSERT_TAIL(&optd->QB, span, linkq);
+ span->active = 2; /* Mark as being in Q */
+}
+
+void
+yasm_object_optimize(yasm_object *object, yasm_errwarns *errwarns)
+{
+ yasm_section *sect;
+ unsigned long bc_index = 0;
+ int saw_error = 0;
+ optimize_data optd;
+ yasm_span *span, *span_temp;
+ yasm_offset_setter *os;
+ int retval;
+ unsigned int i;
+
+ TAILQ_INIT(&optd.spans);
+ STAILQ_INIT(&optd.offset_setters);
+ optd.itree = IT_create();
+
+ /* Create an placeholder offset setter for spans to point to; this will
+ * get updated if/when we actually run into one.
+ */
+ os = yasm_xmalloc(sizeof(yasm_offset_setter));
+ os->bc = NULL;
+ os->cur_val = 0;
+ os->new_val = 0;
+ os->thres = 0;
+ STAILQ_INSERT_TAIL(&optd.offset_setters, os, link);
+ optd.os = os;
+
+ /* Step 1a */
+ STAILQ_FOREACH(sect, &object->sections, link) {
+ unsigned long offset = 0;
+
+ yasm_bytecode *bc = STAILQ_FIRST(&sect->bcs);
+
+ bc->bc_index = bc_index++;
+
+ /* Skip our locally created empty bytecode first. */
+ bc = STAILQ_NEXT(bc, link);
+
+ /* Iterate through the remainder, if any. */
+ while (bc) {
+ bc->bc_index = bc_index++;
+ bc->offset = offset;
+
+ retval = yasm_bc_calc_len(bc, optimize_add_span, &optd);
+ yasm_errwarn_propagate(errwarns, bc->line);
+ if (retval)
+ saw_error = 1;
+ else {
+ if (bc->callback->special == YASM_BC_SPECIAL_OFFSET) {
+ /* Remember it as offset setter */
+ os->bc = bc;
+ os->thres = yasm_bc_next_offset(bc);
+
+ /* Create new placeholder */
+ os = yasm_xmalloc(sizeof(yasm_offset_setter));
+ os->bc = NULL;
+ os->cur_val = 0;
+ os->new_val = 0;
+ os->thres = 0;
+ STAILQ_INSERT_TAIL(&optd.offset_setters, os, link);
+ optd.os = os;
+
+ if (bc->multiple) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("cannot combine multiples and setting assembly position"));
+ yasm_errwarn_propagate(errwarns, bc->line);
+ saw_error = 1;
+ }
+ }
+
+ offset += bc->len*bc->mult_int;
+ }
+
+ bc = STAILQ_NEXT(bc, link);
+ }
+ }
+
+ if (saw_error) {
+ optimize_cleanup(&optd);
+ return;
+ }
+
+ /* Step 1b */
+ TAILQ_FOREACH_SAFE(span, &optd.spans, link, span_temp) {
+ span_create_terms(span);
+ if (yasm_error_occurred()) {
+ yasm_errwarn_propagate(errwarns, span->bc->line);
+ saw_error = 1;
+ } else if (recalc_normal_span(span)) {
+ retval = yasm_bc_expand(span->bc, span->id, span->cur_val,
+ span->new_val, &span->neg_thres,
+ &span->pos_thres);
+ yasm_errwarn_propagate(errwarns, span->bc->line);
+ if (retval < 0)
+ saw_error = 1;
+ else if (retval > 0) {
+ if (!span->active) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("secondary expansion of an external/complex value"));
+ yasm_errwarn_propagate(errwarns, span->bc->line);
+ saw_error = 1;
+ }
+ } else {
+ TAILQ_REMOVE(&optd.spans, span, link);
+ span_destroy(span);
+ continue;
+ }
+ }
+ span->cur_val = span->new_val;
+ }
+
+ if (saw_error) {
+ optimize_cleanup(&optd);
+ return;
+ }
+
+ /* Step 1c */
+ if (update_all_bc_offsets(object, errwarns)) {
+ optimize_cleanup(&optd);
+ return;
+ }
+
+ /* Step 1d */
+ STAILQ_INIT(&optd.QB);
+ TAILQ_FOREACH(span, &optd.spans, link) {
+ yasm_intnum *intn;
+
+ /* Update span terms based on new bc offsets */
+ for (i=0; i<span->num_terms; i++) {
+ intn = yasm_calc_bc_dist(span->terms[i].precbc,
+ span->terms[i].precbc2);
+ if (!intn)
+ yasm_internal_error(N_("could not calculate bc distance"));
+ span->terms[i].cur_val = span->terms[i].new_val;
+ span->terms[i].new_val = yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
+ }
+ if (span->rel_term) {
+ span->rel_term->cur_val = span->rel_term->new_val;
+ if (span->rel_term->precbc2)
+ span->rel_term->new_val =
+ yasm_bc_next_offset(span->rel_term->precbc2) -
+ span->bc->offset;
+ else
+ span->rel_term->new_val = span->bc->offset -
+ yasm_bc_next_offset(span->rel_term->precbc);
+ }
+
+ if (recalc_normal_span(span)) {
+ /* Exceeded threshold, add span to QB */
+ STAILQ_INSERT_TAIL(&optd.QB, span, linkq);
+ span->active = 2;
+ }
+ }
+
+ /* Do we need step 2? If not, go ahead and exit. */
+ if (STAILQ_EMPTY(&optd.QB)) {
+ optimize_cleanup(&optd);
+ return;
+ }
+
+ /* Update offset-setters values */
+ STAILQ_FOREACH(os, &optd.offset_setters, link) {
+ if (!os->bc)
+ continue;
+ os->thres = yasm_bc_next_offset(os->bc);
+ os->new_val = os->bc->offset;
+ os->cur_val = os->new_val;
+ }
+
+ /* Build up interval tree */
+ TAILQ_FOREACH(span, &optd.spans, link) {
+ for (i=0; i<span->num_terms; i++)
+ optimize_itree_add(optd.itree, span, &span->terms[i]);
+ if (span->rel_term)
+ optimize_itree_add(optd.itree, span, span->rel_term);
+ }
+
+ /* Look for cycles in times expansion (span.id==0) */
+ TAILQ_FOREACH(span, &optd.spans, link) {
+ if (span->id > 0)
+ continue;
+ optd.span = span;
+ IT_enumerate(optd.itree, (long)span->bc->bc_index,
+ (long)span->bc->bc_index, &optd, check_cycle);
+ if (yasm_error_occurred()) {
+ yasm_errwarn_propagate(errwarns, span->bc->line);
+ saw_error = 1;
+ }
+ }
+
+ if (saw_error) {
+ optimize_cleanup(&optd);
+ return;
+ }
+
+ /* Step 2 */
+ STAILQ_INIT(&optd.QA);
+ while (!STAILQ_EMPTY(&optd.QA) || !(STAILQ_EMPTY(&optd.QB))) {
+ unsigned long orig_len;
+ long offset_diff;
+
+ /* QA is for TIMES, update those first, then update non-TIMES.
+ * This is so that TIMES can absorb increases before we look at
+ * expanding non-TIMES BCs.
+ */
+ if (!STAILQ_EMPTY(&optd.QA)) {
+ span = STAILQ_FIRST(&optd.QA);
+ STAILQ_REMOVE_HEAD(&optd.QA, linkq);
+ } else {
+ span = STAILQ_FIRST(&optd.QB);
+ STAILQ_REMOVE_HEAD(&optd.QB, linkq);
+ }
+
+ if (!span->active)
+ continue;
+ span->active = 1; /* no longer in Q */
+
+ /* Make sure we ended up ultimately exceeding thresholds; due to
+ * offset BCs we may have been placed on Q and then reduced in size
+ * again.
+ */
+ if (!recalc_normal_span(span))
+ continue;
+
+ orig_len = span->bc->len * span->bc->mult_int;
+
+ retval = yasm_bc_expand(span->bc, span->id, span->cur_val,
+ span->new_val, &span->neg_thres,
+ &span->pos_thres);
+ yasm_errwarn_propagate(errwarns, span->bc->line);
+
+ if (retval < 0) {
+ /* error */
+ saw_error = 1;
+ continue;
+ } else if (retval > 0) {
+ /* another threshold, keep active */
+ for (i=0; i<span->num_terms; i++)
+ span->terms[i].cur_val = span->terms[i].new_val;
+ if (span->rel_term)
+ span->rel_term->cur_val = span->rel_term->new_val;
+ span->cur_val = span->new_val;
+ } else
+ span->active = 0; /* we're done with this span */
+
+ optd.len_diff = span->bc->len * span->bc->mult_int - orig_len;
+ if (optd.len_diff == 0)
+ continue; /* didn't increase in size */
+
+ /* Iterate over all spans dependent across the bc just expanded */
+ IT_enumerate(optd.itree, (long)span->bc->bc_index,
+ (long)span->bc->bc_index, &optd, optimize_term_expand);
+
+ /* Iterate over offset-setters that follow the bc just expanded.
+ * Stop iteration if:
+ * - no more offset-setters in this section
+ * - offset-setter didn't move its following offset
+ */
+ os = span->os;
+ offset_diff = optd.len_diff;
+ while (os->bc && os->bc->section == span->bc->section
+ && offset_diff != 0) {
+ unsigned long old_next_offset = os->cur_val + os->bc->len;
+ long neg_thres_temp;
+
+ if (offset_diff < 0 && (unsigned long)(-offset_diff) > os->new_val)
+ yasm_internal_error(N_("org/align went to negative offset"));
+ os->new_val += offset_diff;
+
+ orig_len = os->bc->len;
+ retval = yasm_bc_expand(os->bc, 1, (long)os->cur_val,
+ (long)os->new_val, &neg_thres_temp,
+ (long *)&os->thres);
+ yasm_errwarn_propagate(errwarns, os->bc->line);
+
+ offset_diff = os->new_val + os->bc->len - old_next_offset;
+ optd.len_diff = os->bc->len - orig_len;
+ if (optd.len_diff != 0)
+ IT_enumerate(optd.itree, (long)os->bc->bc_index,
+ (long)os->bc->bc_index, &optd, optimize_term_expand);
+
+ os->cur_val = os->new_val;
+ os = STAILQ_NEXT(os, link);
+ }
+ }
+
+ if (saw_error) {
+ optimize_cleanup(&optd);
+ return;
+ }
+
+ /* Step 3 */
+ update_all_bc_offsets(object, errwarns);
+ optimize_cleanup(&optd);
+}
diff --git a/contrib/tools/yasm/libyasm/section.h b/contrib/tools/yasm/libyasm/section.h
new file mode 100644
index 0000000000..521031f3a5
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/section.h
@@ -0,0 +1,384 @@
+/**
+ * \file libyasm/section.h
+ * \brief YASM section interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_SECTION_H
+#define YASM_SECTION_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Basic YASM relocation. Object formats will need to extend this
+ * structure with additional fields for relocation type, etc.
+ */
+typedef struct yasm_reloc yasm_reloc;
+
+struct yasm_reloc {
+ /*@reldef@*/ STAILQ_ENTRY(yasm_reloc) link; /**< Link to next reloc */
+ yasm_intnum *addr; /**< Offset (address) within section */
+ /*@dependent@*/ yasm_symrec *sym; /**< Relocated symbol */
+};
+
+/** An object. This is the internal representation of an object file. */
+struct yasm_object {
+ /*@owned@*/ char *src_filename; /**< Source filename */
+ /*@owned@*/ char *deb_filename; /**< Debug filename */
+ /*@owned@*/ char *obj_filename; /**< Object filename */
+
+ /*@owned@*/ yasm_symtab *symtab; /**< Symbol table */
+ /*@owned@*/ yasm_arch *arch; /**< Target architecture */
+ /*@owned@*/ yasm_objfmt *objfmt; /**< Object format */
+ /*@owned@*/ yasm_dbgfmt *dbgfmt; /**< Debug format */
+
+ /** Currently active section. Used by some directives. NULL if no
+ * section active.
+ */
+ /*@dependent@*/ /*@null@*/ yasm_section *cur_section;
+
+ /** Linked list of sections. */
+ /*@reldef@*/ STAILQ_HEAD(yasm_sectionhead, yasm_section) sections;
+
+ /** Directives, organized as two level HAMT; first level is parser,
+ * second level is directive name.
+ */
+ /*@owned@*/ struct HAMT *directives;
+
+ /** Prefix prepended to externally-visible symbols (empty string if none) */
+ /*@owned@*/ char *global_prefix;
+
+ /** Suffix appended to externally-visible symbols (empty string if none) */
+ /*@owned@*/ char *global_suffix;
+};
+
+/** Create a new object. A default section is created as the first section.
+ * An empty symbol table (yasm_symtab) and line mapping (yasm_linemap) are
+ * automatically created.
+ * \param src_filename source filename (e.g. "file.asm")
+ * \param obj_filename object filename (e.g. "file.o")
+ * \param arch architecture
+ * \param objfmt_module object format module
+ * \param dbgfmt_module debug format module
+ * \return Newly allocated object, or NULL on error.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@only@*/ yasm_object *yasm_object_create
+ (const char *src_filename, const char *obj_filename,
+ /*@kept@*/ yasm_arch *arch,
+ const yasm_objfmt_module *objfmt_module,
+ const yasm_dbgfmt_module *dbgfmt_module);
+
+/** Create a new, or continue an existing, general section. The section is
+ * added to the object if there's not already a section by that name.
+ * \param object object
+ * \param name section name
+ * \param align alignment in bytes (0 if none)
+ * \param code if nonzero, section is intended to contain code
+ * (e.g. alignment should be made with NOP instructions, not 0)
+ * \param res_only if nonzero, only space-reserving bytecodes are allowed in
+ * the section (ignored if section already exists)
+ * \param isnew output; set to nonzero if section did not already exist
+ * \param line virtual line of section declaration (ignored if section
+ * already exists)
+ * \return New section.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_section *yasm_object_get_general
+ (yasm_object *object, const char *name, unsigned long align, int code,
+ int res_only, /*@out@*/ int *isnew, unsigned long line);
+
+/** Handle a directive. Passed down to object format, debug format, or
+ * architecture as appropriate.
+ * \param object object
+ * \param name directive name
+ * \param parser parser keyword
+ * \param valparams value/parameters
+ * \param objext_valparams "object format-specific" value/parameters
+ * \param line virtual line (from yasm_linemap)
+ * \return 0 if directive recognized, nonzero if unrecognized.
+ */
+YASM_LIB_DECL
+int yasm_object_directive(yasm_object *object, const char *name,
+ const char *parser, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams,
+ unsigned long line);
+
+/** Delete (free allocated memory for) an object. All sections in the
+ * object and all bytecodes within those sections are also deleted.
+ * \param object object
+ */
+YASM_LIB_DECL
+void yasm_object_destroy(/*@only@*/ yasm_object *object);
+
+/** Print an object. For debugging purposes.
+ * \param object object
+ * \param f file
+ * \param indent_level indentation level
+ */
+YASM_LIB_DECL
+void yasm_object_print(const yasm_object *object, FILE *f, int indent_level);
+
+/** Finalize an object after parsing.
+ * \param object object
+ * \param errwarns error/warning set
+ * \note Errors/warnings are stored into errwarns.
+ */
+YASM_LIB_DECL
+void yasm_object_finalize(yasm_object *object, yasm_errwarns *errwarns);
+
+/** Traverses all sections in an object, calling a function on each section.
+ * \param object object
+ * \param d data pointer passed to func on each call
+ * \param func function
+ * \return Stops early (and returns func's return value) if func returns a
+ * nonzero value; otherwise 0.
+ */
+YASM_LIB_DECL
+int yasm_object_sections_traverse
+ (yasm_object *object, /*@null@*/ void *d,
+ int (*func) (yasm_section *sect, /*@null@*/ void *d));
+
+/** Find a general section in an object, based on its name.
+ * \param object object
+ * \param name section name
+ * \return Section matching name, or NULL if no match found.
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ yasm_section *yasm_object_find_general
+ (yasm_object *object, const char *name);
+
+/** Change the source filename for an object.
+ * \param object object
+ * \param src_filename new source filename (e.g. "file.asm")
+ */
+YASM_LIB_DECL
+void yasm_object_set_source_fn(yasm_object *object, const char *src_filename);
+
+/** Change the prefix used for externally-visible symbols.
+ * \param object object
+ * \param prefix new prefix
+ */
+YASM_LIB_DECL
+void yasm_object_set_global_prefix(yasm_object *object, const char *prefix);
+
+/** Change the suffix used for externally-visible symbols.
+ * \param object object
+ * \param suffix new suffix
+ */
+YASM_LIB_DECL
+void yasm_object_set_global_suffix(yasm_object *object, const char *suffix);
+
+/** Optimize an object. Takes the unoptimized object and optimizes it.
+ * If successful, the object is ready for output to an object file.
+ * \param object object
+ * \param errwarns error/warning set
+ * \note Optimization failures are stored into errwarns.
+ */
+YASM_LIB_DECL
+void yasm_object_optimize(yasm_object *object, yasm_errwarns *errwarns);
+
+/** Determine if a section is flagged to contain code.
+ * \param sect section
+ * \return Nonzero if section is flagged to contain code.
+ */
+YASM_LIB_DECL
+int yasm_section_is_code(yasm_section *sect);
+
+/** Get yasm_optimizer-specific flags. For yasm_optimizer use only.
+ * \param sect section
+ * \return Optimizer-specific flags.
+ */
+YASM_LIB_DECL
+unsigned long yasm_section_get_opt_flags(const yasm_section *sect);
+
+/** Set yasm_optimizer-specific flags. For yasm_optimizer use only.
+ * \param sect section
+ * \param opt_flags optimizer-specific flags.
+ */
+YASM_LIB_DECL
+void yasm_section_set_opt_flags(yasm_section *sect, unsigned long opt_flags);
+
+/** Determine if a section was declared as the "default" section (e.g. not
+ * created through a section directive).
+ * \param sect section
+ * \return Nonzero if section was declared as default.
+ */
+YASM_LIB_DECL
+int yasm_section_is_default(const yasm_section *sect);
+
+/** Set section "default" flag to a new value.
+ * \param sect section
+ * \param def new value of default flag
+ */
+YASM_LIB_DECL
+void yasm_section_set_default(yasm_section *sect, int def);
+
+/** Get object owner of a section.
+ * \param sect section
+ * \return Object this section is a part of.
+ */
+YASM_LIB_DECL
+yasm_object *yasm_section_get_object(const yasm_section *sect);
+
+/** Get assocated data for a section and data callback.
+ * \param sect section
+ * \param callback callback used when adding data
+ * \return Associated data (NULL if none).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ void *yasm_section_get_data
+ (yasm_section *sect, const yasm_assoc_data_callback *callback);
+
+/** Add associated data to a section.
+ * \attention Deletes any existing associated data for that data callback.
+ * \param sect section
+ * \param callback callback
+ * \param data data to associate
+ */
+YASM_LIB_DECL
+void yasm_section_add_data(yasm_section *sect,
+ const yasm_assoc_data_callback *callback,
+ /*@null@*/ /*@only@*/ void *data);
+
+/** Add a relocation to a section.
+ * \param sect section
+ * \param reloc relocation
+ * \param destroy_func function that can destroy the relocation
+ * \note Does not make a copy of reloc. The same destroy_func must be
+ * used for all relocations in a section or an internal error will occur.
+ * The section will destroy the relocation address; it is the caller's
+ * responsibility to destroy any other allocated data.
+ */
+YASM_LIB_DECL
+void yasm_section_add_reloc(yasm_section *sect, yasm_reloc *reloc,
+ void (*destroy_func) (/*@only@*/ void *reloc));
+
+/** Get the first relocation for a section.
+ * \param sect section
+ * \return First relocation for section. NULL if no relocations.
+ */
+YASM_LIB_DECL
+/*@null@*/ yasm_reloc *yasm_section_relocs_first(yasm_section *sect);
+
+/** Get the next relocation for a section.
+ * \param reloc previous relocation
+ * \return Next relocation for section. NULL if no more relocations.
+ */
+/*@null@*/ yasm_reloc *yasm_section_reloc_next(yasm_reloc *reloc);
+#ifndef YASM_DOXYGEN
+#define yasm_section_reloc_next(x) STAILQ_NEXT((x), link)
+#endif
+
+/** Get the basic relocation information for a relocation.
+ * \param reloc relocation
+ * \param addrp address of relocation within section (returned)
+ * \param symp relocated symbol (returned)
+ */
+YASM_LIB_DECL
+void yasm_reloc_get(yasm_reloc *reloc, yasm_intnum **addrp,
+ /*@dependent@*/ yasm_symrec **symp);
+
+/** Get the first bytecode in a section.
+ * \param sect section
+ * \return First bytecode in section (at least one empty bytecode is always
+ * present).
+ */
+YASM_LIB_DECL
+yasm_bytecode *yasm_section_bcs_first(yasm_section *sect);
+
+/** Get the last bytecode in a section.
+ * \param sect section
+ * \return Last bytecode in section (at least one empty bytecode is always
+ * present).
+ */
+YASM_LIB_DECL
+yasm_bytecode *yasm_section_bcs_last(yasm_section *sect);
+
+/** Add bytecode to the end of a section.
+ * \note Does not make a copy of bc; so don't pass this function static or
+ * local variables, and discard the bc pointer after calling this
+ * function.
+ * \param sect section
+ * \param bc bytecode (may be NULL)
+ * \return If bytecode was actually appended (it wasn't NULL or empty), the
+ * bytecode; otherwise NULL.
+ */
+YASM_LIB_DECL
+/*@only@*/ /*@null@*/ yasm_bytecode *yasm_section_bcs_append
+ (yasm_section *sect,
+ /*@returned@*/ /*@only@*/ /*@null@*/ yasm_bytecode *bc);
+
+/** Traverses all bytecodes in a section, calling a function on each bytecode.
+ * \param sect section
+ * \param errwarns error/warning set (may be NULL)
+ * \param d data pointer passed to func on each call (may be NULL)
+ * \param func function
+ * \return Stops early (and returns func's return value) if func returns a
+ * nonzero value; otherwise 0.
+ * \note If errwarns is non-NULL, yasm_errwarn_propagate() is called after
+ * each call to func (with the bytecode's line number).
+ */
+YASM_LIB_DECL
+int yasm_section_bcs_traverse
+ (yasm_section *sect, /*@null@*/ yasm_errwarns *errwarns,
+ /*@null@*/ void *d, int (*func) (yasm_bytecode *bc, /*@null@*/ void *d));
+
+/** Get name of a section.
+ * \param sect section
+ * \return Section name.
+ */
+YASM_LIB_DECL
+/*@observer@*/ const char *yasm_section_get_name(const yasm_section *sect);
+
+/** Change alignment of a section.
+ * \param sect section
+ * \param align alignment in bytes
+ * \param line virtual line
+ */
+YASM_LIB_DECL
+void yasm_section_set_align(yasm_section *sect, unsigned long align,
+ unsigned long line);
+
+/** Get alignment of a section.
+ * \param sect section
+ * \return Alignment in bytes (0 if none).
+ */
+YASM_LIB_DECL
+unsigned long yasm_section_get_align(const yasm_section *sect);
+
+/** Print a section. For debugging purposes.
+ * \param f file
+ * \param indent_level indentation level
+ * \param sect section
+ * \param print_bcs if nonzero, print bytecodes within section
+ */
+YASM_LIB_DECL
+void yasm_section_print(/*@null@*/ const yasm_section *sect, FILE *f,
+ int indent_level, int print_bcs);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/strcasecmp.c b/contrib/tools/yasm/libyasm/strcasecmp.c
new file mode 100644
index 0000000000..a87bd88bc9
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/strcasecmp.c
@@ -0,0 +1,94 @@
+/*
+ * strcasecmp() implementation for systems that don't have it or stricmp()
+ * or strcmpi().
+ *
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND 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 REGENTS OR 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 "util.h"
+
+#ifndef USE_OUR_OWN_STRCASECMP
+#undef yasm__strcasecmp
+#undef yasm__strncasecmp
+#endif
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <ctype.h>
+
+int
+yasm__strcasecmp(const char *s1, const char *s2)
+{
+#ifdef HAVE_STRCASECMP
+ return strcasecmp(s1, s2);
+#elif HAVE_STRICMP
+ return stricmp(s1, s2);
+#elif HAVE__STRICMP
+ return _stricmp(s1, s2);
+#elif HAVE_STRCMPI
+ return strcmpi(s1, s2);
+#else
+ const unsigned char
+ *us1 = (const unsigned char *)s1,
+ *us2 = (const unsigned char *)s2;
+
+ while (tolower(*us1) == tolower(*us2++))
+ if (*us1++ == '\0')
+ return (0);
+ return (tolower(*us1) - tolower(*--us2));
+#endif
+}
+
+int
+yasm__strncasecmp(const char *s1, const char *s2, size_t n)
+{
+#ifdef HAVE_STRCASECMP
+ return strncasecmp(s1, s2, n);
+#elif HAVE_STRICMP
+ return strnicmp(s1, s2, n);
+#elif HAVE__STRNICMP
+ return _strnicmp(s1, s2, n);
+#elif HAVE_STRCMPI
+ return strncmpi(s1, s2, n);
+#else
+ const unsigned char
+ *us1 = (const unsigned char *)s1,
+ *us2 = (const unsigned char *)s2;
+
+ if (n != 0) {
+ do {
+ if (tolower(*us1) != tolower(*us2++))
+ return (tolower(*us1) - tolower(*--us2));
+ if (*us1++ == '\0')
+ break;
+ } while (--n != 0);
+ }
+ return (0);
+#endif
+}
diff --git a/contrib/tools/yasm/libyasm/strsep.c b/contrib/tools/yasm/libyasm/strsep.c
new file mode 100644
index 0000000000..5688a60879
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/strsep.c
@@ -0,0 +1,85 @@
+/*
+ * strsep() implementation for systems that don't have it.
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND 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 REGENTS OR 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.
+ */
+#define NO_STRING_INLINES
+#include "util.h"
+
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef HAVE_STRSEP
+#undef yasm__strsep
+#endif
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+/*@-nullstate@*/
+char *
+yasm__strsep(char **stringp, const char *delim)
+{
+#ifdef HAVE_STRSEP
+ return strsep(stringp, delim);
+#else
+ char *s;
+ const char *spanp;
+ int c, sc;
+ char *tok;
+
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+#endif
+}
+/*@=nullstate@*/
diff --git a/contrib/tools/yasm/libyasm/symrec.c b/contrib/tools/yasm/libyasm/symrec.c
new file mode 100644
index 0000000000..694f0c6768
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/symrec.c
@@ -0,0 +1,714 @@
+/*
+ * Symbol table handling
+ *
+ * Copyright (C) 2001-2007 Michael Urman, 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 "util.h"
+
+#include <limits.h>
+#include <ctype.h>
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+#include "valparam.h"
+#include "hamt.h"
+#include "assocdat.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "floatnum.h"
+#include "expr.h"
+#include "symrec.h"
+
+#include "bytecode.h"
+#include "section.h"
+#include "objfmt.h"
+
+
+typedef enum {
+ SYM_UNKNOWN, /* for unknown type (COMMON/EXTERN) */
+ SYM_EQU, /* for EQU defined symbols (expressions) */
+ SYM_LABEL, /* for labels */
+ SYM_CURPOS, /* for labels representing the current
+ assembly position */
+ SYM_SPECIAL /* for special symbols that need to be in
+ the symbol table but otherwise have no
+ purpose */
+} sym_type;
+
+struct yasm_symrec {
+ char *name;
+ sym_type type;
+ yasm_sym_status status;
+ yasm_sym_vis visibility;
+ unsigned long def_line; /* line where symbol was first defined */
+ unsigned long decl_line; /* line where symbol was first declared */
+ unsigned long use_line; /* line where symbol was first used */
+ union {
+ yasm_expr *expn; /* equ value */
+
+ /* bytecode immediately preceding a label */
+ /*@dependent@*/ yasm_bytecode *precbc;
+ } value;
+ unsigned int size; /* 0 if not user-defined */
+ const char *segment; /* for segmented systems like DOS */
+
+ /* associated data; NULL if none */
+ /*@null@*/ /*@only@*/ yasm__assoc_data *assoc_data;
+};
+
+/* Linked list of symbols not in the symbol table. */
+typedef struct non_table_symrec_s {
+ /*@reldef@*/ SLIST_ENTRY(non_table_symrec_s) link;
+ /*@owned@*/ yasm_symrec *rec;
+} non_table_symrec;
+
+struct yasm_symtab {
+ /* The symbol table: a hash array mapped trie (HAMT). */
+ /*@only@*/ HAMT *sym_table;
+ /* Symbols not in the table */
+ SLIST_HEAD(nontablesymhead_s, non_table_symrec_s) non_table_syms;
+
+ int case_sensitive;
+};
+
+static void
+objext_valparams_destroy(void *data)
+{
+ yasm_vps_destroy((yasm_valparamhead *)data);
+}
+
+static void
+objext_valparams_print(void *data, FILE *f, int indent_level)
+{
+ yasm_vps_print((yasm_valparamhead *)data, f);
+}
+
+static yasm_assoc_data_callback objext_valparams_cb = {
+ objext_valparams_destroy,
+ objext_valparams_print
+};
+
+static void
+common_size_destroy(void *data)
+{
+ yasm_expr **e = (yasm_expr **)data;
+ yasm_expr_destroy(*e);
+ yasm_xfree(data);
+}
+
+static void
+common_size_print(void *data, FILE *f, int indent_level)
+{
+ yasm_expr **e = (yasm_expr **)data;
+ yasm_expr_print(*e, f);
+}
+
+static yasm_assoc_data_callback common_size_cb = {
+ common_size_destroy,
+ common_size_print
+};
+
+yasm_symtab *
+yasm_symtab_create(void)
+{
+ yasm_symtab *symtab = yasm_xmalloc(sizeof(yasm_symtab));
+ symtab->sym_table = HAMT_create(0, yasm_internal_error_);
+ SLIST_INIT(&symtab->non_table_syms);
+ symtab->case_sensitive = 1;
+ return symtab;
+}
+
+void
+yasm_symtab_set_case_sensitive(yasm_symtab *symtab, int sensitive)
+{
+ symtab->case_sensitive = sensitive;
+}
+
+static void
+symrec_destroy_one(/*@only@*/ void *d)
+{
+ yasm_symrec *sym = d;
+ yasm_xfree(sym->name);
+ if (sym->type == SYM_EQU && (sym->status & YASM_SYM_VALUED))
+ yasm_expr_destroy(sym->value.expn);
+ yasm__assoc_data_destroy(sym->assoc_data);
+ yasm_xfree(sym);
+}
+
+static /*@partial@*/ yasm_symrec *
+symrec_new_common(/*@keep@*/ char *name, int case_sensitive)
+{
+ yasm_symrec *rec = yasm_xmalloc(sizeof(yasm_symrec));
+
+ if (!case_sensitive) {
+ char *c;
+ for (c=name; *c; c++)
+ *c = tolower(*c);
+ }
+
+ rec->name = name;
+ rec->type = SYM_UNKNOWN;
+ rec->def_line = 0;
+ rec->decl_line = 0;
+ rec->use_line = 0;
+ rec->visibility = YASM_SYM_LOCAL;
+ rec->size = 0;
+ rec->segment = NULL;
+ rec->assoc_data = NULL;
+ return rec;
+}
+
+static /*@partial@*/ /*@dependent@*/ yasm_symrec *
+symtab_get_or_new_in_table(yasm_symtab *symtab, /*@only@*/ char *name)
+{
+ yasm_symrec *rec = symrec_new_common(name, symtab->case_sensitive);
+ int replace = 0;
+
+ rec->status = YASM_SYM_NOSTATUS;
+
+ if (!symtab->case_sensitive) {
+ char *c;
+ for (c=name; *c; c++)
+ *c = tolower(*c);
+ }
+
+ return HAMT_insert(symtab->sym_table, name, rec, &replace,
+ symrec_destroy_one);
+}
+
+static /*@partial@*/ /*@dependent@*/ yasm_symrec *
+symtab_get_or_new_not_in_table(yasm_symtab *symtab, /*@only@*/ char *name)
+{
+ non_table_symrec *sym = yasm_xmalloc(sizeof(non_table_symrec));
+ sym->rec = symrec_new_common(name, symtab->case_sensitive);
+
+ sym->rec->status = YASM_SYM_NOTINTABLE;
+
+ SLIST_INSERT_HEAD(&symtab->non_table_syms, sym, link);
+
+ return sym->rec;
+}
+
+/* create a new symrec */
+/*@-freshtrans -mustfree@*/
+static /*@partial@*/ /*@dependent@*/ yasm_symrec *
+symtab_get_or_new(yasm_symtab *symtab, const char *name, int in_table)
+{
+ char *symname = yasm__xstrdup(name);
+
+ if (in_table)
+ return symtab_get_or_new_in_table(symtab, symname);
+ else
+ return symtab_get_or_new_not_in_table(symtab, symname);
+}
+/*@=freshtrans =mustfree@*/
+
+int
+yasm_symtab_traverse(yasm_symtab *symtab, void *d,
+ int (*func) (yasm_symrec *sym, void *d))
+{
+ return HAMT_traverse(symtab->sym_table, d, (int (*) (void *, void *))func);
+}
+
+const yasm_symtab_iter *
+yasm_symtab_first(const yasm_symtab *symtab)
+{
+ return (const yasm_symtab_iter *)HAMT_first(symtab->sym_table);
+}
+
+/*@null@*/ const yasm_symtab_iter *
+yasm_symtab_next(const yasm_symtab_iter *prev)
+{
+ return (const yasm_symtab_iter *)HAMT_next((const HAMTEntry *)prev);
+}
+
+yasm_symrec *
+yasm_symtab_iter_value(const yasm_symtab_iter *cur)
+{
+ return (yasm_symrec *)HAMTEntry_get_data((const HAMTEntry *)cur);
+}
+
+yasm_symrec *
+yasm_symtab_abs_sym(yasm_symtab *symtab)
+{
+ yasm_symrec *rec = symtab_get_or_new(symtab, "", 1);
+ rec->def_line = 0;
+ rec->decl_line = 0;
+ rec->use_line = 0;
+ rec->type = SYM_EQU;
+ rec->value.expn =
+ yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(0)), 0);
+ rec->status |= YASM_SYM_DEFINED|YASM_SYM_VALUED|YASM_SYM_USED;
+ return rec;
+}
+
+yasm_symrec *
+yasm_symtab_use(yasm_symtab *symtab, const char *name, unsigned long line)
+{
+ yasm_symrec *rec = symtab_get_or_new(symtab, name, 1);
+ if (rec->use_line == 0)
+ rec->use_line = line; /* set line number of first use */
+ rec->status |= YASM_SYM_USED;
+ return rec;
+}
+
+yasm_symrec *
+yasm_symtab_get(yasm_symtab *symtab, const char *name)
+{
+ if (!symtab->case_sensitive) {
+ char *_name = yasm__xstrdup(name);
+ char *c;
+ yasm_symrec *ret;
+ for (c=_name; *c; c++)
+ *c = tolower(*c);
+ ret = HAMT_search(symtab->sym_table, _name);
+ yasm_xfree(_name);
+ return ret;
+ } else
+ return HAMT_search(symtab->sym_table, name);
+}
+
+static /*@dependent@*/ yasm_symrec *
+symtab_define(yasm_symtab *symtab, const char *name, sym_type type,
+ int in_table, unsigned long line)
+{
+ yasm_symrec *rec = symtab_get_or_new(symtab, name, in_table);
+
+ /* Has it been defined before (either by DEFINED or COMMON/EXTERN)? */
+ if (rec->status & YASM_SYM_DEFINED) {
+ yasm_error_set_xref(rec->def_line!=0 ? rec->def_line : rec->decl_line,
+ N_("`%s' previously defined here"), name);
+ yasm_error_set(YASM_ERROR_GENERAL, N_("redefinition of `%s'"),
+ name);
+ } else {
+ if (rec->visibility & YASM_SYM_EXTERN)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("`%s' both defined and declared extern"), name);
+ rec->def_line = line; /* set line number of definition */
+ rec->type = type;
+ rec->status |= YASM_SYM_DEFINED;
+ rec->size = 0;
+ rec->segment = NULL;
+ }
+ return rec;
+}
+
+yasm_symrec *
+yasm_symtab_define_equ(yasm_symtab *symtab, const char *name, yasm_expr *e,
+ unsigned long line)
+{
+ yasm_symrec *rec = symtab_define(symtab, name, SYM_EQU, 1, line);
+ if (yasm_error_occurred())
+ return rec;
+ rec->value.expn = e;
+ rec->status |= YASM_SYM_VALUED;
+ return rec;
+}
+
+yasm_symrec *
+yasm_symtab_define_label(yasm_symtab *symtab, const char *name,
+ yasm_bytecode *precbc, int in_table,
+ unsigned long line)
+{
+ yasm_symrec *rec = symtab_define(symtab, name, SYM_LABEL, in_table, line);
+ if (yasm_error_occurred())
+ return rec;
+ rec->value.precbc = precbc;
+ if (in_table && precbc)
+ yasm_bc__add_symrec(precbc, rec);
+ return rec;
+}
+
+yasm_symrec *
+yasm_symtab_define_curpos(yasm_symtab *symtab, const char *name,
+ yasm_bytecode *precbc, unsigned long line)
+{
+ yasm_symrec *rec = symtab_define(symtab, name, SYM_CURPOS, 0, line);
+ if (yasm_error_occurred())
+ return rec;
+ rec->value.precbc = precbc;
+ return rec;
+}
+
+yasm_symrec *
+yasm_symtab_define_special(yasm_symtab *symtab, const char *name,
+ yasm_sym_vis vis)
+{
+ yasm_symrec *rec = symtab_define(symtab, name, SYM_SPECIAL, 1, 0);
+ if (yasm_error_occurred())
+ return rec;
+ rec->status |= YASM_SYM_VALUED;
+ rec->visibility = vis;
+ return rec;
+}
+
+yasm_symrec *
+yasm_symtab_declare(yasm_symtab *symtab, const char *name, yasm_sym_vis vis,
+ unsigned long line)
+{
+ yasm_symrec *rec = symtab_get_or_new(symtab, name, 1);
+ yasm_symrec_declare(rec, vis, line);
+ return rec;
+}
+
+void
+yasm_symrec_declare(yasm_symrec *rec, yasm_sym_vis vis, unsigned long line)
+{
+ /* Allowable combinations:
+ * Existing State-------------- vis New State-------------------
+ * DEFINED GLOBAL COMMON EXTERN GCE DEFINED GLOBAL COMMON EXTERN
+ * 0 - 0 0 GCE 0 G C E
+ * 0 - 0 1 GE 0 G 0 E
+ * 0 - 1 0 GC 0 G C 0
+ * X 0 - 1 1
+ * 1 - 0 0 G 1 G 0 0
+ * X 1 - - 1
+ * X 1 - 1 -
+ */
+ if ((vis == YASM_SYM_GLOBAL) ||
+ (!(rec->status & YASM_SYM_DEFINED) &&
+ (!(rec->visibility & (YASM_SYM_COMMON | YASM_SYM_EXTERN)) ||
+ ((rec->visibility & YASM_SYM_COMMON) && (vis == YASM_SYM_COMMON)) ||
+ ((rec->visibility & YASM_SYM_EXTERN) && (vis == YASM_SYM_EXTERN))))) {
+ rec->decl_line = line;
+ rec->visibility |= vis;
+ } else
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("duplicate definition of `%s'; first defined on line %lu"),
+ rec->name, rec->def_line!=0 ? rec->def_line : rec->decl_line);
+}
+
+typedef struct symtab_finalize_info {
+ unsigned long firstundef_line;
+ int undef_extern;
+ yasm_errwarns *errwarns;
+} symtab_finalize_info;
+
+static int
+symtab_parser_finalize_checksym(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ symtab_finalize_info *info = (symtab_finalize_info *)d;
+
+ /* error if a symbol is used but never defined or extern/common declared */
+ if ((sym->status & YASM_SYM_USED) && !(sym->status & YASM_SYM_DEFINED) &&
+ !(sym->visibility & (YASM_SYM_EXTERN | YASM_SYM_COMMON))) {
+ if (info->undef_extern)
+ sym->visibility |= YASM_SYM_EXTERN;
+ else {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("undefined symbol `%s' (first use)"), sym->name);
+ yasm_errwarn_propagate(info->errwarns, sym->use_line);
+ if (sym->use_line < info->firstundef_line)
+ info->firstundef_line = sym->use_line;
+ }
+ }
+
+ return 0;
+}
+
+void
+yasm_symtab_parser_finalize(yasm_symtab *symtab, int undef_extern,
+ yasm_errwarns *errwarns)
+{
+ symtab_finalize_info info;
+ info.firstundef_line = ULONG_MAX;
+ info.undef_extern = undef_extern;
+ info.errwarns = errwarns;
+ yasm_symtab_traverse(symtab, &info, symtab_parser_finalize_checksym);
+ if (info.firstundef_line < ULONG_MAX) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_(" (Each undefined symbol is reported only once.)"));
+ yasm_errwarn_propagate(errwarns, info.firstundef_line);
+ }
+}
+
+void
+yasm_symtab_destroy(yasm_symtab *symtab)
+{
+ HAMT_destroy(symtab->sym_table, symrec_destroy_one);
+
+ while (!SLIST_EMPTY(&symtab->non_table_syms)) {
+ non_table_symrec *sym = SLIST_FIRST(&symtab->non_table_syms);
+ SLIST_REMOVE_HEAD(&symtab->non_table_syms, link);
+ symrec_destroy_one(sym->rec);
+ yasm_xfree(sym);
+ }
+
+ yasm_xfree(symtab);
+}
+
+typedef struct symrec_print_data {
+ FILE *f;
+ int indent_level;
+} symrec_print_data;
+
+/*@+voidabstract@*/
+static int
+symrec_print_wrapper(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ symrec_print_data *data = (symrec_print_data *)d;
+ assert(data != NULL);
+ fprintf(data->f, "%*sSymbol `%s'\n", data->indent_level, "", sym->name);
+ yasm_symrec_print(sym, data->f, data->indent_level+1);
+ return 0;
+}
+
+void
+yasm_symtab_print(yasm_symtab *symtab, FILE *f, int indent_level)
+{
+ symrec_print_data data;
+ data.f = f;
+ data.indent_level = indent_level;
+ yasm_symtab_traverse(symtab, &data, symrec_print_wrapper);
+}
+/*@=voidabstract@*/
+
+const char *
+yasm_symrec_get_name(const yasm_symrec *sym)
+{
+ return sym->name;
+}
+
+char *
+yasm_symrec_get_global_name(const yasm_symrec *sym, const yasm_object *object)
+{
+ if (sym->visibility & (YASM_SYM_GLOBAL|YASM_SYM_COMMON|YASM_SYM_EXTERN)) {
+ char *name = yasm_xmalloc(strlen(object->global_prefix) +
+ strlen(sym->name) +
+ strlen(object->global_suffix) + 1);
+ strcpy(name, object->global_prefix);
+ strcat(name, sym->name);
+ strcat(name, object->global_suffix);
+ return name;
+ }
+ return yasm__xstrdup(sym->name);
+}
+
+yasm_sym_vis
+yasm_symrec_get_visibility(const yasm_symrec *sym)
+{
+ return sym->visibility;
+}
+
+yasm_sym_status
+yasm_symrec_get_status(const yasm_symrec *sym)
+{
+ return sym->status;
+}
+
+unsigned long
+yasm_symrec_get_def_line(const yasm_symrec *sym)
+{
+ return sym->def_line;
+}
+
+unsigned long
+yasm_symrec_get_decl_line(const yasm_symrec *sym)
+{
+ return sym->decl_line;
+}
+
+unsigned long
+yasm_symrec_get_use_line(const yasm_symrec *sym)
+{
+ return sym->use_line;
+}
+
+const yasm_expr *
+yasm_symrec_get_equ(const yasm_symrec *sym)
+{
+ if (sym->type == SYM_EQU && (sym->status & YASM_SYM_VALUED))
+ return sym->value.expn;
+ return (const yasm_expr *)NULL;
+}
+
+int
+yasm_symrec_get_label(const yasm_symrec *sym,
+ yasm_symrec_get_label_bytecodep *precbc)
+{
+ if (!(sym->type == SYM_LABEL || sym->type == SYM_CURPOS)
+ || !sym->value.precbc) {
+ *precbc = (yasm_symrec_get_label_bytecodep)0xDEADBEEF;
+ return 0;
+ }
+ *precbc = sym->value.precbc;
+ return 1;
+}
+
+void
+yasm_symrec_set_size(yasm_symrec *sym, int size)
+{
+ sym->size = size;
+}
+
+int
+yasm_symrec_get_size(const yasm_symrec *sym)
+{
+ return sym->size;
+}
+
+void
+yasm_symrec_set_segment(yasm_symrec *sym, const char *segment)
+{
+ sym->segment = segment;
+}
+
+const char *
+yasm_symrec_get_segment(const yasm_symrec *sym)
+{
+ return sym->segment;
+}
+
+int
+yasm_symrec_is_abs(const yasm_symrec *sym)
+{
+ return (sym->def_line == 0 && sym->type == SYM_EQU &&
+ sym->name[0] == '\0');
+}
+
+int
+yasm_symrec_is_special(const yasm_symrec *sym)
+{
+ return (sym->type == SYM_SPECIAL);
+}
+
+int
+yasm_symrec_is_curpos(const yasm_symrec *sym)
+{
+ return (sym->type == SYM_CURPOS);
+}
+
+void
+yasm_symrec_set_objext_valparams(yasm_symrec *sym,
+ /*@only@*/ yasm_valparamhead *objext_valparams)
+{
+ yasm_symrec_add_data(sym, &objext_valparams_cb, objext_valparams);
+}
+
+yasm_valparamhead *
+yasm_symrec_get_objext_valparams(yasm_symrec *sym)
+{
+ return yasm_symrec_get_data(sym, &objext_valparams_cb);
+}
+
+void
+yasm_symrec_set_common_size(yasm_symrec *sym,
+ /*@only@*/ yasm_expr *common_size)
+{
+ yasm_expr **ep = yasm_xmalloc(sizeof(yasm_expr *));
+ *ep = common_size;
+ yasm_symrec_add_data(sym, &common_size_cb, ep);
+}
+
+yasm_expr **
+yasm_symrec_get_common_size(yasm_symrec *sym)
+{
+ return (yasm_expr **)yasm_symrec_get_data(sym, &common_size_cb);
+}
+
+void *
+yasm_symrec_get_data(yasm_symrec *sym,
+ const yasm_assoc_data_callback *callback)
+{
+ return yasm__assoc_data_get(sym->assoc_data, callback);
+}
+
+void
+yasm_symrec_add_data(yasm_symrec *sym,
+ const yasm_assoc_data_callback *callback, void *data)
+{
+ sym->assoc_data = yasm__assoc_data_add(sym->assoc_data, callback, data);
+}
+
+void
+yasm_symrec_print(const yasm_symrec *sym, FILE *f, int indent_level)
+{
+ switch (sym->type) {
+ case SYM_UNKNOWN:
+ fprintf(f, "%*s-Unknown (Common/Extern)-\n", indent_level, "");
+ break;
+ case SYM_EQU:
+ fprintf(f, "%*s_EQU_\n", indent_level, "");
+ fprintf(f, "%*sExpn=", indent_level, "");
+ if (sym->status & YASM_SYM_VALUED)
+ yasm_expr_print(sym->value.expn, f);
+ else
+ fprintf(f, "***UNVALUED***");
+ fprintf(f, "\n");
+ break;
+ case SYM_LABEL:
+ case SYM_CURPOS:
+ fprintf(f, "%*s_%s_\n%*sSection:\n", indent_level, "",
+ sym->type == SYM_LABEL ? "Label" : "CurPos",
+ indent_level, "");
+ yasm_section_print(yasm_bc_get_section(sym->value.precbc), f,
+ indent_level+1, 0);
+ fprintf(f, "%*sPreceding bytecode:\n", indent_level, "");
+ yasm_bc_print(sym->value.precbc, f, indent_level+1);
+ break;
+ case SYM_SPECIAL:
+ fprintf(f, "%*s-Special-\n", indent_level, "");
+ break;
+ }
+
+ fprintf(f, "%*sStatus=", indent_level, "");
+ if (sym->status == YASM_SYM_NOSTATUS)
+ fprintf(f, "None\n");
+ else {
+ if (sym->status & YASM_SYM_USED)
+ fprintf(f, "Used,");
+ if (sym->status & YASM_SYM_DEFINED)
+ fprintf(f, "Defined,");
+ if (sym->status & YASM_SYM_VALUED)
+ fprintf(f, "Valued,");
+ if (sym->status & YASM_SYM_NOTINTABLE)
+ fprintf(f, "Not in Table,");
+ fprintf(f, "\n");
+ }
+
+ fprintf(f, "%*sVisibility=", indent_level, "");
+ if (sym->visibility == YASM_SYM_LOCAL)
+ fprintf(f, "Local\n");
+ else {
+ if (sym->visibility & YASM_SYM_GLOBAL)
+ fprintf(f, "Global,");
+ if (sym->visibility & YASM_SYM_COMMON)
+ fprintf(f, "Common,");
+ if (sym->visibility & YASM_SYM_EXTERN)
+ fprintf(f, "Extern,");
+ fprintf(f, "\n");
+ }
+
+ if (sym->assoc_data) {
+ fprintf(f, "%*sAssociated data:\n", indent_level, "");
+ yasm__assoc_data_print(sym->assoc_data, f, indent_level+1);
+ }
+
+ fprintf(f, "%*sLine Index (Defined)=%lu\n", indent_level, "",
+ sym->def_line);
+ fprintf(f, "%*sLine Index (Declared)=%lu\n", indent_level, "",
+ sym->decl_line);
+ fprintf(f, "%*sLine Index (Used)=%lu\n", indent_level, "", sym->use_line);
+}
diff --git a/contrib/tools/yasm/libyasm/symrec.h b/contrib/tools/yasm/libyasm/symrec.h
new file mode 100644
index 0000000000..b1f797c647
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/symrec.h
@@ -0,0 +1,437 @@
+/**
+ * \file libyasm/symrec.h
+ * \brief YASM symbol table interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Michael Urman, Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_SYMREC_H
+#define YASM_SYMREC_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Symbol status. YASM_SYM_DEFINED is set by yasm_symtab_define_label(),
+ * yasm_symtab_define_equ(), or yasm_symtab_declare()/yasm_symrec_declare()
+ * with a visibility of #YASM_SYM_EXTERN or #YASM_SYM_COMMON.
+ */
+typedef enum yasm_sym_status {
+ YASM_SYM_NOSTATUS = 0, /**< no status */
+ YASM_SYM_USED = 1 << 0, /**< for use before definition */
+ YASM_SYM_DEFINED = 1 << 1, /**< once it's been defined in the file */
+ YASM_SYM_VALUED = 1 << 2, /**< once its value has been determined */
+ YASM_SYM_NOTINTABLE = 1 << 3 /**< if it's not in sym_table (ex. '$') */
+} yasm_sym_status;
+
+/** Symbol record visibility.
+ * \note YASM_SYM_EXTERN and YASM_SYM_COMMON are mutually exclusive.
+ */
+typedef enum yasm_sym_vis {
+ YASM_SYM_LOCAL = 0, /**< Default, local only */
+ YASM_SYM_GLOBAL = 1 << 0, /**< If symbol is declared GLOBAL */
+ YASM_SYM_COMMON = 1 << 1, /**< If symbol is declared COMMON */
+ YASM_SYM_EXTERN = 1 << 2, /**< If symbol is declared EXTERN */
+ YASM_SYM_DLOCAL = 1 << 3 /**< If symbol is explicitly declared LOCAL */
+} yasm_sym_vis;
+
+/** Create a new symbol table. */
+YASM_LIB_DECL
+yasm_symtab *yasm_symtab_create(void);
+
+/** Destroy a symbol table and all internal symbols.
+ * \param symtab symbol table
+ * \warning All yasm_symrec *'s into this symbol table become invalid after
+ * this is called!
+ */
+YASM_LIB_DECL
+void yasm_symtab_destroy(/*@only@*/ yasm_symtab *symtab);
+
+/** Set the symbol table to be case sensitive or not.
+ * Should be called before adding any symbol.
+ * \param symtab symbol table
+ * \param sensitive whether the symbol table should be case sensitive.
+ */
+YASM_LIB_DECL
+void yasm_symtab_set_case_sensitive(yasm_symtab *symtab, int sensitive);
+
+/** Get a reference to the symbol table's "absolute" symbol. This is
+ * essentially an EQU with no name and value 0, and is used for relocating
+ * absolute current-position-relative values.
+ * \see yasm_value_set_curpos_rel().
+ * \param symtab symbol table
+ * \return Absolute symbol (dependent pointer, do not free).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_symrec *yasm_symtab_abs_sym(yasm_symtab *symtab);
+
+/** Get a reference to (use) a symbol. The symbol does not necessarily need to
+ * be defined before it is used.
+ * \param symtab symbol table
+ * \param name symbol name
+ * \param line virtual line where referenced
+ * \return Symbol (dependent pointer, do not free).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_symrec *yasm_symtab_use
+ (yasm_symtab *symtab, const char *name, unsigned long line);
+
+/** Get a reference to a symbol, without "using" it. Should be used for cases
+ * when an internal assembler usage of a symbol shouldn't be treated like a
+ * normal user symbol usage.
+ * \param symtab symbol table
+ * \param name symbol name
+ * \return Symbol (dependent pointer, do not free). May be NULL if symbol
+ * doesn't exist.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@dependent@*/ yasm_symrec *yasm_symtab_get
+ (yasm_symtab *symtab, const char *name);
+
+/** Define a symbol as an EQU value.
+ * \param symtab symbol table
+ * \param name symbol (EQU) name
+ * \param e EQU value (expression)
+ * \param line virtual line of EQU
+ * \return Symbol (dependent pointer, do not free).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_symrec *yasm_symtab_define_equ
+ (yasm_symtab *symtab, const char *name, /*@keep@*/ yasm_expr *e,
+ unsigned long line);
+
+/** Define a symbol as a label.
+ * \param symtab symbol table
+ * \param name symbol (label) name
+ * \param precbc bytecode preceding label
+ * \param in_table nonzero if the label should be inserted into the symbol
+ * table (some specially-generated ones should not be)
+ * \param line virtual line of label
+ * \return Symbol (dependent pointer, do not free).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_symrec *yasm_symtab_define_label
+ (yasm_symtab *symtab, const char *name,
+ /*@dependent@*/ yasm_bytecode *precbc, int in_table, unsigned long line);
+
+/** Define a symbol as a label representing the current assembly position.
+ * This should be used for this purpose instead of yasm_symtab_define_label()
+ * as value_finalize_scan() looks for usage of this symbol type for special
+ * handling. The symbol created is not inserted into the symbol table.
+ * \param symtab symbol table
+ * \param name symbol (label) name
+ * \param precbc bytecode preceding label
+ * \param line virtual line of label
+ * \return Symbol (dependent pointer, do not free).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_symrec *yasm_symtab_define_curpos
+ (yasm_symtab *symtab, const char *name,
+ /*@dependent@*/ yasm_bytecode *precbc, unsigned long line);
+
+/** Define a special symbol that will appear in the symbol table and have a
+ * defined name, but have no other data associated with it within the
+ * standard symrec.
+ * \param symtab symbol table
+ * \param name symbol name
+ * \param vis symbol visibility
+ * \return Symbol (dependent pointer, do not free).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_symrec *yasm_symtab_define_special
+ (yasm_symtab *symtab, const char *name, yasm_sym_vis vis);
+
+/** Declare external visibility of a symbol.
+ * \note Not all visibility combinations are allowed.
+ * \param symtab symbol table
+ * \param name symbol name
+ * \param vis visibility
+ * \param line virtual line of visibility-setting
+ * \return Symbol (dependent pointer, do not free).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ yasm_symrec *yasm_symtab_declare
+ (yasm_symtab *symtab, const char *name, yasm_sym_vis vis,
+ unsigned long line);
+
+/** Declare external visibility of a symbol.
+ * \note Not all visibility combinations are allowed.
+ * \param symrec symbol
+ * \param vis visibility
+ * \param line virtual line of visibility-setting
+ */
+YASM_LIB_DECL
+void yasm_symrec_declare(yasm_symrec *symrec, yasm_sym_vis vis,
+ unsigned long line);
+
+/** Callback function for yasm_symrec_traverse().
+ * \param sym symbol
+ * \param d data passed into yasm_symrec_traverse()
+ * \return Nonzero to stop symbol traversal.
+ */
+typedef int (*yasm_symtab_traverse_callback)
+ (yasm_symrec *sym, /*@null@*/ void *d);
+
+/** Traverse all symbols in the symbol table.
+ * \param symtab symbol table
+ * \param d data to pass to each call of callback function
+ * \param func callback function called on each symbol
+ * \return Nonzero value returned by callback function if it ever returned
+ * nonzero.
+ */
+YASM_LIB_DECL
+int /*@alt void@*/ yasm_symtab_traverse
+ (yasm_symtab *symtab, /*@null@*/ void *d,
+ yasm_symtab_traverse_callback func);
+
+/** Symbol table iterator (opaque type). */
+typedef struct yasm_symtab_iter yasm_symtab_iter;
+
+/** Get an iterator pointing to the first symbol in the symbol table.
+ * \param symtab symbol table
+ * \return Iterator for the symbol table.
+ */
+YASM_LIB_DECL
+const yasm_symtab_iter *yasm_symtab_first(const yasm_symtab *symtab);
+
+/** Move a symbol table iterator to the next symbol in the symbol table.
+ * \param prev Previous iterator value
+ * \return Next iterator value, or NULL if no more symbols in the table.
+ */
+YASM_LIB_DECL
+/*@null@*/ const yasm_symtab_iter *yasm_symtab_next
+ (const yasm_symtab_iter *prev);
+
+/** Get the symbol corresponding to the current symbol table iterator value.
+ * \param cur iterator value
+ * \return Corresponding symbol.
+ */
+YASM_LIB_DECL
+yasm_symrec *yasm_symtab_iter_value(const yasm_symtab_iter *cur);
+
+/** Finalize symbol table after parsing stage. Checks for symbols that are
+ * used but never defined or declared #YASM_SYM_EXTERN or #YASM_SYM_COMMON.
+ * \param symtab symbol table
+ * \param undef_extern if nonzero, all undef syms should be declared extern
+ * \param errwarns error/warning set
+ * \note Errors/warnings are stored into errwarns.
+ */
+YASM_LIB_DECL
+void yasm_symtab_parser_finalize(yasm_symtab *symtab, int undef_extern,
+ yasm_errwarns *errwarns);
+
+/** Print the symbol table. For debugging purposes.
+ * \param symtab symbol table
+ * \param f file
+ * \param indent_level indentation level
+ */
+YASM_LIB_DECL
+void yasm_symtab_print(yasm_symtab *symtab, FILE *f, int indent_level);
+
+/** Get the name of a symbol.
+ * \param sym symbol
+ * \return Symbol name.
+ */
+YASM_LIB_DECL
+/*@observer@*/ const char *yasm_symrec_get_name(const yasm_symrec *sym);
+
+/** Get the externally-visible (global) name of a symbol.
+ * \param sym symbol
+ * \param object object
+ * \return Externally-visible symbol name (allocated, caller must free).
+ */
+YASM_LIB_DECL
+/*@only@*/ char *yasm_symrec_get_global_name(const yasm_symrec *sym,
+ const yasm_object *object);
+
+/** Get the visibility of a symbol.
+ * \param sym symbol
+ * \return Symbol visibility.
+ */
+YASM_LIB_DECL
+yasm_sym_vis yasm_symrec_get_visibility(const yasm_symrec *sym);
+
+/** Get the status of a symbol.
+ * \param sym symbol
+ * \return Symbol status.
+ */
+YASM_LIB_DECL
+yasm_sym_status yasm_symrec_get_status(const yasm_symrec *sym);
+
+/** Get the virtual line of where a symbol was first defined.
+ * \param sym symbol
+ * \return line virtual line
+ */
+YASM_LIB_DECL
+unsigned long yasm_symrec_get_def_line(const yasm_symrec *sym);
+
+/** Get the virtual line of where a symbol was first declared.
+ * \param sym symbol
+ * \return line virtual line
+ */
+YASM_LIB_DECL
+unsigned long yasm_symrec_get_decl_line(const yasm_symrec *sym);
+
+/** Get the virtual line of where a symbol was first used.
+ * \param sym symbol
+ * \return line virtual line
+ */
+YASM_LIB_DECL
+unsigned long yasm_symrec_get_use_line(const yasm_symrec *sym);
+
+/** Get EQU value of a symbol.
+ * \param sym symbol
+ * \return EQU value, or NULL if symbol is not an EQU or is not defined.
+ */
+YASM_LIB_DECL
+/*@observer@*/ /*@null@*/ const yasm_expr *yasm_symrec_get_equ
+ (const yasm_symrec *sym);
+
+/** Dependent pointer to a bytecode. */
+typedef /*@dependent@*/ yasm_bytecode *yasm_symrec_get_label_bytecodep;
+
+/** Get the label location of a symbol.
+ * \param sym symbol
+ * \param precbc bytecode preceding label (output)
+ * \return 0 if not symbol is not a label or if the symbol's visibility is
+ * #YASM_SYM_EXTERN or #YASM_SYM_COMMON (not defined in the file).
+ */
+YASM_LIB_DECL
+int yasm_symrec_get_label(const yasm_symrec *sym,
+ /*@out@*/ yasm_symrec_get_label_bytecodep *precbc);
+
+/** Set the size of a symbol.
+ * \param sym symbol
+ * \param size size to be set
+ */
+YASM_LIB_DECL
+void yasm_symrec_set_size(yasm_symrec *sym, int size);
+
+/** Get the size of a symbol.
+ * \param sym symbol
+ * \return size of the symbol, 0 if none specified by the user.
+ */
+YASM_LIB_DECL
+int yasm_symrec_get_size(const yasm_symrec *sym);
+
+/** Set the segment of a symbol.
+ * \param sym symbol
+ * \param segment segment to be set
+ */
+YASM_LIB_DECL
+void yasm_symrec_set_segment(yasm_symrec *sym, const char *segment);
+
+/** Get the segment of a symbol.
+ * \param sym symbol
+ * \return segment of the symbol, NULL if none specified by the user.
+ */
+YASM_LIB_DECL
+const char *yasm_symrec_get_segment(const yasm_symrec *sym);
+
+/** Determine if symbol is the "absolute" symbol created by
+ * yasm_symtab_abs_sym().
+ * \param sym symbol
+ * \return 0 if symbol is not the "absolute" symbol, nonzero otherwise.
+ */
+YASM_LIB_DECL
+int yasm_symrec_is_abs(const yasm_symrec *sym);
+
+/** Determine if symbol is a special symbol.
+ * \param sym symbol
+ * \return 0 if symbol is not a special symbol, nonzero otherwise.
+ */
+YASM_LIB_DECL
+int yasm_symrec_is_special(const yasm_symrec *sym);
+
+/** Determine if symbol is a label representing the current assembly position.
+ * \param sym symbol
+ * \return 0 if symbol is not a current position label, nonzero otherwise.
+ */
+YASM_LIB_DECL
+int yasm_symrec_is_curpos(const yasm_symrec *sym);
+
+/** Set object-extended valparams.
+ * \param sym symbol
+ * \param objext_valparams object-extended valparams
+ */
+YASM_LIB_DECL
+void yasm_symrec_set_objext_valparams
+ (yasm_symrec *sym, /*@only@*/ yasm_valparamhead *objext_valparams);
+
+/** Get object-extended valparams, if any, associated with symbol's
+ * declaration.
+ * \param sym symbol
+ * \return Object-extended valparams (NULL if none).
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@dependent@*/ yasm_valparamhead *yasm_symrec_get_objext_valparams
+ (yasm_symrec *sym);
+
+/** Set common size of symbol.
+ * \param sym symbol
+ * \param common_size common size expression
+ */
+YASM_LIB_DECL
+void yasm_symrec_set_common_size
+ (yasm_symrec *sym, /*@only@*/ yasm_expr *common_size);
+
+/** Get common size of symbol, if symbol is declared COMMON and a size was set
+ * for it.
+ * \param sym symbol
+ * \return Common size (NULL if none).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ yasm_expr **yasm_symrec_get_common_size
+ (yasm_symrec *sym);
+
+/** Get associated data for a symbol and data callback.
+ * \param sym symbol
+ * \param callback callback used when adding data
+ * \return Associated data (NULL if none).
+ */
+YASM_LIB_DECL
+/*@dependent@*/ /*@null@*/ void *yasm_symrec_get_data
+ (yasm_symrec *sym, const yasm_assoc_data_callback *callback);
+
+/** Add associated data to a symbol.
+ * \attention Deletes any existing associated data for that data callback.
+ * \param sym symbol
+ * \param callback callback
+ * \param data data to associate
+ */
+YASM_LIB_DECL
+void yasm_symrec_add_data(yasm_symrec *sym,
+ const yasm_assoc_data_callback *callback,
+ /*@only@*/ /*@null@*/ void *data);
+
+/** Print a symbol. For debugging purposes.
+ * \param f file
+ * \param indent_level indentation level
+ * \param sym symbol
+ */
+YASM_LIB_DECL
+void yasm_symrec_print(const yasm_symrec *sym, FILE *f, int indent_level);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/valparam.c b/contrib/tools/yasm/libyasm/valparam.c
new file mode 100644
index 0000000000..88e41a7c5d
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/valparam.c
@@ -0,0 +1,385 @@
+/*
+ * Value/Parameter type functions
+ *
+ * Copyright (C) 2001-2007 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 "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+#include "valparam.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "expr.h"
+#include "symrec.h"
+
+#include "section.h"
+
+void
+yasm_call_directive(const yasm_directive *directive, yasm_object *object,
+ yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp;
+
+ if ((directive->flags & (YASM_DIR_ARG_REQUIRED|YASM_DIR_ID_REQUIRED)) &&
+ (!valparams || !yasm_vps_first(valparams))) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("directive `%s' requires an argument"),
+ directive->name);
+ return;
+ }
+ if (valparams) {
+ vp = yasm_vps_first(valparams);
+ if ((directive->flags & YASM_DIR_ID_REQUIRED) &&
+ vp->type != YASM_PARAM_ID) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("directive `%s' requires an identifier parameter"),
+ directive->name);
+ return;
+ }
+ }
+ directive->handler(object, valparams, objext_valparams, line);
+}
+
+yasm_valparam *
+yasm_vp_create_id(/*@keep@*/ char *v, /*@keep@*/ char *p, int id_prefix)
+{
+ yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
+ r->val = v;
+ r->type = YASM_PARAM_ID;
+ r->param.id = p;
+ r->id_prefix = (char)id_prefix;
+ return r;
+}
+
+yasm_valparam *
+yasm_vp_create_string(/*@keep@*/ char *v, /*@keep@*/ char *p)
+{
+ yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
+ r->val = v;
+ r->type = YASM_PARAM_STRING;
+ r->param.str = p;
+ r->id_prefix = '\0';
+ return r;
+}
+
+yasm_valparam *
+yasm_vp_create_expr(/*@keep@*/ char *v, /*@keep@*/ yasm_expr *p)
+{
+ yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
+ r->val = v;
+ r->type = YASM_PARAM_EXPR;
+ r->param.e = p;
+ r->id_prefix = '\0';
+ return r;
+}
+
+/*@null@*/ /*@only@*/ yasm_expr *
+yasm_vp_expr(const yasm_valparam *vp, yasm_symtab *symtab, unsigned long line)
+{
+ if (!vp)
+ return NULL;
+ switch (vp->type) {
+ case YASM_PARAM_ID:
+ return yasm_expr_create_ident(yasm_expr_sym(
+ yasm_symtab_use(symtab, yasm_vp_id(vp), line)), line);
+ case YASM_PARAM_EXPR:
+ return yasm_expr_copy(vp->param.e);
+ default:
+ return NULL;
+ }
+}
+
+/*@null@*/ /*@dependent@*/ const char *
+yasm_vp_string(const yasm_valparam *vp)
+{
+ if (!vp)
+ return NULL;
+ switch (vp->type) {
+ case YASM_PARAM_ID:
+ return vp->param.id;
+ case YASM_PARAM_STRING:
+ return vp->param.str;
+ default:
+ return NULL;
+ }
+}
+
+/*@null@*/ /*@dependent@*/ const char *
+yasm_vp_id(const yasm_valparam *vp)
+{
+ if (!vp)
+ return NULL;
+ if (vp->type == YASM_PARAM_ID) {
+ if (vp->param.id[0] == vp->id_prefix)
+ return &vp->param.id[1];
+ else
+ return vp->param.id;
+ }
+ return NULL;
+}
+
+void
+yasm_vps_delete(yasm_valparamhead *headp)
+{
+ yasm_valparam *cur, *next;
+
+ cur = STAILQ_FIRST(headp);
+ while (cur) {
+ next = STAILQ_NEXT(cur, link);
+ if (cur->val)
+ yasm_xfree(cur->val);
+ switch (cur->type) {
+ case YASM_PARAM_ID:
+ yasm_xfree(cur->param.id);
+ break;
+ case YASM_PARAM_STRING:
+ yasm_xfree(cur->param.str);
+ break;
+ case YASM_PARAM_EXPR:
+ yasm_expr_destroy(cur->param.e);
+ break;
+ }
+ yasm_xfree(cur);
+ cur = next;
+ }
+ STAILQ_INIT(headp);
+}
+
+void
+yasm_vps_print(const yasm_valparamhead *headp, FILE *f)
+{
+ const yasm_valparam *vp;
+
+ if(!headp) {
+ fprintf(f, "(none)");
+ return;
+ }
+
+ yasm_vps_foreach(vp, headp) {
+ if (vp->val)
+ fprintf(f, "(\"%s\",", vp->val);
+ else
+ fprintf(f, "((nil),");
+ switch (vp->type) {
+ case YASM_PARAM_ID:
+ fprintf(f, "%s", vp->param.id);
+ break;
+ case YASM_PARAM_STRING:
+ fprintf(f, "\"%s\"", vp->param.str);
+ break;
+ case YASM_PARAM_EXPR:
+ yasm_expr_print(vp->param.e, f);
+ break;
+ }
+ fprintf(f, ")");
+ if (yasm_vps_next(vp))
+ fprintf(f, ",");
+ }
+}
+
+yasm_valparamhead *
+yasm_vps_create(void)
+{
+ yasm_valparamhead *headp = yasm_xmalloc(sizeof(yasm_valparamhead));
+ yasm_vps_initialize(headp);
+ return headp;
+}
+
+void
+yasm_vps_destroy(yasm_valparamhead *headp)
+{
+ yasm_vps_delete(headp);
+ yasm_xfree(headp);
+}
+
+int
+yasm_dir_helper(void *obj, yasm_valparam *vp_first, unsigned long line,
+ const yasm_dir_help *help, size_t nhelp, void *data,
+ int (*helper_valparam) (void *obj, yasm_valparam *vp,
+ unsigned long line, void *data))
+{
+ yasm_valparam *vp = vp_first;
+ int anymatched = 0;
+ int matched;
+
+ if (!vp)
+ return 0;
+
+ do {
+ const char *s;
+ size_t i;
+
+ matched = 0;
+ if (!vp->val && (s = yasm_vp_id(vp))) {
+ for (i=0; i<nhelp; i++) {
+ if (help[i].needsparam == 0 &&
+ yasm__strcasecmp(s, help[i].name) == 0) {
+ if (help[i].helper(obj, vp, line,
+ ((char *)data)+help[i].off,
+ help[i].arg) != 0)
+ return -1;
+ matched = 1;
+ anymatched = 1;
+ break;
+ }
+ }
+ } else if (vp->val) {
+ for (i=0; i<nhelp; i++) {
+ if (help[i].needsparam == 1 &&
+ yasm__strcasecmp(vp->val, help[i].name) == 0) {
+ if (help[i].helper(obj, vp, line,
+ ((char *)data)+help[i].off,
+ help[i].arg) != 0)
+ return -1;
+ matched = 1;
+ anymatched = 1;
+ break;
+ }
+ }
+ }
+
+ if (!matched) {
+ int final = helper_valparam(obj, vp, line, data);
+ if (final < 0)
+ return -1;
+ if (final > 0)
+ anymatched = 1;
+ }
+ } while((vp = yasm_vps_next(vp)));
+
+ return anymatched;
+}
+
+int
+yasm_dir_helper_flag_or(void *obj, yasm_valparam *vp, unsigned long line,
+ void *d, uintptr_t flag)
+{
+ unsigned long *flags = (unsigned long *)d;
+ *flags |= flag;
+ return 0;
+}
+
+int
+yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line,
+ void *d, uintptr_t flag)
+{
+ unsigned long *flags = (unsigned long *)d;
+ *flags &= ~flag;
+ return 0;
+}
+
+int
+yasm_dir_helper_flag_set(void *obj, yasm_valparam *vp, unsigned long line,
+ void *d, uintptr_t flag)
+{
+ unsigned long *flags = (unsigned long *)d;
+ *flags = flag;
+ return 0;
+}
+
+int
+yasm_dir_helper_expr(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg)
+{
+ yasm_object *object = (yasm_object *)obj;
+ yasm_expr **expr = (yasm_expr **)data;
+
+ if (*expr)
+ yasm_expr_destroy(*expr);
+ if (!(*expr = yasm_vp_expr(vp, object->symtab, line))) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("argument to `%s' is not an expression"),
+ vp->val);
+ return -1;
+ }
+ return 0;
+}
+
+int
+yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg)
+{
+ yasm_object *object = (yasm_object *)obj;
+ /*@only@*/ /*@null@*/ yasm_expr *e;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *local;
+ yasm_intnum **intn = (yasm_intnum **)data;
+
+ if (*intn)
+ yasm_intnum_destroy(*intn);
+ if (!(e = yasm_vp_expr(vp, object->symtab, line)) ||
+ !(local = yasm_expr_get_intnum(&e, 0))) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("argument to `%s' is not an integer"),
+ vp->val);
+ if (e)
+ yasm_expr_destroy(e);
+ return -1;
+ }
+ *intn = yasm_intnum_copy(local);
+ yasm_expr_destroy(e);
+ return 0;
+}
+
+int
+yasm_dir_helper_string(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg)
+{
+ /*@dependent@*/ /*@null@*/ const char *local;
+ char **s = (char **)data;
+
+ if (*s)
+ yasm_xfree(*s);
+ if (!(local = yasm_vp_string(vp))) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("argument to `%s' is not a string or identifier"),
+ vp->val);
+ return -1;
+ }
+ *s = yasm__xstrdup(local);
+ return 0;
+}
+
+int
+yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp,
+ unsigned long line, void *data)
+{
+ const char *s;
+
+ if (vp->val) {
+ yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"),
+ vp->val);
+ return 0;
+ }
+
+ if ((s = yasm_vp_id(vp)))
+ yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"), s);
+ else if (vp->type == YASM_PARAM_STRING)
+ yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized string qualifier"));
+ else
+ yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized numeric qualifier"));
+
+ return 0;
+}
diff --git a/contrib/tools/yasm/libyasm/valparam.h b/contrib/tools/yasm/libyasm/valparam.h
new file mode 100644
index 0000000000..d7343d4955
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/valparam.h
@@ -0,0 +1,408 @@
+/**
+ * \file libyasm/valparam.h
+ * \brief YASM value/parameter interface.
+ *
+ * \license
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_VALPARAM_H
+#define YASM_VALPARAM_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Value/parameter pair. \internal */
+struct yasm_valparam {
+ /*@reldef@*/ STAILQ_ENTRY(yasm_valparam) link; /**< Next pair in list */
+ /*@owned@*/ /*@null@*/ char *val; /**< Value */
+
+ /** Parameter type. */
+ enum yasm_param_type {
+ YASM_PARAM_ID, /**< Identifier */
+ YASM_PARAM_STRING, /**< String */
+ YASM_PARAM_EXPR /**< Expression */
+ } type; /**< Parameter type */
+
+ /** Parameter value. */
+ union yasm_param {
+ /*@owned@*/ char *id; /**< Identifier */
+ /*@owned@*/ char *str; /**< String */
+ /*@owned@*/ yasm_expr *e; /**< Expression */
+ } param; /**< Parameter */
+
+ /** Prefix character that indicates a raw identifier. When
+ * yasm_vp_string() is called on a #YASM_PARAM_ID, all characters are
+ * returned. When yasm_vp_id() is called on a #YASM_PARAM_ID, if the
+ * identifier begins with this character, this character is stripped
+ * from the returned value.
+ */
+ char id_prefix;
+};
+
+/** Linked list of value/parameter pairs. \internal */
+/*@reldef@*/ STAILQ_HEAD(yasm_valparamhead, yasm_valparam);
+
+/** Directive list entry structure. */
+struct yasm_directive {
+ /** Directive name. GAS directives should include the ".", NASM
+ * directives should just be the raw name (not including the []).
+ * NULL entry required to terminate list of directives.
+ */
+ /*@null@*/ const char *name;
+
+ const char *parser; /**< Parser keyword */
+
+ /** Handler callback function for the directive.
+ * \param object object
+ * \param valparams value/parameters
+ * \param objext_valparams object format-specific value/parameters
+ * \param line virtual line (from yasm_linemap)
+ */
+ void (*handler) (yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line);
+
+ /** Flags for pre-handler parameter checking. */
+ enum yasm_directive_flags {
+ YASM_DIR_ANY = 0, /**< Any valparams accepted */
+ YASM_DIR_ARG_REQUIRED = 1, /**< Require at least 1 valparam */
+ YASM_DIR_ID_REQUIRED = 2 /**< First valparam must be ID */
+ } flags;
+};
+
+/** Call a directive. Performs any valparam checks asked for by the
+ * directive prior to call. Note that for a variety of reasons, a directive
+ * can generate an error.
+ * \param directive directive
+ * \param object object
+ * \param valparams value/parameters
+ * \param objext_valparams object format-specific value/parameters
+ * \param line virtual line (from yasm_linemap)
+ */
+YASM_LIB_DECL
+void yasm_call_directive(const yasm_directive *directive, yasm_object *object,
+ yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams,
+ unsigned long line);
+
+/** Create a new valparam with identifier parameter.
+ * \param v value
+ * \param p parameter
+ * \param id_prefix identifier prefix for raw identifiers
+ * \return Newly allocated valparam.
+ */
+YASM_LIB_DECL
+yasm_valparam *yasm_vp_create_id(/*@keep@*/ char *v, /*@keep@*/ char *p,
+ int id_prefix);
+
+/** Create a new valparam with string parameter.
+ * \param v value
+ * \param p parameter
+ * \return Newly allocated valparam.
+ */
+YASM_LIB_DECL
+yasm_valparam *yasm_vp_create_string(/*@keep@*/ char *v, /*@keep@*/ char *p);
+
+/** Create a new valparam with expression parameter.
+ * \param v value
+ * \param p parameter
+ * \return Newly allocated valparam.
+ */
+YASM_LIB_DECL
+yasm_valparam *yasm_vp_create_expr(/*@keep@*/ char *v,
+ /*@keep@*/ yasm_expr *p);
+
+/** Get a valparam parameter as an expr. If the parameter is an identifier,
+ * it's treated as a symbol (yasm_symtab_use() is called to convert it).
+ * \param vp valparam
+ * \param symtab symbol table
+ * \param line virtual line
+ * \return Expression, or NULL if vp is NULL or the parameter cannot be
+ * converted to an expression.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@only@*/ yasm_expr *yasm_vp_expr
+ (const yasm_valparam *vp, yasm_symtab *symtab, unsigned long line);
+
+/** Get a valparam parameter as a string. If the parameter is an identifier,
+ * it's treated as a string.
+ * \param vp valparam
+ * \return String, or NULL if vp is NULL or the parameter cannot be realized
+ * as a string.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@dependent@*/ const char *yasm_vp_string(const yasm_valparam *vp);
+
+/** Get a valparam parameter as an identifier.
+ * \param vp valparam
+ * \return Identifier (string), or NULL if vp is NULL or the parameter is not
+ * an identifier.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@dependent@*/ const char *yasm_vp_id(const yasm_valparam *vp);
+
+/** Create a new linked list of valparams.
+ * \return Newly allocated valparam list.
+ */
+YASM_LIB_DECL
+yasm_valparamhead *yasm_vps_create(void);
+
+/** Destroy a list of valparams (created with yasm_vps_create).
+ * \param headp list of valparams
+ */
+YASM_LIB_DECL
+void yasm_vps_destroy(yasm_valparamhead *headp);
+
+/** Initialize linked list of valparams.
+ * \param headp linked list
+ */
+void yasm_vps_initialize(/*@out@*/ yasm_valparamhead *headp);
+#ifndef YASM_DOXYGEN
+#define yasm_vps_initialize(headp) STAILQ_INIT(headp)
+#endif
+
+/** Destroy (free allocated memory for) linked list of valparams (created with
+ * yasm_vps_initialize).
+ * \warning Deletes val/params.
+ * \param headp linked list
+ */
+YASM_LIB_DECL
+void yasm_vps_delete(yasm_valparamhead *headp);
+
+/** Append valparam to tail of linked list.
+ * \param headp linked list
+ * \param vp valparam
+ */
+void yasm_vps_append(yasm_valparamhead *headp, /*@keep@*/ yasm_valparam *vp);
+#ifndef YASM_DOXYGEN
+#define yasm_vps_append(headp, vp) do { \
+ if (vp) \
+ STAILQ_INSERT_TAIL(headp, vp, link); \
+ } while(0)
+#endif
+
+/** Get first valparam in linked list.
+ * \param headp linked list
+ * \return First valparam in linked list.
+ */
+/*@null@*/ /*@dependent@*/ yasm_valparam *yasm_vps_first
+ (yasm_valparamhead *headp);
+#ifndef YASM_DOXYGEN
+#define yasm_vps_first(headp) STAILQ_FIRST(headp)
+#endif
+
+/** Get next valparam in linked list.
+ * \param cur previous valparam in linked list
+ * \return Next valparam in linked list.
+ */
+/*@null@*/ /*@dependent@*/ yasm_valparam *yasm_vps_next(yasm_valparam *cur);
+#ifndef YASM_DOXYGEN
+#define yasm_vps_next(cur) STAILQ_NEXT(cur, link)
+#endif
+
+/** Iterate through linked list of valparams.
+ * \internal
+ * \param iter iterator variable
+ * \param headp linked list
+ */
+#ifndef YASM_DOXYGEN
+#define yasm_vps_foreach(iter, headp) STAILQ_FOREACH(iter, headp, link)
+#endif
+
+/** Print linked list of valparams. For debugging purposes.
+ * \param f file
+ * \param headp linked list
+ */
+YASM_LIB_DECL
+void yasm_vps_print(/*@null@*/ const yasm_valparamhead *headp, FILE *f);
+
+/** Directive valparam parse helper structure. */
+typedef struct yasm_dir_help {
+ /** Value portion of val=param (if needsparam=1), or standalone identifier
+ * (if needsparam=0).
+ */
+ const char *name;
+
+ /** 1 if value requires parameter, 0 if it must not have a parameter. */
+ int needsparam;
+
+ /** Helper callback function if name and parameter existence match.
+ * \param obj obj passed into yasm_dir_helper()
+ * \param vp value/parameter
+ * \param line line passed into yasm_dir_helper()
+ * \param data data passed into yasm_dir_helper() plus
+ #yasm_dir_help.off offset
+ * \param arg #yasm_dir_help.arg argument
+ * \return -1 on error, 0 otherwise.
+ */
+ int (*helper) (void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg);
+
+ /** Offset added to data pointer passed into yasm_dir_helper() before
+ * data pointer is given to #yasm_dir_help.helper(). This is so that
+ * a structure can be passed into yasm_dir_helper() and this can be an
+ * offsetof() to point the helper function to a specific structure
+ * member.
+ */
+ size_t off;
+
+ /** Argument to pass in as the arg parameter to #yasm_dir_help.helper().
+ */
+ uintptr_t arg;
+} yasm_dir_help;
+
+/** Help parse a list of directive value/parameters. Takes an array of
+ * #yasm_dir_help structures and tries to match val=param (or just val)
+ * against the passed value/parameters. When no match is found in the
+ * array of help structures, calls helper_valparam.
+ * \param obj object to be passed to yasm_dir_help.helper() or
+ * helper_valparam() callback
+ * \param vp_first first value/parameter to examine
+ * \param line virtual line number; passed down to helper callback
+ * \param help array of #yasm_dir_help structures
+ * \param nhelp number of array elements
+ * \param data base data pointer; if a match is found,
+ * the respective #yasm_dir_help.off is added to this
+ * prior to it being passed to the helper callback
+ * \param helper_valparam catch-all callback; should return -1 on error,
+ * 0 if not matched, 1 if matched.
+ * \return -1 on error, 1 if any arguments matched (including via
+ * catch-all callback), 0 if no match.
+ */
+YASM_LIB_DECL
+int yasm_dir_helper(void *obj, yasm_valparam *vp_first, unsigned long line,
+ const yasm_dir_help *help, size_t nhelp, void *data,
+ int (*helper_valparam) (void *object,
+ yasm_valparam *vp,
+ unsigned long line,
+ void *data));
+
+/** Standard helper for yasm_dir_helper() that simply sets a flag when called.
+ * It does not look at the vp; rather, it uses the value of the arg parameter,
+ * and stores an unsigned long value to data.
+ * \param obj unused
+ * \param vp unused
+ * \param line unused
+ * \param data pointer to an unsigned long
+ * \param arg flag to set
+ * \return 0
+ */
+YASM_LIB_DECL
+int yasm_dir_helper_flag_set(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg);
+
+/** Standard helper for yasm_dir_helper() that simply ORs a flag when called.
+ * It does not look at the vp; rather, it uses the value of the arg parameter,
+ * and ORs it with the unsigned long value in data.
+ * \param obj unused
+ * \param vp unused
+ * \param line unused
+ * \param data pointer to an unsigned long
+ * \param arg flag to OR
+ * \return 0
+ */
+YASM_LIB_DECL
+int yasm_dir_helper_flag_or(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg);
+
+/** Standard helper for yasm_dir_helper() that simply ANDs a flag when called.
+ * It does not look at the vp; rather, it uses the value of the arg parameter,
+ * and ANDs its inverse (~) with the unsigned long value in data.
+ * \param obj unused
+ * \param vp unused
+ * \param line unused
+ * \param data pointer to an unsigned long
+ * \param arg flag to AND
+ * \return 0
+ */
+YASM_LIB_DECL
+int yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg);
+
+/** Standard helper for yasm_dir_helper() that parses an expr parameter.
+ * The #yasm_dir_help structure that uses this function should have
+ * needsparam=1. The obj parameter to yasm_dir_helper() when this helper
+ * is used MUST point to a #yasm_object. In addition, the data parameter
+ * that is ultimately passed to this function (e.g. yasm_dir_helper() data
+ * parameter plus #yasm_dir_help.off) must point to a #yasm_expr *
+ * initialized to NULL.
+ * \param obj object; must be #yasm_object
+ * \param vp valparam
+ * \param line virtual line number
+ * \param data pointer to #yasm_expr *
+ * \param arg unused argument
+ * \return -1 on error, 0 otherwise.
+ */
+YASM_LIB_DECL
+int yasm_dir_helper_expr(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg);
+
+/** Standard helper for yasm_dir_helper() that parses an intnum parameter.
+ * The #yasm_dir_help structure that uses this function should have
+ * needsparam=1. The obj parameter to yasm_dir_helper() when this helper
+ * is used MUST point to a #yasm_object. In addition, the data parameter
+ * that is ultimately passed to this function (e.g. yasm_dir_helper() data
+ * parameter plus #yasm_dir_help.off) must point to a #yasm_intnum *
+ * initialized to NULL.
+ * \param obj object; must be #yasm_object
+ * \param vp valparam
+ * \param line virtual line number
+ * \param data pointer to #yasm_intnum *
+ * \param arg unused argument
+ * \return -1 on error, 0 otherwise.
+ */
+YASM_LIB_DECL
+int yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg);
+
+/** Standard helper for yasm_dir_helper() that parses an string (or
+ * standalone identifier) parameter.
+ * The #yasm_dir_help structure that uses this function should have
+ * needsparam=1. The data parameter that is ultimately passed to this
+ * function (e.g. yasm_dir_helper() data parameter plus #yasm_dir_help.off)
+ * must point to a char * initialized to NULL.
+ * \param obj unused
+ * \param vp valparam
+ * \param line unused
+ * \param data pointer to char *
+ * \param arg unused
+ * \return -1 on error, 0 otherwise.
+ */
+YASM_LIB_DECL
+int yasm_dir_helper_string(void *obj, yasm_valparam *vp, unsigned long line,
+ void *data, uintptr_t arg);
+
+/** Standard catch-all callback fro yasm_dir_helper(). Generates standard
+ * warning for all valparams.
+ * \param obj unused
+ * \param vp valparam
+ * \param line unused
+ * \param data unused
+ * \return 0
+ */
+YASM_LIB_DECL
+int yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp,
+ unsigned long line, void *data);
+#endif
diff --git a/contrib/tools/yasm/libyasm/value.c b/contrib/tools/yasm/libyasm/value.c
new file mode 100644
index 0000000000..3ab73c1cec
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/value.c
@@ -0,0 +1,771 @@
+/*
+ * Value handling
+ *
+ * Copyright (C) 2006-2007 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 "util.h"
+
+#include "libyasm-stdint.h"
+#include "coretype.h"
+#include "bitvect.h"
+
+#include "errwarn.h"
+#include "intnum.h"
+#include "floatnum.h"
+#include "expr.h"
+#include "value.h"
+#include "symrec.h"
+
+#include "bytecode.h"
+#include "section.h"
+
+#include "arch.h"
+
+
+void
+yasm_value_initialize(/*@out@*/ yasm_value *value,
+ /*@null@*/ /*@kept@*/ yasm_expr *e, unsigned int size)
+{
+ value->abs = e;
+ value->rel = NULL;
+ value->wrt = NULL;
+ value->seg_of = 0;
+ value->rshift = 0;
+ value->curpos_rel = 0;
+ value->ip_rel = 0;
+ value->jump_target = 0;
+ value->section_rel = 0;
+ value->no_warn = 0;
+ value->sign = 0;
+ value->size = size;
+}
+
+void
+yasm_value_init_sym(/*@out@*/ yasm_value *value, /*@null@*/ yasm_symrec *sym,
+ unsigned int size)
+{
+ value->abs = NULL;
+ value->rel = sym;
+ value->wrt = NULL;
+ value->seg_of = 0;
+ value->rshift = 0;
+ value->curpos_rel = 0;
+ value->ip_rel = 0;
+ value->jump_target = 0;
+ value->section_rel = 0;
+ value->no_warn = 0;
+ value->sign = 0;
+ value->size = size;
+}
+
+void
+yasm_value_init_copy(yasm_value *value, const yasm_value *orig)
+{
+ value->abs = orig->abs ? yasm_expr_copy(orig->abs) : NULL;
+ value->rel = orig->rel;
+ value->wrt = orig->wrt;
+ value->seg_of = orig->seg_of;
+ value->rshift = orig->rshift;
+ value->curpos_rel = orig->curpos_rel;
+ value->ip_rel = orig->ip_rel;
+ value->jump_target = orig->jump_target;
+ value->section_rel = orig->section_rel;
+ value->no_warn = orig->no_warn;
+ value->sign = orig->sign;
+ value->size = orig->size;
+}
+
+void
+yasm_value_delete(yasm_value *value)
+{
+ if (value->abs)
+ yasm_expr_destroy(value->abs);
+ value->abs = NULL;
+ value->rel = NULL;
+}
+
+void
+yasm_value_set_curpos_rel(yasm_value *value, yasm_bytecode *bc,
+ unsigned int ip_rel)
+{
+ value->curpos_rel = 1;
+ value->ip_rel = ip_rel;
+ /* In order for us to correctly output curpos-relative values, we must
+ * have a relative portion of the value. If one doesn't exist, point
+ * to a custom absolute symbol.
+ */
+ if (!value->rel) {
+ yasm_object *object = yasm_section_get_object(yasm_bc_get_section(bc));
+ value->rel = yasm_symtab_abs_sym(object->symtab);
+ }
+}
+
+static int
+value_finalize_scan(yasm_value *value, yasm_expr *e,
+ /*@null@*/ yasm_bytecode *expr_precbc, int ssym_not_ok)
+{
+ int i;
+ /*@dependent@*/ yasm_section *sect;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
+
+ unsigned long shamt; /* for SHR */
+
+ /* Yes, this has a maximum upper bound on 32 terms, based on an
+ * "insane number of terms" (and ease of implementation) WAG.
+ * The right way to do this would be a stack-based alloca, but that's
+ * not ISO C. We really don't want to malloc here as this function is
+ * hit a lot!
+ *
+ * This is a bitmask to keep things small, as this is a recursive
+ * routine and we don't want to eat up stack space.
+ */
+ unsigned long used; /* for ADD */
+
+ /* Thanks to this running after a simplify, we don't need to iterate
+ * down through IDENTs or handle SUB.
+ *
+ * We scan for a single symrec, gathering info along the way. After
+ * we've found the symrec, we keep scanning but error if we find
+ * another one. We pull out the single symrec and any legal operations
+ * performed on it.
+ *
+ * Also, if we find a float anywhere, we don't allow mixing of a single
+ * symrec with it.
+ */
+ switch (e->op) {
+ case YASM_EXPR_ADD:
+ /* Okay for single symrec anywhere in expr.
+ * Check for single symrec anywhere.
+ * Handle symrec-symrec by checking for (-1*symrec)
+ * and symrec term pairs (where both symrecs are in the same
+ * segment).
+ */
+ if (e->numterms > 32)
+ yasm__fatal(N_("expression on line %d has too many add terms;"
+ " internal limit of 32"), e->line);
+
+ used = 0;
+
+ for (i=0; i<e->numterms; i++) {
+ int j;
+ yasm_expr *sube;
+ yasm_intnum *intn;
+ yasm_symrec *sym;
+ /*@dependent@*/ yasm_section *sect2;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc2;
+
+ /* First look for an (-1*symrec) term */
+ if (e->terms[i].type != YASM_EXPR_EXPR)
+ continue;
+ sube = e->terms[i].data.expn;
+
+ if (sube->op != YASM_EXPR_MUL || sube->numterms != 2) {
+ /* recurse instead */
+ if (value_finalize_scan(value, sube, expr_precbc,
+ ssym_not_ok))
+ return 1;
+ continue;
+ }
+
+ if (sube->terms[0].type == YASM_EXPR_INT &&
+ sube->terms[1].type == YASM_EXPR_SYM) {
+ intn = sube->terms[0].data.intn;
+ sym = sube->terms[1].data.sym;
+ } else if (sube->terms[0].type == YASM_EXPR_SYM &&
+ sube->terms[1].type == YASM_EXPR_INT) {
+ sym = sube->terms[0].data.sym;
+ intn = sube->terms[1].data.intn;
+ } else {
+ if (value_finalize_scan(value, sube, expr_precbc,
+ ssym_not_ok))
+ return 1;
+ continue;
+ }
+
+ if (!yasm_intnum_is_neg1(intn)) {
+ if (value_finalize_scan(value, sube, expr_precbc,
+ ssym_not_ok))
+ return 1;
+ continue;
+ }
+
+ /* Look for the same symrec term; even if both are external,
+ * they should cancel out.
+ */
+ for (j=0; j<e->numterms; j++) {
+ if (e->terms[j].type == YASM_EXPR_SYM
+ && e->terms[j].data.sym == sym
+ && (used & (1<<j)) == 0) {
+ /* Mark as used */
+ used |= 1<<j;
+
+ /* Replace both symrec portions with 0 */
+ yasm_expr_destroy(sube);
+ e->terms[i].type = YASM_EXPR_INT;
+ e->terms[i].data.intn = yasm_intnum_create_uint(0);
+ e->terms[j].type = YASM_EXPR_INT;
+ e->terms[j].data.intn = yasm_intnum_create_uint(0);
+
+ break; /* stop looking */
+ }
+ }
+ if (j != e->numterms)
+ continue;
+
+ if (!yasm_symrec_get_label(sym, &precbc)) {
+ if (value_finalize_scan(value, sube, expr_precbc,
+ ssym_not_ok))
+ return 1;
+ continue;
+ }
+ sect2 = yasm_bc_get_section(precbc);
+
+ /* Now look for a unused symrec term in the same segment */
+ for (j=0; j<e->numterms; j++) {
+ if (e->terms[j].type == YASM_EXPR_SYM
+ && yasm_symrec_get_label(e->terms[j].data.sym,
+ &precbc2)
+ && (sect = yasm_bc_get_section(precbc2))
+ && sect == sect2
+ && (used & (1<<j)) == 0) {
+ /* Mark as used */
+ used |= 1<<j;
+ break; /* stop looking */
+ }
+ }
+
+ /* We didn't match in the same segment. If the
+ * -1*symrec is actually -1*curpos, we can match
+ * unused symrec terms in other segments and generate
+ * a curpos-relative reloc.
+ *
+ * Similarly, handle -1*symrec in other segment via the
+ * following transformation:
+ * other-this = (other-.)+(.-this)
+ * We can only do this transformation if "this" is in
+ * this expr's segment.
+ *
+ * Don't do this if we've already become curpos-relative.
+ * The unmatched symrec will be caught below.
+ */
+ if (j == e->numterms && !value->curpos_rel
+ && (yasm_symrec_is_curpos(sym)
+ || (expr_precbc
+ && sect2 == yasm_bc_get_section(expr_precbc)))) {
+ for (j=0; j<e->numterms; j++) {
+ if (e->terms[j].type == YASM_EXPR_SYM
+ && !yasm_symrec_get_equ(e->terms[j].data.sym)
+ && !yasm_symrec_is_special(e->terms[j].data.sym)
+ && (used & (1<<j)) == 0) {
+ /* Mark as used */
+ used |= 1<<j;
+ /* Mark value as curpos-relative */
+ if (value->rel || ssym_not_ok)
+ return 1;
+ value->rel = e->terms[j].data.sym;
+ value->curpos_rel = 1;
+ if (yasm_symrec_is_curpos(sym)) {
+ /* Replace both symrec portions with 0 */
+ yasm_expr_destroy(sube);
+ e->terms[i].type = YASM_EXPR_INT;
+ e->terms[i].data.intn =
+ yasm_intnum_create_uint(0);
+ e->terms[j].type = YASM_EXPR_INT;
+ e->terms[j].data.intn =
+ yasm_intnum_create_uint(0);
+ } else {
+ /* Replace positive portion with curpos */
+ yasm_object *object =
+ yasm_section_get_object(sect2);
+ yasm_symtab *symtab = object->symtab;
+ e->terms[j].data.sym =
+ yasm_symtab_define_curpos
+ (symtab, ".", expr_precbc, e->line);
+ }
+ break; /* stop looking */
+ }
+ }
+ }
+
+
+ if (j == e->numterms)
+ return 1; /* We didn't find a match! */
+ }
+
+ /* Look for unmatched symrecs. If we've already found one or
+ * we don't WANT to find one, error out.
+ */
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_SYM
+ && (used & (1<<i)) == 0) {
+ if (value->rel || ssym_not_ok)
+ return 1;
+ value->rel = e->terms[i].data.sym;
+ /* and replace with 0 */
+ e->terms[i].type = YASM_EXPR_INT;
+ e->terms[i].data.intn = yasm_intnum_create_uint(0);
+ }
+ }
+ break;
+ case YASM_EXPR_SHR:
+ /* Okay for single symrec in LHS and constant on RHS.
+ * Single symrecs are not okay on RHS.
+ * If RHS is non-constant, don't allow single symrec on LHS.
+ * XXX: should rshift be an expr instead??
+ */
+
+ /* Check for single sym on LHS */
+ if (e->terms[0].type != YASM_EXPR_SYM)
+ break;
+
+ /* If we already have a sym, we can't take another one */
+ if (value->rel || ssym_not_ok)
+ return 1;
+
+ /* RHS must be a positive integer */
+ if (e->terms[1].type != YASM_EXPR_INT)
+ return 1; /* can't shift sym by non-constant integer */
+ shamt = yasm_intnum_get_uint(e->terms[1].data.intn);
+ if ((shamt + value->rshift) > YASM_VALUE_RSHIFT_MAX)
+ return 1; /* total shift would be too large */
+
+ /* Update value */
+ value->rshift += shamt;
+ value->rel = e->terms[0].data.sym;
+
+ /* Replace symbol with 0 */
+ e->terms[0].type = YASM_EXPR_INT;
+ e->terms[0].data.intn = yasm_intnum_create_uint(0);
+
+ /* Just leave SHR in place */
+ break;
+ case YASM_EXPR_SEG:
+ /* Okay for single symrec (can only be done once).
+ * Not okay for anything BUT a single symrec as an immediate
+ * child.
+ */
+ if (e->terms[0].type != YASM_EXPR_SYM)
+ return 1;
+
+ if (value->seg_of)
+ return 1; /* multiple SEG not legal */
+ value->seg_of = 1;
+
+ if (value->rel || ssym_not_ok)
+ return 1; /* got a relative portion somewhere else? */
+ value->rel = e->terms[0].data.sym;
+
+ /* replace with ident'ed 0 */
+ e->op = YASM_EXPR_IDENT;
+ e->terms[0].type = YASM_EXPR_INT;
+ e->terms[0].data.intn = yasm_intnum_create_uint(0);
+ break;
+ case YASM_EXPR_WRT:
+ /* Okay for single symrec in LHS and either a register or single
+ * symrec (as an immediate child) on RHS.
+ * If a single symrec on RHS, can only be done once.
+ * WRT reg is left in expr for arch to look at.
+ */
+
+ /* Handle RHS */
+ switch (e->terms[1].type) {
+ case YASM_EXPR_SYM:
+ if (value->wrt)
+ return 1;
+ value->wrt = e->terms[1].data.sym;
+ /* and drop the WRT portion */
+ e->op = YASM_EXPR_IDENT;
+ e->numterms = 1;
+ break;
+ case YASM_EXPR_REG:
+ break; /* ignore */
+ default:
+ return 1;
+ }
+
+ /* Handle LHS */
+ switch (e->terms[0].type) {
+ case YASM_EXPR_SYM:
+ if (value->rel || ssym_not_ok)
+ return 1;
+ value->rel = e->terms[0].data.sym;
+ /* and replace with 0 */
+ e->terms[0].type = YASM_EXPR_INT;
+ e->terms[0].data.intn = yasm_intnum_create_uint(0);
+ break;
+ case YASM_EXPR_EXPR:
+ /* recurse */
+ return value_finalize_scan(value, e->terms[0].data.expn,
+ expr_precbc, ssym_not_ok);
+ default:
+ break; /* ignore */
+ }
+
+ break;
+ default:
+ /* Single symrec not allowed anywhere */
+ for (i=0; i<e->numterms; i++) {
+ switch (e->terms[i].type) {
+ case YASM_EXPR_SYM:
+ return 1;
+ case YASM_EXPR_EXPR:
+ /* recurse */
+ return value_finalize_scan(value,
+ e->terms[i].data.expn,
+ expr_precbc, 1);
+ default:
+ break;
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+int
+yasm_value_finalize_expr(yasm_value *value, yasm_expr *e,
+ yasm_bytecode *precbc, unsigned int size)
+{
+ if (!e) {
+ yasm_value_initialize(value, NULL, size);
+ return 0;
+ }
+ yasm_value_initialize(value, e, size);
+ return yasm_value_finalize(value, precbc);
+}
+
+int
+yasm_value_finalize(yasm_value *value, yasm_bytecode *precbc)
+{
+ if (!value->abs)
+ return 0;
+
+ value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL);
+
+ /* quit early if there was an issue in simplify() */
+ if (yasm_error_occurred())
+ return 1;
+
+ /* Strip top-level AND masking to an all-1s mask the same size
+ * of the value size. This allows forced avoidance of overflow warnings.
+ */
+ if (value->abs->op == YASM_EXPR_AND) {
+ int term;
+
+ /* Calculate 1<<size - 1 value */
+ yasm_intnum *mask = yasm_intnum_create_uint(1);
+ yasm_intnum *mask_tmp = yasm_intnum_create_uint(value->size);
+ yasm_intnum_calc(mask, YASM_EXPR_SHL, mask_tmp);
+ yasm_intnum_set_uint(mask_tmp, 1);
+ yasm_intnum_calc(mask, YASM_EXPR_SUB, mask_tmp);
+ yasm_intnum_destroy(mask_tmp);
+
+ /* Walk terms and delete matching masks */
+ for (term=value->abs->numterms-1; term>=0; term--) {
+ if (value->abs->terms[term].type == YASM_EXPR_INT &&
+ yasm_intnum_compare(value->abs->terms[term].data.intn,
+ mask) == 0) {
+ /* Delete the intnum */
+ yasm_intnum_destroy(value->abs->terms[term].data.intn);
+
+ /* Slide everything to its right over by 1 */
+ if (term != value->abs->numterms-1) /* if it wasn't last.. */
+ memmove(&value->abs->terms[term],
+ &value->abs->terms[term+1],
+ (value->abs->numterms-1-term)*
+ sizeof(yasm_expr__item));
+
+ /* Update numterms */
+ value->abs->numterms--;
+
+ /* Indicate warnings have been disabled */
+ value->no_warn = 1;
+ }
+ }
+ if (value->abs->numterms == 1)
+ value->abs->op = YASM_EXPR_IDENT;
+ yasm_intnum_destroy(mask);
+ }
+
+ /* Handle trivial (IDENT) cases immediately */
+ if (value->abs->op == YASM_EXPR_IDENT) {
+ switch (value->abs->terms[0].type) {
+ case YASM_EXPR_INT:
+ if (yasm_intnum_is_zero(value->abs->terms[0].data.intn)) {
+ yasm_expr_destroy(value->abs);
+ value->abs = NULL;
+ }
+ return 0;
+ case YASM_EXPR_REG:
+ case YASM_EXPR_FLOAT:
+ return 0;
+ case YASM_EXPR_SYM:
+ value->rel = value->abs->terms[0].data.sym;
+ yasm_expr_destroy(value->abs);
+ value->abs = NULL;
+ return 0;
+ case YASM_EXPR_EXPR:
+ /* Bring up lower values. */
+ while (value->abs->op == YASM_EXPR_IDENT
+ && value->abs->terms[0].type == YASM_EXPR_EXPR) {
+ yasm_expr *sube = value->abs->terms[0].data.expn;
+ yasm_xfree(value->abs);
+ value->abs = sube;
+ }
+ break;
+ default:
+ yasm_internal_error(N_("unexpected expr term type"));
+ }
+ }
+
+ if (value_finalize_scan(value, value->abs, precbc, 0))
+ return 1;
+
+ value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL);
+
+ /* Simplify 0 in abs to NULL */
+ if (value->abs->op == YASM_EXPR_IDENT
+ && value->abs->terms[0].type == YASM_EXPR_INT
+ && yasm_intnum_is_zero(value->abs->terms[0].data.intn)) {
+ yasm_expr_destroy(value->abs);
+ value->abs = NULL;
+ }
+ return 0;
+}
+
+yasm_intnum *
+yasm_value_get_intnum(yasm_value *value, yasm_bytecode *bc, int calc_bc_dist)
+{
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL;
+ /*@only@*/ yasm_intnum *outval;
+ int sym_local;
+
+ if (value->abs) {
+ /* Handle integer expressions, if non-integer or too complex, return
+ * NULL.
+ */
+ intn = yasm_expr_get_intnum(&value->abs, calc_bc_dist);
+ if (!intn)
+ return NULL;
+ }
+
+ if (value->rel) {
+ /* If relative portion is not in bc section, return NULL.
+ * Otherwise get the relative portion's offset.
+ */
+ /*@dependent@*/ yasm_bytecode *rel_prevbc;
+ unsigned long dist;
+
+ if (!bc)
+ return NULL; /* Can't calculate relative value */
+
+ sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc);
+ if (value->wrt || value->seg_of || value->section_rel || !sym_local)
+ return NULL; /* we can't handle SEG, WRT, or external symbols */
+ if (rel_prevbc->section != bc->section)
+ return NULL; /* not in this section */
+ if (!value->curpos_rel)
+ return NULL; /* not PC-relative */
+
+ /* Calculate value relative to current assembly position */
+ dist = yasm_bc_next_offset(rel_prevbc);
+ if (dist < bc->offset) {
+ outval = yasm_intnum_create_uint(bc->offset - dist);
+ yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL);
+ } else {
+ dist -= bc->offset;
+ outval = yasm_intnum_create_uint(dist);
+ }
+
+ if (value->rshift > 0) {
+ /*@only@*/ yasm_intnum *shamt =
+ yasm_intnum_create_uint((unsigned long)value->rshift);
+ yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt);
+ yasm_intnum_destroy(shamt);
+ }
+ /* Add in absolute portion */
+ if (intn)
+ yasm_intnum_calc(outval, YASM_EXPR_ADD, intn);
+ return outval;
+ }
+
+ if (intn)
+ return yasm_intnum_copy(intn);
+
+ /* No absolute or relative portions: output 0 */
+ return yasm_intnum_create_uint(0);
+}
+
+int
+yasm_value_output_basic(yasm_value *value, /*@out@*/ unsigned char *buf,
+ size_t destsize, yasm_bytecode *bc, int warn,
+ yasm_arch *arch)
+{
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL;
+ /*@only@*/ yasm_intnum *outval;
+ int sym_local;
+ int retval = 1;
+ unsigned int valsize = value->size;
+
+ if (value->no_warn)
+ warn = 0;
+
+ if (value->abs) {
+ /* Handle floating point expressions */
+ if (!value->rel && value->abs->op == YASM_EXPR_IDENT
+ && value->abs->terms[0].type == YASM_EXPR_FLOAT) {
+ if (yasm_arch_floatnum_tobytes(arch, value->abs->terms[0].data.flt,
+ buf, destsize, valsize, 0, warn))
+ return -1;
+ else
+ return 1;
+ }
+
+ /* Check for complex float expressions */
+ if (yasm_expr__contains(value->abs, YASM_EXPR_FLOAT)) {
+ yasm_error_set(YASM_ERROR_FLOATING_POINT,
+ N_("floating point expression too complex"));
+ return -1;
+ }
+
+ /* Handle normal integer expressions */
+ intn = yasm_expr_get_intnum(&value->abs, 1);
+
+ if (!intn) {
+ /* Second try before erroring: yasm_expr_get_intnum doesn't handle
+ * SEG:OFF, so try simplifying out any to just the OFF portion,
+ * then getting the intnum again.
+ */
+ yasm_expr *seg = yasm_expr_extract_deep_segoff(&value->abs);
+ if (seg)
+ yasm_expr_destroy(seg);
+ intn = yasm_expr_get_intnum(&value->abs, 1);
+ }
+
+ if (!intn) {
+ /* Still don't have an integer! */
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("expression too complex"));
+ return -1;
+ }
+ }
+
+ /* Adjust warn for signed/unsigned integer warnings */
+ if (warn != 0)
+ warn = value->sign ? -1 : 1;
+
+ if (value->rel) {
+ /* If relative portion is not in bc section, don't try to handle it
+ * here. Otherwise get the relative portion's offset.
+ */
+ /*@dependent@*/ yasm_bytecode *rel_prevbc;
+ unsigned long dist;
+
+ sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc);
+ if (value->wrt || value->seg_of || value->section_rel || !sym_local)
+ return 0; /* we can't handle SEG, WRT, or external symbols */
+ if (rel_prevbc->section != bc->section)
+ return 0; /* not in this section */
+ if (!value->curpos_rel)
+ return 0; /* not PC-relative */
+
+ /* Calculate value relative to current assembly position */
+ dist = yasm_bc_next_offset(rel_prevbc);
+ if (dist < bc->offset) {
+ outval = yasm_intnum_create_uint(bc->offset - dist);
+ yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL);
+ } else {
+ dist -= bc->offset;
+ outval = yasm_intnum_create_uint(dist);
+ }
+
+ if (value->rshift > 0) {
+ /*@only@*/ yasm_intnum *shamt =
+ yasm_intnum_create_uint((unsigned long)value->rshift);
+ yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt);
+ yasm_intnum_destroy(shamt);
+ }
+ /* Add in absolute portion */
+ if (intn)
+ yasm_intnum_calc(outval, YASM_EXPR_ADD, intn);
+ /* Output! */
+ if (yasm_arch_intnum_tobytes(arch, outval, buf, destsize, valsize, 0,
+ bc, warn))
+ retval = -1;
+ yasm_intnum_destroy(outval);
+ return retval;
+ }
+
+ if (value->seg_of || value->rshift || value->curpos_rel || value->ip_rel
+ || value->section_rel)
+ return 0; /* We can't handle this with just an absolute */
+
+ if (intn) {
+ /* Output just absolute portion */
+ if (yasm_arch_intnum_tobytes(arch, intn, buf, destsize, valsize, 0, bc,
+ warn))
+ retval = -1;
+ } else {
+ /* No absolute or relative portions: output 0 */
+ outval = yasm_intnum_create_uint(0);
+ if (yasm_arch_intnum_tobytes(arch, outval, buf, destsize, valsize, 0,
+ bc, warn))
+ retval = -1;
+ yasm_intnum_destroy(outval);
+ }
+ return retval;
+}
+
+void
+yasm_value_print(const yasm_value *value, FILE *f, int indent_level)
+{
+ fprintf(f, "%*s%u-bit, %ssigned", indent_level, "", value->size,
+ value->sign ? "" : "un");
+ fprintf(f, "%*sAbsolute portion=", indent_level, "");
+ yasm_expr_print(value->abs, f);
+ fprintf(f, "\n");
+ if (value->rel) {
+ fprintf(f, "%*sRelative to=%s%s\n", indent_level, "",
+ value->seg_of ? "SEG " : "",
+ yasm_symrec_get_name(value->rel));
+ if (value->wrt)
+ fprintf(f, "%*s(With respect to=%s)\n", indent_level, "",
+ yasm_symrec_get_name(value->wrt));
+ if (value->rshift > 0)
+ fprintf(f, "%*s(Right shifted by=%u)\n", indent_level, "",
+ value->rshift);
+ if (value->curpos_rel)
+ fprintf(f, "%*s(Relative to current position)\n", indent_level,
+ "");
+ if (value->ip_rel)
+ fprintf(f, "%*s(IP-relative)\n", indent_level, "");
+ if (value->jump_target)
+ fprintf(f, "%*s(Jump target)\n", indent_level, "");
+ if (value->section_rel)
+ fprintf(f, "%*s(Section-relative)\n", indent_level, "");
+ if (value->no_warn)
+ fprintf(f, "%*s(Overflow warnings disabled)\n", indent_level, "");
+ }
+}
diff --git a/contrib/tools/yasm/libyasm/value.h b/contrib/tools/yasm/libyasm/value.h
new file mode 100644
index 0000000000..4dc294bcc3
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/value.h
@@ -0,0 +1,172 @@
+/**
+ * \file libyasm/value.h
+ * \brief YASM value interface.
+ *
+ * \license
+ * Copyright (C) 2006-2007 Peter Johnson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * \endlicense
+ */
+#ifndef YASM_VALUE_H
+#define YASM_VALUE_H
+
+#ifndef YASM_LIB_DECL
+#define YASM_LIB_DECL
+#endif
+
+/** Initialize a #yasm_value with just an expression. No processing is
+ * performed, the expression is simply stuck into value.abs and the other
+ * fields are initialized. Use yasm_expr_extract_value() to perform "smart"
+ * processing into a #yasm_value. This function is intended for use during
+ * parsing simply to ensure all fields of the value are initialized; after
+ * the parse is complete, yasm_value_extract() should be called to finalize
+ * the value. The value defaults to unsigned.
+ * \param value value to be initialized
+ * \param e expression (kept)
+ * \param size value size (in bits)
+ */
+YASM_LIB_DECL
+void yasm_value_initialize(/*@out@*/ yasm_value *value,
+ /*@null@*/ /*@kept@*/ yasm_expr *e,
+ unsigned int size);
+
+/** Initialize a #yasm_value with just a symrec. No processing is performed,
+ * the symrec is simply stuck into value.rel and the other fields are
+ * initialized.
+ * \param value value to be initialized
+ * \param sym symrec
+ * \param size value size (in bits)
+ */
+YASM_LIB_DECL
+void yasm_value_init_sym(/*@out@*/ yasm_value *value,
+ /*@null@*/ yasm_symrec *sym, unsigned int size);
+
+/** Initialize a #yasm_value as a copy of another yasm_value. Any expressions
+ * within orig are copied, so it's safe to delete the copy.
+ * \param value value (copy to create)
+ * \param orig original value
+ */
+YASM_LIB_DECL
+void yasm_value_init_copy(yasm_value *value, const yasm_value *orig);
+
+/** Frees any memory inside value; does not free value itself.
+ * \param value value
+ */
+YASM_LIB_DECL
+void yasm_value_delete(yasm_value *value);
+
+/** Set a value to be relative to the current assembly position rather than
+ * relative to the section start.
+ * \param value value
+ * \param bc bytecode containing value
+ * \param ip_rel if nonzero, indicates IP-relative data relocation,
+ * sometimes used to generate special relocations
+ * \note If value is just an absolute value, will get an absolute symrec to
+ * reference to (via bc's symbol table).
+ */
+YASM_LIB_DECL
+void yasm_value_set_curpos_rel(yasm_value *value, yasm_bytecode *bc,
+ unsigned int ip_rel);
+
+/** Perform yasm_value_finalize_expr() on a value that already exists from
+ * being initialized with yasm_value_initialize().
+ * \param value value
+ * \param precbc previous bytecode to bytecode containing value
+ * \return Nonzero if value could not be split.
+ */
+YASM_LIB_DECL
+int yasm_value_finalize(yasm_value *value, /*@null@*/ yasm_bytecode *precbc);
+
+/** Break a #yasm_expr into a #yasm_value constituent parts. Extracts
+ * the relative portion of the value, SEG and WRT portions, and top-level
+ * right shift, if any. Places the remaining expr into the absolute
+ * portion of the value. Essentially a combination of yasm_value_initialize()
+ * and yasm_value_finalize(). First expands references to symrecs in
+ * absolute sections by expanding with the absolute section start plus the
+ * symrec offset within the absolute section.
+ * \param value value to store split portions into
+ * \param e expression input
+ * \param precbc previous bytecode to bytecode containing expression
+ * \param size value size (in bits)
+ * \return Nonzero if the expr could not be split into a value for some
+ * reason (e.g. the relative portion was not added, but multiplied,
+ * etc).
+ * \warning Do not use e after this call. Even if an error is returned, e
+ * is stored into value.
+ * \note This should only be called after the parse is complete. Calling
+ * before the parse is complete will usually result in an error return.
+ */
+YASM_LIB_DECL
+int yasm_value_finalize_expr(/*@out@*/ yasm_value *value,
+ /*@null@*/ /*@kept@*/ yasm_expr *e,
+ /*@null@*/ yasm_bytecode *precbc,
+ unsigned int size);
+
+/** Get value if absolute or PC-relative section-local relative. Returns NULL
+ * otherwise.
+ * \param value value
+ * \param bc current bytecode (for PC-relative calculation); if
+ * NULL, NULL is returned for PC-relative values.
+ * \param calc_bc_dist if nonzero, calculates bytecode distances in absolute
+ * portion of value
+ * \note Adds in value.rel (correctly) if PC-relative and in the same section
+ * as bc (and there is no WRT or SEG).
+ * \return Intnum if can be resolved to integer value, otherwise NULL.
+ */
+YASM_LIB_DECL
+/*@null@*/ /*@only@*/ yasm_intnum *yasm_value_get_intnum
+ (yasm_value *value, /*@null@*/ yasm_bytecode *bc, int calc_bc_dist);
+
+/** Output value if constant or PC-relative section-local. This should be
+ * used from objfmt yasm_output_value_func() functions.
+ * functions.
+ * \param value value
+ * \param buf buffer for byte representation
+ * \param destsize destination size (in bytes)
+ * \param bc current bytecode (usually passed into higher-level
+ * calling function)
+ * \param warn enables standard warnings: zero for none;
+ * nonzero for overflow/underflow floating point and
+ * integer warnings
+ * \param arch architecture
+ * \note Adds in value.rel (correctly) if PC-relative and in the same section
+ * as bc (and there is no WRT or SEG); if this is not the desired
+ * behavior, e.g. a reloc is needed in this case, don't use this
+ * function!
+ * \return 0 if no value output due to value needing relocation;
+ * 1 if value output; -1 if error.
+ */
+YASM_LIB_DECL
+int yasm_value_output_basic
+ (yasm_value *value, /*@out@*/ unsigned char *buf, size_t destsize,
+ yasm_bytecode *bc, int warn, yasm_arch *arch);
+
+/** Print a value. For debugging purposes.
+ * \param value value
+ * \param indent_level indentation level
+ * \param f file
+ */
+YASM_LIB_DECL
+void yasm_value_print(const yasm_value *value, FILE *f, int indent_level);
+
+#endif
diff --git a/contrib/tools/yasm/libyasm/xmalloc.c b/contrib/tools/yasm/libyasm/xmalloc.c
new file mode 100644
index 0000000000..81b608c078
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/xmalloc.c
@@ -0,0 +1,114 @@
+/*
+ * Memory allocation routines with error checking. Idea from GNU libiberty.
+ *
+ * Copyright (C) 2001-2007 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 "util.h"
+
+#include "coretype.h"
+#include "errwarn.h"
+
+
+#ifdef WITH_DMALLOC
+#undef yasm_xmalloc
+#undef yasm_xcalloc
+#undef yasm_xrealloc
+#undef yasm_xfree
+#endif
+
+static /*@only@*/ /*@out@*/ void *def_xmalloc(size_t size);
+static /*@only@*/ void *def_xcalloc(size_t nelem, size_t elsize);
+static /*@only@*/ void *def_xrealloc
+ (/*@only@*/ /*@out@*/ /*@returned@*/ /*@null@*/ void *oldmem, size_t size)
+ /*@modifies oldmem@*/;
+static void def_xfree(/*@only@*/ /*@out@*/ /*@null@*/ void *p)
+ /*@modifies p@*/;
+
+/* storage for global function pointers */
+YASM_LIB_DECL
+/*@only@*/ /*@out@*/ void * (*yasm_xmalloc) (size_t size) = def_xmalloc;
+YASM_LIB_DECL
+/*@only@*/ void * (*yasm_xcalloc) (size_t nelem, size_t elsize) = def_xcalloc;
+YASM_LIB_DECL
+/*@only@*/ void * (*yasm_xrealloc)
+ (/*@only@*/ /*@out@*/ /*@returned@*/ /*@null@*/ void *oldmem, size_t size)
+ /*@modifies oldmem@*/ = def_xrealloc;
+YASM_LIB_DECL
+void (*yasm_xfree) (/*@only@*/ /*@out@*/ /*@null@*/ void *p)
+ /*@modifies p@*/ = def_xfree;
+
+
+static void *
+def_xmalloc(size_t size)
+{
+ void *newmem;
+
+ if (size == 0)
+ size = 1;
+ newmem = malloc(size);
+ if (!newmem)
+ yasm__fatal(N_("out of memory"));
+
+ return newmem;
+}
+
+static void *
+def_xcalloc(size_t nelem, size_t elsize)
+{
+ void *newmem;
+
+ if (nelem == 0 || elsize == 0)
+ nelem = elsize = 1;
+
+ newmem = calloc(nelem, elsize);
+ if (!newmem)
+ yasm__fatal(N_("out of memory"));
+
+ return newmem;
+}
+
+static void *
+def_xrealloc(void *oldmem, size_t size)
+{
+ void *newmem;
+
+ if (size == 0)
+ size = 1;
+ if (!oldmem)
+ newmem = malloc(size);
+ else
+ newmem = realloc(oldmem, size);
+ if (!newmem)
+ yasm__fatal(N_("out of memory"));
+
+ return newmem;
+}
+
+static void
+def_xfree(void *p)
+{
+ if (!p)
+ return;
+ free(p);
+}
diff --git a/contrib/tools/yasm/libyasm/xstrdup.c b/contrib/tools/yasm/libyasm/xstrdup.c
new file mode 100644
index 0000000000..b187704f0e
--- /dev/null
+++ b/contrib/tools/yasm/libyasm/xstrdup.c
@@ -0,0 +1,68 @@
+/*
+ * strdup() implementation with error checking (using xmalloc).
+ *
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND 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 REGENTS OR 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 "util.h"
+
+#include "coretype.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strdup.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+
+#ifdef WITH_DMALLOC
+#undef yasm__xstrdup
+#endif
+
+char *
+yasm__xstrdup(const char *str)
+{
+ size_t len;
+ char *copy;
+
+ len = strlen(str) + 1;
+ copy = yasm_xmalloc(len);
+ memcpy(copy, str, len);
+ return (copy);
+}
+
+char *
+yasm__xstrndup(const char *str, size_t max)
+{
+ size_t len = 0;
+ char *copy;
+
+ while (len < max && str[len] != '\0')
+ len++;
+ copy = yasm_xmalloc(len+1);
+ memcpy(copy, str, len);
+ copy[len] = '\0';
+ return (copy);
+}
diff --git a/contrib/tools/yasm/modules/arch/lc3b/lc3barch.c b/contrib/tools/yasm/modules/arch/lc3b/lc3barch.c
new file mode 100644
index 0000000000..051452862f
--- /dev/null
+++ b/contrib/tools/yasm/modules/arch/lc3b/lc3barch.c
@@ -0,0 +1,212 @@
+/*
+ * LC-3b architecture description
+ *
+ * Copyright (C) 2003-2007 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 <util.h>
+
+#include <libyasm.h>
+
+#include "lc3barch.h"
+
+
+yasm_arch_module yasm_lc3b_LTX_arch;
+
+
+static /*@only@*/ yasm_arch *
+lc3b_create(const char *machine, const char *parser,
+ /*@out@*/ yasm_arch_create_error *error)
+{
+ yasm_arch_base *arch;
+
+ *error = YASM_ARCH_CREATE_OK;
+
+ if (yasm__strcasecmp(machine, "lc3b") != 0) {
+ *error = YASM_ARCH_CREATE_BAD_MACHINE;
+ return NULL;
+ }
+
+ if (yasm__strcasecmp(parser, "nasm") != 0) {
+ *error = YASM_ARCH_CREATE_BAD_PARSER;
+ return NULL;
+ }
+
+ arch = yasm_xmalloc(sizeof(yasm_arch_base));
+ arch->module = &yasm_lc3b_LTX_arch;
+ return (yasm_arch *)arch;
+}
+
+static void
+lc3b_destroy(/*@only@*/ yasm_arch *arch)
+{
+ yasm_xfree(arch);
+}
+
+static const char *
+lc3b_get_machine(/*@unused@*/ const yasm_arch *arch)
+{
+ return "lc3b";
+}
+
+static unsigned int
+lc3b_get_address_size(/*@unused@*/ const yasm_arch *arch)
+{
+ return 16;
+}
+
+static int
+lc3b_set_var(yasm_arch *arch, const char *var, unsigned long val)
+{
+ return 1;
+}
+
+static const unsigned char **
+lc3b_get_fill(const yasm_arch *arch)
+{
+ /* NOP pattern is all 0's per LC-3b Assembler 3.50 output */
+ static const unsigned char *fill[16] = {
+ NULL, /* unused */
+ NULL, /* 1 - illegal; all opcodes are 2 bytes long */
+ (const unsigned char *)
+ "\x00\x00", /* 4 */
+ NULL, /* 3 - illegal */
+ (const unsigned char *)
+ "\x00\x00\x00\x00", /* 4 */
+ NULL, /* 5 - illegal */
+ (const unsigned char *)
+ "\x00\x00\x00\x00\x00\x00", /* 6 */
+ NULL, /* 7 - illegal */
+ (const unsigned char *)
+ "\x00\x00\x00\x00\x00\x00" /* 8 */
+ "\x00\x00",
+ NULL, /* 9 - illegal */
+ (const unsigned char *)
+ "\x00\x00\x00\x00\x00\x00" /* 10 */
+ "\x00\x00\x00\x00",
+ NULL, /* 11 - illegal */
+ (const unsigned char *)
+ "\x00\x00\x00\x00\x00\x00" /* 12 */
+ "\x00\x00\x00\x00\x00\x00",
+ NULL, /* 13 - illegal */
+ (const unsigned char *)
+ "\x00\x00\x00\x00\x00\x00" /* 14 */
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ NULL /* 15 - illegal */
+ };
+ return fill;
+}
+
+static unsigned int
+lc3b_get_reg_size(/*@unused@*/ yasm_arch *arch, /*@unused@*/ uintptr_t reg)
+{
+ return 16;
+}
+
+static uintptr_t
+lc3b_reggroup_get_reg(/*@unused@*/ yasm_arch *arch,
+ /*@unused@*/ uintptr_t reggroup,
+ /*@unused@*/ unsigned long regindex)
+{
+ return 0;
+}
+
+static void
+lc3b_reg_print(/*@unused@*/ yasm_arch *arch, uintptr_t reg, FILE *f)
+{
+ fprintf(f, "r%u", (unsigned int)(reg&7));
+}
+
+static int
+lc3b_floatnum_tobytes(yasm_arch *arch, const yasm_floatnum *flt,
+ unsigned char *buf, size_t destsize, size_t valsize,
+ size_t shift, int warn)
+{
+ yasm_error_set(YASM_ERROR_FLOATING_POINT,
+ N_("LC-3b does not support floating point"));
+ return 1;
+}
+
+static yasm_effaddr *
+lc3b_ea_create_expr(yasm_arch *arch, yasm_expr *e)
+{
+ yasm_effaddr *ea = yasm_xmalloc(sizeof(yasm_effaddr));
+ yasm_value_initialize(&ea->disp, e, 0);
+ ea->need_nonzero_len = 0;
+ ea->need_disp = 1;
+ ea->nosplit = 0;
+ ea->strong = 0;
+ ea->segreg = 0;
+ ea->pc_rel = 0;
+ ea->not_pc_rel = 0;
+ return ea;
+}
+
+void
+yasm_lc3b__ea_destroy(/*@only@*/ yasm_effaddr *ea)
+{
+ yasm_value_delete(&ea->disp);
+ yasm_xfree(ea);
+}
+
+static void
+lc3b_ea_print(const yasm_effaddr *ea, FILE *f, int indent_level)
+{
+ fprintf(f, "%*sDisp:\n", indent_level, "");
+ yasm_value_print(&ea->disp, f, indent_level+1);
+}
+
+/* Define lc3b machines -- see arch.h for details */
+static yasm_arch_machine lc3b_machines[] = {
+ { "LC-3b", "lc3b" },
+ { NULL, NULL }
+};
+
+/* Define arch structure -- see arch.h for details */
+yasm_arch_module yasm_lc3b_LTX_arch = {
+ "LC-3b",
+ "lc3b",
+ NULL,
+ lc3b_create,
+ lc3b_destroy,
+ lc3b_get_machine,
+ lc3b_get_address_size,
+ lc3b_set_var,
+ yasm_lc3b__parse_check_insnprefix,
+ yasm_lc3b__parse_check_regtmod,
+ lc3b_get_fill,
+ lc3b_floatnum_tobytes,
+ yasm_lc3b__intnum_tobytes,
+ lc3b_get_reg_size,
+ lc3b_reggroup_get_reg,
+ lc3b_reg_print,
+ NULL, /*yasm_lc3b__segreg_print*/
+ lc3b_ea_create_expr,
+ yasm_lc3b__ea_destroy,
+ lc3b_ea_print,
+ yasm_lc3b__create_empty_insn,
+ lc3b_machines,
+ "lc3b",
+ 16,
+ 2
+};
diff --git a/contrib/tools/yasm/modules/arch/lc3b/lc3barch.h b/contrib/tools/yasm/modules/arch/lc3b/lc3barch.h
new file mode 100644
index 0000000000..9ded8cbef7
--- /dev/null
+++ b/contrib/tools/yasm/modules/arch/lc3b/lc3barch.h
@@ -0,0 +1,70 @@
+/*
+ * LC-3b Architecture header file
+ *
+ * Copyright (C) 2003-2007 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.
+ */
+#ifndef YASM_LC3BARCH_H
+#define YASM_LC3BARCH_H
+
+/* Types of immediate. All immediates are stored in the LSBs of the insn. */
+typedef enum lc3b_imm_type {
+ LC3B_IMM_NONE = 0, /* no immediate */
+ LC3B_IMM_4, /* 4-bit */
+ LC3B_IMM_5, /* 5-bit */
+ LC3B_IMM_6_WORD, /* 6-bit, word-multiple (byte>>1) */
+ LC3B_IMM_6_BYTE, /* 6-bit, byte-multiple */
+ LC3B_IMM_8, /* 8-bit, word-multiple (byte>>1) */
+ LC3B_IMM_9, /* 9-bit, signed, word-multiple (byte>>1) */
+ LC3B_IMM_9_PC /* 9-bit, signed, word-multiple, PC relative */
+} lc3b_imm_type;
+
+/* Bytecode types */
+
+typedef struct lc3b_insn {
+ yasm_value imm; /* immediate or relative value */
+ lc3b_imm_type imm_type; /* size of the immediate */
+
+ unsigned int opcode; /* opcode */
+} lc3b_insn;
+
+void yasm_lc3b__bc_transform_insn(yasm_bytecode *bc, lc3b_insn *insn);
+
+yasm_arch_insnprefix yasm_lc3b__parse_check_insnprefix
+ (yasm_arch *arch, const char *id, size_t id_len, unsigned long line,
+ /*@out@*/ /*@only@*/ yasm_bytecode **bc, /*@out@*/ uintptr_t *prefix);
+yasm_arch_regtmod yasm_lc3b__parse_check_regtmod
+ (yasm_arch *arch, const char *id, size_t id_len,
+ /*@out@*/ uintptr_t *data);
+
+int yasm_lc3b__intnum_tobytes
+ (yasm_arch *arch, const yasm_intnum *intn, unsigned char *buf,
+ size_t destsize, size_t valsize, int shift, const yasm_bytecode *bc,
+ int warn);
+
+/*@only@*/ yasm_bytecode *yasm_lc3b__create_empty_insn(yasm_arch *arch,
+ unsigned long line);
+
+void yasm_lc3b__ea_destroy(/*@only@*/ yasm_effaddr *ea);
+
+#endif
diff --git a/contrib/tools/yasm/modules/arch/lc3b/lc3bbc.c b/contrib/tools/yasm/modules/arch/lc3b/lc3bbc.c
new file mode 100644
index 0000000000..d077c7c5fb
--- /dev/null
+++ b/contrib/tools/yasm/modules/arch/lc3b/lc3bbc.c
@@ -0,0 +1,249 @@
+/*
+ * LC-3b bytecode utility functions
+ *
+ * Copyright (C) 2003-2007 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 <util.h>
+
+#include <libyasm.h>
+
+#include "lc3barch.h"
+
+
+/* Bytecode callback function prototypes */
+
+static void lc3b_bc_insn_destroy(void *contents);
+static void lc3b_bc_insn_print(const void *contents, FILE *f,
+ int indent_level);
+static int lc3b_bc_insn_calc_len(yasm_bytecode *bc,
+ yasm_bc_add_span_func add_span,
+ void *add_span_data);
+static int lc3b_bc_insn_expand(yasm_bytecode *bc, int span, long old_val,
+ long new_val, /*@out@*/ long *neg_thres,
+ /*@out@*/ long *pos_thres);
+static int lc3b_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart,
+ void *d, yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+/* Bytecode callback structures */
+
+static const yasm_bytecode_callback lc3b_bc_callback_insn = {
+ lc3b_bc_insn_destroy,
+ lc3b_bc_insn_print,
+ yasm_bc_finalize_common,
+ NULL,
+ lc3b_bc_insn_calc_len,
+ lc3b_bc_insn_expand,
+ lc3b_bc_insn_tobytes,
+ 0
+};
+
+
+void
+yasm_lc3b__bc_transform_insn(yasm_bytecode *bc, lc3b_insn *insn)
+{
+ yasm_bc_transform(bc, &lc3b_bc_callback_insn, insn);
+}
+
+static void
+lc3b_bc_insn_destroy(void *contents)
+{
+ lc3b_insn *insn = (lc3b_insn *)contents;
+ yasm_value_delete(&insn->imm);
+ yasm_xfree(contents);
+}
+
+static void
+lc3b_bc_insn_print(const void *contents, FILE *f, int indent_level)
+{
+ const lc3b_insn *insn = (const lc3b_insn *)contents;
+
+ fprintf(f, "%*s_Instruction_\n", indent_level, "");
+ fprintf(f, "%*sImmediate Value:", indent_level, "");
+ if (!insn->imm.abs)
+ fprintf(f, " (nil)\n");
+ else {
+ indent_level++;
+ fprintf(f, "\n");
+ yasm_value_print(&insn->imm, f, indent_level);
+ fprintf(f, "%*sType=", indent_level, "");
+ switch (insn->imm_type) {
+ case LC3B_IMM_NONE:
+ fprintf(f, "NONE-SHOULDN'T HAPPEN");
+ break;
+ case LC3B_IMM_4:
+ fprintf(f, "4-bit");
+ break;
+ case LC3B_IMM_5:
+ fprintf(f, "5-bit");
+ break;
+ case LC3B_IMM_6_WORD:
+ fprintf(f, "6-bit, word-multiple");
+ break;
+ case LC3B_IMM_6_BYTE:
+ fprintf(f, "6-bit, byte-multiple");
+ break;
+ case LC3B_IMM_8:
+ fprintf(f, "8-bit, word-multiple");
+ break;
+ case LC3B_IMM_9:
+ fprintf(f, "9-bit, signed, word-multiple");
+ break;
+ case LC3B_IMM_9_PC:
+ fprintf(f, "9-bit, signed, word-multiple, PC-relative");
+ break;
+ }
+ indent_level--;
+ }
+ /* FIXME
+ fprintf(f, "\n%*sOrigin=", indent_level, "");
+ if (insn->origin) {
+ fprintf(f, "\n");
+ yasm_symrec_print(insn->origin, f, indent_level+1);
+ } else
+ fprintf(f, "(nil)\n");
+ */
+ fprintf(f, "%*sOpcode: %04x\n", indent_level, "",
+ (unsigned int)insn->opcode);
+}
+
+static int
+lc3b_bc_insn_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ lc3b_insn *insn = (lc3b_insn *)bc->contents;
+ yasm_bytecode *target_prevbc;
+
+ /* Fixed size instruction length */
+ bc->len += 2;
+
+ /* Only need to worry about out-of-range to PC-relative */
+ if (insn->imm_type != LC3B_IMM_9_PC)
+ return 0;
+
+ if (insn->imm.rel
+ && (!yasm_symrec_get_label(insn->imm.rel, &target_prevbc)
+ || target_prevbc->section != bc->section)) {
+ /* External or out of segment, so we can't check distance. */
+ return 0;
+ }
+
+ /* 9-bit signed, word-multiple displacement */
+ add_span(add_span_data, bc, 1, &insn->imm, -512+(long)bc->len,
+ 511+(long)bc->len);
+ return 0;
+}
+
+static int
+lc3b_bc_insn_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
+{
+ yasm_error_set(YASM_ERROR_VALUE, N_("jump target out of range"));
+ return -1;
+}
+
+static int
+lc3b_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ lc3b_insn *insn = (lc3b_insn *)bc->contents;
+ /*@only@*/ yasm_intnum *delta;
+ unsigned long buf_off = (unsigned long)(*bufp - bufstart);
+
+ /* Output opcode */
+ YASM_SAVE_16_L(*bufp, insn->opcode);
+
+ /* Insert immediate into opcode. */
+ switch (insn->imm_type) {
+ case LC3B_IMM_NONE:
+ break;
+ case LC3B_IMM_4:
+ insn->imm.size = 4;
+ if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
+ return 1;
+ break;
+ case LC3B_IMM_5:
+ insn->imm.size = 5;
+ insn->imm.sign = 1;
+ if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
+ return 1;
+ break;
+ case LC3B_IMM_6_WORD:
+ insn->imm.size = 6;
+ if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
+ return 1;
+ break;
+ case LC3B_IMM_6_BYTE:
+ insn->imm.size = 6;
+ insn->imm.sign = 1;
+ if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
+ return 1;
+ break;
+ case LC3B_IMM_8:
+ insn->imm.size = 8;
+ if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
+ return 1;
+ break;
+ case LC3B_IMM_9_PC:
+ /* Adjust relative displacement to end of bytecode */
+ delta = yasm_intnum_create_int(-1);
+ if (!insn->imm.abs)
+ insn->imm.abs = yasm_expr_create_ident(yasm_expr_int(delta),
+ bc->line);
+ else
+ insn->imm.abs =
+ yasm_expr_create(YASM_EXPR_ADD,
+ yasm_expr_expr(insn->imm.abs),
+ yasm_expr_int(delta), bc->line);
+
+ insn->imm.size = 9;
+ insn->imm.sign = 1;
+ if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
+ return 1;
+ break;
+ case LC3B_IMM_9:
+ insn->imm.size = 9;
+ if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
+ return 1;
+ break;
+ default:
+ yasm_internal_error(N_("Unrecognized immediate type"));
+ }
+
+ *bufp += 2; /* all instructions are 2 bytes in size */
+ return 0;
+}
+
+int
+yasm_lc3b__intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn,
+ unsigned char *buf, size_t destsize, size_t valsize,
+ int shift, const yasm_bytecode *bc, int warn)
+{
+ /* Write value out. */
+ yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn);
+ return 0;
+}
diff --git a/contrib/tools/yasm/modules/arch/x86/x86arch.c b/contrib/tools/yasm/modules/arch/x86/x86arch.c
new file mode 100644
index 0000000000..bac11774ea
--- /dev/null
+++ b/contrib/tools/yasm/modules/arch/x86/x86arch.c
@@ -0,0 +1,633 @@
+/*
+ * x86 architecture description
+ *
+ * Copyright (C) 2002-2007 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 <util.h>
+
+#include <libyasm.h>
+
+#include "x86arch.h"
+
+
+yasm_arch_module yasm_x86_LTX_arch;
+
+
+static /*@only@*/ yasm_arch *
+x86_create(const char *machine, const char *parser,
+ /*@out@*/ yasm_arch_create_error *error)
+{
+ yasm_arch_x86 *arch_x86;
+ unsigned int amd64_machine, address_size;
+
+ *error = YASM_ARCH_CREATE_OK;
+
+ if (yasm__strcasecmp(machine, "x86") == 0) {
+ amd64_machine = 0;
+ address_size = 32;
+ } else if (yasm__strcasecmp(machine, "amd64") == 0) {
+ amd64_machine = 1;
+ address_size = 64;
+ } else if (yasm__strcasecmp(machine, "x32") == 0) {
+ amd64_machine = 1;
+ address_size = 32;
+ }
+ else {
+ *error = YASM_ARCH_CREATE_BAD_MACHINE;
+ return NULL;
+ }
+
+ arch_x86 = yasm_xmalloc(sizeof(yasm_arch_x86));
+
+ arch_x86->arch.module = &yasm_x86_LTX_arch;
+
+ /* default to all instructions/features enabled */
+ arch_x86->active_cpu = 0;
+ arch_x86->cpu_enables_size = 1;
+ arch_x86->cpu_enables = yasm_xmalloc(sizeof(wordptr));
+ arch_x86->cpu_enables[0] = BitVector_Create(64, FALSE);
+ BitVector_Fill(arch_x86->cpu_enables[0]);
+
+ arch_x86->amd64_machine = amd64_machine;
+ arch_x86->mode_bits = 0;
+ arch_x86->address_size = address_size;
+ arch_x86->force_strict = 0;
+ arch_x86->default_rel = 0;
+ arch_x86->gas_intel_mode = 0;
+ arch_x86->nop = X86_NOP_BASIC;
+
+ if (yasm__strcasecmp(parser, "nasm") == 0)
+ arch_x86->parser = X86_PARSER_NASM;
+ else if (yasm__strcasecmp(parser, "tasm") == 0)
+ arch_x86->parser = X86_PARSER_TASM;
+ else if (yasm__strcasecmp(parser, "gas") == 0
+ || yasm__strcasecmp(parser, "gnu") == 0)
+ arch_x86->parser = X86_PARSER_GAS;
+ else {
+ yasm_xfree(arch_x86);
+ *error = YASM_ARCH_CREATE_BAD_PARSER;
+ return NULL;
+ }
+
+ return (yasm_arch *)arch_x86;
+}
+
+static void
+x86_destroy(/*@only@*/ yasm_arch *arch)
+{
+ yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
+ unsigned int i;
+ for (i=0; i<arch_x86->cpu_enables_size; i++)
+ BitVector_Destroy(arch_x86->cpu_enables[i]);
+ yasm_xfree(arch_x86->cpu_enables);
+ yasm_xfree(arch);
+}
+
+static const char *
+x86_get_machine(const yasm_arch *arch)
+{
+ const yasm_arch_x86 *arch_x86 = (const yasm_arch_x86 *)arch;
+ if (arch_x86->amd64_machine) {
+ if (arch_x86->address_size == 32)
+ return "x32";
+ else
+ return "amd64";
+ } else
+ return "x86";
+}
+
+static unsigned int
+x86_get_address_size(const yasm_arch *arch)
+{
+ const yasm_arch_x86 *arch_x86 = (const yasm_arch_x86 *)arch;
+ if (arch_x86->mode_bits != 0)
+ return arch_x86->mode_bits;
+ return arch_x86->address_size;
+}
+
+static int
+x86_set_var(yasm_arch *arch, const char *var, unsigned long val)
+{
+ yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
+ if (yasm__strcasecmp(var, "mode_bits") == 0)
+ arch_x86->mode_bits = (unsigned int)val;
+ else if (yasm__strcasecmp(var, "force_strict") == 0)
+ arch_x86->force_strict = (unsigned int)val;
+ else if (yasm__strcasecmp(var, "default_rel") == 0) {
+ if (arch_x86->mode_bits != 64)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("ignoring default rel in non-64-bit mode"));
+ else
+ arch_x86->default_rel = (unsigned int)val;
+ } else if (yasm__strcasecmp(var, "gas_intel_mode") == 0) {
+ arch_x86->gas_intel_mode = (unsigned int)val;
+ } else
+ return 1;
+ return 0;
+}
+
+static void
+x86_dir_cpu(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)object->arch;
+
+ yasm_valparam *vp;
+ yasm_vps_foreach(vp, valparams) {
+ /*@null@*/ /*@dependent@*/ const char *s = yasm_vp_string(vp);
+ if (s)
+ yasm_x86__parse_cpu(arch_x86, s, strlen(s));
+ else if (vp->type == YASM_PARAM_EXPR) {
+ const yasm_intnum *intcpu;
+ intcpu = yasm_expr_get_intnum(&vp->param.e, 0);
+ if (!intcpu)
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("invalid argument to [%s]"), "CPU");
+ else {
+ char strcpu[16];
+ sprintf(strcpu, "%lu", yasm_intnum_get_uint(intcpu));
+ yasm_x86__parse_cpu(arch_x86, strcpu, strlen(strcpu));
+ }
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"),
+ "CPU");
+ }
+}
+
+static void
+x86_dir_bits(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)object->arch;
+ yasm_valparam *vp;
+ /*@only@*/ /*@null@*/ yasm_expr *e = NULL;
+ const yasm_intnum *intn;
+ long lval;
+
+ if ((vp = yasm_vps_first(valparams)) && !vp->val &&
+ (e = yasm_vp_expr(vp, object->symtab, line)) != NULL &&
+ (intn = yasm_expr_get_intnum(&e, 0)) != NULL &&
+ (lval = yasm_intnum_get_int(intn)) &&
+ (lval == 16 || lval == 32 || lval == 64))
+ arch_x86->mode_bits = (unsigned char)lval;
+ else
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid argument to [%s]"),
+ "BITS");
+ if (e)
+ yasm_expr_destroy(e);
+}
+
+static void
+x86_dir_code16(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)object->arch;
+ arch_x86->mode_bits = 16;
+}
+
+static void
+x86_dir_code32(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)object->arch;
+ arch_x86->mode_bits = 32;
+}
+
+static void
+x86_dir_code64(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)object->arch;
+ arch_x86->mode_bits = 64;
+}
+
+static const unsigned char **
+x86_get_fill(const yasm_arch *arch)
+{
+ const yasm_arch_x86 *arch_x86 = (const yasm_arch_x86 *)arch;
+
+ /* Fill patterns that GAS uses. */
+ static const unsigned char fill16_1[1] =
+ {0x90}; /* 1 - nop */
+ static const unsigned char fill16_2[2] =
+ {0x89, 0xf6}; /* 2 - mov si, si */
+ static const unsigned char fill16_3[3] =
+ {0x8d, 0x74, 0x00}; /* 3 - lea si, [si+byte 0] */
+ static const unsigned char fill16_4[4] =
+ {0x8d, 0xb4, 0x00, 0x00}; /* 4 - lea si, [si+word 0] */
+ static const unsigned char fill16_5[5] =
+ {0x90, /* 5 - nop */
+ 0x8d, 0xb4, 0x00, 0x00}; /* lea si, [si+word 0] */
+ static const unsigned char fill16_6[6] =
+ {0x89, 0xf6, /* 6 - mov si, si */
+ 0x8d, 0xbd, 0x00, 0x00}; /* lea di, [di+word 0] */
+ static const unsigned char fill16_7[7] =
+ {0x8d, 0x74, 0x00, /* 7 - lea si, [si+byte 0] */
+ 0x8d, 0xbd, 0x00, 0x00}; /* lea di, [di+word 0] */
+ static const unsigned char fill16_8[8] =
+ {0x8d, 0xb4, 0x00, 0x00, /* 8 - lea si, [si+word 0] */
+ 0x8d, 0xbd, 0x00, 0x00}; /* lea di, [di+word 0] */
+ static const unsigned char fill16_9[9] =
+ {0xeb, 0x07, 0x90, 0x90, 0x90, 0x90, /* 9 - jmp $+9; nop fill */
+ 0x90, 0x90, 0x90};
+ static const unsigned char fill16_10[10] =
+ {0xeb, 0x08, 0x90, 0x90, 0x90, 0x90, /* 10 - jmp $+10; nop fill */
+ 0x90, 0x90, 0x90, 0x90};
+ static const unsigned char fill16_11[11] =
+ {0xeb, 0x09, 0x90, 0x90, 0x90, 0x90, /* 11 - jmp $+11; nop fill */
+ 0x90, 0x90, 0x90, 0x90, 0x90};
+ static const unsigned char fill16_12[12] =
+ {0xeb, 0x0a, 0x90, 0x90, 0x90, 0x90, /* 12 - jmp $+12; nop fill */
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
+ static const unsigned char fill16_13[13] =
+ {0xeb, 0x0b, 0x90, 0x90, 0x90, 0x90, /* 13 - jmp $+13; nop fill */
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
+ static const unsigned char fill16_14[14] =
+ {0xeb, 0x0c, 0x90, 0x90, 0x90, 0x90, /* 14 - jmp $+14; nop fill */
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
+ static const unsigned char fill16_15[15] =
+ {0xeb, 0x0d, 0x90, 0x90, 0x90, 0x90, /* 15 - jmp $+15; nop fill */
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
+ static const unsigned char *fill16[16] =
+ {
+ NULL, fill16_1, fill16_2, fill16_3,
+ fill16_4, fill16_5, fill16_6, fill16_7,
+ fill16_8, fill16_9, fill16_10, fill16_11,
+ fill16_12, fill16_13, fill16_14, fill16_15
+ };
+
+ static const unsigned char fill32_1[1] =
+ {0x90}; /* 1 - nop */
+ static const unsigned char fill32_2[2] =
+ {0x66, 0x90}; /* 2 - xchg ax, ax (o16 nop) */
+ static const unsigned char fill32_3[3] =
+ {0x8d, 0x76, 0x00}; /* 3 - lea esi, [esi+byte 0] */
+ static const unsigned char fill32_4[4] =
+ {0x8d, 0x74, 0x26, 0x00}; /* 4 - lea esi, [esi*1+byte 0] */
+ static const unsigned char fill32_5[5] =
+ {0x90, /* 5 - nop */
+ 0x8d, 0x74, 0x26, 0x00}; /* lea esi, [esi*1+byte 0] */
+ static const unsigned char fill32_6[6] =
+ {0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00};/* 6 - lea esi, [esi+dword 0] */
+ static const unsigned char fill32_7[7] =
+ {0x8d, 0xb4, 0x26, 0x00, 0x00, 0x00, /* 7 - lea esi, [esi*1+dword 0] */
+ 0x00};
+ static const unsigned char fill32_8[8] =
+ {0x90, /* 8 - nop */
+ 0x8d, 0xb4, 0x26, 0x00, 0x00, 0x00, /* lea esi, [esi*1+dword 0] */
+ 0x00};
+#if 0
+ /* GAS uses these */
+ static const unsigned char fill32_9[9] =
+ {0x89, 0xf6, /* 9 - mov esi, esi */
+ 0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, /* lea edi, [edi*1+dword 0] */
+ 0x00};
+ static const unsigned char fill32_10[10] =
+ {0x8d, 0x76, 0x00, /* 10 - lea esi, [esi+byte 0] */
+ 0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, /* lea edi, [edi+dword 0] */
+ 0x00};
+ static const unsigned char fill32_11[11] =
+ {0x8d, 0x74, 0x26, 0x00, /* 11 - lea esi, [esi*1+byte 0] */
+ 0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, /* lea edi, [edi*1+dword 0] */
+ 0x00};
+ static const unsigned char fill32_12[12] =
+ {0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00, /* 12 - lea esi, [esi+dword 0] */
+ 0x8d, 0xbf, 0x00, 0x00, 0x00, 0x00};/* lea edi, [edi+dword 0] */
+ static const unsigned char fill32_13[13] =
+ {0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00, /* 13 - lea esi, [esi+dword 0] */
+ 0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, /* lea edi, [edi*1+dword 0] */
+ 0x00};
+ static const unsigned char fill32_14[14] =
+ {0x8d, 0xb4, 0x26, 0x00, 0x00, 0x00, /* 14 - lea esi, [esi*1+dword 0] */
+ 0x00,
+ 0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, /* lea edi, [edi*1+dword 0] */
+ 0x00};
+#else
+ /* But on newer processors, these are recommended */
+ static const unsigned char fill32_9[9] =
+ {0xeb, 0x07, 0x90, 0x90, 0x90, 0x90, /* 9 - jmp $+9; nop fill */
+ 0x90, 0x90, 0x90};
+ static const unsigned char fill32_10[10] =
+ {0xeb, 0x08, 0x90, 0x90, 0x90, 0x90, /* 10 - jmp $+10; nop fill */
+ 0x90, 0x90, 0x90, 0x90};
+ static const unsigned char fill32_11[11] =
+ {0xeb, 0x09, 0x90, 0x90, 0x90, 0x90, /* 11 - jmp $+11; nop fill */
+ 0x90, 0x90, 0x90, 0x90, 0x90};
+ static const unsigned char fill32_12[12] =
+ {0xeb, 0x0a, 0x90, 0x90, 0x90, 0x90, /* 12 - jmp $+12; nop fill */
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
+ static const unsigned char fill32_13[13] =
+ {0xeb, 0x0b, 0x90, 0x90, 0x90, 0x90, /* 13 - jmp $+13; nop fill */
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
+ static const unsigned char fill32_14[14] =
+ {0xeb, 0x0c, 0x90, 0x90, 0x90, 0x90, /* 14 - jmp $+14; nop fill */
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
+#endif
+ static const unsigned char fill32_15[15] =
+ {0xeb, 0x0d, 0x90, 0x90, 0x90, 0x90, /* 15 - jmp $+15; nop fill */
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
+ static const unsigned char *fill32[16] =
+ {
+ NULL, fill32_1, fill32_2, fill32_3,
+ fill32_4, fill32_5, fill32_6, fill32_7,
+ fill32_8, fill32_9, fill32_10, fill32_11,
+ fill32_12, fill32_13, fill32_14, fill32_15
+ };
+
+ /* Long form nops available on more recent Intel and AMD processors */
+ static const unsigned char fill32new_3[3] =
+ {0x0f, 0x1f, 0x00}; /* 3 - nop(3) */
+ static const unsigned char fill32new_4[4] =
+ {0x0f, 0x1f, 0x40, 0x00}; /* 4 - nop(4) */
+ static const unsigned char fill32new_5[5] =
+ {0x0f, 0x1f, 0x44, 0x00, 0x00}; /* 5 - nop(5) */
+ static const unsigned char fill32new_6[6] =
+ {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00}; /* 6 - nop(6) */
+ static const unsigned char fill32new_7[7] =
+ {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}; /* 7 - nop(7) */
+ static const unsigned char fill32new_8[8] =
+ {0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, /* 8 - nop(8) */
+ 0x00};
+ static const unsigned char fill32new_9[9] =
+ {0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, /* 9 - nop(9) */
+ 0x00, 0x00};
+
+ /* Longer forms preferred by Intel use repeated o16 prefixes */
+ static const unsigned char fill32intel_10[10] =
+ {0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, /* 10 - o16; cs; nop */
+ 0x00, 0x00, 0x00};
+ static const unsigned char fill32intel_11[11] =
+ {0x66, 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, /* 11 - 2x o16; cs; nop */
+ 0x00, 0x00, 0x00, 0x00};
+ static const unsigned char fill32intel_12[12] =
+ {0x66, 0x66, 0x66, 0x2e, 0x0f, 0x1f, 0x84, /* 12 - 3x o16; cs; nop */
+ 0x00, 0x00, 0x00, 0x00, 0x00};
+ static const unsigned char fill32intel_13[13] =
+ {0x66, 0x66, 0x66, 0x66, 0x2e, 0x0f, 0x1f, /* 13 - 4x o16; cs; nop */
+ 0x84, 0x00, 0x00, 0x00, 0x00, 0x00};
+ static const unsigned char fill32intel_14[14] =
+ {0x66, 0x66, 0x66, 0x66, 0x66, 0x2e, 0x0f, /* 14 - 5x o16; cs; nop */
+ 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00};
+ static const unsigned char fill32intel_15[15] =
+ {0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x2e, /* 15 - 6x o16; cs; nop */
+ 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ /* Longer forms preferred by AMD use fewer o16 prefixes and no CS prefix;
+ * Source: Software Optimisation Guide for AMD Family 10h
+ * Processors 40546 revision 3.10 February 2009
+ */
+ static const unsigned char fill32amd_10[10] =
+ {0x66, 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, /* 10 - nop(10) */
+ 0x00, 0x00, 0x00};
+ static const unsigned char fill32amd_11[11] =
+ {0x0f, 0x1f, 0x44, 0x00, 0x00, /* 11 - nop(5) */
+ 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00}; /* nop(6) */
+ static const unsigned char fill32amd_12[12] =
+ {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, /* 12 - nop(6) */
+ 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00}; /* nop(6) */
+ static const unsigned char fill32amd_13[13] =
+ {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, /* 13 - nop(6) */
+ 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}; /* nop(7) */
+ static const unsigned char fill32amd_14[14] =
+ {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, /* 14 - nop(7) */
+ 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}; /* nop(7) */
+ static const unsigned char fill32amd_15[15] =
+ {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, /* 15 - nop(7) */
+ 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}; /* nop(8) */
+
+ static const unsigned char *fill32_intel[16] =
+ {
+ NULL, fill32_1, fill32_2, fill32new_3,
+ fill32new_4, fill32new_5, fill32new_6, fill32new_7,
+ fill32new_8, fill32new_9, fill32intel_10, fill32intel_11,
+ fill32intel_12, fill32intel_13, fill32intel_14, fill32intel_15
+ };
+ static const unsigned char *fill32_amd[16] =
+ {
+ NULL, fill32_1, fill32_2, fill32new_3,
+ fill32new_4, fill32new_5, fill32new_6, fill32new_7,
+ fill32new_8, fill32new_9, fill32amd_10, fill32amd_11,
+ fill32amd_12, fill32amd_13, fill32amd_14, fill32amd_15
+ };
+
+ switch (arch_x86->mode_bits) {
+ case 16:
+ return fill16;
+ case 32:
+ if (arch_x86->nop == X86_NOP_INTEL)
+ return fill32_intel;
+ else if (arch_x86->nop == X86_NOP_AMD)
+ return fill32_amd;
+ else
+ return fill32;
+ case 64:
+ /* We know long nops are available in 64-bit mode; default to Intel
+ * ones if unspecified (to match GAS behavior).
+ */
+ if (arch_x86->nop == X86_NOP_AMD)
+ return fill32_amd;
+ else
+ return fill32_intel;
+ default:
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("Invalid mode_bits in x86_get_fill"));
+ return NULL;
+ }
+}
+
+unsigned int
+yasm_x86__get_reg_size(uintptr_t reg)
+{
+ switch ((x86_expritem_reg_size)(reg & ~0xFUL)) {
+ case X86_REG8:
+ case X86_REG8X:
+ return 8;
+ case X86_REG16:
+ return 16;
+ case X86_REG32:
+ case X86_CRREG:
+ case X86_DRREG:
+ case X86_TRREG:
+ return 32;
+ case X86_REG64:
+ case X86_MMXREG:
+ return 64;
+ case X86_XMMREG:
+ return 128;
+ case X86_YMMREG:
+ return 256;
+ case X86_FPUREG:
+ return 80;
+ default:
+ yasm_error_set(YASM_ERROR_VALUE, N_("unknown register size"));
+ }
+ return 0;
+}
+
+static unsigned int
+x86_get_reg_size(yasm_arch *arch, uintptr_t reg)
+{
+ return yasm_x86__get_reg_size(reg);
+}
+
+static uintptr_t
+x86_reggroup_get_reg(yasm_arch *arch, uintptr_t reggroup,
+ unsigned long regindex)
+{
+ yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
+ switch ((x86_expritem_reg_size)(reggroup & ~0xFUL)) {
+ case X86_XMMREG:
+ case X86_YMMREG:
+ if (arch_x86->mode_bits == 64) {
+ if (regindex > 15)
+ return 0;
+ return reggroup | (regindex & 15);
+ }
+ /*@fallthrough@*/
+ case X86_MMXREG:
+ case X86_FPUREG:
+ if (regindex > 7)
+ return 0;
+ return reggroup | (regindex & 7);
+ default:
+ yasm_error_set(YASM_ERROR_VALUE, N_("bad register group"));
+ }
+ return 0;
+}
+
+static void
+x86_reg_print(yasm_arch *arch, uintptr_t reg, FILE *f)
+{
+ static const char *name8[] = {"al","cl","dl","bl","ah","ch","dh","bh"};
+ static const char *name8x[] = {
+ "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
+ "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
+ };
+ static const char *name16[] = {
+ "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
+ "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
+ };
+ static const char *name32[] = {
+ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
+ "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
+ };
+ static const char *name64[] = {
+ "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+ };
+
+ switch ((x86_expritem_reg_size)(reg & ~0xFUL)) {
+ case X86_REG8:
+ fprintf(f, "%s", name8[reg&0xF]);
+ break;
+ case X86_REG8X:
+ fprintf(f, "%s", name8x[reg&0xF]);
+ break;
+ case X86_REG16:
+ fprintf(f, "%s", name16[reg&0xF]);
+ break;
+ case X86_REG32:
+ fprintf(f, "%s", name32[reg&0xF]);
+ break;
+ case X86_REG64:
+ fprintf(f, "%s", name64[reg&0xF]);
+ break;
+ case X86_MMXREG:
+ fprintf(f, "mm%d", (int)(reg&0xF));
+ break;
+ case X86_XMMREG:
+ fprintf(f, "xmm%d", (int)(reg&0xF));
+ break;
+ case X86_YMMREG:
+ fprintf(f, "ymm%d", (int)(reg&0xF));
+ break;
+ case X86_CRREG:
+ fprintf(f, "cr%d", (int)(reg&0xF));
+ break;
+ case X86_DRREG:
+ fprintf(f, "dr%d", (int)(reg&0xF));
+ break;
+ case X86_TRREG:
+ fprintf(f, "tr%d", (int)(reg&0xF));
+ break;
+ case X86_FPUREG:
+ fprintf(f, "st%d", (int)(reg&0xF));
+ break;
+ default:
+ yasm_error_set(YASM_ERROR_VALUE, N_("unknown register size"));
+ }
+}
+
+static void
+x86_segreg_print(yasm_arch *arch, uintptr_t segreg, FILE *f)
+{
+ static const char *name[] = {"es","cs","ss","ds","fs","gs"};
+ fprintf(f, "%s", name[segreg&7]);
+}
+
+/* Define x86 machines -- see arch.h for details */
+static const yasm_arch_machine x86_machines[] = {
+ { "IA-32 and derivatives", "x86" },
+ { "AMD64", "amd64" },
+ { "X32", "x32" },
+ { NULL, NULL }
+};
+
+static const yasm_directive x86_directives[] = {
+ { "cpu", "nasm", x86_dir_cpu, YASM_DIR_ARG_REQUIRED },
+ { "bits", "nasm", x86_dir_bits, YASM_DIR_ARG_REQUIRED },
+ { ".code16", "gas", x86_dir_code16, YASM_DIR_ANY },
+ { ".code32", "gas", x86_dir_code32, YASM_DIR_ANY },
+ { ".code64", "gas", x86_dir_code64, YASM_DIR_ANY },
+ { NULL, NULL, NULL, 0 }
+};
+
+/* Define arch structure -- see arch.h for details */
+yasm_arch_module yasm_x86_LTX_arch = {
+ "x86 (IA-32 and derivatives), AMD64",
+ "x86",
+ x86_directives,
+ x86_create,
+ x86_destroy,
+ x86_get_machine,
+ x86_get_address_size,
+ x86_set_var,
+ yasm_x86__parse_check_insnprefix,
+ yasm_x86__parse_check_regtmod,
+ x86_get_fill,
+ yasm_x86__floatnum_tobytes,
+ yasm_x86__intnum_tobytes,
+ x86_get_reg_size,
+ x86_reggroup_get_reg,
+ x86_reg_print,
+ x86_segreg_print,
+ yasm_x86__ea_create_expr,
+ yasm_x86__ea_destroy,
+ yasm_x86__ea_print,
+ yasm_x86__create_empty_insn,
+ x86_machines,
+ "x86",
+ 16,
+ 1
+};
diff --git a/contrib/tools/yasm/modules/arch/x86/x86arch.h b/contrib/tools/yasm/modules/arch/x86/x86arch.h
new file mode 100644
index 0000000000..78c3d73920
--- /dev/null
+++ b/contrib/tools/yasm/modules/arch/x86/x86arch.h
@@ -0,0 +1,336 @@
+/*
+ * x86 Architecture header file
+ *
+ * Copyright (C) 2001-2007 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.
+ */
+#ifndef YASM_X86ARCH_H
+#define YASM_X86ARCH_H
+
+#include <libyasm/bitvect.h>
+
+/* Available CPU feature flags */
+#define CPU_Any 0 /* Any old cpu will do */
+#define CPU_086 CPU_Any
+#define CPU_186 1 /* i186 or better required */
+#define CPU_286 2 /* i286 or better required */
+#define CPU_386 3 /* i386 or better required */
+#define CPU_486 4 /* i486 or better required */
+#define CPU_586 5 /* i585 or better required */
+#define CPU_686 6 /* i686 or better required */
+#define CPU_P3 7 /* Pentium3 or better required */
+#define CPU_P4 8 /* Pentium4 or better required */
+#define CPU_IA64 9 /* IA-64 or better required */
+#define CPU_K6 10 /* AMD K6 or better required */
+#define CPU_Athlon 11 /* AMD Athlon or better required */
+#define CPU_Hammer 12 /* AMD Sledgehammer or better required */
+#define CPU_FPU 13 /* FPU support required */
+#define CPU_MMX 14 /* MMX support required */
+#define CPU_SSE 15 /* Streaming SIMD extensions required */
+#define CPU_SSE2 16 /* Streaming SIMD extensions 2 required */
+#define CPU_SSE3 17 /* Streaming SIMD extensions 3 required */
+#define CPU_3DNow 18 /* 3DNow! support required */
+#define CPU_Cyrix 19 /* Cyrix-specific instruction */
+#define CPU_AMD 20 /* AMD-specific inst. (older than K6) */
+#define CPU_SMM 21 /* System Management Mode instruction */
+#define CPU_Prot 22 /* Protected mode only instruction */
+#define CPU_Undoc 23 /* Undocumented instruction */
+#define CPU_Obs 24 /* Obsolete instruction */
+#define CPU_Priv 25 /* Priveleged instruction */
+#define CPU_SVM 26 /* Secure Virtual Machine instruction */
+#define CPU_PadLock 27 /* VIA PadLock instruction */
+#define CPU_EM64T 28 /* Intel EM64T or better */
+#define CPU_SSSE3 29 /* Streaming SIMD extensions 3 required */
+#define CPU_SSE41 30 /* Streaming SIMD extensions 4.1 required */
+#define CPU_SSE42 31 /* Streaming SIMD extensions 4.2 required */
+#define CPU_SSE4a 32 /* AMD Streaming SIMD extensions 4a required */
+#define CPU_XSAVE 33 /* Intel XSAVE instructions */
+#define CPU_AVX 34 /* Intel Advanced Vector Extensions */
+#define CPU_FMA 35 /* Intel Fused-Multiply-Add Extensions */
+#define CPU_AES 36 /* AES instruction */
+#define CPU_CLMUL 37 /* PCLMULQDQ instruction */
+#define CPU_MOVBE 38 /* MOVBE instruction */
+#define CPU_XOP 39 /* AMD XOP extensions */
+#define CPU_FMA4 40 /* AMD Fused-Multiply-Add extensions */
+#define CPU_F16C 41 /* Intel float-16 instructions */
+#define CPU_FSGSBASE 42 /* Intel FSGSBASE instructions */
+#define CPU_RDRAND 43 /* Intel RDRAND instruction */
+#define CPU_XSAVEOPT 44 /* Intel XSAVEOPT instruction */
+#define CPU_EPTVPID 45 /* Intel INVEPT, INVVPID instructions */
+#define CPU_SMX 46 /* Intel SMX instruction (GETSEC) */
+#define CPU_AVX2 47 /* Intel AVX2 instructions */
+#define CPU_BMI1 48 /* Intel BMI1 instructions */
+#define CPU_BMI2 49 /* Intel BMI2 instructions */
+#define CPU_INVPCID 50 /* Intel INVPCID instruction */
+#define CPU_LZCNT 51 /* Intel LZCNT instruction */
+#define CPU_TBM 52 /* AMD TBM instruction */
+#define CPU_TSX 53 /* Intel TSX instructions */
+#define CPU_SHA 54 /* Intel SHA instructions */
+#define CPU_SMAP 55 /* Intel SMAP instructions */
+#define CPU_RDSEED 56 /* Intel RDSEED instruction */
+#define CPU_ADX 57 /* Intel ADCX and ADOX instructions */
+#define CPU_PRFCHW 58 /* Intel/AMD PREFETCHW instruction */
+
+enum x86_parser_type {
+ X86_PARSER_NASM = 0,
+ X86_PARSER_TASM = 1,
+ X86_PARSER_GAS = 2
+};
+
+#define PARSER(arch) (((arch)->parser == X86_PARSER_GAS && (arch)->gas_intel_mode) ? X86_PARSER_NASM : (arch)->parser)
+
+typedef struct yasm_arch_x86 {
+ yasm_arch_base arch; /* base structure */
+
+ /* What instructions/features are enabled? */
+ unsigned int active_cpu; /* active index into cpu_enables table */
+ unsigned int cpu_enables_size; /* size of cpu_enables table */
+ wordptr *cpu_enables;
+
+ unsigned int amd64_machine;
+ enum x86_parser_type parser;
+ unsigned int mode_bits;
+ unsigned int address_size;
+ unsigned int force_strict;
+ unsigned int default_rel;
+ unsigned int gas_intel_mode;
+
+ enum {
+ X86_NOP_BASIC = 0,
+ X86_NOP_INTEL = 1,
+ X86_NOP_AMD = 2
+ } nop;
+} yasm_arch_x86;
+
+/* 0-15 (low 4 bits) used for register number, stored in same data area.
+ * Note 8-15 are only valid for some registers, and only in 64-bit mode.
+ */
+typedef enum {
+ X86_REG8 = 0x1<<4,
+ X86_REG8X = 0x2<<4, /* 64-bit mode only, REX prefix version of REG8 */
+ X86_REG16 = 0x3<<4,
+ X86_REG32 = 0x4<<4,
+ X86_REG64 = 0x5<<4, /* 64-bit mode only */
+ X86_FPUREG = 0x6<<4,
+ X86_MMXREG = 0x7<<4,
+ X86_XMMREG = 0x8<<4,
+ X86_YMMREG = 0x9<<4,
+ X86_CRREG = 0xA<<4,
+ X86_DRREG = 0xB<<4,
+ X86_TRREG = 0xC<<4,
+ X86_RIP = 0xD<<4 /* 64-bit mode only, always RIP (regnum ignored) */
+} x86_expritem_reg_size;
+
+/* Low 8 bits are used for the prefix value, stored in same data area. */
+typedef enum {
+ X86_LOCKREP = 1<<8,
+ X86_ADDRSIZE = 2<<8,
+ X86_OPERSIZE = 3<<8,
+ X86_SEGREG = 4<<8,
+ X86_REX = 5<<8,
+ X86_ACQREL = 6<<8 /*TSX hint prefixes*/
+} x86_parse_insn_prefix;
+
+typedef enum {
+ X86_NEAR = 1,
+ X86_SHORT,
+ X86_FAR,
+ X86_TO
+} x86_parse_targetmod;
+
+typedef enum {
+ JMP_NONE,
+ JMP_SHORT,
+ JMP_NEAR,
+ JMP_SHORT_FORCED,
+ JMP_NEAR_FORCED
+} x86_jmp_opcode_sel;
+
+typedef enum {
+ X86_REX_W = 3,
+ X86_REX_R = 2,
+ X86_REX_X = 1,
+ X86_REX_B = 0
+} x86_rex_bit_pos;
+
+/* Sets REX (4th bit) and 3 LS bits from register size/number. Returns 1 if
+ * impossible to fit reg into REX, otherwise returns 0. Input parameter rexbit
+ * indicates bit of REX to use if REX is needed. Will not modify REX if not
+ * in 64-bit mode or if it wasn't needed to express reg.
+ */
+int yasm_x86__set_rex_from_reg(unsigned char *rex, unsigned char *low3,
+ uintptr_t reg, unsigned int bits,
+ x86_rex_bit_pos rexbit);
+
+/* Effective address type */
+typedef struct x86_effaddr {
+ yasm_effaddr ea; /* base structure */
+
+ /* VSIB uses the normal SIB byte, but this flag enables it. */
+ unsigned char vsib_mode; /* 0 if not, 1 if XMM, 2 if YMM */
+
+ /* How the spare (register) bits in Mod/RM are handled:
+ * Even if valid_modrm=0, the spare bits are still valid (don't overwrite!)
+ * They're set in bytecode_create_insn().
+ */
+ unsigned char modrm;
+ unsigned char valid_modrm; /* 1 if Mod/RM byte currently valid, 0 if not */
+ unsigned char need_modrm; /* 1 if Mod/RM byte needed, 0 if not */
+
+ unsigned char sib;
+ unsigned char valid_sib; /* 1 if SIB byte currently valid, 0 if not */
+ unsigned char need_sib; /* 1 if SIB byte needed, 0 if not,
+ 0xff if unknown */
+} x86_effaddr;
+
+void yasm_x86__ea_init(x86_effaddr *x86_ea, unsigned int spare,
+ yasm_bytecode *precbc);
+
+void yasm_x86__ea_set_disponly(x86_effaddr *x86_ea);
+x86_effaddr *yasm_x86__ea_create_reg(x86_effaddr *x86_ea, unsigned long reg,
+ unsigned char *rex, unsigned int bits);
+x86_effaddr *yasm_x86__ea_create_imm
+ (x86_effaddr *x86_ea, /*@keep@*/ yasm_expr *imm, unsigned int im_len);
+yasm_effaddr *yasm_x86__ea_create_expr(yasm_arch *arch,
+ /*@keep@*/ yasm_expr *e);
+void yasm_x86__ea_destroy(yasm_effaddr *ea);
+void yasm_x86__ea_print(const yasm_effaddr *ea, FILE *f, int indent_level);
+
+void yasm_x86__bc_insn_opersize_override(yasm_bytecode *bc,
+ unsigned int opersize);
+void yasm_x86__bc_insn_addrsize_override(yasm_bytecode *bc,
+ unsigned int addrsize);
+void yasm_x86__bc_insn_set_lockrep_prefix(yasm_bytecode *bc,
+ unsigned int prefix);
+
+/* Bytecode types */
+typedef struct x86_common {
+ unsigned char addrsize; /* 0 or =mode_bits => no override */
+ unsigned char opersize; /* 0 or =mode_bits => no override */
+ unsigned char lockrep_pre; /* 0 indicates no prefix */
+ unsigned char acqrel_pre; /* 0 indicates no prefix. We need this because
+ xqcuire/xrelease might require F0 prefix */
+
+ unsigned char mode_bits;
+} x86_common;
+
+typedef struct x86_opcode {
+ unsigned char opcode[3]; /* opcode */
+ unsigned char len;
+} x86_opcode;
+
+typedef struct x86_insn {
+ x86_common common; /* common x86 information */
+ x86_opcode opcode;
+
+ /*@null@*/ x86_effaddr *x86_ea; /* effective address */
+
+ /*@null@*/ yasm_value *imm; /* immediate or relative value */
+
+ unsigned char def_opersize_64; /* default operand size in 64-bit mode */
+ unsigned char special_prefix; /* "special" prefix (0=none) */
+
+ unsigned char rex; /* REX AMD64 extension, 0 if none,
+ 0xff if not allowed (high 8 bit reg used) */
+
+ /* Postponed (from parsing to later binding) action options. */
+ enum {
+ /* None */
+ X86_POSTOP_NONE = 0,
+
+ /* Instructions that take a sign-extended imm8 as well as imm values
+ * (eg, the arith instructions and a subset of the imul instructions)
+ * should set this and put the imm8 form as the "normal" opcode (in
+ * the first one or two bytes) and non-imm8 form in the second or
+ * third byte of the opcode.
+ */
+ X86_POSTOP_SIGNEXT_IMM8,
+
+ /* Override any attempt at address-size override to 16 bits, and never
+ * generate a prefix. This is used for the ENTER opcode.
+ */
+ X86_POSTOP_ADDRESS16
+ } postop;
+} x86_insn;
+
+typedef struct x86_jmp {
+ x86_common common; /* common x86 information */
+ x86_opcode shortop, nearop;
+
+ yasm_value target; /* jump target */
+
+ /* which opcode are we using? */
+ /* The *FORCED forms are specified in the source as such */
+ x86_jmp_opcode_sel op_sel;
+} x86_jmp;
+
+/* Direct (immediate) FAR jumps ONLY; indirect FAR jumps get turned into
+ * x86_insn bytecodes; relative jumps turn into x86_jmp bytecodes.
+ * This bytecode is not legal in 64-bit mode.
+ */
+typedef struct x86_jmpfar {
+ x86_common common; /* common x86 information */
+ x86_opcode opcode;
+
+ yasm_value segment; /* target segment */
+ yasm_value offset; /* target offset */
+} x86_jmpfar;
+
+void yasm_x86__bc_transform_insn(yasm_bytecode *bc, x86_insn *insn);
+void yasm_x86__bc_transform_jmp(yasm_bytecode *bc, x86_jmp *jmp);
+void yasm_x86__bc_transform_jmpfar(yasm_bytecode *bc, x86_jmpfar *jmpfar);
+
+void yasm_x86__bc_apply_prefixes
+ (x86_common *common, unsigned char *rex, unsigned int def_opersize_64,
+ unsigned int num_prefixes, uintptr_t *prefixes);
+
+/* Check an effective address. Returns 0 if EA was successfully determined,
+ * 1 if invalid EA, or 2 if indeterminate EA.
+ */
+int yasm_x86__expr_checkea
+ (x86_effaddr *x86_ea, unsigned char *addrsize, unsigned int bits,
+ int address16_op, unsigned char *rex, yasm_bytecode *bc);
+
+void yasm_x86__parse_cpu(yasm_arch_x86 *arch_x86, const char *cpuid,
+ size_t cpuid_len);
+
+yasm_arch_insnprefix yasm_x86__parse_check_insnprefix
+ (yasm_arch *arch, const char *id, size_t id_len, unsigned long line,
+ /*@out@*/ yasm_bytecode **bc, /*@out@*/ uintptr_t *prefix);
+yasm_arch_regtmod yasm_x86__parse_check_regtmod
+ (yasm_arch *arch, const char *id, size_t id_len,
+ /*@out@*/ uintptr_t *data);
+
+int yasm_x86__floatnum_tobytes
+ (yasm_arch *arch, const yasm_floatnum *flt, unsigned char *buf,
+ size_t destsize, size_t valsize, size_t shift, int warn);
+int yasm_x86__intnum_tobytes
+ (yasm_arch *arch, const yasm_intnum *intn, unsigned char *buf,
+ size_t destsize, size_t valsize, int shift, const yasm_bytecode *bc,
+ int warn);
+
+unsigned int yasm_x86__get_reg_size(uintptr_t reg);
+
+/*@only@*/ yasm_bytecode *yasm_x86__create_empty_insn(yasm_arch *arch,
+ unsigned long line);
+#endif
diff --git a/contrib/tools/yasm/modules/arch/x86/x86bc.c b/contrib/tools/yasm/modules/arch/x86/x86bc.c
new file mode 100644
index 0000000000..a6681552dd
--- /dev/null
+++ b/contrib/tools/yasm/modules/arch/x86/x86bc.c
@@ -0,0 +1,1062 @@
+/*
+ * x86 bytecode utility functions
+ *
+ * Copyright (C) 2001-2007 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 <util.h>
+
+#include <libyasm.h>
+
+#include "x86arch.h"
+
+
+/* Bytecode callback function prototypes */
+
+static void x86_bc_insn_destroy(void *contents);
+static void x86_bc_insn_print(const void *contents, FILE *f,
+ int indent_level);
+static int x86_bc_insn_calc_len(yasm_bytecode *bc,
+ yasm_bc_add_span_func add_span,
+ void *add_span_data);
+static int x86_bc_insn_expand(yasm_bytecode *bc, int span, long old_val,
+ long new_val, /*@out@*/ long *neg_thres,
+ /*@out@*/ long *pos_thres);
+static int x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart,
+ void *d, yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static void x86_bc_jmp_destroy(void *contents);
+static void x86_bc_jmp_print(const void *contents, FILE *f, int indent_level);
+static int x86_bc_jmp_calc_len(yasm_bytecode *bc,
+ yasm_bc_add_span_func add_span,
+ void *add_span_data);
+static int x86_bc_jmp_expand(yasm_bytecode *bc, int span, long old_val,
+ long new_val, /*@out@*/ long *neg_thres,
+ /*@out@*/ long *pos_thres);
+static int x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart,
+ void *d, yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static void x86_bc_jmpfar_destroy(void *contents);
+static void x86_bc_jmpfar_print(const void *contents, FILE *f,
+ int indent_level);
+static int x86_bc_jmpfar_calc_len(yasm_bytecode *bc,
+ yasm_bc_add_span_func add_span,
+ void *add_span_data);
+static int x86_bc_jmpfar_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+/* Bytecode callback structures */
+
+static const yasm_bytecode_callback x86_bc_callback_insn = {
+ x86_bc_insn_destroy,
+ x86_bc_insn_print,
+ yasm_bc_finalize_common,
+ NULL,
+ x86_bc_insn_calc_len,
+ x86_bc_insn_expand,
+ x86_bc_insn_tobytes,
+ 0
+};
+
+static const yasm_bytecode_callback x86_bc_callback_jmp = {
+ x86_bc_jmp_destroy,
+ x86_bc_jmp_print,
+ yasm_bc_finalize_common,
+ NULL,
+ x86_bc_jmp_calc_len,
+ x86_bc_jmp_expand,
+ x86_bc_jmp_tobytes,
+ 0
+};
+
+static const yasm_bytecode_callback x86_bc_callback_jmpfar = {
+ x86_bc_jmpfar_destroy,
+ x86_bc_jmpfar_print,
+ yasm_bc_finalize_common,
+ NULL,
+ x86_bc_jmpfar_calc_len,
+ yasm_bc_expand_common,
+ x86_bc_jmpfar_tobytes,
+ 0
+};
+
+int
+yasm_x86__set_rex_from_reg(unsigned char *rex, unsigned char *low3,
+ uintptr_t reg, unsigned int bits,
+ x86_rex_bit_pos rexbit)
+{
+ *low3 = (unsigned char)(reg&7);
+
+ if (bits == 64) {
+ x86_expritem_reg_size size = (x86_expritem_reg_size)(reg & ~0xFUL);
+
+ if (size == X86_REG8X || (reg & 0xF) >= 8) {
+ /* Check to make sure we can set it */
+ if (*rex == 0xff) {
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("cannot use A/B/C/DH with instruction needing REX"));
+ return 1;
+ }
+ *rex |= 0x40 | (((reg & 8) >> 3) << rexbit);
+ } else if (size == X86_REG8 && (reg & 7) >= 4) {
+ /* AH/BH/CH/DH, so no REX allowed */
+ if (*rex != 0 && *rex != 0xff) {
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("cannot use A/B/C/DH with instruction needing REX"));
+ return 1;
+ }
+ *rex = 0xff; /* Flag so we can NEVER set it (see above) */
+ }
+ }
+
+ return 0;
+}
+
+void
+yasm_x86__bc_transform_insn(yasm_bytecode *bc, x86_insn *insn)
+{
+ yasm_bc_transform(bc, &x86_bc_callback_insn, insn);
+}
+
+void
+yasm_x86__bc_transform_jmp(yasm_bytecode *bc, x86_jmp *jmp)
+{
+ yasm_bc_transform(bc, &x86_bc_callback_jmp, jmp);
+}
+
+void
+yasm_x86__bc_transform_jmpfar(yasm_bytecode *bc, x86_jmpfar *jmpfar)
+{
+ yasm_bc_transform(bc, &x86_bc_callback_jmpfar, jmpfar);
+}
+
+void
+yasm_x86__ea_init(x86_effaddr *x86_ea, unsigned int spare,
+ yasm_bytecode *precbc)
+{
+ if (yasm_value_finalize(&x86_ea->ea.disp, precbc))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("effective address too complex"));
+ x86_ea->modrm &= 0xC7; /* zero spare/reg bits */
+ x86_ea->modrm |= (spare << 3) & 0x38; /* plug in provided bits */
+}
+
+void
+yasm_x86__ea_set_disponly(x86_effaddr *x86_ea)
+{
+ x86_ea->valid_modrm = 0;
+ x86_ea->need_modrm = 0;
+ x86_ea->valid_sib = 0;
+ x86_ea->need_sib = 0;
+}
+
+static x86_effaddr *
+ea_create(void)
+{
+ x86_effaddr *x86_ea = yasm_xmalloc(sizeof(x86_effaddr));
+
+ yasm_value_initialize(&x86_ea->ea.disp, NULL, 0);
+ x86_ea->ea.need_nonzero_len = 0;
+ x86_ea->ea.need_disp = 0;
+ x86_ea->ea.nosplit = 0;
+ x86_ea->ea.strong = 0;
+ x86_ea->ea.segreg = 0;
+ x86_ea->ea.pc_rel = 0;
+ x86_ea->ea.not_pc_rel = 0;
+ x86_ea->ea.data_len = 0;
+ x86_ea->vsib_mode = 0;
+ x86_ea->modrm = 0;
+ x86_ea->valid_modrm = 0;
+ x86_ea->need_modrm = 0;
+ x86_ea->sib = 0;
+ x86_ea->valid_sib = 0;
+ x86_ea->need_sib = 0;
+
+ return x86_ea;
+}
+
+x86_effaddr *
+yasm_x86__ea_create_reg(x86_effaddr *x86_ea, unsigned long reg,
+ unsigned char *rex, unsigned int bits)
+{
+ unsigned char rm;
+
+ if (yasm_x86__set_rex_from_reg(rex, &rm, reg, bits, X86_REX_B))
+ return NULL;
+
+ if (!x86_ea)
+ x86_ea = ea_create();
+ x86_ea->modrm = 0xC0 | rm; /* Mod=11, R/M=Reg, Reg=0 */
+ x86_ea->valid_modrm = 1;
+ x86_ea->need_modrm = 1;
+
+ return x86_ea;
+}
+
+yasm_effaddr *
+yasm_x86__ea_create_expr(yasm_arch *arch, yasm_expr *e)
+{
+ yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
+ x86_effaddr *x86_ea;
+
+ x86_ea = ea_create();
+
+ if (arch_x86->parser == X86_PARSER_GAS) {
+ /* Need to change foo+rip into foo wrt rip (even in .intel_syntax mode).
+ * Note this assumes a particular ordering coming from the parser
+ * to work (it's not very smart)!
+ */
+ if (e->op == YASM_EXPR_ADD && e->terms[0].type == YASM_EXPR_REG
+ && e->terms[0].data.reg == X86_RIP) {
+ /* replace register with 0 */
+ e->terms[0].type = YASM_EXPR_INT;
+ e->terms[0].data.intn = yasm_intnum_create_uint(0);
+ /* build new wrt expression */
+ e = yasm_expr_create(YASM_EXPR_WRT, yasm_expr_expr(e),
+ yasm_expr_reg(X86_RIP), e->line);
+ }
+ }
+ yasm_value_initialize(&x86_ea->ea.disp, e, 0);
+ x86_ea->ea.need_disp = 1;
+ x86_ea->need_modrm = 1;
+ /* We won't know whether we need an SIB until we know more about expr and
+ * the BITS/address override setting.
+ */
+ x86_ea->need_sib = 0xff;
+
+ x86_ea->ea.data_len = 0;
+
+ return (yasm_effaddr *)x86_ea;
+}
+
+/*@-compmempass@*/
+x86_effaddr *
+yasm_x86__ea_create_imm(x86_effaddr *x86_ea, yasm_expr *imm,
+ unsigned int im_len)
+{
+ if (!x86_ea)
+ x86_ea = ea_create();
+ yasm_value_initialize(&x86_ea->ea.disp, imm, im_len);
+ x86_ea->ea.need_disp = 1;
+
+ return x86_ea;
+}
+/*@=compmempass@*/
+
+void
+yasm_x86__bc_apply_prefixes(x86_common *common, unsigned char *rex,
+ unsigned int def_opersize_64,
+ unsigned int num_prefixes, uintptr_t *prefixes)
+{
+ unsigned int i;
+ int first = 1;
+
+ for (i=0; i<num_prefixes; i++) {
+ switch ((x86_parse_insn_prefix)(prefixes[i] & 0xff00)) {
+ /*To be accurate, we should enforce that TSX hints come only with a
+ predefined set of instructions, and in most cases only with F0
+ prefix. Otherwise they will have completely different semantics.
+ But F0 prefix can come only with a predefined set of instructions
+ too. And if it comes with other instructions, CPU will #UD.
+ Hence, F0-applicability should be enforced too. But it's not
+ currently. Maybe it is the decision made, that user should know
+ himself what he is doing with LOCK prefix. In this case, we should
+ not enforce TSX hints applicability too. And let user take care of
+ correct usage of TSX hints.
+ That is what we are going to do.*/
+ case X86_ACQREL:
+ if (common->acqrel_pre != 0)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("multiple XACQUIRE/XRELEASE prefixes, "
+ "using leftmost"));
+ common->acqrel_pre = (unsigned char)prefixes[i] & 0xff;
+ break;
+ case X86_LOCKREP:
+ if (common->lockrep_pre != 0)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("multiple LOCK or REP prefixes, using leftmost"));
+ common->lockrep_pre = (unsigned char)prefixes[i] & 0xff;
+ break;
+ case X86_ADDRSIZE:
+ common->addrsize = (unsigned char)prefixes[i] & 0xff;
+ break;
+ case X86_OPERSIZE:
+ common->opersize = (unsigned char)prefixes[i] & 0xff;
+ if (common->mode_bits == 64 && common->opersize == 64 &&
+ def_opersize_64 != 64) {
+ if (!rex)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("ignoring REX prefix on jump"));
+ else if (*rex == 0xff)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("REX prefix not allowed on this instruction, ignoring"));
+ else
+ *rex = 0x48;
+ }
+ break;
+ case X86_SEGREG:
+ /* This is a hack.. we should really be putting this in the
+ * the effective address!
+ */
+ common->lockrep_pre = (unsigned char)prefixes[i] & 0xff;
+ break;
+ case X86_REX:
+ if (!rex)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("ignoring REX prefix on jump"));
+ else if (*rex == 0xff)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("REX prefix not allowed on this instruction, ignoring"));
+ else {
+ if (*rex != 0) {
+ if (first)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("overriding generated REX prefix"));
+ else
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("multiple REX prefixes, using leftmost"));
+ }
+ /* Here we assume that we can't get this prefix in non
+ * 64 bit mode due to checks in parse_check_prefix().
+ */
+ common->mode_bits = 64;
+ *rex = (unsigned char)prefixes[i] & 0xff;
+ }
+ first = 0;
+ break;
+ }
+ }
+}
+
+static void
+x86_bc_insn_destroy(void *contents)
+{
+ x86_insn *insn = (x86_insn *)contents;
+ if (insn->x86_ea)
+ yasm_x86__ea_destroy((yasm_effaddr *)insn->x86_ea);
+ if (insn->imm) {
+ yasm_value_delete(insn->imm);
+ yasm_xfree(insn->imm);
+ }
+ yasm_xfree(contents);
+}
+
+static void
+x86_bc_jmp_destroy(void *contents)
+{
+ x86_jmp *jmp = (x86_jmp *)contents;
+ yasm_value_delete(&jmp->target);
+ yasm_xfree(contents);
+}
+
+static void
+x86_bc_jmpfar_destroy(void *contents)
+{
+ x86_jmpfar *jmpfar = (x86_jmpfar *)contents;
+ yasm_value_delete(&jmpfar->segment);
+ yasm_value_delete(&jmpfar->offset);
+ yasm_xfree(contents);
+}
+
+void
+yasm_x86__ea_destroy(yasm_effaddr *ea)
+{
+ yasm_value_delete(&ea->disp);
+ yasm_xfree(ea);
+}
+
+void
+yasm_x86__ea_print(const yasm_effaddr *ea, FILE *f, int indent_level)
+{
+ const x86_effaddr *x86_ea = (const x86_effaddr *)ea;
+ fprintf(f, "%*sDisp:\n", indent_level, "");
+ yasm_value_print(&ea->disp, f, indent_level+1);
+ fprintf(f, "%*sNoSplit=%u\n", indent_level, "", (unsigned int)ea->nosplit);
+ fprintf(f, "%*sSegmentOv=%02x\n", indent_level, "",
+ (unsigned int)x86_ea->ea.segreg);
+ fprintf(f, "%*sVSIBMode=%u\n", indent_level, "",
+ (unsigned int)x86_ea->vsib_mode);
+ fprintf(f, "%*sModRM=%03o ValidRM=%u NeedRM=%u\n", indent_level, "",
+ (unsigned int)x86_ea->modrm, (unsigned int)x86_ea->valid_modrm,
+ (unsigned int)x86_ea->need_modrm);
+ fprintf(f, "%*sSIB=%03o ValidSIB=%u NeedSIB=%u\n", indent_level, "",
+ (unsigned int)x86_ea->sib, (unsigned int)x86_ea->valid_sib,
+ (unsigned int)x86_ea->need_sib);
+}
+
+static void
+x86_common_print(const x86_common *common, FILE *f, int indent_level)
+{
+ fprintf(f, "%*sAddrSize=%u OperSize=%u LockRepPre=%02x "
+ "ACQREL_Pre=%02x BITS=%u\n",
+ indent_level, "",
+ (unsigned int)common->addrsize,
+ (unsigned int)common->opersize,
+ (unsigned int)common->lockrep_pre,
+ (unsigned int)common->acqrel_pre,
+ (unsigned int)common->mode_bits);
+}
+
+static void
+x86_opcode_print(const x86_opcode *opcode, FILE *f, int indent_level)
+{
+ fprintf(f, "%*sOpcode: %02x %02x %02x OpLen=%u\n", indent_level, "",
+ (unsigned int)opcode->opcode[0],
+ (unsigned int)opcode->opcode[1],
+ (unsigned int)opcode->opcode[2],
+ (unsigned int)opcode->len);
+}
+
+static void
+x86_bc_insn_print(const void *contents, FILE *f, int indent_level)
+{
+ const x86_insn *insn = (const x86_insn *)contents;
+
+ fprintf(f, "%*s_Instruction_\n", indent_level, "");
+ fprintf(f, "%*sEffective Address:", indent_level, "");
+ if (insn->x86_ea) {
+ fprintf(f, "\n");
+ yasm_x86__ea_print((yasm_effaddr *)insn->x86_ea, f, indent_level+1);
+ } else
+ fprintf(f, " (nil)\n");
+ fprintf(f, "%*sImmediate Value:", indent_level, "");
+ if (!insn->imm)
+ fprintf(f, " (nil)\n");
+ else {
+ indent_level++;
+ fprintf(f, "\n");
+ yasm_value_print(insn->imm, f, indent_level);
+ indent_level--;
+ }
+ x86_opcode_print(&insn->opcode, f, indent_level);
+ x86_common_print(&insn->common, f, indent_level);
+ fprintf(f, "%*sSpPre=%02x REX=%03o PostOp=%u\n", indent_level, "",
+ (unsigned int)insn->special_prefix,
+ (unsigned int)insn->rex,
+ (unsigned int)insn->postop);
+}
+
+static void
+x86_bc_jmp_print(const void *contents, FILE *f, int indent_level)
+{
+ const x86_jmp *jmp = (const x86_jmp *)contents;
+
+ fprintf(f, "%*s_Jump_\n", indent_level, "");
+ fprintf(f, "%*sTarget:\n", indent_level, "");
+ yasm_value_print(&jmp->target, f, indent_level+1);
+ /* FIXME
+ fprintf(f, "%*sOrigin=\n", indent_level, "");
+ yasm_symrec_print(jmp->origin, f, indent_level+1);
+ */
+ fprintf(f, "\n%*sShort Form:\n", indent_level, "");
+ if (jmp->shortop.len == 0)
+ fprintf(f, "%*sNone\n", indent_level+1, "");
+ else
+ x86_opcode_print(&jmp->shortop, f, indent_level+1);
+ fprintf(f, "%*sNear Form:\n", indent_level, "");
+ if (jmp->nearop.len == 0)
+ fprintf(f, "%*sNone\n", indent_level+1, "");
+ else
+ x86_opcode_print(&jmp->nearop, f, indent_level+1);
+ fprintf(f, "%*sOpSel=", indent_level, "");
+ switch (jmp->op_sel) {
+ case JMP_NONE:
+ fprintf(f, "None");
+ break;
+ case JMP_SHORT:
+ fprintf(f, "Short");
+ break;
+ case JMP_NEAR:
+ fprintf(f, "Near");
+ break;
+ case JMP_SHORT_FORCED:
+ fprintf(f, "Forced Short");
+ break;
+ case JMP_NEAR_FORCED:
+ fprintf(f, "Forced Near");
+ break;
+ default:
+ fprintf(f, "UNKNOWN!!");
+ break;
+ }
+ x86_common_print(&jmp->common, f, indent_level);
+}
+
+static void
+x86_bc_jmpfar_print(const void *contents, FILE *f, int indent_level)
+{
+ const x86_jmpfar *jmpfar = (const x86_jmpfar *)contents;
+
+ fprintf(f, "%*s_Far_Jump_\n", indent_level, "");
+ fprintf(f, "%*sSegment:\n", indent_level, "");
+ yasm_value_print(&jmpfar->segment, f, indent_level+1);
+ fprintf(f, "%*sOffset:\n", indent_level, "");
+ yasm_value_print(&jmpfar->offset, f, indent_level+1);
+ x86_opcode_print(&jmpfar->opcode, f, indent_level);
+ x86_common_print(&jmpfar->common, f, indent_level);
+}
+
+static unsigned int
+x86_common_calc_len(const x86_common *common)
+{
+ unsigned int len = 0;
+
+ if (common->addrsize != 0 && common->addrsize != common->mode_bits)
+ len++;
+ if (common->opersize != 0 &&
+ ((common->mode_bits != 64 && common->opersize != common->mode_bits) ||
+ (common->mode_bits == 64 && common->opersize == 16)))
+ len++;
+ if (common->lockrep_pre != 0)
+ len++;
+ if (common->acqrel_pre != 0)
+ len++;
+
+
+ return len;
+}
+
+static int
+x86_bc_insn_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ x86_insn *insn = (x86_insn *)bc->contents;
+ x86_effaddr *x86_ea = insn->x86_ea;
+ yasm_value *imm = insn->imm;
+
+ if (x86_ea) {
+ /* Check validity of effective address and calc R/M bits of
+ * Mod/RM byte and SIB byte. We won't know the Mod field
+ * of the Mod/RM byte until we know more about the
+ * displacement.
+ */
+ if (yasm_x86__expr_checkea(x86_ea, &insn->common.addrsize,
+ insn->common.mode_bits, insn->postop == X86_POSTOP_ADDRESS16,
+ &insn->rex, bc))
+ /* failed, don't bother checking rest of insn */
+ return -1;
+
+ if (x86_ea->ea.disp.size == 0 && x86_ea->ea.need_nonzero_len) {
+ /* Handle unknown case, default to byte-sized and set as
+ * critical expression.
+ */
+ x86_ea->ea.disp.size = 8;
+ add_span(add_span_data, bc, 1, &x86_ea->ea.disp, -128, 127);
+ }
+ bc->len += x86_ea->ea.disp.size/8;
+
+ /* Handle address16 postop case */
+ if (insn->postop == X86_POSTOP_ADDRESS16)
+ insn->common.addrsize = 0;
+
+ /* Compute length of ea and add to total */
+ bc->len += x86_ea->need_modrm + (x86_ea->need_sib ? 1:0);
+ bc->len += (x86_ea->ea.segreg != 0) ? 1 : 0;
+ }
+
+ if (imm) {
+ unsigned int immlen = imm->size;
+
+ /* TODO: check imm->len vs. sized len from expr? */
+
+ /* Handle signext_imm8 postop special-casing */
+ if (insn->postop == X86_POSTOP_SIGNEXT_IMM8) {
+ /*@null@*/ /*@only@*/ yasm_intnum *num;
+ num = yasm_value_get_intnum(imm, NULL, 0);
+
+ if (!num) {
+ /* Unknown; default to byte form and set as critical
+ * expression.
+ */
+ immlen = 8;
+ add_span(add_span_data, bc, 2, imm, -128, 127);
+ } else {
+ if (yasm_intnum_in_range(num, -128, 127)) {
+ /* We can use the sign-extended byte form: shorten
+ * the immediate length to 1 and make the byte form
+ * permanent.
+ */
+ imm->size = 8;
+ imm->sign = 1;
+ immlen = 8;
+ } else {
+ /* We can't. Copy over the word-sized opcode. */
+ insn->opcode.opcode[0] =
+ insn->opcode.opcode[insn->opcode.len];
+ insn->opcode.len = 1;
+ }
+ insn->postop = X86_POSTOP_NONE;
+ yasm_intnum_destroy(num);
+ }
+ }
+
+ bc->len += immlen/8;
+ }
+
+ /* VEX and XOP prefixes never have REX (it's embedded in the opcode).
+ * For VEX, we can come into this function with the three byte form,
+ * so we need to see if we can optimize to the two byte form.
+ * We can't do it earlier, as we don't know all of the REX byte until now.
+ */
+ if (insn->special_prefix == 0xC4) {
+ /* See if we can shorten the VEX prefix to its two byte form.
+ * In order to do this, REX.X, REX.B, and REX.W/VEX.W must all be 0,
+ * and the VEX mmmmm field must be 1.
+ */
+ if ((insn->opcode.opcode[0] & 0x1F) == 1 &&
+ (insn->opcode.opcode[1] & 0x80) == 0 &&
+ (insn->rex == 0xff || (insn->rex & 0x0B) == 0)) {
+ insn->opcode.opcode[0] = insn->opcode.opcode[1];
+ insn->opcode.opcode[1] = insn->opcode.opcode[2];
+ insn->opcode.opcode[2] = 0; /* sanity */
+ insn->opcode.len = 2;
+ insn->special_prefix = 0xC5; /* mark as two-byte VEX */
+ }
+ } else if (insn->rex != 0xff && insn->rex != 0 &&
+ insn->special_prefix != 0xC5 && insn->special_prefix != 0x8F)
+ bc->len++;
+
+ bc->len += insn->opcode.len;
+ bc->len += x86_common_calc_len(&insn->common);
+ bc->len += (insn->special_prefix != 0) ? 1:0;
+ return 0;
+}
+
+static int
+x86_bc_insn_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
+{
+ x86_insn *insn = (x86_insn *)bc->contents;
+ x86_effaddr *x86_ea = insn->x86_ea;
+ yasm_effaddr *ea = &x86_ea->ea;
+ yasm_value *imm = insn->imm;
+
+ if (ea && span == 1) {
+ /* Change displacement length into word-sized */
+ if (ea->disp.size == 8) {
+ ea->disp.size = (insn->common.addrsize == 16) ? 16 : 32;
+ x86_ea->modrm &= ~0300;
+ x86_ea->modrm |= 0200;
+ bc->len--;
+ bc->len += ea->disp.size/8;
+ }
+ }
+
+ if (imm && span == 2) {
+ if (insn->postop == X86_POSTOP_SIGNEXT_IMM8) {
+ /* Update bc->len for new opcode and immediate size */
+ bc->len -= insn->opcode.len;
+ bc->len += imm->size/8;
+
+ /* Change to the word-sized opcode */
+ insn->opcode.opcode[0] = insn->opcode.opcode[insn->opcode.len];
+ insn->opcode.len = 1;
+ insn->postop = X86_POSTOP_NONE;
+ }
+ }
+
+ return 0;
+}
+
+static int
+x86_bc_jmp_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ x86_jmp *jmp = (x86_jmp *)bc->contents;
+ yasm_bytecode *target_prevbc;
+ unsigned char opersize;
+
+ /* As opersize may be 0, figure out its "real" value. */
+ opersize = (jmp->common.opersize == 0) ?
+ jmp->common.mode_bits : jmp->common.opersize;
+
+ bc->len += x86_common_calc_len(&jmp->common);
+
+ if (jmp->op_sel == JMP_NEAR_FORCED || jmp->shortop.len == 0) {
+ if (jmp->nearop.len == 0) {
+ yasm_error_set(YASM_ERROR_TYPE, N_("near jump does not exist"));
+ return -1;
+ }
+
+ /* Near jump, no spans needed */
+ if (jmp->shortop.len == 0)
+ jmp->op_sel = JMP_NEAR;
+ bc->len += jmp->nearop.len;
+ bc->len += (opersize == 16) ? 2 : 4;
+ return 0;
+ }
+
+ if (jmp->op_sel == JMP_SHORT_FORCED || jmp->nearop.len == 0) {
+ if (jmp->shortop.len == 0) {
+ yasm_error_set(YASM_ERROR_TYPE, N_("short jump does not exist"));
+ return -1;
+ }
+
+ /* We want to be sure to error if we exceed short length, so
+ * put it in as a dependent expression (falling through).
+ */
+ }
+
+ if (jmp->target.rel
+ && (!yasm_symrec_get_label(jmp->target.rel, &target_prevbc)
+ || target_prevbc->section != bc->section)) {
+ /* External or out of segment, so we can't check distance.
+ * Allowing short jumps depends on the objfmt supporting
+ * 8-bit relocs. While most don't, some might, so allow it here.
+ * Otherwise default to word-sized.
+ * The objfmt will error if not supported.
+ */
+ if (jmp->op_sel == JMP_SHORT_FORCED || jmp->nearop.len == 0) {
+ if (jmp->op_sel == JMP_NONE)
+ jmp->op_sel = JMP_SHORT;
+ bc->len += jmp->shortop.len + 1;
+ } else {
+ jmp->op_sel = JMP_NEAR;
+ bc->len += jmp->nearop.len;
+ bc->len += (opersize == 16) ? 2 : 4;
+ }
+ return 0;
+ }
+
+ /* Default to short jump and generate span */
+ if (jmp->op_sel == JMP_NONE)
+ jmp->op_sel = JMP_SHORT;
+ bc->len += jmp->shortop.len + 1;
+ add_span(add_span_data, bc, 1, &jmp->target, -128+(long)bc->len,
+ 127+(long)bc->len);
+ return 0;
+}
+
+static int
+x86_bc_jmp_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
+{
+ x86_jmp *jmp = (x86_jmp *)bc->contents;
+ unsigned char opersize;
+
+ if (span != 1)
+ yasm_internal_error(N_("unrecognized span id"));
+
+ /* As opersize may be 0, figure out its "real" value. */
+ opersize = (jmp->common.opersize == 0) ?
+ jmp->common.mode_bits : jmp->common.opersize;
+
+ if (jmp->op_sel == JMP_SHORT_FORCED || jmp->nearop.len == 0) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("short jump out of range"));
+ return -1;
+ }
+
+ if (jmp->op_sel == JMP_NEAR)
+ yasm_internal_error(N_("trying to expand an already-near jump"));
+
+ /* Upgrade to a near jump */
+ jmp->op_sel = JMP_NEAR;
+ bc->len -= jmp->shortop.len + 1;
+ bc->len += jmp->nearop.len;
+ bc->len += (opersize == 16) ? 2 : 4;
+
+ return 0;
+}
+
+static int
+x86_bc_jmpfar_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ x86_jmpfar *jmpfar = (x86_jmpfar *)bc->contents;
+ unsigned char opersize;
+
+ opersize = (jmpfar->common.opersize == 0) ?
+ jmpfar->common.mode_bits : jmpfar->common.opersize;
+
+ bc->len += jmpfar->opcode.len;
+ bc->len += 2; /* segment */
+ bc->len += (opersize == 16) ? 2 : 4;
+ bc->len += x86_common_calc_len(&jmpfar->common);
+
+ return 0;
+}
+
+static void
+x86_common_tobytes(const x86_common *common, unsigned char **bufp,
+ unsigned int segreg)
+{
+ if (segreg != 0)
+ YASM_WRITE_8(*bufp, (unsigned char)segreg);
+ if (common->addrsize != 0 && common->addrsize != common->mode_bits)
+ YASM_WRITE_8(*bufp, 0x67);
+ if (common->opersize != 0 &&
+ ((common->mode_bits != 64 && common->opersize != common->mode_bits) ||
+ (common->mode_bits == 64 && common->opersize == 16)))
+ YASM_WRITE_8(*bufp, 0x66);
+ /*TSX hints come before lock prefix*/
+ if (common->acqrel_pre != 0)
+ YASM_WRITE_8(*bufp, common->acqrel_pre);
+ if (common->lockrep_pre != 0)
+ YASM_WRITE_8(*bufp, common->lockrep_pre);
+}
+
+static void
+x86_opcode_tobytes(const x86_opcode *opcode, unsigned char **bufp)
+{
+ unsigned int i;
+ for (i=0; i<opcode->len; i++)
+ YASM_WRITE_8(*bufp, opcode->opcode[i]);
+}
+
+static int
+x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ x86_insn *insn = (x86_insn *)bc->contents;
+ /*@null@*/ x86_effaddr *x86_ea = (x86_effaddr *)insn->x86_ea;
+ yasm_value *imm = insn->imm;
+
+ /* Prefixes */
+ x86_common_tobytes(&insn->common, bufp,
+ x86_ea ? (unsigned int)(x86_ea->ea.segreg>>8) : 0);
+ if (insn->special_prefix != 0)
+ YASM_WRITE_8(*bufp, insn->special_prefix);
+ if (insn->special_prefix == 0xC4 || insn->special_prefix == 0x8F) {
+ /* 3-byte VEX/XOP; merge in 1s complement of REX.R, REX.X, REX.B */
+ insn->opcode.opcode[0] &= 0x1F;
+ if (insn->rex != 0xff)
+ insn->opcode.opcode[0] |= ((~insn->rex) & 0x07) << 5;
+ /* merge REX.W via ORing; there should never be a case in which REX.W
+ * is important when VEX.W is already set by the instruction.
+ */
+ if (insn->rex != 0xff && (insn->rex & 0x8) != 0)
+ insn->opcode.opcode[1] |= 0x80;
+ } else if (insn->special_prefix == 0xC5) {
+ /* 2-byte VEX; merge in 1s complement of REX.R */
+ insn->opcode.opcode[0] &= 0x7F;
+ if (insn->rex != 0xff && (insn->rex & 0x4) == 0)
+ insn->opcode.opcode[0] |= 0x80;
+ /* No other REX bits should be set */
+ if (insn->rex != 0xff && (insn->rex & 0xB) != 0)
+ yasm_internal_error(N_("x86: REX.WXB set, but 2-byte VEX"));
+ } else if (insn->rex != 0xff && insn->rex != 0) {
+ if (insn->common.mode_bits != 64)
+ yasm_internal_error(N_("x86: got a REX prefix in non-64-bit mode"));
+ YASM_WRITE_8(*bufp, insn->rex);
+ }
+
+ /* Opcode */
+ x86_opcode_tobytes(&insn->opcode, bufp);
+
+ /* Effective address: ModR/M (if required), SIB (if required), and
+ * displacement (if required).
+ */
+ if (x86_ea) {
+ if (x86_ea->need_modrm) {
+ if (!x86_ea->valid_modrm)
+ yasm_internal_error(N_("invalid Mod/RM in x86 tobytes_insn"));
+ YASM_WRITE_8(*bufp, x86_ea->modrm);
+ }
+
+ if (x86_ea->need_sib) {
+ if (!x86_ea->valid_sib)
+ yasm_internal_error(N_("invalid SIB in x86 tobytes_insn"));
+ YASM_WRITE_8(*bufp, x86_ea->sib);
+ }
+
+ if (x86_ea->ea.need_disp) {
+ unsigned int disp_len = x86_ea->ea.disp.size/8;
+
+ if (x86_ea->ea.disp.ip_rel) {
+ /* Adjust relative displacement to end of bytecode */
+ /*@only@*/ yasm_intnum *delta;
+ delta = yasm_intnum_create_int(-(long)bc->len);
+ if (!x86_ea->ea.disp.abs)
+ x86_ea->ea.disp.abs =
+ yasm_expr_create_ident(yasm_expr_int(delta), bc->line);
+ else
+ x86_ea->ea.disp.abs =
+ yasm_expr_create(YASM_EXPR_ADD,
+ yasm_expr_expr(x86_ea->ea.disp.abs),
+ yasm_expr_int(delta), bc->line);
+ }
+ if (output_value(&x86_ea->ea.disp, *bufp, disp_len,
+ (unsigned long)(*bufp-bufstart), bc, 1, d))
+ return 1;
+ *bufp += disp_len;
+ }
+ }
+
+ /* Immediate (if required) */
+ if (imm) {
+ unsigned int imm_len;
+ if (insn->postop == X86_POSTOP_SIGNEXT_IMM8) {
+ /* If we got here with this postop still set, we need to force
+ * imm size to 8 here.
+ */
+ imm->size = 8;
+ imm->sign = 1;
+ imm_len = 1;
+ } else
+ imm_len = imm->size/8;
+ if (output_value(imm, *bufp, imm_len, (unsigned long)(*bufp-bufstart),
+ bc, 1, d))
+ return 1;
+ *bufp += imm_len;
+ }
+
+ return 0;
+}
+
+static int
+x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ x86_jmp *jmp = (x86_jmp *)bc->contents;
+ unsigned char opersize;
+ unsigned int i;
+ /*@only@*/ yasm_intnum *delta;
+
+ /* Prefixes */
+ x86_common_tobytes(&jmp->common, bufp, 0);
+
+ /* As opersize may be 0, figure out its "real" value. */
+ opersize = (jmp->common.opersize == 0) ?
+ jmp->common.mode_bits : jmp->common.opersize;
+
+ /* Check here again to see if forms are actually legal. */
+ switch (jmp->op_sel) {
+ case JMP_SHORT_FORCED:
+ case JMP_SHORT:
+ /* 1 byte relative displacement */
+ if (jmp->shortop.len == 0)
+ yasm_internal_error(N_("short jump does not exist"));
+
+ /* Opcode */
+ x86_opcode_tobytes(&jmp->shortop, bufp);
+
+ /* Adjust relative displacement to end of bytecode */
+ delta = yasm_intnum_create_int(-(long)bc->len);
+ if (!jmp->target.abs)
+ jmp->target.abs = yasm_expr_create_ident(yasm_expr_int(delta),
+ bc->line);
+ else
+ jmp->target.abs =
+ yasm_expr_create(YASM_EXPR_ADD,
+ yasm_expr_expr(jmp->target.abs),
+ yasm_expr_int(delta), bc->line);
+
+ jmp->target.size = 8;
+ jmp->target.sign = 1;
+ if (output_value(&jmp->target, *bufp, 1,
+ (unsigned long)(*bufp-bufstart), bc, 1, d))
+ return 1;
+ *bufp += 1;
+ break;
+ case JMP_NEAR_FORCED:
+ case JMP_NEAR:
+ /* 2/4 byte relative displacement (depending on operand size) */
+ if (jmp->nearop.len == 0) {
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("near jump does not exist"));
+ return 1;
+ }
+
+ /* Opcode */
+ x86_opcode_tobytes(&jmp->nearop, bufp);
+
+ i = (opersize == 16) ? 2 : 4;
+
+ /* Adjust relative displacement to end of bytecode */
+ delta = yasm_intnum_create_int(-(long)bc->len);
+ if (!jmp->target.abs)
+ jmp->target.abs = yasm_expr_create_ident(yasm_expr_int(delta),
+ bc->line);
+ else
+ jmp->target.abs =
+ yasm_expr_create(YASM_EXPR_ADD,
+ yasm_expr_expr(jmp->target.abs),
+ yasm_expr_int(delta), bc->line);
+
+ jmp->target.size = i*8;
+ jmp->target.sign = 1;
+ if (output_value(&jmp->target, *bufp, i,
+ (unsigned long)(*bufp-bufstart), bc, 1, d))
+ return 1;
+ *bufp += i;
+ break;
+ case JMP_NONE:
+ yasm_internal_error(N_("jump op_sel cannot be JMP_NONE in tobytes"));
+ default:
+ yasm_internal_error(N_("unrecognized relative jump op_sel"));
+ }
+ return 0;
+}
+
+static int
+x86_bc_jmpfar_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@unused@*/ yasm_output_reloc_func output_reloc)
+{
+ x86_jmpfar *jmpfar = (x86_jmpfar *)bc->contents;
+ unsigned int i;
+ unsigned char opersize;
+
+ x86_common_tobytes(&jmpfar->common, bufp, 0);
+ x86_opcode_tobytes(&jmpfar->opcode, bufp);
+
+ /* As opersize may be 0, figure out its "real" value. */
+ opersize = (jmpfar->common.opersize == 0) ?
+ jmpfar->common.mode_bits : jmpfar->common.opersize;
+
+ /* Absolute displacement: segment and offset */
+ i = (opersize == 16) ? 2 : 4;
+ jmpfar->offset.size = i*8;
+ if (output_value(&jmpfar->offset, *bufp, i,
+ (unsigned long)(*bufp-bufstart), bc, 1, d))
+ return 1;
+ *bufp += i;
+ jmpfar->segment.size = 16;
+ if (output_value(&jmpfar->segment, *bufp, 2,
+ (unsigned long)(*bufp-bufstart), bc, 1, d))
+ return 1;
+ *bufp += 2;
+
+ return 0;
+}
+
+int
+yasm_x86__intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn,
+ unsigned char *buf, size_t destsize, size_t valsize,
+ int shift, const yasm_bytecode *bc, int warn)
+{
+ /* Write value out. */
+ yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn);
+ return 0;
+}
diff --git a/contrib/tools/yasm/modules/arch/x86/x86expr.c b/contrib/tools/yasm/modules/arch/x86/x86expr.c
new file mode 100644
index 0000000000..e9ddcce57e
--- /dev/null
+++ b/contrib/tools/yasm/modules/arch/x86/x86expr.c
@@ -0,0 +1,1061 @@
+/*
+ * x86 expression handling
+ *
+ * Copyright (C) 2001-2007 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 <util.h>
+
+#include <libyasm.h>
+
+#include "x86arch.h"
+
+
+typedef struct x86_checkea_reg3264_data {
+ int *regs; /* total multiplier for each reg */
+ unsigned char vsib_mode;
+ unsigned char bits;
+ unsigned char addrsize;
+} x86_checkea_reg3264_data;
+
+/* Only works if ei->type == EXPR_REG (doesn't check).
+ * Overwrites ei with intnum of 0 (to eliminate regs from the final expr).
+ */
+static /*@null@*/ /*@dependent@*/ int *
+x86_expr_checkea_get_reg3264(yasm_expr__item *ei, int *regnum,
+ /*returned*/ void *d)
+{
+ x86_checkea_reg3264_data *data = d;
+
+ switch ((x86_expritem_reg_size)(ei->data.reg & ~0xFUL)) {
+ case X86_REG32:
+ if (data->addrsize != 32)
+ return 0;
+ *regnum = (unsigned int)(ei->data.reg & 0xF);
+ break;
+ case X86_REG64:
+ if (data->addrsize != 64)
+ return 0;
+ *regnum = (unsigned int)(ei->data.reg & 0xF);
+ break;
+ case X86_XMMREG:
+ if (data->vsib_mode != 1)
+ return 0;
+ if (data->bits != 64 && (ei->data.reg & 0x8) == 0x8)
+ return 0;
+ *regnum = 17+(unsigned int)(ei->data.reg & 0xF);
+ break;
+ case X86_YMMREG:
+ if (data->vsib_mode != 2)
+ return 0;
+ if (data->bits != 64 && (ei->data.reg & 0x8) == 0x8)
+ return 0;
+ *regnum = 17+(unsigned int)(ei->data.reg & 0xF);
+ break;
+ case X86_RIP:
+ if (data->bits != 64)
+ return 0;
+ *regnum = 16;
+ break;
+ default:
+ return 0;
+ }
+
+ /* overwrite with 0 to eliminate register from displacement expr */
+ ei->type = YASM_EXPR_INT;
+ ei->data.intn = yasm_intnum_create_uint(0);
+
+ /* we're okay */
+ return &data->regs[*regnum];
+}
+
+typedef struct x86_checkea_reg16_data {
+ int bx, si, di, bp; /* total multiplier for each reg */
+} x86_checkea_reg16_data;
+
+/* Only works if ei->type == EXPR_REG (doesn't check).
+ * Overwrites ei with intnum of 0 (to eliminate regs from the final expr).
+ */
+static /*@null@*/ int *
+x86_expr_checkea_get_reg16(yasm_expr__item *ei, int *regnum, void *d)
+{
+ x86_checkea_reg16_data *data = d;
+ /* in order: ax,cx,dx,bx,sp,bp,si,di */
+ /*@-nullassign@*/
+ static int *reg16[8] = {0,0,0,0,0,0,0,0};
+ /*@=nullassign@*/
+
+ reg16[3] = &data->bx;
+ reg16[5] = &data->bp;
+ reg16[6] = &data->si;
+ reg16[7] = &data->di;
+
+ /* don't allow 32-bit registers */
+ if ((ei->data.reg & ~0xFUL) != X86_REG16)
+ return 0;
+
+ /* & 7 for sanity check */
+ *regnum = (unsigned int)(ei->data.reg & 0x7);
+
+ /* only allow BX, SI, DI, BP */
+ if (!reg16[*regnum])
+ return 0;
+
+ /* overwrite with 0 to eliminate register from displacement expr */
+ ei->type = YASM_EXPR_INT;
+ ei->data.intn = yasm_intnum_create_uint(0);
+
+ /* we're okay */
+ return reg16[*regnum];
+}
+
+/* Distribute over registers to help bring them to the topmost level of e.
+ * Also check for illegal operations against registers.
+ * Returns 0 if something was illegal, 1 if legal and nothing in e changed,
+ * and 2 if legal and e needs to be simplified.
+ *
+ * Only half joking: Someday make this/checkea able to accept crazy things
+ * like: (bx+di)*(bx+di)-bx*bx-2*bx*di-di*di+di? Probably not: NASM never
+ * accepted such things, and it's doubtful such an expn is valid anyway
+ * (even though the above one is). But even macros would be hard-pressed
+ * to generate something like this.
+ *
+ * e must already have been simplified for this function to work properly
+ * (as it doesn't think things like SUB are valid).
+ *
+ * IMPLEMENTATION NOTE: About the only thing this function really needs to
+ * "distribute" is: (non-float-expn or intnum) * (sum expn of registers).
+ *
+ * TODO: Clean up this code, make it easier to understand.
+ */
+static int
+x86_expr_checkea_distcheck_reg(yasm_expr **ep, unsigned int bits)
+{
+ yasm_expr *e = *ep;
+ int i;
+ int havereg = -1, havereg_expr = -1;
+ int retval = 1; /* default to legal, no changes */
+
+ for (i=0; i<e->numterms; i++) {
+ switch (e->terms[i].type) {
+ case YASM_EXPR_REG:
+ /* Check op to make sure it's valid to use w/register. */
+ switch (e->op) {
+ case YASM_EXPR_MUL:
+ /* Check for reg*reg */
+ if (havereg != -1)
+ return 0;
+ break;
+ case YASM_EXPR_ADD:
+ case YASM_EXPR_IDENT:
+ break;
+ default:
+ return 0;
+ }
+ havereg = i;
+ break;
+ case YASM_EXPR_FLOAT:
+ /* Floats not allowed. */
+ return 0;
+ case YASM_EXPR_EXPR:
+ if (yasm_expr__contains(e->terms[i].data.expn,
+ YASM_EXPR_REG)) {
+ int ret2;
+
+ /* Check op to make sure it's valid to use w/register. */
+ if (e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_MUL)
+ return 0;
+ /* Check for reg*reg */
+ if (e->op == YASM_EXPR_MUL && havereg != -1)
+ return 0;
+ havereg = i;
+ havereg_expr = i;
+ /* Recurse to check lower levels */
+ ret2 =
+ x86_expr_checkea_distcheck_reg(&e->terms[i].data.expn,
+ bits);
+ if (ret2 == 0)
+ return 0;
+ if (ret2 == 2)
+ retval = 2;
+ } else if (yasm_expr__contains(e->terms[i].data.expn,
+ YASM_EXPR_FLOAT))
+ return 0; /* Disallow floats */
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* just exit if no registers were used */
+ if (havereg == -1)
+ return retval;
+
+ /* Distribute */
+ if (e->op == YASM_EXPR_MUL && havereg_expr != -1) {
+ yasm_expr *ne;
+
+ retval = 2; /* we're going to change it */
+
+ /* The reg expn *must* be EXPR_ADD at this point. Sanity check. */
+ if (e->terms[havereg_expr].type != YASM_EXPR_EXPR ||
+ e->terms[havereg_expr].data.expn->op != YASM_EXPR_ADD)
+ yasm_internal_error(N_("Register expression not ADD or EXPN"));
+
+ /* Iterate over each term in reg expn */
+ for (i=0; i<e->terms[havereg_expr].data.expn->numterms; i++) {
+ /* Copy everything EXCEPT havereg_expr term into new expression */
+ ne = yasm_expr__copy_except(e, havereg_expr);
+ assert(ne != NULL);
+ /* Copy reg expr term into uncopied (empty) term in new expn */
+ ne->terms[havereg_expr] =
+ e->terms[havereg_expr].data.expn->terms[i]; /* struct copy */
+ /* Overwrite old reg expr term with new expn */
+ e->terms[havereg_expr].data.expn->terms[i].type = YASM_EXPR_EXPR;
+ e->terms[havereg_expr].data.expn->terms[i].data.expn = ne;
+ }
+
+ /* Replace e with expanded reg expn */
+ ne = e->terms[havereg_expr].data.expn;
+ e->terms[havereg_expr].type = YASM_EXPR_NONE; /* don't delete it! */
+ yasm_expr_destroy(e); /* but everything else */
+ e = ne;
+ /*@-onlytrans@*/
+ *ep = ne;
+ /*@=onlytrans@*/
+ }
+
+ return retval;
+}
+
+/* Simplify and determine if expression is superficially valid:
+ * Valid expr should be [(int-equiv expn)]+[reg*(int-equiv expn)+...]
+ * where the [...] parts are optional.
+ *
+ * Don't simplify out constant identities if we're looking for an indexreg: we
+ * may need the multiplier for determining what the indexreg is!
+ *
+ * Returns 1 if invalid register usage, 2 if unable to determine all values,
+ * and 0 if all values successfully determined and saved in data.
+ */
+static int
+x86_expr_checkea_getregusage(yasm_expr **ep, /*@null@*/ int *indexreg,
+ int *pcrel, unsigned int bits, void *data,
+ int *(*get_reg)(yasm_expr__item *ei, int *regnum, void *d))
+{
+ int i;
+ int *reg;
+ int regnum;
+ int indexval = 0;
+ int indexmult = 0;
+ yasm_expr *e, *wrt;
+
+ /*@-unqualifiedtrans@*/
+ *ep = yasm_expr__level_tree(*ep, 1, 1, indexreg == 0, 0, NULL, NULL);
+
+ /* Check for WRT rip first */
+ wrt = yasm_expr_extract_wrt(ep);
+ if (wrt && wrt->op == YASM_EXPR_IDENT &&
+ wrt->terms[0].type == YASM_EXPR_REG) {
+ if (bits != 64) { /* only valid in 64-bit mode */
+ yasm_expr_destroy(wrt);
+ return 1;
+ }
+ reg = get_reg(&wrt->terms[0], &regnum, data);
+ if (!reg || regnum != 16) { /* only accept rip */
+ yasm_expr_destroy(wrt);
+ return 1;
+ }
+ (*reg)++;
+
+ /* Delete WRT. Set pcrel to 1 to indicate to x86
+ * bytecode code to do PC-relative displacement transform.
+ */
+ *pcrel = 1;
+ yasm_expr_destroy(wrt);
+ } else if (wrt) {
+ yasm_expr_destroy(wrt);
+ return 1;
+ }
+
+ /*@=unqualifiedtrans@*/
+ assert(*ep != NULL);
+ e = *ep;
+ switch (x86_expr_checkea_distcheck_reg(ep, bits)) {
+ case 0:
+ return 1;
+ case 2:
+ /* Need to simplify again */
+ *ep = yasm_expr__level_tree(*ep, 1, 1, indexreg == 0, 0, NULL,
+ NULL);
+ e = *ep;
+ break;
+ default:
+ break;
+ }
+
+ switch (e->op) {
+ case YASM_EXPR_ADD:
+ /* Prescan for non-int multipliers against a reg.
+ * This is invalid due to the optimizer structure.
+ */
+ for (i=0; i<e->numterms; i++)
+ if (e->terms[i].type == YASM_EXPR_EXPR) {
+ yasm_expr__order_terms(e->terms[i].data.expn);
+ if (e->terms[i].data.expn->terms[0].type ==
+ YASM_EXPR_REG) {
+ if (e->terms[i].data.expn->numterms > 2)
+ return 1;
+ if (e->terms[i].data.expn->terms[1].type !=
+ YASM_EXPR_INT)
+ return 1;
+ }
+ }
+
+ /*@fallthrough@*/
+ case YASM_EXPR_IDENT:
+ /* Check each term for register (and possible multiplier). */
+ for (i=0; i<e->numterms; i++) {
+ if (e->terms[i].type == YASM_EXPR_REG) {
+ reg = get_reg(&e->terms[i], &regnum, data);
+ if (!reg)
+ return 1;
+ (*reg)++;
+ /* Let last, largest multipler win indexreg */
+ if (indexreg && *reg > 0 && indexval <= *reg &&
+ !indexmult) {
+ *indexreg = regnum;
+ indexval = *reg;
+ }
+ } else if (e->terms[i].type == YASM_EXPR_EXPR) {
+ /* Already ordered from ADD above, just grab the value.
+ * Sanity check for EXPR_INT.
+ */
+ if (e->terms[i].data.expn->terms[0].type ==
+ YASM_EXPR_REG) {
+ long delta;
+ if (e->terms[i].data.expn->terms[1].type !=
+ YASM_EXPR_INT)
+ yasm_internal_error(
+ N_("Non-integer value in reg expn"));
+ reg = get_reg(&e->terms[i].data.expn->terms[0],
+ &regnum, data);
+ if (!reg)
+ return 1;
+ delta = yasm_intnum_get_int(
+ e->terms[i].data.expn->terms[1].data.intn);
+ (*reg) += delta;
+ /* Let last, largest multipler win indexreg */
+ if (indexreg && delta > 0 && indexval <= *reg) {
+ *indexreg = regnum;
+ indexval = *reg;
+ indexmult = 1;
+ } else if (indexreg && *indexreg == regnum &&
+ delta < 0 && *reg <= 1) {
+ *indexreg = -1;
+ indexval = 0;
+ indexmult = 0;
+ }
+ }
+ }
+ }
+ break;
+ case YASM_EXPR_MUL:
+ /* Here, too, check for non-int multipliers against a reg. */
+ yasm_expr__order_terms(e);
+ if (e->terms[0].type == YASM_EXPR_REG) {
+ long delta;
+ if (e->numterms > 2)
+ return 1;
+ if (e->terms[1].type != YASM_EXPR_INT)
+ return 1;
+ reg = get_reg(&e->terms[0], &regnum, data);
+ if (!reg)
+ return 1;
+ delta = yasm_intnum_get_int(e->terms[1].data.intn);
+ (*reg) += delta;
+ if (indexreg)
+ {
+ if (delta < 0 && *reg <= 1)
+ {
+ *indexreg = -1;
+ indexval = 0;
+ indexmult = 0;
+ }
+ else
+ *indexreg = regnum;
+ }
+ }
+ break;
+ case YASM_EXPR_SEGOFF:
+ /* No registers are allowed on either side. */
+ if (yasm_expr__contains(e, YASM_EXPR_REG))
+ return 1;
+ break;
+ default:
+ /* Should never get here! */
+ yasm_internal_error(N_("unexpected expr op"));
+ }
+
+ /* Simplify expr, which is now really just the displacement. This
+ * should get rid of the 0's we put in for registers in the callback.
+ */
+ *ep = yasm_expr_simplify(*ep, 0);
+ /* e = *ep; */
+
+ return 0;
+}
+
+/* Calculate the displacement length, if possible.
+ * Takes several extra inputs so it can be used by both 32-bit and 16-bit
+ * expressions:
+ * wordsize=16 for 16-bit, =32 for 32-bit.
+ * noreg=1 if the *ModRM byte* has no registers used.
+ * dispreq=1 if a displacement value is *required* (even if =0).
+ * Returns 0 if successfully calculated, 1 if not.
+ */
+/*@-nullstate@*/
+static int
+x86_checkea_calc_displen(x86_effaddr *x86_ea, unsigned int wordsize, int noreg,
+ int dispreq)
+{
+ /*@null@*/ /*@only@*/ yasm_intnum *num;
+
+ x86_ea->valid_modrm = 0; /* default to not yet valid */
+
+ switch (x86_ea->ea.disp.size) {
+ case 0:
+ break;
+ /* If not 0, the displacement length was forced; set the Mod bits
+ * appropriately and we're done with the ModRM byte.
+ */
+ case 8:
+ /* Byte is only a valid override if there are registers in the
+ * EA. With no registers, we must have a 16/32 value.
+ */
+ if (noreg) {
+ yasm_warn_set(YASM_WARN_IMPLICIT_SIZE_OVERRIDE,
+ N_("invalid displacement size; fixed"));
+ x86_ea->ea.disp.size = wordsize;
+ } else
+ x86_ea->modrm |= 0100;
+ x86_ea->valid_modrm = 1;
+ return 0;
+ case 16:
+ case 32:
+ /* Don't allow changing displacement different from BITS setting
+ * directly; require an address-size override to change it.
+ */
+ if (wordsize != x86_ea->ea.disp.size) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("invalid effective address (displacement size)"));
+ return 1;
+ }
+ if (!noreg)
+ x86_ea->modrm |= 0200;
+ x86_ea->valid_modrm = 1;
+ return 0;
+ default:
+ /* we shouldn't ever get any other size! */
+ yasm_internal_error(N_("strange EA displacement size"));
+ }
+
+ /* The displacement length hasn't been forced (or the forcing wasn't
+ * valid), try to determine what it is.
+ */
+ if (noreg) {
+ /* No register in ModRM expression, so it must be disp16/32,
+ * and as the Mod bits are set to 0 by the caller, we're done
+ * with the ModRM byte.
+ */
+ x86_ea->ea.disp.size = wordsize;
+ x86_ea->valid_modrm = 1;
+ return 0;
+ }
+
+ if (dispreq) {
+ /* for BP/EBP, there *must* be a displacement value, but we
+ * may not know the size (8 or 16/32) for sure right now.
+ */
+ x86_ea->ea.need_nonzero_len = 1;
+ }
+
+ if (x86_ea->ea.disp.rel) {
+ /* Relative displacement; basically all object formats need non-byte
+ * for relocation here, so just do that. (TODO: handle this
+ * differently?)
+ */
+ x86_ea->ea.disp.size = wordsize;
+ x86_ea->modrm |= 0200;
+ x86_ea->valid_modrm = 1;
+ return 0;
+ }
+
+ /* At this point there's 3 possibilities for the displacement:
+ * - None (if =0)
+ * - signed 8 bit (if in -128 to 127 range)
+ * - 16/32 bit (word size)
+ * For now, check intnum value right now; if it's not 0,
+ * assume 8 bit and set up for allowing 16 bit later.
+ * FIXME: The complex expression equaling zero is probably a rare case,
+ * so we ignore it for now.
+ */
+ num = yasm_value_get_intnum(&x86_ea->ea.disp, NULL, 0);
+ if (!num) {
+ /* Still has unknown values. */
+ x86_ea->ea.need_nonzero_len = 1;
+ x86_ea->modrm |= 0100;
+ x86_ea->valid_modrm = 1;
+ return 0;
+ }
+
+ /* Figure out what size displacement we will have. */
+ if (yasm_intnum_is_zero(num) && !x86_ea->ea.need_nonzero_len) {
+ /* If we know that the displacement is 0 right now,
+ * go ahead and delete the expr and make it so no
+ * displacement value is included in the output.
+ * The Mod bits of ModRM are set to 0 above, and
+ * we're done with the ModRM byte!
+ */
+ yasm_value_delete(&x86_ea->ea.disp);
+ x86_ea->ea.need_disp = 0;
+ } else if (yasm_intnum_in_range(num, -128, 127)) {
+ /* It fits into a signed byte */
+ x86_ea->ea.disp.size = 8;
+ x86_ea->modrm |= 0100;
+ } else {
+ /* It's a 16/32-bit displacement */
+ x86_ea->ea.disp.size = wordsize;
+ x86_ea->modrm |= 0200;
+ }
+ x86_ea->valid_modrm = 1; /* We're done with ModRM */
+
+ yasm_intnum_destroy(num);
+ return 0;
+}
+/*@=nullstate@*/
+
+static int
+x86_expr_checkea_getregsize_callback(yasm_expr__item *ei, void *d)
+{
+ unsigned char *addrsize = (unsigned char *)d;
+
+ if (ei->type == YASM_EXPR_REG) {
+ switch ((x86_expritem_reg_size)(ei->data.reg & ~0xFUL)) {
+ case X86_REG16:
+ *addrsize = 16;
+ break;
+ case X86_REG32:
+ *addrsize = 32;
+ break;
+ case X86_REG64:
+ case X86_RIP:
+ *addrsize = 64;
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+ } else
+ return 0;
+}
+
+int
+yasm_x86__expr_checkea(x86_effaddr *x86_ea, unsigned char *addrsize,
+ unsigned int bits, int address16_op, unsigned char *rex,
+ yasm_bytecode *bc)
+{
+ int retval;
+
+ if (*addrsize == 0) {
+ /* we need to figure out the address size from what we know about:
+ * - the displacement length
+ * - what registers are used in the expression
+ * - the bits setting
+ */
+ switch (x86_ea->ea.disp.size) {
+ case 16:
+ /* must be 16-bit */
+ *addrsize = 16;
+ break;
+ case 64:
+ /* We have to support this for the MemOffs case, but it's
+ * otherwise illegal. It's also illegal in non-64-bit mode.
+ */
+ if (x86_ea->need_modrm || x86_ea->need_sib) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("invalid effective address (displacement size)"));
+ return 1;
+ }
+ *addrsize = 64;
+ break;
+ case 32:
+ /* Must be 32-bit in 16-bit or 32-bit modes. In 64-bit mode,
+ * we don't know unless we look at the registers, except in the
+ * MemOffs case (see the end of this function).
+ */
+ if (bits != 64 || (!x86_ea->need_modrm && !x86_ea->need_sib)) {
+ *addrsize = 32;
+ break;
+ }
+ /*@fallthrough@*/
+ default:
+ /* If SIB is required, but we're in 16-bit mode, set to 32. */
+ if (bits == 16 && x86_ea->need_sib == 1) {
+ *addrsize = 32;
+ break;
+ }
+ /* check for use of 16 or 32-bit registers; if none are used
+ * default to bits setting.
+ */
+ if (!x86_ea->ea.disp.abs ||
+ !yasm_expr__traverse_leaves_in(x86_ea->ea.disp.abs,
+ addrsize, x86_expr_checkea_getregsize_callback))
+ *addrsize = bits;
+ /* TODO: Add optional warning here if switched address size
+ * from bits setting just by register use.. eg [ax] in
+ * 32-bit mode would generate a warning.
+ */
+ }
+ }
+
+ if ((*addrsize == 32 || *addrsize == 64) &&
+ ((x86_ea->need_modrm && !x86_ea->valid_modrm) ||
+ (x86_ea->need_sib && !x86_ea->valid_sib))) {
+ int i;
+ unsigned char low3;
+ enum {
+ REG3264_NONE = -1,
+ REG3264_EAX = 0,
+ REG3264_ECX,
+ REG3264_EDX,
+ REG3264_EBX,
+ REG3264_ESP,
+ REG3264_EBP,
+ REG3264_ESI,
+ REG3264_EDI,
+ REG64_R8,
+ REG64_R9,
+ REG64_R10,
+ REG64_R11,
+ REG64_R12,
+ REG64_R13,
+ REG64_R14,
+ REG64_R15,
+ REG64_RIP,
+ SIMDREGS
+ };
+ int reg3264mult[33] =
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ x86_checkea_reg3264_data reg3264_data;
+ int basereg = REG3264_NONE; /* "base" register (for SIB) */
+ int indexreg = REG3264_NONE; /* "index" register (for SIB) */
+ int regcount = 17; /* normally don't check SIMD regs */
+
+ if (x86_ea->vsib_mode != 0)
+ regcount = 33;
+
+ /* We can only do 64-bit addresses in 64-bit mode. */
+ if (*addrsize == 64 && bits != 64) {
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("invalid effective address (64-bit in non-64-bit mode)"));
+ return 1;
+ }
+
+ if (x86_ea->ea.pc_rel && bits != 64) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("RIP-relative directive ignored in non-64-bit mode"));
+ x86_ea->ea.pc_rel = 0;
+ }
+
+ reg3264_data.regs = reg3264mult;
+ reg3264_data.vsib_mode = x86_ea->vsib_mode;
+ reg3264_data.bits = bits;
+ reg3264_data.addrsize = *addrsize;
+ if (x86_ea->ea.disp.abs) {
+ int pcrel = 0;
+ switch (x86_expr_checkea_getregusage
+ (&x86_ea->ea.disp.abs, &indexreg, &pcrel, bits,
+ &reg3264_data, x86_expr_checkea_get_reg3264)) {
+ case 1:
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("invalid effective address"));
+ return 1;
+ case 2:
+ if (pcrel)
+ yasm_value_set_curpos_rel(&x86_ea->ea.disp, bc, 1);
+ return 2;
+ default:
+ if (pcrel)
+ yasm_value_set_curpos_rel(&x86_ea->ea.disp, bc, 1);
+ break;
+ }
+ }
+
+ /* If indexreg mult is 0, discard it.
+ * This is possible because of the way indexreg is found in
+ * expr_checkea_getregusage().
+ */
+ if (indexreg != REG3264_NONE && reg3264mult[indexreg] == 0)
+ indexreg = REG3264_NONE;
+
+ /* Find a basereg (*1, but not indexreg), if there is one.
+ * Also, if an indexreg hasn't been assigned, try to find one.
+ * Meanwhile, check to make sure there's no negative register mults.
+ */
+ for (i=0; i<regcount; i++) {
+ if (reg3264mult[i] < 0) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("invalid effective address"));
+ return 1;
+ }
+ if (i != indexreg && reg3264mult[i] == 1 &&
+ basereg == REG3264_NONE)
+ basereg = i;
+ else if (indexreg == REG3264_NONE && reg3264mult[i] > 0)
+ indexreg = i;
+ }
+
+ if (x86_ea->vsib_mode != 0) {
+ /* For VSIB, the SIMD register needs to go into the indexreg.
+ * Also check basereg (must be a GPR if present) and indexreg
+ * (must be a SIMD register).
+ */
+ if (basereg >= SIMDREGS &&
+ (indexreg == REG3264_NONE || reg3264mult[indexreg] == 1)) {
+ int temp = basereg;
+ basereg = indexreg;
+ indexreg = temp;
+ }
+ if (basereg >= REG64_RIP || indexreg < SIMDREGS) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("invalid effective address"));
+ return 1;
+ }
+ } else if (indexreg != REG3264_NONE && basereg == REG3264_NONE)
+ /* Handle certain special cases of indexreg mults when basereg is
+ * empty.
+ */
+ switch (reg3264mult[indexreg]) {
+ case 1:
+ /* Only optimize this way if nosplit wasn't specified */
+ if (!x86_ea->ea.nosplit) {
+ basereg = indexreg;
+ indexreg = -1;
+ }
+ break;
+ case 2:
+ /* Only split if nosplit wasn't specified */
+ if (!x86_ea->ea.nosplit) {
+ basereg = indexreg;
+ reg3264mult[indexreg] = 1;
+ }
+ break;
+ case 3:
+ case 5:
+ case 9:
+ basereg = indexreg;
+ reg3264mult[indexreg]--;
+ break;
+ }
+
+ /* Make sure there's no other registers than the basereg and indexreg
+ * we just found.
+ */
+ for (i=0; i<regcount; i++)
+ if (i != basereg && i != indexreg && reg3264mult[i] != 0) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("invalid effective address"));
+ return 1;
+ }
+
+ /* Check the index multiplier value for validity if present. */
+ if (indexreg != REG3264_NONE && reg3264mult[indexreg] != 1 &&
+ reg3264mult[indexreg] != 2 && reg3264mult[indexreg] != 4 &&
+ reg3264mult[indexreg] != 8) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid effective address"));
+ return 1;
+ }
+
+ /* ESP is not a legal indexreg. */
+ if (indexreg == REG3264_ESP) {
+ /* If mult>1 or basereg is ESP also, there's no way to make it
+ * legal.
+ */
+ if (reg3264mult[REG3264_ESP] > 1 || basereg == REG3264_ESP) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("invalid effective address"));
+ return 1;
+ }
+ /* If mult==1 and basereg is not ESP, swap indexreg w/basereg. */
+ indexreg = basereg;
+ basereg = REG3264_ESP;
+ }
+
+ /* RIP is only legal if it's the ONLY register used. */
+ if (indexreg == REG64_RIP ||
+ (basereg == REG64_RIP && indexreg != REG3264_NONE)) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid effective address"));
+ return 1;
+ }
+
+ /* At this point, we know the base and index registers and that the
+ * memory expression is (essentially) valid. Now build the ModRM and
+ * (optional) SIB bytes.
+ */
+
+ /* If we're supposed to be RIP-relative and there's no register
+ * usage, change to RIP-relative.
+ */
+ if (basereg == REG3264_NONE && indexreg == REG3264_NONE &&
+ x86_ea->ea.pc_rel) {
+ basereg = REG64_RIP;
+ yasm_value_set_curpos_rel(&x86_ea->ea.disp, bc, 1);
+ }
+
+ /* First determine R/M (Mod is later determined from disp size) */
+ x86_ea->need_modrm = 1; /* we always need ModRM */
+ if (basereg == REG3264_NONE && indexreg == REG3264_NONE) {
+ /* Just a disp32: in 64-bit mode the RM encoding is used for RIP
+ * offset addressing, so we need to use the SIB form instead.
+ */
+ if (bits == 64) {
+ x86_ea->modrm |= 4;
+ x86_ea->need_sib = 1;
+ } else {
+ x86_ea->modrm |= 5;
+ x86_ea->sib = 0;
+ x86_ea->valid_sib = 0;
+ x86_ea->need_sib = 0;
+ }
+ } else if (basereg == REG64_RIP) {
+ x86_ea->modrm |= 5;
+ x86_ea->sib = 0;
+ x86_ea->valid_sib = 0;
+ x86_ea->need_sib = 0;
+ /* RIP always requires a 32-bit displacement */
+ x86_ea->valid_modrm = 1;
+ x86_ea->ea.disp.size = 32;
+ return 0;
+ } else if (indexreg == REG3264_NONE) {
+ /* basereg only */
+ /* Don't need to go to the full effort of determining what type
+ * of register basereg is, as x86_set_rex_from_reg doesn't pay
+ * much attention.
+ */
+ if (yasm_x86__set_rex_from_reg(rex, &low3,
+ (unsigned int)(X86_REG64 | basereg),
+ bits, X86_REX_B))
+ return 1;
+ x86_ea->modrm |= low3;
+ /* we don't need an SIB *unless* basereg is ESP or R12 */
+ if (basereg == REG3264_ESP || basereg == REG64_R12)
+ x86_ea->need_sib = 1;
+ else {
+ x86_ea->sib = 0;
+ x86_ea->valid_sib = 0;
+ x86_ea->need_sib = 0;
+ }
+ } else {
+ /* index or both base and index */
+ x86_ea->modrm |= 4;
+ x86_ea->need_sib = 1;
+ }
+
+ /* Determine SIB if needed */
+ if (x86_ea->need_sib == 1) {
+ x86_ea->sib = 0; /* start with 0 */
+
+ /* Special case: no basereg */
+ if (basereg == REG3264_NONE)
+ x86_ea->sib |= 5;
+ else {
+ if (yasm_x86__set_rex_from_reg(rex, &low3, (unsigned int)
+ (X86_REG64 | basereg), bits,
+ X86_REX_B))
+ return 1;
+ x86_ea->sib |= low3;
+ }
+
+ /* Put in indexreg, checking for none case */
+ if (indexreg == REG3264_NONE)
+ x86_ea->sib |= 040;
+ /* Any scale field is valid, just leave at 0. */
+ else {
+ if (indexreg >= SIMDREGS) {
+ if (yasm_x86__set_rex_from_reg(rex, &low3,
+ (unsigned int)(X86_XMMREG | (indexreg-SIMDREGS)),
+ bits, X86_REX_X))
+ return 1;
+ } else {
+ if (yasm_x86__set_rex_from_reg(rex, &low3,
+ (unsigned int)(X86_REG64 | indexreg),
+ bits, X86_REX_X))
+ return 1;
+ }
+ x86_ea->sib |= low3 << 3;
+ /* Set scale field, 1 case -> 0, so don't bother. */
+ switch (reg3264mult[indexreg]) {
+ case 2:
+ x86_ea->sib |= 0100;
+ break;
+ case 4:
+ x86_ea->sib |= 0200;
+ break;
+ case 8:
+ x86_ea->sib |= 0300;
+ break;
+ }
+ }
+
+ x86_ea->valid_sib = 1; /* Done with SIB */
+ }
+
+ /* Calculate displacement length (if possible) */
+ retval = x86_checkea_calc_displen
+ (x86_ea, 32, basereg == REG3264_NONE,
+ basereg == REG3264_EBP || basereg == REG64_R13);
+ return retval;
+ } else if (*addrsize == 16 && x86_ea->need_modrm && !x86_ea->valid_modrm) {
+ static const unsigned char modrm16[16] = {
+ 0006 /* disp16 */, 0007 /* [BX] */, 0004 /* [SI] */,
+ 0000 /* [BX+SI] */, 0005 /* [DI] */, 0001 /* [BX+DI] */,
+ 0377 /* invalid */, 0377 /* invalid */, 0006 /* [BP]+d */,
+ 0377 /* invalid */, 0002 /* [BP+SI] */, 0377 /* invalid */,
+ 0003 /* [BP+DI] */, 0377 /* invalid */, 0377 /* invalid */,
+ 0377 /* invalid */
+ };
+ x86_checkea_reg16_data reg16mult = {0, 0, 0, 0};
+ enum {
+ HAVE_NONE = 0,
+ HAVE_BX = 1<<0,
+ HAVE_SI = 1<<1,
+ HAVE_DI = 1<<2,
+ HAVE_BP = 1<<3
+ } havereg = HAVE_NONE;
+
+ /* 64-bit mode does not allow 16-bit addresses */
+ if (bits == 64 && !address16_op) {
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("16-bit addresses not supported in 64-bit mode"));
+ return 1;
+ }
+
+ /* 16-bit cannot have SIB */
+ x86_ea->sib = 0;
+ x86_ea->valid_sib = 0;
+ x86_ea->need_sib = 0;
+
+ if (x86_ea->ea.disp.abs) {
+ int pcrel = 0;
+ switch (x86_expr_checkea_getregusage
+ (&x86_ea->ea.disp.abs, (int *)NULL, &pcrel, bits,
+ &reg16mult, x86_expr_checkea_get_reg16)) {
+ case 1:
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("invalid effective address"));
+ return 1;
+ case 2:
+ if (pcrel)
+ yasm_value_set_curpos_rel(&x86_ea->ea.disp, bc, 1);
+ return 2;
+ default:
+ if (pcrel)
+ yasm_value_set_curpos_rel(&x86_ea->ea.disp, bc, 1);
+ break;
+ }
+ }
+
+ /* reg multipliers not 0 or 1 are illegal. */
+ if (reg16mult.bx & ~1 || reg16mult.si & ~1 || reg16mult.di & ~1 ||
+ reg16mult.bp & ~1) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid effective address"));
+ return 1;
+ }
+
+ /* Set havereg appropriately */
+ if (reg16mult.bx > 0)
+ havereg |= HAVE_BX;
+ if (reg16mult.si > 0)
+ havereg |= HAVE_SI;
+ if (reg16mult.di > 0)
+ havereg |= HAVE_DI;
+ if (reg16mult.bp > 0)
+ havereg |= HAVE_BP;
+
+ /* Check the modrm value for invalid combinations. */
+ if (modrm16[havereg] & 0070) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid effective address"));
+ return 1;
+ }
+
+ /* Set ModRM byte for registers */
+ x86_ea->modrm |= modrm16[havereg];
+
+ /* Calculate displacement length (if possible) */
+ retval = x86_checkea_calc_displen
+ (x86_ea, 16, havereg == HAVE_NONE, havereg == HAVE_BP);
+ return retval;
+ } else if (!x86_ea->need_modrm && !x86_ea->need_sib) {
+ /* Special case for MOV MemOffs opcode: displacement but no modrm. */
+ switch (*addrsize) {
+ case 64:
+ if (bits != 64) {
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("invalid effective address (64-bit in non-64-bit mode)"));
+ return 1;
+ }
+ x86_ea->ea.disp.size = 64;
+ break;
+ case 32:
+ x86_ea->ea.disp.size = 32;
+ break;
+ case 16:
+ /* 64-bit mode does not allow 16-bit addresses */
+ if (bits == 64 && !address16_op) {
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("16-bit addresses not supported in 64-bit mode"));
+ return 1;
+ }
+ x86_ea->ea.disp.size = 16;
+ break;
+ }
+ }
+ return 0;
+}
+
+int
+yasm_x86__floatnum_tobytes(yasm_arch *arch, const yasm_floatnum *flt,
+ unsigned char *buf, size_t destsize, size_t valsize,
+ size_t shift, int warn)
+{
+ if (!yasm_floatnum_check_size(flt, valsize)) {
+ yasm_error_set(YASM_ERROR_FLOATING_POINT,
+ N_("invalid floating point constant size"));
+ return 1;
+ }
+
+ yasm_floatnum_get_sized(flt, buf, destsize, valsize, shift, 0, warn);
+ return 0;
+}
diff --git a/contrib/tools/yasm/modules/arch/x86/x86id.c b/contrib/tools/yasm/modules/arch/x86/x86id.c
new file mode 100644
index 0000000000..6207c2062c
--- /dev/null
+++ b/contrib/tools/yasm/modules/arch/x86/x86id.c
@@ -0,0 +1,1951 @@
+/*
+ * x86 identifier recognition and instruction handling
+ *
+ * Copyright (C) 2002-2007 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 <ctype.h>
+#include <util.h>
+
+#include <libyasm.h>
+#include <libyasm/phash.h>
+
+#include "modules/arch/x86/x86arch.h"
+
+
+static const char *cpu_find_reverse(unsigned int cpu0, unsigned int cpu1,
+ unsigned int cpu2);
+
+/* Opcode modifiers. */
+#define MOD_Gap 0 /* Eats a parameter / does nothing */
+#define MOD_PreAdd 1 /* Parameter adds to "special" prefix */
+#define MOD_Op0Add 2 /* Parameter adds to opcode byte 0 */
+#define MOD_Op1Add 3 /* Parameter adds to opcode byte 1 */
+#define MOD_Op2Add 4 /* Parameter adds to opcode byte 2 */
+#define MOD_SpAdd 5 /* Parameter adds to "spare" value */
+#define MOD_OpSizeR 6 /* Parameter replaces opersize */
+#define MOD_Imm8 7 /* Parameter is included as immediate byte */
+#define MOD_AdSizeR 8 /* Parameter replaces addrsize (jmp only) */
+#define MOD_DOpS64R 9 /* Parameter replaces default 64-bit opersize */
+#define MOD_Op1AddSp 10 /* Parameter is added as "spare" to opcode byte 2 */
+#define MOD_SetVEX 11 /* Parameter replaces internal VEX prefix value */
+
+/* GAS suffix flags for instructions */
+enum x86_gas_suffix_flags {
+ SUF_Z = 1<<0, /* no suffix */
+ SUF_B = 1<<1,
+ SUF_W = 1<<2,
+ SUF_L = 1<<3,
+ SUF_Q = 1<<4,
+ SUF_S = 1<<5,
+ SUF_MASK = SUF_Z|SUF_B|SUF_W|SUF_L|SUF_Q|SUF_S,
+
+ /* Flags only used in x86_insn_info */
+ GAS_ONLY = 1<<6, /* Only available in GAS mode */
+ GAS_ILLEGAL = 1<<7, /* Illegal in GAS mode */
+ GAS_NO_REV = 1<<8 /* Don't reverse operands in GAS mode */
+};
+
+/* Miscellaneous flag tests for instructions */
+enum x86_misc_flags {
+ /* These are tested against BITS==64. */
+ ONLY_64 = 1<<0, /* Only available in 64-bit mode */
+ NOT_64 = 1<<1, /* Not available (invalid) in 64-bit mode */
+ /* These are tested against whether the base instruction is an AVX one. */
+ ONLY_AVX = 1<<2, /* Only available in AVX instruction */
+ NOT_AVX = 1<<3 /* Not available (invalid) in AVX instruction */
+};
+
+enum x86_operand_type {
+ OPT_Imm = 0, /* immediate */
+ OPT_Reg = 1, /* any general purpose or FPU register */
+ OPT_Mem = 2, /* memory */
+ OPT_RM = 3, /* any general purpose or FPU register OR memory */
+ OPT_SIMDReg = 4, /* any MMX or XMM register */
+ OPT_SIMDRM = 5, /* any MMX or XMM register OR memory */
+ OPT_SegReg = 6, /* any segment register */
+ OPT_CRReg = 7, /* any CR register */
+ OPT_DRReg = 8, /* any DR register */
+ OPT_TRReg = 9, /* any TR register */
+ OPT_ST0 = 10, /* ST0 */
+ OPT_Areg = 11, /* AL/AX/EAX/RAX (depending on size) */
+ OPT_Creg = 12, /* CL/CX/ECX/RCX (depending on size) */
+ OPT_Dreg = 13, /* DL/DX/EDX/RDX (depending on size) */
+ OPT_CS = 14, /* CS */
+ OPT_DS = 15, /* DS */
+ OPT_ES = 16, /* ES */
+ OPT_FS = 17, /* FS */
+ OPT_GS = 18, /* GS */
+ OPT_SS = 19, /* SS */
+ OPT_CR4 = 20, /* CR4 */
+ /* memory offset (an EA, but with no registers allowed)
+ * [special case for MOV opcode]
+ */
+ OPT_MemOffs = 21,
+ OPT_Imm1 = 22, /* immediate, value=1 (for special-case shift) */
+ /* immediate, does not contain SEG:OFF (for jmp/call) */
+ OPT_ImmNotSegOff = 23,
+ OPT_XMM0 = 24, /* XMM0 */
+ /* AX/EAX/RAX memory operand only (EA) [special case for SVM opcodes]
+ */
+ OPT_MemrAX = 25,
+ /* EAX memory operand only (EA) [special case for SVM skinit opcode] */
+ OPT_MemEAX = 26,
+ /* XMM VSIB memory operand */
+ OPT_MemXMMIndex = 27,
+ /* YMM VSIB memory operand */
+ OPT_MemYMMIndex = 28
+};
+
+enum x86_operand_size {
+ /* any size acceptable/no size spec acceptable (dep. on strict) */
+ OPS_Any = 0,
+ /* 8/16/32/64/80/128/256 bits (from user or reg size) */
+ OPS_8 = 1,
+ OPS_16 = 2,
+ OPS_32 = 3,
+ OPS_64 = 4,
+ OPS_80 = 5,
+ OPS_128 = 6,
+ OPS_256 = 7,
+ /* current BITS setting; when this is used the size matched
+ * gets stored into the opersize as well.
+ */
+ OPS_BITS = 8
+};
+
+enum x86_operand_targetmod {
+ OPTM_None = 0, /* no target mod acceptable */
+ OPTM_Near = 1, /* NEAR */
+ OPTM_Short = 2, /* SHORT */
+ OPTM_Far = 3, /* FAR (or SEG:OFF immediate) */
+ OPTM_To = 4 /* TO */
+};
+
+enum x86_operand_action {
+ OPA_None = 0, /* does nothing (operand data is discarded) */
+ OPA_EA = 1, /* operand data goes into ea field */
+ OPA_Imm = 2, /* operand data goes into imm field */
+ OPA_SImm = 3, /* operand data goes into sign-extended imm field */
+ OPA_Spare = 4, /* operand data goes into "spare" field */
+ OPA_Op0Add = 5, /* operand data is added to opcode byte 0 */
+ OPA_Op1Add = 6, /* operand data is added to opcode byte 1 */
+ /* operand data goes into BOTH ea and spare
+ * (special case for imul opcode)
+ */
+ OPA_SpareEA = 7,
+ /* relative jump (outputs a jmp instead of normal insn) */
+ OPA_JmpRel = 8,
+ /* operand size goes into address size (jmp only) */
+ OPA_AdSizeR = 9,
+ /* far jump (outputs a farjmp instead of normal insn) */
+ OPA_JmpFar = 10,
+ /* ea operand only sets address size (no actual ea field) */
+ OPA_AdSizeEA = 11,
+ OPA_VEX = 12, /* operand data goes into VEX/XOP "vvvv" field */
+ /* operand data goes into BOTH VEX/XOP "vvvv" field and ea field */
+ OPA_EAVEX = 13,
+ /* operand data goes into BOTH VEX/XOP "vvvv" field and spare field */
+ OPA_SpareVEX = 14,
+ /* operand data goes into upper 4 bits of immediate byte (VEX is4 field) */
+ OPA_VEXImmSrc = 15,
+ /* operand data goes into bottom 4 bits of immediate byte
+ * (currently only VEX imz2 field)
+ */
+ OPA_VEXImm = 16
+};
+
+enum x86_operand_post_action {
+ OPAP_None = 0,
+ /* sign-extended imm8 that could expand to a large imm16/32 */
+ OPAP_SImm8 = 1,
+ /* could become a short opcode mov with bits=64 and a32 prefix */
+ OPAP_ShortMov = 2,
+ /* forced 16-bit address size (override ignored, no prefix) */
+ OPAP_A16 = 3,
+ /* large imm64 that can become a sign-extended imm32 */
+ OPAP_SImm32Avail = 4
+};
+
+typedef struct x86_info_operand {
+ /* Operand types. These are more detailed than the "general" types for all
+ * architectures, as they include the size, for instance.
+ */
+
+ /* general type (must be exact match, except for RM types): */
+ unsigned int type:5;
+
+ /* size (user-specified, or from register size) */
+ unsigned int size:4;
+
+ /* size implicit or explicit ("strictness" of size matching on
+ * non-registers -- registers are always strictly matched):
+ * 0 = user size must exactly match size above.
+ * 1 = user size either unspecified or exactly match size above.
+ */
+ unsigned int relaxed:1;
+
+ /* effective address size
+ * 0 = any address size allowed except for 64-bit
+ * 1 = only 64-bit address size allowed
+ */
+ unsigned int eas64:1;
+
+ /* target modification */
+ unsigned int targetmod:3;
+
+ /* Actions: what to do with the operand if the instruction matches.
+ * Essentially describes what part of the output bytecode gets the
+ * operand. This may require conversion (e.g. a register going into
+ * an ea field). Naturally, only one of each of these may be contained
+ * in the operands of a single insn_info structure.
+ */
+ unsigned int action:5;
+
+ /* Postponed actions: actions which can't be completed at
+ * parse-time due to possibly dependent expressions. For these, some
+ * additional data (stored in the second byte of the opcode with a
+ * one-byte opcode) is passed to later stages of the assembler with
+ * flags set to indicate postponed actions.
+ */
+ unsigned int post_action:3;
+} x86_info_operand;
+
+typedef struct x86_insn_info {
+ /* GAS suffix flags */
+ unsigned int gas_flags:9; /* Enabled for these GAS suffixes */
+
+ /* Tests against BITS==64, AVX, and XOP */
+ unsigned int misc_flags:5;
+
+ /* The CPU feature flags needed to execute this instruction. This is OR'ed
+ * with arch-specific data[2]. This combined value is compared with
+ * cpu_enabled to see if all bits set here are set in cpu_enabled--if so,
+ * the instruction is available on this CPU.
+ */
+ unsigned int cpu0:6;
+ unsigned int cpu1:6;
+ unsigned int cpu2:6;
+
+ /* Opcode modifiers for variations of instruction. As each modifier reads
+ * its parameter in LSB->MSB order from the arch-specific data[1] from the
+ * lexer data, and the LSB of the arch-specific data[1] is reserved for the
+ * count of insn_info structures in the instruction grouping, there can
+ * only be a maximum of 3 modifiers.
+ */
+ unsigned char modifiers[3];
+
+ /* Operand Size */
+ unsigned char opersize;
+
+ /* Default operand size in 64-bit mode (0 = 32-bit for readability). */
+ unsigned char def_opersize_64;
+
+ /* A special instruction prefix, used for some of the Intel SSE and SSE2
+ * instructions. Intel calls these 3-byte opcodes, but in AMD64's 64-bit
+ * mode, they're treated like normal prefixes (e.g. the REX prefix needs
+ * to be *after* the F2/F3/66 "prefix").
+ * (0=no special prefix)
+ * 0xC0 - 0xCF indicate a VEX prefix, with the four LSBs holding "WLpp":
+ * W: VEX.W field (meaning depends on opcode)
+ * L: 0=128-bit, 1=256-bit
+ * pp: SIMD prefix designation:
+ * 00: None
+ * 01: 66
+ * 10: F3
+ * 11: F2
+ * 0x80 - 0x8F indicate a XOP prefix, with the four LSBs holding "WLpp":
+ * same meanings as VEX prefix.
+ */
+ unsigned char special_prefix;
+
+ /* The length of the basic opcode */
+ unsigned char opcode_len;
+
+ /* The basic 1-3 byte opcode (not including the special instruction
+ * prefix).
+ */
+ unsigned char opcode[3];
+
+ /* The 3-bit "spare" value (extended opcode) for the R/M byte field */
+ unsigned char spare;
+
+ /* The number of operands this form of the instruction takes */
+ unsigned int num_operands:4;
+
+ /* The index into the insn_operands array which contains the type of each
+ * operand, see above
+ */
+ unsigned int operands_index:12;
+} x86_insn_info;
+
+typedef struct x86_id_insn {
+ yasm_insn insn; /* base structure */
+
+ /* instruction parse group - NULL if empty instruction (just prefixes) */
+ /*@null@*/ const x86_insn_info *group;
+
+ /* CPU feature flags enabled at the time of parsing the instruction */
+ wordptr cpu_enabled;
+
+ /* Modifier data */
+ unsigned char mod_data[3];
+
+ /* Number of elements in the instruction parse group */
+ unsigned int num_info:8;
+
+ /* BITS setting active at the time of parsing the instruction */
+ unsigned int mode_bits:8;
+
+ /* Suffix flags */
+ unsigned int suffix:9;
+
+ /* Tests against BITS==64 and AVX */
+ unsigned int misc_flags:5;
+
+ /* Parser enabled at the time of parsing the instruction */
+ unsigned int parser:2;
+
+ /* Strict forced setting at the time of parsing the instruction */
+ unsigned int force_strict:1;
+
+ /* Default rel setting at the time of parsing the instruction */
+ unsigned int default_rel:1;
+} x86_id_insn;
+
+static void x86_id_insn_destroy(void *contents);
+static void x86_id_insn_print(const void *contents, FILE *f, int indent_level);
+static void x86_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+
+static const yasm_bytecode_callback x86_id_insn_callback = {
+ x86_id_insn_destroy,
+ x86_id_insn_print,
+ x86_id_insn_finalize,
+ NULL,
+ yasm_bc_calc_len_common,
+ yasm_bc_expand_common,
+ yasm_bc_tobytes_common,
+ YASM_BC_SPECIAL_INSN
+};
+
+#include "x86insns.c"
+
+/* Looks for the first SIMD register match for the purposes of VSIB matching.
+ * Full legality checking is performed in EA code.
+ */
+static int
+x86_expr_contains_simd_cb(const yasm_expr__item *ei, void *d)
+{
+ int ymm = *((int *)d);
+ if (ei->type != YASM_EXPR_REG)
+ return 0;
+ switch ((x86_expritem_reg_size)(ei->data.reg & ~0xFUL)) {
+ case X86_XMMREG:
+ if (!ymm)
+ return 1;
+ break;
+ case X86_YMMREG:
+ if (ymm)
+ return 1;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int
+x86_expr_contains_simd(const yasm_expr *e, int ymm)
+{
+ return yasm_expr__traverse_leaves_in_const(e, &ymm,
+ x86_expr_contains_simd_cb);
+}
+
+static void
+x86_finalize_common(x86_common *common, const x86_insn_info *info,
+ unsigned int mode_bits)
+{
+ common->addrsize = 0;
+ common->opersize = info->opersize;
+ common->lockrep_pre = 0;
+ common->acqrel_pre = 0;
+ common->mode_bits = (unsigned char)mode_bits;
+}
+
+static void
+x86_finalize_opcode(x86_opcode *opcode, const x86_insn_info *info)
+{
+ opcode->len = info->opcode_len;
+ opcode->opcode[0] = info->opcode[0];
+ opcode->opcode[1] = info->opcode[1];
+ opcode->opcode[2] = info->opcode[2];
+}
+
+/* Clear operands so they don't get destroyed after we've copied references. */
+static void
+x86_id_insn_clear_operands(x86_id_insn *id_insn)
+{
+ yasm_insn_operand *op = yasm_insn_ops_first(&id_insn->insn);
+ while (op) {
+ op->type = YASM_INSN__OPERAND_REG;
+ op = yasm_insn_op_next(op);
+ }
+}
+
+static void
+x86_finalize_jmpfar(yasm_bytecode *bc, yasm_bytecode *prev_bc,
+ const x86_insn_info *info)
+{
+ x86_id_insn *id_insn = (x86_id_insn *)bc->contents;
+ unsigned char *mod_data = id_insn->mod_data;
+ unsigned int mode_bits = id_insn->mode_bits;
+ x86_jmpfar *jmpfar;
+ yasm_insn_operand *op;
+ unsigned int i;
+
+ jmpfar = yasm_xmalloc(sizeof(x86_jmpfar));
+ x86_finalize_common(&jmpfar->common, info, mode_bits);
+ x86_finalize_opcode(&jmpfar->opcode, info);
+
+ op = yasm_insn_ops_first(&id_insn->insn);
+
+ if (op->type == YASM_INSN__OPERAND_IMM && op->seg) {
+ /* SEG:OFF */
+ if (yasm_value_finalize_expr(&jmpfar->segment, op->seg, prev_bc, 16))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("jump target segment too complex"));
+ if (yasm_value_finalize_expr(&jmpfar->offset, op->data.val, prev_bc,
+ 0))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("jump target offset too complex"));
+ } else if (op->targetmod == X86_FAR) {
+ /* "FAR imm" target needs to become "seg imm:imm". */
+ yasm_expr *e = yasm_expr_create_branch(YASM_EXPR_SEG,
+ yasm_expr_copy(op->data.val),
+ op->data.val->line);
+ if (yasm_value_finalize_expr(&jmpfar->offset, op->data.val, prev_bc, 0)
+ || yasm_value_finalize_expr(&jmpfar->segment, e, prev_bc, 16))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("jump target expression too complex"));
+ } else if (yasm_insn_op_next(op)) {
+ /* Two operand form (gas) */
+ yasm_insn_operand *op2 = yasm_insn_op_next(op);
+ if (yasm_value_finalize_expr(&jmpfar->segment, op->data.val, prev_bc,
+ 16))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("jump target segment too complex"));
+ if (yasm_value_finalize_expr(&jmpfar->offset, op2->data.val, prev_bc,
+ 0))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("jump target offset too complex"));
+ if (op2->size == OPS_BITS)
+ jmpfar->common.opersize = (unsigned char)mode_bits;
+ } else
+ yasm_internal_error(N_("didn't get FAR expression in jmpfar"));
+
+ /* Apply modifiers */
+ for (i=0; i<NELEMS(info->modifiers); i++) {
+ switch (info->modifiers[i]) {
+ case MOD_Gap:
+ break;
+ case MOD_Op0Add:
+ jmpfar->opcode.opcode[0] += mod_data[i];
+ break;
+ case MOD_Op1Add:
+ jmpfar->opcode.opcode[1] += mod_data[i];
+ break;
+ case MOD_Op2Add:
+ jmpfar->opcode.opcode[2] += mod_data[i];
+ break;
+ case MOD_Op1AddSp:
+ jmpfar->opcode.opcode[1] += mod_data[i]<<3;
+ break;
+ default:
+ break;
+ }
+ }
+
+ yasm_x86__bc_apply_prefixes((x86_common *)jmpfar, NULL,
+ info->def_opersize_64,
+ id_insn->insn.num_prefixes,
+ id_insn->insn.prefixes);
+
+ x86_id_insn_clear_operands(id_insn);
+
+ /* Transform the bytecode */
+ yasm_x86__bc_transform_jmpfar(bc, jmpfar);
+}
+
+static void
+x86_finalize_jmp(yasm_bytecode *bc, yasm_bytecode *prev_bc,
+ const x86_insn_info *jinfo)
+{
+ x86_id_insn *id_insn = (x86_id_insn *)bc->contents;
+ x86_jmp *jmp;
+ int num_info = id_insn->num_info;
+ const x86_insn_info *info = id_insn->group;
+ unsigned char *mod_data = id_insn->mod_data;
+ unsigned int mode_bits = id_insn->mode_bits;
+ /*unsigned char suffix = id_insn->suffix;*/
+ yasm_insn_operand *op;
+ static const unsigned char size_lookup[] =
+ {0, 8, 16, 32, 64, 80, 128, 0, 0}; /* 256 not needed */
+ unsigned int i;
+
+ /* We know the target is in operand 0, but sanity check for Imm. */
+ op = yasm_insn_ops_first(&id_insn->insn);
+ if (op->type != YASM_INSN__OPERAND_IMM)
+ yasm_internal_error(N_("invalid operand conversion"));
+
+ jmp = yasm_xmalloc(sizeof(x86_jmp));
+ x86_finalize_common(&jmp->common, jinfo, mode_bits);
+ if (yasm_value_finalize_expr(&jmp->target, op->data.val, prev_bc, 0))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("jump target expression too complex"));
+ if (jmp->target.seg_of || jmp->target.rshift || jmp->target.curpos_rel)
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid jump target"));
+ yasm_value_set_curpos_rel(&jmp->target, bc, 0);
+ jmp->target.jump_target = 1;
+
+ /* See if the user explicitly specified short/near/far. */
+ switch (insn_operands[jinfo->operands_index+0].targetmod) {
+ case OPTM_Short:
+ jmp->op_sel = JMP_SHORT_FORCED;
+ break;
+ case OPTM_Near:
+ jmp->op_sel = JMP_NEAR_FORCED;
+ break;
+ default:
+ jmp->op_sel = JMP_NONE;
+ }
+
+ /* Check for address size setting in second operand, if present */
+ if (jinfo->num_operands > 1 &&
+ insn_operands[jinfo->operands_index+1].action == OPA_AdSizeR)
+ jmp->common.addrsize = (unsigned char)
+ size_lookup[insn_operands[jinfo->operands_index+1].size];
+
+ /* Check for address size override */
+ for (i=0; i<NELEMS(jinfo->modifiers); i++) {
+ if (jinfo->modifiers[i] == MOD_AdSizeR)
+ jmp->common.addrsize = mod_data[i];
+ }
+
+ /* Scan through other infos for this insn looking for short/near versions.
+ * Needs to match opersize and number of operands, also be within CPU.
+ */
+ jmp->shortop.len = 0;
+ jmp->nearop.len = 0;
+ for (; num_info>0 && (jmp->shortop.len == 0 || jmp->nearop.len == 0);
+ num_info--, info++) {
+ /* Match CPU */
+ if (mode_bits != 64 && (info->misc_flags & ONLY_64))
+ continue;
+ if (mode_bits == 64 && (info->misc_flags & NOT_64))
+ continue;
+
+ if (!BitVector_bit_test(id_insn->cpu_enabled, info->cpu0) ||
+ !BitVector_bit_test(id_insn->cpu_enabled, info->cpu1) ||
+ !BitVector_bit_test(id_insn->cpu_enabled, info->cpu2))
+ continue;
+
+ if (info->num_operands == 0)
+ continue;
+
+ if (insn_operands[info->operands_index+0].action != OPA_JmpRel)
+ continue;
+
+ if (info->opersize != jmp->common.opersize)
+ continue;
+
+ switch (insn_operands[info->operands_index+0].targetmod) {
+ case OPTM_Short:
+ x86_finalize_opcode(&jmp->shortop, info);
+ for (i=0; i<NELEMS(info->modifiers); i++) {
+ if (info->modifiers[i] == MOD_Op0Add)
+ jmp->shortop.opcode[0] += mod_data[i];
+ }
+ break;
+ case OPTM_Near:
+ x86_finalize_opcode(&jmp->nearop, info);
+ for (i=0; i<NELEMS(info->modifiers); i++) {
+ if (info->modifiers[i] == MOD_Op1Add)
+ jmp->nearop.opcode[1] += mod_data[i];
+ }
+ break;
+ }
+ }
+
+ if ((jmp->op_sel == JMP_SHORT_FORCED) && (jmp->shortop.len == 0))
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("no SHORT form of that jump instruction exists"));
+ if ((jmp->op_sel == JMP_NEAR_FORCED) && (jmp->nearop.len == 0))
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("no NEAR form of that jump instruction exists"));
+
+ if (jmp->op_sel == JMP_NONE) {
+ if (jmp->nearop.len == 0)
+ jmp->op_sel = JMP_SHORT_FORCED;
+ if (jmp->shortop.len == 0)
+ jmp->op_sel = JMP_NEAR_FORCED;
+ }
+
+ yasm_x86__bc_apply_prefixes((x86_common *)jmp, NULL,
+ jinfo->def_opersize_64,
+ id_insn->insn.num_prefixes,
+ id_insn->insn.prefixes);
+
+ x86_id_insn_clear_operands(id_insn);
+
+ /* Transform the bytecode */
+ yasm_x86__bc_transform_jmp(bc, jmp);
+}
+
+static const x86_insn_info *
+x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops,
+ yasm_insn_operand **rev_ops, const unsigned int *size_lookup,
+ int bypass)
+{
+ const x86_insn_info *info = id_insn->group;
+ unsigned int num_info = id_insn->num_info;
+ unsigned int suffix = id_insn->suffix;
+ unsigned int mode_bits = id_insn->mode_bits;
+ int found = 0;
+
+ /* Just do a simple linear search through the info array for a match.
+ * First match wins.
+ */
+ for (; num_info>0 && !found; num_info--, info++) {
+ yasm_insn_operand *op, **use_ops;
+ const x86_info_operand *info_ops =
+ &insn_operands[info->operands_index];
+ unsigned int gas_flags = info->gas_flags;
+ unsigned int misc_flags = info->misc_flags;
+ unsigned int size;
+ int mismatch = 0;
+ unsigned int i;
+
+ /* Match CPU */
+ if (mode_bits != 64 && (misc_flags & ONLY_64))
+ continue;
+ if (mode_bits == 64 && (misc_flags & NOT_64))
+ continue;
+
+ if (bypass != 8 &&
+ (!BitVector_bit_test(id_insn->cpu_enabled, info->cpu0) ||
+ !BitVector_bit_test(id_insn->cpu_enabled, info->cpu1) ||
+ !BitVector_bit_test(id_insn->cpu_enabled, info->cpu2)))
+ continue;
+
+ /* Match # of operands */
+ if (id_insn->insn.num_operands != info->num_operands)
+ continue;
+
+ /* Match AVX */
+ if (!(id_insn->misc_flags & ONLY_AVX) && (misc_flags & ONLY_AVX))
+ continue;
+ if ((id_insn->misc_flags & ONLY_AVX) && (misc_flags & NOT_AVX))
+ continue;
+
+ /* Match parser mode */
+ if ((gas_flags & GAS_ONLY) && id_insn->parser != X86_PARSER_GAS)
+ continue;
+ if ((gas_flags & GAS_ILLEGAL) && id_insn->parser == X86_PARSER_GAS)
+ continue;
+
+ /* Match suffix (if required) */
+ if (id_insn->parser == X86_PARSER_GAS
+ && ((suffix & SUF_MASK) & (gas_flags & SUF_MASK)) == 0)
+ continue;
+
+ /* Use reversed operands in GAS mode if not otherwise specified */
+ use_ops = ops;
+ if (id_insn->parser == X86_PARSER_GAS && !(gas_flags & GAS_NO_REV))
+ use_ops = rev_ops;
+
+ if (id_insn->insn.num_operands == 0) {
+ found = 1; /* no operands -> must have a match here. */
+ break;
+ }
+
+ /* Match each operand type and size */
+ for (i = 0, op = use_ops[0]; op && i<info->num_operands && !mismatch;
+ op = use_ops[++i]) {
+ /* Check operand type */
+ switch (info_ops[i].type) {
+ case OPT_Imm:
+ if (op->type != YASM_INSN__OPERAND_IMM)
+ mismatch = 1;
+ break;
+ case OPT_RM:
+ if (op->type == YASM_INSN__OPERAND_MEMORY)
+ break;
+ /*@fallthrough@*/
+ case OPT_Reg:
+ if (op->type != YASM_INSN__OPERAND_REG)
+ mismatch = 1;
+ else {
+ switch ((x86_expritem_reg_size)(op->data.reg&~0xFUL)) {
+ case X86_REG8:
+ case X86_REG8X:
+ case X86_REG16:
+ case X86_REG32:
+ case X86_REG64:
+ case X86_FPUREG:
+ break;
+ default:
+ mismatch = 1;
+ break;
+ }
+ }
+ break;
+ case OPT_Mem:
+ if (op->type != YASM_INSN__OPERAND_MEMORY)
+ mismatch = 1;
+ break;
+ case OPT_SIMDRM:
+ if (op->type == YASM_INSN__OPERAND_MEMORY)
+ break;
+ /*@fallthrough@*/
+ case OPT_SIMDReg:
+ if (op->type != YASM_INSN__OPERAND_REG)
+ mismatch = 1;
+ else {
+ switch ((x86_expritem_reg_size)(op->data.reg&~0xFUL)) {
+ case X86_MMXREG:
+ case X86_XMMREG:
+ case X86_YMMREG:
+ break;
+ default:
+ mismatch = 1;
+ break;
+ }
+ }
+ break;
+ case OPT_SegReg:
+ if (op->type != YASM_INSN__OPERAND_SEGREG)
+ mismatch = 1;
+ break;
+ case OPT_CRReg:
+ if (op->type != YASM_INSN__OPERAND_REG ||
+ (op->data.reg & ~0xFUL) != X86_CRREG)
+ mismatch = 1;
+ break;
+ case OPT_DRReg:
+ if (op->type != YASM_INSN__OPERAND_REG ||
+ (op->data.reg & ~0xFUL) != X86_DRREG)
+ mismatch = 1;
+ break;
+ case OPT_TRReg:
+ if (op->type != YASM_INSN__OPERAND_REG ||
+ (op->data.reg & ~0xFUL) != X86_TRREG)
+ mismatch = 1;
+ break;
+ case OPT_ST0:
+ if (op->type != YASM_INSN__OPERAND_REG ||
+ op->data.reg != X86_FPUREG)
+ mismatch = 1;
+ break;
+ case OPT_Areg:
+ if (op->type != YASM_INSN__OPERAND_REG ||
+ (info_ops[i].size == OPS_8 &&
+ op->data.reg != (X86_REG8 | 0) &&
+ op->data.reg != (X86_REG8X | 0)) ||
+ (info_ops[i].size == OPS_16 &&
+ op->data.reg != (X86_REG16 | 0)) ||
+ (info_ops[i].size == OPS_32 &&
+ op->data.reg != (X86_REG32 | 0)) ||
+ (info_ops[i].size == OPS_64 &&
+ op->data.reg != (X86_REG64 | 0)))
+ mismatch = 1;
+ break;
+ case OPT_Creg:
+ if (op->type != YASM_INSN__OPERAND_REG ||
+ (info_ops[i].size == OPS_8 &&
+ op->data.reg != (X86_REG8 | 1) &&
+ op->data.reg != (X86_REG8X | 1)) ||
+ (info_ops[i].size == OPS_16 &&
+ op->data.reg != (X86_REG16 | 1)) ||
+ (info_ops[i].size == OPS_32 &&
+ op->data.reg != (X86_REG32 | 1)) ||
+ (info_ops[i].size == OPS_64 &&
+ op->data.reg != (X86_REG64 | 1)))
+ mismatch = 1;
+ break;
+ case OPT_Dreg:
+ if (op->type != YASM_INSN__OPERAND_REG ||
+ (info_ops[i].size == OPS_8 &&
+ op->data.reg != (X86_REG8 | 2) &&
+ op->data.reg != (X86_REG8X | 2)) ||
+ (info_ops[i].size == OPS_16 &&
+ op->data.reg != (X86_REG16 | 2)) ||
+ (info_ops[i].size == OPS_32 &&
+ op->data.reg != (X86_REG32 | 2)) ||
+ (info_ops[i].size == OPS_64 &&
+ op->data.reg != (X86_REG64 | 2)))
+ mismatch = 1;
+ break;
+ case OPT_CS:
+ if (op->type != YASM_INSN__OPERAND_SEGREG ||
+ (op->data.reg & 0xF) != 1)
+ mismatch = 1;
+ break;
+ case OPT_DS:
+ if (op->type != YASM_INSN__OPERAND_SEGREG ||
+ (op->data.reg & 0xF) != 3)
+ mismatch = 1;
+ break;
+ case OPT_ES:
+ if (op->type != YASM_INSN__OPERAND_SEGREG ||
+ (op->data.reg & 0xF) != 0)
+ mismatch = 1;
+ break;
+ case OPT_FS:
+ if (op->type != YASM_INSN__OPERAND_SEGREG ||
+ (op->data.reg & 0xF) != 4)
+ mismatch = 1;
+ break;
+ case OPT_GS:
+ if (op->type != YASM_INSN__OPERAND_SEGREG ||
+ (op->data.reg & 0xF) != 5)
+ mismatch = 1;
+ break;
+ case OPT_SS:
+ if (op->type != YASM_INSN__OPERAND_SEGREG ||
+ (op->data.reg & 0xF) != 2)
+ mismatch = 1;
+ break;
+ case OPT_CR4:
+ if (op->type != YASM_INSN__OPERAND_REG ||
+ op->data.reg != (X86_CRREG | 4))
+ mismatch = 1;
+ break;
+ case OPT_MemOffs:
+ if (op->type != YASM_INSN__OPERAND_MEMORY ||
+ yasm_expr__contains(op->data.ea->disp.abs,
+ YASM_EXPR_REG) ||
+ op->data.ea->pc_rel ||
+ (!op->data.ea->not_pc_rel && id_insn->default_rel &&
+ op->data.ea->disp.size != 64))
+ mismatch = 1;
+ break;
+ case OPT_Imm1:
+ if (op->type == YASM_INSN__OPERAND_IMM) {
+ const yasm_intnum *num;
+ num = yasm_expr_get_intnum(&op->data.val, 0);
+ if (!num || !yasm_intnum_is_pos1(num))
+ mismatch = 1;
+ } else
+ mismatch = 1;
+ break;
+ case OPT_ImmNotSegOff:
+ if (op->type != YASM_INSN__OPERAND_IMM ||
+ op->targetmod != 0 || op->seg)
+ mismatch = 1;
+ break;
+ case OPT_XMM0:
+ if (op->type != YASM_INSN__OPERAND_REG ||
+ op->data.reg != X86_XMMREG)
+ mismatch = 1;
+ break;
+ case OPT_MemrAX: {
+ const uintptr_t *regp;
+ if (op->type != YASM_INSN__OPERAND_MEMORY ||
+ !(regp = yasm_expr_get_reg(&op->data.ea->disp.abs, 0)) ||
+ (*regp != (X86_REG16 | 0) &&
+ *regp != (X86_REG32 | 0) &&
+ *regp != (X86_REG64 | 0)))
+ mismatch = 1;
+ break;
+ }
+ case OPT_MemEAX: {
+ const uintptr_t *regp;
+ if (op->type != YASM_INSN__OPERAND_MEMORY ||
+ !(regp = yasm_expr_get_reg(&op->data.ea->disp.abs, 0)) ||
+ *regp != (X86_REG32 | 0))
+ mismatch = 1;
+ break;
+ }
+ case OPT_MemXMMIndex:
+ if (op->type != YASM_INSN__OPERAND_MEMORY ||
+ !x86_expr_contains_simd(op->data.ea->disp.abs, 0))
+ mismatch = 1;
+ break;
+ case OPT_MemYMMIndex:
+ if (op->type != YASM_INSN__OPERAND_MEMORY ||
+ !x86_expr_contains_simd(op->data.ea->disp.abs, 1))
+ mismatch = 1;
+ break;
+ default:
+ yasm_internal_error(N_("invalid operand type"));
+ }
+
+ if (mismatch)
+ break;
+
+ /* Check operand size */
+ size = size_lookup[info_ops[i].size];
+ if (id_insn->parser == X86_PARSER_GAS) {
+ /* Require relaxed operands for GAS mode (don't allow
+ * per-operand sizing).
+ */
+ if (op->type == YASM_INSN__OPERAND_REG && op->size == 0) {
+ /* Register size must exactly match */
+ if (yasm_x86__get_reg_size(op->data.reg) != size)
+ mismatch = 1;
+ } else if ((info_ops[i].type == OPT_Imm
+ || info_ops[i].type == OPT_ImmNotSegOff
+ || info_ops[i].type == OPT_Imm1)
+ && !info_ops[i].relaxed
+ && info_ops[i].action != OPA_JmpRel)
+ mismatch = 1;
+ } else {
+ if (op->type == YASM_INSN__OPERAND_REG && op->size == 0) {
+ /* Register size must exactly match */
+ if ((bypass == 4 && i == 0) || (bypass == 5 && i == 1)
+ || (bypass == 6 && i == 2))
+ ;
+ else if (yasm_x86__get_reg_size(op->data.reg) != size)
+ mismatch = 1;
+ } else {
+ if ((bypass == 1 && i == 0) || (bypass == 2 && i == 1)
+ || (bypass == 3 && i == 2))
+ ;
+ else if (info_ops[i].relaxed) {
+ /* Relaxed checking */
+ if (size != 0 && op->size != size && op->size != 0)
+ mismatch = 1;
+ } else {
+ /* Strict checking */
+ if (op->size != size)
+ mismatch = 1;
+ }
+ }
+ }
+
+ if (mismatch)
+ break;
+
+ /* Check for 64-bit effective address size in NASM mode */
+ if (id_insn->parser != X86_PARSER_GAS &&
+ op->type == YASM_INSN__OPERAND_MEMORY) {
+ if (info_ops[i].eas64) {
+ if (op->data.ea->disp.size != 64)
+ mismatch = 1;
+ } else if (op->data.ea->disp.size == 64)
+ mismatch = 1;
+ }
+
+ if (mismatch)
+ break;
+
+ /* Check target modifier */
+ switch (info_ops[i].targetmod) {
+ case OPTM_None:
+ if (op->targetmod != 0)
+ mismatch = 1;
+ break;
+ case OPTM_Near:
+ if (op->targetmod != X86_NEAR)
+ mismatch = 1;
+ break;
+ case OPTM_Short:
+ if (op->targetmod != X86_SHORT)
+ mismatch = 1;
+ break;
+ case OPTM_Far:
+ if (op->targetmod != X86_FAR)
+ mismatch = 1;
+ break;
+ case OPTM_To:
+ if (op->targetmod != X86_TO)
+ mismatch = 1;
+ break;
+ default:
+ yasm_internal_error(N_("invalid target modifier type"));
+ }
+ }
+
+ if (!mismatch) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ return NULL;
+ return info;
+}
+
+static void
+x86_match_error(x86_id_insn *id_insn, yasm_insn_operand **ops,
+ yasm_insn_operand **rev_ops, const unsigned int *size_lookup)
+{
+ const x86_insn_info *i;
+ int ni;
+ int found;
+ int bypass;
+
+ /* Check for matching # of operands */
+ found = 0;
+ for (ni=id_insn->num_info, i=id_insn->group; ni>0; ni--, i++) {
+ if (id_insn->insn.num_operands == i->num_operands) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ yasm_error_set(YASM_ERROR_TYPE, N_("invalid number of operands"));
+ return;
+ }
+
+ for (bypass=1; bypass<9; bypass++) {
+ i = x86_find_match(id_insn, ops, rev_ops, size_lookup, bypass);
+ if (i)
+ break;
+ }
+
+ switch (bypass) {
+ case 1:
+ case 4:
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("invalid size for operand %d"), 1);
+ break;
+ case 2:
+ case 5:
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("invalid size for operand %d"), 2);
+ break;
+ case 3:
+ case 6:
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("invalid size for operand %d"), 3);
+ break;
+ case 7:
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("one of source operand 1 or 3 must match dest operand"));
+ break;
+ case 8:
+ {
+ unsigned int cpu0 = i->cpu0, cpu1 = i->cpu1, cpu2 = i->cpu2;
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("requires CPU%s"),
+ cpu_find_reverse(cpu0, cpu1, cpu2));
+ break;
+ }
+ default:
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("invalid combination of opcode and operands"));
+ }
+}
+
+static void
+x86_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ x86_id_insn *id_insn = (x86_id_insn *)bc->contents;
+ x86_insn *insn;
+ const x86_insn_info *info = id_insn->group;
+ unsigned int mode_bits = id_insn->mode_bits;
+ unsigned char *mod_data = id_insn->mod_data;
+ yasm_insn_operand *op, *ops[5], *rev_ops[5];
+ /*@null@*/ yasm_expr *imm;
+ unsigned char im_len;
+ unsigned char im_sign;
+ unsigned char spare;
+ unsigned char vexdata, vexreg;
+ unsigned int i;
+ unsigned int size_lookup[] = {0, 8, 16, 32, 64, 80, 128, 256, 0};
+ unsigned long do_postop = 0;
+
+ size_lookup[OPS_BITS] = mode_bits;
+
+ yasm_insn_finalize(&id_insn->insn);
+
+ /* Build local array of operands from list, since we know we have a max
+ * of 5 operands.
+ */
+ if (id_insn->insn.num_operands > 5) {
+ yasm_error_set(YASM_ERROR_TYPE, N_("too many operands"));
+ return;
+ }
+ ops[0] = ops[1] = ops[2] = ops[3] = ops[4] = NULL;
+ for (i = 0, op = yasm_insn_ops_first(&id_insn->insn);
+ op && i < id_insn->insn.num_operands;
+ op = yasm_insn_op_next(op), i++)
+ ops[i] = op;
+
+ /* If we're running in GAS mode, build a reverse array of the operands
+ * as most GAS instructions have reversed operands from Intel style.
+ */
+ if (id_insn->parser == X86_PARSER_GAS) {
+ rev_ops[0] = rev_ops[1] = rev_ops[2] = rev_ops[3] = rev_ops[4] = NULL;
+ for (i = id_insn->insn.num_operands-1,
+ op = yasm_insn_ops_first(&id_insn->insn);
+ op; op = yasm_insn_op_next(op), i--)
+ rev_ops[i] = op;
+ }
+
+ /* If we're running in GAS mode, look at the first insn_info to see
+ * if this is a relative jump (OPA_JmpRel). If so, run through the
+ * operands and adjust for dereferences / lack thereof.
+ */
+ if (id_insn->parser == X86_PARSER_GAS
+ && insn_operands[info->operands_index+0].action == OPA_JmpRel) {
+ for (i = 0, op = ops[0]; op; op = ops[++i]) {
+ if (!op->deref && (op->type == YASM_INSN__OPERAND_REG
+ || (op->type == YASM_INSN__OPERAND_MEMORY
+ && op->data.ea->strong)))
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("indirect call without `*'"));
+ if (!op->deref && op->type == YASM_INSN__OPERAND_MEMORY
+ && !op->data.ea->strong) {
+ /* Memory that is not dereferenced, and not strong, is
+ * actually an immediate for the purposes of relative jumps.
+ */
+ if (op->data.ea->segreg != 0)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("skipping prefixes on this instruction"));
+ imm = op->data.ea->disp.abs;
+ op->data.ea->disp.abs = NULL;
+ yasm_x86__ea_destroy(op->data.ea);
+ op->type = YASM_INSN__OPERAND_IMM;
+ op->data.val = imm;
+ }
+ }
+ }
+
+ info = x86_find_match(id_insn, ops, rev_ops, size_lookup, 0);
+
+ if (!info) {
+ /* Didn't find a match */
+ x86_match_error(id_insn, ops, rev_ops, size_lookup);
+ return;
+ }
+
+ if (id_insn->insn.num_operands > 0) {
+ switch (insn_operands[info->operands_index+0].action) {
+ case OPA_JmpRel:
+ /* Shortcut to JmpRel */
+ x86_finalize_jmp(bc, prev_bc, info);
+ return;
+ case OPA_JmpFar:
+ /* Shortcut to JmpFar */
+ x86_finalize_jmpfar(bc, prev_bc, info);
+ return;
+ }
+ }
+
+ /* Copy what we can from info */
+ insn = yasm_xmalloc(sizeof(x86_insn));
+ x86_finalize_common(&insn->common, info, mode_bits);
+ x86_finalize_opcode(&insn->opcode, info);
+ insn->x86_ea = NULL;
+ imm = NULL;
+ insn->def_opersize_64 = info->def_opersize_64;
+ insn->special_prefix = info->special_prefix;
+ spare = info->spare;
+ vexdata = 0;
+ vexreg = 0;
+ im_len = 0;
+ im_sign = 0;
+ insn->postop = X86_POSTOP_NONE;
+ insn->rex = 0;
+
+ /* Move VEX/XOP data (stored in special prefix) to separate location to
+ * allow overriding of special prefix by modifiers.
+ */
+ if ((insn->special_prefix & 0xF0) == 0xC0 ||
+ (insn->special_prefix & 0xF0) == 0x80) {
+ vexdata = insn->special_prefix;
+ insn->special_prefix = 0;
+ }
+
+ /* Apply modifiers */
+ for (i=0; i<NELEMS(info->modifiers); i++) {
+ switch (info->modifiers[i]) {
+ case MOD_Gap:
+ break;
+ case MOD_PreAdd:
+ insn->special_prefix += mod_data[i];
+ break;
+ case MOD_Op0Add:
+ insn->opcode.opcode[0] += mod_data[i];
+ break;
+ case MOD_Op1Add:
+ insn->opcode.opcode[1] += mod_data[i];
+ break;
+ case MOD_Op2Add:
+ insn->opcode.opcode[2] += mod_data[i];
+ break;
+ case MOD_SpAdd:
+ spare += mod_data[i];
+ break;
+ case MOD_OpSizeR:
+ insn->common.opersize = mod_data[i];
+ break;
+ case MOD_Imm8:
+ imm = yasm_expr_create_ident(yasm_expr_int(
+ yasm_intnum_create_uint(mod_data[i])), bc->line);
+ im_len = 8;
+ break;
+ case MOD_DOpS64R:
+ insn->def_opersize_64 = mod_data[i];
+ break;
+ case MOD_Op1AddSp:
+ insn->opcode.opcode[1] += mod_data[i]<<3;
+ break;
+ case MOD_SetVEX:
+ vexdata = mod_data[i];
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* In 64-bit mode, if opersize is 64 and default is not 64,
+ * force REX byte.
+ */
+ if (mode_bits == 64 && insn->common.opersize == 64 &&
+ insn->def_opersize_64 != 64)
+ insn->rex = 0x48;
+
+ /* Go through operands and assign */
+ if (id_insn->insn.num_operands > 0) {
+ yasm_insn_operand **use_ops = ops;
+ const x86_info_operand *info_ops =
+ &insn_operands[info->operands_index];
+
+ /* Use reversed operands in GAS mode if not otherwise specified */
+ if (id_insn->parser == X86_PARSER_GAS
+ && !(info->gas_flags & GAS_NO_REV))
+ use_ops = rev_ops;
+
+ for (i = 0, op = use_ops[0]; op && i<info->num_operands;
+ op = use_ops[++i]) {
+ switch (info_ops[i].action) {
+ case OPA_None:
+ /* Throw away the operand contents */
+ switch (op->type) {
+ case YASM_INSN__OPERAND_REG:
+ case YASM_INSN__OPERAND_SEGREG:
+ break;
+ case YASM_INSN__OPERAND_MEMORY:
+ yasm_x86__ea_destroy(op->data.ea);
+ break;
+ case YASM_INSN__OPERAND_IMM:
+ yasm_expr_destroy(op->data.val);
+ break;
+ }
+ break;
+ case OPA_EA:
+ switch (op->type) {
+ case YASM_INSN__OPERAND_REG:
+ insn->x86_ea =
+ yasm_x86__ea_create_reg(insn->x86_ea,
+ (unsigned long)op->data.reg, &insn->rex,
+ mode_bits);
+ break;
+ case YASM_INSN__OPERAND_SEGREG:
+ yasm_internal_error(
+ N_("invalid operand conversion"));
+ case YASM_INSN__OPERAND_MEMORY:
+ if (op->seg)
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("invalid segment in effective address"));
+ insn->x86_ea = (x86_effaddr *)op->data.ea;
+ if (info_ops[i].type == OPT_MemOffs)
+ /* Special-case for MOV MemOffs instruction */
+ yasm_x86__ea_set_disponly(insn->x86_ea);
+ else if (info_ops[i].type == OPT_MemXMMIndex) {
+ /* Remember VSIB mode */
+ insn->x86_ea->vsib_mode = 1;
+ insn->x86_ea->need_sib = 1;
+ } else if (info_ops[i].type == OPT_MemYMMIndex) {
+ /* Remember VSIB mode */
+ insn->x86_ea->vsib_mode = 2;
+ insn->x86_ea->need_sib = 1;
+ } else if (id_insn->default_rel &&
+ !op->data.ea->not_pc_rel &&
+ op->data.ea->segreg != 0x6404 &&
+ op->data.ea->segreg != 0x6505 &&
+ !yasm_expr__contains(
+ op->data.ea->disp.abs, YASM_EXPR_REG))
+ /* Enable default PC-rel if no regs and segreg
+ * is not FS or GS.
+ */
+ insn->x86_ea->ea.pc_rel = 1;
+ break;
+ case YASM_INSN__OPERAND_IMM:
+ insn->x86_ea =
+ yasm_x86__ea_create_imm(insn->x86_ea,
+ op->data.val,
+ size_lookup[info_ops[i].size]);
+ break;
+ }
+ break;
+ case OPA_EAVEX:
+ if (op->type != YASM_INSN__OPERAND_REG)
+ yasm_internal_error(N_("invalid operand conversion"));
+ insn->x86_ea =
+ yasm_x86__ea_create_reg(insn->x86_ea,
+ (unsigned long)op->data.reg, &insn->rex, mode_bits);
+ vexreg = op->data.reg & 0xF;
+ break;
+ case OPA_Imm:
+ if (op->seg)
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("immediate does not support segment"));
+ if (op->type == YASM_INSN__OPERAND_IMM) {
+ imm = op->data.val;
+ im_len = size_lookup[info_ops[i].size];
+ } else
+ yasm_internal_error(N_("invalid operand conversion"));
+ break;
+ case OPA_SImm:
+ if (op->seg)
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("immediate does not support segment"));
+ if (op->type == YASM_INSN__OPERAND_IMM) {
+ imm = op->data.val;
+ im_len = size_lookup[info_ops[i].size];
+ im_sign = 1;
+ } else
+ yasm_internal_error(N_("invalid operand conversion"));
+ break;
+ case OPA_Spare:
+ if (op->type == YASM_INSN__OPERAND_SEGREG)
+ spare = (unsigned char)(op->data.reg&7);
+ else if (op->type == YASM_INSN__OPERAND_REG) {
+ if (yasm_x86__set_rex_from_reg(&insn->rex, &spare,
+ op->data.reg, mode_bits, X86_REX_R))
+ return;
+ } else
+ yasm_internal_error(N_("invalid operand conversion"));
+ break;
+ case OPA_SpareVEX:
+ if (op->type != YASM_INSN__OPERAND_REG)
+ yasm_internal_error(N_("invalid operand conversion"));
+ if (yasm_x86__set_rex_from_reg(&insn->rex, &spare,
+ op->data.reg, mode_bits, X86_REX_R))
+ return;
+ vexreg = op->data.reg & 0xF;
+ break;
+ case OPA_Op0Add:
+ if (op->type == YASM_INSN__OPERAND_REG) {
+ unsigned char opadd;
+ if (yasm_x86__set_rex_from_reg(&insn->rex, &opadd,
+ op->data.reg, mode_bits, X86_REX_B))
+ return;
+ insn->opcode.opcode[0] += opadd;
+ } else
+ yasm_internal_error(N_("invalid operand conversion"));
+ break;
+ case OPA_Op1Add:
+ if (op->type == YASM_INSN__OPERAND_REG) {
+ unsigned char opadd;
+ if (yasm_x86__set_rex_from_reg(&insn->rex, &opadd,
+ op->data.reg, mode_bits, X86_REX_B))
+ return;
+ insn->opcode.opcode[1] += opadd;
+ } else
+ yasm_internal_error(N_("invalid operand conversion"));
+ break;
+ case OPA_SpareEA:
+ if (op->type == YASM_INSN__OPERAND_REG) {
+ insn->x86_ea =
+ yasm_x86__ea_create_reg(insn->x86_ea,
+ (unsigned long)op->data.reg, &insn->rex,
+ mode_bits);
+ if (!insn->x86_ea ||
+ yasm_x86__set_rex_from_reg(&insn->rex, &spare,
+ op->data.reg, mode_bits, X86_REX_R)) {
+ if (insn->x86_ea)
+ yasm_xfree(insn->x86_ea);
+ yasm_xfree(insn);
+ return;
+ }
+ } else
+ yasm_internal_error(N_("invalid operand conversion"));
+ break;
+ case OPA_AdSizeEA: {
+ const uintptr_t *regp = NULL;
+ /* Only implement this for OPT_MemrAX and OPT_MemEAX
+ * for now.
+ */
+ if (op->type != YASM_INSN__OPERAND_MEMORY ||
+ !(regp = yasm_expr_get_reg(&op->data.ea->disp.abs, 0)))
+ yasm_internal_error(N_("invalid operand conversion"));
+ /* 64-bit mode does not allow 16-bit addresses */
+ if (mode_bits == 64 && *regp == (X86_REG16 | 0))
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("16-bit addresses not supported in 64-bit mode"));
+ else if (*regp == (X86_REG16 | 0))
+ insn->common.addrsize = 16;
+ else if (*regp == (X86_REG32 | 0))
+ insn->common.addrsize = 32;
+ else if (mode_bits == 64 && *regp == (X86_REG64 | 0))
+ insn->common.addrsize = 64;
+ else
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("unsupported address size"));
+ yasm_x86__ea_destroy(op->data.ea);
+ break;
+ }
+ case OPA_VEX:
+ if (op->type != YASM_INSN__OPERAND_REG)
+ yasm_internal_error(N_("invalid operand conversion"));
+ vexreg = op->data.reg & 0xF;
+ break;
+ case OPA_VEXImmSrc:
+ if (op->type != YASM_INSN__OPERAND_REG)
+ yasm_internal_error(N_("invalid operand conversion"));
+
+ if (!imm) {
+ imm = yasm_expr_create_ident(
+ yasm_expr_int(
+ yasm_intnum_create_uint((op->data.reg << 4)
+ & 0xF0)),
+ bc->line);
+ } else {
+ imm = yasm_expr_create(
+ YASM_EXPR_OR,
+ yasm_expr_expr(yasm_expr_create(
+ YASM_EXPR_AND,
+ yasm_expr_expr(imm),
+ yasm_expr_int(yasm_intnum_create_uint(0x0F)),
+ bc->line)),
+ yasm_expr_int(
+ yasm_intnum_create_uint((op->data.reg << 4)
+ & 0xF0)),
+ bc->line);
+ }
+ im_len = 8;
+ break;
+ case OPA_VEXImm:
+ if (op->type != YASM_INSN__OPERAND_IMM)
+ yasm_internal_error(N_("invalid operand conversion"));
+
+ if (!imm)
+ imm = op->data.val;
+ else {
+ imm = yasm_expr_create(
+ YASM_EXPR_OR,
+ yasm_expr_expr(yasm_expr_create(
+ YASM_EXPR_AND,
+ yasm_expr_expr(op->data.val),
+ yasm_expr_int(yasm_intnum_create_uint(0x0F)),
+ bc->line)),
+ yasm_expr_expr(yasm_expr_create(
+ YASM_EXPR_AND,
+ yasm_expr_expr(imm),
+ yasm_expr_int(yasm_intnum_create_uint(0xF0)),
+ bc->line)),
+ bc->line);
+ }
+ im_len = 8;
+ break;
+ default:
+ yasm_internal_error(N_("unknown operand action"));
+ }
+
+ if (info_ops[i].size == OPS_BITS)
+ insn->common.opersize = (unsigned char)mode_bits;
+
+ switch (info_ops[i].post_action) {
+ case OPAP_None:
+ break;
+ case OPAP_SImm8:
+ /* Check operand strictness; if strict and non-8-bit,
+ * pre-emptively expand to full size.
+ * For unspecified size case, still optimize.
+ */
+ if (!(id_insn->force_strict || op->strict)
+ || op->size == 0)
+ insn->postop = X86_POSTOP_SIGNEXT_IMM8;
+ else if (op->size != 8) {
+ insn->opcode.opcode[0] =
+ insn->opcode.opcode[insn->opcode.len];
+ insn->opcode.len = 1;
+ }
+ break;
+ case OPAP_ShortMov:
+ do_postop = OPAP_ShortMov;
+ break;
+ case OPAP_A16:
+ insn->postop = X86_POSTOP_ADDRESS16;
+ break;
+ case OPAP_SImm32Avail:
+ do_postop = OPAP_SImm32Avail;
+ break;
+ default:
+ yasm_internal_error(
+ N_("unknown operand postponed action"));
+ }
+ }
+ }
+
+ if (insn->x86_ea) {
+ yasm_x86__ea_init(insn->x86_ea, spare, prev_bc);
+ for (i=0; i<id_insn->insn.num_segregs; i++)
+ yasm_ea_set_segreg(&insn->x86_ea->ea, id_insn->insn.segregs[i]);
+ } else if (id_insn->insn.num_segregs > 0 && insn->special_prefix == 0) {
+ if (id_insn->insn.num_segregs > 1)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("multiple segment overrides, using leftmost"));
+ insn->special_prefix = (unsigned char)
+ (id_insn->insn.segregs[id_insn->insn.num_segregs-1]>>8);
+ } else if (id_insn->insn.num_segregs > 0)
+ yasm_internal_error(N_("unhandled segment prefix"));
+
+ if (imm) {
+ insn->imm = yasm_xmalloc(sizeof(yasm_value));
+ if (yasm_value_finalize_expr(insn->imm, imm, prev_bc, im_len))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("immediate expression too complex"));
+ insn->imm->sign = im_sign;
+ } else
+ insn->imm = NULL;
+
+ yasm_x86__bc_apply_prefixes((x86_common *)insn, &insn->rex,
+ insn->def_opersize_64,
+ id_insn->insn.num_prefixes,
+ id_insn->insn.prefixes);
+
+ if (insn->postop == X86_POSTOP_ADDRESS16 && insn->common.addrsize) {
+ yasm_warn_set(YASM_WARN_GENERAL, N_("address size override ignored"));
+ insn->common.addrsize = 0;
+ }
+
+ /* Handle non-span-dependent post-ops here */
+ switch (do_postop) {
+ case OPAP_ShortMov:
+ /* Long (modrm+sib) mov instructions in amd64 can be optimized into
+ * short mov instructions if a 32-bit address override is applied in
+ * 64-bit mode to an EA of just an offset (no registers) and the
+ * target register is al/ax/eax/rax.
+ *
+ * We don't want to do this if we're in default rel mode.
+ */
+ if (!id_insn->default_rel &&
+ insn->common.mode_bits == 64 &&
+ insn->common.addrsize == 32 &&
+ (!insn->x86_ea->ea.disp.abs ||
+ !yasm_expr__contains(insn->x86_ea->ea.disp.abs,
+ YASM_EXPR_REG))) {
+ yasm_x86__ea_set_disponly(insn->x86_ea);
+ /* Make the short form permanent. */
+ insn->opcode.opcode[0] = insn->opcode.opcode[1];
+ }
+ insn->opcode.opcode[1] = 0; /* avoid possible confusion */
+ break;
+ case OPAP_SImm32Avail:
+ /* Used for 64-bit mov immediate, which can take a sign-extended
+ * imm32 as well as imm64 values. The imm32 form is put in the
+ * second byte of the opcode and its ModRM byte is put in the third
+ * byte of the opcode.
+ */
+ if (!insn->imm->abs ||
+ (yasm_expr_get_intnum(&insn->imm->abs, 0) &&
+ yasm_intnum_check_size(
+ yasm_expr_get_intnum(&insn->imm->abs, 0), 32, 0, 1))) {
+ /* Throwaway REX byte */
+ unsigned char rex_temp = 0;
+
+ /* Build ModRM EA - CAUTION: this depends on
+ * opcode 0 being a mov instruction!
+ */
+ insn->x86_ea = yasm_x86__ea_create_reg(insn->x86_ea,
+ (unsigned long)insn->opcode.opcode[0]-0xB8, &rex_temp, 64);
+
+ /* Make the imm32s form permanent. */
+ insn->opcode.opcode[0] = insn->opcode.opcode[1];
+ insn->imm->size = 32;
+ }
+ insn->opcode.opcode[1] = 0; /* avoid possible confusion */
+ break;
+ default:
+ break;
+ }
+
+ /* Convert to VEX/XOP prefixes if requested.
+ * To save space in the insn structure, the VEX/XOP prefix is written into
+ * special_prefix and the first 2 bytes of the instruction are set to
+ * the second two VEX/XOP bytes. During calc_len() it may be shortened to
+ * one VEX byte (this can only be done after knowledge of REX value); this
+ * further optimization is not possible for XOP.
+ */
+ if (vexdata) {
+ int xop = ((vexdata & 0xF0) == 0x80);
+ unsigned char vex1 = 0xE0; /* R=X=B=1, mmmmm=0 */
+ unsigned char vex2;
+
+ if (xop) {
+ /* Look at the first bytes of the opcode for the XOP mmmmm field.
+ * Leave R=X=B=1 for now.
+ */
+ if (insn->opcode.opcode[0] != 0x08 &&
+ insn->opcode.opcode[0] != 0x09 &&
+ insn->opcode.opcode[0] != 0x0A)
+ yasm_internal_error(N_("first opcode byte of XOP must be 0x08, 0x09, or 0x0A"));
+ vex1 |= insn->opcode.opcode[0];
+ /* Move opcode byte back one byte to make room for XOP prefix. */
+ insn->opcode.opcode[2] = insn->opcode.opcode[1];
+ } else {
+ /* Look at the first bytes of the opcode to see what leading bytes
+ * to encode in the VEX mmmmm field. Leave R=X=B=1 for now.
+ */
+ if (insn->opcode.opcode[0] != 0x0F)
+ yasm_internal_error(N_("first opcode byte of VEX must be 0x0F"));
+
+ if (insn->opcode.opcode[1] == 0x38)
+ vex1 |= 0x02; /* implied 0x0F 0x38 */
+ else if (insn->opcode.opcode[1] == 0x3A)
+ vex1 |= 0x03; /* implied 0x0F 0x3A */
+ else {
+ /* Originally a 0F-only opcode; move opcode byte back one
+ * position to make room for VEX prefix.
+ */
+ insn->opcode.opcode[2] = insn->opcode.opcode[1];
+ vex1 |= 0x01; /* implied 0x0F */
+ }
+ }
+
+ /* Check for update of special prefix by modifiers */
+ if (insn->special_prefix != 0) {
+ vexdata &= ~0x03;
+ switch (insn->special_prefix) {
+ case 0x66:
+ vexdata |= 0x01;
+ break;
+ case 0xF3:
+ vexdata |= 0x02;
+ break;
+ case 0xF2:
+ vexdata |= 0x03;
+ break;
+ default:
+ yasm_internal_error(N_("unrecognized special prefix"));
+ }
+ }
+
+ /* 2nd VEX byte is WvvvvLpp.
+ * W, L, pp come from vexdata
+ * vvvv comes from 1s complement of vexreg
+ */
+ vex2 = (((vexdata & 0x8) << 4) | /* W */
+ ((15 - (vexreg & 0xF)) << 3) | /* vvvv */
+ (vexdata & 0x7)); /* Lpp */
+
+ /* Save to special_prefix and opcode */
+ insn->special_prefix = xop ? 0x8F : 0xC4; /* VEX/XOP prefix */
+ insn->opcode.opcode[0] = vex1;
+ insn->opcode.opcode[1] = vex2;
+ insn->opcode.len = 3; /* two prefix bytes and 1 opcode byte */
+ }
+
+ x86_id_insn_clear_operands(id_insn);
+
+ /* Transform the bytecode */
+ yasm_x86__bc_transform_insn(bc, insn);
+}
+
+/* Static parse data structure for instructions */
+typedef struct insnprefix_parse_data {
+ const char *name;
+
+ /* instruction parse group - NULL if prefix */
+ /*@null@*/ const x86_insn_info *group;
+
+ /* For instruction, number of elements in group.
+ * For prefix, prefix type shifted right by 8.
+ */
+ unsigned int num_info:8;
+
+ /* For instruction, GAS suffix flags.
+ * For prefix, prefix value.
+ */
+ unsigned int flags:8;
+
+ /* Instruction modifier data. */
+ unsigned int mod_data0:8;
+ unsigned int mod_data1:8;
+ unsigned int mod_data2:8;
+
+ /* Tests against BITS==64 and AVX */
+ unsigned int misc_flags:6;
+
+ /* CPU flags */
+ unsigned int cpu0:6;
+ unsigned int cpu1:6;
+ unsigned int cpu2:6;
+} insnprefix_parse_data;
+
+/* Pull in all parse data */
+#include "x86insn_nasm.c"
+#include "x86insn_gas.c"
+
+static const char *
+cpu_find_reverse(unsigned int cpu0, unsigned int cpu1, unsigned int cpu2)
+{
+ static char cpuname[200];
+ wordptr cpu = BitVector_Create(128, TRUE);
+
+ if (cpu0 != CPU_Any)
+ BitVector_Bit_On(cpu, cpu0);
+ if (cpu1 != CPU_Any)
+ BitVector_Bit_On(cpu, cpu1);
+ if (cpu2 != CPU_Any)
+ BitVector_Bit_On(cpu, cpu2);
+
+ cpuname[0] = '\0';
+
+ if (BitVector_bit_test(cpu, CPU_Prot))
+ strcat(cpuname, " Protected");
+ if (BitVector_bit_test(cpu, CPU_Undoc))
+ strcat(cpuname, " Undocumented");
+ if (BitVector_bit_test(cpu, CPU_Obs))
+ strcat(cpuname, " Obsolete");
+ if (BitVector_bit_test(cpu, CPU_Priv))
+ strcat(cpuname, " Privileged");
+
+ if (BitVector_bit_test(cpu, CPU_FPU))
+ strcat(cpuname, " FPU");
+ if (BitVector_bit_test(cpu, CPU_MMX))
+ strcat(cpuname, " MMX");
+ if (BitVector_bit_test(cpu, CPU_SSE))
+ strcat(cpuname, " SSE");
+ if (BitVector_bit_test(cpu, CPU_SSE2))
+ strcat(cpuname, " SSE2");
+ if (BitVector_bit_test(cpu, CPU_SSE3))
+ strcat(cpuname, " SSE3");
+ if (BitVector_bit_test(cpu, CPU_3DNow))
+ strcat(cpuname, " 3DNow");
+ if (BitVector_bit_test(cpu, CPU_Cyrix))
+ strcat(cpuname, " Cyrix");
+ if (BitVector_bit_test(cpu, CPU_AMD))
+ strcat(cpuname, " AMD");
+ if (BitVector_bit_test(cpu, CPU_SMM))
+ strcat(cpuname, " SMM");
+ if (BitVector_bit_test(cpu, CPU_SVM))
+ strcat(cpuname, " SVM");
+ if (BitVector_bit_test(cpu, CPU_PadLock))
+ strcat(cpuname, " PadLock");
+ if (BitVector_bit_test(cpu, CPU_EM64T))
+ strcat(cpuname, " EM64T");
+ if (BitVector_bit_test(cpu, CPU_SSSE3))
+ strcat(cpuname, " SSSE3");
+ if (BitVector_bit_test(cpu, CPU_SSE41))
+ strcat(cpuname, " SSE4.1");
+ if (BitVector_bit_test(cpu, CPU_SSE42))
+ strcat(cpuname, " SSE4.2");
+
+ if (BitVector_bit_test(cpu, CPU_186))
+ strcat(cpuname, " 186");
+ if (BitVector_bit_test(cpu, CPU_286))
+ strcat(cpuname, " 286");
+ if (BitVector_bit_test(cpu, CPU_386))
+ strcat(cpuname, " 386");
+ if (BitVector_bit_test(cpu, CPU_486))
+ strcat(cpuname, " 486");
+ if (BitVector_bit_test(cpu, CPU_586))
+ strcat(cpuname, " 586");
+ if (BitVector_bit_test(cpu, CPU_686))
+ strcat(cpuname, " 686");
+ if (BitVector_bit_test(cpu, CPU_P3))
+ strcat(cpuname, " P3");
+ if (BitVector_bit_test(cpu, CPU_P4))
+ strcat(cpuname, " P4");
+ if (BitVector_bit_test(cpu, CPU_IA64))
+ strcat(cpuname, " IA64");
+ if (BitVector_bit_test(cpu, CPU_K6))
+ strcat(cpuname, " K6");
+ if (BitVector_bit_test(cpu, CPU_Athlon))
+ strcat(cpuname, " Athlon");
+ if (BitVector_bit_test(cpu, CPU_Hammer))
+ strcat(cpuname, " Hammer");
+
+ BitVector_Destroy(cpu);
+ return cpuname;
+}
+
+yasm_arch_insnprefix
+yasm_x86__parse_check_insnprefix(yasm_arch *arch, const char *id,
+ size_t id_len, unsigned long line,
+ yasm_bytecode **bc, uintptr_t *prefix)
+{
+ yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
+ /*@null@*/ const insnprefix_parse_data *pdata;
+ size_t i;
+ static char lcaseid[17];
+
+ *bc = (yasm_bytecode *)NULL;
+ *prefix = 0;
+
+ if (id_len > 16)
+ return YASM_ARCH_NOTINSNPREFIX;
+ for (i=0; i<id_len; i++)
+ lcaseid[i] = tolower(id[i]);
+ lcaseid[id_len] = '\0';
+
+ switch (PARSER(arch_x86)) {
+ case X86_PARSER_NASM:
+ pdata = insnprefix_nasm_find(lcaseid, id_len);
+ break;
+ case X86_PARSER_TASM:
+ 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;
+
+ if (pdata->group) {
+ x86_id_insn *id_insn;
+ wordptr cpu_enabled = arch_x86->cpu_enables[arch_x86->active_cpu];
+ unsigned int cpu0, cpu1, cpu2;
+
+ if (arch_x86->mode_bits != 64 && (pdata->misc_flags & ONLY_64)) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("`%s' is an instruction in 64-bit mode"), id);
+ return YASM_ARCH_NOTINSNPREFIX;
+ }
+ if (arch_x86->mode_bits == 64 && (pdata->misc_flags & NOT_64)) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("`%s' invalid in 64-bit mode"), id);
+ id_insn = yasm_xmalloc(sizeof(x86_id_insn));
+ yasm_insn_initialize(&id_insn->insn);
+ id_insn->group = not64_insn;
+ id_insn->cpu_enabled = cpu_enabled;
+ id_insn->mod_data[0] = 0;
+ id_insn->mod_data[1] = 0;
+ id_insn->mod_data[2] = 0;
+ id_insn->num_info = NELEMS(not64_insn);
+ id_insn->mode_bits = arch_x86->mode_bits;
+ id_insn->suffix = 0;
+ id_insn->misc_flags = 0;
+ id_insn->parser = PARSER(arch_x86);
+
+ id_insn->force_strict = arch_x86->force_strict != 0;
+ id_insn->default_rel = arch_x86->default_rel != 0;
+ *bc = yasm_bc_create_common(&x86_id_insn_callback, id_insn, line);
+ return YASM_ARCH_INSN;
+ }
+
+ cpu0 = pdata->cpu0;
+ cpu1 = pdata->cpu1;
+ cpu2 = pdata->cpu2;
+
+ if (!BitVector_bit_test(cpu_enabled, cpu0) ||
+ !BitVector_bit_test(cpu_enabled, cpu1) ||
+ !BitVector_bit_test(cpu_enabled, cpu2)) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("`%s' is an instruction in CPU%s"), id,
+ cpu_find_reverse(cpu0, cpu1, cpu2));
+ return YASM_ARCH_NOTINSNPREFIX;
+ }
+
+ id_insn = yasm_xmalloc(sizeof(x86_id_insn));
+ yasm_insn_initialize(&id_insn->insn);
+ id_insn->group = pdata->group;
+ id_insn->cpu_enabled = cpu_enabled;
+ id_insn->mod_data[0] = pdata->mod_data0;
+ id_insn->mod_data[1] = pdata->mod_data1;
+ id_insn->mod_data[2] = pdata->mod_data2;
+ id_insn->num_info = pdata->num_info;
+ id_insn->mode_bits = arch_x86->mode_bits;
+ id_insn->suffix = pdata->flags;
+ id_insn->misc_flags = pdata->misc_flags;
+ id_insn->parser = PARSER(arch_x86);
+ id_insn->force_strict = arch_x86->force_strict != 0;
+ id_insn->default_rel = arch_x86->default_rel != 0;
+ *bc = yasm_bc_create_common(&x86_id_insn_callback, id_insn, line);
+ return YASM_ARCH_INSN;
+ } else {
+ unsigned long type = pdata->num_info<<8;
+ unsigned long value = pdata->flags;
+
+ if (arch_x86->mode_bits == 64 && type == X86_OPERSIZE && value == 32) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ 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_set(YASM_ERROR_GENERAL,
+ N_("Cannot override address size to 16 bits in 64-bit mode"));
+ return YASM_ARCH_NOTINSNPREFIX;
+ }
+
+ if (arch_x86->mode_bits != 64 && (pdata->misc_flags & ONLY_64)) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("`%s' is a prefix in 64-bit mode"), id);
+ return YASM_ARCH_NOTINSNPREFIX;
+ }
+ *prefix = type|value;
+ return YASM_ARCH_PREFIX;
+ }
+}
+
+static void
+x86_id_insn_destroy(void *contents)
+{
+ x86_id_insn *id_insn = (x86_id_insn *)contents;
+ yasm_insn_delete(&id_insn->insn, yasm_x86__ea_destroy);
+ yasm_xfree(contents);
+}
+
+static void
+x86_id_insn_print(const void *contents, FILE *f, int indent_level)
+{
+ const x86_id_insn *id_insn = (const x86_id_insn *)contents;
+ yasm_insn_print(&id_insn->insn, f, indent_level);
+ /*TODO*/
+}
+
+/*@only@*/ yasm_bytecode *
+yasm_x86__create_empty_insn(yasm_arch *arch, unsigned long line)
+{
+ yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
+ x86_id_insn *id_insn = yasm_xmalloc(sizeof(x86_id_insn));
+
+ yasm_insn_initialize(&id_insn->insn);
+ id_insn->group = empty_insn;
+ id_insn->cpu_enabled = arch_x86->cpu_enables[arch_x86->active_cpu];
+ id_insn->mod_data[0] = 0;
+ id_insn->mod_data[1] = 0;
+ id_insn->mod_data[2] = 0;
+ id_insn->num_info = NELEMS(empty_insn);
+ id_insn->mode_bits = arch_x86->mode_bits;
+ id_insn->suffix = (PARSER(arch_x86) == X86_PARSER_GAS) ? SUF_Z : 0;
+ id_insn->misc_flags = 0;
+ id_insn->parser = PARSER(arch_x86);
+ id_insn->force_strict = arch_x86->force_strict != 0;
+ id_insn->default_rel = arch_x86->default_rel != 0;
+
+ return yasm_bc_create_common(&x86_id_insn_callback, id_insn, line);
+}
+
diff --git a/contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.c b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.c
new file mode 100644
index 0000000000..9b06fe3495
--- /dev/null
+++ b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.c
@@ -0,0 +1,107 @@
+/*
+ * CodeView debugging formats implementation for Yasm
+ *
+ * Copyright (C) 2006-2007 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 <util.h>
+
+#include <libyasm.h>
+
+#include "cv-dbgfmt.h"
+
+yasm_dbgfmt_module yasm_cv8_LTX_dbgfmt;
+
+
+static /*@null@*/ /*@only@*/ yasm_dbgfmt *
+cv_dbgfmt_create(yasm_object *object, yasm_dbgfmt_module *module, int version)
+{
+ yasm_dbgfmt_cv *dbgfmt_cv = yasm_xmalloc(sizeof(yasm_dbgfmt_cv));
+ size_t i;
+
+ dbgfmt_cv->dbgfmt.module = module;
+
+ dbgfmt_cv->filenames_allocated = 32;
+ dbgfmt_cv->filenames_size = 0;
+ dbgfmt_cv->filenames =
+ yasm_xmalloc(sizeof(cv_filename)*dbgfmt_cv->filenames_allocated);
+ for (i=0; i<dbgfmt_cv->filenames_allocated; i++) {
+ dbgfmt_cv->filenames[i].pathname = NULL;
+ dbgfmt_cv->filenames[i].filename = NULL;
+ dbgfmt_cv->filenames[i].str_off = 0;
+ dbgfmt_cv->filenames[i].info_off = 0;
+ }
+
+ dbgfmt_cv->version = version;
+
+ return (yasm_dbgfmt *)dbgfmt_cv;
+}
+
+static /*@null@*/ /*@only@*/ yasm_dbgfmt *
+cv8_dbgfmt_create(yasm_object *object)
+{
+ return cv_dbgfmt_create(object, &yasm_cv8_LTX_dbgfmt, 8);
+}
+
+static void
+cv_dbgfmt_destroy(/*@only@*/ yasm_dbgfmt *dbgfmt)
+{
+ yasm_dbgfmt_cv *dbgfmt_cv = (yasm_dbgfmt_cv *)dbgfmt;
+ size_t i;
+ for (i=0; i<dbgfmt_cv->filenames_size; i++) {
+ if (dbgfmt_cv->filenames[i].pathname)
+ yasm_xfree(dbgfmt_cv->filenames[i].pathname);
+ }
+ yasm_xfree(dbgfmt_cv->filenames);
+ yasm_xfree(dbgfmt);
+}
+
+/* Add a bytecode to a section, updating offset on insertion;
+ * no optimization necessary.
+ */
+yasm_bytecode *
+yasm_cv__append_bc(yasm_section *sect, yasm_bytecode *bc)
+{
+ yasm_bytecode *precbc = yasm_section_bcs_last(sect);
+ bc->offset = yasm_bc_next_offset(precbc);
+ yasm_section_bcs_append(sect, bc);
+ return precbc;
+}
+
+static void
+cv_dbgfmt_generate(yasm_object *object, yasm_linemap *linemap,
+ yasm_errwarns *errwarns)
+{
+ yasm_cv__generate_symline(object, linemap, errwarns);
+ yasm_cv__generate_type(object);
+}
+
+/* Define dbgfmt structure -- see dbgfmt.h for details */
+yasm_dbgfmt_module yasm_cv8_LTX_dbgfmt = {
+ "CodeView debugging format for VC8",
+ "cv8",
+ NULL, /* no directives */
+ cv8_dbgfmt_create,
+ cv_dbgfmt_destroy,
+ cv_dbgfmt_generate
+};
diff --git a/contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.h b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.h
new file mode 100644
index 0000000000..134b0b885b
--- /dev/null
+++ b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-dbgfmt.h
@@ -0,0 +1,58 @@
+/*
+ * CodeView debugging formats implementation for Yasm
+ *
+ * Copyright (C) 2006-2007 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.
+ */
+#ifndef YASM_CV_DBGFMT_H
+#define YASM_CV_DBGFMT_H
+
+typedef struct {
+ char *pathname; /* full pathname (drive+basepath+filename) */
+ char *filename; /* filename as yasm knows it internally */
+ unsigned long str_off; /* offset into pathname string table */
+ unsigned long info_off; /* offset into source info table */
+ unsigned char digest[16]; /* MD5 digest of source file */
+} cv_filename;
+
+/* Global data */
+typedef struct yasm_dbgfmt_cv {
+ yasm_dbgfmt_base dbgfmt; /* base structure */
+
+ cv_filename *filenames;
+ size_t filenames_size;
+ size_t filenames_allocated;
+
+ int version;
+} yasm_dbgfmt_cv;
+
+yasm_bytecode *yasm_cv__append_bc(yasm_section *sect, yasm_bytecode *bc);
+
+/* Symbol/Line number functions */
+yasm_section *yasm_cv__generate_symline
+ (yasm_object *object, yasm_linemap *linemap, yasm_errwarns *errwarns);
+
+/* Type functions */
+yasm_section *yasm_cv__generate_type(yasm_object *object);
+
+#endif
diff --git a/contrib/tools/yasm/modules/dbgfmts/codeview/cv-symline.c b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-symline.c
new file mode 100644
index 0000000000..8d7030221f
--- /dev/null
+++ b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-symline.c
@@ -0,0 +1,1102 @@
+/*
+ * CodeView debugging format - symbol and line information
+ *
+ * Copyright (C) 2006-2007 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.
+ * 3. Neither the name of the author nor the names of other contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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 <util.h>
+
+#include <libyasm.h>
+
+#include "cv-dbgfmt.h"
+
+enum cv8_symheadtype {
+ CV8_DEBUG_SYMS = 0xF1, /* CV5 symbol information */
+ CV8_LINE_NUMS = 0xF2, /* line numbers for a section */
+ CV8_FILE_STRTAB = 0xF3, /* filename string table */
+ CV8_FILE_INFO = 0xF4 /* source file info */
+};
+
+enum cv_symtype {
+ /* Non-modal Symbols */
+ CV_S_COMPILE = 0x0001, /* Compile Flag */
+ CV_S_REGISTER = 0x0002, /* Register */
+ CV_S_CONSTANT = 0x0003, /* Constant */
+ CV_S_UDT = 0x0004, /* User-defined Type */
+ CV_S_SSEARCH = 0x0005, /* Start Search */
+ CV_S_END = 0x0006, /* End of Block */
+ CV_S_SKIP = 0x0007, /* Skip Record */
+ CV_S_OBJNAME = 0x0009, /* Object File Name */
+ CV_S_ENDARG = 0x000a, /* End of Arguments */
+ CV_S_COBOLUDT = 0x000b, /* COBOL User-defined Type */
+ CV_S_MANYREG = 0x000c, /* Many Registers */
+ CV_S_RETURN = 0x000d, /* Function Return */
+ CV_S_ENTRYTHIS = 0x000e, /* "this" at Method Entry */
+
+ /* Symbols for 16:16 Segmented Architectures */
+ CV_S_BPREL16 = 0x0100, /* BP Relative 16:16 */
+ CV_S_LDATA16 = 0x0101, /* Local Data 16:16 */
+ CV_S_GDATA16 = 0x0102, /* Global Data Symbol 16:16 */
+ CV_S_PUB16 = 0x0103, /* Public Symbol 16:16 */
+ CV_S_LPROC16 = 0x0104, /* Local Start 16:16 */
+ CV_S_GPROC16 = 0x0105, /* Global Start 16:16 */
+ CV_S_THUNK16 = 0x0106, /* Thunk Start 16:16 */
+ CV_S_BLOCK16 = 0x0107, /* Block Start 16:16 */
+ CV_S_WITH16 = 0x0108, /* With Start 16:16 */
+ CV_S_LABEL16 = 0x0109, /* Code Label 16:16 */
+ CV_S_CEXMODEL16 = 0x0110, /* Change Execution Model 16:16 */
+ CV_S_VFTPATH16 = 0x010b, /* Virtual Function Table Path 16:16 */
+ CV_S_REGREL16 = 0x010c, /* Register Relative 16:16 */
+
+ /* Symbols for 16:32 Segmented Architectures */
+ CV_S_BPREL32 = 0x0200, /* BP Relative 16:32 */
+ CV_S_LDATA32 = 0x0201, /* Local Data 16:32 */
+ CV_S_GDATA32 = 0x0202, /* Global Data Symbol 16:32 */
+ CV_S_PUB32 = 0x0203, /* Public Symbol 16:32 */
+ CV_S_LPROC32 = 0x0204, /* Local Start 16:32 */
+ CV_S_GPROC32 = 0x0205, /* Global Start 16:32 */
+ CV_S_THUNK32 = 0x0206, /* Thunk Start 16:32 */
+ CV_S_BLOCK32 = 0x0207, /* Block Start 16:32 */
+ CV_S_WITH32 = 0x0208, /* With Start 16:32 */
+ CV_S_LABEL32 = 0x0209, /* Code Label 16:32 */
+ CV_S_CEXMODEL32 = 0x0210, /* Change Execution Model 16:32 */
+ CV_S_VFTPATH32 = 0x020b, /* Virtual Function Table Path 16:32 */
+ CV_S_REGREL32 = 0x020c, /* Register Relative 16:32 */
+ CV_S_LTHREAD32 = 0x020d, /* Local Thread Storage 16:32 */
+ CV_S_GTHREAD32 = 0x020e, /* Global Thread Storage 16:32 */
+
+ /* Symbols for MIPS */
+ CV_S_LPROCMIPS = 0x0300, /* Local procedure start MIPS */
+ CV_S_GPROCMIPS = 0x0301, /* Global procedure start MIPS */
+
+ /* Symbols for CV8 - strings are 0 terminated rather than length-prefix.
+ * Incomplete and unofficial.
+ */
+ CV8_S_OBJNAME = 0x1101, /* Object File Name */
+ CV8_S_LABEL32 = 0x1105, /* Code Label 16:32 */
+ CV8_S_LDATA32 = 0x110c, /* Local Data 16:32 */
+ CV8_S_GDATA32 = 0x110d, /* Global Data 16:32 */
+ CV8_S_LPROC32 = 0x1110, /* Local Start 16:32 */
+ CV8_S_COMPILE = 0x1116 /* Compile Flag */
+};
+
+typedef struct cv8_symhead {
+ enum cv8_symheadtype type;
+ yasm_bytecode *start_prevbc;
+ yasm_bytecode *end_prevbc;
+ int first; /* nonzero if first symhead in section */
+} cv8_symhead;
+
+typedef struct cv8_fileinfo {
+ const cv_filename *fn;
+} cv8_fileinfo;
+
+/* Note: each line number group is associated with a file AND a section */
+typedef struct cv8_linepair {
+ unsigned long offset;
+ unsigned long line;
+} cv8_linepair;
+
+/* Decrease linked list overhead a bit doing it this way */
+typedef struct cv8_lineset {
+ STAILQ_ENTRY(cv8_lineset) link;
+ cv8_linepair pairs[126];
+ size_t num_pairs;
+} cv8_lineset;
+
+/* Note: Due to line number sorting requirements (by section offset it seems)
+ * one file may need more than one record per section. */
+typedef struct cv8_lineinfo {
+ STAILQ_ENTRY(cv8_lineinfo) link;
+ const cv_filename *fn; /* filename associated with line numbers */
+ yasm_section *sect; /* section line numbers are for */
+ yasm_symrec *sectsym; /* symbol for beginning of sect */
+ unsigned long num_linenums;
+ int first_in_sect; /* First lineinfo for this section. */
+ STAILQ_HEAD(cv8_lineset_head, cv8_lineset) linesets;
+} cv8_lineinfo;
+
+/* Symbols use a bit of meta-programming to encode formats: each character
+ * of format represents the output generated, as follows:
+ * 'b' : 1 byte value (integer)
+ * 'h' : 2 byte value (integer)
+ * 'w' : 4 byte value (integer)
+ * 'Y' : symrec SECREL+SECTION (pointer)
+ * 'T' : type index (integer)
+ * 'S' : length-prefixed string (pointer)
+ * 'Z' : 0-terminated string (pointer)
+ */
+typedef struct cv_sym {
+ enum cv_symtype type;
+ const char *format;
+ union {
+ unsigned long i;
+ void *p;
+ } args[10];
+} cv_sym;
+
+/* Bytecode callback function prototypes */
+static void cv8_symhead_bc_destroy(void *contents);
+static void cv8_symhead_bc_print(const void *contents, FILE *f,
+ int indent_level);
+static int cv8_symhead_bc_calc_len
+ (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
+static int cv8_symhead_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static void cv8_fileinfo_bc_destroy(void *contents);
+static void cv8_fileinfo_bc_print(const void *contents, FILE *f,
+ int indent_level);
+static int cv8_fileinfo_bc_calc_len
+ (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
+static int cv8_fileinfo_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static void cv8_lineinfo_bc_destroy(void *contents);
+static void cv8_lineinfo_bc_print(const void *contents, FILE *f,
+ int indent_level);
+static int cv8_lineinfo_bc_calc_len
+ (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
+static int cv8_lineinfo_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static void cv_sym_bc_destroy(void *contents);
+static void cv_sym_bc_print(const void *contents, FILE *f, int indent_level);
+static int cv_sym_bc_calc_len
+ (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
+static int cv_sym_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+/* Bytecode callback structures */
+static const yasm_bytecode_callback cv8_symhead_bc_callback = {
+ cv8_symhead_bc_destroy,
+ cv8_symhead_bc_print,
+ yasm_bc_finalize_common,
+ NULL,
+ cv8_symhead_bc_calc_len,
+ yasm_bc_expand_common,
+ cv8_symhead_bc_tobytes,
+ 0
+};
+
+static const yasm_bytecode_callback cv8_fileinfo_bc_callback = {
+ cv8_fileinfo_bc_destroy,
+ cv8_fileinfo_bc_print,
+ yasm_bc_finalize_common,
+ NULL,
+ cv8_fileinfo_bc_calc_len,
+ yasm_bc_expand_common,
+ cv8_fileinfo_bc_tobytes,
+ 0
+};
+
+static const yasm_bytecode_callback cv8_lineinfo_bc_callback = {
+ cv8_lineinfo_bc_destroy,
+ cv8_lineinfo_bc_print,
+ yasm_bc_finalize_common,
+ NULL,
+ cv8_lineinfo_bc_calc_len,
+ yasm_bc_expand_common,
+ cv8_lineinfo_bc_tobytes,
+ 0
+};
+
+static const yasm_bytecode_callback cv_sym_bc_callback = {
+ cv_sym_bc_destroy,
+ cv_sym_bc_print,
+ yasm_bc_finalize_common,
+ NULL,
+ cv_sym_bc_calc_len,
+ yasm_bc_expand_common,
+ cv_sym_bc_tobytes,
+ 0
+};
+
+static cv8_symhead *cv8_add_symhead(yasm_section *sect, unsigned long type,
+ int first);
+static void cv8_set_symhead_end(cv8_symhead *head, yasm_bytecode *end_prevbc);
+
+static yasm_bytecode *cv8_add_fileinfo
+ (yasm_section *sect, const cv_filename *fn);
+
+static unsigned long cv_sym_size(const cv_sym *cvs);
+
+
+static cv_sym *
+cv8_add_sym_objname(yasm_section *sect, /*@keep@*/ char *objname)
+{
+ yasm_bytecode *bc;
+ cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym));
+ cvs->type = CV8_S_OBJNAME;
+ cvs->format = "wZ";
+ cvs->args[0].i = 0; /* signature (0=asm) */
+ cvs->args[1].p = objname; /* object filename */
+
+ bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0);
+ bc->len = cv_sym_size(cvs);
+ yasm_cv__append_bc(sect, bc);
+ return cvs;
+}
+
+static cv_sym *
+cv8_add_sym_compile(yasm_object *object, yasm_section *sect,
+ /*@keep@*/ char *creator)
+{
+ yasm_bytecode *bc;
+ cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym));
+ cvs->type = CV8_S_COMPILE;
+ cvs->format = "wwwwZh";
+ cvs->args[0].i = 3; /* language (3=Masm) */
+
+ /* target processor; 0xD0 = AMD64 */
+ if (strcmp(yasm_arch_keyword(object->arch), "x86") == 0) {
+ if (strcmp(yasm_arch_get_machine(object->arch), "amd64") == 0)
+ cvs->args[1].i = 0xD0;
+ else
+ cvs->args[1].i = 0x6; /* 686, FIXME */
+ } else
+ cvs->args[1].i = 0; /* XXX: unknown */
+
+ cvs->args[2].i = 0; /* flags (assume 0 for now) */
+ cvs->args[3].i = 0; /* creator version number (assume 0 for now) */
+ cvs->args[4].p = creator; /* creator string */
+ cvs->args[5].i = 0; /* no pairs of key/value */
+
+ bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0);
+ bc->len = cv_sym_size(cvs);
+ yasm_cv__append_bc(sect, bc);
+ return cvs;
+}
+
+static cv_sym *
+cv8_add_sym_label(yasm_section *sect, yasm_symrec *sym)
+{
+ yasm_bytecode *bc;
+ cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym));
+ cvs->type = CV8_S_LABEL32;
+ cvs->format = "YbZ";
+ cvs->args[0].p = sym; /* symrec for label */
+ cvs->args[1].i = 0; /* flags (assume 0 for now) */
+ cvs->args[2].p = yasm__xstrdup(yasm_symrec_get_name(sym));
+
+ bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0);
+ bc->len = cv_sym_size(cvs);
+ yasm_cv__append_bc(sect, bc);
+ return cvs;
+}
+
+static cv_sym *
+cv8_add_sym_data(yasm_section *sect, unsigned long type, yasm_symrec *sym,
+ int is_global)
+{
+ yasm_bytecode *bc;
+ cv_sym *cvs = yasm_xmalloc(sizeof(cv_sym));
+ cvs->type = is_global ? CV8_S_GDATA32 : CV8_S_LDATA32;
+ cvs->format = "wYZ";
+ cvs->args[0].i = type; /* type index */
+ cvs->args[1].p = sym; /* symrec for label */
+ cvs->args[2].p = yasm__xstrdup(yasm_symrec_get_name(sym));
+
+ bc = yasm_bc_create_common(&cv_sym_bc_callback, cvs, 0);
+ bc->len = cv_sym_size(cvs);
+ yasm_cv__append_bc(sect, bc);
+ return cvs;
+}
+
+static size_t
+cv_dbgfmt_add_file(yasm_dbgfmt_cv *dbgfmt_cv, size_t filenum,
+ const char *filename)
+{
+ char *pathname;
+ size_t i;
+ yasm_md5_context context;
+ FILE *f;
+ unsigned char *buf;
+ size_t len;
+
+ /* Put the filename into the filename table */
+ if (filenum == 0) {
+ /* Look to see if we already have that filename in the table */
+ for (; filenum<dbgfmt_cv->filenames_size; filenum++) {
+ if (!dbgfmt_cv->filenames[filenum].filename ||
+ strcmp(dbgfmt_cv->filenames[filenum].filename, filename) == 0)
+ break;
+ }
+ } else
+ filenum--; /* array index is 0-based */
+
+ /* Realloc table if necessary */
+ if (filenum >= dbgfmt_cv->filenames_allocated) {
+ size_t old_allocated = dbgfmt_cv->filenames_allocated;
+ dbgfmt_cv->filenames_allocated = filenum+32;
+ dbgfmt_cv->filenames = yasm_xrealloc(dbgfmt_cv->filenames,
+ sizeof(cv_filename)*dbgfmt_cv->filenames_allocated);
+ for (i=old_allocated; i<dbgfmt_cv->filenames_allocated; i++) {
+ dbgfmt_cv->filenames[i].pathname = NULL;
+ dbgfmt_cv->filenames[i].filename = NULL;
+ dbgfmt_cv->filenames[i].str_off = 0;
+ dbgfmt_cv->filenames[i].info_off = 0;
+ }
+ }
+
+ /* Calculate MD5 checksum of file */
+ buf = yasm_xmalloc(1024);
+ yasm_md5_init(&context);
+ f = fopen(filename, "rb");
+ if (!f)
+ yasm__fatal(N_("codeview: could not open source file"));
+ while ((len = fread(buf, 1, 1024, f)) > 0)
+ yasm_md5_update(&context, buf, (unsigned long)len);
+ yasm_md5_final(dbgfmt_cv->filenames[filenum].digest, &context);
+ fclose(f);
+ yasm_xfree(buf);
+
+ /* Actually save in table */
+ if (dbgfmt_cv->filenames[filenum].pathname)
+ yasm_xfree(dbgfmt_cv->filenames[filenum].pathname);
+ if (dbgfmt_cv->filenames[filenum].filename)
+ yasm_xfree(dbgfmt_cv->filenames[filenum].filename);
+
+ pathname = yasm__abspath(filename);
+ dbgfmt_cv->filenames[filenum].pathname = pathname;
+ dbgfmt_cv->filenames[filenum].filename = yasm__xstrdup(filename);
+
+ /* Update table size */
+ if (filenum >= dbgfmt_cv->filenames_size)
+ dbgfmt_cv->filenames_size = filenum + 1;
+
+ return filenum;
+}
+
+static yasm_bytecode *
+cv_append_str(yasm_section *sect, const char *str)
+{
+ yasm_datavalhead dvs;
+ yasm_bytecode *bc;
+
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_string(yasm__xstrdup(str),
+ strlen(str)));
+ bc = yasm_bc_create_data(&dvs, 1, 1, NULL, 0);
+ yasm_bc_finalize(bc, yasm_cv__append_bc(sect, bc));
+ yasm_bc_calc_len(bc, NULL, NULL);
+ return bc;
+}
+
+typedef struct cv_line_info {
+ yasm_section *debug_symline;
+ yasm_object *object;
+ yasm_dbgfmt_cv *dbgfmt_cv;
+ yasm_linemap *linemap;
+ yasm_errwarns *errwarns;
+ unsigned int num_lineinfos;
+ STAILQ_HEAD(cv8_lineinfo_head, cv8_lineinfo) cv8_lineinfos;
+ /*@null@*/ cv8_lineinfo *cv8_cur_li;
+ /*@null@*/ cv8_lineset *cv8_cur_ls;
+} cv_line_info;
+
+static int
+cv_generate_line_bc(yasm_bytecode *bc, /*@null@*/ void *d)
+{
+ cv_line_info *info = (cv_line_info *)d;
+ yasm_dbgfmt_cv *dbgfmt_cv = info->dbgfmt_cv;
+ size_t i;
+ const char *filename;
+ unsigned long line;
+ /*@null@*/ yasm_bytecode *nextbc = yasm_bc__next(bc);
+ yasm_section *sect = yasm_bc_get_section(bc);
+
+ if (nextbc && bc->offset == nextbc->offset)
+ return 0;
+
+ yasm_linemap_lookup(info->linemap, bc->line, &filename, &line);
+
+ if (!info->cv8_cur_li
+ || strcmp(filename, info->cv8_cur_li->fn->filename) != 0) {
+ yasm_bytecode *sectbc;
+ char symname[8];
+ int first_in_sect = !info->cv8_cur_li;
+
+ /* Find file */
+ for (i=0; i<dbgfmt_cv->filenames_size; i++) {
+ if (strcmp(filename, dbgfmt_cv->filenames[i].filename) == 0)
+ break;
+ }
+ if (i >= dbgfmt_cv->filenames_size)
+ yasm_internal_error(N_("could not find filename in table"));
+
+ /* and create new lineinfo structure */
+ info->cv8_cur_li = yasm_xmalloc(sizeof(cv8_lineinfo));
+ info->cv8_cur_li->fn = &dbgfmt_cv->filenames[i];
+ info->cv8_cur_li->sect = sect;
+ info->cv8_cur_li->first_in_sect = first_in_sect;
+ sectbc = yasm_section_bcs_first(sect);
+ if (sectbc->symrecs && sectbc->symrecs[0])
+ info->cv8_cur_li->sectsym = sectbc->symrecs[0];
+ else {
+ sprintf(symname, ".%06u", info->num_lineinfos++);
+ info->cv8_cur_li->sectsym =
+ yasm_symtab_define_label(info->object->symtab, symname, sectbc,
+ 1, 0);
+ }
+ info->cv8_cur_li->num_linenums = 0;
+ STAILQ_INIT(&info->cv8_cur_li->linesets);
+ STAILQ_INSERT_TAIL(&info->cv8_lineinfos, info->cv8_cur_li, link);
+ info->cv8_cur_ls = NULL;
+ }
+
+ /* build new lineset if necessary */
+ if (!info->cv8_cur_ls || info->cv8_cur_ls->num_pairs >= 126) {
+ info->cv8_cur_ls = yasm_xmalloc(sizeof(cv8_lineset));
+ info->cv8_cur_ls->num_pairs = 0;
+ STAILQ_INSERT_TAIL(&info->cv8_cur_li->linesets, info->cv8_cur_ls, link);
+ }
+
+ /* add linepair for this bytecode */
+ info->cv8_cur_ls->pairs[info->cv8_cur_ls->num_pairs].offset = bc->offset;
+ info->cv8_cur_ls->pairs[info->cv8_cur_ls->num_pairs].line =
+ 0x80000000 | line;
+ info->cv8_cur_ls->num_pairs++;
+ info->cv8_cur_li->num_linenums++;
+
+ return 0;
+}
+
+static int
+cv_generate_line_section(yasm_section *sect, /*@null@*/ void *d)
+{
+ cv_line_info *info = (cv_line_info *)d;
+
+ if (!yasm_section_is_code(sect))
+ return 0; /* not code, so no line data for this section */
+
+ info->cv8_cur_li = NULL;
+ info->cv8_cur_ls = NULL;
+
+ yasm_section_bcs_traverse(sect, info->errwarns, info, cv_generate_line_bc);
+
+ return 0;
+}
+
+static int
+cv_generate_filename(const char *filename, void *d)
+{
+ cv_dbgfmt_add_file((yasm_dbgfmt_cv *)d, 0, filename);
+ return 0;
+}
+
+static int
+cv_generate_sym(yasm_symrec *sym, void *d)
+{
+ cv_line_info *info = (cv_line_info *)d;
+ yasm_bytecode *precbc;
+ const char *name = yasm_symrec_get_name(sym);
+
+ /* only care about labels (for now). Don't put in symbols starting with
+ * ".", as these are typically internally generated ones (like section
+ * symbols).
+ */
+ if (name[0] == '.' || !yasm_symrec_get_label(sym, &precbc))
+ return 0;
+
+ /* TODO: add data types; until then, just mark everything as UBYTE */
+ if (yasm_section_is_code(yasm_bc_get_section(precbc)))
+ cv8_add_sym_label(info->debug_symline, sym);
+ else
+ cv8_add_sym_data(info->debug_symline, 0x20, sym,
+ yasm_symrec_get_visibility(sym) & YASM_SYM_GLOBAL?1:0);
+ return 0;
+}
+
+yasm_section *
+yasm_cv__generate_symline(yasm_object *object, yasm_linemap *linemap,
+ yasm_errwarns *errwarns)
+{
+ yasm_dbgfmt_cv *dbgfmt_cv = (yasm_dbgfmt_cv *)object->dbgfmt;
+ cv_line_info info;
+ int new;
+ size_t i;
+ cv8_symhead *head;
+ cv8_lineinfo *li;
+ yasm_bytecode *bc;
+ unsigned long off;
+
+ /* Generate filenames based on linemap */
+ yasm_linemap_traverse_filenames(linemap, dbgfmt_cv,
+ cv_generate_filename);
+
+ info.object = object;
+ info.dbgfmt_cv = dbgfmt_cv;
+ info.linemap = linemap;
+ info.errwarns = errwarns;
+ info.debug_symline =
+ yasm_object_get_general(object, ".debug$S", 1, 0, 0, &new, 0);
+ info.num_lineinfos = 0;
+ STAILQ_INIT(&info.cv8_lineinfos);
+ info.cv8_cur_li = NULL;
+ info.cv8_cur_ls = NULL;
+
+ /* source filenames string table */
+ head = cv8_add_symhead(info.debug_symline, CV8_FILE_STRTAB, 1);
+ cv_append_str(info.debug_symline, "");
+ off = 1;
+ for (i=0; i<dbgfmt_cv->filenames_size; i++) {
+ if (!dbgfmt_cv->filenames[i].pathname) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("codeview file number %d unassigned"), i+1);
+ yasm_errwarn_propagate(errwarns, 0);
+ continue;
+ }
+ bc = cv_append_str(info.debug_symline,
+ dbgfmt_cv->filenames[i].pathname);
+ dbgfmt_cv->filenames[i].str_off = off;
+ off += bc->len;
+ }
+ cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline));
+
+ /* Align 4 */
+ bc = yasm_bc_create_align
+ (yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(4)), 0),
+ NULL, NULL, NULL, 0);
+ yasm_bc_finalize(bc, yasm_cv__append_bc(info.debug_symline, bc));
+ yasm_bc_calc_len(bc, NULL, NULL);
+
+ /* source file info table */
+ head = cv8_add_symhead(info.debug_symline, CV8_FILE_INFO, 0);
+ off = 0;
+ for (i=0; i<dbgfmt_cv->filenames_size; i++) {
+ if (!dbgfmt_cv->filenames[i].pathname)
+ continue;
+ bc = cv8_add_fileinfo(info.debug_symline, &dbgfmt_cv->filenames[i]);
+ dbgfmt_cv->filenames[i].info_off = off;
+ off += bc->len;
+ }
+ cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline));
+
+ /* Already aligned 4 */
+
+ /* Generate line numbers for sections */
+ yasm_object_sections_traverse(object, (void *)&info,
+ cv_generate_line_section);
+
+ /* Output line numbers for sections */
+ head = NULL;
+ STAILQ_FOREACH(li, &info.cv8_lineinfos, link) {
+ if (li->first_in_sect) {
+ if (head)
+ cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline));
+ head = cv8_add_symhead(info.debug_symline, CV8_LINE_NUMS, 0);
+ }
+ bc = yasm_bc_create_common(&cv8_lineinfo_bc_callback, li, 0);
+ bc->len = (li->first_in_sect ? 24 : 12) + li->num_linenums*8;
+ yasm_cv__append_bc(info.debug_symline, bc);
+ }
+ if (head)
+ cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline));
+
+ /* Already aligned 4 */
+
+ /* Output debugging symbols */
+ head = cv8_add_symhead(info.debug_symline, CV8_DEBUG_SYMS, 0);
+ /* add object and compile flag first */
+ cv8_add_sym_objname(info.debug_symline,
+ yasm__abspath(object->obj_filename));
+ if (getenv("YASM_TEST_SUITE"))
+ cv8_add_sym_compile(object, info.debug_symline,
+ yasm__xstrdup("yasm HEAD"));
+ else
+ cv8_add_sym_compile(object, info.debug_symline,
+ yasm__xstrdup(PACKAGE_STRING));
+ /* then iterate through symbol table */
+ yasm_symtab_traverse(object->symtab, &info, cv_generate_sym);
+ cv8_set_symhead_end(head, yasm_section_bcs_last(info.debug_symline));
+
+ /* Align 4 at end */
+ bc = yasm_bc_create_align
+ (yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(4)), 0),
+ NULL, NULL, NULL, 0);
+ yasm_bc_finalize(bc, yasm_cv__append_bc(info.debug_symline, bc));
+ yasm_bc_calc_len(bc, NULL, NULL);
+
+ return info.debug_symline;
+}
+
+static void
+cv_out_sym(yasm_symrec *sym, unsigned long off, yasm_bytecode *bc,
+ unsigned char **bufp, void *d, yasm_output_value_func output_value)
+{
+ yasm_value val;
+
+ /* sym in its section */
+ yasm_value_init_sym(&val, sym, 32);
+ val.section_rel = 1;
+ output_value(&val, *bufp, 4, off, bc, 0, d);
+ *bufp += 4;
+
+ /* section index */
+ yasm_value_init_sym(&val, sym, 16);
+ val.seg_of = 1;
+ output_value(&val, *bufp, 2, off+4, bc, 0, d);
+ *bufp += 2;
+}
+
+static cv8_symhead *
+cv8_add_symhead(yasm_section *sect, unsigned long type, int first)
+{
+ cv8_symhead *head;
+ yasm_bytecode *bc;
+
+ head = yasm_xmalloc(sizeof(cv8_symhead));
+ head->type = type;
+ head->first = first;
+ head->start_prevbc = yasm_section_bcs_last(sect);
+
+ bc = yasm_bc_create_common(&cv8_symhead_bc_callback, head, 0);
+ if (first)
+ bc->len = 12;
+ else
+ bc->len = 8;
+
+ head->end_prevbc = bc;
+ yasm_cv__append_bc(sect, bc);
+ return head;
+}
+
+static void
+cv8_set_symhead_end(cv8_symhead *head, yasm_bytecode *end_prevbc)
+{
+ head->end_prevbc = end_prevbc;
+}
+
+static void
+cv8_symhead_bc_destroy(void *contents)
+{
+ yasm_xfree(contents);
+}
+
+static void
+cv8_symhead_bc_print(const void *contents, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+static int
+cv8_symhead_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ yasm_internal_error(N_("tried to calc_len a codeview symhead bytecode"));
+ /*@notreached@*/
+ return 0;
+}
+
+static int
+cv8_symhead_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ yasm_object *object = yasm_section_get_object(bc->section);
+ cv8_symhead *head = (cv8_symhead *)bc->contents;
+ unsigned char *buf = *bufp;
+ yasm_intnum *intn, *cval;
+
+ cval = yasm_intnum_create_uint(4);
+ /* Output "version" if first */
+ if (head->first) {
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
+ buf += 4;
+ }
+
+ /* Type contained - 4 bytes */
+ yasm_intnum_set_uint(cval, head->type);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
+ buf += 4;
+
+ /* Total length of info (following this field) - 4 bytes */
+ yasm_intnum_set_uint(cval, bc->len);
+ intn = yasm_calc_bc_dist(head->start_prevbc, head->end_prevbc);
+ yasm_intnum_calc(intn, YASM_EXPR_SUB, cval);
+ yasm_arch_intnum_tobytes(object->arch, intn, buf, 4, 32, 0, bc, 0);
+ buf += 4;
+ yasm_intnum_destroy(intn);
+
+ *bufp = buf;
+
+ yasm_intnum_destroy(cval);
+ return 0;
+}
+
+static yasm_bytecode *
+cv8_add_fileinfo(yasm_section *sect, const cv_filename *fn)
+{
+ cv8_fileinfo *fi;
+ yasm_bytecode *bc;
+
+ fi = yasm_xmalloc(sizeof(cv8_fileinfo));
+ fi->fn = fn;
+
+ bc = yasm_bc_create_common(&cv8_fileinfo_bc_callback, fi, 0);
+ bc->len = 24;
+
+ yasm_cv__append_bc(sect, bc);
+ return bc;
+}
+
+static void
+cv8_fileinfo_bc_destroy(void *contents)
+{
+ yasm_xfree(contents);
+}
+
+static void
+cv8_fileinfo_bc_print(const void *contents, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+static int
+cv8_fileinfo_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ yasm_internal_error(N_("tried to calc_len a codeview fileinfo bytecode"));
+ /*@notreached@*/
+ return 0;
+}
+
+static int
+cv8_fileinfo_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ yasm_object *object = yasm_section_get_object(bc->section);
+ cv8_fileinfo *fi = (cv8_fileinfo *)bc->contents;
+ unsigned char *buf = *bufp;
+ yasm_intnum *cval;
+ int i;
+
+ /* Offset in filename string table */
+ cval = yasm_intnum_create_uint(fi->fn->str_off);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
+ buf += 4;
+
+ /* Checksum type/length */
+ yasm_intnum_set_uint(cval, 0x0110);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 0);
+ buf += 2;
+
+ /* Checksum */
+ for (i=0; i<16; i++)
+ YASM_WRITE_8(buf, fi->fn->digest[i]);
+
+ /* Pad */
+ YASM_WRITE_8(buf, 0);
+ YASM_WRITE_8(buf, 0);
+
+ *bufp = buf;
+
+ yasm_intnum_destroy(cval);
+ return 0;
+}
+
+static void
+cv8_lineinfo_bc_destroy(void *contents)
+{
+ cv8_lineinfo *li = (cv8_lineinfo *)contents;
+ cv8_lineset *ls1, *ls2;
+
+ /* delete line sets */
+ ls1 = STAILQ_FIRST(&li->linesets);
+ while (ls1) {
+ ls2 = STAILQ_NEXT(ls1, link);
+ yasm_xfree(ls1);
+ ls1 = ls2;
+ }
+
+ yasm_xfree(contents);
+}
+
+static void
+cv8_lineinfo_bc_print(const void *contents, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+static int
+cv8_lineinfo_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ yasm_internal_error(N_("tried to calc_len a codeview linehead bytecode"));
+ /*@notreached@*/
+ return 0;
+}
+
+static int
+cv8_lineinfo_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ yasm_object *object = yasm_section_get_object(bc->section);
+ cv8_lineinfo *li = (cv8_lineinfo *)bc->contents;
+ unsigned char *buf = *bufp;
+ yasm_intnum *cval;
+ unsigned long i;
+ cv8_lineset *ls;
+
+ if (li->first_in_sect) {
+ /* start offset and section */
+ cv_out_sym(li->sectsym, (unsigned long)(buf - bufstart), bc, &buf,
+ d, output_value);
+
+ /* Two bytes of pad/alignment */
+ YASM_WRITE_8(buf, 0);
+ YASM_WRITE_8(buf, 0);
+
+ /* Section length covered by line number info */
+ cval = yasm_calc_bc_dist(yasm_section_bcs_first(li->sect),
+ yasm_section_bcs_last(li->sect));
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
+ yasm_intnum_destroy(cval);
+ buf += 4;
+ }
+
+ /* Offset of source file in info table */
+ cval = yasm_intnum_create_uint(li->fn->info_off);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
+ buf += 4;
+
+ /* Number of line number pairs */
+ yasm_intnum_set_uint(cval, li->num_linenums);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
+ buf += 4;
+
+ /* Number of bytes of line number pairs + 12 (no, I don't know why) */
+ yasm_intnum_set_uint(cval, li->num_linenums*8+12);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
+ buf += 4;
+
+ /* Offset / line number pairs */
+ i = 0;
+ STAILQ_FOREACH(ls, &li->linesets, link) {
+ unsigned long j;
+ for (j=0; i<li->num_linenums && j<126; i++, j++) {
+ /* offset in section */
+ yasm_intnum_set_uint(cval, ls->pairs[j].offset);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
+ buf += 4;
+
+ /* line number in file */
+ yasm_intnum_set_uint(cval, ls->pairs[j].line);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 0);
+ buf += 4;
+ }
+ }
+
+ *bufp = buf;
+
+ yasm_intnum_destroy(cval);
+ return 0;
+}
+
+static unsigned long
+cv_sym_size(const cv_sym *cvs)
+{
+ const char *ch = cvs->format;
+ unsigned long len = 4; /* sym length and type */
+ unsigned long slen;
+ int arg = 0;
+
+ while (*ch) {
+ switch (*ch) {
+ case 'b':
+ len++;
+ arg++;
+ break;
+ case 'h':
+ len += 2;
+ arg++;
+ break;
+ case 'w':
+ len += 4;
+ arg++;
+ break;
+ case 'Y':
+ len += 6; /* XXX: will be 4 in 16-bit version */
+ arg++;
+ break;
+ case 'T':
+ len += 4; /* XXX: will be 2 in CV4 */
+ arg++;
+ break;
+ case 'S':
+ len += 1; /* XXX: is this 1 or 2? */
+ slen = (unsigned long)strlen((const char *)cvs->args[arg++].p);
+ len += slen <= 0xff ? slen : 0xff;
+ break;
+ case 'Z':
+ len +=
+ (unsigned long)strlen((const char *)cvs->args[arg++].p) + 1;
+ break;
+ default:
+ yasm_internal_error(N_("unknown sym format character"));
+ }
+ ch++;
+ }
+
+ return len;
+}
+
+static void
+cv_sym_bc_destroy(void *contents)
+{
+ cv_sym *cvs = (cv_sym *)contents;
+ const char *ch = cvs->format;
+ int arg = 0;
+
+ while (*ch) {
+ switch (*ch) {
+ case 'b':
+ case 'h':
+ case 'w':
+ case 'Y':
+ case 'T':
+ arg++;
+ break; /* nothing to destroy */
+ case 'S':
+ case 'Z':
+ yasm_xfree(cvs->args[arg++].p);
+ break;
+ default:
+ yasm_internal_error(N_("unknown sym format character"));
+ }
+ ch++;
+ }
+
+ yasm_xfree(contents);
+}
+
+static void
+cv_sym_bc_print(const void *contents, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+static int
+cv_sym_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ yasm_internal_error(N_("tried to calc_len a codeview sym bytecode"));
+ /*@notreached@*/
+ return 0;
+}
+
+static int
+cv_sym_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ yasm_object *object = yasm_section_get_object(bc->section);
+ cv_sym *cvs = (cv_sym *)bc->contents;
+ unsigned char *buf = *bufp;
+ yasm_intnum *cval;
+ const char *ch = cvs->format;
+ size_t len;
+ int arg = 0;
+
+ /* Total length of record (following this field) - 2 bytes */
+ cval = yasm_intnum_create_uint(bc->len-2);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 1);
+ buf += 2;
+
+ /* Type contained - 2 bytes */
+ yasm_intnum_set_uint(cval, cvs->type);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 0);
+ buf += 2;
+
+ while (*ch) {
+ switch (*ch) {
+ case 'b':
+ YASM_WRITE_8(buf, cvs->args[arg].i);
+ arg++;
+ break;
+ case 'h':
+ yasm_intnum_set_uint(cval, cvs->args[arg++].i);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0,
+ bc, 0);
+ buf += 2;
+ break;
+ case 'w':
+ yasm_intnum_set_uint(cval, cvs->args[arg++].i);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0,
+ bc, 0);
+ buf += 4;
+ break;
+ case 'Y':
+ cv_out_sym((yasm_symrec *)cvs->args[arg++].p,
+ (unsigned long)(buf-bufstart), bc, &buf, d,
+ output_value);
+ break;
+ case 'T':
+ yasm_intnum_set_uint(cval, cvs->args[arg++].i);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0,
+ bc, 0);
+ buf += 4; /* XXX: will be 2 in CV4 */
+ break;
+ case 'S':
+ len = strlen((char *)cvs->args[arg].p);
+ len = len <= 0xff ? len : 0xff;
+ YASM_WRITE_8(buf, len);
+ memcpy(buf, (char *)cvs->args[arg].p, len);
+ buf += len;
+ arg++;
+ break;
+ case 'Z':
+ len = strlen((char *)cvs->args[arg].p)+1;
+ memcpy(buf, (char *)cvs->args[arg].p, len);
+ buf += len;
+ arg++;
+ break;
+ default:
+ yasm_internal_error(N_("unknown leaf format character"));
+ }
+ ch++;
+ }
+
+ *bufp = buf;
+
+ yasm_intnum_destroy(cval);
+ return 0;
+}
diff --git a/contrib/tools/yasm/modules/dbgfmts/codeview/cv-type.c b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-type.c
new file mode 100644
index 0000000000..2a52f18436
--- /dev/null
+++ b/contrib/tools/yasm/modules/dbgfmts/codeview/cv-type.c
@@ -0,0 +1,778 @@
+/*
+ * CodeView debugging format - type information
+ *
+ * Copyright (C) 2006-2007 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.
+ * 3. Neither the name of the author nor the names of other contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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 <util.h>
+
+#include <libyasm.h>
+
+#include "cv-dbgfmt.h"
+
+enum cv_reservedtype {
+ /* Bitfields representation - type */
+ CV_TYPE_SPECIAL = 0x00<<4, /* Special */
+ CV_TYPE_SIGNED = 0x01<<4, /* Signed integral value */
+ CV_TYPE_UNSIGNED = 0x02<<4, /* Unsigned integral value */
+ CV_TYPE_BOOLEAN = 0x03<<4, /* Boolean */
+ CV_TYPE_REAL = 0x04<<4, /* Real */
+ CV_TYPE_COMPLEX = 0x05<<4, /* Complex */
+ CV_TYPE_SPECIAL2 = 0x06<<4, /* Special2 */
+ CV_TYPE_REALINT = 0x07<<4, /* Really int value */
+
+ /* "size" of CV_TYPE_SPECIAL */
+ CV_SPECIAL_NOTYPE = 0x00<<0, /* No type */
+ CV_SPECIAL_ABS = 0x01<<0, /* Absolute symbol */
+ CV_SPECIAL_SEG = 0x02<<0, /* Segment */
+ CV_SPECIAL_VOID = 0x03<<0, /* Void */
+ CV_SPECIAL_CURRENCY = 0x04<<0, /* Basic 8-byte currency value */
+ CV_SPECIAL_NEARBSTR = 0x05<<0, /* Near Basic string */
+ CV_SPECIAL_FARBSTR = 0x06<<0, /* Far Basic string */
+
+ /* Size of CV_TYPE_SIGNED, CV_TYPE_UNSIGNED, and CV_TYPE_BOOLEAN */
+ CV_INTEGER_1BYTE = 0x00<<0, /* 1 byte */
+ CV_INTEGER_2BYTE = 0x01<<0, /* 2 byte */
+ CV_INTEGER_4BYTE = 0x02<<0, /* 4 byte */
+ CV_INTEGER_8BYTE = 0x03<<0, /* 8 byte */
+
+ /* Size of CV_TYPE_REAL and CV_TYPE_COMPLEX */
+ CV_REAL_32BIT = 0x00<<0, /* 32 bit */
+ CV_REAL_64BIT = 0x01<<0, /* 64 bit */
+ CV_REAL_80BIT = 0x02<<0, /* 80 bit */
+ CV_REAL_128BIT = 0x03<<0, /* 128 bit */
+ CV_REAL_48BIT = 0x04<<0, /* 48 bit */
+
+ /* "size" of CV_TYPE_SPECIAL2 */
+ CV_SPECIAL2_BIT = 0x00<<0, /* Bit */
+ CV_SPECIAL2_PASCHAR = 0x01<<0, /* Pascal CHAR */
+
+ /* Size of CV_TYPE_REALINT */
+ CV_REALINT_CHAR = 0x00<<0, /* Char */
+ CV_REALINT_WCHAR = 0x01<<0, /* Wide character */
+ CV_REALINT_S2BYTE = 0x02<<0, /* 2-byte signed integer */
+ CV_REALINT_U2BYTE = 0x03<<0, /* 2-byte unsigned integer */
+ CV_REALINT_S4BYTE = 0x04<<0, /* 4-byte signed integer */
+ CV_REALINT_U4BYTE = 0x05<<0, /* 4-byte unsigned integer */
+ CV_REALINT_S8BYTE = 0x06<<0, /* 8-byte signed integer */
+ CV_REALINT_U8BYTE = 0x07<<0, /* 8-byte unsigned integer */
+
+ /* Mode */
+ CV_MODE_DIRECT = 0x00<<8, /* Direct; not a pointer */
+ CV_MODE_NEAR = 0x01<<8, /* Near pointer */
+ CV_MODE_FAR = 0x02<<8, /* Far pointer */
+ CV_MODE_HUGE = 0x03<<8, /* Huge pointer */
+ CV_MODE_NEAR32 = 0x04<<8, /* 32-bit near pointer */
+ CV_MODE_FAR32 = 0x05<<8, /* 32-bit far pointer */
+ CV_MODE_NEAR64 = 0x06<<8, /* 64-bit near pointer */
+
+ /* Pure primitive type listing - based on above bitfields */
+
+ /* Special Types */
+ CV_T_NOTYPE = 0x0000, /* Uncharacterized type (no type) */
+ CV_T_ABS = 0x0001, /* Absolute symbol */
+ CV_T_SEGMENT = 0x0002, /* Segment type */
+ CV_T_VOID = 0x0003, /* Void */
+ CV_T_PVOID = 0x0103, /* Near pointer to void */
+ CV_T_PFVOID = 0x0203, /* Far pointer to void */
+ CV_T_PHVOID = 0x0303, /* Huge pointer to void */
+ CV_T_32PVOID = 0x0403, /* 32-bit near pointer to void */
+ CV_T_32PFVOID = 0x0503, /* 32-bit far pointer to void */
+ CV_T_CURRENCY = 0x0004, /* Basic 8-byte currency value */
+ CV_T_NBASICSTR = 0x0005, /* Near Basic string */
+ CV_T_FBASICSTR = 0x0006, /* Far Basic string */
+ CV_T_BIT = 0x0060, /* Bit */
+ CV_T_PASCHAR = 0x0061, /* Pascal CHAR */
+ /* Character Types */
+ CV_T_CHAR = 0x0010, /* 8-bit signed */
+ CV_T_UCHAR = 0x0020, /* 8-bit unsigned */
+ CV_T_PCHAR = 0x0110, /* Near pointer to 8-bit signed */
+ CV_T_PUCHAR = 0x0120, /* Near pointer to 8-bit unsigned */
+ CV_T_PFCHAR = 0x0210, /* Far pointer to 8-bit signed */
+ CV_T_PFUCHAR = 0x0220, /* Far pointer to 8-bit unsigned */
+ CV_T_PHCHAR = 0x0310, /* Huge pointer to 8-bit signed */
+ CV_T_PHUCHAR = 0x0320, /* Huge pointer to 8-bit unsigned */
+ CV_T_32PCHAR = 0x0410, /* 16:32 near pointer to 8-bit signed */
+ CV_T_32PUCHAR = 0x0420, /* 16:32 near pointer to 8-bit unsigned */
+ CV_T_32PFCHAR = 0x0510, /* 16:32 far pointer to 8-bit signed */
+ CV_T_32PFUCHAR = 0x0520, /* 16:32 far pointer to 8-bit unsigned */
+ /* Real Character Types */
+ CV_T_RCHAR = 0x0070, /* Real char */
+ CV_T_PRCHAR = 0x0170, /* Near pointer to a real char */
+ CV_T_PFRCHAR = 0x0270, /* Far pointer to a real char */
+ CV_T_PHRCHAR = 0x0370, /* Huge pointer to a real char */
+ CV_T_32PRCHAR = 0x0470, /* 16:32 near pointer to a real char */
+ CV_T_32PFRCHAR = 0x0570, /* 16:32 far pointer to a real char */
+ /* Wide Character Types */
+ CV_T_WCHAR = 0x0071, /* Wide char */
+ CV_T_PWCHAR = 0x0171, /* Near pointer to a wide char */
+ CV_T_PFWCHAR = 0x0271, /* Far pointer to a wide char */
+ CV_T_PHWCHAR = 0x0371, /* Huge pointer to a wide char */
+ CV_T_32PWCHAR = 0x0471, /* 16:32 near pointer to a wide char */
+ CV_T_32PFWCHAR = 0x0571, /* 16:32 far pointer to a wide char */
+ /* Real 16-bit Integer Types */
+ CV_T_INT2 = 0x0072, /* Real 16-bit signed int */
+ CV_T_UINT2 = 0x0073, /* Real 16-bit unsigned int */
+ CV_T_PINT2 = 0x0172, /* Near pointer to 16-bit signed int */
+ CV_T_PUINT2 = 0x0173, /* Near pointer to 16-bit unsigned int */
+ CV_T_PFINT2 = 0x0272, /* Far pointer to 16-bit signed int */
+ CV_T_PFUINT2 = 0x0273, /* Far pointer to 16-bit unsigned int */
+ CV_T_PHINT2 = 0x0372, /* Huge pointer to 16-bit signed int */
+ CV_T_PHUINT2 = 0x0373, /* Huge pointer to 16-bit unsigned int */
+ CV_T_32PINT2 = 0x0472, /* 16:32 near pointer to 16-bit signed int */
+ CV_T_32PUINT2 = 0x0473, /* 16:32 near pointer to 16-bit unsigned int */
+ CV_T_32PFINT2 = 0x0572, /* 16:32 far pointer to 16-bit signed int */
+ CV_T_32PFUINT2 = 0x0573, /* 16:32 far pointer to 16-bit unsigned int */
+ /* 16-bit Short Types */
+ CV_T_SHORT = 0x0011, /* 16-bit signed */
+ CV_T_USHORT = 0x0021, /* 16-bit unsigned */
+ CV_T_PSHORT = 0x0111, /* Near pointer to 16-bit signed */
+ CV_T_PUSHORT = 0x0121, /* Near pointer to 16-bit unsigned */
+ CV_T_PFSHORT = 0x0211, /* Far pointer to 16-bit signed */
+ CV_T_PFUSHORT = 0x0221, /* Far pointer to 16-bit unsigned */
+ CV_T_PHSHORT = 0x0311, /* Huge pointer to 16-bit signed */
+ CV_T_PHUSHORT = 0x0321, /* Huge pointer to 16-bit unsigned */
+ CV_T_32PSHORT = 0x0411, /* 16:32 near pointer to 16-bit signed */
+ CV_T_32PUSHORT = 0x0421, /* 16:32 near pointer to 16-bit unsigned */
+ CV_T_32PFSHORT = 0x0511, /* 16:32 far pointer to 16-bit signed */
+ CV_T_32PFUSHORT = 0x0521, /* 16:32 far pointer to 16-bit unsigned */
+ /* Real 32-bit Integer Types */
+ CV_T_INT4 = 0x0074, /* Real 32-bit signed int */
+ CV_T_UINT4 = 0x0075, /* Real 32-bit unsigned int */
+ CV_T_PINT4 = 0x0174, /* Near pointer to 32-bit signed int */
+ CV_T_PUINT4 = 0x0175, /* Near pointer to 32-bit unsigned int */
+ CV_T_PFINT4 = 0x0274, /* Far pointer to 32-bit signed int */
+ CV_T_PFUINT4 = 0x0275, /* Far pointer to 32-bit unsigned int */
+ CV_T_PHINT4 = 0x0374, /* Huge pointer to 32-bit signed int */
+ CV_T_PHUINT4 = 0x0375, /* Huge pointer to 32-bit unsigned int */
+ CV_T_32PINT4 = 0x0474, /* 16:32 near pointer to 32-bit signed int */
+ CV_T_32PUINT4 = 0x0475, /* 16:32 near pointer to 32-bit unsigned int */
+ CV_T_32PFINT4 = 0x0574, /* 16:32 far pointer to 32-bit signed int */
+ CV_T_32PFUINT4 = 0x0575, /* 16:32 far pointer to 32-bit unsigned int */
+ /* 32-bit Long Types */
+ CV_T_LONG = 0x0012, /* 32-bit signed */
+ CV_T_ULONG = 0x0022, /* 32-bit unsigned */
+ CV_T_PLONG = 0x0112, /* Near pointer to 32-bit signed */
+ CV_T_PULONG = 0x0122, /* Near pointer to 32-bit unsigned */
+ CV_T_PFLONG = 0x0212, /* Far pointer to 32-bit signed */
+ CV_T_PFULONG = 0x0222, /* Far pointer to 32-bit unsigned */
+ CV_T_PHLONG = 0x0312, /* Huge pointer to 32-bit signed */
+ CV_T_PHULONG = 0x0322, /* Huge pointer to 32-bit unsigned */
+ CV_T_32PLONG = 0x0412, /* 16:32 near pointer to 32-bit signed */
+ CV_T_32PULONG = 0x0422, /* 16:32 near pointer to 32-bit unsigned */
+ CV_T_32PFLONG = 0x0512, /* 16:32 far pointer to 32-bit signed */
+ CV_T_32PFULONG = 0x0522, /* 16:32 far pointer to 32-bit unsigned */
+ /* Real 64-bit int Types */
+ CV_T_INT8 = 0x0076, /* 64-bit signed int */
+ CV_T_UINT8 = 0x0077, /* 64-bit unsigned int */
+ CV_T_PINT8 = 0x0176, /* Near pointer to 64-bit signed int */
+ CV_T_PUINT8 = 0x0177, /* Near pointer to 64-bit unsigned int */
+ CV_T_PFINT8 = 0x0276, /* Far pointer to 64-bit signed int */
+ CV_T_PFUINT8 = 0x0277, /* Far pointer to 64-bit unsigned int */
+ CV_T_PHINT8 = 0x0376, /* Huge pointer to 64-bit signed int */
+ CV_T_PHUINT8 = 0x0377, /* Huge pointer to 64-bit unsigned int */
+ CV_T_32PINT8 = 0x0476, /* 16:32 near pointer to 64-bit signed int */
+ CV_T_32PUINT8 = 0x0477, /* 16:32 near pointer to 64-bit unsigned int */
+ CV_T_32PFINT8 = 0x0576, /* 16:32 far pointer to 64-bit signed int */
+ CV_T_32PFUINT8 = 0x0577, /* 16:32 far pointer to 64-bit unsigned int */
+ /* 64-bit Integral Types */
+ CV_T_QUAD = 0x0013, /* 64-bit signed */
+ CV_T_UQUAD = 0x0023, /* 64-bit unsigned */
+ CV_T_PQUAD = 0x0113, /* Near pointer to 64-bit signed */
+ CV_T_PUQUAD = 0x0123, /* Near pointer to 64-bit unsigned */
+ CV_T_PFQUAD = 0x0213, /* Far pointer to 64-bit signed */
+ CV_T_PFUQUAD = 0x0223, /* Far pointer to 64-bit unsigned */
+ CV_T_PHQUAD = 0x0313, /* Huge pointer to 64-bit signed */
+ CV_T_PHUQUAD = 0x0323, /* Huge pointer to 64-bit unsigned */
+ CV_T_32PQUAD = 0x0413, /* 16:32 near pointer to 64-bit signed */
+ CV_T_32PUQUAD = 0x0423, /* 16:32 near pointer to 64-bit unsigned */
+ CV_T_32PFQUAD = 0x0513, /* 16:32 far pointer to 64-bit signed */
+ CV_T_32PFUQUAD = 0x0523, /* 16:32 far pointer to 64-bit unsigned */
+ /* 32-bit Real Types */
+ CV_T_REAL32 = 0x0040, /* 32-bit real */
+ CV_T_PREAL32 = 0x0140, /* Near pointer to 32-bit real */
+ CV_T_PFREAL32 = 0x0240, /* Far pointer to 32-bit real */
+ CV_T_PHREAL32 = 0x0340, /* Huge pointer to 32-bit real */
+ CV_T_32PREAL32 = 0x0440, /* 16:32 near pointer to 32-bit real */
+ CV_T_32PFREAL32 = 0x0540, /* 16:32 far pointer to 32-bit real */
+ /* 48-bit Real Types */
+ CV_T_REAL48 = 0x0044, /* 48-bit real */
+ CV_T_PREAL48 = 0x0144, /* Near pointer to 48-bit real */
+ CV_T_PFREAL48 = 0x0244, /* Far pointer to 48-bit real */
+ CV_T_PHREAL48 = 0x0344, /* Huge pointer to 48-bit real */
+ CV_T_32PREAL48 = 0x0444, /* 16:32 near pointer to 48-bit real */
+ CV_T_32PFREAL48 = 0x0544, /* 16:32 far pointer to 48-bit real */
+ /* 64-bit Real Types */
+ CV_T_REAL64 = 0x0041, /* 64-bit real */
+ CV_T_PREAL64 = 0x0141, /* Near pointer to 64-bit real */
+ CV_T_PFREAL64 = 0x0241, /* Far pointer to 64-bit real */
+ CV_T_PHREAL64 = 0x0341, /* Huge pointer to 64-bit real */
+ CV_T_32PREAL64 = 0x0441, /* 16:32 near pointer to 64-bit real */
+ CV_T_32PFREAL64 = 0x0541, /* 16:32 far pointer to 64-bit real */
+ /* 80-bit Real Types */
+ CV_T_REAL80 = 0x0042, /* 80-bit real */
+ CV_T_PREAL80 = 0x0142, /* Near pointer to 80-bit real */
+ CV_T_PFREAL80 = 0x0242, /* Far pointer to 80-bit real */
+ CV_T_PHREAL80 = 0x0342, /* Huge pointer to 80-bit real */
+ CV_T_32PREAL80 = 0x0442, /* 16:32 near pointer to 80-bit real */
+ CV_T_32PFREAL80 = 0x0542, /* 16:32 far pointer to 80-bit real */
+ /* 128-bit Real Types */
+ CV_T_REAL128 = 0x0043, /* 128-bit real */
+ CV_T_PREAL128 = 0x0143, /* Near pointer to 128-bit real */
+ CV_T_PFREAL128 = 0x0243, /* Far pointer to 128-bit real */
+ CV_T_PHREAL128 = 0x0343, /* Huge pointer to 128-bit real */
+ CV_T_32PREAL128 = 0x0443, /* 16:32 near pointer to 128-bit real */
+ CV_T_32PFREAL128 = 0x0543, /* 16:32 far pointer to 128-bit real */
+ /* 32-bit Complex Types */
+ CV_T_CPLX32 = 0x0050, /* 32-bit complex */
+ CV_T_PCPLX32 = 0x0150, /* Near pointer to 32-bit complex */
+ CV_T_PFCPLX32 = 0x0250, /* Far pointer to 32-bit complex */
+ CV_T_PHCPLX32 = 0x0350, /* Huge pointer to 32-bit complex */
+ CV_T_32PCPLX32 = 0x0450, /* 16:32 near pointer to 32-bit complex */
+ CV_T_32PFCPLX32 = 0x0550, /* 16:32 far pointer to 32-bit complex */
+ /* 64-bit Complex Types */
+ CV_T_CPLX64 = 0x0051, /* 64-bit complex */
+ CV_T_PCPLX64 = 0x0151, /* Near pointer to 64-bit complex */
+ CV_T_PFCPLX64 = 0x0251, /* Far pointer to 64-bit complex */
+ CV_T_PHCPLX64 = 0x0351, /* Huge pointer to 64-bit complex */
+ CV_T_32PCPLX64 = 0x0451, /* 16:32 near pointer to 64-bit complex */
+ CV_T_32PFCPLX64 = 0x0551, /* 16:32 far pointer to 64-bit complex */
+ /* 80-bit Complex Types */
+ CV_T_CPLX80 = 0x0052, /* 80-bit complex */
+ CV_T_PCPLX80 = 0x0152, /* Near pointer to 80-bit complex */
+ CV_T_PFCPLX80 = 0x0252, /* Far pointer to 80-bit complex */
+ CV_T_PHCPLX80 = 0x0352, /* Huge pointer to 80-bit complex */
+ CV_T_32PCPLX80 = 0x0452, /* 16:32 near pointer to 80-bit complex */
+ CV_T_32PFCPLX80 = 0x0552, /* 16:32 far pointer to 80-bit complex */
+ /* 128-bit Complex Types */
+ CV_T_CPLX128 = 0x0053, /* 128-bit complex */
+ CV_T_PCPLX128 = 0x0153, /* Near pointer to 128-bit complex */
+ CV_T_PFCPLX128 = 0x0253, /* Far pointer to 128-bit complex */
+ CV_T_PHCPLX128 = 0x0353, /* Huge pointer to 128-bit real */
+ CV_T_32PCPLX128 = 0x0453, /* 16:32 near pointer to 128-bit complex */
+ CV_T_32PFCPLX128 = 0x0553, /* 16:32 far pointer to 128-bit complex */
+ /* Boolean Types */
+ CV_T_BOOL08 = 0x0030, /* 8-bit Boolean */
+ CV_T_BOOL16 = 0x0031, /* 16-bit Boolean */
+ CV_T_BOOL32 = 0x0032, /* 32-bit Boolean */
+ CV_T_BOOL64 = 0x0033, /* 64-bit Boolean */
+ CV_T_PBOOL08 = 0x0130, /* Near pointer to 8-bit Boolean */
+ CV_T_PBOOL16 = 0x0131, /* Near pointer to 16-bit Boolean */
+ CV_T_PBOOL32 = 0x0132, /* Near pointer to 32-bit Boolean */
+ CV_T_PBOOL64 = 0x0133, /* Near pointer to 64-bit Boolean */
+ CV_T_PFBOOL08 = 0x0230, /* Far pointer to 8-bit Boolean */
+ CV_T_PFBOOL16 = 0x0231, /* Far pointer to 16-bit Boolean */
+ CV_T_PFBOOL32 = 0x0232, /* Far pointer to 32-bit Boolean */
+ CV_T_PFBOOL64 = 0x0233, /* Far pointer to 64-bit Boolean */
+ CV_T_PHBOOL08 = 0x0330, /* Huge pointer to 8-bit Boolean */
+ CV_T_PHBOOL16 = 0x0331, /* Huge pointer to 16-bit Boolean */
+ CV_T_PHBOOL32 = 0x0332, /* Huge pointer to 32-bit Boolean */
+ CV_T_PHBOOL64 = 0x0333, /* Huge pointer to 64-bit Boolean */
+ CV_T_32PBOOL08 = 0x0430, /* 16:32 near pointer to 8-bit Boolean */
+ CV_T_32PBOOL16 = 0x0431, /* 16:32 near pointer to 16-bit Boolean */
+ CV_T_32PBOOL32 = 0x0432, /* 16:32 near pointer to 32-bit Boolean */
+ CV_T_32PBOOL64 = 0x0433, /* 16:32 near pointer to 64-bit Boolean */
+ CV_T_32PFBOOL08 = 0x0530, /* 16:32 far pointer to 8-bit Boolean */
+ CV_T_32PFBOOL16 = 0x0531, /* 16:32 far pointer to 16-bit Boolean */
+ CV_T_32PFBOOL32 = 0x0532, /* 16:32 far pointer to 32-bit Boolean */
+ CV_T_32PFBOOL64 = 0x0533, /* 16:32 far pointer to 64-bit Boolean */
+
+ /* Non-primitive types are stored in the TYPES section (generated in
+ * cv-type.c) and start at this index (e.g. 0x1000 is the first type
+ * in TYPES, 0x1001 the second, etc.
+ */
+ CV_FIRST_NONPRIM = 0x1000
+};
+
+enum cv_leaftype {
+ /* Leaf indices for type records that can be referenced from symbols */
+ CV4_LF_MODIFIER = 0x0001, /* Type Modifier */
+ CV4_LF_POINTER = 0x0002, /* Pointer */
+ CV4_LF_ARRAY = 0x0003, /* Simple Array */
+ CV4_LF_CLASS = 0x0004, /* Classes */
+ CV4_LF_STRUCTURE = 0x0005, /* Structures */
+ CV4_LF_UNION = 0x0006, /* Unions */
+ CV4_LF_ENUM = 0x0007, /* Enumeration */
+ CV4_LF_PROCEDURE = 0x0008, /* Procedure */
+ CV4_LF_MFUNCTION = 0x0009, /* Member Function */
+ CV4_LF_VTSHAPE = 0x000a, /* Virtual Function Table Shape */
+ CV4_LF_BARRAY = 0x000d, /* Basic Array */
+ CV4_LF_LABEL = 0x000e, /* Label */
+ CV4_LF_NULL = 0x000f, /* Null */
+ CV4_LF_DIMARRAY = 0x0011, /* Multiply Dimensioned Array */
+ CV4_LF_VFTPATH = 0x0012, /* Path to Virtual Function Table */
+ CV4_LF_PRECOMP = 0x0013, /* Reference Precompiled Types */
+ CV4_LF_ENDPRECOMP = 0x0014, /* End of Precompiled Types */
+
+ /* CodeView 5.0 version */
+ CV5_LF_MODIFIER = 0x1001, /* Type Modifier */
+ CV5_LF_POINTER = 0x1002, /* Pointer */
+ CV5_LF_ARRAY = 0x1003, /* Simple Array */
+ CV5_LF_CLASS = 0x1004, /* Classes */
+ CV5_LF_STRUCTURE = 0x1005, /* Structures */
+ CV5_LF_UNION = 0x1006, /* Unions */
+ CV5_LF_ENUM = 0x1007, /* Enumeration */
+ CV5_LF_PROCEDURE = 0x1008, /* Procedure */
+ CV5_LF_MFUNCTION = 0x1009, /* Member Function */
+ CV5_LF_VTSHAPE = 0x000a, /* Virtual Function Table Shape */
+ CV5_LF_BARRAY = 0x100d, /* Basic Array */
+ CV5_LF_LABEL = 0x000e, /* Label */
+ CV5_LF_NULL = 0x000f, /* Null */
+ CV5_LF_DIMARRAY = 0x100c, /* Multiply Dimensioned Array */
+ CV5_LF_VFTPATH = 0x100d, /* Path to Virtual Function Table */
+ CV5_LF_PRECOMP = 0x100e, /* Reference Precompiled Types */
+ CV5_LF_ENDPRECOMP = 0x0014, /* End of Precompiled Types */
+ CV5_LF_TYPESERVER = 0x0016, /* Reference Typeserver */
+
+ /* Leaf indices for type records that can be referenced from other type
+ * records
+ */
+ CV4_LF_SKIP = 0x0200, /* Skip */
+ CV4_LF_ARGLIST = 0x0201, /* Argument List */
+ CV4_LF_DEFARG = 0x0202, /* Default Argument */
+ CV4_LF_LIST = 0x0203, /* Arbitrary List */
+ CV4_LF_FIELDLIST = 0x0204, /* Field List */
+ CV4_LF_DERIVED = 0x0205, /* Derived Classes */
+ CV4_LF_BITFIELD = 0x0206, /* Bit Fields */
+ CV4_LF_METHODLIST = 0x0207, /* Method List */
+ CV4_LF_DIMCONU = 0x0208, /* Dimensioned Array with Constant Upper Bound */
+ CV4_LF_DIMCONLU = 0x0209, /* Dimensioned Array with Constant Lower and Upper Bounds */
+ CV4_LF_DIMVARU = 0x020a, /* Dimensioned Array with Variable Upper Bound */
+ CV4_LF_DIMVARLU = 0x020b, /* Dimensioned Array with Variable Lower and Upper Bounds */
+ CV4_LF_REFSYM = 0x020c, /* Referenced Symbol */
+
+ /* CodeView 5.0 version */
+ CV5_LF_SKIP = 0x1200, /* Skip */
+ CV5_LF_ARGLIST = 0x1201, /* Argument List */
+ CV5_LF_DEFARG = 0x1202, /* Default Argument */
+ CV5_LF_FIELDLIST = 0x1203, /* Field List */
+ CV5_LF_DERIVED = 0x1204, /* Derived Classes */
+ CV5_LF_BITFIELD = 0x1205, /* Bit Fields */
+ CV5_LF_METHODLIST = 0x1206, /* Method List */
+ CV5_LF_DIMCONU = 0x1207, /* Dimensioned Array with Constant Upper Bound */
+ CV5_LF_DIMCONLU = 0x1208, /* Dimensioned Array with Constant Lower and Upper Bounds */
+ CV5_LF_DIMVARU = 0x1209, /* Dimensioned Array with Variable Upper Bound */
+ CV5_LF_DIMVARLU = 0x120a, /* Dimensioned Array with Variable Lower and Upper Bounds */
+ CV5_LF_REFSYM = 0x020c, /* Referenced Symbol */
+
+ /* Leaf indices for fields of complex lists */
+ CV4_LF_BCLASS = 0x0400, /* Real Base Class */
+ CV4_LF_VBCLASS = 0x0401, /* Direct Virtual Base Class */
+ CV4_LF_IVBCLASS = 0x0402, /* Indirect Virtual Base Class */
+ CV4_LF_ENUMERATE = 0x0403, /* Enumeration Name and Value */
+ CV4_LF_FRIENDFCN = 0x0404, /* Friend Function */
+ CV4_LF_INDEX = 0x0405, /* Index To Another Type Record */
+ CV4_LF_MEMBER = 0x0406, /* Data Member */
+ CV4_LF_STMEMBER = 0x0407, /* Static Data Member */
+ CV4_LF_METHOD = 0x0408, /* Method */
+ CV4_LF_NESTTYPE = 0x0409, /* Nested Type Definition */
+ CV4_LF_VFUNCTAB = 0x040a, /* Virtual Function Table Pointer */
+ CV4_LF_FRIENDCLS = 0x040b, /* Friend Class */
+ CV4_LF_ONEMETHOD = 0x040c, /* One Method */
+ CV4_LF_VFUNCOFF = 0x040d, /* Virtual Function Offset */
+
+ /* CodeView 5.0 version */
+ CV5_LF_BCLASS = 0x1400, /* Real Base Class */
+ CV5_LF_VBCLASS = 0x1401, /* Direct Virtual Base Class */
+ CV5_LF_IVBCLASS = 0x1402, /* Indirect Virtual Base Class */
+ CV5_LF_ENUMERATE = 0x0403, /* Enumeration Name and Value */
+ CV5_LF_FRIENDFCN = 0x1403, /* Friend Function */
+ CV5_LF_INDEX = 0x1404, /* Index To Another Type Record */
+ CV5_LF_MEMBER = 0x1405, /* Data Member */
+ CV5_LF_STMEMBER = 0x1406, /* Static Data Member */
+ CV5_LF_METHOD = 0x1407, /* Method */
+ CV5_LF_NESTTYPE = 0x1408, /* Nested Type Definition */
+ CV5_LF_VFUNCTAB = 0x1409, /* Virtual Function Table Pointer */
+ CV5_LF_FRIENDCLS = 0x140a, /* Friend Class */
+ CV5_LF_ONEMETHOD = 0x140b, /* One Method */
+ CV5_LF_VFUNCOFF = 0x140c, /* Virtual Function Offset */
+ CV5_LF_NESTTYPEEX = 0x140d, /* Nested Type Extended Definition */
+ CV5_LF_MEMBERMODIFY = 0x140e, /* Member Modification */
+ /* XXX: CodeView 5.0 spec also lists 0x040f as LF_MEMBERMODIFY? */
+
+ /* Leaf indices for numeric fields of symbols and type records */
+ CV_LF_NUMERIC = 0x8000,
+ CV_LF_CHAR = 0x8000, /* Signed Char (8-bit) */
+ CV_LF_SHORT = 0x8001, /* Signed Short (16-bit) */
+ CV_LF_USHORT = 0x8002, /* Unsigned Short (16-bit) */
+ CV_LF_LONG = 0x8003, /* Signed Long (32-bit) */
+ CV_LF_ULONG = 0x8004, /* Unsigned Long (32-bit) */
+ CV_LF_REAL32 = 0x8005, /* 32-bit Float */
+ CV_LF_REAL64 = 0x8006, /* 64-bit Float */
+ CV_LF_REAL80 = 0x8007, /* 80-bit Float */
+ CV_LF_REAL128 = 0x8008, /* 128-bit Float */
+ CV_LF_QUADWORD = 0x8009, /* Signed Quad Word (64-bit) */
+ CV_LF_UQUADWORD = 0x800a, /* Unsigned Quad Word (64-bit) */
+ CV_LF_REAL48 = 0x800b, /* 48-bit Float */
+ CV_LF_COMPLEX32 = 0x800c, /* 32-bit Complex */
+ CV_LF_COMPLEX64 = 0x800d, /* 64-bit Complex */
+ CV_LF_COMPLEX80 = 0x800e, /* 80-bit Complex */
+ CV_LF_COMPLEX128 = 0x800f, /* 128-bit Complex */
+ CV_LF_VARSTRING = 0x8010, /* Variable-length String */
+
+ /* Leaf padding bytes */
+ CV_LF_PAD0 = 0xf0,
+ CV_LF_PAD1 = 0xf1,
+ CV_LF_PAD2 = 0xf2,
+ CV_LF_PAD3 = 0xf3,
+ CV_LF_PAD4 = 0xf4,
+ CV_LF_PAD5 = 0xf5,
+ CV_LF_PAD6 = 0xf6,
+ CV_LF_PAD7 = 0xf7,
+ CV_LF_PAD8 = 0xf8,
+ CV_LF_PAD9 = 0xf9,
+ CV_LF_PAD10 = 0xfa,
+ CV_LF_PAD11 = 0xfb,
+ CV_LF_PAD12 = 0xfc,
+ CV_LF_PAD13 = 0xfc,
+ CV_LF_PAD14 = 0xfe,
+ CV_LF_PAD15 = 0xff
+};
+
+/* Leaves use a bit of meta-programming to encode formats: each character
+ * of format represents the output generated, as follows:
+ * 'b' : 1 byte value (integer)
+ * 'h' : 2 byte value (integer)
+ * 'w' : 4 byte value (integer)
+ * 'L' : subleaf, recurses into cv_leaf (pointer)
+ * 'T' : 4 byte type index, pulls cv_type.index from cv_type (pointer)
+ * 'S' : length-prefixed string (pointer)
+ */
+typedef struct cv_leaf {
+ enum cv_leaftype type;
+ const char *format; /* format of args */
+ union {
+ unsigned long i;
+ void *p;
+ } args[6];
+} cv_leaf;
+
+typedef struct cv_type {
+ unsigned long indx; /* type # (must be same as output order) */
+ size_t num_leaves;
+ /*@null@*/ /*@only@*/ cv_leaf **leaves;
+} cv_type;
+
+/* Bytecode callback function prototypes */
+static void cv_type_bc_destroy(void *contents);
+static void cv_type_bc_print(const void *contents, FILE *f, int indent_level);
+static int cv_type_bc_calc_len
+ (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
+static int cv_type_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+/* Bytecode callback structures */
+static const yasm_bytecode_callback cv_type_bc_callback = {
+ cv_type_bc_destroy,
+ cv_type_bc_print,
+ yasm_bc_finalize_common,
+ NULL,
+ cv_type_bc_calc_len,
+ yasm_bc_expand_common,
+ cv_type_bc_tobytes,
+ 0
+};
+
+static cv_type *cv_type_create(unsigned long indx);
+static void cv_type_append_leaf(cv_type *type, /*@keep@*/ cv_leaf *leaf);
+
+
+static cv_leaf *
+cv_leaf_create_label(int is_far)
+{
+ cv_leaf *leaf = yasm_xmalloc(sizeof(cv_leaf));
+ leaf->type = CV5_LF_LABEL;
+ leaf->format = "h";
+ leaf->args[0].i = is_far ? 4 : 0;
+ return leaf;
+}
+
+yasm_section *
+yasm_cv__generate_type(yasm_object *object)
+{
+ int new;
+ unsigned long indx = CV_FIRST_NONPRIM;
+ yasm_section *debug_type;
+ yasm_bytecode *bc;
+ cv_type *type;
+
+ debug_type =
+ yasm_object_get_general(object, ".debug$T", 1, 0, 0, &new, 0);
+
+ /* Add label type */
+ type = cv_type_create(indx++);
+ cv_type_append_leaf(type, cv_leaf_create_label(0));
+ bc = yasm_bc_create_common(&cv_type_bc_callback, type, 0);
+ yasm_bc_finalize(bc, yasm_cv__append_bc(debug_type, bc));
+ yasm_bc_calc_len(bc, NULL, NULL);
+
+ return debug_type;
+}
+
+static void
+cv_leaf_destroy(cv_leaf *leaf)
+{
+ const char *ch = leaf->format;
+ int arg = 0;
+
+ while (*ch) {
+ switch (*ch) {
+ case 'b':
+ case 'h':
+ case 'w':
+ arg++;
+ break; /* nothing to destroy */
+ case 'L':
+ cv_leaf_destroy((cv_leaf *)leaf->args[arg++].p);
+ break;
+ case 'T':
+ arg++; /* nothing to destroy */
+ break;
+ case 'S':
+ yasm_xfree(leaf->args[arg++].p);
+ break;
+ default:
+ yasm_internal_error(N_("unknown leaf format character"));
+ }
+ ch++;
+ }
+}
+
+static unsigned long
+cv_leaf_size(const cv_leaf *leaf)
+{
+ const char *ch = leaf->format;
+ unsigned long len = 2; /* leaf type */
+ unsigned long slen;
+ int arg = 0;
+
+ while (*ch) {
+ switch (*ch) {
+ case 'b':
+ len++;
+ arg++;
+ break;
+ case 'h':
+ len += 2;
+ arg++;
+ break;
+ case 'w':
+ len += 4;
+ arg++;
+ break;
+ case 'L':
+ len += cv_leaf_size((const cv_leaf *)leaf->args[arg++].p);
+ break;
+ case 'T':
+ len += 4; /* XXX: will be 2 in CV4 */
+ arg++;
+ break;
+ case 'S':
+ len += 1; /* XXX: is this 1 or 2? */
+ slen = (unsigned long)strlen((const char *)leaf->args[arg++].p);
+ len += slen <= 0xff ? slen : 0xff;
+ break;
+ default:
+ yasm_internal_error(N_("unknown leaf format character"));
+ }
+ ch++;
+ }
+
+ return len;
+}
+
+static void
+cv_leaf_tobytes(const cv_leaf *leaf, yasm_bytecode *bc, yasm_arch *arch,
+ unsigned char **bufp, yasm_intnum *cval)
+{
+ unsigned char *buf = *bufp;
+ const char *ch = leaf->format;
+ size_t len;
+ int arg = 0;
+
+ /* leaf type */
+ yasm_intnum_set_uint(cval, leaf->type);
+ yasm_arch_intnum_tobytes(arch, cval, buf, 2, 16, 0, bc, 0);
+ buf += 2;
+
+ while (*ch) {
+ switch (*ch) {
+ case 'b':
+ YASM_WRITE_8(buf, leaf->args[arg].i);
+ arg++;
+ break;
+ case 'h':
+ yasm_intnum_set_uint(cval, leaf->args[arg++].i);
+ yasm_arch_intnum_tobytes(arch, cval, buf, 2, 16, 0, bc, 0);
+ buf += 2;
+ break;
+ case 'w':
+ yasm_intnum_set_uint(cval, leaf->args[arg++].i);
+ yasm_arch_intnum_tobytes(arch, cval, buf, 4, 32, 0, bc, 0);
+ buf += 4;
+ break;
+ case 'L':
+ cv_leaf_tobytes((const cv_leaf *)leaf->args[arg++].p, bc, arch,
+ &buf, cval);
+ break;
+ case 'T':
+ yasm_intnum_set_uint(cval,
+ ((const cv_type *)leaf->args[arg++].p)->indx);
+ yasm_arch_intnum_tobytes(arch, cval, buf, 4, 32, 0, bc, 0);
+ buf += 4; /* XXX: will be 2 in CV4 */
+ break;
+ case 'S':
+ len = strlen((const char *)leaf->args[arg].p);
+ len = len <= 0xff ? len : 0xff;
+ YASM_WRITE_8(buf, len);
+ memcpy(buf, (const char *)leaf->args[arg].p, len);
+ buf += len;
+ arg++;
+ break;
+ default:
+ yasm_internal_error(N_("unknown leaf format character"));
+ }
+ ch++;
+ }
+
+ *bufp = buf;
+}
+
+static cv_type *
+cv_type_create(unsigned long indx)
+{
+ cv_type *type = yasm_xmalloc(sizeof(cv_type));
+
+ type->indx = indx;
+ type->num_leaves = 0;
+ type->leaves = NULL;
+
+ return type;
+}
+
+static void
+cv_type_append_leaf(cv_type *type, /*@keep@*/ cv_leaf *leaf)
+{
+ type->num_leaves++;
+
+ /* This is inefficient for large numbers of leaves, but that won't happen
+ * until we add structure support.
+ */
+ type->leaves = yasm_xrealloc(type->leaves,
+ type->num_leaves*sizeof(cv_leaf *));
+
+ type->leaves[type->num_leaves-1] = leaf;
+}
+
+static void
+cv_type_bc_destroy(void *contents)
+{
+ cv_type *type = (cv_type *)contents;
+ size_t i;
+
+ for (i=0; i<type->num_leaves; i++)
+ cv_leaf_destroy(type->leaves[i]);
+ if (type->leaves)
+ yasm_xfree(type->leaves);
+ yasm_xfree(contents);
+}
+
+static void
+cv_type_bc_print(const void *contents, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+static int
+cv_type_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ cv_type *type = (cv_type *)bc->contents;
+ size_t i;
+
+ if (type->indx == CV_FIRST_NONPRIM)
+ bc->len = 4+2;
+ else
+ bc->len = 2;
+
+ for (i=0; i<type->num_leaves; i++)
+ bc->len += cv_leaf_size(type->leaves[i]);
+
+ /* Pad to multiple of 4 */
+ if (bc->len & 0x3)
+ bc->len += 4-(bc->len & 0x3);
+
+ return 0;
+}
+
+static int
+cv_type_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ yasm_object *object = yasm_section_get_object(bc->section);
+ cv_type *type = (cv_type *)bc->contents;
+ unsigned char *buf = *bufp;
+ yasm_intnum *cval;
+ size_t i;
+ unsigned long reclen = bc->len - 2;
+
+ cval = yasm_intnum_create_uint(4); /* version */
+ if (type->indx == CV_FIRST_NONPRIM) {
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 4, 32, 0, bc, 1);
+ buf += 4;
+ reclen -= 4;
+ }
+
+ /* Total length of record (following this field) - 2 bytes */
+ yasm_intnum_set_uint(cval, reclen);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 1);
+ buf += 2;
+
+ /* Leaves */
+ for (i=0; i<type->num_leaves; i++)
+ cv_leaf_tobytes(type->leaves[i], bc, object->arch, &buf, cval);
+
+ /* Pad to multiple of 4 */
+ switch ((buf-(*bufp)) & 0x3) {
+ case 3:
+ YASM_WRITE_8(buf, CV_LF_PAD3);
+ case 2:
+ YASM_WRITE_8(buf, CV_LF_PAD2);
+ case 1:
+ YASM_WRITE_8(buf, CV_LF_PAD1);
+ case 0:
+ break;
+ }
+
+ *bufp = buf;
+
+ yasm_intnum_destroy(cval);
+ return 0;
+}
diff --git a/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-aranges.c b/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-aranges.c
new file mode 100644
index 0000000000..f398b7fa72
--- /dev/null
+++ b/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-aranges.c
@@ -0,0 +1,125 @@
+/*
+ * DWARF2 debugging format - address range table
+ *
+ * Copyright (C) 2006-2007 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 <util.h>
+
+#include <libyasm.h>
+
+#include "dwarf2-dbgfmt.h"
+
+
+static void
+dwarf2_append_arange(yasm_section *debug_aranges, /*@only@*/ yasm_expr *start,
+ /*@only@*/ yasm_expr *length, unsigned int sizeof_address)
+{
+ yasm_datavalhead dvs;
+ yasm_bytecode *bc;
+
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(start));
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(length));
+ bc = yasm_bc_create_data(&dvs, sizeof_address, 0, NULL, 0);
+ yasm_bc_finalize(bc, yasm_dwarf2__append_bc(debug_aranges, bc));
+ yasm_bc_calc_len(bc, NULL, NULL);
+}
+
+typedef struct dwarf2_aranges_info {
+ yasm_section *debug_aranges; /* section to which address ranges go */
+ yasm_object *object;
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2;
+} dwarf2_aranges_info;
+
+static int
+dwarf2_generate_aranges_section(yasm_section *sect, /*@null@*/ void *d)
+{
+ dwarf2_aranges_info *info = (dwarf2_aranges_info *)d;
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = info->dbgfmt_dwarf2;
+ /*@null@*/ dwarf2_section_data *dsd;
+ /*@only@*/ yasm_expr *start, *length;
+
+ dsd = yasm_section_get_data(sect, &yasm_dwarf2__section_data_cb);
+ if (!dsd)
+ return 0; /* no line data for this section */
+
+ /* Create address range descriptor */
+ start = yasm_expr_create_ident(
+ yasm_expr_sym(yasm_dwarf2__bc_sym(info->object->symtab,
+ yasm_section_bcs_first(sect))), 0);
+ length = yasm_expr_create_ident(
+ yasm_expr_int(yasm_calc_bc_dist(yasm_section_bcs_first(sect),
+ yasm_section_bcs_last(sect))), 0);
+ dwarf2_append_arange(info->debug_aranges, start, length,
+ dbgfmt_dwarf2->sizeof_address);
+
+ return 0;
+}
+
+yasm_section *
+yasm_dwarf2__generate_aranges(yasm_object *object, yasm_section *debug_info)
+{
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)object->dbgfmt;
+ int new;
+ yasm_section *debug_aranges;
+ yasm_bytecode *bc;
+ dwarf2_head *head;
+ dwarf2_aranges_info info;
+
+ debug_aranges =
+ yasm_object_get_general(object, ".debug_aranges",
+ 2*dbgfmt_dwarf2->sizeof_address, 0, 0, &new,
+ 0);
+
+ /* header */
+ head = yasm_dwarf2__add_head(dbgfmt_dwarf2, debug_aranges, debug_info, 1,
+ 1);
+
+ /* align ranges to 2x address size (range size) */
+ bc = yasm_bc_create_align(
+ yasm_expr_create_ident(yasm_expr_int(
+ yasm_intnum_create_uint(dbgfmt_dwarf2->sizeof_address*2)), 0),
+ NULL, NULL, NULL, 0);
+ yasm_bc_finalize(bc, yasm_dwarf2__append_bc(debug_aranges, bc));
+ yasm_bc_calc_len(bc, NULL, NULL);
+
+ info.debug_aranges = debug_aranges;
+ info.object = object;
+ info.dbgfmt_dwarf2 = dbgfmt_dwarf2;
+
+ yasm_object_sections_traverse(object, (void *)&info,
+ dwarf2_generate_aranges_section);
+
+ /* Terminate with empty address range descriptor */
+ dwarf2_append_arange(debug_aranges,
+ yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(0)), 0),
+ yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(0)), 0),
+ dbgfmt_dwarf2->sizeof_address);
+
+ /* mark end of aranges information */
+ yasm_dwarf2__set_head_end(head, yasm_section_bcs_last(debug_aranges));
+
+ return debug_aranges;
+}
+
diff --git a/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c b/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c
new file mode 100644
index 0000000000..5b66f8a70f
--- /dev/null
+++ b/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c
@@ -0,0 +1,348 @@
+/*
+ * DWARF2 debugging format
+ *
+ * Copyright (C) 2006-2007 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 <util.h>
+
+#include <libyasm.h>
+
+#include "dwarf2-dbgfmt.h"
+
+struct dwarf2_head {
+ yasm_bytecode *start_prevbc;
+ yasm_bytecode *end_prevbc;
+ /*@null@*/ yasm_section *debug_ptr;
+ int with_address;
+ int with_segment;
+};
+
+/* Bytecode callback function prototypes */
+static void dwarf2_head_bc_destroy(void *contents);
+static void dwarf2_head_bc_print(const void *contents, FILE *f,
+ int indent_level);
+static int dwarf2_head_bc_calc_len
+ (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
+static int dwarf2_head_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+/* Bytecode callback structures */
+static const yasm_bytecode_callback dwarf2_head_bc_callback = {
+ dwarf2_head_bc_destroy,
+ dwarf2_head_bc_print,
+ yasm_bc_finalize_common,
+ NULL,
+ dwarf2_head_bc_calc_len,
+ yasm_bc_expand_common,
+ dwarf2_head_bc_tobytes,
+ 0
+};
+
+/* Section data callback function prototypes */
+static void dwarf2_section_data_destroy(void *data);
+static void dwarf2_section_data_print(void *data, FILE *f, int indent_level);
+
+/* Section data callback */
+const yasm_assoc_data_callback yasm_dwarf2__section_data_cb = {
+ dwarf2_section_data_destroy,
+ dwarf2_section_data_print
+};
+
+yasm_dbgfmt_module yasm_dwarf2_LTX_dbgfmt;
+
+
+static /*@null@*/ /*@only@*/ yasm_dbgfmt *
+dwarf2_dbgfmt_create(yasm_object *object)
+{
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 =
+ yasm_xmalloc(sizeof(yasm_dbgfmt_dwarf2));
+ size_t i;
+
+ dbgfmt_dwarf2->dbgfmt.module = &yasm_dwarf2_LTX_dbgfmt;
+
+ dbgfmt_dwarf2->dirs_allocated = 32;
+ dbgfmt_dwarf2->dirs_size = 0;
+ dbgfmt_dwarf2->dirs =
+ yasm_xmalloc(sizeof(char *)*dbgfmt_dwarf2->dirs_allocated);
+
+ dbgfmt_dwarf2->filenames_allocated = 32;
+ dbgfmt_dwarf2->filenames_size = 0;
+ dbgfmt_dwarf2->filenames =
+ yasm_xmalloc(sizeof(dwarf2_filename)*dbgfmt_dwarf2->filenames_allocated);
+ for (i=0; i<dbgfmt_dwarf2->filenames_allocated; i++) {
+ dbgfmt_dwarf2->filenames[i].pathname = NULL;
+ dbgfmt_dwarf2->filenames[i].filename = NULL;
+ dbgfmt_dwarf2->filenames[i].dir = 0;
+ }
+
+ dbgfmt_dwarf2->format = DWARF2_FORMAT_32BIT; /* TODO: flexible? */
+
+ dbgfmt_dwarf2->sizeof_address = yasm_arch_get_address_size(object->arch)/8;
+ switch (dbgfmt_dwarf2->format) {
+ case DWARF2_FORMAT_32BIT:
+ dbgfmt_dwarf2->sizeof_offset = 4;
+ break;
+ case DWARF2_FORMAT_64BIT:
+ dbgfmt_dwarf2->sizeof_offset = 8;
+ break;
+ }
+ dbgfmt_dwarf2->min_insn_len = yasm_arch_min_insn_len(object->arch);
+
+ return (yasm_dbgfmt *)dbgfmt_dwarf2;
+}
+
+static void
+dwarf2_dbgfmt_destroy(/*@only@*/ yasm_dbgfmt *dbgfmt)
+{
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)dbgfmt;
+ size_t i;
+ for (i=0; i<dbgfmt_dwarf2->dirs_size; i++)
+ if (dbgfmt_dwarf2->dirs[i])
+ yasm_xfree(dbgfmt_dwarf2->dirs[i]);
+ yasm_xfree(dbgfmt_dwarf2->dirs);
+ for (i=0; i<dbgfmt_dwarf2->filenames_size; i++) {
+ if (dbgfmt_dwarf2->filenames[i].pathname)
+ yasm_xfree(dbgfmt_dwarf2->filenames[i].pathname);
+ if (dbgfmt_dwarf2->filenames[i].filename)
+ yasm_xfree(dbgfmt_dwarf2->filenames[i].filename);
+ }
+ yasm_xfree(dbgfmt_dwarf2->filenames);
+ yasm_xfree(dbgfmt);
+}
+
+/* Add a bytecode to a section, updating offset on insertion;
+ * no optimization necessary.
+ */
+yasm_bytecode *
+yasm_dwarf2__append_bc(yasm_section *sect, yasm_bytecode *bc)
+{
+ yasm_bytecode *precbc = yasm_section_bcs_last(sect);
+ bc->offset = yasm_bc_next_offset(precbc);
+ yasm_section_bcs_append(sect, bc);
+ return precbc;
+}
+
+static void
+dwarf2_dbgfmt_generate(yasm_object *object, yasm_linemap *linemap,
+ yasm_errwarns *errwarns)
+{
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)object->dbgfmt;
+ size_t num_line_sections;
+ /*@null@*/ yasm_section *debug_info, *debug_line, *main_code;
+
+ /* If we don't have any .file directives, generate line information
+ * based on the asm source.
+ */
+ debug_line = yasm_dwarf2__generate_line(object, linemap, errwarns,
+ dbgfmt_dwarf2->filenames_size == 0,
+ &main_code, &num_line_sections);
+
+ /* If we don't have a .debug_info (or it's empty), generate the minimal
+ * set of .debug_info, .debug_aranges, and .debug_abbrev so that the
+ * .debug_line we're generating is actually useful.
+ */
+ debug_info = yasm_object_find_general(object, ".debug_info");
+ if (num_line_sections > 0 &&
+ (!debug_info || yasm_section_bcs_first(debug_info)
+ == yasm_section_bcs_last(debug_info))) {
+ debug_info = yasm_dwarf2__generate_info(object, debug_line, main_code);
+ yasm_dwarf2__generate_aranges(object, debug_info);
+ /*yasm_dwarf2__generate_pubnames(object, debug_info);*/
+ }
+}
+
+yasm_symrec *
+yasm_dwarf2__bc_sym(yasm_symtab *symtab, yasm_bytecode *bc)
+{
+ /*@dependent@*/ yasm_symrec *sym;
+ if (bc->symrecs && bc->symrecs[0])
+ sym = bc->symrecs[0];
+ else
+ sym = yasm_symtab_define_label(symtab, ".bcsym", bc, 0, 0);
+ return sym;
+}
+
+dwarf2_head *
+yasm_dwarf2__add_head
+ (yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2, yasm_section *sect,
+ /*@null@*/ yasm_section *debug_ptr, int with_address, int with_segment)
+{
+ dwarf2_head *head;
+ yasm_bytecode *bc;
+
+ head = yasm_xmalloc(sizeof(dwarf2_head));
+ head->start_prevbc = yasm_section_bcs_last(sect);
+
+ bc = yasm_bc_create_common(&dwarf2_head_bc_callback, head, 0);
+ bc->len = dbgfmt_dwarf2->sizeof_offset + 2;
+ if (dbgfmt_dwarf2->format == DWARF2_FORMAT_64BIT)
+ bc->len += 4;
+
+ if (debug_ptr) {
+ head->debug_ptr = debug_ptr;
+ bc->len += dbgfmt_dwarf2->sizeof_offset;
+ } else
+ head->debug_ptr = NULL;
+
+ head->with_address = with_address;
+ head->with_segment = with_segment;
+ if (with_address)
+ bc->len++;
+ if (with_segment)
+ bc->len++;
+
+ head->end_prevbc = bc;
+ yasm_dwarf2__append_bc(sect, bc);
+ return head;
+}
+
+void
+yasm_dwarf2__set_head_end(dwarf2_head *head, yasm_bytecode *end_prevbc)
+{
+ head->end_prevbc = end_prevbc;
+}
+
+static void
+dwarf2_head_bc_destroy(void *contents)
+{
+ yasm_xfree(contents);
+}
+
+static void
+dwarf2_head_bc_print(const void *contents, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+static int
+dwarf2_head_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ yasm_internal_error(N_("tried to calc_len a dwarf2 head bytecode"));
+ /*@notreached@*/
+ return 0;
+}
+
+static int
+dwarf2_head_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ yasm_object *object = yasm_section_get_object(bc->section);
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)object->dbgfmt;
+ dwarf2_head *head = (dwarf2_head *)bc->contents;
+ unsigned char *buf = *bufp;
+ yasm_intnum *intn, *cval;
+
+ if (dbgfmt_dwarf2->format == DWARF2_FORMAT_64BIT) {
+ YASM_WRITE_8(buf, 0xff);
+ YASM_WRITE_8(buf, 0xff);
+ YASM_WRITE_8(buf, 0xff);
+ YASM_WRITE_8(buf, 0xff);
+ }
+
+ /* Total length of aranges info (following this field) */
+ cval = yasm_intnum_create_uint(dbgfmt_dwarf2->sizeof_offset);
+ intn = yasm_calc_bc_dist(head->start_prevbc, head->end_prevbc);
+ yasm_intnum_calc(intn, YASM_EXPR_SUB, cval);
+ yasm_arch_intnum_tobytes(object->arch, intn, buf,
+ dbgfmt_dwarf2->sizeof_offset,
+ dbgfmt_dwarf2->sizeof_offset*8, 0, bc, 0);
+ buf += dbgfmt_dwarf2->sizeof_offset;
+ yasm_intnum_destroy(intn);
+
+ /* DWARF version */
+ yasm_intnum_set_uint(cval, 2);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf, 2, 16, 0, bc, 0);
+ buf += 2;
+
+ /* Pointer to another debug section */
+ if (head->debug_ptr) {
+ yasm_value value;
+ yasm_value_init_sym(&value,
+ yasm_dwarf2__bc_sym(object->symtab,
+ yasm_section_bcs_first(head->debug_ptr)),
+ dbgfmt_dwarf2->sizeof_offset*8);
+ output_value(&value, buf, dbgfmt_dwarf2->sizeof_offset,
+ (unsigned long)(buf-bufstart), bc, 0, d);
+ buf += dbgfmt_dwarf2->sizeof_offset;
+ }
+
+ /* Size of the offset portion of the address */
+ if (head->with_address)
+ YASM_WRITE_8(buf, dbgfmt_dwarf2->sizeof_address);
+
+ /* Size of a segment descriptor. 0 = flat address space */
+ if (head->with_segment)
+ YASM_WRITE_8(buf, 0);
+
+ *bufp = buf;
+
+ yasm_intnum_destroy(cval);
+ return 0;
+}
+
+static void
+dwarf2_section_data_destroy(void *data)
+{
+ dwarf2_section_data *dsd = data;
+ dwarf2_loc *n1, *n2;
+
+ /* Delete locations */
+ n1 = STAILQ_FIRST(&dsd->locs);
+ while (n1) {
+ n2 = STAILQ_NEXT(n1, link);
+ yasm_xfree(n1);
+ n1 = n2;
+ }
+
+ yasm_xfree(data);
+}
+
+static void
+dwarf2_section_data_print(void *data, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+static const yasm_directive dwarf2_directives[] = {
+ { ".loc", "gas", yasm_dwarf2__dir_loc, YASM_DIR_ARG_REQUIRED },
+ { ".file", "gas", yasm_dwarf2__dir_file, YASM_DIR_ARG_REQUIRED },
+ { "loc", "nasm", yasm_dwarf2__dir_loc, YASM_DIR_ARG_REQUIRED },
+ { "file", "nasm", yasm_dwarf2__dir_file, YASM_DIR_ARG_REQUIRED },
+ { NULL, NULL, NULL, 0 }
+};
+
+/* Define dbgfmt structure -- see dbgfmt.h for details */
+yasm_dbgfmt_module yasm_dwarf2_LTX_dbgfmt = {
+ "DWARF2 debugging format",
+ "dwarf2",
+ dwarf2_directives,
+ dwarf2_dbgfmt_create,
+ dwarf2_dbgfmt_destroy,
+ dwarf2_dbgfmt_generate
+};
diff --git a/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.h b/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.h
new file mode 100644
index 0000000000..03752345cd
--- /dev/null
+++ b/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.h
@@ -0,0 +1,131 @@
+/*
+ * DWARF2 debugging format
+ *
+ * Copyright (C) 2006-2007 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.
+ */
+#ifndef YASM_DWARF2_DBGFMT_H
+#define YASM_DWARF2_DBGFMT_H
+
+#define WITH_DWARF3 1
+
+typedef struct {
+ char *pathname; /* full filename */
+ char *filename; /* basename of full filename */
+ unsigned long dir; /* index into directories array for relative path;
+ * 0 for current directory. */
+} dwarf2_filename;
+
+/* Global data */
+typedef struct yasm_dbgfmt_dwarf2 {
+ yasm_dbgfmt_base dbgfmt; /* base structure */
+
+ char **dirs;
+ unsigned long dirs_size;
+ unsigned long dirs_allocated;
+
+ dwarf2_filename *filenames;
+ unsigned long filenames_size;
+ unsigned long filenames_allocated;
+
+ enum {
+ DWARF2_FORMAT_32BIT,
+ DWARF2_FORMAT_64BIT
+ } format;
+
+ unsigned int sizeof_address, sizeof_offset, min_insn_len;
+} yasm_dbgfmt_dwarf2;
+
+/* .loc directive data */
+typedef struct dwarf2_loc {
+ /*@reldef@*/ STAILQ_ENTRY(dwarf2_loc) link;
+
+ unsigned long vline; /* virtual line number of .loc directive */
+
+ /* source information */
+ unsigned long file; /* index into table of filenames */
+ unsigned long line; /* source line number */
+ unsigned long column; /* source column */
+ unsigned long discriminator;
+ int isa_change;
+ unsigned long isa;
+ enum {
+ IS_STMT_NOCHANGE = 0,
+ IS_STMT_SET,
+ IS_STMT_CLEAR
+ } is_stmt;
+ int basic_block;
+ int prologue_end;
+ int epilogue_begin;
+
+ yasm_bytecode *bc; /* first bytecode following */
+ yasm_symrec *sym; /* last symbol preceding */
+} dwarf2_loc;
+
+/* Per-section data */
+typedef struct dwarf2_section_data {
+ /* The locations set by the .loc directives in this section, in assembly
+ * source order.
+ */
+ /*@reldef@*/ STAILQ_HEAD(dwarf2_lochead, dwarf2_loc) locs;
+} dwarf2_section_data;
+
+extern const yasm_assoc_data_callback yasm_dwarf2__section_data_cb;
+
+yasm_bytecode *yasm_dwarf2__append_bc(yasm_section *sect, yasm_bytecode *bc);
+
+/*@dependent@*/ yasm_symrec *yasm_dwarf2__bc_sym(yasm_symtab *symtab,
+ yasm_bytecode *bc);
+
+typedef struct dwarf2_head dwarf2_head;
+dwarf2_head *yasm_dwarf2__add_head
+ (yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2, yasm_section *sect,
+ /*@null@*/ yasm_section *debug_ptr, int with_address, int with_segment);
+void yasm_dwarf2__set_head_end(dwarf2_head *head, yasm_bytecode *end_prevbc);
+
+/* Line number functions */
+yasm_section *yasm_dwarf2__generate_line
+ (yasm_object *object, yasm_linemap *linemap, yasm_errwarns *errwarns,
+ int asm_source, /*@out@*/ yasm_section **main_code,
+ /*@out@*/ size_t *num_line_sections);
+void yasm_dwarf2__dir_loc(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams,
+ unsigned long line);
+void yasm_dwarf2__dir_file(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams,
+ unsigned long line);
+
+/* Address range table functions */
+yasm_section *yasm_dwarf2__generate_aranges(yasm_object *object,
+ yasm_section *debug_info);
+
+/* Name lookup table functions */
+yasm_section *yasm_dwarf2__generate_pubnames(yasm_object *object,
+ yasm_section *debug_info);
+
+/* Information functions */
+yasm_section *yasm_dwarf2__generate_info
+ (yasm_object *object, yasm_section *debug_line,
+ /*@null@*/ yasm_section *main_code);
+
+#endif
diff --git a/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-info.c b/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-info.c
new file mode 100644
index 0000000000..96d24db06a
--- /dev/null
+++ b/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-info.c
@@ -0,0 +1,438 @@
+/*
+ * DWARF2 debugging format - info and abbreviation tables
+ *
+ * Copyright (C) 2006-2007 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 <util.h>
+
+#include <libyasm.h>
+
+#include "dwarf2-dbgfmt.h"
+
+#define DW_LANG_Mips_Assembler 0x8001
+
+/* Tag encodings */
+typedef enum {
+ DW_TAG_padding = 0x00,
+ DW_TAG_array_type = 0x01,
+ DW_TAG_class_type = 0x02,
+ DW_TAG_entry_point = 0x03,
+ DW_TAG_enumeration_type = 0x04,
+ DW_TAG_formal_parameter = 0x05,
+ DW_TAG_imported_declaration = 0x08,
+ DW_TAG_label = 0x0a,
+ DW_TAG_lexical_block = 0x0b,
+ DW_TAG_member = 0x0d,
+ DW_TAG_pointer_type = 0x0f,
+ DW_TAG_reference_type = 0x10,
+ DW_TAG_compile_unit = 0x11,
+ DW_TAG_string_type = 0x12,
+ DW_TAG_structure_type = 0x13,
+ DW_TAG_subroutine_type = 0x15,
+ DW_TAG_typedef = 0x16,
+ DW_TAG_union_type = 0x17,
+ DW_TAG_unspecified_parameters = 0x18,
+ DW_TAG_variant = 0x19,
+ DW_TAG_common_block = 0x1a,
+ DW_TAG_common_inclusion = 0x1b,
+ DW_TAG_inheritance = 0x1c,
+ DW_TAG_inlined_subroutine = 0x1d,
+ DW_TAG_module = 0x1e,
+ DW_TAG_ptr_to_member_type = 0x1f,
+ DW_TAG_set_type = 0x20,
+ DW_TAG_subrange_type = 0x21,
+ DW_TAG_with_stmt = 0x22,
+ DW_TAG_access_declaration = 0x23,
+ DW_TAG_base_type = 0x24,
+ DW_TAG_catch_block = 0x25,
+ DW_TAG_const_type = 0x26,
+ DW_TAG_constant = 0x27,
+ DW_TAG_enumerator = 0x28,
+ DW_TAG_file_type = 0x29,
+ DW_TAG_friend = 0x2a,
+ DW_TAG_namelist = 0x2b,
+ DW_TAG_namelist_item = 0x2c,
+ DW_TAG_packed_type = 0x2d,
+ DW_TAG_subprogram = 0x2e,
+ DW_TAG_template_type_param = 0x2f,
+ DW_TAG_template_value_param = 0x30,
+ DW_TAG_thrown_type = 0x31,
+ DW_TAG_try_block = 0x32,
+ DW_TAG_variant_part = 0x33,
+ DW_TAG_variable = 0x34,
+ DW_TAG_volatile_type = 0x35
+} dwarf_tag;
+
+/* Attribute form encodings */
+typedef enum {
+ DW_FORM_addr = 0x01,
+ DW_FORM_block2 = 0x03,
+ DW_FORM_block4 = 0x04,
+ DW_FORM_data2 = 0x05,
+ DW_FORM_data4 = 0x06,
+ DW_FORM_data8 = 0x07,
+ DW_FORM_string = 0x08,
+ DW_FORM_block = 0x09,
+ DW_FORM_block1 = 0x0a,
+ DW_FORM_data1 = 0x0b,
+ DW_FORM_flag = 0x0c,
+ DW_FORM_sdata = 0x0d,
+ DW_FORM_strp = 0x0e,
+ DW_FORM_udata = 0x0f,
+ DW_FORM_ref_addr = 0x10,
+ DW_FORM_ref1 = 0x11,
+ DW_FORM_ref2 = 0x12,
+ DW_FORM_ref4 = 0x13,
+ DW_FORM_ref8 = 0x14,
+ DW_FORM_ref_udata = 0x15,
+ DW_FORM_indirect = 0x16
+} dwarf_form;
+
+/* Attribute encodings */
+typedef enum {
+ DW_AT_sibling = 0x01,
+ DW_AT_location = 0x02,
+ DW_AT_name = 0x03,
+ DW_AT_ordering = 0x09,
+ DW_AT_subscr_data = 0x0a,
+ DW_AT_byte_size = 0x0b,
+ DW_AT_bit_offset = 0x0c,
+ DW_AT_bit_size = 0x0d,
+ DW_AT_element_list = 0x0f,
+ DW_AT_stmt_list = 0x10,
+ DW_AT_low_pc = 0x11,
+ DW_AT_high_pc = 0x12,
+ DW_AT_language = 0x13,
+ DW_AT_member = 0x14,
+ DW_AT_discr = 0x15,
+ DW_AT_discr_value = 0x16,
+ DW_AT_visibility = 0x17,
+ DW_AT_import = 0x18,
+ DW_AT_string_length = 0x19,
+ DW_AT_common_reference = 0x1a,
+ DW_AT_comp_dir = 0x1b,
+ DW_AT_const_value = 0x1c,
+ DW_AT_containing_type = 0x1d,
+ DW_AT_default_value = 0x1e,
+ DW_AT_inline = 0x20,
+ DW_AT_is_optional = 0x21,
+ DW_AT_lower_bound = 0x22,
+ DW_AT_producer = 0x25,
+ DW_AT_prototyped = 0x27,
+ DW_AT_return_addr = 0x2a,
+ DW_AT_start_scope = 0x2c,
+ DW_AT_stride_size = 0x2e,
+ DW_AT_upper_bound = 0x2f,
+ DW_AT_abstract_origin = 0x31,
+ DW_AT_accessibility = 0x32,
+ DW_AT_address_class = 0x33,
+ DW_AT_artificial = 0x34,
+ DW_AT_base_types = 0x35,
+ DW_AT_calling_convention = 0x36,
+ DW_AT_count = 0x37,
+ DW_AT_data_member_location = 0x38,
+ DW_AT_decl_column = 0x39,
+ DW_AT_decl_file = 0x3a,
+ DW_AT_decl_line = 0x3b,
+ DW_AT_declaration = 0x3c,
+ DW_AT_discr_list = 0x3d,
+ DW_AT_encoding = 0x3e,
+ DW_AT_external = 0x3f,
+ DW_AT_frame_base = 0x40,
+ DW_AT_friend = 0x41,
+ DW_AT_identifier_case = 0x42,
+ DW_AT_macro_info = 0x43,
+ DW_AT_namelist_items = 0x44,
+ DW_AT_priority = 0x45,
+ DW_AT_segment = 0x46,
+ DW_AT_specification = 0x47,
+ DW_AT_static_link = 0x48,
+ DW_AT_type = 0x49,
+ DW_AT_use_location = 0x4a,
+ DW_AT_variable_parameter = 0x4b,
+ DW_AT_virtuality = 0x4c,
+ DW_AT_vtable_elem_location = 0x4d
+} dwarf_attribute;
+
+typedef struct dwarf2_abbrev_attr {
+ STAILQ_ENTRY(dwarf2_abbrev_attr) link;
+ dwarf_attribute name;
+ dwarf_form form;
+} dwarf2_abbrev_attr;
+
+typedef struct dwarf2_abbrev {
+ unsigned long id;
+ dwarf_tag tag;
+ int has_children;
+ STAILQ_HEAD(dwarf2_abbrev_attrhead, dwarf2_abbrev_attr) attrs;
+} dwarf2_abbrev;
+
+/* Bytecode callback function prototypes */
+
+static void dwarf2_abbrev_bc_destroy(void *contents);
+static void dwarf2_abbrev_bc_print(const void *contents, FILE *f,
+ int indent_level);
+static int dwarf2_abbrev_bc_calc_len
+ (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
+static int dwarf2_abbrev_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+/* Bytecode callback structures */
+
+static const yasm_bytecode_callback dwarf2_abbrev_bc_callback = {
+ dwarf2_abbrev_bc_destroy,
+ dwarf2_abbrev_bc_print,
+ yasm_bc_finalize_common,
+ NULL,
+ dwarf2_abbrev_bc_calc_len,
+ yasm_bc_expand_common,
+ dwarf2_abbrev_bc_tobytes,
+ 0
+};
+
+
+static unsigned long
+dwarf2_add_abbrev_attr(dwarf2_abbrev *abbrev, dwarf_attribute name,
+ dwarf_form form)
+{
+ dwarf2_abbrev_attr *attr = yasm_xmalloc(sizeof(dwarf2_abbrev_attr));
+ attr->name = name;
+ attr->form = form;
+ STAILQ_INSERT_TAIL(&abbrev->attrs, attr, link);
+ return yasm_size_uleb128(name) + yasm_size_uleb128(form);
+}
+
+static void
+dwarf2_append_expr(yasm_section *sect, /*@only@*/ yasm_expr *expr,
+ unsigned int size, int leb)
+{
+ yasm_datavalhead dvs;
+ yasm_bytecode *bc;
+
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(expr));
+ if (leb == 0)
+ bc = yasm_bc_create_data(&dvs, size, 0, NULL, 0);
+ else
+ bc = yasm_bc_create_leb128(&dvs, leb<0, 0);
+ yasm_bc_finalize(bc, yasm_dwarf2__append_bc(sect, bc));
+ yasm_bc_calc_len(bc, NULL, NULL);
+}
+
+static void
+dwarf2_append_str(yasm_section *sect, const char *str)
+{
+ yasm_datavalhead dvs;
+ yasm_bytecode *bc;
+
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_string(yasm__xstrdup(str),
+ strlen(str)));
+ bc = yasm_bc_create_data(&dvs, 1, 1, NULL, 0);
+ yasm_bc_finalize(bc, yasm_dwarf2__append_bc(sect, bc));
+ yasm_bc_calc_len(bc, NULL, NULL);
+}
+
+yasm_section *
+yasm_dwarf2__generate_info(yasm_object *object, yasm_section *debug_line,
+ yasm_section *main_code)
+{
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)object->dbgfmt;
+ int new;
+ yasm_bytecode *abc;
+ dwarf2_abbrev *abbrev;
+ dwarf2_head *head;
+ char *buf;
+ yasm_section *debug_abbrev =
+ yasm_object_get_general(object, ".debug_abbrev", 4, 0, 0, &new, 0);
+ yasm_section *debug_info =
+ yasm_object_get_general(object, ".debug_info", 4, 0, 0, &new, 0);
+
+ yasm_section_set_align(debug_abbrev, 0, 0);
+ yasm_section_set_align(debug_info, 0, 0);
+
+ /* Create abbreviation table entry for compilation unit */
+ abbrev = yasm_xmalloc(sizeof(dwarf2_abbrev));
+ abc = yasm_bc_create_common(&dwarf2_abbrev_bc_callback, abbrev, 0);
+ abbrev->id = 1;
+ abbrev->tag = DW_TAG_compile_unit;
+ abbrev->has_children = 0;
+ abc->len = yasm_size_uleb128(abbrev->id) + yasm_size_uleb128(abbrev->tag)
+ + 3;
+ STAILQ_INIT(&abbrev->attrs);
+ yasm_dwarf2__append_bc(debug_abbrev, abc);
+
+ /* info header */
+ head = yasm_dwarf2__add_head(dbgfmt_dwarf2, debug_info, debug_abbrev, 1, 0);
+
+ /* Generate abbreviations at the same time as info (since they're linked
+ * and we're only generating one piece of info).
+ */
+
+ /* generating info using abbrev 1 */
+ dwarf2_append_expr(debug_info,
+ yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(1)), 0),
+ 0, 1);
+
+ /* statement list (line numbers) */
+ abc->len += dwarf2_add_abbrev_attr(abbrev, DW_AT_stmt_list, DW_FORM_data4);
+ dwarf2_append_expr(debug_info,
+ yasm_expr_create_ident(yasm_expr_sym(
+ yasm_dwarf2__bc_sym(object->symtab,
+ yasm_section_bcs_first(debug_line))), 0),
+ dbgfmt_dwarf2->sizeof_offset, 0);
+
+ if (main_code) {
+ yasm_symrec *first;
+ first = yasm_dwarf2__bc_sym(object->symtab,
+ yasm_section_bcs_first(main_code));
+ /* All code is contiguous in one section */
+ abc->len += dwarf2_add_abbrev_attr(abbrev, DW_AT_low_pc, DW_FORM_addr);
+ dwarf2_append_expr(debug_info,
+ yasm_expr_create_ident(yasm_expr_sym(first), 0),
+ dbgfmt_dwarf2->sizeof_address, 0);
+
+ abc->len += dwarf2_add_abbrev_attr(abbrev, DW_AT_high_pc, DW_FORM_addr);
+ dwarf2_append_expr(debug_info,
+ yasm_expr_create(YASM_EXPR_ADD, yasm_expr_sym(first),
+ yasm_expr_int(yasm_calc_bc_dist(
+ yasm_section_bcs_first(main_code),
+ yasm_section_bcs_last(main_code))), 0),
+ dbgfmt_dwarf2->sizeof_address, 0);
+ }
+
+ /* input filename */
+ abc->len += dwarf2_add_abbrev_attr(abbrev, DW_AT_name, DW_FORM_string);
+ if (!object->deb_filename) {
+ object->deb_filename = yasm_replace_path(
+ dbgfmt_dwarf2->dbgfmt.module->replace_map, dbgfmt_dwarf2->dbgfmt.module->replace_map_size,
+ object->src_filename, strlen(object->src_filename));
+ }
+ dwarf2_append_str(debug_info, object->deb_filename);
+
+ /* compile directory (current working directory) */
+ abc->len += dwarf2_add_abbrev_attr(abbrev, DW_AT_comp_dir, DW_FORM_string);
+ buf = yasm__getcwd();
+ char * new_cwd_name = yasm_replace_path(
+ dbgfmt_dwarf2->dbgfmt.module->replace_map, dbgfmt_dwarf2->dbgfmt.module->replace_map_size,
+ buf, strlen(buf));
+ dwarf2_append_str(debug_info, new_cwd_name);
+ yasm_xfree(new_cwd_name);
+ yasm_xfree(buf);
+
+ /* producer - assembler name */
+ abc->len += dwarf2_add_abbrev_attr(abbrev, DW_AT_producer, DW_FORM_string);
+ if (getenv("YASM_TEST_SUITE"))
+ dwarf2_append_str(debug_info, "yasm HEAD");
+ else
+ dwarf2_append_str(debug_info, PACKAGE_STRING);
+
+ /* language - no standard code for assembler, use MIPS as a substitute */
+ abc->len += dwarf2_add_abbrev_attr(abbrev, DW_AT_language, DW_FORM_data2);
+ dwarf2_append_expr(debug_info,
+ yasm_expr_create_ident(yasm_expr_int(
+ yasm_intnum_create_uint(DW_LANG_Mips_Assembler)), 0), 2, 0);
+
+ /* Terminate list of abbreviations */
+ abbrev = yasm_xmalloc(sizeof(dwarf2_abbrev));
+ abc = yasm_bc_create_common(&dwarf2_abbrev_bc_callback, abbrev, 0);
+ abbrev->id = 0;
+ abbrev->tag = 0;
+ abbrev->has_children = 0;
+ STAILQ_INIT(&abbrev->attrs);
+ abc->len = 1;
+ yasm_dwarf2__append_bc(debug_abbrev, abc);
+
+ /* mark end of info */
+ yasm_dwarf2__set_head_end(head, yasm_section_bcs_last(debug_info));
+
+ return debug_info;
+}
+
+static void
+dwarf2_abbrev_bc_destroy(void *contents)
+{
+ dwarf2_abbrev *abbrev = (dwarf2_abbrev *)contents;
+ dwarf2_abbrev_attr *n1, *n2;
+
+ /* Delete attributes */
+ n1 = STAILQ_FIRST(&abbrev->attrs);
+ while (n1) {
+ n2 = STAILQ_NEXT(n1, link);
+ yasm_xfree(n1);
+ n1 = n2;
+ }
+
+ yasm_xfree(contents);
+}
+
+static void
+dwarf2_abbrev_bc_print(const void *contents, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+static int
+dwarf2_abbrev_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ yasm_internal_error(N_("tried to calc_len a dwarf2 aranges head bytecode"));
+ /*@notreached@*/
+ return 0;
+}
+
+static int
+dwarf2_abbrev_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ dwarf2_abbrev *abbrev = (dwarf2_abbrev *)bc->contents;
+ unsigned char *buf = *bufp;
+ dwarf2_abbrev_attr *attr;
+
+ if (abbrev->id == 0) {
+ YASM_WRITE_8(buf, 0);
+ *bufp = buf;
+ return 0;
+ }
+
+ buf += yasm_get_uleb128(abbrev->id, buf);
+ buf += yasm_get_uleb128(abbrev->tag, buf);
+ YASM_WRITE_8(buf, abbrev->has_children);
+
+ STAILQ_FOREACH(attr, &abbrev->attrs, link) {
+ buf += yasm_get_uleb128(attr->name, buf);
+ buf += yasm_get_uleb128(attr->form, buf);
+ }
+
+ YASM_WRITE_8(buf, 0);
+ YASM_WRITE_8(buf, 0);
+
+ *bufp = buf;
+ return 0;
+}
+
diff --git a/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-line.c b/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-line.c
new file mode 100644
index 0000000000..14639ca429
--- /dev/null
+++ b/contrib/tools/yasm/modules/dbgfmts/dwarf2/dwarf2-line.c
@@ -0,0 +1,1156 @@
+/*
+ * DWARF2 debugging format - line information
+ *
+ * Copyright (C) 2006-2007 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.
+ * 3. Neither the name of the author nor the names of other contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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 <util.h>
+
+#include <libyasm.h>
+
+#include "dwarf2-dbgfmt.h"
+
+/* DWARF line number opcodes */
+typedef enum {
+ DW_LNS_extended_op = 0,
+ DW_LNS_copy,
+ DW_LNS_advance_pc,
+ DW_LNS_advance_line,
+ DW_LNS_set_file,
+ DW_LNS_set_column,
+ DW_LNS_negate_stmt,
+ DW_LNS_set_basic_block,
+ DW_LNS_const_add_pc,
+ DW_LNS_fixed_advance_pc,
+#ifdef WITH_DWARF3
+ /* DWARF 3 extensions */
+ DW_LNS_set_prologue_end,
+ DW_LNS_set_epilogue_begin,
+ DW_LNS_set_isa,
+#endif
+ DWARF2_LINE_OPCODE_BASE
+} dwarf_line_number_op;
+
+/* # of LEB128 operands needed for each of the above opcodes */
+static unsigned char line_opcode_num_operands[DWARF2_LINE_OPCODE_BASE-1] = {
+ 0, /* DW_LNS_copy */
+ 1, /* DW_LNS_advance_pc */
+ 1, /* DW_LNS_advance_line */
+ 1, /* DW_LNS_set_file */
+ 1, /* DW_LNS_set_column */
+ 0, /* DW_LNS_negate_stmt */
+ 0, /* DW_LNS_set_basic_block */
+ 0, /* DW_LNS_const_add_pc */
+ 1, /* DW_LNS_fixed_advance_pc */
+#ifdef WITH_DWARF3
+ 0, /* DW_LNS_set_prologue_end */
+ 0, /* DW_LNS_set_epilogue_begin */
+ 1 /* DW_LNS_set_isa */
+#endif
+};
+
+/* Line number extended opcodes */
+typedef enum {
+ DW_LNE_end_sequence = 1,
+ DW_LNE_set_address,
+ DW_LNE_define_file,
+ DW_LNE_set_discriminator
+} dwarf_line_number_ext_op;
+
+/* Base and range for line offsets in special opcodes */
+#define DWARF2_LINE_BASE -5
+#define DWARF2_LINE_RANGE 14
+
+#define DWARF2_MAX_SPECIAL_ADDR_DELTA \
+ (((255-DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE)*\
+ dbgfmt_dwarf2->min_insn_len)
+
+/* Initial value of is_stmt register */
+#define DWARF2_LINE_DEFAULT_IS_STMT 1
+
+/* Line number state machine register state */
+typedef struct dwarf2_line_state {
+ /* static configuration */
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2;
+
+ /* DWARF2 state machine registers */
+ unsigned long address;
+ unsigned long file;
+ unsigned long line;
+ unsigned long column;
+ unsigned long isa;
+ int is_stmt;
+
+ /* other state information */
+ /*@null@*/ yasm_bytecode *precbc;
+} dwarf2_line_state;
+
+typedef struct dwarf2_spp {
+ yasm_bytecode *line_start_prevbc;
+ yasm_bytecode *line_end_prevbc;
+} dwarf2_spp;
+
+typedef struct dwarf2_line_op {
+ dwarf_line_number_op opcode;
+ /*@owned@*/ /*@null@*/ yasm_intnum *operand;
+
+ /* extended opcode */
+ dwarf_line_number_ext_op ext_opcode;
+ /*@null@*/ /*@dependent@*/ yasm_symrec *ext_operand; /* unsigned */
+ /*@null@*/ /*@dependent@*/ yasm_intnum *ext_operand_int; /* unsigned */
+ unsigned long ext_operandsize;
+} dwarf2_line_op;
+
+/* Bytecode callback function prototypes */
+static void dwarf2_spp_bc_destroy(void *contents);
+static void dwarf2_spp_bc_print(const void *contents, FILE *f,
+ int indent_level);
+static int dwarf2_spp_bc_calc_len
+ (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
+static int dwarf2_spp_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static void dwarf2_line_op_bc_destroy(void *contents);
+static void dwarf2_line_op_bc_print(const void *contents, FILE *f,
+ int indent_level);
+static int dwarf2_line_op_bc_calc_len
+ (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
+static int dwarf2_line_op_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+/* Bytecode callback structures */
+static const yasm_bytecode_callback dwarf2_spp_bc_callback = {
+ dwarf2_spp_bc_destroy,
+ dwarf2_spp_bc_print,
+ yasm_bc_finalize_common,
+ NULL,
+ dwarf2_spp_bc_calc_len,
+ yasm_bc_expand_common,
+ dwarf2_spp_bc_tobytes,
+ 0
+};
+
+static const yasm_bytecode_callback dwarf2_line_op_bc_callback = {
+ dwarf2_line_op_bc_destroy,
+ dwarf2_line_op_bc_print,
+ yasm_bc_finalize_common,
+ NULL,
+ dwarf2_line_op_bc_calc_len,
+ yasm_bc_expand_common,
+ dwarf2_line_op_bc_tobytes,
+ 0
+};
+
+
+static size_t
+dwarf2_dbgfmt_add_file(yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2, unsigned long filenum,
+ const char *pathname)
+{
+ size_t dirlen;
+ const char *filename;
+ unsigned long i, dir;
+
+ /* Put the directory into the directory table */
+ dir = 0;
+ dirlen = yasm__splitpath(pathname, &filename);
+ if (dirlen > 0) {
+ /* Look to see if we already have that dir in the table */
+ for (dir=1; dir<dbgfmt_dwarf2->dirs_size+1; dir++) {
+ if (strncmp(dbgfmt_dwarf2->dirs[dir-1], pathname, dirlen) == 0
+ && dbgfmt_dwarf2->dirs[dir-1][dirlen] == '\0')
+ break;
+ }
+ if (dir >= dbgfmt_dwarf2->dirs_size+1) {
+ /* Not found in table, add to end, reallocing if necessary */
+ if (dir >= dbgfmt_dwarf2->dirs_allocated+1) {
+ dbgfmt_dwarf2->dirs_allocated = dir+32;
+ dbgfmt_dwarf2->dirs = yasm_xrealloc(dbgfmt_dwarf2->dirs,
+ sizeof(char *)*dbgfmt_dwarf2->dirs_allocated);
+ }
+ dbgfmt_dwarf2->dirs[dir-1] = yasm__xstrndup(pathname, dirlen);
+ dbgfmt_dwarf2->dirs_size = dir;
+ }
+ }
+
+ /* Put the filename into the filename table */
+ if (filenum == 0) {
+ /* Look to see if we already have that filename in the table */
+ for (; filenum<dbgfmt_dwarf2->filenames_size; filenum++) {
+ if (!dbgfmt_dwarf2->filenames[filenum].filename ||
+ (dbgfmt_dwarf2->filenames[filenum].dir == dir
+ && strcmp(dbgfmt_dwarf2->filenames[filenum].filename,
+ filename) == 0))
+ break;
+ }
+ } else
+ filenum--; /* array index is 0-based */
+
+ /* Realloc table if necessary */
+ if (filenum >= dbgfmt_dwarf2->filenames_allocated) {
+ unsigned long old_allocated = dbgfmt_dwarf2->filenames_allocated;
+ dbgfmt_dwarf2->filenames_allocated = filenum+32;
+ dbgfmt_dwarf2->filenames = yasm_xrealloc(dbgfmt_dwarf2->filenames,
+ sizeof(dwarf2_filename)*dbgfmt_dwarf2->filenames_allocated);
+ for (i=old_allocated; i<dbgfmt_dwarf2->filenames_allocated; i++) {
+ dbgfmt_dwarf2->filenames[i].pathname = NULL;
+ dbgfmt_dwarf2->filenames[i].filename = NULL;
+ dbgfmt_dwarf2->filenames[i].dir = 0;
+ }
+ }
+
+ /* Actually save in table */
+ if (dbgfmt_dwarf2->filenames[filenum].pathname)
+ yasm_xfree(dbgfmt_dwarf2->filenames[filenum].pathname);
+ if (dbgfmt_dwarf2->filenames[filenum].filename)
+ yasm_xfree(dbgfmt_dwarf2->filenames[filenum].filename);
+ dbgfmt_dwarf2->filenames[filenum].pathname = yasm__xstrdup(pathname);
+ dbgfmt_dwarf2->filenames[filenum].filename = yasm__xstrdup(filename);
+ dbgfmt_dwarf2->filenames[filenum].dir = dir;
+
+ /* Update table size */
+ if (filenum >= dbgfmt_dwarf2->filenames_size)
+ dbgfmt_dwarf2->filenames_size = filenum + 1;
+
+ return filenum;
+}
+
+/* Create and add a new line opcode to a section, updating offset on insertion;
+ * no optimization necessary.
+ */
+static yasm_bytecode *
+dwarf2_dbgfmt_append_line_op(yasm_section *sect, dwarf_line_number_op opcode,
+ /*@only@*/ /*@null@*/ yasm_intnum *operand)
+{
+ dwarf2_line_op *line_op = yasm_xmalloc(sizeof(dwarf2_line_op));
+ yasm_bytecode *bc;
+
+ line_op->opcode = opcode;
+ line_op->operand = operand;
+ line_op->ext_opcode = 0;
+ line_op->ext_operand = NULL;
+ line_op->ext_operand_int = NULL;
+ line_op->ext_operandsize = 0;
+
+ bc = yasm_bc_create_common(&dwarf2_line_op_bc_callback, line_op, 0);
+ bc->len = 1;
+ if (operand)
+ bc->len += yasm_intnum_size_leb128(operand,
+ opcode == DW_LNS_advance_line);
+
+ yasm_dwarf2__append_bc(sect, bc);
+ return bc;
+}
+
+/* Create and add a new extended line opcode to a section, updating offset on
+ * insertion; no optimization necessary.
+ */
+static yasm_bytecode *
+dwarf2_dbgfmt_append_line_ext_op(yasm_section *sect,
+ dwarf_line_number_ext_op ext_opcode,
+ unsigned long ext_operandsize,
+ /*@null@*/ yasm_symrec *ext_operand)
+{
+ dwarf2_line_op *line_op = yasm_xmalloc(sizeof(dwarf2_line_op));
+ yasm_bytecode *bc;
+
+ line_op->opcode = DW_LNS_extended_op;
+ line_op->operand = yasm_intnum_create_uint(ext_operandsize+1);
+ line_op->ext_opcode = ext_opcode;
+ line_op->ext_operand = ext_operand;
+ line_op->ext_operand_int = NULL;
+ line_op->ext_operandsize = ext_operandsize;
+
+ bc = yasm_bc_create_common(&dwarf2_line_op_bc_callback, line_op, 0);
+ bc->len = 2 + yasm_intnum_size_leb128(line_op->operand, 0) +
+ ext_operandsize;
+
+ yasm_dwarf2__append_bc(sect, bc);
+ return bc;
+}
+
+static yasm_bytecode *
+dwarf2_dbgfmt_append_line_ext_op_int(yasm_section *sect,
+ dwarf_line_number_ext_op ext_opcode,
+ /*@only@*/ yasm_intnum *ext_operand)
+{
+ dwarf2_line_op *line_op = yasm_xmalloc(sizeof(dwarf2_line_op));
+ unsigned long ext_operandsize = yasm_intnum_size_leb128(ext_operand, 0);
+ yasm_bytecode *bc;
+
+ line_op->opcode = DW_LNS_extended_op;
+ line_op->operand = yasm_intnum_create_uint(ext_operandsize+1);
+ line_op->ext_opcode = ext_opcode;
+ line_op->ext_operand = NULL;
+ line_op->ext_operand_int = ext_operand;
+ line_op->ext_operandsize = ext_operandsize;
+
+ bc = yasm_bc_create_common(&dwarf2_line_op_bc_callback, line_op, 0);
+ bc->len = 2 + yasm_intnum_size_leb128(line_op->operand, 0) +
+ ext_operandsize;
+
+ yasm_dwarf2__append_bc(sect, bc);
+ return bc;
+}
+
+static void
+dwarf2_dbgfmt_finalize_locs(yasm_section *sect, dwarf2_section_data *dsd)
+{
+ /*@dependent@*/ yasm_symrec *lastsym = NULL;
+ /*@null@*/ yasm_bytecode *bc;
+ /*@null@*/ dwarf2_loc *loc;
+
+ bc = yasm_section_bcs_first(sect);
+ STAILQ_FOREACH(loc, &dsd->locs, link) {
+ /* Find the first bytecode following this loc by looking at
+ * the virtual line numbers. XXX: this assumes the source file
+ * order will be the same as the actual section order. If we ever
+ * implement subsegs this will NOT necessarily be true and this logic
+ * will need to be fixed to handle it!
+ *
+ * Keep track of last symbol seen prior to the loc.
+ */
+ while (bc && bc->line <= loc->vline) {
+ if (bc->symrecs) {
+ int i = 0;
+ while (bc->symrecs[i]) {
+ lastsym = bc->symrecs[i];
+ i++;
+ }
+ }
+ bc = yasm_bc__next(bc);
+ }
+ loc->sym = lastsym;
+ loc->bc = bc;
+ }
+}
+
+static int
+dwarf2_dbgfmt_gen_line_op(yasm_section *debug_line, dwarf2_line_state *state,
+ const dwarf2_loc *loc,
+ /*@null@*/ const dwarf2_loc *nextloc)
+{
+ unsigned long addr_delta;
+ long line_delta;
+ int opcode1, opcode2;
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = state->dbgfmt_dwarf2;
+
+ if (state->file != loc->file) {
+ state->file = loc->file;
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_file,
+ yasm_intnum_create_uint(state->file));
+ }
+ if (state->column != loc->column) {
+ state->column = loc->column;
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_column,
+ yasm_intnum_create_uint(state->column));
+ }
+ if (loc->discriminator != 0) {
+ dwarf2_dbgfmt_append_line_ext_op_int(debug_line,
+ DW_LNE_set_discriminator,
+ yasm_intnum_create_uint(loc->discriminator));
+ }
+#ifdef WITH_DWARF3
+ if (loc->isa_change) {
+ state->isa = loc->isa;
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_isa,
+ yasm_intnum_create_uint(state->isa));
+ }
+#endif
+ if (state->is_stmt == 0 && loc->is_stmt == IS_STMT_SET) {
+ state->is_stmt = 1;
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_negate_stmt, NULL);
+ } else if (state->is_stmt == 1 && loc->is_stmt == IS_STMT_CLEAR) {
+ state->is_stmt = 0;
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_negate_stmt, NULL);
+ }
+ if (loc->basic_block) {
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_basic_block, NULL);
+ }
+#ifdef WITH_DWARF3
+ if (loc->prologue_end) {
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_prologue_end, NULL);
+ }
+ if (loc->epilogue_begin) {
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_set_epilogue_begin,
+ NULL);
+ }
+#endif
+
+ /* If multiple loc for the same location, use last */
+ if (nextloc && nextloc->bc->offset == loc->bc->offset)
+ return 0;
+
+ if (!state->precbc) {
+ /* Set the starting address for the section */
+ if (!loc->sym) {
+ /* shouldn't happen! */
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("could not find label prior to loc"));
+ return 1;
+ }
+ dwarf2_dbgfmt_append_line_ext_op(debug_line, DW_LNE_set_address,
+ dbgfmt_dwarf2->sizeof_address, loc->sym);
+ addr_delta = 0;
+ } else if (loc->bc) {
+ if (state->precbc->offset > loc->bc->offset)
+ yasm_internal_error(N_("dwarf2 address went backwards?"));
+ addr_delta = loc->bc->offset - state->precbc->offset;
+ } else
+ return 0; /* ran out of bytecodes! XXX: do something? */
+
+ /* Generate appropriate opcode(s). Address can only increment,
+ * whereas line number can go backwards.
+ */
+ line_delta = loc->line - state->line;
+ state->line = loc->line;
+
+ /* First handle the line delta */
+ if (line_delta < DWARF2_LINE_BASE
+ || line_delta >= DWARF2_LINE_BASE+DWARF2_LINE_RANGE) {
+ /* Won't fit in special opcode, use (signed) line advance */
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_advance_line,
+ yasm_intnum_create_int(line_delta));
+ line_delta = 0;
+ }
+
+ /* Next handle the address delta */
+ opcode1 = DWARF2_LINE_OPCODE_BASE + line_delta - DWARF2_LINE_BASE +
+ DWARF2_LINE_RANGE * (addr_delta / dbgfmt_dwarf2->min_insn_len);
+ opcode2 = DWARF2_LINE_OPCODE_BASE + line_delta - DWARF2_LINE_BASE +
+ DWARF2_LINE_RANGE * ((addr_delta - DWARF2_MAX_SPECIAL_ADDR_DELTA) /
+ dbgfmt_dwarf2->min_insn_len);
+ if (line_delta == 0 && addr_delta == 0) {
+ /* Both line and addr deltas are 0: do DW_LNS_copy */
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_copy, NULL);
+ } else if (addr_delta <= DWARF2_MAX_SPECIAL_ADDR_DELTA && opcode1 <= 255) {
+ /* Addr delta in range of special opcode */
+ dwarf2_dbgfmt_append_line_op(debug_line, opcode1, NULL);
+ } else if (addr_delta <= 2*DWARF2_MAX_SPECIAL_ADDR_DELTA
+ && opcode2 <= 255) {
+ /* Addr delta in range of const_add_pc + special */
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_const_add_pc, NULL);
+ dwarf2_dbgfmt_append_line_op(debug_line, opcode2, NULL);
+ } else {
+ /* Need advance_pc */
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_advance_pc,
+ yasm_intnum_create_uint(addr_delta));
+ /* Take care of any remaining line_delta and add entry to matrix */
+ if (line_delta == 0)
+ dwarf2_dbgfmt_append_line_op(debug_line, DW_LNS_copy, NULL);
+ else {
+ unsigned int opcode;
+ opcode = DWARF2_LINE_OPCODE_BASE + line_delta - DWARF2_LINE_BASE;
+ dwarf2_dbgfmt_append_line_op(debug_line, opcode, NULL);
+ }
+ }
+ state->precbc = loc->bc;
+ return 0;
+}
+
+typedef struct dwarf2_line_bc_info {
+ yasm_section *debug_line;
+ yasm_object *object;
+ yasm_linemap *linemap;
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2;
+ dwarf2_line_state *state;
+ dwarf2_loc loc;
+ unsigned long lastfile;
+} dwarf2_line_bc_info;
+
+static int
+dwarf2_filename_equals(const dwarf2_filename *fn,
+ char **dirs,
+ const char *pathname,
+ unsigned long dirlen,
+ const char *filename)
+{
+ /* check directory */
+ if (fn->dir == 0) {
+ if (dirlen != 0)
+ return 0;
+ } else {
+ if (strncmp(dirs[fn->dir-1], pathname, dirlen) != 0 ||
+ dirs[fn->dir-1][dirlen] != '\0')
+ return 0;
+ }
+
+ /* check filename */
+ return strcmp(fn->filename, filename) == 0;
+}
+
+static int
+dwarf2_generate_line_bc(yasm_bytecode *bc, /*@null@*/ void *d)
+{
+ dwarf2_line_bc_info *info = (dwarf2_line_bc_info *)d;
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = info->dbgfmt_dwarf2;
+ unsigned long i;
+ size_t dirlen;
+ const char *pathname, *filename;
+ /*@null@*/ yasm_bytecode *nextbc = yasm_bc__next(bc);
+
+ if (nextbc && bc->offset == nextbc->offset)
+ return 0;
+
+ info->loc.vline = bc->line;
+ info->loc.bc = bc;
+
+ /* Keep track of last symbol seen */
+ if (bc->symrecs) {
+ i = 0;
+ while (bc->symrecs[i]) {
+ info->loc.sym = bc->symrecs[i];
+ i++;
+ }
+ }
+
+ yasm_linemap_lookup(info->linemap, bc->line, &pathname, &info->loc.line);
+ dirlen = yasm__splitpath(pathname, &filename);
+ char * new_dir_name = yasm_replace_path(
+ dbgfmt_dwarf2->dbgfmt.module->replace_map, dbgfmt_dwarf2->dbgfmt.module->replace_map_size,
+ pathname, dirlen);
+ dirlen = strlen(new_dir_name);
+
+ /* Find file index; just linear search it unless it was the last used */
+ if (info->lastfile > 0
+ && dwarf2_filename_equals(&dbgfmt_dwarf2->filenames[info->lastfile-1],
+ dbgfmt_dwarf2->dirs, new_dir_name, dirlen,
+ filename))
+ info->loc.file = info->lastfile;
+ else {
+ for (i=0; i<dbgfmt_dwarf2->filenames_size; i++) {
+ if (dwarf2_filename_equals(&dbgfmt_dwarf2->filenames[i],
+ dbgfmt_dwarf2->dirs, new_dir_name, dirlen,
+ filename))
+ break;
+ }
+ if (i >= dbgfmt_dwarf2->filenames_size)
+ yasm_internal_error(N_("could not find filename in table"));
+ info->loc.file = i+1;
+ info->lastfile = i+1;
+ }
+ yasm_xfree(new_dir_name);
+ if (dwarf2_dbgfmt_gen_line_op(info->debug_line, info->state, &info->loc,
+ NULL))
+ return 1;
+ return 0;
+}
+
+typedef struct dwarf2_line_info {
+ yasm_section *debug_line; /* section to which line number info goes */
+ yasm_object *object;
+ yasm_linemap *linemap;
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2;
+ yasm_errwarns *errwarns;
+
+ /* Generate based on bytecodes (1) or locs (0)? Use bytecodes if we're
+ * generating line numbers for the actual assembly source file.
+ */
+ int asm_source;
+
+ /* number of sections line number info generated for */
+ size_t num_sections;
+ /* last section line number info generated for */
+ /*@null@*/ yasm_section *last_code;
+} dwarf2_line_info;
+
+static int
+dwarf2_generate_line_section(yasm_section *sect, /*@null@*/ void *d)
+{
+ dwarf2_line_info *info = (dwarf2_line_info *)d;
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = info->dbgfmt_dwarf2;
+ /*@null@*/ dwarf2_section_data *dsd;
+ /*@null@*/ yasm_bytecode *bc;
+ dwarf2_line_state state;
+ unsigned long addr_delta;
+
+ dsd = yasm_section_get_data(sect, &yasm_dwarf2__section_data_cb);
+ if (!dsd) {
+ if (info->asm_source && yasm_section_is_code(sect)) {
+ /* Create line data for asm code sections */
+ dsd = yasm_xmalloc(sizeof(dwarf2_section_data));
+ STAILQ_INIT(&dsd->locs);
+ yasm_section_add_data(sect, &yasm_dwarf2__section_data_cb, dsd);
+ } else
+ return 0; /* no line data for this section */
+ }
+
+ info->num_sections++;
+ info->last_code = sect;
+
+ /* initialize state machine registers for each sequence */
+ state.dbgfmt_dwarf2 = dbgfmt_dwarf2;
+ state.address = 0;
+ state.file = 1;
+ state.line = 1;
+ state.column = 0;
+ state.isa = 0;
+ state.is_stmt = DWARF2_LINE_DEFAULT_IS_STMT;
+ state.precbc = NULL;
+
+ if (info->asm_source) {
+ dwarf2_line_bc_info bcinfo;
+
+ bcinfo.debug_line = info->debug_line;
+ bcinfo.object = info->object;
+ bcinfo.linemap = info->linemap;
+ bcinfo.dbgfmt_dwarf2 = dbgfmt_dwarf2;
+ bcinfo.state = &state;
+ bcinfo.lastfile = 0;
+ bcinfo.loc.isa_change = 0;
+ bcinfo.loc.column = 0;
+ bcinfo.loc.discriminator = 0;
+ bcinfo.loc.is_stmt = IS_STMT_NOCHANGE;
+ bcinfo.loc.basic_block = 0;
+ bcinfo.loc.prologue_end = 0;
+ bcinfo.loc.epilogue_begin = 0;
+ bcinfo.loc.sym = NULL;
+
+ /* bcs_traverse() skips first "dummy" bytecode, so look at it
+ * separately to determine the initial symrec.
+ */
+ bc = yasm_section_bcs_first(sect);
+ if (bc->symrecs) {
+ size_t i = 0;
+ while (bc->symrecs[i]) {
+ bcinfo.loc.sym = bc->symrecs[i];
+ i++;
+ }
+ }
+
+ yasm_section_bcs_traverse(sect, info->errwarns, &bcinfo,
+ dwarf2_generate_line_bc);
+ } else {
+ /*@null@*/ dwarf2_loc *loc;
+
+ dwarf2_dbgfmt_finalize_locs(sect, dsd);
+
+ STAILQ_FOREACH(loc, &dsd->locs, link) {
+ if (dwarf2_dbgfmt_gen_line_op(info->debug_line, &state, loc,
+ STAILQ_NEXT(loc, link)))
+ return 1;
+ }
+ }
+
+ /* End sequence: bring address to end of section, then output end
+ * sequence opcode. Don't use a special opcode to do this as we don't
+ * want an extra entry in the line matrix.
+ */
+ if (!state.precbc)
+ state.precbc = yasm_section_bcs_first(sect);
+ bc = yasm_section_bcs_last(sect);
+ addr_delta = yasm_bc_next_offset(bc) - state.precbc->offset;
+ if (addr_delta == DWARF2_MAX_SPECIAL_ADDR_DELTA)
+ dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_const_add_pc,
+ NULL);
+ else if (addr_delta > 0)
+ dwarf2_dbgfmt_append_line_op(info->debug_line, DW_LNS_advance_pc,
+ yasm_intnum_create_uint(addr_delta));
+ dwarf2_dbgfmt_append_line_ext_op(info->debug_line, DW_LNE_end_sequence, 0,
+ NULL);
+
+ return 0;
+}
+
+static int
+dwarf2_generate_filename(const char *filename, void *d)
+{
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)d;
+ char *deb_name = yasm_replace_path(
+ dbgfmt_dwarf2->dbgfmt.module->replace_map, dbgfmt_dwarf2->dbgfmt.module->replace_map_size,
+ filename, strlen(filename));
+ dwarf2_dbgfmt_add_file(dbgfmt_dwarf2, 0, deb_name);
+ yasm_xfree(deb_name);
+ return 0;
+}
+
+yasm_section *
+yasm_dwarf2__generate_line(yasm_object *object, yasm_linemap *linemap,
+ yasm_errwarns *errwarns, int asm_source,
+ /*@out@*/ yasm_section **main_code,
+ /*@out@*/ size_t *num_line_sections)
+{
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)object->dbgfmt;
+ dwarf2_line_info info;
+ int new;
+ size_t i;
+ yasm_bytecode *sppbc;
+ dwarf2_spp *spp;
+ dwarf2_head *head;
+
+ if (asm_source) {
+ /* Generate dirs and filenames based on linemap */
+ yasm_linemap_traverse_filenames(linemap, dbgfmt_dwarf2,
+ dwarf2_generate_filename);
+ }
+
+ info.num_sections = 0;
+ info.last_code = NULL;
+ info.asm_source = asm_source;
+ info.object = object;
+ info.linemap = linemap;
+ info.dbgfmt_dwarf2 = dbgfmt_dwarf2;
+ info.debug_line = yasm_object_get_general(object, ".debug_line", 1, 0, 0,
+ &new, 0);
+
+ /* header */
+ head = yasm_dwarf2__add_head(dbgfmt_dwarf2, info.debug_line, NULL, 0, 0);
+
+ /* statement program prologue */
+ spp = yasm_xmalloc(sizeof(dwarf2_spp));
+ sppbc = yasm_bc_create_common(&dwarf2_spp_bc_callback, spp, 0);
+ sppbc->len = dbgfmt_dwarf2->sizeof_offset + 5 +
+ NELEMS(line_opcode_num_operands);
+
+ /* directory list */
+ for (i=0; i<dbgfmt_dwarf2->dirs_size; i++)
+ sppbc->len += (unsigned long)strlen(dbgfmt_dwarf2->dirs[i])+1;
+ sppbc->len++;
+
+ /* filename list */
+ for (i=0; i<dbgfmt_dwarf2->filenames_size; i++) {
+ if (!dbgfmt_dwarf2->filenames[i].filename) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("dwarf2 file number %d unassigned"), i+1);
+ yasm_errwarn_propagate(errwarns, 0);
+ continue;
+ }
+ sppbc->len +=
+ (unsigned long)strlen(dbgfmt_dwarf2->filenames[i].filename) + 1 +
+ yasm_size_uleb128(dbgfmt_dwarf2->filenames[i].dir) + 2;
+ }
+ sppbc->len++;
+ yasm_dwarf2__append_bc(info.debug_line, sppbc);
+
+ /* statement program */
+ yasm_object_sections_traverse(object, (void *)&info,
+ dwarf2_generate_line_section);
+
+ /* mark end of line information */
+ yasm_dwarf2__set_head_end(head, yasm_section_bcs_last(info.debug_line));
+
+ *num_line_sections = info.num_sections;
+ if (info.num_sections == 1)
+ *main_code = info.last_code;
+ else
+ *main_code = NULL;
+ return info.debug_line;
+}
+
+static void
+dwarf2_spp_bc_destroy(void *contents)
+{
+ yasm_xfree(contents);
+}
+
+static void
+dwarf2_spp_bc_print(const void *contents, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+static int
+dwarf2_spp_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ yasm_internal_error(N_("tried to calc_len a dwarf2 spp bytecode"));
+ /*@notreached@*/
+ return 0;
+}
+
+static int
+dwarf2_spp_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ yasm_object *object = yasm_section_get_object(bc->section);
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)object->dbgfmt;
+ unsigned char *buf = *bufp;
+ yasm_intnum *cval;
+ size_t i, len;
+
+ /* Prologue length (following this field) */
+ cval = yasm_intnum_create_uint(bc->len - (unsigned long)(buf-*bufp) -
+ dbgfmt_dwarf2->sizeof_offset);
+ yasm_arch_intnum_tobytes(object->arch, cval, buf,
+ dbgfmt_dwarf2->sizeof_offset,
+ dbgfmt_dwarf2->sizeof_offset*8, 0, bc, 0);
+ buf += dbgfmt_dwarf2->sizeof_offset;
+
+ YASM_WRITE_8(buf, dbgfmt_dwarf2->min_insn_len); /* minimum_instr_len */
+ YASM_WRITE_8(buf, DWARF2_LINE_DEFAULT_IS_STMT); /* default_is_stmt */
+ YASM_WRITE_8(buf, DWARF2_LINE_BASE); /* line_base */
+ YASM_WRITE_8(buf, DWARF2_LINE_RANGE); /* line_range */
+ YASM_WRITE_8(buf, DWARF2_LINE_OPCODE_BASE); /* opcode_base */
+
+ /* Standard opcode # operands array */
+ for (i=0; i<NELEMS(line_opcode_num_operands); i++)
+ YASM_WRITE_8(buf, line_opcode_num_operands[i]);
+
+ /* directory list */
+ for (i=0; i<dbgfmt_dwarf2->dirs_size; i++) {
+ len = strlen(dbgfmt_dwarf2->dirs[i])+1;
+ memcpy(buf, dbgfmt_dwarf2->dirs[i], len);
+ buf += len;
+ }
+ /* finish with single 0 byte */
+ YASM_WRITE_8(buf, 0);
+
+ /* filename list */
+ for (i=0; i<dbgfmt_dwarf2->filenames_size; i++) {
+ len = strlen(dbgfmt_dwarf2->filenames[i].filename)+1;
+ memcpy(buf, dbgfmt_dwarf2->filenames[i].filename, len);
+ buf += len;
+
+ /* dir */
+ buf += yasm_get_uleb128(dbgfmt_dwarf2->filenames[i].dir, buf);
+ YASM_WRITE_8(buf, 0); /* time */
+ YASM_WRITE_8(buf, 0); /* length */
+ }
+ /* finish with single 0 byte */
+ YASM_WRITE_8(buf, 0);
+
+ *bufp = buf;
+
+ yasm_intnum_destroy(cval);
+ return 0;
+}
+
+static void
+dwarf2_line_op_bc_destroy(void *contents)
+{
+ dwarf2_line_op *line_op = (dwarf2_line_op *)contents;
+ if (line_op->operand)
+ yasm_intnum_destroy(line_op->operand);
+ if (line_op->ext_operand_int)
+ yasm_intnum_destroy(line_op->ext_operand_int);
+ yasm_xfree(contents);
+}
+
+static void
+dwarf2_line_op_bc_print(const void *contents, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+static int
+dwarf2_line_op_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ yasm_internal_error(N_("tried to calc_len a dwarf2 line_op bytecode"));
+ /*@notreached@*/
+ return 0;
+}
+
+static int
+dwarf2_line_op_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ dwarf2_line_op *line_op = (dwarf2_line_op *)bc->contents;
+ unsigned char *buf = *bufp;
+
+ YASM_WRITE_8(buf, line_op->opcode);
+ if (line_op->operand)
+ buf += yasm_intnum_get_leb128(line_op->operand, buf,
+ line_op->opcode == DW_LNS_advance_line);
+ if (line_op->ext_opcode > 0) {
+ YASM_WRITE_8(buf, line_op->ext_opcode);
+ if (line_op->ext_operand) {
+ yasm_value value;
+ yasm_value_init_sym(&value, line_op->ext_operand,
+ line_op->ext_operandsize*8);
+ output_value(&value, buf, line_op->ext_operandsize,
+ (unsigned long)(buf-bufstart), bc, 0, d);
+ buf += line_op->ext_operandsize;
+ }
+ if (line_op->ext_operand_int) {
+ buf += yasm_intnum_get_leb128(line_op->ext_operand_int, buf, 0);
+ }
+ }
+
+ *bufp = buf;
+ return 0;
+}
+
+void
+yasm_dwarf2__dir_loc(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp;
+ int in_is_stmt = 0, in_isa = 0, in_discriminator = 0;
+
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *intn;
+ dwarf2_section_data *dsd;
+ dwarf2_loc *loc = yasm_xmalloc(sizeof(dwarf2_loc));
+
+ /* File number (required) */
+ if (!valparams || !(vp = yasm_vps_first(valparams)) ||
+ vp->val || vp->type != YASM_PARAM_EXPR) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("file number required"));
+ yasm_xfree(loc);
+ return;
+ }
+ intn = yasm_expr_get_intnum(&vp->param.e, 0);
+ if (!intn) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("file number is not a constant"));
+ yasm_xfree(loc);
+ return;
+ }
+ if (yasm_intnum_sign(intn) != 1) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("file number less than one"));
+ yasm_xfree(loc);
+ return;
+ }
+ loc->file = yasm_intnum_get_uint(intn);
+
+ /* Line number (required) */
+ vp = yasm_vps_next(vp);
+ if (!vp || vp->val || vp->type != YASM_PARAM_EXPR) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("line number required"));
+ yasm_xfree(loc);
+ return;
+ }
+ intn = yasm_expr_get_intnum(&vp->param.e, 0);
+ if (!intn) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("line number is not a constant"));
+ yasm_xfree(loc);
+ return;
+ }
+ loc->line = yasm_intnum_get_uint(intn);
+
+ /* Generate new section data if it doesn't already exist */
+ if (!object->cur_section) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("[%s] can only be used inside of a section"), "loc");
+ yasm_xfree(loc);
+ return;
+ }
+ dsd = yasm_section_get_data(object->cur_section,
+ &yasm_dwarf2__section_data_cb);
+ if (!dsd) {
+ dsd = yasm_xmalloc(sizeof(dwarf2_section_data));
+ STAILQ_INIT(&dsd->locs);
+ yasm_section_add_data(object->cur_section,
+ &yasm_dwarf2__section_data_cb, dsd);
+ }
+
+ /* Defaults for optional settings */
+ loc->column = 0;
+ loc->discriminator = 0;
+ loc->isa_change = 0;
+ loc->isa = 0;
+ loc->is_stmt = IS_STMT_NOCHANGE;
+ loc->basic_block = 0;
+ loc->prologue_end = 0;
+ loc->epilogue_begin = 0;
+
+ /* Optional column number */
+ vp = yasm_vps_next(vp);
+ if (vp && !vp->val && vp->type == YASM_PARAM_EXPR) {
+ intn = yasm_expr_get_intnum(&vp->param.e, 0);
+ if (!intn) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("column number is not a constant"));
+ yasm_xfree(loc);
+ return;
+ }
+ loc->column = yasm_intnum_get_uint(intn);
+ vp = yasm_vps_next(vp);
+ }
+
+ /* Other options; note for GAS compatibility we need to support both:
+ * is_stmt=1 (NASM) and
+ * is_stmt 1 (GAS)
+ */
+ while (vp) {
+ /*@null@*/ /*@dependent@*/ const char *s;
+ /*@null@*/ /*@only@*/ yasm_expr *e;
+
+restart:
+ if (in_is_stmt) {
+ in_is_stmt = 0;
+ if (!(e = yasm_vp_expr(vp, object->symtab, line)) ||
+ !(intn = yasm_expr_get_intnum(&e, 0))) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("is_stmt value is not a constant"));
+ yasm_xfree(loc);
+ if (e)
+ yasm_expr_destroy(e);
+ return;
+ }
+ if (yasm_intnum_is_zero(intn))
+ loc->is_stmt = IS_STMT_SET;
+ else if (yasm_intnum_is_pos1(intn))
+ loc->is_stmt = IS_STMT_CLEAR;
+ else {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("is_stmt value not 0 or 1"));
+ yasm_xfree(loc);
+ yasm_expr_destroy(e);
+ return;
+ }
+ yasm_expr_destroy(e);
+ } else if (in_isa) {
+ in_isa = 0;
+ if (!(e = yasm_vp_expr(vp, object->symtab, line)) ||
+ !(intn = yasm_expr_get_intnum(&e, 0))) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("isa value is not a constant"));
+ yasm_xfree(loc);
+ if (e)
+ yasm_expr_destroy(e);
+ return;
+ }
+ if (yasm_intnum_sign(intn) < 0) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("isa value less than zero"));
+ yasm_xfree(loc);
+ yasm_expr_destroy(e);
+ return;
+ }
+ loc->isa_change = 1;
+ loc->isa = yasm_intnum_get_uint(intn);
+ yasm_expr_destroy(e);
+ } else if (in_discriminator) {
+ in_discriminator = 0;
+ if (!(e = yasm_vp_expr(vp, object->symtab, line)) ||
+ !(intn = yasm_expr_get_intnum(&e, 0))) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("discriminator value is not a constant"));
+ yasm_xfree(loc);
+ if (e)
+ yasm_expr_destroy(e);
+ return;
+ }
+ if (yasm_intnum_sign(intn) < 0) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("discriminator value less than zero"));
+ yasm_xfree(loc);
+ yasm_expr_destroy(e);
+ return;
+ }
+ loc->discriminator = yasm_intnum_get_uint(intn);
+ yasm_expr_destroy(e);
+ } else if (!vp->val && (s = yasm_vp_id(vp))) {
+ if (yasm__strcasecmp(s, "is_stmt") == 0)
+ in_is_stmt = 1;
+ else if (yasm__strcasecmp(s, "isa") == 0)
+ in_isa = 1;
+ else if (yasm__strcasecmp(s, "discriminator") == 0)
+ in_discriminator = 1;
+ else if (yasm__strcasecmp(s, "basic_block") == 0)
+ loc->basic_block = 1;
+ else if (yasm__strcasecmp(s, "prologue_end") == 0)
+ loc->prologue_end = 1;
+ else if (yasm__strcasecmp(s, "epilogue_begin") == 0)
+ loc->epilogue_begin = 1;
+ else
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("unrecognized loc option `%s'"), s);
+ } else if (!vp->val) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("unrecognized numeric qualifier"));
+ } else if (yasm__strcasecmp(vp->val, "is_stmt") == 0) {
+ in_is_stmt = 1;
+ goto restart; /* don't go to the next valparam */
+ } else if (yasm__strcasecmp(vp->val, "isa") == 0) {
+ in_isa = 1;
+ goto restart; /* don't go to the next valparam */
+ } else if (yasm__strcasecmp(vp->val, "discriminator") == 0) {
+ in_discriminator = 1;
+ goto restart; /* don't go to the next valparam */
+ } else
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("unrecognized loc option `%s'"), vp->val);
+ vp = yasm_vps_next(vp);
+ }
+
+ if (in_is_stmt || in_isa || in_discriminator) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("%s requires value"),
+ in_is_stmt ? "is_stmt" :
+ (in_isa ? "isa" : "discriminator"));
+ yasm_xfree(loc);
+ return;
+ }
+
+ /* Append new location */
+ loc->vline = line;
+ loc->bc = NULL;
+ loc->sym = NULL;
+ STAILQ_INSERT_TAIL(&dsd->locs, loc, link);
+}
+
+void
+yasm_dwarf2__dir_file(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_dbgfmt_dwarf2 *dbgfmt_dwarf2 = (yasm_dbgfmt_dwarf2 *)object->dbgfmt;
+ yasm_valparam *vp;
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *file_intn;
+ unsigned long filenum;
+
+ if (!valparams) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires an argument"),
+ "FILE");
+ return;
+ }
+
+ vp = yasm_vps_first(valparams);
+ if (yasm_vp_string(vp)) {
+ /* Just a bare filename */
+ yasm_object_set_source_fn(object, yasm_vp_string(vp));
+ object->deb_filename = yasm_replace_path(
+ dbgfmt_dwarf2->dbgfmt.module->replace_map, dbgfmt_dwarf2->dbgfmt.module->replace_map_size,
+ yasm_vp_string(vp), strlen(yasm_vp_string(vp)));
+ return;
+ }
+
+ /* Otherwise.. first vp is the file number */
+ if (vp->type != YASM_PARAM_EXPR ||
+ !(file_intn = yasm_expr_get_intnum(&vp->param.e, 0))) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("file number is not a constant"));
+ return;
+ }
+ filenum = yasm_intnum_get_uint(file_intn);
+
+ vp = yasm_vps_next(vp);
+ if (!yasm_vp_string(vp)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("file number given but no filename"));
+ return;
+ }
+
+ dwarf2_dbgfmt_add_file(dbgfmt_dwarf2, filenum, yasm_vp_string(vp));
+}
diff --git a/contrib/tools/yasm/modules/dbgfmts/null/null-dbgfmt.c b/contrib/tools/yasm/modules/dbgfmts/null/null-dbgfmt.c
new file mode 100644
index 0000000000..d2d1bed58e
--- /dev/null
+++ b/contrib/tools/yasm/modules/dbgfmts/null/null-dbgfmt.c
@@ -0,0 +1,64 @@
+/*
+ * Null debugging format (creates NO debugging information)
+ *
+ * Copyright (C) 2002-2007 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 <util.h>
+
+#include <libyasm.h>
+
+
+yasm_dbgfmt_module yasm_null_LTX_dbgfmt;
+
+
+static /*@null@*/ /*@only@*/ yasm_dbgfmt *
+null_dbgfmt_create(yasm_object *object)
+{
+ yasm_dbgfmt_base *dbgfmt = yasm_xmalloc(sizeof(yasm_dbgfmt_base));
+ dbgfmt->module = &yasm_null_LTX_dbgfmt;
+ return (yasm_dbgfmt *)dbgfmt;
+}
+
+static void
+null_dbgfmt_destroy(/*@only@*/ yasm_dbgfmt *dbgfmt)
+{
+ yasm_xfree(dbgfmt);
+}
+
+static void
+null_dbgfmt_generate(yasm_object *object, yasm_linemap *linemap,
+ yasm_errwarns *errwarns)
+{
+}
+
+
+/* Define dbgfmt structure -- see dbgfmt.h for details */
+yasm_dbgfmt_module yasm_null_LTX_dbgfmt = {
+ "No debugging info",
+ "null",
+ NULL, /* no directives */
+ null_dbgfmt_create,
+ null_dbgfmt_destroy,
+ null_dbgfmt_generate
+};
diff --git a/contrib/tools/yasm/modules/dbgfmts/stabs/stabs-dbgfmt.c b/contrib/tools/yasm/modules/dbgfmts/stabs/stabs-dbgfmt.c
new file mode 100644
index 0000000000..5c0cba6aeb
--- /dev/null
+++ b/contrib/tools/yasm/modules/dbgfmts/stabs/stabs-dbgfmt.c
@@ -0,0 +1,511 @@
+/*
+ * Stabs debugging format
+ *
+ * Copyright (C) 2003-2007 Michael Urman
+ *
+ * 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 <util.h>
+
+#include <libyasm.h>
+
+typedef enum {
+ N_UNDF = 0x00, /* Undefined */
+ N_GSYM = 0x20, /* Global symbol */
+ N_FNAME = 0x22, /* Function name (BSD Fortran) */
+ N_FUN = 0x24, /* Function name or Text segment variable */
+ N_STSYM = 0x26, /* Data segment file-scope variable */
+ N_LCSYM = 0x28, /* BSS segment file-scope variable */
+ N_MAIN = 0x2a, /* Name of main routine */
+ N_ROSYM = 0x2c, /* Variable in .rodata section */
+ N_PC = 0x30, /* Global symbol (Pascal) */
+ N_SYMS = 0x32, /* Number of symbols (Ultrix V4.0) */
+ N_NOMAP = 0x34, /* No DST map */
+ N_OBJ = 0x38, /* Object file (Solaris2) */
+ N_OPT = 0x3c, /* Debugger options (Solaris2) */
+ N_RSYM = 0x40, /* Register variable */
+ N_M2C = 0x42, /* Modula-2 compilation unit */
+ N_SLINE = 0x44, /* Line numbers in .text segment */
+ N_DSLINE = 0x46, /* Line numbers in .data segment */
+ N_BSLINE = 0x48, /* Line numbers in .bss segment */
+ N_BROWS = 0x48, /* Source code .cb file's path */
+ N_DEFD = 0x4a, /* GNU Modula-2 definition module dependency */
+ N_FLINE = 0x4c, /* Function start/body/end line numbers (Solaris2) */
+ N_EHDECL = 0x50, /* GNU C++ exception variable */
+ N_MOD2 = 0x50, /* Modula2 info for imc (Ultrix V4.0) */
+ N_CATCH = 0x54, /* GNU C++ catch clause */
+ N_SSYM = 0x60, /* Structure or union element */
+ N_ENDM = 0x62, /* Last stab for module (Solaris2) */
+ N_SO = 0x64, /* Path and name of source files */
+ N_LSYM = 0x80, /* Stack variable */
+ N_BINCL = 0x84, /* Beginning of include file */
+ N_SOL = 0x84, /* Name of include file */
+ N_PSYM = 0xa0, /* Parameter variable */
+ N_EINCL = 0xa2, /* End of include file */
+ N_ENTRY = 0xa4, /* Alternate entry point */
+ N_LBRAC = 0xc0, /* Beginning of lexical block */
+ N_EXCL = 0xc2, /* Placeholder for a deleted include file */
+ N_SCOPE = 0xc4, /* Modula 2 scope info (Sun) */
+ N_RBRAC = 0xe0, /* End of lexical block */
+ N_BCOMM = 0xe2, /* Begin named common block */
+ N_ECOMM = 0xe4, /* End named common block */
+ N_ECOML = 0xe8, /* Member of common block */
+ N_WITH = 0xea, /* Pascal with statement: type,,0,0,offset (Solaris2) */
+ N_NBTEXT = 0xf0, /* Gould non-base registers */
+ N_NBDATA = 0xf2, /* Gould non-base registers */
+ N_NBBSS = 0xf4, /* Gould non-base registers */
+ N_NBSTS = 0xf6, /* Gould non-base registers */
+ N_NBLCS = 0xf8 /* Gould non-base registers */
+} stabs_stab_type;
+
+typedef struct yasm_dbgfmt_stabs {
+ yasm_dbgfmt_base dbgfmt; /* base structure */
+} yasm_dbgfmt_stabs;
+
+typedef struct {
+ unsigned long lastline; /* track line and file of bytecodes */
+ unsigned long curline;
+ const char *lastfile;
+ const char *curfile;
+
+ unsigned int stablen; /* size of a stab for current machine */
+ unsigned long stabcount; /* count stored stabs; doesn't include first */
+
+ yasm_section *stab; /* sections to which stabs, stabstrs appended */
+ yasm_section *stabstr;
+
+ yasm_bytecode *basebc; /* base bytecode from which to track SLINEs */
+
+ yasm_object *object;
+ yasm_linemap *linemap;
+ yasm_errwarns *errwarns;
+} stabs_info;
+
+typedef struct {
+ /*@null@*/ yasm_bytecode *bcstr; /* bytecode in stabstr for string */
+ stabs_stab_type type; /* stab type: N_* */
+ unsigned char other; /* unused, but stored here anyway */
+ unsigned short desc; /* description element of a stab */
+ /*@null@*/ yasm_symrec *symvalue; /* value element needing relocation */
+ /*@null@*/yasm_bytecode *bcvalue; /* relocated stab's bytecode */
+ unsigned long value; /* fallthrough value if above NULL */
+} stabs_stab;
+
+/* Bytecode callback function prototypes */
+
+static void stabs_bc_str_destroy(void *contents);
+static void stabs_bc_str_print(const void *contents, FILE *f, int
+ indent_level);
+static int stabs_bc_str_calc_len
+ (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
+static int stabs_bc_str_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static void stabs_bc_stab_destroy(void *contents);
+static void stabs_bc_stab_print(const void *contents, FILE *f, int
+ indent_level);
+static int stabs_bc_stab_calc_len
+ (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
+static int stabs_bc_stab_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+/* Bytecode callback structures */
+
+static const yasm_bytecode_callback stabs_bc_str_callback = {
+ stabs_bc_str_destroy,
+ stabs_bc_str_print,
+ yasm_bc_finalize_common,
+ NULL,
+ stabs_bc_str_calc_len,
+ yasm_bc_expand_common,
+ stabs_bc_str_tobytes,
+ 0
+};
+
+static const yasm_bytecode_callback stabs_bc_stab_callback = {
+ stabs_bc_stab_destroy,
+ stabs_bc_stab_print,
+ yasm_bc_finalize_common,
+ NULL,
+ stabs_bc_stab_calc_len,
+ yasm_bc_expand_common,
+ stabs_bc_stab_tobytes,
+ 0
+};
+
+yasm_dbgfmt_module yasm_stabs_LTX_dbgfmt;
+
+
+static /*@null@*/ /*@only@*/ yasm_dbgfmt *
+stabs_dbgfmt_create(yasm_object *object)
+{
+ yasm_dbgfmt_stabs *dbgfmt_stabs = yasm_xmalloc(sizeof(yasm_dbgfmt_stabs));
+ dbgfmt_stabs->dbgfmt.module = &yasm_stabs_LTX_dbgfmt;
+ return (yasm_dbgfmt *)dbgfmt_stabs;
+}
+
+static void
+stabs_dbgfmt_destroy(/*@only@*/ yasm_dbgfmt *dbgfmt)
+{
+ yasm_xfree(dbgfmt);
+}
+
+/* Create and add a new strtab-style string bytecode to a section, updating
+ * offset on insertion; no optimization necessary */
+/* Copies the string, so you must still free yours as normal */
+static yasm_bytecode *
+stabs_dbgfmt_append_bcstr(yasm_section *sect, const char *str)
+{
+ yasm_bytecode *bc;
+
+ bc = yasm_bc_create_common(&stabs_bc_str_callback, yasm__xstrdup(str), 0);
+ bc->len = (unsigned long)(strlen(str)+1);
+ bc->offset = yasm_bc_next_offset(yasm_section_bcs_last(sect));
+
+ yasm_section_bcs_append(sect, bc);
+
+ return bc;
+}
+
+/* Create and add a new stab bytecode to a section, updating offset on
+ * insertion; no optimization necessary. */
+/* Requires a string bytecode, or NULL, for its string entry */
+static stabs_stab *
+stabs_dbgfmt_append_stab(stabs_info *info, yasm_section *sect,
+ /*@null@*/ yasm_bytecode *bcstr, stabs_stab_type type,
+ unsigned long desc, /*@null@*/ yasm_symrec *symvalue,
+ /*@null@*/ yasm_bytecode *bcvalue, unsigned long value)
+{
+ yasm_bytecode *bc;
+ stabs_stab *stab = yasm_xmalloc(sizeof(stabs_stab));
+
+ stab->other = 0;
+ stab->bcstr = bcstr;
+ stab->type = type;
+ stab->desc = (unsigned short)desc;
+ stab->symvalue = symvalue;
+ stab->bcvalue = bcvalue;
+ stab->value = value;
+
+ bc = yasm_bc_create_common(&stabs_bc_stab_callback, stab,
+ bcvalue ? bcvalue->line : 0);
+ bc->len = info->stablen;
+ bc->offset = yasm_bc_next_offset(yasm_section_bcs_last(sect));
+
+ yasm_section_bcs_append(sect, bc);
+
+ info->stabcount++;
+ return stab;
+}
+
+static void
+stabs_dbgfmt_generate_n_fun(stabs_info *info, yasm_bytecode *bc)
+{
+ /* check all syms at this bc for potential function syms */
+ int bcsym;
+ for (bcsym=0; bc->symrecs && bc->symrecs[bcsym]; bcsym++)
+ {
+ char *str;
+ yasm_symrec *sym = bc->symrecs[bcsym];
+ const char *name = yasm_symrec_get_name(sym);
+
+ /* best guess algorithm - ignore labels containing a . or $ */
+ if (strchr(name, '.') || strchr(name, '$'))
+ continue;
+
+ /* if a function, update basebc, and output a funcname:F1 stab */
+ info->basebc = bc;
+
+ str = yasm_xmalloc(strlen(name)+4);
+ strcpy(str, name);
+ strcat(str, ":F1");
+ stabs_dbgfmt_append_stab(info, info->stab,
+ stabs_dbgfmt_append_bcstr(info->stabstr, str),
+ N_FUN, 0, sym, info->basebc, 0);
+ yasm_xfree(str);
+ break;
+ }
+}
+
+static int
+stabs_dbgfmt_generate_bcs(yasm_bytecode *bc, void *d)
+{
+ stabs_info *info = (stabs_info *)d;
+ yasm_linemap_lookup(info->linemap, bc->line, &info->curfile,
+ &info->curline);
+
+ /* check for new function */
+ stabs_dbgfmt_generate_n_fun(info, bc);
+
+ if (info->lastfile != info->curfile) {
+ info->lastline = 0; /* new file, so line changes */
+ /*stabs_dbgfmt_append_stab(info, info->stab,
+ stabs_dbgfmt_append_bcstr(info->stabstr, info->curfile),
+ N_SOL, 0, NULL, bc, 0);*/
+ }
+
+ /* output new line stabs if there's a basebc (known function) */
+ if (info->basebc != NULL && info->curline != info->lastline) {
+ info->lastline = bc->line;
+ stabs_dbgfmt_append_stab(info, info->stab, NULL, N_SLINE,
+ info->curline, NULL, NULL,
+ bc->offset - info->basebc->offset);
+ }
+
+ info->lastline = info->curline;
+ info->lastfile = info->curfile;
+
+ return 0;
+}
+
+static int
+stabs_dbgfmt_generate_sections(yasm_section *sect, /*@null@*/ void *d)
+{
+ stabs_info *info = (stabs_info *)d;
+ const char *sectname=yasm_section_get_name(sect);
+
+ /* each section has a different base symbol */
+ info->basebc = NULL;
+
+ /* handle first (pseudo) bc separately */
+ stabs_dbgfmt_generate_n_fun(d, yasm_section_bcs_first(sect));
+
+ yasm_section_bcs_traverse(sect, info->errwarns, d,
+ stabs_dbgfmt_generate_bcs);
+
+ if (yasm__strcasecmp(sectname, ".text")==0) {
+ /* Close out last function by appending a null SO stab after last bc */
+ yasm_bytecode *bc = yasm_section_bcs_last(sect);
+ yasm_symrec *sym =
+ yasm_symtab_define_label(info->object->symtab, ".n_so", bc, 1,
+ bc->line);
+ stabs_dbgfmt_append_stab(info, info->stab, 0, N_SO, 0, sym, bc, 0);
+ }
+
+ return 1;
+}
+
+static void
+stabs_dbgfmt_generate(yasm_object *object, yasm_linemap *linemap,
+ yasm_errwarns *errwarns)
+{
+ stabs_info info;
+ int new;
+ yasm_bytecode *dbgbc;
+ stabs_stab *stab;
+ yasm_bytecode *filebc, *laststr, *firstbc;
+ yasm_symrec *firstsym;
+ yasm_section *stext;
+
+ /* Stablen is determined by arch/machine */
+ if (yasm__strcasecmp(yasm_arch_keyword(object->arch), "x86") == 0) {
+ info.stablen = 12;
+ }
+ else /* unknown machine; generate nothing */
+ return;
+
+ info.object = object;
+ info.linemap = linemap;
+ info.errwarns = errwarns;
+ info.lastline = 0;
+ info.stabcount = 0;
+ info.stab = yasm_object_get_general(object, ".stab", 4, 0, 0, &new, 0);
+ if (!new) {
+ yasm_bytecode *last = yasm_section_bcs_last(info.stab);
+ if (last == NULL) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("stabs debugging conflicts with user-defined section .stab"));
+ yasm_errwarn_propagate(errwarns,
+ yasm_section_bcs_first(info.stab)->line);
+ } else {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("stabs debugging overrides empty section .stab"));
+ yasm_errwarn_propagate(errwarns, 0);
+ }
+ }
+
+ info.stabstr =
+ yasm_object_get_general(object, ".stabstr", 1, 0, 0, &new, 0);
+ if (!new) {
+ yasm_bytecode *last = yasm_section_bcs_last(info.stabstr);
+ if (last == NULL) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("stabs debugging conflicts with user-defined section .stabstr"));
+ yasm_errwarn_propagate(errwarns,
+ yasm_section_bcs_first(info.stab)->line);
+ } else {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("stabs debugging overrides empty section .stabstr"));
+ yasm_errwarn_propagate(errwarns, 0);
+ }
+ }
+
+ /* initial pseudo-stab */
+ stab = yasm_xmalloc(sizeof(stabs_stab));
+ dbgbc = yasm_bc_create_common(&stabs_bc_stab_callback, stab, 0);
+ dbgbc->len = info.stablen;
+ dbgbc->offset = 0;
+ yasm_section_bcs_append(info.stab, dbgbc);
+
+ /* initial strtab bytecodes */
+ stabs_dbgfmt_append_bcstr(info.stabstr, "");
+ filebc = stabs_dbgfmt_append_bcstr(info.stabstr, object->src_filename);
+
+ stext = yasm_object_find_general(object, ".text");
+ firstsym = yasm_symtab_use(object->symtab, ".text", 0);
+ firstbc = yasm_section_bcs_first(stext);
+ /* N_SO file stab */
+ stabs_dbgfmt_append_stab(&info, info.stab, filebc, N_SO, 0,
+ firstsym, firstbc, 0);
+
+ yasm_object_sections_traverse(object, (void *)&info,
+ stabs_dbgfmt_generate_sections);
+
+ /* fill initial pseudo-stab's fields */
+ laststr = yasm_section_bcs_last(info.stabstr);
+ if (laststr == NULL)
+ yasm_internal_error(".stabstr has no entries");
+
+ stab->bcvalue = NULL;
+ stab->symvalue = NULL;
+ stab->value = yasm_bc_next_offset(laststr);
+ stab->bcstr = filebc;
+ stab->type = N_UNDF;
+ stab->other = 0;
+ if (info.stabcount > 0xffff) {
+ yasm_warn_set(YASM_WARN_GENERAL, N_("over 65535 stabs"));
+ yasm_errwarn_propagate(errwarns, 0);
+ stab->desc = 0xffff;
+ } else
+ stab->desc = (unsigned short)info.stabcount;
+}
+
+static int
+stabs_bc_stab_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ /* This entire function, essentially the core of rendering stabs to a file,
+ * needs to become endian aware. Size appears not to be an issue, as known
+ * 64-bit systems use truncated values in 32-bit fields. */
+
+ const stabs_stab *stab = (const stabs_stab *)bc->contents;
+ unsigned char *buf = *bufp;
+
+ YASM_WRITE_32_L(buf, stab->bcstr ? stab->bcstr->offset : 0);
+ YASM_WRITE_8(buf, stab->type);
+ YASM_WRITE_8(buf, stab->other);
+ YASM_WRITE_16_L(buf, stab->desc);
+
+ if (stab->symvalue != NULL) {
+ bc->offset += 8;
+ output_reloc(stab->symvalue, bc, buf, 4, 32, 0, d);
+ bc->offset -= 8;
+ buf += 4;
+ }
+ else if (stab->bcvalue != NULL) {
+ YASM_WRITE_32_L(buf, stab->bcvalue->offset);
+ }
+ else {
+ YASM_WRITE_32_L(buf, stab->value);
+ }
+
+ *bufp = buf;
+ return 0;
+}
+
+static int
+stabs_bc_str_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ const char *str = (const char *)bc->contents;
+ unsigned char *buf = *bufp;
+
+ strcpy((char *)buf, str);
+ buf += strlen(str)+1;
+
+ *bufp = buf;
+ return 0;
+}
+
+static void
+stabs_bc_stab_destroy(void *contents)
+{
+ yasm_xfree(contents);
+}
+
+static void
+stabs_bc_str_destroy(void *contents)
+{
+ yasm_xfree(contents);
+}
+
+static void
+stabs_bc_stab_print(const void *contents, FILE *f, int indent_level)
+{
+ const stabs_stab *stab = (const stabs_stab *)contents;
+ const char *str = "";
+ fprintf(f, "%*s.stabs \"%s\", 0x%x, 0x%x, 0x%x, 0x%lx\n",
+ indent_level, "", str, stab->type, stab->other, stab->desc,
+ stab->bcvalue ? stab->bcvalue->offset : stab->value);
+}
+
+static void
+stabs_bc_str_print(const void *contents, FILE *f, int indent_level)
+{
+ fprintf(f, "%*s\"%s\"\n", indent_level, "", (const char *)contents);
+}
+
+static int
+stabs_bc_stab_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ yasm_internal_error(N_("tried to resolve a stabs stab bytecode"));
+ /*@notreached@*/
+ return 0;
+}
+
+static int
+stabs_bc_str_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ yasm_internal_error(N_("tried to resolve a stabs str bytecode"));
+ /*@notreached@*/
+ return 0;
+}
+
+/* Define dbgfmt structure -- see dbgfmt.h for details */
+yasm_dbgfmt_module yasm_stabs_LTX_dbgfmt = {
+ "Stabs debugging format",
+ "stabs",
+ NULL, /* no directives */
+ stabs_dbgfmt_create,
+ stabs_dbgfmt_destroy,
+ stabs_dbgfmt_generate
+};
diff --git a/contrib/tools/yasm/modules/gas-token.c b/contrib/tools/yasm/modules/gas-token.c
new file mode 100644
index 0000000000..454287b6d8
--- /dev/null
+++ b/contrib/tools/yasm/modules/gas-token.c
@@ -0,0 +1,1407 @@
+/* Generated by re2c
+ */
+/*
+ * GAS-compatible re2c lexer
+ *
+ * Copyright (C) 2005-2007 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.
+ * 3. Neither the name of the author nor the names of other contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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 <util.h>
+
+#include <libyasm.h>
+
+#include "modules/parsers/gas/gas-parser.h"
+
+
+#define BSIZE 8192
+
+#define YYCURSOR cursor
+#define YYLIMIT (s->lim)
+#define YYMARKER (s->ptr)
+#define YYFILL(n) {cursor = fill(parser_gas, cursor);}
+
+#define RETURN(i) do {s->cur = cursor; parser_gas->tokch = s->tok[0]; \
+ return i;} while (0)
+
+#define SCANINIT() {s->tok = cursor;}
+
+#define TOK ((char *)s->tok)
+#define TOKLEN (size_t)(cursor-s->tok)
+
+/* Bridge function to convert byte-oriented parser with line-oriented
+ * preprocessor.
+ */
+static size_t
+preproc_input(yasm_parser_gas *parser_gas, /*@out@*/ YYCTYPE *buf,
+ size_t max_size)
+{
+ size_t tot=0;
+ while (max_size > 0) {
+ size_t n;
+
+ if (!parser_gas->line) {
+ parser_gas->line = yasm_preproc_get_line(parser_gas->preproc);
+ if (!parser_gas->line)
+ return tot; /* EOF */
+ parser_gas->linepos = parser_gas->line;
+ parser_gas->lineleft = strlen(parser_gas->line) + 1;
+ parser_gas->line[parser_gas->lineleft-1] = '\n';
+ }
+
+ n = parser_gas->lineleft<max_size ? parser_gas->lineleft : max_size;
+ strncpy((char *)buf+tot, parser_gas->linepos, n);
+
+ if (n == parser_gas->lineleft) {
+ yasm_xfree(parser_gas->line);
+ parser_gas->line = NULL;
+ } else {
+ parser_gas->lineleft -= n;
+ parser_gas->linepos += n;
+ }
+
+ tot += n;
+ max_size -= n;
+ }
+ return tot;
+}
+#if 0
+static size_t
+fill_input(void *d, unsigned char *buf, size_t max)
+{
+ return yasm_preproc_input((yasm_preproc *)d, (char *)buf, max);
+}
+#endif
+static YYCTYPE *
+fill(yasm_parser_gas *parser_gas, YYCTYPE *cursor)
+{
+ yasm_scanner *s = &parser_gas->s;
+ int first = 0;
+ if(!s->eof){
+ size_t cnt = s->tok - s->bot;
+ if(cnt){
+ memmove(s->bot, s->tok, (size_t)(s->lim - s->tok));
+ s->tok = s->bot;
+ s->ptr -= cnt;
+ cursor -= cnt;
+ s->lim -= cnt;
+ }
+ if (!s->bot)
+ first = 1;
+ if((s->top - s->lim) < BSIZE){
+ YYCTYPE *buf = yasm_xmalloc((size_t)(s->lim - s->bot) + BSIZE);
+ memcpy(buf, s->tok, (size_t)(s->lim - s->tok));
+ s->tok = buf;
+ s->ptr = &buf[s->ptr - s->bot];
+ cursor = &buf[cursor - s->bot];
+ s->lim = &buf[s->lim - s->bot];
+ s->top = &s->lim[BSIZE];
+ if (s->bot)
+ yasm_xfree(s->bot);
+ s->bot = buf;
+ }
+ if((cnt = preproc_input(parser_gas, s->lim, BSIZE)) == 0) {
+ s->eof = &s->lim[cnt]; *s->eof++ = '\n';
+ }
+ s->lim += cnt;
+ if (first && parser_gas->save_input) {
+ int i;
+ YYCTYPE *saveline;
+ parser_gas->save_last ^= 1;
+ saveline = parser_gas->save_line[parser_gas->save_last];
+ /* save next line into cur_line */
+ for (i=0; i<79 && &s->tok[i] < s->lim && s->tok[i] != '\n'; i++)
+ saveline[i] = s->tok[i];
+ saveline[i] = '\0';
+ }
+ }
+ return cursor;
+}
+
+static YYCTYPE *
+save_line(yasm_parser_gas *parser_gas, YYCTYPE *cursor)
+{
+ yasm_scanner *s = &parser_gas->s;
+ int i = 0;
+ YYCTYPE *saveline;
+
+ parser_gas->save_last ^= 1;
+ saveline = parser_gas->save_line[parser_gas->save_last];
+
+ /* save next line into cur_line */
+ if ((YYLIMIT - YYCURSOR) < 80)
+ YYFILL(80);
+ for (i=0; i<79 && &cursor[i] < s->lim && cursor[i] != '\n'; i++)
+ saveline[i] = cursor[i];
+ saveline[i] = '\0';
+ return cursor;
+}
+
+/* starting size of string buffer */
+#define STRBUF_ALLOC_SIZE 128
+
+/* string buffer used when parsing strings/character constants */
+static YYCTYPE *strbuf = NULL;
+
+/* length of strbuf (including terminating NULL character) */
+static size_t strbuf_size = 0;
+
+static void
+strbuf_append(size_t count, YYCTYPE *cursor, yasm_scanner *s, int ch)
+{
+ if (count >= strbuf_size) {
+ strbuf = yasm_xrealloc(strbuf, strbuf_size + STRBUF_ALLOC_SIZE);
+ strbuf_size += STRBUF_ALLOC_SIZE;
+ }
+ strbuf[count] = ch;
+}
+
+
+
+
+int
+gas_parser_lex(YYSTYPE *lvalp, yasm_parser_gas *parser_gas)
+{
+ yasm_scanner *s = &parser_gas->s;
+ YYCTYPE *cursor = s->cur;
+ size_t count;
+ YYCTYPE savech;
+
+ /* Handle one token of lookahead */
+ if (parser_gas->peek_token != NONE) {
+ int tok = parser_gas->peek_token;
+ *lvalp = parser_gas->peek_tokval; /* structure copy */
+ parser_gas->tokch = parser_gas->peek_tokch;
+ parser_gas->peek_token = NONE;
+ return tok;
+ }
+
+ /* Catch EOF */
+ if (s->eof && cursor == s->eof)
+ return 0;
+
+ /* Jump to proper "exclusive" states */
+ switch (parser_gas->state) {
+ case COMMENT:
+ goto comment;
+ case SECTION_DIRECTIVE:
+ goto section_directive;
+ case NASM_FILENAME:
+ goto nasm_filename;
+ default:
+ break;
+ }
+
+scan:
+ SCANINIT();
+
+ {
+ static unsigned char yybm[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 12, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 12, 0,
+ 254, 254, 126, 126, 126, 126, 126, 126,
+ 94, 94, 0, 0, 0, 0, 0, 0,
+ 8, 78, 78, 78, 78, 78, 78, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 0, 0, 0, 0, 12,
+ 0, 78, 78, 78, 78, 78, 78, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+
+{
+ YYCTYPE yych;
+ unsigned int yyaccept;
+ goto yy0;
+ ++YYCURSOR;
+yy0:
+ if((YYLIMIT - YYCURSOR) < 5) YYFILL(5);
+ yych = *YYCURSOR;
+ if(yych <= '/'){
+ if(yych <= '#'){
+ if(yych <= '\r'){
+ if(yych <= '\t'){
+ if(yych <= '\b') goto yy30;
+ goto yy26;
+ } else {
+ if(yych <= '\n') goto yy28;
+ if(yych <= '\f') goto yy30;
+ goto yy26;
+ }
+ } else {
+ if(yych <= ' '){
+ if(yych <= '\037') goto yy30;
+ goto yy26;
+ } else {
+ if(yych <= '!') goto yy17;
+ if(yych <= '"') goto yy11;
+ goto yy24;
+ }
+ }
+ } else {
+ if(yych <= '*'){
+ if(yych <= '%'){
+ if(yych <= '$') goto yy17;
+ goto yy22;
+ } else {
+ if(yych == '\'') goto yy9;
+ goto yy17;
+ }
+ } else {
+ if(yych <= ','){
+ if(yych <= '+') goto yy5;
+ goto yy17;
+ } else {
+ if(yych <= '-') goto yy5;
+ if(yych <= '.') goto yy7;
+ goto yy18;
+ }
+ }
+ }
+ } else {
+ if(yych <= 'Z'){
+ if(yych <= '<'){
+ if(yych <= '9'){
+ if(yych >= '1') goto yy4;
+ goto yy2;
+ } else {
+ if(yych <= ':') goto yy17;
+ if(yych <= ';') goto yy19;
+ goto yy13;
+ }
+ } else {
+ if(yych <= '>'){
+ if(yych <= '=') goto yy17;
+ goto yy15;
+ } else {
+ if(yych <= '?') goto yy30;
+ if(yych <= '@') goto yy17;
+ goto yy21;
+ }
+ }
+ } else {
+ if(yych <= 'z'){
+ if(yych <= '^'){
+ if(yych <= ']') goto yy30;
+ goto yy17;
+ } else {
+ if(yych == '`') goto yy30;
+ goto yy21;
+ }
+ } else {
+ if(yych <= '|'){
+ if(yych <= '{') goto yy30;
+ goto yy17;
+ } else {
+ if(yych == '~') goto yy17;
+ goto yy30;
+ }
+ }
+ }
+ }
+yy2: yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if(yych <= 'T'){
+ if(yych <= 'A'){
+ if(yych <= '/'){
+ if(yych == '.') goto yy90;
+ goto yy3;
+ } else {
+ if(yych <= '9') goto yy90;
+ if(yych <= ':') goto yy81;
+ goto yy3;
+ }
+ } else {
+ if(yych <= 'E'){
+ if(yych <= 'B') goto yy85;
+ if(yych >= 'D') goto yy88;
+ goto yy3;
+ } else {
+ if(yych <= 'F') goto yy86;
+ if(yych >= 'T') goto yy88;
+ goto yy3;
+ }
+ }
+ } else {
+ if(yych <= 'e'){
+ if(yych <= 'a'){
+ if(yych == 'X') goto yy92;
+ goto yy3;
+ } else {
+ if(yych <= 'b') goto yy85;
+ if(yych >= 'd') goto yy88;
+ goto yy3;
+ }
+ } else {
+ if(yych <= 't'){
+ if(yych <= 'f') goto yy86;
+ if(yych >= 't') goto yy88;
+ goto yy3;
+ } else {
+ if(yych == 'x') goto yy92;
+ goto yy3;
+ }
+ }
+ }
+yy3:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ lvalp->intn = yasm_intnum_create_dec(TOK);
+ s->tok[TOKLEN] = savech;
+ RETURN(INTNUM);
+ }
+yy4: yych = *++YYCURSOR;
+ if(yych <= 'E'){
+ if(yych <= ':'){
+ if(yych <= '9') goto yy84;
+ goto yy81;
+ } else {
+ if(yych == 'B') goto yy77;
+ goto yy84;
+ }
+ } else {
+ if(yych <= 'b'){
+ if(yych <= 'F') goto yy79;
+ if(yych <= 'a') goto yy84;
+ goto yy77;
+ } else {
+ if(yych == 'f') goto yy79;
+ goto yy84;
+ }
+ }
+yy5: yyaccept = 1;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if(yych == '.') goto yy61;
+ if(yych <= '/') goto yy6;
+ if(yych <= '9') goto yy59;
+ goto yy6;
+yy6:
+{ RETURN(s->tok[0]); }
+yy7: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 16) {
+ goto yy49;
+ }
+ goto yy37;
+yy8:
+{
+ lvalp->str.contents = yasm__xstrndup(TOK, TOKLEN);
+ lvalp->str.len = TOKLEN;
+ RETURN(ID);
+ }
+yy9: yych = *++YYCURSOR;
+ goto yy10;
+yy10:
+{
+ goto charconst;
+ }
+yy11: yych = *++YYCURSOR;
+ goto yy12;
+yy12:
+{
+ goto stringconst;
+ }
+yy13: yych = *++YYCURSOR;
+ if(yych == '<') goto yy47;
+ goto yy14;
+yy14:
+{ RETURN(LEFT_OP); }
+yy15: yych = *++YYCURSOR;
+ if(yych == '>') goto yy45;
+ goto yy16;
+yy16:
+{ RETURN(RIGHT_OP); }
+yy17: yych = *++YYCURSOR;
+ goto yy6;
+yy18: yych = *++YYCURSOR;
+ if(yych == '*') goto yy43;
+ if(yych == '/') goto yy41;
+ goto yy6;
+yy19: yych = *++YYCURSOR;
+ goto yy20;
+yy20:
+{
+ parser_gas->state = INITIAL;
+ RETURN(s->tok[0]);
+ }
+yy21: yych = *++YYCURSOR;
+ goto yy37;
+yy22: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy33;
+ }
+ goto yy23;
+yy23:
+{
+ yasm_warn_set(YASM_WARN_UNREC_CHAR,
+ N_("ignoring unrecognized character `%s'"),
+ yasm__conv_unprint(s->tok[0]));
+ goto scan;
+ }
+yy24: yych = *++YYCURSOR;
+ goto yy25;
+yy25:
+{
+ if (parser_gas->is_cpp_preproc)
+ {
+ RETURN(CPP_LINE_MARKER);
+ } else
+ goto line_comment;
+ }
+yy26: yych = *++YYCURSOR;
+ goto yy32;
+yy27:
+{ goto scan; }
+yy28: yych = *++YYCURSOR;
+ goto yy29;
+yy29:
+{
+ if (parser_gas->save_input)
+ cursor = save_line(parser_gas, cursor);
+ parser_gas->state = INITIAL;
+ RETURN(s->tok[0]);
+ }
+yy30: yych = *++YYCURSOR;
+ goto yy23;
+yy31: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy32;
+yy32: if(yybm[0+yych] & 1) {
+ goto yy31;
+ }
+ goto yy27;
+yy33: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy34;
+yy34: if(yybm[0+yych] & 2) {
+ goto yy33;
+ }
+ goto yy35;
+yy35:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ if (parser_gas->is_nasm_preproc && strcmp(TOK+1, "line") == 0) {
+ s->tok[TOKLEN] = savech;
+ RETURN(NASM_LINE_MARKER);
+ }
+
+ switch (yasm_arch_parse_check_regtmod
+ (p_object->arch, TOK+1, TOKLEN-1, &lvalp->arch_data)) {
+ 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_set(YASM_ERROR_GENERAL,
+ N_("Unrecognized register name `%s'"), s->tok);
+ s->tok[TOKLEN] = savech;
+ lvalp->arch_data = 0;
+ RETURN(REG);
+ }
+yy36: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy37;
+yy37: if(yybm[0+yych] & 4) {
+ goto yy36;
+ }
+ if(yych != '@') goto yy8;
+ goto yy38;
+yy38: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy39;
+yy39: if(yybm[0+yych] & 8) {
+ goto yy38;
+ }
+ goto yy40;
+yy40:
+{
+ /* if @ not part of ID, move the scanner cursor to the first @ */
+ if (!((yasm_objfmt_base *)p_object->objfmt)->module->id_at_ok)
+ cursor = (unsigned char *)strchr(TOK, '@');
+ lvalp->str.contents = yasm__xstrndup(TOK, TOKLEN);
+ lvalp->str.len = TOKLEN;
+ RETURN(ID);
+ }
+yy41: yych = *++YYCURSOR;
+ goto yy42;
+yy42:
+{ goto line_comment; }
+yy43: yych = *++YYCURSOR;
+ goto yy44;
+yy44:
+{ parser_gas->state = COMMENT; goto comment; }
+yy45: yych = *++YYCURSOR;
+ goto yy46;
+yy46:
+{ RETURN(RIGHT_OP); }
+yy47: yych = *++YYCURSOR;
+ goto yy48;
+yy48:
+{ RETURN(LEFT_OP); }
+yy49: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+ yych = *YYCURSOR;
+ goto yy50;
+yy50: if(yybm[0+yych] & 16) {
+ goto yy49;
+ }
+ if(yych <= 'E'){
+ if(yych <= '.'){
+ if(yych == '$') goto yy36;
+ if(yych >= '.') goto yy36;
+ goto yy51;
+ } else {
+ if(yych <= '?') goto yy51;
+ if(yych <= '@') goto yy38;
+ if(yych <= 'D') goto yy36;
+ goto yy52;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych <= 'Z') goto yy36;
+ if(yych == '_') goto yy36;
+ goto yy51;
+ } else {
+ if(yych == 'e') goto yy52;
+ if(yych <= 'z') goto yy36;
+ goto yy51;
+ }
+ }
+yy51:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ lvalp->flt = yasm_floatnum_create(TOK);
+ s->tok[TOKLEN] = savech;
+ RETURN(FLTNUM);
+ }
+yy52: yyaccept = 2;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if(yych <= ','){
+ if(yych == '+') goto yy55;
+ goto yy37;
+ } else {
+ if(yych <= '-') goto yy55;
+ if(yych <= '/') goto yy37;
+ if(yych >= ':') goto yy37;
+ goto yy53;
+ }
+yy53: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy54;
+yy54: if(yych <= '?'){
+ if(yych <= '-'){
+ if(yych == '$') goto yy36;
+ goto yy51;
+ } else {
+ if(yych <= '.') goto yy36;
+ if(yych <= '/') goto yy51;
+ if(yych <= '9') goto yy53;
+ goto yy51;
+ }
+ } else {
+ if(yych <= '^'){
+ if(yych <= '@') goto yy38;
+ if(yych <= 'Z') goto yy36;
+ goto yy51;
+ } else {
+ if(yych == '`') goto yy51;
+ if(yych <= 'z') goto yy36;
+ goto yy51;
+ }
+ }
+yy55: yych = *++YYCURSOR;
+ if(yych <= '/') goto yy56;
+ if(yych <= '9') goto yy57;
+ goto yy56;
+yy56: YYCURSOR = YYMARKER;
+ switch(yyaccept){
+ case 0: goto yy3;
+ case 6: goto yy91;
+ case 3: goto yy51;
+ case 4: goto yy66;
+ case 5: goto yy87;
+ case 1: goto yy6;
+ case 2: goto yy8;
+ }
+yy57: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy58;
+yy58: if(yych <= '/') goto yy51;
+ if(yych <= '9') goto yy57;
+ goto yy51;
+yy59: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+ yych = *YYCURSOR;
+ goto yy60;
+yy60: if(yych == '.') goto yy65;
+ if(yych <= '/') goto yy56;
+ if(yych <= '9') goto yy59;
+ goto yy56;
+yy61: yych = *++YYCURSOR;
+ if(yych <= '/') goto yy56;
+ if(yych >= ':') goto yy56;
+ goto yy62;
+yy62: yyaccept = 3;
+ YYMARKER = ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+ yych = *YYCURSOR;
+ goto yy63;
+yy63: if(yych <= 'D'){
+ if(yych <= '/') goto yy51;
+ if(yych <= '9') goto yy62;
+ goto yy51;
+ } else {
+ if(yych <= 'E') goto yy64;
+ if(yych != 'e') goto yy51;
+ goto yy64;
+ }
+yy64: yych = *++YYCURSOR;
+ if(yych <= ','){
+ if(yych == '+') goto yy55;
+ goto yy56;
+ } else {
+ if(yych <= '-') goto yy55;
+ if(yych <= '/') goto yy56;
+ if(yych <= '9') goto yy57;
+ goto yy56;
+ }
+yy65: yyaccept = 4;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if(yych <= 'D'){
+ if(yych <= '/') goto yy66;
+ if(yych <= '9') goto yy67;
+ goto yy66;
+ } else {
+ if(yych <= 'E') goto yy69;
+ if(yych == 'e') goto yy69;
+ goto yy66;
+ }
+yy66:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ lvalp->flt = yasm_floatnum_create(TOK);
+ s->tok[TOKLEN] = savech;
+ RETURN(FLTNUM);
+ }
+yy67: yyaccept = 3;
+ YYMARKER = ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+ yych = *YYCURSOR;
+ goto yy68;
+yy68: if(yych <= 'D'){
+ if(yych <= '/') goto yy51;
+ if(yych <= '9') goto yy67;
+ goto yy51;
+ } else {
+ if(yych <= 'E') goto yy73;
+ if(yych == 'e') goto yy73;
+ goto yy51;
+ }
+yy69: yych = *++YYCURSOR;
+ if(yych <= ','){
+ if(yych != '+') goto yy56;
+ goto yy70;
+ } else {
+ if(yych <= '-') goto yy70;
+ if(yych <= '/') goto yy56;
+ if(yych <= '9') goto yy71;
+ goto yy56;
+ }
+yy70: yych = *++YYCURSOR;
+ if(yych <= '/') goto yy56;
+ if(yych >= ':') goto yy56;
+ goto yy71;
+yy71: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy72;
+yy72: if(yych <= '/') goto yy66;
+ if(yych <= '9') goto yy71;
+ goto yy66;
+yy73: yych = *++YYCURSOR;
+ if(yych <= ','){
+ if(yych != '+') goto yy56;
+ goto yy74;
+ } else {
+ if(yych <= '-') goto yy74;
+ if(yych <= '/') goto yy56;
+ if(yych <= '9') goto yy75;
+ goto yy56;
+ }
+yy74: yych = *++YYCURSOR;
+ if(yych <= '/') goto yy56;
+ if(yych >= ':') goto yy56;
+ goto yy75;
+yy75: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy76;
+yy76: if(yych <= '/') goto yy51;
+ if(yych <= '9') goto yy75;
+ goto yy51;
+yy77: yych = *++YYCURSOR;
+ goto yy78;
+yy78:
+{
+ /* build local label name */
+ lvalp->str.contents = yasm_xmalloc(30);
+ lvalp->str.len =
+ sprintf(lvalp->str.contents, "L%c\001%lu", s->tok[0],
+ parser_gas->local[s->tok[0]-'0']);
+ RETURN(ID);
+ }
+yy79: yych = *++YYCURSOR;
+ goto yy80;
+yy80:
+{
+ /* build local label name */
+ lvalp->str.contents = yasm_xmalloc(30);
+ lvalp->str.len =
+ sprintf(lvalp->str.contents, "L%c\001%lu", s->tok[0],
+ parser_gas->local[s->tok[0]-'0']+1);
+ RETURN(ID);
+ }
+yy81: yych = *++YYCURSOR;
+ goto yy82;
+yy82:
+{
+ /* increment label index */
+ parser_gas->local[s->tok[0]-'0']++;
+ /* build local label name */
+ lvalp->str.contents = yasm_xmalloc(30);
+ lvalp->str.len =
+ sprintf(lvalp->str.contents, "L%c\001%lu", s->tok[0],
+ parser_gas->local[s->tok[0]-'0']);
+ RETURN(LABEL);
+ }
+yy83: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+ yych = *YYCURSOR;
+ goto yy84;
+yy84: if(yych == '.') goto yy65;
+ if(yych <= '/') goto yy3;
+ if(yych <= '9') goto yy83;
+ goto yy3;
+yy85: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 128) {
+ goto yy104;
+ }
+ goto yy78;
+yy86: yyaccept = 5;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if(yych == '+') goto yy96;
+ if(yych == '-') goto yy96;
+ goto yy97;
+yy87:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ lvalp->flt = yasm_floatnum_create(TOK+2);
+ s->tok[TOKLEN] = savech;
+ RETURN(FLTNUM);
+ }
+yy88: yyaccept = 5;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if(yych == '+') goto yy96;
+ if(yych == '-') goto yy96;
+ goto yy97;
+yy89: yyaccept = 6;
+ YYMARKER = ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
+ yych = *YYCURSOR;
+ goto yy90;
+yy90: if(yybm[0+yych] & 32) {
+ goto yy89;
+ }
+ if(yych == '.') goto yy65;
+ if(yych <= '/') goto yy91;
+ if(yych <= '9') goto yy59;
+ goto yy91;
+yy91:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ lvalp->intn = yasm_intnum_create_oct(TOK);
+ s->tok[TOKLEN] = savech;
+ RETURN(INTNUM);
+ }
+yy92: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 64) {
+ goto yy93;
+ }
+ goto yy56;
+yy93: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy94;
+yy94: if(yybm[0+yych] & 64) {
+ goto yy93;
+ }
+ goto yy95;
+yy95:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ /* skip 0 and x */
+ lvalp->intn = yasm_intnum_create_hex(TOK+2);
+ s->tok[TOKLEN] = savech;
+ RETURN(INTNUM);
+ }
+yy96: yyaccept = 5;
+ YYMARKER = ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+ yych = *YYCURSOR;
+ goto yy97;
+yy97: if(yych <= '9'){
+ if(yych == '.') goto yy98;
+ if(yych <= '/') goto yy87;
+ goto yy96;
+ } else {
+ if(yych <= 'E'){
+ if(yych <= 'D') goto yy87;
+ goto yy100;
+ } else {
+ if(yych == 'e') goto yy100;
+ goto yy87;
+ }
+ }
+yy98: yyaccept = 5;
+ YYMARKER = ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+ yych = *YYCURSOR;
+ goto yy99;
+yy99: if(yych <= 'D'){
+ if(yych <= '/') goto yy87;
+ if(yych <= '9') goto yy98;
+ goto yy87;
+ } else {
+ if(yych <= 'E') goto yy100;
+ if(yych != 'e') goto yy87;
+ goto yy100;
+ }
+yy100: yych = *++YYCURSOR;
+ if(yych <= ','){
+ if(yych != '+') goto yy56;
+ goto yy101;
+ } else {
+ if(yych <= '-') goto yy101;
+ if(yych <= '/') goto yy56;
+ if(yych <= '9') goto yy102;
+ goto yy56;
+ }
+yy101: yych = *++YYCURSOR;
+ if(yych <= '/') goto yy56;
+ if(yych >= ':') goto yy56;
+ goto yy102;
+yy102: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy103;
+yy103: if(yych <= '/') goto yy87;
+ if(yych <= '9') goto yy102;
+ goto yy87;
+yy104: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy105;
+yy105: if(yybm[0+yych] & 128) {
+ goto yy104;
+ }
+ goto yy106;
+yy106:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ lvalp->intn = yasm_intnum_create_bin(TOK+2);
+ s->tok[TOKLEN] = savech;
+ RETURN(INTNUM);
+ }
+}
+}
+
+
+ /* C-style comment; nesting not supported */
+comment:
+ SCANINIT();
+
+ {
+
+{
+ YYCTYPE yych;
+ goto yy107;
+ ++YYCURSOR;
+yy107:
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if(yych == '\n') goto yy111;
+ if(yych != '*') goto yy113;
+ goto yy109;
+yy109: yych = *++YYCURSOR;
+ if(yych == '/') goto yy114;
+ goto yy110;
+yy110:
+{
+ if (cursor == s->eof)
+ return 0;
+ goto comment;
+ }
+yy111: yych = *++YYCURSOR;
+ goto yy112;
+yy112:
+{
+ if (parser_gas->save_input)
+ cursor = save_line(parser_gas, cursor);
+ RETURN(s->tok[0]);
+ }
+yy113: yych = *++YYCURSOR;
+ goto yy110;
+yy114: yych = *++YYCURSOR;
+ goto yy115;
+yy115:
+{ parser_gas->state = INITIAL; goto scan; }
+}
+}
+
+
+ /* Single line comment. */
+line_comment:
+ {
+ static unsigned char yybm[] = {
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 0, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ };
+
+{
+ YYCTYPE yych;
+ goto yy116;
+yy117: ++YYCURSOR;
+yy116:
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy118;
+yy118: if(yybm[0+yych] & 128) {
+ goto yy117;
+ }
+ goto yy119;
+yy119:
+{ goto scan; }
+}
+}
+
+
+ /* .section directive (the section name portion thereof) */
+section_directive:
+ SCANINIT();
+
+ {
+ static unsigned char yybm[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 64, 0, 0, 0, 64, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 64, 0, 0, 0, 128, 0, 0, 0,
+ 0, 0, 0, 0, 0, 128, 128, 0,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 0, 0, 0, 0, 0, 0,
+ 0, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 0, 0, 0, 0, 128,
+ 0, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+
+{
+ YYCTYPE yych;
+ goto yy120;
+ ++YYCURSOR;
+yy120:
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if(yych <= '$'){
+ if(yych <= '\r'){
+ if(yych <= '\t'){
+ if(yych <= '\b') goto yy132;
+ goto yy126;
+ } else {
+ if(yych <= '\n') goto yy130;
+ if(yych <= '\f') goto yy132;
+ goto yy126;
+ }
+ } else {
+ if(yych <= '!'){
+ if(yych == ' ') goto yy126;
+ goto yy132;
+ } else {
+ if(yych <= '"') goto yy124;
+ if(yych <= '#') goto yy132;
+ goto yy122;
+ }
+ }
+ } else {
+ if(yych <= '@'){
+ if(yych <= '.'){
+ if(yych <= '+') goto yy132;
+ if(yych <= ',') goto yy128;
+ goto yy122;
+ } else {
+ if(yych <= '/') goto yy132;
+ if(yych >= ':') goto yy132;
+ goto yy122;
+ }
+ } else {
+ if(yych <= '_'){
+ if(yych <= 'Z') goto yy122;
+ if(yych <= '^') goto yy132;
+ goto yy122;
+ } else {
+ if(yych <= '`') goto yy132;
+ if(yych >= '{') goto yy132;
+ goto yy122;
+ }
+ }
+ }
+yy122: yych = *++YYCURSOR;
+ goto yy137;
+yy123:
+{
+ lvalp->str.contents = yasm__xstrndup(TOK, TOKLEN);
+ lvalp->str.len = TOKLEN;
+ parser_gas->state = INITIAL;
+ RETURN(ID);
+ }
+yy124: yych = *++YYCURSOR;
+ goto yy125;
+yy125:
+{ goto stringconst; }
+yy126: yych = *++YYCURSOR;
+ goto yy135;
+yy127:
+{ goto section_directive; }
+yy128: yych = *++YYCURSOR;
+ goto yy129;
+yy129:
+{
+ parser_gas->state = INITIAL;
+ RETURN(s->tok[0]);
+ }
+yy130: yych = *++YYCURSOR;
+ goto yy131;
+yy131:
+{
+ if (parser_gas->save_input)
+ cursor = save_line(parser_gas, cursor);
+ parser_gas->state = INITIAL;
+ RETURN(s->tok[0]);
+ }
+yy132: yych = *++YYCURSOR;
+ goto yy133;
+yy133:
+{
+ yasm_warn_set(YASM_WARN_UNREC_CHAR,
+ N_("ignoring unrecognized character `%s'"),
+ yasm__conv_unprint(s->tok[0]));
+ goto section_directive;
+ }
+yy134: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy135;
+yy135: if(yybm[0+yych] & 64) {
+ goto yy134;
+ }
+ goto yy127;
+yy136: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy137;
+yy137: if(yybm[0+yych] & 128) {
+ goto yy136;
+ }
+ goto yy123;
+}
+}
+
+
+ /* filename portion of nasm preproc %line */
+nasm_filename:
+ strbuf = yasm_xmalloc(STRBUF_ALLOC_SIZE);
+ strbuf_size = STRBUF_ALLOC_SIZE;
+ count = 0;
+
+nasm_filename_scan:
+ SCANINIT();
+
+ {
+ static unsigned char yybm[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 128, 0, 0, 0, 128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 128, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+
+{
+ YYCTYPE yych;
+ goto yy138;
+ ++YYCURSOR;
+yy138:
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if(yych <= '\f'){
+ if(yych <= '\b') goto yy144;
+ if(yych <= '\t') goto yy142;
+ if(yych >= '\v') goto yy144;
+ goto yy140;
+ } else {
+ if(yych <= '\r') goto yy142;
+ if(yych == ' ') goto yy142;
+ goto yy144;
+ }
+yy140: yych = *++YYCURSOR;
+ goto yy141;
+yy141:
+{
+ strbuf_append(count++, cursor, s, '\0');
+ lvalp->str.contents = (char *)strbuf;
+ lvalp->str.len = count;
+ parser_gas->state = INITIAL;
+ RETURN(STRING);
+ }
+yy142: yych = *++YYCURSOR;
+ goto yy147;
+yy143:
+{ goto nasm_filename_scan; }
+yy144: yych = *++YYCURSOR;
+ goto yy145;
+yy145:
+{
+ if (cursor == s->eof) {
+ strbuf_append(count++, cursor, s, '\0');
+ lvalp->str.contents = (char *)strbuf;
+ lvalp->str.len = count;
+ parser_gas->state = INITIAL;
+ RETURN(STRING);
+ }
+ strbuf_append(count++, cursor, s, s->tok[0]);
+ goto nasm_filename_scan;
+ }
+yy146: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy147;
+yy147: if(yybm[0+yych] & 128) {
+ goto yy146;
+ }
+ goto yy143;
+}
+}
+
+
+ /* character constant values */
+charconst:
+ /*TODO*/
+
+ /* string constant values */
+stringconst:
+ strbuf = yasm_xmalloc(STRBUF_ALLOC_SIZE);
+ strbuf_size = STRBUF_ALLOC_SIZE;
+ count = 0;
+
+stringconst_scan:
+ SCANINIT();
+
+ {
+
+{
+ YYCTYPE yych;
+ goto yy148;
+ ++YYCURSOR;
+yy148:
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if(yych == '"') goto yy152;
+ if(yych != '\\') goto yy154;
+ goto yy150;
+yy150: yych = *++YYCURSOR;
+ if(yych != '\n') goto yy155;
+ goto yy151;
+yy151:
+{
+ if (cursor == s->eof) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("unexpected end of file in string"));
+ lvalp->str.contents = (char *)strbuf;
+ lvalp->str.len = count;
+ RETURN(STRING);
+ }
+ strbuf_append(count++, cursor, s, s->tok[0]);
+ goto stringconst_scan;
+ }
+yy152: yych = *++YYCURSOR;
+ goto yy153;
+yy153:
+{
+ strbuf_append(count, cursor, s, '\0');
+ yasm_unescape_cstring(strbuf, &count);
+ lvalp->str.contents = (char *)strbuf;
+ lvalp->str.len = count;
+ RETURN(STRING);
+ }
+yy154: yych = *++YYCURSOR;
+ goto yy151;
+yy155: yych = *++YYCURSOR;
+ goto yy156;
+yy156:
+{
+ if (cursor == s->eof) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("unexpected end of file in string"));
+ lvalp->str.contents = (char *)strbuf;
+ lvalp->str.len = count;
+ RETURN(STRING);
+ }
+ strbuf_append(count++, cursor, s, '\\');
+ strbuf_append(count++, cursor, s, s->tok[1]);
+ goto stringconst_scan;
+ }
+}
+}
+
+}
+
diff --git a/contrib/tools/yasm/modules/init_plugin.c b/contrib/tools/yasm/modules/init_plugin.c
new file mode 100644
index 0000000000..86ae4c53f9
--- /dev/null
+++ b/contrib/tools/yasm/modules/init_plugin.c
@@ -0,0 +1,86 @@
+/* arch_lc3b arch_x86 listfmt_nasm parser_gas parser_nasm preproc_nasm preproc_raw preproc_cpp preproc_gas dbgfmt_cv8 dbgfmt_dwarf2 dbgfmt_null dbgfmt_stabs objfmt_dbg objfmt_bin objfmt_elf objfmt_elf32 objfmt_elf64 objfmt_elfx32 objfmt_coff objfmt_win32 objfmt_win64 objfmt_macho objfmt_macho32 objfmt_macho64 objfmt_rdf objfmt_xdf
+ rev 1
+ */
+
+#include <libyasm.h>
+#include <libyasm/module.h>
+
+extern yasm_arch_module yasm_lc3b_LTX_arch;
+extern yasm_arch_module yasm_x86_LTX_arch;
+extern yasm_listfmt_module yasm_nasm_LTX_listfmt;
+extern yasm_parser_module yasm_gas_LTX_parser;
+extern yasm_parser_module yasm_nasm_LTX_parser;
+extern yasm_preproc_module yasm_nasm_LTX_preproc;
+extern yasm_preproc_module yasm_raw_LTX_preproc;
+extern yasm_preproc_module yasm_cpp_LTX_preproc;
+extern yasm_preproc_module yasm_gas_LTX_preproc;
+extern yasm_dbgfmt_module yasm_cv8_LTX_dbgfmt;
+extern yasm_dbgfmt_module yasm_dwarf2_LTX_dbgfmt;
+extern yasm_dbgfmt_module yasm_null_LTX_dbgfmt;
+extern yasm_dbgfmt_module yasm_stabs_LTX_dbgfmt;
+extern yasm_objfmt_module yasm_dbg_LTX_objfmt;
+extern yasm_objfmt_module yasm_bin_LTX_objfmt;
+extern yasm_objfmt_module yasm_elf_LTX_objfmt;
+extern yasm_objfmt_module yasm_elf32_LTX_objfmt;
+extern yasm_objfmt_module yasm_elf64_LTX_objfmt;
+extern yasm_objfmt_module yasm_elfx32_LTX_objfmt;
+extern yasm_objfmt_module yasm_coff_LTX_objfmt;
+extern yasm_objfmt_module yasm_win32_LTX_objfmt;
+extern yasm_objfmt_module yasm_win64_LTX_objfmt;
+extern yasm_objfmt_module yasm_macho_LTX_objfmt;
+extern yasm_objfmt_module yasm_macho32_LTX_objfmt;
+extern yasm_objfmt_module yasm_macho64_LTX_objfmt;
+extern yasm_objfmt_module yasm_rdf_LTX_objfmt;
+extern yasm_objfmt_module yasm_xdf_LTX_objfmt;
+void
+yasm_init_plugin(void)
+{
+ yasm_register_module(YASM_MODULE_ARCH, "lc3b", &yasm_lc3b_LTX_arch);
+ yasm_register_module(YASM_MODULE_ARCH, "x86", &yasm_x86_LTX_arch);
+ yasm_register_module(YASM_MODULE_LISTFMT, "nasm", &yasm_nasm_LTX_listfmt);
+ yasm_register_module(YASM_MODULE_PARSER, "gas", &yasm_gas_LTX_parser);
+ yasm_register_module(YASM_MODULE_PARSER, "nasm", &yasm_nasm_LTX_parser);
+ yasm_register_module(YASM_MODULE_PREPROC, "nasm", &yasm_nasm_LTX_preproc);
+ yasm_register_module(YASM_MODULE_PREPROC, "raw", &yasm_raw_LTX_preproc);
+ yasm_register_module(YASM_MODULE_PREPROC, "cpp", &yasm_cpp_LTX_preproc);
+ yasm_register_module(YASM_MODULE_PREPROC, "gas", &yasm_gas_LTX_preproc);
+ yasm_register_module(YASM_MODULE_DBGFMT, "cv8", &yasm_cv8_LTX_dbgfmt);
+ yasm_register_module(YASM_MODULE_DBGFMT, "dwarf2", &yasm_dwarf2_LTX_dbgfmt);
+ yasm_register_module(YASM_MODULE_DBGFMT, "null", &yasm_null_LTX_dbgfmt);
+ yasm_register_module(YASM_MODULE_DBGFMT, "stabs", &yasm_stabs_LTX_dbgfmt);
+ yasm_register_module(YASM_MODULE_OBJFMT, "dbg", &yasm_dbg_LTX_objfmt);
+ yasm_register_module(YASM_MODULE_OBJFMT, "bin", &yasm_bin_LTX_objfmt);
+ yasm_register_module(YASM_MODULE_OBJFMT, "elf", &yasm_elf_LTX_objfmt);
+ yasm_register_module(YASM_MODULE_OBJFMT, "elf32", &yasm_elf32_LTX_objfmt);
+ yasm_register_module(YASM_MODULE_OBJFMT, "elf64", &yasm_elf64_LTX_objfmt);
+ yasm_register_module(YASM_MODULE_OBJFMT, "elfx32", &yasm_elfx32_LTX_objfmt);
+ yasm_register_module(YASM_MODULE_OBJFMT, "coff", &yasm_coff_LTX_objfmt);
+ yasm_register_module(YASM_MODULE_OBJFMT, "win32", &yasm_win32_LTX_objfmt);
+ yasm_register_module(YASM_MODULE_OBJFMT, "win64", &yasm_win64_LTX_objfmt);
+ yasm_register_module(YASM_MODULE_OBJFMT, "macho", &yasm_macho_LTX_objfmt);
+ yasm_register_module(YASM_MODULE_OBJFMT, "macho32", &yasm_macho32_LTX_objfmt);
+ yasm_register_module(YASM_MODULE_OBJFMT, "macho64", &yasm_macho64_LTX_objfmt);
+ yasm_register_module(YASM_MODULE_OBJFMT, "rdf", &yasm_rdf_LTX_objfmt);
+ yasm_register_module(YASM_MODULE_OBJFMT, "xdf", &yasm_xdf_LTX_objfmt);
+}
+
+void
+yasm_plugin_set_replace(const char* replace_params[], int size) {
+ yasm_dwarf2_LTX_dbgfmt.replace_map = replace_params;
+ yasm_dwarf2_LTX_dbgfmt.replace_map_size = size;
+ yasm_elf_LTX_objfmt.replace_map = replace_params;
+ yasm_elf_LTX_objfmt.replace_map_size = size;
+ yasm_elf32_LTX_objfmt.replace_map = replace_params;
+ yasm_elf32_LTX_objfmt.replace_map_size = size;
+ yasm_elf64_LTX_objfmt.replace_map = replace_params;
+ yasm_elf64_LTX_objfmt.replace_map_size = size;
+ yasm_elfx32_LTX_objfmt.replace_map = replace_params;
+ yasm_elfx32_LTX_objfmt.replace_map_size = size;
+
+ yasm_macho_LTX_objfmt.replace_map = replace_params;
+ yasm_macho_LTX_objfmt.replace_map_size = size;
+ yasm_macho32_LTX_objfmt.replace_map = replace_params;
+ yasm_macho32_LTX_objfmt.replace_map_size = size;
+ yasm_macho64_LTX_objfmt.replace_map = replace_params;
+ yasm_macho64_LTX_objfmt.replace_map_size = size;
+}
diff --git a/contrib/tools/yasm/modules/lc3bid.c b/contrib/tools/yasm/modules/lc3bid.c
new file mode 100644
index 0000000000..89903bca51
--- /dev/null
+++ b/contrib/tools/yasm/modules/lc3bid.c
@@ -0,0 +1,915 @@
+/* Generated by re2c
+ */
+/*
+ * LC-3b identifier recognition and instruction handling
+ *
+ * Copyright (C) 2003-2007 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 <util.h>
+
+#include <libyasm.h>
+
+#include "modules/arch/lc3b/lc3barch.h"
+
+
+/* Opcode modifiers. The opcode bytes are in "reverse" order because the
+ * parameters are read from the arch-specific data in LSB->MSB order.
+ * (only for asthetic reasons in the lexer code below, no practical reason).
+ */
+#define MOD_OpHAdd (1UL<<0) /* Parameter adds to upper 8 bits of insn */
+#define MOD_OpLAdd (1UL<<1) /* Parameter adds to lower 8 bits of insn */
+
+/* Operand types. These are more detailed than the "general" types for all
+ * architectures, as they include the size, for instance.
+ * Bit Breakdown (from LSB to MSB):
+ * - 1 bit = general type (must be exact match, except for =3):
+ * 0 = immediate
+ * 1 = register
+ *
+ * MSBs than the above are actions: what to do with the operand if the
+ * instruction matches. Essentially describes what part of the output bytecode
+ * gets the operand. This may require conversion (e.g. a register going into
+ * an ea field). Naturally, only one of each of these may be contained in the
+ * operands of a single insn_info structure.
+ * - 2 bits = action:
+ * 0 = does nothing (operand data is discarded)
+ * 1 = DR field
+ * 2 = SR field
+ * 3 = immediate
+ *
+ * Immediate operands can have different sizes.
+ * - 3 bits = size:
+ * 0 = no immediate
+ * 1 = 4-bit immediate
+ * 2 = 5-bit immediate
+ * 3 = 6-bit index, word (16 bit)-multiple
+ * 4 = 6-bit index, byte-multiple
+ * 5 = 8-bit immediate, word-multiple
+ * 6 = 9-bit signed immediate, word-multiple
+ * 7 = 9-bit signed offset from next PC ($+2), word-multiple
+ */
+#define OPT_Imm 0x0
+#define OPT_Reg 0x1
+#define OPT_MASK 0x1
+
+#define OPA_None (0<<1)
+#define OPA_DR (1<<1)
+#define OPA_SR (2<<1)
+#define OPA_Imm (3<<1)
+#define OPA_MASK (3<<1)
+
+#define OPI_None (LC3B_IMM_NONE<<3)
+#define OPI_4 (LC3B_IMM_4<<3)
+#define OPI_5 (LC3B_IMM_5<<3)
+#define OPI_6W (LC3B_IMM_6_WORD<<3)
+#define OPI_6B (LC3B_IMM_6_BYTE<<3)
+#define OPI_8 (LC3B_IMM_8<<3)
+#define OPI_9 (LC3B_IMM_9<<3)
+#define OPI_9PC (LC3B_IMM_9_PC<<3)
+#define OPI_MASK (7<<3)
+
+typedef struct lc3b_insn_info {
+ /* Opcode modifiers for variations of instruction. As each modifier reads
+ * its parameter in LSB->MSB order from the arch-specific data[1] from the
+ * lexer data, and the LSB of the arch-specific data[1] is reserved for the
+ * count of insn_info structures in the instruction grouping, there can
+ * only be a maximum of 3 modifiers.
+ */
+ unsigned int modifiers;
+
+ /* The basic 2 byte opcode */
+ unsigned int opcode;
+
+ /* The number of operands this form of the instruction takes */
+ unsigned char num_operands;
+
+ /* The types of each operand, see above */
+ unsigned int operands[3];
+} lc3b_insn_info;
+
+typedef struct lc3b_id_insn {
+ yasm_insn insn; /* base structure */
+
+ /* instruction parse group - NULL if empty instruction (just prefixes) */
+ /*@null@*/ const lc3b_insn_info *group;
+
+ /* Modifier data */
+ unsigned long mod_data;
+
+ /* Number of elements in the instruction parse group */
+ unsigned int num_info:8;
+} lc3b_id_insn;
+
+static void lc3b_id_insn_destroy(void *contents);
+static void lc3b_id_insn_print(const void *contents, FILE *f, int indent_level);
+static void lc3b_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
+
+static const yasm_bytecode_callback lc3b_id_insn_callback = {
+ lc3b_id_insn_destroy,
+ lc3b_id_insn_print,
+ lc3b_id_insn_finalize,
+ NULL,
+ yasm_bc_calc_len_common,
+ yasm_bc_expand_common,
+ yasm_bc_tobytes_common,
+ YASM_BC_SPECIAL_INSN
+};
+
+/*
+ * Instruction groupings
+ */
+
+static const lc3b_insn_info empty_insn[] = {
+ { 0, 0, 0, {0, 0, 0} }
+};
+
+static const lc3b_insn_info addand_insn[] = {
+ { MOD_OpHAdd, 0x1000, 3,
+ {OPT_Reg|OPA_DR, OPT_Reg|OPA_SR, OPT_Reg|OPA_Imm|OPI_5} },
+ { MOD_OpHAdd, 0x1020, 3,
+ {OPT_Reg|OPA_DR, OPT_Reg|OPA_SR, OPT_Imm|OPA_Imm|OPI_5} }
+};
+
+static const lc3b_insn_info br_insn[] = {
+ { MOD_OpHAdd, 0x0000, 1, {OPT_Imm|OPA_Imm|OPI_9PC, 0, 0} }
+};
+
+static const lc3b_insn_info jmp_insn[] = {
+ { 0, 0xC000, 2, {OPT_Reg|OPA_DR, OPT_Imm|OPA_Imm|OPI_9, 0} }
+};
+
+static const lc3b_insn_info lea_insn[] = {
+ { 0, 0xE000, 2, {OPT_Reg|OPA_DR, OPT_Imm|OPA_Imm|OPI_9PC, 0} }
+};
+
+static const lc3b_insn_info ldst_insn[] = {
+ { MOD_OpHAdd, 0x0000, 3,
+ {OPT_Reg|OPA_DR, OPT_Reg|OPA_SR, OPT_Imm|OPA_Imm|OPI_6W} }
+};
+
+static const lc3b_insn_info ldstb_insn[] = {
+ { MOD_OpHAdd, 0x0000, 3,
+ {OPT_Reg|OPA_DR, OPT_Reg|OPA_SR, OPT_Imm|OPA_Imm|OPI_6B} }
+};
+
+static const lc3b_insn_info not_insn[] = {
+ { 0, 0x903F, 2, {OPT_Reg|OPA_DR, OPT_Reg|OPA_SR, 0} }
+};
+
+static const lc3b_insn_info nooperand_insn[] = {
+ { MOD_OpHAdd, 0x0000, 0, {0, 0, 0} }
+};
+
+static const lc3b_insn_info shift_insn[] = {
+ { MOD_OpLAdd, 0xD000, 3,
+ {OPT_Reg|OPA_DR, OPT_Reg|OPA_SR, OPT_Imm|OPA_Imm|OPI_4} }
+};
+
+static const lc3b_insn_info trap_insn[] = {
+ { 0, 0xF000, 1, {OPT_Imm|OPA_Imm|OPI_8, 0, 0} }
+};
+
+static void
+lc3b_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ lc3b_id_insn *id_insn = (lc3b_id_insn *)bc->contents;
+ lc3b_insn *insn;
+ int num_info = id_insn->num_info;
+ const lc3b_insn_info *info = id_insn->group;
+ unsigned long mod_data = id_insn->mod_data;
+ int found = 0;
+ yasm_insn_operand *op;
+ int i;
+
+ yasm_insn_finalize(&id_insn->insn);
+
+ /* Just do a simple linear search through the info array for a match.
+ * First match wins.
+ */
+ for (; num_info>0 && !found; num_info--, info++) {
+ int mismatch = 0;
+
+ /* Match # of operands */
+ if (id_insn->insn.num_operands != info->num_operands)
+ continue;
+
+ if (id_insn->insn.num_operands == 0) {
+ found = 1; /* no operands -> must have a match here. */
+ break;
+ }
+
+ /* Match each operand type and size */
+ for(i = 0, op = yasm_insn_ops_first(&id_insn->insn);
+ op && i<info->num_operands && !mismatch;
+ op = yasm_insn_op_next(op), i++) {
+ /* Check operand type */
+ switch ((int)(info->operands[i] & OPT_MASK)) {
+ case OPT_Imm:
+ if (op->type != YASM_INSN__OPERAND_IMM)
+ mismatch = 1;
+ break;
+ case OPT_Reg:
+ if (op->type != YASM_INSN__OPERAND_REG)
+ mismatch = 1;
+ break;
+ default:
+ yasm_internal_error(N_("invalid operand type"));
+ }
+
+ if (mismatch)
+ break;
+ }
+
+ if (!mismatch) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ /* Didn't find a matching one */
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("invalid combination of opcode and operands"));
+ return;
+ }
+
+ /* Copy what we can from info */
+ insn = yasm_xmalloc(sizeof(lc3b_insn));
+ yasm_value_initialize(&insn->imm, NULL, 0);
+ insn->imm_type = LC3B_IMM_NONE;
+ insn->opcode = info->opcode;
+
+ /* Apply modifiers */
+ if (info->modifiers & MOD_OpHAdd) {
+ insn->opcode += ((unsigned int)(mod_data & 0xFF))<<8;
+ mod_data >>= 8;
+ }
+ if (info->modifiers & MOD_OpLAdd) {
+ insn->opcode += (unsigned int)(mod_data & 0xFF);
+ /*mod_data >>= 8;*/
+ }
+
+ /* Go through operands and assign */
+ if (id_insn->insn.num_operands > 0) {
+ for(i = 0, op = yasm_insn_ops_first(&id_insn->insn);
+ op && i<info->num_operands; op = yasm_insn_op_next(op), i++) {
+
+ switch ((int)(info->operands[i] & OPA_MASK)) {
+ case OPA_None:
+ /* Throw away the operand contents */
+ if (op->type == YASM_INSN__OPERAND_IMM)
+ yasm_expr_destroy(op->data.val);
+ break;
+ case OPA_DR:
+ if (op->type != YASM_INSN__OPERAND_REG)
+ yasm_internal_error(N_("invalid operand conversion"));
+ insn->opcode |= ((unsigned int)(op->data.reg & 0x7)) << 9;
+ break;
+ case OPA_SR:
+ if (op->type != YASM_INSN__OPERAND_REG)
+ yasm_internal_error(N_("invalid operand conversion"));
+ insn->opcode |= ((unsigned int)(op->data.reg & 0x7)) << 6;
+ break;
+ case OPA_Imm:
+ insn->imm_type = (info->operands[i] & OPI_MASK)>>3;
+ switch (op->type) {
+ case YASM_INSN__OPERAND_IMM:
+ if (insn->imm_type == LC3B_IMM_6_WORD
+ || insn->imm_type == LC3B_IMM_8
+ || insn->imm_type == LC3B_IMM_9
+ || insn->imm_type == LC3B_IMM_9_PC)
+ op->data.val = yasm_expr_create(YASM_EXPR_SHR,
+ yasm_expr_expr(op->data.val),
+ yasm_expr_int(yasm_intnum_create_uint(1)),
+ op->data.val->line);
+ if (yasm_value_finalize_expr(&insn->imm,
+ op->data.val,
+ prev_bc, 0))
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("immediate expression too complex"));
+ break;
+ case YASM_INSN__OPERAND_REG:
+ if (yasm_value_finalize_expr(&insn->imm,
+ yasm_expr_create_ident(yasm_expr_int(
+ yasm_intnum_create_uint(op->data.reg & 0x7)),
+ bc->line), prev_bc, 0))
+ yasm_internal_error(N_("reg expr too complex?"));
+ break;
+ default:
+ yasm_internal_error(N_("invalid operand conversion"));
+ }
+ break;
+ default:
+ yasm_internal_error(N_("unknown operand action"));
+ }
+
+ /* Clear so it doesn't get destroyed */
+ op->type = YASM_INSN__OPERAND_REG;
+ }
+
+ if (insn->imm_type == LC3B_IMM_9_PC) {
+ if (insn->imm.seg_of || insn->imm.rshift > 1
+ || insn->imm.curpos_rel)
+ yasm_error_set(YASM_ERROR_VALUE, N_("invalid jump target"));
+ insn->imm.curpos_rel = 1;
+ }
+ }
+
+ /* Transform the bytecode */
+ yasm_lc3b__bc_transform_insn(bc, insn);
+}
+
+
+#define YYCTYPE unsigned char
+#define YYCURSOR id
+#define YYLIMIT id
+#define YYMARKER marker
+#define YYFILL(n) (void)(n)
+
+yasm_arch_regtmod
+yasm_lc3b__parse_check_regtmod(yasm_arch *arch, const char *oid, size_t id_len,
+ uintptr_t *data)
+{
+ const YYCTYPE *id = (const YYCTYPE *)oid;
+ /*const char *marker;*/
+
+{
+ YYCTYPE yych;
+ goto yy0;
+ ++YYCURSOR;
+yy0:
+ if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+ yych = *YYCURSOR;
+ if(yych <= 'R'){
+ if(yych <= '\000') goto yy6;
+ if(yych <= 'Q') goto yy4;
+ goto yy2;
+ } else {
+ if(yych != 'r') goto yy4;
+ goto yy2;
+ }
+yy2: yych = *++YYCURSOR;
+ if(yych <= '/') goto yy5;
+ if(yych <= '7') goto yy8;
+ goto yy5;
+yy3:
+{
+ return YASM_ARCH_NOTREGTMOD;
+ }
+yy4: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy5;
+yy5: if(yych <= '\000') goto yy3;
+ goto yy4;
+yy6: yych = *++YYCURSOR;
+ goto yy7;
+yy7:
+{
+ return YASM_ARCH_NOTREGTMOD;
+ }
+yy8: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy4;
+ goto yy9;
+yy9:
+{
+ *data = (oid[1]-'0');
+ return YASM_ARCH_REG;
+ }
+}
+
+}
+
+#define RET_INSN(g, m) \
+ do { \
+ group = g##_insn; \
+ mod = m; \
+ nelems = NELEMS(g##_insn); \
+ goto done; \
+ } while(0)
+
+yasm_arch_insnprefix
+yasm_lc3b__parse_check_insnprefix(yasm_arch *arch, const char *oid,
+ size_t id_len, unsigned long line,
+ yasm_bytecode **bc, uintptr_t *prefix)
+{
+ const YYCTYPE *id = (const YYCTYPE *)oid;
+ const lc3b_insn_info *group = empty_insn;
+ unsigned long mod = 0;
+ unsigned int nelems = NELEMS(empty_insn);
+ lc3b_id_insn *id_insn;
+
+ *bc = (yasm_bytecode *)NULL;
+ *prefix = 0;
+
+ /*const char *marker;*/
+
+{
+ YYCTYPE yych;
+ goto yy10;
+ ++YYCURSOR;
+yy10:
+ if((YYLIMIT - YYCURSOR) < 6) YYFILL(6);
+ yych = *YYCURSOR;
+ if(yych <= 'T'){
+ if(yych <= 'K'){
+ if(yych <= 'A'){
+ if(yych <= '\000') goto yy23;
+ if(yych <= '@') goto yy21;
+ goto yy12;
+ } else {
+ if(yych <= 'B') goto yy14;
+ if(yych == 'J') goto yy15;
+ goto yy21;
+ }
+ } else {
+ if(yych <= 'N'){
+ if(yych <= 'L') goto yy16;
+ if(yych <= 'M') goto yy21;
+ goto yy18;
+ } else {
+ if(yych <= 'Q') goto yy21;
+ if(yych <= 'R') goto yy19;
+ if(yych <= 'S') goto yy17;
+ goto yy20;
+ }
+ }
+ } else {
+ if(yych <= 'l'){
+ if(yych <= 'b'){
+ if(yych <= '`') goto yy21;
+ if(yych >= 'b') goto yy14;
+ goto yy12;
+ } else {
+ if(yych == 'j') goto yy15;
+ if(yych <= 'k') goto yy21;
+ goto yy16;
+ }
+ } else {
+ if(yych <= 'q'){
+ if(yych == 'n') goto yy18;
+ goto yy21;
+ } else {
+ if(yych <= 'r') goto yy19;
+ if(yych <= 's') goto yy17;
+ if(yych <= 't') goto yy20;
+ goto yy21;
+ }
+ }
+ }
+yy12: yych = *++YYCURSOR;
+ if(yych <= 'N'){
+ if(yych == 'D') goto yy88;
+ if(yych <= 'M') goto yy22;
+ goto yy89;
+ } else {
+ if(yych <= 'd'){
+ if(yych <= 'c') goto yy22;
+ goto yy88;
+ } else {
+ if(yych == 'n') goto yy89;
+ goto yy22;
+ }
+ }
+yy13:
+{
+ return YASM_ARCH_NOTINSNPREFIX;
+ }
+yy14: yych = *++YYCURSOR;
+ if(yych == 'R') goto yy72;
+ if(yych == 'r') goto yy72;
+ goto yy22;
+yy15: yych = *++YYCURSOR;
+ if(yych <= 'S'){
+ if(yych == 'M') goto yy66;
+ if(yych <= 'R') goto yy22;
+ goto yy67;
+ } else {
+ if(yych <= 'm'){
+ if(yych <= 'l') goto yy22;
+ goto yy66;
+ } else {
+ if(yych == 's') goto yy67;
+ goto yy22;
+ }
+ }
+yy16: yych = *++YYCURSOR;
+ if(yych <= 'S'){
+ if(yych <= 'D'){
+ if(yych <= 'C') goto yy22;
+ goto yy53;
+ } else {
+ if(yych <= 'E') goto yy55;
+ if(yych <= 'R') goto yy22;
+ goto yy56;
+ }
+ } else {
+ if(yych <= 'e'){
+ if(yych <= 'c') goto yy22;
+ if(yych <= 'd') goto yy53;
+ goto yy55;
+ } else {
+ if(yych == 's') goto yy56;
+ goto yy22;
+ }
+ }
+yy17: yych = *++YYCURSOR;
+ if(yych == 'T') goto yy47;
+ if(yych == 't') goto yy47;
+ goto yy22;
+yy18: yych = *++YYCURSOR;
+ if(yych == 'O') goto yy42;
+ if(yych == 'o') goto yy42;
+ goto yy22;
+yy19: yych = *++YYCURSOR;
+ if(yych <= 'T'){
+ if(yych <= 'E'){
+ if(yych <= 'D') goto yy22;
+ goto yy29;
+ } else {
+ if(yych <= 'R') goto yy22;
+ if(yych <= 'S') goto yy30;
+ goto yy31;
+ }
+ } else {
+ if(yych <= 'r'){
+ if(yych == 'e') goto yy29;
+ goto yy22;
+ } else {
+ if(yych <= 's') goto yy30;
+ if(yych <= 't') goto yy31;
+ goto yy22;
+ }
+ }
+yy20: yych = *++YYCURSOR;
+ if(yych == 'R') goto yy25;
+ if(yych == 'r') goto yy25;
+ goto yy22;
+yy21: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy22;
+yy22: if(yych <= '\000') goto yy13;
+ goto yy21;
+yy23: yych = *++YYCURSOR;
+ goto yy24;
+yy24:
+{
+ return YASM_ARCH_NOTINSNPREFIX;
+ }
+yy25: yych = *++YYCURSOR;
+ if(yych == 'A') goto yy26;
+ if(yych != 'a') goto yy22;
+ goto yy26;
+yy26: yych = *++YYCURSOR;
+ if(yych == 'P') goto yy27;
+ if(yych != 'p') goto yy22;
+ goto yy27;
+yy27: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy28;
+yy28:
+{ RET_INSN(trap, 0); }
+yy29: yych = *++YYCURSOR;
+ if(yych == 'T') goto yy40;
+ if(yych == 't') goto yy40;
+ goto yy22;
+yy30: yych = *++YYCURSOR;
+ if(yych == 'H') goto yy34;
+ if(yych == 'h') goto yy34;
+ goto yy22;
+yy31: yych = *++YYCURSOR;
+ if(yych == 'I') goto yy32;
+ if(yych != 'i') goto yy22;
+ goto yy32;
+yy32: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy33;
+yy33:
+{ RET_INSN(nooperand, 0x80); }
+yy34: yych = *++YYCURSOR;
+ if(yych == 'F') goto yy35;
+ if(yych != 'f') goto yy22;
+ goto yy35;
+yy35: yych = *++YYCURSOR;
+ if(yych <= 'L'){
+ if(yych == 'A') goto yy38;
+ if(yych <= 'K') goto yy22;
+ goto yy36;
+ } else {
+ if(yych <= 'a'){
+ if(yych <= '`') goto yy22;
+ goto yy38;
+ } else {
+ if(yych != 'l') goto yy22;
+ goto yy36;
+ }
+ }
+yy36: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy37;
+yy37:
+{ RET_INSN(shift, 0x10); }
+yy38: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy39;
+yy39:
+{ RET_INSN(shift, 0x30); }
+yy40: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy41;
+yy41:
+{ RET_INSN(nooperand, 0xCE); }
+yy42: yych = *++YYCURSOR;
+ if(yych <= 'T'){
+ if(yych == 'P') goto yy45;
+ if(yych <= 'S') goto yy22;
+ goto yy43;
+ } else {
+ if(yych <= 'p'){
+ if(yych <= 'o') goto yy22;
+ goto yy45;
+ } else {
+ if(yych != 't') goto yy22;
+ goto yy43;
+ }
+ }
+yy43: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy44;
+yy44:
+{ RET_INSN(not, 0); }
+yy45: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy46;
+yy46:
+{ RET_INSN(nooperand, 0); }
+yy47: yych = *++YYCURSOR;
+ if(yych <= 'I'){
+ if(yych <= 'A'){
+ if(yych >= '\001') goto yy21;
+ goto yy48;
+ } else {
+ if(yych <= 'B') goto yy51;
+ if(yych <= 'H') goto yy21;
+ goto yy49;
+ }
+ } else {
+ if(yych <= 'b'){
+ if(yych <= 'a') goto yy21;
+ goto yy51;
+ } else {
+ if(yych == 'i') goto yy49;
+ goto yy21;
+ }
+ }
+yy48:
+{ RET_INSN(ldst, 0x30); }
+yy49: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy50;
+yy50:
+{ RET_INSN(ldst, 0xB0); }
+yy51: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy52;
+yy52:
+{ RET_INSN(ldstb, 0x70); }
+yy53: yych = *++YYCURSOR;
+ if(yych <= 'I'){
+ if(yych <= 'A'){
+ if(yych >= '\001') goto yy21;
+ goto yy54;
+ } else {
+ if(yych <= 'B') goto yy64;
+ if(yych <= 'H') goto yy21;
+ goto yy62;
+ }
+ } else {
+ if(yych <= 'b'){
+ if(yych <= 'a') goto yy21;
+ goto yy64;
+ } else {
+ if(yych == 'i') goto yy62;
+ goto yy21;
+ }
+ }
+yy54:
+{ RET_INSN(ldst, 0x20); }
+yy55: yych = *++YYCURSOR;
+ if(yych == 'A') goto yy60;
+ if(yych == 'a') goto yy60;
+ goto yy22;
+yy56: yych = *++YYCURSOR;
+ if(yych == 'H') goto yy57;
+ if(yych != 'h') goto yy22;
+ goto yy57;
+yy57: yych = *++YYCURSOR;
+ if(yych == 'F') goto yy58;
+ if(yych != 'f') goto yy22;
+ goto yy58;
+yy58: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy59;
+yy59:
+{ RET_INSN(shift, 0x00); }
+yy60: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy61;
+yy61:
+{ RET_INSN(lea, 0); }
+yy62: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy63;
+yy63:
+{ RET_INSN(ldst, 0xA0); }
+yy64: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy65;
+yy65:
+{ RET_INSN(ldstb, 0x60); }
+yy66: yych = *++YYCURSOR;
+ if(yych == 'P') goto yy70;
+ if(yych == 'p') goto yy70;
+ goto yy22;
+yy67: yych = *++YYCURSOR;
+ if(yych == 'R') goto yy68;
+ if(yych != 'r') goto yy22;
+ goto yy68;
+yy68: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy69;
+yy69:
+{ RET_INSN(br, 0x40); }
+yy70: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy71;
+yy71:
+{ RET_INSN(jmp, 0); }
+yy72: yych = *++YYCURSOR;
+ if(yych <= 'Z'){
+ if(yych <= 'N'){
+ if(yych <= '\000') goto yy73;
+ if(yych <= 'M') goto yy21;
+ goto yy74;
+ } else {
+ if(yych == 'P') goto yy78;
+ if(yych <= 'Y') goto yy21;
+ goto yy76;
+ }
+ } else {
+ if(yych <= 'o'){
+ if(yych == 'n') goto yy74;
+ goto yy21;
+ } else {
+ if(yych <= 'p') goto yy78;
+ if(yych == 'z') goto yy76;
+ goto yy21;
+ }
+ }
+yy73:
+{ RET_INSN(br, 0x00); }
+yy74: yych = *++YYCURSOR;
+ if(yych <= 'Z'){
+ if(yych <= 'O'){
+ if(yych >= '\001') goto yy21;
+ goto yy75;
+ } else {
+ if(yych <= 'P') goto yy82;
+ if(yych <= 'Y') goto yy21;
+ goto yy84;
+ }
+ } else {
+ if(yych <= 'p'){
+ if(yych <= 'o') goto yy21;
+ goto yy82;
+ } else {
+ if(yych == 'z') goto yy84;
+ goto yy21;
+ }
+ }
+yy75:
+{ RET_INSN(br, 0x08); }
+yy76: yych = *++YYCURSOR;
+ if(yych <= 'P'){
+ if(yych <= '\000') goto yy77;
+ if(yych <= 'O') goto yy21;
+ goto yy80;
+ } else {
+ if(yych == 'p') goto yy80;
+ goto yy21;
+ }
+yy77:
+{ RET_INSN(br, 0x04); }
+yy78: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy79;
+yy79:
+{ RET_INSN(br, 0x02); }
+yy80: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy81;
+yy81:
+{ RET_INSN(br, 0x06); }
+yy82: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy83;
+yy83:
+{ RET_INSN(br, 0x0A); }
+yy84: yych = *++YYCURSOR;
+ if(yych <= 'P'){
+ if(yych <= '\000') goto yy85;
+ if(yych <= 'O') goto yy21;
+ goto yy86;
+ } else {
+ if(yych == 'p') goto yy86;
+ goto yy21;
+ }
+yy85:
+{ RET_INSN(br, 0x0C); }
+yy86: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy87;
+yy87:
+{ RET_INSN(br, 0x0E); }
+yy88: yych = *++YYCURSOR;
+ if(yych == 'D') goto yy92;
+ if(yych == 'd') goto yy92;
+ goto yy22;
+yy89: yych = *++YYCURSOR;
+ if(yych == 'D') goto yy90;
+ if(yych != 'd') goto yy22;
+ goto yy90;
+yy90: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy91;
+yy91:
+{ RET_INSN(addand, 0x40); }
+yy92: yych = *++YYCURSOR;
+ if(yych >= '\001') goto yy21;
+ goto yy93;
+yy93:
+{ RET_INSN(addand, 0x00); }
+}
+
+
+done:
+ id_insn = yasm_xmalloc(sizeof(lc3b_id_insn));
+ yasm_insn_initialize(&id_insn->insn);
+ id_insn->group = group;
+ id_insn->mod_data = mod;
+ id_insn->num_info = nelems;
+ *bc = yasm_bc_create_common(&lc3b_id_insn_callback, id_insn, line);
+ return YASM_ARCH_INSN;
+}
+
+static void
+lc3b_id_insn_destroy(void *contents)
+{
+ lc3b_id_insn *id_insn = (lc3b_id_insn *)contents;
+ yasm_insn_delete(&id_insn->insn, yasm_lc3b__ea_destroy);
+ yasm_xfree(contents);
+}
+
+static void
+lc3b_id_insn_print(const void *contents, FILE *f, int indent_level)
+{
+ const lc3b_id_insn *id_insn = (const lc3b_id_insn *)contents;
+ yasm_insn_print(&id_insn->insn, f, indent_level);
+ /*TODO*/
+}
+
+/*@only@*/ yasm_bytecode *
+yasm_lc3b__create_empty_insn(yasm_arch *arch, unsigned long line)
+{
+ lc3b_id_insn *id_insn = yasm_xmalloc(sizeof(lc3b_id_insn));
+
+ yasm_insn_initialize(&id_insn->insn);
+ id_insn->group = empty_insn;
+ id_insn->mod_data = 0;
+ id_insn->num_info = NELEMS(empty_insn);
+
+ return yasm_bc_create_common(&lc3b_id_insn_callback, id_insn, line);
+}
+
diff --git a/contrib/tools/yasm/modules/listfmts/nasm/nasm-listfmt.c b/contrib/tools/yasm/modules/listfmts/nasm/nasm-listfmt.c
new file mode 100644
index 0000000000..1dfc5b621c
--- /dev/null
+++ b/contrib/tools/yasm/modules/listfmts/nasm/nasm-listfmt.c
@@ -0,0 +1,301 @@
+/*
+ * NASM-style list format
+ *
+ * Copyright (C) 2004-2007 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 <util.h>
+
+#include <libyasm.h>
+
+/* NOTE: For this code to generate relocation information, the relocations
+ * have to be added by the object format to each section in program source
+ * order.
+ *
+ * This should not be an issue, as program source order == section bytecode
+ * order, so unless the object formats are very obtuse with their bytecode
+ * iteration, this should just happen.
+ */
+
+#define REGULAR_BUF_SIZE 1024
+
+yasm_listfmt_module yasm_nasm_LTX_listfmt;
+
+typedef struct sectreloc {
+ /*@reldef@*/ SLIST_ENTRY(sectreloc) link;
+ yasm_section *sect;
+ /*@null@*/ yasm_reloc *next_reloc; /* next relocation in section */
+ unsigned long next_reloc_addr;
+} sectreloc;
+
+typedef struct bcreloc {
+ /*@reldef@*/ STAILQ_ENTRY(bcreloc) link;
+ unsigned long offset; /* start of reloc from start of bytecode */
+ size_t size; /* size of reloc in bytes */
+ int rel; /* PC/IP-relative or "absolute" */
+} bcreloc;
+
+typedef struct nasm_listfmt_output_info {
+ yasm_arch *arch;
+ /*@reldef@*/ STAILQ_HEAD(bcrelochead, bcreloc) bcrelocs;
+ /*@null@*/ yasm_reloc *next_reloc; /* next relocation in section */
+ unsigned long next_reloc_addr;
+} nasm_listfmt_output_info;
+
+
+static /*@null@*/ /*@only@*/ yasm_listfmt *
+nasm_listfmt_create(const char *in_filename, const char *obj_filename)
+{
+ yasm_listfmt_base *listfmt = yasm_xmalloc(sizeof(yasm_listfmt_base));
+ listfmt->module = &yasm_nasm_LTX_listfmt;
+ return (yasm_listfmt *)listfmt;
+}
+
+static void
+nasm_listfmt_destroy(/*@only@*/ yasm_listfmt *listfmt)
+{
+ yasm_xfree(listfmt);
+}
+
+static int
+nasm_listfmt_output_value(yasm_value *value, unsigned char *buf,
+ unsigned int destsize, unsigned long offset,
+ yasm_bytecode *bc, int warn, /*@null@*/ void *d)
+{
+ /*@null@*/ nasm_listfmt_output_info *info = (nasm_listfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
+ unsigned int valsize = value->size;
+
+ assert(info != NULL);
+
+ /* Output */
+ switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
+ info->arch)) {
+ case -1:
+ return 1;
+ case 0:
+ break;
+ default:
+ return 0;
+ }
+
+ /* Generate reloc if needed */
+ if (info->next_reloc && info->next_reloc_addr == bc->offset+offset) {
+ bcreloc *reloc = yasm_xmalloc(sizeof(bcreloc));
+ reloc->offset = offset;
+ reloc->size = destsize;
+ reloc->rel = value->curpos_rel;
+ STAILQ_INSERT_TAIL(&info->bcrelocs, reloc, link);
+
+ /* Get next reloc's info */
+ info->next_reloc = yasm_section_reloc_next(info->next_reloc);
+ if (info->next_reloc) {
+ yasm_intnum *addr;
+ yasm_symrec *sym;
+ yasm_reloc_get(info->next_reloc, &addr, &sym);
+ info->next_reloc_addr = yasm_intnum_get_uint(addr);
+ }
+ }
+
+ if (value->abs) {
+ intn = yasm_expr_get_intnum(&value->abs, 0);
+ if (intn)
+ return yasm_arch_intnum_tobytes(info->arch, intn, buf, destsize,
+ valsize, 0, bc, 0);
+ else {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("relocation too complex"));
+ return 1;
+ }
+ } else {
+ int retval;
+ intn = yasm_intnum_create_uint(0);
+ retval = yasm_arch_intnum_tobytes(info->arch, intn, buf, destsize,
+ valsize, 0, bc, 0);
+ yasm_intnum_destroy(intn);
+ return retval;
+ }
+
+ return 0;
+}
+
+static void
+nasm_listfmt_output(yasm_listfmt *listfmt, FILE *f, yasm_linemap *linemap,
+ yasm_arch *arch)
+{
+ yasm_bytecode *bc;
+ const char *source;
+ unsigned long line = 1;
+ unsigned long listline = 1;
+ /*@only@*/ unsigned char *buf;
+ nasm_listfmt_output_info info;
+ /*@reldef@*/ SLIST_HEAD(sectrelochead, sectreloc) reloc_hist;
+ /*@null@*/ sectreloc *last_hist = NULL;
+ /*@null@*/ bcreloc *reloc = NULL;
+ yasm_section *sect;
+
+ SLIST_INIT(&reloc_hist);
+
+ info.arch = arch;
+
+ buf = yasm_xmalloc(REGULAR_BUF_SIZE);
+
+ while (!yasm_linemap_get_source(linemap, line, &bc, &source)) {
+ if (!bc) {
+ fprintf(f, "%6lu %*s%s\n", listline++, 32, "", source);
+ } else {
+ /* get the next relocation for the bytecode's section */
+ sect = yasm_bc_get_section(bc);
+ if (!last_hist || last_hist->sect != sect) {
+ int found = 0;
+
+ /* look through reloc_hist for matching section */
+ SLIST_FOREACH(last_hist, &reloc_hist, link) {
+ if (last_hist->sect == sect) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ /* not found, add to list*/
+ last_hist = yasm_xmalloc(sizeof(sectreloc));
+ last_hist->sect = sect;
+ last_hist->next_reloc = yasm_section_relocs_first(sect);
+
+ if (last_hist->next_reloc) {
+ yasm_intnum *addr;
+ yasm_symrec *sym;
+ yasm_reloc_get(last_hist->next_reloc, &addr, &sym);
+ last_hist->next_reloc_addr =
+ yasm_intnum_get_uint(addr);
+ }
+
+ SLIST_INSERT_HEAD(&reloc_hist, last_hist, link);
+ }
+ }
+
+ info.next_reloc = last_hist->next_reloc;
+ info.next_reloc_addr = last_hist->next_reloc_addr;
+ STAILQ_INIT(&info.bcrelocs);
+
+ /* loop over bytecodes on this line (usually only one) */
+ while (bc && bc->line == line) {
+ /*@null@*/ /*@only@*/ unsigned char *bigbuf;
+ unsigned long size = REGULAR_BUF_SIZE;
+ long multiple;
+ unsigned long offset = bc->offset;
+ unsigned char *origp, *p;
+ int gap;
+
+ /* convert bytecode into bytes, recording relocs along the
+ * way
+ */
+ bigbuf = yasm_bc_tobytes(bc, buf, &size, &gap, &info,
+ nasm_listfmt_output_value, NULL);
+ yasm_bc_get_multiple(bc, &multiple, 1);
+ if (multiple <= 0)
+ size = 0;
+ else
+ size /= multiple;
+
+ /* output bytes with reloc information */
+ origp = bigbuf ? bigbuf : buf;
+ p = origp;
+ reloc = STAILQ_FIRST(&info.bcrelocs);
+ if (gap) {
+ fprintf(f, "%6lu %08lX <gap>%*s%s\n", listline++, offset,
+ 18, "", source ? source : "");
+ } else while (size > 0) {
+ int i;
+
+ fprintf(f, "%6lu %08lX ", listline++, offset);
+ for (i=0; i<18 && size > 0; size--) {
+ if (reloc && (unsigned long)(p-origp) ==
+ reloc->offset) {
+ fprintf(f, "%c", reloc->rel ? '(' : '[');
+ i++;
+ }
+ fprintf(f, "%02X", *(p++));
+ i+=2;
+ if (reloc && (unsigned long)(p-origp) ==
+ reloc->offset+reloc->size) {
+ fprintf(f, "%c", reloc->rel ? ')' : ']');
+ i++;
+ reloc = STAILQ_NEXT(reloc, link);
+ }
+ }
+ if (size > 0)
+ fprintf(f, "-");
+ else {
+ if (multiple > 1) {
+ fprintf(f, "<rept>");
+ i += 6;
+ }
+ fprintf(f, "%*s", 18-i+1, "");
+ }
+ if (source) {
+ fprintf(f, " %s", source);
+ source = NULL;
+ }
+ fprintf(f, "\n");
+ }
+
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+ bc = STAILQ_NEXT(bc, link);
+ }
+
+ /* delete bcrelocs (newly generated next bytecode if any) */
+ reloc = STAILQ_FIRST(&info.bcrelocs);
+ while (reloc) {
+ bcreloc *reloc2 = STAILQ_NEXT(reloc, link);
+ yasm_xfree(reloc);
+ reloc = reloc2;
+ }
+
+ /* save reloc context */
+ last_hist->next_reloc = info.next_reloc;
+ last_hist->next_reloc_addr = info.next_reloc_addr;
+ }
+ line++;
+ }
+
+ /* delete reloc history */
+ while (!SLIST_EMPTY(&reloc_hist)) {
+ last_hist = SLIST_FIRST(&reloc_hist);
+ SLIST_REMOVE_HEAD(&reloc_hist, link);
+ yasm_xfree(last_hist);
+ }
+
+ yasm_xfree(buf);
+}
+
+/* Define listfmt structure -- see listfmt.h for details */
+yasm_listfmt_module yasm_nasm_LTX_listfmt = {
+ "NASM-style list format",
+ "nasm",
+ nasm_listfmt_create,
+ nasm_listfmt_destroy,
+ nasm_listfmt_output
+};
diff --git a/contrib/tools/yasm/modules/nasm-macros.c b/contrib/tools/yasm/modules/nasm-macros.c
new file mode 100644
index 0000000000..aa6262a7a8
--- /dev/null
+++ b/contrib/tools/yasm/modules/nasm-macros.c
@@ -0,0 +1,94 @@
+/* This file auto-generated from standard.mac by genmacro.c - don't edit it */
+
+#include <stddef.h>
+
+static const char *nasm_standard_mac[] = {
+ "%define __FILE__",
+ "%define __LINE__",
+ "%define __SECT__ [section .text]",
+ "%imacro section 1+.nolist",
+ "%define __SECT__ [section %1]",
+ "__SECT__",
+ "%endmacro",
+ "%imacro segment 1+.nolist",
+ "%define __SECT__ [segment %1]",
+ "__SECT__",
+ "%endmacro",
+ "%imacro absolute 1+.nolist",
+ "%define __SECT__ [absolute %1]",
+ "__SECT__",
+ "%endmacro",
+ "%imacro struc 1-2.nolist 0",
+ "%push struc",
+ "%define %$strucname %1",
+ "[absolute %2]",
+ "%$strucname:",
+ "%endmacro",
+ "%imacro endstruc 0.nolist",
+ "%{$strucname}_size EQU $ - %$strucname",
+ "%pop",
+ "__SECT__",
+ "%endmacro",
+ "%imacro istruc 1.nolist",
+ "%push istruc",
+ "%define %$strucname %1",
+ "%$strucstart:",
+ "%endmacro",
+ "%imacro at 1-2+.nolist",
+ "times %1-($-%$strucstart) db 0",
+ "%2",
+ "%endmacro",
+ "%imacro iend 0.nolist",
+ "times %{$strucname}_size-($-%$strucstart) db 0",
+ "%pop",
+ "%endmacro",
+ "%imacro align 1-2+.nolist nop",
+ "%ifidni %2,nop",
+ "[align %1]",
+ "%else",
+ "times ($$-$) & ((%1)-1) %2",
+ "%endif",
+ "%endmacro",
+ "%imacro alignb 1-2+.nolist resb 1",
+ "times ($$-$) & ((%1)-1) %2",
+ "%endmacro",
+ "%imacro extern 1-*.nolist",
+ "%rep %0",
+ "[extern %1]",
+ "%rotate 1",
+ "%endrep",
+ "%endmacro",
+ "%imacro bits 1+.nolist",
+ "[bits %1]",
+ "%endmacro",
+ "%imacro use16 0.nolist",
+ "[bits 16]",
+ "%endmacro",
+ "%imacro use32 0.nolist",
+ "[bits 32]",
+ "%endmacro",
+ "%imacro use64 0.nolist",
+ "[bits 64]",
+ "%endmacro",
+ "%imacro global 1-*.nolist",
+ "%rep %0",
+ "[global %1]",
+ "%rotate 1",
+ "%endrep",
+ "%endmacro",
+ "%imacro common 1-*.nolist",
+ "%rep %0",
+ "[common %1]",
+ "%rotate 1",
+ "%endrep",
+ "%endmacro",
+ "%imacro cpu 1+.nolist",
+ "[cpu %1]",
+ "%endmacro",
+ "%imacro default 1+.nolist",
+ "[default %1]",
+ "%endmacro",
+ "%define __OUTPUT_FORMAT__ __YASM_OBJFMT__",
+ NULL
+};
+
diff --git a/contrib/tools/yasm/modules/nasm-token.c b/contrib/tools/yasm/modules/nasm-token.c
new file mode 100644
index 0000000000..93d91b9f7b
--- /dev/null
+++ b/contrib/tools/yasm/modules/nasm-token.c
@@ -0,0 +1,3217 @@
+/* Generated by re2c
+ */
+/*
+ * NASM-compatible re2c lexer
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Portions based on re2c's example code.
+ *
+ * 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 <util.h>
+
+#include <libyasm.h>
+
+#include "modules/parsers/nasm/nasm-parser.h"
+#include "modules/preprocs/nasm/nasm.h"
+
+
+#define YYCURSOR cursor
+#define YYLIMIT (s->lim)
+#define YYMARKER (s->ptr)
+#define YYFILL(n) {}
+
+#define RETURN(i) {s->cur = cursor; parser_nasm->tokch = s->tok[0]; \
+ return i;}
+
+#define SCANINIT() {s->tok = cursor;}
+
+#define TOK ((char *)s->tok)
+#define TOKLEN (size_t)(cursor-s->tok)
+
+
+/* starting size of string buffer */
+#define STRBUF_ALLOC_SIZE 128
+
+/* string buffer used when parsing strings/character constants */
+static YYCTYPE *strbuf = NULL;
+
+/* length of strbuf (including terminating NULL character) */
+static size_t strbuf_size = 0;
+
+static int linechg_numcount;
+
+
+
+static int
+handle_dot_label(YYSTYPE *lvalp, char *tok, size_t toklen, size_t zeropos,
+ yasm_parser_nasm *parser_nasm)
+{
+ /* check for special non-local labels like ..start */
+ if (tok[zeropos+1] == '.') {
+ lvalp->str_val = yasm__xstrndup(tok+zeropos+(parser_nasm->tasm?2:0),
+ toklen-zeropos-(parser_nasm->tasm?2:0));
+ /* check for special non-local ..@label */
+ if (lvalp->str_val[zeropos+2] == '@')
+ return NONLOCAL_ID;
+ return SPECIAL_ID;
+ }
+ if (parser_nasm->masm && tok[zeropos] == '.') {
+ lvalp->str_val = yasm__xstrndup(tok + zeropos, toklen - zeropos);
+ return SPECIAL_ID;
+ }
+ if (parser_nasm->tasm && (!tasm_locals ||
+ (tok[zeropos] == '.' &&
+ tok[zeropos+1] != '@' && tok[zeropos+2] != '@'))) {
+ /* no locals on Tasm without the 'locals' directive */
+ /* .foo is never local either, but .@@foo may be (local structure
+ * members) */
+ lvalp->str_val = yasm__xstrndup(tok + zeropos, toklen - zeropos);
+ return SPECIAL_ID;
+ }
+ if (!parser_nasm->locallabel_base) {
+ lvalp->str_val = yasm__xstrndup(tok+zeropos, toklen-zeropos);
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("no non-local label before `%s'"),
+ lvalp->str_val);
+ } else {
+ size_t len = toklen - zeropos + parser_nasm->locallabel_base_len;
+ lvalp->str_val = yasm_xmalloc(len + 1);
+ strcpy(lvalp->str_val, parser_nasm->locallabel_base);
+ strncat(lvalp->str_val, tok+zeropos, toklen-zeropos);
+ lvalp->str_val[len] = '\0';
+ }
+
+ return LOCAL_ID;
+}
+
+int
+nasm_parser_lex(YYSTYPE *lvalp, yasm_parser_nasm *parser_nasm)
+{
+ yasm_scanner *s = &parser_nasm->s;
+ YYCTYPE *cursor = s->cur;
+ YYCTYPE endch;
+ size_t count;
+ YYCTYPE savech;
+
+ /* Handle one token of lookahead */
+ if (parser_nasm->peek_token != NONE) {
+ int tok = parser_nasm->peek_token;
+ *lvalp = parser_nasm->peek_tokval; /* structure copy */
+ parser_nasm->tokch = parser_nasm->peek_tokch;
+ parser_nasm->peek_token = NONE;
+ return tok;
+ }
+
+ /* Catch EOL (EOF from the scanner perspective) */
+ if (s->eof && cursor == s->eof)
+ return 0;
+
+ /* Jump to proper "exclusive" states */
+ switch (parser_nasm->state) {
+ case DIRECTIVE:
+ goto directive;
+ case SECTION_DIRECTIVE:
+ goto section_directive;
+ case DIRECTIVE2:
+ goto directive2;
+ case LINECHG:
+ goto linechg;
+ case LINECHG2:
+ goto linechg2;
+ default:
+ break;
+ }
+
+scan:
+ SCANINIT();
+ if (*cursor == '\0')
+ goto endofinput;
+
+ {
+ static unsigned char yybm[] = {
+ 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 3, 3, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 3, 1,
+ 255, 255, 63, 63, 63, 63, 63, 63,
+ 15, 15, 1, 1, 1, 1, 1, 3,
+ 3, 7, 7, 7, 7, 7, 7, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 1, 1, 1, 1, 167,
+ 1, 7, 7, 7, 7, 7, 7, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 1, 1, 1, 3, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 128, 0, 0, 0, 128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 128, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+
+{
+ YYCTYPE yych;
+ unsigned int yyaccept;
+ goto yy0;
+ ++YYCURSOR;
+yy0:
+ if((YYLIMIT - YYCURSOR) < 8) YYFILL(8);
+ yych = *YYCURSOR;
+ switch(yych){
+ case '\000': goto yy43;
+ case '\t': case '\r': case ' ': goto yy41;
+ case '"': case '\'': goto yy9;
+ case '$': goto yy7;
+ case '%': goto yy11;
+ case '&': case '(':
+ case ')':
+ case '*':
+ case '+':
+ case ',':
+ case '-': case ':': case '=': case '[': case '^': case '|': case '~': goto yy32;
+ case '.': goto yy36;
+ case '/': goto yy31;
+ case '0': goto yy2;
+ case '1': goto yy4;
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7': goto yy5;
+ case '8':
+ case '9': goto yy6;
+ case ';': goto yy39;
+ case '<': goto yy28;
+ case '>': goto yy30;
+ case '?': goto yy33;
+ case '@': goto yy37;
+ case 'A': case 'a': goto yy26;
+ case 'B': case 'b': goto yy12;
+ case 'C': case 'F':
+ case 'G': case 'J':
+ case 'K': case 'M': case 'P': case 'U':
+ case 'V': case 'X': case 'Z': case '_': case 'c': case 'f':
+ case 'g': case 'j':
+ case 'k': case 'm': case 'p': case 'u':
+ case 'v': case 'x': case 'z': goto yy38;
+ case 'D': case 'd': goto yy16;
+ case 'E': case 'e': goto yy24;
+ case 'H': case 'h': goto yy14;
+ case 'I': case 'i': goto yy23;
+ case 'L': case 'l': goto yy17;
+ case 'N': case 'n': goto yy27;
+ case 'O': case 'o': goto yy20;
+ case 'Q': case 'q': goto yy18;
+ case 'R': case 'r': goto yy22;
+ case 'S': case 's': goto yy25;
+ case 'T': case 't': goto yy19;
+ case 'W': case 'w': goto yy15;
+ case 'Y': case 'y': goto yy21;
+ case ']': goto yy34;
+ default: goto yy45;
+ }
+yy2: yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if(yybm[0+yych] & 64) {
+ goto yy222;
+ }
+ switch(yych){
+ case '.': goto yy203;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7': goto yy216;
+ case '8':
+ case '9': goto yy206;
+ case 'A': case 'C':
+ case 'D':
+ case 'E':
+ case 'F': case 'a': case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy208;
+ case 'B': case 'b': goto yy224;
+ case 'H': case 'h': goto yy210;
+ case 'O': case 'Q': case 'o': case 'q': goto yy220;
+ case 'X': case 'x': goto yy228;
+ case '_': goto yy226;
+ default: goto yy3;
+ }
+yy3:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ lvalp->intn = yasm_intnum_create_dec(TOK);
+ s->tok[TOKLEN] = savech;
+ RETURN(INTNUM);
+ }
+yy4: yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if(yybm[0+yych] & 64) {
+ goto yy222;
+ }
+ switch(yych){
+ case '.': goto yy203;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7': goto yy216;
+ case '8':
+ case '9': goto yy206;
+ case 'A': case 'C':
+ case 'D':
+ case 'E':
+ case 'F': case 'a': case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy208;
+ case 'B': case 'b': goto yy224;
+ case 'H': case 'h': goto yy210;
+ case 'O': case 'Q': case 'o': case 'q': goto yy220;
+ case '_': goto yy226;
+ default: goto yy3;
+ }
+yy5: yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if(yybm[0+yych] & 16) {
+ goto yy216;
+ }
+ if(yych <= 'P'){
+ if(yych <= '@'){
+ if(yych <= '.'){
+ if(yych <= '-') goto yy3;
+ goto yy203;
+ } else {
+ if(yych <= '/') goto yy3;
+ if(yych <= '9') goto yy206;
+ goto yy3;
+ }
+ } else {
+ if(yych <= 'H'){
+ if(yych <= 'F') goto yy208;
+ if(yych <= 'G') goto yy3;
+ goto yy210;
+ } else {
+ if(yych == 'O') goto yy220;
+ goto yy3;
+ }
+ }
+ } else {
+ if(yych <= 'g'){
+ if(yych <= '_'){
+ if(yych <= 'Q') goto yy220;
+ if(yych <= '^') goto yy3;
+ goto yy218;
+ } else {
+ if(yych <= '`') goto yy3;
+ if(yych <= 'f') goto yy208;
+ goto yy3;
+ }
+ } else {
+ if(yych <= 'o'){
+ if(yych <= 'h') goto yy210;
+ if(yych <= 'n') goto yy3;
+ goto yy220;
+ } else {
+ if(yych == 'q') goto yy220;
+ goto yy3;
+ }
+ }
+ }
+yy6: yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if(yych <= 'G'){
+ if(yych <= '/'){
+ if(yych == '.') goto yy203;
+ goto yy3;
+ } else {
+ if(yych <= '9') goto yy206;
+ if(yych <= '@') goto yy3;
+ if(yych <= 'F') goto yy208;
+ goto yy3;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych <= 'H') goto yy210;
+ if(yych == '_') goto yy208;
+ goto yy3;
+ } else {
+ if(yych <= 'f') goto yy208;
+ if(yych == 'h') goto yy210;
+ goto yy3;
+ }
+ }
+yy7: yych = *++YYCURSOR;
+ if(yych <= '>'){
+ if(yych <= '-'){
+ if(yych <= '"') goto yy8;
+ if(yych <= '#') goto yy194;
+ if(yych <= '$') goto yy197;
+ goto yy8;
+ } else {
+ if(yych <= '.') goto yy194;
+ if(yych <= '/') goto yy8;
+ if(yych <= '9') goto yy199;
+ goto yy8;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych <= 'Z') goto yy194;
+ if(yych == '_') goto yy194;
+ goto yy8;
+ } else {
+ if(yych <= 'z') goto yy194;
+ if(yych == '~') goto yy194;
+ goto yy8;
+ }
+ }
+yy8:
+{ RETURN(s->tok[0]); }
+yy9: yych = *++YYCURSOR;
+ goto yy10;
+yy10:
+{
+ endch = s->tok[0];
+ goto stringconst;
+ }
+yy11: yyaccept = 1;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if(yych == '%') goto yy186;
+ if(yych == 'l') goto yy188;
+ goto yy8;
+yy12: yych = *++YYCURSOR;
+ if(yych == 'Y') goto yy182;
+ if(yych == 'y') goto yy182;
+ goto yy51;
+yy13:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ if (parser_nasm->state != INSTRUCTION) {
+ uintptr_t prefix;
+ switch (yasm_arch_parse_check_insnprefix
+ (p_object->arch, TOK, TOKLEN, cur_line, &lvalp->bc,
+ &prefix)) {
+ case YASM_ARCH_INSN:
+ parser_nasm->state = INSTRUCTION;
+ s->tok[TOKLEN] = savech;
+ RETURN(INSN);
+ case YASM_ARCH_PREFIX:
+ lvalp->arch_data = prefix;
+ s->tok[TOKLEN] = savech;
+ RETURN(PREFIX);
+ default:
+ break;
+ }
+ }
+ switch (yasm_arch_parse_check_regtmod
+ (p_object->arch, TOK, TOKLEN, &lvalp->arch_data)) {
+ 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);
+ case YASM_ARCH_REGGROUP:
+ if (parser_nasm->masm) {
+ s->tok[TOKLEN] = savech;
+ RETURN(REGGROUP);
+ }
+ default:
+ break;
+ }
+ if (parser_nasm->masm) {
+ if (!yasm__strcasecmp(TOK, "offset")) {
+ s->tok[TOKLEN] = savech;
+ RETURN(OFFSET);
+ }
+ } else if (parser_nasm->tasm) {
+ if (!yasm__strcasecmp(TOK, "shl")) {
+ s->tok[TOKLEN] = savech;
+ RETURN(LEFT_OP);
+ }
+ if (!yasm__strcasecmp(TOK, "shr")) {
+ s->tok[TOKLEN] = savech;
+ RETURN(RIGHT_OP);
+ }
+ if (!yasm__strcasecmp(TOK, "and")) {
+ s->tok[TOKLEN] = savech;
+ RETURN('&');
+ }
+ if (!yasm__strcasecmp(TOK, "or")) {
+ s->tok[TOKLEN] = savech;
+ RETURN('|');
+ }
+ if (!yasm__strcasecmp(TOK, "not")) {
+ s->tok[TOKLEN] = savech;
+ RETURN('~');
+ }
+ if (!yasm__strcasecmp(TOK, "low")) {
+ s->tok[TOKLEN] = savech;
+ RETURN(LOW);
+ }
+ if (!yasm__strcasecmp(TOK, "high")) {
+ s->tok[TOKLEN] = savech;
+ RETURN(HIGH);
+ }
+ if (!yasm__strcasecmp(TOK, "offset")) {
+ s->tok[TOKLEN] = savech;
+ RETURN(OFFSET);
+ }
+ if (!yasm__strcasecmp(TOK, "fword")) {
+ s->tok[TOKLEN] = savech;
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)*2;
+ RETURN(SIZE_OVERRIDE);
+ }
+ if (!yasm__strcasecmp(TOK, "df")) {
+ s->tok[TOKLEN] = savech;
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)*3;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(DECLARE_DATA);
+ }
+ if (!yasm__strcasecmp(TOK, "label")) {
+ s->tok[TOKLEN] = savech;
+ RETURN(LABEL);
+ }
+ if (!yasm__strcasecmp(TOK, "dup")) {
+ s->tok[TOKLEN] = savech;
+ RETURN(DUP);
+ }
+ }
+ /* Propagate errors in case we got a warning from the arch */
+ yasm_errwarn_propagate(parser_nasm->errwarns, cur_line);
+ /* Just an identifier, return as such. */
+ s->tok[TOKLEN] = savech;
+ lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
+ RETURN(ID);
+ }
+yy14: yych = *++YYCURSOR;
+ if(yych == 'W') goto yy177;
+ if(yych == 'w') goto yy177;
+ goto yy51;
+yy15: yych = *++YYCURSOR;
+ if(yych <= 'R'){
+ if(yych == 'O') goto yy170;
+ if(yych <= 'Q') goto yy51;
+ goto yy171;
+ } else {
+ if(yych <= 'o'){
+ if(yych <= 'n') goto yy51;
+ goto yy170;
+ } else {
+ if(yych == 'r') goto yy171;
+ goto yy51;
+ }
+ }
+yy16: yych = *++YYCURSOR;
+ switch(yych){
+ case 'B': case 'b': goto yy144;
+ case 'D': case 'd': goto yy146;
+ case 'H': case 'h': goto yy148;
+ case 'O': case 'o': goto yy149;
+ case 'Q': case 'q': goto yy151;
+ case 'T': case 't': goto yy153;
+ case 'W': case 'w': goto yy155;
+ case 'Y': case 'y': goto yy157;
+ default: goto yy51;
+ }
+yy17: yych = *++YYCURSOR;
+ if(yych == 'O') goto yy140;
+ if(yych == 'o') goto yy140;
+ goto yy51;
+yy18: yych = *++YYCURSOR;
+ if(yych == 'W') goto yy135;
+ if(yych == 'w') goto yy135;
+ goto yy51;
+yy19: yych = *++YYCURSOR;
+ if(yych <= 'W'){
+ if(yych == 'I') goto yy125;
+ if(yych <= 'V') goto yy51;
+ goto yy126;
+ } else {
+ if(yych <= 'i'){
+ if(yych <= 'h') goto yy51;
+ goto yy125;
+ } else {
+ if(yych == 'w') goto yy126;
+ goto yy51;
+ }
+ }
+yy20: yych = *++YYCURSOR;
+ if(yych == 'W') goto yy120;
+ if(yych == 'w') goto yy120;
+ goto yy51;
+yy21: yych = *++YYCURSOR;
+ if(yych == 'W') goto yy115;
+ if(yych == 'w') goto yy115;
+ goto yy51;
+yy22: yych = *++YYCURSOR;
+ if(yych == 'E') goto yy92;
+ if(yych == 'e') goto yy92;
+ goto yy51;
+yy23: yych = *++YYCURSOR;
+ if(yych == 'N') goto yy86;
+ if(yych == 'n') goto yy86;
+ goto yy51;
+yy24: yych = *++YYCURSOR;
+ if(yych == 'Q') goto yy83;
+ if(yych == 'q') goto yy83;
+ goto yy51;
+yy25: yych = *++YYCURSOR;
+ if(yych <= 'T'){
+ if(yych == 'E') goto yy74;
+ if(yych <= 'S') goto yy51;
+ goto yy75;
+ } else {
+ if(yych <= 'e'){
+ if(yych <= 'd') goto yy51;
+ goto yy74;
+ } else {
+ if(yych == 't') goto yy75;
+ goto yy51;
+ }
+ }
+yy26: yych = *++YYCURSOR;
+ if(yych == 'B') goto yy71;
+ if(yych == 'b') goto yy71;
+ goto yy51;
+yy27: yych = *++YYCURSOR;
+ if(yych == 'O') goto yy64;
+ if(yych == 'o') goto yy64;
+ goto yy51;
+yy28: yych = *++YYCURSOR;
+ if(yych == '<') goto yy62;
+ goto yy29;
+yy29:
+{
+ yasm_warn_set(YASM_WARN_UNREC_CHAR,
+ N_("ignoring unrecognized character `%s'"),
+ yasm__conv_unprint(s->tok[0]));
+ goto scan;
+ }
+yy30: yych = *++YYCURSOR;
+ if(yych == '>') goto yy60;
+ goto yy29;
+yy31: yych = *++YYCURSOR;
+ if(yych == '/') goto yy58;
+ goto yy8;
+yy32: yych = *++YYCURSOR;
+ goto yy8;
+yy33: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy8;
+yy34: yych = *++YYCURSOR;
+ goto yy35;
+yy35:
+{ RETURN(s->tok[0]); }
+yy36: yych = *++YYCURSOR;
+ if(yych <= '>'){
+ if(yych <= '-'){
+ if(yych <= '"') goto yy29;
+ if(yych <= '$') goto yy56;
+ goto yy29;
+ } else {
+ if(yych == '/') goto yy29;
+ if(yych <= '9') goto yy56;
+ goto yy29;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych <= 'Z') goto yy56;
+ if(yych == '_') goto yy56;
+ goto yy29;
+ } else {
+ if(yych <= 'z') goto yy56;
+ if(yych == '~') goto yy56;
+ goto yy29;
+ }
+ }
+yy37: yych = *++YYCURSOR;
+ if(yych == '@') goto yy52;
+ goto yy51;
+yy38: yych = *++YYCURSOR;
+ goto yy51;
+yy39: yych = *++YYCURSOR;
+ goto yy49;
+yy40:
+{ goto scan; }
+yy41: yych = *++YYCURSOR;
+ goto yy47;
+yy42:
+{ goto scan; }
+yy43: yych = *++YYCURSOR;
+ goto yy44;
+yy44:
+{ goto endofinput; }
+yy45: yych = *++YYCURSOR;
+ goto yy29;
+yy46: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy47;
+yy47: if(yybm[256+yych] & 128) {
+ goto yy46;
+ }
+ goto yy42;
+yy48: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy49;
+yy49: if(yybm[0+yych] & 1) {
+ goto yy48;
+ }
+ goto yy40;
+yy50: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy51;
+yy51: if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy13;
+yy52: yych = *++YYCURSOR;
+ if(yych <= '>'){
+ if(yych <= '-'){
+ if(yych <= '"') goto yy13;
+ if(yych >= '%') goto yy13;
+ goto yy53;
+ } else {
+ if(yych == '/') goto yy13;
+ if(yych >= ':') goto yy13;
+ goto yy53;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych <= 'Z') goto yy53;
+ if(yych != '_') goto yy13;
+ goto yy53;
+ } else {
+ if(yych <= 'z') goto yy53;
+ if(yych != '~') goto yy13;
+ goto yy53;
+ }
+ }
+yy53: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy54;
+yy54: if(yych <= '>'){
+ if(yych <= '-'){
+ if(yych <= '"') goto yy55;
+ if(yych <= '$') goto yy53;
+ goto yy55;
+ } else {
+ if(yych == '/') goto yy55;
+ if(yych <= '9') goto yy53;
+ goto yy55;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych <= 'Z') goto yy53;
+ if(yych == '_') goto yy53;
+ goto yy55;
+ } else {
+ if(yych <= 'z') goto yy53;
+ if(yych == '~') goto yy53;
+ goto yy55;
+ }
+ }
+yy55:
+{
+ RETURN(handle_dot_label(lvalp, TOK, TOKLEN, 0, parser_nasm));
+ }
+yy56: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy57;
+yy57: if(yych <= '>'){
+ if(yych <= '-'){
+ if(yych <= '"') goto yy55;
+ if(yych <= '$') goto yy56;
+ goto yy55;
+ } else {
+ if(yych == '/') goto yy55;
+ if(yych <= '9') goto yy56;
+ goto yy55;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych <= 'Z') goto yy56;
+ if(yych == '_') goto yy56;
+ goto yy55;
+ } else {
+ if(yych <= 'z') goto yy56;
+ if(yych == '~') goto yy56;
+ goto yy55;
+ }
+ }
+yy58: yych = *++YYCURSOR;
+ goto yy59;
+yy59:
+{ RETURN(SIGNDIV); }
+yy60: yych = *++YYCURSOR;
+ goto yy61;
+yy61:
+{ RETURN(RIGHT_OP); }
+yy62: yych = *++YYCURSOR;
+ goto yy63;
+yy63:
+{ RETURN(LEFT_OP); }
+yy64: yych = *++YYCURSOR;
+ if(yych == 'S') goto yy65;
+ if(yych != 's') goto yy51;
+ goto yy65;
+yy65: yych = *++YYCURSOR;
+ if(yych == 'P') goto yy66;
+ if(yych != 'p') goto yy51;
+ goto yy66;
+yy66: yych = *++YYCURSOR;
+ if(yych == 'L') goto yy67;
+ if(yych != 'l') goto yy51;
+ goto yy67;
+yy67: yych = *++YYCURSOR;
+ if(yych == 'I') goto yy68;
+ if(yych != 'i') goto yy51;
+ goto yy68;
+yy68: yych = *++YYCURSOR;
+ if(yych == 'T') goto yy69;
+ if(yych != 't') goto yy51;
+ goto yy69;
+yy69: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy70;
+yy70:
+{ RETURN(NOSPLIT); }
+yy71: yych = *++YYCURSOR;
+ if(yych == 'S') goto yy72;
+ if(yych != 's') goto yy51;
+ goto yy72;
+yy72: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy73;
+yy73:
+{ RETURN(ABS); }
+yy74: yych = *++YYCURSOR;
+ if(yych == 'G') goto yy81;
+ if(yych == 'g') goto yy81;
+ goto yy51;
+yy75: yych = *++YYCURSOR;
+ if(yych == 'R') goto yy76;
+ if(yych != 'r') goto yy51;
+ goto yy76;
+yy76: yych = *++YYCURSOR;
+ if(yych == 'I') goto yy77;
+ if(yych != 'i') goto yy51;
+ goto yy77;
+yy77: yych = *++YYCURSOR;
+ if(yych == 'C') goto yy78;
+ if(yych != 'c') goto yy51;
+ goto yy78;
+yy78: yych = *++YYCURSOR;
+ if(yych == 'T') goto yy79;
+ if(yych != 't') goto yy51;
+ goto yy79;
+yy79: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy80;
+yy80:
+{ RETURN(STRICT); }
+yy81: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy82;
+yy82:
+{ RETURN(SEG); }
+yy83: yych = *++YYCURSOR;
+ if(yych == 'U') goto yy84;
+ if(yych != 'u') goto yy51;
+ goto yy84;
+yy84: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy85;
+yy85:
+{ RETURN(EQU); }
+yy86: yych = *++YYCURSOR;
+ if(yych == 'C') goto yy87;
+ if(yych != 'c') goto yy51;
+ goto yy87;
+yy87: yych = *++YYCURSOR;
+ if(yych == 'B') goto yy88;
+ if(yych != 'b') goto yy51;
+ goto yy88;
+yy88: yych = *++YYCURSOR;
+ if(yych == 'I') goto yy89;
+ if(yych != 'i') goto yy51;
+ goto yy89;
+yy89: yych = *++YYCURSOR;
+ if(yych == 'N') goto yy90;
+ if(yych != 'n') goto yy51;
+ goto yy90;
+yy90: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy91;
+yy91:
+{ RETURN(INCBIN); }
+yy92: yych = *++YYCURSOR;
+ if(yych <= 'S'){
+ if(yych == 'L') goto yy94;
+ if(yych <= 'R') goto yy51;
+ goto yy93;
+ } else {
+ if(yych <= 'l'){
+ if(yych <= 'k') goto yy51;
+ goto yy94;
+ } else {
+ if(yych != 's') goto yy51;
+ goto yy93;
+ }
+ }
+yy93: yych = *++YYCURSOR;
+ switch(yych){
+ case 'B': case 'b': goto yy96;
+ case 'D': case 'd': goto yy98;
+ case 'H': case 'h': goto yy100;
+ case 'O': case 'o': goto yy101;
+ case 'Q': case 'q': goto yy103;
+ case 'T': case 't': goto yy105;
+ case 'W': case 'w': goto yy107;
+ case 'Y': case 'y': goto yy109;
+ default: goto yy51;
+ }
+yy94: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy95;
+yy95:
+{ RETURN(REL); }
+yy96: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy97;
+yy97:
+{
+ lvalp->int_info = 8;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(RESERVE_SPACE);
+ }
+yy98: yych = *++YYCURSOR;
+ if(yych <= 'Q'){
+ if(yych <= '.'){
+ if(yych <= '"') goto yy99;
+ if(yych <= '$') goto yy50;
+ if(yych >= '.') goto yy50;
+ goto yy99;
+ } else {
+ if(yych <= '9'){
+ if(yych >= '0') goto yy50;
+ goto yy99;
+ } else {
+ if(yych <= '>') goto yy99;
+ if(yych <= 'P') goto yy50;
+ goto yy113;
+ }
+ }
+ } else {
+ if(yych <= 'p'){
+ if(yych <= '^'){
+ if(yych <= 'Z') goto yy50;
+ goto yy99;
+ } else {
+ if(yych != '`') goto yy50;
+ goto yy99;
+ }
+ } else {
+ if(yych <= 'z'){
+ if(yych <= 'q') goto yy113;
+ goto yy50;
+ } else {
+ if(yych == '~') goto yy50;
+ goto yy99;
+ }
+ }
+ }
+yy99:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)*2;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(RESERVE_SPACE);
+ }
+yy100: yych = *++YYCURSOR;
+ if(yych == 'W') goto yy111;
+ if(yych == 'w') goto yy111;
+ goto yy51;
+yy101: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy102;
+yy102:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(RESERVE_SPACE);
+ }
+yy103: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy104;
+yy104:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)*4;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(RESERVE_SPACE);
+ }
+yy105: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy106;
+yy106:
+{
+ lvalp->int_info = 80;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(RESERVE_SPACE);
+ }
+yy107: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy108;
+yy108:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch);
+ parser_nasm->state = INSTRUCTION;
+ RETURN(RESERVE_SPACE);
+ }
+yy109: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy110;
+yy110:
+{
+ lvalp->int_info = 256;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(RESERVE_SPACE);
+ }
+yy111: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy112;
+yy112:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)/2;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(RESERVE_SPACE);
+ }
+yy113: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy114;
+yy114:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(RESERVE_SPACE);
+ }
+yy115: yych = *++YYCURSOR;
+ if(yych == 'O') goto yy116;
+ if(yych != 'o') goto yy51;
+ goto yy116;
+yy116: yych = *++YYCURSOR;
+ if(yych == 'R') goto yy117;
+ if(yych != 'r') goto yy51;
+ goto yy117;
+yy117: yych = *++YYCURSOR;
+ if(yych == 'D') goto yy118;
+ if(yych != 'd') goto yy51;
+ goto yy118;
+yy118: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy119;
+yy119:
+{
+ lvalp->int_info = 256;
+ RETURN(SIZE_OVERRIDE);
+ }
+yy120: yych = *++YYCURSOR;
+ if(yych == 'O') goto yy121;
+ if(yych != 'o') goto yy51;
+ goto yy121;
+yy121: yych = *++YYCURSOR;
+ if(yych == 'R') goto yy122;
+ if(yych != 'r') goto yy51;
+ goto yy122;
+yy122: yych = *++YYCURSOR;
+ if(yych == 'D') goto yy123;
+ if(yych != 'd') goto yy51;
+ goto yy123;
+yy123: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy124;
+yy124:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
+ RETURN(SIZE_OVERRIDE);
+ }
+yy125: yych = *++YYCURSOR;
+ if(yych == 'M') goto yy131;
+ if(yych == 'm') goto yy131;
+ goto yy51;
+yy126: yych = *++YYCURSOR;
+ if(yych == 'O') goto yy127;
+ if(yych != 'o') goto yy51;
+ goto yy127;
+yy127: yych = *++YYCURSOR;
+ if(yych == 'R') goto yy128;
+ if(yych != 'r') goto yy51;
+ goto yy128;
+yy128: yych = *++YYCURSOR;
+ if(yych == 'D') goto yy129;
+ if(yych != 'd') goto yy51;
+ goto yy129;
+yy129: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy130;
+yy130:
+{ lvalp->int_info = 80; RETURN(SIZE_OVERRIDE); }
+yy131: yych = *++YYCURSOR;
+ if(yych == 'E') goto yy132;
+ if(yych != 'e') goto yy51;
+ goto yy132;
+yy132: yych = *++YYCURSOR;
+ if(yych == 'S') goto yy133;
+ if(yych != 's') goto yy51;
+ goto yy133;
+yy133: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy134;
+yy134:
+{ RETURN(TIMES); }
+yy135: yych = *++YYCURSOR;
+ if(yych == 'O') goto yy136;
+ if(yych != 'o') goto yy51;
+ goto yy136;
+yy136: yych = *++YYCURSOR;
+ if(yych == 'R') goto yy137;
+ if(yych != 'r') goto yy51;
+ goto yy137;
+yy137: yych = *++YYCURSOR;
+ if(yych == 'D') goto yy138;
+ if(yych != 'd') goto yy51;
+ goto yy138;
+yy138: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy139;
+yy139:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)*4;
+ RETURN(SIZE_OVERRIDE);
+ }
+yy140: yych = *++YYCURSOR;
+ if(yych == 'N') goto yy141;
+ if(yych != 'n') goto yy51;
+ goto yy141;
+yy141: yych = *++YYCURSOR;
+ if(yych == 'G') goto yy142;
+ if(yych != 'g') goto yy51;
+ goto yy142;
+yy142: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy143;
+yy143:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)*2;
+ RETURN(SIZE_OVERRIDE);
+ }
+yy144: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy145;
+yy145:
+{
+ lvalp->int_info = 8;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(DECLARE_DATA);
+ }
+yy146: yych = *++YYCURSOR;
+ if(yych <= 'Q'){
+ if(yych <= '.'){
+ if(yych <= '"') goto yy147;
+ if(yych <= '$') goto yy50;
+ if(yych >= '.') goto yy50;
+ goto yy147;
+ } else {
+ if(yych <= '9'){
+ if(yych >= '0') goto yy50;
+ goto yy147;
+ } else {
+ if(yych <= '>') goto yy147;
+ if(yych <= 'P') goto yy50;
+ goto yy168;
+ }
+ }
+ } else {
+ if(yych <= 'p'){
+ if(yych <= '^'){
+ if(yych <= 'Z') goto yy50;
+ goto yy147;
+ } else {
+ if(yych != '`') goto yy50;
+ goto yy147;
+ }
+ } else {
+ if(yych <= 'z'){
+ if(yych <= 'q') goto yy168;
+ goto yy50;
+ } else {
+ if(yych == '~') goto yy50;
+ goto yy147;
+ }
+ }
+ }
+yy147:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)*2;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(DECLARE_DATA);
+ }
+yy148: yych = *++YYCURSOR;
+ if(yych == 'W') goto yy166;
+ if(yych == 'w') goto yy166;
+ goto yy51;
+yy149: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy150;
+yy150:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(DECLARE_DATA);
+ }
+yy151: yych = *++YYCURSOR;
+ if(yych <= 'W'){
+ if(yych <= '.'){
+ if(yych <= '"') goto yy152;
+ if(yych <= '$') goto yy50;
+ if(yych >= '.') goto yy50;
+ goto yy152;
+ } else {
+ if(yych <= '9'){
+ if(yych >= '0') goto yy50;
+ goto yy152;
+ } else {
+ if(yych <= '>') goto yy152;
+ if(yych <= 'V') goto yy50;
+ goto yy161;
+ }
+ }
+ } else {
+ if(yych <= 'v'){
+ if(yych <= '^'){
+ if(yych <= 'Z') goto yy50;
+ goto yy152;
+ } else {
+ if(yych != '`') goto yy50;
+ goto yy152;
+ }
+ } else {
+ if(yych <= 'z'){
+ if(yych <= 'w') goto yy161;
+ goto yy50;
+ } else {
+ if(yych == '~') goto yy50;
+ goto yy152;
+ }
+ }
+ }
+yy152:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)*4;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(DECLARE_DATA);
+ }
+yy153: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy154;
+yy154:
+{
+ lvalp->int_info = 80;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(DECLARE_DATA);
+ }
+yy155: yych = *++YYCURSOR;
+ if(yych <= 'O'){
+ if(yych <= '.'){
+ if(yych <= '"') goto yy156;
+ if(yych <= '$') goto yy50;
+ if(yych >= '.') goto yy50;
+ goto yy156;
+ } else {
+ if(yych <= '9'){
+ if(yych >= '0') goto yy50;
+ goto yy156;
+ } else {
+ if(yych <= '>') goto yy156;
+ if(yych <= 'N') goto yy50;
+ goto yy159;
+ }
+ }
+ } else {
+ if(yych <= 'n'){
+ if(yych <= '^'){
+ if(yych <= 'Z') goto yy50;
+ goto yy156;
+ } else {
+ if(yych != '`') goto yy50;
+ goto yy156;
+ }
+ } else {
+ if(yych <= 'z'){
+ if(yych <= 'o') goto yy159;
+ goto yy50;
+ } else {
+ if(yych == '~') goto yy50;
+ goto yy156;
+ }
+ }
+ }
+yy156:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch);
+ parser_nasm->state = INSTRUCTION;
+ RETURN(DECLARE_DATA);
+ }
+yy157: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy158;
+yy158:
+{
+ lvalp->int_info = 256;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(DECLARE_DATA);
+ }
+yy159: yych = *++YYCURSOR;
+ if(yych == 'R') goto yy160;
+ if(yych != 'r') goto yy51;
+ goto yy160;
+yy160: yych = *++YYCURSOR;
+ if(yych == 'D') goto yy142;
+ if(yych == 'd') goto yy142;
+ goto yy51;
+yy161: yych = *++YYCURSOR;
+ if(yych == 'O') goto yy162;
+ if(yych != 'o') goto yy51;
+ goto yy162;
+yy162: yych = *++YYCURSOR;
+ if(yych == 'R') goto yy163;
+ if(yych != 'r') goto yy51;
+ goto yy163;
+yy163: yych = *++YYCURSOR;
+ if(yych == 'D') goto yy164;
+ if(yych != 'd') goto yy51;
+ goto yy164;
+yy164: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy165;
+yy165:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
+ RETURN(SIZE_OVERRIDE);
+ }
+yy166: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy167;
+yy167:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)/2;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(DECLARE_DATA);
+ }
+yy168: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy169;
+yy169:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)*8;
+ parser_nasm->state = INSTRUCTION;
+ RETURN(DECLARE_DATA);
+ }
+yy170: yych = *++YYCURSOR;
+ if(yych == 'R') goto yy174;
+ if(yych == 'r') goto yy174;
+ goto yy51;
+yy171: yych = *++YYCURSOR;
+ if(yych == 'T') goto yy172;
+ if(yych != 't') goto yy51;
+ goto yy172;
+yy172: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy173;
+yy173:
+{ RETURN(WRT); }
+yy174: yych = *++YYCURSOR;
+ if(yych == 'D') goto yy175;
+ if(yych != 'd') goto yy51;
+ goto yy175;
+yy175: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy176;
+yy176:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch);
+ RETURN(SIZE_OVERRIDE);
+ }
+yy177: yych = *++YYCURSOR;
+ if(yych == 'O') goto yy178;
+ if(yych != 'o') goto yy51;
+ goto yy178;
+yy178: yych = *++YYCURSOR;
+ if(yych == 'R') goto yy179;
+ if(yych != 'r') goto yy51;
+ goto yy179;
+yy179: yych = *++YYCURSOR;
+ if(yych == 'D') goto yy180;
+ if(yych != 'd') goto yy51;
+ goto yy180;
+yy180: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy181;
+yy181:
+{
+ lvalp->int_info = yasm_arch_wordsize(p_object->arch)/2;
+ RETURN(SIZE_OVERRIDE);
+ }
+yy182: yych = *++YYCURSOR;
+ if(yych == 'T') goto yy183;
+ if(yych != 't') goto yy51;
+ goto yy183;
+yy183: yych = *++YYCURSOR;
+ if(yych == 'E') goto yy184;
+ if(yych != 'e') goto yy51;
+ goto yy184;
+yy184: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 2) {
+ goto yy50;
+ }
+ goto yy185;
+yy185:
+{ lvalp->int_info = 8; RETURN(SIZE_OVERRIDE); }
+yy186: yych = *++YYCURSOR;
+ goto yy187;
+yy187:
+{ RETURN(SIGNMOD); }
+yy188: yych = *++YYCURSOR;
+ if(yych == 'i') goto yy190;
+ goto yy189;
+yy189: YYCURSOR = YYMARKER;
+ switch(yyaccept){
+ case 0: goto yy3;
+ case 3: goto yy225;
+ case 2: goto yy205;
+ case 1: goto yy8;
+ }
+yy190: yych = *++YYCURSOR;
+ if(yych != 'n') goto yy189;
+ goto yy191;
+yy191: yych = *++YYCURSOR;
+ if(yych != 'e') goto yy189;
+ goto yy192;
+yy192: yych = *++YYCURSOR;
+ goto yy193;
+yy193:
+{
+ parser_nasm->state = LINECHG;
+ linechg_numcount = 0;
+ RETURN(LINE);
+ }
+yy194: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy195;
+yy195: if(yych <= '>'){
+ if(yych <= '-'){
+ if(yych <= '"') goto yy196;
+ if(yych <= '$') goto yy194;
+ goto yy196;
+ } else {
+ if(yych == '/') goto yy196;
+ if(yych <= '9') goto yy194;
+ goto yy196;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych <= 'Z') goto yy194;
+ if(yych == '_') goto yy194;
+ goto yy196;
+ } else {
+ if(yych <= 'z') goto yy194;
+ if(yych == '~') goto yy194;
+ goto yy196;
+ }
+ }
+yy196:
+{
+ if (TOK[1] == '.' ||
+ (parser_nasm->tasm && TOK[1] == '@' && TOK[2] == '@')) {
+ /* handle like .label */
+ RETURN(handle_dot_label(lvalp, TOK, TOKLEN, 1, parser_nasm));
+ }
+ lvalp->str_val = yasm__xstrndup(TOK+1, TOKLEN-1);
+ RETURN(ID);
+ }
+yy197: yych = *++YYCURSOR;
+ if(yych <= '>'){
+ if(yych <= '-'){
+ if(yych <= '"') goto yy198;
+ if(yych <= '$') goto yy194;
+ goto yy198;
+ } else {
+ if(yych == '/') goto yy198;
+ if(yych <= '9') goto yy194;
+ goto yy198;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych <= 'Z') goto yy194;
+ if(yych == '_') goto yy194;
+ goto yy198;
+ } else {
+ if(yych <= 'z') goto yy194;
+ if(yych == '~') goto yy194;
+ goto yy198;
+ }
+ }
+yy198:
+{ RETURN(START_SECTION_ID); }
+yy199: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 4) {
+ goto yy200;
+ }
+ goto yy195;
+yy200: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy201;
+yy201: if(yybm[0+yych] & 4) {
+ goto yy200;
+ }
+ if(yych <= '>'){
+ if(yych <= '$'){
+ if(yych >= '#') goto yy194;
+ goto yy202;
+ } else {
+ if(yych == '.') goto yy194;
+ goto yy202;
+ }
+ } else {
+ if(yych <= 'z'){
+ if(yych <= 'Z') goto yy194;
+ if(yych >= 'g') goto yy194;
+ goto yy202;
+ } else {
+ if(yych == '~') goto yy194;
+ goto yy202;
+ }
+ }
+yy202:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ if (s->tok[1] == 'x' || s->tok[1] == 'X')
+ /* skip 0 and x */
+ lvalp->intn = yasm_intnum_create_hex(TOK+2);
+ else
+ /* don't skip 0 */
+ lvalp->intn = yasm_intnum_create_hex(TOK+1);
+ s->tok[TOKLEN] = savech;
+ RETURN(INTNUM);
+ }
+yy203: yyaccept = 2;
+ YYMARKER = ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+ yych = *YYCURSOR;
+ goto yy204;
+yy204: if(yybm[0+yych] & 8) {
+ goto yy203;
+ }
+ if(yych == 'E') goto yy212;
+ if(yych == 'e') goto yy212;
+ goto yy205;
+yy205:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ lvalp->flt = yasm_floatnum_create(TOK);
+ s->tok[TOKLEN] = savech;
+ RETURN(FLTNUM);
+ }
+yy206: yyaccept = 0;
+ YYMARKER = ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy207;
+yy207: if(yych <= 'G'){
+ if(yych <= '/'){
+ if(yych == '.') goto yy203;
+ goto yy3;
+ } else {
+ if(yych <= '9') goto yy206;
+ if(yych <= '@') goto yy3;
+ if(yych >= 'G') goto yy3;
+ goto yy208;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych <= 'H') goto yy210;
+ if(yych != '_') goto yy3;
+ goto yy208;
+ } else {
+ if(yych <= 'f') goto yy208;
+ if(yych == 'h') goto yy210;
+ goto yy3;
+ }
+ }
+yy208: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy209;
+yy209: if(yych <= 'H'){
+ if(yych <= '@'){
+ if(yych <= '/') goto yy189;
+ if(yych <= '9') goto yy208;
+ goto yy189;
+ } else {
+ if(yych <= 'F') goto yy208;
+ if(yych <= 'G') goto yy189;
+ goto yy210;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych == '_') goto yy208;
+ goto yy189;
+ } else {
+ if(yych <= 'f') goto yy208;
+ if(yych != 'h') goto yy189;
+ goto yy210;
+ }
+ }
+yy210: yych = *++YYCURSOR;
+ goto yy211;
+yy211:
+{
+ s->tok[TOKLEN-1] = '\0'; /* strip off 'h' */
+ lvalp->intn = yasm_intnum_create_hex(TOK);
+ RETURN(INTNUM);
+ }
+yy212: yych = *++YYCURSOR;
+ if(yych <= ','){
+ if(yych != '+') goto yy189;
+ goto yy213;
+ } else {
+ if(yych <= '-') goto yy213;
+ if(yych <= '/') goto yy189;
+ if(yych <= '9') goto yy214;
+ goto yy189;
+ }
+yy213: yych = *++YYCURSOR;
+ if(yych <= '/') goto yy189;
+ if(yych >= ':') goto yy189;
+ goto yy214;
+yy214: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy215;
+yy215: if(yych <= '/') goto yy205;
+ if(yych <= '9') goto yy214;
+ goto yy205;
+yy216: yyaccept = 0;
+ YYMARKER = ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy217;
+yy217: if(yybm[0+yych] & 16) {
+ goto yy216;
+ }
+ if(yych <= 'P'){
+ if(yych <= '@'){
+ if(yych <= '.'){
+ if(yych <= '-') goto yy3;
+ goto yy203;
+ } else {
+ if(yych <= '/') goto yy3;
+ if(yych <= '9') goto yy206;
+ goto yy3;
+ }
+ } else {
+ if(yych <= 'H'){
+ if(yych <= 'F') goto yy208;
+ if(yych <= 'G') goto yy3;
+ goto yy210;
+ } else {
+ if(yych == 'O') goto yy220;
+ goto yy3;
+ }
+ }
+ } else {
+ if(yych <= 'g'){
+ if(yych <= '_'){
+ if(yych <= 'Q') goto yy220;
+ if(yych <= '^') goto yy3;
+ goto yy218;
+ } else {
+ if(yych <= '`') goto yy3;
+ if(yych <= 'f') goto yy208;
+ goto yy3;
+ }
+ } else {
+ if(yych <= 'o'){
+ if(yych <= 'h') goto yy210;
+ if(yych <= 'n') goto yy3;
+ goto yy220;
+ } else {
+ if(yych == 'q') goto yy220;
+ goto yy3;
+ }
+ }
+ }
+yy218: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy219;
+yy219: if(yybm[0+yych] & 32) {
+ goto yy218;
+ }
+ if(yych <= 'P'){
+ if(yych <= 'F'){
+ if(yych <= '7') goto yy189;
+ if(yych <= '9') goto yy208;
+ if(yych <= '@') goto yy189;
+ goto yy208;
+ } else {
+ if(yych <= 'H'){
+ if(yych <= 'G') goto yy189;
+ goto yy210;
+ } else {
+ if(yych != 'O') goto yy189;
+ goto yy220;
+ }
+ }
+ } else {
+ if(yych <= 'h'){
+ if(yych <= '`'){
+ if(yych >= 'R') goto yy189;
+ goto yy220;
+ } else {
+ if(yych <= 'f') goto yy208;
+ if(yych <= 'g') goto yy189;
+ goto yy210;
+ }
+ } else {
+ if(yych <= 'o'){
+ if(yych <= 'n') goto yy189;
+ goto yy220;
+ } else {
+ if(yych != 'q') goto yy189;
+ goto yy220;
+ }
+ }
+ }
+yy220: yych = *++YYCURSOR;
+ goto yy221;
+yy221:
+{
+ s->tok[TOKLEN-1] = '\0'; /* strip off 'q' or 'o' */
+ lvalp->intn = yasm_intnum_create_oct(TOK);
+ RETURN(INTNUM);
+ }
+yy222: yyaccept = 0;
+ YYMARKER = ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ goto yy223;
+yy223: if(yybm[0+yych] & 64) {
+ goto yy222;
+ }
+ switch(yych){
+ case '.': goto yy203;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7': goto yy216;
+ case '8':
+ case '9': goto yy206;
+ case 'A': case 'C':
+ case 'D':
+ case 'E':
+ case 'F': case 'a': case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy208;
+ case 'B': case 'b': goto yy224;
+ case 'H': case 'h': goto yy210;
+ case 'O': case 'Q': case 'o': case 'q': goto yy220;
+ case '_': goto yy226;
+ default: goto yy3;
+ }
+yy224: yyaccept = 3;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if(yych <= 'H'){
+ if(yych <= '@'){
+ if(yych <= '/') goto yy225;
+ if(yych <= '9') goto yy208;
+ goto yy225;
+ } else {
+ if(yych <= 'F') goto yy208;
+ if(yych >= 'H') goto yy210;
+ goto yy225;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych == '_') goto yy208;
+ goto yy225;
+ } else {
+ if(yych <= 'f') goto yy208;
+ if(yych == 'h') goto yy210;
+ goto yy225;
+ }
+ }
+yy225:
+{
+ s->tok[TOKLEN-1] = '\0'; /* strip off 'b' */
+ lvalp->intn = yasm_intnum_create_bin(TOK);
+ RETURN(INTNUM);
+ }
+yy226: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ goto yy227;
+yy227: if(yybm[0+yych] & 128) {
+ goto yy226;
+ }
+ switch(yych){
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7': goto yy218;
+ case '8':
+ case '9': case 'A': case 'C':
+ case 'D':
+ case 'E':
+ case 'F': case 'a': case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy208;
+ case 'B': case 'b': goto yy224;
+ case 'H': case 'h': goto yy210;
+ case 'O': case 'Q': case 'o': case 'q': goto yy220;
+ default: goto yy189;
+ }
+yy228: yych = *++YYCURSOR;
+ if(yych <= 'F'){
+ if(yych <= '/') goto yy189;
+ if(yych <= '9') goto yy229;
+ if(yych <= '@') goto yy189;
+ goto yy229;
+ } else {
+ if(yych <= '_'){
+ if(yych <= '^') goto yy189;
+ goto yy229;
+ } else {
+ if(yych <= '`') goto yy189;
+ if(yych >= 'g') goto yy189;
+ goto yy229;
+ }
+ }
+yy229: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy230;
+yy230: if(yych <= 'F'){
+ if(yych <= '/') goto yy202;
+ if(yych <= '9') goto yy229;
+ if(yych <= '@') goto yy202;
+ goto yy229;
+ } else {
+ if(yych <= '_'){
+ if(yych <= '^') goto yy202;
+ goto yy229;
+ } else {
+ if(yych <= '`') goto yy202;
+ if(yych <= 'f') goto yy229;
+ goto yy202;
+ }
+ }
+}
+}
+
+
+ /* %line linenum+lineinc filename */
+linechg:
+ SCANINIT();
+ if (*cursor == '\0')
+ goto endofinput;
+
+ {
+ static unsigned char yybm[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 64, 0, 0, 0, 64, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 64, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+
+{
+ YYCTYPE yych;
+ goto yy231;
+ ++YYCURSOR;
+yy231:
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if(yych <= '\037'){
+ if(yych <= '\t'){
+ if(yych <= '\000') goto yy235;
+ if(yych <= '\b') goto yy241;
+ goto yy239;
+ } else {
+ if(yych == '\r') goto yy239;
+ goto yy241;
+ }
+ } else {
+ if(yych <= '+'){
+ if(yych <= ' ') goto yy239;
+ if(yych <= '*') goto yy241;
+ goto yy237;
+ } else {
+ if(yych <= '/') goto yy241;
+ if(yych >= ':') goto yy241;
+ goto yy233;
+ }
+ }
+yy233: yych = *++YYCURSOR;
+ goto yy246;
+yy234:
+{
+ linechg_numcount++;
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ lvalp->intn = yasm_intnum_create_dec(TOK);
+ s->tok[TOKLEN] = savech;
+ RETURN(INTNUM);
+ }
+yy235: yych = *++YYCURSOR;
+ goto yy236;
+yy236:
+{ goto endofinput; }
+yy237: yych = *++YYCURSOR;
+ goto yy238;
+yy238:
+{
+ RETURN(s->tok[0]);
+ }
+yy239: yych = *++YYCURSOR;
+ goto yy244;
+yy240:
+{
+ if (linechg_numcount == 2) {
+ parser_nasm->state = LINECHG2;
+ goto linechg2;
+ }
+ goto linechg;
+ }
+yy241: yych = *++YYCURSOR;
+ goto yy242;
+yy242:
+{
+ yasm_warn_set(YASM_WARN_UNREC_CHAR,
+ N_("ignoring unrecognized character `%s'"),
+ yasm__conv_unprint(s->tok[0]));
+ goto linechg;
+ }
+yy243: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy244;
+yy244: if(yybm[0+yych] & 64) {
+ goto yy243;
+ }
+ goto yy240;
+yy245: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy246;
+yy246: if(yybm[0+yych] & 128) {
+ goto yy245;
+ }
+ goto yy234;
+}
+}
+
+
+linechg2:
+ SCANINIT();
+ if (*cursor == '\0')
+ goto endofinput;
+
+ {
+ static unsigned char yybm[] = {
+ 0, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ };
+
+{
+ YYCTYPE yych;
+ goto yy247;
+ ++YYCURSOR;
+yy247:
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if(yych <= '\000') goto yy249;
+ if(yych == '\r') goto yy251;
+ goto yy253;
+yy249: yych = *++YYCURSOR;
+ goto yy250;
+yy250:
+{ goto endofinput; }
+yy251: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 128) {
+ goto yy253;
+ }
+ goto yy252;
+yy252:
+{ goto linechg2; }
+yy253: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy254;
+yy254: if(yybm[0+yych] & 128) {
+ goto yy253;
+ }
+ goto yy255;
+yy255:
+{
+ parser_nasm->state = LINECHG;
+ lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
+ RETURN(FILENAME);
+ }
+}
+}
+
+
+ /* directive: [name value] */
+directive:
+ SCANINIT();
+ if (*cursor == '\0')
+ goto endofinput;
+
+ {
+ static unsigned char yybm[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 0, 0, 0, 0, 0, 0,
+ 0, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 0, 0, 0, 0, 128,
+ 0, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+
+{
+ YYCTYPE yych;
+ goto yy256;
+ ++YYCURSOR;
+yy256:
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if(yych <= ']'){
+ if(yych <= '@'){
+ if(yych >= '\001') goto yy263;
+ goto yy258;
+ } else {
+ if(yych <= 'Z') goto yy261;
+ if(yych <= '\\') goto yy263;
+ goto yy260;
+ }
+ } else {
+ if(yych <= '_'){
+ if(yych <= '^') goto yy263;
+ goto yy261;
+ } else {
+ if(yych <= '`') goto yy263;
+ if(yych <= 'z') goto yy261;
+ goto yy263;
+ }
+ }
+yy258: yych = *++YYCURSOR;
+ goto yy259;
+yy259:
+{ goto endofinput; }
+yy260: yych = *++YYCURSOR;
+ goto yy259;
+yy261: yych = *++YYCURSOR;
+ goto yy266;
+yy262:
+{
+ lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
+ if (yasm__strcasecmp(lvalp->str_val, "section") == 0 ||
+ yasm__strcasecmp(lvalp->str_val, "segment") == 0)
+ parser_nasm->state = SECTION_DIRECTIVE;
+ else
+ parser_nasm->state = DIRECTIVE2;
+ RETURN(DIRECTIVE_NAME);
+ }
+yy263: yych = *++YYCURSOR;
+ goto yy264;
+yy264:
+{
+ yasm_warn_set(YASM_WARN_UNREC_CHAR,
+ N_("ignoring unrecognized character `%s'"),
+ yasm__conv_unprint(s->tok[0]));
+ goto directive;
+ }
+yy265: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy266;
+yy266: if(yybm[0+yych] & 128) {
+ goto yy265;
+ }
+ goto yy262;
+}
+}
+
+
+ /* section directive (the section name portion thereof) */
+section_directive:
+ SCANINIT();
+ if (*cursor == '\0')
+ goto endofinput;
+
+ {
+ static unsigned char yybm[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 64, 0, 0, 0, 64, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 64, 0, 0, 128, 128, 0, 0, 0,
+ 0, 0, 0, 0, 0, 128, 128, 0,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 0, 0, 0, 0, 0, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 0, 0, 0, 0, 128,
+ 0, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 0, 0, 0, 128, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+
+{
+ YYCTYPE yych;
+ goto yy267;
+ ++YYCURSOR;
+yy267:
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if(yych <= ','){
+ if(yych <= '\037'){
+ if(yych <= '\t'){
+ if(yych <= '\000') goto yy275;
+ if(yych <= '\b') goto yy278;
+ goto yy273;
+ } else {
+ if(yych == '\r') goto yy273;
+ goto yy278;
+ }
+ } else {
+ if(yych <= '"'){
+ if(yych <= ' ') goto yy273;
+ if(yych <= '!') goto yy278;
+ goto yy271;
+ } else {
+ if(yych <= '$') goto yy269;
+ if(yych == '\'') goto yy271;
+ goto yy278;
+ }
+ }
+ } else {
+ if(yych <= ']'){
+ if(yych <= '9'){
+ if(yych == '/') goto yy278;
+ goto yy269;
+ } else {
+ if(yych <= '>') goto yy278;
+ if(yych <= 'Z') goto yy269;
+ if(yych <= '\\') goto yy278;
+ goto yy277;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych != '_') goto yy278;
+ goto yy269;
+ } else {
+ if(yych <= 'z') goto yy269;
+ if(yych != '~') goto yy278;
+ goto yy269;
+ }
+ }
+ }
+yy269: yych = *++YYCURSOR;
+ goto yy283;
+yy270:
+{
+ lvalp->str.contents = yasm__xstrndup(TOK, TOKLEN);
+ lvalp->str.len = TOKLEN;
+ parser_nasm->state = DIRECTIVE2;
+ RETURN(STRING);
+ }
+yy271: yych = *++YYCURSOR;
+ goto yy272;
+yy272:
+{
+ parser_nasm->state = DIRECTIVE2;
+ endch = s->tok[0];
+ goto stringconst;
+ }
+yy273: yych = *++YYCURSOR;
+ goto yy281;
+yy274:
+{
+ parser_nasm->state = DIRECTIVE2;
+ goto section_directive;
+ }
+yy275: yych = *++YYCURSOR;
+ goto yy276;
+yy276:
+{ goto endofinput; }
+yy277: yych = *++YYCURSOR;
+ goto yy276;
+yy278: yych = *++YYCURSOR;
+ goto yy279;
+yy279:
+{
+ yasm_warn_set(YASM_WARN_UNREC_CHAR,
+ N_("ignoring unrecognized character `%s'"),
+ yasm__conv_unprint(s->tok[0]));
+ goto section_directive;
+ }
+yy280: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy281;
+yy281: if(yybm[0+yych] & 64) {
+ goto yy280;
+ }
+ goto yy274;
+yy282: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy283;
+yy283: if(yybm[0+yych] & 128) {
+ goto yy282;
+ }
+ goto yy270;
+}
+}
+
+
+ /* inner part of directive */
+directive2:
+ SCANINIT();
+ if (*cursor == '\0')
+ goto endofinput;
+
+ {
+ static unsigned char yybm[] = {
+ 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 3, 3, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 3, 1,
+ 255, 255, 63, 63, 63, 63, 63, 63,
+ 15, 15, 1, 1, 1, 1, 1, 3,
+ 3, 7, 7, 7, 7, 7, 7, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 1, 1, 1, 1, 167,
+ 1, 7, 7, 7, 7, 7, 7, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 1, 1, 1, 3, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 128, 0, 0, 0, 128, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 128, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+
+{
+ YYCTYPE yych;
+ unsigned int yyaccept;
+ goto yy284;
+ ++YYCURSOR;
+yy284:
+ if((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
+ yych = *YYCURSOR;
+ if(yych <= '7'){
+ if(yych <= '#'){
+ if(yych <= '\r'){
+ if(yych <= '\b'){
+ if(yych <= '\000') goto yy309;
+ goto yy311;
+ } else {
+ if(yych <= '\t') goto yy307;
+ if(yych <= '\f') goto yy311;
+ goto yy307;
+ }
+ } else {
+ if(yych <= ' '){
+ if(yych <= '\037') goto yy311;
+ goto yy307;
+ } else {
+ if(yych == '"') goto yy293;
+ goto yy311;
+ }
+ }
+ } else {
+ if(yych <= '-'){
+ if(yych <= '%'){
+ if(yych <= '$') goto yy291;
+ goto yy299;
+ } else {
+ if(yych == '\'') goto yy293;
+ goto yy300;
+ }
+ } else {
+ if(yych <= '/'){
+ if(yych <= '.') goto yy303;
+ goto yy298;
+ } else {
+ if(yych <= '0') goto yy286;
+ if(yych <= '1') goto yy288;
+ goto yy289;
+ }
+ }
+ }
+ } else {
+ if(yych <= '['){
+ if(yych <= '='){
+ if(yych <= ':'){
+ if(yych <= '9') goto yy290;
+ goto yy300;
+ } else {
+ if(yych <= ';') goto yy305;
+ if(yych <= '<') goto yy295;
+ goto yy300;
+ }
+ } else {
+ if(yych <= '?'){
+ if(yych <= '>') goto yy297;
+ goto yy303;
+ } else {
+ if(yych <= '@') goto yy311;
+ if(yych <= 'Z') goto yy303;
+ goto yy300;
+ }
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych <= ']'){
+ if(yych <= '\\') goto yy311;
+ goto yy301;
+ } else {
+ if(yych <= '^') goto yy300;
+ if(yych <= '_') goto yy303;
+ goto yy311;
+ }
+ } else {
+ if(yych <= '|'){
+ if(yych <= 'z') goto yy303;
+ if(yych <= '{') goto yy311;
+ goto yy300;
+ } else {
+ if(yych == '~') goto yy300;
+ goto yy311;
+ }
+ }
+ }
+ }
+yy286: yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if(yych == 'X') goto yy352;
+ if(yych == 'x') goto yy352;
+ goto yy347;
+yy287:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ lvalp->intn = yasm_intnum_create_dec(TOK);
+ s->tok[TOKLEN] = savech;
+ RETURN(INTNUM);
+ }
+yy288: yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ goto yy347;
+yy289: yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ goto yy341;
+yy290: yyaccept = 0;
+ yych = *(YYMARKER = ++YYCURSOR);
+ goto yy334;
+yy291: yych = *++YYCURSOR;
+ if(yych <= '>'){
+ if(yych <= '-'){
+ if(yych <= '"') goto yy292;
+ if(yych <= '$') goto yy326;
+ goto yy292;
+ } else {
+ if(yych <= '.') goto yy326;
+ if(yych <= '/') goto yy292;
+ if(yych <= '9') goto yy329;
+ goto yy292;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych <= 'Z') goto yy326;
+ if(yych == '_') goto yy326;
+ goto yy292;
+ } else {
+ if(yych <= 'z') goto yy326;
+ if(yych == '~') goto yy326;
+ goto yy292;
+ }
+ }
+yy292:
+{ RETURN(s->tok[0]); }
+yy293: yych = *++YYCURSOR;
+ goto yy294;
+yy294:
+{
+ endch = s->tok[0];
+ goto stringconst;
+ }
+yy295: yych = *++YYCURSOR;
+ if(yych == '<') goto yy324;
+ goto yy296;
+yy296:
+{
+ yasm_warn_set(YASM_WARN_UNREC_CHAR,
+ N_("ignoring unrecognized character `%s'"),
+ yasm__conv_unprint(s->tok[0]));
+ goto scan;
+ }
+yy297: yych = *++YYCURSOR;
+ if(yych == '>') goto yy322;
+ goto yy296;
+yy298: yych = *++YYCURSOR;
+ if(yych == '/') goto yy320;
+ goto yy292;
+yy299: yych = *++YYCURSOR;
+ if(yych == '%') goto yy318;
+ goto yy292;
+yy300: yych = *++YYCURSOR;
+ goto yy292;
+yy301: yych = *++YYCURSOR;
+ goto yy302;
+yy302:
+{ goto endofinput; }
+yy303: yych = *++YYCURSOR;
+ goto yy317;
+yy304:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ switch (yasm_arch_parse_check_regtmod
+ (p_object->arch, TOK, TOKLEN, &lvalp->arch_data)) {
+ case YASM_ARCH_REG:
+ s->tok[TOKLEN] = savech;
+ RETURN(REG);
+ default:
+ s->tok[TOKLEN] = savech;
+ }
+ /* Propagate errors in case we got a warning from the arch */
+ yasm_errwarn_propagate(parser_nasm->errwarns, cur_line);
+ /* Just an identifier, return as such. */
+ lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
+ RETURN(ID);
+ }
+yy305: yych = *++YYCURSOR;
+ goto yy315;
+yy306:
+{ goto directive2; }
+yy307: yych = *++YYCURSOR;
+ goto yy313;
+yy308:
+{ goto directive2; }
+yy309: yych = *++YYCURSOR;
+ goto yy310;
+yy310:
+{ goto endofinput; }
+yy311: yych = *++YYCURSOR;
+ goto yy296;
+yy312: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy313;
+yy313: if(yybm[256+yych] & 128) {
+ goto yy312;
+ }
+ goto yy308;
+yy314: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy315;
+yy315: if(yybm[0+yych] & 1) {
+ goto yy314;
+ }
+ goto yy306;
+yy316: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy317;
+yy317: if(yybm[0+yych] & 2) {
+ goto yy316;
+ }
+ goto yy304;
+yy318: yych = *++YYCURSOR;
+ goto yy319;
+yy319:
+{ RETURN(SIGNMOD); }
+yy320: yych = *++YYCURSOR;
+ goto yy321;
+yy321:
+{ RETURN(SIGNDIV); }
+yy322: yych = *++YYCURSOR;
+ goto yy323;
+yy323:
+{ RETURN(RIGHT_OP); }
+yy324: yych = *++YYCURSOR;
+ goto yy325;
+yy325:
+{ RETURN(LEFT_OP); }
+yy326: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy327;
+yy327: if(yych <= '>'){
+ if(yych <= '-'){
+ if(yych <= '"') goto yy328;
+ if(yych <= '$') goto yy326;
+ goto yy328;
+ } else {
+ if(yych == '/') goto yy328;
+ if(yych <= '9') goto yy326;
+ goto yy328;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych <= 'Z') goto yy326;
+ if(yych == '_') goto yy326;
+ goto yy328;
+ } else {
+ if(yych <= 'z') goto yy326;
+ if(yych == '~') goto yy326;
+ goto yy328;
+ }
+ }
+yy328:
+{
+ lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
+ RETURN(ID);
+ }
+yy329: yych = *++YYCURSOR;
+ if(yybm[0+yych] & 4) {
+ goto yy330;
+ }
+ goto yy327;
+yy330: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy331;
+yy331: if(yybm[0+yych] & 4) {
+ goto yy330;
+ }
+ if(yych <= '>'){
+ if(yych <= '$'){
+ if(yych >= '#') goto yy326;
+ goto yy332;
+ } else {
+ if(yych == '.') goto yy326;
+ goto yy332;
+ }
+ } else {
+ if(yych <= 'z'){
+ if(yych <= 'Z') goto yy326;
+ if(yych >= 'g') goto yy326;
+ goto yy332;
+ } else {
+ if(yych == '~') goto yy326;
+ goto yy332;
+ }
+ }
+yy332:
+{
+ savech = s->tok[TOKLEN];
+ s->tok[TOKLEN] = '\0';
+ if (s->tok[1] == 'x' || s->tok[1] == 'X')
+ /* skip 0 and x */
+ lvalp->intn = yasm_intnum_create_hex(TOK+2);
+ else
+ /* don't skip 0 */
+ lvalp->intn = yasm_intnum_create_hex(TOK+1);
+ s->tok[TOKLEN] = savech;
+ RETURN(INTNUM);
+ }
+yy333: yyaccept = 0;
+ YYMARKER = ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy334;
+yy334: if(yybm[0+yych] & 8) {
+ goto yy333;
+ }
+ if(yych <= '^'){
+ if(yych <= 'F'){
+ if(yych <= '@') goto yy287;
+ goto yy335;
+ } else {
+ if(yych == 'H') goto yy338;
+ goto yy287;
+ }
+ } else {
+ if(yych <= 'f'){
+ if(yych == '`') goto yy287;
+ goto yy335;
+ } else {
+ if(yych == 'h') goto yy338;
+ goto yy287;
+ }
+ }
+yy335: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy336;
+yy336: if(yych <= 'H'){
+ if(yych <= '@'){
+ if(yych <= '/') goto yy337;
+ if(yych <= '9') goto yy335;
+ goto yy337;
+ } else {
+ if(yych <= 'F') goto yy335;
+ if(yych >= 'H') goto yy338;
+ goto yy337;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych == '_') goto yy335;
+ goto yy337;
+ } else {
+ if(yych <= 'f') goto yy335;
+ if(yych == 'h') goto yy338;
+ goto yy337;
+ }
+ }
+yy337: YYCURSOR = YYMARKER;
+ switch(yyaccept){
+ case 0: goto yy287;
+ case 1: goto yy349;
+ }
+yy338: yych = *++YYCURSOR;
+ goto yy339;
+yy339:
+{
+ s->tok[TOKLEN-1] = '\0'; /* strip off 'h' */
+ lvalp->intn = yasm_intnum_create_hex(TOK);
+ RETURN(INTNUM);
+ }
+yy340: yyaccept = 0;
+ YYMARKER = ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy341;
+yy341: if(yybm[0+yych] & 16) {
+ goto yy340;
+ }
+ if(yych <= 'Q'){
+ if(yych <= 'G'){
+ if(yych <= '9'){
+ if(yych <= '7') goto yy287;
+ goto yy333;
+ } else {
+ if(yych <= '@') goto yy287;
+ if(yych <= 'F') goto yy335;
+ goto yy287;
+ }
+ } else {
+ if(yych <= 'N'){
+ if(yych <= 'H') goto yy338;
+ goto yy287;
+ } else {
+ if(yych == 'P') goto yy287;
+ goto yy344;
+ }
+ }
+ } else {
+ if(yych <= 'g'){
+ if(yych <= '_'){
+ if(yych <= '^') goto yy287;
+ goto yy342;
+ } else {
+ if(yych <= '`') goto yy287;
+ if(yych <= 'f') goto yy335;
+ goto yy287;
+ }
+ } else {
+ if(yych <= 'o'){
+ if(yych <= 'h') goto yy338;
+ if(yych <= 'n') goto yy287;
+ goto yy344;
+ } else {
+ if(yych == 'q') goto yy344;
+ goto yy287;
+ }
+ }
+ }
+yy342: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy343;
+yy343: if(yybm[0+yych] & 32) {
+ goto yy342;
+ }
+ if(yych <= 'P'){
+ if(yych <= 'F'){
+ if(yych <= '7') goto yy337;
+ if(yych <= '9') goto yy335;
+ if(yych <= '@') goto yy337;
+ goto yy335;
+ } else {
+ if(yych <= 'H'){
+ if(yych <= 'G') goto yy337;
+ goto yy338;
+ } else {
+ if(yych != 'O') goto yy337;
+ goto yy344;
+ }
+ }
+ } else {
+ if(yych <= 'h'){
+ if(yych <= '`'){
+ if(yych >= 'R') goto yy337;
+ goto yy344;
+ } else {
+ if(yych <= 'f') goto yy335;
+ if(yych <= 'g') goto yy337;
+ goto yy338;
+ }
+ } else {
+ if(yych <= 'o'){
+ if(yych <= 'n') goto yy337;
+ goto yy344;
+ } else {
+ if(yych != 'q') goto yy337;
+ goto yy344;
+ }
+ }
+ }
+yy344: yych = *++YYCURSOR;
+ goto yy345;
+yy345:
+{
+ s->tok[TOKLEN-1] = '\0'; /* strip off 'q' or 'o' */
+ lvalp->intn = yasm_intnum_create_oct(TOK);
+ RETURN(INTNUM);
+ }
+yy346: yyaccept = 0;
+ YYMARKER = ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ goto yy347;
+yy347: if(yybm[0+yych] & 64) {
+ goto yy346;
+ }
+ switch(yych){
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7': goto yy340;
+ case '8':
+ case '9': goto yy333;
+ case 'A': case 'C':
+ case 'D':
+ case 'E':
+ case 'F': case 'a': case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy335;
+ case 'B': case 'b': goto yy348;
+ case 'H': case 'h': goto yy338;
+ case 'O': case 'Q': case 'o': case 'q': goto yy344;
+ case '_': goto yy350;
+ default: goto yy287;
+ }
+yy348: yyaccept = 1;
+ yych = *(YYMARKER = ++YYCURSOR);
+ if(yych <= 'H'){
+ if(yych <= '@'){
+ if(yych <= '/') goto yy349;
+ if(yych <= '9') goto yy335;
+ goto yy349;
+ } else {
+ if(yych <= 'F') goto yy335;
+ if(yych >= 'H') goto yy338;
+ goto yy349;
+ }
+ } else {
+ if(yych <= '`'){
+ if(yych == '_') goto yy335;
+ goto yy349;
+ } else {
+ if(yych <= 'f') goto yy335;
+ if(yych == 'h') goto yy338;
+ goto yy349;
+ }
+ }
+yy349:
+{
+ s->tok[TOKLEN-1] = '\0'; /* strip off 'b' */
+ lvalp->intn = yasm_intnum_create_bin(TOK);
+ RETURN(INTNUM);
+ }
+yy350: ++YYCURSOR;
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ goto yy351;
+yy351: if(yybm[0+yych] & 128) {
+ goto yy350;
+ }
+ switch(yych){
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7': goto yy342;
+ case '8':
+ case '9': case 'A': case 'C':
+ case 'D':
+ case 'E':
+ case 'F': case 'a': case 'c':
+ case 'd':
+ case 'e':
+ case 'f': goto yy335;
+ case 'B': case 'b': goto yy348;
+ case 'H': case 'h': goto yy338;
+ case 'O': case 'Q': case 'o': case 'q': goto yy344;
+ default: goto yy337;
+ }
+yy352: yych = *++YYCURSOR;
+ if(yych <= 'F'){
+ if(yych <= '/') goto yy337;
+ if(yych <= '9') goto yy353;
+ if(yych <= '@') goto yy337;
+ goto yy353;
+ } else {
+ if(yych <= '_'){
+ if(yych <= '^') goto yy337;
+ goto yy353;
+ } else {
+ if(yych <= '`') goto yy337;
+ if(yych >= 'g') goto yy337;
+ goto yy353;
+ }
+ }
+yy353: ++YYCURSOR;
+ if(YYLIMIT == YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ goto yy354;
+yy354: if(yych <= 'F'){
+ if(yych <= '/') goto yy332;
+ if(yych <= '9') goto yy353;
+ if(yych <= '@') goto yy332;
+ goto yy353;
+ } else {
+ if(yych <= '_'){
+ if(yych <= '^') goto yy332;
+ goto yy353;
+ } else {
+ if(yych <= '`') goto yy332;
+ if(yych <= 'f') goto yy353;
+ goto yy332;
+ }
+ }
+}
+}
+
+
+ /* string/character constant values */
+stringconst:
+ strbuf = yasm_xmalloc(STRBUF_ALLOC_SIZE);
+ strbuf_size = STRBUF_ALLOC_SIZE;
+ count = 0;
+
+stringconst_scan:
+ SCANINIT();
+ if (*cursor == '\0')
+ goto stringconst_error;
+
+ {
+
+{
+ YYCTYPE yych;
+ goto yy355;
+ ++YYCURSOR;
+yy355:
+ if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
+ yych = *YYCURSOR;
+ if(yych <= '"'){
+ if(yych <= '\000') goto yy357;
+ if(yych <= '!') goto yy362;
+ goto yy361;
+ } else {
+ if(yych == '\'') goto yy359;
+ goto yy362;
+ }
+yy357: yych = *++YYCURSOR;
+ goto yy358;
+yy358:
+{ goto stringconst_error; }
+yy359: yych = *++YYCURSOR;
+ if(yych == '\'') goto yy363;
+ goto yy360;
+yy360:
+{
+ if (s->tok[0] == endch)
+ goto stringconst_end;
+
+ strbuf[count++] = s->tok[0];
+ if (count >= strbuf_size) {
+ strbuf = yasm_xrealloc(strbuf, strbuf_size + STRBUF_ALLOC_SIZE);
+ strbuf_size += STRBUF_ALLOC_SIZE;
+ }
+
+ goto stringconst_scan;
+ }
+yy361: yych = *++YYCURSOR;
+ if(yych == '"') goto yy363;
+ goto yy360;
+yy362: yych = *++YYCURSOR;
+ goto yy360;
+yy363: yych = *++YYCURSOR;
+ goto yy364;
+yy364:
+{
+ if (endch != s->tok[0]) {
+ strbuf[count++] = s->tok[0];
+ if (count >= strbuf_size) {
+ strbuf = yasm_xrealloc(strbuf,
+ strbuf_size + STRBUF_ALLOC_SIZE);
+ strbuf_size += STRBUF_ALLOC_SIZE;
+ }
+ } else if (!parser_nasm->tasm) {
+ YYCURSOR--;
+ goto stringconst_end;
+ }
+ strbuf[count++] = s->tok[0];
+ if (count >= strbuf_size) {
+ strbuf = yasm_xrealloc(strbuf, strbuf_size + STRBUF_ALLOC_SIZE);
+ strbuf_size += STRBUF_ALLOC_SIZE;
+ }
+ goto stringconst_scan;
+ }
+}
+}
+
+
+stringconst_error:
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("unterminated string"));
+
+stringconst_end:
+ strbuf[count] = '\0';
+ lvalp->str.contents = (char *)strbuf;
+ lvalp->str.len = count;
+ RETURN(STRING);
+
+endofinput:
+ parser_nasm->state = INITIAL;
+ RETURN(s->tok[0]);
+}
+
diff --git a/contrib/tools/yasm/modules/nasm-version.c b/contrib/tools/yasm/modules/nasm-version.c
new file mode 100644
index 0000000000..0d806749a5
--- /dev/null
+++ b/contrib/tools/yasm/modules/nasm-version.c
@@ -0,0 +1,15 @@
+/* This file auto-generated from standard.mac by genmacro.c - don't edit it */
+
+#include <stddef.h>
+
+static const char *nasm_version_mac[] = {
+ "%define __YASM_MAJOR__ 1",
+ "%define __YASM_MINOR__ 3",
+ "%define __YASM_SUBMINOR__ 0",
+ "%define __YASM_BUILD__ 0",
+ "%define __YASM_PATCHLEVEL__ 0",
+ "%define __YASM_VERSION_ID__ 001030000h",
+ "%define __YASM_VER__ \"1.3.0\"",
+ NULL
+};
+
diff --git a/contrib/tools/yasm/modules/objfmts/bin/bin-objfmt.c b/contrib/tools/yasm/modules/objfmts/bin/bin-objfmt.c
new file mode 100644
index 0000000000..5f422245d3
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/bin/bin-objfmt.c
@@ -0,0 +1,1972 @@
+/*
+ * Flat-format binary object format
+ *
+ * Copyright (C) 2002-2007 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 <util.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <libyasm.h>
+
+
+#define REGULAR_OUTBUF_SIZE 1024
+
+typedef struct bin_section_data {
+ int bss; /* aka nobits */
+
+ /* User-provided alignment */
+ yasm_intnum *align, *valign;
+
+ /* User-provided starts */
+ /*@null@*/ /*@owned@*/ yasm_expr *start, *vstart;
+
+ /* User-provided follows */
+ /*@null@*/ /*@owned@*/ char *follows, *vfollows;
+
+ /* Calculated (final) starts, used only during output() */
+ /*@null@*/ /*@owned@*/ yasm_intnum *istart, *ivstart;
+
+ /* Calculated (final) length, used only during output() */
+ /*@null@*/ /*@owned@*/ yasm_intnum *length;
+} bin_section_data;
+
+typedef struct yasm_objfmt_bin {
+ yasm_objfmt_base objfmt; /* base structure */
+
+ enum {
+ NO_MAP = 0,
+ MAP_NONE = 0x01,
+ MAP_BRIEF = 0x02,
+ MAP_SECTIONS = 0x04,
+ MAP_SYMBOLS = 0x08
+ } map_flags;
+ /*@null@*/ /*@only@*/ char *map_filename;
+
+ /*@null@*/ /*@only@*/ yasm_expr *org;
+} yasm_objfmt_bin;
+
+/* symrec data is used only for the special symbols section<sectname>.start,
+ * section<sectname>.vstart, and section<sectname>.length
+ */
+typedef struct bin_symrec_data {
+ yasm_section *section; /* referenced section */
+ enum bin_ssym {
+ SSYM_START,
+ SSYM_VSTART,
+ SSYM_LENGTH
+ } which;
+} bin_symrec_data;
+
+static void bin_section_data_destroy(/*@only@*/ void *d);
+static void bin_section_data_print(void *data, FILE *f, int indent_level);
+
+static const yasm_assoc_data_callback bin_section_data_cb = {
+ bin_section_data_destroy,
+ bin_section_data_print
+};
+
+static void bin_symrec_data_destroy(/*@only@*/ void *d);
+static void bin_symrec_data_print(void *data, FILE *f, int indent_level);
+
+static const yasm_assoc_data_callback bin_symrec_data_cb = {
+ bin_symrec_data_destroy,
+ bin_symrec_data_print
+};
+
+yasm_objfmt_module yasm_bin_LTX_objfmt;
+
+
+static yasm_objfmt *
+bin_objfmt_create(yasm_object *object)
+{
+ yasm_objfmt_bin *objfmt_bin = yasm_xmalloc(sizeof(yasm_objfmt_bin));
+ objfmt_bin->objfmt.module = &yasm_bin_LTX_objfmt;
+
+ objfmt_bin->map_flags = NO_MAP;
+ objfmt_bin->map_filename = NULL;
+ objfmt_bin->org = NULL;
+
+ return (yasm_objfmt *)objfmt_bin;
+}
+
+typedef TAILQ_HEAD(bin_group_head, bin_group) bin_groups;
+
+typedef struct bin_group {
+ TAILQ_ENTRY(bin_group) link;
+ yasm_section *section;
+ bin_section_data *bsd;
+
+ /* Groups that (in parallel) logically come immediately after this
+ * group's section.
+ */
+ bin_groups follow_groups;
+} bin_group;
+
+/* Recursive function to find group containing named section. */
+static bin_group *
+find_group_by_name(bin_groups *groups, const char *name)
+{
+ bin_group *group, *found;
+ TAILQ_FOREACH(group, groups, link) {
+ if (strcmp(yasm_section_get_name(group->section), name) == 0)
+ return group;
+ /* Recurse to loop through follow groups */
+ found = find_group_by_name(&group->follow_groups, name);
+ if (found)
+ return found;
+ }
+ return NULL;
+}
+
+/* Recursive function to find group. Returns NULL if not found. */
+static bin_group *
+find_group_by_section(bin_groups *groups, yasm_section *section)
+{
+ bin_group *group, *found;
+ TAILQ_FOREACH(group, groups, link) {
+ if (group->section == section)
+ return group;
+ /* Recurse to loop through follow groups */
+ found = find_group_by_section(&group->follow_groups, section);
+ if (found)
+ return found;
+ }
+ return NULL;
+}
+
+#if 0
+/* Debugging function */
+static void
+print_groups(const bin_groups *groups, int indent_level)
+{
+ bin_group *group;
+ TAILQ_FOREACH(group, groups, link) {
+ printf("%*sSection `%s':\n", indent_level, "",
+ yasm_section_get_name(group->section));
+ bin_section_data_print(group->bsd, stdout, indent_level+1);
+ if (!TAILQ_EMPTY(&group->follow_groups)) {
+ printf("%*sFollowing groups:\n", indent_level, "");
+ print_groups(&group->follow_groups, indent_level+1);
+ }
+ }
+}
+#endif
+
+static void
+bin_group_destroy(/*@only@*/ bin_group *group)
+{
+ bin_group *follow, *group_temp;
+ TAILQ_FOREACH_SAFE(follow, &group->follow_groups, link, group_temp)
+ bin_group_destroy(follow);
+ yasm_xfree(group);
+}
+
+typedef struct bin_objfmt_output_info {
+ yasm_object *object;
+ yasm_errwarns *errwarns;
+ /*@dependent@*/ FILE *f;
+ /*@only@*/ unsigned char *buf;
+ /*@observer@*/ const yasm_section *sect;
+ unsigned long start; /* what normal variables go against */
+
+ yasm_intnum *origin;
+ yasm_intnum *tmp_intn; /* temporary working intnum */
+
+ bin_groups lma_groups, vma_groups;
+} bin_objfmt_output_info;
+
+static int
+bin_objfmt_check_sym(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ /*@null@*/ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
+ yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+ assert(info != NULL);
+
+ /* Don't check internally-generated symbols. Only internally generated
+ * symbols have symrec data, so simply check for its presence.
+ */
+ if (yasm_symrec_get_data(sym, &bin_symrec_data_cb))
+ return 0;
+
+ if (vis & YASM_SYM_EXTERN) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("binary object format does not support extern variables"));
+ yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym));
+ } else if (vis & YASM_SYM_GLOBAL) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("binary object format does not support global variables"));
+ yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym));
+ } else if (vis & YASM_SYM_COMMON) {
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("binary object format does not support common variables"));
+ yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym));
+ }
+ return 0;
+}
+
+static int
+bin_lma_create_group(yasm_section *sect, /*@null@*/ void *d)
+{
+ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
+ bin_section_data *bsd = yasm_section_get_data(sect, &bin_section_data_cb);
+ unsigned long align = yasm_section_get_align(sect);
+ bin_group *group;
+
+ assert(info != NULL);
+ assert(bsd != NULL);
+
+ group = yasm_xmalloc(sizeof(bin_group));
+ group->section = sect;
+ group->bsd = bsd;
+ TAILQ_INIT(&group->follow_groups);
+
+ /* Determine section alignment as necessary. */
+ if (!bsd->align)
+ bsd->align = yasm_intnum_create_uint(align > 4 ? align : 4);
+ else {
+ yasm_intnum *align_intn = yasm_intnum_create_uint(align);
+ if (yasm_intnum_compare(align_intn, bsd->align) > 0) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("section `%s' internal align of %lu is greater than `%s' of %lu; using `%s'"),
+ yasm_section_get_name(sect),
+ yasm_intnum_get_uint(align_intn),
+ N_("align"),
+ yasm_intnum_get_uint(bsd->align),
+ N_("align"));
+ yasm_errwarn_propagate(info->errwarns, 0);
+ }
+ yasm_intnum_destroy(align_intn);
+ }
+
+ /* Calculate section integer start. */
+ if (bsd->start) {
+ bsd->istart = yasm_expr_get_intnum(&bsd->start, 0);
+ if (!bsd->istart) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("start expression is too complex"));
+ yasm_errwarn_propagate(info->errwarns, bsd->start->line);
+ return 1;
+ } else
+ bsd->istart = yasm_intnum_copy(bsd->istart);
+ } else
+ bsd->istart = NULL;
+
+ /* Calculate section integer vstart. */
+ if (bsd->vstart) {
+ bsd->ivstart = yasm_expr_get_intnum(&bsd->vstart, 0);
+ if (!bsd->ivstart) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("vstart expression is too complex"));
+ yasm_errwarn_propagate(info->errwarns, bsd->vstart->line);
+ return 1;
+ } else
+ bsd->ivstart = yasm_intnum_copy(bsd->ivstart);
+ } else
+ bsd->ivstart = NULL;
+
+ /* Calculate section integer length. */
+ bsd->length = yasm_calc_bc_dist(yasm_section_bcs_first(sect),
+ yasm_section_bcs_last(sect));
+
+ TAILQ_INSERT_TAIL(&info->lma_groups, group, link);
+ return 0;
+}
+
+static int
+bin_vma_create_group(yasm_section *sect, /*@null@*/ void *d)
+{
+ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
+ bin_section_data *bsd = yasm_section_get_data(sect, &bin_section_data_cb);
+ bin_group *group;
+
+ assert(info != NULL);
+ assert(bsd != NULL);
+
+ group = yasm_xmalloc(sizeof(bin_group));
+ group->section = sect;
+ group->bsd = bsd;
+ TAILQ_INIT(&group->follow_groups);
+
+ TAILQ_INSERT_TAIL(&info->vma_groups, group, link);
+ return 0;
+}
+
+/* Calculates new start address based on alignment constraint.
+ * Start is modified (rounded up) to the closest aligned value greater than
+ * what was passed in.
+ * Align must be a power of 2.
+ */
+static void
+bin_objfmt_align(yasm_intnum *start, const yasm_intnum *align)
+{
+ /* Because alignment is always a power of two, we can use some bit
+ * trickery to do this easily.
+ */
+ yasm_intnum *align_intn =
+ yasm_intnum_create_uint(yasm_intnum_get_uint(align)-1);
+ yasm_intnum_calc(align_intn, YASM_EXPR_AND, start);
+ if (!yasm_intnum_is_zero(align_intn)) {
+ /* start = (start & ~(align-1)) + align; */
+ yasm_intnum_set_uint(align_intn, yasm_intnum_get_uint(align)-1);
+ yasm_intnum_calc(align_intn, YASM_EXPR_NOT, NULL);
+ yasm_intnum_calc(align_intn, YASM_EXPR_AND, start);
+ yasm_intnum_set(start, align);
+ yasm_intnum_calc(start, YASM_EXPR_ADD, align_intn);
+ }
+ yasm_intnum_destroy(align_intn);
+}
+
+/* Recursive function to assign start addresses.
+ * Updates start, last, and vdelta parameters as it goes along.
+ * The tmp parameter is just a working intnum so one doesn't have to be
+ * locally allocated for this purpose.
+ */
+static void
+group_assign_start_recurse(bin_group *group, yasm_intnum *start,
+ yasm_intnum *last, yasm_intnum *vdelta,
+ yasm_intnum *tmp, yasm_errwarns *errwarns)
+{
+ bin_group *follow_group;
+
+ /* Determine LMA */
+ if (group->bsd->istart) {
+ yasm_intnum_set(group->bsd->istart, start);
+ if (group->bsd->align) {
+ bin_objfmt_align(group->bsd->istart, group->bsd->align);
+ if (yasm_intnum_compare(start, group->bsd->istart) != 0) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("start inconsistent with align; using aligned value"));
+ yasm_errwarn_propagate(errwarns, group->bsd->start->line);
+ }
+ }
+ } else {
+ group->bsd->istart = yasm_intnum_copy(start);
+ if (group->bsd->align != 0)
+ bin_objfmt_align(group->bsd->istart, group->bsd->align);
+ }
+
+ /* Determine VMA if either just valign specified or if no v* specified */
+ if (!group->bsd->vstart) {
+ if (!group->bsd->vfollows && !group->bsd->valign) {
+ /* No v* specified, set VMA=LMA+vdelta. */
+ group->bsd->ivstart = yasm_intnum_copy(group->bsd->istart);
+ yasm_intnum_calc(group->bsd->ivstart, YASM_EXPR_ADD, vdelta);
+ } else if (!group->bsd->vfollows) {
+ /* Just valign specified: set VMA=LMA+vdelta, align VMA, then add
+ * delta between unaligned and aligned to vdelta parameter.
+ */
+ group->bsd->ivstart = yasm_intnum_copy(group->bsd->istart);
+ yasm_intnum_calc(group->bsd->ivstart, YASM_EXPR_ADD, vdelta);
+ yasm_intnum_set(tmp, group->bsd->ivstart);
+ bin_objfmt_align(group->bsd->ivstart, group->bsd->valign);
+ yasm_intnum_calc(vdelta, YASM_EXPR_ADD, group->bsd->ivstart);
+ yasm_intnum_calc(vdelta, YASM_EXPR_SUB, tmp);
+ }
+ }
+
+ /* Find the maximum end value */
+ yasm_intnum_set(tmp, group->bsd->istart);
+ yasm_intnum_calc(tmp, YASM_EXPR_ADD, group->bsd->length);
+ if (yasm_intnum_compare(tmp, last) > 0) /* tmp > last */
+ yasm_intnum_set(last, tmp);
+
+ /* Recurse for each following group. */
+ TAILQ_FOREACH(follow_group, &group->follow_groups, link) {
+ /* Following sections have to follow this one,
+ * so add length to start.
+ */
+ yasm_intnum_set(start, group->bsd->istart);
+ yasm_intnum_calc(start, YASM_EXPR_ADD, group->bsd->length);
+
+ group_assign_start_recurse(follow_group, start, last, vdelta, tmp,
+ errwarns);
+ }
+}
+
+/* Recursive function to assign start addresses.
+ * Updates start parameter as it goes along.
+ * The tmp parameter is just a working intnum so one doesn't have to be
+ * locally allocated for this purpose.
+ */
+static void
+group_assign_vstart_recurse(bin_group *group, yasm_intnum *start,
+ yasm_errwarns *errwarns)
+{
+ bin_group *follow_group;
+
+ /* Determine VMA section alignment as necessary.
+ * Default to LMA alignment if not specified.
+ */
+ if (!group->bsd->valign)
+ group->bsd->valign = yasm_intnum_copy(group->bsd->align);
+ else {
+ unsigned long align = yasm_section_get_align(group->section);
+ yasm_intnum *align_intn = yasm_intnum_create_uint(align);
+ if (yasm_intnum_compare(align_intn, group->bsd->valign) > 0) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("section `%s' internal align of %lu is greater than `%s' of %lu; using `%s'"),
+ yasm_section_get_name(group->section),
+ yasm_intnum_get_uint(align_intn),
+ N_("valign"),
+ yasm_intnum_get_uint(group->bsd->valign),
+ N_("valign"));
+ yasm_errwarn_propagate(errwarns, 0);
+ }
+ yasm_intnum_destroy(align_intn);
+ }
+
+ /* Determine VMA */
+ if (group->bsd->ivstart) {
+ yasm_intnum_set(group->bsd->ivstart, start);
+ if (group->bsd->valign) {
+ bin_objfmt_align(group->bsd->ivstart, group->bsd->valign);
+ if (yasm_intnum_compare(start, group->bsd->ivstart) != 0) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("vstart inconsistent with valign"));
+ yasm_errwarn_propagate(errwarns, group->bsd->vstart->line);
+ }
+ }
+ } else {
+ group->bsd->ivstart = yasm_intnum_copy(start);
+ if (group->bsd->valign)
+ bin_objfmt_align(group->bsd->ivstart, group->bsd->valign);
+ }
+
+ /* Recurse for each following group. */
+ TAILQ_FOREACH(follow_group, &group->follow_groups, link) {
+ /* Following sections have to follow this one,
+ * so add length to start.
+ */
+ yasm_intnum_set(start, group->bsd->ivstart);
+ yasm_intnum_calc(start, YASM_EXPR_ADD, group->bsd->length);
+
+ group_assign_vstart_recurse(follow_group, start, errwarns);
+ }
+}
+
+static /*@null@*/ const yasm_intnum *
+get_ssym_value(yasm_symrec *sym)
+{
+ bin_symrec_data *bsymd = yasm_symrec_get_data(sym, &bin_symrec_data_cb);
+ bin_section_data *bsd;
+
+ if (!bsymd)
+ return NULL;
+
+ bsd = yasm_section_get_data(bsymd->section, &bin_section_data_cb);
+ assert(bsd != NULL);
+
+ switch (bsymd->which) {
+ case SSYM_START: return bsd->istart;
+ case SSYM_VSTART: return bsd->ivstart;
+ case SSYM_LENGTH: return bsd->length;
+ }
+ return NULL;
+}
+
+static /*@only@*/ yasm_expr *
+bin_objfmt_expr_xform(/*@returned@*/ /*@only@*/ yasm_expr *e,
+ /*@unused@*/ /*@null@*/ void *d)
+{
+ int i;
+ for (i=0; i<e->numterms; i++) {
+ /*@dependent@*/ yasm_section *sect;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
+ /*@null@*/ yasm_intnum *dist;
+ /*@null@*/ const yasm_intnum *ssymval;
+
+ /* Transform symrecs or precbcs that reference sections into
+ * vstart + intnum(dist).
+ */
+ if (((e->terms[i].type == YASM_EXPR_SYM &&
+ yasm_symrec_get_label(e->terms[i].data.sym, &precbc)) ||
+ (e->terms[i].type == YASM_EXPR_PRECBC &&
+ (precbc = e->terms[i].data.precbc))) &&
+ (sect = yasm_bc_get_section(precbc)) &&
+ (dist = yasm_calc_bc_dist(yasm_section_bcs_first(sect), precbc))) {
+ bin_section_data *bsd;
+ bsd = yasm_section_get_data(sect, &bin_section_data_cb);
+ assert(bsd != NULL);
+ yasm_intnum_calc(dist, YASM_EXPR_ADD, bsd->ivstart);
+ e->terms[i].type = YASM_EXPR_INT;
+ e->terms[i].data.intn = dist;
+ }
+
+ /* Transform our special symrecs into the appropriate value */
+ if (e->terms[i].type == YASM_EXPR_SYM &&
+ (ssymval = get_ssym_value(e->terms[i].data.sym))) {
+ e->terms[i].type = YASM_EXPR_INT;
+ e->terms[i].data.intn = yasm_intnum_copy(ssymval);
+ }
+ }
+
+ return e;
+}
+
+typedef struct map_output_info {
+ /* address width */
+ int bytes;
+
+ /* intnum output static data areas */
+ unsigned char *buf;
+ yasm_intnum *intn;
+
+ /* symrec output information */
+ unsigned long count;
+ yasm_section *section; /* NULL for EQUs */
+
+ yasm_object *object; /* object */
+ FILE *f; /* map output file */
+} map_output_info;
+
+static int
+map_prescan_bytes(yasm_section *sect, void *d)
+{
+ bin_section_data *bsd = yasm_section_get_data(sect, &bin_section_data_cb);
+ map_output_info *info = (map_output_info *)d;
+
+ assert(bsd != NULL);
+ assert(info != NULL);
+
+ while (!yasm_intnum_check_size(bsd->length, info->bytes * 8, 0, 0))
+ info->bytes *= 2;
+ while (!yasm_intnum_check_size(bsd->istart, info->bytes * 8, 0, 0))
+ info->bytes *= 2;
+ while (!yasm_intnum_check_size(bsd->ivstart, info->bytes * 8, 0, 0))
+ info->bytes *= 2;
+
+ return 0;
+}
+
+static void
+map_print_intnum(const yasm_intnum *intn, map_output_info *info)
+{
+ size_t i;
+ yasm_intnum_get_sized(intn, info->buf, info->bytes, info->bytes*8, 0, 0,
+ 0);
+ for (i=info->bytes; i != 0; i--)
+ fprintf(info->f, "%02X", info->buf[i-1]);
+}
+
+static void
+map_sections_summary(bin_groups *groups, map_output_info *info)
+{
+ bin_group *group;
+ TAILQ_FOREACH(group, groups, link) {
+ bin_section_data *bsd = group->bsd;
+
+ assert(bsd != NULL);
+ assert(info != NULL);
+
+ map_print_intnum(bsd->ivstart, info);
+ fprintf(info->f, " ");
+
+ yasm_intnum_set(info->intn, bsd->ivstart);
+ yasm_intnum_calc(info->intn, YASM_EXPR_ADD, bsd->length);
+ map_print_intnum(info->intn, info);
+ fprintf(info->f, " ");
+
+ map_print_intnum(bsd->istart, info);
+ fprintf(info->f, " ");
+
+ yasm_intnum_set(info->intn, bsd->istart);
+ yasm_intnum_calc(info->intn, YASM_EXPR_ADD, bsd->length);
+ map_print_intnum(info->intn, info);
+ fprintf(info->f, " ");
+
+ map_print_intnum(bsd->length, info);
+ fprintf(info->f, " ");
+
+ fprintf(info->f, "%-*s", 10, bsd->bss ? "nobits" : "progbits");
+ fprintf(info->f, "%s\n", yasm_section_get_name(group->section));
+
+ /* Recurse to loop through follow groups */
+ map_sections_summary(&group->follow_groups, info);
+ }
+}
+
+static void
+map_sections_detail(bin_groups *groups, map_output_info *info)
+{
+ bin_group *group;
+ TAILQ_FOREACH(group, groups, link) {
+ bin_section_data *bsd = group->bsd;
+ size_t i;
+ const char *s;
+
+ s = yasm_section_get_name(group->section);
+ fprintf(info->f, "---- Section %s ", s);
+ for (i=0; i<(65-strlen(s)); i++)
+ fputc('-', info->f);
+
+ fprintf(info->f, "\n\nclass: %s",
+ bsd->bss ? "nobits" : "progbits");
+ fprintf(info->f, "\nlength: ");
+ map_print_intnum(bsd->length, info);
+ fprintf(info->f, "\nstart: ");
+ map_print_intnum(bsd->istart, info);
+ fprintf(info->f, "\nalign: ");
+ map_print_intnum(bsd->align, info);
+ fprintf(info->f, "\nfollows: %s",
+ bsd->follows ? bsd->follows : "not defined");
+ fprintf(info->f, "\nvstart: ");
+ map_print_intnum(bsd->ivstart, info);
+ fprintf(info->f, "\nvalign: ");
+ map_print_intnum(bsd->valign, info);
+ fprintf(info->f, "\nvfollows: %s\n\n",
+ bsd->vfollows ? bsd->vfollows : "not defined");
+
+ /* Recurse to loop through follow groups */
+ map_sections_detail(&group->follow_groups, info);
+ }
+}
+
+static int
+map_symrec_count(yasm_symrec *sym, void *d)
+{
+ map_output_info *info = (map_output_info *)d;
+ /*@dependent@*/ yasm_bytecode *precbc;
+
+ assert(info != NULL);
+
+ /* TODO: autodetect wider size */
+ if (!info->section && yasm_symrec_get_equ(sym)) {
+ info->count++;
+ } else if (yasm_symrec_get_label(sym, &precbc) &&
+ yasm_bc_get_section(precbc) == info->section) {
+ info->count++;
+ }
+ return 0;
+}
+
+static int
+map_symrec_output(yasm_symrec *sym, void *d)
+{
+ map_output_info *info = (map_output_info *)d;
+ const yasm_expr *equ;
+ /*@dependent@*/ yasm_bytecode *precbc;
+ /*@only@*/ char *name = yasm_symrec_get_global_name(sym, info->object);
+
+ assert(info != NULL);
+
+ if (!info->section && (equ = yasm_symrec_get_equ(sym))) {
+ yasm_expr *realequ = yasm_expr_copy(equ);
+ realequ = yasm_expr__level_tree
+ (realequ, 1, 1, 1, 0, bin_objfmt_expr_xform, NULL);
+ yasm_intnum_set(info->intn, yasm_expr_get_intnum(&realequ, 0));
+ yasm_expr_destroy(realequ);
+ map_print_intnum(info->intn, info);
+ fprintf(info->f, " %s\n", name);
+ } else if (yasm_symrec_get_label(sym, &precbc) &&
+ yasm_bc_get_section(precbc) == info->section) {
+ bin_section_data *bsd =
+ yasm_section_get_data(info->section, &bin_section_data_cb);
+
+ /* Real address */
+ yasm_intnum_set_uint(info->intn, yasm_bc_next_offset(precbc));
+ yasm_intnum_calc(info->intn, YASM_EXPR_ADD, bsd->istart);
+ map_print_intnum(info->intn, info);
+ fprintf(info->f, " ");
+
+ /* Virtual address */
+ yasm_intnum_set_uint(info->intn, yasm_bc_next_offset(precbc));
+ yasm_intnum_calc(info->intn, YASM_EXPR_ADD, bsd->ivstart);
+ map_print_intnum(info->intn, info);
+
+ /* Name */
+ fprintf(info->f, " %s\n", name);
+ }
+ yasm_xfree(name);
+ return 0;
+}
+
+static void
+map_sections_symbols(bin_groups *groups, map_output_info *info)
+{
+ bin_group *group;
+ TAILQ_FOREACH(group, groups, link) {
+ info->count = 0;
+ info->section = group->section;
+ yasm_symtab_traverse(info->object->symtab, info, map_symrec_count);
+
+ if (info->count > 0) {
+ const char *s = yasm_section_get_name(group->section);
+ size_t i;
+ fprintf(info->f, "---- Section %s ", s);
+ for (i=0; i<(65-strlen(s)); i++)
+ fputc('-', info->f);
+ fprintf(info->f, "\n\n%-*s%-*s%s\n",
+ info->bytes*2+2, "Real",
+ info->bytes*2+2, "Virtual",
+ "Name");
+ yasm_symtab_traverse(info->object->symtab, info,
+ map_symrec_output);
+ fprintf(info->f, "\n\n");
+ }
+
+ /* Recurse to loop through follow groups */
+ map_sections_symbols(&group->follow_groups, info);
+ }
+}
+
+static void
+output_map(bin_objfmt_output_info *info)
+{
+ yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *)info->object->objfmt;
+ FILE *f;
+ int i;
+ map_output_info mapinfo;
+
+ if (objfmt_bin->map_flags == NO_MAP)
+ return;
+
+ if (objfmt_bin->map_flags == MAP_NONE)
+ objfmt_bin->map_flags = MAP_BRIEF; /* default to brief */
+
+ if (!objfmt_bin->map_filename)
+ f = stdout; /* default to stdout */
+ else {
+ f = fopen(objfmt_bin->map_filename, "wt");
+ if (!f) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("unable to open map file `%s'"),
+ objfmt_bin->map_filename);
+ yasm_errwarn_propagate(info->errwarns, 0);
+ return;
+ }
+ }
+
+ mapinfo.object = info->object;
+ mapinfo.f = f;
+
+ /* Temporary intnum */
+ mapinfo.intn = info->tmp_intn;
+
+ /* Prescan all values to figure out what width we should make the output
+ * fields. Start with a minimum of 4.
+ */
+ mapinfo.bytes = 4;
+ while (!yasm_intnum_check_size(info->origin, mapinfo.bytes * 8, 0, 0))
+ mapinfo.bytes *= 2;
+ yasm_object_sections_traverse(info->object, &mapinfo, map_prescan_bytes);
+ mapinfo.buf = yasm_xmalloc(mapinfo.bytes);
+
+ fprintf(f, "\n- YASM Map file ");
+ for (i=0; i<63; i++)
+ fputc('-', f);
+ fprintf(f, "\n\nSource file: %s\n", info->object->src_filename);
+ fprintf(f, "Output file: %s\n\n", info->object->obj_filename);
+
+ fprintf(f, "-- Program origin ");
+ for (i=0; i<61; i++)
+ fputc('-', f);
+ fprintf(f, "\n\n");
+ map_print_intnum(info->origin, &mapinfo);
+ fprintf(f, "\n\n");
+
+ if (objfmt_bin->map_flags & MAP_BRIEF) {
+ fprintf(f, "-- Sections (summary) ");
+ for (i=0; i<57; i++)
+ fputc('-', f);
+ fprintf(f, "\n\n%-*s%-*s%-*s%-*s%-*s%-*s%s\n",
+ mapinfo.bytes*2+2, "Vstart",
+ mapinfo.bytes*2+2, "Vstop",
+ mapinfo.bytes*2+2, "Start",
+ mapinfo.bytes*2+2, "Stop",
+ mapinfo.bytes*2+2, "Length",
+ 10, "Class", "Name");
+
+ map_sections_summary(&info->lma_groups, &mapinfo);
+ fprintf(f, "\n");
+ }
+
+ if (objfmt_bin->map_flags & MAP_SECTIONS) {
+ fprintf(f, "-- Sections (detailed) ");
+ for (i=0; i<56; i++)
+ fputc('-', f);
+ fprintf(f, "\n\n");
+ map_sections_detail(&info->lma_groups, &mapinfo);
+ }
+
+ if (objfmt_bin->map_flags & MAP_SYMBOLS) {
+ fprintf(f, "-- Symbols ");
+ for (i=0; i<68; i++)
+ fputc('-', f);
+ fprintf(f, "\n\n");
+
+ /* We do two passes for EQU and each section; the first pass
+ * determines the byte width to use for the value and whether any
+ * symbols are present, the second pass actually outputs the text.
+ */
+
+ /* EQUs */
+ mapinfo.count = 0;
+ mapinfo.section = NULL;
+ yasm_symtab_traverse(info->object->symtab, &mapinfo, map_symrec_count);
+
+ if (mapinfo.count > 0) {
+ fprintf(f, "---- No Section ");
+ for (i=0; i<63; i++)
+ fputc('-', f);
+ fprintf(f, "\n\n%-*s%s\n", mapinfo.bytes*2+2, "Value", "Name");
+ yasm_symtab_traverse(info->object->symtab, &mapinfo,
+ map_symrec_output);
+ fprintf(f, "\n\n");
+ }
+
+ /* Other sections */
+ map_sections_symbols(&info->lma_groups, &mapinfo);
+ }
+
+ if (f != stdout)
+ fclose(f);
+
+ yasm_xfree(mapinfo.buf);
+}
+
+/* Check for LMA overlap using a simple N^2 algorithm. */
+static int
+check_lma_overlap(yasm_section *sect, /*@null@*/ void *d)
+{
+ bin_section_data *bsd, *bsd2;
+ yasm_section *other = (yasm_section *)d;
+ yasm_intnum *overlap;
+
+ if (!d)
+ return yasm_object_sections_traverse(yasm_section_get_object(sect),
+ sect, check_lma_overlap);
+ if (sect == other)
+ return 0;
+
+ bsd = yasm_section_get_data(sect, &bin_section_data_cb);
+ bsd2 = yasm_section_get_data(other, &bin_section_data_cb);
+
+ if (yasm_intnum_is_zero(bsd->length) ||
+ yasm_intnum_is_zero(bsd2->length))
+ return 0;
+
+ if (yasm_intnum_compare(bsd->istart, bsd2->istart) <= 0) {
+ overlap = yasm_intnum_copy(bsd->istart);
+ yasm_intnum_calc(overlap, YASM_EXPR_ADD, bsd->length);
+ yasm_intnum_calc(overlap, YASM_EXPR_SUB, bsd2->istart);
+ } else {
+ overlap = yasm_intnum_copy(bsd2->istart);
+ yasm_intnum_calc(overlap, YASM_EXPR_ADD, bsd2->length);
+ yasm_intnum_calc(overlap, YASM_EXPR_SUB, bsd->istart);
+ }
+
+ if (yasm_intnum_sign(overlap) > 0) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("sections `%s' and `%s' overlap by %lu bytes"),
+ yasm_section_get_name(sect),
+ yasm_section_get_name(other),
+ yasm_intnum_get_uint(overlap));
+ yasm_intnum_destroy(overlap);
+ return -1;
+ }
+
+ yasm_intnum_destroy(overlap);
+ return 0;
+}
+
+static int
+bin_objfmt_output_value(yasm_value *value, unsigned char *buf,
+ unsigned int destsize,
+ /*@unused@*/ unsigned long offset, yasm_bytecode *bc,
+ int warn, /*@null@*/ void *d)
+{
+ /*@null@*/ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
+ /*@dependent@*/ yasm_section *sect;
+
+ assert(info != NULL);
+
+ /* Binary objects we need to resolve against object, not against section. */
+ if (value->rel) {
+ unsigned int rshift = (unsigned int)value->rshift;
+ yasm_expr *syme;
+ /*@null@*/ const yasm_intnum *ssymval;
+
+ if (yasm_symrec_is_abs(value->rel)) {
+ syme = yasm_expr_create_ident(yasm_expr_int(
+ yasm_intnum_create_uint(0)), bc->line);
+ } else if (yasm_symrec_get_label(value->rel, &precbc)
+ && (sect = yasm_bc_get_section(precbc))) {
+ syme = yasm_expr_create_ident(yasm_expr_sym(value->rel), bc->line);
+ } else if ((ssymval = get_ssym_value(value->rel))) {
+ syme = yasm_expr_create_ident(yasm_expr_int(
+ yasm_intnum_copy(ssymval)), bc->line);
+ } else
+ goto done;
+
+ /* Handle PC-relative */
+ if (value->curpos_rel) {
+ yasm_expr *sube;
+ sube = yasm_expr_create(YASM_EXPR_SUB, yasm_expr_precbc(bc),
+ yasm_expr_int(yasm_intnum_create_uint(bc->len*bc->mult_int)),
+ bc->line);
+ syme = yasm_expr_create(YASM_EXPR_SUB, yasm_expr_expr(syme),
+ yasm_expr_expr(sube), bc->line);
+ value->curpos_rel = 0;
+ value->ip_rel = 0;
+ }
+
+ if (value->rshift > 0)
+ syme = yasm_expr_create(YASM_EXPR_SHR, yasm_expr_expr(syme),
+ yasm_expr_int(yasm_intnum_create_uint(rshift)), bc->line);
+
+ /* Add into absolute portion */
+ if (!value->abs)
+ value->abs = syme;
+ else
+ value->abs =
+ yasm_expr_create(YASM_EXPR_ADD, yasm_expr_expr(value->abs),
+ yasm_expr_expr(syme), bc->line);
+ value->rel = NULL;
+ value->rshift = 0;
+ }
+done:
+ /* Simplify absolute portion of value, transforming symrecs */
+ if (value->abs)
+ value->abs = yasm_expr__level_tree
+ (value->abs, 1, 1, 1, 0, bin_objfmt_expr_xform, NULL);
+
+ /* Output */
+ switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
+ info->object->arch)) {
+ case -1:
+ return 1;
+ case 0:
+ break;
+ default:
+ return 0;
+ }
+
+ /* Couldn't output, assume it contains an external reference. */
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("binary object format does not support external references"));
+ return 1;
+}
+
+static int
+bin_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
+{
+ /*@null@*/ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
+ /*@null@*/ /*@only@*/ unsigned char *bigbuf;
+ unsigned long size = REGULAR_OUTBUF_SIZE;
+ int gap;
+
+ assert(info != NULL);
+
+ bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &gap, info,
+ bin_objfmt_output_value, NULL);
+
+ /* Don't bother doing anything else if size ended up being 0. */
+ if (size == 0) {
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+ return 0;
+ }
+
+ /* Warn that gaps are converted to 0 and write out the 0's. */
+ if (gap) {
+ unsigned long left;
+ yasm_warn_set(YASM_WARN_UNINIT_CONTENTS,
+ N_("uninitialized space declared in code/data section: zeroing"));
+ /* Write out in chunks */
+ memset(info->buf, 0, REGULAR_OUTBUF_SIZE);
+ left = size;
+ while (left > REGULAR_OUTBUF_SIZE) {
+ fwrite(info->buf, REGULAR_OUTBUF_SIZE, 1, info->f);
+ left -= REGULAR_OUTBUF_SIZE;
+ }
+ fwrite(info->buf, left, 1, info->f);
+ } else {
+ /* Output buf (or bigbuf if non-NULL) to file */
+ fwrite(bigbuf ? bigbuf : info->buf, (size_t)size, 1, info->f);
+ }
+
+ /* If bigbuf was allocated, free it */
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+
+ return 0;
+}
+
+/* Check to ensure bytecode is res* (for BSS sections) */
+static int
+bin_objfmt_no_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
+{
+ /*@null@*/ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
+ /*@null@*/ /*@only@*/ unsigned char *bigbuf;
+ unsigned long size = REGULAR_OUTBUF_SIZE;
+ int gap;
+
+ assert(info != NULL);
+
+ bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &gap, info,
+ bin_objfmt_output_value, NULL);
+
+ /* If bigbuf was allocated, free it */
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+
+ /* Don't bother doing anything else if size ended up being 0. */
+ if (size == 0)
+ return 0;
+
+ /* Warn if not a gap. */
+ if (!gap) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("initialized space declared in nobits section: ignoring"));
+ }
+
+ return 0;
+}
+
+static int
+bin_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d)
+{
+ bin_section_data *bsd = yasm_section_get_data(sect, &bin_section_data_cb);
+ /*@null@*/ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
+
+ assert(bsd != NULL);
+ assert(info != NULL);
+
+ if (bsd->bss) {
+ yasm_section_bcs_traverse(sect, info->errwarns,
+ info, bin_objfmt_no_output_bytecode);
+ } else {
+ yasm_intnum_set(info->tmp_intn, bsd->istart);
+ yasm_intnum_calc(info->tmp_intn, YASM_EXPR_SUB, info->origin);
+ if (yasm_intnum_sign(info->tmp_intn) < 0) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("section `%s' starts before origin (ORG)"),
+ yasm_section_get_name(sect));
+ yasm_errwarn_propagate(info->errwarns, 0);
+ return 0;
+ }
+ if (!yasm_intnum_check_size(info->tmp_intn, sizeof(long)*8, 0, 1)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("section `%s' start value too large"),
+ yasm_section_get_name(sect));
+ yasm_errwarn_propagate(info->errwarns, 0);
+ return 0;
+ }
+ if (fseek(info->f, yasm_intnum_get_int(info->tmp_intn) + info->start,
+ SEEK_SET) < 0)
+ yasm__fatal(N_("could not seek on output file"));
+ yasm_section_bcs_traverse(sect, info->errwarns,
+ info, bin_objfmt_output_bytecode);
+ }
+
+ return 0;
+}
+
+static void
+bin_objfmt_cleanup(bin_objfmt_output_info *info)
+{
+ bin_group *group, *group_temp;
+
+ yasm_xfree(info->buf);
+ yasm_intnum_destroy(info->origin);
+ yasm_intnum_destroy(info->tmp_intn);
+
+ TAILQ_FOREACH_SAFE(group, &info->lma_groups, link, group_temp)
+ bin_group_destroy(group);
+
+ TAILQ_FOREACH_SAFE(group, &info->vma_groups, link, group_temp)
+ bin_group_destroy(group);
+}
+
+static void
+bin_objfmt_output(yasm_object *object, FILE *f, /*@unused@*/ int all_syms,
+ yasm_errwarns *errwarns)
+{
+ yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *)object->objfmt;
+ bin_objfmt_output_info info;
+ bin_group *group, *lma_group, *vma_group, *group_temp;
+ yasm_intnum *start, *last, *vdelta;
+ bin_groups unsorted_groups, bss_groups;
+
+ info.start = ftell(f);
+
+ /* Set ORG to 0 unless otherwise specified */
+ if (objfmt_bin->org) {
+ info.origin = yasm_expr_get_intnum(&objfmt_bin->org, 0);
+ if (!info.origin) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("ORG expression is too complex"));
+ yasm_errwarn_propagate(errwarns, objfmt_bin->org->line);
+ return;
+ }
+ if (yasm_intnum_sign(info.origin) < 0) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("ORG expression is negative"));
+ yasm_errwarn_propagate(errwarns, objfmt_bin->org->line);
+ return;
+ }
+ info.origin = yasm_intnum_copy(info.origin);
+ } else
+ info.origin = yasm_intnum_create_uint(0);
+
+ info.object = object;
+ info.errwarns = errwarns;
+ info.f = f;
+ info.buf = yasm_xmalloc(REGULAR_OUTBUF_SIZE);
+ info.tmp_intn = yasm_intnum_create_uint(0);
+ TAILQ_INIT(&info.lma_groups);
+ TAILQ_INIT(&info.vma_groups);
+
+ /* Check symbol table */
+ yasm_symtab_traverse(object->symtab, &info, bin_objfmt_check_sym);
+
+ /* Create section groups */
+ if (yasm_object_sections_traverse(object, &info, bin_lma_create_group)) {
+ bin_objfmt_cleanup(&info);
+ return; /* error detected */
+ }
+
+ /* Determine section order according to LMA.
+ * Sections can be ordered either by (priority):
+ * - follows
+ * - start
+ * - progbits/nobits setting
+ * - order in the input file
+ */
+
+ /* Look at each group with follows specified, and find the section
+ * that group is supposed to follow.
+ */
+ TAILQ_FOREACH_SAFE(lma_group, &info.lma_groups, link, group_temp) {
+ if (lma_group->bsd->follows) {
+ bin_group *found;
+ /* Need to find group containing section this section follows. */
+ found =
+ find_group_by_name(&info.lma_groups, lma_group->bsd->follows);
+ if (!found) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("section `%s' follows an invalid or unknown section `%s'"),
+ yasm_section_get_name(lma_group->section),
+ lma_group->bsd->follows);
+ yasm_errwarn_propagate(errwarns, 0);
+ bin_objfmt_cleanup(&info);
+ return;
+ }
+
+ /* Check for loops */
+ if (lma_group->section == found->section ||
+ find_group_by_section(&lma_group->follow_groups,
+ found->section)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("follows loop between section `%s' and section `%s'"),
+ yasm_section_get_name(lma_group->section),
+ yasm_section_get_name(found->section));
+ yasm_errwarn_propagate(errwarns, 0);
+ bin_objfmt_cleanup(&info);
+ return;
+ }
+
+ /* Remove this section from main lma groups list */
+ TAILQ_REMOVE(&info.lma_groups, lma_group, link);
+ /* Add it after the section it's supposed to follow. */
+ TAILQ_INSERT_TAIL(&found->follow_groups, lma_group, link);
+ }
+ }
+
+ /* Sort the top-level groups according to their start address.
+ * Use Shell sort for ease of implementation.
+ * If no start address is specified for a section, don't change the order,
+ * and move BSS sections to a separate list so they can be moved to the
+ * end of the lma list after all other sections are sorted.
+ */
+ unsorted_groups = info.lma_groups; /* structure copy */
+ TAILQ_INIT(&info.lma_groups);
+ TAILQ_INIT(&bss_groups);
+ TAILQ_FOREACH_SAFE(lma_group, &unsorted_groups, link, group_temp) {
+ bin_group *before;
+
+ if (!lma_group->bsd->istart) {
+ if (lma_group->bsd->bss)
+ TAILQ_INSERT_TAIL(&bss_groups, lma_group, link);
+ else
+ TAILQ_INSERT_TAIL(&info.lma_groups, lma_group, link);
+ continue;
+ }
+
+ before = NULL;
+ TAILQ_FOREACH(group, &info.lma_groups, link) {
+ if (!group->bsd->istart)
+ continue;
+ if (yasm_intnum_compare(group->bsd->istart,
+ lma_group->bsd->istart) > 0) {
+ before = group;
+ break;
+ }
+ }
+ if (before)
+ TAILQ_INSERT_BEFORE(before, lma_group, link);
+ else
+ TAILQ_INSERT_TAIL(&info.lma_groups, lma_group, link);
+ }
+
+ /* Move the pure-BSS sections to the end of the LMA list. */
+ TAILQ_FOREACH_SAFE(group, &bss_groups, link, group_temp)
+ TAILQ_INSERT_TAIL(&info.lma_groups, group, link);
+ TAILQ_INIT(&bss_groups); /* For sanity */
+
+ /* Assign a LMA start address to every section.
+ * Also assign VMA=LMA unless otherwise specified.
+ *
+ * We need to assign VMA=LMA here (while walking the tree) for the case:
+ * sect1 start=0 (size=0x11)
+ * sect2 follows=sect1 valign=16 (size=0x104)
+ * sect3 follows=sect2 valign=16
+ * Where the valign of sect2 will result in a sect3 vaddr higher than a
+ * naive segment-by-segment interpretation (where sect3 and sect2 would
+ * have a VMA overlap).
+ *
+ * Algorithm for VMA=LMA setting:
+ * Start with delta=0.
+ * If there's no virtual attributes, we simply set VMA = LMA+delta.
+ * If there's only valign specified, we set VMA = aligned LMA, and add
+ * any new alignment difference to delta.
+ *
+ * We could do the LMA start and VMA=LMA steps in two separate steps,
+ * but it's easier to just recurse once.
+ */
+ start = yasm_intnum_copy(info.origin);
+ last = yasm_intnum_copy(info.origin);
+ vdelta = yasm_intnum_create_uint(0);
+ TAILQ_FOREACH(lma_group, &info.lma_groups, link) {
+ if (lma_group->bsd->istart)
+ yasm_intnum_set(start, lma_group->bsd->istart);
+ group_assign_start_recurse(lma_group, start, last, vdelta,
+ info.tmp_intn, errwarns);
+ yasm_intnum_set(start, last);
+ }
+ yasm_intnum_destroy(last);
+ yasm_intnum_destroy(vdelta);
+
+ /*
+ * Determine section order according to VMA
+ */
+
+ /* Create section groups */
+ if (yasm_object_sections_traverse(object, &info, bin_vma_create_group)) {
+ yasm_intnum_destroy(start);
+ bin_objfmt_cleanup(&info);
+ return; /* error detected */
+ }
+
+ /* Look at each group with vfollows specified, and find the section
+ * that group is supposed to follow.
+ */
+ TAILQ_FOREACH_SAFE(vma_group, &info.vma_groups, link, group_temp) {
+ if (vma_group->bsd->vfollows) {
+ bin_group *found;
+ /* Need to find group containing section this section follows. */
+ found = find_group_by_name(&info.vma_groups,
+ vma_group->bsd->vfollows);
+ if (!found) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("section `%s' vfollows an invalid or unknown section `%s'"),
+ yasm_section_get_name(vma_group->section),
+ vma_group->bsd->vfollows);
+ yasm_errwarn_propagate(errwarns, 0);
+ yasm_intnum_destroy(start);
+ bin_objfmt_cleanup(&info);
+ return;
+ }
+
+ /* Check for loops */
+ if (vma_group->section == found->section ||
+ find_group_by_section(&vma_group->follow_groups,
+ found->section)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("vfollows loop between section `%s' and section `%s'"),
+ yasm_section_get_name(vma_group->section),
+ yasm_section_get_name(found->section));
+ yasm_errwarn_propagate(errwarns, 0);
+ bin_objfmt_cleanup(&info);
+ return;
+ }
+
+ /* Remove this section from main lma groups list */
+ TAILQ_REMOVE(&info.vma_groups, vma_group, link);
+ /* Add it after the section it's supposed to follow. */
+ TAILQ_INSERT_TAIL(&found->follow_groups, vma_group, link);
+ }
+ }
+
+ /* Due to the combination of steps above, we now know that all top-level
+ * groups have integer ivstart:
+ * Vstart Vfollows Valign Handled by
+ * No No No group_assign_start_recurse()
+ * No No Yes group_assign_start_recurse()
+ * No Yes - vfollows loop (above)
+ * Yes - - bin_lma_create_group()
+ */
+ TAILQ_FOREACH(vma_group, &info.vma_groups, link) {
+ yasm_intnum_set(start, vma_group->bsd->ivstart);
+ group_assign_vstart_recurse(vma_group, start, errwarns);
+ }
+
+ /* Output map file */
+ output_map(&info);
+
+ /* Ensure we don't have overlapping progbits LMAs.
+ * Use a dumb O(N^2) algorithm as the number of sections is essentially
+ * always low.
+ */
+ if (yasm_object_sections_traverse(object, NULL, check_lma_overlap)) {
+ yasm_errwarn_propagate(errwarns, 0);
+ yasm_intnum_destroy(start);
+ bin_objfmt_cleanup(&info);
+ return;
+ }
+
+ /* Output sections */
+ yasm_object_sections_traverse(object, &info, bin_objfmt_output_section);
+
+ /* Clean up */
+ yasm_intnum_destroy(start);
+ bin_objfmt_cleanup(&info);
+}
+
+static void
+bin_objfmt_destroy(yasm_objfmt *objfmt)
+{
+ yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *)objfmt;
+ if (objfmt_bin->map_filename)
+ yasm_xfree(objfmt_bin->map_filename);
+ yasm_expr_destroy(objfmt_bin->org);
+ yasm_xfree(objfmt);
+}
+
+static void
+define_section_symbol(yasm_symtab *symtab, yasm_section *sect,
+ const char *sectname, const char *suffix,
+ enum bin_ssym which, unsigned long line)
+{
+ yasm_symrec *sym;
+ bin_symrec_data *bsymd = yasm_xmalloc(sizeof(bin_symrec_data));
+ char *symname = yasm_xmalloc(8+strlen(sectname)+strlen(suffix)+1);
+
+ strcpy(symname, "section.");
+ strcat(symname, sectname);
+ strcat(symname, suffix);
+
+ bsymd->section = sect;
+ bsymd->which = which;
+
+ sym = yasm_symtab_declare(symtab, symname, YASM_SYM_EXTERN, line);
+ yasm_xfree(symname);
+ yasm_symrec_add_data(sym, &bin_symrec_data_cb, bsymd);
+}
+
+static void
+bin_objfmt_init_new_section(yasm_section *sect, unsigned long line)
+{
+ yasm_object *object = yasm_section_get_object(sect);
+ const char *sectname = yasm_section_get_name(sect);
+ /*yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *)object->objfmt;*/
+ bin_section_data *data;
+
+ data = yasm_xmalloc(sizeof(bin_section_data));
+ data->bss = 0;
+ data->align = NULL;
+ data->valign = NULL;
+ data->start = NULL;
+ data->vstart = NULL;
+ data->follows = NULL;
+ data->vfollows = NULL;
+ data->istart = NULL;
+ data->ivstart = NULL;
+ data->length = NULL;
+ yasm_section_add_data(sect, &bin_section_data_cb, data);
+
+ define_section_symbol(object->symtab, sect, sectname, ".start",
+ SSYM_START, line);
+ define_section_symbol(object->symtab, sect, sectname, ".vstart",
+ SSYM_VSTART, line);
+ define_section_symbol(object->symtab, sect, sectname, ".length",
+ SSYM_LENGTH, line);
+}
+
+static yasm_section *
+bin_objfmt_add_default_section(yasm_object *object)
+{
+ yasm_section *retval;
+ int isnew;
+
+ retval = yasm_object_get_general(object, ".text", 0, 1, 0, &isnew, 0);
+ if (isnew)
+ yasm_section_set_default(retval, 1);
+ return retval;
+}
+
+/* GAS-style flags */
+static int
+bin_helper_gasflags(void *obj, yasm_valparam *vp, unsigned long line, void *d,
+ /*@unused@*/ uintptr_t arg)
+{
+ /* TODO */
+ return 0;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_section *
+bin_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
+ /*@unused@*/ /*@null@*/
+ yasm_valparamhead *objext_valparams,
+ unsigned long line)
+{
+ yasm_valparam *vp;
+ yasm_section *retval;
+ int isnew;
+ int flags_override = 0;
+ const char *sectname;
+ bin_section_data *bsd = NULL;
+
+ struct bin_section_switch_data {
+ /*@only@*/ /*@null@*/ char *follows;
+ /*@only@*/ /*@null@*/ char *vfollows;
+ /*@only@*/ /*@null@*/ yasm_expr *start;
+ /*@only@*/ /*@null@*/ yasm_expr *vstart;
+ /*@only@*/ /*@null@*/ yasm_intnum *align;
+ /*@only@*/ /*@null@*/ yasm_intnum *valign;
+ unsigned long bss;
+ unsigned long code;
+ } data;
+
+ static const yasm_dir_help help[] = {
+ { "follows", 1, yasm_dir_helper_string,
+ offsetof(struct bin_section_switch_data, follows), 0 },
+ { "vfollows", 1, yasm_dir_helper_string,
+ offsetof(struct bin_section_switch_data, vfollows), 0 },
+ { "start", 1, yasm_dir_helper_expr,
+ offsetof(struct bin_section_switch_data, start), 0 },
+ { "vstart", 1, yasm_dir_helper_expr,
+ offsetof(struct bin_section_switch_data, vstart), 0 },
+ { "align", 1, yasm_dir_helper_intn,
+ offsetof(struct bin_section_switch_data, align), 0 },
+ { "valign", 1, yasm_dir_helper_intn,
+ offsetof(struct bin_section_switch_data, valign), 0 },
+ { "nobits", 0, yasm_dir_helper_flag_set,
+ offsetof(struct bin_section_switch_data, bss), 1 },
+ { "progbits", 0, yasm_dir_helper_flag_set,
+ offsetof(struct bin_section_switch_data, bss), 0 },
+ { "code", 0, yasm_dir_helper_flag_set,
+ offsetof(struct bin_section_switch_data, code), 1 },
+ { "data", 0, yasm_dir_helper_flag_set,
+ offsetof(struct bin_section_switch_data, code), 0 },
+ { "execute", 0, yasm_dir_helper_flag_set,
+ offsetof(struct bin_section_switch_data, code), 1 },
+ { "noexecute", 0, yasm_dir_helper_flag_set,
+ offsetof(struct bin_section_switch_data, code), 0 },
+ { "gasflags", 1, bin_helper_gasflags, 0, 0 }
+ };
+
+ vp = yasm_vps_first(valparams);
+ sectname = yasm_vp_string(vp);
+ if (!sectname)
+ return NULL;
+ vp = yasm_vps_next(vp);
+
+ retval = yasm_object_find_general(object, sectname);
+ if (retval) {
+ bsd = yasm_section_get_data(retval, &bin_section_data_cb);
+ assert(bsd != NULL);
+ data.follows = bsd->follows;
+ data.vfollows = bsd->vfollows;
+ data.start = bsd->start;
+ data.vstart = bsd->vstart;
+ data.align = NULL;
+ data.valign = NULL;
+ data.bss = bsd->bss;
+ data.code = yasm_section_is_code(retval);
+ } else {
+ data.follows = NULL;
+ data.vfollows = NULL;
+ data.start = NULL;
+ data.vstart = NULL;
+ data.align = NULL;
+ data.valign = NULL;
+ data.bss = strcmp(sectname, ".bss") == 0;
+ data.code = strcmp(sectname, ".text") == 0;
+ }
+
+ flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help),
+ &data, yasm_dir_helper_valparam_warn);
+ if (flags_override < 0)
+ return NULL; /* error occurred */
+
+ if (data.start && data.follows) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("cannot combine `start' and `follows' section attributes"));
+ return NULL;
+ }
+
+ if (data.vstart && data.vfollows) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("cannot combine `vstart' and `vfollows' section attributes"));
+ return NULL;
+ }
+
+ if (data.align) {
+ unsigned long align = yasm_intnum_get_uint(data.align);
+
+ /* Alignments must be a power of two. */
+ if (!is_exp2(align)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("argument to `%s' is not a power of two"),
+ "align");
+ return NULL;
+ }
+ } else
+ data.align = bsd ? bsd->align : NULL;
+
+ if (data.valign) {
+ unsigned long valign = yasm_intnum_get_uint(data.valign);
+
+ /* Alignments must be a power of two. */
+ if (!is_exp2(valign)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("argument to `%s' is not a power of two"),
+ "valign");
+ return NULL;
+ }
+ } else
+ data.valign = bsd ? bsd->valign : NULL;
+
+ retval = yasm_object_get_general(object, sectname, 0, (int)data.code,
+ (int)data.bss, &isnew, line);
+
+ bsd = yasm_section_get_data(retval, &bin_section_data_cb);
+
+ if (isnew || yasm_section_is_default(retval)) {
+ yasm_section_set_default(retval, 0);
+ }
+
+ /* Update section flags */
+ bsd->bss = data.bss;
+ bsd->align = data.align;
+ bsd->valign = data.valign;
+ bsd->start = data.start;
+ bsd->vstart = data.vstart;
+ bsd->follows = data.follows;
+ bsd->vfollows = data.vfollows;
+
+ return retval;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+bin_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ return NULL;
+}
+
+static void
+bin_objfmt_dir_org(yasm_object *object,
+ /*@null@*/ yasm_valparamhead *valparams,
+ /*@unused@*/ /*@null@*/
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *)object->objfmt;
+ yasm_valparam *vp;
+
+ /* We only allow a single ORG in a program. */
+ if (objfmt_bin->org) {
+ yasm_error_set(YASM_ERROR_GENERAL, N_("program origin redefined"));
+ return;
+ }
+
+ /* ORG takes just a simple expression as param */
+ vp = yasm_vps_first(valparams);
+ objfmt_bin->org = yasm_vp_expr(vp, object->symtab, line);
+ if (!objfmt_bin->org) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("argument to ORG must be expression"));
+ return;
+ }
+}
+
+struct bin_dir_map_data {
+ unsigned long flags;
+ /*@only@*/ /*@null@*/ char *filename;
+};
+
+static int
+dir_map_filename(void *obj, yasm_valparam *vp, unsigned long line, void *data)
+{
+ struct bin_dir_map_data *mdata = (struct bin_dir_map_data *)data;
+ const char *filename;
+
+ if (mdata->filename) {
+ yasm_warn_set(YASM_WARN_GENERAL, N_("map file already specified"));
+ return 0;
+ }
+
+ filename = yasm_vp_string(vp);
+ if (!filename) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("unexpected expression in [map]"));
+ return -1;
+ }
+ mdata->filename = yasm__xstrdup(filename);
+
+ return 1;
+}
+
+static void
+bin_objfmt_dir_map(yasm_object *object,
+ /*@null@*/ yasm_valparamhead *valparams,
+ /*@unused@*/ /*@null@*/
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *)object->objfmt;
+
+ struct bin_dir_map_data data;
+
+ static const yasm_dir_help help[] = {
+ { "all", 0, yasm_dir_helper_flag_or,
+ offsetof(struct bin_dir_map_data, flags),
+ MAP_BRIEF|MAP_SECTIONS|MAP_SYMBOLS },
+ { "brief", 0, yasm_dir_helper_flag_or,
+ offsetof(struct bin_dir_map_data, flags), MAP_BRIEF },
+ { "sections", 0, yasm_dir_helper_flag_or,
+ offsetof(struct bin_dir_map_data, flags), MAP_SECTIONS },
+ { "segments", 0, yasm_dir_helper_flag_or,
+ offsetof(struct bin_dir_map_data, flags), MAP_SECTIONS },
+ { "symbols", 0, yasm_dir_helper_flag_or,
+ offsetof(struct bin_dir_map_data, flags), MAP_SYMBOLS }
+ };
+
+ data.flags = objfmt_bin->map_flags | MAP_NONE;
+ data.filename = objfmt_bin->map_filename;
+
+ if (valparams && yasm_dir_helper(object, yasm_vps_first(valparams), line, help,
+ NELEMS(help), &data, dir_map_filename) < 0)
+ return; /* error occurred */
+
+ objfmt_bin->map_flags = data.flags;
+ objfmt_bin->map_filename = data.filename;
+}
+
+static void
+bin_section_data_destroy(void *data)
+{
+ bin_section_data *bsd = (bin_section_data *)data;
+ if (bsd->start)
+ yasm_expr_destroy(bsd->start);
+ if (bsd->vstart)
+ yasm_expr_destroy(bsd->vstart);
+ if (bsd->follows)
+ yasm_xfree(bsd->follows);
+ if (bsd->vfollows)
+ yasm_xfree(bsd->vfollows);
+ if (bsd->istart)
+ yasm_intnum_destroy(bsd->istart);
+ if (bsd->ivstart)
+ yasm_intnum_destroy(bsd->ivstart);
+ if (bsd->length)
+ yasm_intnum_destroy(bsd->length);
+ yasm_xfree(data);
+}
+
+static void
+bin_section_data_print(void *data, FILE *f, int indent_level)
+{
+ bin_section_data *bsd = (bin_section_data *)data;
+
+ fprintf(f, "%*sbss=%d\n", indent_level, "", bsd->bss);
+
+ fprintf(f, "%*salign=", indent_level, "");
+ if (bsd->align)
+ yasm_intnum_print(bsd->align, f);
+ else
+ fprintf(f, "(nil)");
+ fprintf(f, "\n%*svalign=", indent_level, "");
+ if (bsd->valign)
+ yasm_intnum_print(bsd->valign, f);
+ else
+ fprintf(f, "(nil)");
+
+ fprintf(f, "\n%*sstart=", indent_level, "");
+ yasm_expr_print(bsd->start, f);
+ fprintf(f, "\n%*svstart=", indent_level, "");
+ yasm_expr_print(bsd->vstart, f);
+
+ fprintf(f, "\n%*sfollows=", indent_level, "");
+ if (bsd->follows)
+ fprintf(f, "\"%s\"", bsd->follows);
+ else
+ fprintf(f, "(nil)");
+ fprintf(f, "\n%*svfollows=", indent_level, "");
+ if (bsd->vfollows)
+ fprintf(f, "\"%s\"", bsd->vfollows);
+ else
+ fprintf(f, "(nil)");
+
+ fprintf(f, "\n%*sistart=", indent_level, "");
+ if (bsd->istart)
+ yasm_intnum_print(bsd->istart, f);
+ else
+ fprintf(f, "(nil)");
+ fprintf(f, "\n%*sivstart=", indent_level, "");
+ if (bsd->ivstart)
+ yasm_intnum_print(bsd->ivstart, f);
+ else
+ fprintf(f, "(nil)");
+
+ fprintf(f, "\n%*slength=", indent_level, "");
+ if (bsd->length)
+ yasm_intnum_print(bsd->length, f);
+ else
+ fprintf(f, "(nil)");
+ fprintf(f, "\n");
+}
+
+static void
+bin_symrec_data_destroy(void *data)
+{
+ yasm_xfree(data);
+}
+
+static void
+bin_symrec_data_print(void *data, FILE *f, int indent_level)
+{
+ bin_symrec_data *bsymd = (bin_symrec_data *)data;
+
+ fprintf(f, "%*ssection=\"%s\"\n", indent_level, "",
+ yasm_section_get_name(bsymd->section));
+ fprintf(f, "%*swhich=", indent_level, "");
+ switch (bsymd->which) {
+ case SSYM_START: fprintf(f, "START"); break;
+ case SSYM_VSTART: fprintf(f, "VSTART"); break;
+ case SSYM_LENGTH: fprintf(f, "LENGTH"); break;
+ }
+ fprintf(f, "\n");
+}
+
+
+/* Define valid debug formats to use with this object format */
+static const char *bin_objfmt_dbgfmt_keywords[] = {
+ "null",
+ NULL
+};
+
+static const yasm_directive bin_objfmt_directives[] = {
+ { "org", "nasm", bin_objfmt_dir_org, YASM_DIR_ARG_REQUIRED },
+ { "map", "nasm", bin_objfmt_dir_map, YASM_DIR_ANY },
+ { NULL, NULL, NULL, 0 }
+};
+
+static const char *bin_nasm_stdmac[] = {
+ "%imacro org 1+.nolist",
+ "[org %1]",
+ "%endmacro",
+ NULL
+};
+
+static const yasm_stdmac bin_objfmt_stdmacs[] = {
+ { "nasm", "nasm", bin_nasm_stdmac },
+ { "tasm", "tasm", bin_nasm_stdmac },
+ { NULL, NULL, NULL }
+};
+
+/* Define objfmt structure -- see objfmt.h for details */
+yasm_objfmt_module yasm_bin_LTX_objfmt = {
+ "Flat format binary",
+ "bin",
+ NULL,
+ 16,
+ 0,
+ bin_objfmt_dbgfmt_keywords,
+ "null",
+ bin_objfmt_directives,
+ bin_objfmt_stdmacs,
+ bin_objfmt_create,
+ bin_objfmt_output,
+ bin_objfmt_destroy,
+ bin_objfmt_add_default_section,
+ bin_objfmt_init_new_section,
+ bin_objfmt_section_switch,
+ bin_objfmt_get_special_sym
+};
+
+#define EXE_HEADER_SIZE 0x200
+
+/* DOS .EXE binaries are just raw binaries with a header */
+yasm_objfmt_module yasm_dosexe_LTX_objfmt;
+
+static yasm_objfmt *
+dosexe_objfmt_create(yasm_object *object)
+{
+ yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *) bin_objfmt_create(object);
+ objfmt_bin->objfmt.module = &yasm_dosexe_LTX_objfmt;
+ return (yasm_objfmt *)objfmt_bin;
+}
+
+static unsigned long
+get_sym(yasm_object *object, const char *name) {
+ yasm_symrec *symrec = yasm_symtab_get(object->symtab, name);
+ yasm_bytecode *prevbc;
+ if (!symrec)
+ return 0;
+ if (!yasm_symrec_get_label(symrec, &prevbc))
+ return 0;
+ return prevbc->offset + prevbc->len;
+}
+
+static void
+dosexe_objfmt_output(yasm_object *object, FILE *f, /*@unused@*/ int all_syms,
+ yasm_errwarns *errwarns)
+{
+ unsigned long tot_size, size, bss_size;
+ unsigned long start, bss;
+ unsigned char c;
+
+ fseek(f, EXE_HEADER_SIZE, SEEK_SET);
+
+ bin_objfmt_output(object, f, all_syms, errwarns);
+
+ tot_size = ftell(f);
+
+ /* if there is a __bss_start symbol, data after it is 0, no need to write
+ * it. */
+ bss = get_sym(object, "__bss_start");
+ if (bss)
+ size = bss;
+ else
+ size = tot_size;
+ bss_size = tot_size - size;
+#ifdef HAVE_FTRUNCATE
+ if (size != tot_size)
+ ftruncate(fileno(f), EXE_HEADER_SIZE + size);
+#endif
+ fseek(f, 0, SEEK_SET);
+
+ /* magic */
+ fwrite("MZ", 1, 2, f);
+
+ /* file size */
+ c = size & 0xff;
+ fwrite(&c, 1, 1, f);
+ c = !!(size & 0x100);
+ fwrite(&c, 1, 1, f);
+ c = ((size + 511) >> 9) & 0xff;
+ fwrite(&c, 1, 1, f);
+ c = ((size + 511) >> 17) & 0xff;
+ fwrite(&c, 1, 1, f);
+
+ /* relocation # */
+ c = 0;
+ fwrite(&c, 1, 1, f);
+ fwrite(&c, 1, 1, f);
+
+ /* header size */
+ c = EXE_HEADER_SIZE / 16;
+ fwrite(&c, 1, 1, f);
+ c = 0;
+ fwrite(&c, 1, 1, f);
+
+ /* minimum paragraph # */
+ bss_size = (bss_size + 15) >> 4;
+ c = bss_size & 0xff;
+ fwrite(&c, 1, 1, f);
+ c = (bss_size >> 8) & 0xff;
+ fwrite(&c, 1, 1, f);
+
+ /* maximum paragraph # */
+ c = 0xFF;
+ fwrite(&c, 1, 1, f);
+ fwrite(&c, 1, 1, f);
+
+ /* relative value of stack segment */
+ c = 0;
+ fwrite(&c, 1, 1, f);
+ fwrite(&c, 1, 1, f);
+
+ /* SP at start */
+ c = 0;
+ fwrite(&c, 1, 1, f);
+ fwrite(&c, 1, 1, f);
+
+ /* header checksum */
+ c = 0;
+ fwrite(&c, 1, 1, f);
+ fwrite(&c, 1, 1, f);
+
+ /* IP at start */
+ start = get_sym(object, "start");
+ if (!start) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("%s: could not find symbol `start'"));
+ return;
+ }
+ c = start & 0xff;
+ fwrite(&c, 1, 1, f);
+ c = (start >> 8) & 0xff;
+ fwrite(&c, 1, 1, f);
+
+ /* CS start */
+ c = 0;
+ fwrite(&c, 1, 1, f);
+ fwrite(&c, 1, 1, f);
+
+ /* reloc start */
+ c = 0x22;
+ fwrite(&c, 1, 1, f);
+ c = 0;
+ fwrite(&c, 1, 1, f);
+
+ /* Overlay number */
+ c = 0;
+ fwrite(&c, 1, 1, f);
+ fwrite(&c, 1, 1, f);
+}
+
+
+/* Define objfmt structure -- see objfmt.h for details */
+yasm_objfmt_module yasm_dosexe_LTX_objfmt = {
+ "DOS .EXE format binary",
+ "dosexe",
+ "exe",
+ 16,
+ 0,
+ bin_objfmt_dbgfmt_keywords,
+ "null",
+ bin_objfmt_directives,
+ bin_objfmt_stdmacs,
+ dosexe_objfmt_create,
+ dosexe_objfmt_output,
+ bin_objfmt_destroy,
+ bin_objfmt_add_default_section,
+ bin_objfmt_init_new_section,
+ bin_objfmt_section_switch,
+ bin_objfmt_get_special_sym
+};
diff --git a/contrib/tools/yasm/modules/objfmts/coff/coff-objfmt.c b/contrib/tools/yasm/modules/objfmts/coff/coff-objfmt.c
new file mode 100644
index 0000000000..388b09af32
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/coff/coff-objfmt.c
@@ -0,0 +1,2522 @@
+/*
+ * COFF (DJGPP) object format
+ *
+ * Copyright (C) 2002-2007 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 <util.h>
+#include <time.h>
+
+#include <libyasm.h>
+
+#include "coff-objfmt.h"
+
+
+#define REGULAR_OUTBUF_SIZE 1024
+
+/* Defining this to 0 sets all section VMA's to 0 rather than as the same as
+ * the LMA. According to the DJGPP COFF Spec, this should be set to 1
+ * (VMA=LMA), and indeed DJGPP's GCC output shows VMA=LMA. However, NASM
+ * outputs VMA=0 (as if this was 0), and GNU objdump output looks a lot nicer
+ * with VMA=0. Who's right? This is #defined as changing this setting affects
+ * several places in the code.
+ */
+#define COFF_SET_VMA (!objfmt_coff->win32)
+
+#define COFF_MACHINE_I386 0x014C
+#define COFF_MACHINE_AMD64 0x8664
+
+#define COFF_F_LNNO 0x0004 /* line number info NOT present */
+#define COFF_F_LSYMS 0x0008 /* local symbols NOT present */
+#define COFF_F_AR32WR 0x0100 /* 32-bit little endian file */
+
+typedef struct coff_reloc {
+ yasm_reloc reloc;
+ enum {
+ COFF_RELOC_ABSOLUTE = 0, /* absolute, no reloc needed */
+
+ /* I386 relocations */
+ COFF_RELOC_I386_ADDR16 = 0x1, /* 16-bit absolute reference */
+ COFF_RELOC_I386_REL16 = 0x2, /* 16-bit PC-relative reference */
+ COFF_RELOC_I386_ADDR32 = 0x6, /* 32-bit absolute reference */
+ COFF_RELOC_I386_ADDR32NB = 0x7, /* 32-bit absolute ref w/o base */
+ COFF_RELOC_I386_SEG12 = 0x9, /* 16-bit absolute segment ref */
+ COFF_RELOC_I386_SECTION = 0xA, /* section index */
+ COFF_RELOC_I386_SECREL = 0xB, /* offset from start of segment */
+ COFF_RELOC_I386_TOKEN = 0xC, /* CLR metadata token */
+ COFF_RELOC_I386_SECREL7 = 0xD, /* 7-bit offset from base of sect */
+ COFF_RELOC_I386_REL32 = 0x14, /* 32-bit PC-relative reference */
+
+ /* AMD64 relocations */
+ COFF_RELOC_AMD64_ADDR64 = 0x1, /* 64-bit address (VA) */
+ COFF_RELOC_AMD64_ADDR32 = 0x2, /* 32-bit address (VA) */
+ COFF_RELOC_AMD64_ADDR32NB = 0x3, /* 32-bit address w/o base (RVA) */
+ COFF_RELOC_AMD64_REL32 = 0x4, /* 32-bit relative (0 byte dist) */
+ COFF_RELOC_AMD64_REL32_1 = 0x5, /* 32-bit relative (1 byte dist) */
+ COFF_RELOC_AMD64_REL32_2 = 0x6, /* 32-bit relative (2 byte dist) */
+ COFF_RELOC_AMD64_REL32_3 = 0x7, /* 32-bit relative (3 byte dist) */
+ COFF_RELOC_AMD64_REL32_4 = 0x8, /* 32-bit relative (4 byte dist) */
+ COFF_RELOC_AMD64_REL32_5 = 0x9, /* 32-bit relative (5 byte dist) */
+ COFF_RELOC_AMD64_SECTION = 0xA, /* section index */
+ COFF_RELOC_AMD64_SECREL = 0xB, /* 32-bit offset from base of sect */
+ COFF_RELOC_AMD64_SECREL7 = 0xC, /* 7-bit offset from base of sect */
+ COFF_RELOC_AMD64_TOKEN = 0xD /* CLR metadata token */
+ } type; /* type of relocation */
+} coff_reloc;
+
+#define COFF_STYP_TEXT 0x00000020UL
+#define COFF_STYP_DATA 0x00000040UL
+#define COFF_STYP_BSS 0x00000080UL
+#define COFF_STYP_INFO 0x00000200UL
+#define COFF_STYP_STD_MASK 0x000003FFUL
+#define COFF_STYP_ALIGN_MASK 0x00F00000UL
+#define COFF_STYP_ALIGN_SHIFT 20
+#define COFF_STYP_NRELOC_OVFL 0x01000000UL
+#define COFF_STYP_DISCARD 0x02000000UL
+#define COFF_STYP_NOCACHE 0x04000000UL
+#define COFF_STYP_NOPAGE 0x08000000UL
+#define COFF_STYP_SHARED 0x10000000UL
+#define COFF_STYP_EXECUTE 0x20000000UL
+#define COFF_STYP_READ 0x40000000UL
+#define COFF_STYP_WRITE 0x80000000UL
+#define COFF_STYP_WIN32_MASK 0xFF000000UL
+
+#define COFF_FLAG_NOBASE (1UL<<0) /* Use no-base (NB) relocs */
+
+typedef struct coff_section_data {
+ /*@dependent@*/ yasm_symrec *sym; /* symbol created for this section */
+ unsigned int scnum; /* section number (1=first section) */
+ unsigned long flags; /* section flags (see COFF_STYP_* above) */
+ unsigned long addr; /* starting memory address (first section -> 0) */
+ unsigned long scnptr; /* file ptr to raw data */
+ unsigned long size; /* size of raw data (section data) in bytes */
+ unsigned long relptr; /* file ptr to relocation */
+ unsigned long nreloc; /* number of relocation entries >64k -> error */
+ unsigned long flags2; /* internal flags (see COFF_FLAG_* above) */
+ unsigned long strtab_name; /* strtab offset of name if name > 8 chars */
+ int isdebug; /* is a debug section? */
+} coff_section_data;
+
+typedef enum coff_symrec_sclass {
+ COFF_SCL_EFCN = 0xff, /* physical end of function */
+ COFF_SCL_NULL = 0,
+ COFF_SCL_AUTO = 1, /* automatic variable */
+ COFF_SCL_EXT = 2, /* external symbol */
+ COFF_SCL_STAT = 3, /* static */
+ COFF_SCL_REG = 4, /* register variable */
+ COFF_SCL_EXTDEF = 5, /* external definition */
+ COFF_SCL_LABEL = 6, /* label */
+ COFF_SCL_ULABEL = 7, /* undefined label */
+ COFF_SCL_MOS = 8, /* member of structure */
+ COFF_SCL_ARG = 9, /* function argument */
+ COFF_SCL_STRTAG = 10, /* structure tag */
+ COFF_SCL_MOU = 11, /* member of union */
+ COFF_SCL_UNTAG = 12, /* union tag */
+ COFF_SCL_TPDEF = 13, /* type definition */
+ COFF_SCL_USTATIC = 14, /* undefined static */
+ COFF_SCL_ENTAG = 15, /* enumeration tag */
+ COFF_SCL_MOE = 16, /* member of enumeration */
+ COFF_SCL_REGPARM = 17, /* register parameter */
+ COFF_SCL_FIELD = 18, /* bit field */
+ COFF_SCL_AUTOARG = 19, /* auto argument */
+ COFF_SCL_LASTENT = 20, /* dummy entry (end of block) */
+ COFF_SCL_BLOCK = 100, /* ".bb" or ".eb" */
+ COFF_SCL_FCN = 101, /* ".bf" or ".ef" */
+ COFF_SCL_EOS = 102, /* end of structure */
+ COFF_SCL_FILE = 103, /* file name */
+ COFF_SCL_LINE = 104, /* line # reformatted as symbol table entry */
+ COFF_SCL_ALIAS = 105, /* duplicate tag */
+ COFF_SCL_HIDDEN = 106 /* ext symbol in dmert public lib */
+} coff_symrec_sclass;
+
+typedef union coff_symtab_auxent {
+ /* no data needed for section symbol auxent, all info avail from sym */
+ /*@owned@*/ char *fname; /* filename aux entry */
+} coff_symtab_auxent;
+
+typedef enum coff_symtab_auxtype {
+ COFF_SYMTAB_AUX_NONE = 0,
+ COFF_SYMTAB_AUX_SECT,
+ COFF_SYMTAB_AUX_FILE
+} coff_symtab_auxtype;
+
+typedef struct coff_symrec_data {
+ int forcevis; /* force visibility in symbol table */
+ unsigned long index; /* assigned COFF symbol table index */
+ unsigned int type; /* type */
+ coff_symrec_sclass sclass; /* storage class */
+
+ int numaux; /* number of auxiliary entries */
+ coff_symtab_auxtype auxtype; /* type of aux entries */
+ coff_symtab_auxent aux[1]; /* actually may be any size (including 0) */
+} coff_symrec_data;
+
+typedef struct yasm_objfmt_coff {
+ yasm_objfmt_base objfmt; /* base structure */
+
+ unsigned int parse_scnum; /* sect numbering in parser */
+ int win32; /* nonzero for win32/64 output */
+ int win64; /* nonzero for win64 output */
+
+ unsigned int machine; /* COFF machine to use */
+
+ coff_symrec_data *filesym_data; /* Data for .file symbol */
+
+ /* data for .def/.endef and related directives */
+ coff_symrec_data *def_sym; /* symbol specified by .def */
+
+ /* data for win64 proc_frame and related directives */
+ unsigned long proc_frame; /* Line number of start of proc, or 0 */
+ unsigned long done_prolog; /* Line number of end of prologue, or 0 */
+ /*@null@*/ coff_unwind_info *unwind; /* Unwind info */
+
+ yasm_symrec *ssym_imagebase; /* ..imagebase symbol for win64 */
+} yasm_objfmt_coff;
+
+typedef struct coff_objfmt_output_info {
+ yasm_object *object;
+ yasm_objfmt_coff *objfmt_coff;
+ yasm_errwarns *errwarns;
+ /*@dependent@*/ FILE *f;
+ /*@only@*/ unsigned char *buf;
+ yasm_section *sect;
+ /*@dependent@*/ coff_section_data *csd;
+ unsigned long addr; /* start of next section */
+
+ unsigned long indx; /* current symbol index */
+ int all_syms; /* outputting all symbols? */
+ unsigned long strtab_offset; /* current string table offset */
+} coff_objfmt_output_info;
+
+static void coff_section_data_destroy(/*@only@*/ void *d);
+static void coff_section_data_print(void *data, FILE *f, int indent_level);
+
+static const yasm_assoc_data_callback coff_section_data_cb = {
+ coff_section_data_destroy,
+ coff_section_data_print
+};
+
+static void coff_symrec_data_destroy(/*@only@*/ void *d);
+static void coff_symrec_data_print(void *data, FILE *f, int indent_level);
+
+static const yasm_assoc_data_callback coff_symrec_data_cb = {
+ coff_symrec_data_destroy,
+ coff_symrec_data_print
+};
+
+/* Bytecode callback function prototypes */
+static void win32_sxdata_bc_destroy(void *contents);
+static void win32_sxdata_bc_print(const void *contents, FILE *f,
+ int indent_level);
+static int win32_sxdata_bc_calc_len
+ (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
+static int win32_sxdata_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+/* Bytecode callback structures */
+static const yasm_bytecode_callback win32_sxdata_bc_callback = {
+ win32_sxdata_bc_destroy,
+ win32_sxdata_bc_print,
+ yasm_bc_finalize_common,
+ NULL,
+ win32_sxdata_bc_calc_len,
+ yasm_bc_expand_common,
+ win32_sxdata_bc_tobytes,
+ 0
+};
+
+yasm_objfmt_module yasm_coff_LTX_objfmt;
+yasm_objfmt_module yasm_win32_LTX_objfmt;
+yasm_objfmt_module yasm_win64_LTX_objfmt;
+
+
+static /*@dependent@*/ coff_symrec_data *
+coff_objfmt_sym_set_data(yasm_symrec *sym, coff_symrec_sclass sclass,
+ int numaux, coff_symtab_auxtype auxtype)
+{
+ coff_symrec_data *sym_data;
+
+ sym_data = yasm_xmalloc(sizeof(coff_symrec_data) +
+ (numaux-1)*sizeof(coff_symtab_auxent));
+ sym_data->forcevis = 0;
+ sym_data->index = 0;
+ sym_data->type = 0;
+ sym_data->sclass = sclass;
+ sym_data->numaux = numaux;
+ sym_data->auxtype = auxtype;
+
+ yasm_symrec_add_data(sym, &coff_symrec_data_cb, sym_data);
+
+ return sym_data;
+}
+
+static yasm_objfmt_coff *
+coff_common_create(yasm_object *object)
+{
+ yasm_objfmt_coff *objfmt_coff = yasm_xmalloc(sizeof(yasm_objfmt_coff));
+ yasm_symrec *filesym;
+
+ /* Only support x86 arch */
+ if (yasm__strcasecmp(yasm_arch_keyword(object->arch), "x86") != 0) {
+ yasm_xfree(objfmt_coff);
+ return NULL;
+ }
+
+ objfmt_coff->parse_scnum = 1; /* section numbering starts at 1 */
+
+ /* FIXME: misuse of NULL bytecode here; it works, but only barely. */
+ filesym = yasm_symtab_define_special(object->symtab, ".file",
+ YASM_SYM_GLOBAL);
+ objfmt_coff->filesym_data =
+ coff_objfmt_sym_set_data(filesym, COFF_SCL_FILE, 1,
+ COFF_SYMTAB_AUX_FILE);
+ /* Filename is set in coff_objfmt_output */
+ objfmt_coff->filesym_data->aux[0].fname = NULL;
+
+ objfmt_coff->proc_frame = 0;
+ objfmt_coff->done_prolog = 0;
+ objfmt_coff->unwind = NULL;
+ objfmt_coff->ssym_imagebase = NULL;
+
+ return objfmt_coff;
+}
+
+static yasm_objfmt *
+coff_objfmt_create(yasm_object *object)
+{
+ yasm_objfmt_coff *objfmt_coff = coff_common_create(object);
+
+ if (objfmt_coff) {
+ /* Support x86 and amd64 machines of x86 arch */
+ if (yasm__strcasecmp(yasm_arch_get_machine(object->arch), "x86") == 0)
+ objfmt_coff->machine = COFF_MACHINE_I386;
+ else if (yasm__strcasecmp(yasm_arch_get_machine(object->arch),
+ "amd64") == 0)
+ objfmt_coff->machine = COFF_MACHINE_AMD64;
+ else {
+ yasm_xfree(objfmt_coff);
+ return NULL;
+ }
+
+ objfmt_coff->objfmt.module = &yasm_coff_LTX_objfmt;
+ objfmt_coff->win32 = 0;
+ objfmt_coff->win64 = 0;
+ }
+ return (yasm_objfmt *)objfmt_coff;
+}
+
+static yasm_objfmt *
+win32_objfmt_create(yasm_object *object)
+{
+ yasm_objfmt_coff *objfmt_coff = coff_common_create(object);
+
+ if (objfmt_coff) {
+ /* Support x86 and amd64 machines of x86 arch.
+ * (amd64 machine supported for backwards compatibility)
+ */
+ if (yasm__strcasecmp(yasm_arch_get_machine(object->arch),
+ "x86") == 0) {
+ objfmt_coff->machine = COFF_MACHINE_I386;
+ objfmt_coff->objfmt.module = &yasm_win32_LTX_objfmt;
+ objfmt_coff->win64 = 0;
+ } else if (yasm__strcasecmp(yasm_arch_get_machine(object->arch),
+ "amd64") == 0) {
+ objfmt_coff->machine = COFF_MACHINE_AMD64;
+ objfmt_coff->objfmt.module = &yasm_win64_LTX_objfmt;
+ objfmt_coff->win64 = 1;
+ } else {
+ yasm_xfree(objfmt_coff);
+ return NULL;
+ }
+
+ objfmt_coff->win32 = 1;
+ /* Define a @feat.00 symbol for win32 safeseh handling */
+ if (!objfmt_coff->win64) {
+ yasm_symrec *feat00;
+ coff_symrec_data *sym_data;
+ feat00 = yasm_symtab_define_equ(object->symtab, "@feat.00",
+ yasm_expr_create_ident(yasm_expr_int(
+ yasm_intnum_create_uint(1)), 0), 0);
+ sym_data = coff_objfmt_sym_set_data(feat00, COFF_SCL_STAT, 0,
+ COFF_SYMTAB_AUX_NONE);
+ sym_data->forcevis = 1;
+ }
+ }
+ return (yasm_objfmt *)objfmt_coff;
+}
+
+static yasm_objfmt *
+win64_objfmt_create(yasm_object *object)
+{
+ yasm_objfmt_coff *objfmt_coff = coff_common_create(object);
+
+ if (objfmt_coff) {
+ /* Support amd64 machine of x86 arch */
+ if (yasm__strcasecmp(yasm_arch_get_machine(object->arch),
+ "amd64") == 0) {
+ objfmt_coff->machine = COFF_MACHINE_AMD64;
+ } else {
+ yasm_xfree(objfmt_coff);
+ return NULL;
+ }
+
+ objfmt_coff->objfmt.module = &yasm_win64_LTX_objfmt;
+ objfmt_coff->win32 = 1;
+ objfmt_coff->win64 = 1;
+ objfmt_coff->ssym_imagebase =
+ yasm_symtab_define_label(object->symtab, "..imagebase", NULL, 0, 0);
+ }
+ return (yasm_objfmt *)objfmt_coff;
+}
+
+static void
+coff_objfmt_init_new_section(yasm_section *sect, unsigned long line)
+{
+ yasm_object *object = yasm_section_get_object(sect);
+ const char *sectname = yasm_section_get_name(sect);
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ coff_section_data *data;
+ yasm_symrec *sym;
+
+ data = yasm_xmalloc(sizeof(coff_section_data));
+ data->scnum = objfmt_coff->parse_scnum++;
+ data->flags = 0;
+ data->addr = 0;
+ data->scnptr = 0;
+ data->size = 0;
+ data->relptr = 0;
+ data->nreloc = 0;
+ data->flags2 = 0;
+ data->strtab_name = 0;
+ data->isdebug = 0;
+
+ if (yasm__strncasecmp(sectname, ".debug", 6)==0) {
+ data->flags = COFF_STYP_DATA;
+ if (objfmt_coff->win32)
+ data->flags |= COFF_STYP_DISCARD|COFF_STYP_READ;
+ data->isdebug = 1;
+ } else
+ data->flags = COFF_STYP_TEXT;
+
+ yasm_section_add_data(sect, &coff_section_data_cb, data);
+
+ sym = yasm_symtab_define_label(object->symtab, sectname,
+ yasm_section_bcs_first(sect), 1, line);
+ yasm_symrec_declare(sym, YASM_SYM_GLOBAL, line);
+ coff_objfmt_sym_set_data(sym, COFF_SCL_STAT, 1, COFF_SYMTAB_AUX_SECT);
+ data->sym = sym;
+}
+
+static int
+coff_objfmt_set_section_addr(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ coff_section_data *csd;
+
+ assert(info != NULL);
+ csd = yasm_section_get_data(sect, &coff_section_data_cb);
+ assert(csd != NULL);
+
+ csd->addr = info->addr;
+ info->addr += yasm_bc_next_offset(yasm_section_bcs_last(sect));
+
+ return 0;
+}
+
+static int
+coff_objfmt_output_value(yasm_value *value, unsigned char *buf,
+ unsigned int destsize, unsigned long offset,
+ yasm_bytecode *bc, int warn, /*@null@*/ void *d)
+{
+ /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
+ yasm_objfmt_coff *objfmt_coff;
+ /*@only@*/ /*@null@*/ yasm_intnum *dist = NULL;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
+ unsigned long intn_val, intn_minus;
+ int retval;
+ unsigned int valsize = value->size;
+
+ assert(info != NULL);
+ objfmt_coff = info->objfmt_coff;
+
+ if (value->abs)
+ value->abs = yasm_expr_simplify(value->abs, 1);
+
+ /* Try to output constant and PC-relative section-local first.
+ * Note this does NOT output any value with a SEG, WRT, external,
+ * cross-section, or non-PC-relative reference (those are handled below).
+ */
+ switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
+ info->object->arch)) {
+ case -1:
+ return 1;
+ case 0:
+ break;
+ default:
+ return 0;
+ }
+
+ /* Handle other expressions, with relocation if necessary */
+ if (value->rshift > 0
+ || (value->seg_of && (value->wrt || value->curpos_rel))
+ || (value->section_rel && (value->wrt || value->curpos_rel))) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("coff: relocation too complex"));
+ return 1;
+ }
+
+ intn_val = 0;
+ intn_minus = 0;
+ if (value->rel) {
+ yasm_sym_vis vis = yasm_symrec_get_visibility(value->rel);
+ /*@dependent@*/ /*@null@*/ yasm_symrec *sym = value->rel;
+ unsigned long addr;
+ coff_reloc *reloc;
+ int nobase = info->csd->flags2 & COFF_FLAG_NOBASE;
+
+ /* Sometimes we want the relocation to be generated against one
+ * symbol but the value generated correspond to a different symbol.
+ * This is done through (sym being referenced) WRT (sym used for
+ * reloc). Note both syms need to be in the same section!
+ */
+ if (value->wrt && value->wrt == objfmt_coff->ssym_imagebase)
+ nobase = 1;
+ else if (value->wrt) {
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *rel_precbc, *wrt_precbc;
+
+ if (!yasm_symrec_get_label(sym, &rel_precbc)
+ || !yasm_symrec_get_label(value->wrt, &wrt_precbc)) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("coff: wrt expression too complex"));
+ return 1;
+ }
+ dist = yasm_calc_bc_dist(wrt_precbc, rel_precbc);
+ if (!dist) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("coff: cannot wrt across sections"));
+ return 1;
+ }
+ sym = value->wrt;
+ }
+
+ if (vis & YASM_SYM_COMMON) {
+ /* In standard COFF, COMMON symbols have their length added in */
+ if (!objfmt_coff->win32) {
+ /*@dependent@*/ /*@null@*/ yasm_expr **csize_expr;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *common_size;
+
+ csize_expr = yasm_symrec_get_common_size(sym);
+ assert(csize_expr != NULL);
+ common_size = yasm_expr_get_intnum(csize_expr, 1);
+ if (!common_size) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("coff: common size too complex"));
+ return 1;
+ }
+
+ if (yasm_intnum_sign(common_size) < 0) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("coff: common size is negative"));
+ return 1;
+ }
+
+ intn_val += yasm_intnum_get_uint(common_size);
+ }
+ } else if (!(vis & YASM_SYM_EXTERN) && !objfmt_coff->win64) {
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *sym_precbc;
+
+ /* Local symbols need relocation to their section's start */
+ if (yasm_symrec_get_label(sym, &sym_precbc)) {
+ yasm_section *sym_sect = yasm_bc_get_section(sym_precbc);
+ /*@null@*/ coff_section_data *sym_csd;
+ sym_csd = yasm_section_get_data(sym_sect,
+ &coff_section_data_cb);
+ assert(sym_csd != NULL);
+ sym = sym_csd->sym;
+ intn_val = yasm_bc_next_offset(sym_precbc);
+ if (COFF_SET_VMA)
+ intn_val += sym_csd->addr;
+ }
+ }
+
+ if (value->curpos_rel) {
+ /* For standard COFF, need to adjust to start of section, e.g.
+ * subtract out the bytecode offset.
+ * For Win32 COFF, need to adjust based on value size and position.
+ * For Win64 COFF that's IP-relative, adjust to next bytecode;
+ * the difference between the offset+destsize and BC length is
+ * taken care of by special relocation types.
+ */
+ if (objfmt_coff->win64 && value->ip_rel)
+ intn_val += bc->len*bc->mult_int;
+ else if (objfmt_coff->win32)
+ intn_val += offset+destsize;
+ else
+ intn_minus = bc->offset;
+ }
+
+ if (value->seg_of) {
+ /* Segment generation; zero value. */
+ intn_val = 0;
+ intn_minus = 0;
+ }
+
+ /* Generate reloc */
+ reloc = yasm_xmalloc(sizeof(coff_reloc));
+ addr = bc->offset + offset;
+ if (COFF_SET_VMA)
+ addr += info->addr;
+ reloc->reloc.addr = yasm_intnum_create_uint(addr);
+ reloc->reloc.sym = sym;
+
+ if (value->curpos_rel) {
+ if (objfmt_coff->machine == COFF_MACHINE_I386) {
+ if (valsize == 32)
+ reloc->type = COFF_RELOC_I386_REL32;
+ else {
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("coff: invalid relocation size"));
+ return 1;
+ }
+ } else if (objfmt_coff->machine == COFF_MACHINE_AMD64) {
+ if (valsize != 32) {
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("coff: invalid relocation size"));
+ return 1;
+ }
+ if (!value->ip_rel)
+ reloc->type = COFF_RELOC_AMD64_REL32;
+ else switch (bc->len*bc->mult_int - (offset+destsize)) {
+ case 0:
+ reloc->type = COFF_RELOC_AMD64_REL32;
+ break;
+ case 1:
+ reloc->type = COFF_RELOC_AMD64_REL32_1;
+ break;
+ case 2:
+ reloc->type = COFF_RELOC_AMD64_REL32_2;
+ break;
+ case 3:
+ reloc->type = COFF_RELOC_AMD64_REL32_3;
+ break;
+ case 4:
+ reloc->type = COFF_RELOC_AMD64_REL32_4;
+ break;
+ case 5:
+ reloc->type = COFF_RELOC_AMD64_REL32_5;
+ break;
+ default:
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("coff: invalid relocation size"));
+ return 1;
+ }
+ } else
+ yasm_internal_error(N_("coff objfmt: unrecognized machine"));
+ } else if (value->seg_of) {
+ if (objfmt_coff->machine == COFF_MACHINE_I386)
+ reloc->type = COFF_RELOC_I386_SECTION;
+ else if (objfmt_coff->machine == COFF_MACHINE_AMD64)
+ reloc->type = COFF_RELOC_AMD64_SECTION;
+ else
+ yasm_internal_error(N_("coff objfmt: unrecognized machine"));
+ } else if (value->section_rel) {
+ if (objfmt_coff->machine == COFF_MACHINE_I386)
+ reloc->type = COFF_RELOC_I386_SECREL;
+ else if (objfmt_coff->machine == COFF_MACHINE_AMD64)
+ reloc->type = COFF_RELOC_AMD64_SECREL;
+ else
+ yasm_internal_error(N_("coff objfmt: unrecognized machine"));
+ } else {
+ if (objfmt_coff->machine == COFF_MACHINE_I386) {
+ if (nobase)
+ reloc->type = COFF_RELOC_I386_ADDR32NB;
+ else
+ reloc->type = COFF_RELOC_I386_ADDR32;
+ } else if (objfmt_coff->machine == COFF_MACHINE_AMD64) {
+ if (valsize == 32) {
+ if (nobase)
+ reloc->type = COFF_RELOC_AMD64_ADDR32NB;
+ else
+ reloc->type = COFF_RELOC_AMD64_ADDR32;
+ } else if (valsize == 64)
+ reloc->type = COFF_RELOC_AMD64_ADDR64;
+ else {
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("coff: invalid relocation size"));
+ return 1;
+ }
+ } else
+ yasm_internal_error(N_("coff objfmt: unrecognized machine"));
+ }
+ info->csd->nreloc++;
+ yasm_section_add_reloc(info->sect, (yasm_reloc *)reloc, yasm_xfree);
+ }
+
+ /* Build up final integer output from intn_val, intn_minus, value->abs,
+ * and dist. We do all this at the end to avoid creating temporary
+ * intnums above (except for dist).
+ */
+ if (intn_minus <= intn_val)
+ intn = yasm_intnum_create_uint(intn_val-intn_minus);
+ else {
+ intn = yasm_intnum_create_uint(intn_minus-intn_val);
+ yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
+ }
+
+ if (value->abs) {
+ yasm_intnum *intn2 = yasm_expr_get_intnum(&value->abs, 0);
+ if (!intn2) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("coff: relocation too complex"));
+ yasm_intnum_destroy(intn);
+ if (dist)
+ yasm_intnum_destroy(dist);
+ return 1;
+ }
+ yasm_intnum_calc(intn, YASM_EXPR_ADD, intn2);
+ }
+
+ if (dist) {
+ yasm_intnum_calc(intn, YASM_EXPR_ADD, dist);
+ yasm_intnum_destroy(dist);
+ }
+
+ retval = yasm_arch_intnum_tobytes(info->object->arch, intn, buf, destsize,
+ valsize, 0, bc, warn);
+ yasm_intnum_destroy(intn);
+ return retval;
+}
+
+static int
+coff_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
+{
+ /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
+ /*@null@*/ /*@only@*/ unsigned char *bigbuf;
+ unsigned long size = REGULAR_OUTBUF_SIZE;
+ int gap;
+
+ assert(info != NULL);
+
+ bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &gap, info,
+ coff_objfmt_output_value, NULL);
+
+ /* Don't bother doing anything else if size ended up being 0. */
+ if (size == 0) {
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+ return 0;
+ }
+
+ info->csd->size += size;
+
+ /* Warn that gaps are converted to 0 and write out the 0's. */
+ if (gap) {
+ unsigned long left;
+ yasm_warn_set(YASM_WARN_UNINIT_CONTENTS,
+ N_("uninitialized space declared in code/data section: zeroing"));
+ /* Write out in chunks */
+ memset(info->buf, 0, REGULAR_OUTBUF_SIZE);
+ left = size;
+ while (left > REGULAR_OUTBUF_SIZE) {
+ fwrite(info->buf, REGULAR_OUTBUF_SIZE, 1, info->f);
+ left -= REGULAR_OUTBUF_SIZE;
+ }
+ fwrite(info->buf, left, 1, info->f);
+ } else {
+ /* Output buf (or bigbuf if non-NULL) to file */
+ fwrite(bigbuf ? bigbuf : info->buf, (size_t)size, 1, info->f);
+ }
+
+ /* If bigbuf was allocated, free it */
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+
+ return 0;
+}
+
+static int
+coff_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ coff_section_data *csd;
+ long pos;
+ coff_reloc *reloc;
+ unsigned char *localbuf;
+
+ assert(info != NULL);
+ csd = yasm_section_get_data(sect, &coff_section_data_cb);
+ assert(csd != NULL);
+
+ /* Add to strtab if in win32 format and name > 8 chars */
+ if (info->objfmt_coff->win32) {
+ size_t namelen = strlen(yasm_section_get_name(sect));
+ if (namelen > 8) {
+ csd->strtab_name = info->strtab_offset;
+ info->strtab_offset += (unsigned long)(namelen + 1);
+ }
+ }
+
+ if (!csd->isdebug)
+ csd->addr = info->addr;
+
+ if ((csd->flags & COFF_STYP_STD_MASK) == COFF_STYP_BSS) {
+ /* Don't output BSS sections.
+ * TODO: Check for non-reserve bytecodes?
+ */
+ pos = 0; /* position = 0 because it's not in the file */
+ csd->size = yasm_bc_next_offset(yasm_section_bcs_last(sect));
+ } else {
+ pos = ftell(info->f);
+ if (pos == -1) {
+ yasm__fatal(N_("could not get file position on output file"));
+ /*@notreached@*/
+ return 1;
+ }
+
+ info->sect = sect;
+ info->csd = csd;
+ yasm_section_bcs_traverse(sect, info->errwarns, info,
+ coff_objfmt_output_bytecode);
+
+ /* Sanity check final section size */
+ if (yasm_errwarns_num_errors(info->errwarns, 0) == 0 &&
+ csd->size != yasm_bc_next_offset(yasm_section_bcs_last(sect)))
+ yasm_internal_error(
+ N_("coff: section computed size did not match actual size"));
+ }
+
+ /* Empty? Go on to next section */
+ if (csd->size == 0)
+ return 0;
+
+ if (!csd->isdebug)
+ info->addr += csd->size;
+ csd->scnptr = (unsigned long)pos;
+
+ /* No relocations to output? Go on to next section */
+ if (csd->nreloc == 0)
+ return 0;
+
+ pos = ftell(info->f);
+ if (pos == -1) {
+ yasm__fatal(N_("could not get file position on output file"));
+ /*@notreached@*/
+ return 1;
+ }
+ csd->relptr = (unsigned long)pos;
+
+ /* If >=64K relocs (for Win32/64), we set a flag in the section header
+ * (NRELOC_OVFL) and the first relocation contains the number of relocs.
+ */
+ if (csd->nreloc >= 64*1024 && info->objfmt_coff->win32) {
+ localbuf = info->buf;
+ YASM_WRITE_32_L(localbuf, csd->nreloc+1); /* address of relocation */
+ YASM_WRITE_32_L(localbuf, 0); /* relocated symbol */
+ YASM_WRITE_16_L(localbuf, 0); /* type of relocation */
+ fwrite(info->buf, 10, 1, info->f);
+ }
+
+ reloc = (coff_reloc *)yasm_section_relocs_first(sect);
+ while (reloc) {
+ /*@null@*/ coff_symrec_data *csymd;
+ localbuf = info->buf;
+
+ csymd = yasm_symrec_get_data(reloc->reloc.sym, &coff_symrec_data_cb);
+ if (!csymd)
+ yasm_internal_error(
+ N_("coff: no symbol data for relocated symbol"));
+
+ yasm_intnum_get_sized(reloc->reloc.addr, localbuf, 4, 32, 0, 0, 0);
+ localbuf += 4; /* address of relocation */
+ YASM_WRITE_32_L(localbuf, csymd->index); /* relocated symbol */
+ YASM_WRITE_16_L(localbuf, reloc->type); /* type of relocation */
+ fwrite(info->buf, 10, 1, info->f);
+
+ reloc = (coff_reloc *)yasm_section_reloc_next((yasm_reloc *)reloc);
+ }
+
+ return 0;
+}
+
+static int
+coff_objfmt_output_sectstr(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
+ const char *name;
+ size_t len;
+
+ /* Add to strtab if in win32 format and name > 8 chars */
+ if (!info->objfmt_coff->win32)
+ return 0;
+
+ name = yasm_section_get_name(sect);
+ len = strlen(name);
+ if (len > 8)
+ fwrite(name, len+1, 1, info->f);
+ return 0;
+}
+
+static int
+coff_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
+ yasm_objfmt_coff *objfmt_coff;
+ /*@dependent@*/ /*@null@*/ coff_section_data *csd;
+ unsigned char *localbuf;
+ unsigned long align = yasm_section_get_align(sect);
+
+ assert(info != NULL);
+ objfmt_coff = info->objfmt_coff;
+ csd = yasm_section_get_data(sect, &coff_section_data_cb);
+ assert(csd != NULL);
+
+ /* Check to see if alignment is supported size */
+ if (align > 8192)
+ align = 8192;
+
+ /* Convert alignment into flags setting */
+ csd->flags &= ~COFF_STYP_ALIGN_MASK;
+ while (align != 0) {
+ csd->flags += 1<<COFF_STYP_ALIGN_SHIFT;
+ align >>= 1;
+ }
+
+ /* section name */
+ localbuf = info->buf;
+ if (strlen(yasm_section_get_name(sect)) > 8) {
+ char namenum[30];
+ sprintf(namenum, "/%ld", csd->strtab_name);
+ strncpy((char *)localbuf, namenum, 8);
+ } else
+ strncpy((char *)localbuf, yasm_section_get_name(sect), 8);
+ localbuf += 8;
+ if (csd->isdebug) {
+ YASM_WRITE_32_L(localbuf, 0); /* physical address */
+ YASM_WRITE_32_L(localbuf, 0); /* virtual address */
+ } else {
+ YASM_WRITE_32_L(localbuf, csd->addr); /* physical address */
+ if (COFF_SET_VMA)
+ YASM_WRITE_32_L(localbuf, csd->addr);/* virtual address */
+ else
+ YASM_WRITE_32_L(localbuf, 0); /* virtual address */
+ }
+ YASM_WRITE_32_L(localbuf, csd->size); /* section size */
+ YASM_WRITE_32_L(localbuf, csd->scnptr); /* file ptr to data */
+ YASM_WRITE_32_L(localbuf, csd->relptr); /* file ptr to relocs */
+ YASM_WRITE_32_L(localbuf, 0); /* file ptr to line nums */
+ if (csd->nreloc >= 64*1024) {
+ /* Win32/64 has special handling for this case. */
+ if (objfmt_coff->win32)
+ csd->flags |= COFF_STYP_NRELOC_OVFL;
+ else {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("too many relocations in section `%s'"),
+ yasm_section_get_name(sect));
+ yasm_errwarn_propagate(info->errwarns, 0);
+ }
+ YASM_WRITE_16_L(localbuf, 0xFFFF); /* max out */
+ } else
+ YASM_WRITE_16_L(localbuf, csd->nreloc); /* num of relocation entries */
+ YASM_WRITE_16_L(localbuf, 0); /* num of line number entries */
+ YASM_WRITE_32_L(localbuf, csd->flags); /* flags */
+ fwrite(info->buf, 40, 1, info->f);
+
+ return 0;
+}
+
+static int
+coff_objfmt_count_sym(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
+ yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+ coff_symrec_data *sym_data;
+
+ assert(info != NULL);
+
+ sym_data = yasm_symrec_get_data(sym, &coff_symrec_data_cb);
+
+ if (info->all_syms || vis != YASM_SYM_LOCAL || yasm_symrec_is_abs(sym) ||
+ (sym_data && sym_data->forcevis)) {
+ /* Save index in symrec data */
+ if (!sym_data)
+ sym_data = coff_objfmt_sym_set_data(sym, COFF_SCL_NULL, 0,
+ COFF_SYMTAB_AUX_NONE);
+ /* Set storage class based on visibility if not already set */
+ if (sym_data->sclass == COFF_SCL_NULL) {
+ if (vis & (YASM_SYM_EXTERN|YASM_SYM_GLOBAL|YASM_SYM_COMMON))
+ sym_data->sclass = COFF_SCL_EXT;
+ else
+ sym_data->sclass = COFF_SCL_STAT;
+ }
+
+ sym_data->index = info->indx;
+
+ info->indx += sym_data->numaux + 1;
+ }
+ return 0;
+}
+
+static int
+coff_objfmt_output_sym(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
+ yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+ int is_abs = yasm_symrec_is_abs(sym);
+ /*@dependent@*/ /*@null@*/ coff_symrec_data *csymd;
+ yasm_valparamhead *objext_valparams =
+ yasm_symrec_get_objext_valparams(sym);
+ csymd = yasm_symrec_get_data(sym, &coff_symrec_data_cb);
+
+ assert(info != NULL);
+
+ /* Look for "function" flag on global syms */
+ if (csymd && csymd->type == 0 && (vis & YASM_SYM_GLOBAL) != 0) {
+ if (objext_valparams) {
+ const char *id = yasm_vp_id(yasm_vps_first(objext_valparams));
+ if (yasm__strcasecmp(id, "function") == 0)
+ csymd->type = 0x20;
+ }
+ }
+
+ /* Don't output local syms unless outputting all syms */
+ if (info->all_syms || vis != YASM_SYM_LOCAL || is_abs ||
+ (csymd && csymd->forcevis)) {
+ /*@only*/ char *name;
+ const yasm_expr *equ_val;
+ const yasm_intnum *intn;
+ unsigned char *localbuf;
+ size_t len;
+ int aux;
+ unsigned long value = 0;
+ unsigned int scnum = 0xfffe; /* -2 = debugging symbol */
+ /*@dependent@*/ /*@null@*/ yasm_section *sect;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
+ unsigned long scnlen = 0; /* for sect auxent */
+ unsigned long nreloc = 0; /* for sect auxent */
+ yasm_objfmt_coff *objfmt_coff = info->objfmt_coff;
+
+ if (is_abs)
+ name = yasm__xstrdup(".absolut");
+ else
+ name = yasm_symrec_get_global_name(sym, info->object);
+ len = strlen(name);
+
+ /* Get symrec's of_data (needed for storage class) */
+ if (!csymd)
+ yasm_internal_error(N_("coff: expected sym data to be present"));
+
+ /* Look at symrec for value/scnum/etc. */
+ if (yasm_symrec_get_label(sym, &precbc)) {
+ if (precbc)
+ sect = yasm_bc_get_section(precbc);
+ else
+ sect = NULL;
+ /* it's a label: get value and offset.
+ * If there is not a section, leave as debugging symbol.
+ */
+ if (sect) {
+ /*@dependent@*/ /*@null@*/ coff_section_data *csectd;
+ csectd = yasm_section_get_data(sect, &coff_section_data_cb);
+ if (csectd) {
+ scnum = csectd->scnum;
+ scnlen = csectd->size;
+ nreloc = csectd->nreloc;
+ if (COFF_SET_VMA)
+ value = csectd->addr;
+ } else
+ yasm_internal_error(N_("didn't understand section"));
+ if (precbc)
+ value += yasm_bc_next_offset(precbc);
+ }
+ } else if ((equ_val = yasm_symrec_get_equ(sym))) {
+ yasm_expr *equ_val_copy = yasm_expr_copy(equ_val);
+ intn = yasm_expr_get_intnum(&equ_val_copy, 1);
+ if (!intn) {
+ if (vis & YASM_SYM_GLOBAL) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("global EQU value not an integer expression"));
+ yasm_errwarn_propagate(info->errwarns, equ_val->line);
+ }
+ } else
+ value = yasm_intnum_get_uint(intn);
+ yasm_expr_destroy(equ_val_copy);
+
+ scnum = 0xffff; /* -1 = absolute symbol */
+ } else {
+ if (vis & YASM_SYM_COMMON) {
+ /*@dependent@*/ /*@null@*/ yasm_expr **csize_expr;
+ csize_expr = yasm_symrec_get_common_size(sym);
+ assert(csize_expr != NULL);
+ intn = yasm_expr_get_intnum(csize_expr, 1);
+ if (!intn) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("COMMON data size not an integer expression"));
+ yasm_errwarn_propagate(info->errwarns,
+ (*csize_expr)->line);
+ } else
+ value = yasm_intnum_get_uint(intn);
+ scnum = 0;
+ }
+ if (vis & YASM_SYM_EXTERN)
+ scnum = 0;
+ }
+
+ localbuf = info->buf;
+ if (len > 8) {
+ YASM_WRITE_32_L(localbuf, 0); /* "zeros" field */
+ YASM_WRITE_32_L(localbuf, info->strtab_offset); /* strtab offset */
+ info->strtab_offset += (unsigned long)(len+1);
+ } else {
+ /* <8 chars, so no string table entry needed */
+ strncpy((char *)localbuf, name, 8);
+ localbuf += 8;
+ }
+ YASM_WRITE_32_L(localbuf, value); /* value */
+ YASM_WRITE_16_L(localbuf, scnum); /* section number */
+ YASM_WRITE_16_L(localbuf, csymd->type); /* type */
+ YASM_WRITE_8(localbuf, csymd->sclass); /* storage class */
+ YASM_WRITE_8(localbuf, csymd->numaux); /* number of aux entries */
+ fwrite(info->buf, 18, 1, info->f);
+ for (aux=0; aux<csymd->numaux; aux++) {
+ localbuf = info->buf;
+ memset(localbuf, 0, 18);
+ switch (csymd->auxtype) {
+ case COFF_SYMTAB_AUX_NONE:
+ break;
+ case COFF_SYMTAB_AUX_SECT:
+ YASM_WRITE_32_L(localbuf, scnlen); /* section length */
+ YASM_WRITE_16_L(localbuf, nreloc); /* number relocs */
+ YASM_WRITE_16_L(localbuf, 0); /* number line nums */
+ break;
+ case COFF_SYMTAB_AUX_FILE:
+ len = strlen(csymd->aux[0].fname);
+ if (len > 14) {
+ YASM_WRITE_32_L(localbuf, 0);
+ YASM_WRITE_32_L(localbuf, info->strtab_offset);
+ info->strtab_offset += (unsigned long)(len+1);
+ } else
+ strncpy((char *)localbuf, csymd->aux[0].fname, 14);
+ break;
+ default:
+ yasm_internal_error(
+ N_("coff: unrecognized aux symtab type"));
+ }
+ fwrite(info->buf, 18, 1, info->f);
+ }
+ yasm_xfree(name);
+ }
+ return 0;
+}
+
+static int
+coff_objfmt_output_str(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
+ yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+ /*@dependent@*/ /*@null@*/ coff_symrec_data *csymd;
+ csymd = yasm_symrec_get_data(sym, &coff_symrec_data_cb);
+
+ assert(info != NULL);
+
+ /* Don't output local syms unless outputting all syms */
+ if (info->all_syms || vis != YASM_SYM_LOCAL ||
+ (csymd && csymd->forcevis)) {
+ /*@only@*/ char *name = yasm_symrec_get_global_name(sym, info->object);
+ size_t len = strlen(name);
+ int aux;
+
+ if (!csymd)
+ yasm_internal_error(N_("coff: expected sym data to be present"));
+
+ if (len > 8)
+ fwrite(name, len+1, 1, info->f);
+ for (aux=0; aux<csymd->numaux; aux++) {
+ switch (csymd->auxtype) {
+ case COFF_SYMTAB_AUX_FILE:
+ len = strlen(csymd->aux[0].fname);
+ if (len > 14)
+ fwrite(csymd->aux[0].fname, len+1, 1, info->f);
+ break;
+ default:
+ break;
+ }
+ }
+ yasm_xfree(name);
+ }
+ return 0;
+}
+
+static void
+coff_objfmt_output(yasm_object *object, FILE *f, int all_syms,
+ yasm_errwarns *errwarns)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ coff_objfmt_output_info info;
+ unsigned char *localbuf;
+ long pos;
+ unsigned long symtab_pos;
+ unsigned long symtab_count;
+ unsigned int flags;
+ unsigned long ts;
+
+ if (objfmt_coff->proc_frame) {
+ yasm_error_set_xref(objfmt_coff->proc_frame,
+ N_("procedure started here"));
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("end of file in procedure frame"));
+ yasm_errwarn_propagate(errwarns, 0);
+ return;
+ }
+
+ if (objfmt_coff->filesym_data->aux[0].fname)
+ yasm_xfree(objfmt_coff->filesym_data->aux[0].fname);
+ if (!object->deb_filename) {
+ object->deb_filename = yasm_replace_path(
+ objfmt_coff->objfmt.module->replace_map, objfmt_coff->objfmt.module->replace_map_size,
+ object->src_filename, strlen(object->src_filename));
+ }
+ objfmt_coff->filesym_data->aux[0].fname =
+ yasm__xstrdup(object->deb_filename);
+
+ /* Force all syms for win64 because they're needed for relocations.
+ * FIXME: Not *all* syms need to be output, only the ones needed for
+ * relocation. Find a way to do that someday.
+ */
+ all_syms |= objfmt_coff->win64;
+
+ info.strtab_offset = 4;
+ info.object = object;
+ info.objfmt_coff = objfmt_coff;
+ info.errwarns = errwarns;
+ info.f = f;
+ info.buf = yasm_xmalloc(REGULAR_OUTBUF_SIZE);
+
+ /* Allocate space for headers by seeking forward */
+ if (fseek(f, (long)(20+40*(objfmt_coff->parse_scnum-1)), SEEK_SET) < 0) {
+ yasm__fatal(N_("could not seek on output file"));
+ /*@notreached@*/
+ return;
+ }
+
+ /* Finalize symbol table (assign index to each symbol) */
+ info.indx = 0;
+ info.all_syms = all_syms;
+ yasm_symtab_traverse(object->symtab, &info, coff_objfmt_count_sym);
+ symtab_count = info.indx;
+
+ /* Section data/relocs */
+ if (COFF_SET_VMA) {
+ /* If we're setting the VMA, we need to do a first section pass to
+ * determine each section's addr value before actually outputting
+ * relocations, as a relocation's section address is added into the
+ * addends in the generated code.
+ */
+ info.addr = 0;
+ if (yasm_object_sections_traverse(object, &info,
+ coff_objfmt_set_section_addr))
+ return;
+ }
+ info.addr = 0;
+ if (yasm_object_sections_traverse(object, &info,
+ coff_objfmt_output_section))
+ return;
+
+ /* Symbol table */
+ pos = ftell(f);
+ if (pos == -1) {
+ yasm__fatal(N_("could not get file position on output file"));
+ /*@notreached@*/
+ return;
+ }
+ symtab_pos = (unsigned long)pos;
+ yasm_symtab_traverse(object->symtab, &info, coff_objfmt_output_sym);
+
+ /* String table */
+ yasm_fwrite_32_l(info.strtab_offset, f); /* total length */
+ yasm_object_sections_traverse(object, &info, coff_objfmt_output_sectstr);
+ yasm_symtab_traverse(object->symtab, &info, coff_objfmt_output_str);
+
+ /* Write headers */
+ if (fseek(f, 0, SEEK_SET) < 0) {
+ yasm__fatal(N_("could not seek on output file"));
+ /*@notreached@*/
+ return;
+ }
+
+ localbuf = info.buf;
+ YASM_WRITE_16_L(localbuf, objfmt_coff->machine); /* magic number */
+ YASM_WRITE_16_L(localbuf, objfmt_coff->parse_scnum-1);/* number of sects */
+ if (getenv("YASM_TEST_SUITE"))
+ ts = 0;
+ else
+ ts = (unsigned long)time(NULL);
+ YASM_WRITE_32_L(localbuf, ts); /* time/date stamp */
+ YASM_WRITE_32_L(localbuf, symtab_pos); /* file ptr to symtab */
+ YASM_WRITE_32_L(localbuf, symtab_count); /* number of symtabs */
+ YASM_WRITE_16_L(localbuf, 0); /* size of optional header (none) */
+ /* flags */
+ flags = 0;
+ if (strcmp(yasm_dbgfmt_keyword(object->dbgfmt), "null")==0)
+ flags = COFF_F_LNNO;
+ if (!all_syms)
+ flags |= COFF_F_LSYMS;
+ if (objfmt_coff->machine != COFF_MACHINE_AMD64)
+ flags |= COFF_F_AR32WR;
+ YASM_WRITE_16_L(localbuf, flags);
+ fwrite(info.buf, 20, 1, f);
+
+ yasm_object_sections_traverse(object, &info, coff_objfmt_output_secthead);
+
+ yasm_xfree(info.buf);
+}
+
+static void
+coff_objfmt_destroy(yasm_objfmt *objfmt)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)objfmt;
+ if (objfmt_coff->filesym_data->aux[0].fname)
+ yasm_xfree(objfmt_coff->filesym_data->aux[0].fname);
+ if (objfmt_coff->unwind)
+ yasm_win64__uwinfo_destroy(objfmt_coff->unwind);
+ yasm_xfree(objfmt);
+}
+
+static yasm_section *
+coff_objfmt_add_default_section(yasm_object *object)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ yasm_section *retval;
+ coff_section_data *csd;
+ int isnew;
+
+ retval = yasm_object_get_general(object, ".text", 16, 1, 0, &isnew, 0);
+ if (isnew) {
+ csd = yasm_section_get_data(retval, &coff_section_data_cb);
+ csd->flags = COFF_STYP_TEXT;
+ if (objfmt_coff->win32)
+ csd->flags |= COFF_STYP_EXECUTE | COFF_STYP_READ;
+ yasm_section_set_default(retval, 1);
+ }
+ return retval;
+}
+
+struct coff_section_switch_data {
+ int isdefault;
+ int gasflags;
+ unsigned long flags;
+ unsigned long flags2;
+ /*@only@*/ /*@null@*/ yasm_intnum *align_intn;
+};
+
+/* GAS-style flags */
+static int
+coff_helper_gasflags(void *obj, yasm_valparam *vp, unsigned long line, void *d,
+ /*@unused@*/ uintptr_t arg)
+{
+ struct coff_section_switch_data *data =
+ (struct coff_section_switch_data *)d;
+ int alloc = 0, load = 0, readonly = 0, code = 0, datasect = 0;
+ int shared = 0;
+ const char *s = yasm_vp_string(vp);
+ size_t i;
+
+ if (!s) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("non-string section attribute"));
+ return -1;
+ }
+
+ /* For GAS, default to read/write data */
+ if (data->isdefault)
+ data->flags = COFF_STYP_TEXT | COFF_STYP_READ | COFF_STYP_WRITE;
+
+ for (i=0; i<strlen(s); i++) {
+ switch (s[i]) {
+ case 'a':
+ break;
+ case 'b':
+ alloc = 1;
+ load = 0;
+ break;
+ case 'n':
+ load = 0;
+ break;
+ case 's':
+ shared = 1;
+ /*@fallthrough@*/
+ case 'd':
+ datasect = 1;
+ load = 1;
+ readonly = 0;
+ break;
+ case 'x':
+ code = 1;
+ load = 1;
+ break;
+ case 'r':
+ datasect = 1;
+ load = 1;
+ readonly = 1;
+ break;
+ case 'w':
+ readonly = 0;
+ break;
+ default:
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("unrecognized section attribute: `%c'"),
+ s[i]);
+ }
+ }
+
+ if (code)
+ data->flags = COFF_STYP_TEXT | COFF_STYP_EXECUTE | COFF_STYP_READ;
+ else if (datasect)
+ data->flags = COFF_STYP_DATA | COFF_STYP_READ | COFF_STYP_WRITE;
+ else if (readonly)
+ data->flags = COFF_STYP_DATA | COFF_STYP_READ;
+ else if (load)
+ data->flags = COFF_STYP_TEXT;
+ else if (alloc)
+ data->flags = COFF_STYP_BSS;
+
+ if (shared)
+ data->flags |= COFF_STYP_SHARED;
+
+ data->gasflags = 1;
+ return 0;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_section *
+coff_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
+ /*@unused@*/ /*@null@*/
+ yasm_valparamhead *objext_valparams,
+ unsigned long line)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ yasm_valparam *vp;
+ yasm_section *retval;
+ int isnew;
+ int iscode = 0;
+ int flags_override;
+ const char *sectname;
+ char *realname;
+ int resonly = 0;
+ unsigned long align = 0;
+ coff_section_data *csd;
+
+ struct coff_section_switch_data data;
+
+ static const yasm_dir_help help[] = {
+ { "code", 0, yasm_dir_helper_flag_set,
+ offsetof(struct coff_section_switch_data, flags),
+ COFF_STYP_TEXT | COFF_STYP_EXECUTE | COFF_STYP_READ },
+ { "text", 0, yasm_dir_helper_flag_set,
+ offsetof(struct coff_section_switch_data, flags),
+ COFF_STYP_TEXT | COFF_STYP_EXECUTE | COFF_STYP_READ },
+ { "data", 0, yasm_dir_helper_flag_set,
+ offsetof(struct coff_section_switch_data, flags),
+ COFF_STYP_DATA | COFF_STYP_READ | COFF_STYP_WRITE },
+ { "rdata", 0, yasm_dir_helper_flag_set,
+ offsetof(struct coff_section_switch_data, flags),
+ COFF_STYP_DATA | COFF_STYP_READ },
+ { "bss", 0, yasm_dir_helper_flag_set,
+ offsetof(struct coff_section_switch_data, flags),
+ COFF_STYP_BSS | COFF_STYP_READ | COFF_STYP_WRITE },
+ { "info", 0, yasm_dir_helper_flag_set,
+ offsetof(struct coff_section_switch_data, flags),
+ COFF_STYP_INFO | COFF_STYP_DISCARD | COFF_STYP_READ },
+ { "gasflags", 1, coff_helper_gasflags, 0, 0 },
+ /* Win32 only below this point */
+ { "discard", 0, yasm_dir_helper_flag_or,
+ offsetof(struct coff_section_switch_data, flags), COFF_STYP_DISCARD},
+ { "nodiscard", 0, yasm_dir_helper_flag_and,
+ offsetof(struct coff_section_switch_data, flags), COFF_STYP_DISCARD},
+ { "cache", 0, yasm_dir_helper_flag_and,
+ offsetof(struct coff_section_switch_data, flags), COFF_STYP_NOCACHE},
+ { "nocache", 0, yasm_dir_helper_flag_or,
+ offsetof(struct coff_section_switch_data, flags), COFF_STYP_NOCACHE},
+ { "page", 0, yasm_dir_helper_flag_and,
+ offsetof(struct coff_section_switch_data, flags), COFF_STYP_NOPAGE },
+ { "nopage", 0, yasm_dir_helper_flag_or,
+ offsetof(struct coff_section_switch_data, flags), COFF_STYP_NOPAGE },
+ { "share", 0, yasm_dir_helper_flag_or,
+ offsetof(struct coff_section_switch_data, flags), COFF_STYP_SHARED },
+ { "noshare", 0, yasm_dir_helper_flag_and,
+ offsetof(struct coff_section_switch_data, flags), COFF_STYP_SHARED },
+ { "execute", 0, yasm_dir_helper_flag_or,
+ offsetof(struct coff_section_switch_data, flags), COFF_STYP_EXECUTE},
+ { "noexecute", 0, yasm_dir_helper_flag_and,
+ offsetof(struct coff_section_switch_data, flags), COFF_STYP_EXECUTE},
+ { "read", 0, yasm_dir_helper_flag_or,
+ offsetof(struct coff_section_switch_data, flags), COFF_STYP_READ },
+ { "noread", 0, yasm_dir_helper_flag_and,
+ offsetof(struct coff_section_switch_data, flags), COFF_STYP_READ },
+ { "write", 0, yasm_dir_helper_flag_or,
+ offsetof(struct coff_section_switch_data, flags), COFF_STYP_WRITE },
+ { "nowrite", 0, yasm_dir_helper_flag_and,
+ offsetof(struct coff_section_switch_data, flags), COFF_STYP_WRITE },
+ { "base", 0, yasm_dir_helper_flag_and,
+ offsetof(struct coff_section_switch_data, flags2), COFF_FLAG_NOBASE},
+ { "nobase", 0, yasm_dir_helper_flag_or,
+ offsetof(struct coff_section_switch_data, flags2), COFF_FLAG_NOBASE},
+ { "align", 1, yasm_dir_helper_intn,
+ offsetof(struct coff_section_switch_data, align_intn), 0 }
+ };
+
+ vp = yasm_vps_first(valparams);
+ sectname = yasm_vp_string(vp);
+ if (!sectname)
+ return NULL;
+ vp = yasm_vps_next(vp);
+
+ data.isdefault = 0;
+ data.gasflags = 0;
+ data.flags = 0;
+ data.flags2 = 0;
+ data.align_intn = NULL;
+
+ if (strcmp(sectname, ".data") == 0) {
+ data.flags = COFF_STYP_DATA | COFF_STYP_READ | COFF_STYP_WRITE;
+ if (objfmt_coff->win32) {
+ if (objfmt_coff->machine == COFF_MACHINE_AMD64)
+ align = 16;
+ else
+ align = 4;
+ }
+ } else if (strcmp(sectname, ".bss") == 0) {
+ data.flags = COFF_STYP_BSS | COFF_STYP_READ | COFF_STYP_WRITE;
+ if (objfmt_coff->win32) {
+ if (objfmt_coff->machine == COFF_MACHINE_AMD64)
+ align = 16;
+ else
+ align = 4;
+ }
+ resonly = 1;
+ } else if (strcmp(sectname, ".text") == 0) {
+ data.flags = COFF_STYP_TEXT | COFF_STYP_EXECUTE | COFF_STYP_READ;
+ if (objfmt_coff->win32)
+ align = 16;
+ } else if (strcmp(sectname, ".rdata") == 0
+ || strncmp(sectname, ".rodata", 7) == 0
+ || strncmp(sectname, ".rdata$", 7) == 0) {
+ data.flags = COFF_STYP_DATA | COFF_STYP_READ;
+ if (objfmt_coff->win32)
+ align = 8;
+ else
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("Standard COFF does not support read-only data sections"));
+ } else if (strcmp(sectname, ".drectve") == 0) {
+ data.flags = COFF_STYP_INFO;
+ if (objfmt_coff->win32)
+ data.flags |= COFF_STYP_DISCARD | COFF_STYP_READ;
+ } else if (objfmt_coff->win64 && strcmp(sectname, ".pdata") == 0) {
+ data.flags = COFF_STYP_DATA | COFF_STYP_READ;
+ align = 4;
+ data.flags2 = COFF_FLAG_NOBASE;
+ } else if (objfmt_coff->win64 && strcmp(sectname, ".xdata") == 0) {
+ data.flags = COFF_STYP_DATA | COFF_STYP_READ;
+ align = 8;
+ data.flags2 = COFF_FLAG_NOBASE;
+ } else if (objfmt_coff->win32 && strcmp(sectname, ".sxdata") == 0) {
+ data.flags = COFF_STYP_INFO;
+ } else if (strcmp(sectname, ".comment") == 0) {
+ data.flags = COFF_STYP_INFO | COFF_STYP_DISCARD | COFF_STYP_READ;
+ } else if (yasm__strncasecmp(sectname, ".debug", 6)==0) {
+ data.flags = COFF_STYP_DATA | COFF_STYP_DISCARD | COFF_STYP_READ;
+ align = 1;
+ } else {
+ /* Default to code, but set a flag so if we get gasflags we can
+ * change it (NASM and GAS have different defaults).
+ */
+ data.isdefault = 1;
+ data.flags = COFF_STYP_TEXT | COFF_STYP_EXECUTE | COFF_STYP_READ;
+ }
+
+ flags_override = yasm_dir_helper(object, vp, line, help,
+ objfmt_coff->win32 ? NELEMS(help) : 7,
+ &data, yasm_dir_helper_valparam_warn);
+ if (flags_override < 0)
+ return NULL; /* error occurred */
+
+ if (data.flags & COFF_STYP_EXECUTE)
+ iscode = 1;
+
+ if (!objfmt_coff->win32)
+ data.flags &= ~COFF_STYP_WIN32_MASK;
+
+ if (data.align_intn) {
+ align = yasm_intnum_get_uint(data.align_intn);
+ yasm_intnum_destroy(data.align_intn);
+
+ /* Alignments must be a power of two. */
+ if (!is_exp2(align)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("argument to `%s' is not a power of two"),
+ "align");
+ return NULL;
+ }
+
+ /* Check to see if alignment is supported size */
+ if (align > 8192) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("Win32 does not support alignments > 8192"));
+ return NULL;
+ }
+ }
+
+ realname = yasm__xstrdup(sectname);
+ if (strlen(sectname) > 8 && !objfmt_coff->win32) {
+ /* win32 format supports >8 character section names in object
+ * files via "/nnnn" (where nnnn is decimal offset into string table),
+ * so only warn for regular COFF.
+ */
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("COFF section names limited to 8 characters: truncating"));
+ realname[8] = '\0';
+ }
+
+ retval = yasm_object_get_general(object, realname, align, iscode,
+ resonly, &isnew, line);
+ yasm_xfree(realname);
+
+ csd = yasm_section_get_data(retval, &coff_section_data_cb);
+
+ if (isnew || yasm_section_is_default(retval)) {
+ yasm_section_set_default(retval, 0);
+ csd->flags = data.flags;
+ csd->flags2 = data.flags2;
+ yasm_section_set_align(retval, align, line);
+ } else if (flags_override && !data.gasflags)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("section flags ignored on section redeclaration"));
+ return retval;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+coff_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ return NULL;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+win64_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ if (yasm__strcasecmp(name, "imagebase") == 0) {
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ return objfmt_coff->ssym_imagebase;
+ }
+ return NULL;
+}
+
+static void
+coff_section_data_destroy(void *data)
+{
+ yasm_xfree(data);
+}
+
+static void
+coff_section_data_print(void *data, FILE *f, int indent_level)
+{
+ coff_section_data *csd = (coff_section_data *)data;
+
+ fprintf(f, "%*ssym=\n", indent_level, "");
+ yasm_symrec_print(csd->sym, f, indent_level+1);
+ fprintf(f, "%*sscnum=%d\n", indent_level, "", csd->scnum);
+ fprintf(f, "%*sflags=", indent_level, "");
+ switch (csd->flags & COFF_STYP_STD_MASK) {
+ case COFF_STYP_TEXT:
+ fprintf(f, "TEXT");
+ break;
+ case COFF_STYP_DATA:
+ fprintf(f, "DATA");
+ break;
+ case COFF_STYP_BSS:
+ fprintf(f, "BSS");
+ break;
+ default:
+ fprintf(f, "UNKNOWN");
+ break;
+ }
+ fprintf(f, "\n%*saddr=0x%lx\n", indent_level, "", csd->addr);
+ fprintf(f, "%*sscnptr=0x%lx\n", indent_level, "", csd->scnptr);
+ fprintf(f, "%*ssize=%ld\n", indent_level, "", csd->size);
+ fprintf(f, "%*srelptr=0x%lx\n", indent_level, "", csd->relptr);
+ fprintf(f, "%*snreloc=%ld\n", indent_level, "", csd->nreloc);
+ fprintf(f, "%*srelocs:\n", indent_level, "");
+}
+
+static void
+coff_symrec_data_destroy(void *data)
+{
+ yasm_xfree(data);
+}
+
+static void
+coff_symrec_data_print(void *data, FILE *f, int indent_level)
+{
+ coff_symrec_data *csd = (coff_symrec_data *)data;
+
+ fprintf(f, "%*ssymtab index=%lu\n", indent_level, "", csd->index);
+ fprintf(f, "%*ssclass=%d\n", indent_level, "", csd->sclass);
+}
+
+static void
+dir_export(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp;
+ /*@null@*/ const char *symname;
+ int isnew;
+ yasm_section *sect;
+ yasm_datavalhead dvs;
+
+ /* Reference exported symbol (to generate error if not declared) */
+ vp = yasm_vps_first(valparams);
+ symname = yasm_vp_id(vp);
+ if (symname)
+ yasm_symtab_use(object->symtab, symname, line);
+ else {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("argument to EXPORT must be symbol name"));
+ return;
+ }
+
+ /* Add to end of linker directives */
+ sect = yasm_object_get_general(object, ".drectve", 0, 0, 0, &isnew, line);
+
+ /* Initialize directive section if needed */
+ if (isnew) {
+ coff_section_data *csd;
+ csd = yasm_section_get_data(sect, &coff_section_data_cb);
+ csd->flags = COFF_STYP_INFO | COFF_STYP_DISCARD | COFF_STYP_READ;
+ }
+
+ /* Add text as data bytecode */
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_string(yasm__xstrdup("-export:"),
+ strlen("-export:")));
+ yasm_dvs_append(&dvs, yasm_dv_create_string(yasm__xstrdup(symname),
+ strlen(symname)));
+ yasm_dvs_append(&dvs, yasm_dv_create_string(yasm__xstrdup(" "), 1));
+ yasm_section_bcs_append(sect, yasm_bc_create_data(&dvs, 1, 0, NULL, line));
+}
+
+static void
+dir_safeseh(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp;
+ /*@null@*/ const char *symname;
+ yasm_symrec *sym;
+ int isnew;
+ yasm_section *sect;
+
+ /* Reference symbol (to generate error if not declared).
+ * Also, symbol must be externally visible, so force it.
+ */
+ vp = yasm_vps_first(valparams);
+ symname = yasm_vp_id(vp);
+ if (symname) {
+ coff_symrec_data *sym_data;
+ sym = yasm_symtab_use(object->symtab, symname, line);
+ sym_data = yasm_symrec_get_data(sym, &coff_symrec_data_cb);
+ if (!sym_data) {
+ sym_data = coff_objfmt_sym_set_data(sym, COFF_SCL_NULL, 0,
+ COFF_SYMTAB_AUX_NONE);
+ }
+ sym_data->forcevis = 1;
+ sym_data->type = 0x20; /* function */
+ } else {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("argument to SAFESEH must be symbol name"));
+ return;
+ }
+
+ /*
+ * Add symbol number to end of .sxdata section.
+ */
+
+ sect = yasm_object_get_general(object, ".sxdata", 0, 0, 0, &isnew, line);
+
+ /* Initialize sxdata section if needed */
+ if (isnew) {
+ coff_section_data *csd;
+ csd = yasm_section_get_data(sect, &coff_section_data_cb);
+ csd->flags = COFF_STYP_INFO;
+ }
+
+ /* Add as sxdata bytecode */
+ yasm_section_bcs_append(sect,
+ yasm_bc_create_common(&win32_sxdata_bc_callback,
+ sym, line));
+}
+
+static void
+win32_sxdata_bc_destroy(void *contents)
+{
+ /* Contents is just the symbol pointer, so no need to delete */
+}
+
+static void
+win32_sxdata_bc_print(const void *contents, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+static int
+win32_sxdata_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ bc->len += 4;
+ return 0;
+}
+
+static int
+win32_sxdata_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ yasm_symrec *sym = (yasm_symrec *)bc->contents;
+ unsigned char *buf = *bufp;
+ coff_symrec_data *csymd;
+
+ csymd = yasm_symrec_get_data(sym, &coff_symrec_data_cb);
+ if (!csymd)
+ yasm_internal_error(N_("coff: no symbol data for SAFESEH symbol"));
+
+ YASM_WRITE_32_L(buf, csymd->index);
+
+ *bufp = buf;
+ return 0;
+}
+
+static void
+dir_ident(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ yasm_valparamhead sect_vps;
+ yasm_datavalhead dvs;
+ yasm_section *comment;
+ const char *sectname;
+ yasm_valparam *vp, *vp2;
+
+ /* Accept, but do nothing with empty ident */
+ if (!valparams)
+ return;
+
+ vp = yasm_vps_first(valparams);
+ if (!vp)
+ return;
+
+ if (objfmt_coff->win32) {
+ /* Put ident data into .comment section for COFF, or .rdata$zzz
+ * to be compatible with the GNU linker, which doesn't ignore
+ * .comment (see binutils/gas/config/obj-coff.c:476-502).
+ */
+ sectname = ".rdata$zzz";
+ } else {
+ sectname = ".comment";
+ }
+ yasm_vps_initialize(&sect_vps);
+ vp2 = yasm_vp_create_id(NULL, yasm__xstrdup(sectname), '\0');
+ yasm_vps_append(&sect_vps, vp2);
+ comment = coff_objfmt_section_switch(object, &sect_vps, NULL, line);
+ yasm_vps_delete(&sect_vps);
+
+ /* To match GAS output, if the comment section is empty, put an
+ * initial 0 byte in the section.
+ */
+ if (yasm_section_bcs_first(comment) == yasm_section_bcs_last(comment)) {
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(
+ yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(0)),
+ line)));
+ yasm_section_bcs_append(comment,
+ yasm_bc_create_data(&dvs, 1, 0, object->arch, line));
+ }
+
+ yasm_dvs_initialize(&dvs);
+ do {
+ const char *s = yasm_vp_string(vp);
+ if (!s) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_(".comment requires string parameters"));
+ yasm_dvs_delete(&dvs);
+ return;
+ }
+ yasm_dvs_append(&dvs,
+ yasm_dv_create_string(yasm__xstrdup(s), strlen(s)));
+ } while ((vp = yasm_vps_next(vp)));
+
+ yasm_section_bcs_append(comment,
+ yasm_bc_create_data(&dvs, 1, 1, object->arch, line));
+}
+
+static void
+dir_secrel32(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_datavalhead dvs;
+ yasm_valparam *vp;
+
+ if (!object->cur_section) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_(".secrel32 can only be used inside of a section"));
+ return;
+ }
+
+ vp = yasm_vps_first(valparams);
+ yasm_dvs_initialize(&dvs);
+ do {
+ yasm_expr *e = yasm_vp_expr(vp, object->symtab, line);
+ yasm_dataval *dv;
+ if (!e) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_(".secrel32 requires expressions"));
+ yasm_dvs_delete(&dvs);
+ return;
+ }
+ dv = yasm_dv_create_expr(e);
+ yasm_dv_get_value(dv)->section_rel = 1;
+ yasm_dvs_append(&dvs, dv);
+ } while ((vp = yasm_vps_next(vp)));
+
+ yasm_section_bcs_append(object->cur_section,
+ yasm_bc_create_data(&dvs, 4, 0, object->arch, line));
+}
+
+static void
+dir_def(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ yasm_valparam *vp;
+ const char *symname;
+ yasm_symrec *sym;
+ coff_symrec_data *sym_data;
+
+ if (objfmt_coff->def_sym) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_(".def pseudo-op used inside of .def/.endef; ignored"));
+ return;
+ }
+
+ vp = yasm_vps_first(valparams);
+ symname = yasm_vp_id(vp);
+ if (!symname) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("argument to SAFESEH must be symbol name"));
+ return;
+ }
+
+ sym = yasm_symtab_use(object->symtab, symname, line);
+ sym_data = yasm_symrec_get_data(sym, &coff_symrec_data_cb);
+ if (!sym_data) {
+ sym_data = coff_objfmt_sym_set_data(sym, COFF_SCL_NULL, 0,
+ COFF_SYMTAB_AUX_NONE);
+ }
+ objfmt_coff->def_sym = sym_data;
+}
+
+static void
+dir_scl(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ yasm_intnum *intn = NULL;
+
+ if (!objfmt_coff->def_sym) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("%s pseudo-op used outside of .def/.endef; ignored"),
+ ".scl");
+ return;
+ }
+
+ if (yasm_dir_helper_intn(object, yasm_vps_first(valparams), line,
+ &intn, 0) < 0)
+ return;
+ if (!intn)
+ return;
+ objfmt_coff->def_sym->sclass = yasm_intnum_get_uint(intn);
+ yasm_intnum_destroy(intn);
+}
+
+static void
+dir_type(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ yasm_intnum *intn = NULL;
+
+ if (!objfmt_coff->def_sym) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("%s pseudo-op used outside of .def/.endef; ignored"),
+ ".type");
+ return;
+ }
+
+ if (yasm_dir_helper_intn(object, yasm_vps_first(valparams), line,
+ &intn, 0) < 0)
+ return;
+ if (!intn)
+ return;
+ objfmt_coff->def_sym->type = yasm_intnum_get_uint(intn);
+ yasm_intnum_destroy(intn);
+}
+
+static void
+dir_endef(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ if (!objfmt_coff->def_sym) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_(".endef pseudo-op used before .def; ignored"));
+ return;
+ }
+ objfmt_coff->def_sym = NULL;
+}
+
+static void
+dir_proc_frame(yasm_object *object, /*@null@*/ yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ const char *name = yasm_vp_id(vp);
+
+ if (objfmt_coff->proc_frame) {
+ yasm_error_set_xref(objfmt_coff->proc_frame,
+ N_("previous procedure started here"));
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("nested procedures not supported (didn't use [ENDPROC_FRAME]?)"));
+ return;
+ }
+ objfmt_coff->proc_frame = line;
+ objfmt_coff->done_prolog = 0;
+ objfmt_coff->unwind = yasm_win64__uwinfo_create();
+ objfmt_coff->unwind->proc = yasm_symtab_use(object->symtab, name, line);
+
+ /* Optional error handler */
+ vp = yasm_vps_next(vp);
+ if (!vp || !(name = yasm_vp_id(vp)))
+ return;
+ objfmt_coff->unwind->ehandler =
+ yasm_symtab_use(object->symtab, name, line);
+}
+
+static int
+procframe_checkstate(yasm_objfmt_coff *objfmt_coff, const char *dirname)
+{
+ if (!objfmt_coff->proc_frame) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("[%s] without preceding [PROC_FRAME]"), dirname);
+ return 0;
+ }
+ if (objfmt_coff->done_prolog) {
+ yasm_error_set_xref(objfmt_coff->done_prolog,
+ N_("prologue ended here"));
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] after end of prologue"),
+ dirname);
+ return 0;
+ }
+ if (!objfmt_coff->unwind)
+ yasm_internal_error(N_("unwind info not present"));
+ return 1;
+}
+
+/* Get current assembly position.
+ * XXX: There should be a better way to do this.
+ */
+static yasm_symrec *
+get_curpos(yasm_object *object, const char *dirname, unsigned long line)
+{
+ if (!object->cur_section) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("[%s] can only be used inside of a section"),
+ dirname);
+ return NULL;
+ }
+ return yasm_symtab_define_curpos(object->symtab, "$",
+ yasm_section_bcs_last(object->cur_section), line);
+}
+
+static void
+dir_pushreg(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ coff_unwind_code *code;
+ const uintptr_t *reg;
+
+ if (!procframe_checkstate(objfmt_coff, "PUSHREG"))
+ return;
+
+ if (vp->type != YASM_PARAM_EXPR ||
+ !(reg = yasm_expr_get_reg(&vp->param.e, 0))) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("[%s] requires a register as the first parameter"),
+ "PUSHREG");
+ return;
+ }
+
+ /* Generate a PUSH_NONVOL unwind code. */
+ code = yasm_xmalloc(sizeof(coff_unwind_code));
+ code->proc = objfmt_coff->unwind->proc;
+ code->loc = get_curpos(object, "PUSHREG", line);
+ code->opcode = UWOP_PUSH_NONVOL;
+ code->info = (unsigned int)(*reg & 0xF);
+ yasm_value_initialize(&code->off, NULL, 0);
+ SLIST_INSERT_HEAD(&objfmt_coff->unwind->codes, code, link);
+}
+
+static void
+dir_setframe(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ coff_unwind_code *code;
+ const uintptr_t *reg;
+ yasm_expr *off = NULL;
+
+ if (!procframe_checkstate(objfmt_coff, "SETFRAME"))
+ return;
+
+ if (vp->type != YASM_PARAM_EXPR ||
+ !(reg = yasm_expr_get_reg(&vp->param.e, 0))) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("[%s] requires a register as the first parameter"),
+ "SETFRAME");
+ return;
+ }
+
+ vp = yasm_vps_next(vp);
+ if (vp)
+ off = yasm_vp_expr(vp, object->symtab, line);
+
+ /* Set the frame fields in the unwind info */
+ objfmt_coff->unwind->framereg = (unsigned long)(*reg);
+ yasm_value_initialize(&objfmt_coff->unwind->frameoff, off, 8);
+
+ /* Generate a SET_FPREG unwind code */
+ code = yasm_xmalloc(sizeof(coff_unwind_code));
+ code->proc = objfmt_coff->unwind->proc;
+ code->loc = get_curpos(object, "SETFRAME", line);
+ code->opcode = UWOP_SET_FPREG;
+ code->info = (unsigned int)(*reg & 0xF);
+ yasm_value_initialize(&code->off, off ? yasm_expr_copy(off) : NULL, 8);
+ SLIST_INSERT_HEAD(&objfmt_coff->unwind->codes, code, link);
+}
+
+static void
+dir_allocstack(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ /*@null@*/ /*@only@*/ yasm_expr *size;
+ coff_unwind_code *code;
+
+ if (!procframe_checkstate(objfmt_coff, "ALLOCSTACK"))
+ return;
+
+ size = yasm_vp_expr(vp, object->symtab, line);
+ if (!size) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires a size"),
+ "ALLOCSTACK");
+ return;
+ }
+
+ /* Generate an ALLOC_SMALL unwind code; this will get enlarged to an
+ * ALLOC_LARGE if necessary.
+ */
+ code = yasm_xmalloc(sizeof(coff_unwind_code));
+ code->proc = objfmt_coff->unwind->proc;
+ code->loc = get_curpos(object, "ALLOCSTACK", line);
+ code->opcode = UWOP_ALLOC_SMALL;
+ code->info = 0;
+ yasm_value_initialize(&code->off, size, 7);
+ SLIST_INSERT_HEAD(&objfmt_coff->unwind->codes, code, link);
+}
+
+static void
+dir_save_common(yasm_object *object, yasm_valparamhead *valparams,
+ unsigned long line, const char *name, int op)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ coff_unwind_code *code;
+ const uintptr_t *reg;
+ /*@only@*/ /*@null@*/ yasm_expr *offset;
+
+ if (!procframe_checkstate(objfmt_coff, name))
+ return;
+
+ if (vp->type != YASM_PARAM_EXPR ||
+ !(reg = yasm_expr_get_reg(&vp->param.e, 0))) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("[%s] requires a register as the first parameter"),
+ name);
+ return;
+ }
+
+ vp = yasm_vps_next(vp);
+ offset = yasm_vp_expr(vp, object->symtab, line);
+ if (!offset) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("[%s] requires an offset as the second parameter"),
+ name);
+ return;
+ }
+
+ /* Generate a SAVE_XXX unwind code; this will get enlarged to a
+ * SAVE_XXX_FAR if necessary.
+ */
+ code = yasm_xmalloc(sizeof(coff_unwind_code));
+ code->proc = objfmt_coff->unwind->proc;
+ code->loc = get_curpos(object, name, line);
+ code->opcode = op;
+ code->info = (unsigned int)(*reg & 0xF);
+ yasm_value_initialize(&code->off, offset, 16);
+ SLIST_INSERT_HEAD(&objfmt_coff->unwind->codes, code, link);
+}
+
+static void
+dir_savereg(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ dir_save_common(object, valparams, line, "SAVEREG", UWOP_SAVE_NONVOL);
+}
+
+static void
+dir_savexmm128(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ dir_save_common(object, valparams, line, "SAVEXMM128", UWOP_SAVE_XMM128);
+}
+
+static void
+dir_pushframe(yasm_object *object, /*@null@*/ yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ coff_unwind_code *code;
+
+ if (!procframe_checkstate(objfmt_coff, "PUSHFRAME"))
+ return;
+
+ /* Generate a PUSH_MACHFRAME unwind code. If there's any parameter,
+ * we set info to 1. Otherwise we set info to 0.
+ */
+ code = yasm_xmalloc(sizeof(coff_unwind_code));
+ code->proc = objfmt_coff->unwind->proc;
+ code->loc = get_curpos(object, "PUSHFRAME", line);
+ code->opcode = UWOP_PUSH_MACHFRAME;
+ code->info = vp != NULL;
+ yasm_value_initialize(&code->off, NULL, 0);
+ SLIST_INSERT_HEAD(&objfmt_coff->unwind->codes, code, link);
+}
+
+static void
+dir_endprolog(yasm_object *object, /*@null@*/ yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ if (!procframe_checkstate(objfmt_coff, "ENDPROLOG"))
+ return;
+ objfmt_coff->done_prolog = line;
+
+ objfmt_coff->unwind->prolog = get_curpos(object, "ENDPROLOG", line);
+}
+
+static void
+dir_endproc_frame(yasm_object *object, /*@null@*/ yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ yasm_section *sect;
+ coff_section_data *csd;
+ yasm_datavalhead dvs;
+ int isnew;
+ /*@dependent@*/ yasm_symrec *curpos, *unwindpos, *proc_sym, *xdata_sym;
+
+ if (!objfmt_coff->proc_frame) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("[%s] without preceding [PROC_FRAME]"),
+ "ENDPROC_FRAME");
+ return;
+ }
+ if (!objfmt_coff->done_prolog) {
+ yasm_error_set_xref(objfmt_coff->proc_frame,
+ N_("procedure started here"));
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("ended procedure without ending prologue"),
+ "ENDPROC_FRAME");
+ objfmt_coff->proc_frame = 0;
+ yasm_win64__uwinfo_destroy(objfmt_coff->unwind);
+ objfmt_coff->unwind = NULL;
+ return;
+ }
+ if (!objfmt_coff->unwind)
+ yasm_internal_error(N_("unwind info not present"));
+
+ proc_sym = objfmt_coff->unwind->proc;
+
+ curpos = get_curpos(object, "ENDPROC_FRAME", line);
+
+ /*
+ * Add unwind info to end of .xdata section.
+ */
+
+ sect = yasm_object_get_general(object, ".xdata", 0, 0, 0, &isnew, line);
+
+ /* Initialize xdata section if needed */
+ if (isnew) {
+ csd = yasm_section_get_data(sect, &coff_section_data_cb);
+ csd->flags = COFF_STYP_DATA | COFF_STYP_READ;
+ yasm_section_set_align(sect, 8, line);
+ }
+
+ /* Get current position in .xdata section */
+ unwindpos = yasm_symtab_define_curpos(object->symtab, "$",
+ yasm_section_bcs_last(sect), line);
+ /* Get symbol for .xdata as we'll want to reference it with WRT */
+ csd = yasm_section_get_data(sect, &coff_section_data_cb);
+ xdata_sym = csd->sym;
+
+ /* Add unwind info. Use line number of start of procedure. */
+ yasm_win64__unwind_generate(sect, objfmt_coff->unwind,
+ objfmt_coff->proc_frame);
+ objfmt_coff->unwind = NULL; /* generate keeps the unwind pointer */
+
+ /*
+ * Add function lookup to end of .pdata section.
+ */
+
+ sect = yasm_object_get_general(object, ".pdata", 0, 0, 0, &isnew, line);
+
+ /* Initialize pdata section if needed */
+ if (isnew) {
+ csd = yasm_section_get_data(sect, &coff_section_data_cb);
+ csd->flags = COFF_STYP_DATA | COFF_STYP_READ;
+ csd->flags2 = COFF_FLAG_NOBASE;
+ yasm_section_set_align(sect, 4, line);
+ }
+
+ /* Add function structure as data bytecode */
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(
+ yasm_expr_create_ident(yasm_expr_sym(proc_sym), line)));
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(
+ yasm_expr_create(YASM_EXPR_WRT, yasm_expr_sym(curpos),
+ yasm_expr_sym(proc_sym), line)));
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(
+ yasm_expr_create(YASM_EXPR_WRT, yasm_expr_sym(unwindpos),
+ yasm_expr_sym(xdata_sym), line)));
+ yasm_section_bcs_append(sect, yasm_bc_create_data(&dvs, 4, 0, NULL, line));
+
+ objfmt_coff->proc_frame = 0;
+ objfmt_coff->done_prolog = 0;
+}
+
+/* Define valid debug formats to use with this object format */
+static const char *coff_objfmt_dbgfmt_keywords[] = {
+ "null",
+ "dwarf2",
+ NULL
+};
+
+static const yasm_directive coff_objfmt_directives[] = {
+ { ".ident", "gas", dir_ident, YASM_DIR_ANY },
+ { "ident", "nasm", dir_ident, YASM_DIR_ANY },
+ { ".def", "gas", dir_def, YASM_DIR_ID_REQUIRED },
+ { ".endef", "gas", dir_endef, YASM_DIR_ANY },
+ { ".scl", "gas", dir_scl, YASM_DIR_ARG_REQUIRED },
+ { ".type", "gas", dir_type, YASM_DIR_ARG_REQUIRED },
+ { ".secrel32", "gas", dir_secrel32, YASM_DIR_ARG_REQUIRED },
+ { NULL, NULL, NULL, 0 }
+};
+
+/* Define objfmt structure -- see objfmt.h for details */
+yasm_objfmt_module yasm_coff_LTX_objfmt = {
+ "COFF (DJGPP)",
+ "coff",
+ "o",
+ 32,
+ 0,
+ coff_objfmt_dbgfmt_keywords,
+ "null",
+ coff_objfmt_directives,
+ NULL, /* no standard macros */
+ coff_objfmt_create,
+ coff_objfmt_output,
+ coff_objfmt_destroy,
+ coff_objfmt_add_default_section,
+ coff_objfmt_init_new_section,
+ coff_objfmt_section_switch,
+ coff_objfmt_get_special_sym
+};
+
+/* Define valid debug formats to use with this object format */
+static const char *winXX_objfmt_dbgfmt_keywords[] = {
+ "null",
+ "dwarf2",
+ "cv8",
+ NULL
+};
+
+static const yasm_directive win32_objfmt_directives[] = {
+ { ".ident", "gas", dir_ident, YASM_DIR_ANY },
+ { "ident", "nasm", dir_ident, YASM_DIR_ANY },
+ { ".def", "gas", dir_def, YASM_DIR_ID_REQUIRED },
+ { ".endef", "gas", dir_endef, YASM_DIR_ANY },
+ { ".scl", "gas", dir_scl, YASM_DIR_ARG_REQUIRED },
+ { ".type", "gas", dir_type, YASM_DIR_ARG_REQUIRED },
+ { ".secrel32", "gas", dir_secrel32, YASM_DIR_ARG_REQUIRED },
+ { ".export", "gas", dir_export, YASM_DIR_ID_REQUIRED },
+ { "export", "nasm", dir_export, YASM_DIR_ID_REQUIRED },
+ { ".safeseh", "gas", dir_safeseh, YASM_DIR_ID_REQUIRED },
+ { "safeseh", "nasm", dir_safeseh, YASM_DIR_ID_REQUIRED },
+ { NULL, NULL, NULL, 0 }
+};
+
+static const char *win32_nasm_stdmac[] = {
+ "%imacro export 1+.nolist",
+ "[export %1]",
+ "%endmacro",
+ "%imacro safeseh 1+.nolist",
+ "[safeseh %1]",
+ "%endmacro",
+ NULL
+};
+
+static const yasm_stdmac win32_objfmt_stdmacs[] = {
+ { "nasm", "nasm", win32_nasm_stdmac },
+ { NULL, NULL, NULL }
+};
+
+/* Define objfmt structure -- see objfmt.h for details */
+yasm_objfmt_module yasm_win32_LTX_objfmt = {
+ "Win32",
+ "win32",
+ "obj",
+ 32,
+ 1,
+ winXX_objfmt_dbgfmt_keywords,
+ "null",
+ win32_objfmt_directives,
+ win32_objfmt_stdmacs,
+ win32_objfmt_create,
+ coff_objfmt_output,
+ coff_objfmt_destroy,
+ coff_objfmt_add_default_section,
+ coff_objfmt_init_new_section,
+ coff_objfmt_section_switch,
+ coff_objfmt_get_special_sym
+};
+
+static const yasm_directive win64_objfmt_directives[] = {
+ { ".ident", "gas", dir_ident, YASM_DIR_ANY },
+ { "ident", "nasm", dir_ident, YASM_DIR_ANY },
+ { ".def", "gas", dir_def, YASM_DIR_ID_REQUIRED },
+ { ".endef", "gas", dir_endef, YASM_DIR_ANY },
+ { ".scl", "gas", dir_scl, YASM_DIR_ARG_REQUIRED },
+ { ".type", "gas", dir_type, YASM_DIR_ARG_REQUIRED },
+ { ".secrel32", "gas", dir_secrel32, YASM_DIR_ARG_REQUIRED },
+ { ".export", "gas", dir_export, YASM_DIR_ID_REQUIRED },
+ { "export", "nasm", dir_export, YASM_DIR_ID_REQUIRED },
+ { ".proc_frame", "gas", dir_proc_frame, YASM_DIR_ID_REQUIRED },
+ { "proc_frame", "nasm", dir_proc_frame, YASM_DIR_ID_REQUIRED },
+ { ".pushreg", "gas", dir_pushreg, YASM_DIR_ARG_REQUIRED },
+ { "pushreg", "nasm", dir_pushreg, YASM_DIR_ARG_REQUIRED },
+ { ".setframe", "gas", dir_setframe, YASM_DIR_ARG_REQUIRED },
+ { "setframe", "nasm", dir_setframe, YASM_DIR_ARG_REQUIRED },
+ { ".allocstack", "gas", dir_allocstack, YASM_DIR_ARG_REQUIRED },
+ { "allocstack", "nasm", dir_allocstack, YASM_DIR_ARG_REQUIRED },
+ { ".savereg", "gas", dir_savereg, YASM_DIR_ARG_REQUIRED },
+ { "savereg", "nasm", dir_savereg, YASM_DIR_ARG_REQUIRED },
+ { ".savexmm128", "gas", dir_savexmm128, YASM_DIR_ARG_REQUIRED },
+ { "savexmm128", "nasm", dir_savexmm128, YASM_DIR_ARG_REQUIRED },
+ { ".pushframe", "gas", dir_pushframe, YASM_DIR_ANY },
+ { "pushframe", "nasm", dir_pushframe, YASM_DIR_ANY },
+ { ".endprolog", "gas", dir_endprolog, YASM_DIR_ANY },
+ { "endprolog", "nasm", dir_endprolog, YASM_DIR_ANY },
+ { ".endproc_frame", "gas", dir_endproc_frame, YASM_DIR_ANY },
+ { "endproc_frame", "nasm", dir_endproc_frame, YASM_DIR_ANY },
+ { NULL, NULL, NULL, 0 }
+};
+
+#include "win64-nasm.c"
+#include "win64-gas.c"
+
+static const yasm_stdmac win64_objfmt_stdmacs[] = {
+ { "nasm", "nasm", win64_nasm_stdmac },
+ { "gas", "nasm", win64_gas_stdmac },
+ { NULL, NULL, NULL }
+};
+
+/* Define objfmt structure -- see objfmt.h for details */
+yasm_objfmt_module yasm_win64_LTX_objfmt = {
+ "Win64",
+ "win64",
+ "obj",
+ 64,
+ 1,
+ winXX_objfmt_dbgfmt_keywords,
+ "null",
+ win64_objfmt_directives,
+ win64_objfmt_stdmacs,
+ win64_objfmt_create,
+ coff_objfmt_output,
+ coff_objfmt_destroy,
+ coff_objfmt_add_default_section,
+ coff_objfmt_init_new_section,
+ coff_objfmt_section_switch,
+ win64_objfmt_get_special_sym
+};
+yasm_objfmt_module yasm_x64_LTX_objfmt = {
+ "Win64",
+ "x64",
+ "obj",
+ 64,
+ 1,
+ winXX_objfmt_dbgfmt_keywords,
+ "null",
+ win64_objfmt_directives,
+ win64_objfmt_stdmacs,
+ win64_objfmt_create,
+ coff_objfmt_output,
+ coff_objfmt_destroy,
+ coff_objfmt_add_default_section,
+ coff_objfmt_init_new_section,
+ coff_objfmt_section_switch,
+ win64_objfmt_get_special_sym
+};
diff --git a/contrib/tools/yasm/modules/objfmts/coff/coff-objfmt.h b/contrib/tools/yasm/modules/objfmts/coff/coff-objfmt.h
new file mode 100644
index 0000000000..10d88a0982
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/coff/coff-objfmt.h
@@ -0,0 +1,77 @@
+/*
+ * COFF (DJGPP) object format
+ *
+ * Copyright (C) 2007 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.
+ */
+#ifndef COFF_OBJFMT_H
+#define COFF_OBJFMT_H
+
+typedef struct coff_unwind_code {
+ SLIST_ENTRY(coff_unwind_code) link;
+
+ /*@dependent@*/ yasm_symrec *proc; /* Start of procedure */
+ /*@dependent@*/ yasm_symrec *loc; /* Location of operation */
+ /* Unwind operation code */
+ enum {
+ UWOP_PUSH_NONVOL = 0,
+ UWOP_ALLOC_LARGE = 1,
+ UWOP_ALLOC_SMALL = 2,
+ UWOP_SET_FPREG = 3,
+ UWOP_SAVE_NONVOL = 4,
+ UWOP_SAVE_NONVOL_FAR = 5,
+ UWOP_SAVE_XMM128 = 8,
+ UWOP_SAVE_XMM128_FAR = 9,
+ UWOP_PUSH_MACHFRAME = 10
+ } opcode;
+ unsigned int info; /* Operation info */
+ yasm_value off; /* Offset expression (used for some codes) */
+} coff_unwind_code;
+
+typedef struct coff_unwind_info {
+ /*@dependent@*/ yasm_symrec *proc; /* Start of procedure */
+ /*@dependent@*/ yasm_symrec *prolog; /* End of prologue */
+
+ /*@null@*/ /*@dependent@*/ yasm_symrec *ehandler; /* Error handler */
+
+ unsigned long framereg; /* Frame register */
+ yasm_value frameoff; /* Frame offset */
+
+ /* Linked list of codes, in decreasing location offset order.
+ * Inserting at the head of this list during assembly naturally results
+ * in this sorting.
+ */
+ SLIST_HEAD(coff_unwind_code_head, coff_unwind_code) codes;
+
+ /* These aren't used until inside of generate. */
+ yasm_value prolog_size;
+ yasm_value codes_count;
+} coff_unwind_info;
+
+coff_unwind_info *yasm_win64__uwinfo_create(void);
+void yasm_win64__uwinfo_destroy(coff_unwind_info *info);
+void yasm_win64__unwind_generate(yasm_section *xdata,
+ /*@only@*/ coff_unwind_info *info,
+ unsigned long line);
+
+#endif
diff --git a/contrib/tools/yasm/modules/objfmts/coff/win64-except.c b/contrib/tools/yasm/modules/objfmts/coff/win64-except.c
new file mode 100644
index 0000000000..8c8ecbbc49
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/coff/win64-except.c
@@ -0,0 +1,559 @@
+/*
+ * Win64 structured exception handling support
+ *
+ * Copyright (C) 2007 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 <util.h>
+
+#include <libyasm.h>
+
+#include "coff-objfmt.h"
+
+
+#define UNW_FLAG_EHANDLER 0x01
+#define UNW_FLAG_UHANDLER 0x02
+#define UNW_FLAG_CHAININFO 0x04
+
+/* Bytecode callback function prototypes */
+static void win64_uwinfo_bc_destroy(void *contents);
+static void win64_uwinfo_bc_print(const void *contents, FILE *f,
+ int indent_level);
+static void win64_uwinfo_bc_finalize(yasm_bytecode *bc,
+ yasm_bytecode *prev_bc);
+static int win64_uwinfo_bc_calc_len
+ (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
+static int win64_uwinfo_bc_expand(yasm_bytecode *bc, int span, long old_val,
+ long new_val, /*@out@*/ long *neg_thres,
+ /*@out@*/ long *pos_thres);
+static int win64_uwinfo_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+static void win64_uwcode_bc_destroy(void *contents);
+static void win64_uwcode_bc_print(const void *contents, FILE *f,
+ int indent_level);
+static void win64_uwcode_bc_finalize(yasm_bytecode *bc,
+ yasm_bytecode *prev_bc);
+static int win64_uwcode_bc_calc_len
+ (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
+static int win64_uwcode_bc_expand(yasm_bytecode *bc, int span, long old_val,
+ long new_val, /*@out@*/ long *neg_thres,
+ /*@out@*/ long *pos_thres);
+static int win64_uwcode_bc_tobytes
+ (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ /*@null@*/ yasm_output_reloc_func output_reloc);
+
+/* Bytecode callback structures */
+static const yasm_bytecode_callback win64_uwinfo_bc_callback = {
+ win64_uwinfo_bc_destroy,
+ win64_uwinfo_bc_print,
+ win64_uwinfo_bc_finalize,
+ NULL,
+ win64_uwinfo_bc_calc_len,
+ win64_uwinfo_bc_expand,
+ win64_uwinfo_bc_tobytes,
+ 0
+};
+
+static const yasm_bytecode_callback win64_uwcode_bc_callback = {
+ win64_uwcode_bc_destroy,
+ win64_uwcode_bc_print,
+ win64_uwcode_bc_finalize,
+ NULL,
+ win64_uwcode_bc_calc_len,
+ win64_uwcode_bc_expand,
+ win64_uwcode_bc_tobytes,
+ 0
+};
+
+
+coff_unwind_info *
+yasm_win64__uwinfo_create(void)
+{
+ coff_unwind_info *info = yasm_xmalloc(sizeof(coff_unwind_info));
+ info->proc = NULL;
+ info->prolog = NULL;
+ info->ehandler = NULL;
+ info->framereg = 0;
+ /* Frameoff is really a 4-bit value, scaled by 16 */
+ yasm_value_initialize(&info->frameoff, NULL, 8);
+ SLIST_INIT(&info->codes);
+ yasm_value_initialize(&info->prolog_size, NULL, 8);
+ yasm_value_initialize(&info->codes_count, NULL, 8);
+ return info;
+}
+
+void
+yasm_win64__uwinfo_destroy(coff_unwind_info *info)
+{
+ coff_unwind_code *code;
+
+ yasm_value_delete(&info->frameoff);
+ yasm_value_delete(&info->prolog_size);
+ yasm_value_delete(&info->codes_count);
+
+ while (!SLIST_EMPTY(&info->codes)) {
+ code = SLIST_FIRST(&info->codes);
+ SLIST_REMOVE_HEAD(&info->codes, link);
+ yasm_value_delete(&code->off);
+ yasm_xfree(code);
+ }
+ yasm_xfree(info);
+}
+
+void
+yasm_win64__unwind_generate(yasm_section *xdata, coff_unwind_info *info,
+ unsigned long line)
+{
+ yasm_bytecode *infobc, *codebc = NULL;
+ coff_unwind_code *code;
+
+ /* 4-byte align the start of unwind info */
+ yasm_section_bcs_append(xdata, yasm_bc_create_align(
+ yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(4)),
+ line),
+ NULL, NULL, NULL, line));
+
+ /* Prolog size = end of prolog - start of procedure */
+ yasm_value_initialize(&info->prolog_size,
+ yasm_expr_create(YASM_EXPR_SUB, yasm_expr_sym(info->prolog),
+ yasm_expr_sym(info->proc), line),
+ 8);
+
+ /* Unwind info */
+ infobc = yasm_bc_create_common(&win64_uwinfo_bc_callback, info, line);
+ yasm_section_bcs_append(xdata, infobc);
+
+ /* Code array */
+ SLIST_FOREACH(code, &info->codes, link) {
+ codebc = yasm_bc_create_common(&win64_uwcode_bc_callback, code,
+ yasm_symrec_get_def_line(code->loc));
+ yasm_section_bcs_append(xdata, codebc);
+ }
+
+ /* Avoid double-free (by code destroy and uwinfo destroy). */
+ SLIST_INIT(&info->codes);
+
+ /* Number of codes = (Last code - end of info) >> 1 */
+ if (!codebc) {
+ yasm_value_initialize(&info->codes_count,
+ yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(0)),
+ line),
+ 8);
+ } else {
+ yasm_value_initialize(&info->codes_count,
+ yasm_expr_create(YASM_EXPR_SHR, yasm_expr_expr(
+ yasm_expr_create(YASM_EXPR_SUB, yasm_expr_precbc(codebc),
+ yasm_expr_precbc(infobc), line)),
+ yasm_expr_int(yasm_intnum_create_uint(1)), line),
+ 8);
+ }
+
+ /* 4-byte align */
+ yasm_section_bcs_append(xdata, yasm_bc_create_align(
+ yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(4)),
+ line),
+ NULL, NULL, NULL, line));
+
+ /* Exception handler, if present. Use data bytecode. */
+ if (info->ehandler) {
+ yasm_datavalhead dvs;
+
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(
+ yasm_expr_create_ident(yasm_expr_sym(info->ehandler), line)));
+ yasm_section_bcs_append(xdata,
+ yasm_bc_create_data(&dvs, 4, 0, NULL, line));
+ }
+}
+
+static void
+win64_uwinfo_bc_destroy(void *contents)
+{
+ yasm_win64__uwinfo_destroy((coff_unwind_info *)contents);
+}
+
+static void
+win64_uwinfo_bc_print(const void *contents, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+static void
+win64_uwinfo_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ coff_unwind_info *info = (coff_unwind_info *)bc->contents;
+
+ if (yasm_value_finalize(&info->prolog_size, prev_bc))
+ yasm_internal_error(N_("prolog size expression too complex"));
+
+ if (yasm_value_finalize(&info->codes_count, prev_bc))
+ yasm_internal_error(N_("codes count expression too complex"));
+
+ if (yasm_value_finalize(&info->frameoff, prev_bc))
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("frame offset expression too complex"));
+}
+
+static int
+win64_uwinfo_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ coff_unwind_info *info = (coff_unwind_info *)bc->contents;
+ /*@only@*/ /*@null@*/ yasm_intnum *intn;
+ long intv;
+
+ /* Want to make sure prolog size and codes count doesn't exceed
+ * byte-size, and scaled frame offset doesn't exceed 4 bits.
+ */
+ add_span(add_span_data, bc, 1, &info->prolog_size, 0, 255);
+ add_span(add_span_data, bc, 2, &info->codes_count, 0, 255);
+
+ intn = yasm_value_get_intnum(&info->frameoff, bc, 0);
+ if (intn) {
+ intv = yasm_intnum_get_int(intn);
+ if (intv < 0 || intv > 240)
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("frame offset of %ld bytes, must be between 0 and 240"),
+ intv);
+ else if ((intv & 0xF) != 0)
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("frame offset of %ld is not a multiple of 16"), intv);
+ yasm_intnum_destroy(intn);
+ } else
+ add_span(add_span_data, bc, 3, &info->frameoff, 0, 240);
+
+ bc->len += 4;
+ return 0;
+}
+
+static int
+win64_uwinfo_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
+{
+ coff_unwind_info *info = (coff_unwind_info *)bc->contents;
+ switch (span) {
+ case 1:
+ yasm_error_set_xref(yasm_symrec_get_def_line(info->prolog),
+ N_("prologue ended here"));
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("prologue %ld bytes, must be <256"), new_val);
+ return -1;
+ case 2:
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("%ld unwind codes, maximum of 255"), new_val);
+ return -1;
+ case 3:
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("frame offset of %ld bytes, must be between 0 and 240"),
+ new_val);
+ return -1;
+ default:
+ yasm_internal_error(N_("unrecognized span id"));
+ }
+ return 0;
+}
+
+static int
+win64_uwinfo_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ coff_unwind_info *info = (coff_unwind_info *)bc->contents;
+ unsigned char *buf = *bufp;
+ /*@only@*/ /*@null@*/ yasm_intnum *frameoff;
+ long intv;
+
+ /* Version and flags */
+ if (info->ehandler)
+ YASM_WRITE_8(buf, 1 | (UNW_FLAG_EHANDLER << 3));
+ else
+ YASM_WRITE_8(buf, 1);
+
+ /* Size of prolog */
+ output_value(&info->prolog_size, buf, 1, (unsigned long)(buf-bufstart),
+ bc, 1, d);
+ buf += 1;
+
+ /* Count of codes */
+ output_value(&info->codes_count, buf, 1, (unsigned long)(buf-bufstart),
+ bc, 1, d);
+ buf += 1;
+
+ /* Frame register and offset */
+ frameoff = yasm_value_get_intnum(&info->frameoff, bc, 1);
+ if (!frameoff) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("frame offset expression too complex"));
+ return 1;
+ }
+ intv = yasm_intnum_get_int(frameoff);
+ if (intv < 0 || intv > 240)
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("frame offset of %ld bytes, must be between 0 and 240"), intv);
+ else if ((intv & 0xF) != 0)
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("frame offset of %ld is not a multiple of 16"), intv);
+
+ YASM_WRITE_8(buf, ((unsigned long)intv & 0xF0) | (info->framereg & 0x0F));
+ yasm_intnum_destroy(frameoff);
+
+ *bufp = buf;
+ return 0;
+}
+
+static void
+win64_uwcode_bc_destroy(void *contents)
+{
+ coff_unwind_code *code = (coff_unwind_code *)contents;
+ yasm_value_delete(&code->off);
+ yasm_xfree(contents);
+}
+
+static void
+win64_uwcode_bc_print(const void *contents, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+static void
+win64_uwcode_bc_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
+{
+ coff_unwind_code *code = (coff_unwind_code *)bc->contents;
+ if (yasm_value_finalize(&code->off, prev_bc))
+ yasm_error_set(YASM_ERROR_VALUE, N_("offset expression too complex"));
+}
+
+static int
+win64_uwcode_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
+ void *add_span_data)
+{
+ coff_unwind_code *code = (coff_unwind_code *)bc->contents;
+ int span = 0;
+ /*@only@*/ /*@null@*/ yasm_intnum *intn;
+ long intv;
+ long low, high, mask;
+
+ bc->len += 2; /* Prolog offset, code, and info */
+
+ switch (code->opcode) {
+ case UWOP_PUSH_NONVOL:
+ case UWOP_SET_FPREG:
+ case UWOP_PUSH_MACHFRAME:
+ /* always 1 node */
+ return 0;
+ case UWOP_ALLOC_SMALL:
+ case UWOP_ALLOC_LARGE:
+ /* Start with smallest, then work our way up as necessary */
+ code->opcode = UWOP_ALLOC_SMALL;
+ code->info = 0;
+ span = 1; low = 8; high = 128; mask = 0x7;
+ break;
+ case UWOP_SAVE_NONVOL:
+ case UWOP_SAVE_NONVOL_FAR:
+ /* Start with smallest, then work our way up as necessary */
+ code->opcode = UWOP_SAVE_NONVOL;
+ bc->len += 2; /* Scaled offset */
+ span = 2;
+ low = 0;
+ high = 8*64*1024-8; /* 16-bit field, *8 scaling */
+ mask = 0x7;
+ break;
+ case UWOP_SAVE_XMM128:
+ case UWOP_SAVE_XMM128_FAR:
+ /* Start with smallest, then work our way up as necessary */
+ code->opcode = UWOP_SAVE_XMM128;
+ bc->len += 2; /* Scaled offset */
+ span = 3;
+ low = 0;
+ high = 16*64*1024-16; /* 16-bit field, *16 scaling */
+ mask = 0xF;
+ break;
+ default:
+ yasm_internal_error(N_("unrecognied unwind opcode"));
+ /*@unreached@*/
+ return 0;
+ }
+
+ intn = yasm_value_get_intnum(&code->off, bc, 0);
+ if (intn) {
+ intv = yasm_intnum_get_int(intn);
+ if (intv > high) {
+ /* Expand it ourselves here if we can and we're already larger */
+ if (win64_uwcode_bc_expand(bc, span, intv, intv, &low, &high) > 0)
+ add_span(add_span_data, bc, span, &code->off, low, high);
+ }
+ if (intv < low)
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("negative offset not allowed"));
+ if ((intv & mask) != 0)
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("offset of %ld is not a multiple of %ld"), intv, mask+1);
+ yasm_intnum_destroy(intn);
+ } else
+ add_span(add_span_data, bc, span, &code->off, low, high);
+ return 0;
+}
+
+static int
+win64_uwcode_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
+ /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
+{
+ coff_unwind_code *code = (coff_unwind_code *)bc->contents;
+
+ if (new_val < 0) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("negative offset not allowed"));
+ return -1;
+ }
+
+ if (span == 1) {
+ /* 3 stages: SMALL, LARGE and info=0, LARGE and info=1 */
+ if (code->opcode == UWOP_ALLOC_LARGE && code->info == 1)
+ yasm_internal_error(N_("expansion on already largest alloc"));
+
+ if (code->opcode == UWOP_ALLOC_SMALL && new_val > 128) {
+ /* Overflowed small size */
+ code->opcode = UWOP_ALLOC_LARGE;
+ bc->len += 2;
+ }
+ if (new_val <= 8*64*1024-8) {
+ /* Still can grow one more size */
+ *pos_thres = 8*64*1024-8;
+ return 1;
+ }
+ /* We're into the largest size */
+ code->info = 1;
+ bc->len += 2;
+ } else if (code->opcode == UWOP_SAVE_NONVOL && span == 2) {
+ code->opcode = UWOP_SAVE_NONVOL_FAR;
+ bc->len += 2;
+ } else if (code->opcode == UWOP_SAVE_XMM128 && span == 3) {
+ code->opcode = UWOP_SAVE_XMM128_FAR;
+ bc->len += 2;
+ }
+ return 0;
+}
+
+static int
+win64_uwcode_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
+ unsigned char *bufstart, void *d,
+ yasm_output_value_func output_value,
+ yasm_output_reloc_func output_reloc)
+{
+ coff_unwind_code *code = (coff_unwind_code *)bc->contents;
+ unsigned char *buf = *bufp;
+ yasm_value val;
+ unsigned int size;
+ int shift;
+ long intv, low, high, mask;
+ yasm_intnum *intn;
+
+ /* Offset in prolog */
+ yasm_value_initialize(&val,
+ yasm_expr_create(YASM_EXPR_SUB, yasm_expr_sym(code->loc),
+ yasm_expr_sym(code->proc), bc->line),
+ 8);
+ output_value(&val, buf, 1, (unsigned long)(buf-bufstart), bc, 1, d);
+ buf += 1;
+ yasm_value_delete(&val);
+
+ /* Offset value */
+ switch (code->opcode) {
+ case UWOP_PUSH_NONVOL:
+ case UWOP_SET_FPREG:
+ case UWOP_PUSH_MACHFRAME:
+ /* just 1 node, no offset; write opcode and info and we're done */
+ YASM_WRITE_8(buf, (code->info << 4) | (code->opcode & 0xF));
+ *bufp = buf;
+ return 0;
+ case UWOP_ALLOC_SMALL:
+ /* 1 node, but offset stored in info */
+ size = 0; low = 8; high = 128; shift = 3; mask = 0x7;
+ break;
+ case UWOP_ALLOC_LARGE:
+ if (code->info == 0) {
+ size = 2; low = 136; high = 8*64*1024-8; shift = 3;
+ } else {
+ size = 4; low = high = 0; shift = 0;
+ }
+ mask = 0x7;
+ break;
+ case UWOP_SAVE_NONVOL:
+ size = 2; low = 0; high = 8*64*1024-8; shift = 3; mask = 0x7;
+ break;
+ case UWOP_SAVE_XMM128:
+ size = 2; low = 0; high = 16*64*1024-16; shift = 4; mask = 0xF;
+ break;
+ case UWOP_SAVE_NONVOL_FAR:
+ size = 4; low = high = 0; shift = 0; mask = 0x7;
+ break;
+ case UWOP_SAVE_XMM128_FAR:
+ size = 4; low = high = 0; shift = 0; mask = 0xF;
+ break;
+ default:
+ yasm_internal_error(N_("unrecognied unwind opcode"));
+ /*@unreached@*/
+ return 1;
+ }
+
+ /* Check for overflow */
+ intn = yasm_value_get_intnum(&code->off, bc, 1);
+ if (!intn) {
+ yasm_error_set(YASM_ERROR_VALUE, N_("offset expression too complex"));
+ return 1;
+ }
+ intv = yasm_intnum_get_int(intn);
+ if (size != 4 && (intv < low || intv > high)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("offset of %ld bytes, must be between %ld and %ld"),
+ intv, low, high);
+ return 1;
+ }
+ if ((intv & mask) != 0) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("offset of %ld is not a multiple of %ld"),
+ intv, mask+1);
+ return 1;
+ }
+
+ /* Stored value in info instead of extra code space */
+ if (size == 0)
+ code->info = (yasm_intnum_get_uint(intn) >> shift)-1;
+
+ /* Opcode and info */
+ YASM_WRITE_8(buf, (code->info << 4) | (code->opcode & 0xF));
+
+ if (size != 0) {
+ yasm_intnum_get_sized(intn, buf, size, size*8, -shift, 0, 1);
+ buf += size;
+ }
+
+ yasm_intnum_destroy(intn);
+
+ *bufp = buf;
+ return 0;
+}
diff --git a/contrib/tools/yasm/modules/objfmts/dbg/dbg-objfmt.c b/contrib/tools/yasm/modules/objfmts/dbg/dbg-objfmt.c
new file mode 100644
index 0000000000..bdf403c762
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/dbg/dbg-objfmt.c
@@ -0,0 +1,183 @@
+/*
+ * Debugging object format (used to debug object format module interface)
+ *
+ * Copyright (C) 2001-2007 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 <util.h>
+
+#include <libyasm.h>
+
+
+typedef struct yasm_objfmt_dbg {
+ yasm_objfmt_base objfmt; /* base structure */
+
+ FILE *dbgfile;
+} yasm_objfmt_dbg;
+
+yasm_objfmt_module yasm_dbg_LTX_objfmt;
+
+
+static yasm_objfmt *
+dbg_objfmt_create(yasm_object *object)
+{
+ yasm_objfmt_dbg *objfmt_dbg = yasm_xmalloc(sizeof(yasm_objfmt_dbg));
+
+ objfmt_dbg->objfmt.module = &yasm_dbg_LTX_objfmt;
+
+ objfmt_dbg->dbgfile = tmpfile();
+ if (!objfmt_dbg->dbgfile) {
+ fprintf(stderr, N_("could not open temporary file"));
+ return 0;
+ }
+ fprintf(objfmt_dbg->dbgfile, "create()\n");
+ return (yasm_objfmt *)objfmt_dbg;
+}
+
+static void
+dbg_objfmt_output(yasm_object *object, FILE *f, int all_syms,
+ yasm_errwarns *errwarns)
+{
+ yasm_objfmt_dbg *objfmt_dbg = (yasm_objfmt_dbg *)object->objfmt;
+ char buf[1024];
+ size_t i;
+
+ /* Copy temp file to real output file */
+ rewind(objfmt_dbg->dbgfile);
+ while ((i = fread(buf, 1, 1024, objfmt_dbg->dbgfile))) {
+ if (fwrite(buf, 1, i, f) != i)
+ break;
+ }
+
+ /* Reassign objfmt debug file to output file */
+ fclose(objfmt_dbg->dbgfile);
+ objfmt_dbg->dbgfile = f;
+
+ fprintf(objfmt_dbg->dbgfile, "output(f, object->\n");
+ yasm_object_print(object, objfmt_dbg->dbgfile, 1);
+ fprintf(objfmt_dbg->dbgfile, "%d)\n", all_syms);
+ fprintf(objfmt_dbg->dbgfile, " Symbol Table:\n");
+ yasm_symtab_print(object->symtab, objfmt_dbg->dbgfile, 1);
+}
+
+static void
+dbg_objfmt_destroy(yasm_objfmt *objfmt)
+{
+ yasm_objfmt_dbg *objfmt_dbg = (yasm_objfmt_dbg *)objfmt;
+ fprintf(objfmt_dbg->dbgfile, "destroy()\n");
+ yasm_xfree(objfmt);
+}
+
+static void
+dbg_objfmt_init_new_section(yasm_section *sect, unsigned long line)
+{
+ yasm_object *object = yasm_section_get_object(sect);
+ yasm_objfmt_dbg *objfmt_dbg = (yasm_objfmt_dbg *)object->objfmt;
+ fprintf(objfmt_dbg->dbgfile, "init_new_section(\"%s\", %lu)\n",
+ yasm_section_get_name(sect), line);
+ yasm_symtab_define_label(object->symtab, ".text",
+ yasm_section_bcs_first(sect), 1, 0);
+}
+
+static yasm_section *
+dbg_objfmt_add_default_section(yasm_object *object)
+{
+ yasm_objfmt_dbg *objfmt_dbg = (yasm_objfmt_dbg *)object->objfmt;
+ yasm_section *retval;
+ int isnew;
+
+ fprintf(objfmt_dbg->dbgfile, "add_default_section()\n");
+ retval = yasm_object_get_general(object, ".text", 0, 0, 0, &isnew, 0);
+ if (isnew) {
+ yasm_section_set_default(retval, 1);
+ }
+ return retval;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_section *
+dbg_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
+ /*@unused@*/ /*@null@*/
+ yasm_valparamhead *objext_valparams,
+ unsigned long line)
+{
+ yasm_objfmt_dbg *objfmt_dbg = (yasm_objfmt_dbg *)object->objfmt;
+ yasm_valparam *vp;
+ yasm_section *retval;
+ int isnew;
+
+ fprintf(objfmt_dbg->dbgfile, "section_switch(headp, ");
+ yasm_vps_print(valparams, objfmt_dbg->dbgfile);
+ fprintf(objfmt_dbg->dbgfile, ", ");
+ yasm_vps_print(objext_valparams, objfmt_dbg->dbgfile);
+ fprintf(objfmt_dbg->dbgfile, ", %lu), returning ", line);
+
+ vp = yasm_vps_first(valparams);
+ if (!yasm_vp_string(vp)) {
+ fprintf(objfmt_dbg->dbgfile, "NULL\n");
+ return NULL;
+ }
+ retval = yasm_object_get_general(object, yasm_vp_string(vp), 0, 0, 0,
+ &isnew, line);
+ if (isnew) {
+ fprintf(objfmt_dbg->dbgfile, "(new) ");
+ }
+ yasm_section_set_default(retval, 0);
+ fprintf(objfmt_dbg->dbgfile, "\"%s\" section\n", vp->val);
+ return retval;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+dbg_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ yasm_objfmt_dbg *objfmt_dbg = (yasm_objfmt_dbg *)object->objfmt;
+ fprintf(objfmt_dbg->dbgfile, "get_special_sym(object, \"%s\", \"%s\")\n",
+ name, parser);
+ return NULL;
+}
+
+/* Define valid debug formats to use with this object format */
+static const char *dbg_objfmt_dbgfmt_keywords[] = {
+ "null",
+ NULL
+};
+
+/* Define objfmt structure -- see objfmt.h for details */
+yasm_objfmt_module yasm_dbg_LTX_objfmt = {
+ "Trace of all info passed to object format module",
+ "dbg",
+ "dbg",
+ 32,
+ 0,
+ dbg_objfmt_dbgfmt_keywords,
+ "null",
+ NULL, /* no directives */
+ NULL, /* no standard macros */
+ dbg_objfmt_create,
+ dbg_objfmt_output,
+ dbg_objfmt_destroy,
+ dbg_objfmt_add_default_section,
+ dbg_objfmt_init_new_section,
+ dbg_objfmt_section_switch,
+ dbg_objfmt_get_special_sym
+};
diff --git a/contrib/tools/yasm/modules/objfmts/elf/elf-machine.h b/contrib/tools/yasm/modules/objfmts/elf/elf-machine.h
new file mode 100644
index 0000000000..ea6cb4ec94
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/elf/elf-machine.h
@@ -0,0 +1,108 @@
+/*
+ * ELF object machine specific format helpers
+ *
+ * Copyright (C) 2004-2007 Michael Urman
+ *
+ * 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.
+ */
+
+#ifndef ELF_MACHINE_H_INCLUDED
+#define ELF_MACHINE_H_INCLUDED
+
+#define YASM_WRITE_32I_L(p, i) do {\
+ assert(yasm_intnum_check_size(i, 32, 0, 2)); \
+ yasm_intnum_get_sized(i, p, 4, 32, 0, 0, 0); \
+ p += 4; } while (0)
+
+#define YASM_WRITE_64I_L(p, i) do {\
+ assert(yasm_intnum_check_size(i, 64, 0, 2)); \
+ yasm_intnum_get_sized(i, p, 8, 64, 0, 0, 0); \
+ p += 8; } while (0)
+
+#define YASM_WRITE_64C_L(p, hi, lo) do {\
+ YASM_WRITE_32_L(p, lo); \
+ YASM_WRITE_32_L(p, hi); } while (0)
+
+#define YASM_WRITE_64Z_L(p, i) YASM_WRITE_64C_L(p, 0, i)
+
+typedef int(*func_accepts_reloc)(size_t val, yasm_symrec *wrt);
+typedef void(*func_write_symtab_entry)(unsigned char *bufp,
+ elf_symtab_entry *entry,
+ yasm_intnum *value_intn,
+ yasm_intnum *size_intn);
+typedef void(*func_write_secthead)(unsigned char *bufp, elf_secthead *shead);
+typedef void(*func_write_secthead_rel)(unsigned char *bufp,
+ elf_secthead *shead,
+ elf_section_index symtab_idx,
+ elf_section_index sindex);
+
+typedef void(*func_handle_reloc_addend)(yasm_intnum *intn,
+ elf_reloc_entry *reloc,
+ unsigned long offset);
+typedef unsigned int(*func_map_reloc_info_to_type)(elf_reloc_entry *reloc);
+typedef void(*func_write_reloc)(unsigned char *bufp,
+ elf_reloc_entry *reloc,
+ unsigned int r_type,
+ unsigned int r_sym);
+typedef void (*func_write_proghead)(unsigned char **bufpp,
+ elf_offset secthead_addr,
+ unsigned long secthead_count,
+ elf_section_index shstrtab_index);
+
+enum {
+ ELF_SSYM_SYM_RELATIVE = 1 << 0,
+ ELF_SSYM_CURPOS_ADJUST = 1 << 1,
+ ELF_SSYM_THREAD_LOCAL = 1 << 2
+};
+
+typedef struct {
+ const char *name; /* should be something like ..name */
+ const int sym_rel; /* symbol or section-relative? */
+ const unsigned int reloc; /* relocation type */
+ const unsigned int size; /* legal data size */
+} elf_machine_ssym;
+
+struct elf_machine_handler {
+ const char *arch;
+ const char *machine;
+ const char *reloc_section_prefix;
+ const unsigned long symtab_entry_size;
+ const unsigned long symtab_entry_align;
+ const unsigned long reloc_entry_size;
+ const unsigned long secthead_size;
+ const unsigned long proghead_size;
+ func_accepts_reloc accepts_reloc;
+ func_write_symtab_entry write_symtab_entry;
+ func_write_secthead write_secthead;
+ func_write_secthead_rel write_secthead_rel;
+ func_handle_reloc_addend handle_reloc_addend;
+ func_map_reloc_info_to_type map_reloc_info_to_type;
+ func_write_reloc write_reloc;
+ func_write_proghead write_proghead;
+
+ elf_machine_ssym *ssyms; /* array of "special" syms */
+ const size_t num_ssyms; /* size of array */
+
+ const int bits; /* usually 32 or 64 */
+};
+
+#endif /* ELF_MACHINE_H_INCLUDED */
diff --git a/contrib/tools/yasm/modules/objfmts/elf/elf-objfmt.c b/contrib/tools/yasm/modules/objfmts/elf/elf-objfmt.c
new file mode 100644
index 0000000000..6874a1689f
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/elf/elf-objfmt.c
@@ -0,0 +1,1403 @@
+/*
+ * ELF object format
+ *
+ * Copyright (C) 2003-2007 Michael Urman
+ *
+ * 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 <util.h>
+
+/* Notes
+ *
+ * elf-objfmt uses the "linking" view of an ELF file:
+ * ELF header, an optional program header table, several sections,
+ * and a section header table
+ *
+ * The ELF header tells us some overall program information,
+ * where to find the PHT (if it exists) with phnum and phentsize,
+ * and where to find the SHT with shnum and shentsize
+ *
+ * The PHT doesn't seem to be generated by NASM for elftest.asm
+ *
+ * The SHT
+ *
+ * Each Section is spatially disjoint, and has exactly one SHT entry.
+ */
+
+#include <libyasm.h>
+
+#include "elf.h"
+#include "elf-machine.h"
+
+typedef struct yasm_objfmt_elf {
+ yasm_objfmt_base objfmt; /* base structure */
+
+ elf_symtab_head* elf_symtab; /* symbol table of indexed syms */
+ elf_strtab_head* shstrtab; /* section name strtab */
+ elf_strtab_head* strtab; /* strtab entries */
+
+ elf_strtab_entry *file_strtab_entry;/* .file symbol associated string */
+ yasm_symrec *dotdotsym; /* ..sym symbol */
+} yasm_objfmt_elf;
+
+typedef struct {
+ yasm_objfmt_elf *objfmt_elf;
+ yasm_errwarns *errwarns;
+ FILE *f;
+ elf_secthead *shead;
+ yasm_section *sect;
+ yasm_object *object;
+ unsigned long sindex;
+ yasm_symrec *GOT_sym;
+} elf_objfmt_output_info;
+
+typedef struct {
+ yasm_object *object;
+ yasm_objfmt_elf *objfmt_elf;
+ yasm_errwarns *errwarns;
+ int local_names;
+} build_symtab_info;
+
+yasm_objfmt_module yasm_elf_LTX_objfmt;
+yasm_objfmt_module yasm_elf32_LTX_objfmt;
+yasm_objfmt_module yasm_elf64_LTX_objfmt;
+yasm_objfmt_module yasm_elfx32_LTX_objfmt;
+
+
+static elf_symtab_entry *
+elf_objfmt_symtab_append(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym,
+ elf_section_index sectidx, elf_symbol_binding bind,
+ elf_symbol_type type, elf_symbol_vis vis,
+ yasm_expr *size, elf_address *value,
+ yasm_object *object)
+{
+ elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
+
+ if (!entry) {
+ /*@only@*/ char *symname = yasm_symrec_get_global_name(sym, object);
+ elf_strtab_entry *name =
+ elf_strtab_append_str(objfmt_elf->strtab, symname);
+ yasm_xfree(symname);
+ entry = elf_symtab_entry_create(name, sym);
+ yasm_symrec_add_data(sym, &elf_symrec_data, entry);
+ }
+
+ /* Only append to table if not already appended */
+ if (!elf_sym_in_table(entry))
+ elf_symtab_append_entry(objfmt_elf->elf_symtab, entry);
+
+ elf_symtab_set_nonzero(entry, NULL, sectidx, bind, type, size, value);
+ elf_sym_set_visibility(entry, vis);
+
+ return entry;
+}
+
+static elf_symtab_entry *
+build_extern(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
+{
+ yasm_valparamhead *objext_valparams =
+ yasm_symrec_get_objext_valparams(sym);
+
+ if (objext_valparams) {
+ yasm_valparam *vp = yasm_vps_first(objext_valparams);
+ for (; vp; vp = yasm_vps_next(vp)) {
+ if (yasm_vp_string(vp))
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("unrecognized symbol type `%s'"),
+ yasm_vp_string(vp));
+ }
+ }
+
+ return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL, 0,
+ STV_DEFAULT, NULL, NULL, object);
+}
+
+struct elf_build_global_data {
+ yasm_expr *size;
+ unsigned long type; /* elf_symbol_type */
+ elf_symbol_vis vis;
+ unsigned int vis_overrides;
+};
+
+static int
+elf_global_helper_valparam(void *obj, yasm_valparam *vp, unsigned long line,
+ void *d)
+
+{
+ struct elf_build_global_data *data = (struct elf_build_global_data *)d;
+ const char *s;
+
+ if (!vp->val && (s = yasm_vp_id(vp))) {
+ yasm_error_set(YASM_ERROR_TYPE, N_("unrecognized symbol type `%s'"),
+ s);
+ return -1;
+ } else if (!vp->val && vp->type == YASM_PARAM_EXPR && !data->size) {
+ data->size = yasm_expr_copy(vp->param.e);
+ return 0;
+ } else
+ return yasm_dir_helper_valparam_warn(obj, vp, line, d);
+}
+
+static int
+elf_global_helper_vis(void *obj, yasm_valparam *vp, unsigned long line,
+ void *d, uintptr_t vis)
+{
+ struct elf_build_global_data *data = (struct elf_build_global_data *)d;
+ data->vis = vis;
+ data->vis_overrides++;
+ return 0;
+}
+
+
+static elf_symtab_entry *
+build_global(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
+{
+ yasm_valparamhead *objext_valparams =
+ yasm_symrec_get_objext_valparams(sym);
+
+ struct elf_build_global_data data;
+
+ static const yasm_dir_help help[] = {
+ { "function", 0, yasm_dir_helper_flag_set,
+ offsetof(struct elf_build_global_data, type), STT_FUNC },
+ { "data", 0, yasm_dir_helper_flag_set,
+ offsetof(struct elf_build_global_data, type), STT_OBJECT },
+ { "object", 0, yasm_dir_helper_flag_set,
+ offsetof(struct elf_build_global_data, type), STT_OBJECT },
+ { "internal", 0, elf_global_helper_vis, 0, STV_INTERNAL },
+ { "hidden", 0, elf_global_helper_vis, 0, STV_HIDDEN },
+ { "protected", 0, elf_global_helper_vis, 0, STV_PROTECTED },
+ };
+
+ data.size = NULL;
+ data.type = 0;
+ data.vis = STV_DEFAULT;
+ data.vis_overrides = 0;
+
+ if (objext_valparams)
+ yasm_dir_helper(sym, yasm_vps_first(objext_valparams),
+ yasm_symrec_get_decl_line(sym), help, NELEMS(help),
+ &data, elf_global_helper_valparam);
+
+ if (data.vis_overrides > 1) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("More than one symbol visibility provided; using last"));
+ }
+
+ return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL,
+ data.type, data.vis, data.size, NULL,
+ object);
+}
+
+static /*@null@*/ elf_symtab_entry *
+build_common(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object)
+{
+ yasm_expr **size = yasm_symrec_get_common_size(sym);
+ yasm_valparamhead *objext_valparams =
+ yasm_symrec_get_objext_valparams(sym);
+ unsigned long addralign = 0;
+
+ if (objext_valparams) {
+ yasm_valparam *vp = yasm_vps_first(objext_valparams);
+ for (; vp; vp = yasm_vps_next(vp)) {
+ if (!vp->val) {
+ /*@only@*/ /*@null@*/ yasm_expr *align_expr;
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *align_intn;
+
+ if (!(align_expr = yasm_vp_expr(vp, object->symtab,
+ yasm_symrec_get_def_line(sym)))
+ || !(align_intn = yasm_expr_get_intnum(&align_expr, 0))) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("alignment constraint is not an integer"));
+ if (align_expr)
+ yasm_expr_destroy(align_expr);
+ return NULL;
+ }
+ addralign = yasm_intnum_get_uint(align_intn);
+ yasm_expr_destroy(align_expr);
+
+ /* Alignments must be a power of two. */
+ if (!is_exp2(addralign)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("alignment constraint is not a power of two"));
+ return NULL;
+ }
+ } else
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("Unrecognized qualifier `%s'"), vp->val);
+ }
+ }
+
+ return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_COMMON, STB_GLOBAL,
+ 0, STV_DEFAULT, *size, &addralign, object);
+}
+
+static int
+elf_objfmt_build_symtab(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ build_symtab_info *info = (build_symtab_info *)d;
+ yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+ yasm_sym_status status = yasm_symrec_get_status(sym);
+ elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
+ elf_address value=0;
+ yasm_section *sect=NULL;
+ yasm_bytecode *precbc=NULL;
+
+ assert(info != NULL);
+
+ if (vis & YASM_SYM_EXTERN) {
+ entry = build_extern(info->objfmt_elf, sym, info->object);
+ yasm_errwarn_propagate(info->errwarns,
+ yasm_symrec_get_decl_line(sym));
+ return 0;
+ }
+
+ if (vis & YASM_SYM_COMMON) {
+ entry = build_common(info->objfmt_elf, sym, info->object);
+ yasm_errwarn_propagate(info->errwarns,
+ yasm_symrec_get_decl_line(sym));
+ /* If the COMMON variable was actually defined, fall through. */
+ if (!(status & YASM_SYM_DEFINED))
+ return 0;
+ }
+
+ /* Ignore any undefined at this point. */
+ if (!(status & YASM_SYM_DEFINED))
+ return 0;
+
+ if (!yasm_symrec_get_label(sym, &precbc)) {
+ if (!yasm_symrec_get_equ(sym) && !yasm_symrec_is_abs(sym))
+ return 0;
+ precbc = NULL;
+ }
+
+ if (precbc)
+ sect = yasm_bc_get_section(precbc);
+
+ if (entry && elf_sym_in_table(entry))
+ ;
+ else if (vis & YASM_SYM_GLOBAL) {
+ entry = build_global(info->objfmt_elf, sym, info->object);
+ yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym));
+ } else {
+ int is_sect = 0;
+
+ /* Locals (except when debugging) do not need to be
+ * in the symbol table, unless they're a section.
+ */
+ if (sect &&
+ strcmp(yasm_symrec_get_name(sym), yasm_section_get_name(sect))==0)
+ is_sect = 1;
+#if 0
+ /* FIXME: to enable this we must have handling in place for special
+ * symbols.
+ */
+ if (!info->local_names && !is_sect)
+ return 0;
+#else
+ if (yasm_symrec_get_equ(sym) && !yasm_symrec_is_abs(sym))
+ return 0;
+#endif
+ entry = yasm_symrec_get_data(sym, &elf_symrec_data);
+ if (!entry) {
+ /*@only@*/ char *symname =
+ yasm_symrec_get_global_name(sym, info->object);
+ elf_strtab_entry *name = !info->local_names || is_sect ? NULL :
+ elf_strtab_append_str(info->objfmt_elf->strtab, symname);
+ yasm_xfree(symname);
+ entry = elf_symtab_entry_create(name, sym);
+ yasm_symrec_add_data(sym, &elf_symrec_data, entry);
+ }
+
+ if (!elf_sym_in_table(entry))
+ elf_symtab_insert_local_sym(info->objfmt_elf->elf_symtab, entry);
+
+ elf_symtab_set_nonzero(entry, sect, 0, STB_LOCAL,
+ is_sect ? STT_SECTION : 0, NULL, 0);
+
+ if (is_sect)
+ return 0;
+ }
+
+ if (precbc)
+ value = yasm_bc_next_offset(precbc);
+ elf_symtab_set_nonzero(entry, sect, 0, 0, 0, NULL, &value);
+
+ return 0;
+}
+
+static yasm_objfmt *
+elf_objfmt_create_common(yasm_object *object, yasm_objfmt_module *module,
+ int bits_pref,
+ const elf_machine_handler **elf_march_out)
+{
+ yasm_objfmt_elf *objfmt_elf = yasm_xmalloc(sizeof(yasm_objfmt_elf));
+ yasm_symrec *filesym;
+ elf_symtab_entry *entry;
+ const elf_machine_handler *elf_march;
+
+ objfmt_elf->objfmt.module = module;
+ elf_march = elf_set_arch(object->arch, object->symtab, bits_pref);
+ if (!elf_march) {
+ yasm_xfree(objfmt_elf);
+ return NULL;
+ }
+ if (elf_march_out)
+ *elf_march_out = elf_march;
+
+ objfmt_elf->shstrtab = elf_strtab_create();
+ objfmt_elf->strtab = elf_strtab_create();
+ objfmt_elf->elf_symtab = elf_symtab_create();
+
+ /* FIXME: misuse of NULL bytecode here; it works, but only barely. */
+ filesym = yasm_symtab_define_label(object->symtab, ".file", NULL, 0, 0);
+ if (!object->deb_filename) {
+ object->deb_filename = yasm_replace_path(
+ module->replace_map, module->replace_map_size,
+ object->src_filename, strlen(object->src_filename));
+ }
+ /* Put in current input filename; we'll replace it in output() */
+ objfmt_elf->file_strtab_entry =
+ elf_strtab_append_str(objfmt_elf->strtab, object->deb_filename);
+ entry = elf_symtab_entry_create(objfmt_elf->file_strtab_entry, filesym);
+ yasm_symrec_add_data(filesym, &elf_symrec_data, entry);
+ elf_symtab_set_nonzero(entry, NULL, SHN_ABS, STB_LOCAL, STT_FILE, NULL,
+ NULL);
+ elf_symtab_append_entry(objfmt_elf->elf_symtab, entry);
+
+ /* FIXME: misuse of NULL bytecode */
+ objfmt_elf->dotdotsym =
+ yasm_symtab_define_label(object->symtab, "..sym", NULL, 0, 0);
+
+ return (yasm_objfmt *)objfmt_elf;
+}
+
+static yasm_objfmt *
+elf_objfmt_create(yasm_object *object)
+{
+ const elf_machine_handler *elf_march;
+ yasm_objfmt *objfmt;
+ yasm_objfmt_elf *objfmt_elf;
+
+ objfmt = elf_objfmt_create_common(object, &yasm_elf_LTX_objfmt, 0,
+ &elf_march);
+ if (objfmt) {
+ objfmt_elf = (yasm_objfmt_elf *)objfmt;
+ /* Figure out which bitness of object format to use */
+ if (strcmp (elf_march->machine, "x32") == 0)
+ objfmt_elf->objfmt.module = &yasm_elfx32_LTX_objfmt;
+ else if (elf_march->bits == 32)
+ objfmt_elf->objfmt.module = &yasm_elf32_LTX_objfmt;
+ else if (elf_march->bits == 64)
+ objfmt_elf->objfmt.module = &yasm_elf64_LTX_objfmt;
+ }
+ return objfmt;
+}
+
+static yasm_objfmt *
+elf32_objfmt_create(yasm_object *object)
+{
+ return elf_objfmt_create_common(object, &yasm_elf32_LTX_objfmt, 32, NULL);
+}
+
+static yasm_objfmt *
+elf64_objfmt_create(yasm_object *object)
+{
+ return elf_objfmt_create_common(object, &yasm_elf64_LTX_objfmt, 64, NULL);
+}
+
+static yasm_objfmt *
+elfx32_objfmt_create(yasm_object *object)
+{
+ return elf_objfmt_create_common(object, &yasm_elfx32_LTX_objfmt, 32, NULL);
+}
+
+static long
+elf_objfmt_output_align(FILE *f, unsigned int align)
+{
+ long pos;
+ unsigned long delta;
+ if (!is_exp2(align))
+ yasm_internal_error("requested alignment not a power of two");
+
+ pos = ftell(f);
+ if (pos == -1) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("could not get file position on output file"));
+ return -1;
+ }
+ delta = align - (pos & (align-1));
+ if (delta != align) {
+ pos += delta;
+ if (fseek(f, pos, SEEK_SET) < 0) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("could not set file position on output file"));
+ return -1;
+ }
+ }
+ return pos;
+}
+
+static int
+elf_objfmt_output_reloc(yasm_symrec *sym, yasm_bytecode *bc,
+ unsigned char *buf, unsigned int destsize,
+ unsigned int valsize, int warn, void *d)
+{
+ elf_reloc_entry *reloc;
+ elf_objfmt_output_info *info = d;
+ yasm_intnum *zero;
+ int retval;
+
+ reloc = elf_reloc_entry_create(sym, NULL,
+ yasm_intnum_create_uint(bc->offset), 0, valsize, 0);
+ if (reloc == NULL) {
+ yasm_error_set(YASM_ERROR_TYPE, N_("elf: invalid relocation size"));
+ return 1;
+ }
+ /* allocate .rel[a] sections on a need-basis */
+ elf_secthead_append_reloc(info->sect, info->shead, reloc);
+
+ zero = yasm_intnum_create_uint(0);
+ elf_handle_reloc_addend(zero, reloc, 0);
+ retval = yasm_arch_intnum_tobytes(info->object->arch, zero, buf, destsize,
+ valsize, 0, bc, warn);
+ yasm_intnum_destroy(zero);
+ return retval;
+}
+
+static int
+elf_objfmt_output_value(yasm_value *value, unsigned char *buf,
+ unsigned int destsize, unsigned long offset,
+ yasm_bytecode *bc, int warn, /*@null@*/ void *d)
+{
+ /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
+ unsigned long intn_val;
+ /*@null@*/ elf_reloc_entry *reloc = NULL;
+ int retval;
+ unsigned int valsize = value->size;
+
+ if (info == NULL)
+ yasm_internal_error("null info struct");
+
+ if (value->abs)
+ value->abs = yasm_expr_simplify(value->abs, 1);
+
+ /* Try to output constant and PC-relative section-local first.
+ * Note this does NOT output any value with a SEG, WRT, external,
+ * cross-section, or non-PC-relative reference (those are handled below).
+ */
+ switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
+ info->object->arch)) {
+ case -1:
+ return 1;
+ case 0:
+ break;
+ default:
+ return 0;
+ }
+
+ /* Handle other expressions, with relocation if necessary */
+ if (value->seg_of || value->section_rel || value->rshift > 0) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("elf: relocation too complex"));
+ return 1;
+ }
+
+ intn_val = 0;
+ if (value->rel) {
+ yasm_sym_vis vis = yasm_symrec_get_visibility(value->rel);
+ /*@dependent@*/ /*@null@*/ yasm_symrec *sym = value->rel;
+ /*@dependent@*/ /*@null@*/ yasm_symrec *wrt = value->wrt;
+
+ if (wrt == info->objfmt_elf->dotdotsym)
+ wrt = NULL;
+ else if (wrt && elf_is_wrt_sym_relative(wrt))
+ ;
+ else if (wrt && elf_is_wrt_pos_adjusted(wrt))
+ intn_val = offset + bc->offset;
+ else if (vis == YASM_SYM_LOCAL) {
+ yasm_bytecode *sym_precbc;
+ /* Local symbols need relocation to their section's start, and
+ * add in the offset of the bytecode (within the target section)
+ * into the abs portion.
+ *
+ * This is only done if the symbol is relocated against the
+ * section instead of the symbol itself.
+ */
+ if (yasm_symrec_get_label(sym, &sym_precbc)) {
+ /* Relocate to section start */
+ yasm_section *sym_sect = yasm_bc_get_section(sym_precbc);
+ /*@null@*/ elf_secthead *sym_shead;
+ sym_shead = yasm_section_get_data(sym_sect, &elf_section_data);
+ assert(sym_shead != NULL);
+ sym = elf_secthead_get_sym(sym_shead);
+
+ intn_val = yasm_bc_next_offset(sym_precbc);
+ }
+ }
+
+ /* For PC-relative, need to add offset of expression within bc. */
+ if (value->curpos_rel)
+ intn_val += offset;
+
+ /* Check for _GLOBAL_OFFSET_TABLE_ symbol reference */
+ reloc = elf_reloc_entry_create(sym, wrt,
+ yasm_intnum_create_uint(bc->offset + offset), value->curpos_rel,
+ valsize, sym == info->GOT_sym);
+ if (reloc == NULL) {
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("elf: invalid relocation (WRT or size)"));
+ return 1;
+ }
+ /* allocate .rel[a] sections on a need-basis */
+ elf_secthead_append_reloc(info->sect, info->shead, reloc);
+ }
+
+ intn = yasm_intnum_create_uint(intn_val);
+
+ if (value->abs) {
+ yasm_intnum *intn2 = yasm_expr_get_intnum(&value->abs, 0);
+ if (!intn2) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("elf: relocation too complex"));
+ yasm_intnum_destroy(intn);
+ return 1;
+ }
+ yasm_intnum_calc(intn, YASM_EXPR_ADD, intn2);
+ }
+
+ if (reloc)
+ elf_handle_reloc_addend(intn, reloc, offset);
+ retval = yasm_arch_intnum_tobytes(info->object->arch, intn, buf, destsize,
+ valsize, 0, bc, warn);
+ yasm_intnum_destroy(intn);
+ return retval;
+}
+
+static int
+elf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
+{
+ /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
+ unsigned char buf[256];
+ /*@null@*/ /*@only@*/ unsigned char *bigbuf;
+ unsigned long size = 256;
+ int gap;
+
+ if (info == NULL)
+ yasm_internal_error("null info struct");
+
+ bigbuf = yasm_bc_tobytes(bc, buf, &size, &gap, info,
+ elf_objfmt_output_value, elf_objfmt_output_reloc);
+
+ /* Don't bother doing anything else if size ended up being 0. */
+ if (size == 0) {
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+ return 0;
+ }
+ else {
+ yasm_intnum *bcsize = yasm_intnum_create_uint(size);
+ elf_secthead_add_size(info->shead, bcsize);
+ yasm_intnum_destroy(bcsize);
+ }
+
+ /* Warn that gaps are converted to 0 and write out the 0's. */
+ if (gap) {
+ unsigned long left;
+ yasm_warn_set(YASM_WARN_UNINIT_CONTENTS,
+ N_("uninitialized space declared in code/data section: zeroing"));
+ /* Write out in chunks */
+ memset(buf, 0, 256);
+ left = size;
+ while (left > 256) {
+ fwrite(buf, 256, 1, info->f);
+ left -= 256;
+ }
+ fwrite(buf, left, 1, info->f);
+ } else {
+ /* Output buf (or bigbuf if non-NULL) to file */
+ fwrite(bigbuf ? bigbuf : buf, (size_t)size, 1, info->f);
+ }
+
+ /* If bigbuf was allocated, free it */
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+
+ return 0;
+}
+
+static int
+elf_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ elf_secthead *shead;
+ long pos;
+ char *relname;
+ const char *sectname;
+
+ if (info == NULL)
+ yasm_internal_error("null info struct");
+ shead = yasm_section_get_data(sect, &elf_section_data);
+ if (shead == NULL)
+ yasm_internal_error("no associated data");
+
+ if (elf_secthead_get_align(shead) == 0)
+ elf_secthead_set_align(shead, yasm_section_get_align(sect));
+
+ /* don't output header-only sections */
+ if ((elf_secthead_get_type(shead) & SHT_NOBITS) == SHT_NOBITS)
+ {
+ yasm_bytecode *last = yasm_section_bcs_last(sect);
+ if (last) {
+ yasm_intnum *sectsize;
+ sectsize = yasm_intnum_create_uint(yasm_bc_next_offset(last));
+ elf_secthead_add_size(shead, sectsize);
+ yasm_intnum_destroy(sectsize);
+ }
+ elf_secthead_set_index(shead, ++info->sindex);
+ return 0;
+ }
+
+ if ((pos = ftell(info->f)) == -1) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("couldn't read position on output stream"));
+ yasm_errwarn_propagate(info->errwarns, 0);
+ }
+ pos = elf_secthead_set_file_offset(shead, pos);
+ if (fseek(info->f, pos, SEEK_SET) < 0) {
+ yasm_error_set(YASM_ERROR_IO, N_("couldn't seek on output stream"));
+ yasm_errwarn_propagate(info->errwarns, 0);
+ }
+
+ info->sect = sect;
+ info->shead = shead;
+ yasm_section_bcs_traverse(sect, info->errwarns, info,
+ elf_objfmt_output_bytecode);
+
+ elf_secthead_set_index(shead, ++info->sindex);
+
+ /* No relocations to output? Go on to next section */
+ if (elf_secthead_write_relocs_to_file(info->f, sect, shead,
+ info->errwarns) == 0)
+ return 0;
+ elf_secthead_set_rel_index(shead, ++info->sindex);
+
+ /* name the relocation section .rel[a].foo */
+ sectname = yasm_section_get_name(sect);
+ relname = elf_secthead_name_reloc_section(sectname);
+ elf_secthead_set_rel_name(shead,
+ elf_strtab_append_str(info->objfmt_elf->shstrtab, relname));
+ yasm_xfree(relname);
+
+ return 0;
+}
+
+static int
+elf_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ elf_secthead *shead;
+
+ if (info == NULL)
+ yasm_internal_error("null info struct");
+ shead = yasm_section_get_data(sect, &elf_section_data);
+ if (shead == NULL)
+ yasm_internal_error("no section header attached to section");
+
+ if(elf_secthead_write_to_file(info->f, shead, info->sindex+1))
+ info->sindex++;
+
+ /* output strtab headers here? */
+
+ /* relocation entries for .foo are stored in section .rel[a].foo */
+ if(elf_secthead_write_rel_to_file(info->f, 3, sect, shead,
+ info->sindex+1))
+ info->sindex++;
+
+ return 0;
+}
+
+static void
+elf_objfmt_output(yasm_object *object, FILE *f, int all_syms,
+ yasm_errwarns *errwarns)
+{
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
+ elf_objfmt_output_info info;
+ build_symtab_info buildsym_info;
+ long pos;
+ unsigned long elf_shead_addr;
+ elf_secthead *esdn;
+ unsigned long elf_strtab_offset, elf_shstrtab_offset, elf_symtab_offset;
+ unsigned long elf_strtab_size, elf_shstrtab_size, elf_symtab_size;
+ elf_strtab_entry *elf_strtab_name, *elf_shstrtab_name, *elf_symtab_name;
+ unsigned long elf_symtab_nlocal;
+
+ info.object = object;
+ info.objfmt_elf = objfmt_elf;
+ info.errwarns = errwarns;
+ info.f = f;
+ info.GOT_sym = yasm_symtab_get(object->symtab, "_GLOBAL_OFFSET_TABLE_");
+
+ if (!object->deb_filename) {
+ object->deb_filename = yasm_replace_path(
+ objfmt_elf->objfmt.module->replace_map, objfmt_elf->objfmt.module->replace_map_size,
+ object->src_filename, strlen(object->src_filename));
+ }
+ /* Update filename strtab */
+ elf_strtab_entry_set_str(objfmt_elf->file_strtab_entry,
+ object->deb_filename);
+
+ /* Allocate space for Ehdr by seeking forward */
+ if (fseek(f, (long)(elf_proghead_get_size()), SEEK_SET) < 0) {
+ yasm_error_set(YASM_ERROR_IO, N_("could not seek on output file"));
+ yasm_errwarn_propagate(errwarns, 0);
+ return;
+ }
+
+ /* add all (local) syms to symtab because relocation needs a symtab index
+ * if all_syms, register them by name. if not, use strtab entry 0 */
+ buildsym_info.object = object;
+ buildsym_info.objfmt_elf = objfmt_elf;
+ buildsym_info.errwarns = errwarns;
+ buildsym_info.local_names = all_syms;
+ yasm_symtab_traverse(object->symtab, &buildsym_info,
+ elf_objfmt_build_symtab);
+ elf_symtab_nlocal = elf_symtab_assign_indices(objfmt_elf->elf_symtab);
+
+ /* output known sections - includes reloc sections which aren't in yasm's
+ * list. Assign indices as we go. */
+ info.sindex = 3;
+ if (yasm_object_sections_traverse(object, &info,
+ elf_objfmt_output_section))
+ return;
+
+ /* add final sections to the shstrtab */
+ elf_strtab_name = elf_strtab_append_str(objfmt_elf->shstrtab, ".strtab");
+ elf_symtab_name = elf_strtab_append_str(objfmt_elf->shstrtab, ".symtab");
+ elf_shstrtab_name = elf_strtab_append_str(objfmt_elf->shstrtab,
+ ".shstrtab");
+
+ /* output .shstrtab */
+ if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
+ yasm_errwarn_propagate(errwarns, 0);
+ return;
+ }
+ elf_shstrtab_offset = (unsigned long) pos;
+ elf_shstrtab_size = elf_strtab_output_to_file(f, objfmt_elf->shstrtab);
+
+ /* output .strtab */
+ if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
+ yasm_errwarn_propagate(errwarns, 0);
+ return;
+ }
+ elf_strtab_offset = (unsigned long) pos;
+ elf_strtab_size = elf_strtab_output_to_file(f, objfmt_elf->strtab);
+
+ /* output .symtab - last section so all others have indexes */
+ if ((pos = elf_objfmt_output_align(f, 4)) == -1) {
+ yasm_errwarn_propagate(errwarns, 0);
+ return;
+ }
+ elf_symtab_offset = (unsigned long) pos;
+ elf_symtab_size = elf_symtab_write_to_file(f, objfmt_elf->elf_symtab,
+ errwarns);
+
+ /* output section header table */
+ if ((pos = elf_objfmt_output_align(f, 16)) == -1) {
+ yasm_errwarn_propagate(errwarns, 0);
+ return;
+ }
+ elf_shead_addr = (unsigned long) pos;
+
+ /* stabs debugging support */
+ if (strcmp(yasm_dbgfmt_keyword(object->dbgfmt), "stabs")==0) {
+ yasm_section *stabsect = yasm_object_find_general(object, ".stab");
+ yasm_section *stabstrsect =
+ yasm_object_find_general(object, ".stabstr");
+ if (stabsect && stabstrsect) {
+ elf_secthead *stab =
+ yasm_section_get_data(stabsect, &elf_section_data);
+ elf_secthead *stabstr =
+ yasm_section_get_data(stabstrsect, &elf_section_data);
+ if (stab && stabstr) {
+ elf_secthead_set_link(stab, elf_secthead_get_index(stabstr));
+ }
+ else
+ yasm_internal_error(N_("missing .stab or .stabstr section/data"));
+ }
+ }
+
+ /* output dummy section header - 0 */
+ info.sindex = 0;
+
+ esdn = elf_secthead_create(NULL, SHT_NULL, 0, 0, 0);
+ elf_secthead_set_index(esdn, 0);
+ elf_secthead_write_to_file(f, esdn, 0);
+ elf_secthead_destroy(esdn);
+
+ esdn = elf_secthead_create(elf_shstrtab_name, SHT_STRTAB, 0,
+ elf_shstrtab_offset, elf_shstrtab_size);
+ elf_secthead_set_index(esdn, 1);
+ elf_secthead_write_to_file(f, esdn, 1);
+ elf_secthead_destroy(esdn);
+
+ esdn = elf_secthead_create(elf_strtab_name, SHT_STRTAB, 0,
+ elf_strtab_offset, elf_strtab_size);
+ elf_secthead_set_index(esdn, 2);
+ elf_secthead_write_to_file(f, esdn, 2);
+ elf_secthead_destroy(esdn);
+
+ esdn = elf_secthead_create(elf_symtab_name, SHT_SYMTAB, 0,
+ elf_symtab_offset, elf_symtab_size);
+ elf_secthead_set_index(esdn, 3);
+ elf_secthead_set_info(esdn, elf_symtab_nlocal);
+ elf_secthead_set_link(esdn, 2); /* for .strtab, which is index 2 */
+ elf_secthead_write_to_file(f, esdn, 3);
+ elf_secthead_destroy(esdn);
+
+ info.sindex = 3;
+ /* output remaining section headers */
+ yasm_object_sections_traverse(object, &info, elf_objfmt_output_secthead);
+
+ /* output Ehdr */
+ if (fseek(f, 0, SEEK_SET) < 0) {
+ yasm_error_set(YASM_ERROR_IO, N_("could not seek on output file"));
+ yasm_errwarn_propagate(errwarns, 0);
+ return;
+ }
+
+ elf_proghead_write_to_file(f, elf_shead_addr, info.sindex+1, 1);
+}
+
+static void
+elf_objfmt_destroy(yasm_objfmt *objfmt)
+{
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)objfmt;
+ elf_symtab_destroy(objfmt_elf->elf_symtab);
+ elf_strtab_destroy(objfmt_elf->shstrtab);
+ elf_strtab_destroy(objfmt_elf->strtab);
+ yasm_xfree(objfmt);
+}
+
+static void
+elf_objfmt_init_new_section(yasm_section *sect, unsigned long line)
+{
+ yasm_object *object = yasm_section_get_object(sect);
+ const char *sectname = yasm_section_get_name(sect);
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
+ elf_secthead *esd;
+ yasm_symrec *sym;
+ elf_strtab_entry *name = elf_strtab_append_str(objfmt_elf->shstrtab,
+ sectname);
+
+ elf_section_type type=SHT_PROGBITS;
+ elf_size entsize=0;
+
+ if (yasm__strcasecmp(sectname, ".stab")==0) {
+ entsize = 12;
+ } else if (yasm__strcasecmp(sectname, ".stabstr")==0) {
+ type = SHT_STRTAB;
+ }
+
+ esd = elf_secthead_create(name, type, 0, 0, 0);
+ elf_secthead_set_entsize(esd, entsize);
+ yasm_section_add_data(sect, &elf_section_data, esd);
+ sym = yasm_symtab_define_label(object->symtab, sectname,
+ yasm_section_bcs_first(sect), 1, line);
+
+ elf_secthead_set_sym(esd, sym);
+}
+
+static yasm_section *
+elf_objfmt_add_default_section(yasm_object *object)
+{
+ yasm_section *retval;
+ int isnew;
+
+ retval = yasm_object_get_general(object, ".text", 16, 1, 0, &isnew, 0);
+ if (isnew)
+ {
+ elf_secthead *esd = yasm_section_get_data(retval, &elf_section_data);
+ elf_secthead_set_typeflags(esd, SHT_PROGBITS,
+ SHF_ALLOC + SHF_EXECINSTR);
+ yasm_section_set_default(retval, 1);
+ }
+ return retval;
+}
+
+struct elf_section_switch_data {
+ /*@only@*/ /*@null@*/ yasm_intnum *align_intn;
+ unsigned long flags;
+ unsigned long type;
+ int gasflags;
+ int stdsect;
+};
+
+/* GAS-style flags */
+static int
+elf_helper_gasflags(void *obj, yasm_valparam *vp, unsigned long line, void *d,
+ /*@unused@*/ uintptr_t arg)
+{
+ struct elf_section_switch_data *data = (struct elf_section_switch_data *)d;
+ const char *s = yasm_vp_string(vp);
+ size_t i;
+
+ if (!s) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("non-string section attribute"));
+ return -1;
+ }
+
+ if (data->stdsect && strlen(s) == 0) {
+ data->gasflags = 1;
+ return 0;
+ }
+
+ data->flags = 0;
+ for (i=0; i<strlen(s); i++) {
+ switch (s[i]) {
+ case 'a':
+ data->flags |= SHF_ALLOC;
+ break;
+ case 'w':
+ data->flags |= SHF_WRITE;
+ break;
+ case 'x':
+ data->flags |= SHF_EXECINSTR;
+ break;
+ case 'M':
+ data->flags |= SHF_MERGE;
+ break;
+ case 'S':
+ data->flags |= SHF_STRINGS;
+ break;
+ case 'G':
+ data->flags |= SHF_GROUP;
+ break;
+ case 'T':
+ data->flags |= SHF_TLS;
+ break;
+ default:
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("unrecognized section attribute: `%c'"),
+ s[i]);
+ }
+ }
+
+ data->gasflags = 1;
+ return 0;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_section *
+elf_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *objext_valparams,
+ unsigned long line)
+{
+ yasm_valparam *vp;
+ yasm_section *retval;
+ int isnew;
+ unsigned long align = 4;
+ int flags_override = 0;
+ const char *sectname;
+ int resonly = 0;
+
+ struct elf_section_switch_data data;
+
+ static const yasm_dir_help help[] = {
+ { "alloc", 0, yasm_dir_helper_flag_or,
+ offsetof(struct elf_section_switch_data, flags), SHF_ALLOC },
+ { "exec", 0, yasm_dir_helper_flag_or,
+ offsetof(struct elf_section_switch_data, flags), SHF_EXECINSTR },
+ { "write", 0, yasm_dir_helper_flag_or,
+ offsetof(struct elf_section_switch_data, flags), SHF_WRITE },
+ { "tls", 0, yasm_dir_helper_flag_or,
+ offsetof(struct elf_section_switch_data, flags), SHF_TLS },
+ { "progbits", 0, yasm_dir_helper_flag_set,
+ offsetof(struct elf_section_switch_data, type), SHT_PROGBITS },
+ { "noalloc", 0, yasm_dir_helper_flag_and,
+ offsetof(struct elf_section_switch_data, flags), SHF_ALLOC },
+ { "noexec", 0, yasm_dir_helper_flag_and,
+ offsetof(struct elf_section_switch_data, flags), SHF_EXECINSTR },
+ { "nowrite", 0, yasm_dir_helper_flag_and,
+ offsetof(struct elf_section_switch_data, flags), SHF_WRITE },
+ { "notls", 0, yasm_dir_helper_flag_and,
+ offsetof(struct elf_section_switch_data, flags), SHF_TLS },
+ { "noprogbits", 0, yasm_dir_helper_flag_set,
+ offsetof(struct elf_section_switch_data, type), SHT_NOBITS },
+ { "nobits", 0, yasm_dir_helper_flag_set,
+ offsetof(struct elf_section_switch_data, type), SHT_NOBITS },
+ { "gasflags", 1, elf_helper_gasflags, 0, 0 },
+ { "align", 1, yasm_dir_helper_intn,
+ offsetof(struct elf_section_switch_data, align_intn), 0 }
+ };
+ /*@only@*/ /*@null@*/ yasm_expr *merge_expr = NULL;
+ /*@dependent@*/ /*@null@*/ const yasm_intnum *merge_intn = NULL;
+ elf_secthead *esd;
+
+ data.align_intn = NULL;
+ data.flags = SHF_ALLOC;
+ data.type = SHT_PROGBITS;
+ data.gasflags = 0;
+ data.stdsect = 1;
+
+ vp = yasm_vps_first(valparams);
+ sectname = yasm_vp_string(vp);
+ if (!sectname)
+ return NULL;
+ vp = yasm_vps_next(vp);
+
+ if (strcmp(sectname, ".bss") == 0) {
+ data.type = SHT_NOBITS;
+ data.flags = SHF_ALLOC + SHF_WRITE;
+ resonly = 1;
+ } else if (strcmp(sectname, ".data") == 0) {
+ data.type = SHT_PROGBITS;
+ data.flags = SHF_ALLOC + SHF_WRITE;
+ } else if (strcmp(sectname, ".tdata") == 0) {
+ data.type = SHT_PROGBITS;
+ data.flags = SHF_ALLOC + SHF_WRITE + SHF_TLS;
+ } else if (strcmp(sectname, ".rodata") == 0) {
+ data.type = SHT_PROGBITS;
+ data.flags = SHF_ALLOC;
+ } else if (strcmp(sectname, ".text") == 0) {
+ align = 16;
+ data.type = SHT_PROGBITS;
+ data.flags = SHF_ALLOC + SHF_EXECINSTR;
+ } else if (strcmp(sectname, ".comment") == 0) {
+ align = 0;
+ data.type = SHT_PROGBITS;
+ data.flags = 0;
+ } else {
+ /* Default to code */
+ align = 1;
+ data.stdsect = 0;
+ }
+
+ flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help),
+ &data, yasm_dir_helper_valparam_warn);
+ if (flags_override < 0)
+ return NULL; /* error occurred */
+
+ if (data.align_intn) {
+ align = yasm_intnum_get_uint(data.align_intn);
+ yasm_intnum_destroy(data.align_intn);
+
+ /* Alignments must be a power of two. */
+ if (!is_exp2(align)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("argument to `%s' is not a power of two"),
+ "align");
+ return NULL;
+ }
+ }
+
+ /* Handle merge entity size */
+ if (data.flags & SHF_MERGE) {
+ if (objext_valparams && (vp = yasm_vps_first(objext_valparams))
+ && !vp->val) {
+ if (!(merge_expr = yasm_vp_expr(vp, object->symtab, line)) ||
+ !(merge_intn = yasm_expr_get_intnum(&merge_expr, 0)))
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("invalid merge entity size"));
+ } else {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("entity size for SHF_MERGE not specified"));
+ data.flags &= ~SHF_MERGE;
+ }
+ }
+
+ retval = yasm_object_get_general(object, sectname, align,
+ (data.flags & SHF_EXECINSTR) != 0,
+ resonly, &isnew, line);
+
+ esd = yasm_section_get_data(retval, &elf_section_data);
+
+ if (isnew || yasm_section_is_default(retval)) {
+ yasm_section_set_default(retval, 0);
+ elf_secthead_set_typeflags(esd, data.type, data.flags);
+ if (merge_intn)
+ elf_secthead_set_entsize(esd, yasm_intnum_get_uint(merge_intn));
+ yasm_section_set_align(retval, align, line);
+ } else if (flags_override && !data.gasflags)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("section flags ignored on section redeclaration"));
+ if (merge_expr)
+ yasm_expr_destroy(merge_expr);
+ return retval;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+elf_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ if (yasm__strcasecmp(name, "sym") == 0) {
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
+ return objfmt_elf->dotdotsym;
+ }
+ return elf_get_special_sym(name, parser);
+}
+
+static void
+dir_type(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ const char *symname = yasm_vp_id(vp);
+ /* Get symbol elf data */
+ yasm_symrec *sym = yasm_symtab_use(object->symtab, symname, line);
+ elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
+ /*@null@*/ const char *type;
+
+ /* Create entry if necessary */
+ if (!entry) {
+ entry = elf_symtab_entry_create(
+ elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
+ yasm_symrec_add_data(sym, &elf_symrec_data, entry);
+ }
+
+ /* Pull new type from param */
+ vp = yasm_vps_next(vp);
+ if (vp && !vp->val && (type = yasm_vp_id(vp))) {
+ if (yasm__strcasecmp(type, "function") == 0)
+ elf_sym_set_type(entry, STT_FUNC);
+ else if (yasm__strcasecmp(type, "object") == 0)
+ elf_sym_set_type(entry, STT_OBJECT);
+ else if (yasm__strcasecmp(type, "tls_object") == 0)
+ elf_sym_set_type(entry, STT_TLS);
+ else if (yasm__strcasecmp(type, "notype") == 0)
+ elf_sym_set_type(entry, STT_NOTYPE);
+ else
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("unrecognized symbol type `%s'"), type);
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("no type specified"));
+}
+
+static void
+dir_size(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ const char *symname = yasm_vp_id(vp);
+ /* Get symbol elf data */
+ yasm_symrec *sym = yasm_symtab_use(object->symtab, symname, line);
+ elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data);
+ /*@only@*/ /*@null@*/ yasm_expr *size;
+
+ /* Create entry if necessary */
+ if (!entry) {
+ entry = elf_symtab_entry_create(
+ elf_strtab_append_str(objfmt_elf->strtab, symname), sym);
+ yasm_symrec_add_data(sym, &elf_symrec_data, entry);
+ }
+
+ /* Pull new size from param */
+ vp = yasm_vps_next(vp);
+ if (vp && !vp->val && (size = yasm_vp_expr(vp, object->symtab, line)))
+ elf_sym_set_size(entry, size);
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("no size specified"));
+}
+
+static void
+dir_weak(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt;
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ const char *symname = yasm_vp_id(vp);
+ yasm_symrec *sym = yasm_symtab_declare(object->symtab, symname,
+ YASM_SYM_GLOBAL, line);
+ elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_WEAK, 0,
+ STV_DEFAULT, NULL, NULL, object);
+}
+
+static void
+dir_ident(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparamhead sect_vps;
+ yasm_datavalhead dvs;
+ yasm_section *comment;
+ yasm_valparam *vp;
+ yasm_valparam *vp2;
+
+ /* Accept, but do nothing with empty ident */
+ if (!valparams)
+ return;
+ vp = yasm_vps_first(valparams);
+ if (!vp)
+ return;
+
+ /* Put ident data into .comment section */
+ yasm_vps_initialize(&sect_vps);
+ vp2 = yasm_vp_create_string(NULL, yasm__xstrdup(".comment"));
+ yasm_vps_append(&sect_vps, vp2);
+ comment = elf_objfmt_section_switch(object, &sect_vps, NULL, line);
+ yasm_vps_delete(&sect_vps);
+
+ /* To match GAS output, if the comment section is empty, put an
+ * initial 0 byte in the section.
+ */
+ if (yasm_section_bcs_first(comment) == yasm_section_bcs_last(comment)) {
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(
+ yasm_expr_create_ident(
+ yasm_expr_int(yasm_intnum_create_uint(0)), line)));
+ yasm_section_bcs_append(comment,
+ yasm_bc_create_data(&dvs, 1, 0, object->arch, line));
+ }
+
+ yasm_dvs_initialize(&dvs);
+ do {
+ const char *s = yasm_vp_string(vp);
+ if (!s) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_(".comment requires string parameters"));
+ yasm_dvs_delete(&dvs);
+ return;
+ }
+ yasm_dvs_append(&dvs,
+ yasm_dv_create_string(yasm__xstrdup(s), strlen(s)));
+ } while ((vp = yasm_vps_next(vp)));
+
+ yasm_section_bcs_append(comment,
+ yasm_bc_create_data(&dvs, 1, 1, object->arch, line));
+}
+
+/* Define valid debug formats to use with this object format */
+static const char *elf_objfmt_dbgfmt_keywords[] = {
+ "null",
+ "stabs",
+ "dwarf2",
+ NULL
+};
+
+static const yasm_directive elf_objfmt_directives[] = {
+ { ".type", "gas", dir_type, YASM_DIR_ID_REQUIRED },
+ { ".size", "gas", dir_size, YASM_DIR_ID_REQUIRED },
+ { ".weak", "gas", dir_weak, YASM_DIR_ID_REQUIRED },
+ { ".ident", "gas", dir_ident, YASM_DIR_ANY },
+ { "type", "nasm", dir_type, YASM_DIR_ID_REQUIRED },
+ { "size", "nasm", dir_size, YASM_DIR_ID_REQUIRED },
+ { "weak", "nasm", dir_weak, YASM_DIR_ID_REQUIRED },
+ { "ident", "nasm", dir_ident, YASM_DIR_ANY },
+ { NULL, NULL, NULL, 0 }
+};
+
+static const char *elf_nasm_stdmac[] = {
+ "%imacro type 1+.nolist",
+ "[type %1]",
+ "%endmacro",
+ "%imacro size 1+.nolist",
+ "[size %1]",
+ "%endmacro",
+ "%imacro weak 1+.nolist",
+ "[weak %1]",
+ "%endmacro",
+ NULL
+};
+
+static const yasm_stdmac elf_objfmt_stdmacs[] = {
+ { "nasm", "nasm", elf_nasm_stdmac },
+ { NULL, NULL, NULL }
+};
+
+/* Define objfmt structure -- see objfmt.h for details */
+yasm_objfmt_module yasm_elf_LTX_objfmt = {
+ "ELF",
+ "elf",
+ "o",
+ 32,
+ 0,
+ elf_objfmt_dbgfmt_keywords,
+ "null",
+ elf_objfmt_directives,
+ elf_objfmt_stdmacs,
+ elf_objfmt_create,
+ elf_objfmt_output,
+ elf_objfmt_destroy,
+ elf_objfmt_add_default_section,
+ elf_objfmt_init_new_section,
+ elf_objfmt_section_switch,
+ elf_objfmt_get_special_sym
+};
+
+yasm_objfmt_module yasm_elf32_LTX_objfmt = {
+ "ELF (32-bit)",
+ "elf32",
+ "o",
+ 32,
+ 0,
+ elf_objfmt_dbgfmt_keywords,
+ "null",
+ elf_objfmt_directives,
+ elf_objfmt_stdmacs,
+ elf32_objfmt_create,
+ elf_objfmt_output,
+ elf_objfmt_destroy,
+ elf_objfmt_add_default_section,
+ elf_objfmt_init_new_section,
+ elf_objfmt_section_switch,
+ elf_objfmt_get_special_sym
+};
+
+yasm_objfmt_module yasm_elf64_LTX_objfmt = {
+ "ELF (64-bit)",
+ "elf64",
+ "o",
+ 64,
+ 0,
+ elf_objfmt_dbgfmt_keywords,
+ "null",
+ elf_objfmt_directives,
+ elf_objfmt_stdmacs,
+ elf64_objfmt_create,
+ elf_objfmt_output,
+ elf_objfmt_destroy,
+ elf_objfmt_add_default_section,
+ elf_objfmt_init_new_section,
+ elf_objfmt_section_switch,
+ elf_objfmt_get_special_sym
+};
+
+yasm_objfmt_module yasm_elfx32_LTX_objfmt = {
+ "ELF (x32)",
+ "elfx32",
+ "o",
+ 64,
+ 0,
+ elf_objfmt_dbgfmt_keywords,
+ "null",
+ elf_objfmt_directives,
+ elf_objfmt_stdmacs,
+ elfx32_objfmt_create,
+ elf_objfmt_output,
+ elf_objfmt_destroy,
+ elf_objfmt_add_default_section,
+ elf_objfmt_init_new_section,
+ elf_objfmt_section_switch,
+ elf_objfmt_get_special_sym
+};
diff --git a/contrib/tools/yasm/modules/objfmts/elf/elf-x86-amd64.c b/contrib/tools/yasm/modules/objfmts/elf/elf-x86-amd64.c
new file mode 100644
index 0000000000..3ba376af03
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/elf/elf-x86-amd64.c
@@ -0,0 +1,256 @@
+/*
+ * ELF object format helpers - x86:amd64
+ *
+ * Copyright (C) 2004-2007 Michael Urman
+ *
+ * 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 <util.h>
+
+#include <libyasm.h>
+#define YASM_OBJFMT_ELF_INTERNAL
+#include "elf.h"
+#include "elf-machine.h"
+
+static elf_machine_ssym elf_x86_amd64_ssyms[] = {
+ {"pltoff", ELF_SSYM_SYM_RELATIVE, R_X86_64_PLTOFF64, 64},
+ {"plt", ELF_SSYM_SYM_RELATIVE, R_X86_64_PLT32, 32},
+ {"gotplt", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTPLT64, 64},
+ {"gotoff", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTOFF64, 64},
+ {"gotpcrel", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTPCREL, 32},
+ {"tlsgd", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TLSGD, 32},
+ {"tlsld", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TLSLD, 32},
+ {"gottpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_GOTTPOFF, 32},
+ {"tpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TPOFF32, 32},
+ {"dtpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_DTPOFF32, 32},
+ {"got", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOT32, 32},
+ {"tlsdesc", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_GOTPC32_TLSDESC, 32},
+ {"tlscall", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TLSDESC_CALL, 32}
+};
+
+static int
+elf_x86_amd64_accepts_reloc(size_t val, yasm_symrec *wrt)
+{
+ if (wrt) {
+ const elf_machine_ssym *ssym = (elf_machine_ssym *)
+ yasm_symrec_get_data(wrt, &elf_ssym_symrec_data);
+ if (!ssym || val != ssym->size)
+ return 0;
+ return 1;
+ }
+ return (val&(val-1)) ? 0 : ((val & (8|16|32|64)) != 0);
+}
+
+static void
+elf_x86_amd64_write_symtab_entry(unsigned char *bufp,
+ elf_symtab_entry *entry,
+ yasm_intnum *value_intn,
+ yasm_intnum *size_intn)
+{
+ YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0);
+ YASM_WRITE_8(bufp, ELF64_ST_INFO(entry->bind, entry->type));
+ YASM_WRITE_8(bufp, ELF64_ST_OTHER(entry->vis));
+ if (entry->sect) {
+ elf_secthead *shead =
+ yasm_section_get_data(entry->sect, &elf_section_data);
+ if (!shead)
+ yasm_internal_error(N_("symbol references section without data"));
+ YASM_WRITE_16_L(bufp, shead->index);
+ } else {
+ YASM_WRITE_16_L(bufp, entry->index);
+ }
+ YASM_WRITE_64I_L(bufp, value_intn);
+ YASM_WRITE_64I_L(bufp, size_intn);
+}
+
+static void
+elf_x86_amd64_write_secthead(unsigned char *bufp, elf_secthead *shead)
+{
+ YASM_WRITE_32_L(bufp, shead->name ? shead->name->index : 0);
+ YASM_WRITE_32_L(bufp, shead->type);
+ YASM_WRITE_64Z_L(bufp, shead->flags);
+ YASM_WRITE_64Z_L(bufp, 0); /* vmem address */
+ YASM_WRITE_64Z_L(bufp, shead->offset);
+ YASM_WRITE_64I_L(bufp, shead->size);
+
+ YASM_WRITE_32_L(bufp, shead->link);
+ YASM_WRITE_32_L(bufp, shead->info);
+
+ YASM_WRITE_64Z_L(bufp, shead->align);
+ YASM_WRITE_64Z_L(bufp, shead->entsize);
+}
+
+static void
+elf_x86_amd64_write_secthead_rel(unsigned char *bufp,
+ elf_secthead *shead,
+ elf_section_index symtab_idx,
+ elf_section_index sindex)
+{
+ yasm_intnum *nreloc;
+ yasm_intnum *relocsize;
+
+ YASM_WRITE_32_L(bufp, shead->rel_name ? shead->rel_name->index : 0);
+ YASM_WRITE_32_L(bufp, SHT_RELA);
+ YASM_WRITE_64Z_L(bufp, 0);
+ YASM_WRITE_64Z_L(bufp, 0);
+ YASM_WRITE_64Z_L(bufp, shead->rel_offset);
+
+ nreloc = yasm_intnum_create_uint(shead->nreloc);
+ relocsize = yasm_intnum_create_uint(RELOC64A_SIZE);
+ yasm_intnum_calc(relocsize, YASM_EXPR_MUL, nreloc);
+ YASM_WRITE_64I_L(bufp, relocsize); /* size */
+ yasm_intnum_destroy(nreloc);
+ yasm_intnum_destroy(relocsize);
+
+ YASM_WRITE_32_L(bufp, symtab_idx); /* link: symtab index */
+ YASM_WRITE_32_L(bufp, shead->index); /* info: relocated's index */
+ YASM_WRITE_64Z_L(bufp, RELOC64_ALIGN); /* align */
+ YASM_WRITE_64Z_L(bufp, RELOC64A_SIZE); /* entity size */
+}
+
+static void
+elf_x86_amd64_handle_reloc_addend(yasm_intnum *intn,
+ elf_reloc_entry *reloc,
+ unsigned long offset)
+{
+ /* .rela: copy value out as addend, replace original with 0 */
+ reloc->addend = yasm_intnum_copy(intn);
+ yasm_intnum_zero(intn);
+}
+
+static unsigned int
+elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc)
+{
+ if (reloc->wrt) {
+ const elf_machine_ssym *ssym = (elf_machine_ssym *)
+ yasm_symrec_get_data(reloc->wrt, &elf_ssym_symrec_data);
+ if (!ssym || reloc->valsize != ssym->size)
+ yasm_internal_error(N_("Unsupported WRT"));
+
+ /* Force TLS type; this is required by the linker. */
+ if (ssym->sym_rel & ELF_SSYM_THREAD_LOCAL) {
+ elf_symtab_entry *esym;
+
+ esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
+ if (esym)
+ esym->type = STT_TLS;
+ }
+ /* Map PC-relative GOT to appropriate relocation */
+ if (reloc->rtype_rel && ssym->reloc == R_X86_64_GOT32)
+ return (unsigned char) R_X86_64_GOTPCREL;
+ return (unsigned char) ssym->reloc;
+ } else if (reloc->is_GOT_sym && reloc->valsize == 32) {
+ return (unsigned char) R_X86_64_GOTPC32;
+ } else if (reloc->is_GOT_sym && reloc->valsize == 64) {
+ return (unsigned char) R_X86_64_GOTPC64;
+ } else if (reloc->rtype_rel) {
+ switch (reloc->valsize) {
+ case 8: return (unsigned char) R_X86_64_PC8;
+ case 16: return (unsigned char) R_X86_64_PC16;
+ case 32: return (unsigned char) R_X86_64_PC32;
+ case 64: return (unsigned char) R_X86_64_PC64;
+ default: yasm_internal_error(N_("Unsupported relocation size"));
+ }
+ } else {
+ switch (reloc->valsize) {
+ case 8: return (unsigned char) R_X86_64_8;
+ case 16: return (unsigned char) R_X86_64_16;
+ case 32: return (unsigned char) R_X86_64_32;
+ case 64: return (unsigned char) R_X86_64_64;
+ default: yasm_internal_error(N_("Unsupported relocation size"));
+ }
+ }
+ return 0;
+}
+
+static void
+elf_x86_amd64_write_reloc(unsigned char *bufp, elf_reloc_entry *reloc,
+ unsigned int r_type, unsigned int r_sym)
+{
+ YASM_WRITE_64I_L(bufp, reloc->reloc.addr);
+ /*YASM_WRITE_64_L(bufp, ELF64_R_INFO(r_sym, r_type));*/
+ YASM_WRITE_64C_L(bufp, r_sym, r_type);
+ if (reloc->addend)
+ YASM_WRITE_64I_L(bufp, reloc->addend);
+ else {
+ YASM_WRITE_32_L(bufp, 0);
+ YASM_WRITE_32_L(bufp, 0);
+ }
+}
+
+static void
+elf_x86_amd64_write_proghead(unsigned char **bufpp,
+ elf_offset secthead_addr,
+ unsigned long secthead_count,
+ elf_section_index shstrtab_index)
+{
+ unsigned char *bufp = *bufpp;
+ unsigned char *buf = bufp-4;
+ YASM_WRITE_8(bufp, ELFCLASS64); /* elf class */
+ YASM_WRITE_8(bufp, ELFDATA2LSB); /* data encoding :: MSB? */
+ YASM_WRITE_8(bufp, EV_CURRENT); /* elf version */
+ YASM_WRITE_8(bufp, ELFOSABI_SYSV); /* os/abi */
+ YASM_WRITE_8(bufp, 0); /* SYSV v3 ABI=0 */
+ while (bufp-buf < EI_NIDENT) /* e_ident padding */
+ YASM_WRITE_8(bufp, 0);
+
+ YASM_WRITE_16_L(bufp, ET_REL); /* e_type - object file */
+ YASM_WRITE_16_L(bufp, EM_X86_64); /* e_machine - or others */
+ YASM_WRITE_32_L(bufp, EV_CURRENT); /* elf version */
+ YASM_WRITE_64Z_L(bufp, 0); /* e_entry */
+ YASM_WRITE_64Z_L(bufp, 0); /* e_phoff */
+ YASM_WRITE_64Z_L(bufp, secthead_addr); /* e_shoff secthead off */
+
+ YASM_WRITE_32_L(bufp, 0); /* e_flags */
+ YASM_WRITE_16_L(bufp, EHDR64_SIZE); /* e_ehsize */
+ YASM_WRITE_16_L(bufp, 0); /* e_phentsize */
+ YASM_WRITE_16_L(bufp, 0); /* e_phnum */
+ YASM_WRITE_16_L(bufp, SHDR64_SIZE); /* e_shentsize */
+ YASM_WRITE_16_L(bufp, secthead_count); /* e_shnum */
+ YASM_WRITE_16_L(bufp, shstrtab_index); /* e_shstrndx */
+ *bufpp = bufp;
+}
+
+const elf_machine_handler
+elf_machine_handler_x86_amd64 = {
+ "x86", "amd64", ".rela",
+ SYMTAB64_SIZE, SYMTAB64_ALIGN, RELOC64A_SIZE, SHDR64_SIZE, EHDR64_SIZE,
+ elf_x86_amd64_accepts_reloc,
+ elf_x86_amd64_write_symtab_entry,
+ elf_x86_amd64_write_secthead,
+ elf_x86_amd64_write_secthead_rel,
+ elf_x86_amd64_handle_reloc_addend,
+ elf_x86_amd64_map_reloc_info_to_type,
+ elf_x86_amd64_write_reloc,
+ elf_x86_amd64_write_proghead,
+ elf_x86_amd64_ssyms,
+ sizeof(elf_x86_amd64_ssyms)/sizeof(elf_x86_amd64_ssyms[0]),
+ 64
+};
diff --git a/contrib/tools/yasm/modules/objfmts/elf/elf-x86-x32.c b/contrib/tools/yasm/modules/objfmts/elf/elf-x86-x32.c
new file mode 100644
index 0000000000..40a25a12a7
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/elf/elf-x86-x32.c
@@ -0,0 +1,251 @@
+/*
+ * ELF object format helpers - x86:x32
+ *
+ * Copyright (C) 2012 Michael Urman and H.J. Lu
+ *
+ * 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 <util.h>
+
+#include <libyasm.h>
+#define YASM_OBJFMT_ELF_INTERNAL
+#include "elf.h"
+#include "elf-machine.h"
+
+static elf_machine_ssym elf_x86_x32_ssyms[] = {
+ {"plt", ELF_SSYM_SYM_RELATIVE, R_X86_64_PLT32, 32},
+ {"gotpcrel", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTPCREL, 32},
+ {"tlsgd", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TLSGD, 32},
+ {"tlsld", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TLSLD, 32},
+ {"gottpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_GOTTPOFF, 32},
+ {"tpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TPOFF32, 32},
+ {"dtpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_DTPOFF32, 32},
+ {"got", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOT32, 32},
+ {"tlsdesc", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_GOTPC32_TLSDESC, 32},
+ {"tlscall", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_X86_64_TLSDESC_CALL, 32}
+};
+
+static int
+elf_x86_x32_accepts_reloc(size_t val, yasm_symrec *wrt)
+{
+ if (wrt) {
+ const elf_machine_ssym *ssym = (elf_machine_ssym *)
+ yasm_symrec_get_data(wrt, &elf_ssym_symrec_data);
+ if (!ssym || val != ssym->size)
+ return 0;
+ return 1;
+ }
+ return (val&(val-1)) ? 0 : ((val & (8|16|32)) != 0);
+}
+
+static void
+elf_x86_x32_write_symtab_entry(unsigned char *bufp,
+ elf_symtab_entry *entry,
+ yasm_intnum *value_intn,
+ yasm_intnum *size_intn)
+{
+ YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0);
+ YASM_WRITE_32I_L(bufp, value_intn);
+ YASM_WRITE_32I_L(bufp, size_intn);
+
+ YASM_WRITE_8(bufp, ELF32_ST_INFO(entry->bind, entry->type));
+ YASM_WRITE_8(bufp, ELF32_ST_OTHER(entry->vis));
+ if (entry->sect) {
+ elf_secthead *shead =
+ yasm_section_get_data(entry->sect, &elf_section_data);
+ if (!shead)
+ yasm_internal_error(N_("symbol references section without data"));
+ YASM_WRITE_16_L(bufp, shead->index);
+ } else {
+ YASM_WRITE_16_L(bufp, entry->index);
+ }
+}
+
+static void
+elf_x86_x32_write_secthead(unsigned char *bufp, elf_secthead *shead)
+{
+ YASM_WRITE_32_L(bufp, shead->name ? shead->name->index : 0);
+ YASM_WRITE_32_L(bufp, shead->type);
+ YASM_WRITE_32_L(bufp, shead->flags);
+ YASM_WRITE_32_L(bufp, 0); /* vmem address */
+ YASM_WRITE_32_L(bufp, shead->offset);
+ YASM_WRITE_32I_L(bufp, shead->size);
+
+ YASM_WRITE_32_L(bufp, shead->link);
+ YASM_WRITE_32_L(bufp, shead->info);
+
+ YASM_WRITE_32_L(bufp, shead->align);
+ YASM_WRITE_32_L(bufp, shead->entsize);
+}
+
+static void
+elf_x86_x32_write_secthead_rel(unsigned char *bufp,
+ elf_secthead *shead,
+ elf_section_index symtab_idx,
+ elf_section_index sindex)
+{
+ yasm_intnum *nreloc;
+ yasm_intnum *relocsize;
+
+ YASM_WRITE_32_L(bufp, shead->rel_name ? shead->rel_name->index : 0);
+ YASM_WRITE_32_L(bufp, SHT_RELA);
+ YASM_WRITE_32_L(bufp, 0);
+ YASM_WRITE_32_L(bufp, 0);
+ YASM_WRITE_32_L(bufp, shead->rel_offset);
+
+ nreloc = yasm_intnum_create_uint(shead->nreloc);
+ relocsize = yasm_intnum_create_uint(RELOC32A_SIZE);
+ yasm_intnum_calc(relocsize, YASM_EXPR_MUL, nreloc);
+ YASM_WRITE_32I_L(bufp, relocsize); /* size */
+ yasm_intnum_destroy(nreloc);
+ yasm_intnum_destroy(relocsize);
+
+ YASM_WRITE_32_L(bufp, symtab_idx); /* link: symtab index */
+ YASM_WRITE_32_L(bufp, shead->index); /* info: relocated's index */
+ YASM_WRITE_32_L(bufp, RELOC32_ALIGN); /* align */
+ YASM_WRITE_32_L(bufp, RELOC32A_SIZE); /* entity size */
+}
+
+static void
+elf_x86_x32_handle_reloc_addend(yasm_intnum *intn,
+ elf_reloc_entry *reloc,
+ unsigned long offset)
+{
+ /* .rela: copy value out as addend, replace original with 0 */
+ reloc->addend = yasm_intnum_copy(intn);
+ yasm_intnum_zero(intn);
+}
+
+static unsigned int
+elf_x86_x32_map_reloc_info_to_type(elf_reloc_entry *reloc)
+{
+ if (reloc->wrt) {
+ const elf_machine_ssym *ssym = (elf_machine_ssym *)
+ yasm_symrec_get_data(reloc->wrt, &elf_ssym_symrec_data);
+ if (!ssym || reloc->valsize != ssym->size)
+ yasm_internal_error(N_("Unsupported WRT"));
+
+ /* Force TLS type; this is required by the linker. */
+ if (ssym->sym_rel & ELF_SSYM_THREAD_LOCAL) {
+ elf_symtab_entry *esym;
+
+ esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
+ if (esym)
+ esym->type = STT_TLS;
+ }
+ /* Map PC-relative GOT to appropriate relocation */
+ if (reloc->rtype_rel && ssym->reloc == R_X86_64_GOT32)
+ return (unsigned char) R_X86_64_GOTPCREL;
+ return (unsigned char) ssym->reloc;
+ } else if (reloc->is_GOT_sym && reloc->valsize == 32) {
+ return (unsigned char) R_X86_64_GOTPC32;
+ } else if (reloc->is_GOT_sym && reloc->valsize == 64) {
+ yasm_internal_error(N_("Unsupported relocation size"));
+ } else if (reloc->rtype_rel) {
+ switch (reloc->valsize) {
+ case 8: return (unsigned char) R_X86_64_PC8;
+ case 16: return (unsigned char) R_X86_64_PC16;
+ case 32: return (unsigned char) R_X86_64_PC32;
+ default: yasm_internal_error(N_("Unsupported relocation size"));
+ }
+ } else {
+ switch (reloc->valsize) {
+ case 8: return (unsigned char) R_X86_64_8;
+ case 16: return (unsigned char) R_X86_64_16;
+ case 32: return (unsigned char) R_X86_64_32;
+ case 64: return (unsigned char) R_X86_64_64;
+ default: yasm_internal_error(N_("Unsupported relocation size"));
+ }
+ }
+ return 0;
+}
+
+static void
+elf_x86_x32_write_reloc(unsigned char *bufp, elf_reloc_entry *reloc,
+ unsigned int r_type, unsigned int r_sym)
+{
+ YASM_WRITE_32I_L(bufp, reloc->reloc.addr);
+ YASM_WRITE_32_L(bufp, ELF32_R_INFO((unsigned long)r_sym, (unsigned char)r_type));
+ if (reloc->addend)
+ YASM_WRITE_32I_L(bufp, reloc->addend);
+ else {
+ YASM_WRITE_32_L(bufp, 0);
+ }
+}
+
+static void
+elf_x86_x32_write_proghead(unsigned char **bufpp,
+ elf_offset secthead_addr,
+ unsigned long secthead_count,
+ elf_section_index shstrtab_index)
+{
+ unsigned char *bufp = *bufpp;
+ unsigned char *buf = bufp-4;
+ YASM_WRITE_8(bufp, ELFCLASS32); /* elf class */
+ YASM_WRITE_8(bufp, ELFDATA2LSB); /* data encoding :: MSB? */
+ YASM_WRITE_8(bufp, EV_CURRENT); /* elf version */
+ YASM_WRITE_8(bufp, ELFOSABI_SYSV); /* os/abi */
+ YASM_WRITE_8(bufp, 0); /* SYSV v3 ABI=0 */
+ while (bufp-buf < EI_NIDENT) /* e_ident padding */
+ YASM_WRITE_8(bufp, 0);
+
+ YASM_WRITE_16_L(bufp, ET_REL); /* e_type - object file */
+ YASM_WRITE_16_L(bufp, EM_X86_64); /* e_machine - or others */
+ YASM_WRITE_32_L(bufp, EV_CURRENT); /* elf version */
+ YASM_WRITE_32_L(bufp, 0); /* e_entry */
+ YASM_WRITE_32_L(bufp, 0); /* e_phoff */
+ YASM_WRITE_32_L(bufp, secthead_addr); /* e_shoff secthead off */
+
+ YASM_WRITE_32_L(bufp, 0); /* e_flags */
+ YASM_WRITE_16_L(bufp, EHDR32_SIZE); /* e_ehsize */
+ YASM_WRITE_16_L(bufp, 0); /* e_phentsize */
+ YASM_WRITE_16_L(bufp, 0); /* e_phnum */
+ YASM_WRITE_16_L(bufp, SHDR32_SIZE); /* e_shentsize */
+ YASM_WRITE_16_L(bufp, secthead_count); /* e_shnum */
+ YASM_WRITE_16_L(bufp, shstrtab_index); /* e_shstrndx */
+ *bufpp = bufp;
+}
+
+const elf_machine_handler
+elf_machine_handler_x86_x32 = {
+ "x86", "x32", ".rela",
+ SYMTAB32_SIZE, SYMTAB32_ALIGN, RELOC32A_SIZE, SHDR32_SIZE, EHDR32_SIZE,
+ elf_x86_x32_accepts_reloc,
+ elf_x86_x32_write_symtab_entry,
+ elf_x86_x32_write_secthead,
+ elf_x86_x32_write_secthead_rel,
+ elf_x86_x32_handle_reloc_addend,
+ elf_x86_x32_map_reloc_info_to_type,
+ elf_x86_x32_write_reloc,
+ elf_x86_x32_write_proghead,
+ elf_x86_x32_ssyms,
+ sizeof(elf_x86_x32_ssyms)/sizeof(elf_x86_x32_ssyms[0]),
+ 32
+};
diff --git a/contrib/tools/yasm/modules/objfmts/elf/elf-x86-x86.c b/contrib/tools/yasm/modules/objfmts/elf/elf-x86-x86.c
new file mode 100644
index 0000000000..d79ec6eabd
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/elf/elf-x86-x86.c
@@ -0,0 +1,242 @@
+/*
+ * ELF object format helpers - x86:x86
+ *
+ * Copyright (C) 2004-2007 Michael Urman
+ *
+ * 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 <util.h>
+
+#include <libyasm.h>
+#define YASM_OBJFMT_ELF_INTERNAL
+#include "elf.h"
+#include "elf-machine.h"
+
+static elf_machine_ssym elf_x86_x86_ssyms[] = {
+ {"plt", ELF_SSYM_SYM_RELATIVE, R_386_PLT32, 32},
+ {"gotoff", 0, R_386_GOTOFF, 32},
+ /* special one for NASM */
+ {"gotpc", ELF_SSYM_CURPOS_ADJUST, R_386_GOTPC, 32},
+ {"tlsgd", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_GD, 32},
+ {"tlsldm", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_LDM, 32},
+ {"gottpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_IE_32, 32},
+ {"tpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_LE_32, 32},
+ {"ntpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_LE, 32},
+ {"dtpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_LDO_32, 32},
+ {"gotntpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_GOTIE, 32},
+ {"indntpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_IE, 32},
+ {"got", ELF_SSYM_SYM_RELATIVE, R_386_GOT32, 32},
+ {"tlsdesc", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_GOTDESC, 32},
+ {"tlscall", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+ R_386_TLS_DESC_CALL, 32}
+};
+
+static int
+elf_x86_x86_accepts_reloc(size_t val, yasm_symrec *wrt)
+{
+ if (wrt) {
+ const elf_machine_ssym *ssym = (elf_machine_ssym *)
+ yasm_symrec_get_data(wrt, &elf_ssym_symrec_data);
+ if (!ssym || val != ssym->size)
+ return 0;
+ return 1;
+ }
+ return (val&(val-1)) ? 0 : ((val & (8|16|32)) != 0);
+}
+
+static void
+elf_x86_x86_write_symtab_entry(unsigned char *bufp,
+ elf_symtab_entry *entry,
+ yasm_intnum *value_intn,
+ yasm_intnum *size_intn)
+{
+ YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0);
+ YASM_WRITE_32I_L(bufp, value_intn);
+ YASM_WRITE_32I_L(bufp, size_intn);
+
+ YASM_WRITE_8(bufp, ELF32_ST_INFO(entry->bind, entry->type));
+ YASM_WRITE_8(bufp, ELF32_ST_OTHER(entry->vis));
+ if (entry->sect) {
+ elf_secthead *shead =
+ yasm_section_get_data(entry->sect, &elf_section_data);
+ if (!shead)
+ yasm_internal_error(N_("symbol references section without data"));
+ YASM_WRITE_16_L(bufp, shead->index);
+ } else {
+ YASM_WRITE_16_L(bufp, entry->index);
+ }
+}
+
+static void
+elf_x86_x86_write_secthead(unsigned char *bufp, elf_secthead *shead)
+{
+ YASM_WRITE_32_L(bufp, shead->name ? shead->name->index : 0);
+ YASM_WRITE_32_L(bufp, shead->type);
+ YASM_WRITE_32_L(bufp, shead->flags);
+ YASM_WRITE_32_L(bufp, 0); /* vmem address */
+
+ YASM_WRITE_32_L(bufp, shead->offset);
+ YASM_WRITE_32I_L(bufp, shead->size);
+ YASM_WRITE_32_L(bufp, shead->link);
+ YASM_WRITE_32_L(bufp, shead->info);
+
+ YASM_WRITE_32_L(bufp, shead->align);
+ YASM_WRITE_32_L(bufp, shead->entsize);
+
+}
+
+static void
+elf_x86_x86_write_secthead_rel(unsigned char *bufp,
+ elf_secthead *shead,
+ elf_section_index symtab_idx,
+ elf_section_index sindex)
+{
+ YASM_WRITE_32_L(bufp, shead->rel_name ? shead->rel_name->index : 0);
+ YASM_WRITE_32_L(bufp, SHT_REL);
+ YASM_WRITE_32_L(bufp, 0);
+ YASM_WRITE_32_L(bufp, 0);
+
+ YASM_WRITE_32_L(bufp, shead->rel_offset);
+ YASM_WRITE_32_L(bufp, RELOC32_SIZE * shead->nreloc);/* size */
+ YASM_WRITE_32_L(bufp, symtab_idx); /* link: symtab index */
+ YASM_WRITE_32_L(bufp, shead->index); /* info: relocated's index */
+
+ YASM_WRITE_32_L(bufp, RELOC32_ALIGN); /* align */
+ YASM_WRITE_32_L(bufp, RELOC32_SIZE); /* entity size */
+}
+
+static void
+elf_x86_x86_handle_reloc_addend(yasm_intnum *intn,
+ elf_reloc_entry *reloc,
+ unsigned long offset)
+{
+ if (!reloc->wrt && reloc->is_GOT_sym && reloc->valsize == 32 && offset != 0)
+ {
+ yasm_intnum *off_intn = yasm_intnum_create_uint(offset);
+ yasm_intnum_calc(intn, YASM_EXPR_ADD, off_intn);
+ yasm_intnum_destroy(off_intn);
+ }
+ return; /* .rel: Leave addend in intn */
+}
+
+static unsigned int
+elf_x86_x86_map_reloc_info_to_type(elf_reloc_entry *reloc)
+{
+ if (reloc->wrt) {
+ const elf_machine_ssym *ssym = (elf_machine_ssym *)
+ yasm_symrec_get_data(reloc->wrt, &elf_ssym_symrec_data);
+ if (!ssym || reloc->valsize != ssym->size)
+ yasm_internal_error(N_("Unsupported WRT"));
+
+ /* Force TLS type; this is required by the linker. */
+ if (ssym->sym_rel & ELF_SSYM_THREAD_LOCAL) {
+ elf_symtab_entry *esym;
+
+ esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
+ if (esym)
+ esym->type = STT_TLS;
+ }
+ return (unsigned char) ssym->reloc;
+ } else if (reloc->is_GOT_sym && reloc->valsize == 32) {
+ return (unsigned char) R_386_GOTPC;
+ } else if (reloc->rtype_rel) {
+ switch (reloc->valsize) {
+ case 8: return (unsigned char) R_386_PC8;
+ case 16: return (unsigned char) R_386_PC16;
+ case 32: return (unsigned char) R_386_PC32;
+ default: yasm_internal_error(N_("Unsupported relocation size"));
+ }
+ } else {
+ switch (reloc->valsize) {
+ case 8: return (unsigned char) R_386_8;
+ case 16: return (unsigned char) R_386_16;
+ case 32: return (unsigned char) R_386_32;
+ default: yasm_internal_error(N_("Unsupported relocation size"));
+ }
+ }
+ return 0;
+}
+
+static void
+elf_x86_x86_write_reloc(unsigned char *bufp, elf_reloc_entry *reloc,
+ unsigned int r_type, unsigned int r_sym)
+{
+ YASM_WRITE_32I_L(bufp, reloc->reloc.addr);
+ YASM_WRITE_32_L(bufp, ELF32_R_INFO((unsigned long)r_sym, (unsigned char)r_type));
+}
+
+static void
+elf_x86_x86_write_proghead(unsigned char **bufpp,
+ elf_offset secthead_addr,
+ unsigned long secthead_count,
+ elf_section_index shstrtab_index)
+{
+ unsigned char *bufp = *bufpp;
+ unsigned char *buf = bufp-4;
+ YASM_WRITE_8(bufp, ELFCLASS32); /* elf class */
+ YASM_WRITE_8(bufp, ELFDATA2LSB); /* data encoding :: MSB? */
+ YASM_WRITE_8(bufp, EV_CURRENT); /* elf version */
+ while (bufp-buf < EI_NIDENT) /* e_ident padding */
+ YASM_WRITE_8(bufp, 0);
+
+ YASM_WRITE_16_L(bufp, ET_REL); /* e_type - object file */
+ YASM_WRITE_16_L(bufp, EM_386); /* e_machine - or others */
+ YASM_WRITE_32_L(bufp, EV_CURRENT); /* elf version */
+ YASM_WRITE_32_L(bufp, 0); /* e_entry exection startaddr */
+ YASM_WRITE_32_L(bufp, 0); /* e_phoff program header off */
+ YASM_WRITE_32_L(bufp, secthead_addr); /* e_shoff section header off */
+ YASM_WRITE_32_L(bufp, 0); /* e_flags also by arch */
+ YASM_WRITE_16_L(bufp, EHDR32_SIZE); /* e_ehsize */
+ YASM_WRITE_16_L(bufp, 0); /* e_phentsize */
+ YASM_WRITE_16_L(bufp, 0); /* e_phnum */
+ YASM_WRITE_16_L(bufp, SHDR32_SIZE); /* e_shentsize */
+ YASM_WRITE_16_L(bufp, secthead_count); /* e_shnum */
+ YASM_WRITE_16_L(bufp, shstrtab_index); /* e_shstrndx */
+ *bufpp = bufp;
+}
+
+const elf_machine_handler
+elf_machine_handler_x86_x86 = {
+ "x86", "x86", ".rel",
+ SYMTAB32_SIZE, SYMTAB32_ALIGN, RELOC32_SIZE, SHDR32_SIZE, EHDR32_SIZE,
+ elf_x86_x86_accepts_reloc,
+ elf_x86_x86_write_symtab_entry,
+ elf_x86_x86_write_secthead,
+ elf_x86_x86_write_secthead_rel,
+ elf_x86_x86_handle_reloc_addend,
+ elf_x86_x86_map_reloc_info_to_type,
+ elf_x86_x86_write_reloc,
+ elf_x86_x86_write_proghead,
+ elf_x86_x86_ssyms,
+ sizeof(elf_x86_x86_ssyms)/sizeof(elf_x86_x86_ssyms[0]),
+ 32
+};
diff --git a/contrib/tools/yasm/modules/objfmts/elf/elf.c b/contrib/tools/yasm/modules/objfmts/elf/elf.c
new file mode 100644
index 0000000000..2486bba8df
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/elf/elf.c
@@ -0,0 +1,960 @@
+/*
+ * ELF object format helpers
+ *
+ * Copyright (C) 2003-2007 Michael Urman
+ *
+ * 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 <util.h>
+
+#include <libyasm.h>
+#define YASM_OBJFMT_ELF_INTERNAL
+#include "elf.h"
+#include "elf-machine.h"
+
+static void elf_section_data_destroy(void *data);
+static void elf_secthead_print(void *data, FILE *f, int indent_level);
+
+const yasm_assoc_data_callback elf_section_data = {
+ elf_section_data_destroy,
+ elf_secthead_print
+};
+
+static void elf_symrec_data_destroy(/*@only@*/ void *d);
+static void elf_symtab_entry_print(void *data, FILE *f, int indent_level);
+static void elf_ssym_symtab_entry_print(void *data, FILE *f, int indent_level);
+
+const yasm_assoc_data_callback elf_symrec_data = {
+ elf_symrec_data_destroy,
+ elf_symtab_entry_print
+};
+
+const yasm_assoc_data_callback elf_ssym_symrec_data = {
+ elf_symrec_data_destroy,
+ elf_ssym_symtab_entry_print
+};
+
+extern elf_machine_handler
+ elf_machine_handler_x86_x86,
+ elf_machine_handler_x86_amd64,
+ elf_machine_handler_x86_x32;
+
+static const elf_machine_handler *elf_machine_handlers[] =
+{
+ &elf_machine_handler_x86_x86,
+ &elf_machine_handler_x86_amd64,
+ &elf_machine_handler_x86_x32,
+ NULL
+};
+static const elf_machine_handler elf_null_machine = {0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0};
+static elf_machine_handler const *elf_march = &elf_null_machine;
+static yasm_symrec **elf_ssyms;
+
+const elf_machine_handler *
+elf_set_arch(yasm_arch *arch, yasm_symtab *symtab, int bits_pref)
+{
+ const char *machine = yasm_arch_get_machine(arch);
+ int i;
+
+ for (i=0, elf_march = elf_machine_handlers[0];
+ elf_march != NULL;
+ elf_march = elf_machine_handlers[++i])
+ {
+ if (yasm__strcasecmp(yasm_arch_keyword(arch), elf_march->arch)==0) {
+ if (yasm__strcasecmp(machine, elf_march->machine)==0) {
+ if (bits_pref == 0 || bits_pref == elf_march->bits)
+ break;
+ } else if (bits_pref == elf_march->bits
+ && yasm__strcasecmp(machine, "amd64") == 0
+ && yasm__strcasecmp(elf_march->machine, "x32") == 0)
+ break;
+ }
+ }
+
+ if (elf_march && elf_march->num_ssyms > 0)
+ {
+ /* Allocate "special" syms */
+ elf_ssyms =
+ yasm_xmalloc(elf_march->num_ssyms * sizeof(yasm_symrec *));
+ for (i=0; (unsigned int)i<elf_march->num_ssyms; i++)
+ {
+ /* FIXME: misuse of NULL bytecode */
+ elf_ssyms[i] = yasm_symtab_define_label(symtab,
+ elf_march->ssyms[i].name,
+ NULL, 0, 0);
+ yasm_symrec_add_data(elf_ssyms[i], &elf_ssym_symrec_data,
+ (void*)&elf_march->ssyms[i]);
+ }
+ }
+
+ return elf_march;
+}
+
+yasm_symrec *
+elf_get_special_sym(const char *name, const char *parser)
+{
+ int i;
+ for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) {
+ if (yasm__strcasecmp(name, elf_march->ssyms[i].name) == 0)
+ return elf_ssyms[i];
+ }
+ return NULL;
+}
+
+/* reloc functions */
+int elf_ssym_has_flag(yasm_symrec *wrt, int flag);
+
+int
+elf_is_wrt_sym_relative(yasm_symrec *wrt)
+{
+ return elf_ssym_has_flag(wrt, ELF_SSYM_SYM_RELATIVE);
+}
+
+int
+elf_is_wrt_pos_adjusted(yasm_symrec *wrt)
+{
+ return elf_ssym_has_flag(wrt, ELF_SSYM_CURPOS_ADJUST);
+}
+
+int
+elf_ssym_has_flag(yasm_symrec *wrt, int flag)
+{
+ int i;
+ for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) {
+ if (elf_ssyms[i] == wrt)
+ return (elf_march->ssyms[i].sym_rel & flag) != 0;
+ }
+ return 0;
+}
+
+/* takes ownership of addr */
+elf_reloc_entry *
+elf_reloc_entry_create(yasm_symrec *sym,
+ yasm_symrec *wrt,
+ yasm_intnum *addr,
+ int rel,
+ size_t valsize,
+ int is_GOT_sym)
+{
+ elf_reloc_entry *entry;
+
+ if (!elf_march->accepts_reloc)
+ yasm_internal_error(N_("Unsupported machine for ELF output"));
+
+ if (!elf_march->accepts_reloc(valsize, wrt))
+ {
+ if (addr)
+ yasm_intnum_destroy(addr);
+ return NULL;
+ }
+
+ if (sym == NULL)
+ yasm_internal_error("sym is null");
+
+ entry = yasm_xmalloc(sizeof(elf_reloc_entry));
+ entry->reloc.sym = sym;
+ entry->reloc.addr = addr;
+ entry->rtype_rel = rel;
+ entry->valsize = valsize;
+ entry->addend = NULL;
+ entry->wrt = wrt;
+ entry->is_GOT_sym = is_GOT_sym;
+
+ return entry;
+}
+
+void
+elf_reloc_entry_destroy(void *entry)
+{
+ if (((elf_reloc_entry*)entry)->addend)
+ yasm_intnum_destroy(((elf_reloc_entry*)entry)->addend);
+ yasm_xfree(entry);
+}
+
+/* strtab functions */
+elf_strtab_entry *
+elf_strtab_entry_create(const char *str)
+{
+ elf_strtab_entry *entry = yasm_xmalloc(sizeof(elf_strtab_entry));
+ entry->str = yasm__xstrdup(str);
+ entry->index = 0;
+ return entry;
+}
+
+void
+elf_strtab_entry_set_str(elf_strtab_entry *entry, const char *str)
+{
+ elf_strtab_entry *last;
+ if (entry->str)
+ yasm_xfree(entry->str);
+ entry->str = yasm__xstrdup(str);
+
+ /* Update all following indices since string length probably changes */
+ last = entry;
+ entry = STAILQ_NEXT(last, qlink);
+ while (entry) {
+ entry->index = last->index + (unsigned long)strlen(last->str) + 1;
+ last = entry;
+ entry = STAILQ_NEXT(last, qlink);
+ }
+}
+
+elf_strtab_head *
+elf_strtab_create()
+{
+ elf_strtab_head *strtab = yasm_xmalloc(sizeof(elf_strtab_head));
+ elf_strtab_entry *entry = yasm_xmalloc(sizeof(elf_strtab_entry));
+
+ STAILQ_INIT(strtab);
+ entry->index = 0;
+ entry->str = yasm__xstrdup("");
+
+ STAILQ_INSERT_TAIL(strtab, entry, qlink);
+ return strtab;
+}
+
+elf_strtab_entry *
+elf_strtab_append_str(elf_strtab_head *strtab, const char *str)
+{
+ elf_strtab_entry *last, *entry;
+
+ if (strtab == NULL)
+ yasm_internal_error("strtab is null");
+ if (STAILQ_EMPTY(strtab))
+ yasm_internal_error("strtab is missing initial dummy entry");
+
+ last = STAILQ_LAST(strtab, elf_strtab_entry, qlink);
+
+ entry = elf_strtab_entry_create(str);
+ entry->index = last->index + (unsigned long)strlen(last->str) + 1;
+
+ STAILQ_INSERT_TAIL(strtab, entry, qlink);
+ return entry;
+}
+
+void
+elf_strtab_destroy(elf_strtab_head *strtab)
+{
+ elf_strtab_entry *s1, *s2;
+
+ if (strtab == NULL)
+ yasm_internal_error("strtab is null");
+ if (STAILQ_EMPTY(strtab))
+ yasm_internal_error("strtab is missing initial dummy entry");
+
+ s1 = STAILQ_FIRST(strtab);
+ while (s1 != NULL) {
+ s2 = STAILQ_NEXT(s1, qlink);
+ yasm_xfree(s1->str);
+ yasm_xfree(s1);
+ s1 = s2;
+ }
+ yasm_xfree(strtab);
+}
+
+unsigned long
+elf_strtab_output_to_file(FILE *f, elf_strtab_head *strtab)
+{
+ unsigned long size = 0;
+ elf_strtab_entry *entry;
+
+ if (strtab == NULL)
+ yasm_internal_error("strtab is null");
+
+ /* consider optimizing tables here */
+ STAILQ_FOREACH(entry, strtab, qlink) {
+ size_t len = 1 + strlen(entry->str);
+ fwrite(entry->str, len, 1, f);
+ size += (unsigned long)len;
+ }
+ return size;
+}
+
+
+
+/* symtab functions */
+elf_symtab_entry *
+elf_symtab_entry_create(elf_strtab_entry *name,
+ yasm_symrec *sym)
+{
+ elf_symtab_entry *entry = yasm_xmalloc(sizeof(elf_symtab_entry));
+ entry->in_table = 0;
+ entry->sym = sym;
+ entry->sect = NULL;
+ entry->name = name;
+ entry->value = 0;
+
+ entry->xsize = NULL;
+ entry->size = 0;
+ entry->index = 0;
+ entry->bind = 0;
+ entry->type = STT_NOTYPE;
+ entry->vis = STV_DEFAULT;
+
+ return entry;
+}
+
+static void
+elf_symtab_entry_destroy(elf_symtab_entry *entry)
+{
+ if (entry == NULL)
+ yasm_internal_error("symtab entry is null");
+
+ yasm_xfree(entry);
+}
+
+static void
+elf_symrec_data_destroy(void *data)
+{
+ /* do nothing, as this stuff is in the symtab anyway... this speaks of bad
+ * design/use or this stuff, i fear */
+
+ /* watch for double-free here ... */
+ /*elf_symtab_entry_destroy((elf_symtab_entry *)data);*/
+}
+
+static void
+elf_symtab_entry_print(void *data, FILE *f, int indent_level)
+{
+ elf_symtab_entry *entry = data;
+ if (entry == NULL)
+ yasm_internal_error("symtab entry is null");
+
+ fprintf(f, "%*sbind=", indent_level, "");
+ switch (entry->bind) {
+ case STB_LOCAL: fprintf(f, "local\n"); break;
+ case STB_GLOBAL: fprintf(f, "global\n"); break;
+ case STB_WEAK: fprintf(f, "weak\n"); break;
+ default: fprintf(f, "undef\n"); break;
+ }
+ fprintf(f, "%*stype=", indent_level, "");
+ switch (entry->type) {
+ case STT_NOTYPE: fprintf(f, "notype\n"); break;
+ case STT_OBJECT: fprintf(f, "object\n"); break;
+ case STT_FUNC: fprintf(f, "func\n"); break;
+ case STT_SECTION: fprintf(f, "section\n");break;
+ case STT_FILE: fprintf(f, "file\n"); break;
+ default: fprintf(f, "undef\n"); break;
+ }
+ fprintf(f, "%*ssize=", indent_level, "");
+ if (entry->xsize)
+ yasm_expr_print(entry->xsize, f);
+ else
+ fprintf(f, "%ld", entry->size);
+ fprintf(f, "\n");
+}
+
+static void
+elf_ssym_symtab_entry_print(void *data, FILE *f, int indent_level)
+{
+ /* TODO */
+}
+
+elf_symtab_head *
+elf_symtab_create()
+{
+ elf_symtab_head *symtab = yasm_xmalloc(sizeof(elf_symtab_head));
+ elf_symtab_entry *entry = yasm_xmalloc(sizeof(elf_symtab_entry));
+
+ STAILQ_INIT(symtab);
+ entry->in_table = 1;
+ entry->sym = NULL;
+ entry->sect = NULL;
+ entry->name = NULL;
+ entry->value = 0;
+ entry->xsize = NULL;
+ entry->size = 0;
+ entry->index = SHN_UNDEF;
+ entry->bind = STB_LOCAL;
+ entry->type = STT_NOTYPE;
+ entry->vis = STV_DEFAULT;
+ entry->symindex = 0;
+ STAILQ_INSERT_TAIL(symtab, entry, qlink);
+ return symtab;
+}
+
+void
+elf_symtab_append_entry(elf_symtab_head *symtab, elf_symtab_entry *entry)
+{
+ if (symtab == NULL)
+ yasm_internal_error("symtab is null");
+ if (entry == NULL)
+ yasm_internal_error("symtab entry is null");
+ if (STAILQ_EMPTY(symtab))
+ yasm_internal_error(N_("symtab is missing initial dummy entry"));
+
+ STAILQ_INSERT_TAIL(symtab, entry, qlink);
+ entry->in_table = 1;
+}
+
+void
+elf_symtab_insert_local_sym(elf_symtab_head *symtab, elf_symtab_entry *entry)
+{
+ elf_symtab_entry *after = STAILQ_FIRST(symtab);
+ elf_symtab_entry *before = NULL;
+
+ while (after && (after->bind == STB_LOCAL)) {
+ before = after;
+ if (before->type == STT_FILE) break;
+ after = STAILQ_NEXT(after, qlink);
+ }
+ STAILQ_INSERT_AFTER(symtab, before, entry, qlink);
+ entry->in_table = 1;
+}
+
+void
+elf_symtab_destroy(elf_symtab_head *symtab)
+{
+ elf_symtab_entry *s1, *s2;
+
+ if (symtab == NULL)
+ yasm_internal_error("symtab is null");
+ if (STAILQ_EMPTY(symtab))
+ yasm_internal_error(N_("symtab is missing initial dummy entry"));
+
+ s1 = STAILQ_FIRST(symtab);
+ while (s1 != NULL) {
+ s2 = STAILQ_NEXT(s1, qlink);
+ elf_symtab_entry_destroy(s1);
+ s1 = s2;
+ }
+ yasm_xfree(symtab);
+}
+
+unsigned long
+elf_symtab_assign_indices(elf_symtab_head *symtab)
+{
+ elf_symtab_entry *entry, *prev=NULL;
+ unsigned long last_local=0;
+
+ if (symtab == NULL)
+ yasm_internal_error("symtab is null");
+ if (STAILQ_EMPTY(symtab))
+ yasm_internal_error(N_("symtab is missing initial dummy entry"));
+
+ STAILQ_FOREACH(entry, symtab, qlink) {
+ if (prev)
+ entry->symindex = prev->symindex + 1;
+ if (entry->bind == STB_LOCAL)
+ last_local = entry->symindex;
+ prev = entry;
+ }
+ return last_local + 1;
+}
+
+unsigned long
+elf_symtab_write_to_file(FILE *f, elf_symtab_head *symtab,
+ yasm_errwarns *errwarns)
+{
+ unsigned char buf[SYMTAB_MAXSIZE], *bufp;
+ elf_symtab_entry *entry;
+ unsigned long size = 0;
+
+ if (!symtab)
+ yasm_internal_error(N_("symtab is null"));
+
+ STAILQ_FOREACH(entry, symtab, qlink) {
+
+ yasm_intnum *size_intn=NULL, *value_intn=NULL;
+ bufp = buf;
+
+ /* get size (if specified); expr overrides stored integer */
+ if (entry->xsize) {
+ size_intn = yasm_intnum_copy(
+ yasm_expr_get_intnum(&entry->xsize, 1));
+ if (!size_intn) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("size specifier not an integer expression"));
+ yasm_errwarn_propagate(errwarns, entry->xsize->line);
+ }
+ }
+ else
+ size_intn = yasm_intnum_create_uint(entry->size);
+
+ /* get EQU value for constants */
+ if (entry->sym) {
+ const yasm_expr *equ_expr_c;
+ equ_expr_c = yasm_symrec_get_equ(entry->sym);
+
+ if (equ_expr_c != NULL) {
+ const yasm_intnum *equ_intn;
+ yasm_expr *equ_expr = yasm_expr_copy(equ_expr_c);
+ equ_intn = yasm_expr_get_intnum(&equ_expr, 1);
+
+ if (equ_intn == NULL) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("EQU value not an integer expression"));
+ yasm_errwarn_propagate(errwarns, equ_expr->line);
+ } else
+ value_intn = yasm_intnum_copy(equ_intn);
+ entry->index = SHN_ABS;
+ yasm_expr_destroy(equ_expr);
+ }
+ }
+ if (value_intn == NULL)
+ value_intn = yasm_intnum_create_uint(entry->value);
+
+ /* If symbol is in a TLS section, force its type to TLS. */
+ if (entry->sym) {
+ yasm_bytecode *precbc;
+ yasm_section *sect;
+ elf_secthead *shead;
+ if (yasm_symrec_get_label(entry->sym, &precbc) &&
+ (sect = yasm_bc_get_section(precbc)) &&
+ (shead = yasm_section_get_data(sect, &elf_section_data)) &&
+ shead->flags & SHF_TLS) {
+ entry->type = STT_TLS;
+ }
+ }
+
+ if (!elf_march->write_symtab_entry || !elf_march->symtab_entry_size)
+ yasm_internal_error(N_("Unsupported machine for ELF output"));
+ elf_march->write_symtab_entry(bufp, entry, value_intn, size_intn);
+ fwrite(buf, elf_march->symtab_entry_size, 1, f);
+ size += elf_march->symtab_entry_size;
+
+ yasm_intnum_destroy(size_intn);
+ yasm_intnum_destroy(value_intn);
+ }
+ return size;
+}
+
+void elf_symtab_set_nonzero(elf_symtab_entry *entry,
+ yasm_section *sect,
+ elf_section_index sectidx,
+ elf_symbol_binding bind,
+ elf_symbol_type type,
+ yasm_expr *xsize,
+ elf_address *value)
+{
+ if (!entry)
+ yasm_internal_error("NULL entry");
+ if (sect) entry->sect = sect;
+ if (sectidx) entry->index = sectidx;
+ if (bind) entry->bind = bind;
+ if (type) entry->type = type;
+ if (xsize) entry->xsize = xsize;
+ if (value) entry->value = *value;
+}
+
+void
+elf_sym_set_visibility(elf_symtab_entry *entry,
+ elf_symbol_vis vis)
+{
+ entry->vis = ELF_ST_VISIBILITY(vis);
+}
+
+void
+elf_sym_set_type(elf_symtab_entry *entry,
+ elf_symbol_type type)
+{
+ entry->type = type;
+}
+
+void
+elf_sym_set_size(elf_symtab_entry *entry,
+ struct yasm_expr *size)
+{
+ if (entry->xsize)
+ yasm_expr_destroy(entry->xsize);
+ entry->xsize = size;
+}
+
+int
+elf_sym_in_table(elf_symtab_entry *entry)
+{
+ return entry->in_table;
+}
+
+elf_secthead *
+elf_secthead_create(elf_strtab_entry *name,
+ elf_section_type type,
+ elf_section_flags flags,
+ elf_address offset,
+ elf_size size)
+{
+ elf_secthead *esd = yasm_xmalloc(sizeof(elf_secthead));
+
+ esd->type = type;
+ esd->flags = flags;
+ esd->offset = offset;
+ esd->size = yasm_intnum_create_uint(size);
+ esd->link = 0;
+ esd->info = 0;
+ esd->align = 0;
+ esd->entsize = 0;
+ esd->index = 0;
+
+ esd->sym = NULL;
+ esd->name = name;
+ esd->index = 0;
+ esd->rel_name = NULL;
+ esd->rel_index = 0;
+ esd->rel_offset = 0;
+ esd->nreloc = 0;
+
+ if (name && (strcmp(name->str, ".symtab") == 0)) {
+ if (!elf_march->symtab_entry_size || !elf_march->symtab_entry_align)
+ yasm_internal_error(N_("unsupported ELF format"));
+ esd->entsize = elf_march->symtab_entry_size;
+ esd->align = elf_march->symtab_entry_align;
+ }
+
+ return esd;
+}
+
+void
+elf_secthead_destroy(elf_secthead *shead)
+{
+ if (shead == NULL)
+ yasm_internal_error(N_("shead is null"));
+
+ yasm_intnum_destroy(shead->size);
+
+ yasm_xfree(shead);
+}
+
+static void
+elf_section_data_destroy(void *data)
+{
+ elf_secthead_destroy((elf_secthead *)data);
+}
+
+static void
+elf_secthead_print(void *data, FILE *f, int indent_level)
+{
+ elf_secthead *sect = data;
+ fprintf(f, "%*sname=%s\n", indent_level, "",
+ sect->name ? sect->name->str : "<undef>");
+ fprintf(f, "%*ssym=\n", indent_level, "");
+ yasm_symrec_print(sect->sym, f, indent_level+1);
+ fprintf(f, "%*sindex=0x%x\n", indent_level, "", sect->index);
+ fprintf(f, "%*sflags=", indent_level, "");
+ if (sect->flags & SHF_WRITE)
+ fprintf(f, "WRITE ");
+ if (sect->flags & SHF_ALLOC)
+ fprintf(f, "ALLOC ");
+ if (sect->flags & SHF_EXECINSTR)
+ fprintf(f, "EXEC ");
+ /*if (sect->flags & SHF_MASKPROC)
+ fprintf(f, "PROC-SPECIFIC"); */
+ fprintf(f, "%*soffset=0x%lx\n", indent_level, "", sect->offset);
+ fprintf(f, "%*ssize=0x%lx\n", indent_level, "",
+ yasm_intnum_get_uint(sect->size));
+ fprintf(f, "%*slink=0x%x\n", indent_level, "", sect->link);
+ fprintf(f, "%*salign=%lu\n", indent_level, "", sect->align);
+ fprintf(f, "%*snreloc=%ld\n", indent_level, "", sect->nreloc);
+}
+
+unsigned long
+elf_secthead_write_to_file(FILE *f, elf_secthead *shead,
+ elf_section_index sindex)
+{
+ unsigned char buf[SHDR_MAXSIZE], *bufp = buf;
+ shead->index = sindex;
+
+ if (shead == NULL)
+ yasm_internal_error("shead is null");
+
+ if (!elf_march->write_secthead || !elf_march->secthead_size)
+ yasm_internal_error(N_("Unsupported machine for ELF output"));
+ elf_march->write_secthead(bufp, shead);
+ if (fwrite(buf, elf_march->secthead_size, 1, f))
+ return elf_march->secthead_size;
+ yasm_internal_error(N_("Failed to write an elf section header"));
+ return 0;
+}
+
+void
+elf_secthead_append_reloc(yasm_section *sect, elf_secthead *shead,
+ elf_reloc_entry *reloc)
+{
+ if (sect == NULL)
+ yasm_internal_error("sect is null");
+ if (shead == NULL)
+ yasm_internal_error("shead is null");
+ if (reloc == NULL)
+ yasm_internal_error("reloc is null");
+
+ shead->nreloc++;
+ yasm_section_add_reloc(sect, (yasm_reloc *)reloc, elf_reloc_entry_destroy);
+}
+
+char *
+elf_secthead_name_reloc_section(const char *basesect)
+{
+ if (!elf_march->reloc_section_prefix)
+ {
+ yasm_internal_error(N_("Unsupported machine for ELF output"));
+ return NULL;
+ }
+ else
+ {
+ size_t prepend_length = strlen(elf_march->reloc_section_prefix);
+ char *sectname = yasm_xmalloc(prepend_length + strlen(basesect) + 1);
+ strcpy(sectname, elf_march->reloc_section_prefix);
+ strcat(sectname, basesect);
+ return sectname;
+ }
+}
+
+void
+elf_handle_reloc_addend(yasm_intnum *intn,
+ elf_reloc_entry *reloc,
+ unsigned long offset)
+{
+ if (!elf_march->handle_reloc_addend)
+ yasm_internal_error(N_("Unsupported machine for ELF output"));
+ elf_march->handle_reloc_addend(intn, reloc, offset);
+}
+
+unsigned long
+elf_secthead_write_rel_to_file(FILE *f, elf_section_index symtab_idx,
+ yasm_section *sect, elf_secthead *shead,
+ elf_section_index sindex)
+{
+ unsigned char buf[SHDR_MAXSIZE], *bufp = buf;
+
+ if (shead == NULL)
+ yasm_internal_error("shead is null");
+
+ if (!yasm_section_relocs_first(sect))
+ return 0; /* no relocations, no .rel.* section header */
+
+ shead->rel_index = sindex;
+
+ if (!elf_march->write_secthead_rel || !elf_march->secthead_size)
+ yasm_internal_error(N_("Unsupported machine for ELF output"));
+ elf_march->write_secthead_rel(bufp, shead, symtab_idx, sindex);
+ if (fwrite(buf, elf_march->secthead_size, 1, f))
+ return elf_march->secthead_size;
+ yasm_internal_error(N_("Failed to write an elf section header"));
+ return 0;
+}
+
+unsigned long
+elf_secthead_write_relocs_to_file(FILE *f, yasm_section *sect,
+ elf_secthead *shead, yasm_errwarns *errwarns)
+{
+ elf_reloc_entry *reloc;
+ unsigned char buf[RELOC_MAXSIZE], *bufp;
+ unsigned long size = 0;
+ long pos;
+
+ if (shead == NULL)
+ yasm_internal_error("shead is null");
+
+ reloc = (elf_reloc_entry *)yasm_section_relocs_first(sect);
+ if (!reloc)
+ return 0;
+
+ /* first align section to multiple of 4 */
+ pos = ftell(f);
+ if (pos == -1) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("couldn't read position on output stream"));
+ yasm_errwarn_propagate(errwarns, 0);
+ }
+ pos = (pos + 3) & ~3;
+ if (fseek(f, pos, SEEK_SET) < 0) {
+ yasm_error_set(YASM_ERROR_IO, N_("couldn't seek on output stream"));
+ yasm_errwarn_propagate(errwarns, 0);
+ }
+ shead->rel_offset = (unsigned long)pos;
+
+
+ while (reloc) {
+ unsigned int r_type=0, r_sym;
+ elf_symtab_entry *esym;
+
+ esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
+ if (esym)
+ r_sym = esym->symindex;
+ else
+ r_sym = STN_UNDEF;
+
+ if (!elf_march->map_reloc_info_to_type)
+ yasm_internal_error(N_("Unsupported arch/machine for elf output"));
+ r_type = elf_march->map_reloc_info_to_type(reloc);
+
+ bufp = buf;
+ if (!elf_march->write_reloc || !elf_march->reloc_entry_size)
+ yasm_internal_error(N_("Unsupported arch/machine for elf output"));
+ elf_march->write_reloc(bufp, reloc, r_type, r_sym);
+ fwrite(buf, elf_march->reloc_entry_size, 1, f);
+ size += elf_march->reloc_entry_size;
+
+ reloc = (elf_reloc_entry *)
+ yasm_section_reloc_next((yasm_reloc *)reloc);
+ }
+ return size;
+}
+
+elf_section_type
+elf_secthead_get_type(elf_secthead *shead)
+{
+ return shead->type;
+}
+
+void
+elf_secthead_set_typeflags(elf_secthead *shead, elf_section_type type,
+ elf_section_flags flags)
+{
+ shead->type = type;
+ shead->flags = flags;
+}
+
+int
+elf_secthead_is_empty(elf_secthead *shead)
+{
+ return yasm_intnum_is_zero(shead->size);
+}
+
+yasm_symrec *
+elf_secthead_get_sym(elf_secthead *shead)
+{
+ return shead->sym;
+}
+
+elf_section_index
+elf_secthead_get_index(elf_secthead *shead)
+{
+ return shead->index;
+}
+
+unsigned long
+elf_secthead_get_align(const elf_secthead *shead)
+{
+ return shead->align;
+}
+
+unsigned long
+elf_secthead_set_align(elf_secthead *shead, unsigned long align)
+{
+ return shead->align = align;
+}
+
+elf_section_info
+elf_secthead_set_info(elf_secthead *shead, elf_section_info info)
+{
+ return shead->info = info;
+}
+
+elf_section_index
+elf_secthead_set_index(elf_secthead *shead, elf_section_index sectidx)
+{
+ return shead->index = sectidx;
+}
+
+elf_section_index
+elf_secthead_set_link(elf_secthead *shead, elf_section_index link)
+{
+ return shead->link = link;
+}
+
+elf_section_index
+elf_secthead_set_rel_index(elf_secthead *shead, elf_section_index sectidx)
+{
+ return shead->rel_index = sectidx;
+}
+
+elf_strtab_entry *
+elf_secthead_set_rel_name(elf_secthead *shead, elf_strtab_entry *entry)
+{
+ return shead->rel_name = entry;
+}
+
+elf_size
+elf_secthead_set_entsize(elf_secthead *shead, elf_size size)
+{
+ return shead->entsize = size;
+}
+
+yasm_symrec *
+elf_secthead_set_sym(elf_secthead *shead, yasm_symrec *sym)
+{
+ return shead->sym = sym;
+}
+
+void
+elf_secthead_add_size(elf_secthead *shead, yasm_intnum *size)
+{
+ if (size) {
+ yasm_intnum_calc(shead->size, YASM_EXPR_ADD, size);
+ }
+}
+
+long
+elf_secthead_set_file_offset(elf_secthead *shead, long pos)
+{
+ unsigned long align = shead->align;
+
+ if (align == 0 || align == 1) {
+ shead->offset = (unsigned long)pos;
+ return pos;
+ }
+ else if (align & (align - 1))
+ yasm_internal_error(
+ N_("alignment %d for section `%s' is not a power of 2"));
+ /*, align, sect->name->str);*/
+
+ shead->offset = (unsigned long)((pos + align - 1) & ~(align - 1));
+ return (long)shead->offset;
+}
+
+unsigned long
+elf_proghead_get_size(void)
+{
+ if (!elf_march->proghead_size)
+ yasm_internal_error(N_("Unsupported ELF format for output"));
+ return elf_march->proghead_size;
+}
+
+unsigned long
+elf_proghead_write_to_file(FILE *f,
+ elf_offset secthead_addr,
+ unsigned long secthead_count,
+ elf_section_index shstrtab_index)
+{
+ unsigned char buf[EHDR_MAXSIZE], *bufp = buf;
+
+ YASM_WRITE_8(bufp, ELFMAG0); /* ELF magic number */
+ YASM_WRITE_8(bufp, ELFMAG1);
+ YASM_WRITE_8(bufp, ELFMAG2);
+ YASM_WRITE_8(bufp, ELFMAG3);
+
+ if (!elf_march->write_proghead || !elf_march->proghead_size)
+ yasm_internal_error(N_("Unsupported ELF format for output"));
+ elf_march->write_proghead(&bufp, secthead_addr, secthead_count, shstrtab_index);
+
+ if (((unsigned)(bufp - buf)) != elf_march->proghead_size)
+ yasm_internal_error(N_("ELF program header is not proper length"));
+
+ if (fwrite(buf, elf_march->proghead_size, 1, f))
+ return elf_march->proghead_size;
+
+ yasm_internal_error(N_("Failed to write ELF program header"));
+ return 0;
+}
diff --git a/contrib/tools/yasm/modules/objfmts/elf/elf.h b/contrib/tools/yasm/modules/objfmts/elf/elf.h
new file mode 100644
index 0000000000..fce629ae45
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/elf/elf.h
@@ -0,0 +1,532 @@
+/*
+ * ELF object format helpers
+ *
+ * Copyright (C) 2003-2007 Michael Urman
+ *
+ * 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.
+ */
+
+#ifndef ELF_H_INCLUDED
+#define ELF_H_INCLUDED
+
+typedef struct elf_reloc_entry elf_reloc_entry;
+typedef struct elf_reloc_head elf_reloc_head;
+typedef struct elf_secthead elf_secthead;
+typedef struct elf_strtab_entry elf_strtab_entry;
+typedef struct elf_strtab_head elf_strtab_head;
+typedef struct elf_symtab_entry elf_symtab_entry;
+typedef struct elf_symtab_head elf_symtab_head;
+
+typedef struct elf_machine_handler elf_machine_handler;
+
+typedef unsigned long elf_address;
+typedef unsigned long elf_offset;
+typedef unsigned long elf_size;
+typedef unsigned long elf_section_info;
+
+typedef enum {
+ ET_NONE = 0,
+ ET_REL = 1, /* Relocatable */
+ ET_EXEC = 2, /* Executable */
+ ET_DYN = 3, /* Shared object */
+ ET_CORE = 4, /* Core */
+ ET_LOOS = 0xfe00, /* Environment specific */
+ ET_HIOS = 0xfeff,
+ ET_LOPROC = 0xff00, /* Processor specific */
+ ET_HIPROC = 0xffff
+} elf_file_type;
+
+typedef enum {
+ EM_NONE = 0,
+ EM_M32 = 1, /* AT&T WE 32100 */
+ EM_SPARC = 2, /* SPARC */
+ EM_386 = 3, /* Intel 80386 */
+ EM_68K = 4, /* Motorola 68000 */
+ EM_88K = 5, /* Motorola 88000 */
+ EM_860 = 7, /* Intel 80860 */
+ EM_MIPS = 8, /* MIPS RS3000 */
+
+ EM_S370 = 9, /* IBM System/370 */
+ EM_MIPS_RS4_BE = 10, /* MIPS R4000 Big-Endian (dep)*/
+ EM_PARISC = 15, /* HPPA */
+ EM_SPARC32PLUS = 18, /* SPARC v8plus */
+ EM_PPC = 20, /* PowerPC 32-bit */
+ EM_PPC64 = 21, /* PowerPC 64-bit */
+ EM_ARM = 40, /* ARM */
+ EM_SPARCV9 = 43, /* SPARC v9 64-bit */
+ EM_IA_64 = 50, /* Intel IA-64 */
+ EM_X86_64 = 62, /* AMD x86-64 */
+ EM_ALPHA = 0x9026 /* Alpha (no ABI) */
+} elf_machine;
+
+typedef enum {
+ ELFMAG0 = 0x7f,
+ ELFMAG1 = 0x45,
+ ELFMAG2 = 0x4c,
+ ELFMAG3 = 0x46
+} elf_magic;
+
+typedef enum {
+ EV_NONE = 0, /* invalid */
+ EV_CURRENT = 1 /* current */
+} elf_version;
+
+typedef enum {
+ EI_MAG0 = 0, /* File id */
+ EI_MAG1 = 1,
+ EI_MAG2 = 2,
+ EI_MAG3 = 3,
+ EI_CLASS = 4, /* File class */
+ EI_DATA = 5, /* Data encoding */
+ EI_VERSION = 6, /* File version */
+ EI_OSABI = 7, /* OS and ABI */
+ EI_ABIVERSION = 8, /* version of ABI */
+
+ EI_PAD = 9, /* Pad to end; start here */
+ EI_NIDENT = 16 /* Sizeof e_ident[] */
+} elf_identification_index;
+
+typedef enum {
+ ELFOSABI_SYSV = 0, /* System V ABI */
+ ELFOSABI_HPUX = 1, /* HP-UX os */
+ ELFOSABI_STANDALONE = 255 /* Standalone / embedded app */
+} elf_osabi_index;
+
+typedef enum {
+ ELFCLASSNONE = 0, /* invalid */
+ ELFCLASS32 = 1, /* 32-bit */
+ ELFCLASS64 = 2 /* 64-bit */
+} elf_class;
+
+typedef enum {
+ ELFDATANONE = 0,
+ ELFDATA2LSB = 1,
+ ELFDATA2MSB = 2
+} elf_data_encoding;
+
+/* elf section types - index of semantics */
+typedef enum {
+ SHT_NULL = 0, /* inactive section - no associated data */
+ SHT_PROGBITS = 1, /* defined by program for its own meaning */
+ SHT_SYMTAB = 2, /* symbol table (primarily) for linking */
+ SHT_STRTAB = 3, /* string table - symbols need names */
+ SHT_RELA = 4, /* relocation entries w/ explicit addends */
+ SHT_HASH = 5, /* symbol hash table - for dynamic linking */
+ SHT_DYNAMIC = 6, /* information for dynamic linking */
+ SHT_NOTE = 7, /* extra data marking the file somehow */
+ SHT_NOBITS = 8, /* no stored data, but occupies runtime space */
+ SHT_REL = 9, /* relocations entries w/o explicit addends */
+ SHT_SHLIB = 10, /* reserved; unspecified semantics */
+ SHT_DYNSYM = 11, /* like symtab, but more for dynamic linking */
+
+ SHT_LOOS = 0x60000000, /* reserved for environment specific use */
+ SHT_HIOS = 0x6fffffff,
+ SHT_LOPROC = 0x70000000, /* reserved for processor specific semantics */
+ SHT_HIPROC = 0x7fffffff/*,
+ SHT_LOUSER = 0x80000000,*/ /* reserved for applications; safe */
+ /*SHT_HIUSER = 0xffffffff*/
+} elf_section_type;
+
+/* elf section flags - bitfield of attributes */
+typedef enum {
+ SHF_WRITE = 0x1, /* data should be writable at runtime */
+ SHF_ALLOC = 0x2, /* occupies memory at runtime */
+ SHF_EXECINSTR = 0x4, /* contains machine instructions */
+ SHF_MERGE = 0x10, /* data can be merged */
+ SHF_STRINGS = 0x20, /* contains 0-terminated strings */
+ SHF_GROUP = 0x200, /* member of a section group */
+ SHF_TLS = 0x400, /* thread local storage */
+ SHF_MASKOS = 0x0f000000/*,*//* environment specific use */
+ /*SHF_MASKPROC = 0xf0000000*/ /* bits reserved for processor specific needs */
+} elf_section_flags;
+
+/* elf section index - just the special ones */
+typedef enum {
+ SHN_UNDEF = 0, /* undefined symbol; requires other global */
+ SHN_LORESERVE = 0xff00, /* reserved for various semantics */
+ SHN_LOPROC = 0xff00, /* reserved for processor specific semantics */
+ SHN_HIPROC = 0xff1f,
+ SHN_LOOS = 0xff20, /* reserved for environment specific use */
+ SHN_HIOS = 0xff3f,
+ SHN_ABS = 0xfff1, /* associated symbols don't change on reloc */
+ SHN_COMMON = 0xfff2, /* associated symbols refer to unallocated */
+ SHN_HIRESERVE = 0xffff
+} elf_section_index;
+
+/* elf symbol binding - index of visibility/behavior */
+typedef enum {
+ STB_LOCAL = 0, /* invisible outside defining file */
+ STB_GLOBAL = 1, /* visible to all combined object files */
+ STB_WEAK = 2, /* global but lower precedence */
+
+ STB_LOOS = 10, /* Environment specific use */
+ STB_HIOS = 12,
+ STB_LOPROC = 13, /* reserved for processor specific semantics */
+ STB_HIPROC = 15
+} elf_symbol_binding;
+
+/* elf symbol type - index of classifications */
+typedef enum {
+ STT_NOTYPE = 0, /* type not specified */
+ STT_OBJECT = 1, /* data object such as a variable, array, etc */
+ STT_FUNC = 2, /* a function or executable code */
+ STT_SECTION = 3, /* a section: often for relocation, STB_LOCAL */
+ STT_FILE = 4, /* often source filename: STB_LOCAL, SHN_ABS */
+ STT_COMMON = 5, /* Uninitialized common block. */
+ STT_TLS = 6, /* TLS object. */
+ STT_NUM = 7,
+
+ STT_LOOS = 10, /* Environment specific use */
+ STT_HIOS = 12,
+ STT_LOPROC = 13, /* reserved for processor specific semantics */
+ STT_HIPROC = 15
+} elf_symbol_type;
+
+typedef enum {
+ STN_UNDEF = 0
+} elf_symbol_index;
+
+/* elf symbol visibility - lower two bits of OTHER field */
+typedef enum {
+ STV_DEFAULT = 0, /* Default symbol visibility rules */
+ STV_INTERNAL = 1, /* Processor specific hidden class */
+ STV_HIDDEN = 2, /* Sym unavailable in other modules */
+ STV_PROTECTED = 3 /* Not preemptable, not exported */
+} elf_symbol_vis;
+
+
+/* internal only object definitions */
+#ifdef YASM_OBJFMT_ELF_INTERNAL
+
+#define ELF_VISIBILITY_MASK 0x03
+#define ELF_ST_VISIBILITY(v) ((v) & ELF_VISIBILITY_MASK)
+
+#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t))
+#define ELF32_ST_OTHER(vis) ELF_ST_VISIBILITY(vis)
+
+#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+#define ELF64_R_INFO(s,t) (((s)<<32) + ((t) & 0xffffffffL))
+#define ELF64_ST_OTHER(vis) ELF_ST_VISIBILITY(vis)
+
+#define EHDR32_SIZE 52
+#define EHDR64_SIZE 64
+#define EHDR_MAXSIZE 64
+
+#define SHDR32_SIZE 40
+#define SHDR64_SIZE 64
+#define SHDR_MAXSIZE 64
+
+#define SYMTAB32_SIZE 16
+#define SYMTAB64_SIZE 24
+#define SYMTAB_MAXSIZE 24
+
+#define SYMTAB32_ALIGN 4
+#define SYMTAB64_ALIGN 8
+
+#define RELOC32_SIZE 8
+#define RELOC32A_SIZE 12
+#define RELOC64_SIZE 16
+#define RELOC64A_SIZE 24
+#define RELOC_MAXSIZE 24
+
+#define RELOC32_ALIGN 4
+#define RELOC64_ALIGN 8
+
+
+/* elf relocation type - index of semantics
+ *
+ * A = Addend (r_addend for RELA, value at location for REL)
+ * B = Base address
+ * G = Offset into global offset table (GOT)
+ * GOT = Address of the global offset table (GOT)
+ * L = Location of procedure linkage table (PLT)
+ * P = Location of location being relocated (r_offset)
+ * S = Value of symbol
+ */
+typedef enum {
+ R_386_NONE = 0, /* none */
+ R_386_32 = 1, /* word32, S + A */
+ R_386_PC32 = 2, /* word32, S + A - P */
+ R_386_GOT32 = 3, /* word32, G + A - P */
+ R_386_PLT32 = 4, /* word32, L + A - P */
+ R_386_COPY = 5, /* none */
+ R_386_GLOB_DAT = 6, /* word32, S */
+ R_386_JMP_SLOT = 7, /* word32, S */
+ R_386_RELATIVE = 8, /* word32, B + A */
+ R_386_GOTOFF = 9, /* word32, S + A - GOT */
+ R_386_GOTPC = 10, /* word32, GOT + A - P */
+ R_386_TLS_TPOFF = 14, /* Negative offset in static TLS block (GNU
+ version) */
+ R_386_TLS_IE = 15, /* Absolute address of GOT entry for negative
+ static TLS block offset */
+ R_386_TLS_GOTIE = 16, /* GOT entry for negative static TLS block
+ offset */
+ R_386_TLS_LE = 17, /* Negative offset relative to static TLS
+ (GNU version) */
+ R_386_TLS_GD = 18, /* Direct 32 bit for GNU version of GD TLS */
+ R_386_TLS_LDM = 19, /* Direct 32 bit for GNU version of LD TLS
+ in LE code */
+ R_386_16 = 20, /* word16, S + A (GNU extension) */
+ R_386_PC16 = 21, /* word16, S + A - P (GNU extension) */
+ R_386_8 = 22, /* word8, S + A (GNU extension) */
+ R_386_PC8 = 23, /* word8, S + A - P (GNU extension) */
+ R_386_TLS_GD_32 = 24, /* Direct 32 bit for GD TLS */
+ R_386_TLS_GD_PUSH = 25, /* Tag for pushl in GD TLS code */
+ R_386_TLS_GD_CALL = 26, /* Relocation for call to */
+ R_386_TLS_GD_POP = 27, /* Tag for popl in GD TLS code */
+ R_386_TLS_LDM_32 = 28, /* Direct 32 bit for local dynamic code */
+ R_386_TLS_LDM_PUSH = 29, /* Tag for pushl in LDM TLS code */
+ R_386_TLS_LDM_CALL = 30, /* Relocation for call to */
+ R_386_TLS_LDM_POP = 31, /* Tag for popl in LDM TLS code */
+ R_386_TLS_LDO_32 = 32, /* Offset relative to TLS block */
+ R_386_TLS_IE_32 = 33, /* GOT entry for static TLS block */
+ R_386_TLS_LE_32 = 34, /* Offset relative to static TLS block */
+ R_386_TLS_DTPMOD32 = 35, /* ID of module containing symbol */
+ R_386_TLS_DTPOFF32 = 36, /* Offset in TLS block */
+ R_386_TLS_TPOFF32 = 37, /* Offset in static TLS block */
+ R_386_TLS_GOTDESC = 39,
+ R_386_TLS_DESC_CALL = 40,
+ R_386_TLS_DESC = 41
+} elf_386_relocation_type;
+
+typedef enum {
+ R_X86_64_NONE = 0, /* none */
+ R_X86_64_64 = 1, /* word64, S + A */
+ R_X86_64_PC32 = 2, /* word32, S + A - P */
+ R_X86_64_GOT32 = 3, /* word32, G + A */
+ R_X86_64_PLT32 = 4, /* word32, L + A - P */
+ R_X86_64_COPY = 5, /* none */
+ R_X86_64_GLOB_DAT = 6, /* word64, S, set GOT entry to data address */
+ R_X86_64_JMP_SLOT = 7, /* word64, S, set GOT entry to code address */
+ R_X86_64_RELATIVE = 8, /* word64, B + A */
+ R_X86_64_GOTPCREL = 9, /* word32, G + GOT + A - P */
+ R_X86_64_32 = 10, /* word32 (zero extend), S + A */
+ R_X86_64_32S = 11, /* word32 (sign extend), S + A */
+ R_X86_64_16 = 12, /* word16, S + A */
+ R_X86_64_PC16 = 13, /* word16, S + A - P */
+ R_X86_64_8 = 14, /* word8, S + A */
+ R_X86_64_PC8 = 15, /* word8, S + A - P */
+ R_X86_64_DPTMOD64 = 16, /* word64, ID of module containing symbol */
+ R_X86_64_DTPOFF64 = 17, /* word64, offset in TLS block */
+ R_X86_64_TPOFF64 = 18, /* word64, offset in initial TLS block */
+ R_X86_64_TLSGD = 19, /* word32, PC-rel offset to GD GOT block */
+ R_X86_64_TLSLD = 20, /* word32, PC-rel offset to LD GOT block */
+ R_X86_64_DTPOFF32 = 21, /* word32, offset to TLS block */
+ R_X86_64_GOTTPOFF = 22, /* word32, PC-rel offset to IE GOT entry */
+ R_X86_64_TPOFF32 = 23, /* word32, offset in initial TLS block */
+ R_X86_64_PC64 = 24, /* word64, PC relative */
+ R_X86_64_GOTOFF64 = 25, /* word64, offset to GOT */
+ R_X86_64_GOTPC32 = 26, /* word32, signed pc relative to GOT */
+ R_X86_64_GOT64 = 27, /* word64, GOT entry offset */
+ R_X86_64_GOTPCREL64 = 28, /* word64, signed pc relative to GOT entry */
+ R_X86_64_GOTPC64 = 29, /* word64, signed pc relative to GOT */
+ R_X86_64_GOTPLT64 = 30, /* like GOT64, but indicates PLT entry needed */
+ R_X86_64_PLTOFF64 = 31, /* word64, GOT relative offset to PLT entry */
+ R_X86_64_GOTPC32_TLSDESC = 34, /* GOT offset for TLS descriptor */
+ R_X86_64_TLSDESC_CALL = 35, /* Marker for call through TLS descriptor */
+ R_X86_64_TLSDESC = 36 /* TLS descriptor */
+} elf_x86_64_relocation_type;
+
+struct elf_secthead {
+ elf_section_type type;
+ elf_section_flags flags;
+ elf_address offset;
+ yasm_intnum *size;
+ elf_section_index link;
+ elf_section_info info; /* see note ESD1 */
+ unsigned long align;
+ elf_size entsize;
+
+ yasm_symrec *sym;
+ elf_strtab_entry *name;
+ elf_section_index index;
+
+ elf_strtab_entry *rel_name;
+ elf_section_index rel_index;
+ elf_address rel_offset;
+ unsigned long nreloc;
+};
+
+/* Note ESD1:
+ * for section types SHT_REL, SHT_RELA:
+ * link -> index of associated symbol table
+ * info -> index of relocated section
+ * for section types SHT_SYMTAB, SHT_DYNSYM:
+ * link -> index of associated string table
+ * info -> 1+index of last "local symbol" (bind == STB_LOCAL)
+ * (for section type SHT_DNAMIC:
+ * link -> index of string table
+ * info -> 0 )
+ * (for section type SHT_HASH:
+ * link -> index of symbol table to which hash applies
+ * info -> 0 )
+ * for all others:
+ * link -> SHN_UNDEF
+ * info -> 0
+ */
+
+struct elf_reloc_entry {
+ yasm_reloc reloc;
+ int rtype_rel;
+ size_t valsize;
+ yasm_intnum *addend;
+ /*@null@*/ yasm_symrec *wrt;
+ int is_GOT_sym;
+};
+
+STAILQ_HEAD(elf_strtab_head, elf_strtab_entry);
+struct elf_strtab_entry {
+ STAILQ_ENTRY(elf_strtab_entry) qlink;
+ unsigned long index;
+ char *str;
+};
+
+STAILQ_HEAD(elf_symtab_head, elf_symtab_entry);
+struct elf_symtab_entry {
+ STAILQ_ENTRY(elf_symtab_entry) qlink;
+ int in_table;
+ yasm_symrec *sym;
+ yasm_section *sect;
+ elf_strtab_entry *name;
+ elf_address value;
+ /*@dependent@*/ yasm_expr *xsize;
+ elf_size size;
+ elf_section_index index;
+ elf_symbol_binding bind;
+ elf_symbol_type type;
+ elf_symbol_vis vis;
+ elf_symbol_index symindex;
+};
+
+#endif /* defined(YASM_OBJFMT_ELF_INTERNAL) */
+
+extern const yasm_assoc_data_callback elf_section_data;
+extern const yasm_assoc_data_callback elf_symrec_data;
+extern const yasm_assoc_data_callback elf_ssym_symrec_data;
+
+
+const elf_machine_handler *elf_set_arch(struct yasm_arch *arch,
+ yasm_symtab *symtab,
+ int bits_pref);
+
+yasm_symrec *elf_get_special_sym(const char *name, const char *parser);
+
+/* reloc functions */
+int elf_is_wrt_sym_relative(yasm_symrec *wrt);
+int elf_is_wrt_pos_adjusted(yasm_symrec *wrt);
+elf_reloc_entry *elf_reloc_entry_create(yasm_symrec *sym,
+ /*@null@*/ yasm_symrec *wrt,
+ yasm_intnum *addr,
+ int rel,
+ size_t valsize,
+ int is_GOT_sym);
+void elf_reloc_entry_destroy(void *entry);
+
+/* strtab functions */
+elf_strtab_entry *elf_strtab_entry_create(const char *str);
+void elf_strtab_entry_set_str(elf_strtab_entry *entry, const char *str);
+elf_strtab_head *elf_strtab_create(void);
+elf_strtab_entry *elf_strtab_append_str(elf_strtab_head *head, const char *str);
+void elf_strtab_destroy(elf_strtab_head *head);
+unsigned long elf_strtab_output_to_file(FILE *f, elf_strtab_head *head);
+
+/* symtab functions */
+elf_symtab_entry *elf_symtab_entry_create(elf_strtab_entry *name,
+ struct yasm_symrec *sym);
+elf_symtab_head *elf_symtab_create(void);
+void elf_symtab_append_entry(elf_symtab_head *symtab, elf_symtab_entry *entry);
+void elf_symtab_insert_local_sym(elf_symtab_head *symtab,
+ elf_symtab_entry *entry);
+void elf_symtab_destroy(elf_symtab_head *head);
+unsigned long elf_symtab_assign_indices(elf_symtab_head *symtab);
+unsigned long elf_symtab_write_to_file(FILE *f, elf_symtab_head *symtab,
+ yasm_errwarns *errwarns);
+void elf_symtab_set_nonzero(elf_symtab_entry *entry,
+ struct yasm_section *sect,
+ elf_section_index sectidx,
+ elf_symbol_binding bind,
+ elf_symbol_type type,
+ struct yasm_expr *size,
+ elf_address *value);
+void elf_sym_set_visibility(elf_symtab_entry *entry,
+ elf_symbol_vis vis);
+void elf_sym_set_type(elf_symtab_entry *entry, elf_symbol_type type);
+void elf_sym_set_size(elf_symtab_entry *entry, struct yasm_expr *size);
+int elf_sym_in_table(elf_symtab_entry *entry);
+
+/* section header functions */
+elf_secthead *elf_secthead_create(elf_strtab_entry *name,
+ elf_section_type type,
+ elf_section_flags flags,
+ elf_address offset,
+ elf_size size);
+void elf_secthead_destroy(elf_secthead *esd);
+unsigned long elf_secthead_write_to_file(FILE *f, elf_secthead *esd,
+ elf_section_index sindex);
+void elf_secthead_append_reloc(yasm_section *sect, elf_secthead *shead,
+ elf_reloc_entry *reloc);
+elf_section_type elf_secthead_get_type(elf_secthead *shead);
+void elf_secthead_set_typeflags(elf_secthead *shead, elf_section_type type,
+ elf_section_flags flags);
+int elf_secthead_is_empty(elf_secthead *shead);
+struct yasm_symrec *elf_secthead_get_sym(elf_secthead *shead);
+unsigned long elf_secthead_get_align(const elf_secthead *shead);
+unsigned long elf_secthead_set_align(elf_secthead *shead, unsigned long align);
+elf_section_index elf_secthead_get_index(elf_secthead *shead);
+elf_section_info elf_secthead_set_info(elf_secthead *shead,
+ elf_section_info info);
+elf_section_index elf_secthead_set_index(elf_secthead *shead,
+ elf_section_index sectidx);
+elf_section_index elf_secthead_set_link(elf_secthead *shead,
+ elf_section_index link);
+elf_section_index elf_secthead_set_rel_index(elf_secthead *shead,
+ elf_section_index sectidx);
+elf_strtab_entry *elf_secthead_set_rel_name(elf_secthead *shead,
+ elf_strtab_entry *entry);
+elf_size elf_secthead_set_entsize(elf_secthead *shead, elf_size size);
+struct yasm_symrec *elf_secthead_set_sym(elf_secthead *shead,
+ struct yasm_symrec *sym);
+void elf_secthead_add_size(elf_secthead *shead, yasm_intnum *size);
+char *elf_secthead_name_reloc_section(const char *basesect);
+void elf_handle_reloc_addend(yasm_intnum *intn,
+ elf_reloc_entry *reloc,
+ unsigned long offset);
+unsigned long elf_secthead_write_rel_to_file(FILE *f, elf_section_index symtab,
+ yasm_section *sect,
+ elf_secthead *esd,
+ elf_section_index sindex);
+unsigned long elf_secthead_write_relocs_to_file(FILE *f, yasm_section *sect,
+ elf_secthead *shead,
+ yasm_errwarns *errwarns);
+long elf_secthead_set_file_offset(elf_secthead *shead, long pos);
+
+/* program header function */
+unsigned long
+elf_proghead_get_size(void);
+unsigned long
+elf_proghead_write_to_file(FILE *f,
+ elf_offset secthead_addr,
+ unsigned long secthead_count,
+ elf_section_index shstrtab_index);
+
+#endif /* ELF_H_INCLUDED */
diff --git a/contrib/tools/yasm/modules/objfmts/macho/macho-objfmt.c b/contrib/tools/yasm/modules/objfmts/macho/macho-objfmt.c
new file mode 100644
index 0000000000..0a48d9b905
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/macho/macho-objfmt.c
@@ -0,0 +1,1620 @@
+/*
+ * Mac OS X ABI Mach-O File Format
+ *
+ * Copyright (C) 2007 Henryk Richter, built upon xdf objfmt (C) 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.
+ */
+/*
+ notes: This implementation is rather basic. There are several implementation
+ issues to be sorted out for full compliance and error resilience.
+ Some examples are given below (nasm syntax).
+
+ 1) section placement
+ Mach-O requires BSS sections to be placed last in object files. This
+ has to be done manually.
+ Example:
+
+ section .text
+ mov rax,[qword foo]
+ section .data
+ dw 0
+ section .bss
+ foo dw 0
+
+ 2) addressing issues
+
+ 2.1) symbol relative relocation (i.e. mov eax,[foo wrt bar])
+ Not implemented yet.
+
+ 2.2) data referencing in 64 bit mode
+ While ELF allows 32 bit absolute relocations in 64 bit mode, Mach-O
+ does not. Therefore code like
+ lea rbx,[_foo] ;48 8d 1c 25 00 00 00 00
+ mov rcx,[_bar] ;48 8b 0c 25 00 00 00 00
+ with a 32 bit address field cannot be relocated into an address >= 0x100000000 (OSX actually
+ uses that).
+
+ Actually, the only register where a 64 bit displacement is allowed in x86-64, is rax
+ as in the example 1).
+
+ A plausible workaround is either classic PIC (like in C), which is in turn
+ not implemented in this object format. The recommended was is PC relative
+ code (called RIP-relative in x86-64). So instead of the lines above, just write:
+ lea rbx,[_foo wrt rip]
+ mov rcx,[_bar wrt rip]
+
+ 2.3) section/data alignment
+ Normally, you specify sections with a specific alignment
+ and get your data layed out as desired. Unfortunately, the
+ linker in MacOS X seems to ignore the section alignment requests.
+ The workaround is an explicit alignment at the end of the text section.
+
+ section .text
+ movdqa xmm0,[_foo wrt rip]
+
+ align 16
+ section .data align=16
+ _foo dw 32,32,32,32,32,32,32,32
+
+ FIXME: perform that operation implicitly!
+
+ 2.4) cross section symbol differences unsupported in current implementation
+ [extern foo]
+ [extern bar]
+ section .data
+ dq bar-foo
+
+ Will currently produce an error though the necessary means are provided
+ by the Mach-O specification.
+
+*/
+
+#include <util.h>
+
+#include <libyasm.h>
+
+/* MACH-O DEFINES */
+/* Mach-O in-file header structure sizes (32 BIT, see below for 64 bit defs) */
+#define MACHO_HEADER_SIZE 28
+#define MACHO_SEGCMD_SIZE 56
+#define MACHO_SECTCMD_SIZE 68
+#define MACHO_SYMCMD_SIZE 24
+#define MACHO_NLIST_SIZE 12
+#define MACHO_RELINFO_SIZE 8
+
+/* 64 bit sizes */
+#define MACHO_HEADER64_SIZE 32
+#define MACHO_SEGCMD64_SIZE 72
+#define MACHO_SECTCMD64_SIZE 80
+#define MACHO_NLIST64_SIZE 16
+#define MACHO_RELINFO64_SIZE 8
+
+
+/* Mach-O file header values */
+#define MH_MAGIC 0xfeedface
+#define MH_MAGIC_64 0xfeedfacf
+
+/* CPU machine type */
+#define CPU_TYPE_I386 7 /* x86 platform */
+#define CPU_TYPE_X86_64 (CPU_TYPE_I386|CPU_ARCH_ABI64)
+#define CPU_ARCH_ABI64 0x01000000 /* 64 bit ABI */
+
+/* CPU machine subtype, e.g. processor */
+#define CPU_SUBTYPE_I386_ALL 3 /* all-x86 compatible */
+#define CPU_SUBTYPE_X86_64_ALL CPU_SUBTYPE_I386_ALL
+#define CPU_SUBTYPE_386 3
+#define CPU_SUBTYPE_486 4
+#define CPU_SUBTYPE_486SX (4 + 128)
+#define CPU_SUBTYPE_586 5
+#define CPU_SUBTYPE_INTEL(f, m) ((f) + ((m) << 4))
+#define CPU_SUBTYPE_PENT CPU_SUBTYPE_INTEL(5, 0)
+#define CPU_SUBTYPE_PENTPRO CPU_SUBTYPE_INTEL(6, 1)
+#define CPU_SUBTYPE_PENTII_M3 CPU_SUBTYPE_INTEL(6, 3)
+#define CPU_SUBTYPE_PENTII_M5 CPU_SUBTYPE_INTEL(6, 5)
+#define CPU_SUBTYPE_PENTIUM_4 CPU_SUBTYPE_INTEL(10, 0)
+
+#define CPU_SUBTYPE_INTEL_FAMILY(x) ((x) & 15)
+#define CPU_SUBTYPE_INTEL_FAMILY_MAX 15
+
+#define CPU_SUBTYPE_INTEL_MODEL(x) ((x) >> 4)
+#define CPU_SUBTYPE_INTEL_MODEL_ALL 0
+
+#define MH_OBJECT 0x1 /* object file */
+
+#define LC_SEGMENT 0x1 /* segment load command */
+#define LC_SYMTAB 0x2 /* symbol table load command */
+#define LC_SEGMENT_64 0x19 /* segment load command */
+
+
+#define VM_PROT_NONE 0x00
+#define VM_PROT_READ 0x01
+#define VM_PROT_WRITE 0x02
+#define VM_PROT_EXECUTE 0x04
+
+#define VM_PROT_DEFAULT (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
+#define VM_PROT_ALL (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
+
+#define SECTION_TYPE 0x000000ff /* section type mask */
+#define SECTION_ATTRIBUTES 0xffffff00UL/* section attributes mask */
+
+#define S_REGULAR 0x0 /* standard section */
+#define S_ZEROFILL 0x1 /* zerofill, in-memory only */
+#define S_CSTRING_LITERALS 0x2 /* literal C strings */
+#define S_4BYTE_LITERALS 0x3 /* only 4-byte literals */
+#define S_8BYTE_LITERALS 0x4 /* only 8-byte literals */
+#define S_LITERAL_POINTERS 0x5 /* only pointers to literals */
+#define S_NON_LAZY_SYMBOL_POINTERS 0x6 /* only non-lazy symbol pointers */
+#define S_LAZY_SYMBOL_POINTERS 0x7 /* only lazy symbol pointers */
+#define S_SYMBOL_STUBS 0x8 /* only symbol stubs; byte size of
+ * stub in the reserved2 field */
+#define S_MOD_INIT_FUNC_POINTERS 0x9 /* only function pointers for init */
+#define S_MOD_TERM_FUNC_POINTERS 0xa /* only function pointers for term */
+#define S_COALESCED 0xb /* symbols that are to be coalesced */
+#define S_GB_ZEROFILL 0xc /* >4GB zero fill on demand section */
+#define S_INTERPOSING 0xd /* only pairs of function pointers for
+ * interposing */
+#define S_16BYTE_LITERALS 0xe /* only 16 byte literals */
+
+#define S_ATTR_DEBUG 0x02000000 /* a debug section */
+#define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */
+#define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some
+ * machine instructions */
+#define S_ATTR_EXT_RELOC 0x00000200 /* section has external
+ * relocation entries */
+#define S_ATTR_LOC_RELOC 0x00000100 /* section has local
+ * relocation entries */
+
+#define SECTION_ATTRIBUTES_USR 0xff000000UL /* User setable attributes */
+#define S_ATTR_PURE_INSTRUCTIONS 0x80000000UL /* only true machine insns */
+#define S_ATTR_NO_TOC 0x40000000UL /* coalesced symbols that are
+ * not to be in a ranlib table
+ * of contents */
+#define S_ATTR_STRIP_STATIC_SYMS 0x20000000UL /* ok to strip static symbols
+ * in this section in files
+ * with the MH_DYLDLINK flag */
+#define S_ATTR_NO_DEAD_STRIP 0x10000000UL /* no dead stripping */
+#define S_ATTR_LIVE_SUPPORT 0x08000000UL /* blocks are live if they
+ * reference live blocks */
+#define S_ATTR_SELF_MODIFYING_CODE 0x04000000UL /* Used with i386 code stubs
+ * written on by dyld */
+
+/* macho references symbols in different ways whether they are linked at
+ * runtime (LAZY, read library functions) or at link time (NON_LAZY, mostly
+ * data)
+ *
+ * TODO: proper support for dynamically linkable modules would require the
+ * __import sections as well as the dsymtab command
+ */
+#define REFERENCE_FLAG_UNDEFINED_NON_LAZY 0x0
+#define REFERENCE_FLAG_UNDEFINED_LAZY 0x1
+
+#define align(x, y) \
+ (((x) + (y) - 1) & ~((y) - 1)) /* align x to multiple of y */
+
+#define align32(x) \
+ align(x, 4) /* align x to 32 bit boundary */
+
+#define macho_MAGIC 0x87654322
+
+/* Symbol table type field bit masks */
+#define N_STAB 0xe0 /* mask indicating stab entry */
+#define N_PEXT 0x10 /* private external bit */
+#define N_TYPE 0x0e /* mask for all the type bits */
+#define N_EXT 0x01 /* external (global) bit */
+
+/* Symbol table type field values */
+#define N_UNDF 0x00 /* undefined */
+#define N_ABS 0x02 /* absolute address */
+#define N_SECT 0x0e /* symbol is defined in a section */
+
+#define NO_SECT 0 /* no section for symbol in nlist */
+
+#define REGULAR_OUTBUF_SIZE 1024
+
+
+typedef struct macho_reloc {
+ yasm_reloc reloc;
+ int pcrel;
+ int length;
+ int ext;
+ enum reloc_type_x86_64 {
+ /* x86 relocations */
+ GENERIC_RELOC_VANILLA = 0, /* generic relocation */
+ GENERIC_RELOC_PAIR = 1, /* Only follows a GENERIC_RELOC_SECTDIFF */
+ GENERIC_RELOC_SECTDIFF = 2,
+ GENERIC_RELOC_PB_LA_PTR = 3, /* prebound lazy pointer */
+ GENERIC_RELOC_LOCAL_SECTDIFF = 4,
+
+ /* x86-64 relocations */
+ X86_64_RELOC_UNSIGNED = 0, /* for absolute addresses */
+ X86_64_RELOC_SIGNED = 1, /* for signed 32-bit displacement */
+ X86_64_RELOC_BRANCH = 2, /* a CALL/JMP insn with 32-bit disp */
+ X86_64_RELOC_GOT_LOAD = 3, /* a MOVQ load of a GOT entry */
+ X86_64_RELOC_GOT = 4, /* other GOT references */
+ X86_64_RELOC_SUBTRACTOR = 5, /* must be followed by a X86_64_RELOC_UNSIGNED */
+ X86_64_RELOC_SIGNED_1 = 6, /* signed 32-bit disp, -1 addend */
+ X86_64_RELOC_SIGNED_2 = 7, /* signed 32-bit disp, -2 addend */
+ X86_64_RELOC_SIGNED_4 = 8 /* signed 32-bit disp, -4 addend */
+ } type;
+} macho_reloc;
+
+typedef struct macho_section_data {
+ /*@dependent@*/ yasm_symrec *sym; /* symbol created for this section */
+ long scnum; /* section number (0=first section) */
+ /*@only@*/ char *segname; /* segment name in file */
+ /*@only@*/ char *sectname; /* section name in file */
+ unsigned long flags; /* S_* flags */
+ unsigned long size; /* size of raw data (section data) in bytes */
+ unsigned long offset; /* offset in raw data within file in bytes */
+ unsigned long vmoff; /* memory offset */
+ unsigned long nreloc; /* number of relocation entries */
+ unsigned int extreloc; /* external relocations present (0/1) */
+} macho_section_data;
+
+
+typedef struct macho_symrec_data {
+ unsigned long index; /* index in output order */
+ yasm_intnum *value; /* valid after writing symtable to file */
+ unsigned long length; /* length + 1 (plus auto underscore) */
+} macho_symrec_data;
+
+
+typedef struct yasm_objfmt_macho {
+ yasm_objfmt_base objfmt; /* base structure */
+
+ long parse_scnum; /* sect numbering in parser */
+ int bits; /* 32 / 64 */
+
+ yasm_symrec *gotpcrel_sym; /* ..gotpcrel */
+} yasm_objfmt_macho;
+
+
+typedef struct macho_objfmt_output_info {
+ yasm_object *object;
+ yasm_objfmt_macho *objfmt_macho;
+ yasm_errwarns *errwarns;
+ /*@dependent@ */ FILE *f;
+ /*@only@ */ unsigned char *buf;
+ yasm_section *sect;
+ /*@dependent@ */ macho_section_data *msd;
+
+ unsigned int is_64; /* write object in 64 bit mode */
+
+ /* vmsize and filesize available after traversing section count routine */
+ unsigned long vmsize; /* raw size of all sections (including BSS) */
+ unsigned long filesize; /* size of sections in file (excluding BSS) */
+ unsigned long offset; /* offset within file */
+
+ /* forward offset tracking */
+ unsigned long rel_base; /* first relocation in file */
+ unsigned long s_reloff; /* in-file offset to relocations */
+
+ unsigned long indx; /* current symbol size in bytes (name length+1) */
+ unsigned long symindex; /* current symbol index in output order */
+ int all_syms; /* outputting all symbols? */
+ unsigned long strlength; /* length of all strings */
+} macho_objfmt_output_info;
+
+
+static void macho_section_data_destroy(/*@only@*/ void *d);
+static void macho_section_data_print(void *data, FILE *f, int indent_level);
+
+static const yasm_assoc_data_callback macho_section_data_cb = {
+ macho_section_data_destroy,
+ macho_section_data_print
+};
+
+static void macho_symrec_data_destroy(/*@only@*/ void *d);
+static void macho_symrec_data_print(void *data, FILE *f, int indent_level);
+
+static const yasm_assoc_data_callback macho_symrec_data_cb = {
+ macho_symrec_data_destroy,
+ macho_symrec_data_print
+};
+
+yasm_objfmt_module yasm_macho_LTX_objfmt;
+yasm_objfmt_module yasm_macho32_LTX_objfmt;
+yasm_objfmt_module yasm_macho64_LTX_objfmt;
+
+static yasm_objfmt *
+macho_objfmt_create_common(yasm_object *object, yasm_objfmt_module *module,
+ int bits_pref)
+{
+ yasm_objfmt_macho *objfmt_macho = yasm_xmalloc(sizeof(yasm_objfmt_macho));
+
+ objfmt_macho->objfmt.module = module;
+
+ /* Only support x86 arch for now */
+ if (yasm__strcasecmp(yasm_arch_keyword(object->arch), "x86") != 0) {
+ yasm_xfree(objfmt_macho);
+ return NULL;
+ }
+
+ /* Support x86 and amd64 machines of x86 arch */
+ if (yasm__strcasecmp(yasm_arch_get_machine(object->arch), "x86") == 0 &&
+ (bits_pref == 0 || bits_pref == 32)) {
+ objfmt_macho->bits = 32;
+ objfmt_macho->gotpcrel_sym = NULL;
+ } else if (yasm__strcasecmp(yasm_arch_get_machine(object->arch),
+ "amd64") == 0 &&
+ (bits_pref == 0 || bits_pref == 64)) {
+ objfmt_macho->bits = 64;
+ /* FIXME: misuse of NULL bytecode */
+ objfmt_macho->gotpcrel_sym =
+ yasm_symtab_define_label(object->symtab, "..gotpcrel", NULL, 0, 0);
+ } else {
+ yasm_xfree(objfmt_macho);
+ return NULL;
+ }
+
+ objfmt_macho->parse_scnum = 0; /* section numbering starts at 0 */
+ return (yasm_objfmt *)objfmt_macho;
+}
+
+static yasm_objfmt *
+macho_objfmt_create(yasm_object *object)
+{
+ yasm_objfmt *objfmt;
+ yasm_objfmt_macho *objfmt_macho;
+
+ objfmt = macho_objfmt_create_common(object, &yasm_macho_LTX_objfmt, 0);
+ if (objfmt) {
+ objfmt_macho = (yasm_objfmt_macho *)objfmt;
+ /* Figure out which bitness of object format to use */
+ if (objfmt_macho->bits == 32)
+ objfmt_macho->objfmt.module = &yasm_macho32_LTX_objfmt;
+ else if (objfmt_macho->bits == 64)
+ objfmt_macho->objfmt.module = &yasm_macho64_LTX_objfmt;
+ }
+ return objfmt;
+}
+
+static yasm_objfmt *
+macho32_objfmt_create(yasm_object *object)
+{
+ return macho_objfmt_create_common(object, &yasm_macho32_LTX_objfmt, 32);
+}
+
+static yasm_objfmt *
+macho64_objfmt_create(yasm_object *object)
+{
+ return macho_objfmt_create_common(object, &yasm_macho64_LTX_objfmt, 64);
+}
+
+static int
+macho_objfmt_output_value(yasm_value *value, unsigned char *buf,
+ unsigned int destsize, unsigned long offset,
+ yasm_bytecode *bc, int warn, /*@null@*/ void *d)
+{
+ /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
+ yasm_objfmt_macho *objfmt_macho;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
+ unsigned long intn_minus = 0, intn_plus = 0;
+ int retval;
+ unsigned int valsize = value->size;
+ macho_reloc *reloc = NULL;
+
+ assert(info != NULL);
+ objfmt_macho = info->objfmt_macho;
+
+ if (value->abs)
+ value->abs = yasm_expr_simplify(value->abs, 1);
+
+ /* Try to output constant and PC-relative section-local first.
+ * Note this does NOT output any value with a SEG, WRT, external,
+ * cross-section, or non-PC-relative reference (those are handled below).
+ */
+ switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
+ info->object->arch)) {
+ case -1:
+ return 1;
+ case 0:
+ break;
+ default:
+ return 0;
+ }
+
+ if (value->section_rel) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("macho: relocation too complex for current implementation"));
+ return 1;
+ }
+
+ if (value->rel) {
+ yasm_sym_vis vis = yasm_symrec_get_visibility(value->rel);
+
+ reloc = yasm_xcalloc(sizeof(macho_reloc), 1);
+ reloc->reloc.addr = yasm_intnum_create_uint(bc->offset + offset);
+ reloc->reloc.sym = value->rel;
+ switch (valsize) {
+ case 64:
+ reloc->length = 3;
+ break;
+ case 32:
+ reloc->length = 2;
+ break;
+ case 16:
+ reloc->length = 1;
+ break;
+ case 8:
+ reloc->length = 0;
+ break;
+ default:
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("macho: relocation size unsupported"));
+ yasm_xfree(reloc);
+ return 1;
+ }
+ reloc->pcrel = 0;
+ reloc->ext = 0;
+ reloc->type = GENERIC_RELOC_VANILLA;
+ /* R_ABS */
+
+ if (value->rshift > 0) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("macho: shifted relocations not supported"));
+ yasm_xfree(reloc);
+ return 1;
+ }
+
+ if (value->seg_of) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("macho: SEG not supported"));
+ yasm_xfree(reloc);
+ return 1;
+ }
+
+ if (value->curpos_rel && objfmt_macho->gotpcrel_sym &&
+ value->wrt == objfmt_macho->gotpcrel_sym) {
+ reloc->type = X86_64_RELOC_GOT;
+ value->wrt = NULL;
+ } else if (value->wrt) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("macho: invalid WRT"));
+ yasm_xfree(reloc);
+ return 1;
+ }
+
+ if (value->curpos_rel) {
+ reloc->pcrel = 1;
+ if (!info->is_64) {
+ /* Adjust to start of section, so subtract out the bytecode
+ * offset.
+ */
+ intn_minus = bc->offset;
+ } else {
+ /* Add in the offset plus value size to end up with 0. */
+ intn_plus = offset+destsize;
+ if (reloc->type == X86_64_RELOC_GOT) {
+ /* XXX: This is a hack */
+ if (offset >= 2 && buf[-2] == 0x8B)
+ reloc->type = X86_64_RELOC_GOT_LOAD;
+ } else if (value->jump_target)
+ reloc->type = X86_64_RELOC_BRANCH;
+ else
+ reloc->type = X86_64_RELOC_SIGNED;
+ }
+ } else if (info->is_64) {
+ if (valsize == 32) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("macho: sorry, cannot apply 32 bit absolute relocations in 64 bit mode, consider \"[_symbol wrt rip]\" for mem access, \"qword\" and \"dq _foo\" for pointers."));
+ return 1;
+ }
+ reloc->type = X86_64_RELOC_UNSIGNED;
+ }
+
+ /* It seems that x86-64 objects need to have all extern relocs? */
+ if (info->is_64)
+ reloc->ext = 1;
+
+ if ((vis & YASM_SYM_EXTERN) || (vis & YASM_SYM_COMMON)) {
+ reloc->ext = 1;
+ info->msd->extreloc = 1; /* section has external relocations */
+ } else if (!info->is_64) {
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *sym_precbc;
+
+ /* Local symbols need valued to their actual address */
+ if (yasm_symrec_get_label(value->rel, &sym_precbc)) {
+ yasm_section *sym_sect = yasm_bc_get_section(sym_precbc);
+ /*@null@*/ macho_section_data *msd;
+ msd = yasm_section_get_data(sym_sect, &macho_section_data_cb);
+ assert(msd != NULL);
+ intn_plus += msd->vmoff + yasm_bc_next_offset(sym_precbc);
+ }
+ }
+
+ info->msd->nreloc++;
+ /*printf("reloc %s type %d ",yasm_symrec_get_name(reloc->reloc.sym),reloc->type);*/
+ yasm_section_add_reloc(info->sect, (yasm_reloc *)reloc, yasm_xfree);
+ }
+
+ if (intn_minus <= intn_plus)
+ intn = yasm_intnum_create_uint(intn_plus-intn_minus);
+ else {
+ intn = yasm_intnum_create_uint(intn_minus-intn_plus);
+ yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
+ }
+
+ if (value->abs) {
+ yasm_intnum *intn2 = yasm_expr_get_intnum(&value->abs, 0);
+
+ if (!intn2) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("macho: relocation too complex"));
+ yasm_intnum_destroy(intn);
+ return 1;
+ }
+ yasm_intnum_calc(intn, YASM_EXPR_ADD, intn2);
+ }
+
+ retval = yasm_arch_intnum_tobytes(info->object->arch, intn, buf, destsize,
+ valsize, 0, bc, warn);
+ /*printf("val %ld\n",yasm_intnum_get_int(intn));*/
+ yasm_intnum_destroy(intn);
+ return retval;
+}
+
+static int
+macho_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
+{
+ /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
+ /*@null@*/ /*@only@*/ unsigned char *bigbuf;
+ unsigned long size = REGULAR_OUTBUF_SIZE;
+ int gap;
+
+ assert(info != NULL);
+
+ bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &gap, info,
+ macho_objfmt_output_value, NULL);
+
+ /* Don't bother doing anything else if size ended up being 0. */
+ if (size == 0) {
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+ return 0;
+ }
+
+ /* Warn that gaps are converted to 0 and write out the 0's. */
+ if (gap) {
+ unsigned long left;
+
+ yasm_warn_set(YASM_WARN_UNINIT_CONTENTS,
+ N_("uninitialized space: zeroing"));
+ /* Write out in chunks */
+ memset(info->buf, 0, REGULAR_OUTBUF_SIZE);
+ left = size;
+ while (left > REGULAR_OUTBUF_SIZE) {
+ fwrite(info->buf, REGULAR_OUTBUF_SIZE, 1, info->f);
+ left -= REGULAR_OUTBUF_SIZE;
+ }
+ fwrite(info->buf, left, 1, info->f);
+ } else {
+ /* Output buf (or bigbuf if non-NULL) to file */
+ fwrite(bigbuf ? bigbuf : info->buf, (size_t) size, 1, info->f);
+ }
+
+ /* If bigbuf was allocated, free it */
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+
+ return 0;
+}
+
+static int
+macho_objfmt_output_section(yasm_section *sect, /*@null@ */ void *d)
+{
+ /*@null@ */ macho_objfmt_output_info *info =
+ (macho_objfmt_output_info *) d;
+ /*@dependent@ *//*@null@ */ macho_section_data *msd;
+
+ assert(info != NULL);
+ msd = yasm_section_get_data(sect, &macho_section_data_cb);
+ assert(msd != NULL);
+
+ if (!(msd->flags & S_ZEROFILL)) {
+ /* Output non-BSS sections */
+ info->sect = sect;
+ info->msd = msd;
+ yasm_section_bcs_traverse(sect, info->errwarns, info,
+ macho_objfmt_output_bytecode);
+ }
+ return 0;
+}
+
+static int
+macho_objfmt_output_relocs(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ macho_section_data *msd;
+ macho_reloc *reloc;
+
+ reloc = (macho_reloc *)yasm_section_relocs_first(sect);
+ while (reloc) {
+ unsigned char *localbuf = info->buf;
+ /*@null@*/ macho_symrec_data *xsymd;
+ unsigned long symnum;
+
+ xsymd = yasm_symrec_get_data(reloc->reloc.sym, &macho_symrec_data_cb);
+ yasm_intnum_get_sized(reloc->reloc.addr, localbuf, 4, 32, 0, 0, 0);
+ localbuf += 4; /* address of relocation */
+
+ if (reloc->ext)
+ symnum = xsymd->index;
+ else {
+ /* find section where the symbol relates to */
+ /*@dependent@*/ /*@null@*/ yasm_section *dsect;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
+ symnum = 0; /* default to absolute */
+ if (yasm_symrec_get_label(reloc->reloc.sym, &precbc) &&
+ (dsect = yasm_bc_get_section(precbc)) &&
+ (msd = yasm_section_get_data(dsect, &macho_section_data_cb)))
+ symnum = msd->scnum+1;
+ }
+ YASM_WRITE_32_L(localbuf,
+ (symnum & 0x00ffffff) |
+ (((unsigned long)reloc->pcrel & 1) << 24) |
+ (((unsigned long)reloc->length & 3) << 25) |
+ (((unsigned long)reloc->ext & 1) << 27) |
+ (((unsigned long)reloc->type & 0xf) << 28));
+ fwrite(info->buf, 8, 1, info->f);
+ reloc = (macho_reloc *)yasm_section_reloc_next((yasm_reloc *)reloc);
+ }
+
+ return 0;
+}
+
+static int
+exp2_to_bits(unsigned long val)
+{
+ int ret = 0;
+
+ while (val) {
+ val >>= 1;
+ ret++;
+ }
+ ret = (ret > 0) ? ret - 1 : 0;
+
+ return ret;
+}
+
+static int
+macho_objfmt_is_section_label(yasm_symrec *sym)
+{
+ /*@dependent@*/ /*@null@*/ yasm_section *sect;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
+
+ /* Look at symrec for value/scnum/etc. */
+ if (yasm_symrec_get_label(sym, &precbc)) {
+ if (precbc)
+ sect = yasm_bc_get_section(precbc);
+ else
+ sect = NULL;
+ /* it's a label: get value and offset.
+ * If there is not a section, leave as debugging symbol.
+ */
+ if (sect) {
+ /*@dependent@*/ /*@null@*/ macho_section_data *msd;
+
+ msd = yasm_section_get_data(sect, &macho_section_data_cb);
+ if (msd) {
+ if (msd->sym == sym)
+ return 1; /* don't store section names */
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+macho_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ macho_section_data *msd;
+ unsigned char *localbuf;
+
+ assert(info != NULL);
+ msd = yasm_section_get_data(sect, &macho_section_data_cb);
+ assert(msd != NULL);
+
+ localbuf = info->buf;
+
+ memset(localbuf, 0, 16);
+ strncpy((char *)localbuf, msd->sectname, 16);
+ localbuf += 16;
+ memset(localbuf, 0, 16);
+ strncpy((char *)localbuf, msd->segname, 16);
+ localbuf += 16;
+ /* section address, size depend on 32/64 bit mode */
+ YASM_WRITE_32_L(localbuf, msd->vmoff); /* address in memory */
+ if (info->is_64)
+ YASM_WRITE_32_L(localbuf, 0); /* 64-bit mode: upper 32 bits = 0 */
+ YASM_WRITE_32_L(localbuf, msd->size); /* size in memory */
+ if (info->is_64)
+ YASM_WRITE_32_L(localbuf, 0); /* 64-bit mode: upper 32 bits = 0 */
+
+ /* offset,align,reloff,nreloc,flags,reserved1,reserved2 are 32 bit */
+ if ((msd->flags & SECTION_TYPE) != S_ZEROFILL) {
+ YASM_WRITE_32_L(localbuf, msd->offset);
+ YASM_WRITE_32_L(localbuf, exp2_to_bits(yasm_section_get_align(sect)));
+ if (msd->nreloc) {
+ msd->flags |= S_ATTR_LOC_RELOC;
+ if (msd->extreloc)
+ msd->flags |= S_ATTR_EXT_RELOC;
+ YASM_WRITE_32_L(localbuf,
+ align32((long)(info->rel_base + info->s_reloff)));
+ YASM_WRITE_32_L(localbuf, msd->nreloc); /* nreloc */
+ } else {
+ YASM_WRITE_32_L(localbuf, 0);
+ YASM_WRITE_32_L(localbuf, 0);
+ }
+
+ info->s_reloff += msd->nreloc * MACHO_RELINFO_SIZE; /* nreloc */
+ } else {
+ YASM_WRITE_32_L(localbuf, 0); /* these are zero in BSS */
+ YASM_WRITE_32_L(localbuf, 0);
+ YASM_WRITE_32_L(localbuf, 0);
+ YASM_WRITE_32_L(localbuf, 0);
+ }
+
+ YASM_WRITE_32_L(localbuf, msd->flags); /* flags */
+ YASM_WRITE_32_L(localbuf, 0); /* reserved 1 */
+ YASM_WRITE_32_L(localbuf, 0); /* reserved 2 */
+
+ if (info->is_64)
+ fwrite(info->buf, MACHO_SECTCMD64_SIZE, 1, info->f);
+ else
+ fwrite(info->buf, MACHO_SECTCMD_SIZE, 1, info->f);
+
+ return 0;
+}
+
+
+static int
+macho_objfmt_count_sym(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
+ /*@only@*/ char *name;
+ yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+
+ assert(info != NULL);
+ if (info->all_syms ||
+ vis & (YASM_SYM_GLOBAL | YASM_SYM_COMMON | YASM_SYM_EXTERN)) {
+ if (0 == macho_objfmt_is_section_label(sym)) {
+ /* Save index in symrec data */
+ macho_symrec_data *sym_data =
+ yasm_symrec_get_data(sym, &macho_symrec_data_cb);
+ if (!sym_data) {
+ sym_data = yasm_xcalloc(sizeof(macho_symrec_data), 1);
+ yasm_symrec_add_data(sym, &macho_symrec_data_cb, sym_data);
+ }
+ sym_data->index = info->symindex;
+ info->symindex++;
+
+ name = yasm_symrec_get_global_name(sym, info->object);
+ /*printf("%s\n",name); */
+ /* name length + delimiter */
+ sym_data->length = (unsigned long)strlen(name) + 1;
+ info->strlength += sym_data->length;
+ info->indx++;
+ yasm_xfree(name);
+ }
+ }
+ return 0;
+}
+
+
+static int
+macho_objfmt_output_symtable(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
+ yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+
+ assert(info != NULL);
+
+ if (info->all_syms ||
+ vis & (YASM_SYM_GLOBAL | YASM_SYM_COMMON | YASM_SYM_EXTERN)) {
+ const yasm_expr *equ_val;
+ const yasm_intnum *intn;
+ unsigned long value = 0;
+ long scnum = -3; /* -3 = debugging symbol */
+ /*@dependent@*/ /*@null@*/ yasm_section *sect;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
+ unsigned char *localbuf;
+ yasm_intnum *val;
+ unsigned int long_int_bytes = (info->is_64) ? 8 : 4;
+ unsigned int n_type = 0, n_sect = 0, n_desc = 0;
+ macho_symrec_data *symd;
+
+ val = yasm_intnum_create_uint(0);
+
+ symd = yasm_symrec_get_data(sym, &macho_symrec_data_cb);
+
+ /* Look at symrec for value/scnum/etc. */
+ if (yasm_symrec_get_label(sym, &precbc)) {
+ if (precbc)
+ sect = yasm_bc_get_section(precbc);
+ else
+ sect = NULL;
+ /* it's a label: get value and offset.
+ * If there is not a section, leave as debugging symbol.
+ */
+ if (sect) {
+ /*@dependent@*/ /*@null@*/ macho_section_data *msd;
+
+ msd = yasm_section_get_data(sect, &macho_section_data_cb);
+ if (msd) {
+ if (msd->sym == sym) {
+ /* don't store section names */
+ yasm_intnum_destroy(val);
+ return 0;
+ }
+ scnum = msd->scnum;
+ n_type = N_SECT;
+ } else
+ yasm_internal_error(N_("didn't understand section"));
+ if (precbc)
+ value += yasm_bc_next_offset(precbc);
+ /* all values are subject to correction: base offset is first
+ * raw section, therefore add section offset
+ */
+ if (msd)
+ value += msd->vmoff;
+ yasm_intnum_set_uint(val, value);
+ /*printf("%s offset %lx\n",name,value);*/
+ }
+ } else if ((equ_val = yasm_symrec_get_equ(sym))) {
+ yasm_expr *equ_val_copy = yasm_expr_copy(equ_val);
+
+ intn = yasm_expr_get_intnum(&equ_val_copy, 1);
+ if (!intn) {
+ if (vis & YASM_SYM_GLOBAL) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("global EQU value not an integer expression"));
+ yasm_errwarn_propagate(info->errwarns, equ_val->line);
+ }
+ } else
+ value = yasm_intnum_get_uint(intn);
+ yasm_expr_destroy(equ_val_copy);
+ yasm_intnum_set_uint(val, value);
+ n_type = N_ABS;
+ scnum = -2; /* -2 = absolute symbol */
+ }
+
+ if (vis & YASM_SYM_EXTERN) {
+ n_type = N_EXT;
+ scnum = -1;
+ /*n_desc = REFERENCE_FLAG_UNDEFINED_LAZY; * FIXME: see definition of REFERENCE_FLAG_* above */
+ } else if (vis & YASM_SYM_COMMON) {
+ yasm_expr **csize = yasm_symrec_get_common_size(sym);
+ n_type = N_UNDF | N_EXT;
+ if (csize) {
+ intn = yasm_expr_get_intnum(csize, 1);
+ if (!intn) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("COMMON data size not an integer expression"));
+ yasm_errwarn_propagate(info->errwarns, (*csize)->line);
+ } else
+ yasm_intnum_set_uint(val, yasm_intnum_get_uint(intn));
+ }
+ /*printf("common symbol %s val %lu\n", name, yasm_intnum_get_uint(val));*/
+ } else if (vis & YASM_SYM_GLOBAL) {
+ yasm_valparamhead *valparams =
+ yasm_symrec_get_objext_valparams(sym);
+
+ struct macho_global_data {
+ unsigned long flag; /* N_PEXT */
+ } data;
+
+ data.flag = 0;
+
+ if (valparams) {
+ static const yasm_dir_help help[] = {
+ { "private_extern", 0, yasm_dir_helper_flag_set,
+ offsetof(struct macho_global_data, flag), N_PEXT },
+ };
+ yasm_dir_helper(sym, yasm_vps_first(valparams),
+ yasm_symrec_get_decl_line(sym), help, NELEMS(help),
+ &data, yasm_dir_helper_valparam_warn);
+ }
+
+ n_type |= N_EXT | data.flag;
+ }
+
+ localbuf = info->buf;
+ YASM_WRITE_32_L(localbuf, info->indx); /* offset in string table */
+ YASM_WRITE_8(localbuf, n_type); /* type of symbol entry */
+ n_sect = (scnum >= 0) ? scnum + 1 : NO_SECT;
+ YASM_WRITE_8(localbuf, n_sect); /* referring section where symbol is found */
+ YASM_WRITE_16_L(localbuf, n_desc); /* extra description */
+ yasm_intnum_get_sized(val, localbuf, long_int_bytes, ((long_int_bytes) << 3), 0, 0, 0); /* value/argument */
+ localbuf += long_int_bytes;
+ if (symd)
+ symd->value = val;
+ else
+ yasm_intnum_destroy(val);
+
+ info->indx += symd->length;
+
+ fwrite(info->buf, 8 + long_int_bytes, 1, info->f);
+ }
+
+ return 0;
+}
+
+
+static int
+macho_objfmt_output_str(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
+ yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+
+ assert(info != NULL);
+
+ if (info->all_syms ||
+ vis & (YASM_SYM_GLOBAL | YASM_SYM_COMMON | YASM_SYM_EXTERN)) {
+ if (0 == macho_objfmt_is_section_label(sym)) {
+ /*@only@*/ char *name =
+ yasm_symrec_get_global_name(sym, info->object);
+ size_t len = strlen(name);
+
+ fwrite(name, len + 1, 1, info->f);
+ yasm_xfree(name);
+ }
+ }
+ return 0;
+}
+
+static int
+macho_objfmt_calc_sectsize(yasm_section *sect, /*@null@ */ void *d)
+{
+ /*@null@ */ macho_objfmt_output_info *info =
+ (macho_objfmt_output_info *) d;
+ /*@dependent@ *//*@null@ */ macho_section_data *msd;
+ unsigned long align;
+
+ assert(info != NULL);
+ msd = yasm_section_get_data(sect, &macho_section_data_cb);
+ assert(msd != NULL);
+
+ msd->size = yasm_bc_next_offset(yasm_section_bcs_last(sect));
+ if (!(msd->flags & S_ZEROFILL)) {
+ msd->offset = info->offset;
+ info->offset += msd->size;
+ info->filesize += msd->size;
+ }
+
+ /* accumulate size in memory */
+ msd->vmoff = info->vmsize;
+ info->vmsize += msd->size;
+
+ /* align both start and end of section */
+ align = yasm_section_get_align(sect);
+ if (align != 0) {
+ unsigned long delta = msd->vmoff % align;
+ if (delta > 0) {
+ msd->vmoff += align - delta;
+ info->vmsize += align - delta;
+ }
+ }
+
+ return 0;
+}
+
+/* write object */
+static void
+macho_objfmt_output(yasm_object *object, FILE *f, int all_syms,
+ yasm_errwarns *errwarns)
+{
+ yasm_objfmt_macho *objfmt_macho = (yasm_objfmt_macho *)object->objfmt;
+ macho_objfmt_output_info info;
+ unsigned char *localbuf;
+ unsigned long symtab_count = 0;
+ unsigned long headsize;
+ unsigned int macho_segcmdsize, macho_sectcmdsize, macho_nlistsize;
+ unsigned int macho_segcmd;
+ unsigned int head_ncmds, head_sizeofcmds;
+ unsigned long fileoffset, fileoff_sections;
+ yasm_intnum *val;
+ unsigned long long_int_bytes;
+ const char pad_data[3] = "\0\0\0";
+
+ info.object = object;
+ info.objfmt_macho = objfmt_macho;
+ info.errwarns = errwarns;
+ info.f = f;
+ info.buf = yasm_xmalloc(REGULAR_OUTBUF_SIZE);
+
+ if (objfmt_macho->parse_scnum == 0) {
+ yasm_internal_error(N_("no sections defined"));
+ /*@notreached@*/
+ return;
+ }
+
+ val = yasm_intnum_create_uint(0);
+
+ /*
+ * MACH-O Header, Seg CMD, Sect CMDs, Sym Tab, Reloc Data
+ */
+ info.is_64 = (objfmt_macho->bits == 32) ? 0 : 1;
+ if (info.is_64) {
+ /* this works only when SYMBOLS and SECTIONS present */
+ headsize =
+ MACHO_HEADER64_SIZE + MACHO_SEGCMD64_SIZE +
+ (MACHO_SECTCMD64_SIZE * (objfmt_macho->parse_scnum)) +
+ MACHO_SYMCMD_SIZE;
+ macho_segcmd = LC_SEGMENT_64;
+ macho_segcmdsize = MACHO_SEGCMD64_SIZE;
+ macho_sectcmdsize = MACHO_SECTCMD64_SIZE;
+ macho_nlistsize = MACHO_NLIST64_SIZE;
+ long_int_bytes = 8;
+ } else {
+ headsize =
+ MACHO_HEADER_SIZE + MACHO_SEGCMD_SIZE +
+ (MACHO_SECTCMD_SIZE * (objfmt_macho->parse_scnum)) +
+ MACHO_SYMCMD_SIZE;
+ macho_segcmd = LC_SEGMENT;
+ macho_segcmdsize = MACHO_SEGCMD_SIZE;
+ macho_sectcmdsize = MACHO_SECTCMD_SIZE;
+ macho_nlistsize = MACHO_NLIST_SIZE;
+ long_int_bytes = 4;
+ }
+
+ /* Get number of symbols */
+ info.symindex = 0;
+ info.indx = 0;
+ info.strlength = 1; /* string table starts with a zero byte */
+ info.all_syms = all_syms || info.is_64;
+ /*info.all_syms = 1; * force all syms into symbol table */
+ yasm_symtab_traverse(object->symtab, &info, macho_objfmt_count_sym);
+ symtab_count = info.indx;
+
+ /* write raw section data first */
+ if (fseek(f, (long)headsize, SEEK_SET) < 0) {
+ yasm__fatal(N_("could not seek on output file"));
+ /*@notreached@ */
+ return;
+ }
+
+ /* get size of sections in memory (including BSS) and size of sections
+ * in file (without BSS)
+ */
+ info.vmsize = 0;
+ info.filesize = 0;
+ info.offset = headsize;
+ yasm_object_sections_traverse(object, &info, macho_objfmt_calc_sectsize);
+
+ /* output sections to file */
+ yasm_object_sections_traverse(object, &info, macho_objfmt_output_section);
+
+ fileoff_sections = ftell(f);
+
+ /* Write headers */
+ if (fseek(f, 0, SEEK_SET) < 0) {
+ yasm__fatal(N_("could not seek on output file"));
+ /*@notreached@*/
+ return;
+ }
+
+ localbuf = info.buf;
+
+ /* header size is common to 32 bit and 64 bit variants */
+ if (info.is_64) {
+ YASM_WRITE_32_L(localbuf, MH_MAGIC_64); /* magic number */
+ /* i386 64-bit ABI */
+ YASM_WRITE_32_L(localbuf, CPU_ARCH_ABI64 | CPU_TYPE_I386);
+ } else {
+ YASM_WRITE_32_L(localbuf, MH_MAGIC); /* magic number */
+ YASM_WRITE_32_L(localbuf, CPU_TYPE_I386); /* i386 32-bit ABI */
+ }
+ /* i386 all cpu subtype compatible */
+ YASM_WRITE_32_L(localbuf, CPU_SUBTYPE_I386_ALL);
+ YASM_WRITE_32_L(localbuf, MH_OBJECT); /* MACH file type */
+
+ /* calculate number of commands and their size, put to stream */
+ head_ncmds = 0;
+ head_sizeofcmds = 0;
+ if (objfmt_macho->parse_scnum > 0) {
+ head_ncmds++;
+ head_sizeofcmds +=
+ macho_segcmdsize + macho_sectcmdsize * objfmt_macho->parse_scnum;
+ }
+ if (symtab_count > 0) {
+ head_ncmds++;
+ head_sizeofcmds += MACHO_SYMCMD_SIZE;
+ }
+
+ YASM_WRITE_32_L(localbuf, head_ncmds);
+ YASM_WRITE_32_L(localbuf, head_sizeofcmds);
+ YASM_WRITE_32_L(localbuf, 0); /* no flags (yet) */
+ if (info.is_64) {
+ YASM_WRITE_32_L(localbuf, 0); /* reserved in 64 bit */
+ fileoffset = MACHO_HEADER64_SIZE + head_sizeofcmds;
+ } else {
+ /* initial offset to first section */
+ fileoffset = MACHO_HEADER_SIZE + head_sizeofcmds;
+ }
+
+ /* --------------- write segment header command ---------------- */
+ YASM_WRITE_32_L(localbuf, macho_segcmd); /* command LC_SEGMENT */
+ /* size of load command including section load commands */
+ YASM_WRITE_32_L(localbuf,
+ macho_segcmdsize +
+ macho_sectcmdsize * objfmt_macho->parse_scnum);
+ /* in an MH_OBJECT file all sections are in one unnamed (name all zeros)
+ * segment (16x0)
+ */
+ YASM_WRITE_32_L(localbuf, 0);
+ YASM_WRITE_32_L(localbuf, 0);
+ YASM_WRITE_32_L(localbuf, 0);
+ YASM_WRITE_32_L(localbuf, 0);
+
+ /* in-memory offset, in-memory size */
+ yasm_intnum_set_uint(val, 0); /* offset in memory (vmaddr) */
+ yasm_intnum_get_sized(val, localbuf, long_int_bytes,
+ ((long_int_bytes) << 3), 0, 0, 0);
+ localbuf += long_int_bytes;
+ yasm_intnum_set_uint(val, info.vmsize); /* size in memory (vmsize) */
+ yasm_intnum_get_sized(val, localbuf, long_int_bytes,
+ ((long_int_bytes) << 3), 0, 0, 0);
+ localbuf += long_int_bytes;
+ /* offset in file to first section */
+ yasm_intnum_set_uint(val, fileoffset);
+ yasm_intnum_get_sized(val, localbuf, long_int_bytes,
+ ((long_int_bytes) << 3), 0, 0, 0);
+ localbuf += long_int_bytes;
+ yasm_intnum_set_uint(val, info.filesize); /* overall size in file */
+ yasm_intnum_get_sized(val, localbuf, long_int_bytes,
+ ((long_int_bytes) << 3), 0, 0, 0);
+ localbuf += long_int_bytes;
+
+ YASM_WRITE_32_L(localbuf, VM_PROT_DEFAULT); /* VM protection, maximum */
+ YASM_WRITE_32_L(localbuf, VM_PROT_DEFAULT); /* VM protection, initial */
+ /* number of sections */
+ YASM_WRITE_32_L(localbuf, objfmt_macho->parse_scnum);
+ YASM_WRITE_32_L(localbuf, 0); /* no flags */
+
+ /* write MACH-O header and segment command to outfile */
+ fwrite(info.buf, (size_t) (localbuf - info.buf), 1, f);
+
+ /* next: section headers */
+ /* offset to relocs for first section */
+ info.rel_base = align32((long)fileoff_sections);
+ info.s_reloff = 0; /* offset for relocs of following sections */
+ yasm_object_sections_traverse(object, &info, macho_objfmt_output_secthead);
+
+ localbuf = info.buf;
+ /* write out symbol command */
+ YASM_WRITE_32_L(localbuf, LC_SYMTAB); /* cmd == LC_SYMTAB */
+ YASM_WRITE_32_L(localbuf, MACHO_SYMCMD_SIZE);
+ /* symbol table offset */
+ YASM_WRITE_32_L(localbuf, info.rel_base + info.s_reloff);
+ YASM_WRITE_32_L(localbuf, symtab_count); /* number of symbols */
+
+ YASM_WRITE_32_L(localbuf, macho_nlistsize * symtab_count + info.rel_base +
+ info.s_reloff); /* string table offset */
+ YASM_WRITE_32_L(localbuf, info.strlength); /* string table size */
+ /* write symbol command */
+ fwrite(info.buf, (size_t)(localbuf - info.buf), 1, f);
+
+ /*printf("num symbols %d, vmsize %d, filesize %d\n",symtab_count,
+ info.vmsize, info.filesize ); */
+
+ /* get back to end of raw section data */
+ if (fseek(f, (long)fileoff_sections, SEEK_SET) < 0) {
+ yasm__fatal(N_("could not seek on output file"));
+ /*@notreached@*/
+ return;
+ }
+
+ /* padding to long boundary */
+ if ((info.rel_base - fileoff_sections) > 0) {
+ fwrite(pad_data, info.rel_base - fileoff_sections, 1, f);
+ }
+
+ /* relocation data */
+ yasm_object_sections_traverse(object, &info, macho_objfmt_output_relocs);
+
+ /* symbol table (NLIST) */
+ info.indx = 1; /* restart symbol table indices */
+ yasm_symtab_traverse(object->symtab, &info, macho_objfmt_output_symtable);
+
+ /* symbol strings */
+ fwrite(pad_data, 1, 1, f);
+ yasm_symtab_traverse(object->symtab, &info, macho_objfmt_output_str);
+
+ yasm_intnum_destroy(val);
+ yasm_xfree(info.buf);
+}
+
+static void
+macho_objfmt_destroy(yasm_objfmt *objfmt)
+{
+ yasm_xfree(objfmt);
+}
+
+static void
+macho_objfmt_init_new_section(yasm_section *sect, unsigned long line)
+{
+ yasm_object *object = yasm_section_get_object(sect);
+ const char *sectname = yasm_section_get_name(sect);
+ yasm_objfmt_macho *objfmt_macho = (yasm_objfmt_macho *)object->objfmt;
+ macho_section_data *data;
+ yasm_symrec *sym;
+
+ data = yasm_xmalloc(sizeof(macho_section_data));
+ data->scnum = objfmt_macho->parse_scnum++;
+ data->segname = NULL;
+ data->sectname = NULL;
+ data->flags = S_REGULAR;
+ data->size = 0;
+ data->offset = 0;
+ data->vmoff = 0;
+ data->nreloc = 0;
+ data->extreloc = 0;
+ yasm_section_add_data(sect, &macho_section_data_cb, data);
+
+ sym = yasm_symtab_define_label(object->symtab, sectname,
+ yasm_section_bcs_first(sect), 1, line);
+ data->sym = sym;
+}
+
+static yasm_section *
+macho_objfmt_add_default_section(yasm_object *object)
+{
+ yasm_section *retval;
+ macho_section_data *msd;
+ int isnew;
+
+ retval = yasm_object_get_general(object, "LC_SEGMENT.__TEXT.__text", 0, 1,
+ 0, &isnew, 0);
+ if (isnew) {
+ msd = yasm_section_get_data(retval, &macho_section_data_cb);
+ msd->segname = yasm__xstrdup("__TEXT");
+ msd->sectname = yasm__xstrdup("__text");
+ msd->flags = S_ATTR_PURE_INSTRUCTIONS;
+ yasm_section_set_align(retval, 0, 0);
+ yasm_section_set_default(retval, 1);
+ }
+ return retval;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_section *
+macho_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
+ /*@unused@*/ /*@null@*/
+ yasm_valparamhead *objext_valparams,
+ unsigned long line)
+{
+ yasm_valparam *vp;
+ yasm_section *retval;
+ int isnew;
+ /*@only@*/ char *f_sectname;
+ unsigned long flags;
+ unsigned long align;
+ int flags_override = 0;
+ const char *sectname;
+ char *realname;
+ int resonly = 0;
+ macho_section_data *msd;
+ size_t i;
+
+ static const struct {
+ const char *in;
+ const char *seg;
+ const char *sect;
+ unsigned long flags;
+ unsigned long align;
+ } section_name_translation[] = {
+ {".text", "__TEXT", "__text", S_ATTR_PURE_INSTRUCTIONS, 0},
+ {".const", "__TEXT", "__const", S_REGULAR, 0},
+ {".static_const", "__TEXT", "__static_const", S_REGULAR, 0},
+ {".cstring", "__TEXT", "__cstring", S_CSTRING_LITERALS, 0},
+ {".literal4", "__TEXT", "__literal4", S_4BYTE_LITERALS, 4},
+ {".literal8", "__TEXT", "__literal8", S_8BYTE_LITERALS, 8},
+ {".literal16", "__TEXT", "__literal16", S_16BYTE_LITERALS, 16},
+ {".constructor", "__TEXT", "__constructor", S_REGULAR, 0},
+ {".destructor", "__TEXT", "__destructor", S_REGULAR, 0},
+ {".fvmlib_init0", "__TEXT", "__fvmlib_init0", S_REGULAR, 0},
+ {".fvmlib_init1", "__TEXT", "__fvmlib_init1", S_REGULAR, 0},
+ {".mod_init_func", "__DATA", "__mod_init_func",
+ S_MOD_INIT_FUNC_POINTERS, 4},
+ {".mod_term_func", "__DATA", "__mod_term_func",
+ S_MOD_TERM_FUNC_POINTERS, 4},
+ {".dyld", "__DATA", "__dyld", S_REGULAR, 0},
+ {".data", "__DATA", "__data", S_REGULAR, 0},
+ {".static_data", "__DATA", "__static_data", S_REGULAR, 0},
+ {".const_data", "__DATA", "__const", S_REGULAR, 0},
+ {".rodata", "__DATA", "__const", S_REGULAR, 0},
+ {".bss", "__DATA", "__bss", S_ZEROFILL, 0},
+ {".objc_class_names", "__TEXT", "__cstring", S_CSTRING_LITERALS, 0},
+ {".objc_meth_var_types","__TEXT", "__cstring", S_CSTRING_LITERALS, 0},
+ {".objc_meth_var_names","__TEXT", "__cstring", S_CSTRING_LITERALS, 0},
+ {".objc_selector_strs", "__OBJC", "__selector_strs",
+ S_CSTRING_LITERALS, 0},
+ {".objc_class", "__OBJC", "__class",
+ S_ATTR_NO_DEAD_STRIP, 0},
+ {".objc_meta_class", "__OBJC", "__meta_class",
+ S_ATTR_NO_DEAD_STRIP, 0},
+ {".objc_string_object", "__OBJC", "__string_object",
+ S_ATTR_NO_DEAD_STRIP, 0},
+ {".objc_protocol", "__OBJC", "__protocol",
+ S_ATTR_NO_DEAD_STRIP, 0},
+ {".objc_cat_cls_meth", "__OBJC", "__cat_cls_meth",
+ S_ATTR_NO_DEAD_STRIP, 0},
+ {".objc_cat_inst_meth", "__OBJC", "__cat_inst_meth",
+ S_ATTR_NO_DEAD_STRIP, 0},
+ {".objc_cls_meth", "__OBJC", "__cls_meth",
+ S_ATTR_NO_DEAD_STRIP, 0},
+ {".objc_inst_meth", "__OBJC", "__inst_meth",
+ S_ATTR_NO_DEAD_STRIP, 0},
+ {".objc_message_refs", "__OBJC", "__message_refs",
+ S_LITERAL_POINTERS|S_ATTR_NO_DEAD_STRIP, 4},
+ {".objc_cls_refs", "__OBJC", "__cls_refs",
+ S_LITERAL_POINTERS|S_ATTR_NO_DEAD_STRIP, 4},
+ {".objc_module_info", "__OBJC", "__module_info",
+ S_ATTR_NO_DEAD_STRIP, 0},
+ {".objc_symbols", "__OBJC", "__symbols",
+ S_ATTR_NO_DEAD_STRIP, 0},
+ {".objc_category", "__OBJC", "__category",
+ S_ATTR_NO_DEAD_STRIP, 0},
+ {".objc_class_vars", "__OBJC", "__class_vars",
+ S_ATTR_NO_DEAD_STRIP, 0},
+ {".objc_instance_vars", "__OBJC", "__instance_vars",
+ S_ATTR_NO_DEAD_STRIP, 0}
+ };
+
+ struct macho_section_switch_data {
+ /*@only@*/ /*@null@*/ char *f_segname;
+ /*@only@*/ /*@null@*/ yasm_intnum *align_intn;
+ } data;
+
+ static const yasm_dir_help help[] = {
+ { "segname", 1, yasm_dir_helper_string,
+ offsetof(struct macho_section_switch_data, f_segname), 0 },
+ { "align", 1, yasm_dir_helper_intn,
+ offsetof(struct macho_section_switch_data, align_intn), 0 }
+ };
+
+ data.f_segname = NULL;
+ data.align_intn = NULL;
+
+ vp = yasm_vps_first(valparams);
+ sectname = yasm_vp_string(vp);
+ if (!sectname)
+ return NULL;
+ vp = yasm_vps_next(vp);
+
+ /* translate .text,.data,.bss to __text,__data,__bss... */
+ for (i=0; i<NELEMS(section_name_translation); i++) {
+ if (yasm__strcasecmp(sectname, section_name_translation[i].in) == 0)
+ break;
+ }
+
+ if (i == NELEMS(section_name_translation)) {
+ const char *s;
+ if (vp && !vp->val && (s = yasm_vp_string(vp))) {
+ /* Treat as SEGNAME, SECTNAME */
+ if (strlen(sectname) > 16)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("segment name is too long, max 16 chars; truncating"));
+ data.f_segname = yasm__xstrndup(sectname, 16);
+ if (strlen(s) > 16)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("section name is too long, max 16 chars; truncating"));
+ f_sectname = yasm__xstrndup(s, 16);
+ flags = S_REGULAR;
+ align = 0;
+
+ sectname = s;
+ vp = yasm_vps_next(vp);
+ } else {
+ data.f_segname = NULL;
+ if (strlen(sectname) > 16)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("section name is too long, max 16 chars; truncating"));
+ f_sectname = yasm__xstrndup(sectname, 16);
+ flags = S_ATTR_SOME_INSTRUCTIONS;
+ align = 0;
+ }
+ } else {
+ data.f_segname = yasm__xstrdup(section_name_translation[i].seg);
+ f_sectname = yasm__xstrdup(section_name_translation[i].sect);
+ flags = section_name_translation[i].flags;
+ align = section_name_translation[i].align;
+ }
+
+ flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help),
+ &data, yasm_dir_helper_valparam_warn);
+ if (flags_override < 0)
+ return NULL; /* error occurred */
+
+ if (data.align_intn) {
+ align = yasm_intnum_get_uint(data.align_intn);
+ yasm_intnum_destroy(data.align_intn);
+
+ /* Alignments must be a power of two. */
+ if (!is_exp2(align)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("argument to `%s' is not a power of two"),
+ vp->val);
+ return NULL;
+ }
+
+ /* Check to see if alignment is supported size */
+ if (align > 16384) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("macho implementation does not support alignments > 16384"));
+ return NULL;
+ }
+ }
+
+ if (!data.f_segname) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("Unknown section name, defaulting to __TEXT segment"));
+ data.f_segname = yasm__xstrdup("__TEXT");
+ }
+
+ /* Build a unique sectname from f_segname and f_sectname. */
+ realname = yasm_xmalloc(strlen("LC_SEGMENT") + 1 + strlen(data.f_segname) + 1 +
+ strlen(f_sectname) + 1);
+ sprintf(realname, "LC_SEGMENT.%s.%s", data.f_segname, f_sectname);
+ retval = yasm_object_get_general(object, realname, align, 1, resonly,
+ &isnew, line);
+ yasm_xfree(realname);
+
+ msd = yasm_section_get_data(retval, &macho_section_data_cb);
+
+ if (isnew || yasm_section_is_default(retval)) {
+ yasm_section_set_default(retval, 0);
+ msd->segname = data.f_segname;
+ msd->sectname = f_sectname;
+ msd->flags = flags;
+ yasm_section_set_align(retval, align, line);
+ } else if (flags_override) {
+ /* align is the only value used from overrides. */
+ if (yasm_section_get_align(retval) != align) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("section flags ignored on section redeclaration"));
+ }
+ }
+ return retval;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+macho_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ yasm_objfmt_macho *objfmt_macho = (yasm_objfmt_macho *)object->objfmt;
+ if (yasm__strcasecmp(name, "gotpcrel") == 0) {
+ return objfmt_macho->gotpcrel_sym;
+ }
+ return NULL;
+}
+
+static void
+macho_section_data_destroy(void *data)
+{
+ macho_section_data *msd = (macho_section_data *) data;
+ yasm_xfree(msd->segname);
+ yasm_xfree(msd->sectname);
+ yasm_xfree(data);
+}
+
+static void
+macho_section_data_print(void *data, FILE *f, int indent_level)
+{
+ macho_section_data *msd = (macho_section_data *) data;
+
+ fprintf(f, "%*ssym=\n", indent_level, "");
+ yasm_symrec_print(msd->sym, f, indent_level + 1);
+ fprintf(f, "%*sscnum=%ld\n", indent_level, "", msd->scnum);
+ fprintf(f, "%*sflags=0x%lx\n", indent_level, "", msd->flags);
+ fprintf(f, "%*ssize=%lu\n", indent_level, "", msd->size);
+ fprintf(f, "%*snreloc=%lu\n", indent_level, "", msd->nreloc);
+ fprintf(f, "%*soffset=%lu\n", indent_level, "", msd->offset);
+ fprintf(f, "%*sextreloc=%u\n", indent_level, "", msd->extreloc);
+}
+
+static void
+macho_symrec_data_destroy(void *data)
+{
+ yasm_xfree(data);
+}
+
+static void
+macho_symrec_data_print(void *data, FILE *f, int indent_level)
+{
+ macho_symrec_data *msd = (macho_symrec_data *)data;
+
+ fprintf(f, "%*sindex=%ld\n", indent_level, "", msd->index);
+ fprintf(f, "%*svalue=", indent_level, "");
+ if (msd->value)
+ fprintf(f, "%ld\n", yasm_intnum_get_int(msd->value));
+ else
+ fprintf(f, "nil\n");
+}
+
+
+/* Define valid debug formats to use with this object format */
+static const char *macho_objfmt_dbgfmt_keywords[] = {
+ "null",
+ NULL
+};
+
+/* Define objfmt structure -- see objfmt.h for details */
+yasm_objfmt_module yasm_macho_LTX_objfmt = {
+ "Mac OS X ABI Mach-O File Format",
+ "macho",
+ "o",
+ 32,
+ 0,
+ macho_objfmt_dbgfmt_keywords,
+ "null",
+ NULL, /* no directives */
+ NULL, /* no standard macros */
+ macho_objfmt_create,
+ macho_objfmt_output,
+ macho_objfmt_destroy,
+ macho_objfmt_add_default_section,
+ macho_objfmt_init_new_section,
+ macho_objfmt_section_switch,
+ macho_objfmt_get_special_sym
+};
+
+yasm_objfmt_module yasm_macho32_LTX_objfmt = {
+ "Mac OS X ABI Mach-O File Format (32-bit)",
+ "macho32",
+ "o",
+ 32,
+ 0,
+ macho_objfmt_dbgfmt_keywords,
+ "null",
+ NULL, /* no directives */
+ NULL, /* no standard macros */
+ macho32_objfmt_create,
+ macho_objfmt_output,
+ macho_objfmt_destroy,
+ macho_objfmt_add_default_section,
+ macho_objfmt_init_new_section,
+ macho_objfmt_section_switch,
+ macho_objfmt_get_special_sym
+};
+
+yasm_objfmt_module yasm_macho64_LTX_objfmt = {
+ "Mac OS X ABI Mach-O File Format (64-bit)",
+ "macho64",
+ "o",
+ 64,
+ 0,
+ macho_objfmt_dbgfmt_keywords,
+ "null",
+ NULL, /* no directives */
+ NULL, /* no standard macros */
+ macho64_objfmt_create,
+ macho_objfmt_output,
+ macho_objfmt_destroy,
+ macho_objfmt_add_default_section,
+ macho_objfmt_init_new_section,
+ macho_objfmt_section_switch,
+ macho_objfmt_get_special_sym
+};
diff --git a/contrib/tools/yasm/modules/objfmts/rdf/rdf-objfmt.c b/contrib/tools/yasm/modules/objfmts/rdf/rdf-objfmt.c
new file mode 100644
index 0000000000..eb3c66688c
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/rdf/rdf-objfmt.c
@@ -0,0 +1,1088 @@
+/*
+ * Relocatable Dynamic Object File Format (RDOFF) version 2 format
+ *
+ * Copyright (C) 2006-2007 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 <util.h>
+
+#include <libyasm.h>
+
+
+#define REGULAR_OUTBUF_SIZE 1024
+
+#define RDF_MAGIC "RDOFF2"
+
+/* Maximum size of an import/export label (including trailing zero) */
+#define EXIM_LABEL_MAX 64
+
+/* Maximum size of library or module name (including trailing zero) */
+#define MODLIB_NAME_MAX 128
+
+/* Maximum number of segments that we can handle in one file */
+#define RDF_MAXSEGS 64
+
+/* Record types that may present the RDOFF header */
+#define RDFREC_GENERIC 0
+#define RDFREC_RELOC 1
+#define RDFREC_IMPORT 2
+#define RDFREC_GLOBAL 3
+#define RDFREC_DLL 4
+#define RDFREC_BSS 5
+#define RDFREC_SEGRELOC 6
+#define RDFREC_FARIMPORT 7
+#define RDFREC_MODNAME 8
+#define RDFREC_COMMON 10
+
+/* Flags for ExportRec/ImportRec */
+#define SYM_DATA 1
+#define SYM_FUNCTION 2
+
+/* Flags for ExportRec */
+#define SYM_GLOBAL 4
+
+/* Flags for ImportRec */
+#define SYM_IMPORT 8
+#define SYM_FAR 16
+
+typedef struct rdf_reloc {
+ yasm_reloc reloc;
+ enum {
+ RDF_RELOC_NORM, /* normal */
+ RDF_RELOC_REL, /* relative to current position */
+ RDF_RELOC_SEG /* segment containing symbol */
+ } type; /* type of relocation */
+ unsigned int size;
+ unsigned int refseg;
+} rdf_reloc;
+
+typedef struct rdf_section_data {
+ /*@dependent@*/ yasm_symrec *sym; /* symbol created for this section */
+ long scnum; /* section number (0=first section) */
+ enum {
+ RDF_SECT_BSS = 0,
+ RDF_SECT_CODE = 1,
+ RDF_SECT_DATA = 2,
+ RDF_SECT_COMMENT = 3,
+ RDF_SECT_LCOMMENT = 4,
+ RDF_SECT_PCOMMENT = 5,
+ RDF_SECT_SYMDEBUG = 6,
+ RDF_SECT_LINEDEBUG = 7
+ } type; /* section type */
+ unsigned int reserved; /* reserved data */
+ unsigned long size; /* size of raw data (section data) in bytes */
+
+ unsigned char *raw_data; /* raw section data, only used during output */
+} rdf_section_data;
+
+typedef struct rdf_symrec_data {
+ unsigned int segment; /* assigned RDF "segment" index */
+} rdf_symrec_data;
+
+typedef STAILQ_HEAD(xdf_str_head, xdf_str) xdf_str_head;
+typedef struct xdf_str {
+ STAILQ_ENTRY(xdf_str) link;
+ /*@owned@*/ char *str;
+} xdf_str;
+
+typedef struct yasm_objfmt_rdf {
+ yasm_objfmt_base objfmt; /* base structure */
+
+ long parse_scnum; /* sect numbering in parser */
+
+ /*@owned@*/ xdf_str_head module_names;
+ /*@owned@*/ xdf_str_head library_names;
+} yasm_objfmt_rdf;
+
+typedef struct rdf_objfmt_output_info {
+ yasm_object *object;
+ yasm_objfmt_rdf *objfmt_rdf;
+ yasm_errwarns *errwarns;
+ /*@dependent@*/ FILE *f;
+ /*@only@*/ unsigned char *buf;
+ yasm_section *sect;
+ /*@dependent@*/ rdf_section_data *rsd;
+
+ unsigned long indx; /* symbol "segment" (extern/common only) */
+
+ unsigned long bss_size; /* total BSS size */
+} rdf_objfmt_output_info;
+
+static void rdf_section_data_destroy(/*@only@*/ void *d);
+static void rdf_section_data_print(void *data, FILE *f, int indent_level);
+
+static const yasm_assoc_data_callback rdf_section_data_cb = {
+ rdf_section_data_destroy,
+ rdf_section_data_print
+};
+
+static void rdf_symrec_data_destroy(/*@only@*/ void *d);
+static void rdf_symrec_data_print(void *data, FILE *f, int indent_level);
+
+static const yasm_assoc_data_callback rdf_symrec_data_cb = {
+ rdf_symrec_data_destroy,
+ rdf_symrec_data_print
+};
+
+yasm_objfmt_module yasm_rdf_LTX_objfmt;
+
+
+static /*@dependent@*/ rdf_symrec_data *
+rdf_objfmt_sym_set_data(yasm_symrec *sym, unsigned int segment)
+{
+ rdf_symrec_data *rsymd = yasm_xmalloc(sizeof(rdf_symrec_data));
+
+ rsymd->segment = segment;
+
+ yasm_symrec_add_data(sym, &rdf_symrec_data_cb, rsymd);
+ return rsymd;
+}
+
+static yasm_objfmt *
+rdf_objfmt_create(yasm_object *object)
+{
+ yasm_objfmt_rdf *objfmt_rdf = yasm_xmalloc(sizeof(yasm_objfmt_rdf));
+
+ /* We theoretically support all arches, so don't check.
+ * Really we only support byte-addressable ones.
+ */
+
+ objfmt_rdf->parse_scnum = 0; /* section numbering starts at 0 */
+
+ STAILQ_INIT(&objfmt_rdf->module_names);
+ STAILQ_INIT(&objfmt_rdf->library_names);
+
+ objfmt_rdf->objfmt.module = &yasm_rdf_LTX_objfmt;
+
+ return (yasm_objfmt *)objfmt_rdf;
+}
+
+static int
+rdf_objfmt_output_value(yasm_value *value, unsigned char *buf,
+ unsigned int destsize, unsigned long offset,
+ yasm_bytecode *bc, int warn, /*@null@*/ void *d)
+{
+ /*@null@*/ rdf_objfmt_output_info *info = (rdf_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
+ unsigned long intn_minus;
+ unsigned long intn_plus;
+ int retval;
+ unsigned int valsize = value->size;
+
+ assert(info != NULL);
+
+ if (value->abs)
+ value->abs = yasm_expr_simplify(value->abs, 1);
+
+ /* Try to output constant and PC-relative section-local first.
+ * Note this does NOT output any value with a SEG, WRT, external,
+ * cross-section, or non-PC-relative reference (those are handled below).
+ */
+ switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
+ info->object->arch)) {
+ case -1:
+ return 1;
+ case 0:
+ break;
+ default:
+ return 0;
+ }
+
+ if (value->section_rel) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("rdf: relocation too complex"));
+ return 1;
+ }
+
+ if (value->rel && value->wrt) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("rdf: WRT not supported"));
+ return 1;
+ }
+
+ intn_minus = 0;
+ intn_plus = 0;
+ if (value->rel) {
+ rdf_reloc *reloc;
+ /*@null@*/ rdf_symrec_data *rsymd;
+ /*@dependent@*/ yasm_bytecode *precbc;
+
+ reloc = yasm_xmalloc(sizeof(rdf_reloc));
+ reloc->reloc.addr = yasm_intnum_create_uint(bc->offset + offset);
+ reloc->reloc.sym = value->rel;
+ reloc->size = valsize/8;
+
+ if (value->seg_of)
+ reloc->type = RDF_RELOC_SEG;
+ else if (value->curpos_rel) {
+ reloc->type = RDF_RELOC_REL;
+ /* Adjust to start of section, so subtract out the bytecode
+ * offset.
+ */
+ intn_minus = bc->offset;
+ } else
+ reloc->type = RDF_RELOC_NORM;
+
+ if (yasm_symrec_get_label(value->rel, &precbc)) {
+ /* local, set the value to be the offset, and the refseg to the
+ * segment number.
+ */
+ /*@dependent@*/ /*@null@*/ rdf_section_data *csectd;
+ /*@dependent@*/ yasm_section *sect;
+
+ sect = yasm_bc_get_section(precbc);
+ csectd = yasm_section_get_data(sect, &rdf_section_data_cb);
+ if (!csectd)
+ yasm_internal_error(N_("didn't understand section"));
+ reloc->refseg = csectd->scnum;
+ intn_plus = yasm_bc_next_offset(precbc);
+ } else {
+ /* must be common/external */
+ rsymd = yasm_symrec_get_data(reloc->reloc.sym,
+ &rdf_symrec_data_cb);
+ if (!rsymd)
+ yasm_internal_error(
+ N_("rdf: no symbol data for relocated symbol"));
+ reloc->refseg = rsymd->segment;
+ }
+
+ yasm_section_add_reloc(info->sect, (yasm_reloc *)reloc, yasm_xfree);
+ }
+
+ if (intn_minus > 0) {
+ intn = yasm_intnum_create_uint(intn_minus);
+ yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
+ } else
+ intn = yasm_intnum_create_uint(intn_plus);
+
+ if (value->abs) {
+ yasm_intnum *intn2 = yasm_expr_get_intnum(&value->abs, 0);
+ if (!intn2) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("rdf: relocation too complex"));
+ yasm_intnum_destroy(intn);
+ return 1;
+ }
+ yasm_intnum_calc(intn, YASM_EXPR_ADD, intn2);
+ }
+
+ retval = yasm_arch_intnum_tobytes(info->object->arch, intn, buf, destsize,
+ valsize, 0, bc, warn);
+ yasm_intnum_destroy(intn);
+ return retval;
+}
+
+static int
+rdf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
+{
+ /*@null@*/ rdf_objfmt_output_info *info = (rdf_objfmt_output_info *)d;
+ /*@null@*/ /*@only@*/ unsigned char *bigbuf;
+ unsigned long size = REGULAR_OUTBUF_SIZE;
+ int gap;
+
+ assert(info != NULL);
+
+ bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &gap, info,
+ rdf_objfmt_output_value, NULL);
+
+ /* Don't bother doing anything else if size ended up being 0. */
+ if (size == 0) {
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+ return 0;
+ }
+
+ /* Warn that gaps are converted to 0 and write out the 0's. */
+ if (gap) {
+ yasm_warn_set(YASM_WARN_UNINIT_CONTENTS,
+ N_("uninitialized space: zeroing"));
+ /* Write out in chunks */
+ memset(&info->rsd->raw_data[info->rsd->size], 0, size);
+ } else {
+ /* Output buf (or bigbuf if non-NULL) to file */
+ memcpy(&info->rsd->raw_data[info->rsd->size],
+ bigbuf ? bigbuf : info->buf, (size_t)size);
+ }
+
+ info->rsd->size += size;
+
+ /* If bigbuf was allocated, free it */
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+
+ return 0;
+}
+
+static int
+rdf_objfmt_output_section_mem(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ rdf_objfmt_output_info *info = (rdf_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ rdf_section_data *rsd;
+ unsigned long size;
+
+ assert(info != NULL);
+ rsd = yasm_section_get_data(sect, &rdf_section_data_cb);
+ assert(rsd != NULL);
+
+ size = yasm_bc_next_offset(yasm_section_bcs_last(sect));
+
+ if (rsd->type == RDF_SECT_BSS) {
+ /* Don't output BSS sections, but remember length
+ * TODO: Check for non-reserve bytecodes?
+ */
+ info->bss_size += size;
+ return 0;
+ }
+
+ /* Empty? Go on to next section */
+ if (size == 0)
+ return 0;
+
+ /* See UGH comment in output() for why we're doing this */
+ rsd->raw_data = yasm_xmalloc(size);
+ rsd->size = 0;
+
+ info->sect = sect;
+ info->rsd = rsd;
+ yasm_section_bcs_traverse(sect, info->errwarns, info,
+ rdf_objfmt_output_bytecode);
+
+ /* Sanity check final section size */
+ if (rsd->size != size)
+ yasm_internal_error(
+ N_("rdf: section computed size did not match actual size"));
+
+ return 0;
+}
+
+static int
+rdf_objfmt_output_section_reloc(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ rdf_objfmt_output_info *info = (rdf_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ rdf_section_data *rsd;
+ rdf_reloc *reloc;
+
+ assert(info != NULL);
+ rsd = yasm_section_get_data(sect, &rdf_section_data_cb);
+ assert(rsd != NULL);
+
+ if (rsd->type == RDF_SECT_BSS) {
+ /* Don't output BSS sections. */
+ return 0;
+ }
+
+ /* Empty? Go on to next section */
+ if (rsd->size == 0)
+ return 0;
+
+ reloc = (rdf_reloc *)yasm_section_relocs_first(sect);
+ while (reloc) {
+ unsigned char *localbuf = info->buf;
+
+ if (reloc->type == RDF_RELOC_SEG)
+ YASM_WRITE_8(localbuf, RDFREC_SEGRELOC);
+ else
+ YASM_WRITE_8(localbuf, RDFREC_RELOC);
+ YASM_WRITE_8(localbuf, 8); /* record length */
+ /* Section number, +0x40 if relative reloc */
+ YASM_WRITE_8(localbuf, rsd->scnum +
+ (reloc->type == RDF_RELOC_REL ? 0x40 : 0));
+ yasm_intnum_get_sized(reloc->reloc.addr, localbuf, 4, 32, 0, 0, 0);
+ localbuf += 4; /* offset of relocation */
+ YASM_WRITE_8(localbuf, reloc->size); /* size of relocation */
+ YASM_WRITE_16_L(localbuf, reloc->refseg); /* relocated symbol */
+ fwrite(info->buf, 10, 1, info->f);
+
+ reloc = (rdf_reloc *)yasm_section_reloc_next((yasm_reloc *)reloc);
+ }
+
+ return 0;
+}
+
+static int
+rdf_objfmt_output_section_file(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ rdf_objfmt_output_info *info = (rdf_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ rdf_section_data *rsd;
+ unsigned char *localbuf;
+
+ assert(info != NULL);
+ rsd = yasm_section_get_data(sect, &rdf_section_data_cb);
+ assert(rsd != NULL);
+
+ if (rsd->type == RDF_SECT_BSS) {
+ /* Don't output BSS sections. */
+ return 0;
+ }
+
+ /* Empty? Go on to next section */
+ if (rsd->size == 0)
+ return 0;
+
+ /* Section header */
+ localbuf = info->buf;
+ YASM_WRITE_16_L(localbuf, rsd->type); /* type */
+ YASM_WRITE_16_L(localbuf, rsd->scnum); /* number */
+ YASM_WRITE_16_L(localbuf, rsd->reserved); /* reserved */
+ YASM_WRITE_32_L(localbuf, rsd->size); /* length */
+ fwrite(info->buf, 10, 1, info->f);
+
+ /* Section data */
+ fwrite(rsd->raw_data, rsd->size, 1, info->f);
+
+ /* Free section data */
+ yasm_xfree(rsd->raw_data);
+ rsd->raw_data = NULL;
+
+ return 0;
+}
+
+#define FLAG_EXT 0x1000
+#define FLAG_GLOB 0x2000
+#define FLAG_SET 0x4000
+#define FLAG_CLR 0x8000
+#define FLAG_MASK 0x0fff
+
+static int
+rdf_helper_flag(void *obj, yasm_valparam *vp, unsigned long line, void *d,
+ uintptr_t flag)
+{
+ yasm_symrec *sym = (yasm_symrec *)obj;
+ yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+ unsigned int *flags = (unsigned int *)d;
+
+ if (((vis & YASM_SYM_GLOBAL) && (flag & FLAG_GLOB)) ||
+ ((vis & YASM_SYM_EXTERN) && (flag & FLAG_EXT))) {
+ if (flag & FLAG_SET)
+ *flags |= flag & FLAG_MASK;
+ else if (flag & FLAG_CLR)
+ *flags &= ~(flag & FLAG_MASK);
+ }
+ return 0;
+}
+
+static unsigned int
+rdf_parse_flags(yasm_symrec *sym)
+{
+ /*@dependent@*/ /*@null@*/ yasm_valparamhead *objext_valparams =
+ yasm_symrec_get_objext_valparams(sym);
+ unsigned int flags = 0;
+
+ static const yasm_dir_help help[] = {
+ { "data", 0, rdf_helper_flag, 0,
+ FLAG_EXT|FLAG_GLOB|FLAG_SET|SYM_DATA },
+ { "object", 0, rdf_helper_flag, 0,
+ FLAG_EXT|FLAG_GLOB|FLAG_SET|SYM_DATA },
+ { "proc", 0, rdf_helper_flag, 0,
+ FLAG_EXT|FLAG_GLOB|FLAG_SET|SYM_FUNCTION },
+ { "function", 0, rdf_helper_flag, 0,
+ FLAG_EXT|FLAG_GLOB|FLAG_SET|SYM_FUNCTION },
+ { "import", 0, rdf_helper_flag, 0, FLAG_EXT|FLAG_SET|SYM_IMPORT },
+ { "export", 0, rdf_helper_flag, 0, FLAG_GLOB|FLAG_SET|SYM_GLOBAL },
+ { "far", 0, rdf_helper_flag, 0, FLAG_EXT|FLAG_SET|SYM_FAR },
+ { "near", 0, rdf_helper_flag, 0, FLAG_EXT|FLAG_CLR|SYM_FAR }
+ };
+
+ if (!objext_valparams)
+ return 0;
+
+ yasm_dir_helper(sym, yasm_vps_first(objext_valparams), 0, help,
+ NELEMS(help), &flags, yasm_dir_helper_valparam_warn);
+
+ return flags;
+}
+
+static int
+rdf_objfmt_output_sym(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ /*@null@*/ rdf_objfmt_output_info *info = (rdf_objfmt_output_info *)d;
+ yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+ /*@only@*/ char *name;
+ size_t len;
+ unsigned long value = 0;
+ unsigned int scnum = 0;
+ /*@dependent@*/ /*@null@*/ yasm_section *sect;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
+ unsigned char *localbuf;
+
+ assert(info != NULL);
+
+ if (vis == YASM_SYM_LOCAL || vis == YASM_SYM_DLOCAL)
+ return 0; /* skip local syms */
+
+ /* Look at symrec for value/scnum/etc. */
+ if (yasm_symrec_get_label(sym, &precbc)) {
+ /*@dependent@*/ /*@null@*/ rdf_section_data *csectd;
+
+ if (precbc)
+ sect = yasm_bc_get_section(precbc);
+ else
+ sect = NULL;
+ if (!sect)
+ return 0;
+
+ /* it's a label: get value and offset. */
+ csectd = yasm_section_get_data(sect, &rdf_section_data_cb);
+ if (csectd)
+ scnum = csectd->scnum;
+ else
+ yasm_internal_error(N_("didn't understand section"));
+ value = yasm_bc_next_offset(precbc);
+ } else if (yasm_symrec_get_equ(sym)) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("rdf does not support exporting EQU/absolute values"));
+ yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym));
+ return 0;
+ }
+
+ name = yasm_symrec_get_global_name(sym, info->object);
+ len = strlen(name);
+
+ if (len > EXIM_LABEL_MAX-1) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("label name too long, truncating to %d bytes"),
+ EXIM_LABEL_MAX);
+ len = EXIM_LABEL_MAX-1;
+ }
+
+ localbuf = info->buf;
+ if (vis & YASM_SYM_GLOBAL) {
+ YASM_WRITE_8(localbuf, RDFREC_GLOBAL);
+ YASM_WRITE_8(localbuf, 6+len+1); /* record length */
+ YASM_WRITE_8(localbuf, rdf_parse_flags(sym)); /* flags */
+ YASM_WRITE_8(localbuf, scnum); /* segment referred to */
+ YASM_WRITE_32_L(localbuf, value); /* offset */
+ } else {
+ /* Save symbol segment in symrec data (for later reloc gen) */
+ scnum = info->indx++;
+ rdf_objfmt_sym_set_data(sym, scnum);
+
+ if (vis & YASM_SYM_COMMON) {
+ /*@dependent@*/ /*@null@*/ yasm_expr **csize_expr;
+ const yasm_intnum *intn;
+ /*@dependent@*/ /*@null@*/ yasm_valparamhead *objext_valparams =
+ yasm_symrec_get_objext_valparams(sym);
+ unsigned long addralign = 0;
+
+ YASM_WRITE_8(localbuf, RDFREC_COMMON);
+ YASM_WRITE_8(localbuf, 8+len+1); /* record length */
+ YASM_WRITE_16_L(localbuf, scnum); /* segment allocated */
+
+ /* size */
+ csize_expr = yasm_symrec_get_common_size(sym);
+ assert(csize_expr != NULL);
+ intn = yasm_expr_get_intnum(csize_expr, 1);
+ if (!intn) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("COMMON data size not an integer expression"));
+ } else
+ value = yasm_intnum_get_uint(intn);
+ YASM_WRITE_32_L(localbuf, value);
+
+ /* alignment */
+ if (objext_valparams) {
+ yasm_valparam *vp = yasm_vps_first(objext_valparams);
+ for (; vp; vp = yasm_vps_next(vp)) {
+ if (!vp->val) {
+ /*@only@*/ /*@null@*/ yasm_expr *align_expr;
+ /*@dependent@*/ /*@null@*/
+ const yasm_intnum *align_intn;
+
+ if (!(align_expr = yasm_vp_expr(vp,
+ info->object->symtab,
+ yasm_symrec_get_decl_line(sym))) ||
+ !(align_intn = yasm_expr_get_intnum(&align_expr,
+ 0))) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("argument to `%s' is not an integer"),
+ vp->val);
+ if (align_expr)
+ yasm_expr_destroy(align_expr);
+ continue;
+ }
+ addralign = yasm_intnum_get_uint(align_intn);
+ yasm_expr_destroy(align_expr);
+
+ /* Alignments must be a power of two. */
+ if (!is_exp2(addralign)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("alignment constraint is not a power of two"));
+ continue;
+ }
+ } else
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("Unrecognized qualifier `%s'"), vp->val);
+ }
+ }
+ YASM_WRITE_16_L(localbuf, addralign);
+ } else if (vis & YASM_SYM_EXTERN) {
+ unsigned int flags = rdf_parse_flags(sym);
+ if (flags & SYM_FAR) {
+ YASM_WRITE_8(localbuf, RDFREC_FARIMPORT);
+ flags &= ~SYM_FAR;
+ } else
+ YASM_WRITE_8(localbuf, RDFREC_IMPORT);
+ YASM_WRITE_8(localbuf, 3+len+1); /* record length */
+ YASM_WRITE_8(localbuf, flags); /* flags */
+ YASM_WRITE_16_L(localbuf, scnum); /* segment allocated */
+ }
+ }
+
+ /* Symbol name */
+ memcpy(localbuf, name, len);
+ localbuf += len;
+ YASM_WRITE_8(localbuf, 0); /* 0-terminated name */
+ yasm_xfree(name);
+
+ fwrite(info->buf, (unsigned long)(localbuf-info->buf), 1, info->f);
+
+ yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym));
+ return 0;
+}
+
+static void
+rdf_objfmt_output(yasm_object *object, FILE *f, int all_syms,
+ yasm_errwarns *errwarns)
+{
+ yasm_objfmt_rdf *objfmt_rdf = (yasm_objfmt_rdf *)object->objfmt;
+ rdf_objfmt_output_info info;
+ unsigned char *localbuf;
+ long headerlen, filelen;
+ xdf_str *cur;
+ size_t len;
+
+ info.object = object;
+ info.objfmt_rdf = objfmt_rdf;
+ info.errwarns = errwarns;
+ info.f = f;
+ info.buf = yasm_xmalloc(REGULAR_OUTBUF_SIZE);
+ info.bss_size = 0;
+
+ /* Allocate space for file header by seeking forward */
+ if (fseek(f, (long)strlen(RDF_MAGIC)+8, SEEK_SET) < 0) {
+ yasm__fatal(N_("could not seek on output file"));
+ /*@notreached@*/
+ return;
+ }
+
+ /* Output custom header records (library and module, etc) */
+ cur = STAILQ_FIRST(&objfmt_rdf->module_names);
+ while (cur) {
+ len = strlen(cur->str)+1;
+ localbuf = info.buf;
+ YASM_WRITE_8(localbuf, RDFREC_MODNAME); /* record type */
+ YASM_WRITE_8(localbuf, len); /* record length */
+ fwrite(info.buf, 2, 1, f);
+ fwrite(cur->str, len, 1, f);
+ cur = STAILQ_NEXT(cur, link);
+ }
+
+ cur = STAILQ_FIRST(&objfmt_rdf->library_names);
+ while (cur) {
+ len = strlen(cur->str)+1;
+ localbuf = info.buf;
+ YASM_WRITE_8(localbuf, RDFREC_DLL); /* record type */
+ YASM_WRITE_8(localbuf, len); /* record length */
+ fwrite(info.buf, 2, 1, f);
+ fwrite(cur->str, len, 1, f);
+ cur = STAILQ_NEXT(cur, link);
+ }
+
+ /* Output symbol table */
+ info.indx = objfmt_rdf->parse_scnum;
+ yasm_symtab_traverse(object->symtab, &info, rdf_objfmt_output_sym);
+
+ /* UGH! Due to the fact the relocs go at the beginning of the file, and
+ * we only know if we have relocs when we output the sections, we have
+ * to output the section data before we have output the relocs. But
+ * we also don't know how much space to preallocate for relocs, so....
+ * we output into memory buffers first (thus the UGH).
+ *
+ * Stupid object format design, if you ask me (basically all other
+ * object formats put the relocs *after* the section data to avoid this
+ * exact problem).
+ *
+ * We also calculate the total size of all BSS sections here.
+ */
+ if (yasm_object_sections_traverse(object, &info,
+ rdf_objfmt_output_section_mem))
+ return;
+
+ /* Output all relocs */
+ if (yasm_object_sections_traverse(object, &info,
+ rdf_objfmt_output_section_reloc))
+ return;
+
+ /* Output BSS record */
+ if (info.bss_size > 0) {
+ localbuf = info.buf;
+ YASM_WRITE_8(localbuf, RDFREC_BSS); /* record type */
+ YASM_WRITE_8(localbuf, 4); /* record length */
+ YASM_WRITE_32_L(localbuf, info.bss_size); /* total BSS size */
+ fwrite(info.buf, 6, 1, f);
+ }
+
+ /* Determine header length */
+ headerlen = ftell(f);
+ if (headerlen == -1) {
+ yasm__fatal(N_("could not get file position on output file"));
+ /*@notreached@*/
+ return;
+ }
+
+ /* Section data (to file) */
+ if (yasm_object_sections_traverse(object, &info,
+ rdf_objfmt_output_section_file))
+ return;
+
+ /* NULL section to end file */
+ memset(info.buf, 0, 10);
+ fwrite(info.buf, 10, 1, f);
+
+ /* Determine object length */
+ filelen = ftell(f);
+ if (filelen == -1) {
+ yasm__fatal(N_("could not get file position on output file"));
+ /*@notreached@*/
+ return;
+ }
+
+ /* Write file header */
+ if (fseek(f, 0, SEEK_SET) < 0) {
+ yasm__fatal(N_("could not seek on output file"));
+ /*@notreached@*/
+ return;
+ }
+
+ fwrite(RDF_MAGIC, strlen(RDF_MAGIC), 1, f);
+ localbuf = info.buf;
+ YASM_WRITE_32_L(localbuf, filelen-10); /* object size */
+ YASM_WRITE_32_L(localbuf, headerlen-14); /* header size */
+ fwrite(info.buf, 8, 1, f);
+
+ yasm_xfree(info.buf);
+}
+
+static void
+rdf_objfmt_destroy(yasm_objfmt *objfmt)
+{
+ yasm_objfmt_rdf *objfmt_rdf = (yasm_objfmt_rdf *)objfmt;
+ xdf_str *cur, *next;
+
+ cur = STAILQ_FIRST(&objfmt_rdf->module_names);
+ while (cur) {
+ next = STAILQ_NEXT(cur, link);
+ yasm_xfree(cur->str);
+ yasm_xfree(cur);
+ cur = next;
+ }
+
+ cur = STAILQ_FIRST(&objfmt_rdf->library_names);
+ while (cur) {
+ next = STAILQ_NEXT(cur, link);
+ yasm_xfree(cur->str);
+ yasm_xfree(cur);
+ cur = next;
+ }
+
+ yasm_xfree(objfmt);
+}
+
+static void
+rdf_objfmt_init_new_section(yasm_section *sect, unsigned long line)
+{
+ yasm_object *object = yasm_section_get_object(sect);
+ const char *sectname = yasm_section_get_name(sect);
+ yasm_objfmt_rdf *objfmt_rdf = (yasm_objfmt_rdf *)object->objfmt;
+ rdf_section_data *data;
+ yasm_symrec *sym;
+
+ data = yasm_xmalloc(sizeof(rdf_section_data));
+ data->scnum = objfmt_rdf->parse_scnum++;
+ data->type = 0;
+ data->reserved = 0;
+ data->size = 0;
+ data->raw_data = NULL;
+ yasm_section_add_data(sect, &rdf_section_data_cb, data);
+
+ sym = yasm_symtab_define_label(object->symtab, sectname,
+ yasm_section_bcs_first(sect), 1, line);
+ data->sym = sym;
+}
+
+static yasm_section *
+rdf_objfmt_add_default_section(yasm_object *object)
+{
+ yasm_section *retval;
+ rdf_section_data *rsd;
+ int isnew;
+
+ retval = yasm_object_get_general(object, ".text", 0, 1, 0, &isnew, 0);
+ if (isnew) {
+ rsd = yasm_section_get_data(retval, &rdf_section_data_cb);
+ rsd->type = RDF_SECT_CODE;
+ rsd->reserved = 0;
+ yasm_section_set_default(retval, 1);
+ }
+ return retval;
+}
+
+static int
+rdf_helper_set_type(void *obj, yasm_valparam *vp, unsigned long line,
+ void *d, uintptr_t newtype)
+{
+ unsigned int *type = (unsigned int *)d;
+ *type = newtype;
+ return 0;
+}
+
+struct rdf_section_switch_data {
+ /*@only@*/ /*@null@*/ yasm_intnum *reserved_intn;
+ unsigned int type;
+};
+
+static int
+rdf_helper_set_reserved(void *obj, yasm_valparam *vp, unsigned long line,
+ void *d)
+{
+ struct rdf_section_switch_data *data = (struct rdf_section_switch_data *)d;
+
+ if (!vp->val && vp->type == YASM_PARAM_EXPR)
+ return yasm_dir_helper_intn(obj, vp, line, &data->reserved_intn, 0);
+ else
+ return yasm_dir_helper_valparam_warn(obj, vp, line, d);
+}
+
+static /*@observer@*/ /*@null@*/ yasm_section *
+rdf_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
+ /*@unused@*/ /*@null@*/
+ yasm_valparamhead *objext_valparams,
+ unsigned long line)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ yasm_section *retval;
+ int isnew;
+ unsigned int reserved = 0;
+ int flags_override = 0;
+ const char *sectname;
+ rdf_section_data *rsd;
+
+ struct rdf_section_switch_data data;
+
+ static const yasm_dir_help help[] = {
+ { "bss", 0, rdf_helper_set_type,
+ offsetof(struct rdf_section_switch_data, type), RDF_SECT_BSS },
+ { "code", 0, rdf_helper_set_type,
+ offsetof(struct rdf_section_switch_data, type), RDF_SECT_CODE },
+ { "text", 0, rdf_helper_set_type,
+ offsetof(struct rdf_section_switch_data, type), RDF_SECT_CODE },
+ { "data", 0, rdf_helper_set_type,
+ offsetof(struct rdf_section_switch_data, type), RDF_SECT_DATA },
+ { "comment", 0, rdf_helper_set_type,
+ offsetof(struct rdf_section_switch_data, type), RDF_SECT_COMMENT },
+ { "lcomment", 0, rdf_helper_set_type,
+ offsetof(struct rdf_section_switch_data, type), RDF_SECT_LCOMMENT },
+ { "pcomment", 0, rdf_helper_set_type,
+ offsetof(struct rdf_section_switch_data, type), RDF_SECT_PCOMMENT },
+ { "symdebug", 0, rdf_helper_set_type,
+ offsetof(struct rdf_section_switch_data, type), RDF_SECT_SYMDEBUG },
+ { "linedebug", 0, rdf_helper_set_type,
+ offsetof(struct rdf_section_switch_data, type), RDF_SECT_LINEDEBUG },
+ { "reserved", 1, yasm_dir_helper_intn,
+ offsetof(struct rdf_section_switch_data, reserved_intn), 0 }
+ };
+
+ data.reserved_intn = NULL;
+ data.type = 0xffff;
+
+ vp = yasm_vps_first(valparams);
+ sectname = yasm_vp_string(vp);
+ if (!sectname)
+ return NULL;
+ vp = yasm_vps_next(vp);
+
+ if (strcmp(sectname, ".text") == 0)
+ data.type = RDF_SECT_CODE;
+ else if (strcmp(sectname, ".data") == 0)
+ data.type = RDF_SECT_DATA;
+ else if (strcmp(sectname, ".bss") == 0)
+ data.type = RDF_SECT_BSS;
+
+ flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help),
+ &data, rdf_helper_set_reserved);
+ if (flags_override < 0)
+ return NULL; /* error occurred */
+
+ if (data.type == 0xffff) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("new segment declared without type code"));
+ data.type = RDF_SECT_DATA;
+ }
+
+ if (data.reserved_intn) {
+ reserved = yasm_intnum_get_uint(data.reserved_intn);
+ yasm_intnum_destroy(data.reserved_intn);
+ }
+
+ retval = yasm_object_get_general(object, sectname, 0, 1,
+ data.type == RDF_SECT_BSS, &isnew, line);
+
+ rsd = yasm_section_get_data(retval, &rdf_section_data_cb);
+
+ if (isnew || yasm_section_is_default(retval)) {
+ yasm_section_set_default(retval, 0);
+ rsd->type = data.type;
+ rsd->reserved = reserved;
+ } else if (flags_override)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("section flags ignored on section redeclaration"));
+ return retval;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+rdf_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ return NULL;
+}
+
+static void
+rdf_section_data_destroy(void *data)
+{
+ rdf_section_data *rsd = (rdf_section_data *)data;
+ if (rsd->raw_data)
+ yasm_xfree(rsd->raw_data);
+ yasm_xfree(data);
+}
+
+static void
+rdf_section_data_print(void *data, FILE *f, int indent_level)
+{
+ rdf_section_data *rsd = (rdf_section_data *)data;
+
+ fprintf(f, "%*ssym=\n", indent_level, "");
+ yasm_symrec_print(rsd->sym, f, indent_level+1);
+ fprintf(f, "%*sscnum=%ld\n", indent_level, "", rsd->scnum);
+ fprintf(f, "%*stype=0x%x\n", indent_level, "", rsd->type);
+ fprintf(f, "%*sreserved=0x%x\n", indent_level, "", rsd->reserved);
+ fprintf(f, "%*ssize=%ld\n", indent_level, "", rsd->size);
+}
+
+static void
+rdf_symrec_data_destroy(void *data)
+{
+ yasm_xfree(data);
+}
+
+static void
+rdf_symrec_data_print(void *data, FILE *f, int indent_level)
+{
+ rdf_symrec_data *rsymd = (rdf_symrec_data *)data;
+
+ fprintf(f, "%*ssymtab segment=%u\n", indent_level, "", rsymd->segment);
+}
+
+static void
+rdf_objfmt_add_libmodule(yasm_object *object, char *name, int lib)
+{
+ yasm_objfmt_rdf *objfmt_rdf = (yasm_objfmt_rdf *)object->objfmt;
+ xdf_str *str;
+
+ /* Add to list */
+ str = yasm_xmalloc(sizeof(xdf_str));
+ str->str = name;
+ if (lib)
+ STAILQ_INSERT_TAIL(&objfmt_rdf->library_names, str, link);
+ else
+ STAILQ_INSERT_TAIL(&objfmt_rdf->module_names, str, link);
+
+ if (strlen(str->str) > MODLIB_NAME_MAX-1) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("name too long, truncating to %d bytes"),
+ MODLIB_NAME_MAX);
+ str->str[MODLIB_NAME_MAX-1] = '\0';
+ }
+}
+
+static void
+dir_library(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ rdf_objfmt_add_libmodule(object, yasm__xstrdup(yasm_vp_string(vp)), 1);
+}
+
+static void
+dir_module(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ rdf_objfmt_add_libmodule(object, yasm__xstrdup(yasm_vp_string(vp)), 0);
+}
+
+/* Define valid debug formats to use with this object format */
+static const char *rdf_objfmt_dbgfmt_keywords[] = {
+ "null",
+ NULL
+};
+
+static const yasm_directive rdf_objfmt_directives[] = {
+ { "library", "nasm", dir_library, YASM_DIR_ARG_REQUIRED },
+ { "module", "nasm", dir_module, YASM_DIR_ARG_REQUIRED },
+ { NULL, NULL, NULL, 0 }
+};
+
+static const char *rdf_nasm_stdmac[] = {
+ "%imacro library 1+.nolist",
+ "[library %1]",
+ "%endmacro",
+ "%imacro module 1+.nolist",
+ "[module %1]",
+ "%endmacro",
+ NULL
+};
+
+static const yasm_stdmac rdf_objfmt_stdmacs[] = {
+ { "nasm", "nasm", rdf_nasm_stdmac },
+ { NULL, NULL, NULL }
+};
+
+/* Define objfmt structure -- see objfmt.h for details */
+yasm_objfmt_module yasm_rdf_LTX_objfmt = {
+ "Relocatable Dynamic Object File Format (RDOFF) v2.0",
+ "rdf",
+ "rdf",
+ 32,
+ 0,
+ rdf_objfmt_dbgfmt_keywords,
+ "null",
+ rdf_objfmt_directives,
+ rdf_objfmt_stdmacs,
+ rdf_objfmt_create,
+ rdf_objfmt_output,
+ rdf_objfmt_destroy,
+ rdf_objfmt_add_default_section,
+ rdf_objfmt_init_new_section,
+ rdf_objfmt_section_switch,
+ rdf_objfmt_get_special_sym
+};
diff --git a/contrib/tools/yasm/modules/objfmts/xdf/xdf-objfmt.c b/contrib/tools/yasm/modules/objfmts/xdf/xdf-objfmt.c
new file mode 100644
index 0000000000..9ad0e60afa
--- /dev/null
+++ b/contrib/tools/yasm/modules/objfmts/xdf/xdf-objfmt.c
@@ -0,0 +1,842 @@
+/*
+ * Extended Dynamic Object format
+ *
+ * Copyright (C) 2004-2007 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 <util.h>
+
+#include <libyasm.h>
+
+
+#define REGULAR_OUTBUF_SIZE 1024
+
+#define XDF_MAGIC 0x87654322
+
+#define XDF_SYM_EXTERN 1
+#define XDF_SYM_GLOBAL 2
+#define XDF_SYM_EQU 4
+
+typedef struct xdf_reloc {
+ yasm_reloc reloc;
+ /*@null@*/ yasm_symrec *base; /* base symbol (for WRT) */
+ enum {
+ XDF_RELOC_REL = 1, /* relative to segment */
+ XDF_RELOC_WRT = 2, /* relative to symbol */
+ XDF_RELOC_RIP = 4, /* RIP-relative */
+ XDF_RELOC_SEG = 8 /* segment containing symbol */
+ } type; /* type of relocation */
+ enum {
+ XDF_RELOC_8 = 1,
+ XDF_RELOC_16 = 2,
+ XDF_RELOC_32 = 4,
+ XDF_RELOC_64 = 8
+ } size; /* size of relocation */
+ unsigned int shift; /* relocation shift (0,4,8,16,24,32) */
+} xdf_reloc;
+
+typedef struct xdf_section_data {
+ /*@dependent@*/ yasm_symrec *sym; /* symbol created for this section */
+ yasm_intnum *addr; /* starting memory address */
+ yasm_intnum *vaddr; /* starting virtual address */
+ long scnum; /* section number (0=first section) */
+ enum {
+ XDF_SECT_ABSOLUTE = 0x01,
+ XDF_SECT_FLAT = 0x02,
+ XDF_SECT_BSS = 0x04,
+ XDF_SECT_EQU = 0x08,
+ XDF_SECT_USE_16 = 0x10,
+ XDF_SECT_USE_32 = 0x20,
+ XDF_SECT_USE_64 = 0x40
+ } flags; /* section flags */
+ unsigned long scnptr; /* file ptr to raw data */
+ unsigned long size; /* size of raw data (section data) in bytes */
+ unsigned long relptr; /* file ptr to relocation */
+ unsigned long nreloc; /* number of relocation entries >64k -> error */
+} xdf_section_data;
+
+typedef struct xdf_symrec_data {
+ unsigned long index; /* assigned XDF symbol table index */
+} xdf_symrec_data;
+
+typedef struct yasm_objfmt_xdf {
+ yasm_objfmt_base objfmt; /* base structure */
+
+ long parse_scnum; /* sect numbering in parser */
+} yasm_objfmt_xdf;
+
+typedef struct xdf_objfmt_output_info {
+ yasm_object *object;
+ yasm_objfmt_xdf *objfmt_xdf;
+ yasm_errwarns *errwarns;
+ /*@dependent@*/ FILE *f;
+ /*@only@*/ unsigned char *buf;
+ yasm_section *sect;
+ /*@dependent@*/ xdf_section_data *xsd;
+
+ unsigned long indx; /* current symbol index */
+ int all_syms; /* outputting all symbols? */
+ unsigned long strtab_offset; /* current string table offset */
+} xdf_objfmt_output_info;
+
+static void xdf_section_data_destroy(/*@only@*/ void *d);
+static void xdf_section_data_print(void *data, FILE *f, int indent_level);
+
+static const yasm_assoc_data_callback xdf_section_data_cb = {
+ xdf_section_data_destroy,
+ xdf_section_data_print
+};
+
+static void xdf_symrec_data_destroy(/*@only@*/ void *d);
+static void xdf_symrec_data_print(void *data, FILE *f, int indent_level);
+
+static const yasm_assoc_data_callback xdf_symrec_data_cb = {
+ xdf_symrec_data_destroy,
+ xdf_symrec_data_print
+};
+
+yasm_objfmt_module yasm_xdf_LTX_objfmt;
+
+
+static yasm_objfmt *
+xdf_objfmt_create(yasm_object *object)
+{
+ yasm_objfmt_xdf *objfmt_xdf = yasm_xmalloc(sizeof(yasm_objfmt_xdf));
+
+ /* Only support x86 arch */
+ if (yasm__strcasecmp(yasm_arch_keyword(object->arch), "x86") != 0) {
+ yasm_xfree(objfmt_xdf);
+ return NULL;
+ }
+
+ /* Support x86 and amd64 machines of x86 arch */
+ if (yasm__strcasecmp(yasm_arch_get_machine(object->arch), "x86") &&
+ yasm__strcasecmp(yasm_arch_get_machine(object->arch), "amd64")) {
+ yasm_xfree(objfmt_xdf);
+ return NULL;
+ }
+
+ objfmt_xdf->parse_scnum = 0; /* section numbering starts at 0 */
+
+ objfmt_xdf->objfmt.module = &yasm_xdf_LTX_objfmt;
+
+ return (yasm_objfmt *)objfmt_xdf;
+}
+
+static int
+xdf_objfmt_output_value(yasm_value *value, unsigned char *buf,
+ unsigned int destsize, unsigned long offset,
+ yasm_bytecode *bc, int warn, /*@null@*/ void *d)
+{
+ /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
+ unsigned long intn_minus;
+ int retval;
+ unsigned int valsize = value->size;
+
+ assert(info != NULL);
+
+ if (value->abs)
+ value->abs = yasm_expr_simplify(value->abs, 1);
+
+ /* Try to output constant and PC-relative section-local first.
+ * Note this does NOT output any value with a SEG, WRT, external,
+ * cross-section, or non-PC-relative reference (those are handled below).
+ */
+ switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
+ info->object->arch)) {
+ case -1:
+ return 1;
+ case 0:
+ break;
+ default:
+ return 0;
+ }
+
+ if (value->section_rel) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("xdf: relocation too complex"));
+ return 1;
+ }
+
+ intn_minus = 0;
+ if (value->rel) {
+ xdf_reloc *reloc;
+
+ reloc = yasm_xmalloc(sizeof(xdf_reloc));
+ reloc->reloc.addr = yasm_intnum_create_uint(bc->offset + offset);
+ reloc->reloc.sym = value->rel;
+ reloc->base = NULL;
+ reloc->size = valsize/8;
+ reloc->shift = value->rshift;
+
+ if (value->seg_of)
+ reloc->type = XDF_RELOC_SEG;
+ else if (value->wrt) {
+ reloc->base = value->wrt;
+ reloc->type = XDF_RELOC_WRT;
+ } else if (value->curpos_rel) {
+ reloc->type = XDF_RELOC_RIP;
+ /* Adjust to start of section, so subtract out the bytecode
+ * offset.
+ */
+ intn_minus = bc->offset;
+ } else
+ reloc->type = XDF_RELOC_REL;
+ info->xsd->nreloc++;
+ yasm_section_add_reloc(info->sect, (yasm_reloc *)reloc, yasm_xfree);
+ }
+
+ if (intn_minus > 0) {
+ intn = yasm_intnum_create_uint(intn_minus);
+ yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
+ } else
+ intn = yasm_intnum_create_uint(0);
+
+ if (value->abs) {
+ yasm_intnum *intn2 = yasm_expr_get_intnum(&value->abs, 0);
+ if (!intn2) {
+ yasm_error_set(YASM_ERROR_TOO_COMPLEX,
+ N_("xdf: relocation too complex"));
+ yasm_intnum_destroy(intn);
+ return 1;
+ }
+ yasm_intnum_calc(intn, YASM_EXPR_ADD, intn2);
+ }
+
+ retval = yasm_arch_intnum_tobytes(info->object->arch, intn, buf, destsize,
+ valsize, 0, bc, warn);
+ yasm_intnum_destroy(intn);
+ return retval;
+}
+
+static int
+xdf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
+{
+ /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d;
+ /*@null@*/ /*@only@*/ unsigned char *bigbuf;
+ unsigned long size = REGULAR_OUTBUF_SIZE;
+ int gap;
+
+ assert(info != NULL);
+
+ bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &gap, info,
+ xdf_objfmt_output_value, NULL);
+
+ /* Don't bother doing anything else if size ended up being 0. */
+ if (size == 0) {
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+ return 0;
+ }
+
+ info->xsd->size += size;
+
+ /* Warn that gaps are converted to 0 and write out the 0's. */
+ if (gap) {
+ unsigned long left;
+ yasm_warn_set(YASM_WARN_UNINIT_CONTENTS,
+ N_("uninitialized space: zeroing"));
+ /* Write out in chunks */
+ memset(info->buf, 0, REGULAR_OUTBUF_SIZE);
+ left = size;
+ while (left > REGULAR_OUTBUF_SIZE) {
+ fwrite(info->buf, REGULAR_OUTBUF_SIZE, 1, info->f);
+ left -= REGULAR_OUTBUF_SIZE;
+ }
+ fwrite(info->buf, left, 1, info->f);
+ } else {
+ /* Output buf (or bigbuf if non-NULL) to file */
+ fwrite(bigbuf ? bigbuf : info->buf, (size_t)size, 1, info->f);
+ }
+
+ /* If bigbuf was allocated, free it */
+ if (bigbuf)
+ yasm_xfree(bigbuf);
+
+ return 0;
+}
+
+static int
+xdf_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ xdf_section_data *xsd;
+ long pos;
+ xdf_reloc *reloc;
+
+ assert(info != NULL);
+ xsd = yasm_section_get_data(sect, &xdf_section_data_cb);
+ assert(xsd != NULL);
+
+ if (xsd->flags & XDF_SECT_BSS) {
+ /* Don't output BSS sections.
+ * TODO: Check for non-reserve bytecodes?
+ */
+ pos = 0; /* position = 0 because it's not in the file */
+ xsd->size = yasm_bc_next_offset(yasm_section_bcs_last(sect));
+ } else {
+ pos = ftell(info->f);
+ if (pos == -1) {
+ yasm__fatal(N_("could not get file position on output file"));
+ /*@notreached@*/
+ return 1;
+ }
+
+ info->sect = sect;
+ info->xsd = xsd;
+ yasm_section_bcs_traverse(sect, info->errwarns, info,
+ xdf_objfmt_output_bytecode);
+
+ /* Sanity check final section size */
+ if (xsd->size != yasm_bc_next_offset(yasm_section_bcs_last(sect)))
+ yasm_internal_error(
+ N_("xdf: section computed size did not match actual size"));
+ }
+
+ /* Empty? Go on to next section */
+ if (xsd->size == 0)
+ return 0;
+
+ xsd->scnptr = (unsigned long)pos;
+
+ /* No relocations to output? Go on to next section */
+ if (xsd->nreloc == 0)
+ return 0;
+
+ pos = ftell(info->f);
+ if (pos == -1) {
+ yasm__fatal(N_("could not get file position on output file"));
+ /*@notreached@*/
+ return 1;
+ }
+ xsd->relptr = (unsigned long)pos;
+
+ reloc = (xdf_reloc *)yasm_section_relocs_first(sect);
+ while (reloc) {
+ unsigned char *localbuf = info->buf;
+ /*@null@*/ xdf_symrec_data *xsymd;
+
+ xsymd = yasm_symrec_get_data(reloc->reloc.sym, &xdf_symrec_data_cb);
+ if (!xsymd)
+ yasm_internal_error(
+ N_("xdf: no symbol data for relocated symbol"));
+
+ yasm_intnum_get_sized(reloc->reloc.addr, localbuf, 4, 32, 0, 0, 0);
+ localbuf += 4; /* address of relocation */
+ YASM_WRITE_32_L(localbuf, xsymd->index); /* relocated symbol */
+ if (reloc->base) {
+ xsymd = yasm_symrec_get_data(reloc->base, &xdf_symrec_data_cb);
+ if (!xsymd)
+ yasm_internal_error(
+ N_("xdf: no symbol data for relocated base symbol"));
+ YASM_WRITE_32_L(localbuf, xsymd->index); /* base symbol */
+ } else {
+ if (reloc->type == XDF_RELOC_WRT)
+ yasm_internal_error(
+ N_("xdf: no base symbol for WRT relocation"));
+ YASM_WRITE_32_L(localbuf, 0); /* no base symbol */
+ }
+ YASM_WRITE_8(localbuf, reloc->type); /* type of relocation */
+ YASM_WRITE_8(localbuf, reloc->size); /* size of relocation */
+ YASM_WRITE_8(localbuf, reloc->shift); /* relocation shift */
+ YASM_WRITE_8(localbuf, 0); /* flags */
+ fwrite(info->buf, 16, 1, info->f);
+
+ reloc = (xdf_reloc *)yasm_section_reloc_next((yasm_reloc *)reloc);
+ }
+
+ return 0;
+}
+
+static int
+xdf_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d)
+{
+ /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d;
+ /*@dependent@*/ /*@null@*/ xdf_section_data *xsd;
+ /*@null@*/ xdf_symrec_data *xsymd;
+ unsigned char *localbuf;
+
+ assert(info != NULL);
+ xsd = yasm_section_get_data(sect, &xdf_section_data_cb);
+ assert(xsd != NULL);
+
+ localbuf = info->buf;
+ xsymd = yasm_symrec_get_data(xsd->sym, &xdf_symrec_data_cb);
+ assert(xsymd != NULL);
+
+ YASM_WRITE_32_L(localbuf, xsymd->index); /* section name symbol */
+ if (xsd->addr) {
+ yasm_intnum_get_sized(xsd->addr, localbuf, 8, 64, 0, 0, 0);
+ localbuf += 8; /* physical address */
+ } else {
+ YASM_WRITE_32_L(localbuf, 0);
+ YASM_WRITE_32_L(localbuf, 0);
+ }
+ if (xsd->vaddr) {
+ yasm_intnum_get_sized(xsd->vaddr, localbuf, 8, 64, 0, 0, 0);
+ localbuf += 8; /* virtual address */
+ } else if (xsd->addr) {
+ yasm_intnum_get_sized(xsd->addr, localbuf, 8, 64, 0, 0, 0);
+ localbuf += 8; /* VA=PA */
+ } else {
+ YASM_WRITE_32_L(localbuf, 0);
+ YASM_WRITE_32_L(localbuf, 0);
+ }
+ YASM_WRITE_16_L(localbuf, yasm_section_get_align(sect)); /* alignment */
+ YASM_WRITE_16_L(localbuf, xsd->flags); /* flags */
+ YASM_WRITE_32_L(localbuf, xsd->scnptr); /* file ptr to data */
+ YASM_WRITE_32_L(localbuf, xsd->size); /* section size */
+ YASM_WRITE_32_L(localbuf, xsd->relptr); /* file ptr to relocs */
+ YASM_WRITE_32_L(localbuf, xsd->nreloc); /* num of relocation entries */
+ fwrite(info->buf, 40, 1, info->f);
+
+ return 0;
+}
+
+static int
+xdf_objfmt_count_sym(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d;
+ yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+ assert(info != NULL);
+ if (vis & YASM_SYM_COMMON) {
+ yasm_error_set(YASM_ERROR_GENERAL,
+ N_("XDF object format does not support common variables"));
+ yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym));
+ return 0;
+ }
+ if (info->all_syms ||
+ (vis != YASM_SYM_LOCAL && !(vis & YASM_SYM_DLOCAL))) {
+ /* Save index in symrec data */
+ xdf_symrec_data *sym_data = yasm_xmalloc(sizeof(xdf_symrec_data));
+ sym_data->index = info->indx;
+ yasm_symrec_add_data(sym, &xdf_symrec_data_cb, sym_data);
+
+ info->indx++;
+ }
+ return 0;
+}
+
+static int
+xdf_objfmt_output_sym(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d;
+ yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+
+ assert(info != NULL);
+
+ if (info->all_syms || vis != YASM_SYM_LOCAL) {
+ /*@only@*/ char *name = yasm_symrec_get_global_name(sym, info->object);
+ const yasm_expr *equ_val;
+ const yasm_intnum *intn;
+ size_t len = strlen(name);
+ unsigned long value = 0;
+ long scnum = -3; /* -3 = debugging symbol */
+ /*@dependent@*/ /*@null@*/ yasm_section *sect;
+ /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
+ unsigned long flags = 0;
+ unsigned char *localbuf;
+
+ if (vis & YASM_SYM_GLOBAL)
+ flags = XDF_SYM_GLOBAL;
+
+ /* Look at symrec for value/scnum/etc. */
+ if (yasm_symrec_get_label(sym, &precbc)) {
+ if (precbc)
+ sect = yasm_bc_get_section(precbc);
+ else
+ sect = NULL;
+ /* it's a label: get value and offset.
+ * If there is not a section, leave as debugging symbol.
+ */
+ if (sect) {
+ /*@dependent@*/ /*@null@*/ xdf_section_data *csectd;
+ csectd = yasm_section_get_data(sect, &xdf_section_data_cb);
+ if (csectd)
+ scnum = csectd->scnum;
+ else
+ yasm_internal_error(N_("didn't understand section"));
+ if (precbc)
+ value += yasm_bc_next_offset(precbc);
+ }
+ } else if ((equ_val = yasm_symrec_get_equ(sym))) {
+ yasm_expr *equ_val_copy = yasm_expr_copy(equ_val);
+ intn = yasm_expr_get_intnum(&equ_val_copy, 1);
+ if (!intn) {
+ if (vis & YASM_SYM_GLOBAL) {
+ yasm_error_set(YASM_ERROR_NOT_CONSTANT,
+ N_("global EQU value not an integer expression"));
+ yasm_errwarn_propagate(info->errwarns, equ_val->line);
+ }
+ } else
+ value = yasm_intnum_get_uint(intn);
+ yasm_expr_destroy(equ_val_copy);
+
+ flags |= XDF_SYM_EQU;
+ scnum = -2; /* -2 = absolute symbol */
+ } else {
+ if (vis & YASM_SYM_EXTERN) {
+ flags = XDF_SYM_EXTERN;
+ scnum = -1;
+ }
+ }
+
+ localbuf = info->buf;
+ YASM_WRITE_32_L(localbuf, scnum); /* section number */
+ YASM_WRITE_32_L(localbuf, value); /* value */
+ YASM_WRITE_32_L(localbuf, info->strtab_offset);
+ info->strtab_offset += (unsigned long)(len+1);
+ YASM_WRITE_32_L(localbuf, flags); /* flags */
+ fwrite(info->buf, 16, 1, info->f);
+ yasm_xfree(name);
+ }
+ return 0;
+}
+
+static int
+xdf_objfmt_output_str(yasm_symrec *sym, /*@null@*/ void *d)
+{
+ /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d;
+ yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
+
+ assert(info != NULL);
+
+ if (info->all_syms || vis != YASM_SYM_LOCAL) {
+ /*@only@*/ char *name = yasm_symrec_get_global_name(sym, info->object);
+ size_t len = strlen(name);
+ fwrite(name, len+1, 1, info->f);
+ yasm_xfree(name);
+ }
+ return 0;
+}
+
+static void
+xdf_objfmt_output(yasm_object *object, FILE *f, int all_syms,
+ yasm_errwarns *errwarns)
+{
+ yasm_objfmt_xdf *objfmt_xdf = (yasm_objfmt_xdf *)object->objfmt;
+ xdf_objfmt_output_info info;
+ unsigned char *localbuf;
+ unsigned long symtab_count = 0;
+
+ info.object = object;
+ info.objfmt_xdf = objfmt_xdf;
+ info.errwarns = errwarns;
+ info.f = f;
+ info.buf = yasm_xmalloc(REGULAR_OUTBUF_SIZE);
+
+ /* Allocate space for headers by seeking forward */
+ if (fseek(f, (long)(16+40*(objfmt_xdf->parse_scnum)), SEEK_SET) < 0) {
+ yasm__fatal(N_("could not seek on output file"));
+ /*@notreached@*/
+ return;
+ }
+
+ /* Get number of symbols */
+ info.indx = 0;
+ info.all_syms = 1; /* force all syms into symbol table */
+ yasm_symtab_traverse(object->symtab, &info, xdf_objfmt_count_sym);
+ symtab_count = info.indx;
+
+ /* Get file offset of start of string table */
+ info.strtab_offset = 16+40*(objfmt_xdf->parse_scnum)+16*symtab_count;
+
+ /* Output symbol table */
+ yasm_symtab_traverse(object->symtab, &info, xdf_objfmt_output_sym);
+
+ /* Output string table */
+ yasm_symtab_traverse(object->symtab, &info, xdf_objfmt_output_str);
+
+ /* Section data/relocs */
+ if (yasm_object_sections_traverse(object, &info,
+ xdf_objfmt_output_section))
+ return;
+
+ /* Write headers */
+ if (fseek(f, 0, SEEK_SET) < 0) {
+ yasm__fatal(N_("could not seek on output file"));
+ /*@notreached@*/
+ return;
+ }
+
+ localbuf = info.buf;
+ YASM_WRITE_32_L(localbuf, XDF_MAGIC); /* magic number */
+ YASM_WRITE_32_L(localbuf, objfmt_xdf->parse_scnum); /* number of sects */
+ YASM_WRITE_32_L(localbuf, symtab_count); /* number of symtabs */
+ /* size of sect headers + symbol table + strings */
+ YASM_WRITE_32_L(localbuf, info.strtab_offset-16);
+ fwrite(info.buf, 16, 1, f);
+
+ yasm_object_sections_traverse(object, &info, xdf_objfmt_output_secthead);
+
+ yasm_xfree(info.buf);
+}
+
+static void
+xdf_objfmt_destroy(yasm_objfmt *objfmt)
+{
+ yasm_xfree(objfmt);
+}
+
+static void
+xdf_objfmt_init_new_section(yasm_section *sect, unsigned long line)
+{
+ yasm_object *object = yasm_section_get_object(sect);
+ const char *sectname = yasm_section_get_name(sect);
+ yasm_objfmt_xdf *objfmt_xdf = (yasm_objfmt_xdf *)object->objfmt;
+ xdf_section_data *data;
+ yasm_symrec *sym;
+
+ data = yasm_xmalloc(sizeof(xdf_section_data));
+ data->scnum = objfmt_xdf->parse_scnum++;
+ data->flags = 0;
+ data->addr = NULL;
+ data->vaddr = NULL;
+ data->scnptr = 0;
+ data->size = 0;
+ data->relptr = 0;
+ data->nreloc = 0;
+ yasm_section_add_data(sect, &xdf_section_data_cb, data);
+
+ sym = yasm_symtab_define_label(object->symtab, sectname,
+ yasm_section_bcs_first(sect), 1, line);
+ data->sym = sym;
+}
+
+static yasm_section *
+xdf_objfmt_add_default_section(yasm_object *object)
+{
+ yasm_section *retval;
+ int isnew;
+
+ retval = yasm_object_get_general(object, ".text", 0, 1, 0, &isnew, 0);
+ if (isnew)
+ yasm_section_set_default(retval, 1);
+ return retval;
+}
+
+static int
+xdf_helper_use(void *obj, yasm_valparam *vp, unsigned long line, void *d,
+ uintptr_t bits)
+{
+ yasm_object *object = (yasm_object *)obj;
+ unsigned long *flags = (unsigned long *)d;
+ *flags &= ~(XDF_SECT_USE_16|XDF_SECT_USE_32|XDF_SECT_USE_64);
+ switch (bits) {
+ case 16: *flags |= XDF_SECT_USE_16; break;
+ case 32: *flags |= XDF_SECT_USE_32; break;
+ case 64: *flags |= XDF_SECT_USE_64; break;
+ };
+ yasm_arch_set_var(object->arch, "mode_bits", bits);
+ return 0;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_section *
+xdf_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
+ /*@unused@*/ /*@null@*/
+ yasm_valparamhead *objext_valparams,
+ unsigned long line)
+{
+ yasm_valparam *vp;
+ yasm_section *retval;
+ int isnew;
+ int flags_override = 0;
+ const char *sectname;
+ int resonly = 0;
+ xdf_section_data *xsd;
+ unsigned long align = 0;
+
+ struct xdf_section_switch_data {
+ /*@only@*/ /*@null@*/ yasm_intnum *absaddr;
+ /*@only@*/ /*@null@*/ yasm_intnum *vaddr;
+ /*@only@*/ /*@null@*/ yasm_intnum *align_intn;
+ unsigned long flags;
+ } data;
+
+ static const yasm_dir_help help[] = {
+ { "use16", 0, xdf_helper_use,
+ offsetof(struct xdf_section_switch_data, flags), 16 },
+ { "use32", 0, xdf_helper_use,
+ offsetof(struct xdf_section_switch_data, flags), 32 },
+ { "use64", 0, xdf_helper_use,
+ offsetof(struct xdf_section_switch_data, flags), 64 },
+ { "bss", 0, yasm_dir_helper_flag_or,
+ offsetof(struct xdf_section_switch_data, flags), XDF_SECT_BSS },
+ { "flat", 0, yasm_dir_helper_flag_or,
+ offsetof(struct xdf_section_switch_data, flags), XDF_SECT_FLAT },
+ { "absolute", 1, yasm_dir_helper_intn,
+ offsetof(struct xdf_section_switch_data, absaddr), 0 },
+ { "virtual", 1, yasm_dir_helper_intn,
+ offsetof(struct xdf_section_switch_data, vaddr), 0 },
+ { "align", 1, yasm_dir_helper_intn,
+ offsetof(struct xdf_section_switch_data, align_intn), 0 }
+ };
+
+ data.absaddr = NULL;
+ data.vaddr = NULL;
+ data.align_intn = NULL;
+ data.flags = 0;
+
+ vp = yasm_vps_first(valparams);
+ sectname = yasm_vp_string(vp);
+ if (!sectname)
+ return NULL;
+ vp = yasm_vps_next(vp);
+
+ flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help),
+ &data, yasm_dir_helper_valparam_warn);
+ if (flags_override < 0)
+ return NULL; /* error occurred */
+
+ if (data.absaddr)
+ data.flags |= XDF_SECT_ABSOLUTE;
+ if (data.align_intn) {
+ align = yasm_intnum_get_uint(data.align_intn);
+ yasm_intnum_destroy(data.align_intn);
+
+ /* Alignments must be a power of two. */
+ if (!is_exp2(align)) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("argument to `%s' is not a power of two"),
+ "align");
+ if (data.vaddr)
+ yasm_intnum_destroy(data.vaddr);
+ if (data.absaddr)
+ yasm_intnum_destroy(data.absaddr);
+ return NULL;
+ }
+
+ /* Check to see if alignment is supported size */
+ if (align > 4096) {
+ yasm_error_set(YASM_ERROR_VALUE,
+ N_("XDF does not support alignments > 4096"));
+ if (data.vaddr)
+ yasm_intnum_destroy(data.vaddr);
+ if (data.absaddr)
+ yasm_intnum_destroy(data.absaddr);
+ return NULL;
+ }
+ }
+
+ retval = yasm_object_get_general(object, sectname, align, 1, resonly,
+ &isnew, line);
+
+ xsd = yasm_section_get_data(retval, &xdf_section_data_cb);
+
+ if (isnew || yasm_section_is_default(retval)) {
+ yasm_section_set_default(retval, 0);
+ xsd->flags = data.flags;
+ if (data.absaddr) {
+ if (xsd->addr)
+ yasm_intnum_destroy(xsd->addr);
+ xsd->addr = data.absaddr;
+ }
+ if (data.vaddr) {
+ if (xsd->vaddr)
+ yasm_intnum_destroy(xsd->vaddr);
+ xsd->vaddr = data.vaddr;
+ }
+ yasm_section_set_align(retval, align, line);
+ } else if (flags_override)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("section flags ignored on section redeclaration"));
+ return retval;
+}
+
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+xdf_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ return NULL;
+}
+
+static void
+xdf_section_data_destroy(void *data)
+{
+ xdf_section_data *xsd = (xdf_section_data *)data;
+ if (xsd->addr)
+ yasm_intnum_destroy(xsd->addr);
+ if (xsd->vaddr)
+ yasm_intnum_destroy(xsd->vaddr);
+ yasm_xfree(data);
+}
+
+static void
+xdf_section_data_print(void *data, FILE *f, int indent_level)
+{
+ xdf_section_data *xsd = (xdf_section_data *)data;
+
+ fprintf(f, "%*ssym=\n", indent_level, "");
+ yasm_symrec_print(xsd->sym, f, indent_level+1);
+ fprintf(f, "%*sscnum=%ld\n", indent_level, "", xsd->scnum);
+ fprintf(f, "%*sflags=0x%x\n", indent_level, "", xsd->flags);
+ fprintf(f, "%*saddr=", indent_level, "");
+ yasm_intnum_print(xsd->addr, f);
+ fprintf(f, "%*svaddr=", indent_level, "");
+ yasm_intnum_print(xsd->vaddr, f);
+ fprintf(f, "%*sscnptr=0x%lx\n", indent_level, "", xsd->scnptr);
+ fprintf(f, "%*ssize=%ld\n", indent_level, "", xsd->size);
+ fprintf(f, "%*srelptr=0x%lx\n", indent_level, "", xsd->relptr);
+ fprintf(f, "%*snreloc=%ld\n", indent_level, "", xsd->nreloc);
+}
+
+static void
+xdf_symrec_data_destroy(void *data)
+{
+ yasm_xfree(data);
+}
+
+static void
+xdf_symrec_data_print(void *data, FILE *f, int indent_level)
+{
+ xdf_symrec_data *xsd = (xdf_symrec_data *)data;
+
+ fprintf(f, "%*ssymtab index=%lu\n", indent_level, "", xsd->index);
+}
+
+/* Define valid debug formats to use with this object format */
+static const char *xdf_objfmt_dbgfmt_keywords[] = {
+ "null",
+ NULL
+};
+
+/* Define objfmt structure -- see objfmt.h for details */
+yasm_objfmt_module yasm_xdf_LTX_objfmt = {
+ "Extended Dynamic Object",
+ "xdf",
+ "xdf",
+ 32,
+ 0,
+ xdf_objfmt_dbgfmt_keywords,
+ "null",
+ NULL, /* no directives */
+ NULL, /* no standard macros */
+ xdf_objfmt_create,
+ xdf_objfmt_output,
+ xdf_objfmt_destroy,
+ xdf_objfmt_add_default_section,
+ xdf_objfmt_init_new_section,
+ xdf_objfmt_section_switch,
+ xdf_objfmt_get_special_sym
+};
diff --git a/contrib/tools/yasm/modules/parsers/gas/gas-parse-intel.c b/contrib/tools/yasm/modules/parsers/gas/gas-parse-intel.c
new file mode 100644
index 0000000000..9d412fc7d3
--- /dev/null
+++ b/contrib/tools/yasm/modules/parsers/gas/gas-parse-intel.c
@@ -0,0 +1,90 @@
+/*
+ * GAS-compatible parser Intel syntax support
+ *
+ * Copyright (C) 2010 Alexei Svitkine
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of other contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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 <util.h>
+
+#include <libyasm.h>
+
+#include "modules/parsers/gas/gas-parser.h"
+#include "modules/parsers/nasm/nasm-parser-struct.h"
+
+extern yasm_bytecode *gas_intel_syntax_parse_instr(yasm_parser_nasm *parser_nasm, unsigned char *instr);
+
+#define SET_FIELDS(to, from) \
+ (to)->object = (from)->object; \
+ (to)->locallabel_base = (from)->locallabel_base; \
+ (to)->locallabel_base_len = (from)->locallabel_base_len; \
+ (to)->preproc = (from)->preproc; \
+ (to)->errwarns = (from)->errwarns; \
+ (to)->linemap = (from)->linemap; \
+ (to)->prev_bc = (from)->prev_bc;
+
+yasm_bytecode *parse_instr_intel(yasm_parser_gas *parser_gas)
+{
+ char *stok, *slim;
+ unsigned char *line;
+ size_t length;
+
+ yasm_parser_nasm parser_nasm;
+ yasm_bytecode *bc;
+
+ memset(&parser_nasm, 0, sizeof(parser_nasm));
+
+ yasm_arch_set_var(parser_gas->object->arch, "gas_intel_mode", 1);
+ SET_FIELDS(&parser_nasm, parser_gas);
+ parser_nasm.masm = 1;
+
+ stok = (char *) parser_gas->s.tok;
+ slim = (char *) parser_gas->s.lim;
+ length = 0;
+ while (&stok[length] < slim && stok[length] != '\n') {
+ length++;
+ }
+
+ if (&stok[length] == slim && parser_gas->line) {
+ line = yasm_xmalloc(length + parser_gas->lineleft + 1);
+ memcpy(line, parser_gas->s.tok, length);
+ memcpy(line + length, parser_gas->linepos, parser_gas->lineleft);
+ length += parser_gas->lineleft;
+ if (line[length - 1] == '\n') length--;
+ } else {
+ line = yasm_xmalloc(length + 1);
+ memcpy(line, parser_gas->s.tok, length);
+ }
+ line[length] = '\0';
+
+ bc = gas_intel_syntax_parse_instr(&parser_nasm, line);
+
+ SET_FIELDS(parser_gas, &parser_nasm);
+ yasm_arch_set_var(parser_gas->object->arch, "gas_intel_mode", 0);
+
+ yasm_xfree(line);
+
+ return bc;
+}
diff --git a/contrib/tools/yasm/modules/parsers/gas/gas-parse.c b/contrib/tools/yasm/modules/parsers/gas/gas-parse.c
new file mode 100644
index 0000000000..14c86a70f4
--- /dev/null
+++ b/contrib/tools/yasm/modules/parsers/gas/gas-parse.c
@@ -0,0 +1,1766 @@
+/*
+ * GAS-compatible parser
+ *
+ * Copyright (C) 2005-2007 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.
+ * 3. Neither the name of the author nor the names of other contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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 <util.h>
+
+#include <libyasm.h>
+
+#include <ctype.h>
+#include <limits.h>
+#include <math.h>
+
+#include "modules/parsers/gas/gas-parser.h"
+
+typedef struct dir_lookup {
+ const char *name;
+ yasm_bytecode * (*handler) (yasm_parser_gas *, unsigned int);
+ unsigned int param;
+ enum gas_parser_state newstate;
+} dir_lookup;
+
+static void cpp_line_marker(yasm_parser_gas *parser_gas);
+static void nasm_line_marker(yasm_parser_gas *parser_gas);
+static yasm_bytecode *parse_instr(yasm_parser_gas *parser_gas);
+static int parse_dirvals(yasm_parser_gas *parser_gas, yasm_valparamhead *vps);
+static int parse_datavals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs);
+static int parse_strvals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs);
+static yasm_effaddr *parse_memaddr(yasm_parser_gas *parser_gas);
+static yasm_insn_operand *parse_operand(yasm_parser_gas *parser_gas);
+static yasm_expr *parse_expr(yasm_parser_gas *parser_gas);
+static yasm_expr *parse_expr0(yasm_parser_gas *parser_gas);
+static yasm_expr *parse_expr1(yasm_parser_gas *parser_gas);
+static yasm_expr *parse_expr2(yasm_parser_gas *parser_gas);
+
+static void define_label(yasm_parser_gas *parser_gas, char *name, int local);
+static void define_lcomm(yasm_parser_gas *parser_gas, /*@only@*/ char *name,
+ yasm_expr *size, /*@null@*/ yasm_expr *align);
+static yasm_section *gas_get_section
+ (yasm_parser_gas *parser_gas, /*@only@*/ char *name, /*@null@*/ char *flags,
+ /*@null@*/ char *type, /*@null@*/ yasm_valparamhead *objext_valparams,
+ int builtin);
+static void gas_switch_section
+ (yasm_parser_gas *parser_gas, /*@only@*/ const char *name,
+ /*@null@*/ char *flags, /*@null@*/ char *type,
+ /*@null@*/ yasm_valparamhead *objext_valparams, int builtin);
+static yasm_bytecode *gas_parser_align
+ (yasm_parser_gas *parser_gas, yasm_section *sect, yasm_expr *boundval,
+ /*@null@*/ yasm_expr *fillval, /*@null@*/ yasm_expr *maxskipval,
+ int power2);
+static yasm_bytecode *gas_parser_dir_fill
+ (yasm_parser_gas *parser_gas, /*@only@*/ yasm_expr *repeat,
+ /*@only@*/ /*@null@*/ yasm_expr *size,
+ /*@only@*/ /*@null@*/ yasm_expr *value);
+
+#define is_eol_tok(tok) ((tok) == '\n' || (tok) == ';' || (tok) == 0)
+#define is_eol() is_eol_tok(curtok)
+
+#define get_next_token() (curtok = gas_parser_lex(&curval, parser_gas))
+
+static void
+get_peek_token(yasm_parser_gas *parser_gas)
+{
+ char savech = parser_gas->tokch;
+ if (parser_gas->peek_token != NONE)
+ yasm_internal_error(N_("can only have one token of lookahead"));
+ parser_gas->peek_token =
+ gas_parser_lex(&parser_gas->peek_tokval, parser_gas);
+ parser_gas->peek_tokch = parser_gas->tokch;
+ parser_gas->tokch = savech;
+}
+
+static void
+destroy_curtok_(yasm_parser_gas *parser_gas)
+{
+ if (curtok < 256)
+ ;
+ else switch ((enum tokentype)curtok) {
+ case INTNUM:
+ yasm_intnum_destroy(curval.intn);
+ break;
+ case FLTNUM:
+ yasm_floatnum_destroy(curval.flt);
+ break;
+ case ID:
+ case LABEL:
+ case STRING:
+ yasm_xfree(curval.str.contents);
+ break;
+ default:
+ break;
+ }
+ curtok = NONE; /* sanity */
+}
+#define destroy_curtok() destroy_curtok_(parser_gas)
+
+/* Eat all remaining tokens to EOL, discarding all of them. If there's any
+ * intervening tokens, generates an error (junk at end of line).
+ */
+static void
+demand_eol_(yasm_parser_gas *parser_gas)
+{
+ if (is_eol())
+ return;
+
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("junk at end of line, first unrecognized character is `%c'"),
+ parser_gas->tokch);
+
+ do {
+ destroy_curtok();
+ get_next_token();
+ } while (!is_eol());
+}
+#define demand_eol() demand_eol_(parser_gas)
+
+static int
+expect_(yasm_parser_gas *parser_gas, int token)
+{
+ static char strch[] = "` '";
+ const char *str;
+
+ if (curtok == token)
+ return 1;
+
+ switch (token) {
+ case INTNUM: str = "integer"; break;
+ case FLTNUM: str = "floating point value"; break;
+ case STRING: str = "string"; break;
+ case REG: str = "register"; break;
+ case REGGROUP: str = "register group"; break;
+ case SEGREG: str = "segment register"; break;
+ case TARGETMOD: str = "target modifier"; break;
+ case LEFT_OP: str = "<<"; break;
+ case RIGHT_OP: str = ">>"; break;
+ case ID: str = "identifier"; break;
+ case LABEL: str = "label"; break;
+ default:
+ strch[1] = token;
+ str = strch;
+ break;
+ }
+ yasm_error_set(YASM_ERROR_PARSE, "expected %s", str);
+ destroy_curtok();
+ return 0;
+}
+#define expect(token) expect_(parser_gas, token)
+
+static yasm_bytecode *
+parse_line(yasm_parser_gas *parser_gas)
+{
+ yasm_bytecode *bc;
+ yasm_expr *e;
+ yasm_valparamhead vps;
+ char *id;
+ const dir_lookup *dir;
+
+ if (is_eol())
+ return NULL;
+
+ bc = parse_instr(parser_gas);
+ if (bc)
+ return bc;
+
+ switch (curtok) {
+ case ID:
+ id = ID_val;
+
+ /* See if it's a gas-specific directive */
+ dir = (const dir_lookup *)HAMT_search(parser_gas->dirs, id);
+ if (dir) {
+ parser_gas->state = dir->newstate;
+ get_next_token(); /* ID */
+ return dir->handler(parser_gas, dir->param);
+ }
+
+ get_next_token(); /* ID */
+ if (curtok == ':') {
+ /* Label */
+ parser_gas->state = INITIAL;
+ get_next_token(); /* : */
+ define_label(parser_gas, id, 0);
+ return parse_line(parser_gas);
+ } else if (curtok == '=') {
+ /* EQU */
+ /* TODO: allow redefinition, assigning to . (same as .org) */
+ parser_gas->state = INITIAL;
+ get_next_token(); /* = */
+ e = parse_expr(parser_gas);
+ if (e)
+ yasm_symtab_define_equ(p_symtab, id, e, cur_line);
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected after `%s'"), "=");
+ yasm_xfree(id);
+ return NULL;
+ }
+
+ /* possibly a directive; try to parse it */
+ parse_dirvals(parser_gas, &vps);
+ if (!yasm_object_directive(p_object, id, "gas", &vps, NULL,
+ cur_line)) {
+ yasm_vps_delete(&vps);
+ yasm_xfree(id);
+ return NULL;
+ }
+ yasm_vps_delete(&vps);
+ if (id[0] == '.')
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("directive `%s' not recognized"), id);
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("instruction not recognized: `%s'"), id);
+ yasm_xfree(id);
+ return NULL;
+ case LABEL:
+ define_label(parser_gas, LABEL_val, 0);
+ get_next_token(); /* LABEL */
+ return parse_line(parser_gas);
+ case CPP_LINE_MARKER:
+ get_next_token();
+ cpp_line_marker(parser_gas);
+ return NULL;
+ case NASM_LINE_MARKER:
+ get_next_token();
+ nasm_line_marker(parser_gas);
+ return NULL;
+ default:
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("label or instruction expected at start of line"));
+ return NULL;
+ }
+}
+
+/*
+ Handle line markers generated by cpp.
+
+ We expect a positive integer (line) followed by a string (filename). If we
+ fail to find either of these, we treat the line as a comment. There is a
+ possibility of false positives (mistaking a comment for a line marker, when
+ the comment is not intended as a line marker) but this cannot be avoided
+ without adding a filter to the input before passing it to cpp.
+
+ This function is only called if the preprocessor was 'cpp', since the
+ CPP_LINE_MARKER token isn't generated for any other preprocessor. With any
+ other preprocessor, anything after a '#' is always treated as a comment.
+*/
+static void
+cpp_line_marker(yasm_parser_gas *parser_gas)
+{
+ yasm_valparamhead vps;
+ yasm_valparam *vp;
+ unsigned long line;
+ char *filename;
+
+ /* Line number. */
+ if (curtok != INTNUM) {
+ /* Skip over a comment. */
+ while (curtok != '\n')
+ get_next_token();
+
+ return;
+ }
+
+ if (yasm_intnum_sign(INTNUM_val) < 0) {
+ get_next_token(); /* INTNUM */
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("line number is negative"));
+ return;
+ }
+
+ line = yasm_intnum_get_uint(INTNUM_val);
+
+ /*
+ Set to (line - 1) since the directive indicates that the *next* line
+ will have the number given.
+
+ cpp should never produce line=0, but the if keeps us safe just incase.
+ */
+ if (line != 0)
+ line--;
+
+ yasm_intnum_destroy(INTNUM_val);
+ get_next_token(); /* INTNUM */
+
+ /* File name, in quotes. */
+ if (curtok != STRING) {
+ /* Skip over a comment. */
+ while (curtok != '\n')
+ get_next_token();
+
+ return;
+ }
+
+ filename = STRING_val.contents;
+ get_next_token();
+
+ /* Set linemap. */
+ yasm_linemap_set(parser_gas->linemap, filename, 0, line, 1);
+
+ /*
+ The first line marker in the file (which should be on the first line
+ of the file) will give us the name of the source file. This information
+ needs to be passed on to the debug format module.
+ */
+ if (parser_gas->seen_line_marker == 0) {
+ parser_gas->seen_line_marker = 1;
+
+ yasm_vps_initialize(&vps);
+ vp = yasm_vp_create_string(NULL, filename);
+ yasm_vps_append(&vps, vp);
+
+ yasm_object_directive(p_object, ".file", "gas", &vps, NULL, cur_line);
+
+ yasm_vps_delete(&vps);
+ } else
+ yasm_xfree(filename);
+
+ /* Skip flags. */
+ while (1) {
+ switch (curtok) {
+ case INTNUM:
+ break;
+
+ case '\n':
+ return;
+
+ default:
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("junk at end of cpp line marker"));
+ return;
+ }
+ get_next_token();
+ }
+}
+
+/*
+ Handle line markers generated by the nasm preproc.
+
+ We expect a positive integer (line) followed by a plus sign, followed by
+ another positive integer, followed by a string (filename).
+
+ This function is only called if the preprocessor was 'nasm', since the
+ NASM_LINE_MARKER token isn't generated for any other preprocessor.
+*/
+static void
+nasm_line_marker(yasm_parser_gas *parser_gas)
+{
+ yasm_valparamhead vps;
+ yasm_valparam *vp;
+ unsigned long line, incr;
+ char *filename;
+
+ /* Line number. */
+ if (!expect(INTNUM)) return;
+
+ if (yasm_intnum_sign(INTNUM_val) < 0) {
+ get_next_token(); /* INTNUM */
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("line number is negative"));
+ return;
+ }
+
+ line = yasm_intnum_get_uint(INTNUM_val);
+
+ /*
+ Set to (line - 1) since the directive indicates that the *next* line
+ will have the number given.
+
+ cpp should never produce line=0, but the if keeps us safe just incase.
+ */
+ if (line != 0)
+ line--;
+
+ yasm_intnum_destroy(INTNUM_val);
+ get_next_token(); /* INTNUM */
+
+ if (!expect('+')) return;
+ get_next_token(); /* + */
+
+ /* Line number increment. */
+ if (!expect(INTNUM)) return;
+
+ if (yasm_intnum_sign(INTNUM_val) < 0) {
+ get_next_token(); /* INTNUM */
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("line increment is negative"));
+ return;
+ }
+
+ incr = yasm_intnum_get_uint(INTNUM_val);
+ yasm_intnum_destroy(INTNUM_val);
+
+ /* File name is not in quotes, so need to switch to a different tokenizer
+ * state.
+ */
+ parser_gas->state = NASM_FILENAME;
+ get_next_token(); /* INTNUM */
+ if (!expect(STRING)) {
+ parser_gas->state = INITIAL;
+ return;
+ }
+
+ filename = STRING_val.contents;
+
+ /* Set linemap. */
+ yasm_linemap_set(parser_gas->linemap, filename, 0, line, incr);
+
+ /*
+ The first line marker in the file (which should be on the first line
+ of the file) will give us the name of the source file. This information
+ needs to be passed on to the debug format module.
+ */
+ if (parser_gas->seen_line_marker == 0) {
+ parser_gas->seen_line_marker = 1;
+
+ yasm_vps_initialize(&vps);
+ vp = yasm_vp_create_string(NULL, filename);
+ yasm_vps_append(&vps, vp);
+
+ yasm_object_directive(p_object, ".file", "gas", &vps, NULL, cur_line);
+
+ yasm_vps_delete(&vps);
+ } else
+ yasm_xfree(filename);
+
+ /* We need to poke back on the \n that was consumed by the tokenizer */
+ parser_gas->peek_token = '\n';
+ get_next_token();
+}
+
+/* Line directive */
+static yasm_bytecode *
+dir_line(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ if (!expect(INTNUM)) return NULL;
+ if (yasm_intnum_sign(INTNUM_val) < 0) {
+ get_next_token(); /* INTNUM */
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("line number is negative"));
+ return NULL;
+ }
+
+ parser_gas->dir_line = yasm_intnum_get_uint(INTNUM_val);
+ yasm_intnum_destroy(INTNUM_val);
+ get_next_token(); /* INTNUM */
+
+ if (parser_gas->dir_fileline == 3) {
+ /* Have both file and line */
+ yasm_linemap_set(parser_gas->linemap, NULL, 0,
+ parser_gas->dir_line, 1);
+ } else if (parser_gas->dir_fileline == 1) {
+ /* Had previous file directive only */
+ parser_gas->dir_fileline = 3;
+ yasm_linemap_set(parser_gas->linemap, parser_gas->dir_file, 0,
+ parser_gas->dir_line, 1);
+ } else {
+ /* Didn't see file yet */
+ parser_gas->dir_fileline = 2;
+ }
+ return NULL;
+}
+
+/* Alignment directives */
+
+static yasm_bytecode *
+dir_align(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ yasm_expr *bound, *fill=NULL, *maxskip=NULL;
+
+ bound = parse_expr(parser_gas);
+ if (!bound) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_(".align directive must specify alignment"));
+ return NULL;
+ }
+
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ fill = parse_expr(parser_gas);
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ maxskip = parse_expr(parser_gas);
+ }
+ }
+
+ return gas_parser_align(parser_gas, cursect, bound, fill, maxskip,
+ (int)param);
+}
+
+static yasm_bytecode *
+dir_org(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ yasm_intnum *start, *value=NULL;
+ yasm_bytecode *bc;
+
+ /* TODO: support expr instead of intnum */
+ if (!expect(INTNUM)) return NULL;
+ start = INTNUM_val;
+ get_next_token(); /* INTNUM */
+
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ /* TODO: support expr instead of intnum */
+ if (!expect(INTNUM)) return NULL;
+ value = INTNUM_val;
+ get_next_token(); /* INTNUM */
+ }
+ if (value) {
+ bc = yasm_bc_create_org(yasm_intnum_get_uint(start),
+ yasm_intnum_get_uint(value), cur_line);
+ yasm_intnum_destroy(value);
+ } else
+ bc = yasm_bc_create_org(yasm_intnum_get_uint(start), 0,
+ cur_line);
+ yasm_intnum_destroy(start);
+ return bc;
+}
+
+/* Data visibility directives */
+
+static yasm_bytecode *
+dir_local(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ if (!expect(ID)) return NULL;
+ yasm_symtab_declare(p_symtab, ID_val, YASM_SYM_DLOCAL, cur_line);
+ yasm_xfree(ID_val);
+ get_next_token(); /* ID */
+ return NULL;
+}
+
+static yasm_bytecode *
+dir_comm(yasm_parser_gas *parser_gas, unsigned int is_lcomm)
+{
+ yasm_expr *align = NULL;
+ /*@null@*/ /*@dependent@*/ yasm_symrec *sym;
+ char *id;
+ yasm_expr *e;
+
+ if (!expect(ID)) return NULL;
+ id = ID_val;
+ get_next_token(); /* ID */
+ if (!expect(',')) {
+ yasm_xfree(id);
+ return NULL;
+ }
+ get_next_token(); /* , */
+ e = parse_expr(parser_gas);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("size expected for `%s'"),
+ ".COMM");
+ return NULL;
+ }
+ if (curtok == ',') {
+ /* Optional alignment expression */
+ get_next_token(); /* ',' */
+ align = parse_expr(parser_gas);
+ }
+ /* If already explicitly declared local, treat like LCOMM */
+ if (is_lcomm
+ || ((sym = yasm_symtab_get(p_symtab, id))
+ && yasm_symrec_get_visibility(sym) == YASM_SYM_DLOCAL)) {
+ define_lcomm(parser_gas, id, e, align);
+ } else if (align) {
+ /* Give third parameter as objext valparam */
+ yasm_valparamhead *extvps = yasm_vps_create();
+ yasm_valparam *vp = yasm_vp_create_expr(NULL, align);
+ yasm_vps_append(extvps, vp);
+
+ sym = yasm_symtab_declare(p_symtab, id, YASM_SYM_COMMON,
+ cur_line);
+ yasm_symrec_set_common_size(sym, e);
+ yasm_symrec_set_objext_valparams(sym, extvps);
+
+ yasm_xfree(id);
+ } else {
+ sym = yasm_symtab_declare(p_symtab, id, YASM_SYM_COMMON,
+ cur_line);
+ yasm_symrec_set_common_size(sym, e);
+ yasm_xfree(id);
+ }
+ return NULL;
+}
+
+/* Integer data definition directives */
+
+static yasm_bytecode *
+dir_ascii(yasm_parser_gas *parser_gas, unsigned int withzero)
+{
+ yasm_datavalhead dvs;
+ if (!parse_strvals(parser_gas, &dvs))
+ return NULL;
+ return yasm_bc_create_data(&dvs, 1, (int)withzero, p_object->arch,
+ cur_line);
+}
+
+static yasm_bytecode *
+dir_data(yasm_parser_gas *parser_gas, unsigned int size)
+{
+ yasm_datavalhead dvs;
+ if (!parse_datavals(parser_gas, &dvs))
+ return NULL;
+ return yasm_bc_create_data(&dvs, size, 0, p_object->arch, cur_line);
+}
+
+static yasm_bytecode *
+dir_leb128(yasm_parser_gas *parser_gas, unsigned int sign)
+{
+ yasm_datavalhead dvs;
+ if (!parse_datavals(parser_gas, &dvs))
+ return NULL;
+ return yasm_bc_create_leb128(&dvs, (int)sign, cur_line);
+}
+
+/* Empty space / fill data definition directives */
+
+static yasm_bytecode *
+dir_zero(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ yasm_bytecode *bc;
+ yasm_datavalhead dvs;
+ yasm_expr *e = parse_expr(parser_gas);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected after `%s'"), ".ZERO");
+ return NULL;
+ }
+
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(
+ p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0)))));
+ bc = yasm_bc_create_data(&dvs, 1, 0, p_object->arch, cur_line);
+ yasm_bc_set_multiple(bc, e);
+ return bc;
+}
+
+static yasm_bytecode *
+dir_skip(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ yasm_expr *e, *e_val;
+ yasm_bytecode *bc;
+ yasm_datavalhead dvs;
+
+ e = parse_expr(parser_gas);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected after `%s'"), ".SKIP");
+ return NULL;
+ }
+ if (curtok != ',')
+ return yasm_bc_create_reserve(e, 1, cur_line);
+ get_next_token(); /* ',' */
+ e_val = parse_expr(parser_gas);
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(e_val));
+ bc = yasm_bc_create_data(&dvs, 1, 0, p_object->arch, cur_line);
+
+ yasm_bc_set_multiple(bc, e);
+ return bc;
+}
+
+/* fill data definition directive */
+static yasm_bytecode *
+dir_fill(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ yasm_expr *sz=NULL, *val=NULL;
+ yasm_expr *e = parse_expr(parser_gas);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected after `%s'"), ".FILL");
+ return NULL;
+ }
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ sz = parse_expr(parser_gas);
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ val = parse_expr(parser_gas);
+ }
+ }
+ return gas_parser_dir_fill(parser_gas, e, sz, val);
+}
+
+/* Section directives */
+
+static yasm_bytecode *
+dir_bss_section(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ gas_switch_section(parser_gas, ".bss", NULL, NULL, NULL, 1);
+ return NULL;
+}
+
+static yasm_bytecode *
+dir_data_section(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ gas_switch_section(parser_gas, ".data", NULL, NULL, NULL, 1);
+ return NULL;
+}
+
+static yasm_bytecode *
+dir_text_section(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ gas_switch_section(parser_gas, ".text", NULL, NULL, NULL, 1);
+ return NULL;
+}
+
+static yasm_bytecode *
+dir_section(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ /* DIR_SECTION ID ',' STRING ',' '@' ID ',' dirvals */
+ char *sectname, *flags = NULL, *type = NULL;
+ yasm_valparamhead vps;
+ int have_vps = 0;
+
+ if (!expect(ID)) return NULL;
+ sectname = ID_val;
+ get_next_token(); /* ID */
+
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ if (!expect(STRING)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("flag string expected"));
+ yasm_xfree(sectname);
+ return NULL;
+ }
+ flags = STRING_val.contents;
+ get_next_token(); /* STRING */
+ }
+
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ if (!expect('@')) {
+ yasm_xfree(sectname);
+ yasm_xfree(flags);
+ return NULL;
+ }
+ get_next_token(); /* '@' */
+ if (!expect(ID)) {
+ yasm_xfree(sectname);
+ yasm_xfree(flags);
+ return NULL;
+ }
+ type = ID_val;
+ get_next_token(); /* ID */
+ }
+
+ if (curtok == ',') {
+ get_next_token(); /* ',' */
+ if (parse_dirvals(parser_gas, &vps))
+ have_vps = 1;
+ }
+
+ gas_switch_section(parser_gas, sectname, flags, type,
+ have_vps ? &vps : NULL, 0);
+ yasm_xfree(sectname);
+ yasm_xfree(flags);
+ return NULL;
+}
+
+/* Other directives */
+
+static yasm_bytecode *
+dir_equ(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ yasm_expr *e;
+ char *id;
+
+ /* ID ',' expr */
+ if (!expect(ID)) return NULL;
+ id = ID_val;
+ get_next_token(); /* ID */
+ if (!expect(',')) {
+ yasm_xfree(id);
+ return NULL;
+ }
+ get_next_token(); /* ',' */
+ e = parse_expr(parser_gas);
+ if (e)
+ yasm_symtab_define_equ(p_symtab, id, e, cur_line);
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected after `%s'"), ",");
+ yasm_xfree(id);
+ return NULL;
+}
+
+static yasm_bytecode *
+dir_file(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ yasm_valparamhead vps;
+ yasm_valparam *vp;
+
+ if (curtok == STRING) {
+ /* No file number; this form also sets the assembler's
+ * internal line number.
+ */
+ char *filename = STRING_val.contents;
+
+ get_next_token(); /* STRING */
+ if (parser_gas->dir_fileline == 3) {
+ /* Have both file and line */
+ const char *old_fn;
+ unsigned long old_line;
+
+ yasm_linemap_lookup(parser_gas->linemap, cur_line, &old_fn,
+ &old_line);
+ yasm_linemap_set(parser_gas->linemap, filename, 0, old_line,
+ 1);
+ } else if (parser_gas->dir_fileline == 2) {
+ /* Had previous line directive only */
+ parser_gas->dir_fileline = 3;
+ yasm_linemap_set(parser_gas->linemap, filename, 0,
+ parser_gas->dir_line, 1);
+ } else {
+ /* Didn't see line yet, save file */
+ parser_gas->dir_fileline = 1;
+ if (parser_gas->dir_file)
+ yasm_xfree(parser_gas->dir_file);
+ parser_gas->dir_file = yasm__xstrdup(filename);
+ }
+
+ /* Pass change along to debug format */
+ yasm_vps_initialize(&vps);
+ vp = yasm_vp_create_string(NULL, filename);
+ yasm_vps_append(&vps, vp);
+
+ yasm_object_directive(p_object, ".file", "gas", &vps, NULL,
+ cur_line);
+
+ yasm_vps_delete(&vps);
+ return NULL;
+ }
+
+ /* fileno filename form */
+ yasm_vps_initialize(&vps);
+
+ if (!expect(INTNUM)) return NULL;
+ vp = yasm_vp_create_expr(NULL,
+ p_expr_new_ident(yasm_expr_int(INTNUM_val)));
+ yasm_vps_append(&vps, vp);
+ get_next_token(); /* INTNUM */
+
+ if (!expect(STRING)) {
+ yasm_vps_delete(&vps);
+ return NULL;
+ }
+ vp = yasm_vp_create_string(NULL, STRING_val.contents);
+ yasm_vps_append(&vps, vp);
+ get_next_token(); /* STRING */
+
+ yasm_object_directive(p_object, ".file", "gas", &vps, NULL,
+ cur_line);
+
+ yasm_vps_delete(&vps);
+ return NULL;
+}
+
+
+static yasm_bytecode *
+dir_intel_syntax(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ parser_gas->intel_syntax = 1;
+
+ do {
+ destroy_curtok();
+ get_next_token();
+ } while (!is_eol());
+ return NULL;
+}
+
+static yasm_bytecode *
+dir_att_syntax(yasm_parser_gas *parser_gas, unsigned int param)
+{
+ parser_gas->intel_syntax = 0;
+ return NULL;
+}
+
+static yasm_bytecode *
+parse_instr(yasm_parser_gas *parser_gas)
+{
+ yasm_bytecode *bc;
+ char *id;
+ uintptr_t prefix;
+
+ if (parser_gas->intel_syntax) {
+ bc = parse_instr_intel(parser_gas);
+ if (bc) {
+ yasm_warn_disable(YASM_WARN_UNREC_CHAR);
+ do {
+ destroy_curtok();
+ get_next_token();
+ } while (!is_eol());
+ yasm_warn_enable(YASM_WARN_UNREC_CHAR);
+ }
+ return bc;
+ }
+
+ if (curtok != ID)
+ return NULL;
+
+ id = ID_val;
+
+ /* instructions/prefixes must start with a letter */
+ if (!isalpha(id[0]))
+ return NULL;
+
+ /* check to be sure it's not a label or equ */
+ get_peek_token(parser_gas);
+ if (parser_gas->peek_token == ':' || parser_gas->peek_token == '=')
+ return NULL;
+
+ switch (yasm_arch_parse_check_insnprefix
+ (p_object->arch, ID_val, ID_len, cur_line, &bc, &prefix)) {
+ case YASM_ARCH_INSN:
+ {
+ yasm_insn *insn;
+
+ /* Propagate errors in case we got a warning from the arch */
+ yasm_errwarn_propagate(parser_gas->errwarns, cur_line);
+
+ insn = yasm_bc_get_insn(bc);
+
+ yasm_xfree(id);
+ get_next_token(); /* ID */
+ if (is_eol())
+ return bc; /* no operands */
+
+ /* parse operands */
+ for (;;) {
+ yasm_insn_operand *op = parse_operand(parser_gas);
+ if (!op) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression syntax error"));
+ yasm_bc_destroy(bc);
+ return NULL;
+ }
+ yasm_insn_ops_append(insn, op);
+
+ if (is_eol())
+ break;
+ if (!expect(',')) {
+ yasm_bc_destroy(bc);
+ return NULL;
+ }
+ get_next_token();
+ }
+ return bc;
+ }
+ case YASM_ARCH_PREFIX:
+ /* Propagate errors in case we got a warning from the arch */
+ yasm_errwarn_propagate(parser_gas->errwarns, cur_line);
+
+ yasm_xfree(id);
+ get_next_token(); /* ID */
+ bc = parse_instr(parser_gas);
+ if (!bc)
+ bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
+ yasm_insn_add_prefix(yasm_bc_get_insn(bc), prefix);
+ return bc;
+ default:
+ break;
+ }
+
+ /* Check for segment register used as prefix */
+ switch (yasm_arch_parse_check_regtmod(p_object->arch, ID_val, ID_len,
+ &prefix)) {
+ case YASM_ARCH_SEGREG:
+ yasm_xfree(id);
+ get_next_token(); /* ID */
+ bc = parse_instr(parser_gas);
+ if (!bc)
+ bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
+ yasm_insn_add_seg_prefix(yasm_bc_get_insn(bc), prefix);
+ return bc;
+ default:
+ return NULL;
+ }
+}
+
+static int
+parse_dirvals(yasm_parser_gas *parser_gas, yasm_valparamhead *vps)
+{
+ yasm_valparam *vp;
+ yasm_expr *e;
+ int num = 0;
+
+ yasm_vps_initialize(vps);
+
+ for (;;) {
+ switch (curtok) {
+ case ID:
+ get_peek_token(parser_gas);
+ switch (parser_gas->peek_token) {
+ case '+': case '-':
+ case '|': case '^': case '&': case '!':
+ case '*': case '/': case '%': case LEFT_OP: case RIGHT_OP:
+ e = parse_expr(parser_gas);
+ vp = yasm_vp_create_expr(NULL, e);
+ break;
+ default:
+ /* Just an ID */
+ vp = yasm_vp_create_id(NULL, ID_val, '\0');
+ get_next_token(); /* ID */
+ break;
+ }
+ break;
+ case STRING:
+ vp = yasm_vp_create_string(NULL, STRING_val.contents);
+ get_next_token(); /* STRING */
+ break;
+ case REG:
+ e = p_expr_new_ident(yasm_expr_reg(REG_val));
+ vp = yasm_vp_create_expr(NULL, e);
+ get_next_token(); /* REG */
+ break;
+ case '@':
+ /* XXX: is throwing it away *really* the right thing? */
+ get_next_token(); /* @ */
+ continue;
+ default:
+ e = parse_expr(parser_gas);
+ if (!e)
+ return num;
+ vp = yasm_vp_create_expr(NULL, e);
+ break;
+ }
+ yasm_vps_append(vps, vp);
+ num++;
+ if (curtok == ',')
+ get_next_token(); /* ',' */
+ }
+ return num;
+}
+
+static int
+parse_datavals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs)
+{
+ yasm_expr *e;
+ yasm_dataval *dv;
+ int num = 0;
+
+ yasm_dvs_initialize(dvs);
+
+ for (;;) {
+ e = parse_expr(parser_gas);
+ if (!e) {
+ yasm_dvs_delete(dvs);
+ yasm_dvs_initialize(dvs);
+ return 0;
+ }
+ dv = yasm_dv_create_expr(e);
+ yasm_dvs_append(dvs, dv);
+ num++;
+ if (curtok != ',')
+ break;
+ get_next_token(); /* ',' */
+ }
+ return num;
+}
+
+static int
+parse_strvals(yasm_parser_gas *parser_gas, yasm_datavalhead *dvs)
+{
+ yasm_dataval *dv;
+ int num = 0;
+
+ yasm_dvs_initialize(dvs);
+
+ for (;;) {
+ if (!expect(STRING)) {
+ yasm_dvs_delete(dvs);
+ yasm_dvs_initialize(dvs);
+ return 0;
+ }
+ dv = yasm_dv_create_string(STRING_val.contents, STRING_val.len);
+ yasm_dvs_append(dvs, dv);
+ get_next_token(); /* STRING */
+ num++;
+ if (curtok != ',')
+ break;
+ get_next_token(); /* ',' */
+ }
+ return num;
+}
+
+/* instruction operands */
+/* memory addresses */
+static yasm_effaddr *
+parse_memaddr(yasm_parser_gas *parser_gas)
+{
+ yasm_effaddr *ea = NULL;
+ yasm_expr *e1, *e2;
+ int strong = 0;
+
+ if (curtok == SEGREG) {
+ uintptr_t segreg = SEGREG_val;
+ get_next_token(); /* SEGREG */
+ if (!expect(':')) return NULL;
+ get_next_token(); /* ':' */
+ ea = parse_memaddr(parser_gas);
+ if (!ea)
+ return NULL;
+ yasm_ea_set_segreg(ea, segreg);
+ return ea;
+ }
+
+ /* We want to parse a leading expression, except when it's actually
+ * just a memory address (with no preceding expression) such as
+ * (REG...) or (,...).
+ */
+ get_peek_token(parser_gas);
+ if (curtok != '(' || (parser_gas->peek_token != REG
+ && parser_gas->peek_token != ','))
+ e1 = parse_expr(parser_gas);
+ else
+ e1 = NULL;
+
+ if (curtok == '(') {
+ int havereg = 0;
+ uintptr_t reg = 0;
+ yasm_intnum *scale = NULL;
+
+ get_next_token(); /* '(' */
+
+ /* base register */
+ if (curtok == REG) {
+ e2 = p_expr_new_ident(yasm_expr_reg(REG_val));
+ get_next_token(); /* REG */
+ } else
+ e2 = p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0)));
+
+ if (curtok == ')')
+ goto done;
+
+ if (!expect(',')) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid memory expression"));
+ if (e1) yasm_expr_destroy(e1);
+ yasm_expr_destroy(e2);
+ return NULL;
+ }
+ get_next_token(); /* ',' */
+
+ if (curtok == ')')
+ goto done;
+
+ /* index register */
+ if (curtok == REG) {
+ reg = REG_val;
+ havereg = 1;
+ get_next_token(); /* REG */
+ if (curtok != ',') {
+ scale = yasm_intnum_create_uint(1);
+ goto done;
+ }
+ get_next_token(); /* ',' */
+ }
+
+ /* scale */
+ if (!expect(INTNUM)) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("non-integer scale"));
+ if (e1) yasm_expr_destroy(e1);
+ yasm_expr_destroy(e2);
+ return NULL;
+ }
+ scale = INTNUM_val;
+ get_next_token(); /* INTNUM */
+
+done:
+ if (!expect(')')) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid memory expression"));
+ if (scale) yasm_intnum_destroy(scale);
+ if (e1) yasm_expr_destroy(e1);
+ yasm_expr_destroy(e2);
+ return NULL;
+ }
+ get_next_token(); /* ')' */
+
+ if (scale) {
+ if (!havereg) {
+ if (yasm_intnum_get_uint(scale) != 1)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("scale factor of %u without an index register"),
+ yasm_intnum_get_uint(scale));
+ yasm_intnum_destroy(scale);
+ } else
+ e2 = p_expr_new(yasm_expr_expr(e2), YASM_EXPR_ADD,
+ yasm_expr_expr(p_expr_new(yasm_expr_reg(reg), YASM_EXPR_MUL,
+ yasm_expr_int(scale))));
+ }
+
+ if (e1) {
+ /* Ordering is critical here to correctly detecting presence of
+ * RIP in RIP-relative expressions.
+ */
+ e1 = p_expr_new_tree(e2, YASM_EXPR_ADD, e1);
+ } else
+ e1 = e2;
+ strong = 1;
+ }
+
+ if (!e1)
+ return NULL;
+ ea = yasm_arch_ea_create(p_object->arch, e1);
+ if (strong)
+ ea->strong = 1;
+ return ea;
+}
+
+static yasm_insn_operand *
+parse_operand(yasm_parser_gas *parser_gas)
+{
+ yasm_effaddr *ea;
+ yasm_insn_operand *op;
+ uintptr_t reg;
+
+ switch (curtok) {
+ case REG:
+ reg = REG_val;
+ get_next_token(); /* REG */
+ return yasm_operand_create_reg(reg);
+ case SEGREG:
+ /* need to see if it's really a memory address */
+ get_peek_token(parser_gas);
+ if (parser_gas->peek_token == ':') {
+ ea = parse_memaddr(parser_gas);
+ if (!ea)
+ return NULL;
+ return yasm_operand_create_mem(ea);
+ }
+ reg = SEGREG_val;
+ get_next_token(); /* SEGREG */
+ return yasm_operand_create_segreg(reg);
+ case REGGROUP:
+ {
+ unsigned long regindex;
+ reg = REGGROUP_val;
+ get_next_token(); /* REGGROUP */
+ if (curtok != '(')
+ return yasm_operand_create_reg(reg);
+ get_next_token(); /* '(' */
+ if (!expect(INTNUM)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("integer register index expected"));
+ return NULL;
+ }
+ regindex = yasm_intnum_get_uint(INTNUM_val);
+ get_next_token(); /* INTNUM */
+ if (!expect(')')) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("missing closing parenthesis for register index"));
+ return NULL;
+ }
+ get_next_token(); /* ')' */
+ reg = yasm_arch_reggroup_get_reg(p_object->arch, reg, regindex);
+ if (reg == 0) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("bad register index `%u'"),
+ regindex);
+ return NULL;
+ }
+ return yasm_operand_create_reg(reg);
+ }
+ case '$':
+ {
+ yasm_expr *e;
+ get_next_token(); /* '$' */
+ e = parse_expr(parser_gas);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression missing after `%s'"), "$");
+ return NULL;
+ }
+ return yasm_operand_create_imm(e);
+ }
+ case '*':
+ get_next_token(); /* '*' */
+ if (curtok == REG) {
+ op = yasm_operand_create_reg(REG_val);
+ get_next_token(); /* REG */
+ } else {
+ ea = parse_memaddr(parser_gas);
+ if (!ea) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression missing after `%s'"), "*");
+ return NULL;
+ }
+ op = yasm_operand_create_mem(ea);
+ }
+ op->deref = 1;
+ return op;
+ default:
+ ea = parse_memaddr(parser_gas);
+ if (!ea)
+ return NULL;
+ return yasm_operand_create_mem(ea);
+ }
+}
+
+/* Expression grammar parsed is:
+ *
+ * expr : expr0 [ {+,-} expr0...]
+ * expr0 : expr1 [ {|,^,&,!} expr1...]
+ * expr1 : expr2 [ {*,/,%,<<,>>} expr2...]
+ * expr2 : { ~,+,- } expr2
+ * | (expr)
+ * | symbol
+ * | number
+ */
+
+static yasm_expr *
+parse_expr(yasm_parser_gas *parser_gas)
+{
+ yasm_expr *e, *f;
+ e = parse_expr0(parser_gas);
+ if (!e)
+ return NULL;
+
+ while (curtok == '+' || curtok == '-') {
+ int op = curtok;
+ get_next_token();
+ f = parse_expr0(parser_gas);
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (op) {
+ case '+': e = p_expr_new_tree(e, YASM_EXPR_ADD, f); break;
+ case '-': e = p_expr_new_tree(e, YASM_EXPR_SUB, f); break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *
+parse_expr0(yasm_parser_gas *parser_gas)
+{
+ yasm_expr *e, *f;
+ e = parse_expr1(parser_gas);
+ if (!e)
+ return NULL;
+
+ while (curtok == '|' || curtok == '^' || curtok == '&' || curtok == '!') {
+ int op = curtok;
+ get_next_token();
+ f = parse_expr1(parser_gas);
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (op) {
+ case '|': e = p_expr_new_tree(e, YASM_EXPR_OR, f); break;
+ case '^': e = p_expr_new_tree(e, YASM_EXPR_XOR, f); break;
+ case '&': e = p_expr_new_tree(e, YASM_EXPR_AND, f); break;
+ case '!': e = p_expr_new_tree(e, YASM_EXPR_NOR, f); break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *
+parse_expr1(yasm_parser_gas *parser_gas)
+{
+ yasm_expr *e, *f;
+ e = parse_expr2(parser_gas);
+ if (!e)
+ return NULL;
+
+ while (curtok == '*' || curtok == '/' || curtok == '%' || curtok == LEFT_OP
+ || curtok == RIGHT_OP) {
+ int op = curtok;
+ get_next_token();
+ f = parse_expr2(parser_gas);
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (op) {
+ case '*': e = p_expr_new_tree(e, YASM_EXPR_MUL, f); break;
+ case '/': e = p_expr_new_tree(e, YASM_EXPR_DIV, f); break;
+ case '%': e = p_expr_new_tree(e, YASM_EXPR_MOD, f); break;
+ case LEFT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHL, f); break;
+ case RIGHT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHR, f); break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *
+parse_expr2(yasm_parser_gas *parser_gas)
+{
+ yasm_expr *e;
+ yasm_symrec *sym;
+
+ switch (curtok) {
+ case '+':
+ get_next_token();
+ return parse_expr2(parser_gas);
+ case '-':
+ get_next_token();
+ e = parse_expr2(parser_gas);
+ if (!e)
+ return NULL;
+ return p_expr_new_branch(YASM_EXPR_NEG, e);
+ case '~':
+ get_next_token();
+ e = parse_expr2(parser_gas);
+ if (!e)
+ return NULL;
+ return p_expr_new_branch(YASM_EXPR_NOT, e);
+ case '(':
+ get_next_token();
+ e = parse_expr(parser_gas);
+ if (!e)
+ return NULL;
+ if (!expect(')')) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("missing parenthesis"));
+ return NULL;
+ }
+ get_next_token();
+ return e;
+ case INTNUM:
+ e = p_expr_new_ident(yasm_expr_int(INTNUM_val));
+ get_next_token();
+ return e;
+ case FLTNUM:
+ e = p_expr_new_ident(yasm_expr_float(FLTNUM_val));
+ get_next_token();
+ return e;
+ case ID:
+ {
+ char *name = ID_val;
+ get_next_token(); /* ID */
+
+ /* "." references the current assembly position */
+ if (name[1] == '\0' && name[0] == '.')
+ sym = yasm_symtab_define_curpos(p_symtab, ".",
+ parser_gas->prev_bc, cur_line);
+ else
+ sym = yasm_symtab_use(p_symtab, name, cur_line);
+ yasm_xfree(name);
+
+ if (curtok == '@') {
+ yasm_symrec *wrt;
+ /* TODO: this is needed for shared objects, e.g. sym@PLT */
+ get_next_token(); /* '@' */
+ if (!expect(ID)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected identifier after `@'"));
+ return NULL;
+ }
+ wrt = yasm_objfmt_get_special_sym(p_object, ID_val, "gas");
+ yasm_xfree(ID_val);
+ get_next_token(); /* ID */
+ if (!wrt) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("unrecognized identifier after `@'"));
+ return p_expr_new_ident(yasm_expr_sym(sym));
+ }
+ return p_expr_new(yasm_expr_sym(sym), YASM_EXPR_WRT,
+ yasm_expr_sym(wrt));
+ }
+
+ return p_expr_new_ident(yasm_expr_sym(sym));
+ }
+ default:
+ return NULL;
+ }
+}
+
+static void
+define_label(yasm_parser_gas *parser_gas, char *name, int local)
+{
+ if (!local) {
+ if (parser_gas->locallabel_base)
+ yasm_xfree(parser_gas->locallabel_base);
+ parser_gas->locallabel_base_len = strlen(name);
+ parser_gas->locallabel_base =
+ yasm_xmalloc(parser_gas->locallabel_base_len+1);
+ strcpy(parser_gas->locallabel_base, name);
+ }
+
+ yasm_symtab_define_label(p_symtab, name, parser_gas->prev_bc, 1,
+ cur_line);
+ yasm_xfree(name);
+}
+
+static void
+define_lcomm(yasm_parser_gas *parser_gas, /*@only@*/ char *name,
+ yasm_expr *size, /*@null@*/ yasm_expr *align)
+{
+ /* Put into .bss section. */
+ /*@dependent@*/ yasm_section *bss =
+ gas_get_section(parser_gas, yasm__xstrdup(".bss"), NULL, NULL, NULL, 1);
+
+ if (align) {
+ /* XXX: assume alignment is in bytes, not power-of-two */
+ yasm_section_bcs_append(bss, gas_parser_align(parser_gas, bss, align,
+ NULL, NULL, 0));
+ }
+
+ yasm_symtab_define_label(p_symtab, name, yasm_section_bcs_last(bss), 1,
+ cur_line);
+ yasm_section_bcs_append(bss, yasm_bc_create_reserve(size, 1, cur_line));
+ yasm_xfree(name);
+}
+
+static yasm_section *
+gas_get_section(yasm_parser_gas *parser_gas, char *name,
+ /*@null@*/ char *flags, /*@null@*/ char *type,
+ /*@null@*/ yasm_valparamhead *objext_valparams,
+ int builtin)
+{
+ yasm_valparamhead vps;
+ yasm_valparam *vp;
+ char *gasflags;
+ yasm_section *new_section;
+
+ yasm_vps_initialize(&vps);
+ vp = yasm_vp_create_id(NULL, name, '\0');
+ yasm_vps_append(&vps, vp);
+
+ if (!builtin) {
+ if (flags)
+ gasflags = yasm__xstrdup(flags);
+ else
+ gasflags = yasm__xstrdup("");
+ vp = yasm_vp_create_string(yasm__xstrdup("gasflags"), gasflags);
+ yasm_vps_append(&vps, vp);
+ if (type) {
+ vp = yasm_vp_create_id(NULL, type, '\0');
+ yasm_vps_append(&vps, vp);
+ }
+ }
+
+ new_section = yasm_objfmt_section_switch(p_object, &vps, objext_valparams,
+ cur_line);
+
+ yasm_vps_delete(&vps);
+ return new_section;
+}
+
+static void
+gas_switch_section(yasm_parser_gas *parser_gas, const char *name,
+ /*@null@*/ char *flags, /*@null@*/ char *type,
+ /*@null@*/ yasm_valparamhead *objext_valparams,
+ int builtin)
+{
+ yasm_section *new_section;
+
+ new_section = gas_get_section(parser_gas, yasm__xstrdup(name), flags, type,
+ objext_valparams, builtin);
+ if (new_section) {
+ cursect = new_section;
+ parser_gas->prev_bc = yasm_section_bcs_last(new_section);
+ } else
+ yasm_error_set(YASM_ERROR_GENERAL, N_("invalid section name `%s'"),
+ name);
+
+ if (objext_valparams)
+ yasm_vps_delete(objext_valparams);
+}
+
+static yasm_bytecode *
+gas_parser_align(yasm_parser_gas *parser_gas, yasm_section *sect,
+ yasm_expr *boundval, /*@null@*/ yasm_expr *fillval,
+ /*@null@*/ yasm_expr *maxskipval, int power2)
+{
+ yasm_intnum *boundintn;
+
+ /* Convert power of two to number of bytes if necessary */
+ if (power2)
+ boundval = yasm_expr_create(YASM_EXPR_SHL,
+ yasm_expr_int(yasm_intnum_create_uint(1)),
+ yasm_expr_expr(boundval), cur_line);
+
+ /* Largest .align in the section specifies section alignment. */
+ boundintn = yasm_expr_get_intnum(&boundval, 0);
+ if (boundintn) {
+ unsigned long boundint = yasm_intnum_get_uint(boundintn);
+
+ /* Alignments must be a power of two. */
+ if (is_exp2(boundint)) {
+ if (boundint > yasm_section_get_align(sect))
+ yasm_section_set_align(sect, boundint, cur_line);
+ }
+ }
+
+ return yasm_bc_create_align(boundval, fillval, maxskipval,
+ yasm_section_is_code(sect) ?
+ yasm_arch_get_fill(p_object->arch) : NULL,
+ cur_line);
+}
+
+static yasm_bytecode *
+gas_parser_dir_fill(yasm_parser_gas *parser_gas, /*@only@*/ yasm_expr *repeat,
+ /*@only@*/ /*@null@*/ yasm_expr *size,
+ /*@only@*/ /*@null@*/ yasm_expr *value)
+{
+ yasm_datavalhead dvs;
+ yasm_bytecode *bc;
+ unsigned int ssize;
+
+ if (size) {
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
+ intn = yasm_expr_get_intnum(&size, 0);
+ if (!intn) {
+ yasm_error_set(YASM_ERROR_NOT_ABSOLUTE,
+ N_("size must be an absolute expression"));
+ yasm_expr_destroy(repeat);
+ yasm_expr_destroy(size);
+ if (value)
+ yasm_expr_destroy(value);
+ return NULL;
+ }
+ ssize = yasm_intnum_get_uint(intn);
+ } else
+ ssize = 1;
+
+ if (!value)
+ value = yasm_expr_create_ident(
+ yasm_expr_int(yasm_intnum_create_uint(0)), cur_line);
+
+ yasm_dvs_initialize(&dvs);
+ yasm_dvs_append(&dvs, yasm_dv_create_expr(value));
+ bc = yasm_bc_create_data(&dvs, ssize, 0, p_object->arch, cur_line);
+
+ yasm_bc_set_multiple(bc, repeat);
+
+ return bc;
+}
+
+static dir_lookup dirs_static[] = {
+ /* FIXME: Whether this is power-of-two or not depends on arch and objfmt. */
+ {".align", dir_align, 0, INITIAL},
+ {".p2align", dir_align, 1, INITIAL},
+ {".balign", dir_align, 0, INITIAL},
+ {".org", dir_org, 0, INITIAL},
+ /* data visibility directives */
+ {".local", dir_local, 0, INITIAL},
+ {".comm", dir_comm, 0, INITIAL},
+ {".lcomm", dir_comm, 1, INITIAL},
+ /* integer data declaration directives */
+ {".byte", dir_data, 1, INITIAL},
+ {".2byte", dir_data, 2, INITIAL},
+ {".4byte", dir_data, 4, INITIAL},
+ {".8byte", dir_data, 8, INITIAL},
+ {".16byte", dir_data, 16, INITIAL},
+ /* TODO: These should depend on arch */
+ {".short", dir_data, 2, INITIAL},
+ {".int", dir_data, 4, INITIAL},
+ {".long", dir_data, 4, INITIAL},
+ {".hword", dir_data, 2, INITIAL},
+ {".quad", dir_data, 8, INITIAL},
+ {".octa", dir_data, 16, INITIAL},
+ /* XXX: At least on x86, this is 2 bytes */
+ {".value", dir_data, 2, INITIAL},
+ /* ASCII data declaration directives */
+ {".ascii", dir_ascii, 0, INITIAL}, /* no terminating zero */
+ {".asciz", dir_ascii, 1, INITIAL}, /* add terminating zero */
+ {".string", dir_ascii, 1, INITIAL}, /* add terminating zero */
+ /* LEB128 integer data declaration directives */
+ {".sleb128", dir_leb128, 1, INITIAL}, /* signed */
+ {".uleb128", dir_leb128, 0, INITIAL}, /* unsigned */
+ /* floating point data declaration directives */
+ {".float", dir_data, 4, INITIAL},
+ {".single", dir_data, 4, INITIAL},
+ {".double", dir_data, 8, INITIAL},
+ {".tfloat", dir_data, 10, INITIAL},
+ /* section directives */
+ {".bss", dir_bss_section, 0, INITIAL},
+ {".data", dir_data_section, 0, INITIAL},
+ {".text", dir_text_section, 0, INITIAL},
+ {".section", dir_section, 0, SECTION_DIRECTIVE},
+ /* empty space/fill directives */
+ {".skip", dir_skip, 0, INITIAL},
+ {".space", dir_skip, 0, INITIAL},
+ {".fill", dir_fill, 0, INITIAL},
+ {".zero", dir_zero, 0, INITIAL},
+ /* syntax directives */
+ {".intel_syntax", dir_intel_syntax, 0, INITIAL},
+ {".att_syntax", dir_att_syntax, 0, INITIAL},
+ /* other directives */
+ {".equ", dir_equ, 0, INITIAL},
+ {".file", dir_file, 0, INITIAL},
+ {".line", dir_line, 0, INITIAL},
+ {".set", dir_equ, 0, INITIAL}
+};
+
+static void
+no_delete(void *data)
+{
+}
+
+void
+gas_parser_parse(yasm_parser_gas *parser_gas)
+{
+ dir_lookup word;
+ unsigned int i;
+ int replace = 1;
+
+ word.name = ".word";
+ word.handler = dir_data;
+ word.param = yasm_arch_wordsize(p_object->arch)/8;
+ word.newstate = INITIAL;
+
+ /* Create directive lookup */
+ parser_gas->dirs = HAMT_create(1, yasm_internal_error_);
+ HAMT_insert(parser_gas->dirs, word.name, &word, &replace, no_delete);
+ for (i=0; i<NELEMS(dirs_static); i++) {
+ replace = 1;
+ HAMT_insert(parser_gas->dirs, dirs_static[i].name,
+ &dirs_static[i], &replace, no_delete);
+ }
+
+ while (get_next_token() != 0) {
+ yasm_bytecode *bc = NULL, *temp_bc;
+
+ if (!is_eol()) {
+ bc = parse_line(parser_gas);
+ demand_eol();
+ }
+
+ yasm_errwarn_propagate(parser_gas->errwarns, cur_line);
+
+ temp_bc = yasm_section_bcs_append(cursect, bc);
+ if (temp_bc)
+ parser_gas->prev_bc = temp_bc;
+ if (curtok == ';')
+ continue; /* don't advance line number until \n */
+ if (parser_gas->save_input)
+ yasm_linemap_add_source(parser_gas->linemap,
+ temp_bc,
+ (char *)parser_gas->save_line[parser_gas->save_last ^ 1]);
+ yasm_linemap_goto_next(parser_gas->linemap);
+ parser_gas->dir_line++; /* keep track for .line followed by .file */
+ }
+
+ HAMT_destroy(parser_gas->dirs, no_delete);
+}
diff --git a/contrib/tools/yasm/modules/parsers/gas/gas-parser.c b/contrib/tools/yasm/modules/parsers/gas/gas-parser.c
new file mode 100644
index 0000000000..088bcdad0a
--- /dev/null
+++ b/contrib/tools/yasm/modules/parsers/gas/gas-parser.c
@@ -0,0 +1,133 @@
+/*
+ * GAS-compatible parser
+ *
+ * Copyright (C) 2005-2007 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.
+ * 3. Neither the name of the author nor the names of other contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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 <util.h>
+
+#include <libyasm.h>
+
+#include "gas-parser.h"
+
+
+static void
+gas_parser_do_parse(yasm_object *object, yasm_preproc *pp,
+ int save_input, yasm_linemap *linemap,
+ yasm_errwarns *errwarns)
+{
+ yasm_parser_gas parser_gas;
+ int i;
+
+ parser_gas.object = object;
+ parser_gas.linemap = linemap;
+
+ parser_gas.locallabel_base = (char *)NULL;
+ parser_gas.locallabel_base_len = 0;
+
+ parser_gas.dir_fileline = 0;
+ parser_gas.dir_file = NULL;
+ parser_gas.dir_line = 0;
+ parser_gas.seen_line_marker = 0;
+
+ parser_gas.preproc = pp;
+ parser_gas.errwarns = errwarns;
+
+ parser_gas.prev_bc = yasm_section_bcs_first(object->cur_section);
+
+ parser_gas.save_input = save_input;
+ parser_gas.save_last = 0;
+
+ parser_gas.peek_token = NONE;
+
+ parser_gas.line = NULL;
+
+ /* initialize scanner structure */
+ yasm_scanner_initialize(&parser_gas.s);
+
+ parser_gas.state = INITIAL;
+
+ for (i=0; i<10; i++)
+ parser_gas.local[i] = 0;
+
+ parser_gas.intel_syntax = 0;
+
+ parser_gas.is_cpp_preproc =
+ yasm__strcasecmp(((yasm_preproc_base*)pp)->module->keyword, "cpp") == 0;
+ parser_gas.is_nasm_preproc =
+ yasm__strcasecmp(((yasm_preproc_base*)pp)->module->keyword, "nasm") == 0;
+
+ gas_parser_parse(&parser_gas);
+
+ /* Check for ending inside a comment */
+ if (parser_gas.state == COMMENT) {
+ yasm_warn_set(YASM_WARN_GENERAL, N_("end of file in comment"));
+ /* XXX: Minus two to compensate for already having moved past the EOF
+ * in the linemap.
+ */
+ yasm_errwarn_propagate(errwarns,
+ yasm_linemap_get_current(parser_gas.linemap)-2);
+ }
+
+ yasm_scanner_delete(&parser_gas.s);
+
+ /* Free locallabel base if necessary */
+ if (parser_gas.locallabel_base)
+ yasm_xfree(parser_gas.locallabel_base);
+
+ if (parser_gas.dir_file)
+ yasm_xfree(parser_gas.dir_file);
+
+ /* Convert all undefined symbols into extern symbols */
+ yasm_symtab_parser_finalize(object->symtab, 1, errwarns);
+}
+
+/* Define valid preprocessors to use with this parser */
+static const char *gas_parser_preproc_keywords[] = {
+ "gas",
+ "raw",
+ "cpp",
+ "nasm",
+ NULL
+};
+
+/* Define parser structure -- see parser.h for details */
+yasm_parser_module yasm_gas_LTX_parser = {
+ "GNU AS (GAS)-compatible parser",
+ "gas",
+ gas_parser_preproc_keywords,
+ "gas",
+ NULL, /* No standard macros */
+ gas_parser_do_parse
+};
+yasm_parser_module yasm_gnu_LTX_parser = {
+ "GNU AS (GAS)-compatible parser",
+ "gnu",
+ gas_parser_preproc_keywords,
+ "gas",
+ NULL, /* No standard macros */
+ gas_parser_do_parse
+};
diff --git a/contrib/tools/yasm/modules/parsers/gas/gas-parser.h b/contrib/tools/yasm/modules/parsers/gas/gas-parser.h
new file mode 100644
index 0000000000..99659e964a
--- /dev/null
+++ b/contrib/tools/yasm/modules/parsers/gas/gas-parser.h
@@ -0,0 +1,163 @@
+/*
+ * GAS-compatible parser header file
+ *
+ * Copyright (C) 2005-2007 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.
+ * 3. Neither the name of the author nor the names of other contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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.
+ */
+#ifndef YASM_GAS_PARSER_H
+#define YASM_GAS_PARSER_H
+
+#define YYCTYPE unsigned char
+
+#define MAX_SAVED_LINE_LEN 80
+
+enum tokentype {
+ INTNUM = 258,
+ FLTNUM,
+ STRING,
+ REG,
+ REGGROUP,
+ SEGREG,
+ TARGETMOD,
+ LEFT_OP,
+ RIGHT_OP,
+ ID,
+ LABEL,
+ CPP_LINE_MARKER,
+ NASM_LINE_MARKER,
+ NONE
+};
+
+typedef union {
+ unsigned int int_info;
+ yasm_intnum *intn;
+ yasm_floatnum *flt;
+ yasm_bytecode *bc;
+ uintptr_t arch_data;
+ struct {
+ char *contents;
+ size_t len;
+ } str;
+} yystype;
+#define YYSTYPE yystype
+
+enum gas_parser_state {
+ INITIAL,
+ COMMENT,
+ SECTION_DIRECTIVE,
+ NASM_FILENAME
+};
+
+typedef struct yasm_parser_gas {
+ /*@only@*/ yasm_object *object;
+
+ /* last "base" label for local (.) labels */
+ /*@null@*/ char *locallabel_base;
+ size_t locallabel_base_len;
+
+ /* .line/.file: we have to see both to start setting linemap versions */
+ int dir_fileline;
+ /*@null@*/ char *dir_file;
+ unsigned long dir_line;
+
+ /* Have we seen a line marker? */
+ int seen_line_marker;
+
+ /*@dependent@*/ yasm_preproc *preproc;
+ /*@dependent@*/ yasm_errwarns *errwarns;
+
+ /*@dependent@*/ yasm_linemap *linemap;
+
+ /*@null@*/ yasm_bytecode *prev_bc;
+ yasm_bytecode *temp_bc;
+
+ int save_input;
+ YYCTYPE save_line[2][MAX_SAVED_LINE_LEN];
+ int save_last;
+
+ /* Line data storage used in preproc_input(). */
+ char *line, *linepos;
+ size_t lineleft;
+
+ yasm_scanner s;
+ enum gas_parser_state state;
+
+ int token; /* enum tokentype or any character */
+ yystype tokval;
+ char tokch; /* first character of token */
+
+ /* one token of lookahead; used sparingly */
+ int peek_token; /* NONE if none */
+ yystype peek_tokval;
+ char peek_tokch;
+
+ /* Index of local labels; what's stored here is the /next/ index,
+ * so these are all 0 at start.
+ */
+ unsigned long local[10];
+
+ /* Parser-handled directives HAMT lookup */
+ HAMT *dirs;
+
+ int intel_syntax;
+
+ int is_nasm_preproc;
+ int is_cpp_preproc;
+} yasm_parser_gas;
+
+/* shorter access names to commonly used parser_gas fields */
+#define p_object (parser_gas->object)
+#define p_symtab (parser_gas->object->symtab)
+#define cursect (parser_gas->object->cur_section)
+#define curtok (parser_gas->token)
+#define curval (parser_gas->tokval)
+
+#define INTNUM_val (curval.intn)
+#define FLTNUM_val (curval.flt)
+#define STRING_val (curval.str)
+#define REG_val (curval.arch_data)
+#define REGGROUP_val (curval.arch_data)
+#define SEGREG_val (curval.arch_data)
+#define TARGETMOD_val (curval.arch_data)
+#define ID_val (curval.str.contents)
+#define ID_len (curval.str.len)
+#define LABEL_val (curval.str.contents)
+#define LABEL_len (curval.str.len)
+
+#define cur_line (yasm_linemap_get_current(parser_gas->linemap))
+
+#define p_expr_new(l,o,r) yasm_expr_create(o,l,r,cur_line)
+#define p_expr_new_tree(l,o,r) yasm_expr_create_tree(l,o,r,cur_line)
+#define p_expr_new_branch(o,r) yasm_expr_create_branch(o,r,cur_line)
+#define p_expr_new_ident(r) yasm_expr_create_ident(r,cur_line)
+
+yasm_bytecode *parse_instr_intel(yasm_parser_gas *parser_gas);
+
+void gas_parser_parse(yasm_parser_gas *parser_gas);
+void gas_parser_cleanup(yasm_parser_gas *parser_gas);
+int gas_parser_lex(YYSTYPE *lvalp, yasm_parser_gas *parser_gas);
+
+#endif
diff --git a/contrib/tools/yasm/modules/parsers/nasm/nasm-parse.c b/contrib/tools/yasm/modules/parsers/nasm/nasm-parse.c
new file mode 100644
index 0000000000..44d3b5d707
--- /dev/null
+++ b/contrib/tools/yasm/modules/parsers/nasm/nasm-parse.c
@@ -0,0 +1,1680 @@
+/*
+ * NASM-compatible parser
+ *
+ * Copyright (C) 2001-2007 Peter Johnson, Michael Urman
+ *
+ * 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 <util.h>
+
+#include <libyasm.h>
+
+#include <math.h>
+
+#include "modules/parsers/nasm/nasm-parser.h"
+#include "modules/preprocs/nasm/nasm.h"
+
+typedef enum {
+ NORM_EXPR,
+ DIR_EXPR, /* Can't have seg:off or WRT anywhere */
+ DV_EXPR /* Can't have registers anywhere */
+} expr_type;
+
+static yasm_bytecode *parse_line(yasm_parser_nasm *parser_nasm);
+static int parse_directive_valparams(yasm_parser_nasm *parser_nasm,
+ /*@out@*/ yasm_valparamhead *vps);
+static yasm_bytecode *parse_times(yasm_parser_nasm *parser_nasm);
+static yasm_bytecode *parse_exp(yasm_parser_nasm *parser_nasm);
+static yasm_bytecode *parse_instr(yasm_parser_nasm *parser_nasm);
+static yasm_insn_operand *parse_operand(yasm_parser_nasm *parser_nasm);
+static yasm_insn_operand *parse_memaddr(yasm_parser_nasm *parser_nasm);
+static yasm_expr *parse_expr(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_bexpr(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_expr0(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_expr1(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_expr2(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_expr3(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_expr4(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_expr5(yasm_parser_nasm *parser_nasm, expr_type type);
+static yasm_expr *parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type);
+
+static void nasm_parser_directive
+ (yasm_parser_nasm *parser_nasm, const char *name,
+ /*@null@*/ yasm_valparamhead *valparams,
+ /*@null@*/ yasm_valparamhead *objext_valparams);
+static void set_nonlocal_label(yasm_parser_nasm *parser_nasm, const char *name);
+static void define_label(yasm_parser_nasm *parser_nasm, /*@only@*/ char *name,
+ unsigned int size);
+
+static void yasm_ea_set_implicit_size_segment(yasm_parser_nasm *parser_nasm,
+ yasm_effaddr *ea, yasm_expr *e)
+{
+ if (parser_nasm->tasm) {
+ const char *segment = yasm_expr_segment(e);
+ ea->data_len = yasm_expr_size(e);
+ if (segment) {
+ const char *segreg = tasm_get_segment_register(segment);
+ if (segreg)
+ yasm_arch_parse_check_regtmod(p_object->arch, segreg,
+ strlen(segreg), &ea->segreg);
+ }
+ }
+}
+
+
+#define is_eol_tok(tok) ((tok) == 0)
+#define is_eol() is_eol_tok(curtok)
+
+#define get_next_token() (curtok = nasm_parser_lex(&curval, parser_nasm))
+
+static void
+get_peek_token(yasm_parser_nasm *parser_nasm)
+{
+ char savech = parser_nasm->tokch;
+ if (parser_nasm->peek_token != NONE)
+ yasm_internal_error(N_("only can have one token of lookahead"));
+ parser_nasm->peek_token =
+ nasm_parser_lex(&parser_nasm->peek_tokval, parser_nasm);
+ parser_nasm->peek_tokch = parser_nasm->tokch;
+ parser_nasm->tokch = savech;
+}
+
+static void
+destroy_curtok_(yasm_parser_nasm *parser_nasm)
+{
+ if (curtok < 256)
+ ;
+ else switch ((enum tokentype)curtok) {
+ case INTNUM:
+ yasm_intnum_destroy(curval.intn);
+ break;
+ case FLTNUM:
+ yasm_floatnum_destroy(curval.flt);
+ break;
+ case DIRECTIVE_NAME:
+ case FILENAME:
+ case ID:
+ case LOCAL_ID:
+ case SPECIAL_ID:
+ case NONLOCAL_ID:
+ yasm_xfree(curval.str_val);
+ break;
+ case STRING:
+ yasm_xfree(curval.str.contents);
+ break;
+ case INSN:
+ yasm_bc_destroy(curval.bc);
+ break;
+ default:
+ break;
+ }
+ curtok = NONE; /* sanity */
+}
+#define destroy_curtok() destroy_curtok_(parser_nasm)
+
+/* Eat all remaining tokens to EOL, discarding all of them. If there's any
+ * intervening tokens, generates an error (junk at end of line).
+ */
+static void
+demand_eol_(yasm_parser_nasm *parser_nasm)
+{
+ if (is_eol())
+ return;
+
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("junk at end of line, first unrecognized character is `%c'"),
+ parser_nasm->tokch);
+
+ do {
+ destroy_curtok();
+ get_next_token();
+ } while (!is_eol());
+}
+#define demand_eol() demand_eol_(parser_nasm)
+
+static const char *
+describe_token(int token)
+{
+ static char strch[] = "` '";
+ const char *str;
+
+ switch (token) {
+ case 0: str = "end of line"; break;
+ case INTNUM: str = "integer"; break;
+ case FLTNUM: str = "floating point value"; break;
+ case DIRECTIVE_NAME: str = "directive name"; break;
+ case FILENAME: str = "filename"; break;
+ case STRING: str = "string"; break;
+ case SIZE_OVERRIDE: str = "size override"; break;
+ case DECLARE_DATA: str = "DB/DW/etc."; break;
+ case RESERVE_SPACE: str = "RESB/RESW/etc."; break;
+ case INCBIN: str = "INCBIN"; break;
+ case EQU: str = "EQU"; break;
+ case TIMES: str = "TIMES"; break;
+ case SEG: str = "SEG"; break;
+ case WRT: str = "WRT"; break;
+ case NOSPLIT: str = "NOSPLIT"; break;
+ case STRICT: str = "STRICT"; break;
+ case INSN: str = "instruction"; break;
+ case PREFIX: str = "instruction prefix"; break;
+ case REG: str = "register"; break;
+ case REGGROUP: str = "register group"; break;
+ case SEGREG: str = "segment register"; break;
+ case TARGETMOD: str = "target modifier"; break;
+ case LEFT_OP: str = "<<"; break;
+ case RIGHT_OP: str = ">>"; break;
+ case SIGNDIV: str = "//"; break;
+ case SIGNMOD: str = "%%"; break;
+ case START_SECTION_ID: str = "$$"; break;
+ case ID: str = "identifier"; break;
+ case LOCAL_ID: str = ".identifier"; break;
+ case SPECIAL_ID: str = "..identifier"; break;
+ case NONLOCAL_ID: str = "..@identifier"; break;
+ case LINE: str = "%line"; break;
+ default:
+ strch[1] = token;
+ str = strch;
+ break;
+ }
+
+ return str;
+}
+
+static int
+expect_(yasm_parser_nasm *parser_nasm, int token)
+{
+ if (curtok == token)
+ return 1;
+
+ yasm_error_set(YASM_ERROR_PARSE, "expected %s", describe_token(token));
+ destroy_curtok();
+ return 0;
+}
+#define expect(token) expect_(parser_nasm, token)
+
+void
+nasm_parser_parse(yasm_parser_nasm *parser_nasm)
+{
+ unsigned char *line;
+ while ((line = (unsigned char *)
+ yasm_preproc_get_line(parser_nasm->preproc)) != NULL) {
+ yasm_bytecode *bc = NULL, *temp_bc;
+
+ parser_nasm->s.bot = line;
+ parser_nasm->s.tok = line;
+ parser_nasm->s.ptr = line;
+ parser_nasm->s.cur = line;
+ parser_nasm->s.lim = line + strlen((char *)line)+1;
+ parser_nasm->s.top = parser_nasm->s.lim;
+
+ get_next_token();
+ if (!is_eol()) {
+ bc = parse_line(parser_nasm);
+ demand_eol();
+ }
+
+ if (parser_nasm->abspos) {
+ /* If we're inside an absolute section, just add to the absolute
+ * position rather than appending bytecodes to a section.
+ * Only RES* are allowed in an absolute section, so this is easy.
+ */
+ if (bc) {
+ /*@null@*/ const yasm_expr *numitems, *multiple;
+ unsigned int itemsize;
+ numitems = yasm_bc_reserve_numitems(bc, &itemsize);
+ if (numitems) {
+ yasm_expr *e;
+ e = yasm_expr_create(YASM_EXPR_MUL,
+ yasm_expr_expr(yasm_expr_copy(numitems)),
+ yasm_expr_int(yasm_intnum_create_uint(itemsize)),
+ cur_line);
+ multiple = yasm_bc_get_multiple_expr(bc);
+ if (multiple)
+ e = yasm_expr_create_tree(e, YASM_EXPR_MUL,
+ yasm_expr_copy(multiple),
+ cur_line);
+ parser_nasm->abspos = yasm_expr_create_tree(
+ parser_nasm->abspos, YASM_EXPR_ADD, e, cur_line);
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("only RES* allowed within absolute section"));
+ yasm_bc_destroy(bc);
+ }
+ temp_bc = NULL;
+ } else if (bc) {
+ temp_bc = yasm_section_bcs_append(cursect, bc);
+ if (temp_bc)
+ parser_nasm->prev_bc = temp_bc;
+ } else
+ temp_bc = NULL;
+ yasm_errwarn_propagate(parser_nasm->errwarns, cur_line);
+
+ if (parser_nasm->save_input)
+ yasm_linemap_add_source(parser_nasm->linemap, temp_bc,
+ (char *)line);
+ yasm_linemap_goto_next(parser_nasm->linemap);
+ yasm_xfree(line);
+ }
+}
+
+/* All parse_* functions expect to be called with curtok being their first
+ * token. They should return with curtok being the token *after* their
+ * information.
+ */
+
+static yasm_bytecode *
+parse_line(yasm_parser_nasm *parser_nasm)
+{
+ yasm_bytecode *bc;
+
+ bc = parse_exp(parser_nasm);
+ if (bc)
+ return bc;
+
+ switch (curtok) {
+ case LINE: /* LINE INTNUM '+' INTNUM FILENAME */
+ {
+ yasm_intnum *line, *incr;
+ char *filename;
+
+ get_next_token();
+
+ if (!expect(INTNUM)) return NULL;
+ line = INTNUM_val;
+ get_next_token();
+
+ if (!expect('+')) return NULL;
+ get_next_token();
+
+ if (!expect(INTNUM)) return NULL;
+ incr = INTNUM_val;
+ get_next_token();
+
+ if (!expect(FILENAME)) return NULL;
+ filename = FILENAME_val;
+ get_next_token();
+
+ /* %line indicates the line number of the *next* line, so subtract
+ * out the increment when setting the line number.
+ */
+ yasm_linemap_set(parser_nasm->linemap, filename, 0,
+ yasm_intnum_get_uint(line) - yasm_intnum_get_uint(incr),
+ yasm_intnum_get_uint(incr));
+ yasm_intnum_destroy(line);
+ yasm_intnum_destroy(incr);
+ yasm_xfree(filename);
+ return NULL;
+ }
+ case '[': /* [ directive ] */
+ {
+ char *dirname;
+ yasm_valparamhead dir_vps;
+ int have_vps = 1;
+
+ parser_nasm->state = DIRECTIVE;
+ get_next_token();
+
+ if (!expect(DIRECTIVE_NAME))
+ return NULL;
+ dirname = DIRECTIVE_NAME_val;
+ get_next_token();
+
+ /* ignore [warning]. TODO: actually implement */
+ if (yasm__strcasecmp(dirname, "warning") == 0) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("[warning] directive not supported; ignored"));
+
+ /* throw away the rest of the directive tokens */
+ while (!is_eol() && curtok != ']')
+ {
+ destroy_curtok();
+ get_next_token();
+ }
+ expect(']');
+ get_next_token();
+ return NULL;
+ }
+
+ if (curtok == ']' || curtok == ':')
+ have_vps = 0;
+ else if (!parse_directive_valparams(parser_nasm, &dir_vps)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("invalid arguments to [%s]"), dirname);
+ yasm_xfree(dirname);
+ return NULL;
+ }
+ if (curtok == ':') {
+ yasm_valparamhead ext_vps;
+ get_next_token();
+ if (!parse_directive_valparams(parser_nasm, &ext_vps)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("invalid arguments to [%s]"), dirname);
+ yasm_xfree(dirname);
+ return NULL;
+ }
+ nasm_parser_directive(parser_nasm, dirname,
+ have_vps ? &dir_vps : NULL, &ext_vps);
+ } else
+ nasm_parser_directive(parser_nasm, dirname,
+ have_vps ? &dir_vps : NULL, NULL);
+ yasm_xfree(dirname);
+ expect(']');
+ get_next_token();
+ return NULL;
+ }
+ case TIMES: /* TIMES expr exp */
+ get_next_token();
+ return parse_times(parser_nasm);
+ case ID:
+ case SPECIAL_ID:
+ case NONLOCAL_ID:
+ case LOCAL_ID:
+ {
+ char *name = ID_val;
+ int local = parser_nasm->tasm
+ ? (curtok == ID || curtok == LOCAL_ID ||
+ (curtok == SPECIAL_ID && name[0] == '@'))
+ : (curtok != ID);
+ unsigned int size = 0;
+
+ get_next_token();
+ if (is_eol()) {
+ /* label alone on the line */
+ yasm_warn_set(YASM_WARN_ORPHAN_LABEL,
+ N_("label alone on a line without a colon might be in error"));
+ if (!local)
+ set_nonlocal_label(parser_nasm, name);
+ define_label(parser_nasm, name, 0);
+ return NULL;
+ }
+ if (curtok == ':')
+ get_next_token();
+
+ if (curtok == EQU || (parser_nasm->tasm && curtok == '=')) {
+ /* label EQU expr */
+ yasm_expr *e;
+ get_next_token();
+
+ if (parser_nasm->tasm && curtok == SIZE_OVERRIDE) {
+ size = SIZE_OVERRIDE_val;
+ get_next_token();
+ }
+
+ e = parse_expr(parser_nasm, NORM_EXPR);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected after %s"), "EQU");
+ yasm_xfree(name);
+ return NULL;
+ }
+ yasm_symtab_define_equ(p_symtab, name, e, cur_line);
+ yasm_xfree(name);
+ return NULL;
+ }
+
+ if (parser_nasm->tasm && curtok == LABEL)
+ get_next_token();
+
+ if (parser_nasm->tasm && curtok == SIZE_OVERRIDE) {
+ size = SIZE_OVERRIDE_val;
+ get_next_token();
+ }
+
+ if (!local)
+ set_nonlocal_label(parser_nasm, name);
+
+ if (is_eol()) {
+ define_label(parser_nasm, name, size);
+ return NULL;
+ }
+ if (curtok == TIMES) {
+ define_label(parser_nasm, name, size);
+ get_next_token();
+ return parse_times(parser_nasm);
+ }
+ bc = parse_exp(parser_nasm);
+ if (!parser_nasm->tasm && !bc)
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("instruction expected after label"));
+ if (parser_nasm->tasm && bc && !size)
+ size = yasm_bc_elem_size(bc);
+ define_label(parser_nasm, name, size);
+ return bc;
+ }
+ default:
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("label or instruction expected at start of line"));
+ return NULL;
+ }
+}
+
+static int
+parse_directive_valparams(yasm_parser_nasm *parser_nasm,
+ /*@out@*/ yasm_valparamhead *vps)
+{
+ yasm_vps_initialize(vps);
+ for (;;) {
+ yasm_valparam *vp;
+ yasm_expr *e;
+ char *id = NULL;
+
+ /* Look for value first */
+ if (curtok == ID) {
+ get_peek_token(parser_nasm);
+ if (parser_nasm->peek_token == '=') {
+ id = ID_val;
+ get_next_token(); /* id */
+ get_next_token(); /* '=' */
+ }
+ }
+
+ /* Look for parameter */
+ switch (curtok) {
+ case STRING:
+ vp = yasm_vp_create_string(id, STRING_val.contents);
+ get_next_token();
+ break;
+ case ID:
+ /* We need a peek token, but avoid error if we have one
+ * already; we need to work whether or not we hit the
+ * "value=" if test above.
+ *
+ * We cheat and peek ahead to see if this is just an ID or
+ * the ID is part of an expression. We assume a + or - means
+ * that it's part of an expression (e.g. "x+y" is parsed as
+ * the expression "x+y" and not as "x", "+y").
+ */
+ if (parser_nasm->peek_token == NONE)
+ get_peek_token(parser_nasm);
+ switch (parser_nasm->peek_token) {
+ case '|': case '^': case '&': case LEFT_OP: case RIGHT_OP:
+ case '+': case '-':
+ case '*': case '/': case '%': case SIGNDIV: case SIGNMOD:
+ break;
+ default:
+ /* Just an id */
+ vp = yasm_vp_create_id(id, ID_val, '$');
+ get_next_token();
+ goto next;
+ }
+ /*@fallthrough@*/
+ default:
+ e = parse_expr(parser_nasm, DIR_EXPR);
+ if (!e) {
+ yasm_vps_delete(vps);
+ return 0;
+ }
+ vp = yasm_vp_create_expr(id, e);
+ break;
+ }
+next:
+ yasm_vps_append(vps, vp);
+ if (curtok == ',')
+ get_next_token();
+ if (curtok == ']' || curtok == ':' || is_eol())
+ return 1;
+ }
+}
+
+static yasm_bytecode *
+parse_times(yasm_parser_nasm *parser_nasm)
+{
+ yasm_expr *multiple;
+ yasm_bytecode *bc;
+
+ multiple = parse_bexpr(parser_nasm, DV_EXPR);
+ if (!multiple) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("expression expected after %s"),
+ "TIMES");
+ return NULL;
+ }
+ bc = parse_exp(parser_nasm);
+ if (!bc) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("instruction expected after TIMES expression"));
+ yasm_expr_destroy(multiple);
+ return NULL;
+ }
+ yasm_bc_set_multiple(bc, multiple);
+ return bc;
+}
+
+static yasm_bytecode *
+parse_exp(yasm_parser_nasm *parser_nasm)
+{
+ yasm_bytecode *bc;
+
+ bc = parse_instr(parser_nasm);
+ if (bc)
+ return bc;
+
+ switch (curtok) {
+ case DECLARE_DATA:
+ {
+ unsigned int size = DECLARE_DATA_val/8;
+ yasm_datavalhead dvs;
+ yasm_dataval *dv;
+ yasm_expr *e, *e2;
+
+ get_next_token();
+
+ yasm_dvs_initialize(&dvs);
+ for (;;) {
+ if (curtok == STRING) {
+ /* Peek ahead to see if we're in an expr. If we're not,
+ * then generate a real string dataval.
+ */
+ get_peek_token(parser_nasm);
+ if (parser_nasm->peek_token == ','
+ || is_eol_tok(parser_nasm->peek_token)) {
+ dv = yasm_dv_create_string(STRING_val.contents,
+ STRING_val.len);
+ get_next_token();
+ goto dv_done;
+ }
+ }
+ if (curtok == '?') {
+ yasm_dvs_delete(&dvs);
+ get_next_token();
+ if (! is_eol_tok(curtok)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("can not handle more than one '?'"));
+ return NULL;
+ }
+ return yasm_bc_create_reserve(
+ p_expr_new_ident(yasm_expr_int(
+ yasm_intnum_create_uint(1))),
+ size, cur_line);
+ }
+ if (!(e = parse_bexpr(parser_nasm, DV_EXPR))) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression or string expected"));
+ yasm_dvs_delete(&dvs);
+ return NULL;
+ }
+ if (curtok == DUP) {
+ get_next_token();
+ if (curtok != '(') {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected ( after DUP"));
+ goto error;
+ }
+ get_next_token();
+ if (curtok == '?') {
+ get_next_token();
+ if (curtok != ')') {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected ) after DUPlicated expression"));
+ goto error;
+ }
+ get_next_token();
+ if (! is_eol_tok(curtok)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("can not handle more than one '?'"));
+ goto error;
+ }
+ yasm_dvs_delete(&dvs);
+ return yasm_bc_create_reserve(e, size, cur_line);
+ } else if ((e2 = parse_bexpr(parser_nasm, DV_EXPR))) {
+ if (curtok != ')') {
+ yasm_expr_destroy(e2);
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected ) after DUPlicated expression"));
+ goto error;
+ }
+ get_next_token();
+ dv = yasm_dv_create_expr(e2);
+ yasm_dv_set_multiple(dv, e);
+ } else {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression or string expected"));
+error:
+ yasm_expr_destroy(e);
+ yasm_dvs_delete(&dvs);
+ return NULL;
+ }
+ } else
+ dv = yasm_dv_create_expr(e);
+dv_done:
+ yasm_dvs_append(&dvs, dv);
+ if (is_eol())
+ break;
+ if (!expect(',')) {
+ yasm_dvs_delete(&dvs);
+ return NULL;
+ }
+ get_next_token();
+ if (is_eol()) /* allow trailing , on list */
+ break;
+ }
+ return yasm_bc_create_data(&dvs, size, 0, p_object->arch,
+ cur_line);
+ }
+ case RESERVE_SPACE:
+ {
+ unsigned int size = RESERVE_SPACE_val/8;
+ yasm_expr *e;
+ get_next_token();
+ e = parse_bexpr(parser_nasm, DV_EXPR);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected after %s"), "RESx");
+ return NULL;
+ }
+ return yasm_bc_create_reserve(e, size, cur_line);
+ }
+ case INCBIN:
+ {
+ char *filename;
+ yasm_expr *start = NULL, *maxlen = NULL;
+
+ get_next_token();
+
+ if (!expect(STRING)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("filename string expected after INCBIN"));
+ return NULL;
+ }
+ filename = STRING_val.contents;
+ get_next_token();
+
+ /* optional start expression */
+ if (curtok == ',')
+ get_next_token();
+ if (is_eol())
+ goto incbin_done;
+ start = parse_bexpr(parser_nasm, DV_EXPR);
+ if (!start) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected for INCBIN start"));
+ return NULL;
+ }
+
+ /* optional maxlen expression */
+ if (curtok == ',')
+ get_next_token();
+ if (is_eol())
+ goto incbin_done;
+ maxlen = parse_bexpr(parser_nasm, DV_EXPR);
+ if (!maxlen) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expression expected for INCBIN maximum length"));
+ return NULL;
+ }
+
+incbin_done:
+ return yasm_bc_create_incbin(filename, start, maxlen,
+ parser_nasm->linemap, cur_line);
+ }
+ default:
+ return NULL;
+ }
+}
+
+static yasm_bytecode *
+parse_instr(yasm_parser_nasm *parser_nasm)
+{
+ yasm_bytecode *bc;
+
+ switch (curtok) {
+ case INSN:
+ {
+ yasm_insn *insn;
+ bc = INSN_val;
+ insn = yasm_bc_get_insn(bc);
+
+ get_next_token();
+ if (is_eol())
+ return bc; /* no operands */
+
+ /* parse operands */
+ for (;;) {
+ yasm_insn_operand *op = parse_operand(parser_nasm);
+ if (!op) {
+ if (insn->num_operands == 0)
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("unexpected %s after instruction"),
+ describe_token(curtok));
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected operand, got %s"),
+ describe_token(curtok));
+ yasm_bc_destroy(bc);
+ return NULL;
+ }
+ yasm_insn_ops_append(insn, op);
+
+ if (is_eol())
+ break;
+ if (!expect(',')) {
+ yasm_bc_destroy(bc);
+ return NULL;
+ }
+ get_next_token();
+ }
+ return bc;
+ }
+ case PREFIX:
+ {
+ uintptr_t prefix = PREFIX_val;
+ get_next_token();
+ bc = parse_instr(parser_nasm);
+ if (!bc)
+ bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
+ yasm_insn_add_prefix(yasm_bc_get_insn(bc), prefix);
+ return bc;
+ }
+ case SEGREG:
+ {
+ uintptr_t segreg = SEGREG_val;
+ get_next_token();
+ bc = parse_instr(parser_nasm);
+ if (!bc)
+ bc = yasm_arch_create_empty_insn(p_object->arch, cur_line);
+ yasm_insn_add_seg_prefix(yasm_bc_get_insn(bc), segreg);
+ return bc;
+ }
+ default:
+ return NULL;
+ }
+}
+
+static yasm_insn_operand *
+parse_operand(yasm_parser_nasm *parser_nasm)
+{
+ yasm_insn_operand *op;
+ switch (curtok) {
+ case '[':
+ {
+ get_next_token();
+ op = parse_memaddr(parser_nasm);
+
+ expect(']');
+ get_next_token();
+
+ if (!op) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("memory address expected"));
+ return NULL;
+ }
+
+ if (parser_nasm->tasm && !is_eol() && curtok != ',') {
+ yasm_expr *e = NULL, *f;
+ yasm_effaddr *ea;
+
+ switch (op->type) {
+ case YASM_INSN__OPERAND_IMM:
+ e = op->data.val;
+ break;
+ case YASM_INSN__OPERAND_MEMORY:
+ if (op->data.ea->disp.rel) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("relative adressing not supported\n"));
+ return NULL;
+ }
+ e = yasm_expr_copy(op->data.ea->disp.abs);
+ yasm_arch_ea_destroy(p_object->arch, op->data.ea);
+ break;
+ case YASM_INSN__OPERAND_REG:
+ case YASM_INSN__OPERAND_SEGREG:
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("register adressing not supported\n"));
+ return NULL;
+ }
+ yasm_xfree(op);
+ f = parse_bexpr(parser_nasm, NORM_EXPR);
+ if (!f) {
+ yasm_expr_destroy(e);
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after ]"));
+ return NULL;
+ }
+ e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
+ ea = yasm_arch_ea_create(p_object->arch, e);
+ yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
+ op = yasm_operand_create_mem(ea);
+ }
+ return op;
+ }
+ case OFFSET:
+ {
+ yasm_insn_operand *op2;
+ get_next_token();
+ if (parser_nasm->masm && curtok == ID && !yasm__strcasecmp(ID_val, "flat")) {
+ get_next_token();
+ if (curtok == ':') {
+ get_next_token();
+ }
+ }
+ op = parse_operand(parser_nasm);
+ if (!op) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("memory address expected"));
+ return NULL;
+ }
+ if (op->type == YASM_INSN__OPERAND_IMM)
+ return op;
+ if (op->type != YASM_INSN__OPERAND_MEMORY) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("OFFSET applied to non-memory operand"));
+ return NULL;
+ }
+ if (op->data.ea->disp.rel) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("OFFSET applied to non-absolute memory operand"));
+ return NULL;
+ }
+ if (op->data.ea->disp.abs)
+ op2 = yasm_operand_create_imm(op->data.ea->disp.abs);
+ else
+ op2 = yasm_operand_create_imm(p_expr_new_ident(
+ yasm_expr_int(yasm_intnum_create_uint(0))));
+ yasm_xfree(op);
+ return op2;
+ }
+ case SEGREG:
+ {
+ uintptr_t segreg = SEGREG_val;
+ get_next_token();
+ if (parser_nasm->tasm && curtok == ':') {
+ get_next_token();
+ op = parse_operand(parser_nasm);
+ if (!op)
+ return NULL;
+ if (op->type == YASM_INSN__OPERAND_IMM) {
+ yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch,
+ op->data.val);
+ yasm_insn_operand *op2;
+ yasm_ea_set_implicit_size_segment(parser_nasm, ea,
+ op->data.val);
+ op2 = yasm_operand_create_mem(ea);
+ op2->size = op->size;
+ yasm_xfree(op);
+ op = op2;
+ }
+ if (op->type != YASM_INSN__OPERAND_MEMORY) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("segment applied to non-memory operand"));
+ return NULL;
+ }
+ yasm_ea_set_segreg(op->data.ea, segreg);
+ return op;
+ }
+ op = yasm_operand_create_segreg(segreg);
+ return op;
+ }
+ case REG:
+ op = yasm_operand_create_reg(REG_val);
+ get_next_token();
+ return op;
+ case REGGROUP:
+ {
+ unsigned long regindex;
+ uintptr_t reg = REGGROUP_val;
+ get_next_token(); /* REGGROUP */
+ if (curtok != '(')
+ return yasm_operand_create_reg(reg);
+ get_next_token(); /* '(' */
+ if (!expect(INTNUM)) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("integer register index expected"));
+ return NULL;
+ }
+ regindex = yasm_intnum_get_uint(INTNUM_val);
+ get_next_token(); /* INTNUM */
+ if (!expect(')')) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("missing closing parenthesis for register index"));
+ return NULL;
+ }
+ get_next_token(); /* ')' */
+ reg = yasm_arch_reggroup_get_reg(p_object->arch, reg, regindex);
+ if (reg == 0) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("bad register index `%u'"),
+ regindex);
+ return NULL;
+ }
+ return yasm_operand_create_reg(reg);
+ }
+ case STRICT:
+ get_next_token();
+ op = parse_operand(parser_nasm);
+ if (op)
+ op->strict = 1;
+ return op;
+ case SIZE_OVERRIDE:
+ {
+ unsigned int size = SIZE_OVERRIDE_val;
+ get_next_token();
+ if (parser_nasm->masm && curtok == ID && !yasm__strcasecmp(ID_val, "ptr")) {
+ get_next_token();
+ }
+ op = parse_operand(parser_nasm);
+ if (!op)
+ return NULL;
+ if (op->type == YASM_INSN__OPERAND_REG &&
+ yasm_arch_get_reg_size(p_object->arch, op->data.reg) != size)
+ yasm_error_set(YASM_ERROR_TYPE,
+ N_("cannot override register size"));
+ else {
+ /* Silently override others unless a warning is turned on.
+ * This is to allow overrides such as:
+ * %define arg1 dword [bp+4]
+ * cmp word arg1, 2
+ * Which expands to:
+ * cmp word dword [bp+4], 2
+ */
+ if (op->size != 0) {
+ if (op->size != size)
+ yasm_warn_set(YASM_WARN_SIZE_OVERRIDE,
+ N_("overriding operand size from %u-bit to %u-bit"),
+ op->size, size);
+ else
+ yasm_warn_set(YASM_WARN_SIZE_OVERRIDE,
+ N_("double operand size override"));
+ }
+ op->size = size;
+ }
+ return op;
+ }
+ case TARGETMOD:
+ {
+ uintptr_t tmod = TARGETMOD_val;
+ get_next_token();
+ op = parse_operand(parser_nasm);
+ if (op)
+ op->targetmod = tmod;
+ return op;
+ }
+ case ID:
+ case LOCAL_ID:
+ case NONLOCAL_ID:
+ if (parser_nasm->tasm) {
+ get_peek_token(parser_nasm);
+ if (parser_nasm->peek_token == '[') {
+ yasm_symrec *sym = yasm_symtab_use(p_symtab, ID_val,
+ cur_line);
+ yasm_expr *e = p_expr_new_ident(yasm_expr_sym(sym)), *f;
+ yasm_effaddr *ea;
+ yasm_xfree(ID_val);
+ get_next_token();
+ get_next_token();
+ f = parse_bexpr(parser_nasm, NORM_EXPR);
+ if (!f) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after ["));
+ return NULL;
+ }
+ e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
+ if (!expect(']')) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("missing closing bracket"));
+ return NULL;
+ }
+ get_next_token();
+ ea = yasm_arch_ea_create(p_object->arch, e);
+ yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
+ op = yasm_operand_create_mem(ea);
+ return op;
+ }
+ }
+ /* Fallthrough */
+ default:
+ {
+ yasm_expr *e = parse_bexpr(parser_nasm, NORM_EXPR);
+ if (!e)
+ return NULL;
+ if (curtok != ':') {
+ if (parser_nasm->tasm && yasm_expr_size(e)) {
+ yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch, e);
+ yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
+ op = yasm_operand_create_mem(ea);
+ return op;
+ } else if (curtok == '[') {
+ yasm_expr *f;
+ yasm_effaddr *ea;
+ yasm_insn_operand *op2;
+
+ op = parse_operand(parser_nasm);
+ if (!op)
+ return NULL;
+
+ f = op->data.ea->disp.abs;
+ e = p_expr_new_tree(e, YASM_EXPR_ADD, f);
+ ea = yasm_arch_ea_create(p_object->arch, e);
+ yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
+ op2 = yasm_operand_create_mem(ea);
+
+ yasm_xfree(op);
+
+ return op2;
+ } else {
+ return yasm_operand_create_imm(e);
+ }
+ } else {
+ yasm_expr *off;
+ get_next_token();
+ off = parse_bexpr(parser_nasm, NORM_EXPR);
+ if (!off) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+ op = yasm_operand_create_imm(off);
+ op->seg = e;
+ return op;
+ }
+ }
+ }
+}
+
+/* memory addresses */
+static yasm_insn_operand *
+parse_memaddr(yasm_parser_nasm *parser_nasm)
+{
+ yasm_insn_operand *op;
+ switch (curtok) {
+ case SEGREG:
+ {
+ uintptr_t segreg = SEGREG_val;
+ get_next_token();
+ if (!expect(':')) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("`:' required after segment register"));
+ return NULL;
+ }
+ get_next_token();
+ op = parse_memaddr(parser_nasm);
+ if (op)
+ yasm_ea_set_segreg(op->data.ea, segreg);
+ return op;
+ }
+ case SIZE_OVERRIDE:
+ {
+ unsigned int size = SIZE_OVERRIDE_val;
+ get_next_token();
+ op = parse_memaddr(parser_nasm);
+ if (op)
+ op->data.ea->disp.size = size;
+ return op;
+ }
+ case NOSPLIT:
+ get_next_token();
+ op = parse_memaddr(parser_nasm);
+ if (op)
+ op->data.ea->nosplit = 1;
+ return op;
+ case REL:
+ get_next_token();
+ op = parse_memaddr(parser_nasm);
+ if (op) {
+ op->data.ea->pc_rel = 1;
+ op->data.ea->not_pc_rel = 0;
+ }
+ return op;
+ case ABS:
+ get_next_token();
+ op = parse_memaddr(parser_nasm);
+ if (op) {
+ op->data.ea->pc_rel = 0;
+ op->data.ea->not_pc_rel = 1;
+ }
+ return op;
+ default:
+ {
+ yasm_expr *e = parse_bexpr(parser_nasm, NORM_EXPR);
+ if (!e)
+ return NULL;
+ if (curtok != ':') {
+ yasm_effaddr *ea = yasm_arch_ea_create(p_object->arch, e);
+ yasm_ea_set_implicit_size_segment(parser_nasm, ea, e);
+ return yasm_operand_create_mem(ea);
+ } else {
+ yasm_effaddr *ea;
+ yasm_expr *off;
+ get_next_token();
+ off = parse_bexpr(parser_nasm, NORM_EXPR);
+ if (!off) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+ ea = yasm_arch_ea_create(p_object->arch, off);
+ yasm_ea_set_implicit_size_segment(parser_nasm, ea, off);
+ op = yasm_operand_create_mem(ea);
+ op->seg = e;
+ return op;
+ }
+ }
+ }
+}
+
+/* Expression grammar parsed is:
+ *
+ * expr : bexpr [ : bexpr ]
+ * bexpr : expr0 [ WRT expr6 ]
+ * expr0 : expr1 [ {|} expr1...]
+ * expr1 : expr2 [ {^} expr2...]
+ * expr2 : expr3 [ {&} expr3...]
+ * expr3 : expr4 [ {<<,>>} expr4...]
+ * expr4 : expr5 [ {+,-} expr5...]
+ * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
+ * expr6 : { ~,+,-,SEG } expr6
+ * | (expr)
+ * | symbol
+ * | $
+ * | number
+ */
+
+#define parse_expr_common(leftfunc, tok, rightfunc, op) \
+ do { \
+ yasm_expr *e, *f; \
+ e = leftfunc(parser_nasm, type); \
+ if (!e) \
+ return NULL; \
+ \
+ while (curtok == tok) { \
+ get_next_token(); \
+ f = rightfunc(parser_nasm, type); \
+ if (!f) { \
+ yasm_error_set(YASM_ERROR_SYNTAX, \
+ N_("expected expression after %s"), \
+ describe_token(op)); \
+ yasm_expr_destroy(e); \
+ return NULL; \
+ } \
+ e = p_expr_new_tree(e, op, f); \
+ } \
+ return e; \
+ } while(0)
+
+static yasm_expr *
+parse_expr(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ switch (type) {
+ case DIR_EXPR:
+ /* directive expressions can't handle seg:off or WRT */
+ return parse_expr0(parser_nasm, type);
+ default:
+ parse_expr_common(parse_bexpr, ':', parse_bexpr, YASM_EXPR_SEGOFF);
+ }
+ /*@notreached@*/
+ return NULL;
+}
+
+static yasm_expr *
+parse_bexpr(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ parse_expr_common(parse_expr0, WRT, parse_expr6, YASM_EXPR_WRT);
+}
+
+static yasm_expr *
+parse_expr0(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ parse_expr_common(parse_expr1, '|', parse_expr1, YASM_EXPR_OR);
+}
+
+static yasm_expr *
+parse_expr1(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ parse_expr_common(parse_expr2, '^', parse_expr2, YASM_EXPR_XOR);
+}
+
+static yasm_expr *
+parse_expr2(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ parse_expr_common(parse_expr3, '&', parse_expr3, YASM_EXPR_AND);
+}
+
+static yasm_expr *
+parse_expr3(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ yasm_expr *e, *f;
+ e = parse_expr4(parser_nasm, type);
+ if (!e)
+ return NULL;
+
+ while (curtok == LEFT_OP || curtok == RIGHT_OP) {
+ int op = curtok;
+ get_next_token();
+ f = parse_expr4(parser_nasm, type);
+ if (!f) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"),
+ describe_token(op));
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (op) {
+ case LEFT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHL, f); break;
+ case RIGHT_OP: e = p_expr_new_tree(e, YASM_EXPR_SHR, f); break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *
+parse_expr4(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ yasm_expr *e, *f;
+ e = parse_expr5(parser_nasm, type);
+ if (!e)
+ return NULL;
+
+ while (curtok == '+' || curtok == '-') {
+ int op = curtok;
+ get_next_token();
+ f = parse_expr5(parser_nasm, type);
+ if (!f) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"),
+ describe_token(op));
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (op) {
+ case '+': e = p_expr_new_tree(e, YASM_EXPR_ADD, f); break;
+ case '-': e = p_expr_new_tree(e, YASM_EXPR_SUB, f); break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *
+parse_expr5(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ yasm_expr *e, *f;
+ e = parse_expr6(parser_nasm, type);
+ if (!e)
+ return NULL;
+
+ while (curtok == '*' || curtok == '/' || curtok == '%'
+ || curtok == SIGNDIV || curtok == SIGNMOD) {
+ int op = curtok;
+ get_next_token();
+ f = parse_expr6(parser_nasm, type);
+ if (!f) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"),
+ describe_token(op));
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (op) {
+ case '*': e = p_expr_new_tree(e, YASM_EXPR_MUL, f); break;
+ case '/': e = p_expr_new_tree(e, YASM_EXPR_DIV, f); break;
+ case '%': e = p_expr_new_tree(e, YASM_EXPR_MOD, f); break;
+ case SIGNDIV: e = p_expr_new_tree(e, YASM_EXPR_SIGNDIV, f); break;
+ case SIGNMOD: e = p_expr_new_tree(e, YASM_EXPR_SIGNMOD, f); break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *
+parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type)
+{
+ yasm_expr *e;
+ yasm_symrec *sym;
+
+ switch (curtok) {
+ case '+':
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"), "`+'");
+ }
+ return e;
+ case '-':
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"), "`-'");
+ return NULL;
+ }
+ return p_expr_new_branch(YASM_EXPR_NEG, e);
+ case '~':
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"), "`~'");
+ return NULL;
+ }
+ return p_expr_new_branch(YASM_EXPR_NOT, e);
+ case LOW:
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"), "LOW");
+ return NULL;
+ }
+ return p_expr_new_tree(e, YASM_EXPR_AND,
+ p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0xff))));
+ case HIGH:
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"), "HIGH");
+ return NULL;
+ }
+ return p_expr_new_tree(
+ p_expr_new_tree(e, YASM_EXPR_SHR,
+ p_expr_new_ident(yasm_expr_int(
+ yasm_intnum_create_uint(8)))),
+ YASM_EXPR_AND,
+ p_expr_new_ident(yasm_expr_int(yasm_intnum_create_uint(0xff))));
+ case SEG:
+ get_next_token();
+ e = parse_expr6(parser_nasm, type);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"), "SEG");
+ return NULL;
+ }
+ return p_expr_new_branch(YASM_EXPR_SEG, e);
+ case '(':
+ get_next_token();
+ e = parse_expr(parser_nasm, type);
+ if (!e) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("expected expression after %s"), "`('");
+ return NULL;
+ }
+ if (!expect(')')) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("missing parenthesis"));
+ return NULL;
+ }
+ get_next_token();
+ return e;
+ case INTNUM:
+ e = p_expr_new_ident(yasm_expr_int(INTNUM_val));
+ get_next_token();
+ return e;
+ case REG:
+ if (type == DV_EXPR) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("data values can't have registers"));
+ return NULL;
+ }
+ e = p_expr_new_ident(yasm_expr_reg(REG_val));
+ get_next_token();
+ return e;
+ }
+
+ /* directives allow very little and handle IDs specially */
+ if (type == DIR_EXPR) {
+ switch (curtok) {
+ case ID:
+ sym = yasm_symtab_use(p_symtab, ID_val, cur_line);
+ e = p_expr_new_ident(yasm_expr_sym(sym));
+ yasm_xfree(ID_val);
+ break;
+ default:
+ return NULL;
+ }
+ } else switch (curtok) {
+ case FLTNUM:
+ e = p_expr_new_ident(yasm_expr_float(FLTNUM_val));
+ break;
+ case STRING:
+ {
+ yasm_intnum *intn;
+ if (parser_nasm->tasm)
+ intn = yasm_intnum_create_charconst_tasm(STRING_val.contents);
+ else
+ intn = yasm_intnum_create_charconst_nasm(STRING_val.contents);
+ e = p_expr_new_ident(yasm_expr_int(intn));
+ yasm_xfree(STRING_val.contents);
+ break;
+ }
+ case SPECIAL_ID:
+ sym = yasm_objfmt_get_special_sym(p_object, ID_val+2, "nasm");
+ if (sym) {
+ e = p_expr_new_ident(yasm_expr_sym(sym));
+ yasm_xfree(ID_val);
+ break;
+ }
+ /*@fallthrough@*/
+ case ID:
+ case LOCAL_ID:
+ case NONLOCAL_ID:
+ sym = yasm_symtab_use(p_symtab, ID_val, cur_line);
+ e = p_expr_new_ident(yasm_expr_sym(sym));
+ yasm_xfree(ID_val);
+ break;
+ case '$':
+ /* "$" references the current assembly position */
+ if (parser_nasm->abspos)
+ e = yasm_expr_copy(parser_nasm->abspos);
+ else {
+ sym = yasm_symtab_define_curpos(p_symtab, "$",
+ parser_nasm->prev_bc, cur_line);
+ e = p_expr_new_ident(yasm_expr_sym(sym));
+ }
+ break;
+ case START_SECTION_ID:
+ /* "$$" references the start of the current section */
+ if (parser_nasm->absstart)
+ e = yasm_expr_copy(parser_nasm->absstart);
+ else {
+ sym = yasm_symtab_define_label(p_symtab, "$$",
+ yasm_section_bcs_first(cursect), 0, cur_line);
+ e = p_expr_new_ident(yasm_expr_sym(sym));
+ }
+ break;
+ default:
+ return NULL;
+ }
+
+ get_next_token();
+ return e;
+}
+
+static void
+set_nonlocal_label(yasm_parser_nasm *parser_nasm, const char *name)
+{
+ if (!parser_nasm->tasm || tasm_locals) {
+ if (parser_nasm->locallabel_base)
+ yasm_xfree(parser_nasm->locallabel_base);
+ parser_nasm->locallabel_base_len = strlen(name);
+ parser_nasm->locallabel_base =
+ yasm_xmalloc(parser_nasm->locallabel_base_len+1);
+ strcpy(parser_nasm->locallabel_base, name);
+ }
+}
+
+static void
+define_label(yasm_parser_nasm *parser_nasm, char *name, unsigned int size)
+{
+ yasm_symrec *symrec;
+
+ if (parser_nasm->abspos)
+ symrec = yasm_symtab_define_equ(p_symtab, name,
+ yasm_expr_copy(parser_nasm->abspos),
+ cur_line);
+ else
+ symrec = yasm_symtab_define_label(p_symtab, name, parser_nasm->prev_bc,
+ 1, cur_line);
+
+ yasm_symrec_set_size(symrec, size);
+ yasm_symrec_set_segment(symrec, tasm_segment);
+
+ yasm_xfree(name);
+}
+
+static void
+dir_align(yasm_object *object, yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams, unsigned long line)
+{
+ yasm_valparam *vp = yasm_vps_first(valparams);
+ yasm_expr *boundval = yasm_vp_expr(vp, object->symtab, line);
+ /*@depedent@*/ yasm_intnum *boundintn;
+
+ /* Largest .align in the section specifies section alignment.
+ * Note: this doesn't match NASM behavior, but is a lot more
+ * intelligent!
+ */
+ if (boundval && (boundintn = yasm_expr_get_intnum(&boundval, 0))) {
+ unsigned long boundint = yasm_intnum_get_uint(boundintn);
+
+ /* Alignments must be a power of two. */
+ if (is_exp2(boundint)) {
+ if (boundint > yasm_section_get_align(object->cur_section))
+ yasm_section_set_align(object->cur_section, boundint, line);
+ }
+ }
+
+ /* As this directive is called only when nop is used as fill, always
+ * use arch (nop) fill.
+ */
+ yasm_section_bcs_append(object->cur_section,
+ yasm_bc_create_align(boundval, NULL, NULL,
+ /*yasm_section_is_code(object->cur_section) ?*/
+ yasm_arch_get_fill(object->arch)/* : NULL*/,
+ line));
+}
+
+static void
+nasm_parser_directive(yasm_parser_nasm *parser_nasm, const char *name,
+ yasm_valparamhead *valparams,
+ yasm_valparamhead *objext_valparams)
+{
+ unsigned long line = cur_line;
+ yasm_valparam *vp;
+
+ if (!yasm_object_directive(p_object, name, "nasm", valparams,
+ objext_valparams, line))
+ ;
+ else if (yasm__strcasecmp(name, "absolute") == 0) {
+ if (!valparams) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("directive `%s' requires an argument"),
+ "absolute");
+ } else {
+ vp = yasm_vps_first(valparams);
+ if (parser_nasm->absstart)
+ yasm_expr_destroy(parser_nasm->absstart);
+ if (parser_nasm->abspos)
+ yasm_expr_destroy(parser_nasm->abspos);
+ parser_nasm->absstart = yasm_vp_expr(vp, p_object->symtab, line);
+ parser_nasm->abspos = yasm_expr_copy(parser_nasm->absstart);
+ cursect = NULL;
+ parser_nasm->prev_bc = NULL;
+ }
+ } else if (yasm__strcasecmp(name, "align") == 0) {
+ /* Really, we shouldn't end up with an align directive in an absolute
+ * section (as it's supposed to be only used for nop fill), but handle
+ * it gracefully anyway.
+ */
+ if (parser_nasm->abspos) {
+ yasm_expr *boundval, *e;
+ vp = yasm_vps_first(valparams);
+ boundval = yasm_vp_expr(vp, p_object->symtab, line);
+ e = yasm_expr_create_tree(
+ yasm_expr_create_tree(yasm_expr_copy(parser_nasm->absstart),
+ YASM_EXPR_SUB,
+ yasm_expr_copy(parser_nasm->abspos),
+ cur_line),
+ YASM_EXPR_AND,
+ yasm_expr_create(YASM_EXPR_SUB, yasm_expr_expr(boundval),
+ yasm_expr_int(yasm_intnum_create_uint(1)),
+ cur_line),
+ cur_line);
+ parser_nasm->abspos = yasm_expr_create_tree(
+ parser_nasm->abspos, YASM_EXPR_ADD, e, cur_line);
+ } else if (!valparams) {
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("directive `%s' requires an argument"), "align");
+ } else
+ dir_align(p_object, valparams, objext_valparams, line);
+ } else if (yasm__strcasecmp(name, "default") == 0) {
+ if (!valparams)
+ ;
+ else {
+ vp = yasm_vps_first(valparams);
+ while (vp) {
+ const char *id = yasm_vp_id(vp);
+ if (id) {
+ if (yasm__strcasecmp(id, "rel") == 0)
+ yasm_arch_set_var(p_object->arch, "default_rel", 1);
+ else if (yasm__strcasecmp(id, "abs") == 0)
+ yasm_arch_set_var(p_object->arch, "default_rel", 0);
+ else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("unrecognized default `%s'"), id);
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX,
+ N_("unrecognized default value"));
+ vp = yasm_vps_next(vp);
+ }
+ }
+ } else
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("unrecognized directive `%s'"),
+ name);
+
+ if (parser_nasm->absstart && cursect) {
+ /* We switched to a new section. Get out of absolute section mode. */
+ yasm_expr_destroy(parser_nasm->absstart);
+ parser_nasm->absstart = NULL;
+ if (parser_nasm->abspos) {
+ yasm_expr_destroy(parser_nasm->abspos);
+ parser_nasm->abspos = NULL;
+ }
+ }
+
+ if (cursect) {
+ /* In case cursect changed or a bytecode was added, update prev_bc. */
+ parser_nasm->prev_bc = yasm_section_bcs_last(cursect);
+ }
+
+ if (valparams)
+ yasm_vps_delete(valparams);
+ if (objext_valparams)
+ yasm_vps_delete(objext_valparams);
+}
+
+yasm_bytecode *
+gas_intel_syntax_parse_instr(yasm_parser_nasm *parser_nasm, unsigned char *instr)
+{
+ yasm_bytecode *bc = NULL;
+ char *sinstr = (char *) instr;
+
+ parser_nasm->s.bot = instr;
+ parser_nasm->s.tok = instr;
+ parser_nasm->s.ptr = instr;
+ parser_nasm->s.cur = instr;
+ parser_nasm->s.lim = instr + strlen(sinstr) + 1;
+ parser_nasm->s.top = parser_nasm->s.lim;
+ parser_nasm->peek_token = NONE;
+
+ get_next_token();
+ if (!is_eol()) {
+ bc = parse_instr(parser_nasm);
+ }
+
+ return bc;
+}
diff --git a/contrib/tools/yasm/modules/parsers/nasm/nasm-parser-struct.h b/contrib/tools/yasm/modules/parsers/nasm/nasm-parser-struct.h
new file mode 100644
index 0000000000..b9223510ba
--- /dev/null
+++ b/contrib/tools/yasm/modules/parsers/nasm/nasm-parser-struct.h
@@ -0,0 +1,85 @@
+/*
+ * NASM-compatible parser struct header file
+ *
+ * Copyright (C) 2002-2007 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.
+ */
+#ifndef YASM_NASM_PARSER_STRUCT_H
+#define YASM_NASM_PARSER_STRUCT_H
+
+typedef union {
+ unsigned int int_info;
+ char *str_val;
+ yasm_intnum *intn;
+ yasm_floatnum *flt;
+ yasm_bytecode *bc;
+ uintptr_t arch_data;
+ struct {
+ char *contents;
+ size_t len;
+ } str;
+} nasm_yystype;
+
+typedef struct yasm_parser_nasm {
+ int tasm;
+ int masm;
+
+ /*@only@*/ yasm_object *object;
+
+ /* last "base" label for local (.) labels */
+ /*@null@*/ char *locallabel_base;
+ size_t locallabel_base_len;
+
+ /*@dependent@*/ yasm_preproc *preproc;
+ /*@dependent@*/ yasm_errwarns *errwarns;
+
+ /*@dependent@*/ yasm_linemap *linemap;
+
+ /*@null@*/ yasm_bytecode *prev_bc;
+
+ int save_input;
+
+ yasm_scanner s;
+ int state;
+
+ int token; /* enum tokentype or any character */
+ nasm_yystype tokval;
+ char tokch; /* first character of token */
+
+ /* one token of lookahead; used sparingly */
+ int peek_token; /* NONE if none */
+ nasm_yystype peek_tokval;
+ char peek_tokch;
+
+ /* Starting point of the absolute section. NULL if not in an absolute
+ * section.
+ */
+ /*@null@*/ yasm_expr *absstart;
+
+ /* Current location inside an absolute section (including the start).
+ * NULL if not in an absolute section.
+ */
+ /*@null@*/ yasm_expr *abspos;
+} yasm_parser_nasm;
+
+#endif
diff --git a/contrib/tools/yasm/modules/parsers/nasm/nasm-parser.c b/contrib/tools/yasm/modules/parsers/nasm/nasm-parser.c
new file mode 100644
index 0000000000..bd166929f7
--- /dev/null
+++ b/contrib/tools/yasm/modules/parsers/nasm/nasm-parser.c
@@ -0,0 +1,140 @@
+/*
+ * NASM-compatible parser
+ *
+ * Copyright (C) 2001-2007 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 <util.h>
+
+#include <libyasm.h>
+
+#include "nasm-parser.h"
+
+
+static void
+nasm_do_parse(yasm_object *object, yasm_preproc *pp, int save_input,
+ yasm_linemap *linemap, yasm_errwarns *errwarns, int tasm)
+{
+ yasm_parser_nasm parser_nasm;
+
+ parser_nasm.tasm = tasm;
+ parser_nasm.masm = 0;
+
+ parser_nasm.object = object;
+ parser_nasm.linemap = linemap;
+
+ parser_nasm.locallabel_base = (char *)NULL;
+ parser_nasm.locallabel_base_len = 0;
+
+ parser_nasm.preproc = pp;
+ parser_nasm.errwarns = errwarns;
+
+ parser_nasm.prev_bc = yasm_section_bcs_first(object->cur_section);
+
+ parser_nasm.save_input = save_input;
+
+ parser_nasm.peek_token = NONE;
+
+ parser_nasm.absstart = NULL;
+ parser_nasm.abspos = NULL;
+
+ /* initialize scanner structure */
+ yasm_scanner_initialize(&parser_nasm.s);
+
+ parser_nasm.state = INITIAL;
+
+ nasm_parser_parse(&parser_nasm);
+
+ /*yasm_scanner_delete(&parser_nasm.s);*/
+
+ /* Free locallabel base if necessary */
+ if (parser_nasm.locallabel_base)
+ yasm_xfree(parser_nasm.locallabel_base);
+
+ /* Check for undefined symbols */
+ yasm_symtab_parser_finalize(object->symtab, 0, errwarns);
+}
+
+static void
+nasm_parser_do_parse(yasm_object *object, yasm_preproc *pp,
+ int save_input, yasm_linemap *linemap,
+ yasm_errwarns *errwarns)
+{
+ nasm_do_parse(object, pp, save_input, linemap, errwarns, 0);
+}
+
+#include "nasm-macros.c"
+
+/* Define valid preprocessors to use with this parser */
+static const char *nasm_parser_preproc_keywords[] = {
+ "raw",
+ "nasm",
+ NULL
+};
+
+static const yasm_stdmac nasm_parser_stdmacs[] = {
+ { "nasm", "nasm", nasm_standard_mac },
+ { NULL, NULL, NULL }
+};
+
+/* Define parser structure -- see parser.h for details */
+yasm_parser_module yasm_nasm_LTX_parser = {
+ "NASM-compatible parser",
+ "nasm",
+ nasm_parser_preproc_keywords,
+ "nasm",
+ nasm_parser_stdmacs,
+ nasm_parser_do_parse
+};
+
+static void
+tasm_parser_do_parse(yasm_object *object, yasm_preproc *pp,
+ int save_input, yasm_linemap *linemap,
+ yasm_errwarns *errwarns)
+{
+ yasm_symtab_set_case_sensitive(object->symtab, 0);
+ yasm_warn_disable(YASM_WARN_IMPLICIT_SIZE_OVERRIDE);
+ nasm_do_parse(object, pp, save_input, linemap, errwarns, 1);
+}
+
+/* Define valid preprocessors to use with this parser */
+static const char *tasm_parser_preproc_keywords[] = {
+ "raw",
+ "tasm",
+ NULL
+};
+
+static const yasm_stdmac tasm_parser_stdmacs[] = {
+ { "tasm", "tasm", nasm_standard_mac },
+ { NULL, NULL, NULL }
+};
+
+/* Define parser structure -- see parser.h for details */
+yasm_parser_module yasm_tasm_LTX_parser = {
+ "TASM-compatible parser",
+ "tasm",
+ tasm_parser_preproc_keywords,
+ "tasm",
+ tasm_parser_stdmacs,
+ tasm_parser_do_parse
+};
diff --git a/contrib/tools/yasm/modules/parsers/nasm/nasm-parser.h b/contrib/tools/yasm/modules/parsers/nasm/nasm-parser.h
new file mode 100644
index 0000000000..dc19cfb5e0
--- /dev/null
+++ b/contrib/tools/yasm/modules/parsers/nasm/nasm-parser.h
@@ -0,0 +1,123 @@
+/*
+ * NASM-compatible parser header file
+ *
+ * Copyright (C) 2002-2007 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.
+ */
+#ifndef YASM_NASM_PARSER_H
+#define YASM_NASM_PARSER_H
+
+#include "nasm-parser-struct.h"
+
+#define YYCTYPE unsigned char
+
+#define MAX_SAVED_LINE_LEN 80
+
+enum tokentype {
+ INTNUM = 258,
+ FLTNUM,
+ DIRECTIVE_NAME,
+ FILENAME,
+ STRING,
+ SIZE_OVERRIDE,
+ OFFSET,
+ DECLARE_DATA,
+ RESERVE_SPACE,
+ LABEL,
+ INCBIN,
+ EQU,
+ TIMES,
+ DUP,
+ SEG,
+ WRT,
+ ABS,
+ REL,
+ NOSPLIT,
+ STRICT,
+ INSN,
+ PREFIX,
+ REG,
+ REGGROUP,
+ SEGREG,
+ TARGETMOD,
+ LEFT_OP,
+ RIGHT_OP,
+ LOW,
+ HIGH,
+ SIGNDIV,
+ SIGNMOD,
+ START_SECTION_ID,
+ ID,
+ LOCAL_ID,
+ SPECIAL_ID,
+ NONLOCAL_ID,
+ LINE,
+ NONE /* special token for lookahead */
+};
+
+enum nasm_parser_state {
+ INITIAL,
+ DIRECTIVE,
+ SECTION_DIRECTIVE,
+ DIRECTIVE2,
+ LINECHG,
+ LINECHG2,
+ INSTRUCTION
+};
+
+#define YYSTYPE nasm_yystype
+
+/* shorter access names to commonly used parser_nasm fields */
+#define p_object (parser_nasm->object)
+#define p_symtab (parser_nasm->object->symtab)
+#define cursect (parser_nasm->object->cur_section)
+#define curtok (parser_nasm->token)
+#define curval (parser_nasm->tokval)
+
+#define INTNUM_val (curval.intn)
+#define FLTNUM_val (curval.flt)
+#define DIRECTIVE_NAME_val (curval.str_val)
+#define FILENAME_val (curval.str_val)
+#define STRING_val (curval.str)
+#define SIZE_OVERRIDE_val (curval.int_info)
+#define DECLARE_DATA_val (curval.int_info)
+#define RESERVE_SPACE_val (curval.int_info)
+#define INSN_val (curval.bc)
+#define PREFIX_val (curval.arch_data)
+#define REG_val (curval.arch_data)
+#define REGGROUP_val (curval.arch_data)
+#define SEGREG_val (curval.arch_data)
+#define TARGETMOD_val (curval.arch_data)
+#define ID_val (curval.str_val)
+
+#define cur_line (yasm_linemap_get_current(parser_nasm->linemap))
+
+#define p_expr_new_tree(l,o,r) yasm_expr_create_tree(l,o,r,cur_line)
+#define p_expr_new_branch(o,r) yasm_expr_create_branch(o,r,cur_line)
+#define p_expr_new_ident(r) yasm_expr_create_ident(r,cur_line)
+
+void nasm_parser_parse(yasm_parser_nasm *parser_nasm);
+void nasm_parser_cleanup(yasm_parser_nasm *parser_nasm);
+int nasm_parser_lex(YYSTYPE *lvalp, yasm_parser_nasm *parser_nasm);
+
+#endif
diff --git a/contrib/tools/yasm/modules/preprocs/cpp/cpp-preproc.c b/contrib/tools/yasm/modules/preprocs/cpp/cpp-preproc.c
new file mode 100644
index 0000000000..663f726cc7
--- /dev/null
+++ b/contrib/tools/yasm/modules/preprocs/cpp/cpp-preproc.c
@@ -0,0 +1,402 @@
+/*
+ * Invoke an external C preprocessor
+ *
+ * Copyright (C) 2007 Paul Barker
+ * Copyright (C) 2001-2007 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 <util.h>
+#include <libyasm.h>
+
+/* TODO: Use autoconf to get the limit on the command line length. */
+#define CMDLINE_SIZE 32770
+
+#define BSIZE 512
+
+/* Pre-declare the preprocessor module object. */
+yasm_preproc_module yasm_cpp_LTX_preproc;
+
+/*******************************************************************************
+ Structures.
+*******************************************************************************/
+
+/* An entry in a list of arguments to pass to cpp. */
+typedef struct cpp_arg_entry {
+ TAILQ_ENTRY(cpp_arg_entry) entry;
+
+ /*
+ The operator (eg "-I") and the parameter (eg "include/"). op is expected
+ to point to a string literal, whereas param is expected to be a copy of
+ the parameter which is free'd when no-longer needed (in
+ cpp_preproc_destroy()).
+ */
+ const char *op;
+ char *param;
+} cpp_arg_entry;
+
+typedef struct yasm_preproc_cpp {
+ yasm_preproc_base preproc; /* base structure */
+
+ /* List of arguments to pass to cpp. */
+ TAILQ_HEAD(cpp_arg_head, cpp_arg_entry) cpp_args;
+
+ char *filename;
+ FILE *f, *f_deps;
+ yasm_linemap *cur_lm;
+ yasm_errwarns *errwarns;
+
+ int flags;
+} yasm_preproc_cpp;
+
+/* Flag values for yasm_preproc_cpp->flags. */
+#define CPP_HAS_BEEN_INVOKED 0x01
+#define CPP_HAS_GENERATED_DEPS 0x02
+
+/*******************************************************************************
+ Internal functions and helpers.
+*******************************************************************************/
+
+/*
+ Append a string to the command line, ensuring that we don't overflow the
+ buffer.
+*/
+#define APPEND(s) do { \
+ size_t _len = strlen(s); \
+ if (p + _len >= limit) \
+ yasm__fatal(N_("command line too long!")); \
+ strcpy(p, s); \
+ p += _len; \
+} while (0)
+
+/*
+ Put all the options together into a command line that can be used to invoke
+ cpp.
+*/
+static char *
+cpp_build_cmdline(yasm_preproc_cpp *pp, const char *extra)
+{
+ char *cmdline, *p, *limit;
+ cpp_arg_entry *arg;
+
+ /* Initialize command line. */
+ cmdline = p = yasm_xmalloc(strlen(CPP_PROG)+CMDLINE_SIZE);
+ limit = p + CMDLINE_SIZE;
+ strcpy(p, CPP_PROG);
+ p += strlen(CPP_PROG);
+
+ arg = TAILQ_FIRST(&pp->cpp_args);
+
+ /* Append arguments from the list. */
+ while ( arg ) {
+ APPEND(" ");
+ APPEND(arg->op);
+ APPEND(" ");
+ APPEND(arg->param);
+
+ arg = TAILQ_NEXT(arg, entry);
+ }
+
+ /* Append extra arguments. */
+ if (extra) {
+ APPEND(" ");
+ APPEND(extra);
+ }
+ /* Append final arguments. */
+ APPEND(" -x assembler-with-cpp ");
+ APPEND(pp->filename);
+
+ return cmdline;
+}
+
+/* Invoke the c preprocessor. */
+static void
+cpp_invoke(yasm_preproc_cpp *pp)
+{
+ char *cmdline;
+
+ cmdline = cpp_build_cmdline(pp, NULL);
+
+#ifdef HAVE_POPEN
+ pp->f = popen(cmdline, "r");
+ if (!pp->f)
+ yasm__fatal( N_("Failed to execute preprocessor") );
+#else
+ yasm__fatal( N_("Cannot execute preprocessor, no popen available") );
+#endif
+
+ yasm_xfree(cmdline);
+}
+
+/* Free memory used by the list of arguments. */
+static void
+cpp_destroy_args(yasm_preproc_cpp *pp)
+{
+ cpp_arg_entry *arg;
+
+ while ( (arg = TAILQ_FIRST(&pp->cpp_args)) ) {
+ TAILQ_REMOVE(&pp->cpp_args, arg, entry);
+ yasm_xfree(arg->param);
+ yasm_xfree(arg);
+ }
+}
+
+/* Invoke the c preprocessor to generate dependency info. */
+static void
+cpp_generate_deps(yasm_preproc_cpp *pp)
+{
+ char *cmdline;
+
+ cmdline = cpp_build_cmdline(pp, "-M");
+
+#ifdef HAVE_POPEN
+ pp->f_deps = popen(cmdline, "r");
+ if (!pp->f_deps)
+ yasm__fatal( N_("Failed to execute preprocessor") );
+#else
+ yasm__fatal( N_("Cannot execute preprocessor, no popen available") );
+#endif
+
+ yasm_xfree(cmdline);
+}
+
+/*******************************************************************************
+ Interface functions.
+*******************************************************************************/
+static yasm_preproc *
+cpp_preproc_create(const char *in, yasm_symtab *symtab, yasm_linemap *lm,
+ yasm_errwarns *errwarns)
+{
+ yasm_preproc_cpp *pp = yasm_xmalloc(sizeof(yasm_preproc_cpp));
+ void * iter;
+ const char * inc_dir;
+
+ pp->preproc.module = &yasm_cpp_LTX_preproc;
+ pp->f = pp->f_deps = NULL;
+ pp->cur_lm = lm;
+ pp->errwarns = errwarns;
+ pp->flags = 0;
+ pp->filename = yasm__xstrdup(in);
+
+ TAILQ_INIT(&pp->cpp_args);
+
+ /* Iterate through the list of include dirs. */
+ iter = NULL;
+ while ((inc_dir = yasm_get_include_dir(&iter)) != NULL) {
+ cpp_arg_entry *arg = yasm_xmalloc(sizeof(cpp_arg_entry));
+ arg->op = "-I";
+ arg->param = yasm__xstrdup(inc_dir);
+
+ TAILQ_INSERT_TAIL(&pp->cpp_args, arg, entry);
+ }
+
+ return (yasm_preproc *)pp;
+}
+
+static void
+cpp_preproc_destroy(yasm_preproc *preproc)
+{
+ yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;
+
+ if (pp->f) {
+#ifdef HAVE_POPEN
+ if (pclose(pp->f) != 0)
+ yasm__fatal( N_("Preprocessor exited with failure") );
+#endif
+ }
+
+ cpp_destroy_args(pp);
+
+ yasm_xfree(pp->filename);
+ yasm_xfree(pp);
+}
+
+static char *
+cpp_preproc_get_line(yasm_preproc *preproc)
+{
+ yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;
+ int bufsize = BSIZE;
+ char *buf, *p;
+
+ if (! (pp->flags & CPP_HAS_BEEN_INVOKED) ) {
+ pp->flags |= CPP_HAS_BEEN_INVOKED;
+
+ cpp_invoke(pp);
+ }
+
+ /*
+ Once the preprocessor has been run, we're just dealing with a normal
+ file.
+ */
+
+ /* Loop to ensure entire line is read (don't want to limit line length). */
+ buf = yasm_xmalloc((size_t)bufsize);
+ p = buf;
+ for (;;) {
+ if (!fgets(p, bufsize-(p-buf), pp->f)) {
+ if (ferror(pp->f)) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("error when reading from file"));
+ yasm_errwarn_propagate(pp->errwarns,
+ yasm_linemap_get_current(pp->cur_lm));
+ }
+ break;
+ }
+ p += strlen(p);
+ if (p > buf && p[-1] == '\n')
+ break;
+ if ((p-buf) >= bufsize) {
+ /* Increase size of buffer */
+ char *oldbuf = buf;
+ bufsize *= 2;
+ buf = yasm_xrealloc(buf, (size_t)bufsize);
+ p = buf + (p-oldbuf);
+ }
+ }
+
+ if (p == buf) {
+ /* No data; must be at EOF */
+ yasm_xfree(buf);
+ return NULL;
+ }
+
+ /* Strip the line ending */
+ buf[strcspn(buf, "\r\n")] = '\0';
+
+ return buf;
+}
+
+static size_t
+cpp_preproc_get_included_file(yasm_preproc *preproc, char *buf,
+ size_t max_size)
+{
+ char *p = buf;
+ int ch = '\0';
+ size_t n = 0;
+ yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;
+
+ if (! (pp->flags & CPP_HAS_GENERATED_DEPS) ) {
+ pp->flags |= CPP_HAS_GENERATED_DEPS;
+
+ cpp_generate_deps(pp);
+
+ /* Skip target name and first dependency. */
+ while (ch != ':')
+ ch = fgetc(pp->f_deps);
+
+ fgetc(pp->f_deps); /* Discard space after colon. */
+
+ while (ch != ' ' && ch != EOF)
+ ch = fgetc(pp->f_deps);
+
+ if (ch == EOF)
+ return 0;
+ }
+
+ while (n < max_size) {
+ ch = fgetc(pp->f_deps);
+
+ if (ch == ' ' || ch == EOF) {
+ *p = '\0';
+ return n;
+ }
+
+ /* Eat any silly characters. */
+ if (ch < ' ')
+ continue;
+
+ *p++ = ch;
+ n++;
+ }
+
+ /* Ensure the buffer is null-terminated. */
+ *(p - 1) = '\0';
+ return n;
+}
+
+static void
+cpp_preproc_add_include_file(yasm_preproc *preproc, const char *filename)
+{
+ yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;
+
+ cpp_arg_entry *arg = yasm_xmalloc(sizeof(cpp_arg_entry));
+ arg->op = "-include";
+ arg->param = yasm__xstrdup(filename);
+
+ TAILQ_INSERT_TAIL(&pp->cpp_args, arg, entry);
+}
+
+static void
+cpp_preproc_predefine_macro(yasm_preproc *preproc, const char *macronameval)
+{
+ yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;
+
+ cpp_arg_entry *arg = yasm_xmalloc(sizeof(cpp_arg_entry));
+ arg->op = "-D";
+ arg->param = yasm__xstrdup(macronameval);
+
+ TAILQ_INSERT_TAIL(&pp->cpp_args, arg, entry);
+}
+
+static void
+cpp_preproc_undefine_macro(yasm_preproc *preproc, const char *macroname)
+{
+ yasm_preproc_cpp *pp = (yasm_preproc_cpp *)preproc;
+
+ cpp_arg_entry *arg = yasm_xmalloc(sizeof(cpp_arg_entry));
+ arg->op = "-U";
+ arg->param = yasm__xstrdup(macroname);
+
+ TAILQ_INSERT_TAIL(&pp->cpp_args, arg, entry);
+}
+
+static void
+cpp_preproc_define_builtin(yasm_preproc *preproc, const char *macronameval)
+{
+ /* Handle a builtin as if it were a predefine. */
+ cpp_preproc_predefine_macro(preproc, macronameval);
+}
+
+static void
+cpp_preproc_add_standard(yasm_preproc *preproc, const char **macros)
+{
+ /* TODO */
+}
+
+/*******************************************************************************
+ Preprocessor module object.
+*******************************************************************************/
+
+yasm_preproc_module yasm_cpp_LTX_preproc = {
+ "Run input through external C preprocessor",
+ "cpp",
+ cpp_preproc_create,
+ cpp_preproc_destroy,
+ cpp_preproc_get_line,
+ cpp_preproc_get_included_file,
+ cpp_preproc_add_include_file,
+ cpp_preproc_predefine_macro,
+ cpp_preproc_undefine_macro,
+ cpp_preproc_define_builtin,
+ cpp_preproc_add_standard
+};
diff --git a/contrib/tools/yasm/modules/preprocs/gas/gas-eval.c b/contrib/tools/yasm/modules/preprocs/gas/gas-eval.c
new file mode 100644
index 0000000000..3625c7a9be
--- /dev/null
+++ b/contrib/tools/yasm/modules/preprocs/gas/gas-eval.c
@@ -0,0 +1,444 @@
+/* eval.c expression evaluator for the Netwide Assembler
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ *
+ * initial version 27/iii/95 by Simon Tatham
+ */
+#include <util.h>
+#include <libyasm-stdint.h>
+#include <libyasm/coretype.h>
+#include <libyasm/intnum.h>
+#include <libyasm/expr.h>
+#include <libyasm/symrec.h>
+#include <ctype.h>
+
+#include "gas-eval.h"
+
+/* The assembler symbol table. */
+static yasm_symtab *symtab;
+
+static scanner scan; /* Address of scanner routine */
+static efunc error; /* Address of error reporting routine */
+
+static struct tokenval *tokval; /* The current token */
+static int i; /* The t_type of tokval */
+
+static void *scpriv;
+static void *epriv;
+
+/*
+ * Recursive-descent parser. Called with a single boolean operand,
+ * which is TRUE if the evaluation is critical (i.e. unresolved
+ * symbols are an error condition). Must update the global `i' to
+ * reflect the token after the parsed string. May return NULL.
+ *
+ * evaluate() should report its own errors: on return it is assumed
+ * that if NULL has been returned, the error has already been
+ * reported.
+ */
+
+/*
+ * Grammar parsed is:
+ *
+ * expr : bexpr [ WRT expr6 ]
+ * bexpr : rexp0 or expr0 depending on relative-mode setting
+ * rexp0 : rexp1 [ {||} rexp1...]
+ * rexp1 : rexp2 [ {^^} rexp2...]
+ * rexp2 : rexp3 [ {&&} rexp3...]
+ * rexp3 : expr0 [ {=,==,<>,!=,<,>,<=,>=} expr0 ]
+ * expr0 : expr1 [ {|} expr1...]
+ * expr1 : expr2 [ {^} expr2...]
+ * expr2 : expr3 [ {&} expr3...]
+ * expr3 : expr4 [ {<<,>>} expr4...]
+ * expr4 : expr5 [ {+,-} expr5...]
+ * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
+ * expr6 : { ~,+,-,SEG } expr6
+ * | (bexpr)
+ * | symbol
+ * | $
+ * | number
+ */
+
+static yasm_expr *rexp0(void), *rexp1(void), *rexp2(void), *rexp3(void);
+
+static yasm_expr *expr0(void), *expr1(void), *expr2(void), *expr3(void);
+static yasm_expr *expr4(void), *expr5(void), *expr6(void);
+
+static yasm_expr *(*bexpr)(void);
+
+static yasm_expr *rexp0(void)
+{
+ yasm_expr *e, *f;
+
+ e = rexp1();
+ if (!e)
+ return NULL;
+
+ while (i == TOKEN_DBL_OR)
+ {
+ i = scan(scpriv, tokval);
+ f = rexp1();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_LOR, f, 0);
+ }
+ return e;
+}
+
+static yasm_expr *rexp1(void)
+{
+ yasm_expr *e, *f;
+
+ e = rexp2();
+ if (!e)
+ return NULL;
+
+ while (i == TOKEN_DBL_XOR)
+ {
+ i = scan(scpriv, tokval);
+ f = rexp2();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_LXOR, f, 0);
+ }
+ return e;
+}
+
+static yasm_expr *rexp2(void)
+{
+ yasm_expr *e, *f;
+
+ e = rexp3();
+ if (!e)
+ return NULL;
+ while (i == TOKEN_DBL_AND)
+ {
+ i = scan(scpriv, tokval);
+ f = rexp3();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_LAND, f, 0);
+ }
+ return e;
+}
+
+static yasm_expr *rexp3(void)
+{
+ yasm_expr *e, *f;
+
+ e = expr0();
+ if (!e)
+ return NULL;
+
+ while (i == TOKEN_EQ || i == TOKEN_LT || i == TOKEN_GT ||
+ i == TOKEN_NE || i == TOKEN_LE || i == TOKEN_GE)
+ {
+ int j = i;
+ i = scan(scpriv, tokval);
+ f = expr0();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (j)
+ {
+ case TOKEN_EQ:
+ e = yasm_expr_create_tree(e, YASM_EXPR_EQ, f, 0);
+ break;
+ case TOKEN_LT:
+ e = yasm_expr_create_tree(e, YASM_EXPR_LT, f, 0);
+ break;
+ case TOKEN_GT:
+ e = yasm_expr_create_tree(e, YASM_EXPR_GT, f, 0);
+ break;
+ case TOKEN_NE:
+ e = yasm_expr_create_tree(e, YASM_EXPR_NE, f, 0);
+ break;
+ case TOKEN_LE:
+ e = yasm_expr_create_tree(e, YASM_EXPR_LE, f, 0);
+ break;
+ case TOKEN_GE:
+ e = yasm_expr_create_tree(e, YASM_EXPR_GE, f, 0);
+ break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *expr0(void)
+{
+ yasm_expr *e, *f;
+
+ e = expr1();
+ if (!e)
+ return NULL;
+
+ while (i == '|')
+ {
+ i = scan(scpriv, tokval);
+ f = expr1();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_OR, f, 0);
+ }
+ return e;
+}
+
+static yasm_expr *expr1(void)
+{
+ yasm_expr *e, *f;
+
+ e = expr2();
+ if (!e)
+ return NULL;
+
+ while (i == '^') {
+ i = scan(scpriv, tokval);
+ f = expr2();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_XOR, f, 0);
+ }
+ return e;
+}
+
+static yasm_expr *expr2(void)
+{
+ yasm_expr *e, *f;
+
+ e = expr3();
+ if (!e)
+ return NULL;
+
+ while (i == '&') {
+ i = scan(scpriv, tokval);
+ f = expr3();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_AND, f, 0);
+ }
+ return e;
+}
+
+static yasm_expr *expr3(void)
+{
+ yasm_expr *e, *f;
+
+ e = expr4();
+ if (!e)
+ return NULL;
+
+ while (i == TOKEN_SHL || i == TOKEN_SHR)
+ {
+ int j = i;
+ i = scan(scpriv, tokval);
+ f = expr4();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (j) {
+ case TOKEN_SHL:
+ e = yasm_expr_create_tree(e, YASM_EXPR_SHL, f, 0);
+ break;
+ case TOKEN_SHR:
+ e = yasm_expr_create_tree(e, YASM_EXPR_SHR, f, 0);
+ break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *expr4(void)
+{
+ yasm_expr *e, *f;
+
+ e = expr5();
+ if (!e)
+ return NULL;
+ while (i == '+' || i == '-')
+ {
+ int j = i;
+ i = scan(scpriv, tokval);
+ f = expr5();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+ switch (j) {
+ case '+':
+ e = yasm_expr_create_tree(e, YASM_EXPR_ADD, f, 0);
+ break;
+ case '-':
+ e = yasm_expr_create_tree(e, YASM_EXPR_SUB, f, 0);
+ break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *expr5(void)
+{
+ yasm_expr *e, *f;
+
+ e = expr6();
+ if (!e)
+ return NULL;
+ while (i == '*' || i == '/' || i == '%' ||
+ i == TOKEN_SDIV || i == TOKEN_SMOD)
+ {
+ int j = i;
+ i = scan(scpriv, tokval);
+ f = expr6();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+ switch (j) {
+ case '*':
+ e = yasm_expr_create_tree(e, YASM_EXPR_MUL, f, 0);
+ break;
+ case '/':
+ e = yasm_expr_create_tree(e, YASM_EXPR_DIV, f, 0);
+ break;
+ case '%':
+ e = yasm_expr_create_tree(e, YASM_EXPR_MOD, f, 0);
+ break;
+ case TOKEN_SDIV:
+ e = yasm_expr_create_tree(e, YASM_EXPR_SIGNDIV, f, 0);
+ break;
+ case TOKEN_SMOD:
+ e = yasm_expr_create_tree(e, YASM_EXPR_SIGNMOD, f, 0);
+ break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *expr6(void)
+{
+ yasm_expr *e = NULL;
+
+ if (i == '-') {
+ i = scan(scpriv, tokval);
+ e = expr6();
+ if (!e)
+ return NULL;
+ return yasm_expr_create_branch(YASM_EXPR_NEG, e, 0);
+ } else if (i == '+') {
+ i = scan(scpriv, tokval);
+ return expr6();
+ } else if (i == '~') {
+ i = scan(scpriv, tokval);
+ e = expr6();
+ if (!e)
+ return NULL;
+ return yasm_expr_create_branch(YASM_EXPR_NOT, e, 0);
+ } else if (i == TOKEN_SEG) {
+ i = scan(scpriv, tokval);
+ e = expr6();
+ if (!e)
+ return NULL;
+ error(epriv, ERR_NONFATAL, "%s not supported", "SEG");
+ return e;
+ } else if (i == '(') {
+ i = scan(scpriv, tokval);
+ e = bexpr();
+ if (!e)
+ return NULL;
+ if (i != ')') {
+ error(epriv, ERR_NONFATAL, "expecting `)'");
+ return NULL;
+ }
+ i = scan(scpriv, tokval);
+ return e;
+ }
+ else if (i == TOKEN_NUM || i == TOKEN_ID ||
+ i == TOKEN_HERE || i == TOKEN_BASE)
+ {
+ switch (i) {
+ case TOKEN_NUM:
+ e = yasm_expr_create_ident(yasm_expr_int(tokval->t_integer), 0);
+ tokval->t_integer = NULL;
+ break;
+ case TOKEN_ID:
+ if (symtab) {
+ yasm_symrec *sym =
+ yasm_symtab_get(symtab, tokval->t_charptr);
+ if (sym) {
+ e = yasm_expr_create_ident(yasm_expr_sym(sym), 0);
+ } else {
+ error(epriv, ERR_NONFATAL,
+ "undefined symbol `%s' in preprocessor",
+ tokval->t_charptr);
+ e = yasm_expr_create_ident(yasm_expr_int(
+ yasm_intnum_create_int(1)), 0);
+ }
+ break;
+ }
+ /*fallthrough*/
+ case TOKEN_HERE:
+ case TOKEN_BASE:
+ error(epriv, ERR_NONFATAL,
+ "cannot reference symbol `%s' in preprocessor",
+ (i == TOKEN_ID ? tokval->t_charptr :
+ i == TOKEN_HERE ? "$" : "$$"));
+ e = yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_int(1)),
+ 0);
+ break;
+ }
+ i = scan(scpriv, tokval);
+ return e;
+ } else {
+ error(epriv, ERR_NONFATAL, "expression syntax error");
+ return NULL;
+ }
+}
+
+yasm_expr *evaluate (scanner sc, void *scprivate, struct tokenval *tv,
+ void *eprivate, int critical, efunc report_error,
+ yasm_symtab *st)
+{
+ if (critical & CRITICAL) {
+ critical &= ~CRITICAL;
+ bexpr = rexp0;
+ } else
+ bexpr = expr0;
+
+ scan = sc;
+ scpriv = scprivate;
+ tokval = tv;
+ error = report_error;
+ epriv = eprivate;
+ symtab = st;
+
+ if (tokval->t_type == TOKEN_INVALID)
+ i = scan(scpriv, tokval);
+ else
+ i = tokval->t_type;
+
+ return bexpr ();
+}
diff --git a/contrib/tools/yasm/modules/preprocs/gas/gas-eval.h b/contrib/tools/yasm/modules/preprocs/gas/gas-eval.h
new file mode 100644
index 0000000000..18dcc517a9
--- /dev/null
+++ b/contrib/tools/yasm/modules/preprocs/gas/gas-eval.h
@@ -0,0 +1,120 @@
+/* eval.h header file for eval.c
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+#ifndef YASM_EVAL_H
+#define YASM_EVAL_H
+
+/*
+ * -------------------------
+ * Error reporting functions
+ * -------------------------
+ */
+
+/*
+ * An error reporting function should look like this.
+ */
+typedef void (*efunc) (void *private_data, int severity, const char *fmt, ...);
+
+/*
+ * These are the error severity codes which get passed as the first
+ * argument to an efunc.
+ */
+
+#define ERR_DEBUG 0x00000008 /* put out debugging message */
+#define ERR_WARNING 0x00000000 /* warn only: no further action */
+#define ERR_NONFATAL 0x00000001 /* terminate assembly after phase */
+#define ERR_FATAL 0x00000002 /* instantly fatal: exit with error */
+#define ERR_PANIC 0x00000003 /* internal error: panic instantly
+ * and dump core for reference */
+#define ERR_MASK 0x0000000F /* mask off the above codes */
+#define ERR_NOFILE 0x00000010 /* don't give source file name/line */
+#define ERR_USAGE 0x00000020 /* print a usage message */
+#define ERR_PASS1 0x00000040 /* only print this error on pass one */
+
+/*
+ * These codes define specific types of suppressible warning.
+ */
+
+#define ERR_WARN_MASK 0x0000FF00 /* the mask for this feature */
+#define ERR_WARN_SHR 8 /* how far to shift right */
+
+#define ERR_WARN_MNP 0x00000100 /* macro-num-parameters warning */
+#define ERR_WARN_MSR 0x00000200 /* macro self-reference */
+#define ERR_WARN_OL 0x00000300 /* orphan label (no colon, and
+ * alone on line) */
+#define ERR_WARN_NOV 0x00000400 /* numeric overflow */
+#define ERR_WARN_GNUELF 0x00000500 /* using GNU ELF extensions */
+#define ERR_WARN_MAX 5 /* the highest numbered one */
+
+/*
+ * The expression evaluator must be passed a scanner function; a
+ * standard scanner is provided as part of nasmlib.c. The
+ * preprocessor will use a different one. Scanners, and the
+ * token-value structures they return, look like this.
+ *
+ * The return value from the scanner is always a copy of the
+ * `t_type' field in the structure.
+ */
+struct tokenval {
+ int t_type;
+ yasm_intnum *t_integer, *t_inttwo;
+ char *t_charptr;
+};
+typedef int (*scanner) (void *private_data, struct tokenval *tv);
+
+/*
+ * Token types returned by the scanner, in addition to ordinary
+ * ASCII character values, and zero for end-of-string.
+ */
+enum { /* token types, other than chars */
+ TOKEN_INVALID = -1, /* a placeholder value */
+ TOKEN_EOS = 0, /* end of string */
+ TOKEN_EQ = '=', TOKEN_GT = '>', TOKEN_LT = '<', /* aliases */
+ TOKEN_ID = 256, TOKEN_NUM, TOKEN_REG, TOKEN_INSN, /* major token types */
+ TOKEN_ERRNUM, /* numeric constant with error in */
+ TOKEN_HERE, TOKEN_BASE, /* $ and $$ */
+ TOKEN_SPECIAL, /* BYTE, WORD, DWORD, FAR, NEAR, etc */
+ TOKEN_PREFIX, /* A32, O16, LOCK, REPNZ, TIMES, etc */
+ TOKEN_SHL, TOKEN_SHR, /* << and >> */
+ TOKEN_SDIV, TOKEN_SMOD, /* // and %% */
+ TOKEN_GE, TOKEN_LE, TOKEN_NE, /* >=, <= and <> (!= is same as <>) */
+ TOKEN_DBL_AND, TOKEN_DBL_OR, TOKEN_DBL_XOR, /* &&, || and ^^ */
+ TOKEN_SEG, TOKEN_WRT, /* SEG and WRT */
+ TOKEN_FLOAT /* floating-point constant */
+};
+
+/*
+ * The actual expression evaluator function looks like this. When
+ * called, it expects the first token of its expression to already
+ * be in `*tv'; if it is not, set tv->t_type to TOKEN_INVALID and
+ * it will start by calling the scanner.
+ *
+ * `critical' is non-zero if the expression may not contain forward
+ * references. The evaluator will report its own error if this
+ * occurs; if `critical' is 1, the error will be "symbol not
+ * defined before use", whereas if `critical' is 2, the error will
+ * be "symbol undefined".
+ *
+ * If `critical' has bit 8 set (in addition to its main value: 0x101
+ * and 0x102 correspond to 1 and 2) then an extended expression
+ * syntax is recognised, in which relational operators such as =, <
+ * and >= are accepted, as well as low-precedence logical operators
+ * &&, ^^ and ||.
+ */
+#define CRITICAL 0x100
+typedef yasm_expr *(*evalfunc) (scanner sc, void *scprivate, struct tokenval *tv,
+ int critical, efunc error, yasm_symtab *symtab);
+
+/*
+ * The evaluator itself.
+ */
+yasm_expr *evaluate (scanner sc, void *scprivate, struct tokenval *tv,
+ void *eprivate, int critical, efunc report_error,
+ yasm_symtab *symtab);
+
+#endif
diff --git a/contrib/tools/yasm/modules/preprocs/gas/gas-preproc.c b/contrib/tools/yasm/modules/preprocs/gas/gas-preproc.c
new file mode 100644
index 0000000000..60c9e4f0cd
--- /dev/null
+++ b/contrib/tools/yasm/modules/preprocs/gas/gas-preproc.c
@@ -0,0 +1,1409 @@
+/*
+ * GAS preprocessor (emulates GNU Assembler's preprocessor)
+ *
+ * Copyright (C) 2009 Alexei Svitkine
+ *
+ * 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 <util.h>
+#include <ctype.h>
+
+#include <libyasm.h>
+#include "modules/preprocs/gas/gas-eval.h"
+
+#define FALSE 0
+#define TRUE 1
+#define BSIZE 512
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+typedef struct buffered_line {
+ char *line;
+ int line_number;
+ SLIST_ENTRY(buffered_line) next;
+} buffered_line;
+
+typedef struct included_file {
+ char *filename;
+ int lines_remaining;
+ SLIST_ENTRY(included_file) next;
+} included_file;
+
+typedef struct macro_entry {
+ char *name;
+ int num_params;
+ char **params;
+ int num_lines;
+ char **lines;
+ STAILQ_ENTRY(macro_entry) next;
+} macro_entry;
+
+typedef struct deferred_define {
+ char *name;
+ char *value;
+ SLIST_ENTRY(deferred_define) next;
+} deferred_define;
+
+typedef struct expr_state {
+ const char *string;
+ char *symbol;
+ int string_cursor;
+} expr_state;
+
+typedef struct yasm_preproc_gas {
+ yasm_preproc_base preproc; /* base structure */
+
+ FILE *in;
+ char *in_filename;
+
+ yasm_symtab *defines;
+ SLIST_HEAD(deferred_defines_head, deferred_define) deferred_defines;
+
+ int depth;
+ int skip_depth;
+
+ int in_comment;
+
+ expr_state expr;
+
+ SLIST_HEAD(buffered_lines_head, buffered_line) buffered_lines;
+ SLIST_HEAD(included_files_head, included_file) included_files;
+ STAILQ_HEAD(macros_head, macro_entry) macros;
+
+ int in_line_number;
+ int next_line_number;
+ int current_line_number; /* virtual (output) line number */
+
+ yasm_linemap *cur_lm;
+ yasm_errwarns *errwarns;
+ int fatal_error;
+ int detect_errors_only;
+} yasm_preproc_gas;
+
+yasm_preproc_module yasm_gas_LTX_preproc;
+
+/* Forward declarations. */
+
+static int substitute_values(yasm_preproc_gas *pp, char **line_ptr);
+
+/* String helpers. */
+
+static const char *starts_with(const char *big, const char *little)
+{
+ while (*little) {
+ if (*little++ != *big++) {
+ return NULL;
+ }
+ }
+ return big;
+}
+
+static void skip_whitespace(const char **line)
+{
+ while (isspace(**line)) {
+ (*line)++;
+ }
+}
+
+static void skip_whitespace2(char **line)
+{
+ while (isspace(**line)) {
+ (*line)++;
+ }
+}
+
+static const char *matches(const char *line, const char *directive)
+{
+ skip_whitespace(&line);
+
+ if (*line == '.') {
+ line = starts_with(line + 1, directive);
+ if (line && (!*line || isspace(*line))) {
+ skip_whitespace(&line);
+ return line;
+ }
+ }
+
+ return NULL;
+}
+
+static int unquote(const char *arg, char *to, size_t to_size, char q, char expected, const char **remainder)
+{
+ const char *quote;
+ const char *end;
+ size_t len;
+
+ skip_whitespace(&arg);
+ if (*arg != q) {
+ return -1;
+ }
+
+ arg++;
+
+ end = arg;
+ do {
+ quote = strchr(end, q);
+ if (!quote) {
+ return -2;
+ }
+ end = quote + 1;
+ } while (*(quote - 1) == '\\');
+
+ skip_whitespace(&end);
+ if (*end != expected) {
+ return -3;
+ }
+
+ if (remainder) {
+ *remainder = end + 1;
+ }
+
+ len = (size_t) (quote - arg);
+ if (len >= to_size) {
+ return -4;
+ }
+
+ strncpy(to, arg, len);
+ to[len] = '\0';
+
+ return (int) len;
+}
+
+/* Line-reading. */
+
+static char *read_line_from_file(yasm_preproc_gas *pp, FILE *file)
+{
+ int bufsize = BSIZE;
+ char *buf;
+ char *p;
+
+ buf = yasm_xmalloc((size_t)bufsize);
+
+ /* Loop to ensure entire line is read (don't want to limit line length). */
+ p = buf;
+ for (;;) {
+ if (!fgets(p, bufsize - (p - buf), file)) {
+ if (ferror(file)) {
+ yasm_error_set(YASM_ERROR_IO, N_("error when reading from file"));
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ }
+ break;
+ }
+ p += strlen(p);
+ if (p > buf && p[-1] == '\n') {
+ break;
+ }
+ if ((p - buf) + 1 >= bufsize) {
+ /* Increase size of buffer */
+ char *oldbuf = buf;
+ bufsize *= 2;
+ buf = yasm_xrealloc(buf, (size_t) bufsize);
+ p = buf + (p - oldbuf);
+ }
+ }
+
+ if (p == buf) {
+ /* No data; must be at EOF */
+ yasm_xfree(buf);
+ return NULL;
+ }
+
+ /* Strip the line ending */
+ buf[strcspn(buf, "\r\n")] = '\0';
+ return buf;
+}
+
+static char *read_line(yasm_preproc_gas *pp)
+{
+ char *line;
+
+ if (!SLIST_EMPTY(&pp->included_files)) {
+ included_file *inc_file = SLIST_FIRST(&pp->included_files);
+ if (inc_file->lines_remaining <= 0) {
+ SLIST_REMOVE_HEAD(&pp->included_files, next);
+ yasm_xfree(inc_file->filename);
+ yasm_xfree(inc_file);
+ }
+ }
+
+ if (!SLIST_EMPTY(&pp->buffered_lines)) {
+ buffered_line *bline = SLIST_FIRST(&pp->buffered_lines);
+ SLIST_REMOVE_HEAD(&pp->buffered_lines, next);
+ line = bline->line;
+ if (bline->line_number != -1) {
+ pp->next_line_number = bline->line_number;
+ }
+ yasm_xfree(bline);
+ if (!SLIST_EMPTY(&pp->included_files)) {
+ SLIST_FIRST(&pp->included_files)->lines_remaining--;
+ }
+ return line;
+ }
+
+ line = read_line_from_file(pp, pp->in);
+ if (line) {
+ pp->in_line_number++;
+ pp->next_line_number = pp->in_line_number;
+ }
+
+ return line;
+}
+
+static const char *get_arg(yasm_preproc_gas *pp, const char *src, char *dest, size_t dest_size)
+{
+ const char *comma = strchr(src, ',');
+ if (comma) {
+ size_t len = (size_t) (comma - src);
+ if (len >= dest_size) {
+ len = dest_size - 1;
+ }
+ strncpy(dest, src, len);
+ dest[len] = '\0';
+ comma++;
+ skip_whitespace(&comma);
+ } else {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("expected comma"));
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ }
+ return comma;
+}
+
+/* GAS expression evaluation. */
+
+static char get_char(yasm_preproc_gas *pp)
+{
+ return pp->expr.string[pp->expr.string_cursor];
+}
+
+static const char *get_str(yasm_preproc_gas *pp)
+{
+ return pp->expr.string + pp->expr.string_cursor;
+}
+
+static void next_char(yasm_preproc_gas *pp)
+{
+ pp->expr.string_cursor++;
+}
+
+static int ishex(char c)
+{
+ c = tolower(c);
+ return isdigit(c) || (c >= 'a' && c <= 'f');
+}
+
+static void gas_scan_init(yasm_preproc_gas *pp, struct tokenval *tokval, const char *arg1)
+{
+ pp->expr.symbol = NULL;
+ pp->expr.string = arg1;
+ pp->expr.string_cursor = 0;
+ memset(tokval, 0, sizeof(struct tokenval));
+ tokval->t_type = TOKEN_INVALID;
+}
+
+static void gas_scan_cleanup(yasm_preproc_gas *pp, struct tokenval *tokval)
+{
+ if (tokval->t_integer) {
+ yasm_intnum_destroy(tokval->t_integer);
+ tokval->t_integer = NULL;
+ }
+ if (pp->expr.symbol) {
+ yasm_xfree(pp->expr.symbol);
+ pp->expr.symbol = NULL;
+ }
+}
+
+static int gas_scan(void *preproc, struct tokenval *tokval)
+{
+ yasm_preproc_gas *pp = (yasm_preproc_gas *) preproc;
+ char c = get_char(pp);
+ const char *str;
+
+ tokval->t_charptr = NULL;
+
+ if (c == '\0') {
+ return tokval->t_type = TOKEN_EOS;
+ }
+
+ if (isspace(c)) {
+ do {
+ next_char(pp);
+ c = get_char(pp);
+ } while (isspace(c));
+ }
+
+ if (isdigit(c)) {
+ int char_index = 0;
+ int value = 0;
+
+ do {
+ value = value*10 + (c - '0');
+ char_index++;
+ next_char(pp);
+ c = get_char(pp);
+ if (char_index == 1 && c == 'x' && value == 0) {
+ next_char(pp);
+ c = get_char(pp);
+ /* Hex notation. */
+ while (ishex(c)) {
+ if (isdigit(c)) {
+ value = (value << 4) | (c - '0');
+ } else {
+ value = (value << 4) | (tolower(c) - 'a' + 0xa);
+ }
+ next_char(pp);
+ c = get_char(pp);
+ }
+ break;
+ }
+ } while (isdigit(c));
+
+ if (tokval->t_integer) {
+ yasm_intnum_destroy(tokval->t_integer);
+ }
+ tokval->t_integer = yasm_intnum_create_int(value);
+ return tokval->t_type = TOKEN_NUM;
+ }
+
+ tokval->t_type = TOKEN_INVALID;
+ str = get_str(pp);
+
+ {
+ /* It should be tested whether GAS supports all of these or if there are missing ones. */
+ unsigned i;
+ struct {
+ const char *op;
+ int token;
+ } ops[] = {
+ { "<<", TOKEN_SHL },
+ { ">>", TOKEN_SHR },
+ { "//", TOKEN_SDIV },
+ { "%%", TOKEN_SMOD },
+ { "==", TOKEN_EQ },
+ { "!=", TOKEN_NE },
+ { "<>", TOKEN_NE },
+ { "<>", TOKEN_NE },
+ { "<=", TOKEN_LE },
+ { ">=", TOKEN_GE },
+ { "&&", TOKEN_DBL_AND },
+ { "^^", TOKEN_DBL_XOR },
+ { "||", TOKEN_DBL_OR }
+ };
+ for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) {
+ if (!strcmp(str, ops[i].op)) {
+ tokval->t_type = ops[i].token;
+ break;
+ }
+ }
+ }
+
+ if (tokval->t_type != TOKEN_INVALID) {
+ next_char(pp);
+ next_char(pp);
+ } else {
+ str = get_str(pp);
+
+ next_char(pp);
+ tokval->t_type = c;
+
+ /* Is it a symbol? If so we need to make it a TOKEN_ID. */
+ if (isalpha(c) || c == '_' || c == '.') {
+ int symbol_length = 1;
+
+ c = get_char(pp);
+ while (isalnum(c) || c == '$' || c == '_') {
+ symbol_length++;
+ next_char(pp);
+ c = get_char(pp);
+ }
+
+ pp->expr.symbol = yasm_xrealloc(pp->expr.symbol, symbol_length + 1);
+ memcpy(pp->expr.symbol, str, symbol_length);
+ pp->expr.symbol[symbol_length] = '\0';
+
+ tokval->t_type = TOKEN_ID;
+ tokval->t_charptr = pp->expr.symbol;
+ }
+ }
+
+ return tokval->t_type;
+}
+
+static void gas_err(void *private_data, int severity, const char *fmt, ...)
+{
+ va_list args;
+ yasm_preproc_gas *pp = private_data;
+
+ if (!pp->detect_errors_only) {
+ va_start(args, fmt);
+ yasm_error_set_va(YASM_ERROR_SYNTAX, N_(fmt), args);
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ va_end(args);
+ }
+
+ pp->fatal_error = 1;
+}
+
+static long eval_expr(yasm_preproc_gas *pp, const char *arg1)
+{
+ struct tokenval tv;
+ yasm_expr *expr;
+ yasm_intnum *intn;
+ long value;
+ expr_state prev_state;
+
+ if (!*arg1) {
+ return 0;
+ }
+
+ prev_state = pp->expr;
+ gas_scan_init(pp, &tv, arg1);
+ expr = evaluate(gas_scan, pp, &tv, pp, CRITICAL, gas_err, pp->defines);
+ intn = yasm_expr_get_intnum(&expr, 0);
+ value = yasm_intnum_get_int(intn);
+ yasm_expr_destroy(expr);
+ gas_scan_cleanup(pp, &tv);
+ pp->expr = prev_state;
+
+ return value;
+}
+
+/* If-directive helpers. */
+
+static int handle_if(yasm_preproc_gas *pp, int is_true)
+{
+ assert(pp->depth >= 0);
+ assert(pp->skip_depth == 0);
+ if (is_true) {
+ pp->depth++;
+ } else {
+ pp->skip_depth = 1;
+ }
+ return 1;
+}
+
+static int handle_endif(yasm_preproc_gas *pp)
+{
+ if (pp->depth) {
+ pp->depth--;
+ } else {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("\".endif\" without \".if\""));
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ return 0;
+ }
+ return 1;
+}
+
+static int handle_else(yasm_preproc_gas *pp, int is_elseif)
+{
+ if (!pp->depth) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("\".%s\" without \".if\""), is_elseif ? "elseif" : "else");
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ return 0;
+ } else {
+ pp->skip_depth = 1;
+ }
+ return 1;
+}
+
+/* Directive-handling functions. */
+
+static int eval_if(yasm_preproc_gas *pp, int negate, const char *arg1)
+{
+ long value;
+ if (!*arg1) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("expression is required in \".if\" statement"));
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ return 0;
+ }
+ value = eval_expr(pp, arg1);
+ handle_if(pp, (negate ? !value : !!value));
+ return 1;
+}
+
+static int eval_else(yasm_preproc_gas *pp, int unused)
+{
+ return handle_else(pp, 0);
+}
+
+static int eval_endif(yasm_preproc_gas *pp, int unused)
+{
+ return handle_endif(pp);
+}
+
+static int eval_elseif(yasm_preproc_gas *pp, int unused, const char *arg1)
+{
+ if (!*arg1) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("expression is required in \".elseif\" statement"));
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ return 0;
+ }
+ if (!handle_else(pp, 1)) {
+ return 0;
+ }
+ return eval_if(pp, 0, arg1);
+}
+
+static int eval_ifb(yasm_preproc_gas *pp, int negate, const char *arg1)
+{
+ int is_blank = !*arg1;
+ return handle_if(pp, (negate ? !is_blank : is_blank));
+}
+
+static int eval_ifc(yasm_preproc_gas *pp, int negate, const char *args)
+{
+ char arg1[512], arg2[512];
+ const char *remainder;
+ int len = unquote(args, arg1, sizeof(arg1), '\'', ',', &remainder);
+ if (len >= 0) {
+ len = unquote(remainder, arg2, sizeof(arg2), '\'', '\0', NULL);
+ if (len >= 0) {
+ int result = !strcmp(arg1, arg2);
+ return handle_if(pp, (negate ? !result : result));
+ }
+ } else {
+ /* first argument was not single-quoted, assume non-quoted mode */
+ remainder = get_arg(pp, args, arg1, sizeof(arg1));
+ if (remainder) {
+ int result = !strcmp(arg1, remainder);
+ return handle_if(pp, (negate ? !result : result));
+ }
+ }
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("\"%s\" expects two single-quoted or unquoted arguments"), negate ? ".ifnc" : ".ifc");
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ return 0;
+}
+
+static int eval_ifeqs(yasm_preproc_gas *pp, int negate, const char *args)
+{
+ char arg1[512], arg2[512];
+ const char *remainder;
+ int len = unquote(args, arg1, sizeof(arg1), '"', ',', &remainder);
+ if (len >= 0) {
+ len = unquote(remainder, arg2, sizeof(arg2), '"', '\0', NULL);
+ if (len >= 0) {
+ int result = !strcmp(arg1, arg2);
+ return handle_if(pp, (negate ? !result : result));
+ }
+ }
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("\"%s\" expects two double-quoted arguments"), negate ? ".ifnes" : ".ifeqs");
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ return 1;
+}
+
+static int eval_ifdef(yasm_preproc_gas *pp, int negate, const char *name)
+{
+ yasm_symrec *rec = yasm_symtab_get(pp->defines, name);
+ int result = (rec != NULL);
+ return handle_if(pp, (negate ? !result : result));
+}
+
+static int eval_ifge(yasm_preproc_gas *pp, int negate, const char *arg1)
+{
+ long value = eval_expr(pp, arg1);
+ int result = (value >= 0);
+ return handle_if(pp, (negate ? !result : result));
+}
+
+static int eval_ifgt(yasm_preproc_gas *pp, int negate, const char *arg1)
+{
+ long value = eval_expr(pp, arg1);
+ int result = (value > 0);
+ return handle_if(pp, (negate ? !result : result));
+}
+
+static int eval_include(yasm_preproc_gas *pp, int unused, const char *arg1)
+{
+ char *current_filename;
+ char filename[MAXPATHLEN];
+ char *line;
+ int num_lines;
+ FILE *file;
+ buffered_line *prev_bline;
+ included_file *inc_file;
+
+ if (unquote(arg1, filename, sizeof(filename), '"', '\0', NULL) < 0) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("string expected"));
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ return 0;
+ }
+
+ if (SLIST_EMPTY(&pp->included_files)) {
+ current_filename = pp->in_filename;
+ } else {
+ current_filename = SLIST_FIRST(&pp->included_files)->filename;
+ }
+ file = yasm_fopen_include(filename, current_filename, "r", NULL);
+ if (!file) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("unable to open included file \"%s\""), filename);
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ return 0;
+ }
+
+ num_lines = 0;
+ prev_bline = NULL;
+ line = read_line_from_file(pp, file);
+ while (line) {
+ buffered_line *bline = yasm_xmalloc(sizeof(buffered_line));
+ bline->line = line;
+ bline->line_number = -1;
+ if (prev_bline) {
+ SLIST_INSERT_AFTER(prev_bline, bline, next);
+ } else {
+ SLIST_INSERT_HEAD(&pp->buffered_lines, bline, next);
+ }
+ prev_bline = bline;
+ line = read_line_from_file(pp, file);
+ num_lines++;
+ }
+
+ inc_file = yasm_xmalloc(sizeof(included_file));
+ inc_file->filename = yasm__xstrdup(filename);
+ inc_file->lines_remaining = num_lines;
+ SLIST_INSERT_HEAD(&pp->included_files, inc_file, next);
+ return 1;
+}
+
+static int try_eval_expr(yasm_preproc_gas *pp, const char *value, long *result)
+{
+ int success;
+
+ pp->detect_errors_only = 1;
+ *result = eval_expr(pp, value);
+ success = !pp->fatal_error;
+ pp->fatal_error = 0;
+ pp->detect_errors_only = 0;
+
+ return success;
+}
+
+static int remove_define(yasm_preproc_gas *pp, const char *name, int allow_redefine)
+{
+ yasm_symrec *rec = yasm_symtab_get(pp->defines, name);
+ if (rec) {
+ const yasm_symtab_iter *entry;
+ yasm_symtab *new_defines;
+
+ if (!allow_redefine) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("symbol \"%s\" is already defined"), name);
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ return 0;
+ }
+
+ new_defines = yasm_symtab_create();
+
+ for (entry = yasm_symtab_first(pp->defines); entry; entry = yasm_symtab_next(entry)) {
+ yasm_symrec *entry_rec = yasm_symtab_iter_value(entry);
+ const char *rec_name = yasm_symrec_get_name(entry_rec);
+ if (strcmp(rec_name, name)) {
+ yasm_intnum *num = yasm_intnum_create_int(eval_expr(pp, rec_name));
+ yasm_expr *expr = yasm_expr_create_ident(yasm_expr_int(num), 0);
+ yasm_symtab_define_equ(new_defines, rec_name, expr, 0);
+ }
+ }
+
+ yasm_symtab_destroy(pp->defines);
+ pp->defines = new_defines;
+ }
+ return (rec != NULL);
+}
+
+static void add_define(yasm_preproc_gas *pp, const char *name, long value, int allow_redefine, int substitute)
+{
+ deferred_define *def, *prev_def, *temp_def;
+ yasm_intnum *num;
+ yasm_expr *expr;
+
+ remove_define(pp, name, allow_redefine);
+
+ /* Add the new define. */
+ num = yasm_intnum_create_int(value);
+ expr = yasm_expr_create_ident(yasm_expr_int(num), 0);
+ yasm_symtab_define_equ(pp->defines, name, expr, 0);
+
+ /* Perform substitution on any deferred defines. */
+ if (substitute) {
+ prev_def = NULL;
+ temp_def = NULL;
+ SLIST_FOREACH_SAFE(def, &pp->deferred_defines, next, temp_def) {
+ if (substitute_values(pp, &def->value)) {
+ /* Value was updated - check if it can be added to the symtab. */
+ if (try_eval_expr(pp, def->value, &value)) {
+ add_define(pp, def->name, value, FALSE, FALSE);
+ if (prev_def) {
+ SLIST_NEXT(prev_def, next) = SLIST_NEXT(def, next);
+ } else {
+ SLIST_FIRST(&pp->deferred_defines) = SLIST_NEXT(def, next);
+ }
+ yasm_xfree(def->name);
+ yasm_xfree(def->value);
+ yasm_xfree(def);
+ continue;
+ }
+ }
+ prev_def = def;
+ }
+ }
+}
+
+static int eval_set(yasm_preproc_gas *pp, int allow_redefine, const char *name, const char *value)
+{
+ if (!pp->skip_depth) {
+ long result;
+
+ if (!try_eval_expr(pp, value, &result)) {
+ deferred_define *def;
+ remove_define(pp, name, allow_redefine);
+ def = yasm_xmalloc(sizeof(deferred_define));
+ def->name = yasm__xstrdup(name);
+ def->value = yasm__xstrdup(value);
+ substitute_values(pp, &def->value);
+ SLIST_INSERT_HEAD(&pp->deferred_defines, def, next);
+ } else {
+ add_define(pp, name, result, allow_redefine, TRUE);
+ }
+ }
+ return 1;
+}
+
+static int eval_macro(yasm_preproc_gas *pp, int unused, char *args)
+{
+ char *end;
+ char *line;
+ long nesting = 1;
+ macro_entry *macro = yasm_xmalloc(sizeof(macro_entry));
+
+ memset(macro, 0, sizeof(macro_entry));
+
+ end = args;
+ while (*end && !isspace(*end)) {
+ end++;
+ }
+ macro->name = yasm_xmalloc(end - args + 1);
+ memcpy(macro->name, args, end - args);
+ macro->name[end - args] = '\0';
+
+ skip_whitespace2(&end);
+ while (*end) {
+ args = end;
+ while (*end && !isspace(*end) && *end != ',') {
+ end++;
+ }
+ macro->num_params++;
+ macro->params = yasm_xrealloc(macro->params, macro->num_params*sizeof(char *));
+ macro->params[macro->num_params - 1] = yasm_xmalloc(end - args + 1);
+ memcpy(macro->params[macro->num_params - 1], args, end - args);
+ macro->params[macro->num_params - 1][end - args] = '\0';
+ skip_whitespace2(&end);
+ if (*end == ',') {
+ end++;
+ skip_whitespace2(&end);
+ }
+ }
+
+ STAILQ_INSERT_TAIL(&pp->macros, macro, next);
+
+ line = read_line(pp);
+ while (line) {
+ char *line2 = line;
+ skip_whitespace2(&line2);
+ if (starts_with(line2, ".macro")) {
+ nesting++;
+ } else if (starts_with(line, ".endm") && --nesting == 0) {
+ return 1;
+ }
+ macro->num_lines++;
+ macro->lines = yasm_xrealloc(macro->lines, macro->num_lines*sizeof(char *));
+ macro->lines[macro->num_lines - 1] = line;
+ line = read_line(pp);
+ }
+
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("unexpected EOF in \".macro\" block"));
+ yasm_errwarn_propagate(pp->errwarns, yasm_linemap_get_current(pp->cur_lm));
+ return 0;
+}
+
+static int eval_endm(yasm_preproc_gas *pp, int unused)
+{
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("\".endm\" without \".macro\""));
+ yasm_errwarn_propagate(pp->errwarns, yasm_linemap_get_current(pp->cur_lm));
+ return 0;
+}
+
+static void get_param_value(macro_entry *macro, int param_index, const char *args, const char **value, int *length)
+{
+ int arg_index = 0;
+ const char *default_value = NULL;
+ const char *end, *eq = strstr(macro->params[param_index], "=");
+
+ if (eq) {
+ default_value = eq + 1;
+ }
+
+ skip_whitespace(&args);
+ end = args;
+ while (*end) {
+ args = end;
+ while (*end && !isspace(*end) && *end != ',') {
+ end++;
+ }
+ if (arg_index == param_index) {
+ if (end == args && default_value) {
+ *value = default_value;
+ *length = strlen(default_value);
+ } else {
+ *value = args;
+ *length = end - args;
+ }
+ return;
+ }
+ arg_index++;
+ skip_whitespace(&end);
+ if (*end == ',') {
+ end++;
+ skip_whitespace(&end);
+ }
+ }
+
+ *value = default_value;
+ *length = (default_value ? strlen(default_value) : 0);
+}
+
+static void expand_macro(yasm_preproc_gas *pp, macro_entry *macro, const char *args)
+{
+ int i, j;
+ buffered_line *prev_bline = NULL;
+
+ for (i = 0; i < macro->num_lines; i++) {
+ buffered_line *bline = yasm_xmalloc(sizeof(buffered_line));
+ struct tokenval tokval;
+ int prev_was_backslash = FALSE;
+ int line_length = strlen(macro->lines[i]);
+ char *work = yasm__xstrdup(macro->lines[i]);
+ expr_state prev_state = pp->expr;
+
+ gas_scan_init(pp, &tokval, work);
+ while (gas_scan(pp, &tokval) != TOKEN_EOS) {
+ if (prev_was_backslash) {
+ if (tokval.t_type == TOKEN_ID) {
+ for (j = 0; j < macro->num_params; j++) {
+ char *end = strstr(macro->params[j], "=");
+ int len = (end ? (size_t)(end - macro->params[j])
+ : strlen(macro->params[j]));
+ if (!strncmp(tokval.t_charptr, macro->params[j], len)
+ && tokval.t_charptr[len] == '\0') {
+ /* now, find matching argument. */
+ const char *value;
+ char *line = work + (pp->expr.string - work);
+ int cursor = pp->expr.string_cursor;
+ int value_length, delta;
+
+ get_param_value(macro, j, args, &value, &value_length);
+
+ len++; /* leading slash */
+ delta = value_length - len;
+ line_length += delta;
+ if (delta > 0) {
+ line = yasm_xrealloc(line, line_length + 1);
+ }
+ memmove(line + cursor - len + value_length, line + cursor, strlen(line + cursor) + 1);
+ memcpy(line + cursor - len, value, value_length);
+ pp->expr.string = work = line;
+ pp->expr.string_cursor += delta;
+ if (pp->expr.symbol) {
+ yasm_xfree(pp->expr.symbol);
+ pp->expr.symbol = NULL;
+ }
+ }
+ }
+ }
+ prev_was_backslash = FALSE;
+ } else if (tokval.t_type == '\\') {
+ prev_was_backslash = TRUE;
+ }
+ }
+ gas_scan_cleanup(pp, &tokval);
+
+ bline->line = work + (pp->expr.string - work);
+ bline->line_number = -1;
+ pp->expr = prev_state;
+
+ if (prev_bline) {
+ SLIST_INSERT_AFTER(prev_bline, bline, next);
+ } else {
+ SLIST_INSERT_HEAD(&pp->buffered_lines, bline, next);
+ }
+ prev_bline = bline;
+ }
+}
+
+static int eval_rept(yasm_preproc_gas *pp, int unused, const char *arg1)
+{
+ long i, n = eval_expr(pp, arg1);
+ long num_lines = 0;
+ long nesting = 1;
+ char *line = read_line(pp);
+ buffered_line *prev_bline = NULL;
+ SLIST_HEAD(buffered_lines_head, buffered_line) lines;
+ int rept_start_file_line_number = pp->next_line_number - 1;
+ int rept_start_output_line_number = pp->current_line_number;
+
+ SLIST_INIT(&lines);
+
+ while (line) {
+ skip_whitespace2(&line);
+ if (starts_with(line, ".rept")) {
+ nesting++;
+ } else if (starts_with(line, ".endr") && --nesting == 0) {
+ for (i = 0; i < n; i++) {
+ buffered_line *current_line;
+ prev_bline = NULL;
+ SLIST_FOREACH(current_line, &lines, next) {
+ buffered_line *bline = yasm_xmalloc(sizeof(buffered_line));
+ bline->line = yasm__xstrdup(current_line->line);
+ bline->line_number = current_line->line_number;
+ if (prev_bline) {
+ SLIST_INSERT_AFTER(prev_bline, bline, next);
+ } else {
+ SLIST_INSERT_HEAD(&pp->buffered_lines, bline, next);
+ }
+ prev_bline = bline;
+ }
+ }
+ if (!SLIST_EMPTY(&pp->included_files)) {
+ included_file *inc_file = SLIST_FIRST(&pp->included_files);
+ inc_file->lines_remaining += n * num_lines;
+ }
+ while (!SLIST_EMPTY(&lines)) {
+ buffered_line *bline = SLIST_FIRST(&lines);
+ SLIST_REMOVE_HEAD(&lines, next);
+ yasm_xfree(bline->line);
+ yasm_xfree(bline);
+ }
+ yasm_xfree(line);
+ return 1;
+ }
+ if (n > 0) {
+ buffered_line *bline = yasm_xmalloc(sizeof(buffered_line));
+ bline->line = line;
+ bline->line_number = pp->next_line_number;
+ if (prev_bline) {
+ SLIST_INSERT_AFTER(prev_bline, bline, next);
+ } else {
+ SLIST_INSERT_HEAD(&lines, bline, next);
+ }
+ prev_bline = bline;
+ } else {
+ yasm_xfree(line);
+ }
+ line = read_line(pp);
+ num_lines++;
+ }
+ yasm_linemap_set(pp->cur_lm, pp->in_filename, rept_start_output_line_number, rept_start_file_line_number, 0);
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("rept without matching endr"));
+ yasm_errwarn_propagate(pp->errwarns, rept_start_output_line_number);
+ return 0;
+}
+
+static int eval_endr(yasm_preproc_gas *pp, int unused)
+{
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("\".endr\" without \".rept\""));
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ return 0;
+}
+
+/* Top-level line processing. */
+
+typedef int (*pp_fn0_t)(yasm_preproc_gas *pp, int param);
+typedef int (*pp_fn1_t)(yasm_preproc_gas *pp, int param, const char *arg1);
+typedef int (*pp_fn2_t)(yasm_preproc_gas *pp, int param, const char *arg1, const char *arg2);
+
+#define FN(f) ((pp_fn0_t) &(f))
+
+static void kill_comments(yasm_preproc_gas *pp, char *line)
+{
+ int next = 2;
+ char *cstart;
+
+ skip_whitespace2(&line);
+ if (*line == '#' || !strncmp(line, "//", 2)) {
+ *line = '\0';
+ return;
+ }
+
+ if (pp->in_comment) {
+ cstart = line;
+ next = 0;
+ } else {
+ cstart = strstr(line, "/*");
+ next = 2;
+ }
+
+ while (cstart) {
+ char *cend = strstr(cstart + next, "*/");
+
+ if (!cend) {
+ *cstart = '\0';
+ pp->in_comment = TRUE;
+ return;
+ }
+
+ memmove(cstart, cend + 2, strlen(cend + 2) + 1);
+ pp->in_comment = FALSE;
+ cstart = strstr(cstart, "/*");
+ next = 2;
+ }
+}
+
+static int substitute_values(yasm_preproc_gas *pp, char **line_ptr)
+{
+ int changed = 0;
+ char *line = *line_ptr;
+ int line_length = strlen(line);
+ struct tokenval tokval;
+ expr_state prev_state = pp->expr;
+
+ gas_scan_init(pp, &tokval, line);
+ while (gas_scan(pp, &tokval) != TOKEN_EOS) {
+ if (tokval.t_type == TOKEN_ID) {
+ yasm_symrec *rec = yasm_symtab_get(pp->defines, tokval.t_charptr);
+ if (rec) {
+ int cursor = pp->expr.string_cursor;
+ int len = strlen(tokval.t_charptr);
+ char value[64];
+ int value_length = sprintf(value, "%ld", eval_expr(pp, tokval.t_charptr));
+ int delta = value_length - len;
+
+ line_length += delta;
+ if (delta > 0) {
+ line = yasm_xrealloc(line, line_length + 1);
+ }
+ memmove(line + cursor - len + value_length, line + cursor, strlen(line + cursor) + 1);
+ memcpy(line + cursor - len, value, value_length);
+ pp->expr.string = line;
+ pp->expr.string_cursor = cursor + delta;
+ changed = 1;
+ }
+ yasm_xfree(pp->expr.symbol);
+ pp->expr.symbol = NULL;
+ }
+ }
+ gas_scan_cleanup(pp, &tokval);
+ pp->expr = prev_state;
+
+ if (changed) {
+ *line_ptr = line;
+ }
+
+ return changed;
+}
+
+static int process_line(yasm_preproc_gas *pp, char **line_ptr)
+{
+ macro_entry *macro;
+ size_t i;
+ char *line = *line_ptr;
+ struct {
+ const char *name;
+ int nargs;
+ pp_fn0_t fn;
+ int param;
+ } directives[] = {
+ {"else", 0, FN(eval_else), 0},
+ {"elseif", 1, FN(eval_elseif), 0},
+ {"endif", 0, FN(eval_endif), 0},
+ {"if", 1, FN(eval_if), 0},
+ {"ifb", 1, FN(eval_ifb), 0},
+ {"ifc", 1, FN(eval_ifc), 0},
+ {"ifdef", 1, FN(eval_ifdef), 0},
+ {"ifeq", 1, FN(eval_if), 1},
+ {"ifeqs", 1, FN(eval_ifeqs), 0},
+ {"ifge", 1, FN(eval_ifge), 0},
+ {"ifgt", 1, FN(eval_ifgt), 0},
+ {"ifle", 1, FN(eval_ifgt), 1},
+ {"iflt", 1, FN(eval_ifge), 1},
+ {"ifnb", 1, FN(eval_ifb), 1},
+ {"ifnc", 1, FN(eval_ifc), 1},
+ {"ifndef", 1, FN(eval_ifdef), 1},
+ {"ifnotdef", 1, FN(eval_ifdef), 1},
+ {"ifne", 1, FN(eval_if), 0},
+ {"ifnes", 1, FN(eval_ifeqs), 1},
+ {"include", 1, FN(eval_include), 0},
+ {"set", 2, FN(eval_set), 1},
+ {"equ", 2, FN(eval_set), 1},
+ {"equiv", 2, FN(eval_set), 0},
+ {"macro", 1, FN(eval_macro), 0},
+ {"endm", 0, FN(eval_endm), 0},
+ {"rept", 1, FN(eval_rept), 0},
+ {"endr", 1, FN(eval_endr), 0},
+ };
+
+ kill_comments(pp, line);
+ skip_whitespace2(&line);
+ if (*line == '\0') {
+ return FALSE;
+ }
+
+ /* See if this is a macro call. */
+ STAILQ_FOREACH(macro, &pp->macros, next) {
+ const char *remainder = starts_with(line, macro->name);
+ if (remainder && (!*remainder || isspace(*remainder))) {
+ skip_whitespace2(&line);
+ expand_macro(pp, macro, remainder);
+ return FALSE;
+ }
+ }
+
+ for (i = 0; i < sizeof(directives)/sizeof(directives[0]); i++) {
+ char buf1[1024];
+ const char *remainder = matches(line, directives[i].name);
+
+ if (remainder) {
+ if (pp->skip_depth) {
+ if (!strncmp("if", directives[i].name, 2)) {
+ pp->skip_depth++;
+ } else if (!strcmp("endif", directives[i].name)) {
+ pp->skip_depth--;
+ } else if (!strcmp("else", directives[i].name)) {
+ if (pp->skip_depth == 1) {
+ pp->skip_depth = 0;
+ pp->depth++;
+ }
+ }
+ return FALSE;
+ } else if (directives[i].nargs == 0) {
+ pp_fn0_t fn = (pp_fn0_t) directives[i].fn;
+ pp->fatal_error = !fn(pp, directives[i].param);
+ return FALSE;
+ } else if (directives[i].nargs == 1) {
+ pp_fn1_t fn = (pp_fn1_t) directives[i].fn;
+ skip_whitespace(&remainder);
+ pp->fatal_error = !fn(pp, directives[i].param, remainder);
+ return FALSE;
+ } else if (directives[i].nargs == 2) {
+ remainder = get_arg(pp, remainder, buf1, sizeof(buf1));
+ if (!remainder || !*remainder || !*buf1) {
+ yasm_error_set(YASM_ERROR_SYNTAX, N_("\".%s\" expects two arguments"), directives[i].name);
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ pp->fatal_error = 1;
+ } else {
+ pp_fn2_t fn = (pp_fn2_t) directives[i].fn;
+ pp->fatal_error = !fn(pp, directives[i].param, buf1, remainder);
+ }
+ return FALSE;
+ }
+ }
+ }
+
+ if (pp->skip_depth == 0) {
+ substitute_values(pp, line_ptr);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* Functions exported by the preprocessor. */
+
+static yasm_preproc *
+gas_preproc_create(const char *in_filename, yasm_symtab *symtab,
+ yasm_linemap *lm, yasm_errwarns *errwarns)
+{
+ FILE *f;
+ yasm_preproc_gas *pp = yasm_xmalloc(sizeof(yasm_preproc_gas));
+
+ if (strcmp(in_filename, "-") != 0) {
+ f = fopen(in_filename, "r");
+ if (!f) {
+ yasm__fatal_missing_input_file(N_("Could not open input file"), in_filename);
+ }
+ } else {
+ f = stdin;
+ }
+
+ pp->preproc.module = &yasm_gas_LTX_preproc;
+ pp->in = f;
+ pp->in_filename = yasm__xstrdup(in_filename);
+ pp->defines = yasm_symtab_create();
+ SLIST_INIT(&pp->deferred_defines);
+ yasm_symtab_set_case_sensitive(pp->defines, 1);
+ pp->depth = 0;
+ pp->skip_depth = 0;
+ pp->in_comment = FALSE;
+ SLIST_INIT(&pp->buffered_lines);
+ SLIST_INIT(&pp->included_files);
+ STAILQ_INIT(&pp->macros);
+ pp->in_line_number = 0;
+ pp->next_line_number = 0;
+ pp->current_line_number = 0;
+ pp->cur_lm = lm;
+ pp->errwarns = errwarns;
+ pp->fatal_error = 0;
+ pp->detect_errors_only = 0;
+
+ return (yasm_preproc *) pp;
+}
+
+static void
+gas_preproc_destroy(yasm_preproc *preproc)
+{
+ yasm_preproc_gas *pp = (yasm_preproc_gas *) preproc;
+ yasm_xfree(pp->in_filename);
+ yasm_symtab_destroy(pp->defines);
+ while (!SLIST_EMPTY(&pp->deferred_defines)) {
+ deferred_define *def = SLIST_FIRST(&pp->deferred_defines);
+ SLIST_REMOVE_HEAD(&pp->deferred_defines, next);
+ yasm_xfree(def->name);
+ yasm_xfree(def->value);
+ yasm_xfree(def);
+ }
+ while (!SLIST_EMPTY(&pp->buffered_lines)) {
+ buffered_line *bline = SLIST_FIRST(&pp->buffered_lines);
+ SLIST_REMOVE_HEAD(&pp->buffered_lines, next);
+ yasm_xfree(bline->line);
+ yasm_xfree(bline);
+ }
+ while (!SLIST_EMPTY(&pp->included_files)) {
+ included_file *inc_file = SLIST_FIRST(&pp->included_files);
+ SLIST_REMOVE_HEAD(&pp->included_files, next);
+ yasm_xfree(inc_file->filename);
+ yasm_xfree(inc_file);
+ }
+ while (!STAILQ_EMPTY(&pp->macros)) {
+ int i;
+ macro_entry *macro = STAILQ_FIRST(&pp->macros);
+ STAILQ_REMOVE_HEAD(&pp->macros, next);
+ yasm_xfree(macro->name);
+ for (i = 0; i < macro->num_params; i++)
+ yasm_xfree(macro->params[i]);
+ yasm_xfree(macro->params);
+ for (i = 0; i < macro->num_lines; i++)
+ yasm_xfree(macro->lines[i]);
+ yasm_xfree(macro->lines);
+ yasm_xfree(macro);
+ }
+ yasm_xfree(preproc);
+}
+
+static char *
+gas_preproc_get_line(yasm_preproc *preproc)
+{
+ yasm_preproc_gas *pp = (yasm_preproc_gas *)preproc;
+ int done = FALSE;
+ char *line = NULL;
+
+ pp->current_line_number++;
+
+ do {
+ if (line != NULL) {
+ yasm_xfree(line);
+ }
+ if (pp->fatal_error) {
+ return NULL;
+ }
+ line = read_line(pp);
+ if (line == NULL) {
+ if (pp->in_comment) {
+ yasm_linemap_set(pp->cur_lm, pp->in_filename, pp->current_line_number, pp->next_line_number, 0);
+ yasm_warn_set(YASM_WARN_GENERAL, N_("end of file in comment"));
+ yasm_errwarn_propagate(pp->errwarns, pp->current_line_number);
+ pp->in_comment = FALSE;
+ }
+ return NULL;
+ }
+ done = process_line(pp, &line);
+ } while (!done);
+
+ yasm_linemap_set(pp->cur_lm, pp->in_filename, pp->current_line_number, pp->next_line_number, 0);
+
+ return line;
+}
+
+static size_t
+gas_preproc_get_included_file(yasm_preproc *preproc, char *buf,
+ size_t max_size)
+{
+ /* TODO */
+ return 0;
+}
+
+static void
+gas_preproc_add_include_file(yasm_preproc *preproc, const char *filename)
+{
+ yasm_preproc_gas *pp = (yasm_preproc_gas *) preproc;
+ eval_include(pp, 0, filename);
+}
+
+static void
+gas_preproc_predefine_macro(yasm_preproc *preproc, const char *macronameval)
+{
+ yasm_preproc_gas *pp = (yasm_preproc_gas *) preproc;
+ const char *eq = strstr(macronameval, "=");
+ char *name, *value;
+ if (eq) {
+ value = yasm__xstrdup(eq + 1);
+ name = yasm_xmalloc(eq - macronameval + 1);
+ memcpy(name, macronameval, eq - macronameval);
+ name[eq - macronameval] = '\0';
+ } else {
+ name = yasm__xstrdup(macronameval);
+ value = yasm__xstrdup("");
+ }
+ eval_set(pp, 1, name, value);
+ yasm_xfree(name);
+ yasm_xfree(value);
+}
+
+static void
+gas_preproc_undefine_macro(yasm_preproc *preproc, const char *macroname)
+{
+ /* TODO */
+}
+
+static void
+gas_preproc_define_builtin(yasm_preproc *preproc, const char *macronameval)
+{
+ /* TODO */
+}
+
+static void
+gas_preproc_add_standard(yasm_preproc *preproc, const char **macros)
+{
+ /* TODO */
+}
+
+
+/* Define preproc structure -- see preproc.h for details */
+yasm_preproc_module yasm_gas_LTX_preproc = {
+ "GNU AS (GAS)-compatible preprocessor",
+ "gas",
+ gas_preproc_create,
+ gas_preproc_destroy,
+ gas_preproc_get_line,
+ gas_preproc_get_included_file,
+ gas_preproc_add_include_file,
+ gas_preproc_predefine_macro,
+ gas_preproc_undefine_macro,
+ gas_preproc_define_builtin,
+ gas_preproc_add_standard
+};
diff --git a/contrib/tools/yasm/modules/preprocs/nasm/genversion.c b/contrib/tools/yasm/modules/preprocs/nasm/genversion.c
new file mode 100644
index 0000000000..164b4d6b51
--- /dev/null
+++ b/contrib/tools/yasm/modules/preprocs/nasm/genversion.c
@@ -0,0 +1,81 @@
+/*
+ *
+ * Generate version.mac
+ *
+ * Copyright (C) 2006-2007 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 "config.h" /* for PACKAGE_VERSION */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+int
+main(int argc, char *argv[])
+{
+ FILE *out;
+ int major, minor, subminor, patchlevel, matched;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <outfile>\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ matched = sscanf(PACKAGE_VERSION, "%d.%d.%d.%d", &major, &minor, &subminor,
+ &patchlevel);
+
+ if (matched == 3)
+ patchlevel = 0;
+ else if (matched != 4) {
+ fprintf(stderr, "Version tokenizing error\n");
+ return EXIT_FAILURE;
+ }
+
+ out = fopen(argv[1], "wt");
+
+ if (!out) {
+ fprintf(stderr, "Could not open `%s'.\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+
+ fprintf(out, "; This file auto-generated by genversion.c"
+ " - don't edit it\n");
+
+ fprintf(out, "%%define __YASM_MAJOR__ %d\n", major);
+ fprintf(out, "%%define __YASM_MINOR__ %d\n", minor);
+ fprintf(out, "%%define __YASM_SUBMINOR__ %d\n", subminor);
+ fprintf(out, "%%define __YASM_BUILD__ %d\n", patchlevel);
+ fprintf(out, "%%define __YASM_PATCHLEVEL__ %d\n", patchlevel);
+
+ /* Version id (hex number) */
+ fprintf(out, "%%define __YASM_VERSION_ID__ 0%02x%02x%02x%02xh\n", major,
+ minor, subminor, patchlevel);
+
+ /* Version string */
+ fprintf(out, "%%define __YASM_VER__ \"%s\"\n", PACKAGE_VERSION);
+ fclose(out);
+
+ return EXIT_SUCCESS;
+}
diff --git a/contrib/tools/yasm/modules/preprocs/nasm/nasm-eval.c b/contrib/tools/yasm/modules/preprocs/nasm/nasm-eval.c
new file mode 100644
index 0000000000..e249484cd5
--- /dev/null
+++ b/contrib/tools/yasm/modules/preprocs/nasm/nasm-eval.c
@@ -0,0 +1,441 @@
+/* eval.c expression evaluator for the Netwide Assembler
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ *
+ * initial version 27/iii/95 by Simon Tatham
+ */
+#include <util.h>
+#include <libyasm-stdint.h>
+#include <libyasm/coretype.h>
+#include <libyasm/intnum.h>
+#include <libyasm/expr.h>
+#include <libyasm/symrec.h>
+#include <ctype.h>
+
+#include "nasm.h"
+#include "nasmlib.h"
+#include "nasm-eval.h"
+
+/* The assembler symbol table. */
+extern yasm_symtab *nasm_symtab;
+
+static scanner scan; /* Address of scanner routine */
+static efunc error; /* Address of error reporting routine */
+
+static struct tokenval *tokval; /* The current token */
+static int i; /* The t_type of tokval */
+
+static void *scpriv;
+
+/*
+ * Recursive-descent parser. Called with a single boolean operand,
+ * which is TRUE if the evaluation is critical (i.e. unresolved
+ * symbols are an error condition). Must update the global `i' to
+ * reflect the token after the parsed string. May return NULL.
+ *
+ * evaluate() should report its own errors: on return it is assumed
+ * that if NULL has been returned, the error has already been
+ * reported.
+ */
+
+/*
+ * Grammar parsed is:
+ *
+ * expr : bexpr [ WRT expr6 ]
+ * bexpr : rexp0 or expr0 depending on relative-mode setting
+ * rexp0 : rexp1 [ {||} rexp1...]
+ * rexp1 : rexp2 [ {^^} rexp2...]
+ * rexp2 : rexp3 [ {&&} rexp3...]
+ * rexp3 : expr0 [ {=,==,<>,!=,<,>,<=,>=} expr0 ]
+ * expr0 : expr1 [ {|} expr1...]
+ * expr1 : expr2 [ {^} expr2...]
+ * expr2 : expr3 [ {&} expr3...]
+ * expr3 : expr4 [ {<<,>>} expr4...]
+ * expr4 : expr5 [ {+,-} expr5...]
+ * expr5 : expr6 [ {*,/,%,//,%%} expr6...]
+ * expr6 : { ~,+,-,SEG } expr6
+ * | (bexpr)
+ * | symbol
+ * | $
+ * | number
+ */
+
+static yasm_expr *rexp0(void), *rexp1(void), *rexp2(void), *rexp3(void);
+
+static yasm_expr *expr0(void), *expr1(void), *expr2(void), *expr3(void);
+static yasm_expr *expr4(void), *expr5(void), *expr6(void);
+
+static yasm_expr *(*bexpr)(void);
+
+static yasm_expr *rexp0(void)
+{
+ yasm_expr *e, *f;
+
+ e = rexp1();
+ if (!e)
+ return NULL;
+
+ while (i == TOKEN_DBL_OR)
+ {
+ i = scan(scpriv, tokval);
+ f = rexp1();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_LOR, f, 0);
+ }
+ return e;
+}
+
+static yasm_expr *rexp1(void)
+{
+ yasm_expr *e, *f;
+
+ e = rexp2();
+ if (!e)
+ return NULL;
+
+ while (i == TOKEN_DBL_XOR)
+ {
+ i = scan(scpriv, tokval);
+ f = rexp2();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_LXOR, f, 0);
+ }
+ return e;
+}
+
+static yasm_expr *rexp2(void)
+{
+ yasm_expr *e, *f;
+
+ e = rexp3();
+ if (!e)
+ return NULL;
+ while (i == TOKEN_DBL_AND)
+ {
+ i = scan(scpriv, tokval);
+ f = rexp3();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_LAND, f, 0);
+ }
+ return e;
+}
+
+static yasm_expr *rexp3(void)
+{
+ yasm_expr *e, *f;
+
+ e = expr0();
+ if (!e)
+ return NULL;
+
+ while (i == TOKEN_EQ || i == TOKEN_LT || i == TOKEN_GT ||
+ i == TOKEN_NE || i == TOKEN_LE || i == TOKEN_GE)
+ {
+ int j = i;
+ i = scan(scpriv, tokval);
+ f = expr0();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (j)
+ {
+ case TOKEN_EQ:
+ e = yasm_expr_create_tree(e, YASM_EXPR_EQ, f, 0);
+ break;
+ case TOKEN_LT:
+ e = yasm_expr_create_tree(e, YASM_EXPR_LT, f, 0);
+ break;
+ case TOKEN_GT:
+ e = yasm_expr_create_tree(e, YASM_EXPR_GT, f, 0);
+ break;
+ case TOKEN_NE:
+ e = yasm_expr_create_tree(e, YASM_EXPR_NE, f, 0);
+ break;
+ case TOKEN_LE:
+ e = yasm_expr_create_tree(e, YASM_EXPR_LE, f, 0);
+ break;
+ case TOKEN_GE:
+ e = yasm_expr_create_tree(e, YASM_EXPR_GE, f, 0);
+ break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *expr0(void)
+{
+ yasm_expr *e, *f;
+
+ e = expr1();
+ if (!e)
+ return NULL;
+
+ while (i == '|')
+ {
+ i = scan(scpriv, tokval);
+ f = expr1();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_OR, f, 0);
+ }
+ return e;
+}
+
+static yasm_expr *expr1(void)
+{
+ yasm_expr *e, *f;
+
+ e = expr2();
+ if (!e)
+ return NULL;
+
+ while (i == '^') {
+ i = scan(scpriv, tokval);
+ f = expr2();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_XOR, f, 0);
+ }
+ return e;
+}
+
+static yasm_expr *expr2(void)
+{
+ yasm_expr *e, *f;
+
+ e = expr3();
+ if (!e)
+ return NULL;
+
+ while (i == '&') {
+ i = scan(scpriv, tokval);
+ f = expr3();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ e = yasm_expr_create_tree(e, YASM_EXPR_AND, f, 0);
+ }
+ return e;
+}
+
+static yasm_expr *expr3(void)
+{
+ yasm_expr *e, *f;
+
+ e = expr4();
+ if (!e)
+ return NULL;
+
+ while (i == TOKEN_SHL || i == TOKEN_SHR)
+ {
+ int j = i;
+ i = scan(scpriv, tokval);
+ f = expr4();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+
+ switch (j) {
+ case TOKEN_SHL:
+ e = yasm_expr_create_tree(e, YASM_EXPR_SHL, f, 0);
+ break;
+ case TOKEN_SHR:
+ e = yasm_expr_create_tree(e, YASM_EXPR_SHR, f, 0);
+ break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *expr4(void)
+{
+ yasm_expr *e, *f;
+
+ e = expr5();
+ if (!e)
+ return NULL;
+ while (i == '+' || i == '-')
+ {
+ int j = i;
+ i = scan(scpriv, tokval);
+ f = expr5();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+ switch (j) {
+ case '+':
+ e = yasm_expr_create_tree(e, YASM_EXPR_ADD, f, 0);
+ break;
+ case '-':
+ e = yasm_expr_create_tree(e, YASM_EXPR_SUB, f, 0);
+ break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *expr5(void)
+{
+ yasm_expr *e, *f;
+
+ e = expr6();
+ if (!e)
+ return NULL;
+ while (i == '*' || i == '/' || i == '%' ||
+ i == TOKEN_SDIV || i == TOKEN_SMOD)
+ {
+ int j = i;
+ i = scan(scpriv, tokval);
+ f = expr6();
+ if (!f) {
+ yasm_expr_destroy(e);
+ return NULL;
+ }
+ switch (j) {
+ case '*':
+ e = yasm_expr_create_tree(e, YASM_EXPR_MUL, f, 0);
+ break;
+ case '/':
+ e = yasm_expr_create_tree(e, YASM_EXPR_DIV, f, 0);
+ break;
+ case '%':
+ e = yasm_expr_create_tree(e, YASM_EXPR_MOD, f, 0);
+ break;
+ case TOKEN_SDIV:
+ e = yasm_expr_create_tree(e, YASM_EXPR_SIGNDIV, f, 0);
+ break;
+ case TOKEN_SMOD:
+ e = yasm_expr_create_tree(e, YASM_EXPR_SIGNMOD, f, 0);
+ break;
+ }
+ }
+ return e;
+}
+
+static yasm_expr *expr6(void)
+{
+ yasm_expr *e = NULL;
+
+ if (i == '-') {
+ i = scan(scpriv, tokval);
+ e = expr6();
+ if (!e)
+ return NULL;
+ return yasm_expr_create_branch(YASM_EXPR_NEG, e, 0);
+ } else if (i == '+') {
+ i = scan(scpriv, tokval);
+ return expr6();
+ } else if (i == '~') {
+ i = scan(scpriv, tokval);
+ e = expr6();
+ if (!e)
+ return NULL;
+ return yasm_expr_create_branch(YASM_EXPR_NOT, e, 0);
+ } else if (i == TOKEN_SEG) {
+ i = scan(scpriv, tokval);
+ e = expr6();
+ if (!e)
+ return NULL;
+ error(ERR_NONFATAL, "%s not supported", "SEG");
+ return e;
+ } else if (i == '(') {
+ i = scan(scpriv, tokval);
+ e = bexpr();
+ if (!e)
+ return NULL;
+ if (i != ')') {
+ error(ERR_NONFATAL, "expecting `)'");
+ return NULL;
+ }
+ i = scan(scpriv, tokval);
+ return e;
+ }
+ else if (i == TOKEN_NUM || i == TOKEN_ID ||
+ i == TOKEN_HERE || i == TOKEN_BASE)
+ {
+ switch (i) {
+ case TOKEN_NUM:
+ e = yasm_expr_create_ident(yasm_expr_int(tokval->t_integer), 0);
+ break;
+ case TOKEN_ID:
+ if (nasm_symtab) {
+ yasm_symrec *sym =
+ yasm_symtab_get(nasm_symtab, tokval->t_charptr);
+ if (sym) {
+ e = yasm_expr_create_ident(yasm_expr_sym(sym), 0);
+ } else {
+ error(ERR_NONFATAL,
+ "undefined symbol `%s' in preprocessor",
+ tokval->t_charptr);
+ e = yasm_expr_create_ident(yasm_expr_int(
+ yasm_intnum_create_int(1)), 0);
+ }
+ break;
+ }
+ /*fallthrough*/
+ case TOKEN_HERE:
+ case TOKEN_BASE:
+ error(ERR_NONFATAL,
+ "cannot reference symbol `%s' in preprocessor",
+ (i == TOKEN_ID ? tokval->t_charptr :
+ i == TOKEN_HERE ? "$" : "$$"));
+ e = yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_int(1)),
+ 0);
+ break;
+ }
+ i = scan(scpriv, tokval);
+ return e;
+ } else {
+ error(ERR_NONFATAL, "expression syntax error");
+ return NULL;
+ }
+}
+
+yasm_expr *nasm_evaluate (scanner sc, void *scprivate, struct tokenval *tv,
+ int critical, efunc report_error)
+{
+ if (critical & CRITICAL) {
+ critical &= ~CRITICAL;
+ bexpr = rexp0;
+ } else
+ bexpr = expr0;
+
+ scan = sc;
+ scpriv = scprivate;
+ tokval = tv;
+ error = report_error;
+
+ if (tokval->t_type == TOKEN_INVALID)
+ i = scan(scpriv, tokval);
+ else
+ i = tokval->t_type;
+
+ return bexpr ();
+}
diff --git a/contrib/tools/yasm/modules/preprocs/nasm/nasm-eval.h b/contrib/tools/yasm/modules/preprocs/nasm/nasm-eval.h
new file mode 100644
index 0000000000..f06937c5cc
--- /dev/null
+++ b/contrib/tools/yasm/modules/preprocs/nasm/nasm-eval.h
@@ -0,0 +1,18 @@
+/* eval.h header file for eval.c
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+#ifndef NASM_EVAL_H
+#define NASM_EVAL_H
+
+/*
+ * The evaluator itself.
+ */
+yasm_expr *nasm_evaluate (scanner sc, void *scprivate, struct tokenval *tv,
+ int critical, efunc report_error);
+
+#endif
diff --git a/contrib/tools/yasm/modules/preprocs/nasm/nasm-pp.c b/contrib/tools/yasm/modules/preprocs/nasm/nasm-pp.c
new file mode 100644
index 0000000000..27a8cc6c93
--- /dev/null
+++ b/contrib/tools/yasm/modules/preprocs/nasm/nasm-pp.c
@@ -0,0 +1,5317 @@
+/* -*- mode: c; c-file-style: "bsd" -*- */
+/* preproc.c macro preprocessor for the Netwide Assembler
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ *
+ * initial version 18/iii/97 by Simon Tatham
+ */
+
+/* Typical flow of text through preproc
+ *
+ * pp_getline gets tokenised lines, either
+ *
+ * from a macro expansion
+ *
+ * or
+ * {
+ * read_line gets raw text from stdmacpos, or predef, or current input file
+ * tokenise converts to tokens
+ * }
+ *
+ * expand_mmac_params is used to expand %1 etc., unless a macro is being
+ * defined or a false conditional is being processed
+ * (%0, %1, %+1, %-1, %%foo
+ *
+ * do_directive checks for directives
+ *
+ * expand_smacro is used to expand single line macros
+ *
+ * expand_mmacro is used to expand multi-line macros
+ *
+ * detoken is used to convert the line back to text
+ */
+#include <util.h>
+#include <libyasm-stdint.h>
+#include <libyasm/coretype.h>
+#include <libyasm/intnum.h>
+#include <libyasm/expr.h>
+#include <libyasm/file.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <limits.h>
+
+#include "nasm.h"
+#include "nasmlib.h"
+#include "nasm-pp.h"
+
+typedef struct SMacro SMacro;
+typedef struct MMacro MMacro;
+typedef struct Context Context;
+typedef struct Token Token;
+typedef struct Blocks Blocks;
+typedef struct Line Line;
+typedef struct Include Include;
+typedef struct Cond Cond;
+
+/*
+ * Store the definition of a single-line macro.
+ */
+struct SMacro
+{
+ SMacro *next;
+ char *name;
+ int level;
+ int casesense;
+ int nparam;
+ int in_progress;
+ Token *expansion;
+};
+
+/*
+ * Store the definition of a multi-line macro. This is also used to
+ * store the interiors of `%rep...%endrep' blocks, which are
+ * effectively self-re-invoking multi-line macros which simply
+ * don't have a name or bother to appear in the hash tables. %rep
+ * blocks are signified by having a NULL `name' field.
+ *
+ * In a MMacro describing a `%rep' block, the `in_progress' field
+ * isn't merely boolean, but gives the number of repeats left to
+ * run.
+ *
+ * The `next' field is used for storing MMacros in hash tables; the
+ * `next_active' field is for stacking them on istk entries.
+ *
+ * When a MMacro is being expanded, `params', `iline', `nparam',
+ * `paramlen', `rotate' and `unique' are local to the invocation.
+ */
+struct MMacro
+{
+ MMacro *next;
+ char *name;
+ int casesense;
+ long nparam_min, nparam_max;
+ int plus; /* is the last parameter greedy? */
+ int nolist; /* is this macro listing-inhibited? */
+ int in_progress;
+ Token *dlist; /* All defaults as one list */
+ Token **defaults; /* Parameter default pointers */
+ int ndefs; /* number of default parameters */
+ Line *expansion;
+
+ MMacro *next_active;
+ MMacro *rep_nest; /* used for nesting %rep */
+ Token **params; /* actual parameters */
+ Token *iline; /* invocation line */
+ long nparam, rotate, *paramlen;
+ unsigned long unique;
+ int lineno; /* Current line number on expansion */
+};
+
+/*
+ * The context stack is composed of a linked list of these.
+ */
+struct Context
+{
+ Context *next;
+ SMacro *localmac;
+ char *name;
+ unsigned long number;
+};
+
+/*
+ * This is the internal form which we break input lines up into.
+ * Typically stored in linked lists.
+ *
+ * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not
+ * necessarily used as-is, but is intended to denote the number of
+ * the substituted parameter. So in the definition
+ *
+ * %define a(x,y) ( (x) & ~(y) )
+ *
+ * the token representing `x' will have its type changed to
+ * TOK_SMAC_PARAM, but the one representing `y' will be
+ * TOK_SMAC_PARAM+1.
+ *
+ * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
+ * which doesn't need quotes around it. Used in the pre-include
+ * mechanism as an alternative to trying to find a sensible type of
+ * quote to use on the filename we were passed.
+ */
+struct Token
+{
+ Token *next;
+ char *text;
+ SMacro *mac; /* associated macro for TOK_SMAC_END */
+ int type;
+};
+enum
+{
+ TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,
+ TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM,
+ TOK_INTERNAL_STRING
+};
+
+/*
+ * Multi-line macro definitions are stored as a linked list of
+ * these, which is essentially a container to allow several linked
+ * lists of Tokens.
+ *
+ * Note that in this module, linked lists are treated as stacks
+ * wherever possible. For this reason, Lines are _pushed_ on to the
+ * `expansion' field in MMacro structures, so that the linked list,
+ * if walked, would give the macro lines in reverse order; this
+ * means that we can walk the list when expanding a macro, and thus
+ * push the lines on to the `expansion' field in _istk_ in reverse
+ * order (so that when popped back off they are in the right
+ * order). It may seem cockeyed, and it relies on my design having
+ * an even number of steps in, but it works...
+ *
+ * Some of these structures, rather than being actual lines, are
+ * markers delimiting the end of the expansion of a given macro.
+ * This is for use in the cycle-tracking and %rep-handling code.
+ * Such structures have `finishes' non-NULL, and `first' NULL. All
+ * others have `finishes' NULL, but `first' may still be NULL if
+ * the line is blank.
+ */
+struct Line
+{
+ Line *next;
+ MMacro *finishes;
+ Token *first;
+};
+
+/*
+ * To handle an arbitrary level of file inclusion, we maintain a
+ * stack (ie linked list) of these things.
+ */
+struct Include
+{
+ Include *next;
+ FILE *fp;
+ Cond *conds;
+ Line *expansion;
+ char *fname;
+ int lineno, lineinc;
+ MMacro *mstk; /* stack of active macros/reps */
+};
+
+/*
+ * Conditional assembly: we maintain a separate stack of these for
+ * each level of file inclusion. (The only reason we keep the
+ * stacks separate is to ensure that a stray `%endif' in a file
+ * included from within the true branch of a `%if' won't terminate
+ * it and cause confusion: instead, rightly, it'll cause an error.)
+ */
+struct Cond
+{
+ Cond *next;
+ int state;
+};
+enum
+{
+ /*
+ * These states are for use just after %if or %elif: IF_TRUE
+ * means the condition has evaluated to truth so we are
+ * currently emitting, whereas IF_FALSE means we are not
+ * currently emitting but will start doing so if a %else comes
+ * up. In these states, all directives are admissible: %elif,
+ * %else and %endif. (And of course %if.)
+ */
+ COND_IF_TRUE, COND_IF_FALSE,
+ /*
+ * These states come up after a %else: ELSE_TRUE means we're
+ * emitting, and ELSE_FALSE means we're not. In ELSE_* states,
+ * any %elif or %else will cause an error.
+ */
+ COND_ELSE_TRUE, COND_ELSE_FALSE,
+ /*
+ * This state means that we're not emitting now, and also that
+ * nothing until %endif will be emitted at all. It's for use in
+ * two circumstances: (i) when we've had our moment of emission
+ * and have now started seeing %elifs, and (ii) when the
+ * condition construct in question is contained within a
+ * non-emitting branch of a larger condition construct.
+ */
+ COND_NEVER
+};
+#define emitting(x) ( (x) == COND_IF_TRUE || (x) == COND_ELSE_TRUE )
+
+/*
+ * These defines are used as the possible return values for do_directive
+ */
+#define NO_DIRECTIVE_FOUND 0
+#define DIRECTIVE_FOUND 1
+
+/*
+ * Condition codes. Note that we use c_ prefix not C_ because C_ is
+ * used in nasm.h for the "real" condition codes. At _this_ level,
+ * we treat CXZ and ECXZ as condition codes, albeit non-invertible
+ * ones, so we need a different enum...
+ */
+static const char *conditions[] = {
+ "a", "ae", "b", "be", "c", "cxz", "e", "ecxz", "g", "ge", "l", "le",
+ "na", "nae", "nb", "nbe", "nc", "ne", "ng", "nge", "nl", "nle", "no",
+ "np", "ns", "nz", "o", "p", "pe", "po", "s", "z"
+};
+enum
+{
+ c_A, c_AE, c_B, c_BE, c_C, c_CXZ, c_E, c_ECXZ, c_G, c_GE, c_L, c_LE,
+ c_NA, c_NAE, c_NB, c_NBE, c_NC, c_NE, c_NG, c_NGE, c_NL, c_NLE, c_NO,
+ c_NP, c_NS, c_NZ, c_O, c_P, c_PE, c_PO, c_S, c_Z
+};
+static int inverse_ccs[] = {
+ c_NA, c_NAE, c_NB, c_NBE, c_NC, -1, c_NE, -1, c_NG, c_NGE, c_NL, c_NLE,
+ c_A, c_AE, c_B, c_BE, c_C, c_E, c_G, c_GE, c_L, c_LE, c_O, c_P, c_S,
+ c_Z, c_NO, c_NP, c_PO, c_PE, c_NS, c_NZ
+};
+
+/*
+ * Directive names.
+ */
+static const char *directives[] = {
+ "%arg",
+ "%assign", "%clear", "%define", "%elif", "%elifctx", "%elifdef",
+ "%elifid", "%elifidn", "%elifidni", "%elifmacro", "%elifnctx", "%elifndef",
+ "%elifnid", "%elifnidn", "%elifnidni", "%elifnmacro", "%elifnnum", "%elifnstr",
+ "%elifnum", "%elifstr", "%else", "%endif", "%endm", "%endmacro",
+ "%endrep", "%endscope", "%error", "%exitrep", "%iassign", "%idefine", "%if",
+ "%ifctx", "%ifdef", "%ifid", "%ifidn", "%ifidni", "%ifmacro", "%ifnctx",
+ "%ifndef", "%ifnid", "%ifnidn", "%ifnidni", "%ifnmacro", "%ifnnum",
+ "%ifnstr", "%ifnum", "%ifstr", "%imacro", "%include",
+ "%ixdefine", "%line",
+ "%local",
+ "%macro", "%pop", "%push", "%rep", "%repl", "%rotate",
+ "%scope", "%stacksize",
+ "%strlen", "%substr", "%undef", "%xdefine"
+};
+enum
+{
+ PP_ARG,
+ PP_ASSIGN, PP_CLEAR, PP_DEFINE, PP_ELIF, PP_ELIFCTX, PP_ELIFDEF,
+ PP_ELIFID, PP_ELIFIDN, PP_ELIFIDNI, PP_ELIFMACRO, PP_ELIFNCTX, PP_ELIFNDEF,
+ PP_ELIFNID, PP_ELIFNIDN, PP_ELIFNIDNI, PP_ELIFNMACRO, PP_ELIFNNUM, PP_ELIFNSTR,
+ PP_ELIFNUM, PP_ELIFSTR, PP_ELSE, PP_ENDIF, PP_ENDM, PP_ENDMACRO,
+ PP_ENDREP, PP_ENDSCOPE, PP_ERROR, PP_EXITREP, PP_IASSIGN, PP_IDEFINE, PP_IF,
+ PP_IFCTX, PP_IFDEF, PP_IFID, PP_IFIDN, PP_IFIDNI, PP_IFMACRO, PP_IFNCTX,
+ PP_IFNDEF, PP_IFNID, PP_IFNIDN, PP_IFNIDNI, PP_IFNMACRO, PP_IFNNUM,
+ PP_IFNSTR, PP_IFNUM, PP_IFSTR, PP_IMACRO, PP_INCLUDE,
+ PP_IXDEFINE, PP_LINE,
+ PP_LOCAL,
+ PP_MACRO, PP_POP, PP_PUSH, PP_REP, PP_REPL, PP_ROTATE,
+ PP_SCOPE, PP_STACKSIZE,
+ PP_STRLEN, PP_SUBSTR, PP_UNDEF, PP_XDEFINE
+};
+
+/* If this is a an IF, ELIF, ELSE or ENDIF keyword */
+static int is_condition(int arg)
+{
+ return ((arg >= PP_ELIF) && (arg <= PP_ENDIF)) ||
+ ((arg >= PP_IF) && (arg <= PP_IFSTR));
+}
+
+/* For TASM compatibility we need to be able to recognise TASM compatible
+ * conditional compilation directives. Using the NASM pre-processor does
+ * not work, so we look for them specifically from the following list and
+ * then jam in the equivalent NASM directive into the input stream.
+ */
+
+#ifndef MAX
+# define MAX(a,b) ( ((a) > (b)) ? (a) : (b))
+#endif
+
+enum
+{
+ TM_ARG, TM_ELIF, TM_ELSE, TM_ENDIF, TM_IF, TM_IFDEF, TM_IFDIFI,
+ TM_IFNDEF, TM_INCLUDE, TM_LOCAL,
+ TM_REPT, TM_IRP, TM_MACRO,
+ TM_STRUC, TM_SEGMENT
+};
+
+static const char *tasm_directives[] = {
+ "arg", "elif", "else", "endif", "if", "ifdef", "ifdifi",
+ "ifndef", "include", "local"
+};
+
+static int StackSize = 4;
+static const char *StackPointer = "ebp";
+static int ArgOffset = 8;
+static int LocalOffset = 4;
+static int Level = 0;
+
+
+static Context *cstk;
+static Include *istk;
+
+static FILE *first_fp = NULL;
+
+static efunc _error; /* Pointer to client-provided error reporting function */
+static evalfunc evaluate;
+
+static int pass; /* HACK: pass 0 = generate dependencies only */
+
+static unsigned long unique; /* unique identifier numbers */
+
+static Line *builtindef = NULL;
+static Line *stddef = NULL;
+static Line *predef = NULL;
+static int first_line = 1;
+
+static ListGen *list;
+
+/*
+ * The number of hash values we use for the macro lookup tables.
+ * FIXME: We should *really* be able to configure this at run time,
+ * or even have the hash table automatically expanding when necessary.
+ */
+#define NHASH 4096
+
+/*
+ * The current set of multi-line macros we have defined.
+ */
+static MMacro *mmacros[NHASH];
+
+/*
+ * The current set of single-line macros we have defined.
+ */
+static SMacro *smacros[NHASH];
+
+/*
+ * The multi-line macro we are currently defining, or the %rep
+ * block we are currently reading, if any.
+ */
+static MMacro *defining;
+
+/*
+ * The number of macro parameters to allocate space for at a time.
+ */
+#define PARAM_DELTA 16
+
+/*
+ * Macros to make NASM ignore some TASM directives before the first include
+ * directive.
+ */
+static const char *tasm_compat_macros[] =
+{
+ "%idefine IDEAL",
+ "%idefine JUMPS",
+ "%idefine END",
+ "%idefine P8086 CPU 8086",
+ "%idefine P186 CPU 186",
+ "%idefine P286 CPU 286",
+ "%idefine P286N CPU 286",
+ "%idefine P286P CPU 286 Priv",
+ "%idefine P386 CPU 386",
+ "%idefine P386N CPU 386",
+ "%idefine P386P CPU 386 Priv",
+ "%idefine P486 CPU 486",
+ "%idefine P586 CPU 586",
+ "%idefine .8086 CPU 8086",
+ "%idefine .186 CPU 186",
+ "%idefine .286 CPU 286",
+ "%idefine .286C CPU 286",
+ "%idefine .286P CPU 286",
+ "%idefine .386 CPU 386",
+ "%idefine .386C CPU 386",
+ "%idefine .386P CPU 386",
+ "%idefine .486 CPU 486",
+ "%idefine .486C CPU 486",
+ "%idefine .486P CPU 486",
+ "%idefine .586 CPU 586",
+ "%idefine .586C CPU 586",
+ "%idefine .586P CPU 586",
+ "",
+ "%imacro TITLE 1",
+ "%endm",
+ "%imacro NAME 1",
+ "%endm",
+ "",
+ "%imacro EXTRN 1-*.nolist",
+ "%rep %0",
+ "[extern %1]",
+ "%rotate 1",
+ "%endrep",
+ "%endmacro",
+ "",
+ "%imacro PUBLIC 1-*.nolist",
+ "%rep %0",
+ "[global %1]",
+ "%rotate 1",
+ "%endrep",
+ "%endmacro",
+ "",
+ "; this is not needed",
+ "%idefine PTR",
+ NULL
+};
+
+static int nested_mac_count, nested_rep_count;
+
+/*
+ * Tokens are allocated in blocks to improve speed
+ */
+#define TOKEN_BLOCKSIZE 4096
+static Token *freeTokens = NULL;
+struct Blocks {
+ Blocks *next;
+ void *chunk;
+};
+
+static Blocks blocks = { NULL, NULL };
+
+/*
+ * Forward declarations.
+ */
+static Token *expand_mmac_params(Token * tline);
+static Token *expand_smacro(Token * tline);
+static Token *expand_id(Token * tline);
+static Context *get_ctx(char *name, int all_contexts);
+static void make_tok_num(Token * tok, yasm_intnum *val);
+static void error(int severity, const char *fmt, ...);
+static void *new_Block(size_t size);
+static void delete_Blocks(void);
+static Token *new_Token(Token * next, int type, const char *text,
+ size_t txtlen);
+static Token *delete_Token(Token * t);
+static Token *tokenise(char *line);
+
+/*
+ * Macros for safe checking of token pointers, avoid *(NULL)
+ */
+#define tok_type_(x,t) ((x) && (x)->type == (t))
+#define skip_white_(x) if (tok_type_((x), TOK_WHITESPACE)) (x)=(x)->next
+#define tok_is_(x,v) (tok_type_((x), TOK_OTHER) && !strcmp((x)->text,(v)))
+#define tok_isnt_(x,v) ((x) && ((x)->type!=TOK_OTHER || strcmp((x)->text,(v))))
+
+/* Handle TASM specific directives, which do not contain a % in
+ * front of them. We do it here because I could not find any other
+ * place to do it for the moment, and it is a hack (ideally it would
+ * be nice to be able to use the NASM pre-processor to do it).
+ */
+
+typedef struct TMEndItem {
+ int type;
+ void *data;
+ struct TMEndItem *next;
+} TMEndItem;
+
+static TMEndItem *EndmStack = NULL, *EndsStack = NULL;
+
+char **TMParameters;
+
+struct TStrucField {
+ char *name;
+ char *type;
+ struct TStrucField *next;
+};
+struct TStruc {
+ char *name;
+ struct TStrucField *fields, *lastField;
+ struct TStruc *next;
+};
+static struct TStruc *TStrucs = NULL;
+static int inTstruc = 0;
+
+struct TSegmentAssume {
+ char *segreg;
+ char *segment;
+};
+struct TSegmentAssume *TAssumes;
+
+const char *tasm_get_segment_register(const char *segment)
+{
+ struct TSegmentAssume *assume;
+ if (!TAssumes)
+ return NULL;
+ for (assume = TAssumes; assume->segreg; assume++) {
+ if (!strcmp(assume->segment, segment))
+ break;
+ }
+ return assume->segreg;
+}
+
+static char *
+check_tasm_directive(char *line)
+{
+ int i, j, k, m;
+ size_t len, len2;
+ char *p, *oldline, oldchar, *q, oldchar2;
+ TMEndItem *end;
+
+ p = line;
+
+ /* Skip whitespace */
+ while (isspace(*p) && *p != 0 && *p != ';')
+ p++;
+
+ /* Ignore nasm directives */
+ if (*p == '%')
+ return line;
+
+ /* Binary search for the directive name */
+ len = 0;
+ while (!isspace(p[len]) && p[len] != 0 && p[len] != ';')
+ len++;
+ if (!len)
+ return line;
+
+ oldchar = p[len];
+ p[len] = 0;
+ i = -1;
+ j = elements(tasm_directives);
+ while (j - i > 1)
+ {
+ k = (j + i) / 2;
+ m = nasm_stricmp(p, tasm_directives[k]);
+ if (m == 0)
+ {
+ /* We have found a directive, so jam a % in front of it
+ * so that NASM will then recognise it as one if it's own.
+ */
+ p[len] = oldchar;
+ len = strlen(p);
+ oldline = line;
+ if (k == TM_IFDIFI)
+ {
+ /* NASM does not recognise IFDIFI, so we convert it to
+ * %ifdef BOGUS. This is not used in NASM comaptible
+ * code, but does need to parse for the TASM macro
+ * package.
+ */
+ line = nasm_malloc(13);
+ strcpy(line, "%ifdef BOGUS");
+ }
+ else if (k == TM_INCLUDE)
+ {
+ /* add double quotes around file name */
+ p += 7 + 1;
+ while (isspace(*p) && *p)
+ p++;
+ len = strlen(p);
+ line = nasm_malloc(1 + 7 + 1 + 1 + len + 1 + 1);
+ sprintf(line, "%%include \"%s\"", p);
+ }
+ else
+ {
+ line = nasm_malloc(len + 2);
+ line[0] = '%';
+ memcpy(line + 1, p, len + 1);
+ }
+ nasm_free(oldline);
+ return line;
+ }
+ else if (m < 0)
+ {
+ j = k;
+ }
+ else
+ i = k;
+ }
+
+ /* Not a simple directive */
+
+ if (!nasm_stricmp(p, "endm")) {
+ /* handle end of endm directive */
+ char **parameter;
+ end = EndmStack;
+ /* undef parameters */
+ if (!end) {
+ error(ERR_FATAL, "ENDM: not in an endm context");
+ return line;
+ }
+ EndmStack = EndmStack->next;
+ nasm_free(line);
+ switch (end->type) {
+ case TM_MACRO:
+ len = 0;
+ for (parameter = end->data; *parameter; parameter++)
+ len += 6 + 1 + strlen(*parameter) + 1;
+ len += 5 + 1;
+ line = nasm_malloc(len);
+ p = line;
+ for (parameter = end->data; *parameter; parameter++) {
+ p += sprintf(p, "%%undef %s\n", *parameter);
+ nasm_free(*parameter);
+ }
+ nasm_free(end->data);
+ nasm_free(end);
+ sprintf(p, "%%endm");
+ return line;
+ case TM_REPT:
+ nasm_free(end);
+ return nasm_strdup("%endrep");
+ case TM_IRP: {
+ char **data;
+ const char *irp_format =
+ "%%undef %s\n"
+ "%%rotate 1\n"
+ "%%endrep\n"
+ "%%endm\n"
+ "irp %s\n"
+ "%%undef irp";
+ data = end->data;
+ line = nasm_malloc(strlen(irp_format) - 4 + strlen(data[0])
+ + strlen(data[1]));
+ sprintf(line, irp_format, data[0], data[1]);
+ nasm_free(data[0]);
+ nasm_free(data[1]);
+ nasm_free(data);
+ return line;
+ }
+ default:
+ error(ERR_FATAL, "ENDM: bogus endm context type %d\n",end->type);
+ return NULL;
+ }
+ } else if (!nasm_stricmp(p, "end")) {
+ nasm_free(line);
+ return nasm_strdup("");
+ } else if (!nasm_stricmp(p, "rept")) {
+ /* handle repeat directive */
+ end = nasm_malloc(sizeof(*end));
+ end->type = TM_REPT;
+ end->next = EndmStack;
+ EndmStack = end;
+ memcpy(p, "%rep", 4);
+ p[len] = oldchar;
+ return line;
+ } else if (!nasm_stricmp(p, "locals")) {
+ tasm_locals = 1;
+ nasm_free(line);
+ return nasm_strdup("");
+ }
+
+ if (!oldchar)
+ return line;
+
+ /* handle two-words directives */
+ q = p + len + 1;
+ /* Skip whitespaces */
+ while (isspace(*q) && *q)
+ q++;
+
+ len2 = 0;
+ while (!isspace(q[len2]) && q[len2]!=',' && q[len2] != 0)
+ len2++;
+ oldchar2 = q[len2];
+ q[len2] = '\0';
+
+ if (!nasm_stricmp(p, "irp")) {
+ /* handle indefinite repeat directive */
+ const char *irp_format =
+ "%%imacro irp 0-*\n"
+ "%%rep %%0\n"
+ "%%define %s %%1\n";
+ char **data;
+
+ data = malloc(2*sizeof(char*));
+ oldline = line;
+ line = nasm_malloc(strlen(irp_format) - 2 + len2 + 1);
+ sprintf(line,irp_format,q);
+ data[0] = nasm_strdup(q);
+
+ if (!oldchar2)
+ error(ERR_FATAL, "%s: expected <values>", q + len2);
+ p = strchr(q + len2 + 1, '<');
+ if (!p)
+ error(ERR_FATAL, "%s: expected <values>", q + len2);
+ p++;
+ q = strchr(p, '>');
+ data[1] = nasm_strndup(p, q - p);
+
+ end = nasm_malloc(sizeof(*end));
+ end->type = TM_IRP;
+ end->next = EndmStack;
+ end->data = data;
+ EndmStack = end;
+
+ nasm_free(oldline);
+ return line;
+ } else if (!nasm_stricmp(q, "macro")) {
+ char *name = p;
+ /* handle MACRO */
+ /* count parameters */
+ j = 1;
+ i = 0;
+ TMParameters = nasm_malloc(j*sizeof(*TMParameters));
+ len = 0;
+ p = q + len2 + 1;
+ /* Skip whitespaces */
+ while (isspace(*p) && *p)
+ p++;
+ while (*p) {
+ /* Get parameter name */
+ for (q = p; !isspace(*q) && *q != ',' && *q; q++);
+ len2 = q-p;
+ if (len2 == 0)
+ error(ERR_FATAL, "'%s': expected parameter name", p);
+ TMParameters[i] = nasm_malloc(len2 + 1);
+ memcpy(TMParameters[i], p, len2);
+ TMParameters[i][len2] = '\0';
+ len += len2;
+ i++;
+ if (i + 1 > j) {
+ j *= 2;
+ TMParameters = nasm_realloc(TMParameters,
+ j*sizeof(*TMParameters));
+ }
+ if (i == 1000)
+ error(ERR_FATAL, "too many parameters for macro %s", name);
+ p = q;
+ while (isspace(*p) && *p)
+ p++;
+ if (!*p)
+ break;
+ if (*p != ',')
+ error(ERR_FATAL, "expected comma");
+ p++;
+ while (isspace(*p) && *p)
+ p++;
+ }
+ TMParameters[i] = NULL;
+ TMParameters = nasm_realloc(TMParameters,
+ (i+1)*sizeof(*TMParameters));
+ len += 1 + 6 + 1 + strlen(name) + 1 + 3; /* macro definition */
+ len += i * (1 + 9 + 1 + 1 + 1 + 3 + 2); /* macro parameter definition */
+ oldline = line;
+ p = line = nasm_malloc(len + 1);
+ p += sprintf(p, "%%imacro %s 0-*", name);
+ nasm_free(oldline);
+ for (j = 0; TMParameters[j]; j++) {
+ p += sprintf(p, "\n%%idefine %s %%{%-u}", TMParameters[j], j + 1);
+ }
+ end = nasm_malloc(sizeof(*end));
+ end->type = TM_MACRO;
+ end->next = EndmStack;
+ end->data = TMParameters;
+ EndmStack = end;
+ return line;
+ } else if (!nasm_stricmp(q, "proc")) {
+ /* handle PROC */
+ oldline = line;
+ line = nasm_malloc(2 + len + 1);
+ sprintf(line, "..%s",p);
+ nasm_free(oldline);
+ return line;
+ } else if (!nasm_stricmp(q, "struc")) {
+ /* handle struc */
+ struct TStruc *struc;
+ if (inTstruc) {
+ error(ERR_FATAL, "STRUC: already in a struc context");
+ return line;
+ }
+ oldline = line;
+ line = nasm_malloc(5 + 1 + len + 1);
+ sprintf(line, "struc %s", p);
+ struc = malloc(sizeof(*struc));
+ struc->name = nasm_strdup(p);
+ struc->fields = NULL;
+ struc->lastField = NULL;
+ struc->next = TStrucs;
+ TStrucs = struc;
+ inTstruc = 1;
+ nasm_free(oldline);
+ end = nasm_malloc(sizeof(*end));
+ end->type = TM_STRUC;
+ end->next = EndsStack;
+ EndsStack = end;
+ return line;
+ } else if (!nasm_stricmp(q, "segment")) {
+ /* handle SEGMENT */
+ oldline = line;
+ line = nasm_strdup(oldchar2?q+len2+1:"");
+ if (tasm_segment) {
+ error(ERR_FATAL, "SEGMENT: already in a segment context");
+ return line;
+ }
+ tasm_segment = nasm_strdup(p);
+ nasm_free(oldline);
+ end = nasm_malloc(sizeof(*end));
+ end->type = TM_SEGMENT;
+ end->next = EndsStack;
+ EndsStack = end;
+ return line;
+ } else if (!nasm_stricmp(p, "ends") || !nasm_stricmp(q, "ends")) {
+ /* handle end of ends directive */
+ end = EndsStack;
+ /* undef parameters */
+ if (!end) {
+ error(ERR_FATAL, "ENDS: not in an ends context");
+ return line;
+ }
+ EndsStack = EndsStack->next;
+ nasm_free(line);
+ switch (end->type) {
+ case TM_STRUC:
+ inTstruc = 0;
+ return nasm_strdup("endstruc");
+ case TM_SEGMENT:
+ /* XXX: yes, we leak memory here, but that permits labels
+ * to avoid strduping... */
+ tasm_segment = NULL;
+ return nasm_strdup("");
+ default:
+ error(ERR_FATAL, "ENDS: bogus ends context type %d",end->type);
+ return NULL;
+ }
+ } else if (!nasm_stricmp(p, "endp") || !nasm_stricmp(q, "endp")) {
+ nasm_free(line);
+ return nasm_strdup("");
+ } else if (!nasm_stricmp(p, "assume")) {
+ struct TSegmentAssume *assume;
+ /* handle ASSUME */
+ if (!TAssumes) {
+ TAssumes = nasm_malloc(sizeof(*TAssumes));
+ TAssumes[0].segreg = NULL;
+ }
+ i = 0;
+ q[len2] = oldchar2;
+ /* Skip whitespaces */
+ while (isspace(*q) && *q)
+ q++;
+ while (*q && *q != ';') {
+ p = q;
+ for (; *q && *q != ';' && *q != ':' && !isspace(*q); q++);
+ if (!*q || *q == ';')
+ break;
+ /* segment register name */
+ for (assume = TAssumes; assume->segreg; assume++)
+ if (strlen(assume->segreg) == (size_t)(q-p) &&
+ !yasm__strncasecmp(assume->segreg, p, q-p))
+ break;
+ if (!assume->segreg) {
+ i = assume - TAssumes + 1;
+ TAssumes = nasm_realloc(TAssumes, (i+1)*sizeof(*TAssumes));
+ assume = TAssumes + i - 1;
+ assume->segreg = nasm_strndup(p, q-p);
+ assume[1].segreg = NULL;
+ }
+ for (; *q && *q != ';' && *q != ':' && isspace(*q); q++);
+ if (*q != ':')
+ error(ERR_FATAL, "expected `:' instead of `%c'", *q);
+ for (q++; *q && isspace(*q); q++);
+
+ /* segment name */
+ p = q;
+ for (; *q && *q != ';' && *q != ',' && !isspace(*q); q++);
+ assume->segment = nasm_strndup(p, q-p);
+ for (; *q && isspace(*q); q++);
+ if (*q && *q != ';' && *q != ',')
+ error(ERR_FATAL, "expected `,' instead of `%c'", *q);
+
+ if (*q && *q != ';')
+ q++;
+ for (; *q && isspace(*q); q++);
+ }
+ TAssumes[i].segreg = NULL;
+ TAssumes = nasm_realloc(TAssumes, (i+1)*sizeof(*TAssumes));
+ nasm_free(line);
+ return nasm_strdup("");
+ } else if (inTstruc) {
+ struct TStrucField *field;
+ /* TODO: handle unnamed data */
+ field = nasm_malloc(sizeof(*field));
+ field->name = nasm_strdup(p);
+ /* TODO: type struc ! */
+ field->type = nasm_strdup(q);
+ field->next = NULL;
+ if (!TStrucs->fields)
+ TStrucs->fields = field;
+ else if (TStrucs->lastField)
+ TStrucs->lastField->next = field;
+ TStrucs->lastField = field;
+ if (!oldchar2) {
+ error(ERR_FATAL, "Expected struc field initializer after %s %s", p, q);
+ return line;
+ }
+ oldline = line;
+ line = nasm_malloc(1 + len + 1 + len2 + 1 + strlen(q+len2+1) + 1);
+ sprintf(line, ".%s %s %s", p, q, q+len2+1);
+ nasm_free(oldline);
+ return line;
+ }
+ {
+ struct TStruc *struc;
+ for (struc = TStrucs; struc; struc = struc->next) {
+ if (!yasm__strcasecmp(q, struc->name)) {
+ char *r = q + len2 + 1, *s, *t, tasm_param[6];
+ struct TStrucField *field = struc->fields;
+ int size, n;
+ if (!oldchar2) {
+ error(ERR_FATAL, "Expected struc field initializer after %s %s", p, q);
+ return line;
+ }
+ r = strchr(r, '<');
+ if (!r) {
+ error(ERR_FATAL, "Expected < for struc field initializer in %s %s %s", p, q, r);
+ return line;
+ }
+ t = strchr(r + 1, '>');
+ if (!t) {
+ error(ERR_FATAL, "Expected > for struc field initializer in %s %s %s", p, q, r);
+ return line;
+ }
+ *t = 0;
+ oldline = line;
+ size = len + len2 + 128;
+ line = nasm_malloc(size);
+ if (defining)
+ for (n=0;TMParameters[n];n++)
+ if (!strcmp(TMParameters[n],p)) {
+ sprintf(tasm_param,"%%{%d}",n+1);
+ p = tasm_param;
+ break;
+ }
+ n = sprintf(line, "%s: istruc %s\n", p, q);
+ /* use initialisers */
+ while ((s = strchr(r + 1, ','))) {
+ if (!field) {
+ error(ERR_FATAL, "Too many initializers in structure %s %s", p, q);
+ return oldline;
+ }
+ *s = 0;
+ m = strlen(p) + 1 + strlen(field->name)*2 + 8 +
+ strlen(field->type) + 1 + strlen(r+1) + 2;
+ size += m;
+ line = nasm_realloc(line, size);
+ sprintf(line + n, "%s.%s: at .%s, %s %s\n",
+ p, field->name, field->name, field->type, r + 1);
+ n += m-1;
+ r = s;
+ field = field->next;
+ }
+ /* complete with last initializer and '?' */
+ while(field) {
+ m = strlen(p) + 1 + strlen(field->name)*2 + 8 +
+ strlen(field->type) + 1 + (r ? strlen(r+1) : 1) + 2;
+ size += m;
+ line = nasm_realloc(line, size);
+ sprintf(line + n, "%s.%s: at .%s, %s %s\n", p, field->name,
+ field->name, field->type, r ? r + 1: "?");
+ n += m-1;
+ r = NULL;
+ field = field->next;
+ }
+ line = nasm_realloc(line, n + 5);
+ sprintf(line + n, "iend");
+ nasm_free(oldline);
+ return line;
+ }
+ }
+ }
+
+ q[len2] = oldchar2;
+ p[len] = oldchar;
+
+ return line;
+}
+
+static Token * tasm_join_tokens(Token *tline)
+{
+ Token *t, *prev, *next;
+ for (prev = NULL, t = tline; t; prev = t, t = next) {
+ next = t->next;
+ if (t->type == TOK_OTHER && !strcmp(t->text,"&")) {
+ if (!prev)
+ error(ERR_FATAL, "no token before &");
+ else if (!next)
+ error(ERR_FATAL, "no token after &");
+ else if (prev->type != next->type)
+ error(ERR_FATAL, "can't handle different types of token around &");
+ else if (!prev->text || !next->text)
+ error(ERR_FATAL, "can't handle empty token around &");
+ else {
+ int lenp = strlen(prev->text);
+ int lenn = strlen(next->text);
+ prev->text = nasm_realloc(prev->text, lenp + lenn + 1);
+ strncpy(prev->text + lenp, next->text, lenn + 1);
+ (void) delete_Token(t);
+ prev->next = delete_Token(next);
+ t = prev;
+ next = t->next;
+ }
+ }
+ }
+ return tline;
+}
+
+/*
+ * The pre-preprocessing stage... This function translates line
+ * number indications as they emerge from GNU cpp (`# lineno "file"
+ * flags') into NASM preprocessor line number indications (`%line
+ * lineno file').
+ */
+static char *
+prepreproc(char *line)
+{
+ int lineno;
+ size_t fnlen;
+ char *fname, *oldline;
+ char *c, *d, *ret;
+ Line *l, **lp;
+
+ if (line[0] == '#' && line[1] == ' ')
+ {
+ oldline = line;
+ fname = oldline + 2;
+ lineno = atoi(fname);
+ fname += strspn(fname, "0123456789 ");
+ if (*fname == '"')
+ fname++;
+ fnlen = strcspn(fname, "\"");
+ line = nasm_malloc(20 + fnlen);
+ sprintf(line, "%%line %d %.*s", lineno, (int)fnlen, fname);
+ nasm_free(oldline);
+ }
+ if (tasm_compatible_mode)
+ line = check_tasm_directive(line);
+
+ if (!(c = strchr(line, '\n')))
+ return line;
+
+ /* Turn multiline macros into several lines */
+ *c = '\0';
+ ret = nasm_strdup(line);
+
+ lp = &istk->expansion;
+ do {
+ d = strchr(c+1, '\n');
+ if (d)
+ *d = '\0';
+ l = malloc(sizeof(*l));
+ l -> first = tokenise(c+1);
+ l -> finishes = NULL;
+ l -> next = *lp;
+ *lp = l;
+ c = d;
+ lp = &l -> next;
+ } while (c);
+ nasm_free(line);
+ return ret;
+}
+
+/*
+ * The hash function for macro lookups. Note that due to some
+ * macros having case-insensitive names, the hash function must be
+ * invariant under case changes. We implement this by applying a
+ * perfectly normal hash function to the uppercase of the string.
+ */
+static int
+hash(char *s)
+{
+ unsigned int h = 0;
+ unsigned int i = 0;
+ /*
+ * Powers of three, mod 31.
+ */
+ static const int multipliers[] = {
+ 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10,
+ 30, 28, 22, 4, 12, 5, 15, 14, 11, 2, 6, 18, 23, 7, 21
+ };
+
+
+ while (*s)
+ {
+ h += multipliers[i] * (unsigned char) (toupper(*s));
+ s++;
+ if (++i >= elements(multipliers))
+ i = 0;
+ }
+ h %= NHASH;
+ return h;
+}
+
+/*
+ * Free a linked list of tokens.
+ */
+static void
+free_tlist(Token * list_)
+{
+ while (list_)
+ {
+ list_ = delete_Token(list_);
+ }
+}
+
+/*
+ * Free a linked list of lines.
+ */
+static void
+free_llist(Line * list_)
+{
+ Line *l;
+ while (list_)
+ {
+ l = list_;
+ list_ = list_->next;
+ free_tlist(l->first);
+ nasm_free(l);
+ }
+}
+
+/*
+ * Free an MMacro
+ */
+static void
+free_mmacro(MMacro * m)
+{
+ nasm_free(m->name);
+ free_tlist(m->dlist);
+ nasm_free(m->defaults);
+ free_llist(m->expansion);
+ nasm_free(m);
+}
+
+/*
+ * Pop the context stack.
+ */
+static void
+ctx_pop(void)
+{
+ Context *c = cstk;
+ SMacro *smac, *s;
+
+ cstk = cstk->next;
+ smac = c->localmac;
+ while (smac)
+ {
+ s = smac;
+ smac = smac->next;
+ nasm_free(s->name);
+ free_tlist(s->expansion);
+ nasm_free(s);
+ }
+ nasm_free(c->name);
+ nasm_free(c);
+}
+
+#define BUF_DELTA 512
+/*
+ * Read a line from the top file in istk, handling multiple CR/LFs
+ * at the end of the line read, and handling spurious ^Zs. Will
+ * return lines from the standard macro set if this has not already
+ * been done.
+ */
+static char *
+read_line(void)
+{
+ char *buffer, *p, *q;
+ int bufsize, continued_count;
+
+ bufsize = BUF_DELTA;
+ buffer = nasm_malloc(BUF_DELTA);
+ p = buffer;
+ continued_count = 0;
+ while (1)
+ {
+ q = fgets(p, bufsize - (int)(p - buffer), istk->fp);
+ if (!q)
+ break;
+ p += strlen(p);
+ if (p > buffer && p[-1] == '\n')
+ {
+ /* Convert backslash-CRLF line continuation sequences into
+ nothing at all (for DOS and Windows) */
+ if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
+ p -= 3;
+ *p = 0;
+ continued_count++;
+ }
+ /* Also convert backslash-LF line continuation sequences into
+ nothing at all (for Unix) */
+ else if (((p - 1) > buffer) && (p[-2] == '\\')) {
+ p -= 2;
+ *p = 0;
+ continued_count++;
+ }
+ else {
+ break;
+ }
+ }
+ if (p - buffer > bufsize - 10)
+ {
+ long offset = (long)(p - buffer);
+ bufsize += BUF_DELTA;
+ buffer = nasm_realloc(buffer, (size_t)bufsize);
+ p = buffer + offset; /* prevent stale-pointer problems */
+ }
+ }
+
+ if (!q && p == buffer)
+ {
+ nasm_free(buffer);
+ return NULL;
+ }
+
+ nasm_src_set_linnum(nasm_src_get_linnum() + istk->lineinc + (continued_count * istk->lineinc));
+
+ /*
+ * Play safe: remove CRs as well as LFs, if any of either are
+ * present at the end of the line.
+ */
+ while (--p >= buffer && (*p == '\n' || *p == '\r'))
+ *p = '\0';
+
+ /*
+ * Handle spurious ^Z, which may be inserted into source files
+ * by some file transfer utilities.
+ */
+ buffer[strcspn(buffer, "\032")] = '\0';
+
+ list->line(LIST_READ, buffer);
+
+ return buffer;
+}
+
+/*
+ * Tokenise a line of text. This is a very simple process since we
+ * don't need to parse the value out of e.g. numeric tokens: we
+ * simply split one string into many.
+ */
+static Token *
+tokenise(char *line)
+{
+ char *p = line;
+ int type;
+ Token *list_ = NULL;
+ Token *t, **tail = &list_;
+
+ while (*line)
+ {
+ p = line;
+ if (*p == '%')
+ {
+ p++;
+ if ( isdigit(*p) ||
+ ((*p == '-' || *p == '+') && isdigit(p[1])) ||
+ ((*p == '+') && (isspace(p[1]) || !p[1])))
+ {
+ do
+ {
+ p++;
+ }
+ while (isdigit(*p));
+ type = TOK_PREPROC_ID;
+ }
+ else if (*p == '{')
+ {
+ p++;
+ while (*p && *p != '}')
+ {
+ p[-1] = *p;
+ p++;
+ }
+ p[-1] = '\0';
+ if (*p)
+ p++;
+ type = TOK_PREPROC_ID;
+ }
+ else if (isidchar(*p) ||
+ ((*p == '!' || *p == '%' || *p == '$') &&
+ isidchar(p[1])))
+ {
+ do
+ {
+ p++;
+ }
+ while (isidchar(*p));
+ type = TOK_PREPROC_ID;
+ }
+ else
+ {
+ type = TOK_OTHER;
+ if (*p == '%')
+ p++;
+ }
+ }
+ else if (isidstart(*p) || (*p == '$' && isidstart(p[1])))
+ {
+ type = TOK_ID;
+ p++;
+ while (*p && isidchar(*p))
+ p++;
+ }
+ else if (*p == '\'' || *p == '"')
+ {
+ /*
+ * A string token.
+ */
+ char c = *p;
+ p++;
+ type = TOK_STRING;
+ while (*p && *p != c)
+ p++;
+
+ if (*p)
+ {
+ p++;
+ }
+ else
+ {
+ error(ERR_WARNING, "unterminated string");
+ type = -1;
+ }
+ }
+ else if (isnumstart(*p))
+ {
+ /*
+ * A number token.
+ */
+ type = TOK_NUMBER;
+ p++;
+ while (*p && isnumchar(*p))
+ p++;
+ }
+ else if (isspace(*p))
+ {
+ type = TOK_WHITESPACE;
+ p++;
+ while (*p && isspace(*p))
+ p++;
+ /*
+ * Whitespace just before end-of-line is discarded by
+ * pretending it's a comment; whitespace just before a
+ * comment gets lumped into the comment.
+ */
+ if (!*p || *p == ';')
+ {
+ type = TOK_COMMENT;
+ while (*p)
+ p++;
+ }
+ }
+ else if (*p == ';')
+ {
+ type = TOK_COMMENT;
+ while (*p)
+ p++;
+ }
+ else
+ {
+ /*
+ * Anything else is an operator of some kind. We check
+ * for all the double-character operators (>>, <<, //,
+ * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
+ * else is a single-character operator.
+ */
+ type = TOK_OTHER;
+ if ((p[0] == '>' && p[1] == '>') ||
+ (p[0] == '<' && p[1] == '<') ||
+ (p[0] == '/' && p[1] == '/') ||
+ (p[0] == '<' && p[1] == '=') ||
+ (p[0] == '>' && p[1] == '=') ||
+ (p[0] == '=' && p[1] == '=') ||
+ (p[0] == '!' && p[1] == '=') ||
+ (p[0] == '<' && p[1] == '>') ||
+ (p[0] == '&' && p[1] == '&') ||
+ (p[0] == '|' && p[1] == '|') ||
+ (p[0] == '^' && p[1] == '^'))
+ {
+ p++;
+ }
+ p++;
+ }
+
+ /* Handle unterminated string */
+ if (type == -1)
+ {
+ *tail = t = new_Token(NULL, TOK_STRING, line, (size_t)(p-line)+1);
+ t->text[p-line] = *line;
+ tail = &t->next;
+ }
+ else if (type != TOK_COMMENT)
+ {
+ *tail = t = new_Token(NULL, type, line, (size_t)(p - line));
+ tail = &t->next;
+ }
+ line = p;
+ }
+ return list_;
+}
+
+/*
+ * this function allocates a new managed block of memory and
+ * returns a pointer to the block. The managed blocks are
+ * deleted only all at once by the delete_Blocks function.
+ */
+static void *
+new_Block(size_t size)
+{
+ Blocks *b = &blocks;
+
+ /* first, get to the end of the linked list */
+ while (b->next)
+ b = b->next;
+ /* now allocate the requested chunk */
+ b->chunk = nasm_malloc(size);
+
+ /* now allocate a new block for the next request */
+ b->next = nasm_malloc(sizeof(Blocks));
+ /* and initialize the contents of the new block */
+ b->next->next = NULL;
+ b->next->chunk = NULL;
+ return b->chunk;
+}
+
+/*
+ * this function deletes all managed blocks of memory
+ */
+static void
+delete_Blocks(void)
+{
+ Blocks *a,*b = &blocks;
+
+ /*
+ * keep in mind that the first block, pointed to by blocks
+ * is a static and not dynamically allocated, so we don't
+ * free it.
+ */
+ while (b)
+ {
+ if (b->chunk)
+ nasm_free(b->chunk);
+ a = b;
+ b = b->next;
+ if (a != &blocks)
+ nasm_free(a);
+ }
+}
+
+/*
+ * this function creates a new Token and passes a pointer to it
+ * back to the caller. It sets the type and text elements, and
+ * also the mac and next elements to NULL.
+ */
+static Token *
+new_Token(Token * next, int type, const char *text, size_t txtlen)
+{
+ Token *t;
+ int i;
+
+ if (freeTokens == NULL)
+ {
+ freeTokens = (Token *)new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
+ for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
+ freeTokens[i].next = &freeTokens[i + 1];
+ freeTokens[i].next = NULL;
+ }
+ t = freeTokens;
+ freeTokens = t->next;
+ t->next = next;
+ t->mac = NULL;
+ t->type = type;
+ if (type == TOK_WHITESPACE || text == NULL)
+ {
+ t->text = NULL;
+ }
+ else
+ {
+ if (txtlen == 0)
+ txtlen = strlen(text);
+ t->text = nasm_malloc(1 + txtlen);
+ strncpy(t->text, text, txtlen);
+ t->text[txtlen] = '\0';
+ }
+ return t;
+}
+
+static Token *
+delete_Token(Token * t)
+{
+ Token *next = t->next;
+ nasm_free(t->text);
+ t->next = freeTokens;
+ freeTokens = t;
+ return next;
+}
+
+/*
+ * Convert a line of tokens back into text.
+ * If expand_locals is not zero, identifiers of the form "%$*xxx"
+ * will be transformed into ..@ctxnum.xxx
+ */
+static char *
+detoken(Token * tlist, int expand_locals)
+{
+ Token *t;
+ size_t len;
+ char *line, *p;
+
+ len = 0;
+ for (t = tlist; t; t = t->next)
+ {
+ if (t->type == TOK_PREPROC_ID && t->text[1] == '!')
+ {
+ char *p2 = getenv(t->text + 2);
+ nasm_free(t->text);
+ if (p2)
+ t->text = nasm_strdup(p2);
+ else
+ t->text = NULL;
+ }
+ /* Expand local macros here and not during preprocessing */
+ if (expand_locals &&
+ t->type == TOK_PREPROC_ID && t->text &&
+ t->text[0] == '%' && t->text[1] == '$')
+ {
+ Context *ctx = get_ctx(t->text, FALSE);
+ if (ctx)
+ {
+ char buffer[40];
+ char *p2, *q = t->text + 2;
+
+ q += strspn(q, "$");
+ sprintf(buffer, "..@%lu.", ctx->number);
+ p2 = nasm_strcat(buffer, q);
+ nasm_free(t->text);
+ t->text = p2;
+ }
+ }
+ if (t->type == TOK_WHITESPACE)
+ {
+ len++;
+ }
+ else if (t->text)
+ {
+ len += strlen(t->text);
+ }
+ }
+ p = line = nasm_malloc(len + 1);
+ for (t = tlist; t; t = t->next)
+ {
+ if (t->type == TOK_WHITESPACE)
+ {
+ *p = ' ';
+ p++;
+ *p = '\0';
+ }
+ else if (t->text)
+ {
+ strcpy(p, t->text);
+ p += strlen(p);
+ }
+ }
+ *p = '\0';
+ return line;
+}
+
+/*
+ * A scanner, suitable for use by the expression evaluator, which
+ * operates on a line of Tokens. Expects a pointer to a pointer to
+ * the first token in the line to be passed in as its private_data
+ * field.
+ */
+static int
+ppscan(void *private_data, struct tokenval *tokval)
+{
+ Token **tlineptr = private_data;
+ Token *tline;
+
+ do
+ {
+ tline = *tlineptr;
+ *tlineptr = tline ? tline->next : NULL;
+ }
+ while (tline && (tline->type == TOK_WHITESPACE ||
+ tline->type == TOK_COMMENT));
+
+ if (!tline)
+ return tokval->t_type = TOKEN_EOS;
+
+ if (tline->text[0] == '$' && !tline->text[1])
+ return tokval->t_type = TOKEN_HERE;
+ if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
+ return tokval->t_type = TOKEN_BASE;
+
+ if (tline->type == TOK_ID)
+ {
+ tokval->t_charptr = tline->text;
+ if (tline->text[0] == '$')
+ {
+ tokval->t_charptr++;
+ return tokval->t_type = TOKEN_ID;
+ }
+
+ /*
+ * This is the only special case we actually need to worry
+ * about in this restricted context.
+ */
+ if (!nasm_stricmp(tline->text, "seg"))
+ return tokval->t_type = TOKEN_SEG;
+
+ return tokval->t_type = TOKEN_ID;
+ }
+
+ if (tline->type == TOK_NUMBER)
+ {
+ int rn_error;
+
+ tokval->t_integer = nasm_readnum(tline->text, &rn_error);
+ if (rn_error)
+ return tokval->t_type = TOKEN_ERRNUM;
+ tokval->t_charptr = NULL;
+ return tokval->t_type = TOKEN_NUM;
+ }
+
+ if (tline->type == TOK_STRING)
+ {
+ int rn_warn;
+ char q, *r;
+ size_t l;
+
+ r = tline->text;
+ q = *r++;
+ l = strlen(r);
+
+ if (l == 0 || r[l - 1] != q)
+ return tokval->t_type = TOKEN_ERRNUM;
+ tokval->t_integer = nasm_readstrnum(r, l - 1, &rn_warn);
+ if (rn_warn)
+ error(ERR_WARNING | ERR_PASS1, "character constant too long");
+ tokval->t_charptr = NULL;
+ return tokval->t_type = TOKEN_NUM;
+ }
+
+ if (tline->type == TOK_OTHER)
+ {
+ if (!strcmp(tline->text, "<<"))
+ return tokval->t_type = TOKEN_SHL;
+ if (!strcmp(tline->text, ">>"))
+ return tokval->t_type = TOKEN_SHR;
+ if (!strcmp(tline->text, "//"))
+ return tokval->t_type = TOKEN_SDIV;
+ if (!strcmp(tline->text, "%%"))
+ return tokval->t_type = TOKEN_SMOD;
+ if (!strcmp(tline->text, "=="))
+ return tokval->t_type = TOKEN_EQ;
+ if (!strcmp(tline->text, "<>"))
+ return tokval->t_type = TOKEN_NE;
+ if (!strcmp(tline->text, "!="))
+ return tokval->t_type = TOKEN_NE;
+ if (!strcmp(tline->text, "<="))
+ return tokval->t_type = TOKEN_LE;
+ if (!strcmp(tline->text, ">="))
+ return tokval->t_type = TOKEN_GE;
+ if (!strcmp(tline->text, "&&"))
+ return tokval->t_type = TOKEN_DBL_AND;
+ if (!strcmp(tline->text, "^^"))
+ return tokval->t_type = TOKEN_DBL_XOR;
+ if (!strcmp(tline->text, "||"))
+ return tokval->t_type = TOKEN_DBL_OR;
+ }
+
+ /*
+ * We have no other options: just return the first character of
+ * the token text.
+ */
+ return tokval->t_type = tline->text[0];
+}
+
+/*
+ * Compare a string to the name of an existing macro; this is a
+ * simple wrapper which calls either strcmp or nasm_stricmp
+ * depending on the value of the `casesense' parameter.
+ */
+static int
+mstrcmp(char *p, char *q, int casesense)
+{
+ return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
+}
+
+/*
+ * Return the Context structure associated with a %$ token. Return
+ * NULL, having _already_ reported an error condition, if the
+ * context stack isn't deep enough for the supplied number of $
+ * signs.
+ * If all_contexts == TRUE, contexts that enclose current are
+ * also scanned for such smacro, until it is found; if not -
+ * only the context that directly results from the number of $'s
+ * in variable's name.
+ */
+static Context *
+get_ctx(char *name, int all_contexts)
+{
+ Context *ctx;
+ SMacro *m;
+ size_t i;
+
+ if (!name || name[0] != '%' || name[1] != '$')
+ return NULL;
+
+ if (!cstk)
+ {
+ error(ERR_NONFATAL, "`%s': context stack is empty", name);
+ return NULL;
+ }
+
+ for (i = strspn(name + 2, "$"), ctx = cstk; (i > 0) && ctx; i--)
+ {
+ ctx = ctx->next;
+/* i--; Lino - 02/25/02 */
+ }
+ if (!ctx)
+ {
+ error(ERR_NONFATAL, "`%s': context stack is only"
+ " %d level%s deep", name, i - 1, (i == 2 ? "" : "s"));
+ return NULL;
+ }
+ if (!all_contexts)
+ return ctx;
+
+ do
+ {
+ /* Search for this smacro in found context */
+ m = ctx->localmac;
+ while (m)
+ {
+ if (!mstrcmp(m->name, name, m->casesense))
+ return ctx;
+ m = m->next;
+ }
+ ctx = ctx->next;
+ }
+ while (ctx);
+ return NULL;
+}
+
+/*
+ * Open an include file. This routine must always return a valid
+ * file pointer if it returns - it's responsible for throwing an
+ * ERR_FATAL and bombing out completely if not. It should also try
+ * the include path one by one until it finds the file or reaches
+ * the end of the path.
+ */
+static FILE *
+inc_fopen(char *file, char **newname)
+{
+ FILE *fp;
+ char *combine = NULL, *c;
+ char *pb, *p1, *p2, *file2 = NULL;
+
+ /* Try to expand all %ENVVAR% in filename. Warn, and leave %string%
+ * intact, if ENVVAR is not set in the environment.
+ */
+ pb = file;
+ p1 = pb;
+ for (;;) {
+ char *env;
+ while (*p1 != '\0' && *p1 != '%')
+ p1++;
+ if (*p1 == '\0')
+ break;
+ p2 = p1+1;
+ while (*p2 != '\0' && *p2 != '%')
+ p2++;
+ if (*p2 == '\0')
+ break;
+ /* Okay, we have a %...%, with p1 pointing to the first %, and p2
+ * pointing to the second %.
+ */
+ *p2 = '\0';
+ env = getenv(p1+1);
+ if (!env) {
+ /* warn, restore %, and continue looking */
+ error(ERR_WARNING, "environment variable `%s' does not exist",
+ p1+1);
+ *p2 = '%';
+ p1 = p2+1;
+ continue;
+ }
+ /* need to expand */
+ if (!file2) {
+ file2 = nasm_malloc(strlen(file)+strlen(env)+1);
+ file2[0] = '\0';
+ } else
+ file2 = nasm_realloc(file2, strlen(file2)+strlen(env)+1);
+ *p1 = '\0';
+ strcat(file2, pb);
+ strcat(file2, env);
+ pb = p2+1;
+ p1 = pb;
+ }
+ /* add tail end; string is long enough that we don't need to realloc */
+ if (file2)
+ strcat(file2, pb);
+
+ fp = yasm_fopen_include(file2 ? file2 : file, nasm_src_get_fname(), "r",
+ &combine);
+ if (!fp && tasm_compatible_mode)
+ {
+ char *thefile = file2 ? file2 : file;
+ /* try a few case combinations */
+ do {
+ for (c = thefile; *c; c++)
+ *c = toupper(*c);
+ fp = yasm_fopen_include(thefile, nasm_src_get_fname(), "r", &combine);
+ if (fp) break;
+ *thefile = tolower(*thefile);
+ fp = yasm_fopen_include(thefile, nasm_src_get_fname(), "r", &combine);
+ if (fp) break;
+ for (c = thefile; *c; c++)
+ *c = tolower(*c);
+ fp = yasm_fopen_include(thefile, nasm_src_get_fname(), "r", &combine);
+ if (fp) break;
+ *thefile = toupper(*thefile);
+ fp = yasm_fopen_include(thefile, nasm_src_get_fname(), "r", &combine);
+ if (fp) break;
+ } while (0);
+ }
+ if (!fp)
+ error(ERR_FATAL, "unable to open include file `%s'",
+ file2 ? file2 : file);
+ nasm_preproc_add_dep(combine);
+
+ if (file2)
+ nasm_free(file2);
+
+ *newname = combine;
+ return fp;
+}
+
+/*
+ * Determine if we should warn on defining a single-line macro of
+ * name `name', with `nparam' parameters. If nparam is 0 or -1, will
+ * return TRUE if _any_ single-line macro of that name is defined.
+ * Otherwise, will return TRUE if a single-line macro with either
+ * `nparam' or no parameters is defined.
+ *
+ * If a macro with precisely the right number of parameters is
+ * defined, or nparam is -1, the address of the definition structure
+ * will be returned in `defn'; otherwise NULL will be returned. If `defn'
+ * is NULL, no action will be taken regarding its contents, and no
+ * error will occur.
+ *
+ * Note that this is also called with nparam zero to resolve
+ * `ifdef'.
+ *
+ * If you already know which context macro belongs to, you can pass
+ * the context pointer as first parameter; if you won't but name begins
+ * with %$ the context will be automatically computed. If all_contexts
+ * is true, macro will be searched in outer contexts as well.
+ */
+static int
+smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
+ int nocase)
+{
+ SMacro *m;
+ int highest_level = -1;
+
+ if (ctx)
+ m = ctx->localmac;
+ else if (name[0] == '%' && name[1] == '$')
+ {
+ if (cstk)
+ ctx = get_ctx(name, FALSE);
+ if (!ctx)
+ return FALSE; /* got to return _something_ */
+ m = ctx->localmac;
+ }
+ else
+ m = smacros[hash(name)];
+
+ while (m)
+ {
+ if (!mstrcmp(m->name, name, m->casesense && nocase) &&
+ (nparam <= 0 || m->nparam == 0 || nparam == m->nparam) && (highest_level < 0 || m->level > highest_level))
+ {
+ highest_level = m->level;
+ if (defn)
+ {
+ if (nparam == m->nparam || nparam == -1)
+ *defn = m;
+ else
+ *defn = NULL;
+ }
+ }
+ m = m->next;
+ }
+
+ return highest_level >= 0;
+}
+
+/*
+ * Count and mark off the parameters in a multi-line macro call.
+ * This is called both from within the multi-line macro expansion
+ * code, and also to mark off the default parameters when provided
+ * in a %macro definition line.
+ */
+static void
+count_mmac_params(Token * t, int *nparam, Token *** params)
+{
+ int paramsize, brace;
+
+ *nparam = paramsize = 0;
+ *params = NULL;
+ while (t)
+ {
+ if (*nparam+1 >= paramsize)
+ {
+ paramsize += PARAM_DELTA;
+ *params = nasm_realloc(*params, sizeof(**params) * paramsize);
+ }
+ skip_white_(t);
+ brace = FALSE;
+ if (tok_is_(t, "{"))
+ brace = TRUE;
+ (*params)[(*nparam)++] = t;
+ while (tok_isnt_(t, brace ? "}" : ","))
+ t = t->next;
+ if (t)
+ { /* got a comma/brace */
+ t = t->next;
+ if (brace)
+ {
+ /*
+ * Now we've found the closing brace, look further
+ * for the comma.
+ */
+ skip_white_(t);
+ if (tok_isnt_(t, ","))
+ {
+ error(ERR_NONFATAL,
+ "braces do not enclose all of macro parameter");
+ while (tok_isnt_(t, ","))
+ t = t->next;
+ }
+ if (t)
+ t = t->next; /* eat the comma */
+ }
+ }
+ }
+}
+
+/*
+ * Determine whether one of the various `if' conditions is true or
+ * not.
+ *
+ * We must free the tline we get passed.
+ */
+static int
+if_condition(Token * tline, int i)
+{
+ int j, casesense;
+ Token *t, *tt, **tptr, *origline;
+ struct tokenval tokval;
+ yasm_expr *evalresult;
+ yasm_intnum *intn;
+
+ origline = tline;
+
+ switch (i)
+ {
+ case PP_IFCTX:
+ case PP_ELIFCTX:
+ case PP_IFNCTX:
+ case PP_ELIFNCTX:
+ j = FALSE; /* have we matched yet? */
+ while (cstk && tline)
+ {
+ skip_white_(tline);
+ if (!tline || tline->type != TOK_ID)
+ {
+ error(ERR_NONFATAL,
+ "`%s' expects context identifiers",
+ directives[i]);
+ free_tlist(origline);
+ return -1;
+ }
+ if (!nasm_stricmp(tline->text, cstk->name))
+ j = TRUE;
+ tline = tline->next;
+ }
+ if (i == PP_IFNCTX || i == PP_ELIFNCTX)
+ j = !j;
+ free_tlist(origline);
+ return j;
+
+ case PP_IFDEF:
+ case PP_ELIFDEF:
+ case PP_IFNDEF:
+ case PP_ELIFNDEF:
+ j = FALSE; /* have we matched yet? */
+ while (tline)
+ {
+ skip_white_(tline);
+ if (!tline || (tline->type != TOK_ID &&
+ (tline->type != TOK_PREPROC_ID ||
+ tline->text[1] != '$')))
+ {
+ error(ERR_NONFATAL,
+ "`%s' expects macro identifiers",
+ directives[i]);
+ free_tlist(origline);
+ return -1;
+ }
+ if (smacro_defined(NULL, tline->text, 0, NULL, 1))
+ j = TRUE;
+ tline = tline->next;
+ }
+ if (i == PP_IFNDEF || i == PP_ELIFNDEF)
+ j = !j;
+ free_tlist(origline);
+ return j;
+
+ case PP_IFIDN:
+ case PP_ELIFIDN:
+ case PP_IFNIDN:
+ case PP_ELIFNIDN:
+ case PP_IFIDNI:
+ case PP_ELIFIDNI:
+ case PP_IFNIDNI:
+ case PP_ELIFNIDNI:
+ tline = expand_smacro(tline);
+ t = tt = tline;
+ while (tok_isnt_(tt, ","))
+ tt = tt->next;
+ if (!tt)
+ {
+ error(ERR_NONFATAL,
+ "`%s' expects two comma-separated arguments",
+ directives[i]);
+ free_tlist(tline);
+ return -1;
+ }
+ tt = tt->next;
+ casesense = (i == PP_IFIDN || i == PP_ELIFIDN ||
+ i == PP_IFNIDN || i == PP_ELIFNIDN);
+ j = TRUE; /* assume equality unless proved not */
+ while ((t->type != TOK_OTHER || strcmp(t->text, ",")) && tt)
+ {
+ if (tt->type == TOK_OTHER && !strcmp(tt->text, ","))
+ {
+ error(ERR_NONFATAL, "`%s': more than one comma on line",
+ directives[i]);
+ free_tlist(tline);
+ return -1;
+ }
+ if (t->type == TOK_WHITESPACE)
+ {
+ t = t->next;
+ continue;
+ }
+ if (tt->type == TOK_WHITESPACE)
+ {
+ tt = tt->next;
+ continue;
+ }
+ if (tt->type != t->type)
+ {
+ j = FALSE; /* found mismatching tokens */
+ break;
+ }
+ /* Unify surrounding quotes for strings */
+ if (t->type == TOK_STRING)
+ {
+ tt->text[0] = t->text[0];
+ tt->text[strlen(tt->text) - 1] = t->text[0];
+ }
+ if (mstrcmp(tt->text, t->text, casesense) != 0)
+ {
+ j = FALSE; /* found mismatching tokens */
+ break;
+ }
+
+ t = t->next;
+ tt = tt->next;
+ }
+ if ((t->type != TOK_OTHER || strcmp(t->text, ",")) || tt)
+ j = FALSE; /* trailing gunk on one end or other */
+ if (i == PP_IFNIDN || i == PP_ELIFNIDN ||
+ i == PP_IFNIDNI || i == PP_ELIFNIDNI)
+ j = !j;
+ free_tlist(tline);
+ return j;
+
+ case PP_IFMACRO:
+ case PP_ELIFMACRO:
+ case PP_IFNMACRO:
+ case PP_ELIFNMACRO:
+ {
+ int found = 0;
+ MMacro searching, *mmac;
+
+ tline = tline->next;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tok_type_(tline, TOK_ID))
+ {
+ error(ERR_NONFATAL,
+ "`%s' expects a macro name",
+ directives[i]);
+ return -1;
+ }
+ searching.name = nasm_strdup(tline->text);
+ searching.casesense = (i == PP_MACRO);
+ searching.plus = FALSE;
+ searching.nolist = FALSE;
+ searching.in_progress = FALSE;
+ searching.rep_nest = NULL;
+ searching.nparam_min = 0;
+ searching.nparam_max = INT_MAX;
+ tline = expand_smacro(tline->next);
+ skip_white_(tline);
+ if (!tline)
+ {
+ } else if (!tok_type_(tline, TOK_NUMBER))
+ {
+ error(ERR_NONFATAL,
+ "`%s' expects a parameter count or nothing",
+ directives[i]);
+ }
+ else
+ {
+ intn = nasm_readnum(tline->text, &j);
+ searching.nparam_min = searching.nparam_max =
+ yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
+ if (j)
+ error(ERR_NONFATAL,
+ "unable to parse parameter count `%s'",
+ tline->text);
+ }
+ if (tline && tok_is_(tline->next, "-"))
+ {
+ tline = tline->next->next;
+ if (tok_is_(tline, "*"))
+ searching.nparam_max = INT_MAX;
+ else if (!tok_type_(tline, TOK_NUMBER))
+ error(ERR_NONFATAL,
+ "`%s' expects a parameter count after `-'",
+ directives[i]);
+ else
+ {
+ intn = nasm_readnum(tline->text, &j);
+ searching.nparam_max = yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
+ if (j)
+ error(ERR_NONFATAL,
+ "unable to parse parameter count `%s'",
+ tline->text);
+ if (searching.nparam_min > searching.nparam_max)
+ error(ERR_NONFATAL,
+ "minimum parameter count exceeds maximum");
+ }
+ }
+ if (tline && tok_is_(tline->next, "+"))
+ {
+ tline = tline->next;
+ searching.plus = TRUE;
+ }
+ mmac = mmacros[hash(searching.name)];
+ while (mmac)
+ {
+ if (!strcmp(mmac->name, searching.name) &&
+ (mmac->nparam_min <= searching.nparam_max
+ || searching.plus)
+ && (searching.nparam_min <= mmac->nparam_max
+ || mmac->plus))
+ {
+ found = TRUE;
+ break;
+ }
+ mmac = mmac->next;
+ }
+ nasm_free(searching.name);
+ free_tlist(origline);
+ if (i == PP_IFNMACRO || i == PP_ELIFNMACRO)
+ found = !found;
+ return found;
+ }
+
+ case PP_IFID:
+ case PP_ELIFID:
+ case PP_IFNID:
+ case PP_ELIFNID:
+ case PP_IFNUM:
+ case PP_ELIFNUM:
+ case PP_IFNNUM:
+ case PP_ELIFNNUM:
+ case PP_IFSTR:
+ case PP_ELIFSTR:
+ case PP_IFNSTR:
+ case PP_ELIFNSTR:
+ tline = expand_smacro(tline);
+ t = tline;
+ while (tok_type_(t, TOK_WHITESPACE))
+ t = t->next;
+ j = FALSE; /* placate optimiser */
+ if (t)
+ switch (i)
+ {
+ case PP_IFID:
+ case PP_ELIFID:
+ case PP_IFNID:
+ case PP_ELIFNID:
+ j = (t->type == TOK_ID);
+ break;
+ case PP_IFNUM:
+ case PP_ELIFNUM:
+ case PP_IFNNUM:
+ case PP_ELIFNNUM:
+ j = (t->type == TOK_NUMBER);
+ break;
+ case PP_IFSTR:
+ case PP_ELIFSTR:
+ case PP_IFNSTR:
+ case PP_ELIFNSTR:
+ j = (t->type == TOK_STRING);
+ break;
+ }
+ if (i == PP_IFNID || i == PP_ELIFNID ||
+ i == PP_IFNNUM || i == PP_ELIFNNUM ||
+ i == PP_IFNSTR || i == PP_ELIFNSTR)
+ j = !j;
+ free_tlist(tline);
+ return j;
+
+ case PP_IF:
+ case PP_ELIF:
+ t = tline = expand_smacro(tline);
+ tptr = &t;
+ tokval.t_type = TOKEN_INVALID;
+ evalresult = evaluate(ppscan, tptr, &tokval, pass | CRITICAL,
+ error);
+ free_tlist(tline);
+ if (!evalresult)
+ return -1;
+ if (tokval.t_type)
+ error(ERR_WARNING,
+ "trailing garbage after expression ignored");
+ intn = yasm_expr_get_intnum(&evalresult, 0);
+ if (!intn)
+ {
+ error(ERR_NONFATAL,
+ "non-constant value given to `%s'", directives[i]);
+ yasm_expr_destroy(evalresult);
+ return -1;
+ }
+ j = !yasm_intnum_is_zero(intn);
+ yasm_expr_destroy(evalresult);
+ return j;
+
+ default:
+ error(ERR_FATAL,
+ "preprocessor directive `%s' not yet implemented",
+ directives[i]);
+ free_tlist(origline);
+ return -1; /* yeah, right */
+ }
+}
+
+/*
+ * Expand macros in a string. Used in %error and %include directives.
+ * First tokenise the string, apply "expand_smacro" and then de-tokenise back.
+ * The returned variable should ALWAYS be freed after usage.
+ */
+static void
+expand_macros_in_string(char **p)
+{
+ Token *line = tokenise(*p);
+ line = expand_smacro(line);
+ *p = detoken(line, FALSE);
+}
+
+/**
+ * find and process preprocessor directive in passed line
+ * Find out if a line contains a preprocessor directive, and deal
+ * with it if so.
+ *
+ * If a directive _is_ found, it is the responsibility of this routine
+ * (and not the caller) to free_tlist() the line.
+ *
+ * @param tline a pointer to the current tokeninzed line linked list
+ * @return DIRECTIVE_FOUND or NO_DIRECTIVE_FOUND
+ *
+ */
+static int
+do_directive(Token * tline)
+{
+ int i, j, k, m, nparam, nolist;
+ int offset;
+ char *p, *mname, *newname;
+ Include *inc;
+ Context *ctx;
+ Cond *cond;
+ SMacro *smac, **smhead;
+ MMacro *mmac;
+ Token *t, *tt, *param_start, *macro_start, *last, **tptr, *origline;
+ Line *l;
+ struct tokenval tokval;
+ yasm_expr *evalresult;
+ MMacro *tmp_defining; /* Used when manipulating rep_nest */
+ yasm_intnum *intn;
+
+ origline = tline;
+
+ skip_white_(tline);
+ if (!tok_type_(tline, TOK_PREPROC_ID) ||
+ (tline->text[1] == '%' || tline->text[1] == '$'
+ || tline->text[1] == '!'))
+ return NO_DIRECTIVE_FOUND;
+
+ i = -1;
+ j = elements(directives);
+ while (j - i > 1)
+ {
+ k = (j + i) / 2;
+ m = nasm_stricmp(tline->text, directives[k]);
+ if (m == 0) {
+ if (tasm_compatible_mode) {
+ i = k;
+ j = -2;
+ } else if (k != PP_ARG && k != PP_LOCAL && k != PP_STACKSIZE) {
+ i = k;
+ j = -2;
+ }
+ break;
+ }
+ else if (m < 0) {
+ j = k;
+ }
+ else
+ i = k;
+ }
+
+ /*
+ * If we're in a non-emitting branch of a condition construct,
+ * or walking to the end of an already terminated %rep block,
+ * we should ignore all directives except for condition
+ * directives.
+ */
+ if (((istk->conds && !emitting(istk->conds->state)) ||
+ (istk->mstk && !istk->mstk->in_progress)) &&
+ !is_condition(i))
+ {
+ return NO_DIRECTIVE_FOUND;
+ }
+
+ /*
+ * If we're defining a macro or reading a %rep block, we should
+ * ignore all directives except for %macro/%imacro (which
+ * generate an error), %endm/%endmacro, and (only if we're in a
+ * %rep block) %endrep. If we're in a %rep block, another %rep
+ * causes an error, so should be let through.
+ */
+ if (defining && i != PP_MACRO && i != PP_IMACRO &&
+ i != PP_ENDMACRO && i != PP_ENDM &&
+ (defining->name || (i != PP_ENDREP && i != PP_REP)))
+ {
+ return NO_DIRECTIVE_FOUND;
+ }
+
+ if (defining) {
+ if (i == PP_MACRO || i == PP_IMACRO) {
+ nested_mac_count++;
+ return NO_DIRECTIVE_FOUND;
+ } else if (nested_mac_count > 0) {
+ if (i == PP_ENDMACRO) {
+ nested_mac_count--;
+ return NO_DIRECTIVE_FOUND;
+ }
+ }
+ if (!defining->name) {
+ if (i == PP_REP) {
+ nested_rep_count++;
+ return NO_DIRECTIVE_FOUND;
+ } else if (nested_rep_count > 0) {
+ if (i == PP_ENDREP) {
+ nested_rep_count--;
+ return NO_DIRECTIVE_FOUND;
+ }
+ }
+ }
+ }
+
+ if (j != -2)
+ {
+ error(ERR_NONFATAL, "unknown preprocessor directive `%s'",
+ tline->text);
+ return NO_DIRECTIVE_FOUND; /* didn't get it */
+ }
+
+ switch (i)
+ {
+ case PP_STACKSIZE:
+ /* Directive to tell NASM what the default stack size is. The
+ * default is for a 16-bit stack, and this can be overriden with
+ * %stacksize large.
+ * the following form:
+ *
+ * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
+ */
+ tline = tline->next;
+ if (tline && tline->type == TOK_WHITESPACE)
+ tline = tline->next;
+ if (!tline || tline->type != TOK_ID)
+ {
+ error(ERR_NONFATAL, "`%%stacksize' missing size parameter");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ if (nasm_stricmp(tline->text, "flat") == 0)
+ {
+ /* All subsequent ARG directives are for a 32-bit stack */
+ StackSize = 4;
+ StackPointer = "ebp";
+ ArgOffset = 8;
+ LocalOffset = 4;
+ }
+ else if (nasm_stricmp(tline->text, "large") == 0)
+ {
+ /* All subsequent ARG directives are for a 16-bit stack,
+ * far function call.
+ */
+ StackSize = 2;
+ StackPointer = "bp";
+ ArgOffset = 4;
+ LocalOffset = 2;
+ }
+ else if (nasm_stricmp(tline->text, "small") == 0)
+ {
+ /* All subsequent ARG directives are for a 16-bit stack,
+ * far function call. We don't support near functions.
+ */
+ StackSize = 2;
+ StackPointer = "bp";
+ ArgOffset = 6;
+ LocalOffset = 2;
+ }
+ else
+ {
+ error(ERR_NONFATAL, "`%%stacksize' invalid size type");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_ARG:
+ /* TASM like ARG directive to define arguments to functions, in
+ * the following form:
+ *
+ * ARG arg1:WORD, arg2:DWORD, arg4:QWORD
+ */
+ offset = ArgOffset;
+ do
+ {
+ char *arg, directive[256];
+ int size = StackSize;
+
+ /* Find the argument name */
+ tline = tline->next;
+ if (tline && tline->type == TOK_WHITESPACE)
+ tline = tline->next;
+ if (!tline || tline->type != TOK_ID)
+ {
+ error(ERR_NONFATAL, "`%%arg' missing argument parameter");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ arg = tline->text;
+
+ /* Find the argument size type */
+ tline = tline->next;
+ if (!tline || tline->type != TOK_OTHER
+ || tline->text[0] != ':')
+ {
+ error(ERR_NONFATAL,
+ "Syntax error processing `%%arg' directive");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ tline = tline->next;
+ if (!tline || tline->type != TOK_ID)
+ {
+ error(ERR_NONFATAL,
+ "`%%arg' missing size type parameter");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+
+ /* Allow macro expansion of type parameter */
+ tt = tokenise(tline->text);
+ tt = expand_smacro(tt);
+ if (nasm_stricmp(tt->text, "byte") == 0)
+ {
+ size = MAX(StackSize, 1);
+ }
+ else if (nasm_stricmp(tt->text, "word") == 0)
+ {
+ size = MAX(StackSize, 2);
+ }
+ else if (nasm_stricmp(tt->text, "dword") == 0)
+ {
+ size = MAX(StackSize, 4);
+ }
+ else if (nasm_stricmp(tt->text, "qword") == 0)
+ {
+ size = MAX(StackSize, 8);
+ }
+ else if (nasm_stricmp(tt->text, "tword") == 0)
+ {
+ size = MAX(StackSize, 10);
+ }
+ else
+ {
+ error(ERR_NONFATAL,
+ "Invalid size type for `%%arg' missing directive");
+ free_tlist(tt);
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ free_tlist(tt);
+
+ /* Now define the macro for the argument */
+ sprintf(directive, "%%define %s (%s+%d)", arg, StackPointer,
+ offset);
+ do_directive(tokenise(directive));
+ offset += size;
+
+ /* Move to the next argument in the list */
+ tline = tline->next;
+ if (tline && tline->type == TOK_WHITESPACE)
+ tline = tline->next;
+ }
+ while (tline && tline->type == TOK_OTHER
+ && tline->text[0] == ',');
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_LOCAL:
+ /* TASM like LOCAL directive to define local variables for a
+ * function, in the following form:
+ *
+ * LOCAL local1:WORD, local2:DWORD, local4:QWORD = LocalSize
+ *
+ * The '= LocalSize' at the end is ignored by NASM, but is
+ * required by TASM to define the local parameter size (and used
+ * by the TASM macro package).
+ */
+ offset = LocalOffset;
+ do
+ {
+ char *local, directive[256];
+ int size = StackSize;
+
+ /* Find the argument name */
+ tline = tline->next;
+ if (tline && tline->type == TOK_WHITESPACE)
+ tline = tline->next;
+ if (!tline || tline->type != TOK_ID)
+ {
+ error(ERR_NONFATAL,
+ "`%%local' missing argument parameter");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ local = tline->text;
+
+ /* Find the argument size type */
+ tline = tline->next;
+ if (!tline || tline->type != TOK_OTHER
+ || tline->text[0] != ':')
+ {
+ error(ERR_NONFATAL,
+ "Syntax error processing `%%local' directive");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ tline = tline->next;
+ if (!tline || tline->type != TOK_ID)
+ {
+ error(ERR_NONFATAL,
+ "`%%local' missing size type parameter");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+
+ /* Allow macro expansion of type parameter */
+ tt = tokenise(tline->text);
+ tt = expand_smacro(tt);
+ if (nasm_stricmp(tt->text, "byte") == 0)
+ {
+ size = MAX(StackSize, 1);
+ }
+ else if (nasm_stricmp(tt->text, "word") == 0)
+ {
+ size = MAX(StackSize, 2);
+ }
+ else if (nasm_stricmp(tt->text, "dword") == 0)
+ {
+ size = MAX(StackSize, 4);
+ }
+ else if (nasm_stricmp(tt->text, "qword") == 0)
+ {
+ size = MAX(StackSize, 8);
+ }
+ else if (nasm_stricmp(tt->text, "tword") == 0)
+ {
+ size = MAX(StackSize, 10);
+ }
+ else
+ {
+ error(ERR_NONFATAL,
+ "Invalid size type for `%%local' missing directive");
+ free_tlist(tt);
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ free_tlist(tt);
+
+ /* Now define the macro for the argument */
+ sprintf(directive, "%%define %s (%s-%d)", local, StackPointer,
+ offset);
+ do_directive(tokenise(directive));
+ offset += size;
+
+ /* Now define the assign to setup the enter_c macro correctly */
+ sprintf(directive, "%%assign %%$localsize %%$localsize+%d",
+ size);
+ do_directive(tokenise(directive));
+
+ /* Move to the next argument in the list */
+ tline = tline->next;
+ if (tline && tline->type == TOK_WHITESPACE)
+ tline = tline->next;
+ }
+ while (tline && tline->type == TOK_OTHER
+ && tline->text[0] == ',');
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_CLEAR:
+ if (tline->next)
+ error(ERR_WARNING,
+ "trailing garbage after `%%clear' ignored");
+ for (j = 0; j < NHASH; j++)
+ {
+ while (mmacros[j])
+ {
+ MMacro *m2 = mmacros[j];
+ mmacros[j] = m2->next;
+ free_mmacro(m2);
+ }
+ while (smacros[j])
+ {
+ SMacro *s = smacros[j];
+ smacros[j] = smacros[j]->next;
+ nasm_free(s->name);
+ free_tlist(s->expansion);
+ nasm_free(s);
+ }
+ }
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_INCLUDE:
+ tline = tline->next;
+ skip_white_(tline);
+ if (!tline || (tline->type != TOK_STRING &&
+ tline->type != TOK_INTERNAL_STRING))
+ {
+ error(ERR_NONFATAL, "`%%include' expects a file name");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND; /* but we did _something_ */
+ }
+ if (tline->next)
+ error(ERR_WARNING,
+ "trailing garbage after `%%include' ignored");
+ if (tline->type != TOK_INTERNAL_STRING)
+ {
+ p = tline->text + 1; /* point past the quote to the name */
+ p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
+ }
+ else
+ p = tline->text; /* internal_string is easier */
+ expand_macros_in_string(&p);
+ inc = nasm_malloc(sizeof(Include));
+ inc->next = istk;
+ inc->conds = NULL;
+ inc->fp = inc_fopen(p, &newname);
+ inc->fname = nasm_src_set_fname(newname);
+ inc->lineno = nasm_src_set_linnum(0);
+ inc->lineinc = 1;
+ inc->expansion = NULL;
+ inc->mstk = NULL;
+ istk = inc;
+ list->uplevel(LIST_INCLUDE);
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_PUSH:
+ tline = tline->next;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tok_type_(tline, TOK_ID))
+ {
+ error(ERR_NONFATAL, "`%%push' expects a context identifier");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND; /* but we did _something_ */
+ }
+ if (tline->next)
+ error(ERR_WARNING, "trailing garbage after `%%push' ignored");
+ ctx = nasm_malloc(sizeof(Context));
+ ctx->next = cstk;
+ ctx->localmac = NULL;
+ ctx->name = nasm_strdup(tline->text);
+ ctx->number = unique++;
+ cstk = ctx;
+ free_tlist(origline);
+ break;
+
+ case PP_REPL:
+ tline = tline->next;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tok_type_(tline, TOK_ID))
+ {
+ error(ERR_NONFATAL, "`%%repl' expects a context identifier");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND; /* but we did _something_ */
+ }
+ if (tline->next)
+ error(ERR_WARNING, "trailing garbage after `%%repl' ignored");
+ if (!cstk)
+ error(ERR_NONFATAL, "`%%repl': context stack is empty");
+ else
+ {
+ nasm_free(cstk->name);
+ cstk->name = nasm_strdup(tline->text);
+ }
+ free_tlist(origline);
+ break;
+
+ case PP_POP:
+ if (tline->next)
+ error(ERR_WARNING, "trailing garbage after `%%pop' ignored");
+ if (!cstk)
+ error(ERR_NONFATAL,
+ "`%%pop': context stack is already empty");
+ else
+ ctx_pop();
+ free_tlist(origline);
+ break;
+
+ case PP_SCOPE:
+ if (tline->next)
+ error(ERR_WARNING, "trailing garbage after `%%scope' ignored");
+ Level++;
+ free_tlist(origline);
+ break;
+
+ case PP_ENDSCOPE:
+ if (tline->next)
+ error(ERR_WARNING, "trailing garbage after `%%endscope' ignored");
+ if (!Level)
+ error(ERR_NONFATAL,
+ "`%%endscope': already popped all levels");
+ else
+ {
+ for (k = 0; k < NHASH; k++)
+ {
+ SMacro **smlast = &smacros[k];
+ smac = smacros[k];
+ while (smac)
+ {
+ if (smac->level < Level)
+ {
+ smlast = &smac->next;
+ smac = smac->next;
+ }
+ else
+ {
+ *smlast = smac->next;
+ nasm_free(smac->name);
+ free_tlist(smac->expansion);
+ nasm_free(smac);
+ smac = *smlast;
+ }
+ }
+ }
+ for (ctx = cstk; ctx; ctx = ctx->next)
+ {
+ SMacro **smlast = &ctx->localmac;
+ smac = ctx->localmac;
+ while (smac)
+ {
+ if (smac->level < Level)
+ {
+ smlast = &smac->next;
+ smac = smac->next;
+ }
+ else
+ {
+ *smlast = smac->next;
+ nasm_free(smac->name);
+ free_tlist(smac->expansion);
+ nasm_free(smac);
+ smac = *smlast;
+ }
+ }
+ }
+ Level--;
+ }
+ free_tlist(origline);
+ break;
+
+ case PP_ERROR:
+ tline->next = expand_smacro(tline->next);
+ tline = tline->next;
+ skip_white_(tline);
+ if (tok_type_(tline, TOK_STRING))
+ {
+ p = tline->text + 1; /* point past the quote to the name */
+ p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
+ expand_macros_in_string(&p);
+ error(ERR_NONFATAL, "%s", p);
+ nasm_free(p);
+ }
+ else
+ {
+ p = detoken(tline, FALSE);
+ error(ERR_WARNING, "%s", p);
+ nasm_free(p);
+ }
+ free_tlist(origline);
+ break;
+
+ case PP_IF:
+ case PP_IFCTX:
+ case PP_IFDEF:
+ case PP_IFID:
+ case PP_IFIDN:
+ case PP_IFIDNI:
+ case PP_IFMACRO:
+ case PP_IFNCTX:
+ case PP_IFNDEF:
+ case PP_IFNID:
+ case PP_IFNIDN:
+ case PP_IFNIDNI:
+ case PP_IFNMACRO:
+ case PP_IFNNUM:
+ case PP_IFNSTR:
+ case PP_IFNUM:
+ case PP_IFSTR:
+ if (istk->conds && !emitting(istk->conds->state))
+ j = COND_NEVER;
+ else
+ {
+ j = if_condition(tline->next, i);
+ tline->next = NULL; /* it got freed */
+ j = j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
+ }
+ free_tlist(origline);
+ cond = nasm_malloc(sizeof(Cond));
+ cond->next = istk->conds;
+ cond->state = j;
+ istk->conds = cond;
+ return DIRECTIVE_FOUND;
+
+ case PP_ELIF:
+ case PP_ELIFCTX:
+ case PP_ELIFDEF:
+ case PP_ELIFID:
+ case PP_ELIFIDN:
+ case PP_ELIFIDNI:
+ case PP_ELIFMACRO:
+ case PP_ELIFNCTX:
+ case PP_ELIFNDEF:
+ case PP_ELIFNID:
+ case PP_ELIFNIDN:
+ case PP_ELIFNIDNI:
+ case PP_ELIFNMACRO:
+ case PP_ELIFNNUM:
+ case PP_ELIFNSTR:
+ case PP_ELIFNUM:
+ case PP_ELIFSTR:
+ if (!istk->conds)
+ error(ERR_FATAL, "`%s': no matching `%%if'", directives[i]);
+ if (emitting(istk->conds->state)
+ || istk->conds->state == COND_NEVER)
+ istk->conds->state = COND_NEVER;
+ else
+ {
+ /*
+ * IMPORTANT: In the case of %if, we will already have
+ * called expand_mmac_params(); however, if we're
+ * processing an %elif we must have been in a
+ * non-emitting mode, which would have inhibited
+ * the normal invocation of expand_mmac_params(). Therefore,
+ * we have to do it explicitly here.
+ */
+ j = if_condition(expand_mmac_params(tline->next), i);
+ tline->next = NULL; /* it got freed */
+ istk->conds->state =
+ j < 0 ? COND_NEVER : j ? COND_IF_TRUE : COND_IF_FALSE;
+ }
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_ELSE:
+ if (tline->next)
+ error(ERR_WARNING, "trailing garbage after `%%else' ignored");
+ if (!istk->conds)
+ error(ERR_FATAL, "`%%else': no matching `%%if'");
+ if (emitting(istk->conds->state)
+ || istk->conds->state == COND_NEVER)
+ istk->conds->state = COND_ELSE_FALSE;
+ else
+ istk->conds->state = COND_ELSE_TRUE;
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_ENDIF:
+ if (tline->next)
+ error(ERR_WARNING,
+ "trailing garbage after `%%endif' ignored");
+ if (!istk->conds)
+ error(ERR_FATAL, "`%%endif': no matching `%%if'");
+ cond = istk->conds;
+ istk->conds = cond->next;
+ nasm_free(cond);
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_MACRO:
+ case PP_IMACRO:
+ if (defining)
+ error(ERR_FATAL,
+ "`%%%smacro': already defining a macro",
+ (i == PP_IMACRO ? "i" : ""));
+ tline = tline->next;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tok_type_(tline, TOK_ID))
+ {
+ error(ERR_NONFATAL,
+ "`%%%smacro' expects a macro name",
+ (i == PP_IMACRO ? "i" : ""));
+ return DIRECTIVE_FOUND;
+ }
+ defining = nasm_malloc(sizeof(MMacro));
+ defining->name = nasm_strdup(tline->text);
+ defining->casesense = (i == PP_MACRO);
+ defining->plus = FALSE;
+ defining->nolist = FALSE;
+ defining->in_progress = FALSE;
+ defining->rep_nest = NULL;
+ tline = expand_smacro(tline->next);
+ skip_white_(tline);
+ if (!tok_type_(tline, TOK_NUMBER))
+ {
+ error(ERR_NONFATAL,
+ "`%%%smacro' expects a parameter count",
+ (i == PP_IMACRO ? "i" : ""));
+ defining->nparam_min = defining->nparam_max = 0;
+ }
+ else
+ {
+ intn = nasm_readnum(tline->text, &j);
+ defining->nparam_min = defining->nparam_max =
+ yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
+ if (j)
+ error(ERR_NONFATAL,
+ "unable to parse parameter count `%s'",
+ tline->text);
+ }
+ if (tline && tok_is_(tline->next, "-"))
+ {
+ tline = tline->next->next;
+ if (tok_is_(tline, "*"))
+ defining->nparam_max = INT_MAX;
+ else if (!tok_type_(tline, TOK_NUMBER))
+ error(ERR_NONFATAL,
+ "`%%%smacro' expects a parameter count after `-'",
+ (i == PP_IMACRO ? "i" : ""));
+ else
+ {
+ intn = nasm_readnum(tline->text, &j);
+ defining->nparam_max = yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
+ if (j)
+ error(ERR_NONFATAL,
+ "unable to parse parameter count `%s'",
+ tline->text);
+ if (defining->nparam_min > defining->nparam_max)
+ error(ERR_NONFATAL,
+ "minimum parameter count exceeds maximum");
+ }
+ }
+ if (tline && tok_is_(tline->next, "+"))
+ {
+ tline = tline->next;
+ defining->plus = TRUE;
+ }
+ if (tline && tok_type_(tline->next, TOK_ID) &&
+ !nasm_stricmp(tline->next->text, ".nolist"))
+ {
+ tline = tline->next;
+ defining->nolist = TRUE;
+ }
+ mmac = mmacros[hash(defining->name)];
+ while (mmac)
+ {
+ if (!strcmp(mmac->name, defining->name) &&
+ (mmac->nparam_min <= defining->nparam_max
+ || defining->plus)
+ && (defining->nparam_min <= mmac->nparam_max
+ || mmac->plus))
+ {
+ error(ERR_WARNING,
+ "redefining multi-line macro `%s'",
+ defining->name);
+ break;
+ }
+ mmac = mmac->next;
+ }
+ /*
+ * Handle default parameters.
+ */
+ if (tline && tline->next)
+ {
+ defining->dlist = tline->next;
+ tline->next = NULL;
+ count_mmac_params(defining->dlist, &defining->ndefs,
+ &defining->defaults);
+ }
+ else
+ {
+ defining->dlist = NULL;
+ defining->defaults = NULL;
+ }
+ defining->expansion = NULL;
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_ENDM:
+ case PP_ENDMACRO:
+ if (!defining)
+ {
+ error(ERR_NONFATAL, "`%s': not defining a macro",
+ tline->text);
+ return DIRECTIVE_FOUND;
+ }
+ k = hash(defining->name);
+ defining->next = mmacros[k];
+ mmacros[k] = defining;
+ defining = NULL;
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_ROTATE:
+ if (tline->next && tline->next->type == TOK_WHITESPACE)
+ tline = tline->next;
+ if (tline->next == NULL)
+ {
+ free_tlist(origline);
+ error(ERR_NONFATAL, "`%%rotate' missing rotate count");
+ return DIRECTIVE_FOUND;
+ }
+ t = expand_smacro(tline->next);
+ tline->next = NULL;
+ free_tlist(origline);
+ tline = t;
+ tptr = &t;
+ tokval.t_type = TOKEN_INVALID;
+ evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
+ free_tlist(tline);
+ if (!evalresult)
+ return DIRECTIVE_FOUND;
+ if (tokval.t_type)
+ error(ERR_WARNING,
+ "trailing garbage after expression ignored");
+ intn = yasm_expr_get_intnum(&evalresult, 0);
+ if (!intn)
+ {
+ error(ERR_NONFATAL, "non-constant value given to `%%rotate'");
+ yasm_expr_destroy(evalresult);
+ return DIRECTIVE_FOUND;
+ }
+ mmac = istk->mstk;
+ while (mmac && !mmac->name) /* avoid mistaking %reps for macros */
+ mmac = mmac->next_active;
+ if (!mmac)
+ {
+ error(ERR_NONFATAL,
+ "`%%rotate' invoked outside a macro call");
+ }
+ else if (mmac->nparam == 0)
+ {
+ error(ERR_NONFATAL,
+ "`%%rotate' invoked within macro without parameters");
+ }
+ else
+ {
+ mmac->rotate = mmac->rotate + yasm_intnum_get_int(intn);
+
+ if (mmac->rotate < 0)
+ mmac->rotate =
+ mmac->nparam - (-mmac->rotate) % mmac->nparam;
+ mmac->rotate %= mmac->nparam;
+ }
+ yasm_expr_destroy(evalresult);
+ return DIRECTIVE_FOUND;
+
+ case PP_REP:
+ nolist = FALSE;
+ do {
+ tline = tline->next;
+ } while (tok_type_(tline, TOK_WHITESPACE));
+
+ if (tok_type_(tline, TOK_ID) &&
+ nasm_stricmp(tline->text, ".nolist") == 0)
+ {
+ nolist = TRUE;
+ do {
+ tline = tline->next;
+ } while (tok_type_(tline, TOK_WHITESPACE));
+ }
+
+ if (tline)
+ {
+ t = expand_smacro(tline);
+ tptr = &t;
+ tokval.t_type = TOKEN_INVALID;
+ evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
+ if (!evalresult)
+ {
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ if (tokval.t_type)
+ error(ERR_WARNING,
+ "trailing garbage after expression ignored");
+ intn = yasm_expr_get_intnum(&evalresult, 0);
+ if (!intn)
+ {
+ error(ERR_NONFATAL, "non-constant value given to `%%rep'");
+ yasm_expr_destroy(evalresult);
+ return DIRECTIVE_FOUND;
+ }
+ i = (int)yasm_intnum_get_int(intn) + 1;
+ yasm_expr_destroy(evalresult);
+ }
+ else
+ {
+ error(ERR_NONFATAL, "`%%rep' expects a repeat count");
+ i = 0;
+ }
+ free_tlist(origline);
+
+ tmp_defining = defining;
+ defining = nasm_malloc(sizeof(MMacro));
+ defining->name = NULL; /* flags this macro as a %rep block */
+ defining->casesense = 0;
+ defining->plus = FALSE;
+ defining->nolist = nolist;
+ defining->in_progress = i;
+ defining->nparam_min = defining->nparam_max = 0;
+ defining->defaults = NULL;
+ defining->dlist = NULL;
+ defining->expansion = NULL;
+ defining->next_active = istk->mstk;
+ defining->rep_nest = tmp_defining;
+ return DIRECTIVE_FOUND;
+
+ case PP_ENDREP:
+ if (!defining || defining->name)
+ {
+ error(ERR_NONFATAL, "`%%endrep': no matching `%%rep'");
+ return DIRECTIVE_FOUND;
+ }
+
+ /*
+ * Now we have a "macro" defined - although it has no name
+ * and we won't be entering it in the hash tables - we must
+ * push a macro-end marker for it on to istk->expansion.
+ * After that, it will take care of propagating itself (a
+ * macro-end marker line for a macro which is really a %rep
+ * block will cause the macro to be re-expanded, complete
+ * with another macro-end marker to ensure the process
+ * continues) until the whole expansion is forcibly removed
+ * from istk->expansion by a %exitrep.
+ */
+ l = nasm_malloc(sizeof(Line));
+ l->next = istk->expansion;
+ l->finishes = defining;
+ l->first = NULL;
+ istk->expansion = l;
+
+ istk->mstk = defining;
+
+ list->uplevel(defining->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
+ tmp_defining = defining;
+ defining = defining->rep_nest;
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_EXITREP:
+ /*
+ * We must search along istk->expansion until we hit a
+ * macro-end marker for a macro with no name. Then we set
+ * its `in_progress' flag to 0.
+ */
+ for (l = istk->expansion; l; l = l->next)
+ if (l->finishes && !l->finishes->name)
+ break;
+
+ if (l)
+ l->finishes->in_progress = 0;
+ else
+ error(ERR_NONFATAL, "`%%exitrep' not within `%%rep' block");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_XDEFINE:
+ case PP_IXDEFINE:
+ case PP_DEFINE:
+ case PP_IDEFINE:
+ tline = tline->next;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tline || (tline->type != TOK_ID &&
+ (tline->type != TOK_PREPROC_ID ||
+ tline->text[1] != '$')))
+ {
+ error(ERR_NONFATAL,
+ "`%%%s%sdefine' expects a macro identifier",
+ ((i == PP_IDEFINE || i == PP_IXDEFINE) ? "i" : ""),
+ ((i == PP_XDEFINE || i == PP_IXDEFINE) ? "x" : ""));
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+
+ ctx = get_ctx(tline->text, FALSE);
+ if (!ctx)
+ smhead = &smacros[hash(tline->text)];
+ else
+ smhead = &ctx->localmac;
+ mname = tline->text;
+ last = tline;
+ param_start = tline = tline->next;
+ nparam = 0;
+
+ /* Expand the macro definition now for %xdefine and %ixdefine */
+ if ((i == PP_XDEFINE) || (i == PP_IXDEFINE))
+ tline = expand_smacro(tline);
+
+ if (tok_is_(tline, "("))
+ {
+ /*
+ * This macro has parameters.
+ */
+
+ tline = tline->next;
+ while (1)
+ {
+ skip_white_(tline);
+ if (!tline)
+ {
+ error(ERR_NONFATAL, "parameter identifier expected");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ if (tline->type != TOK_ID)
+ {
+ error(ERR_NONFATAL,
+ "`%s': parameter identifier expected",
+ tline->text);
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ tline->type = TOK_SMAC_PARAM + nparam++;
+ tline = tline->next;
+ skip_white_(tline);
+ if (tok_is_(tline, ","))
+ {
+ tline = tline->next;
+ continue;
+ }
+ if (!tok_is_(tline, ")"))
+ {
+ error(ERR_NONFATAL,
+ "`)' expected to terminate macro template");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ break;
+ }
+ last = tline;
+ tline = tline->next;
+ }
+ if (tok_type_(tline, TOK_WHITESPACE))
+ last = tline, tline = tline->next;
+ macro_start = NULL;
+ last->next = NULL;
+ t = tline;
+ while (t)
+ {
+ if (t->type == TOK_ID)
+ {
+ for (tt = param_start; tt; tt = tt->next)
+ if (tt->type >= TOK_SMAC_PARAM &&
+ !strcmp(tt->text, t->text))
+ t->type = tt->type;
+ }
+ tt = t->next;
+ t->next = macro_start;
+ macro_start = t;
+ t = tt;
+ }
+ /*
+ * Good. We now have a macro name, a parameter count, and a
+ * token list (in reverse order) for an expansion. We ought
+ * to be OK just to create an SMacro, store it, and let
+ * free_tlist have the rest of the line (which we have
+ * carefully re-terminated after chopping off the expansion
+ * from the end).
+ */
+ if (smacro_defined(ctx, mname, nparam, &smac, i == PP_DEFINE))
+ {
+ if (!smac)
+ {
+ error(ERR_WARNING,
+ "single-line macro `%s' defined both with and"
+ " without parameters", mname);
+ free_tlist(origline);
+ free_tlist(macro_start);
+ return DIRECTIVE_FOUND;
+ }
+ else if (smac->level == Level)
+ {
+ /*
+ * We're redefining in the same level, so we have to
+ * take over an existing SMacro structure. This means
+ * freeing what was already in it.
+ */
+ nasm_free(smac->name);
+ free_tlist(smac->expansion);
+ }
+ else
+ {
+ smac = nasm_malloc(sizeof(SMacro));
+ smac->next = *smhead;
+ *smhead = smac;
+ }
+ }
+ else
+ {
+ smac = nasm_malloc(sizeof(SMacro));
+ smac->next = *smhead;
+ *smhead = smac;
+ }
+ smac->name = nasm_strdup(mname);
+ smac->casesense = ((i == PP_DEFINE) || (i == PP_XDEFINE));
+ smac->nparam = nparam;
+ smac->level = Level;
+ smac->expansion = macro_start;
+ smac->in_progress = FALSE;
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_UNDEF:
+ tline = tline->next;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tline || (tline->type != TOK_ID &&
+ (tline->type != TOK_PREPROC_ID ||
+ tline->text[1] != '$')))
+ {
+ error(ERR_NONFATAL, "`%%undef' expects a macro identifier");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ if (tline->next)
+ {
+ error(ERR_WARNING,
+ "trailing garbage after macro name ignored");
+ }
+
+ /* Find the context that symbol belongs to */
+ ctx = get_ctx(tline->text, FALSE);
+ if (!ctx)
+ smhead = &smacros[hash(tline->text)];
+ else
+ smhead = &ctx->localmac;
+
+ mname = tline->text;
+
+ /*
+ * We now have a macro name... go hunt for it.
+ */
+ while (smacro_defined(ctx, mname, -1, &smac, 1))
+ {
+ /* Defined, so we need to find its predecessor and nuke it */
+ SMacro **s;
+ for (s = smhead; *s && *s != smac; s = &(*s)->next);
+ if (*s)
+ {
+ *s = smac->next;
+ nasm_free(smac->name);
+ free_tlist(smac->expansion);
+ nasm_free(smac);
+ }
+ }
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_STRLEN:
+ tline = tline->next;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tline || (tline->type != TOK_ID &&
+ (tline->type != TOK_PREPROC_ID ||
+ tline->text[1] != '$')))
+ {
+ error(ERR_NONFATAL,
+ "`%%strlen' expects a macro identifier as first parameter");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ ctx = get_ctx(tline->text, FALSE);
+ if (!ctx)
+ smhead = &smacros[hash(tline->text)];
+ else
+ smhead = &ctx->localmac;
+ mname = tline->text;
+ last = tline;
+ tline = expand_smacro(tline->next);
+ last->next = NULL;
+
+ t = tline;
+ while (tok_type_(t, TOK_WHITESPACE))
+ t = t->next;
+ /* t should now point to the string */
+ if (t->type != TOK_STRING)
+ {
+ error(ERR_NONFATAL,
+ "`%%strlen` requires string as second parameter");
+ free_tlist(tline);
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+
+ macro_start = nasm_malloc(sizeof(*macro_start));
+ macro_start->next = NULL;
+ make_tok_num(macro_start,
+ yasm_intnum_create_uint((unsigned long)(strlen(t->text) - 2)));
+ macro_start->mac = NULL;
+
+ /*
+ * We now have a macro name, an implicit parameter count of
+ * zero, and a numeric token to use as an expansion. Create
+ * and store an SMacro.
+ */
+ if (smacro_defined(ctx, mname, 0, &smac, i == PP_STRLEN))
+ {
+ if (!smac)
+ error(ERR_WARNING,
+ "single-line macro `%s' defined both with and"
+ " without parameters", mname);
+ else
+ {
+ /*
+ * We're redefining, so we have to take over an
+ * existing SMacro structure. This means freeing
+ * what was already in it.
+ */
+ nasm_free(smac->name);
+ free_tlist(smac->expansion);
+ }
+ }
+ else
+ {
+ smac = nasm_malloc(sizeof(SMacro));
+ smac->next = *smhead;
+ *smhead = smac;
+ }
+ smac->name = nasm_strdup(mname);
+ smac->casesense = (i == PP_STRLEN);
+ smac->nparam = 0;
+ smac->level = 0;
+ smac->expansion = macro_start;
+ smac->in_progress = FALSE;
+ free_tlist(tline);
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_SUBSTR:
+ tline = tline->next;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tline || (tline->type != TOK_ID &&
+ (tline->type != TOK_PREPROC_ID ||
+ tline->text[1] != '$')))
+ {
+ error(ERR_NONFATAL,
+ "`%%substr' expects a macro identifier as first parameter");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ ctx = get_ctx(tline->text, FALSE);
+ if (!ctx)
+ smhead = &smacros[hash(tline->text)];
+ else
+ smhead = &ctx->localmac;
+ mname = tline->text;
+ last = tline;
+ tline = expand_smacro(tline->next);
+ last->next = NULL;
+
+ t = tline->next;
+ while (tok_type_(t, TOK_WHITESPACE))
+ t = t->next;
+
+ /* t should now point to the string */
+ if (t->type != TOK_STRING)
+ {
+ error(ERR_NONFATAL,
+ "`%%substr` requires string as second parameter");
+ free_tlist(tline);
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+
+ tt = t->next;
+ tptr = &tt;
+ tokval.t_type = TOKEN_INVALID;
+ evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
+ if (!evalresult)
+ {
+ free_tlist(tline);
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ intn = yasm_expr_get_intnum(&evalresult, 0);
+ if (!intn)
+ {
+ error(ERR_NONFATAL, "non-constant value given to `%%substr`");
+ free_tlist(tline);
+ free_tlist(origline);
+ yasm_expr_destroy(evalresult);
+ return DIRECTIVE_FOUND;
+ }
+
+ macro_start = nasm_malloc(sizeof(*macro_start));
+ macro_start->next = NULL;
+ macro_start->text = nasm_strdup("'''");
+ if (yasm_intnum_sign(intn) == 1
+ && yasm_intnum_get_uint(intn) < strlen(t->text) - 1)
+ {
+ macro_start->text[1] = t->text[yasm_intnum_get_uint(intn)];
+ }
+ else
+ {
+ macro_start->text[2] = '\0';
+ }
+ yasm_expr_destroy(evalresult);
+ macro_start->type = TOK_STRING;
+ macro_start->mac = NULL;
+
+ /*
+ * We now have a macro name, an implicit parameter count of
+ * zero, and a numeric token to use as an expansion. Create
+ * and store an SMacro.
+ */
+ if (smacro_defined(ctx, mname, 0, &smac, i == PP_SUBSTR))
+ {
+ if (!smac)
+ error(ERR_WARNING,
+ "single-line macro `%s' defined both with and"
+ " without parameters", mname);
+ else
+ {
+ /*
+ * We're redefining, so we have to take over an
+ * existing SMacro structure. This means freeing
+ * what was already in it.
+ */
+ nasm_free(smac->name);
+ free_tlist(smac->expansion);
+ }
+ }
+ else
+ {
+ smac = nasm_malloc(sizeof(SMacro));
+ smac->next = *smhead;
+ *smhead = smac;
+ }
+ smac->name = nasm_strdup(mname);
+ smac->casesense = (i == PP_SUBSTR);
+ smac->nparam = 0;
+ smac->level = 0;
+ smac->expansion = macro_start;
+ smac->in_progress = FALSE;
+ free_tlist(tline);
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+
+ case PP_ASSIGN:
+ case PP_IASSIGN:
+ tline = tline->next;
+ skip_white_(tline);
+ tline = expand_id(tline);
+ if (!tline || (tline->type != TOK_ID &&
+ (tline->type != TOK_PREPROC_ID ||
+ tline->text[1] != '$')))
+ {
+ error(ERR_NONFATAL,
+ "`%%%sassign' expects a macro identifier",
+ (i == PP_IASSIGN ? "i" : ""));
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ ctx = get_ctx(tline->text, FALSE);
+ if (!ctx)
+ smhead = &smacros[hash(tline->text)];
+ else
+ smhead = &ctx->localmac;
+ mname = tline->text;
+ last = tline;
+ tline = expand_smacro(tline->next);
+ last->next = NULL;
+
+ t = tline;
+ tptr = &t;
+ tokval.t_type = TOKEN_INVALID;
+ evalresult = evaluate(ppscan, tptr, &tokval, pass, error);
+ free_tlist(tline);
+ if (!evalresult)
+ {
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+
+ if (tokval.t_type)
+ error(ERR_WARNING,
+ "trailing garbage after expression ignored");
+
+ intn = yasm_expr_get_intnum(&evalresult, 0);
+ if (!intn)
+ {
+ error(ERR_NONFATAL,
+ "non-constant value given to `%%%sassign'",
+ (i == PP_IASSIGN ? "i" : ""));
+ free_tlist(origline);
+ yasm_expr_destroy(evalresult);
+ return DIRECTIVE_FOUND;
+ }
+
+ macro_start = nasm_malloc(sizeof(*macro_start));
+ macro_start->next = NULL;
+ make_tok_num(macro_start, yasm_intnum_copy(intn));
+ yasm_expr_destroy(evalresult);
+ macro_start->mac = NULL;
+
+ /*
+ * We now have a macro name, an implicit parameter count of
+ * zero, and a numeric token to use as an expansion. Create
+ * and store an SMacro.
+ */
+ if (smacro_defined(ctx, mname, 0, &smac, i == PP_ASSIGN))
+ {
+ if (!smac)
+ error(ERR_WARNING,
+ "single-line macro `%s' defined both with and"
+ " without parameters", mname);
+ else
+ {
+ /*
+ * We're redefining, so we have to take over an
+ * existing SMacro structure. This means freeing
+ * what was already in it.
+ */
+ nasm_free(smac->name);
+ free_tlist(smac->expansion);
+ }
+ }
+ else
+ {
+ smac = nasm_malloc(sizeof(SMacro));
+ smac->next = *smhead;
+ *smhead = smac;
+ }
+ smac->name = nasm_strdup(mname);
+ smac->casesense = (i == PP_ASSIGN);
+ smac->nparam = 0;
+ smac->level = 0;
+ smac->expansion = macro_start;
+ smac->in_progress = FALSE;
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ case PP_LINE:
+ /*
+ * Syntax is `%line nnn[+mmm] [filename]'
+ */
+ tline = tline->next;
+ skip_white_(tline);
+ if (!tok_type_(tline, TOK_NUMBER))
+ {
+ error(ERR_NONFATAL, "`%%line' expects line number");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ intn = nasm_readnum(tline->text, &j);
+ k = yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
+ m = 1;
+ tline = tline->next;
+ if (tok_is_(tline, "+"))
+ {
+ tline = tline->next;
+ if (!tok_type_(tline, TOK_NUMBER))
+ {
+ error(ERR_NONFATAL, "`%%line' expects line increment");
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+ }
+ intn = nasm_readnum(tline->text, &j);
+ m = yasm_intnum_get_int(intn);
+ yasm_intnum_destroy(intn);
+ tline = tline->next;
+ }
+ skip_white_(tline);
+ nasm_src_set_linnum(k);
+ istk->lineinc = m;
+ if (tline)
+ {
+ nasm_free(nasm_src_set_fname(detoken(tline, FALSE)));
+ }
+ free_tlist(origline);
+ return DIRECTIVE_FOUND;
+
+ default:
+ error(ERR_FATAL,
+ "preprocessor directive `%s' not yet implemented",
+ directives[i]);
+ break;
+ }
+ return DIRECTIVE_FOUND;
+}
+
+/*
+ * Ensure that a macro parameter contains a condition code and
+ * nothing else. Return the condition code index if so, or -1
+ * otherwise.
+ */
+static int
+find_cc(Token * t)
+{
+ Token *tt;
+ int i, j, k, m;
+
+ skip_white_(t);
+ if (t->type != TOK_ID)
+ return -1;
+ tt = t->next;
+ skip_white_(tt);
+ if (tt && (tt->type != TOK_OTHER || strcmp(tt->text, ",")))
+ return -1;
+
+ i = -1;
+ j = elements(conditions);
+ while (j - i > 1)
+ {
+ k = (j + i) / 2;
+ m = nasm_stricmp(t->text, conditions[k]);
+ if (m == 0)
+ {
+ i = k;
+ j = -2;
+ break;
+ }
+ else if (m < 0)
+ {
+ j = k;
+ }
+ else
+ i = k;
+ }
+ if (j != -2)
+ return -1;
+ return i;
+}
+
+/*
+ * Expand MMacro-local things: parameter references (%0, %n, %+n,
+ * %-n) and MMacro-local identifiers (%%foo).
+ */
+static Token *
+expand_mmac_params(Token * tline)
+{
+ Token *t, *tt, **tail, *thead;
+
+ tail = &thead;
+ thead = NULL;
+
+ while (tline)
+ {
+ if (tline->type == TOK_PREPROC_ID &&
+ (((tline->text[1] == '+' || tline->text[1] == '-')
+ && tline->text[2]) || tline->text[1] == '%'
+ || (tline->text[1] >= '0' && tline->text[1] <= '9')))
+ {
+ char *text = NULL;
+ int type = 0, cc; /* type = 0 to placate optimisers */
+ char tmpbuf[30];
+ char *second_text = NULL;
+ int n, i;
+ MMacro *mac;
+
+ t = tline;
+ tline = tline->next;
+
+ second_text = strchr(t->text, ':');
+
+ mac = istk->mstk;
+ while (mac && !mac->name) /* avoid mistaking %reps for macros */
+ mac = mac->next_active;
+ if (!mac)
+ error(ERR_NONFATAL, "`%s': not in a macro call", t->text);
+ else
+ {
+ if (second_text)
+ {
+ int end = atoi(second_text+1)-1;
+ int is_fst = 1;
+ int k;
+ n = atoi(t->text + 1)-1;
+ if (end < 0)
+ end += mac->nparam;
+
+ for (k = n; k <= end; k++)
+ {
+ if (k >= mac->nparam)
+ tt = NULL;
+ else
+ {
+ if (mac->nparam > 1)
+ k = (k + mac->rotate) % mac->nparam;
+ tt = mac->params[k];
+ }
+ if (tt)
+ {
+ if (!is_fst && mac->paramlen[k])
+ {
+ *tail = new_Token(NULL, TOK_OTHER, ",", 0);
+ tail = &(*tail)->next;
+ }
+ if (mac->paramlen[k])
+ is_fst = 0;
+ for (i = 0; i < mac->paramlen[k]; i++)
+ {
+ *tail =
+ new_Token(NULL, tt->type, tt->text,
+ 0);
+ tail = &(*tail)->next;
+ tt = tt->next;
+ }
+ }
+ text = NULL; /* we've done it here */
+ }
+ }
+ else
+ {
+ switch (t->text[1])
+ {
+ /*
+ * We have to make a substitution of one of the
+ * forms %1, %-1, %+1, %%foo, %0.
+ */
+ case '0':
+ type = TOK_NUMBER;
+ sprintf(tmpbuf, "%ld", mac->nparam);
+ text = nasm_strdup(tmpbuf);
+ break;
+ case '%':
+ type = TOK_ID;
+ sprintf(tmpbuf, "..@%lu.", mac->unique);
+ text = nasm_strcat(tmpbuf, t->text + 2);
+ break;
+ case '-':
+ n = atoi(t->text + 2) - 1;
+ if (n >= mac->nparam)
+ tt = NULL;
+ else
+ {
+ if (mac->nparam > 1)
+ n = (n + mac->rotate) % mac->nparam;
+ tt = mac->params[n];
+ }
+ cc = find_cc(tt);
+ if (cc == -1)
+ {
+ error(ERR_NONFATAL,
+ "macro parameter %d is not a condition code",
+ n + 1);
+ text = NULL;
+ }
+ else
+ {
+ type = TOK_ID;
+ if (inverse_ccs[cc] == -1)
+ {
+ error(ERR_NONFATAL,
+ "condition code `%s' is not invertible",
+ conditions[cc]);
+ text = NULL;
+ }
+ else
+ text =
+ nasm_strdup(conditions[inverse_ccs
+ [cc]]);
+ }
+ break;
+ case '+':
+ n = atoi(t->text + 2) - 1;
+ if (n >= mac->nparam)
+ tt = NULL;
+ else
+ {
+ if (mac->nparam > 1)
+ n = (n + mac->rotate) % mac->nparam;
+ tt = mac->params[n];
+ }
+ cc = find_cc(tt);
+ if (cc == -1)
+ {
+ error(ERR_NONFATAL,
+ "macro parameter %d is not a condition code",
+ n + 1);
+ text = NULL;
+ }
+ else
+ {
+ type = TOK_ID;
+ text = nasm_strdup(conditions[cc]);
+ }
+ break;
+ default:
+ n = atoi(t->text + 1) - 1;
+ if (n >= mac->nparam)
+ tt = NULL;
+ else
+ {
+ if (mac->nparam > 1)
+ n = (n + mac->rotate) % mac->nparam;
+ tt = mac->params[n];
+ }
+ if (tt)
+ {
+ for (i = 0; i < mac->paramlen[n]; i++)
+ {
+ *tail =
+ new_Token(NULL, tt->type, tt->text,
+ 0);
+ tail = &(*tail)->next;
+ tt = tt->next;
+ }
+ }
+ text = NULL; /* we've done it here */
+ break;
+ }
+ }
+ }
+
+ if (!text)
+ {
+ delete_Token(t);
+ }
+ else
+ {
+ *tail = t;
+ tail = &t->next;
+ t->type = type;
+ nasm_free(t->text);
+ t->text = text;
+ t->mac = NULL;
+ }
+ continue;
+ }
+ else
+ {
+ t = *tail = tline;
+ tline = tline->next;
+ t->mac = NULL;
+ tail = &t->next;
+ }
+ }
+ *tail = NULL;
+ t = thead;
+ for (; t && (tt = t->next) != NULL; t = t->next)
+ switch (t->type)
+ {
+ case TOK_WHITESPACE:
+ if (tt->type == TOK_WHITESPACE)
+ {
+ t->next = delete_Token(tt);
+ }
+ break;
+ case TOK_ID:
+ if (tt->type == TOK_ID || tt->type == TOK_NUMBER)
+ {
+ char *tmp = nasm_strcat(t->text, tt->text);
+ nasm_free(t->text);
+ t->text = tmp;
+ t->next = delete_Token(tt);
+ }
+ break;
+ case TOK_NUMBER:
+ if (tt->type == TOK_NUMBER)
+ {
+ char *tmp = nasm_strcat(t->text, tt->text);
+ nasm_free(t->text);
+ t->text = tmp;
+ t->next = delete_Token(tt);
+ }
+ break;
+ }
+
+ return thead;
+}
+
+/*
+ * Expand all single-line macro calls made in the given line.
+ * Return the expanded version of the line. The original is deemed
+ * to be destroyed in the process. (In reality we'll just move
+ * Tokens from input to output a lot of the time, rather than
+ * actually bothering to destroy and replicate.)
+ */
+static Token *
+expand_smacro(Token * tline)
+{
+ Token *t, *tt, *mstart, **tail, *thead;
+ SMacro *head = NULL, *m;
+ Token **params;
+ int *paramsize;
+ int nparam, sparam, brackets, rescan;
+ Token *org_tline = tline;
+ Context *ctx;
+ char *mname;
+
+ /*
+ * Trick: we should avoid changing the start token pointer since it can
+ * be contained in "next" field of other token. Because of this
+ * we allocate a copy of first token and work with it; at the end of
+ * routine we copy it back
+ */
+ if (org_tline)
+ {
+ tline =
+ new_Token(org_tline->next, org_tline->type, org_tline->text,
+ 0);
+ tline->mac = org_tline->mac;
+ nasm_free(org_tline->text);
+ org_tline->text = NULL;
+ }
+
+ again:
+ tail = &thead;
+ thead = NULL;
+
+ while (tline)
+ { /* main token loop */
+ if ((mname = tline->text))
+ {
+ /* if this token is a local macro, look in local context */
+ if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
+ ctx = get_ctx(mname, TRUE);
+ else
+ ctx = NULL;
+ if (!ctx)
+ head = smacros[hash(mname)];
+ else
+ head = ctx->localmac;
+ /*
+ * We've hit an identifier. As in is_mmacro below, we first
+ * check whether the identifier is a single-line macro at
+ * all, then think about checking for parameters if
+ * necessary.
+ */
+ for (m = head; m; m = m->next)
+ if (!mstrcmp(m->name, mname, m->casesense))
+ break;
+ if (m)
+ {
+ mstart = tline;
+ params = NULL;
+ paramsize = NULL;
+ if (m->nparam == 0)
+ {
+ /*
+ * Simple case: the macro is parameterless. Discard the
+ * one token that the macro call took, and push the
+ * expansion back on the to-do stack.
+ */
+ if (!m->expansion)
+ {
+ if (!strcmp("__FILE__", m->name))
+ {
+ long num = 0;
+ nasm_src_get(&num, &(tline->text));
+ nasm_quote(&(tline->text));
+ tline->type = TOK_STRING;
+ continue;
+ }
+ if (!strcmp("__LINE__", m->name))
+ {
+ nasm_free(tline->text);
+ make_tok_num(tline, yasm_intnum_create_int(nasm_src_get_linnum()));
+ continue;
+ }
+ tline = delete_Token(tline);
+ continue;
+ }
+ }
+ else
+ {
+ /*
+ * Complicated case: at least one macro with this name
+ * exists and takes parameters. We must find the
+ * parameters in the call, count them, find the SMacro
+ * that corresponds to that form of the macro call, and
+ * substitute for the parameters when we expand. What a
+ * pain.
+ */
+ /*tline = tline->next;
+ skip_white_(tline);*/
+ do {
+ t = tline->next;
+ while (tok_type_(t, TOK_SMAC_END))
+ {
+ t->mac->in_progress = FALSE;
+ t->text = NULL;
+ t = tline->next = delete_Token(t);
+ }
+ tline = t;
+ } while (tok_type_(tline, TOK_WHITESPACE));
+ if (!tok_is_(tline, "("))
+ {
+ /*
+ * This macro wasn't called with parameters: ignore
+ * the call. (Behaviour borrowed from gnu cpp.)
+ */
+ tline = mstart;
+ m = NULL;
+ }
+ else
+ {
+ int paren = 0;
+ int white = 0;
+ brackets = 0;
+ nparam = 0;
+ sparam = PARAM_DELTA;
+ params = nasm_malloc(sparam * sizeof(Token *));
+ params[0] = tline->next;
+ paramsize = nasm_malloc(sparam * sizeof(int));
+ paramsize[0] = 0;
+ while (TRUE)
+ { /* parameter loop */
+ /*
+ * For some unusual expansions
+ * which concatenates function call
+ */
+ t = tline->next;
+ while (tok_type_(t, TOK_SMAC_END))
+ {
+ t->mac->in_progress = FALSE;
+ t->text = NULL;
+ t = tline->next = delete_Token(t);
+ }
+ tline = t;
+
+ if (!tline)
+ {
+ error(ERR_NONFATAL,
+ "macro call expects terminating `)'");
+ break;
+ }
+ if (tline->type == TOK_WHITESPACE
+ && brackets <= 0)
+ {
+ if (paramsize[nparam])
+ white++;
+ else
+ params[nparam] = tline->next;
+ continue; /* parameter loop */
+ }
+ if (tline->type == TOK_OTHER
+ && tline->text[1] == 0)
+ {
+ char ch = tline->text[0];
+ if (ch == ',' && !paren && brackets <= 0)
+ {
+ if (++nparam >= sparam)
+ {
+ sparam += PARAM_DELTA;
+ params = nasm_realloc(params,
+ sparam * sizeof(Token *));
+ paramsize = nasm_realloc(paramsize,
+ sparam * sizeof(int));
+ }
+ params[nparam] = tline->next;
+ paramsize[nparam] = 0;
+ white = 0;
+ continue; /* parameter loop */
+ }
+ if (ch == '{' &&
+ (brackets > 0 || (brackets == 0 &&
+ !paramsize[nparam])))
+ {
+ if (!(brackets++))
+ {
+ params[nparam] = tline->next;
+ continue; /* parameter loop */
+ }
+ }
+ if (ch == '}' && brackets > 0)
+ if (--brackets == 0)
+ {
+ brackets = -1;
+ continue; /* parameter loop */
+ }
+ if (ch == '(' && !brackets)
+ paren++;
+ if (ch == ')' && brackets <= 0)
+ if (--paren < 0)
+ break;
+ }
+ if (brackets < 0)
+ {
+ brackets = 0;
+ error(ERR_NONFATAL, "braces do not "
+ "enclose all of macro parameter");
+ }
+ paramsize[nparam] += white + 1;
+ white = 0;
+ } /* parameter loop */
+ nparam++;
+ while (m && (m->nparam != nparam ||
+ mstrcmp(m->name, mname,
+ m->casesense)))
+ m = m->next;
+ if (!m)
+ error(ERR_WARNING | ERR_WARN_MNP,
+ "macro `%s' exists, "
+ "but not taking %d parameters",
+ mstart->text, nparam);
+ }
+ }
+ if (m && m->in_progress)
+ m = NULL;
+ if (!m) /* in progess or didn't find '(' or wrong nparam */
+ {
+ /*
+ * Design question: should we handle !tline, which
+ * indicates missing ')' here, or expand those
+ * macros anyway, which requires the (t) test a few
+ * lines down?
+ */
+ nasm_free(params);
+ nasm_free(paramsize);
+ tline = mstart;
+ }
+ else
+ {
+ /*
+ * Expand the macro: we are placed on the last token of the
+ * call, so that we can easily split the call from the
+ * following tokens. We also start by pushing an SMAC_END
+ * token for the cycle removal.
+ */
+ t = tline;
+ if (t)
+ {
+ tline = t->next;
+ t->next = NULL;
+ }
+ tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
+ tt->mac = m;
+ m->in_progress = TRUE;
+ tline = tt;
+ for (t = m->expansion; t; t = t->next)
+ {
+ if (t->type >= TOK_SMAC_PARAM)
+ {
+ Token *pcopy = tline, **ptail = &pcopy;
+ Token *ttt, *pt;
+ int i;
+
+ ttt = params[t->type - TOK_SMAC_PARAM];
+ for (i = paramsize[t->type - TOK_SMAC_PARAM];
+ --i >= 0;)
+ {
+ pt = *ptail =
+ new_Token(tline, ttt->type, ttt->text,
+ 0);
+ ptail = &pt->next;
+ ttt = ttt->next;
+ }
+ tline = pcopy;
+ }
+ else
+ {
+ tt = new_Token(tline, t->type, t->text, 0);
+ tline = tt;
+ }
+ }
+
+ /*
+ * Having done that, get rid of the macro call, and clean
+ * up the parameters.
+ */
+ nasm_free(params);
+ nasm_free(paramsize);
+ free_tlist(mstart);
+ continue; /* main token loop */
+ }
+ }
+ }
+
+ if (tline->type == TOK_SMAC_END)
+ {
+ tline->mac->in_progress = FALSE;
+ tline = delete_Token(tline);
+ }
+ else
+ {
+ t = *tail = tline;
+ tline = tline->next;
+ t->mac = NULL;
+ t->next = NULL;
+ tail = &t->next;
+ }
+ }
+
+ /*
+ * Now scan the entire line and look for successive TOK_IDs that resulted
+ * after expansion (they can't be produced by tokenise()). The successive
+ * TOK_IDs should be concatenated.
+ * Also we look for %+ tokens and concatenate the tokens before and after
+ * them (without white spaces in between).
+ */
+ t = thead;
+ rescan = 0;
+ while (t)
+ {
+ while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
+ t = t->next;
+ if (!t || !t->next)
+ break;
+ if (t->next->type == TOK_ID ||
+ t->next->type == TOK_PREPROC_ID ||
+ t->next->type == TOK_NUMBER)
+ {
+ char *p = nasm_strcat(t->text, t->next->text);
+ nasm_free(t->text);
+ t->next = delete_Token(t->next);
+ t->text = p;
+ rescan = 1;
+ }
+ else if (t->next->type == TOK_WHITESPACE && t->next->next &&
+ t->next->next->type == TOK_PREPROC_ID &&
+ strcmp(t->next->next->text, "%+") == 0)
+ {
+ /* free the next whitespace, the %+ token and next whitespace */
+ int i;
+ for (i = 1; i <= 3; i++)
+ {
+ if (!t->next || (i != 2 && t->next->type != TOK_WHITESPACE))
+ break;
+ t->next = delete_Token(t->next);
+ } /* endfor */
+ }
+ else
+ t = t->next;
+ }
+ /* If we concatenaded something, re-scan the line for macros */
+ if (rescan)
+ {
+ tline = thead;
+ goto again;
+ }
+
+ if (org_tline)
+ {
+ if (thead)
+ {
+ *org_tline = *thead;
+ /* since we just gave text to org_line, don't free it */
+ thead->text = NULL;
+ delete_Token(thead);
+ }
+ else
+ {
+ /* the expression expanded to empty line;
+ we can't return NULL for some reasons
+ we just set the line to a single WHITESPACE token. */
+ memset(org_tline, 0, sizeof(*org_tline));
+ org_tline->text = NULL;
+ org_tline->type = TOK_WHITESPACE;
+ }
+ thead = org_tline;
+ }
+
+ return thead;
+}
+
+/*
+ * Similar to expand_smacro but used exclusively with macro identifiers
+ * right before they are fetched in. The reason is that there can be
+ * identifiers consisting of several subparts. We consider that if there
+ * are more than one element forming the name, user wants a expansion,
+ * otherwise it will be left as-is. Example:
+ *
+ * %define %$abc cde
+ *
+ * the identifier %$abc will be left as-is so that the handler for %define
+ * will suck it and define the corresponding value. Other case:
+ *
+ * %define _%$abc cde
+ *
+ * In this case user wants name to be expanded *before* %define starts
+ * working, so we'll expand %$abc into something (if it has a value;
+ * otherwise it will be left as-is) then concatenate all successive
+ * PP_IDs into one.
+ */
+static Token *
+expand_id(Token * tline)
+{
+ Token *cur, *oldnext = NULL;
+
+ if (!tline || !tline->next)
+ return tline;
+
+ cur = tline;
+ while (cur->next &&
+ (cur->next->type == TOK_ID ||
+ cur->next->type == TOK_PREPROC_ID || cur->next->type == TOK_NUMBER))
+ cur = cur->next;
+
+ /* If identifier consists of just one token, don't expand */
+ if (cur == tline)
+ return tline;
+
+ if (cur)
+ {
+ oldnext = cur->next; /* Detach the tail past identifier */
+ cur->next = NULL; /* so that expand_smacro stops here */
+ }
+
+ tline = expand_smacro(tline);
+
+ if (cur)
+ {
+ /* expand_smacro possibly changhed tline; re-scan for EOL */
+ cur = tline;
+ while (cur && cur->next)
+ cur = cur->next;
+ if (cur)
+ cur->next = oldnext;
+ }
+
+ return tline;
+}
+
+/*
+ * Determine whether the given line constitutes a multi-line macro
+ * call, and return the MMacro structure called if so. Doesn't have
+ * to check for an initial label - that's taken care of in
+ * expand_mmacro - but must check numbers of parameters. Guaranteed
+ * to be called with tline->type == TOK_ID, so the putative macro
+ * name is easy to find.
+ */
+static MMacro *
+is_mmacro(Token * tline, Token *** params_array)
+{
+ MMacro *head, *m;
+ Token **params;
+ int nparam;
+
+ head = mmacros[hash(tline->text)];
+
+ /*
+ * Efficiency: first we see if any macro exists with the given
+ * name. If not, we can return NULL immediately. _Then_ we
+ * count the parameters, and then we look further along the
+ * list if necessary to find the proper MMacro.
+ */
+ for (m = head; m; m = m->next)
+ if (!mstrcmp(m->name, tline->text, m->casesense))
+ break;
+ if (!m)
+ return NULL;
+
+ /*
+ * OK, we have a potential macro. Count and demarcate the
+ * parameters.
+ */
+ count_mmac_params(tline->next, &nparam, &params);
+
+ /*
+ * So we know how many parameters we've got. Find the MMacro
+ * structure that handles this number.
+ */
+ while (m)
+ {
+ if (m->nparam_min <= nparam && (m->plus || nparam <= m->nparam_max))
+ {
+ /*
+ * This one is right. Just check if cycle removal
+ * prohibits us using it before we actually celebrate...
+ */
+ if (m->in_progress)
+ {
+#if 0
+ error(ERR_NONFATAL,
+ "self-reference in multi-line macro `%s'", m->name);
+#endif
+ nasm_free(params);
+ return NULL;
+ }
+ /*
+ * It's right, and we can use it. Add its default
+ * parameters to the end of our list if necessary.
+ */
+ if (m->defaults && nparam < m->nparam_min + m->ndefs)
+ {
+ params =
+ nasm_realloc(params,
+ ((m->nparam_min + m->ndefs + 1) * sizeof(*params)));
+ while (nparam < m->nparam_min + m->ndefs)
+ {
+ params[nparam] = m->defaults[nparam - m->nparam_min];
+ nparam++;
+ }
+ }
+ /*
+ * If we've gone over the maximum parameter count (and
+ * we're in Plus mode), ignore parameters beyond
+ * nparam_max.
+ */
+ if (m->plus && nparam > m->nparam_max)
+ nparam = m->nparam_max;
+ /*
+ * Then terminate the parameter list, and leave.
+ */
+ if (!params)
+ { /* need this special case */
+ params = nasm_malloc(sizeof(*params));
+ nparam = 0;
+ }
+ params[nparam] = NULL;
+ *params_array = params;
+ return m;
+ }
+ /*
+ * This one wasn't right: look for the next one with the
+ * same name.
+ */
+ for (m = m->next; m; m = m->next)
+ if (!mstrcmp(m->name, tline->text, m->casesense))
+ break;
+ }
+
+ /*
+ * After all that, we didn't find one with the right number of
+ * parameters. Issue a warning, and fail to expand the macro.
+ */
+ error(ERR_WARNING | ERR_WARN_MNP,
+ "macro `%s' exists, but not taking %d parameters",
+ tline->text, nparam);
+ nasm_free(params);
+ return NULL;
+}
+
+/*
+ * Expand the multi-line macro call made by the given line, if
+ * there is one to be expanded. If there is, push the expansion on
+ * istk->expansion and return 1. Otherwise return 0.
+ */
+static int
+expand_mmacro(Token * tline)
+{
+ Token *startline = tline;
+ Token *label = NULL;
+ int dont_prepend = 0;
+ Token **params, *t, *tt;
+ MMacro *m;
+ Line *l, *ll;
+ int i, nparam;
+ long *paramlen;
+
+ t = tline;
+ skip_white_(t);
+/* if (!tok_type_(t, TOK_ID)) Lino 02/25/02 */
+ if (!tok_type_(t, TOK_ID) && !tok_type_(t, TOK_PREPROC_ID))
+ return 0;
+ m = is_mmacro(t, &params);
+ if (!m)
+ {
+ Token *last;
+ /*
+ * We have an id which isn't a macro call. We'll assume
+ * it might be a label; we'll also check to see if a
+ * colon follows it. Then, if there's another id after
+ * that lot, we'll check it again for macro-hood.
+ */
+ label = last = t;
+ t = t->next;
+ if (tok_type_(t, TOK_WHITESPACE))
+ last = t, t = t->next;
+ if (tok_is_(t, ":"))
+ {
+ dont_prepend = 1;
+ last = t, t = t->next;
+ if (tok_type_(t, TOK_WHITESPACE))
+ last = t, t = t->next;
+ }
+ if (!tok_type_(t, TOK_ID) || (m = is_mmacro(t, &params)) == NULL)
+ return 0;
+ last->next = NULL;
+ tline = t;
+ }
+
+ /*
+ * Fix up the parameters: this involves stripping leading and
+ * trailing whitespace, then stripping braces if they are
+ * present.
+ */
+ for (nparam = 0; params[nparam]; nparam++)
+ ;
+ paramlen = nparam ? nasm_malloc(nparam * sizeof(*paramlen)) : NULL;
+
+ for (i = 0; params[i]; i++)
+ {
+ int brace = FALSE;
+ int comma = (!m->plus || i < nparam - 1);
+
+ t = params[i];
+ skip_white_(t);
+ if (tok_is_(t, "{"))
+ t = t->next, brace = TRUE, comma = FALSE;
+ params[i] = t;
+ paramlen[i] = 0;
+ while (t)
+ {
+ if (comma && t->type == TOK_OTHER && !strcmp(t->text, ","))
+ break; /* ... because we have hit a comma */
+ if (comma && t->type == TOK_WHITESPACE && tok_is_(t->next, ","))
+ break; /* ... or a space then a comma */
+ if (brace && t->type == TOK_OTHER && !strcmp(t->text, "}"))
+ break; /* ... or a brace */
+ t = t->next;
+ paramlen[i]++;
+ }
+ }
+
+ /*
+ * OK, we have a MMacro structure together with a set of
+ * parameters. We must now go through the expansion and push
+ * copies of each Line on to istk->expansion. Substitution of
+ * parameter tokens and macro-local tokens doesn't get done
+ * until the single-line macro substitution process; this is
+ * because delaying them allows us to change the semantics
+ * later through %rotate.
+ *
+ * First, push an end marker on to istk->expansion, mark this
+ * macro as in progress, and set up its invocation-specific
+ * variables.
+ */
+ ll = nasm_malloc(sizeof(Line));
+ ll->next = istk->expansion;
+ ll->finishes = m;
+ ll->first = NULL;
+ istk->expansion = ll;
+
+ m->in_progress = TRUE;
+ m->params = params;
+ m->iline = tline;
+ m->nparam = nparam;
+ m->rotate = 0;
+ m->paramlen = paramlen;
+ m->unique = unique++;
+ m->lineno = 0;
+
+ m->next_active = istk->mstk;
+ istk->mstk = m;
+
+ for (l = m->expansion; l; l = l->next)
+ {
+ Token **tail;
+
+ ll = nasm_malloc(sizeof(Line));
+ ll->finishes = NULL;
+ ll->next = istk->expansion;
+ istk->expansion = ll;
+ tail = &ll->first;
+
+ for (t = l->first; t; t = t->next)
+ {
+ Token *x = t;
+ if (t->type == TOK_PREPROC_ID &&
+ t->text[1] == '0' && t->text[2] == '0')
+ {
+ dont_prepend = -1;
+ x = label;
+ if (!x)
+ continue;
+ }
+ tt = *tail = new_Token(NULL, x->type, x->text, 0);
+ tail = &tt->next;
+ }
+ *tail = NULL;
+ }
+
+ /*
+ * If we had a label, push it on as the first line of
+ * the macro expansion.
+ */
+ if (label)
+ {
+ if (dont_prepend < 0)
+ free_tlist(startline);
+ else
+ {
+ ll = nasm_malloc(sizeof(Line));
+ ll->finishes = NULL;
+ ll->next = istk->expansion;
+ istk->expansion = ll;
+ ll->first = startline;
+ if (!dont_prepend)
+ {
+ while (label->next)
+ label = label->next;
+ label->next = tt = new_Token(NULL, TOK_OTHER, ":", 0);
+ }
+ }
+ }
+
+ list->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO);
+
+ return 1;
+}
+
+/*
+ * Since preprocessor always operates only on the line that didn't
+ * arrive yet, we should always use ERR_OFFBY1. Also since user
+ * won't want to see same error twice (preprocessing is done once
+ * per pass) we will want to show errors only during pass one.
+ */
+static void
+error(int severity, const char *fmt, ...)
+{
+ va_list arg;
+ char buff[1024];
+
+ /* If we're in a dead branch of IF or something like it, ignore the error */
+ if (istk && istk->conds && !emitting(istk->conds->state))
+ return;
+
+ va_start(arg, fmt);
+#ifdef HAVE_VSNPRINTF
+ vsnprintf(buff, sizeof(buff), fmt, arg);
+#else
+ vsprintf(buff, fmt, arg);
+#endif
+ va_end(arg);
+
+ if (istk && istk->mstk && istk->mstk->name)
+ _error(severity | ERR_PASS1, "(%s:%d) %s", istk->mstk->name,
+ istk->mstk->lineno, buff);
+ else
+ _error(severity | ERR_PASS1, "%s", buff);
+}
+
+static void
+pp_reset(FILE *f, const char *file, int apass, efunc errfunc, evalfunc eval,
+ ListGen * listgen)
+{
+ int h;
+
+ first_fp = f;
+ _error = errfunc;
+ cstk = NULL;
+ istk = nasm_malloc(sizeof(Include));
+ istk->next = NULL;
+ istk->conds = NULL;
+ istk->expansion = NULL;
+ istk->mstk = NULL;
+ istk->fp = f;
+ istk->fname = NULL;
+ nasm_free(nasm_src_set_fname(nasm_strdup(file)));
+ nasm_src_set_linnum(0);
+ istk->lineinc = 1;
+ defining = NULL;
+ nested_mac_count = 0;
+ nested_rep_count = 0;
+ for (h = 0; h < NHASH; h++)
+ {
+ mmacros[h] = NULL;
+ smacros[h] = NULL;
+ }
+ unique = 0;
+ if (tasm_compatible_mode) {
+ pp_extra_stdmac(tasm_compat_macros);
+ }
+ list = listgen;
+ evaluate = eval;
+ pass = apass;
+ first_line = 1;
+}
+
+/*
+ * Nasty hack: here we push the contents of `predef' on
+ * to the top-level expansion stack, since this is the
+ * most convenient way to implement the pre-include and
+ * pre-define features.
+ */
+static void
+poke_predef(Line *predef_lines)
+{
+ Line *pd, *l;
+ Token *head, **tail, *t;
+
+ for (pd = predef_lines; pd; pd = pd->next)
+ {
+ head = NULL;
+ tail = &head;
+ for (t = pd->first; t; t = t->next)
+ {
+ *tail = new_Token(NULL, t->type, t->text, 0);
+ tail = &(*tail)->next;
+ }
+ l = nasm_malloc(sizeof(Line));
+ l->next = istk->expansion;
+ l->first = head;
+ l->finishes = FALSE;
+ istk->expansion = l;
+ }
+}
+
+static char *
+pp_getline(void)
+{
+ char *line;
+ Token *tline;
+
+ while (1)
+ {
+ /*
+ * Fetch a tokenised line, either from the macro-expansion
+ * buffer or from the input file.
+ */
+ tline = NULL;
+
+ if (first_line)
+ {
+ /* Reverse order */
+ poke_predef(predef);
+ poke_predef(stddef);
+ poke_predef(builtindef);
+ first_line = 0;
+ }
+
+ if (!istk)
+ return NULL;
+ while (istk->expansion && istk->expansion->finishes)
+ {
+ Line *l = istk->expansion;
+ if (!l->finishes->name && l->finishes->in_progress > 1)
+ {
+ Line *ll;
+
+ /*
+ * This is a macro-end marker for a macro with no
+ * name, which means it's not really a macro at all
+ * but a %rep block, and the `in_progress' field is
+ * more than 1, meaning that we still need to
+ * repeat. (1 means the natural last repetition; 0
+ * means termination by %exitrep.) We have
+ * therefore expanded up to the %endrep, and must
+ * push the whole block on to the expansion buffer
+ * again. We don't bother to remove the macro-end
+ * marker: we'd only have to generate another one
+ * if we did.
+ */
+ l->finishes->in_progress--;
+ for (l = l->finishes->expansion; l; l = l->next)
+ {
+ Token *t, *tt, **tail;
+
+ ll = nasm_malloc(sizeof(Line));
+ ll->next = istk->expansion;
+ ll->finishes = NULL;
+ ll->first = NULL;
+ tail = &ll->first;
+
+ for (t = l->first; t; t = t->next)
+ {
+ if (t->text || t->type == TOK_WHITESPACE)
+ {
+ tt = *tail = new_Token(NULL, t->type, t->text, 0);
+ tail = &tt->next;
+ }
+ }
+
+ istk->expansion = ll;
+ }
+ }
+ else
+ {
+ /*
+ * Check whether a `%rep' was started and not ended
+ * within this macro expansion. This can happen and
+ * should be detected. It's a fatal error because
+ * I'm too confused to work out how to recover
+ * sensibly from it.
+ */
+ if (defining)
+ {
+ if (defining->name)
+ error(ERR_PANIC, "defining with name in expansion");
+ else if (istk->mstk->name)
+ error(ERR_FATAL, "`%%rep' without `%%endrep' within"
+ " expansion of macro `%s'", istk->mstk->name);
+ }
+
+ /*
+ * FIXME: investigate the relationship at this point between
+ * istk->mstk and l->finishes
+ */
+ {
+ MMacro *m = istk->mstk;
+ istk->mstk = m->next_active;
+ if (m->name)
+ {
+ /*
+ * This was a real macro call, not a %rep, and
+ * therefore the parameter information needs to
+ * be freed.
+ */
+ nasm_free(m->params);
+ free_tlist(m->iline);
+ nasm_free(m->paramlen);
+ l->finishes->in_progress = FALSE;
+ }
+ else
+ free_mmacro(m);
+ }
+ istk->expansion = l->next;
+ nasm_free(l);
+ list->downlevel(LIST_MACRO);
+ }
+ }
+ while (1)
+ { /* until we get a line we can use */
+
+ if (istk->expansion)
+ { /* from a macro expansion */
+ char *p;
+ Line *l = istk->expansion;
+ if (istk->mstk)
+ istk->mstk->lineno++;
+ tline = l->first;
+ istk->expansion = l->next;
+ nasm_free(l);
+ p = detoken(tline, FALSE);
+ list->line(LIST_MACRO, p);
+ nasm_free(p);
+ break;
+ }
+ line = read_line();
+ if (line)
+ { /* from the current input file */
+ line = prepreproc(line);
+ tline = tokenise(line);
+ nasm_free(line);
+ break;
+ }
+ /*
+ * The current file has ended; work down the istk
+ */
+ {
+ Include *i = istk;
+ if (i->fp != first_fp)
+ fclose(i->fp);
+ if (i->conds)
+ error(ERR_FATAL, "expected `%%endif' before end of file");
+ /* only set line and file name if there's a next node */
+ if (i->next)
+ {
+ nasm_src_set_linnum(i->lineno);
+ nasm_free(nasm_src_set_fname(nasm_strdup(i->fname)));
+ }
+ istk = i->next;
+ list->downlevel(LIST_INCLUDE);
+ nasm_free(i);
+ if (!istk)
+ return NULL;
+ if (istk->expansion && istk->expansion->finishes)
+ break;
+ }
+ }
+
+ /*
+ * We must expand MMacro parameters and MMacro-local labels
+ * _before_ we plunge into directive processing, to cope
+ * with things like `%define something %1' such as STRUC
+ * uses. Unless we're _defining_ a MMacro, in which case
+ * those tokens should be left alone to go into the
+ * definition; and unless we're in a non-emitting
+ * condition, in which case we don't want to meddle with
+ * anything.
+ */
+ if (!defining && !(istk->conds && !emitting(istk->conds->state)))
+ tline = expand_mmac_params(tline);
+
+ /*
+ * Check the line to see if it's a preprocessor directive.
+ */
+ if (do_directive(tline) == DIRECTIVE_FOUND)
+ {
+ continue;
+ }
+ else if (defining)
+ {
+ /*
+ * We're defining a multi-line macro. We emit nothing
+ * at all, and just
+ * shove the tokenised line on to the macro definition.
+ */
+ Line *l = nasm_malloc(sizeof(Line));
+ l->next = defining->expansion;
+ l->first = tline;
+ l->finishes = FALSE;
+ defining->expansion = l;
+ continue;
+ }
+ else if (istk->conds && !emitting(istk->conds->state))
+ {
+ /*
+ * We're in a non-emitting branch of a condition block.
+ * Emit nothing at all, not even a blank line: when we
+ * emerge from the condition we'll give a line-number
+ * directive so we keep our place correctly.
+ */
+ free_tlist(tline);
+ continue;
+ }
+ else if (istk->mstk && !istk->mstk->in_progress)
+ {
+ /*
+ * We're in a %rep block which has been terminated, so
+ * we're walking through to the %endrep without
+ * emitting anything. Emit nothing at all, not even a
+ * blank line: when we emerge from the %rep block we'll
+ * give a line-number directive so we keep our place
+ * correctly.
+ */
+ free_tlist(tline);
+ continue;
+ }
+ else
+ {
+ tline = expand_smacro(tline);
+ if (!expand_mmacro(tline))
+ {
+ /*
+ * De-tokenise the line again, and emit it.
+ */
+ if (tasm_compatible_mode)
+ tline = tasm_join_tokens(tline);
+
+ line = detoken(tline, TRUE);
+ free_tlist(tline);
+ break;
+ }
+ else
+ {
+ continue; /* expand_mmacro calls free_tlist */
+ }
+ }
+ }
+
+ return line;
+}
+
+static void
+pp_cleanup(int pass_)
+{
+ int h;
+
+ if (pass_ == 1)
+ {
+ if (defining)
+ {
+ error(ERR_NONFATAL, "end of file while still defining macro `%s'",
+ defining->name);
+ free_mmacro(defining);
+ }
+ return;
+ }
+ while (cstk)
+ ctx_pop();
+ for (h = 0; h < NHASH; h++)
+ {
+ while (mmacros[h])
+ {
+ MMacro *m = mmacros[h];
+ mmacros[h] = mmacros[h]->next;
+ free_mmacro(m);
+ }
+ while (smacros[h])
+ {
+ SMacro *s = smacros[h];
+ smacros[h] = smacros[h]->next;
+ nasm_free(s->name);
+ free_tlist(s->expansion);
+ nasm_free(s);
+ }
+ }
+ while (istk)
+ {
+ Include *i = istk;
+ istk = istk->next;
+ if (i->fp != first_fp)
+ fclose(i->fp);
+ nasm_free(i->fname);
+ nasm_free(i);
+ }
+ while (cstk)
+ ctx_pop();
+ if (pass_ == 0)
+ {
+ free_llist(builtindef);
+ free_llist(stddef);
+ free_llist(predef);
+ builtindef = NULL;
+ stddef = NULL;
+ predef = NULL;
+ freeTokens = NULL;
+ delete_Blocks();
+ blocks.next = NULL;
+ blocks.chunk = NULL;
+ }
+}
+
+void
+pp_pre_include(const char *fname)
+{
+ Token *inc, *space, *name;
+ Line *l;
+
+ name = new_Token(NULL, TOK_INTERNAL_STRING, fname, 0);
+ space = new_Token(name, TOK_WHITESPACE, NULL, 0);
+ inc = new_Token(space, TOK_PREPROC_ID, "%include", 0);
+
+ l = nasm_malloc(sizeof(Line));
+ l->next = predef;
+ l->first = inc;
+ l->finishes = FALSE;
+ predef = l;
+}
+
+void
+pp_pre_define(char *definition)
+{
+ Token *def, *space;
+ Line *l;
+ char *equals;
+
+ equals = strchr(definition, '=');
+ space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
+ def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
+ if (equals)
+ *equals = ' ';
+ space->next = tokenise(definition);
+ if (equals)
+ *equals = '=';
+
+ l = nasm_malloc(sizeof(Line));
+ l->next = predef;
+ l->first = def;
+ l->finishes = FALSE;
+ predef = l;
+}
+
+void
+pp_pre_undefine(char *definition)
+{
+ Token *def, *space;
+ Line *l;
+
+ space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
+ def = new_Token(space, TOK_PREPROC_ID, "%undef", 0);
+ space->next = tokenise(definition);
+
+ l = nasm_malloc(sizeof(Line));
+ l->next = predef;
+ l->first = def;
+ l->finishes = FALSE;
+ predef = l;
+}
+
+void
+pp_builtin_define(char *definition)
+{
+ Token *def, *space;
+ Line *l;
+ char *equals;
+
+ equals = strchr(definition, '=');
+ space = new_Token(NULL, TOK_WHITESPACE, NULL, 0);
+ def = new_Token(space, TOK_PREPROC_ID, "%define", 0);
+ if (equals)
+ *equals = ' ';
+ space->next = tokenise(definition);
+ if (equals)
+ *equals = '=';
+
+ l = nasm_malloc(sizeof(Line));
+ l->next = builtindef;
+ l->first = def;
+ l->finishes = FALSE;
+ builtindef = l;
+}
+
+void
+pp_extra_stdmac(const char **macros)
+{
+ const char **lp;
+
+ for (lp=macros; *lp; lp++)
+ {
+ char *macro;
+ Token *t;
+ Line *l;
+
+ macro = nasm_strdup(*lp);
+ t = tokenise(macro);
+ nasm_free(macro);
+
+ l = nasm_malloc(sizeof(Line));
+ l->next = stddef;
+ l->first = t;
+ l->finishes = FALSE;
+ stddef = l;
+ }
+}
+
+static void
+make_tok_num(Token * tok, yasm_intnum *val)
+{
+ tok->text = yasm_intnum_get_str(val);
+ tok->type = TOK_NUMBER;
+ yasm_intnum_destroy(val);
+}
+
+Preproc nasmpp = {
+ pp_reset,
+ pp_getline,
+ pp_cleanup
+};
diff --git a/contrib/tools/yasm/modules/preprocs/nasm/nasm-pp.h b/contrib/tools/yasm/modules/preprocs/nasm/nasm-pp.h
new file mode 100644
index 0000000000..a1990206f2
--- /dev/null
+++ b/contrib/tools/yasm/modules/preprocs/nasm/nasm-pp.h
@@ -0,0 +1,22 @@
+/* preproc.h header file for preproc.c
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+#ifndef YASM_NASM_PREPROC_H
+#define YASM_NASM_PREPROC_H
+
+void pp_pre_include (const char *);
+void pp_pre_define (char *);
+void pp_pre_undefine (char *);
+void pp_builtin_define (char *);
+void pp_extra_stdmac (const char **);
+
+extern Preproc nasmpp;
+
+void nasm_preproc_add_dep(char *);
+
+#endif
diff --git a/contrib/tools/yasm/modules/preprocs/nasm/nasm-preproc.c b/contrib/tools/yasm/modules/preprocs/nasm/nasm-preproc.c
new file mode 100644
index 0000000000..566dd8004b
--- /dev/null
+++ b/contrib/tools/yasm/modules/preprocs/nasm/nasm-preproc.c
@@ -0,0 +1,342 @@
+/*
+ * Imported NASM preprocessor - glue code
+ *
+ * Copyright (C) 2002-2007 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 <util.h>
+
+#include <libyasm.h>
+
+#include "nasm.h"
+#include "nasmlib.h"
+#include "nasm-pp.h"
+#include "nasm-eval.h"
+
+typedef struct yasm_preproc_nasm {
+ yasm_preproc_base preproc; /* Base structure */
+
+ FILE *in;
+ char *line;
+ char *file_name;
+ long prior_linnum;
+ int lineinc;
+} yasm_preproc_nasm;
+yasm_symtab *nasm_symtab;
+static yasm_linemap *cur_lm;
+static yasm_errwarns *cur_errwarns;
+int tasm_compatible_mode = 0;
+int tasm_locals;
+const char *tasm_segment;
+
+#include "nasm-version.c"
+
+typedef struct preproc_dep {
+ STAILQ_ENTRY(preproc_dep) link;
+ char *name;
+} preproc_dep;
+
+static STAILQ_HEAD(preproc_dep_head, preproc_dep) *preproc_deps;
+static int done_dep_preproc;
+
+yasm_preproc_module yasm_nasm_LTX_preproc;
+
+static void
+nil_listgen_init(char *p, efunc e)
+{
+}
+
+static void
+nil_listgen_cleanup(void)
+{
+}
+
+static void
+nil_listgen_output(long v, const void *d, unsigned long v2)
+{
+}
+
+static void
+nil_listgen_line(int v, char *p)
+{
+}
+
+static void
+nil_listgen_uplevel(int v)
+{
+}
+
+static void
+nil_listgen_downlevel(int v)
+{
+}
+
+static ListGen nil_list = {
+ nil_listgen_init,
+ nil_listgen_cleanup,
+ nil_listgen_output,
+ nil_listgen_line,
+ nil_listgen_uplevel,
+ nil_listgen_downlevel
+};
+
+
+static void
+nasm_efunc(int severity, const char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ switch (severity & ERR_MASK) {
+ case ERR_WARNING:
+ yasm_warn_set_va(YASM_WARN_PREPROC, fmt, va);
+ break;
+ case ERR_NONFATAL:
+ yasm_error_set_va(YASM_ERROR_GENERAL, fmt, va);
+ break;
+ case ERR_FATAL:
+ yasm_fatal(fmt, va);
+ /*@notreached@*/
+ break;
+ case ERR_PANIC:
+ yasm_internal_error(fmt); /* FIXME */
+ break;
+ case ERR_DEBUG:
+ break;
+ }
+ va_end(va);
+ yasm_errwarn_propagate(cur_errwarns,
+ yasm_linemap_poke(cur_lm, nasm_src_get_fname(),
+ (unsigned long)nasm_src_get_linnum()));
+}
+
+static yasm_preproc *
+nasm_preproc_create(const char *in_filename, yasm_symtab *symtab,
+ yasm_linemap *lm, yasm_errwarns *errwarns)
+{
+ FILE *f;
+ yasm_preproc_nasm *preproc_nasm = yasm_xmalloc(sizeof(yasm_preproc_nasm));
+
+ preproc_nasm->preproc.module = &yasm_nasm_LTX_preproc;
+
+ if (strcmp(in_filename, "-") != 0) {
+ f = fopen(in_filename, "r");
+ if (!f)
+ yasm__fatal_missing_input_file( N_("Could not open input file"), in_filename );
+ }
+ else
+ f = stdin;
+
+ preproc_nasm->in = f;
+ nasm_symtab = symtab;
+ cur_lm = lm;
+ cur_errwarns = errwarns;
+ preproc_deps = NULL;
+ done_dep_preproc = 0;
+ preproc_nasm->line = NULL;
+ preproc_nasm->file_name = NULL;
+ preproc_nasm->prior_linnum = 0;
+ preproc_nasm->lineinc = 0;
+ nasmpp.reset(f, in_filename, 2, nasm_efunc, nasm_evaluate, &nil_list);
+
+ pp_extra_stdmac(nasm_version_mac);
+
+ return (yasm_preproc *)preproc_nasm;
+}
+
+static void
+nasm_preproc_destroy(yasm_preproc *preproc)
+{
+ yasm_preproc_nasm *preproc_nasm = (yasm_preproc_nasm *)preproc;
+ nasmpp.cleanup(0);
+ if (preproc_nasm->line)
+ yasm_xfree(preproc_nasm->line);
+ if (preproc_nasm->file_name)
+ yasm_xfree(preproc_nasm->file_name);
+ yasm_xfree(preproc);
+ if (preproc_deps)
+ yasm_xfree(preproc_deps);
+}
+
+static char *
+nasm_preproc_get_line(yasm_preproc *preproc)
+{
+ yasm_preproc_nasm *preproc_nasm = (yasm_preproc_nasm *)preproc;
+ long linnum;
+ int altline;
+ char *line;
+
+ if (preproc_nasm->line) {
+ char *retval = preproc_nasm->line;
+ preproc_nasm->line = NULL;
+ return retval;
+ }
+
+ line = nasmpp.getline();
+ if (!line)
+ {
+ nasmpp.cleanup(1);
+ return NULL; /* EOF */
+ }
+
+ linnum = preproc_nasm->prior_linnum += preproc_nasm->lineinc;
+ altline = nasm_src_get(&linnum, &preproc_nasm->file_name);
+ if (altline != 0) {
+ preproc_nasm->lineinc =
+ (altline != -1 || preproc_nasm->lineinc != 1);
+ preproc_nasm->line = line;
+ line = yasm_xmalloc(40+strlen(preproc_nasm->file_name));
+ sprintf(line, "%%line %ld+%d %s", linnum,
+ preproc_nasm->lineinc, preproc_nasm->file_name);
+ preproc_nasm->prior_linnum = linnum;
+ }
+
+ return line;
+}
+
+void
+nasm_preproc_add_dep(char *name)
+{
+ preproc_dep *dep;
+
+ /* If not processing dependencies, simply return */
+ if (!preproc_deps)
+ return;
+
+ /* Save in preproc_deps */
+ dep = yasm_xmalloc(sizeof(preproc_dep));
+ dep->name = yasm__xstrdup(name);
+ STAILQ_INSERT_TAIL(preproc_deps, dep, link);
+}
+
+static size_t
+nasm_preproc_get_included_file(yasm_preproc *preproc, /*@out@*/ char *buf,
+ size_t max_size)
+{
+ if (!preproc_deps) {
+ preproc_deps = yasm_xmalloc(sizeof(struct preproc_dep_head));
+ STAILQ_INIT(preproc_deps);
+ }
+
+ for (;;) {
+ char *line;
+
+ /* Pull first dep out of preproc_deps and return it if there is one */
+ if (!STAILQ_EMPTY(preproc_deps)) {
+ char *name;
+ preproc_dep *dep = STAILQ_FIRST(preproc_deps);
+ STAILQ_REMOVE_HEAD(preproc_deps, link);
+ name = dep->name;
+ yasm_xfree(dep);
+ strncpy(buf, name, max_size);
+ buf[max_size-1] = '\0';
+ yasm_xfree(name);
+ return strlen(buf);
+ }
+
+ /* No more preprocessing to do */
+ if (done_dep_preproc) {
+ return 0;
+ }
+
+ /* Preprocess some more, throwing away the result */
+ line = nasmpp.getline();
+ if (line)
+ yasm_xfree(line);
+ else
+ done_dep_preproc = 1;
+ }
+}
+
+static void
+nasm_preproc_add_include_file(yasm_preproc *preproc, const char *filename)
+{
+ pp_pre_include(filename);
+}
+
+static void
+nasm_preproc_predefine_macro(yasm_preproc *preproc, const char *macronameval)
+{
+ char *mnv = yasm__xstrdup(macronameval);
+ pp_pre_define(mnv);
+ yasm_xfree(mnv);
+}
+
+static void
+nasm_preproc_undefine_macro(yasm_preproc *preproc, const char *macroname)
+{
+ char *mn = yasm__xstrdup(macroname);
+ pp_pre_undefine(mn);
+ yasm_xfree(mn);
+}
+
+static void
+nasm_preproc_define_builtin(yasm_preproc *preproc, const char *macronameval)
+{
+ char *mnv = yasm__xstrdup(macronameval);
+ pp_builtin_define(mnv);
+ yasm_xfree(mnv);
+}
+
+static void
+nasm_preproc_add_standard(yasm_preproc *preproc, const char **macros)
+{
+ pp_extra_stdmac(macros);
+}
+
+/* Define preproc structure -- see preproc.h for details */
+yasm_preproc_module yasm_nasm_LTX_preproc = {
+ "Real NASM Preprocessor",
+ "nasm",
+ nasm_preproc_create,
+ nasm_preproc_destroy,
+ nasm_preproc_get_line,
+ nasm_preproc_get_included_file,
+ nasm_preproc_add_include_file,
+ nasm_preproc_predefine_macro,
+ nasm_preproc_undefine_macro,
+ nasm_preproc_define_builtin,
+ nasm_preproc_add_standard
+};
+
+static yasm_preproc *
+tasm_preproc_create(const char *in_filename, yasm_symtab *symtab,
+ yasm_linemap *lm, yasm_errwarns *errwarns)
+{
+ tasm_compatible_mode = 1;
+ return nasm_preproc_create(in_filename, symtab, lm, errwarns);
+}
+
+yasm_preproc_module yasm_tasm_LTX_preproc = {
+ "Real TASM Preprocessor",
+ "tasm",
+ tasm_preproc_create,
+ nasm_preproc_destroy,
+ nasm_preproc_get_line,
+ nasm_preproc_get_included_file,
+ nasm_preproc_add_include_file,
+ nasm_preproc_predefine_macro,
+ nasm_preproc_undefine_macro,
+ nasm_preproc_define_builtin,
+ nasm_preproc_add_standard
+};
diff --git a/contrib/tools/yasm/modules/preprocs/nasm/nasm.h b/contrib/tools/yasm/modules/preprocs/nasm/nasm.h
new file mode 100644
index 0000000000..b3382ffe92
--- /dev/null
+++ b/contrib/tools/yasm/modules/preprocs/nasm/nasm.h
@@ -0,0 +1,283 @@
+/* nasm.h main header file for the Netwide Assembler: inter-module interface
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ *
+ * initial version: 27/iii/95 by Simon Tatham
+ */
+#ifndef YASM_NASM_H
+#define YASM_NASM_H
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef FALSE
+#define FALSE 0 /* comes in handy */
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FILENAME_MAX
+#define FILENAME_MAX 256
+#endif
+
+#ifndef PREFIX_MAX
+#define PREFIX_MAX 10
+#endif
+
+#ifndef POSTFIX_MAX
+#define POSTFIX_MAX 10
+#endif
+
+#define IDLEN_MAX 4096
+
+/*
+ * -------------------------
+ * Error reporting functions
+ * -------------------------
+ */
+
+/*
+ * An error reporting function should look like this.
+ */
+typedef void (*efunc) (int severity, const char *fmt, ...);
+
+/*
+ * These are the error severity codes which get passed as the first
+ * argument to an efunc.
+ */
+
+#define ERR_DEBUG 0x00000008 /* put out debugging message */
+#define ERR_WARNING 0x00000000 /* warn only: no further action */
+#define ERR_NONFATAL 0x00000001 /* terminate assembly after phase */
+#define ERR_FATAL 0x00000002 /* instantly fatal: exit with error */
+#define ERR_PANIC 0x00000003 /* internal error: panic instantly
+ * and dump core for reference */
+#define ERR_MASK 0x0000000F /* mask off the above codes */
+#define ERR_NOFILE 0x00000010 /* don't give source file name/line */
+#define ERR_USAGE 0x00000020 /* print a usage message */
+#define ERR_PASS1 0x00000040 /* only print this error on pass one */
+
+/*
+ * These codes define specific types of suppressible warning.
+ */
+
+#define ERR_WARN_MASK 0x0000FF00 /* the mask for this feature */
+#define ERR_WARN_SHR 8 /* how far to shift right */
+
+#define ERR_WARN_MNP 0x00000100 /* macro-num-parameters warning */
+#define ERR_WARN_MSR 0x00000200 /* macro self-reference */
+#define ERR_WARN_OL 0x00000300 /* orphan label (no colon, and
+ * alone on line) */
+#define ERR_WARN_NOV 0x00000400 /* numeric overflow */
+#define ERR_WARN_GNUELF 0x00000500 /* using GNU ELF extensions */
+#define ERR_WARN_MAX 5 /* the highest numbered one */
+
+/*
+ * -----------------------
+ * Other function typedefs
+ * -----------------------
+ */
+
+/*
+ * List-file generators should look like this:
+ */
+typedef struct {
+ /*
+ * Called to initialise the listing file generator. Before this
+ * is called, the other routines will silently do nothing when
+ * called. The `char *' parameter is the file name to write the
+ * listing to.
+ */
+ void (*init) (char *, efunc);
+
+ /*
+ * Called to clear stuff up and close the listing file.
+ */
+ void (*cleanup) (void);
+
+ /*
+ * Called to output binary data. Parameters are: the offset;
+ * the data; the data type. Data types are similar to the
+ * output-format interface, only OUT_ADDRESS will _always_ be
+ * displayed as if it's relocatable, so ensure that any non-
+ * relocatable address has been converted to OUT_RAWDATA by
+ * then. Note that OUT_RAWDATA+0 is a valid data type, and is a
+ * dummy call used to give the listing generator an offset to
+ * work with when doing things like uplevel(LIST_TIMES) or
+ * uplevel(LIST_INCBIN).
+ */
+ void (*output) (long, const void *, unsigned long);
+
+ /*
+ * Called to send a text line to the listing generator. The
+ * `int' parameter is LIST_READ or LIST_MACRO depending on
+ * whether the line came directly from an input file or is the
+ * result of a multi-line macro expansion.
+ */
+ void (*line) (int, char *);
+
+ /*
+ * Called to change one of the various levelled mechanisms in
+ * the listing generator. LIST_INCLUDE and LIST_MACRO can be
+ * used to increase the nesting level of include files and
+ * macro expansions; LIST_TIMES and LIST_INCBIN switch on the
+ * two binary-output-suppression mechanisms for large-scale
+ * pseudo-instructions.
+ *
+ * LIST_MACRO_NOLIST is synonymous with LIST_MACRO except that
+ * it indicates the beginning of the expansion of a `nolist'
+ * macro, so anything under that level won't be expanded unless
+ * it includes another file.
+ */
+ void (*uplevel) (int);
+
+ /*
+ * Reverse the effects of uplevel.
+ */
+ void (*downlevel) (int);
+} ListGen;
+
+/*
+ * The expression evaluator must be passed a scanner function; a
+ * standard scanner is provided as part of nasmlib.c. The
+ * preprocessor will use a different one. Scanners, and the
+ * token-value structures they return, look like this.
+ *
+ * The return value from the scanner is always a copy of the
+ * `t_type' field in the structure.
+ */
+struct tokenval {
+ int t_type;
+ yasm_intnum *t_integer, *t_inttwo;
+ char *t_charptr;
+};
+typedef int (*scanner) (void *private_data, struct tokenval *tv);
+
+/*
+ * Token types returned by the scanner, in addition to ordinary
+ * ASCII character values, and zero for end-of-string.
+ */
+enum { /* token types, other than chars */
+ TOKEN_INVALID = -1, /* a placeholder value */
+ TOKEN_EOS = 0, /* end of string */
+ TOKEN_EQ = '=', TOKEN_GT = '>', TOKEN_LT = '<', /* aliases */
+ TOKEN_ID = 256, TOKEN_NUM, TOKEN_REG, TOKEN_INSN, /* major token types */
+ TOKEN_ERRNUM, /* numeric constant with error in */
+ TOKEN_HERE, TOKEN_BASE, /* $ and $$ */
+ TOKEN_SPECIAL, /* BYTE, WORD, DWORD, FAR, NEAR, etc */
+ TOKEN_PREFIX, /* A32, O16, LOCK, REPNZ, TIMES, etc */
+ TOKEN_SHL, TOKEN_SHR, /* << and >> */
+ TOKEN_SDIV, TOKEN_SMOD, /* // and %% */
+ TOKEN_GE, TOKEN_LE, TOKEN_NE, /* >=, <= and <> (!= is same as <>) */
+ TOKEN_DBL_AND, TOKEN_DBL_OR, TOKEN_DBL_XOR, /* &&, || and ^^ */
+ TOKEN_SEG, TOKEN_WRT, /* SEG and WRT */
+ TOKEN_FLOAT /* floating-point constant */
+};
+
+/*
+ * The actual expression evaluator function looks like this. When
+ * called, it expects the first token of its expression to already
+ * be in `*tv'; if it is not, set tv->t_type to TOKEN_INVALID and
+ * it will start by calling the scanner.
+ *
+ * `critical' is non-zero if the expression may not contain forward
+ * references. The evaluator will report its own error if this
+ * occurs; if `critical' is 1, the error will be "symbol not
+ * defined before use", whereas if `critical' is 2, the error will
+ * be "symbol undefined".
+ *
+ * If `critical' has bit 8 set (in addition to its main value: 0x101
+ * and 0x102 correspond to 1 and 2) then an extended expression
+ * syntax is recognised, in which relational operators such as =, <
+ * and >= are accepted, as well as low-precedence logical operators
+ * &&, ^^ and ||.
+ */
+#define CRITICAL 0x100
+typedef yasm_expr *(*evalfunc) (scanner sc, void *scprivate, struct tokenval *tv,
+ int critical, efunc error);
+
+/*
+ * Preprocessors ought to look like this:
+ */
+typedef struct {
+ /*
+ * Called at the start of a pass; given a file name, the number
+ * of the pass, an error reporting function, an evaluator
+ * function, and a listing generator to talk to.
+ */
+ void (*reset) (FILE *, const char *, int, efunc, evalfunc, ListGen *);
+
+ /*
+ * Called to fetch a line of preprocessed source. The line
+ * returned has been malloc'ed, and so should be freed after
+ * use.
+ */
+ char *(*getline) (void);
+
+ /*
+ * Called at the end of a pass.
+ */
+ void (*cleanup) (int);
+} Preproc;
+
+/*
+ * ----------------------------------------------------------------
+ * Some lexical properties of the NASM source language, included
+ * here because they are shared between the parser and preprocessor
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * isidstart matches any character that may start an identifier, and isidchar
+ * matches any character that may appear at places other than the start of an
+ * identifier. E.g. a period may only appear at the start of an identifier
+ * (for local labels), whereas a number may appear anywhere *but* at the
+ * start.
+ */
+
+#define isidstart(c) ( isalpha(c) || (c)=='_' || (c)=='.' || (c)=='?' \
+ || (c)=='@' )
+#define isidchar(c) ( isidstart(c) || isdigit(c) || (c)=='$' || (c)=='#' \
+ || (c)=='~' )
+
+/* Ditto for numeric constants. */
+
+#define isnumstart(c) ( isdigit(c) || (c)=='$' )
+#define isnumchar(c) ( isalnum(c) )
+
+/* This returns the numeric value of a given 'digit'. */
+
+#define numvalue(c) ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
+
+/*
+ * Data-type flags that get passed to listing-file routines.
+ */
+enum {
+ LIST_READ, LIST_MACRO, LIST_MACRO_NOLIST, LIST_INCLUDE,
+ LIST_INCBIN, LIST_TIMES
+};
+
+/*
+ * -----
+ * Other
+ * -----
+ */
+
+/*
+ * This is a useful #define which I keep meaning to use more often:
+ * the number of elements of a statically defined array.
+ */
+
+#define elements(x) ( sizeof(x) / sizeof(*(x)) )
+
+extern int tasm_compatible_mode;
+extern int tasm_locals;
+extern const char *tasm_segment;
+const char *tasm_get_segment_register(const char *segment);
+
+#endif
diff --git a/contrib/tools/yasm/modules/preprocs/nasm/nasmlib.c b/contrib/tools/yasm/modules/preprocs/nasm/nasmlib.c
new file mode 100644
index 0000000000..2ced911780
--- /dev/null
+++ b/contrib/tools/yasm/modules/preprocs/nasm/nasmlib.c
@@ -0,0 +1,201 @@
+/* nasmlib.c library routines for the Netwide Assembler
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+#include <util.h>
+#include <libyasm/coretype.h>
+#include <libyasm/intnum.h>
+#include <ctype.h>
+
+#include "nasm.h"
+#include "nasmlib.h"
+/*#include "insns.h"*/ /* For MAX_KEYWORD */
+
+#define lib_isnumchar(c) ( isalnum(c) || (c) == '$')
+#define numvalue(c) ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
+
+yasm_intnum *nasm_readnum (char *str, int *error)
+{
+ char *r = str, *q, *p;
+ long radix;
+ yasm_intnum *intn;
+ char save;
+ int digit;
+ int sign = 0;
+
+ *error = FALSE;
+
+ while (isspace(*r)) r++; /* find start of number */
+
+ /*
+ * If the number came from make_tok_num (as a result of an %assign), it
+ * might have a '-' built into it (rather than in a preceeding token).
+ */
+ if (*r == '-')
+ {
+ r++;
+ sign = 1;
+ }
+
+ q = r;
+
+ while (lib_isnumchar(*q)) q++; /* find end of number */
+
+ /*
+ * If it begins 0x, 0X or $, or ends in H, it's in hex. if it
+ * ends in Q, it's octal. if it ends in B, it's binary.
+ * Otherwise, it's ordinary decimal.
+ */
+ if (*r=='0' && (r[1]=='x' || r[1]=='X'))
+ radix = 16, r += 2;
+ else if (*r=='$')
+ radix = 16, r++;
+ else if (q[-1]=='H' || q[-1]=='h')
+ radix = 16 , q--;
+ else if (q[-1]=='Q' || q[-1]=='q' || q[-1]=='O' || q[-1]=='o')
+ radix = 8 , q--;
+ else if (q[-1]=='B' || q[-1]=='b')
+ radix = 2 , q--;
+ else
+ radix = 10;
+
+ /*
+ * If this number has been found for us by something other than
+ * the ordinary scanners, then it might be malformed by having
+ * nothing between the prefix and the suffix. Check this case
+ * now.
+ */
+ if (r >= q) {
+ *error = TRUE;
+ return yasm_intnum_create_uint(0);
+ }
+
+ /* Check for valid number of that radix */
+ p = r;
+ while (*p && p < q) {
+ if (*p<'0' || (*p>'9' && *p<'A') || (digit = numvalue(*p)) >= radix)
+ {
+ *error = TRUE;
+ return yasm_intnum_create_uint(0);
+ }
+ p++;
+ }
+
+ /* Use intnum to actually do the conversion */
+ save = *q;
+ *q = '\0';
+ switch (radix) {
+ case 2:
+ intn = yasm_intnum_create_bin(r);
+ break;
+ case 8:
+ intn = yasm_intnum_create_oct(r);
+ break;
+ case 10:
+ intn = yasm_intnum_create_dec(r);
+ break;
+ case 16:
+ intn = yasm_intnum_create_hex(r);
+ break;
+ default:
+ *error = TRUE;
+ intn = yasm_intnum_create_uint(0);
+ break;
+ }
+ *q = save;
+
+ if (sign)
+ yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
+ return intn;
+}
+
+yasm_intnum *nasm_readstrnum (char *str, size_t length, int *warn)
+{
+ char save;
+ yasm_intnum *intn;
+
+ *warn = FALSE;
+
+ save = str[length];
+ str[length] = '\0';
+ intn = yasm_intnum_create_charconst_nasm(str);
+ str[length] = save;
+
+ return intn;
+}
+
+static char *file_name = NULL;
+static long line_number = 0;
+
+char *nasm_src_set_fname(char *newname)
+{
+ char *oldname = file_name;
+ file_name = newname;
+ return oldname;
+}
+
+char *nasm_src_get_fname(void)
+{
+ return file_name;
+}
+
+long nasm_src_set_linnum(long newline)
+{
+ long oldline = line_number;
+ line_number = newline;
+ return oldline;
+}
+
+long nasm_src_get_linnum(void)
+{
+ return line_number;
+}
+
+int nasm_src_get(long *xline, char **xname)
+{
+ if (!file_name || !*xname || strcmp(*xname, file_name))
+ {
+ nasm_free(*xname);
+ *xname = file_name ? nasm_strdup(file_name) : NULL;
+ *xline = line_number;
+ return -2;
+ }
+ if (*xline != line_number)
+ {
+ long tmp = line_number - *xline;
+ *xline = line_number;
+ return tmp;
+ }
+ return 0;
+}
+
+void nasm_quote(char **str)
+{
+ size_t ln=strlen(*str);
+ char q=(*str)[0];
+ char *p;
+ if (ln>1 && (*str)[ln-1]==q && (q=='"' || q=='\''))
+ return;
+ q = '"';
+ if (strchr(*str,q))
+ q = '\'';
+ p = nasm_malloc(ln+3);
+ strcpy(p+1, *str);
+ nasm_free(*str);
+ p[ln+1] = p[0] = q;
+ p[ln+2] = 0;
+ *str = p;
+}
+
+char *nasm_strcat(const char *one, const char *two)
+{
+ char *rslt;
+ size_t l1=strlen(one);
+ rslt = nasm_malloc(l1+strlen(two)+1);
+ strcpy(rslt, one);
+ strcpy(rslt+l1, two);
+ return rslt;
+}
diff --git a/contrib/tools/yasm/modules/preprocs/nasm/nasmlib.h b/contrib/tools/yasm/modules/preprocs/nasm/nasmlib.h
new file mode 100644
index 0000000000..c26c0668b5
--- /dev/null
+++ b/contrib/tools/yasm/modules/preprocs/nasm/nasmlib.h
@@ -0,0 +1,60 @@
+/* nasmlib.h header file for nasmlib.c
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+#ifndef YASM_NASMLIB_H
+#define YASM_NASMLIB_H
+
+/*
+ * Wrappers around malloc, realloc and free. nasm_malloc will
+ * fatal-error and die rather than return NULL; nasm_realloc will
+ * do likewise, and will also guarantee to work right on being
+ * passed a NULL pointer; nasm_free will do nothing if it is passed
+ * a NULL pointer.
+ */
+#define nasm_malloc yasm_xmalloc
+#define nasm_realloc yasm_xrealloc
+#ifdef WITH_DMALLOC
+#define nasm_free(p) do { if (p) yasm_xfree(p); } while(0)
+#else
+#define nasm_free(p) yasm_xfree(p)
+#endif
+#define nasm_strdup yasm__xstrdup
+#define nasm_strndup yasm__xstrndup
+#define nasm_stricmp yasm__strcasecmp
+#define nasm_strnicmp yasm__strncasecmp
+
+/*
+ * Convert a string into a number, using NASM number rules. Sets
+ * `*error' to TRUE if an error occurs, and FALSE otherwise.
+ */
+yasm_intnum *nasm_readnum(char *str, int *error);
+
+/*
+ * Convert a character constant into a number. Sets
+ * `*warn' to TRUE if an overflow occurs, and FALSE otherwise.
+ * str points to and length covers the middle of the string,
+ * without the quotes.
+ */
+yasm_intnum *nasm_readstrnum(char *str, size_t length, int *warn);
+
+char *nasm_src_set_fname(char *newname);
+char *nasm_src_get_fname(void);
+long nasm_src_set_linnum(long newline);
+long nasm_src_get_linnum(void);
+/*
+ * src_get may be used if you simply want to know the source file and line.
+ * It is also used if you maintain private status about the source location
+ * It return 0 if the information was the same as the last time you
+ * checked, -1 if the name changed and (new-old) if just the line changed.
+ */
+int nasm_src_get(long *xline, char **xname);
+
+void nasm_quote(char **str);
+char *nasm_strcat(const char *one, const char *two);
+
+#endif
diff --git a/contrib/tools/yasm/modules/preprocs/raw/raw-preproc.c b/contrib/tools/yasm/modules/preprocs/raw/raw-preproc.c
new file mode 100644
index 0000000000..9745b242fe
--- /dev/null
+++ b/contrib/tools/yasm/modules/preprocs/raw/raw-preproc.c
@@ -0,0 +1,169 @@
+/*
+ * Raw preprocessor (preforms NO preprocessing)
+ *
+ * Copyright (C) 2001-2007 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 <util.h>
+
+#include <libyasm.h>
+
+
+#define BSIZE 512
+
+typedef struct yasm_preproc_raw {
+ yasm_preproc_base preproc; /* base structure */
+
+ FILE *in;
+ yasm_linemap *cur_lm;
+ yasm_errwarns *errwarns;
+} yasm_preproc_raw;
+
+yasm_preproc_module yasm_raw_LTX_preproc;
+
+static yasm_preproc *
+raw_preproc_create(const char *in_filename, yasm_symtab *symtab,
+ yasm_linemap *lm, yasm_errwarns *errwarns)
+{
+ FILE *f;
+ yasm_preproc_raw *preproc_raw = yasm_xmalloc(sizeof(yasm_preproc_raw));
+
+ if (strcmp(in_filename, "-") != 0) {
+ f = fopen(in_filename, "r");
+ if (!f)
+ yasm__fatal_missing_input_file( N_("Could not open input file"), in_filename );
+ }
+ else
+ f = stdin;
+
+ preproc_raw->preproc.module = &yasm_raw_LTX_preproc;
+ preproc_raw->in = f;
+ preproc_raw->cur_lm = lm;
+ preproc_raw->errwarns = errwarns;
+
+ return (yasm_preproc *)preproc_raw;
+}
+
+static void
+raw_preproc_destroy(yasm_preproc *preproc)
+{
+ yasm_xfree(preproc);
+}
+
+static char *
+raw_preproc_get_line(yasm_preproc *preproc)
+{
+ yasm_preproc_raw *preproc_raw = (yasm_preproc_raw *)preproc;
+ int bufsize = BSIZE;
+ char *buf = yasm_xmalloc((size_t)bufsize);
+ char *p;
+
+ /* Loop to ensure entire line is read (don't want to limit line length). */
+ p = buf;
+ for (;;) {
+ if (!fgets(p, bufsize-(p-buf), preproc_raw->in)) {
+ if (ferror(preproc_raw->in)) {
+ yasm_error_set(YASM_ERROR_IO,
+ N_("error when reading from file"));
+ yasm_errwarn_propagate(preproc_raw->errwarns,
+ yasm_linemap_get_current(preproc_raw->cur_lm));
+ }
+ break;
+ }
+ p += strlen(p);
+ if (p > buf && p[-1] == '\n')
+ break;
+ if ((p-buf)+1 >= bufsize) {
+ /* Increase size of buffer */
+ char *oldbuf = buf;
+ bufsize *= 2;
+ buf = yasm_xrealloc(buf, (size_t)bufsize);
+ p = buf + (p-oldbuf);
+ }
+ }
+
+ if (p == buf) {
+ /* No data; must be at EOF */
+ yasm_xfree(buf);
+ return NULL;
+ }
+
+ /* Strip the line ending */
+ buf[strcspn(buf, "\r\n")] = '\0';
+
+ return buf;
+}
+
+static size_t
+raw_preproc_get_included_file(yasm_preproc *preproc, char *buf,
+ size_t max_size)
+{
+ /* no included files */
+ return 0;
+}
+
+static void
+raw_preproc_add_include_file(yasm_preproc *preproc, const char *filename)
+{
+ /* no pre-include files */
+}
+
+static void
+raw_preproc_predefine_macro(yasm_preproc *preproc, const char *macronameval)
+{
+ /* no pre-defining macros */
+}
+
+static void
+raw_preproc_undefine_macro(yasm_preproc *preproc, const char *macroname)
+{
+ /* no undefining macros */
+}
+
+static void
+raw_preproc_define_builtin(yasm_preproc *preproc, const char *macronameval)
+{
+ /* no builtin defines */
+}
+
+static void
+raw_preproc_add_standard(yasm_preproc *preproc, const char **macros)
+{
+ /* no standard macros */
+}
+
+
+/* Define preproc structure -- see preproc.h for details */
+yasm_preproc_module yasm_raw_LTX_preproc = {
+ "Disable preprocessing",
+ "raw",
+ raw_preproc_create,
+ raw_preproc_destroy,
+ raw_preproc_get_line,
+ raw_preproc_get_included_file,
+ raw_preproc_add_include_file,
+ raw_preproc_predefine_macro,
+ raw_preproc_undefine_macro,
+ raw_preproc_define_builtin,
+ raw_preproc_add_standard
+};
diff --git a/contrib/tools/yasm/modules/win64-gas.c b/contrib/tools/yasm/modules/win64-gas.c
new file mode 100644
index 0000000000..1ad8be329c
--- /dev/null
+++ b/contrib/tools/yasm/modules/win64-gas.c
@@ -0,0 +1,65 @@
+/* This file auto-generated from standard.mac by genmacro.c - don't edit it */
+
+#include <stddef.h>
+
+static const char *win64_gas_stdmac[] = {
+ "%imacro export 1+.nolist",
+ ".export %1",
+ "%endmacro",
+ "%imacro proc_frame 1+.nolist",
+ "%1:",
+ ".proc_frame %1",
+ "%endmacro",
+ "%imacro endproc_frame 0.nolist",
+ ".endproc_frame",
+ "%endmacro",
+ "%imacro push_reg 1",
+ "pushq %1",
+ ".pushreg %1",
+ "%endmacro",
+ "%imacro rex_push_reg 1",
+ ".byte 0x48",
+ "pushq %1",
+ ".pushreg %1",
+ "%endmacro",
+ "%imacro push_eflags 0",
+ "pushfq",
+ ".allocstack 8",
+ "%endmacro",
+ "%imacro rex_push_eflags 0",
+ ".byte 0x48",
+ "pushfq",
+ ".allocstack 8",
+ "%endmacro",
+ "%imacro alloc_stack 1",
+ "subq $%1, %rsp",
+ ".allocstack %1",
+ "%endmacro",
+ "%imacro save_reg 2",
+ "movq %1, %2(%rsp)",
+ ".savereg %1 %2",
+ "%endmacro",
+ "%imacro save_xmm128 2",
+ "movdqa %1, %2(%rsp)",
+ ".savexmm128 %1, %2",
+ "%endmacro",
+ "%imacro push_frame 0-1.nolist",
+ ".pushframe %1",
+ "%endmacro",
+ "%imacro set_frame 1-2",
+ "%if %0==1",
+ "movq %rsp, %1",
+ "%else",
+ "leaq %2(%rsp), %1",
+ "%endif",
+ ".setframe %1, %2",
+ "%endmacro",
+ "%imacro end_prolog 0.nolist",
+ ".endprolog",
+ "%endmacro",
+ "%imacro end_prologue 0.nolist",
+ ".endprolog",
+ "%endmacro",
+ NULL
+};
+
diff --git a/contrib/tools/yasm/modules/win64-nasm.c b/contrib/tools/yasm/modules/win64-nasm.c
new file mode 100644
index 0000000000..95152c3893
--- /dev/null
+++ b/contrib/tools/yasm/modules/win64-nasm.c
@@ -0,0 +1,65 @@
+/* This file auto-generated from standard.mac by genmacro.c - don't edit it */
+
+#include <stddef.h>
+
+static const char *win64_nasm_stdmac[] = {
+ "%imacro export 1+.nolist",
+ "[export %1]",
+ "%endmacro",
+ "%imacro proc_frame 1+.nolist",
+ "%1:",
+ "[proc_frame %1]",
+ "%endmacro",
+ "%imacro endproc_frame 0.nolist",
+ "[endproc_frame]",
+ "%endmacro",
+ "%imacro push_reg 1",
+ "push %1",
+ "[pushreg %1]",
+ "%endmacro",
+ "%imacro rex_push_reg 1",
+ "db 0x48",
+ "push %1",
+ "[pushreg %1]",
+ "%endmacro",
+ "%imacro push_eflags 0",
+ "pushfq",
+ "[allocstack 8]",
+ "%endmacro",
+ "%imacro rex_push_eflags 0",
+ "db 0x48",
+ "pushfq",
+ "[allocstack 8]",
+ "%endmacro",
+ "%imacro alloc_stack 1",
+ "sub rsp, %1",
+ "[allocstack %1]",
+ "%endmacro",
+ "%imacro save_reg 2",
+ "mov [rsp+%2], %1",
+ "[savereg %1 %2]",
+ "%endmacro",
+ "%imacro save_xmm128 2",
+ "movdqa [rsp+%2], %1",
+ "[savexmm128 %1 %2]",
+ "%endmacro",
+ "%imacro push_frame 0-1.nolist",
+ "[pushframe %1]",
+ "%endmacro",
+ "%imacro set_frame 1-2",
+ "%if %0==1",
+ "mov %1, rsp",
+ "%else",
+ "lea %1, [rsp+%2]",
+ "%endif",
+ "[setframe %1 %2]",
+ "%endmacro",
+ "%imacro end_prolog 0.nolist",
+ "[endprolog]",
+ "%endmacro",
+ "%imacro end_prologue 0.nolist",
+ "[endprolog]",
+ "%endmacro",
+ NULL
+};
+
diff --git a/contrib/tools/yasm/modules/x86cpu.c b/contrib/tools/yasm/modules/x86cpu.c
new file mode 100644
index 0000000000..f1677a4382
--- /dev/null
+++ b/contrib/tools/yasm/modules/x86cpu.c
@@ -0,0 +1,481 @@
+/* ANSI-C code produced by genperf */
+
+#include <util.h>
+
+#include <ctype.h>
+#include <libyasm.h>
+#include <libyasm/phash.h>
+
+#include "modules/arch/x86/x86arch.h"
+
+#define PROC_8086 0
+#define PROC_186 1
+#define PROC_286 2
+#define PROC_386 3
+#define PROC_486 4
+#define PROC_586 5
+#define PROC_686 6
+#define PROC_p2 7
+#define PROC_p3 8
+#define PROC_p4 9
+#define PROC_prescott 10
+#define PROC_conroe 11
+#define PROC_penryn 12
+#define PROC_nehalem 13
+#define PROC_westmere 14
+#define PROC_sandybridge 15
+#define PROC_ivybridge 16
+#define PROC_haswell 17
+#define PROC_broadwell 18
+#define PROC_skylake 19
+
+static void
+x86_cpu_intel(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data)
+{
+ BitVector_Empty(cpu);
+
+ BitVector_Bit_On(cpu, CPU_Priv);
+ if (data >= PROC_286)
+ BitVector_Bit_On(cpu, CPU_Prot);
+ if (data >= PROC_386)
+ BitVector_Bit_On(cpu, CPU_SMM);
+ if (data >= PROC_skylake) {
+ BitVector_Bit_On(cpu, CPU_SHA);
+ }
+ if (data >= PROC_broadwell) {
+ BitVector_Bit_On(cpu, CPU_RDSEED);
+ BitVector_Bit_On(cpu, CPU_ADX);
+ BitVector_Bit_On(cpu, CPU_PRFCHW);
+ }
+ if (data >= PROC_haswell) {
+ BitVector_Bit_On(cpu, CPU_FMA);
+ BitVector_Bit_On(cpu, CPU_AVX2);
+ BitVector_Bit_On(cpu, CPU_BMI1);
+ BitVector_Bit_On(cpu, CPU_BMI2);
+ BitVector_Bit_On(cpu, CPU_INVPCID);
+ BitVector_Bit_On(cpu, CPU_LZCNT);
+ BitVector_Bit_On(cpu, CPU_TSX);
+ BitVector_Bit_On(cpu, CPU_SMAP);
+ }
+ if (data >= PROC_ivybridge) {
+ BitVector_Bit_On(cpu, CPU_F16C);
+ BitVector_Bit_On(cpu, CPU_FSGSBASE);
+ BitVector_Bit_On(cpu, CPU_RDRAND);
+ }
+ if (data >= PROC_sandybridge) {
+ BitVector_Bit_On(cpu, CPU_AVX);
+ BitVector_Bit_On(cpu, CPU_XSAVEOPT);
+ BitVector_Bit_On(cpu, CPU_EPTVPID);
+ BitVector_Bit_On(cpu, CPU_SMX);
+ }
+ if (data >= PROC_westmere) {
+ BitVector_Bit_On(cpu, CPU_AES);
+ BitVector_Bit_On(cpu, CPU_CLMUL);
+ }
+ if (data >= PROC_nehalem) {
+ BitVector_Bit_On(cpu, CPU_SSE42);
+ BitVector_Bit_On(cpu, CPU_XSAVE);
+ }
+ if (data >= PROC_penryn)
+ BitVector_Bit_On(cpu, CPU_SSE41);
+ if (data >= PROC_conroe)
+ BitVector_Bit_On(cpu, CPU_SSSE3);
+ if (data >= PROC_prescott)
+ BitVector_Bit_On(cpu, CPU_SSE3);
+ if (data >= PROC_p4)
+ BitVector_Bit_On(cpu, CPU_SSE2);
+ if (data >= PROC_p3)
+ BitVector_Bit_On(cpu, CPU_SSE);
+ if (data >= PROC_p2)
+ BitVector_Bit_On(cpu, CPU_MMX);
+ if (data >= PROC_486)
+ BitVector_Bit_On(cpu, CPU_FPU);
+ if (data >= PROC_prescott)
+ BitVector_Bit_On(cpu, CPU_EM64T);
+
+ if (data >= PROC_p4)
+ BitVector_Bit_On(cpu, CPU_P4);
+ if (data >= PROC_p3)
+ BitVector_Bit_On(cpu, CPU_P3);
+ if (data >= PROC_686)
+ BitVector_Bit_On(cpu, CPU_686);
+ if (data >= PROC_586)
+ BitVector_Bit_On(cpu, CPU_586);
+ if (data >= PROC_486)
+ BitVector_Bit_On(cpu, CPU_486);
+ if (data >= PROC_386)
+ BitVector_Bit_On(cpu, CPU_386);
+ if (data >= PROC_286)
+ BitVector_Bit_On(cpu, CPU_286);
+ if (data >= PROC_186)
+ BitVector_Bit_On(cpu, CPU_186);
+ BitVector_Bit_On(cpu, CPU_086);
+
+ /* Use Intel long NOPs if 686 or better */
+ if (data >= PROC_686)
+ arch_x86->nop = X86_NOP_INTEL;
+ else
+ arch_x86->nop = X86_NOP_BASIC;
+}
+
+static void
+x86_cpu_ia64(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data)
+{
+ BitVector_Empty(cpu);
+ BitVector_Bit_On(cpu, CPU_Priv);
+ BitVector_Bit_On(cpu, CPU_Prot);
+ BitVector_Bit_On(cpu, CPU_SMM);
+ BitVector_Bit_On(cpu, CPU_SSE2);
+ BitVector_Bit_On(cpu, CPU_SSE);
+ BitVector_Bit_On(cpu, CPU_MMX);
+ BitVector_Bit_On(cpu, CPU_FPU);
+ BitVector_Bit_On(cpu, CPU_IA64);
+ BitVector_Bit_On(cpu, CPU_P4);
+ BitVector_Bit_On(cpu, CPU_P3);
+ BitVector_Bit_On(cpu, CPU_686);
+ BitVector_Bit_On(cpu, CPU_586);
+ BitVector_Bit_On(cpu, CPU_486);
+ BitVector_Bit_On(cpu, CPU_386);
+ BitVector_Bit_On(cpu, CPU_286);
+ BitVector_Bit_On(cpu, CPU_186);
+ BitVector_Bit_On(cpu, CPU_086);
+}
+
+#define PROC_bulldozer 11
+#define PROC_k10 10
+#define PROC_venice 9
+#define PROC_hammer 8
+#define PROC_k7 7
+#define PROC_k6 6
+
+static void
+x86_cpu_amd(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data)
+{
+ BitVector_Empty(cpu);
+
+ BitVector_Bit_On(cpu, CPU_Priv);
+ BitVector_Bit_On(cpu, CPU_Prot);
+ BitVector_Bit_On(cpu, CPU_SMM);
+ BitVector_Bit_On(cpu, CPU_3DNow);
+ if (data >= PROC_bulldozer) {
+ BitVector_Bit_On(cpu, CPU_XOP);
+ BitVector_Bit_On(cpu, CPU_FMA4);
+ }
+ if (data >= PROC_k10)
+ BitVector_Bit_On(cpu, CPU_SSE4a);
+ if (data >= PROC_venice)
+ BitVector_Bit_On(cpu, CPU_SSE3);
+ if (data >= PROC_hammer)
+ BitVector_Bit_On(cpu, CPU_SSE2);
+ if (data >= PROC_k7)
+ BitVector_Bit_On(cpu, CPU_SSE);
+ if (data >= PROC_k6)
+ BitVector_Bit_On(cpu, CPU_MMX);
+ BitVector_Bit_On(cpu, CPU_FPU);
+
+ if (data >= PROC_hammer)
+ BitVector_Bit_On(cpu, CPU_Hammer);
+ if (data >= PROC_k7)
+ BitVector_Bit_On(cpu, CPU_Athlon);
+ if (data >= PROC_k6)
+ BitVector_Bit_On(cpu, CPU_K6);
+ BitVector_Bit_On(cpu, CPU_686);
+ BitVector_Bit_On(cpu, CPU_586);
+ BitVector_Bit_On(cpu, CPU_486);
+ BitVector_Bit_On(cpu, CPU_386);
+ BitVector_Bit_On(cpu, CPU_286);
+ BitVector_Bit_On(cpu, CPU_186);
+ BitVector_Bit_On(cpu, CPU_086);
+
+ /* Use AMD long NOPs if k6 or better */
+ if (data >= PROC_k6)
+ arch_x86->nop = X86_NOP_AMD;
+ else
+ arch_x86->nop = X86_NOP_BASIC;
+}
+
+static void
+x86_cpu_set(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data)
+{
+ BitVector_Bit_On(cpu, data);
+}
+
+static void
+x86_cpu_clear(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data)
+{
+ BitVector_Bit_Off(cpu, data);
+}
+
+static void
+x86_cpu_set_sse4(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data)
+{
+ BitVector_Bit_On(cpu, CPU_SSE41);
+ BitVector_Bit_On(cpu, CPU_SSE42);
+}
+
+static void
+x86_cpu_clear_sse4(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data)
+{
+ BitVector_Bit_Off(cpu, CPU_SSE41);
+ BitVector_Bit_Off(cpu, CPU_SSE42);
+}
+
+static void
+x86_nop(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data)
+{
+ arch_x86->nop = data;
+}
+
+struct cpu_parse_data {
+ const char *name;
+ void (*handler) (wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data);
+ unsigned int data;
+};
+static const struct cpu_parse_data *
+cpu_find(const char *key, size_t len)
+{
+ static const struct cpu_parse_data pd[179] = {
+ {"noeptvpid", x86_cpu_clear, CPU_EPTVPID},
+ {"amd", x86_cpu_set, CPU_AMD},
+ {"sse41", x86_cpu_set, CPU_SSE41},
+ {"pentium", x86_cpu_intel, PROC_586},
+ {"intelnop", x86_nop, X86_NOP_INTEL},
+ {"pclmulqdq", x86_cpu_set, CPU_CLMUL},
+ {"sse42", x86_cpu_set, CPU_SSE42},
+ {"nobmi2", x86_cpu_clear, CPU_BMI2},
+ {"pentium3", x86_cpu_intel, PROC_p3},
+ {"broadwell", x86_cpu_intel, PROC_broadwell},
+ {"aes", x86_cpu_set, CPU_AES},
+ {"eptvpid", x86_cpu_set, CPU_EPTVPID},
+ {"f16c", x86_cpu_set, CPU_F16C},
+ {"amdnop", x86_nop, X86_NOP_AMD},
+ {"pentium-2", x86_cpu_intel, PROC_p2},
+ {"nofpu", x86_cpu_clear, CPU_FPU},
+ {"bmi2", x86_cpu_set, CPU_BMI2},
+ {"katmai", x86_cpu_intel, PROC_p3},
+ {"pentiumiii", x86_cpu_intel, PROC_p3},
+ {"fpu", x86_cpu_set, CPU_FPU},
+ {"noundoc", x86_cpu_clear, CPU_Undoc},
+ {"no3dnow", x86_cpu_clear, CPU_3DNow},
+ {"i486", x86_cpu_intel, PROC_486},
+ {"noundocumented", x86_cpu_clear, CPU_Undoc},
+ {"sse", x86_cpu_set, CPU_SSE},
+ {"nossse3", x86_cpu_clear, CPU_SSSE3},
+ {"noclmul", x86_cpu_clear, CPU_CLMUL},
+ {"tsx", x86_cpu_set, CPU_TSX},
+ {"nocyrix", x86_cpu_clear, CPU_Cyrix},
+ {"nosse", x86_cpu_clear, CPU_SSE},
+ {"nofma", x86_cpu_clear, CPU_FMA},
+ {"phenom", x86_cpu_amd, PROC_k10},
+ {"haswell", x86_cpu_intel, PROC_haswell},
+ {"noprot", x86_cpu_clear, CPU_Prot},
+ {"padlock", x86_cpu_set, CPU_PadLock},
+ {"nopclmulqdq", x86_cpu_clear, CPU_CLMUL},
+ {"nofma4", x86_cpu_clear, CPU_FMA4},
+ {"nofsgsbase", x86_cpu_clear, CPU_FSGSBASE},
+ {"prot", x86_cpu_set, CPU_Prot},
+ {"opteron", x86_cpu_amd, PROC_hammer},
+ {"nof16c", x86_cpu_clear, CPU_F16C},
+ {"i386", x86_cpu_intel, PROC_386},
+ {"ssse3", x86_cpu_set, CPU_SSSE3},
+ {"protected", x86_cpu_set, CPU_Prot},
+ {"bulldozer", x86_cpu_amd, PROC_bulldozer},
+ {"lzcnt", x86_cpu_set, CPU_LZCNT},
+ {"obs", x86_cpu_set, CPU_Obs},
+ {"noprotected", x86_cpu_clear, CPU_Prot},
+ {"athlon-64", x86_cpu_amd, PROC_hammer},
+ {"undocumented", x86_cpu_set, CPU_Undoc},
+ {"i686", x86_cpu_intel, PROC_686},
+ {"k8", x86_cpu_amd, PROC_hammer},
+ {"k10", x86_cpu_amd, PROC_k10},
+ {"noavx2", x86_cpu_clear, CPU_AVX2},
+ {"sandybridge", x86_cpu_intel, PROC_sandybridge},
+ {"nommx", x86_cpu_clear, CPU_MMX},
+ {"priv", x86_cpu_set, CPU_Priv},
+ {"sse4.1", x86_cpu_set, CPU_SSE41},
+ {"8086", x86_cpu_intel, PROC_8086},
+ {"noprivileged", x86_cpu_clear, CPU_Priv},
+ {"i586", x86_cpu_intel, PROC_586},
+ {"ia-64", x86_cpu_ia64, 0},
+ {"nosse2", x86_cpu_clear, CPU_SSE2},
+ {"obsolete", x86_cpu_set, CPU_Obs},
+ {"186", x86_cpu_intel, PROC_186},
+ {"sse4a", x86_cpu_set, CPU_SSE4a},
+ {"ia64", x86_cpu_ia64, 0},
+ {"core2", x86_cpu_intel, PROC_conroe},
+ {"noxsaveopt", x86_cpu_clear, CPU_XSAVEOPT},
+ {"sse4.2", x86_cpu_set, CPU_SSE42},
+ {"prescott", x86_cpu_intel, PROC_prescott},
+ {"avx2", x86_cpu_set, CPU_AVX2},
+ {"80186", x86_cpu_intel, PROC_186},
+ {"nopriv", x86_cpu_clear, CPU_Priv},
+ {"nosse4.1", x86_cpu_clear, CPU_SSE41},
+ {"nordseed", x86_cpu_clear, CPU_RDSEED},
+ {"pentium2", x86_cpu_intel, PROC_p2},
+ {"conroe", x86_cpu_intel, PROC_conroe},
+ {"nosse42", x86_cpu_clear, CPU_SSE42},
+ {"pentium-ii", x86_cpu_intel, PROC_p2},
+ {"svm", x86_cpu_set, CPU_SVM},
+ {"386", x86_cpu_intel, PROC_386},
+ {"em64t", x86_cpu_set, CPU_EM64T},
+ {"p2", x86_cpu_intel, PROC_p2},
+ {"athlon64", x86_cpu_amd, PROC_hammer},
+ {"3dnow", x86_cpu_set, CPU_3DNow},
+ {"nosse4", x86_cpu_clear_sse4, 0},
+ {"nosmx", x86_cpu_clear, CPU_SMX},
+ {"williamette", x86_cpu_intel, PROC_p4},
+ {"family10h", x86_cpu_amd, PROC_k10},
+ {"athlon", x86_cpu_amd, PROC_k7},
+ {"586", x86_cpu_intel, PROC_586},
+ {"686", x86_cpu_intel, PROC_686},
+ {"smm", x86_cpu_set, CPU_SMM},
+ {"xsave", x86_cpu_set, CPU_XSAVE},
+ {"privileged", x86_cpu_set, CPU_Priv},
+ {"p6", x86_cpu_intel, PROC_686},
+ {"smap", x86_cpu_set, CPU_SMAP},
+ {"avx", x86_cpu_set, CPU_AVX},
+ {"pentium-4", x86_cpu_intel, PROC_p4},
+ {"pentiumii", x86_cpu_intel, PROC_p2},
+ {"sha", x86_cpu_set, CPU_SHA},
+ {"fma4", x86_cpu_set, CPU_FMA4},
+ {"pentium-iii", x86_cpu_intel, PROC_p3},
+ {"skylake", x86_cpu_intel, PROC_skylake},
+ {"nosse4.2", x86_cpu_clear, CPU_SSE42},
+ {"pentium4", x86_cpu_intel, PROC_p4},
+ {"noaes", x86_cpu_clear, CPU_AES},
+ {"i186", x86_cpu_intel, PROC_186},
+ {"rdrand", x86_cpu_set, CPU_RDRAND},
+ {"80286", x86_cpu_intel, PROC_286},
+ {"pentiumiv", x86_cpu_intel, PROC_p4},
+ {"xop", x86_cpu_set, CPU_XOP},
+ {"mmx", x86_cpu_set, CPU_MMX},
+ {"486", x86_cpu_intel, PROC_486},
+ {"clawhammer", x86_cpu_amd, PROC_hammer},
+ {"rdseed", x86_cpu_set, CPU_RDSEED},
+ {"i286", x86_cpu_intel, PROC_286},
+ {"prfchw", x86_cpu_set, CPU_PRFCHW},
+ {"nosse3", x86_cpu_clear, CPU_SSE3},
+ {"sse4", x86_cpu_set_sse4, 0},
+ {"pentium-iv", x86_cpu_intel, PROC_p4},
+ {"p4", x86_cpu_intel, PROC_p4},
+ {"nordrand", x86_cpu_clear, CPU_RDRAND},
+ {"ppro", x86_cpu_intel, PROC_686},
+ {"p5", x86_cpu_intel, PROC_586},
+ {"notbm", x86_cpu_clear, CPU_TBM},
+ {"cyrix", x86_cpu_set, CPU_Cyrix},
+ {"80386", x86_cpu_intel, PROC_386},
+ {"k6", x86_cpu_amd, PROC_k6},
+ {"basicnop", x86_nop, X86_NOP_BASIC},
+ {"nomovbe", x86_cpu_clear, CPU_MOVBE},
+ {"noadx", x86_cpu_clear, CPU_ADX},
+ {"nosmap", x86_cpu_clear, CPU_SMAP},
+ {"nosmm", x86_cpu_clear, CPU_SMM},
+ {"xsaveopt", x86_cpu_set, CPU_XSAVEOPT},
+ {"pentium-3", x86_cpu_intel, PROC_p3},
+ {"nosvm", x86_cpu_clear, CPU_SVM},
+ {"nosha", x86_cpu_clear, CPU_SHA},
+ {"invpcid", x86_cpu_set, CPU_INVPCID},
+ {"nobmi1", x86_cpu_clear, CPU_BMI1},
+ {"ivybridge", x86_cpu_intel, PROC_ivybridge},
+ {"p3", x86_cpu_intel, PROC_p3},
+ {"pentiumpro", x86_cpu_intel, PROC_686},
+ {"penryn", x86_cpu_intel, PROC_penryn},
+ {"80486", x86_cpu_intel, PROC_486},
+ {"noxop", x86_cpu_clear, CPU_XOP},
+ {"undoc", x86_cpu_set, CPU_Undoc},
+ {"noobsolete", x86_cpu_clear, CPU_Obs},
+ {"noavx", x86_cpu_clear, CPU_AVX},
+ {"nolzcnt", x86_cpu_clear, CPU_LZCNT},
+ {"noprfchw", x86_cpu_clear, CPU_PRFCHW},
+ {"notsx", x86_cpu_clear, CPU_TSX},
+ {"bmi1", x86_cpu_set, CPU_BMI1},
+ {"itanium", x86_cpu_ia64, 0},
+ {"venice", x86_cpu_amd, PROC_venice},
+ {"noxsave", x86_cpu_clear, CPU_XSAVE},
+ {"noamd", x86_cpu_clear, CPU_AMD},
+ {"noobs", x86_cpu_clear, CPU_Obs},
+ {"noem64t", x86_cpu_clear, CPU_EM64T},
+ {"hammer", x86_cpu_amd, PROC_hammer},
+ {"nehalem", x86_cpu_intel, PROC_nehalem},
+ {"sse3", x86_cpu_set, CPU_SSE3},
+ {"sse2", x86_cpu_set, CPU_SSE2},
+ {"clmul", x86_cpu_set, CPU_CLMUL},
+ {"smx", x86_cpu_set, CPU_SMX},
+ {"nosse4a", x86_cpu_clear, CPU_SSE4a},
+ {"tbm", x86_cpu_set, CPU_TBM},
+ {"fma", x86_cpu_set, CPU_FMA},
+ {"nopadlock", x86_cpu_clear, CPU_PadLock},
+ {"nosse41", x86_cpu_clear, CPU_SSE41},
+ {"adx", x86_cpu_set, CPU_ADX},
+ {"westmere", x86_cpu_intel, PROC_westmere},
+ {"k7", x86_cpu_amd, PROC_k7},
+ {"noinvpcid", x86_cpu_clear, CPU_INVPCID},
+ {"fsgsbase", x86_cpu_set, CPU_FSGSBASE},
+ {"corei7", x86_cpu_intel, PROC_nehalem},
+ {"movbe", x86_cpu_set, CPU_MOVBE},
+ {"286", x86_cpu_intel, PROC_286}
+ };
+ static const unsigned char tab[] = {
+ 183,125,113,40,125,0,0,0,183,146,116,85,0,113,113,183,
+ 113,131,0,82,88,0,131,125,85,0,113,0,0,7,0,40,
+ 22,7,0,0,125,220,87,183,184,7,0,0,0,113,11,0,
+ 84,0,0,0,0,131,0,113,0,120,0,113,0,0,51,11,
+ 55,190,0,0,183,61,120,131,85,135,0,0,0,0,0,82,
+ 74,183,0,87,220,0,235,0,220,229,0,0,220,243,124,145,
+ 0,220,131,0,221,0,0,0,237,0,135,125,124,168,0,69,
+ 0,124,22,0,131,131,163,113,184,214,155,133,55,0,0,0,
+ };
+
+ const struct cpu_parse_data *ret;
+ unsigned long rsl, val = phash_lookup(key, len, 0xdaa66d2bUL);
+ rsl = ((val>>25)^tab[val&0x7f]);
+ if (rsl >= 179) return NULL;
+ ret = &pd[rsl];
+ if (strcmp(key, ret->name) != 0) return NULL;
+ return ret;
+}
+
+
+
+void
+yasm_x86__parse_cpu(yasm_arch_x86 *arch_x86, const char *cpuid,
+ size_t cpuid_len)
+{
+ /*@null@*/ const struct cpu_parse_data *pdata;
+ wordptr new_cpu;
+ size_t i;
+ static char lcaseid[16];
+
+ if (cpuid_len > 15)
+ return;
+ for (i=0; i<cpuid_len; i++)
+ lcaseid[i] = tolower(cpuid[i]);
+ lcaseid[cpuid_len] = '\0';
+
+ pdata = cpu_find(lcaseid, cpuid_len);
+ if (!pdata) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("unrecognized CPU identifier `%s'"), cpuid);
+ return;
+ }
+
+ new_cpu = BitVector_Clone(arch_x86->cpu_enables[arch_x86->active_cpu]);
+ pdata->handler(new_cpu, arch_x86, pdata->data);
+
+ /* try to find an existing match in the CPU table first */
+ for (i=0; i<arch_x86->cpu_enables_size; i++) {
+ if (BitVector_equal(arch_x86->cpu_enables[i], new_cpu)) {
+ arch_x86->active_cpu = i;
+ BitVector_Destroy(new_cpu);
+ return;
+ }
+ }
+
+ /* not found, need to add a new entry */
+ arch_x86->active_cpu = arch_x86->cpu_enables_size++;
+ arch_x86->cpu_enables =
+ yasm_xrealloc(arch_x86->cpu_enables,
+ arch_x86->cpu_enables_size*sizeof(wordptr));
+ arch_x86->cpu_enables[arch_x86->active_cpu] = new_cpu;
+}
+
diff --git a/contrib/tools/yasm/modules/x86insn_gas.c b/contrib/tools/yasm/modules/x86insn_gas.c
new file mode 100644
index 0000000000..e0773185ba
--- /dev/null
+++ b/contrib/tools/yasm/modules/x86insn_gas.c
@@ -0,0 +1,2154 @@
+/* ANSI-C code produced by genperf */
+struct insnprefix_parse_data;
+static const struct insnprefix_parse_data *
+insnprefix_gas_find(const char *key, size_t len)
+{
+ static const struct insnprefix_parse_data pd[2070] = {
+ {"vpunpckhqdq", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x6D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"psrad", pshift_insn, 4, SUF_Z, 0xE2, 0x72, 0x04, 0, CPU_MMX, 0, 0},
+ {"rsldt", cyrixsmm_insn, 1, SUF_Z, 0x7B, 0, 0, 0, CPU_486, CPU_Cyrix, CPU_SMM},
+ {"ldmxcsr", ldstmxcsr_insn, 1, SUF_Z, 0x02, 0, 0, 0, CPU_SSE, 0, 0},
+ {"idivl", div_insn, 8, SUF_L, 0x07, 0, 0, 0, CPU_386, 0, 0},
+ {"vhaddpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x7C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"aqword", NULL, X86_ADDRSIZE>>8, 0x40, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"vcmpeq_uqsd", ssecmp_64_insn, 4, SUF_Z, 0x08, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"subl", arith_insn, 22, SUF_L, 0x28, 0x05, 0, 0, CPU_386, 0, 0},
+ {"vcmple_oqsd", ssecmp_64_insn, 4, SUF_Z, 0x12, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"shrdw", shlrd_insn, 9, SUF_W, 0xAC, 0, 0, 0, CPU_386, 0, 0},
+ {"xchgb", xchg_insn, 16, SUF_B, 0, 0, 0, 0, 0, 0, 0},
+ {"dec", incdec_insn, 6, SUF_Z, 0x48, 0x01, 0, 0, 0, 0, 0},
+ {"finit", threebyte_insn, 1, SUF_Z, 0x9B, 0xDB, 0xE3, 0, CPU_FPU, 0, 0},
+ {"iret", onebyte_insn, 1, SUF_Z, 0xCF, 0, 0, 0, 0, 0, 0},
+ {"mul", f6_insn, 4, SUF_Z, 0x04, 0, 0, 0, 0, 0, 0},
+ {"vcvtdq2pd", avx_cvt_xmm64_insn, 3, SUF_Z, 0xF3, 0xE6, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lzcntl", cnt_insn, 3, SUF_L, 0xBD, 0, 0, 0, CPU_LZCNT, 0, 0},
+ {"vucomiss", avx_xmm_xmm32_insn, 2, SUF_Z, 0x00, 0x2E, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vblendpd", sse4imm_256_insn, 4, SUF_Z, 0x0D, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sscal", onebyte_insn, 1, SUF_Z, 0xAF, 0x20, 0, 0, CPU_386, 0, 0},
+ {"vcmpnlt_uqpd", ssecmp_128_insn, 3, SUF_Z, 0x15, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setpob", setcc_insn, 1, SUF_B, 0x0B, 0, 0, 0, CPU_386, 0, 0},
+ {"andn", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_Z, 0x00, 0x38, 0xF2, ONLY_AVX, CPU_BMI1, 0, 0},
+ {"scasq", onebyte_insn, 1, SUF_Z, 0xAF, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"xorw", arith_insn, 22, SUF_W, 0x30, 0x06, 0, 0, 0, 0, 0},
+ {"vprotw", vprot_insn, 3, SUF_Z, 0x01, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vfmsub231sd", vfma_sd_insn, 2, SUF_Z, 0xBB, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpmovmskbq", pmovmskb_insn, 6, SUF_Q, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"data32", NULL, X86_OPERSIZE>>8, 0x20, 0, 0, 0, 0, 0, 0, 0},
+ {"movntdq", movnt_insn, 2, SUF_Z, 0x66, 0xE7, 0, 0, CPU_SSE2, 0, 0},
+ {"vandps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x54, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fidivrs", fiarith_insn, 2, SUF_S, 0x07, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"vcmpfalse_osss", ssecmp_32_insn, 4, SUF_Z, 0x1B, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpneqpd", ssecmp_128_insn, 3, SUF_Z, 0x04, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpneq_oqsd", ssecmp_64_insn, 4, SUF_Z, 0x0C, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomnequb", vpcom_insn, 1, SUF_Z, 0xEC, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"vfnmadd213sd", vfma_sd_insn, 2, SUF_Z, 0xAD, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"cmplesd", ssecmp_64_insn, 4, SUF_Z, 0x02, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"vpshaq", amd_vpshift_insn, 2, SUF_Z, 0x9B, 0, 0, 0, CPU_XOP, 0, 0},
+ {"iretw", onebyte_insn, 1, SUF_Z, 0xCF, 0x10, 0, 0, 0, 0, 0},
+ {"vpcomltub", vpcom_insn, 1, SUF_Z, 0xEC, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"vmovupd", movau_insn, 6, SUF_Z, 0x66, 0x10, 0x01, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fabs", twobyte_insn, 1, SUF_Z, 0xD9, 0xE1, 0, 0, CPU_FPU, 0, 0},
+ {"lgdtq", twobytemem_insn, 1, SUF_Q, 0x02, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"vcmpgeps", ssecmp_128_insn, 3, SUF_Z, 0x0D, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"popfw", onebyte_insn, 1, SUF_Z, 0x9D, 0x10, 0x40, 0, 0, 0, 0},
+ {"vpmovsxwd", sse4m64_insn, 4, SUF_Z, 0x23, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpsravd", vpshiftv_vexw0_avx2_insn, 2, SUF_Z, 0x46, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vpmadcswd", vpma_insn, 1, SUF_Z, 0xB6, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpmovsxbq", sse4m16_insn, 4, SUF_Z, 0x22, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomleud", vpcom_insn, 1, SUF_Z, 0xEE, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"phsubw", ssse3_insn, 5, SUF_Z, 0x05, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"call", call_insn, 30, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"cmovpe", cmovcc_insn, 3, SUF_Z, 0x0A, 0, 0, 0, CPU_686, 0, 0},
+ {"vpcomneqq", vpcom_insn, 1, SUF_Z, 0xCF, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"fcomp", fcom_insn, 6, SUF_Z, 0xD8, 0x03, 0, 0, CPU_FPU, 0, 0},
+ {"vdpps", sse4imm_256_insn, 4, SUF_Z, 0x40, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmovsxdq", sse4m64_insn, 4, SUF_Z, 0x25, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"rcll", shift_insn, 16, SUF_L, 0x02, 0, 0, 0, CPU_386, 0, 0},
+ {"xorps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x57, 0, 0, CPU_SSE, 0, 0},
+ {"cmovaq", cmovcc_insn, 3, SUF_Q, 0x07, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"int3", onebyte_insn, 1, SUF_Z, 0xCC, 0, 0, 0, 0, 0, 0},
+ {"fsubrp", farithp_insn, 3, SUF_Z, 0xE8, 0, 0, 0, CPU_FPU, 0, 0},
+ {"pdepq", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_Q, 0xF2, 0x38, 0xF5, ONLY_64|ONLY_AVX, CPU_BMI2, 0, 0},
+ {"vfmadd132pd", vfma_pd_insn, 2, SUF_Z, 0x98, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"bts", bittest_insn, 6, SUF_Z, 0xAB, 0x05, 0, 0, CPU_386, 0, 0},
+ {"jnge", jcc_insn, 9, SUF_Z, 0x0C, 0, 0, 0, 0, 0, 0},
+ {"movbe", movbe_insn, 6, SUF_Z, 0, 0, 0, 0, CPU_MOVBE, 0, 0},
+ {"rsdc", rsdc_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_486, CPU_Cyrix, CPU_SMM},
+ {"psubusb", mmxsse2_insn, 2, SUF_Z, 0xD8, 0, 0, 0, CPU_MMX, 0, 0},
+ {"pmaxsb", sse4_insn, 2, SUF_Z, 0x3C, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"ffree", ffree_insn, 1, SUF_Z, 0xDD, 0, 0, 0, CPU_FPU, 0, 0},
+ {"fsubrl", farith_insn, 7, SUF_L, 0xE0, 0xE8, 0x05, 0, CPU_FPU, 0, 0},
+ {"pminsb", sse4_insn, 2, SUF_Z, 0x38, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vcmpltsd", ssecmp_64_insn, 4, SUF_Z, 0x01, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtsd2ss", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5A, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"verr", prot286_insn, 1, SUF_Z, 0x04, 0x00, 0, 0, CPU_286, CPU_Prot, 0},
+ {"pcmpgtb", mmxsse2_insn, 2, SUF_Z, 0x64, 0, 0, 0, CPU_MMX, 0, 0},
+ {"lcall", ljmpcall_insn, 7, SUF_Z, 0x03, 0x9A, 0, 0, 0, 0, 0},
+ {"vcmpngt_uqss", ssecmp_32_insn, 4, SUF_Z, 0x1A, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmulhuw", mmxsse2_insn, 2, SUF_Z, 0xE4, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vcmpeq_ossd", ssecmp_64_insn, 4, SUF_Z, 0x10, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmaxsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5F, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpclmulhqlqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x01, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpunord_sps", ssecmp_128_insn, 3, SUF_Z, 0x13, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"data64", NULL, X86_OPERSIZE>>8, 0x40, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"fimul", fiarith_insn, 2, SUF_Z, 0x01, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"tzcntq", cnt_insn, 3, SUF_Q, 0xBC, 0, 0, ONLY_64, CPU_BMI1, 0, 0},
+ {"cmovgel", cmovcc_insn, 3, SUF_L, 0x0D, 0, 0, 0, CPU_686, 0, 0},
+ {"cmovbw", cmovcc_insn, 3, SUF_W, 0x02, 0, 0, 0, CPU_686, 0, 0},
+ {"vcmpordss", ssecmp_32_insn, 4, SUF_Z, 0x07, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"blendpd", sse4imm_insn, 2, SUF_Z, 0x0D, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"seta", setcc_insn, 1, SUF_Z, 0x07, 0, 0, 0, CPU_386, 0, 0},
+ {"vfnmaddss", fma_128_m32_insn, 3, SUF_Z, 0x7A, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"blsfilll", xop_gpr_reg_rm_09_insn, 2, SUF_L, 0x01, 0x02, 0, 0, CPU_386, CPU_TBM, 0},
+ {"incw", incdec_insn, 6, SUF_W, 0x40, 0x00, 0, 0, 0, 0, 0},
+ {"blsmsk", vex_gpr_ndd_rm_0F38_regext_insn, 2, SUF_Z, 0x00, 0xF3, 0x02, ONLY_AVX, CPU_BMI1, 0, 0},
+ {"testq", test_insn, 20, SUF_Q, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"pushfq", onebyte_insn, 1, SUF_Z, 0x9C, 0x40, 0x40, ONLY_64, 0, 0, 0},
+ {"jbe", jcc_insn, 9, SUF_Z, 0x06, 0, 0, 0, 0, 0, 0},
+ {"vpcomuw", vpcom_imm_insn, 1, SUF_Z, 0xED, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vcomisd", avx_xmm_xmm64_insn, 2, SUF_Z, 0x66, 0x2F, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpneq_osps", ssecmp_128_insn, 3, SUF_Z, 0x1C, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpneq_usps", ssecmp_128_insn, 3, SUF_Z, 0x14, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pswapd", now3d_insn, 1, SUF_Z, 0xBB, 0, 0, 0, CPU_3DNow, CPU_Athlon, 0},
+ {"blciq", xop_gpr_reg_rm_09_insn, 2, SUF_Q, 0x02, 0x06, 0, ONLY_64, CPU_TBM, 0, 0},
+ {"skinit", skinit_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_SVM, 0, 0},
+ {"sqrtsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x51, 0, 0, CPU_SSE2, 0, 0},
+ {"frndint", twobyte_insn, 1, SUF_Z, 0xD9, 0xFC, 0, 0, CPU_FPU, 0, 0},
+ {"vpxor", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xEF, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movmskpdl", movmsk_insn, 4, SUF_L, 0x66, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"cmpltss", ssecmp_32_insn, 4, SUF_Z, 0x01, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"loop", loop_insn, 8, SUF_Z, 0x02, 0, 0, 0, 0, 0, 0},
+ {"vphsubwd", vphaddsub_insn, 1, SUF_Z, 0xE2, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpcomltuq", vpcom_insn, 1, SUF_Z, 0xEF, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"psubq", mmxsse2_insn, 2, SUF_Z, 0xFB, 0, 0, 0, CPU_MMX, 0, 0},
+ {"cmovcq", cmovcc_insn, 3, SUF_Q, 0x02, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"vpsrlw", vpshift_insn, 8, SUF_Z, 0xD1, 0x71, 0x02, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setleb", setcc_insn, 1, SUF_B, 0x0E, 0, 0, 0, CPU_386, 0, 0},
+ {"vcmpnltps", ssecmp_128_insn, 3, SUF_Z, 0x05, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cvtps2pi", cvt_mm_xmm64_insn, 2, SUF_Z, 0x2D, 0, 0, 0, CPU_SSE, 0, 0},
+ {"lgdtw", twobytemem_insn, 1, SUF_W, 0x02, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"vpcomq", vpcom_imm_insn, 1, SUF_Z, 0xCF, 0, 0, 0, CPU_XOP, 0, 0},
+ {"jna", jcc_insn, 9, SUF_Z, 0x06, 0, 0, 0, 0, 0, 0},
+ {"vpsubusb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xD8, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpgt_oqss", ssecmp_32_insn, 4, SUF_Z, 0x1E, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmsub231ps", vfma_ps_insn, 2, SUF_Z, 0xBA, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vfnmsubpd", fma_128_256_insn, 4, SUF_Z, 0x7D, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"vmsave", svm_rax_insn, 2, SUF_Z, 0xDB, 0, 0, 0, CPU_SVM, 0, 0},
+ {"aesdec", aes_insn, 2, SUF_Z, 0x38, 0xDE, 0, 0, CPU_AVX, 0, 0},
+ {"vcvtpd2ps", avx_cvt_xmm128_insn, 2, SUF_Z, 0x66, 0x5A, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vphaddwq", vphaddsub_insn, 1, SUF_Z, 0xC7, 0, 0, 0, CPU_XOP, 0, 0},
+ {"cmovpo", cmovcc_insn, 3, SUF_Z, 0x0B, 0, 0, 0, CPU_686, 0, 0},
+ {"pmulld", sse4_insn, 2, SUF_Z, 0x40, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"cbtw", onebyte_insn, 1, SUF_Z, 0x98, 0x10, 0, 0, 0, 0, 0},
+ {"loadall286", twobyte_insn, 1, SUF_Z, 0x0F, 0x05, 0, 0, CPU_286, CPU_Undoc, 0},
+ {"rexy", NULL, X86_REX>>8, 0x42, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"lgsw", lfgss_insn, 3, SUF_W, 0xB5, 0, 0, 0, CPU_386, 0, 0},
+ {"vcmpngeps", ssecmp_128_insn, 3, SUF_Z, 0x09, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"btc", bittest_insn, 6, SUF_Z, 0xBB, 0x07, 0, 0, CPU_386, 0, 0},
+ {"vcmpeq_uqss", ssecmp_32_insn, 4, SUF_Z, 0x08, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"invept", eptvpid_insn, 2, SUF_Z, 0x00, 0, 0, 0, CPU_386, CPU_EPTVPID, 0},
+ {"vfmaddsub231pd", vfma_pd_insn, 2, SUF_Z, 0xB6, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"strl", str_insn, 4, SUF_L, 0, 0, 0, 0, CPU_386, CPU_Prot, 0},
+ {"shlxl", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_L, 0x66, 0x38, 0xF7, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"loopq", loopq_insn, 4, SUF_Z, 0x02, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"pmvzb", cyrixmmx_insn, 1, SUF_Z, 0x58, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"vshufpd", xmm_xmm128_imm_256_insn, 3, SUF_Z, 0x66, 0xC6, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpsubq", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xFB, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fnstsw", fnstsw_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"incl", incdec_insn, 6, SUF_L, 0x40, 0x00, 0, 0, CPU_386, 0, 0},
+ {"fnop", twobyte_insn, 1, SUF_Z, 0xD9, 0xD0, 0, 0, CPU_FPU, 0, 0},
+ {"punpckhdq", mmxsse2_insn, 2, SUF_Z, 0x6A, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vphadduwd", vphaddsub_insn, 1, SUF_Z, 0xD6, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vmovaps", movau_insn, 6, SUF_Z, 0x00, 0x28, 0x01, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpsllq", vpshift_insn, 8, SUF_Z, 0xF3, 0x73, 0x06, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pfmul", now3d_insn, 1, SUF_Z, 0xB4, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"vcmpfalsess", ssecmp_32_insn, 4, SUF_Z, 0x0B, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmptrue_ussd", ssecmp_64_insn, 4, SUF_Z, 0x1F, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmple_oqps", ssecmp_128_insn, 3, SUF_Z, 0x12, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpinsrwq", pinsrw_insn, 9, SUF_Q, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpminub", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xDA, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"blcfillq", xop_gpr_reg_rm_09_insn, 2, SUF_Q, 0x01, 0x01, 0, ONLY_64, CPU_TBM, 0, 0},
+ {"incq", incdec_insn, 6, SUF_Q, 0x40, 0x00, 0, ONLY_64, 0, 0, 0},
+ {"pdep", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_Z, 0xF2, 0x38, 0xF5, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"cmovnc", cmovcc_insn, 3, SUF_Z, 0x03, 0, 0, 0, CPU_686, 0, 0},
+ {"movntil", movnti_insn, 2, SUF_L, 0, 0, 0, 0, CPU_P4, 0, 0},
+ {"cmoveq", cmovcc_insn, 3, SUF_Q, 0x04, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"pfrcpit2", now3d_insn, 1, SUF_Z, 0xB6, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"cmovaew", cmovcc_insn, 3, SUF_W, 0x03, 0, 0, 0, CPU_686, 0, 0},
+ {"vinserti128", vinsertif128_insn, 1, SUF_Z, 0x38, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"movmskpdq", movmsk_insn, 4, SUF_Q, 0x66, 0, 0, ONLY_64, CPU_SSE2, 0, 0},
+ {"vpmaxud", ssse3_insn, 5, SUF_Z, 0x3F, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"xaddw", cmpxchgxadd_insn, 4, SUF_W, 0xC0, 0, 0, 0, CPU_486, 0, 0},
+ {"psubb", mmxsse2_insn, 2, SUF_Z, 0xF8, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vminpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x5D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"mulpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x59, 0, 0, CPU_SSE2, 0, 0},
+ {"fisttpl", fildstp_insn, 4, SUF_L, 0x01, 0x00, 0x01, 0, CPU_SSE3, 0, 0},
+ {"vcmpordps", ssecmp_128_insn, 3, SUF_Z, 0x07, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lgs", lfgss_insn, 3, SUF_Z, 0xB5, 0, 0, 0, CPU_386, 0, 0},
+ {"lzcntq", cnt_insn, 3, SUF_Q, 0xBD, 0, 0, ONLY_64, CPU_LZCNT, 0, 0},
+ {"frstor", onebytemem_insn, 1, SUF_Z, 0x04, 0xDD, 0, 0, CPU_FPU, 0, 0},
+ {"vcmpge_oqpd", ssecmp_128_insn, 3, SUF_Z, 0x1D, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setnbb", setcc_insn, 1, SUF_B, 0x03, 0, 0, 0, CPU_386, 0, 0},
+ {"fcmovnbe", fcmovcc_insn, 1, SUF_Z, 0xDB, 0xD0, 0, 0, CPU_686, CPU_FPU, 0},
+ {"pminub", mmxsse2_insn, 2, SUF_Z, 0xDA, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vcvttpd2dqx", avx_cvt_xmm128_x_insn, 1, SUF_Z, 0x66, 0xE6, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmaddsub231ps", vfma_ps_insn, 2, SUF_Z, 0xB6, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"data16", NULL, X86_OPERSIZE>>8, 0x10, 0, 0, 0, 0, 0, 0, 0},
+ {"lmsw", prot286_insn, 1, SUF_Z, 0x06, 0x01, 0, 0, CPU_286, CPU_Priv, 0},
+ {"cmovnsq", cmovcc_insn, 3, SUF_Q, 0x09, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"ficompl", fiarith_insn, 2, SUF_L, 0x03, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"sets", setcc_insn, 1, SUF_Z, 0x08, 0, 0, 0, CPU_386, 0, 0},
+ {"vpmuldq", ssse3_insn, 5, SUF_Z, 0x28, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"mulss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x59, 0, 0, CPU_SSE, 0, 0},
+ {"minpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x5D, 0, 0, CPU_SSE2, 0, 0},
+ {"pshufhw", xmm_xmm128_imm_insn, 1, SUF_Z, 0xF3, 0x70, 0, 0, CPU_SSE2, 0, 0},
+ {"dword", NULL, X86_OPERSIZE>>8, 0x20, 0, 0, 0, 0, 0, 0, 0},
+ {"cmovnael", cmovcc_insn, 3, SUF_L, 0x02, 0, 0, 0, CPU_686, 0, 0},
+ {"xtest", tsx_0x0F_0x01_insn, 1, SUF_Z, 0xD6, 0, 0, 0, CPU_TSX, 0, 0},
+ {"sar", shift_insn, 16, SUF_Z, 0x07, 0, 0, 0, 0, 0, 0},
+ {"cmovngel", cmovcc_insn, 3, SUF_L, 0x0C, 0, 0, 0, CPU_686, 0, 0},
+ {"cmovnlew", cmovcc_insn, 3, SUF_W, 0x0F, 0, 0, 0, CPU_686, 0, 0},
+ {"sidt", twobytemem_insn, 1, SUF_Z, 0x01, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"fxrstor", twobytemem_insn, 1, SUF_Z, 0x01, 0x0F, 0xAE, 0, CPU_686, CPU_FPU, 0},
+ {"adcxl", vex_gpr_ndd_rm_0F38_insn, 2, SUF_L, 0x66, 0xF6, 0, 0, CPU_ADX, 0, 0},
+ {"mull", f6_insn, 4, SUF_L, 0x04, 0, 0, 0, CPU_386, 0, 0},
+ {"wbinvd", twobyte_insn, 1, SUF_Z, 0x0F, 0x09, 0, 0, CPU_486, CPU_Priv, 0},
+ {"pmaxuw", sse4_insn, 2, SUF_Z, 0x3E, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"setnp", setcc_insn, 1, SUF_Z, 0x0B, 0, 0, 0, CPU_386, 0, 0},
+ {"decb", incdec_insn, 6, SUF_B, 0x48, 0x01, 0, 0, 0, 0, 0},
+ {"fnsaves", onebytemem_insn, 1, SUF_S, 0x06, 0xDD, 0, 0, CPU_FPU, 0, 0},
+ {"cmovbe", cmovcc_insn, 3, SUF_Z, 0x06, 0, 0, 0, CPU_686, 0, 0},
+ {"fsaves", twobytemem_insn, 1, SUF_S, 0x06, 0x9B, 0xDD, 0, CPU_FPU, 0, 0},
+ {"jz", jcc_insn, 9, SUF_Z, 0x04, 0, 0, 0, 0, 0, 0},
+ {"cmovngeq", cmovcc_insn, 3, SUF_Q, 0x0C, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"neg", f6_insn, 4, SUF_Z, 0x03, 0, 0, 0, 0, 0, 0},
+ {"jmp", jmp_insn, 31, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"fdivrp", farithp_insn, 3, SUF_Z, 0xF8, 0, 0, 0, CPU_FPU, 0, 0},
+ {"cmovnsl", cmovcc_insn, 3, SUF_L, 0x09, 0, 0, 0, CPU_686, 0, 0},
+ {"lesl", ldes_insn, 2, SUF_L, 0xC4, 0, 0, NOT_64, CPU_386, 0, 0},
+ {"vpsllvq", vpshiftv_vexw1_avx2_insn, 2, SUF_Z, 0x47, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"movslq", movsxd_insn, 1, SUF_L, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"vmovss", movss_insn, 4, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovbew", cmovcc_insn, 3, SUF_W, 0x06, 0, 0, 0, CPU_686, 0, 0},
+ {"vpermpd", vperm_imm_avx2_insn, 1, SUF_Z, 0x01, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vcmpfalsesd", ssecmp_64_insn, 4, SUF_Z, 0x0B, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pcmpeqd", mmxsse2_insn, 2, SUF_Z, 0x76, 0, 0, 0, CPU_MMX, 0, 0},
+ {"cmovne", cmovcc_insn, 3, SUF_Z, 0x05, 0, 0, 0, CPU_686, 0, 0},
+ {"vpcomeqw", vpcom_insn, 1, SUF_Z, 0xCD, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"movsb", onebyte_insn, 1, SUF_Z, 0xA4, 0x00, 0, 0, 0, 0, 0},
+ {"loopnzl", loopl_insn, 4, SUF_Z, 0x00, 0x20, 0, 0, 0, 0, 0},
+ {"pmaxsd", sse4_insn, 2, SUF_Z, 0x3D, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"fld", fld_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"fstpt", fldstpt_insn, 1, SUF_Z, 0x07, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vcmplepd", ssecmp_128_insn, 3, SUF_Z, 0x02, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lidtq", twobytemem_insn, 1, SUF_Q, 0x03, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"blsmskl", vex_gpr_ndd_rm_0F38_regext_insn, 2, SUF_L, 0x00, 0xF3, 0x02, ONLY_AVX, CPU_BMI1, 0, 0},
+ {"vcmpge_oqsd", ssecmp_64_insn, 4, SUF_Z, 0x1D, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"unpckhps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x15, 0, 0, CPU_SSE, 0, 0},
+ {"vmreadq", vmxmemrd_insn, 2, SUF_Q, 0, 0, 0, ONLY_64, CPU_P4, 0, 0},
+ {"btsw", bittest_insn, 6, SUF_W, 0xAB, 0x05, 0, 0, CPU_386, 0, 0},
+ {"vpinsrwl", pinsrw_insn, 9, SUF_L, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcmpgtw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x65, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pextq", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_Q, 0xF3, 0x38, 0xF5, ONLY_64|ONLY_AVX, CPU_BMI2, 0, 0},
+ {"vcmpnge_uqsd", ssecmp_64_insn, 4, SUF_Z, 0x19, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pavgw", mmxsse2_insn, 2, SUF_Z, 0xE3, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vpunpckhbw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x68, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmlaunch", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xC2, 0, CPU_P4, 0, 0},
+ {"loopnew", loopw_insn, 4, SUF_Z, 0x00, 0x10, 0, NOT_64, 0, 0, 0},
+ {"vmaxps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x5F, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rdshr", rdwrshr_insn, 1, SUF_Z, 0x00, 0, 0, 0, CPU_686, CPU_Cyrix, CPU_SMM},
+ {"setge", setcc_insn, 1, SUF_Z, 0x0D, 0, 0, 0, CPU_386, 0, 0},
+ {"pcmpgtw", mmxsse2_insn, 2, SUF_Z, 0x65, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vsqrtpd", avx_xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x51, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fstsw", fstsw_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"cmovzw", cmovcc_insn, 3, SUF_W, 0x04, 0, 0, 0, CPU_686, 0, 0},
+ {"frstors", onebytemem_insn, 1, SUF_S, 0x04, 0xDD, 0, 0, CPU_FPU, 0, 0},
+ {"smsww", sldtmsw_insn, 6, SUF_W, 0x04, 0x01, 0, 0, CPU_286, 0, 0},
+ {"vpsubusw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xD9, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fisubrs", fiarith_insn, 2, SUF_S, 0x05, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"vmovshdup", avx_xmm_xmm128_insn, 2, SUF_Z, 0xF3, 0x16, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"xacquire", NULL, X86_ACQREL>>8, 0xF2, 0, 0, 0, 0, 0, 0, 0},
+ {"vcmple_oqss", ssecmp_32_insn, 4, SUF_Z, 0x12, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpgt_oqpd", ssecmp_128_insn, 3, SUF_Z, 0x1E, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pfsub", now3d_insn, 1, SUF_Z, 0x9A, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"vpgatherdd", gather_32x_32y_insn, 2, SUF_Z, 0x90, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vcmpngtss", ssecmp_32_insn, 4, SUF_Z, 0x0A, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmovzxbw", sse4m64_insn, 4, SUF_Z, 0x30, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"cmovgl", cmovcc_insn, 3, SUF_L, 0x0F, 0, 0, 0, CPU_686, 0, 0},
+ {"movaps", movau_insn, 6, SUF_Z, 0x00, 0x28, 0x01, 0, CPU_SSE, 0, 0},
+ {"rdfsbase", fs_gs_base_insn, 2, SUF_Z, 0x00, 0, 0, ONLY_64, CPU_FSGSBASE, 0, 0},
+ {"wrmsr", twobyte_insn, 1, SUF_Z, 0x0F, 0x30, 0, 0, CPU_586, CPU_Priv, 0},
+ {"movmskpsl", movmsk_insn, 4, SUF_L, 0, 0, 0, 0, CPU_386, CPU_SSE, 0},
+ {"vcmpngtpd", ssecmp_128_insn, 3, SUF_Z, 0x0A, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"decw", incdec_insn, 6, SUF_W, 0x48, 0x01, 0, 0, 0, 0, 0},
+ {"vmclear", vmxthreebytemem_insn, 1, SUF_Z, 0x66, 0, 0, 0, CPU_P4, 0, 0},
+ {"vfmsub213pd", vfma_pd_insn, 2, SUF_Z, 0xAA, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"roundps", sse4imm_insn, 2, SUF_Z, 0x08, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"xsaveopt", twobytemem_insn, 1, SUF_Z, 0x06, 0x0F, 0xAE, 0, CPU_XSAVEOPT, 0, 0},
+ {"blsmskq", vex_gpr_ndd_rm_0F38_regext_insn, 2, SUF_Q, 0x00, 0xF3, 0x02, ONLY_64|ONLY_AVX, CPU_BMI1, 0, 0},
+ {"fnstcww", fldnstcw_insn, 1, SUF_W, 0x07, 0, 0, 0, CPU_FPU, 0, 0},
+ {"unpcklpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x14, 0, 0, CPU_SSE2, 0, 0},
+ {"pfrcp", now3d_insn, 1, SUF_Z, 0x96, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"phaddw", ssse3_insn, 5, SUF_Z, 0x01, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"adoxq", vex_gpr_ndd_rm_0F38_insn, 2, SUF_Q, 0xF3, 0xF6, 0, ONLY_64, CPU_ADX, 0, 0},
+ {"vcmpnltsd", ssecmp_64_insn, 4, SUF_Z, 0x05, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomleub", vpcom_insn, 1, SUF_Z, 0xEC, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"vpsrlq", vpshift_insn, 8, SUF_Z, 0xD3, 0x73, 0x02, ONLY_AVX, CPU_AVX, 0, 0},
+ {"psllq", pshift_insn, 4, SUF_Z, 0xF3, 0x73, 0x06, 0, CPU_MMX, 0, 0},
+ {"enterl", enter_insn, 3, SUF_L, 0, 0, 0, NOT_64, CPU_186, 0, 0},
+ {"wrshr", rdwrshr_insn, 1, SUF_Z, 0x01, 0, 0, 0, CPU_686, CPU_Cyrix, CPU_SMM},
+ {"blcsq", xop_gpr_reg_rm_09_insn, 2, SUF_Q, 0x01, 0x03, 0, ONLY_64, CPU_TBM, 0, 0},
+ {"vpmadcsswd", vpma_insn, 1, SUF_Z, 0xA6, 0, 0, 0, CPU_XOP, 0, 0},
+ {"fdivl", farith_insn, 7, SUF_L, 0xF8, 0xF0, 0x06, 0, CPU_FPU, 0, 0},
+ {"salb", shift_insn, 16, SUF_B, 0x04, 0, 0, 0, 0, 0, 0},
+ {"vpcomequq", vpcom_insn, 1, SUF_Z, 0xEF, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"cmovpw", cmovcc_insn, 3, SUF_W, 0x0A, 0, 0, 0, CPU_686, 0, 0},
+ {"cmovgw", cmovcc_insn, 3, SUF_W, 0x0F, 0, 0, 0, CPU_686, 0, 0},
+ {"vpmovmskbl", pmovmskb_insn, 6, SUF_L, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"iretl", onebyte_insn, 1, SUF_Z, 0xCF, 0x20, 0, 0, CPU_386, 0, 0},
+ {"fdiv", farith_insn, 7, SUF_Z, 0xF8, 0xF0, 0x06, 0, CPU_FPU, 0, 0},
+ {"vpermps", vperm_var_avx2_insn, 1, SUF_Z, 0x16, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vphaddwd", vphaddsub_insn, 1, SUF_Z, 0xC6, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpnlt_uqss", ssecmp_32_insn, 4, SUF_Z, 0x15, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomleuw", vpcom_insn, 1, SUF_Z, 0xED, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"crc32l", crc32_insn, 5, SUF_L, 0, 0, 0, 0, CPU_386, CPU_SSE42, 0},
+ {"cmpsq", onebyte_insn, 1, SUF_Z, 0xA7, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"cmovpel", cmovcc_insn, 3, SUF_L, 0x0A, 0, 0, 0, CPU_686, 0, 0},
+ {"cmovnlel", cmovcc_insn, 3, SUF_L, 0x0F, 0, 0, 0, CPU_686, 0, 0},
+ {"sysretl", twobyte_insn, 1, SUF_L, 0x0F, 0x07, 0, 0, CPU_686, CPU_AMD, CPU_Priv},
+ {"setpo", setcc_insn, 1, SUF_Z, 0x0B, 0, 0, 0, CPU_386, 0, 0},
+ {"vpcomgtq", vpcom_insn, 1, SUF_Z, 0xCF, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"phsubsw", ssse3_insn, 5, SUF_Z, 0x07, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"pinsrw", pinsrw_insn, 9, SUF_Z, 0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vfmadd231ps", vfma_ps_insn, 2, SUF_Z, 0xB8, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"mulps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x59, 0, 0, CPU_SSE, 0, 0},
+ {"setz", setcc_insn, 1, SUF_Z, 0x04, 0, 0, 0, CPU_386, 0, 0},
+ {"cmpltsd", ssecmp_64_insn, 4, SUF_Z, 0x01, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"fstl", fst_insn, 3, SUF_L, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vcmptrueps", ssecmp_128_insn, 3, SUF_Z, 0x0F, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovow", cmovcc_insn, 3, SUF_W, 0x00, 0, 0, 0, CPU_686, 0, 0},
+ {"extrq", extrq_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_SSE4a, 0, 0},
+ {"verrw", prot286_insn, 1, SUF_W, 0x04, 0x00, 0, 0, CPU_286, CPU_Prot, 0},
+ {"setno", setcc_insn, 1, SUF_Z, 0x01, 0, 0, 0, CPU_386, 0, 0},
+ {"lssw", lfgss_insn, 3, SUF_W, 0xB2, 0, 0, 0, CPU_386, 0, 0},
+ {"cmpunordps", ssecmp_128_insn, 3, SUF_Z, 0x03, 0, 0, 0, CPU_SSE, 0, 0},
+ {"shlxq", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_Q, 0x66, 0x38, 0xF7, ONLY_64|ONLY_AVX, CPU_BMI2, 0, 0},
+ {"emms", twobyte_insn, 1, SUF_Z, 0x0F, 0x77, 0, 0, CPU_MMX, 0, 0},
+ {"sarq", shift_insn, 16, SUF_Q, 0x07, 0, 0, ONLY_64, 0, 0, 0},
+ {"pminsd", sse4_insn, 2, SUF_Z, 0x39, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"rorw", shift_insn, 16, SUF_W, 0x01, 0, 0, 0, 0, 0, 0},
+ {"pxor", mmxsse2_insn, 2, SUF_Z, 0xEF, 0, 0, 0, CPU_MMX, 0, 0},
+ {"pfnacc", now3d_insn, 1, SUF_Z, 0x8A, 0, 0, 0, CPU_3DNow, CPU_Athlon, 0},
+ {"pf2iw", now3d_insn, 1, SUF_Z, 0x1C, 0, 0, 0, CPU_3DNow, CPU_Athlon, 0},
+ {"invpcid", invpcid_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_INVPCID, CPU_Priv},
+ {"fcompl", fcom_insn, 6, SUF_L, 0xD8, 0x03, 0, 0, CPU_FPU, 0, 0},
+ {"larq", larlsl_insn, 6, SUF_Q, 0x02, 0, 0, ONLY_64, CPU_286, CPU_Prot, 0},
+ {"str", str_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_286, CPU_Prot, 0},
+ {"movmskpsq", movmsk_insn, 4, SUF_Q, 0, 0, 0, ONLY_64, CPU_SSE, 0, 0},
+ {"lds", ldes_insn, 2, SUF_Z, 0xC5, 0, 0, NOT_64, 0, 0, 0},
+ {"vpinsrb", pinsrb_insn, 4, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pushf", onebyte_insn, 1, SUF_Z, 0x9C, 0x00, 0x40, 0, 0, 0, 0},
+ {"vcvtsd2sil", cvt_rx_xmm64_insn, 4, SUF_L, 0xF2, 0x2D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jge", jcc_insn, 9, SUF_Z, 0x0D, 0, 0, 0, 0, 0, 0},
+ {"setpb", setcc_insn, 1, SUF_B, 0x0A, 0, 0, 0, CPU_386, 0, 0},
+ {"andl", arith_insn, 22, SUF_L, 0x20, 0x04, 0, 0, CPU_386, 0, 0},
+ {"vaesdec", aes_insn, 2, SUF_Z, 0x38, 0xDE, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"xstore", padlock_insn, 1, SUF_Z, 0xC0, 0x00, 0xA7, 0, CPU_PadLock, 0, 0},
+ {"sha1nexte", intel_SHA1NEXTE_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SHA, 0, 0},
+ {"andps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x54, 0, 0, CPU_SSE, 0, 0},
+ {"vphaddbd", vphaddsub_insn, 1, SUF_Z, 0xC2, 0, 0, 0, CPU_XOP, 0, 0},
+ {"rorxl", vex_gpr_reg_rm_0F_imm8_insn, 2, SUF_L, 0xF2, 0x3A, 0xF0, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"jmpw", jmp_insn, 31, SUF_W, 0, 0, 0, 0, 0, 0, 0},
+ {"fildll", fbldstp_insn, 1, SUF_Z, 0x05, 0, 0, 0, CPU_FPU, 0, 0},
+ {"out", out_insn, 12, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"mulsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x59, 0, 0, CPU_SSE2, 0, 0},
+ {"movss", movss_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_SSE, 0, 0},
+ {"smswl", sldtmsw_insn, 6, SUF_L, 0x04, 0x01, 0, 0, CPU_386, 0, 0},
+ {"aam", aadm_insn, 2, SUF_Z, 0x00, 0, 0, NOT_64, 0, 0, 0},
+ {"stosw", onebyte_insn, 1, SUF_Z, 0xAB, 0x10, 0, 0, 0, 0, 0},
+ {"ptest", sse4_insn, 2, SUF_Z, 0x17, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"lretw", retnf_insn, 6, SUF_W, 0xCA, 0x10, 0, 0, 0, 0, 0},
+ {"notq", f6_insn, 4, SUF_Q, 0x02, 0, 0, ONLY_64, 0, 0, 0},
+ {"vmload", svm_rax_insn, 2, SUF_Z, 0xDA, 0, 0, 0, CPU_SVM, 0, 0},
+ {"andb", arith_insn, 22, SUF_B, 0x20, 0x04, 0, 0, 0, 0, 0},
+ {"vcmpeq_usss", ssecmp_32_insn, 4, SUF_Z, 0x18, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpsubsw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xE9, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmovmskpd", movmsk_insn, 4, SUF_Z, 0x66, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmsub231pd", vfma_pd_insn, 2, SUF_Z, 0xBE, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"cmovg", cmovcc_insn, 3, SUF_Z, 0x0F, 0, 0, 0, CPU_686, 0, 0},
+ {"cmpeqpd", ssecmp_128_insn, 3, SUF_Z, 0x00, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"vfmsub213sd", vfma_sd_insn, 2, SUF_Z, 0xAB, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"rex64", NULL, X86_REX>>8, 0x48, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"vpcmpistri", sse4pcmpstr_insn, 1, SUF_Z, 0x63, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpminsb", ssse3_insn, 5, SUF_Z, 0x38, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmadd231pd", vfma_pd_insn, 2, SUF_Z, 0xBC, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"ja", jcc_insn, 9, SUF_Z, 0x07, 0, 0, 0, 0, 0, 0},
+ {"vpmullw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xD5, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvttpd2dq", avx_cvt_xmm128_insn, 2, SUF_Z, 0x66, 0xE6, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vgatherdps", gather_32x_32y_insn, 2, SUF_Z, 0x92, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vfmsub213ss", vfma_ss_insn, 2, SUF_Z, 0xAB, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"cmpxchgb", cmpxchgxadd_insn, 4, SUF_B, 0xB0, 0, 0, 0, CPU_486, 0, 0},
+ {"sgdtw", twobytemem_insn, 1, SUF_W, 0x00, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"cmpb", arith_insn, 22, SUF_B, 0x38, 0x07, 0, 0, 0, 0, 0},
+ {"vmulpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x59, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cvttsd2siq", cvt_rx_xmm64_insn, 4, SUF_Q, 0xF2, 0x2C, 0, ONLY_64, CPU_SSE2, 0, 0},
+ {"movzwq", movszx_insn, 5, SUF_W, 0xB6, 0, 0, ONLY_64, CPU_386, 0, 0},
+ {"les", ldes_insn, 2, SUF_Z, 0xC4, 0, 0, NOT_64, 0, 0, 0},
+ {"vcmpngepd", ssecmp_128_insn, 3, SUF_Z, 0x09, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"clflush", clflush_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_P3, 0, 0},
+ {"leavew", onebyte_insn, 1, SUF_Z, 0xC9, 0x10, 0x00, 0, CPU_186, 0, 0},
+ {"addsubps", xmm_xmm128_insn, 2, SUF_Z, 0xF2, 0xD0, 0, 0, CPU_SSE3, 0, 0},
+ {"vinsertps", insertps_insn, 4, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmresume", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xC3, 0, CPU_P4, 0, 0},
+ {"cmpnlesd", ssecmp_64_insn, 4, SUF_Z, 0x06, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"setnge", setcc_insn, 1, SUF_Z, 0x0C, 0, 0, 0, CPU_386, 0, 0},
+ {"adcxq", vex_gpr_ndd_rm_0F38_insn, 2, SUF_Q, 0x66, 0xF6, 0, ONLY_64, CPU_ADX, 0, 0},
+ {"xsetbv", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xD1, 0, CPU_386, CPU_Priv, CPU_XSAVE},
+ {"vphsubsw", ssse3_insn, 5, SUF_Z, 0x07, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpgtsd", ssecmp_64_insn, 4, SUF_Z, 0x0E, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vphsubw", ssse3_insn, 5, SUF_Z, 0x05, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovnbel", cmovcc_insn, 3, SUF_L, 0x07, 0, 0, 0, CPU_686, 0, 0},
+ {"fcomi", fcom2_insn, 2, SUF_Z, 0xDB, 0xF0, 0, 0, CPU_686, CPU_FPU, 0},
+ {"blsfillq", xop_gpr_reg_rm_09_insn, 2, SUF_Q, 0x01, 0x02, 0, ONLY_64, CPU_TBM, 0, 0},
+ {"mulxl", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_L, 0xF2, 0x38, 0xF6, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"fcomip", fcom2_insn, 2, SUF_Z, 0xDF, 0xF0, 0, 0, CPU_686, CPU_FPU, 0},
+ {"vpinsrq", pinsrq_insn, 2, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomw", vpcom_imm_insn, 1, SUF_Z, 0xCD, 0, 0, 0, CPU_XOP, 0, 0},
+ {"rsts", cyrixsmm_insn, 1, SUF_Z, 0x7D, 0, 0, 0, CPU_486, CPU_Cyrix, CPU_SMM},
+ {"vpcomleb", vpcom_insn, 1, SUF_Z, 0xCC, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"vdivpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x5E, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"add", arith_insn, 22, SUF_Z, 0x00, 0x00, 0, 0, 0, 0, 0},
+ {"sldtw", sldtmsw_insn, 6, SUF_W, 0x00, 0x00, 0, 0, CPU_286, 0, 0},
+ {"rorl", shift_insn, 16, SUF_L, 0x01, 0, 0, 0, CPU_386, 0, 0},
+ {"vcvtsi2sd", cvt_xmm_rmx_insn, 6, SUF_Z, 0xF2, 0x2A, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpnge_uqps", ssecmp_128_insn, 3, SUF_Z, 0x19, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmsubpd", fma_128_256_insn, 4, SUF_Z, 0x6D, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"vpminsd", ssse3_insn, 5, SUF_Z, 0x39, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fistl", fiarith_insn, 2, SUF_L, 0x02, 0xDB, 0, 0, CPU_FPU, 0, 0},
+ {"fcmovu", fcmovcc_insn, 1, SUF_Z, 0xDA, 0xD8, 0, 0, CPU_686, CPU_FPU, 0},
+ {"scasb", onebyte_insn, 1, SUF_Z, 0xAE, 0x00, 0, 0, 0, 0, 0},
+ {"phminposuw", sse4_insn, 2, SUF_Z, 0x41, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"pextrwl", pextrw_insn, 7, SUF_L, 0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vpclmulqdq", pclmulqdq_insn, 2, SUF_Z, 0x3A, 0x44, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vphaddbw", vphaddsub_insn, 1, SUF_Z, 0xC1, 0, 0, 0, CPU_XOP, 0, 0},
+ {"psubsb", mmxsse2_insn, 2, SUF_Z, 0xE8, 0, 0, 0, CPU_MMX, 0, 0},
+ {"lss", lfgss_insn, 3, SUF_Z, 0xB2, 0, 0, 0, CPU_386, 0, 0},
+ {"pushal", onebyte_insn, 1, SUF_Z, 0x60, 0x20, 0, NOT_64, CPU_386, 0, 0},
+ {"setb", setcc_insn, 1, SUF_Z, 0x02, 0, 0, 0, CPU_386, 0, 0},
+ {"cmpnltps", ssecmp_128_insn, 3, SUF_Z, 0x05, 0, 0, 0, CPU_SSE, 0, 0},
+ {"rcpss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x53, 0, 0, CPU_SSE, 0, 0},
+ {"vcmpnltpd", ssecmp_128_insn, 3, SUF_Z, 0x05, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpneqps", ssecmp_128_insn, 3, SUF_Z, 0x04, 0, 0, 0, CPU_SSE, 0, 0},
+ {"vpsadbw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xF6, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtss2sil", cvt_rx_xmm32_insn, 4, SUF_L, 0xF3, 0x2D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fadds", farith_insn, 7, SUF_S, 0xC0, 0xC0, 0x00, 0, CPU_FPU, 0, 0},
+ {"cmovbeq", cmovcc_insn, 3, SUF_Q, 0x06, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"bextrl", bextr_insn, 4, SUF_L, 0, 0, 0, ONLY_AVX, CPU_386, CPU_BMI1, 0},
+ {"vsqrtps", avx_xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x51, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpunord_ssd", ssecmp_64_insn, 4, SUF_Z, 0x13, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmaxsw", mmxsse2_insn, 2, SUF_Z, 0xEE, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"lcallq", ljmpcall_insn, 7, SUF_Q, 0x03, 0x9A, 0, ONLY_64, 0, 0, 0},
+ {"vpextrb", pextrb_insn, 3, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fchs", twobyte_insn, 1, SUF_Z, 0xD9, 0xE0, 0, 0, CPU_FPU, 0, 0},
+ {"cmovnbeq", cmovcc_insn, 3, SUF_Q, 0x07, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"sha1msg2", intel_SHA1MSG2_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SHA, 0, 0},
+ {"vpaddusb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xDC, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"faddp", farithp_insn, 3, SUF_Z, 0xC0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"cmovnbe", cmovcc_insn, 3, SUF_Z, 0x07, 0, 0, 0, CPU_686, 0, 0},
+ {"psrldq", pslrldq_insn, 4, SUF_Z, 0x03, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"movswl", movszx_insn, 5, SUF_W, 0xBE, 0, 0, 0, CPU_386, 0, 0},
+ {"outsw", onebyte_insn, 1, SUF_Z, 0x6F, 0x10, 0, 0, 0, 0, 0},
+ {"vpminud", ssse3_insn, 5, SUF_Z, 0x3B, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"aesimc", aesimc_insn, 1, SUF_Z, 0x38, 0xDB, 0, 0, CPU_AES, 0, 0},
+ {"movsd", movsd_insn, 5, SUF_Z, 0, 0, 0, 0, CPU_386, 0, 0},
+ {"fistpq", fildstp_insn, 4, SUF_Q, 0x03, 0x02, 0x07, 0, CPU_FPU, 0, 0},
+ {"loopnzq", loopq_insn, 4, SUF_Z, 0x00, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"vcmpngt_uqps", ssecmp_128_insn, 3, SUF_Z, 0x1A, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setsb", setcc_insn, 1, SUF_B, 0x08, 0, 0, 0, CPU_386, 0, 0},
+ {"vpsignw", ssse3_insn, 5, SUF_Z, 0x09, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"scasl", onebyte_insn, 1, SUF_Z, 0xAF, 0x20, 0, 0, CPU_386, 0, 0},
+ {"addb", arith_insn, 22, SUF_B, 0x00, 0x00, 0, 0, 0, 0, 0},
+ {"jnc", jcc_insn, 9, SUF_Z, 0x03, 0, 0, 0, 0, 0, 0},
+ {"cmpeqsd", ssecmp_64_insn, 4, SUF_Z, 0x00, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"maxss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5F, 0, 0, CPU_SSE, 0, 0},
+ {"lodsl", onebyte_insn, 1, SUF_Z, 0xAD, 0x20, 0, 0, CPU_386, 0, 0},
+ {"lahf", onebyte_insn, 1, SUF_Z, 0x9F, 0, 0, 0, 0, 0, 0},
+ {"setp", setcc_insn, 1, SUF_Z, 0x0A, 0, 0, 0, CPU_386, 0, 0},
+ {"vpunpcklwd", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x61, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmwritel", vmxmemwr_insn, 2, SUF_L, 0, 0, 0, NOT_64, CPU_P4, 0, 0},
+ {"blendps", sse4imm_insn, 2, SUF_Z, 0x0C, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vmcall", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xC1, 0, CPU_P4, 0, 0},
+ {"pushq", push_insn, 35, SUF_Q, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"vcmpnleps", ssecmp_128_insn, 3, SUF_Z, 0x06, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomtrueuw", vpcom_insn, 1, SUF_Z, 0xED, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"pmuldq", sse4_insn, 2, SUF_Z, 0x28, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"cmpl", arith_insn, 22, SUF_L, 0x38, 0x07, 0, 0, CPU_386, 0, 0},
+ {"pfmin", now3d_insn, 1, SUF_Z, 0x94, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"fldpi", twobyte_insn, 1, SUF_Z, 0xD9, 0xEB, 0, 0, CPU_FPU, 0, 0},
+ {"vcvtsi2sdl", cvt_xmm_rmx_insn, 6, SUF_L, 0xF2, 0x2A, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpsraw", vpshift_insn, 8, SUF_Z, 0xE1, 0x71, 0x04, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtps2ph", avx_cvtps2ph_insn, 4, SUF_Z, 0x66, 0x1D, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"subq", arith_insn, 22, SUF_Q, 0x28, 0x05, 0, ONLY_64, 0, 0, 0},
+ {"fsubrs", farith_insn, 7, SUF_S, 0xE0, 0xE8, 0x05, 0, CPU_FPU, 0, 0},
+ {"xchgq", xchg_insn, 16, SUF_Q, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"cmovsq", cmovcc_insn, 3, SUF_Q, 0x08, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"shldq", shlrd_insn, 9, SUF_Q, 0xA4, 0, 0, ONLY_64, CPU_386, 0, 0},
+ {"leaveq", onebyte_insn, 1, SUF_Z, 0xC9, 0x00, 0x40, ONLY_64, 0, 0, 0},
+ {"stc", onebyte_insn, 1, SUF_Z, 0xF9, 0, 0, 0, 0, 0, 0},
+ {"fsave", twobytemem_insn, 1, SUF_Z, 0x06, 0x9B, 0xDD, 0, CPU_FPU, 0, 0},
+ {"rclb", shift_insn, 16, SUF_B, 0x02, 0, 0, 0, 0, 0, 0},
+ {"fisubrl", fiarith_insn, 2, SUF_L, 0x05, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"vpsrlvd", vpshiftv_vexw0_avx2_insn, 2, SUF_Z, 0x45, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"fstenvl", twobytemem_insn, 1, SUF_L, 0x06, 0x9B, 0xD9, 0, CPU_FPU, 0, 0},
+ {"paddsb", mmxsse2_insn, 2, SUF_Z, 0xEC, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vmwriteq", vmxmemwr_insn, 2, SUF_Q, 0, 0, 0, ONLY_64, CPU_P4, 0, 0},
+ {"ud2", twobyte_insn, 1, SUF_Z, 0x0F, 0x0B, 0, 0, CPU_286, 0, 0},
+ {"vfmaddsub132pd", vfma_pd_insn, 2, SUF_Z, 0x96, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"sti", onebyte_insn, 1, SUF_Z, 0xFB, 0, 0, 0, 0, 0, 0},
+ {"shld", shlrd_insn, 9, SUF_Z, 0xA4, 0, 0, 0, CPU_386, 0, 0},
+ {"vpabsd", avx2_ssse3_2op_insn, 2, SUF_Z, 0x1E, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"mwait", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xC9, 0, CPU_SSE3, 0, 0},
+ {"cvtsi2sd", cvt_xmm_rmx_insn, 6, SUF_Z, 0xF2, 0x2A, 0, 0, CPU_SSE2, 0, 0},
+ {"cmovnp", cmovcc_insn, 3, SUF_Z, 0x0B, 0, 0, 0, CPU_686, 0, 0},
+ {"vcvtpd2dq", avx_cvt_xmm128_insn, 2, SUF_Z, 0xF2, 0xE6, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmovsxbw", sse4m64_insn, 4, SUF_Z, 0x20, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"fisubl", fiarith_insn, 2, SUF_L, 0x04, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"daa", onebyte_insn, 1, SUF_Z, 0x27, 0, 0, NOT_64, 0, 0, 0},
+ {"fdivrl", farith_insn, 7, SUF_L, 0xF0, 0xF8, 0x07, 0, CPU_FPU, 0, 0},
+ {"stac", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xCB, 0, CPU_SMAP, 0, 0},
+ {"testw", test_insn, 20, SUF_W, 0, 0, 0, 0, 0, 0, 0},
+ {"movzwl", movszx_insn, 5, SUF_W, 0xB6, 0, 0, 0, CPU_386, 0, 0},
+ {"vpblendw", sse4imm_256avx2_insn, 4, SUF_Z, 0x0E, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomgtuq", vpcom_insn, 1, SUF_Z, 0xEF, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"setnaeb", setcc_insn, 1, SUF_B, 0x02, 0, 0, 0, CPU_386, 0, 0},
+ {"pextrwq", pextrw_insn, 7, SUF_Q, 0, 0, 0, ONLY_64, CPU_MMX, CPU_P3, 0},
+ {"lodsq", onebyte_insn, 1, SUF_Z, 0xAD, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"fincstp", twobyte_insn, 1, SUF_Z, 0xD9, 0xF7, 0, 0, CPU_FPU, 0, 0},
+ {"cmovlew", cmovcc_insn, 3, SUF_W, 0x0E, 0, 0, 0, CPU_686, 0, 0},
+ {"insertq", insertq_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_SSE4a, 0, 0},
+ {"notl", f6_insn, 4, SUF_L, 0x02, 0, 0, 0, CPU_386, 0, 0},
+ {"vfnmadd132sd", vfma_sd_insn, 2, SUF_Z, 0x9D, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"cmova", cmovcc_insn, 3, SUF_Z, 0x07, 0, 0, 0, CPU_686, 0, 0},
+ {"fstcw", fstcw_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vpclmullqhqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x10, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movnti", movnti_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_P4, 0, 0},
+ {"packusdw", sse4_insn, 2, SUF_Z, 0x2B, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"punpckhqdq", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x6D, 0, 0, CPU_SSE2, 0, 0},
+ {"lzcntw", cnt_insn, 3, SUF_W, 0xBD, 0, 0, 0, CPU_LZCNT, 0, 0},
+ {"pcmpistri", sse4pcmpstr_insn, 1, SUF_Z, 0x63, 0, 0, 0, CPU_SSE42, 0, 0},
+ {"fimull", fiarith_insn, 2, SUF_L, 0x01, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"fnstenv", onebytemem_insn, 1, SUF_Z, 0x06, 0xD9, 0, 0, CPU_FPU, 0, 0},
+ {"cmovncw", cmovcc_insn, 3, SUF_W, 0x03, 0, 0, 0, CPU_686, 0, 0},
+ {"leaw", lea_insn, 3, SUF_W, 0, 0, 0, 0, 0, 0, 0},
+ {"vfmadd132ss", vfma_ss_insn, 2, SUF_Z, 0x99, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"pshufd", xmm_xmm128_imm_insn, 1, SUF_Z, 0x66, 0x70, 0, 0, CPU_SSE2, 0, 0},
+ {"blsil", vex_gpr_ndd_rm_0F38_regext_insn, 2, SUF_L, 0x00, 0xF3, 0x03, ONLY_AVX, CPU_BMI1, 0, 0},
+ {"stosl", onebyte_insn, 1, SUF_Z, 0xAB, 0x20, 0, 0, CPU_386, 0, 0},
+ {"mulq", f6_insn, 4, SUF_Q, 0x04, 0, 0, ONLY_64, 0, 0, 0},
+ {"cmovbl", cmovcc_insn, 3, SUF_L, 0x02, 0, 0, 0, CPU_686, 0, 0},
+ {"vpmaxsd", ssse3_insn, 5, SUF_Z, 0x3D, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rsqrtps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x52, 0, 0, CPU_SSE, 0, 0},
+ {"ror", shift_insn, 16, SUF_Z, 0x01, 0, 0, 0, 0, 0, 0},
+ {"vcmptrue_usss", ssecmp_32_insn, 4, SUF_Z, 0x1F, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpermq", vperm_imm_avx2_insn, 1, SUF_Z, 0x00, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"xcryptofb", padlock_insn, 1, SUF_Z, 0xE8, 0xF3, 0xA7, 0, CPU_PadLock, 0, 0},
+ {"btsl", bittest_insn, 6, SUF_L, 0xAB, 0x05, 0, 0, CPU_386, 0, 0},
+ {"vfnmsub213ps", vfma_ps_insn, 2, SUF_Z, 0xAE, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"stmxcsr", ldstmxcsr_insn, 1, SUF_Z, 0x03, 0, 0, 0, CPU_SSE, 0, 0},
+ {"vzeroupper", vzero_insn, 1, SUF_Z, 0xC0, 0, 0, 0, CPU_AVX, 0, 0},
+ {"adcx", vex_gpr_ndd_rm_0F38_insn, 2, SUF_Z, 0x66, 0xF6, 0, 0, CPU_ADX, 0, 0},
+ {"setnz", setcc_insn, 1, SUF_Z, 0x05, 0, 0, 0, CPU_386, 0, 0},
+ {"fildl", fildstp_insn, 4, SUF_L, 0x00, 0x02, 0x05, 0, CPU_FPU, 0, 0},
+ {"movlps", movhlp_insn, 3, SUF_Z, 0x00, 0x12, 0, 0, CPU_SSE, 0, 0},
+ {"vmovmskpdq", movmsk_insn, 4, SUF_Q, 0x66, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovngw", cmovcc_insn, 3, SUF_W, 0x0E, 0, 0, 0, CPU_686, 0, 0},
+ {"cltd", onebyte_insn, 1, SUF_Z, 0x99, 0x20, 0, 0, CPU_386, 0, 0},
+ {"fmuls", farith_insn, 7, SUF_S, 0xC8, 0xC8, 0x01, 0, CPU_FPU, 0, 0},
+ {"fcom", fcom_insn, 6, SUF_Z, 0xD0, 0x02, 0, 0, CPU_FPU, 0, 0},
+ {"andq", arith_insn, 22, SUF_Q, 0x20, 0x04, 0, ONLY_64, 0, 0, 0},
+ {"vfmaddps", fma_128_256_insn, 4, SUF_Z, 0x68, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"fst", fst_insn, 3, SUF_Z, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vmaskmovpd", vmaskmov_insn, 4, SUF_Z, 0x2D, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cld", onebyte_insn, 1, SUF_Z, 0xFC, 0, 0, 0, 0, 0, 0},
+ {"vpinsrd", pinsrd_insn, 2, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"xchgl", xchg_insn, 16, SUF_L, 0, 0, 0, 0, 0, 0, 0},
+ {"vcmpgtpd", ssecmp_128_insn, 3, SUF_Z, 0x0E, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovael", cmovcc_insn, 3, SUF_L, 0x03, 0, 0, 0, CPU_686, 0, 0},
+ {"phaddsw", ssse3_insn, 5, SUF_Z, 0x03, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"pclmullqlqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x00, 0, 0, 0, CPU_AVX, 0, 0},
+ {"cmovnleq", cmovcc_insn, 3, SUF_Q, 0x0F, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"pcmpeqb", mmxsse2_insn, 2, SUF_Z, 0x74, 0, 0, 0, CPU_MMX, 0, 0},
+ {"word", NULL, X86_OPERSIZE>>8, 0x10, 0, 0, 0, 0, 0, 0, 0},
+ {"blcmskq", xop_gpr_reg_rm_09_insn, 2, SUF_Q, 0x02, 0x01, 0, ONLY_64, CPU_TBM, 0, 0},
+ {"vpcomgtud", vpcom_insn, 1, SUF_Z, 0xEE, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"fsubr", farith_insn, 7, SUF_Z, 0xE0, 0xE8, 0x05, 0, CPU_FPU, 0, 0},
+ {"cmovp", cmovcc_insn, 3, SUF_Z, 0x0A, 0, 0, 0, CPU_686, 0, 0},
+ {"shrq", shift_insn, 16, SUF_Q, 0x05, 0, 0, ONLY_64, 0, 0, 0},
+ {"vpcomgtd", vpcom_insn, 1, SUF_Z, 0xCE, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"vfnmsub132sd", vfma_sd_insn, 2, SUF_Z, 0x9F, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpor", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xEB, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"psllw", pshift_insn, 4, SUF_Z, 0xF1, 0x71, 0x06, 0, CPU_MMX, 0, 0},
+ {"fbld", fbldstp_insn, 1, SUF_Z, 0x04, 0, 0, 0, CPU_FPU, 0, 0},
+ {"subw", arith_insn, 22, SUF_W, 0x28, 0x05, 0, 0, 0, 0, 0},
+ {"vmovhlps", movhllhps_insn, 2, SUF_Z, 0x12, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovleq", cmovcc_insn, 3, SUF_Q, 0x0E, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"imulw", imul_insn, 19, SUF_W, 0, 0, 0, 0, 0, 0, 0},
+ {"cvttss2siq", cvt_rx_xmm32_insn, 4, SUF_Q, 0xF3, 0x2C, 0, ONLY_64, CPU_SSE, 0, 0},
+ {"vgatherqpd", gather_64x_64y_insn, 2, SUF_Z, 0x93, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"imulq", imul_insn, 19, SUF_Q, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"ret", retnf_insn, 6, SUF_Z, 0xC2, 0, 0, 0, 0, 0, 0},
+ {"vphminposuw", avx_ssse3_2op_insn, 1, SUF_Z, 0x41, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpneqsd", ssecmp_64_insn, 4, SUF_Z, 0x04, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"jae", jcc_insn, 9, SUF_Z, 0x03, 0, 0, 0, 0, 0, 0},
+ {"vpavgb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xE0, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cwtd", onebyte_insn, 1, SUF_Z, 0x99, 0x10, 0, 0, 0, 0, 0},
+ {"movddup", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x12, 0, 0, CPU_SSE3, 0, 0},
+ {"vpcomud", vpcom_imm_insn, 1, SUF_Z, 0xEE, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpmovzxwd", sse4m64_insn, 4, SUF_Z, 0x33, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmsubss", fma_128_m32_insn, 3, SUF_Z, 0x7E, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"cmovgew", cmovcc_insn, 3, SUF_W, 0x0D, 0, 0, 0, CPU_686, 0, 0},
+ {"bzhi", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_Z, 0x00, 0x38, 0xF5, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"setab", setcc_insn, 1, SUF_B, 0x07, 0, 0, 0, CPU_386, 0, 0},
+ {"rsqrtss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x52, 0, 0, CPU_SSE, 0, 0},
+ {"vfmaddsub213pd", vfma_pd_insn, 2, SUF_Z, 0xA6, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"montmul", padlock_insn, 1, SUF_Z, 0xC0, 0xF3, 0xA6, 0, CPU_PadLock, 0, 0},
+ {"rcrq", shift_insn, 16, SUF_Q, 0x03, 0, 0, ONLY_64, 0, 0, 0},
+ {"vpaddsb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xEC, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vbroadcastss", vbroadcastss_insn, 4, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovnz", cmovcc_insn, 3, SUF_Z, 0x05, 0, 0, 0, CPU_686, 0, 0},
+ {"cmpxchgw", cmpxchgxadd_insn, 4, SUF_W, 0xB0, 0, 0, 0, CPU_486, 0, 0},
+ {"fcompp", twobyte_insn, 1, SUF_Z, 0xDE, 0xD9, 0, 0, CPU_FPU, 0, 0},
+ {"vpshab", amd_vpshift_insn, 2, SUF_Z, 0x98, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vaddpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x58, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtsi2ssq", cvt_xmm_rmx_insn, 6, SUF_Q, 0xF3, 0x2A, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"clc", onebyte_insn, 1, SUF_Z, 0xF8, 0, 0, 0, 0, 0, 0},
+ {"cmovlw", cmovcc_insn, 3, SUF_W, 0x0C, 0, 0, 0, CPU_686, 0, 0},
+ {"lgdt", twobytemem_insn, 1, SUF_Z, 0x02, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"getsec", twobyte_insn, 1, SUF_Z, 0x0F, 0x37, 0, 0, CPU_SMX, 0, 0},
+ {"blsrl", vex_gpr_ndd_rm_0F38_regext_insn, 2, SUF_L, 0x00, 0xF3, 0x01, ONLY_AVX, CPU_BMI1, 0, 0},
+ {"vpsignb", ssse3_insn, 5, SUF_Z, 0x08, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pblendw", sse4imm_insn, 2, SUF_Z, 0x0E, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vmovlhps", movhllhps_insn, 2, SUF_Z, 0x16, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"svdc", svdc_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_486, CPU_Cyrix, CPU_SMM},
+ {"vmovlpd", movhlp_insn, 3, SUF_Z, 0x66, 0x12, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vdppd", sse4imm_insn, 2, SUF_Z, 0x41, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"xbegin", tsx_xbegin_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_TSX, 0},
+ {"sldtq", sldtmsw_insn, 6, SUF_Q, 0x00, 0x00, 0, ONLY_64, CPU_286, 0, 0},
+ {"vpcmpeqb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x74, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpnless", ssecmp_32_insn, 4, SUF_Z, 0x06, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"fprem1", twobyte_insn, 1, SUF_Z, 0xD9, 0xF5, 0, 0, CPU_286, CPU_FPU, 0},
+ {"lssl", lfgss_insn, 3, SUF_L, 0xB2, 0, 0, 0, CPU_386, 0, 0},
+ {"inw", in_insn, 12, SUF_W, 0, 0, 0, 0, 0, 0, 0},
+ {"bzhiq", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_Q, 0x00, 0x38, 0xF5, ONLY_64|ONLY_AVX, CPU_BMI2, 0, 0},
+ {"pop", pop_insn, 23, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"vblendps", sse4imm_256_insn, 4, SUF_Z, 0x0C, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"flds", fld_insn, 4, SUF_S, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"movsxw", movszx_insn, 5, SUF_W, 0xBE, 0, 0, 0, CPU_386, 0, 0},
+ {"movabsw", movabs_insn, 9, SUF_W, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"divps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x5E, 0, 0, CPU_SSE, 0, 0},
+ {"vpcomfalseb", vpcom_insn, 1, SUF_Z, 0xCC, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpsd", cmpsd_insn, 5, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcmpgtq", ssse3_insn, 5, SUF_Z, 0x37, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setbb", setcc_insn, 1, SUF_B, 0x02, 0, 0, 0, CPU_386, 0, 0},
+ {"shrw", shift_insn, 16, SUF_W, 0x05, 0, 0, 0, 0, 0, 0},
+ {"andpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x54, 0, 0, CPU_SSE2, 0, 0},
+ {"vaesdeclast", aes_insn, 2, SUF_Z, 0x38, 0xDF, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"testb", test_insn, 20, SUF_B, 0, 0, 0, 0, 0, 0, 0},
+ {"vfmsub231ss", vfma_ss_insn, 2, SUF_Z, 0xBB, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"rexxz", NULL, X86_REX>>8, 0x45, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"cmpnlepd", ssecmp_128_insn, 3, SUF_Z, 0x06, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"lidt", twobytemem_insn, 1, SUF_Z, 0x03, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"vfmsubps", fma_128_256_insn, 4, SUF_Z, 0x6C, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"svldt", cyrixsmm_insn, 1, SUF_Z, 0x7A, 0, 0, 0, CPU_486, CPU_Cyrix, CPU_SMM},
+ {"rclw", shift_insn, 16, SUF_W, 0x02, 0, 0, 0, 0, 0, 0},
+ {"vphsubbw", vphaddsub_insn, 1, SUF_Z, 0xE1, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpnge_uqss", ssecmp_32_insn, 4, SUF_Z, 0x19, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movswq", movszx_insn, 5, SUF_W, 0xBE, 0, 0, ONLY_64, CPU_386, 0, 0},
+ {"blcic", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x01, 0x05, 0, 0, CPU_386, CPU_TBM, 0},
+ {"setns", setcc_insn, 1, SUF_Z, 0x09, 0, 0, 0, CPU_386, 0, 0},
+ {"vcmpneq_oqps", ssecmp_128_insn, 3, SUF_Z, 0x0C, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rorb", shift_insn, 16, SUF_B, 0x01, 0, 0, 0, 0, 0, 0},
+ {"vpcomgtuw", vpcom_insn, 1, SUF_Z, 0xED, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"vfmsubss", fma_128_m32_insn, 3, SUF_Z, 0x6E, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"vpperm", vpperm_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_XOP, 0, 0},
+ {"cmpxchg", cmpxchgxadd_insn, 4, SUF_Z, 0xB0, 0, 0, 0, CPU_486, 0, 0},
+ {"setnbeb", setcc_insn, 1, SUF_B, 0x07, 0, 0, 0, CPU_386, 0, 0},
+ {"vmovsd", movsd_insn, 5, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vrcpss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x53, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmovzxbd", sse4m32_insn, 4, SUF_Z, 0x31, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vroundpd", avx_sse4imm_insn, 3, SUF_Z, 0x09, 0, 0, ONLY_AVX, CPU_SSE41, 0, 0},
+ {"popl", pop_insn, 23, SUF_L, 0, 0, 0, NOT_64, CPU_386, 0, 0},
+ {"fisttpll", fildstp_insn, 4, SUF_Q, 0x07, 0, 0, 0, CPU_SSE3, 0, 0},
+ {"vaddsubpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0xD0, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmadd132ps", vfma_ps_insn, 2, SUF_Z, 0x98, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"blcfill", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x01, 0x01, 0, 0, CPU_386, CPU_TBM, 0},
+ {"vandnpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x55, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sbbb", arith_insn, 22, SUF_B, 0x18, 0x03, 0, 0, 0, 0, 0},
+ {"vcmpfalseps", ssecmp_128_insn, 3, SUF_Z, 0x0B, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"popcnt", cnt_insn, 3, SUF_Z, 0xB8, 0, 0, 0, CPU_SSE42, 0, 0},
+ {"vpcomnequd", vpcom_insn, 1, SUF_Z, 0xEE, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"adcq", arith_insn, 22, SUF_Q, 0x10, 0x02, 0, ONLY_64, 0, 0, 0},
+ {"vpcomequw", vpcom_insn, 1, SUF_Z, 0xED, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"prefetcht1", twobytemem_insn, 1, SUF_Z, 0x02, 0x0F, 0x18, 0, CPU_P3, 0, 0},
+ {"movdqa", movau_insn, 6, SUF_Z, 0x66, 0x6F, 0x10, 0, CPU_SSE2, 0, 0},
+ {"vmovq", vmovq_insn, 5, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpxchg16b", cmpxchg16b_insn, 1, SUF_Z, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"smovq", onebyte_insn, 1, SUF_Z, 0xA5, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"fildq", fildstp_insn, 4, SUF_Q, 0x00, 0x02, 0x05, 0, CPU_FPU, 0, 0},
+ {"ficoml", fiarith_insn, 2, SUF_L, 0x02, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"cmovae", cmovcc_insn, 3, SUF_Z, 0x03, 0, 0, 0, CPU_686, 0, 0},
+ {"vaddsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x58, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movb", mov_insn, 69, SUF_B, 0, 0, 0, 0, 0, 0, 0},
+ {"fist", fiarith_insn, 2, SUF_Z, 0x02, 0xDB, 0, 0, CPU_FPU, 0, 0},
+ {"vpcomb", vpcom_imm_insn, 1, SUF_Z, 0xCC, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpneq_oqss", ssecmp_32_insn, 4, SUF_Z, 0x0C, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"xorpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x57, 0, 0, CPU_SSE2, 0, 0},
+ {"cmpsd", cmpsd_insn, 5, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"movabs", movabs_insn, 9, SUF_Z, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"jrcxz", jcxz_insn, 2, SUF_Z, 0x40, 0, 0, ONLY_64, 0, 0, 0},
+ {"vmovhpd", movhlp_insn, 3, SUF_Z, 0x66, 0x16, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovpq", cmovcc_insn, 3, SUF_Q, 0x0A, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"vpsubw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xF9, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"smovl", onebyte_insn, 1, SUF_Z, 0xA5, 0x20, 0, 0, CPU_386, 0, 0},
+ {"and", arith_insn, 22, SUF_Z, 0x20, 0x04, 0, 0, 0, 0, 0},
+ {"andw", arith_insn, 22, SUF_W, 0x20, 0x04, 0, 0, 0, 0, 0},
+ {"cmpleps", ssecmp_128_insn, 3, SUF_Z, 0x02, 0, 0, 0, CPU_SSE, 0, 0},
+ {"vpmovzxdq", sse4m64_insn, 4, SUF_Z, 0x35, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"subss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5C, 0, 0, CPU_SSE, 0, 0},
+ {"vpcomtrueq", vpcom_insn, 1, SUF_Z, 0xCF, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"fldl2e", twobyte_insn, 1, SUF_Z, 0xD9, 0xEA, 0, 0, CPU_FPU, 0, 0},
+ {"negw", f6_insn, 4, SUF_W, 0x03, 0, 0, 0, 0, 0, 0},
+ {"fidivl", fiarith_insn, 2, SUF_L, 0x06, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"setnc", setcc_insn, 1, SUF_Z, 0x03, 0, 0, 0, CPU_386, 0, 0},
+ {"clts", twobyte_insn, 1, SUF_Z, 0x0F, 0x06, 0, 0, CPU_286, CPU_Priv, 0},
+ {"vcmpgtps", ssecmp_128_insn, 3, SUF_Z, 0x0E, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setnl", setcc_insn, 1, SUF_Z, 0x0D, 0, 0, 0, CPU_386, 0, 0},
+ {"vphaddd", ssse3_insn, 5, SUF_Z, 0x02, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomneub", vpcom_insn, 1, SUF_Z, 0xEC, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"cmp", arith_insn, 22, SUF_Z, 0x38, 0x07, 0, 0, 0, 0, 0},
+ {"fstsww", fstsw_insn, 2, SUF_W, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"cmpordpd", ssecmp_128_insn, 3, SUF_Z, 0x07, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"punpckhbw", mmxsse2_insn, 2, SUF_Z, 0x68, 0, 0, 0, CPU_MMX, 0, 0},
+ {"svts", cyrixsmm_insn, 1, SUF_Z, 0x7C, 0, 0, 0, CPU_486, CPU_Cyrix, CPU_SMM},
+ {"cmpq", arith_insn, 22, SUF_Q, 0x38, 0x07, 0, ONLY_64, 0, 0, 0},
+ {"cmovbq", cmovcc_insn, 3, SUF_Q, 0x02, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"ficomp", fiarith_insn, 2, SUF_Z, 0x03, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"vmmcall", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xD9, 0, CPU_SVM, 0, 0},
+ {"cqo", onebyte_insn, 1, SUF_Z, 0x99, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"vcmpnlepd", ssecmp_128_insn, 3, SUF_Z, 0x06, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setnb", setcc_insn, 1, SUF_Z, 0x03, 0, 0, 0, CPU_386, 0, 0},
+ {"vpsllvd", vpshiftv_vexw0_avx2_insn, 2, SUF_Z, 0x47, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vcmplt_oqpd", ssecmp_128_insn, 3, SUF_Z, 0x11, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pextrw", pextrw_insn, 7, SUF_Z, 0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"loopzl", loopl_insn, 4, SUF_Z, 0x01, 0x20, 0, 0, 0, 0, 0},
+ {"retq", retnf_insn, 6, SUF_Z, 0xC2, 0, 0, ONLY_64, 0, 0, 0},
+ {"vcmpordsd", ssecmp_64_insn, 4, SUF_Z, 0x07, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"seteb", setcc_insn, 1, SUF_B, 0x04, 0, 0, 0, CPU_386, 0, 0},
+ {"vmxoff", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xC4, 0, CPU_P4, 0, 0},
+ {"pfcmpeq", now3d_insn, 1, SUF_Z, 0xB0, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"pmovsxbq", sse4m16_insn, 4, SUF_Z, 0x22, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vfnmadd231ss", vfma_ss_insn, 2, SUF_Z, 0xBD, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"loopel", loopl_insn, 4, SUF_Z, 0x01, 0x20, 0, 0, 0, 0, 0},
+ {"pause", onebyte_prefix_insn, 1, SUF_Z, 0xF3, 0x90, 0, 0, CPU_P4, 0, 0},
+ {"addps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x58, 0, 0, CPU_SSE, 0, 0},
+ {"vcmpfalse_ossd", ssecmp_64_insn, 4, SUF_Z, 0x1B, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rcr", shift_insn, 16, SUF_Z, 0x03, 0, 0, 0, 0, 0, 0},
+ {"vfmadd213pd", vfma_pd_insn, 2, SUF_Z, 0xA8, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"xchg", xchg_insn, 16, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"ucomiss", xmm_xmm32_insn, 4, SUF_Z, 0x00, 0x2E, 0, 0, CPU_SSE, 0, 0},
+ {"popq", pop_insn, 23, SUF_Q, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"lfsq", lfgss_insn, 3, SUF_Q, 0xB4, 0, 0, ONLY_64, CPU_386, 0, 0},
+ {"vcmpneq_usss", ssecmp_32_insn, 4, SUF_Z, 0x14, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"crc32w", crc32_insn, 5, SUF_W, 0, 0, 0, 0, CPU_386, CPU_SSE42, 0},
+ {"setngeb", setcc_insn, 1, SUF_B, 0x0C, 0, 0, 0, CPU_386, 0, 0},
+ {"vpalignr", sse4imm_256avx2_insn, 4, SUF_Z, 0x0F, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomtrueuq", vpcom_insn, 1, SUF_Z, 0xEF, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"pinsrb", pinsrb_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"movshdup", xmm_xmm128_insn, 2, SUF_Z, 0xF3, 0x16, 0, 0, CPU_SSE3, 0, 0},
+ {"cmovll", cmovcc_insn, 3, SUF_L, 0x0C, 0, 0, 0, CPU_686, 0, 0},
+ {"vpextrd", pextrd_insn, 1, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lgdtl", twobytemem_insn, 1, SUF_L, 0x02, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"vpblendvb", avx2_sse4xmm0_insn, 2, SUF_Z, 0x4C, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"setlb", setcc_insn, 1, SUF_B, 0x0C, 0, 0, 0, CPU_386, 0, 0},
+ {"vfmsubadd213ps", vfma_ps_insn, 2, SUF_Z, 0xA7, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"unpckhpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x15, 0, 0, CPU_SSE2, 0, 0},
+ {"vpcomfalseud", vpcom_insn, 1, SUF_Z, 0xEE, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"cmovnlq", cmovcc_insn, 3, SUF_Q, 0x0D, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"cmovge", cmovcc_insn, 3, SUF_Z, 0x0D, 0, 0, 0, CPU_686, 0, 0},
+ {"movabsb", movabs_insn, 9, SUF_B, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"popa", onebyte_insn, 1, SUF_Z, 0x61, 0x00, 0, NOT_64, CPU_186, 0, 0},
+ {"invvpid", eptvpid_insn, 2, SUF_Z, 0x01, 0, 0, 0, CPU_386, CPU_EPTVPID, 0},
+ {"vpcomneud", vpcom_insn, 1, SUF_Z, 0xEE, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"blsrq", vex_gpr_ndd_rm_0F38_regext_insn, 2, SUF_Q, 0x00, 0xF3, 0x01, ONLY_64|ONLY_AVX, CPU_BMI1, 0, 0},
+ {"ljmpl", ljmpcall_insn, 7, SUF_L, 0x05, 0xEA, 0, 0, CPU_386, 0, 0},
+ {"movzx", movszx_insn, 5, SUF_Z, 0xB6, 0, 0, 0, CPU_386, 0, 0},
+ {"pi2fd", now3d_insn, 1, SUF_Z, 0x0D, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"setng", setcc_insn, 1, SUF_Z, 0x0E, 0, 0, 0, CPU_386, 0, 0},
+ {"vpcomfalsed", vpcom_insn, 1, SUF_Z, 0xCE, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"vpabsb", avx2_ssse3_2op_insn, 2, SUF_Z, 0x1C, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpgesd", ssecmp_64_insn, 4, SUF_Z, 0x0D, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmaddsd", fma_128_m64_insn, 3, SUF_Z, 0x7B, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"rdgsbase", fs_gs_base_insn, 2, SUF_Z, 0x01, 0, 0, ONLY_64, CPU_FSGSBASE, 0, 0},
+ {"testl", test_insn, 20, SUF_L, 0, 0, 0, 0, CPU_386, 0, 0},
+ {"vsubsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"shrxl", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_L, 0xF2, 0x38, 0xF7, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"enter", enter_insn, 3, SUF_Z, 0, 0, 0, 0, CPU_186, 0, 0},
+ {"vpmacsdqh", vpma_insn, 1, SUF_Z, 0x9F, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vfnmadd213ss", vfma_ss_insn, 2, SUF_Z, 0xAD, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"setaeb", setcc_insn, 1, SUF_B, 0x03, 0, 0, 0, CPU_386, 0, 0},
+ {"vpgatherdq", gather_64x_64x_insn, 2, SUF_Z, 0x90, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"cmpxchg8b", cmpxchg8b_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_586, 0, 0},
+ {"cvttps2pi", cvt_mm_xmm64_insn, 2, SUF_Z, 0x2C, 0, 0, 0, CPU_SSE, 0, 0},
+ {"pmovmskb", pmovmskb_insn, 6, SUF_Z, 0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"fdivp", farithp_insn, 3, SUF_Z, 0xF0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vcmpnle_uqsd", ssecmp_64_insn, 4, SUF_Z, 0x16, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cvtsd2si", cvt_rx_xmm64_insn, 4, SUF_Z, 0xF2, 0x2D, 0, 0, CPU_386, CPU_SSE2, 0},
+ {"vpcomgeq", vpcom_insn, 1, SUF_Z, 0xCF, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"vfnmadd132ss", vfma_ss_insn, 2, SUF_Z, 0x9D, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpmacssdql", vpma_insn, 1, SUF_Z, 0x87, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpunpcklqdq", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x6C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sysenter", twobyte_insn, 1, SUF_Z, 0x0F, 0x34, 0, NOT_64, CPU_686, 0, 0},
+ {"popw", pop_insn, 23, SUF_W, 0, 0, 0, 0, 0, 0, 0},
+ {"lodsw", onebyte_insn, 1, SUF_Z, 0xAD, 0x10, 0, 0, 0, 0, 0},
+ {"vcmpgt_oqps", ssecmp_128_insn, 3, SUF_Z, 0x1E, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmovmskbl", pmovmskb_insn, 6, SUF_L, 0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"pinsrq", pinsrq_insn, 2, SUF_Z, 0, 0, 0, ONLY_64, CPU_SSE41, 0, 0},
+ {"movsl", onebyte_insn, 1, SUF_Z, 0xA5, 0x20, 0, 0, CPU_386, 0, 0},
+ {"vcmptrue_usps", ssecmp_128_insn, 3, SUF_Z, 0x1F, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"addr64", NULL, X86_ADDRSIZE>>8, 0x40, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"fsin", twobyte_insn, 1, SUF_Z, 0xD9, 0xFE, 0, 0, CPU_286, CPU_FPU, 0},
+ {"adoxl", vex_gpr_ndd_rm_0F38_insn, 2, SUF_L, 0xF3, 0xF6, 0, 0, CPU_ADX, 0, 0},
+ {"vpcomnequq", vpcom_insn, 1, SUF_Z, 0xEF, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"pfmax", now3d_insn, 1, SUF_Z, 0xA4, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"pfcmpge", now3d_insn, 1, SUF_Z, 0x90, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"loopnz", loop_insn, 8, SUF_Z, 0x00, 0, 0, 0, 0, 0, 0},
+ {"vcmpnle_uqss", ssecmp_32_insn, 4, SUF_Z, 0x16, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setpeb", setcc_insn, 1, SUF_B, 0x0A, 0, 0, 0, CPU_386, 0, 0},
+ {"vextractps", extractps_insn, 2, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jc", jcc_insn, 9, SUF_Z, 0x02, 0, 0, 0, 0, 0, 0},
+ {"vpcomltq", vpcom_insn, 1, SUF_Z, 0xCF, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"vfmsubsd", fma_128_m64_insn, 3, SUF_Z, 0x6F, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"movmskpd", movmsk_insn, 4, SUF_Z, 0x66, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"vfmsubadd231ps", vfma_ps_insn, 2, SUF_Z, 0xB7, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vcmpeq_usps", ssecmp_128_insn, 3, SUF_Z, 0x18, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fistpl", fildstp_insn, 4, SUF_L, 0x03, 0x02, 0x07, 0, CPU_FPU, 0, 0},
+ {"fistpll", fbldstp_insn, 1, SUF_Z, 0x07, 0, 0, 0, CPU_FPU, 0, 0},
+ {"jnbe", jcc_insn, 9, SUF_Z, 0x07, 0, 0, 0, 0, 0, 0},
+ {"pmovsxwq", sse4m32_insn, 4, SUF_Z, 0x24, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vpcomgtub", vpcom_insn, 1, SUF_Z, 0xEC, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"unpcklps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x14, 0, 0, CPU_SSE, 0, 0},
+ {"btr", bittest_insn, 6, SUF_Z, 0xB3, 0x06, 0, 0, CPU_386, 0, 0},
+ {"cmovnsw", cmovcc_insn, 3, SUF_W, 0x09, 0, 0, 0, CPU_686, 0, 0},
+ {"sbbl", arith_insn, 22, SUF_L, 0x18, 0x03, 0, 0, CPU_386, 0, 0},
+ {"idivq", div_insn, 8, SUF_Q, 0x07, 0, 0, ONLY_64, 0, 0, 0},
+ {"strw", str_insn, 4, SUF_W, 0, 0, 0, 0, CPU_286, CPU_Prot, 0},
+ {"psignw", ssse3_insn, 5, SUF_Z, 0x09, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"vcvtsi2sdq", cvt_xmm_rmx_insn, 6, SUF_Q, 0xF2, 0x2A, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setgb", setcc_insn, 1, SUF_B, 0x0F, 0, 0, 0, CPU_386, 0, 0},
+ {"vpextrw", pextrw_insn, 7, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmoval", cmovcc_insn, 3, SUF_L, 0x07, 0, 0, 0, CPU_686, 0, 0},
+ {"vpextrwq", pextrw_insn, 7, SUF_Q, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sldtl", sldtmsw_insn, 6, SUF_L, 0x00, 0x00, 0, 0, CPU_386, 0, 0},
+ {"vcmpunordss", ssecmp_32_insn, 4, SUF_Z, 0x03, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"aesenc", aes_insn, 2, SUF_Z, 0x38, 0xDC, 0, 0, CPU_AVX, 0, 0},
+ {"pmaddubsw", ssse3_insn, 5, SUF_Z, 0x04, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"cvtsi2ss", cvt_xmm_rmx_insn, 6, SUF_Z, 0xF3, 0x2A, 0, 0, CPU_386, CPU_SSE, 0},
+ {"vphaddw", ssse3_insn, 5, SUF_Z, 0x01, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"repnz", NULL, X86_LOCKREP>>8, 0xF2, 0, 0, 0, 0, 0, 0, 0},
+ {"fidivrl", fiarith_insn, 2, SUF_L, 0x07, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"fsqrt", twobyte_insn, 1, SUF_Z, 0xD9, 0xFA, 0, 0, CPU_FPU, 0, 0},
+ {"fsetpm", twobyte_insn, 1, SUF_Z, 0xDB, 0xE4, 0, 0, CPU_286, CPU_FPU, CPU_Obs},
+ {"insw", onebyte_insn, 1, SUF_Z, 0x6D, 0x10, 0, 0, 0, 0, 0},
+ {"setbeb", setcc_insn, 1, SUF_B, 0x06, 0, 0, 0, CPU_386, 0, 0},
+ {"vpsubb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xF8, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rex64xy", NULL, X86_REX>>8, 0x4E, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"vpsrldq", pslrldq_insn, 4, SUF_Z, 0x03, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"xorq", arith_insn, 22, SUF_Q, 0x30, 0x06, 0, ONLY_64, 0, 0, 0},
+ {"punpcklbw", mmxsse2_insn, 2, SUF_Z, 0x60, 0, 0, 0, CPU_MMX, 0, 0},
+ {"rdtscp", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xF9, 0, CPU_686, CPU_AMD, CPU_Priv},
+ {"lfence", threebyte_insn, 1, SUF_Z, 0x0F, 0xAE, 0xE8, 0, CPU_P3, 0, 0},
+ {"vpcmpestri", sse4pcmpstr_insn, 1, SUF_Z, 0x61, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"divpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x5E, 0, 0, CPU_SSE2, 0, 0},
+ {"vcmpss", xmm_xmm32_imm_insn, 4, SUF_Z, 0xF3, 0xC2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fidivs", fiarith_insn, 2, SUF_S, 0x06, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"pcmpeqq", sse4_insn, 2, SUF_Z, 0x29, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"setnbe", setcc_insn, 1, SUF_Z, 0x07, 0, 0, 0, CPU_386, 0, 0},
+ {"pshufb", ssse3_insn, 5, SUF_Z, 0x00, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"cmovgeq", cmovcc_insn, 3, SUF_Q, 0x0D, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"vpaddq", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xD4, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"clgi", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xDD, 0, CPU_SVM, 0, 0},
+ {"rcpps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x53, 0, 0, CPU_SSE, 0, 0},
+ {"cmovno", cmovcc_insn, 3, SUF_Z, 0x01, 0, 0, 0, CPU_686, 0, 0},
+ {"addss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x58, 0, 0, CPU_SSE, 0, 0},
+ {"vcmpneqss", ssecmp_32_insn, 4, SUF_Z, 0x04, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pavgusb", now3d_insn, 1, SUF_Z, 0xBF, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"vfmadd213ps", vfma_ps_insn, 2, SUF_Z, 0xA8, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpcomneqw", vpcom_insn, 1, SUF_Z, 0xCD, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"vpmaxsb", ssse3_insn, 5, SUF_Z, 0x3C, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pminsw", mmxsse2_insn, 2, SUF_Z, 0xEA, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vcmpnge_uqpd", ssecmp_128_insn, 3, SUF_Z, 0x19, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomtrueud", vpcom_insn, 1, SUF_Z, 0xEE, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"setpe", setcc_insn, 1, SUF_Z, 0x0A, 0, 0, 0, CPU_386, 0, 0},
+ {"cmovnlw", cmovcc_insn, 3, SUF_W, 0x0D, 0, 0, 0, CPU_686, 0, 0},
+ {"cbw", onebyte_insn, 1, SUF_Z, 0x98, 0x10, 0, 0, 0, 0, 0},
+ {"vcmpge_oqss", ssecmp_32_insn, 4, SUF_Z, 0x1D, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jpo", jcc_insn, 9, SUF_Z, 0x0B, 0, 0, 0, 0, 0, 0},
+ {"leavel", onebyte_insn, 1, SUF_Z, 0xC9, 0x00, 0x40, 0, CPU_186, 0, 0},
+ {"mpsadbw", sse4imm_insn, 2, SUF_Z, 0x42, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vcvttsd2si", cvt_rx_xmm64_insn, 4, SUF_Z, 0xF2, 0x2C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vminps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x5D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpnleps", ssecmp_128_insn, 3, SUF_Z, 0x06, 0, 0, 0, CPU_SSE, 0, 0},
+ {"blendvpd", sse4xmm0_insn, 2, SUF_Z, 0x15, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vaddss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x58, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomltuw", vpcom_insn, 1, SUF_Z, 0xED, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"orw", arith_insn, 22, SUF_W, 0x08, 0x01, 0, 0, 0, 0, 0},
+ {"adword", NULL, X86_ADDRSIZE>>8, 0x20, 0, 0, 0, 0, 0, 0, 0},
+ {"vprotb", vprot_insn, 3, SUF_Z, 0x00, 0, 0, 0, CPU_XOP, 0, 0},
+ {"pclmulhqhqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x11, 0, 0, 0, CPU_AVX, 0, 0},
+ {"shrdq", shlrd_insn, 9, SUF_Q, 0xAC, 0, 0, ONLY_64, CPU_386, 0, 0},
+ {"vminss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpmaxub", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xDE, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomltud", vpcom_insn, 1, SUF_Z, 0xEE, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"vpaddusw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xDD, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movsq", onebyte_insn, 1, SUF_Z, 0xA5, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"subsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5C, 0, 0, CPU_SSE2, 0, 0},
+ {"vfmaddsubpd", fma_128_256_insn, 4, SUF_Z, 0x5D, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"cvtdq2ps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x5B, 0, 0, CPU_SSE2, 0, 0},
+ {"prefetch", twobytemem_insn, 1, SUF_Z, 0x00, 0x0F, 0x0D, 0, CPU_3DNow, 0, 0},
+ {"vaesenc", aes_insn, 2, SUF_Z, 0x38, 0xDC, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"shl", shift_insn, 16, SUF_Z, 0x04, 0, 0, 0, 0, 0, 0},
+ {"vcmpunord_spd", ssecmp_128_insn, 3, SUF_Z, 0x13, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"bsfw", bsfr_insn, 3, SUF_W, 0xBC, 0, 0, 0, CPU_386, 0, 0},
+ {"bswap", bswap_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_486, 0, 0},
+ {"vfmadd231sd", vfma_sd_insn, 2, SUF_Z, 0xB9, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"fistps", fildstp_insn, 4, SUF_S, 0x03, 0x02, 0x07, 0, CPU_FPU, 0, 0},
+ {"fdivs", farith_insn, 7, SUF_S, 0xF8, 0xF0, 0x06, 0, CPU_FPU, 0, 0},
+ {"pextrq", pextrq_insn, 1, SUF_Z, 0, 0, 0, ONLY_64, CPU_SSE41, 0, 0},
+ {"adcl", arith_insn, 22, SUF_L, 0x10, 0x02, 0, 0, CPU_386, 0, 0},
+ {"vpmacsdql", vpma_insn, 1, SUF_Z, 0x97, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpcomeqq", vpcom_insn, 1, SUF_Z, 0xCF, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"tzmskq", xop_gpr_reg_rm_09_insn, 2, SUF_Q, 0x01, 0x04, 0, ONLY_64, CPU_TBM, 0, 0},
+ {"rcl", shift_insn, 16, SUF_Z, 0x02, 0, 0, 0, 0, 0, 0},
+ {"vsqrtsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x51, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cdqe", onebyte_insn, 1, SUF_Z, 0x98, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"negq", f6_insn, 4, SUF_Q, 0x03, 0, 0, ONLY_64, 0, 0, 0},
+ {"pextrb", pextrb_insn, 3, SUF_Z, 0, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"movzbq", movszx_insn, 5, SUF_B, 0xB6, 0, 0, ONLY_64, CPU_386, 0, 0},
+ {"vcmpngtps", ssecmp_128_insn, 3, SUF_Z, 0x0A, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomgeb", vpcom_insn, 1, SUF_Z, 0xCC, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"lea", lea_insn, 3, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"invd", twobyte_insn, 1, SUF_Z, 0x0F, 0x08, 0, 0, CPU_486, CPU_Priv, 0},
+ {"sarxl", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_L, 0xF3, 0x38, 0xF7, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"movdqu", movau_insn, 6, SUF_Z, 0xF3, 0x6F, 0x10, 0, CPU_SSE2, 0, 0},
+ {"vdivsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5E, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpneqpd", ssecmp_128_insn, 3, SUF_Z, 0x04, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"xcryptecb", padlock_insn, 1, SUF_Z, 0xC8, 0xF3, 0xA7, 0, CPU_PadLock, 0, 0},
+ {"shll", shift_insn, 16, SUF_L, 0x04, 0, 0, 0, CPU_386, 0, 0},
+ {"int", int_insn, 1, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"wrfsbase", fs_gs_base_insn, 2, SUF_Z, 0x02, 0, 0, ONLY_64, CPU_FSGSBASE, 0, 0},
+ {"shufps", xmm_xmm128_imm_insn, 1, SUF_Z, 0x00, 0xC6, 0, 0, CPU_SSE, 0, 0},
+ {"subpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x5C, 0, 0, CPU_SSE2, 0, 0},
+ {"vcvtpd2psy", avx_cvt_xmm128_y_insn, 1, SUF_Z, 0x66, 0x5A, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovnew", cmovcc_insn, 3, SUF_W, 0x05, 0, 0, 0, CPU_686, 0, 0},
+ {"crc32", crc32_insn, 5, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_SSE42, 0},
+ {"vmovapd", movau_insn, 6, SUF_Z, 0x66, 0x28, 0x01, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rdrand", rdrand_insn, 3, SUF_Z, 0x06, 0, 0, 0, CPU_RDRAND, 0, 0},
+ {"cmovnbew", cmovcc_insn, 3, SUF_W, 0x07, 0, 0, 0, CPU_686, 0, 0},
+ {"invvpidl", eptvpid_insn, 2, SUF_L, 0x01, 0, 0, NOT_64, CPU_386, CPU_EPTVPID, 0},
+ {"ljmp", ljmpcall_insn, 7, SUF_Z, 0x05, 0xEA, 0, 0, 0, 0, 0},
+ {"vcmpeqpd", ssecmp_128_insn, 3, SUF_Z, 0x00, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"popfl", onebyte_insn, 1, SUF_Z, 0x9D, 0x20, 0, NOT_64, CPU_386, 0, 0},
+ {"wrgsbase", fs_gs_base_insn, 2, SUF_Z, 0x03, 0, 0, ONLY_64, CPU_FSGSBASE, 0, 0},
+ {"lodsb", onebyte_insn, 1, SUF_Z, 0xAC, 0x00, 0, 0, 0, 0, 0},
+ {"vcmpgess", ssecmp_32_insn, 4, SUF_Z, 0x0D, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"aesenclast", aes_insn, 2, SUF_Z, 0x38, 0xDD, 0, 0, CPU_AVX, 0, 0},
+ {"cmovel", cmovcc_insn, 3, SUF_L, 0x04, 0, 0, 0, CPU_686, 0, 0},
+ {"vpsignd", ssse3_insn, 5, SUF_Z, 0x0A, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"stosb", onebyte_insn, 1, SUF_Z, 0xAA, 0x00, 0, 0, 0, 0, 0},
+ {"smovb", onebyte_insn, 1, SUF_Z, 0xA4, 0x00, 0, 0, 0, 0, 0},
+ {"vcmpeqss", ssecmp_32_insn, 4, SUF_Z, 0x00, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpandn", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xDF, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmovmskpsl", movmsk_insn, 4, SUF_L, 0x00, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmovntps", movnt_insn, 2, SUF_Z, 0x00, 0x2B, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtpd2psx", avx_cvt_xmm128_x_insn, 1, SUF_Z, 0x66, 0x5A, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpordps", ssecmp_128_insn, 3, SUF_Z, 0x07, 0, 0, 0, CPU_SSE, 0, 0},
+ {"vpaddd", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xFE, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fptan", twobyte_insn, 1, SUF_Z, 0xD9, 0xF2, 0, 0, CPU_FPU, 0, 0},
+ {"shldw", shlrd_insn, 9, SUF_W, 0xA4, 0, 0, 0, CPU_386, 0, 0},
+ {"outsl", onebyte_insn, 1, SUF_Z, 0x6F, 0x20, 0, 0, CPU_386, 0, 0},
+ {"vmovmskpsq", movmsk_insn, 4, SUF_Q, 0x00, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fldcw", fldnstcw_insn, 1, SUF_Z, 0x05, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vcmpord_ssd", ssecmp_64_insn, 4, SUF_Z, 0x17, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmsub231sd", vfma_sd_insn, 2, SUF_Z, 0xBF, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"pmullw", mmxsse2_insn, 2, SUF_Z, 0xD5, 0, 0, 0, CPU_MMX, 0, 0},
+ {"jno", jcc_insn, 9, SUF_Z, 0x01, 0, 0, 0, 0, 0, 0},
+ {"vprotq", vprot_insn, 3, SUF_Z, 0x03, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpneq_ospd", ssecmp_128_insn, 3, SUF_Z, 0x1C, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sarb", shift_insn, 16, SUF_B, 0x07, 0, 0, 0, 0, 0, 0},
+ {"aaa", onebyte_insn, 1, SUF_Z, 0x37, 0, 0, NOT_64, 0, 0, 0},
+ {"psubd", mmxsse2_insn, 2, SUF_Z, 0xFA, 0, 0, 0, CPU_MMX, 0, 0},
+ {"cmovpew", cmovcc_insn, 3, SUF_W, 0x0A, 0, 0, 0, CPU_686, 0, 0},
+ {"blci", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x02, 0x06, 0, 0, CPU_386, CPU_TBM, 0},
+ {"cmpnltsd", ssecmp_64_insn, 4, SUF_Z, 0x05, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"rex64x", NULL, X86_REX>>8, 0x4C, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"blsr", vex_gpr_ndd_rm_0F38_regext_insn, 2, SUF_Z, 0x00, 0xF3, 0x01, ONLY_AVX, CPU_BMI1, 0, 0},
+ {"vaeskeygenassist", aes_imm_insn, 1, SUF_Z, 0x3A, 0xDF, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpnltss", ssecmp_32_insn, 4, SUF_Z, 0x05, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"cwde", onebyte_insn, 1, SUF_Z, 0x98, 0x20, 0, 0, CPU_386, 0, 0},
+ {"fcmovne", fcmovcc_insn, 1, SUF_Z, 0xDB, 0xC8, 0, 0, CPU_686, CPU_FPU, 0},
+ {"sscab", onebyte_insn, 1, SUF_Z, 0xAE, 0x00, 0, 0, 0, 0, 0},
+ {"vphaddbq", vphaddsub_insn, 1, SUF_Z, 0xC3, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vcvttss2sil", cvt_rx_xmm32_insn, 4, SUF_L, 0xF3, 0x2C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"roundsd", sse4m64imm_insn, 4, SUF_Z, 0x0B, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"pfacc", now3d_insn, 1, SUF_Z, 0xAE, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"fsubl", farith_insn, 7, SUF_L, 0xE8, 0xE0, 0x04, 0, CPU_FPU, 0, 0},
+ {"invlpg", twobytemem_insn, 1, SUF_Z, 0x07, 0x0F, 0x01, 0, CPU_486, CPU_Priv, 0},
+ {"pextl", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_L, 0xF3, 0x38, 0xF5, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"fldenvl", onebytemem_insn, 1, SUF_L, 0x04, 0xD9, 0, 0, CPU_FPU, 0, 0},
+ {"lretq", retnf_insn, 6, SUF_Q, 0xCA, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"addr16", NULL, X86_ADDRSIZE>>8, 0x10, 0, 0, 0, 0, 0, 0, 0},
+ {"cmovncl", cmovcc_insn, 3, SUF_L, 0x03, 0, 0, 0, CPU_686, 0, 0},
+ {"movzbw", movszx_insn, 5, SUF_B, 0xB6, 0, 0, 0, CPU_386, 0, 0},
+ {"pmvlzb", cyrixmmx_insn, 1, SUF_Z, 0x5B, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"boundw", bound_insn, 2, SUF_W, 0, 0, 0, NOT_64, CPU_186, 0, 0},
+ {"vroundsd", sse4m64imm_insn, 4, SUF_Z, 0x0B, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"loopz", loop_insn, 8, SUF_Z, 0x01, 0, 0, 0, 0, 0, 0},
+ {"roundpd", sse4imm_insn, 2, SUF_Z, 0x09, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"sfence", threebyte_insn, 1, SUF_Z, 0x0F, 0xAE, 0xF8, 0, CPU_P3, 0, 0},
+ {"vpcomgew", vpcom_insn, 1, SUF_Z, 0xCD, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"vpcmpistrm", sse4pcmpstr_insn, 1, SUF_Z, 0x62, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"repz", NULL, X86_LOCKREP>>8, 0xF3, 0, 0, 0, 0, 0, 0, 0},
+ {"iretq", onebyte_insn, 1, SUF_Z, 0xCF, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"pclmullqhqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x10, 0, 0, 0, CPU_AVX, 0, 0},
+ {"vcmplt_oqss", ssecmp_32_insn, 4, SUF_Z, 0x11, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpeq_osps", ssecmp_128_insn, 3, SUF_Z, 0x10, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpw", arith_insn, 22, SUF_W, 0x38, 0x07, 0, 0, 0, 0, 0},
+ {"adox", vex_gpr_ndd_rm_0F38_insn, 2, SUF_Z, 0xF3, 0xF6, 0, 0, CPU_ADX, 0, 0},
+ {"rexyz", NULL, X86_REX>>8, 0x43, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"rorxq", vex_gpr_reg_rm_0F_imm8_insn, 2, SUF_Q, 0xF2, 0x3A, 0xF0, ONLY_64|ONLY_AVX, CPU_BMI2, 0, 0},
+ {"movsxb", movszx_insn, 5, SUF_B, 0xBE, 0, 0, 0, CPU_386, 0, 0},
+ {"paddsw", mmxsse2_insn, 2, SUF_Z, 0xED, 0, 0, 0, CPU_MMX, 0, 0},
+ {"lldtw", prot286_insn, 1, SUF_W, 0x02, 0x00, 0, 0, CPU_286, CPU_Priv, CPU_Prot},
+ {"vpcomneuw", vpcom_insn, 1, SUF_Z, 0xED, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpnlesd", ssecmp_64_insn, 4, SUF_Z, 0x06, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfrczss", vfrczss_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_XOP, 0, 0},
+ {"movw", mov_insn, 69, SUF_W, 0, 0, 0, 0, 0, 0, 0},
+ {"crc32q", crc32_insn, 5, SUF_Q, 0, 0, 0, ONLY_64, CPU_SSE42, 0, 0},
+ {"vextracti128", vextractif128_insn, 1, SUF_Z, 0x39, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"subps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x5C, 0, 0, CPU_SSE, 0, 0},
+ {"inb", in_insn, 12, SUF_B, 0, 0, 0, 0, 0, 0, 0},
+ {"vfnmsub231ps", vfma_ps_insn, 2, SUF_Z, 0xBE, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vphaddubw", vphaddsub_insn, 1, SUF_Z, 0xD1, 0, 0, 0, CPU_XOP, 0, 0},
+ {"pmachriw", pmachriw_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"vmpsadbw", sse4imm_256avx2_insn, 4, SUF_Z, 0x42, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovngew", cmovcc_insn, 3, SUF_W, 0x0C, 0, 0, 0, CPU_686, 0, 0},
+ {"popcntq", cnt_insn, 3, SUF_Q, 0xB8, 0, 0, ONLY_64, CPU_SSE42, 0, 0},
+ {"insertps", insertps_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"cmpxchgl", cmpxchgxadd_insn, 4, SUF_L, 0xB0, 0, 0, 0, CPU_486, 0, 0},
+ {"vcomiss", avx_xmm_xmm32_insn, 2, SUF_Z, 0x00, 0x2F, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcmpgtd", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"loopzw", loopw_insn, 4, SUF_Z, 0x01, 0x10, 0, NOT_64, 0, 0, 0},
+ {"retw", retnf_insn, 6, SUF_Z, 0xC2, 0x10, 0, 0, 0, 0, 0},
+ {"pavgb", mmxsse2_insn, 2, SUF_Z, 0xE0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"loopnel", loopl_insn, 4, SUF_Z, 0x00, 0x20, 0, 0, 0, 0, 0},
+ {"vpsrld", vpshift_insn, 8, SUF_Z, 0xD2, 0x72, 0x02, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtpd2dqx", avx_cvt_xmm128_x_insn, 1, SUF_Z, 0xF2, 0xE6, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"ficomps", fiarith_insn, 2, SUF_S, 0x03, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"fisttps", fildstp_insn, 4, SUF_S, 0x01, 0x00, 0x01, 0, CPU_SSE3, 0, 0},
+ {"vandpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x54, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"haddpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x7C, 0, 0, CPU_SSE3, 0, 0},
+ {"bsfl", bsfr_insn, 3, SUF_L, 0xBC, 0, 0, 0, CPU_386, 0, 0},
+ {"rolq", shift_insn, 16, SUF_Q, 0x00, 0, 0, ONLY_64, 0, 0, 0},
+ {"vcmpneq_ussd", ssecmp_64_insn, 4, SUF_Z, 0x14, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pinsrwl", pinsrw_insn, 9, SUF_L, 0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"pmovzxwd", sse4m64_insn, 4, SUF_Z, 0x33, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vcmpgt_oqsd", ssecmp_64_insn, 4, SUF_Z, 0x1E, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pslld", pshift_insn, 4, SUF_Z, 0xF2, 0x72, 0x06, 0, CPU_MMX, 0, 0},
+ {"bextr", bextr_insn, 4, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_386, CPU_BMI1, 0},
+ {"movsbl", movszx_insn, 5, SUF_B, 0xBE, 0, 0, 0, CPU_386, 0, 0},
+ {"vpcomuq", vpcom_imm_insn, 1, SUF_Z, 0xEF, 0, 0, 0, CPU_XOP, 0, 0},
+ {"pcmpestrm", sse4pcmpstr_insn, 1, SUF_Z, 0x60, 0, 0, 0, CPU_SSE42, 0, 0},
+ {"pfcmpgt", now3d_insn, 1, SUF_Z, 0xA0, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"ltrw", prot286_insn, 1, SUF_W, 0x03, 0x00, 0, 0, CPU_286, CPU_Priv, CPU_Prot},
+ {"paddusw", mmxsse2_insn, 2, SUF_Z, 0xDD, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vpmacsswd", vpma_insn, 1, SUF_Z, 0x86, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vfnmsubsd", fma_128_m64_insn, 3, SUF_Z, 0x7F, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"loopew", loopw_insn, 4, SUF_Z, 0x01, 0x10, 0, NOT_64, 0, 0, 0},
+ {"vmaskmovdqu", maskmovdqu_insn, 1, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cvtsi2sdq", cvt_xmm_rmx_insn, 6, SUF_Q, 0xF2, 0x2A, 0, ONLY_64, CPU_SSE2, 0, 0},
+ {"fisubs", fiarith_insn, 2, SUF_S, 0x04, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"cmpeqss", ssecmp_32_insn, 4, SUF_Z, 0x00, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"cqto", onebyte_insn, 1, SUF_Z, 0x99, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"vcmpunordpd", ssecmp_128_insn, 3, SUF_Z, 0x03, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setna", setcc_insn, 1, SUF_Z, 0x06, 0, 0, 0, CPU_386, 0, 0},
+ {"cvtdq2pd", xmm_xmm64_insn, 4, SUF_Z, 0xF3, 0xE6, 0, 0, CPU_SSE2, 0, 0},
+ {"andnpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x55, 0, 0, CPU_SSE2, 0, 0},
+ {"vcmpeq_uqps", ssecmp_128_insn, 3, SUF_Z, 0x08, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtsi2ss", cvt_xmm_rmx_insn, 6, SUF_Z, 0xF3, 0x2A, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"psrld", pshift_insn, 4, SUF_Z, 0xD2, 0x72, 0x02, 0, CPU_MMX, 0, 0},
+ {"outl", out_insn, 12, SUF_L, 0, 0, 0, 0, CPU_386, 0, 0},
+ {"vcvttss2siq", cvt_rx_xmm32_insn, 4, SUF_Q, 0xF3, 0x2C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"paddq", mmxsse2_insn, 2, SUF_Z, 0xD4, 0, 0, 0, CPU_MMX, 0, 0},
+ {"cmpneqss", ssecmp_32_insn, 4, SUF_Z, 0x04, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"vfrczsd", vfrczsd_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_XOP, 0, 0},
+ {"xsaveopt64", xsaveopt64_insn, 1, SUF_Z, 0x06, 0x0F, 0xAE, ONLY_64, CPU_XSAVEOPT, 0, 0},
+ {"fnstsww", fnstsw_insn, 2, SUF_W, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vfmaddss", fma_128_m32_insn, 3, SUF_Z, 0x6A, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"fsubs", farith_insn, 7, SUF_S, 0xE8, 0xE0, 0x04, 0, CPU_FPU, 0, 0},
+ {"vpshufd", xmm_xmm128_imm_256avx2_insn, 2, SUF_Z, 0x66, 0x70, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fstpl", fstp_insn, 4, SUF_L, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vcmpeq_ussd", ssecmp_64_insn, 4, SUF_Z, 0x18, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jle", jcc_insn, 9, SUF_Z, 0x0E, 0, 0, 0, 0, 0, 0},
+ {"sidtq", twobytemem_insn, 1, SUF_Q, 0x01, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"vpshlb", amd_vpshift_insn, 2, SUF_Z, 0x94, 0, 0, 0, CPU_XOP, 0, 0},
+ {"pinsrwq", pinsrw_insn, 9, SUF_Q, 0, 0, 0, ONLY_64, CPU_MMX, CPU_P3, 0},
+ {"js", jcc_insn, 9, SUF_Z, 0x08, 0, 0, 0, 0, 0, 0},
+ {"andnq", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_Q, 0x00, 0x38, 0xF2, ONLY_64|ONLY_AVX, CPU_BMI1, 0, 0},
+ {"cmpsl", onebyte_insn, 1, SUF_Z, 0xA7, 0x20, 0, 0, CPU_386, 0, 0},
+ {"vmovlps", movhlp_insn, 3, SUF_Z, 0x00, 0x12, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pabsd", ssse3_insn, 5, SUF_Z, 0x1E, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"vpcomequd", vpcom_insn, 1, SUF_Z, 0xEE, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"salw", shift_insn, 16, SUF_W, 0x04, 0, 0, 0, 0, 0, 0},
+ {"movntss", movntss_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SSE4a, 0, 0},
+ {"movlhps", movhllhps_insn, 2, SUF_Z, 0x16, 0, 0, 0, CPU_SSE, 0, 0},
+ {"vcmpltps", ssecmp_128_insn, 3, SUF_Z, 0x01, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovoq", cmovcc_insn, 3, SUF_Q, 0x00, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"rex64xz", NULL, X86_REX>>8, 0x4D, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"vfmsubadd132ps", vfma_ps_insn, 2, SUF_Z, 0x97, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vcmplt_oqsd", ssecmp_64_insn, 4, SUF_Z, 0x11, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovnzl", cmovcc_insn, 3, SUF_L, 0x05, 0, 0, 0, CPU_686, 0, 0},
+ {"cvttss2sil", cvt_rx_xmm32_insn, 4, SUF_L, 0xF3, 0x2C, 0, 0, CPU_386, CPU_SSE, 0},
+ {"pand", mmxsse2_insn, 2, SUF_Z, 0xDB, 0, 0, 0, CPU_MMX, 0, 0},
+ {"packuswb", mmxsse2_insn, 2, SUF_Z, 0x67, 0, 0, 0, CPU_MMX, 0, 0},
+ {"rcrw", shift_insn, 16, SUF_W, 0x03, 0, 0, 0, 0, 0, 0},
+ {"loadall", twobyte_insn, 1, SUF_Z, 0x0F, 0x07, 0, 0, CPU_386, CPU_Undoc, 0},
+ {"vprotd", vprot_insn, 3, SUF_Z, 0x02, 0, 0, 0, CPU_XOP, 0, 0},
+ {"popcntl", cnt_insn, 3, SUF_L, 0xB8, 0, 0, 0, CPU_SSE42, 0, 0},
+ {"xsave", twobytemem_insn, 1, SUF_Z, 0x04, 0x0F, 0xAE, 0, CPU_386, CPU_XSAVE, 0},
+ {"addq", arith_insn, 22, SUF_Q, 0x00, 0x00, 0, ONLY_64, 0, 0, 0},
+ {"fldlg2", twobyte_insn, 1, SUF_Z, 0xD9, 0xEC, 0, 0, CPU_FPU, 0, 0},
+ {"fwait", onebyte_insn, 1, SUF_Z, 0x9B, 0, 0, 0, CPU_FPU, 0, 0},
+ {"cvtsi2sdl", cvt_xmm_rmx_insn, 6, SUF_L, 0xF2, 0x2A, 0, 0, CPU_SSE2, 0, 0},
+ {"cmovl", cmovcc_insn, 3, SUF_Z, 0x0C, 0, 0, 0, CPU_686, 0, 0},
+ {"rol", shift_insn, 16, SUF_Z, 0x00, 0, 0, 0, 0, 0, 0},
+ {"tzmsk", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x01, 0x04, 0, 0, CPU_386, CPU_TBM, 0},
+ {"loope", loop_insn, 8, SUF_Z, 0x01, 0, 0, 0, 0, 0, 0},
+ {"decl", incdec_insn, 6, SUF_L, 0x48, 0x01, 0, 0, CPU_386, 0, 0},
+ {"shlb", shift_insn, 16, SUF_B, 0x04, 0, 0, 0, 0, 0, 0},
+ {"cmpsw", onebyte_insn, 1, SUF_Z, 0xA7, 0x10, 0, 0, 0, 0, 0},
+ {"inc", incdec_insn, 6, SUF_Z, 0x40, 0x00, 0, 0, 0, 0, 0},
+ {"vpshlw", amd_vpshift_insn, 2, SUF_Z, 0x95, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpcomneqd", vpcom_insn, 1, SUF_Z, 0xCE, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"vunpckhps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x15, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movups", movau_insn, 6, SUF_Z, 0x00, 0x10, 0x01, 0, CPU_SSE, 0, 0},
+ {"smint", twobyte_insn, 1, SUF_Z, 0x0F, 0x38, 0, 0, CPU_686, CPU_Cyrix, 0},
+ {"addsubpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0xD0, 0, 0, CPU_SSE3, 0, 0},
+ {"sha1msg1", intel_SHA1MSG1_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SHA, 0, 0},
+ {"pmovzxdq", sse4m64_insn, 4, SUF_Z, 0x35, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vaddps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x58, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"in", in_insn, 12, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"setnpb", setcc_insn, 1, SUF_B, 0x0B, 0, 0, 0, CPU_386, 0, 0},
+ {"sete", setcc_insn, 1, SUF_Z, 0x04, 0, 0, 0, CPU_386, 0, 0},
+ {"vcmpnlt_uqsd", ssecmp_64_insn, 4, SUF_Z, 0x15, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmsub132sd", vfma_sd_insn, 2, SUF_Z, 0x9B, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"cmovnae", cmovcc_insn, 3, SUF_Z, 0x02, 0, 0, 0, CPU_686, 0, 0},
+ {"xcryptcfb", padlock_insn, 1, SUF_Z, 0xE0, 0xF3, 0xA7, 0, CPU_PadLock, 0, 0},
+ {"vcvtss2siq", cvt_rx_xmm32_insn, 4, SUF_Q, 0xF3, 0x2D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fcmovnb", fcmovcc_insn, 1, SUF_Z, 0xDB, 0xC0, 0, 0, CPU_686, CPU_FPU, 0},
+ {"vfmadd213ss", vfma_ss_insn, 2, SUF_Z, 0xA9, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"pushfw", onebyte_insn, 1, SUF_Z, 0x9C, 0x10, 0x40, 0, 0, 0, 0},
+ {"vcmpless", ssecmp_32_insn, 4, SUF_Z, 0x02, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sidtl", twobytemem_insn, 1, SUF_L, 0x01, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"vpcomfalsew", vpcom_insn, 1, SUF_Z, 0xCD, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"xcryptctr", padlock_insn, 1, SUF_Z, 0xD8, 0xF3, 0xA7, 0, CPU_PadLock, 0, 0},
+ {"fidiv", fiarith_insn, 2, SUF_Z, 0x06, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"cvtpi2pd", cvt_xmm_mm_ss_insn, 1, SUF_Z, 0x66, 0x2A, 0, 0, CPU_SSE2, 0, 0},
+ {"fxrstorq", twobytemem_insn, 1, SUF_Q, 0x01, 0x0F, 0xAE, 0, CPU_686, CPU_FPU, 0},
+ {"aas", onebyte_insn, 1, SUF_Z, 0x3F, 0, 0, NOT_64, 0, 0, 0},
+ {"pfrsqrt", now3d_insn, 1, SUF_Z, 0x97, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"cmovpeq", cmovcc_insn, 3, SUF_Q, 0x0A, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"vaesenclast", aes_insn, 2, SUF_Z, 0x38, 0xDD, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmreadl", vmxmemrd_insn, 2, SUF_L, 0, 0, 0, NOT_64, CPU_P4, 0, 0},
+ {"vpcomub", vpcom_imm_insn, 1, SUF_Z, 0xEC, 0, 0, 0, CPU_XOP, 0, 0},
+ {"movupd", movau_insn, 6, SUF_Z, 0x66, 0x10, 0x01, 0, CPU_SSE2, 0, 0},
+ {"btcw", bittest_insn, 6, SUF_W, 0xBB, 0x07, 0, 0, CPU_386, 0, 0},
+ {"popfq", onebyte_insn, 1, SUF_Z, 0x9D, 0x40, 0x40, ONLY_64, 0, 0, 0},
+ {"pmulhrw", now3d_insn, 1, SUF_Z, 0xB7, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"psubsw", mmxsse2_insn, 2, SUF_Z, 0xE9, 0, 0, 0, CPU_MMX, 0, 0},
+ {"lsl", larlsl_insn, 6, SUF_Z, 0x03, 0, 0, 0, CPU_286, CPU_Prot, 0},
+ {"rdtsc", twobyte_insn, 1, SUF_Z, 0x0F, 0x31, 0, 0, CPU_586, 0, 0},
+ {"scasw", onebyte_insn, 1, SUF_Z, 0xAF, 0x10, 0, 0, 0, 0, 0},
+ {"pmvnzb", cyrixmmx_insn, 1, SUF_Z, 0x5A, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"pmulhw", mmxsse2_insn, 2, SUF_Z, 0xE5, 0, 0, 0, CPU_MMX, 0, 0},
+ {"sha1rnds4", intel_SHA1RNDS4_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SHA, 0, 0},
+ {"jb", jcc_insn, 9, SUF_Z, 0x02, 0, 0, 0, 0, 0, 0},
+ {"blsi", vex_gpr_ndd_rm_0F38_regext_insn, 2, SUF_Z, 0x00, 0xF3, 0x03, ONLY_AVX, CPU_BMI1, 0, 0},
+ {"vfmaddsub213ps", vfma_ps_insn, 2, SUF_Z, 0xA6, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpcmpeqw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x75, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmaddsd", fma_128_m64_insn, 3, SUF_Z, 0x6B, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"vcmpordpd", ssecmp_128_insn, 3, SUF_Z, 0x07, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpclmulhqhqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x11, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setne", setcc_insn, 1, SUF_Z, 0x05, 0, 0, 0, CPU_386, 0, 0},
+ {"pmaddwd", mmxsse2_insn, 2, SUF_Z, 0xF5, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vpcomneb", vpcom_insn, 1, SUF_Z, 0xCC, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"pclmulhqlqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x01, 0, 0, 0, CPU_AVX, 0, 0},
+ {"xaddb", cmpxchgxadd_insn, 4, SUF_B, 0xC0, 0, 0, 0, CPU_486, 0, 0},
+ {"cmpps", xmm_xmm128_imm_insn, 1, SUF_Z, 0x00, 0xC2, 0, 0, CPU_SSE, 0, 0},
+ {"movntq", movntq_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SSE, 0, 0},
+ {"idivw", div_insn, 8, SUF_W, 0x07, 0, 0, 0, 0, 0, 0},
+ {"push", push_insn, 35, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"vfmsub231pd", vfma_pd_insn, 2, SUF_Z, 0xBA, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"test", test_insn, 20, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"pslldq", pslrldq_insn, 4, SUF_Z, 0x07, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"sha256rnds2", intel_SHA256RNDS2_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SHA, 0, 0},
+ {"cmovb", cmovcc_insn, 3, SUF_Z, 0x02, 0, 0, 0, CPU_686, 0, 0},
+ {"rex64xyz", NULL, X86_REX>>8, 0x4F, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"blcs", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x01, 0x03, 0, 0, CPU_386, CPU_TBM, 0},
+ {"punpcklwd", mmxsse2_insn, 2, SUF_Z, 0x61, 0, 0, 0, CPU_MMX, 0, 0},
+ {"sqrtps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x51, 0, 0, CPU_SSE, 0, 0},
+ {"cmovnaeq", cmovcc_insn, 3, SUF_Q, 0x02, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"vmread", vmxmemrd_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_P4, 0, 0},
+ {"fldz", twobyte_insn, 1, SUF_Z, 0xD9, 0xEE, 0, 0, CPU_FPU, 0, 0},
+ {"vpunpckldq", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x62, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"retl", retnf_insn, 6, SUF_Z, 0xC2, 0, 0, NOT_64, 0, 0, 0},
+ {"vlddqu", lddqu_insn, 2, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"loopnzw", loopw_insn, 4, SUF_Z, 0x00, 0x10, 0, NOT_64, 0, 0, 0},
+ {"vmaxss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5F, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cvttpd2pi", cvt_mm_xmm_insn, 1, SUF_Z, 0x66, 0x2C, 0, 0, CPU_SSE2, 0, 0},
+ {"btrl", bittest_insn, 6, SUF_L, 0xB3, 0x06, 0, 0, CPU_386, 0, 0},
+ {"cvttsd2si", cvt_rx_xmm64_insn, 4, SUF_Z, 0xF2, 0x2C, 0, 0, CPU_SSE2, 0, 0},
+ {"cmovns", cmovcc_insn, 3, SUF_Z, 0x09, 0, 0, 0, CPU_686, 0, 0},
+ {"vblendvpd", avx_sse4xmm0_insn, 2, SUF_Z, 0x4B, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fistp", fildstp_insn, 4, SUF_Z, 0x03, 0x02, 0x07, 0, CPU_FPU, 0, 0},
+ {"setbe", setcc_insn, 1, SUF_Z, 0x06, 0, 0, 0, CPU_386, 0, 0},
+ {"cmpordss", ssecmp_32_insn, 4, SUF_Z, 0x07, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"vfrczps", vfrc_pdps_insn, 2, SUF_Z, 0x00, 0, 0, 0, CPU_XOP, 0, 0},
+ {"sysret", twobyte_insn, 1, SUF_Z, 0x0F, 0x07, 0, 0, CPU_686, CPU_AMD, CPU_Priv},
+ {"pfrsqit1", now3d_insn, 1, SUF_Z, 0xA7, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"pdistib", cyrixmmx_insn, 1, SUF_Z, 0x54, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"sha256msg2", intel_SHA256MSG2_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SHA, 0, 0},
+ {"pshuflw", xmm_xmm128_imm_insn, 1, SUF_Z, 0xF2, 0x70, 0, 0, CPU_SSE2, 0, 0},
+ {"vpcomged", vpcom_insn, 1, SUF_Z, 0xCE, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"addpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x58, 0, 0, CPU_SSE2, 0, 0},
+ {"fstenv", twobytemem_insn, 1, SUF_Z, 0x06, 0x9B, 0xD9, 0, CPU_FPU, 0, 0},
+ {"vpcomled", vpcom_insn, 1, SUF_Z, 0xCE, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"vpackssdw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x6B, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovnbl", cmovcc_insn, 3, SUF_L, 0x03, 0, 0, 0, CPU_686, 0, 0},
+ {"vpcomleuq", vpcom_insn, 1, SUF_Z, 0xEF, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"paddsiw", cyrixmmx_insn, 1, SUF_Z, 0x51, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"dppd", sse4imm_insn, 2, SUF_Z, 0x41, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"incb", incdec_insn, 6, SUF_B, 0x40, 0x00, 0, 0, 0, 0, 0},
+ {"vpmulhuw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xE4, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmovmskpdl", movmsk_insn, 4, SUF_L, 0x66, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"hnt", NULL, X86_SEGREG>>8, 0x2E, 0, 0, 0, 0, 0, 0, 0},
+ {"fclex", threebyte_insn, 1, SUF_Z, 0x9B, 0xDB, 0xE2, 0, CPU_FPU, 0, 0},
+ {"vcmpord_sss", ssecmp_32_insn, 4, SUF_Z, 0x17, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"aeskeygenassist", aes_imm_insn, 1, SUF_Z, 0x3A, 0xDF, 0, 0, CPU_AES, 0, 0},
+ {"cvtsi2ssq", cvt_xmm_rmx_insn, 6, SUF_Q, 0xF3, 0x2A, 0, ONLY_64, CPU_SSE, 0, 0},
+ {"extractps", extractps_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_SSE41, 0},
+ {"cmpless", ssecmp_32_insn, 4, SUF_Z, 0x02, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"psubusw", mmxsse2_insn, 2, SUF_Z, 0xD9, 0, 0, 0, CPU_MMX, 0, 0},
+ {"setnzb", setcc_insn, 1, SUF_B, 0x05, 0, 0, 0, CPU_386, 0, 0},
+ {"vpacksswb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x63, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pandn", mmxsse2_insn, 2, SUF_Z, 0xDF, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vpsubd", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xFA, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmptruesd", ssecmp_64_insn, 4, SUF_Z, 0x0F, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fucomp", fcom2_insn, 2, SUF_Z, 0xDD, 0xE8, 0, 0, CPU_286, CPU_FPU, 0},
+ {"lar", larlsl_insn, 6, SUF_Z, 0x02, 0, 0, 0, CPU_286, CPU_Prot, 0},
+ {"blsic", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x01, 0x06, 0, 0, CPU_386, CPU_TBM, 0},
+ {"ibts", ibts_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_Obs, CPU_Undoc},
+ {"sysexit", twobyte_insn, 1, SUF_Z, 0x0F, 0x35, 0, NOT_64, CPU_686, CPU_Priv, 0},
+ {"vmovmskps", movmsk_insn, 4, SUF_Z, 0x00, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtss2sd", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5A, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vunpcklps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x14, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fdivr", farith_insn, 7, SUF_Z, 0xF0, 0xF8, 0x07, 0, CPU_FPU, 0, 0},
+ {"vpshufb", ssse3_insn, 5, SUF_Z, 0x00, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmptruepd", ssecmp_128_insn, 3, SUF_Z, 0x0F, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpshufhw", xmm_xmm128_imm_256avx2_insn, 2, SUF_Z, 0xF3, 0x70, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"loopl", loopl_insn, 4, SUF_Z, 0x02, 0x20, 0, 0, 0, 0, 0},
+ {"vfnmaddps", fma_128_256_insn, 4, SUF_Z, 0x78, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"movsbw", movszx_insn, 5, SUF_B, 0xBE, 0, 0, 0, CPU_386, 0, 0},
+ {"fstps", fstp_insn, 4, SUF_S, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"fadd", farith_insn, 7, SUF_Z, 0xC0, 0xC0, 0x00, 0, CPU_FPU, 0, 0},
+ {"vcmpeqsd", ssecmp_64_insn, 4, SUF_Z, 0x00, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpngt_uqsd", ssecmp_64_insn, 4, SUF_Z, 0x1A, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sscaw", onebyte_insn, 1, SUF_Z, 0xAF, 0x10, 0, 0, 0, 0, 0},
+ {"setnlb", setcc_insn, 1, SUF_B, 0x0D, 0, 0, 0, CPU_386, 0, 0},
+ {"vpmulld", ssse3_insn, 5, SUF_Z, 0x40, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmsub132pd", vfma_pd_insn, 2, SUF_Z, 0x9A, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"palignr", ssse3imm_insn, 2, SUF_Z, 0x0F, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"orpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x56, 0, 0, CPU_SSE2, 0, 0},
+ {"vminsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fsincos", twobyte_insn, 1, SUF_Z, 0xD9, 0xFB, 0, 0, CPU_286, CPU_FPU, 0},
+ {"vcmple_oqpd", ssecmp_128_insn, 3, SUF_Z, 0x12, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmagw", cyrixmmx_insn, 1, SUF_Z, 0x52, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"setnleb", setcc_insn, 1, SUF_B, 0x0F, 0, 0, 0, CPU_386, 0, 0},
+ {"vcmpps", xmm_xmm128_imm_256_insn, 3, SUF_Z, 0x00, 0xC2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpmulhrsw", ssse3_insn, 5, SUF_Z, 0x0B, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setcb", setcc_insn, 1, SUF_B, 0x02, 0, 0, 0, CPU_386, 0, 0},
+ {"lgsl", lfgss_insn, 3, SUF_L, 0xB5, 0, 0, 0, CPU_386, 0, 0},
+ {"paveb", cyrixmmx_insn, 1, SUF_Z, 0x50, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"sbbq", arith_insn, 22, SUF_Q, 0x18, 0x03, 0, ONLY_64, 0, 0, 0},
+ {"vfmaddpd", fma_128_256_insn, 4, SUF_Z, 0x69, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"fcos", twobyte_insn, 1, SUF_Z, 0xD9, 0xFF, 0, 0, CPU_286, CPU_FPU, 0},
+ {"cvtsi2ssl", cvt_xmm_rmx_insn, 6, SUF_L, 0xF3, 0x2A, 0, 0, CPU_386, CPU_SSE, 0},
+ {"setneb", setcc_insn, 1, SUF_B, 0x05, 0, 0, 0, CPU_386, 0, 0},
+ {"vfnmsub132ps", vfma_ps_insn, 2, SUF_Z, 0x9E, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"lfsw", lfgss_insn, 3, SUF_W, 0xB4, 0, 0, 0, CPU_386, 0, 0},
+ {"vpcmpestrm", sse4pcmpstr_insn, 1, SUF_Z, 0x60, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"arpl", arpl_insn, 1, SUF_Z, 0, 0, 0, NOT_64, CPU_286, CPU_Prot, 0},
+ {"cmovew", cmovcc_insn, 3, SUF_W, 0x04, 0, 0, 0, CPU_686, 0, 0},
+ {"pminuw", sse4_insn, 2, SUF_Z, 0x3A, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"movabsq", movabs_insn, 9, SUF_Q, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"cmovo", cmovcc_insn, 3, SUF_Z, 0x00, 0, 0, 0, CPU_686, 0, 0},
+ {"blsicl", xop_gpr_reg_rm_09_insn, 2, SUF_L, 0x01, 0x06, 0, 0, CPU_386, CPU_TBM, 0},
+ {"smovw", onebyte_insn, 1, SUF_Z, 0xA5, 0x10, 0, 0, 0, 0, 0},
+ {"faddl", farith_insn, 7, SUF_L, 0xC0, 0xC0, 0x00, 0, CPU_FPU, 0, 0},
+ {"maxsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5F, 0, 0, CPU_SSE2, 0, 0},
+ {"aad", aadm_insn, 2, SUF_Z, 0x01, 0, 0, NOT_64, 0, 0, 0},
+ {"vpmaskmovq", vmaskmov_vexw1_avx2_insn, 4, SUF_Z, 0x8C, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vfmadd132sd", vfma_sd_insn, 2, SUF_Z, 0x99, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"rep", NULL, X86_LOCKREP>>8, 0xF3, 0, 0, 0, 0, 0, 0, 0},
+ {"vcmpltss", ssecmp_32_insn, 4, SUF_Z, 0x01, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sub", arith_insn, 22, SUF_Z, 0x28, 0x05, 0, 0, 0, 0, 0},
+ {"smswq", sldtmsw_insn, 6, SUF_Q, 0x04, 0x01, 0, ONLY_64, CPU_286, 0, 0},
+ {"qword", NULL, X86_OPERSIZE>>8, 0x40, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"vcmpunordps", ssecmp_128_insn, 3, SUF_Z, 0x03, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cltq", onebyte_insn, 1, SUF_Z, 0x98, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"vfnmadd213pd", vfma_pd_insn, 2, SUF_Z, 0xAC, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"minsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5D, 0, 0, CPU_SSE2, 0, 0},
+ {"fmul", farith_insn, 7, SUF_Z, 0xC8, 0xC8, 0x01, 0, CPU_FPU, 0, 0},
+ {"cmpss", xmm_xmm32_imm_insn, 4, SUF_Z, 0xF3, 0xC2, 0, 0, CPU_SSE, 0, 0},
+ {"vcvtsd2si", cvt_rx_xmm64_insn, 4, SUF_Z, 0xF2, 0x2D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"addsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x58, 0, 0, CPU_SSE2, 0, 0},
+ {"vmulss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x59, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"btsq", bittest_insn, 6, SUF_Q, 0xAB, 0x05, 0, ONLY_64, CPU_386, 0, 0},
+ {"cvtsd2sil", cvt_rx_xmm64_insn, 4, SUF_L, 0xF2, 0x2D, 0, 0, CPU_386, CPU_SSE2, 0},
+ {"vpcomtrueb", vpcom_insn, 1, SUF_Z, 0xCC, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"vpcomeqb", vpcom_insn, 1, SUF_Z, 0xCC, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"fidivr", fiarith_insn, 2, SUF_Z, 0x07, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"vpcomgeuw", vpcom_insn, 1, SUF_Z, 0xED, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"cmovnel", cmovcc_insn, 3, SUF_L, 0x05, 0, 0, 0, CPU_686, 0, 0},
+ {"vpmovzxwq", sse4m32_insn, 4, SUF_Z, 0x34, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpeq_osss", ssecmp_32_insn, 4, SUF_Z, 0x10, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"shrb", shift_insn, 16, SUF_B, 0x05, 0, 0, 0, 0, 0, 0},
+ {"maxpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x5F, 0, 0, CPU_SSE2, 0, 0},
+ {"hsubps", xmm_xmm128_insn, 2, SUF_Z, 0xF2, 0x7D, 0, 0, CPU_SSE3, 0, 0},
+ {"sarx", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_Z, 0xF3, 0x38, 0xF7, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"vpcomgtb", vpcom_insn, 1, SUF_Z, 0xCC, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"vextractf128", vextractif128_insn, 1, SUF_Z, 0x19, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtsi2ssl", cvt_xmm_rmx_insn, 6, SUF_L, 0xF3, 0x2A, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movzxb", movszx_insn, 5, SUF_B, 0xB6, 0, 0, 0, CPU_386, 0, 0},
+ {"vpbroadcastw", vpbroadcastw_avx2_insn, 4, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"shlw", shift_insn, 16, SUF_W, 0x04, 0, 0, 0, 0, 0, 0},
+ {"cmpltps", ssecmp_128_insn, 3, SUF_Z, 0x01, 0, 0, 0, CPU_SSE, 0, 0},
+ {"xlatb", onebyte_insn, 1, SUF_Z, 0xD7, 0x00, 0, 0, 0, 0, 0},
+ {"xsha1", padlock_insn, 1, SUF_Z, 0xC8, 0xF3, 0xA6, 0, CPU_PadLock, 0, 0},
+ {"lret", retnf_insn, 6, SUF_Z, 0xCA, 0, 0, 0, 0, 0, 0},
+ {"xsha256", padlock_insn, 1, SUF_Z, 0xD0, 0xF3, 0xA6, 0, CPU_PadLock, 0, 0},
+ {"vpsrad", vpshift_insn, 8, SUF_Z, 0xE2, 0x72, 0x04, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovnpl", cmovcc_insn, 3, SUF_L, 0x0B, 0, 0, 0, CPU_686, 0, 0},
+ {"addw", arith_insn, 22, SUF_W, 0x00, 0x00, 0, 0, 0, 0, 0},
+ {"setg", setcc_insn, 1, SUF_Z, 0x0F, 0, 0, 0, CPU_386, 0, 0},
+ {"vphaddubq", vphaddsub_insn, 1, SUF_Z, 0xD3, 0, 0, 0, CPU_XOP, 0, 0},
+ {"cmovngl", cmovcc_insn, 3, SUF_L, 0x0E, 0, 0, 0, CPU_686, 0, 0},
+ {"vpermilpd", vpermil_insn, 4, SUF_Z, 0x05, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpmacswd", vpma_insn, 1, SUF_Z, 0x96, 0, 0, 0, CPU_XOP, 0, 0},
+ {"clac", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xCA, 0, CPU_SMAP, 0, 0},
+ {"punpckhwd", mmxsse2_insn, 2, SUF_Z, 0x69, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vpcmpgtb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x64, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"leave", onebyte_insn, 1, SUF_Z, 0xC9, 0x00, 0x40, 0, CPU_186, 0, 0},
+ {"shrd", shlrd_insn, 9, SUF_Z, 0xAC, 0, 0, 0, CPU_386, 0, 0},
+ {"vfmsub132ps", vfma_ps_insn, 2, SUF_Z, 0x9A, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"lretl", retnf_insn, 6, SUF_L, 0xCA, 0, 0, 0, 0, 0, 0},
+ {"cmovpol", cmovcc_insn, 3, SUF_L, 0x0B, 0, 0, 0, CPU_686, 0, 0},
+ {"orl", arith_insn, 22, SUF_L, 0x08, 0x01, 0, 0, CPU_386, 0, 0},
+ {"fnstcw", fldnstcw_insn, 1, SUF_Z, 0x07, 0, 0, 0, CPU_FPU, 0, 0},
+ {"punpckldq", mmxsse2_insn, 2, SUF_Z, 0x62, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vpmaddwd", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xF5, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"mulb", f6_insn, 4, SUF_B, 0x04, 0, 0, 0, 0, 0, 0},
+ {"cmppd", xmm_xmm128_imm_insn, 1, SUF_Z, 0x66, 0xC2, 0, 0, CPU_SSE2, 0, 0},
+ {"rex", NULL, X86_REX>>8, 0x40, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"movd", movd_insn, 8, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_MMX, 0},
+ {"vpshaw", amd_vpshift_insn, 2, SUF_Z, 0x99, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vrsqrtps", avx_xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x52, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtph2ps", avx_cvtph2ps_insn, 4, SUF_Z, 0x66, 0x13, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vsubss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"tzcntl", cnt_insn, 3, SUF_L, 0xBC, 0, 0, 0, CPU_BMI1, 0, 0},
+ {"not", f6_insn, 4, SUF_Z, 0x02, 0, 0, 0, 0, 0, 0},
+ {"cvtpd2pi", cvt_mm_xmm_insn, 1, SUF_Z, 0x66, 0x2D, 0, 0, CPU_SSE2, 0, 0},
+ {"vcmpngtsd", ssecmp_64_insn, 4, SUF_Z, 0x0A, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rex64yz", NULL, X86_REX>>8, 0x4B, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"vpblendd", vex_66_0F3A_imm8_avx2_insn, 2, SUF_Z, 0x02, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vpmovmskb", pmovmskb_insn, 6, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fldt", fldstpt_insn, 1, SUF_Z, 0x05, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vpunpcklbw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x60, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"femms", twobyte_insn, 1, SUF_Z, 0x0F, 0x0E, 0, 0, CPU_3DNow, 0, 0},
+ {"vpsrlvq", vpshiftv_vexw1_avx2_insn, 2, SUF_Z, 0x45, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"paddusb", mmxsse2_insn, 2, SUF_Z, 0xDC, 0, 0, 0, CPU_MMX, 0, 0},
+ {"movdq2q", movdq2q_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"vfnmsub132pd", vfma_pd_insn, 2, SUF_Z, 0x9E, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"adcb", arith_insn, 22, SUF_B, 0x10, 0x02, 0, 0, 0, 0, 0},
+ {"vcmpneqps", ssecmp_128_insn, 3, SUF_Z, 0x04, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"andnl", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_L, 0x00, 0x38, 0xF2, ONLY_AVX, CPU_BMI1, 0, 0},
+ {"fnstenvl", onebytemem_insn, 1, SUF_L, 0x06, 0xD9, 0, 0, CPU_FPU, 0, 0},
+ {"smi", onebyte_insn, 1, SUF_Z, 0xF1, 0, 0, 0, CPU_386, CPU_Undoc, 0},
+ {"cmovol", cmovcc_insn, 3, SUF_L, 0x00, 0, 0, 0, CPU_686, 0, 0},
+ {"wait", onebyte_insn, 1, SUF_Z, 0x9B, 0, 0, 0, 0, 0, 0},
+ {"vpcmov", vpcmov_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vunpcklpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x14, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jl", jcc_insn, 9, SUF_Z, 0x0C, 0, 0, 0, 0, 0, 0},
+ {"fnclex", twobyte_insn, 1, SUF_Z, 0xDB, 0xE2, 0, 0, CPU_FPU, 0, 0},
+ {"shlq", shift_insn, 16, SUF_Q, 0x04, 0, 0, ONLY_64, 0, 0, 0},
+ {"sall", shift_insn, 16, SUF_L, 0x04, 0, 0, 0, CPU_386, 0, 0},
+ {"swapgs", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xF8, ONLY_64, 0, 0, 0},
+ {"cvttps2dq", xmm_xmm128_insn, 2, SUF_Z, 0xF3, 0x5B, 0, 0, CPU_SSE2, 0, 0},
+ {"pmaxud", sse4_insn, 2, SUF_Z, 0x3F, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vpaddsw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xED, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"prefetcht0", twobytemem_insn, 1, SUF_Z, 0x01, 0x0F, 0x18, 0, CPU_P3, 0, 0},
+ {"repne", NULL, X86_LOCKREP>>8, 0xF2, 0, 0, 0, 0, 0, 0, 0},
+ {"vfmsub132ss", vfma_ss_insn, 2, SUF_Z, 0x9B, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"lsll", larlsl_insn, 6, SUF_L, 0x03, 0, 0, 0, CPU_286, CPU_Prot, 0},
+ {"vgatherqps", gather_32x_32y_128_insn, 2, SUF_Z, 0x93, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vrsqrtss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x52, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"divl", div_insn, 8, SUF_L, 0x06, 0, 0, 0, CPU_386, 0, 0},
+ {"pcmpgtq", sse4_insn, 2, SUF_Z, 0x37, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"pmulhrsw", ssse3_insn, 5, SUF_Z, 0x0B, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"repe", NULL, X86_LOCKREP>>8, 0xF3, 0, 0, 0, 0, 0, 0, 0},
+ {"vpcomtrued", vpcom_insn, 1, SUF_Z, 0xCE, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"fldl", fld_insn, 4, SUF_L, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"cvtps2pd", xmm_xmm64_insn, 4, SUF_Z, 0x00, 0x5A, 0, 0, CPU_SSE2, 0, 0},
+ {"vcmpnless", ssecmp_32_insn, 4, SUF_Z, 0x06, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"loopeq", loopq_insn, 4, SUF_Z, 0x01, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"aesdeclast", aes_insn, 2, SUF_Z, 0x38, 0xDF, 0, 0, CPU_AVX, 0, 0},
+ {"vpcomequb", vpcom_insn, 1, SUF_Z, 0xEC, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"stgi", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xDC, 0, CPU_SVM, 0, 0},
+ {"vpmovzxbd", sse4m32_insn, 4, SUF_Z, 0x31, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"psignb", ssse3_insn, 5, SUF_Z, 0x08, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"vpshlq", amd_vpshift_insn, 2, SUF_Z, 0x97, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpcomfalseuq", vpcom_insn, 1, SUF_Z, 0xEF, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"mulxq", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_Q, 0xF2, 0x38, 0xF6, ONLY_64|ONLY_AVX, CPU_BMI2, 0, 0},
+ {"jmpq", jmp_insn, 31, SUF_Q, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"cvtsd2siq", cvt_rx_xmm64_insn, 4, SUF_Q, 0xF2, 0x2D, 0, ONLY_64, CPU_SSE2, 0, 0},
+ {"movhpd", movhlp_insn, 3, SUF_Z, 0x66, 0x16, 0, 0, CPU_SSE2, 0, 0},
+ {"punpcklqdq", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x6C, 0, 0, CPU_SSE2, 0, 0},
+ {"verw", prot286_insn, 1, SUF_Z, 0x05, 0x00, 0, 0, CPU_286, CPU_Prot, 0},
+ {"cmpunordsd", ssecmp_64_insn, 4, SUF_Z, 0x03, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"vzeroall", vzero_insn, 1, SUF_Z, 0xC4, 0, 0, 0, CPU_AVX, 0, 0},
+ {"vperm2i128", vperm2i128_avx2_insn, 1, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"jo", jcc_insn, 9, SUF_Z, 0x00, 0, 0, 0, 0, 0, 0},
+ {"callq", call_insn, 30, SUF_Q, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"cmovle", cmovcc_insn, 3, SUF_Z, 0x0E, 0, 0, 0, CPU_686, 0, 0},
+ {"sgdtq", twobytemem_insn, 1, SUF_Q, 0x00, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"cmovnpq", cmovcc_insn, 3, SUF_Q, 0x0B, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"cvtpd2ps", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x5A, 0, 0, CPU_SSE2, 0, 0},
+ {"minss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5D, 0, 0, CPU_SSE, 0, 0},
+ {"loopw", loopw_insn, 4, SUF_Z, 0x02, 0x10, 0, NOT_64, 0, 0, 0},
+ {"inveptl", eptvpid_insn, 2, SUF_L, 0x00, 0, 0, NOT_64, CPU_386, CPU_EPTVPID, 0},
+ {"bsr", bsfr_insn, 3, SUF_Z, 0xBD, 0, 0, 0, CPU_386, 0, 0},
+ {"vcmpgtss", ssecmp_32_insn, 4, SUF_Z, 0x0E, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"negl", f6_insn, 4, SUF_L, 0x03, 0, 0, 0, CPU_386, 0, 0},
+ {"psrlw", pshift_insn, 4, SUF_Z, 0xD1, 0x71, 0x02, 0, CPU_MMX, 0, 0},
+ {"vpmuludq", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xF4, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pext", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_Z, 0xF3, 0x38, 0xF5, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"rsm", twobyte_insn, 1, SUF_Z, 0x0F, 0xAA, 0, 0, CPU_586, CPU_SMM, 0},
+ {"addl", arith_insn, 22, SUF_L, 0x00, 0x00, 0, 0, CPU_386, 0, 0},
+ {"vpermd", vperm_var_avx2_insn, 1, SUF_Z, 0x36, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"fxsave", twobytemem_insn, 1, SUF_Z, 0x00, 0x0F, 0xAE, 0, CPU_686, CPU_FPU, 0},
+ {"vphadduwq", vphaddsub_insn, 1, SUF_Z, 0xD7, 0, 0, 0, CPU_XOP, 0, 0},
+ {"pminud", sse4_insn, 2, SUF_Z, 0x3B, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"ldsw", ldes_insn, 2, SUF_W, 0xC5, 0, 0, NOT_64, 0, 0, 0},
+ {"movsw", onebyte_insn, 1, SUF_Z, 0xA5, 0x10, 0, 0, 0, 0, 0},
+ {"pmaxub", mmxsse2_insn, 2, SUF_Z, 0xDE, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vldmxcsr", ldstmxcsr_insn, 1, SUF_Z, 0x02, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vhsubpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x7D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vucomisd", avx_xmm_xmm64_insn, 2, SUF_Z, 0x66, 0x2E, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovpow", cmovcc_insn, 3, SUF_W, 0x0B, 0, 0, 0, CPU_686, 0, 0},
+ {"pmvgezb", cyrixmmx_insn, 1, SUF_Z, 0x5C, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"cvtsd2ss", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5A, 0, 0, CPU_SSE2, 0, 0},
+ {"vbroadcastf128", vbroadcastif128_insn, 1, SUF_Z, 0x1A, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lldt", prot286_insn, 1, SUF_Z, 0x02, 0x00, 0, 0, CPU_286, CPU_Priv, CPU_Prot},
+ {"t1mskc", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x01, 0x07, 0, 0, CPU_386, CPU_TBM, 0},
+ {"movsx", movszx_insn, 5, SUF_Z, 0xBE, 0, 0, 0, CPU_386, 0, 0},
+ {"vpmacsdd", vpma_insn, 1, SUF_Z, 0x9E, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vcmplesd", ssecmp_64_insn, 4, SUF_Z, 0x02, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"prefetchw", twobytemem_insn, 1, SUF_Z, 0x01, 0x0F, 0x0D, 0, CPU_PRFCHW, 0, 0},
+ {"pextrd", pextrd_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_SSE41, 0},
+ {"vcmpfalse_osps", ssecmp_128_insn, 3, SUF_Z, 0x1B, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vptest", sse4_insn, 2, SUF_Z, 0x17, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"loopneq", loopq_insn, 4, SUF_Z, 0x00, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"fucompp", twobyte_insn, 1, SUF_Z, 0xDA, 0xE9, 0, 0, CPU_286, CPU_FPU, 0},
+ {"vpextrq", pextrq_insn, 1, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"umov", umov_insn, 6, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_Undoc, 0},
+ {"fcmovb", fcmovcc_insn, 1, SUF_Z, 0xDA, 0xC0, 0, 0, CPU_686, CPU_FPU, 0},
+ {"vinsertf128", vinsertif128_insn, 1, SUF_Z, 0x18, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"std", onebyte_insn, 1, SUF_Z, 0xFD, 0, 0, 0, 0, 0, 0},
+ {"cvtpd2dq", xmm_xmm128_insn, 2, SUF_Z, 0xF2, 0xE6, 0, 0, CPU_SSE2, 0, 0},
+ {"vpcomned", vpcom_insn, 1, SUF_Z, 0xCE, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"vpand", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xDB, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"bswapq", bswap_insn, 2, SUF_Q, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"vpmacssdqh", vpma_insn, 1, SUF_Z, 0x8F, 0, 0, 0, CPU_XOP, 0, 0},
+ {"blcicl", xop_gpr_reg_rm_09_insn, 2, SUF_L, 0x01, 0x05, 0, 0, CPU_386, CPU_TBM, 0},
+ {"strq", str_insn, 4, SUF_Q, 0, 0, 0, ONLY_64, CPU_286, CPU_Prot, 0},
+ {"vshufps", xmm_xmm128_imm_256_insn, 3, SUF_Z, 0x00, 0xC6, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"roll", shift_insn, 16, SUF_L, 0x00, 0, 0, 0, CPU_386, 0, 0},
+ {"cvttpd2dq", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0xE6, 0, 0, CPU_SSE2, 0, 0},
+ {"salq", shift_insn, 16, SUF_Q, 0x04, 0, 0, ONLY_64, 0, 0, 0},
+ {"vpcomfalseq", vpcom_insn, 1, SUF_Z, 0xCF, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"leaq", lea_insn, 3, SUF_Q, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"vmovdqu", movau_insn, 6, SUF_Z, 0xF3, 0x6F, 0x10, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpmaddubsw", ssse3_insn, 5, SUF_Z, 0x04, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpltpd", ssecmp_128_insn, 3, SUF_Z, 0x01, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"outw", out_insn, 12, SUF_W, 0, 0, 0, 0, 0, 0, 0},
+ {"cmovncq", cmovcc_insn, 3, SUF_Q, 0x03, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"blcmskl", xop_gpr_reg_rm_09_insn, 2, SUF_L, 0x02, 0x01, 0, 0, CPU_386, CPU_TBM, 0},
+ {"vfmadd231ss", vfma_ss_insn, 2, SUF_Z, 0xB9, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"cmpordsd", ssecmp_64_insn, 4, SUF_Z, 0x07, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"setnle", setcc_insn, 1, SUF_Z, 0x0F, 0, 0, 0, CPU_386, 0, 0},
+ {"vfmadd231pd", vfma_pd_insn, 2, SUF_Z, 0xB8, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vcmpneqsd", ssecmp_64_insn, 4, SUF_Z, 0x04, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmptrst", vmxtwobytemem_insn, 1, SUF_Z, 0x07, 0, 0, 0, CPU_P4, 0, 0},
+ {"cmovsl", cmovcc_insn, 3, SUF_L, 0x08, 0, 0, 0, CPU_686, 0, 0},
+ {"vpmovsxbw", sse4m64_insn, 4, SUF_Z, 0x20, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpneq_ossd", ssecmp_64_insn, 4, SUF_Z, 0x1C, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"xgetbv", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xD0, 0, CPU_386, CPU_XSAVE, 0},
+ {"addr32", NULL, X86_ADDRSIZE>>8, 0x20, 0, 0, 0, 0, 0, 0, 0},
+ {"vcmpneq_osss", ssecmp_32_insn, 4, SUF_Z, 0x1C, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmulsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x59, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"maskmovdqu", maskmovdqu_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"vpslldq", pslrldq_insn, 4, SUF_Z, 0x07, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"maskmovq", maskmovq_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vcmpeq_uspd", ssecmp_128_insn, 3, SUF_Z, 0x18, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmulhriw", cyrixmmx_insn, 1, SUF_Z, 0x5D, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"vcvtps2dq", avx_xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x5B, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmsub231ss", vfma_ss_insn, 2, SUF_Z, 0xBF, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"shrx", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_Z, 0xF2, 0x38, 0xF7, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"psadbw", mmxsse2_insn, 2, SUF_Z, 0xF6, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vmovd", vmovd_insn, 2, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_386, CPU_AVX, 0},
+ {"pushfl", onebyte_insn, 1, SUF_Z, 0x9C, 0x20, 0, NOT_64, CPU_386, 0, 0},
+ {"vfnmadd132ps", vfma_ps_insn, 2, SUF_Z, 0x9C, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"sqrtpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x51, 0, 0, CPU_SSE2, 0, 0},
+ {"cvtss2sil", cvt_rx_xmm32_insn, 4, SUF_L, 0xF3, 0x2D, 0, 0, CPU_386, CPU_SSE, 0},
+ {"fyl2x", twobyte_insn, 1, SUF_Z, 0xD9, 0xF1, 0, 0, CPU_FPU, 0, 0},
+ {"btq", bittest_insn, 6, SUF_Q, 0xA3, 0x04, 0, ONLY_64, CPU_386, 0, 0},
+ {"vpslld", vpshift_insn, 8, SUF_Z, 0xF2, 0x72, 0x06, ONLY_AVX, CPU_AVX, 0, 0},
+ {"invlpga", invlpga_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_SVM, 0, 0},
+ {"xorb", arith_insn, 22, SUF_B, 0x30, 0x06, 0, 0, 0, 0, 0},
+ {"fsubp", farithp_insn, 3, SUF_Z, 0xE0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vcvtps2pd", avx_cvt_xmm64_insn, 3, SUF_Z, 0x00, 0x5A, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmsub213pd", vfma_pd_insn, 2, SUF_Z, 0xAE, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vcvttsd2sil", cvt_rx_xmm64_insn, 4, SUF_L, 0xF2, 0x2C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jp", jcc_insn, 9, SUF_Z, 0x0A, 0, 0, 0, 0, 0, 0},
+ {"vsubpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x5C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lesw", ldes_insn, 2, SUF_W, 0xC4, 0, 0, NOT_64, 0, 0, 0},
+ {"vxorps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x57, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"divb", div_insn, 8, SUF_B, 0x06, 0, 0, 0, 0, 0, 0},
+ {"movq", mov_insn, 69, SUF_Q, 0, 0, 0, 0, 0, 0, 0},
+ {"lfsl", lfgss_insn, 3, SUF_L, 0xB4, 0, 0, 0, CPU_386, 0, 0},
+ {"syscall", twobyte_insn, 1, SUF_Z, 0x0F, 0x05, 0, 0, CPU_686, CPU_AMD, 0},
+ {"btl", bittest_insn, 6, SUF_L, 0xA3, 0x04, 0, 0, CPU_386, 0, 0},
+ {"fucomip", fcom2_insn, 2, SUF_Z, 0xDF, 0xE8, 0, 0, CPU_686, CPU_FPU, 0},
+ {"setncb", setcc_insn, 1, SUF_B, 0x03, 0, 0, 0, CPU_386, 0, 0},
+ {"cmovnol", cmovcc_insn, 3, SUF_L, 0x01, 0, 0, 0, CPU_686, 0, 0},
+ {"xcryptcbc", padlock_insn, 1, SUF_Z, 0xD0, 0xF3, 0xA7, 0, CPU_PadLock, 0, 0},
+ {"vcmplt_oqps", ssecmp_128_insn, 3, SUF_Z, 0x11, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"btrq", bittest_insn, 6, SUF_Q, 0xB3, 0x06, 0, ONLY_64, CPU_386, 0, 0},
+ {"paddw", mmxsse2_insn, 2, SUF_Z, 0xFD, 0, 0, 0, CPU_MMX, 0, 0},
+ {"pmovzxbq", sse4m16_insn, 4, SUF_Z, 0x32, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"rorq", shift_insn, 16, SUF_Q, 0x01, 0, 0, ONLY_64, 0, 0, 0},
+ {"xrelease", NULL, X86_ACQREL>>8, 0xF3, 0, 0, 0, 0, 0, 0, 0},
+ {"vpshld", amd_vpshift_insn, 2, SUF_Z, 0x96, 0, 0, 0, CPU_XOP, 0, 0},
+ {"fstp", fstp_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"movsbq", movszx_insn, 5, SUF_B, 0xBE, 0, 0, ONLY_64, CPU_386, 0, 0},
+ {"fucom", fcom2_insn, 2, SUF_Z, 0xDD, 0xE0, 0, 0, CPU_286, CPU_FPU, 0},
+ {"vpclmullqlqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x00, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"hsubpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x7D, 0, 0, CPU_SSE3, 0, 0},
+ {"por", mmxsse2_insn, 2, SUF_Z, 0xEB, 0, 0, 0, CPU_MMX, 0, 0},
+ {"mulx", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_Z, 0xF2, 0x38, 0xF6, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"vpcomneqb", vpcom_insn, 1, SUF_Z, 0xCC, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"movmskps", movmsk_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_SSE, 0},
+ {"fucomi", fcom2_insn, 2, SUF_Z, 0xDB, 0xE8, 0, 0, CPU_686, CPU_FPU, 0},
+ {"ht", NULL, X86_SEGREG>>8, 0x3E, 0, 0, 0, 0, 0, 0, 0},
+ {"vroundps", avx_sse4imm_insn, 3, SUF_Z, 0x08, 0, 0, ONLY_AVX, CPU_SSE41, 0, 0},
+ {"ud1", twobyte_insn, 1, SUF_Z, 0x0F, 0xB9, 0, 0, CPU_286, CPU_Undoc, 0},
+ {"insl", onebyte_insn, 1, SUF_Z, 0x6D, 0x20, 0, 0, CPU_386, 0, 0},
+ {"vcmpngt_uqpd", ssecmp_128_insn, 3, SUF_Z, 0x1A, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rex64y", NULL, X86_REX>>8, 0x4A, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"fldln2", twobyte_insn, 1, SUF_Z, 0xD9, 0xED, 0, 0, CPU_FPU, 0, 0},
+ {"ldsl", ldes_insn, 2, SUF_L, 0xC5, 0, 0, NOT_64, CPU_386, 0, 0},
+ {"tzmskl", xop_gpr_reg_rm_09_insn, 2, SUF_L, 0x01, 0x04, 0, 0, CPU_386, CPU_TBM, 0},
+ {"vcmppd", xmm_xmm128_imm_256_insn, 3, SUF_Z, 0x66, 0xC2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sidtw", twobytemem_insn, 1, SUF_W, 0x01, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"vpextrwl", pextrw_insn, 7, SUF_L, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fldl2t", twobyte_insn, 1, SUF_Z, 0xD9, 0xE9, 0, 0, CPU_FPU, 0, 0},
+ {"insb", onebyte_insn, 1, SUF_Z, 0x6C, 0x00, 0, 0, 0, 0, 0},
+ {"bound", bound_insn, 2, SUF_Z, 0, 0, 0, NOT_64, CPU_186, 0, 0},
+ {"vmwrite", vmxmemwr_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_P4, 0, 0},
+ {"cmpxchgq", cmpxchgxadd_insn, 4, SUF_Q, 0xB0, 0, 0, ONLY_64, CPU_486, 0, 0},
+ {"fsts", fst_insn, 3, SUF_S, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"orps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x56, 0, 0, CPU_SSE, 0, 0},
+ {"vandnps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x55, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fdivrs", farith_insn, 7, SUF_S, 0xF0, 0xF8, 0x07, 0, CPU_FPU, 0, 0},
+ {"fldcww", fldnstcw_insn, 1, SUF_W, 0x05, 0, 0, 0, CPU_FPU, 0, 0},
+ {"movl", mov_insn, 69, SUF_L, 0, 0, 0, 0, CPU_386, 0, 0},
+ {"movq2dq", movq2dq_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"cmpunordpd", ssecmp_128_insn, 3, SUF_Z, 0x03, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"rdseed", rdrand_insn, 3, SUF_Z, 0x07, 0, 0, 0, CPU_RDSEED, 0, 0},
+ {"cmovneq", cmovcc_insn, 3, SUF_Q, 0x05, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"vpmovzxbq", sse4m16_insn, 4, SUF_Z, 0x32, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpsb", onebyte_insn, 1, SUF_Z, 0xA6, 0x00, 0, 0, 0, 0, 0},
+ {"vfmadd213sd", vfma_sd_insn, 2, SUF_Z, 0xA9, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"into", onebyte_insn, 1, SUF_Z, 0xCE, 0, 0, NOT_64, 0, 0, 0},
+ {"cmovzl", cmovcc_insn, 3, SUF_L, 0x04, 0, 0, 0, CPU_686, 0, 0},
+ {"imulb", imul_insn, 19, SUF_B, 0, 0, 0, 0, 0, 0, 0},
+ {"setc", setcc_insn, 1, SUF_Z, 0x02, 0, 0, 0, CPU_386, 0, 0},
+ {"vstmxcsr", ldstmxcsr_insn, 1, SUF_Z, 0x03, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fldenv", onebytemem_insn, 1, SUF_Z, 0x04, 0xD9, 0, 0, CPU_FPU, 0, 0},
+ {"pmovsxwd", sse4m64_insn, 4, SUF_Z, 0x23, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vcmpnltss", ssecmp_32_insn, 4, SUF_Z, 0x05, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movntpd", movnt_insn, 2, SUF_Z, 0x66, 0x2B, 0, 0, CPU_SSE2, 0, 0},
+ {"pcmpeqw", mmxsse2_insn, 2, SUF_Z, 0x75, 0, 0, 0, CPU_MMX, 0, 0},
+ {"fcoms", fcom_insn, 6, SUF_S, 0xD0, 0x02, 0, 0, CPU_FPU, 0, 0},
+ {"vpaddb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xFC, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sldt", sldtmsw_insn, 6, SUF_Z, 0x00, 0x00, 0, 0, CPU_286, 0, 0},
+ {"fisttpq", fildstp_insn, 4, SUF_Q, 0x01, 0x00, 0x01, 0, CPU_SSE3, 0, 0},
+ {"vpmacsww", vpma_insn, 1, SUF_Z, 0x95, 0, 0, 0, CPU_XOP, 0, 0},
+ {"jne", jcc_insn, 9, SUF_Z, 0x05, 0, 0, 0, 0, 0, 0},
+ {"shldl", shlrd_insn, 9, SUF_L, 0xA4, 0, 0, 0, CPU_386, 0, 0},
+ {"cmc", onebyte_insn, 1, SUF_Z, 0xF5, 0, 0, 0, 0, 0, 0},
+ {"cmovs", cmovcc_insn, 3, SUF_Z, 0x08, 0, 0, 0, CPU_686, 0, 0},
+ {"movlpd", movhlp_insn, 3, SUF_Z, 0x66, 0x12, 0, 0, CPU_SSE2, 0, 0},
+ {"calll", call_insn, 30, SUF_L, 0, 0, 0, 0, CPU_386, 0, 0},
+ {"subb", arith_insn, 22, SUF_B, 0x28, 0x05, 0, 0, 0, 0, 0},
+ {"lmsww", prot286_insn, 1, SUF_W, 0x06, 0x01, 0, 0, CPU_286, CPU_Priv, 0},
+ {"vmrun", svm_rax_insn, 2, SUF_Z, 0xD8, 0, 0, 0, CPU_SVM, 0, 0},
+ {"cmovna", cmovcc_insn, 3, SUF_Z, 0x06, 0, 0, 0, CPU_686, 0, 0},
+ {"cmovnpw", cmovcc_insn, 3, SUF_W, 0x0B, 0, 0, 0, CPU_686, 0, 0},
+ {"bextrq", bextr_insn, 4, SUF_Q, 0, 0, 0, ONLY_64|ONLY_AVX, CPU_BMI1, 0, 0},
+ {"vpmacssww", vpma_insn, 1, SUF_Z, 0x85, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vdivss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5E, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movabsl", movabs_insn, 9, SUF_L, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"callw", call_insn, 30, SUF_W, 0, 0, 0, 0, 0, 0, 0},
+ {"vpcomlew", vpcom_insn, 1, SUF_Z, 0xCD, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"fninit", twobyte_insn, 1, SUF_Z, 0xDB, 0xE3, 0, 0, CPU_FPU, 0, 0},
+ {"vpavgw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xE3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpltpd", ssecmp_128_insn, 3, SUF_Z, 0x01, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cpuid", twobyte_insn, 1, SUF_Z, 0x0F, 0xA2, 0, 0, CPU_486, 0, 0},
+ {"pmovzxwq", sse4m32_insn, 4, SUF_Z, 0x34, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"cmovnaew", cmovcc_insn, 3, SUF_W, 0x02, 0, 0, 0, CPU_686, 0, 0},
+ {"comiss", xmm_xmm32_insn, 4, SUF_Z, 0x00, 0x2F, 0, 0, CPU_SSE, 0, 0},
+ {"cmovnoq", cmovcc_insn, 3, SUF_Q, 0x01, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"negb", f6_insn, 4, SUF_B, 0x03, 0, 0, 0, 0, 0, 0},
+ {"vfnmadd231sd", vfma_sd_insn, 2, SUF_Z, 0xBD, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"xchgw", xchg_insn, 16, SUF_W, 0, 0, 0, 0, 0, 0, 0},
+ {"rexz", NULL, X86_REX>>8, 0x41, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"sbb", arith_insn, 22, SUF_Z, 0x18, 0x03, 0, 0, 0, 0, 0},
+ {"lslw", larlsl_insn, 6, SUF_W, 0x03, 0, 0, 0, CPU_286, CPU_Prot, 0},
+ {"cmovnzw", cmovcc_insn, 3, SUF_W, 0x05, 0, 0, 0, CPU_686, 0, 0},
+ {"vfrczpd", vfrc_pdps_insn, 2, SUF_Z, 0x01, 0, 0, 0, CPU_XOP, 0, 0},
+ {"bsrw", bsfr_insn, 3, SUF_W, 0xBD, 0, 0, 0, CPU_386, 0, 0},
+ {"fcomps", fcom_insn, 6, SUF_S, 0xD8, 0x03, 0, 0, CPU_FPU, 0, 0},
+ {"rorx", vex_gpr_reg_rm_0F_imm8_insn, 2, SUF_Z, 0xF2, 0x3A, 0xF0, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"shufpd", xmm_xmm128_imm_insn, 1, SUF_Z, 0x66, 0xC6, 0, 0, CPU_SSE2, 0, 0},
+ {"vpcomleq", vpcom_insn, 1, SUF_Z, 0xCF, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpunordsd", ssecmp_64_insn, 4, SUF_Z, 0x03, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"minps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x5D, 0, 0, CPU_SSE, 0, 0},
+ {"vaesimc", aesimc_insn, 1, SUF_Z, 0x38, 0xDB, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movhps", movhlp_insn, 3, SUF_Z, 0x00, 0x16, 0, 0, CPU_SSE, 0, 0},
+ {"vdivps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x5E, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"filds", fildstp_insn, 4, SUF_S, 0x00, 0x02, 0x05, 0, CPU_FPU, 0, 0},
+ {"adc", arith_insn, 22, SUF_Z, 0x10, 0x02, 0, 0, 0, 0, 0},
+ {"vtestpd", sse4_insn, 2, SUF_Z, 0x0F, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pfpnacc", now3d_insn, 1, SUF_Z, 0x8E, 0, 0, 0, CPU_3DNow, CPU_Athlon, 0},
+ {"vmovsldup", avx_xmm_xmm128_insn, 2, SUF_Z, 0xF3, 0x12, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpbroadcastb", vpbroadcastb_avx2_insn, 4, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"sahf", onebyte_insn, 1, SUF_Z, 0x9E, 0, 0, 0, 0, 0, 0},
+ {"vmovhps", movhlp_insn, 3, SUF_Z, 0x00, 0x16, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fpatan", twobyte_insn, 1, SUF_Z, 0xD9, 0xF3, 0, 0, CPU_FPU, 0, 0},
+ {"psubw", mmxsse2_insn, 2, SUF_Z, 0xF9, 0, 0, 0, CPU_MMX, 0, 0},
+ {"sqrtss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x51, 0, 0, CPU_SSE, 0, 0},
+ {"vpminuw", ssse3_insn, 5, SUF_Z, 0x3A, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rex64z", NULL, X86_REX>>8, 0x49, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"cmovng", cmovcc_insn, 3, SUF_Z, 0x0E, 0, 0, 0, CPU_686, 0, 0},
+ {"cmovngq", cmovcc_insn, 3, SUF_Q, 0x0E, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"blcil", xop_gpr_reg_rm_09_insn, 2, SUF_L, 0x02, 0x06, 0, 0, CPU_386, CPU_TBM, 0},
+ {"setob", setcc_insn, 1, SUF_B, 0x00, 0, 0, 0, CPU_386, 0, 0},
+ {"xbts", xbts_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_Obs, CPU_Undoc},
+ {"loopne", loop_insn, 8, SUF_Z, 0x00, 0, 0, 0, 0, 0, 0},
+ {"fxch", fxch_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vfmsubadd132pd", vfma_pd_insn, 2, SUF_Z, 0x97, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vmovddup", vmovddup_insn, 3, SUF_Z, 0xF2, 0x12, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"enterq", enter_insn, 3, SUF_Q, 0, 0, 0, ONLY_64, CPU_186, 0, 0},
+ {"vpcomnequw", vpcom_insn, 1, SUF_Z, 0xED, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"vpunpckhdq", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x6A, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fnstenvs", onebytemem_insn, 1, SUF_S, 0x06, 0xD9, 0, 0, CPU_FPU, 0, 0},
+ {"phaddd", ssse3_insn, 5, SUF_Z, 0x02, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"vmovups", movau_insn, 6, SUF_Z, 0x00, 0x10, 0x01, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomneuq", vpcom_insn, 1, SUF_Z, 0xEF, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"imul", imul_insn, 19, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"fimuls", fiarith_insn, 2, SUF_S, 0x01, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"jg", jcc_insn, 9, SUF_Z, 0x0F, 0, 0, 0, 0, 0, 0},
+ {"fcoml", fcom_insn, 6, SUF_L, 0xD0, 0x02, 0, 0, CPU_FPU, 0, 0},
+ {"vxorpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x57, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmaddsubps", fma_128_256_insn, 4, SUF_Z, 0x5C, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"vpaddw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xFD, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vbroadcasti128", vbroadcastif128_insn, 1, SUF_Z, 0x5A, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vcvttpd2dqy", avx_cvt_xmm128_y_insn, 1, SUF_Z, 0x66, 0xE6, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"mov", mov_insn, 69, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"fmull", farith_insn, 7, SUF_L, 0xC8, 0xC8, 0x01, 0, CPU_FPU, 0, 0},
+ {"vpcomfalseub", vpcom_insn, 1, SUF_Z, 0xEC, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"xaddq", cmpxchgxadd_insn, 4, SUF_Q, 0xC0, 0, 0, ONLY_64, CPU_486, 0, 0},
+ {"inl", in_insn, 12, SUF_L, 0, 0, 0, 0, CPU_386, 0, 0},
+ {"t1mskcl", xop_gpr_reg_rm_09_insn, 2, SUF_L, 0x01, 0x07, 0, 0, CPU_386, CPU_TBM, 0},
+ {"nop", onebyte_insn, 1, SUF_Z, 0x90, 0, 0, 0, 0, 0, 0},
+ {"rexx", NULL, X86_REX>>8, 0x44, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"vperm2f128", vperm2f128_insn, 1, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"tzcnt", cnt_insn, 3, SUF_Z, 0xBC, 0, 0, 0, CPU_BMI1, 0, 0},
+ {"hlt", onebyte_insn, 1, SUF_Z, 0xF4, 0, 0, 0, CPU_Priv, 0, 0},
+ {"vcmpeq_uqpd", ssecmp_128_insn, 3, SUF_Z, 0x08, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sgdt", twobytemem_insn, 1, SUF_Z, 0x00, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"cwtl", onebyte_insn, 1, SUF_Z, 0x98, 0x20, 0, 0, CPU_386, 0, 0},
+ {"xorl", arith_insn, 22, SUF_L, 0x30, 0x06, 0, 0, CPU_386, 0, 0},
+ {"movapd", movau_insn, 6, SUF_Z, 0x66, 0x28, 0x01, 0, CPU_SSE2, 0, 0},
+ {"vpmovsxwq", sse4m32_insn, 4, SUF_Z, 0x24, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmsubadd231pd", vfma_pd_insn, 2, SUF_Z, 0xB7, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"cvttsd2sil", cvt_rx_xmm64_insn, 4, SUF_L, 0xF2, 0x2C, 0, 0, CPU_SSE2, 0, 0},
+ {"cmpunordss", ssecmp_32_insn, 4, SUF_Z, 0x03, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"vpcomneq", vpcom_insn, 1, SUF_Z, 0xCF, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"ffreep", ffree_insn, 1, SUF_Z, 0xDF, 0, 0, 0, CPU_686, CPU_FPU, CPU_Undoc},
+ {"vfnmsub213ss", vfma_ss_insn, 2, SUF_Z, 0xAF, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"outsb", onebyte_insn, 1, SUF_Z, 0x6E, 0x00, 0, 0, 0, 0, 0},
+ {"psubsiw", cyrixmmx_insn, 1, SUF_Z, 0x55, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"jng", jcc_insn, 9, SUF_Z, 0x0E, 0, 0, 0, 0, 0, 0},
+ {"vpcomltd", vpcom_insn, 1, SUF_Z, 0xCE, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"t1mskcq", xop_gpr_reg_rm_09_insn, 2, SUF_Q, 0x01, 0x07, 0, ONLY_64, CPU_TBM, 0, 0},
+ {"rdmsr", twobyte_insn, 1, SUF_Z, 0x0F, 0x32, 0, 0, CPU_586, CPU_Priv, 0},
+ {"notb", f6_insn, 4, SUF_B, 0x02, 0, 0, 0, 0, 0, 0},
+ {"idiv", div_insn, 8, SUF_Z, 0x07, 0, 0, 0, 0, 0, 0},
+ {"vpshuflw", xmm_xmm128_imm_256avx2_insn, 2, SUF_Z, 0xF2, 0x70, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"paddd", mmxsse2_insn, 2, SUF_Z, 0xFE, 0, 0, 0, CPU_MMX, 0, 0},
+ {"tzcntw", cnt_insn, 3, SUF_W, 0xBC, 0, 0, 0, CPU_BMI1, 0, 0},
+ {"pcmpgtd", mmxsse2_insn, 2, SUF_Z, 0x66, 0, 0, 0, CPU_MMX, 0, 0},
+ {"stosq", onebyte_insn, 1, SUF_Z, 0xAB, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"arplw", arpl_insn, 1, SUF_W, 0, 0, 0, NOT_64, CPU_286, CPU_Prot, 0},
+ {"vpermilps", vpermil_insn, 4, SUF_Z, 0x04, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmadd231ps", vfma_ps_insn, 2, SUF_Z, 0xBC, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"xadd", cmpxchgxadd_insn, 4, SUF_Z, 0xC0, 0, 0, 0, CPU_486, 0, 0},
+ {"shrdl", shlrd_insn, 9, SUF_L, 0xAC, 0, 0, 0, CPU_386, 0, 0},
+ {"fscale", twobyte_insn, 1, SUF_Z, 0xD9, 0xFD, 0, 0, CPU_FPU, 0, 0},
+ {"rdpmc", twobyte_insn, 1, SUF_Z, 0x0F, 0x33, 0, 0, CPU_686, 0, 0},
+ {"cvtpi2ps", cvt_xmm_mm_ps_insn, 1, SUF_Z, 0x2A, 0, 0, 0, CPU_SSE, 0, 0},
+ {"cmovgq", cmovcc_insn, 3, SUF_Q, 0x0F, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"vfnmsubps", fma_128_256_insn, 4, SUF_Z, 0x7C, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"seto", setcc_insn, 1, SUF_Z, 0x00, 0, 0, 0, CPU_386, 0, 0},
+ {"jnae", jcc_insn, 9, SUF_Z, 0x02, 0, 0, 0, 0, 0, 0},
+ {"popcntw", cnt_insn, 3, SUF_W, 0xB8, 0, 0, 0, CPU_SSE42, 0, 0},
+ {"vpgatherqd", gather_32x_32y_128_insn, 2, SUF_Z, 0x91, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"salc", onebyte_insn, 1, SUF_Z, 0xD6, 0, 0, NOT_64, CPU_Undoc, 0, 0},
+ {"vcmpngesd", ssecmp_64_insn, 4, SUF_Z, 0x09, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomgeud", vpcom_insn, 1, SUF_Z, 0xEE, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"blcicq", xop_gpr_reg_rm_09_insn, 2, SUF_Q, 0x01, 0x05, 0, ONLY_64, CPU_TBM, 0, 0},
+ {"pcmpestri", sse4pcmpstr_insn, 1, SUF_Z, 0x61, 0, 0, 0, CPU_SSE42, 0, 0},
+ {"sarxq", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_Q, 0xF3, 0x38, 0xF7, ONLY_64|ONLY_AVX, CPU_BMI2, 0, 0},
+ {"lddqu", lddqu_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_SSE3, 0, 0},
+ {"vpcomtruew", vpcom_insn, 1, SUF_Z, 0xCD, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"fxam", twobyte_insn, 1, SUF_Z, 0xD9, 0xE5, 0, 0, CPU_FPU, 0, 0},
+ {"crc32b", crc32_insn, 5, SUF_B, 0, 0, 0, 0, CPU_386, CPU_SSE42, 0},
+ {"vpinsrw", pinsrw_insn, 9, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vphsubdq", vphaddsub_insn, 1, SUF_Z, 0xE3, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vfmsubaddps", fma_128_256_insn, 4, SUF_Z, 0x5E, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"btw", bittest_insn, 6, SUF_W, 0xA3, 0x04, 0, 0, CPU_386, 0, 0},
+ {"pi2fw", now3d_insn, 1, SUF_Z, 0x0C, 0, 0, 0, CPU_3DNow, CPU_Athlon, 0},
+ {"movhlps", movhllhps_insn, 2, SUF_Z, 0x12, 0, 0, 0, CPU_SSE, 0, 0},
+ {"divsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5E, 0, 0, CPU_SSE2, 0, 0},
+ {"vcmpge_oqps", ssecmp_128_insn, 3, SUF_Z, 0x1D, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rexxyz", NULL, X86_REX>>8, 0x47, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"pf2id", now3d_insn, 1, SUF_Z, 0x1D, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"andnps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x55, 0, 0, CPU_SSE, 0, 0},
+ {"cmovzq", cmovcc_insn, 3, SUF_Q, 0x04, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"cwd", onebyte_insn, 1, SUF_Z, 0x99, 0x10, 0, 0, 0, 0, 0},
+ {"blcsl", xop_gpr_reg_rm_09_insn, 2, SUF_L, 0x01, 0x03, 0, 0, CPU_386, CPU_TBM, 0},
+ {"maxps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x5F, 0, 0, CPU_SSE, 0, 0},
+ {"comisd", xmm_xmm64_insn, 4, SUF_Z, 0x66, 0x2F, 0, 0, CPU_SSE2, 0, 0},
+ {"vcmpnle_uqps", ssecmp_128_insn, 3, SUF_Z, 0x16, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovnzq", cmovcc_insn, 3, SUF_Q, 0x05, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"ljmpw", ljmpcall_insn, 7, SUF_W, 0x05, 0xEA, 0, 0, 0, 0, 0},
+ {"cmpeqps", ssecmp_128_insn, 3, SUF_Z, 0x00, 0, 0, 0, CPU_SSE, 0, 0},
+ {"orb", arith_insn, 22, SUF_B, 0x08, 0x01, 0, 0, 0, 0, 0},
+ {"fists", fiarith_insn, 2, SUF_S, 0x02, 0xDB, 0, 0, CPU_FPU, 0, 0},
+ {"vmaskmovps", vmaskmov_insn, 4, SUF_Z, 0x2C, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"xend", tsx_0x0F_0x01_insn, 1, SUF_Z, 0xD5, 0, 0, 0, CPU_TSX, 0, 0},
+ {"fiadd", fiarith_insn, 2, SUF_Z, 0x00, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"jns", jcc_insn, 9, SUF_Z, 0x09, 0, 0, 0, 0, 0, 0},
+ {"vpcomfalseuw", vpcom_insn, 1, SUF_Z, 0xED, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"bsrl", bsfr_insn, 3, SUF_L, 0xBD, 0, 0, 0, CPU_386, 0, 0},
+ {"pabsb", ssse3_insn, 5, SUF_Z, 0x1C, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"vcmptruess", ssecmp_32_insn, 4, SUF_Z, 0x0F, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sal", shift_insn, 16, SUF_Z, 0x04, 0, 0, 0, 0, 0, 0},
+ {"movzbl", movszx_insn, 5, SUF_B, 0xB6, 0, 0, 0, CPU_386, 0, 0},
+ {"packssdw", mmxsse2_insn, 2, SUF_Z, 0x6B, 0, 0, 0, CPU_MMX, 0, 0},
+ {"fcmovbe", fcmovcc_insn, 1, SUF_Z, 0xDA, 0xD0, 0, 0, CPU_686, CPU_FPU, 0},
+ {"orq", arith_insn, 22, SUF_Q, 0x08, 0x01, 0, ONLY_64, 0, 0, 0},
+ {"blsicq", xop_gpr_reg_rm_09_insn, 2, SUF_Q, 0x01, 0x06, 0, ONLY_64, CPU_TBM, 0, 0},
+ {"fiaddl", fiarith_insn, 2, SUF_L, 0x00, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"fprem", twobyte_insn, 1, SUF_Z, 0xD9, 0xF8, 0, 0, CPU_FPU, 0, 0},
+ {"vpcomltw", vpcom_insn, 1, SUF_Z, 0xCD, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"sarl", shift_insn, 16, SUF_L, 0x07, 0, 0, 0, CPU_386, 0, 0},
+ {"shr", shift_insn, 16, SUF_Z, 0x05, 0, 0, 0, 0, 0, 0},
+ {"pushl", push_insn, 35, SUF_L, 0, 0, 0, 0, CPU_386, 0, 0},
+ {"imull", imul_insn, 19, SUF_L, 0, 0, 0, 0, CPU_386, 0, 0},
+ {"ftst", twobyte_insn, 1, SUF_Z, 0xD9, 0xE4, 0, 0, CPU_FPU, 0, 0},
+ {"vcmpeqps", ssecmp_128_insn, 3, SUF_Z, 0x00, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lcalll", ljmpcall_insn, 7, SUF_L, 0x03, 0x9A, 0, 0, CPU_386, 0, 0},
+ {"lock", NULL, X86_LOCKREP>>8, 0xF0, 0, 0, 0, 0, 0, 0, 0},
+ {"cmovnbw", cmovcc_insn, 3, SUF_W, 0x03, 0, 0, 0, CPU_686, 0, 0},
+ {"movzxw", movszx_insn, 5, SUF_W, 0xB6, 0, 0, 0, CPU_386, 0, 0},
+ {"or", arith_insn, 22, SUF_Z, 0x08, 0x01, 0, 0, 0, 0, 0},
+ {"vcmpnle_uqpd", ssecmp_128_insn, 3, SUF_Z, 0x16, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setl", setcc_insn, 1, SUF_Z, 0x0C, 0, 0, 0, CPU_386, 0, 0},
+ {"movntiq", movnti_insn, 2, SUF_Q, 0, 0, 0, ONLY_64, CPU_P4, 0, 0},
+ {"lfs", lfgss_insn, 3, SUF_Z, 0xB4, 0, 0, 0, CPU_386, 0, 0},
+ {"vroundss", sse4m32imm_insn, 4, SUF_Z, 0x0A, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setzb", setcc_insn, 1, SUF_B, 0x04, 0, 0, 0, CPU_386, 0, 0},
+ {"pcmpistrm", sse4pcmpstr_insn, 1, SUF_Z, 0x62, 0, 0, 0, CPU_SSE42, 0, 0},
+ {"je", jcc_insn, 9, SUF_Z, 0x04, 0, 0, 0, 0, 0, 0},
+ {"psraw", pshift_insn, 4, SUF_Z, 0xE1, 0x71, 0x04, 0, CPU_MMX, 0, 0},
+ {"shlx", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_Z, 0x66, 0x38, 0xF7, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"mfence", threebyte_insn, 1, SUF_Z, 0x0F, 0xAE, 0xF0, 0, CPU_P3, 0, 0},
+ {"vcvtsd2siq", cvt_rx_xmm64_insn, 4, SUF_Q, 0xF2, 0x2D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vtestps", sse4_insn, 2, SUF_Z, 0x0E, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"verww", prot286_insn, 1, SUF_W, 0x05, 0x00, 0, 0, CPU_286, CPU_Prot, 0},
+ {"vfmsubaddpd", fma_128_256_insn, 4, SUF_Z, 0x5F, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"fyl2xp1", twobyte_insn, 1, SUF_Z, 0xD9, 0xF9, 0, 0, CPU_FPU, 0, 0},
+ {"vunpckhpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x15, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vsubps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x5C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"divss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5E, 0, 0, CPU_SSE, 0, 0},
+ {"blcfilll", xop_gpr_reg_rm_09_insn, 2, SUF_L, 0x01, 0x01, 0, 0, CPU_386, CPU_TBM, 0},
+ {"vcmptrue_uspd", ssecmp_128_insn, 3, SUF_Z, 0x1F, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vorpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x56, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setgeb", setcc_insn, 1, SUF_B, 0x0D, 0, 0, 0, CPU_386, 0, 0},
+ {"vmxon", vmxthreebytemem_insn, 1, SUF_Z, 0xF3, 0, 0, 0, CPU_P4, 0, 0},
+ {"vpmaskmovd", vmaskmov_insn, 4, SUF_Z, 0x8C, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vfnmaddpd", fma_128_256_insn, 4, SUF_Z, 0x79, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"cmovpl", cmovcc_insn, 3, SUF_L, 0x0A, 0, 0, 0, CPU_686, 0, 0},
+ {"pabsw", ssse3_insn, 5, SUF_Z, 0x1D, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"cmovnge", cmovcc_insn, 3, SUF_Z, 0x0C, 0, 0, 0, CPU_686, 0, 0},
+ {"aword", NULL, X86_ADDRSIZE>>8, 0x10, 0, 0, 0, 0, 0, 0, 0},
+ {"sscaq", onebyte_insn, 1, SUF_Z, 0xAF, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"fstenvs", twobytemem_insn, 1, SUF_S, 0x06, 0x9B, 0xD9, 0, CPU_FPU, 0, 0},
+ {"vpmovzxbw", sse4m64_insn, 4, SUF_Z, 0x30, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpsllw", vpshift_insn, 8, SUF_Z, 0xF1, 0x71, 0x06, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpabsw", avx2_ssse3_2op_insn, 2, SUF_Z, 0x1D, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"popf", onebyte_insn, 1, SUF_Z, 0x9D, 0x00, 0x40, 0, 0, 0, 0},
+ {"vcmpunord_sss", ssecmp_32_insn, 4, SUF_Z, 0x13, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"bsf", bsfr_insn, 3, SUF_Z, 0xBC, 0, 0, 0, CPU_386, 0, 0},
+ {"cmovaw", cmovcc_insn, 3, SUF_W, 0x07, 0, 0, 0, CPU_686, 0, 0},
+ {"psrlq", pshift_insn, 4, SUF_Z, 0xD3, 0x73, 0x02, 0, CPU_MMX, 0, 0},
+ {"divw", div_insn, 8, SUF_W, 0x06, 0, 0, 0, 0, 0, 0},
+ {"cmovnal", cmovcc_insn, 3, SUF_L, 0x06, 0, 0, 0, CPU_686, 0, 0},
+ {"vpcmpeqq", ssse3_insn, 5, SUF_Z, 0x29, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovnaq", cmovcc_insn, 3, SUF_Q, 0x06, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"cmove", cmovcc_insn, 3, SUF_Z, 0x04, 0, 0, 0, CPU_686, 0, 0},
+ {"popaw", onebyte_insn, 1, SUF_Z, 0x61, 0x10, 0, NOT_64, CPU_186, 0, 0},
+ {"invvpidq", eptvpid_insn, 2, SUF_Q, 0x01, 0, 0, ONLY_64, CPU_EPTVPID, 0, 0},
+ {"vcvtdq2ps", avx_xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x5B, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vrcpps", avx_xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x53, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"packsswb", mmxsse2_insn, 2, SUF_Z, 0x63, 0, 0, 0, CPU_MMX, 0, 0},
+ {"sarw", shift_insn, 16, SUF_W, 0x07, 0, 0, 0, 0, 0, 0},
+ {"pfrcpit1", now3d_insn, 1, SUF_Z, 0xA6, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"btcl", bittest_insn, 6, SUF_L, 0xBB, 0x07, 0, 0, CPU_386, 0, 0},
+ {"rolb", shift_insn, 16, SUF_B, 0x00, 0, 0, 0, 0, 0, 0},
+ {"vphadddq", vphaddsub_insn, 1, SUF_Z, 0xCB, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpmaxsw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xEE, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpminsw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xEA, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jnz", jcc_insn, 9, SUF_Z, 0x05, 0, 0, 0, 0, 0, 0},
+ {"vphsubd", ssse3_insn, 5, SUF_Z, 0x06, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vblendvps", avx_sse4xmm0_insn, 2, SUF_Z, 0x4A, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vhaddps", xmm_xmm128_256_insn, 4, SUF_Z, 0xF2, 0x7C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lidtl", twobytemem_insn, 1, SUF_L, 0x03, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"divq", div_insn, 8, SUF_Q, 0x06, 0, 0, ONLY_64, 0, 0, 0},
+ {"outb", out_insn, 12, SUF_B, 0, 0, 0, 0, 0, 0, 0},
+ {"setnsb", setcc_insn, 1, SUF_B, 0x09, 0, 0, 0, CPU_386, 0, 0},
+ {"vcmpfalse_ospd", ssecmp_128_insn, 3, SUF_Z, 0x1B, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jnb", jcc_insn, 9, SUF_Z, 0x03, 0, 0, 0, 0, 0, 0},
+ {"vpmovsxdq", sse4m64_insn, 4, SUF_Z, 0x25, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"adcw", arith_insn, 22, SUF_W, 0x10, 0x02, 0, 0, 0, 0, 0},
+ {"cmovbel", cmovcc_insn, 3, SUF_L, 0x06, 0, 0, 0, CPU_686, 0, 0},
+ {"cmovaeq", cmovcc_insn, 3, SUF_Q, 0x03, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"fcmovnu", fcmovcc_insn, 1, SUF_Z, 0xDB, 0xD8, 0, 0, CPU_686, CPU_FPU, 0},
+ {"idivb", div_insn, 8, SUF_B, 0x07, 0, 0, 0, 0, 0, 0},
+ {"sgdtl", twobytemem_insn, 1, SUF_L, 0x00, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"jmpl", jmp_insn, 31, SUF_L, 0, 0, 0, 0, CPU_386, 0, 0},
+ {"fisttp", fildstp_insn, 4, SUF_Z, 0x01, 0x00, 0x01, 0, CPU_SSE3, 0, 0},
+ {"vcmpord_sps", ssecmp_128_insn, 3, SUF_Z, 0x17, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"haddps", xmm_xmm128_insn, 2, SUF_Z, 0xF2, 0x7C, 0, 0, CPU_SSE3, 0, 0},
+ {"rolw", shift_insn, 16, SUF_W, 0x00, 0, 0, 0, 0, 0, 0},
+ {"vcvtpd2dqy", avx_cvt_xmm128_y_insn, 1, SUF_Z, 0xF2, 0xE6, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"bt", bittest_insn, 6, SUF_Z, 0xA3, 0x04, 0, 0, CPU_386, 0, 0},
+ {"vcmpfalsepd", ssecmp_128_insn, 3, SUF_Z, 0x0B, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpleps", ssecmp_128_insn, 3, SUF_Z, 0x02, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vphaddubd", vphaddsub_insn, 1, SUF_Z, 0xD2, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vfnmsub132ss", vfma_ss_insn, 2, SUF_Z, 0x9F, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"cmovnow", cmovcc_insn, 3, SUF_W, 0x01, 0, 0, 0, CPU_686, 0, 0},
+ {"cvtps2dq", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x5B, 0, 0, CPU_SSE2, 0, 0},
+ {"bsrq", bsfr_insn, 3, SUF_Q, 0xBD, 0, 0, ONLY_64, CPU_386, 0, 0},
+ {"vcmpord_spd", ssecmp_128_insn, 3, SUF_Z, 0x17, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomd", vpcom_imm_insn, 1, SUF_Z, 0xCE, 0, 0, 0, CPU_XOP, 0, 0},
+ {"jnle", jcc_insn, 9, SUF_Z, 0x0F, 0, 0, 0, 0, 0, 0},
+ {"vhsubps", xmm_xmm128_256_insn, 4, SUF_Z, 0xF2, 0x7D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jcxz", jcxz_insn, 2, SUF_Z, 0x10, 0, 0, 0, 0, 0, 0},
+ {"fsavel", twobytemem_insn, 1, SUF_L, 0x06, 0x9B, 0xDD, 0, CPU_FPU, 0, 0},
+ {"cmovnbq", cmovcc_insn, 3, SUF_Q, 0x03, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"lidtw", twobytemem_insn, 1, SUF_W, 0x03, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"vcvtss2si", cvt_rx_xmm32_insn, 4, SUF_Z, 0xF3, 0x2D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"mulw", f6_insn, 4, SUF_W, 0x04, 0, 0, 0, 0, 0, 0},
+ {"vbroadcastsd", vbroadcastsd_insn, 2, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovlel", cmovcc_insn, 3, SUF_L, 0x0E, 0, 0, 0, CPU_686, 0, 0},
+ {"pmovmskbq", pmovmskb_insn, 6, SUF_Q, 0, 0, 0, ONLY_64, CPU_MMX, CPU_P3, 0},
+ {"frstorl", onebytemem_insn, 1, SUF_L, 0x04, 0xDD, 0, 0, CPU_FPU, 0, 0},
+ {"cvttss2si", cvt_rx_xmm32_insn, 4, SUF_Z, 0xF3, 0x2C, 0, 0, CPU_386, CPU_SSE, 0},
+ {"cmpnltpd", ssecmp_128_insn, 3, SUF_Z, 0x05, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"vpcomgtw", vpcom_insn, 1, SUF_Z, 0xCD, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"xaddl", cmpxchgxadd_insn, 4, SUF_L, 0xC0, 0, 0, 0, CPU_486, 0, 0},
+ {"vpmulhw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xE5, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lgsq", lfgss_insn, 3, SUF_Q, 0xB5, 0, 0, ONLY_64, CPU_386, 0, 0},
+ {"boundl", bound_insn, 2, SUF_L, 0, 0, 0, NOT_64, CPU_386, 0, 0},
+ {"vmaxpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x5F, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movntdqa", movntdqa_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"xstorerng", padlock_insn, 1, SUF_Z, 0xC0, 0x00, 0xA7, 0, CPU_PadLock, 0, 0},
+ {"fxsaveq", twobytemem_insn, 1, SUF_Q, 0x00, 0x0F, 0xAE, 0, CPU_686, CPU_FPU, 0},
+ {"cmplepd", ssecmp_128_insn, 3, SUF_Z, 0x02, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"vpunpckhwd", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x69, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fiadds", fiarith_insn, 2, SUF_S, 0x00, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"bsfq", bsfr_insn, 3, SUF_Q, 0xBC, 0, 0, ONLY_64, CPU_386, 0, 0},
+ {"cvtss2si", cvt_rx_xmm32_insn, 4, SUF_Z, 0xF3, 0x2D, 0, 0, CPU_386, CPU_SSE, 0},
+ {"pushw", push_insn, 35, SUF_W, 0, 0, 0, 0, 0, 0, 0},
+ {"vphaddsw", ssse3_insn, 5, SUF_Z, 0x03, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"prefetcht2", twobytemem_insn, 1, SUF_Z, 0x03, 0x0F, 0x18, 0, CPU_P3, 0, 0},
+ {"setnae", setcc_insn, 1, SUF_Z, 0x02, 0, 0, 0, CPU_386, 0, 0},
+ {"xor", arith_insn, 22, SUF_Z, 0x30, 0x06, 0, 0, 0, 0, 0},
+ {"pshufw", pshufw_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"div", div_insn, 8, SUF_Z, 0x06, 0, 0, 0, 0, 0, 0},
+ {"xabort", tsx_xabort_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_TSX, 0, 0},
+ {"vmovntdq", movnt_insn, 2, SUF_Z, 0x66, 0xE7, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"das", onebyte_insn, 1, SUF_Z, 0x2F, 0, 0, NOT_64, 0, 0, 0},
+ {"notw", f6_insn, 4, SUF_W, 0x02, 0, 0, 0, 0, 0, 0},
+ {"monitor", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xC8, 0, CPU_SSE3, 0, 0},
+ {"pmuludq", mmxsse2_insn, 2, SUF_Z, 0xF4, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"psignd", ssse3_insn, 5, SUF_Z, 0x0A, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"vpmaxuw", ssse3_insn, 5, SUF_Z, 0x3E, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rexxy", NULL, X86_REX>>8, 0x46, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"vcmpnlt_uqps", ssecmp_128_insn, 3, SUF_Z, 0x15, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"decq", incdec_insn, 6, SUF_Q, 0x48, 0x01, 0, ONLY_64, 0, 0, 0},
+ {"fsub", farith_insn, 7, SUF_Z, 0xE8, 0xE0, 0x04, 0, CPU_FPU, 0, 0},
+ {"ficoms", fiarith_insn, 2, SUF_S, 0x02, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"btrw", bittest_insn, 6, SUF_W, 0xB3, 0x06, 0, 0, CPU_386, 0, 0},
+ {"vfnmsub213sd", vfma_sd_insn, 2, SUF_Z, 0xAF, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"setnob", setcc_insn, 1, SUF_B, 0x01, 0, 0, 0, CPU_386, 0, 0},
+ {"vpcomgeub", vpcom_insn, 1, SUF_Z, 0xEC, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"cmovz", cmovcc_insn, 3, SUF_Z, 0x04, 0, 0, 0, CPU_686, 0, 0},
+ {"vpackuswb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x67, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cli", onebyte_insn, 1, SUF_Z, 0xFA, 0, 0, 0, 0, 0, 0},
+ {"pinsrd", pinsrd_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_SSE41, 0},
+ {"vfmsubadd213pd", vfma_pd_insn, 2, SUF_Z, 0xA7, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"setnab", setcc_insn, 1, SUF_B, 0x06, 0, 0, 0, CPU_386, 0, 0},
+ {"larw", larlsl_insn, 6, SUF_W, 0x02, 0, 0, 0, CPU_286, CPU_Prot, 0},
+ {"pusha", onebyte_insn, 1, SUF_Z, 0x60, 0x00, 0, NOT_64, CPU_186, 0, 0},
+ {"pfadd", now3d_insn, 1, SUF_Z, 0x9E, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"bzhil", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_L, 0x00, 0x38, 0xF5, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"cmovpoq", cmovcc_insn, 3, SUF_Q, 0x0B, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"blsfill", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x01, 0x02, 0, 0, CPU_386, CPU_TBM, 0},
+ {"cdq", onebyte_insn, 1, SUF_Z, 0x99, 0x20, 0, 0, CPU_386, 0, 0},
+ {"cvtss2siq", cvt_rx_xmm32_insn, 4, SUF_Q, 0xF3, 0x2D, 0, ONLY_64, CPU_SSE, 0, 0},
+ {"cmovnb", cmovcc_insn, 3, SUF_Z, 0x03, 0, 0, 0, CPU_686, 0, 0},
+ {"vcvttsd2siq", cvt_rx_xmm64_insn, 4, SUF_Q, 0xF2, 0x2C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setae", setcc_insn, 1, SUF_Z, 0x03, 0, 0, 0, CPU_386, 0, 0},
+ {"movntps", movnt_insn, 2, SUF_Z, 0x00, 0x2B, 0, 0, CPU_SSE, 0, 0},
+ {"vcmpneq_oqpd", ssecmp_128_insn, 3, SUF_Z, 0x0C, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lssq", lfgss_insn, 3, SUF_Q, 0xB2, 0, 0, ONLY_64, CPU_386, 0, 0},
+ {"jpe", jcc_insn, 9, SUF_Z, 0x0A, 0, 0, 0, 0, 0, 0},
+ {"fstcww", fstcw_insn, 1, SUF_W, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"fnsave", onebytemem_insn, 1, SUF_Z, 0x06, 0xDD, 0, 0, CPU_FPU, 0, 0},
+ {"movntsd", movntsd_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SSE4a, 0, 0},
+ {"pblendvb", sse4xmm0_insn, 2, SUF_Z, 0x10, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"enterw", enter_insn, 3, SUF_W, 0, 0, 0, 0, CPU_186, 0, 0},
+ {"larl", larlsl_insn, 6, SUF_L, 0x02, 0, 0, 0, CPU_286, CPU_Prot, 0},
+ {"blendvps", sse4xmm0_insn, 2, SUF_Z, 0x14, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"pdepl", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_L, 0xF2, 0x38, 0xF5, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"jecxz", jcxz_insn, 2, SUF_Z, 0x20, 0, 0, 0, CPU_386, 0, 0},
+ {"blcmsk", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x02, 0x01, 0, 0, CPU_386, CPU_TBM, 0},
+ {"vpshad", amd_vpshift_insn, 2, SUF_Z, 0x9A, 0, 0, 0, CPU_XOP, 0, 0},
+ {"smsw", sldtmsw_insn, 6, SUF_Z, 0x04, 0x01, 0, 0, CPU_286, 0, 0},
+ {"vcvttps2dq", avx_xmm_xmm128_insn, 2, SUF_Z, 0xF3, 0x5B, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvttss2si", cvt_rx_xmm32_insn, 4, SUF_Z, 0xF3, 0x2C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovcw", cmovcc_insn, 3, SUF_W, 0x02, 0, 0, 0, CPU_686, 0, 0},
+ {"vpsubsb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xE8, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pfsubr", now3d_insn, 1, SUF_Z, 0xAA, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"dpps", sse4imm_insn, 2, SUF_Z, 0x40, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"pmulhrwc", cyrixmmx_insn, 1, SUF_Z, 0x59, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"fdecstp", twobyte_insn, 1, SUF_Z, 0xD9, 0xF6, 0, 0, CPU_FPU, 0, 0},
+ {"fld1", twobyte_insn, 1, SUF_Z, 0xD9, 0xE8, 0, 0, CPU_FPU, 0, 0},
+ {"lslq", larlsl_insn, 6, SUF_Q, 0x03, 0, 0, ONLY_64, CPU_286, CPU_Prot, 0},
+ {"movsldup", xmm_xmm128_insn, 2, SUF_Z, 0xF3, 0x12, 0, 0, CPU_SSE3, 0, 0},
+ {"vfnmadd213ps", vfma_ps_insn, 2, SUF_Z, 0xAC, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vorps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x56, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fxtract", twobyte_insn, 1, SUF_Z, 0xD9, 0xF4, 0, 0, CPU_FPU, 0, 0},
+ {"xrstor", twobytemem_insn, 1, SUF_Z, 0x05, 0x0F, 0xAE, 0, CPU_386, CPU_XSAVE, 0},
+ {"vfnmadd132pd", vfma_pd_insn, 2, SUF_Z, 0x9C, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"cmovsw", cmovcc_insn, 3, SUF_W, 0x08, 0, 0, 0, CPU_686, 0, 0},
+ {"vpcomnew", vpcom_insn, 1, SUF_Z, 0xCD, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"cmovc", cmovcc_insn, 3, SUF_Z, 0x02, 0, 0, 0, CPU_686, 0, 0},
+ {"cmpxchg8bq", cmpxchg8b_insn, 1, SUF_Q, 0, 0, 0, 0, CPU_586, 0, 0},
+ {"roundss", sse4m32imm_insn, 4, SUF_Z, 0x0A, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vsqrtss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x51, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rcrb", shift_insn, 16, SUF_B, 0x03, 0, 0, 0, 0, 0, 0},
+ {"vmptrld", vmxtwobytemem_insn, 1, SUF_Z, 0x06, 0, 0, 0, CPU_P4, 0, 0},
+ {"popal", onebyte_insn, 1, SUF_Z, 0x61, 0x20, 0, NOT_64, CPU_386, 0, 0},
+ {"sysretq", twobyte_insn, 1, SUF_Q, 0x0F, 0x07, 0, 0, CPU_686, CPU_AMD, CPU_Priv},
+ {"setle", setcc_insn, 1, SUF_Z, 0x0E, 0, 0, 0, CPU_386, 0, 0},
+ {"jnl", jcc_insn, 9, SUF_Z, 0x0D, 0, 0, 0, 0, 0, 0},
+ {"ucomisd", xmm_xmm64_insn, 4, SUF_Z, 0x66, 0x2E, 0, 0, CPU_SSE2, 0, 0},
+ {"sbbw", arith_insn, 22, SUF_W, 0x18, 0x03, 0, 0, 0, 0, 0},
+ {"fbstp", fbldstp_insn, 1, SUF_Z, 0x06, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vpcomtrueub", vpcom_insn, 1, SUF_Z, 0xEC, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"paddb", mmxsse2_insn, 2, SUF_Z, 0xFC, 0, 0, 0, CPU_MMX, 0, 0},
+ {"cmovnll", cmovcc_insn, 3, SUF_L, 0x0D, 0, 0, 0, CPU_686, 0, 0},
+ {"cvtss2sd", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5A, 0, 0, CPU_SSE2, 0, 0},
+ {"vpcmpeqd", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x76, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovnl", cmovcc_insn, 3, SUF_Z, 0x0D, 0, 0, 0, CPU_686, 0, 0},
+ {"vpcomltb", vpcom_insn, 1, SUF_Z, 0xCC, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"setngb", setcc_insn, 1, SUF_B, 0x0E, 0, 0, 0, CPU_386, 0, 0},
+ {"vphaddudq", vphaddsub_insn, 1, SUF_Z, 0xDB, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpmovsxbd", sse4m32_insn, 4, SUF_Z, 0x21, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"loopzq", loopq_insn, 4, SUF_Z, 0x01, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"cmovnle", cmovcc_insn, 3, SUF_Z, 0x0F, 0, 0, 0, CPU_686, 0, 0},
+ {"vcmpgepd", ssecmp_128_insn, 3, SUF_Z, 0x0D, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"btcq", bittest_insn, 6, SUF_Q, 0xBB, 0x07, 0, ONLY_64, CPU_386, 0, 0},
+ {"rcrl", shift_insn, 16, SUF_L, 0x03, 0, 0, 0, CPU_386, 0, 0},
+ {"vmovntdqa", movntdqa_insn, 2, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovcl", cmovcc_insn, 3, SUF_L, 0x02, 0, 0, 0, CPU_686, 0, 0},
+ {"vcmpeq_ospd", ssecmp_128_insn, 3, SUF_Z, 0x10, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"f2xm1", twobyte_insn, 1, SUF_Z, 0xD9, 0xF0, 0, 0, CPU_FPU, 0, 0},
+ {"vpmacssdd", vpma_insn, 1, SUF_Z, 0x8E, 0, 0, 0, CPU_XOP, 0, 0},
+ {"leal", lea_insn, 3, SUF_L, 0, 0, 0, 0, CPU_386, 0, 0},
+ {"vpcomeqd", vpcom_insn, 1, SUF_Z, 0xCE, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"ljmpq", ljmpcall_insn, 7, SUF_Q, 0x05, 0xEA, 0, ONLY_64, 0, 0, 0},
+ {"vpbroadcastd", vpbroadcastd_avx2_insn, 4, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"jnp", jcc_insn, 9, SUF_Z, 0x0B, 0, 0, 0, 0, 0, 0},
+ {"vpcomgeuq", vpcom_insn, 1, SUF_Z, 0xEF, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"prefetchnta", twobytemem_insn, 1, SUF_Z, 0x00, 0x0F, 0x18, 0, CPU_P3, 0, 0},
+ {"bswapl", bswap_insn, 2, SUF_L, 0, 0, 0, 0, CPU_486, 0, 0},
+ {"pmovsxbd", sse4m32_insn, 4, SUF_Z, 0x21, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"lzcnt", cnt_insn, 3, SUF_Z, 0xBD, 0, 0, 0, CPU_LZCNT, 0, 0},
+ {"sha256msg1", intel_SHA256MSG1_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SHA, 0, 0},
+ {"cmovnaw", cmovcc_insn, 3, SUF_W, 0x06, 0, 0, 0, CPU_686, 0, 0},
+ {"ficom", fiarith_insn, 2, SUF_Z, 0x02, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"vmovntpd", movnt_insn, 2, SUF_Z, 0x66, 0x2B, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpngess", ssecmp_32_insn, 4, SUF_Z, 0x09, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fisubr", fiarith_insn, 2, SUF_Z, 0x05, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"vfmaddsub132ps", vfma_ps_insn, 2, SUF_Z, 0x96, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vaddsubps", xmm_xmm128_256_insn, 4, SUF_Z, 0xF2, 0xD0, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpbroadcastq", vpbroadcastq_avx2_insn, 4, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"cmovlq", cmovcc_insn, 3, SUF_Q, 0x0C, 0, 0, ONLY_64, CPU_686, 0, 0},
+ {"inveptq", eptvpid_insn, 2, SUF_Q, 0x00, 0, 0, ONLY_64, CPU_EPTVPID, 0, 0},
+ {"vmulps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x59, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pclmulqdq", pclmulqdq_insn, 2, SUF_Z, 0x3A, 0x44, 0, 0, CPU_AVX, 0, 0},
+ {"vfmsub213ps", vfma_ps_insn, 2, SUF_Z, 0xAA, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"phsubd", ssse3_insn, 5, SUF_Z, 0x06, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"fmulp", farithp_insn, 3, SUF_Z, 0xC8, 0, 0, 0, CPU_FPU, 0, 0},
+ {"lcallw", ljmpcall_insn, 7, SUF_W, 0x03, 0x9A, 0, 0, 0, 0, 0},
+ {"fisub", fiarith_insn, 2, SUF_Z, 0x04, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"vpackusdw", ssse3_insn, 5, SUF_Z, 0x2B, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"smintold", twobyte_insn, 1, SUF_Z, 0x0F, 0x7E, 0, 0, CPU_486, CPU_Cyrix, CPU_Obs},
+ {"vpgatherqq", gather_64x_64y_insn, 2, SUF_Z, 0x91, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vcmpneq_uspd", ssecmp_128_insn, 3, SUF_Z, 0x14, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"blsiq", vex_gpr_ndd_rm_0F38_regext_insn, 2, SUF_Q, 0x00, 0xF3, 0x03, ONLY_64|ONLY_AVX, CPU_BMI1, 0, 0},
+ {"ltr", prot286_insn, 1, SUF_Z, 0x03, 0x00, 0, 0, CPU_286, CPU_Priv, CPU_Prot},
+ {"fild", fildstp_insn, 4, SUF_Z, 0x00, 0x02, 0x05, 0, CPU_FPU, 0, 0},
+ {"fldenvs", onebytemem_insn, 1, SUF_S, 0x04, 0xD9, 0, 0, CPU_FPU, 0, 0},
+ {"vmovdqa", movau_insn, 6, SUF_Z, 0x66, 0x6F, 0x10, ONLY_AVX, CPU_AVX, 0, 0},
+ {"shrxq", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_Q, 0xF2, 0x38, 0xF7, ONLY_64|ONLY_AVX, CPU_BMI2, 0, 0},
+ {"fcmove", fcmovcc_insn, 1, SUF_Z, 0xDA, 0xC8, 0, 0, CPU_686, CPU_FPU, 0},
+ {"shrl", shift_insn, 16, SUF_L, 0x05, 0, 0, 0, CPU_386, 0, 0},
+ {"rclq", shift_insn, 16, SUF_Q, 0x02, 0, 0, ONLY_64, 0, 0, 0},
+ {"fnsavel", onebytemem_insn, 1, SUF_L, 0x06, 0xDD, 0, 0, CPU_FPU, 0, 0},
+ {"vgatherdpd", gather_64x_64x_insn, 2, SUF_Z, 0x92, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"pushaw", onebyte_insn, 1, SUF_Z, 0x60, 0x10, 0, NOT_64, CPU_186, 0, 0}
+ };
+ static const unsigned short tab[] = {
+ 555,1559,555,108,108,1495,0,108,0,0,2332,555,1208,0,108,1317,
+ 1317,1732,0,0,1495,555,463,517,1636,1317,988,0,1317,0,555,555,
+ 1929,108,1325,0,274,555,1633,1633,555,555,1325,555,2040,274,1325,1383,
+ 555,1383,0,555,1317,988,1732,555,274,1636,1633,1602,1325,1383,0,0,
+ 1325,1929,2332,1514,1383,108,0,0,1383,0,0,988,1317,274,1325,1633,
+ 1325,517,1383,0,0,1633,108,274,1325,555,108,0,939,0,1636,274,
+ 0,1995,274,1929,1383,0,0,1317,1929,555,0,0,0,555,0,0,
+ 0,0,0,1514,1383,1633,1325,0,1633,0,1325,274,0,274,1317,0,
+ 1602,1317,0,2260,555,1633,1633,0,555,1325,0,1732,1325,988,1325,0,
+ 1383,1495,1636,555,901,274,1495,555,1208,1912,1602,1325,1633,0,1325,2403,
+ 108,1383,1317,108,0,0,517,0,673,0,0,0,1495,1325,1208,0,
+ 555,1317,1317,2332,1325,0,1514,555,555,555,1732,1602,0,0,274,0,
+ 517,939,0,2242,1633,0,1633,555,0,1732,555,517,2040,1633,1633,0,
+ 1602,0,1317,274,1383,0,1633,517,0,673,1995,1732,1912,1636,1602,1732,
+ 673,0,1732,108,1325,555,555,1633,1317,0,1732,555,555,555,939,0,
+ 517,1602,0,0,1929,555,901,0,108,108,1325,517,108,1325,1317,0,
+ 1325,0,1208,0,0,0,108,274,555,0,1383,1325,555,1325,1633,0,
+ 1383,1602,1383,0,0,517,274,0,591,0,1455,555,555,1317,1325,555,
+ 555,1317,0,108,555,0,0,108,1633,555,1602,0,1732,555,0,108,
+ 0,1636,1633,1633,517,555,555,0,274,1317,0,1912,1325,1208,1325,555,
+ 1383,1633,108,1317,0,1325,1495,1929,1633,673,1633,463,1317,0,0,517,
+ 0,1317,1929,0,455,1633,0,0,1602,1929,0,1929,2332,1317,555,238,
+ 0,274,517,1325,1317,0,274,0,555,1317,555,555,0,1192,1325,463,
+ 555,939,1633,0,0,0,1929,1325,1359,555,1317,1317,274,1732,555,0,
+ 555,1929,0,1325,448,0,1636,555,988,1208,108,274,555,1325,1317,555,
+ 1929,1929,1317,1325,108,902,555,0,555,988,1325,901,1325,1317,1732,1101,
+ 1208,1633,1732,108,1317,1317,108,555,1929,555,1995,1317,1929,1383,517,0,
+ 0,1633,1602,1912,1929,274,2464,0,555,1929,1317,0,0,555,1317,2180,
+ 1327,0,517,555,1633,1732,1636,1602,517,1208,555,555,1383,1317,1633,0,
+ 988,1192,0,0,1495,673,673,0,555,1495,1325,517,1732,1633,555,1325,
+ 108,1929,1732,1325,988,555,1325,1208,1929,274,0,673,555,1732,1633,134,
+ 108,1929,673,1208,555,1208,0,0,2464,0,1633,1929,0,913,673,0,
+ 108,1317,1383,1633,0,555,0,0,1995,1317,0,2040,1317,1633,2332,108,
+ 1633,1495,555,0,0,2040,926,673,1929,1325,1732,1929,1342,1633,1636,517,
+ 0,0,517,182,1359,108,274,2040,108,108,0,0,555,988,517,1633,
+ 1633,1325,1929,673,1633,1912,1288,555,1732,1325,0,1325,517,1325,1325,555,
+ 0,0,2055,108,0,1732,517,274,901,1359,1929,1417,1636,926,555,0,
+ 2040,0,1633,591,1929,1325,274,926,1325,517,0,765,108,0,2040,1383,
+ 1514,901,1809,666,1732,1732,555,1732,555,0,0,1912,555,555,555,1929,
+ 1317,0,517,673,555,274,673,2398,1208,555,1853,1633,1325,555,0,555,
+ 0,1383,1325,1317,1929,108,2037,1383,108,1728,673,555,1835,591,1732,1995,
+ 0,0,939,555,666,1325,1011,555,0,1929,108,1602,2332,0,1325,1633,
+ 1732,1602,555,429,2040,1633,0,555,2040,1633,0,0,1325,1929,0,1912,
+ 2040,1011,0,1732,517,1732,0,0,1633,1325,555,108,517,469,1636,108,
+ 1011,0,0,0,1912,926,1929,988,1636,1633,274,182,1317,108,1325,0,
+ 555,988,0,0,0,1771,1633,939,1732,1995,0,858,0,555,1633,0,
+ 939,0,555,108,555,1633,1995,555,2510,0,516,939,1208,1912,858,1205,
+ 0,785,0,988,1495,274,1011,902,0,0,184,0,1514,108,0,0,
+ 1732,1633,469,1005,455,555,0,0,1455,428,1929,0,926,1633,1317,555,
+ 939,0,1317,939,0,1327,1929,0,1668,1732,555,0,1929,1633,1929,555,
+ 0,0,0,555,1607,1011,1325,1495,400,1011,1924,1383,901,469,1929,1835,
+ 2040,1602,227,1342,1325,1192,0,1728,2040,1343,517,227,1929,1591,1912,429,
+ 988,1559,1929,1325,0,1732,1317,0,902,0,555,0,1912,988,1633,1547,
+ 200,1618,1636,926,0,1636,274,999,274,1809,1929,673,902,555,1624,591,
+ 1636,591,0,517,555,1383,1633,0,1809,1679,0,673,1011,555,0,108,
+ 1929,1495,1111,0,988,0,108,0,1995,2403,238,514,0,1995,1317,0,
+ 1343,517,913,673,988,1614,1912,1325,673,816,1212,1325,1732,1929,1835,1602,
+ 0,1636,108,455,1912,555,0,816,555,274,1633,0,1325,0,1929,1111,
+ 634,1636,555,1636,1559,0,1636,0,1514,2040,657,1034,1771,1853,258,1633,
+ 901,555,1208,1912,1959,816,440,0,1807,1924,1514,316,182,1732,1383,1618,
+ 988,1591,1559,274,274,0,858,0,1383,1929,1602,1633,1514,1005,1617,0,
+ 2060,517,1715,988,1542,1732,820,1633,1011,1383,1851,0,1650,1633,108,1912,
+ 1995,916,1636,1995,1208,0,0,1325,274,1645,108,0,0,0,0,440,
+ 1670,2060,676,1602,1942,1420,1317,939,729,274,0,0,1965,274,975,238,
+ };
+
+ const struct insnprefix_parse_data *ret;
+ unsigned long rsl, val = phash_lookup(key, len, 0xbc1b868fUL);
+ rsl = ((val>>23)^tab[val&0x3ff]);
+ if (rsl >= 2070) return NULL;
+ ret = &pd[rsl];
+ if (strcmp(key, ret->name) != 0) return NULL;
+ return ret;
+}
+
+
diff --git a/contrib/tools/yasm/modules/x86insn_nasm.c b/contrib/tools/yasm/modules/x86insn_nasm.c
new file mode 100644
index 0000000000..9d59b2e24b
--- /dev/null
+++ b/contrib/tools/yasm/modules/x86insn_nasm.c
@@ -0,0 +1,1506 @@
+/* ANSI-C code produced by genperf */
+struct insnprefix_parse_data;
+static const struct insnprefix_parse_data *
+insnprefix_nasm_find(const char *key, size_t len)
+{
+ static const struct insnprefix_parse_data pd[1454] = {
+ {"vpsubd", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xFA, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpltps", ssecmp_128_insn, 3, SUF_Z, 0x01, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmovhpd", movhlp_insn, 3, SUF_Z, 0x66, 0x16, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcomisd", avx_xmm_xmm64_insn, 2, SUF_Z, 0x66, 0x2F, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpltpd", ssecmp_128_insn, 3, SUF_Z, 0x01, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"pmvgezb", cyrixmmx_insn, 1, SUF_Z, 0x5C, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"cmovle", cmovcc_insn, 3, SUF_Z, 0x0E, 0, 0, 0, CPU_686, 0, 0},
+ {"cvttss2si", cvt_rx_xmm32_insn, 4, SUF_Z, 0xF3, 0x2C, 0, 0, CPU_386, CPU_SSE, 0},
+ {"xbegin", tsx_xbegin_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_TSX, 0},
+ {"vmovapd", movau_insn, 6, SUF_Z, 0x66, 0x28, 0x01, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovc", cmovcc_insn, 3, SUF_Z, 0x02, 0, 0, 0, CPU_686, 0, 0},
+ {"fninit", twobyte_insn, 1, SUF_Z, 0xDB, 0xE3, 0, 0, CPU_FPU, 0, 0},
+ {"vfrczss", vfrczss_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_XOP, 0, 0},
+ {"pushfd", onebyte_insn, 1, SUF_Z, 0x9C, 0x20, 0, NOT_64, CPU_386, 0, 0},
+ {"vpcomleuq", vpcom_insn, 1, SUF_Z, 0xEF, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"vpmulhuw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xE4, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpsubq", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xFB, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fstpt", fldstpt_insn, 1, SUF_Z, 0x07, 0, 0, 0, CPU_FPU, 0, 0},
+ {"adc", arith_insn, 22, SUF_Z, 0x10, 0x02, 0, 0, 0, 0, 0},
+ {"vmulss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x59, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"stosq", onebyte_insn, 1, SUF_Z, 0xAB, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"vzeroupper", vzero_insn, 1, SUF_Z, 0xC0, 0, 0, 0, CPU_AVX, 0, 0},
+ {"jnle", jcc_insn, 9, SUF_Z, 0x0F, 0, 0, 0, 0, 0, 0},
+ {"pmulhuw", mmxsse2_insn, 2, SUF_Z, 0xE4, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vcmpord_sss", ssecmp_32_insn, 4, SUF_Z, 0x17, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fxsave", twobytemem_insn, 1, SUF_Z, 0x00, 0x0F, 0xAE, 0, CPU_686, CPU_FPU, 0},
+ {"setnbe", setcc_insn, 1, SUF_Z, 0x07, 0, 0, 0, CPU_386, 0, 0},
+ {"insertps", insertps_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"rdtsc", twobyte_insn, 1, SUF_Z, 0x0F, 0x31, 0, 0, CPU_586, 0, 0},
+ {"psubd", mmxsse2_insn, 2, SUF_Z, 0xFA, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vcmptrue_uspd", ssecmp_128_insn, 3, SUF_Z, 0x1F, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmulps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x59, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpeq_usps", ssecmp_128_insn, 3, SUF_Z, 0x18, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cvtpd2ps", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x5A, 0, 0, CPU_SSE2, 0, 0},
+ {"vfnmsubsd", fma_128_m64_insn, 3, SUF_Z, 0x7F, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"vpcomtrueq", vpcom_insn, 1, SUF_Z, 0xCF, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"vpclmulqdq", pclmulqdq_insn, 2, SUF_Z, 0x3A, 0x44, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmova", cmovcc_insn, 3, SUF_Z, 0x07, 0, 0, 0, CPU_686, 0, 0},
+ {"vmaxss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5F, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pi2fw", now3d_insn, 1, SUF_Z, 0x0C, 0, 0, 0, CPU_3DNow, CPU_Athlon, 0},
+ {"vfnmadd132pd", vfma_pd_insn, 2, SUF_Z, 0x9C, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vdpps", sse4imm_256_insn, 4, SUF_Z, 0x40, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpclmulhqhqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x11, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmsub213pd", vfma_pd_insn, 2, SUF_Z, 0xAA, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"pmaxsw", mmxsse2_insn, 2, SUF_Z, 0xEE, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vpaddq", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xD4, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcmov", vpcmov_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpcomud", vpcom_imm_insn, 1, SUF_Z, 0xEE, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpslld", vpshift_insn, 8, SUF_Z, 0xF2, 0x72, 0x06, ONLY_AVX, CPU_AVX, 0, 0},
+ {"shufpd", xmm_xmm128_imm_insn, 1, SUF_Z, 0x66, 0xC6, 0, 0, CPU_SSE2, 0, 0},
+ {"vpcomgtud", vpcom_insn, 1, SUF_Z, 0xEE, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"cdq", onebyte_insn, 1, SUF_Z, 0x99, 0x20, 0, 0, CPU_386, 0, 0},
+ {"vcmpge_oqps", ssecmp_128_insn, 3, SUF_Z, 0x1D, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rcpss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x53, 0, 0, CPU_SSE, 0, 0},
+ {"aad", aadm_insn, 2, SUF_Z, 0x01, 0, 0, NOT_64, 0, 0, 0},
+ {"vinserti128", vinsertif128_insn, 1, SUF_Z, 0x38, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vphsubd", ssse3_insn, 5, SUF_Z, 0x06, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fdiv", farith_insn, 7, SUF_Z, 0xF8, 0xF0, 0x06, 0, CPU_FPU, 0, 0},
+ {"fst", fst_insn, 3, SUF_Z, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vpcomled", vpcom_insn, 1, SUF_Z, 0xCE, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"setne", setcc_insn, 1, SUF_Z, 0x05, 0, 0, 0, CPU_386, 0, 0},
+ {"xcryptcfb", padlock_insn, 1, SUF_Z, 0xE0, 0xF3, 0xA7, 0, CPU_PadLock, 0, 0},
+ {"pmaddubsw", ssse3_insn, 5, SUF_Z, 0x04, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"bt", bittest_insn, 6, SUF_Z, 0xA3, 0x04, 0, 0, CPU_386, 0, 0},
+ {"blendvpd", sse4xmm0_insn, 2, SUF_Z, 0x15, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vroundss", sse4m32imm_insn, 4, SUF_Z, 0x0A, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"iret", onebyte_insn, 1, SUF_Z, 0xCF, 0, 0, 0, 0, 0, 0},
+ {"movbe", movbe_insn, 6, SUF_Z, 0, 0, 0, 0, CPU_MOVBE, 0, 0},
+ {"lar", larlsl_insn, 6, SUF_Z, 0x02, 0, 0, 0, CPU_286, CPU_Prot, 0},
+ {"mulss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x59, 0, 0, CPU_SSE, 0, 0},
+ {"or", arith_insn, 22, SUF_Z, 0x08, 0x01, 0, 0, 0, 0, 0},
+ {"cmpxchg", cmpxchgxadd_insn, 4, SUF_Z, 0xB0, 0, 0, 0, CPU_486, 0, 0},
+ {"vcvttpd2dq", avx_cvt_xmm128_insn, 2, SUF_Z, 0x66, 0xE6, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lds", ldes_insn, 2, SUF_Z, 0xC5, 0, 0, NOT_64, 0, 0, 0},
+ {"vphaddubw", vphaddsub_insn, 1, SUF_Z, 0xD1, 0, 0, 0, CPU_XOP, 0, 0},
+ {"jg", jcc_insn, 9, SUF_Z, 0x0F, 0, 0, 0, 0, 0, 0},
+ {"movzx", movszx_insn, 5, SUF_Z, 0xB6, 0, 0, 0, CPU_386, 0, 0},
+ {"vpmacssdqh", vpma_insn, 1, SUF_Z, 0x8F, 0, 0, 0, CPU_XOP, 0, 0},
+ {"addsubps", xmm_xmm128_insn, 2, SUF_Z, 0xF2, 0xD0, 0, 0, CPU_SSE3, 0, 0},
+ {"fsin", twobyte_insn, 1, SUF_Z, 0xD9, 0xFE, 0, 0, CPU_286, CPU_FPU, 0},
+ {"vpminsb", ssse3_insn, 5, SUF_Z, 0x38, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"psignd", ssse3_insn, 5, SUF_Z, 0x0A, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"fucompp", twobyte_insn, 1, SUF_Z, 0xDA, 0xE9, 0, 0, CPU_286, CPU_FPU, 0},
+ {"vpunpcklqdq", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x6C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pcmpeqb", mmxsse2_insn, 2, SUF_Z, 0x74, 0, 0, 0, CPU_MMX, 0, 0},
+ {"extractps", extractps_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_SSE41, 0},
+ {"btc", bittest_insn, 6, SUF_Z, 0xBB, 0x07, 0, 0, CPU_386, 0, 0},
+ {"vpshlb", amd_vpshift_insn, 2, SUF_Z, 0x94, 0, 0, 0, CPU_XOP, 0, 0},
+ {"ror", shift_insn, 16, SUF_Z, 0x01, 0, 0, 0, 0, 0, 0},
+ {"vpsravd", vpshiftv_vexw0_avx2_insn, 2, SUF_Z, 0x46, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"setge", setcc_insn, 1, SUF_Z, 0x0D, 0, 0, 0, CPU_386, 0, 0},
+ {"vpcomgtub", vpcom_insn, 1, SUF_Z, 0xEC, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"vfmaddsub213ps", vfma_ps_insn, 2, SUF_Z, 0xA6, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpcomleub", vpcom_insn, 1, SUF_Z, 0xEC, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"cmpordps", ssecmp_128_insn, 3, SUF_Z, 0x07, 0, 0, 0, CPU_SSE, 0, 0},
+ {"movhpd", movhlp_insn, 3, SUF_Z, 0x66, 0x16, 0, 0, CPU_SSE2, 0, 0},
+ {"mwait", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xC9, 0, CPU_SSE3, 0, 0},
+ {"vmovmskps", movmsk_insn, 4, SUF_Z, 0x00, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpaddd", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xFE, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmsub132ss", vfma_ss_insn, 2, SUF_Z, 0x9B, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpminuw", ssse3_insn, 5, SUF_Z, 0x3A, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpshaq", amd_vpshift_insn, 2, SUF_Z, 0x9B, 0, 0, 0, CPU_XOP, 0, 0},
+ {"dec", incdec_insn, 6, SUF_Z, 0x48, 0x01, 0, 0, 0, 0, 0},
+ {"vmovss", movss_insn, 4, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmadd132ps", vfma_ps_insn, 2, SUF_Z, 0x98, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"int03", onebyte_insn, 1, SUF_Z, 0xCC, 0, 0, 0, 0, 0, 0},
+ {"blcfill", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x01, 0x01, 0, 0, CPU_386, CPU_TBM, 0},
+ {"phsubsw", ssse3_insn, 5, SUF_Z, 0x07, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"subpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x5C, 0, 0, CPU_SSE2, 0, 0},
+ {"stmxcsr", ldstmxcsr_insn, 1, SUF_Z, 0x03, 0, 0, 0, CPU_SSE, 0, 0},
+ {"cmovl", cmovcc_insn, 3, SUF_Z, 0x0C, 0, 0, 0, CPU_686, 0, 0},
+ {"vpcomneud", vpcom_insn, 1, SUF_Z, 0xEE, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"xorps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x57, 0, 0, CPU_SSE, 0, 0},
+ {"vcmpeq_usss", ssecmp_32_insn, 4, SUF_Z, 0x18, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpngt_uqsd", ssecmp_64_insn, 4, SUF_Z, 0x1A, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vsubps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x5C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vucomiss", avx_xmm_xmm32_insn, 2, SUF_Z, 0x00, 0x2E, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmp", arith_insn, 22, SUF_Z, 0x38, 0x07, 0, 0, 0, 0, 0},
+ {"bsr", bsfr_insn, 3, SUF_Z, 0xBD, 0, 0, 0, CPU_386, 0, 0},
+ {"cmc", onebyte_insn, 1, SUF_Z, 0xF5, 0, 0, 0, 0, 0, 0},
+ {"vpshad", amd_vpshift_insn, 2, SUF_Z, 0x9A, 0, 0, 0, CPU_XOP, 0, 0},
+ {"pmovmskb", pmovmskb_insn, 6, SUF_Z, 0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"setz", setcc_insn, 1, SUF_Z, 0x04, 0, 0, 0, CPU_386, 0, 0},
+ {"cmovo", cmovcc_insn, 3, SUF_Z, 0x00, 0, 0, 0, CPU_686, 0, 0},
+ {"vfmaddsd", fma_128_m64_insn, 3, SUF_Z, 0x6B, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"vcmpnltsd", ssecmp_64_insn, 4, SUF_Z, 0x05, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"xsha1", padlock_insn, 1, SUF_Z, 0xC8, 0xF3, 0xA6, 0, CPU_PadLock, 0, 0},
+ {"out", out_insn, 12, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"vdivsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5E, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfrczsd", vfrczsd_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpextrw", pextrw_insn, 7, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"subss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5C, 0, 0, CPU_SSE, 0, 0},
+ {"roundpd", sse4imm_insn, 2, SUF_Z, 0x09, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vpermilpd", vpermil_insn, 4, SUF_Z, 0x05, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmsub231ps", vfma_ps_insn, 2, SUF_Z, 0xBE, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"sysret", twobyte_insn, 1, SUF_Z, 0x0F, 0x07, 0, 0, CPU_686, CPU_AMD, CPU_Priv},
+ {"sub", arith_insn, 22, SUF_Z, 0x28, 0x05, 0, 0, 0, 0, 0},
+ {"popf", onebyte_insn, 1, SUF_Z, 0x9D, 0x00, 0x40, 0, 0, 0, 0},
+ {"pmvlzb", cyrixmmx_insn, 1, SUF_Z, 0x5B, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"vfmadd213ss", vfma_ss_insn, 2, SUF_Z, 0xA9, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"str", str_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_286, CPU_Prot, 0},
+ {"lahf", onebyte_insn, 1, SUF_Z, 0x9F, 0, 0, 0, 0, 0, 0},
+ {"fnstenv", onebytemem_insn, 1, SUF_Z, 0x06, 0xD9, 0, 0, CPU_FPU, 0, 0},
+ {"ficom", fiarith_insn, 2, SUF_Z, 0x02, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"vpmovsxbq", sse4m16_insn, 4, SUF_Z, 0x22, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pminub", mmxsse2_insn, 2, SUF_Z, 0xDA, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"sqrtpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x51, 0, 0, CPU_SSE2, 0, 0},
+ {"stac", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xCB, 0, CPU_SMAP, 0, 0},
+ {"vfmaddsub231ps", vfma_ps_insn, 2, SUF_Z, 0xB6, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpcomltq", vpcom_insn, 1, SUF_Z, 0xCF, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"cli", onebyte_insn, 1, SUF_Z, 0xFA, 0, 0, 0, 0, 0, 0},
+ {"vfnmadd132sd", vfma_sd_insn, 2, SUF_Z, 0x9D, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vrcpss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x53, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fnstsw", fnstsw_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vrsqrtps", avx_xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x52, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomb", vpcom_imm_insn, 1, SUF_Z, 0xCC, 0, 0, 0, CPU_XOP, 0, 0},
+ {"verr", prot286_insn, 1, SUF_Z, 0x04, 0x00, 0, 0, CPU_286, CPU_Prot, 0},
+ {"pmovzxdq", sse4m64_insn, 4, SUF_Z, 0x35, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vcmpneq_oqpd", ssecmp_128_insn, 3, SUF_Z, 0x0C, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setae", setcc_insn, 1, SUF_Z, 0x03, 0, 0, 0, CPU_386, 0, 0},
+ {"vhaddpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x7C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtsd2si", cvt_rx_xmm64_insn, 4, SUF_Z, 0xF2, 0x2D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmaxuw", sse4_insn, 2, SUF_Z, 0x3E, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"rorx", vex_gpr_reg_rm_0F_imm8_insn, 2, SUF_Z, 0xF2, 0x3A, 0xF0, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"andn", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_Z, 0x00, 0x38, 0xF2, ONLY_AVX, CPU_BMI1, 0, 0},
+ {"vpmovzxwq", sse4m32_insn, 4, SUF_Z, 0x34, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fisub", fiarith_insn, 2, SUF_Z, 0x04, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"vcmptrue_usps", ssecmp_128_insn, 3, SUF_Z, 0x1F, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomneq", vpcom_insn, 1, SUF_Z, 0xCF, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"getsec", twobyte_insn, 1, SUF_Z, 0x0F, 0x37, 0, 0, CPU_SMX, 0, 0},
+ {"bzhi", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_Z, 0x00, 0x38, 0xF5, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"cvtsd2si", cvt_rx_xmm64_insn, 4, SUF_Z, 0xF2, 0x2D, 0, 0, CPU_386, CPU_SSE2, 0},
+ {"vpcomned", vpcom_insn, 1, SUF_Z, 0xCE, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"xtest", tsx_0x0F_0x01_insn, 1, SUF_Z, 0xD6, 0, 0, 0, CPU_TSX, 0, 0},
+ {"pclmulqdq", pclmulqdq_insn, 2, SUF_Z, 0x3A, 0x44, 0, 0, CPU_AVX, 0, 0},
+ {"minsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5D, 0, 0, CPU_SSE2, 0, 0},
+ {"vldmxcsr", ldstmxcsr_insn, 1, SUF_Z, 0x02, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpneq_oqps", ssecmp_128_insn, 3, SUF_Z, 0x0C, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmovsxwd", sse4m64_insn, 4, SUF_Z, 0x23, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"iretd", onebyte_insn, 1, SUF_Z, 0xCF, 0x20, 0, 0, CPU_386, 0, 0},
+ {"vmcall", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xC1, 0, CPU_P4, 0, 0},
+ {"shl", shift_insn, 16, SUF_Z, 0x04, 0, 0, 0, 0, 0, 0},
+ {"cmovnp", cmovcc_insn, 3, SUF_Z, 0x0B, 0, 0, 0, CPU_686, 0, 0},
+ {"cmpltss", ssecmp_32_insn, 4, SUF_Z, 0x01, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"movddup", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x12, 0, 0, CPU_SSE3, 0, 0},
+ {"xrstor", twobytemem_insn, 1, SUF_Z, 0x05, 0x0F, 0xAE, 0, CPU_386, CPU_XSAVE, 0},
+ {"pinsrb", pinsrb_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"pushf", onebyte_insn, 1, SUF_Z, 0x9C, 0x00, 0x40, 0, 0, 0, 0},
+ {"vxorpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x57, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpunordss", ssecmp_32_insn, 4, SUF_Z, 0x03, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpmaxud", ssse3_insn, 5, SUF_Z, 0x3F, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fiadd", fiarith_insn, 2, SUF_Z, 0x00, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"vcmple_oqpd", ssecmp_128_insn, 3, SUF_Z, 0x12, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpss", xmm_xmm32_imm_insn, 4, SUF_Z, 0xF3, 0xC2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sysenter", twobyte_insn, 1, SUF_Z, 0x0F, 0x34, 0, NOT_64, CPU_686, 0, 0},
+ {"vpcomleq", vpcom_insn, 1, SUF_Z, 0xCF, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"finit", threebyte_insn, 1, SUF_Z, 0x9B, 0xDB, 0xE3, 0, CPU_FPU, 0, 0},
+ {"vpcomneqw", vpcom_insn, 1, SUF_Z, 0xCD, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"clgi", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xDD, 0, CPU_SVM, 0, 0},
+ {"vpabsb", avx2_ssse3_2op_insn, 2, SUF_Z, 0x1C, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"addpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x58, 0, 0, CPU_SSE2, 0, 0},
+ {"cmovg", cmovcc_insn, 3, SUF_Z, 0x0F, 0, 0, 0, CPU_686, 0, 0},
+ {"movlps", movhlp_insn, 3, SUF_Z, 0x00, 0x12, 0, 0, CPU_SSE, 0, 0},
+ {"vaddss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x58, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"outsb", onebyte_insn, 1, SUF_Z, 0x6E, 0x00, 0, 0, 0, 0, 0},
+ {"vpcomequd", vpcom_insn, 1, SUF_Z, 0xEE, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"wrmsr", twobyte_insn, 1, SUF_Z, 0x0F, 0x30, 0, 0, CPU_586, CPU_Priv, 0},
+ {"vpshufb", ssse3_insn, 5, SUF_Z, 0x00, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpackssdw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x6B, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"ftst", twobyte_insn, 1, SUF_Z, 0xD9, 0xE4, 0, 0, CPU_FPU, 0, 0},
+ {"arpl", arpl_insn, 1, SUF_Z, 0, 0, 0, NOT_64, CPU_286, CPU_Prot, 0},
+ {"fcmovb", fcmovcc_insn, 1, SUF_Z, 0xDA, 0xC0, 0, 0, CPU_686, CPU_FPU, 0},
+ {"vfnmadd132ss", vfma_ss_insn, 2, SUF_Z, 0x9D, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"rsldt", cyrixsmm_insn, 1, SUF_Z, 0x7B, 0, 0, 0, CPU_486, CPU_Cyrix, CPU_SMM},
+ {"vfmsubss", fma_128_m32_insn, 3, SUF_Z, 0x6E, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"pcmpgtw", mmxsse2_insn, 2, SUF_Z, 0x65, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vcmpfalse_osss", ssecmp_32_insn, 4, SUF_Z, 0x1B, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"comiss", xmm_xmm32_insn, 4, SUF_Z, 0x00, 0x2F, 0, 0, CPU_SSE, 0, 0},
+ {"loopz", loop_insn, 8, SUF_Z, 0x01, 0, 0, 0, 0, 0, 0},
+ {"cmpnlepd", ssecmp_128_insn, 3, SUF_Z, 0x06, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"pfmin", now3d_insn, 1, SUF_Z, 0x94, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"xsha256", padlock_insn, 1, SUF_Z, 0xD0, 0xF3, 0xA6, 0, CPU_PadLock, 0, 0},
+ {"vfnmsub132ss", vfma_ss_insn, 2, SUF_Z, 0x9F, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"fldl2t", twobyte_insn, 1, SUF_Z, 0xD9, 0xE9, 0, 0, CPU_FPU, 0, 0},
+ {"vpsignd", ssse3_insn, 5, SUF_Z, 0x0A, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpaddusw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xDD, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fcmovu", fcmovcc_insn, 1, SUF_Z, 0xDA, 0xD8, 0, 0, CPU_686, CPU_FPU, 0},
+ {"vmovaps", movau_insn, 6, SUF_Z, 0x00, 0x28, 0x01, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmple_oqsd", ssecmp_64_insn, 4, SUF_Z, 0x12, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpextrq", pextrq_insn, 1, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpnltps", ssecmp_128_insn, 3, SUF_Z, 0x05, 0, 0, 0, CPU_SSE, 0, 0},
+ {"vfnmadd231pd", vfma_pd_insn, 2, SUF_Z, 0xBC, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"fsubp", farithp_insn, 3, SUF_Z, 0xE8, 0, 0, 0, CPU_FPU, 0, 0},
+ {"pmulld", sse4_insn, 2, SUF_Z, 0x40, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vfnmadd132ps", vfma_ps_insn, 2, SUF_Z, 0x9C, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpunpcklbw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x60, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vorps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x56, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmovmskpd", movmsk_insn, 4, SUF_Z, 0x66, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpeqpd", ssecmp_128_insn, 3, SUF_Z, 0x00, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"vmovdqa", movau_insn, 6, SUF_Z, 0x66, 0x6F, 0x10, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jl", jcc_insn, 9, SUF_Z, 0x0C, 0, 0, 0, 0, 0, 0},
+ {"vcmpgesd", ssecmp_64_insn, 4, SUF_Z, 0x0D, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cvttpd2pi", cvt_mm_xmm_insn, 1, SUF_Z, 0x66, 0x2C, 0, 0, CPU_SSE2, 0, 0},
+ {"phsubw", ssse3_insn, 5, SUF_Z, 0x05, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"pminsw", mmxsse2_insn, 2, SUF_Z, 0xEA, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vpgatherqq", gather_64x_64y_insn, 2, SUF_Z, 0x91, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vfmadd132sd", vfma_sd_insn, 2, SUF_Z, 0x99, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"setpo", setcc_insn, 1, SUF_Z, 0x0B, 0, 0, 0, CPU_386, 0, 0},
+ {"fidiv", fiarith_insn, 2, SUF_Z, 0x06, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"clts", twobyte_insn, 1, SUF_Z, 0x0F, 0x06, 0, 0, CPU_286, CPU_Priv, 0},
+ {"prefetcht0", twobytemem_insn, 1, SUF_Z, 0x01, 0x0F, 0x18, 0, CPU_P3, 0, 0},
+ {"cvtsi2ss", cvt_xmm_rmx_insn, 6, SUF_Z, 0xF3, 0x2A, 0, 0, CPU_386, CPU_SSE, 0},
+ {"vpmuludq", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xF4, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"xcryptctr", padlock_insn, 1, SUF_Z, 0xD8, 0xF3, 0xA7, 0, CPU_PadLock, 0, 0},
+ {"vfmadd132ss", vfma_ss_insn, 2, SUF_Z, 0x99, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpcmpistri", sse4pcmpstr_insn, 1, SUF_Z, 0x63, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"popfw", onebyte_insn, 1, SUF_Z, 0x9D, 0x10, 0x40, 0, 0, 0, 0},
+ {"vstmxcsr", ldstmxcsr_insn, 1, SUF_Z, 0x03, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpmovzxbd", sse4m32_insn, 4, SUF_Z, 0x31, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rsqrtps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x52, 0, 0, CPU_SSE, 0, 0},
+ {"vfmsubadd213pd", vfma_pd_insn, 2, SUF_Z, 0xA7, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"prefetcht1", twobytemem_insn, 1, SUF_Z, 0x02, 0x0F, 0x18, 0, CPU_P3, 0, 0},
+ {"xrelease", NULL, X86_ACQREL>>8, 0xF3, 0, 0, 0, 0, 0, 0, 0},
+ {"wait", onebyte_insn, 1, SUF_Z, 0x9B, 0, 0, 0, 0, 0, 0},
+ {"aesenc", aes_insn, 2, SUF_Z, 0x38, 0xDC, 0, 0, CPU_AVX, 0, 0},
+ {"cmpordsd", ssecmp_64_insn, 4, SUF_Z, 0x07, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"lodsb", onebyte_insn, 1, SUF_Z, 0xAC, 0x00, 0, 0, 0, 0, 0},
+ {"vcmpeq_ussd", ssecmp_64_insn, 4, SUF_Z, 0x18, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fimul", fiarith_insn, 2, SUF_Z, 0x01, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"setns", setcc_insn, 1, SUF_Z, 0x09, 0, 0, 0, CPU_386, 0, 0},
+ {"vunpcklpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x14, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sha1nexte", intel_SHA1NEXTE_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SHA, 0, 0},
+ {"xorpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x57, 0, 0, CPU_SSE2, 0, 0},
+ {"jp", jcc_insn, 9, SUF_Z, 0x0A, 0, 0, 0, 0, 0, 0},
+ {"vcmpfalse_ossd", ssecmp_64_insn, 4, SUF_Z, 0x1B, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vaesenc", aes_insn, 2, SUF_Z, 0x38, 0xDC, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fnop", twobyte_insn, 1, SUF_Z, 0xD9, 0xD0, 0, 0, CPU_FPU, 0, 0},
+ {"nop", onebyte_insn, 1, SUF_Z, 0x90, 0, 0, 0, 0, 0, 0},
+ {"test", test_insn, 20, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"pmulhrsw", ssse3_insn, 5, SUF_Z, 0x0B, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"cvtdq2pd", xmm_xmm64_insn, 4, SUF_Z, 0xF3, 0xE6, 0, 0, CPU_SSE2, 0, 0},
+ {"pmaddwd", mmxsse2_insn, 2, SUF_Z, 0xF5, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vperm2i128", vperm2i128_avx2_insn, 1, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vcmpnltss", ssecmp_32_insn, 4, SUF_Z, 0x05, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"frstor", onebytemem_insn, 1, SUF_Z, 0x04, 0xDD, 0, 0, CPU_FPU, 0, 0},
+ {"vcmpnlt_uqps", ssecmp_128_insn, 3, SUF_Z, 0x15, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"blcic", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x01, 0x05, 0, 0, CPU_386, CPU_TBM, 0},
+ {"vfnmsub132sd", vfma_sd_insn, 2, SUF_Z, 0x9F, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"loopnz", loop_insn, 8, SUF_Z, 0x00, 0, 0, 0, 0, 0, 0},
+ {"vcmpordss", ssecmp_32_insn, 4, SUF_Z, 0x07, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movntsd", movntsd_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SSE4a, 0, 0},
+ {"mov", mov_insn, 69, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"jc", jcc_insn, 9, SUF_Z, 0x02, 0, 0, 0, 0, 0, 0},
+ {"cmpltps", ssecmp_128_insn, 3, SUF_Z, 0x01, 0, 0, 0, CPU_SSE, 0, 0},
+ {"palignr", ssse3imm_insn, 2, SUF_Z, 0x0F, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"vpmuldq", ssse3_insn, 5, SUF_Z, 0x28, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovnz", cmovcc_insn, 3, SUF_Z, 0x05, 0, 0, 0, CPU_686, 0, 0},
+ {"vpshuflw", xmm_xmm128_imm_256avx2_insn, 2, SUF_Z, 0xF2, 0x70, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpmovzxdq", sse4m64_insn, 4, SUF_Z, 0x35, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpnge_uqps", ssecmp_128_insn, 3, SUF_Z, 0x19, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fstp", fstp_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vpacksswb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x63, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmaddps", fma_128_256_insn, 4, SUF_Z, 0x68, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"vcmptruepd", ssecmp_128_insn, 3, SUF_Z, 0x0F, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vaddsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x58, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vphaddbq", vphaddsub_insn, 1, SUF_Z, 0xC3, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vaesimc", aesimc_insn, 1, SUF_Z, 0x38, 0xDB, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"wbinvd", twobyte_insn, 1, SUF_Z, 0x0F, 0x09, 0, 0, CPU_486, CPU_Priv, 0},
+ {"salc", onebyte_insn, 1, SUF_Z, 0xD6, 0, 0, NOT_64, CPU_Undoc, 0, 0},
+ {"vcmpnltps", ssecmp_128_insn, 3, SUF_Z, 0x05, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"ptest", sse4_insn, 2, SUF_Z, 0x17, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"jne", jcc_insn, 9, SUF_Z, 0x05, 0, 0, 0, 0, 0, 0},
+ {"vpmovsxbd", sse4m32_insn, 4, SUF_Z, 0x21, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vminsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fcmovnb", fcmovcc_insn, 1, SUF_Z, 0xDB, 0xC0, 0, 0, CPU_686, CPU_FPU, 0},
+ {"vpunpcklwd", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x61, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pclmullqhqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x10, 0, 0, 0, CPU_AVX, 0, 0},
+ {"loadall286", twobyte_insn, 1, SUF_Z, 0x0F, 0x05, 0, 0, CPU_286, CPU_Undoc, 0},
+ {"popcnt", cnt_insn, 3, SUF_Z, 0xB8, 0, 0, 0, CPU_SSE42, 0, 0},
+ {"fld", fld_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vpcomfalseuw", vpcom_insn, 1, SUF_Z, 0xED, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"fprem", twobyte_insn, 1, SUF_Z, 0xD9, 0xF8, 0, 0, CPU_FPU, 0, 0},
+ {"vcvtps2pd", avx_cvt_xmm64_insn, 3, SUF_Z, 0x00, 0x5A, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmsub231ss", vfma_ss_insn, 2, SUF_Z, 0xBB, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vfmadd213sd", vfma_sd_insn, 2, SUF_Z, 0xA9, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vprotw", vprot_insn, 3, SUF_Z, 0x01, 0, 0, 0, CPU_XOP, 0, 0},
+ {"cmovge", cmovcc_insn, 3, SUF_Z, 0x0D, 0, 0, 0, CPU_686, 0, 0},
+ {"popa", onebyte_insn, 1, SUF_Z, 0x61, 0x00, 0, NOT_64, CPU_186, 0, 0},
+ {"cmovna", cmovcc_insn, 3, SUF_Z, 0x06, 0, 0, 0, CPU_686, 0, 0},
+ {"vroundpd", avx_sse4imm_insn, 3, SUF_Z, 0x09, 0, 0, ONLY_AVX, CPU_SSE41, 0, 0},
+ {"pcmpistrm", sse4pcmpstr_insn, 1, SUF_Z, 0x62, 0, 0, 0, CPU_SSE42, 0, 0},
+ {"movq2dq", movq2dq_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"blsi", vex_gpr_ndd_rm_0F38_regext_insn, 2, SUF_Z, 0x00, 0xF3, 0x03, ONLY_AVX, CPU_BMI1, 0, 0},
+ {"vminps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x5D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"maxsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5F, 0, 0, CPU_SSE2, 0, 0},
+ {"vcmpneq_ossd", ssecmp_64_insn, 4, SUF_Z, 0x1C, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"in", in_insn, 12, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"retn", retnf_insn, 6, SUF_Z, 0xC2, 0, 0, 0, 0, 0, 0},
+ {"cmpsd", cmpsd_insn, 5, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"psrlw", pshift_insn, 4, SUF_Z, 0xD1, 0x71, 0x02, 0, CPU_MMX, 0, 0},
+ {"vpsrlvd", vpshiftv_vexw0_avx2_insn, 2, SUF_Z, 0x45, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"movsd", movsd_insn, 5, SUF_Z, 0, 0, 0, 0, CPU_386, 0, 0},
+ {"subsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5C, 0, 0, CPU_SSE2, 0, 0},
+ {"das", onebyte_insn, 1, SUF_Z, 0x2F, 0, 0, NOT_64, 0, 0, 0},
+ {"movaps", movau_insn, 6, SUF_Z, 0x00, 0x28, 0x01, 0, CPU_SSE, 0, 0},
+ {"fxtract", twobyte_insn, 1, SUF_Z, 0xD9, 0xF4, 0, 0, CPU_FPU, 0, 0},
+ {"rep", NULL, X86_LOCKREP>>8, 0xF3, 0, 0, 0, 0, 0, 0, 0},
+ {"vcmpnless", ssecmp_32_insn, 4, SUF_Z, 0x06, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vaeskeygenassist", aes_imm_insn, 1, SUF_Z, 0x3A, 0xDF, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpaddsb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xEC, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pand", mmxsse2_insn, 2, SUF_Z, 0xDB, 0, 0, 0, CPU_MMX, 0, 0},
+ {"cmovb", cmovcc_insn, 3, SUF_Z, 0x02, 0, 0, 0, CPU_686, 0, 0},
+ {"vpcmpgtd", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmovzxwq", sse4m32_insn, 4, SUF_Z, 0x34, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vfmsubadd132ps", vfma_ps_insn, 2, SUF_Z, 0x97, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpmovsxdq", sse4m64_insn, 4, SUF_Z, 0x25, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"psrlq", pshift_insn, 4, SUF_Z, 0xD3, 0x73, 0x02, 0, CPU_MMX, 0, 0},
+ {"vshufps", xmm_xmm128_imm_256_insn, 3, SUF_Z, 0x00, 0xC6, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"ficomp", fiarith_insn, 2, SUF_Z, 0x03, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"vpcomneqq", vpcom_insn, 1, SUF_Z, 0xCF, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"vphaddwd", vphaddsub_insn, 1, SUF_Z, 0xC6, 0, 0, 0, CPU_XOP, 0, 0},
+ {"scasq", onebyte_insn, 1, SUF_Z, 0xAF, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"vcmpgess", ssecmp_32_insn, 4, SUF_Z, 0x0D, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmptrueps", ssecmp_128_insn, 3, SUF_Z, 0x0F, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"divss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5E, 0, 0, CPU_SSE, 0, 0},
+ {"vblendvpd", avx_sse4xmm0_insn, 2, SUF_Z, 0x4B, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpnle_uqss", ssecmp_32_insn, 4, SUF_Z, 0x16, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"punpcklqdq", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x6C, 0, 0, CPU_SSE2, 0, 0},
+ {"vphsubbw", vphaddsub_insn, 1, SUF_Z, 0xE1, 0, 0, 0, CPU_XOP, 0, 0},
+ {"hsubpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x7D, 0, 0, CPU_SSE3, 0, 0},
+ {"vfnmsub132ps", vfma_ps_insn, 2, SUF_Z, 0x9E, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"fxch", fxch_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vpsrad", vpshift_insn, 8, SUF_Z, 0xE2, 0x72, 0x04, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sets", setcc_insn, 1, SUF_Z, 0x08, 0, 0, 0, CPU_386, 0, 0},
+ {"montmul", padlock_insn, 1, SUF_Z, 0xC0, 0xF3, 0xA6, 0, CPU_PadLock, 0, 0},
+ {"shld", shlrd_insn, 9, SUF_Z, 0xA4, 0, 0, 0, CPU_386, 0, 0},
+ {"jnbe", jcc_insn, 9, SUF_Z, 0x07, 0, 0, 0, 0, 0, 0},
+ {"fucomip", fcom2_insn, 2, SUF_Z, 0xDF, 0xE8, 0, 0, CPU_686, CPU_FPU, 0},
+ {"vfnmsubpd", fma_128_256_insn, 4, SUF_Z, 0x7D, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"psllw", pshift_insn, 4, SUF_Z, 0xF1, 0x71, 0x06, 0, CPU_MMX, 0, 0},
+ {"vpsubw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xF9, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fcomi", fcom2_insn, 2, SUF_Z, 0xDB, 0xF0, 0, 0, CPU_686, CPU_FPU, 0},
+ {"pusha", onebyte_insn, 1, SUF_Z, 0x60, 0x00, 0, NOT_64, CPU_186, 0, 0},
+ {"vcmpnltpd", ssecmp_128_insn, 3, SUF_Z, 0x05, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"adox", vex_gpr_ndd_rm_0F38_insn, 2, SUF_Z, 0xF3, 0xF6, 0, 0, CPU_ADX, 0, 0},
+ {"cmpordpd", ssecmp_128_insn, 3, SUF_Z, 0x07, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"lfence", threebyte_insn, 1, SUF_Z, 0x0F, 0xAE, 0xE8, 0, CPU_P3, 0, 0},
+ {"loopne", loop_insn, 8, SUF_Z, 0x00, 0, 0, 0, 0, 0, 0},
+ {"vfmadd213pd", vfma_pd_insn, 2, SUF_Z, 0xA8, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"movsq", onebyte_insn, 1, SUF_Z, 0xA5, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"vcmpunord_ssd", ssecmp_64_insn, 4, SUF_Z, 0x13, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pslldq", pslrldq_insn, 4, SUF_Z, 0x07, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"fisttp", fildstp_insn, 4, SUF_Z, 0x01, 0x00, 0x01, 0, CPU_SSE3, 0, 0},
+ {"fldcw", fldnstcw_insn, 1, SUF_Z, 0x05, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vpcomltw", vpcom_insn, 1, SUF_Z, 0xCD, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"vpackusdw", ssse3_insn, 5, SUF_Z, 0x2B, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovng", cmovcc_insn, 3, SUF_Z, 0x0E, 0, 0, 0, CPU_686, 0, 0},
+ {"andnps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x55, 0, 0, CPU_SSE, 0, 0},
+ {"cwde", onebyte_insn, 1, SUF_Z, 0x98, 0x20, 0, 0, CPU_386, 0, 0},
+ {"vpcomtruew", vpcom_insn, 1, SUF_Z, 0xCD, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"xsetbv", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xD1, 0, CPU_386, CPU_Priv, CPU_XSAVE},
+ {"movsw", onebyte_insn, 1, SUF_Z, 0xA5, 0x10, 0, 0, 0, 0, 0},
+ {"vpcomw", vpcom_imm_insn, 1, SUF_Z, 0xCD, 0, 0, 0, CPU_XOP, 0, 0},
+ {"pext", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_Z, 0xF3, 0x38, 0xF5, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"pmovsxbd", sse4m32_insn, 4, SUF_Z, 0x21, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"cmpnleps", ssecmp_128_insn, 3, SUF_Z, 0x06, 0, 0, 0, CPU_SSE, 0, 0},
+ {"vfmsubsd", fma_128_m64_insn, 3, SUF_Z, 0x6F, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"fcos", twobyte_insn, 1, SUF_Z, 0xD9, 0xFF, 0, 0, CPU_286, CPU_FPU, 0},
+ {"repnz", NULL, X86_LOCKREP>>8, 0xF2, 0, 0, 0, 0, 0, 0, 0},
+ {"vcmpngtsd", ssecmp_64_insn, 4, SUF_Z, 0x0A, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fsubr", farith_insn, 7, SUF_Z, 0xE0, 0xE8, 0x05, 0, CPU_FPU, 0, 0},
+ {"setng", setcc_insn, 1, SUF_Z, 0x0E, 0, 0, 0, CPU_386, 0, 0},
+ {"paddsiw", cyrixmmx_insn, 1, SUF_Z, 0x51, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"psubusb", mmxsse2_insn, 2, SUF_Z, 0xD8, 0, 0, 0, CPU_MMX, 0, 0},
+ {"psignw", ssse3_insn, 5, SUF_Z, 0x09, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"cmovnae", cmovcc_insn, 3, SUF_Z, 0x02, 0, 0, 0, CPU_686, 0, 0},
+ {"vpcomgeb", vpcom_insn, 1, SUF_Z, 0xCC, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"vmovshdup", avx_xmm_xmm128_insn, 2, SUF_Z, 0xF3, 0x16, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pshufhw", xmm_xmm128_imm_insn, 1, SUF_Z, 0xF3, 0x70, 0, 0, CPU_SSE2, 0, 0},
+ {"fldt", fldstpt_insn, 1, SUF_Z, 0x05, 0, 0, 0, CPU_FPU, 0, 0},
+ {"pmovsxbq", sse4m16_insn, 4, SUF_Z, 0x22, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"extrq", extrq_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_SSE4a, 0, 0},
+ {"fidivr", fiarith_insn, 2, SUF_Z, 0x07, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"vpabsd", avx2_ssse3_2op_insn, 2, SUF_Z, 0x1E, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmaskmovpd", vmaskmov_insn, 4, SUF_Z, 0x2D, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rsts", cyrixsmm_insn, 1, SUF_Z, 0x7D, 0, 0, 0, CPU_486, CPU_Cyrix, CPU_SMM},
+ {"vfmsubaddpd", fma_128_256_insn, 4, SUF_Z, 0x5F, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"paddsw", mmxsse2_insn, 2, SUF_Z, 0xED, 0, 0, 0, CPU_MMX, 0, 0},
+ {"cmpnless", ssecmp_32_insn, 4, SUF_Z, 0x06, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"vinsertps", insertps_insn, 4, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fcmovne", fcmovcc_insn, 1, SUF_Z, 0xDB, 0xC8, 0, 0, CPU_686, CPU_FPU, 0},
+ {"vcmpneq_osps", ssecmp_128_insn, 3, SUF_Z, 0x1C, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vextractf128", vextractif128_insn, 1, SUF_Z, 0x19, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmulhw", mmxsse2_insn, 2, SUF_Z, 0xE5, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vfnmsub213ps", vfma_ps_insn, 2, SUF_Z, 0xAE, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"sha256rnds2", intel_SHA256RNDS2_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SHA, 0, 0},
+ {"vcmpnle_uqsd", ssecmp_64_insn, 4, SUF_Z, 0x16, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovns", cmovcc_insn, 3, SUF_Z, 0x09, 0, 0, 0, CPU_686, 0, 0},
+ {"xcryptecb", padlock_insn, 1, SUF_Z, 0xC8, 0xF3, 0xA7, 0, CPU_PadLock, 0, 0},
+ {"vcvtpd2dq", avx_cvt_xmm128_insn, 2, SUF_Z, 0xF2, 0xE6, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pfadd", now3d_insn, 1, SUF_Z, 0x9E, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"fbld", fbldstp_insn, 1, SUF_Z, 0x04, 0, 0, 0, CPU_FPU, 0, 0},
+ {"rsm", twobyte_insn, 1, SUF_Z, 0x0F, 0xAA, 0, 0, CPU_586, CPU_SMM, 0},
+ {"vxorps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x57, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmuldq", sse4_insn, 2, SUF_Z, 0x28, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vshufpd", xmm_xmm128_imm_256_insn, 3, SUF_Z, 0x66, 0xC6, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpgtps", ssecmp_128_insn, 3, SUF_Z, 0x0E, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pop", pop_insn, 23, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"movhps", movhlp_insn, 3, SUF_Z, 0x00, 0x16, 0, 0, CPU_SSE, 0, 0},
+ {"sqrtss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x51, 0, 0, CPU_SSE, 0, 0},
+ {"vcmpord_spd", ssecmp_128_insn, 3, SUF_Z, 0x17, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cvtpi2pd", cvt_xmm_mm_ss_insn, 1, SUF_Z, 0x66, 0x2A, 0, 0, CPU_SSE2, 0, 0},
+ {"vpunpckhwd", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x69, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmsub213ps", vfma_ps_insn, 2, SUF_Z, 0xAA, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vmovntdq", movnt_insn, 2, SUF_Z, 0x66, 0xE7, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmove", cmovcc_insn, 3, SUF_Z, 0x04, 0, 0, 0, CPU_686, 0, 0},
+ {"setl", setcc_insn, 1, SUF_Z, 0x0C, 0, 0, 0, CPU_386, 0, 0},
+ {"vpcomnequw", vpcom_insn, 1, SUF_Z, 0xED, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpeqps", ssecmp_128_insn, 3, SUF_Z, 0x00, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmrun", svm_rax_insn, 2, SUF_Z, 0xD8, 0, 0, 0, CPU_SVM, 0, 0},
+ {"pswapd", now3d_insn, 1, SUF_Z, 0xBB, 0, 0, 0, CPU_3DNow, CPU_Athlon, 0},
+ {"vcmpltpd", ssecmp_128_insn, 3, SUF_Z, 0x01, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmovsxdq", sse4m64_insn, 4, SUF_Z, 0x25, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"skinit", skinit_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_SVM, 0, 0},
+ {"setno", setcc_insn, 1, SUF_Z, 0x01, 0, 0, 0, CPU_386, 0, 0},
+ {"pmaxub", mmxsse2_insn, 2, SUF_Z, 0xDE, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"ldmxcsr", ldstmxcsr_insn, 1, SUF_Z, 0x02, 0, 0, 0, CPU_SSE, 0, 0},
+ {"setnc", setcc_insn, 1, SUF_Z, 0x03, 0, 0, 0, CPU_386, 0, 0},
+ {"xsaveopt", twobytemem_insn, 1, SUF_Z, 0x06, 0x0F, 0xAE, 0, CPU_XSAVEOPT, 0, 0},
+ {"vcmpnlesd", ssecmp_64_insn, 4, SUF_Z, 0x06, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpslldq", pslrldq_insn, 4, SUF_Z, 0x07, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vphsubdq", vphaddsub_insn, 1, SUF_Z, 0xE3, 0, 0, 0, CPU_XOP, 0, 0},
+ {"cdqe", onebyte_insn, 1, SUF_Z, 0x98, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"cvtps2dq", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x5B, 0, 0, CPU_SSE2, 0, 0},
+ {"vpsubusw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xD9, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"btr", bittest_insn, 6, SUF_Z, 0xB3, 0x06, 0, 0, CPU_386, 0, 0},
+ {"fnclex", twobyte_insn, 1, SUF_Z, 0xDB, 0xE2, 0, 0, CPU_FPU, 0, 0},
+ {"invlpg", twobytemem_insn, 1, SUF_Z, 0x07, 0x0F, 0x01, 0, CPU_486, CPU_Priv, 0},
+ {"vfmaddsubpd", fma_128_256_insn, 4, SUF_Z, 0x5D, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"vpbroadcastw", vpbroadcastw_avx2_insn, 4, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"xstorerng", padlock_insn, 1, SUF_Z, 0xC0, 0x00, 0xA7, 0, CPU_PadLock, 0, 0},
+ {"neg", f6_insn, 4, SUF_Z, 0x03, 0, 0, 0, 0, 0, 0},
+ {"vpshufhw", xmm_xmm128_imm_256avx2_insn, 2, SUF_Z, 0xF3, 0x70, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"a64", NULL, X86_ADDRSIZE>>8, 0x40, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"insertq", insertq_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_SSE4a, 0, 0},
+ {"vcmpnle_uqps", ssecmp_128_insn, 3, SUF_Z, 0x16, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"int", int_insn, 1, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"vpshufd", xmm_xmm128_imm_256avx2_insn, 2, SUF_Z, 0x66, 0x70, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vsqrtss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x51, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcmpistrm", sse4pcmpstr_insn, 1, SUF_Z, 0x62, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmptruess", ssecmp_32_insn, 4, SUF_Z, 0x0F, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpunordsd", ssecmp_64_insn, 4, SUF_Z, 0x03, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"maxpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x5F, 0, 0, CPU_SSE2, 0, 0},
+ {"vcmpneqss", ssecmp_32_insn, 4, SUF_Z, 0x04, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fucomi", fcom2_insn, 2, SUF_Z, 0xDB, 0xE8, 0, 0, CPU_686, CPU_FPU, 0},
+ {"packusdw", sse4_insn, 2, SUF_Z, 0x2B, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"lodsw", onebyte_insn, 1, SUF_Z, 0xAD, 0x10, 0, 0, 0, 0, 0},
+ {"vpalignr", sse4imm_256avx2_insn, 4, SUF_Z, 0x0F, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpmovmskb", pmovmskb_insn, 6, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vinsertf128", vinsertif128_insn, 1, SUF_Z, 0x18, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"paddw", mmxsse2_insn, 2, SUF_Z, 0xFD, 0, 0, 0, CPU_MMX, 0, 0},
+ {"pmvnzb", cyrixmmx_insn, 1, SUF_Z, 0x5A, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"pabsb", ssse3_insn, 5, SUF_Z, 0x1C, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"vfnmsub231ss", vfma_ss_insn, 2, SUF_Z, 0xBF, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"pandn", mmxsse2_insn, 2, SUF_Z, 0xDF, 0, 0, 0, CPU_MMX, 0, 0},
+ {"setnl", setcc_insn, 1, SUF_Z, 0x0D, 0, 0, 0, CPU_386, 0, 0},
+ {"vmovupd", movau_insn, 6, SUF_Z, 0x66, 0x10, 0x01, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtph2ps", avx_cvtph2ps_insn, 4, SUF_Z, 0x66, 0x13, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vaddsubps", xmm_xmm128_256_insn, 4, SUF_Z, 0xF2, 0xD0, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sarx", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_Z, 0xF3, 0x38, 0xF7, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"vpcomtrued", vpcom_insn, 1, SUF_Z, 0xCE, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"vpsllq", vpshift_insn, 8, SUF_Z, 0xF3, 0x73, 0x06, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcmpgtq", ssse3_insn, 5, SUF_Z, 0x37, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpxchg8b", cmpxchg8b_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_586, 0, 0},
+ {"vfmaddsub132ps", vfma_ps_insn, 2, SUF_Z, 0x96, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vfnmsub231sd", vfma_sd_insn, 2, SUF_Z, 0xBF, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vroundps", avx_sse4imm_insn, 3, SUF_Z, 0x08, 0, 0, ONLY_AVX, CPU_SSE41, 0, 0},
+ {"xchg", xchg_insn, 16, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"umov", umov_insn, 6, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_Undoc, 0},
+ {"vpbroadcastd", vpbroadcastd_avx2_insn, 4, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"fild", fildstp_insn, 4, SUF_Z, 0x00, 0x02, 0x05, 0, CPU_FPU, 0, 0},
+ {"sldt", sldtmsw_insn, 6, SUF_Z, 0x00, 0x00, 0, 0, CPU_286, 0, 0},
+ {"fdivp", farithp_insn, 3, SUF_Z, 0xF8, 0, 0, 0, CPU_FPU, 0, 0},
+ {"jna", jcc_insn, 9, SUF_Z, 0x06, 0, 0, 0, 0, 0, 0},
+ {"vpcomtrueb", vpcom_insn, 1, SUF_Z, 0xCC, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"aaa", onebyte_insn, 1, SUF_Z, 0x37, 0, 0, NOT_64, 0, 0, 0},
+ {"bsf", bsfr_insn, 3, SUF_Z, 0xBC, 0, 0, 0, CPU_386, 0, 0},
+ {"dppd", sse4imm_insn, 2, SUF_Z, 0x41, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"cmovnc", cmovcc_insn, 3, SUF_Z, 0x03, 0, 0, 0, CPU_686, 0, 0},
+ {"vpcomltb", vpcom_insn, 1, SUF_Z, 0xCC, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"cmpss", xmm_xmm32_imm_insn, 4, SUF_Z, 0xF3, 0xC2, 0, 0, CPU_SSE, 0, 0},
+ {"xbts", xbts_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_Obs, CPU_Undoc},
+ {"vmovsd", movsd_insn, 5, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fstsw", fstsw_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"xgetbv", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xD0, 0, CPU_386, CPU_XSAVE, 0},
+ {"vpcomneuq", vpcom_insn, 1, SUF_Z, 0xEF, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpneq_usps", ssecmp_128_insn, 3, SUF_Z, 0x14, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"roundss", sse4m32imm_insn, 4, SUF_Z, 0x0A, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vpmacsdqh", vpma_insn, 1, SUF_Z, 0x9F, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpgepd", ssecmp_128_insn, 3, SUF_Z, 0x0D, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vphaddw", ssse3_insn, 5, SUF_Z, 0x01, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fxrstor", twobytemem_insn, 1, SUF_Z, 0x01, 0x0F, 0xAE, 0, CPU_686, CPU_FPU, 0},
+ {"fsave", twobytemem_insn, 1, SUF_Z, 0x06, 0x9B, 0xDD, 0, CPU_FPU, 0, 0},
+ {"hlt", onebyte_insn, 1, SUF_Z, 0xF4, 0, 0, 0, CPU_Priv, 0, 0},
+ {"fldpi", twobyte_insn, 1, SUF_Z, 0xD9, 0xEB, 0, 0, CPU_FPU, 0, 0},
+ {"pavgw", mmxsse2_insn, 2, SUF_Z, 0xE3, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vfmadd231ps", vfma_ps_insn, 2, SUF_Z, 0xB8, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpmaxub", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xDE, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movd", movd_insn, 8, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_MMX, 0},
+ {"pabsw", ssse3_insn, 5, SUF_Z, 0x1D, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"cpuid", twobyte_insn, 1, SUF_Z, 0x0F, 0xA2, 0, 0, CPU_486, 0, 0},
+ {"pf2iw", now3d_insn, 1, SUF_Z, 0x1C, 0, 0, 0, CPU_3DNow, CPU_Athlon, 0},
+ {"vpcomgeud", vpcom_insn, 1, SUF_Z, 0xEE, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpgtss", ssecmp_32_insn, 4, SUF_Z, 0x0E, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpsd", cmpsd_insn, 5, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomneuw", vpcom_insn, 1, SUF_Z, 0xED, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"cmpunordpd", ssecmp_128_insn, 3, SUF_Z, 0x03, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"pause", onebyte_prefix_insn, 1, SUF_Z, 0xF3, 0x90, 0, 0, CPU_P4, 0, 0},
+ {"unpckhpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x15, 0, 0, CPU_SSE2, 0, 0},
+ {"vcmpge_oqsd", ssecmp_64_insn, 4, SUF_Z, 0x1D, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"xadd", cmpxchgxadd_insn, 4, SUF_Z, 0xC0, 0, 0, 0, CPU_486, 0, 0},
+ {"vpmaxuw", ssse3_insn, 5, SUF_Z, 0x3E, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cvtsd2ss", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5A, 0, 0, CPU_SSE2, 0, 0},
+ {"rcr", shift_insn, 16, SUF_Z, 0x03, 0, 0, 0, 0, 0, 0},
+ {"clc", onebyte_insn, 1, SUF_Z, 0xF8, 0, 0, 0, 0, 0, 0},
+ {"vpcomgew", vpcom_insn, 1, SUF_Z, 0xCD, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"vpminub", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xDA, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movntps", movnt_insn, 2, SUF_Z, 0x00, 0x2B, 0, 0, CPU_SSE, 0, 0},
+ {"monitor", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xC8, 0, CPU_SSE3, 0, 0},
+ {"vfnmaddss", fma_128_m32_insn, 3, SUF_Z, 0x7A, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"seto", setcc_insn, 1, SUF_Z, 0x00, 0, 0, 0, CPU_386, 0, 0},
+ {"vcmpneqps", ssecmp_128_insn, 3, SUF_Z, 0x04, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmplt_oqps", ssecmp_128_insn, 3, SUF_Z, 0x11, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmread", vmxmemrd_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_P4, 0, 0},
+ {"vpclmullqlqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x00, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"punpckldq", mmxsse2_insn, 2, SUF_Z, 0x62, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vpavgb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xE0, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"psignb", ssse3_insn, 5, SUF_Z, 0x08, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"fcmovnu", fcmovcc_insn, 1, SUF_Z, 0xDB, 0xD8, 0, 0, CPU_686, CPU_FPU, 0},
+ {"vgatherqps", gather_32x_32y_128_insn, 2, SUF_Z, 0x93, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vpcomuw", vpcom_imm_insn, 1, SUF_Z, 0xED, 0, 0, 0, CPU_XOP, 0, 0},
+ {"pi2fd", now3d_insn, 1, SUF_Z, 0x0D, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"vpcomq", vpcom_imm_insn, 1, SUF_Z, 0xCF, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vhaddps", xmm_xmm128_256_insn, 4, SUF_Z, 0xF2, 0x7C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vphadddq", vphaddsub_insn, 1, SUF_Z, 0xCB, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vmulsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x59, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"mulx", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_Z, 0xF2, 0x38, 0xF6, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"vpermpd", vperm_imm_avx2_insn, 1, SUF_Z, 0x01, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vpmovzxbq", sse4m16_insn, 4, SUF_Z, 0x32, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"psraw", pshift_insn, 4, SUF_Z, 0xE1, 0x71, 0x04, 0, CPU_MMX, 0, 0},
+ {"vpermilps", vpermil_insn, 4, SUF_Z, 0x04, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jno", jcc_insn, 9, SUF_Z, 0x01, 0, 0, 0, 0, 0, 0},
+ {"vcmpordpd", ssecmp_128_insn, 3, SUF_Z, 0x07, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"comisd", xmm_xmm64_insn, 4, SUF_Z, 0x66, 0x2F, 0, 0, CPU_SSE2, 0, 0},
+ {"vfnmaddsd", fma_128_m64_insn, 3, SUF_Z, 0x7B, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"punpckhdq", mmxsse2_insn, 2, SUF_Z, 0x6A, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vcmpnle_uqpd", ssecmp_128_insn, 3, SUF_Z, 0x16, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"aesenclast", aes_insn, 2, SUF_Z, 0x38, 0xDD, 0, 0, CPU_AVX, 0, 0},
+ {"pcmpeqd", mmxsse2_insn, 2, SUF_Z, 0x76, 0, 0, 0, CPU_MMX, 0, 0},
+ {"sha1msg2", intel_SHA1MSG2_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SHA, 0, 0},
+ {"vtestps", sse4_insn, 2, SUF_Z, 0x0E, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmagw", cyrixmmx_insn, 1, SUF_Z, 0x52, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"vpinsrw", pinsrw_insn, 9, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movntq", movntq_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SSE, 0, 0},
+ {"vfmsub231ps", vfma_ps_insn, 2, SUF_Z, 0xBA, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"cmovno", cmovcc_insn, 3, SUF_Z, 0x01, 0, 0, 0, CPU_686, 0, 0},
+ {"punpckhwd", mmxsse2_insn, 2, SUF_Z, 0x69, 0, 0, 0, CPU_MMX, 0, 0},
+ {"movq", movq_insn, 9, SUF_Z, 0, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vfnmsub132pd", vfma_pd_insn, 2, SUF_Z, 0x9E, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"push", push_insn, 35, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"imul", imul_insn, 19, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"popfd", onebyte_insn, 1, SUF_Z, 0x9D, 0x20, 0, NOT_64, CPU_386, 0, 0},
+ {"vfmsub213sd", vfma_sd_insn, 2, SUF_Z, 0xAB, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"call", call_insn, 30, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"pmvzb", cyrixmmx_insn, 1, SUF_Z, 0x58, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"vsubpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x5C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpsllvq", vpshiftv_vexw1_avx2_insn, 2, SUF_Z, 0x47, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"pclmulhqhqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x11, 0, 0, 0, CPU_AVX, 0, 0},
+ {"blsmsk", vex_gpr_ndd_rm_0F38_regext_insn, 2, SUF_Z, 0x00, 0xF3, 0x02, ONLY_AVX, CPU_BMI1, 0, 0},
+ {"vprotb", vprot_insn, 3, SUF_Z, 0x00, 0, 0, 0, CPU_XOP, 0, 0},
+ {"loop", loop_insn, 8, SUF_Z, 0x02, 0, 0, 0, 0, 0, 0},
+ {"jle", jcc_insn, 9, SUF_Z, 0x0E, 0, 0, 0, 0, 0, 0},
+ {"stgi", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xDC, 0, CPU_SVM, 0, 0},
+ {"not", f6_insn, 4, SUF_Z, 0x02, 0, 0, 0, 0, 0, 0},
+ {"svldt", cyrixsmm_insn, 1, SUF_Z, 0x7A, 0, 0, 0, CPU_486, CPU_Cyrix, CPU_SMM},
+ {"vpmaxsd", ssse3_insn, 5, SUF_Z, 0x3D, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"maxss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5F, 0, 0, CPU_SSE, 0, 0},
+ {"vminpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x5D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"blcs", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x01, 0x03, 0, 0, CPU_386, CPU_TBM, 0},
+ {"vpcmpeqw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x75, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"frndint", twobyte_insn, 1, SUF_Z, 0xD9, 0xFC, 0, 0, CPU_FPU, 0, 0},
+ {"vpcmpestrm", sse4pcmpstr_insn, 1, SUF_Z, 0x60, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpeqss", ssecmp_32_insn, 4, SUF_Z, 0x00, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"vfmsubadd213ps", vfma_ps_insn, 2, SUF_Z, 0xA7, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"cmovnl", cmovcc_insn, 3, SUF_Z, 0x0D, 0, 0, 0, CPU_686, 0, 0},
+ {"fldlg2", twobyte_insn, 1, SUF_Z, 0xD9, 0xEC, 0, 0, CPU_FPU, 0, 0},
+ {"clflush", clflush_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_P3, 0, 0},
+ {"iretq", onebyte_insn, 1, SUF_Z, 0xCF, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"vphaddubd", vphaddsub_insn, 1, SUF_Z, 0xD2, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vfnmadd213ps", vfma_ps_insn, 2, SUF_Z, 0xAC, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vmload", svm_rax_insn, 2, SUF_Z, 0xDA, 0, 0, 0, CPU_SVM, 0, 0},
+ {"vpminud", ssse3_insn, 5, SUF_Z, 0x3B, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"packssdw", mmxsse2_insn, 2, SUF_Z, 0x6B, 0, 0, 0, CPU_MMX, 0, 0},
+ {"pcmpeqw", mmxsse2_insn, 2, SUF_Z, 0x75, 0, 0, 0, CPU_MMX, 0, 0},
+ {"js", jcc_insn, 9, SUF_Z, 0x08, 0, 0, 0, 0, 0, 0},
+ {"jpo", jcc_insn, 9, SUF_Z, 0x0B, 0, 0, 0, 0, 0, 0},
+ {"sidt", twobytemem_insn, 1, SUF_Z, 0x01, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"jnge", jcc_insn, 9, SUF_Z, 0x0C, 0, 0, 0, 0, 0, 0},
+ {"loope", loop_insn, 8, SUF_Z, 0x01, 0, 0, 0, 0, 0, 0},
+ {"invpcid", invpcid_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_INVPCID, CPU_Priv},
+ {"pavgb", mmxsse2_insn, 2, SUF_Z, 0xE0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"pminsd", sse4_insn, 2, SUF_Z, 0x39, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"cmovnb", cmovcc_insn, 3, SUF_Z, 0x03, 0, 0, 0, CPU_686, 0, 0},
+ {"mulsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x59, 0, 0, CPU_SSE2, 0, 0},
+ {"vcmpgt_oqsd", ssecmp_64_insn, 4, SUF_Z, 0x1E, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"blsr", vex_gpr_ndd_rm_0F38_regext_insn, 2, SUF_Z, 0x00, 0xF3, 0x01, ONLY_AVX, CPU_BMI1, 0, 0},
+ {"vcmplt_oqss", ssecmp_32_insn, 4, SUF_Z, 0x11, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmsub213sd", vfma_sd_insn, 2, SUF_Z, 0xAF, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"shrd", shlrd_insn, 9, SUF_Z, 0xAC, 0, 0, 0, CPU_386, 0, 0},
+ {"vpackuswb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x67, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"paddd", mmxsse2_insn, 2, SUF_Z, 0xFE, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vcmpeq_osps", ssecmp_128_insn, 3, SUF_Z, 0x10, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vaddpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x58, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpbroadcastb", vpbroadcastb_avx2_insn, 4, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"pmuludq", mmxsse2_insn, 2, SUF_Z, 0xF4, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"cmpnltsd", ssecmp_64_insn, 4, SUF_Z, 0x05, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"vcmpgt_oqpd", ssecmp_128_insn, 3, SUF_Z, 0x1E, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcmpgtb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x64, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomfalseq", vpcom_insn, 1, SUF_Z, 0xCF, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpgtpd", ssecmp_128_insn, 3, SUF_Z, 0x0E, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmadd231ps", vfma_ps_insn, 2, SUF_Z, 0xBC, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"paddusb", mmxsse2_insn, 2, SUF_Z, 0xDC, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vcmpnge_uqpd", ssecmp_128_insn, 3, SUF_Z, 0x19, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpps", xmm_xmm128_imm_insn, 1, SUF_Z, 0x00, 0xC2, 0, 0, CPU_SSE, 0, 0},
+ {"vsqrtsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x51, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setnp", setcc_insn, 1, SUF_Z, 0x0B, 0, 0, 0, CPU_386, 0, 0},
+ {"vpcmpeqb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x74, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"psubsb", mmxsse2_insn, 2, SUF_Z, 0xE8, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vzeroall", vzero_insn, 1, SUF_Z, 0xC4, 0, 0, 0, CPU_AVX, 0, 0},
+ {"jo", jcc_insn, 9, SUF_Z, 0x00, 0, 0, 0, 0, 0, 0},
+ {"vpmovzxwd", sse4m64_insn, 4, SUF_Z, 0x33, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpminsw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xEA, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"bswap", bswap_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_486, 0, 0},
+ {"movntpd", movnt_insn, 2, SUF_Z, 0x66, 0x2B, 0, 0, CPU_SSE2, 0, 0},
+ {"paddb", mmxsse2_insn, 2, SUF_Z, 0xFC, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vpmaskmovq", vmaskmov_vexw1_avx2_insn, 4, SUF_Z, 0x8C, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vfnmsub213pd", vfma_pd_insn, 2, SUF_Z, 0xAE, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"jng", jcc_insn, 9, SUF_Z, 0x0E, 0, 0, 0, 0, 0, 0},
+ {"vcmpngeps", ssecmp_128_insn, 3, SUF_Z, 0x09, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"minss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5D, 0, 0, CPU_SSE, 0, 0},
+ {"vpsubusb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xD8, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vsqrtps", avx_xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x51, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fclex", threebyte_insn, 1, SUF_Z, 0x9B, 0xDB, 0xE2, 0, CPU_FPU, 0, 0},
+ {"pmovzxbq", sse4m16_insn, 4, SUF_Z, 0x32, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vextracti128", vextractif128_insn, 1, SUF_Z, 0x39, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"pcmpistri", sse4pcmpstr_insn, 1, SUF_Z, 0x63, 0, 0, 0, CPU_SSE42, 0, 0},
+ {"ucomisd", xmm_xmm64_insn, 4, SUF_Z, 0x66, 0x2E, 0, 0, CPU_SSE2, 0, 0},
+ {"vmwrite", vmxmemwr_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_P4, 0, 0},
+ {"pfacc", now3d_insn, 1, SUF_Z, 0xAE, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"lldt", prot286_insn, 1, SUF_Z, 0x02, 0x00, 0, 0, CPU_286, CPU_Priv, CPU_Prot},
+ {"fincstp", twobyte_insn, 1, SUF_Z, 0xD9, 0xF7, 0, 0, CPU_FPU, 0, 0},
+ {"vcmpps", xmm_xmm128_imm_256_insn, 3, SUF_Z, 0x00, 0xC2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fcomp", fcom_insn, 6, SUF_Z, 0xD8, 0x03, 0, 0, CPU_FPU, 0, 0},
+ {"pmullw", mmxsse2_insn, 2, SUF_Z, 0xD5, 0, 0, 0, CPU_MMX, 0, 0},
+ {"cqo", onebyte_insn, 1, SUF_Z, 0x99, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"blendvps", sse4xmm0_insn, 2, SUF_Z, 0x14, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vpcomfalseud", vpcom_insn, 1, SUF_Z, 0xEE, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"vpsignw", ssse3_insn, 5, SUF_Z, 0x09, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lgs", lfgss_insn, 3, SUF_Z, 0xB5, 0, 0, 0, CPU_386, 0, 0},
+ {"vfmaddpd", fma_128_256_insn, 4, SUF_Z, 0x69, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"vcmpnge_uqss", ssecmp_32_insn, 4, SUF_Z, 0x19, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"minps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x5D, 0, 0, CPU_SSE, 0, 0},
+ {"aesdec", aes_insn, 2, SUF_Z, 0x38, 0xDE, 0, 0, CPU_AVX, 0, 0},
+ {"vpsignb", ssse3_insn, 5, SUF_Z, 0x08, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pminud", sse4_insn, 2, SUF_Z, 0x3B, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vpcomuq", vpcom_imm_insn, 1, SUF_Z, 0xEF, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpmaxsw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xEE, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmmcall", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xD9, 0, CPU_SVM, 0, 0},
+ {"vpunpckldq", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x62, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fcompp", twobyte_insn, 1, SUF_Z, 0xDE, 0xD9, 0, 0, CPU_FPU, 0, 0},
+ {"vcmpneq_ussd", ssecmp_64_insn, 4, SUF_Z, 0x14, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomneqd", vpcom_insn, 1, SUF_Z, 0xCE, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"pblendw", sse4imm_insn, 2, SUF_Z, 0x0E, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vmovq", vmovq_insn, 5, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"haddps", xmm_xmm128_insn, 2, SUF_Z, 0xF2, 0x7C, 0, 0, CPU_SSE3, 0, 0},
+ {"svts", cyrixsmm_insn, 1, SUF_Z, 0x7C, 0, 0, 0, CPU_486, CPU_Cyrix, CPU_SMM},
+ {"o16", NULL, X86_OPERSIZE>>8, 0x10, 0, 0, 0, 0, 0, 0, 0},
+ {"rcl", shift_insn, 16, SUF_Z, 0x02, 0, 0, 0, 0, 0, 0},
+ {"jge", jcc_insn, 9, SUF_Z, 0x0D, 0, 0, 0, 0, 0, 0},
+ {"pfrcpit1", now3d_insn, 1, SUF_Z, 0xA6, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"pminsb", sse4_insn, 2, SUF_Z, 0x38, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"daa", onebyte_insn, 1, SUF_Z, 0x27, 0, 0, NOT_64, 0, 0, 0},
+ {"vpcomtrueub", vpcom_insn, 1, SUF_Z, 0xEC, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"andnpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x55, 0, 0, CPU_SSE2, 0, 0},
+ {"stosw", onebyte_insn, 1, SUF_Z, 0xAB, 0x10, 0, 0, 0, 0, 0},
+ {"vpabsw", avx2_ssse3_2op_insn, 2, SUF_Z, 0x1D, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pfrsqit1", now3d_insn, 1, SUF_Z, 0xA7, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"sqrtps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x51, 0, 0, CPU_SSE, 0, 0},
+ {"fnsave", onebytemem_insn, 1, SUF_Z, 0x06, 0xDD, 0, 0, CPU_FPU, 0, 0},
+ {"vpcomleuw", vpcom_insn, 1, SUF_Z, 0xED, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"cvtdq2ps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x5B, 0, 0, CPU_SSE2, 0, 0},
+ {"vcvtsd2ss", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5A, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vdivpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x5E, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpneq_ospd", ssecmp_128_insn, 3, SUF_Z, 0x1C, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"wrgsbase", fs_gs_base_insn, 2, SUF_Z, 0x03, 0, 0, ONLY_64, CPU_FSGSBASE, 0, 0},
+ {"add", arith_insn, 22, SUF_Z, 0x00, 0x00, 0, 0, 0, 0, 0},
+ {"smi", onebyte_insn, 1, SUF_Z, 0xF1, 0, 0, 0, CPU_386, CPU_Undoc, 0},
+ {"vpcomequq", vpcom_insn, 1, SUF_Z, 0xEF, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"movapd", movau_insn, 6, SUF_Z, 0x66, 0x28, 0x01, 0, CPU_SSE2, 0, 0},
+ {"vpmulhw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xE5, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cvttps2dq", xmm_xmm128_insn, 2, SUF_Z, 0xF3, 0x5B, 0, 0, CPU_SSE2, 0, 0},
+ {"addss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x58, 0, 0, CPU_SSE, 0, 0},
+ {"rsqrtss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x52, 0, 0, CPU_SSE, 0, 0},
+ {"vpperm", vpperm_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpcomnequq", vpcom_insn, 1, SUF_Z, 0xEF, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"vcvttsd2si", cvt_rx_xmm64_insn, 4, SUF_Z, 0xF2, 0x2C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmulhriw", cyrixmmx_insn, 1, SUF_Z, 0x5D, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"mul", f6_insn, 4, SUF_Z, 0x04, 0, 0, 0, 0, 0, 0},
+ {"ucomiss", xmm_xmm32_insn, 4, SUF_Z, 0x00, 0x2E, 0, 0, CPU_SSE, 0, 0},
+ {"vpcomneqb", vpcom_insn, 1, SUF_Z, 0xCC, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"vpsllw", vpshift_insn, 8, SUF_Z, 0xF1, 0x71, 0x06, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomfalseb", vpcom_insn, 1, SUF_Z, 0xCC, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"vpmovsxwd", sse4m64_insn, 4, SUF_Z, 0x23, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"xend", tsx_0x0F_0x01_insn, 1, SUF_Z, 0xD5, 0, 0, 0, CPU_TSX, 0, 0},
+ {"pshufd", xmm_xmm128_imm_insn, 1, SUF_Z, 0x66, 0x70, 0, 0, CPU_SSE2, 0, 0},
+ {"jnc", jcc_insn, 9, SUF_Z, 0x03, 0, 0, 0, 0, 0, 0},
+ {"vcmpnleps", ssecmp_128_insn, 3, SUF_Z, 0x06, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"psrldq", pslrldq_insn, 4, SUF_Z, 0x03, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"setb", setcc_insn, 1, SUF_Z, 0x02, 0, 0, 0, CPU_386, 0, 0},
+ {"pinsrw", pinsrw_insn, 9, SUF_Z, 0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"jnae", jcc_insn, 9, SUF_Z, 0x02, 0, 0, 0, 0, 0, 0},
+ {"movupd", movau_insn, 6, SUF_Z, 0x66, 0x10, 0x01, 0, CPU_SSE2, 0, 0},
+ {"vcmptrue_ussd", ssecmp_64_insn, 4, SUF_Z, 0x1F, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fcmovbe", fcmovcc_insn, 1, SUF_Z, 0xDA, 0xD0, 0, 0, CPU_686, CPU_FPU, 0},
+ {"movups", movau_insn, 6, SUF_Z, 0x00, 0x10, 0x01, 0, CPU_SSE, 0, 0},
+ {"fyl2x", twobyte_insn, 1, SUF_Z, 0xD9, 0xF1, 0, 0, CPU_FPU, 0, 0},
+ {"stosd", onebyte_insn, 1, SUF_Z, 0xAB, 0x20, 0, 0, CPU_386, 0, 0},
+ {"vcmple_oqss", ssecmp_32_insn, 4, SUF_Z, 0x12, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jb", jcc_insn, 9, SUF_Z, 0x02, 0, 0, 0, 0, 0, 0},
+ {"vpcomfalseub", vpcom_insn, 1, SUF_Z, 0xEC, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"fxam", twobyte_insn, 1, SUF_Z, 0xD9, 0xE5, 0, 0, CPU_FPU, 0, 0},
+ {"vmresume", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xC3, 0, CPU_P4, 0, 0},
+ {"vcmpneq_osss", ssecmp_32_insn, 4, SUF_Z, 0x1C, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"swapgs", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xF8, ONLY_64, 0, 0, 0},
+ {"vpunpckhqdq", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x6D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"prefetcht2", twobytemem_insn, 1, SUF_Z, 0x03, 0x0F, 0x18, 0, CPU_P3, 0, 0},
+ {"pmachriw", pmachriw_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"aas", onebyte_insn, 1, SUF_Z, 0x3F, 0, 0, NOT_64, 0, 0, 0},
+ {"fldz", twobyte_insn, 1, SUF_Z, 0xD9, 0xEE, 0, 0, CPU_FPU, 0, 0},
+ {"vcmppd", xmm_xmm128_imm_256_insn, 3, SUF_Z, 0x66, 0xC2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"retf", retnf_insn, 6, SUF_Z, 0xCA, 0x40, 0, 0, 0, 0, 0},
+ {"iretw", onebyte_insn, 1, SUF_Z, 0xCF, 0x10, 0, 0, 0, 0, 0},
+ {"pclmulhqlqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x01, 0, 0, 0, CPU_AVX, 0, 0},
+ {"vpcomgtw", vpcom_insn, 1, SUF_Z, 0xCD, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"pfcmpeq", now3d_insn, 1, SUF_Z, 0xB0, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"mfence", threebyte_insn, 1, SUF_Z, 0x0F, 0xAE, 0xF0, 0, CPU_P3, 0, 0},
+ {"vprotq", vprot_insn, 3, SUF_Z, 0x03, 0, 0, 0, CPU_XOP, 0, 0},
+ {"jae", jcc_insn, 9, SUF_Z, 0x03, 0, 0, 0, 0, 0, 0},
+ {"fpatan", twobyte_insn, 1, SUF_Z, 0xD9, 0xF3, 0, 0, CPU_FPU, 0, 0},
+ {"pfsub", now3d_insn, 1, SUF_Z, 0x9A, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"pmaxsb", sse4_insn, 2, SUF_Z, 0x3C, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vcmpltsd", ssecmp_64_insn, 4, SUF_Z, 0x01, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomnequb", vpcom_insn, 1, SUF_Z, 0xEC, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"insw", onebyte_insn, 1, SUF_Z, 0x6D, 0x10, 0, 0, 0, 0, 0},
+ {"vfmsub132sd", vfma_sd_insn, 2, SUF_Z, 0x9B, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"prefetchw", twobytemem_insn, 1, SUF_Z, 0x01, 0x0F, 0x0D, 0, CPU_PRFCHW, 0, 0},
+ {"vlddqu", lddqu_insn, 2, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpfalsepd", ssecmp_128_insn, 3, SUF_Z, 0x0B, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpxchg16b", cmpxchg16b_insn, 1, SUF_Z, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"vpmaddubsw", ssse3_insn, 5, SUF_Z, 0x04, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"smsw", sldtmsw_insn, 6, SUF_Z, 0x04, 0x01, 0, 0, CPU_286, 0, 0},
+ {"movlpd", movhlp_insn, 3, SUF_Z, 0x66, 0x12, 0, 0, CPU_SSE2, 0, 0},
+ {"vcmpngess", ssecmp_32_insn, 4, SUF_Z, 0x09, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"maskmovq", maskmovq_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"cmovae", cmovcc_insn, 3, SUF_Z, 0x03, 0, 0, 0, CPU_686, 0, 0},
+ {"setnae", setcc_insn, 1, SUF_Z, 0x02, 0, 0, 0, CPU_386, 0, 0},
+ {"vminss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomgeub", vpcom_insn, 1, SUF_Z, 0xEC, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"jns", jcc_insn, 9, SUF_Z, 0x09, 0, 0, 0, 0, 0, 0},
+ {"ibts", ibts_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_Obs, CPU_Undoc},
+ {"je", jcc_insn, 9, SUF_Z, 0x04, 0, 0, 0, 0, 0, 0},
+ {"pmovsxbw", sse4m64_insn, 4, SUF_Z, 0x20, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vunpckhps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x15, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vbroadcasti128", vbroadcastif128_insn, 1, SUF_Z, 0x5A, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"cld", onebyte_insn, 1, SUF_Z, 0xFC, 0, 0, 0, 0, 0, 0},
+ {"ud1", twobyte_insn, 1, SUF_Z, 0x0F, 0xB9, 0, 0, CPU_286, CPU_Undoc, 0},
+ {"vmovups", movau_insn, 6, SUF_Z, 0x00, 0x10, 0x01, ONLY_AVX, CPU_AVX, 0, 0},
+ {"f2xm1", twobyte_insn, 1, SUF_Z, 0xD9, 0xF0, 0, 0, CPU_FPU, 0, 0},
+ {"vcmpneq_uspd", ssecmp_128_insn, 3, SUF_Z, 0x14, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmadd231ss", vfma_ss_insn, 2, SUF_Z, 0xBD, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vcmpneq_oqss", ssecmp_32_insn, 4, SUF_Z, 0x0C, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpor", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xEB, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jrcxz", jcxz_insn, 2, SUF_Z, 0x40, 0, 0, ONLY_64, 0, 0, 0},
+ {"vpand", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xDB, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpminsd", ssse3_insn, 5, SUF_Z, 0x39, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomgtuq", vpcom_insn, 1, SUF_Z, 0xEF, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"vpmovzxbw", sse4m64_insn, 4, SUF_Z, 0x30, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomtrueud", vpcom_insn, 1, SUF_Z, 0xEE, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"vpcomneb", vpcom_insn, 1, SUF_Z, 0xCC, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"cvttps2pi", cvt_mm_xmm64_insn, 2, SUF_Z, 0x2C, 0, 0, 0, CPU_SSE, 0, 0},
+ {"movmskpd", movmsk_insn, 4, SUF_Z, 0x66, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"pfsubr", now3d_insn, 1, SUF_Z, 0xAA, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"vsubss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"invvpid", eptvpid_insn, 2, SUF_Z, 0x01, 0, 0, 0, CPU_386, CPU_EPTVPID, 0},
+ {"cmpleps", ssecmp_128_insn, 3, SUF_Z, 0x02, 0, 0, 0, CPU_SSE, 0, 0},
+ {"vpavgw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xE3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmovhlps", movhllhps_insn, 2, SUF_Z, 0x12, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpeq_uqpd", ssecmp_128_insn, 3, SUF_Z, 0x08, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"maxps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x5F, 0, 0, CPU_SSE, 0, 0},
+ {"insb", onebyte_insn, 1, SUF_Z, 0x6C, 0x00, 0, 0, 0, 0, 0},
+ {"vpmaxsb", ssse3_insn, 5, SUF_Z, 0x3C, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmplepd", ssecmp_128_insn, 3, SUF_Z, 0x02, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"popad", onebyte_insn, 1, SUF_Z, 0x61, 0x20, 0, NOT_64, CPU_386, 0, 0},
+ {"cmovnge", cmovcc_insn, 3, SUF_Z, 0x0C, 0, 0, 0, CPU_686, 0, 0},
+ {"unpckhps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x15, 0, 0, CPU_SSE, 0, 0},
+ {"cmovpo", cmovcc_insn, 3, SUF_Z, 0x0B, 0, 0, 0, CPU_686, 0, 0},
+ {"setnb", setcc_insn, 1, SUF_Z, 0x03, 0, 0, 0, CPU_386, 0, 0},
+ {"sbb", arith_insn, 22, SUF_Z, 0x18, 0x03, 0, 0, 0, 0, 0},
+ {"divpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x5E, 0, 0, CPU_SSE2, 0, 0},
+ {"vbroadcastf128", vbroadcastif128_insn, 1, SUF_Z, 0x1A, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"insd", onebyte_insn, 1, SUF_Z, 0x6D, 0x20, 0, 0, CPU_386, 0, 0},
+ {"invept", eptvpid_insn, 2, SUF_Z, 0x00, 0, 0, 0, CPU_386, CPU_EPTVPID, 0},
+ {"vmaxsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5F, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpsw", onebyte_insn, 1, SUF_Z, 0xA7, 0x10, 0, 0, 0, 0, 0},
+ {"vcmpeqss", ssecmp_32_insn, 4, SUF_Z, 0x00, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"mulps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x59, 0, 0, CPU_SSE, 0, 0},
+ {"vaddps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x58, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpgeps", ssecmp_128_insn, 3, SUF_Z, 0x0D, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfrczps", vfrc_pdps_insn, 2, SUF_Z, 0x00, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpeq_uqss", ssecmp_32_insn, 4, SUF_Z, 0x08, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"sysexit", twobyte_insn, 1, SUF_Z, 0x0F, 0x35, 0, NOT_64, CPU_686, CPU_Priv, 0},
+ {"xor", arith_insn, 22, SUF_Z, 0x30, 0x06, 0, 0, 0, 0, 0},
+ {"pshuflw", xmm_xmm128_imm_insn, 1, SUF_Z, 0xF2, 0x70, 0, 0, CPU_SSE2, 0, 0},
+ {"vfrczpd", vfrc_pdps_insn, 2, SUF_Z, 0x01, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpcomleud", vpcom_insn, 1, SUF_Z, 0xEE, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"vpcomlew", vpcom_insn, 1, SUF_Z, 0xCD, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"addps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x58, 0, 0, CPU_SSE, 0, 0},
+ {"vpsraw", vpshift_insn, 8, SUF_Z, 0xE1, 0x71, 0x04, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcomiss", avx_xmm_xmm32_insn, 2, SUF_Z, 0x00, 0x2F, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpngtpd", ssecmp_128_insn, 3, SUF_Z, 0x0A, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpnltpd", ssecmp_128_insn, 3, SUF_Z, 0x05, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"sqrtsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x51, 0, 0, CPU_SSE2, 0, 0},
+ {"pfrsqrt", now3d_insn, 1, SUF_Z, 0x97, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"scasw", onebyte_insn, 1, SUF_Z, 0xAF, 0x10, 0, 0, 0, 0, 0},
+ {"pinsrd", pinsrd_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_SSE41, 0},
+ {"vaesenclast", aes_insn, 2, SUF_Z, 0x38, 0xDD, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rdtscp", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xF9, 0, CPU_686, CPU_AMD, CPU_Priv},
+ {"vcmpeq_ospd", ssecmp_128_insn, 3, SUF_Z, 0x10, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"div", div_insn, 8, SUF_Z, 0x06, 0, 0, 0, 0, 0, 0},
+ {"cvtpd2pi", cvt_mm_xmm_insn, 1, SUF_Z, 0x66, 0x2D, 0, 0, CPU_SSE2, 0, 0},
+ {"vcmpltss", ssecmp_32_insn, 4, SUF_Z, 0x01, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vphaddwq", vphaddsub_insn, 1, SUF_Z, 0xC7, 0, 0, 0, CPU_XOP, 0, 0},
+ {"cmovz", cmovcc_insn, 3, SUF_Z, 0x04, 0, 0, 0, CPU_686, 0, 0},
+ {"vpcomltud", vpcom_insn, 1, SUF_Z, 0xEE, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"ret", retnf_insn, 6, SUF_Z, 0xC2, 0, 0, 0, 0, 0, 0},
+ {"vpshaw", amd_vpshift_insn, 2, SUF_Z, 0x99, 0, 0, 0, CPU_XOP, 0, 0},
+ {"pblendvb", sse4xmm0_insn, 2, SUF_Z, 0x10, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"pinsrq", pinsrq_insn, 2, SUF_Z, 0, 0, 0, ONLY_64, CPU_SSE41, 0, 0},
+ {"vmulpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x59, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmaxsd", sse4_insn, 2, SUF_Z, 0x3D, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"cmovne", cmovcc_insn, 3, SUF_Z, 0x05, 0, 0, 0, CPU_686, 0, 0},
+ {"ltr", prot286_insn, 1, SUF_Z, 0x03, 0x00, 0, 0, CPU_286, CPU_Priv, CPU_Prot},
+ {"fdecstp", twobyte_insn, 1, SUF_Z, 0xD9, 0xF6, 0, 0, CPU_FPU, 0, 0},
+ {"lsl", larlsl_insn, 6, SUF_Z, 0x03, 0, 0, 0, CPU_286, CPU_Prot, 0},
+ {"pcmpgtb", mmxsse2_insn, 2, SUF_Z, 0x64, 0, 0, 0, CPU_MMX, 0, 0},
+ {"psrld", pshift_insn, 4, SUF_Z, 0xD2, 0x72, 0x02, 0, CPU_MMX, 0, 0},
+ {"xsave", twobytemem_insn, 1, SUF_Z, 0x04, 0x0F, 0xAE, 0, CPU_386, CPU_XSAVE, 0},
+ {"hsubps", xmm_xmm128_insn, 2, SUF_Z, 0xF2, 0x7D, 0, 0, CPU_SSE3, 0, 0},
+ {"sti", onebyte_insn, 1, SUF_Z, 0xFB, 0, 0, 0, 0, 0, 0},
+ {"pfcmpge", now3d_insn, 1, SUF_Z, 0x90, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"setnz", setcc_insn, 1, SUF_Z, 0x05, 0, 0, 0, CPU_386, 0, 0},
+ {"vaesdeclast", aes_insn, 2, SUF_Z, 0x38, 0xDF, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmadd213ss", vfma_ss_insn, 2, SUF_Z, 0xAD, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"pcmpestri", sse4pcmpstr_insn, 1, SUF_Z, 0x61, 0, 0, 0, CPU_SSE42, 0, 0},
+ {"vpcmpeqq", ssse3_insn, 5, SUF_Z, 0x29, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fmul", farith_insn, 7, SUF_Z, 0xC8, 0xC8, 0x01, 0, CPU_FPU, 0, 0},
+ {"vmovntpd", movnt_insn, 2, SUF_Z, 0x66, 0x2B, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpmadcsswd", vpma_insn, 1, SUF_Z, 0xA6, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpngt_uqps", ssecmp_128_insn, 3, SUF_Z, 0x1A, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"svdc", svdc_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_486, CPU_Cyrix, CPU_SMM},
+ {"orpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x56, 0, 0, CPU_SSE2, 0, 0},
+ {"fdivrp", farithp_insn, 3, SUF_Z, 0xF0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vgatherdps", gather_32x_32y_insn, 2, SUF_Z, 0x92, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"packsswb", mmxsse2_insn, 2, SUF_Z, 0x63, 0, 0, 0, CPU_MMX, 0, 0},
+ {"scasd", onebyte_insn, 1, SUF_Z, 0xAF, 0x20, 0, 0, CPU_386, 0, 0},
+ {"vfmsub231pd", vfma_pd_insn, 2, SUF_Z, 0xBA, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"fptan", twobyte_insn, 1, SUF_Z, 0xD9, 0xF2, 0, 0, CPU_FPU, 0, 0},
+ {"vpcomd", vpcom_imm_insn, 1, SUF_Z, 0xCE, 0, 0, 0, CPU_XOP, 0, 0},
+ {"cvtsi2sd", cvt_xmm_rmx_insn, 6, SUF_Z, 0xF2, 0x2A, 0, 0, CPU_SSE2, 0, 0},
+ {"vphsubwd", vphaddsub_insn, 1, SUF_Z, 0xE2, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpnlt_uqpd", ssecmp_128_insn, 3, SUF_Z, 0x15, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpneqpd", ssecmp_128_insn, 3, SUF_Z, 0x04, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"ud2", twobyte_insn, 1, SUF_Z, 0x0F, 0x0B, 0, 0, CPU_286, 0, 0},
+ {"andps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x54, 0, 0, CPU_SSE, 0, 0},
+ {"vorpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x56, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lmsw", prot286_insn, 1, SUF_Z, 0x06, 0x01, 0, 0, CPU_286, CPU_Priv, 0},
+ {"tzmsk", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x01, 0x04, 0, 0, CPU_386, CPU_TBM, 0},
+ {"vdppd", sse4imm_insn, 2, SUF_Z, 0x41, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"smintold", twobyte_insn, 1, SUF_Z, 0x0F, 0x7E, 0, 0, CPU_486, CPU_Cyrix, CPU_Obs},
+ {"smint", twobyte_insn, 1, SUF_Z, 0x0F, 0x38, 0, 0, CPU_686, CPU_Cyrix, 0},
+ {"vcmpnlt_uqss", ssecmp_32_insn, 4, SUF_Z, 0x15, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovs", cmovcc_insn, 3, SUF_Z, 0x08, 0, 0, 0, CPU_686, 0, 0},
+ {"vpcomequw", vpcom_insn, 1, SUF_Z, 0xED, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"cvttsd2si", cvt_rx_xmm64_insn, 4, SUF_Z, 0xF2, 0x2C, 0, 0, CPU_SSE2, 0, 0},
+ {"vcmpge_oqss", ssecmp_32_insn, 4, SUF_Z, 0x1D, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"minpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x5D, 0, 0, CPU_SSE2, 0, 0},
+ {"por", mmxsse2_insn, 2, SUF_Z, 0xEB, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vcmpfalseps", ssecmp_128_insn, 3, SUF_Z, 0x0B, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vaddsubpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0xD0, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmxon", vmxthreebytemem_insn, 1, SUF_Z, 0xF3, 0, 0, 0, CPU_P4, 0, 0},
+ {"fldln2", twobyte_insn, 1, SUF_Z, 0xD9, 0xED, 0, 0, CPU_FPU, 0, 0},
+ {"pfpnacc", now3d_insn, 1, SUF_Z, 0x8E, 0, 0, 0, CPU_3DNow, CPU_Athlon, 0},
+ {"lfs", lfgss_insn, 3, SUF_Z, 0xB4, 0, 0, 0, CPU_386, 0, 0},
+ {"vmovlps", movhlp_insn, 3, SUF_Z, 0x00, 0x12, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtsi2sd", cvt_xmm_rmx_insn, 6, SUF_Z, 0xF2, 0x2A, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtdq2ps", avx_xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x5B, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtss2sd", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5A, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpge_oqpd", ssecmp_128_insn, 3, SUF_Z, 0x1D, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmsub132pd", vfma_pd_insn, 2, SUF_Z, 0x9A, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpblendw", sse4imm_256avx2_insn, 4, SUF_Z, 0x0E, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmulhrw", now3d_insn, 1, SUF_Z, 0xB7, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"vcmpless", ssecmp_32_insn, 4, SUF_Z, 0x02, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movntss", movntss_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SSE4a, 0, 0},
+ {"vpandn", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xDF, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pextrd", pextrd_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_SSE41, 0},
+ {"divsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5E, 0, 0, CPU_SSE2, 0, 0},
+ {"pmaxud", sse4_insn, 2, SUF_Z, 0x3F, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"pfmul", now3d_insn, 1, SUF_Z, 0xB4, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"vmaxpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x5F, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vgatherdpd", gather_64x_64x_insn, 2, SUF_Z, 0x92, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"movnti", movnti_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_P4, 0, 0},
+ {"pxor", mmxsse2_insn, 2, SUF_Z, 0xEF, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vpmovsxbw", sse4m64_insn, 4, SUF_Z, 0x20, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmovhps", movhlp_insn, 3, SUF_Z, 0x00, 0x16, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jbe", jcc_insn, 9, SUF_Z, 0x06, 0, 0, 0, 0, 0, 0},
+ {"outsw", onebyte_insn, 1, SUF_Z, 0x6F, 0x10, 0, 0, 0, 0, 0},
+ {"vcmpngt_uqpd", ssecmp_128_insn, 3, SUF_Z, 0x1A, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpeqpd", ssecmp_128_insn, 3, SUF_Z, 0x00, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpermd", vperm_var_avx2_insn, 1, SUF_Z, 0x36, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vpcomltuw", vpcom_insn, 1, SUF_Z, 0xED, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"wrshr", rdwrshr_insn, 1, SUF_Z, 0x01, 0, 0, 0, CPU_686, CPU_Cyrix, CPU_SMM},
+ {"vmxoff", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xC4, 0, CPU_P4, 0, 0},
+ {"paddq", mmxsse2_insn, 2, SUF_Z, 0xD4, 0, 0, 0, CPU_MMX, 0, 0},
+ {"fstcw", fstcw_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"setnle", setcc_insn, 1, SUF_Z, 0x0F, 0, 0, 0, CPU_386, 0, 0},
+ {"cbw", onebyte_insn, 1, SUF_Z, 0x98, 0x10, 0, 0, 0, 0, 0},
+ {"vfmsub213ss", vfma_ss_insn, 2, SUF_Z, 0xAB, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"pfmax", now3d_insn, 1, SUF_Z, 0xA4, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"jnb", jcc_insn, 9, SUF_Z, 0x03, 0, 0, 0, 0, 0, 0},
+ {"blendps", sse4imm_insn, 2, SUF_Z, 0x0C, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"fsincos", twobyte_insn, 1, SUF_Z, 0xD9, 0xFB, 0, 0, CPU_286, CPU_FPU, 0},
+ {"vfmadd231ss", vfma_ss_insn, 2, SUF_Z, 0xB9, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"fld1", twobyte_insn, 1, SUF_Z, 0xD9, 0xE8, 0, 0, CPU_FPU, 0, 0},
+ {"t1mskc", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x01, 0x07, 0, 0, CPU_386, CPU_TBM, 0},
+ {"xabort", tsx_xabort_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_TSX, 0, 0},
+ {"pextrw", pextrw_insn, 7, SUF_Z, 0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vfnmsub231pd", vfma_pd_insn, 2, SUF_Z, 0xBE, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"psubsw", mmxsse2_insn, 2, SUF_Z, 0xE9, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vfnmsubss", fma_128_m32_insn, 3, SUF_Z, 0x7E, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"lea", lea_insn, 3, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"vmptrld", vmxtwobytemem_insn, 1, SUF_Z, 0x06, 0, 0, 0, CPU_P4, 0, 0},
+ {"cmpeqsd", ssecmp_64_insn, 4, SUF_Z, 0x00, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"o64", NULL, X86_OPERSIZE>>8, 0x40, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"vcvtpd2ps", avx_cvt_xmm128_insn, 2, SUF_Z, 0x66, 0x5A, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"faddp", farithp_insn, 3, SUF_Z, 0xC0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vpsrldq", pslrldq_insn, 4, SUF_Z, 0x03, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpfalsesd", ssecmp_64_insn, 4, SUF_Z, 0x0B, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lzcnt", cnt_insn, 3, SUF_Z, 0xBD, 0, 0, 0, CPU_LZCNT, 0, 0},
+ {"vcmpunord_sss", ssecmp_32_insn, 4, SUF_Z, 0x13, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpleps", ssecmp_128_insn, 3, SUF_Z, 0x02, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vextractps", extractps_insn, 2, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"enter", enter_insn, 3, SUF_Z, 0, 0, 0, 0, CPU_186, 0, 0},
+ {"vandnpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x55, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"roundsd", sse4m64imm_insn, 4, SUF_Z, 0x0B, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vpaddb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xFC, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpordss", ssecmp_32_insn, 4, SUF_Z, 0x07, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"vpcomeqb", vpcom_insn, 1, SUF_Z, 0xCC, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"vgatherqpd", gather_64x_64y_insn, 2, SUF_Z, 0x93, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"pcmpeqq", sse4_insn, 2, SUF_Z, 0x29, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"fsetpm", twobyte_insn, 1, SUF_Z, 0xDB, 0xE4, 0, 0, CPU_286, CPU_FPU, CPU_Obs},
+ {"vpcomgeuw", vpcom_insn, 1, SUF_Z, 0xED, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"vpmadcswd", vpma_insn, 1, SUF_Z, 0xB6, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vcvtps2ph", avx_cvtps2ph_insn, 4, SUF_Z, 0x66, 0x1D, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpneqpd", ssecmp_128_insn, 3, SUF_Z, 0x04, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fcmove", fcmovcc_insn, 1, SUF_Z, 0xDA, 0xC8, 0, 0, CPU_686, CPU_FPU, 0},
+ {"vfmadd231pd", vfma_pd_insn, 2, SUF_Z, 0xB8, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"fprem1", twobyte_insn, 1, SUF_Z, 0xD9, 0xF5, 0, 0, CPU_286, CPU_FPU, 0},
+ {"setna", setcc_insn, 1, SUF_Z, 0x06, 0, 0, 0, CPU_386, 0, 0},
+ {"cwd", onebyte_insn, 1, SUF_Z, 0x99, 0x10, 0, 0, 0, 0, 0},
+ {"aesimc", aesimc_insn, 1, SUF_Z, 0x38, 0xDB, 0, 0, CPU_AES, 0, 0},
+ {"idiv", div_insn, 8, SUF_Z, 0x07, 0, 0, 0, 0, 0, 0},
+ {"vcmplt_oqsd", ssecmp_64_insn, 4, SUF_Z, 0x11, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cvtps2pi", cvt_mm_xmm64_insn, 2, SUF_Z, 0x2D, 0, 0, 0, CPU_SSE, 0, 0},
+ {"vblendps", sse4imm_256_insn, 4, SUF_Z, 0x0C, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setnge", setcc_insn, 1, SUF_Z, 0x0C, 0, 0, 0, CPU_386, 0, 0},
+ {"xsaveopt64", xsaveopt64_insn, 1, SUF_Z, 0x06, 0x0F, 0xAE, ONLY_64, CPU_XSAVEOPT, 0, 0},
+ {"pcmpestrm", sse4pcmpstr_insn, 1, SUF_Z, 0x60, 0, 0, 0, CPU_SSE42, 0, 0},
+ {"vpshlq", amd_vpshift_insn, 2, SUF_Z, 0x97, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vmaskmovdqu", maskmovdqu_insn, 1, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomnew", vpcom_insn, 1, SUF_Z, 0xCD, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpunordpd", ssecmp_128_insn, 3, SUF_Z, 0x03, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpneqsd", ssecmp_64_insn, 4, SUF_Z, 0x04, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cvttpd2dq", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0xE6, 0, 0, CPU_SSE2, 0, 0},
+ {"sahf", onebyte_insn, 1, SUF_Z, 0x9E, 0, 0, 0, 0, 0, 0},
+ {"vpshab", amd_vpshift_insn, 2, SUF_Z, 0x98, 0, 0, 0, CPU_XOP, 0, 0},
+ {"jnz", jcc_insn, 9, SUF_Z, 0x05, 0, 0, 0, 0, 0, 0},
+ {"pextrb", pextrb_insn, 3, SUF_Z, 0, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vmsave", svm_rax_insn, 2, SUF_Z, 0xDB, 0, 0, 0, CPU_SVM, 0, 0},
+ {"vcmpordsd", ssecmp_64_insn, 4, SUF_Z, 0x07, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setbe", setcc_insn, 1, SUF_Z, 0x06, 0, 0, 0, CPU_386, 0, 0},
+ {"vfmsubadd231ps", vfma_ps_insn, 2, SUF_Z, 0xB7, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpcomgtb", vpcom_insn, 1, SUF_Z, 0xCC, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"vfnmsubps", fma_128_256_insn, 4, SUF_Z, 0x7C, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"shrx", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_Z, 0xF2, 0x38, 0xF7, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"dpps", sse4imm_insn, 2, SUF_Z, 0x40, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"movdqa", movau_insn, 6, SUF_Z, 0x66, 0x6F, 0x10, 0, CPU_SSE2, 0, 0},
+ {"xcryptofb", padlock_insn, 1, SUF_Z, 0xE8, 0xF3, 0xA7, 0, CPU_PadLock, 0, 0},
+ {"jmp", jmp_insn, 31, SUF_Z, 0, 0, 0, 0, 0, 0, 0},
+ {"vpsrlq", vpshift_insn, 8, SUF_Z, 0xD3, 0x73, 0x02, ONLY_AVX, CPU_AVX, 0, 0},
+ {"invlpga", invlpga_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_SVM, 0, 0},
+ {"vpcomgtq", vpcom_insn, 1, SUF_Z, 0xCF, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"vpsadbw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xF6, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vroundsd", sse4m64imm_insn, 4, SUF_Z, 0x0B, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmaddss", fma_128_m32_insn, 3, SUF_Z, 0x6A, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"fbstp", fbldstp_insn, 1, SUF_Z, 0x06, 0, 0, 0, CPU_FPU, 0, 0},
+ {"rdpmc", twobyte_insn, 1, SUF_Z, 0x0F, 0x33, 0, 0, CPU_686, 0, 0},
+ {"pslld", pshift_insn, 4, SUF_Z, 0xF2, 0x72, 0x06, 0, CPU_MMX, 0, 0},
+ {"vpcomeqd", vpcom_insn, 1, SUF_Z, 0xCE, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"movntdqa", movntdqa_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"subps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x5C, 0, 0, CPU_SSE, 0, 0},
+ {"adcx", vex_gpr_ndd_rm_0F38_insn, 2, SUF_Z, 0x66, 0xF6, 0, 0, CPU_ADX, 0, 0},
+ {"repz", NULL, X86_LOCKREP>>8, 0xF3, 0, 0, 0, 0, 0, 0, 0},
+ {"ja", jcc_insn, 9, SUF_Z, 0x07, 0, 0, 0, 0, 0, 0},
+ {"vpmacsdql", vpma_insn, 1, SUF_Z, 0x97, 0, 0, 0, CPU_XOP, 0, 0},
+ {"psadbw", mmxsse2_insn, 2, SUF_Z, 0xF6, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vfnmaddps", fma_128_256_insn, 4, SUF_Z, 0x78, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"pshufb", ssse3_insn, 5, SUF_Z, 0x00, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"o32", NULL, X86_OPERSIZE>>8, 0x20, 0, 0, 0, 0, 0, 0, 0},
+ {"vpcomeqq", vpcom_insn, 1, SUF_Z, 0xCF, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"blendpd", sse4imm_insn, 2, SUF_Z, 0x0D, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"popfq", onebyte_insn, 1, SUF_Z, 0x9D, 0x40, 0x40, ONLY_64, 0, 0, 0},
+ {"vhsubps", xmm_xmm128_256_insn, 4, SUF_Z, 0xF2, 0x7D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpclmulhqlqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x01, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vandpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x54, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cvtpi2ps", cvt_xmm_mm_ps_insn, 1, SUF_Z, 0x2A, 0, 0, 0, CPU_SSE, 0, 0},
+ {"vpblendvb", avx2_sse4xmm0_insn, 2, SUF_Z, 0x4C, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"movntdq", movnt_insn, 2, SUF_Z, 0x66, 0xE7, 0, 0, CPU_SSE2, 0, 0},
+ {"vpaddw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xFD, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomeqw", vpcom_insn, 1, SUF_Z, 0xCD, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"unpcklpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x14, 0, 0, CPU_SSE2, 0, 0},
+ {"vpcomgtuw", vpcom_insn, 1, SUF_Z, 0xED, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"fadd", farith_insn, 7, SUF_Z, 0xC0, 0xC0, 0x00, 0, CPU_FPU, 0, 0},
+ {"fcmovnbe", fcmovcc_insn, 1, SUF_Z, 0xDB, 0xD0, 0, 0, CPU_686, CPU_FPU, 0},
+ {"vpcomltub", vpcom_insn, 1, SUF_Z, 0xEC, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"cmplepd", ssecmp_128_insn, 3, SUF_Z, 0x02, 0x66, 0, 0, CPU_SSE, 0, 0},
+ {"fyl2xp1", twobyte_insn, 1, SUF_Z, 0xD9, 0xF9, 0, 0, CPU_FPU, 0, 0},
+ {"vpmacssdql", vpma_insn, 1, SUF_Z, 0x87, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vmpsadbw", sse4imm_256avx2_insn, 4, SUF_Z, 0x42, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"punpckhqdq", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x6D, 0, 0, CPU_SSE2, 0, 0},
+ {"pushaw", onebyte_insn, 1, SUF_Z, 0x60, 0x10, 0, NOT_64, CPU_186, 0, 0},
+ {"sar", shift_insn, 16, SUF_Z, 0x07, 0, 0, 0, 0, 0, 0},
+ {"shlx", vex_gpr_reg_rm_nds_0F_insn, 2, SUF_Z, 0x66, 0x38, 0xF7, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"vcmpunord_sps", ssecmp_128_insn, 3, SUF_Z, 0x13, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomfalsew", vpcom_insn, 1, SUF_Z, 0xCD, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"vpbroadcastq", vpbroadcastq_avx2_insn, 4, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"movdqu", movau_insn, 6, SUF_Z, 0xF3, 0x6F, 0x10, 0, CPU_SSE2, 0, 0},
+ {"vcmpord_ssd", ssecmp_64_insn, 4, SUF_Z, 0x17, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpfalsess", ssecmp_32_insn, 4, SUF_Z, 0x0B, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"lddqu", lddqu_insn, 2, SUF_Z, 0, 0, 0, 0, CPU_SSE3, 0, 0},
+ {"sha1msg1", intel_SHA1MSG1_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SHA, 0, 0},
+ {"lock", NULL, X86_LOCKREP>>8, 0xF0, 0, 0, 0, 0, 0, 0, 0},
+ {"lss", lfgss_insn, 3, SUF_Z, 0xB2, 0, 0, 0, CPU_386, 0, 0},
+ {"orps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x56, 0, 0, CPU_SSE, 0, 0},
+ {"vbroadcastsd", vbroadcastsd_insn, 2, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rsdc", rsdc_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_486, CPU_Cyrix, CPU_SMM},
+ {"crc32", crc32_insn, 5, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_SSE42, 0},
+ {"sal", shift_insn, 16, SUF_Z, 0x04, 0, 0, 0, 0, 0, 0},
+ {"movsldup", xmm_xmm128_insn, 2, SUF_Z, 0xF3, 0x12, 0, 0, CPU_SSE3, 0, 0},
+ {"vpcomneub", vpcom_insn, 1, SUF_Z, 0xEC, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"movsb", onebyte_insn, 1, SUF_Z, 0xA4, 0x00, 0, 0, 0, 0, 0},
+ {"jcxz", jcxz_insn, 2, SUF_Z, 0x10, 0, 0, 0, 0, 0, 0},
+ {"vphadduwd", vphaddsub_insn, 1, SUF_Z, 0xD6, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpcomequb", vpcom_insn, 1, SUF_Z, 0xEC, 0x04, 0, 0, CPU_XOP, 0, 0},
+ {"vpcomgeq", vpcom_insn, 1, SUF_Z, 0xCF, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"cmpeqps", ssecmp_128_insn, 3, SUF_Z, 0x00, 0, 0, 0, CPU_SSE, 0, 0},
+ {"psubsiw", cyrixmmx_insn, 1, SUF_Z, 0x55, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"vpcomfalseuq", vpcom_insn, 1, SUF_Z, 0xEF, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpngesd", ssecmp_64_insn, 4, SUF_Z, 0x09, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpsubb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xF8, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpextrb", pextrb_insn, 3, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fdivr", farith_insn, 7, SUF_Z, 0xF0, 0xF8, 0x07, 0, CPU_FPU, 0, 0},
+ {"cmpless", ssecmp_32_insn, 4, SUF_Z, 0x02, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"vcmpeq_ossd", ssecmp_64_insn, 4, SUF_Z, 0x10, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pabsd", ssse3_insn, 5, SUF_Z, 0x1E, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"vprotd", vprot_insn, 3, SUF_Z, 0x02, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpermq", vperm_imm_avx2_insn, 1, SUF_Z, 0x00, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vmovntps", movnt_insn, 2, SUF_Z, 0x00, 0x2B, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtps2dq", avx_xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x5B, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pmovzxwd", sse4m64_insn, 4, SUF_Z, 0x33, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"phaddd", ssse3_insn, 5, SUF_Z, 0x02, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"jnp", jcc_insn, 9, SUF_Z, 0x0B, 0, 0, 0, 0, 0, 0},
+ {"vdivss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5E, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vunpcklps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x14, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"punpcklbw", mmxsse2_insn, 2, SUF_Z, 0x60, 0, 0, 0, CPU_MMX, 0, 0},
+ {"pmovzxbd", sse4m32_insn, 4, SUF_Z, 0x31, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vcmpfalse_ospd", ssecmp_128_insn, 3, SUF_Z, 0x1B, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmaxps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x5F, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomub", vpcom_imm_insn, 1, SUF_Z, 0xEC, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vcmptrue_usss", ssecmp_32_insn, 4, SUF_Z, 0x1F, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vphaddbw", vphaddsub_insn, 1, SUF_Z, 0xC1, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vpmacssdd", vpma_insn, 1, SUF_Z, 0x8E, 0, 0, 0, CPU_XOP, 0, 0},
+ {"sete", setcc_insn, 1, SUF_Z, 0x04, 0, 0, 0, CPU_386, 0, 0},
+ {"fcom", fcom_insn, 6, SUF_Z, 0xD0, 0x02, 0, 0, CPU_FPU, 0, 0},
+ {"paveb", cyrixmmx_insn, 1, SUF_Z, 0x50, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"vphaddd", ssse3_insn, 5, SUF_Z, 0x02, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomltuq", vpcom_insn, 1, SUF_Z, 0xEF, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"aeskeygenassist", aes_imm_insn, 1, SUF_Z, 0x3A, 0xDF, 0, 0, CPU_AES, 0, 0},
+ {"movss", movss_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_SSE, 0, 0},
+ {"vpmacsswd", vpma_insn, 1, SUF_Z, 0x86, 0, 0, 0, CPU_XOP, 0, 0},
+ {"fchs", twobyte_insn, 1, SUF_Z, 0xD9, 0xE0, 0, 0, CPU_FPU, 0, 0},
+ {"vphminposuw", avx_ssse3_2op_insn, 1, SUF_Z, 0x41, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"les", ldes_insn, 2, SUF_Z, 0xC4, 0, 0, NOT_64, 0, 0, 0},
+ {"movhlps", movhllhps_insn, 2, SUF_Z, 0x12, 0, 0, 0, CPU_SSE, 0, 0},
+ {"a16", NULL, X86_ADDRSIZE>>8, 0x10, 0, 0, 0, 0, 0, 0, 0},
+ {"vpaddsw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xED, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"aesdeclast", aes_insn, 2, SUF_Z, 0x38, 0xDF, 0, 0, CPU_AVX, 0, 0},
+ {"lodsq", onebyte_insn, 1, SUF_Z, 0xAD, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"vpinsrd", pinsrd_insn, 2, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpgatherdq", gather_64x_64x_insn, 2, SUF_Z, 0x90, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"pshufw", pshufw_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_MMX, CPU_P3, 0},
+ {"vpgatherqd", gather_32x_32y_128_insn, 2, SUF_Z, 0x91, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vpblendd", vex_66_0F3A_imm8_avx2_insn, 2, SUF_Z, 0x02, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vblendpd", sse4imm_256_insn, 4, SUF_Z, 0x0D, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pushfw", onebyte_insn, 1, SUF_Z, 0x9C, 0x10, 0x40, 0, 0, 0, 0},
+ {"lodsd", onebyte_insn, 1, SUF_Z, 0xAD, 0x20, 0, 0, CPU_386, 0, 0},
+ {"vfmaddsub213pd", vfma_pd_insn, 2, SUF_Z, 0xA6, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vpcomfalsed", vpcom_insn, 1, SUF_Z, 0xCE, 0x06, 0, 0, CPU_XOP, 0, 0},
+ {"fnstcw", fldnstcw_insn, 1, SUF_Z, 0x07, 0, 0, 0, CPU_FPU, 0, 0},
+ {"rdshr", rdwrshr_insn, 1, SUF_Z, 0x00, 0, 0, 0, CPU_686, CPU_Cyrix, CPU_SMM},
+ {"phminposuw", sse4_insn, 2, SUF_Z, 0x41, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"pclmullqlqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x00, 0, 0, 0, CPU_AVX, 0, 0},
+ {"bound", bound_insn, 2, SUF_Z, 0, 0, 0, NOT_64, CPU_186, 0, 0},
+ {"tzcnt", cnt_insn, 3, SUF_Z, 0xBC, 0, 0, 0, CPU_BMI1, 0, 0},
+ {"rdrand", rdrand_insn, 3, SUF_Z, 0x06, 0, 0, 0, CPU_RDRAND, 0, 0},
+ {"vpcomtrueuq", vpcom_insn, 1, SUF_Z, 0xEF, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"pfrcp", now3d_insn, 1, SUF_Z, 0x96, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"vcmpneq_oqsd", ssecmp_64_insn, 4, SUF_Z, 0x0C, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvttps2dq", avx_xmm_xmm128_insn, 2, SUF_Z, 0xF3, 0x5B, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpinsrb", pinsrb_insn, 4, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movlhps", movhllhps_insn, 2, SUF_Z, 0x16, 0, 0, 0, CPU_SSE, 0, 0},
+ {"vpmovsxwq", sse4m32_insn, 4, SUF_Z, 0x24, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pdistib", cyrixmmx_insn, 1, SUF_Z, 0x54, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"vpxor", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xEF, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fabs", twobyte_insn, 1, SUF_Z, 0xD9, 0xE1, 0, 0, CPU_FPU, 0, 0},
+ {"blci", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x02, 0x06, 0, 0, CPU_386, CPU_TBM, 0},
+ {"vmovlpd", movhlp_insn, 3, SUF_Z, 0x66, 0x12, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vbroadcastss", vbroadcastss_insn, 4, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpngt_uqss", ssecmp_32_insn, 4, SUF_Z, 0x1A, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"roundps", sse4imm_insn, 2, SUF_Z, 0x08, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"sha256msg1", intel_SHA256MSG1_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SHA, 0, 0},
+ {"movsxd", movsxd_insn, 1, SUF_Z, 0, 0, 0, ONLY_64, 0, 0, 0},
+ {"fsubrp", farithp_insn, 3, SUF_Z, 0xE0, 0, 0, 0, CPU_FPU, 0, 0},
+ {"vmaskmovps", vmaskmov_insn, 4, SUF_Z, 0x2C, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"movsx", movszx_insn, 5, SUF_Z, 0xBE, 0, 0, 0, CPU_386, 0, 0},
+ {"fistp", fildstp_insn, 4, SUF_Z, 0x03, 0x02, 0x07, 0, CPU_FPU, 0, 0},
+ {"vfmsubps", fma_128_256_insn, 4, SUF_Z, 0x6C, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"movmskps", movmsk_insn, 4, SUF_Z, 0, 0, 0, 0, CPU_386, CPU_SSE, 0},
+ {"cmplesd", ssecmp_64_insn, 4, SUF_Z, 0x02, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"maskmovdqu", maskmovdqu_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"prefetchnta", twobytemem_insn, 1, SUF_Z, 0x00, 0x0F, 0x18, 0, CPU_P3, 0, 0},
+ {"loadall", twobyte_insn, 1, SUF_Z, 0x0F, 0x07, 0, 0, CPU_386, CPU_Undoc, 0},
+ {"cmpunordsd", ssecmp_64_insn, 4, SUF_Z, 0x03, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"haddpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x7C, 0, 0, CPU_SSE3, 0, 0},
+ {"vpshlw", amd_vpshift_insn, 2, SUF_Z, 0x95, 0, 0, 0, CPU_XOP, 0, 0},
+ {"addsubpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0xD0, 0, 0, CPU_SSE3, 0, 0},
+ {"phaddw", ssse3_insn, 5, SUF_Z, 0x01, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"vphaddsw", ssse3_insn, 5, SUF_Z, 0x03, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpeq_uqsd", ssecmp_64_insn, 4, SUF_Z, 0x08, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpunordss", ssecmp_32_insn, 4, SUF_Z, 0x03, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"cmpsb", onebyte_insn, 1, SUF_Z, 0xA6, 0x00, 0, 0, 0, 0, 0},
+ {"vpcomtrueuw", vpcom_insn, 1, SUF_Z, 0xED, 0x07, 0, 0, CPU_XOP, 0, 0},
+ {"rcpps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x53, 0, 0, CPU_SSE, 0, 0},
+ {"packuswb", mmxsse2_insn, 2, SUF_Z, 0x67, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vmovlhps", movhllhps_insn, 2, SUF_Z, 0x16, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmppd", xmm_xmm128_imm_insn, 1, SUF_Z, 0x66, 0xC2, 0, 0, CPU_SSE2, 0, 0},
+ {"vfmsubadd231pd", vfma_pd_insn, 2, SUF_Z, 0xB7, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vphaddudq", vphaddsub_insn, 1, SUF_Z, 0xDB, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vphaddubq", vphaddsub_insn, 1, SUF_Z, 0xD3, 0, 0, 0, CPU_XOP, 0, 0},
+ {"scasb", onebyte_insn, 1, SUF_Z, 0xAE, 0x00, 0, 0, 0, 0, 0},
+ {"vfmaddsubps", fma_128_256_insn, 4, SUF_Z, 0x5C, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"vpcomgtd", vpcom_insn, 1, SUF_Z, 0xCE, 0x02, 0, 0, CPU_XOP, 0, 0},
+ {"seta", setcc_insn, 1, SUF_Z, 0x07, 0, 0, 0, CPU_386, 0, 0},
+ {"pmulhrwc", cyrixmmx_insn, 1, SUF_Z, 0x59, 0, 0, 0, CPU_Cyrix, CPU_MMX, 0},
+ {"vtestpd", sse4_insn, 2, SUF_Z, 0x0F, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmaddsub132pd", vfma_pd_insn, 2, SUF_Z, 0x96, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"cmpneqps", ssecmp_128_insn, 3, SUF_Z, 0x04, 0, 0, 0, CPU_SSE, 0, 0},
+ {"vpmaskmovd", vmaskmov_insn, 4, SUF_Z, 0x8C, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vcmpordps", ssecmp_128_insn, 3, SUF_Z, 0x07, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcvtsi2ss", cvt_xmm_rmx_insn, 6, SUF_Z, 0xF3, 0x2A, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vunpckhpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x15, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setc", setcc_insn, 1, SUF_Z, 0x02, 0, 0, 0, CPU_386, 0, 0},
+ {"repne", NULL, X86_LOCKREP>>8, 0xF2, 0, 0, 0, 0, 0, 0, 0},
+ {"vandnps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x55, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"aam", aadm_insn, 2, SUF_Z, 0x00, 0, 0, NOT_64, 0, 0, 0},
+ {"mulpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x59, 0, 0, CPU_SSE2, 0, 0},
+ {"a32", NULL, X86_ADDRSIZE>>8, 0x20, 0, 0, 0, 0, 0, 0, 0},
+ {"vcmpfalse_osps", ssecmp_128_insn, 3, SUF_Z, 0x1B, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"jecxz", jcxz_insn, 2, SUF_Z, 0x20, 0, 0, 0, CPU_386, 0, 0},
+ {"vcmple_oqps", ssecmp_128_insn, 3, SUF_Z, 0x12, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmovpe", cmovcc_insn, 3, SUF_Z, 0x0A, 0, 0, 0, CPU_686, 0, 0},
+ {"vcmpngepd", ssecmp_128_insn, 3, SUF_Z, 0x09, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vsqrtpd", avx_xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x51, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpmacsww", vpma_insn, 1, SUF_Z, 0x95, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vfmaddsub231pd", vfma_pd_insn, 2, SUF_Z, 0xB6, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"int3", onebyte_insn, 1, SUF_Z, 0xCC, 0, 0, 0, 0, 0, 0},
+ {"vcvtdq2pd", avx_cvt_xmm64_insn, 3, SUF_Z, 0xF3, 0xE6, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fisubr", fiarith_insn, 2, SUF_Z, 0x05, 0xDA, 0, 0, CPU_FPU, 0, 0},
+ {"pextrq", pextrq_insn, 1, SUF_Z, 0, 0, 0, ONLY_64, CPU_SSE41, 0, 0},
+ {"popaw", onebyte_insn, 1, SUF_Z, 0x61, 0x10, 0, NOT_64, CPU_186, 0, 0},
+ {"vcmpnge_uqsd", ssecmp_64_insn, 4, SUF_Z, 0x19, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmsub132ps", vfma_ps_insn, 2, SUF_Z, 0x9A, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vcmplesd", ssecmp_64_insn, 4, SUF_Z, 0x02, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"into", onebyte_insn, 1, SUF_Z, 0xCE, 0, 0, NOT_64, 0, 0, 0},
+ {"vpmacsdd", vpma_insn, 1, SUF_Z, 0x9E, 0, 0, 0, CPU_XOP, 0, 0},
+ {"cmovbe", cmovcc_insn, 3, SUF_Z, 0x06, 0, 0, 0, CPU_686, 0, 0},
+ {"vpsubsb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xE8, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpmulld", ssse3_insn, 5, SUF_Z, 0x40, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vphsubw", ssse3_insn, 5, SUF_Z, 0x05, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpsrlvq", vpshiftv_vexw1_avx2_insn, 2, SUF_Z, 0x45, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vpsllvd", vpshiftv_vexw0_avx2_insn, 2, SUF_Z, 0x47, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"std", onebyte_insn, 1, SUF_Z, 0xFD, 0, 0, 0, 0, 0, 0},
+ {"psrad", pshift_insn, 4, SUF_Z, 0xE2, 0x72, 0x04, 0, CPU_MMX, 0, 0},
+ {"psllq", pshift_insn, 4, SUF_Z, 0xF3, 0x73, 0x06, 0, CPU_MMX, 0, 0},
+ {"fucom", fcom2_insn, 2, SUF_Z, 0xDD, 0xE0, 0, 0, CPU_286, CPU_FPU, 0},
+ {"vpcmpeqd", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x76, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpord_sps", ssecmp_128_insn, 3, SUF_Z, 0x17, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmovntdqa", movntdqa_insn, 2, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpgatherdd", gather_32x_32y_insn, 2, SUF_Z, 0x90, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"vfmsubpd", fma_128_256_insn, 4, SUF_Z, 0x6D, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"vaesdec", aes_insn, 2, SUF_Z, 0x38, 0xDE, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcomged", vpcom_insn, 1, SUF_Z, 0xCE, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"rol", shift_insn, 16, SUF_Z, 0x00, 0, 0, 0, 0, 0, 0},
+ {"punpckhbw", mmxsse2_insn, 2, SUF_Z, 0x68, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vphsubsw", ssse3_insn, 5, SUF_Z, 0x07, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpltsd", ssecmp_64_insn, 4, SUF_Z, 0x01, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"fcomip", fcom2_insn, 2, SUF_Z, 0xDF, 0xF0, 0, 0, CPU_686, CPU_FPU, 0},
+ {"vfmadd231sd", vfma_sd_insn, 2, SUF_Z, 0xB9, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"psubusw", mmxsse2_insn, 2, SUF_Z, 0xD9, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vcmpunord_spd", ssecmp_128_insn, 3, SUF_Z, 0x13, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpneq_usss", ssecmp_32_insn, 4, SUF_Z, 0x14, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpclmullqhqdq", pclmulqdq_fixed_insn, 2, SUF_Z, 0x10, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpeq_uspd", ssecmp_128_insn, 3, SUF_Z, 0x18, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"inc", incdec_insn, 6, SUF_Z, 0x40, 0x00, 0, 0, 0, 0, 0},
+ {"psubq", mmxsse2_insn, 2, SUF_Z, 0xFB, 0, 0, 0, CPU_MMX, 0, 0},
+ {"unpcklps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x14, 0, 0, CPU_SSE, 0, 0},
+ {"vcmpgt_oqss", ssecmp_32_insn, 4, SUF_Z, 0x1E, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpunordps", ssecmp_128_insn, 3, SUF_Z, 0x03, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmadd213sd", vfma_sd_insn, 2, SUF_Z, 0xAD, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"pdep", vex_gpr_reg_nds_rm_0F_insn, 2, SUF_Z, 0xF2, 0x38, 0xF5, ONLY_AVX, CPU_BMI2, 0, 0},
+ {"phaddsw", ssse3_insn, 5, SUF_Z, 0x03, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"xcryptcbc", padlock_insn, 1, SUF_Z, 0xD0, 0xF3, 0xA7, 0, CPU_PadLock, 0, 0},
+ {"vpmullw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xD5, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"blsfill", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x01, 0x02, 0, 0, CPU_386, CPU_TBM, 0},
+ {"and", arith_insn, 22, SUF_Z, 0x20, 0x04, 0, 0, 0, 0, 0},
+ {"xacquire", NULL, X86_ACQREL>>8, 0xF2, 0, 0, 0, 0, 0, 0, 0},
+ {"vpcomnequd", vpcom_insn, 1, SUF_Z, 0xEE, 0x05, 0, 0, CPU_XOP, 0, 0},
+ {"movshdup", xmm_xmm128_insn, 2, SUF_Z, 0xF3, 0x16, 0, 0, CPU_SSE3, 0, 0},
+ {"vfnmadd231sd", vfma_sd_insn, 2, SUF_Z, 0xBD, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"femms", twobyte_insn, 1, SUF_Z, 0x0F, 0x0E, 0, 0, CPU_3DNow, 0, 0},
+ {"vpcomgeuq", vpcom_insn, 1, SUF_Z, 0xEF, 0x03, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpnlt_uqsd", ssecmp_64_insn, 4, SUF_Z, 0x15, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pcmpgtd", mmxsse2_insn, 2, SUF_Z, 0x66, 0, 0, 0, CPU_MMX, 0, 0},
+ {"andpd", xmm_xmm128_insn, 2, SUF_Z, 0x66, 0x54, 0, 0, CPU_SSE2, 0, 0},
+ {"vhsubpd", xmm_xmm128_256_insn, 4, SUF_Z, 0x66, 0x7D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vblendvps", avx_sse4xmm0_insn, 2, SUF_Z, 0x4A, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpgtsd", ssecmp_64_insn, 4, SUF_Z, 0x0E, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpcmpestri", sse4pcmpstr_insn, 1, SUF_Z, 0x61, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rdmsr", twobyte_insn, 1, SUF_Z, 0x0F, 0x32, 0, 0, CPU_586, CPU_Priv, 0},
+ {"vpcmpgtw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x65, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pfnacc", now3d_insn, 1, SUF_Z, 0x8A, 0, 0, 0, CPU_3DNow, CPU_Athlon, 0},
+ {"leave", onebyte_insn, 1, SUF_Z, 0xC9, 0x00, 0x40, 0, CPU_186, 0, 0},
+ {"jz", jcc_insn, 9, SUF_Z, 0x04, 0, 0, 0, 0, 0, 0},
+ {"psubw", mmxsse2_insn, 2, SUF_Z, 0xF9, 0, 0, 0, CPU_MMX, 0, 0},
+ {"jnl", jcc_insn, 9, SUF_Z, 0x0D, 0, 0, 0, 0, 0, 0},
+ {"repe", NULL, X86_LOCKREP>>8, 0xF3, 0, 0, 0, 0, 0, 0, 0},
+ {"pushfq", onebyte_insn, 1, SUF_Z, 0x9C, 0x40, 0x40, ONLY_64, 0, 0, 0},
+ {"vmlaunch", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xC2, 0, CPU_P4, 0, 0},
+ {"vfmsubaddps", fma_128_256_insn, 4, SUF_Z, 0x5E, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"cmpxchg486", cmpxchgxadd_insn, 4, SUF_Z, 0xA6, 0, 0, 0, CPU_486, CPU_Undoc, 0},
+ {"blsic", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x01, 0x06, 0, 0, CPU_386, CPU_TBM, 0},
+ {"vcmptruesd", ssecmp_64_insn, 4, SUF_Z, 0x0F, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"stc", onebyte_insn, 1, SUF_Z, 0xF9, 0, 0, 0, 0, 0, 0},
+ {"vpermps", vperm_var_avx2_insn, 1, SUF_Z, 0x16, 0, 0, ONLY_AVX, CPU_AVX2, 0, 0},
+ {"xlatb", onebyte_insn, 1, SUF_Z, 0xD7, 0x00, 0, 0, 0, 0, 0},
+ {"vpmacssww", vpma_insn, 1, SUF_Z, 0x85, 0, 0, 0, CPU_XOP, 0, 0},
+ {"pavgusb", now3d_insn, 1, SUF_Z, 0xBF, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"vfmsub231sd", vfma_sd_insn, 2, SUF_Z, 0xBB, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vmovd", vmovd_insn, 2, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_386, CPU_AVX, 0},
+ {"cvtps2pd", xmm_xmm64_insn, 4, SUF_Z, 0x00, 0x5A, 0, 0, CPU_SSE2, 0, 0},
+ {"verw", prot286_insn, 1, SUF_Z, 0x05, 0x00, 0, 0, CPU_286, CPU_Prot, 0},
+ {"pushad", onebyte_insn, 1, SUF_Z, 0x60, 0x20, 0, NOT_64, CPU_386, 0, 0},
+ {"wrfsbase", fs_gs_base_insn, 2, SUF_Z, 0x02, 0, 0, ONLY_64, CPU_FSGSBASE, 0, 0},
+ {"paddusw", mmxsse2_insn, 2, SUF_Z, 0xDD, 0, 0, 0, CPU_MMX, 0, 0},
+ {"vucomisd", avx_xmm_xmm64_insn, 2, SUF_Z, 0x66, 0x2E, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fldenv", onebytemem_insn, 1, SUF_Z, 0x04, 0xD9, 0, 0, CPU_FPU, 0, 0},
+ {"psubb", mmxsse2_insn, 2, SUF_Z, 0xF8, 0, 0, 0, CPU_MMX, 0, 0},
+ {"lidt", twobytemem_insn, 1, SUF_Z, 0x03, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"vfmadd213ps", vfma_ps_insn, 2, SUF_Z, 0xA8, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"cmovnbe", cmovcc_insn, 3, SUF_Z, 0x07, 0, 0, 0, CPU_686, 0, 0},
+ {"shufps", xmm_xmm128_imm_insn, 1, SUF_Z, 0x00, 0xC6, 0, 0, CPU_SSE, 0, 0},
+ {"emms", twobyte_insn, 1, SUF_Z, 0x0F, 0x77, 0, 0, CPU_MMX, 0, 0},
+ {"vfmsubadd132pd", vfma_pd_insn, 2, SUF_Z, 0x97, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"fldl2e", twobyte_insn, 1, SUF_Z, 0xD9, 0xEA, 0, 0, CPU_FPU, 0, 0},
+ {"invd", twobyte_insn, 1, SUF_Z, 0x0F, 0x08, 0, 0, CPU_486, CPU_Priv, 0},
+ {"vphadduwq", vphaddsub_insn, 1, SUF_Z, 0xD7, 0, 0, 0, CPU_XOP, 0, 0},
+ {"cvtss2si", cvt_rx_xmm32_insn, 4, SUF_Z, 0xF3, 0x2D, 0, 0, CPU_386, CPU_SSE, 0},
+ {"vpcomltd", vpcom_insn, 1, SUF_Z, 0xCE, 0x00, 0, 0, CPU_XOP, 0, 0},
+ {"shr", shift_insn, 16, SUF_Z, 0x05, 0, 0, 0, 0, 0, 0},
+ {"vcvtss2si", cvt_rx_xmm32_insn, 4, SUF_Z, 0xF3, 0x2D, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpeq_uqps", ssecmp_128_insn, 3, SUF_Z, 0x08, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vsubsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x5C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pminuw", sse4_insn, 2, SUF_Z, 0x3A, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vcmpgt_oqps", ssecmp_128_insn, 3, SUF_Z, 0x1E, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"xstore", padlock_insn, 1, SUF_Z, 0xC0, 0x00, 0xA7, 0, CPU_PadLock, 0, 0},
+ {"pmovsxwq", sse4m32_insn, 4, SUF_Z, 0x24, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vcmpngtss", ssecmp_32_insn, 4, SUF_Z, 0x0A, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfnmadd213pd", vfma_pd_insn, 2, SUF_Z, 0xAC, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"vphaddbd", vphaddsub_insn, 1, SUF_Z, 0xC2, 0, 0, 0, CPU_XOP, 0, 0},
+ {"divps", xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x5E, 0, 0, CPU_SSE, 0, 0},
+ {"pf2id", now3d_insn, 1, SUF_Z, 0x1D, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"lgdt", twobytemem_insn, 1, SUF_Z, 0x02, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"syscall", twobyte_insn, 1, SUF_Z, 0x0F, 0x05, 0, 0, CPU_686, CPU_AMD, 0},
+ {"vpmaddwd", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xF5, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpneqss", ssecmp_32_insn, 4, SUF_Z, 0x04, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"setle", setcc_insn, 1, SUF_Z, 0x0E, 0, 0, 0, CPU_386, 0, 0},
+ {"stosb", onebyte_insn, 1, SUF_Z, 0xAA, 0x00, 0, 0, 0, 0, 0},
+ {"sha1rnds4", intel_SHA1RNDS4_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SHA, 0, 0},
+ {"setg", setcc_insn, 1, SUF_Z, 0x0F, 0, 0, 0, CPU_386, 0, 0},
+ {"ffree", ffree_insn, 1, SUF_Z, 0xDD, 0, 0, 0, CPU_FPU, 0, 0},
+ {"fmulp", farithp_insn, 3, SUF_Z, 0xC8, 0, 0, 0, CPU_FPU, 0, 0},
+ {"fucomp", fcom2_insn, 2, SUF_Z, 0xDD, 0xE8, 0, 0, CPU_286, CPU_FPU, 0},
+ {"cvtss2sd", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x5A, 0, 0, CPU_SSE2, 0, 0},
+ {"phsubd", ssse3_insn, 5, SUF_Z, 0x06, 0, 0, 0, CPU_SSSE3, 0, 0},
+ {"vdivps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x5E, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"rdseed", rdrand_insn, 3, SUF_Z, 0x07, 0, 0, 0, CPU_RDSEED, 0, 0},
+ {"vpsrlw", vpshift_insn, 8, SUF_Z, 0xD1, 0x71, 0x02, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpeqsd", ssecmp_64_insn, 4, SUF_Z, 0x00, 0xF2, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpngtps", ssecmp_128_insn, 3, SUF_Z, 0x0A, 0x00, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cvtpd2dq", xmm_xmm128_insn, 2, SUF_Z, 0xF2, 0xE6, 0, 0, CPU_SSE2, 0, 0},
+ {"vfnmaddpd", fma_128_256_insn, 4, SUF_Z, 0x79, 0, 0, ONLY_AVX, CPU_FMA4, 0, 0},
+ {"vmptrst", vmxtwobytemem_insn, 1, SUF_Z, 0x07, 0, 0, 0, CPU_P4, 0, 0},
+ {"rdgsbase", fs_gs_base_insn, 2, SUF_Z, 0x01, 0, 0, ONLY_64, CPU_FSGSBASE, 0, 0},
+ {"vpcomleb", vpcom_insn, 1, SUF_Z, 0xCC, 0x01, 0, 0, CPU_XOP, 0, 0},
+ {"pmovzxbw", sse4m64_insn, 4, SUF_Z, 0x30, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vrsqrtss", xmm_xmm32_insn, 4, SUF_Z, 0xF3, 0x52, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setpe", setcc_insn, 1, SUF_Z, 0x0A, 0, 0, 0, CPU_386, 0, 0},
+ {"ffreep", ffree_insn, 1, SUF_Z, 0xDF, 0, 0, 0, CPU_686, CPU_FPU, CPU_Undoc},
+ {"sgdt", twobytemem_insn, 1, SUF_Z, 0x00, 0x0F, 0x01, 0, CPU_286, CPU_Priv, 0},
+ {"addsd", xmm_xmm64_insn, 4, SUF_Z, 0xF2, 0x58, 0, 0, CPU_SSE2, 0, 0},
+ {"sfence", threebyte_insn, 1, SUF_Z, 0x0F, 0xAE, 0xF8, 0, CPU_P3, 0, 0},
+ {"mpsadbw", sse4imm_insn, 2, SUF_Z, 0x42, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vpunpckhbw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x68, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vcmpnlepd", ssecmp_128_insn, 3, SUF_Z, 0x06, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vandps", xmm_xmm128_256_insn, 4, SUF_Z, 0x00, 0x54, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"cmpneqsd", ssecmp_64_insn, 4, SUF_Z, 0x04, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"fsqrt", twobyte_insn, 1, SUF_Z, 0xD9, 0xFA, 0, 0, CPU_FPU, 0, 0},
+ {"vpinsrq", pinsrq_insn, 2, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vmovddup", vmovddup_insn, 3, SUF_Z, 0xF2, 0x12, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpmacswd", vpma_insn, 1, SUF_Z, 0x96, 0, 0, 0, CPU_XOP, 0, 0},
+ {"vcmpeq_osss", ssecmp_32_insn, 4, SUF_Z, 0x10, 0xF3, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"setp", setcc_insn, 1, SUF_Z, 0x0A, 0, 0, 0, CPU_386, 0, 0},
+ {"cmpsq", onebyte_insn, 1, SUF_Z, 0xA7, 0x40, 0, ONLY_64, 0, 0, 0},
+ {"vmovdqu", movau_insn, 6, SUF_Z, 0xF3, 0x6F, 0x10, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pfrcpit2", now3d_insn, 1, SUF_Z, 0xB6, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"jpe", jcc_insn, 9, SUF_Z, 0x0A, 0, 0, 0, 0, 0, 0},
+ {"vpunpckhdq", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0x6A, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"bextr", bextr_insn, 4, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_386, CPU_BMI1, 0},
+ {"vmovsldup", avx_xmm_xmm128_insn, 2, SUF_Z, 0xF3, 0x12, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpaddusb", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xDC, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vperm2f128", vperm2f128_insn, 1, SUF_Z, 0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"pcmpgtq", sse4_insn, 2, SUF_Z, 0x37, 0, 0, 0, CPU_SSE41, 0, 0},
+ {"vpshld", amd_vpshift_insn, 2, SUF_Z, 0x96, 0, 0, 0, CPU_XOP, 0, 0},
+ {"fsub", farith_insn, 7, SUF_Z, 0xE8, 0xE0, 0x04, 0, CPU_FPU, 0, 0},
+ {"movdq2q", movdq2q_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SSE2, 0, 0},
+ {"vpsrld", vpshift_insn, 8, SUF_Z, 0xD2, 0x72, 0x02, ONLY_AVX, CPU_AVX, 0, 0},
+ {"fwait", onebyte_insn, 1, SUF_Z, 0x9B, 0, 0, 0, CPU_FPU, 0, 0},
+ {"cmpnltss", ssecmp_32_insn, 4, SUF_Z, 0x05, 0xF3, 0, 0, CPU_SSE, 0, 0},
+ {"blcmsk", xop_gpr_reg_rm_09_insn, 2, SUF_Z, 0x02, 0x01, 0, 0, CPU_386, CPU_TBM, 0},
+ {"punpcklwd", mmxsse2_insn, 2, SUF_Z, 0x61, 0, 0, 0, CPU_MMX, 0, 0},
+ {"cmpunordps", ssecmp_128_insn, 3, SUF_Z, 0x03, 0, 0, 0, CPU_SSE, 0, 0},
+ {"cmpnlesd", ssecmp_64_insn, 4, SUF_Z, 0x06, 0xF2, 0, 0, CPU_SSE2, 0, 0},
+ {"pfcmpgt", now3d_insn, 1, SUF_Z, 0xA0, 0, 0, 0, CPU_3DNow, 0, 0},
+ {"cmovnle", cmovcc_insn, 3, SUF_Z, 0x0F, 0, 0, 0, CPU_686, 0, 0},
+ {"vmclear", vmxthreebytemem_insn, 1, SUF_Z, 0x66, 0, 0, 0, CPU_P4, 0, 0},
+ {"vcmplt_oqpd", ssecmp_128_insn, 3, SUF_Z, 0x11, 0x66, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"clac", threebyte_insn, 1, SUF_Z, 0x0F, 0x01, 0xCA, 0, CPU_SMAP, 0, 0},
+ {"fscale", twobyte_insn, 1, SUF_Z, 0xD9, 0xFD, 0, 0, CPU_FPU, 0, 0},
+ {"vrcpps", avx_xmm_xmm128_insn, 2, SUF_Z, 0x00, 0x53, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"outsd", onebyte_insn, 1, SUF_Z, 0x6F, 0x20, 0, 0, CPU_386, 0, 0},
+ {"fist", fiarith_insn, 2, SUF_Z, 0x02, 0xDB, 0, 0, CPU_FPU, 0, 0},
+ {"vfnmsub213ss", vfma_ss_insn, 2, SUF_Z, 0xAF, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"bts", bittest_insn, 6, SUF_Z, 0xAB, 0x05, 0, 0, CPU_386, 0, 0},
+ {"paddsb", mmxsse2_insn, 2, SUF_Z, 0xEC, 0, 0, 0, CPU_MMX, 0, 0},
+ {"cmovp", cmovcc_insn, 3, SUF_Z, 0x0A, 0, 0, 0, CPU_686, 0, 0},
+ {"fstenv", twobytemem_insn, 1, SUF_Z, 0x06, 0x9B, 0xD9, 0, CPU_FPU, 0, 0},
+ {"rdfsbase", fs_gs_base_insn, 2, SUF_Z, 0x00, 0, 0, ONLY_64, CPU_FSGSBASE, 0, 0},
+ {"vcvttss2si", cvt_rx_xmm32_insn, 4, SUF_Z, 0xF3, 0x2C, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vptest", sse4_insn, 2, SUF_Z, 0x17, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vfmadd132pd", vfma_pd_insn, 2, SUF_Z, 0x98, 0, 0, ONLY_AVX, CPU_FMA, 0, 0},
+ {"prefetch", twobytemem_insn, 1, SUF_Z, 0x00, 0x0F, 0x0D, 0, CPU_3DNow, 0, 0},
+ {"sha256msg2", intel_SHA256MSG2_insn, 1, SUF_Z, 0, 0, 0, 0, CPU_SHA, 0, 0},
+ {"vpsubsw", xmm_xmm128_256avx2_insn, 4, SUF_Z, 0x66, 0xE9, 0xC0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpmulhrsw", ssse3_insn, 5, SUF_Z, 0x0B, 0xC0, 0, ONLY_AVX, CPU_AVX, 0, 0},
+ {"vpextrd", pextrd_insn, 1, SUF_Z, 0xC0, 0, 0, ONLY_AVX, CPU_AVX, 0, 0}
+ };
+ static const unsigned short tab[] = {
+ 894,83,1140,0,1213,1379,1140,864,11,0,281,793,281,281,864,0,
+ 0,517,0,1312,1213,0,1213,323,0,11,11,1212,0,0,764,0,
+ 351,793,1140,762,323,823,323,1044,1213,323,665,764,665,665,0,1044,
+ 159,764,197,1044,0,1312,1042,605,281,721,1379,333,348,1432,764,665,
+ 0,629,83,764,0,508,1140,0,1140,0,0,605,764,1042,0,1059,
+ 1042,11,83,517,1044,1140,1042,665,1213,629,351,630,665,348,83,924,
+ 1042,11,0,517,83,395,1140,1379,988,1213,1213,281,323,629,1140,1116,
+ 1477,574,1312,864,323,1000,323,823,793,281,721,1074,1044,864,1044,1044,
+ 896,1213,517,11,281,0,764,1042,1312,281,1379,702,605,1203,1212,824,
+ 1481,0,1232,0,1000,323,1105,0,307,764,0,508,281,764,988,0,
+ 884,665,0,0,824,1312,1140,517,517,288,281,823,1140,702,823,517,
+ 341,528,1042,1338,0,1044,1529,1232,988,1203,517,323,0,0,47,764,
+ 399,1213,1140,333,1338,64,1213,11,864,293,1312,1109,0,988,1116,427,
+ 323,1140,1432,764,11,764,323,0,1042,630,427,0,580,630,336,1312,
+ 179,517,1042,1383,0,506,0,988,83,988,1140,336,11,11,1140,11,
+ 1042,864,1218,630,517,83,333,1044,1312,197,0,0,864,793,702,323,
+ 0,1140,574,764,83,924,111,764,1312,159,94,1481,1044,265,281,665,
+ 0,1140,665,1383,62,323,528,764,574,986,764,665,935,630,1042,281,
+ 988,517,1044,83,630,567,988,399,1140,1232,1042,580,764,1042,0,864,
+ 1189,605,443,348,11,864,83,307,894,605,1204,1140,0,764,829,1140,
+ 892,665,988,1116,517,1042,517,0,348,1213,1109,605,605,1312,1140,197,
+ 1044,0,891,83,982,83,6,1185,1127,83,399,83,1042,1312,1044,1042,
+ 0,281,197,1509,924,517,630,935,811,665,896,517,179,1203,605,829,
+ 864,83,1295,83,0,1312,11,328,1140,891,1432,0,0,764,793,1218,
+ 1217,665,1089,519,1312,570,629,1312,764,1165,307,281,257,889,1042,721,
+ 764,1109,443,281,0,0,884,440,688,0,864,1140,1116,83,1140,874,
+ 1042,1213,0,1053,1477,427,336,0,605,665,1312,803,0,764,442,517,
+ 605,1212,1508,702,333,665,764,0,0,630,0,1140,968,525,1212,0,
+ 0,1379,72,0,764,0,1027,327,83,788,145,1476,1107,0,721,358,
+ 894,823,1206,307,1523,281,630,988,94,793,764,1415,721,1074,0,0,
+ 629,1218,919,665,336,1474,799,733,1044,876,215,1212,1169,665,864,864,
+ 764,605,342,1438,569,0,11,0,522,1212,1020,33,427,1064,265,835,
+ };
+
+ const struct insnprefix_parse_data *ret;
+ unsigned long rsl, val = phash_lookup(key, len, 0xbe1e08bbUL);
+ rsl = ((val>>23)^tab[val&0x1ff]);
+ if (rsl >= 1454) return NULL;
+ ret = &pd[rsl];
+ if (strcmp(key, ret->name) != 0) return NULL;
+ return ret;
+}
+
+
diff --git a/contrib/tools/yasm/modules/x86insns.c b/contrib/tools/yasm/modules/x86insns.c
new file mode 100644
index 0000000000..df5b6fae36
--- /dev/null
+++ b/contrib/tools/yasm/modules/x86insns.c
@@ -0,0 +1,2424 @@
+/* Generated by gen_x86_insn.py rHEAD, do not edit */
+static const x86_info_operand insn_operands[] = {
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_Mem, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEXImmSrc, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDRM, OPS_256, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_VEXImmSrc, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDRM, OPS_256, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_Mem, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEXImmSrc, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_Mem, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEXImmSrc, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEXImmSrc, OPAP_None},
+ {OPT_Mem, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_Mem, OPS_8, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_Mem, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEXImmSrc, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_VEXImmSrc, OPAP_None},
+ {OPT_SIMDRM, OPS_256, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_Mem, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEXImmSrc, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEXImmSrc, OPAP_None},
+ {OPT_Mem, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_Mem, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 0, 0, OPTM_None, OPA_SImm, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 0, 0, OPTM_None, OPA_SImm, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 0, 0, OPTM_None, OPA_SImm, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_16, 1, 0, OPTM_None, OPA_SImm, OPAP_SImm8},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_SImm, OPAP_SImm8},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_SImm, OPAP_SImm8},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_Mem, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDRM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_Mem, OPS_8, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_Mem, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Mem, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDRM, OPS_256, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Mem, OPS_8, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_SIMDRM, OPS_256, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDRM, OPS_256, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Mem, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Mem, OPS_128, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_MemXMMIndex, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_MemXMMIndex, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_XMM0, OPS_128, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_MemXMMIndex, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_MemYMMIndex, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_MemYMMIndex, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_RM, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_RM, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Creg, OPS_8, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Creg, OPS_8, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Creg, OPS_8, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_MemYMMIndex, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_RM, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_VEX, OPAP_None},
+ {OPT_RM, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_RM, OPS_16, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_RM, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_RM, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_SpareEA, OPAP_None},
+ {OPT_Imm, OPS_8, 0, 0, OPTM_None, OPA_SImm, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_SpareEA, OPAP_None},
+ {OPT_Imm, OPS_8, 0, 0, OPTM_None, OPA_SImm, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_SpareEA, OPAP_None},
+ {OPT_Imm, OPS_8, 0, 0, OPTM_None, OPA_SImm, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_SpareEA, OPAP_None},
+ {OPT_Imm, OPS_16, 1, 0, OPTM_None, OPA_SImm, OPAP_SImm8},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_SpareEA, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_SImm, OPAP_SImm8},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_SpareEA, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_SImm, OPAP_SImm8},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_RM, OPS_8, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_8, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_8, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_8, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_ST0, OPS_80, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Reg, OPS_80, 0, 0, OPTM_None, OPA_Op1Add, OPAP_None},
+ {OPT_Reg, OPS_80, 0, 0, OPTM_None, OPA_Op1Add, OPAP_None},
+ {OPT_ST0, OPS_80, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_SIMDRM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDRM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDRM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Areg, OPS_8, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_MemOffs, OPS_8, 1, 1, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_MemOffs, OPS_16, 1, 1, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_MemOffs, OPS_32, 1, 1, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_64, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_MemOffs, OPS_64, 1, 1, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_MemOffs, OPS_8, 1, 1, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_8, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_MemOffs, OPS_16, 1, 1, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_MemOffs, OPS_32, 1, 1, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_MemOffs, OPS_64, 1, 1, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_64, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Op0Add, OPAP_None},
+ {OPT_Imm, OPS_64, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Mem, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Areg, OPS_8, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_MemOffs, OPS_8, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_MemOffs, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_MemOffs, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_MemOffs, OPS_8, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_8, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_MemOffs, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_MemOffs, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_RM, OPS_8, 1, 0, OPTM_None, OPA_EA, OPAP_ShortMov},
+ {OPT_Areg, OPS_8, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_ShortMov},
+ {OPT_Areg, OPS_16, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_ShortMov},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_ShortMov},
+ {OPT_Areg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Areg, OPS_8, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_8, 1, 0, OPTM_None, OPA_EA, OPAP_ShortMov},
+ {OPT_Areg, OPS_16, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_ShortMov},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_ShortMov},
+ {OPT_Areg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_ShortMov},
+ {OPT_Mem, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SegReg, OPS_16, 1, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SegReg, OPS_16, 1, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SegReg, OPS_16, 1, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SegReg, OPS_16, 1, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SegReg, OPS_16, 1, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_8, 0, 0, OPTM_None, OPA_Op0Add, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_Op0Add, OPAP_None},
+ {OPT_Imm, OPS_16, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Op0Add, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Op0Add, OPAP_None},
+ {OPT_Imm, OPS_64, 0, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Op0Add, OPAP_None},
+ {OPT_Imm, OPS_64, 1, 0, OPTM_None, OPA_Imm, OPAP_SImm32Avail},
+ {OPT_RM, OPS_8, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 0, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_RM, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_16, 0, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_32, 0, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_RM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_32, 0, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_RM, OPS_8, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_RM, OPS_16, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_16, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_RM, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_RM, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_CR4, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_CRReg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_CRReg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_CR4, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_CRReg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_DRReg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_DRReg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_DRReg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Mem, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_8, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_RM, OPS_8, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_RM, OPS_16, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_RM, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_64, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_RM, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_Any, 0, 0, OPTM_None, OPA_JmpRel, OPAP_None},
+ {OPT_Creg, OPS_32, 0, 0, OPTM_None, OPA_AdSizeR, OPAP_None},
+ {OPT_Imm, OPS_Any, 0, 0, OPTM_Short, OPA_JmpRel, OPAP_None},
+ {OPT_Creg, OPS_32, 0, 0, OPTM_None, OPA_AdSizeR, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDRM, OPS_256, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Imm, OPS_Any, 0, 0, OPTM_None, OPA_JmpRel, OPAP_None},
+ {OPT_Creg, OPS_64, 0, 0, OPTM_None, OPA_AdSizeR, OPAP_None},
+ {OPT_Imm, OPS_Any, 0, 0, OPTM_Short, OPA_JmpRel, OPAP_None},
+ {OPT_Creg, OPS_64, 0, 0, OPTM_None, OPA_AdSizeR, OPAP_None},
+ {OPT_Imm, OPS_Any, 0, 0, OPTM_None, OPA_JmpRel, OPAP_None},
+ {OPT_Creg, OPS_16, 0, 0, OPTM_None, OPA_AdSizeR, OPAP_None},
+ {OPT_Imm, OPS_Any, 0, 0, OPTM_Short, OPA_JmpRel, OPAP_None},
+ {OPT_Creg, OPS_16, 0, 0, OPTM_None, OPA_AdSizeR, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Areg, OPS_8, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Areg, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Dreg, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Areg, OPS_8, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Dreg, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Areg, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Dreg, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_EAVEX, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_EAVEX, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_MemrAX, OPS_Any, 0, 0, OPTM_None, OPA_AdSizeEA, OPAP_None},
+ {OPT_Creg, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Areg, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_Op0Add, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_Op0Add, OPAP_None},
+ {OPT_Areg, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Op0Add, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Op0Add, OPAP_None},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Areg, OPS_64, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Areg, OPS_64, 0, 0, OPTM_None, OPA_Op0Add, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Op0Add, OPAP_None},
+ {OPT_Areg, OPS_64, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_Any, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_Any, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_Any, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_8, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_16, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_8, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_RM, OPS_8, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Creg, OPS_8, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_RM, OPS_8, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm1, OPS_8, 1, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_RM, OPS_16, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Creg, OPS_8, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_RM, OPS_16, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm1, OPS_8, 1, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_RM, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Creg, OPS_8, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_RM, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm1, OPS_8, 1, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_RM, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Creg, OPS_8, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_RM, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm1, OPS_8, 1, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Imm, OPS_16, 1, 0, OPTM_None, OPA_JmpFar, OPAP_None},
+ {OPT_Imm, OPS_16, 1, 0, OPTM_None, OPA_JmpFar, OPAP_None},
+ {OPT_Imm, OPS_16, 1, 0, OPTM_None, OPA_JmpFar, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_JmpFar, OPAP_None},
+ {OPT_Imm, OPS_16, 1, 0, OPTM_None, OPA_JmpFar, OPAP_None},
+ {OPT_Imm, OPS_BITS, 1, 0, OPTM_None, OPA_JmpFar, OPAP_None},
+ {OPT_Areg, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Imm, OPS_16, 1, 0, OPTM_None, OPA_Imm, OPAP_SImm8},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_Imm, OPAP_SImm8},
+ {OPT_Areg, OPS_64, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_Imm, OPAP_SImm8},
+ {OPT_RM, OPS_16, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 0, 0, OPTM_None, OPA_SImm, OPAP_None},
+ {OPT_RM, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_16, 0, 0, OPTM_None, OPA_Imm, OPAP_SImm8},
+ {OPT_RM, OPS_16, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_16, 1, 0, OPTM_None, OPA_Imm, OPAP_SImm8},
+ {OPT_RM, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 0, 0, OPTM_None, OPA_SImm, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_32, 0, 0, OPTM_None, OPA_Imm, OPAP_SImm8},
+ {OPT_RM, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_Imm, OPAP_SImm8},
+ {OPT_RM, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_8, 0, 0, OPTM_None, OPA_SImm, OPAP_None},
+ {OPT_RM, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_Imm, OPAP_SImm8},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_256, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Mem, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_256, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Reg, OPS_16, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_8, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_16, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDRM, OPS_256, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Mem, OPS_80, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SegReg, OPS_16, 1, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDRM, OPS_64, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Areg, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Imm, OPS_16, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Areg, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Areg, OPS_64, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Imm, OPS_32, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_SegReg, OPS_16, 1, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_80, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_Mem, OPS_128, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_8, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_8, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_SIMDRM, OPS_128, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_SIMDReg, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_256, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_32, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_16, 1, 0, OPTM_None, OPA_EA, OPAP_A16},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_Imm, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Spare, OPAP_None},
+ {OPT_RM, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_RM, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SIMDReg, OPS_128, 0, 0, OPTM_None, OPA_SpareVEX, OPAP_None},
+ {OPT_RM, OPS_64, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Mem, OPS_16, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Mem, OPS_32, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_MemEAX, OPS_Any, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Mem, OPS_80, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Reg, OPS_BITS, 0, 0, OPTM_None, OPA_Op0Add, OPAP_None},
+ {OPT_RM, OPS_BITS, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_SS, OPS_Any, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_SS, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_SS, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_DS, OPS_Any, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_DS, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_DS, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_ES, OPS_Any, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_ES, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_ES, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_FS, OPS_Any, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_FS, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_FS, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_GS, OPS_Any, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_GS, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_GS, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_Mem, OPS_Any, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_ImmNotSegOff, OPS_Any, 0, 0, OPTM_None, OPA_JmpRel, OPAP_None},
+ {OPT_ImmNotSegOff, OPS_16, 0, 0, OPTM_None, OPA_JmpRel, OPAP_None},
+ {OPT_ImmNotSegOff, OPS_32, 0, 0, OPTM_None, OPA_JmpRel, OPAP_None},
+ {OPT_Imm, OPS_16, 0, 0, OPTM_Near, OPA_JmpRel, OPAP_None},
+ {OPT_Imm, OPS_32, 0, 0, OPTM_Near, OPA_JmpRel, OPAP_None},
+ {OPT_Imm, OPS_Any, 0, 0, OPTM_Near, OPA_JmpRel, OPAP_None},
+ {OPT_Reg, OPS_BITS, 0, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_RM, OPS_16, 0, 0, OPTM_Near, OPA_EA, OPAP_None},
+ {OPT_RM, OPS_32, 0, 0, OPTM_Near, OPA_EA, OPAP_None},
+ {OPT_RM, OPS_64, 0, 0, OPTM_Near, OPA_EA, OPAP_None},
+ {OPT_Mem, OPS_Any, 0, 0, OPTM_Near, OPA_EA, OPAP_None},
+ {OPT_Mem, OPS_16, 0, 0, OPTM_Far, OPA_EA, OPAP_None},
+ {OPT_Mem, OPS_32, 0, 0, OPTM_Far, OPA_EA, OPAP_None},
+ {OPT_Mem, OPS_64, 0, 0, OPTM_Far, OPA_EA, OPAP_None},
+ {OPT_Mem, OPS_Any, 0, 0, OPTM_Far, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_16, 0, 0, OPTM_Far, OPA_JmpFar, OPAP_None},
+ {OPT_Imm, OPS_32, 0, 0, OPTM_Far, OPA_JmpFar, OPAP_None},
+ {OPT_Imm, OPS_Any, 0, 0, OPTM_Far, OPA_JmpFar, OPAP_None},
+ {OPT_Imm, OPS_16, 0, 0, OPTM_None, OPA_JmpFar, OPAP_None},
+ {OPT_Imm, OPS_32, 0, 0, OPTM_None, OPA_JmpFar, OPAP_None},
+ {OPT_Imm, OPS_Any, 0, 0, OPTM_None, OPA_JmpFar, OPAP_None},
+ {OPT_Reg, OPS_80, 0, 0, OPTM_To, OPA_Op1Add, OPAP_None},
+ {OPT_Reg, OPS_32, 0, 0, OPTM_None, OPA_Op1Add, OPAP_None},
+ {OPT_Reg, OPS_64, 0, 0, OPTM_None, OPA_Op1Add, OPAP_None},
+ {OPT_Mem, OPS_BITS, 1, 0, OPTM_None, OPA_EA, OPAP_None},
+ {OPT_Imm, OPS_16, 0, 0, OPTM_None, OPA_JmpRel, OPAP_None},
+ {OPT_Imm, OPS_32, 0, 0, OPTM_None, OPA_JmpRel, OPAP_None},
+ {OPT_Imm, OPS_8, 1, 0, OPTM_None, OPA_SImm, OPAP_None},
+ {OPT_Imm, OPS_BITS, 1, 0, OPTM_None, OPA_Imm, OPAP_SImm8},
+ {OPT_Imm, OPS_32, 0, 0, OPTM_None, OPA_SImm, OPAP_None},
+ {OPT_CS, OPS_Any, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_CS, OPS_16, 0, 0, OPTM_None, OPA_None, OPAP_None},
+ {OPT_CS, OPS_32, 0, 0, OPTM_None, OPA_None, OPAP_None}
+};
+
+static const x86_insn_info empty_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0 }
+};
+
+static const x86_insn_info not64_insn[] = {
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0 }
+};
+
+static const x86_insn_info onebyte_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, MOD_OpSizeR, MOD_DOpS64R}, 0, 0, 0, 1, {0x00, 0, 0}, 0, 0, 0 }
+};
+
+static const x86_insn_info onebyte_prefix_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {MOD_PreAdd, MOD_Op0Add, 0}, 0, 0, 0x00, 1, {0x00, 0, 0}, 0, 0, 0 }
+};
+
+static const x86_insn_info twobyte_insn[] = {
+ { SUF_L|SUF_Q|SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, MOD_Op1Add, 0}, 0, 0, 0, 2, {0x00, 0x00, 0}, 0, 0, 0 }
+};
+
+static const x86_insn_info threebyte_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, MOD_Op1Add, MOD_Op2Add}, 0, 0, 0, 3, {0x00, 0x00, 0x00}, 0, 0, 0 }
+};
+
+static const x86_insn_info onebytemem_insn[] = {
+ { SUF_L|SUF_Q|SUF_S|SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, MOD_Op0Add, 0}, 0, 0, 0, 1, {0x00, 0, 0}, 0, 1, 674 }
+};
+
+static const x86_insn_info twobytemem_insn[] = {
+ { SUF_L|SUF_Q|SUF_S|SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, MOD_Op0Add, MOD_Op1Add}, 0, 0, 0, 2, {0x00, 0x00, 0}, 0, 1, 532 }
+};
+
+static const x86_insn_info mov_insn[] = {
+ { SUF_B|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xA0, 0, 0}, 0, 2, 365 },
+ { SUF_W|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xA1, 0, 0}, 0, 2, 367 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xA1, 0, 0}, 0, 2, 369 },
+ { SUF_B|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xA2, 0, 0}, 0, 2, 371 },
+ { SUF_W|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xA3, 0, 0}, 0, 2, 373 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xA3, 0, 0}, 0, 2, 375 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xA0, 0, 0}, 0, 2, 341 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xA1, 0, 0}, 0, 2, 343 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xA1, 0, 0}, 0, 2, 345 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xA1, 0, 0}, 0, 2, 347 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xA2, 0, 0}, 0, 2, 349 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xA3, 0, 0}, 0, 2, 351 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xA3, 0, 0}, 0, 2, 353 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xA3, 0, 0}, 0, 2, 355 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x88, 0xA2, 0}, 0, 2, 377 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x89, 0xA3, 0}, 0, 2, 379 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x89, 0xA3, 0}, 0, 2, 381 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x89, 0xA3, 0}, 0, 2, 383 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x88, 0, 0}, 0, 2, 323 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x89, 0, 0}, 0, 2, 260 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x89, 0, 0}, 0, 2, 266 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x89, 0, 0}, 0, 2, 272 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x8A, 0xA0, 0}, 0, 2, 385 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x8B, 0xA1, 0}, 0, 2, 387 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x8B, 0xA1, 0}, 0, 2, 389 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x8B, 0xA1, 0}, 0, 2, 391 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x8A, 0, 0}, 0, 2, 325 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x8B, 0, 0}, 0, 2, 98 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x8B, 0, 0}, 0, 2, 101 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x8B, 0, 0}, 0, 2, 104 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x8C, 0, 0}, 0, 2, 393 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x8C, 0, 0}, 0, 2, 395 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x8C, 0, 0}, 0, 2, 397 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x8C, 0, 0}, 0, 2, 399 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x8E, 0, 0}, 0, 2, 401 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x8E, 0, 0}, 0, 2, 396 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x8E, 0, 0}, 0, 2, 398 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xB0, 0, 0}, 0, 2, 403 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xB8, 0, 0}, 0, 2, 405 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xB8, 0, 0}, 0, 2, 407 },
+ { GAS_ILLEGAL|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xB8, 0, 0}, 0, 2, 409 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xB8, 0xC7, 0}, 0, 2, 411 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xC6, 0, 0}, 0, 2, 413 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xC7, 0, 0}, 0, 2, 415 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xC7, 0, 0}, 0, 2, 417 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xC7, 0, 0}, 0, 2, 419 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xC6, 0, 0}, 0, 2, 421 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xC7, 0, 0}, 0, 2, 423 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xC7, 0, 0}, 0, 2, 425 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xC7, 0, 0}, 0, 2, 427 },
+ { SUF_L|SUF_Z, NOT_64, CPU_586, CPU_Priv, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x22, 0}, 0, 2, 429 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, CPU_Priv, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x22, 0}, 0, 2, 431 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_Priv, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x22, 0}, 0, 2, 433 },
+ { SUF_L|SUF_Z, NOT_64, CPU_586, CPU_Priv, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x20, 0}, 0, 2, 435 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, CPU_Priv, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x20, 0}, 0, 2, 430 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_Priv, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x20, 0}, 0, 2, 437 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, CPU_Priv, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x23, 0}, 0, 2, 439 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_Priv, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x23, 0}, 0, 2, 441 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, CPU_Priv, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x21, 0}, 0, 2, 440 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_Priv, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x21, 0}, 0, 2, 443 },
+ { GAS_ONLY|SUF_Q|SUF_Z, 0, CPU_MMX, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x6F, 0}, 0, 2, 140 },
+ { GAS_ONLY|SUF_Q|SUF_Z, ONLY_64, CPU_MMX, 0, 0, {0, 0, 0}, 64, 0, 0, 2, {0x0F, 0x6E, 0}, 0, 2, 295 },
+ { GAS_ONLY|SUF_Q|SUF_Z, 0, CPU_MMX, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x7F, 0}, 0, 2, 331 },
+ { GAS_ONLY|SUF_Q|SUF_Z, ONLY_64, CPU_MMX, 0, 0, {0, 0, 0}, 64, 0, 0, 2, {0x0F, 0x7E, 0}, 0, 2, 297 },
+ { GAS_ONLY|SUF_Q|SUF_Z, 0, CPU_SSE2, 0, 0, {0, 0, 0}, 0, 0, 0xF3, 2, {0x0F, 0x7E, 0}, 0, 2, 64 },
+ { GAS_ONLY|SUF_Q|SUF_Z, 0, CPU_SSE2, 0, 0, {0, 0, 0}, 0, 0, 0xF3, 2, {0x0F, 0x7E, 0}, 0, 2, 333 },
+ { GAS_ONLY|SUF_Q|SUF_Z, ONLY_64, CPU_SSE2, 0, 0, {0, 0, 0}, 64, 0, 0x66, 2, {0x0F, 0x6E, 0}, 0, 2, 301 },
+ { GAS_ONLY|SUF_Q|SUF_Z, 0, CPU_SSE2, 0, 0, {0, 0, 0}, 0, 0, 0x66, 2, {0x0F, 0xD6, 0}, 0, 2, 335 },
+ { GAS_ONLY|SUF_Q|SUF_Z, ONLY_64, CPU_SSE2, 0, 0, {0, 0, 0}, 64, 0, 0x66, 2, {0x0F, 0x7E, 0}, 0, 2, 182 }
+};
+
+static const x86_insn_info movabs_insn[] = {
+ { SUF_B|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xA0, 0, 0}, 0, 2, 341 },
+ { SUF_W|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xA1, 0, 0}, 0, 2, 343 },
+ { SUF_L|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xA1, 0, 0}, 0, 2, 345 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xA1, 0, 0}, 0, 2, 347 },
+ { SUF_B|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xA2, 0, 0}, 0, 2, 349 },
+ { SUF_W|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xA3, 0, 0}, 0, 2, 351 },
+ { SUF_L|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xA3, 0, 0}, 0, 2, 353 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xA3, 0, 0}, 0, 2, 355 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xB8, 0, 0}, 0, 2, 357 }
+};
+
+static const x86_insn_info movszx_insn[] = {
+ { SUF_B|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 16, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 603 },
+ { SUF_B|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 32, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 537 },
+ { SUF_B|SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op1Add, 0, 0}, 64, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 541 },
+ { SUF_W|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 32, 0, 0, 2, {0x0F, 0x01, 0}, 0, 2, 539 },
+ { SUF_W|SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op1Add, 0, 0}, 64, 0, 0, 2, {0x0F, 0x01, 0}, 0, 2, 605 }
+};
+
+static const x86_insn_info movsxd_insn[] = {
+ { SUF_L|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x63, 0, 0}, 0, 2, 647 }
+};
+
+static const x86_insn_info push_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0x50, 0, 0}, 0, 1, 657 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 64, 0, 1, {0x50, 0, 0}, 0, 1, 405 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x50, 0, 0}, 0, 1, 407 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0x50, 0, 0}, 0, 1, 357 },
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0xFF, 0, 0}, 6, 1, 658 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 64, 0, 1, {0xFF, 0, 0}, 6, 1, 287 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xFF, 0, 0}, 6, 1, 283 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0xFF, 0, 0}, 6, 1, 286 },
+ { GAS_ILLEGAL|SUF_Z, 0, CPU_186, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0x6A, 0, 0}, 0, 1, 100 },
+ { GAS_ONLY|SUF_Z, 0, CPU_186, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0x6A, 0, 0}, 0, 1, 702 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 64, 0, 1, {0x6A, 0x68, 0}, 0, 1, 112 },
+ { GAS_ILLEGAL|SUF_Z, NOT_64, CPU_186, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x6A, 0x68, 0}, 0, 1, 703 },
+ { SUF_W|SUF_Z, 0, CPU_186, 0, 0, {0, 0, 0}, 16, 64, 0, 1, {0x6A, 0x68, 0}, 0, 1, 574 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x6A, 0x68, 0}, 0, 1, 576 },
+ { GAS_ILLEGAL|SUF_Z, 0, CPU_186, 0, 0, {0, 0, 0}, 16, 64, 0, 1, {0x68, 0, 0}, 0, 1, 416 },
+ { GAS_ILLEGAL|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x68, 0, 0}, 0, 1, 418 },
+ { GAS_ILLEGAL|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 64, 0, 1, {0x68, 0, 0}, 0, 1, 704 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x0E, 0, 0}, 0, 1, 705 },
+ { SUF_W|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x0E, 0, 0}, 0, 1, 706 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x0E, 0, 0}, 0, 1, 707 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x16, 0, 0}, 0, 1, 659 },
+ { SUF_W|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x16, 0, 0}, 0, 1, 660 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x16, 0, 0}, 0, 1, 661 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x1E, 0, 0}, 0, 1, 662 },
+ { SUF_W|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x1E, 0, 0}, 0, 1, 663 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x1E, 0, 0}, 0, 1, 664 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x06, 0, 0}, 0, 1, 665 },
+ { SUF_W|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x06, 0, 0}, 0, 1, 666 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x06, 0, 0}, 0, 1, 667 },
+ { SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0xA0, 0}, 0, 1, 668 },
+ { SUF_W|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 16, 0, 0, 2, {0x0F, 0xA0, 0}, 0, 1, 669 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 2, {0x0F, 0xA0, 0}, 0, 1, 670 },
+ { SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0xA8, 0}, 0, 1, 671 },
+ { SUF_W|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 16, 0, 0, 2, {0x0F, 0xA8, 0}, 0, 1, 672 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 2, {0x0F, 0xA8, 0}, 0, 1, 673 }
+};
+
+static const x86_insn_info pop_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0x58, 0, 0}, 0, 1, 657 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 64, 0, 1, {0x58, 0, 0}, 0, 1, 405 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x58, 0, 0}, 0, 1, 407 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0x58, 0, 0}, 0, 1, 357 },
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0x8F, 0, 0}, 0, 1, 658 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 64, 0, 1, {0x8F, 0, 0}, 0, 1, 287 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x8F, 0, 0}, 0, 1, 283 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0x8F, 0, 0}, 0, 1, 286 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x17, 0, 0}, 0, 1, 659 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x17, 0, 0}, 0, 1, 660 },
+ { SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x17, 0, 0}, 0, 1, 661 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x1F, 0, 0}, 0, 1, 662 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x1F, 0, 0}, 0, 1, 663 },
+ { SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x1F, 0, 0}, 0, 1, 664 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x07, 0, 0}, 0, 1, 665 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x07, 0, 0}, 0, 1, 666 },
+ { SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x07, 0, 0}, 0, 1, 667 },
+ { SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0xA1, 0}, 0, 1, 668 },
+ { SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 16, 0, 0, 2, {0x0F, 0xA1, 0}, 0, 1, 669 },
+ { SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 2, {0x0F, 0xA1, 0}, 0, 1, 670 },
+ { SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0xA9, 0}, 0, 1, 671 },
+ { SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 16, 0, 0, 2, {0x0F, 0xA9, 0}, 0, 1, 672 },
+ { SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 2, {0x0F, 0xA9, 0}, 0, 1, 673 }
+};
+
+static const x86_insn_info xchg_insn[] = {
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x86, 0, 0}, 0, 2, 323 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x86, 0, 0}, 0, 2, 325 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x90, 0, 0}, 0, 2, 517 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x90, 0, 0}, 0, 2, 519 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x87, 0, 0}, 0, 2, 260 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x87, 0, 0}, 0, 2, 98 },
+ { SUF_L|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x87, 0, 0}, 0, 2, 521 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x90, 0, 0}, 0, 2, 523 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x90, 0, 0}, 0, 2, 525 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x87, 0, 0}, 0, 2, 266 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x87, 0, 0}, 0, 2, 101 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x90, 0, 0}, 0, 2, 527 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x90, 0, 0}, 0, 2, 356 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x90, 0, 0}, 0, 2, 529 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x87, 0, 0}, 0, 2, 272 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x87, 0, 0}, 0, 2, 104 }
+};
+
+static const x86_insn_info in_insn[] = {
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xE4, 0, 0}, 0, 2, 498 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xE5, 0, 0}, 0, 2, 500 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xE5, 0, 0}, 0, 2, 617 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xEC, 0, 0}, 0, 2, 504 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xED, 0, 0}, 0, 2, 506 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xED, 0, 0}, 0, 2, 502 },
+ { GAS_ONLY|SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xE4, 0, 0}, 0, 1, 3 },
+ { GAS_ONLY|SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xE5, 0, 0}, 0, 1, 3 },
+ { GAS_ONLY|SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xE5, 0, 0}, 0, 1, 3 },
+ { GAS_ONLY|SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xEC, 0, 0}, 0, 1, 503 },
+ { GAS_ONLY|SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xED, 0, 0}, 0, 1, 503 },
+ { GAS_ONLY|SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xED, 0, 0}, 0, 1, 503 }
+};
+
+static const x86_insn_info out_insn[] = {
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xE6, 0, 0}, 0, 2, 497 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xE7, 0, 0}, 0, 2, 499 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xE7, 0, 0}, 0, 2, 501 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xEE, 0, 0}, 0, 2, 503 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xEF, 0, 0}, 0, 2, 505 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xEF, 0, 0}, 0, 2, 507 },
+ { GAS_ONLY|SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xE6, 0, 0}, 0, 1, 3 },
+ { GAS_ONLY|SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xE7, 0, 0}, 0, 1, 3 },
+ { GAS_ONLY|SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xE7, 0, 0}, 0, 1, 3 },
+ { GAS_ONLY|SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xEE, 0, 0}, 0, 1, 503 },
+ { GAS_ONLY|SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xEF, 0, 0}, 0, 1, 503 },
+ { GAS_ONLY|SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xEF, 0, 0}, 0, 1, 503 }
+};
+
+static const x86_insn_info lea_insn[] = {
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x8D, 0, 0}, 0, 2, 531 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x8D, 0, 0}, 0, 2, 533 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x8D, 0, 0}, 0, 2, 535 }
+};
+
+static const x86_insn_info ldes_insn[] = {
+ { SUF_W|SUF_Z, NOT_64, 0, 0, 0, {MOD_Op0Add, 0, 0}, 16, 0, 0, 1, {0x00, 0, 0}, 0, 2, 531 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {MOD_Op0Add, 0, 0}, 32, 0, 0, 1, {0x00, 0, 0}, 0, 2, 533 }
+};
+
+static const x86_insn_info lfgss_insn[] = {
+ { SUF_W|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 16, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 531 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 32, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 533 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 64, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 535 }
+};
+
+static const x86_insn_info arith_insn[] = {
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, 0, 0}, 0, 0, 0, 1, {0x04, 0, 0}, 0, 2, 498 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_Op2Add, MOD_Op1AddSp, 0}, 16, 0, 0, 2, {0x83, 0xC0, 0x05}, 0, 2, 573 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op2Add, MOD_Op1AddSp, 0}, 32, 0, 0, 2, {0x83, 0xC0, 0x05}, 0, 2, 575 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op2Add, MOD_Op1AddSp, 0}, 64, 0, 0, 2, {0x83, 0xC0, 0x05}, 0, 2, 577 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 0, 0, 0, 1, {0x80, 0, 0}, 0, 2, 421 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 0, 0, 0, 1, {0x80, 0, 0}, 0, 2, 413 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 16, 0, 0, 1, {0x83, 0, 0}, 0, 2, 579 },
+ { GAS_ILLEGAL|SUF_Z, 0, 0, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 16, 0, 0, 1, {0x83, 0x81, 0}, 0, 2, 581 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 16, 0, 0, 1, {0x83, 0x81, 0}, 0, 2, 583 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 32, 0, 0, 1, {0x83, 0, 0}, 0, 2, 585 },
+ { GAS_ILLEGAL|SUF_Z, NOT_64, CPU_386, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 32, 0, 0, 1, {0x83, 0x81, 0}, 0, 2, 587 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 32, 0, 0, 1, {0x83, 0x81, 0}, 0, 2, 589 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 64, 0, 0, 1, {0x83, 0, 0}, 0, 2, 591 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 64, 0, 0, 1, {0x83, 0x81, 0}, 0, 2, 593 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, 0, 0}, 0, 0, 0, 1, {0x00, 0, 0}, 0, 2, 323 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, 0, 0}, 16, 0, 0, 1, {0x01, 0, 0}, 0, 2, 260 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op0Add, 0, 0}, 32, 0, 0, 1, {0x01, 0, 0}, 0, 2, 266 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op0Add, 0, 0}, 64, 0, 0, 1, {0x01, 0, 0}, 0, 2, 272 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, 0, 0}, 0, 0, 0, 1, {0x02, 0, 0}, 0, 2, 325 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, 0, 0}, 16, 0, 0, 1, {0x03, 0, 0}, 0, 2, 98 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op0Add, 0, 0}, 32, 0, 0, 1, {0x03, 0, 0}, 0, 2, 101 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op0Add, 0, 0}, 64, 0, 0, 1, {0x03, 0, 0}, 0, 2, 104 }
+};
+
+static const x86_insn_info incdec_insn[] = {
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 0, 0, 0, 1, {0xFE, 0, 0}, 0, 1, 421 },
+ { SUF_W|SUF_Z, NOT_64, 0, 0, 0, {MOD_Op0Add, 0, 0}, 16, 0, 0, 1, {0x00, 0, 0}, 0, 1, 405 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 16, 0, 0, 1, {0xFF, 0, 0}, 0, 1, 287 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {MOD_Op0Add, 0, 0}, 32, 0, 0, 1, {0x00, 0, 0}, 0, 1, 407 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 32, 0, 0, 1, {0xFF, 0, 0}, 0, 1, 283 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 64, 0, 0, 1, {0xFF, 0, 0}, 0, 1, 286 }
+};
+
+static const x86_insn_info f6_insn[] = {
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 1, {0xF6, 0, 0}, 0, 1, 421 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 16, 0, 0, 1, {0xF7, 0, 0}, 0, 1, 287 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_SpAdd, 0, 0}, 32, 0, 0, 1, {0xF7, 0, 0}, 0, 1, 283 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_SpAdd, 0, 0}, 64, 0, 0, 1, {0xF7, 0, 0}, 0, 1, 286 }
+};
+
+static const x86_insn_info div_insn[] = {
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 1, {0xF6, 0, 0}, 0, 1, 421 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 16, 0, 0, 1, {0xF7, 0, 0}, 0, 1, 287 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_SpAdd, 0, 0}, 32, 0, 0, 1, {0xF7, 0, 0}, 0, 1, 283 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_SpAdd, 0, 0}, 64, 0, 0, 1, {0xF7, 0, 0}, 0, 1, 286 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 1, {0xF6, 0, 0}, 0, 2, 471 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 16, 0, 0, 1, {0xF7, 0, 0}, 0, 2, 473 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_SpAdd, 0, 0}, 32, 0, 0, 1, {0xF7, 0, 0}, 0, 2, 475 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_SpAdd, 0, 0}, 64, 0, 0, 1, {0xF7, 0, 0}, 0, 2, 477 }
+};
+
+static const x86_insn_info test_insn[] = {
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xA8, 0, 0}, 0, 2, 498 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xA9, 0, 0}, 0, 2, 623 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xA9, 0, 0}, 0, 2, 625 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xA9, 0, 0}, 0, 2, 627 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xF6, 0, 0}, 0, 2, 421 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xF6, 0, 0}, 0, 2, 413 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xF7, 0, 0}, 0, 2, 423 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xF7, 0, 0}, 0, 2, 415 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xF7, 0, 0}, 0, 2, 425 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xF7, 0, 0}, 0, 2, 417 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xF7, 0, 0}, 0, 2, 427 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xF7, 0, 0}, 0, 2, 419 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x84, 0, 0}, 0, 2, 323 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x85, 0, 0}, 0, 2, 260 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x85, 0, 0}, 0, 2, 266 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x85, 0, 0}, 0, 2, 272 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x84, 0, 0}, 0, 2, 325 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x85, 0, 0}, 0, 2, 98 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x85, 0, 0}, 0, 2, 101 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x85, 0, 0}, 0, 2, 104 }
+};
+
+static const x86_insn_info aadm_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, 0, 0}, 0, 0, 0, 2, {0xD4, 0x0A, 0}, 0, 0, 0 },
+ { SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, 0, 0}, 0, 0, 0, 1, {0xD4, 0, 0}, 0, 1, 3 }
+};
+
+static const x86_insn_info imul_insn[] = {
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xF6, 0, 0}, 5, 1, 421 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xF7, 0, 0}, 5, 1, 287 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xF7, 0, 0}, 5, 1, 283 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xF7, 0, 0}, 5, 1, 286 },
+ { SUF_W|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 16, 0, 0, 2, {0x0F, 0xAF, 0}, 0, 2, 98 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 2, {0x0F, 0xAF, 0}, 0, 2, 101 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_386, 0, 0, {0, 0, 0}, 64, 0, 0, 2, {0x0F, 0xAF, 0}, 0, 2, 104 },
+ { SUF_W|SUF_Z, 0, CPU_186, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x6B, 0, 0}, 0, 3, 98 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x6B, 0, 0}, 0, 3, 101 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_186, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x6B, 0, 0}, 0, 3, 104 },
+ { SUF_W|SUF_Z, 0, CPU_186, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x6B, 0, 0}, 0, 2, 303 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x6B, 0, 0}, 0, 2, 305 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_186, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x6B, 0, 0}, 0, 2, 307 },
+ { SUF_W|SUF_Z, 0, CPU_186, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x6B, 0x69, 0}, 0, 3, 107 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x6B, 0x69, 0}, 0, 3, 110 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_186, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x6B, 0x69, 0}, 0, 3, 113 },
+ { SUF_W|SUF_Z, 0, CPU_186, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x6B, 0x69, 0}, 0, 2, 309 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x6B, 0x69, 0}, 0, 2, 311 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_186, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x6B, 0x69, 0}, 0, 2, 313 }
+};
+
+static const x86_insn_info shift_insn[] = {
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 1, {0xD2, 0, 0}, 0, 2, 551 },
+ { SUF_B|SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 1, {0xD0, 0, 0}, 0, 2, 553 },
+ { SUF_B|SUF_Z, 0, CPU_186, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 1, {0xC0, 0, 0}, 0, 2, 421 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 16, 0, 0, 1, {0xD3, 0, 0}, 0, 2, 555 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 16, 0, 0, 1, {0xD1, 0, 0}, 0, 2, 557 },
+ { SUF_W|SUF_Z, 0, CPU_186, 0, 0, {MOD_SpAdd, 0, 0}, 16, 0, 0, 1, {0xC1, 0, 0}, 0, 2, 287 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_SpAdd, 0, 0}, 32, 0, 0, 1, {0xD3, 0, 0}, 0, 2, 559 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_SpAdd, 0, 0}, 32, 0, 0, 1, {0xD1, 0, 0}, 0, 2, 561 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_SpAdd, 0, 0}, 32, 0, 0, 1, {0xC1, 0, 0}, 0, 2, 289 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_SpAdd, 0, 0}, 64, 0, 0, 1, {0xD3, 0, 0}, 0, 2, 563 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_SpAdd, 0, 0}, 64, 0, 0, 1, {0xD1, 0, 0}, 0, 2, 565 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_186, 0, 0, {MOD_SpAdd, 0, 0}, 64, 0, 0, 1, {0xC1, 0, 0}, 0, 2, 291 },
+ { GAS_ONLY|SUF_B|SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 1, {0xD0, 0, 0}, 0, 1, 421 },
+ { GAS_ONLY|SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 16, 0, 0, 1, {0xD1, 0, 0}, 0, 1, 287 },
+ { GAS_ONLY|SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_SpAdd, 0, 0}, 32, 0, 0, 1, {0xD1, 0, 0}, 0, 1, 283 },
+ { GAS_ONLY|SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_SpAdd, 0, 0}, 64, 0, 0, 1, {0xD1, 0, 0}, 0, 1, 286 }
+};
+
+static const x86_insn_info shlrd_insn[] = {
+ { SUF_W|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 16, 0, 0, 2, {0x0F, 0x00, 0}, 0, 3, 260 },
+ { SUF_W|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 16, 0, 0, 2, {0x0F, 0x01, 0}, 0, 3, 263 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 32, 0, 0, 2, {0x0F, 0x00, 0}, 0, 3, 266 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 32, 0, 0, 2, {0x0F, 0x01, 0}, 0, 3, 269 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 64, 0, 0, 2, {0x0F, 0x00, 0}, 0, 3, 272 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 64, 0, 0, 2, {0x0F, 0x01, 0}, 0, 3, 275 },
+ { GAS_ONLY|SUF_W|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 16, 0, 0, 2, {0x0F, 0x01, 0}, 0, 2, 260 },
+ { GAS_ONLY|SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 32, 0, 0, 2, {0x0F, 0x01, 0}, 0, 2, 266 },
+ { GAS_ONLY|SUF_Q|SUF_Z, ONLY_64, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 64, 0, 0, 2, {0x0F, 0x01, 0}, 0, 2, 272 }
+};
+
+static const x86_insn_info call_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, {0, 0, 0}, 0, 1, 675 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 0, {0, 0, 0}, 0, 1, 676 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 0, {0, 0, 0}, 0, 1, 677 },
+ { SUF_L|SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 0, {0, 0, 0}, 0, 1, 677 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xE8, 0, 0}, 0, 1, 678 },
+ { SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xE8, 0, 0}, 0, 1, 679 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 64, 0, 1, {0xE8, 0, 0}, 0, 1, 679 },
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0xE8, 0, 0}, 0, 1, 680 },
+ { SUF_W, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xFF, 0, 0}, 2, 1, 287 },
+ { SUF_L, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xFF, 0, 0}, 2, 1, 283 },
+ { SUF_Q, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 64, 0, 1, {0xFF, 0, 0}, 2, 1, 286 },
+ { GAS_ONLY|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0xFF, 0, 0}, 2, 1, 681 },
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0xFF, 0, 0}, 2, 1, 674 },
+ { GAS_ILLEGAL|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 64, 0, 1, {0xFF, 0, 0}, 2, 1, 682 },
+ { GAS_ILLEGAL|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xFF, 0, 0}, 2, 1, 683 },
+ { GAS_ILLEGAL|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 64, 0, 1, {0xFF, 0, 0}, 2, 1, 684 },
+ { GAS_ILLEGAL|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0xFF, 0, 0}, 2, 1, 685 },
+ { GAS_ILLEGAL|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xFF, 0, 0}, 3, 1, 686 },
+ { GAS_ILLEGAL|SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xFF, 0, 0}, 3, 1, 687 },
+ { GAS_ILLEGAL|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xFF, 0, 0}, 3, 1, 688 },
+ { GAS_ILLEGAL|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xFF, 0, 0}, 3, 1, 689 },
+ { GAS_ILLEGAL|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x9A, 0, 0}, 0, 1, 690 },
+ { GAS_ILLEGAL|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x9A, 0, 0}, 0, 1, 691 },
+ { GAS_ILLEGAL|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x9A, 0, 0}, 0, 1, 692 },
+ { GAS_ILLEGAL|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x9A, 0, 0}, 0, 1, 693 },
+ { GAS_ILLEGAL|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x9A, 0, 0}, 0, 1, 694 },
+ { GAS_ILLEGAL|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x9A, 0, 0}, 0, 1, 695 },
+ { GAS_ONLY|GAS_NO_REV|SUF_W, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x9A, 0, 0}, 0, 2, 567 },
+ { GAS_ONLY|GAS_NO_REV|SUF_L, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x9A, 0, 0}, 0, 2, 569 },
+ { GAS_ONLY|GAS_NO_REV|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0x9A, 0, 0}, 0, 2, 571 }
+};
+
+static const x86_insn_info jmp_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, {0, 0, 0}, 0, 1, 675 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 0, {0, 0, 0}, 0, 1, 676 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x00, 0, 0}, 0, 1, 677 },
+ { SUF_L|SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0x00, 0, 0}, 0, 1, 677 },
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0xEB, 0, 0}, 0, 1, 483 },
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 64, 0, 1, {0xE9, 0, 0}, 0, 1, 678 },
+ { SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xE9, 0, 0}, 0, 1, 679 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 64, 0, 1, {0xE9, 0, 0}, 0, 1, 679 },
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0xE9, 0, 0}, 0, 1, 680 },
+ { SUF_W, 0, 0, 0, 0, {0, 0, 0}, 16, 64, 0, 1, {0xFF, 0, 0}, 4, 1, 287 },
+ { SUF_L, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xFF, 0, 0}, 4, 1, 283 },
+ { SUF_Q, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 64, 0, 1, {0xFF, 0, 0}, 4, 1, 286 },
+ { GAS_ONLY|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0xFF, 0, 0}, 4, 1, 681 },
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0xFF, 0, 0}, 4, 1, 674 },
+ { GAS_ILLEGAL|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 64, 0, 1, {0xFF, 0, 0}, 4, 1, 682 },
+ { GAS_ILLEGAL|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xFF, 0, 0}, 4, 1, 683 },
+ { GAS_ILLEGAL|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 64, 0, 1, {0xFF, 0, 0}, 4, 1, 684 },
+ { GAS_ILLEGAL|SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 1, {0xFF, 0, 0}, 4, 1, 685 },
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xFF, 0, 0}, 5, 1, 686 },
+ { SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xFF, 0, 0}, 5, 1, 687 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 1, {0xFF, 0, 0}, 5, 1, 688 },
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xFF, 0, 0}, 5, 1, 689 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xEA, 0, 0}, 0, 1, 690 },
+ { SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xEA, 0, 0}, 0, 1, 691 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xEA, 0, 0}, 0, 1, 692 },
+ { GAS_ILLEGAL|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xEA, 0, 0}, 0, 1, 693 },
+ { GAS_ILLEGAL|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xEA, 0, 0}, 0, 1, 694 },
+ { GAS_ILLEGAL|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xEA, 0, 0}, 0, 1, 695 },
+ { GAS_ONLY|GAS_NO_REV|SUF_W, NOT_64, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xEA, 0, 0}, 0, 2, 567 },
+ { GAS_ONLY|GAS_NO_REV|SUF_L, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xEA, 0, 0}, 0, 2, 569 },
+ { GAS_ONLY|GAS_NO_REV|SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xEA, 0, 0}, 0, 2, 571 }
+};
+
+static const x86_insn_info ljmpcall_insn[] = {
+ { SUF_W, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 16, 0, 0, 1, {0xFF, 0, 0}, 0, 1, 34 },
+ { SUF_L, 0, CPU_386, 0, 0, {MOD_SpAdd, 0, 0}, 32, 0, 0, 1, {0xFF, 0, 0}, 0, 1, 58 },
+ { SUF_Q, ONLY_64, 0, 0, 0, {MOD_SpAdd, 0, 0}, 64, 0, 0, 1, {0xFF, 0, 0}, 0, 1, 6 },
+ { SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 1, {0xFF, 0, 0}, 0, 1, 699 },
+ { GAS_NO_REV|SUF_W, NOT_64, 0, 0, 0, {MOD_Gap, MOD_Op0Add, 0}, 16, 0, 0, 1, {0x00, 0, 0}, 0, 2, 567 },
+ { GAS_NO_REV|SUF_L, NOT_64, CPU_386, 0, 0, {MOD_Gap, MOD_Op0Add, 0}, 32, 0, 0, 1, {0x00, 0, 0}, 0, 2, 569 },
+ { GAS_NO_REV|SUF_Z, NOT_64, 0, 0, 0, {MOD_Gap, MOD_Op0Add, 0}, 0, 0, 0, 1, {0x00, 0, 0}, 0, 2, 571 }
+};
+
+static const x86_insn_info retnf_insn[] = {
+ { SUF_Z, NOT_64, 0, 0, 0, {MOD_Op0Add, 0, 0}, 0, 0, 0, 1, {0x01, 0, 0}, 0, 0, 0 },
+ { SUF_Z, NOT_64, 0, 0, 0, {MOD_Op0Add, 0, 0}, 0, 0, 0, 1, {0x00, 0, 0}, 0, 1, 406 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op0Add, MOD_OpSizeR, 0}, 0, 0, 0, 1, {0x01, 0, 0}, 0, 0, 0 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op0Add, MOD_OpSizeR, 0}, 0, 0, 0, 1, {0x00, 0, 0}, 0, 1, 406 },
+ { SUF_L|SUF_Q|SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, MOD_OpSizeR, 0}, 0, 0, 0, 1, {0x01, 0, 0}, 0, 0, 0 },
+ { SUF_L|SUF_Q|SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, MOD_OpSizeR, 0}, 0, 0, 0, 1, {0x00, 0, 0}, 0, 1, 406 }
+};
+
+static const x86_insn_info enter_insn[] = {
+ { GAS_NO_REV|SUF_L|SUF_Z, NOT_64, CPU_186, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xC8, 0, 0}, 0, 2, 645 },
+ { GAS_NO_REV|SUF_Q|SUF_Z, ONLY_64, CPU_186, 0, 0, {0, 0, 0}, 64, 64, 0, 1, {0xC8, 0, 0}, 0, 2, 645 },
+ { GAS_ONLY|GAS_NO_REV|SUF_W|SUF_Z, 0, CPU_186, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0xC8, 0, 0}, 0, 2, 645 }
+};
+
+static const x86_insn_info jcc_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, {0, 0, 0}, 0, 1, 481 },
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 16, 0, 0, 0, {0, 0, 0}, 0, 1, 700 },
+ { SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 0, {0, 0, 0}, 0, 1, 701 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 0, {0, 0, 0}, 0, 1, 701 },
+ { SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, 0, 0}, 0, 64, 0, 1, {0x70, 0, 0}, 0, 1, 483 },
+ { SUF_Z, 0, CPU_186, 0, 0, {MOD_Op1Add, 0, 0}, 16, 64, 0, 2, {0x0F, 0x80, 0}, 0, 1, 678 },
+ { SUF_Z, NOT_64, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 32, 0, 0, 2, {0x0F, 0x80, 0}, 0, 1, 679 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op1Add, 0, 0}, 64, 64, 0, 2, {0x0F, 0x80, 0}, 0, 1, 679 },
+ { SUF_Z, 0, CPU_186, 0, 0, {MOD_Op1Add, 0, 0}, 0, 64, 0, 2, {0x0F, 0x80, 0}, 0, 1, 680 }
+};
+
+static const x86_insn_info jcxz_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {MOD_AdSizeR, 0, 0}, 0, 0, 0, 0, {0, 0, 0}, 0, 1, 481 },
+ { SUF_Z, 0, 0, 0, 0, {MOD_AdSizeR, 0, 0}, 0, 64, 0, 1, {0xE3, 0, 0}, 0, 1, 483 }
+};
+
+static const x86_insn_info loop_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, {0, 0, 0}, 0, 1, 481 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, {0, 0, 0}, 0, 2, 493 },
+ { SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 0, 64, 0, 0, {0, 0, 0}, 0, 2, 481 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 0, {0, 0, 0}, 0, 2, 489 },
+ { SUF_Z, NOT_64, 0, 0, 0, {MOD_Op0Add, 0, 0}, 0, 0, 0, 1, {0xE0, 0, 0}, 0, 1, 483 },
+ { SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, 0, 0}, 0, 64, 0, 1, {0xE0, 0, 0}, 0, 2, 495 },
+ { SUF_Z, 0, CPU_386, 0, 0, {MOD_Op0Add, 0, 0}, 0, 64, 0, 1, {0xE0, 0, 0}, 0, 2, 483 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op0Add, 0, 0}, 0, 64, 0, 1, {0xE0, 0, 0}, 0, 2, 491 }
+};
+
+static const x86_insn_info loopw_insn[] = {
+ { SUF_Z, NOT_64, 0, 0, 0, {MOD_Gap, MOD_AdSizeR, 0}, 0, 64, 0, 0, {0, 0, 0}, 0, 1, 481 },
+ { SUF_Z, NOT_64, 0, 0, 0, {MOD_Op0Add, MOD_AdSizeR, 0}, 0, 64, 0, 1, {0xE0, 0, 0}, 0, 1, 483 },
+ { SUF_Z, NOT_64, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 0, {0, 0, 0}, 0, 2, 493 },
+ { SUF_Z, NOT_64, 0, 0, 0, {MOD_Op0Add, 0, 0}, 0, 64, 0, 1, {0xE0, 0, 0}, 0, 2, 495 }
+};
+
+static const x86_insn_info loopl_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {MOD_Gap, MOD_AdSizeR, 0}, 0, 64, 0, 0, {0, 0, 0}, 0, 1, 481 },
+ { SUF_Z, 0, 0, 0, 0, {MOD_Op0Add, MOD_AdSizeR, 0}, 0, 64, 0, 1, {0xE0, 0, 0}, 0, 1, 483 },
+ { SUF_Z, 0, CPU_386, 0, 0, {0, 0, 0}, 0, 64, 0, 0, {0, 0, 0}, 0, 2, 481 },
+ { SUF_Z, 0, CPU_386, 0, 0, {MOD_Op0Add, 0, 0}, 0, 64, 0, 1, {0xE0, 0, 0}, 0, 2, 483 }
+};
+
+static const x86_insn_info loopq_insn[] = {
+ { SUF_Z, ONLY_64, 0, 0, 0, {MOD_Gap, MOD_AdSizeR, 0}, 0, 64, 0, 0, {0, 0, 0}, 0, 1, 481 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op0Add, MOD_AdSizeR, 0}, 0, 64, 0, 1, {0xE0, 0, 0}, 0, 1, 483 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 0, 64, 0, 0, {0, 0, 0}, 0, 2, 489 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op0Add, 0, 0}, 0, 64, 0, 1, {0xE0, 0, 0}, 0, 2, 491 }
+};
+
+static const x86_insn_info setcc_insn[] = {
+ { SUF_B|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0x0F, 0x90, 0}, 2, 1, 323 }
+};
+
+static const x86_insn_info cmpsd_insn[] = {
+ { GAS_ILLEGAL|SUF_Z, NOT_AVX, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xA7, 0, 0}, 0, 0, 0 },
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0xF2, 2, {0x0F, 0xC2, 0}, 0, 3, 92 },
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0xF2, 2, {0x0F, 0xC2, 0}, 0, 3, 95 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC3, 2, {0x0F, 0xC2, 0}, 0, 4, 0 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC3, 2, {0x0F, 0xC2, 0}, 0, 4, 4 }
+};
+
+static const x86_insn_info movsd_insn[] = {
+ { SUF_Z, NOT_AVX, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0xA5, 0, 0}, 0, 0, 0 },
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0xF2, 2, {0x0F, 0x10, 0}, 0, 2, 92 },
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0xF2, 2, {0x0F, 0x10, 0}, 0, 2, 451 },
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0xF2, 2, {0x0F, 0x11, 0}, 0, 2, 47 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC3, 2, {0x0F, 0x10, 0}, 0, 3, 0 }
+};
+
+static const x86_insn_info bittest_insn[] = {
+ { SUF_W|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 16, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 260 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 32, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 266 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 64, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 272 },
+ { SUF_W|SUF_Z, 0, CPU_386, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 16, 0, 0, 2, {0x0F, 0xBA, 0}, 0, 2, 287 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 32, 0, 0, 2, {0x0F, 0xBA, 0}, 0, 2, 289 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_386, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 64, 0, 0, 2, {0x0F, 0xBA, 0}, 0, 2, 291 }
+};
+
+static const x86_insn_info bsfr_insn[] = {
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_Op1Add, 0, 0}, 16, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 98 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 32, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 101 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op1Add, 0, 0}, 64, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 104 }
+};
+
+static const x86_insn_info int_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xCD, 0, 0}, 0, 1, 3 }
+};
+
+static const x86_insn_info bound_insn[] = {
+ { SUF_W|SUF_Z, NOT_64, CPU_186, 0, 0, {0, 0, 0}, 16, 0, 0, 1, {0x62, 0, 0}, 0, 2, 465 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, 0, 0, {0, 0, 0}, 32, 0, 0, 1, {0x62, 0, 0}, 0, 2, 359 }
+};
+
+static const x86_insn_info larlsl_insn[] = {
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_Op1Add, 0, 0}, 16, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 455 },
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_Op1Add, 0, 0}, 16, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 98 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 32, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 457 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 32, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 459 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op1Add, 0, 0}, 64, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 461 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op1Add, 0, 0}, 64, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 463 }
+};
+
+static const x86_insn_info arpl_insn[] = {
+ { SUF_W|SUF_Z, NOT_64, CPU_286, CPU_Prot, 0, {0, 0, 0}, 0, 0, 0, 1, {0x63, 0, 0}, 0, 2, 260 }
+};
+
+static const x86_insn_info str_insn[] = {
+ { SUF_W|SUF_Z, 0, CPU_286, CPU_Prot, 0, {0, 0, 0}, 16, 0, 0, 2, {0x0F, 0x00, 0}, 1, 1, 395 },
+ { SUF_L|SUF_Z, 0, CPU_386, CPU_Prot, 0, {0, 0, 0}, 32, 0, 0, 2, {0x0F, 0x00, 0}, 1, 1, 26 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_286, CPU_Prot, 0, {0, 0, 0}, 64, 0, 0, 2, {0x0F, 0x00, 0}, 1, 1, 30 },
+ { SUF_L|SUF_W|SUF_Z, 0, CPU_286, CPU_Prot, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 1, 1, 99 }
+};
+
+static const x86_insn_info prot286_insn[] = {
+ { SUF_W|SUF_Z, 0, CPU_286, 0, 0, {MOD_SpAdd, MOD_Op1Add, 0}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 1, 99 }
+};
+
+static const x86_insn_info sldtmsw_insn[] = {
+ { SUF_W|SUF_Z, 0, CPU_286, 0, 0, {MOD_SpAdd, MOD_Op1Add, 0}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 1, 34 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_SpAdd, MOD_Op1Add, 0}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 1, 58 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_286, 0, 0, {MOD_SpAdd, MOD_Op1Add, 0}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 1, 6 },
+ { SUF_W|SUF_Z, 0, CPU_286, 0, 0, {MOD_SpAdd, MOD_Op1Add, 0}, 16, 0, 0, 2, {0x0F, 0x00, 0}, 0, 1, 395 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_SpAdd, MOD_Op1Add, 0}, 32, 0, 0, 2, {0x0F, 0x00, 0}, 0, 1, 26 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_286, 0, 0, {MOD_SpAdd, MOD_Op1Add, 0}, 64, 0, 0, 2, {0x0F, 0x00, 0}, 0, 1, 30 }
+};
+
+static const x86_insn_info fld_insn[] = {
+ { SUF_S|SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xD9, 0, 0}, 0, 1, 654 },
+ { SUF_L|SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xDD, 0, 0}, 0, 1, 212 },
+ { SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xDB, 0, 0}, 5, 1, 656 },
+ { SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0xD9, 0xC0, 0}, 0, 1, 328 }
+};
+
+static const x86_insn_info fstp_insn[] = {
+ { SUF_S|SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xD9, 0, 0}, 3, 1, 654 },
+ { SUF_L|SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xDD, 0, 0}, 3, 1, 212 },
+ { SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xDB, 0, 0}, 7, 1, 656 },
+ { SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0xDD, 0xD8, 0}, 0, 1, 328 }
+};
+
+static const x86_insn_info fldstpt_insn[] = {
+ { SUF_Z, 0, CPU_FPU, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 1, {0xDB, 0, 0}, 0, 1, 619 }
+};
+
+static const x86_insn_info fildstp_insn[] = {
+ { SUF_S|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 1, {0xDF, 0, 0}, 0, 1, 653 },
+ { SUF_L|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 1, {0xDB, 0, 0}, 0, 1, 654 },
+ { SUF_Q|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Gap, MOD_Op0Add, MOD_SpAdd}, 0, 0, 0, 1, {0xDD, 0, 0}, 0, 1, 212 },
+ { GAS_ONLY|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 1, {0xDF, 0, 0}, 0, 1, 34 }
+};
+
+static const x86_insn_info fbldstp_insn[] = {
+ { SUF_Z, 0, CPU_FPU, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 1, {0xDF, 0, 0}, 0, 1, 619 }
+};
+
+static const x86_insn_info fst_insn[] = {
+ { SUF_S|SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xD9, 0, 0}, 2, 1, 654 },
+ { SUF_L|SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xDD, 0, 0}, 2, 1, 212 },
+ { SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0xDD, 0xD0, 0}, 0, 1, 328 }
+};
+
+static const x86_insn_info fxch_insn[] = {
+ { SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0xD9, 0xC8, 0}, 0, 1, 328 },
+ { SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0xD9, 0xC8, 0}, 0, 2, 327 },
+ { SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0xD9, 0xC8, 0}, 0, 2, 329 },
+ { SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0xD9, 0xC9, 0}, 0, 0, 0 }
+};
+
+static const x86_insn_info fcom_insn[] = {
+ { SUF_S|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 0, 0, 0, 1, {0xD8, 0, 0}, 0, 1, 654 },
+ { SUF_L|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 0, 0, 0, 1, {0xDC, 0, 0}, 0, 1, 212 },
+ { SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0xD8, 0x00, 0}, 0, 1, 328 },
+ { GAS_ONLY|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Gap, MOD_SpAdd, 0}, 0, 0, 0, 1, {0xD8, 0, 0}, 0, 1, 58 },
+ { GAS_ONLY|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0xD8, 0x01, 0}, 0, 0, 0 },
+ { GAS_ILLEGAL|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0xD8, 0x00, 0}, 0, 2, 327 }
+};
+
+static const x86_insn_info fcom2_insn[] = {
+ { SUF_Z, 0, CPU_286, CPU_FPU, 0, {MOD_Op0Add, MOD_Op1Add, 0}, 0, 0, 0, 2, {0x00, 0x00, 0}, 0, 1, 328 },
+ { SUF_Z, 0, CPU_286, CPU_FPU, 0, {MOD_Op0Add, MOD_Op1Add, 0}, 0, 0, 0, 2, {0x00, 0x00, 0}, 0, 2, 327 }
+};
+
+static const x86_insn_info farith_insn[] = {
+ { SUF_S|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Gap, MOD_Gap, MOD_SpAdd}, 0, 0, 0, 1, {0xD8, 0, 0}, 0, 1, 654 },
+ { SUF_L|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Gap, MOD_Gap, MOD_SpAdd}, 0, 0, 0, 1, {0xDC, 0, 0}, 0, 1, 212 },
+ { SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Gap, MOD_Op1Add, 0}, 0, 0, 0, 2, {0xD8, 0x00, 0}, 0, 1, 328 },
+ { SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Gap, MOD_Op1Add, 0}, 0, 0, 0, 2, {0xD8, 0x00, 0}, 0, 2, 327 },
+ { SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0xDC, 0x00, 0}, 0, 1, 696 },
+ { GAS_ILLEGAL|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0xDC, 0x00, 0}, 0, 2, 329 },
+ { GAS_ONLY|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Gap, MOD_Op1Add, 0}, 0, 0, 0, 2, {0xDC, 0x00, 0}, 0, 2, 329 }
+};
+
+static const x86_insn_info farithp_insn[] = {
+ { SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0xDE, 0x01, 0}, 0, 0, 0 },
+ { SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0xDE, 0x00, 0}, 0, 1, 328 },
+ { SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0xDE, 0x00, 0}, 0, 2, 329 }
+};
+
+static const x86_insn_info fiarith_insn[] = {
+ { SUF_S|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_SpAdd, MOD_Op0Add, 0}, 0, 0, 0, 1, {0x04, 0, 0}, 0, 1, 653 },
+ { SUF_L|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_SpAdd, MOD_Op0Add, 0}, 0, 0, 0, 1, {0x00, 0, 0}, 0, 1, 654 }
+};
+
+static const x86_insn_info fldnstcw_insn[] = {
+ { SUF_W|SUF_Z, 0, CPU_FPU, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 1, {0xD9, 0, 0}, 0, 1, 34 }
+};
+
+static const x86_insn_info fstcw_insn[] = {
+ { SUF_W|SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x9B, 0xD9, 0}, 7, 1, 34 }
+};
+
+static const x86_insn_info fnstsw_insn[] = {
+ { SUF_W|SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 1, {0xDD, 0, 0}, 7, 1, 34 },
+ { SUF_W|SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0xDF, 0xE0, 0}, 0, 1, 343 }
+};
+
+static const x86_insn_info fstsw_insn[] = {
+ { SUF_W|SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x9B, 0xDD, 0}, 7, 1, 34 },
+ { SUF_W|SUF_Z, 0, CPU_FPU, 0, 0, {0, 0, 0}, 0, 0, 0, 3, {0x9B, 0xDF, 0xE0}, 0, 1, 343 }
+};
+
+static const x86_insn_info ffree_insn[] = {
+ { SUF_Z, 0, CPU_FPU, 0, 0, {MOD_Op0Add, 0, 0}, 0, 0, 0, 2, {0x00, 0xC0, 0}, 0, 1, 328 }
+};
+
+static const x86_insn_info bswap_insn[] = {
+ { SUF_L|SUF_Z, 0, CPU_486, 0, 0, {0, 0, 0}, 32, 0, 0, 2, {0x0F, 0xC8, 0}, 0, 1, 697 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 2, {0x0F, 0xC8, 0}, 0, 1, 698 }
+};
+
+static const x86_insn_info cmpxchgxadd_insn[] = {
+ { SUF_B|SUF_Z, 0, CPU_486, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 323 },
+ { SUF_W|SUF_Z, 0, CPU_486, 0, 0, {MOD_Op1Add, 0, 0}, 16, 0, 0, 2, {0x0F, 0x01, 0}, 0, 2, 260 },
+ { SUF_L|SUF_Z, 0, CPU_486, 0, 0, {MOD_Op1Add, 0, 0}, 32, 0, 0, 2, {0x0F, 0x01, 0}, 0, 2, 266 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_486, 0, 0, {MOD_Op1Add, 0, 0}, 64, 0, 0, 2, {0x0F, 0x01, 0}, 0, 2, 272 }
+};
+
+static const x86_insn_info cmpxchg8b_insn[] = {
+ { SUF_Q|SUF_Z, 0, CPU_586, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0xC7, 0}, 1, 1, 6 }
+};
+
+static const x86_insn_info cmovcc_insn[] = {
+ { SUF_W|SUF_Z, 0, CPU_686, 0, 0, {MOD_Op1Add, 0, 0}, 16, 0, 0, 2, {0x0F, 0x40, 0}, 0, 2, 98 },
+ { SUF_L|SUF_Z, 0, CPU_686, 0, 0, {MOD_Op1Add, 0, 0}, 32, 0, 0, 2, {0x0F, 0x40, 0}, 0, 2, 101 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_686, 0, 0, {MOD_Op1Add, 0, 0}, 64, 0, 0, 2, {0x0F, 0x40, 0}, 0, 2, 104 }
+};
+
+static const x86_insn_info fcmovcc_insn[] = {
+ { SUF_Z, 0, CPU_686, CPU_FPU, 0, {MOD_Op0Add, MOD_Op1Add, 0}, 0, 0, 0, 2, {0x00, 0x00, 0}, 0, 2, 327 }
+};
+
+static const x86_insn_info movnti_insn[] = {
+ { SUF_L|SUF_Z, 0, CPU_P4, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0xC3, 0}, 0, 2, 337 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_P4, 0, 0, {0, 0, 0}, 64, 0, 0, 2, {0x0F, 0xC3, 0}, 0, 2, 339 }
+};
+
+static const x86_insn_info clflush_insn[] = {
+ { SUF_Z, 0, CPU_P3, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0xAE, 0}, 7, 1, 50 }
+};
+
+static const x86_insn_info movd_insn[] = {
+ { SUF_Z, 0, CPU_386, CPU_MMX, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x6E, 0}, 0, 2, 293 },
+ { SUF_Z, ONLY_64, CPU_MMX, 0, 0, {0, 0, 0}, 64, 0, 0, 2, {0x0F, 0x6E, 0}, 0, 2, 295 },
+ { SUF_Z, 0, CPU_386, CPU_MMX, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x7E, 0}, 0, 2, 294 },
+ { SUF_Z, ONLY_64, CPU_MMX, 0, 0, {0, 0, 0}, 64, 0, 0, 2, {0x0F, 0x7E, 0}, 0, 2, 297 },
+ { SUF_Z, 0, CPU_386, CPU_SSE2, 0, {0, 0, 0}, 0, 0, 0x66, 2, {0x0F, 0x6E, 0}, 0, 2, 299 },
+ { SUF_Z, ONLY_64, CPU_SSE2, 0, 0, {0, 0, 0}, 64, 0, 0x66, 2, {0x0F, 0x6E, 0}, 0, 2, 301 },
+ { SUF_Z, 0, CPU_386, CPU_SSE2, 0, {0, 0, 0}, 0, 0, 0x66, 2, {0x0F, 0x7E, 0}, 0, 2, 188 },
+ { SUF_Z, ONLY_64, CPU_SSE2, 0, 0, {0, 0, 0}, 64, 0, 0x66, 2, {0x0F, 0x7E, 0}, 0, 2, 182 }
+};
+
+static const x86_insn_info movq_insn[] = {
+ { GAS_ILLEGAL|SUF_Z, 0, CPU_MMX, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x6F, 0}, 0, 2, 140 },
+ { GAS_ILLEGAL|SUF_Z, ONLY_64, CPU_MMX, 0, 0, {0, 0, 0}, 64, 0, 0, 2, {0x0F, 0x6E, 0}, 0, 2, 295 },
+ { GAS_ILLEGAL|SUF_Z, 0, CPU_MMX, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x7F, 0}, 0, 2, 331 },
+ { GAS_ILLEGAL|SUF_Z, ONLY_64, CPU_MMX, 0, 0, {0, 0, 0}, 64, 0, 0, 2, {0x0F, 0x7E, 0}, 0, 2, 297 },
+ { GAS_ILLEGAL|SUF_Z, 0, CPU_SSE2, 0, 0, {0, 0, 0}, 0, 0, 0xF3, 2, {0x0F, 0x7E, 0}, 0, 2, 64 },
+ { GAS_ILLEGAL|SUF_Z, 0, CPU_SSE2, 0, 0, {0, 0, 0}, 0, 0, 0xF3, 2, {0x0F, 0x7E, 0}, 0, 2, 333 },
+ { GAS_ILLEGAL|SUF_Z, ONLY_64, CPU_SSE2, 0, 0, {0, 0, 0}, 64, 0, 0x66, 2, {0x0F, 0x6E, 0}, 0, 2, 301 },
+ { GAS_ILLEGAL|SUF_Z, 0, CPU_SSE2, 0, 0, {0, 0, 0}, 0, 0, 0x66, 2, {0x0F, 0xD6, 0}, 0, 2, 335 },
+ { GAS_ILLEGAL|SUF_Z, ONLY_64, CPU_SSE2, 0, 0, {0, 0, 0}, 64, 0, 0x66, 2, {0x0F, 0x7E, 0}, 0, 2, 182 }
+};
+
+static const x86_insn_info mmxsse2_insn[] = {
+ { SUF_Z, 0, CPU_MMX, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 140 },
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0x66, 2, {0x0F, 0x00, 0}, 0, 2, 155 }
+};
+
+static const x86_insn_info pshift_insn[] = {
+ { SUF_Z, 0, CPU_MMX, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 140 },
+ { SUF_Z, 0, CPU_MMX, 0, 0, {MOD_Gap, MOD_Op1Add, MOD_SpAdd}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 162 },
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0x66, 2, {0x0F, 0x00, 0}, 0, 2, 155 },
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_Gap, MOD_Op1Add, MOD_SpAdd}, 0, 0, 0x66, 2, {0x0F, 0x00, 0}, 0, 2, 2 }
+};
+
+static const x86_insn_info vpshift_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0xC1, 2, {0x0F, 0x00, 0}, 0, 2, 158 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Gap, MOD_Op1Add, MOD_SpAdd}, 0, 0, 0xC1, 2, {0x0F, 0x00, 0}, 0, 2, 511 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0xC1, 2, {0x0F, 0x00, 0}, 0, 3, 12 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Gap, MOD_Op1Add, MOD_SpAdd}, 0, 0, 0xC1, 2, {0x0F, 0x00, 0}, 0, 3, 1 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0xC5, 2, {0x0F, 0x00, 0}, 0, 2, 639 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Gap, MOD_Op1Add, MOD_SpAdd}, 0, 0, 0xC5, 2, {0x0F, 0x00, 0}, 0, 2, 513 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0xC5, 2, {0x0F, 0x00, 0}, 0, 3, 8 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Gap, MOD_Op1Add, MOD_SpAdd}, 0, 0, 0xC5, 2, {0x0F, 0x00, 0}, 0, 3, 200 }
+};
+
+static const x86_insn_info xmm_xmm128_256_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 158 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 3, 12 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC4, 2, {0x0F, 0x00, 0}, 0, 2, 197 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC4, 2, {0x0F, 0x00, 0}, 0, 3, 16 }
+};
+
+static const x86_insn_info xmm_xmm128_256avx2_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 158 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 3, 12 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC4, 2, {0x0F, 0x00, 0}, 0, 2, 197 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC4, 2, {0x0F, 0x00, 0}, 0, 3, 16 }
+};
+
+static const x86_insn_info xmm_xmm128_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 158 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 3, 12 }
+};
+
+static const x86_insn_info cvt_rx_xmm32_insn[] = {
+ { SUF_L|SUF_Z, 0, CPU_386, CPU_SSE, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 164 },
+ { SUF_L|SUF_Z, 0, CPU_386, CPU_SSE, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 359 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 64, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 170 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 64, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 361 }
+};
+
+static const x86_insn_info cvt_mm_xmm64_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 315 },
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 317 }
+};
+
+static const x86_insn_info cvt_xmm_mm_ps_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 333 }
+};
+
+static const x86_insn_info cvt_xmm_rmx_insn[] = {
+ { SUF_L|SUF_Z, 0, CPU_386, CPU_SSE, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 649 },
+ { SUF_L|SUF_Z, NOT_64, CPU_386, CPU_SSE, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 239 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 64, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 651 },
+ { SUF_L|SUF_Z, ONLY_AVX|NOT_64, CPU_386, CPU_AVX, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 3, 88 },
+ { SUF_L|SUF_Z, ONLY_AVX, CPU_386, CPU_AVX, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 3, 281 },
+ { SUF_Q|SUF_Z, ONLY_64|ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 64, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 3, 284 }
+};
+
+static const x86_insn_info xmm_xmm32_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 92 },
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 146 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 3, 0 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 3, 56 }
+};
+
+static const x86_insn_info ssecmp_128_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_Imm8, MOD_PreAdd, MOD_SetVEX}, 0, 0, 0, 2, {0x0F, 0xC2, 0}, 0, 2, 158 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Imm8, MOD_PreAdd, 0}, 0, 0, 0xC0, 2, {0x0F, 0xC2, 0}, 0, 3, 12 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Imm8, MOD_PreAdd, 0}, 0, 0, 0xC4, 2, {0x0F, 0xC2, 0}, 0, 3, 16 }
+};
+
+static const x86_insn_info ssecmp_32_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_Imm8, MOD_PreAdd, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0xC2, 0}, 0, 2, 92 },
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_Imm8, MOD_PreAdd, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0xC2, 0}, 0, 2, 146 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Imm8, MOD_PreAdd, 0}, 0, 0, 0xC0, 2, {0x0F, 0xC2, 0}, 0, 3, 0 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Imm8, MOD_PreAdd, 0}, 0, 0, 0xC0, 2, {0x0F, 0xC2, 0}, 0, 3, 56 }
+};
+
+static const x86_insn_info xmm_xmm128_imm_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 3, 185 }
+};
+
+static const x86_insn_info xmm_xmm128_imm_256avx2_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 3, 185 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC4, 2, {0x0F, 0x00, 0}, 0, 3, 191 }
+};
+
+static const x86_insn_info xmm_xmm128_imm_256_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 3, 158 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 4, 60 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC4, 2, {0x0F, 0x00, 0}, 0, 4, 20 }
+};
+
+static const x86_insn_info xmm_xmm32_imm_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 3, 92 },
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 3, 146 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 4, 0 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 4, 56 }
+};
+
+static const x86_insn_info ldstmxcsr_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_SpAdd, MOD_SetVEX, 0}, 0, 0, 0, 2, {0x0F, 0xAE, 0}, 0, 1, 58 }
+};
+
+static const x86_insn_info maskmovq_insn[] = {
+ { SUF_Z, 0, CPU_MMX, CPU_P3, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0xF7, 0}, 0, 2, 641 }
+};
+
+static const x86_insn_info movau_insn[] = {
+ { SUF_Z, NOT_AVX, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 155 },
+ { SUF_Z, NOT_AVX, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_Op1Add}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 485 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 2, 155 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_Op1Add}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 2, 485 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC4, 2, {0x0F, 0x00, 0}, 0, 2, 191 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_Op1Add}, 0, 0, 0xC4, 2, {0x0F, 0x00, 0}, 0, 2, 487 }
+};
+
+static const x86_insn_info movhllhps_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_Op1Add, MOD_SetVEX, 0}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 92 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 3, 0 }
+};
+
+static const x86_insn_info movhlp_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 95 },
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x01, 0}, 0, 2, 47 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 3, 4 }
+};
+
+static const x86_insn_info movmsk_insn[] = {
+ { SUF_L|SUF_Z, 0, CPU_386, CPU_SSE, 0, {MOD_PreAdd, MOD_SetVEX, 0}, 0, 0, 0x00, 2, {0x0F, 0x50, 0}, 0, 2, 164 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_SetVEX, 0}, 64, 0, 0x00, 2, {0x0F, 0x50, 0}, 0, 2, 170 },
+ { SUF_L|SUF_Z, ONLY_AVX, CPU_386, CPU_AVX, 0, {MOD_PreAdd, 0, 0}, 0, 0, 0xC4, 2, {0x0F, 0x50, 0}, 0, 2, 319 },
+ { SUF_Q|SUF_Z, ONLY_64|ONLY_AVX, CPU_SSE, 0, 0, {MOD_PreAdd, 0, 0}, 64, 0, 0xC4, 2, {0x0F, 0x50, 0}, 0, 2, 321 }
+};
+
+static const x86_insn_info movnt_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 599 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC4, 2, {0x0F, 0x00, 0}, 0, 2, 601 }
+};
+
+static const x86_insn_info movntq_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0xE7, 0}, 0, 2, 363 }
+};
+
+static const x86_insn_info movss_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0xF3, 2, {0x0F, 0x10, 0}, 0, 2, 92 },
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0xF3, 2, {0x0F, 0x10, 0}, 0, 2, 336 },
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0xF3, 2, {0x0F, 0x11, 0}, 0, 2, 450 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC2, 2, {0x0F, 0x10, 0}, 0, 3, 0 }
+};
+
+static const x86_insn_info pextrw_insn[] = {
+ { SUF_L|SUF_Z, NOT_AVX, CPU_MMX, CPU_P3, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0xC5, 0}, 0, 3, 161 },
+ { SUF_L|SUF_Z, 0, CPU_386, CPU_SSE2, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 2, {0x0F, 0xC5, 0}, 0, 3, 164 },
+ { SUF_Q|SUF_Z, ONLY_64|NOT_AVX, CPU_MMX, CPU_P3, 0, {0, 0, 0}, 64, 0, 0, 2, {0x0F, 0xC5, 0}, 0, 3, 167 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_SSE2, 0, 0, {MOD_SetVEX, 0, 0}, 64, 0, 0x66, 2, {0x0F, 0xC5, 0}, 0, 3, 170 },
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x15}, 0, 3, 173 },
+ { SUF_Z, 0, CPU_386, CPU_SSE41, 0, {MOD_SetVEX, 0, 0}, 32, 0, 0x66, 3, {0x0F, 0x3A, 0x15}, 0, 3, 176 },
+ { SUF_Z, ONLY_64, CPU_SSE41, 0, 0, {MOD_SetVEX, 0, 0}, 64, 0, 0x66, 3, {0x0F, 0x3A, 0x15}, 0, 3, 179 }
+};
+
+static const x86_insn_info pinsrw_insn[] = {
+ { SUF_L|SUF_Z, NOT_AVX, CPU_MMX, CPU_P3, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0xC4, 0}, 0, 3, 116 },
+ { SUF_Q|SUF_Z, ONLY_64|NOT_AVX, CPU_MMX, CPU_P3, 0, {0, 0, 0}, 64, 64, 0, 2, {0x0F, 0xC4, 0}, 0, 3, 119 },
+ { SUF_L|SUF_Z, NOT_AVX, CPU_MMX, CPU_P3, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0xC4, 0}, 0, 3, 122 },
+ { SUF_L|SUF_Z, 0, CPU_386, CPU_SSE2, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 2, {0x0F, 0xC4, 0}, 0, 3, 125 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_SSE2, 0, 0, {MOD_SetVEX, 0, 0}, 64, 64, 0x66, 2, {0x0F, 0xC4, 0}, 0, 3, 128 },
+ { SUF_L|SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 2, {0x0F, 0xC4, 0}, 0, 3, 131 },
+ { SUF_L|SUF_Z, ONLY_AVX, CPU_386, CPU_AVX, 0, {0, 0, 0}, 0, 0, 0xC1, 2, {0x0F, 0xC4, 0}, 0, 4, 24 },
+ { SUF_Q|SUF_Z, ONLY_64|ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 64, 64, 0xC1, 2, {0x0F, 0xC4, 0}, 0, 4, 28 },
+ { SUF_L|SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC1, 2, {0x0F, 0xC4, 0}, 0, 4, 32 }
+};
+
+static const x86_insn_info pmovmskb_insn[] = {
+ { SUF_L|SUF_Z, NOT_AVX, CPU_MMX, CPU_P3, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0xD7, 0}, 0, 2, 161 },
+ { SUF_L|SUF_Z, 0, CPU_386, CPU_SSE2, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 2, {0x0F, 0xD7, 0}, 0, 2, 164 },
+ { SUF_L|SUF_Z, ONLY_AVX, CPU_386, CPU_AVX2, 0, {0, 0, 0}, 0, 0, 0xC5, 2, {0x0F, 0xD7, 0}, 0, 2, 319 },
+ { SUF_Q|SUF_Z, ONLY_64|NOT_AVX, CPU_MMX, CPU_P3, 0, {0, 0, 0}, 64, 64, 0, 2, {0x0F, 0xD7, 0}, 0, 2, 167 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_SSE2, 0, 0, {MOD_SetVEX, 0, 0}, 64, 64, 0x66, 2, {0x0F, 0xD7, 0}, 0, 2, 170 },
+ { SUF_Q|SUF_Z, ONLY_64|ONLY_AVX, CPU_SSE2, 0, 0, {0, 0, 0}, 64, 64, 0xC5, 2, {0x0F, 0xD7, 0}, 0, 2, 321 }
+};
+
+static const x86_insn_info pshufw_insn[] = {
+ { SUF_Z, 0, CPU_MMX, CPU_P3, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x70, 0}, 0, 3, 140 }
+};
+
+static const x86_insn_info xmm_xmm64_insn[] = {
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 92 },
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 95 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 3, 0 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 3, 4 }
+};
+
+static const x86_insn_info ssecmp_64_insn[] = {
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_Imm8, MOD_PreAdd, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0xC2, 0}, 0, 2, 92 },
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_Imm8, MOD_PreAdd, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0xC2, 0}, 0, 2, 95 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Imm8, MOD_PreAdd, 0}, 0, 0, 0xC0, 2, {0x0F, 0xC2, 0}, 0, 3, 0 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Imm8, MOD_PreAdd, 0}, 0, 0, 0xC0, 2, {0x0F, 0xC2, 0}, 0, 3, 4 }
+};
+
+static const x86_insn_info cvt_rx_xmm64_insn[] = {
+ { SUF_L|SUF_Z, 0, CPU_386, CPU_SSE2, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 164 },
+ { SUF_L|SUF_Z, 0, CPU_386, CPU_SSE2, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 338 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_SSE2, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 64, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 170 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_SSE2, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_SetVEX}, 64, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 469 }
+};
+
+static const x86_insn_info cvt_mm_xmm_insn[] = {
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 615 }
+};
+
+static const x86_insn_info cvt_xmm_mm_ss_insn[] = {
+ { SUF_Z, 0, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 2, 333 }
+};
+
+static const x86_insn_info eptvpid_insn[] = {
+ { SUF_L|SUF_Z, NOT_64, CPU_386, CPU_EPTVPID, 0, {MOD_Op2Add, 0, 0}, 32, 0, 0x66, 3, {0x0F, 0x38, 0x80}, 0, 2, 611 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_EPTVPID, 0, 0, {MOD_Op2Add, 0, 0}, 64, 0, 0x66, 3, {0x0F, 0x38, 0x80}, 0, 2, 613 }
+};
+
+static const x86_insn_info vmxmemrd_insn[] = {
+ { SUF_L|SUF_Z, NOT_64, CPU_P4, 0, 0, {0, 0, 0}, 32, 0, 0, 2, {0x0F, 0x78, 0}, 0, 2, 266 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_P4, 0, 0, {0, 0, 0}, 64, 64, 0, 2, {0x0F, 0x78, 0}, 0, 2, 272 }
+};
+
+static const x86_insn_info vmxmemwr_insn[] = {
+ { SUF_L|SUF_Z, NOT_64, CPU_P4, 0, 0, {0, 0, 0}, 32, 0, 0, 2, {0x0F, 0x79, 0}, 0, 2, 101 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_P4, 0, 0, {0, 0, 0}, 64, 64, 0, 2, {0x0F, 0x79, 0}, 0, 2, 104 }
+};
+
+static const x86_insn_info vmxtwobytemem_insn[] = {
+ { SUF_Z, 0, CPU_P4, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0, 2, {0x0F, 0xC7, 0}, 0, 1, 6 }
+};
+
+static const x86_insn_info vmxthreebytemem_insn[] = {
+ { SUF_Z, 0, CPU_P4, 0, 0, {MOD_PreAdd, 0, 0}, 0, 0, 0x00, 2, {0x0F, 0xC7, 0}, 6, 1, 6 }
+};
+
+static const x86_insn_info maskmovdqu_insn[] = {
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 2, {0x0F, 0xF7, 0}, 0, 2, 64 }
+};
+
+static const x86_insn_info movdq2q_insn[] = {
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {0, 0, 0}, 0, 0, 0xF2, 2, {0x0F, 0xD6, 0}, 0, 2, 315 }
+};
+
+static const x86_insn_info movq2dq_insn[] = {
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {0, 0, 0}, 0, 0, 0xF3, 2, {0x0F, 0xD6, 0}, 0, 2, 445 }
+};
+
+static const x86_insn_info pslrldq_insn[] = {
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_SpAdd, MOD_SetVEX, 0}, 0, 0, 0x66, 2, {0x0F, 0x73, 0}, 0, 2, 511 },
+ { SUF_Z, 0, CPU_SSE2, 0, 0, {MOD_SpAdd, MOD_SetVEX, 0}, 0, 0, 0x66, 2, {0x0F, 0x73, 0}, 0, 3, 1 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0xC5, 2, {0x0F, 0x73, 0}, 0, 2, 513 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_SpAdd, 0, 0}, 0, 0, 0xC5, 2, {0x0F, 0x73, 0}, 0, 3, 200 }
+};
+
+static const x86_insn_info lddqu_insn[] = {
+ { SUF_Z, 0, CPU_SSE3, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0xF2, 2, {0x0F, 0xF0, 0}, 0, 2, 595 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC7, 2, {0x0F, 0xF0, 0}, 0, 2, 597 }
+};
+
+static const x86_insn_info ssse3_insn[] = {
+ { SUF_Z, NOT_AVX, CPU_SSSE3, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0, 3, {0x0F, 0x38, 0x00}, 0, 2, 140 },
+ { SUF_Z, 0, CPU_SSSE3, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x38, 0x00}, 0, 2, 158 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x00}, 0, 3, 12 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 2, 197 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 3, 16 }
+};
+
+static const x86_insn_info ssse3imm_insn[] = {
+ { SUF_Z, 0, CPU_SSSE3, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0, 3, {0x0F, 0x3A, 0x00}, 0, 3, 140 },
+ { SUF_Z, 0, CPU_SSSE3, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x00}, 0, 3, 185 }
+};
+
+static const x86_insn_info sse4_insn[] = {
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x38, 0x00}, 0, 2, 155 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 2, 191 }
+};
+
+static const x86_insn_info sse4imm_256_insn[] = {
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x00}, 0, 3, 158 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 60 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x3A, 0x00}, 0, 3, 197 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x3A, 0x00}, 0, 4, 20 }
+};
+
+static const x86_insn_info sse4imm_256avx2_insn[] = {
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x00}, 0, 3, 158 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 60 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x3A, 0x00}, 0, 3, 197 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x3A, 0x00}, 0, 4, 20 }
+};
+
+static const x86_insn_info sse4imm_insn[] = {
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x00}, 0, 3, 158 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 60 }
+};
+
+static const x86_insn_info sse4m32imm_insn[] = {
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x00}, 0, 3, 92 },
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x00}, 0, 3, 146 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 0 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 56 }
+};
+
+static const x86_insn_info sse4m64imm_insn[] = {
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x00}, 0, 3, 92 },
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x00}, 0, 3, 95 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 0 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 4 }
+};
+
+static const x86_insn_info sse4xmm0_insn[] = {
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x38, 0x00}, 0, 2, 155 },
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x38, 0x00}, 0, 3, 242 }
+};
+
+static const x86_insn_info avx_sse4xmm0_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 12 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x3A, 0x00}, 0, 4, 16 }
+};
+
+static const x86_insn_info avx2_sse4xmm0_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 12 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x3A, 0x00}, 0, 4, 16 }
+};
+
+static const x86_insn_info crc32_insn[] = {
+ { SUF_B|SUF_Z, 0, CPU_386, CPU_SSE42, 0, {0, 0, 0}, 0, 0, 0xF2, 3, {0x0F, 0x38, 0xF0}, 0, 2, 537 },
+ { SUF_W|SUF_Z, 0, CPU_386, CPU_SSE42, 0, {0, 0, 0}, 16, 0, 0xF2, 3, {0x0F, 0x38, 0xF1}, 0, 2, 539 },
+ { SUF_L|SUF_Z, 0, CPU_386, CPU_SSE42, 0, {0, 0, 0}, 32, 0, 0xF2, 3, {0x0F, 0x38, 0xF1}, 0, 2, 101 },
+ { SUF_B|SUF_Z, ONLY_64, CPU_SSE42, 0, 0, {0, 0, 0}, 64, 0, 0xF2, 3, {0x0F, 0x38, 0xF0}, 0, 2, 541 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_SSE42, 0, 0, {0, 0, 0}, 64, 0, 0xF2, 3, {0x0F, 0x38, 0xF1}, 0, 2, 104 }
+};
+
+static const x86_insn_info extractps_insn[] = {
+ { SUF_Z, 0, CPU_386, CPU_SSE41, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x17}, 0, 3, 188 },
+ { SUF_Z, ONLY_64, CPU_SSE41, 0, 0, {MOD_SetVEX, 0, 0}, 64, 0, 0x66, 3, {0x0F, 0x3A, 0x17}, 0, 3, 179 }
+};
+
+static const x86_insn_info insertps_insn[] = {
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x21}, 0, 3, 146 },
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x21}, 0, 3, 92 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x21}, 0, 4, 56 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x21}, 0, 4, 0 }
+};
+
+static const x86_insn_info movntdqa_insn[] = {
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x38, 0x2A}, 0, 2, 595 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x2A}, 0, 2, 597 }
+};
+
+static const x86_insn_info sse4pcmpstr_insn[] = {
+ { SUF_Z, 0, CPU_SSE42, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x00}, 0, 3, 185 }
+};
+
+static const x86_insn_info pextrb_insn[] = {
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x14}, 0, 3, 194 },
+ { SUF_Z, 0, CPU_386, CPU_SSE41, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x14}, 0, 3, 176 },
+ { SUF_Z, ONLY_64, CPU_SSE41, 0, 0, {MOD_SetVEX, 0, 0}, 64, 0, 0x66, 3, {0x0F, 0x3A, 0x14}, 0, 3, 179 }
+};
+
+static const x86_insn_info pextrd_insn[] = {
+ { SUF_Z, 0, CPU_386, CPU_SSE41, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x16}, 0, 3, 188 }
+};
+
+static const x86_insn_info pextrq_insn[] = {
+ { SUF_Z, ONLY_64, CPU_SSE41, 0, 0, {MOD_SetVEX, 0, 0}, 64, 0, 0x66, 3, {0x0F, 0x3A, 0x16}, 0, 3, 182 }
+};
+
+static const x86_insn_info pinsrb_insn[] = {
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x20}, 0, 3, 143 },
+ { SUF_Z, 0, CPU_386, CPU_SSE41, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x20}, 0, 3, 125 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x20}, 0, 4, 48 },
+ { SUF_Z, ONLY_AVX, CPU_386, CPU_AVX, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x20}, 0, 4, 52 }
+};
+
+static const x86_insn_info pinsrd_insn[] = {
+ { SUF_Z, 0, CPU_386, CPU_SSE41, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x22}, 0, 3, 239 },
+ { SUF_Z, ONLY_AVX, CPU_386, CPU_AVX, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x22}, 0, 4, 88 }
+};
+
+static const x86_insn_info pinsrq_insn[] = {
+ { SUF_Z, ONLY_64, CPU_SSE41, 0, 0, {MOD_SetVEX, 0, 0}, 64, 0, 0x66, 3, {0x0F, 0x3A, 0x22}, 0, 3, 227 },
+ { SUF_Z, ONLY_64|ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 64, 0, 0xC1, 3, {0x0F, 0x3A, 0x22}, 0, 4, 84 }
+};
+
+static const x86_insn_info sse4m16_insn[] = {
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x38, 0x00}, 0, 2, 447 },
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x38, 0x00}, 0, 2, 64 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 2, 449 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 2, 208 }
+};
+
+static const x86_insn_info sse4m32_insn[] = {
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x38, 0x00}, 0, 2, 336 },
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x38, 0x00}, 0, 2, 64 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 2, 479 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 2, 208 }
+};
+
+static const x86_insn_info sse4m64_insn[] = {
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x38, 0x00}, 0, 2, 451 },
+ { SUF_Z, 0, CPU_SSE41, 0, 0, {MOD_Op2Add, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x38, 0x00}, 0, 2, 64 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 2, 509 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 2, 208 }
+};
+
+static const x86_insn_info cnt_insn[] = {
+ { SUF_W|SUF_Z, 0, 0, 0, 0, {MOD_Op1Add, 0, 0}, 16, 0, 0xF3, 2, {0x0F, 0x00, 0}, 0, 2, 98 },
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_Op1Add, 0, 0}, 32, 0, 0xF3, 2, {0x0F, 0x00, 0}, 0, 2, 101 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_Op1Add, 0, 0}, 64, 0, 0xF3, 2, {0x0F, 0x00, 0}, 0, 2, 104 }
+};
+
+static const x86_insn_info vmovd_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_386, CPU_AVX, 0, {0, 0, 0}, 0, 0, 0xC1, 2, {0x0F, 0x6E, 0}, 0, 2, 299 },
+ { SUF_Z, ONLY_AVX, CPU_386, CPU_AVX, 0, {0, 0, 0}, 0, 0, 0xC1, 2, {0x0F, 0x7E, 0}, 0, 2, 188 }
+};
+
+static const x86_insn_info vmovq_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC2, 2, {0x0F, 0x7E, 0}, 0, 2, 64 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC2, 2, {0x0F, 0x7E, 0}, 0, 2, 451 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC1, 2, {0x0F, 0xD6, 0}, 0, 2, 47 },
+ { SUF_Z, ONLY_64|ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 64, 0, 0xC1, 2, {0x0F, 0x6E, 0}, 0, 2, 301 },
+ { SUF_Z, ONLY_64|ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 64, 0, 0xC1, 2, {0x0F, 0x7E, 0}, 0, 2, 182 }
+};
+
+static const x86_insn_info avx_xmm_xmm128_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 2, 155 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC4, 2, {0x0F, 0x00, 0}, 0, 2, 191 }
+};
+
+static const x86_insn_info avx_sse4imm_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_SSE41, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 3, 185 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 3, 185 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x3A, 0x00}, 0, 3, 191 }
+};
+
+static const x86_insn_info vmovddup_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 2, 64 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 2, 451 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC4, 2, {0x0F, 0x00, 0}, 0, 2, 191 }
+};
+
+static const x86_insn_info avx_xmm_xmm64_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_SSE2, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 2, 64 },
+ { SUF_Z, ONLY_AVX, CPU_SSE2, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 2, 451 }
+};
+
+static const x86_insn_info avx_xmm_xmm32_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 2, 64 },
+ { SUF_Z, ONLY_AVX, CPU_SSE, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 2, 336 }
+};
+
+static const x86_insn_info avx_cvt_xmm64_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 2, 64 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 2, 451 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC4, 2, {0x0F, 0x00, 0}, 0, 2, 453 }
+};
+
+static const x86_insn_info avx_ssse3_2op_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x00}, 0, 2, 155 }
+};
+
+static const x86_insn_info avx2_ssse3_2op_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x00}, 0, 2, 155 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 2, 191 }
+};
+
+static const x86_insn_info avx_cvt_xmm128_x_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 2, 155 }
+};
+
+static const x86_insn_info avx_cvt_xmm128_y_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC4, 2, {0x0F, 0x00, 0}, 0, 2, 205 }
+};
+
+static const x86_insn_info avx_cvt_xmm128_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC0, 2, {0x0F, 0x00, 0}, 0, 2, 607 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_PreAdd, MOD_Op1Add, 0}, 0, 0, 0xC4, 2, {0x0F, 0x00, 0}, 0, 2, 609 }
+};
+
+static const x86_insn_info vbroadcastss_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x18}, 0, 2, 336 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x18}, 0, 2, 449 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x18}, 0, 2, 64 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x18}, 0, 2, 208 }
+};
+
+static const x86_insn_info vbroadcastsd_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x19}, 0, 2, 479 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x19}, 0, 2, 208 }
+};
+
+static const x86_insn_info vbroadcastif128_insn[] = {
+ { SUF_Z, ONLY_AVX, 0, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 2, 509 }
+};
+
+static const x86_insn_info vextractif128_insn[] = {
+ { SUF_Z, ONLY_AVX, 0, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x3A, 0x00}, 0, 3, 236 }
+};
+
+static const x86_insn_info vinsertif128_insn[] = {
+ { SUF_Z, ONLY_AVX, 0, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x3A, 0x00}, 0, 4, 8 }
+};
+
+static const x86_insn_info vzero_insn[] = {
+ { SUF_Z, 0, CPU_AVX, 0, 0, {MOD_SetVEX, 0, 0}, 0, 0, 0, 2, {0x0F, 0x77, 0}, 0, 0, 0 }
+};
+
+static const x86_insn_info vmaskmov_insn[] = {
+ { SUF_Z, ONLY_AVX, 0, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x00}, 0, 3, 12 },
+ { SUF_Z, ONLY_AVX, 0, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 3, 16 },
+ { SUF_Z, ONLY_AVX, 0, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x02}, 0, 3, 203 },
+ { SUF_Z, ONLY_AVX, 0, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x02}, 0, 3, 206 }
+};
+
+static const x86_insn_info vpermil_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x08}, 0, 3, 12 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x08}, 0, 3, 16 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 3, 185 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x3A, 0x00}, 0, 3, 191 }
+};
+
+static const x86_insn_info vperm2f128_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, 0, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x3A, 0x06}, 0, 4, 20 }
+};
+
+static const x86_insn_info vperm_var_avx2_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 3, 16 }
+};
+
+static const x86_insn_info vperm_imm_avx2_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xCD, 3, {0x0F, 0x3A, 0x00}, 0, 3, 191 }
+};
+
+static const x86_insn_info vperm2i128_avx2_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x3A, 0x46}, 0, 4, 20 }
+};
+
+static const x86_insn_info vpbroadcastb_avx2_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x78}, 0, 2, 543 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x78}, 0, 2, 545 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x78}, 0, 2, 635 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x78}, 0, 2, 637 }
+};
+
+static const x86_insn_info vpbroadcastw_avx2_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x79}, 0, 2, 543 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x79}, 0, 2, 545 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x79}, 0, 2, 547 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x79}, 0, 2, 549 }
+};
+
+static const x86_insn_info vpbroadcastd_avx2_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x58}, 0, 2, 543 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x58}, 0, 2, 545 },
+ { SUF_Z, ONLY_AVX, CPU_386, CPU_AVX2, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x58}, 0, 2, 299 },
+ { SUF_Z, ONLY_AVX, CPU_386, CPU_AVX2, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x58}, 0, 2, 643 }
+};
+
+static const x86_insn_info vpbroadcastq_avx2_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x59}, 0, 2, 543 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x59}, 0, 2, 545 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x59}, 0, 2, 333 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {0, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x59}, 0, 2, 621 }
+};
+
+static const x86_insn_info vpshiftv_vexw0_avx2_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x00}, 0, 3, 12 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 3, 16 }
+};
+
+static const x86_insn_info vpshiftv_vexw1_avx2_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC9, 3, {0x0F, 0x38, 0x00}, 0, 3, 12 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xCD, 3, {0x0F, 0x38, 0x00}, 0, 3, 16 }
+};
+
+static const x86_insn_info vmaskmov_vexw1_avx2_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC9, 3, {0x0F, 0x38, 0x00}, 0, 3, 12 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xCD, 3, {0x0F, 0x38, 0x00}, 0, 3, 16 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC9, 3, {0x0F, 0x38, 0x02}, 0, 3, 203 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xCD, 3, {0x0F, 0x38, 0x02}, 0, 3, 206 }
+};
+
+static const x86_insn_info vex_66_0F3A_imm8_avx2_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 60 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x3A, 0x00}, 0, 4, 20 }
+};
+
+static const x86_insn_info gather_64x_64x_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC9, 3, {0x0F, 0x38, 0x00}, 0, 3, 221 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xCD, 3, {0x0F, 0x38, 0x00}, 0, 3, 224 }
+};
+
+static const x86_insn_info gather_64x_64y_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC9, 3, {0x0F, 0x38, 0x00}, 0, 3, 221 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xCD, 3, {0x0F, 0x38, 0x00}, 0, 3, 278 }
+};
+
+static const x86_insn_info gather_32x_32y_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x00}, 0, 3, 245 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 3, 251 }
+};
+
+static const x86_insn_info gather_32x_32y_128_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x00}, 0, 3, 245 },
+ { SUF_Z, ONLY_AVX, CPU_AVX2, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 3, 248 }
+};
+
+static const x86_insn_info tsx_xabort_insn[] = {
+ { SUF_Z, 0, CPU_TSX, 0, 0, {0, 0, 0}, 0, 0, 0, 2, {0xC6, 0xF8, 0}, 0, 1, 3 }
+};
+
+static const x86_insn_info tsx_xbegin_insn[] = {
+ { SUF_Z, 0, CPU_386, CPU_TSX, 0, {0, 0, 0}, 0, 0, 0, 2, {0xC7, 0xF8, 0}, 0, 1, 679 },
+ { SUF_Z, NOT_64, CPU_TSX, 0, 0, {0, 0, 0}, 16, 0, 0, 2, {0xC7, 0xF8, 0}, 0, 1, 678 }
+};
+
+static const x86_insn_info tsx_0x0F_0x01_insn[] = {
+ { SUF_Z, 0, CPU_TSX, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0, 3, {0x0F, 0x01, 0x00}, 0, 0, 0 }
+};
+
+static const x86_insn_info vfma_ps_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_FMA, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x00}, 0, 3, 12 },
+ { SUF_Z, ONLY_AVX, CPU_FMA, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x38, 0x00}, 0, 3, 16 }
+};
+
+static const x86_insn_info vfma_pd_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_FMA, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC9, 3, {0x0F, 0x38, 0x00}, 0, 3, 12 },
+ { SUF_Z, ONLY_AVX, CPU_FMA, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xCD, 3, {0x0F, 0x38, 0x00}, 0, 3, 16 }
+};
+
+static const x86_insn_info vfma_ss_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_FMA, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x00}, 0, 3, 0 },
+ { SUF_Z, ONLY_AVX, CPU_FMA, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x38, 0x00}, 0, 3, 56 }
+};
+
+static const x86_insn_info vfma_sd_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_FMA, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC9, 3, {0x0F, 0x38, 0x00}, 0, 3, 0 },
+ { SUF_Z, ONLY_AVX, CPU_FMA, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC9, 3, {0x0F, 0x38, 0x00}, 0, 3, 4 }
+};
+
+static const x86_insn_info aes_insn[] = {
+ { SUF_Z, 0, CPU_AES, 0, 0, {MOD_Op1Add, MOD_Op2Add, MOD_SetVEX}, 0, 0, 0x66, 3, {0x0F, 0x00, 0x00}, 0, 2, 158 },
+ { SUF_Z, ONLY_AVX, CPU_AES, CPU_AVX, 0, {MOD_Op1Add, MOD_Op2Add, 0}, 0, 0, 0xC1, 3, {0x0F, 0x00, 0x00}, 0, 3, 12 }
+};
+
+static const x86_insn_info aesimc_insn[] = {
+ { SUF_Z, 0, CPU_AES, 0, 0, {MOD_Op1Add, MOD_Op2Add, MOD_SetVEX}, 0, 0, 0x66, 3, {0x0F, 0x00, 0x00}, 0, 2, 155 }
+};
+
+static const x86_insn_info aes_imm_insn[] = {
+ { SUF_Z, 0, CPU_AES, 0, 0, {MOD_Op1Add, MOD_Op2Add, MOD_SetVEX}, 0, 0, 0x66, 3, {0x0F, 0x00, 0x00}, 0, 3, 185 }
+};
+
+static const x86_insn_info pclmulqdq_insn[] = {
+ { SUF_Z, 0, CPU_CLMUL, 0, 0, {MOD_Op1Add, MOD_Op2Add, MOD_SetVEX}, 0, 0, 0x66, 3, {0x0F, 0x00, 0x00}, 0, 3, 158 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, CPU_CLMUL, 0, {MOD_Op1Add, MOD_Op2Add, 0}, 0, 0, 0xC1, 3, {0x0F, 0x00, 0x00}, 0, 4, 60 }
+};
+
+static const x86_insn_info pclmulqdq_fixed_insn[] = {
+ { SUF_Z, 0, CPU_CLMUL, 0, 0, {MOD_Imm8, MOD_SetVEX, 0}, 0, 0, 0x66, 3, {0x0F, 0x3A, 0x44}, 0, 2, 158 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, CPU_CLMUL, 0, {MOD_Imm8, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x44}, 0, 3, 12 }
+};
+
+static const x86_insn_info rdrand_insn[] = {
+ { SUF_Z, 0, 0, 0, 0, {MOD_SpAdd, 0, 0}, 16, 0, 0, 2, {0x0F, 0xC7, 0}, 0, 1, 395 },
+ { SUF_Z, 0, CPU_386, 0, 0, {MOD_SpAdd, 0, 0}, 32, 0, 0, 2, {0x0F, 0xC7, 0}, 0, 1, 26 },
+ { SUF_Z, ONLY_64, 0, 0, 0, {MOD_SpAdd, 0, 0}, 64, 0, 0, 2, {0x0F, 0xC7, 0}, 0, 1, 30 }
+};
+
+static const x86_insn_info fs_gs_base_insn[] = {
+ { SUF_Z, ONLY_64, CPU_FSGSBASE, 0, 0, {MOD_SpAdd, 0, 0}, 32, 0, 0xF3, 2, {0x0F, 0xAE, 0}, 0, 1, 26 },
+ { SUF_Z, ONLY_64, CPU_FSGSBASE, 0, 0, {MOD_SpAdd, 0, 0}, 64, 0, 0xF3, 2, {0x0F, 0xAE, 0}, 0, 1, 30 }
+};
+
+static const x86_insn_info avx_cvtps2ph_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, CPU_F16C, 0, {MOD_PreAdd, MOD_Op2Add, 0}, 0, 0, 0xC0, 3, {0x0F, 0x3A, 0x00}, 0, 3, 209 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, CPU_F16C, 0, {MOD_PreAdd, MOD_Op2Add, 0}, 0, 0, 0xC0, 3, {0x0F, 0x3A, 0x00}, 0, 3, 212 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, CPU_F16C, 0, {MOD_PreAdd, MOD_Op2Add, 0}, 0, 0, 0xC4, 3, {0x0F, 0x3A, 0x00}, 0, 3, 215 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, CPU_F16C, 0, {MOD_PreAdd, MOD_Op2Add, 0}, 0, 0, 0xC4, 3, {0x0F, 0x3A, 0x00}, 0, 3, 218 }
+};
+
+static const x86_insn_info avx_cvtph2ps_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_AVX, CPU_F16C, 0, {MOD_PreAdd, MOD_Op2Add, 0}, 0, 0, 0xC0, 3, {0x0F, 0x38, 0x00}, 0, 2, 64 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, CPU_F16C, 0, {MOD_PreAdd, MOD_Op2Add, 0}, 0, 0, 0xC0, 3, {0x0F, 0x38, 0x00}, 0, 2, 631 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, CPU_F16C, 0, {MOD_PreAdd, MOD_Op2Add, 0}, 0, 0, 0xC4, 3, {0x0F, 0x38, 0x00}, 0, 2, 208 },
+ { SUF_Z, ONLY_AVX, CPU_AVX, CPU_F16C, 0, {MOD_PreAdd, MOD_Op2Add, 0}, 0, 0, 0xC4, 3, {0x0F, 0x38, 0x00}, 0, 2, 633 }
+};
+
+static const x86_insn_info extrq_insn[] = {
+ { SUF_Z, 0, CPU_SSE4a, 0, 0, {0, 0, 0}, 0, 0, 0x66, 2, {0x0F, 0x78, 0}, 0, 3, 65 },
+ { SUF_Z, 0, CPU_SSE4a, 0, 0, {0, 0, 0}, 0, 0, 0x66, 2, {0x0F, 0x79, 0}, 0, 2, 64 }
+};
+
+static const x86_insn_info insertq_insn[] = {
+ { SUF_Z, 0, CPU_SSE4a, 0, 0, {0, 0, 0}, 0, 0, 0xF2, 2, {0x0F, 0x78, 0}, 0, 4, 64 },
+ { SUF_Z, 0, CPU_SSE4a, 0, 0, {0, 0, 0}, 0, 0, 0xF2, 2, {0x0F, 0x79, 0}, 0, 2, 64 }
+};
+
+static const x86_insn_info movntsd_insn[] = {
+ { SUF_Z, 0, CPU_SSE4a, 0, 0, {0, 0, 0}, 0, 0, 0xF2, 2, {0x0F, 0x2B, 0}, 0, 2, 47 }
+};
+
+static const x86_insn_info movntss_insn[] = {
+ { SUF_Z, 0, CPU_SSE4a, 0, 0, {0, 0, 0}, 0, 0, 0xF3, 2, {0x0F, 0x2B, 0}, 0, 2, 450 }
+};
+
+static const x86_insn_info vfrc_pdps_insn[] = {
+ { SUF_Z, 0, CPU_XOP, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0x80, 2, {0x09, 0x80, 0}, 0, 2, 155 },
+ { SUF_Z, 0, CPU_XOP, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0x84, 2, {0x09, 0x80, 0}, 0, 2, 191 }
+};
+
+static const x86_insn_info vfrczsd_insn[] = {
+ { SUF_Z, 0, CPU_XOP, 0, 0, {0, 0, 0}, 0, 0, 0x80, 2, {0x09, 0x83, 0}, 0, 2, 64 },
+ { SUF_Z, 0, CPU_XOP, 0, 0, {0, 0, 0}, 0, 0, 0x80, 2, {0x09, 0x83, 0}, 0, 2, 451 }
+};
+
+static const x86_insn_info vfrczss_insn[] = {
+ { SUF_Z, 0, CPU_XOP, 0, 0, {0, 0, 0}, 0, 0, 0x80, 2, {0x09, 0x82, 0}, 0, 2, 64 },
+ { SUF_Z, 0, CPU_XOP, 0, 0, {0, 0, 0}, 0, 0, 0x80, 2, {0x09, 0x82, 0}, 0, 2, 336 }
+};
+
+static const x86_insn_info vpcmov_insn[] = {
+ { SUF_Z, 0, CPU_XOP, 0, 0, {0, 0, 0}, 0, 0, 0x80, 2, {0x08, 0xA2, 0}, 0, 4, 12 },
+ { SUF_Z, 0, CPU_XOP, 0, 0, {0, 0, 0}, 0, 0, 0x88, 2, {0x08, 0xA2, 0}, 0, 4, 68 },
+ { SUF_Z, 0, CPU_XOP, 0, 0, {0, 0, 0}, 0, 0, 0x84, 2, {0x08, 0xA2, 0}, 0, 4, 16 },
+ { SUF_Z, 0, CPU_XOP, 0, 0, {0, 0, 0}, 0, 0, 0x8C, 2, {0x08, 0xA2, 0}, 0, 4, 72 }
+};
+
+static const x86_insn_info vpcom_insn[] = {
+ { SUF_Z, 0, CPU_XOP, 0, 0, {MOD_Op1Add, MOD_Imm8, 0}, 0, 0, 0x80, 2, {0x08, 0x00, 0}, 0, 3, 12 }
+};
+
+static const x86_insn_info vpcom_imm_insn[] = {
+ { SUF_Z, 0, CPU_XOP, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0x80, 2, {0x08, 0x00, 0}, 0, 4, 60 }
+};
+
+static const x86_insn_info vphaddsub_insn[] = {
+ { SUF_Z, 0, CPU_XOP, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0x80, 2, {0x09, 0x00, 0}, 0, 2, 155 }
+};
+
+static const x86_insn_info vpma_insn[] = {
+ { SUF_Z, 0, CPU_XOP, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0x80, 2, {0x08, 0x00, 0}, 0, 4, 12 }
+};
+
+static const x86_insn_info vpperm_insn[] = {
+ { SUF_Z, 0, CPU_XOP, 0, 0, {0, 0, 0}, 0, 0, 0x80, 2, {0x08, 0xA3, 0}, 0, 4, 12 },
+ { SUF_Z, 0, CPU_XOP, 0, 0, {0, 0, 0}, 0, 0, 0x88, 2, {0x08, 0xA3, 0}, 0, 4, 68 }
+};
+
+static const x86_insn_info vprot_insn[] = {
+ { SUF_Z, 0, CPU_XOP, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0x80, 2, {0x09, 0x90, 0}, 0, 3, 155 },
+ { SUF_Z, 0, CPU_XOP, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0x88, 2, {0x09, 0x90, 0}, 0, 3, 12 },
+ { SUF_Z, 0, CPU_XOP, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0x80, 2, {0x08, 0xC0, 0}, 0, 3, 185 }
+};
+
+static const x86_insn_info amd_vpshift_insn[] = {
+ { SUF_Z, 0, CPU_XOP, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0x80, 2, {0x09, 0x00, 0}, 0, 3, 155 },
+ { SUF_Z, 0, CPU_XOP, 0, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0x88, 2, {0x09, 0x00, 0}, 0, 3, 12 }
+};
+
+static const x86_insn_info fma_128_256_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_FMA4, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 12 },
+ { SUF_Z, ONLY_AVX, CPU_FMA4, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC9, 3, {0x0F, 0x3A, 0x00}, 0, 4, 68 },
+ { SUF_Z, ONLY_AVX, CPU_FMA4, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC5, 3, {0x0F, 0x3A, 0x00}, 0, 4, 16 },
+ { SUF_Z, ONLY_AVX, CPU_FMA4, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xCD, 3, {0x0F, 0x3A, 0x00}, 0, 4, 72 }
+};
+
+static const x86_insn_info fma_128_m32_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_FMA4, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 36 },
+ { SUF_Z, ONLY_AVX, CPU_FMA4, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 76 },
+ { SUF_Z, ONLY_AVX, CPU_FMA4, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC9, 3, {0x0F, 0x3A, 0x00}, 0, 4, 80 }
+};
+
+static const x86_insn_info fma_128_m64_insn[] = {
+ { SUF_Z, ONLY_AVX, CPU_FMA4, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 36 },
+ { SUF_Z, ONLY_AVX, CPU_FMA4, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC1, 3, {0x0F, 0x3A, 0x00}, 0, 4, 40 },
+ { SUF_Z, ONLY_AVX, CPU_FMA4, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0xC9, 3, {0x0F, 0x3A, 0x00}, 0, 4, 44 }
+};
+
+static const x86_insn_info xsaveopt64_insn[] = {
+ { SUF_Z, ONLY_64, 0, 0, 0, {MOD_SpAdd, MOD_Op0Add, MOD_Op1Add}, 64, 0, 0, 2, {0x00, 0x00, 0}, 0, 1, 532 }
+};
+
+static const x86_insn_info movbe_insn[] = {
+ { SUF_Z, 0, CPU_MOVBE, 0, 0, {0, 0, 0}, 16, 0, 0, 3, {0x0F, 0x38, 0xF0}, 0, 2, 465 },
+ { SUF_Z, 0, CPU_MOVBE, 0, 0, {0, 0, 0}, 16, 0, 0, 3, {0x0F, 0x38, 0xF1}, 0, 2, 467 },
+ { SUF_Z, 0, CPU_386, CPU_MOVBE, 0, {0, 0, 0}, 32, 0, 0, 3, {0x0F, 0x38, 0xF0}, 0, 2, 359 },
+ { SUF_Z, 0, CPU_386, CPU_MOVBE, 0, {0, 0, 0}, 32, 0, 0, 3, {0x0F, 0x38, 0xF1}, 0, 2, 337 },
+ { SUF_Z, ONLY_64, CPU_MOVBE, 0, 0, {0, 0, 0}, 64, 0, 0, 3, {0x0F, 0x38, 0xF0}, 0, 2, 469 },
+ { SUF_Z, ONLY_64, CPU_MOVBE, 0, 0, {0, 0, 0}, 64, 0, 0, 3, {0x0F, 0x38, 0xF1}, 0, 2, 339 }
+};
+
+static const x86_insn_info vex_gpr_ndd_rm_0F38_regext_insn[] = {
+ { SUF_L|SUF_Z, ONLY_AVX, CPU_386, 0, 0, {MOD_PreAdd, MOD_Op2Add, MOD_SpAdd}, 32, 0, 0xC0, 3, {0x0F, 0x38, 0x00}, 0, 2, 255 },
+ { SUF_Q|SUF_Z, ONLY_64|ONLY_AVX, 0, 0, 0, {MOD_PreAdd, MOD_Op2Add, MOD_SpAdd}, 64, 0, 0xC0, 3, {0x0F, 0x38, 0x00}, 0, 2, 258 }
+};
+
+static const x86_insn_info vex_gpr_reg_rm_0F_imm8_insn[] = {
+ { SUF_L|SUF_Z, ONLY_AVX, CPU_386, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_Op2Add}, 32, 0, 0xC0, 3, {0x0F, 0x00, 0x00}, 0, 3, 134 },
+ { SUF_Q|SUF_Z, ONLY_64|ONLY_AVX, 0, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_Op2Add}, 64, 0, 0xC0, 3, {0x0F, 0x00, 0x00}, 0, 3, 137 }
+};
+
+static const x86_insn_info vex_gpr_reg_nds_rm_0F_insn[] = {
+ { SUF_L|SUF_Z, ONLY_AVX, CPU_386, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_Op2Add}, 32, 0, 0xC0, 3, {0x0F, 0x00, 0x00}, 0, 3, 254 },
+ { SUF_Q|SUF_Z, ONLY_64|ONLY_AVX, 0, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_Op2Add}, 64, 0, 0xC0, 3, {0x0F, 0x00, 0x00}, 0, 3, 257 }
+};
+
+static const x86_insn_info vex_gpr_reg_rm_nds_0F_insn[] = {
+ { SUF_L|SUF_Z, ONLY_AVX, CPU_386, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_Op2Add}, 32, 0, 0xC0, 3, {0x0F, 0x00, 0x00}, 0, 3, 149 },
+ { SUF_Q|SUF_Z, ONLY_64|ONLY_AVX, 0, 0, 0, {MOD_PreAdd, MOD_Op1Add, MOD_Op2Add}, 64, 0, 0xC0, 3, {0x0F, 0x00, 0x00}, 0, 3, 152 }
+};
+
+static const x86_insn_info bextr_insn[] = {
+ { SUF_L|SUF_Z, ONLY_AVX, CPU_386, CPU_BMI1, 0, {0, 0, 0}, 32, 0, 0xC0, 3, {0x0F, 0x38, 0xF7}, 0, 3, 149 },
+ { SUF_L|SUF_Z, ONLY_AVX, CPU_386, CPU_TBM, 0, {0, 0, 0}, 32, 0, 0x80, 2, {0x0A, 0x10, 0}, 0, 3, 230 },
+ { SUF_Q|SUF_Z, ONLY_64|ONLY_AVX, CPU_BMI1, 0, 0, {0, 0, 0}, 64, 0, 0xC0, 3, {0x0F, 0x38, 0xF7}, 0, 3, 152 },
+ { SUF_Q|SUF_Z, ONLY_64|ONLY_AVX, CPU_TBM, 0, 0, {0, 0, 0}, 64, 0, 0x88, 2, {0x0A, 0x10, 0}, 0, 3, 233 }
+};
+
+static const x86_insn_info invpcid_insn[] = {
+ { SUF_Z, NOT_64, CPU_386, CPU_INVPCID, CPU_Priv, {0, 0, 0}, 0, 0, 0x66, 3, {0x0F, 0x38, 0x82}, 0, 2, 611 },
+ { SUF_Z, ONLY_64, CPU_INVPCID, CPU_Priv, 0, {0, 0, 0}, 0, 64, 0x66, 3, {0x0F, 0x38, 0x82}, 0, 2, 613 }
+};
+
+static const x86_insn_info intel_SHA1MSG1_insn[] = {
+ { SUF_Z, 0, CPU_SHA, 0, 0, {0, 0, 0}, 0, 0, 0, 3, {0x0F, 0x38, 0xC9}, 0, 2, 155 }
+};
+
+static const x86_insn_info intel_SHA1MSG2_insn[] = {
+ { SUF_Z, 0, CPU_SHA, 0, 0, {0, 0, 0}, 0, 0, 0, 3, {0x0F, 0x38, 0xCA}, 0, 2, 155 }
+};
+
+static const x86_insn_info intel_SHA1NEXTE_insn[] = {
+ { SUF_Z, 0, CPU_SHA, 0, 0, {0, 0, 0}, 0, 0, 0, 3, {0x0F, 0x38, 0xC8}, 0, 2, 155 }
+};
+
+static const x86_insn_info intel_SHA1RNDS4_insn[] = {
+ { SUF_Z, 0, CPU_SHA, 0, 0, {0, 0, 0}, 0, 0, 0, 3, {0x0F, 0x3A, 0xCC}, 0, 3, 185 }
+};
+
+static const x86_insn_info intel_SHA256MSG1_insn[] = {
+ { SUF_Z, 0, CPU_SHA, 0, 0, {0, 0, 0}, 0, 0, 0, 3, {0x0F, 0x38, 0xCC}, 0, 2, 155 }
+};
+
+static const x86_insn_info intel_SHA256MSG2_insn[] = {
+ { SUF_Z, 0, CPU_SHA, 0, 0, {0, 0, 0}, 0, 0, 0, 3, {0x0F, 0x38, 0xCD}, 0, 2, 155 }
+};
+
+static const x86_insn_info intel_SHA256RNDS2_insn[] = {
+ { SUF_Z, 0, CPU_SHA, 0, 0, {0, 0, 0}, 0, 0, 0, 3, {0x0F, 0x38, 0xCB}, 0, 2, 64 }
+};
+
+static const x86_insn_info vex_gpr_ndd_rm_0F38_insn[] = {
+ { SUF_L|SUF_Z, 0, CPU_386, 0, 0, {MOD_PreAdd, MOD_Op2Add, 0}, 32, 0, 0x00, 3, {0x0F, 0x38, 0x00}, 0, 2, 101 },
+ { SUF_Q|SUF_Z, ONLY_64, 0, 0, 0, {MOD_PreAdd, MOD_Op2Add, 0}, 64, 0, 0x00, 3, {0x0F, 0x38, 0x00}, 0, 2, 104 }
+};
+
+static const x86_insn_info xop_gpr_reg_rm_09_insn[] = {
+ { SUF_L|SUF_Z, 0, CPU_386, CPU_TBM, 0, {MOD_Op1Add, MOD_SpAdd, 0}, 32, 0, 0x80, 2, {0x09, 0x00, 0}, 0, 2, 255 },
+ { SUF_Q|SUF_Z, ONLY_64, CPU_TBM, 0, 0, {MOD_Op1Add, MOD_SpAdd, 0}, 64, 0, 0x88, 2, {0x09, 0x00, 0}, 0, 2, 258 }
+};
+
+static const x86_insn_info now3d_insn[] = {
+ { SUF_Z, 0, CPU_3DNow, 0, 0, {MOD_Imm8, 0, 0}, 0, 0, 0, 2, {0x0F, 0x0F, 0}, 0, 2, 140 }
+};
+
+static const x86_insn_info cmpxchg16b_insn[] = {
+ { SUF_Z, ONLY_64, 0, 0, 0, {0, 0, 0}, 64, 0, 0, 2, {0x0F, 0xC7, 0}, 1, 1, 510 }
+};
+
+static const x86_insn_info invlpga_insn[] = {
+ { SUF_Z, 0, CPU_SVM, 0, 0, {0, 0, 0}, 0, 0, 0, 3, {0x0F, 0x01, 0xDF}, 0, 0, 0 },
+ { SUF_Z, 0, CPU_386, CPU_SVM, 0, {0, 0, 0}, 0, 0, 0, 3, {0x0F, 0x01, 0xDF}, 0, 2, 515 }
+};
+
+static const x86_insn_info skinit_insn[] = {
+ { SUF_Z, 0, CPU_SVM, 0, 0, {0, 0, 0}, 0, 0, 0, 3, {0x0F, 0x01, 0xDE}, 0, 0, 0 },
+ { SUF_Z, 0, CPU_SVM, 0, 0, {0, 0, 0}, 0, 0, 0, 3, {0x0F, 0x01, 0xDE}, 0, 1, 655 }
+};
+
+static const x86_insn_info svm_rax_insn[] = {
+ { SUF_Z, 0, CPU_SVM, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0, 3, {0x0F, 0x01, 0x00}, 0, 0, 0 },
+ { SUF_Z, 0, CPU_SVM, 0, 0, {MOD_Op2Add, 0, 0}, 0, 0, 0, 3, {0x0F, 0x01, 0x00}, 0, 1, 515 }
+};
+
+static const x86_insn_info padlock_insn[] = {
+ { SUF_Z, 0, CPU_PadLock, 0, 0, {MOD_Imm8, MOD_PreAdd, MOD_Op1Add}, 0, 0, 0x00, 2, {0x0F, 0x00, 0}, 0, 0, 0 }
+};
+
+static const x86_insn_info cyrixmmx_insn[] = {
+ { SUF_Z, 0, CPU_Cyrix, CPU_MMX, 0, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 2, 140 }
+};
+
+static const x86_insn_info pmachriw_insn[] = {
+ { SUF_Z, 0, CPU_Cyrix, CPU_MMX, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x5E, 0}, 0, 2, 317 }
+};
+
+static const x86_insn_info rdwrshr_insn[] = {
+ { SUF_Z, 0, CPU_686, CPU_Cyrix, CPU_SMM, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0x0F, 0x36, 0}, 0, 1, 90 }
+};
+
+static const x86_insn_info rsdc_insn[] = {
+ { SUF_Z, 0, CPU_486, CPU_Cyrix, CPU_SMM, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x79, 0}, 0, 2, 629 }
+};
+
+static const x86_insn_info cyrixsmm_insn[] = {
+ { SUF_Z, 0, CPU_486, CPU_Cyrix, CPU_SMM, {MOD_Op1Add, 0, 0}, 0, 0, 0, 2, {0x0F, 0x00, 0}, 0, 1, 619 }
+};
+
+static const x86_insn_info svdc_insn[] = {
+ { SUF_Z, 0, CPU_486, CPU_Cyrix, CPU_SMM, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x78, 0}, 0, 2, 619 }
+};
+
+static const x86_insn_info ibts_insn[] = {
+ { SUF_Z, 0, CPU_386, CPU_Obs, CPU_Undoc, {0, 0, 0}, 16, 0, 0, 2, {0x0F, 0xA7, 0}, 0, 2, 260 },
+ { SUF_Z, 0, CPU_386, CPU_Obs, CPU_Undoc, {0, 0, 0}, 32, 0, 0, 2, {0x0F, 0xA7, 0}, 0, 2, 266 }
+};
+
+static const x86_insn_info umov_insn[] = {
+ { SUF_Z, 0, CPU_386, CPU_Undoc, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x10, 0}, 0, 2, 323 },
+ { SUF_Z, 0, CPU_386, CPU_Undoc, 0, {0, 0, 0}, 16, 0, 0, 2, {0x0F, 0x11, 0}, 0, 2, 260 },
+ { SUF_Z, 0, CPU_386, CPU_Undoc, 0, {0, 0, 0}, 32, 0, 0, 2, {0x0F, 0x11, 0}, 0, 2, 266 },
+ { SUF_Z, 0, CPU_386, CPU_Undoc, 0, {0, 0, 0}, 0, 0, 0, 2, {0x0F, 0x12, 0}, 0, 2, 325 },
+ { SUF_Z, 0, CPU_386, CPU_Undoc, 0, {0, 0, 0}, 16, 0, 0, 2, {0x0F, 0x13, 0}, 0, 2, 98 },
+ { SUF_Z, 0, CPU_386, CPU_Undoc, 0, {0, 0, 0}, 32, 0, 0, 2, {0x0F, 0x13, 0}, 0, 2, 101 }
+};
+
+static const x86_insn_info xbts_insn[] = {
+ { SUF_Z, 0, CPU_386, CPU_Obs, CPU_Undoc, {0, 0, 0}, 16, 0, 0, 2, {0x0F, 0xA6, 0}, 0, 2, 465 },
+ { SUF_Z, 0, CPU_386, CPU_Obs, CPU_Undoc, {0, 0, 0}, 32, 0, 0, 2, {0x0F, 0xA6, 0}, 0, 2, 359 }
+};
+
+
diff --git a/contrib/tools/yasm/modules/x86regtmod.c b/contrib/tools/yasm/modules/x86regtmod.c
new file mode 100644
index 0000000000..cdec3577e2
--- /dev/null
+++ b/contrib/tools/yasm/modules/x86regtmod.c
@@ -0,0 +1,261 @@
+/* ANSI-C code produced by genperf */
+
+#include <util.h>
+
+#include <ctype.h>
+#include <libyasm.h>
+#include <libyasm/phash.h>
+
+#include "modules/arch/x86/x86arch.h"
+
+enum regtmod_type {
+ REG = 1,
+ REGGROUP,
+ SEGREG,
+ TARGETMOD
+};
+struct regtmod_parse_data {
+ const char *name;
+ unsigned int type:8; /* regtmod_type */
+
+ /* REG: register size
+ * SEGREG: prefix encoding
+ * Others: 0
+ */
+ unsigned int size_prefix:8;
+
+ /* REG: register index
+ * REGGROUP: register group type
+ * SEGREG: register encoding
+ * TARGETMOD: target modifier
+ */
+ unsigned int data:8;
+
+ /* REG: required bits setting
+ * SEGREG: BITS in which the segment is ignored
+ * Others: 0
+ */
+ unsigned int bits:8;
+};
+static const struct regtmod_parse_data *
+regtmod_find(const char *key, size_t len)
+{
+ static const struct regtmod_parse_data pd[152] = {
+ {"st6", REG, X86_FPUREG, 6, 0},
+ {"ymm1", REG, X86_YMMREG, 1, 0},
+ {"rsp", REG, X86_REG64, 4, 64},
+ {"r10", REG, X86_REG64, 10, 64},
+ {"bp", REG, X86_REG16, 5, 0},
+ {"r10b", REG, X86_REG8, 10, 64},
+ {"mm2", REG, X86_MMXREG, 2, 0},
+ {"rdi", REG, X86_REG64, 7, 64},
+ {"ymm12", REG, X86_YMMREG, 12, 64},
+ {"r8", REG, X86_REG64, 8, 64},
+ {"gs", SEGREG, 0x65, 0x05, 0},
+ {"r10d", REG, X86_REG32, 10, 64},
+ {"rsi", REG, X86_REG64, 6, 64},
+ {"eax", REG, X86_REG32, 0, 0},
+ {"mm3", REG, X86_MMXREG, 3, 0},
+ {"tr6", REG, X86_TRREG, 6, 0},
+ {"tr0", REG, X86_TRREG, 0, 0},
+ {"ah", REG, X86_REG8, 4, 0},
+ {"xmm6", REG, X86_XMMREG, 6, 0},
+ {"dr6", REG, X86_DRREG, 6, 0},
+ {"esp", REG, X86_REG32, 4, 0},
+ {"bpl", REG, X86_REG8X, 5, 64},
+ {"tr5", REG, X86_TRREG, 5, 0},
+ {"ax", REG, X86_REG16, 0, 0},
+ {"sp", REG, X86_REG16, 4, 0},
+ {"r15b", REG, X86_REG8, 15, 64},
+ {"xmm14", REG, X86_XMMREG, 14, 64},
+ {"xmm12", REG, X86_XMMREG, 12, 64},
+ {"r11", REG, X86_REG64, 11, 64},
+ {"xmm", REGGROUP, 0, X86_XMMREG, 0},
+ {"ymm2", REG, X86_YMMREG, 2, 0},
+ {"ebp", REG, X86_REG32, 5, 0},
+ {"xmm8", REG, X86_XMMREG, 8, 64},
+ {"r12d", REG, X86_REG32, 12, 64},
+ {"ymm4", REG, X86_YMMREG, 4, 0},
+ {"ymm3", REG, X86_YMMREG, 3, 0},
+ {"rax", REG, X86_REG64, 0, 64},
+ {"xmm3", REG, X86_XMMREG, 3, 0},
+ {"xmm0", REG, X86_XMMREG, 0, 0},
+ {"dr7", REG, X86_DRREG, 7, 0},
+ {"r14w", REG, X86_REG16, 14, 64},
+ {"mm1", REG, X86_MMXREG, 1, 0},
+ {"bl", REG, X86_REG8, 3, 0},
+ {"r9w", REG, X86_REG16, 9, 64},
+ {"ymm13", REG, X86_YMMREG, 13, 64},
+ {"r9b", REG, X86_REG8, 9, 64},
+ {"ymm8", REG, X86_YMMREG, 8, 64},
+ {"dx", REG, X86_REG16, 2, 0},
+ {"r12", REG, X86_REG64, 12, 64},
+ {"r12w", REG, X86_REG16, 12, 64},
+ {"r9", REG, X86_REG64, 9, 64},
+ {"r15w", REG, X86_REG16, 15, 64},
+ {"sil", REG, X86_REG8X, 6, 64},
+ {"r10w", REG, X86_REG16, 10, 64},
+ {"ymm6", REG, X86_YMMREG, 6, 0},
+ {"ss", SEGREG, 0x36, 0x02, 64},
+ {"tr4", REG, X86_TRREG, 4, 0},
+ {"cr3", REG, X86_CRREG, 3, 0},
+ {"r11w", REG, X86_REG16, 11, 64},
+ {"xmm4", REG, X86_XMMREG, 4, 0},
+ {"st0", REG, X86_FPUREG, 0, 0},
+ {"dil", REG, X86_REG8X, 7, 64},
+ {"tr3", REG, X86_TRREG, 3, 0},
+ {"r13d", REG, X86_REG32, 13, 64},
+ {"r8w", REG, X86_REG16, 8, 64},
+ {"xmm13", REG, X86_XMMREG, 13, 64},
+ {"st3", REG, X86_FPUREG, 3, 0},
+ {"xmm15", REG, X86_XMMREG, 15, 64},
+ {"xmm10", REG, X86_XMMREG, 10, 64},
+ {"es", SEGREG, 0x26, 0x00, 64},
+ {"cr8", REG, X86_CRREG, 8, 64},
+ {"xmm7", REG, X86_XMMREG, 7, 0},
+ {"spl", REG, X86_REG8X, 4, 64},
+ {"r15", REG, X86_REG64, 15, 64},
+ {"cr4", REG, X86_CRREG, 4, 0},
+ {"fs", SEGREG, 0x64, 0x04, 0},
+ {"rcx", REG, X86_REG64, 1, 64},
+ {"mm0", REG, X86_MMXREG, 0, 0},
+ {"mm", REGGROUP, 0, X86_MMXREG, 0},
+ {"tr1", REG, X86_TRREG, 1, 0},
+ {"short", TARGETMOD, 0, X86_SHORT, 0},
+ {"st4", REG, X86_FPUREG, 4, 0},
+ {"cr0", REG, X86_CRREG, 0, 0},
+ {"xmm11", REG, X86_XMMREG, 11, 64},
+ {"mm4", REG, X86_MMXREG, 4, 0},
+ {"bh", REG, X86_REG8, 7, 0},
+ {"r15d", REG, X86_REG32, 15, 64},
+ {"dr2", REG, X86_DRREG, 2, 0},
+ {"r8d", REG, X86_REG32, 8, 64},
+ {"ymm7", REG, X86_YMMREG, 7, 0},
+ {"xmm9", REG, X86_XMMREG, 9, 64},
+ {"r12b", REG, X86_REG8, 12, 64},
+ {"st2", REG, X86_FPUREG, 2, 0},
+ {"ymm9", REG, X86_YMMREG, 9, 64},
+ {"st7", REG, X86_FPUREG, 7, 0},
+ {"bx", REG, X86_REG16, 3, 0},
+ {"ymm11", REG, X86_YMMREG, 11, 64},
+ {"ymm5", REG, X86_YMMREG, 5, 0},
+ {"ymm15", REG, X86_YMMREG, 15, 64},
+ {"rbp", REG, X86_REG64, 5, 64},
+ {"r13", REG, X86_REG64, 13, 64},
+ {"mm5", REG, X86_MMXREG, 5, 0},
+ {"si", REG, X86_REG16, 6, 0},
+ {"dl", REG, X86_REG8, 2, 0},
+ {"di", REG, X86_REG16, 7, 0},
+ {"cr2", REG, X86_CRREG, 2, 0},
+ {"r14d", REG, X86_REG32, 14, 64},
+ {"ymm14", REG, X86_YMMREG, 14, 64},
+ {"tr7", REG, X86_TRREG, 7, 0},
+ {"ds", SEGREG, 0x3e, 0x03, 64},
+ {"cx", REG, X86_REG16, 1, 0},
+ {"st", REGGROUP, 0, X86_FPUREG, 0},
+ {"edi", REG, X86_REG32, 7, 0},
+ {"al", REG, X86_REG8, 0, 0},
+ {"mm7", REG, X86_MMXREG, 7, 0},
+ {"ebx", REG, X86_REG32, 3, 0},
+ {"xmm2", REG, X86_XMMREG, 2, 0},
+ {"st5", REG, X86_FPUREG, 5, 0},
+ {"rip", REG, X86_RIP, 0, 64},
+ {"rbx", REG, X86_REG64, 3, 64},
+ {"to", TARGETMOD, 0, X86_TO, 0},
+ {"r11d", REG, X86_REG32, 11, 64},
+ {"dr5", REG, X86_DRREG, 5, 0},
+ {"dr1", REG, X86_DRREG, 1, 0},
+ {"near", TARGETMOD, 0, X86_NEAR, 0},
+ {"r14", REG, X86_REG64, 14, 64},
+ {"dh", REG, X86_REG8, 6, 0},
+ {"cl", REG, X86_REG8, 1, 0},
+ {"dr4", REG, X86_DRREG, 4, 0},
+ {"ymm10", REG, X86_YMMREG, 10, 64},
+ {"dr3", REG, X86_DRREG, 3, 0},
+ {"xmm5", REG, X86_XMMREG, 5, 0},
+ {"mm6", REG, X86_MMXREG, 6, 0},
+ {"r13w", REG, X86_REG16, 13, 64},
+ {"far", TARGETMOD, 0, X86_FAR, 0},
+ {"ymm0", REG, X86_YMMREG, 0, 0},
+ {"ymm", REGGROUP, 0, X86_YMMREG, 0},
+ {"ch", REG, X86_REG8, 5, 0},
+ {"xmm1", REG, X86_XMMREG, 1, 0},
+ {"esi", REG, X86_REG32, 6, 0},
+ {"r14b", REG, X86_REG8, 14, 64},
+ {"st1", REG, X86_FPUREG, 1, 0},
+ {"r8b", REG, X86_REG8, 8, 64},
+ {"r11b", REG, X86_REG8, 11, 64},
+ {"r13b", REG, X86_REG8, 13, 64},
+ {"ecx", REG, X86_REG32, 1, 0},
+ {"tr2", REG, X86_TRREG, 2, 0},
+ {"rdx", REG, X86_REG64, 2, 64},
+ {"r9d", REG, X86_REG32, 9, 64},
+ {"cs", SEGREG, 0x2e, 0x01, 0},
+ {"dr0", REG, X86_DRREG, 0, 0},
+ {"edx", REG, X86_REG32, 2, 0}
+ };
+ static const unsigned char tab[] = {
+ 0,0,125,22,0,0,85,0,85,168,0,0,0,7,113,0,
+ 0,0,0,22,183,0,0,11,42,55,0,0,82,0,88,235,
+ 0,0,0,0,0,0,183,85,0,0,145,113,220,125,22,0,
+ 88,183,0,7,0,0,0,7,0,125,113,87,131,116,7,0,
+ 113,7,0,113,0,87,87,7,7,7,113,40,85,125,113,85,
+ 0,0,22,235,0,131,125,113,0,22,0,220,0,220,0,120,
+ 116,0,124,184,0,0,0,183,92,125,0,92,125,0,0,177,
+ 7,0,0,7,0,45,0,214,180,113,211,163,142,0,88,173,
+ };
+
+ const struct regtmod_parse_data *ret;
+ unsigned long rsl, val = phash_lookup(key, len, 0x9e3779b9UL);
+ rsl = ((val>>25)^tab[val&0x7f]);
+ if (rsl >= 152) return NULL;
+ ret = &pd[rsl];
+ if (strcmp(key, ret->name) != 0) return NULL;
+ return ret;
+}
+
+
+
+yasm_arch_regtmod
+yasm_x86__parse_check_regtmod(yasm_arch *arch, const char *id, size_t id_len,
+ uintptr_t *data)
+{
+ yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
+ /*@null@*/ const struct 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->type;
+ bits = pdata->bits;
+
+ if (type == YASM_ARCH_REG && bits != 0 && arch_x86->mode_bits != bits) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("`%s' is a register in %u-bit mode"), id, bits);
+ return YASM_ARCH_NOTREGTMOD;
+ }
+
+ if (type == YASM_ARCH_SEGREG && bits != 0 && arch_x86->mode_bits == bits) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("`%s' segment register ignored in %u-bit mode"), id,
+ bits);
+ }
+
+ if (type == YASM_ARCH_SEGREG)
+ *data = (pdata->size_prefix<<8) | pdata->data;
+ else
+ *data = pdata->size_prefix | pdata->data;
+ return type;
+}
+
diff --git a/contrib/tools/yasm/util.h b/contrib/tools/yasm/util.h
new file mode 100644
index 0000000000..4174648a22
--- /dev/null
+++ b/contrib/tools/yasm/util.h
@@ -0,0 +1,167 @@
+/*
+ * YASM utility functions.
+ *
+ * Includes standard headers and defines prototypes for replacement functions
+ * if needed.
+ *
+ * Copyright (C) 2001-2007 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.
+ */
+#ifndef YASM_UTIL_H
+#define YASM_UTIL_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined(HAVE_GNU_C_LIBRARY) || defined(__MINGW32__) || defined(__DJGPP__)
+
+/* Work around glibc's non-defining of certain things when using gcc -ansi */
+# ifdef __STRICT_ANSI__
+# undef __STRICT_ANSI__
+# endif
+
+/* Work around glibc's string inlines (in bits/string2.h) if needed */
+# ifdef NO_STRING_INLINES
+# define __NO_STRING_INLINES
+# endif
+
+#endif
+
+#if !defined(lint) && !defined(NDEBUG)
+# define NDEBUG
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#if !defined(_musl_)
+#if __linux__ && __x86_64__
+__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
+#endif
+#endif
+
+#include <libyasm-stdint.h>
+#include <libyasm/coretype.h>
+
+#ifdef lint
+# define _(String) String
+#else
+# ifdef HAVE_LOCALE_H
+# include <locale.h>
+# endif
+
+# ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(String) gettext(String)
+# else
+# define gettext(Msgid) (Msgid)
+# define dgettext(Domainname, Msgid) (Msgid)
+# define dcgettext(Domainname, Msgid, Category) (Msgid)
+# define textdomain(Domainname) while (0) /* nothing */
+# define bindtextdomain(Domainname, Dirname) while (0) /* nothing */
+# define _(String) (String)
+# endif
+#endif
+
+#ifdef gettext_noop
+# define N_(String) gettext_noop(String)
+#else
+# define N_(String) (String)
+#endif
+
+#ifdef HAVE_MERGESORT
+#define yasm__mergesort(a, b, c, d) mergesort(a, b, c, d)
+#endif
+
+#ifdef HAVE_STRSEP
+#define yasm__strsep(a, b) strsep(a, b)
+#endif
+
+#ifdef HAVE_STRCASECMP
+# define yasm__strcasecmp(x, y) strcasecmp(x, y)
+# define yasm__strncasecmp(x, y, n) strncasecmp(x, y, n)
+#elif HAVE_STRICMP
+# define yasm__strcasecmp(x, y) stricmp(x, y)
+# define yasm__strncasecmp(x, y, n) strnicmp(x, y, n)
+#elif HAVE__STRICMP
+# define yasm__strcasecmp(x, y) _stricmp(x, y)
+# define yasm__strncasecmp(x, y, n) _strnicmp(x, y, n)
+#elif HAVE_STRCMPI
+# define yasm__strcasecmp(x, y) strcmpi(x, y)
+# define yasm__strncasecmp(x, y, n) strncmpi(x, y, n)
+#else
+# define USE_OUR_OWN_STRCASECMP
+#endif
+
+#include <libyasm/compat-queue.h>
+
+#ifdef WITH_DMALLOC
+# include <dmalloc.h>
+# define yasm__xstrdup(str) xstrdup(str)
+# define yasm_xmalloc(size) xmalloc(size)
+# define yasm_xcalloc(count, size) xcalloc(count, size)
+# define yasm_xrealloc(ptr, size) xrealloc(ptr, size)
+# define yasm_xfree(ptr) xfree(ptr)
+#endif
+
+/* Bit-counting: used primarily by HAMT but also in a few other places. */
+#define BC_TWO(c) (0x1ul << (c))
+#define BC_MSK(c) (((unsigned long)(-1)) / (BC_TWO(BC_TWO(c)) + 1ul))
+#define BC_COUNT(x,c) ((x) & BC_MSK(c)) + (((x) >> (BC_TWO(c))) & BC_MSK(c))
+#define BitCount(d, s) do { \
+ d = BC_COUNT(s, 0); \
+ d = BC_COUNT(d, 1); \
+ d = BC_COUNT(d, 2); \
+ d = BC_COUNT(d, 3); \
+ d = BC_COUNT(d, 4); \
+ } while (0)
+
+/** Determine if a value is exactly a power of 2. Zero is treated as a power
+ * of two.
+ * \param x value
+ * \return Nonzero if x is a power of 2.
+ */
+#define is_exp2(x) ((x & (x - 1)) == 0)
+
+#ifndef NELEMS
+/** Get the number of elements in an array.
+ * \internal
+ * \param array array
+ * \return Number of elements.
+ */
+#define NELEMS(array) (sizeof(array) / sizeof(array[0]))
+#endif
+
+char * yasm_replace_path(const char* replace_map[], int size, const char* str, int pref_len);
+
+#endif
diff --git a/contrib/tools/yasm/ya.make b/contrib/tools/yasm/ya.make
new file mode 100644
index 0000000000..d1f8adc08f
--- /dev/null
+++ b/contrib/tools/yasm/ya.make
@@ -0,0 +1,24 @@
+# Autogenerated for platforms:
+# darwin-x86_64
+# linux-x86_64
+# windows-x86_64
+
+OWNER(
+ somov
+ g:contrib
+ g:ymake
+)
+
+VERSION(1.3.0)
+
+IF (USE_PREBUILT_TOOLS)
+ INCLUDE(${ARCADIA_ROOT}/build/prebuilt/contrib/tools/yasm/ya.make.prebuilt)
+ENDIF()
+
+IF (NOT PREBUILT)
+ INCLUDE(${ARCADIA_ROOT}/contrib/tools/yasm/bin/ya.make)
+ENDIF()
+
+RECURSE(
+ bin
+)