LCOV - code coverage report
Current view: top level - asmjit - x86assembler.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 186 1705 10.9 %
Date: 2024-10-18 14:00:27 Functions: 4 7 57.1 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             : Copyright (c) 2008-2017, Petr Kobalicek
       3             : 
       4             : This software is provided 'as-is', without any express or implied
       5             : warranty. In no event will the authors be held liable for any damages
       6             : arising from the use of this software.
       7             : 
       8             : Permission is granted to anyone to use this software for any purpose,
       9             : including commercial applications, and to alter it and redistribute it
      10             : freely, subject to the following restrictions:
      11             : 
      12             : 1. The origin of this software must not be misrepresented; you must not
      13             :    claim that you wrote the original software. If you use this software
      14             :    in a product, an acknowledgment in the product documentation would be
      15             :    appreciated but is not required.
      16             : 2. Altered source versions must be plainly marked as such, and must not be
      17             :    misrepresented as being the original software.
      18             : 3. This notice may not be removed or altered from any source distribution.
      19             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      20             : #ifdef __PLUMED_HAS_ASMJIT
      21             : #pragma GCC diagnostic push
      22             : #pragma GCC diagnostic ignored "-Wpedantic"
      23             : // [AsmJit]
      24             : // Complete x86/x64 JIT and Remote Assembler for C++.
      25             : //
      26             : // [License]
      27             : // Zlib - See LICENSE.md file in the package.
      28             : 
      29             : // [Export]
      30             : #define ASMJIT_EXPORTS
      31             : 
      32             : // [Guard]
      33             : #include "./asmjit_build.h"
      34             : #if defined(ASMJIT_BUILD_X86)
      35             : 
      36             : // [Dependencies]
      37             : #include "./cpuinfo.h"
      38             : #include "./logging.h"
      39             : #include "./misc_p.h"
      40             : #include "./utils.h"
      41             : #include "./x86assembler.h"
      42             : #include "./x86logging_p.h"
      43             : 
      44             : // [Api-Begin]
      45             : #include "./asmjit_apibegin.h"
      46             : 
      47             : namespace PLMD {
      48             : namespace asmjit {
      49             : 
      50             : // ============================================================================
      51             : // [FastUInt8]
      52             : // ============================================================================
      53             : 
      54             : #if ASMJIT_ARCH_X86 || ASMJIT_ARCH_X64
      55             : typedef unsigned char FastUInt8;
      56             : #else
      57             : typedef unsigned int FastUInt8;
      58             : #endif
      59             : 
      60             : // ============================================================================
      61             : // [Constants]
      62             : // ============================================================================
      63             : 
      64             : //! \internal
      65             : //!
      66             : //! X86/X64 bytes used to encode important prefixes.
      67             : enum X86Byte {
      68             :   //! 1-byte REX prefix mask.
      69             :   kX86ByteRex = 0x40,
      70             : 
      71             :   //! 1-byte REX.W component.
      72             :   kX86ByteRexW = 0x08,
      73             : 
      74             :   //! 2-byte VEX prefix:
      75             :   //!   - `[0]` - `0xC5`.
      76             :   //!   - `[1]` - `RvvvvLpp`.
      77             :   kX86ByteVex2 = 0xC5,
      78             : 
      79             :   //! 3-byte VEX prefix.
      80             :   //!   - `[0]` - `0xC4`.
      81             :   //!   - `[1]` - `RXBmmmmm`.
      82             :   //!   - `[2]` - `WvvvvLpp`.
      83             :   kX86ByteVex3 = 0xC4,
      84             : 
      85             :   //! 3-byte XOP prefix.
      86             :   //!   - `[0]` - `0x8F`.
      87             :   //!   - `[1]` - `RXBmmmmm`.
      88             :   //!   - `[2]` - `WvvvvLpp`.
      89             :   kX86ByteXop3 = 0x8F,
      90             : 
      91             :   //! 4-byte EVEX prefix.
      92             :   //!   - `[0]` - `0x62`.
      93             :   //!   - `[1]` - Payload0 or `P[ 7: 0]` - `[R  X  B  R' 0  0  m  m]`.
      94             :   //!   - `[2]` - Payload1 or `P[15: 8]` - `[W  v  v  v  v  1  p  p]`.
      95             :   //!   - `[3]` - Payload2 or `P[23:16]` - `[z  L' L  b  V' a  a  a]`.
      96             :   //!
      97             :   //! Groups:
      98             :   //!   - `P[ 1: 0]` - OPCODE: EVEX.mmmmm, only lowest 2 bits [1:0] used.
      99             :   //!   - `P[ 3: 2]` - ______: Must be 0.
     100             :   //!   - `P[    4]` - REG-ID: EVEX.R' - 5th bit of 'RRRRR'.
     101             :   //!   - `P[    5]` - REG-ID: EVEX.B  - 4th bit of 'BBBBB'.
     102             :   //!   - `P[    6]` - REG-ID: EVEX.X  - 5th bit of 'BBBBB' or 4th bit of 'XXXX' (with SIB).
     103             :   //!   - `P[    7]` - REG-ID: EVEX.R  - 4th bit of 'RRRRR'.
     104             :   //!   - `P[ 9: 8]` - OPCODE: EVEX.pp.
     105             :   //!   - `P[   10]` - ______: Must be 1.
     106             :   //!   - `P[14:11]` - REG-ID: 4 bits of 'VVVV'.
     107             :   //!   - `P[   15]` - OPCODE: EVEX.W.
     108             :   //!   - `P[18:16]` - REG-ID: K register k0...k7 (Merging/Zeroing Vector Ops).
     109             :   //!   - `P[   19]` - REG-ID: 5th bit of 'VVVVV'.
     110             :   //!   - `P[   20]` - OPCODE: Broadcast/Rounding Control/SAE bit.
     111             :   //!   - `P[22.21]` - OPCODE: Vector Length (L' and  L) / Rounding Control.
     112             :   //!   - `P[   23]` - OPCODE: Zeroing/Merging.
     113             :   kX86ByteEvex = 0x62
     114             : };
     115             : 
     116             : // AsmJit specific (used to encode VVVVV field in XOP/VEX/EVEX).
     117             : enum VexVVVVV {
     118             :   kVexVVVVVShift = 7,
     119             :   kVexVVVVVMask = 0x1F << kVexVVVVVShift
     120             : };
     121             : 
     122             : //! \internal
     123             : //!
     124             : //! Instruction 2-byte/3-byte opcode prefix definition.
     125             : struct X86OpCodeMM {
     126             :   uint8_t len;
     127             :   uint8_t data[3];
     128             : };
     129             : 
     130             : //! \internal
     131             : //!
     132             : //! Mandatory prefixes used to encode legacy [66, F3, F2] or [9B] byte.
     133             : static const uint8_t x86OpCodePP[8] = { 0x00, 0x66, 0xF3, 0xF2, 0x00, 0x00, 0x00, 0x9B };
     134             : 
     135             : //! \internal
     136             : //!
     137             : //! Instruction 2-byte/3-byte opcode prefix data.
     138             : static const X86OpCodeMM x86OpCodeMM[] = {
     139             :   { 0, { 0x00, 0x00, 0 } }, // #00 (0b0000).
     140             :   { 1, { 0x0F, 0x00, 0 } }, // #01 (0b0001).
     141             :   { 2, { 0x0F, 0x38, 0 } }, // #02 (0b0010).
     142             :   { 2, { 0x0F, 0x3A, 0 } }, // #03 (0b0011).
     143             :   { 2, { 0x0F, 0x01, 0 } }, // #04 (0b0100).
     144             :   { 0, { 0x00, 0x00, 0 } }, // #05 (0b0101).
     145             :   { 0, { 0x00, 0x00, 0 } }, // #06 (0b0110).
     146             :   { 0, { 0x00, 0x00, 0 } }, // #07 (0b0111).
     147             :   { 0, { 0x00, 0x00, 0 } }, // #08 (0b1000).
     148             :   { 0, { 0x00, 0x00, 0 } }, // #09 (0b1001).
     149             :   { 0, { 0x00, 0x00, 0 } }, // #0A (0b1010).
     150             :   { 0, { 0x00, 0x00, 0 } }, // #0B (0b1011).
     151             :   { 0, { 0x00, 0x00, 0 } }, // #0C (0b1100).
     152             :   { 0, { 0x00, 0x00, 0 } }, // #0D (0b1101).
     153             :   { 0, { 0x00, 0x00, 0 } }, // #0E (0b1110).
     154             :   { 0, { 0x00, 0x00, 0 } }  // #0F (0b1111).
     155             : };
     156             : 
     157             : static const uint8_t x86SegmentPrefix[8] = { 0x00, 0x26, 0x2E, 0x36, 0x3E, 0x64, 0x65, 0x00 };
     158             : static const uint8_t x86OpCodePushSeg[8] = { 0x00, 0x06, 0x0E, 0x16, 0x1E, 0xA0, 0xA8, 0x00 };
     159             : static const uint8_t x86OpCodePopSeg[8]  = { 0x00, 0x07, 0x00, 0x17, 0x1F, 0xA1, 0xA9, 0x00 };
     160             : 
     161             : // ============================================================================
     162             : // [asmjit::X86MemInfo | X86VEXPrefix | X86LLByRegType | X86CDisp8Table]
     163             : // ============================================================================
     164             : 
     165             : //! \internal
     166             : //!
     167             : //! Memory operand's info bits.
     168             : //!
     169             : //! A lookup table that contains various information based on the BASE and INDEX
     170             : //! information of a memory operand. This is much better and safer than playing
     171             : //! with IFs in the code and can check for errors must faster and better.
     172             : enum X86MemInfo_Enum {
     173             :   kX86MemInfo_0         = 0x00,
     174             : 
     175             :   kX86MemInfo_BaseGp    = 0x01, //!< Has BASE reg, REX.B can be 1, compatible with REX.B byte.
     176             :   kX86MemInfo_Index     = 0x02, //!< Has INDEX reg, REX.X can be 1, compatible with REX.X byte.
     177             : 
     178             :   kX86MemInfo_BaseLabel = 0x10, //!< Base is Label.
     179             :   kX86MemInfo_BaseRip   = 0x20, //!< Base is RIP.
     180             : 
     181             :   kX86MemInfo_67H_X86   = 0x40, //!< Address-size override in 32-bit mode.
     182             :   kX86MemInfo_67H_X64   = 0x80, //!< Address-size override in 64-bit mode.
     183             :   kX86MemInfo_67H_Mask  = 0xC0  //!< Contains all address-size override bits.
     184             : };
     185             : 
     186             : template<uint32_t X>
     187             : struct X86MemInfo_T {
     188             :   enum {
     189             :     B = (X     ) & 0x1F,
     190             :     I = (X >> 5) & 0x1F,
     191             : 
     192             :     kBase  = ((B >= X86Reg::kRegGpw  && B <= X86Reg::kRegGpq ) ? kX86MemInfo_BaseGp    :
     193             :               (B == X86Reg::kRegRip                          ) ? kX86MemInfo_BaseRip   :
     194             :               (B == Label::kLabelTag                         ) ? kX86MemInfo_BaseLabel : 0),
     195             : 
     196             :     kIndex = ((I >= X86Reg::kRegGpw  && I <= X86Reg::kRegGpq ) ? kX86MemInfo_Index     :
     197             :               (I >= X86Reg::kRegXmm  && I <= X86Reg::kRegZmm ) ? kX86MemInfo_Index     : 0),
     198             : 
     199             :     k67H   = ((B == X86Reg::kRegGpw  && I == X86Reg::kRegNone) ? kX86MemInfo_67H_X86   :
     200             :               (B == X86Reg::kRegGpd  && I == X86Reg::kRegNone) ? kX86MemInfo_67H_X64   :
     201             :               (B == X86Reg::kRegNone && I == X86Reg::kRegGpw ) ? kX86MemInfo_67H_X86   :
     202             :               (B == X86Reg::kRegNone && I == X86Reg::kRegGpd ) ? kX86MemInfo_67H_X64   :
     203             :               (B == X86Reg::kRegGpw  && I == X86Reg::kRegGpw ) ? kX86MemInfo_67H_X86   :
     204             :               (B == X86Reg::kRegGpd  && I == X86Reg::kRegGpd ) ? kX86MemInfo_67H_X64   :
     205             :               (B == X86Reg::kRegGpw  && I == X86Reg::kRegXmm ) ? kX86MemInfo_67H_X86   :
     206             :               (B == X86Reg::kRegGpd  && I == X86Reg::kRegXmm ) ? kX86MemInfo_67H_X64   :
     207             :               (B == X86Reg::kRegGpw  && I == X86Reg::kRegYmm ) ? kX86MemInfo_67H_X86   :
     208             :               (B == X86Reg::kRegGpd  && I == X86Reg::kRegYmm ) ? kX86MemInfo_67H_X64   :
     209             :               (B == X86Reg::kRegGpw  && I == X86Reg::kRegZmm ) ? kX86MemInfo_67H_X86   :
     210             :               (B == X86Reg::kRegGpd  && I == X86Reg::kRegZmm ) ? kX86MemInfo_67H_X64   :
     211             :               (B == Label::kLabelTag && I == X86Reg::kRegGpw ) ? kX86MemInfo_67H_X86   :
     212             :               (B == Label::kLabelTag && I == X86Reg::kRegGpd ) ? kX86MemInfo_67H_X64   : 0),
     213             : 
     214             :     kValue = kBase | kIndex | k67H | 0x04 | 0x08
     215             :   };
     216             : };
     217             : 
     218             : // The result stored in the LUT is a combination of
     219             : //   - 67H - Address override prefix - depends on BASE+INDEX register types and
     220             : //           the target architecture.
     221             : //   - REX - A possible combination of REX.[B|X|R|W] bits in REX prefix where
     222             : //           REX.B and REX.X are possibly masked out, but REX.R and REX.W are
     223             : //           kept as is.
     224             : static const uint8_t x86MemInfo[] = { ASMJIT_TABLE_T_1024(X86MemInfo_T, kValue, 0) };
     225             : 
     226             : // VEX3 or XOP xor bits applied to the opcode before emitted. The index to this
     227             : // table is 'mmmmm' value, which contains all we need. This is only used by a
     228             : // 3 BYTE VEX and XOP prefixes, 2 BYTE VEX prefix is handled differently. The
     229             : // idea is to minimize the difference between VEX3 vs XOP when encoding VEX
     230             : // or XOP instruction. This should minimize the code required to emit such
     231             : // instructions and should also make it faster as we don't need any branch to
     232             : // decide between VEX3 vs XOP.
     233             : //            ____    ___
     234             : // [_OPCODE_|WvvvvLpp|RXBmmmmm|VEX3_XOP]
     235             : template<uint32_t X>
     236             : struct X86VEXPrefix_T {
     237             :   enum { kValue = ((X & 0x08) ? kX86ByteXop3 : kX86ByteVex3) | (0xF << 19) | (0x7 << 13) };
     238             : };
     239             : static const uint32_t x86VEXPrefix[] = { ASMJIT_TABLE_T_16(X86VEXPrefix_T, kValue, 0) };
     240             : 
     241             : // Table that contains LL opcode field addressed by a register size / 16. It's
     242             : // used to propagate L.256 or L.512 when YMM or ZMM registers are used,
     243             : // respectively.
     244             : template<uint32_t X>
     245             : struct X86LLBySizeDiv16_T {
     246             :   enum {
     247             :     kValue = (X & (64 >> 4)) ? X86Inst::kOpCode_LL_512 :
     248             :              (X & (32 >> 4)) ? X86Inst::kOpCode_LL_256 : 0
     249             :   };
     250             : };
     251             : static const uint32_t x86LLBySizeDiv16[] = { ASMJIT_TABLE_T_16(X86LLBySizeDiv16_T, kValue, 0) };
     252             : 
     253             : // Table that contains LL opcode field addressed by a register size / 16. It's
     254             : // used to propagate L.256 or L.512 when YMM or ZMM registers are used,
     255             : // respectively.
     256             : template<uint32_t X>
     257             : struct X86LLByRegType_T {
     258             :   enum {
     259             :     kValue = X == X86Reg::kRegZmm ? X86Inst::kOpCode_LL_512 :
     260             :              X == X86Reg::kRegYmm ? X86Inst::kOpCode_LL_256 : 0
     261             :   };
     262             : };
     263             : static const uint32_t x86LLByRegType[] = { ASMJIT_TABLE_T_16(X86LLByRegType_T, kValue, 0) };
     264             : 
     265             : // Table that contains a scale (shift left) based on 'TTWLL' field and
     266             : // the instruction's tuple-type (TT) field. The scale is then applied to
     267             : // the BASE-N stored in each opcode to calculate the final compressed
     268             : // displacement used by all EVEX encoded instructions.
     269             : template<uint32_t X>
     270             : struct X86CDisp8SHL_T {
     271             :   enum {
     272             :     TT = (((X) >> 3) << X86Inst::kOpCode_CDTT_Shift),
     273             :     LL = (((X) >> 0) & 0x3),
     274             :     W  = (((X) >> 2) & 0x1),
     275             : 
     276             :     kValue = (TT == X86Inst::kOpCode_CDTT_None ? ((LL==0) ? 0 : (LL==1) ? 0   : 0  ) :
     277             :               TT == X86Inst::kOpCode_CDTT_ByLL ? ((LL==0) ? 0 : (LL==1) ? 1   : 2  ) :
     278             :               TT == X86Inst::kOpCode_CDTT_T1W  ? ((LL==0) ? W : (LL==1) ? 1+W : 2+W) :
     279             :               TT == X86Inst::kOpCode_CDTT_DUP  ? ((LL==0) ? 0 : (LL==1) ? 2   : 3  ) : 0 ) << X86Inst::kOpCode_CDSHL_Shift
     280             :   };
     281             : };
     282             : static const uint32_t x86CDisp8SHL[] = { ASMJIT_TABLE_T_32(X86CDisp8SHL_T, kValue, 0) };
     283             : 
     284             : // Table that contains MOD byte of a 16-bit [BASE + disp] address.
     285             : //   0xFF == Invalid.
     286             : static const uint8_t x86Mod16BaseTable[8] = {
     287             :   0xFF, // AX -> N/A.
     288             :   0xFF, // CX -> N/A.
     289             :   0xFF, // DX -> N/A.
     290             :   0x07, // BX -> 111.
     291             :   0xFF, // SP -> N/A.
     292             :   0x06, // BP -> 110.
     293             :   0x04, // SI -> 100.
     294             :   0x05  // DI -> 101.
     295             : };
     296             : 
     297             : // Table that contains MOD byte of a 16-bit [BASE + INDEX + disp] combination.
     298             : //   0xFF == Invalid.
     299             : template<uint32_t X>
     300             : struct X86Mod16BaseIndexTable_T {
     301             :   enum {
     302             :     B = X >> 3,
     303             :     I = X & 0x7,
     304             : 
     305             :     kValue = ((B == X86Gp::kIdBx && I == X86Gp::kIdSi) || (B == X86Gp::kIdSi && I == X86Gp::kIdBx)) ? 0x00 :
     306             :              ((B == X86Gp::kIdBx && I == X86Gp::kIdDi) || (B == X86Gp::kIdDi && I == X86Gp::kIdBx)) ? 0x01 :
     307             :              ((B == X86Gp::kIdBp && I == X86Gp::kIdSi) || (B == X86Gp::kIdSi && I == X86Gp::kIdBp)) ? 0x02 :
     308             :              ((B == X86Gp::kIdBp && I == X86Gp::kIdDi) || (B == X86Gp::kIdDi && I == X86Gp::kIdBp)) ? 0x03 : 0xFF
     309             :   };
     310             : };
     311             : static const uint8_t x86Mod16BaseIndexTable[] = { ASMJIT_TABLE_T_64(X86Mod16BaseIndexTable_T, kValue, 0) };
     312             : 
     313             : // ============================================================================
     314             : // [asmjit::X86Assembler - Helpers]
     315             : // ============================================================================
     316             : 
     317             : static ASMJIT_INLINE bool x86IsJmpOrCall(uint32_t instId) noexcept {
     318           0 :   return instId == X86Inst::kIdJmp ||
     319           0 :          instId == X86Inst::kIdCall;
     320             : }
     321             : 
     322             : static ASMJIT_INLINE bool x86IsImplicitMem(const Operand_& op, uint32_t base) noexcept {
     323           0 :   return op.isMem() && op.as<X86Mem>().getBaseId() == base;
     324             : }
     325             : 
     326             : static ASMJIT_INLINE int64_t x86SignExtend32To64(int64_t imm) noexcept {
     327           0 :   return static_cast<int64_t>(static_cast<int32_t>(imm & 0xFFFFFFFF));
     328             : }
     329             : 
     330             : //! Get `O` field of `opCode`.
     331             : static ASMJIT_INLINE uint32_t x86ExtractO(uint32_t opCode) noexcept {
     332      593300 :   return (opCode >> X86Inst::kOpCode_O_Shift) & 0x07;
     333             : }
     334             : 
     335             : static ASMJIT_INLINE uint32_t x86ExtractREX(uint32_t opCode, uint32_t options) noexcept {
     336             :   // kOpCode_REX was designed in a way that when shifted there will be no bytes
     337             :   // set except REX.[B|X|R|W]. The returned value forms a real REX prefix byte.
     338             :   // This case is tested by `X86Inst.cpp`.
     339      593300 :   return (opCode | options) >> X86Inst::kOpCode_REX_Shift;
     340             : }
     341             : 
     342             : //! Combine `regId` and `vvvvvId` into a single value (used by AVX and AVX-512).
     343             : static ASMJIT_INLINE uint32_t x86PackRegAndVvvvv(uint32_t regId, uint32_t vvvvvId) noexcept {
     344           0 :   return regId + (vvvvvId << kVexVVVVVShift);
     345             : }
     346             : 
     347             : static ASMJIT_INLINE uint32_t x86OpCodeLByVMem(const Operand_& op) noexcept {
     348           0 :   return x86LLByRegType[op.as<X86Mem>().getIndexType()];
     349             : }
     350             : 
     351             : static ASMJIT_INLINE uint32_t x86OpCodeLBySize(uint32_t size) noexcept {
     352           0 :   return x86LLBySizeDiv16[size / 16];
     353             : }
     354             : 
     355             : static ASMJIT_INLINE uint32_t x86ExtractLLMM(uint32_t opCode, uint32_t options) noexcept {
     356           0 :   uint32_t x = opCode & (X86Inst::kOpCode_LL_Mask | X86Inst::kOpCode_MM_Mask);
     357           0 :   uint32_t y = options & X86Inst::kOptionVex3;
     358           0 :   return (x | y) >> X86Inst::kOpCode_MM_Shift;
     359             : }
     360             : 
     361             : //! Encode MOD byte.
     362             : static ASMJIT_INLINE uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) noexcept {
     363             :   ASMJIT_ASSERT(m <= 3);
     364             :   ASMJIT_ASSERT(o <= 7);
     365             :   ASMJIT_ASSERT(rm <= 7);
     366           0 :   return (m << 6) + (o << 3) + rm;
     367             : }
     368             : 
     369             : //! Encode SIB byte.
     370             : static ASMJIT_INLINE uint32_t x86EncodeSib(uint32_t s, uint32_t i, uint32_t b) noexcept {
     371             :   ASMJIT_ASSERT(s <= 3);
     372             :   ASMJIT_ASSERT(i <= 7);
     373             :   ASMJIT_ASSERT(b <= 7);
     374           0 :   return (s << 6) + (i << 3) + b;
     375             : }
     376             : 
     377             : // ============================================================================
     378             : // [asmjit::X86Assembler - Construction / Destruction]
     379             : // ============================================================================
     380             : 
     381       32111 : X86Assembler::X86Assembler(CodeHolder* code) noexcept : Assembler() {
     382       32111 :   if (code)
     383       32111 :     code->attach(this);
     384       32111 : }
     385       32111 : X86Assembler::~X86Assembler() noexcept {}
     386             : 
     387             : // ============================================================================
     388             : // [asmjit::X86Assembler - Events]
     389             : // ============================================================================
     390             : 
     391       32111 : Error X86Assembler::onAttach(CodeHolder* code) noexcept {
     392             :   uint32_t archType = code->getArchType();
     393       32111 :   if (!ArchInfo::isX86Family(archType))
     394             :     return DebugUtils::errored(kErrorInvalidArch);
     395             : 
     396       32111 :   ASMJIT_PROPAGATE(Base::onAttach(code));
     397             : 
     398       32111 :   if (archType == ArchInfo::kTypeX86) {
     399             :     // 32 bit architecture - X86.
     400             :     _setAddressOverrideMask(kX86MemInfo_67H_X86);
     401           0 :     _globalOptions |= X86Inst::_kOptionInvalidRex;
     402           0 :     _nativeGpArray = x86OpData.gpd;
     403             :   }
     404             :   else {
     405             :     // 64 bit architecture - X64 or X32.
     406             :     _setAddressOverrideMask(kX86MemInfo_67H_X64);
     407       32111 :     _nativeGpArray = x86OpData.gpq;
     408             :   }
     409             : 
     410       32111 :   _nativeGpReg = _nativeGpArray[0];
     411       32111 :   return kErrorOk;
     412             : }
     413             : 
     414           0 : Error X86Assembler::onDetach(CodeHolder* code) noexcept {
     415           0 :   return Base::onDetach(code);
     416             : }
     417             : 
     418             : // ============================================================================
     419             : // [asmjit::X86Assembler - Helpers]
     420             : // ============================================================================
     421             : 
     422             : #define EMIT_BYTE(VAL)                               \
     423             :   do {                                               \
     424             :     cursor[0] = static_cast<uint8_t>((VAL) & 0xFFU); \
     425             :     cursor += 1;                                     \
     426             :   } while (0)
     427             : 
     428             : #define EMIT_16(VAL)                                 \
     429             :   do {                                               \
     430             :     Utils::writeU16uLE(cursor,                       \
     431             :       static_cast<uint32_t>((VAL) & 0xFFFFU));       \
     432             :     cursor += 2;                                     \
     433             :   } while (0)
     434             : 
     435             : #define EMIT_32(VAL)                                 \
     436             :   do {                                               \
     437             :     Utils::writeU32uLE(cursor,                       \
     438             :       static_cast<uint32_t>((VAL) & 0xFFFFFFFFU));   \
     439             :     cursor += 4;                                     \
     440             :   } while (0)
     441             : 
     442             : #define ADD_66H_P(EXP)                                                   \
     443             :   do {                                                                   \
     444             :     opCode |= (static_cast<uint32_t>(EXP) << X86Inst::kOpCode_PP_Shift); \
     445             :   } while (0)
     446             : 
     447             : #define ADD_66H_P_BY_SIZE(SIZE)                                          \
     448             :   do {                                                                   \
     449             :     opCode |= (static_cast<uint32_t>((SIZE) & 0x02))                     \
     450             :            << (X86Inst::kOpCode_PP_Shift - 1);                           \
     451             :   } while (0)
     452             : 
     453             : #define ADD_REX_W(EXP)                                                   \
     454             :   do {                                                                   \
     455             :     if (EXP)                                                             \
     456             :       opCode |= X86Inst::kOpCode_W;                                      \
     457             :   } while (0)
     458             : 
     459             : #define ADD_REX_W_BY_SIZE(SIZE)                                          \
     460             :   do {                                                                   \
     461             :     if ((SIZE) == 8)                                                     \
     462             :       opCode |= X86Inst::kOpCode_W;                                      \
     463             :   } while (0)
     464             : 
     465             : #define ADD_PREFIX_BY_SIZE(SIZE)                                         \
     466             :   do {                                                                   \
     467             :     ADD_66H_P_BY_SIZE(SIZE);                                             \
     468             :     ADD_REX_W_BY_SIZE(SIZE);                                             \
     469             :   } while (0)
     470             : 
     471             : #define ADD_VEX_W(EXP)                                                   \
     472             :   do {                                                                   \
     473             :     opCode |= static_cast<uint32_t>(EXP) << X86Inst::kOpCode_W_Shift;    \
     474             :   } while (0)
     475             : 
     476             : #define EMIT_PP(OPCODE)                                                  \
     477             :   do {                                                                   \
     478             :     uint32_t ppIndex =                                                   \
     479             :       ((OPCODE                   ) >> X86Inst::kOpCode_PP_Shift) &       \
     480             :       (X86Inst::kOpCode_PP_FPUMask >> X86Inst::kOpCode_PP_Shift) ;       \
     481             :     uint8_t ppCode = x86OpCodePP[ppIndex];                               \
     482             :                                                                          \
     483             :     cursor[0] = ppCode;                                                  \
     484             :     cursor   += ppIndex != 0;                                            \
     485             :   } while (0)
     486             : 
     487             : #define EMIT_MM_OP(OPCODE)                                               \
     488             :   do {                                                                   \
     489             :     uint32_t op = OPCODE & (0x00FF | X86Inst::kOpCode_MM_Mask);          \
     490             :                                                                          \
     491             :     uint32_t mmIndex = op >> X86Inst::kOpCode_MM_Shift;                  \
     492             :     const X86OpCodeMM& mmCode = x86OpCodeMM[mmIndex];                    \
     493             :                                                                          \
     494             :     if (mmIndex) {                                                       \
     495             :       cursor[0] = mmCode.data[0];                                        \
     496             :       cursor[1] = mmCode.data[1];                                        \
     497             :       cursor   += mmCode.len;                                            \
     498             :     }                                                                    \
     499             :                                                                          \
     500             :     EMIT_BYTE(op);                                                       \
     501             :   } while (0)
     502             : 
     503             : // If the operand is BPL|SPL|SIL|DIL|R8B-15B
     504             : //   - Force REX prefix
     505             : // If the operand is AH|BH|CH|DH
     506             : //   - patch its index from 0..3 to 4..7 as encoded by X86.
     507             : //   - Disallow REX prefix.
     508             : #define FIXUP_GPB(REG_OP, REG_ID)                                   \
     509             :   do {                                                                   \
     510             :     if (!static_cast<const X86Gp&>(REG_OP).isGpbHi()) {                  \
     511             :       options |= (REG_ID >= 4) ? X86Inst::kOptionRex : 0;                \
     512             :     }                                                                    \
     513             :     else {                                                               \
     514             :       options |= X86Inst::_kOptionInvalidRex;                            \
     515             :       REG_ID += 4;                                                       \
     516             :     }                                                                    \
     517             :   } while (0)
     518             : 
     519             : #define ENC_OPS1(OP0)                     ((Operand::kOp##OP0))
     520             : #define ENC_OPS2(OP0, OP1)                ((Operand::kOp##OP0) + ((Operand::kOp##OP1) << 3))
     521             : #define ENC_OPS3(OP0, OP1, OP2)           ((Operand::kOp##OP0) + ((Operand::kOp##OP1) << 3) + ((Operand::kOp##OP2) << 6))
     522             : #define ENC_OPS4(OP0, OP1, OP2, OP3)      ((Operand::kOp##OP0) + ((Operand::kOp##OP1) << 3) + ((Operand::kOp##OP2) << 6) + ((Operand::kOp##OP3) << 9))
     523             : 
     524             : // ============================================================================
     525             : // [asmjit::X86Assembler - Emit]
     526             : // ============================================================================
     527             : 
     528      593300 : Error X86Assembler::_emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) {
     529             :   Error err;
     530             : 
     531             :   const Operand_* rmRel;         // Memory operand or operand that holds Label|Imm.
     532             :   uint32_t rmInfo;               // Memory operand's info based on x86MemInfo.
     533             :   uint32_t rbReg;                // Memory base or modRM register.
     534             :   uint32_t rxReg;                // Memory index register.
     535             :   uint32_t opReg;                // ModR/M opcode or register id.
     536             :   uint32_t opCode;               // Instruction opcode.
     537             : 
     538             :   LabelEntry* label;             // Label entry.
     539      593300 :   RelocEntry* re = nullptr;      // Relocation entry.
     540             :   int32_t relOffset;             // Relative offset
     541             :   FastUInt8 relSize = 0;         // Relative size.
     542             : 
     543             :   int64_t imVal = 0;             // Immediate value (must be 64-bit).
     544             :   FastUInt8 imLen = 0;           // Immediate length.
     545             : 
     546             :   const uint32_t kSHR_W_PP = X86Inst::kOpCode_PP_Shift - 16;
     547             :   const uint32_t kSHR_W_EW = X86Inst::kOpCode_EW_Shift - 23;
     548             : 
     549      593300 :   uint8_t* cursor = _bufferPtr;
     550      593300 :   uint32_t options = static_cast<uint32_t>(instId >= X86Inst::_kIdCount)       |
     551      593300 :                      static_cast<uint32_t>((size_t)(_bufferEnd - cursor) < 16) |
     552      593300 :                      getGlobalOptions() | getOptions();
     553             : 
     554      593300 :   const X86Inst* instData = X86InstDB::instData + instId;
     555             :   const X86Inst::CommonData* commonData;
     556             : 
     557             :   // Handle failure and rare cases first.
     558             :   const uint32_t kErrorsAndSpecialCases =
     559             :     CodeEmitter::kOptionMaybeFailureCase | // Error and buffer check.
     560             :     CodeEmitter::kOptionStrictValidation | // Strict validation.
     561             :     X86Inst::kOptionRep                  | // REP/REPZ prefix.
     562             :     X86Inst::kOptionRepnz                | // REPNZ prefix.
     563             :     X86Inst::kOptionLock                 | // LOCK prefix.
     564             :     X86Inst::kOptionXAcquire             | // XACQUIRE prefix.
     565             :     X86Inst::kOptionXRelease             ; // XRELEASE prefix.
     566             : 
     567             :   // Signature of the first 3 operands.
     568      593300 :   uint32_t isign3 = o0.getOp() + (o1.getOp() << 3) + (o2.getOp() << 6);
     569             : 
     570      593300 :   if (ASMJIT_UNLIKELY(options & kErrorsAndSpecialCases)) {
     571             :     // Don't do anything if we are in error state.
     572       32111 :     if (_lastError) return _lastError;
     573             : 
     574       32111 :     if (options & CodeEmitter::kOptionMaybeFailureCase) {
     575             :       // Unknown instruction.
     576       32111 :       if (ASMJIT_UNLIKELY(instId >= X86Inst::_kIdCount))
     577           0 :         goto InvalidArgument;
     578             : 
     579             :       // Grow request, happens rarely.
     580       32111 :       if ((size_t)(_bufferEnd - cursor) < 16) {
     581       32111 :         err = _code->growBuffer(&_section->_buffer, 16);
     582       32111 :         if (ASMJIT_UNLIKELY(err)) goto Failed;
     583             : 
     584       32111 :         cursor = _bufferPtr;
     585       32111 :         options &= ~1;
     586             :       }
     587             :     }
     588             : 
     589             :     // Strict validation.
     590             : #if !defined(ASMJIT_DISABLE_VALIDATION)
     591       32111 :     if (options & CodeEmitter::kOptionStrictValidation) {
     592             :       Operand_ opArray[6];
     593             : 
     594             :       opArray[0].copyFrom(o0);
     595             :       opArray[1].copyFrom(o1);
     596             :       opArray[2].copyFrom(o2);
     597             :       opArray[3].copyFrom(o3);
     598             : 
     599           0 :       if (options & kOptionOp4Op5Used) {
     600             :         opArray[4].copyFrom(_op4);
     601             :         opArray[5].copyFrom(_op5);
     602             :       }
     603             :       else {
     604             :         opArray[4].reset();
     605             :         opArray[5].reset();
     606             :       }
     607             : 
     608           0 :       err = Inst::validate(getArchType(), Inst::Detail(instId, options, _extraReg), opArray, 6);
     609           0 :       if (ASMJIT_UNLIKELY(err)) goto Failed;
     610             :     }
     611             : #endif // !ASMJIT_DISABLE_VALIDATION
     612             : 
     613             :     uint32_t iFlags = instData->getFlags();
     614             : 
     615             :     // LOCK, XACQUIRE, and XRELEASE prefixes.
     616       32111 :     if (options & X86Inst::kOptionLock) {
     617           0 :       bool xAcqRel = (options & (X86Inst::kOptionXAcquire | X86Inst::kOptionXRelease)) != 0;
     618             : 
     619           0 :       if (ASMJIT_UNLIKELY(!(iFlags & (X86Inst::kFlagLock)) && !xAcqRel))
     620           0 :         goto InvalidLockPrefix;
     621             : 
     622           0 :       if (xAcqRel) {
     623           0 :         if (ASMJIT_UNLIKELY((options & X86Inst::kOptionXAcquire) && !(iFlags & X86Inst::kFlagXAcquire)))
     624           0 :           goto InvalidXAcquirePrefix;
     625             : 
     626           0 :         if (ASMJIT_UNLIKELY((options & X86Inst::kOptionXRelease) && !(iFlags & X86Inst::kFlagXRelease)))
     627           0 :           goto InvalidXReleasePrefix;
     628             : 
     629           0 :         EMIT_BYTE((options & X86Inst::kOptionXAcquire) ? 0xF2 : 0xF3);
     630             :       }
     631             : 
     632           0 :       EMIT_BYTE(0xF0);
     633             :     }
     634             : 
     635             :     // REP and REPNZ prefixes.
     636       32111 :     if (options & (X86Inst::kOptionRep | X86Inst::kOptionRepnz)) {
     637           0 :       if (ASMJIT_UNLIKELY(!(iFlags & (X86Inst::kFlagRep | X86Inst::kFlagRepnz))))
     638           0 :         goto InvalidRepPrefix;
     639             : 
     640           0 :       if (_extraReg.isValid() && ASMJIT_UNLIKELY(_extraReg.getKind() != X86Reg::kKindGp || _extraReg.getId() != X86Gp::kIdCx))
     641           0 :         goto InvalidRepPrefix;
     642             : 
     643           0 :       EMIT_BYTE((options & X86Inst::kOptionRepnz) ? 0xF2 : 0xF3);
     644             :     }
     645             :   }
     646             : 
     647             :   // --------------------------------------------------------------------------
     648             :   // [Encoding Scope]
     649             :   // --------------------------------------------------------------------------
     650             : 
     651             :   opCode = instData->getMainOpCode();
     652             :   opReg = x86ExtractO(opCode);
     653             :   commonData = &instData->getCommonData();
     654             : 
     655      593300 :   switch (instData->getEncodingType()) {
     656           0 :     case X86Inst::kEncodingNone:
     657           0 :       goto EmitDone;
     658             : 
     659             :     // ------------------------------------------------------------------------
     660             :     // [X86]
     661             :     // ------------------------------------------------------------------------
     662             : 
     663           0 :     case X86Inst::kEncodingX86Op:
     664           0 :       goto EmitX86Op;
     665             : 
     666           0 :     case X86Inst::kEncodingX86Op_O_I8:
     667           0 :       if (ASMJIT_UNLIKELY(isign3 != ENC_OPS1(Imm)))
     668           0 :         goto InvalidInstruction;
     669             : 
     670           0 :       imVal = o0.as<Imm>().getUInt8();
     671             :       imLen = 1;
     672             :       ASMJIT_FALLTHROUGH;
     673             : 
     674           0 :     case X86Inst::kEncodingX86Op_O:
     675             :       rbReg = 0;
     676           0 :       goto EmitX86R;
     677             : 
     678           0 :     case X86Inst::kEncodingX86Op_xAX:
     679           0 :       if (isign3 == 0)
     680           0 :         goto EmitX86Op;
     681             : 
     682           0 :       if (isign3 == ENC_OPS1(Reg) && o0.getId() == X86Gp::kIdAx)
     683           0 :         goto EmitX86Op;
     684             :       break;
     685             : 
     686           0 :     case X86Inst::kEncodingX86Op_xDX_xAX:
     687           0 :       if (isign3 == 0)
     688           0 :         goto EmitX86Op;
     689             : 
     690           0 :       if (isign3 == ENC_OPS2(Reg, Reg) && o0.getId() == X86Gp::kIdDx &&
     691             :                                           o1.getId() == X86Gp::kIdAx)
     692           0 :         goto EmitX86Op;
     693             :       break;
     694             : 
     695           0 :     case X86Inst::kEncodingX86Op_ZAX:
     696           0 :       if (isign3 == 0)
     697           0 :         goto EmitX86Op;
     698             : 
     699             :       rmRel = &o0;
     700           0 :       if (isign3 == ENC_OPS1(Mem) && x86IsImplicitMem(o0, X86Gp::kIdAx))
     701           0 :         goto EmitX86OpImplicitMem;
     702             : 
     703             :       break;
     704             : 
     705           0 :     case X86Inst::kEncodingX86I_xAX:
     706             :       // Implicit form.
     707           0 :       if (isign3 == ENC_OPS1(Imm)) {
     708           0 :         imVal = o0.as<Imm>().getUInt8();
     709             :         imLen = 1;
     710           0 :         goto EmitX86Op;
     711             :       }
     712             : 
     713             :       // Explicit form.
     714           0 :       if (isign3 == ENC_OPS2(Reg, Imm) && o0.getId() == X86Gp::kIdAx) {
     715           0 :         imVal = o1.as<Imm>().getUInt8();
     716             :         imLen = 1;
     717           0 :         goto EmitX86Op;
     718             :       }
     719             :       break;
     720             : 
     721             :     case X86Inst::kEncodingX86M:
     722             :       rbReg = o0.getId();
     723           0 :       ADD_PREFIX_BY_SIZE(o0.getSize());
     724             : 
     725           0 :       if (isign3 == ENC_OPS1(Reg))
     726           0 :         goto EmitX86R;
     727             : 
     728             :       rmRel = &o0;
     729           0 :       if (isign3 == ENC_OPS1(Mem))
     730           0 :         goto EmitX86M;
     731             :       break;
     732             : 
     733             :     case X86Inst::kEncodingX86M_GPB_MulDiv:
     734           0 : CaseX86M_GPB_MulDiv:
     735             :       // Explicit form?
     736           0 :       if (isign3 > 0x7) {
     737             :         // [AX] <- [AX] div|mul r8.
     738           0 :         if (isign3 == ENC_OPS2(Reg, Reg)) {
     739           0 :           if (ASMJIT_UNLIKELY(!X86Reg::isGpw(o0, X86Gp::kIdAx) || !X86Reg::isGpb(o1)))
     740           0 :             goto InvalidInstruction;
     741             : 
     742             :           rbReg = o1.getId();
     743           0 :           FIXUP_GPB(o1, rbReg);
     744           0 :           goto EmitX86R;
     745             :         }
     746             : 
     747             :         // [AX] <- [AX] div|mul m8.
     748           0 :         if (isign3 == ENC_OPS2(Reg, Mem)) {
     749           0 :           if (ASMJIT_UNLIKELY(!X86Reg::isGpw(o0, X86Gp::kIdAx)))
     750           0 :             goto InvalidInstruction;
     751             : 
     752             :           rmRel = &o1;
     753           0 :           goto EmitX86M;
     754             :         }
     755             : 
     756             :         // [?DX:?AX] <- [?DX:?AX] div|mul r16|r32|r64
     757           0 :         if (isign3 == ENC_OPS3(Reg, Reg, Reg)) {
     758           0 :           if (ASMJIT_UNLIKELY(o0.getSize() != o1.getSize()))
     759           0 :             goto InvalidInstruction;
     760             :           rbReg = o2.getId();
     761             : 
     762           0 :           opCode++;
     763           0 :           ADD_PREFIX_BY_SIZE(o0.getSize());
     764           0 :           goto EmitX86R;
     765             :         }
     766             : 
     767             :         // [?DX:?AX] <- [?DX:?AX] div|mul m16|m32|m64
     768           0 :         if (isign3 == ENC_OPS3(Reg, Reg, Mem)) {
     769           0 :           if (ASMJIT_UNLIKELY(o0.getSize() != o1.getSize()))
     770           0 :             goto InvalidInstruction;
     771             :           rmRel = &o2;
     772             : 
     773           0 :           opCode++;
     774           0 :           ADD_PREFIX_BY_SIZE(o0.getSize());
     775           0 :           goto EmitX86M;
     776             :         }
     777             : 
     778           0 :         goto InvalidInstruction;
     779             :       }
     780             : 
     781             :       ASMJIT_FALLTHROUGH;
     782             : 
     783             :     case X86Inst::kEncodingX86M_GPB:
     784           0 :       if (isign3 == ENC_OPS1(Reg)) {
     785             :         rbReg = o0.getId();
     786           0 :         if (o0.getSize() == 1) {
     787           0 :           FIXUP_GPB(o0, rbReg);
     788           0 :           goto EmitX86R;
     789             :         }
     790             :         else {
     791           0 :           opCode++;
     792           0 :           ADD_PREFIX_BY_SIZE(o0.getSize());
     793           0 :           goto EmitX86R;
     794             :         }
     795             :       }
     796             : 
     797           0 :       if (isign3 == ENC_OPS1(Mem)) {
     798           0 :         if (ASMJIT_UNLIKELY(o0.getSize() == 0))
     799           0 :           goto AmbiguousOperandSize;
     800             :         rmRel = &o0;
     801             : 
     802           0 :         opCode += o0.getSize() != 1;
     803           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
     804           0 :         goto EmitX86M;
     805             :       }
     806             :       break;
     807             : 
     808           0 :     case X86Inst::kEncodingX86M_Only:
     809           0 :       if (isign3 == ENC_OPS1(Mem)) {
     810             :         rmRel = &o0;
     811           0 :         goto EmitX86M;
     812             :       }
     813             :       break;
     814             : 
     815             :     case X86Inst::kEncodingX86Rm:
     816           0 :       ADD_PREFIX_BY_SIZE(o0.getSize());
     817             :       ASMJIT_FALLTHROUGH;
     818             : 
     819             :     case X86Inst::kEncodingX86Rm_NoRexW:
     820           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
     821             :         opReg = o0.getId();
     822             :         rbReg = o1.getId();
     823           0 :         goto EmitX86R;
     824             :       }
     825             : 
     826           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
     827             :         opReg = o0.getId();
     828             :         rmRel = &o1;
     829           0 :         goto EmitX86M;
     830             :       }
     831             :       break;
     832             : 
     833           0 :     case X86Inst::kEncodingX86Rm_Raw66H:
     834             :       // We normally emit either [66|F2|F3], this instruction requires 66+[F2|F3].
     835           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
     836             :         opReg = o0.getId();
     837             :         rbReg = o1.getId();
     838             : 
     839           0 :         if (o0.getSize() == 2)
     840           0 :           EMIT_BYTE(0x66);
     841             :         else
     842           0 :           ADD_REX_W_BY_SIZE(o0.getSize());
     843           0 :         goto EmitX86R;
     844             :       }
     845             : 
     846           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
     847             :         opReg = o0.getId();
     848             :         rmRel = &o1;
     849             : 
     850           0 :         if (o0.getSize() == 2)
     851           0 :           EMIT_BYTE(0x66);
     852             :         else
     853           0 :           ADD_REX_W_BY_SIZE(o0.getSize());
     854           0 :         goto EmitX86M;
     855             :       }
     856             :       break;
     857             : 
     858             :     case X86Inst::kEncodingX86Mr:
     859           0 :       ADD_PREFIX_BY_SIZE(o0.getSize());
     860             :       ASMJIT_FALLTHROUGH;
     861             : 
     862             :     case X86Inst::kEncodingX86Mr_NoSize:
     863           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
     864             :         rbReg = o0.getId();
     865             :         opReg = o1.getId();
     866           0 :         goto EmitX86R;
     867             :       }
     868             : 
     869           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
     870             :         rmRel = &o0;
     871             :         opReg = o1.getId();
     872           0 :         goto EmitX86M;
     873             :       }
     874             :       break;
     875             : 
     876        9424 :     case X86Inst::kEncodingX86Arith:
     877        9424 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
     878           0 :         if (o0.getSize() != o1.getSize())
     879           0 :           goto OperandSizeMismatch;
     880             : 
     881             :         opReg = o0.getId();
     882             :         rbReg = o1.getId();
     883             : 
     884           0 :         if (o0.getSize() == 1) {
     885           0 :           opCode += 2;
     886           0 :           FIXUP_GPB(o0, opReg);
     887           0 :           FIXUP_GPB(o1, rbReg);
     888             : 
     889           0 :           if (!(options & X86Inst::kOptionModMR))
     890           0 :             goto EmitX86R;
     891             : 
     892             :           opCode -= 2;
     893             :           Utils::swap(opReg, rbReg);
     894           0 :           goto EmitX86R;
     895             :         }
     896             :         else {
     897           0 :           opCode += 3;
     898           0 :           ADD_PREFIX_BY_SIZE(o0.getSize());
     899             : 
     900           0 :           if (!(options & X86Inst::kOptionModMR))
     901           0 :             goto EmitX86R;
     902             : 
     903           0 :           opCode -= 2;
     904             :           Utils::swap(opReg, rbReg);
     905           0 :           goto EmitX86R;
     906             :         }
     907             :       }
     908             : 
     909        9424 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
     910             :         opReg = o0.getId();
     911             :         rmRel = &o1;
     912             : 
     913           0 :         if (o0.getSize() == 1) {
     914           0 :           FIXUP_GPB(o0, opReg);
     915           0 :           opCode += 2;
     916           0 :           goto EmitX86M;
     917             :         }
     918             :         else {
     919           0 :           opCode += 3;
     920           0 :           ADD_PREFIX_BY_SIZE(o0.getSize());
     921           0 :           goto EmitX86M;
     922             :         }
     923             :       }
     924             : 
     925        9424 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
     926             :         opReg = o1.getId();
     927             :         rmRel = &o0;
     928             : 
     929           0 :         if (o1.getSize() == 1) {
     930           0 :           FIXUP_GPB(o1, opReg);
     931           0 :           goto EmitX86M;
     932             :         }
     933             :         else {
     934           0 :           opCode++;
     935           0 :           ADD_PREFIX_BY_SIZE(o1.getSize());
     936           0 :           goto EmitX86M;
     937             :         }
     938             :       }
     939             : 
     940             :       // The remaining instructions use 0x80 opcode.
     941             :       opCode = 0x80;
     942             : 
     943        9424 :       if (isign3 == ENC_OPS2(Reg, Imm)) {
     944        9424 :         uint32_t size = o0.getSize();
     945             : 
     946             :         rbReg = o0.getId();
     947             :         imVal = static_cast<const Imm&>(o1).getInt64();
     948             : 
     949        9424 :         if (size == 1) {
     950           0 :           FIXUP_GPB(o0, rbReg);
     951             :           imLen = 1;
     952             :         }
     953             :         else {
     954        9424 :           if (size == 2) {
     955             :             ADD_66H_P(1);
     956             :           }
     957        9424 :           else if (size == 4) {
     958             :             // Sign extend so isInt8 returns the right result.
     959             :             imVal = x86SignExtend32To64(imVal);
     960             :           }
     961        9424 :           else if (size == 8) {
     962             :             // In 64-bit mode it's not possible to use 64-bit immediate.
     963        9424 :             if (Utils::isUInt32(imVal)) {
     964             :               // Zero-extend `and` by using a 32-bit GPD destination instead of a 64-bit GPQ.
     965        9424 :               if (instId == X86Inst::kIdAnd)
     966           0 :                 size = 4;
     967        9424 :               else if (!Utils::isInt32(imVal))
     968           0 :                 goto InvalidImmediate;
     969             :             }
     970        9424 :             ADD_REX_W_BY_SIZE(size);
     971             :           }
     972             : 
     973       18848 :           imLen = std::min<uint32_t>(size, 4);
     974        9424 :           if (Utils::isInt8(imVal) && !(options & X86Inst::kOptionLongForm))
     975             :             imLen = 1;
     976             :         }
     977             : 
     978             :         // Alternate Form - AL, AX, EAX, RAX.
     979        9424 :         if (rbReg == 0 && (size == 1 || imLen != 1) && !(options & X86Inst::kOptionLongForm)) {
     980           0 :           opCode &= X86Inst::kOpCode_PP_66 | X86Inst::kOpCode_W;
     981           0 :           opCode |= ((opReg << 3) | (0x04 + (size != 1)));
     982           0 :           imLen = std::min<uint32_t>(size, 4);
     983           0 :           goto EmitX86Op;
     984             :         }
     985             : 
     986        9424 :         opCode += size != 1 ? (imLen != 1 ? 1 : 3) : 0;
     987        9424 :         goto EmitX86R;
     988             :       }
     989             : 
     990           0 :       if (isign3 == ENC_OPS2(Mem, Imm)) {
     991           0 :         uint32_t memSize = o0.getSize();
     992             : 
     993           0 :         if (ASMJIT_UNLIKELY(memSize == 0))
     994           0 :           goto AmbiguousOperandSize;
     995             : 
     996             :         imVal = static_cast<const Imm&>(o1).getInt64();
     997           0 :         imLen = std::min<uint32_t>(memSize, 4);
     998             : 
     999             :         // Sign extend so isInt8 returns the right result.
    1000           0 :         if (memSize == 4)
    1001             :           imVal = x86SignExtend32To64(imVal);
    1002             : 
    1003           0 :         if (Utils::isInt8(imVal) && !(options & X86Inst::kOptionLongForm))
    1004             :           imLen = 1;
    1005             : 
    1006           0 :         opCode += memSize != 1 ? (imLen != 1 ? 1 : 3) : 0;
    1007           0 :         ADD_PREFIX_BY_SIZE(memSize);
    1008             : 
    1009             :         rmRel = &o0;
    1010           0 :         goto EmitX86M;
    1011             :       }
    1012             :       break;
    1013             : 
    1014           0 :     case X86Inst::kEncodingX86Bswap:
    1015           0 :       if (isign3 == ENC_OPS1(Reg)) {
    1016           0 :         if (ASMJIT_UNLIKELY(o0.getSize() < 4))
    1017           0 :           goto InvalidInstruction;
    1018             : 
    1019             :         opReg = o0.getId();
    1020           0 :         ADD_REX_W_BY_SIZE(o0.getSize());
    1021           0 :         goto EmitX86OpReg;
    1022             :       }
    1023             :       break;
    1024             : 
    1025           0 :     case X86Inst::kEncodingX86Bt:
    1026           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    1027           0 :         ADD_PREFIX_BY_SIZE(o1.getSize());
    1028             :         opReg = o1.getId();
    1029             :         rbReg = o0.getId();
    1030           0 :         goto EmitX86R;
    1031             :       }
    1032             : 
    1033           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    1034           0 :         ADD_PREFIX_BY_SIZE(o1.getSize());
    1035             :         opReg = o1.getId();
    1036             :         rmRel = &o0;
    1037           0 :         goto EmitX86M;
    1038             :       }
    1039             : 
    1040             :       // The remaining instructions use the secondary opcode/r.
    1041             :       imVal = static_cast<const Imm&>(o1).getInt64();
    1042             :       imLen = 1;
    1043             : 
    1044             :       opCode = commonData->getAltOpCode();
    1045             :       opReg = x86ExtractO(opCode);
    1046           0 :       ADD_PREFIX_BY_SIZE(o0.getSize());
    1047             : 
    1048           0 :       if (isign3 == ENC_OPS2(Reg, Imm)) {
    1049             :         rbReg = o0.getId();
    1050           0 :         goto EmitX86R;
    1051             :       }
    1052             : 
    1053           0 :       if (isign3 == ENC_OPS2(Mem, Imm)) {
    1054           0 :         if (ASMJIT_UNLIKELY(o0.getSize() == 0))
    1055           0 :           goto AmbiguousOperandSize;
    1056             : 
    1057             :         rmRel = &o0;
    1058           0 :         goto EmitX86M;
    1059             :       }
    1060             :       break;
    1061             : 
    1062       13122 :     case X86Inst::kEncodingX86Call:
    1063       13122 :       if (isign3 == ENC_OPS1(Reg)) {
    1064             :         rbReg = o0.getId();
    1065       13122 :         goto EmitX86R;
    1066             :       }
    1067             : 
    1068             :       rmRel = &o0;
    1069           0 :       if (isign3 == ENC_OPS1(Mem))
    1070           0 :         goto EmitX86M;
    1071             : 
    1072             :       // Call with 32-bit displacement use 0xE8 opcode. Call with 8-bit
    1073             :       // displacement is not encodable so the alternative opcode field
    1074             :       // in X86DB must be zero.
    1075             :       opCode = 0xE8;
    1076             :       opReg = 0;
    1077           0 :       goto EmitJmpCall;
    1078             : 
    1079           0 :     case X86Inst::kEncodingX86Cmpxchg: {
    1080             :       // Convert explicit to implicit.
    1081           0 :       if (isign3 & (0x7 << 6)) {
    1082           0 :         if (!X86Reg::isGp(o2) || o2.getId() != X86Gp::kIdAx)
    1083           0 :           goto InvalidInstruction;
    1084           0 :         isign3 &= 0x3F;
    1085             :       }
    1086             : 
    1087           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    1088           0 :         if (o0.getSize() != o1.getSize())
    1089           0 :           goto OperandSizeMismatch;
    1090             : 
    1091             :         rbReg = o0.getId();
    1092             :         opReg = o1.getId();
    1093             : 
    1094           0 :         if (o0.getSize() == 1) {
    1095           0 :           FIXUP_GPB(o0, rbReg);
    1096           0 :           FIXUP_GPB(o1, opReg);
    1097           0 :           goto EmitX86R;
    1098             :         }
    1099             :         else {
    1100           0 :           ADD_PREFIX_BY_SIZE(o0.getSize());
    1101           0 :           opCode++;
    1102           0 :           goto EmitX86R;
    1103             :         }
    1104             :       }
    1105             : 
    1106           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    1107             :         opReg = o1.getId();
    1108             :         rmRel = &o0;
    1109             : 
    1110           0 :         if (o1.getSize() == 1) {
    1111           0 :           FIXUP_GPB(o0, opReg);
    1112           0 :           goto EmitX86M;
    1113             :         }
    1114             :         else {
    1115           0 :           ADD_PREFIX_BY_SIZE(o1.getSize());
    1116           0 :           opCode++;
    1117           0 :           goto EmitX86M;
    1118             :         }
    1119             :       }
    1120             :       break;
    1121             :     }
    1122             : 
    1123             :     case X86Inst::kEncodingX86Crc:
    1124             :       opReg = o0.getId();
    1125           0 :       ADD_REX_W_BY_SIZE(o0.getSize());
    1126             : 
    1127           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    1128             :         rbReg = o1.getId();
    1129             : 
    1130           0 :         if (o1.getSize() == 1) {
    1131           0 :           FIXUP_GPB(o1, rbReg);
    1132           0 :           goto EmitX86R;
    1133             :         }
    1134             :         else {
    1135             :           // This seems to be the only exception of encoding 66F2 PP prefix.
    1136           0 :           if (o1.getSize() == 2) EMIT_BYTE(0x66);
    1137             : 
    1138           0 :           opCode++;
    1139           0 :           goto EmitX86R;
    1140             :         }
    1141             :       }
    1142             : 
    1143           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    1144             :         rmRel = &o1;
    1145           0 :         if (o1.getSize() == 0)
    1146           0 :           goto AmbiguousOperandSize;
    1147             : 
    1148             :         // This seems to be the only exception of encoding 66F2 PP prefix.
    1149           0 :         if (o1.getSize() == 2) EMIT_BYTE(0x66);
    1150             : 
    1151           0 :         opCode += o1.getSize() != 1;
    1152           0 :         goto EmitX86M;
    1153             :       }
    1154             :       break;
    1155             : 
    1156           0 :     case X86Inst::kEncodingX86Enter:
    1157           0 :       if (isign3 == ENC_OPS2(Imm, Imm)) {
    1158             :         uint32_t iw = static_cast<const Imm&>(o0).getUInt16();
    1159             :         uint32_t ib = static_cast<const Imm&>(o1).getUInt8();
    1160             : 
    1161           0 :         imVal = iw | (ib << 16);
    1162             :         imLen = 3;
    1163           0 :         goto EmitX86Op;
    1164             :       }
    1165             :       break;
    1166             : 
    1167           0 :     case X86Inst::kEncodingX86Imul:
    1168             :       // First process all forms distinct of `kEncodingX86M_OptB_MulDiv`.
    1169           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Imm)) {
    1170             :         opCode = 0x6B;
    1171           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
    1172             : 
    1173             :         imVal = static_cast<const Imm&>(o2).getInt64();
    1174             :         imLen = 1;
    1175             : 
    1176           0 :         if (!Utils::isInt8(imVal) || (options & X86Inst::kOptionLongForm)) {
    1177           0 :           opCode -= 2;
    1178           0 :           imLen = o0.getSize() == 2 ? 2 : 4;
    1179             :         }
    1180             : 
    1181             :         opReg = o0.getId();
    1182             :         rbReg = o1.getId();
    1183             : 
    1184           0 :         goto EmitX86R;
    1185             :       }
    1186             : 
    1187           0 :       if (isign3 == ENC_OPS3(Reg, Mem, Imm)) {
    1188             :         opCode = 0x6B;
    1189           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
    1190             : 
    1191             :         imVal = static_cast<const Imm&>(o2).getInt64();
    1192             :         imLen = 1;
    1193             : 
    1194             :         // Sign extend so isInt8 returns the right result.
    1195           0 :         if (o0.getSize() == 4)
    1196             :           imVal = x86SignExtend32To64(imVal);
    1197             : 
    1198           0 :         if (!Utils::isInt8(imVal) || (options & X86Inst::kOptionLongForm)) {
    1199           0 :           opCode -= 2;
    1200           0 :           imLen = o0.getSize() == 2 ? 2 : 4;
    1201             :         }
    1202             : 
    1203             :         opReg = o0.getId();
    1204             :         rmRel = &o1;
    1205             : 
    1206           0 :         goto EmitX86M;
    1207             :       }
    1208             : 
    1209           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    1210             :         // Must be explicit 'ax, r8' form.
    1211           0 :         if (o1.getSize() == 1)
    1212           0 :           goto CaseX86M_GPB_MulDiv;
    1213             : 
    1214           0 :         if (o0.getSize() != o1.getSize())
    1215           0 :           goto OperandSizeMismatch;
    1216             : 
    1217             :         opReg = o0.getId();
    1218             :         rbReg = o1.getId();
    1219             : 
    1220             :         opCode = X86Inst::kOpCode_MM_0F | 0xAF;
    1221           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
    1222           0 :         goto EmitX86R;
    1223             :       }
    1224             : 
    1225           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    1226             :         // Must be explicit 'ax, m8' form.
    1227           0 :         if (o1.getSize() == 1)
    1228           0 :           goto CaseX86M_GPB_MulDiv;
    1229             : 
    1230             :         opReg = o0.getId();
    1231             :         rmRel = &o1;
    1232             : 
    1233             :         opCode = X86Inst::kOpCode_MM_0F | 0xAF;
    1234           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
    1235           0 :         goto EmitX86M;
    1236             :       }
    1237             : 
    1238             :       // Shorthand to imul 'reg, reg, imm'.
    1239           0 :       if (isign3 == ENC_OPS2(Reg, Imm)) {
    1240             :         opCode = 0x6B;
    1241           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
    1242             : 
    1243             :         imVal = static_cast<const Imm&>(o1).getInt64();
    1244             :         imLen = 1;
    1245             : 
    1246             :         // Sign extend so isInt8 returns the right result.
    1247           0 :         if (o0.getSize() == 4)
    1248             :           imVal = x86SignExtend32To64(imVal);
    1249             : 
    1250           0 :         if (!Utils::isInt8(imVal) || (options & X86Inst::kOptionLongForm)) {
    1251           0 :           opCode -= 2;
    1252           0 :           imLen = o0.getSize() == 2 ? 2 : 4;
    1253             :         }
    1254             : 
    1255             :         opReg = rbReg = o0.getId();
    1256           0 :         goto EmitX86R;
    1257             :       }
    1258             : 
    1259             :       // Try implicit form.
    1260           0 :       goto CaseX86M_GPB_MulDiv;
    1261             : 
    1262           0 :     case X86Inst::kEncodingX86In:
    1263           0 :       if (isign3 == ENC_OPS2(Reg, Imm)) {
    1264           0 :         if (ASMJIT_UNLIKELY(o0.getId() != X86Gp::kIdAx))
    1265           0 :           goto InvalidInstruction;
    1266             : 
    1267           0 :         imVal = o1.as<Imm>().getUInt8();
    1268             :         imLen = 1;
    1269             : 
    1270           0 :         opCode = commonData->getAltOpCode() + (o0.getSize() != 1);
    1271           0 :         ADD_66H_P_BY_SIZE(o0.getSize());
    1272           0 :         goto EmitX86Op;
    1273             :       }
    1274             : 
    1275           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    1276           0 :         if (ASMJIT_UNLIKELY(o0.getId() != X86Gp::kIdAx || o1.getId() != X86Gp::kIdDx))
    1277           0 :           goto InvalidInstruction;
    1278             : 
    1279           0 :         opCode += o0.getSize() != 1;
    1280           0 :         ADD_66H_P_BY_SIZE(o0.getSize());
    1281           0 :         goto EmitX86Op;
    1282             :       }
    1283             :       break;
    1284             : 
    1285           0 :     case X86Inst::kEncodingX86Ins:
    1286           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    1287           0 :         if (ASMJIT_UNLIKELY(!x86IsImplicitMem(o0, X86Gp::kIdDi) || o1.getId() != X86Gp::kIdDx))
    1288           0 :           goto InvalidInstruction;
    1289             : 
    1290             :         uint32_t size = o0.getSize();
    1291           0 :         if (ASMJIT_UNLIKELY(size == 0))
    1292           0 :           goto AmbiguousOperandSize;
    1293             : 
    1294             :         rmRel = &o0;
    1295           0 :         opCode += (size != 1);
    1296             : 
    1297           0 :         ADD_66H_P_BY_SIZE(size);
    1298           0 :         goto EmitX86OpImplicitMem;
    1299             :       }
    1300             :       break;
    1301             : 
    1302           0 :     case X86Inst::kEncodingX86IncDec:
    1303           0 :       if (isign3 == ENC_OPS1(Reg)) {
    1304             :         rbReg = o0.getId();
    1305             : 
    1306           0 :         if (o0.getSize() == 1) {
    1307           0 :           FIXUP_GPB(o0, rbReg);
    1308           0 :           goto EmitX86R;
    1309             :         }
    1310             : 
    1311           0 :         if (is32Bit()) {
    1312             :           // INC r16|r32 is only encodable in 32-bit mode (collides with REX).
    1313           0 :           opCode = commonData->getAltOpCode() + (rbReg & 0x07);
    1314           0 :           ADD_66H_P_BY_SIZE(o0.getSize());
    1315           0 :           goto EmitX86Op;
    1316             :         }
    1317             :         else {
    1318           0 :           opCode++;
    1319           0 :           ADD_PREFIX_BY_SIZE(o0.getSize());
    1320           0 :           goto EmitX86R;
    1321             :         }
    1322             :       }
    1323             : 
    1324           0 :       if (isign3 == ENC_OPS1(Mem)) {
    1325             :         rmRel = &o0;
    1326           0 :         opCode += o0.getSize() != 1;
    1327             : 
    1328           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
    1329           0 :         goto EmitX86M;
    1330             :       }
    1331             :       break;
    1332             : 
    1333           0 :     case X86Inst::kEncodingX86Int:
    1334           0 :       if (isign3 == ENC_OPS1(Imm)) {
    1335             :         imVal = static_cast<const Imm&>(o0).getInt64();
    1336             :         imLen = 1;
    1337           0 :         goto EmitX86Op;
    1338             :       }
    1339             :       break;
    1340             : 
    1341           0 :     case X86Inst::kEncodingX86Jcc:
    1342           0 :       if (_globalHints & CodeEmitter::kHintPredictedJumps) {
    1343           0 :         if (options & X86Inst::kOptionTaken)
    1344           0 :           EMIT_BYTE(0x3E);
    1345           0 :         if (options & X86Inst::kOptionNotTaken)
    1346           0 :           EMIT_BYTE(0x2E);
    1347             :       }
    1348             : 
    1349             :       rmRel = &o0;
    1350             :       opReg = 0;
    1351           0 :       goto EmitJmpCall;
    1352             : 
    1353           0 :     case X86Inst::kEncodingX86JecxzLoop:
    1354             :       rmRel = &o0;
    1355             :       // Explicit jecxz|loop [r|e]cx, dst
    1356           0 :       if (o0.isReg()) {
    1357           0 :         if (ASMJIT_UNLIKELY(!X86Reg::isGp(o0, X86Gp::kIdCx)))
    1358           0 :           goto InvalidInstruction;
    1359             : 
    1360           0 :         if ((is32Bit() && o0.getSize() == 2) || (is64Bit() && o0.getSize() == 4))
    1361           0 :           EMIT_BYTE(0x67);
    1362             : 
    1363             :         rmRel = &o1;
    1364             :       }
    1365             : 
    1366             :       opReg = 0;
    1367           0 :       goto EmitJmpCall;
    1368             : 
    1369           0 :     case X86Inst::kEncodingX86Jmp:
    1370           0 :       if (isign3 == ENC_OPS1(Reg)) {
    1371             :         rbReg = o0.getId();
    1372           0 :         goto EmitX86R;
    1373             :       }
    1374             : 
    1375             :       rmRel = &o0;
    1376           0 :       if (isign3 == ENC_OPS1(Mem))
    1377           0 :         goto EmitX86M;
    1378             : 
    1379             :       // Jump encoded with 32-bit displacement use 0xE9 opcode. Jump encoded
    1380             :       // with 8-bit displacement's opcode is stored as an alternative opcode.
    1381             :       opCode = 0xE9;
    1382             :       opReg = 0;
    1383           0 :       goto EmitJmpCall;
    1384             : 
    1385           0 :     case X86Inst::kEncodingX86JmpRel:
    1386             :       rmRel = &o0;
    1387           0 :       goto EmitJmpCall;
    1388             : 
    1389           0 :     case X86Inst::kEncodingX86Lea:
    1390           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    1391           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
    1392             :         opReg = o0.getId();
    1393             :         rmRel = &o1;
    1394           0 :         goto EmitX86M;
    1395             :       }
    1396             :       break;
    1397             : 
    1398      106298 :     case X86Inst::kEncodingX86Mov:
    1399             :       // Reg <- Reg
    1400      106298 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    1401             :         opReg = o0.getId();
    1402             :         rbReg = o1.getId();
    1403             : 
    1404             :         // Asmjit uses segment registers indexed from 1 to 6, leaving zero as
    1405             :         // "no segment register used". We have to fix this (decrement the index
    1406             :         // of the register) when emitting MOV instructions which move to/from
    1407             :         // a segment register. The segment register is always `opReg`, because
    1408             :         // the MOV instruction uses either RM or MR encoding.
    1409             : 
    1410             :         // GP <- ??
    1411           0 :         if (X86Reg::isGp(o0)) {
    1412             :           // GP <- GP
    1413           0 :           if (X86Reg::isGp(o1)) {
    1414             :             uint32_t size0 = o0.getSize();
    1415             :             uint32_t size1 = o1.getSize();
    1416             : 
    1417           0 :             if (size0 != size1) {
    1418             :               // We allow 'mov r64, r32' as it's basically zero-extend.
    1419           0 :               if (size0 == 8 && size1 == 4)
    1420             :                 size0 = 4; // Zero extend, don't promote to 64-bit.
    1421             :               else
    1422           0 :                 goto InvalidInstruction;
    1423             :             }
    1424             : 
    1425           0 :             if (size0 == 1) {
    1426           0 :               FIXUP_GPB(o0, opReg);
    1427           0 :               FIXUP_GPB(o1, rbReg);
    1428             :               opCode = 0x8A;
    1429             : 
    1430           0 :               if (!(options & X86Inst::kOptionModMR))
    1431           0 :                 goto EmitX86R;
    1432             : 
    1433             :               opCode -= 2;
    1434             :               Utils::swap(opReg, rbReg);
    1435           0 :               goto EmitX86R;
    1436             :             }
    1437             :             else {
    1438             :               opCode = 0x8B;
    1439           0 :               ADD_PREFIX_BY_SIZE(size0);
    1440             : 
    1441           0 :               if (!(options & X86Inst::kOptionModMR))
    1442           0 :                 goto EmitX86R;
    1443             : 
    1444           0 :               opCode -= 2;
    1445             :               Utils::swap(opReg, rbReg);
    1446           0 :               goto EmitX86R;
    1447             :             }
    1448             :           }
    1449             : 
    1450             :           opReg = rbReg;
    1451             :           rbReg = o0.getId();
    1452             : 
    1453             :           // GP <- SEG
    1454           0 :           if (X86Reg::isSeg(o1)) {
    1455             :             opCode = 0x8C;
    1456           0 :             opReg--;
    1457           0 :             ADD_PREFIX_BY_SIZE(o0.getSize());
    1458           0 :             goto EmitX86R;
    1459             :           }
    1460             : 
    1461             :           // GP <- CR
    1462           0 :           if (X86Reg::isCr(o1)) {
    1463             :             opCode = 0x20 | X86Inst::kOpCode_MM_0F;
    1464             : 
    1465             :             // Use `LOCK MOV` in 32-bit mode if CR8+ register is accessed (AMD extension).
    1466           0 :             if ((opReg & 0x8) && is32Bit()) {
    1467           0 :               EMIT_BYTE(0xF0);
    1468           0 :               opReg &= 0x7;
    1469             :             }
    1470           0 :             goto EmitX86R;
    1471             :           }
    1472             : 
    1473             :           // GP <- DR
    1474           0 :           if (X86Reg::isDr(o1)) {
    1475             :             opCode = 0x21 | X86Inst::kOpCode_MM_0F;
    1476           0 :             goto EmitX86R;
    1477             :           }
    1478             :         }
    1479             :         else {
    1480             :           // ?? <- GP
    1481           0 :           if (!X86Reg::isGp(o1))
    1482           0 :             goto InvalidInstruction;
    1483             : 
    1484             :           // SEG <- GP
    1485           0 :           if (X86Reg::isSeg(o0)) {
    1486             :             opCode = 0x8E;
    1487           0 :             opReg--;
    1488           0 :             ADD_PREFIX_BY_SIZE(o1.getSize());
    1489           0 :             goto EmitX86R;
    1490             :           }
    1491             : 
    1492             :           // CR <- GP
    1493           0 :           if (X86Reg::isCr(o0)) {
    1494             :             opCode = 0x22 | X86Inst::kOpCode_MM_0F;
    1495             : 
    1496             :             // Use `LOCK MOV` in 32-bit mode if CR8+ register is accessed (AMD extension).
    1497           0 :             if ((opReg & 0x8) && is32Bit()) {
    1498           0 :               EMIT_BYTE(0xF0);
    1499           0 :               opReg &= 0x7;
    1500             :             }
    1501           0 :             goto EmitX86R;
    1502             :           }
    1503             : 
    1504             :           // DR <- GP
    1505           0 :           if (X86Reg::isDr(o0)) {
    1506             :             opCode = 0x23 | X86Inst::kOpCode_MM_0F;
    1507           0 :             goto EmitX86R;
    1508             :           }
    1509             :         }
    1510             : 
    1511           0 :         goto InvalidInstruction;
    1512             :       }
    1513             : 
    1514      106298 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    1515             :         opReg = o0.getId();
    1516             :         rmRel = &o1;
    1517             : 
    1518             :         // SEG <- Mem
    1519           0 :         if (X86Reg::isSeg(o0)) {
    1520             :           opCode = 0x8E;
    1521           0 :           opReg--;
    1522           0 :           ADD_PREFIX_BY_SIZE(o1.getSize());
    1523           0 :           goto EmitX86M;
    1524             :         }
    1525             :         // Reg <- Mem
    1526             :         else {
    1527           0 :           if (o0.getSize() == 1) {
    1528             :             opCode = 0;
    1529           0 :             FIXUP_GPB(o0, opReg);
    1530             :           }
    1531             :           else {
    1532             :             opCode = 1;
    1533           0 :             ADD_PREFIX_BY_SIZE(o0.getSize());
    1534             :           }
    1535             : 
    1536             :           // Handle a special form `mov al|ax|eax|rax, [ptr64]` that doesn't use MOD.
    1537           0 :           if (o0.getId() == X86Gp::kIdAx && !rmRel->as<X86Mem>().hasBaseOrIndex()) {
    1538             :             imVal = rmRel->as<X86Mem>().getOffset();
    1539           0 :             if (!is64Bit() || (is64Bit() && ((options & X86Inst::kOptionLongForm) || !Utils::isInt32(imVal)))) {
    1540           0 :               opCode += 0xA0;
    1541           0 :               goto EmitX86OpMovAbs;
    1542             :             }
    1543             :           }
    1544             : 
    1545           0 :           opCode += 0x8A;
    1546           0 :           goto EmitX86M;
    1547             :         }
    1548             :       }
    1549             : 
    1550      106298 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    1551             :         opReg = o1.getId();
    1552             :         rmRel = &o0;
    1553             : 
    1554             :         // Mem <- SEG
    1555           0 :         if (X86Reg::isSeg(o1)) {
    1556             :           opCode = 0x8C;
    1557           0 :           opReg--;
    1558           0 :           ADD_PREFIX_BY_SIZE(o0.getSize());
    1559           0 :           goto EmitX86M;
    1560             :         }
    1561             :         // Mem <- Reg
    1562             :         else {
    1563           0 :           if (o1.getSize() == 1) {
    1564             :             opCode = 0;
    1565           0 :             FIXUP_GPB(o1, opReg);
    1566             :           }
    1567             :           else {
    1568             :             opCode = 1;
    1569           0 :             ADD_PREFIX_BY_SIZE(o1.getSize());
    1570             :           }
    1571             : 
    1572             :           // Handle a special form `mov [ptr64], al|ax|eax|rax` that doesn't use MOD.
    1573           0 :           if (o1.getId() == X86Gp::kIdAx && !rmRel->as<X86Mem>().hasBaseOrIndex()) {
    1574             :             imVal = rmRel->as<X86Mem>().getOffset();
    1575           0 :             if (!is64Bit() || (is64Bit() && ((options & X86Inst::kOptionLongForm) || !Utils::isInt32(imVal)))) {
    1576           0 :               opCode += 0xA2;
    1577           0 :               goto EmitX86OpMovAbs;
    1578             :             }
    1579             :           }
    1580             : 
    1581           0 :           opCode += 0x88;
    1582           0 :           goto EmitX86M;
    1583             :         }
    1584             :       }
    1585             : 
    1586      106298 :       if (isign3 == ENC_OPS2(Reg, Imm)) {
    1587             :         opReg = o0.getId();
    1588      106298 :         imLen = o0.getSize();
    1589             : 
    1590      106298 :         if (imLen == 1) {
    1591           0 :           FIXUP_GPB(o0, opReg);
    1592             : 
    1593           0 :           imVal = static_cast<const Imm&>(o1).getUInt8();
    1594             :           opCode = 0xB0;
    1595           0 :           goto EmitX86OpReg;
    1596             :         }
    1597             :         else {
    1598             :           // 64-bit immediate in 64-bit mode is allowed.
    1599             :           imVal = static_cast<const Imm&>(o1).getInt64();
    1600             : 
    1601             :           // Optimize the instruction size by using a 32-bit immediate if possible.
    1602      106298 :           if (imLen == 8 && !(options & X86Inst::kOptionLongForm)) {
    1603      106298 :             if (Utils::isUInt32(imVal)) {
    1604             :               // Zero-extend by using a 32-bit GPD destination instead of a 64-bit GPQ.
    1605             :               imLen = 4;
    1606             :             }
    1607      106298 :             else if (Utils::isInt32(imVal)) {
    1608             :               // Sign-extend, uses 'C7 /0' opcode.
    1609             :               rbReg = opReg;
    1610             : 
    1611             :               opCode = 0xC7 | X86Inst::kOpCode_W;
    1612             :               opReg = 0;
    1613             : 
    1614             :               imLen = 4;
    1615           0 :               goto EmitX86R;
    1616             :             }
    1617             :           }
    1618             : 
    1619             :           opCode = 0xB8;
    1620      106298 :           ADD_PREFIX_BY_SIZE(imLen);
    1621      106298 :           goto EmitX86OpReg;
    1622             :         }
    1623             :       }
    1624             : 
    1625           0 :       if (isign3 == ENC_OPS2(Mem, Imm)) {
    1626           0 :         uint32_t memSize = o0.getSize();
    1627             : 
    1628           0 :         if (ASMJIT_UNLIKELY(memSize == 0))
    1629           0 :           goto AmbiguousOperandSize;
    1630             : 
    1631             :         imVal = static_cast<const Imm&>(o1).getInt64();
    1632           0 :         imLen = std::min<uint32_t>(memSize, 4);
    1633             : 
    1634           0 :         opCode = 0xC6 + (memSize != 1);
    1635             :         opReg = 0;
    1636           0 :         ADD_PREFIX_BY_SIZE(memSize);
    1637             : 
    1638             :         rmRel = &o0;
    1639           0 :         goto EmitX86M;
    1640             :       }
    1641             :       break;
    1642             : 
    1643           0 :     case X86Inst::kEncodingX86MovsxMovzx:
    1644           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    1645             :         opReg = o0.getId();
    1646             :         rbReg = o1.getId();
    1647           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
    1648             : 
    1649           0 :         if (o1.getSize() == 1) {
    1650           0 :           FIXUP_GPB(o1, rbReg);
    1651           0 :           goto EmitX86R;
    1652             :         }
    1653             :         else {
    1654           0 :           opCode++;
    1655           0 :           goto EmitX86R;
    1656             :         }
    1657             :       }
    1658             : 
    1659           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    1660           0 :         opCode += o1.getSize() != 1;
    1661           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
    1662             : 
    1663             :         opReg = o0.getId();
    1664             :         rmRel = &o1;
    1665           0 :         goto EmitX86M;
    1666             :       }
    1667             :       break;
    1668             : 
    1669           0 :     case X86Inst::kEncodingX86Out:
    1670           0 :       if (isign3 == ENC_OPS2(Imm, Reg)) {
    1671           0 :         if (ASMJIT_UNLIKELY(o1.getId() != X86Gp::kIdAx))
    1672           0 :           goto InvalidInstruction;
    1673             : 
    1674           0 :         imVal = o0.as<Imm>().getUInt8();
    1675             :         imLen = 1;
    1676             : 
    1677           0 :         opCode = commonData->getAltOpCode() + (o1.getSize() != 1);
    1678           0 :         ADD_66H_P_BY_SIZE(o1.getSize());
    1679           0 :         goto EmitX86Op;
    1680             :       }
    1681             : 
    1682           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    1683           0 :         if (ASMJIT_UNLIKELY(o0.getId() != X86Gp::kIdDx || o1.getId() != X86Gp::kIdAx))
    1684           0 :           goto InvalidInstruction;
    1685             : 
    1686           0 :         opCode += o1.getSize() != 1;
    1687           0 :         ADD_66H_P_BY_SIZE(o1.getSize());
    1688           0 :         goto EmitX86Op;
    1689             :       }
    1690             :       break;
    1691             : 
    1692           0 :     case X86Inst::kEncodingX86Outs:
    1693           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    1694           0 :         if (ASMJIT_UNLIKELY(o0.getId() != X86Gp::kIdDx || !x86IsImplicitMem(o1, X86Gp::kIdSi)))
    1695           0 :           goto InvalidInstruction;
    1696             : 
    1697             :         uint32_t size = o1.getSize();
    1698           0 :         if (ASMJIT_UNLIKELY(size == 0))
    1699           0 :           goto AmbiguousOperandSize;
    1700             : 
    1701             :         rmRel = &o1;
    1702           0 :         opCode += (size != 1);
    1703             : 
    1704           0 :         ADD_66H_P_BY_SIZE(size);
    1705           0 :         goto EmitX86OpImplicitMem;
    1706             :       }
    1707             :       break;
    1708             : 
    1709        7156 :     case X86Inst::kEncodingX86Push:
    1710        7156 :       if (isign3 == ENC_OPS1(Reg)) {
    1711        7156 :         if (X86Reg::isSeg(o0)) {
    1712             :           uint32_t segment = o0.getId();
    1713           0 :           if (ASMJIT_UNLIKELY(segment >= X86Seg::kIdCount))
    1714           0 :             goto InvalidSegment;
    1715             : 
    1716           0 :           if (segment >= X86Seg::kIdFs)
    1717           0 :             EMIT_BYTE(0x0F);
    1718             : 
    1719           0 :           EMIT_BYTE(x86OpCodePushSeg[segment]);
    1720           0 :           goto EmitDone;
    1721             :         }
    1722             :         else {
    1723        7156 :           goto CaseX86Pop_Gp;
    1724             :         }
    1725             :       }
    1726             : 
    1727           0 :       if (isign3 == ENC_OPS1(Imm)) {
    1728             :         imVal = static_cast<const Imm&>(o0).getInt64();
    1729             :         imLen = 4;
    1730             : 
    1731           0 :         if (Utils::isInt8(imVal) && !(options & X86Inst::kOptionLongForm))
    1732             :           imLen = 1;
    1733             : 
    1734             :         opCode = imLen == 1 ? 0x6A : 0x68;
    1735           0 :         goto EmitX86Op;
    1736             :       }
    1737             :       ASMJIT_FALLTHROUGH;
    1738             : 
    1739             :     case X86Inst::kEncodingX86Pop:
    1740        7156 :       if (isign3 == ENC_OPS1(Reg)) {
    1741        7156 :         if (X86Reg::isSeg(o0)) {
    1742             :           uint32_t segment = o0.getId();
    1743           0 :           if (ASMJIT_UNLIKELY(segment == X86Seg::kIdCs || segment >= X86Seg::kIdCount))
    1744           0 :             goto InvalidSegment;
    1745             : 
    1746           0 :           if (segment >= X86Seg::kIdFs)
    1747           0 :             EMIT_BYTE(0x0F);
    1748             : 
    1749           0 :           EMIT_BYTE(x86OpCodePopSeg[segment]);
    1750           0 :           goto EmitDone;
    1751             :         }
    1752             :         else {
    1753       14312 : CaseX86Pop_Gp:
    1754             :           // We allow 2 byte, 4 byte, and 8 byte register sizes, although PUSH
    1755             :           // and POP only allow 2 bytes or native size. On 64-bit we simply
    1756             :           // PUSH/POP 64-bit register even if 32-bit register was given.
    1757       14312 :           if (ASMJIT_UNLIKELY(o0.getSize() < 2))
    1758           0 :             goto InvalidInstruction;
    1759             : 
    1760             :           opCode = commonData->getAltOpCode();
    1761             :           opReg = o0.getId();
    1762             : 
    1763       14312 :           ADD_66H_P_BY_SIZE(o0.getSize());
    1764       14312 :           goto EmitX86OpReg;
    1765             :         }
    1766             :       }
    1767             : 
    1768           0 :       if (isign3 == ENC_OPS1(Mem)) {
    1769           0 :         if (ASMJIT_UNLIKELY(o0.getSize() == 0))
    1770           0 :           goto AmbiguousOperandSize;
    1771             : 
    1772           0 :         if (ASMJIT_UNLIKELY(o0.getSize() != 2 && o0.getSize() != getGpSize()))
    1773           0 :           goto InvalidInstruction;
    1774             : 
    1775           0 :         ADD_66H_P_BY_SIZE(o0.getSize());
    1776             :         rmRel = &o0;
    1777           0 :         goto EmitX86M;
    1778             :       }
    1779             :       break;
    1780             : 
    1781       32111 :     case X86Inst::kEncodingX86Ret:
    1782       32111 :       if (isign3 == 0) {
    1783             :         // 'ret' without immediate, change C2 to C3.
    1784       32111 :         opCode++;
    1785       32111 :         goto EmitX86Op;
    1786             :       }
    1787             : 
    1788           0 :       if (isign3 == ENC_OPS1(Imm)) {
    1789             :         imVal = static_cast<const Imm&>(o0).getInt64();
    1790           0 :         if (imVal == 0 && !(options & X86Inst::kOptionLongForm)) {
    1791             :           // 'ret' without immediate, change C2 to C3.
    1792           0 :           opCode++;
    1793           0 :           goto EmitX86Op;
    1794             :         }
    1795             :         else {
    1796             :           imLen = 2;
    1797           0 :           goto EmitX86Op;
    1798             :         }
    1799             :       }
    1800             :       break;
    1801             : 
    1802             :     case X86Inst::kEncodingX86Rot:
    1803           0 :       if (o0.isReg()) {
    1804             :         rbReg = o0.getId();
    1805             : 
    1806           0 :         if (o0.getSize() == 1) {
    1807           0 :           FIXUP_GPB(o0, rbReg);
    1808             :         }
    1809             :         else {
    1810           0 :           opCode++;
    1811           0 :           ADD_PREFIX_BY_SIZE(o0.getSize());
    1812             :         }
    1813             : 
    1814           0 :         if (isign3 == ENC_OPS2(Reg, Reg)) {
    1815           0 :           if (ASMJIT_UNLIKELY(o1.getId() != X86Gp::kIdCx))
    1816           0 :             goto InvalidInstruction;
    1817             : 
    1818           0 :           opCode += 2;
    1819           0 :           goto EmitX86R;
    1820             :         }
    1821             : 
    1822           0 :         if (isign3 == ENC_OPS2(Reg, Imm)) {
    1823           0 :           imVal = static_cast<const Imm&>(o1).getInt64() & 0xFF;
    1824             :           imLen = 0;
    1825             : 
    1826           0 :           if (imVal == 1 && !(options & X86Inst::kOptionLongForm))
    1827           0 :             goto EmitX86R;
    1828             : 
    1829             :           imLen = 1;
    1830           0 :           opCode -= 0x10;
    1831           0 :           goto EmitX86R;
    1832             :         }
    1833             :       }
    1834             :       else {
    1835           0 :         opCode += o0.getSize() != 1;
    1836           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
    1837             : 
    1838           0 :         if (isign3 == ENC_OPS2(Mem, Reg)) {
    1839           0 :           if (ASMJIT_UNLIKELY(o1.getId() != X86Gp::kIdCx))
    1840           0 :             goto InvalidInstruction;
    1841             : 
    1842           0 :           opCode += 2;
    1843             :           rmRel = &o0;
    1844           0 :           goto EmitX86M;
    1845             :         }
    1846             : 
    1847           0 :         if (isign3 == ENC_OPS2(Mem, Imm)) {
    1848           0 :           if (ASMJIT_UNLIKELY(o0.getSize() == 0))
    1849           0 :             goto AmbiguousOperandSize;
    1850             : 
    1851           0 :           imVal = static_cast<const Imm&>(o1).getInt64() & 0xFF;
    1852             :           imLen = 0;
    1853             :           rmRel = &o0;
    1854             : 
    1855           0 :           if (imVal == 1 && !(options & X86Inst::kOptionLongForm))
    1856           0 :             goto EmitX86M;
    1857             : 
    1858             :           imLen = 1;
    1859           0 :           opCode -= 0x10;
    1860           0 :           goto EmitX86M;
    1861             :         }
    1862             :       }
    1863             :       break;
    1864             : 
    1865           0 :     case X86Inst::kEncodingX86Set:
    1866           0 :       if (isign3 == ENC_OPS1(Reg)) {
    1867             :         rbReg = o0.getId();
    1868           0 :         FIXUP_GPB(o0, rbReg);
    1869           0 :         goto EmitX86R;
    1870             :       }
    1871             : 
    1872           0 :       if (isign3 == ENC_OPS1(Mem)) {
    1873             :         rmRel = &o0;
    1874           0 :         goto EmitX86M;
    1875             :       }
    1876             :       break;
    1877             : 
    1878           0 :     case X86Inst::kEncodingX86ShldShrd:
    1879           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Imm)) {
    1880           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
    1881             :         imVal = static_cast<const Imm&>(o2).getInt64();
    1882             :         imLen = 1;
    1883             : 
    1884             :         opReg = o1.getId();
    1885             :         rbReg = o0.getId();
    1886           0 :         goto EmitX86R;
    1887             :       }
    1888             : 
    1889           0 :       if (isign3 == ENC_OPS3(Mem, Reg, Imm)) {
    1890           0 :         ADD_PREFIX_BY_SIZE(o1.getSize());
    1891             :         imVal = static_cast<const Imm&>(o2).getInt64();
    1892             :         imLen = 1;
    1893             : 
    1894             :         opReg = o1.getId();
    1895             :         rmRel = &o0;
    1896           0 :         goto EmitX86M;
    1897             :       }
    1898             : 
    1899             :       // The following instructions use opCode + 1.
    1900           0 :       opCode++;
    1901             : 
    1902           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Reg)) {
    1903           0 :         if (ASMJIT_UNLIKELY(o2.getId() != X86Gp::kIdCx))
    1904           0 :           goto InvalidInstruction;
    1905             : 
    1906           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
    1907             :         opReg = o1.getId();
    1908             :         rbReg = o0.getId();
    1909           0 :         goto EmitX86R;
    1910             :       }
    1911             : 
    1912           0 :       if (isign3 == ENC_OPS3(Mem, Reg, Reg)) {
    1913           0 :         if (ASMJIT_UNLIKELY(o2.getId() != X86Gp::kIdCx))
    1914           0 :           goto InvalidInstruction;
    1915             : 
    1916           0 :         ADD_PREFIX_BY_SIZE(o1.getSize());
    1917             :         opReg = o1.getId();
    1918             :         rmRel = &o0;
    1919           0 :         goto EmitX86M;
    1920             :       }
    1921             :       break;
    1922             : 
    1923           0 :     case X86Inst::kEncodingX86StrRm:
    1924           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    1925             :         rmRel = &o1;
    1926           0 :         if (ASMJIT_UNLIKELY(rmRel->as<X86Mem>().getOffsetLo32() || !X86Reg::isGp(o0.as<X86Reg>(), X86Gp::kIdAx)))
    1927           0 :           goto InvalidInstruction;
    1928             : 
    1929             :         uint32_t size = o0.getSize();
    1930           0 :         if (o1.hasSize() && ASMJIT_UNLIKELY(o1.getSize() != size))
    1931           0 :           goto OperandSizeMismatch;
    1932             : 
    1933           0 :         ADD_PREFIX_BY_SIZE(size);
    1934           0 :         opCode += static_cast<uint32_t>(size != 1);
    1935             : 
    1936           0 :         goto EmitX86OpImplicitMem;
    1937             :       }
    1938             :       break;
    1939             : 
    1940           0 :     case X86Inst::kEncodingX86StrMr:
    1941           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    1942             :         rmRel = &o0;
    1943           0 :         if (ASMJIT_UNLIKELY(rmRel->as<X86Mem>().getOffsetLo32() || !X86Reg::isGp(o1.as<X86Reg>(), X86Gp::kIdAx)))
    1944           0 :           goto InvalidInstruction;
    1945             : 
    1946             :         uint32_t size = o1.getSize();
    1947           0 :         if (o0.hasSize() && ASMJIT_UNLIKELY(o0.getSize() != size))
    1948           0 :           goto OperandSizeMismatch;
    1949             : 
    1950           0 :         ADD_PREFIX_BY_SIZE(size);
    1951           0 :         opCode += static_cast<uint32_t>(size != 1);
    1952             : 
    1953           0 :         goto EmitX86OpImplicitMem;
    1954             :       }
    1955             :       break;
    1956             : 
    1957           0 :     case X86Inst::kEncodingX86StrMm:
    1958           0 :       if (isign3 == ENC_OPS2(Mem, Mem)) {
    1959           0 :         if (ASMJIT_UNLIKELY(o0.as<X86Mem>().getBaseIndexType() !=
    1960             :                             o1.as<X86Mem>().getBaseIndexType()))
    1961           0 :           goto InvalidInstruction;
    1962             : 
    1963             :         rmRel = &o1;
    1964           0 :         if (ASMJIT_UNLIKELY(o0.as<X86Mem>().hasOffset()))
    1965           0 :           goto InvalidInstruction;
    1966             : 
    1967             :         uint32_t size = o1.getSize();
    1968           0 :         if (ASMJIT_UNLIKELY(size == 0))
    1969           0 :           goto AmbiguousOperandSize;
    1970             : 
    1971           0 :         if (ASMJIT_UNLIKELY(o0.getSize() != size))
    1972           0 :           goto OperandSizeMismatch;
    1973             : 
    1974           0 :         ADD_PREFIX_BY_SIZE(size);
    1975           0 :         opCode += static_cast<uint32_t>(size != 1);
    1976             : 
    1977           0 :         goto EmitX86OpImplicitMem;
    1978             :       }
    1979             :       break;
    1980             : 
    1981           0 :     case X86Inst::kEncodingX86Test:
    1982           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    1983           0 :         if (o0.getSize() != o1.getSize())
    1984           0 :           goto OperandSizeMismatch;
    1985             : 
    1986             :         rbReg = o0.getId();
    1987             :         opReg = o1.getId();
    1988             : 
    1989           0 :         if (o0.getSize() == 1) {
    1990           0 :           FIXUP_GPB(o0, rbReg);
    1991           0 :           FIXUP_GPB(o1, opReg);
    1992           0 :           goto EmitX86R;
    1993             :         }
    1994             :         else {
    1995           0 :           opCode++;
    1996           0 :           ADD_PREFIX_BY_SIZE(o0.getSize());
    1997           0 :           goto EmitX86R;
    1998             :         }
    1999             :       }
    2000             : 
    2001           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    2002             :         opReg = o1.getId();
    2003             :         rmRel = &o0;
    2004             : 
    2005           0 :         if (o1.getSize() == 1) {
    2006           0 :           FIXUP_GPB(o1, opReg);
    2007           0 :           goto EmitX86M;
    2008             :         }
    2009             :         else {
    2010           0 :           opCode++;
    2011           0 :           ADD_PREFIX_BY_SIZE(o1.getSize());
    2012           0 :           goto EmitX86M;
    2013             :         }
    2014             :       }
    2015             : 
    2016             :       // The following instructions use the secondary opcode.
    2017             :       opCode = commonData->getAltOpCode();
    2018             :       opReg = x86ExtractO(opCode);
    2019             : 
    2020           0 :       if (isign3 == ENC_OPS2(Reg, Imm)) {
    2021             :         rbReg = o0.getId();
    2022             : 
    2023           0 :         if (o0.getSize() == 1) {
    2024           0 :           FIXUP_GPB(o0, rbReg);
    2025             : 
    2026           0 :           imVal = static_cast<const Imm&>(o1).getUInt8();
    2027             :           imLen = 1;
    2028             :         }
    2029             :         else {
    2030           0 :           opCode++;
    2031           0 :           ADD_PREFIX_BY_SIZE(o0.getSize());
    2032             : 
    2033             :           imVal = static_cast<const Imm&>(o1).getInt64();
    2034           0 :           imLen = std::min<uint32_t>(o0.getSize(), 4);
    2035             :         }
    2036             : 
    2037             :         // Alternate Form - AL, AX, EAX, RAX.
    2038           0 :         if (o0.getId() == 0 && !(options & X86Inst::kOptionLongForm)) {
    2039           0 :           opCode &= X86Inst::kOpCode_PP_66 | X86Inst::kOpCode_W;
    2040           0 :           opCode |= 0xA8 + (o0.getSize() != 1);
    2041           0 :           goto EmitX86Op;
    2042             :         }
    2043             : 
    2044           0 :         goto EmitX86R;
    2045             :       }
    2046             : 
    2047           0 :       if (isign3 == ENC_OPS2(Mem, Imm)) {
    2048           0 :         if (ASMJIT_UNLIKELY(o0.getSize() == 0))
    2049           0 :           goto AmbiguousOperandSize;
    2050             : 
    2051             :         imVal = static_cast<const Imm&>(o1).getInt64();
    2052           0 :         imLen = std::min<uint32_t>(o0.getSize(), 4);
    2053             : 
    2054           0 :         opCode += (o0.getSize() != 1);
    2055           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
    2056             : 
    2057             :         rmRel = &o0;
    2058           0 :         goto EmitX86M;
    2059             :       }
    2060             :       break;
    2061             : 
    2062           0 :     case X86Inst::kEncodingX86Xchg:
    2063           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    2064             :         opReg = o0.getId();
    2065             :         rmRel = &o1;
    2066             : 
    2067           0 :         if (o0.getSize() == 1) {
    2068           0 :           FIXUP_GPB(o0, opReg);
    2069           0 :           goto EmitX86M;
    2070             :         }
    2071             :         else {
    2072           0 :           opCode++;
    2073           0 :           ADD_PREFIX_BY_SIZE(o0.getSize());
    2074           0 :           goto EmitX86M;
    2075             :         }
    2076             :       }
    2077             :       ASMJIT_FALLTHROUGH;
    2078             : 
    2079             :     case X86Inst::kEncodingX86Xadd:
    2080           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    2081             :         rbReg = o0.getId();
    2082             :         opReg = o1.getId();
    2083             : 
    2084           0 :         if (o0.getSize() != o1.getSize())
    2085           0 :           goto OperandSizeMismatch;
    2086             : 
    2087           0 :         if (o0.getSize() == 1) {
    2088           0 :           FIXUP_GPB(o0, rbReg);
    2089           0 :           FIXUP_GPB(o1, opReg);
    2090           0 :           goto EmitX86R;
    2091             :         }
    2092             :         else {
    2093           0 :           opCode++;
    2094           0 :           ADD_PREFIX_BY_SIZE(o0.getSize());
    2095             : 
    2096             :           // Special opcode for 'xchg ?ax, reg'.
    2097           0 :           if (instId == X86Inst::kIdXchg && (opReg == 0 || rbReg == 0)) {
    2098           0 :             opCode &= X86Inst::kOpCode_PP_66 | X86Inst::kOpCode_W;
    2099           0 :             opCode |= 0x90;
    2100             :             // One of `xchg a, b` or `xchg b, a` is AX/EAX/RAX.
    2101           0 :             opReg += rbReg;
    2102           0 :             goto EmitX86OpReg;
    2103             :           }
    2104             :           else {
    2105           0 :             goto EmitX86R;
    2106             :           }
    2107             :         }
    2108             :       }
    2109             : 
    2110           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    2111           0 :         opCode += o1.getSize() != 1;
    2112           0 :         ADD_PREFIX_BY_SIZE(o1.getSize());
    2113             : 
    2114             :         opReg = o1.getId();
    2115             :         rmRel = &o0;
    2116           0 :         goto EmitX86M;
    2117             :       }
    2118             :       break;
    2119             : 
    2120           0 :     case X86Inst::kEncodingX86Fence:
    2121             :       rbReg = 0;
    2122           0 :       goto EmitX86R;
    2123             : 
    2124           0 :     case X86Inst::kEncodingX86Bndmov:
    2125           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    2126             :         opReg = o0.getId();
    2127             :         rbReg = o1.getId();
    2128             : 
    2129             :         // ModRM encoding:
    2130           0 :         if (!(options & X86Inst::kOptionModMR))
    2131           0 :           goto EmitX86R;
    2132             : 
    2133             :         // ModMR encoding:
    2134             :         opCode = commonData->getAltOpCode();
    2135             :         std::swap(opReg, rbReg);
    2136           0 :         goto EmitX86R;
    2137             :       }
    2138             : 
    2139           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    2140             :         opReg = o0.getId();
    2141             :         rmRel = &o1;
    2142           0 :         goto EmitX86M;
    2143             :       }
    2144             : 
    2145           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    2146             :         opCode = commonData->getAltOpCode();
    2147             : 
    2148             :         rmRel = &o0;
    2149             :         opReg = o1.getId();
    2150           0 :         goto EmitX86M;
    2151             :       }
    2152             :       break;
    2153             : 
    2154             :     // ------------------------------------------------------------------------
    2155             :     // [FPU]
    2156             :     // ------------------------------------------------------------------------
    2157             : 
    2158           0 :     case X86Inst::kEncodingFpuOp:
    2159           0 :       goto EmitFpuOp;
    2160             : 
    2161           0 :     case X86Inst::kEncodingFpuArith:
    2162           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    2163             :         opReg = o0.getId();
    2164             :         rbReg = o1.getId();
    2165             : 
    2166             :         // We switch to the alternative opcode if the first operand is zero.
    2167           0 :         if (opReg == 0) {
    2168           0 : CaseFpuArith_Reg:
    2169           0 :           opCode = ((0xD8   << X86Inst::kOpCode_FPU_2B_Shift)       ) +
    2170           0 :                    ((opCode >> X86Inst::kOpCode_FPU_2B_Shift) & 0xFF) + rbReg;
    2171           0 :           goto EmitFpuOp;
    2172             :         }
    2173           0 :         else if (rbReg == 0) {
    2174             :           rbReg = opReg;
    2175           0 :           opCode = ((0xDC   << X86Inst::kOpCode_FPU_2B_Shift)       ) +
    2176           0 :                    ((opCode                                 ) & 0xFF) + rbReg;
    2177           0 :           goto EmitFpuOp;
    2178             :         }
    2179             :         else {
    2180           0 :           goto InvalidInstruction;
    2181             :         }
    2182             :       }
    2183             : 
    2184           0 :       if (isign3 == ENC_OPS1(Mem)) {
    2185           0 : CaseFpuArith_Mem:
    2186             :         // 0xD8/0xDC, depends on the size of the memory operand; opReg is valid.
    2187           0 :         opCode = (o0.getSize() == 4) ? 0xD8 : 0xDC;
    2188             :         // Clear compressed displacement before going to EmitX86M.
    2189           0 :         opCode &= ~static_cast<uint32_t>(X86Inst::kOpCode_CDSHL_Mask);
    2190             : 
    2191             :         rmRel = &o0;
    2192           0 :         goto EmitX86M;
    2193             :       }
    2194             :       break;
    2195             : 
    2196           0 :     case X86Inst::kEncodingFpuCom:
    2197           0 :       if (isign3 == 0) {
    2198             :         rbReg = 1;
    2199           0 :         goto CaseFpuArith_Reg;
    2200             :       }
    2201             : 
    2202           0 :       if (isign3 == ENC_OPS1(Reg)) {
    2203             :         rbReg = o0.getId();
    2204           0 :         goto CaseFpuArith_Reg;
    2205             :       }
    2206             : 
    2207           0 :       if (isign3 == ENC_OPS1(Mem)) {
    2208           0 :         goto CaseFpuArith_Mem;
    2209             :       }
    2210             :       break;
    2211             : 
    2212           0 :     case X86Inst::kEncodingFpuFldFst:
    2213           0 :       if (isign3 == ENC_OPS1(Mem)) {
    2214             :         rmRel = &o0;
    2215             : 
    2216           0 :         if (o0.getSize() == 4 && commonData->hasFlag(X86Inst::kFlagFpuM32)) {
    2217           0 :           goto EmitX86M;
    2218             :         }
    2219             : 
    2220           0 :         if (o0.getSize() == 8 && commonData->hasFlag(X86Inst::kFlagFpuM64)) {
    2221           0 :           opCode += 4;
    2222           0 :           goto EmitX86M;
    2223             :         }
    2224             : 
    2225           0 :         if (o0.getSize() == 10 && commonData->hasFlag(X86Inst::kFlagFpuM80)) {
    2226             :           opCode = commonData->getAltOpCode();
    2227             :           opReg  = x86ExtractO(opCode);
    2228           0 :           goto EmitX86M;
    2229             :         }
    2230             :       }
    2231             : 
    2232           0 :       if (isign3 == ENC_OPS1(Reg)) {
    2233           0 :         if (instId == X86Inst::kIdFld ) { opCode = (0xD9 << X86Inst::kOpCode_FPU_2B_Shift) + 0xC0 + o0.getId(); goto EmitFpuOp; }
    2234           0 :         if (instId == X86Inst::kIdFst ) { opCode = (0xDD << X86Inst::kOpCode_FPU_2B_Shift) + 0xD0 + o0.getId(); goto EmitFpuOp; }
    2235           0 :         if (instId == X86Inst::kIdFstp) { opCode = (0xDD << X86Inst::kOpCode_FPU_2B_Shift) + 0xD8 + o0.getId(); goto EmitFpuOp; }
    2236             :       }
    2237             :       break;
    2238             : 
    2239           0 :     case X86Inst::kEncodingFpuM:
    2240           0 :       if (isign3 == ENC_OPS1(Mem)) {
    2241             :         // Clear compressed displacement before going to EmitX86M.
    2242           0 :         opCode &= ~static_cast<uint32_t>(X86Inst::kOpCode_CDSHL_Mask);
    2243             : 
    2244             :         rmRel = &o0;
    2245           0 :         if (o0.getSize() == 2 && commonData->hasFlag(X86Inst::kFlagFpuM16)) {
    2246           0 :           opCode += 4;
    2247           0 :           goto EmitX86M;
    2248             :         }
    2249             : 
    2250           0 :         if (o0.getSize() == 4 && commonData->hasFlag(X86Inst::kFlagFpuM32)) {
    2251           0 :           goto EmitX86M;
    2252             :         }
    2253             : 
    2254           0 :         if (o0.getSize() == 8 && commonData->hasFlag(X86Inst::kFlagFpuM64)) {
    2255           0 :           opCode = commonData->getAltOpCode() & ~static_cast<uint32_t>(X86Inst::kOpCode_CDSHL_Mask);
    2256             :           opReg  = x86ExtractO(opCode);
    2257           0 :           goto EmitX86M;
    2258             :         }
    2259             :       }
    2260             :       break;
    2261             : 
    2262           0 :     case X86Inst::kEncodingFpuRDef:
    2263           0 :       if (isign3 == 0) {
    2264           0 :         opCode += 1;
    2265           0 :         goto EmitFpuOp;
    2266             :       }
    2267             :       ASMJIT_FALLTHROUGH;
    2268             : 
    2269             :     case X86Inst::kEncodingFpuR:
    2270           0 :       if (isign3 == ENC_OPS1(Reg)) {
    2271           0 :         opCode += o0.getId();
    2272           0 :         goto EmitFpuOp;
    2273             :       }
    2274             :       break;
    2275             : 
    2276           0 :     case X86Inst::kEncodingFpuStsw:
    2277           0 :       if (isign3 == ENC_OPS1(Reg)) {
    2278           0 :         if (ASMJIT_UNLIKELY(o0.getId() != X86Gp::kIdAx))
    2279           0 :           goto InvalidInstruction;
    2280             : 
    2281             :         opCode = commonData->getAltOpCode();
    2282           0 :         goto EmitFpuOp;
    2283             :       }
    2284             : 
    2285           0 :       if (isign3 == ENC_OPS1(Mem)) {
    2286             :         // Clear compressed displacement before going to EmitX86M.
    2287           0 :         opCode &= ~static_cast<uint32_t>(X86Inst::kOpCode_CDSHL_Mask);
    2288             : 
    2289             :         rmRel = &o0;
    2290           0 :         goto EmitX86M;
    2291             :       }
    2292             :       break;
    2293             : 
    2294             :     // ------------------------------------------------------------------------
    2295             :     // [Ext]
    2296             :     // ------------------------------------------------------------------------
    2297             : 
    2298           0 :     case X86Inst::kEncodingExtPextrw:
    2299           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Imm)) {
    2300           0 :         ADD_66H_P(X86Reg::isXmm(o1));
    2301             : 
    2302             :         imVal = static_cast<const Imm&>(o2).getInt64();
    2303             :         imLen = 1;
    2304             : 
    2305             :         opReg = o0.getId();
    2306             :         rbReg = o1.getId();
    2307           0 :         goto EmitX86R;
    2308             :       }
    2309             : 
    2310           0 :       if (isign3 == ENC_OPS3(Mem, Reg, Imm)) {
    2311             :         // Secondary opcode of 'pextrw' instruction (SSE4.1).
    2312             :         opCode = commonData->getAltOpCode();
    2313           0 :         ADD_66H_P(X86Reg::isXmm(o1));
    2314             : 
    2315             :         imVal = static_cast<const Imm&>(o2).getInt64();
    2316             :         imLen = 1;
    2317             : 
    2318             :         opReg = o1.getId();
    2319             :         rmRel = &o0;
    2320           0 :         goto EmitX86M;
    2321             :       }
    2322             :       break;
    2323             : 
    2324           0 :     case X86Inst::kEncodingExtExtract:
    2325           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Imm)) {
    2326           0 :         ADD_66H_P(X86Reg::isXmm(o1));
    2327             : 
    2328             :         imVal = static_cast<const Imm&>(o2).getInt64();
    2329             :         imLen = 1;
    2330             : 
    2331             :         opReg = o1.getId();
    2332             :         rbReg = o0.getId();
    2333           0 :         goto EmitX86R;
    2334             :       }
    2335             : 
    2336           0 :       if (isign3 == ENC_OPS3(Mem, Reg, Imm)) {
    2337           0 :         ADD_66H_P(X86Reg::isXmm(o1));
    2338             : 
    2339             :         imVal = static_cast<const Imm&>(o2).getInt64();
    2340             :         imLen = 1;
    2341             : 
    2342             :         opReg = o1.getId();
    2343             :         rmRel = &o0;
    2344           0 :         goto EmitX86M;
    2345             :       }
    2346             :       break;
    2347             : 
    2348      298656 :     case X86Inst::kEncodingExtMov:
    2349             :       // GP|MMX|XMM <- GP|MMX|XMM
    2350      298656 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    2351             :         opReg = o0.getId();
    2352             :         rbReg = o1.getId();
    2353             : 
    2354      122543 :         if (!(options & X86Inst::kOptionModMR) || !commonData->hasAltOpCode())
    2355      122543 :           goto EmitX86R;
    2356             : 
    2357             :         opCode = commonData->getAltOpCode();
    2358             :         Utils::swap(opReg, rbReg);
    2359           0 :         goto EmitX86R;
    2360             :       }
    2361             : 
    2362             :       // GP|MMX|XMM <- Mem
    2363      176113 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    2364             :         opReg = o0.getId();
    2365             :         rmRel = &o1;
    2366      135619 :         goto EmitX86M;
    2367             :       }
    2368             : 
    2369             :       // The following instruction uses opCode[1].
    2370             :       opCode = commonData->getAltOpCode();
    2371             : 
    2372             :       // Mem <- GP|MMX|XMM
    2373       40494 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    2374             :         opReg = o1.getId();
    2375             :         rmRel = &o0;
    2376       40494 :         goto EmitX86M;
    2377             :       }
    2378             :       break;
    2379             : 
    2380           0 :     case X86Inst::kEncodingExtMovnti:
    2381           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    2382           0 :         ADD_REX_W(X86Reg::isGpq(o1));
    2383             : 
    2384             :         opReg = o1.getId();
    2385             :         rmRel = &o0;
    2386           0 :         goto EmitX86M;
    2387             :       }
    2388             :       break;
    2389             : 
    2390           0 :     case X86Inst::kEncodingExtMovbe:
    2391           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    2392           0 :         if (o0.getSize() == 1)
    2393           0 :           goto InvalidInstruction;
    2394             : 
    2395           0 :         ADD_PREFIX_BY_SIZE(o0.getSize());
    2396             :         opReg = o0.getId();
    2397             :         rmRel = &o1;
    2398           0 :         goto EmitX86M;
    2399             :       }
    2400             : 
    2401             :       // The following instruction uses the secondary opcode.
    2402             :       opCode = commonData->getAltOpCode();
    2403             : 
    2404           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    2405           0 :         if (o1.getSize() == 1)
    2406           0 :           goto InvalidInstruction;
    2407             : 
    2408           0 :         ADD_PREFIX_BY_SIZE(o1.getSize());
    2409             :         opReg = o1.getId();
    2410             :         rmRel = &o0;
    2411           0 :         goto EmitX86M;
    2412             :       }
    2413             :       break;
    2414             : 
    2415             :     case X86Inst::kEncodingExtMovd:
    2416           0 : CaseExtMovd:
    2417             :       opReg = o0.getId();
    2418           0 :       ADD_66H_P(X86Reg::isXmm(o0));
    2419             : 
    2420             :       // MMX/XMM <- Gp
    2421           0 :       if (isign3 == ENC_OPS2(Reg, Reg) && X86Reg::isGp(o1)) {
    2422             :         rbReg = o1.getId();
    2423           0 :         goto EmitX86R;
    2424             :       }
    2425             : 
    2426             :       // MMX/XMM <- Mem
    2427           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    2428             :         rmRel = &o1;
    2429           0 :         goto EmitX86M;
    2430             :       }
    2431             : 
    2432             :       // The following instructions use the secondary opcode.
    2433           0 :       opCode &= X86Inst::kOpCode_W;
    2434           0 :       opCode |= commonData->getAltOpCode();
    2435             :       opReg = o1.getId();
    2436           0 :       ADD_66H_P(X86Reg::isXmm(o1));
    2437             : 
    2438             :       // GP <- MMX/XMM
    2439           0 :       if (isign3 == ENC_OPS2(Reg, Reg) && X86Reg::isGp(o0)) {
    2440             :         rbReg = o0.getId();
    2441           0 :         goto EmitX86R;
    2442             :       }
    2443             : 
    2444             :       // Mem <- MMX/XMM
    2445           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    2446             :         rmRel = &o0;
    2447           0 :         goto EmitX86M;
    2448             :       }
    2449             :       break;
    2450             : 
    2451           0 :     case X86Inst::kEncodingExtMovq:
    2452           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    2453             :         opReg = o0.getId();
    2454             :         rbReg = o1.getId();
    2455             : 
    2456             :         // MMX <- MMX
    2457           0 :         if (X86Reg::isMm(o0) && X86Reg::isMm(o1)) {
    2458             :           opCode = X86Inst::kOpCode_PP_00 | X86Inst::kOpCode_MM_0F | 0x6F;
    2459             : 
    2460           0 :           if (!(options & X86Inst::kOptionModMR))
    2461           0 :             goto EmitX86R;
    2462             : 
    2463             :           opCode += 0x10;
    2464             :           Utils::swap(opReg, rbReg);
    2465           0 :           goto EmitX86R;
    2466             :         }
    2467             : 
    2468             :         // XMM <- XMM
    2469           0 :         if (X86Reg::isXmm(o0) && X86Reg::isXmm(o1)) {
    2470             :           opCode = X86Inst::kOpCode_PP_F3 | X86Inst::kOpCode_MM_0F | 0x7E;
    2471             : 
    2472           0 :           if (!(options & X86Inst::kOptionModMR))
    2473           0 :             goto EmitX86R;
    2474             : 
    2475             :           opCode = X86Inst::kOpCode_PP_66 | X86Inst::kOpCode_MM_0F | 0xD6;
    2476             :           Utils::swap(opReg, rbReg);
    2477           0 :           goto EmitX86R;
    2478             :         }
    2479             : 
    2480             :         // MMX <- XMM (MOVDQ2Q)
    2481           0 :         if (X86Reg::isMm(o0) && X86Reg::isXmm(o1)) {
    2482             :           opCode = X86Inst::kOpCode_PP_F2 | X86Inst::kOpCode_MM_0F | 0xD6;
    2483           0 :           goto EmitX86R;
    2484             :         }
    2485             : 
    2486             :         // XMM <- MMX (MOVQ2DQ)
    2487           0 :         if (X86Reg::isXmm(o0) && X86Reg::isMm(o1)) {
    2488             :           opCode = X86Inst::kOpCode_PP_F3 | X86Inst::kOpCode_MM_0F | 0xD6;
    2489           0 :           goto EmitX86R;
    2490             :         }
    2491             :       }
    2492             : 
    2493           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    2494             :         opReg = o0.getId();
    2495             :         rmRel = &o1;
    2496             : 
    2497             :         // MMX <- Mem
    2498           0 :         if (X86Reg::isMm(o0)) {
    2499             :           opCode = X86Inst::kOpCode_PP_00 | X86Inst::kOpCode_MM_0F | 0x6F;
    2500           0 :           goto EmitX86M;
    2501             :         }
    2502             : 
    2503             :         // XMM <- Mem
    2504           0 :         if (X86Reg::isXmm(o0)) {
    2505             :           opCode = X86Inst::kOpCode_PP_F3 | X86Inst::kOpCode_MM_0F | 0x7E;
    2506           0 :           goto EmitX86M;
    2507             :         }
    2508             :       }
    2509             : 
    2510           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    2511             :         opReg = o1.getId();
    2512             :         rmRel = &o0;
    2513             : 
    2514             :         // Mem <- MMX
    2515           0 :         if (X86Reg::isMm(o1)) {
    2516             :           opCode = X86Inst::kOpCode_PP_00 | X86Inst::kOpCode_MM_0F | 0x7F;
    2517           0 :           goto EmitX86M;
    2518             :         }
    2519             : 
    2520             :         // Mem <- XMM
    2521           0 :         if (X86Reg::isXmm(o1)) {
    2522             :           opCode = X86Inst::kOpCode_PP_66 | X86Inst::kOpCode_MM_0F | 0xD6;
    2523           0 :           goto EmitX86M;
    2524             :         }
    2525             :       }
    2526             : 
    2527             :       // MOVQ in other case is simply a MOVD instruction promoted to 64-bit.
    2528           0 :       opCode |= X86Inst::kOpCode_W;
    2529           0 :       goto CaseExtMovd;
    2530             : 
    2531             :     case X86Inst::kEncodingExtRm_XMM0:
    2532           0 :       if (ASMJIT_UNLIKELY(!o2.isNone() && !X86Reg::isXmm(o2, 0)))
    2533           0 :         goto InvalidInstruction;
    2534             : 
    2535           0 :       isign3 &= 0x3F;
    2536           0 :       goto CaseExtRm;
    2537             : 
    2538             :     case X86Inst::kEncodingExtRm_ZDI:
    2539           0 :       if (ASMJIT_UNLIKELY(!o2.isNone() && !x86IsImplicitMem(o2, X86Gp::kIdDi)))
    2540           0 :         goto InvalidInstruction;
    2541             : 
    2542           0 :       isign3 &= 0x3F;
    2543           0 :       goto CaseExtRm;
    2544             : 
    2545             :     case X86Inst::kEncodingExtRm_Wx:
    2546           0 :       ADD_REX_W(X86Reg::isGpq(o0) || o1.getSize() == 8);
    2547             :       ASMJIT_FALLTHROUGH;
    2548             : 
    2549             :     case X86Inst::kEncodingExtRm:
    2550      117107 : CaseExtRm:
    2551      117107 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    2552             :         opReg = o0.getId();
    2553             :         rbReg = o1.getId();
    2554      117107 :         goto EmitX86R;
    2555             :       }
    2556             : 
    2557           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    2558             :         opReg = o0.getId();
    2559             :         rmRel = &o1;
    2560           0 :         goto EmitX86M;
    2561             :       }
    2562             :       break;
    2563             : 
    2564           0 :     case X86Inst::kEncodingExtRm_P:
    2565           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    2566           0 :         ADD_66H_P(X86Reg::isXmm(o0) | X86Reg::isXmm(o1));
    2567             : 
    2568             :         opReg = o0.getId();
    2569             :         rbReg = o1.getId();
    2570           0 :         goto EmitX86R;
    2571             :       }
    2572             : 
    2573           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    2574           0 :         ADD_66H_P(X86Reg::isXmm(o0));
    2575             : 
    2576             :         opReg = o0.getId();
    2577             :         rmRel = &o1;
    2578           0 :         goto EmitX86M;
    2579             :       }
    2580             :       break;
    2581             : 
    2582           0 :     case X86Inst::kEncodingExtRmRi:
    2583           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    2584             :         opReg = o0.getId();
    2585             :         rbReg = o1.getId();
    2586           0 :         goto EmitX86R;
    2587             :       }
    2588             : 
    2589           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    2590             :         opReg = o0.getId();
    2591             :         rmRel = &o1;
    2592           0 :         goto EmitX86M;
    2593             :       }
    2594             : 
    2595             :       // The following instruction uses the secondary opcode.
    2596             :       opCode = commonData->getAltOpCode();
    2597             :       opReg  = x86ExtractO(opCode);
    2598             : 
    2599           0 :       if (isign3 == ENC_OPS2(Reg, Imm)) {
    2600             :         imVal = static_cast<const Imm&>(o1).getInt64();
    2601             :         imLen = 1;
    2602             : 
    2603             :         rbReg = o0.getId();
    2604           0 :         goto EmitX86R;
    2605             :       }
    2606             :       break;
    2607             : 
    2608           0 :     case X86Inst::kEncodingExtRmRi_P:
    2609           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    2610           0 :         ADD_66H_P(X86Reg::isXmm(o0) | X86Reg::isXmm(o1));
    2611             : 
    2612             :         opReg = o0.getId();
    2613             :         rbReg = o1.getId();
    2614           0 :         goto EmitX86R;
    2615             :       }
    2616             : 
    2617           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    2618           0 :         ADD_66H_P(X86Reg::isXmm(o0));
    2619             : 
    2620             :         opReg = o0.getId();
    2621             :         rmRel = &o1;
    2622           0 :         goto EmitX86M;
    2623             :       }
    2624             : 
    2625             :       // The following instruction uses the secondary opcode.
    2626             :       opCode = commonData->getAltOpCode();
    2627             :       opReg  = x86ExtractO(opCode);
    2628             : 
    2629           0 :       if (isign3 == ENC_OPS2(Reg, Imm)) {
    2630           0 :         ADD_66H_P(X86Reg::isXmm(o0));
    2631             : 
    2632             :         imVal = static_cast<const Imm&>(o1).getInt64();
    2633             :         imLen = 1;
    2634             : 
    2635             :         rbReg = o0.getId();
    2636           0 :         goto EmitX86R;
    2637             :       }
    2638             :       break;
    2639             : 
    2640             :     case X86Inst::kEncodingExtRmi:
    2641             :       imVal = static_cast<const Imm&>(o2).getInt64();
    2642             :       imLen = 1;
    2643             : 
    2644        2270 :       if (isign3 == ENC_OPS3(Reg, Reg, Imm)) {
    2645             :         opReg = o0.getId();
    2646             :         rbReg = o1.getId();
    2647        2270 :         goto EmitX86R;
    2648             :       }
    2649             : 
    2650           0 :       if (isign3 == ENC_OPS3(Reg, Mem, Imm)) {
    2651             :         opReg = o0.getId();
    2652             :         rmRel = &o1;
    2653           0 :         goto EmitX86M;
    2654             :       }
    2655             :       break;
    2656             : 
    2657             :     case X86Inst::kEncodingExtRmi_P:
    2658             :       imVal = static_cast<const Imm&>(o2).getInt64();
    2659             :       imLen = 1;
    2660             : 
    2661           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Imm)) {
    2662           0 :         ADD_66H_P(X86Reg::isXmm(o0) | X86Reg::isXmm(o1));
    2663             : 
    2664             :         opReg = o0.getId();
    2665             :         rbReg = o1.getId();
    2666           0 :         goto EmitX86R;
    2667             :       }
    2668             : 
    2669           0 :       if (isign3 == ENC_OPS3(Reg, Mem, Imm)) {
    2670           0 :         ADD_66H_P(X86Reg::isXmm(o0));
    2671             : 
    2672             :         opReg = o0.getId();
    2673             :         rmRel = &o1;
    2674           0 :         goto EmitX86M;
    2675             :       }
    2676             :       break;
    2677             : 
    2678             :     // ------------------------------------------------------------------------
    2679             :     // [Extrq / Insertq (SSE4A)]
    2680             :     // ------------------------------------------------------------------------
    2681             : 
    2682             :     case X86Inst::kEncodingExtExtrq:
    2683             :       opReg = o0.getId();
    2684             :       rbReg = o1.getId();
    2685             : 
    2686           0 :       if (isign3 == ENC_OPS2(Reg, Reg))
    2687           0 :         goto EmitX86R;
    2688             : 
    2689             :       // The following instruction uses the secondary opcode.
    2690             :       opCode = commonData->getAltOpCode();
    2691             : 
    2692           0 :       if (isign3 == ENC_OPS3(Reg, Imm, Imm)) {
    2693           0 :         imVal = (static_cast<const Imm&>(o1).getUInt32()     ) +
    2694           0 :                 (static_cast<const Imm&>(o2).getUInt32() << 8) ;
    2695             :         imLen = 2;
    2696             : 
    2697             :         rbReg = x86ExtractO(opCode);
    2698           0 :         goto EmitX86R;
    2699             :       }
    2700             :       break;
    2701             : 
    2702             :     case X86Inst::kEncodingExtInsertq: {
    2703           0 :       const uint32_t isign4 = isign3 + (o3.getOp() << 9);
    2704             :       opReg = o0.getId();
    2705             :       rbReg = o1.getId();
    2706             : 
    2707           0 :       if (isign4 == ENC_OPS2(Reg, Reg))
    2708           0 :         goto EmitX86R;
    2709             : 
    2710             :       // The following instruction uses the secondary opcode.
    2711             :       opCode = commonData->getAltOpCode();
    2712             : 
    2713           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
    2714           0 :         imVal = (static_cast<const Imm&>(o2).getUInt32()     ) +
    2715           0 :                 (static_cast<const Imm&>(o3).getUInt32() << 8) ;
    2716             :         imLen = 2;
    2717           0 :         goto EmitX86R;
    2718             :       }
    2719             :       break;
    2720             :     }
    2721             : 
    2722             :     // ------------------------------------------------------------------------
    2723             :     // [3dNow]
    2724             :     // ------------------------------------------------------------------------
    2725             : 
    2726           0 :     case X86Inst::kEncodingExt3dNow:
    2727             :       // Every 3dNow instruction starts with 0x0F0F and the actual opcode is
    2728             :       // stored as 8-bit immediate.
    2729           0 :       imVal = opCode & 0xFF;
    2730             :       imLen = 1;
    2731             : 
    2732             :       opCode = X86Inst::kOpCode_MM_0F | 0x0F;
    2733             :       opReg = o0.getId();
    2734             : 
    2735           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    2736             :         rbReg = o1.getId();
    2737           0 :         goto EmitX86R;
    2738             :       }
    2739             : 
    2740           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    2741             :         rmRel = &o1;
    2742           0 :         goto EmitX86M;
    2743             :       }
    2744             :       break;
    2745             : 
    2746             :     // ------------------------------------------------------------------------
    2747             :     // [VEX/EVEX]
    2748             :     // ------------------------------------------------------------------------
    2749             : 
    2750           0 :     case X86Inst::kEncodingVexOp:
    2751           0 :       goto EmitVexEvexOp;
    2752             : 
    2753           0 :     case X86Inst::kEncodingVexKmov:
    2754           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    2755             :         opReg = o0.getId();
    2756             :         rbReg = o1.getId();
    2757             : 
    2758             :         // Form 'k, reg'.
    2759           0 :         if (X86Reg::isGp(o1)) {
    2760             :           opCode = commonData->getAltOpCode();
    2761           0 :           goto EmitVexEvexR;
    2762             :         }
    2763             : 
    2764             :         // Form 'reg, k'.
    2765           0 :         if (X86Reg::isGp(o0)) {
    2766           0 :           opCode = commonData->getAltOpCode() + 1;
    2767           0 :           goto EmitVexEvexR;
    2768             :         }
    2769             : 
    2770             :         // Form 'k, k'.
    2771           0 :         if (!(options & X86Inst::kOptionModMR))
    2772           0 :           goto EmitVexEvexR;
    2773             : 
    2774           0 :         opCode++;
    2775             :         Utils::swap(opReg, rbReg);
    2776           0 :         goto EmitVexEvexR;
    2777             :       }
    2778             : 
    2779           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    2780             :         opReg = o0.getId();
    2781             :         rmRel = &o1;
    2782             : 
    2783           0 :         goto EmitVexEvexM;
    2784             :       }
    2785             : 
    2786           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    2787             :         opReg = o1.getId();
    2788             :         rmRel = &o0;
    2789             : 
    2790           0 :         opCode++;
    2791           0 :         goto EmitVexEvexM;
    2792             :       }
    2793             :       break;
    2794             : 
    2795           0 :     case X86Inst::kEncodingVexM:
    2796           0 :       if (isign3 == ENC_OPS1(Mem)) {
    2797             :         rmRel = &o0;
    2798           0 :         goto EmitVexEvexM;
    2799             :       }
    2800             :       break;
    2801             : 
    2802           0 :     case X86Inst::kEncodingVexM_VM:
    2803           0 :       if (isign3 == ENC_OPS1(Mem)) {
    2804           0 :         opCode |= x86OpCodeLByVMem(o0);
    2805             :         rmRel = &o0;
    2806           0 :         goto EmitVexEvexM;
    2807             :       }
    2808             :       break;
    2809             : 
    2810             :     case X86Inst::kEncodingVexMr_Lx:
    2811           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize());
    2812             : 
    2813           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    2814             :         opReg = o1.getId();
    2815             :         rbReg = o0.getId();
    2816           0 :         goto EmitVexEvexR;
    2817             :       }
    2818             : 
    2819           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    2820             :         opReg = o1.getId();
    2821             :         rmRel = &o0;
    2822           0 :         goto EmitVexEvexM;
    2823             :       }
    2824             :       break;
    2825             : 
    2826           0 :     case X86Inst::kEncodingVexMr_VM:
    2827           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    2828           0 :         opCode |= std::max(x86OpCodeLByVMem(o0), x86OpCodeLBySize(o1.getSize()));
    2829             : 
    2830             :         opReg = o1.getId();
    2831             :         rmRel = &o0;
    2832           0 :         goto EmitVexEvexM;
    2833             :       }
    2834             :       break;
    2835             : 
    2836             :     case X86Inst::kEncodingVexMri_Lx:
    2837           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize());
    2838             :       ASMJIT_FALLTHROUGH;
    2839             : 
    2840           0 :     case X86Inst::kEncodingVexMri:
    2841             :       imVal = static_cast<const Imm&>(o2).getInt64();
    2842             :       imLen = 1;
    2843             : 
    2844           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Imm)) {
    2845             :         opReg = o1.getId();
    2846             :         rbReg = o0.getId();
    2847           0 :         goto EmitVexEvexR;
    2848             :       }
    2849             : 
    2850           0 :       if (isign3 == ENC_OPS3(Mem, Reg, Imm)) {
    2851             :         opReg = o1.getId();
    2852             :         rmRel = &o0;
    2853           0 :         goto EmitVexEvexM;
    2854             :       }
    2855             :       break;
    2856             : 
    2857             :     case X86Inst::kEncodingVexRm_ZDI:
    2858           0 :       if (ASMJIT_UNLIKELY(!o2.isNone() && !x86IsImplicitMem(o2, X86Gp::kIdDi)))
    2859           0 :         goto InvalidInstruction;
    2860             : 
    2861           0 :       isign3 &= 0x3F;
    2862           0 :       goto CaseVexRm;
    2863             : 
    2864             :     case X86Inst::kEncodingVexRm_Wx:
    2865           0 :       ADD_REX_W(X86Reg::isGpq(o0) | X86Reg::isGpq(o1));
    2866           0 :       goto CaseVexRm;
    2867             : 
    2868             :     case X86Inst::kEncodingVexRm_Lx:
    2869           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize());
    2870             :       ASMJIT_FALLTHROUGH;
    2871             : 
    2872             :     case X86Inst::kEncodingVexRm:
    2873           0 : CaseVexRm:
    2874           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    2875             :         opReg = o0.getId();
    2876             :         rbReg = o1.getId();
    2877           0 :         goto EmitVexEvexR;
    2878             :       }
    2879             : 
    2880           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    2881             :         opReg = o0.getId();
    2882             :         rmRel = &o1;
    2883           0 :         goto EmitVexEvexM;
    2884             :       }
    2885             :       break;
    2886             : 
    2887           0 :     case X86Inst::kEncodingVexRm_VM:
    2888           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    2889           0 :         opCode |= std::max(x86OpCodeLByVMem(o1), x86OpCodeLBySize(o0.getSize()));
    2890             :         opReg = o0.getId();
    2891             :         rmRel = &o1;
    2892           0 :         goto EmitVexEvexM;
    2893             :       }
    2894             :       break;
    2895             : 
    2896           0 :     case X86Inst::kEncodingVexRm_T1_4X: {
    2897           0 :       if (!(options & kOptionOp4Op5Used))
    2898           0 :         goto InvalidInstruction;
    2899             : 
    2900           0 :       if (X86Reg::isZmm(o0  ) && X86Reg::isZmm(o1) &&
    2901           0 :           X86Reg::isZmm(o2  ) && X86Reg::isZmm(o3) &&
    2902           0 :           X86Reg::isZmm(_op4) && _op5.isMem()) {
    2903             : 
    2904             :         // Registers [o1, o2, o3, _op4] must start aligned and must be consecutive.
    2905             :         uint32_t i1 = o1.getId();
    2906             :         uint32_t i2 = o2.getId();
    2907             :         uint32_t i3 = o3.getId();
    2908             :         uint32_t i4 = _op4.getId();
    2909             : 
    2910           0 :         if (ASMJIT_UNLIKELY((i1 & 0x3) != 0 || i2 != i1 + 1 || i3 != i1 + 2 || i4 != i1 + 3))
    2911           0 :           goto NotConsecutiveRegs;
    2912             : 
    2913             :         opReg = o0.getId();
    2914           0 :         rmRel = &_op5;
    2915           0 :         goto EmitVexEvexM;
    2916             :       }
    2917             :       break;
    2918             :     }
    2919             : 
    2920             :     case X86Inst::kEncodingVexRmi_Wx:
    2921           0 :       ADD_REX_W(X86Reg::isGpq(o0) | X86Reg::isGpq(o1));
    2922           0 :       goto CaseVexRmi;
    2923             : 
    2924             :     case X86Inst::kEncodingVexRmi_Lx:
    2925           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize());
    2926             :       ASMJIT_FALLTHROUGH;
    2927             : 
    2928             :     case X86Inst::kEncodingVexRmi:
    2929           0 : CaseVexRmi:
    2930             :       imVal = static_cast<const Imm&>(o2).getInt64();
    2931             :       imLen = 1;
    2932             : 
    2933           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Imm)) {
    2934             :         opReg = o0.getId();
    2935             :         rbReg = o1.getId();
    2936           0 :         goto EmitVexEvexR;
    2937             :       }
    2938             : 
    2939           0 :       if (isign3 == ENC_OPS3(Reg, Mem, Imm)) {
    2940             :         opReg = o0.getId();
    2941             :         rmRel = &o1;
    2942           0 :         goto EmitVexEvexM;
    2943             :       }
    2944             :       break;
    2945             : 
    2946             :     case X86Inst::kEncodingVexRvm:
    2947           0 : CaseVexRvm:
    2948           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Reg)) {
    2949           0 : CaseVexRvm_R:
    2950             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    2951             :         rbReg = o2.getId();
    2952           0 :         goto EmitVexEvexR;
    2953             :       }
    2954             : 
    2955           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Mem)) {
    2956             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    2957             :         rmRel = &o2;
    2958           0 :         goto EmitVexEvexM;
    2959             :       }
    2960             :       break;
    2961             : 
    2962             :     case X86Inst::kEncodingVexRvm_ZDX_Wx:
    2963           0 :       if (ASMJIT_UNLIKELY(!o3.isNone() && !X86Reg::isGp(o3, X86Gp::kIdDx)))
    2964           0 :         goto InvalidInstruction;
    2965             :       ASMJIT_FALLTHROUGH;
    2966             : 
    2967             :     case X86Inst::kEncodingVexRvm_Wx:
    2968           0 :       ADD_REX_W(X86Reg::isGpq(o0) | (o2.getSize() == 8));
    2969           0 :       goto CaseVexRvm;
    2970             : 
    2971             :     case X86Inst::kEncodingVexRvm_Lx:
    2972           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize());
    2973           0 :       goto CaseVexRvm;
    2974             : 
    2975             :     case X86Inst::kEncodingVexRvmr_Lx:
    2976           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize());
    2977             :       ASMJIT_FALLTHROUGH;
    2978             : 
    2979           0 :     case X86Inst::kEncodingVexRvmr: {
    2980           0 :       const uint32_t isign4 = isign3 + (o3.getOp() << 9);
    2981           0 :       imVal = o3.getId() << 4;
    2982             :       imLen = 1;
    2983             : 
    2984           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
    2985             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    2986             :         rbReg = o2.getId();
    2987           0 :         goto EmitVexEvexR;
    2988             :       }
    2989             : 
    2990           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Mem, Reg)) {
    2991             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    2992             :         rmRel = &o2;
    2993           0 :         goto EmitVexEvexM;
    2994             :       }
    2995             :       break;
    2996             :     }
    2997             : 
    2998             :     case X86Inst::kEncodingVexRvmi_Lx:
    2999           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize());
    3000             :       ASMJIT_FALLTHROUGH;
    3001             : 
    3002           0 :     case X86Inst::kEncodingVexRvmi: {
    3003           0 :       const uint32_t isign4 = isign3 + (o3.getOp() << 9);
    3004             :       imVal = static_cast<const Imm&>(o3).getInt64();
    3005             :       imLen = 1;
    3006             : 
    3007           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
    3008             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3009             :         rbReg = o2.getId();
    3010           0 :         goto EmitVexEvexR;
    3011             :       }
    3012             : 
    3013           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Mem, Imm)) {
    3014             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3015             :         rmRel = &o2;
    3016           0 :         goto EmitVexEvexM;
    3017             :       }
    3018             :       break;
    3019             :     }
    3020             : 
    3021             :     case X86Inst::kEncodingVexRmv_Wx:
    3022           0 :       ADD_REX_W(X86Reg::isGpq(o0) | X86Reg::isGpq(o2));
    3023             :       ASMJIT_FALLTHROUGH;
    3024             : 
    3025             :     case X86Inst::kEncodingVexRmv:
    3026           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Reg)) {
    3027             :         opReg = x86PackRegAndVvvvv(o0.getId(), o2.getId());
    3028             :         rbReg = o1.getId();
    3029           0 :         goto EmitVexEvexR;
    3030             :       }
    3031             : 
    3032           0 :       if (isign3 == ENC_OPS3(Reg, Mem, Reg)) {
    3033             :         opReg = x86PackRegAndVvvvv(o0.getId(), o2.getId());
    3034             :         rmRel = &o1;
    3035           0 :         goto EmitVexEvexM;
    3036             :       }
    3037             :       break;
    3038             : 
    3039           0 :     case X86Inst::kEncodingVexRmvRm_VM:
    3040           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    3041             :         opCode  = commonData->getAltOpCode();
    3042           0 :         opCode |= std::max(x86OpCodeLByVMem(o1), x86OpCodeLBySize(o0.getSize()));
    3043             : 
    3044             :         opReg = o0.getId();
    3045             :         rmRel = &o1;
    3046           0 :         goto EmitVexEvexM;
    3047             :       }
    3048             : 
    3049             :       ASMJIT_FALLTHROUGH;
    3050             : 
    3051             :     case X86Inst::kEncodingVexRmv_VM:
    3052           0 :       if (isign3 == ENC_OPS3(Reg, Mem, Reg)) {
    3053           0 :         opCode |= std::max(x86OpCodeLByVMem(o1), x86OpCodeLBySize(o0.getSize() | o2.getSize()));
    3054             : 
    3055             :         opReg = x86PackRegAndVvvvv(o0.getId(), o2.getId());
    3056             :         rmRel = &o1;
    3057           0 :         goto EmitVexEvexM;
    3058             :       }
    3059             :       break;
    3060             : 
    3061             : 
    3062             :     case X86Inst::kEncodingVexRmvi: {
    3063           0 :       const uint32_t isign4 = isign3 + (o3.getOp() << 9);
    3064             :       imVal = static_cast<const Imm&>(o3).getInt64();
    3065             :       imLen = 1;
    3066             : 
    3067           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
    3068             :         opReg = x86PackRegAndVvvvv(o0.getId(), o2.getId());
    3069             :         rbReg = o1.getId();
    3070           0 :         goto EmitVexEvexR;
    3071             :       }
    3072             : 
    3073           0 :       if (isign4 == ENC_OPS4(Reg, Mem, Reg, Imm)) {
    3074             :         opReg = x86PackRegAndVvvvv(o0.getId(), o2.getId());
    3075             :         rmRel = &o1;
    3076           0 :         goto EmitVexEvexM;
    3077             :       }
    3078             :       break;
    3079             :     }
    3080             : 
    3081           0 :     case X86Inst::kEncodingVexMovdMovq:
    3082           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    3083           0 :         if (X86Reg::isGp(o0)) {
    3084             :           opCode = commonData->getAltOpCode();
    3085           0 :           ADD_REX_W_BY_SIZE(o0.getSize());
    3086             :           opReg = o1.getId();
    3087             :           rbReg = o0.getId();
    3088           0 :           goto EmitVexEvexR;
    3089             :         }
    3090             : 
    3091           0 :         if (X86Reg::isGp(o1)) {
    3092           0 :           ADD_REX_W_BY_SIZE(o1.getSize());
    3093             :           opReg = o0.getId();
    3094             :           rbReg = o1.getId();
    3095           0 :           goto EmitVexEvexR;
    3096             :         }
    3097             : 
    3098             :         // If this is a 'W' version (movq) then allow also vmovq 'xmm|xmm' form.
    3099           0 :         if (opCode & X86Inst::kOpCode_EW) {
    3100           0 :           opCode &= ~(X86Inst::kOpCode_PP_VEXMask | X86Inst::kOpCode_MM_Mask | 0xFF);
    3101           0 :           opCode |=  (X86Inst::kOpCode_PP_F3      | X86Inst::kOpCode_MM_0F   | 0x7E);
    3102             : 
    3103             :           opReg = o0.getId();
    3104             :           rbReg = o1.getId();
    3105           0 :           goto EmitVexEvexR;
    3106             :         }
    3107             :       }
    3108             : 
    3109           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    3110           0 :         if (opCode & X86Inst::kOpCode_EW) {
    3111           0 :           opCode &= ~(X86Inst::kOpCode_PP_VEXMask | X86Inst::kOpCode_MM_Mask | 0xFF);
    3112           0 :           opCode |=  (X86Inst::kOpCode_PP_F3      | X86Inst::kOpCode_MM_0F   | 0x7E);
    3113             :         }
    3114             : 
    3115             :         opReg = o0.getId();
    3116             :         rmRel = &o1;
    3117           0 :         goto EmitVexEvexM;
    3118             :       }
    3119             : 
    3120             :       // The following instruction uses the secondary opcode.
    3121             :       opCode = commonData->getAltOpCode();
    3122             : 
    3123           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    3124           0 :         if (opCode & X86Inst::kOpCode_EW) {
    3125           0 :           opCode &= ~(X86Inst::kOpCode_PP_VEXMask | X86Inst::kOpCode_MM_Mask | 0xFF);
    3126           0 :           opCode |=  (X86Inst::kOpCode_PP_66      | X86Inst::kOpCode_MM_0F   | 0xD6);
    3127             :         }
    3128             : 
    3129             :         opReg = o1.getId();
    3130             :         rmRel = &o0;
    3131           0 :         goto EmitVexEvexM;
    3132             :       }
    3133             :       break;
    3134             : 
    3135             :     case X86Inst::kEncodingVexRmMr_Lx:
    3136           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize());
    3137             :       ASMJIT_FALLTHROUGH;
    3138             : 
    3139           0 :     case X86Inst::kEncodingVexRmMr:
    3140           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    3141             :         opReg = o0.getId();
    3142             :         rbReg = o1.getId();
    3143           0 :         goto EmitVexEvexR;
    3144             :       }
    3145             : 
    3146           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    3147             :         opReg = o0.getId();
    3148             :         rmRel = &o1;
    3149           0 :         goto EmitVexEvexM;
    3150             :       }
    3151             : 
    3152             :       // The following instruction uses the secondary opcode.
    3153           0 :       opCode &= X86Inst::kOpCode_LL_Mask;
    3154           0 :       opCode |= commonData->getAltOpCode();
    3155             : 
    3156           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    3157             :         opReg = o1.getId();
    3158             :         rmRel = &o0;
    3159           0 :         goto EmitVexEvexM;
    3160             :       }
    3161             :       break;
    3162             : 
    3163           0 :     case X86Inst::kEncodingVexRvmRmv:
    3164           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Reg)) {
    3165             :         opReg = x86PackRegAndVvvvv(o0.getId(), o2.getId());
    3166             :         rbReg = o1.getId();
    3167             : 
    3168           0 :         if (!(options & X86Inst::kOptionModMR))
    3169           0 :           goto EmitVexEvexR;
    3170             : 
    3171             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3172             :         rbReg = o2.getId();
    3173             : 
    3174           0 :         ADD_VEX_W(true);
    3175           0 :         goto EmitVexEvexR;
    3176             :       }
    3177             : 
    3178           0 :       if (isign3 == ENC_OPS3(Reg, Mem, Reg)) {
    3179             :         opReg = x86PackRegAndVvvvv(o0.getId(), o2.getId());
    3180             :         rmRel = &o1;
    3181           0 :         goto EmitVexEvexM;
    3182             :       }
    3183             : 
    3184           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Mem)) {
    3185             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3186             :         rmRel = &o2;
    3187             : 
    3188           0 :         ADD_VEX_W(true);
    3189           0 :         goto EmitVexEvexM;
    3190             :       }
    3191             :       break;
    3192             : 
    3193             :     case X86Inst::kEncodingVexRvmRmi_Lx:
    3194           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize());
    3195             :       ASMJIT_FALLTHROUGH;
    3196             : 
    3197           0 :     case X86Inst::kEncodingVexRvmRmi:
    3198           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Reg)) {
    3199             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3200             :         rbReg = o2.getId();
    3201           0 :         goto EmitVexEvexR;
    3202             :       }
    3203             : 
    3204           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Mem)) {
    3205             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3206             :         rmRel = &o2;
    3207           0 :         goto EmitVexEvexM;
    3208             :       }
    3209             : 
    3210             :       // The following instructions use the secondary opcode.
    3211           0 :       opCode &= X86Inst::kOpCode_LL_Mask;
    3212           0 :       opCode |= commonData->getAltOpCode();
    3213             : 
    3214             :       imVal = static_cast<const Imm&>(o2).getInt64();
    3215             :       imLen = 1;
    3216             : 
    3217           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Imm)) {
    3218             :         opReg = o0.getId();
    3219             :         rbReg = o1.getId();
    3220           0 :         goto EmitVexEvexR;
    3221             :       }
    3222             : 
    3223           0 :       if (isign3 == ENC_OPS3(Reg, Mem, Imm)) {
    3224             :         opReg = o0.getId();
    3225             :         rmRel = &o1;
    3226           0 :         goto EmitVexEvexM;
    3227             :       }
    3228             :       break;
    3229             : 
    3230           0 :     case X86Inst::kEncodingVexRvmRmvRmi:
    3231           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Reg)) {
    3232             :         opReg = x86PackRegAndVvvvv(o0.getId(), o2.getId());
    3233             :         rbReg = o1.getId();
    3234             : 
    3235           0 :         if (!(options & X86Inst::kOptionModMR))
    3236           0 :           goto EmitVexEvexR;
    3237             : 
    3238             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3239             :         rbReg = o2.getId();
    3240             : 
    3241           0 :         ADD_VEX_W(true);
    3242           0 :         goto EmitVexEvexR;
    3243             :       }
    3244             : 
    3245           0 :       if (isign3 == ENC_OPS3(Reg, Mem, Reg)) {
    3246             :         opReg = x86PackRegAndVvvvv(o0.getId(), o2.getId());
    3247             :         rmRel = &o1;
    3248             : 
    3249           0 :         goto EmitVexEvexM;
    3250             :       }
    3251             : 
    3252           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Mem)) {
    3253             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3254             :         rmRel = &o2;
    3255             : 
    3256           0 :         ADD_VEX_W(true);
    3257           0 :         goto EmitVexEvexM;
    3258             :       }
    3259             : 
    3260             :       // The following instructions use the secondary opcode.
    3261             :       opCode = commonData->getAltOpCode();
    3262             : 
    3263             :       imVal = static_cast<const Imm&>(o2).getInt64();
    3264             :       imLen = 1;
    3265             : 
    3266           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Imm)) {
    3267             :         opReg = o0.getId();
    3268             :         rbReg = o1.getId();
    3269           0 :         goto EmitVexEvexR;
    3270             :       }
    3271             : 
    3272           0 :       if (isign3 == ENC_OPS3(Reg, Mem, Imm)) {
    3273             :         opReg = o0.getId();
    3274             :         rmRel = &o1;
    3275           0 :         goto EmitVexEvexM;
    3276             :       }
    3277             :       break;
    3278             : 
    3279           0 :     case X86Inst::kEncodingVexRvmMr:
    3280           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Reg)) {
    3281             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3282             :         rbReg = o2.getId();
    3283           0 :         goto EmitVexEvexR;
    3284             :       }
    3285             : 
    3286           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Mem)) {
    3287             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3288             :         rmRel = &o2;
    3289           0 :         goto EmitVexEvexM;
    3290             :       }
    3291             : 
    3292             :       // The following instructions use the secondary opcode.
    3293             :       opCode = commonData->getAltOpCode();
    3294             : 
    3295           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    3296             :         opReg = o1.getId();
    3297             :         rbReg = o0.getId();
    3298           0 :         goto EmitVexEvexR;
    3299             :       }
    3300             : 
    3301           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    3302             :         opReg = o1.getId();
    3303             :         rmRel = &o0;
    3304           0 :         goto EmitVexEvexM;
    3305             :       }
    3306             :       break;
    3307             : 
    3308             :     case X86Inst::kEncodingVexRvmMvr_Lx:
    3309           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize());
    3310             :       ASMJIT_FALLTHROUGH;
    3311             : 
    3312           0 :     case X86Inst::kEncodingVexRvmMvr:
    3313           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Reg)) {
    3314             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3315             :         rbReg = o2.getId();
    3316           0 :         goto EmitVexEvexR;
    3317             :       }
    3318             : 
    3319           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Mem)) {
    3320             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3321             :         rmRel = &o2;
    3322           0 :         goto EmitVexEvexM;
    3323             :       }
    3324             : 
    3325             :       // The following instruction uses the secondary opcode.
    3326           0 :       opCode &= X86Inst::kOpCode_LL_Mask;
    3327           0 :       opCode |= commonData->getAltOpCode();
    3328             : 
    3329           0 :       if (isign3 == ENC_OPS3(Mem, Reg, Reg)) {
    3330             :         opReg = x86PackRegAndVvvvv(o2.getId(), o1.getId());
    3331             :         rmRel = &o0;
    3332           0 :         goto EmitVexEvexM;
    3333             :       }
    3334             :       break;
    3335             : 
    3336             :     case X86Inst::kEncodingVexRvmVmi_Lx:
    3337           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize());
    3338             :       ASMJIT_FALLTHROUGH;
    3339             : 
    3340           0 :     case X86Inst::kEncodingVexRvmVmi:
    3341           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Reg)) {
    3342             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3343             :         rbReg = o2.getId();
    3344           0 :         goto EmitVexEvexR;
    3345             :       }
    3346             : 
    3347           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Mem)) {
    3348             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3349             :         rmRel = &o2;
    3350           0 :         goto EmitVexEvexM;
    3351             :       }
    3352             : 
    3353             :       // The following instruction uses the secondary opcode.
    3354           0 :       opCode &= X86Inst::kOpCode_LL_Mask;
    3355           0 :       opCode |= commonData->getAltOpCode();
    3356             :       opReg = x86ExtractO(opCode);
    3357             : 
    3358             :       imVal = static_cast<const Imm&>(o2).getInt64();
    3359             :       imLen = 1;
    3360             : 
    3361           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Imm)) {
    3362             :         opReg = x86PackRegAndVvvvv(opReg, o0.getId());
    3363             :         rbReg = o1.getId();
    3364           0 :         goto EmitVexEvexR;
    3365             :       }
    3366             : 
    3367           0 :       if (isign3 == ENC_OPS3(Reg, Mem, Imm)) {
    3368             :         opReg = x86PackRegAndVvvvv(opReg, o0.getId());
    3369             :         rmRel = &o1;
    3370           0 :         goto EmitVexEvexM;
    3371             :       }
    3372             :       break;
    3373             : 
    3374             :     case X86Inst::kEncodingVexVm_Wx:
    3375           0 :       ADD_REX_W(X86Reg::isGpq(o0) | X86Reg::isGpq(o1));
    3376             :       ASMJIT_FALLTHROUGH;
    3377             : 
    3378             :     case X86Inst::kEncodingVexVm:
    3379           0 :       if (isign3 == ENC_OPS2(Reg, Reg)) {
    3380             :         opReg = x86PackRegAndVvvvv(opReg, o0.getId());
    3381             :         rbReg = o1.getId();
    3382           0 :         goto EmitVexEvexR;
    3383             :       }
    3384             : 
    3385           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    3386             :         opReg = x86PackRegAndVvvvv(opReg, o0.getId());
    3387             :         rmRel = &o1;
    3388           0 :         goto EmitVexEvexM;
    3389             :       }
    3390             :       break;
    3391             : 
    3392           0 :     case X86Inst::kEncodingVexEvexVmi_Lx:
    3393           0 :       if (isign3 == ENC_OPS3(Reg, Mem, Imm))
    3394           0 :         opCode |= X86Inst::kOpCode_MM_ForceEvex;
    3395             :       ASMJIT_FALLTHROUGH;
    3396             : 
    3397             :     case X86Inst::kEncodingVexVmi_Lx:
    3398           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize());
    3399             :       ASMJIT_FALLTHROUGH;
    3400             : 
    3401           0 :     case X86Inst::kEncodingVexVmi:
    3402             :       imVal = static_cast<const Imm&>(o2).getInt64();
    3403             :       imLen = 1;
    3404             : 
    3405           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Imm)) {
    3406             :         opReg = x86PackRegAndVvvvv(opReg, o0.getId());
    3407             :         rbReg = o1.getId();
    3408           0 :         goto EmitVexEvexR;
    3409             :       }
    3410             : 
    3411           0 :       if (isign3 == ENC_OPS3(Reg, Mem, Imm)) {
    3412             :         opReg = x86PackRegAndVvvvv(opReg, o0.getId());
    3413             :         rmRel = &o1;
    3414           0 :         goto EmitVexEvexM;
    3415             :       }
    3416             :       break;
    3417             : 
    3418             :     case X86Inst::kEncodingVexRvrmRvmr_Lx:
    3419           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize());
    3420             :       ASMJIT_FALLTHROUGH;
    3421             : 
    3422           0 :     case X86Inst::kEncodingVexRvrmRvmr: {
    3423           0 :       const uint32_t isign4 = isign3 + (o3.getOp() << 9);
    3424             : 
    3425           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
    3426           0 :         imVal = o3.getId() << 4;
    3427             :         imLen = 1;
    3428             : 
    3429             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3430             :         rbReg = o2.getId();
    3431             : 
    3432           0 :         goto EmitVexEvexR;
    3433             :       }
    3434             : 
    3435           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Mem)) {
    3436           0 :         imVal = o2.getId() << 4;
    3437             :         imLen = 1;
    3438             : 
    3439             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3440             :         rmRel = &o3;
    3441             : 
    3442           0 :         ADD_VEX_W(true);
    3443           0 :         goto EmitVexEvexM;
    3444             :       }
    3445             : 
    3446           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Mem, Reg)) {
    3447           0 :         imVal = o3.getId() << 4;
    3448             :         imLen = 1;
    3449             : 
    3450             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3451             :         rmRel = &o2;
    3452             : 
    3453           0 :         goto EmitVexEvexM;
    3454             :       }
    3455             :       break;
    3456             :     }
    3457             : 
    3458           0 :     case X86Inst::kEncodingVexRvrmiRvmri_Lx: {
    3459           0 :       if (!(options & CodeEmitter::kOptionOp4Op5Used) || !_op4.isImm())
    3460           0 :         goto InvalidInstruction;
    3461             : 
    3462           0 :       const uint32_t isign4 = isign3 + (o3.getOp() << 9);
    3463           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize() | o2.getSize() | o3.getSize());
    3464             : 
    3465           0 :       imVal = static_cast<const Imm&>(_op4).getUInt8() & 0x0F;
    3466             :       imLen = 1;
    3467             : 
    3468           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
    3469           0 :         imVal |= o3.getId() << 4;
    3470             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3471             :         rbReg = o2.getId();
    3472             : 
    3473           0 :         goto EmitVexEvexR;
    3474             :       }
    3475             : 
    3476           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Mem)) {
    3477           0 :         imVal |= o2.getId() << 4;
    3478             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3479             :         rmRel = &o3;
    3480             : 
    3481           0 :         ADD_VEX_W(true);
    3482           0 :         goto EmitVexEvexM;
    3483             :       }
    3484             : 
    3485           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Mem, Reg)) {
    3486           0 :         imVal |= o3.getId() << 4;
    3487             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3488             :         rmRel = &o2;
    3489             : 
    3490           0 :         goto EmitVexEvexM;
    3491             :       }
    3492             :       break;
    3493             :     }
    3494             : 
    3495           0 :     case X86Inst::kEncodingVexMovssMovsd:
    3496           0 :       if (isign3 == ENC_OPS3(Reg, Reg, Reg)) {
    3497           0 :         goto CaseVexRvm_R;
    3498             :       }
    3499             : 
    3500           0 :       if (isign3 == ENC_OPS2(Reg, Mem)) {
    3501             :         opReg = o0.getId();
    3502             :         rmRel = &o1;
    3503           0 :         goto EmitVexEvexM;
    3504             :       }
    3505             : 
    3506           0 :       if (isign3 == ENC_OPS2(Mem, Reg)) {
    3507             :         opCode = commonData->getAltOpCode();
    3508             :         opReg = o1.getId();
    3509             :         rmRel = &o0;
    3510           0 :         goto EmitVexEvexM;
    3511             :       }
    3512             :       break;
    3513             : 
    3514             :     // ------------------------------------------------------------------------
    3515             :     // [FMA4]
    3516             :     // ------------------------------------------------------------------------
    3517             : 
    3518             :     case X86Inst::kEncodingFma4_Lx:
    3519             :       // It's fine to just check the first operand, second is just for sanity.
    3520           0 :       opCode |= x86OpCodeLBySize(o0.getSize() | o1.getSize());
    3521             :       ASMJIT_FALLTHROUGH;
    3522             : 
    3523           0 :     case X86Inst::kEncodingFma4: {
    3524           0 :       const uint32_t isign4 = isign3 + (o3.getOp() << 9);
    3525             : 
    3526           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
    3527           0 :         imVal = o3.getId() << 4;
    3528             :         imLen = 1;
    3529             : 
    3530             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3531             :         rbReg = o2.getId();
    3532             : 
    3533           0 :         goto EmitVexEvexR;
    3534             :       }
    3535             : 
    3536           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Mem)) {
    3537           0 :         imVal = o2.getId() << 4;
    3538             :         imLen = 1;
    3539             : 
    3540             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3541             :         rmRel = &o3;
    3542             : 
    3543           0 :         ADD_VEX_W(true);
    3544           0 :         goto EmitVexEvexM;
    3545             :       }
    3546             : 
    3547           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Mem, Reg)) {
    3548           0 :         imVal = o3.getId() << 4;
    3549             :         imLen = 1;
    3550             : 
    3551             :         opReg = x86PackRegAndVvvvv(o0.getId(), o1.getId());
    3552             :         rmRel = &o2;
    3553             : 
    3554           0 :         goto EmitVexEvexM;
    3555             :       }
    3556             :       break;
    3557             :     }
    3558             :   }
    3559           0 :   goto InvalidInstruction;
    3560             : 
    3561             :   // --------------------------------------------------------------------------
    3562             :   // [Emit - X86]
    3563             :   // --------------------------------------------------------------------------
    3564             : 
    3565           0 : EmitX86OpMovAbs:
    3566             :   imLen = getGpSize();
    3567             : 
    3568             :   // Segment-override prefix.
    3569           0 :   if (rmRel->as<X86Mem>().hasSegment())
    3570           0 :     EMIT_BYTE(x86SegmentPrefix[rmRel->as<X86Mem>().getSegmentId()]);
    3571             : 
    3572           0 : EmitX86Op:
    3573             :   // Emit mandatory instruction prefix.
    3574       32111 :   EMIT_PP(opCode);
    3575             : 
    3576             :   // Emit REX prefix (64-bit only).
    3577             :   {
    3578             :     uint32_t rex = x86ExtractREX(opCode, options);
    3579       32111 :     if (rex) {
    3580           0 :       if (options & X86Inst::_kOptionInvalidRex)
    3581           0 :         goto InvalidRexPrefix;
    3582           0 :       EMIT_BYTE(rex | kX86ByteRex);
    3583             :     }
    3584             :   }
    3585             : 
    3586             :   // Emit instruction opcodes.
    3587       32111 :   EMIT_MM_OP(opCode);
    3588             : 
    3589       32111 :   if (imLen != 0)
    3590           0 :     goto EmitImm;
    3591             :   else
    3592       32111 :     goto EmitDone;
    3593             : 
    3594      120610 : EmitX86OpReg:
    3595             :   // Emit mandatory instruction prefix.
    3596      120610 :   EMIT_PP(opCode);
    3597             : 
    3598             :   // Emit REX prefix (64-bit only).
    3599             :   {
    3600             :     uint32_t rex = x86ExtractREX(opCode, options) |
    3601      120610 :                    (opReg >> 3); // Rex.B (0x01).
    3602      120610 :     if (rex) {
    3603      106298 :       EMIT_BYTE(rex | kX86ByteRex);
    3604      106298 :       if (options & X86Inst::_kOptionInvalidRex)
    3605           0 :         goto InvalidRexPrefix;
    3606      106298 :       opReg &= 0x7;
    3607             :     }
    3608             :   }
    3609             : 
    3610             :   // Emit instruction opcodes.
    3611      120610 :   opCode += opReg;
    3612      120610 :   EMIT_MM_OP(opCode);
    3613             : 
    3614      120610 :   if (imLen != 0)
    3615      106298 :     goto EmitImm;
    3616             :   else
    3617       14312 :     goto EmitDone;
    3618             : 
    3619           0 : EmitX86OpImplicitMem:
    3620             :   // NOTE: Don't change the emit order here, it's compatible with KeyStone/LLVM.
    3621           0 :   rmInfo = x86MemInfo[rmRel->as<X86Mem>().getBaseIndexType()];
    3622           0 :   if (ASMJIT_UNLIKELY(rmRel->as<X86Mem>().hasOffset() || (rmInfo & kX86MemInfo_Index)))
    3623           0 :     goto InvalidInstruction;
    3624             : 
    3625             :   // Emit mandatory instruction prefix.
    3626           0 :   EMIT_PP(opCode);
    3627             : 
    3628             :   // Emit REX prefix (64-bit only).
    3629             :   {
    3630             :     uint32_t rex = x86ExtractREX(opCode, options);
    3631           0 :     if (rex) {
    3632           0 :       if (options & X86Inst::_kOptionInvalidRex)
    3633           0 :         goto InvalidRexPrefix;
    3634           0 :       EMIT_BYTE(rex | kX86ByteRex);
    3635             :     }
    3636             :   }
    3637             : 
    3638             :   // Segment-override prefix.
    3639           0 :   if (rmRel->as<X86Mem>().hasSegment())
    3640           0 :     EMIT_BYTE(x86SegmentPrefix[rmRel->as<X86Mem>().getSegmentId()]);
    3641             : 
    3642             :   // Address-override prefix.
    3643           0 :   if (rmInfo & _getAddressOverrideMask())
    3644           0 :     EMIT_BYTE(0x67);
    3645             : 
    3646             :   // Emit instruction opcodes.
    3647           0 :   EMIT_MM_OP(opCode);
    3648             : 
    3649             :   if (imLen != 0)
    3650             :     goto EmitImm;
    3651             :   else
    3652           0 :     goto EmitDone;
    3653             : 
    3654      264466 : EmitX86R:
    3655             :   // Mandatory instruction prefix.
    3656      264466 :   EMIT_PP(opCode);
    3657             : 
    3658             :   // Rex prefix (64-bit only).
    3659             :   {
    3660      264466 :     uint32_t rex = x86ExtractREX(opCode, options) |
    3661      264466 :                    ((opReg & 0x08) >> 1) | // REX.R (0x04).
    3662      264466 :                    ((rbReg       ) >> 3) ; // REX.B (0x01).
    3663      264466 :     if (rex) {
    3664       24182 :       if (options & X86Inst::_kOptionInvalidRex)
    3665           0 :         goto InvalidRexPrefix;
    3666       24182 :       EMIT_BYTE(rex | kX86ByteRex);
    3667       24182 :       opReg &= 0x07;
    3668       24182 :       rbReg &= 0x07;
    3669             :     }
    3670             :   }
    3671             : 
    3672             :   // Instruction opcodes.
    3673      264466 :   EMIT_MM_OP(opCode);
    3674             :   // ModR.
    3675      264466 :   EMIT_BYTE(x86EncodeMod(3, opReg, rbReg));
    3676             : 
    3677      264466 :   if (imLen != 0)
    3678       11694 :     goto EmitImm;
    3679             :   else
    3680      252772 :     goto EmitDone;
    3681             : 
    3682      176113 : EmitX86M:
    3683             :   ASMJIT_ASSERT(rmRel != nullptr);
    3684             :   ASMJIT_ASSERT(rmRel->getOp() == Operand::kOpMem);
    3685      176113 :   rmInfo = x86MemInfo[rmRel->as<X86Mem>().getBaseIndexType()];
    3686             : 
    3687             :   // GP instructions have never compressed displacement specified.
    3688             :   ASMJIT_ASSERT((opCode & X86Inst::kOpCode_CDSHL_Mask) == 0);
    3689             : 
    3690             :   // Segment-override prefix.
    3691      176113 :   if (rmRel->as<X86Mem>().hasSegment())
    3692           0 :     EMIT_BYTE(x86SegmentPrefix[rmRel->as<X86Mem>().getSegmentId()]);
    3693             : 
    3694             :   // Address-override prefix.
    3695      176113 :   if (rmInfo & _getAddressOverrideMask())
    3696           0 :     EMIT_BYTE(0x67);
    3697             : 
    3698             :   // Mandatory instruction prefix.
    3699      176113 :   EMIT_PP(opCode);
    3700             : 
    3701             :   rbReg = rmRel->as<X86Mem>().getBaseId();
    3702             :   rxReg = rmRel->as<X86Mem>().getIndexId();
    3703             : 
    3704             :   // REX prefix (64-bit only).
    3705             :   {
    3706             :     uint32_t rex;
    3707             : 
    3708      176113 :     rex  = (rbReg >> 3) & 0x01; // REX.B (0x01).
    3709      176113 :     rex |= (rxReg >> 2) & 0x02; // REX.X (0x02).
    3710      176113 :     rex |= (opReg >> 1) & 0x04; // REX.R (0x04).
    3711             : 
    3712      176113 :     rex &= rmInfo;
    3713      176113 :     rex |= x86ExtractREX(opCode, options);
    3714             : 
    3715      176113 :     if (rex) {
    3716       15564 :       if (options & X86Inst::_kOptionInvalidRex)
    3717           0 :         goto InvalidRexPrefix;
    3718       15564 :       EMIT_BYTE(rex | kX86ByteRex);
    3719       15564 :       opReg &= 0x07;
    3720             :     }
    3721             :   }
    3722             : 
    3723             :   // Instruction opcodes.
    3724      176113 :   EMIT_MM_OP(opCode);
    3725             :   // ... Fall through ...
    3726             : 
    3727             :   // --------------------------------------------------------------------------
    3728             :   // [Emit - MOD/SIB]
    3729             :   // --------------------------------------------------------------------------
    3730             : 
    3731      176113 : EmitModSib:
    3732      176113 :   if (!(rmInfo & (kX86MemInfo_Index | kX86MemInfo_67H_X86))) {
    3733             :     // ==========|> [BASE + DISP8|DISP32].
    3734      176113 :     if (rmInfo & kX86MemInfo_BaseGp) {
    3735      176113 :       rbReg &= 0x7;
    3736             :       relOffset = rmRel->as<X86Mem>().getOffsetLo32();
    3737             : 
    3738             :       uint32_t mod = x86EncodeMod(0, opReg, rbReg);
    3739      176113 :       if (rbReg == X86Gp::kIdSp) {
    3740             :         // [XSP|R12].
    3741       92292 :         if (relOffset == 0) {
    3742        9424 :           EMIT_BYTE(mod);
    3743        9424 :           EMIT_BYTE(x86EncodeSib(0, 4, 4));
    3744             :         }
    3745             :         // [XSP|R12 + DISP8|DISP32].
    3746             :         else {
    3747       82868 :           uint32_t cdShift = (opCode & X86Inst::kOpCode_CDSHL_Mask) >> X86Inst::kOpCode_CDSHL_Shift;
    3748       82868 :           int32_t cdOffset = relOffset >> cdShift;
    3749             : 
    3750       82868 :           if (Utils::isInt8(cdOffset) && relOffset == (cdOffset << cdShift)) {
    3751       37808 :             EMIT_BYTE(mod + 0x40); // <- MOD(1, opReg, rbReg).
    3752       37808 :             EMIT_BYTE(x86EncodeSib(0, 4, 4));
    3753       37808 :             EMIT_BYTE(cdOffset & 0xFF);
    3754             :           }
    3755             :           else {
    3756       45060 :             EMIT_BYTE(mod + 0x80); // <- MOD(2, opReg, rbReg).
    3757       45060 :             EMIT_BYTE(x86EncodeSib(0, 4, 4));
    3758       45060 :             EMIT_32(relOffset);
    3759             :           }
    3760             :         }
    3761             :       }
    3762       83821 :       else if (rbReg != X86Gp::kIdBp && relOffset == 0) {
    3763             :         // [BASE].
    3764       60659 :         EMIT_BYTE(mod);
    3765             :       }
    3766             :       else {
    3767             :         // [BASE + DISP8|DISP32].
    3768       23162 :         uint32_t cdShift = (opCode & X86Inst::kOpCode_CDSHL_Mask) >> X86Inst::kOpCode_CDSHL_Shift;
    3769       23162 :         int32_t cdOffset = relOffset >> cdShift;
    3770             : 
    3771       23162 :         if (Utils::isInt8(cdOffset) && relOffset == (cdOffset << cdShift)) {
    3772       14986 :           EMIT_BYTE(mod + 0x40);
    3773       14986 :           EMIT_BYTE(cdOffset & 0xFF);
    3774             :         }
    3775             :         else {
    3776        8176 :           EMIT_BYTE(mod + 0x80);
    3777        8176 :           EMIT_32(relOffset);
    3778             :         }
    3779             :       }
    3780             :     }
    3781             :     // ==========|> [ABSOLUTE | DISP32].
    3782           0 :     else if (!(rmInfo & (kX86MemInfo_BaseLabel | kX86MemInfo_BaseRip))) {
    3783           0 :       if (is32Bit()) {
    3784             :         relOffset = rmRel->as<X86Mem>().getOffsetLo32();
    3785           0 :         EMIT_BYTE(x86EncodeMod(0, opReg, 5));
    3786           0 :         EMIT_32(relOffset);
    3787             :       }
    3788             :       else {
    3789             :         uint64_t baseAddress = getCodeInfo().getBaseAddress();
    3790             :         relOffset = rmRel->as<X86Mem>().getOffsetLo32();
    3791             : 
    3792             :         // Prefer absolute addressing mode if FS|GS segment override is present.
    3793           0 :         bool absoluteValid = rmRel->as<X86Mem>().getOffsetHi32() == (relOffset >> 31);
    3794           0 :         bool preferAbsolute = (rmRel->as<X86Mem>().getSegmentId() >= X86Seg::kIdFs) || rmRel->as<X86Mem>().isAbs();
    3795             : 
    3796             :         // If we know the base address and the memory operand points to an
    3797             :         // absolute address it's possible to calculate REL32 that can be
    3798             :         // be used as [RIP+REL32] in 64-bit mode.
    3799           0 :         if (baseAddress != Globals::kNoBaseAddress && !preferAbsolute) {
    3800             :           const uint32_t kModRel32Size = 5;
    3801           0 :           uint64_t rip64 = baseAddress +
    3802           0 :             static_cast<uint64_t>((uintptr_t)(cursor - _bufferData)) + imLen + kModRel32Size;
    3803             : 
    3804           0 :           uint64_t rel64 = static_cast<uint64_t>(rmRel->as<X86Mem>().getOffset()) - rip64;
    3805           0 :           if (Utils::isInt32(static_cast<int64_t>(rel64))) {
    3806           0 :             EMIT_BYTE(x86EncodeMod(0, opReg, 5));
    3807           0 :             EMIT_32(static_cast<uint32_t>(rel64 & 0xFFFFFFFFU));
    3808           0 :             if (imLen != 0)
    3809           0 :               goto EmitImm;
    3810             :             else
    3811           0 :               goto EmitDone;
    3812             :           }
    3813             :         }
    3814             : 
    3815           0 :         if (ASMJIT_UNLIKELY(!absoluteValid))
    3816           0 :           goto InvalidAddress64Bit;
    3817             : 
    3818           0 :         EMIT_BYTE(x86EncodeMod(0, opReg, 4));
    3819           0 :         EMIT_BYTE(x86EncodeSib(0, 4, 5));
    3820           0 :         EMIT_32(relOffset);
    3821             :       }
    3822             :     }
    3823             :     // ==========|> [LABEL|RIP + DISP32]
    3824             :     else {
    3825           0 :       EMIT_BYTE(x86EncodeMod(0, opReg, 5));
    3826             : 
    3827           0 :       if (is32Bit()) {
    3828           0 : EmitModSib_LabelRip_X86:
    3829           0 :         if (ASMJIT_UNLIKELY(_code->_relocations.willGrow(&_code->_baseHeap) != kErrorOk))
    3830           0 :           goto NoHeapMemory;
    3831             : 
    3832             :         relOffset = rmRel->as<X86Mem>().getOffsetLo32();
    3833           0 :         if (rmInfo & kX86MemInfo_BaseLabel) {
    3834             :           // [LABEL->ABS].
    3835           0 :           label = _code->getLabelEntry(rmRel->as<X86Mem>().getBaseId());
    3836           0 :           if (!label) goto InvalidLabel;
    3837             : 
    3838           0 :           err = _code->newRelocEntry(&re, RelocEntry::kTypeRelToAbs, 4);
    3839           0 :           if (ASMJIT_UNLIKELY(err)) goto Failed;
    3840             : 
    3841           0 :           re->_sourceSectionId = _section->getId();
    3842           0 :           re->_sourceOffset = static_cast<uint64_t>((uintptr_t)(cursor - _bufferData));
    3843           0 :           re->_data = static_cast<int64_t>(relOffset);
    3844             : 
    3845           0 :           if (label->isBound()) {
    3846             :             // Bound label.
    3847           0 :             re->_data += static_cast<uint64_t>(label->getOffset());
    3848           0 :             EMIT_32(0);
    3849             :           }
    3850             :           else {
    3851             :             // Non-bound label.
    3852           0 :             relOffset = -4 - imLen;
    3853             :             relSize = 4;
    3854           0 :             goto EmitRel;
    3855             :           }
    3856             :         }
    3857             :         else {
    3858             :           // [RIP->ABS].
    3859           0 :           err = _code->newRelocEntry(&re, RelocEntry::kTypeRelToAbs, 4);
    3860           0 :           if (ASMJIT_UNLIKELY(err)) goto Failed;
    3861             : 
    3862           0 :           re->_sourceSectionId = _section->getId();
    3863           0 :           re->_sourceOffset = static_cast<uint64_t>((uintptr_t)(cursor - _bufferData));
    3864           0 :           re->_data = re->_sourceOffset + static_cast<uint64_t>(static_cast<int64_t>(relOffset));
    3865           0 :           EMIT_32(0);
    3866             :         }
    3867             :       }
    3868             :       else {
    3869             :         relOffset = rmRel->as<X86Mem>().getOffsetLo32();
    3870           0 :         if (rmInfo & kX86MemInfo_BaseLabel) {
    3871             :           // [RIP].
    3872           0 :           label = _code->getLabelEntry(rmRel->as<X86Mem>().getBaseId());
    3873           0 :           if (!label) goto InvalidLabel;
    3874             : 
    3875           0 :           relOffset -= (4 + imLen);
    3876           0 :           if (label->isBound()) {
    3877             :             // Bound label.
    3878           0 :             relOffset += label->getOffset() - static_cast<int32_t>((intptr_t)(cursor - _bufferData));
    3879           0 :             EMIT_32(static_cast<int32_t>(relOffset));
    3880             :           }
    3881             :           else {
    3882             :             // Non-bound label.
    3883             :             relSize = 4;
    3884           0 :             goto EmitRel;
    3885             :           }
    3886             :         }
    3887             :         else {
    3888             :           // [RIP].
    3889           0 :           EMIT_32(static_cast<int32_t>(relOffset));
    3890             :         }
    3891             :       }
    3892             :     }
    3893             :   }
    3894           0 :   else if (!(rmInfo & kX86MemInfo_67H_X86)) {
    3895             :     // ESP|RSP can't be used as INDEX in pure SIB mode, however, VSIB mode
    3896             :     // allows XMM4|YMM4|ZMM4 (that's why the check is before the label).
    3897           0 :     if (ASMJIT_UNLIKELY(rxReg == X86Gp::kIdSp))
    3898           0 :       goto InvalidAddressIndex;
    3899             : 
    3900           0 : EmitModVSib:
    3901           0 :     rxReg &= 0x7;
    3902             : 
    3903             :     // ==========|> [BASE + INDEX + DISP8|DISP32].
    3904           0 :     if (rmInfo & kX86MemInfo_BaseGp) {
    3905           0 :       rbReg &= 0x7;
    3906             :       relOffset = rmRel->as<X86Mem>().getOffsetLo32();
    3907             : 
    3908             :       uint32_t mod = x86EncodeMod(0, opReg, 4);
    3909             :       uint32_t sib = x86EncodeSib(rmRel->as<X86Mem>().getShift(), rxReg, rbReg);
    3910             : 
    3911           0 :       if (relOffset == 0 && rbReg != X86Gp::kIdBp) {
    3912             :         // [BASE + INDEX << SHIFT].
    3913           0 :         EMIT_BYTE(mod);
    3914           0 :         EMIT_BYTE(sib);
    3915             :       }
    3916             :       else {
    3917           0 :         uint32_t cdShift = (opCode & X86Inst::kOpCode_CDSHL_Mask) >> X86Inst::kOpCode_CDSHL_Shift;
    3918           0 :         int32_t cdOffset = relOffset >> cdShift;
    3919             : 
    3920           0 :         if (Utils::isInt8(cdOffset) && relOffset == (cdOffset << cdShift)) {
    3921             :           // [BASE + INDEX << SHIFT + DISP8].
    3922           0 :           EMIT_BYTE(mod + 0x40); // <- MOD(1, opReg, 4).
    3923           0 :           EMIT_BYTE(sib);
    3924           0 :           EMIT_BYTE(cdOffset);
    3925             :         }
    3926             :         else {
    3927             :           // [BASE + INDEX << SHIFT + DISP32].
    3928           0 :           EMIT_BYTE(mod + 0x80); // <- MOD(2, opReg, 4).
    3929           0 :           EMIT_BYTE(sib);
    3930           0 :           EMIT_32(relOffset);
    3931             :         }
    3932             :       }
    3933             :     }
    3934             :     // ==========|> [INDEX + DISP32].
    3935           0 :     else if (!(rmInfo & (kX86MemInfo_BaseLabel | kX86MemInfo_BaseRip))) {
    3936             :       // [INDEX << SHIFT + DISP32].
    3937           0 :       EMIT_BYTE(x86EncodeMod(0, opReg, 4));
    3938           0 :       EMIT_BYTE(x86EncodeSib(rmRel->as<X86Mem>().getShift(), rxReg, 5));
    3939             : 
    3940             :       relOffset = rmRel->as<X86Mem>().getOffsetLo32();
    3941           0 :       EMIT_32(relOffset);
    3942             :     }
    3943             :     // ==========|> [LABEL|RIP + INDEX + DISP32].
    3944             :     else {
    3945           0 :       if (is32Bit()) {
    3946           0 :         EMIT_BYTE(x86EncodeMod(0, opReg, 4));
    3947           0 :         EMIT_BYTE(x86EncodeSib(rmRel->as<X86Mem>().getShift(), rxReg, 5));
    3948           0 :         goto EmitModSib_LabelRip_X86;
    3949             :       }
    3950             :       else {
    3951             :         // NOTE: This also handles VSIB+RIP, which is not allowed in 64-bit mode.
    3952           0 :         goto InvalidAddress;
    3953             :       }
    3954             :     }
    3955             :   }
    3956             :   else {
    3957             :     // 16-bit address mode (32-bit mode with 67 override prefix).
    3958           0 :     relOffset = (static_cast<int32_t>(rmRel->as<X86Mem>().getOffsetLo32()) << 16) >> 16;
    3959             : 
    3960             :     // NOTE: 16-bit addresses don't use SIB byte and their encoding differs. We
    3961             :     // use a table-based approach to calculate the proper MOD byte as it's easier.
    3962             :     // Also, not all BASE [+ INDEX] combinations are supported in 16-bit mode, so
    3963             :     // this may fail.
    3964             :     const uint32_t kBaseGpIdx = (kX86MemInfo_BaseGp | kX86MemInfo_Index);
    3965             : 
    3966           0 :     if (rmInfo & kBaseGpIdx) {
    3967             :       // ==========|> [BASE + INDEX + DISP16].
    3968             :       uint32_t mod;
    3969             : 
    3970           0 :       rbReg &= 0x7;
    3971           0 :       rxReg &= 0x7;
    3972             : 
    3973           0 :       if ((rmInfo & kBaseGpIdx) == kBaseGpIdx) {
    3974             :         uint32_t shf = rmRel->as<X86Mem>().getShift();
    3975           0 :         if (ASMJIT_UNLIKELY(shf != 0))
    3976           0 :           goto InvalidAddress;
    3977           0 :         mod = x86Mod16BaseIndexTable[(rbReg << 3) + rxReg];
    3978             :       }
    3979             :       else {
    3980           0 :         if (rmInfo & kX86MemInfo_Index)
    3981             :           rbReg = rxReg;
    3982           0 :         mod = x86Mod16BaseTable[rbReg];
    3983             :       }
    3984             : 
    3985           0 :       if (ASMJIT_UNLIKELY(mod == 0xFF))
    3986           0 :         goto InvalidAddress;
    3987             : 
    3988           0 :       mod += opReg << 3;
    3989           0 :       if (relOffset == 0 && mod != 0x06) {
    3990           0 :         EMIT_BYTE(mod);
    3991             :       }
    3992           0 :       else if (Utils::isInt8(relOffset)) {
    3993           0 :         EMIT_BYTE(mod + 0x40);
    3994           0 :         EMIT_BYTE(relOffset);
    3995             :       }
    3996             :       else {
    3997           0 :         EMIT_BYTE(mod + 0x80);
    3998           0 :         EMIT_16(relOffset);
    3999             :       }
    4000             :     }
    4001             :     else {
    4002             :       // Not supported in 16-bit addresses.
    4003           0 :       if (rmInfo & (kX86MemInfo_BaseRip | kX86MemInfo_BaseLabel))
    4004           0 :         goto InvalidAddress;
    4005             : 
    4006             :       // ==========|> [DISP16].
    4007           0 :       EMIT_BYTE(opReg | 0x06);
    4008           0 :       EMIT_16(relOffset);
    4009             :     }
    4010             :   }
    4011             : 
    4012      176113 :   if (imLen != 0)
    4013           0 :     goto EmitImm;
    4014             :   else
    4015      176113 :     goto EmitDone;
    4016             : 
    4017             :   // --------------------------------------------------------------------------
    4018             :   // [Emit - FPU]
    4019             :   // --------------------------------------------------------------------------
    4020             : 
    4021           0 : EmitFpuOp:
    4022             :   // Mandatory instruction prefix.
    4023           0 :   EMIT_PP(opCode);
    4024             : 
    4025             :   // FPU instructions consist of two opcodes.
    4026           0 :   EMIT_BYTE(opCode >> X86Inst::kOpCode_FPU_2B_Shift);
    4027           0 :   EMIT_BYTE(opCode);
    4028           0 :   goto EmitDone;
    4029             : 
    4030             :   // --------------------------------------------------------------------------
    4031             :   // [Emit - VEX / EVEX]
    4032             :   // --------------------------------------------------------------------------
    4033             : 
    4034             : EmitVexEvexOp:
    4035             :   {
    4036             :     // These don't use immediate.
    4037             :     ASMJIT_ASSERT(imLen == 0);
    4038             : 
    4039             :     // Only 'vzeroall' and 'vzeroupper' instructions use this encoding, they
    4040             :     // don't define 'W' to be '1' so we can just check the 'mmmmm' field. Both
    4041             :     // functions can encode by using VEV2 prefix so VEV3 is basically only used
    4042             :     // when forced from outside.
    4043             :     ASMJIT_ASSERT((opCode & X86Inst::kOpCode_W) == 0);
    4044             : 
    4045           0 :     uint32_t x = ((opCode & X86Inst::kOpCode_MM_Mask   ) >> (X86Inst::kOpCode_MM_Shift     )) |
    4046           0 :                  ((opCode & X86Inst::kOpCode_LL_Mask   ) >> (X86Inst::kOpCode_LL_Shift - 10)) |
    4047           0 :                  ((opCode & X86Inst::kOpCode_PP_VEXMask) >> (X86Inst::kOpCode_PP_Shift -  8)) |
    4048           0 :                  ((options & X86Inst::kOptionVex3      ) >> (X86Inst::kOpCode_MM_Shift     )) ;
    4049           0 :     if (x & 0x04U) {
    4050           0 :       x  = (x & (0x4 ^ 0xFFFF)) << 8;                    // [00000000|00000Lpp|0000m0mm|00000000].
    4051           0 :       x ^= (kX86ByteVex3) |                              // [........|00000Lpp|0000m0mm|__VEX3__].
    4052             :            (0x07U  << 13) |                              // [........|00000Lpp|1110m0mm|__VEX3__].
    4053           0 :            (0x0FU  << 19) |                              // [........|01111Lpp|1110m0mm|__VEX3__].
    4054           0 :            (opCode << 24) ;                              // [_OPCODE_|01111Lpp|1110m0mm|__VEX3__].
    4055             : 
    4056           0 :       EMIT_32(x);
    4057           0 :       goto EmitDone;
    4058             :     }
    4059             :     else {
    4060           0 :       x = ((x >> 8) ^ x) ^ 0xF9;
    4061           0 :       EMIT_BYTE(kX86ByteVex2);
    4062           0 :       EMIT_BYTE(x);
    4063           0 :       EMIT_BYTE(opCode);
    4064           0 :       goto EmitDone;
    4065             :     }
    4066             :   }
    4067             : 
    4068           0 : EmitVexEvexR:
    4069             :   {
    4070             :     // VEX instructions use only 0-1 BYTE immediate.
    4071             :     ASMJIT_ASSERT(imLen <= 1);
    4072             : 
    4073             :     // Construct `x` - a complete EVEX|VEX prefix.
    4074           0 :     uint32_t x = ((opReg << 4) & 0xF980U) |              // [........|........|Vvvvv..R|R.......].
    4075           0 :                  ((rbReg << 2) & 0x0060U) |              // [........|........|........|.BB.....].
    4076             :                  (x86ExtractLLMM(opCode, options)) |     // [........|.LL.....|Vvvvv..R|RBBmmmmm].
    4077           0 :                  (_extraReg.getId() << 16);              // [........|.LL..aaa|Vvvvv..R|RBBmmmmm].
    4078           0 :     opReg &= 0x7;
    4079             : 
    4080             :     // Mark invalid VEX (force EVEX) case:               // [@.......|.LL..aaa|Vvvvv..R|RBBmmmmm].
    4081           0 :     x |= (~commonData->getFlags() & X86Inst::kFlagVex) << (31 - Utils::firstBitOfT<X86Inst::kFlagVex>());
    4082             : 
    4083             :     // Handle AVX512 options by a single branch.
    4084             :     const uint32_t kAvx512Options = X86Inst::kOptionZMask   |
    4085             :                                     X86Inst::kOption1ToX    |
    4086             :                                     X86Inst::kOptionSAE     |
    4087             :                                     X86Inst::kOptionER      ;
    4088           0 :     if (options & kAvx512Options) {
    4089             :       // Memory broadcast without a memory operand is invalid.
    4090           0 :       if (ASMJIT_UNLIKELY(options & X86Inst::kOption1ToX))
    4091           0 :         goto InvalidBroadcast;
    4092             : 
    4093             :       // TODO: {sae} and {er}
    4094           0 :       x |= options & X86Inst::kOptionZMask;              // [@.......|zLL..aaa|Vvvvv..R|RBBmmmmm].
    4095             :     }
    4096             : 
    4097             :     // Check if EVEX is required by checking bits in `x` :  [@.......|xx...xxx|x......x|.x.x....].
    4098           0 :     if (x & 0x80C78150U) {
    4099           0 :       uint32_t y = ((x << 4) & 0x00080000U) |            // [@.......|....V...|........|........].
    4100           0 :                    ((x >> 4) & 0x00000010U) ;            // [@.......|....V...|........|...R....].
    4101           0 :       x  = (x & 0x00FF78E3U) | y;                        // [........|zLL.Vaaa|0vvvv000|RBBR00mm].
    4102           0 :       x  = (x << 8) |                                    // [zLL.Vaaa|0vvvv000|RBBR00mm|00000000].
    4103           0 :            ((opCode >> kSHR_W_PP) & 0x00830000U) |       // [zLL.Vaaa|Wvvvv0pp|RBBR00mm|00000000].
    4104           0 :            ((opCode >> kSHR_W_EW) & 0x00800000U) ;       // [zLL.Vaaa|Wvvvv0pp|RBBR00mm|00000000] (added EVEX.W).
    4105             :                                                          //      _     ____    ____
    4106           0 :       x ^= 0x087CF000U | kX86ByteEvex;                   // [zLL.Vaaa|Wvvvv1pp|RBBR00mm|01100010].
    4107             : 
    4108             :       EMIT_32(x);
    4109           0 :       EMIT_BYTE(opCode);
    4110             : 
    4111           0 :       rbReg &= 0x7;
    4112           0 :       EMIT_BYTE(x86EncodeMod(3, opReg, rbReg));
    4113             : 
    4114           0 :       if (imLen == 0) goto EmitDone;
    4115           0 :       EMIT_BYTE(imVal & 0xFF);
    4116           0 :       goto EmitDone;
    4117             :     }
    4118             : 
    4119             :     // Not EVEX, prepare `x` for VEX2 or VEX3:          x = [........|00L00000|0vvvv000|R0B0mmmm].
    4120           0 :     x |= ((opCode >> (kSHR_W_PP + 8)) & 0x8300U) |       // [00000000|00L00000|Wvvvv0pp|R0B0mmmm].
    4121           0 :          ((x      >> 11             ) & 0x0400U) ;       // [00000000|00L00000|WvvvvLpp|R0B0mmmm].
    4122             : 
    4123             :     // Check if VEX3 is required / forced:                  [........|........|x.......|..x..x..].
    4124           0 :     if (x & 0x0008024U) {
    4125           0 :       uint32_t xorMsk = x86VEXPrefix[x & 0xF] | (opCode << 24);
    4126             : 
    4127             :       // Clear 'FORCE-VEX3' bit and all high bits.
    4128           0 :       x  = (x & (0x4 ^ 0xFFFF)) << 8;                    // [00000000|WvvvvLpp|R0B0m0mm|00000000].
    4129             :                                                          //            ____    _ _
    4130           0 :       x ^= xorMsk;                                       // [_OPCODE_|WvvvvLpp|R1Bmmmmm|VEX3|XOP].
    4131             :       EMIT_32(x);
    4132             : 
    4133           0 :       rbReg &= 0x7;
    4134           0 :       EMIT_BYTE(x86EncodeMod(3, opReg, rbReg));
    4135             : 
    4136           0 :       if (imLen == 0) goto EmitDone;
    4137           0 :       EMIT_BYTE(imVal & 0xFF);
    4138           0 :       goto EmitDone;
    4139             :     }
    4140             :     else {
    4141             :       // 'mmmmm' must be '00001'.
    4142             :       ASMJIT_ASSERT((x & 0x1F) == 0x01);
    4143             : 
    4144           0 :       x = ((x >> 8) ^ x) ^ 0xF9;
    4145           0 :       EMIT_BYTE(kX86ByteVex2);
    4146           0 :       EMIT_BYTE(x);
    4147           0 :       EMIT_BYTE(opCode);
    4148             : 
    4149           0 :       rbReg &= 0x7;
    4150           0 :       EMIT_BYTE(x86EncodeMod(3, opReg, rbReg));
    4151             : 
    4152           0 :       if (imLen == 0) goto EmitDone;
    4153           0 :       EMIT_BYTE(imVal & 0xFF);
    4154           0 :       goto EmitDone;
    4155             :     }
    4156             :   }
    4157             : 
    4158           0 : EmitVexEvexM:
    4159             :   ASMJIT_ASSERT(rmRel != nullptr);
    4160             :   ASMJIT_ASSERT(rmRel->getOp() == Operand::kOpMem);
    4161           0 :   rmInfo = x86MemInfo[rmRel->as<X86Mem>().getBaseIndexType()];
    4162             : 
    4163             :   // Segment-override prefix.
    4164           0 :   if (rmRel->as<X86Mem>().hasSegment())
    4165           0 :     EMIT_BYTE(x86SegmentPrefix[rmRel->as<X86Mem>().getSegmentId()]);
    4166             : 
    4167             :   // Address-override prefix.
    4168           0 :   if (rmInfo & _getAddressOverrideMask())
    4169           0 :     EMIT_BYTE(0x67);
    4170             : 
    4171           0 :   rbReg = rmRel->as<X86Mem>().hasBaseReg()  ? rmRel->as<X86Mem>().getBaseId()  : uint32_t(0);
    4172           0 :   rxReg = rmRel->as<X86Mem>().hasIndexReg() ? rmRel->as<X86Mem>().getIndexId() : uint32_t(0);
    4173             : 
    4174             :   {
    4175             :     // VEX instructions use only 0-1 BYTE immediate.
    4176             :     ASMJIT_ASSERT(imLen <= 1);
    4177             : 
    4178             :     // Construct `x` - a complete EVEX|VEX prefix.
    4179           0 :     uint32_t x = ((opReg << 4 ) & 0x0000F980U) |         // [........|........|Vvvvv..R|R.......].
    4180           0 :                  ((rxReg << 3 ) & 0x00000040U) |         // [........|........|........|.X......].
    4181           0 :                  ((rxReg << 15) & 0x00080000U) |         // [........|....X...|........|........].
    4182           0 :                  ((rbReg << 2 ) & 0x00000020U) |         // [........|........|........|..B.....].
    4183             :                  (x86ExtractLLMM(opCode, options)) |     // [........|.LL.X...|Vvvvv..R|RXBmmmmm].
    4184           0 :                  (_extraReg.getId() << 16)         ;     // [........|.LL.Xaaa|Vvvvv..R|RXBmmmmm].
    4185           0 :     opReg &= 0x07U;
    4186             : 
    4187             :     // Mark invalid VEX (force EVEX) case:               // [@.......|.LL.Xaaa|Vvvvv..R|RXBmmmmm].
    4188           0 :     x |= (~commonData->getFlags() & X86Inst::kFlagVex) << (31 - Utils::firstBitOfT<X86Inst::kFlagVex>());
    4189             : 
    4190             :     // Handle AVX512 options by a single branch.
    4191             :     const uint32_t kAvx512Options = X86Inst::kOption1ToX    |
    4192             :                                     X86Inst::kOptionZMask   |
    4193             :                                     X86Inst::kOptionSAE     |
    4194             :                                     X86Inst::kOptionER      ;
    4195           0 :     if (options & kAvx512Options) {
    4196             :       // {er} and {sae} are both invalid if memory operand is used.
    4197           0 :       if (ASMJIT_UNLIKELY(options & (X86Inst::kOptionSAE | X86Inst::kOptionER)))
    4198           0 :         goto InvalidEROrSAE;
    4199             : 
    4200           0 :       x |= options & (X86Inst::kOption1ToX |             // [@.......|.LLbXaaa|Vvvvv..R|RXBmmmmm].
    4201             :                       X86Inst::kOptionZMask);            // [@.......|zLLbXaaa|Vvvvv..R|RXBmmmmm].
    4202             :     }
    4203             : 
    4204             :     // Check if EVEX is required by checking bits in `x` :  [@.......|xx.xxxxx|x......x|...x....].
    4205           0 :     if (x & 0x80DF8110U) {
    4206           0 :       uint32_t y = ((x << 4) & 0x00080000U) |            // [@.......|....V...|........|........].
    4207           0 :                    ((x >> 4) & 0x00000010U) ;            // [@.......|....V...|........|...R....].
    4208           0 :       x  = (x & 0x00FF78E3U) | y;                        // [........|zLLbVaaa|0vvvv000|RXBR00mm].
    4209           0 :       x  = (x << 8) |                                    // [zLLbVaaa|0vvvv000|RBBR00mm|00000000].
    4210           0 :            ((opCode >> kSHR_W_PP) & 0x00830000U) |       // [zLLbVaaa|Wvvvv0pp|RBBR00mm|00000000].
    4211           0 :            ((opCode >> kSHR_W_EW) & 0x00800000U) ;       // [zLLbVaaa|Wvvvv0pp|RBBR00mm|00000000] (added EVEX.W).
    4212             :                                                          //      _     ____    ____
    4213           0 :       x ^= 0x087CF000U | kX86ByteEvex;                   // [zLLbVaaa|Wvvvv1pp|RBBR00mm|01100010].
    4214             : 
    4215             :       EMIT_32(x);
    4216           0 :       EMIT_BYTE(opCode);
    4217             : 
    4218           0 :       if (opCode & 0x10000000U) {
    4219             :         // Broadcast, change the compressed displacement scale to either x4 (SHL 2) or x8 (SHL 3)
    4220             :         // depending on instruction's W. If 'W' is 1 'SHL' must be 3, otherwise it must be 2.
    4221           0 :         opCode &=~static_cast<uint32_t>(X86Inst::kOpCode_CDSHL_Mask);
    4222           0 :         opCode |= ((x & 0x00800000U) ? 3 : 2) << X86Inst::kOpCode_CDSHL_Shift;
    4223             :       }
    4224             :       else {
    4225             :         // Add the compressed displacement 'SHF' to the opcode based on 'TTWLL'.
    4226           0 :         uint32_t TTWLL = ((opCode >> (X86Inst::kOpCode_CDTT_Shift - 3)) & 0x18) +
    4227           0 :                          ((opCode >> (X86Inst::kOpCode_W_Shift    - 2)) & 0x04) +
    4228           0 :                          ((x >> 29) & 0x3);
    4229           0 :         opCode += x86CDisp8SHL[TTWLL];
    4230             :       }
    4231             :     }
    4232             :     else {
    4233             :       // Not EVEX, prepare `x` for VEX2 or VEX3:        x = [........|00L00000|0vvvv000|RXB0mmmm].
    4234           0 :       x |= ((opCode >> (kSHR_W_PP + 8)) & 0x8300U) |     // [00000000|00L00000|Wvvvv0pp|RXB0mmmm].
    4235           0 :            ((x      >> 11             ) & 0x0400U) ;     // [00000000|00L00000|WvvvvLpp|RXB0mmmm].
    4236             : 
    4237             :       // Clear a possible CDisp specified by EVEX.
    4238           0 :       opCode &= ~X86Inst::kOpCode_CDSHL_Mask;
    4239             : 
    4240             :       // Check if VEX3 is required / forced:                [........|........|x.......|.xx..x..].
    4241           0 :       if (x & 0x0008064U) {
    4242           0 :         uint32_t xorMsk = x86VEXPrefix[x & 0xF] | (opCode << 24);
    4243             : 
    4244             :         // Clear 'FORCE-VEX3' bit and all high bits.
    4245           0 :         x  = (x & (0x4 ^ 0xFFFF)) << 8;                  // [00000000|WvvvvLpp|RXB0m0mm|00000000].
    4246             :                                                          //            ____    ___
    4247           0 :         x ^= xorMsk;                                     // [_OPCODE_|WvvvvLpp|RXBmmmmm|VEX3_XOP].
    4248           0 :         EMIT_32(x);
    4249             :       }
    4250             :       else {
    4251             :         // 'mmmmm' must be '00001'.
    4252             :         ASMJIT_ASSERT((x & 0x1F) == 0x01);
    4253             : 
    4254           0 :         x = ((x >> 8) ^ x) ^ 0xF9;
    4255           0 :         EMIT_BYTE(kX86ByteVex2);
    4256           0 :         EMIT_BYTE(x);
    4257           0 :         EMIT_BYTE(opCode);
    4258             :       }
    4259             :     }
    4260             :   }
    4261             : 
    4262             :   // MOD|SIB address.
    4263           0 :   if (!commonData->hasFlag(X86Inst::kFlagVsib))
    4264           0 :     goto EmitModSib;
    4265             : 
    4266             :   // MOD|VSIB address without INDEX is invalid.
    4267           0 :   if (rmInfo & kX86MemInfo_Index)
    4268           0 :     goto EmitModVSib;
    4269           0 :   goto InvalidInstruction;
    4270             : 
    4271             :   // --------------------------------------------------------------------------
    4272             :   // [Emit - Jmp/Jcc/Call]
    4273             :   // --------------------------------------------------------------------------
    4274             : 
    4275             :   // TODO: Should be adjusted after the support for multiple sections feature is added.
    4276           0 : EmitJmpCall:
    4277             :   {
    4278             :     // Emit REX prefix if asked for (64-bit only).
    4279             :     uint32_t rex = x86ExtractREX(opCode, options);
    4280           0 :     if (rex) {
    4281           0 :       if (options & X86Inst::_kOptionInvalidRex)
    4282           0 :         goto InvalidRexPrefix;
    4283           0 :       EMIT_BYTE(rex | kX86ByteRex);
    4284             :     }
    4285             : 
    4286           0 :     uint64_t ip = static_cast<uint64_t>((intptr_t)(cursor - _bufferData));
    4287             :     uint32_t rel32 = 0;
    4288             :     uint32_t opCode8 = commonData->getAltOpCode();
    4289             : 
    4290             :     uint32_t inst8Size  = 1 + 1; //          OPCODE + REL8 .
    4291             :     uint32_t inst32Size = 1 + 4; // [PREFIX] OPCODE + REL32.
    4292             : 
    4293             :     // Jcc instructions with 32-bit displacement use 0x0F prefix,
    4294             :     // other instructions don't. No other prefixes are used by X86.
    4295             :     ASMJIT_ASSERT((opCode8 & X86Inst::kOpCode_MM_Mask) == 0);
    4296             :     ASMJIT_ASSERT((opCode  & X86Inst::kOpCode_MM_Mask) == 0 ||
    4297             :                   (opCode  & X86Inst::kOpCode_MM_Mask) == X86Inst::kOpCode_MM_0F);
    4298             : 
    4299             :     // Only one of these should be used at the same time.
    4300           0 :     inst32Size += static_cast<uint32_t>(opReg != 0);
    4301           0 :     inst32Size += static_cast<uint32_t>((opCode & X86Inst::kOpCode_MM_Mask) == X86Inst::kOpCode_MM_0F);
    4302             : 
    4303           0 :     if (rmRel->isLabel()) {
    4304           0 :       label = _code->getLabelEntry(rmRel->as<Label>());
    4305           0 :       if (!label) goto InvalidLabel;
    4306             : 
    4307           0 :       if (label->isBound()) {
    4308             :         // Bound label.
    4309           0 :         rel32 = static_cast<uint32_t>((static_cast<uint64_t>(label->getOffset()) - ip - inst32Size) & 0xFFFFFFFFU);
    4310           0 :         goto EmitJmpCallRel;
    4311             :       }
    4312             :       else {
    4313             :         // Non-bound label.
    4314           0 :         if (opCode8 && (!opCode || (options & X86Inst::kOptionShortForm))) {
    4315           0 :           EMIT_BYTE(opCode8);
    4316             :           relOffset = -1;
    4317             :           relSize = 1;
    4318           0 :           goto EmitRel;
    4319             :         }
    4320             :         else {
    4321             :           // Refuse also 'short' prefix, if specified.
    4322           0 :           if (ASMJIT_UNLIKELY(!opCode || (options & X86Inst::kOptionShortForm) != 0))
    4323           0 :             goto InvalidDisplacement;
    4324             : 
    4325             :           // Emit [PREFIX] OPCODE [/X] <DISP32>.
    4326           0 :           if (opCode & X86Inst::kOpCode_MM_Mask)
    4327           0 :             EMIT_BYTE(0x0F);
    4328             : 
    4329           0 :           EMIT_BYTE(opCode);
    4330           0 :           if (opReg)
    4331           0 :             EMIT_BYTE(x86EncodeMod(3, opReg, 0));
    4332             : 
    4333             :           relOffset = -4;
    4334             :           relSize = 4;
    4335           0 :           goto EmitRel;
    4336             :         }
    4337             :       }
    4338             :     }
    4339             : 
    4340           0 :     if (rmRel->isImm()) {
    4341             :       uint64_t baseAddress = getCodeInfo().getBaseAddress();
    4342             :       uint64_t jumpAddress = rmRel->as<Imm>().getUInt64();
    4343             : 
    4344             :       // If the base-address is known calculate a relative displacement and
    4345             :       // check if it fits in 32 bits (which is always true in 32-bit mode).
    4346             :       // Emit relative displacement as it was a bound label if all checks ok.
    4347           0 :       if (baseAddress != Globals::kNoBaseAddress) {
    4348           0 :         uint64_t rel64 = jumpAddress - (ip + baseAddress) - inst32Size;
    4349           0 :         if (getArchType() == ArchInfo::kTypeX86 || Utils::isInt32(static_cast<int64_t>(rel64))) {
    4350           0 :           rel32 = static_cast<uint32_t>(rel64 & 0xFFFFFFFFU);
    4351           0 :           goto EmitJmpCallRel;
    4352             :         }
    4353             :         else {
    4354             :           // Relative displacement exceeds 32-bits - relocator can only
    4355             :           // insert trampoline for jmp/call, but not for jcc/jecxz.
    4356           0 :           if (ASMJIT_UNLIKELY(!x86IsJmpOrCall(instId)))
    4357           0 :             goto InvalidDisplacement;
    4358             :         }
    4359             :       }
    4360             : 
    4361           0 :       if (ASMJIT_UNLIKELY(_code->_relocations.willGrow(&_code->_baseHeap) != kErrorOk))
    4362           0 :         goto NoHeapMemory;
    4363             : 
    4364           0 :       err = _code->newRelocEntry(&re, RelocEntry::kTypeAbsToRel, 0);
    4365           0 :       if (ASMJIT_UNLIKELY(err)) goto Failed;
    4366             : 
    4367           0 :       re->_sourceSectionId = _section->getId();
    4368           0 :       re->_data = static_cast<int64_t>(jumpAddress);
    4369             : 
    4370           0 :       if (ASMJIT_LIKELY(opCode)) {
    4371             :         // 64-bit: Emit REX prefix so the instruction can be patched later.
    4372             :         // REX prefix does nothing if not patched, but allows to patch the
    4373             :         // instruction to use MOD/M and to point to a memory where the final
    4374             :         // 64-bit address is stored.
    4375           0 :         re->_size = 4;
    4376           0 :         re->_sourceOffset = ip + inst32Size - 4;
    4377             : 
    4378           0 :         if (getArchType() != ArchInfo::kTypeX86 && x86IsJmpOrCall(instId)) {
    4379           0 :           if (!rex) {
    4380           0 :             re->_sourceOffset++;
    4381           0 :             EMIT_BYTE(kX86ByteRex);
    4382             :           }
    4383             : 
    4384           0 :           re->_type = RelocEntry::kTypeTrampoline;
    4385           0 :           _code->_trampolinesSize += 8;
    4386             :         }
    4387             : 
    4388             :         // Emit [PREFIX] OPCODE [/X] DISP32.
    4389           0 :         if (opCode & X86Inst::kOpCode_MM_Mask)
    4390           0 :           EMIT_BYTE(0x0F);
    4391             : 
    4392           0 :         EMIT_BYTE(opCode);
    4393           0 :         if (opReg)
    4394           0 :           EMIT_BYTE(x86EncodeMod(3, opReg, 0));
    4395             : 
    4396           0 :         EMIT_32(0);
    4397             :       }
    4398             :       else {
    4399           0 :         re->_size = 1;
    4400           0 :         re->_sourceOffset = ip + inst8Size - 1;
    4401             : 
    4402             :         // Emit OPCODE + DISP8.
    4403           0 :         EMIT_BYTE(opCode8);
    4404           0 :         EMIT_BYTE(0);
    4405             :       }
    4406           0 :       goto EmitDone;
    4407             :     }
    4408             : 
    4409             :     // Not Label|Imm -> Invalid.
    4410           0 :     goto InvalidInstruction;
    4411             : 
    4412             :     // Emit jmp/call with relative displacement known at assembly-time. Decide
    4413             :     // between 8-bit and 32-bit displacement encoding. Some instructions only
    4414             :     // allow either 8-bit or 32-bit encoding, others allow both encodings.
    4415           0 : EmitJmpCallRel:
    4416           0 :     if (Utils::isInt8(static_cast<int32_t>(rel32 + inst32Size - inst8Size)) && opCode8 && !(options & X86Inst::kOptionLongForm)) {
    4417           0 :       options |= X86Inst::kOptionShortForm;
    4418           0 :       EMIT_BYTE(opCode8);
    4419           0 :       EMIT_BYTE(rel32 + inst32Size - inst8Size);
    4420           0 :       goto EmitDone;
    4421             :     }
    4422             :     else {
    4423           0 :       if (ASMJIT_UNLIKELY(!opCode || (options & X86Inst::kOptionShortForm) != 0))
    4424           0 :         goto InvalidDisplacement;
    4425             : 
    4426           0 :       options &= ~X86Inst::kOptionShortForm;
    4427           0 :       if (opCode & X86Inst::kOpCode_MM_Mask)
    4428           0 :         EMIT_BYTE(0x0F);
    4429             : 
    4430           0 :       EMIT_BYTE(opCode);
    4431           0 :       if (opReg)
    4432           0 :         EMIT_BYTE(x86EncodeMod(3, opReg, 0));
    4433             : 
    4434           0 :       EMIT_32(rel32);
    4435           0 :       goto EmitDone;
    4436             :     }
    4437             :   }
    4438             : 
    4439             :   // --------------------------------------------------------------------------
    4440             :   // [Emit - Relative]
    4441             :   // --------------------------------------------------------------------------
    4442             : 
    4443           0 : EmitRel:
    4444             :   {
    4445             :     ASMJIT_ASSERT(!label->isBound());
    4446             :     ASMJIT_ASSERT(relSize == 1 || relSize == 4);
    4447             : 
    4448             :     // Chain with label.
    4449           0 :     size_t offset = (size_t)(cursor - _bufferData);
    4450           0 :     LabelLink* link = _code->newLabelLink(label, _section->getId(), offset, relOffset);
    4451             : 
    4452           0 :     if (ASMJIT_UNLIKELY(!link))
    4453           0 :       goto NoHeapMemory;
    4454             : 
    4455           0 :     if (re)
    4456           0 :       link->relocId = re->getId();
    4457             : 
    4458             :     // Emit label size as dummy data.
    4459           0 :     if (relSize == 1)
    4460           0 :       EMIT_BYTE(0x01);
    4461             :     else // if (relSize == 4)
    4462           0 :       EMIT_32(0x04040404);
    4463             :   }
    4464             : 
    4465           0 :   if (imLen == 0)
    4466           0 :     goto EmitDone;
    4467             : 
    4468             :   // --------------------------------------------------------------------------
    4469             :   // [Emit - Immediate]
    4470             :   // --------------------------------------------------------------------------
    4471             : 
    4472           0 : EmitImm:
    4473             :   {
    4474             : #if ASMJIT_ARCH_64BIT
    4475      117992 :     uint32_t i = imLen;
    4476      117992 :     uint64_t imm = static_cast<uint64_t>(imVal);
    4477             : #else
    4478             :     uint32_t i = imLen;
    4479             :     uint32_t imm = static_cast<uint32_t>(imVal & 0xFFFFFFFFU);
    4480             : #endif
    4481             : 
    4482             :     // Many instructions just use a single byte immediate, so make it fast.
    4483      117992 :     EMIT_BYTE(imm & 0xFFU); if (--i == 0) goto EmitDone;
    4484      107330 :     imm >>= 8;
    4485      107330 :     EMIT_BYTE(imm & 0xFFU); if (--i == 0) goto EmitDone;
    4486      107330 :     imm >>= 8;
    4487      107330 :     EMIT_BYTE(imm & 0xFFU); if (--i == 0) goto EmitDone;
    4488      107330 :     imm >>= 8;
    4489      107330 :     EMIT_BYTE(imm & 0xFFU); if (--i == 0) goto EmitDone;
    4490             : 
    4491             :     // Can be 1-4 or 8 bytes, this handles the remaining high DWORD of an 8-byte immediate.
    4492             :     ASMJIT_ASSERT(i == 4);
    4493             : 
    4494             : #if ASMJIT_ARCH_64BIT
    4495      106298 :     imm >>= 8;
    4496      106298 :     EMIT_32(static_cast<uint32_t>(imm));
    4497             : #else
    4498             :     EMIT_32(static_cast<uint32_t>((static_cast<uint64_t>(imVal) >> 32) & 0xFFFFFFFFU));
    4499             : #endif
    4500             :   }
    4501             : 
    4502             :   // --------------------------------------------------------------------------
    4503             :   // [Done]
    4504             :   // --------------------------------------------------------------------------
    4505             : 
    4506      593300 : EmitDone:
    4507             : #if !defined(ASMJIT_DISABLE_LOGGING)
    4508             :   // Logging is a performance hit anyway, so make it the unlikely case.
    4509      593300 :   if (ASMJIT_UNLIKELY(options & CodeEmitter::kOptionLoggingEnabled))
    4510           0 :     _emitLog(instId, options, o0, o1, o2, o3, relSize, imLen, cursor);
    4511             : #endif // !ASMJIT_DISABLE_LOGGING
    4512             : 
    4513             :   resetOptions();
    4514             :   resetExtraReg();
    4515             :   resetInlineComment();
    4516             : 
    4517      593300 :   _bufferPtr = cursor;
    4518      593300 :   return kErrorOk;
    4519             : 
    4520             :   // --------------------------------------------------------------------------
    4521             :   // [Error Cases]
    4522             :   // --------------------------------------------------------------------------
    4523             : 
    4524             : #define ERROR_HANDLER(ERROR)                \
    4525             : ERROR:                                      \
    4526             :   err = DebugUtils::errored(kError##ERROR); \
    4527             :   goto Failed;
    4528             : 
    4529           0 : ERROR_HANDLER(NoHeapMemory)
    4530           0 : ERROR_HANDLER(InvalidArgument)
    4531           0 : ERROR_HANDLER(InvalidLabel)
    4532           0 : ERROR_HANDLER(InvalidInstruction)
    4533           0 : ERROR_HANDLER(InvalidLockPrefix)
    4534           0 : ERROR_HANDLER(InvalidXAcquirePrefix)
    4535           0 : ERROR_HANDLER(InvalidXReleasePrefix)
    4536           0 : ERROR_HANDLER(InvalidRepPrefix)
    4537           0 : ERROR_HANDLER(InvalidRexPrefix)
    4538           0 : ERROR_HANDLER(InvalidBroadcast)
    4539           0 : ERROR_HANDLER(InvalidEROrSAE)
    4540           0 : ERROR_HANDLER(InvalidAddress)
    4541           0 : ERROR_HANDLER(InvalidAddressIndex)
    4542           0 : ERROR_HANDLER(InvalidAddress64Bit)
    4543           0 : ERROR_HANDLER(InvalidDisplacement)
    4544           0 : ERROR_HANDLER(InvalidSegment)
    4545           0 : ERROR_HANDLER(InvalidImmediate)
    4546           0 : ERROR_HANDLER(OperandSizeMismatch)
    4547           0 : ERROR_HANDLER(AmbiguousOperandSize)
    4548           0 : ERROR_HANDLER(NotConsecutiveRegs)
    4549             : 
    4550           0 : Failed:
    4551           0 :   return _emitFailed(err, instId, options, o0, o1, o2, o3);
    4552             : }
    4553             : 
    4554             : // ============================================================================
    4555             : // [asmjit::X86Assembler - Align]
    4556             : // ============================================================================
    4557             : 
    4558           0 : Error X86Assembler::align(uint32_t mode, uint32_t alignment) {
    4559             : #if !defined(ASMJIT_DISABLE_LOGGING)
    4560           0 :   if (_globalOptions & kOptionLoggingEnabled)
    4561           0 :     _code->_logger->logf("%s.align %u\n", _code->_logger->getIndentation(), alignment);
    4562             : #endif // !ASMJIT_DISABLE_LOGGING
    4563             : 
    4564           0 :   if (mode >= kAlignCount)
    4565           0 :     return setLastError(DebugUtils::errored(kErrorInvalidArgument));
    4566             : 
    4567           0 :   if (alignment <= 1)
    4568             :     return kErrorOk;
    4569             : 
    4570           0 :   if (!Utils::isPowerOf2(alignment) || alignment > Globals::kMaxAlignment)
    4571           0 :     return setLastError(DebugUtils::errored(kErrorInvalidArgument));
    4572             : 
    4573           0 :   uint32_t i = static_cast<uint32_t>(Utils::alignDiff<size_t>(getOffset(), alignment));
    4574           0 :   if (i == 0)
    4575             :     return kErrorOk;
    4576             : 
    4577           0 :   if (getRemainingSpace() < i) {
    4578           0 :     Error err = _code->growBuffer(&_section->_buffer, i);
    4579           0 :     if (ASMJIT_UNLIKELY(err)) return setLastError(err);
    4580             :   }
    4581             : 
    4582           0 :   uint8_t* cursor = _bufferPtr;
    4583             :   uint8_t pattern = 0x00;
    4584             : 
    4585           0 :   switch (mode) {
    4586           0 :     case kAlignCode: {
    4587           0 :       if (_globalHints & kHintOptimizedAlign) {
    4588             :         // Intel 64 and IA-32 Architectures Software Developer's Manual - Volume 2B (NOP).
    4589             :         enum { kMaxNopSize = 9 };
    4590             : 
    4591             :         static const uint8_t nopData[kMaxNopSize][kMaxNopSize] = {
    4592             :           { 0x90 },
    4593             :           { 0x66, 0x90 },
    4594             :           { 0x0F, 0x1F, 0x00 },
    4595             :           { 0x0F, 0x1F, 0x40, 0x00 },
    4596             :           { 0x0F, 0x1F, 0x44, 0x00, 0x00 },
    4597             :           { 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00 },
    4598             :           { 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00 },
    4599             :           { 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 },
    4600             :           { 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }
    4601             :         };
    4602             : 
    4603             :         do {
    4604           0 :           uint32_t n = std::min<uint32_t>(i, kMaxNopSize);
    4605           0 :           const uint8_t* src = nopData[n - 1];
    4606             : 
    4607           0 :           i -= n;
    4608             :           do {
    4609           0 :             EMIT_BYTE(*src++);
    4610           0 :           } while (--n);
    4611           0 :         } while (i);
    4612             :       }
    4613             : 
    4614             :       pattern = 0x90;
    4615             :       break;
    4616             :     }
    4617             : 
    4618           0 :     case kAlignData:
    4619             :       pattern = 0xCC;
    4620           0 :       break;
    4621             : 
    4622             :     case kAlignZero:
    4623             :       // Pattern already set to zero.
    4624             :       break;
    4625             :   }
    4626             : 
    4627           0 :   while (i) {
    4628           0 :     EMIT_BYTE(pattern);
    4629           0 :     i--;
    4630             :   }
    4631             : 
    4632           0 :   _bufferPtr = cursor;
    4633           0 :   return kErrorOk;
    4634             : }
    4635             : 
    4636             : } // asmjit namespace
    4637             : } // namespace PLMD
    4638             : 
    4639             : // [Api-End]
    4640             : #include "./asmjit_apiend.h"
    4641             : 
    4642             : // [Guard]
    4643             : #endif // ASMJIT_BUILD_X86
    4644             : #pragma GCC diagnostic pop
    4645             : #endif // __PLUMED_HAS_ASMJIT

Generated by: LCOV version 1.16