summaryrefslogtreecommitdiff
path: root/libcpu
diff options
context:
space:
mode:
Diffstat (limited to 'libcpu')
-rw-r--r--libcpu/ChangeLog357
-rw-r--r--libcpu/Makefile.am72
-rw-r--r--libcpu/Makefile.in547
-rw-r--r--libcpu/defs/i386970
-rw-r--r--libcpu/i386_data.h1415
-rw-r--r--libcpu/i386_disasm.c1054
-rw-r--r--libcpu/i386_gendis.c69
-rw-r--r--libcpu/i386_lex.c2011
-rw-r--r--libcpu/i386_lex.l126
-rw-r--r--libcpu/i386_parse.c3356
-rw-r--r--libcpu/i386_parse.h95
-rw-r--r--libcpu/i386_parse.y1684
-rw-r--r--libcpu/memory-access.h179
-rw-r--r--libcpu/x86_64_disasm.c31
14 files changed, 11966 insertions, 0 deletions
diff --git a/libcpu/ChangeLog b/libcpu/ChangeLog
new file mode 100644
index 0000000..c49f8b9
--- /dev/null
+++ b/libcpu/ChangeLog
@@ -0,0 +1,357 @@
+2010-08-16 Roland McGrath <roland@redhat.com>
+
+ * Makefile.am (%_defs): New pattern rule.
+ (%_dis.h, %.mnemonics): Define as pattern rules using %_defs input.
+ (CLEANFILES): Include all those files.
+
+2010-02-15 Roland McGrath <roland@redhat.com>
+
+ * Makefile.am: Use config/eu.am for common stuff.
+
+2009-04-14 Roland McGrath <roland@redhat.com>
+
+ * Makefile.am (AM_CFLAGS): Add -fdollars-in-identifiers; it is not the
+ default on every machine.
+
+2009-01-23 Roland McGrath <roland@redhat.com>
+
+ * Makefile.am (i386_parse_CFLAGS): Use quotes around command
+ substitution that can produce leading whitespace.
+
+2009-01-01 Ulrich Drepper <drepper@redhat.com>
+
+ * i386_parse.y (instrtable_out): Optimize match_data table by not
+ emitting 0xff masks for leading bytes.
+ * i386_disasm.c (i386_disasm): Adjust reader of match_data.
+
+ * i386_disasm.c (i386_disasm): Reset bufcnt when not matched. We
+ don't expect snprintf to fail.
+
+2008-12-31 Ulrich Drepper <drepper@redhat.com>
+
+ * defs/i386: Add dppd, dpps, insertps, movntdqa, mpsadbw, packusdw,
+ pblendvb, pblendw, pcmpeqq, pcmpestri, pcmpestrm, pcmpistri, pcmpistrm,
+ pcmpgtq, phminposuw, pinsrb, pinsrd, pmaxsb, pmaxsd, pmaxud, pmaxuw,
+ pminsb, pminsd, pminud, pminuw, pmovsxbw, pmovsxbd, pmovsxbq, pmovsxwd,
+ pmovsxwq, pmovsxdq, pmovzxbw, pmovzxbd, pmovzxbq, pmovzxwd, pmovzxwq,
+ pmovzxdq, pmuldq, pmulld, popcnt, ptest, roundss, roundps, roundpd,
+ and roundsd opcodes.
+
+ * i386_disasm.c (i386_disasm): Correct resizing of buffer.
+
+ * i386_parse.y (struct argstring): Add off element.
+ (off_op_str): New global variable.
+ (print_op_str): Print strings as concatenated strings. Keep track
+ of index and length. Update ->off element.
+ (print_op_str_idx): New function.
+ (instrtable_out): Mark op%d_fct as const.
+ Emit two tables for the strings: the string itself (op%d_str) and the
+ index table (op%d_str_idx).
+ * i386_disasm.c (i386_disasm): Adjust for new op%d_str definition.
+
+ * i386_disasm.c [X86_64] (i386_disasm): Handle rex prefix when
+ printing only prefix.
+
+ * i386_disasm.c (i386_disasm): Minor optimizations.
+
+ * i386_parse.y (instrtable_out): No need to emit index, the reader can
+ keep track.
+ * i386_disasm.c (i386_disasm): The index is not emitted anymore, no
+ need to skip it.
+
+ * i386_disasm.c (amd3dnow): Mark as const.
+
+ * defs/i386: Add blendvpd and blendvps opcodes.
+
+2008-12-30 Ulrich Drepper <drepper@redhat.com>
+
+ * defs/i386: Add blendpd and blendps opcodes.
+
+2008-12-19 Ulrich Drepper <drepper@redhat.com>
+
+ * defs/i386: Add entry for AMD 3DNOW.
+ * i386_disasm.c: Implement AMD 3DNOW disassembly.
+
+2008-12-17 Ulrich Drepper <drepper@redhat.com>
+
+ * i386_disasm.c (i386_disasm): If instruction matches prefix,
+ undoing the prefix match finishes the instruction.
+
+2008-01-21 Roland McGrath <roland@redhat.com>
+
+ * defs/i386: Fix typo in comment.
+ * i386_disasm.c (i386_disasm): Handle cltq, cqto.
+
+ * i386_parse.y: Add sanity check for NMNES macro value.
+ * Makefile.am (i386_parse.o): Fix target in dependency rule.
+ (i386_parse.h): New target with empty commands.
+ (i386_lex.o): Depend on it in place of i386_parse.c.
+
+2008-01-21 Ulrich Drepper <drepper@redhat.com>
+
+ * Makefile.am (EXTRA_DIST): Remove defs/x86_64.
+
+2008-01-14 Ulrich Drepper <drepper@redhat.com>
+
+ * defs/i386: Add fixes for opcodes with register number in opcode,
+ 64-bit immediate forms, nop with rex.B.
+ * i386_data.h [X86_64] (FCT_imm64$w): New function.
+ (FCT_oreg): New function.
+ (FCT_oreg$w): New function.
+ * i386_disasm.c (i386_disasm): Reinitialize fmt always before
+ starting the loop to process the string. Handle 0x90 special for
+ x86-64.
+ * i386_parse.y (fillin_arg): Expand synonyms before concatening to
+ form the function name.
+
+2008-01-11 Ulrich Drepper <drepper@redhat.com>
+
+ * i386_disasm.c (struct output_buffer): Remove symcb and symcbarg.
+ (i386_disasm): Remove appropriate initializers.
+ Use symcb to lookup symbol strings.
+
+ * i386_disasm.c (struct output_buffer): Add labelbuf, labelbufsize,
+ symaddr_use, and symaddr fields.
+ (i386_disasm): Remove labelbuf and labelbufsize variables.
+ Add back %e format. Implement %a and %l formats.
+
+ * i386_data.h (general_mod$r_m): Set symaddr_use and symaddr for %rip
+ base addressing.
+
+ * i386_disasm.c (i386_disasm): Resize output buffer if necessary.
+ Optimize output_data initialization. Free buffers before return.
+ (struct output_data): Remove op1str field. Adjust code.
+ (i386_disasm): Store final NUL btye at end of functions.
+
+2008-01-10 Ulrich Drepper <drepper@redhat.com>
+
+ * i386_data.h (FCT_crdb): New function.
+ (FCT_ccc): Use FCT_crdb.
+ (FCT_ddd): Likewise.
+
+ * defs/i386: Fix a few instructions with immediate arguments.
+
+ * i386_disasm.c: Rewrite interface to callback functions for operands
+ to take a single pointer to a structure.
+ * i386_data.h: Adjust all functions.
+
+2008-01-08 Ulrich Drepper <drepper@redhat.com>
+
+ * Makefile.am: Enable x86-64 again.
+ * defs/i386: Lots of changes for x86-64.
+ * i386_data.h: Add support for use in x86-64 disassembler.
+ * i386_disasm.c: Likewise.
+ * i386_parse.y: Likewise.
+ * defs/x86_64: Removed.
+
+2008-01-04 Ulrich Drepper <drepper@redhat.com>
+
+ * defs/i386: Cleanups, remove masks which are not needed.
+ Add remaining Intel opcodes.
+ * i386_data.h (FCT_imm8): Check for input buffer overrun.
+ * i386_disasm.c (i386_disasm): Likewise.
+ * i386_parse.y: Remove suffixes which are not needed anymore.
+
+2008-01-03 Ulrich Drepper <drepper@redhat.com>
+
+ * defs/i386: Add yet more SSE instructions.
+
+2008-01-02 Ulrich Drepper <drepper@redhat.com>
+
+ * i386_disasm.c (i386_disasm): Extend matcher to allow tables to
+ contain instructions with prefixes.
+ * defs/i386: Use for many SSE operations.
+ * i386_data.h (FCT_mmxreg2): Removed.
+
+2008-01-01 Ulrich Drepper <drepper@redhat.com>
+
+ * defs/i386: More 0f prefix support.
+ * i386_data.h (FCT_mmxreg): Implement.
+ (FCT_mmxreg2): Implement.
+ (FCT_mmreg): Remove.
+ * i386_disasm.c (i386_disasm): More special instructions.
+ Fix tttn suffix for cmov.
+ * i386_parse.y: Simplify test for mod/r_m mode.
+
+2007-12-31 Ulrich Drepper <drepper@redhat.com>
+
+ * defs/i386: Fix order or arguments for mov of control/debug registers.
+ * i386_data.h (FCT_ccc): Implement
+ (FCT_ddd): Implement
+
+2007-12-30 Ulrich Drepper <drepper@redhat.com>
+
+ * defs/i386: Fix 0f groups 6 and 7.
+ * i386_data.c (FCT_mod$16r_m): Implement.
+ * i386_disasm.c (i386_disasm): Third parameter can also have string.
+
+2007-12-29 Ulrich Drepper <drepper@redhat.com>
+
+ * defs/i386: Add lots of floating point ops.
+ * i386_data.h (FCT_fmod$fr_m): Removed.
+ (FCT_freg): Implement.
+ * i386_disasm.c (i386_disasm): Implement suffix_D.
+ * i386_parse.y: Emit suffix_D.
+
+ * defs/i386: Use rel instead of dispA.
+ Fix lcall, dec, div, idiv, imul, inc, jmp, ljmp, mul, neg, not, push,
+ test.
+
+ * i386_data.h (FCT_dispA): Removed.
+ (FCT_ds_xx): Add test for end of input buffer.
+ * i386_disasm.c (ABORT_ENTRY): Removed.
+ (i386_disasm): Fix handling of SIB. Pass correct address value to
+ operand callbacks.
+
+ * Makefile.am (*.mnemonics): Filter out INVALID entry.
+ * defs/i386: Define imms8 and use in appropriate places.
+ Add INVALID entries for special opcodes with special mnemonics.
+ Fix int3. Fix typo in shl. Correct xlat.
+ * i386_data.h (FCT_ds_xx): New function.
+ (FCT_ds_si): Use it.
+ (FCT_ds_bx): New function.
+ (FCT_imms8): New function.
+ * i386_disasm.c (MNE_INVALID): Define.
+ (i386_disasm): Handle invalid opcodes in mnemonics printing, not
+ separately. Fix address value passed to operand handlers.
+ * i386_parse.y (bx_reg): Define.
+ (instrtable_out): Handle INVALID entries differently, just use
+ MNE_INVALID value for .mnemonic.
+
+2007-12-28 Ulrich Drepper <drepper@redhat.com>
+
+ * defs/i386: Fix shift and mov immediate instructions.
+ * i386_data.h (FCT_imm16): Implement.
+
+ * defs/i386: Use absval instead of abs of lcall and ljmp.
+ Add parameters for cmps. Fix test and mov immediate.
+ * i386_data.h: Implement FCT_absval.
+ * i386_disasm.c: Handle data16 for suffix_w and FCT_imm.
+
+ * defs/i386: Move entries with 0x9b prefix together.
+ * i386_disasm.c (i386_disasm): Fix recognizing insufficient bytes in
+ input. Handle data16 with suffix_W.
+
+ * i386_data.h (FCT_*): Add end parameter to all functions. Check
+ before using more bytes.
+ (FCT_sel): Implement.
+ * i386_disasm.c (i386_disasm): Better handle end of input buffer.
+ Specal opcode 0x99.
+
+ * Makefile.am: Use m4 to preprocess defs/* files.
+ * defs/i386: Adjust appropriately.
+ * i386_data.c (FCT_ax): Implement.
+ (FCT_ax$w): Use FCT_ax.
+ * i386_disasm.c (ADD_STRING): Use _len instead of len.
+ (i386_disasm): If no instruction can be matched because of lack of
+ input and prefixes have been matched, print prefixes.
+ Recognize abort entries.
+ Handle special cases.
+ * i386_gendis.c: Recognize - input file name.
+ * i386_lex.c: Recognize INVALID token.
+ * i386_parse.y: Handle INVALID token input.
+
+ * defs/i386: Fix mov, pop.
+ * i386_data.h (FCT_sreg3): Implement.
+
+2007-12-27 Ulrich Drepper <drepper@redhat.com>
+
+ * defs/i386: Fix adc, add, cmp, or, sbb, sub, xchg, xor.
+ * i386_data.h (FCT_imms): New function.
+ (FCT_imm$s): Use FCT_imms for handling of signed values.
+ (FCT_imm8): Sign extend values.
+ * i386_disasm.c (i386_disasm): Implement suffix_w0.
+ * i386_parse.y: Emit suffix w0.
+
+ * i386_data.h (FCT_disp8): Add 0x prefix.
+ (FCT_ds_si): Implement.
+ * i386_disasm.c (i386_disasm): Increment addr for invalid prefixes.
+ Implement tttn suffix.
+ * i386_parse.y: Emit tttn suffix definition.
+
+2007-12-26 Ulrich Drepper <drepper@redhat.com>
+
+ * i386_data.h (struct instr_enc): Use suffix field.
+ (FCT_dx): Fill in body.
+ (FCT_es_di): Likewise.
+ (FCT_imm$s): Sign-extended byte values.
+ * i386_disasm.c: Protect ADD_CHAR and ADD_STRING macros. Adjust uses.
+ (i386_disasm): Handle suffix.
+ * i386_parse.y: Emit suffix information.
+ * defs/i386: Remove unnecessary suffixes.
+
+ * Makefile.am: Disable building x86-64 version for now.
+
+ * defs/i386: Fix and, bound, cmp, or, pop, sbb, sub, xor.
+ * i386_data.h: Pass pointer to prefix to functions. If not prefixes
+ are consumed this means invalid input.
+ * i386_disasm.c: Fix prefix printing. Adjust function calls for
+ parameter change.
+ * i386_parse.y: Recognize moda prefix.
+
+2007-12-21 Ulrich Drepper <drepper@redhat.com>
+
+ * i386_data.h: Fix SIB handling.
+ * i386_disasm.c: Likewise.
+
+2007-12-19 Ulrich Drepper <drepper@redhat.com>
+
+ * defs/i386: Fix up 'and' opcode.
+
+2007-10-31 Ulrich Drepper <drepper@redhat.com>
+
+ * Makefile.am: Add dependencies of the generated files on the source
+ files.
+ (i386_lex_CFLAGS): Add -Wno-sign-compare.
+
+ * defs/i386: A lot more data.
+ * defs/x86_64: Likewise.
+ * i386_data.h (struct instr_enc): Add off1_3, off2_3, and off3_3
+ fields.
+ (opfct_t): Add parameter for third operand.
+ (FCT_*): Likewise.
+ (data_prefix): New function.
+ (FCT_abs): Implement.
+ (FCT_ax): Renamed to FCT_ax$w amd implement.
+ (FCT_disp8): Implement.
+ (FCT_dispA): Implement.
+ (FCT_imm): Implement.
+ (FCT_imm$w): Implement.
+ (FCT_imm$s): Don't zero-pad numbers.
+ (FCT_imm8): Likewise.
+ (FCT_rel): Likewise.
+ (general_mod$r_m): New function.
+ (FCT_mod$r_m): Use it.
+ (FCT_mod$r_m$w): New function.
+ (FCT_mod$8r_m): New function.
+ (FCT_reg): Correctly handle 16-bit registers.
+ (FCT_reg$w): New function.
+ * i386_disasm.c (i386_disasm): Handle prefixes better.
+ Pass third parameter to operand functions.
+ * i386_parse.y (struct instruction): Add off3 field.
+ Handle third operand throughout.
+
+2007-02-05 Ulrich Drepper <drepper@redhat.com>
+
+ * i386_disasm.c: New file.
+ * i386_data.h: New file.
+ * i386_gendis.c: New file.
+ * i386_lex.l: New file.
+ * i386_parse.y: New file.
+ * memory-access.h: New file.
+ * x86_64_disasm.c: New file.
+ * defs/i386: New file.
+ * defs/i386.doc: New file.
+ * defs/x86_64: New file.
+
+2005-02-15 Ulrich Drepper <drepper@redhat.com>
+
+ * Makefile (AM_CFLAGS): Add -Wunused -Wextra -Wformat=2.
+
+2005-02-05 Ulrich Drepper <drepper@redhat.com>
+
+ * Makefile.am (AM_CFLAGS): Define, instead of adding things to DEFS.
+
+2003-08-11 Ulrich Drepper <drepper@redhat.com>
+
+ * Moved to CVS archive.
diff --git a/libcpu/Makefile.am b/libcpu/Makefile.am
new file mode 100644
index 0000000..c62db6d
--- /dev/null
+++ b/libcpu/Makefile.am
@@ -0,0 +1,72 @@
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 2002-2010 Red Hat, Inc.
+## This file is part of Red Hat elfutils.
+##
+## Red Hat elfutils 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; version 2 of the License.
+##
+## Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation,
+## Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+##
+## Red Hat elfutils is an included package of the Open Invention Network.
+## An included package of the Open Invention Network is a package for which
+## Open Invention Network licensees cross-license their patents. No patent
+## license is granted, either expressly or impliedly, by designation as an
+## included package. Should you wish to participate in the Open Invention
+## Network licensing program, please visit www.openinventionnetwork.com
+## <http://www.openinventionnetwork.com>.
+##
+include $(top_srcdir)/config/eu.am
+INCLUDES += -I$(srcdir)/../libelf -I$(srcdir)/../libebl \
+ -I$(srcdir)/../libdw -I$(srcdir)/../libasm
+AM_CFLAGS += -fpic -fdollars-in-identifiers
+LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS) -P$(<F:lex.l=)
+LEX_OUTPUT_ROOT = lex.$(<F:lex.l=)
+AM_YFLAGS = -p$(<F:parse.y=)
+
+noinst_LIBRARIES = libcpu_i386.a libcpu_x86_64.a
+noinst_PROGRAMS = i386_gendis
+
+libcpu_i386_a_SOURCES = i386_disasm.c
+libcpu_x86_64_a_SOURCES = x86_64_disasm.c
+
+i386_gendis_SOURCES = i386_gendis.c i386_lex.l i386_parse.y
+
+i386_disasm.o: i386.mnemonics i386_dis.h
+x86_64_disasm.o: x86_64.mnemonics x86_64_dis.h i386_disasm.c
+
+%_defs: $(srcdir)/defs/i386
+ m4 -D$* -DDISASSEMBLER $< > $@
+
+%_dis.h: %_defs i386_gendis
+ ./i386_gendis $< > $@
+
+%.mnemonics: %_defs
+ sed '1,/^%%/d;/^#/d;/^[[:space:]]*$$/d;s/[^:]*:\([^[:space:]]*\).*/MNE(\1)/;s/{[^}]*}//g;/INVALID/d' \
+ $< | sort -u > $@
+
+i386_lex_no_Werror = yes
+
+libeu = ../lib/libeu.a
+
+i386_lex_CFLAGS = -Wno-unused-label -Wno-unused-function -Wno-sign-compare
+i386_parse.o: i386_parse.c i386.mnemonics
+i386_parse_CFLAGS = -DNMNES="`wc -l < i386.mnemonics`"
+i386_lex.o: i386_parse.h
+i386_gendis_LDADD = $(libeu) -lm $(libmudflap)
+
+i386_parse.h: i386_parse.c ;
+
+noinst_HEADERS = memory-access.h i386_parse.h i386_data.h
+
+EXTRA_DIST = defs/i386
+
+CLEANFILES += $(foreach P,i386 x86_64,$P_defs $P.mnemonics $P_dis.h)
diff --git a/libcpu/Makefile.in b/libcpu/Makefile.in
new file mode 100644
index 0000000..8da9935
--- /dev/null
+++ b/libcpu/Makefile.in
@@ -0,0 +1,547 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(top_srcdir)/config/eu.am ChangeLog \
+ i386_lex.c i386_parse.c
+@MUDFLAP_TRUE@am__append_1 = -fmudflap
+noinst_PROGRAMS = i386_gendis$(EXEEXT)
+subdir = libcpu
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
+ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/zip.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libcpu_i386_a_AR = $(AR) $(ARFLAGS)
+libcpu_i386_a_LIBADD =
+am_libcpu_i386_a_OBJECTS = i386_disasm.$(OBJEXT)
+libcpu_i386_a_OBJECTS = $(am_libcpu_i386_a_OBJECTS)
+libcpu_x86_64_a_AR = $(AR) $(ARFLAGS)
+libcpu_x86_64_a_LIBADD =
+am_libcpu_x86_64_a_OBJECTS = x86_64_disasm.$(OBJEXT)
+libcpu_x86_64_a_OBJECTS = $(am_libcpu_x86_64_a_OBJECTS)
+PROGRAMS = $(noinst_PROGRAMS)
+am_i386_gendis_OBJECTS = i386_gendis.$(OBJEXT) i386_lex.$(OBJEXT) \
+ i386_parse.$(OBJEXT)
+i386_gendis_OBJECTS = $(am_i386_gendis_OBJECTS)
+am__DEPENDENCIES_1 =
+i386_gendis_DEPENDENCIES = $(libeu) $(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+@MAINTAINER_MODE_FALSE@am__skiplex = test -f $@ ||
+YLWRAP = $(top_srcdir)/config/ylwrap
+@MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ ||
+YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
+SOURCES = $(libcpu_i386_a_SOURCES) $(libcpu_x86_64_a_SOURCES) \
+ $(i386_gendis_SOURCES)
+DIST_SOURCES = $(libcpu_i386_a_SOURCES) $(libcpu_x86_64_a_SOURCES) \
+ $(i386_gendis_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEBUGPRED = @DEBUGPRED@
+DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DLOCALEDIR='"${localedir}"'
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EXEEXT = @EXEEXT@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = lex.$(<F:lex.l=)
+LIBEBL_SUBDIR = @LIBEBL_SUBDIR@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MODVERSION = @MODVERSION@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+base_cpu = @base_cpu@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+eu_version = @eu_version@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+zip_LIBS = @zip_LIBS@
+INCLUDES = -I. -I$(srcdir) -I$(top_srcdir)/lib -I.. \
+ -I$(srcdir)/../libelf -I$(srcdir)/../libebl \
+ -I$(srcdir)/../libdw -I$(srcdir)/../libasm
+AM_CFLAGS = -std=gnu99 -Wall -Wshadow $(if \
+ $($(*F)_no_Werror),,-Werror) $(if \
+ $($(*F)_no_Wunused),,-Wunused -Wextra) $(if \
+ $($(*F)_no_Wformat),-Wno-format,-Wformat=2) $($(*F)_CFLAGS) \
+ $(am__append_1) -fpic -fdollars-in-identifiers
+@MUDFLAP_FALSE@libmudflap =
+@MUDFLAP_TRUE@libmudflap = -lmudflap
+COMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage $(no_mudflap.os),\
+ $(COMPILE))
+
+CLEANFILES = *.gcno *.gcda $(foreach P,i386 x86_64,$P_defs \
+ $P.mnemonics $P_dis.h)
+textrel_check = if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi
+LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS) -P$(<F:lex.l=)
+AM_YFLAGS = -p$(<F:parse.y=)
+noinst_LIBRARIES = libcpu_i386.a libcpu_x86_64.a
+libcpu_i386_a_SOURCES = i386_disasm.c
+libcpu_x86_64_a_SOURCES = x86_64_disasm.c
+i386_gendis_SOURCES = i386_gendis.c i386_lex.l i386_parse.y
+i386_lex_no_Werror = yes
+libeu = ../lib/libeu.a
+i386_lex_CFLAGS = -Wno-unused-label -Wno-unused-function -Wno-sign-compare
+i386_parse_CFLAGS = -DNMNES="`wc -l < i386.mnemonics`"
+i386_gendis_LDADD = $(libeu) -lm $(libmudflap)
+noinst_HEADERS = memory-access.h i386_parse.h i386_data.h
+EXTRA_DIST = defs/i386
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .l .o .obj .y
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/config/eu.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits libcpu/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnits libcpu/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libcpu_i386.a: $(libcpu_i386_a_OBJECTS) $(libcpu_i386_a_DEPENDENCIES)
+ -rm -f libcpu_i386.a
+ $(libcpu_i386_a_AR) libcpu_i386.a $(libcpu_i386_a_OBJECTS) $(libcpu_i386_a_LIBADD)
+ $(RANLIB) libcpu_i386.a
+libcpu_x86_64.a: $(libcpu_x86_64_a_OBJECTS) $(libcpu_x86_64_a_DEPENDENCIES)
+ -rm -f libcpu_x86_64.a
+ $(libcpu_x86_64_a_AR) libcpu_x86_64.a $(libcpu_x86_64_a_OBJECTS) $(libcpu_x86_64_a_LIBADD)
+ $(RANLIB) libcpu_x86_64.a
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+i386_gendis$(EXEEXT): $(i386_gendis_OBJECTS) $(i386_gendis_DEPENDENCIES)
+ @rm -f i386_gendis$(EXEEXT)
+ $(LINK) $(i386_gendis_OBJECTS) $(i386_gendis_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i386_disasm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i386_gendis.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i386_lex.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i386_parse.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x86_64_disasm.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.l.c:
+ $(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
+
+.y.c:
+ $(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE)
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -rm -f i386_lex.c
+ -rm -f i386_parse.c
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES clean-noinstPROGRAMS ctags distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am
+
+
+%.os: %.c %.o
+@AMDEP_TRUE@ if $(COMPILE.os) -c -o $@ -fpic -DPIC -DSHARED -MT $@ -MD -MP \
+@AMDEP_TRUE@ -MF "$(DEPDIR)/$*.Tpo" `test -f '$<' || echo '$(srcdir)/'`$<; \
+@AMDEP_TRUE@ then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \
+@AMDEP_TRUE@ rm -f "$(DEPDIR)/$*.Tpo"; \
+@AMDEP_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@AMDEP_TRUE@ fi
+@AMDEP_FALSE@ $(COMPILE.os) -c -o $@ -fpic -DPIC -DSHARED $<
+
+i386_disasm.o: i386.mnemonics i386_dis.h
+x86_64_disasm.o: x86_64.mnemonics x86_64_dis.h i386_disasm.c
+
+%_defs: $(srcdir)/defs/i386
+ m4 -D$* -DDISASSEMBLER $< > $@
+
+%_dis.h: %_defs i386_gendis
+ ./i386_gendis $< > $@
+
+%.mnemonics: %_defs
+ sed '1,/^%%/d;/^#/d;/^[[:space:]]*$$/d;s/[^:]*:\([^[:space:]]*\).*/MNE(\1)/;s/{[^}]*}//g;/INVALID/d' \
+ $< | sort -u > $@
+i386_parse.o: i386_parse.c i386.mnemonics
+i386_lex.o: i386_parse.h
+
+i386_parse.h: i386_parse.c ;
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libcpu/defs/i386 b/libcpu/defs/i386
new file mode 100644
index 0000000..e0db28d
--- /dev/null
+++ b/libcpu/defs/i386
@@ -0,0 +1,970 @@
+%mask {s} 1
+%mask {w} 1
+%mask {w1} 1
+%mask {W1} 1
+%mask {W2} 1
+dnl floating point reg suffix
+%mask {D} 1
+%mask {imm8} 8
+%mask {imms8} 8
+%mask {imm16} 16
+%mask {reg} 3
+%mask {oreg} 3
+%mask {reg16} 3
+%mask {reg64} 3
+%mask {tttn} 4
+%mask {mod} 2
+%mask {moda} 2
+%mask {MOD} 2
+%mask {r_m} 3
+dnl like {r_m} but referencing byte register
+%mask {8r_m} 3
+dnl like {r_m} but referencing 16-bit register
+%mask {16r_m} 3
+dnl like {r_m} but referencing 32- or 64-bit register
+%mask {64r_m} 3
+%mask {disp8} 8
+dnl imm really is 8/16/32 bit depending on the situation.
+%mask {imm} 8
+%mask {imm64} 8
+%mask {imms} 8
+%mask {rel} 32
+%mask {abs} 32
+%mask {absval} 32
+%mask {sel} 16
+%mask {imm32} 32
+%mask {ccc} 3
+%mask {ddd} 3
+%mask {sreg3} 3
+%mask {sreg2} 2
+%mask {mmxreg} 3
+%mask {R_M} 3
+%mask {Mod} 2
+%mask {xmmreg} 3
+%mask {R_m} 3
+%mask {xmmreg1} 3
+%mask {xmmreg2} 3
+%mask {mmxreg1} 3
+%mask {mmxreg2} 3
+%mask {predps} 8
+%mask {freg} 3
+%mask {fmod} 2
+%mask {fr_m} 3
+%prefix {R}
+%prefix {RE}
+%suffix {W}
+%suffix {w0}
+%synonym {xmmreg1} {xmmreg}
+%synonym {xmmreg2} {xmmreg}
+%synonym {mmxreg1} {mmxreg}
+%synonym {mmxreg2} {mmxreg}
+ifdef(`i386',
+`%synonym {oreg} {reg}
+%synonym {imm64} {imm}
+')dnl
+
+%%
+ifdef(`i386',
+`00110111:aaa
+11010101,00001010:aad
+11010100,00001010:aam
+00111111:aas
+')dnl
+0001010{w},{imm}:adc {imm}{w},{ax}{w}
+1000000{w},{mod}010{r_m},{imm}:adc{w} {imm}{w},{mod}{r_m}{w}
+1000001{w},{mod}010{r_m},{imms8}:adc{w} {imms8},{mod}{r_m}
+0001000{w},{mod}{reg}{r_m}:adc {reg}{w},{mod}{r_m}{w}
+0001001{w},{mod}{reg}{r_m}:adc {mod}{r_m}{w},{reg}{w}
+0000010{w},{imm}:add {imm}{w},{ax}{w}
+1000000{w},{mod}000{r_m},{imm}:add{w} {imm}{w},{mod}{r_m}{w}
+10000011,{mod}000{r_m},{imms8}:add{w} {imms8},{mod}{r_m}
+0000000{w},{mod}{reg}{r_m}:add {reg}{w},{mod}{r_m}{w}
+0000001{w},{mod}{reg}{r_m}:add {mod}{r_m}{w},{reg}{w}
+01100110,00001111,11010000,{Mod}{xmmreg}{R_m}:addsubpd {Mod}{R_m},{xmmreg}
+11110010,00001111,11010000,{Mod}{xmmreg}{R_m}:addsubps {Mod}{R_m},{xmmreg}
+0010010{w},{imm}:and {imm}{w},{ax}{w}
+1000000{w},{mod}100{r_m},{imm}:and{w} {imm}{w},{mod}{r_m}{w}
+1000001{w},{mod}100{r_m},{imms8}:and{w} {imms8},{mod}{r_m}
+0010000{w},{mod}{reg}{r_m}:and {reg}{w},{mod}{r_m}{w}
+0010001{w},{mod}{reg}{r_m}:and {mod}{r_m}{w},{reg}{w}
+01100110,00001111,01010100,{Mod}{xmmreg}{R_m}:andpd {Mod}{R_m},{xmmreg}
+00001111,01010100,{Mod}{xmmreg}{R_m}:andps {Mod}{R_m},{xmmreg}
+01100110,00001111,01010101,{Mod}{xmmreg}{R_m}:andnpd {Mod}{R_m},{xmmreg}
+00001111,01010101,{Mod}{xmmreg}{R_m}:andnps {Mod}{R_m},{xmmreg}
+ifdef(`i386',
+`01100011,{mod}{reg16}{r_m}:arpl {reg16},{mod}{r_m}
+01100010,{moda}{reg}{r_m}:bound {reg},{moda}{r_m}
+',
+`01100011,{mod}{reg64}{r_m}:movslq {mod}{r_m},{reg64}
+')dnl
+00001111,10111100,{mod}{reg}{r_m}:bsf {mod}{r_m},{reg}
+00001111,10111101,{mod}{reg}{r_m}:bsr {mod}{r_m},{reg}
+00001111,11001{reg}:bswap {reg}
+00001111,10100011,{mod}{reg}{r_m}:bt {reg},{mod}{r_m}
+00001111,10111010,{mod}100{r_m},{imm8}:bt{w} {imm8},{mod}{r_m}
+00001111,10111011,{mod}{reg}{r_m}:btc {reg},{mod}{r_m}
+00001111,10111010,{mod}111{r_m},{imm8}:btc{w} {imm8},{mod}{r_m}
+00001111,10110011,{mod}{reg}{r_m}:btr {reg},{mod}{r_m}
+00001111,10111010,{mod}110{r_m},{imm8}:btr{w} {imm8},{mod}{r_m}
+00001111,10101011,{mod}{reg}{r_m}:bts {reg},{mod}{r_m}
+00001111,10111010,{mod}101{r_m},{imm8}:bts{w} {imm8},{mod}{r_m}
+11101000,{rel}:call{W} {rel}
+11111111,{mod}010{64r_m}:call{W} *{mod}{64r_m}
+ifdef(`i386',
+`10011010,{absval},{sel}:lcall {sel},{absval}
+')dnl
+11111111,{mod}011{64r_m}:lcall{W} *{mod}{64r_m}
+# SPECIAL 10011000:[{rex.w}?cltq:{dpfx}?cbtw:cwtl]
+10011000:INVALID
+# SPECIAL 10011001:[{rex.w}?cqto:{dpfx}?cltd:cwtd]
+10011001:INVALID
+11111000:clc
+11111100:cld
+11111010:cli
+00001111,00000101:syscall
+00001111,00000110:clts
+00001111,00000111:sysret
+00001111,00110100:sysenter
+00001111,00110101:sysexit
+11110101:cmc
+00001111,0100{tttn},{mod}{reg}{r_m}:cmov{tttn} {mod}{r_m},{reg}
+0011110{w},{imm}:cmp {imm}{w},{ax}{w}
+1000000{w},{mod}111{r_m},{imm}:cmp{w} {imm}{w},{mod}{r_m}{w}
+10000011,{mod}111{r_m},{imms8}:cmp{w} {imms8},{mod}{r_m}
+0011100{w},{mod}{reg}{r_m}:cmp {reg}{w},{mod}{r_m}{w}
+0011101{w},{mod}{reg}{r_m}:cmp {mod}{r_m}{w},{reg}{w}
+ifdef(`ASSEMBLER',
+`11110010,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:cmpsd {imm8},{Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:cmpss {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:cmppd {imm8},{Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:cmpps {imm8},{Mod}{R_m},{xmmreg}
+',
+`11110010,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:INVALID {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:INVALID {Mod}{R_m},{xmmreg}
+01100110,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:INVALID {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:INVALID {Mod}{R_m},{xmmreg}
+')dnl
+1010011{w}:{RE}cmps{w} {es_di},{ds_si}
+00001111,1011000{w},{mod}{reg}{r_m}:cmpxchg {reg}{w},{mod}{r_m}{w}
+ifdef(`i386',
+`00001111,11000111,{mod}001{r_m}:cmpxchg8b {mod}{r_m}
+',
+`# SPECIAL 00001111,11000111,{mod}001{r_m}:[{rex.w}?cmpxchg16b:cmpxchg8b] {reg},{mod}{r_m}
+00001111,11000111,{mod}001{r_m}:INVALID {mod}{r_m}
+')dnl
+00001111,10100010:cpuid
+11110011,00001111,11100110,{Mod}{xmmreg}{R_m}:cvtdq2pd {Mod}{R_m},{xmmreg}
+11110010,00001111,11100110,{Mod}{xmmreg}{R_m}:cvtpd2dq {Mod}{R_m},{xmmreg}
+01100110,00001111,11100110,{Mod}{xmmreg}{R_m}:cvttpd2dq {Mod}{R_m},{xmmreg}
+ifdef(`i386',
+`00100111:daa
+00101111:das
+')dnl
+1111111{w},{mod}001{r_m}:dec{w} {mod}{r_m}{w}
+ifdef(`i386',
+`01001{reg}:dec {reg}
+')dnl
+1111011{w},{mod}110{r_m}:div{w} {mod}{r_m}{w}
+00001111,01110111:emms
+11001000,{imm16},{imm8}:enter{W} {imm16},{imm8}
+11011001,11010000:fnop
+11011001,11100000:fchs
+11011001,11100001:fabs
+11011001,11100100:ftst
+11011001,11100101:fxam
+11011001,11101000:fld1
+11011001,11101001:fldl2t
+11011001,11101010:fldl2e
+11011001,11101011:fldpi
+11011001,11101100:fldlg2
+11011001,11101101:fldln2
+11011001,11101110:fldz
+11011001,11110000:f2xm1
+11011001,11110001:fyl2x
+11011001,11110010:fptan
+11011001,11110011:fpatan
+11011001,11110100:fxtract
+11011001,11110101:fprem1
+11011001,11110110:fdecstp
+11011001,11110111:fincstp
+11011001,11111000:fprem
+11011001,11111001:fyl2xp1
+11011001,11111010:fsqrt
+11011001,11111011:fsincos
+11011001,11111100:frndint
+11011001,11111101:fscale
+11011001,11111110:fsin
+11011001,11111111:fcos
+# ORDER
+11011000,11000{freg}:fadd {freg},%st
+11011100,11000{freg}:fadd %st,{freg}
+11011{D}00,{mod}000{r_m}:fadd{D} {mod}{r_m}
+# ORDER END
+# ORDER
+11011000,11001{freg}:fmul {freg},%st
+11011100,11001{freg}:fmul %st,{freg}
+11011{D}00,{mod}001{r_m}:fmul{D} {mod}{r_m}
+# ORDER END
+# ORDER
+11011000,11100{freg}:fsub {freg},%st
+11011100,11100{freg}:fsub %st,{freg}
+11011{D}00,{mod}100{r_m}:fsub{D} {mod}{r_m}
+# ORDER END
+# ORDER
+11011000,11101{freg}:fsubr {freg},%st
+11011100,11101{freg}:fsubr %st,{freg}
+11011{D}00,{mod}101{r_m}:fsubr{D} {mod}{r_m}
+# ORDER END
+# ORDER
+11011101,11010{freg}:fst {freg}
+11011{D}01,{mod}010{r_m}:fst{D} {mod}{r_m}
+# ORDER END
+# ORDER
+11011101,11011{freg}:fstp {freg}
+11011{D}01,{mod}011{r_m}:fstp{D} {mod}{r_m}
+# ORDER END
+11011001,{mod}100{r_m}:fldenv {mod}{r_m}
+11011001,{mod}101{r_m}:fldcw {mod}{r_m}
+11011001,{mod}110{r_m}:fnstenv {mod}{r_m}
+11011001,{mod}111{r_m}:fnstcw {mod}{r_m}
+11011001,11001{freg}:fxch {freg}
+# ORDER
+11011110,11000{freg}:faddp %st,{freg}
+ifdef(`ASSEMBLER',
+`11011110,11000001:faddp
+')dnl
+# ORDER
+11011010,11000{freg}:fcmovb {freg},%st
+11011{w1}10,{mod}000{r_m}:fiadd{w1} {mod}{r_m}
+# ORDER END
+# ORDER
+11011010,11001{freg}:fcmove {freg},%st
+11011110,11001{freg}:fmulp %st,{freg}
+11011{w1}10,{mod}001{r_m}:fimul{w1} {mod}{r_m}
+# ORDER END
+# ORDER
+11011110,11100{freg}:fsubp %st,{freg}
+11011{w1}10,{mod}100{r_m}:fisub{w1} {mod}{r_m}
+# ORDER END
+# ORDER
+11011110,11101{freg}:fsubrp %st,{freg}
+11011{w1}10,{mod}101{r_m}:fisubr{w1} {mod}{r_m}
+# ORDER END
+# ORDER
+11011111,11100000:fnstsw %ax
+11011111,{mod}100{r_m}:fbld {mod}{r_m}
+# ORDER END
+# ORDER
+11011111,11110{freg}:fcomip {freg},%st
+11011111,{mod}110{r_m}:fbstp {mod}{r_m}
+# ORDER END
+11011001,11100000:fchs
+# ORDER
+10011011,11011011,11100010:fclex
+10011011,11011011,11100011:finit
+10011011:fwait
+# END ORDER
+11011011,11100010:fnclex
+11011010,11000{freg}:fcmovb {freg},%st
+11011010,11001{freg}:fcmove {freg},%st
+11011010,11010{freg}:fcmovbe {freg},%st
+11011010,11011{freg}:fcmovu {freg},%st
+11011011,11000{freg}:fcmovnb {freg},%st
+11011011,11001{freg}:fcmovne {freg},%st
+11011011,11010{freg}:fcmovnbe {freg},%st
+11011011,11011{freg}:fcmovnu {freg},%st
+# ORDER
+11011000,11010{freg}:fcom {freg}
+ifdef(`ASSEMBLER',
+`11011000,11010001:fcom
+')dnl
+11011{D}00,{mod}010{r_m}:fcom{D} {mod}{r_m}
+# END ORDER
+# ORDER
+11011000,11011{freg}:fcomp {freg}
+ifdef(`ASSEMBLER',
+`11011000,11011001:fcomp
+')dnl
+11011{D}00,{mod}011{r_m}:fcomp{D} {mod}{r_m}
+# END ORDER
+11011110,11011001:fcompp
+11011011,11110{freg}:fcomi {freg},%st
+11011111,11110{freg}:fcomip {freg},%st
+11011011,11101{freg}:fucomi {freg},%st
+11011111,11101{freg}:fucomip {freg},%st
+11011001,11111111:fcos
+11011001,11110110:fdecstp
+# ORDER
+11011000,11110{freg}:fdiv {freg},%st
+11011100,11110{freg}:fdiv %st,{freg}
+11011{D}00,{mod}110{r_m}:fdiv{D} {mod}{r_m}
+# END ORDER
+11011010,{mod}110{r_m}:fidivl {mod}{r_m}
+# ORDER
+11011110,11110{freg}:fdivp %st,{freg}
+11011110,{mod}110{r_m}:fidiv {mod}{r_m}
+# END ORDER
+11011110,11111{freg}:fdivrp %st,{freg}
+ifdef(`ASSEMBLER',
+`11011110,11111001:fdivp
+')dnl
+# ORDER
+11011000,11111{freg}:fdivr {freg},%st
+11011100,11111{freg}:fdivr %st,{freg}
+11011{D}00,{mod}111{r_m}:fdivr{D} {mod}{r_m}
+# END ORDER
+11011010,{mod}111{r_m}:fidivrl {mod}{r_m}
+11011110,{mod}111{r_m}:fidivr {mod}{r_m}
+11011110,11110{freg}:fdivrp %st,{freg}
+ifdef(`ASSEMBLER',
+`11011110,11110001:fdivrp
+')dnl
+11011101,11000{freg}:ffree {freg}
+11011010,11010{freg}:fcmovbe {freg}
+11011{w1}10,{mod}010{r_m}:ficom{w1} {mod}{r_m}
+11011010,11011{freg}:fcmovu {freg}
+11011{w1}10,{mod}011{r_m}:ficomp{w1} {mod}{r_m}
+11011111,{mod}000{r_m}:fild {mod}{r_m}
+11011011,{mod}000{r_m}:fildl {mod}{r_m}
+11011111,{mod}101{r_m}:fildll {mod}{r_m}
+11011001,11110111:fincstp
+11011011,11100011:fninit
+11011{w1}11,{mod}010{r_m}:fist{w1} {mod}{r_m}
+11011{w1}11,{mod}011{r_m}:fistp{w1} {mod}{r_m}
+11011111,{mod}111{r_m}:fistpll {mod}{r_m}
+11011{w1}11,{mod}001{r_m}:fisttp{w1} {mod}{r_m}
+11011101,{mod}001{r_m}:fisttpll {mod}{r_m}
+11011011,{mod}101{r_m}:fldt {mod}{r_m}
+11011011,{mod}111{r_m}:fstpt {mod}{r_m}
+# ORDER
+11011001,11000{freg}:fld {freg}
+11011{D}01,{mod}000{r_m}:fld{D} {mod}{r_m}
+# ORDER END
+# ORDER
+11011101,11100{freg}:fucom {freg}
+11011101,{mod}100{r_m}:frstor {mod}{r_m}
+# ORDER END
+11011101,11101{freg}:fucomp {freg}
+11011101,{mod}110{r_m}:fnsave {mod}{r_m}
+11011101,{mod}111{r_m}:fnstsw {mod}{r_m}
+#
+#
+#
+11110100:hlt
+1111011{w},{mod}111{r_m}:idiv{w} {mod}{r_m}{w}
+1111011{w},{mod}101{r_m}:imul{w} {mod}{r_m}{w}
+00001111,10101111,{mod}{reg}{r_m}:imul {mod}{r_m},{reg}
+011010{s}1,{mod}{reg}{r_m},{imm}:imul {imm}{s},{mod}{r_m},{reg}
+1110010{w},{imm8}:in {imm8},{ax}{w}
+1110110{w}:in {dx},{ax}{w}
+1111111{w},{mod}000{r_m}:inc{w} {mod}{r_m}{w}
+ifdef(`i386',
+`01000{reg}:inc {reg}
+')dnl
+0110110{w}:{R}ins{w} {dx},{es_di}
+11001101,{imm8}:int {imm8}
+11001100:int3
+ifdef(`i386',
+`11001110:into
+')dnl
+00001111,00001000:invd
+# ORDER
+00001111,00000001,11111000:swapgs
+00001111,00000001,{mod}111{r_m}:invlpg {mod}{r_m}
+# ORDER END
+11001111:iret{W1}
+0111{tttn},{disp8}:j{tttn} {disp8}
+00001111,1000{tttn},{rel}:j{tttn} {rel}
+00001111,1001{tttn},{mod}000{8r_m}:set{tttn} {mod}{8r_m}
+# SPECIAL 11100011,{disp8}:[{dpfx}?jcxz:jecxz] {disp8}
+11100011,{disp8}:INVALID {disp8}
+11101011,{disp8}:jmp {disp8}
+11101001,{rel}:jmp{W} {rel}
+11111111,{mod}100{64r_m}:jmp{W} *{mod}{64r_m}
+11101010,{absval},{sel}:ljmp {sel},{absval}
+11111111,{mod}101{64r_m}:ljmp{W} *{mod}{64r_m}
+10011111:lahf
+00001111,00000010,{mod}{reg}{16r_m}:lar {mod}{16r_m},{reg}
+ifdef(`i386',
+`11000101,{mod}{reg}{r_m}:lds {mod}{r_m},{reg}
+')dnl
+10001101,{mod}{reg}{r_m}:lea {mod}{r_m},{reg}
+11001001:leave{W}
+ifdef(`i386',
+`11000100,{mod}{reg}{r_m}:les {mod}{r_m},{reg}
+')dnl
+00001111,10110100,{mod}{reg}{r_m}:lfs {mod}{r_m},{reg}
+00001111,10110101,{mod}{reg}{r_m}:lgs {mod}{r_m},{reg}
+ifdef(`i386',
+`00001111,00000001,{mod}010{r_m}:lgdt{w0} {mod}{r_m}
+00001111,00000001,{mod}011{r_m}:lidt{w0} {mod}{r_m}
+',
+`00001111,00000001,{mod}010{r_m}:lgdt {mod}{r_m}
+00001111,00000001,{mod}011{r_m}:lidt {mod}{r_m}
+')dnl
+00001111,00000000,{mod}010{16r_m}:lldt {mod}{16r_m}
+00001111,00000001,{mod}110{16r_m}:lmsw {mod}{16r_m}
+11110000:lock
+1010110{w}:{R}lods {ds_si},{ax}{w}
+11100010,{disp8}:loop {disp8}
+11100001,{disp8}:loope {disp8}
+11100000,{disp8}:loopne {disp8}
+00001111,00000011,{mod}{reg}{16r_m}:lsl {mod}{16r_m},{reg}
+00001111,10110010,{mod}{reg}{r_m}:lss {mod}{r_m},{reg}
+00001111,00000000,{mod}011{16r_m}:ltr {mod}{16r_m}
+1000100{w},{mod}{reg}{r_m}:mov {reg}{w},{mod}{r_m}{w}
+1000101{w},{mod}{reg}{r_m}:mov {mod}{r_m}{w},{reg}{w}
+1100011{w},{mod}000{r_m},{imm}:mov{w} {imm}{w},{mod}{r_m}{w}
+1011{w}{oreg},{imm64}:mov {imm64}{w},{oreg}{w}
+1010000{w},{abs}:mov {abs},{ax}{w}
+1010001{w},{abs}:mov {ax}{w},{abs}
+00001111,00100000,11{ccc}{reg64}:mov {ccc},{reg64}
+00001111,00100010,11{ccc}{reg64}:mov {reg64},{ccc}
+00001111,00100001,11{ddd}{reg64}:mov {ddd},{reg64}
+00001111,00100011,11{ddd}{reg64}:mov {reg64},{ddd}
+10001100,{mod}{sreg3}{r_m}:mov {sreg3},{mod}{r_m}
+10001110,{mod}{sreg3}{r_m}:mov {mod}{r_m},{sreg3}
+1010010{w}:{R}movs{w} {ds_si},{es_di}
+00001111,10111110,{mod}{reg}{8r_m}:movsbl {mod}{8r_m},{reg}
+00001111,10111111,{mod}{reg}{16r_m}:movswl {mod}{16r_m},{reg}
+00001111,10110110,{mod}{reg}{8r_m}:movzbl {mod}{8r_m},{reg}
+00001111,10110111,{mod}{reg}{16r_m}:movzwl {mod}{16r_m},{reg}
+1111011{w},{mod}100{r_m}:mul{w} {mod}{r_m}{w}
+1111011{w},{mod}011{r_m}:neg{w} {mod}{r_m}{w}
+11110011,10010000:pause
+ifdef(`i386',
+`10010000:nop
+',
+`10010000:INVALID
+')dnl
+# ORDER before out
+11110011,00001111,10111000,{mod}{reg}{r_m}:popcnt {mod}{r_m},{reg}
+# END ORDER
+1111011{w},{mod}010{r_m}:not{w} {mod}{r_m}{w}
+0000100{w},{mod}{reg}{r_m}:or {reg}{w},{mod}{r_m}{w}
+0000101{w},{mod}{reg}{r_m}:or {mod}{r_m}{w},{reg}{w}
+1000000{w},{mod}001{r_m},{imm}:or{w} {imm}{w},{mod}{r_m}{w}
+1000001{w},{mod}001{r_m},{imms8}:or{w} {imms8},{mod}{r_m}{w}
+0000110{w},{imm}:or {imm}{w},{ax}{w}
+1110011{w},{imm8}:out {ax}{w},{imm8}
+1110111{w}:out {ax}{w},{dx}
+0110111{w}:{R}outs{w} {ds_si},{dx}
+ifdef(`i386',
+`10001111,{mod}000{r_m}:pop{w} {mod}{r_m}
+',
+# XXX This is not the cleanest way...
+`10001111,11000{reg64}:pop {reg64}
+10001111,{mod}000{r_m}:pop{W} {mod}{r_m}
+')dnl
+00001111,10{sreg3}001:pop{W} {sreg3}
+10011101:popf{W}
+# XXX This is not the cleanest way...
+ifdef(`i386',
+`11111111,{mod}110{r_m}:push{w} {mod}{r_m}
+',
+`11111111,11110{reg64}:push {reg64}
+11111111,{mod}110{r_m}:pushq {mod}{r_m}
+')dnl
+ifdef(`i386',
+`01010{reg}:push {reg}
+01011{reg}:pop {reg}
+',
+`01010{reg64}:push {reg64}
+01011{reg64}:pop {reg64}
+')dnl
+011010{s}0,{imm}:push{W} {imm}{s}
+000{sreg2}110:push {sreg2}
+00001111,10{sreg3}000:push{W} {sreg3}
+ifdef(`i386',
+`01100000:pusha{W}
+01100001:popa{W}
+')dnl
+10011100:pushf{W}
+1101000{w},{mod}010{r_m}:rcl{w} {mod}{r_m}{w}
+1101001{w},{mod}010{r_m}:rcl{w} %cl,{mod}{r_m}{w}
+1100000{w},{mod}010{r_m},{imm8}:rcl{w} {imm8},{mod}{r_m}{w}
+1101000{w},{mod}011{r_m}:rcr{w} {mod}{r_m}{w}
+1101001{w},{mod}011{r_m}:rcr{w} %cl,{mod}{r_m}{w}
+1100000{w},{mod}011{r_m},{imm8}:rcr{w} {imm8},{mod}{r_m}{w}
+00001111,00110010:rdmsr
+00001111,00110011:rdpmc
+00001111,00110001:rdtsc
+11000011:ret{W}
+11000010,{imm16}:ret{W} {imm16}
+11001011:lret
+11001010,{imm16}:lret {imm16}
+1101000{w},{mod}000{r_m}:rol{w} {mod}{r_m}{w}
+1101001{w},{mod}000{r_m}:rol{w} %cl,{mod}{r_m}{w}
+1100000{w},{mod}000{r_m},{imm8}:rol{w} {imm8},{mod}{r_m}{w}
+1101000{w},{mod}001{r_m}:ror{w} {mod}{r_m}{w}
+1101001{w},{mod}001{r_m}:ror{w} %cl,{mod}{r_m}{w}
+1100000{w},{mod}001{r_m},{imm8}:ror{w} {imm8},{mod}{r_m}{w}
+00001111,10101010:rsm
+10011110:sahf
+1101000{w},{mod}111{r_m}:sar{w} {mod}{r_m}{w}
+1101001{w},{mod}111{r_m}:sar{w} %cl,{mod}{r_m}{w}
+1100000{w},{mod}111{r_m},{imm8}:sar{w} {imm8},{mod}{r_m}{w}
+0001100{w},{mod}{reg}{r_m}:sbb {reg}{w},{mod}{r_m}{w}
+0001101{w},{mod}{reg}{r_m}:sbb {mod}{r_m}{w},{reg}{w}
+0001110{w},{imm}:sbb {imm}{w},{ax}{w}
+1000000{w},{mod}011{r_m},{imm}:sbb{w} {imm}{w},{mod}{r_m}{w}
+1000001{w},{mod}011{r_m},{imms8}:sbb{w} {imms8},{mod}{r_m}
+1010111{w}:{RE}scas {es_di},{ax}{w}
+00001111,1001{tttn},{mod}000{r_m}:set{tttn} {mod}{r_m}
+1101000{w},{mod}100{r_m}:shl{w} {mod}{r_m}{w}
+1101001{w},{mod}100{r_m}:shl{w} %cl,{mod}{r_m}{w}
+1100000{w},{mod}100{r_m},{imm8}:shl{w} {imm8},{mod}{r_m}{w}
+1101000{w},{mod}101{r_m}:shr{w} {mod}{r_m}{w}
+00001111,10100100,{mod}{reg}{r_m},{imm8}:shld {imm8},{reg},{mod}{r_m}
+00001111,10100101,{mod}{reg}{r_m}:shld %cl,{reg},{mod}{r_m}
+1101001{w},{mod}101{r_m}:shr{w} %cl,{mod}{r_m}{w}
+1100000{w},{mod}101{r_m},{imm8}:shr{w} {imm8},{mod}{r_m}{w}
+00001111,10101100,{mod}{reg}{r_m},{imm8}:shrd {imm8},{reg},{mod}{r_m}
+00001111,10101101,{mod}{reg}{r_m}:shrd %cl,{reg},{mod}{r_m}
+# ORDER
+00001111,00000001,11000001:vmcall
+00001111,00000001,11000010:vmlaunch
+00001111,00000001,11000011:vmresume
+00001111,00000001,11000100:vmxoff
+00001111,01111000,{mod}{reg64}{64r_m}:vmread {reg64},{mod}{64r_m}
+00001111,01111001,{mod}{reg64}{64r_m}:vmwrite {mod}{64r_m},{reg64}
+ifdef(`i386',
+`00001111,00000001,{mod}000{r_m}:sgdtl {mod}{r_m}
+',
+`00001111,00000001,{mod}000{r_m}:sgdt {mod}{r_m}
+')dnl
+# ORDER END
+# ORDER
+ifdef(`i386',
+`00001111,00000001,11001000:monitor %eax,%ecx,%edx
+00001111,00000001,11001001:mwait %eax,%ecx
+',
+`00001111,00000001,11001000:monitor %rax,%rcx,%rdx
+00001111,00000001,11001001:mwait %rax,%rcx
+')dnl
+ifdef(`i386',
+`00001111,00000001,{mod}001{r_m}:sidtl {mod}{r_m}
+',
+`00001111,00000001,{mod}001{r_m}:sidt {mod}{r_m}
+')dnl
+# ORDER END
+00001111,00000000,{mod}000{r_m}:sldt {mod}{r_m}
+00001111,00000001,{mod}100{r_m}:smsw {mod}{r_m}
+11111001:stc
+11111101:std
+11111011:sti
+1010101{w}:{R}stos {ax}{w},{es_di}
+00001111,00000000,{mod}001{r_m}:str {mod}{r_m}
+0010100{w},{mod}{reg}{r_m}:sub {reg}{w},{mod}{r_m}{w}
+0010101{w},{mod}{reg}{r_m}:sub {mod}{r_m}{w},{reg}{w}
+0010110{w},{imm}:sub {imm}{w},{ax}{w}
+1000000{w},{mod}101{r_m},{imm}:sub{w} {imm}{w},{mod}{r_m}{w}
+1000001{w},{mod}101{r_m},{imms8}:sub{w} {imms8},{mod}{r_m}
+1000010{w},{mod}{reg}{r_m}:test {reg}{w},{mod}{r_m}{w}
+1010100{w},{imm}:test {imm}{w},{ax}{w}
+1111011{w},{mod}000{r_m},{imm}:test{w} {imm}{w},{mod}{r_m}{w}
+00001111,00001011:ud2a
+00001111,00000000,{mod}100{16r_m}:verr {mod}{16r_m}
+00001111,00000000,{mod}101{16r_m}:verw {mod}{16r_m}
+00001111,00001001:wbinvd
+00001111,00001101,{mod}000{8r_m}:prefetch {mod}{8r_m}
+00001111,00001101,{mod}001{8r_m}:prefetchw {mod}{8r_m}
+00001111,00011000,{mod}000{r_m}:prefetchnta {mod}{r_m}
+00001111,00011000,{mod}001{r_m}:prefetcht0 {mod}{r_m}
+00001111,00011000,{mod}010{r_m}:prefetcht1 {mod}{r_m}
+00001111,00011000,{mod}011{r_m}:prefetcht2 {mod}{r_m}
+00001111,00011111,{mod}{reg}{r_m}:nop{w} {mod}{r_m}
+00001111,00110000:wrmsr
+00001111,1100000{w},{mod}{reg}{r_m}:xadd {reg}{w},{mod}{r_m}{w}
+1000011{w},{mod}{reg}{r_m}:xchg {reg}{w},{mod}{r_m}{w}
+10010{oreg}:xchg {ax},{oreg}
+11010111:xlat {ds_bx}
+0011000{w},{mod}{reg}{r_m}:xor {reg}{w},{mod}{r_m}{w}
+0011001{w},{mod}{reg}{r_m}:xor {mod}{r_m}{w},{reg}{w}
+0011010{w},{imm}:xor {imm}{w},{ax}{w}
+1000000{w},{mod}110{r_m},{imm}:xor{w} {imm}{w},{mod}{r_m}{w}
+1000001{w},{mod}110{r_m},{imms8}:xor{w} {imms8},{mod}{r_m}
+00001111,01110111:emms
+01100110,00001111,11011011,{Mod}{xmmreg}{R_m}:pand {Mod}{R_m},{xmmreg}
+00001111,11011011,{MOD}{mmxreg}{R_M}:pand {MOD}{R_M},{mmxreg}
+01100110,00001111,11011111,{Mod}{xmmreg}{R_m}:pandn {Mod}{R_m},{xmmreg}
+00001111,11011111,{MOD}{mmxreg}{R_M}:pandn {MOD}{R_M},{mmxreg}
+01100110,00001111,11110101,{Mod}{xmmreg}{R_m}:pmaddwd {Mod}{R_m},{xmmreg}
+00001111,11110101,{MOD}{mmxreg}{R_M}:pmaddwd {MOD}{R_M},{mmxreg}
+01100110,00001111,11101011,{Mod}{xmmreg}{R_m}:por {Mod}{R_m},{xmmreg}
+00001111,11101011,{MOD}{mmxreg}{R_M}:por {MOD}{R_M},{mmxreg}
+01100110,00001111,11101111,{Mod}{xmmreg}{R_m}:pxor {Mod}{R_m},{xmmreg}
+00001111,11101111,{MOD}{mmxreg}{R_M}:pxor {MOD}{R_M},{mmxreg}
+00001111,01010101,{Mod}{xmmreg}{R_m}:andnps {Mod}{R_m},{xmmreg}
+00001111,01010100,{Mod}{xmmreg}{R_m}:andps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000000:cmpeqps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000001:cmpltps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000010:cmpleps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000011:cmpunordps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000100:cmpneqps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000101:cmpnltps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000110:cmpnleps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000111:cmpordps {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000000:cmpeqss {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000001:cmpltss {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000010:cmpless {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000011:cmpunordss {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000100:cmpneqss {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000101:cmpnltss {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000110:cmpnless {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000111:cmpordss {Mod}{R_m},{xmmreg}
+00001111,10101110,{mod}001{r_m}:fxrstor {mod}{r_m}
+00001111,10101110,{mod}000{r_m}:fxsave {mod}{r_m}
+00001111,10101110,{mod}010{r_m}:ldmxcsr {mod}{r_m}
+00001111,10101110,{mod}011{r_m}:stmxcsr {mod}{r_m}
+11110010,00001111,00010000,{Mod}{xmmreg}{R_m}:movsd {Mod}{R_m},{xmmreg}
+11110011,00001111,00010000,{Mod}{xmmreg}{R_m}:movss {Mod}{R_m},{xmmreg}
+01100110,00001111,00010000,{Mod}{xmmreg}{R_m}:movupd {Mod}{R_m},{xmmreg}
+00001111,00010000,{Mod}{xmmreg}{R_m}:movups {Mod}{R_m},{xmmreg}
+11110010,00001111,00010001,{Mod}{xmmreg}{R_m}:movsd {xmmreg},{Mod}{R_m}
+11110011,00001111,00010001,{Mod}{xmmreg}{R_m}:movss {xmmreg},{Mod}{R_m}
+01100110,00001111,00010001,{Mod}{xmmreg}{R_m}:movupd {xmmreg},{Mod}{R_m}
+00001111,00010001,{Mod}{xmmreg}{R_m}:movups {xmmreg},{Mod}{R_m}
+11110010,00001111,00010010,{Mod}{xmmreg}{R_m}:movddup {Mod}{R_m},{xmmreg}
+11110011,00001111,00010010,{Mod}{xmmreg}{R_m}:movsldup {Mod}{R_m},{xmmreg}
+01100110,00001111,00010010,{Mod}{xmmreg}{R_m}:movlpd {Mod}{R_m},{xmmreg}
+00001111,00010010,11{xmmreg1}{xmmreg2}:movhlps {xmmreg2},{xmmreg1}
+00001111,00010010,{Mod}{xmmreg}{R_m}:movlps {Mod}{R_m},{xmmreg}
+01100110,00001111,00010011,11{xmmreg1}{xmmreg2}:movhlpd {xmmreg1},{xmmreg2}
+00001111,00010011,11{xmmreg1}{xmmreg2}:movhlps {xmmreg1},{xmmreg2}
+01100110,00001111,00010011,{Mod}{xmmreg}{R_m}:movlpd {xmmreg},{Mod}{R_m}
+00001111,00010011,{Mod}{xmmreg}{R_m}:movlps {xmmreg},{Mod}{R_m}
+01100110,00001111,00010100,{Mod}{xmmreg}{R_m}:unpcklpd {Mod}{R_m},{xmmreg}
+00001111,00010100,{Mod}{xmmreg}{R_m}:unpcklps {Mod}{R_m},{xmmreg}
+01100110,00001111,00010101,{Mod}{xmmreg}{R_m}:unpckhpd {Mod}{R_m},{xmmreg}
+00001111,00010101,{Mod}{xmmreg}{R_m}:unpckhps {Mod}{R_m},{xmmreg}
+11110011,00001111,00010110,{Mod}{xmmreg}{R_m}:movshdup {Mod}{R_m},{xmmreg}
+01100110,00001111,00010110,{Mod}{xmmreg}{R_m}:movhpd {Mod}{R_m},{xmmreg}
+00001111,00010110,11{xmmreg1}{xmmreg2}:movlhps {xmmreg2},{xmmreg1}
+00001111,00010110,{Mod}{xmmreg}{R_m}:movhps {Mod}{R_m},{xmmreg}
+01100110,00001111,00010111,11{xmmreg1}{xmmreg2}:movlhpd {xmmreg1},{xmmreg2}
+00001111,00010111,11{xmmreg1}{xmmreg2}:movlhps {xmmreg1},{xmmreg2}
+01100110,00001111,00010111,{Mod}{xmmreg}{R_m}:movhpd {xmmreg},{Mod}{R_m}
+00001111,00010111,{Mod}{xmmreg}{R_m}:movhps {xmmreg},{Mod}{R_m}
+01100110,00001111,00101000,{Mod}{xmmreg}{R_m}:movapd {Mod}{R_m},{xmmreg}
+00001111,00101000,{Mod}{xmmreg}{R_m}:movaps {Mod}{R_m},{xmmreg}
+01100110,00001111,00101001,{Mod}{xmmreg}{R_m}:movapd {xmmreg},{Mod}{R_m}
+00001111,00101001,{Mod}{xmmreg}{R_m}:movaps {xmmreg},{Mod}{R_m}
+11110010,00001111,00101010,{mod}{xmmreg}{r_m}:cvtsi2sd {mod}{r_m},{xmmreg}
+11110011,00001111,00101010,{mod}{xmmreg}{r_m}:cvtsi2ss {mod}{r_m},{xmmreg}
+01100110,00001111,00101010,{MOD}{xmmreg}{R_M}:cvtpi2pd {MOD}{R_M},{xmmreg}
+00001111,00101010,{MOD}{xmmreg}{R_M}:cvtpi2ps {MOD}{R_M},{xmmreg}
+01100110,00001111,00101011,{mod}{xmmreg}{r_m}:movntpd {xmmreg},{mod}{r_m}
+00001111,00101011,{mod}{xmmreg}{r_m}:movntps {xmmreg},{mod}{r_m}
+11110010,00001111,00101100,{Mod}{reg}{R_m}:cvttsd2si {Mod}{R_m},{reg}
+11110011,00001111,00101100,{Mod}{reg}{R_m}:cvttss2si {Mod}{R_m},{reg}
+01100110,00001111,00101100,{Mod}{mmxreg}{R_m}:cvttpd2pi {Mod}{R_m},{mmxreg}
+00001111,00101100,{Mod}{mmxreg}{R_m}:cvttps2pi {Mod}{R_m},{mmxreg}
+01100110,00001111,00101101,{Mod}{mmxreg}{R_m}:cvtpd2pi {Mod}{R_m},{mmxreg}
+11110010,00001111,00101101,{Mod}{reg}{R_m}:cvtsd2si {Mod}{R_m},{reg}
+11110011,00001111,00101101,{Mod}{reg}{R_m}:cvtss2si {Mod}{R_m},{reg}
+00001111,00101101,{Mod}{mmxreg}{R_m}:cvtps2pi {Mod}{R_m},{mmxreg}
+01100110,00001111,00101110,{Mod}{xmmreg}{R_m}:ucomisd {Mod}{R_m},{xmmreg}
+00001111,00101110,{Mod}{xmmreg}{R_m}:ucomiss {Mod}{R_m},{xmmreg}
+01100110,00001111,00101111,{Mod}{xmmreg}{R_m}:comisd {Mod}{R_m},{xmmreg}
+00001111,00101111,{Mod}{xmmreg}{R_m}:comiss {Mod}{R_m},{xmmreg}
+00001111,00110111:getsec
+01100110,00001111,01010000,11{reg}{xmmreg}:movmskpd {xmmreg},{reg}
+00001111,01010000,11{reg}{xmmreg}:movmskps {xmmreg},{reg}
+01100110,00001111,01010001,{Mod}{xmmreg}{R_m}:sqrtpd {Mod}{R_m},{xmmreg}
+11110010,00001111,01010001,{Mod}{xmmreg}{R_m}:sqrtsd {Mod}{R_m},{xmmreg}
+11110011,00001111,01010001,{Mod}{xmmreg}{R_m}:sqrtss {Mod}{R_m},{xmmreg}
+00001111,01010001,{Mod}{xmmreg}{R_m}:sqrtps {Mod}{R_m},{xmmreg}
+11110011,00001111,01010010,{Mod}{xmmreg}{R_m}:rsqrtss {Mod}{R_m},{xmmreg}
+00001111,01010010,{Mod}{xmmreg}{R_m}:rsqrtps {Mod}{R_m},{xmmreg}
+11110011,00001111,01010011,{Mod}{xmmreg}{R_m}:rcpss {Mod}{R_m},{xmmreg}
+00001111,01010011,{Mod}{xmmreg}{R_m}:rcpps {Mod}{R_m},{xmmreg}
+01100110,00001111,01010100,{Mod}{xmmreg}{R_m}:andpd {Mod}{R_m},{xmmreg}
+00001111,01010100,{Mod}{xmmreg}{R_m}:andps {Mod}{R_m},{xmmreg}
+01100110,00001111,01010101,{Mod}{xmmreg}{R_m}:andnpd {Mod}{R_m},{xmmreg}
+00001111,01010101,{Mod}{xmmreg}{R_m}:andnps {Mod}{R_m},{xmmreg}
+01100110,00001111,01010110,{Mod}{xmmreg}{R_m}:orpd {Mod}{R_m},{xmmreg}
+00001111,01010110,{Mod}{xmmreg}{R_m}:orps {Mod}{R_m},{xmmreg}
+01100110,00001111,01010111,{Mod}{xmmreg}{R_m}:xorpd {Mod}{R_m},{xmmreg}
+00001111,01010111,{Mod}{xmmreg}{R_m}:xorps {Mod}{R_m},{xmmreg}
+11110010,00001111,01011000,{Mod}{xmmreg}{R_m}:addsd {Mod}{R_m},{xmmreg}
+11110011,00001111,01011000,{Mod}{xmmreg}{R_m}:addss {Mod}{R_m},{xmmreg}
+01100110,00001111,01011000,{Mod}{xmmreg}{R_m}:addpd {Mod}{R_m},{xmmreg}
+00001111,01011000,{Mod}{xmmreg}{R_m}:addps {Mod}{R_m},{xmmreg}
+11110010,00001111,01011001,{Mod}{xmmreg}{R_m}:mulsd {Mod}{R_m},{xmmreg}
+11110011,00001111,01011001,{Mod}{xmmreg}{R_m}:mulss {Mod}{R_m},{xmmreg}
+01100110,00001111,01011001,{Mod}{xmmreg}{R_m}:mulpd {Mod}{R_m},{xmmreg}
+00001111,01011001,{Mod}{xmmreg}{R_m}:mulps {Mod}{R_m},{xmmreg}
+11110010,00001111,01011010,{Mod}{xmmreg}{R_m}:cvtsd2ss {Mod}{R_m},{xmmreg}
+11110011,00001111,01011010,{Mod}{xmmreg}{R_m}:cvtss2sd {Mod}{R_m},{xmmreg}
+01100110,00001111,01011010,{Mod}{xmmreg}{R_m}:cvtpd2ps {Mod}{R_m},{xmmreg}
+00001111,01011010,{Mod}{xmmreg}{R_m}:cvtps2pd {Mod}{R_m},{xmmreg}
+01100110,00001111,01011011,{Mod}{xmmreg}{R_m}:cvtps2dq {Mod}{R_m},{xmmreg}
+11110011,00001111,01011011,{Mod}{xmmreg}{R_m}:cvttps2dq {Mod}{R_m},{xmmreg}
+00001111,01011011,{Mod}{xmmreg}{R_m}:cvtdq2ps {Mod}{R_m},{xmmreg}
+11110010,00001111,01011100,{Mod}{xmmreg}{R_m}:subsd {Mod}{R_m},{xmmreg}
+11110011,00001111,01011100,{Mod}{xmmreg}{R_m}:subss {Mod}{R_m},{xmmreg}
+01100110,00001111,01011100,{Mod}{xmmreg}{R_m}:subpd {Mod}{R_m},{xmmreg}
+00001111,01011100,{Mod}{xmmreg}{R_m}:subps {Mod}{R_m},{xmmreg}
+11110010,00001111,01011101,{Mod}{xmmreg}{R_m}:minsd {Mod}{R_m},{xmmreg}
+11110011,00001111,01011101,{Mod}{xmmreg}{R_m}:minss {Mod}{R_m},{xmmreg}
+01100110,00001111,01011101,{Mod}{xmmreg}{R_m}:minpd {Mod}{R_m},{xmmreg}
+00001111,01011101,{Mod}{xmmreg}{R_m}:minps {Mod}{R_m},{xmmreg}
+11110010,00001111,01011110,{Mod}{xmmreg}{R_m}:divsd {Mod}{R_m},{xmmreg}
+11110011,00001111,01011110,{Mod}{xmmreg}{R_m}:divss {Mod}{R_m},{xmmreg}
+01100110,00001111,01011110,{Mod}{xmmreg}{R_m}:divpd {Mod}{R_m},{xmmreg}
+00001111,01011110,{Mod}{xmmreg}{R_m}:divps {Mod}{R_m},{xmmreg}
+11110010,00001111,01011111,{Mod}{xmmreg}{R_m}:maxsd {Mod}{R_m},{xmmreg}
+11110011,00001111,01011111,{Mod}{xmmreg}{R_m}:maxss {Mod}{R_m},{xmmreg}
+01100110,00001111,01011111,{Mod}{xmmreg}{R_m}:maxpd {Mod}{R_m},{xmmreg}
+00001111,01011111,{Mod}{xmmreg}{R_m}:maxps {Mod}{R_m},{xmmreg}
+01100110,00001111,01100000,{Mod}{xmmreg}{R_m}:punpcklbw {Mod}{R_m},{xmmreg}
+00001111,01100000,{MOD}{mmxreg}{R_M}:punpcklbw {MOD}{R_M},{mmxreg}
+01100110,00001111,01100001,{Mod}{xmmreg}{R_m}:punpcklwd {Mod}{R_m},{xmmreg}
+00001111,01100001,{MOD}{mmxreg}{R_M}:punpcklwd {MOD}{R_M},{mmxreg}
+01100110,00001111,01100010,{Mod}{xmmreg}{R_m}:punpckldq {Mod}{R_m},{xmmreg}
+00001111,01100010,{MOD}{mmxreg}{R_M}:punpckldq {MOD}{R_M},{mmxreg}
+01100110,00001111,01100011,{Mod}{xmmreg}{R_m}:packsswb {Mod}{R_m},{xmmreg}
+00001111,01100011,{MOD}{mmxreg}{R_M}:packsswb {MOD}{R_M},{mmxreg}
+01100110,00001111,01100100,{Mod}{xmmreg}{R_m}:pcmpgtb {Mod}{R_m},{xmmreg}
+00001111,01100100,{MOD}{mmxreg}{R_M}:pcmpgtb {MOD}{R_M},{mmxreg}
+01100110,00001111,01100101,{Mod}{xmmreg}{R_m}:pcmpgtw {Mod}{R_m},{xmmreg}
+00001111,01100101,{MOD}{mmxreg}{R_M}:pcmpgtw {MOD}{R_M},{mmxreg}
+01100110,00001111,01100110,{Mod}{xmmreg}{R_m}:pcmpgtd {Mod}{R_m},{xmmreg}
+00001111,01100110,{MOD}{mmxreg}{R_M}:pcmpgtd {MOD}{R_M},{mmxreg}
+01100110,00001111,01100111,{Mod}{xmmreg}{R_m}:packuswb {Mod}{R_m},{xmmreg}
+00001111,01100111,{MOD}{mmxreg}{R_M}:packuswb {MOD}{R_M},{mmxreg}
+01100110,00001111,01101000,{Mod}{xmmreg}{R_m}:punpckhbw {Mod}{R_m},{xmmreg}
+00001111,01101000,{MOD}{mmxreg}{R_M}:punpckhbw {MOD}{R_M},{mmxreg}
+01100110,00001111,01101001,{Mod}{xmmreg}{R_m}:punpckhwd {Mod}{R_m},{xmmreg}
+00001111,01101001,{MOD}{mmxreg}{R_M}:punpckhwd {MOD}{R_M},{mmxreg}
+01100110,00001111,01101010,{Mod}{xmmreg}{R_m}:punpckhdq {Mod}{R_m},{xmmreg}
+00001111,01101010,{MOD}{mmxreg}{R_M}:punpckhdq {MOD}{R_M},{mmxreg}
+01100110,00001111,01101011,{Mod}{xmmreg}{R_m}:packssdw {Mod}{R_m},{xmmreg}
+00001111,01101011,{MOD}{mmxreg}{R_M}:packssdw {MOD}{R_M},{mmxreg}
+01100110,00001111,01101100,{Mod}{xmmreg}{R_m}:punpcklqdq {Mod}{R_m},{xmmreg}
+01100110,00001111,01101101,{Mod}{xmmreg}{R_m}:punpckhqdq {Mod}{R_m},{xmmreg}
+01100110,00001111,01101110,{mod}{xmmreg}{r_m}:movd {mod}{r_m},{xmmreg}
+00001111,01101110,{mod}{mmxreg}{r_m}:movd {mod}{r_m},{mmxreg}
+01100110,00001111,01101111,{Mod}{xmmreg}{R_m}:movdqa {Mod}{R_m},{xmmreg}
+11110011,00001111,01101111,{Mod}{xmmreg}{R_m}:movdqu {Mod}{R_m},{xmmreg}
+00001111,01101111,{MOD}{mmxreg}{R_M}:movq {MOD}{R_M},{mmxreg}
+01100110,00001111,01110000,{Mod}{xmmreg}{R_m},{imm8}:pshufd {imm8},{Mod}{R_m},{xmmreg}
+11110010,00001111,01110000,{Mod}{xmmreg}{R_m},{imm8}:pshuflw {imm8},{Mod}{R_m},{xmmreg}
+11110011,00001111,01110000,{Mod}{xmmreg}{R_m},{imm8}:pshufhw {imm8},{Mod}{R_m},{xmmreg}
+00001111,01110000,{MOD}{mmxreg}{R_M},{imm8}:pshufw {imm8},{MOD}{R_M},{mmxreg}
+01100110,00001111,01110100,{Mod}{xmmreg}{R_m}:pcmpeqb {Mod}{R_m},{xmmreg}
+00001111,01110100,{MOD}{mmxreg}{R_M}:pcmpeqb {MOD}{R_M},{mmxreg}
+01100110,00001111,01110101,{Mod}{xmmreg}{R_m}:pcmpeqw {Mod}{R_m},{xmmreg}
+00001111,01110101,{MOD}{mmxreg}{R_M}:pcmpeqw {MOD}{R_M},{mmxreg}
+01100110,00001111,01110110,{Mod}{xmmreg}{R_m}:pcmpeqd {Mod}{R_m},{xmmreg}
+00001111,01110110,{MOD}{mmxreg}{R_M}:pcmpeqd {MOD}{R_M},{mmxreg}
+01100110,00001111,01111100,{Mod}{xmmreg}{R_m}:haddpd {Mod}{R_m},{xmmreg}
+11110010,00001111,01111100,{Mod}{xmmreg}{R_m}:haddps {Mod}{R_m},{xmmreg}
+01100110,00001111,01111101,{Mod}{xmmreg}{R_m}:hsubpd {Mod}{R_m},{xmmreg}
+11110010,00001111,01111101,{Mod}{xmmreg}{R_m}:hsubps {Mod}{R_m},{xmmreg}
+01100110,00001111,01111110,{mod}{xmmreg}{r_m}:movd {xmmreg},{mod}{r_m}
+11110011,00001111,01111110,{Mod}{xmmreg}{R_m}:movq {Mod}{R_m},{xmmreg}
+00001111,01111110,{mod}{mmxreg}{r_m}:movd {mmxreg},{mod}{r_m}
+01100110,00001111,01111111,{Mod}{xmmreg}{R_m}:movdqa {xmmreg},{Mod}{R_m}
+11110011,00001111,01111111,{Mod}{xmmreg}{R_m}:movdqu {xmmreg},{Mod}{R_m}
+00001111,01111111,{MOD}{mmxreg}{R_M}:movq {mmxreg},{MOD}{R_M}
+00001111,11000011,{mod}{reg}{r_m}:movnti {reg},{mod}{r_m}
+01100110,00001111,11000100,{mod}{xmmreg}{r_m},{imm8}:pinsrw {imm8},{mod}{r_m},{xmmreg}
+00001111,11000100,{mod}{mmxreg}{r_m},{imm8}:pinsrw {imm8},{mod}{r_m},{mmxreg}
+01100110,00001111,11000101,11{reg}{xmmreg},{imm8}:pextrw {imm8},{xmmreg},{reg}
+00001111,11000101,11{reg}{mmxreg},{imm8}:pextrw {imm8},{mmxreg},{reg}
+01100110,00001111,11000110,{Mod}{xmmreg}{R_m},{imm8}:shufpd {imm8},{Mod}{R_m},{xmmreg}
+00001111,11000110,{Mod}{xmmreg}{R_m},{imm8}:shufps {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,11010001,{Mod}{xmmreg}{R_m}:psrlw {Mod}{R_m},{xmmreg}
+00001111,11010001,{MOD}{mmxreg}{R_M}:psrlw {MOD}{R_M},{mmxreg}
+01100110,00001111,11010010,{Mod}{xmmreg}{R_m}:psrld {Mod}{R_m},{xmmreg}
+00001111,11010010,{MOD}{mmxreg}{R_M}:psrld {MOD}{R_M},{mmxreg}
+01100110,00001111,11010011,{Mod}{xmmreg}{R_m}:psrlq {Mod}{R_m},{xmmreg}
+00001111,11010011,{MOD}{mmxreg}{R_M}:psrlq {MOD}{R_M},{mmxreg}
+01100110,00001111,11010100,{Mod}{xmmreg}{R_m}:paddq {Mod}{R_m},{xmmreg}
+00001111,11010100,{MOD}{mmxreg}{R_M}:paddq {MOD}{R_M},{mmxreg}
+01100110,00001111,11010101,{Mod}{xmmreg}{R_m}:pmullw {Mod}{R_m},{xmmreg}
+00001111,11010101,{MOD}{mmxreg}{R_M}:pmullw {MOD}{R_M},{mmxreg}
+01100110,00001111,11010110,{Mod}{xmmreg}{R_m}:movq {xmmreg},{Mod}{R_m}
+11110010,00001111,11010110,11{mmxreg}{xmmreg}:movdq2q {xmmreg},{mmxreg}
+11110011,00001111,11010110,11{xmmreg}{mmxreg}:movq2dq {mmxreg},{xmmreg}
+01100110,00001111,11010111,11{reg}{xmmreg}:pmovmskb {xmmreg},{reg}
+00001111,11010111,11{reg}{mmxreg}:pmovmskb {mmxreg},{reg}
+01100110,00001111,11011000,{Mod}{xmmreg}{R_m}:psubusb {Mod}{R_m},{xmmreg}
+00001111,11011000,{MOD}{mmxreg}{R_M}:psubusb {MOD}{R_M},{mmxreg}
+01100110,00001111,11011001,{Mod}{xmmreg}{R_m}:psubusw {Mod}{R_m},{xmmreg}
+00001111,11011001,{MOD}{mmxreg}{R_M}:psubusw {MOD}{R_M},{mmxreg}
+01100110,00001111,11011010,{Mod}{xmmreg}{R_m}:pminub {Mod}{R_m},{xmmreg}
+00001111,11011010,{MOD}{mmxreg}{R_M}:pminub {MOD}{R_M},{mmxreg}
+01100110,00001111,11011100,{Mod}{xmmreg}{R_m}:paddusb {Mod}{R_m},{xmmreg}
+00001111,11011100,{MOD}{mmxreg}{R_M}:paddusb {MOD}{R_M},{mmxreg}
+01100110,00001111,11011101,{Mod}{xmmreg}{R_m}:paddusw {Mod}{R_m},{xmmreg}
+00001111,11011101,{MOD}{mmxreg}{R_M}:paddusw {MOD}{R_M},{mmxreg}
+01100110,00001111,11011110,{Mod}{xmmreg}{R_m}:pmaxub {Mod}{R_m},{xmmreg}
+00001111,11011110,{MOD}{mmxreg}{R_M}:pmaxub {MOD}{R_M},{mmxreg}
+01100110,00001111,11100000,{Mod}{xmmreg}{R_m}:pavgb {Mod}{R_m},{xmmreg}
+00001111,11100000,{MOD}{mmxreg}{R_M}:pavgb {MOD}{R_M},{mmxreg}
+01100110,00001111,11100001,{Mod}{xmmreg}{R_m}:psraw {Mod}{R_m},{xmmreg}
+00001111,11100001,{MOD}{mmxreg}{R_M}:psraw {MOD}{R_M},{mmxreg}
+01100110,00001111,11100010,{Mod}{xmmreg}{R_m}:psrad {Mod}{R_m},{xmmreg}
+00001111,11100010,{MOD}{mmxreg}{R_M}:psrad {MOD}{R_M},{mmxreg}
+01100110,00001111,11100011,{Mod}{xmmreg}{R_m}:pavgw {Mod}{R_m},{xmmreg}
+00001111,11100011,{MOD}{mmxreg}{R_M}:pavgw {MOD}{R_M},{mmxreg}
+01100110,00001111,11100100,{Mod}{xmmreg}{R_m}:pmulhuw {Mod}{R_m},{xmmreg}
+00001111,11100100,{MOD}{mmxreg}{R_M}:pmulhuw {MOD}{R_M},{mmxreg}
+01100110,00001111,11100101,{Mod}{xmmreg}{R_m}:pmulhw {Mod}{R_m},{xmmreg}
+00001111,11100101,{MOD}{mmxreg}{R_M}:pmulhw {MOD}{R_M},{mmxreg}
+01100110,00001111,11100111,{Mod}{xmmreg}{R_m}:movntdq {xmmreg},{Mod}{R_m}
+00001111,11100111,{MOD}{mmxreg}{R_M}:movntq {mmxreg},{MOD}{R_M}
+01100110,00001111,11101000,{Mod}{xmmreg}{R_m}:psubsb {Mod}{R_m},{xmmreg}
+00001111,11101000,{MOD}{mmxreg}{R_M}:psubsb {MOD}{R_M},{mmxreg}
+01100110,00001111,11101001,{Mod}{xmmreg}{R_m}:psubsw {Mod}{R_m},{xmmreg}
+00001111,11101001,{MOD}{mmxreg}{R_M}:psubsw {MOD}{R_M},{mmxreg}
+01100110,00001111,11101010,{Mod}{xmmreg}{R_m}:pminsw {Mod}{R_m},{xmmreg}
+00001111,11101010,{MOD}{mmxreg}{R_M}:pminsw {MOD}{R_M},{mmxreg}
+01100110,00001111,11101100,{Mod}{xmmreg}{R_m}:paddsb {Mod}{R_m},{xmmreg}
+00001111,11101100,{MOD}{mmxreg}{R_M}:paddsb {MOD}{R_M},{mmxreg}
+01100110,00001111,11101101,{Mod}{xmmreg}{R_m}:paddsw {Mod}{R_m},{xmmreg}
+00001111,11101101,{MOD}{mmxreg}{R_M}:paddsw {MOD}{R_M},{mmxreg}
+01100110,00001111,11101110,{Mod}{xmmreg}{R_m}:pmaxsw {Mod}{R_m},{xmmreg}
+00001111,11101110,{MOD}{mmxreg}{R_M}:pmaxsw {MOD}{R_M},{mmxreg}
+11110010,00001111,11110000,{mod}{xmmreg}{r_m}:lddqu {mod}{r_m},{xmmreg}
+01100110,00001111,11110001,{Mod}{xmmreg}{R_m}:psllw {Mod}{R_m},{xmmreg}
+00001111,11110001,{MOD}{mmxreg}{R_M}:psllw {MOD}{R_M},{mmxreg}
+01100110,00001111,11110010,{Mod}{xmmreg}{R_m}:pslld {Mod}{R_m},{xmmreg}
+00001111,11110010,{MOD}{mmxreg}{R_M}:pslld {MOD}{R_M},{mmxreg}
+01100110,00001111,11110011,{Mod}{xmmreg}{R_m}:psllq {Mod}{R_m},{xmmreg}
+00001111,11110011,{MOD}{mmxreg}{R_M}:psllq {MOD}{R_M},{mmxreg}
+01100110,00001111,11110100,{Mod}{xmmreg}{R_m}:pmuludq {Mod}{R_m},{xmmreg}
+00001111,11110100,{MOD}{mmxreg}{R_M}:pmuludq {MOD}{R_M},{mmxreg}
+01100110,00001111,11110110,{Mod}{xmmreg}{R_m}:psadbw {Mod}{R_m},{xmmreg}
+00001111,11110110,{MOD}{mmxreg}{R_M}:psadbw {MOD}{R_M},{mmxreg}
+01100110,00001111,11110111,11{xmmreg1}{xmmreg2}:maskmovdqu {xmmreg2},{xmmreg1}
+00001111,11110111,11{mmxreg1}{mmxreg2}:maskmovq {mmxreg2},{mmxreg1}
+01100110,00001111,11111000,{Mod}{xmmreg}{R_m}:psubb {Mod}{R_m},{xmmreg}
+00001111,11111000,{MOD}{mmxreg}{R_M}:psubb {MOD}{R_M},{mmxreg}
+01100110,00001111,11111001,{Mod}{xmmreg}{R_m}:psubw {Mod}{R_m},{xmmreg}
+00001111,11111001,{MOD}{mmxreg}{R_M}:psubw {MOD}{R_M},{mmxreg}
+01100110,00001111,11111010,{Mod}{xmmreg}{R_m}:psubd {Mod}{R_m},{xmmreg}
+00001111,11111010,{MOD}{mmxreg}{R_M}:psubd {MOD}{R_M},{mmxreg}
+01100110,00001111,11111011,{Mod}{xmmreg}{R_m}:psubq {Mod}{R_m},{xmmreg}
+00001111,11111011,{MOD}{mmxreg}{R_M}:psubq {MOD}{R_M},{mmxreg}
+01100110,00001111,11111100,{Mod}{xmmreg}{R_m}:paddb {Mod}{R_m},{xmmreg}
+00001111,11111100,{MOD}{mmxreg}{R_M}:paddb {MOD}{R_M},{mmxreg}
+01100110,00001111,11111101,{Mod}{xmmreg}{R_m}:paddw {Mod}{R_m},{xmmreg}
+00001111,11111101,{MOD}{mmxreg}{R_M}:paddw {MOD}{R_M},{mmxreg}
+01100110,00001111,11111110,{Mod}{xmmreg}{R_m}:paddd {Mod}{R_m},{xmmreg}
+00001111,11111110,{MOD}{mmxreg}{R_M}:paddd {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000000,{Mod}{xmmreg}{R_m}:pshufb {Mod}{R_m},{xmmreg}
+00001111,00111000,00000000,{MOD}{mmxreg}{R_M}:pshufb {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000001,{Mod}{xmmreg}{R_m}:phaddw {Mod}{R_m},{xmmreg}
+00001111,00111000,00000001,{MOD}{mmxreg}{R_M}:phaddw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000010,{Mod}{xmmreg}{R_m}:phaddd {Mod}{R_m},{xmmreg}
+00001111,00111000,00000010,{MOD}{mmxreg}{R_M}:phaddd {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000011,{Mod}{xmmreg}{R_m}:phaddsw {Mod}{R_m},{xmmreg}
+00001111,00111000,00000011,{MOD}{mmxreg}{R_M}:phaddsw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000100,{Mod}{xmmreg}{R_m}:pmaddubsw {Mod}{R_m},{xmmreg}
+00001111,00111000,00000100,{MOD}{mmxreg}{R_M}:pmaddubsw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000101,{Mod}{xmmreg}{R_m}:phsubw {Mod}{R_m},{xmmreg}
+00001111,00111000,00000101,{MOD}{mmxreg}{R_M}:phsubw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000110,{Mod}{xmmreg}{R_m}:phsubd {Mod}{R_m},{xmmreg}
+00001111,00111000,00000110,{MOD}{mmxreg}{R_M}:phsubd {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000111,{Mod}{xmmreg}{R_m}:phsubsw {Mod}{R_m},{xmmreg}
+00001111,00111000,00000111,{MOD}{mmxreg}{R_M}:phsubsw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00001000,{Mod}{xmmreg}{R_m}:psignb {Mod}{R_m},{xmmreg}
+00001111,00111000,00001000,{MOD}{mmxreg}{R_M}:psignb {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00001001,{Mod}{xmmreg}{R_m}:psignw {Mod}{R_m},{xmmreg}
+00001111,00111000,00001001,{MOD}{mmxreg}{R_M}:psignw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00001010,{Mod}{xmmreg}{R_m}:psignd {Mod}{R_m},{xmmreg}
+00001111,00111000,00001010,{MOD}{mmxreg}{R_M}:psignd {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00001011,{Mod}{xmmreg}{R_m}:pmulhrsw {Mod}{R_m},{xmmreg}
+00001111,00111000,00001011,{MOD}{mmxreg}{R_M}:pmulhrsw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00011100,{Mod}{xmmreg}{R_m}:pabsb {Mod}{R_m},{xmmreg}
+00001111,00111000,00011100,{MOD}{mmxreg}{R_M}:pabsb {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00011101,{Mod}{xmmreg}{R_m}:pabsw {Mod}{R_m},{xmmreg}
+00001111,00111000,00011101,{MOD}{mmxreg}{R_M}:pabsw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00011110,{Mod}{xmmreg}{R_m}:pabsd {Mod}{R_m},{xmmreg}
+00001111,00111000,00011110,{MOD}{mmxreg}{R_M}:pabsd {MOD}{R_M},{mmxreg}
+01100110,00001111,00111010,00001111,{Mod}{xmmreg}{R_m},{imm8}:palignr {imm8},{Mod}{R_m},{xmmreg}
+00001111,00111010,00001111,{MOD}{mmxreg}{R_M},{imm8}:palignr {imm8},{MOD}{R_M},{mmxreg}
+01100110,00001111,11000111,{mod}110{r_m}:vmclear {mod}{r_m}
+11110011,00001111,11000111,{mod}110{r_m}:vmxon {mod}{r_m}
+00001111,11000111,{mod}110{r_m}:vmptrld {mod}{r_m}
+00001111,11000111,{mod}111{r_m}:vmptrst {mod}{r_m}
+01100110,00001111,01110001,11010{xmmreg},{imm8}:psrlw {imm8},{xmmreg}
+00001111,01110001,11010{mmxreg},{imm8}:psrlw {imm8},{mmxreg}
+01100110,00001111,01110001,11100{xmmreg},{imm8}:psraw {imm8},{xmmreg}
+00001111,01110001,11100{mmxreg},{imm8}:psraw {imm8},{mmxreg}
+01100110,00001111,01110001,11110{xmmreg},{imm8}:psllw {imm8},{xmmreg}
+00001111,01110001,11110{mmxreg},{imm8}:psllw {imm8},{mmxreg}
+01100110,00001111,01110010,11010{xmmreg},{imm8}:psrld {imm8},{xmmreg}
+00001111,01110010,11010{mmxreg},{imm8}:psrld {imm8},{mmxreg}
+01100110,00001111,01110010,11100{xmmreg},{imm8}:psrad {imm8},{xmmreg}
+00001111,01110010,11100{mmxreg},{imm8}:psrad {imm8},{mmxreg}
+01100110,00001111,01110010,11110{xmmreg},{imm8}:pslld {imm8},{xmmreg}
+00001111,01110010,11110{mmxreg},{imm8}:pslld {imm8},{mmxreg}
+01100110,00001111,01110011,11010{xmmreg},{imm8}:psrlq {imm8},{xmmreg}
+00001111,01110011,11010{mmxreg},{imm8}:psrlq {imm8},{mmxreg}
+01100110,00001111,01110011,11011{xmmreg},{imm8}:psrldq {imm8},{xmmreg}
+01100110,00001111,01110011,11110{xmmreg},{imm8}:psllq {imm8},{xmmreg}
+00001111,01110011,11110{mmxreg},{imm8}:psllq {imm8},{mmxreg}
+01100110,00001111,01110011,11111{xmmreg},{imm8}:pslldq {imm8},{xmmreg}
+00001111,10101110,11101000:lfence
+00001111,10101110,11110000:mfence
+00001111,10101110,11111000:sfence
+00001111,10101110,{mod}111{r_m}:clflush {mod}{r_m}
+00001111,00001111,{MOD}{mmxreg}{R_M}:INVALID {MOD}{R_M},{mmxreg}
+01100110,00001111,00111010,00001100,{Mod}{xmmreg}{R_m},{imm8}:blendps {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00001101,{Mod}{xmmreg}{R_m},{imm8}:blendpd {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00010100,{Mod}{xmmreg}{R_m}:blendvps %xmm0,{Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00010101,{Mod}{xmmreg}{R_m}:blendvpd %xmm0,{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,01000000,{Mod}{xmmreg}{R_m},{imm8}:dpps {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,01000001,{Mod}{xmmreg}{R_m},{imm8}:dppd {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00100001,{Mod}{xmmreg}{R_m},{imm8}:insertps {imm8},{Mod}{R_m},{xmmreg}
+# Mod == 11 is not valid
+01100110,00001111,00111000,00101010,{Mod}{xmmreg}{R_m}:movntdqa {Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,01000010,{Mod}{xmmreg}{R_m},{imm8}:mpsadbw {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00101011,{Mod}{xmmreg}{R_m}:packusdw {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00010000,{Mod}{xmmreg}{R_m}:pblendvb %xmm0,{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00001110,{Mod}{xmmreg}{R_m},{imm8}:pblendw {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00101001,{Mod}{xmmreg}{R_m}:pcmpeqq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,01100001,{Mod}{xmmreg}{R_m},{imm8}:pcmpestri {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,01100000,{Mod}{xmmreg}{R_m},{imm8}:pcmpestrm {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,01100011,{Mod}{xmmreg}{R_m},{imm8}:pcmpistri {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,01100010,{Mod}{xmmreg}{R_m},{imm8}:pcmpistrm {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00110111,{Mod}{xmmreg}{R_m}:pcmpgtq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,01000001,{Mod}{xmmreg}{R_m}:phminposuw {Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00100000,{mod}{xmmreg}{r_m},{imm8}:pinsrb {imm8},{mod}{r_m},{xmmreg}
+01100110,00001111,00111010,00100010,{mod}{xmmreg}{r_m},{imm8}:pinsrd {imm8},{mod}{r_m},{xmmreg}
+01100110,00001111,00111000,00111100,{Mod}{xmmreg}{R_m}:pmaxsb {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00111101,{Mod}{xmmreg}{R_m}:pmaxsd {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00111111,{Mod}{xmmreg}{R_m}:pmaxud {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00111110,{Mod}{xmmreg}{R_m}:pmaxuw {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00111000,{Mod}{xmmreg}{R_m}:pminsb {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00111001,{Mod}{xmmreg}{R_m}:pminsd {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00111011,{Mod}{xmmreg}{R_m}:pminud {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00111010,{Mod}{xmmreg}{R_m}:pminuw {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00100000,{Mod}{xmmreg}{R_m}:pmovsxbw {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00100001,{Mod}{xmmreg}{R_m}:pmovsxbd {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00100010,{Mod}{xmmreg}{R_m}:pmovsxbq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00100011,{Mod}{xmmreg}{R_m}:pmovsxwd {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00100100,{Mod}{xmmreg}{R_m}:pmovsxwq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00100101,{Mod}{xmmreg}{R_m}:pmovsxdq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00110000,{Mod}{xmmreg}{R_m}:pmovzxbw {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00110001,{Mod}{xmmreg}{R_m}:pmovzxbd {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00110010,{Mod}{xmmreg}{R_m}:pmovzxbq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00110011,{Mod}{xmmreg}{R_m}:pmovzxwd {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00110100,{Mod}{xmmreg}{R_m}:pmovzxwq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00110101,{Mod}{xmmreg}{R_m}:pmovzxdq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00101000,{Mod}{xmmreg}{R_m}:pmuldq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,01000000,{Mod}{xmmreg}{R_m}:pmulld {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00010111,{Mod}{xmmreg}{R_m}:ptest {Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00001000,{Mod}{xmmreg}{R_m},{imm8}:roundps {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00001001,{Mod}{xmmreg}{R_m},{imm8}:roundpd {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00001010,{Mod}{xmmreg}{R_m},{imm8}:roundss {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00001011,{Mod}{xmmreg}{R_m},{imm8}:roundsd {imm8},{Mod}{R_m},{xmmreg}
+# ORDER:
+dnl Many previous entries depend on this being last.
+000{sreg2}111:pop {sreg2}
+# ORDER END:
diff --git a/libcpu/i386_data.h b/libcpu/i386_data.h
new file mode 100644
index 0000000..42e6650
--- /dev/null
+++ b/libcpu/i386_data.h
@@ -0,0 +1,1415 @@
+/* Helper routines for disassembler for x86/x86-64.
+ Copyright (C) 2007, 2008 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2007.
+
+ Red Hat elfutils 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; version 2 of the License.
+
+ Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <libasm.h>
+
+struct instr_enc
+{
+ /* The mnemonic. Especially encoded for the optimized table. */
+ unsigned int mnemonic : MNEMONIC_BITS;
+
+ /* The rep/repe prefixes. */
+ unsigned int rep : 1;
+ unsigned int repe : 1;
+
+ /* Mnemonic suffix. */
+ unsigned int suffix : SUFFIX_BITS;
+
+ /* Nonzero if the instruction uses modr/m. */
+ unsigned int modrm : 1;
+
+ /* 1st parameter. */
+ unsigned int fct1 : FCT1_BITS;
+#ifdef STR1_BITS
+ unsigned int str1 : STR1_BITS;
+#endif
+ unsigned int off1_1 : OFF1_1_BITS;
+ unsigned int off1_2 : OFF1_2_BITS;
+ unsigned int off1_3 : OFF1_3_BITS;
+
+ /* 2nd parameter. */
+ unsigned int fct2 : FCT2_BITS;
+#ifdef STR2_BITS
+ unsigned int str2 : STR2_BITS;
+#endif
+ unsigned int off2_1 : OFF2_1_BITS;
+ unsigned int off2_2 : OFF2_2_BITS;
+ unsigned int off2_3 : OFF2_3_BITS;
+
+ /* 3rd parameter. */
+ unsigned int fct3 : FCT3_BITS;
+#ifdef STR3_BITS
+ unsigned int str3 : STR3_BITS;
+#endif
+ unsigned int off3_1 : OFF3_1_BITS;
+#ifdef OFF3_2_BITS
+ unsigned int off3_2 : OFF3_2_BITS;
+#endif
+#ifdef OFF3_3_BITS
+ unsigned int off3_3 : OFF3_3_BITS;
+#endif
+};
+
+
+typedef int (*opfct_t) (struct output_data *);
+
+
+static int
+data_prefix (struct output_data *d)
+{
+ char ch = '\0';
+ if (*d->prefixes & has_cs)
+ {
+ ch = 'c';
+ *d->prefixes &= ~has_cs;
+ }
+ else if (*d->prefixes & has_ds)
+ {
+ ch = 'd';
+ *d->prefixes &= ~has_ds;
+ }
+ else if (*d->prefixes & has_es)
+ {
+ ch = 'e';
+ *d->prefixes &= ~has_es;
+ }
+ else if (*d->prefixes & has_fs)
+ {
+ ch = 'f';
+ *d->prefixes &= ~has_fs;
+ }
+ else if (*d->prefixes & has_gs)
+ {
+ ch = 'g';
+ *d->prefixes &= ~has_gs;
+ }
+ else if (*d->prefixes & has_ss)
+ {
+ ch = 's';
+ *d->prefixes &= ~has_ss;
+ }
+ else
+ return 0;
+
+ if (*d->bufcntp + 4 > d->bufsize)
+ return *d->bufcntp + 4 - d->bufsize;
+
+ d->bufp[(*d->bufcntp)++] = '%';
+ d->bufp[(*d->bufcntp)++] = ch;
+ d->bufp[(*d->bufcntp)++] = 's';
+ d->bufp[(*d->bufcntp)++] = ':';
+
+ return 0;
+}
+
+#ifdef X86_64
+static const char hiregs[8][4] =
+ {
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+ };
+static const char aregs[8][4] =
+ {
+ "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"
+ };
+static const char dregs[8][4] =
+ {
+ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
+ };
+#else
+static const char aregs[8][4] =
+ {
+ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
+ };
+# define dregs aregs
+#endif
+
+static int
+general_mod$r_m (struct output_data *d)
+{
+ int r = data_prefix (d);
+ if (r != 0)
+ return r;
+
+ int prefixes = *d->prefixes;
+ const uint8_t *data = &d->data[d->opoff1 / 8];
+ char *bufp = d->bufp;
+ size_t *bufcntp = d->bufcntp;
+ size_t bufsize = d->bufsize;
+
+ uint_fast8_t modrm = data[0];
+#ifndef X86_64
+ if (unlikely ((prefixes & has_addr16) != 0))
+ {
+ int16_t disp = 0;
+ bool nodisp = false;
+
+ if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
+ /* 16 bit displacement. */
+ disp = read_2sbyte_unaligned (&data[1]);
+ else if ((modrm & 0xc0) == 0x40)
+ /* 8 bit displacement. */
+ disp = *(const int8_t *) &data[1];
+ else if ((modrm & 0xc0) == 0)
+ nodisp = true;
+
+ char tmpbuf[sizeof ("-0x1234(%rr,%rr)")];
+ int n;
+ if ((modrm & 0xc7) == 6)
+ n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx16, disp);
+ else
+ {
+ n = 0;
+ if (!nodisp)
+ n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx16,
+ disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
+
+ if ((modrm & 0x4) == 0)
+ n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%b%c,%%%ci)",
+ "xp"[(modrm >> 1) & 1], "sd"[modrm & 1]);
+ else
+ n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%%s)",
+ ((const char [4][3]) { "si", "di", "bp", "bx" })[modrm & 3]);
+ }
+
+ if (*bufcntp + n + 1 > bufsize)
+ return *bufcntp + n + 1 - bufsize;
+
+ memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
+ *bufcntp += n;
+ }
+ else
+#endif
+ {
+ if ((modrm & 7) != 4)
+ {
+ int32_t disp = 0;
+ bool nodisp = false;
+
+ if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80)
+ /* 32 bit displacement. */
+ disp = read_4sbyte_unaligned (&data[1]);
+ else if ((modrm & 0xc0) == 0x40)
+ /* 8 bit displacement. */
+ disp = *(const int8_t *) &data[1];
+ else if ((modrm & 0xc0) == 0)
+ nodisp = true;
+
+ char tmpbuf[sizeof ("-0x12345678(%rrrr)")];
+ int n;
+ if (nodisp)
+ {
+ n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)",
+#ifdef X86_64
+ (prefixes & has_rex_b) ? hiregs[modrm & 7] :
+#endif
+ aregs[modrm & 7]);
+#ifdef X86_64
+ if (prefixes & has_addr16)
+ {
+ if (prefixes & has_rex_b)
+ tmpbuf[n++] = 'd';
+ else
+ tmpbuf[2] = 'e';
+ }
+#endif
+ }
+ else if ((modrm & 0xc7) != 5)
+ {
+ int p;
+ n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%n%s)",
+ disp < 0 ? "-" : "", disp < 0 ? -disp : disp, &p,
+#ifdef X86_64
+ (prefixes & has_rex_b) ? hiregs[modrm & 7] :
+#endif
+ aregs[modrm & 7]);
+#ifdef X86_64
+ if (prefixes & has_addr16)
+ {
+ if (prefixes & has_rex_b)
+ tmpbuf[n++] = 'd';
+ else
+ tmpbuf[p] = 'e';
+ }
+#endif
+ }
+ else
+ {
+#ifdef X86_64
+ n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)",
+ disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
+
+ d->symaddr_use = addr_rel_always;
+ d->symaddr = disp;
+#else
+ n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp);
+#endif
+ }
+
+ if (*bufcntp + n + 1 > bufsize)
+ return *bufcntp + n + 1 - bufsize;
+
+ memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
+ *bufcntp += n;
+ }
+ else
+ {
+ /* SIB */
+ uint_fast8_t sib = data[1];
+ int32_t disp = 0;
+ bool nodisp = false;
+
+ if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
+ || ((modrm & 0xc7) == 0x4 && (sib & 0x7) == 0x5))
+ /* 32 bit displacement. */
+ disp = read_4sbyte_unaligned (&data[2]);
+ else if ((modrm & 0xc0) == 0x40)
+ /* 8 bit displacement. */
+ disp = *(const int8_t *) &data[2];
+ else
+ nodisp = true;
+
+ char tmpbuf[sizeof ("-0x12345678(%rrrr,%rrrr,N)")];
+ char *cp = tmpbuf;
+ int n;
+ if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25
+#ifdef X86_64
+ || (prefixes & has_rex_x) != 0
+#endif
+ )
+ {
+ if (!nodisp)
+ {
+ n = snprintf (cp, sizeof (tmpbuf), "%s0x%" PRIx32,
+ disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
+ cp += n;
+ }
+
+ *cp++ = '(';
+
+ if ((modrm & 0xc7) != 0x4 || (sib & 0x7) != 0x5)
+ {
+ *cp++ = '%';
+ cp = stpcpy (cp,
+#ifdef X86_64
+ (prefixes & has_rex_b) ? hiregs[sib & 7] :
+ (prefixes & has_addr16) ? dregs[sib & 7] :
+#endif
+ aregs[sib & 7]);
+#ifdef X86_64
+ if ((prefixes & (has_rex_b | has_addr16))
+ == (has_rex_b | has_addr16))
+ *cp++ = 'd';
+#endif
+ }
+
+ if ((sib & 0x38) != 0x20
+#ifdef X86_64
+ || (prefixes & has_rex_x) != 0
+#endif
+ )
+ {
+ *cp++ = ',';
+ *cp++ = '%';
+ cp = stpcpy (cp,
+#ifdef X86_64
+ (prefixes & has_rex_x)
+ ? hiregs[(sib >> 3) & 7] :
+ (prefixes & has_addr16)
+ ? dregs[(sib >> 3) & 7] :
+#endif
+ aregs[(sib >> 3) & 7]);
+#ifdef X86_64
+ if ((prefixes & (has_rex_b | has_addr16))
+ == (has_rex_b | has_addr16))
+ *cp++ = 'd';
+#endif
+
+ *cp++ = ',';
+ *cp++ = '0' + (1 << (sib >> 6));
+ }
+
+ *cp++ = ')';
+ }
+ else
+ {
+ assert (! nodisp);
+#ifdef X86_64
+ if ((prefixes & has_addr16) == 0)
+ n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx64,
+ (int64_t) disp);
+ else
+#endif
+ n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp);
+ cp += n;
+ }
+
+ if (*bufcntp + (cp - tmpbuf) > bufsize)
+ return *bufcntp + (cp - tmpbuf) - bufsize;
+
+ memcpy (&bufp[*bufcntp], tmpbuf, cp - tmpbuf);
+ *bufcntp += cp - tmpbuf;
+ }
+ }
+ return 0;
+}
+
+
+static int
+FCT_MOD$R_M (struct output_data *d)
+{
+ assert (d->opoff1 % 8 == 0);
+ uint_fast8_t modrm = d->data[d->opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ assert (d->opoff1 / 8 == d->opoff2 / 8);
+ assert (d->opoff2 % 8 == 5);
+ //uint_fast8_t byte = d->data[d->opoff2 / 8] & 7;
+ uint_fast8_t byte = modrm & 7;
+
+ size_t *bufcntp = d->bufcntp;
+ char *buf = d->bufp + *bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ int needed;
+ if (*d->prefixes & (has_rep | has_repne))
+ needed = snprintf (buf, avail, "%%%s", dregs[byte]);
+ else
+ needed = snprintf (buf, avail, "%%mm%" PRIxFAST8, byte);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+ }
+
+ return general_mod$r_m (d);
+}
+
+
+static int
+FCT_Mod$R_m (struct output_data *d)
+{
+ assert (d->opoff1 % 8 == 0);
+ uint_fast8_t modrm = d->data[d->opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ assert (d->opoff1 / 8 == d->opoff2 / 8);
+ assert (d->opoff2 % 8 == 5);
+ //uint_fast8_t byte = data[opoff2 / 8] & 7;
+ uint_fast8_t byte = modrm & 7;
+
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8,
+ byte);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *d->bufcntp += needed;
+ return 0;
+ }
+
+ return general_mod$r_m (d);
+}
+
+static int
+generic_abs (struct output_data *d, const char *absstring
+#ifdef X86_64
+ , int abslen
+#else
+# define abslen 4
+#endif
+ )
+{
+ int r = data_prefix (d);
+ if (r != 0)
+ return r;
+
+ assert (d->opoff1 % 8 == 0);
+ assert (d->opoff1 / 8 == 1);
+ if (*d->param_start + abslen > d->end)
+ return -1;
+ *d->param_start += abslen;
+#ifndef X86_64
+ uint32_t absval;
+# define ABSPRIFMT PRIx32
+#else
+ uint64_t absval;
+# define ABSPRIFMT PRIx64
+ if (abslen == 8)
+ absval = read_8ubyte_unaligned (&d->data[1]);
+ else
+#endif
+ absval = read_4ubyte_unaligned (&d->data[1]);
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "%s0x%" ABSPRIFMT,
+ absstring, absval);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+
+static int
+FCT_absval (struct output_data *d)
+{
+ return generic_abs (d, "$"
+#ifdef X86_64
+ , 4
+#endif
+ );
+}
+
+static int
+FCT_abs (struct output_data *d)
+{
+ return generic_abs (d, ""
+#ifdef X86_64
+ , 8
+#endif
+ );
+}
+
+static int
+FCT_ax (struct output_data *d)
+{
+ int is_16bit = (*d->prefixes & has_data16) != 0;
+
+ size_t *bufcntp = d->bufcntp;
+ char *bufp = d->bufp;
+ size_t bufsize = d->bufsize;
+
+ if (*bufcntp + 4 - is_16bit > bufsize)
+ return *bufcntp + 4 - is_16bit - bufsize;
+
+ bufp[(*bufcntp)++] = '%';
+ if (! is_16bit)
+ bufp[(*bufcntp)++] = (
+#ifdef X86_64
+ (*d->prefixes & has_rex_w) ? 'r' :
+#endif
+ 'e');
+ bufp[(*bufcntp)++] = 'a';
+ bufp[(*bufcntp)++] = 'x';
+
+ return 0;
+}
+
+
+static int
+FCT_ax$w (struct output_data *d)
+{
+ if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
+ return FCT_ax (d);
+
+ size_t *bufcntp = d->bufcntp;
+ char *bufp = d->bufp;
+ size_t bufsize = d->bufsize;
+
+ if (*bufcntp + 3 > bufsize)
+ return *bufcntp + 3 - bufsize;
+
+ bufp[(*bufcntp)++] = '%';
+ bufp[(*bufcntp)++] = 'a';
+ bufp[(*bufcntp)++] = 'l';
+
+ return 0;
+}
+
+
+static int
+__attribute__ ((noinline))
+FCT_crdb (struct output_data *d, const char *regstr)
+{
+ if (*d->prefixes & has_data16)
+ return -1;
+
+ size_t *bufcntp = d->bufcntp;
+
+ // XXX If this assert is true, use absolute offset below
+ assert (d->opoff1 / 8 == 2);
+ assert (d->opoff1 % 8 == 2);
+ size_t avail = d->bufsize - *bufcntp;
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "%%%s%" PRIx32,
+ regstr, (uint32_t) (d->data[d->opoff1 / 8] >> 3) & 7);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+
+static int
+FCT_ccc (struct output_data *d)
+{
+ return FCT_crdb (d, "cr");
+}
+
+
+static int
+FCT_ddd (struct output_data *d)
+{
+ return FCT_crdb (d, "db");
+}
+
+
+static int
+FCT_disp8 (struct output_data *d)
+{
+ assert (d->opoff1 % 8 == 0);
+ if (*d->param_start >= d->end)
+ return -1;
+ int32_t offset = *(const int8_t *) (*d->param_start)++;
+
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
+ (uint32_t) (d->addr + (*d->param_start - d->data)
+ + offset));
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+
+static int
+__attribute__ ((noinline))
+FCT_ds_xx (struct output_data *d, const char *reg)
+{
+ int prefix = *d->prefixes & SEGMENT_PREFIXES;
+
+ if (prefix == 0)
+ *d->prefixes |= prefix = has_ds;
+ /* Make sure only one bit is set. */
+ else if ((prefix - 1) & prefix)
+ return -1;
+
+ int r = data_prefix (d);
+
+ assert ((*d->prefixes & prefix) == 0);
+
+ if (r != 0)
+ return r;
+
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "(%%%s%s)",
+#ifdef X86_64
+ *d->prefixes & idx_addr16 ? "e" : "r",
+#else
+ *d->prefixes & idx_addr16 ? "" : "e",
+#endif
+ reg);
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+
+ return 0;
+}
+
+
+static int
+FCT_ds_bx (struct output_data *d)
+{
+ return FCT_ds_xx (d, "bx");
+}
+
+
+static int
+FCT_ds_si (struct output_data *d)
+{
+ return FCT_ds_xx (d, "si");
+}
+
+
+static int
+FCT_dx (struct output_data *d)
+{
+ size_t *bufcntp = d->bufcntp;
+
+ if (*bufcntp + 7 > d->bufsize)
+ return *bufcntp + 7 - d->bufsize;
+
+ memcpy (&d->bufp[*bufcntp], "(%dx)", 5);
+ *bufcntp += 5;
+
+ return 0;
+}
+
+
+static int
+FCT_es_di (struct output_data *d)
+{
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "%%es:(%%%sdi)",
+#ifdef X86_64
+ *d->prefixes & idx_addr16 ? "e" : "r"
+#else
+ *d->prefixes & idx_addr16 ? "" : "e"
+#endif
+ );
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+
+ return 0;
+}
+
+
+static int
+FCT_imm (struct output_data *d)
+{
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ int needed;
+ if (*d->prefixes & has_data16)
+ {
+ if (*d->param_start + 2 > d->end)
+ return -1;
+ uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
+ needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
+ }
+ else
+ {
+ if (*d->param_start + 4 > d->end)
+ return -1;
+ int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
+#ifdef X86_64
+ if (*d->prefixes & has_rex_w)
+ needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
+ (int64_t) word);
+ else
+#endif
+ needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
+ }
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+
+static int
+FCT_imm$w (struct output_data *d)
+{
+ if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
+ return FCT_imm (d);
+
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ if (*d->param_start>= d->end)
+ return -1;
+ uint_fast8_t word = *(*d->param_start)++;
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIxFAST8, word);
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+
+#ifdef X86_64
+static int
+FCT_imm64$w (struct output_data *d)
+{
+ if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) == 0
+ || (*d->prefixes & has_data16) != 0)
+ return FCT_imm$w (d);
+
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ int needed;
+ if (*d->prefixes & has_rex_w)
+ {
+ if (*d->param_start + 8 > d->end)
+ return -1;
+ uint64_t word = read_8ubyte_unaligned_inc (*d->param_start);
+ needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, word);
+ }
+ else
+ {
+ if (*d->param_start + 4 > d->end)
+ return -1;
+ int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
+ needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
+ }
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+#endif
+
+
+static int
+FCT_imms (struct output_data *d)
+{
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ if (*d->param_start>= d->end)
+ return -1;
+ int8_t byte = *(*d->param_start)++;
+#ifdef X86_64
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
+ (int64_t) byte);
+#else
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
+ (int32_t) byte);
+#endif
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+
+static int
+FCT_imm$s (struct output_data *d)
+{
+ uint_fast8_t opcode = d->data[d->opoff2 / 8];
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ if ((opcode & 2) != 0)
+ return FCT_imms (d);
+
+ if ((*d->prefixes & has_data16) == 0)
+ {
+ if (*d->param_start + 4 > d->end)
+ return -1;
+ int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
+#ifdef X86_64
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
+ (int64_t) word);
+#else
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
+#endif
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ }
+ else
+ {
+ if (*d->param_start + 2 > d->end)
+ return -1;
+ uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ }
+ return 0;
+}
+
+
+static int
+FCT_imm16 (struct output_data *d)
+{
+ if (*d->param_start + 2 > d->end)
+ return -1;
+ uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+
+static int
+FCT_imms8 (struct output_data *d)
+{
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ if (*d->param_start >= d->end)
+ return -1;
+ int_fast8_t byte = *(*d->param_start)++;
+ int needed;
+#ifdef X86_64
+ if (*d->prefixes & has_rex_w)
+ needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
+ (int64_t) byte);
+ else
+#endif
+ needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
+ (int32_t) byte);
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+
+static int
+FCT_imm8 (struct output_data *d)
+{
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ if (*d->param_start >= d->end)
+ return -1;
+ uint_fast8_t byte = *(*d->param_start)++;
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
+ (uint32_t) byte);
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+
+static int
+FCT_rel (struct output_data *d)
+{
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ if (*d->param_start + 4 > d->end)
+ return -1;
+ int32_t rel = read_4sbyte_unaligned_inc (*d->param_start);
+#ifdef X86_64
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx64,
+ (uint64_t) (d->addr + rel
+ + (*d->param_start - d->data)));
+#else
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
+ (uint32_t) (d->addr + rel
+ + (*d->param_start - d->data)));
+#endif
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+
+static int
+FCT_mmxreg (struct output_data *d)
+{
+ uint_fast8_t byte = d->data[d->opoff1 / 8];
+ assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
+ byte = (byte >> (5 - d->opoff1 % 8)) & 7;
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+
+static int
+FCT_mod$r_m (struct output_data *d)
+{
+ assert (d->opoff1 % 8 == 0);
+ uint_fast8_t modrm = d->data[d->opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ int prefixes = *d->prefixes;
+ if (prefixes & has_addr16)
+ return -1;
+
+ int is_16bit = (prefixes & has_data16) != 0;
+
+ size_t *bufcntp = d->bufcntp;
+ char *bufp = d->bufp;
+ if (*bufcntp + 5 - is_16bit > d->bufsize)
+ return *bufcntp + 5 - is_16bit - d->bufsize;
+ bufp[(*bufcntp)++] = '%';
+
+ char *cp;
+#ifdef X86_64
+ if ((prefixes & has_rex_b) != 0 && !is_16bit)
+ {
+ cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
+ if ((prefixes & has_rex_w) == 0)
+ *cp++ = 'd';
+ }
+ else
+#endif
+ {
+ cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
+#ifdef X86_64
+ if ((prefixes & has_rex_w) != 0)
+ bufp[*bufcntp] = 'r';
+#endif
+ }
+ *bufcntp = cp - bufp;
+ return 0;
+ }
+
+ return general_mod$r_m (d);
+}
+
+
+#ifndef X86_64
+static int
+FCT_moda$r_m (struct output_data *d)
+{
+ assert (d->opoff1 % 8 == 0);
+ uint_fast8_t modrm = d->data[d->opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ if (*d->prefixes & has_addr16)
+ return -1;
+
+ size_t *bufcntp = d->bufcntp;
+ if (*bufcntp + 3 > d->bufsize)
+ return *bufcntp + 3 - d->bufsize;
+
+ memcpy (&d->bufp[*bufcntp], "???", 3);
+ *bufcntp += 3;
+
+ return 0;
+ }
+
+ return general_mod$r_m (d);
+}
+#endif
+
+
+#ifdef X86_64
+static const char rex_8bit[8][3] =
+ {
+ [0] = "a", [1] = "c", [2] = "d", [3] = "b",
+ [4] = "sp", [5] = "bp", [6] = "si", [7] = "di"
+ };
+#endif
+
+
+static int
+FCT_mod$r_m$w (struct output_data *d)
+{
+ assert (d->opoff1 % 8 == 0);
+ const uint8_t *data = d->data;
+ uint_fast8_t modrm = data[d->opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ int prefixes = *d->prefixes;
+
+ if (prefixes & has_addr16)
+ return -1;
+
+ size_t *bufcntp = d->bufcntp;
+ char *bufp = d->bufp;
+ if (*bufcntp + 5 > d->bufsize)
+ return *bufcntp + 5 - d->bufsize;
+
+ if ((data[d->opoff3 / 8] & (1 << (7 - (d->opoff3 & 7)))) == 0)
+ {
+ bufp[(*bufcntp)++] = '%';
+
+#ifdef X86_64
+ if (prefixes & has_rex)
+ {
+ if (prefixes & has_rex_r)
+ *bufcntp += snprintf (bufp + *bufcntp, d->bufsize - *bufcntp,
+ "r%db", 8 + (modrm & 7));
+ else
+ {
+ char *cp = stpcpy (bufp + *bufcntp, hiregs[modrm & 7]);
+ *cp++ = 'l';
+ *bufcntp = cp - bufp;
+ }
+ }
+ else
+#endif
+ {
+ bufp[(*bufcntp)++] = "acdb"[modrm & 3];
+ bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
+ }
+ }
+ else
+ {
+ int is_16bit = (prefixes & has_data16) != 0;
+
+ bufp[(*bufcntp)++] = '%';
+
+ char *cp;
+#ifdef X86_64
+ if ((prefixes & has_rex_b) != 0 && !is_16bit)
+ {
+ cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
+ if ((prefixes & has_rex_w) == 0)
+ *cp++ = 'd';
+ }
+ else
+#endif
+ {
+ cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
+#ifdef X86_64
+ if ((prefixes & has_rex_w) != 0)
+ bufp[*bufcntp] = 'r';
+#endif
+ }
+ *bufcntp = cp - bufp;
+ }
+ return 0;
+ }
+
+ return general_mod$r_m (d);
+}
+
+
+static int
+FCT_mod$8r_m (struct output_data *d)
+{
+ assert (d->opoff1 % 8 == 0);
+ uint_fast8_t modrm = d->data[d->opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ size_t *bufcntp = d->bufcntp;
+ char *bufp = d->bufp;
+ if (*bufcntp + 3 > d->bufsize)
+ return *bufcntp + 3 - d->bufsize;
+ bufp[(*bufcntp)++] = '%';
+ bufp[(*bufcntp)++] = "acdb"[modrm & 3];
+ bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
+ return 0;
+ }
+
+ return general_mod$r_m (d);
+}
+
+
+static int
+FCT_mod$16r_m (struct output_data *d)
+{
+ assert (d->opoff1 % 8 == 0);
+ uint_fast8_t modrm = d->data[d->opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ assert (d->opoff1 / 8 == d->opoff2 / 8);
+ //uint_fast8_t byte = data[opoff2 / 8] & 7;
+ uint_fast8_t byte = modrm & 7;
+
+ size_t *bufcntp = d->bufcntp;
+ if (*bufcntp + 3 > d->bufsize)
+ return *bufcntp + 3 - d->bufsize;
+ d->bufp[(*bufcntp)++] = '%';
+ memcpy (&d->bufp[*bufcntp], dregs[byte] + 1, sizeof (dregs[0]) - 1);
+ *bufcntp += 2;
+ return 0;
+ }
+
+ return general_mod$r_m (d);
+}
+
+
+#ifdef X86_64
+static int
+FCT_mod$64r_m (struct output_data *d)
+{
+ assert (d->opoff1 % 8 == 0);
+ uint_fast8_t modrm = d->data[d->opoff1 / 8];
+ if ((modrm & 0xc0) == 0xc0)
+ {
+ assert (d->opoff1 / 8 == d->opoff2 / 8);
+ //uint_fast8_t byte = data[opoff2 / 8] & 7;
+ uint_fast8_t byte = modrm & 7;
+
+ size_t *bufcntp = d->bufcntp;
+ if (*bufcntp + 4 > d->bufsize)
+ return *bufcntp + 4 - d->bufsize;
+ char *cp = &d->bufp[*bufcntp];
+ *cp++ = '%';
+ cp = stpcpy (cp,
+ (*d->prefixes & has_rex_b) ? hiregs[byte] : aregs[byte]);
+ *bufcntp = cp - d->bufp;
+ return 0;
+ }
+
+ return general_mod$r_m (d);
+}
+#else
+static typeof (FCT_mod$r_m) FCT_mod$64r_m __attribute__ ((alias ("FCT_mod$r_m")));
+#endif
+
+
+static int
+FCT_reg (struct output_data *d)
+{
+ uint_fast8_t byte = d->data[d->opoff1 / 8];
+ assert (d->opoff1 % 8 + 3 <= 8);
+ byte >>= 8 - (d->opoff1 % 8 + 3);
+ byte &= 7;
+ int is_16bit = (*d->prefixes & has_data16) != 0;
+ size_t *bufcntp = d->bufcntp;
+ if (*bufcntp + 5 > d->bufsize)
+ return *bufcntp + 5 - d->bufsize;
+ d->bufp[(*bufcntp)++] = '%';
+#ifdef X86_64
+ if ((*d->prefixes & has_rex_r) != 0 && !is_16bit)
+ {
+ *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
+ 8 + byte);
+ if ((*d->prefixes & has_rex_w) == 0)
+ d->bufp[(*bufcntp)++] = 'd';
+ }
+ else
+#endif
+ {
+ memcpy (&d->bufp[*bufcntp], dregs[byte] + is_16bit, 3 - is_16bit);
+#ifdef X86_64
+ if ((*d->prefixes & has_rex_w) != 0 && !is_16bit)
+ d->bufp[*bufcntp] = 'r';
+#endif
+ *bufcntp += 3 - is_16bit;
+ }
+ return 0;
+}
+
+
+#ifdef X86_64
+static int
+FCT_oreg (struct output_data *d)
+{
+ /* Special form where register comes from opcode. The rex.B bit is used,
+ rex.R and rex.X are ignored. */
+ int save_prefixes = *d->prefixes;
+
+ *d->prefixes = ((save_prefixes & ~has_rex_r)
+ | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
+
+ int r = FCT_reg (d);
+
+ *d->prefixes = save_prefixes;
+
+ return r;
+}
+#endif
+
+
+static int
+FCT_reg64 (struct output_data *d)
+{
+ uint_fast8_t byte = d->data[d->opoff1 / 8];
+ assert (d->opoff1 % 8 + 3 <= 8);
+ byte >>= 8 - (d->opoff1 % 8 + 3);
+ byte &= 7;
+ if ((*d->prefixes & has_data16) != 0)
+ return -1;
+ size_t *bufcntp = d->bufcntp;
+ if (*bufcntp + 5 > d->bufsize)
+ return *bufcntp + 5 - d->bufsize;
+ d->bufp[(*bufcntp)++] = '%';
+#ifdef X86_64
+ if ((*d->prefixes & has_rex_r) != 0)
+ {
+ *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
+ 8 + byte);
+ if ((*d->prefixes & has_rex_w) == 0)
+ d->bufp[(*bufcntp)++] = 'd';
+ }
+ else
+#endif
+ {
+ memcpy (&d->bufp[*bufcntp], aregs[byte], 3);
+ *bufcntp += 3;
+ }
+ return 0;
+}
+
+
+static int
+FCT_reg$w (struct output_data *d)
+{
+ if (d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7))))
+ return FCT_reg (d);
+
+ uint_fast8_t byte = d->data[d->opoff1 / 8];
+ assert (d->opoff1 % 8 + 3 <= 8);
+ byte >>= 8 - (d->opoff1 % 8 + 3);
+ byte &= 7;
+
+ size_t *bufcntp = d->bufcntp;
+ if (*bufcntp + 4 > d->bufsize)
+ return *bufcntp + 4 - d->bufsize;
+
+ d->bufp[(*bufcntp)++] = '%';
+
+#ifdef X86_64
+ if (*d->prefixes & has_rex)
+ {
+ if (*d->prefixes & has_rex_r)
+ *bufcntp += snprintf (d->bufp + *bufcntp, d->bufsize - *bufcntp,
+ "r%db", 8 + byte);
+ else
+ {
+ char* cp = stpcpy (d->bufp + *bufcntp, rex_8bit[byte]);
+ *cp++ = 'l';
+ *bufcntp = cp - d->bufp;
+ }
+ }
+ else
+#endif
+ {
+ d->bufp[(*bufcntp)++] = "acdb"[byte & 3];
+ d->bufp[(*bufcntp)++] = "lh"[byte >> 2];
+ }
+ return 0;
+}
+
+
+#ifdef X86_64
+static int
+FCT_oreg$w (struct output_data *d)
+{
+ /* Special form where register comes from opcode. The rex.B bit is used,
+ rex.R and rex.X are ignored. */
+ int save_prefixes = *d->prefixes;
+
+ *d->prefixes = ((save_prefixes & ~has_rex_r)
+ | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
+
+ int r = FCT_reg$w (d);
+
+ *d->prefixes = save_prefixes;
+
+ return r;
+}
+#endif
+
+
+static int
+FCT_freg (struct output_data *d)
+{
+ assert (d->opoff1 / 8 == 1);
+ assert (d->opoff1 % 8 == 5);
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "%%st(%" PRIx32 ")",
+ (uint32_t) (d->data[1] & 7));
+ if ((size_t) needed > avail)
+ return (size_t) needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+
+#ifndef X86_64
+static int
+FCT_reg16 (struct output_data *d)
+{
+ if (*d->prefixes & has_data16)
+ return -1;
+
+ *d->prefixes |= has_data16;
+ return FCT_reg (d);
+}
+#endif
+
+
+static int
+FCT_sel (struct output_data *d)
+{
+ assert (d->opoff1 % 8 == 0);
+ assert (d->opoff1 / 8 == 5);
+ if (*d->param_start + 2 > d->end)
+ return -1;
+ *d->param_start += 2;
+ uint16_t absval = read_2ubyte_unaligned (&d->data[5]);
+
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, absval);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
+
+
+static int
+FCT_sreg2 (struct output_data *d)
+{
+ uint_fast8_t byte = d->data[d->opoff1 / 8];
+ assert (d->opoff1 % 8 + 3 <= 8);
+ byte >>= 8 - (d->opoff1 % 8 + 2);
+
+ size_t *bufcntp = d->bufcntp;
+ char *bufp = d->bufp;
+ if (*bufcntp + 3 > d->bufsize)
+ return *bufcntp + 3 - d->bufsize;
+
+ bufp[(*bufcntp)++] = '%';
+ bufp[(*bufcntp)++] = "ecsd"[byte & 3];
+ bufp[(*bufcntp)++] = 's';
+
+ return 0;
+}
+
+
+static int
+FCT_sreg3 (struct output_data *d)
+{
+ uint_fast8_t byte = d->data[d->opoff1 / 8];
+ assert (d->opoff1 % 8 + 4 <= 8);
+ byte >>= 8 - (d->opoff1 % 8 + 3);
+
+ if ((byte & 7) >= 6)
+ return -1;
+
+ size_t *bufcntp = d->bufcntp;
+ char *bufp = d->bufp;
+ if (*bufcntp + 3 > d->bufsize)
+ return *bufcntp + 3 - d->bufsize;
+
+ bufp[(*bufcntp)++] = '%';
+ bufp[(*bufcntp)++] = "ecsdfg"[byte & 7];
+ bufp[(*bufcntp)++] = 's';
+
+ return 0;
+}
+
+
+static int
+FCT_string (struct output_data *d __attribute__ ((unused)))
+{
+ return 0;
+}
+
+
+static int
+FCT_xmmreg (struct output_data *d)
+{
+ uint_fast8_t byte = d->data[d->opoff1 / 8];
+ assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
+ byte = (byte >> (5 - d->opoff1 % 8)) & 7;
+
+ size_t *bufcntp = d->bufcntp;
+ size_t avail = d->bufsize - *bufcntp;
+ int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte);
+ if ((size_t) needed > avail)
+ return needed - avail;
+ *bufcntp += needed;
+ return 0;
+}
diff --git a/libcpu/i386_disasm.c b/libcpu/i386_disasm.c
new file mode 100644
index 0000000..c6bb0a5
--- /dev/null
+++ b/libcpu/i386_disasm.c
@@ -0,0 +1,1054 @@
+/* Disassembler for x86.
+ Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2007.
+
+ Red Hat elfutils 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; version 2 of the License.
+
+ Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <config.h>
+#include <ctype.h>
+#include <endian.h>
+#include <errno.h>
+#include <gelf.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+#include "../libebl/libeblP.h"
+
+#define MACHINE_ENCODING __LITTLE_ENDIAN
+#include "memory-access.h"
+
+
+#ifndef MNEFILE
+# define MNEFILE "i386.mnemonics"
+#endif
+
+#define MNESTRFIELD(line) MNESTRFIELD1 (line)
+#define MNESTRFIELD1(line) str##line
+static const union mnestr_t
+{
+ struct
+ {
+#define MNE(name) char MNESTRFIELD (__LINE__)[sizeof (#name)];
+#include MNEFILE
+#undef MNE
+ };
+ char str[0];
+} mnestr =
+ {
+ {
+#define MNE(name) #name,
+#include MNEFILE
+#undef MNE
+ }
+ };
+
+/* The index can be stored in the instrtab. */
+enum
+ {
+#define MNE(name) MNE_##name,
+#include MNEFILE
+#undef MNE
+ MNE_INVALID
+ };
+
+static const unsigned short int mneidx[] =
+ {
+#define MNE(name) \
+ [MNE_##name] = offsetof (union mnestr_t, MNESTRFIELD (__LINE__)),
+#include MNEFILE
+#undef MNE
+ };
+
+
+enum
+ {
+ idx_rex_b = 0,
+ idx_rex_x,
+ idx_rex_r,
+ idx_rex_w,
+ idx_rex,
+ idx_cs,
+ idx_ds,
+ idx_es,
+ idx_fs,
+ idx_gs,
+ idx_ss,
+ idx_data16,
+ idx_addr16,
+ idx_rep,
+ idx_repne,
+ idx_lock
+ };
+
+enum
+ {
+#define prefbit(pref) has_##pref = 1 << idx_##pref
+ prefbit (rex_b),
+ prefbit (rex_x),
+ prefbit (rex_r),
+ prefbit (rex_w),
+ prefbit (rex),
+ prefbit (cs),
+ prefbit (ds),
+ prefbit (es),
+ prefbit (fs),
+ prefbit (gs),
+ prefbit (ss),
+ prefbit (data16),
+ prefbit (addr16),
+ prefbit (rep),
+ prefbit (repne),
+ prefbit (lock)
+#undef prefbit
+ };
+#define SEGMENT_PREFIXES \
+ (has_cs | has_ds | has_es | has_fs | has_gs | has_ss)
+
+#define prefix_cs 0x2e
+#define prefix_ds 0x3e
+#define prefix_es 0x26
+#define prefix_fs 0x64
+#define prefix_gs 0x65
+#define prefix_ss 0x36
+#define prefix_data16 0x66
+#define prefix_addr16 0x67
+#define prefix_rep 0xf3
+#define prefix_repne 0xf2
+#define prefix_lock 0xf0
+
+
+static const uint8_t known_prefixes[] =
+ {
+#define newpref(pref) [idx_##pref] = prefix_##pref
+ newpref (cs),
+ newpref (ds),
+ newpref (es),
+ newpref (fs),
+ newpref (gs),
+ newpref (ss),
+ newpref (data16),
+ newpref (addr16),
+ newpref (rep),
+ newpref (repne),
+ newpref (lock)
+#undef newpref
+ };
+#define nknown_prefixes (sizeof (known_prefixes) / sizeof (known_prefixes[0]))
+
+
+#if 0
+static const char *prefix_str[] =
+ {
+#define newpref(pref) [idx_##pref] = #pref
+ newpref (cs),
+ newpref (ds),
+ newpref (es),
+ newpref (fs),
+ newpref (gs),
+ newpref (ss),
+ newpref (data16),
+ newpref (addr16),
+ newpref (rep),
+ newpref (repne),
+ newpref (lock)
+#undef newpref
+ };
+#endif
+
+
+static const char amd3dnowstr[] =
+#define MNE_3DNOW_PAVGUSB 1
+ "pavgusb\0"
+#define MNE_3DNOW_PFADD (MNE_3DNOW_PAVGUSB + 8)
+ "pfadd\0"
+#define MNE_3DNOW_PFSUB (MNE_3DNOW_PFADD + 6)
+ "pfsub\0"
+#define MNE_3DNOW_PFSUBR (MNE_3DNOW_PFSUB + 6)
+ "pfsubr\0"
+#define MNE_3DNOW_PFACC (MNE_3DNOW_PFSUBR + 7)
+ "pfacc\0"
+#define MNE_3DNOW_PFCMPGE (MNE_3DNOW_PFACC + 6)
+ "pfcmpge\0"
+#define MNE_3DNOW_PFCMPGT (MNE_3DNOW_PFCMPGE + 8)
+ "pfcmpgt\0"
+#define MNE_3DNOW_PFCMPEQ (MNE_3DNOW_PFCMPGT + 8)
+ "pfcmpeq\0"
+#define MNE_3DNOW_PFMIN (MNE_3DNOW_PFCMPEQ + 8)
+ "pfmin\0"
+#define MNE_3DNOW_PFMAX (MNE_3DNOW_PFMIN + 6)
+ "pfmax\0"
+#define MNE_3DNOW_PI2FD (MNE_3DNOW_PFMAX + 6)
+ "pi2fd\0"
+#define MNE_3DNOW_PF2ID (MNE_3DNOW_PI2FD + 6)
+ "pf2id\0"
+#define MNE_3DNOW_PFRCP (MNE_3DNOW_PF2ID + 6)
+ "pfrcp\0"
+#define MNE_3DNOW_PFRSQRT (MNE_3DNOW_PFRCP + 6)
+ "pfrsqrt\0"
+#define MNE_3DNOW_PFMUL (MNE_3DNOW_PFRSQRT + 8)
+ "pfmul\0"
+#define MNE_3DNOW_PFRCPIT1 (MNE_3DNOW_PFMUL + 6)
+ "pfrcpit1\0"
+#define MNE_3DNOW_PFRSQIT1 (MNE_3DNOW_PFRCPIT1 + 9)
+ "pfrsqit1\0"
+#define MNE_3DNOW_PFRCPIT2 (MNE_3DNOW_PFRSQIT1 + 9)
+ "pfrcpit2\0"
+#define MNE_3DNOW_PMULHRW (MNE_3DNOW_PFRCPIT2 + 9)
+ "pmulhrw";
+
+#define AMD3DNOW_LOW_IDX 0x0d
+#define AMD3DNOW_HIGH_IDX (sizeof (amd3dnow) + AMD3DNOW_LOW_IDX - 1)
+#define AMD3DNOW_IDX(val) ((val) - AMD3DNOW_LOW_IDX)
+static const unsigned char amd3dnow[] =
+ {
+ [AMD3DNOW_IDX (0xbf)] = MNE_3DNOW_PAVGUSB,
+ [AMD3DNOW_IDX (0x9e)] = MNE_3DNOW_PFADD,
+ [AMD3DNOW_IDX (0x9a)] = MNE_3DNOW_PFSUB,
+ [AMD3DNOW_IDX (0xaa)] = MNE_3DNOW_PFSUBR,
+ [AMD3DNOW_IDX (0xae)] = MNE_3DNOW_PFACC,
+ [AMD3DNOW_IDX (0x90)] = MNE_3DNOW_PFCMPGE,
+ [AMD3DNOW_IDX (0xa0)] = MNE_3DNOW_PFCMPGT,
+ [AMD3DNOW_IDX (0xb0)] = MNE_3DNOW_PFCMPEQ,
+ [AMD3DNOW_IDX (0x94)] = MNE_3DNOW_PFMIN,
+ [AMD3DNOW_IDX (0xa4)] = MNE_3DNOW_PFMAX,
+ [AMD3DNOW_IDX (0x0d)] = MNE_3DNOW_PI2FD,
+ [AMD3DNOW_IDX (0x1d)] = MNE_3DNOW_PF2ID,
+ [AMD3DNOW_IDX (0x96)] = MNE_3DNOW_PFRCP,
+ [AMD3DNOW_IDX (0x97)] = MNE_3DNOW_PFRSQRT,
+ [AMD3DNOW_IDX (0xb4)] = MNE_3DNOW_PFMUL,
+ [AMD3DNOW_IDX (0xa6)] = MNE_3DNOW_PFRCPIT1,
+ [AMD3DNOW_IDX (0xa7)] = MNE_3DNOW_PFRSQIT1,
+ [AMD3DNOW_IDX (0xb6)] = MNE_3DNOW_PFRCPIT2,
+ [AMD3DNOW_IDX (0xb7)] = MNE_3DNOW_PMULHRW
+ };
+
+
+struct output_data
+{
+ GElf_Addr addr;
+ int *prefixes;
+ size_t opoff1;
+ size_t opoff2;
+ size_t opoff3;
+ char *bufp;
+ size_t *bufcntp;
+ size_t bufsize;
+ const uint8_t *data;
+ const uint8_t **param_start;
+ const uint8_t *end;
+ char *labelbuf;
+ size_t labelbufsize;
+ enum
+ {
+ addr_none = 0,
+ addr_abs_symbolic,
+ addr_abs_always,
+ addr_rel_symbolic,
+ addr_rel_always
+ } symaddr_use;
+ GElf_Addr symaddr;
+};
+
+
+#ifndef DISFILE
+# define DISFILE "i386_dis.h"
+#endif
+#include DISFILE
+
+
+#define ADD_CHAR(ch) \
+ do { \
+ if (unlikely (bufcnt == bufsize)) \
+ goto enomem; \
+ buf[bufcnt++] = (ch); \
+ } while (0)
+
+#define ADD_STRING(str) \
+ do { \
+ const char *_str = (str); \
+ size_t _len = strlen (_str); \
+ if (unlikely (bufcnt + _len > bufsize)) \
+ goto enomem; \
+ memcpy (buf + bufcnt, str, _len); \
+ bufcnt += _len; \
+ } while (0)
+
+
+int
+i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
+ const char *fmt, DisasmOutputCB_t outcb, DisasmGetSymCB_t symcb,
+ void *outcbarg, void *symcbarg)
+{
+ const char *save_fmt = fmt;
+
+#define BUFSIZE 512
+ char initbuf[BUFSIZE];
+ int prefixes;
+ size_t bufcnt;
+ size_t bufsize = BUFSIZE;
+ char *buf = initbuf;
+ const uint8_t *param_start;
+
+ struct output_data output_data =
+ {
+ .prefixes = &prefixes,
+ .bufp = buf,
+ .bufsize = bufsize,
+ .bufcntp = &bufcnt,
+ .param_start = &param_start,
+ .end = end
+ };
+
+ int retval = 0;
+ while (1)
+ {
+ prefixes = 0;
+
+ const uint8_t *data = *startp;
+ const uint8_t *begin = data;
+
+ /* Recognize all prefixes. */
+ int last_prefix_bit = 0;
+ while (data < end)
+ {
+ unsigned int i;
+ for (i = idx_cs; i < nknown_prefixes; ++i)
+ if (known_prefixes[i] == *data)
+ break;
+ if (i == nknown_prefixes)
+ break;
+
+ prefixes |= last_prefix_bit = 1 << i;
+
+ ++data;
+ }
+
+#ifdef X86_64
+ if (data < end && (*data & 0xf0) == 0x40)
+ prefixes |= ((*data++) & 0xf) | has_rex;
+#endif
+
+ bufcnt = 0;
+ size_t cnt = 0;
+
+ const uint8_t *curr = match_data;
+ const uint8_t *const match_end = match_data + sizeof (match_data);
+
+ assert (data <= end);
+ if (data == end)
+ {
+ if (prefixes != 0)
+ goto print_prefix;
+
+ retval = -1;
+ goto do_ret;
+ }
+
+ next_match:
+ while (curr < match_end)
+ {
+ uint_fast8_t len = *curr++;
+ uint_fast8_t clen = len >> 4;
+ len &= 0xf;
+ const uint8_t *next_curr = curr + clen + (len - clen) * 2;
+
+ assert (len > 0);
+ assert (curr + clen + 2 * (len - clen) <= match_end);
+
+ const uint8_t *codep = data;
+ int correct_prefix = 0;
+ int opoff = 0;
+
+ if (data > begin && codep[-1] == *curr && clen > 0)
+ {
+ /* We match a prefix byte. This is exactly one byte and
+ is matched exactly, without a mask. */
+ --len;
+ --clen;
+ opoff = 8;
+
+ ++curr;
+
+ assert (last_prefix_bit != 0);
+ correct_prefix = last_prefix_bit;
+ }
+
+ size_t avail = len;
+ while (clen > 0)
+ {
+ if (*codep++ != *curr++)
+ goto not;
+ --avail;
+ --clen;
+ if (codep == end && avail > 0)
+ goto do_ret;
+ }
+
+ while (avail > 0)
+ {
+ uint_fast8_t masked = *codep++ & *curr++;
+ if (masked != *curr++)
+ {
+ not:
+ curr = next_curr;
+ ++cnt;
+ bufcnt = 0;
+ goto next_match;
+ }
+
+ --avail;
+ if (codep == end && avail > 0)
+ goto do_ret;
+ }
+
+ if (len > end - data)
+ /* There is not enough data for the entire instruction. The
+ caller can figure this out by looking at the pointer into
+ the input data. */
+ goto do_ret;
+
+ assert (correct_prefix == 0
+ || (prefixes & correct_prefix) != 0);
+ prefixes ^= correct_prefix;
+
+ if (0)
+ {
+ /* Resize the buffer. */
+ char *oldbuf;
+ enomem:
+ oldbuf = buf;
+ if (buf == initbuf)
+ buf = malloc (2 * bufsize);
+ else
+ buf = realloc (buf, 2 * bufsize);
+ if (buf == NULL)
+ {
+ buf = oldbuf;
+ retval = ENOMEM;
+ goto do_ret;
+ }
+ bufsize *= 2;
+
+ output_data.bufp = buf;
+ output_data.bufsize = bufsize;
+ bufcnt = 0;
+
+ if (data == end)
+ {
+ assert (prefixes != 0);
+ goto print_prefix;
+ }
+
+ /* gcc is not clever enough to see the following variables
+ are not used uninitialized. */
+ asm (""
+ : "=mr" (opoff), "=mr" (correct_prefix), "=mr" (codep),
+ "=mr" (next_curr), "=mr" (len));
+ }
+
+ size_t prefix_size = 0;
+
+ // XXXonly print as prefix if valid?
+ if ((prefixes & has_lock) != 0)
+ {
+ ADD_STRING ("lock ");
+ prefix_size += 5;
+ }
+
+ if (instrtab[cnt].rep)
+ {
+ if ((prefixes & has_rep) != 0)
+ {
+ ADD_STRING ("rep ");
+ prefix_size += 4;
+ }
+ }
+ else if (instrtab[cnt].repe
+ && (prefixes & (has_rep | has_repne)) != 0)
+ {
+ if ((prefixes & has_repne) != 0)
+ {
+ ADD_STRING ("repne ");
+ prefix_size += 6;
+ }
+ else if ((prefixes & has_rep) != 0)
+ {
+ ADD_STRING ("repe ");
+ prefix_size += 5;
+ }
+ }
+ else if ((prefixes & (has_rep | has_repne)) != 0)
+ {
+ uint_fast8_t byte;
+ print_prefix:
+ bufcnt = 0;
+ byte = *begin;
+ /* This is a prefix byte. Print it. */
+ switch (byte)
+ {
+ case prefix_rep:
+ ADD_STRING ("rep");
+ break;
+ case prefix_repne:
+ ADD_STRING ("repne");
+ break;
+ case prefix_cs:
+ ADD_STRING ("cs");
+ break;
+ case prefix_ds:
+ ADD_STRING ("ds");
+ break;
+ case prefix_es:
+ ADD_STRING ("es");
+ break;
+ case prefix_fs:
+ ADD_STRING ("fs");
+ break;
+ case prefix_gs:
+ ADD_STRING ("gs");
+ break;
+ case prefix_ss:
+ ADD_STRING ("ss");
+ break;
+ case prefix_data16:
+ ADD_STRING ("data16");
+ break;
+ case prefix_addr16:
+ ADD_STRING ("addr16");
+ break;
+ case prefix_lock:
+ ADD_STRING ("lock");
+ break;
+#ifdef X86_64
+ case 0x40 ... 0x4f:
+ ADD_STRING ("rex");
+ if (byte != 0x40)
+ {
+ ADD_CHAR ('.');
+ if (byte & 0x8)
+ ADD_CHAR ('w');
+ if (byte & 0x4)
+ ADD_CHAR ('r');
+ if (byte & 0x3)
+ ADD_CHAR ('x');
+ if (byte & 0x1)
+ ADD_CHAR ('b');
+ }
+ break;
+#endif
+ default:
+ /* Cannot happen. */
+ puts ("unknown prefix");
+ abort ();
+ }
+ data = begin + 1;
+ ++addr;
+
+ goto out;
+ }
+
+ /* We have a match. First determine how many bytes are
+ needed for the adressing mode. */
+ param_start = codep;
+ if (instrtab[cnt].modrm)
+ {
+ uint_fast8_t modrm = codep[-1];
+
+#ifndef X86_64
+ if (likely ((prefixes & has_addr16) != 0))
+ {
+ /* Account for displacement. */
+ if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
+ param_start += 2;
+ else if ((modrm & 0xc0) == 0x40)
+ param_start += 1;
+ }
+ else
+#endif
+ {
+ /* Account for SIB. */
+ if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 0x4)
+ param_start += 1;
+
+ /* Account for displacement. */
+ if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
+ || ((modrm & 0xc7) == 0x4 && (codep[0] & 0x7) == 0x5))
+ param_start += 4;
+ else if ((modrm & 0xc0) == 0x40)
+ param_start += 1;
+ }
+
+ if (unlikely (param_start > end))
+ goto not;
+ }
+
+ output_data.addr = addr + (data - begin);
+ output_data.data = data;
+
+ unsigned long string_end_idx = 0;
+ fmt = save_fmt;
+ while (*fmt != '\0')
+ {
+ if (*fmt != '%')
+ {
+ char ch = *fmt++;
+ if (ch == '\\')
+ {
+ switch ((ch = *fmt++))
+ {
+ case '0' ... '7':
+ {
+ int val = ch - '0';
+ ch = *fmt;
+ if (ch >= '0' && ch <= '7')
+ {
+ val *= 8;
+ val += ch - '0';
+ ch = *++fmt;
+ if (ch >= '0' && ch <= '7' && val < 32)
+ {
+ val *= 8;
+ val += ch - '0';
+ ++fmt;
+ }
+ }
+ ch = val;
+ }
+ break;
+
+ case 'n':
+ ch = '\n';
+ break;
+
+ case 't':
+ ch = '\t';
+ break;
+
+ default:
+ retval = EINVAL;
+ goto do_ret;
+ }
+ }
+ ADD_CHAR (ch);
+ continue;
+ }
+ ++fmt;
+
+ int width = 0;
+ while (isdigit (*fmt))
+ width = width * 10 + (*fmt++ - '0');
+
+ int prec = 0;
+ if (*fmt == '.')
+ while (isdigit (*++fmt))
+ prec = prec * 10 + (*fmt - '0');
+
+ size_t start_idx = bufcnt;
+ switch (*fmt++)
+ {
+ char mnebuf[16];
+ const char *str;
+
+ case 'm':
+ /* Mnemonic. */
+
+ if (unlikely (instrtab[cnt].mnemonic == MNE_INVALID))
+ {
+ switch (*data)
+ {
+#ifdef X86_64
+ case 0x90:
+ if (prefixes & has_rex_b)
+ goto not;
+ str = "nop";
+ break;
+#endif
+
+ case 0x98:
+#ifdef X86_64
+ if (prefixes == (has_rex_w | has_rex))
+ {
+ str = "cltq";
+ break;
+ }
+#endif
+ if (prefixes & ~has_data16)
+ goto print_prefix;
+ str = prefixes & has_data16 ? "cbtw" : "cwtl";
+ break;
+
+ case 0x99:
+#ifdef X86_64
+ if (prefixes == (has_rex_w | has_rex))
+ {
+ str = "cqto";
+ break;
+ }
+#endif
+ if (prefixes & ~has_data16)
+ goto print_prefix;
+ str = prefixes & has_data16 ? "cwtd" : "cltd";
+ break;
+
+ case 0xe3:
+ if (prefixes & ~has_addr16)
+ goto print_prefix;
+#ifdef X86_64
+ str = prefixes & has_addr16 ? "jecxz" : "jrcxz";
+#else
+ str = prefixes & has_addr16 ? "jcxz" : "jecxz";
+#endif
+ break;
+
+ case 0x0f:
+ if (data[1] == 0x0f)
+ {
+ /* AMD 3DNOW. We need one more byte. */
+ if (param_start >= end)
+ goto not;
+ if (*param_start < AMD3DNOW_LOW_IDX
+ || *param_start > AMD3DNOW_HIGH_IDX)
+ goto not;
+ unsigned int idx
+ = amd3dnow[AMD3DNOW_IDX (*param_start)];
+ if (idx == 0)
+ goto not;
+ str = amd3dnowstr + idx - 1;
+ /* Eat the immediate byte indicating the
+ operation. */
+ ++param_start;
+ break;
+ }
+#ifdef X86_64
+ if (data[1] == 0xc7)
+ {
+ str = ((prefixes & has_rex_w)
+ ? "cmpxchg16b" : "cmpxchg8b");
+ break;
+ }
+#endif
+ if (data[1] == 0xc2)
+ {
+ if (param_start >= end)
+ goto not;
+ if (*param_start > 7)
+ goto not;
+ static const char cmpops[][9] =
+ {
+ [0] = "cmpeq",
+ [1] = "cmplt",
+ [2] = "cmple",
+ [3] = "cmpunord",
+ [4] = "cmpneq",
+ [5] = "cmpnlt",
+ [6] = "cmpnle",
+ [7] = "cmpord"
+ };
+ char *cp = stpcpy (mnebuf, cmpops[*param_start]);
+ if (correct_prefix & (has_rep | has_repne))
+ *cp++ = 's';
+ else
+ *cp++ = 'p';
+ if (correct_prefix & (has_data16 | has_repne))
+ *cp++ = 'd';
+ else
+ *cp++ = 's';
+ *cp = '\0';
+ str = mnebuf;
+ /* Eat the immediate byte indicating the
+ operation. */
+ ++param_start;
+ break;
+ }
+
+ default:
+ assert (! "INVALID not handled");
+ }
+ }
+ else
+ str = mnestr.str + mneidx[instrtab[cnt].mnemonic];
+
+ ADD_STRING (str);
+
+ switch (instrtab[cnt].suffix)
+ {
+ case suffix_none:
+ break;
+
+ case suffix_w:
+ if ((codep[-1] & 0xc0) != 0xc0)
+ {
+ char ch;
+
+ if (data[0] & 1)
+ {
+ if (prefixes & has_data16)
+ ch = 'w';
+#ifdef X86_64
+ else if (prefixes & has_rex_w)
+ ch = 'q';
+#endif
+ else
+ ch = 'l';
+ }
+ else
+ ch = 'b';
+
+ ADD_CHAR (ch);
+ }
+ break;
+
+ case suffix_w0:
+ if ((codep[-1] & 0xc0) != 0xc0)
+ ADD_CHAR ('l');
+ break;
+
+ case suffix_w1:
+ if ((data[0] & 0x4) == 0)
+ ADD_CHAR ('l');
+ break;
+
+ case suffix_W:
+ if (prefixes & has_data16)
+ {
+ ADD_CHAR ('w');
+ prefixes &= ~has_data16;
+ }
+#ifdef X86_64
+ else
+ ADD_CHAR ('q');
+#endif
+ break;
+
+ case suffix_W1:
+ if (prefixes & has_data16)
+ {
+ ADD_CHAR ('w');
+ prefixes &= ~has_data16;
+ }
+#ifdef X86_64
+ else if (prefixes & has_rex_w)
+ ADD_CHAR ('q');
+#endif
+ break;
+
+ case suffix_tttn:;
+ static const char tttn[16][3] =
+ {
+ "o", "no", "b", "ae", "e", "ne", "be", "a",
+ "s", "ns", "p", "np", "l", "ge", "le", "g"
+ };
+ ADD_STRING (tttn[codep[-1 - instrtab[cnt].modrm] & 0x0f]);
+ break;
+
+ case suffix_D:
+ if ((codep[-1] & 0xc0) != 0xc0)
+ ADD_CHAR ((data[0] & 0x04) == 0 ? 's' : 'l');
+ break;
+
+ default:
+ printf("unknown suffix %d\n", instrtab[cnt].suffix);
+ abort ();
+ }
+
+ string_end_idx = bufcnt;
+ break;
+
+ case 'o':
+ if (prec == 1 && instrtab[cnt].fct1 != 0)
+ {
+ /* First parameter. */
+ if (instrtab[cnt].str1 != 0)
+ ADD_STRING (op1_str
+ + op1_str_idx[instrtab[cnt].str1 - 1]);
+
+ output_data.opoff1 = (instrtab[cnt].off1_1
+ + OFF1_1_BIAS - opoff);
+ output_data.opoff2 = (instrtab[cnt].off1_2
+ + OFF1_2_BIAS - opoff);
+ output_data.opoff3 = (instrtab[cnt].off1_3
+ + OFF1_3_BIAS - opoff);
+ int r = op1_fct[instrtab[cnt].fct1] (&output_data);
+ if (r < 0)
+ goto not;
+ if (r > 0)
+ goto enomem;
+
+ string_end_idx = bufcnt;
+ }
+ else if (prec == 2 && instrtab[cnt].fct2 != 0)
+ {
+ /* Second parameter. */
+ if (instrtab[cnt].str2 != 0)
+ ADD_STRING (op2_str
+ + op2_str_idx[instrtab[cnt].str2 - 1]);
+
+ output_data.opoff1 = (instrtab[cnt].off2_1
+ + OFF2_1_BIAS - opoff);
+ output_data.opoff2 = (instrtab[cnt].off2_2
+ + OFF2_2_BIAS - opoff);
+ output_data.opoff3 = (instrtab[cnt].off2_3
+ + OFF2_3_BIAS - opoff);
+ int r = op2_fct[instrtab[cnt].fct2] (&output_data);
+ if (r < 0)
+ goto not;
+ if (r > 0)
+ goto enomem;
+
+ string_end_idx = bufcnt;
+ }
+ else if (prec == 3 && instrtab[cnt].fct3 != 0)
+ {
+ /* Third parameter. */
+ if (instrtab[cnt].str3 != 0)
+ ADD_STRING (op3_str
+ + op3_str_idx[instrtab[cnt].str3 - 1]);
+
+ output_data.opoff1 = (instrtab[cnt].off3_1
+ + OFF3_1_BIAS - opoff);
+ output_data.opoff2 = (instrtab[cnt].off3_2
+ + OFF3_2_BIAS - opoff);
+#ifdef OFF3_3_BITS
+ output_data.opoff3 = (instrtab[cnt].off3_3
+ + OFF3_3_BIAS - opoff);
+#else
+ output_data.opoff3 = 0;
+#endif
+ int r = op3_fct[instrtab[cnt].fct3] (&output_data);
+ if (r < 0)
+ goto not;
+ if (r > 0)
+ goto enomem;
+
+ string_end_idx = bufcnt;
+ }
+ else
+ bufcnt = string_end_idx;
+ break;
+
+ case 'e':
+ string_end_idx = bufcnt;
+ break;
+
+ case 'a':
+ /* Pad to requested column. */
+ while (bufcnt < (size_t) width)
+ ADD_CHAR (' ');
+ width = 0;
+ break;
+
+ case 'l':
+ if (output_data.labelbuf != NULL
+ && output_data.labelbuf[0] != '\0')
+ {
+ ADD_STRING (output_data.labelbuf);
+ output_data.labelbuf[0] = '\0';
+ string_end_idx = bufcnt;
+ }
+ else if (output_data.symaddr_use != addr_none)
+ {
+ GElf_Addr symaddr = output_data.symaddr;
+ if (output_data.symaddr_use >= addr_rel_symbolic)
+ symaddr += addr + param_start - begin;
+
+ // XXX Lookup symbol based on symaddr
+ const char *symstr = NULL;
+ if (symcb != NULL
+ && symcb (0 /* XXX */, 0 /* XXX */, symaddr,
+ &output_data.labelbuf,
+ &output_data.labelbufsize, symcbarg) == 0)
+ symstr = output_data.labelbuf;
+
+ size_t bufavail = bufsize - bufcnt;
+ int r = 0;
+ if (symstr != NULL)
+ r = snprintf (&buf[bufcnt], bufavail, "# <%s>",
+ symstr);
+ else if (output_data.symaddr_use == addr_abs_always
+ || output_data.symaddr_use == addr_rel_always)
+ r = snprintf (&buf[bufcnt], bufavail, "# %#" PRIx64,
+ (uint64_t) symaddr);
+
+ assert (r >= 0);
+ if ((size_t) r >= bufavail)
+ goto enomem;
+ bufcnt += r;
+ string_end_idx = bufcnt;
+
+ output_data.symaddr_use = addr_none;
+ }
+ break;
+ }
+
+ /* Pad according to the specified width. */
+ while (bufcnt + prefix_size < start_idx + width)
+ ADD_CHAR (' ');
+ prefix_size = 0;
+ }
+
+ if ((prefixes & SEGMENT_PREFIXES) != 0)
+ goto print_prefix;
+
+ assert (string_end_idx != ~0ul);
+ bufcnt = string_end_idx;
+
+ addr += param_start - begin;
+ data = param_start;
+
+ goto out;
+ }
+
+ /* Invalid (or at least unhandled) opcode. */
+ if (prefixes != 0)
+ goto print_prefix;
+ assert (*startp == data);
+ ++data;
+ ADD_STRING ("(bad)");
+ addr += data - begin;
+
+ out:
+ if (bufcnt == bufsize)
+ goto enomem;
+ buf[bufcnt] = '\0';
+
+ *startp = data;
+ retval = outcb (buf, bufcnt, outcbarg);
+ if (retval != 0)
+ goto do_ret;
+ }
+
+ do_ret:
+ free (output_data.labelbuf);
+ if (buf != initbuf)
+ free (buf);
+
+ return retval;
+}
diff --git a/libcpu/i386_gendis.c b/libcpu/i386_gendis.c
new file mode 100644
index 0000000..a8570f1
--- /dev/null
+++ b/libcpu/i386_gendis.c
@@ -0,0 +1,69 @@
+/* Generate tables for x86 disassembler.
+ Copyright (C) 2007, 2008 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2007.
+
+ Red Hat elfutils 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; version 2 of the License.
+
+ Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <error.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+extern int i386_parse (void);
+
+
+extern FILE *i386_in;
+extern int i386_debug;
+char *infname;
+
+FILE *outfile;
+
+int
+main (int argc, char *argv[argc])
+{
+ outfile = stdout;
+
+ if (argc == 1)
+ error (EXIT_FAILURE, 0, "usage: %s <MNEDEFFILE>", argv[0]);
+
+ //i386_debug = 1;
+ infname = argv[1];
+ if (strcmp (infname, "-") == 0)
+ i386_in = stdin;
+ else
+ {
+ i386_in = fopen (infname, "r");
+ if (i386_in == NULL)
+ error (EXIT_FAILURE, errno, "cannot open %s", argv[1]);
+ }
+
+ i386_parse ();
+
+ return error_message_count != 0;
+}
diff --git a/libcpu/i386_lex.c b/libcpu/i386_lex.c
new file mode 100644
index 0000000..a4540b9
--- /dev/null
+++ b/libcpu/i386_lex.c
@@ -0,0 +1,2011 @@
+
+#line 3 "i386_lex.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer i386__create_buffer
+#define yy_delete_buffer i386__delete_buffer
+#define yy_flex_debug i386__flex_debug
+#define yy_init_buffer i386__init_buffer
+#define yy_flush_buffer i386__flush_buffer
+#define yy_load_buffer_state i386__load_buffer_state
+#define yy_switch_to_buffer i386__switch_to_buffer
+#define yyin i386_in
+#define yyleng i386_leng
+#define yylex i386_lex
+#define yylineno i386_lineno
+#define yyout i386_out
+#define yyrestart i386_restart
+#define yytext i386_text
+#define yywrap i386_wrap
+#define yyalloc i386_alloc
+#define yyrealloc i386_realloc
+#define yyfree i386_free
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE i386_restart(i386_in )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int i386_leng;
+
+extern FILE *i386_in, *i386_out;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+ * access to the local variable yy_act. Since yyless() is a macro, it would break
+ * existing scanners that call yyless() from OUTSIDE i386_lex.
+ * One obvious solution it to make yy_act a global. I tried that, and saw
+ * a 5% performance hit in a non-i386_lineno scanner, because yy_act is
+ * normally declared as a register variable-- so it is not worth it.
+ */
+ #define YY_LESS_LINENO(n) \
+ do { \
+ int yyl;\
+ for ( yyl = n; yyl < i386_leng; ++yyl )\
+ if ( i386_text[yyl] == '\n' )\
+ --i386_lineno;\
+ }while(0)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up i386_text. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up i386_text again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr) )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via i386_restart()), so that the user can continue scanning by
+ * just pointing i386_in at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when i386_text is formed. */
+static char yy_hold_char;
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+int i386_leng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow i386_wrap()'s to do buffer switches
+ * instead of setting up a fresh i386_in. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void i386_restart (FILE *input_file );
+void i386__switch_to_buffer (YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE i386__create_buffer (FILE *file,int size );
+void i386__delete_buffer (YY_BUFFER_STATE b );
+void i386__flush_buffer (YY_BUFFER_STATE b );
+void i386_push_buffer_state (YY_BUFFER_STATE new_buffer );
+void i386_pop_buffer_state (void );
+
+static void i386_ensure_buffer_stack (void );
+static void i386__load_buffer_state (void );
+static void i386__init_buffer (YY_BUFFER_STATE b,FILE *file );
+
+#define YY_FLUSH_BUFFER i386__flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE i386__scan_buffer (char *base,yy_size_t size );
+YY_BUFFER_STATE i386__scan_string (yyconst char *yy_str );
+YY_BUFFER_STATE i386__scan_bytes (yyconst char *bytes,int len );
+
+void *i386_alloc (yy_size_t );
+void *i386_realloc (void *,yy_size_t );
+void i386_free (void * );
+
+#define yy_new_buffer i386__create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ i386_ensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ i386__create_buffer(i386_in,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ i386_ensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ i386__create_buffer(i386_in,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define i386_wrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *i386_in = (FILE *) 0, *i386_out = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int i386_lineno;
+
+int i386_lineno = 1;
+
+extern char *i386_text;
+#define yytext_ptr i386_text
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[] );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up i386_text.
+ */
+#define YY_DO_BEFORE_ACTION \
+ (yytext_ptr) = yy_bp; \
+ i386_leng = (size_t) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+ (yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 21
+#define YY_END_OF_BUFFER 22
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[62] =
+ { 0,
+ 0, 0, 0, 0, 22, 20, 17, 15, 20, 5,
+ 20, 14, 16, 19, 18, 15, 12, 7, 8, 13,
+ 11, 11, 19, 14, 16, 17, 6, 0, 0, 0,
+ 5, 0, 9, 18, 11, 11, 0, 0, 0, 0,
+ 11, 0, 0, 0, 0, 11, 1, 0, 0, 0,
+ 11, 0, 0, 0, 11, 2, 3, 0, 10, 4,
+ 0
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 1, 4, 1, 5, 1, 1, 1,
+ 1, 1, 1, 6, 1, 1, 7, 8, 9, 10,
+ 10, 10, 10, 10, 10, 10, 10, 11, 1, 1,
+ 1, 1, 1, 1, 12, 13, 13, 14, 13, 13,
+ 13, 13, 15, 13, 13, 16, 13, 17, 13, 13,
+ 13, 13, 13, 13, 13, 18, 13, 13, 13, 13,
+ 1, 1, 1, 1, 13, 1, 19, 13, 13, 13,
+
+ 20, 21, 13, 13, 22, 13, 23, 13, 24, 25,
+ 26, 27, 13, 28, 29, 13, 30, 13, 13, 31,
+ 32, 13, 33, 1, 34, 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, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[35] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 1, 3
+ } ;
+
+static yyconst flex_int16_t yy_base[65] =
+ { 0,
+ 0, 32, 65, 3, 113, 114, 9, 11, 19, 7,
+ 78, 16, 114, 114, 18, 20, 114, 114, 114, 114,
+ 0, 94, 76, 23, 114, 25, 114, 90, 80, 0,
+ 41, 73, 114, 36, 0, 88, 76, 44, 42, 37,
+ 49, 37, 38, 37, 31, 40, 114, 33, 32, 28,
+ 37, 16, 14, 12, 17, 114, 114, 5, 0, 114,
+ 114, 99, 101, 2
+ } ;
+
+static yyconst flex_int16_t yy_def[65] =
+ { 0,
+ 62, 62, 61, 3, 61, 61, 61, 61, 61, 61,
+ 63, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+ 64, 64, 63, 61, 61, 61, 61, 61, 61, 61,
+ 61, 63, 61, 61, 64, 64, 61, 61, 61, 61,
+ 64, 61, 61, 61, 61, 64, 61, 61, 61, 61,
+ 64, 61, 61, 61, 64, 61, 61, 61, 64, 61,
+ 0, 61, 61, 61
+ } ;
+
+static yyconst flex_int16_t yy_nxt[149] =
+ { 0,
+ 61, 7, 8, 35, 9, 24, 25, 10, 10, 10,
+ 26, 26, 26, 26, 31, 31, 31, 26, 26, 34,
+ 34, 34, 34, 27, 34, 34, 26, 26, 60, 39,
+ 59, 40, 11, 7, 12, 13, 9, 34, 34, 10,
+ 10, 10, 28, 58, 57, 29, 56, 30, 31, 31,
+ 31, 55, 54, 53, 52, 51, 50, 49, 48, 47,
+ 46, 45, 44, 43, 11, 14, 15, 16, 14, 14,
+ 17, 14, 18, 19, 14, 20, 21, 21, 21, 22,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 23, 14, 6,
+
+ 6, 6, 32, 32, 42, 41, 33, 38, 37, 33,
+ 36, 33, 61, 5, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 61, 61, 61, 61
+ } ;
+
+static yyconst flex_int16_t yy_chk[149] =
+ { 0,
+ 0, 1, 1, 64, 1, 4, 4, 1, 1, 1,
+ 7, 7, 8, 8, 10, 10, 10, 12, 12, 15,
+ 15, 16, 16, 9, 24, 24, 26, 26, 58, 30,
+ 55, 30, 1, 2, 2, 2, 2, 34, 34, 2,
+ 2, 2, 9, 54, 53, 9, 52, 9, 31, 31,
+ 31, 51, 50, 49, 48, 46, 45, 44, 43, 42,
+ 41, 40, 39, 38, 2, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 62,
+
+ 62, 62, 63, 63, 37, 36, 32, 29, 28, 23,
+ 22, 11, 5, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 61, 61, 61, 61
+ } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[22] =
+ { 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0,
+ 0, 0, };
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int i386__flex_debug;
+int i386__flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *i386_text;
+#line 1 "i386_lex.l"
+#line 2 "i386_lex.l"
+/* Copyright (C) 2004, 2005, 2007, 2008 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ Red Hat elfutils 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; version 2 of the License.
+
+ Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <error.h>
+#include <libintl.h>
+
+#include <system.h>
+#include "i386_parse.h"
+
+
+static void eat_to_eol (void);
+static void invalid_char (int ch);
+
+#line 581 "i386_lex.c"
+
+#define INITIAL 0
+#define MAIN 1
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int i386_lex_destroy (void );
+
+int i386_get_debug (void );
+
+void i386_set_debug (int debug_flag );
+
+YY_EXTRA_TYPE i386_get_extra (void );
+
+void i386_set_extra (YY_EXTRA_TYPE user_defined );
+
+FILE *i386_get_in (void );
+
+void i386_set_in (FILE * in_str );
+
+FILE *i386_get_out (void );
+
+void i386_set_out (FILE * out_str );
+
+int i386_get_leng (void );
+
+char *i386_get_text (void );
+
+int i386_get_lineno (void );
+
+void i386_set_lineno (int line_number );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int i386_wrap (void );
+#else
+extern int i386_wrap (void );
+#endif
+#endif
+
+ static void yyunput (int c,char *buf_ptr );
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( i386_text, i386_leng, 1, i386_out )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ unsigned n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( i386_in )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( i386_in ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, i386_in))==0 && ferror(i386_in)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(i386_in); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int i386_lex (void);
+
+#define YY_DECL int i386_lex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after i386_text and i386_leng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ if ( i386_leng > 0 ) \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+ (i386_text[i386_leng - 1] == '\n'); \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 54 "i386_lex.l"
+
+
+#line 770 "i386_lex.c"
+
+ if ( !(yy_init) )
+ {
+ (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
+
+ if ( ! i386_in )
+ i386_in = stdin;
+
+ if ( ! i386_out )
+ i386_out = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ i386_ensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ i386__create_buffer(i386_in,YY_BUF_SIZE );
+ }
+
+ i386__load_buffer_state( );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = (yy_c_buf_p);
+
+ /* Support of i386_text. */
+ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = (yy_start);
+ yy_current_state += YY_AT_BOL();
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 62 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_current_state != 61 );
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+
+ YY_DO_BEFORE_ACTION;
+
+ if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+ {
+ int yyl;
+ for ( yyl = 0; yyl < i386_leng; ++yyl )
+ if ( i386_text[yyl] == '\n' )
+
+ i386_lineno++;
+;
+ }
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = (yy_hold_char);
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 56 "i386_lex.l"
+{ return kMASK; }
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 58 "i386_lex.l"
+{ return kPREFIX; }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 59 "i386_lex.l"
+{ return kSUFFIX; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 61 "i386_lex.l"
+{ return kSYNONYM; }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 63 "i386_lex.l"
+{ i386_lval.num = strtoul (i386_text, NULL, 10);
+ return kNUMBER; }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 66 "i386_lex.l"
+{ BEGIN (MAIN); return kPERCPERC; }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 69 "i386_lex.l"
+{ return '0'; }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 70 "i386_lex.l"
+{ return '1'; }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 72 "i386_lex.l"
+{ i386_lval.str = xstrndup (i386_text + 1,
+ i386_leng - 2);
+ return kBITFIELD; }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 76 "i386_lex.l"
+{ i386_lval.str = (void *) -1l;
+ return kID; }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 79 "i386_lex.l"
+{ i386_lval.str = xstrndup (i386_text, i386_leng);
+ return kID; }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 82 "i386_lex.l"
+{ return ','; }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 84 "i386_lex.l"
+{ return ':'; }
+ YY_BREAK
+case 14:
+/* rule 14 can match eol */
+YY_RULE_SETUP
+#line 86 "i386_lex.l"
+{ /* IGNORE */ }
+ YY_BREAK
+case 15:
+/* rule 15 can match eol */
+YY_RULE_SETUP
+#line 88 "i386_lex.l"
+{ return '\n'; }
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 90 "i386_lex.l"
+{ eat_to_eol (); }
+ YY_BREAK
+case 17:
+/* rule 17 can match eol */
+YY_RULE_SETUP
+#line 92 "i386_lex.l"
+{ /* IGNORE */ }
+ YY_BREAK
+case 18:
+/* rule 18 can match eol */
+YY_RULE_SETUP
+#line 94 "i386_lex.l"
+{ return kSPACE; }
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 96 "i386_lex.l"
+{ i386_lval.ch = *i386_text; return kCHAR; }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 98 "i386_lex.l"
+{ invalid_char (*i386_text); }
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 101 "i386_lex.l"
+ECHO;
+ YY_BREAK
+#line 974 "i386_lex.c"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(MAIN):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed i386_in at a new source and called
+ * i386_lex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = i386_in;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ (yy_did_buffer_switch_on_eof) = 0;
+
+ if ( i386_wrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * i386_text, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of i386_lex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = (yytext_ptr);
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ i386_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ i386_restart(i386_in );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) i386_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (void)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = (yy_start);
+ yy_current_state += YY_AT_BOL();
+
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 62 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+{
+ register int yy_is_jam;
+ register char *yy_cp = (yy_c_buf_p);
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 62 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 61);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+ static void yyunput (int c, register char * yy_bp )
+{
+ register char *yy_cp;
+
+ yy_cp = (yy_c_buf_p);
+
+ /* undo effects of setting up i386_text */
+ *yy_cp = (yy_hold_char);
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = (yy_n_chars) + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ register char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ if ( c == '\n' ){
+ --i386_lineno;
+ }
+
+ (yytext_ptr) = yy_bp;
+ (yy_hold_char) = *yy_cp;
+ (yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (void)
+#else
+ static int input (void)
+#endif
+
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
+
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+ int offset = (yy_c_buf_p) - (yytext_ptr);
+ ++(yy_c_buf_p);
+
+ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ i386_restart(i386_in );
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( i386_wrap( ) )
+ return EOF;
+
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve i386_text */
+ (yy_hold_char) = *++(yy_c_buf_p);
+
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_at_bol )
+
+ i386_lineno++;
+;
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void i386_restart (FILE * input_file )
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ i386_ensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ i386__create_buffer(i386_in,YY_BUF_SIZE );
+ }
+
+ i386__init_buffer(YY_CURRENT_BUFFER,input_file );
+ i386__load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+ void i386__switch_to_buffer (YY_BUFFER_STATE new_buffer )
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * i386_pop_buffer_state();
+ * i386_push_buffer_state(new_buffer);
+ */
+ i386_ensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ i386__load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (i386_wrap()) processing, but the only time this flag
+ * is looked at is after i386_wrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void i386__load_buffer_state (void)
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ i386_in = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE i386__create_buffer (FILE * file, int size )
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) i386_alloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in i386__create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) i386_alloc(b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in i386__create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ i386__init_buffer(b,file );
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with i386__create_buffer()
+ *
+ */
+ void i386__delete_buffer (YY_BUFFER_STATE b )
+{
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ i386_free((void *) b->yy_ch_buf );
+
+ i386_free((void *) b );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a i386_restart() or at EOF.
+ */
+ static void i386__init_buffer (YY_BUFFER_STATE b, FILE * file )
+
+{
+ int oerrno = errno;
+
+ i386__flush_buffer(b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then i386__init_buffer was _probably_
+ * called from i386_restart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+ void i386__flush_buffer (YY_BUFFER_STATE b )
+{
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ i386__load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+void i386_push_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+ if (new_buffer == NULL)
+ return;
+
+ i386_ensure_buffer_stack();
+
+ /* This block is copied from i386__switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from i386__switch_to_buffer. */
+ i386__load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+void i386_pop_buffer_state (void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ i386__delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ i386__load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void i386_ensure_buffer_stack (void)
+{
+ int num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ (yy_buffer_stack) = (struct yy_buffer_state**)i386_alloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in i386_ensure_buffer_stack()" );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)i386_realloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in i386_ensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE i386__scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) i386_alloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in i386__scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ i386__switch_to_buffer(b );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to i386_lex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * i386__scan_bytes() instead.
+ */
+YY_BUFFER_STATE i386__scan_string (yyconst char * yystr )
+{
+
+ return i386__scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to i386_lex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE i386__scan_bytes (yyconst char * yybytes, int _yybytes_len )
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) i386_alloc(n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in i386__scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = i386__scan_buffer(buf,n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in i386__scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up i386_text. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ i386_text[i386_leng] = (yy_hold_char); \
+ (yy_c_buf_p) = i386_text + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ i386_leng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ *
+ */
+int i386_get_lineno (void)
+{
+
+ return i386_lineno;
+}
+
+/** Get the input stream.
+ *
+ */
+FILE *i386_get_in (void)
+{
+ return i386_in;
+}
+
+/** Get the output stream.
+ *
+ */
+FILE *i386_get_out (void)
+{
+ return i386_out;
+}
+
+/** Get the length of the current token.
+ *
+ */
+int i386_get_leng (void)
+{
+ return i386_leng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *i386_get_text (void)
+{
+ return i386_text;
+}
+
+/** Set the current line number.
+ * @param line_number
+ *
+ */
+void i386_set_lineno (int line_number )
+{
+
+ i386_lineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ *
+ * @see i386__switch_to_buffer
+ */
+void i386_set_in (FILE * in_str )
+{
+ i386_in = in_str ;
+}
+
+void i386_set_out (FILE * out_str )
+{
+ i386_out = out_str ;
+}
+
+int i386_get_debug (void)
+{
+ return i386__flex_debug;
+}
+
+void i386_set_debug (int bdebug )
+{
+ i386__flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from i386_lex_destroy(), so don't allocate here.
+ */
+
+ /* We do not touch i386_lineno unless the option is enabled. */
+ i386_lineno = 1;
+
+ (yy_buffer_stack) = 0;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+ (yy_c_buf_p) = (char *) 0;
+ (yy_init) = 0;
+ (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ i386_in = stdin;
+ i386_out = stdout;
+#else
+ i386_in = (FILE *) 0;
+ i386_out = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * i386_lex_init()
+ */
+ return 0;
+}
+
+/* i386_lex_destroy is for both reentrant and non-reentrant scanners. */
+int i386_lex_destroy (void)
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ i386__delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ i386_pop_buffer_state();
+ }
+
+ /* Destroy the stack itself. */
+ i386_free((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * i386_lex() is called, initialization will occur. */
+ yy_init_globals( );
+
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *i386_alloc (yy_size_t size )
+{
+ return (void *) malloc( size );
+}
+
+void *i386_realloc (void * ptr, yy_size_t size )
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void i386_free (void * ptr )
+{
+ free( (char *) ptr ); /* see i386_realloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 101 "i386_lex.l"
+
+
+
+static void
+eat_to_eol (void)
+{
+ while (1)
+ {
+ int c = input ();
+
+ if (c == EOF || c == '\n')
+ break;
+ }
+}
+
+static void
+invalid_char (int ch)
+{
+ error (0, 0, (isascii (ch)
+ ? gettext ("invalid character '%c' at line %d; ignored")
+ : gettext ("invalid character '\\%o' at line %d; ignored")),
+ ch, i386_lineno);
+}
+
+// Local Variables:
+// mode: C
+// End:
+
diff --git a/libcpu/i386_lex.l b/libcpu/i386_lex.l
new file mode 100644
index 0000000..828c558
--- /dev/null
+++ b/libcpu/i386_lex.l
@@ -0,0 +1,126 @@
+%{
+/* Copyright (C) 2004, 2005, 2007, 2008 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ Red Hat elfutils 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; version 2 of the License.
+
+ Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <error.h>
+#include <libintl.h>
+
+#include <system.h>
+#include "i386_parse.h"
+
+
+static void eat_to_eol (void);
+static void invalid_char (int ch);
+%}
+
+ID [a-zA-Z_][a-zA-Z0-9_/]*
+ID2 [a-zA-Z0-9_:/]*
+NUMBER [0-9]+
+WHITE [[:space:]]+
+
+%option yylineno
+%option never-interactive
+%option noyywrap
+
+
+%x MAIN
+
+%%
+
+"%mask" { return kMASK; }
+
+"%prefix" { return kPREFIX; }
+"%suffix" { return kSUFFIX; }
+
+"%synonym" { return kSYNONYM; }
+
+{NUMBER} { i386_lval.num = strtoul (yytext, NULL, 10);
+ return kNUMBER; }
+
+"%%" { BEGIN (MAIN); return kPERCPERC; }
+
+
+<MAIN>"0" { return '0'; }
+<MAIN>"1" { return '1'; }
+
+<INITIAL,MAIN>"{"{ID2}"}" { i386_lval.str = xstrndup (yytext + 1,
+ yyleng - 2);
+ return kBITFIELD; }
+
+<MAIN>"INVALID" { i386_lval.str = (void *) -1l;
+ return kID; }
+
+<MAIN>{ID} { i386_lval.str = xstrndup (yytext, yyleng);
+ return kID; }
+
+<MAIN>"," { return ','; }
+
+<MAIN>":" { return ':'; }
+
+<INITIAL,MAIN>^"\n" { /* IGNORE */ }
+
+<INITIAL,MAIN>"\n" { return '\n'; }
+
+<INITIAL,MAIN>^"#" { eat_to_eol (); }
+
+{WHITE} { /* IGNORE */ }
+
+<MAIN>{WHITE} { return kSPACE; }
+
+<MAIN>. { i386_lval.ch = *yytext; return kCHAR; }
+
+. { invalid_char (*yytext); }
+
+
+%%
+
+static void
+eat_to_eol (void)
+{
+ while (1)
+ {
+ int c = input ();
+
+ if (c == EOF || c == '\n')
+ break;
+ }
+}
+
+static void
+invalid_char (int ch)
+{
+ error (0, 0, (isascii (ch)
+ ? gettext ("invalid character '%c' at line %d; ignored")
+ : gettext ("invalid character '\\%o' at line %d; ignored")),
+ ch, yylineno);
+}
+
+// Local Variables:
+// mode: C
+// End:
diff --git a/libcpu/i386_parse.c b/libcpu/i386_parse.c
new file mode 100644
index 0000000..68e957b
--- /dev/null
+++ b/libcpu/i386_parse.c
@@ -0,0 +1,3356 @@
+/* A Bison parser, made by GNU Bison 2.4.3. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2009, 2010 Free Software Foundation, Inc.
+
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.4.3"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+/* Substitute the variable and function names. */
+#define yyparse i386_parse
+#define yylex i386_lex
+#define yyerror i386_error
+#define yylval i386_lval
+#define yychar i386_char
+#define yydebug i386_debug
+#define yynerrs i386_nerrs
+
+
+/* Copy the first part of user declarations. */
+
+/* Line 189 of yacc.c */
+#line 1 "i386_parse.y"
+
+/* Parser for i386 CPU description.
+ Copyright (C) 2004, 2005, 2007, 2008, 2009 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ Red Hat elfutils 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; version 2 of the License.
+
+ Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <error.h>
+#include <inttypes.h>
+#include <libintl.h>
+#include <math.h>
+#include <obstack.h>
+#include <search.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+#include <system.h>
+
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+
+/* The error handler. */
+static void yyerror (const char *s);
+
+extern int yylex (void);
+extern int i386_lineno;
+extern char *infname;
+
+
+struct known_bitfield
+{
+ char *name;
+ unsigned long int bits;
+ int tmp;
+};
+
+
+struct bitvalue
+{
+ enum bittype { zeroone, field, failure } type;
+ union
+ {
+ unsigned int value;
+ struct known_bitfield *field;
+ };
+ struct bitvalue *next;
+};
+
+
+struct argname
+{
+ enum nametype { string, nfield } type;
+ union
+ {
+ char *str;
+ struct known_bitfield *field;
+ };
+ struct argname *next;
+};
+
+
+struct argument
+{
+ struct argname *name;
+ struct argument *next;
+};
+
+
+struct instruction
+{
+ /* The byte encoding. */
+ struct bitvalue *bytes;
+
+ /* Prefix possible. */
+ int repe;
+ int rep;
+
+ /* Mnemonic. */
+ char *mnemonic;
+
+ /* Suffix. */
+ enum { suffix_none = 0, suffix_w, suffix_w0, suffix_W, suffix_tttn,
+ suffix_w1, suffix_W1, suffix_D } suffix;
+
+ /* Flag set if modr/m is used. */
+ int modrm;
+
+ /* Operands. */
+ struct operand
+ {
+ char *fct;
+ char *str;
+ int off1;
+ int off2;
+ int off3;
+ } operands[3];
+
+ struct instruction *next;
+};
+
+
+struct synonym
+{
+ char *from;
+ char *to;
+};
+
+
+struct suffix
+{
+ char *name;
+ int idx;
+};
+
+
+struct argstring
+{
+ char *str;
+ int idx;
+ int off;
+};
+
+
+static struct known_bitfield ax_reg =
+ {
+ .name = "ax", .bits = 0, .tmp = 0
+ };
+
+static struct known_bitfield dx_reg =
+ {
+ .name = "dx", .bits = 0, .tmp = 0
+ };
+
+static struct known_bitfield di_reg =
+ {
+ .name = "es_di", .bits = 0, .tmp = 0
+ };
+
+static struct known_bitfield si_reg =
+ {
+ .name = "ds_si", .bits = 0, .tmp = 0
+ };
+
+static struct known_bitfield bx_reg =
+ {
+ .name = "ds_bx", .bits = 0, .tmp = 0
+ };
+
+
+static int bitfield_compare (const void *p1, const void *p2);
+static void new_bitfield (char *name, unsigned long int num);
+static void check_bits (struct bitvalue *value);
+static int check_duplicates (struct bitvalue *val);
+static int check_argsdef (struct bitvalue *bitval, struct argument *args);
+static int check_bitsused (struct bitvalue *bitval,
+ struct known_bitfield *suffix,
+ struct argument *args);
+static struct argname *combine (struct argname *name);
+static void fillin_arg (struct bitvalue *bytes, struct argname *name,
+ struct instruction *instr, int n);
+static void find_numbers (void);
+static int compare_syn (const void *p1, const void *p2);
+static int compare_suf (const void *p1, const void *p2);
+static void instrtable_out (void);
+#if 0
+static void create_mnemonic_table (void);
+#endif
+
+static void *bitfields;
+static struct instruction *instructions;
+static size_t ninstructions;
+static void *synonyms;
+static void *suffixes;
+static int nsuffixes;
+static void *mnemonics;
+size_t nmnemonics;
+extern FILE *outfile;
+
+/* Number of bits used mnemonics. */
+#if 0
+static size_t best_mnemonic_bits;
+#endif
+
+
+/* Line 189 of yacc.c */
+#line 294 "i386_parse.c"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ kMASK = 258,
+ kPREFIX = 259,
+ kSUFFIX = 260,
+ kSYNONYM = 261,
+ kID = 262,
+ kNUMBER = 263,
+ kPERCPERC = 264,
+ kBITFIELD = 265,
+ kCHAR = 266,
+ kSPACE = 267
+ };
+#endif
+/* Tokens. */
+#define kMASK 258
+#define kPREFIX 259
+#define kSUFFIX 260
+#define kSYNONYM 261
+#define kID 262
+#define kNUMBER 263
+#define kPERCPERC 264
+#define kBITFIELD 265
+#define kCHAR 266
+#define kSPACE 267
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 214 of yacc.c */
+#line 214 "i386_parse.y"
+
+ unsigned long int num;
+ char *str;
+ char ch;
+ struct known_bitfield *field;
+ struct bitvalue *bit;
+ struct argname *name;
+ struct argument *arg;
+
+
+
+/* Line 214 of yacc.c */
+#line 366 "i386_parse.c"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 264 of yacc.c */
+#line 378 "i386_parse.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 12
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 37
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 18
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 14
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 32
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 49
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 267
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 13, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 15, 2, 2, 2, 16, 17,
+ 2, 2, 2, 2, 2, 2, 2, 2, 14, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint8 yyprhs[] =
+{
+ 0, 0, 3, 8, 12, 14, 18, 21, 24, 28,
+ 29, 33, 35, 42, 43, 45, 46, 50, 52, 55,
+ 57, 59, 61, 63, 66, 67, 71, 73, 76, 78,
+ 80, 82, 84
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 19, 0, -1, 20, 9, 13, 22, -1, 20, 13,
+ 21, -1, 21, -1, 3, 10, 8, -1, 4, 10,
+ -1, 5, 10, -1, 6, 10, 10, -1, -1, 22,
+ 13, 23, -1, 23, -1, 25, 14, 24, 7, 24,
+ 28, -1, -1, 10, -1, -1, 25, 15, 26, -1,
+ 26, -1, 26, 27, -1, 27, -1, 16, -1, 17,
+ -1, 10, -1, 12, 29, -1, -1, 29, 15, 30,
+ -1, 30, -1, 30, 31, -1, 31, -1, 10, -1,
+ 11, -1, 7, -1, 14, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 244, 244, 254, 255, 258, 260, 262, 264, 276,
+ 279, 280, 283, 366, 369, 385, 388, 398, 405, 413,
+ 417, 424, 431, 453, 456, 459, 469, 477, 485, 488,
+ 520, 529, 536
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "kMASK", "kPREFIX", "kSUFFIX",
+ "kSYNONYM", "kID", "kNUMBER", "kPERCPERC", "kBITFIELD", "kCHAR",
+ "kSPACE", "'\\n'", "':'", "','", "'0'", "'1'", "$accept", "spec",
+ "masks", "mask", "instrs", "instr", "bitfieldopt", "bytes", "byte",
+ "bit", "optargs", "args", "arg", "argcomp", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 10, 58, 44, 48, 49
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 18, 19, 20, 20, 21, 21, 21, 21, 21,
+ 22, 22, 23, 23, 24, 24, 25, 25, 26, 26,
+ 27, 27, 27, 28, 28, 29, 29, 30, 30, 31,
+ 31, 31, 31
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 4, 3, 1, 3, 2, 2, 3, 0,
+ 3, 1, 6, 0, 1, 0, 3, 1, 2, 1,
+ 1, 1, 1, 2, 0, 3, 1, 2, 1, 1,
+ 1, 1, 1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 9, 0, 0, 0, 0, 0, 0, 4, 0, 6,
+ 7, 0, 1, 0, 9, 5, 8, 13, 3, 22,
+ 20, 21, 2, 11, 0, 17, 19, 13, 15, 0,
+ 18, 10, 14, 0, 16, 15, 24, 0, 12, 31,
+ 29, 30, 32, 23, 26, 28, 0, 27, 25
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
+{
+ -1, 5, 6, 7, 22, 23, 33, 24, 25, 26,
+ 38, 43, 44, 45
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -35
+static const yytype_int8 yypact[] =
+{
+ 12, 9, 10, 11, 13, 22, -2, -35, 16, -35,
+ -35, 15, -35, 14, 12, -35, -35, -4, -35, -35,
+ -35, -35, 17, -35, -12, -4, -35, -4, 18, -4,
+ -35, -35, -35, 19, -4, 18, 20, -6, -35, -35,
+ -35, -35, -35, 21, -6, -35, -6, -35, -6
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -35, -35, -35, 23, -35, 2, -1, -35, 4, -25,
+ -35, -35, -15, -34
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+ 30, 39, 28, 29, 40, 41, 19, 13, 42, 30,
+ 47, 14, 20, 21, 47, 1, 2, 3, 4, 8,
+ 9, 10, 12, 11, 15, 16, 35, 17, 32, 31,
+ 27, 48, 37, 34, 36, 0, 46, 18
+};
+
+static const yytype_int8 yycheck[] =
+{
+ 25, 7, 14, 15, 10, 11, 10, 9, 14, 34,
+ 44, 13, 16, 17, 48, 3, 4, 5, 6, 10,
+ 10, 10, 0, 10, 8, 10, 7, 13, 10, 27,
+ 13, 46, 12, 29, 35, -1, 15, 14
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 3, 4, 5, 6, 19, 20, 21, 10, 10,
+ 10, 10, 0, 9, 13, 8, 10, 13, 21, 10,
+ 16, 17, 22, 23, 25, 26, 27, 13, 14, 15,
+ 27, 23, 10, 24, 26, 7, 24, 12, 28, 7,
+ 10, 11, 14, 29, 30, 31, 15, 31, 30
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. However,
+ YYFAIL appears to be in use. Nevertheless, it is formally deprecated
+ in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+ discussed. */
+
+#define YYFAIL goto yyerrlab
+#if defined YYFAIL
+ /* This is here to suppress warnings from the GCC cpp's
+ -Wunused-macros. Normally we don't worry about that warning, but
+ some users do, and we want to make it easy for users to remove
+ YYFAIL uses, which will produce warnings from Bison 2.5. */
+#endif
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+ YYSTYPE *yyvsp;
+ int yyrule;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ YYUSE (yyvaluep);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+
+/* Line 1464 of yacc.c */
+#line 245 "i386_parse.y"
+ {
+ if (error_message_count != 0)
+ error (EXIT_FAILURE, 0,
+ "terminated due to previous error");
+
+ instrtable_out ();
+ }
+ break;
+
+ case 5:
+
+/* Line 1464 of yacc.c */
+#line 259 "i386_parse.y"
+ { new_bitfield ((yyvsp[(2) - (3)].str), (yyvsp[(3) - (3)].num)); }
+ break;
+
+ case 6:
+
+/* Line 1464 of yacc.c */
+#line 261 "i386_parse.y"
+ { new_bitfield ((yyvsp[(2) - (2)].str), -1); }
+ break;
+
+ case 7:
+
+/* Line 1464 of yacc.c */
+#line 263 "i386_parse.y"
+ { new_bitfield ((yyvsp[(2) - (2)].str), -2); }
+ break;
+
+ case 8:
+
+/* Line 1464 of yacc.c */
+#line 265 "i386_parse.y"
+ {
+ struct synonym *newp = xmalloc (sizeof (*newp));
+ newp->from = (yyvsp[(2) - (3)].str);
+ newp->to = (yyvsp[(3) - (3)].str);
+ if (tfind (newp, &synonyms, compare_syn) != NULL)
+ error (0, 0,
+ "%d: duplicate definition for synonym '%s'",
+ i386_lineno, (yyvsp[(2) - (3)].str));
+ else if (tsearch ( newp, &synonyms, compare_syn) == NULL)
+ error (EXIT_FAILURE, 0, "tsearch");
+ }
+ break;
+
+ case 12:
+
+/* Line 1464 of yacc.c */
+#line 284 "i386_parse.y"
+ {
+ if ((yyvsp[(3) - (6)].field) != NULL && strcmp ((yyvsp[(3) - (6)].field)->name, "RE") != 0
+ && strcmp ((yyvsp[(3) - (6)].field)->name, "R") != 0)
+ {
+ error (0, 0, "%d: only 'R' and 'RE' prefix allowed",
+ i386_lineno - 1);
+ }
+ if (check_duplicates ((yyvsp[(1) - (6)].bit)) == 0
+ && check_argsdef ((yyvsp[(1) - (6)].bit), (yyvsp[(6) - (6)].arg)) == 0
+ && check_bitsused ((yyvsp[(1) - (6)].bit), (yyvsp[(5) - (6)].field), (yyvsp[(6) - (6)].arg)) == 0)
+ {
+ struct instruction *newp = xcalloc (sizeof (*newp),
+ 1);
+ if ((yyvsp[(3) - (6)].field) != NULL)
+ {
+ if (strcmp ((yyvsp[(3) - (6)].field)->name, "RE") == 0)
+ newp->repe = 1;
+ else if (strcmp ((yyvsp[(3) - (6)].field)->name, "R") == 0)
+ newp->rep = 1;
+ }
+
+ newp->bytes = (yyvsp[(1) - (6)].bit);
+ newp->mnemonic = (yyvsp[(4) - (6)].str);
+ if (newp->mnemonic != (void *) -1l
+ && tfind ((yyvsp[(4) - (6)].str), &mnemonics,
+ (comparison_fn_t) strcmp) == NULL)
+ {
+ if (tsearch ((yyvsp[(4) - (6)].str), &mnemonics,
+ (comparison_fn_t) strcmp) == NULL)
+ error (EXIT_FAILURE, errno, "tsearch");
+ ++nmnemonics;
+ }
+
+ if ((yyvsp[(5) - (6)].field) != NULL)
+ {
+ if (strcmp ((yyvsp[(5) - (6)].field)->name, "w") == 0)
+ newp->suffix = suffix_w;
+ else if (strcmp ((yyvsp[(5) - (6)].field)->name, "w0") == 0)
+ newp->suffix = suffix_w0;
+ else if (strcmp ((yyvsp[(5) - (6)].field)->name, "tttn") == 0)
+ newp->suffix = suffix_tttn;
+ else if (strcmp ((yyvsp[(5) - (6)].field)->name, "w1") == 0)
+ newp->suffix = suffix_w1;
+ else if (strcmp ((yyvsp[(5) - (6)].field)->name, "W") == 0)
+ newp->suffix = suffix_W;
+ else if (strcmp ((yyvsp[(5) - (6)].field)->name, "W1") == 0)
+ newp->suffix = suffix_W1;
+ else if (strcmp ((yyvsp[(5) - (6)].field)->name, "D") == 0)
+ newp->suffix = suffix_D;
+ else
+ error (EXIT_FAILURE, 0,
+ "%s: %d: unknown suffix '%s'",
+ infname, i386_lineno - 1, (yyvsp[(5) - (6)].field)->name);
+
+ struct suffix search = { .name = (yyvsp[(5) - (6)].field)->name };
+ if (tfind (&search, &suffixes, compare_suf)
+ == NULL)
+ {
+ struct suffix *ns = xmalloc (sizeof (*ns));
+ ns->name = (yyvsp[(5) - (6)].field)->name;
+ ns->idx = ++nsuffixes;
+ if (tsearch (ns, &suffixes, compare_suf)
+ == NULL)
+ error (EXIT_FAILURE, errno, "tsearch");
+ }
+ }
+
+ struct argument *args = (yyvsp[(6) - (6)].arg);
+ int n = 0;
+ while (args != NULL)
+ {
+ fillin_arg ((yyvsp[(1) - (6)].bit), args->name, newp, n);
+
+ args = args->next;
+ ++n;
+ }
+
+ newp->next = instructions;
+ instructions = newp;
+ ++ninstructions;
+ }
+ }
+ break;
+
+ case 14:
+
+/* Line 1464 of yacc.c */
+#line 370 "i386_parse.y"
+ {
+ struct known_bitfield search;
+ search.name = (yyvsp[(1) - (1)].str);
+ struct known_bitfield **res;
+ res = tfind (&search, &bitfields, bitfield_compare);
+ if (res == NULL)
+ {
+ error (0, 0, "%d: unknown bitfield '%s'",
+ i386_lineno, search.name);
+ (yyval.field) = NULL;
+ }
+ else
+ (yyval.field) = *res;
+ }
+ break;
+
+ case 15:
+
+/* Line 1464 of yacc.c */
+#line 385 "i386_parse.y"
+ { (yyval.field) = NULL; }
+ break;
+
+ case 16:
+
+/* Line 1464 of yacc.c */
+#line 389 "i386_parse.y"
+ {
+ check_bits ((yyvsp[(3) - (3)].bit));
+
+ struct bitvalue *runp = (yyvsp[(1) - (3)].bit);
+ while (runp->next != NULL)
+ runp = runp->next;
+ runp->next = (yyvsp[(3) - (3)].bit);
+ (yyval.bit) = (yyvsp[(1) - (3)].bit);
+ }
+ break;
+
+ case 17:
+
+/* Line 1464 of yacc.c */
+#line 399 "i386_parse.y"
+ {
+ check_bits ((yyvsp[(1) - (1)].bit));
+ (yyval.bit) = (yyvsp[(1) - (1)].bit);
+ }
+ break;
+
+ case 18:
+
+/* Line 1464 of yacc.c */
+#line 406 "i386_parse.y"
+ {
+ struct bitvalue *runp = (yyvsp[(1) - (2)].bit);
+ while (runp->next != NULL)
+ runp = runp->next;
+ runp->next = (yyvsp[(2) - (2)].bit);
+ (yyval.bit) = (yyvsp[(1) - (2)].bit);
+ }
+ break;
+
+ case 19:
+
+/* Line 1464 of yacc.c */
+#line 414 "i386_parse.y"
+ { (yyval.bit) = (yyvsp[(1) - (1)].bit); }
+ break;
+
+ case 20:
+
+/* Line 1464 of yacc.c */
+#line 418 "i386_parse.y"
+ {
+ (yyval.bit) = xmalloc (sizeof (struct bitvalue));
+ (yyval.bit)->type = zeroone;
+ (yyval.bit)->value = 0;
+ (yyval.bit)->next = NULL;
+ }
+ break;
+
+ case 21:
+
+/* Line 1464 of yacc.c */
+#line 425 "i386_parse.y"
+ {
+ (yyval.bit) = xmalloc (sizeof (struct bitvalue));
+ (yyval.bit)->type = zeroone;
+ (yyval.bit)->value = 1;
+ (yyval.bit)->next = NULL;
+ }
+ break;
+
+ case 22:
+
+/* Line 1464 of yacc.c */
+#line 432 "i386_parse.y"
+ {
+ (yyval.bit) = xmalloc (sizeof (struct bitvalue));
+ struct known_bitfield search;
+ search.name = (yyvsp[(1) - (1)].str);
+ struct known_bitfield **res;
+ res = tfind (&search, &bitfields, bitfield_compare);
+ if (res == NULL)
+ {
+ error (0, 0, "%d: unknown bitfield '%s'",
+ i386_lineno, search.name);
+ (yyval.bit)->type = failure;
+ }
+ else
+ {
+ (yyval.bit)->type = field;
+ (yyval.bit)->field = *res;
+ }
+ (yyval.bit)->next = NULL;
+ }
+ break;
+
+ case 23:
+
+/* Line 1464 of yacc.c */
+#line 454 "i386_parse.y"
+ { (yyval.arg) = (yyvsp[(2) - (2)].arg); }
+ break;
+
+ case 24:
+
+/* Line 1464 of yacc.c */
+#line 456 "i386_parse.y"
+ { (yyval.arg) = NULL; }
+ break;
+
+ case 25:
+
+/* Line 1464 of yacc.c */
+#line 460 "i386_parse.y"
+ {
+ struct argument *runp = (yyvsp[(1) - (3)].arg);
+ while (runp->next != NULL)
+ runp = runp->next;
+ runp->next = xmalloc (sizeof (struct argument));
+ runp->next->name = combine ((yyvsp[(3) - (3)].name));
+ runp->next->next = NULL;
+ (yyval.arg) = (yyvsp[(1) - (3)].arg);
+ }
+ break;
+
+ case 26:
+
+/* Line 1464 of yacc.c */
+#line 470 "i386_parse.y"
+ {
+ (yyval.arg) = xmalloc (sizeof (struct argument));
+ (yyval.arg)->name = combine ((yyvsp[(1) - (1)].name));
+ (yyval.arg)->next = NULL;
+ }
+ break;
+
+ case 27:
+
+/* Line 1464 of yacc.c */
+#line 478 "i386_parse.y"
+ {
+ struct argname *runp = (yyvsp[(1) - (2)].name);
+ while (runp->next != NULL)
+ runp = runp->next;
+ runp->next = (yyvsp[(2) - (2)].name);
+ (yyval.name) = (yyvsp[(1) - (2)].name);
+ }
+ break;
+
+ case 28:
+
+/* Line 1464 of yacc.c */
+#line 486 "i386_parse.y"
+ { (yyval.name) = (yyvsp[(1) - (1)].name); }
+ break;
+
+ case 29:
+
+/* Line 1464 of yacc.c */
+#line 489 "i386_parse.y"
+ {
+ (yyval.name) = xmalloc (sizeof (struct argname));
+ (yyval.name)->type = nfield;
+ (yyval.name)->next = NULL;
+
+ struct known_bitfield search;
+ search.name = (yyvsp[(1) - (1)].str);
+ struct known_bitfield **res;
+ res = tfind (&search, &bitfields, bitfield_compare);
+ if (res == NULL)
+ {
+ if (strcmp ((yyvsp[(1) - (1)].str), "ax") == 0)
+ (yyval.name)->field = &ax_reg;
+ else if (strcmp ((yyvsp[(1) - (1)].str), "dx") == 0)
+ (yyval.name)->field = &dx_reg;
+ else if (strcmp ((yyvsp[(1) - (1)].str), "es_di") == 0)
+ (yyval.name)->field = &di_reg;
+ else if (strcmp ((yyvsp[(1) - (1)].str), "ds_si") == 0)
+ (yyval.name)->field = &si_reg;
+ else if (strcmp ((yyvsp[(1) - (1)].str), "ds_bx") == 0)
+ (yyval.name)->field = &bx_reg;
+ else
+ {
+ error (0, 0, "%d: unknown bitfield '%s'",
+ i386_lineno, search.name);
+ (yyval.name)->field = NULL;
+ }
+ }
+ else
+ (yyval.name)->field = *res;
+ }
+ break;
+
+ case 30:
+
+/* Line 1464 of yacc.c */
+#line 521 "i386_parse.y"
+ {
+ (yyval.name) = xmalloc (sizeof (struct argname));
+ (yyval.name)->type = string;
+ (yyval.name)->next = NULL;
+ (yyval.name)->str = xmalloc (2);
+ (yyval.name)->str[0] = (yyvsp[(1) - (1)].ch);
+ (yyval.name)->str[1] = '\0';
+ }
+ break;
+
+ case 31:
+
+/* Line 1464 of yacc.c */
+#line 530 "i386_parse.y"
+ {
+ (yyval.name) = xmalloc (sizeof (struct argname));
+ (yyval.name)->type = string;
+ (yyval.name)->next = NULL;
+ (yyval.name)->str = (yyvsp[(1) - (1)].str);
+ }
+ break;
+
+ case 32:
+
+/* Line 1464 of yacc.c */
+#line 537 "i386_parse.y"
+ {
+ (yyval.name) = xmalloc (sizeof (struct argname));
+ (yyval.name)->type = string;
+ (yyval.name)->next = NULL;
+ (yyval.name)->str = xmalloc (2);
+ (yyval.name)->str[0] = ':';
+ (yyval.name)->str[1] = '\0';
+ }
+ break;
+
+
+
+/* Line 1464 of yacc.c */
+#line 2006 "i386_parse.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ *++yyvsp = yylval;
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+
+/* Line 1684 of yacc.c */
+#line 547 "i386_parse.y"
+
+
+static void
+yyerror (const char *s)
+{
+ error (0, 0, gettext ("while reading i386 CPU description: %s at line %d"),
+ gettext (s), i386_lineno);
+}
+
+
+static int
+bitfield_compare (const void *p1, const void *p2)
+{
+ struct known_bitfield *f1 = (struct known_bitfield *) p1;
+ struct known_bitfield *f2 = (struct known_bitfield *) p2;
+
+ return strcmp (f1->name, f2->name);
+}
+
+
+static void
+new_bitfield (char *name, unsigned long int num)
+{
+ struct known_bitfield *newp = xmalloc (sizeof (struct known_bitfield));
+ newp->name = name;
+ newp->bits = num;
+ newp->tmp = 0;
+
+ if (tfind (newp, &bitfields, bitfield_compare) != NULL)
+ {
+ error (0, 0, "%d: duplicated definition of bitfield '%s'",
+ i386_lineno, name);
+ free (name);
+ return;
+ }
+
+ if (tsearch (newp, &bitfields, bitfield_compare) == NULL)
+ error (EXIT_FAILURE, errno, "%d: cannot insert new bitfield '%s'",
+ i386_lineno, name);
+}
+
+
+/* Check that the number of bits is a multiple of 8. */
+static void
+check_bits (struct bitvalue *val)
+{
+ struct bitvalue *runp = val;
+ unsigned int total = 0;
+
+ while (runp != NULL)
+ {
+ if (runp->type == zeroone)
+ ++total;
+ else if (runp->field == NULL)
+ /* No sense doing anything, the field is not known. */
+ return;
+ else
+ total += runp->field->bits;
+
+ runp = runp->next;
+ }
+
+ if (total % 8 != 0)
+ {
+ struct obstack os;
+ obstack_init (&os);
+
+ while (val != NULL)
+ {
+ if (val->type == zeroone)
+ obstack_printf (&os, "%u", val->value);
+ else
+ obstack_printf (&os, "{%s}", val->field->name);
+ val = val->next;
+ }
+ obstack_1grow (&os, '\0');
+
+ error (0, 0, "%d: field '%s' not a multiple of 8 bits in size",
+ i386_lineno, (char *) obstack_finish (&os));
+
+ obstack_free (&os, NULL);
+ }
+}
+
+
+static int
+check_duplicates (struct bitvalue *val)
+{
+ static int testcnt;
+ ++testcnt;
+
+ int result = 0;
+ while (val != NULL)
+ {
+ if (val->type == field && val->field != NULL)
+ {
+ if (val->field->tmp == testcnt)
+ {
+ error (0, 0, "%d: bitfield '%s' used more than once",
+ i386_lineno - 1, val->field->name);
+ result = 1;
+ }
+ val->field->tmp = testcnt;
+ }
+
+ val = val->next;
+ }
+
+ return result;
+}
+
+
+static int
+check_argsdef (struct bitvalue *bitval, struct argument *args)
+{
+ int result = 0;
+
+ while (args != NULL)
+ {
+ for (struct argname *name = args->name; name != NULL; name = name->next)
+ if (name->type == nfield && name->field != NULL
+ && name->field != &ax_reg && name->field != &dx_reg
+ && name->field != &di_reg && name->field != &si_reg
+ && name->field != &bx_reg)
+ {
+ struct bitvalue *runp = bitval;
+
+ while (runp != NULL)
+ if (runp->type == field && runp->field == name->field)
+ break;
+ else
+ runp = runp->next;
+
+ if (runp == NULL)
+ {
+ error (0, 0, "%d: unknown bitfield '%s' used in output format",
+ i386_lineno - 1, name->field->name);
+ result = 1;
+ }
+ }
+
+ args = args->next;
+ }
+
+ return result;
+}
+
+
+static int
+check_bitsused (struct bitvalue *bitval, struct known_bitfield *suffix,
+ struct argument *args)
+{
+ int result = 0;
+
+ while (bitval != NULL)
+ {
+ if (bitval->type == field && bitval->field != NULL
+ && bitval->field != suffix
+ /* {w} is handled special. */
+ && strcmp (bitval->field->name, "w") != 0)
+ {
+ struct argument *runp;
+ for (runp = args; runp != NULL; runp = runp->next)
+ {
+ struct argname *name = runp->name;
+
+ while (name != NULL)
+ if (name->type == nfield && name->field == bitval->field)
+ break;
+ else
+ name = name->next;
+
+ if (name != NULL)
+ break;
+ }
+
+#if 0
+ if (runp == NULL)
+ {
+ error (0, 0, "%d: bitfield '%s' not used",
+ i386_lineno - 1, bitval->field->name);
+ result = 1;
+ }
+#endif
+ }
+
+ bitval = bitval->next;
+ }
+
+ return result;
+}
+
+
+static struct argname *
+combine (struct argname *name)
+{
+ struct argname *last_str = NULL;
+ for (struct argname *runp = name; runp != NULL; runp = runp->next)
+ {
+ if (runp->type == string)
+ {
+ if (last_str == NULL)
+ last_str = runp;
+ else
+ {
+ last_str->str = xrealloc (last_str->str,
+ strlen (last_str->str)
+ + strlen (runp->str) + 1);
+ strcat (last_str->str, runp->str);
+ last_str->next = runp->next;
+ }
+ }
+ else
+ last_str = NULL;
+ }
+ return name;
+}
+
+
+#define obstack_grow_str(ob, str) obstack_grow (ob, str, strlen (str))
+
+
+static void
+fillin_arg (struct bitvalue *bytes, struct argname *name,
+ struct instruction *instr, int n)
+{
+ static struct obstack ob;
+ static int initialized;
+ if (! initialized)
+ {
+ initialized = 1;
+ obstack_init (&ob);
+ }
+
+ struct argname *runp = name;
+ int cnt = 0;
+ while (runp != NULL)
+ {
+ /* We ignore strings in the function name. */
+ if (runp->type == string)
+ {
+ if (instr->operands[n].str != NULL)
+ error (EXIT_FAILURE, 0,
+ "%d: cannot have more than one string parameter",
+ i386_lineno - 1);
+
+ instr->operands[n].str = runp->str;
+ }
+ else
+ {
+ assert (runp->type == nfield);
+
+ /* Construct the function name. */
+ if (cnt++ > 0)
+ obstack_1grow (&ob, '$');
+
+ if (runp->field == NULL)
+ /* Add some string which contains invalid characters. */
+ obstack_grow_str (&ob, "!!!INVALID!!!");
+ else
+ {
+ char *fieldname = runp->field->name;
+
+ struct synonym search = { .from = fieldname };
+
+ struct synonym **res = tfind (&search, &synonyms, compare_syn);
+ if (res != NULL)
+ fieldname = (*res)->to;
+
+ obstack_grow_str (&ob, fieldname);
+ }
+
+ /* Now compute the bit offset of the field. */
+ struct bitvalue *b = bytes;
+ int bitoff = 0;
+ if (runp->field != NULL)
+ while (b != NULL)
+ {
+ if (b->type == field && b->field != NULL)
+ {
+ if (strcmp (b->field->name, runp->field->name) == 0)
+ break;
+ bitoff += b->field->bits;
+ }
+ else
+ ++bitoff;
+
+ b = b->next;
+ }
+ if (instr->operands[n].off1 == 0)
+ instr->operands[n].off1 = bitoff;
+ else if (instr->operands[n].off2 == 0)
+ instr->operands[n].off2 = bitoff;
+ else if (instr->operands[n].off3 == 0)
+ instr->operands[n].off3 = bitoff;
+ else
+ error (EXIT_FAILURE, 0,
+ "%d: cannot have more than three fields in parameter",
+ i386_lineno - 1);
+
+ if (runp->field != NULL
+ && strncasecmp (runp->field->name, "mod", 3) == 0)
+ instr->modrm = 1;
+ }
+
+ runp = runp->next;
+ }
+ if (obstack_object_size (&ob) == 0)
+ obstack_grow_str (&ob, "string");
+ obstack_1grow (&ob, '\0');
+ char *fct = obstack_finish (&ob);
+
+ instr->operands[n].fct = fct;
+}
+
+
+#if 0
+static void
+nameout (const void *nodep, VISIT value, int level)
+{
+ if (value == leaf || value == postorder)
+ printf (" %s\n", *(const char **) nodep);
+}
+#endif
+
+
+static int
+compare_argstring (const void *p1, const void *p2)
+{
+ const struct argstring *a1 = (const struct argstring *) p1;
+ const struct argstring *a2 = (const struct argstring *) p2;
+
+ return strcmp (a1->str, a2->str);
+}
+
+
+static int maxoff[3][3];
+static int minoff[3][3] = { { 1000, 1000, 1000 },
+ { 1000, 1000, 1000 },
+ { 1000, 1000, 1000 } };
+static int nbitoff[3][3];
+static void *fct_names[3];
+static int nbitfct[3];
+static int nbitsuf;
+static void *strs[3];
+static int nbitstr[3];
+static int total_bits = 2; // Already counted the rep/repe bits.
+
+static void
+find_numbers (void)
+{
+ int nfct_names[3] = { 0, 0, 0 };
+ int nstrs[3] = { 0, 0, 0 };
+
+ /* We reverse the order of the instruction list while processing it.
+ Later phases need it in the order in which the input file has
+ them. */
+ struct instruction *reversed = NULL;
+
+ struct instruction *runp = instructions;
+ while (runp != NULL)
+ {
+ for (int i = 0; i < 3; ++i)
+ if (runp->operands[i].fct != NULL)
+ {
+ struct argstring search = { .str = runp->operands[i].fct };
+ if (tfind (&search, &fct_names[i], compare_argstring) == NULL)
+ {
+ struct argstring *newp = xmalloc (sizeof (*newp));
+ newp->str = runp->operands[i].fct;
+ newp->idx = 0;
+ if (tsearch (newp, &fct_names[i], compare_argstring) == NULL)
+ error (EXIT_FAILURE, errno, "tsearch");
+ ++nfct_names[i];
+ }
+
+ if (runp->operands[i].str != NULL)
+ {
+ search.str = runp->operands[i].str;
+ if (tfind (&search, &strs[i], compare_argstring) == NULL)
+ {
+ struct argstring *newp = xmalloc (sizeof (*newp));
+ newp->str = runp->operands[i].str;
+ newp->idx = 0;
+ if (tsearch (newp, &strs[i], compare_argstring) == NULL)
+ error (EXIT_FAILURE, errno, "tsearch");
+ ++nstrs[i];
+ }
+ }
+
+ maxoff[i][0] = MAX (maxoff[i][0], runp->operands[i].off1);
+ maxoff[i][1] = MAX (maxoff[i][1], runp->operands[i].off2);
+ maxoff[i][2] = MAX (maxoff[i][2], runp->operands[i].off3);
+
+ if (runp->operands[i].off1 > 0)
+ minoff[i][0] = MIN (minoff[i][0], runp->operands[i].off1);
+ if (runp->operands[i].off2 > 0)
+ minoff[i][1] = MIN (minoff[i][1], runp->operands[i].off2);
+ if (runp->operands[i].off3 > 0)
+ minoff[i][2] = MIN (minoff[i][2], runp->operands[i].off3);
+ }
+
+ struct instruction *old = runp;
+ runp = runp->next;
+
+ old->next = reversed;
+ reversed = old;
+ }
+ instructions = reversed;
+
+ int d;
+ int c;
+ for (int i = 0; i < 3; ++i)
+ {
+ // printf ("min1 = %d, min2 = %d, min3 = %d\n", minoff[i][0], minoff[i][1], minoff[i][2]);
+ // printf ("max1 = %d, max2 = %d, max3 = %d\n", maxoff[i][0], maxoff[i][1], maxoff[i][2]);
+
+ if (minoff[i][0] == 1000)
+ nbitoff[i][0] = 0;
+ else
+ {
+ nbitoff[i][0] = 1;
+ d = maxoff[i][0] - minoff[i][0];
+ c = 1;
+ while (c < d)
+ {
+ ++nbitoff[i][0];
+ c *= 2;
+ }
+ total_bits += nbitoff[i][0];
+ }
+
+ if (minoff[i][1] == 1000)
+ nbitoff[i][1] = 0;
+ else
+ {
+ nbitoff[i][1] = 1;
+ d = maxoff[i][1] - minoff[i][1];
+ c = 1;
+ while (c < d)
+ {
+ ++nbitoff[i][1];
+ c *= 2;
+ }
+ total_bits += nbitoff[i][1];
+ }
+
+ if (minoff[i][2] == 1000)
+ nbitoff[i][2] = 0;
+ else
+ {
+ nbitoff[i][2] = 1;
+ d = maxoff[i][2] - minoff[i][2];
+ c = 1;
+ while (c < d)
+ {
+ ++nbitoff[i][2];
+ c *= 2;
+ }
+ total_bits += nbitoff[i][2];
+ }
+ // printf ("off1 = %d, off2 = %d, off3 = %d\n", nbitoff[i][0], nbitoff[i][1], nbitoff[i][2]);
+
+ nbitfct[i] = 1;
+ d = nfct_names[i];
+ c = 1;
+ while (c < d)
+ {
+ ++nbitfct[i];
+ c *= 2;
+ }
+ total_bits += nbitfct[i];
+ // printf ("%d fct[%d], %d bits\n", nfct_names[i], i, nbitfct[i]);
+
+ if (nstrs[i] != 0)
+ {
+ nbitstr[i] = 1;
+ d = nstrs[i];
+ c = 1;
+ while (c < d)
+ {
+ ++nbitstr[i];
+ c *= 2;
+ }
+ total_bits += nbitstr[i];
+ }
+
+ // twalk (fct_names[i], nameout);
+ }
+
+ nbitsuf = 0;
+ d = nsuffixes;
+ c = 1;
+ while (c < d)
+ {
+ ++nbitsuf;
+ c *= 2;
+ }
+ total_bits += nbitsuf;
+ // printf ("%d suffixes, %d bits\n", nsuffixes, nbitsuf);
+}
+
+
+static int
+compare_syn (const void *p1, const void *p2)
+{
+ const struct synonym *s1 = (const struct synonym *) p1;
+ const struct synonym *s2 = (const struct synonym *) p2;
+
+ return strcmp (s1->from, s2->from);
+}
+
+
+static int
+compare_suf (const void *p1, const void *p2)
+{
+ const struct suffix *s1 = (const struct suffix *) p1;
+ const struct suffix *s2 = (const struct suffix *) p2;
+
+ return strcmp (s1->name, s2->name);
+}
+
+
+static int count_op_str;
+static int off_op_str;
+static void
+print_op_str (const void *nodep, VISIT value,
+ int level __attribute__ ((unused)))
+{
+ if (value == leaf || value == postorder)
+ {
+ const char *str = (*(struct argstring **) nodep)->str;
+ fprintf (outfile, "%s\n \"%s",
+ count_op_str == 0 ? "" : "\\0\"", str);
+ (*(struct argstring **) nodep)->idx = ++count_op_str;
+ (*(struct argstring **) nodep)->off = off_op_str;
+ off_op_str += strlen (str) + 1;
+ }
+}
+
+
+static void
+print_op_str_idx (const void *nodep, VISIT value,
+ int level __attribute__ ((unused)))
+{
+ if (value == leaf || value == postorder)
+ printf (" %d,\n", (*(struct argstring **) nodep)->off);
+}
+
+
+static void
+print_op_fct (const void *nodep, VISIT value,
+ int level __attribute__ ((unused)))
+{
+ if (value == leaf || value == postorder)
+ {
+ fprintf (outfile, " FCT_%s,\n", (*(struct argstring **) nodep)->str);
+ (*(struct argstring **) nodep)->idx = ++count_op_str;
+ }
+}
+
+
+#if NMNES < 2
+# error "bogus NMNES value"
+#endif
+
+static void
+instrtable_out (void)
+{
+ find_numbers ();
+
+#if 0
+ create_mnemonic_table ();
+
+ fprintf (outfile, "#define MNEMONIC_BITS %zu\n", best_mnemonic_bits);
+#else
+ fprintf (outfile, "#define MNEMONIC_BITS %ld\n",
+ lrint (ceil (log2 (NMNES))));
+#endif
+ fprintf (outfile, "#define SUFFIX_BITS %d\n", nbitsuf);
+ for (int i = 0; i < 3; ++i)
+ {
+ fprintf (outfile, "#define FCT%d_BITS %d\n", i + 1, nbitfct[i]);
+ if (nbitstr[i] != 0)
+ fprintf (outfile, "#define STR%d_BITS %d\n", i + 1, nbitstr[i]);
+ fprintf (outfile, "#define OFF%d_1_BITS %d\n", i + 1, nbitoff[i][0]);
+ fprintf (outfile, "#define OFF%d_1_BIAS %d\n", i + 1, minoff[i][0]);
+ if (nbitoff[i][1] != 0)
+ {
+ fprintf (outfile, "#define OFF%d_2_BITS %d\n", i + 1, nbitoff[i][1]);
+ fprintf (outfile, "#define OFF%d_2_BIAS %d\n", i + 1, minoff[i][1]);
+ }
+ if (nbitoff[i][2] != 0)
+ {
+ fprintf (outfile, "#define OFF%d_3_BITS %d\n", i + 1, nbitoff[i][2]);
+ fprintf (outfile, "#define OFF%d_3_BIAS %d\n", i + 1, minoff[i][2]);
+ }
+ }
+
+ fputs ("\n#include <i386_data.h>\n\n", outfile);
+
+
+#define APPEND(a, b) APPEND_ (a, b)
+#define APPEND_(a, b) a##b
+#define EMIT_SUFFIX(suf) \
+ fprintf (outfile, "#define suffix_%s %d\n", #suf, APPEND (suffix_, suf))
+ EMIT_SUFFIX (none);
+ EMIT_SUFFIX (w);
+ EMIT_SUFFIX (w0);
+ EMIT_SUFFIX (W);
+ EMIT_SUFFIX (tttn);
+ EMIT_SUFFIX (D);
+ EMIT_SUFFIX (w1);
+ EMIT_SUFFIX (W1);
+
+ fputc_unlocked ('\n', outfile);
+
+ for (int i = 0; i < 3; ++i)
+ {
+ /* Functions. */
+ count_op_str = 0;
+ fprintf (outfile, "static const opfct_t op%d_fct[] =\n{\n NULL,\n",
+ i + 1);
+ twalk (fct_names[i], print_op_fct);
+ fputs ("};\n", outfile);
+
+ /* The operand strings. */
+ if (nbitstr[i] != 0)
+ {
+ count_op_str = 0;
+ off_op_str = 0;
+ fprintf (outfile, "static const char op%d_str[] =", i + 1);
+ twalk (strs[i], print_op_str);
+ fputs ("\";\n", outfile);
+
+ fprintf (outfile, "static const uint8_t op%d_str_idx[] = {\n",
+ i + 1);
+ twalk (strs[i], print_op_str_idx);
+ fputs ("};\n", outfile);
+ }
+ }
+
+
+ fputs ("static const struct instr_enc instrtab[] =\n{\n", outfile);
+ struct instruction *instr;
+ for (instr = instructions; instr != NULL; instr = instr->next)
+ {
+ fputs (" {", outfile);
+ if (instr->mnemonic == (void *) -1l)
+ fputs (" .mnemonic = MNE_INVALID,", outfile);
+ else
+ fprintf (outfile, " .mnemonic = MNE_%s,", instr->mnemonic);
+ fprintf (outfile, " .rep = %d,", instr->rep);
+ fprintf (outfile, " .repe = %d,", instr->repe);
+ fprintf (outfile, " .suffix = %d,", instr->suffix);
+ fprintf (outfile, " .modrm = %d,", instr->modrm);
+
+ for (int i = 0; i < 3; ++i)
+ {
+ int idx = 0;
+ if (instr->operands[i].fct != NULL)
+ {
+ struct argstring search = { .str = instr->operands[i].fct };
+ struct argstring **res = tfind (&search, &fct_names[i],
+ compare_argstring);
+ assert (res != NULL);
+ idx = (*res)->idx;
+ }
+ fprintf (outfile, " .fct%d = %d,", i + 1, idx);
+
+ idx = 0;
+ if (instr->operands[i].str != NULL)
+ {
+ struct argstring search = { .str = instr->operands[i].str };
+ struct argstring **res = tfind (&search, &strs[i],
+ compare_argstring);
+ assert (res != NULL);
+ idx = (*res)->idx;
+ }
+ if (nbitstr[i] != 0)
+ fprintf (outfile, " .str%d = %d,", i + 1, idx);
+
+ fprintf (outfile, " .off%d_1 = %d,", i + 1,
+ MAX (0, instr->operands[i].off1 - minoff[i][0]));
+
+ if (nbitoff[i][1] != 0)
+ fprintf (outfile, " .off%d_2 = %d,", i + 1,
+ MAX (0, instr->operands[i].off2 - minoff[i][1]));
+
+ if (nbitoff[i][2] != 0)
+ fprintf (outfile, " .off%d_3 = %d,", i + 1,
+ MAX (0, instr->operands[i].off3 - minoff[i][2]));
+ }
+
+ fputs (" },\n", outfile);
+ }
+ fputs ("};\n", outfile);
+
+ fputs ("static const uint8_t match_data[] =\n{\n", outfile);
+ size_t cnt = 0;
+ for (instr = instructions; instr != NULL; instr = instr->next, ++cnt)
+ {
+ /* First count the number of bytes. */
+ size_t totalbits = 0;
+ size_t zerobits = 0;
+ bool leading_p = true;
+ size_t leadingbits = 0;
+ struct bitvalue *b = instr->bytes;
+ while (b != NULL)
+ {
+ if (b->type == zeroone)
+ {
+ ++totalbits;
+ zerobits = 0;
+ if (leading_p)
+ ++leadingbits;
+ }
+ else
+ {
+ totalbits += b->field->bits;
+ /* We must always count the mod/rm byte. */
+ if (strncasecmp (b->field->name, "mod", 3) == 0)
+ zerobits = 0;
+ else
+ zerobits += b->field->bits;
+ leading_p = false;
+ }
+ b = b->next;
+ }
+ size_t nbytes = (totalbits - zerobits + 7) / 8;
+ assert (nbytes > 0);
+ size_t leadingbytes = leadingbits / 8;
+
+ fprintf (outfile, " %#zx,", nbytes | (leadingbytes << 4));
+
+ /* Now create the mask and byte values. */
+ uint8_t byte = 0;
+ uint8_t mask = 0;
+ int nbits = 0;
+ b = instr->bytes;
+ while (b != NULL)
+ {
+ if (b->type == zeroone)
+ {
+ byte = (byte << 1) | b->value;
+ mask = (mask << 1) | 1;
+ if (++nbits == 8)
+ {
+ if (leadingbytes > 0)
+ {
+ assert (mask == 0xff);
+ fprintf (outfile, " %#" PRIx8 ",", byte);
+ --leadingbytes;
+ }
+ else
+ fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",",
+ mask, byte);
+ byte = mask = nbits = 0;
+ if (--nbytes == 0)
+ break;
+ }
+ }
+ else
+ {
+ assert (leadingbytes == 0);
+
+ unsigned long int remaining = b->field->bits;
+ while (nbits + remaining > 8)
+ {
+ fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",",
+ mask << (8 - nbits), byte << (8 - nbits));
+ remaining = nbits + remaining - 8;
+ byte = mask = nbits = 0;
+ if (--nbytes == 0)
+ break;
+ }
+ byte <<= remaining;
+ mask <<= remaining;
+ nbits += remaining;
+ if (nbits == 8)
+ {
+ fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",", mask, byte);
+ byte = mask = nbits = 0;
+ if (--nbytes == 0)
+ break;
+ }
+ }
+ b = b->next;
+ }
+
+ fputc_unlocked ('\n', outfile);
+ }
+ fputs ("};\n", outfile);
+}
+
+
+#if 0
+static size_t mnemonic_maxlen;
+static size_t mnemonic_minlen;
+static size_t
+which_chars (const char *str[], size_t nstr)
+{
+ char used_char[256];
+ memset (used_char, '\0', sizeof (used_char));
+ mnemonic_maxlen = 0;
+ mnemonic_minlen = 10000;
+ for (size_t cnt = 0; cnt < nstr; ++cnt)
+ {
+ const unsigned char *cp = (const unsigned char *) str[cnt];
+ mnemonic_maxlen = MAX (mnemonic_maxlen, strlen ((char *) cp));
+ mnemonic_minlen = MIN (mnemonic_minlen, strlen ((char *) cp));
+ do
+ used_char[*cp++] = 1;
+ while (*cp != '\0');
+ }
+ size_t nused_char = 0;
+ for (size_t cnt = 0; cnt < 256; ++cnt)
+ if (used_char[cnt] != 0)
+ ++nused_char;
+ return nused_char;
+}
+
+
+static const char **mnemonic_strs;
+static size_t nmnemonic_strs;
+static void
+add_mnemonics (const void *nodep, VISIT value,
+ int level __attribute__ ((unused)))
+{
+ if (value == leaf || value == postorder)
+ mnemonic_strs[nmnemonic_strs++] = *(const char **) nodep;
+}
+
+
+struct charfreq
+{
+ char ch;
+ int freq;
+};
+static struct charfreq pfxfreq[256];
+static struct charfreq sfxfreq[256];
+
+
+static int
+compare_freq (const void *p1, const void *p2)
+{
+ const struct charfreq *c1 = (const struct charfreq *) p1;
+ const struct charfreq *c2 = (const struct charfreq *) p2;
+
+ if (c1->freq > c2->freq)
+ return -1;
+ if (c1->freq < c2->freq)
+ return 1;
+ return 0;
+}
+
+
+static size_t
+compute_pfxfreq (const char *str[], size_t nstr)
+{
+ memset (pfxfreq, '\0', sizeof (pfxfreq));
+
+ for (size_t i = 0; i < nstr; ++i)
+ pfxfreq[i].ch = i;
+
+ for (size_t i = 0; i < nstr; ++i)
+ ++pfxfreq[*((const unsigned char *) str[i])].freq;
+
+ qsort (pfxfreq, 256, sizeof (struct charfreq), compare_freq);
+
+ size_t n = 0;
+ while (n < 256 && pfxfreq[n].freq != 0)
+ ++n;
+ return n;
+}
+
+
+struct strsnlen
+{
+ const char *str;
+ size_t len;
+};
+
+static size_t
+compute_sfxfreq (size_t nstr, struct strsnlen *strsnlen)
+{
+ memset (sfxfreq, '\0', sizeof (sfxfreq));
+
+ for (size_t i = 0; i < nstr; ++i)
+ sfxfreq[i].ch = i;
+
+ for (size_t i = 0; i < nstr; ++i)
+ ++sfxfreq[((const unsigned char *) strchrnul (strsnlen[i].str, '\0'))[-1]].freq;
+
+ qsort (sfxfreq, 256, sizeof (struct charfreq), compare_freq);
+
+ size_t n = 0;
+ while (n < 256 && sfxfreq[n].freq != 0)
+ ++n;
+ return n;
+}
+
+
+static void
+create_mnemonic_table (void)
+{
+ mnemonic_strs = xmalloc (nmnemonics * sizeof (char *));
+
+ twalk (mnemonics, add_mnemonics);
+
+ (void) which_chars (mnemonic_strs, nmnemonic_strs);
+
+ size_t best_so_far = 100000000;
+ char *best_prefix = NULL;
+ char *best_suffix = NULL;
+ char *best_table = NULL;
+ size_t best_table_size = 0;
+ size_t best_table_bits = 0;
+ size_t best_prefix_bits = 0;
+
+ /* We can precompute the prefix characters. */
+ size_t npfx_char = compute_pfxfreq (mnemonic_strs, nmnemonic_strs);
+
+ /* Compute best size for string representation including explicit NUL. */
+ for (size_t pfxbits = 0; (1u << pfxbits) < 2 * npfx_char; ++pfxbits)
+ {
+ char prefix[1 << pfxbits];
+ size_t i;
+ for (i = 0; i < (1u << pfxbits) - 1; ++i)
+ prefix[i] = pfxfreq[i].ch;
+ prefix[i] = '\0';
+
+ struct strsnlen strsnlen[nmnemonic_strs];
+
+ for (i = 0; i < nmnemonic_strs; ++i)
+ {
+ if (strchr (prefix, *mnemonic_strs[i]) != NULL)
+ strsnlen[i].str = mnemonic_strs[i] + 1;
+ else
+ strsnlen[i].str = mnemonic_strs[i];
+ strsnlen[i].len = strlen (strsnlen[i].str);
+ }
+
+ /* With the prefixes gone, try to combine strings. */
+ size_t nstrsnlen = 1;
+ for (i = 1; i < nmnemonic_strs; ++i)
+ {
+ size_t j;
+ for (j = 0; j < nstrsnlen; ++j)
+ if (strsnlen[i].len > strsnlen[j].len
+ && strcmp (strsnlen[j].str,
+ strsnlen[i].str + (strsnlen[i].len
+ - strsnlen[j].len)) == 0)
+ {
+ strsnlen[j] = strsnlen[i];
+ break;
+ }
+ else if (strsnlen[i].len < strsnlen[j].len
+ && strcmp (strsnlen[i].str,
+ strsnlen[j].str + (strsnlen[j].len
+ - strsnlen[i].len)) == 0)
+ break;
+;
+ if (j == nstrsnlen)
+ strsnlen[nstrsnlen++] = strsnlen[i];
+ }
+
+ size_t nsfx_char = compute_sfxfreq (nstrsnlen, strsnlen);
+
+ for (size_t sfxbits = 0; (1u << sfxbits) < 2 * nsfx_char; ++sfxbits)
+ {
+ char suffix[1 << sfxbits];
+
+ for (i = 0; i < (1u << sfxbits) - 1; ++i)
+ suffix[i] = sfxfreq[i].ch;
+ suffix[i] = '\0';
+
+ size_t newlen[nstrsnlen];
+
+ for (i = 0; i < nstrsnlen; ++i)
+ if (strchr (suffix, strsnlen[i].str[strsnlen[i].len - 1]) != NULL)
+ newlen[i] = strsnlen[i].len - 1;
+ else
+ newlen[i] = strsnlen[i].len;
+
+ char charused[256];
+ memset (charused, '\0', sizeof (charused));
+ size_t ncharused = 0;
+
+ const char *tablestr[nstrsnlen];
+ size_t ntablestr = 1;
+ tablestr[0] = strsnlen[0].str;
+ size_t table = newlen[0] + 1;
+ for (i = 1; i < nstrsnlen; ++i)
+ {
+ size_t j;
+ for (j = 0; j < ntablestr; ++j)
+ if (newlen[i] > newlen[j]
+ && memcmp (tablestr[j],
+ strsnlen[i].str + (newlen[i] - newlen[j]),
+ newlen[j]) == 0)
+ {
+ table += newlen[i] - newlen[j];
+ tablestr[j] = strsnlen[i].str;
+ newlen[j] = newlen[i];
+ break;
+ }
+ else if (newlen[i] < newlen[j]
+ && memcmp (strsnlen[i].str,
+ tablestr[j] + (newlen[j] - newlen[i]),
+ newlen[i]) == 0)
+ break;
+
+ if (j == ntablestr)
+ {
+ table += newlen[i] + 1;
+ tablestr[ntablestr] = strsnlen[i].str;
+ newlen[ntablestr] = newlen[i];
+
+ ++ntablestr;
+ }
+
+ for (size_t x = 0; x < newlen[j]; ++x)
+ if (charused[((const unsigned char *) tablestr[j])[x]]++ == 0)
+ ++ncharused;
+ }
+
+ size_t ncharused_bits = 0;
+ i = 1;
+ while (i < ncharused)
+ {
+ i *= 2;
+ ++ncharused_bits;
+ }
+
+ size_t table_bits = 0;
+ i = 1;
+ while (i < table)
+ {
+ i *= 2;
+ ++table_bits;
+ }
+
+ size_t mnemonic_bits = table_bits + pfxbits + sfxbits;
+ size_t new_total = (((table + 7) / 8) * ncharused_bits + ncharused
+ + (pfxbits == 0 ? 0 : (1 << pfxbits) - 1)
+ + (sfxbits == 0 ? 0 : (1 << sfxbits) - 1)
+ + (((total_bits + mnemonic_bits + 7) / 8)
+ * ninstructions));
+
+ if (new_total < best_so_far)
+ {
+ best_so_far = new_total;
+ best_mnemonic_bits = mnemonic_bits;
+
+ free (best_suffix);
+ best_suffix = xstrdup (suffix);
+
+ free (best_prefix);
+ best_prefix = xstrdup (prefix);
+ best_prefix_bits = pfxbits;
+
+ best_table_size = table;
+ best_table_bits = table_bits;
+ char *cp = best_table = xrealloc (best_table, table);
+ for (i = 0; i < ntablestr; ++i)
+ {
+ assert (cp + newlen[i] + 1 <= best_table + table);
+ cp = mempcpy (cp, tablestr[i], newlen[i]);
+ *cp++ = '\0';
+ }
+ assert (cp == best_table + table);
+ }
+ }
+ }
+
+ fputs ("static const char mnemonic_table[] =\n\"", outfile);
+ for (size_t i = 0; i < best_table_size; ++i)
+ {
+ if (((i + 1) % 60) == 0)
+ fputs ("\"\n\"", outfile);
+ if (!isascii (best_table[i]) || !isprint (best_table[i]))
+ fprintf (outfile, "\\%03o", best_table[i]);
+ else
+ fputc (best_table[i], outfile);
+ }
+ fputs ("\";\n", outfile);
+
+ if (best_prefix[0] != '\0')
+ fprintf (outfile,
+ "static const char prefix[%zu] = \"%s\";\n"
+ "#define PREFIXCHAR_BITS %zu\n",
+ strlen (best_prefix), best_prefix, best_prefix_bits);
+ else
+ fputs ("#define NO_PREFIX\n", outfile);
+
+ if (best_suffix[0] != '\0')
+ fprintf (outfile, "static const char suffix[%zu] = \"%s\";\n",
+ strlen (best_suffix), best_suffix);
+ else
+ fputs ("#define NO_SUFFIX\n", outfile);
+
+ for (size_t i = 0; i < nmnemonic_strs; ++i)
+ {
+ const char *mne = mnemonic_strs[i];
+
+ size_t pfxval = 0;
+ char *cp = strchr (best_prefix, *mne);
+ if (cp != NULL)
+ {
+ pfxval = 1 + (cp - best_prefix);
+ ++mne;
+ }
+
+ size_t l = strlen (mne);
+
+ size_t sfxval = 0;
+ cp = strchr (best_suffix, mne[l - 1]);
+ if (cp != NULL)
+ {
+ sfxval = 1 + (cp - best_suffix);
+ --l;
+ }
+
+ char *off = memmem (best_table, best_table_size, mne, l);
+ while (off[l] != '\0')
+ {
+ off = memmem (off + 1, best_table_size, mne, l);
+ assert (off != NULL);
+ }
+
+ fprintf (outfile, "#define MNE_%s %#zx\n",
+ mnemonic_strs[i],
+ (off - best_table)
+ + ((pfxval + (sfxval << best_prefix_bits)) << best_table_bits));
+ }
+}
+#endif
+
diff --git a/libcpu/i386_parse.h b/libcpu/i386_parse.h
new file mode 100644
index 0000000..6b5df63
--- /dev/null
+++ b/libcpu/i386_parse.h
@@ -0,0 +1,95 @@
+/* A Bison parser, made by GNU Bison 2.4.3. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2009, 2010 Free Software Foundation, Inc.
+
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ kMASK = 258,
+ kPREFIX = 259,
+ kSUFFIX = 260,
+ kSYNONYM = 261,
+ kID = 262,
+ kNUMBER = 263,
+ kPERCPERC = 264,
+ kBITFIELD = 265,
+ kCHAR = 266,
+ kSPACE = 267
+ };
+#endif
+/* Tokens. */
+#define kMASK 258
+#define kPREFIX 259
+#define kSUFFIX 260
+#define kSYNONYM 261
+#define kID 262
+#define kNUMBER 263
+#define kPERCPERC 264
+#define kBITFIELD 265
+#define kCHAR 266
+#define kSPACE 267
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 1685 of yacc.c */
+#line 214 "i386_parse.y"
+
+ unsigned long int num;
+ char *str;
+ char ch;
+ struct known_bitfield *field;
+ struct bitvalue *bit;
+ struct argname *name;
+ struct argument *arg;
+
+
+
+/* Line 1685 of yacc.c */
+#line 87 "i386_parse.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+extern YYSTYPE i386_lval;
+
+
diff --git a/libcpu/i386_parse.y b/libcpu/i386_parse.y
new file mode 100644
index 0000000..bea0e33
--- /dev/null
+++ b/libcpu/i386_parse.y
@@ -0,0 +1,1684 @@
+%{
+/* Parser for i386 CPU description.
+ Copyright (C) 2004, 2005, 2007, 2008, 2009 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ Red Hat elfutils 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; version 2 of the License.
+
+ Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <error.h>
+#include <inttypes.h>
+#include <libintl.h>
+#include <math.h>
+#include <obstack.h>
+#include <search.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+#include <system.h>
+
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+
+/* The error handler. */
+static void yyerror (const char *s);
+
+extern int yylex (void);
+extern int i386_lineno;
+extern char *infname;
+
+
+struct known_bitfield
+{
+ char *name;
+ unsigned long int bits;
+ int tmp;
+};
+
+
+struct bitvalue
+{
+ enum bittype { zeroone, field, failure } type;
+ union
+ {
+ unsigned int value;
+ struct known_bitfield *field;
+ };
+ struct bitvalue *next;
+};
+
+
+struct argname
+{
+ enum nametype { string, nfield } type;
+ union
+ {
+ char *str;
+ struct known_bitfield *field;
+ };
+ struct argname *next;
+};
+
+
+struct argument
+{
+ struct argname *name;
+ struct argument *next;
+};
+
+
+struct instruction
+{
+ /* The byte encoding. */
+ struct bitvalue *bytes;
+
+ /* Prefix possible. */
+ int repe;
+ int rep;
+
+ /* Mnemonic. */
+ char *mnemonic;
+
+ /* Suffix. */
+ enum { suffix_none = 0, suffix_w, suffix_w0, suffix_W, suffix_tttn,
+ suffix_w1, suffix_W1, suffix_D } suffix;
+
+ /* Flag set if modr/m is used. */
+ int modrm;
+
+ /* Operands. */
+ struct operand
+ {
+ char *fct;
+ char *str;
+ int off1;
+ int off2;
+ int off3;
+ } operands[3];
+
+ struct instruction *next;
+};
+
+
+struct synonym
+{
+ char *from;
+ char *to;
+};
+
+
+struct suffix
+{
+ char *name;
+ int idx;
+};
+
+
+struct argstring
+{
+ char *str;
+ int idx;
+ int off;
+};
+
+
+static struct known_bitfield ax_reg =
+ {
+ .name = "ax", .bits = 0, .tmp = 0
+ };
+
+static struct known_bitfield dx_reg =
+ {
+ .name = "dx", .bits = 0, .tmp = 0
+ };
+
+static struct known_bitfield di_reg =
+ {
+ .name = "es_di", .bits = 0, .tmp = 0
+ };
+
+static struct known_bitfield si_reg =
+ {
+ .name = "ds_si", .bits = 0, .tmp = 0
+ };
+
+static struct known_bitfield bx_reg =
+ {
+ .name = "ds_bx", .bits = 0, .tmp = 0
+ };
+
+
+static int bitfield_compare (const void *p1, const void *p2);
+static void new_bitfield (char *name, unsigned long int num);
+static void check_bits (struct bitvalue *value);
+static int check_duplicates (struct bitvalue *val);
+static int check_argsdef (struct bitvalue *bitval, struct argument *args);
+static int check_bitsused (struct bitvalue *bitval,
+ struct known_bitfield *suffix,
+ struct argument *args);
+static struct argname *combine (struct argname *name);
+static void fillin_arg (struct bitvalue *bytes, struct argname *name,
+ struct instruction *instr, int n);
+static void find_numbers (void);
+static int compare_syn (const void *p1, const void *p2);
+static int compare_suf (const void *p1, const void *p2);
+static void instrtable_out (void);
+#if 0
+static void create_mnemonic_table (void);
+#endif
+
+static void *bitfields;
+static struct instruction *instructions;
+static size_t ninstructions;
+static void *synonyms;
+static void *suffixes;
+static int nsuffixes;
+static void *mnemonics;
+size_t nmnemonics;
+extern FILE *outfile;
+
+/* Number of bits used mnemonics. */
+#if 0
+static size_t best_mnemonic_bits;
+#endif
+%}
+
+%union {
+ unsigned long int num;
+ char *str;
+ char ch;
+ struct known_bitfield *field;
+ struct bitvalue *bit;
+ struct argname *name;
+ struct argument *arg;
+}
+
+%token kMASK
+%token kPREFIX
+%token kSUFFIX
+%token kSYNONYM
+%token <str> kID
+%token <num> kNUMBER
+%token kPERCPERC
+%token <str> kBITFIELD
+%token <ch> kCHAR
+%token kSPACE
+
+%type <bit> bit byte bytes
+%type <field> bitfieldopt
+%type <name> argcomp arg
+%type <arg> args optargs
+
+%defines
+
+%%
+
+spec: masks kPERCPERC '\n' instrs
+ {
+ if (error_message_count != 0)
+ error (EXIT_FAILURE, 0,
+ "terminated due to previous error");
+
+ instrtable_out ();
+ }
+ ;
+
+masks: masks '\n' mask
+ | mask
+ ;
+
+mask: kMASK kBITFIELD kNUMBER
+ { new_bitfield ($2, $3); }
+ | kPREFIX kBITFIELD
+ { new_bitfield ($2, -1); }
+ | kSUFFIX kBITFIELD
+ { new_bitfield ($2, -2); }
+ | kSYNONYM kBITFIELD kBITFIELD
+ {
+ struct synonym *newp = xmalloc (sizeof (*newp));
+ newp->from = $2;
+ newp->to = $3;
+ if (tfind (newp, &synonyms, compare_syn) != NULL)
+ error (0, 0,
+ "%d: duplicate definition for synonym '%s'",
+ i386_lineno, $2);
+ else if (tsearch ( newp, &synonyms, compare_syn) == NULL)
+ error (EXIT_FAILURE, 0, "tsearch");
+ }
+ |
+ ;
+
+instrs: instrs '\n' instr
+ | instr
+ ;
+
+instr: bytes ':' bitfieldopt kID bitfieldopt optargs
+ {
+ if ($3 != NULL && strcmp ($3->name, "RE") != 0
+ && strcmp ($3->name, "R") != 0)
+ {
+ error (0, 0, "%d: only 'R' and 'RE' prefix allowed",
+ i386_lineno - 1);
+ }
+ if (check_duplicates ($1) == 0
+ && check_argsdef ($1, $6) == 0
+ && check_bitsused ($1, $5, $6) == 0)
+ {
+ struct instruction *newp = xcalloc (sizeof (*newp),
+ 1);
+ if ($3 != NULL)
+ {
+ if (strcmp ($3->name, "RE") == 0)
+ newp->repe = 1;
+ else if (strcmp ($3->name, "R") == 0)
+ newp->rep = 1;
+ }
+
+ newp->bytes = $1;
+ newp->mnemonic = $4;
+ if (newp->mnemonic != (void *) -1l
+ && tfind ($4, &mnemonics,
+ (comparison_fn_t) strcmp) == NULL)
+ {
+ if (tsearch ($4, &mnemonics,
+ (comparison_fn_t) strcmp) == NULL)
+ error (EXIT_FAILURE, errno, "tsearch");
+ ++nmnemonics;
+ }
+
+ if ($5 != NULL)
+ {
+ if (strcmp ($5->name, "w") == 0)
+ newp->suffix = suffix_w;
+ else if (strcmp ($5->name, "w0") == 0)
+ newp->suffix = suffix_w0;
+ else if (strcmp ($5->name, "tttn") == 0)
+ newp->suffix = suffix_tttn;
+ else if (strcmp ($5->name, "w1") == 0)
+ newp->suffix = suffix_w1;
+ else if (strcmp ($5->name, "W") == 0)
+ newp->suffix = suffix_W;
+ else if (strcmp ($5->name, "W1") == 0)
+ newp->suffix = suffix_W1;
+ else if (strcmp ($5->name, "D") == 0)
+ newp->suffix = suffix_D;
+ else
+ error (EXIT_FAILURE, 0,
+ "%s: %d: unknown suffix '%s'",
+ infname, i386_lineno - 1, $5->name);
+
+ struct suffix search = { .name = $5->name };
+ if (tfind (&search, &suffixes, compare_suf)
+ == NULL)
+ {
+ struct suffix *ns = xmalloc (sizeof (*ns));
+ ns->name = $5->name;
+ ns->idx = ++nsuffixes;
+ if (tsearch (ns, &suffixes, compare_suf)
+ == NULL)
+ error (EXIT_FAILURE, errno, "tsearch");
+ }
+ }
+
+ struct argument *args = $6;
+ int n = 0;
+ while (args != NULL)
+ {
+ fillin_arg ($1, args->name, newp, n);
+
+ args = args->next;
+ ++n;
+ }
+
+ newp->next = instructions;
+ instructions = newp;
+ ++ninstructions;
+ }
+ }
+ |
+ ;
+
+bitfieldopt: kBITFIELD
+ {
+ struct known_bitfield search;
+ search.name = $1;
+ struct known_bitfield **res;
+ res = tfind (&search, &bitfields, bitfield_compare);
+ if (res == NULL)
+ {
+ error (0, 0, "%d: unknown bitfield '%s'",
+ i386_lineno, search.name);
+ $$ = NULL;
+ }
+ else
+ $$ = *res;
+ }
+ |
+ { $$ = NULL; }
+ ;
+
+bytes: bytes ',' byte
+ {
+ check_bits ($3);
+
+ struct bitvalue *runp = $1;
+ while (runp->next != NULL)
+ runp = runp->next;
+ runp->next = $3;
+ $$ = $1;
+ }
+ | byte
+ {
+ check_bits ($1);
+ $$ = $1;
+ }
+ ;
+
+byte: byte bit
+ {
+ struct bitvalue *runp = $1;
+ while (runp->next != NULL)
+ runp = runp->next;
+ runp->next = $2;
+ $$ = $1;
+ }
+ | bit
+ { $$ = $1; }
+ ;
+
+bit: '0'
+ {
+ $$ = xmalloc (sizeof (struct bitvalue));
+ $$->type = zeroone;
+ $$->value = 0;
+ $$->next = NULL;
+ }
+ | '1'
+ {
+ $$ = xmalloc (sizeof (struct bitvalue));
+ $$->type = zeroone;
+ $$->value = 1;
+ $$->next = NULL;
+ }
+ | kBITFIELD
+ {
+ $$ = xmalloc (sizeof (struct bitvalue));
+ struct known_bitfield search;
+ search.name = $1;
+ struct known_bitfield **res;
+ res = tfind (&search, &bitfields, bitfield_compare);
+ if (res == NULL)
+ {
+ error (0, 0, "%d: unknown bitfield '%s'",
+ i386_lineno, search.name);
+ $$->type = failure;
+ }
+ else
+ {
+ $$->type = field;
+ $$->field = *res;
+ }
+ $$->next = NULL;
+ }
+ ;
+
+optargs: kSPACE args
+ { $$ = $2; }
+ |
+ { $$ = NULL; }
+ ;
+
+args: args ',' arg
+ {
+ struct argument *runp = $1;
+ while (runp->next != NULL)
+ runp = runp->next;
+ runp->next = xmalloc (sizeof (struct argument));
+ runp->next->name = combine ($3);
+ runp->next->next = NULL;
+ $$ = $1;
+ }
+ | arg
+ {
+ $$ = xmalloc (sizeof (struct argument));
+ $$->name = combine ($1);
+ $$->next = NULL;
+ }
+ ;
+
+arg: arg argcomp
+ {
+ struct argname *runp = $1;
+ while (runp->next != NULL)
+ runp = runp->next;
+ runp->next = $2;
+ $$ = $1;
+ }
+ | argcomp
+ { $$ = $1; }
+ ;
+argcomp: kBITFIELD
+ {
+ $$ = xmalloc (sizeof (struct argname));
+ $$->type = nfield;
+ $$->next = NULL;
+
+ struct known_bitfield search;
+ search.name = $1;
+ struct known_bitfield **res;
+ res = tfind (&search, &bitfields, bitfield_compare);
+ if (res == NULL)
+ {
+ if (strcmp ($1, "ax") == 0)
+ $$->field = &ax_reg;
+ else if (strcmp ($1, "dx") == 0)
+ $$->field = &dx_reg;
+ else if (strcmp ($1, "es_di") == 0)
+ $$->field = &di_reg;
+ else if (strcmp ($1, "ds_si") == 0)
+ $$->field = &si_reg;
+ else if (strcmp ($1, "ds_bx") == 0)
+ $$->field = &bx_reg;
+ else
+ {
+ error (0, 0, "%d: unknown bitfield '%s'",
+ i386_lineno, search.name);
+ $$->field = NULL;
+ }
+ }
+ else
+ $$->field = *res;
+ }
+ | kCHAR
+ {
+ $$ = xmalloc (sizeof (struct argname));
+ $$->type = string;
+ $$->next = NULL;
+ $$->str = xmalloc (2);
+ $$->str[0] = $1;
+ $$->str[1] = '\0';
+ }
+ | kID
+ {
+ $$ = xmalloc (sizeof (struct argname));
+ $$->type = string;
+ $$->next = NULL;
+ $$->str = $1;
+ }
+ | ':'
+ {
+ $$ = xmalloc (sizeof (struct argname));
+ $$->type = string;
+ $$->next = NULL;
+ $$->str = xmalloc (2);
+ $$->str[0] = ':';
+ $$->str[1] = '\0';
+ }
+ ;
+
+%%
+
+static void
+yyerror (const char *s)
+{
+ error (0, 0, gettext ("while reading i386 CPU description: %s at line %d"),
+ gettext (s), i386_lineno);
+}
+
+
+static int
+bitfield_compare (const void *p1, const void *p2)
+{
+ struct known_bitfield *f1 = (struct known_bitfield *) p1;
+ struct known_bitfield *f2 = (struct known_bitfield *) p2;
+
+ return strcmp (f1->name, f2->name);
+}
+
+
+static void
+new_bitfield (char *name, unsigned long int num)
+{
+ struct known_bitfield *newp = xmalloc (sizeof (struct known_bitfield));
+ newp->name = name;
+ newp->bits = num;
+ newp->tmp = 0;
+
+ if (tfind (newp, &bitfields, bitfield_compare) != NULL)
+ {
+ error (0, 0, "%d: duplicated definition of bitfield '%s'",
+ i386_lineno, name);
+ free (name);
+ return;
+ }
+
+ if (tsearch (newp, &bitfields, bitfield_compare) == NULL)
+ error (EXIT_FAILURE, errno, "%d: cannot insert new bitfield '%s'",
+ i386_lineno, name);
+}
+
+
+/* Check that the number of bits is a multiple of 8. */
+static void
+check_bits (struct bitvalue *val)
+{
+ struct bitvalue *runp = val;
+ unsigned int total = 0;
+
+ while (runp != NULL)
+ {
+ if (runp->type == zeroone)
+ ++total;
+ else if (runp->field == NULL)
+ /* No sense doing anything, the field is not known. */
+ return;
+ else
+ total += runp->field->bits;
+
+ runp = runp->next;
+ }
+
+ if (total % 8 != 0)
+ {
+ struct obstack os;
+ obstack_init (&os);
+
+ while (val != NULL)
+ {
+ if (val->type == zeroone)
+ obstack_printf (&os, "%u", val->value);
+ else
+ obstack_printf (&os, "{%s}", val->field->name);
+ val = val->next;
+ }
+ obstack_1grow (&os, '\0');
+
+ error (0, 0, "%d: field '%s' not a multiple of 8 bits in size",
+ i386_lineno, (char *) obstack_finish (&os));
+
+ obstack_free (&os, NULL);
+ }
+}
+
+
+static int
+check_duplicates (struct bitvalue *val)
+{
+ static int testcnt;
+ ++testcnt;
+
+ int result = 0;
+ while (val != NULL)
+ {
+ if (val->type == field && val->field != NULL)
+ {
+ if (val->field->tmp == testcnt)
+ {
+ error (0, 0, "%d: bitfield '%s' used more than once",
+ i386_lineno - 1, val->field->name);
+ result = 1;
+ }
+ val->field->tmp = testcnt;
+ }
+
+ val = val->next;
+ }
+
+ return result;
+}
+
+
+static int
+check_argsdef (struct bitvalue *bitval, struct argument *args)
+{
+ int result = 0;
+
+ while (args != NULL)
+ {
+ for (struct argname *name = args->name; name != NULL; name = name->next)
+ if (name->type == nfield && name->field != NULL
+ && name->field != &ax_reg && name->field != &dx_reg
+ && name->field != &di_reg && name->field != &si_reg
+ && name->field != &bx_reg)
+ {
+ struct bitvalue *runp = bitval;
+
+ while (runp != NULL)
+ if (runp->type == field && runp->field == name->field)
+ break;
+ else
+ runp = runp->next;
+
+ if (runp == NULL)
+ {
+ error (0, 0, "%d: unknown bitfield '%s' used in output format",
+ i386_lineno - 1, name->field->name);
+ result = 1;
+ }
+ }
+
+ args = args->next;
+ }
+
+ return result;
+}
+
+
+static int
+check_bitsused (struct bitvalue *bitval, struct known_bitfield *suffix,
+ struct argument *args)
+{
+ int result = 0;
+
+ while (bitval != NULL)
+ {
+ if (bitval->type == field && bitval->field != NULL
+ && bitval->field != suffix
+ /* {w} is handled special. */
+ && strcmp (bitval->field->name, "w") != 0)
+ {
+ struct argument *runp;
+ for (runp = args; runp != NULL; runp = runp->next)
+ {
+ struct argname *name = runp->name;
+
+ while (name != NULL)
+ if (name->type == nfield && name->field == bitval->field)
+ break;
+ else
+ name = name->next;
+
+ if (name != NULL)
+ break;
+ }
+
+#if 0
+ if (runp == NULL)
+ {
+ error (0, 0, "%d: bitfield '%s' not used",
+ i386_lineno - 1, bitval->field->name);
+ result = 1;
+ }
+#endif
+ }
+
+ bitval = bitval->next;
+ }
+
+ return result;
+}
+
+
+static struct argname *
+combine (struct argname *name)
+{
+ struct argname *last_str = NULL;
+ for (struct argname *runp = name; runp != NULL; runp = runp->next)
+ {
+ if (runp->type == string)
+ {
+ if (last_str == NULL)
+ last_str = runp;
+ else
+ {
+ last_str->str = xrealloc (last_str->str,
+ strlen (last_str->str)
+ + strlen (runp->str) + 1);
+ strcat (last_str->str, runp->str);
+ last_str->next = runp->next;
+ }
+ }
+ else
+ last_str = NULL;
+ }
+ return name;
+}
+
+
+#define obstack_grow_str(ob, str) obstack_grow (ob, str, strlen (str))
+
+
+static void
+fillin_arg (struct bitvalue *bytes, struct argname *name,
+ struct instruction *instr, int n)
+{
+ static struct obstack ob;
+ static int initialized;
+ if (! initialized)
+ {
+ initialized = 1;
+ obstack_init (&ob);
+ }
+
+ struct argname *runp = name;
+ int cnt = 0;
+ while (runp != NULL)
+ {
+ /* We ignore strings in the function name. */
+ if (runp->type == string)
+ {
+ if (instr->operands[n].str != NULL)
+ error (EXIT_FAILURE, 0,
+ "%d: cannot have more than one string parameter",
+ i386_lineno - 1);
+
+ instr->operands[n].str = runp->str;
+ }
+ else
+ {
+ assert (runp->type == nfield);
+
+ /* Construct the function name. */
+ if (cnt++ > 0)
+ obstack_1grow (&ob, '$');
+
+ if (runp->field == NULL)
+ /* Add some string which contains invalid characters. */
+ obstack_grow_str (&ob, "!!!INVALID!!!");
+ else
+ {
+ char *fieldname = runp->field->name;
+
+ struct synonym search = { .from = fieldname };
+
+ struct synonym **res = tfind (&search, &synonyms, compare_syn);
+ if (res != NULL)
+ fieldname = (*res)->to;
+
+ obstack_grow_str (&ob, fieldname);
+ }
+
+ /* Now compute the bit offset of the field. */
+ struct bitvalue *b = bytes;
+ int bitoff = 0;
+ if (runp->field != NULL)
+ while (b != NULL)
+ {
+ if (b->type == field && b->field != NULL)
+ {
+ if (strcmp (b->field->name, runp->field->name) == 0)
+ break;
+ bitoff += b->field->bits;
+ }
+ else
+ ++bitoff;
+
+ b = b->next;
+ }
+ if (instr->operands[n].off1 == 0)
+ instr->operands[n].off1 = bitoff;
+ else if (instr->operands[n].off2 == 0)
+ instr->operands[n].off2 = bitoff;
+ else if (instr->operands[n].off3 == 0)
+ instr->operands[n].off3 = bitoff;
+ else
+ error (EXIT_FAILURE, 0,
+ "%d: cannot have more than three fields in parameter",
+ i386_lineno - 1);
+
+ if (runp->field != NULL
+ && strncasecmp (runp->field->name, "mod", 3) == 0)
+ instr->modrm = 1;
+ }
+
+ runp = runp->next;
+ }
+ if (obstack_object_size (&ob) == 0)
+ obstack_grow_str (&ob, "string");
+ obstack_1grow (&ob, '\0');
+ char *fct = obstack_finish (&ob);
+
+ instr->operands[n].fct = fct;
+}
+
+
+#if 0
+static void
+nameout (const void *nodep, VISIT value, int level)
+{
+ if (value == leaf || value == postorder)
+ printf (" %s\n", *(const char **) nodep);
+}
+#endif
+
+
+static int
+compare_argstring (const void *p1, const void *p2)
+{
+ const struct argstring *a1 = (const struct argstring *) p1;
+ const struct argstring *a2 = (const struct argstring *) p2;
+
+ return strcmp (a1->str, a2->str);
+}
+
+
+static int maxoff[3][3];
+static int minoff[3][3] = { { 1000, 1000, 1000 },
+ { 1000, 1000, 1000 },
+ { 1000, 1000, 1000 } };
+static int nbitoff[3][3];
+static void *fct_names[3];
+static int nbitfct[3];
+static int nbitsuf;
+static void *strs[3];
+static int nbitstr[3];
+static int total_bits = 2; // Already counted the rep/repe bits.
+
+static void
+find_numbers (void)
+{
+ int nfct_names[3] = { 0, 0, 0 };
+ int nstrs[3] = { 0, 0, 0 };
+
+ /* We reverse the order of the instruction list while processing it.
+ Later phases need it in the order in which the input file has
+ them. */
+ struct instruction *reversed = NULL;
+
+ struct instruction *runp = instructions;
+ while (runp != NULL)
+ {
+ for (int i = 0; i < 3; ++i)
+ if (runp->operands[i].fct != NULL)
+ {
+ struct argstring search = { .str = runp->operands[i].fct };
+ if (tfind (&search, &fct_names[i], compare_argstring) == NULL)
+ {
+ struct argstring *newp = xmalloc (sizeof (*newp));
+ newp->str = runp->operands[i].fct;
+ newp->idx = 0;
+ if (tsearch (newp, &fct_names[i], compare_argstring) == NULL)
+ error (EXIT_FAILURE, errno, "tsearch");
+ ++nfct_names[i];
+ }
+
+ if (runp->operands[i].str != NULL)
+ {
+ search.str = runp->operands[i].str;
+ if (tfind (&search, &strs[i], compare_argstring) == NULL)
+ {
+ struct argstring *newp = xmalloc (sizeof (*newp));
+ newp->str = runp->operands[i].str;
+ newp->idx = 0;
+ if (tsearch (newp, &strs[i], compare_argstring) == NULL)
+ error (EXIT_FAILURE, errno, "tsearch");
+ ++nstrs[i];
+ }
+ }
+
+ maxoff[i][0] = MAX (maxoff[i][0], runp->operands[i].off1);
+ maxoff[i][1] = MAX (maxoff[i][1], runp->operands[i].off2);
+ maxoff[i][2] = MAX (maxoff[i][2], runp->operands[i].off3);
+
+ if (runp->operands[i].off1 > 0)
+ minoff[i][0] = MIN (minoff[i][0], runp->operands[i].off1);
+ if (runp->operands[i].off2 > 0)
+ minoff[i][1] = MIN (minoff[i][1], runp->operands[i].off2);
+ if (runp->operands[i].off3 > 0)
+ minoff[i][2] = MIN (minoff[i][2], runp->operands[i].off3);
+ }
+
+ struct instruction *old = runp;
+ runp = runp->next;
+
+ old->next = reversed;
+ reversed = old;
+ }
+ instructions = reversed;
+
+ int d;
+ int c;
+ for (int i = 0; i < 3; ++i)
+ {
+ // printf ("min1 = %d, min2 = %d, min3 = %d\n", minoff[i][0], minoff[i][1], minoff[i][2]);
+ // printf ("max1 = %d, max2 = %d, max3 = %d\n", maxoff[i][0], maxoff[i][1], maxoff[i][2]);
+
+ if (minoff[i][0] == 1000)
+ nbitoff[i][0] = 0;
+ else
+ {
+ nbitoff[i][0] = 1;
+ d = maxoff[i][0] - minoff[i][0];
+ c = 1;
+ while (c < d)
+ {
+ ++nbitoff[i][0];
+ c *= 2;
+ }
+ total_bits += nbitoff[i][0];
+ }
+
+ if (minoff[i][1] == 1000)
+ nbitoff[i][1] = 0;
+ else
+ {
+ nbitoff[i][1] = 1;
+ d = maxoff[i][1] - minoff[i][1];
+ c = 1;
+ while (c < d)
+ {
+ ++nbitoff[i][1];
+ c *= 2;
+ }
+ total_bits += nbitoff[i][1];
+ }
+
+ if (minoff[i][2] == 1000)
+ nbitoff[i][2] = 0;
+ else
+ {
+ nbitoff[i][2] = 1;
+ d = maxoff[i][2] - minoff[i][2];
+ c = 1;
+ while (c < d)
+ {
+ ++nbitoff[i][2];
+ c *= 2;
+ }
+ total_bits += nbitoff[i][2];
+ }
+ // printf ("off1 = %d, off2 = %d, off3 = %d\n", nbitoff[i][0], nbitoff[i][1], nbitoff[i][2]);
+
+ nbitfct[i] = 1;
+ d = nfct_names[i];
+ c = 1;
+ while (c < d)
+ {
+ ++nbitfct[i];
+ c *= 2;
+ }
+ total_bits += nbitfct[i];
+ // printf ("%d fct[%d], %d bits\n", nfct_names[i], i, nbitfct[i]);
+
+ if (nstrs[i] != 0)
+ {
+ nbitstr[i] = 1;
+ d = nstrs[i];
+ c = 1;
+ while (c < d)
+ {
+ ++nbitstr[i];
+ c *= 2;
+ }
+ total_bits += nbitstr[i];
+ }
+
+ // twalk (fct_names[i], nameout);
+ }
+
+ nbitsuf = 0;
+ d = nsuffixes;
+ c = 1;
+ while (c < d)
+ {
+ ++nbitsuf;
+ c *= 2;
+ }
+ total_bits += nbitsuf;
+ // printf ("%d suffixes, %d bits\n", nsuffixes, nbitsuf);
+}
+
+
+static int
+compare_syn (const void *p1, const void *p2)
+{
+ const struct synonym *s1 = (const struct synonym *) p1;
+ const struct synonym *s2 = (const struct synonym *) p2;
+
+ return strcmp (s1->from, s2->from);
+}
+
+
+static int
+compare_suf (const void *p1, const void *p2)
+{
+ const struct suffix *s1 = (const struct suffix *) p1;
+ const struct suffix *s2 = (const struct suffix *) p2;
+
+ return strcmp (s1->name, s2->name);
+}
+
+
+static int count_op_str;
+static int off_op_str;
+static void
+print_op_str (const void *nodep, VISIT value,
+ int level __attribute__ ((unused)))
+{
+ if (value == leaf || value == postorder)
+ {
+ const char *str = (*(struct argstring **) nodep)->str;
+ fprintf (outfile, "%s\n \"%s",
+ count_op_str == 0 ? "" : "\\0\"", str);
+ (*(struct argstring **) nodep)->idx = ++count_op_str;
+ (*(struct argstring **) nodep)->off = off_op_str;
+ off_op_str += strlen (str) + 1;
+ }
+}
+
+
+static void
+print_op_str_idx (const void *nodep, VISIT value,
+ int level __attribute__ ((unused)))
+{
+ if (value == leaf || value == postorder)
+ printf (" %d,\n", (*(struct argstring **) nodep)->off);
+}
+
+
+static void
+print_op_fct (const void *nodep, VISIT value,
+ int level __attribute__ ((unused)))
+{
+ if (value == leaf || value == postorder)
+ {
+ fprintf (outfile, " FCT_%s,\n", (*(struct argstring **) nodep)->str);
+ (*(struct argstring **) nodep)->idx = ++count_op_str;
+ }
+}
+
+
+#if NMNES < 2
+# error "bogus NMNES value"
+#endif
+
+static void
+instrtable_out (void)
+{
+ find_numbers ();
+
+#if 0
+ create_mnemonic_table ();
+
+ fprintf (outfile, "#define MNEMONIC_BITS %zu\n", best_mnemonic_bits);
+#else
+ fprintf (outfile, "#define MNEMONIC_BITS %ld\n",
+ lrint (ceil (log2 (NMNES))));
+#endif
+ fprintf (outfile, "#define SUFFIX_BITS %d\n", nbitsuf);
+ for (int i = 0; i < 3; ++i)
+ {
+ fprintf (outfile, "#define FCT%d_BITS %d\n", i + 1, nbitfct[i]);
+ if (nbitstr[i] != 0)
+ fprintf (outfile, "#define STR%d_BITS %d\n", i + 1, nbitstr[i]);
+ fprintf (outfile, "#define OFF%d_1_BITS %d\n", i + 1, nbitoff[i][0]);
+ fprintf (outfile, "#define OFF%d_1_BIAS %d\n", i + 1, minoff[i][0]);
+ if (nbitoff[i][1] != 0)
+ {
+ fprintf (outfile, "#define OFF%d_2_BITS %d\n", i + 1, nbitoff[i][1]);
+ fprintf (outfile, "#define OFF%d_2_BIAS %d\n", i + 1, minoff[i][1]);
+ }
+ if (nbitoff[i][2] != 0)
+ {
+ fprintf (outfile, "#define OFF%d_3_BITS %d\n", i + 1, nbitoff[i][2]);
+ fprintf (outfile, "#define OFF%d_3_BIAS %d\n", i + 1, minoff[i][2]);
+ }
+ }
+
+ fputs ("\n#include <i386_data.h>\n\n", outfile);
+
+
+#define APPEND(a, b) APPEND_ (a, b)
+#define APPEND_(a, b) a##b
+#define EMIT_SUFFIX(suf) \
+ fprintf (outfile, "#define suffix_%s %d\n", #suf, APPEND (suffix_, suf))
+ EMIT_SUFFIX (none);
+ EMIT_SUFFIX (w);
+ EMIT_SUFFIX (w0);
+ EMIT_SUFFIX (W);
+ EMIT_SUFFIX (tttn);
+ EMIT_SUFFIX (D);
+ EMIT_SUFFIX (w1);
+ EMIT_SUFFIX (W1);
+
+ fputc_unlocked ('\n', outfile);
+
+ for (int i = 0; i < 3; ++i)
+ {
+ /* Functions. */
+ count_op_str = 0;
+ fprintf (outfile, "static const opfct_t op%d_fct[] =\n{\n NULL,\n",
+ i + 1);
+ twalk (fct_names[i], print_op_fct);
+ fputs ("};\n", outfile);
+
+ /* The operand strings. */
+ if (nbitstr[i] != 0)
+ {
+ count_op_str = 0;
+ off_op_str = 0;
+ fprintf (outfile, "static const char op%d_str[] =", i + 1);
+ twalk (strs[i], print_op_str);
+ fputs ("\";\n", outfile);
+
+ fprintf (outfile, "static const uint8_t op%d_str_idx[] = {\n",
+ i + 1);
+ twalk (strs[i], print_op_str_idx);
+ fputs ("};\n", outfile);
+ }
+ }
+
+
+ fputs ("static const struct instr_enc instrtab[] =\n{\n", outfile);
+ struct instruction *instr;
+ for (instr = instructions; instr != NULL; instr = instr->next)
+ {
+ fputs (" {", outfile);
+ if (instr->mnemonic == (void *) -1l)
+ fputs (" .mnemonic = MNE_INVALID,", outfile);
+ else
+ fprintf (outfile, " .mnemonic = MNE_%s,", instr->mnemonic);
+ fprintf (outfile, " .rep = %d,", instr->rep);
+ fprintf (outfile, " .repe = %d,", instr->repe);
+ fprintf (outfile, " .suffix = %d,", instr->suffix);
+ fprintf (outfile, " .modrm = %d,", instr->modrm);
+
+ for (int i = 0; i < 3; ++i)
+ {
+ int idx = 0;
+ if (instr->operands[i].fct != NULL)
+ {
+ struct argstring search = { .str = instr->operands[i].fct };
+ struct argstring **res = tfind (&search, &fct_names[i],
+ compare_argstring);
+ assert (res != NULL);
+ idx = (*res)->idx;
+ }
+ fprintf (outfile, " .fct%d = %d,", i + 1, idx);
+
+ idx = 0;
+ if (instr->operands[i].str != NULL)
+ {
+ struct argstring search = { .str = instr->operands[i].str };
+ struct argstring **res = tfind (&search, &strs[i],
+ compare_argstring);
+ assert (res != NULL);
+ idx = (*res)->idx;
+ }
+ if (nbitstr[i] != 0)
+ fprintf (outfile, " .str%d = %d,", i + 1, idx);
+
+ fprintf (outfile, " .off%d_1 = %d,", i + 1,
+ MAX (0, instr->operands[i].off1 - minoff[i][0]));
+
+ if (nbitoff[i][1] != 0)
+ fprintf (outfile, " .off%d_2 = %d,", i + 1,
+ MAX (0, instr->operands[i].off2 - minoff[i][1]));
+
+ if (nbitoff[i][2] != 0)
+ fprintf (outfile, " .off%d_3 = %d,", i + 1,
+ MAX (0, instr->operands[i].off3 - minoff[i][2]));
+ }
+
+ fputs (" },\n", outfile);
+ }
+ fputs ("};\n", outfile);
+
+ fputs ("static const uint8_t match_data[] =\n{\n", outfile);
+ size_t cnt = 0;
+ for (instr = instructions; instr != NULL; instr = instr->next, ++cnt)
+ {
+ /* First count the number of bytes. */
+ size_t totalbits = 0;
+ size_t zerobits = 0;
+ bool leading_p = true;
+ size_t leadingbits = 0;
+ struct bitvalue *b = instr->bytes;
+ while (b != NULL)
+ {
+ if (b->type == zeroone)
+ {
+ ++totalbits;
+ zerobits = 0;
+ if (leading_p)
+ ++leadingbits;
+ }
+ else
+ {
+ totalbits += b->field->bits;
+ /* We must always count the mod/rm byte. */
+ if (strncasecmp (b->field->name, "mod", 3) == 0)
+ zerobits = 0;
+ else
+ zerobits += b->field->bits;
+ leading_p = false;
+ }
+ b = b->next;
+ }
+ size_t nbytes = (totalbits - zerobits + 7) / 8;
+ assert (nbytes > 0);
+ size_t leadingbytes = leadingbits / 8;
+
+ fprintf (outfile, " %#zx,", nbytes | (leadingbytes << 4));
+
+ /* Now create the mask and byte values. */
+ uint8_t byte = 0;
+ uint8_t mask = 0;
+ int nbits = 0;
+ b = instr->bytes;
+ while (b != NULL)
+ {
+ if (b->type == zeroone)
+ {
+ byte = (byte << 1) | b->value;
+ mask = (mask << 1) | 1;
+ if (++nbits == 8)
+ {
+ if (leadingbytes > 0)
+ {
+ assert (mask == 0xff);
+ fprintf (outfile, " %#" PRIx8 ",", byte);
+ --leadingbytes;
+ }
+ else
+ fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",",
+ mask, byte);
+ byte = mask = nbits = 0;
+ if (--nbytes == 0)
+ break;
+ }
+ }
+ else
+ {
+ assert (leadingbytes == 0);
+
+ unsigned long int remaining = b->field->bits;
+ while (nbits + remaining > 8)
+ {
+ fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",",
+ mask << (8 - nbits), byte << (8 - nbits));
+ remaining = nbits + remaining - 8;
+ byte = mask = nbits = 0;
+ if (--nbytes == 0)
+ break;
+ }
+ byte <<= remaining;
+ mask <<= remaining;
+ nbits += remaining;
+ if (nbits == 8)
+ {
+ fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",", mask, byte);
+ byte = mask = nbits = 0;
+ if (--nbytes == 0)
+ break;
+ }
+ }
+ b = b->next;
+ }
+
+ fputc_unlocked ('\n', outfile);
+ }
+ fputs ("};\n", outfile);
+}
+
+
+#if 0
+static size_t mnemonic_maxlen;
+static size_t mnemonic_minlen;
+static size_t
+which_chars (const char *str[], size_t nstr)
+{
+ char used_char[256];
+ memset (used_char, '\0', sizeof (used_char));
+ mnemonic_maxlen = 0;
+ mnemonic_minlen = 10000;
+ for (size_t cnt = 0; cnt < nstr; ++cnt)
+ {
+ const unsigned char *cp = (const unsigned char *) str[cnt];
+ mnemonic_maxlen = MAX (mnemonic_maxlen, strlen ((char *) cp));
+ mnemonic_minlen = MIN (mnemonic_minlen, strlen ((char *) cp));
+ do
+ used_char[*cp++] = 1;
+ while (*cp != '\0');
+ }
+ size_t nused_char = 0;
+ for (size_t cnt = 0; cnt < 256; ++cnt)
+ if (used_char[cnt] != 0)
+ ++nused_char;
+ return nused_char;
+}
+
+
+static const char **mnemonic_strs;
+static size_t nmnemonic_strs;
+static void
+add_mnemonics (const void *nodep, VISIT value,
+ int level __attribute__ ((unused)))
+{
+ if (value == leaf || value == postorder)
+ mnemonic_strs[nmnemonic_strs++] = *(const char **) nodep;
+}
+
+
+struct charfreq
+{
+ char ch;
+ int freq;
+};
+static struct charfreq pfxfreq[256];
+static struct charfreq sfxfreq[256];
+
+
+static int
+compare_freq (const void *p1, const void *p2)
+{
+ const struct charfreq *c1 = (const struct charfreq *) p1;
+ const struct charfreq *c2 = (const struct charfreq *) p2;
+
+ if (c1->freq > c2->freq)
+ return -1;
+ if (c1->freq < c2->freq)
+ return 1;
+ return 0;
+}
+
+
+static size_t
+compute_pfxfreq (const char *str[], size_t nstr)
+{
+ memset (pfxfreq, '\0', sizeof (pfxfreq));
+
+ for (size_t i = 0; i < nstr; ++i)
+ pfxfreq[i].ch = i;
+
+ for (size_t i = 0; i < nstr; ++i)
+ ++pfxfreq[*((const unsigned char *) str[i])].freq;
+
+ qsort (pfxfreq, 256, sizeof (struct charfreq), compare_freq);
+
+ size_t n = 0;
+ while (n < 256 && pfxfreq[n].freq != 0)
+ ++n;
+ return n;
+}
+
+
+struct strsnlen
+{
+ const char *str;
+ size_t len;
+};
+
+static size_t
+compute_sfxfreq (size_t nstr, struct strsnlen *strsnlen)
+{
+ memset (sfxfreq, '\0', sizeof (sfxfreq));
+
+ for (size_t i = 0; i < nstr; ++i)
+ sfxfreq[i].ch = i;
+
+ for (size_t i = 0; i < nstr; ++i)
+ ++sfxfreq[((const unsigned char *) strchrnul (strsnlen[i].str, '\0'))[-1]].freq;
+
+ qsort (sfxfreq, 256, sizeof (struct charfreq), compare_freq);
+
+ size_t n = 0;
+ while (n < 256 && sfxfreq[n].freq != 0)
+ ++n;
+ return n;
+}
+
+
+static void
+create_mnemonic_table (void)
+{
+ mnemonic_strs = xmalloc (nmnemonics * sizeof (char *));
+
+ twalk (mnemonics, add_mnemonics);
+
+ (void) which_chars (mnemonic_strs, nmnemonic_strs);
+
+ size_t best_so_far = 100000000;
+ char *best_prefix = NULL;
+ char *best_suffix = NULL;
+ char *best_table = NULL;
+ size_t best_table_size = 0;
+ size_t best_table_bits = 0;
+ size_t best_prefix_bits = 0;
+
+ /* We can precompute the prefix characters. */
+ size_t npfx_char = compute_pfxfreq (mnemonic_strs, nmnemonic_strs);
+
+ /* Compute best size for string representation including explicit NUL. */
+ for (size_t pfxbits = 0; (1u << pfxbits) < 2 * npfx_char; ++pfxbits)
+ {
+ char prefix[1 << pfxbits];
+ size_t i;
+ for (i = 0; i < (1u << pfxbits) - 1; ++i)
+ prefix[i] = pfxfreq[i].ch;
+ prefix[i] = '\0';
+
+ struct strsnlen strsnlen[nmnemonic_strs];
+
+ for (i = 0; i < nmnemonic_strs; ++i)
+ {
+ if (strchr (prefix, *mnemonic_strs[i]) != NULL)
+ strsnlen[i].str = mnemonic_strs[i] + 1;
+ else
+ strsnlen[i].str = mnemonic_strs[i];
+ strsnlen[i].len = strlen (strsnlen[i].str);
+ }
+
+ /* With the prefixes gone, try to combine strings. */
+ size_t nstrsnlen = 1;
+ for (i = 1; i < nmnemonic_strs; ++i)
+ {
+ size_t j;
+ for (j = 0; j < nstrsnlen; ++j)
+ if (strsnlen[i].len > strsnlen[j].len
+ && strcmp (strsnlen[j].str,
+ strsnlen[i].str + (strsnlen[i].len
+ - strsnlen[j].len)) == 0)
+ {
+ strsnlen[j] = strsnlen[i];
+ break;
+ }
+ else if (strsnlen[i].len < strsnlen[j].len
+ && strcmp (strsnlen[i].str,
+ strsnlen[j].str + (strsnlen[j].len
+ - strsnlen[i].len)) == 0)
+ break;
+;
+ if (j == nstrsnlen)
+ strsnlen[nstrsnlen++] = strsnlen[i];
+ }
+
+ size_t nsfx_char = compute_sfxfreq (nstrsnlen, strsnlen);
+
+ for (size_t sfxbits = 0; (1u << sfxbits) < 2 * nsfx_char; ++sfxbits)
+ {
+ char suffix[1 << sfxbits];
+
+ for (i = 0; i < (1u << sfxbits) - 1; ++i)
+ suffix[i] = sfxfreq[i].ch;
+ suffix[i] = '\0';
+
+ size_t newlen[nstrsnlen];
+
+ for (i = 0; i < nstrsnlen; ++i)
+ if (strchr (suffix, strsnlen[i].str[strsnlen[i].len - 1]) != NULL)
+ newlen[i] = strsnlen[i].len - 1;
+ else
+ newlen[i] = strsnlen[i].len;
+
+ char charused[256];
+ memset (charused, '\0', sizeof (charused));
+ size_t ncharused = 0;
+
+ const char *tablestr[nstrsnlen];
+ size_t ntablestr = 1;
+ tablestr[0] = strsnlen[0].str;
+ size_t table = newlen[0] + 1;
+ for (i = 1; i < nstrsnlen; ++i)
+ {
+ size_t j;
+ for (j = 0; j < ntablestr; ++j)
+ if (newlen[i] > newlen[j]
+ && memcmp (tablestr[j],
+ strsnlen[i].str + (newlen[i] - newlen[j]),
+ newlen[j]) == 0)
+ {
+ table += newlen[i] - newlen[j];
+ tablestr[j] = strsnlen[i].str;
+ newlen[j] = newlen[i];
+ break;
+ }
+ else if (newlen[i] < newlen[j]
+ && memcmp (strsnlen[i].str,
+ tablestr[j] + (newlen[j] - newlen[i]),
+ newlen[i]) == 0)
+ break;
+
+ if (j == ntablestr)
+ {
+ table += newlen[i] + 1;
+ tablestr[ntablestr] = strsnlen[i].str;
+ newlen[ntablestr] = newlen[i];
+
+ ++ntablestr;
+ }
+
+ for (size_t x = 0; x < newlen[j]; ++x)
+ if (charused[((const unsigned char *) tablestr[j])[x]]++ == 0)
+ ++ncharused;
+ }
+
+ size_t ncharused_bits = 0;
+ i = 1;
+ while (i < ncharused)
+ {
+ i *= 2;
+ ++ncharused_bits;
+ }
+
+ size_t table_bits = 0;
+ i = 1;
+ while (i < table)
+ {
+ i *= 2;
+ ++table_bits;
+ }
+
+ size_t mnemonic_bits = table_bits + pfxbits + sfxbits;
+ size_t new_total = (((table + 7) / 8) * ncharused_bits + ncharused
+ + (pfxbits == 0 ? 0 : (1 << pfxbits) - 1)
+ + (sfxbits == 0 ? 0 : (1 << sfxbits) - 1)
+ + (((total_bits + mnemonic_bits + 7) / 8)
+ * ninstructions));
+
+ if (new_total < best_so_far)
+ {
+ best_so_far = new_total;
+ best_mnemonic_bits = mnemonic_bits;
+
+ free (best_suffix);
+ best_suffix = xstrdup (suffix);
+
+ free (best_prefix);
+ best_prefix = xstrdup (prefix);
+ best_prefix_bits = pfxbits;
+
+ best_table_size = table;
+ best_table_bits = table_bits;
+ char *cp = best_table = xrealloc (best_table, table);
+ for (i = 0; i < ntablestr; ++i)
+ {
+ assert (cp + newlen[i] + 1 <= best_table + table);
+ cp = mempcpy (cp, tablestr[i], newlen[i]);
+ *cp++ = '\0';
+ }
+ assert (cp == best_table + table);
+ }
+ }
+ }
+
+ fputs ("static const char mnemonic_table[] =\n\"", outfile);
+ for (size_t i = 0; i < best_table_size; ++i)
+ {
+ if (((i + 1) % 60) == 0)
+ fputs ("\"\n\"", outfile);
+ if (!isascii (best_table[i]) || !isprint (best_table[i]))
+ fprintf (outfile, "\\%03o", best_table[i]);
+ else
+ fputc (best_table[i], outfile);
+ }
+ fputs ("\";\n", outfile);
+
+ if (best_prefix[0] != '\0')
+ fprintf (outfile,
+ "static const char prefix[%zu] = \"%s\";\n"
+ "#define PREFIXCHAR_BITS %zu\n",
+ strlen (best_prefix), best_prefix, best_prefix_bits);
+ else
+ fputs ("#define NO_PREFIX\n", outfile);
+
+ if (best_suffix[0] != '\0')
+ fprintf (outfile, "static const char suffix[%zu] = \"%s\";\n",
+ strlen (best_suffix), best_suffix);
+ else
+ fputs ("#define NO_SUFFIX\n", outfile);
+
+ for (size_t i = 0; i < nmnemonic_strs; ++i)
+ {
+ const char *mne = mnemonic_strs[i];
+
+ size_t pfxval = 0;
+ char *cp = strchr (best_prefix, *mne);
+ if (cp != NULL)
+ {
+ pfxval = 1 + (cp - best_prefix);
+ ++mne;
+ }
+
+ size_t l = strlen (mne);
+
+ size_t sfxval = 0;
+ cp = strchr (best_suffix, mne[l - 1]);
+ if (cp != NULL)
+ {
+ sfxval = 1 + (cp - best_suffix);
+ --l;
+ }
+
+ char *off = memmem (best_table, best_table_size, mne, l);
+ while (off[l] != '\0')
+ {
+ off = memmem (off + 1, best_table_size, mne, l);
+ assert (off != NULL);
+ }
+
+ fprintf (outfile, "#define MNE_%s %#zx\n",
+ mnemonic_strs[i],
+ (off - best_table)
+ + ((pfxval + (sfxval << best_prefix_bits)) << best_table_bits));
+ }
+}
+#endif
diff --git a/libcpu/memory-access.h b/libcpu/memory-access.h
new file mode 100644
index 0000000..c68eb4a
--- /dev/null
+++ b/libcpu/memory-access.h
@@ -0,0 +1,179 @@
+/* Unaligned memory access functionality.
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2008 Red Hat, Inc.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+ Red Hat elfutils 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; version 2 of the License.
+
+ Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifndef _MEMORY_ACCESS_H
+#define _MEMORY_ACCESS_H 1
+
+#include <byteswap.h>
+#include <endian.h>
+#include <limits.h>
+#include <stdint.h>
+
+
+/* When loading this file we require the macro MACHINE_ENCODING to be
+ defined to signal the endianness of the architecture which is
+ defined. */
+#ifndef MACHINE_ENCODING
+# error "MACHINE_ENCODING needs to be defined"
+#endif
+#if MACHINE_ENCODING != __BIG_ENDIAN && MACHINE_ENCODING != __LITTLE_ENDIAN
+# error "MACHINE_ENCODING must signal either big or little endian"
+#endif
+
+
+/* We use simple memory access functions in case the hardware allows it.
+ The caller has to make sure we don't have alias problems. */
+#if ALLOW_UNALIGNED
+
+# define read_2ubyte_unaligned(Addr) \
+ (unlikely (MACHINE_ENCODING != __BYTE_ORDER) \
+ ? bswap_16 (*((const uint16_t *) (Addr))) \
+ : *((const uint16_t *) (Addr)))
+# define read_2sbyte_unaligned(Addr) \
+ (unlikely (MACHINE_ENCODING != __BYTE_ORDER) \
+ ? (int16_t) bswap_16 (*((const int16_t *) (Addr))) \
+ : *((const int16_t *) (Addr)))
+
+# define read_4ubyte_unaligned_noncvt(Addr) \
+ *((const uint32_t *) (Addr))
+# define read_4ubyte_unaligned(Addr) \
+ (unlikely (MACHINE_ENCODING != __BYTE_ORDER) \
+ ? bswap_32 (*((const uint32_t *) (Addr))) \
+ : *((const uint32_t *) (Addr)))
+# define read_4sbyte_unaligned(Addr) \
+ (unlikely (MACHINE_ENCODING != __BYTE_ORDER) \
+ ? (int32_t) bswap_32 (*((const int32_t *) (Addr))) \
+ : *((const int32_t *) (Addr)))
+
+# define read_8ubyte_unaligned(Addr) \
+ (unlikely (MACHINE_ENCODING != __BYTE_ORDER) \
+ ? bswap_64 (*((const uint64_t *) (Addr))) \
+ : *((const uint64_t *) (Addr)))
+# define read_8sbyte_unaligned(Addr) \
+ (unlikely (MACHINE_ENCODING != __BYTE_ORDER) \
+ ? (int64_t) bswap_64 (*((const int64_t *) (Addr))) \
+ : *((const int64_t *) (Addr)))
+
+#else
+
+union unaligned
+ {
+ void *p;
+ uint16_t u2;
+ uint32_t u4;
+ uint64_t u8;
+ int16_t s2;
+ int32_t s4;
+ int64_t s8;
+ } __attribute__ ((packed));
+
+static inline uint16_t
+read_2ubyte_unaligned (const void *p)
+{
+ const union unaligned *up = p;
+ if (MACHINE_ENCODING != __BYTE_ORDER)
+ return bswap_16 (up->u2);
+ return up->u2;
+}
+static inline int16_t
+read_2sbyte_unaligned (const void *p)
+{
+ const union unaligned *up = p;
+ if (MACHINE_ENCODING != __BYTE_ORDER)
+ return (int16_t) bswap_16 (up->u2);
+ return up->s2;
+}
+
+static inline uint32_t
+read_4ubyte_unaligned_noncvt (const void *p)
+{
+ const union unaligned *up = p;
+ return up->u4;
+}
+static inline uint32_t
+read_4ubyte_unaligned (const void *p)
+{
+ const union unaligned *up = p;
+ if (MACHINE_ENCODING != __BYTE_ORDER)
+ return bswap_32 (up->u4);
+ return up->u4;
+}
+static inline int32_t
+read_4sbyte_unaligned (const void *p)
+{
+ const union unaligned *up = p;
+ if (MACHINE_ENCODING != __BYTE_ORDER)
+ return (int32_t) bswap_32 (up->u4);
+ return up->s4;
+}
+
+static inline uint64_t
+read_8ubyte_unaligned (const void *p)
+{
+ const union unaligned *up = p;
+ if (MACHINE_ENCODING != __BYTE_ORDER)
+ return bswap_64 (up->u8);
+ return up->u8;
+}
+static inline int64_t
+read_8sbyte_unaligned (const void *p)
+{
+ const union unaligned *up = p;
+ if (MACHINE_ENCODING != __BYTE_ORDER)
+ return (int64_t) bswap_64 (up->u8);
+ return up->s8;
+}
+
+#endif /* allow unaligned */
+
+
+#define read_2ubyte_unaligned_inc(Addr) \
+ ({ uint16_t t_ = read_2ubyte_unaligned (Addr); \
+ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \
+ t_; })
+#define read_2sbyte_unaligned_inc(Addr) \
+ ({ int16_t t_ = read_2sbyte_unaligned (Addr); \
+ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \
+ t_; })
+
+#define read_4ubyte_unaligned_inc(Addr) \
+ ({ uint32_t t_ = read_4ubyte_unaligned (Addr); \
+ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \
+ t_; })
+#define read_4sbyte_unaligned_inc(Addr) \
+ ({ int32_t t_ = read_4sbyte_unaligned (Addr); \
+ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \
+ t_; })
+
+#define read_8ubyte_unaligned_inc(Addr) \
+ ({ uint64_t t_ = read_8ubyte_unaligned (Addr); \
+ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \
+ t_; })
+#define read_8sbyte_unaligned_inc(Addr) \
+ ({ int64_t t_ = read_8sbyte_unaligned (Addr); \
+ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \
+ t_; })
+
+#endif /* memory-access.h */
diff --git a/libcpu/x86_64_disasm.c b/libcpu/x86_64_disasm.c
new file mode 100644
index 0000000..b793b78
--- /dev/null
+++ b/libcpu/x86_64_disasm.c
@@ -0,0 +1,31 @@
+/* Disassembler for x86-64.
+ Copyright (C) 2007, 2008 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+ Written by Ulrich Drepper <drepper@redhat.com>, 2007.
+
+ Red Hat elfutils 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; version 2 of the License.
+
+ Red Hat elfutils 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 Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#define i386_disasm x86_64_disasm
+#define DISFILE "x86_64_dis.h"
+#define MNEFILE "x86_64.mnemonics"
+#define X86_64
+#include "i386_disasm.c"