Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel' of ssh://newskysaw.cs.northwestern.edu/home/palacios/palacios...
Patrick G. Bridges [Thu, 9 Feb 2012 20:24:52 +0000 (13:24 -0700)]
25 files changed:
Kconfig
linux_module/iface-file.c
palacios/include/palacios/vmm_msr.h
palacios/include/quix86/quix86.h [new file with mode: 0644]
palacios/lib/i386/Makefile
palacios/lib/i386/libquix86.a [new file with mode: 0644]
palacios/lib/i386/libquix86_debug.a [new file with mode: 0644]
palacios/lib/x86_64/Makefile
palacios/lib/x86_64/libquix86.a [new file with mode: 0644]
palacios/lib/x86_64/libquix86_debug.a [new file with mode: 0644]
palacios/src/devices/cga.c
palacios/src/devices/ide.c
palacios/src/palacios/Makefile
palacios/src/palacios/svm_msr.c
palacios/src/palacios/vm_guest.c
palacios/src/palacios/vmcs.c
palacios/src/palacios/vmm.c
palacios/src/palacios/vmm_checkpoint.c
palacios/src/palacios/vmm_config.c
palacios/src/palacios/vmm_ctrl_regs.c
palacios/src/palacios/vmm_mem.c
palacios/src/palacios/vmm_mem_hook.c
palacios/src/palacios/vmm_msr.c
palacios/src/palacios/vmm_quix86.c [new file with mode: 0644]
palacios/src/palacios/vmx.c

diff --git a/Kconfig b/Kconfig
index 8518fd8..0fb4b9a 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -102,6 +102,16 @@ config V3_DECODER
        help
            This selects the internal V3Vee x86 decoder
 
+config QUIX86
+    bool "QUIX86 decoder"
+    help
+        This selects the QUIX86 decoder library
+
+config QUIX86_DEBUG
+    bool "QUIX86 decoder debug version"
+    help
+        This selects the QUIX86 decoder library compiled w/o optimization
+        and with debug info
 
 endchoice
 
index 39f909b..be31f16 100644 (file)
@@ -344,6 +344,7 @@ static int guest_file_init(struct v3_guest * guest, void ** vm_data) {
 
 static int guest_file_deinit(struct v3_guest * guest, void * vm_data) {
     
+    kfree(vm_data);
     return 0;
 }
 
index f8cbd4e..1869e33 100644 (file)
@@ -26,6 +26,7 @@
 #include <palacios/vmm_types.h>
 #include <palacios/vmm_list.h>
 
+#define IA32_PAT_MSR    0x277
 #define SYSENTER_CS_MSR 0x00000174
 #define SYSENTER_ESP_MSR 0x00000175
 #define SYSENTER_EIP_MSR 0x00000176
diff --git a/palacios/include/quix86/quix86.h b/palacios/include/quix86/quix86.h
new file mode 100644 (file)
index 0000000..8530962
--- /dev/null
@@ -0,0 +1,2049 @@
+/* +------------------------------------------------------------------------+
+   | quix86                                                                 |
+   +------------------------------------------------------------------------+
+   | This file is part of quix86, an x86-64 instruction decoder.            |
+   |                                                                        |
+   | Copyright (C) 2011 Institute for System Programming of Russian Academy |
+   | of Sciences.                                                           |
+   |                                                                        |
+   | Contact e-mail: <unicluster@ispras.ru>.                                |
+   |                                                                        |
+   | quix86 is free software: you can redistribute it and/or modify it      |
+   | under the terms of the GNU Lesser General Public License as published  |
+   | by the Free Software Foundation, either version 3 of the License, or   |
+   | (at your option) any later version.                                    |
+   |                                                                        |
+   | quix86 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 Lesser General Public   |
+   | License for more details.                                              |
+   |                                                                        |
+   | You should have received a copy of the GNU Lesser General Public       |
+   | License along with quix86. If not, see <http://www.gnu.org/licenses/>. |
+   +------------------------------------------------------------------------+ */
+
+#ifndef QUIX86_H
+#define QUIX86_H
+
+/* Provide definitions for INT8..INT64 and UINT8..UINT64.  */
+#ifdef _MSC_VER
+    /* Definitions for INT8..INT64.  */
+#   define QX86_INT8                    __int8
+#   define QX86_INT16                   __int16
+#   define QX86_INT32                   __int32
+#   define QX86_INT64                   __int64
+
+    /* Definitions for UINT8..UINT64.  */
+#   define QX86_UINT8                   unsigned __int8
+#   define QX86_UINT16                  unsigned __int16
+#   define QX86_UINT32                  unsigned __int32
+#   define QX86_UINT64                  unsigned __int64
+#else
+    /* No built-in types.  See if we have one of the standard headers.  */
+#   if defined(HAVE_INTTYPES_H) || defined(HAVE_STDINT_H)
+        /* Prefer <stdint.h> as it's somewhat smaller.  */
+#       ifdef HAVE_STDINT_H
+            /* Include <stdint.h>.  */
+#           include <stdint.h>
+#       else
+            /* Include <inttypes.h> instead.  */
+#           include <inttypes.h>
+#       endif
+
+        /* Definitions for INT8..INT64.  */
+#       define QX86_INT8                int8_t
+#       define QX86_INT16               int16_t
+#       define QX86_INT32               int32_t
+#       define QX86_INT64               int64_t
+
+        /* Definitions for UINT8..UINT64.  */
+#       define QX86_UINT8               uint8_t
+#       define QX86_UINT16              uint16_t
+#       define QX86_UINT32              uint32_t
+#       define QX86_UINT64              uint64_t
+#   else
+        /* Likely definitions for INT8..INT64.  */
+#       define QX86_INT8                signed char
+#       define QX86_INT16               short
+#       define QX86_INT32               int
+#       define QX86_INT64               long long
+
+        /* Likely definitions for UINT8..UINT64.  */
+#       define QX86_UINT8               unsigned char
+#       define QX86_UINT16              unsigned short
+#       define QX86_UINT32              unsigned int
+#       define QX86_UINT64              unsigned long long
+#   endif
+#endif
+
+/* Provide wrappers around const and inline for compilers that don't support
+   C99.  */
+#ifdef _MSC_VER
+    /* Microsoft Visual C is not C99-conformant.  Use alternative keywords.  */
+#   define QX86_CONST                   const
+#   define QX86_INLINE                  __inline
+#   define QX86_RESTRICT                /* ILB */
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+    /* C99 supported.  */
+#   define QX86_CONST                   const
+#   define QX86_INLINE                  inline
+#   define QX86_RESTRICT                restrict
+#elif defined(__GNUC__) && (__GNUC__ >= 4)
+    /* GNU C supported. */
+#   define QX86_CONST                   const
+#   define QX86_INLINE                  inline
+#   define QX86_RESTRICT                restrict
+#elif defined(__cplusplus)
+    /* C++ mode supports const and inline.  */
+#   define QX86_CONST                   const
+#   define QX86_INLINE                  inline
+#   define QX86_RESTRICT                /* ILB */
+#else
+    /* Assume none of the qualifiers is supported.  */
+#   define QX86_CONST                   /* ILB */
+#   define QX86_INLINE                  /* ILB */
+#   define QX86_RESTRICT                /* ILB */
+#endif
+
+/* Wrap declarations in extern "C" if needed.  */
+#ifdef __cplusplus
+    /* Need wrapper.  */
+#   define QX86_EXTERN_C                extern "C"
+#else
+    /* No wrapper required.  */
+#   define QX86_EXTERN_C                /* ILB */
+#endif
+
+/**
+ * 8-bit signed integer type.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+typedef QX86_INT8                       qx86_int8;
+
+/**
+ * 16-bit signed integer type.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+typedef QX86_INT16                      qx86_int16;
+
+/**
+ * 32-bit signed integer type.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+typedef QX86_INT32                      qx86_int32;
+
+/**
+ * 64-bit signed integer type.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+typedef QX86_INT64                      qx86_int64;
+
+/**
+ * 8-bit unsigned integer type.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+typedef QX86_UINT8                      qx86_uint8;
+
+/**
+ * 16-bit unsigned integer type.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+typedef QX86_UINT16                     qx86_uint16;
+
+/**
+ * 32-bit unsigned integer type.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+typedef QX86_UINT32                     qx86_uint32;
+
+/**
+ * 64-bit unsigned integer type.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+typedef QX86_UINT64                     qx86_uint64;
+
+/* Public API structure declarations.  */
+typedef struct qx86_amode               qx86_amode;
+typedef struct qx86_ctx                 qx86_ctx;
+typedef struct qx86_insn                qx86_insn;
+typedef struct qx86_insn_attributes     qx86_insn_attributes;
+typedef struct qx86_insn_modifiers      qx86_insn_modifiers;
+typedef struct qx86_print_options_intel qx86_print_options_intel;
+typedef struct qx86_mtab_item           qx86_mtab_item;
+typedef struct qx86_opcode_map          qx86_opcode_map;
+typedef struct qx86_opcode_map_item     qx86_opcode_map_item;
+typedef struct qx86_operand             qx86_operand;
+typedef struct qx86_operand_far_pointer qx86_operand_far_pointer;
+typedef struct qx86_operand_form        qx86_operand_form;
+typedef struct qx86_operand_form_amode  qx86_operand_form_amode;
+typedef struct qx86_operand_form_rtuple qx86_operand_form_rtuple;
+typedef struct qx86_operand_immediate   qx86_operand_immediate;
+typedef struct qx86_operand_jump_offset qx86_operand_jump_offset;
+typedef struct qx86_operand_memory      qx86_operand_memory;
+typedef struct qx86_operand_register    qx86_operand_register;
+typedef struct qx86_print_item          qx86_print_item;
+typedef struct qx86_rtab_item           qx86_rtab_item;
+typedef struct qx86_rtuple              qx86_rtuple;
+typedef struct qx86_stuple              qx86_stuple;
+
+/* Public API union declarations.  */
+typedef union qx86_operand_union        qx86_operand_union;
+typedef union qx86_operand_form_union   qx86_operand_form_union;
+
+/* Public API enumerations.  */
+
+
+/**
+ * Enumeration of <em>x86</em> instruction defects.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_DEFECT_NONE                    = 0,
+
+    QX86_DEFECT_MODRM_MOD_NOT_3         = 1 << 0,
+    QX86_DEFECT_MODRM_MOD_3             = 1 << 1
+};
+
+
+
+/**
+ * Enumeration of <em>x86</em> displacement sizes.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_DISP_NONE                      = 0,
+    QX86_DISP_8                         = 1,
+    QX86_DISP_16                        = 2,
+    QX86_DISP_32                        = 4,
+    QX86_DISP_64                        = 8,
+
+    QX86_DISP_INVALID                   = 3
+};
+
+
+
+/**
+ * Enumeration of <tt>quix86</tt> error codes.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_SUCCESS                        = 0,
+
+    QX86_E_INTERNAL                     = 1,
+    QX86_E_API                          = 2,
+
+    QX86_E_INSN_INCOMPLETE              = 3,
+    QX86_E_INSN_UNDEFINED               = 4,
+
+    QX86_E_INSUFFICIENT_BUFFER          = 5,
+    
+    QX86_E_CALLBACK                     = 6,
+
+    QX86_E_COUNT                        = 7
+};
+
+
+
+/**
+ * Enumeration of instruction classes.
+ *
+ * An instruction can belong to multiple instruction classes at the same time.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_ICLASS_NONE                    = 0,
+
+    QX86_ICLASS_CONDITIONAL_EXECUTION   = 1 << 0,
+
+    QX86_ICLASS_TRANSFER                = 1 << 1,
+    QX86_ICLASS_TRANSFER_LINKED         = 1 << 2,
+    QX86_ICLASS_TRANSFER_LINKED_BACK    = 1 << 3,
+    QX86_ICLASS_TRANSFER_SERVICE        = 1 << 4
+};
+
+
+
+/**
+ * Architectural limits of the <em>x86</em>.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_IMMEDIATE_SIZE_MAX             = 8,
+    QX86_INSN_SIZE_MAX                  = 15,
+    QX86_OPERAND_NMAX                   = 4
+};
+
+
+/**
+ * Enumeration of <em>x86</em> instruction mnemonics.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum qx86_mnemonic
+{
+    QX86_MNEMONIC_NONE                  = 0,
+
+    /* Enumerators are sorted based on their names.  */
+    QX86_MNEMONIC_AAA                   = 1,
+    QX86_MNEMONIC_AAD                   = 2,
+    QX86_MNEMONIC_AAM                   = 3,
+    QX86_MNEMONIC_AAS                   = 4,
+    QX86_MNEMONIC_ADC                   = 5,
+    QX86_MNEMONIC_ADD                   = 6,
+    QX86_MNEMONIC_ADDPD                 = 7,
+    QX86_MNEMONIC_ADDPS                 = 8,
+    QX86_MNEMONIC_ADDSD                 = 9,
+    QX86_MNEMONIC_ADDSS                 = 10,
+    QX86_MNEMONIC_ADDSUBPD              = 11,
+    QX86_MNEMONIC_ADDSUBPS              = 12,
+    QX86_MNEMONIC_AESDEC                = 13,
+    QX86_MNEMONIC_AESDECLAST            = 14,
+    QX86_MNEMONIC_AESENC                = 15,
+    QX86_MNEMONIC_AESENCLAST            = 16,
+    QX86_MNEMONIC_AESIMC                = 17,
+    QX86_MNEMONIC_AESKEYGENASSIST       = 18,
+    QX86_MNEMONIC_AND                   = 19,
+    QX86_MNEMONIC_ANDNPD                = 20,
+    QX86_MNEMONIC_ANDNPS                = 21,
+    QX86_MNEMONIC_ANDPD                 = 22,
+    QX86_MNEMONIC_ANDPS                 = 23,
+    QX86_MNEMONIC_ARPL                  = 24,
+    QX86_MNEMONIC_BLENDPD               = 25,
+    QX86_MNEMONIC_BLENDPS               = 26,
+    QX86_MNEMONIC_BLENDVPD              = 27,
+    QX86_MNEMONIC_BLENDVPS              = 28,
+    QX86_MNEMONIC_BOUND                 = 29,
+    QX86_MNEMONIC_BSF                   = 30,
+    QX86_MNEMONIC_BSR                   = 31,
+    QX86_MNEMONIC_BSWAP                 = 32,
+    QX86_MNEMONIC_BT                    = 33,
+    QX86_MNEMONIC_BTC                   = 34,
+    QX86_MNEMONIC_BTR                   = 35,
+    QX86_MNEMONIC_BTS                   = 36,
+    QX86_MNEMONIC_CALL                  = 37,
+    QX86_MNEMONIC_CALLF                 = 38,
+    QX86_MNEMONIC_CBW                   = 39,
+    QX86_MNEMONIC_CDQ                   = 40,
+    QX86_MNEMONIC_CDQE                  = 41,
+    QX86_MNEMONIC_CLC                   = 42,
+    QX86_MNEMONIC_CLD                   = 43,
+    QX86_MNEMONIC_CLFLUSH               = 44,
+    QX86_MNEMONIC_CLGI                  = 45,
+    QX86_MNEMONIC_CLI                   = 46,
+    QX86_MNEMONIC_CLTS                  = 47,
+    QX86_MNEMONIC_CMC                   = 48,
+    QX86_MNEMONIC_CMOVA                 = 49,
+    QX86_MNEMONIC_CMOVAE                = 50,
+    QX86_MNEMONIC_CMOVB                 = 51,
+    QX86_MNEMONIC_CMOVBE                = 52,
+    QX86_MNEMONIC_CMOVG                 = 53,
+    QX86_MNEMONIC_CMOVGE                = 54,
+    QX86_MNEMONIC_CMOVL                 = 55,
+    QX86_MNEMONIC_CMOVLE                = 56,
+    QX86_MNEMONIC_CMOVNO                = 57,
+    QX86_MNEMONIC_CMOVNP                = 58,
+    QX86_MNEMONIC_CMOVNS                = 59,
+    QX86_MNEMONIC_CMOVNZ                = 60,
+    QX86_MNEMONIC_CMOVO                 = 61,
+    QX86_MNEMONIC_CMOVP                 = 62,
+    QX86_MNEMONIC_CMOVS                 = 63,
+    QX86_MNEMONIC_CMOVZ                 = 64,
+    QX86_MNEMONIC_CMP                   = 65,
+    QX86_MNEMONIC_CMPPD                 = 66,
+    QX86_MNEMONIC_CMPPS                 = 67,
+    QX86_MNEMONIC_CMPSB                 = 68,
+    QX86_MNEMONIC_CMPSD                 = 69,
+    QX86_MNEMONIC_CMPSD_SSE             = 70,
+    QX86_MNEMONIC_CMPSQ                 = 71,
+    QX86_MNEMONIC_CMPSS                 = 72,
+    QX86_MNEMONIC_CMPSW                 = 73,
+    QX86_MNEMONIC_CMPXCHG               = 74,
+    QX86_MNEMONIC_CMPXCHG16B            = 75,
+    QX86_MNEMONIC_CMPXCHG8B             = 76,
+    QX86_MNEMONIC_COMISD                = 77,
+    QX86_MNEMONIC_COMISS                = 78,
+    QX86_MNEMONIC_CPUID                 = 79,
+    QX86_MNEMONIC_CQO                   = 80,
+    QX86_MNEMONIC_CRC32                 = 81,
+    QX86_MNEMONIC_CVTDQ2PD              = 82,
+    QX86_MNEMONIC_CVTDQ2PS              = 83,
+    QX86_MNEMONIC_CVTPD2DQ              = 84,
+    QX86_MNEMONIC_CVTPD2PI              = 85,
+    QX86_MNEMONIC_CVTPD2PS              = 86,
+    QX86_MNEMONIC_CVTPI2PD              = 87,
+    QX86_MNEMONIC_CVTPI2PS              = 88,
+    QX86_MNEMONIC_CVTPS2DQ              = 89,
+    QX86_MNEMONIC_CVTPS2PD              = 90,
+    QX86_MNEMONIC_CVTPS2PI              = 91,
+    QX86_MNEMONIC_CVTSD2SI              = 92,
+    QX86_MNEMONIC_CVTSD2SS              = 93,
+    QX86_MNEMONIC_CVTSI2SD              = 94,
+    QX86_MNEMONIC_CVTSI2SS              = 95,
+    QX86_MNEMONIC_CVTSS2SD              = 96,
+    QX86_MNEMONIC_CVTSS2SI              = 97,
+    QX86_MNEMONIC_CVTTPD2DQ             = 98,
+    QX86_MNEMONIC_CVTTPD2PI             = 99,
+    QX86_MNEMONIC_CVTTPS2DQ             = 100,
+    QX86_MNEMONIC_CVTTPS2PI             = 101,
+    QX86_MNEMONIC_CVTTSD2SI             = 102,
+    QX86_MNEMONIC_CVTTSS2SI             = 103,
+    QX86_MNEMONIC_CWD                   = 104,
+    QX86_MNEMONIC_CWDE                  = 105,
+    QX86_MNEMONIC_DAA                   = 106,
+    QX86_MNEMONIC_DAS                   = 107,
+    QX86_MNEMONIC_DEC                   = 108,
+    QX86_MNEMONIC_DIV                   = 109,
+    QX86_MNEMONIC_DIVPD                 = 110,
+    QX86_MNEMONIC_DIVPS                 = 111,
+    QX86_MNEMONIC_DIVSD                 = 112,
+    QX86_MNEMONIC_DIVSS                 = 113,
+    QX86_MNEMONIC_DPPD                  = 114,
+    QX86_MNEMONIC_DPPS                  = 115,
+    QX86_MNEMONIC_EMMS                  = 116,
+    QX86_MNEMONIC_ENTER                 = 117,
+    QX86_MNEMONIC_EXTRACTPS             = 118,
+    QX86_MNEMONIC_EXTRQ                 = 119,
+    QX86_MNEMONIC_F2XM1                 = 120,
+    QX86_MNEMONIC_FABS                  = 121,
+    QX86_MNEMONIC_FADD                  = 122,
+    QX86_MNEMONIC_FADDP                 = 123,
+    QX86_MNEMONIC_FBLD                  = 124,
+    QX86_MNEMONIC_FBSTP                 = 125,
+    QX86_MNEMONIC_FCHS                  = 126,
+    QX86_MNEMONIC_FCMOVB                = 127,
+    QX86_MNEMONIC_FCMOVBE               = 128,
+    QX86_MNEMONIC_FCMOVE                = 129,
+    QX86_MNEMONIC_FCMOVNB               = 130,
+    QX86_MNEMONIC_FCMOVNBE              = 131,
+    QX86_MNEMONIC_FCMOVNE               = 132,
+    QX86_MNEMONIC_FCMOVNU               = 133,
+    QX86_MNEMONIC_FCMOVU                = 134,
+    QX86_MNEMONIC_FCOM                  = 135,
+    QX86_MNEMONIC_FCOMI                 = 136,
+    QX86_MNEMONIC_FCOMIP                = 137,
+    QX86_MNEMONIC_FCOMP                 = 138,
+    QX86_MNEMONIC_FCOMPP                = 139,
+    QX86_MNEMONIC_FCOS                  = 140,
+    QX86_MNEMONIC_FDECSTP               = 141,
+    QX86_MNEMONIC_FDIV                  = 142,
+    QX86_MNEMONIC_FDIVP                 = 143,
+    QX86_MNEMONIC_FDIVR                 = 144,
+    QX86_MNEMONIC_FDIVRP                = 145,
+    QX86_MNEMONIC_FEMMS                 = 146,
+    QX86_MNEMONIC_FFREE                 = 147,
+    QX86_MNEMONIC_FIADD                 = 148,
+    QX86_MNEMONIC_FICOM                 = 149,
+    QX86_MNEMONIC_FICOMP                = 150,
+    QX86_MNEMONIC_FIDIV                 = 151,
+    QX86_MNEMONIC_FIDIVR                = 152,
+    QX86_MNEMONIC_FILD                  = 153,
+    QX86_MNEMONIC_FIMUL                 = 154,
+    QX86_MNEMONIC_FINCSTP               = 155,
+    QX86_MNEMONIC_FIST                  = 156,
+    QX86_MNEMONIC_FISTP                 = 157,
+    QX86_MNEMONIC_FISTTP                = 158,
+    QX86_MNEMONIC_FISUB                 = 159,
+    QX86_MNEMONIC_FISUBR                = 160,
+    QX86_MNEMONIC_FLD                   = 161,
+    QX86_MNEMONIC_FLD1                  = 162,
+    QX86_MNEMONIC_FLDCW                 = 163,
+    QX86_MNEMONIC_FLDENV                = 164,
+    QX86_MNEMONIC_FLDL2E                = 165,
+    QX86_MNEMONIC_FLDL2T                = 166,
+    QX86_MNEMONIC_FLDLG2                = 167,
+    QX86_MNEMONIC_FLDLN2                = 168,
+    QX86_MNEMONIC_FLDPI                 = 169,
+    QX86_MNEMONIC_FLDZ                  = 170,
+    QX86_MNEMONIC_FMUL                  = 171,
+    QX86_MNEMONIC_FMULP                 = 172,
+    QX86_MNEMONIC_FNCLEX                = 173,
+    QX86_MNEMONIC_FNINIT                = 174,
+    QX86_MNEMONIC_FNOP                  = 175,
+    QX86_MNEMONIC_FNSAVE                = 176,
+    QX86_MNEMONIC_FNSTCW                = 177,
+    QX86_MNEMONIC_FNSTENV               = 178,
+    QX86_MNEMONIC_FNSTSW                = 179,
+    QX86_MNEMONIC_FPATAN                = 180,
+    QX86_MNEMONIC_FPREM                 = 181,
+    QX86_MNEMONIC_FPREM1                = 182,
+    QX86_MNEMONIC_FPTAN                 = 183,
+    QX86_MNEMONIC_FRNDINT               = 184,
+    QX86_MNEMONIC_FRSTOR                = 185,
+    QX86_MNEMONIC_FSCALE                = 186,
+    QX86_MNEMONIC_FSIN                  = 187,
+    QX86_MNEMONIC_FSINCOS               = 188,
+    QX86_MNEMONIC_FSQRT                 = 189,
+    QX86_MNEMONIC_FST                   = 190,
+    QX86_MNEMONIC_FSTP                  = 191,
+    QX86_MNEMONIC_FSUB                  = 192,
+    QX86_MNEMONIC_FSUBP                 = 193,
+    QX86_MNEMONIC_FSUBR                 = 194,
+    QX86_MNEMONIC_FSUBRP                = 195,
+    QX86_MNEMONIC_FTST                  = 196,
+    QX86_MNEMONIC_FUCOM                 = 197,
+    QX86_MNEMONIC_FUCOMI                = 198,
+    QX86_MNEMONIC_FUCOMIP               = 199,
+    QX86_MNEMONIC_FUCOMP                = 200,
+    QX86_MNEMONIC_FUCOMPP               = 201,
+    QX86_MNEMONIC_FWAIT                 = 202,
+    QX86_MNEMONIC_FXAM                  = 203,
+    QX86_MNEMONIC_FXCH                  = 204,
+    QX86_MNEMONIC_FXRSTOR               = 205,
+    QX86_MNEMONIC_FXSAVE                = 206,
+    QX86_MNEMONIC_FXTRACT               = 207,
+    QX86_MNEMONIC_FYL2X                 = 208,
+    QX86_MNEMONIC_FYL2XP1               = 209,
+    QX86_MNEMONIC_GETSEC                = 210,
+    QX86_MNEMONIC_HADDPD                = 211,
+    QX86_MNEMONIC_HADDPS                = 212,
+    QX86_MNEMONIC_HLT                   = 213,
+    QX86_MNEMONIC_HSUBPD                = 214,
+    QX86_MNEMONIC_HSUBPS                = 215,
+    QX86_MNEMONIC_IDIV                  = 216,
+    QX86_MNEMONIC_IMUL                  = 217,
+    QX86_MNEMONIC_IN                    = 218,
+    QX86_MNEMONIC_INC                   = 219,
+    QX86_MNEMONIC_INSB                  = 220,
+    QX86_MNEMONIC_INSD                  = 221,
+    QX86_MNEMONIC_INSERTPS              = 222,
+    QX86_MNEMONIC_INSERTQ               = 223,
+    QX86_MNEMONIC_INSW                  = 224,
+    QX86_MNEMONIC_INT                   = 225,
+    QX86_MNEMONIC_INT1                  = 226,
+    QX86_MNEMONIC_INT3                  = 227,
+    QX86_MNEMONIC_INTO                  = 228,
+    QX86_MNEMONIC_INVD                  = 229,
+    QX86_MNEMONIC_INVEPT                = 230,
+    QX86_MNEMONIC_INVLPG                = 231,
+    QX86_MNEMONIC_INVLPGA               = 232,
+    QX86_MNEMONIC_INVVPID               = 233,
+    QX86_MNEMONIC_IRET                  = 234,
+    QX86_MNEMONIC_IRETD                 = 235,
+    QX86_MNEMONIC_IRETQ                 = 236,
+    QX86_MNEMONIC_JA                    = 237,
+    QX86_MNEMONIC_JAE                   = 238,
+    QX86_MNEMONIC_JB                    = 239,
+    QX86_MNEMONIC_JBE                   = 240,
+    QX86_MNEMONIC_JCXZ                  = 241,
+    QX86_MNEMONIC_JECXZ                 = 242,
+    QX86_MNEMONIC_JG                    = 243,
+    QX86_MNEMONIC_JGE                   = 244,
+    QX86_MNEMONIC_JL                    = 245,
+    QX86_MNEMONIC_JLE                   = 246,
+    QX86_MNEMONIC_JMP                   = 247,
+    QX86_MNEMONIC_JMPF                  = 248,
+    QX86_MNEMONIC_JNO                   = 249,
+    QX86_MNEMONIC_JNP                   = 250,
+    QX86_MNEMONIC_JNS                   = 251,
+    QX86_MNEMONIC_JNZ                   = 252,
+    QX86_MNEMONIC_JO                    = 253,
+    QX86_MNEMONIC_JP                    = 254,
+    QX86_MNEMONIC_JRCXZ                 = 255,
+    QX86_MNEMONIC_JS                    = 256,
+    QX86_MNEMONIC_JZ                    = 257,
+    QX86_MNEMONIC_LAHF                  = 258,
+    QX86_MNEMONIC_LAR                   = 259,
+    QX86_MNEMONIC_LCS                   = 260,
+    QX86_MNEMONIC_LDDQU                 = 261,
+    QX86_MNEMONIC_LDMXCSR               = 262,
+    QX86_MNEMONIC_LDS                   = 263,
+    QX86_MNEMONIC_LEA                   = 264,
+    QX86_MNEMONIC_LEAVE                 = 265,
+    QX86_MNEMONIC_LES                   = 266,
+    QX86_MNEMONIC_LFENCE                = 267,
+    QX86_MNEMONIC_LFS                   = 268,
+    QX86_MNEMONIC_LGDT                  = 269,
+    QX86_MNEMONIC_LGS                   = 270,
+    QX86_MNEMONIC_LIDT                  = 271,
+    QX86_MNEMONIC_LLDT                  = 272,
+    QX86_MNEMONIC_LMSW                  = 273,
+    QX86_MNEMONIC_LODSB                 = 274,
+    QX86_MNEMONIC_LODSD                 = 275,
+    QX86_MNEMONIC_LODSQ                 = 276,
+    QX86_MNEMONIC_LODSW                 = 277,
+    QX86_MNEMONIC_LOOP                  = 278,
+    QX86_MNEMONIC_LOOPNZ                = 279,
+    QX86_MNEMONIC_LOOPZ                 = 280,
+    QX86_MNEMONIC_LSL                   = 281,
+    QX86_MNEMONIC_LSS                   = 282,
+    QX86_MNEMONIC_LTR                   = 283,
+    QX86_MNEMONIC_LZCNT                 = 284,
+    QX86_MNEMONIC_MASKMOVDQU            = 285,
+    QX86_MNEMONIC_MASKMOVQ              = 286,
+    QX86_MNEMONIC_MAXPD                 = 287,
+    QX86_MNEMONIC_MAXPS                 = 288,
+    QX86_MNEMONIC_MAXSD                 = 289,
+    QX86_MNEMONIC_MAXSS                 = 290,
+    QX86_MNEMONIC_MFENCE                = 291,
+    QX86_MNEMONIC_MINPD                 = 292,
+    QX86_MNEMONIC_MINPS                 = 293,
+    QX86_MNEMONIC_MINSD                 = 294,
+    QX86_MNEMONIC_MINSS                 = 295,
+    QX86_MNEMONIC_MONITOR               = 296,
+    QX86_MNEMONIC_MOV                   = 297,
+    QX86_MNEMONIC_MOVAPD                = 298,
+    QX86_MNEMONIC_MOVAPS                = 299,
+    QX86_MNEMONIC_MOVBE                 = 300,
+    QX86_MNEMONIC_MOVD                  = 301,
+    QX86_MNEMONIC_MOVDDUP               = 302,
+    QX86_MNEMONIC_MOVDQ2Q               = 303,
+    QX86_MNEMONIC_MOVDQA                = 304,
+    QX86_MNEMONIC_MOVDQU                = 305,
+    QX86_MNEMONIC_MOVHLPS               = 306,
+    QX86_MNEMONIC_MOVHPD                = 307,
+    QX86_MNEMONIC_MOVHPS                = 308,
+    QX86_MNEMONIC_MOVLHPS               = 309,
+    QX86_MNEMONIC_MOVLPD                = 310,
+    QX86_MNEMONIC_MOVLPS                = 311,
+    QX86_MNEMONIC_MOVMSKPD              = 312,
+    QX86_MNEMONIC_MOVMSKPS              = 313,
+    QX86_MNEMONIC_MOVNTDQ               = 314,
+    QX86_MNEMONIC_MOVNTDQA              = 315,
+    QX86_MNEMONIC_MOVNTI                = 316,
+    QX86_MNEMONIC_MOVNTPD               = 317,
+    QX86_MNEMONIC_MOVNTPS               = 318,
+    QX86_MNEMONIC_MOVNTQ                = 319,
+    QX86_MNEMONIC_MOVNTSD               = 320,
+    QX86_MNEMONIC_MOVNTSS               = 321,
+    QX86_MNEMONIC_MOVQ                  = 322,
+    QX86_MNEMONIC_MOVQ2DQ               = 323,
+    QX86_MNEMONIC_MOVSB                 = 324,
+    QX86_MNEMONIC_MOVSD                 = 325,
+    QX86_MNEMONIC_MOVSD_SSE             = 326,
+    QX86_MNEMONIC_MOVSHDUP              = 327,
+    QX86_MNEMONIC_MOVSLDUP              = 328,
+    QX86_MNEMONIC_MOVSQ                 = 329,
+    QX86_MNEMONIC_MOVSS                 = 330,
+    QX86_MNEMONIC_MOVSW                 = 331,
+    QX86_MNEMONIC_MOVSX                 = 332,
+    QX86_MNEMONIC_MOVSXD                = 333,
+    QX86_MNEMONIC_MOVUPD                = 334,
+    QX86_MNEMONIC_MOVUPS                = 335,
+    QX86_MNEMONIC_MOVZX                 = 336,
+    QX86_MNEMONIC_MPSADBW               = 337,
+    QX86_MNEMONIC_MUL                   = 338,
+    QX86_MNEMONIC_MULPD                 = 339,
+    QX86_MNEMONIC_MULPS                 = 340,
+    QX86_MNEMONIC_MULSD                 = 341,
+    QX86_MNEMONIC_MULSS                 = 342,
+    QX86_MNEMONIC_MWAIT                 = 343,
+    QX86_MNEMONIC_NEG                   = 344,
+    QX86_MNEMONIC_NOP                   = 345,
+    QX86_MNEMONIC_NOT                   = 346,
+    QX86_MNEMONIC_OR                    = 347,
+    QX86_MNEMONIC_ORPD                  = 348,
+    QX86_MNEMONIC_ORPS                  = 349,
+    QX86_MNEMONIC_OUT                   = 350,
+    QX86_MNEMONIC_OUTSB                 = 351,
+    QX86_MNEMONIC_OUTSD                 = 352,
+    QX86_MNEMONIC_OUTSW                 = 353,
+    QX86_MNEMONIC_PABSB                 = 354,
+    QX86_MNEMONIC_PABSD                 = 355,
+    QX86_MNEMONIC_PABSW                 = 356,
+    QX86_MNEMONIC_PACKSSDW              = 357,
+    QX86_MNEMONIC_PACKSSWB              = 358,
+    QX86_MNEMONIC_PACKUSDW              = 359,
+    QX86_MNEMONIC_PACKUSWB              = 360,
+    QX86_MNEMONIC_PADDB                 = 361,
+    QX86_MNEMONIC_PADDD                 = 362,
+    QX86_MNEMONIC_PADDQ                 = 363,
+    QX86_MNEMONIC_PADDSB                = 364,
+    QX86_MNEMONIC_PADDSW                = 365,
+    QX86_MNEMONIC_PADDUSB               = 366,
+    QX86_MNEMONIC_PADDUSW               = 367,
+    QX86_MNEMONIC_PADDW                 = 368,
+    QX86_MNEMONIC_PALIGNR               = 369,
+    QX86_MNEMONIC_PAND                  = 370,
+    QX86_MNEMONIC_PANDN                 = 371,
+    QX86_MNEMONIC_PAUSE                 = 372,
+    QX86_MNEMONIC_PAVGB                 = 373,
+    QX86_MNEMONIC_PAVGUSB               = 374,
+    QX86_MNEMONIC_PAVGW                 = 375,
+    QX86_MNEMONIC_PBLENDVB              = 376,
+    QX86_MNEMONIC_PBLENDW               = 377,
+    QX86_MNEMONIC_PCLMULQDQ             = 378,
+    QX86_MNEMONIC_PCMPEQB               = 379,
+    QX86_MNEMONIC_PCMPEQD               = 380,
+    QX86_MNEMONIC_PCMPEQQ               = 381,
+    QX86_MNEMONIC_PCMPEQW               = 382,
+    QX86_MNEMONIC_PCMPESTRI             = 383,
+    QX86_MNEMONIC_PCMPESTRM             = 384,
+    QX86_MNEMONIC_PCMPGTB               = 385,
+    QX86_MNEMONIC_PCMPGTD               = 386,
+    QX86_MNEMONIC_PCMPGTQ               = 387,
+    QX86_MNEMONIC_PCMPGTW               = 388,
+    QX86_MNEMONIC_PCMPISTRI             = 389,
+    QX86_MNEMONIC_PCMPISTRM             = 390,
+    QX86_MNEMONIC_PEXTRB                = 391,
+    QX86_MNEMONIC_PEXTRD                = 392,
+    QX86_MNEMONIC_PEXTRQ                = 393,
+    QX86_MNEMONIC_PEXTRW                = 394,
+    QX86_MNEMONIC_PF2ID                 = 395,
+    QX86_MNEMONIC_PF2IW                 = 396,
+    QX86_MNEMONIC_PFACC                 = 397,
+    QX86_MNEMONIC_PFADD                 = 398,
+    QX86_MNEMONIC_PFCMPEQ               = 399,
+    QX86_MNEMONIC_PFCMPGE               = 400,
+    QX86_MNEMONIC_PFCMPGT               = 401,
+    QX86_MNEMONIC_PFMAX                 = 402,
+    QX86_MNEMONIC_PFMIN                 = 403,
+    QX86_MNEMONIC_PFMUL                 = 404,
+    QX86_MNEMONIC_PFNACC                = 405,
+    QX86_MNEMONIC_PFPNACC               = 406,
+    QX86_MNEMONIC_PFRCP                 = 407,
+    QX86_MNEMONIC_PFRCPIT1              = 408,
+    QX86_MNEMONIC_PFRCPIT2              = 409,
+    QX86_MNEMONIC_PFRSQIT1              = 410,
+    QX86_MNEMONIC_PFRSQRT               = 411,
+    QX86_MNEMONIC_PFSUB                 = 412,
+    QX86_MNEMONIC_PFSUBR                = 413,
+    QX86_MNEMONIC_PHADDD                = 414,
+    QX86_MNEMONIC_PHADDSW               = 415,
+    QX86_MNEMONIC_PHADDW                = 416,
+    QX86_MNEMONIC_PHMINPOSUW            = 417,
+    QX86_MNEMONIC_PHSUBD                = 418,
+    QX86_MNEMONIC_PHSUBSW               = 419,
+    QX86_MNEMONIC_PHSUBW                = 420,
+    QX86_MNEMONIC_PI2FD                 = 421,
+    QX86_MNEMONIC_PI2FW                 = 422,
+    QX86_MNEMONIC_PINSRB                = 423,
+    QX86_MNEMONIC_PINSRD                = 424,
+    QX86_MNEMONIC_PINSRQ                = 425,
+    QX86_MNEMONIC_PINSRW                = 426,
+    QX86_MNEMONIC_PMADDUBSW             = 427,
+    QX86_MNEMONIC_PMADDWD               = 428,
+    QX86_MNEMONIC_PMAXSB                = 429,
+    QX86_MNEMONIC_PMAXSD                = 430,
+    QX86_MNEMONIC_PMAXSW                = 431,
+    QX86_MNEMONIC_PMAXUB                = 432,
+    QX86_MNEMONIC_PMAXUD                = 433,
+    QX86_MNEMONIC_PMAXUW                = 434,
+    QX86_MNEMONIC_PMINSB                = 435,
+    QX86_MNEMONIC_PMINSD                = 436,
+    QX86_MNEMONIC_PMINSW                = 437,
+    QX86_MNEMONIC_PMINUB                = 438,
+    QX86_MNEMONIC_PMINUD                = 439,
+    QX86_MNEMONIC_PMINUW                = 440,
+    QX86_MNEMONIC_PMOVMSKB              = 441,
+    QX86_MNEMONIC_PMOVSXBD              = 442,
+    QX86_MNEMONIC_PMOVSXBQ              = 443,
+    QX86_MNEMONIC_PMOVSXBW              = 444,
+    QX86_MNEMONIC_PMOVSXDQ              = 445,
+    QX86_MNEMONIC_PMOVSXWD              = 446,
+    QX86_MNEMONIC_PMOVSXWQ              = 447,
+    QX86_MNEMONIC_PMOVZXBD              = 448,
+    QX86_MNEMONIC_PMOVZXBQ              = 449,
+    QX86_MNEMONIC_PMOVZXBW              = 450,
+    QX86_MNEMONIC_PMOVZXDQ              = 451,
+    QX86_MNEMONIC_PMOVZXWD              = 452,
+    QX86_MNEMONIC_PMOVZXWQ              = 453,
+    QX86_MNEMONIC_PMULDQ                = 454,
+    QX86_MNEMONIC_PMULHRSW              = 455,
+    QX86_MNEMONIC_PMULHRW               = 456,
+    QX86_MNEMONIC_PMULHUW               = 457,
+    QX86_MNEMONIC_PMULHW                = 458,
+    QX86_MNEMONIC_PMULLD                = 459,
+    QX86_MNEMONIC_PMULLW                = 460,
+    QX86_MNEMONIC_PMULUDQ               = 461,
+    QX86_MNEMONIC_POP                   = 462,
+    QX86_MNEMONIC_POPA                  = 463,
+    QX86_MNEMONIC_POPAD                 = 464,
+    QX86_MNEMONIC_POPCNT                = 465,
+    QX86_MNEMONIC_POPF                  = 466,
+    QX86_MNEMONIC_POPFD                 = 467,
+    QX86_MNEMONIC_POPFQ                 = 468,
+    QX86_MNEMONIC_POR                   = 469,
+    QX86_MNEMONIC_PREFETCH              = 470,
+    QX86_MNEMONIC_PREFETCHNTA           = 471,
+    QX86_MNEMONIC_PREFETCHT0            = 472,
+    QX86_MNEMONIC_PREFETCHT1            = 473,
+    QX86_MNEMONIC_PREFETCHT2            = 474,
+    QX86_MNEMONIC_PREFETCHW             = 475,
+    QX86_MNEMONIC_PSADBW                = 476,
+    QX86_MNEMONIC_PSHUFB                = 477,
+    QX86_MNEMONIC_PSHUFD                = 478,
+    QX86_MNEMONIC_PSHUFHW               = 479,
+    QX86_MNEMONIC_PSHUFLW               = 480,
+    QX86_MNEMONIC_PSHUFW                = 481,
+    QX86_MNEMONIC_PSIGNB                = 482,
+    QX86_MNEMONIC_PSIGND                = 483,
+    QX86_MNEMONIC_PSIGNW                = 484,
+    QX86_MNEMONIC_PSLLD                 = 485,
+    QX86_MNEMONIC_PSLLDQ                = 486,
+    QX86_MNEMONIC_PSLLQ                 = 487,
+    QX86_MNEMONIC_PSLLW                 = 488,
+    QX86_MNEMONIC_PSRAD                 = 489,
+    QX86_MNEMONIC_PSRAW                 = 490,
+    QX86_MNEMONIC_PSRLD                 = 491,
+    QX86_MNEMONIC_PSRLDQ                = 492,
+    QX86_MNEMONIC_PSRLQ                 = 493,
+    QX86_MNEMONIC_PSRLW                 = 494,
+    QX86_MNEMONIC_PSUBB                 = 495,
+    QX86_MNEMONIC_PSUBD                 = 496,
+    QX86_MNEMONIC_PSUBQ                 = 497,
+    QX86_MNEMONIC_PSUBSB                = 498,
+    QX86_MNEMONIC_PSUBSW                = 499,
+    QX86_MNEMONIC_PSUBUSB               = 500,
+    QX86_MNEMONIC_PSUBUSW               = 501,
+    QX86_MNEMONIC_PSUBW                 = 502,
+    QX86_MNEMONIC_PSWAPD                = 503,
+    QX86_MNEMONIC_PTEST                 = 504,
+    QX86_MNEMONIC_PUNPCKHBW             = 505,
+    QX86_MNEMONIC_PUNPCKHDQ             = 506,
+    QX86_MNEMONIC_PUNPCKHQDQ            = 507,
+    QX86_MNEMONIC_PUNPCKHWD             = 508,
+    QX86_MNEMONIC_PUNPCKLBW             = 509,
+    QX86_MNEMONIC_PUNPCKLDQ             = 510,
+    QX86_MNEMONIC_PUNPCKLQDQ            = 511,
+    QX86_MNEMONIC_PUNPCKLWD             = 512,
+    QX86_MNEMONIC_PUSH                  = 513,
+    QX86_MNEMONIC_PUSHA                 = 514,
+    QX86_MNEMONIC_PUSHAD                = 515,
+    QX86_MNEMONIC_PUSHF                 = 516,
+    QX86_MNEMONIC_PUSHFD                = 517,
+    QX86_MNEMONIC_PUSHFQ                = 518,
+    QX86_MNEMONIC_PXOR                  = 519,
+    QX86_MNEMONIC_RCL                   = 520,
+    QX86_MNEMONIC_RCPPS                 = 521,
+    QX86_MNEMONIC_RCPSS                 = 522,
+    QX86_MNEMONIC_RCR                   = 523,
+    QX86_MNEMONIC_RDMSR                 = 524,
+    QX86_MNEMONIC_RDPMC                 = 525,
+    QX86_MNEMONIC_RDTSC                 = 526,
+    QX86_MNEMONIC_RDTSCP                = 527,
+    QX86_MNEMONIC_RET                   = 528,
+    QX86_MNEMONIC_RETF                  = 529,
+    QX86_MNEMONIC_ROL                   = 530,
+    QX86_MNEMONIC_ROR                   = 531,
+    QX86_MNEMONIC_ROUNDPD               = 532,
+    QX86_MNEMONIC_ROUNDPS               = 533,
+    QX86_MNEMONIC_ROUNDSD               = 534,
+    QX86_MNEMONIC_ROUNDSS               = 535,
+    QX86_MNEMONIC_RSM                   = 536,
+    QX86_MNEMONIC_RSQRTPS               = 537,
+    QX86_MNEMONIC_RSQRTSS               = 538,
+    QX86_MNEMONIC_SAHF                  = 539,
+    QX86_MNEMONIC_SALC                  = 540,
+    QX86_MNEMONIC_SAR                   = 541,
+    QX86_MNEMONIC_SBB                   = 542,
+    QX86_MNEMONIC_SCASB                 = 543,
+    QX86_MNEMONIC_SCASD                 = 544,
+    QX86_MNEMONIC_SCASQ                 = 545,
+    QX86_MNEMONIC_SCASW                 = 546,
+    QX86_MNEMONIC_SETA                  = 547,
+    QX86_MNEMONIC_SETAE                 = 548,
+    QX86_MNEMONIC_SETB                  = 549,
+    QX86_MNEMONIC_SETBE                 = 550,
+    QX86_MNEMONIC_SETG                  = 551,
+    QX86_MNEMONIC_SETGE                 = 552,
+    QX86_MNEMONIC_SETL                  = 553,
+    QX86_MNEMONIC_SETLE                 = 554,
+    QX86_MNEMONIC_SETNO                 = 555,
+    QX86_MNEMONIC_SETNP                 = 556,
+    QX86_MNEMONIC_SETNS                 = 557,
+    QX86_MNEMONIC_SETNZ                 = 558,
+    QX86_MNEMONIC_SETO                  = 559,
+    QX86_MNEMONIC_SETP                  = 560,
+    QX86_MNEMONIC_SETS                  = 561,
+    QX86_MNEMONIC_SETZ                  = 562,
+    QX86_MNEMONIC_SFENCE                = 563,
+    QX86_MNEMONIC_SGDT                  = 564,
+    QX86_MNEMONIC_SHL                   = 565,
+    QX86_MNEMONIC_SHLD                  = 566,
+    QX86_MNEMONIC_SHR                   = 567,
+    QX86_MNEMONIC_SHRD                  = 568,
+    QX86_MNEMONIC_SHUFPD                = 569,
+    QX86_MNEMONIC_SHUFPS                = 570,
+    QX86_MNEMONIC_SIDT                  = 571,
+    QX86_MNEMONIC_SKINIT                = 572,
+    QX86_MNEMONIC_SLDT                  = 573,
+    QX86_MNEMONIC_SMSW                  = 574,
+    QX86_MNEMONIC_SQRTPD                = 575,
+    QX86_MNEMONIC_SQRTPS                = 576,
+    QX86_MNEMONIC_SQRTSD                = 577,
+    QX86_MNEMONIC_SQRTSS                = 578,
+    QX86_MNEMONIC_STC                   = 579,
+    QX86_MNEMONIC_STD                   = 580,
+    QX86_MNEMONIC_STGI                  = 581,
+    QX86_MNEMONIC_STI                   = 582,
+    QX86_MNEMONIC_STMXCSR               = 583,
+    QX86_MNEMONIC_STOSB                 = 584,
+    QX86_MNEMONIC_STOSD                 = 585,
+    QX86_MNEMONIC_STOSQ                 = 586,
+    QX86_MNEMONIC_STOSW                 = 587,
+    QX86_MNEMONIC_STR                   = 588,
+    QX86_MNEMONIC_SUB                   = 589,
+    QX86_MNEMONIC_SUBPD                 = 590,
+    QX86_MNEMONIC_SUBPS                 = 591,
+    QX86_MNEMONIC_SUBSD                 = 592,
+    QX86_MNEMONIC_SUBSS                 = 593,
+    QX86_MNEMONIC_SWAPGS                = 594,
+    QX86_MNEMONIC_SYSCALL               = 595,
+    QX86_MNEMONIC_SYSENTER              = 596,
+    QX86_MNEMONIC_SYSEXIT               = 597,
+    QX86_MNEMONIC_SYSRET                = 598,
+    QX86_MNEMONIC_TEST                  = 599,
+    QX86_MNEMONIC_UCOMISD               = 600,
+    QX86_MNEMONIC_UCOMISS               = 601,
+    QX86_MNEMONIC_UD2                   = 602,
+    QX86_MNEMONIC_UNPCKHPD              = 603,
+    QX86_MNEMONIC_UNPCKHPS              = 604,
+    QX86_MNEMONIC_UNPCKLPD              = 605,
+    QX86_MNEMONIC_UNPCKLPS              = 606,
+    QX86_MNEMONIC_VERR                  = 607,
+    QX86_MNEMONIC_VERW                  = 608,
+    QX86_MNEMONIC_VMCALL                = 609,
+    QX86_MNEMONIC_VMCLEAR               = 610,
+    QX86_MNEMONIC_VMLAUNCH              = 611,
+    QX86_MNEMONIC_VMLOAD                = 612,
+    QX86_MNEMONIC_VMMCALL               = 613,
+    QX86_MNEMONIC_VMPTRLD               = 614,
+    QX86_MNEMONIC_VMPTRST               = 615,
+    QX86_MNEMONIC_VMREAD                = 616,
+    QX86_MNEMONIC_VMRESUME              = 617,
+    QX86_MNEMONIC_VMRUN                 = 618,
+    QX86_MNEMONIC_VMSAVE                = 619,
+    QX86_MNEMONIC_VMWRITE               = 620,
+    QX86_MNEMONIC_VMXOFF                = 621,
+    QX86_MNEMONIC_VMXON                 = 622,
+    QX86_MNEMONIC_WBINVD                = 623,
+    QX86_MNEMONIC_WRMSR                 = 624,
+    QX86_MNEMONIC_XADD                  = 625,
+    QX86_MNEMONIC_XCHG                  = 626,
+    QX86_MNEMONIC_XGETBV                = 627,
+    QX86_MNEMONIC_XLAT                  = 628,
+    QX86_MNEMONIC_XOR                   = 629,
+    QX86_MNEMONIC_XORPD                 = 630,
+    QX86_MNEMONIC_XORPS                 = 631,
+    QX86_MNEMONIC_XRSTOR                = 632,
+    QX86_MNEMONIC_XSAVE                 = 633,
+    QX86_MNEMONIC_XSETBV                = 634,
+
+    QX86_MNEMONIC_COUNT                 = 635
+};
+
+
+/**
+ * Enumeration of mnemonic attributes.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_MATTRIBUTE_NONE                = 0,
+    QX86_MATTRIBUTE_REP                 = 1 << 0,
+    QX86_MATTRIBUTE_REPZ                = 1 << 1,
+    QX86_MATTRIBUTE_DEFAULT_SIZE_64     = 1 << 2,
+    QX86_MATTRIBUTE_FIXED_SIZE_64       = 1 << 3,
+    QX86_MATTRIBUTE_INTERLOCKABLE       = 1 << 4,
+    QX86_MATTRIBUTE_IMPLICIT_LOCK       = 1 << 5
+};
+
+
+
+/**
+ * Enumeration of ModRM fields.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_MODRM_FIELD_NONE               = 0,
+
+    QX86_MODRM_FIELD_MOD                = 1 << 0,
+    QX86_MODRM_FIELD_REG                = 1 << 2,
+    QX86_MODRM_FIELD_RM                 = 1 << 3
+};
+
+
+
+/**
+ * Enumeration of <em>x86</em> opcode escapes.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_OPCODE_ESCAPE_NONE             = 0,
+
+    QX86_OPCODE_ESCAPE_0F               = 1,
+    QX86_OPCODE_ESCAPE_0F_38            = 2,
+    QX86_OPCODE_ESCAPE_0F_3A            = 3,
+
+    QX86_OPCODE_ESCAPE_COUNT            = 4
+};
+
+
+
+/**
+ * Enumeration of opcode map indexes.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_OPCODE_MAP_INDEX_NONE          = 0,
+
+    QX86_OPCODE_MAP_INDEX_NB            = 1,
+    QX86_OPCODE_MAP_INDEX_PB            = 2,
+
+    QX86_OPCODE_MAP_INDEX_AS            = 3,
+    QX86_OPCODE_MAP_INDEX_CS            = 4,
+    QX86_OPCODE_MAP_INDEX_OS            = 5,
+
+    QX86_OPCODE_MAP_INDEX_SP            = 6,
+
+    QX86_OPCODE_MAP_INDEX_MOD           = 7,
+    QX86_OPCODE_MAP_INDEX_REG           = 8,
+    QX86_OPCODE_MAP_INDEX_RM            = 9,
+
+    QX86_OPCODE_MAP_INDEX_COUNT         = 10
+};
+
+
+
+/**
+ * Enumeration of opcode map item codes.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_OPCODE_MAP_ITEM_CODE_NONE      = -0,
+    QX86_OPCODE_MAP_ITEM_CODE_LINK      = -1,
+    QX86_OPCODE_MAP_ITEM_CODE_PREFIX    = -2
+};
+
+
+
+/**
+ * Enumeration of <em>x86</em> operand attributes.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_OPERAND_ATTRIBUTE_NONE         = 0,
+
+    QX86_OPERAND_ATTRIBUTE_READ         = 1,
+    QX86_OPERAND_ATTRIBUTE_WRITTEN      = 2,
+    QX86_OPERAND_ATTRIBUTE_READWRITTEN  = 3,
+
+    QX86_OPERAND_ATTRIBUTE_RW_CERTAIN   = 4
+};
+
+
+
+/**
+ * Enumeration of <em>x86</em> operand form types.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_OPERAND_FORM_TYPE_NONE         = 0,
+
+    QX86_OPERAND_FORM_TYPE_AMODE        = 1,
+    QX86_OPERAND_FORM_TYPE_IMPLICIT_1   = 2,
+    QX86_OPERAND_FORM_TYPE_RTUPLE       = 3,
+
+    QX86_OPERAND_FORM_COUNT             = 4
+};
+
+
+
+/**
+ * Enumeration of <em>x86</em> operand types.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_OPERAND_TYPE_NONE              = 0,
+
+    QX86_OPERAND_TYPE_FAR_POINTER       = 1,
+    QX86_OPERAND_TYPE_IMMEDIATE         = 2,
+    QX86_OPERAND_TYPE_JUMP_OFFSET       = 3,
+    QX86_OPERAND_TYPE_MEMORY            = 4,
+    QX86_OPERAND_TYPE_REGISTER          = 5,
+
+    QX86_OPERAND_TYPE_COUNT             = 6
+};
+
+
+
+/**
+ * Enumeration of <em>x86</em> register classes.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_RCLASS_NONE                    = 0,
+    QX86_RCLASS_IP                      = 1,
+    QX86_RCLASS_FLAGS                   = 2,
+    QX86_RCLASS_RESERVED_3              = 3,
+
+    QX86_RCLASS_REG8                    = 4,
+    QX86_RCLASS_REG16                   = 5,
+    QX86_RCLASS_REG32                   = 6,
+    QX86_RCLASS_REG64                   = 7,
+
+    QX86_RCLASS_CREG                    = 8,
+    QX86_RCLASS_DREG                    = 9,
+    QX86_RCLASS_SREG                    = 10,
+    QX86_RCLASS_RESERVED_11             = 11,
+
+    QX86_RCLASS_X87                     = 12,
+    QX86_RCLASS_MMX                     = 13,
+    QX86_RCLASS_XMM                     = 14,
+    QX86_RCLASS_YMM                     = 15,
+
+    QX86_RCLASS_COUNT                   = 16
+};
+
+
+
+/**
+ * Enumeration of <em>x86</em> registers.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_REGISTER_NONE                  = 0,
+    QX86_REGISTER_INVALID               = 1,
+    QX86_REGISTER_SPECIAL               = 2,
+    QX86_REGISTER_RESERVED_3            = 3,
+
+    QX86_REGISTER_RESERVED_4            = 4,
+    QX86_REGISTER_IP                    = 5,
+    QX86_REGISTER_EIP                   = 6,
+    QX86_REGISTER_RIP                   = 7,
+
+    QX86_REGISTER_RESERVED_8            = 8,
+    QX86_REGISTER_FLAGS                 = 9,
+    QX86_REGISTER_EFLAGS                = 10,
+    QX86_REGISTER_RFLAGS                = 11,
+
+    QX86_REGISTER_AH                    = 12,
+    QX86_REGISTER_CH                    = 13,
+    QX86_REGISTER_DH                    = 14,
+    QX86_REGISTER_BH                    = 15,
+
+    QX86_REGISTER_AL                    = 16,
+    QX86_REGISTER_CL                    = 17,
+    QX86_REGISTER_DL                    = 18,
+    QX86_REGISTER_BL                    = 19,
+    QX86_REGISTER_SPL                   = 20,
+    QX86_REGISTER_BPL                   = 21,
+    QX86_REGISTER_SIL                   = 22,
+    QX86_REGISTER_DIL                   = 23,
+    QX86_REGISTER_R8B                   = 24,
+    QX86_REGISTER_R9B                   = 25,
+    QX86_REGISTER_R10B                  = 26,
+    QX86_REGISTER_R11B                  = 27,
+    QX86_REGISTER_R12B                  = 28,
+    QX86_REGISTER_R13B                  = 29,
+    QX86_REGISTER_R14B                  = 30,
+    QX86_REGISTER_R15B                  = 31,
+
+    QX86_REGISTER_AX                    = 32,
+    QX86_REGISTER_CX                    = 33,
+    QX86_REGISTER_DX                    = 34,
+    QX86_REGISTER_BX                    = 35,
+    QX86_REGISTER_SP                    = 36,
+    QX86_REGISTER_BP                    = 37,
+    QX86_REGISTER_SI                    = 38,
+    QX86_REGISTER_DI                    = 39,
+    QX86_REGISTER_R8W                   = 40,
+    QX86_REGISTER_R9W                   = 41,
+    QX86_REGISTER_R10W                  = 42,
+    QX86_REGISTER_R11W                  = 43,
+    QX86_REGISTER_R12W                  = 44,
+    QX86_REGISTER_R13W                  = 45,
+    QX86_REGISTER_R14W                  = 46,
+    QX86_REGISTER_R15W                  = 47,
+
+    QX86_REGISTER_EAX                   = 48,
+    QX86_REGISTER_ECX                   = 49,
+    QX86_REGISTER_EDX                   = 50,
+    QX86_REGISTER_EBX                   = 51,
+    QX86_REGISTER_ESP                   = 52,
+    QX86_REGISTER_EBP                   = 53,
+    QX86_REGISTER_ESI                   = 54,
+    QX86_REGISTER_EDI                   = 55,
+    QX86_REGISTER_R8D                   = 56,
+    QX86_REGISTER_R9D                   = 57,
+    QX86_REGISTER_R10D                  = 58,
+    QX86_REGISTER_R11D                  = 59,
+    QX86_REGISTER_R12D                  = 60,
+    QX86_REGISTER_R13D                  = 61,
+    QX86_REGISTER_R14D                  = 62,
+    QX86_REGISTER_R15D                  = 63,
+
+    QX86_REGISTER_RAX                   = 64,
+    QX86_REGISTER_RCX                   = 65,
+    QX86_REGISTER_RDX                   = 66,
+    QX86_REGISTER_RBX                   = 67,
+    QX86_REGISTER_RSP                   = 68,
+    QX86_REGISTER_RBP                   = 69,
+    QX86_REGISTER_RSI                   = 70,
+    QX86_REGISTER_RDI                   = 71,
+    QX86_REGISTER_R8                    = 72,
+    QX86_REGISTER_R9                    = 73,
+    QX86_REGISTER_R10                   = 74,
+    QX86_REGISTER_R11                   = 75,
+    QX86_REGISTER_R12                   = 76,
+    QX86_REGISTER_R13                   = 77,
+    QX86_REGISTER_R14                   = 78,
+    QX86_REGISTER_R15                   = 79,
+
+    QX86_REGISTER_CR0                   = 80,
+    QX86_REGISTER_CR1                   = 81,
+    QX86_REGISTER_CR2                   = 82,
+    QX86_REGISTER_CR3                   = 83,
+    QX86_REGISTER_CR4                   = 84,
+    QX86_REGISTER_CR5                   = 85,
+    QX86_REGISTER_CR6                   = 86,
+    QX86_REGISTER_CR7                   = 87,
+    QX86_REGISTER_CR8                   = 88,
+    QX86_REGISTER_CR9                   = 89,
+    QX86_REGISTER_CR10                  = 90,
+    QX86_REGISTER_CR11                  = 91,
+    QX86_REGISTER_CR12                  = 92,
+    QX86_REGISTER_CR13                  = 93,
+    QX86_REGISTER_CR14                  = 94,
+    QX86_REGISTER_CR15                  = 95,
+
+    QX86_REGISTER_DR0                   = 96,
+    QX86_REGISTER_DR1                   = 97,
+    QX86_REGISTER_DR2                   = 98,
+    QX86_REGISTER_DR3                   = 99,
+    QX86_REGISTER_DR4                   = 100,
+    QX86_REGISTER_DR5                   = 101,
+    QX86_REGISTER_DR6                   = 102,
+    QX86_REGISTER_DR7                   = 103,
+    QX86_REGISTER_DR8                   = 104,
+    QX86_REGISTER_DR9                   = 105,
+    QX86_REGISTER_DR10                  = 106,
+    QX86_REGISTER_DR11                  = 107,
+    QX86_REGISTER_DR12                  = 108,
+    QX86_REGISTER_DR13                  = 109,
+    QX86_REGISTER_DR14                  = 110,
+    QX86_REGISTER_DR15                  = 111,
+
+    QX86_REGISTER_ES                    = 112,
+    QX86_REGISTER_CS                    = 113,
+    QX86_REGISTER_SS                    = 114,
+    QX86_REGISTER_DS                    = 115,
+    QX86_REGISTER_FS                    = 116,
+    QX86_REGISTER_GS                    = 117,
+    QX86_REGISTER_SR6                   = 118,
+    QX86_REGISTER_SR7                   = 119,
+
+    QX86_REGISTER_ST0                   = 120,
+    QX86_REGISTER_ST1                   = 121,
+    QX86_REGISTER_ST2                   = 122,
+    QX86_REGISTER_ST3                   = 123,
+    QX86_REGISTER_ST4                   = 124,
+    QX86_REGISTER_ST5                   = 125,
+    QX86_REGISTER_ST6                   = 126,
+    QX86_REGISTER_ST7                   = 127,
+
+    QX86_REGISTER_FPR0                  = 128,
+    QX86_REGISTER_FPR1                  = 129,
+    QX86_REGISTER_FPR2                  = 130,
+    QX86_REGISTER_FPR3                  = 131,
+    QX86_REGISTER_FPR4                  = 132,
+    QX86_REGISTER_FPR5                  = 133,
+    QX86_REGISTER_FPR6                  = 134,
+    QX86_REGISTER_FPR7                  = 135,
+
+    QX86_REGISTER_MMX0                  = 136,
+    QX86_REGISTER_MMX1                  = 137,
+    QX86_REGISTER_MMX2                  = 138,
+    QX86_REGISTER_MMX3                  = 139,
+    QX86_REGISTER_MMX4                  = 140,
+    QX86_REGISTER_MMX5                  = 141,
+    QX86_REGISTER_MMX6                  = 142,
+    QX86_REGISTER_MMX7                  = 143,
+
+    QX86_REGISTER_XMM0                  = 144,
+    QX86_REGISTER_XMM1                  = 145,
+    QX86_REGISTER_XMM2                  = 146,
+    QX86_REGISTER_XMM3                  = 147,
+    QX86_REGISTER_XMM4                  = 148,
+    QX86_REGISTER_XMM5                  = 149,
+    QX86_REGISTER_XMM6                  = 150,
+    QX86_REGISTER_XMM7                  = 151,
+    QX86_REGISTER_XMM8                  = 152,
+    QX86_REGISTER_XMM9                  = 153,
+    QX86_REGISTER_XMM10                 = 154,
+    QX86_REGISTER_XMM11                 = 155,
+    QX86_REGISTER_XMM12                 = 156,
+    QX86_REGISTER_XMM13                 = 157,
+    QX86_REGISTER_XMM14                 = 158,
+    QX86_REGISTER_XMM15                 = 159,
+
+    QX86_REGISTER_YMM0                  = 160,
+    QX86_REGISTER_YMM1                  = 161,
+    QX86_REGISTER_YMM2                  = 162,
+    QX86_REGISTER_YMM3                  = 163,
+    QX86_REGISTER_YMM4                  = 164,
+    QX86_REGISTER_YMM5                  = 165,
+    QX86_REGISTER_YMM6                  = 166,
+    QX86_REGISTER_YMM7                  = 167,
+    QX86_REGISTER_YMM8                  = 168,
+    QX86_REGISTER_YMM9                  = 169,
+    QX86_REGISTER_YMM10                 = 170,
+    QX86_REGISTER_YMM11                 = 171,
+    QX86_REGISTER_YMM12                 = 172,
+    QX86_REGISTER_YMM13                 = 173,
+    QX86_REGISTER_YMM14                 = 174,
+    QX86_REGISTER_YMM15                 = 175,
+
+    QX86_REGISTER_COUNT                 = 176
+};
+
+
+
+/**
+ * Enumeration of ModRM and SIB <em>scale</em> values.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_SCALE_NONE                     = 0,
+    QX86_SCALE_X2                       = 1,
+    QX86_SCALE_X4                       = 2,
+    QX86_SCALE_X8                       = 3,
+    QX86_SCALE_INVALID                  = 4
+};
+
+
+
+/**
+ * Enumeration of <em>x86</em> code, address, operand, and stack sizes.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_SIZE_16                        = 0,
+    QX86_SIZE_32                        = 1,
+    QX86_SIZE_64                        = 2,
+    QX86_SIZE_INVALID                   = 3,
+    QX86_SIZE_MASK                      = 3
+};
+
+
+
+/**
+ * Enumeration of <em>x86</em> subregisters.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+enum
+{
+    QX86_SUBREG_NONE                    = 0,
+
+    QX86_SUBREG_BASE                    = 1,
+    QX86_SUBREG_LIMIT                   = 2,
+    QX86_SUBREG_FLAGS                   = 3,
+
+    QX86_SUBREG_COUNT                   = 4
+};
+
+
+/* Public API structures.  */
+
+
+/**
+ * Addressing mode definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_amode
+{
+    QX86_CONST char *                   referenceName;
+    QX86_CONST char *                   name;
+
+    qx86_uint8                          modrmField;
+    qx86_uint8                          rclass;
+
+    int                                 (*decodeFunc)(qx86_insn *, int);
+};
+
+
+
+/**
+ * Callback function definition.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+typedef int                             (*qx86_callback)(void *data, int rindex, int subreg, unsigned char *value);
+
+
+
+/**
+ * Decode context structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_ctx
+{
+    qx86_uint8 *                        ptr;
+    int                                 ptrSize;
+
+    int                                 pumpIndex;
+};
+
+
+
+
+
+/**
+ * Instruction attributes definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_insn_attributes
+{
+    qx86_uint8                          addressSize;
+    qx86_uint8                          addressSizeOverridden;
+
+    qx86_uint8                          operandSize;
+    qx86_uint8                          operandSizeOverridden;
+
+    qx86_uint8                          interlocked;
+};
+
+
+
+/**
+ * Instruction modifiers definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_insn_modifiers
+{
+    qx86_uint8                          modrm;
+    qx86_int8                           modrmIndex;
+
+    qx86_uint8                          sib;
+    qx86_int8                           sibIndex;
+
+    qx86_uint8                          rex;
+    qx86_int8                           rexIndex;
+
+    qx86_uint8                          prefixSize;
+
+    qx86_uint8                          escape;
+    qx86_uint8                          opcodePrefix;
+
+    /* XXX: values 0x00, 0xF2, 0xF3.  */
+    qx86_uint8                          repeatPrefix;
+
+    int                                 sriOverride;
+
+    qx86_uint8                          extendedB;
+    qx86_uint8                          extendedR;
+    qx86_uint8                          extendedX;
+};
+
+
+
+
+
+
+
+/**
+ * Far pointer instruction operand definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_operand_far_pointer
+{
+    qx86_uint8                          offset[QX86_IMMEDIATE_SIZE_MAX];
+    qx86_uint8                          offsetSize;
+
+    qx86_uint8                          selector[2];
+};
+
+
+
+/**
+ * Immediate instruction operand definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_operand_immediate
+{
+    qx86_uint8                          value[QX86_IMMEDIATE_SIZE_MAX];
+    qx86_uint8                          valueSize;
+};
+
+
+
+/**
+ * Jump offset instruction operand definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_operand_jump_offset
+{
+    qx86_uint8                          offset[QX86_IMMEDIATE_SIZE_MAX];
+    qx86_uint8                          offsetSize;
+};
+
+
+
+/**
+ * Memory instruction operand definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_operand_memory
+{
+    int                                 sri;
+    int                                 bri;
+    int                                 iri;
+
+    int                                 scale;
+
+    qx86_uint8                          disp[QX86_IMMEDIATE_SIZE_MAX];
+    qx86_uint8                          dispSize;
+};
+
+
+
+/**
+ * Register instruction operand definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_operand_register
+{
+    int                                 rindex;
+};
+
+
+/**
+ * Instruction operand definition union.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+union qx86_operand_union
+{
+    qx86_operand_far_pointer            f;
+    qx86_operand_immediate              i;
+    qx86_operand_jump_offset            j;
+    qx86_operand_memory                 m;
+    qx86_operand_register               r;
+};
+
+
+/**
+ * Instruction operand definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_operand
+{
+    qx86_uint8                          ot;
+
+    int                                 attributes;
+    int                                 size;
+
+    qx86_operand_union                  u;
+};
+
+
+/**
+ * Instruction definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_insn
+{
+    qx86_uint8                          rawSize;
+    qx86_uint8                          raw[QX86_INSN_SIZE_MAX];
+
+    int                                 processorMode;
+
+    int                                 mnemonic;
+    qx86_int8                           operandCount;
+
+    qx86_operand                        operands[QX86_OPERAND_NMAX];
+    qx86_operand_form *                 operandForms[QX86_OPERAND_NMAX];
+
+    qx86_insn_attributes                attributes;
+    qx86_insn_modifiers                 modifiers;
+
+    qx86_uint8                          iclass;
+    qx86_uint8                          defects;
+
+    qx86_callback                       callback;
+    void *                              data;
+};
+
+
+
+/**
+ * Mnemonic table item definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_mtab_item
+{
+    QX86_CONST char *                   referenceName;
+    QX86_CONST char *                   name;
+
+    qx86_uint8                          attributes;
+    qx86_uint8                          iclass;
+
+    int                                 demoted;
+    int                                 promoted;
+
+    // TODO: AT&T print.
+};
+
+
+
+/**
+ * Opcode map definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_opcode_map
+{
+    qx86_uint8                          index;
+    qx86_uint8                          limit;
+
+    qx86_opcode_map_item *              items;
+};
+
+
+
+
+
+
+
+
+
+/**
+ * Addressing mode instruction operand form definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_operand_form_amode
+{
+    qx86_amode *                        amode;
+    qx86_stuple *                       stuple;
+};
+
+
+
+/**
+ * Register tuple instruction operand form definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_operand_form_rtuple
+{
+    qx86_rtuple *                       rtuple;
+};
+
+
+/**
+ * Instruction operand form definition union.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+union qx86_operand_form_union
+{
+    QX86_CONST void *                   initializer[2];
+
+    qx86_operand_form_amode             a;
+    qx86_operand_form_rtuple            r;
+};
+
+
+/**
+ * Instruction operand form definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_operand_form
+{
+    int                                 ft;
+    int                                 attributes;
+    qx86_operand_form_union             u;
+};
+
+
+/**
+ * Opcode map item definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_opcode_map_item
+{
+    int                                 code;
+    qx86_opcode_map *                   link;
+
+    int                                 operandCount;
+    qx86_operand_form                   operandForms[QX86_OPERAND_NMAX];
+};
+
+
+
+/**
+ * Print item definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_print_item
+{
+    QX86_CONST qx86_uint8 *             number;
+    int                                 numberSize;
+
+    QX86_CONST char *                   string;
+};
+
+
+
+/**
+ * Intel print options structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_print_options_intel
+{
+    int                                 flipCase : 1;
+};
+
+
+
+/**
+ * Register table item definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_rtab_item
+{
+    QX86_CONST char *                   referenceName;
+    QX86_CONST char *                   name;
+
+    qx86_uint8                          rclass;
+    qx86_uint8                          size;
+};
+
+
+
+/**
+ * Register tuple definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_rtuple
+{
+    QX86_CONST char *                   referenceName;
+    QX86_CONST char *                   name;
+
+    int                                 rindexes[12];
+};
+
+
+
+/**
+ * Size tuple definition structure.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+struct qx86_stuple
+{
+    QX86_CONST char *                   referenceName;
+    QX86_CONST char *                   name;
+
+    QX86_CONST char *                   atoms[4];
+    int                                 sizes[4];
+};
+
+
+/**
+ * Extract the <em>mod</em> ModRM field value.
+ *
+ * \param                               modrm
+ *                                      ModRM octet value.
+ *
+ * \return                              ModRM <em>mod</em> field value.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+#define QX86_MODRM_MOD(modrm)           ((qx86_uint8) ((modrm) >> 6))
+
+/**
+ * Extract the <em>reg</em> ModRM field value.
+ *
+ * \param                               modrm
+ *                                      ModRM octet value.
+ *
+ * \return                              ModRM <em>reg</em> field value.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+#define QX86_MODRM_REG(modrm)           ((qx86_uint8) (((modrm) >> 3) & 7))
+
+/**
+ * Extract the <em>r/m</em> ModRM field value.
+ *
+ * \param                               modrm
+ *                                      ModRM octet value.
+ *
+ * \return                              ModRM <em>rm</em> field value.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+#define QX86_MODRM_RM(modrm)            ((qx86_uint8) ((modrm) & 7))
+
+/**
+ * Extract the <em>b</em> REX field value.
+ *
+ * \param                               rex
+ *                                      REX octet value.
+ *
+ * \return                              REX <em>b</em> field value.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+#define QX86_REX_B(rex)                 ((qx86_uint8) (0 != ((rex) & 1)))
+
+/**
+ * Extract the <em>r</em> REX field value.
+ *
+ * \param                               rex
+ *                                      REX octet value.
+ *
+ * \return                              REX <em>r</em> field value.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+#define QX86_REX_R(rex)                 ((qx86_uint8) (0 != ((rex) & 4)))
+
+/**
+ * Extract the <em>w</em> REX field value.
+ *
+ * \param                               rex
+ *                                      REX octet value.
+ *
+ * \return                              REX <em>w</em> field value.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+#define QX86_REX_W(rex)                 ((qx86_uint8) (0 != ((rex) & 8)))
+
+/**
+ * Extract the <em>x</em> REX field value.
+ *
+ * \param                               rex
+ *                                      REX octet value.
+ *
+ * \return                              REX <em>x</em> field value.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+#define QX86_REX_X(rex)                 ((qx86_uint8) (0 != ((rex) & 2)))
+
+/**
+ * Extract the <em>base</em> SIB field value.
+ *
+ * \param                               sib
+ *                                      SIB octet value.
+ *
+ * \return                              SIB <em>base</em> field value.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+#define QX86_SIB_BASE(sib)              ((qx86_uint8) ((sib) & 7))
+
+/**
+ * Extract the <em>index</em> SIB field value.
+ *
+ * \param                               sib
+ *                                      SIB octet value.
+ *
+ * \return                              SIB <em>index</em> field value.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+#define QX86_SIB_INDEX(sib)             ((qx86_uint8) (((sib) >> 3) & 7))
+
+/**
+ * Extract the <em>scale</em> SIB field value.
+ *
+ * \param                               sib
+ *                                      SIB octet value.
+ *
+ * \return                              SIB <em>scale</em> field value.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+#define QX86_SIB_SCALE(sib)             ((qx86_uint8) ((sib) >> 6))
+
+/**
+ * Convert a #qx86_size enumerator to number of octets.  The \a size value must
+ * be valid.
+ *
+ * \param                               size
+ *                                      A #qx86_size enumerator.
+ *
+ * \return                              Number of octets.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+#define QX86_SIZE_OCTETS(size)          (2 << (size))
+
+/* XXX XXX XXX */
+extern QX86_CONST qx86_mtab_item        qx86_mtab[QX86_MNEMONIC_COUNT];
+extern QX86_CONST qx86_rtab_item        qx86_rtab[QX86_REGISTER_COUNT];
+
+/**
+ * Calculate effective address of an <em>x86</em> memory operand.
+ *
+ * TODO: documentation.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+QX86_EXTERN_C int
+qx86_calculate_effective_address(QX86_CONST qx86_insn *insn, int operandIndex, qx86_uint64 *address);
+
+/**
+ * Calculate linear address of an <em>x86</em> memory operand.
+ *
+ * TODO: documentation.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+QX86_EXTERN_C int
+qx86_calculate_linear_address(QX86_CONST qx86_insn *insn, int operandIndex, qx86_uint64 *address);
+
+/**
+ * Decode an <em>x86</em> instruction.
+ *
+ * TODO: documentation.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+QX86_EXTERN_C int
+qx86_decode(qx86_insn *insn, int processorMode, QX86_CONST void *ptr, int ptrSize);
+
+/**
+ * Print a decoded <em>x86</em> instruction using the Intel format.
+ *
+ * TODO: documentation.
+ *
+ * \param                               insn
+ *                                      Instruction to print.
+ * \param                               options
+ *                                      Printer options.
+ * \param[out]                          buffer
+ *                                      Pre-allocated buffer to print to.
+ * \param[in,out]                       bufferSize
+ *                                      TODO.
+ *
+ * \return                              TODO.
+ *
+ * \author                              icee
+ * \since                               1.0
+ */
+QX86_EXTERN_C int
+qx86_print_intel(QX86_CONST qx86_insn *insn, QX86_CONST qx86_print_options_intel *options, char *buffer, int *bufferSize);
+
+#endif
index 2579781..1f9fb68 100644 (file)
@@ -1,4 +1,8 @@
 obj-y := null.o
 
 obj-$(V3_CONFIG_XED) :=        libxed.a \
-                       v3-xed-compat.o 
+                       v3-xed-compat.o
+
+obj-$(V3_CONFIG_QUIX86) := libquix86.a
+
+obj-$(V3_CONFIG_QUIX86_DEBUG) := libquix86_debug.a
diff --git a/palacios/lib/i386/libquix86.a b/palacios/lib/i386/libquix86.a
new file mode 100644 (file)
index 0000000..f5e0b2d
Binary files /dev/null and b/palacios/lib/i386/libquix86.a differ
diff --git a/palacios/lib/i386/libquix86_debug.a b/palacios/lib/i386/libquix86_debug.a
new file mode 100644 (file)
index 0000000..0aa7b1e
Binary files /dev/null and b/palacios/lib/i386/libquix86_debug.a differ
index 8853e97..84ddcc5 100644 (file)
@@ -2,3 +2,7 @@ obj-y := null.o
 
 obj-$(V3_CONFIG_XED) :=        libxed32e.a \
                                v3-xed-compat.o
+
+obj-$(V3_CONFIG_QUIX86) := libquix86.a
+
+obj-$(V3_CONFIG_QUIX86_DEBUG) := libquix86_debug.a
diff --git a/palacios/lib/x86_64/libquix86.a b/palacios/lib/x86_64/libquix86.a
new file mode 100644 (file)
index 0000000..441db57
Binary files /dev/null and b/palacios/lib/x86_64/libquix86.a differ
diff --git a/palacios/lib/x86_64/libquix86_debug.a b/palacios/lib/x86_64/libquix86_debug.a
new file mode 100644 (file)
index 0000000..6dfa9b5
Binary files /dev/null and b/palacios/lib/x86_64/libquix86_debug.a differ
index 3fe3743..d99275e 100644 (file)
@@ -612,8 +612,10 @@ static int inp_status1_read(struct guest_info * core, uint16_t port, void * dest
 
     /* next write to attrc selects the index rather than data */
     video_state->attrc_index_flipflop = 0;
+    memset(dest, 0x0, length);
 
-    return notimpl_port_read(priv_data, __FUNCTION__, port, dest, length);
+    handle_port_read(priv_data, __FUNCTION__, port, dest, length, 1);
+    return length;
 }
 
 static int feat_ctrl_read(struct guest_info * core, uint16_t port, void * dest, uint_t length, void * priv_data) {
index f5baf95..285e534 100644 (file)
@@ -737,8 +737,8 @@ static int write_dma_port(struct guest_info * core, ushort_t port, void * src, u
            break;
        }
        default:
-           PrintError("IDE: Invalid DMA Port (%s)\n", dma_port_to_str(port_offset));
-           return -1;
+           PrintError("IDE: Invalid DMA Port (%d) (%s)\n", port, dma_port_to_str(port_offset));
+           break;
     }
 
     return length;
@@ -787,8 +787,8 @@ static int read_dma_port(struct guest_info * core, ushort_t port, void * dst, ui
            break;
        }
        default:
-           PrintError("IDE: Invalid DMA Port (%s)\n", dma_port_to_str(port_offset));
-           return -1;
+           PrintError("IDE: Invalid DMA Port (%d) (%s)\n", port, dma_port_to_str(port_offset));
+           break;
     }
 
     PrintDebug("\tval=%x (len=%d)\n", *(uint32_t *)dst, length);
index 14a1c29..af67c65 100644 (file)
@@ -41,6 +41,9 @@ obj-y := \
 
 obj-$(V3_CONFIG_XED) +=        vmm_xed.o
 obj-$(V3_CONFIG_V3_DECODER) += vmm_v3dec.o
+obj-$(V3_CONFIG_QUIX86) += vmm_quix86.o
+obj-$(V3_CONFIG_QUIX86_DEBUG) += vmm_quix86.o
+
 
 obj-$(V3_CONFIG_SVM) +=    svm.o \
                           svm_io.o \
index 2ffcfac..b90f4a0 100644 (file)
@@ -57,15 +57,20 @@ static int update_map(struct v3_vm_info * vm, uint_t msr, int hook_reads, int ho
     int index = get_bitmap_index(msr);
     uint_t major = index / 4;
     uint_t minor = (index % 4) * 2;
-    uchar_t val = 0;
-    uchar_t mask = 0x3;
+    uint8_t val = 0;
+    uint8_t mask = 0x3;
     uint8_t * bitmap = (uint8_t *)(vm->msr_map.arch_data);
 
-    if (hook_reads) {
+    if (index == -1) {
+       PrintError("MSR (0x%x) out of bitmap range\n", msr);
+       return 0;
+    }
+
+    if (hook_reads != 0) {
        val |= 0x1;
     } 
     
-    if (hook_writes) {
+    if (hook_writes != 0) {
        val |= 0x2;
     }
 
index 72f980c..df30d1d 100644 (file)
@@ -38,14 +38,14 @@ v3_cpu_mode_t v3_get_vm_cpu_mode(struct guest_info * info) {
     struct efer_64 * efer;
     struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
     struct v3_segment * cs = &(info->segments.cs);
-    vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
+
 
     if (info->shdw_pg_mode == SHADOW_PAGING) {
        cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
        efer = (struct efer_64 *)&(info->shdw_pg_state.guest_efer);
     } else if (info->shdw_pg_mode == NESTED_PAGING) {
        cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
-       efer = (struct efer_64 *)&(guest_state->efer);
+       efer = (struct efer_64 *)&(info->ctrl_regs.efer);
     } else {
        PrintError("Invalid Paging Mode...\n");
        V3_ASSERT(0);
@@ -72,14 +72,14 @@ uint_t v3_get_addr_width(struct guest_info * info) {
     struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
     struct efer_64 * efer;
     struct v3_segment * cs = &(info->segments.cs);
-    vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
+
 
     if (info->shdw_pg_mode == SHADOW_PAGING) {
        cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
        efer = (struct efer_64 *)&(info->shdw_pg_state.guest_efer);
     } else if (info->shdw_pg_mode == NESTED_PAGING) {
        cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
-       efer = (struct efer_64 *)&(guest_state->efer);
+       efer = (struct efer_64 *)&(info->ctrl_regs.efer);
     } else {
        PrintError("Invalid Paging Mode...\n");
        V3_ASSERT(0);
@@ -243,18 +243,17 @@ void v3_print_ctrl_regs(struct guest_info * info) {
     struct v3_ctrl_regs * regs = &(info->ctrl_regs);
     int i = 0;
     v3_reg_t * reg_ptr;
-    char * reg_names[] = {"CR0", "CR2", "CR3", "CR4", "CR8", "FLAGS", NULL};
-    vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(info->vmm_data);
+    char * reg_names[] = {"CR0", "CR2", "CR3", "CR4", "CR8", "FLAGS", "EFER", NULL};
+   
 
     reg_ptr = (v3_reg_t *)regs;
 
-    V3_Print("32 bit Ctrl Regs:\n");
+    V3_Print("Ctrl Regs:\n");
 
     for (i = 0; reg_names[i] != NULL; i++) {
        V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
     }
 
-    V3_Print("\tEFER=0x%p\n", (void*)(addr_t)(guest_state->efer));
 
 }
 
@@ -488,7 +487,7 @@ void v3_print_GPRs(struct guest_info * info) {
 #include <palacios/vmcs.h>
 #include <palacios/vmcb.h>
 static int info_hcall(struct guest_info * core, uint_t hcall_id, void * priv_data) {
-    v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+    extern v3_cpu_arch_t v3_mach_type;
     int cpu_valid = 0;
 
     V3_Print("************** Guest State ************\n");
@@ -496,19 +495,19 @@ static int info_hcall(struct guest_info * core, uint_t hcall_id, void * priv_dat
     
     // init SVM/VMX
 #ifdef V3_CONFIG_SVM
-    if ((cpu_type == V3_SVM_CPU) || (cpu_type == V3_SVM_REV3_CPU)) {
+    if ((v3_mach_type == V3_SVM_CPU) || (v3_mach_type == V3_SVM_REV3_CPU)) {
        cpu_valid = 1;
        PrintDebugVMCB((vmcb_t *)(core->vmm_data));
     }
 #endif
 #ifdef V3_CONFIG_VMX
-    if ((cpu_type == V3_VMX_CPU) || (cpu_type == V3_VMX_EPT_CPU) || (cpu_type == V3_VMX_EPT_UG_CPU)) {
+    if ((v3_mach_type == V3_VMX_CPU) || (v3_mach_type == V3_VMX_EPT_CPU) || (v3_mach_type == V3_VMX_EPT_UG_CPU)) {
        cpu_valid = 1;
        v3_print_vmcs();
     }
 #endif
     if (!cpu_valid) {
-       PrintError("Invalid CPU Type 0x%x\n", cpu_type);
+       PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
        return -1;
     }
     
@@ -531,7 +530,7 @@ static int info_hcall(struct guest_info * core, uint_t hcall_id, void * priv_dat
 
 
 int v3_init_vm(struct v3_vm_info * vm) {
-    v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+    extern v3_cpu_arch_t v3_mach_type;
 
 
 
@@ -574,7 +573,7 @@ int v3_init_vm(struct v3_vm_info * vm) {
 
 
     // init SVM/VMX
-    switch (cpu_type) {
+    switch (v3_mach_type) {
 #ifdef V3_CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
@@ -591,7 +590,7 @@ int v3_init_vm(struct v3_vm_info * vm) {
            break;
 #endif
        default:
-           PrintError("Invalid CPU Type 0x%x\n", cpu_type);
+           PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
            return -1;
     }
     
@@ -604,7 +603,7 @@ int v3_init_vm(struct v3_vm_info * vm) {
 
 
 int v3_free_vm_internal(struct v3_vm_info * vm) {
-    v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+    extern v3_cpu_arch_t v3_mach_type;
 
     v3_remove_hypercall(vm, GUEST_INFO_HCALL);
 
@@ -615,7 +614,7 @@ int v3_free_vm_internal(struct v3_vm_info * vm) {
 #endif
 
     // init SVM/VMX
-    switch (cpu_type) {
+    switch (v3_mach_type) {
 #ifdef V3_CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
@@ -632,7 +631,7 @@ int v3_free_vm_internal(struct v3_vm_info * vm) {
            break;
 #endif
        default:
-           PrintError("Invalid CPU Type 0x%x\n", cpu_type);
+           PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
            return -1;
     }
 
@@ -665,7 +664,7 @@ int v3_free_vm_internal(struct v3_vm_info * vm) {
 
 
 int v3_init_core(struct guest_info * core) {
-    v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+    extern v3_cpu_arch_t v3_mach_type;
     struct v3_vm_info * vm = core->vm_info;
 
 
@@ -695,7 +694,7 @@ int v3_init_core(struct guest_info * core) {
     // init SVM/VMX
 
 
-    switch (cpu_type) {
+    switch (v3_mach_type) {
 #ifdef V3_CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
@@ -716,7 +715,7 @@ int v3_init_core(struct guest_info * core) {
            break;
 #endif
        default:
-           PrintError("Invalid CPU Type 0x%x\n", cpu_type);
+           PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
            return -1;
     }
 
@@ -726,7 +725,7 @@ int v3_init_core(struct guest_info * core) {
 
 
 int v3_free_core(struct guest_info * core) {
-    v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+    extern v3_cpu_arch_t v3_mach_type;
 
     
 #ifdef V3_CONFIG_SYMBIOTIC
@@ -748,7 +747,7 @@ int v3_free_core(struct guest_info * core) {
     v3_deinit_core_telemetry(core);
 #endif
 
-    switch (cpu_type) {
+    switch (v3_mach_type) {
 #ifdef V3_CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
@@ -769,7 +768,7 @@ int v3_free_core(struct guest_info * core) {
            break;
 #endif
        default:
-           PrintError("Invalid CPU Type 0x%x\n", cpu_type);
+           PrintError("Invalid CPU Type 0x%x\n", v3_mach_type);
            return -1;
     }
 
index 8fb4080..e28029e 100644 (file)
@@ -234,6 +234,7 @@ int v3_vmx_save_vmcs(struct guest_info * info) {
 
 #ifdef __V3_64BIT__
     check_vmcs_read(VMCS_GUEST_EFER, &(info->ctrl_regs.efer));
+    check_vmcs_read(VMCS_ENTRY_CTRLS, &(vmx_info->entry_ctrls.value));
 #endif
     
     error =  v3_read_vmcs_segments(&(info->segments));
@@ -263,9 +264,6 @@ int v3_vmx_restore_vmcs(struct guest_info * info) {
     check_vmcs_write(VMCS_ENTRY_CTRLS, vmx_info->entry_ctrls.value);
 #endif
 
-
-
-
     error = v3_write_vmcs_segments(&(info->segments));
 
     return error;
@@ -487,6 +485,9 @@ int v3_update_vmcs_host_state(struct guest_info * info) {
 
     // PAT
 
+    v3_get_msr(IA32_PAT_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
+    vmx_ret |= check_vmcs_write(VMCS_HOST_PAT, tmp_msr.value);  
+
 
     // save STAR, LSTAR, FMASK, KERNEL_GS_BASE MSRs in MSR load/store area
     {
index fe9a071..218c68d 100644 (file)
@@ -39,6 +39,8 @@
 
 
 v3_cpu_arch_t v3_cpu_types[V3_CONFIG_MAX_CPUS];
+v3_cpu_arch_t v3_mach_type = V3_INVALID_CPU;
+
 struct v3_os_hooks * os_hooks = NULL;
 int v3_dbg_enable = 0;
 
@@ -105,6 +107,9 @@ void Init_V3(struct v3_os_hooks * hooks, int num_cpus) {
     // Set global variables. 
     os_hooks = hooks;
 
+    // Determine the global machine type
+    v3_mach_type = V3_INVALID_CPU;
+
     for (i = 0; i < V3_CONFIG_MAX_CPUS; i++) {
        v3_cpu_types[i] = V3_INVALID_CPU;
     }
@@ -131,11 +136,15 @@ void Init_V3(struct v3_os_hooks * hooks, int num_cpus) {
 
 
     if ((hooks) && (hooks->call_on_cpu)) {
-
        for (i = 0; i < num_cpus; i++) {
 
            V3_Print("Initializing VMM extensions on cpu %d\n", i);
            hooks->call_on_cpu(i, &init_cpu, (void *)(addr_t)i);
+
+           if (v3_mach_type == V3_INVALID_CPU) {
+               v3_mach_type = v3_cpu_types[i];
+           }
+
        }
     }
 
@@ -210,7 +219,7 @@ static int start_core(void * p)
     PrintDebug("virtual core %u (on logical core %u): in start_core (RIP=%p)\n", 
               core->vcpu_id, core->pcpu_id, (void *)(addr_t)core->rip);
 
-    switch (v3_cpu_types[0]) {
+    switch (v3_mach_type) {
 #ifdef V3_CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
@@ -628,7 +637,7 @@ void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu, int vector) {
 
 
 int v3_vm_enter(struct guest_info * info) {
-    switch (v3_cpu_types[0]) {
+    switch (v3_mach_type) {
 #ifdef V3_CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
index 3258779..5ba96ac 100644 (file)
@@ -237,12 +237,12 @@ static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
 }
 
 int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
-    v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+    extern v3_cpu_arch_t v3_mach_type;
     void * ctx = NULL;
     
     ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
 
-    switch (cpu_type) {
+    switch (v3_mach_type) {
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU: {
            v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header);
@@ -266,12 +266,12 @@ int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
 }
 
 static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
-    v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+    extern v3_cpu_arch_t v3_mach_type;
     void * ctx = NULL;
     
     ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
 
-    switch (cpu_type) {
+    switch (v3_mach_type) {
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU: {
            char header[strlen(svm_chkpt_header) + 1];
@@ -302,7 +302,7 @@ static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
 
 
 static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
-    v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+    extern v3_cpu_arch_t v3_mach_type;
     void * ctx = NULL;
     char key_name[16];
     memset(key_name, 0, 16);
@@ -349,7 +349,7 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
     }
 
 
-    switch (cpu_type) {
+    switch (v3_mach_type) {
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU: {
            char key_name[16];
@@ -384,7 +384,7 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
            break;
        }
        default:
-           PrintError("Invalid CPU Type (%d)\n", cpu_type);
+           PrintError("Invalid CPU Type (%d)\n", v3_mach_type);
            return -1;
     }
 
@@ -395,7 +395,7 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
 
 
 static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
-    v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+    extern v3_cpu_arch_t v3_mach_type;
     void * ctx = NULL;
     char key_name[16];
 
@@ -428,7 +428,7 @@ static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
     v3_chkpt_close_ctx(ctx);
 
     //Architechture specific code
-    switch (cpu_type) {
+    switch (v3_mach_type) {
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU: {
            char key_name[16];
@@ -468,7 +468,7 @@ static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
            break;
        }
        default:
-           PrintError("Invalid CPU Type (%d)\n", cpu_type);
+           PrintError("Invalid CPU Type (%d)\n", v3_mach_type);
            return -1;
     }
     
index 8d348e6..de882d0 100644 (file)
@@ -280,7 +280,7 @@ static int pre_config_vm(struct v3_vm_info * vm, v3_cfg_tree_t * vm_cfg) {
 
 
 static int determine_paging_mode(struct guest_info * info, v3_cfg_tree_t * core_cfg) {
-    extern v3_cpu_arch_t v3_cpu_types[];
+    extern v3_cpu_arch_t v3_mach_type;
 
     v3_cfg_tree_t * vm_tree = info->vm_info->cfg_data->cfg;
     v3_cfg_tree_t * pg_tree = v3_cfg_subtree(vm_tree, "paging");
@@ -291,9 +291,9 @@ static int determine_paging_mode(struct guest_info * info, v3_cfg_tree_t * core_
     if (pg_mode) {
        if ((strcasecmp(pg_mode, "nested") == 0)) {
            // we assume symmetric cores, so if core 0 has nested paging they all do
-           if ((v3_cpu_types[0] == V3_SVM_REV3_CPU) || 
-               (v3_cpu_types[0] == V3_VMX_EPT_CPU) ||
-               (v3_cpu_types[0] == V3_VMX_EPT_UG_CPU)) {
+           if ((v3_mach_type == V3_SVM_REV3_CPU) || 
+               (v3_mach_type == V3_VMX_EPT_CPU) ||
+               (v3_mach_type  == V3_VMX_EPT_UG_CPU)) {
                info->shdw_pg_mode = NESTED_PAGING;
            } else {
                PrintError("Nested paging not supported on this hardware. Defaulting to shadow paging\n");
@@ -432,7 +432,7 @@ static struct v3_vm_info * allocate_guest(int num_cores) {
 
 
 struct v3_vm_info * v3_config_guest(void * cfg_blob, void * priv_data) {
-    v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+    extern v3_cpu_arch_t v3_mach_type;
     struct v3_config * cfg_data = NULL;
     struct v3_vm_info * vm = NULL;
     int num_cores = 0;
@@ -440,7 +440,7 @@ struct v3_vm_info * v3_config_guest(void * cfg_blob, void * priv_data) {
     v3_cfg_tree_t * cores_cfg = NULL;
     v3_cfg_tree_t * per_core_cfg = NULL;
 
-    if (cpu_type == V3_INVALID_CPU) {
+    if (v3_mach_type == V3_INVALID_CPU) {
        PrintError("Configuring guest on invalid CPU\n");
        return NULL;
     }
index 3616ae8..7bc0f0b 100644 (file)
@@ -430,7 +430,7 @@ int v3_handle_cr3_read(struct guest_info * info) {
 
 // We don't need to virtualize CR4, all we need is to detect the activation of PAE
 int v3_handle_cr4_read(struct guest_info * info) {
-    //  PrintError("CR4 Read not handled\n");
+    PrintError("CR4 Read not handled\n");
     // Do nothing...
     return 0;
 }
@@ -460,6 +460,7 @@ int v3_handle_cr4_write(struct guest_info * info) {
     
     // Check to see if we need to flush the tlb
     
+
     if (v3_get_vm_mem_mode(info) == VIRTUAL_MEM) { 
        struct cr4_32 * new_cr4 = (struct cr4_32 *)(dec_instr.src_operand.operand);
        struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
@@ -533,16 +534,16 @@ int v3_handle_cr4_write(struct guest_info * info) {
        return -1;
     }
     
-    
-    if (flush_tlb) {
-       PrintDebug("Handling PSE/PGE/PAE -> TLBFlush (doing flush now!)\n");
-       if (v3_activate_shadow_pt(info) == -1) {
-           PrintError("Failed to activate shadow page tables when emulating TLB flush in handling cr4 write\n");
-           return -1;
+    if (info->shdw_pg_mode == SHADOW_PAGING) {
+       if (flush_tlb) {
+           PrintDebug("Handling PSE/PGE/PAE -> TLBFlush (doing flush now!)\n");
+           if (v3_activate_shadow_pt(info) == -1) {
+               PrintError("Failed to activate shadow page tables when emulating TLB flush in handling cr4 write\n");
+               return -1;
+           }
        }
     }
     
-    
     info->rip += dec_instr.instr_length;
     return 0;
 }
@@ -588,6 +589,11 @@ int v3_handle_efer_write(struct guest_info * core, uint_t msr, struct v3_msr src
        hw_efer->lma = 1;
     }
 
+
+    PrintDebug("RIP=%p\n", (void *)core->rip);
+    PrintDebug("New EFER value HW(hi=%p), VM(hi=%p)\n", (void *)*(uint64_t *)hw_efer, (void *)vm_efer->value); 
+
+
     return 0;
 }
 
index dd262c0..3753a93 100644 (file)
@@ -117,8 +117,14 @@ void v3_delete_mem_map(struct v3_vm_info * vm) {
 
 struct v3_mem_region * v3_create_mem_region(struct v3_vm_info * vm, uint16_t core_id, 
                                               addr_t guest_addr_start, addr_t guest_addr_end) {
-    
-    struct v3_mem_region * entry = (struct v3_mem_region *)V3_Malloc(sizeof(struct v3_mem_region));
+    struct v3_mem_region * entry = NULL;
+
+    if (guest_addr_start >= guest_addr_end) {
+       PrintError("Region start is after region end\n");
+       return NULL;
+    }
+
+    entry = (struct v3_mem_region *)V3_Malloc(sizeof(struct v3_mem_region));
     memset(entry, 0, sizeof(struct v3_mem_region));
 
     entry->guest_start = guest_addr_start;
index a0753cf..98aabdc 100644 (file)
@@ -240,6 +240,11 @@ static int handle_mem_hook(struct guest_info * core, addr_t guest_va, addr_t gue
 
     mem_op_size = ((uint_t)src_req_size < (uint_t)dst_req_size) ? src_req_size : dst_req_size;
 
+    if (mem_op_size == -1) {
+       PrintError("Error: Did not detect any memory operands...\n");
+       return -1;
+    }
+
 
     /* Now handle the hooks if necessary */    
     if ( (src_hook != NULL)  && (src_hook->read != NULL) &&
index bd682a6..b960187 100644 (file)
@@ -109,7 +109,9 @@ int v3_handle_msr_read(struct guest_info * info) {
 
 int v3_msr_unhandled_read(struct guest_info * core, uint32_t msr, struct v3_msr * dst, void * priv_data) {
     V3_Print("Palacios: Unhandled MSR Read (MSR=0x%x) - returning zero\n", msr);
-    dst->lo=dst->hi=0;
+
+    dst->value = 0;
+
     // should produce GPF for unsupported msr
     return 0;
 }
diff --git a/palacios/src/palacios/vmm_quix86.c b/palacios/src/palacios/vmm_quix86.c
new file mode 100644 (file)
index 0000000..480955a
--- /dev/null
@@ -0,0 +1,952 @@
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2012,  Alexander Kudryavtsev <alexk@ispras.ru>
+ * Copyright (c) 2012, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Alexander Kudryavtsev <alexk@ispras.ru>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+#include <palacios/vm_guest.h>
+#include <palacios/vmm_mem_hook.h>
+#include <palacios/vmm_emulator.h>
+#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_hashtable.h>
+#include <palacios/vmm_decoder.h>
+
+#include <quix86/quix86.h>
+
+#ifndef V3_CONFIG_DEBUG_DECODER
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
+#define GPR_REGISTER     0
+#define SEGMENT_REGISTER 1
+#define CTRL_REGISTER    2
+#define DEBUG_REGISTER   3
+
+// QUIX86 does not have to be initialised or deinitialised.
+int v3_init_decoder(struct guest_info * core) {
+    return 0;
+}
+int v3_deinit_decoder(struct guest_info * core) {
+    return 0;
+}
+
+static int get_opcode(qx86_insn *inst);
+static int qx86_register_to_v3_reg(struct guest_info * info, int qx86_reg,
+                 addr_t * v3_reg, uint_t * reg_len);
+
+static int decode_string_op(struct guest_info * core,
+                const qx86_insn * qx86_inst, struct x86_instr * instr)
+{
+    int status = 0;
+    PrintDebug("String operation\n");
+
+    if (instr->prefixes.rep == 1) {
+        uint64_t a_mask = ~(~0ULL <<
+                (QX86_SIZE_OCTETS(qx86_inst->attributes.addressSize) * 8));
+
+        instr->str_op_length = core->vm_regs.rcx & a_mask;
+    } else {
+        instr->str_op_length = 1;
+    }
+
+
+
+    if (instr->op_type == V3_OP_MOVS) {
+        instr->num_operands = 2;
+
+        if((status = qx86_calculate_linear_address(qx86_inst, 0,
+                (qx86_uint64*)&instr->dst_operand.operand)) != QX86_SUCCESS) {
+            PrintError("Could not get destination memory operand: "
+                    "qx86_calculate_linear_address: %d\n", status);
+            return -1;
+        }
+
+       instr->dst_operand.type = MEM_OPERAND;
+       instr->dst_operand.size = qx86_inst->operands[0].size;
+
+
+        if((status = qx86_calculate_linear_address(qx86_inst, 1,
+                (qx86_uint64*)&instr->src_operand.operand)) != QX86_SUCCESS) {
+            PrintError("Could not get source memory operand: "
+                    "qx86_calculate_linear_address: %d\n", status);
+            return -1;
+        }
+
+       instr->src_operand.type = MEM_OPERAND;
+       instr->src_operand.size = qx86_inst->operands[1].size;
+
+        instr->dst_operand.write = 1;
+        instr->src_operand.read = 1;
+
+
+    } else if (instr->op_type == V3_OP_STOS) {
+        instr->num_operands = 2;
+
+        if((status = qx86_calculate_linear_address(qx86_inst, 0,
+                (qx86_uint64*)&instr->dst_operand.operand)) != QX86_SUCCESS) {
+            PrintError("Could not get destination memory operand: "
+                    "qx86_calculate_linear_address: %d\n", status);
+            return -1;
+        }
+
+       instr->dst_operand.type = MEM_OPERAND;
+       instr->dst_operand.size = qx86_inst->operands[0].size;
+
+        // STOS reads from rax
+        qx86_register_to_v3_reg(core,
+            qx86_inst->operands[1].u.r.rindex,
+            &(instr->src_operand.operand), &(instr->src_operand.size));
+        instr->src_operand.type = REG_OPERAND;
+
+        instr->src_operand.read = 1;
+        instr->dst_operand.write = 1;
+
+
+
+    } else {
+        PrintError("Unhandled String OP\n");
+        return -1;
+    }
+
+
+#ifdef V3_CONFIG_DEBUG_DECODER
+    V3_Print("Decoding Instr at %p\n", (void *)core->rip);
+    v3_print_instr(instr);
+    V3_Print("CS DB FLag=%x\n", core->segments.cs.db);
+#endif
+
+
+    return 0;
+}
+
+static int callback(void *data, int rindex, int subreg, unsigned char *value) {
+    void* reg_addr = 0;
+    uint_t reg_size;
+
+    struct guest_info *info = (struct guest_info*)data;
+    int v3_reg_type = qx86_register_to_v3_reg(info,
+        rindex,
+        (addr_t*)&reg_addr, &reg_size);
+
+    if(v3_reg_type == -1) {
+        PrintError("Callback failed to get register index %d\n", rindex);
+        return 0;
+    }
+
+    *(uint64_t*)value = 0;
+    switch(subreg) {
+    case QX86_SUBREG_BASE:
+        *(uint64_t*)value = ((struct v3_segment*)reg_addr)->base;
+        break;
+    case QX86_SUBREG_LIMIT:
+        *(uint32_t*)value = ((struct v3_segment*)reg_addr)->limit;
+        break;
+    case QX86_SUBREG_FLAGS:
+        PrintError("Callback doesn't know how to give flags.\n");
+        return 0;
+    case QX86_SUBREG_NONE: {
+        switch(qx86_rtab[rindex].size) {
+        case 1: *(uint8_t* )value = *(uint8_t* )reg_addr; break;
+        case 2: *(uint16_t*)value = *(uint16_t*)reg_addr; break;
+        case 4: *(uint32_t*)value = *(uint32_t*)reg_addr; break;
+        case 8: *(uint64_t*)value = *(uint64_t*)reg_addr; break;
+        }
+        break;
+    }
+    }
+
+    return 1;
+}
+
+static inline int qx86_op_to_v3_op(struct guest_info *info, qx86_insn *qx86_insn,
+        int op_num, struct x86_operand * v3_op) {
+    int status = 0;
+    qx86_operand *qx86_op = &qx86_insn->operands[op_num];
+    if (qx86_op->ot == QX86_OPERAND_TYPE_REGISTER) {
+        int v3_reg_type = qx86_register_to_v3_reg(info,
+                qx86_op->u.r.rindex,
+                &(v3_op->operand), &(v3_op->size));
+
+        if (v3_reg_type == -1) {
+            PrintError("Operand %d is an Unhandled Operand: %s\n", op_num,
+                    qx86_rtab[qx86_op->u.r.rindex].name);
+            v3_op->type = INVALID_OPERAND;
+            return -1;
+        } else if (v3_reg_type == SEGMENT_REGISTER) {
+            struct v3_segment * seg_reg = (struct v3_segment *)(v3_op->operand);
+            v3_op->operand = (addr_t)&(seg_reg->selector);
+        }
+        v3_op->type = REG_OPERAND;
+
+    } else if(qx86_op->ot == QX86_OPERAND_TYPE_MEMORY) {
+        PrintDebug("Memory operand (%d)\n", op_num);
+        if((status = qx86_calculate_linear_address(qx86_insn, op_num,
+                (qx86_uint64*)&v3_op->operand)) != QX86_SUCCESS) {
+            PrintError("Could not get memory operand %d: "
+                    "qx86_calculate_linear_address() returns %d\n", op_num, status);
+            return -1;
+        }
+        v3_op->type = MEM_OPERAND;
+        v3_op->size = qx86_op->size;
+
+    } else if(qx86_op->ot == QX86_OPERAND_TYPE_IMMEDIATE) {
+        v3_op->size = qx86_op->u.i.valueSize;
+
+        if (v3_op->size > 4) {
+            PrintError("Unhandled 64 bit immediates\n");
+            return -1;
+        }
+        v3_op->operand = (addr_t)*(uint64_t*)qx86_op->u.i.value;
+        v3_op->type = IMM_OPERAND;
+
+    } else {
+        PrintError("Unhandled Operand %d Type %d\n", op_num, qx86_op->ot);
+        return -1;
+    }
+
+    if (qx86_op->attributes & QX86_OPERAND_ATTRIBUTE_READ) {
+        v3_op->read = 1;
+    }
+    if (qx86_op->attributes & QX86_OPERAND_ATTRIBUTE_WRITTEN) {
+        v3_op->write = 1;
+    }
+    return 0;
+}
+
+int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr) {
+    int proc_mode;
+    qx86_insn qx86_inst;
+    uint8_t inst_buf[QX86_INSN_SIZE_MAX];
+
+    memset(instr, 0, sizeof(struct x86_instr));
+    memset(&qx86_inst, 0, sizeof(qx86_inst));
+
+    v3_get_prefixes((uchar_t *)instr_ptr, &(instr->prefixes));
+
+    switch(v3_get_vm_cpu_mode(info)) {
+    case REAL: case LONG_16_COMPAT:
+        proc_mode = QX86_SIZE_16; break;
+    case PROTECTED: case PROTECTED_PAE: case LONG_32_COMPAT:
+        proc_mode = QX86_SIZE_32; break;
+    case LONG:
+        proc_mode = QX86_SIZE_64; break;
+    default:
+        PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
+        return -1;
+    }
+
+    int left_in_page = 0x1000 - (instr_ptr & 0xfff);
+    if(left_in_page < QX86_INSN_SIZE_MAX) {
+        addr_t instr_ptr2;
+        int status = 0;
+
+        if (info->mem_mode == PHYSICAL_MEM) {
+            status = v3_gpa_to_hva(info, get_addr_linear(info,
+                    (info->rip & ~0xfffULL) + 0x1000, &(info->segments.cs)), &instr_ptr2);
+        } else {
+            status = v3_gva_to_hva(info, get_addr_linear(info,
+                    (info->rip & ~0xfffULL) + 0x1000, &(info->segments.cs)), &instr_ptr2);
+        }
+        if (status == -1) {
+            PrintError("Could not translate Instruction Address at second stage "
+                    "translation (%p)\n", (void *)(addr_t)info->rip);
+            return -1;
+        }
+
+        if(((instr_ptr & ~0xfffUL) + 0x1000) != instr_ptr2) {
+            PrintError("Note: physical page non-contiguous\n");
+            memcpy(inst_buf, (const void*)instr_ptr, left_in_page);
+            memcpy(inst_buf + left_in_page, (const void*)instr_ptr2,
+                    QX86_INSN_SIZE_MAX - left_in_page);
+            instr_ptr = (addr_t)inst_buf;
+        } // in other case, address space is contiguous and everything is OK
+    }
+
+    qx86_inst.callback = callback;
+    qx86_inst.data = info;
+
+    int status = qx86_decode(&qx86_inst, proc_mode,
+            (const void*)instr_ptr, QX86_INSN_SIZE_MAX);
+    if(status != QX86_SUCCESS) {
+        PrintError("qx86_decode() returned %d\n", status);
+        return -1;
+    }
+
+    instr->instr_length = qx86_inst.rawSize;
+
+    if ((instr->op_type = get_opcode(&qx86_inst)) == V3_INVALID_OP) {
+        PrintError("Could not get opcode. (mnemonic=%s)\n",
+                qx86_mtab[qx86_inst.mnemonic].name);
+        return -1;
+    }
+
+    if(instr->op_type == V3_OP_MOVS || instr->op_type == V3_OP_STOS) {
+        instr->is_str_op = 1;
+        return decode_string_op(info, &qx86_inst, instr);
+    } else {
+        instr->is_str_op = 0;
+        instr->str_op_length = 0;
+    }
+
+    instr->num_operands = qx86_inst.operandCount;
+
+    // set first operand
+    if (instr->num_operands >= 1) {
+        if (qx86_op_to_v3_op(info, &qx86_inst, 0, &instr->dst_operand) != 0)
+            return -1;
+    }
+
+    // set second operand
+    if (instr->num_operands >= 2) {
+        if (qx86_op_to_v3_op(info, &qx86_inst, 1, &instr->src_operand) != 0)
+            return -1;
+    }
+
+    // set third operand
+    if (instr->num_operands >= 3) {
+        if (qx86_op_to_v3_op(info, &qx86_inst, 2, &instr->third_operand) != 0)
+            return -1;
+    }
+
+#ifdef V3_CONFIG_DEBUG_DECODER
+    qx86_print_options_intel opt;
+    char buf[128];
+    int buf_sz = 128;
+    if(qx86_print_intel(&qx86_inst, &opt, buf, &buf_sz) != QX86_SUCCESS) {
+        PrintDebug("Print failed!\n");
+    } else {
+        PrintDebug("Instruction (%p): %s\n", (void*)info->rip, buf);
+    }
+    PrintDebug("Operands: dst %p src %p 3rd %p\n", (void*)instr->dst_operand.operand,
+            (void*)instr->src_operand.operand, (void*)instr->third_operand.operand);
+#endif
+    return 0;
+}
+
+static int get_opcode(qx86_insn *inst) {
+    switch (inst->mnemonic) {
+#define IS_CR(op) inst->operands[op].ot == QX86_OPERAND_TYPE_REGISTER && \
+    qx86_rtab[inst->operands[op].u.r.rindex].rclass == QX86_RCLASS_CREG
+
+    /* MOV cases */
+    case QX86_MNEMONIC_MOV: {
+        if(inst->operands[0].ot == QX86_OPERAND_TYPE_MEMORY
+                || inst->operands[1].ot == QX86_OPERAND_TYPE_MEMORY)
+            return V3_OP_MOV;
+        if(IS_CR(0))
+            return V3_OP_MOV2CR;
+        if(IS_CR(1))
+            return V3_OP_MOVCR2;
+
+        PrintError("Bad operand types for MOV: %d %d\n", inst->operands[0].ot,
+                inst->operands[1].ot);
+        return V3_INVALID_OP;
+    }
+
+    /* Control Instructions */
+    case QX86_MNEMONIC_SMSW:
+        return V3_OP_SMSW;
+
+    case QX86_MNEMONIC_LMSW:
+        return V3_OP_LMSW;
+
+    case QX86_MNEMONIC_CLTS:
+        return V3_OP_CLTS;
+
+    case QX86_MNEMONIC_INVLPG:
+        return V3_OP_INVLPG;
+
+    /* Data Instructions */
+    case QX86_MNEMONIC_ADC:
+        return V3_OP_ADC;
+
+    case QX86_MNEMONIC_ADD:
+        return V3_OP_ADD;
+
+    case QX86_MNEMONIC_AND:
+        return V3_OP_AND;
+
+    case QX86_MNEMONIC_SUB:
+        return V3_OP_SUB;
+
+
+    case QX86_MNEMONIC_MOVZX:
+        return V3_OP_MOVZX;
+
+    case QX86_MNEMONIC_MOVSX:
+        return V3_OP_MOVSX;
+
+
+    case QX86_MNEMONIC_DEC:
+        return V3_OP_DEC;
+
+    case QX86_MNEMONIC_INC:
+        return V3_OP_INC;
+
+    case QX86_MNEMONIC_OR:
+        return V3_OP_OR;
+
+    case QX86_MNEMONIC_XOR:
+        return V3_OP_XOR;
+
+    case QX86_MNEMONIC_NEG:
+        return V3_OP_NEG;
+
+    case QX86_MNEMONIC_NOT:
+        return V3_OP_NOT;
+
+    case QX86_MNEMONIC_XCHG:
+        return V3_OP_XCHG;
+
+    case QX86_MNEMONIC_SETB:
+        return V3_OP_SETB;
+
+    case QX86_MNEMONIC_SETBE:
+        return V3_OP_SETBE;
+
+    case QX86_MNEMONIC_SETL:
+        return V3_OP_SETL;
+
+    case QX86_MNEMONIC_SETLE:
+        return V3_OP_SETLE;
+
+    case QX86_MNEMONIC_SETAE:
+        return V3_OP_SETNB;
+
+    case QX86_MNEMONIC_SETA:
+        return V3_OP_SETNBE;
+
+    case QX86_MNEMONIC_SETGE:
+        return V3_OP_SETNL;
+
+    case QX86_MNEMONIC_SETG:
+        return V3_OP_SETNLE;
+
+    case QX86_MNEMONIC_SETNO:
+        return V3_OP_SETNO;
+
+    case QX86_MNEMONIC_SETNP:
+        return V3_OP_SETNP;
+
+    case QX86_MNEMONIC_SETNS:
+        return V3_OP_SETNS;
+
+    case QX86_MNEMONIC_SETNZ:
+        return V3_OP_SETNZ;
+
+    case QX86_MNEMONIC_SETO:
+        return V3_OP_SETO;
+
+    case QX86_MNEMONIC_SETP:
+        return V3_OP_SETP;
+
+    case QX86_MNEMONIC_SETS:
+        return V3_OP_SETS;
+
+    case QX86_MNEMONIC_SETZ:
+        return V3_OP_SETZ;
+
+    case QX86_MNEMONIC_MOVSB:
+    case QX86_MNEMONIC_MOVSW:
+    case QX86_MNEMONIC_MOVSD:
+    case QX86_MNEMONIC_MOVSQ:
+        return V3_OP_MOVS;
+
+    case QX86_MNEMONIC_STOSB:
+    case QX86_MNEMONIC_STOSW:
+    case QX86_MNEMONIC_STOSD:
+    case QX86_MNEMONIC_STOSQ:
+        return V3_OP_STOS;
+
+
+    default:
+        return V3_INVALID_OP;
+    }
+}
+
+static int qx86_register_to_v3_reg(struct guest_info * info, int qx86_reg,
+                 addr_t * v3_reg, uint_t * reg_len) {
+    PrintDebug("qx86 Register: %s\n", qx86_rtab[qx86_reg].name);
+
+    switch (qx86_reg) {
+    case QX86_REGISTER_INVALID:
+        *v3_reg = 0;
+        *reg_len = 0;
+        return -1;
+
+    case QX86_REGISTER_RAX:
+        *v3_reg = (addr_t)&(info->vm_regs.rax);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_EAX:
+        *v3_reg = (addr_t)&(info->vm_regs.rax);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_AX:
+        *v3_reg = (addr_t)&(info->vm_regs.rax);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_AH:
+        *v3_reg = (addr_t)(&(info->vm_regs.rax)) + 1;
+        *reg_len = 1;
+        return GPR_REGISTER;
+    case QX86_REGISTER_AL:
+        *v3_reg = (addr_t)&(info->vm_regs.rax);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+    case QX86_REGISTER_RCX:
+        *v3_reg = (addr_t)&(info->vm_regs.rcx);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_ECX:
+        *v3_reg = (addr_t)&(info->vm_regs.rcx);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_CX:
+        *v3_reg = (addr_t)&(info->vm_regs.rcx);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_CH:
+        *v3_reg = (addr_t)(&(info->vm_regs.rcx)) + 1;
+        *reg_len = 1;
+        return GPR_REGISTER;
+    case QX86_REGISTER_CL:
+        *v3_reg = (addr_t)&(info->vm_regs.rcx);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+    case QX86_REGISTER_RDX:
+        *v3_reg = (addr_t)&(info->vm_regs.rdx);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_EDX:
+        *v3_reg = (addr_t)&(info->vm_regs.rdx);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_DX:
+        *v3_reg = (addr_t)&(info->vm_regs.rdx);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_DH:
+        *v3_reg = (addr_t)(&(info->vm_regs.rdx)) + 1;
+        *reg_len = 1;
+        return GPR_REGISTER;
+    case QX86_REGISTER_DL:
+        *v3_reg = (addr_t)&(info->vm_regs.rdx);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+    case QX86_REGISTER_RBX:
+        *v3_reg = (addr_t)&(info->vm_regs.rbx);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_EBX:
+        *v3_reg = (addr_t)&(info->vm_regs.rbx);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_BX:
+        *v3_reg = (addr_t)&(info->vm_regs.rbx);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_BH:
+        *v3_reg = (addr_t)(&(info->vm_regs.rbx)) + 1;
+        *reg_len = 1;
+        return GPR_REGISTER;
+    case QX86_REGISTER_BL:
+        *v3_reg = (addr_t)&(info->vm_regs.rbx);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+
+    case QX86_REGISTER_RSP:
+        *v3_reg = (addr_t)&(info->vm_regs.rsp);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_ESP:
+        *v3_reg = (addr_t)&(info->vm_regs.rsp);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_SP:
+        *v3_reg = (addr_t)&(info->vm_regs.rsp);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_SPL:
+        *v3_reg = (addr_t)&(info->vm_regs.rsp);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+    case QX86_REGISTER_RBP:
+        *v3_reg = (addr_t)&(info->vm_regs.rbp);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_EBP:
+        *v3_reg = (addr_t)&(info->vm_regs.rbp);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_BP:
+        *v3_reg = (addr_t)&(info->vm_regs.rbp);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_BPL:
+        *v3_reg = (addr_t)&(info->vm_regs.rbp);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+
+
+    case QX86_REGISTER_RSI:
+        *v3_reg = (addr_t)&(info->vm_regs.rsi);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_ESI:
+        *v3_reg = (addr_t)&(info->vm_regs.rsi);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_SI:
+        *v3_reg = (addr_t)&(info->vm_regs.rsi);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_SIL:
+        *v3_reg = (addr_t)&(info->vm_regs.rsi);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+
+    case QX86_REGISTER_RDI:
+        *v3_reg = (addr_t)&(info->vm_regs.rdi);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_EDI:
+        *v3_reg = (addr_t)&(info->vm_regs.rdi);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_DI:
+        *v3_reg = (addr_t)&(info->vm_regs.rdi);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_DIL:
+        *v3_reg = (addr_t)&(info->vm_regs.rdi);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+
+
+
+
+    case QX86_REGISTER_R8:
+        *v3_reg = (addr_t)&(info->vm_regs.r8);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R8D:
+        *v3_reg = (addr_t)&(info->vm_regs.r8);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R8W:
+        *v3_reg = (addr_t)&(info->vm_regs.r8);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R8B:
+        *v3_reg = (addr_t)&(info->vm_regs.r8);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+    case QX86_REGISTER_R9:
+        *v3_reg = (addr_t)&(info->vm_regs.r9);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R9D:
+        *v3_reg = (addr_t)&(info->vm_regs.r9);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R9W:
+        *v3_reg = (addr_t)&(info->vm_regs.r9);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R9B:
+        *v3_reg = (addr_t)&(info->vm_regs.r9);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+    case QX86_REGISTER_R10:
+        *v3_reg = (addr_t)&(info->vm_regs.r10);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R10D:
+        *v3_reg = (addr_t)&(info->vm_regs.r10);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R10W:
+        *v3_reg = (addr_t)&(info->vm_regs.r10);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R10B:
+        *v3_reg = (addr_t)&(info->vm_regs.r10);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+    case QX86_REGISTER_R11:
+        *v3_reg = (addr_t)&(info->vm_regs.r11);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R11D:
+        *v3_reg = (addr_t)&(info->vm_regs.r11);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R11W:
+        *v3_reg = (addr_t)&(info->vm_regs.r11);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R11B:
+        *v3_reg = (addr_t)&(info->vm_regs.r11);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+    case QX86_REGISTER_R12:
+        *v3_reg = (addr_t)&(info->vm_regs.r12);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R12D:
+        *v3_reg = (addr_t)&(info->vm_regs.r12);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R12W:
+        *v3_reg = (addr_t)&(info->vm_regs.r12);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R12B:
+        *v3_reg = (addr_t)&(info->vm_regs.r12);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+    case QX86_REGISTER_R13:
+        *v3_reg = (addr_t)&(info->vm_regs.r13);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R13D:
+        *v3_reg = (addr_t)&(info->vm_regs.r13);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R13W:
+        *v3_reg = (addr_t)&(info->vm_regs.r13);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R13B:
+        *v3_reg = (addr_t)&(info->vm_regs.r13);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+    case QX86_REGISTER_R14:
+        *v3_reg = (addr_t)&(info->vm_regs.r14);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R14D:
+        *v3_reg = (addr_t)&(info->vm_regs.r14);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R14W:
+        *v3_reg = (addr_t)&(info->vm_regs.r14);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R14B:
+        *v3_reg = (addr_t)&(info->vm_regs.r14);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+    case QX86_REGISTER_R15:
+        *v3_reg = (addr_t)&(info->vm_regs.r15);
+        *reg_len = 8;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R15D:
+        *v3_reg = (addr_t)&(info->vm_regs.r15);
+        *reg_len = 4;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R15W:
+        *v3_reg = (addr_t)&(info->vm_regs.r15);
+        *reg_len = 2;
+        return GPR_REGISTER;
+    case QX86_REGISTER_R15B:
+        *v3_reg = (addr_t)&(info->vm_regs.r15);
+        *reg_len = 1;
+        return GPR_REGISTER;
+
+
+    case QX86_REGISTER_RIP:
+        *v3_reg = (addr_t)&(info->rip);
+        *reg_len = 8;
+        return CTRL_REGISTER;
+    case QX86_REGISTER_EIP:
+        *v3_reg = (addr_t)&(info->rip);
+        *reg_len = 4;
+        return CTRL_REGISTER;
+    case QX86_REGISTER_IP:
+        *v3_reg = (addr_t)&(info->rip);
+        *reg_len = 2;
+        return CTRL_REGISTER;
+
+    case QX86_REGISTER_FLAGS:
+        *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
+        *reg_len = 2;
+        return CTRL_REGISTER;
+    case QX86_REGISTER_EFLAGS:
+        *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
+        *reg_len = 4;
+        return CTRL_REGISTER;
+    case QX86_REGISTER_RFLAGS:
+        *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
+        *reg_len = 8;
+        return CTRL_REGISTER;
+
+    case QX86_REGISTER_CR0:
+        *v3_reg = (addr_t)&(info->ctrl_regs.cr0);
+        *reg_len = 4;
+        return CTRL_REGISTER;
+    case QX86_REGISTER_CR2:
+        *v3_reg = (addr_t)&(info->ctrl_regs.cr2);
+        *reg_len = 4;
+        return CTRL_REGISTER;
+    case QX86_REGISTER_CR3:
+        *v3_reg = (addr_t)&(info->ctrl_regs.cr3);
+        *reg_len = 4;
+        return CTRL_REGISTER;
+    case QX86_REGISTER_CR4:
+        *v3_reg = (addr_t)&(info->ctrl_regs.cr4);
+        *reg_len = 4;
+        return CTRL_REGISTER;
+    case QX86_REGISTER_CR8:
+        *v3_reg = (addr_t)&(info->ctrl_regs.cr8);
+        *reg_len = 4;
+        return CTRL_REGISTER;
+
+    case QX86_REGISTER_CR1:
+    case QX86_REGISTER_CR5:
+    case QX86_REGISTER_CR6:
+    case QX86_REGISTER_CR7:
+    case QX86_REGISTER_CR9:
+    case QX86_REGISTER_CR10:
+    case QX86_REGISTER_CR11:
+    case QX86_REGISTER_CR12:
+    case QX86_REGISTER_CR13:
+    case QX86_REGISTER_CR14:
+    case QX86_REGISTER_CR15:
+        return -1;
+
+
+    case QX86_REGISTER_CS:
+        *v3_reg = (addr_t)&(info->segments.cs);
+        *reg_len = 8;
+        return SEGMENT_REGISTER;
+    case QX86_REGISTER_DS:
+        *v3_reg = (addr_t)&(info->segments.ds);
+        *reg_len = 8;
+        return SEGMENT_REGISTER;
+    case QX86_REGISTER_ES:
+        *v3_reg = (addr_t)&(info->segments.es);
+        *reg_len = 8;
+        return SEGMENT_REGISTER;
+    case QX86_REGISTER_SS:
+        *v3_reg = (addr_t)&(info->segments.ss);
+        *reg_len = 8;
+        return SEGMENT_REGISTER;
+    case QX86_REGISTER_FS:
+        *v3_reg = (addr_t)&(info->segments.fs);
+        *reg_len = 8;
+        return SEGMENT_REGISTER;
+    case QX86_REGISTER_GS:
+        *v3_reg = (addr_t)&(info->segments.gs);
+        *reg_len = 8;
+        return SEGMENT_REGISTER;
+
+
+    case QX86_REGISTER_DR0:
+    case QX86_REGISTER_DR1:
+    case QX86_REGISTER_DR2:
+    case QX86_REGISTER_DR3:
+    case QX86_REGISTER_DR4:
+    case QX86_REGISTER_DR5:
+    case QX86_REGISTER_DR6:
+    case QX86_REGISTER_DR7:
+    case QX86_REGISTER_DR8:
+    case QX86_REGISTER_DR9:
+    case QX86_REGISTER_DR10:
+    case QX86_REGISTER_DR11:
+    case QX86_REGISTER_DR12:
+    case QX86_REGISTER_DR13:
+    case QX86_REGISTER_DR14:
+    case QX86_REGISTER_DR15:
+        return -1;
+
+
+    case QX86_REGISTER_XMM0:
+    case QX86_REGISTER_XMM1:
+    case QX86_REGISTER_XMM2:
+    case QX86_REGISTER_XMM3:
+    case QX86_REGISTER_XMM4:
+    case QX86_REGISTER_XMM5:
+    case QX86_REGISTER_XMM6:
+    case QX86_REGISTER_XMM7:
+    case QX86_REGISTER_XMM8:
+    case QX86_REGISTER_XMM9:
+    case QX86_REGISTER_XMM10:
+    case QX86_REGISTER_XMM11:
+    case QX86_REGISTER_XMM12:
+    case QX86_REGISTER_XMM13:
+    case QX86_REGISTER_XMM14:
+    case QX86_REGISTER_XMM15:
+
+    case QX86_REGISTER_YMM0:
+    case QX86_REGISTER_YMM1:
+    case QX86_REGISTER_YMM2:
+    case QX86_REGISTER_YMM3:
+    case QX86_REGISTER_YMM4:
+    case QX86_REGISTER_YMM5:
+    case QX86_REGISTER_YMM6:
+    case QX86_REGISTER_YMM7:
+    case QX86_REGISTER_YMM8:
+    case QX86_REGISTER_YMM9:
+    case QX86_REGISTER_YMM10:
+    case QX86_REGISTER_YMM11:
+    case QX86_REGISTER_YMM12:
+    case QX86_REGISTER_YMM13:
+    case QX86_REGISTER_YMM14:
+    case QX86_REGISTER_YMM15:
+
+    case QX86_REGISTER_MMX0:
+    case QX86_REGISTER_MMX1:
+    case QX86_REGISTER_MMX2:
+    case QX86_REGISTER_MMX3:
+    case QX86_REGISTER_MMX4:
+    case QX86_REGISTER_MMX5:
+    case QX86_REGISTER_MMX6:
+    case QX86_REGISTER_MMX7:
+
+    case QX86_REGISTER_ST0:
+    case QX86_REGISTER_ST1:
+    case QX86_REGISTER_ST2:
+    case QX86_REGISTER_ST3:
+    case QX86_REGISTER_ST4:
+    case QX86_REGISTER_ST5:
+    case QX86_REGISTER_ST6:
+    case QX86_REGISTER_ST7:
+        return -1;
+
+    }
+
+
+    return 0;
+}
index 450b18f..78fb31d 100644 (file)
@@ -68,6 +68,9 @@ static int inline check_vmcs_write(vmcs_field_t field, addr_t val) {
         return 1;
     }
 
+
+    
+
     return 0;
 }
 
@@ -100,7 +103,39 @@ static addr_t allocate_vmcs() {
     return (addr_t)V3_PAddr((void *)vmcs_page);
 }
 
+/*
 
+static int debug_efer_read(struct guest_info * core, uint_t msr, struct v3_msr * src, void * priv_data) {
+    struct v3_msr * efer = (struct v3_msr *)&(core->ctrl_regs.efer);
+    V3_Print("\n\nEFER READ\n");
+    
+    v3_print_guest_state(core);
+
+    src->value = efer->value;
+    return 0;
+}
+
+static int debug_efer_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
+    struct v3_msr * efer = (struct v3_msr *)&(core->ctrl_regs.efer);
+    V3_Print("\n\nEFER WRITE\n");
+    
+    v3_print_guest_state(core);
+
+    efer->value = src.value;
+
+    {
+       struct vmx_data * vmx_state = core->vmm_data;
+
+       V3_Print("Trapping page faults and GPFs\n");
+       vmx_state->excp_bmap.pf = 1;
+       vmx_state->excp_bmap.gp = 1;
+       
+        check_vmcs_write(VMCS_EXCP_BITMAP, vmx_state->excp_bmap.value);
+    }
+
+    return 0;
+}
+*/
 
 
 static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state) {
@@ -171,11 +206,7 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state)
     vmx_state->exit_ctrls.host_64_on = 1;
 #endif
 
-    // Hook all accesses to EFER register
-    v3_hook_msr(core->vm_info, EFER_MSR, 
-               &v3_handle_efer_read,
-               &v3_handle_efer_write, 
-               core);
+
 
     // Restore host's EFER register on each VM EXIT
     vmx_state->exit_ctrls.ld_efer = 1;
@@ -184,9 +215,12 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state)
     vmx_state->exit_ctrls.save_efer = 1;
     vmx_state->entry_ctrls.ld_efer  = 1;
 
-    // Cause VM_EXIT whenever CR4.VMXE or CR4.PAE bits are written
-    vmx_ret |= check_vmcs_write(VMCS_CR4_MASK, CR4_VMXE | CR4_PAE);
+    vmx_state->exit_ctrls.save_pat = 1;
+    vmx_state->exit_ctrls.ld_pat = 1;
+    vmx_state->entry_ctrls.ld_pat = 1;
 
+    /* Temporary GPF trap */
+    vmx_state->excp_bmap.gp = 1;
 
     // Setup Guests initial PAT field
     vmx_ret |= check_vmcs_write(VMCS_GUEST_PAT, 0x0007040600070406LL);
@@ -205,6 +239,10 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state)
 #define CR0_WP 0x00010000 // To ensure mem hooks work
         vmx_ret |= check_vmcs_write(VMCS_CR0_MASK, (CR0_PE | CR0_PG | CR0_WP));
 
+
+       // Cause VM_EXIT whenever CR4.VMXE or CR4.PAE bits are written
+       vmx_ret |= check_vmcs_write(VMCS_CR4_MASK, CR4_VMXE | CR4_PAE);
+
         core->ctrl_regs.cr3 = core->direct_map_pt;
 
         // vmx_state->pinbased_ctrls |= NMI_EXIT;
@@ -221,6 +259,12 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state)
        // Setup VMX Assist
        v3_vmxassist_init(core, vmx_state);
 
+       // Hook all accesses to EFER register
+       v3_hook_msr(core->vm_info, EFER_MSR, 
+                   &v3_handle_efer_read,
+                   &v3_handle_efer_write, 
+                   core);
+
     } else if ((core->shdw_pg_mode == NESTED_PAGING) && 
               (v3_cpu_types[core->pcpu_id] == V3_VMX_EPT_CPU)) {
 
@@ -231,6 +275,9 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state)
 
         // vmx_state->pinbased_ctrls |= NMI_EXIT;
 
+       // Cause VM_EXIT whenever CR4.VMXE or CR4.PAE bits are written
+       vmx_ret |= check_vmcs_write(VMCS_CR4_MASK, CR4_VMXE | CR4_PAE);
+       
         /* Disable CR exits */
        vmx_state->pri_proc_ctrls.cr3_ld_exit = 0;
        vmx_state->pri_proc_ctrls.cr3_str_exit = 0;
@@ -254,6 +301,9 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state)
            return -1;
        }
 
+       // Hook all accesses to EFER register
+       v3_hook_msr(core->vm_info, EFER_MSR, NULL, NULL, NULL);
+
     } else if ((core->shdw_pg_mode == NESTED_PAGING) && 
               (v3_cpu_types[core->pcpu_id] == V3_VMX_EPT_UG_CPU)) {
        int i = 0;
@@ -336,11 +386,18 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state)
        vmx_state->pri_proc_ctrls.invlpg_exit = 0;
 
 
+       // Cause VM_EXIT whenever the CR4.VMXE bit is set
+       vmx_ret |= check_vmcs_write(VMCS_CR4_MASK, CR4_VMXE);
+
+
        if (v3_init_ept(core, &hw_info) == -1) {
            PrintError("Error initializing EPT\n");
            return -1;
        }
 
+       // Hook all accesses to EFER register
+       //v3_hook_msr(core->vm_info, EFER_MSR, &debug_efer_read, &debug_efer_write, core);
+       v3_hook_msr(core->vm_info, EFER_MSR, NULL, NULL, NULL);
     } else {
        PrintError("Invalid Virtual paging mode\n");
        return -1;
@@ -410,6 +467,7 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state)
        msr_ret |= v3_hook_msr(core->vm_info, FS_BASE_MSR, NULL, NULL, NULL);
        msr_ret |= v3_hook_msr(core->vm_info, GS_BASE_MSR, NULL, NULL, NULL);
 
+       msr_ret |= v3_hook_msr(core->vm_info, IA32_PAT_MSR, NULL, NULL, NULL);
 
        // Not sure what to do about this... Does not appear to be an explicit hardware cache version...
        msr_ret |= v3_hook_msr(core->vm_info, IA32_CSTAR_MSR, NULL, NULL, NULL);
@@ -730,6 +788,9 @@ static int update_irq_entry_state(struct guest_info * info) {
 
 
 static struct vmx_exit_info exit_log[10];
+static uint64_t rip_log[10];
+
+
 
 static void print_exit_log(struct guest_info * info) {
     int cnt = info->num_exits % 10;
@@ -746,6 +807,9 @@ static void print_exit_log(struct guest_info * info) {
        V3_Print("\tint_info = %p\n", (void *)(addr_t)tmp->int_info);
        V3_Print("\tint_err = %p\n", (void *)(addr_t)tmp->int_err);
        V3_Print("\tinstr_info = %p\n", (void *)(addr_t)tmp->instr_info);
+       V3_Print("\tguest_linear_addr= %p\n", (void *)(addr_t)tmp->guest_linear_addr);
+       V3_Print("\tRIP = %p\n", (void *)rip_log[cnt]);
+
 
        cnt--;
 
@@ -927,6 +991,7 @@ int v3_vmx_enter(struct guest_info * info) {
     //PrintDebug("VMX Exit taken, id-qual: %u-%lu\n", exit_info.exit_reason, exit_info.exit_qual);
 
     exit_log[info->num_exits % 10] = exit_info;
+    rip_log[info->num_exits % 10] = get_addr_linear(info, info->rip, &(info->segments.cs));
 
 #ifdef V3_CONFIG_SYMCALL
     if (info->sym_core_state.symcall_state.sym_call_active == 0) {
@@ -1114,8 +1179,9 @@ int v3_reset_vmx_vm_core(struct guest_info * core, addr_t rip) {
 
 void v3_init_vmx_cpu(int cpu_id) {
     addr_t vmx_on_region = 0;
+    extern v3_cpu_arch_t v3_mach_type;
 
-    if (cpu_id == 0) {
+    if (v3_mach_type == V3_INVALID_CPU) {
        if (v3_init_vmx_hw(&hw_info) == -1) {
            PrintError("Could not initialize VMX hardware features on cpu %d\n", cpu_id);
            return;
@@ -1154,6 +1220,7 @@ void v3_init_vmx_cpu(int cpu_id) {
            v3_cpu_types[cpu_id] = V3_VMX_EPT_UG_CPU;
        }
     }
+    
 }