summaryrefslogtreecommitdiffstats
path: root/libpixelflinger/codeflinger/x86/libenc/enc_tabl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libpixelflinger/codeflinger/x86/libenc/enc_tabl.cpp')
-rw-r--r--libpixelflinger/codeflinger/x86/libenc/enc_tabl.cpp2164
1 files changed, 2164 insertions, 0 deletions
diff --git a/libpixelflinger/codeflinger/x86/libenc/enc_tabl.cpp b/libpixelflinger/codeflinger/x86/libenc/enc_tabl.cpp
new file mode 100644
index 0000000..b60d6b7
--- /dev/null
+++ b/libpixelflinger/codeflinger/x86/libenc/enc_tabl.cpp
@@ -0,0 +1,2164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @author Alexander V. Astapchuk
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h> //qsort
+#include <string.h>
+#include <memory.h>
+#include <errno.h>
+#include <stdlib.h>
+
+
+// need to use EM64T-specifics - new registers, defines from enc_prvt, etc...
+#if !defined(_EM64T_)
+ #define UNDEF_EM64T
+ #define _EM64T_
+#endif
+
+#define USE_ENCODER_DEFINES
+#include "enc_prvt.h"
+#include "enc_defs.h"
+
+#ifdef UNDEF_EM64T
+ #undef _EM64T_
+#endif
+
+//Android x86
+#if 0 //!defined(_HAVE_MMX_)
+ #define Mnemonic_PADDQ Mnemonic_Null
+ #define Mnemonic_PAND Mnemonic_Null
+ #define Mnemonic_POR Mnemonic_Null
+ #define Mnemonic_PSUBQ Mnemonic_Null
+#endif
+
+ENCODER_NAMESPACE_START
+
+
+EncoderBase::MnemonicDesc EncoderBase::mnemonics[Mnemonic_Count];
+EncoderBase::OpcodeDesc EncoderBase::opcodes[Mnemonic_Count][MAX_OPCODES];
+unsigned char EncoderBase::opcodesHashMap[Mnemonic_Count][HASH_MAX];
+
+
+/**
+ * @file
+ * @brief 'Master' copy of encoding data.
+ */
+
+/*
+This file contains a 'master copy' of encoding table - this is the info used
+by both generator of native instructions (EncoderBase class) and by
+disassembling routines. The first one uses an info how to encode the
+instruction, and the second does an opposite - several separate tables are
+built at runtime from this main table.
+
+=============================================================================
+
+The table was designed for easy support and maintenance. Thus, it was made as
+much close as possible to the Intel's IA32 Architecture Manual descriptions.
+The info is based on the latest (at the moment of writing) revision which is
+June 2005, order number 253666-016.
+
+Normally, almost all of opcodes in the 'master' table represented exactly as
+they are shown in the Intel's Architecture manual (well, with slashes
+replaced with underscore). There are several exclusions especially marked.
+
+Normally, to add an opcode/instruction, one only need to copy the whole
+string from the manual, and simply replace '/' with '_'.
+
+I.e., TheManual reads for DEC:
+ (1) FE /1 DEC r/m8 Valid Valid Decrement r/m8 by 1.
+ (2) REX + FE /1 DEC r/m8* Valid N.E. Decrement r/m8 by 1.
+ (3) REX.W + FF /1 DEC r/m64 Valid N.E. Decrement r/m64 by 1.
+
+1. Note, that there is no need to explicitly specify REX-based opcodes for
+ instruction to handle additional registers on EM64T:
+
+ (1) FE /1 DEC r/m8 Valid Valid Decrement r/m8 by 1.
+ (3) REX.W + FF /1 DEC r/m64 Valid N.E. Decrement r/m64 by 1.
+
+2. Copy the string, strip off the text comments, replace '/'=>'_'. Note, that
+ the second line is for EM64T only
+
+ (1) FE /1 DEC r/m8
+ (3) REX.W + FF /1 DEC r/m64
+
+3. Fill out the mnemonic, opcode parameters parts
+
+ BEGIN_MNEMONIC(DEC, MF_AFFECTS_FLAGS, DU)
+ BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xFE, _1}, {r_m8}, DU },
+ {OpcodeInfo::em64t, {REX_W, 0xFF, _1}, {r_m64}, DU },
+
+ DU here - one argument, it's used and defined
+
+4. That's it, that simple !
+
+The operand roles (DU here) are used by Jitrino's optimizing engine to
+perform data flow analysis. It also used to store/obtain number of operands.
+
+Special cases are (see the table for details):
+LEA
+Some FPU operations (i.e. FSTP)
+packed things (XORPD, XORPS, CVTDQ2PD, CVTTPD2DQ)
+
+Also, the Jitrino's needs require to specify all operands - including
+implicit ones (see IMUL).
+
+The master table iself does not need to be ordered - it's get sorted before
+processing. It's recommended (though it's not a law) to group similar
+instructions together - i.e. FPU instructions, MMX, etc.
+
+=============================================================================
+
+The encoding engine builds several tables basing on the 'master' one (here
+'mnemonic' is a kind of synonim for 'instruction'):
+
+- list of mnemonics which holds general info about instructions
+ (EncoderBase::mnemonics)
+- an array of opcodes descriptions (EncodeBase::opcodes)
+- a mapping between a hash value and an opcode description record for a given
+ mnemonic (EncoderBase::opcodesHashMap)
+
+The EncoderBase::mnemonics holds general info about instructions.
+The EncoderBase::opcodesHashMap is used for fast opcode selection basing on
+a hash value.
+The EncodeBase::opcodes is used for the encoding itself.
+
+=============================================================================
+The hash value is calculated and used as follows:
+
+JIT-ted code uses the following operand sizes: 8-, 16-, 32- and 64-bits and
+size for an operand can be encoded in just 2 bits.
+
+The following operand locations are available: one of registers - GP, FP,
+MMX, XMM (not taking segment registers), a memory and an immediate, which
+gives us 6 variants and can be enumerated in 3 bits.
+
+As a grand total, the the whole operand's info needed for opcode selection
+can be packed in 5 bits. Taking into account the IMUL mnemonic with its 3
+operands (including implicit ones), we're getting 15 bits per instruction and
+the complete table is about 32768 items per single instruction.
+
+Seems too many, but luckily, the 15 bit limit will never be reached: the
+worst case is IMUL with its 3 operands:
+(IMUL r64, r/m64, imm32)/(IMUL r32, r/m32, imm32).
+So, assigning lowest value to GP register, the max value of hash can be
+reduced.
+
+The hash values to use are:
+sizes:
+ 8 -> 11
+ 16 -> 10
+ 32 -> 01
+ 64 -> 00
+locations:
+ gp reg -> 000
+ memory -> 001
+ fp reg -> 010
+ mmx reg -> 011
+ xmm reg -> 100
+ immediate -> 101
+and the grand total for the worst case would be
+[ GP 32] [GP 32] [Imm 32]
+[000-01] [000-01] [101 01] = 1077
+
+However, the implicit operands adds additional value, and the worstest case
+is 'SHLD r_m32, r32, CL=r8'. This gives us the maximum number of:
+
+[mem 32] [GP 32] [GP 8b]
+[001-01] [000-01] [000-11] = 5155.
+
+The max number is pretty big and the hash functions is quite rare, thus it
+is not resonable to use a direct addressing i.e.
+OpcodeDesc[mnemonic][hash_code] - there would be a huge waste of space.
+
+Instead, we use a kind of mapping: the opcodes info is stored in packed
+(here: non rare) array. The max number of opcodes will not exceed 255 for
+each instruction. And we have an index array in which we store a mapping
+between a hash code value and opcode position for each given instruction.
+
+Sounds a bit sophisticated, but in real is simple, the opcode gets selected
+in 2 simple steps:
+
+1. Select [hash,mnemonic] => 'n'.
+
+The array is pretty rare - many cells contain 0xFF which
+means 'invalid hash - no opcode with given characteristics'
+
+char EnbcoderBase::opcodesHashMap[Mnemonic_Count][HASH_MAX] =
+
++----+----+----+----+----+----+
+| 00 | 05 | FF | FF | 03 | 12 | ...
+|---------+-------------------+
+| 12 | FF | FF | n | 04 | 25 | ... <- Mnemonic
+|-----------------------------+
+| FF | 11 | FF | 10 | 13 | .. | ...
++-----------------------------+
+ ... ^
+ |
+ hash
+
+2. Select [n,mnemonic] => 'opcode_desc11'
+
+OpcodeDesc EncoderBase::opcodes[Mnemonic_Count][MAX_OPCODES] =
+
++---------------+---------------+---------------+---------------+
+| opcode_desc00 | opcode_desc01 | opcode_desc02 | last_opcode | ...
++---------------+---------------+---------------+---------------+
+| opcode_desc10 | opcode_desc11 | last_opcode | xxx | <- Mnemonic
++---------------+---------------+---------------+---------------+
+| opcode_desc20 | opcode_desc21 | opcode_desc22 | opcode_desc23 | ...
++---------------+---------------+---------------+---------------+
+ ...
+ ^
+ |
+ n
+
+Now, use 'opcode_desc11'.
+
+=============================================================================
+The array of opcodes descriptions (EncodeBase::opcodes) is specially prepared
+to maximize performance - the EncoderBase::encode() is quite hot on client
+applications for the Jitrino/Jitrino.JET.
+The preparation is that opcode descriptions from the 'master' encoding table
+are preprocessed and a special set of OpcodeDesc prepared:
+First, the 'raw' opcode bytes are extracted. Here, 'raw' means the bytes that
+do not depened on any operands values, do not require any analysis and can be
+simply copied into the output buffer during encoding. Also, number of these
+'raw' bytes is counted. The fields are OpcodeDesc::opcode and
+OpcodeDesc::opcode_len.
+
+Then the fisrt non-implicit operand found and its index is stored in
+OpcodeDesc::first_opnd.
+
+The bytes that require processing and analysis ('/r', '+i', etc) are
+extracted and stored in OpcodeDesc::aux0 and OpcodeDesc::aux1 fields.
+
+Here, a special trick is performed:
+ Some opcodes have register/memory operand, but this is not reflected in
+ opcode column - for example, (MOVQ xmm64, xmm_m64). In this case, a fake
+ '_r' added to OpcodeDesc::aux field.
+ Some other opcodes have immediate operands, but this is again not
+ reflected in opcode column - for example, CALL cd or PUSH imm32.
+ In this case, a fake '/cd' or fake '/id' added to appropriate
+ OpcodeDesc::aux field.
+
+The OpcodeDesc::last is non-zero for the final OpcodeDesc record (which does
+not have valid data itself).
+*/
+
+// TODO: To extend flexibility, replace bool fields in MnemonicDesc &
+// MnemonicInfo with a set of flags packed into integer field.
+
+unsigned short EncoderBase::getHash(const OpcodeInfo* odesc)
+{
+ /*
+ NOTE: any changes in the hash computation must be stricty balanced with
+ EncoderBase::Operand::hash_it and EncoderBase::Operands()
+ */
+ unsigned short hash = 0;
+ // The hash computation, uses fast way - table selection instead of if-s.
+ if (odesc->roles.count > 0) {
+ OpndKind kind = odesc->opnds[0].kind;
+ OpndSize size = odesc->opnds[0].size;
+ assert(kind<COUNTOF(kind_hash));
+ assert(size<COUNTOF(size_hash));
+ hash = get_kind_hash(kind) | get_size_hash(size);
+ }
+
+ if (odesc->roles.count > 1) {
+ OpndKind kind = odesc->opnds[1].kind;
+ OpndSize size = odesc->opnds[1].size;
+ assert(kind<COUNTOF(kind_hash));
+ assert(size<COUNTOF(size_hash));
+ hash = (hash<<HASH_BITS_PER_OPERAND) |
+ (get_kind_hash(kind) | get_size_hash(size));
+ }
+
+ if (odesc->roles.count > 2) {
+ OpndKind kind = odesc->opnds[2].kind;
+ OpndSize size = odesc->opnds[2].size;
+ assert(kind<COUNTOF(kind_hash));
+ assert(size<COUNTOF(size_hash));
+ hash = (hash<<HASH_BITS_PER_OPERAND) |
+ (get_kind_hash(kind) | get_size_hash(size));
+ }
+ assert(hash <= HASH_MAX);
+ return hash;
+}
+
+
+#define BEGIN_MNEMONIC(mn, flags, roles) \
+ { Mnemonic_##mn, flags, roles, #mn,
+#define END_MNEMONIC() },
+#define BEGIN_OPCODES() {
+#define END_OPCODES() { OpcodeInfo::all, {OpcodeByteKind_LAST}, {}, {0, 0, 0, 0}}}
+
+
+static MnemonicInfo masterEncodingTable[] = {
+//
+// Null
+//
+BEGIN_MNEMONIC(Null, MF_NONE, N)
+BEGIN_OPCODES()
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(LAHF, MF_USES_FLAGS, D)
+BEGIN_OPCODES()
+// TheManual says it's not always supported in em64t mode, thus excluding it
+ {OpcodeInfo::ia32, {0x9F}, {EAX}, D },
+END_OPCODES()
+END_MNEMONIC()
+//
+// ALU mnemonics - add, adc, or, xor, and, cmp, sub, sbb
+// as they differ only in the opcode extention (/digit) number and
+// in which number the opcode start from, the opcode definitions
+// for those instructions are packed together
+//
+// The 'opcode_starts_from' and 'opcode_ext' in DEFINE_ALU_OPCODES()
+// are enough to define OpcodeInfo::all opcodes and the 'first_opcode'
+// parameter is only due to ADD instruction, which requires an zero opcode
+// byte which, in turn, is coded especially in the current coding scheme.
+//
+
+#define DEFINE_ALU_OPCODES( opc_ext, opcode_starts_from, first_opcode, def_use ) \
+\
+ {OpcodeInfo::decoder, {opcode_starts_from + 4, ib}, {AL, imm8}, DU_U },\
+ {OpcodeInfo::decoder, {Size16, opcode_starts_from + 5, iw}, {AX, imm16}, DU_U },\
+ {OpcodeInfo::decoder, {opcode_starts_from + 5, id}, {EAX, imm32}, DU_U },\
+ {OpcodeInfo::decoder64, {REX_W, opcode_starts_from+5, id}, {RAX, imm32s},DU_U },\
+\
+ {OpcodeInfo::all, {0x80, opc_ext, ib}, {r_m8, imm8}, def_use },\
+ {OpcodeInfo::all, {Size16, 0x81, opc_ext, iw}, {r_m16, imm16}, def_use },\
+ {OpcodeInfo::all, {0x81, opc_ext, id}, {r_m32, imm32}, def_use },\
+ {OpcodeInfo::em64t, {REX_W, 0x81, opc_ext, id}, {r_m64, imm32s}, def_use },\
+\
+ {OpcodeInfo::all, {Size16, 0x83, opc_ext, ib}, {r_m16, imm8s}, def_use },\
+ {OpcodeInfo::all, {0x83, opc_ext, ib}, {r_m32, imm8s}, def_use },\
+ {OpcodeInfo::em64t, {REX_W, 0x83, opc_ext, ib}, {r_m64, imm8s}, def_use },\
+\
+ {OpcodeInfo::all, {first_opcode, _r}, {r_m8, r8}, def_use },\
+\
+ {OpcodeInfo::all, {Size16, opcode_starts_from+1, _r}, {r_m16, r16}, def_use },\
+ {OpcodeInfo::all, {opcode_starts_from+1, _r}, {r_m32, r32}, def_use },\
+ {OpcodeInfo::em64t, {REX_W, opcode_starts_from+1, _r}, {r_m64, r64}, def_use },\
+\
+ {OpcodeInfo::all, {opcode_starts_from+2, _r}, {r8, r_m8}, def_use },\
+\
+ {OpcodeInfo::all, {Size16, opcode_starts_from+3, _r}, {r16, r_m16}, def_use },\
+ {OpcodeInfo::all, {opcode_starts_from+3, _r}, {r32, r_m32}, def_use },\
+ {OpcodeInfo::em64t, {REX_W, opcode_starts_from+3, _r}, {r64, r_m64}, def_use },
+
+BEGIN_MNEMONIC(ADD, MF_AFFECTS_FLAGS|MF_SYMMETRIC, DU_U)
+BEGIN_OPCODES()
+ DEFINE_ALU_OPCODES(_0, 0x00, OxOO, DU_U )
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(OR, MF_AFFECTS_FLAGS|MF_SYMMETRIC, DU_U)
+BEGIN_OPCODES()
+ DEFINE_ALU_OPCODES(_1, 0x08, 0x08, DU_U )
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(ADC, MF_AFFECTS_FLAGS|MF_USES_FLAGS|MF_SYMMETRIC, DU_U)
+BEGIN_OPCODES()
+ DEFINE_ALU_OPCODES(_2, 0x10, 0x10, DU_U )
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(SBB, MF_AFFECTS_FLAGS|MF_USES_FLAGS, DU_U)
+BEGIN_OPCODES()
+ DEFINE_ALU_OPCODES(_3, 0x18, 0x18, DU_U )
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(AND, MF_AFFECTS_FLAGS|MF_SYMMETRIC, DU_U)
+BEGIN_OPCODES()
+ DEFINE_ALU_OPCODES(_4, 0x20, 0x20, DU_U )
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(SUB, MF_AFFECTS_FLAGS|MF_SAME_ARG_NO_USE, DU_U)
+BEGIN_OPCODES()
+ DEFINE_ALU_OPCODES(_5, 0x28, 0x28, DU_U )
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(XOR, MF_AFFECTS_FLAGS|MF_SYMMETRIC|MF_SAME_ARG_NO_USE, DU_U)
+BEGIN_OPCODES()
+ DEFINE_ALU_OPCODES( _6, 0x30, 0x30, DU_U )
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(CMP, MF_AFFECTS_FLAGS, U_U)
+BEGIN_OPCODES()
+ DEFINE_ALU_OPCODES( _7, 0x38, 0x38, U_U )
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(CMPXCHG, MF_AFFECTS_FLAGS, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x0F, 0xB0, _r}, {r_m8, r8, AL}, DU_DU_DU },
+ {OpcodeInfo::all, {Size16, 0x0F, 0xB1, _r}, {r_m16, r16, AX}, DU_DU_DU },
+ {OpcodeInfo::all, {0x0F, 0xB1, _r}, {r_m32, r32, EAX}, DU_DU_DU},
+ {OpcodeInfo::em64t, {REX_W, 0x0F, 0xB1, _r}, {r_m64, r64, RAX}, DU_DU_DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(CMPXCHG8B, MF_AFFECTS_FLAGS, D)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x0F, 0xC7, _1}, {m64}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+#undef DEFINE_ALU_OPCODES
+//
+//
+//
+BEGIN_MNEMONIC(ADDSD, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF2, 0x0F, 0x58, _r}, {xmm64, xmm_m64}, DU_U},
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(ADDSS, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF3, 0x0F, 0x58, _r}, {xmm32, xmm_m32}, DU_U},
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(BSF, MF_AFFECTS_FLAGS, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x0F, 0xBC}, {r32, r_m32}, D_U},
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(BSR, MF_AFFECTS_FLAGS, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x0F, 0xBD}, {r32, r_m32}, D_U},
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(CALL, MF_NONE, U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xE8, cd}, {rel32}, U },
+ {OpcodeInfo::ia32, {Size16, 0xE8, cw}, {rel16}, U },
+ {OpcodeInfo::ia32, {0xFF, _2}, {r_m32}, U },
+ {OpcodeInfo::em64t, {0xFF, _2}, {r_m64}, U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(CMC, MF_USES_FLAGS|MF_AFFECTS_FLAGS, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::decoder, {0xF5}, {}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+//TODO: Workaround. Actually, it's D_DU, but Jitrino's CG thinks it's D_U
+BEGIN_MNEMONIC(CDQ, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x99}, {DX, AX}, D_U },
+ {OpcodeInfo::all, {0x99}, {EDX, EAX}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0x99}, {RDX, RAX}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+#define DEFINE_CMOVcc_MNEMONIC( cc ) \
+ BEGIN_MNEMONIC(CMOV##cc, MF_USES_FLAGS|MF_CONDITIONAL, DU_U ) \
+BEGIN_OPCODES() \
+ {OpcodeInfo::all, {Size16, 0x0F, 0x40 + ConditionMnemonic_##cc, _r}, {r16, r_m16}, DU_U }, \
+ {OpcodeInfo::all, {0x0F, 0x40 + ConditionMnemonic_##cc, _r}, {r32, r_m32}, DU_U }, \
+ {OpcodeInfo::em64t, {REX_W, 0x0F, 0x40 + ConditionMnemonic_##cc, _r}, {r64, r_m64}, DU_U }, \
+END_OPCODES() \
+END_MNEMONIC()
+
+DEFINE_CMOVcc_MNEMONIC(O)
+DEFINE_CMOVcc_MNEMONIC(NO)
+DEFINE_CMOVcc_MNEMONIC(B)
+DEFINE_CMOVcc_MNEMONIC(NB)
+DEFINE_CMOVcc_MNEMONIC(Z)
+DEFINE_CMOVcc_MNEMONIC(NZ)
+DEFINE_CMOVcc_MNEMONIC(BE)
+DEFINE_CMOVcc_MNEMONIC(NBE)
+DEFINE_CMOVcc_MNEMONIC(S)
+DEFINE_CMOVcc_MNEMONIC(NS)
+DEFINE_CMOVcc_MNEMONIC(P)
+DEFINE_CMOVcc_MNEMONIC(NP)
+DEFINE_CMOVcc_MNEMONIC(L)
+DEFINE_CMOVcc_MNEMONIC(NL)
+DEFINE_CMOVcc_MNEMONIC(LE)
+DEFINE_CMOVcc_MNEMONIC(NLE)
+
+#undef DEFINE_CMOVcc_MNEMONIC
+
+/*****************************************************************************
+ ***** SSE conversion routines *****
+*****************************************************************************/
+//
+// double -> float
+BEGIN_MNEMONIC(CVTSD2SS, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF2, 0x0F, 0x5A, _r}, {xmm32, xmm_m64}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+// double -> I_32
+BEGIN_MNEMONIC(CVTSD2SI, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF2, 0x0F, 0x2D, _r}, {r32, xmm_m64}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0xF2, 0x0F, 0x2D, _r}, {r64, xmm_m64}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+// double [truncated] -> I_32
+BEGIN_MNEMONIC(CVTTSD2SI, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF2, 0x0F, 0x2C, _r}, {r32, xmm_m64}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0xF2, 0x0F, 0x2C, _r}, {r64, xmm_m64}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+// float -> double
+BEGIN_MNEMONIC(CVTSS2SD, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF3, 0x0F, 0x5A, _r}, {xmm64, xmm_m32}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+// float -> I_32
+BEGIN_MNEMONIC(CVTSS2SI, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF3, 0x0F, 0x2D, _r}, {r32, xmm_m32}, D_U},
+ {OpcodeInfo::em64t, {REX_W, 0xF3, 0x0F, 0x2D, _r}, {r64, xmm_m32}, D_U},
+END_OPCODES()
+END_MNEMONIC()
+
+// float [truncated] -> I_32
+BEGIN_MNEMONIC(CVTTSS2SI, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF3, 0x0F, 0x2C, _r}, {r32, xmm_m32}, D_U},
+ {OpcodeInfo::em64t, {REX_W, 0xF3, 0x0F, 0x2C, _r}, {r64, xmm_m32}, D_U},
+END_OPCODES()
+END_MNEMONIC()
+
+// I_32 -> double
+BEGIN_MNEMONIC(CVTSI2SD, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF2, 0x0F, 0x2A, _r}, {xmm64, r_m32}, D_U},
+ {OpcodeInfo::em64t, {REX_W, 0xF2, 0x0F, 0x2A, _r}, {xmm64, r_m64}, D_U},
+END_OPCODES()
+END_MNEMONIC()
+
+// I_32 -> float
+BEGIN_MNEMONIC(CVTSI2SS, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF3, 0x0F, 0x2A, _r}, {xmm32, r_m32}, D_U},
+ {OpcodeInfo::em64t, {REX_W, 0xF3, 0x0F, 0x2A, _r}, {xmm32, r_m64}, D_U},
+END_OPCODES()
+END_MNEMONIC()
+
+//
+// ~ SSE conversions
+//
+
+BEGIN_MNEMONIC(DEC, MF_AFFECTS_FLAGS, DU )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xFE, _1}, {r_m8}, DU },
+
+ {OpcodeInfo::all, {Size16, 0xFF, _1}, {r_m16}, DU },
+ {OpcodeInfo::all, {0xFF, _1}, {r_m32}, DU },
+ {OpcodeInfo::em64t, {REX_W, 0xFF, _1}, {r_m64}, DU },
+
+ {OpcodeInfo::ia32, {Size16, 0x48|rw}, {r16}, DU },
+ {OpcodeInfo::ia32, {0x48|rd}, {r32}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(DIVSD, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF2, 0x0F, 0x5E, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(DIVSS, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF3, 0x0F, 0x5E, _r}, {xmm32, xmm_m32}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+/****************************************************************************
+ ***** FPU operations *****
+****************************************************************************/
+
+BEGIN_MNEMONIC(FADDP, MF_NONE, DU )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDE, 0xC1}, {FP0D}, DU },
+ {OpcodeInfo::all, {0xDE, 0xC1}, {FP0S}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FLDZ, MF_NONE, U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xEE}, {FP0D}, D },
+ {OpcodeInfo::all, {0xD9, 0xEE}, {FP0S}, D },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FADD, MF_NONE, U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDC, _0}, {FP0D, m64}, DU_U },
+ {OpcodeInfo::all, {0xD8, _0}, {FP0S, m32}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FSUBP, MF_NONE, DU )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDE, 0xE9}, {FP0D}, DU },
+ {OpcodeInfo::all, {0xDE, 0xE9}, {FP0S}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FSUB, MF_NONE, U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDC, _4}, {FP0D, m64}, DU_U },
+ {OpcodeInfo::all, {0xD8, _4}, {FP0S, m32}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FISUB, MF_NONE, U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDA, _4}, {FP0S, m32}, DU_U },
+// {OpcodeInfo::all, {0xDE, _4}, {FP0S, m16}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+
+
+BEGIN_MNEMONIC(FMUL, MF_NONE, DU_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD8, _1}, {FP0S, m32}, DU_U },
+ {OpcodeInfo::all, {0xDC, _1}, {FP0D, m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FMULP, MF_NONE, DU )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDE, 0xC9}, {FP0D}, DU },
+ {OpcodeInfo::all, {0xDE, 0xC9}, {FP0S}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FDIVP, MF_NONE, DU )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDE, 0xF9}, {FP0D}, DU },
+ {OpcodeInfo::all, {0xDE, 0xF9}, {FP0S}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FDIV, MF_NONE, U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDC, _6}, {FP0D, m64}, DU_U },
+ {OpcodeInfo::all, {0xD8, _6}, {FP0S, m32}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(FUCOM, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDD, 0xE1}, {FP0D, FP1D}, DU_U },
+ {OpcodeInfo::all, {0xDD, 0xE1}, {FP0S, FP1S}, DU_U },
+ // A little trick: actually, these 2 opcodes take only index of the
+ // needed register. To make the things similar to other instructions
+ // we encode here as if they took FPREG.
+ {OpcodeInfo::all, {0xDD, 0xE0|_i}, {fp32}, DU },
+ {OpcodeInfo::all, {0xDD, 0xE0|_i}, {fp64}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FUCOMI, MF_NONE, D_U )
+BEGIN_OPCODES()
+ // A little trick: actually, these 2 opcodes take only index of the
+ // needed register. To make the things similar to other instructions
+ // we encode here as if they took FPREG.
+ {OpcodeInfo::all, {0xDB, 0xE8|_i}, {fp32}, DU },
+ {OpcodeInfo::all, {0xDB, 0xE8|_i}, {fp64}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FUCOMP, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDD, 0xE9}, {FP0D, FP1D}, DU_U },
+ {OpcodeInfo::all, {0xDD, 0xE9}, {FP0S, FP1S}, DU_U },
+ // A little trick: actually, these 2 opcodes take only index of the
+ // needed register. To make the things similar to other instructions
+ // we encode here as if they took FPREG.
+ {OpcodeInfo::all, {0xDD, 0xE8|_i}, {fp32}, DU },
+ {OpcodeInfo::all, {0xDD, 0xE8|_i}, {fp64}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FUCOMIP, MF_NONE, D_U )
+BEGIN_OPCODES()
+ // A little trick: actually, these 2 opcodes take only index of the
+ // needed register. To make the things similar to other instructions
+ // we encode here as if they took FPREG.
+ {OpcodeInfo::all, {0xDF, 0xE8|_i}, {fp32}, DU },
+ {OpcodeInfo::all, {0xDF, 0xE8|_i}, {fp64}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FUCOMPP, MF_NONE, U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDA, 0xE9}, {FP0D, FP1D}, DU_U },
+ {OpcodeInfo::all, {0xDA, 0xE9}, {FP0S, FP1S}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FLDCW, MF_NONE, U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, _5}, {m16}, U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FNSTCW, MF_NONE, D)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, _7}, {m16}, D },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FSTSW, MF_NONE, D)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x9B, 0xDF, 0xE0}, {EAX}, D },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FNSTSW, MF_NONE, D)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDF, 0xE0}, {EAX}, D },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FCHS, MF_NONE, DU )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xE0}, {FP0D}, DU },
+ {OpcodeInfo::all, {0xD9, 0xE0}, {FP0S}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FCLEX, MF_NONE, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x9B, 0xDB, 0xE2}, {}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FNCLEX, MF_NONE, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDB, 0xE2}, {}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+//BEGIN_MNEMONIC(FDECSTP, MF_NONE, N)
+// BEGIN_OPCODES()
+// {OpcodeInfo::all, {0xD9, 0xF6}, {}, N },
+// END_OPCODES()
+//END_MNEMONIC()
+
+BEGIN_MNEMONIC(FILD, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDB, _0}, {FP0S, m32}, D_U },
+ {OpcodeInfo::all, {0xDF, _5}, {FP0D, m64}, D_U },
+ {OpcodeInfo::all, {0xDB, _0}, {FP0S, m32}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+//BEGIN_MNEMONIC(FINCSTP, MF_NONE, N)
+// BEGIN_OPCODES()
+// {OpcodeInfo::all, {0xD9, 0xF7}, {}, N },
+// END_OPCODES()
+//END_MNEMONIC()
+
+BEGIN_MNEMONIC(FIST, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDB, _2}, {m32, FP0S}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FISTP, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDB, _3}, {m32, FP0S}, D_U },
+ {OpcodeInfo::all, {0xDF, _7}, {m64, FP0D}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FISTTP, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xDD, _1}, {m64, FP0D}, D_U },
+ {OpcodeInfo::all, {0xDB, _1}, {m32, FP0S}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FRNDINT, MF_NONE, DU )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xFC}, {FP0S}, DU },
+ {OpcodeInfo::all, {0xD9, 0xFC}, {FP0D}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FLD, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, _0}, {FP0S, m32}, D_U },
+ {OpcodeInfo::all, {0xDD, _0}, {FP0D, m64}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FLDLG2, MF_NONE, U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xEC}, {FP0S}, D },
+ {OpcodeInfo::all, {0xD9, 0xEC}, {FP0D}, D },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FLDLN2, MF_NONE, U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xED}, {FP0S}, D },
+ {OpcodeInfo::all, {0xD9, 0xED}, {FP0D}, D },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FLD1, MF_NONE, U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xE8}, {FP0S}, D },
+ {OpcodeInfo::all, {0xD9, 0xE8}, {FP0D}, D },
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(FPREM, MF_NONE, N)
+ BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xF8}, {}, N },
+ END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FPREM1, MF_NONE, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xF5}, {}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FST, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, _2}, {m32, FP0S}, D_U },
+ {OpcodeInfo::all, {0xDD, _2}, {m64, FP0D}, D_U },
+ // A little trick: actually, these 2 opcodes take only index of the
+ // needed register. To make the things similar to other instructions
+ // we encode here as if they took FPREG.
+ {OpcodeInfo::all, {0xDD, 0xD0|_i}, {fp32}, D },
+ {OpcodeInfo::all, {0xDD, 0xD0|_i}, {fp64}, D },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FSTP, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, _3}, {m32, FP0S}, D_U },
+ {OpcodeInfo::all, {0xDD, _3}, {m64, FP0D}, D_U },
+ // A little trick: actually, these 2 opcodes take only index of the
+ // needed register. To make the things similar to other instructions
+ // we encode here as if they took FPREG.
+ {OpcodeInfo::all, {0xDD, 0xD8|_i}, {fp32}, D },
+ {OpcodeInfo::all, {0xDD, 0xD8|_i}, {fp64}, D },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FSQRT, MF_NONE, DU)
+ BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xFA}, {FP0S}, DU },
+ {OpcodeInfo::all, {0xD9, 0xFA}, {FP0D}, DU },
+ END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(FYL2X, MF_NONE, DU)
+ BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xF1}, {FP0S}, DU },
+ {OpcodeInfo::all, {0xD9, 0xF1}, {FP0D}, DU },
+ END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(FYL2XP1, MF_NONE, DU)
+ BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xF9}, {FP0S}, DU },
+ {OpcodeInfo::all, {0xD9, 0xF9}, {FP0D}, DU },
+ END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(F2XM1, MF_NONE, DU)
+ BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xF0}, {FP0S}, DU },
+ {OpcodeInfo::all, {0xD9, 0xF0}, {FP0D}, DU },
+ END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FPATAN, MF_NONE, DU)
+ BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xF3}, {FP0S}, DU },
+ {OpcodeInfo::all, {0xD9, 0xF3}, {FP0D}, DU },
+ END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FXCH, MF_NONE, DU)
+ BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xC9}, {FP0S}, DU },
+ {OpcodeInfo::all, {0xD9, 0xC9}, {FP0D}, DU },
+ END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FSCALE, MF_NONE, DU)
+ BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xFD}, {FP0S}, DU },
+ {OpcodeInfo::all, {0xD9, 0xFD}, {FP0D}, DU },
+ END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FABS, MF_NONE, DU)
+ BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xE1}, {FP0S}, DU },
+ {OpcodeInfo::all, {0xD9, 0xE1}, {FP0D}, DU },
+ END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FSIN, MF_NONE, DU)
+ BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xFE}, {FP0S}, DU },
+ {OpcodeInfo::all, {0xD9, 0xFE}, {FP0D}, DU },
+ END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FCOS, MF_NONE, DU)
+ BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xFF}, {FP0S}, DU },
+ {OpcodeInfo::all, {0xD9, 0xFF}, {FP0D}, DU },
+ END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(FPTAN, MF_NONE, DU)
+ BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xD9, 0xF2}, {FP0S}, DU },
+ {OpcodeInfo::all, {0xD9, 0xF2}, {FP0D}, DU },
+ END_OPCODES()
+END_MNEMONIC()
+
+//
+// ~ FPU
+//
+
+BEGIN_MNEMONIC(DIV, MF_AFFECTS_FLAGS, DU_DU_U)
+BEGIN_OPCODES()
+#if !defined(_EM64T_)
+ {OpcodeInfo::all, {0xF6, _6}, {AH, AL, r_m8}, DU_DU_U },
+ {OpcodeInfo::all, {Size16, 0xF7, _6}, {DX, AX, r_m16}, DU_DU_U },
+#endif
+ {OpcodeInfo::all, {0xF7, _6}, {EDX, EAX, r_m32}, DU_DU_U },
+ {OpcodeInfo::em64t, {REX_W, 0xF7, _6}, {RDX, RAX, r_m64}, DU_DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(IDIV, MF_AFFECTS_FLAGS, DU_DU_U)
+BEGIN_OPCODES()
+#if !defined(_EM64T_)
+ {OpcodeInfo::all, {0xF6, _7}, {AH, AL, r_m8}, DU_DU_U },
+ {OpcodeInfo::all, {Size16, 0xF7, _7}, {DX, AX, r_m16}, DU_DU_U },
+#endif
+ {OpcodeInfo::all, {0xF7, _7}, {EDX, EAX, r_m32}, DU_DU_U },
+ {OpcodeInfo::em64t, {REX_W, 0xF7, _7}, {RDX, RAX, r_m64}, DU_DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(IMUL, MF_AFFECTS_FLAGS, D_DU_U)
+BEGIN_OPCODES()
+ /*{OpcodeInfo::all, {0xF6, _5}, {AH, AL, r_m8}, D_DU_U },
+ {OpcodeInfo::all, {Size16, 0xF7, _5}, {DX, AX, r_m16}, D_DU_U },
+ */
+ //
+ {OpcodeInfo::all, {0xF7, _5}, {EDX, EAX, r_m32}, D_DU_U },
+ //todo: this opcode's hash conflicts with IMUL r64,r_m64 - they're both 0.
+ // this particular is not currently used, so we may safely drop it, but need to
+ // revisit the hash implementation
+ // {OpcodeInfo::em64t, {REX_W, 0xF7, _5}, {RDX, RAX, r_m64}, D_DU_U },
+ //
+ {OpcodeInfo::all, {Size16, 0x0F, 0xAF, _r}, {r16,r_m16}, DU_U },
+ {OpcodeInfo::all, {0x0F, 0xAF, _r}, {r32,r_m32}, DU_U },
+ {OpcodeInfo::em64t, {REX_W, 0x0F, 0xAF, _r}, {r64,r_m64}, DU_U },
+ {OpcodeInfo::all, {Size16, 0x6B, _r, ib}, {r16,r_m16,imm8s}, D_DU_U },
+ {OpcodeInfo::all, {0x6B, _r, ib}, {r32,r_m32,imm8s}, D_DU_U },
+ {OpcodeInfo::em64t, {REX_W, 0x6B, _r, ib}, {r64,r_m64,imm8s}, D_DU_U },
+ {OpcodeInfo::all, {Size16, 0x6B, _r, ib}, {r16,imm8s}, DU_U },
+ {OpcodeInfo::all, {0x6B, _r, ib}, {r32,imm8s}, DU_U },
+ {OpcodeInfo::em64t, {REX_W, 0x6B, _r, ib}, {r64,imm8s}, DU_U },
+ {OpcodeInfo::all, {Size16, 0x69, _r, iw}, {r16,r_m16,imm16}, D_U_U },
+ {OpcodeInfo::all, {0x69, _r, id}, {r32,r_m32,imm32}, D_U_U },
+ {OpcodeInfo::em64t, {REX_W, 0x69, _r, id}, {r64,r_m64,imm32s}, D_U_U },
+ {OpcodeInfo::all, {Size16, 0x69, _r, iw}, {r16,imm16}, DU_U },
+ {OpcodeInfo::all, {0x69, _r, id}, {r32,imm32}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(MUL, MF_AFFECTS_FLAGS, U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF6, _4}, {AX, AL, r_m8}, D_DU_U },
+ {OpcodeInfo::all, {Size16, 0xF7, _4}, {DX, AX, r_m16}, D_DU_U },
+ {OpcodeInfo::all, {0xF7, _4}, {EDX, EAX, r_m32}, D_DU_U },
+ {OpcodeInfo::em64t, {REX_W, 0xF7, _4}, {RDX, RAX, r_m64}, D_DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(INC, MF_AFFECTS_FLAGS, DU )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xFE, _0}, {r_m8}, DU },
+ {OpcodeInfo::all, {Size16, 0xFF, _0}, {r_m16}, DU },
+ {OpcodeInfo::all, {0xFF, _0}, {r_m32}, DU },
+ {OpcodeInfo::em64t, {REX_W, 0xFF, _0}, {r_m64}, DU },
+ {OpcodeInfo::ia32, {Size16, 0x40|rw}, {r16}, DU },
+ {OpcodeInfo::ia32, {0x40|rd}, {r32}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(INT3, MF_NONE, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xCC}, {}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+#define DEFINE_Jcc_MNEMONIC( cc ) \
+ BEGIN_MNEMONIC(J##cc, MF_USES_FLAGS|MF_CONDITIONAL, U ) \
+BEGIN_OPCODES() \
+ {OpcodeInfo::all, {0x70 + ConditionMnemonic_##cc, cb }, { rel8 }, U }, \
+ {OpcodeInfo::ia32, {Size16, 0x0F, 0x80 + ConditionMnemonic_##cc, cw}, { rel16 }, U }, \
+ {OpcodeInfo::all, {0x0F, 0x80 + ConditionMnemonic_##cc, cd}, { rel32 }, U }, \
+END_OPCODES() \
+END_MNEMONIC()
+
+
+DEFINE_Jcc_MNEMONIC(O)
+DEFINE_Jcc_MNEMONIC(NO)
+DEFINE_Jcc_MNEMONIC(B)
+DEFINE_Jcc_MNEMONIC(NB)
+DEFINE_Jcc_MNEMONIC(Z)
+DEFINE_Jcc_MNEMONIC(NZ)
+DEFINE_Jcc_MNEMONIC(BE)
+DEFINE_Jcc_MNEMONIC(NBE)
+
+DEFINE_Jcc_MNEMONIC(S)
+DEFINE_Jcc_MNEMONIC(NS)
+DEFINE_Jcc_MNEMONIC(P)
+DEFINE_Jcc_MNEMONIC(NP)
+DEFINE_Jcc_MNEMONIC(L)
+DEFINE_Jcc_MNEMONIC(NL)
+DEFINE_Jcc_MNEMONIC(LE)
+DEFINE_Jcc_MNEMONIC(NLE)
+
+#undef DEFINE_Jcc_MNEMONIC
+
+BEGIN_MNEMONIC(JMP, MF_NONE, U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xEB, cb}, {rel8}, U },
+ {OpcodeInfo::ia32, {Size16, 0xE9, cw}, {rel16}, U },
+ {OpcodeInfo::all, {0xE9, cd}, {rel32}, U },
+ {OpcodeInfo::ia32, {Size16, 0xFF, _4}, {r_m16}, U },
+ {OpcodeInfo::ia32, {0xFF, _4}, {r_m32}, U },
+ {OpcodeInfo::em64t, {0xFF, _4}, {r_m64}, U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(LEA, MF_NONE, D_U )
+BEGIN_OPCODES()
+ /*
+ A special case: the LEA instruction itself does not care about size of
+ second operand. This is obviuos why it is, and thus in The Manual, a
+ simple 'm' without size is used.
+ However, in the Jitrino's instrucitons we'll have an operand with a size.
+ Also, the hashing scheme is not supposed to handle OpndSize_Null, and
+ making it to do so will lead to unnecessary complication of hashing
+ scheme. Thus, instead of handling it as a special case, we simply make
+ copies of the opcodes with sizes set.
+ {OpcodeInfo::all, {0x8D, _r}, {r32, m}, D_U },
+ {OpcodeInfo::em64t, {0x8D, _r}, {r64, m}, D_U },
+ */
+ //Android x86: keep r32, m32 only, otherwise, will have decoding error
+ //{OpcodeInfo::all, {0x8D, _r}, {r32, m8}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0x8D, _r}, {r64, m8}, D_U },
+ //{OpcodeInfo::all, {0x8D, _r}, {r32, m16}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0x8D, _r}, {r64, m16}, D_U },
+ {OpcodeInfo::all, {0x8D, _r}, {r32, m32}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0x8D, _r}, {r64, m32}, D_U },
+ {OpcodeInfo::all, {0x8D, _r}, {r32, m64}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0x8D, _r}, {r64, m64}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(LOOP, MF_AFFECTS_FLAGS|MF_USES_FLAGS, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xE2, cb}, {ECX, rel8}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(LOOPE, MF_AFFECTS_FLAGS|MF_USES_FLAGS, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xE1, cb}, {ECX, rel8}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(LOOPNE, MF_AFFECTS_FLAGS|MF_USES_FLAGS, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xE0, cb}, {ECX, rel8}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(MOV, MF_NONE, D_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x88, _r}, {r_m8,r8}, D_U },
+
+ {OpcodeInfo::all, {Size16, 0x89, _r}, {r_m16,r16}, D_U },
+ {OpcodeInfo::all, {0x89, _r}, {r_m32,r32}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0x89, _r}, {r_m64,r64}, D_U },
+ {OpcodeInfo::all, {0x8A, _r}, {r8,r_m8}, D_U },
+
+ {OpcodeInfo::all, {Size16, 0x8B, _r}, {r16,r_m16}, D_U },
+ {OpcodeInfo::all, {0x8B, _r}, {r32,r_m32}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0x8B, _r}, {r64,r_m64}, D_U },
+
+ {OpcodeInfo::all, {0xB0|rb}, {r8,imm8}, D_U },
+
+ {OpcodeInfo::all, {Size16, 0xB8|rw}, {r16,imm16}, D_U },
+ {OpcodeInfo::all, {0xB8|rd}, {r32,imm32}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0xB8|rd}, {r64,imm64}, D_U },
+ {OpcodeInfo::all, {0xC6, _0}, {r_m8,imm8}, D_U },
+
+ {OpcodeInfo::all, {Size16, 0xC7, _0}, {r_m16,imm16}, D_U },
+ {OpcodeInfo::all, {0xC7, _0}, {r_m32,imm32}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0xC7, _0}, {r_m64,imm32s}, D_U },
+
+ {OpcodeInfo::decoder, {0xA0}, {AL, moff8}, D_U },
+ {OpcodeInfo::decoder, {Size16, 0xA1}, {AX, moff16}, D_U },
+ {OpcodeInfo::decoder, {0xA1}, {EAX, moff32}, D_U },
+ //{OpcodeInfo::decoder64, {REX_W, 0xA1}, {RAX, moff64}, D_U },
+
+ {OpcodeInfo::decoder, {0xA2}, {moff8, AL}, D_U },
+ {OpcodeInfo::decoder, {Size16, 0xA3}, {moff16, AX}, D_U },
+ {OpcodeInfo::decoder, {0xA3}, {moff32, EAX}, D_U },
+ //{OpcodeInfo::decoder64, {REX_W, 0xA3}, {moff64, RAX}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+
+
+BEGIN_MNEMONIC(XCHG, MF_NONE, DU_DU )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x87, _r}, {r_m32,r32}, DU_DU },
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(MOVQ, MF_NONE, D_U )
+BEGIN_OPCODES()
+#ifdef _HAVE_MMX_
+ {OpcodeInfo::all, {0x0F, 0x6F, _r}, {mm64, mm_m64}, D_U },
+ {OpcodeInfo::all, {0x0F, 0x7F, _r}, {mm_m64, mm64}, D_U },
+#endif
+ {OpcodeInfo::all, {0xF3, 0x0F, 0x7E }, {xmm64, xmm_m64}, D_U },
+ {OpcodeInfo::all, {0x66, 0x0F, 0xD6 }, {xmm_m64, xmm64}, D_U },
+// {OpcodeInfo::em64t, {REX_W, 0x66, 0x0F, 0x6E, _r}, {xmm64, r_m64}, D_U },
+// {OpcodeInfo::em64t, {REX_W, 0x66, 0x0F, 0x7E, _r}, {r_m64, xmm64}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0x66, 0x0F, 0x6E, _r}, {xmm64, r64}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0x66, 0x0F, 0x7E, _r}, {r64, xmm64}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(MOVD, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x6E, _r}, {xmm32, r_m32}, D_U },
+ {OpcodeInfo::all, {0x66, 0x0F, 0x7E, _r}, {r_m32, xmm32}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+//
+// A bunch of MMX instructions
+//
+#ifdef _HAVE_MMX_
+
+BEGIN_MNEMONIC(EMMS, MF_NONE, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x0F, 0x77}, {}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+#endif
+
+BEGIN_MNEMONIC(PADDQ, MF_NONE, DU_U)
+BEGIN_OPCODES()
+#ifdef _HAVE_MMX_
+ {OpcodeInfo::all, {0x0F, 0xD4, _r}, {mm64, mm_m64}, DU_U },
+#endif
+ {OpcodeInfo::all, {0x66, 0x0F, 0xD4, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PAND, MF_NONE, DU_U)
+BEGIN_OPCODES()
+#ifdef _HAVE_MMX_
+ {OpcodeInfo::all, {0x0F, 0xDB, _r}, {mm64, mm_m64}, DU_U },
+#endif
+ {OpcodeInfo::all, {0x66, 0x0F, 0xDB, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(POR, MF_NONE, DU_U)
+BEGIN_OPCODES()
+#ifdef _HAVE_MMX_
+ {OpcodeInfo::all, {0x0F, 0xEB, _r}, {mm64, mm_m64}, DU_U },
+#endif
+ {OpcodeInfo::all, {0x66, 0x0F, 0xEB, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PSUBQ, MF_NONE, DU_U)
+BEGIN_OPCODES()
+#ifdef _HAVE_MMX_
+ {OpcodeInfo::all, {0x0F, 0xFB, _r}, {mm64, mm_m64}, DU_U },
+#endif
+ {OpcodeInfo::all, {0x66, 0x0F, 0xFB, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PANDN, MF_NONE, DU_U)
+BEGIN_OPCODES()
+#ifdef _HAVE_MMX_
+ {OpcodeInfo::all, {0x0F, 0xDF, _r}, {mm64, mm_m64}, DU_U },
+#endif
+ {OpcodeInfo::all, {0x66, 0x0F, 0xDF, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+BEGIN_MNEMONIC(PSLLQ, MF_NONE, DU_U)
+BEGIN_OPCODES()
+#ifdef _HAVE_MMX_
+ {OpcodeInfo::all, {0x0F, 0xF3, _r}, {mm64, mm_m64}, DU_U },
+#endif
+ {OpcodeInfo::all, {0x66, 0x0F, 0xF3, _r}, {xmm64, xmm_m64}, DU_U },
+ {OpcodeInfo::all, {0x66, 0x0F, 0x73, _6, ib}, {xmm64, imm8}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+BEGIN_MNEMONIC(PSRLQ, MF_NONE, DU_U)
+BEGIN_OPCODES()
+#ifdef _HAVE_MMX_
+ {OpcodeInfo::all, {0x0F, 0xD3, _r}, {mm64, mm_m64}, DU_U },
+#endif
+ {OpcodeInfo::all, {0x66, 0x0F, 0xD3, _r}, {xmm64, xmm_m64}, DU_U },
+ {OpcodeInfo::all, {0x66, 0x0F, 0x73, _2, ib}, {xmm64, imm8}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PXOR, MF_NONE, DU_U)
+BEGIN_OPCODES()
+#ifdef _HAVE_MMX_
+ {OpcodeInfo::all, {0x0F, 0xEF, _r}, {mm64, mm_m64}, DU_U },
+#endif
+ {OpcodeInfo::all, {0x66, 0x0F, 0xEF, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(MOVAPD, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x28, _r}, {xmm64, xmm_m64}, D_U },
+ {OpcodeInfo::all, {0x66, 0x0F, 0x29, _r}, {xmm_m64, xmm64}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(MOVAPS, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x0F, 0x28, _r}, {xmm64, xmm_m64}, D_U },
+ {OpcodeInfo::all, {0x0F, 0x29, _r}, {xmm_m64, xmm64}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(SHUFPS, MF_NONE, D_U_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x0F, 0xC6, _r, ib}, {xmm64, xmm_m64, imm8}, D_U_U },
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(MOVSD, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF2, 0x0F, 0x10, _r}, {xmm64, xmm_m64}, D_U },
+ {OpcodeInfo::all, {0xF2, 0x0F, 0x11, _r}, {xmm_m64, xmm64}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(MOVSS, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF3, 0x0F, 0x10, _r}, {xmm32, xmm_m32}, D_U },
+ {OpcodeInfo::all, {0xF3, 0x0F, 0x11, _r}, {xmm_m32, xmm32}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(MOVSX, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {Size16, 0x0F, 0xBE, _r}, {r16, r_m8s}, D_U },
+ {OpcodeInfo::all, {0x0F, 0xBE, _r}, {r32, r_m8s}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0x0F, 0xBE, _r}, {r64, r_m8s}, D_U },
+
+ {OpcodeInfo::all, {0x0F, 0xBF, _r}, {r32, r_m16s}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0x0F, 0xBF, _r}, {r64, r_m16s}, D_U },
+
+ {OpcodeInfo::em64t, {REX_W, 0x63, _r}, {r64, r_m32s}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(MOVZX, MF_NONE, D_U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {Size16, 0x0F, 0xB6, _r}, {r16, r_m8u}, D_U },
+ {OpcodeInfo::all, {0x0F, 0xB6, _r}, {r32, r_m8u}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0x0F, 0xB6, _r}, {r64, r_m8u}, D_U },
+
+ {OpcodeInfo::all, {0x0F, 0xB7, _r}, {r32, r_m16u}, D_U },
+ {OpcodeInfo::em64t, {REX_W, 0x0F, 0xB7, _r}, {r64, r_m16u}, D_U },
+ //workaround to get r/rm32->r64 ZX mov functionality:
+ //simple 32bit reg copying zeros high bits in 64bit reg
+ {OpcodeInfo::em64t, {0x8B, _r}, {r64, r_m32u}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(MULSD, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF2, 0x0F, 0x59, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(MULSS, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF3, 0x0F, 0x59, _r}, {xmm32, xmm_m32}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(NEG, MF_AFFECTS_FLAGS, DU )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF6, _3}, {r_m8}, DU },
+
+ {OpcodeInfo::all, {Size16, 0xF7, _3}, {r_m16}, DU },
+ {OpcodeInfo::all, {0xF7, _3}, {r_m32}, DU },
+ {OpcodeInfo::em64t, {REX_W, 0xF7, _3}, {r_m64}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(NOP, MF_NONE, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x90}, {}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(NOT, MF_AFFECTS_FLAGS, DU )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF6, _2}, {r_m8}, DU },
+ {OpcodeInfo::all, {Size16, 0xF7, _2}, {r_m16}, DU },
+ {OpcodeInfo::all, {0xF7, _2}, {r_m32}, DU },
+ {OpcodeInfo::em64t, {REX_W, 0xF7, _2}, {r_m64}, DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(POP, MF_NONE, D)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {Size16, 0x8F, _0}, {r_m16}, D },
+ {OpcodeInfo::ia32, {0x8F, _0}, {r_m32}, D },
+ {OpcodeInfo::em64t, {0x8F, _0}, {r_m64}, D },
+
+ {OpcodeInfo::all, {Size16, 0x58|rw }, {r16}, D },
+ {OpcodeInfo::ia32, {0x58|rd }, {r32}, D },
+ {OpcodeInfo::em64t, {0x58|rd }, {r64}, D },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(POPFD, MF_AFFECTS_FLAGS, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x9D}, {}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PREFETCH, MF_NONE, U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x0F, 0x18, _0}, {m8}, U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PUSH, MF_NONE, U )
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {Size16, 0xFF, _6}, {r_m16}, U },
+ {OpcodeInfo::ia32, {0xFF, _6}, {r_m32}, U },
+ {OpcodeInfo::em64t, {0xFF, _6}, {r_m64}, U },
+
+ {OpcodeInfo::all, {Size16, 0x50|rw }, {r16}, U },
+ {OpcodeInfo::ia32, {0x50|rd }, {r32}, U },
+ {OpcodeInfo::em64t, {0x50|rd }, {r64}, U },
+
+ {OpcodeInfo::all, {0x6A}, {imm8}, U },
+ {OpcodeInfo::all, {Size16, 0x68}, {imm16}, U },
+ {OpcodeInfo::ia32, {0x68}, {imm32}, U },
+// {OpcodeInfo::em64t, {0x68}, {imm64}, U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PUSHFD, MF_USES_FLAGS, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x9C}, {}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(RET, MF_NONE, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xC3}, {}, N },
+ {OpcodeInfo::all, {0xC2, iw}, {imm16}, U },
+END_OPCODES()
+END_MNEMONIC()
+
+#define DEFINE_SETcc_MNEMONIC( cc ) \
+ BEGIN_MNEMONIC(SET##cc, MF_USES_FLAGS|MF_CONDITIONAL, DU) \
+BEGIN_OPCODES() \
+ {OpcodeInfo::all, {0x0F, 0x90 + ConditionMnemonic_##cc}, {r_m8}, DU }, \
+END_OPCODES() \
+END_MNEMONIC()
+
+DEFINE_SETcc_MNEMONIC(O)
+DEFINE_SETcc_MNEMONIC(NO)
+DEFINE_SETcc_MNEMONIC(B)
+DEFINE_SETcc_MNEMONIC(NB)
+DEFINE_SETcc_MNEMONIC(Z)
+DEFINE_SETcc_MNEMONIC(NZ)
+DEFINE_SETcc_MNEMONIC(BE)
+DEFINE_SETcc_MNEMONIC(NBE)
+
+DEFINE_SETcc_MNEMONIC(S)
+DEFINE_SETcc_MNEMONIC(NS)
+DEFINE_SETcc_MNEMONIC(P)
+DEFINE_SETcc_MNEMONIC(NP)
+DEFINE_SETcc_MNEMONIC(L)
+DEFINE_SETcc_MNEMONIC(NL)
+DEFINE_SETcc_MNEMONIC(LE)
+DEFINE_SETcc_MNEMONIC(NLE)
+
+#undef DEFINE_SETcc_MNEMONIC
+
+#define DEFINE_SHIFT_MNEMONIC(nam, slash_num, flags) \
+BEGIN_MNEMONIC(nam, flags, DU_U) \
+BEGIN_OPCODES()\
+ /* D0 & D1 opcodes are added w/o 2nd operand (1) because */\
+ /* they are used for decoding only so only instruction length is needed */\
+ {OpcodeInfo::decoder, {0xD0, slash_num}, {r_m8/*,const_1*/}, DU },\
+ {OpcodeInfo::all, {0xD2, slash_num}, {r_m8, CL}, DU_U },\
+ {OpcodeInfo::all, {0xC0, slash_num, ib}, {r_m8, imm8}, DU_U },\
+\
+ {OpcodeInfo::decoder, {Size16, 0xD1, slash_num}, {r_m16/*,const_1*/}, DU },\
+ {OpcodeInfo::all, {Size16, 0xD3, slash_num}, {r_m16, CL}, DU_U },\
+ {OpcodeInfo::all, {Size16, 0xC1, slash_num, ib}, {r_m16, imm8 }, DU_U },\
+\
+ {OpcodeInfo::decoder, {0xD1, slash_num}, {r_m32/*,const_1*/}, DU },\
+ {OpcodeInfo::decoder64, {REX_W, 0xD1, slash_num}, {r_m64/*,const_1*/}, DU },\
+\
+ {OpcodeInfo::all, {0xD3, slash_num}, {r_m32, CL}, DU_U },\
+ {OpcodeInfo::em64t, {REX_W, 0xD3, slash_num}, {r_m64, CL}, DU_U },\
+\
+ {OpcodeInfo::all, {0xC1, slash_num, ib}, {r_m32, imm8}, DU_U },\
+ {OpcodeInfo::em64t, {REX_W, 0xC1, slash_num, ib}, {r_m64, imm8}, DU_U },\
+END_OPCODES()\
+END_MNEMONIC()
+
+
+DEFINE_SHIFT_MNEMONIC(ROL, _0, MF_AFFECTS_FLAGS)
+DEFINE_SHIFT_MNEMONIC(ROR, _1, MF_AFFECTS_FLAGS)
+DEFINE_SHIFT_MNEMONIC(RCL, _2, MF_AFFECTS_FLAGS|MF_USES_FLAGS)
+DEFINE_SHIFT_MNEMONIC(RCR, _3, MF_AFFECTS_FLAGS|MF_USES_FLAGS)
+
+DEFINE_SHIFT_MNEMONIC(SAL, _4, MF_AFFECTS_FLAGS)
+DEFINE_SHIFT_MNEMONIC(SHR, _5, MF_AFFECTS_FLAGS)
+DEFINE_SHIFT_MNEMONIC(SAR, _7, MF_AFFECTS_FLAGS)
+
+#undef DEFINE_SHIFT_MNEMONIC
+
+BEGIN_MNEMONIC(SHLD, MF_AFFECTS_FLAGS, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x0F, 0xA5}, {r_m32, r32, CL}, DU_DU_U },
+ {OpcodeInfo::all, {0x0F, 0xA4}, {r_m32, r32, imm8}, DU_DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(SHRD, MF_AFFECTS_FLAGS, N)
+// TODO: the def/use info is wrong
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x0F, 0xAD}, {r_m32, r32, CL}, DU_DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(SUBSD, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF2, 0x0F, 0x5C, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(SUBSS, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF3, 0x0F, 0x5C, _r}, {xmm32, xmm_m32}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(TEST, MF_AFFECTS_FLAGS, U_U)
+BEGIN_OPCODES()
+
+ {OpcodeInfo::decoder, {0xA8, ib}, { AL, imm8}, U_U },
+ {OpcodeInfo::decoder, {0xA9, iw}, { AX, imm16}, U_U },
+ {OpcodeInfo::decoder, {0xA9, id}, { EAX, imm32}, U_U },
+ {OpcodeInfo::decoder64, {REX_W, 0xA9, id}, { RAX, imm32s}, U_U },
+
+ {OpcodeInfo::all, {0xF6, _0, ib}, {r_m8,imm8}, U_U },
+
+ {OpcodeInfo::all, {Size16, 0xF7, _0, iw}, {r_m16,imm16}, U_U },
+ {OpcodeInfo::all, {0xF7, _0, id}, {r_m32,imm32}, U_U },
+ {OpcodeInfo::em64t, {REX_W, 0xF7, _0, id}, {r_m64,imm32s}, U_U },
+
+ {OpcodeInfo::all, {0x84, _r}, {r_m8,r8}, U_U },
+
+ {OpcodeInfo::all, {Size16, 0x85, _r}, {r_m16,r16}, U_U },
+ {OpcodeInfo::all, {0x85, _r}, {r_m32,r32}, U_U },
+ {OpcodeInfo::em64t, {REX_W, 0x85, _r}, {r_m64,r64}, U_U },
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(UCOMISD, MF_AFFECTS_FLAGS, U_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x2E, _r}, {xmm64, xmm_m64}, U_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(UCOMISS, MF_AFFECTS_FLAGS, U_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x0F, 0x2E, _r}, {xmm32, xmm_m32}, U_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(COMISD, MF_AFFECTS_FLAGS, U_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x2F, _r}, {xmm64, xmm_m64}, U_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(COMISS, MF_AFFECTS_FLAGS, U_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x0F, 0x2F, _r}, {xmm32, xmm_m32}, U_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(XORPD, MF_SAME_ARG_NO_USE|MF_SYMMETRIC, DU_U)
+BEGIN_OPCODES()
+ //Note: they're actually 128 bits
+ {OpcodeInfo::all, {0x66, 0x0F, 0x57, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(XORPS, MF_SAME_ARG_NO_USE|MF_SYMMETRIC, DU_U)
+BEGIN_OPCODES()
+ //Note: they're actually 128 bits
+ {OpcodeInfo::all, {0x0F, 0x57, _r}, {xmm32, xmm_m32}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(CVTDQ2PD, MF_NONE, D_U )
+BEGIN_OPCODES()
+ //Note: they're actually 128 bits
+ {OpcodeInfo::all, {0xF3, 0x0F, 0xE6}, {xmm64, xmm_m64}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(CVTDQ2PS, MF_NONE, D_U )
+BEGIN_OPCODES()
+ //Note: they're actually 128 bits
+ {OpcodeInfo::all, {0x0F, 0x5B, _r}, {xmm32, xmm_m32}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(CVTTPD2DQ, MF_NONE, D_U )
+BEGIN_OPCODES()
+ //Note: they're actually 128 bits
+ {OpcodeInfo::all, {0x66, 0x0F, 0xE6}, {xmm64, xmm_m64}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(CVTTPS2DQ, MF_NONE, D_U )
+BEGIN_OPCODES()
+ //Note: they're actually 128 bits
+ {OpcodeInfo::all, {0xF3, 0x0F, 0x5B, _r}, {xmm32, xmm_m32}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+//
+// String operations
+//
+BEGIN_MNEMONIC(STD, MF_AFFECTS_FLAGS, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xFD}, {}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(CLD, MF_AFFECTS_FLAGS, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xFC}, {}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(SCAS, MF_AFFECTS_FLAGS, N)
+// to be symmetric, this mnemonic must have either m32 or RegName_EAX
+// but as long, as Jitrino's CG does not use the mnemonic, leaving it
+// in its natural form
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xAF}, {}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(STOS, MF_AFFECTS_FLAGS, DU_DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xAB}, {EDI, ECX, EAX}, DU_DU_U },
+ {OpcodeInfo::all, {0xAA}, {EDI, ECX, AL}, DU_DU_U },
+ {OpcodeInfo::em64t, {REX_W, 0xAB}, {RDI, RCX, RAX}, DU_DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+/*
+MOVS and CMPS are the special cases.
+Most the code in both CG and Encoder do not expect 2 memory operands.
+Also, they are not supposed to setup constrains on which register the
+memory reference must reside - m8,m8 or m32,m32 is not the choice.
+We can't use r8,r8 either - will have problem with 8bit EDI, ESI.
+So, as the workaround we do r32,r32 and specify size of the operand through
+the specific mnemonic - the same is in the codegen.
+*/
+BEGIN_MNEMONIC(MOVS8, MF_NONE, DU_DU_DU)
+BEGIN_OPCODES()
+ {OpcodeInfo::ia32, {0xA4}, {r32,r32,ECX}, DU_DU_DU },
+ {OpcodeInfo::em64t, {0xA4}, {r64,r64,RCX}, DU_DU_DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(MOVS16, MF_NONE, DU_DU_DU)
+BEGIN_OPCODES()
+ {OpcodeInfo::ia32, {Size16, 0xA5}, {r32,r32,ECX}, DU_DU_DU },
+ {OpcodeInfo::em64t, {Size16, 0xA5}, {r64,r64,RCX}, DU_DU_DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(MOVS32, MF_NONE, DU_DU_DU)
+BEGIN_OPCODES()
+ {OpcodeInfo::ia32, {0xA5}, {r32,r32,ECX}, DU_DU_DU },
+ {OpcodeInfo::em64t, {0xA5}, {r64,r64,RCX}, DU_DU_DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(MOVS64, MF_NONE, DU_DU_DU)
+BEGIN_OPCODES()
+ {OpcodeInfo::em64t, {REX_W,0xA5}, {r64,r64,RCX}, DU_DU_DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(CMPSB, MF_AFFECTS_FLAGS, DU_DU_DU)
+BEGIN_OPCODES()
+ {OpcodeInfo::ia32, {0xA6}, {ESI,EDI,ECX}, DU_DU_DU },
+ {OpcodeInfo::em64t, {0xA6}, {RSI,RDI,RCX}, DU_DU_DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(CMPSW, MF_AFFECTS_FLAGS, DU_DU_DU)
+BEGIN_OPCODES()
+ {OpcodeInfo::ia32, {Size16, 0xA7}, {ESI,EDI,ECX}, DU_DU_DU },
+ {OpcodeInfo::em64t, {Size16, 0xA7}, {RSI,RDI,RCX}, DU_DU_DU },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(CMPSD, MF_AFFECTS_FLAGS, DU_DU_DU)
+BEGIN_OPCODES()
+ {OpcodeInfo::ia32, {0xA7}, {ESI,EDI,ECX}, DU_DU_DU },
+ {OpcodeInfo::em64t, {0xA7}, {RSI,RDI,RCX}, DU_DU_DU },
+END_OPCODES()
+END_MNEMONIC()
+
+
+BEGIN_MNEMONIC(WAIT, MF_AFFECTS_FLAGS, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x9B}, {}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+//
+// ~String operations
+//
+
+//
+//Note: the instructions below added for the sake of disassembling routine.
+// They need to have flags, params and params usage to be defined more precisely.
+//
+BEGIN_MNEMONIC(LEAVE, MF_NONE, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::decoder, {0xC9}, {}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(ENTER, MF_NONE, N)
+BEGIN_OPCODES()
+ {OpcodeInfo::decoder, {0xC8, iw, ib}, {imm16, imm8}, N },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PADDB, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0xFC, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PADDW, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0xFD, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PADDD, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0xFE, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PSUBB, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0xF8, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PSUBW, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0xF9, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PSUBD, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0xFA, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PMULLW, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0xD5, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PMULLD, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x38, 0x40, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PSLLW, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0xF1, _r}, {xmm64, xmm_m64}, DU_U },
+ {OpcodeInfo::all, {0x66, 0x0F, 0x71, _6, ib}, {xmm64, imm8}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PSLLD, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0xF2, _r}, {xmm64, xmm_m64}, DU_U },
+ {OpcodeInfo::all, {0x66, 0x0F, 0x72, _6, ib}, {xmm64, imm8}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PSRAW, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0xE1, _r}, {xmm64, xmm_m64}, DU_U },
+ {OpcodeInfo::all, {0x66, 0x0F, 0x71, _4, ib}, {xmm64, imm8}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PSRAD, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0xE2, _r}, {xmm64, xmm_m64}, DU_U },
+ {OpcodeInfo::all, {0x66, 0x0F, 0x72, _4, ib}, {xmm64, imm8}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PSRLW, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0xD1, _r}, {xmm64, xmm_m64}, DU_U },
+ {OpcodeInfo::all, {0x66, 0x0F, 0x71, _2, ib}, {xmm64, imm8}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PSRLD, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0xD2, _r}, {xmm64, xmm_m64}, DU_U },
+ {OpcodeInfo::all, {0x66, 0x0F, 0x72, _2, ib}, {xmm64, imm8}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PMOVSXBW, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x38, 0x20, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PSHUFB, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x38, 0x00, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PSHUFD, MF_NONE, D_U_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x70, _r, ib}, {xmm64, xmm_m64, imm8}, D_U_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PSHUFLW, MF_NONE, D_U_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF2, 0x0F, 0x70, _r, ib}, {xmm64, xmm_m64, imm8}, D_U_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PSHUFHW, MF_NONE, D_U_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0xF3, 0x0F, 0x70, _r, ib}, {xmm64, xmm_m64, imm8}, D_U_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PHADDSW, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x38, 0x03, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PHADDW, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x38, 0x01, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PHADDD, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x38, 0x02, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PHSUBSW, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x38, 0x07, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PHSUBW, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x38, 0x05, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PHSUBD, MF_NONE, DU_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x38, 0x06, _r}, {xmm64, xmm_m64}, DU_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PEXTRB, MF_NONE, D_U_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x3A, 0x14, _r, ib}, {r32, xmm64, imm8}, D_U_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PEXTRW, MF_NONE, D_U_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0xC5, _r, ib}, {r32, xmm64, imm8}, D_U_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(PEXTRD, MF_NONE, D_U_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x3A, 0x16, _r, ib}, {r_m32, xmm64, imm8}, D_U_U },
+END_OPCODES()
+END_MNEMONIC()
+
+BEGIN_MNEMONIC(MOVDQA, MF_NONE|MF_SYMMETRIC, D_U)
+BEGIN_OPCODES()
+ {OpcodeInfo::all, {0x66, 0x0F, 0x6F, _r}, {xmm64, xmm_m64}, D_U },
+ //The encoder cannot properly look up when operands are symmetric but opcode is not:
+ //{OpcodeInfo::all, {0x66, 0x0F, 0x7F, _r}, {xmm_m128, xmm128}, D_U },
+END_OPCODES()
+END_MNEMONIC()
+
+}; // ~masterEncodingTable[]
+
+ENCODER_NAMESPACE_END
+
+ENCODER_NAMESPACE_START
+
+static int compareMnemonicInfo(const void* info1, const void* info2)
+{
+ Mnemonic id1, id2;
+
+ id1 = ((const MnemonicInfo*) info1)->mn;
+ id2 = ((const MnemonicInfo*) info2)->mn;
+ if (id1 < id2)
+ return -1;
+ if (id1 > id2)
+ return 1;
+ return 0;
+}
+
+int EncoderBase::buildTable(void)
+{
+ // A check: all mnemonics must be covered
+ assert(COUNTOF(masterEncodingTable) == Mnemonic_Count);
+
+ // sort out the mnemonics so the list become ordered
+ qsort(masterEncodingTable, Mnemonic_Count, sizeof(MnemonicInfo), compareMnemonicInfo);
+
+ //
+ // clear the things
+ //
+ memset(opcodesHashMap, NOHASH, sizeof(opcodesHashMap));
+ memset(opcodes, 0, sizeof(opcodes));
+ //
+ // and, finally, build it
+ for (unsigned i=0; i<Mnemonic_Count; i++) {
+ assert((Mnemonic)i == (masterEncodingTable + i)->mn);
+ buildMnemonicDesc(masterEncodingTable+i);
+ }
+ return 0;
+}
+
+void EncoderBase::buildMnemonicDesc(const MnemonicInfo * minfo)
+{
+ MnemonicDesc& mdesc = mnemonics[minfo->mn];
+ mdesc.mn = minfo->mn;
+ mdesc.flags = minfo->flags;
+ mdesc.roles = minfo->roles;
+ mdesc.name = minfo->name;
+
+ //
+ // fill the used opcodes
+ //
+ for (unsigned i=0, oindex=0; i<COUNTOF(minfo->opcodes); i++) {
+
+ const OpcodeInfo& oinfo = minfo->opcodes[i];
+ OpcodeDesc& odesc = opcodes[minfo->mn][oindex];
+ // last opcode ?
+ if (oinfo.opcode[0] == OpcodeByteKind_LAST) {
+ // mark the opcode 'last', exit
+ odesc.opcode_len = 0;
+ odesc.last = 1;
+ break;
+ }
+ odesc.last = 0;
+#ifdef _EM64T_
+ if (oinfo.platf == OpcodeInfo::ia32) { continue; }
+ if (oinfo.platf == OpcodeInfo::decoder32) { continue; }
+#else
+ if (oinfo.platf == OpcodeInfo::em64t) { continue; }
+ if (oinfo.platf == OpcodeInfo::decoder64) { continue; }
+#endif
+ if (oinfo.platf == OpcodeInfo::decoder64 ||
+ oinfo.platf == OpcodeInfo::decoder32) {
+ odesc.platf = OpcodeInfo::decoder;
+ }
+ else {
+ odesc.platf = (char)oinfo.platf;
+ }
+ //
+ // fill out opcodes
+ //
+ unsigned j = 0;
+ odesc.opcode_len = 0;
+ for(; oinfo.opcode[j]; j++) {
+ unsigned opcod = oinfo.opcode[j];
+ unsigned kind = opcod&OpcodeByteKind_KindMask;
+ if (kind == OpcodeByteKind_REX_W) {
+ odesc.opcode[odesc.opcode_len++] = (unsigned char)0x48;
+ continue;
+ }
+ else if(kind != 0 && kind != OpcodeByteKind_ZeroOpcodeByte) {
+ break;
+ }
+ unsigned lowByte = (opcod & OpcodeByteKind_OpcodeMask);
+ odesc.opcode[odesc.opcode_len++] = (unsigned char)lowByte;
+ }
+ assert(odesc.opcode_len<5);
+ odesc.aux0 = odesc.aux1 = 0;
+ if (oinfo.opcode[j] != 0) {
+ odesc.aux0 = oinfo.opcode[j];
+ assert((odesc.aux0 & OpcodeByteKind_KindMask) != 0);
+ ++j;
+ if(oinfo.opcode[j] != 0) {
+ odesc.aux1 = oinfo.opcode[j];
+ assert((odesc.aux1 & OpcodeByteKind_KindMask) != 0);
+ }
+ }
+ else if (oinfo.roles.count>=2) {
+ if (((oinfo.opnds[0].kind&OpndKind_Mem) &&
+ (isRegKind(oinfo.opnds[1].kind))) ||
+ ((oinfo.opnds[1].kind&OpndKind_Mem) &&
+ (isRegKind(oinfo.opnds[0].kind)))) {
+ // Example: MOVQ xmm1, xmm/m64 has only opcodes
+ // same with SHRD
+ // Adding fake /r
+ odesc.aux0 = _r;
+ }
+ }
+ else if (oinfo.roles.count==1) {
+ if (oinfo.opnds[0].kind&OpndKind_Mem) {
+ // Example: SETcc r/m8, adding fake /0
+ odesc.aux0 = _0;
+ }
+ }
+ // check imm
+ if (oinfo.roles.count > 0 &&
+ (oinfo.opnds[0].kind == OpndKind_Imm ||
+ oinfo.opnds[oinfo.roles.count-1].kind == OpndKind_Imm)) {
+ // Example: CALL cd, PUSH imm32 - they fit both opnds[0] and
+ // opnds[oinfo.roles.count-1].
+ // The A3 opcode fits only opnds[0] - it's currently have
+ // MOV imm32, EAX. Looks ridiculous, but this is how the
+ // moffset is currently implemented. Will need to fix together
+ // with other usages of moff.
+ // adding fake /cd or fake /id
+ unsigned imm_opnd_index =
+ oinfo.opnds[0].kind == OpndKind_Imm ? 0 : oinfo.roles.count-1;
+ OpndSize sz = oinfo.opnds[imm_opnd_index].size;
+ unsigned imm_encode, coff_encode;
+ if (sz==OpndSize_8) {imm_encode = ib; coff_encode=cb; }
+ else if (sz==OpndSize_16) {imm_encode = iw; coff_encode=cw;}
+ else if (sz==OpndSize_32) {imm_encode = id; coff_encode=cd; }
+ else if (sz==OpndSize_64) {imm_encode = io; coff_encode=0xCC; }
+ else { assert(false); imm_encode=0xCC; coff_encode=0xCC; }
+ if (odesc.aux1 == 0) {
+ if (odesc.aux0==0) {
+ odesc.aux0 = imm_encode;
+ }
+ else {
+ if (odesc.aux0 != imm_encode && odesc.aux0 != coff_encode) {
+ odesc.aux1 = imm_encode;
+ }
+ }
+ }
+ else {
+ assert(odesc.aux1==imm_encode);
+ }
+
+ }
+
+ assert(sizeof(odesc.opnds) == sizeof(oinfo.opnds));
+ memcpy(odesc.opnds, oinfo.opnds,
+ sizeof(EncoderBase::OpndDesc)
+ * EncoderBase::MAX_NUM_OPCODE_OPERANDS);
+ odesc.roles = oinfo.roles;
+ odesc.first_opnd = 0;
+ if (odesc.opnds[0].reg != RegName_Null) {
+ ++odesc.first_opnd;
+ if (odesc.opnds[1].reg != RegName_Null) {
+ ++odesc.first_opnd;
+ }
+ }
+
+ if (odesc.platf == OpcodeInfo::decoder) {
+ // if the opcode is only for decoding info, then do not hash it.
+ ++oindex;
+ continue;
+ }
+
+ //
+ // check whether the operand info is a mask (i.e. r_m*).
+ // in this case, split the info to have separate entries for 'r'
+ // and for 'm'.
+ // the good news is that there can be only one such operand.
+ //
+ int opnd2split = -1;
+ for (unsigned k=0; k<oinfo.roles.count; k++) {
+ if ((oinfo.opnds[k].kind & OpndKind_Mem) &&
+ (OpndKind_Mem != oinfo.opnds[k].kind)) {
+ opnd2split = k;
+ break;
+ }
+ };
+
+ if (opnd2split == -1) {
+ // not a mask, hash it, store it, continue.
+ unsigned short hash = getHash(&oinfo);
+ opcodesHashMap[minfo->mn][hash] = (unsigned char)oindex;
+ ++oindex;
+ continue;
+ };
+
+ OpcodeInfo storeItem = oinfo;
+ unsigned short hash;
+
+ // remove the memory part of the mask, and store only 'r' part
+ storeItem.opnds[opnd2split].kind = (OpndKind)(storeItem.opnds[opnd2split].kind & ~OpndKind_Mem);
+ hash = getHash(&storeItem);
+ if (opcodesHashMap[minfo->mn][hash] == NOHASH) {
+ opcodesHashMap[minfo->mn][hash] = (unsigned char)oindex;
+ }
+ // else {
+ // do not overwrite if there is something there, just check that operands match
+ // the reason is that for some instructions there are several possibilities:
+ // say 'DEC r' may be encode as either '48+r' or 'FF /1', and I believe
+ // the first one is better for 'dec r'.
+ // as we're currently processing an opcode with memory part in operand,
+ // leave already filled items intact, so if there is 'OP reg' there, this
+ // better choice will be left in the table instead of 'OP r_m'
+ // }
+
+ // compute hash of memory-based operand, 'm' part in 'r_m'
+ storeItem.opnds[opnd2split].kind = OpndKind_Mem;
+ hash = getHash(&storeItem);
+ // should not happen: for the r_m opcodes, there is a possibility
+ // that hash value of 'r' part intersects with 'OP r' value, but it's
+ // impossible for 'm' part.
+ assert(opcodesHashMap[minfo->mn][hash] == NOHASH);
+ opcodesHashMap[minfo->mn][hash] = (unsigned char)oindex;
+
+ ++oindex;
+ }
+}
+
+ENCODER_NAMESPACE_END