duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

Decoder.c (184418B)


      1 /***************************************************************************************************
      2 
      3   Zyan Disassembler Library (Zydis)
      4 
      5   Original Author : Florian Bernd
      6 
      7  * Permission is hereby granted, free of charge, to any person obtaining a copy
      8  * of this software and associated documentation files (the "Software"), to deal
      9  * in the Software without restriction, including without limitation the rights
     10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11  * copies of the Software, and to permit persons to whom the Software is
     12  * furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included in all
     15  * copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24 
     25 ***************************************************************************************************/
     26 
     27 // ReSharper disable CppClangTidyClangDiagnosticImplicitFallthrough
     28 // ReSharper disable CppClangTidyClangDiagnosticSwitchEnum
     29 // ReSharper disable CppClangTidyClangDiagnosticCoveredSwitchDefault
     30 
     31 // Temporarily disabled due to a LLVM issue:
     32 // ReSharper disable CppClangTidyBugproneNarrowingConversions
     33 
     34 #include <Zycore/LibC.h>
     35 #include <Zydis/Decoder.h>
     36 #include <Zydis/Status.h>
     37 #include <Zydis/Internal/DecoderData.h>
     38 #include <Zydis/Internal/SharedData.h>
     39 
     40 /* ============================================================================================== */
     41 /* Internal enums and types                                                                       */
     42 /* ============================================================================================== */
     43 
     44 /* ---------------------------------------------------------------------------------------------- */
     45 /* Decoder context                                                                                */
     46 /* ---------------------------------------------------------------------------------------------- */
     47 
     48 /**
     49  * Defines the `ZydisDecoderState` struct.
     50  */
     51 typedef struct ZydisDecoderState_
     52 {
     53     /**
     54      * A pointer to the `ZydisDecoder` instance.
     55      */
     56     const ZydisDecoder* decoder;
     57     /**
     58      * A pointer to the `ZydisDecoderContext` struct.
     59      */
     60     ZydisDecoderContext* context;
     61     /**
     62      * The input buffer.
     63      */
     64     const ZyanU8* buffer;
     65     /**
     66      * The input buffer length.
     67      */
     68     ZyanUSize buffer_len;
     69     /**
     70      * Prefix information.
     71      */
     72     struct
     73     {
     74         /**
     75          * Signals, if the instruction has a `LOCK` prefix (`F0`).
     76          *
     77          * This prefix originally belongs to group 1, but separating it from the other ones makes
     78          * parsing easier for us later.
     79          */
     80         ZyanBool has_lock;
     81         /**
     82          * The effective prefix of group 1 (either `F2` or `F3`).
     83          */
     84         ZyanU8 group1;
     85         /**
     86          * The effective prefix of group 2 (`2E`, `36`, `3E`, `26`, `64` or `65`).
     87          */
     88         ZyanU8 group2;
     89         /**
     90          * The effective segment prefix.
     91          */
     92         ZyanU8 effective_segment;
     93         /**
     94          * The prefix that should be treated as the mandatory-prefix, if the
     95          * current instruction needs one.
     96          *
     97          * The last `F3`/`F2` prefix has precedence over previous ones and
     98          * `F3`/`F2` in general have precedence over `66`.
     99          */
    100         ZyanU8 mandatory_candidate;
    101         /**
    102          * The offset of the effective `LOCK` prefix.
    103          */
    104         ZyanU8 offset_lock;
    105         /**
    106          * The offset of the effective prefix in group 1.
    107          */
    108         ZyanU8 offset_group1;
    109         /**
    110          * The offset of the effective prefix in group 2.
    111          */
    112         ZyanU8 offset_group2;
    113         /**
    114          * The offset of the operand-size override prefix (`66`).
    115          *
    116          * This is the only prefix in group 3.
    117          */
    118         ZyanU8 offset_osz_override;
    119         /**
    120          * The offset of the address-size override prefix (`67`).
    121          *
    122          * This is the only prefix in group 4.
    123          */
    124         ZyanU8 offset_asz_override;
    125         /**
    126          * The offset of the effective segment prefix.
    127          */
    128         ZyanU8 offset_segment;
    129         /**
    130          * The offset of the mandatory-candidate prefix.
    131          */
    132         ZyanU8 offset_mandatory;
    133         /**
    134          * The offset of a possible `CET` `no-lock` prefix.
    135          */
    136         ZyanI8 offset_notrack;
    137     } prefixes;
    138 } ZydisDecoderState;
    139 
    140 /* ---------------------------------------------------------------------------------------------- */
    141 /* Register encoding                                                                              */
    142 /* ---------------------------------------------------------------------------------------------- */
    143 
    144 /**
    145  * Defines the `ZydisRegisterEncoding` enum.
    146  */
    147 typedef enum ZydisRegisterEncoding_
    148 {
    149     ZYDIS_REG_ENCODING_INVALID,
    150     /**
    151      * The register-id is encoded as part of the opcode (bits [3..0]).
    152      *
    153      * Possible extension by:
    154      * - `REX.B`
    155      */
    156     ZYDIS_REG_ENCODING_OPCODE,
    157     /**
    158      * The register-id is encoded in `modrm.reg`.
    159      *
    160      * Possible extension by:
    161      * - `.R`
    162      * - `.R'` (vector only, EVEX/MVEX)
    163      */
    164     ZYDIS_REG_ENCODING_REG,
    165     /**
    166      * The register-id is encoded in `.vvvv`.
    167      *
    168      * Possible extension by:
    169      * - `.v'` (vector only, EVEX/MVEX).
    170      */
    171     ZYDIS_REG_ENCODING_NDSNDD,
    172     /**
    173      * The register-id is encoded in `modrm.rm`.
    174      *
    175      * Possible extension by:
    176      * - `.B`
    177      * - `.X` (vector only, EVEX/MVEX)`
    178      */
    179     ZYDIS_REG_ENCODING_RM,
    180     /**
    181      * The register-id is encoded in `modrm.rm` or `sib.base` (if `SIB` is present).
    182      *
    183      * Possible extension by:
    184      * - `.B`
    185      */
    186     ZYDIS_REG_ENCODING_BASE,
    187     /**
    188      * The register-id is encoded in `sib.index`.
    189      *
    190      * Possible extension by:
    191      * - `.X`
    192      */
    193     ZYDIS_REG_ENCODING_INDEX,
    194     /**
    195      * The register-id is encoded in `sib.index`.
    196      *
    197      * Possible extension by:
    198      * - `.X`
    199      * - `.V'` (vector only, EVEX/MVEX)
    200      */
    201     ZYDIS_REG_ENCODING_VIDX,
    202     /**
    203      * The register-id is encoded in an additional 8-bit immediate value.
    204      *
    205      * Bits [7:4] in 64-bit mode with possible extension by bit [3] (vector only), bits [7:5] for
    206      * all other modes.
    207      */
    208     ZYDIS_REG_ENCODING_IS4,
    209     /**
    210      * The register-id is encoded in `EVEX.aaa/MVEX.kkk`.
    211      */
    212     ZYDIS_REG_ENCODING_MASK,
    213 
    214     /**
    215      * Maximum value of this enum.
    216      */
    217     ZYDIS_REG_ENCODING_MAX_VALUE = ZYDIS_REG_ENCODING_MASK,
    218     /**
    219      * The minimum number of bits required to represent all values of this enum.
    220      */
    221     ZYDIS_REG_ENCODING_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REG_ENCODING_MAX_VALUE)
    222 } ZydisRegisterEncoding;
    223 
    224 /* ---------------------------------------------------------------------------------------------- */
    225 
    226 /* ============================================================================================== */
    227 /* Internal functions                                                                             */
    228 /* ============================================================================================== */
    229 
    230 /* ---------------------------------------------------------------------------------------------- */
    231 /* Input helper functions                                                                         */
    232 /* ---------------------------------------------------------------------------------------------- */
    233 
    234 /**
    235  * Reads one byte from the current read-position of the input data-source.
    236  *
    237  * @param   state       A pointer to the `ZydisDecoderState` struct.
    238  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
    239  * @param   value       A pointer to the memory that receives the byte from the input data-source.
    240  *
    241  * @return  A zyan status code.
    242  *
    243  * This function may fail, if the `ZYDIS_MAX_INSTRUCTION_LENGTH` limit got exceeded, or no more
    244  * data is available.
    245  */
    246 static ZyanStatus ZydisInputPeek(ZydisDecoderState* state,
    247     ZydisDecodedInstruction* instruction, ZyanU8* value)
    248 {
    249     ZYAN_ASSERT(state);
    250     ZYAN_ASSERT(instruction);
    251     ZYAN_ASSERT(value);
    252 
    253     if (instruction->length >= ZYDIS_MAX_INSTRUCTION_LENGTH)
    254     {
    255         return ZYDIS_STATUS_INSTRUCTION_TOO_LONG;
    256     }
    257 
    258     if (state->buffer_len > 0)
    259     {
    260         *value = state->buffer[0];
    261         return ZYAN_STATUS_SUCCESS;
    262     }
    263 
    264     return ZYDIS_STATUS_NO_MORE_DATA;
    265 }
    266 
    267 /**
    268  * Increases the read-position of the input data-source by one byte.
    269  *
    270  * @param   state       A pointer to the `ZydisDecoderState` instance
    271  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
    272  *
    273  * This function is supposed to get called ONLY after a successful call of `ZydisInputPeek`.
    274  *
    275  * This function increases the `length` field of the `ZydisDecodedInstruction` struct by one.
    276  */
    277 static void ZydisInputSkip(ZydisDecoderState* state, ZydisDecodedInstruction* instruction)
    278 {
    279     ZYAN_ASSERT(state);
    280     ZYAN_ASSERT(instruction);
    281     ZYAN_ASSERT(instruction->length < ZYDIS_MAX_INSTRUCTION_LENGTH);
    282 
    283     ++instruction->length;
    284     ++state->buffer;
    285     --state->buffer_len;
    286 }
    287 
    288 /**
    289  * Reads one byte from the current read-position of the input data-source and increases
    290  *          the read-position by one byte afterwards.
    291  *
    292  * @param   state       A pointer to the `ZydisDecoderState` struct.
    293  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
    294  * @param   value       A pointer to the memory that receives the byte from the input data-source.
    295  *
    296  * @return  A zyan status code.
    297  *
    298  * This function acts like a subsequent call of `ZydisInputPeek` and `ZydisInputSkip`.
    299  */
    300 static ZyanStatus ZydisInputNext(ZydisDecoderState* state,
    301     ZydisDecodedInstruction* instruction, ZyanU8* value)
    302 {
    303     ZYAN_ASSERT(state);
    304     ZYAN_ASSERT(instruction);
    305     ZYAN_ASSERT(value);
    306 
    307     if (instruction->length >= ZYDIS_MAX_INSTRUCTION_LENGTH)
    308     {
    309         return ZYDIS_STATUS_INSTRUCTION_TOO_LONG;
    310     }
    311 
    312     if (state->buffer_len > 0)
    313     {
    314         *value = state->buffer++[0];
    315         ++instruction->length;
    316         --state->buffer_len;
    317         return ZYAN_STATUS_SUCCESS;
    318     }
    319 
    320     return ZYDIS_STATUS_NO_MORE_DATA;
    321 }
    322 
    323 /**
    324  * Reads a variable amount of bytes from the current read-position of the input
    325  *          data-source and increases the read-position by specified amount of bytes afterwards.
    326  *
    327  * @param   state           A pointer to the `ZydisDecoderState` struct.
    328  * @param   instruction     A pointer to the `ZydisDecodedInstruction` struct.
    329  * @param   value           A pointer to the memory that receives the byte from the input
    330  *                          data-source.
    331  * @param   number_of_bytes The number of bytes to read from the input data-source.
    332  *
    333  * @return  A zyan status code.
    334  *
    335  * This function acts like a subsequent call of `ZydisInputPeek` and `ZydisInputSkip`.
    336  */
    337 static ZyanStatus ZydisInputNextBytes(ZydisDecoderState* state,
    338     ZydisDecodedInstruction* instruction, ZyanU8* value, ZyanU8 number_of_bytes)
    339 {
    340     ZYAN_ASSERT(state);
    341     ZYAN_ASSERT(instruction);
    342     ZYAN_ASSERT(value);
    343 
    344     if (instruction->length + number_of_bytes > ZYDIS_MAX_INSTRUCTION_LENGTH)
    345     {
    346         return ZYDIS_STATUS_INSTRUCTION_TOO_LONG;
    347     }
    348 
    349     if (state->buffer_len >= number_of_bytes)
    350     {
    351         instruction->length += number_of_bytes;
    352 
    353         ZYAN_MEMCPY(value, state->buffer, number_of_bytes);
    354         state->buffer += number_of_bytes;
    355         state->buffer_len -= number_of_bytes;
    356 
    357         return ZYAN_STATUS_SUCCESS;
    358     }
    359 
    360     return ZYDIS_STATUS_NO_MORE_DATA;
    361 }
    362 
    363 /* ---------------------------------------------------------------------------------------------- */
    364 /* Decode functions                                                                               */
    365 /* ---------------------------------------------------------------------------------------------- */
    366 
    367 /**
    368  * Decodes the `REX`-prefix.
    369  *
    370  * @param   context     A pointer to the `ZydisDecoderContext` struct.
    371  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
    372  * @param   data        The `REX` byte.
    373  */
    374 static void ZydisDecodeREX(ZydisDecoderContext* context, ZydisDecodedInstruction* instruction,
    375     ZyanU8 data)
    376 {
    377     ZYAN_ASSERT(instruction);
    378     ZYAN_ASSERT((data & 0xF0) == 0x40);
    379 
    380     instruction->attributes |= ZYDIS_ATTRIB_HAS_REX;
    381     instruction->raw.rex.W   = (data >> 3) & 0x01;
    382     instruction->raw.rex.R   = (data >> 2) & 0x01;
    383     instruction->raw.rex.X   = (data >> 1) & 0x01;
    384     instruction->raw.rex.B   = (data >> 0) & 0x01;
    385 
    386     // Update internal fields
    387     context->vector_unified.W = instruction->raw.rex.W;
    388     context->vector_unified.R = instruction->raw.rex.R;
    389     context->vector_unified.X = instruction->raw.rex.X;
    390     context->vector_unified.B = instruction->raw.rex.B;
    391 }
    392 
    393 /**
    394  * Decodes the `XOP`-prefix.
    395  *
    396  * @param   context     A pointer to the `ZydisDecoderContext` struct.
    397  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
    398  * @param   data        The `XOP` bytes.
    399  *
    400  * @return  A zyan status code.
    401  */
    402 static ZyanStatus ZydisDecodeXOP(ZydisDecoderContext* context,
    403     ZydisDecodedInstruction* instruction, const ZyanU8 data[3])
    404 {
    405     ZYAN_ASSERT(instruction);
    406     ZYAN_ASSERT(data[0] == 0x8F);
    407     ZYAN_ASSERT(((data[1] >> 0) & 0x1F) >= 8);
    408     ZYAN_ASSERT(instruction->raw.xop.offset == instruction->length - 3);
    409 
    410     if (instruction->machine_mode == ZYDIS_MACHINE_MODE_REAL_16)
    411     {
    412         // XOP is invalid in 16-bit real mode
    413         return ZYDIS_STATUS_DECODING_ERROR;
    414     }
    415 
    416     instruction->attributes |= ZYDIS_ATTRIB_HAS_XOP;
    417     instruction->raw.xop.R       = (data[1] >> 7) & 0x01;
    418     instruction->raw.xop.X       = (data[1] >> 6) & 0x01;
    419     instruction->raw.xop.B       = (data[1] >> 5) & 0x01;
    420     instruction->raw.xop.m_mmmm  = (data[1] >> 0) & 0x1F;
    421 
    422     if ((instruction->raw.xop.m_mmmm < 0x08) || (instruction->raw.xop.m_mmmm > 0x0A))
    423     {
    424         // Invalid according to the AMD documentation
    425         return ZYDIS_STATUS_INVALID_MAP;
    426     }
    427 
    428     instruction->raw.xop.W    = (data[2] >> 7) & 0x01;
    429     instruction->raw.xop.vvvv = (data[2] >> 3) & 0x0F;
    430     instruction->raw.xop.L    = (data[2] >> 2) & 0x01;
    431     instruction->raw.xop.pp   = (data[2] >> 0) & 0x03;
    432 
    433     // Update internal fields
    434     context->vector_unified.W    = instruction->raw.xop.W;
    435     context->vector_unified.R    = 0x01 & ~instruction->raw.xop.R;
    436     context->vector_unified.X    = 0x01 & ~instruction->raw.xop.X;
    437     context->vector_unified.B    = 0x01 & ~instruction->raw.xop.B;
    438     context->vector_unified.L    = instruction->raw.xop.L;
    439     context->vector_unified.LL   = instruction->raw.xop.L;
    440     context->vector_unified.vvvv = (0x0F & ~instruction->raw.xop.vvvv);
    441 
    442     return ZYAN_STATUS_SUCCESS;
    443 }
    444 
    445 /**
    446  * Decodes the `VEX`-prefix.
    447  *
    448  * @param   context     A pointer to the `ZydisDecoderContext` struct.
    449  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
    450  * @param   data        The `VEX` bytes.
    451  *
    452  * @return  A zyan status code.
    453  */
    454 static ZyanStatus ZydisDecodeVEX(ZydisDecoderContext* context,
    455     ZydisDecodedInstruction* instruction, const ZyanU8 data[3])
    456 {
    457     ZYAN_ASSERT(instruction);
    458     ZYAN_ASSERT((data[0] == 0xC4) || (data[0] == 0xC5));
    459 
    460     if (instruction->machine_mode == ZYDIS_MACHINE_MODE_REAL_16)
    461     {
    462         // VEX is invalid in 16-bit real mode
    463         return ZYDIS_STATUS_DECODING_ERROR;
    464     }
    465 
    466     instruction->attributes |= ZYDIS_ATTRIB_HAS_VEX;
    467     switch (data[0])
    468     {
    469     case 0xC4:
    470         ZYAN_ASSERT(instruction->raw.vex.offset == instruction->length - 3);
    471         instruction->raw.vex.size    = 3;
    472         instruction->raw.vex.R       = (data[1] >> 7) & 0x01;
    473         instruction->raw.vex.X       = (data[1] >> 6) & 0x01;
    474         instruction->raw.vex.B       = (data[1] >> 5) & 0x01;
    475         instruction->raw.vex.m_mmmm  = (data[1] >> 0) & 0x1F;
    476         instruction->raw.vex.W       = (data[2] >> 7) & 0x01;
    477         instruction->raw.vex.vvvv    = (data[2] >> 3) & 0x0F;
    478         instruction->raw.vex.L       = (data[2] >> 2) & 0x01;
    479         instruction->raw.vex.pp      = (data[2] >> 0) & 0x03;
    480         break;
    481     case 0xC5:
    482         ZYAN_ASSERT(instruction->raw.vex.offset == instruction->length - 2);
    483         instruction->raw.vex.size    = 2;
    484         instruction->raw.vex.R       = (data[1] >> 7) & 0x01;
    485         instruction->raw.vex.X       = 1;
    486         instruction->raw.vex.B       = 1;
    487         instruction->raw.vex.m_mmmm  = 1;
    488         instruction->raw.vex.W       = 0;
    489         instruction->raw.vex.vvvv    = (data[1] >> 3) & 0x0F;
    490         instruction->raw.vex.L       = (data[1] >> 2) & 0x01;
    491         instruction->raw.vex.pp      = (data[1] >> 0) & 0x03;
    492         break;
    493     default:
    494         ZYAN_UNREACHABLE;
    495     }
    496 
    497     // Map 0 is only valid for some KNC instructions
    498 #ifdef ZYDIS_DISABLE_KNC
    499     if ((instruction->raw.vex.m_mmmm == 0) || (instruction->raw.vex.m_mmmm > 0x03))
    500 #else
    501     if (instruction->raw.vex.m_mmmm > 0x03)
    502 #endif
    503     {
    504         // Invalid according to the intel documentation
    505         return ZYDIS_STATUS_INVALID_MAP;
    506     }
    507 
    508     // Update internal fields
    509     context->vector_unified.W    = instruction->raw.vex.W;
    510     context->vector_unified.R    = 0x01 & ~instruction->raw.vex.R;
    511     context->vector_unified.X    = 0x01 & ~instruction->raw.vex.X;
    512     context->vector_unified.B    = 0x01 & ~instruction->raw.vex.B;
    513     context->vector_unified.L    = instruction->raw.vex.L;
    514     context->vector_unified.LL   = instruction->raw.vex.L;
    515     context->vector_unified.vvvv = (0x0F & ~instruction->raw.vex.vvvv);
    516 
    517     return ZYAN_STATUS_SUCCESS;
    518 }
    519 
    520 #ifndef ZYDIS_DISABLE_AVX512
    521 /**
    522  * Decodes the `EVEX`-prefix.
    523  *
    524  * @param   context     A pointer to the `ZydisDecoderContext` struct.
    525  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
    526  * @param   data        The `EVEX` bytes.
    527  *
    528  * @return  A zyan status code.
    529  */
    530 static ZyanStatus ZydisDecodeEVEX(ZydisDecoderContext* context,
    531     ZydisDecodedInstruction* instruction, const ZyanU8 data[4])
    532 {
    533     ZYAN_ASSERT(instruction);
    534     ZYAN_ASSERT(data[0] == 0x62);
    535     ZYAN_ASSERT(instruction->raw.evex.offset == instruction->length - 4);
    536 
    537     if (instruction->machine_mode == ZYDIS_MACHINE_MODE_REAL_16)
    538     {
    539         // EVEX is invalid in 16-bit real mode
    540         return ZYDIS_STATUS_DECODING_ERROR;
    541     }
    542 
    543     instruction->attributes |= ZYDIS_ATTRIB_HAS_EVEX;
    544     instruction->raw.evex.R         = (data[1] >> 7) & 0x01;
    545     instruction->raw.evex.X         = (data[1] >> 6) & 0x01;
    546     instruction->raw.evex.B         = (data[1] >> 5) & 0x01;
    547     instruction->raw.evex.R2        = (data[1] >> 4) & 0x01;
    548 
    549     if (data[1] & 0x08)
    550     {
    551         // Invalid according to the intel documentation
    552         return ZYDIS_STATUS_MALFORMED_EVEX;
    553     }
    554 
    555     instruction->raw.evex.mmm       = (data[1] >> 0) & 0x07;
    556 
    557     if ((instruction->raw.evex.mmm == 0x00) ||
    558         (instruction->raw.evex.mmm == 0x04) ||
    559         (instruction->raw.evex.mmm == 0x07))
    560     {
    561         // Invalid according to the intel documentation
    562         return ZYDIS_STATUS_INVALID_MAP;
    563     }
    564 
    565     instruction->raw.evex.W         = (data[2] >> 7) & 0x01;
    566     instruction->raw.evex.vvvv      = (data[2] >> 3) & 0x0F;
    567 
    568     ZYAN_ASSERT(((data[2] >> 2) & 0x01) == 0x01);
    569 
    570     instruction->raw.evex.pp        = (data[2] >> 0) & 0x03;
    571     instruction->raw.evex.z         = (data[3] >> 7) & 0x01;
    572     instruction->raw.evex.L2        = (data[3] >> 6) & 0x01;
    573     instruction->raw.evex.L         = (data[3] >> 5) & 0x01;
    574     instruction->raw.evex.b         = (data[3] >> 4) & 0x01;
    575     instruction->raw.evex.V2        = (data[3] >> 3) & 0x01;
    576 
    577     if (!instruction->raw.evex.V2 &&
    578         (instruction->machine_mode != ZYDIS_MACHINE_MODE_LONG_64))
    579     {
    580         return ZYDIS_STATUS_MALFORMED_EVEX;
    581     }
    582 
    583     instruction->raw.evex.aaa       = (data[3] >> 0) & 0x07;
    584 
    585     if (instruction->raw.evex.z && !instruction->raw.evex.aaa)
    586     {
    587         return ZYDIS_STATUS_INVALID_MASK; // TODO: Dedicated status code
    588     }
    589 
    590     // Update internal fields
    591     context->vector_unified.W    = instruction->raw.evex.W;
    592     context->vector_unified.R    = 0x01 & ~instruction->raw.evex.R;
    593     context->vector_unified.X    = 0x01 & ~instruction->raw.evex.X;
    594     context->vector_unified.B    = 0x01 & ~instruction->raw.evex.B;
    595     context->vector_unified.LL   = (data[3] >> 5) & 0x03;
    596     context->vector_unified.R2   = 0x01 & ~instruction->raw.evex.R2;
    597     context->vector_unified.V2   = 0x01 & ~instruction->raw.evex.V2;
    598     context->vector_unified.vvvv = 0x0F & ~instruction->raw.evex.vvvv;
    599     context->vector_unified.mask = instruction->raw.evex.aaa;
    600 
    601     if (!instruction->raw.evex.V2 && (instruction->machine_mode != ZYDIS_MACHINE_MODE_LONG_64))
    602     {
    603         return ZYDIS_STATUS_MALFORMED_EVEX;
    604     }
    605     if (!instruction->raw.evex.b && (context->vector_unified.LL == 3))
    606     {
    607         // LL = 3 is only valid for instructions with embedded rounding control
    608         return ZYDIS_STATUS_MALFORMED_EVEX;
    609     }
    610 
    611     return ZYAN_STATUS_SUCCESS;
    612 }
    613 #endif
    614 
    615 #ifndef ZYDIS_DISABLE_KNC
    616 /**
    617  * Decodes the `MVEX`-prefix.
    618  *
    619  * @param   context     A pointer to the `ZydisDecoderContext` struct.
    620  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
    621  * @param   data        The `MVEX` bytes.
    622  *
    623  * @return  A zyan status code.
    624  */
    625 static ZyanStatus ZydisDecodeMVEX(ZydisDecoderContext* context,
    626     ZydisDecodedInstruction* instruction, const ZyanU8 data[4])
    627 {
    628     ZYAN_ASSERT(instruction);
    629     ZYAN_ASSERT(data[0] == 0x62);
    630     ZYAN_ASSERT(instruction->raw.mvex.offset == instruction->length - 4);
    631 
    632     if (instruction->machine_mode != ZYDIS_MACHINE_MODE_LONG_64)
    633     {
    634         // MVEX is only valid in 64-bit mode
    635         return ZYDIS_STATUS_DECODING_ERROR;
    636     }
    637 
    638     instruction->attributes |= ZYDIS_ATTRIB_HAS_MVEX;
    639     instruction->raw.mvex.R    = (data[1] >> 7) & 0x01;
    640     instruction->raw.mvex.X    = (data[1] >> 6) & 0x01;
    641     instruction->raw.mvex.B    = (data[1] >> 5) & 0x01;
    642     instruction->raw.mvex.R2   = (data[1] >> 4) & 0x01;
    643     instruction->raw.mvex.mmmm = (data[1] >> 0) & 0x0F;
    644 
    645     if (instruction->raw.mvex.mmmm > 0x03)
    646     {
    647         // Invalid according to the intel documentation
    648         return ZYDIS_STATUS_INVALID_MAP;
    649     }
    650 
    651     instruction->raw.mvex.W    = (data[2] >> 7) & 0x01;
    652     instruction->raw.mvex.vvvv = (data[2] >> 3) & 0x0F;
    653 
    654     ZYAN_ASSERT(((data[2] >> 2) & 0x01) == 0x00);
    655 
    656     instruction->raw.mvex.pp   = (data[2] >> 0) & 0x03;
    657     instruction->raw.mvex.E    = (data[3] >> 7) & 0x01;
    658     instruction->raw.mvex.SSS  = (data[3] >> 4) & 0x07;
    659     instruction->raw.mvex.V2   = (data[3] >> 3) & 0x01;
    660     instruction->raw.mvex.kkk  = (data[3] >> 0) & 0x07;
    661 
    662     // Update internal fields
    663     context->vector_unified.W    = instruction->raw.mvex.W;
    664     context->vector_unified.R    = 0x01 & ~instruction->raw.mvex.R;
    665     context->vector_unified.X    = 0x01 & ~instruction->raw.mvex.X;
    666     context->vector_unified.B    = 0x01 & ~instruction->raw.mvex.B;
    667     context->vector_unified.R2   = 0x01 & ~instruction->raw.mvex.R2;
    668     context->vector_unified.V2   = 0x01 & ~instruction->raw.mvex.V2;
    669     context->vector_unified.LL   = 2;
    670     context->vector_unified.vvvv = 0x0F & ~instruction->raw.mvex.vvvv;
    671     context->vector_unified.mask = instruction->raw.mvex.kkk;
    672 
    673     return ZYAN_STATUS_SUCCESS;
    674 }
    675 #endif
    676 
    677 /**
    678  * Decodes the `ModRM`-byte.
    679  *
    680  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
    681  * @param   data        The `ModRM` byte.
    682  */
    683 static void ZydisDecodeModRM(ZydisDecodedInstruction* instruction, ZyanU8 data)
    684 {
    685     ZYAN_ASSERT(instruction);
    686     ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_MODRM));
    687     ZYAN_ASSERT(instruction->raw.modrm.offset == instruction->length - 1);
    688 
    689     instruction->attributes   |= ZYDIS_ATTRIB_HAS_MODRM;
    690     instruction->raw.modrm.mod = (data >> 6) & 0x03;
    691     instruction->raw.modrm.reg = (data >> 3) & 0x07;
    692     instruction->raw.modrm.rm  = (data >> 0) & 0x07;
    693 }
    694 
    695 /**
    696  * Decodes the `SIB`-byte.
    697  *
    698  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct
    699  * @param   data        The `SIB` byte.
    700  */
    701 static void ZydisDecodeSIB(ZydisDecodedInstruction* instruction, ZyanU8 data)
    702 {
    703     ZYAN_ASSERT(instruction);
    704     ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MODRM);
    705     ZYAN_ASSERT(instruction->raw.modrm.rm == 4);
    706     ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_SIB));
    707     ZYAN_ASSERT(instruction->raw.sib.offset == instruction->length - 1);
    708 
    709     instruction->attributes    |= ZYDIS_ATTRIB_HAS_SIB;
    710     instruction->raw.sib.scale = (data >> 6) & 0x03;
    711     instruction->raw.sib.index = (data >> 3) & 0x07;
    712     instruction->raw.sib.base  = (data >> 0) & 0x07;
    713 }
    714 
    715 /* ---------------------------------------------------------------------------------------------- */
    716 
    717 /**
    718  * Reads a displacement value.
    719  *
    720  * @param   state       A pointer to the `ZydisDecoderState` struct.
    721  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
    722  * @param   size        The physical size of the displacement value.
    723  *
    724  * @return  A zyan status code.
    725  */
    726 static ZyanStatus ZydisReadDisplacement(ZydisDecoderState* state,
    727     ZydisDecodedInstruction* instruction, ZyanU8 size)
    728 {
    729     ZYAN_ASSERT(state);
    730     ZYAN_ASSERT(instruction);
    731     ZYAN_ASSERT(instruction->raw.disp.size == 0);
    732 
    733     instruction->raw.disp.size = size;
    734     instruction->raw.disp.offset = instruction->length;
    735 
    736     switch (size)
    737     {
    738     case 8:
    739     {
    740         ZyanU8 value;
    741         ZYAN_CHECK(ZydisInputNext(state, instruction, &value));
    742         instruction->raw.disp.value = *(ZyanI8*)&value;
    743         break;
    744     }
    745     case 16:
    746     {
    747         ZyanU16 value;
    748         ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 2));
    749         instruction->raw.disp.value = *(ZyanI16*)&value;
    750         break;
    751     }
    752     case 32:
    753     {
    754         ZyanU32 value;
    755         ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 4));
    756         instruction->raw.disp.value = *(ZyanI32*)&value;
    757         break;
    758     }
    759     case 64:
    760     {
    761         ZyanU64 value;
    762         ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 8));
    763         instruction->raw.disp.value = *(ZyanI64*)&value;
    764         break;
    765     }
    766     default:
    767         ZYAN_UNREACHABLE;
    768     }
    769 
    770     // TODO: Fix endianess on big-endian systems
    771 
    772     return ZYAN_STATUS_SUCCESS;
    773 }
    774 
    775 /**
    776  * Reads an immediate value.
    777  *
    778  * @param   state       A pointer to the `ZydisDecoderState` struct.
    779  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
    780  * @param   id          The immediate id (either `0` or `1`).
    781  * @param   size        The physical size of the immediate value.
    782  * @param   is_signed   Signals, if the immediate value is signed.
    783  * @param   is_relative Signals, if the immediate value is a relative offset.
    784  *
    785  * @return  A zyan status code.
    786  */
    787 static ZyanStatus ZydisReadImmediate(ZydisDecoderState* state,
    788     ZydisDecodedInstruction* instruction, ZyanU8 id, ZyanU8 size, ZyanBool is_signed,
    789     ZyanBool is_relative)
    790 {
    791     ZYAN_ASSERT(state);
    792     ZYAN_ASSERT(instruction);
    793     ZYAN_ASSERT((id == 0) || (id == 1));
    794     ZYAN_ASSERT(is_signed || !is_relative);
    795     ZYAN_ASSERT(instruction->raw.imm[id].size == 0);
    796 
    797     instruction->raw.imm[id].size = size;
    798     instruction->raw.imm[id].offset = instruction->length;
    799     instruction->raw.imm[id].is_signed = is_signed;
    800     instruction->raw.imm[id].is_relative = is_relative;
    801     switch (size)
    802     {
    803     case 8:
    804     {
    805         ZyanU8 value;
    806         ZYAN_CHECK(ZydisInputNext(state, instruction, &value));
    807         if (is_signed)
    808         {
    809             instruction->raw.imm[id].value.s = (ZyanI8)value;
    810         } else
    811         {
    812             instruction->raw.imm[id].value.u = value;
    813         }
    814         break;
    815     }
    816     case 16:
    817     {
    818         ZyanU16 value;
    819         ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 2));
    820         if (is_signed)
    821         {
    822             instruction->raw.imm[id].value.s = (ZyanI16)value;
    823         } else
    824         {
    825             instruction->raw.imm[id].value.u = value;
    826         }
    827         break;
    828     }
    829     case 32:
    830     {
    831         ZyanU32 value;
    832         ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 4));
    833         if (is_signed)
    834         {
    835             instruction->raw.imm[id].value.s = (ZyanI32)value;
    836         } else
    837         {
    838             instruction->raw.imm[id].value.u = value;
    839         }
    840         break;
    841     }
    842     case 64:
    843     {
    844         ZyanU64 value;
    845         ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 8));
    846         if (is_signed)
    847         {
    848             instruction->raw.imm[id].value.s = (ZyanI64)value;
    849         } else
    850         {
    851             instruction->raw.imm[id].value.u = value;
    852         }
    853         break;
    854     }
    855     default:
    856         ZYAN_UNREACHABLE;
    857     }
    858 
    859     // TODO: Fix endianess on big-endian systems
    860 
    861     return ZYAN_STATUS_SUCCESS;
    862 }
    863 
    864 /* ---------------------------------------------------------------------------------------------- */
    865 /* Semantic instruction decoding                                                                  */
    866 /* ---------------------------------------------------------------------------------------------- */
    867 
    868 #ifndef ZYDIS_MINIMAL_MODE
    869 /**
    870  * Calculates the register-id for a specific register-encoding and register-class.
    871  *
    872  * @param   context         A pointer to the `ZydisDecoderContext` struct.
    873  * @param   instruction     A pointer to the ` ZydisDecodedInstruction` struct.
    874  * @param   encoding        The register-encoding.
    875  * @param   register_class  The register-class.
    876  *
    877  * @return  A zyan status code.
    878  *
    879  * This function calculates the register-id by combining different fields and flags of previously
    880  * decoded structs.
    881  */
    882 static ZyanU8 ZydisCalcRegisterId(const ZydisDecoderContext* context,
    883     const ZydisDecodedInstruction* instruction, ZydisRegisterEncoding encoding,
    884     ZydisRegisterClass register_class)
    885 {
    886     ZYAN_ASSERT(context);
    887     ZYAN_ASSERT(instruction);
    888 
    889     // TODO: Combine OPCODE and IS4 in `ZydisPopulateRegisterIds` and get rid of this
    890     // TODO: function entirely
    891 
    892     switch (encoding)
    893     {
    894     case ZYDIS_REG_ENCODING_REG:
    895         return context->reg_info.id_reg;
    896     case ZYDIS_REG_ENCODING_NDSNDD:
    897         return context->reg_info.id_ndsndd;
    898     case ZYDIS_REG_ENCODING_RM:
    899         return context->reg_info.id_rm;
    900     case ZYDIS_REG_ENCODING_BASE:
    901         return context->reg_info.id_base;
    902     case ZYDIS_REG_ENCODING_INDEX:
    903     case ZYDIS_REG_ENCODING_VIDX:
    904         return context->reg_info.id_index;
    905     case ZYDIS_REG_ENCODING_OPCODE:
    906     {
    907         ZYAN_ASSERT((register_class == ZYDIS_REGCLASS_GPR8) ||
    908                     (register_class == ZYDIS_REGCLASS_GPR16) ||
    909                     (register_class == ZYDIS_REGCLASS_GPR32) ||
    910                     (register_class == ZYDIS_REGCLASS_GPR64));
    911         ZyanU8 value = (instruction->opcode & 0x0F);
    912         if (value > 7)
    913         {
    914             value = value - 8;
    915         }
    916         if (instruction->machine_mode != ZYDIS_MACHINE_MODE_LONG_64)
    917         {
    918             return value;
    919         }
    920         return value | (context->vector_unified.B << 3);
    921     }
    922     case ZYDIS_REG_ENCODING_IS4:
    923     {
    924         if (instruction->machine_mode != ZYDIS_MACHINE_MODE_LONG_64)
    925         {
    926             return (instruction->raw.imm[0].value.u >> 4) & 0x07;
    927         }
    928         ZyanU8 value = (instruction->raw.imm[0].value.u >> 4) & 0x0F;
    929         // We have to check the instruction-encoding, because the extension by bit [3] is only
    930         // valid for EVEX and MVEX instructions
    931         if ((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
    932             (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX))
    933         {
    934             switch (register_class)
    935             {
    936             case ZYDIS_REGCLASS_XMM:
    937             case ZYDIS_REGCLASS_YMM:
    938             case ZYDIS_REGCLASS_ZMM:
    939                 value |= ((instruction->raw.imm[0].value.u & 0x08) << 1);
    940             default:
    941                 break;
    942             }
    943         }
    944         return value;
    945     }
    946     case ZYDIS_REG_ENCODING_MASK:
    947         return context->vector_unified.mask;
    948     default:
    949         ZYAN_UNREACHABLE;
    950     }
    951 }
    952 #endif
    953 
    954 #ifndef ZYDIS_MINIMAL_MODE
    955 /**
    956  * Sets the operand-size and element-specific information for the given operand.
    957  *
    958  * @param   context         A pointer to the `ZydisDecoderContext` struct.
    959  * @param   instruction     A pointer to the `ZydisDecodedInstruction` struct.
    960  * @param   operand         A pointer to the `ZydisDecodedOperand` struct.
    961  * @param   definition      A pointer to the `ZydisOperandDefinition` struct.
    962  */
    963 static void ZydisSetOperandSizeAndElementInfo(const ZydisDecoderContext* context,
    964     const ZydisDecodedInstruction* instruction, ZydisDecodedOperand* operand,
    965     const ZydisOperandDefinition* definition)
    966 {
    967     ZYAN_ASSERT(context);
    968     ZYAN_ASSERT(instruction);
    969     ZYAN_ASSERT(operand);
    970     ZYAN_ASSERT(definition);
    971 
    972     // Operand size
    973     switch (operand->type)
    974     {
    975     case ZYDIS_OPERAND_TYPE_REGISTER:
    976     {
    977         if (definition->size[context->eosz_index])
    978         {
    979             operand->size = definition->size[context->eosz_index] * 8;
    980         } else
    981         {
    982             operand->size = ZydisRegisterGetWidth(instruction->machine_mode,
    983                 operand->reg.value);
    984         }
    985         operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
    986         operand->element_size = operand->size;
    987         break;
    988     }
    989     case ZYDIS_OPERAND_TYPE_MEMORY:
    990         switch (instruction->encoding)
    991         {
    992         case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
    993         case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
    994         case ZYDIS_INSTRUCTION_ENCODING_XOP:
    995         case ZYDIS_INSTRUCTION_ENCODING_VEX:
    996             if (operand->mem.type == ZYDIS_MEMOP_TYPE_AGEN)
    997             {
    998                 ZYAN_ASSERT(definition->size[context->eosz_index] == 0);
    999                 operand->size = instruction->address_width;
   1000                 operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
   1001             } else
   1002             {
   1003                 ZYAN_ASSERT(definition->size[context->eosz_index] ||
   1004                     (instruction->meta.category == ZYDIS_CATEGORY_AMX_TILE));
   1005                 operand->size = definition->size[context->eosz_index] * 8;
   1006             }
   1007             break;
   1008         case ZYDIS_INSTRUCTION_ENCODING_EVEX:
   1009 #ifndef ZYDIS_DISABLE_AVX512
   1010             if (definition->size[context->eosz_index])
   1011             {
   1012                 // Operand size is hardcoded
   1013                 operand->size = definition->size[context->eosz_index] * 8;
   1014             } else
   1015             {
   1016                 // Operand size depends on the tuple-type, the element-size and the number of
   1017                 // elements
   1018                 ZYAN_ASSERT(instruction->avx.vector_length);
   1019                 ZYAN_ASSERT(context->evex.element_size);
   1020                 switch (context->evex.tuple_type)
   1021                 {
   1022                 case ZYDIS_TUPLETYPE_FV:
   1023                     if (instruction->avx.broadcast.mode)
   1024                     {
   1025                         operand->size = context->evex.element_size;
   1026                     } else
   1027                     {
   1028                         operand->size = instruction->avx.vector_length;
   1029                     }
   1030                     break;
   1031                 case ZYDIS_TUPLETYPE_HV:
   1032                     if (instruction->avx.broadcast.mode)
   1033                     {
   1034                         operand->size = context->evex.element_size;
   1035                     } else
   1036                     {
   1037                         operand->size = (ZyanU16)instruction->avx.vector_length / 2;
   1038                     }
   1039                     break;
   1040                 case ZYDIS_TUPLETYPE_QUARTER:
   1041                     if (instruction->avx.broadcast.mode)
   1042                     {
   1043                         operand->size = context->evex.element_size;
   1044                     }
   1045                     else
   1046                     {
   1047                         operand->size = (ZyanU16)instruction->avx.vector_length / 4;
   1048                     }
   1049                     break;
   1050                 default:
   1051                     ZYAN_UNREACHABLE;
   1052                 }
   1053             }
   1054             ZYAN_ASSERT(operand->size);
   1055 #else
   1056             ZYAN_UNREACHABLE;
   1057 #endif
   1058             break;
   1059         case ZYDIS_INSTRUCTION_ENCODING_MVEX:
   1060 #ifndef ZYDIS_DISABLE_KNC
   1061             if (definition->size[context->eosz_index])
   1062             {
   1063                 // Operand size is hardcoded
   1064                 operand->size = definition->size[context->eosz_index] * 8;
   1065             } else
   1066             {
   1067                 ZYAN_ASSERT(definition->element_type == ZYDIS_IELEMENT_TYPE_VARIABLE);
   1068                 ZYAN_ASSERT(instruction->avx.vector_length == 512);
   1069 
   1070                 switch (instruction->avx.conversion.mode)
   1071                 {
   1072                 case ZYDIS_CONVERSION_MODE_INVALID:
   1073                     operand->size = 512;
   1074                     switch (context->mvex.functionality)
   1075                     {
   1076                     case ZYDIS_MVEX_FUNC_SF_32:
   1077                     case ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16:
   1078                     case ZYDIS_MVEX_FUNC_UF_32:
   1079                     case ZYDIS_MVEX_FUNC_DF_32:
   1080                         operand->element_type = ZYDIS_ELEMENT_TYPE_FLOAT32;
   1081                         operand->element_size = 32;
   1082                         break;
   1083                     case ZYDIS_MVEX_FUNC_SF_32_BCST:
   1084                         operand->size = 256;
   1085                         operand->element_type = ZYDIS_ELEMENT_TYPE_FLOAT32;
   1086                         operand->element_size = 32;
   1087                         break;
   1088                     case ZYDIS_MVEX_FUNC_SI_32:
   1089                     case ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16:
   1090                     case ZYDIS_MVEX_FUNC_UI_32:
   1091                     case ZYDIS_MVEX_FUNC_DI_32:
   1092                         operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
   1093                         operand->element_size = 32;
   1094                         break;
   1095                     case ZYDIS_MVEX_FUNC_SI_32_BCST:
   1096                         operand->size = 256;
   1097                         operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
   1098                         operand->element_size = 32;
   1099                         break;
   1100                     case ZYDIS_MVEX_FUNC_SF_64:
   1101                     case ZYDIS_MVEX_FUNC_UF_64:
   1102                     case ZYDIS_MVEX_FUNC_DF_64:
   1103                         operand->element_type = ZYDIS_ELEMENT_TYPE_FLOAT64;
   1104                         operand->element_size = 64;
   1105                         break;
   1106                     case ZYDIS_MVEX_FUNC_SI_64:
   1107                     case ZYDIS_MVEX_FUNC_UI_64:
   1108                     case ZYDIS_MVEX_FUNC_DI_64:
   1109                         operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
   1110                         operand->element_size = 64;
   1111                         break;
   1112                     default:
   1113                         ZYAN_UNREACHABLE;
   1114                     }
   1115                     break;
   1116                 case ZYDIS_CONVERSION_MODE_FLOAT16:
   1117                     operand->size = 256;
   1118                     operand->element_type = ZYDIS_ELEMENT_TYPE_FLOAT16;
   1119                     operand->element_size = 16;
   1120                     break;
   1121                 case ZYDIS_CONVERSION_MODE_SINT16:
   1122                     operand->size = 256;
   1123                     operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
   1124                     operand->element_size = 16;
   1125                     break;
   1126                 case ZYDIS_CONVERSION_MODE_UINT16:
   1127                     operand->size = 256;
   1128                     operand->element_type = ZYDIS_ELEMENT_TYPE_UINT;
   1129                     operand->element_size = 16;
   1130                     break;
   1131                 case ZYDIS_CONVERSION_MODE_SINT8:
   1132                     operand->size = 128;
   1133                     operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
   1134                     operand->element_size = 8;
   1135                     break;
   1136                 case ZYDIS_CONVERSION_MODE_UINT8:
   1137                     operand->size = 128;
   1138                     operand->element_type = ZYDIS_ELEMENT_TYPE_UINT;
   1139                     operand->element_size = 8;
   1140                     break;
   1141                 default:
   1142                     ZYAN_UNREACHABLE;
   1143                 }
   1144 
   1145                 switch (instruction->avx.broadcast.mode)
   1146                 {
   1147                 case ZYDIS_BROADCAST_MODE_INVALID:
   1148                     // Nothing to do here
   1149                     break;
   1150                 case ZYDIS_BROADCAST_MODE_1_TO_8:
   1151                 case ZYDIS_BROADCAST_MODE_1_TO_16:
   1152                     operand->size = operand->element_size;
   1153                     break;
   1154                 case ZYDIS_BROADCAST_MODE_4_TO_8:
   1155                 case ZYDIS_BROADCAST_MODE_4_TO_16:
   1156                     operand->size = operand->element_size * 4;
   1157                     break;
   1158                 default:
   1159                     ZYAN_UNREACHABLE;
   1160                 }
   1161             }
   1162 #else
   1163             ZYAN_UNREACHABLE;
   1164 #endif
   1165             break;
   1166         default:
   1167             ZYAN_UNREACHABLE;
   1168         }
   1169         break;
   1170     case ZYDIS_OPERAND_TYPE_POINTER:
   1171         ZYAN_ASSERT((instruction->raw.imm[0].size == 16) ||
   1172                     (instruction->raw.imm[0].size == 32));
   1173         ZYAN_ASSERT( instruction->raw.imm[1].size == 16);
   1174         operand->size = instruction->raw.imm[0].size + instruction->raw.imm[1].size;
   1175         break;
   1176     case ZYDIS_OPERAND_TYPE_IMMEDIATE:
   1177         operand->size = definition->size[context->eosz_index] * 8;
   1178         break;
   1179     default:
   1180         ZYAN_UNREACHABLE;
   1181     }
   1182 
   1183     // Element-type and -size
   1184     if (definition->element_type && (definition->element_type != ZYDIS_IELEMENT_TYPE_VARIABLE))
   1185     {
   1186         ZydisGetElementInfo(definition->element_type, &operand->element_type,
   1187             &operand->element_size);
   1188         if (!operand->element_size)
   1189         {
   1190             // The element size is the same as the operand size. This is used for single element
   1191             // scaling operands
   1192             operand->element_size = operand->size;
   1193         }
   1194     }
   1195 
   1196     // Element count
   1197     if (operand->element_size && operand->size && (operand->element_type != ZYDIS_ELEMENT_TYPE_CC))
   1198     {
   1199         operand->element_count = operand->size / operand->element_size;
   1200     } else
   1201     {
   1202         operand->element_count = 1;
   1203     }
   1204 }
   1205 #endif
   1206 
   1207 #ifndef ZYDIS_MINIMAL_MODE
   1208 /**
   1209  * Decodes an register-operand.
   1210  *
   1211  * @param   instruction      A pointer to the `ZydisDecodedInstruction` struct.
   1212  * @param   operand          A pointer to the `ZydisDecodedOperand` struct.
   1213  * @param   register_class   The register class.
   1214  * @param   register_id      The register id.
   1215  *
   1216  * @return  A zyan status code.
   1217  */
   1218 static ZyanStatus ZydisDecodeOperandRegister(const ZydisDecodedInstruction* instruction,
   1219     ZydisDecodedOperand* operand, ZydisRegisterClass register_class, ZyanU8 register_id)
   1220 {
   1221     ZYAN_ASSERT(instruction);
   1222     ZYAN_ASSERT(operand);
   1223 
   1224     operand->type = ZYDIS_OPERAND_TYPE_REGISTER;
   1225 
   1226     if (register_class == ZYDIS_REGCLASS_GPR8)
   1227     {
   1228         if ((instruction->attributes & ZYDIS_ATTRIB_HAS_REX) && (register_id >= 4))
   1229         {
   1230             operand->reg.value = ZYDIS_REGISTER_SPL + (register_id - 4);
   1231         } else
   1232         {
   1233             operand->reg.value = ZYDIS_REGISTER_AL + register_id;
   1234         }
   1235     } else
   1236     {
   1237         operand->reg.value = ZydisRegisterEncode(register_class, register_id);
   1238         ZYAN_ASSERT(operand->reg.value);
   1239         /*if (!operand->reg.value)
   1240         {
   1241             return ZYAN_STATUS_BAD_REGISTER;
   1242         }*/
   1243     }
   1244 
   1245     return ZYAN_STATUS_SUCCESS;
   1246 }
   1247 #endif
   1248 
   1249 #ifndef ZYDIS_MINIMAL_MODE
   1250 /**
   1251  * Decodes a memory operand.
   1252  *
   1253  * @param   context             A pointer to the `ZydisDecoderContext` struct.
   1254  * @param   instruction         A pointer to the `ZydisDecodedInstruction` struct.
   1255  * @param   operand             A pointer to the `ZydisDecodedOperand` struct.
   1256  * @param   vidx_register_class The register-class to use as the index register-class for
   1257  *                              instructions with `VSIB` addressing.
   1258  *
   1259  * @return  A zyan status code.
   1260  */
   1261 static ZyanStatus ZydisDecodeOperandMemory(const ZydisDecoderContext* context,
   1262     const ZydisDecodedInstruction* instruction, ZydisDecodedOperand* operand,
   1263     ZydisRegisterClass vidx_register_class)
   1264 {
   1265     ZYAN_ASSERT(context);
   1266     ZYAN_ASSERT(instruction);
   1267     ZYAN_ASSERT(operand);
   1268     ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MODRM);
   1269     ZYAN_ASSERT(instruction->raw.modrm.mod != 3);
   1270     ZYAN_ASSERT(!vidx_register_class || ((instruction->raw.modrm.rm == 4) &&
   1271         ((instruction->address_width == 32) || (instruction->address_width == 64))));
   1272 
   1273     operand->type = ZYDIS_OPERAND_TYPE_MEMORY;
   1274     operand->mem.type = ZYDIS_MEMOP_TYPE_MEM;
   1275 
   1276     const ZyanU8 modrm_rm = instruction->raw.modrm.rm;
   1277     ZyanU8 displacement_size = 0;
   1278     switch (instruction->address_width)
   1279     {
   1280     case 16:
   1281     {
   1282         static const ZydisRegister bases[] =
   1283         {
   1284             ZYDIS_REGISTER_BX,   ZYDIS_REGISTER_BX,   ZYDIS_REGISTER_BP,   ZYDIS_REGISTER_BP,
   1285             ZYDIS_REGISTER_SI,   ZYDIS_REGISTER_DI,   ZYDIS_REGISTER_BP,   ZYDIS_REGISTER_BX
   1286         };
   1287         static const ZydisRegister indices[] =
   1288         {
   1289             ZYDIS_REGISTER_SI,   ZYDIS_REGISTER_DI,   ZYDIS_REGISTER_SI,   ZYDIS_REGISTER_DI,
   1290             ZYDIS_REGISTER_NONE, ZYDIS_REGISTER_NONE, ZYDIS_REGISTER_NONE, ZYDIS_REGISTER_NONE
   1291         };
   1292         operand->mem.base = bases[modrm_rm];
   1293         operand->mem.index = indices[modrm_rm];
   1294         operand->mem.scale = (operand->mem.index == ZYDIS_REGISTER_NONE) ? 0 : 1;
   1295         switch (instruction->raw.modrm.mod)
   1296         {
   1297         case 0:
   1298             if (modrm_rm == 6)
   1299             {
   1300                 displacement_size = 16;
   1301                 operand->mem.base = ZYDIS_REGISTER_NONE;
   1302             }
   1303             break;
   1304         case 1:
   1305             displacement_size = 8;
   1306             break;
   1307         case 2:
   1308             displacement_size = 16;
   1309             break;
   1310         default:
   1311             ZYAN_UNREACHABLE;
   1312         }
   1313         break;
   1314     }
   1315     case 32:
   1316     {
   1317         operand->mem.base = ZYDIS_REGISTER_EAX + ZydisCalcRegisterId(context, instruction,
   1318             ZYDIS_REG_ENCODING_BASE, ZYDIS_REGCLASS_GPR32);
   1319         switch (instruction->raw.modrm.mod)
   1320         {
   1321         case 0:
   1322             if (modrm_rm == 5)
   1323             {
   1324                 if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
   1325                 {
   1326                     operand->mem.base = ZYDIS_REGISTER_EIP;
   1327                 } else
   1328                 {
   1329                     operand->mem.base = ZYDIS_REGISTER_NONE;
   1330                 }
   1331                 displacement_size = 32;
   1332             }
   1333             break;
   1334         case 1:
   1335             displacement_size = 8;
   1336             break;
   1337         case 2:
   1338             displacement_size = 32;
   1339             break;
   1340         default:
   1341             ZYAN_UNREACHABLE;
   1342         }
   1343         if (modrm_rm == 4)
   1344         {
   1345             ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_SIB);
   1346             operand->mem.index =
   1347                 ZydisRegisterEncode(vidx_register_class ? vidx_register_class : ZYDIS_REGCLASS_GPR32,
   1348                     ZydisCalcRegisterId(context, instruction,
   1349                         vidx_register_class ? ZYDIS_REG_ENCODING_VIDX : ZYDIS_REG_ENCODING_INDEX,
   1350                         vidx_register_class ? vidx_register_class : ZYDIS_REGCLASS_GPR32));
   1351             operand->mem.scale = (1 << instruction->raw.sib.scale);
   1352             if (operand->mem.index == ZYDIS_REGISTER_ESP)
   1353             {
   1354                 operand->mem.index = ZYDIS_REGISTER_NONE;
   1355                 operand->mem.scale = 0;
   1356             }
   1357             if (operand->mem.base == ZYDIS_REGISTER_EBP)
   1358             {
   1359                 if (instruction->raw.modrm.mod == 0)
   1360                 {
   1361                     operand->mem.base = ZYDIS_REGISTER_NONE;
   1362                 }
   1363                 displacement_size = (instruction->raw.modrm.mod == 1) ? 8 : 32;
   1364             }
   1365         } else
   1366         {
   1367             operand->mem.index = ZYDIS_REGISTER_NONE;
   1368             operand->mem.scale = 0;
   1369         }
   1370         break;
   1371     }
   1372     case 64:
   1373     {
   1374         operand->mem.base = ZYDIS_REGISTER_RAX + ZydisCalcRegisterId(context, instruction,
   1375             ZYDIS_REG_ENCODING_BASE, ZYDIS_REGCLASS_GPR64);
   1376         switch (instruction->raw.modrm.mod)
   1377         {
   1378         case 0:
   1379             if (modrm_rm == 5)
   1380             {
   1381                 if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
   1382                 {
   1383                     operand->mem.base = ZYDIS_REGISTER_RIP;
   1384                 } else
   1385                 {
   1386                     operand->mem.base = ZYDIS_REGISTER_NONE;
   1387                 }
   1388                 displacement_size = 32;
   1389             }
   1390             break;
   1391         case 1:
   1392             displacement_size = 8;
   1393             break;
   1394         case 2:
   1395             displacement_size = 32;
   1396             break;
   1397         default:
   1398             ZYAN_UNREACHABLE;
   1399         }
   1400         if ((modrm_rm & 0x07) == 4)
   1401         {
   1402             ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_SIB);
   1403             operand->mem.index =
   1404                 ZydisRegisterEncode(vidx_register_class ? vidx_register_class : ZYDIS_REGCLASS_GPR64,
   1405                     ZydisCalcRegisterId(context, instruction,
   1406                         vidx_register_class ? ZYDIS_REG_ENCODING_VIDX : ZYDIS_REG_ENCODING_INDEX,
   1407                         vidx_register_class ? vidx_register_class : ZYDIS_REGCLASS_GPR64));
   1408             operand->mem.scale = (1 << instruction->raw.sib.scale);
   1409             if (operand->mem.index == ZYDIS_REGISTER_RSP)
   1410             {
   1411                 operand->mem.index = ZYDIS_REGISTER_NONE;
   1412                 operand->mem.scale = 0;
   1413             }
   1414             if ((operand->mem.base == ZYDIS_REGISTER_RBP) ||
   1415                 (operand->mem.base == ZYDIS_REGISTER_R13))
   1416             {
   1417                 if (instruction->raw.modrm.mod == 0)
   1418                 {
   1419                     operand->mem.base = ZYDIS_REGISTER_NONE;
   1420                 }
   1421                 displacement_size = (instruction->raw.modrm.mod == 1) ? 8 : 32;
   1422             }
   1423         } else
   1424         {
   1425             operand->mem.index = ZYDIS_REGISTER_NONE;
   1426             operand->mem.scale = 0;
   1427         }
   1428         break;
   1429     }
   1430     default:
   1431         ZYAN_UNREACHABLE;
   1432     }
   1433     if (displacement_size)
   1434     {
   1435         ZYAN_ASSERT(instruction->raw.disp.size == displacement_size);
   1436         operand->mem.disp.has_displacement = ZYAN_TRUE;
   1437         operand->mem.disp.value = instruction->raw.disp.value;
   1438     }
   1439     return ZYAN_STATUS_SUCCESS;
   1440 }
   1441 #endif
   1442 
   1443 #ifndef ZYDIS_MINIMAL_MODE
   1444 /**
   1445  * Decodes an implicit register operand.
   1446  *
   1447  * @param   decoder         A pointer to the `ZydisDecoder` instance.
   1448  * @param   context         A pointer to the `ZydisDecoderContext` struct.
   1449  * @param   instruction     A pointer to the `ZydisDecodedInstruction` struct.
   1450  * @param   operand         A pointer to the `ZydisDecodedOperand` struct.
   1451  * @param   definition      A pointer to the `ZydisOperandDefinition` struct.
   1452  */
   1453 static void ZydisDecodeOperandImplicitRegister(const ZydisDecoder* decoder,
   1454     const ZydisDecoderContext* context, const ZydisDecodedInstruction* instruction,
   1455     ZydisDecodedOperand* operand, const ZydisOperandDefinition* definition)
   1456 {
   1457     ZYAN_ASSERT(context);
   1458     ZYAN_ASSERT(instruction);
   1459     ZYAN_ASSERT(operand);
   1460     ZYAN_ASSERT(definition);
   1461 
   1462     operand->type = ZYDIS_OPERAND_TYPE_REGISTER;
   1463 
   1464     switch (definition->op.reg.type)
   1465     {
   1466     case ZYDIS_IMPLREG_TYPE_STATIC:
   1467         operand->reg.value = definition->op.reg.reg.reg;
   1468         break;
   1469     case ZYDIS_IMPLREG_TYPE_GPR_OSZ:
   1470     {
   1471         static const ZydisRegisterClass lookup[3] =
   1472         {
   1473             ZYDIS_REGCLASS_GPR16,
   1474             ZYDIS_REGCLASS_GPR32,
   1475             ZYDIS_REGCLASS_GPR64
   1476         };
   1477         operand->reg.value =
   1478             ZydisRegisterEncode(lookup[context->eosz_index], definition->op.reg.reg.id);
   1479         break;
   1480     }
   1481     case ZYDIS_IMPLREG_TYPE_GPR_ASZ:
   1482         operand->reg.value = ZydisRegisterEncode(
   1483             (instruction->address_width    == 16) ? ZYDIS_REGCLASS_GPR16  :
   1484             (instruction->address_width    == 32) ? ZYDIS_REGCLASS_GPR32  : ZYDIS_REGCLASS_GPR64,
   1485             definition->op.reg.reg.id);
   1486         break;
   1487     case ZYDIS_IMPLREG_TYPE_IP_ASZ:
   1488         operand->reg.value =
   1489             (instruction->address_width    == 16) ? ZYDIS_REGISTER_IP     :
   1490             (instruction->address_width    == 32) ? ZYDIS_REGISTER_EIP    : ZYDIS_REGISTER_RIP;
   1491         break;
   1492     case ZYDIS_IMPLREG_TYPE_GPR_SSZ:
   1493         operand->reg.value = ZydisRegisterEncode(
   1494             (decoder->stack_width == ZYDIS_STACK_WIDTH_16) ? ZYDIS_REGCLASS_GPR16 :
   1495             (decoder->stack_width == ZYDIS_STACK_WIDTH_32) ? ZYDIS_REGCLASS_GPR32 :
   1496                                                              ZYDIS_REGCLASS_GPR64,
   1497             definition->op.reg.reg.id);
   1498         break;
   1499     case ZYDIS_IMPLREG_TYPE_IP_SSZ:
   1500         operand->reg.value =
   1501             (decoder->stack_width == ZYDIS_STACK_WIDTH_16) ? ZYDIS_REGISTER_EIP    :
   1502             (decoder->stack_width == ZYDIS_STACK_WIDTH_32) ? ZYDIS_REGISTER_EIP    :
   1503                                                              ZYDIS_REGISTER_RIP;
   1504         break;
   1505     case ZYDIS_IMPLREG_TYPE_FLAGS_SSZ:
   1506         operand->reg.value =
   1507             (decoder->stack_width == ZYDIS_STACK_WIDTH_16) ? ZYDIS_REGISTER_FLAGS  :
   1508             (decoder->stack_width == ZYDIS_STACK_WIDTH_32) ? ZYDIS_REGISTER_EFLAGS :
   1509                                                              ZYDIS_REGISTER_RFLAGS;
   1510         break;
   1511     default:
   1512         ZYAN_UNREACHABLE;
   1513     }
   1514 }
   1515 #endif
   1516 
   1517 #ifndef ZYDIS_MINIMAL_MODE
   1518 /**
   1519  * Decodes an implicit memory operand.
   1520  *
   1521  * @param   decoder         A pointer to the `ZydisDecoder` instance.
   1522  * @param   context         A pointer to the `ZydisDecoderContext` struct.
   1523  * @param   instruction     A pointer to the `ZydisDecodedInstruction` struct.
   1524  * @param   operand         A pointer to the `ZydisDecodedOperand` struct.
   1525  * @param   definition      A pointer to the `ZydisOperandDefinition` struct.
   1526  */
   1527 static void ZydisDecodeOperandImplicitMemory(const ZydisDecoder* decoder,
   1528     const ZydisDecoderContext* context, const ZydisDecodedInstruction* instruction,
   1529     ZydisDecodedOperand* operand, const ZydisOperandDefinition* definition)
   1530 {
   1531     ZYAN_ASSERT(context);
   1532     ZYAN_ASSERT(operand);
   1533     ZYAN_ASSERT(definition);
   1534 
   1535     static const ZydisRegisterClass lookup[3] =
   1536     {
   1537         ZYDIS_REGCLASS_GPR16,
   1538         ZYDIS_REGCLASS_GPR32,
   1539         ZYDIS_REGCLASS_GPR64
   1540     };
   1541 
   1542     operand->type = ZYDIS_OPERAND_TYPE_MEMORY;
   1543     operand->mem.type = ZYDIS_MEMOP_TYPE_MEM;
   1544 
   1545     switch (definition->op.mem.base)
   1546     {
   1547     case ZYDIS_IMPLMEM_BASE_AGPR_REG:
   1548         operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index],
   1549             ZydisCalcRegisterId(context, instruction, ZYDIS_REG_ENCODING_REG,
   1550                 lookup[context->easz_index]));
   1551         break;
   1552     case ZYDIS_IMPLMEM_BASE_AGPR_RM:
   1553         operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index],
   1554             ZydisCalcRegisterId(context, instruction, ZYDIS_REG_ENCODING_RM,
   1555                 lookup[context->easz_index]));
   1556         break;
   1557     case ZYDIS_IMPLMEM_BASE_AAX:
   1558         operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 0);
   1559         break;
   1560     case ZYDIS_IMPLMEM_BASE_ADX:
   1561         operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 2);
   1562         break;
   1563     case ZYDIS_IMPLMEM_BASE_ABX:
   1564         operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 3);
   1565         break;
   1566     case ZYDIS_IMPLMEM_BASE_ASI:
   1567         operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 6);
   1568         break;
   1569     case ZYDIS_IMPLMEM_BASE_ADI:
   1570         operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 7);
   1571         break;
   1572     case ZYDIS_IMPLMEM_BASE_SSP:
   1573         operand->mem.base = ZydisRegisterEncode(lookup[decoder->stack_width], 4);
   1574         break;
   1575     case ZYDIS_IMPLMEM_BASE_SBP:
   1576         operand->mem.base = ZydisRegisterEncode(lookup[decoder->stack_width], 5);
   1577         break;
   1578     default:
   1579         ZYAN_UNREACHABLE;
   1580     }
   1581 
   1582     if (definition->op.mem.seg)
   1583     {
   1584         operand->mem.segment =
   1585             ZydisRegisterEncode(ZYDIS_REGCLASS_SEGMENT, definition->op.mem.seg - 1);
   1586         ZYAN_ASSERT(operand->mem.segment);
   1587     }
   1588 }
   1589 #endif
   1590 
   1591 #ifndef ZYDIS_MINIMAL_MODE
   1592 ZyanStatus ZydisDecodeOperands(const ZydisDecoder* decoder, const ZydisDecoderContext* context,
   1593     const ZydisDecodedInstruction* instruction, ZydisDecodedOperand* operands, ZyanU8 operand_count)
   1594 {
   1595     ZYAN_ASSERT(decoder);
   1596     ZYAN_ASSERT(context);
   1597     ZYAN_ASSERT(context->definition);
   1598     ZYAN_ASSERT(instruction);
   1599     ZYAN_ASSERT(operands);
   1600     ZYAN_ASSERT(operand_count);
   1601     ZYAN_ASSERT(operand_count <= instruction->operand_count);
   1602 
   1603     const ZydisInstructionDefinition* definition = context->definition;
   1604     const ZydisOperandDefinition* operand = ZydisGetOperandDefinitions(definition);
   1605 
   1606     ZYAN_MEMSET(operands, 0, sizeof(ZydisDecodedOperand) * operand_count);
   1607 
   1608     ZyanU8 imm_id = 0;
   1609     for (ZyanU8 i = 0; i < operand_count; ++i)
   1610     {
   1611         ZydisRegisterClass register_class = ZYDIS_REGCLASS_INVALID;
   1612 
   1613         operands[i].id = i;
   1614         operands[i].visibility = operand->visibility;
   1615         operands[i].actions = operand->actions;
   1616         ZYAN_ASSERT(!(operand->actions &
   1617             ZYDIS_OPERAND_ACTION_READ & ZYDIS_OPERAND_ACTION_CONDREAD) ||
   1618             (operand->actions & ZYDIS_OPERAND_ACTION_READ) ^
   1619             (operand->actions & ZYDIS_OPERAND_ACTION_CONDREAD));
   1620         ZYAN_ASSERT(!(operand->actions &
   1621             ZYDIS_OPERAND_ACTION_WRITE & ZYDIS_OPERAND_ACTION_CONDWRITE) ||
   1622             (operand->actions & ZYDIS_OPERAND_ACTION_WRITE) ^
   1623             (operand->actions & ZYDIS_OPERAND_ACTION_CONDWRITE));
   1624 
   1625         // Implicit operands
   1626         switch (operand->type)
   1627         {
   1628         case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG:
   1629             ZydisDecodeOperandImplicitRegister(decoder, context, instruction, &operands[i], operand);
   1630             break;
   1631         case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM:
   1632             ZydisDecodeOperandImplicitMemory(decoder, context, instruction, &operands[i], operand);
   1633             break;
   1634         case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1:
   1635             operands[i].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
   1636             operands[i].size = 8;
   1637             operands[i].imm.value.u = 1;
   1638             operands[i].imm.is_signed = ZYAN_FALSE;
   1639             operands[i].imm.is_relative = ZYAN_FALSE;
   1640             break;
   1641         default:
   1642             break;
   1643         }
   1644         if (operands[i].type)
   1645         {
   1646             goto FinalizeOperand;
   1647         }
   1648 
   1649         operands[i].encoding = operand->op.encoding;
   1650 
   1651         // Register operands
   1652         switch (operand->type)
   1653         {
   1654         case ZYDIS_SEMANTIC_OPTYPE_GPR8:
   1655             register_class = ZYDIS_REGCLASS_GPR8;
   1656             break;
   1657         case ZYDIS_SEMANTIC_OPTYPE_GPR16:
   1658             register_class = ZYDIS_REGCLASS_GPR16;
   1659             break;
   1660         case ZYDIS_SEMANTIC_OPTYPE_GPR32:
   1661             register_class = ZYDIS_REGCLASS_GPR32;
   1662             break;
   1663         case ZYDIS_SEMANTIC_OPTYPE_GPR64:
   1664             register_class = ZYDIS_REGCLASS_GPR64;
   1665             break;
   1666         case ZYDIS_SEMANTIC_OPTYPE_GPR16_32_64:
   1667             ZYAN_ASSERT((instruction->operand_width == 16) || (instruction->operand_width == 32) ||
   1668                 (instruction->operand_width == 64));
   1669             register_class =
   1670                 (instruction->operand_width == 16) ? ZYDIS_REGCLASS_GPR16 : (
   1671                     (instruction->operand_width == 32) ? ZYDIS_REGCLASS_GPR32 : ZYDIS_REGCLASS_GPR64);
   1672             break;
   1673         case ZYDIS_SEMANTIC_OPTYPE_GPR32_32_64:
   1674             ZYAN_ASSERT((instruction->operand_width == 16) || (instruction->operand_width == 32) ||
   1675                 (instruction->operand_width == 64));
   1676             register_class =
   1677                 (instruction->operand_width == 16) ? ZYDIS_REGCLASS_GPR32 : (
   1678                     (instruction->operand_width == 32) ? ZYDIS_REGCLASS_GPR32 : ZYDIS_REGCLASS_GPR64);
   1679             break;
   1680         case ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32:
   1681             ZYAN_ASSERT((instruction->operand_width == 16) || (instruction->operand_width == 32) ||
   1682                 (instruction->operand_width == 64));
   1683             register_class =
   1684                 (instruction->operand_width == 16) ? ZYDIS_REGCLASS_GPR16 : ZYDIS_REGCLASS_GPR32;
   1685             break;
   1686         case ZYDIS_SEMANTIC_OPTYPE_GPR_ASZ:
   1687             ZYAN_ASSERT((instruction->address_width == 16) || (instruction->address_width == 32) ||
   1688                 (instruction->address_width == 64));
   1689             register_class =
   1690                 (instruction->address_width == 16) ? ZYDIS_REGCLASS_GPR16 : (
   1691                     (instruction->address_width == 32) ? ZYDIS_REGCLASS_GPR32 : ZYDIS_REGCLASS_GPR64);
   1692             break;
   1693         case ZYDIS_SEMANTIC_OPTYPE_FPR:
   1694             register_class = ZYDIS_REGCLASS_X87;
   1695             break;
   1696         case ZYDIS_SEMANTIC_OPTYPE_MMX:
   1697             register_class = ZYDIS_REGCLASS_MMX;
   1698             break;
   1699         case ZYDIS_SEMANTIC_OPTYPE_XMM:
   1700             register_class = ZYDIS_REGCLASS_XMM;
   1701             break;
   1702         case ZYDIS_SEMANTIC_OPTYPE_YMM:
   1703             register_class = ZYDIS_REGCLASS_YMM;
   1704             break;
   1705         case ZYDIS_SEMANTIC_OPTYPE_ZMM:
   1706             register_class = ZYDIS_REGCLASS_ZMM;
   1707             break;
   1708         case ZYDIS_SEMANTIC_OPTYPE_TMM:
   1709             register_class = ZYDIS_REGCLASS_TMM;
   1710             break;
   1711         case ZYDIS_SEMANTIC_OPTYPE_BND:
   1712             register_class = ZYDIS_REGCLASS_BOUND;
   1713             break;
   1714         case ZYDIS_SEMANTIC_OPTYPE_SREG:
   1715             register_class = ZYDIS_REGCLASS_SEGMENT;
   1716             break;
   1717         case ZYDIS_SEMANTIC_OPTYPE_CR:
   1718             register_class = ZYDIS_REGCLASS_CONTROL;
   1719             break;
   1720         case ZYDIS_SEMANTIC_OPTYPE_DR:
   1721             register_class = ZYDIS_REGCLASS_DEBUG;
   1722             break;
   1723         case ZYDIS_SEMANTIC_OPTYPE_MASK:
   1724             register_class = ZYDIS_REGCLASS_MASK;
   1725             break;
   1726         default:
   1727             break;
   1728         }
   1729         if (register_class)
   1730         {
   1731             switch (operand->op.encoding)
   1732             {
   1733             case ZYDIS_OPERAND_ENCODING_MODRM_REG:
   1734                 ZYAN_CHECK(
   1735                     ZydisDecodeOperandRegister(
   1736                         instruction, &operands[i], register_class,
   1737                         ZydisCalcRegisterId(
   1738                             context, instruction, ZYDIS_REG_ENCODING_REG, register_class)));
   1739                 break;
   1740             case ZYDIS_OPERAND_ENCODING_MODRM_RM:
   1741                 ZYAN_CHECK(
   1742                     ZydisDecodeOperandRegister(
   1743                         instruction, &operands[i], register_class,
   1744                         ZydisCalcRegisterId(
   1745                             context, instruction, ZYDIS_REG_ENCODING_RM, register_class)));
   1746                 break;
   1747             case ZYDIS_OPERAND_ENCODING_OPCODE:
   1748                 ZYAN_CHECK(
   1749                     ZydisDecodeOperandRegister(
   1750                         instruction, &operands[i], register_class,
   1751                         ZydisCalcRegisterId(
   1752                             context, instruction, ZYDIS_REG_ENCODING_OPCODE, register_class)));
   1753                 break;
   1754             case ZYDIS_OPERAND_ENCODING_NDSNDD:
   1755                 ZYAN_CHECK(
   1756                     ZydisDecodeOperandRegister(
   1757                         instruction, &operands[i], register_class,
   1758                         ZydisCalcRegisterId(
   1759                             context, instruction, ZYDIS_REG_ENCODING_NDSNDD, register_class)));
   1760                 break;
   1761             case ZYDIS_OPERAND_ENCODING_MASK:
   1762                 ZYAN_CHECK(
   1763                     ZydisDecodeOperandRegister(
   1764                         instruction, &operands[i], register_class,
   1765                         ZydisCalcRegisterId(
   1766                             context, instruction, ZYDIS_REG_ENCODING_MASK, register_class)));
   1767                 break;
   1768             case ZYDIS_OPERAND_ENCODING_IS4:
   1769                 ZYAN_CHECK(
   1770                     ZydisDecodeOperandRegister(
   1771                         instruction, &operands[i], register_class,
   1772                         ZydisCalcRegisterId(
   1773                             context, instruction, ZYDIS_REG_ENCODING_IS4, register_class)));
   1774                 break;
   1775             default:
   1776                 ZYAN_UNREACHABLE;
   1777             }
   1778 
   1779             if (operand->is_multisource4)
   1780             {
   1781                 operands[i].attributes |= ZYDIS_OATTRIB_IS_MULTISOURCE4;
   1782             }
   1783 
   1784             goto FinalizeOperand;
   1785         }
   1786 
   1787         // Memory operands
   1788         switch (operand->type)
   1789         {
   1790         case ZYDIS_SEMANTIC_OPTYPE_MEM:
   1791             ZYAN_CHECK(
   1792                 ZydisDecodeOperandMemory(
   1793                     context, instruction, &operands[i], ZYDIS_REGCLASS_INVALID));
   1794             break;
   1795         case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBX:
   1796             ZYAN_CHECK(
   1797                 ZydisDecodeOperandMemory(
   1798                     context, instruction, &operands[i], ZYDIS_REGCLASS_XMM));
   1799             operands[i].mem.type = ZYDIS_MEMOP_TYPE_VSIB;
   1800             break;
   1801         case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBY:
   1802             ZYAN_CHECK(
   1803                 ZydisDecodeOperandMemory(
   1804                     context, instruction, &operands[i], ZYDIS_REGCLASS_YMM));
   1805             operands[i].mem.type = ZYDIS_MEMOP_TYPE_VSIB;
   1806             break;
   1807         case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBZ:
   1808             ZYAN_CHECK(
   1809                 ZydisDecodeOperandMemory(
   1810                     context, instruction, &operands[i], ZYDIS_REGCLASS_ZMM));
   1811             operands[i].mem.type = ZYDIS_MEMOP_TYPE_VSIB;
   1812             break;
   1813         case ZYDIS_SEMANTIC_OPTYPE_PTR:
   1814             ZYAN_ASSERT((instruction->raw.imm[0].size == 16) ||
   1815                 (instruction->raw.imm[0].size == 32));
   1816             ZYAN_ASSERT(instruction->raw.imm[1].size == 16);
   1817             operands[i].type = ZYDIS_OPERAND_TYPE_POINTER;
   1818             operands[i].ptr.offset = (ZyanU32)instruction->raw.imm[0].value.u;
   1819             operands[i].ptr.segment = (ZyanU16)instruction->raw.imm[1].value.u;
   1820             break;
   1821         case ZYDIS_SEMANTIC_OPTYPE_AGEN:
   1822             operands[i].actions = 0; // TODO: Remove after generator update
   1823             ZYAN_CHECK(
   1824                 ZydisDecodeOperandMemory(
   1825                     context, instruction, &operands[i], ZYDIS_REGCLASS_INVALID));
   1826             operands[i].mem.type = ZYDIS_MEMOP_TYPE_AGEN;
   1827             break;
   1828         case ZYDIS_SEMANTIC_OPTYPE_MOFFS:
   1829             ZYAN_ASSERT(instruction->raw.disp.size);
   1830             operands[i].type = ZYDIS_OPERAND_TYPE_MEMORY;
   1831             operands[i].mem.type = ZYDIS_MEMOP_TYPE_MEM;
   1832             operands[i].mem.disp.has_displacement = ZYAN_TRUE;
   1833             operands[i].mem.disp.value = instruction->raw.disp.value;
   1834             break;
   1835         case ZYDIS_SEMANTIC_OPTYPE_MIB:
   1836             operands[i].actions = 0; // TODO: Remove after generator update
   1837             ZYAN_CHECK(
   1838                 ZydisDecodeOperandMemory(
   1839                     context, instruction, &operands[i], ZYDIS_REGCLASS_INVALID));
   1840             operands[i].mem.type = ZYDIS_MEMOP_TYPE_MIB;
   1841             break;
   1842         default:
   1843             break;
   1844         }
   1845         if (operands[i].type)
   1846         {
   1847 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
   1848             // Handle compressed 8-bit displacement
   1849             if (((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
   1850                 (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)) &&
   1851                 (instruction->raw.disp.size == 8))
   1852             {
   1853                 operands[i].mem.disp.value *= context->cd8_scale;
   1854             }
   1855 #endif
   1856 
   1857             goto FinalizeOperand;
   1858         }
   1859 
   1860         // Immediate operands
   1861         switch (operand->type)
   1862         {
   1863         case ZYDIS_SEMANTIC_OPTYPE_REL:
   1864             ZYAN_ASSERT(instruction->raw.imm[imm_id].is_relative);
   1865             ZYAN_FALLTHROUGH;
   1866         case ZYDIS_SEMANTIC_OPTYPE_IMM:
   1867             ZYAN_ASSERT((imm_id == 0) || (imm_id == 1));
   1868             operands[i].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
   1869             operands[i].size = operand->size[context->eosz_index] * 8;
   1870             if (operand->op.encoding == ZYDIS_OPERAND_ENCODING_IS4)
   1871             {
   1872                 // The upper half of the 8-bit immediate is used to encode a register specifier
   1873                 ZYAN_ASSERT(instruction->raw.imm[imm_id].size == 8);
   1874                 operands[i].imm.value.u = (ZyanU8)instruction->raw.imm[imm_id].value.u & 0x0F;
   1875             }
   1876             else
   1877             {
   1878                 operands[i].imm.value.u = instruction->raw.imm[imm_id].value.u;
   1879             }
   1880             operands[i].imm.is_signed = instruction->raw.imm[imm_id].is_signed;
   1881             operands[i].imm.is_relative = instruction->raw.imm[imm_id].is_relative;
   1882             ++imm_id;
   1883             break;
   1884         default:
   1885             break;
   1886         }
   1887         ZYAN_ASSERT(operands[i].type == ZYDIS_OPERAND_TYPE_IMMEDIATE);
   1888 
   1889     FinalizeOperand:
   1890         // Set segment-register for memory operands
   1891         if (operands[i].type == ZYDIS_OPERAND_TYPE_MEMORY)
   1892         {
   1893             if (!operand->ignore_seg_override &&
   1894                 instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_CS)
   1895             {
   1896                 operands[i].mem.segment = ZYDIS_REGISTER_CS;
   1897             }
   1898             else
   1899                 if (!operand->ignore_seg_override &&
   1900                     instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_SS)
   1901                 {
   1902                     operands[i].mem.segment = ZYDIS_REGISTER_SS;
   1903                 }
   1904                 else
   1905                     if (!operand->ignore_seg_override &&
   1906                         instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_DS)
   1907                     {
   1908                         operands[i].mem.segment = ZYDIS_REGISTER_DS;
   1909                     }
   1910                     else
   1911                         if (!operand->ignore_seg_override &&
   1912                             instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_ES)
   1913                         {
   1914                             operands[i].mem.segment = ZYDIS_REGISTER_ES;
   1915                         }
   1916                         else
   1917                             if (!operand->ignore_seg_override &&
   1918                                 instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_FS)
   1919                             {
   1920                                 operands[i].mem.segment = ZYDIS_REGISTER_FS;
   1921                             }
   1922                             else
   1923                                 if (!operand->ignore_seg_override &&
   1924                                     instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_GS)
   1925                                 {
   1926                                     operands[i].mem.segment = ZYDIS_REGISTER_GS;
   1927                                 }
   1928                                 else
   1929                                 {
   1930                                     if (operands[i].mem.segment == ZYDIS_REGISTER_NONE)
   1931                                     {
   1932                                         if ((operands[i].mem.base == ZYDIS_REGISTER_RSP) ||
   1933                                             (operands[i].mem.base == ZYDIS_REGISTER_RBP) ||
   1934                                             (operands[i].mem.base == ZYDIS_REGISTER_ESP) ||
   1935                                             (operands[i].mem.base == ZYDIS_REGISTER_EBP) ||
   1936                                             (operands[i].mem.base == ZYDIS_REGISTER_SP) ||
   1937                                             (operands[i].mem.base == ZYDIS_REGISTER_BP))
   1938                                         {
   1939                                             operands[i].mem.segment = ZYDIS_REGISTER_SS;
   1940                                         }
   1941                                         else
   1942                                         {
   1943                                             operands[i].mem.segment = ZYDIS_REGISTER_DS;
   1944                                         }
   1945                                     }
   1946                                 }
   1947         }
   1948 
   1949         ZydisSetOperandSizeAndElementInfo(context, instruction, &operands[i], operand);
   1950         ++operand;
   1951     }
   1952 
   1953 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
   1954     // Fix operand-action for EVEX/MVEX instructions with merge-mask
   1955     if (instruction->avx.mask.mode == ZYDIS_MASK_MODE_MERGING)
   1956     {
   1957         ZYAN_ASSERT(operand_count >= 1);
   1958         switch (operands[0].actions)
   1959         {
   1960         case ZYDIS_OPERAND_ACTION_WRITE:
   1961             if (operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
   1962             {
   1963                 operands[0].actions = ZYDIS_OPERAND_ACTION_CONDWRITE;
   1964             }
   1965             else
   1966             {
   1967                 operands[0].actions = ZYDIS_OPERAND_ACTION_READ_CONDWRITE;
   1968             }
   1969             break;
   1970         case ZYDIS_OPERAND_ACTION_READWRITE:
   1971             operands[0].actions = ZYDIS_OPERAND_ACTION_READ_CONDWRITE;
   1972             break;
   1973         default:
   1974             break;
   1975         }
   1976     }
   1977 #endif
   1978 
   1979     return ZYAN_STATUS_SUCCESS;
   1980 }
   1981 #endif
   1982 
   1983 /* ---------------------------------------------------------------------------------------------- */
   1984 
   1985 #ifndef ZYDIS_MINIMAL_MODE
   1986 /**
   1987  * Sets attributes for the given instruction.
   1988  *
   1989  * @param   state       A pointer to the `ZydisDecoderState` struct.
   1990  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
   1991  * @param   definition  A pointer to the `ZydisInstructionDefinition` struct.
   1992  */
   1993 static void ZydisSetAttributes(ZydisDecoderState* state, ZydisDecodedInstruction* instruction,
   1994     const ZydisInstructionDefinition* definition)
   1995 {
   1996     ZYAN_ASSERT(state);
   1997     ZYAN_ASSERT(instruction);
   1998     ZYAN_ASSERT(definition);
   1999 
   2000     if (definition->cpu_state != ZYDIS_RW_ACTION_NONE)
   2001     {
   2002         static const ZydisInstructionAttributes mapping[ZYDIS_RW_ACTION_MAX_VALUE + 1] =
   2003         {
   2004             /* NONE      */ 0,
   2005             /* READ      */ ZYDIS_ATTRIB_CPU_STATE_CR,
   2006             /* WRITE     */ ZYDIS_ATTRIB_CPU_STATE_CW,
   2007             /* READWRITE */ ZYDIS_ATTRIB_CPU_STATE_CR | ZYDIS_ATTRIB_CPU_STATE_CW
   2008         };
   2009         ZYAN_ASSERT(definition->cpu_state < ZYAN_ARRAY_LENGTH(mapping));
   2010         instruction->attributes |= mapping[definition->cpu_state];
   2011     }
   2012 
   2013     if (definition->fpu_state != ZYDIS_RW_ACTION_NONE)
   2014     {
   2015         static const ZydisInstructionAttributes mapping[ZYDIS_RW_ACTION_MAX_VALUE + 1] =
   2016         {
   2017             /* NONE      */ 0,
   2018             /* READ      */ ZYDIS_ATTRIB_FPU_STATE_CR,
   2019             /* WRITE     */ ZYDIS_ATTRIB_FPU_STATE_CW,
   2020             /* READWRITE */ ZYDIS_ATTRIB_FPU_STATE_CR | ZYDIS_ATTRIB_FPU_STATE_CW
   2021         };
   2022         ZYAN_ASSERT(definition->fpu_state < ZYAN_ARRAY_LENGTH(mapping));
   2023         instruction->attributes |= mapping[definition->fpu_state];
   2024     }
   2025 
   2026     if (definition->xmm_state != ZYDIS_RW_ACTION_NONE)
   2027     {
   2028         static const ZydisInstructionAttributes mapping[ZYDIS_RW_ACTION_MAX_VALUE + 1] =
   2029         {
   2030             /* NONE      */ 0,
   2031             /* READ      */ ZYDIS_ATTRIB_XMM_STATE_CR,
   2032             /* WRITE     */ ZYDIS_ATTRIB_XMM_STATE_CW,
   2033             /* READWRITE */ ZYDIS_ATTRIB_XMM_STATE_CR | ZYDIS_ATTRIB_XMM_STATE_CW
   2034         };
   2035         ZYAN_ASSERT(definition->xmm_state < ZYAN_ARRAY_LENGTH(mapping));
   2036         instruction->attributes |= mapping[definition->xmm_state];
   2037     }
   2038 
   2039     switch (instruction->encoding)
   2040     {
   2041     case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
   2042     {
   2043         const ZydisInstructionDefinitionLEGACY* def =
   2044             (const ZydisInstructionDefinitionLEGACY*)definition;
   2045 
   2046         if (def->is_privileged)
   2047         {
   2048             instruction->attributes |= ZYDIS_ATTRIB_IS_PRIVILEGED;
   2049         }
   2050         if (def->accepts_LOCK)
   2051         {
   2052             instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_LOCK;
   2053             if (state->prefixes.has_lock)
   2054             {
   2055                 instruction->attributes |= ZYDIS_ATTRIB_HAS_LOCK;
   2056                 instruction->raw.prefixes[state->prefixes.offset_lock].type =
   2057                     ZYDIS_PREFIX_TYPE_EFFECTIVE;
   2058             }
   2059         }
   2060         if (def->accepts_REP)
   2061         {
   2062             instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_REP;
   2063         }
   2064         if (def->accepts_REPEREPZ)
   2065         {
   2066             instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_REPE;
   2067         }
   2068         if (def->accepts_REPNEREPNZ)
   2069         {
   2070             instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_REPNE;
   2071         }
   2072         if (def->accepts_BOUND)
   2073         {
   2074             instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_BND;
   2075         }
   2076         if (def->accepts_XACQUIRE)
   2077         {
   2078             instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_XACQUIRE;
   2079         }
   2080         if (def->accepts_XRELEASE)
   2081         {
   2082             instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_XRELEASE;
   2083         }
   2084         if (def->accepts_hle_without_lock)
   2085         {
   2086             instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_HLE_WITHOUT_LOCK;
   2087         }
   2088 
   2089         switch (state->prefixes.group1)
   2090         {
   2091         case 0xF2:
   2092             if (instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_REPNE)
   2093             {
   2094                 instruction->attributes |= ZYDIS_ATTRIB_HAS_REPNE;
   2095                 break;
   2096             }
   2097             if (instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_XACQUIRE)
   2098             {
   2099                 if ((instruction->attributes & ZYDIS_ATTRIB_HAS_LOCK) ||
   2100                     (def->accepts_hle_without_lock))
   2101                 {
   2102                     instruction->attributes |= ZYDIS_ATTRIB_HAS_XACQUIRE;
   2103                     break;
   2104                 }
   2105             }
   2106             if (state->decoder->decoder_mode[ZYDIS_DECODER_MODE_MPX] &&
   2107                 instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_BND)
   2108             {
   2109                 instruction->attributes |= ZYDIS_ATTRIB_HAS_BND;
   2110                 break;
   2111             }
   2112             break;
   2113         case 0xF3:
   2114             if (instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_REP)
   2115             {
   2116                 instruction->attributes |= ZYDIS_ATTRIB_HAS_REP;
   2117                 break;
   2118             }
   2119             if (instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_REPE)
   2120             {
   2121                 instruction->attributes |= ZYDIS_ATTRIB_HAS_REPE;
   2122                 break;
   2123             }
   2124             if (instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_XRELEASE)
   2125             {
   2126                 if ((instruction->attributes & ZYDIS_ATTRIB_HAS_LOCK) ||
   2127                     (def->accepts_hle_without_lock))
   2128                 {
   2129                     instruction->attributes |= ZYDIS_ATTRIB_HAS_XRELEASE;
   2130                     break;
   2131                 }
   2132             }
   2133             break;
   2134         default:
   2135             break;
   2136         }
   2137         if ((instruction->raw.prefixes[state->prefixes.offset_group1].type ==
   2138              ZYDIS_PREFIX_TYPE_IGNORED) &&
   2139             (instruction->attributes & (
   2140              ZYDIS_ATTRIB_HAS_REP | ZYDIS_ATTRIB_HAS_REPE | ZYDIS_ATTRIB_HAS_REPNE |
   2141              ZYDIS_ATTRIB_HAS_BND | ZYDIS_ATTRIB_HAS_XACQUIRE | ZYDIS_ATTRIB_HAS_XRELEASE)))
   2142         {
   2143             instruction->raw.prefixes[state->prefixes.offset_group1].type =
   2144                 ZYDIS_PREFIX_TYPE_EFFECTIVE;
   2145         }
   2146 
   2147         if (def->accepts_branch_hints)
   2148         {
   2149             instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_BRANCH_HINTS;
   2150             switch (state->prefixes.group2)
   2151             {
   2152             case 0x2E:
   2153                 instruction->attributes |= ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN;
   2154                 instruction->raw.prefixes[state->prefixes.offset_group2].type =
   2155                     ZYDIS_PREFIX_TYPE_EFFECTIVE;
   2156                 break;
   2157             case 0x3E:
   2158                 instruction->attributes |= ZYDIS_ATTRIB_HAS_BRANCH_TAKEN;
   2159                 instruction->raw.prefixes[state->prefixes.offset_group2].type =
   2160                     ZYDIS_PREFIX_TYPE_EFFECTIVE;
   2161                 break;
   2162             default:
   2163                 break;
   2164             }
   2165         }
   2166 
   2167         if (def->accepts_NOTRACK)
   2168         {
   2169             instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_NOTRACK;
   2170             if (state->decoder->decoder_mode[ZYDIS_DECODER_MODE_CET] &&
   2171                 (state->prefixes.offset_notrack >= 0))
   2172             {
   2173                 instruction->attributes |= ZYDIS_ATTRIB_HAS_NOTRACK;
   2174                 instruction->raw.prefixes[state->prefixes.offset_notrack].type =
   2175                     ZYDIS_PREFIX_TYPE_EFFECTIVE;
   2176             }
   2177         }
   2178 
   2179         if (def->accepts_segment && !def->accepts_branch_hints)
   2180         {
   2181             instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_SEGMENT;
   2182             if (state->prefixes.effective_segment &&
   2183                 !(instruction->attributes & ZYDIS_ATTRIB_HAS_NOTRACK))
   2184             {
   2185                 switch (state->prefixes.effective_segment)
   2186                 {
   2187                 case 0x2E:
   2188                     instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_CS;
   2189                     break;
   2190                 case 0x36:
   2191                     instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
   2192                     break;
   2193                 case 0x3E:
   2194                     instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
   2195                     break;
   2196                 case 0x26:
   2197                     instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_ES;
   2198                     break;
   2199                 case 0x64:
   2200                     instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_FS;
   2201                     break;
   2202                 case 0x65:
   2203                     instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_GS;
   2204                     break;
   2205                 default:
   2206                     ZYAN_UNREACHABLE;
   2207                 }
   2208             }
   2209             if (instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT)
   2210             {
   2211                 instruction->raw.prefixes[state->prefixes.offset_segment].type =
   2212                     ZYDIS_PREFIX_TYPE_EFFECTIVE;
   2213             }
   2214         }
   2215 
   2216         break;
   2217     }
   2218     case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
   2219     case ZYDIS_INSTRUCTION_ENCODING_XOP:
   2220     case ZYDIS_INSTRUCTION_ENCODING_VEX:
   2221     case ZYDIS_INSTRUCTION_ENCODING_EVEX:
   2222     case ZYDIS_INSTRUCTION_ENCODING_MVEX:
   2223         if (definition->accepts_segment)
   2224         {
   2225             instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_SEGMENT;
   2226             if (state->prefixes.effective_segment)
   2227             {
   2228                 switch (state->prefixes.effective_segment)
   2229                 {
   2230                 case 0x2E:
   2231                     instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_CS;
   2232                     break;
   2233                 case 0x36:
   2234                     instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
   2235                     break;
   2236                 case 0x3E:
   2237                     instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
   2238                     break;
   2239                 case 0x26:
   2240                     instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_ES;
   2241                     break;
   2242                 case 0x64:
   2243                     instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_FS;
   2244                     break;
   2245                 case 0x65:
   2246                     instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_GS;
   2247                     break;
   2248                 default:
   2249                     ZYAN_UNREACHABLE;
   2250                 }
   2251             }
   2252             if (instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT)
   2253             {
   2254                 instruction->raw.prefixes[state->prefixes.offset_segment].type =
   2255                     ZYDIS_PREFIX_TYPE_EFFECTIVE;
   2256             }
   2257         }
   2258         break;
   2259     default:
   2260         ZYAN_UNREACHABLE;
   2261     }
   2262 }
   2263 #endif
   2264 
   2265 #ifndef ZYDIS_MINIMAL_MODE
   2266 /**
   2267  * Sets AVX-specific information for the given instruction.
   2268  *
   2269  * @param   context     A pointer to the `ZydisDecoderContext` struct.
   2270  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
   2271  * @param   definition  A pointer to the `ZydisInstructionDefinition` struct.
   2272  *
   2273  * Information set for `XOP`:
   2274  * - Vector Length
   2275  *
   2276  * Information set for `VEX`:
   2277  * - Vector length
   2278  * - Static broadcast-factor
   2279  *
   2280  * Information set for `EVEX`:
   2281  * - Vector length
   2282  * - Broadcast-factor (static and dynamic)
   2283  * - Rounding-mode and SAE
   2284  * - Mask mode
   2285  * - Compressed 8-bit displacement scale-factor
   2286  *
   2287  * Information set for `MVEX`:
   2288  * - Vector length
   2289  * - Broadcast-factor (static and dynamic)
   2290  * - Rounding-mode and SAE
   2291  * - Swizzle- and conversion-mode
   2292  * - Mask mode
   2293  * - Eviction hint
   2294  * - Compressed 8-bit displacement scale-factor
   2295  */
   2296 static void ZydisSetAVXInformation(ZydisDecoderContext* context,
   2297     ZydisDecodedInstruction* instruction, const ZydisInstructionDefinition* definition)
   2298 {
   2299     ZYAN_ASSERT(context);
   2300     ZYAN_ASSERT(instruction);
   2301     ZYAN_ASSERT(definition);
   2302 
   2303     switch (instruction->encoding)
   2304     {
   2305     case ZYDIS_INSTRUCTION_ENCODING_XOP:
   2306     {
   2307         // Vector length
   2308         static const ZyanU16 lookup[2] =
   2309         {
   2310             128,
   2311             256
   2312         };
   2313         ZYAN_ASSERT(context->vector_unified.LL < ZYAN_ARRAY_LENGTH(lookup));
   2314         instruction->avx.vector_length = lookup[context->vector_unified.LL];
   2315         break;
   2316     }
   2317     case ZYDIS_INSTRUCTION_ENCODING_VEX:
   2318     {
   2319         // Vector length
   2320         static const ZyanU16 lookup[2] =
   2321         {
   2322             128,
   2323             256
   2324         };
   2325         ZYAN_ASSERT(context->vector_unified.LL < ZYAN_ARRAY_LENGTH(lookup));
   2326         instruction->avx.vector_length = lookup[context->vector_unified.LL];
   2327 
   2328         // Static broadcast-factor
   2329         const ZydisInstructionDefinitionVEX* def =
   2330             (const ZydisInstructionDefinitionVEX*)definition;
   2331         if (def->broadcast)
   2332         {
   2333             instruction->avx.broadcast.is_static = ZYAN_TRUE;
   2334             static ZydisBroadcastMode broadcasts[ZYDIS_VEX_STATIC_BROADCAST_MAX_VALUE + 1] =
   2335             {
   2336                 ZYDIS_BROADCAST_MODE_INVALID,
   2337                 ZYDIS_BROADCAST_MODE_1_TO_2,
   2338                 ZYDIS_BROADCAST_MODE_1_TO_4,
   2339                 ZYDIS_BROADCAST_MODE_1_TO_8,
   2340                 ZYDIS_BROADCAST_MODE_1_TO_16,
   2341                 ZYDIS_BROADCAST_MODE_1_TO_32,
   2342                 ZYDIS_BROADCAST_MODE_2_TO_4
   2343             };
   2344             instruction->avx.broadcast.mode = broadcasts[def->broadcast];
   2345         }
   2346         break;
   2347     }
   2348     case ZYDIS_INSTRUCTION_ENCODING_EVEX:
   2349     {
   2350 #ifndef ZYDIS_DISABLE_AVX512
   2351         const ZydisInstructionDefinitionEVEX* def =
   2352             (const ZydisInstructionDefinitionEVEX*)definition;
   2353 
   2354         // Vector length
   2355         ZyanU8 vector_length = context->vector_unified.LL;
   2356         if (def->vector_length)
   2357         {
   2358             vector_length = def->vector_length - 1;
   2359         }
   2360         static const ZyanU16 lookup[3] =
   2361         {
   2362             128,
   2363             256,
   2364             512
   2365         };
   2366         ZYAN_ASSERT(vector_length < ZYAN_ARRAY_LENGTH(lookup));
   2367         instruction->avx.vector_length = lookup[vector_length];
   2368 
   2369         context->evex.tuple_type = def->tuple_type;
   2370         if (def->tuple_type)
   2371         {
   2372             ZYAN_ASSERT(instruction->raw.modrm.mod != 3);
   2373             ZYAN_ASSERT(def->element_size);
   2374 
   2375             // Element size
   2376             static const ZyanU8 element_sizes[ZYDIS_IELEMENT_SIZE_MAX_VALUE + 1] =
   2377             {
   2378                   0,   8,  16,  32,  64, 128
   2379             };
   2380             ZYAN_ASSERT(def->element_size < ZYAN_ARRAY_LENGTH(element_sizes));
   2381             context->evex.element_size = element_sizes[def->element_size];
   2382 
   2383             // Compressed disp8 scale and broadcast-factor
   2384             switch (def->tuple_type)
   2385             {
   2386             case ZYDIS_TUPLETYPE_FV:
   2387             {
   2388                 const ZyanU8 evex_b = instruction->raw.evex.b;
   2389                 ZYAN_ASSERT(evex_b < 2);
   2390                 ZYAN_ASSERT(!evex_b || ((!context->vector_unified.W && (context->evex.element_size == 16 ||
   2391                                                                         context->evex.element_size == 32)) ||
   2392                                         ( context->vector_unified.W &&  context->evex.element_size == 64)));
   2393                 ZYAN_ASSERT(!evex_b || def->functionality == ZYDIS_EVEX_FUNC_BC);
   2394 
   2395                 static const ZyanU8 scales[2][3][3] =
   2396                 {
   2397                     /*B0*/ { /*16*/ { 16, 32, 64 }, /*32*/ { 16, 32, 64 }, /*64*/ { 16, 32, 64 } },
   2398                     /*B1*/ { /*16*/ {  2,  2,  2 }, /*32*/ {  4,  4,  4 }, /*64*/ {  8,  8,  8 } }
   2399                 };
   2400                 static const ZydisBroadcastMode broadcasts[2][3][3] =
   2401                 {
   2402                     /*B0*/
   2403                     {
   2404                         /*16*/
   2405                         {
   2406                             ZYDIS_BROADCAST_MODE_INVALID,
   2407                             ZYDIS_BROADCAST_MODE_INVALID,
   2408                             ZYDIS_BROADCAST_MODE_INVALID
   2409                         },
   2410                         /*32*/
   2411                         {
   2412                             ZYDIS_BROADCAST_MODE_INVALID,
   2413                             ZYDIS_BROADCAST_MODE_INVALID,
   2414                             ZYDIS_BROADCAST_MODE_INVALID
   2415                         },
   2416                         /*64*/
   2417                         {
   2418                             ZYDIS_BROADCAST_MODE_INVALID,
   2419                             ZYDIS_BROADCAST_MODE_INVALID,
   2420                             ZYDIS_BROADCAST_MODE_INVALID
   2421                         }
   2422                     },
   2423                     /*B1*/
   2424                     {
   2425                         /*16*/
   2426                         {
   2427                             ZYDIS_BROADCAST_MODE_1_TO_8,
   2428                             ZYDIS_BROADCAST_MODE_1_TO_16,
   2429                             ZYDIS_BROADCAST_MODE_1_TO_32
   2430                         },
   2431                         /*32*/
   2432                         {
   2433                             ZYDIS_BROADCAST_MODE_1_TO_4,
   2434                             ZYDIS_BROADCAST_MODE_1_TO_8,
   2435                             ZYDIS_BROADCAST_MODE_1_TO_16
   2436                         },
   2437                         /*64*/
   2438                         {
   2439                             ZYDIS_BROADCAST_MODE_1_TO_2,
   2440                             ZYDIS_BROADCAST_MODE_1_TO_4,
   2441                             ZYDIS_BROADCAST_MODE_1_TO_8
   2442                         }
   2443                     }
   2444                 };
   2445 
   2446                 const ZyanU8 size_index = context->evex.element_size >> 5;
   2447                 ZYAN_ASSERT(size_index < 3);
   2448 
   2449                 context->cd8_scale = scales[evex_b][size_index][vector_length];
   2450                 instruction->avx.broadcast.mode = broadcasts[evex_b][size_index][vector_length];
   2451                 break;
   2452             }
   2453             case ZYDIS_TUPLETYPE_HV:
   2454             {
   2455                 const ZyanU8 evex_b = instruction->raw.evex.b;
   2456                 ZYAN_ASSERT(evex_b < 2);
   2457                 ZYAN_ASSERT(!context->vector_unified.W);
   2458                 ZYAN_ASSERT((context->evex.element_size == 16) ||
   2459                             (context->evex.element_size == 32));
   2460                 ZYAN_ASSERT(!evex_b || def->functionality == ZYDIS_EVEX_FUNC_BC);
   2461 
   2462                 static const ZyanU8 scales[2][2][3] =
   2463                 {
   2464                     /*B0*/ { /*16*/ {  8, 16, 32 }, /*32*/ {  8, 16, 32 } },
   2465                     /*B1*/ { /*16*/ {  2,  2,  2 }, /*32*/ {  4,  4,  4 } }
   2466                 };
   2467                 static const ZydisBroadcastMode broadcasts[2][2][3] =
   2468                 {
   2469                     /*B0*/
   2470                     {
   2471                         /*16*/
   2472                         {
   2473                             ZYDIS_BROADCAST_MODE_INVALID,
   2474                             ZYDIS_BROADCAST_MODE_INVALID,
   2475                             ZYDIS_BROADCAST_MODE_INVALID
   2476                         },
   2477                         /*32*/
   2478                         {
   2479                             ZYDIS_BROADCAST_MODE_INVALID,
   2480                             ZYDIS_BROADCAST_MODE_INVALID,
   2481                             ZYDIS_BROADCAST_MODE_INVALID
   2482                         }
   2483                     },
   2484                     /*B1*/
   2485                     {
   2486                         /*16*/
   2487                         {
   2488                             ZYDIS_BROADCAST_MODE_1_TO_4,
   2489                             ZYDIS_BROADCAST_MODE_1_TO_8,
   2490                             ZYDIS_BROADCAST_MODE_1_TO_16
   2491                         },
   2492                         /*32*/
   2493                         {
   2494                             ZYDIS_BROADCAST_MODE_1_TO_2,
   2495                             ZYDIS_BROADCAST_MODE_1_TO_4,
   2496                             ZYDIS_BROADCAST_MODE_1_TO_8
   2497                         }
   2498                     }
   2499                 };
   2500 
   2501                 const ZyanU8 size_index = context->evex.element_size >> 5;
   2502                 ZYAN_ASSERT(size_index < 3);
   2503 
   2504                 context->cd8_scale = scales[evex_b][size_index][vector_length];
   2505                 instruction->avx.broadcast.mode = broadcasts[evex_b][size_index][vector_length];
   2506                 break;
   2507             }
   2508             case ZYDIS_TUPLETYPE_FVM:
   2509             {
   2510                 static const ZyanU8 scales[3] =
   2511                 {
   2512                     16, 32, 64
   2513                 };
   2514                 context->cd8_scale = scales[vector_length];
   2515                 break;
   2516             }
   2517             case ZYDIS_TUPLETYPE_GSCAT:
   2518                 switch (context->vector_unified.W)
   2519                 {
   2520                 case 0:
   2521                     ZYAN_ASSERT(context->evex.element_size == 32);
   2522                     break;
   2523                 case 1:
   2524                     ZYAN_ASSERT(context->evex.element_size == 64);
   2525                     break;
   2526                 default:
   2527                     ZYAN_UNREACHABLE;
   2528                 }
   2529                 ZYAN_FALLTHROUGH;
   2530             case ZYDIS_TUPLETYPE_T1S:
   2531             {
   2532                 static const ZyanU8 scales[6] =
   2533                 {
   2534                     /*   */  0,
   2535                     /*  8*/  1,
   2536                     /* 16*/  2,
   2537                     /* 32*/  4,
   2538                     /* 64*/  8,
   2539                     /*128*/ 16,
   2540                 };
   2541                 ZYAN_ASSERT(def->element_size < ZYAN_ARRAY_LENGTH(scales));
   2542                 context->cd8_scale = scales[def->element_size];
   2543                 break;
   2544             };
   2545             case ZYDIS_TUPLETYPE_T1F:
   2546             {
   2547                 static const ZyanU8 scales[3] =
   2548                 {
   2549                     /* 16*/ 2,
   2550                     /* 32*/ 4,
   2551                     /* 64*/ 8
   2552                 };
   2553 
   2554                 const ZyanU8 size_index = context->evex.element_size >> 5;
   2555                 ZYAN_ASSERT(size_index < 3);
   2556 
   2557                 context->cd8_scale = scales[size_index];
   2558                 break;
   2559             }
   2560             case ZYDIS_TUPLETYPE_T1_4X:
   2561                 ZYAN_ASSERT(context->evex.element_size == 32);
   2562                 ZYAN_ASSERT(context->vector_unified.W == 0);
   2563                 context->cd8_scale = 16;
   2564                 break;
   2565             case ZYDIS_TUPLETYPE_T2:
   2566                 switch (context->vector_unified.W)
   2567                 {
   2568                 case 0:
   2569                     ZYAN_ASSERT(context->evex.element_size == 32);
   2570                     context->cd8_scale = 8;
   2571                     break;
   2572                 case 1:
   2573                     ZYAN_ASSERT(context->evex.element_size == 64);
   2574                     ZYAN_ASSERT((instruction->avx.vector_length == 256) ||
   2575                                 (instruction->avx.vector_length == 512));
   2576                     context->cd8_scale = 16;
   2577                     break;
   2578                 default:
   2579                     ZYAN_UNREACHABLE;
   2580                 }
   2581                 break;
   2582             case ZYDIS_TUPLETYPE_T4:
   2583                 switch (context->vector_unified.W)
   2584                 {
   2585                 case 0:
   2586                     ZYAN_ASSERT(context->evex.element_size == 32);
   2587                     ZYAN_ASSERT((instruction->avx.vector_length == 256) ||
   2588                                 (instruction->avx.vector_length == 512));
   2589                     context->cd8_scale = 16;
   2590                     break;
   2591                 case 1:
   2592                     ZYAN_ASSERT(context->evex.element_size == 64);
   2593                     ZYAN_ASSERT(instruction->avx.vector_length == 512);
   2594                     context->cd8_scale = 32;
   2595                     break;
   2596                 default:
   2597                     ZYAN_UNREACHABLE;
   2598                 }
   2599                 break;
   2600             case ZYDIS_TUPLETYPE_T8:
   2601                 ZYAN_ASSERT(!context->vector_unified.W);
   2602                 ZYAN_ASSERT(instruction->avx.vector_length == 512);
   2603                 ZYAN_ASSERT(context->evex.element_size == 32);
   2604                 context->cd8_scale = 32;
   2605                 break;
   2606             case ZYDIS_TUPLETYPE_HVM:
   2607             {
   2608                 static const ZyanU8 scales[3] =
   2609                 {
   2610                      8, 16, 32
   2611                 };
   2612                 context->cd8_scale = scales[vector_length];
   2613                 break;
   2614             }
   2615             case ZYDIS_TUPLETYPE_QVM:
   2616             {
   2617                 static const ZyanU8 scales[3] =
   2618                 {
   2619                      4,  8, 16
   2620                 };
   2621                 context->cd8_scale = scales[vector_length];
   2622                 break;
   2623             }
   2624             case ZYDIS_TUPLETYPE_OVM:
   2625             {
   2626                 static const ZyanU8 scales[3] =
   2627                 {
   2628                      2,  4,  8
   2629                 };
   2630                 context->cd8_scale = scales[vector_length];
   2631                 break;
   2632             }
   2633             case ZYDIS_TUPLETYPE_M128:
   2634                 context->cd8_scale = 16;
   2635                 break;
   2636             case ZYDIS_TUPLETYPE_DUP:
   2637             {
   2638                 static const ZyanU8 scales[3] =
   2639                 {
   2640                      8, 32, 64
   2641                 };
   2642                 context->cd8_scale = scales[vector_length];
   2643                 break;
   2644             }
   2645             case ZYDIS_TUPLETYPE_QUARTER:
   2646             {
   2647                 const ZyanU8 evex_b = instruction->raw.evex.b;
   2648                 ZYAN_ASSERT(evex_b < 2);
   2649                 ZYAN_ASSERT(!context->vector_unified.W);
   2650                 ZYAN_ASSERT(context->evex.element_size == 16);
   2651                 ZYAN_ASSERT(!evex_b || def->functionality == ZYDIS_EVEX_FUNC_BC);
   2652 
   2653                 static const ZyanU8 scales[2][3] =
   2654                 {
   2655                     /*B0*/ {  4,  8, 16 },
   2656                     /*B1*/ {  2,  2,  2 }
   2657                 };
   2658                 static const ZydisBroadcastMode broadcasts[2][3] =
   2659                 {
   2660                     /*B0*/
   2661                     {
   2662                         ZYDIS_BROADCAST_MODE_INVALID,
   2663                         ZYDIS_BROADCAST_MODE_INVALID,
   2664                         ZYDIS_BROADCAST_MODE_INVALID
   2665                     },
   2666                     /*B1*/
   2667                     {
   2668                         ZYDIS_BROADCAST_MODE_1_TO_2,
   2669                         ZYDIS_BROADCAST_MODE_1_TO_4,
   2670                         ZYDIS_BROADCAST_MODE_1_TO_8
   2671                     }
   2672                 };
   2673                 context->cd8_scale = scales[evex_b][vector_length];
   2674                 instruction->avx.broadcast.mode = broadcasts[evex_b][vector_length];
   2675                 break;
   2676             }
   2677             default:
   2678                 ZYAN_UNREACHABLE;
   2679             }
   2680         } else
   2681         {
   2682             ZYAN_ASSERT(instruction->raw.modrm.mod == 3);
   2683         }
   2684 
   2685         // Static broadcast-factor
   2686         if (def->broadcast)
   2687         {
   2688             ZYAN_ASSERT(!instruction->avx.broadcast.mode);
   2689             instruction->avx.broadcast.is_static = ZYAN_TRUE;
   2690             static const ZydisBroadcastMode broadcasts[ZYDIS_EVEX_STATIC_BROADCAST_MAX_VALUE + 1] =
   2691             {
   2692                 ZYDIS_BROADCAST_MODE_INVALID,
   2693                 ZYDIS_BROADCAST_MODE_1_TO_2,
   2694                 ZYDIS_BROADCAST_MODE_1_TO_4,
   2695                 ZYDIS_BROADCAST_MODE_1_TO_8,
   2696                 ZYDIS_BROADCAST_MODE_1_TO_16,
   2697                 ZYDIS_BROADCAST_MODE_1_TO_32,
   2698                 ZYDIS_BROADCAST_MODE_1_TO_64,
   2699                 ZYDIS_BROADCAST_MODE_2_TO_4,
   2700                 ZYDIS_BROADCAST_MODE_2_TO_8,
   2701                 ZYDIS_BROADCAST_MODE_2_TO_16,
   2702                 ZYDIS_BROADCAST_MODE_4_TO_8,
   2703                 ZYDIS_BROADCAST_MODE_4_TO_16,
   2704                 ZYDIS_BROADCAST_MODE_8_TO_16
   2705             };
   2706             ZYAN_ASSERT(def->broadcast < ZYAN_ARRAY_LENGTH(broadcasts));
   2707             instruction->avx.broadcast.mode = broadcasts[def->broadcast];
   2708         }
   2709 
   2710         // Rounding mode and SAE
   2711         if (instruction->raw.evex.b)
   2712         {
   2713             switch (def->functionality)
   2714             {
   2715             case ZYDIS_EVEX_FUNC_INVALID:
   2716             case ZYDIS_EVEX_FUNC_BC:
   2717                 // Noting to do here
   2718                 break;
   2719             case ZYDIS_EVEX_FUNC_RC:
   2720                 instruction->avx.rounding.mode = ZYDIS_ROUNDING_MODE_RN + context->vector_unified.LL;
   2721                 ZYAN_FALLTHROUGH;
   2722             case ZYDIS_EVEX_FUNC_SAE:
   2723                 instruction->avx.has_sae = ZYAN_TRUE;
   2724                 break;
   2725             default:
   2726                 ZYAN_UNREACHABLE;
   2727             }
   2728         }
   2729 
   2730         // Mask
   2731         instruction->avx.mask.reg = ZYDIS_REGISTER_K0 + instruction->raw.evex.aaa;
   2732         switch (def->mask_override)
   2733         {
   2734         case ZYDIS_MASK_OVERRIDE_DEFAULT:
   2735             instruction->avx.mask.mode = ZYDIS_MASK_MODE_MERGING + instruction->raw.evex.z;
   2736             break;
   2737         case ZYDIS_MASK_OVERRIDE_ZEROING:
   2738             instruction->avx.mask.mode = ZYDIS_MASK_MODE_ZEROING;
   2739             break;
   2740         case ZYDIS_MASK_OVERRIDE_CONTROL:
   2741             instruction->avx.mask.mode = ZYDIS_MASK_MODE_CONTROL + instruction->raw.evex.z;
   2742             break;
   2743         default:
   2744             ZYAN_UNREACHABLE;
   2745         }
   2746         if (!instruction->raw.evex.aaa)
   2747         {
   2748             instruction->avx.mask.mode = ZYDIS_MASK_MODE_DISABLED;
   2749         }
   2750 #else
   2751         ZYAN_UNREACHABLE;
   2752 #endif
   2753         break;
   2754     }
   2755     case ZYDIS_INSTRUCTION_ENCODING_MVEX:
   2756     {
   2757 #ifndef ZYDIS_DISABLE_KNC
   2758         // Vector length
   2759         instruction->avx.vector_length = 512;
   2760 
   2761         const ZydisInstructionDefinitionMVEX* def =
   2762             (const ZydisInstructionDefinitionMVEX*)definition;
   2763 
   2764         // Static broadcast-factor
   2765         ZyanU8 index = def->has_element_granularity;
   2766         ZYAN_ASSERT(!index || !def->broadcast);
   2767         if (!index && def->broadcast)
   2768         {
   2769             instruction->avx.broadcast.is_static = ZYAN_TRUE;
   2770             switch (def->broadcast)
   2771             {
   2772             case ZYDIS_MVEX_STATIC_BROADCAST_1_TO_8:
   2773                 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_8;
   2774                 index = 1;
   2775                 break;
   2776             case ZYDIS_MVEX_STATIC_BROADCAST_1_TO_16:
   2777                 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_16;
   2778                 index = 1;
   2779                 break;
   2780             case ZYDIS_MVEX_STATIC_BROADCAST_4_TO_8:
   2781                 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_8;
   2782                 index = 2;
   2783                 break;
   2784             case ZYDIS_MVEX_STATIC_BROADCAST_4_TO_16:
   2785                 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_16;
   2786                 index = 2;
   2787                 break;
   2788             default:
   2789                 ZYAN_UNREACHABLE;
   2790             }
   2791         }
   2792 
   2793         // Compressed disp8 scale and broadcast-factor
   2794         switch (def->functionality)
   2795         {
   2796         case ZYDIS_MVEX_FUNC_IGNORED:
   2797         case ZYDIS_MVEX_FUNC_INVALID:
   2798         case ZYDIS_MVEX_FUNC_RC:
   2799         case ZYDIS_MVEX_FUNC_SAE:
   2800         case ZYDIS_MVEX_FUNC_SWIZZLE_32:
   2801         case ZYDIS_MVEX_FUNC_SWIZZLE_64:
   2802             // Nothing to do here
   2803             break;
   2804         case ZYDIS_MVEX_FUNC_F_32:
   2805         case ZYDIS_MVEX_FUNC_I_32:
   2806         case ZYDIS_MVEX_FUNC_F_64:
   2807         case ZYDIS_MVEX_FUNC_I_64:
   2808             context->cd8_scale = 64;
   2809             break;
   2810         case ZYDIS_MVEX_FUNC_SF_32:
   2811         case ZYDIS_MVEX_FUNC_SF_32_BCST:
   2812         case ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16:
   2813         case ZYDIS_MVEX_FUNC_UF_32:
   2814         {
   2815             static const ZyanU8 lookup[3][8] =
   2816             {
   2817                 { 64,  4, 16, 32, 16, 16, 32, 32 },
   2818                 {  4,  0,  0,  2,  1,  1,  2,  2 },
   2819                 { 16,  0,  0,  8,  4,  4,  8,  8 }
   2820             };
   2821             ZYAN_ASSERT(instruction->raw.mvex.SSS < ZYAN_ARRAY_LENGTH(lookup[index]));
   2822             context->cd8_scale = lookup[index][instruction->raw.mvex.SSS];
   2823             break;
   2824         }
   2825         case ZYDIS_MVEX_FUNC_SI_32:
   2826         case ZYDIS_MVEX_FUNC_UI_32:
   2827         case ZYDIS_MVEX_FUNC_SI_32_BCST:
   2828         case ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16:
   2829         {
   2830             static const ZyanU8 lookup[3][8] =
   2831             {
   2832                 { 64,  4, 16,  0, 16, 16, 32, 32 },
   2833                 {  4,  0,  0,  0,  1,  1,  2,  2 },
   2834                 { 16,  0,  0,  0,  4,  4,  8,  8 }
   2835             };
   2836             ZYAN_ASSERT(instruction->raw.mvex.SSS < ZYAN_ARRAY_LENGTH(lookup[index]));
   2837             context->cd8_scale = lookup[index][instruction->raw.mvex.SSS];
   2838             break;
   2839         }
   2840         case ZYDIS_MVEX_FUNC_SF_64:
   2841         case ZYDIS_MVEX_FUNC_UF_64:
   2842         case ZYDIS_MVEX_FUNC_SI_64:
   2843         case ZYDIS_MVEX_FUNC_UI_64:
   2844         {
   2845             static const ZyanU8 lookup[3][3] =
   2846             {
   2847                 { 64,  8, 32 },
   2848                 {  8,  0,  0 },
   2849                 { 32,  0,  0 }
   2850             };
   2851             ZYAN_ASSERT(instruction->raw.mvex.SSS < ZYAN_ARRAY_LENGTH(lookup[index]));
   2852             context->cd8_scale = lookup[index][instruction->raw.mvex.SSS];
   2853             break;
   2854         }
   2855         case ZYDIS_MVEX_FUNC_DF_32:
   2856         case ZYDIS_MVEX_FUNC_DI_32:
   2857         {
   2858             static const ZyanU8 lookup[2][8] =
   2859             {
   2860                 { 64,  0,  0, 32, 16, 16, 32, 32 },
   2861                 {  4,  0,  0,  2,  1,  1,  2,  2 }
   2862             };
   2863             ZYAN_ASSERT(index < 2);
   2864             ZYAN_ASSERT(instruction->raw.mvex.SSS < ZYAN_ARRAY_LENGTH(lookup[index]));
   2865             context->cd8_scale = lookup[index][instruction->raw.mvex.SSS];
   2866             break;
   2867         }
   2868         case ZYDIS_MVEX_FUNC_DF_64:
   2869         case ZYDIS_MVEX_FUNC_DI_64:
   2870         {
   2871             static const ZyanU8 lookup[2][1] =
   2872             {
   2873                 { 64 },
   2874                 {  8 }
   2875             };
   2876             ZYAN_ASSERT(index < 2);
   2877             ZYAN_ASSERT(instruction->raw.mvex.SSS < ZYAN_ARRAY_LENGTH(lookup[index]));
   2878             context->cd8_scale = lookup[index][instruction->raw.mvex.SSS];
   2879             break;
   2880         }
   2881         default:
   2882             ZYAN_UNREACHABLE;
   2883         }
   2884 
   2885         // Rounding mode, sae, swizzle, convert
   2886         context->mvex.functionality = def->functionality;
   2887         switch (def->functionality)
   2888         {
   2889         case ZYDIS_MVEX_FUNC_IGNORED:
   2890         case ZYDIS_MVEX_FUNC_INVALID:
   2891         case ZYDIS_MVEX_FUNC_F_32:
   2892         case ZYDIS_MVEX_FUNC_I_32:
   2893         case ZYDIS_MVEX_FUNC_F_64:
   2894         case ZYDIS_MVEX_FUNC_I_64:
   2895             // Nothing to do here
   2896             break;
   2897         case ZYDIS_MVEX_FUNC_RC:
   2898             instruction->avx.rounding.mode = ZYDIS_ROUNDING_MODE_RN + (instruction->raw.mvex.SSS & 3);
   2899             ZYAN_FALLTHROUGH;
   2900         case ZYDIS_MVEX_FUNC_SAE:
   2901             if (instruction->raw.mvex.SSS >= 4)
   2902             {
   2903                 instruction->avx.has_sae = ZYAN_TRUE;
   2904             }
   2905             break;
   2906         case ZYDIS_MVEX_FUNC_SWIZZLE_32:
   2907         case ZYDIS_MVEX_FUNC_SWIZZLE_64:
   2908             instruction->avx.swizzle.mode = ZYDIS_SWIZZLE_MODE_DCBA + instruction->raw.mvex.SSS;
   2909             break;
   2910         case ZYDIS_MVEX_FUNC_SF_32:
   2911         case ZYDIS_MVEX_FUNC_SF_32_BCST:
   2912         case ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16:
   2913             switch (instruction->raw.mvex.SSS)
   2914             {
   2915             case 0:
   2916                 break;
   2917             case 1:
   2918                 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_16;
   2919                 break;
   2920             case 2:
   2921                 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_16;
   2922                 break;
   2923             case 3:
   2924                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_FLOAT16;
   2925                 break;
   2926             case 4:
   2927                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT8;
   2928                 break;
   2929             case 5:
   2930                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT8;
   2931                 break;
   2932             case 6:
   2933                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT16;
   2934                 break;
   2935             case 7:
   2936                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT16;
   2937                 break;
   2938             default:
   2939                 ZYAN_UNREACHABLE;
   2940             }
   2941             break;
   2942         case ZYDIS_MVEX_FUNC_SI_32:
   2943         case ZYDIS_MVEX_FUNC_SI_32_BCST:
   2944         case ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16:
   2945             switch (instruction->raw.mvex.SSS)
   2946             {
   2947             case 0:
   2948                 break;
   2949             case 1:
   2950                 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_16;
   2951                 break;
   2952             case 2:
   2953                 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_16;
   2954                 break;
   2955             case 4:
   2956                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT8;
   2957                 break;
   2958             case 5:
   2959                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT8;
   2960                 break;
   2961             case 6:
   2962                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT16;
   2963                 break;
   2964             case 7:
   2965                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT16;
   2966                 break;
   2967             default:
   2968                 ZYAN_UNREACHABLE;
   2969             }
   2970             break;
   2971         case ZYDIS_MVEX_FUNC_SF_64:
   2972         case ZYDIS_MVEX_FUNC_SI_64:
   2973             switch (instruction->raw.mvex.SSS)
   2974             {
   2975             case 0:
   2976                 break;
   2977             case 1:
   2978                 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_8;
   2979                 break;
   2980             case 2:
   2981                 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_8;
   2982                 break;
   2983             default:
   2984                 ZYAN_UNREACHABLE;
   2985             }
   2986             break;
   2987         case ZYDIS_MVEX_FUNC_UF_32:
   2988         case ZYDIS_MVEX_FUNC_DF_32:
   2989             switch (instruction->raw.mvex.SSS)
   2990             {
   2991             case 0:
   2992                 break;
   2993             case 3:
   2994                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_FLOAT16;
   2995                 break;
   2996             case 4:
   2997                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT8;
   2998                 break;
   2999             case 5:
   3000                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT8;
   3001                 break;
   3002             case 6:
   3003                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT16;
   3004                 break;
   3005             case 7:
   3006                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT16;
   3007                 break;
   3008             default:
   3009                 ZYAN_UNREACHABLE;
   3010             }
   3011             break;
   3012         case ZYDIS_MVEX_FUNC_UF_64:
   3013         case ZYDIS_MVEX_FUNC_DF_64:
   3014             break;
   3015         case ZYDIS_MVEX_FUNC_UI_32:
   3016         case ZYDIS_MVEX_FUNC_DI_32:
   3017             switch (instruction->raw.mvex.SSS)
   3018             {
   3019             case 0:
   3020                 break;
   3021             case 4:
   3022                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT8;
   3023                 break;
   3024             case 5:
   3025                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT8;
   3026                 break;
   3027             case 6:
   3028                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT16;
   3029                 break;
   3030             case 7:
   3031                 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT16;
   3032                 break;
   3033             default:
   3034                 ZYAN_UNREACHABLE;
   3035             }
   3036             break;
   3037         case ZYDIS_MVEX_FUNC_UI_64:
   3038         case ZYDIS_MVEX_FUNC_DI_64:
   3039             break;
   3040         default:
   3041             ZYAN_UNREACHABLE;
   3042         }
   3043 
   3044         // Eviction hint
   3045         if ((instruction->raw.modrm.mod != 3) && instruction->raw.mvex.E)
   3046         {
   3047             instruction->avx.has_eviction_hint = ZYAN_TRUE;
   3048         }
   3049 
   3050         // Mask
   3051         instruction->avx.mask.mode = ZYDIS_MASK_MODE_MERGING;
   3052         instruction->avx.mask.reg = ZYDIS_REGISTER_K0 + instruction->raw.mvex.kkk;
   3053 #else
   3054         ZYAN_UNREACHABLE;
   3055 #endif
   3056         break;
   3057     }
   3058     default:
   3059         // Nothing to do here
   3060         break;
   3061     }
   3062 }
   3063 #endif
   3064 
   3065 /* ---------------------------------------------------------------------------------------------- */
   3066 /* Physical instruction decoding                                                                  */
   3067 /* ---------------------------------------------------------------------------------------------- */
   3068 
   3069 /**
   3070  * Collects optional instruction prefixes.
   3071  *
   3072  * @param   state     A pointer to the `ZydisDecoderState` struct.
   3073  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
   3074  *
   3075  * @return  A zyan status code.
   3076  *
   3077  * This function sets the corresponding flag for each prefix and automatically decodes the last
   3078  * `REX`-prefix (if exists).
   3079  */
   3080 static ZyanStatus ZydisCollectOptionalPrefixes(ZydisDecoderState* state,
   3081     ZydisDecodedInstruction* instruction)
   3082 {
   3083     ZYAN_ASSERT(state);
   3084     ZYAN_ASSERT(instruction);
   3085     ZYAN_ASSERT(instruction->raw.prefix_count == 0);
   3086 
   3087     ZyanU8 rex = 0x00;
   3088     ZyanU8 offset = 0;
   3089     ZyanBool done = ZYAN_FALSE;
   3090     do
   3091     {
   3092         ZyanU8 prefix_byte;
   3093         ZYAN_CHECK(ZydisInputPeek(state, instruction, &prefix_byte));
   3094         switch (prefix_byte)
   3095         {
   3096         case 0xF0:
   3097             state->prefixes.has_lock = ZYAN_TRUE;
   3098             state->prefixes.offset_lock = offset;
   3099             break;
   3100         case 0xF2:
   3101             ZYAN_FALLTHROUGH;
   3102         case 0xF3:
   3103             state->prefixes.group1 = prefix_byte;
   3104             state->prefixes.mandatory_candidate = prefix_byte;
   3105             state->prefixes.offset_group1 = offset;
   3106             state->prefixes.offset_mandatory = offset;
   3107             break;
   3108         case 0x2E:
   3109             ZYAN_FALLTHROUGH;
   3110         case 0x36:
   3111             ZYAN_FALLTHROUGH;
   3112         case 0x3E:
   3113             ZYAN_FALLTHROUGH;
   3114         case 0x26:
   3115             if (state->decoder->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
   3116             {
   3117                 if ((prefix_byte == 0x3E) &&
   3118                     (state->prefixes.effective_segment != 0x64) &&
   3119                     (state->prefixes.effective_segment != 0x65))
   3120                 {
   3121                     state->prefixes.offset_notrack = offset;
   3122                 }
   3123                 state->prefixes.group2 = prefix_byte;
   3124                 state->prefixes.offset_group2 = offset;
   3125                 break;
   3126             }
   3127             ZYAN_FALLTHROUGH;
   3128         case 0x64:
   3129             ZYAN_FALLTHROUGH;
   3130         case 0x65:
   3131             state->prefixes.group2 = prefix_byte;
   3132             state->prefixes.offset_group2 = offset;
   3133             state->prefixes.effective_segment = prefix_byte;
   3134             state->prefixes.offset_segment = offset;
   3135             state->prefixes.offset_notrack = -1;
   3136             break;
   3137         case 0x66:
   3138             // context->prefixes.has_osz_override = ZYAN_TRUE;
   3139             state->prefixes.offset_osz_override = offset;
   3140             if (!state->prefixes.mandatory_candidate)
   3141             {
   3142                 state->prefixes.mandatory_candidate = 0x66;
   3143                 state->prefixes.offset_mandatory = offset;
   3144             }
   3145             instruction->attributes |= ZYDIS_ATTRIB_HAS_OPERANDSIZE;
   3146             break;
   3147         case 0x67:
   3148             // context->prefixes.has_asz_override = ZYAN_TRUE;
   3149             state->prefixes.offset_asz_override = offset;
   3150             instruction->attributes |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
   3151             break;
   3152         default:
   3153             if ((state->decoder->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) &&
   3154                 (prefix_byte & 0xF0) == 0x40)
   3155             {
   3156                 rex = prefix_byte;
   3157                 instruction->raw.rex.offset = offset;
   3158             } else
   3159             {
   3160                 done = ZYAN_TRUE;
   3161             }
   3162             break;
   3163         }
   3164         if (!done)
   3165         {
   3166             // Invalidate `REX`, if it's not the last legacy prefix
   3167             if (rex && (rex != prefix_byte))
   3168             {
   3169                 rex = 0x00;
   3170                 instruction->raw.rex.offset = 0;
   3171             }
   3172             instruction->raw.prefixes[instruction->raw.prefix_count++].value = prefix_byte;
   3173             ZydisInputSkip(state, instruction);
   3174             ++offset;
   3175         }
   3176     } while (!done);
   3177 
   3178     if (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE)
   3179     {
   3180         instruction->raw.prefixes[state->prefixes.offset_osz_override].type =
   3181             ZYDIS_PREFIX_TYPE_EFFECTIVE;
   3182     }
   3183     if (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE)
   3184     {
   3185         instruction->raw.prefixes[state->prefixes.offset_asz_override].type =
   3186             ZYDIS_PREFIX_TYPE_EFFECTIVE;
   3187     }
   3188     if (rex)
   3189     {
   3190         instruction->raw.prefixes[instruction->raw.rex.offset].type = ZYDIS_PREFIX_TYPE_EFFECTIVE;
   3191         ZydisDecodeREX(state->context, instruction, rex);
   3192     }
   3193     if ((state->decoder->machine_mode != ZYDIS_MACHINE_MODE_LONG_64) &&
   3194         (state->prefixes.group2 == 0x3E))
   3195     {
   3196         state->prefixes.offset_notrack = state->prefixes.offset_group2;
   3197     }
   3198 
   3199     return ZYAN_STATUS_SUCCESS;
   3200 }
   3201 
   3202 /**
   3203  * Decodes optional instruction parts like the ModRM byte, the SIB byte and
   3204  * additional displacements and/or immediate values.
   3205  *
   3206  * @param   state       A pointer to the `ZydisDecoderState` struct.
   3207  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
   3208  * @param   info        A pointer to the `ZydisInstructionEncodingInfo` struct.
   3209  *
   3210  * @return  A zyan status code.
   3211  */
   3212 static ZyanStatus ZydisDecodeOptionalInstructionParts(ZydisDecoderState* state,
   3213     ZydisDecodedInstruction* instruction, const ZydisInstructionEncodingInfo* info)
   3214 {
   3215     ZYAN_ASSERT(state);
   3216     ZYAN_ASSERT(instruction);
   3217     ZYAN_ASSERT(info);
   3218 
   3219     ZydisDecoderContext* context = state->context;
   3220 
   3221     if (info->flags & ZYDIS_INSTR_ENC_FLAG_HAS_MODRM)
   3222     {
   3223         if (!instruction->raw.modrm.offset)
   3224         {
   3225             instruction->raw.modrm.offset = instruction->length;
   3226             ZyanU8 modrm_byte;
   3227             ZYAN_CHECK(ZydisInputNext(state, instruction, &modrm_byte));
   3228             ZydisDecodeModRM(instruction, modrm_byte);
   3229         }
   3230 
   3231         if (!(info->flags & ZYDIS_INSTR_ENC_FLAG_FORCE_REG_FORM))
   3232         {
   3233             ZyanU8 has_sib = 0;
   3234             ZyanU8 displacement_size = 0;
   3235             switch (instruction->address_width)
   3236             {
   3237             case 16:
   3238                 switch (instruction->raw.modrm.mod)
   3239                 {
   3240                 case 0:
   3241                     if (instruction->raw.modrm.rm == 6)
   3242                     {
   3243                         displacement_size = 16;
   3244                     }
   3245                     break;
   3246                 case 1:
   3247                     displacement_size = 8;
   3248                     break;
   3249                 case 2:
   3250                     displacement_size = 16;
   3251                     break;
   3252                 case 3:
   3253                     break;
   3254                 default:
   3255                     ZYAN_UNREACHABLE;
   3256                 }
   3257                 break;
   3258             case 32:
   3259             case 64:
   3260                 has_sib =
   3261                     (instruction->raw.modrm.mod != 3) && (instruction->raw.modrm.rm == 4);
   3262                 switch (instruction->raw.modrm.mod)
   3263                 {
   3264                 case 0:
   3265                     if (instruction->raw.modrm.rm == 5)
   3266                     {
   3267                         if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
   3268                         {
   3269                             instruction->attributes |= ZYDIS_ATTRIB_IS_RELATIVE;
   3270                         }
   3271                         displacement_size = 32;
   3272                     }
   3273                     break;
   3274                 case 1:
   3275                     displacement_size = 8;
   3276                     break;
   3277                 case 2:
   3278                     displacement_size = 32;
   3279                     break;
   3280                 case 3:
   3281                     break;
   3282                 default:
   3283                     ZYAN_UNREACHABLE;
   3284                 }
   3285                 break;
   3286             default:
   3287                 ZYAN_UNREACHABLE;
   3288             }
   3289             if (has_sib)
   3290             {
   3291                 instruction->raw.sib.offset = instruction->length;
   3292                 ZyanU8 sib_byte;
   3293                 ZYAN_CHECK(ZydisInputNext(state, instruction, &sib_byte));
   3294                 ZydisDecodeSIB(instruction, sib_byte);
   3295                 if (instruction->raw.sib.base == 5)
   3296                 {
   3297                     displacement_size = (instruction->raw.modrm.mod == 1) ? 8 : 32;
   3298                 }
   3299             }
   3300             if (displacement_size)
   3301             {
   3302                 ZYAN_CHECK(ZydisReadDisplacement(state, instruction, displacement_size));
   3303             }
   3304         }
   3305 
   3306         context->reg_info.is_mod_reg = (instruction->raw.modrm.mod == 3) ||
   3307                                        (info->flags & ZYDIS_INSTR_ENC_FLAG_FORCE_REG_FORM);
   3308     }
   3309 
   3310     if (info->flags & ZYDIS_INSTR_ENC_FLAG_HAS_DISP)
   3311     {
   3312         ZYAN_CHECK(ZydisReadDisplacement(
   3313             state, instruction, info->disp.size[context->easz_index]));
   3314     }
   3315 
   3316     if (info->flags & ZYDIS_INSTR_ENC_FLAG_HAS_IMM0)
   3317     {
   3318         if (info->imm[0].is_relative)
   3319         {
   3320             instruction->attributes |= ZYDIS_ATTRIB_IS_RELATIVE;
   3321         }
   3322         ZYAN_CHECK(ZydisReadImmediate(state, instruction, 0,
   3323             info->imm[0].size[context->eosz_index], info->imm[0].is_signed,
   3324             info->imm[0].is_relative));
   3325     }
   3326 
   3327     if (info->flags & ZYDIS_INSTR_ENC_FLAG_HAS_IMM1)
   3328     {
   3329         ZYAN_ASSERT(!(info->flags & ZYDIS_INSTR_ENC_FLAG_HAS_DISP));
   3330         ZYAN_CHECK(ZydisReadImmediate(state, instruction, 1,
   3331             info->imm[1].size[context->eosz_index], info->imm[1].is_signed,
   3332             info->imm[1].is_relative));
   3333     }
   3334 
   3335     return ZYAN_STATUS_SUCCESS;
   3336 }
   3337 
   3338 /* ---------------------------------------------------------------------------------------------- */
   3339 
   3340 /**
   3341  * Sets the effective operand size for the given instruction.
   3342  *
   3343  * @param   context     A pointer to the `ZydisDecoderContext` struct
   3344  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
   3345  * @param   definition  A pointer to the `ZydisInstructionDefinition` struct.
   3346  */
   3347 static void ZydisSetEffectiveOperandWidth(ZydisDecoderContext* context,
   3348     ZydisDecodedInstruction* instruction, const ZydisInstructionDefinition* definition)
   3349 {
   3350     ZYAN_ASSERT(context);
   3351     ZYAN_ASSERT(instruction);
   3352     ZYAN_ASSERT(definition);
   3353 
   3354     static const ZyanU8 operand_size_map[8][8] =
   3355     {
   3356         // Default for most instructions
   3357         {
   3358             16, // 16 __ W0
   3359             32, // 16 66 W0
   3360             32, // 32 __ W0
   3361             16, // 32 66 W0
   3362             32, // 64 __ W0
   3363             16, // 64 66 W0
   3364             64, // 64 __ W1
   3365             64  // 64 66 W1
   3366         },
   3367         // Operand size is forced to 8-bit (this is done later to preserve the `eosz_index`)
   3368         {
   3369             16, // 16 __ W0
   3370             32, // 16 66 W0
   3371             32, // 32 __ W0
   3372             16, // 32 66 W0
   3373             32, // 64 __ W0
   3374             16, // 64 66 W0
   3375             64, // 64 __ W1
   3376             64  // 64 66 W1
   3377         },
   3378         // Operand size override 0x66 is ignored
   3379         {
   3380             16, // 16 __ W0
   3381             16, // 16 66 W0
   3382             32, // 32 __ W0
   3383             32, // 32 66 W0
   3384             32, // 64 __ W0
   3385             32, // 64 66 W0
   3386             64, // 64 __ W1
   3387             64  // 64 66 W1
   3388         },
   3389         // REX.W promotes to 32-bit instead of 64-bit
   3390         {
   3391             16, // 16 __ W0
   3392             32, // 16 66 W0
   3393             32, // 32 __ W0
   3394             16, // 32 66 W0
   3395             32, // 64 __ W0
   3396             16, // 64 66 W0
   3397             32, // 64 __ W1
   3398             32  // 64 66 W1
   3399         },
   3400         // Operand size defaults to 64-bit in 64-bit mode
   3401         {
   3402             16, // 16 __ W0
   3403             32, // 16 66 W0
   3404             32, // 32 __ W0
   3405             16, // 32 66 W0
   3406             64, // 64 __ W0
   3407             16, // 64 66 W0
   3408             64, // 64 __ W1
   3409             64  // 64 66 W1
   3410         },
   3411         // Operand size is forced to 64-bit in 64-bit mode
   3412         {
   3413             16, // 16 __ W0
   3414             32, // 16 66 W0
   3415             32, // 32 __ W0
   3416             16, // 32 66 W0
   3417             64, // 64 __ W0
   3418             64, // 64 66 W0
   3419             64, // 64 __ W1
   3420             64  // 64 66 W1
   3421         },
   3422         // Operand size is forced to 32-bit, if no REX.W is present.
   3423         {
   3424             32, // 16 __ W0
   3425             32, // 16 66 W0
   3426             32, // 32 __ W0
   3427             32, // 32 66 W0
   3428             32, // 64 __ W0
   3429             32, // 64 66 W0
   3430             64, // 64 __ W1
   3431             64  // 64 66 W1
   3432         },
   3433         // Operand size is forced to 64-bit in 64-bit mode and forced to 32-bit in all other modes.
   3434         // This is used for e.g. `mov CR, GPR` and `mov GPR, CR`.
   3435         {
   3436             32, // 16 __ W0
   3437             32, // 16 66 W0
   3438             32, // 32 __ W0
   3439             32, // 32 66 W0
   3440             64, // 64 __ W0
   3441             64, // 64 66 W0
   3442             64, // 64 __ W1
   3443             64  // 64 66 W1
   3444         }
   3445     };
   3446 
   3447     ZyanU8 index = (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE) ? 1 : 0;
   3448     if ((instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_COMPAT_32) ||
   3449         (instruction->machine_mode == ZYDIS_MACHINE_MODE_LEGACY_32))
   3450     {
   3451         index += 2;
   3452     }
   3453     else if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
   3454     {
   3455         index += 4;
   3456         index += (context->vector_unified.W & 0x01) << 1;
   3457     }
   3458 
   3459     ZYAN_ASSERT(definition->operand_size_map < ZYAN_ARRAY_LENGTH(operand_size_map));
   3460     ZYAN_ASSERT(index < ZYAN_ARRAY_LENGTH(operand_size_map[definition->operand_size_map]));
   3461 
   3462     instruction->operand_width = operand_size_map[definition->operand_size_map][index];
   3463     context->eosz_index = instruction->operand_width >> 5;
   3464 
   3465     // TODO: Cleanup code and remove hardcoded condition
   3466     if (definition->operand_size_map == 1)
   3467     {
   3468         instruction->operand_width = 8;
   3469     }
   3470 }
   3471 
   3472 /**
   3473  * Sets the effective address width for the given instruction.
   3474  *
   3475  * @param   context     A pointer to the `ZydisDecoderContext` struct.
   3476  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
   3477  * @param   definition  A pointer to the `ZydisInstructionDefinition` struct.
   3478  */
   3479 static void ZydisSetEffectiveAddressWidth(ZydisDecoderContext* context,
   3480     ZydisDecodedInstruction* instruction, const ZydisInstructionDefinition* definition)
   3481 {
   3482     ZYAN_ASSERT(context);
   3483     ZYAN_ASSERT(instruction);
   3484 
   3485     static const ZyanU8 address_size_map[3][8] =
   3486     {
   3487         // Default for most instructions
   3488         {
   3489             16, // 16 __
   3490             32, // 16 67
   3491             32, // 32 __
   3492             16, // 32 67
   3493             64, // 64 __
   3494             32  // 64 67
   3495         },
   3496         // The address-size override is ignored
   3497         {
   3498             16, // 16 __
   3499             16, // 16 67
   3500             32, // 32 __
   3501             32, // 32 67
   3502             64, // 64 __
   3503             64  // 64 67
   3504         },
   3505         // The address-size is forced to 64-bit in 64-bit mode and 32-bit in non 64-bit mode. This
   3506         // is used by e.g. `ENCLS`, `ENCLV`, `ENCLU`.
   3507         {
   3508             32, // 16 __
   3509             32, // 16 67
   3510             32, // 32 __
   3511             32, // 32 67
   3512             64, // 64 __
   3513             64  // 64 67
   3514         }
   3515     };
   3516 
   3517     ZyanU8 index = (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE) ? 1 : 0;
   3518     if ((instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_COMPAT_32) ||
   3519         (instruction->machine_mode == ZYDIS_MACHINE_MODE_LEGACY_32))
   3520     {
   3521         index += 2;
   3522     }
   3523     else if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
   3524     {
   3525         index += 4;
   3526     }
   3527 
   3528     ZYAN_ASSERT(definition->address_size_map < ZYAN_ARRAY_LENGTH(address_size_map));
   3529     ZYAN_ASSERT(index < ZYAN_ARRAY_LENGTH(address_size_map[definition->address_size_map]));
   3530 
   3531     instruction->address_width = address_size_map[definition->address_size_map][index];
   3532     context->easz_index = instruction->address_width >> 5;
   3533 }
   3534 
   3535 /* ---------------------------------------------------------------------------------------------- */
   3536 
   3537 static ZyanStatus ZydisNodeHandlerXOP(const ZydisDecodedInstruction* instruction, ZyanU16* index)
   3538 {
   3539     ZYAN_ASSERT(instruction);
   3540     ZYAN_ASSERT(index);
   3541 
   3542     switch (instruction->encoding)
   3543     {
   3544     case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
   3545         *index = 0;
   3546         break;
   3547     case ZYDIS_INSTRUCTION_ENCODING_XOP:
   3548         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_XOP);
   3549         *index = (instruction->raw.xop.m_mmmm - 0x08) + (instruction->raw.xop.pp * 3) + 1;
   3550         break;
   3551     default:
   3552         ZYAN_UNREACHABLE;
   3553     }
   3554     return ZYAN_STATUS_SUCCESS;
   3555 }
   3556 
   3557 static ZyanStatus ZydisNodeHandlerVEX(const ZydisDecodedInstruction* instruction, ZyanU16* index)
   3558 {
   3559     ZYAN_ASSERT(instruction);
   3560     ZYAN_ASSERT(index);
   3561 
   3562     switch (instruction->encoding)
   3563     {
   3564     case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
   3565         *index = 0;
   3566         break;
   3567     case ZYDIS_INSTRUCTION_ENCODING_VEX:
   3568         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX);
   3569         *index = instruction->raw.vex.m_mmmm + (instruction->raw.vex.pp << 2) + 1;
   3570         break;
   3571     default:
   3572         ZYAN_UNREACHABLE;
   3573     }
   3574     return ZYAN_STATUS_SUCCESS;
   3575 }
   3576 
   3577 static ZyanStatus ZydisNodeHandlerEMVEX(const ZydisDecodedInstruction* instruction, ZyanU16* index)
   3578 {
   3579     ZYAN_ASSERT(instruction);
   3580     ZYAN_ASSERT(index);
   3581 
   3582     switch (instruction->encoding)
   3583     {
   3584     case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
   3585         *index = 0;
   3586         break;
   3587     case ZYDIS_INSTRUCTION_ENCODING_EVEX:
   3588         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX);
   3589         *index = instruction->raw.evex.mmm + (instruction->raw.evex.pp << 3) + 1;
   3590         break;
   3591     case ZYDIS_INSTRUCTION_ENCODING_MVEX:
   3592         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX);
   3593         *index = instruction->raw.mvex.mmmm + (instruction->raw.mvex.pp << 2) + 33;
   3594         break;
   3595     default:
   3596         ZYAN_UNREACHABLE;
   3597     }
   3598     return ZYAN_STATUS_SUCCESS;
   3599 }
   3600 
   3601 static ZyanStatus ZydisNodeHandlerOpcode(ZydisDecoderState* state,
   3602     ZydisDecodedInstruction* instruction, ZyanU16* index)
   3603 {
   3604     ZYAN_ASSERT(state);
   3605     ZYAN_ASSERT(instruction);
   3606     ZYAN_ASSERT(index);
   3607 
   3608     // Handle possible encoding-prefix and opcode-map changes
   3609     switch (instruction->encoding)
   3610     {
   3611     case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
   3612         ZYAN_CHECK(ZydisInputNext(state, instruction, &instruction->opcode));
   3613         switch (instruction->opcode_map)
   3614         {
   3615         case ZYDIS_OPCODE_MAP_DEFAULT:
   3616             switch (instruction->opcode)
   3617             {
   3618             case 0x0F:
   3619                 instruction->opcode_map = ZYDIS_OPCODE_MAP_0F;
   3620                 break;
   3621             case 0xC4:
   3622             case 0xC5:
   3623             case 0x62:
   3624             {
   3625                 ZyanU8 next_input;
   3626                 ZYAN_CHECK(ZydisInputPeek(state, instruction, &next_input));
   3627                 if (((next_input & 0xF0) >= 0xC0) ||
   3628                     (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64))
   3629                 {
   3630                     if (instruction->attributes & ZYDIS_ATTRIB_HAS_REX)
   3631                     {
   3632                         return ZYDIS_STATUS_ILLEGAL_REX;
   3633                     }
   3634                     if (state->prefixes.has_lock)
   3635                     {
   3636                         return ZYDIS_STATUS_ILLEGAL_LOCK;
   3637                     }
   3638                     if (state->prefixes.mandatory_candidate)
   3639                     {
   3640                         return ZYDIS_STATUS_ILLEGAL_LEGACY_PFX;
   3641                     }
   3642                     ZyanU8 prefix_bytes[4] = { 0, 0, 0, 0 };
   3643                     prefix_bytes[0] = instruction->opcode;
   3644                     switch (instruction->opcode)
   3645                     {
   3646                     case 0xC4:
   3647                         instruction->raw.vex.offset = instruction->length - 1;
   3648                         // Read additional 3-byte VEX-prefix data
   3649                         ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX));
   3650                         ZYAN_CHECK(ZydisInputNextBytes(state, instruction, &prefix_bytes[1], 2));
   3651                         break;
   3652                     case 0xC5:
   3653                         instruction->raw.vex.offset = instruction->length - 1;
   3654                         // Read additional 2-byte VEX-prefix data
   3655                         ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX));
   3656                         ZYAN_CHECK(ZydisInputNext(state, instruction, &prefix_bytes[1]));
   3657                         break;
   3658                     case 0x62:
   3659 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
   3660                         // Read additional EVEX/MVEX-prefix data
   3661                         ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX));
   3662                         ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX));
   3663                         ZYAN_CHECK(ZydisInputNextBytes(state, instruction, &prefix_bytes[1], 3));
   3664                         break;
   3665 #else
   3666                         return ZYDIS_STATUS_DECODING_ERROR;
   3667 #endif
   3668                     default:
   3669                         ZYAN_UNREACHABLE;
   3670                     }
   3671                     switch (instruction->opcode)
   3672                     {
   3673                     case 0xC4:
   3674                     case 0xC5:
   3675                         // Decode VEX-prefix
   3676                         instruction->encoding = ZYDIS_INSTRUCTION_ENCODING_VEX;
   3677                         ZYAN_CHECK(ZydisDecodeVEX(state->context, instruction, prefix_bytes));
   3678                         instruction->opcode_map =
   3679                             ZYDIS_OPCODE_MAP_DEFAULT + instruction->raw.vex.m_mmmm;
   3680                         break;
   3681                     case 0x62:
   3682 #if defined(ZYDIS_DISABLE_AVX512) && defined(ZYDIS_DISABLE_KNC)
   3683                         return ZYDIS_STATUS_DECODING_ERROR;
   3684 #else
   3685                         switch ((prefix_bytes[2] >> 2) & 0x01)
   3686                         {
   3687                         case 0:
   3688 #ifndef ZYDIS_DISABLE_KNC
   3689                             instruction->raw.mvex.offset = instruction->length - 4;
   3690                             // `KNC` instructions are only valid in 64-bit mode.
   3691                             // This condition catches the `MVEX` encoded ones to save a bunch of
   3692                             // `mode` filters in the data-tables.
   3693                             // `KNC` instructions with `VEX` encoding still require a `mode` filter.
   3694                             if (state->decoder->machine_mode != ZYDIS_MACHINE_MODE_LONG_64)
   3695                             {
   3696                                 return ZYDIS_STATUS_DECODING_ERROR;
   3697                             }
   3698                             // Decode MVEX-prefix
   3699                             instruction->encoding = ZYDIS_INSTRUCTION_ENCODING_MVEX;
   3700                             ZYAN_CHECK(ZydisDecodeMVEX(state->context, instruction, prefix_bytes));
   3701                             instruction->opcode_map =
   3702                                 ZYDIS_OPCODE_MAP_DEFAULT + instruction->raw.mvex.mmmm;
   3703                             break;
   3704 #else
   3705                             return ZYDIS_STATUS_DECODING_ERROR;
   3706 #endif
   3707                         case 1:
   3708 #ifndef ZYDIS_DISABLE_AVX512
   3709                             instruction->raw.evex.offset = instruction->length - 4;
   3710                             // Decode EVEX-prefix
   3711                             instruction->encoding = ZYDIS_INSTRUCTION_ENCODING_EVEX;
   3712                             ZYAN_CHECK(ZydisDecodeEVEX(state->context, instruction, prefix_bytes));
   3713                             instruction->opcode_map =
   3714                                 ZYDIS_OPCODE_MAP_DEFAULT + instruction->raw.evex.mmm;
   3715                             break;
   3716 #else
   3717                             return ZYDIS_STATUS_DECODING_ERROR;
   3718 #endif
   3719                         default:
   3720                             ZYAN_UNREACHABLE;
   3721                         }
   3722                         break;
   3723 #endif
   3724                     default:
   3725                         ZYAN_UNREACHABLE;
   3726                     }
   3727                 }
   3728                 break;
   3729             }
   3730             case 0x8F:
   3731             {
   3732                 ZyanU8 next_input;
   3733                 ZYAN_CHECK(ZydisInputPeek(state, instruction, &next_input));
   3734                 if ((next_input & 0x1F) >= 8)
   3735                 {
   3736                     if (instruction->attributes & ZYDIS_ATTRIB_HAS_REX)
   3737                     {
   3738                         return ZYDIS_STATUS_ILLEGAL_REX;
   3739                     }
   3740                     if (state->prefixes.has_lock)
   3741                     {
   3742                         return ZYDIS_STATUS_ILLEGAL_LOCK;
   3743                     }
   3744                     if (state->prefixes.mandatory_candidate)
   3745                     {
   3746                         return ZYDIS_STATUS_ILLEGAL_LEGACY_PFX;
   3747                     }
   3748                     instruction->raw.xop.offset = instruction->length - 1;
   3749                     ZyanU8 prefixBytes[3] = { 0x8F, 0x00, 0x00 };
   3750                     // Read additional xop-prefix data
   3751                     ZYAN_CHECK(ZydisInputNextBytes(state, instruction, &prefixBytes[1], 2));
   3752                     // Decode xop-prefix
   3753                     instruction->encoding = ZYDIS_INSTRUCTION_ENCODING_XOP;
   3754                     ZYAN_CHECK(ZydisDecodeXOP(state->context, instruction, prefixBytes));
   3755                     instruction->opcode_map =
   3756                         ZYDIS_OPCODE_MAP_XOP8 + instruction->raw.xop.m_mmmm - 0x08;
   3757                 }
   3758                 break;
   3759             }
   3760             default:
   3761                 break;
   3762             }
   3763             break;
   3764         case ZYDIS_OPCODE_MAP_0F:
   3765             switch (instruction->opcode)
   3766             {
   3767             case 0x0F:
   3768                 if (state->prefixes.has_lock)
   3769                 {
   3770                     return ZYDIS_STATUS_ILLEGAL_LOCK;
   3771                 }
   3772                 instruction->encoding = ZYDIS_INSTRUCTION_ENCODING_3DNOW;
   3773                 instruction->opcode_map = ZYDIS_OPCODE_MAP_0F0F;
   3774                 break;
   3775             case 0x38:
   3776                 instruction->opcode_map = ZYDIS_OPCODE_MAP_0F38;
   3777                 break;
   3778             case 0x3A:
   3779                 instruction->opcode_map = ZYDIS_OPCODE_MAP_0F3A;
   3780                 break;
   3781             default:
   3782                 break;
   3783             }
   3784             break;
   3785         case ZYDIS_OPCODE_MAP_0F38:
   3786         case ZYDIS_OPCODE_MAP_0F3A:
   3787         case ZYDIS_OPCODE_MAP_XOP8:
   3788         case ZYDIS_OPCODE_MAP_XOP9:
   3789         case ZYDIS_OPCODE_MAP_XOPA:
   3790             // Nothing to do here
   3791             break;
   3792         default:
   3793             ZYAN_UNREACHABLE;
   3794         }
   3795         break;
   3796     case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
   3797         // All 3DNOW (0x0F 0x0F) instructions are using the same operand encoding. We just
   3798         // decode a random (pi2fw) instruction and extract the actual opcode later.
   3799         *index = 0x0C;
   3800         return ZYAN_STATUS_SUCCESS;
   3801     default:
   3802         ZYAN_CHECK(ZydisInputNext(state, instruction, &instruction->opcode));
   3803         break;
   3804     }
   3805 
   3806     *index = instruction->opcode;
   3807     return ZYAN_STATUS_SUCCESS;
   3808 }
   3809 
   3810 static ZyanStatus ZydisNodeHandlerMode(const ZydisDecodedInstruction* instruction, ZyanU16* index)
   3811 {
   3812     ZYAN_ASSERT(instruction);
   3813     ZYAN_ASSERT(index);
   3814 
   3815     switch (instruction->machine_mode)
   3816     {
   3817     case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
   3818     case ZYDIS_MACHINE_MODE_LEGACY_16:
   3819     case ZYDIS_MACHINE_MODE_REAL_16:
   3820         *index = 0;
   3821         break;
   3822     case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
   3823     case ZYDIS_MACHINE_MODE_LEGACY_32:
   3824         *index = 1;
   3825         break;
   3826     case ZYDIS_MACHINE_MODE_LONG_64:
   3827         *index = 2;
   3828         break;
   3829     default:
   3830         ZYAN_UNREACHABLE;
   3831     }
   3832     return ZYAN_STATUS_SUCCESS;
   3833 }
   3834 
   3835 static ZyanStatus ZydisNodeHandlerModeCompact(const ZydisDecodedInstruction* instruction,
   3836     ZyanU16* index)
   3837 {
   3838     ZYAN_ASSERT(instruction);
   3839     ZYAN_ASSERT(index);
   3840 
   3841     *index = (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) ? 0 : 1;
   3842     return ZYAN_STATUS_SUCCESS;
   3843 }
   3844 
   3845 static ZyanStatus ZydisNodeHandlerModrmMod(ZydisDecoderState* state,
   3846     ZydisDecodedInstruction* instruction, ZyanU16* index)
   3847 {
   3848     ZYAN_ASSERT(state);
   3849     ZYAN_ASSERT(instruction);
   3850     ZYAN_ASSERT(index);
   3851 
   3852     if (!instruction->raw.modrm.offset)
   3853     {
   3854         instruction->raw.modrm.offset = instruction->length;
   3855         ZyanU8 modrm_byte;
   3856         ZYAN_CHECK(ZydisInputNext(state, instruction, &modrm_byte));
   3857         ZydisDecodeModRM(instruction, modrm_byte);
   3858     }
   3859     *index = instruction->raw.modrm.mod;
   3860     return ZYAN_STATUS_SUCCESS;
   3861 }
   3862 
   3863 static ZyanStatus ZydisNodeHandlerModrmModCompact(ZydisDecoderState* state,
   3864     ZydisDecodedInstruction* instruction, ZyanU16* index)
   3865 {
   3866     ZYAN_CHECK(ZydisNodeHandlerModrmMod(state, instruction, index));
   3867     *index = (*index == 0x3) ? 0 : 1;
   3868     return ZYAN_STATUS_SUCCESS;
   3869 }
   3870 
   3871 static ZyanStatus ZydisNodeHandlerModrmReg(ZydisDecoderState* state,
   3872     ZydisDecodedInstruction* instruction, ZyanU16* index)
   3873 {
   3874     ZYAN_ASSERT(state);
   3875     ZYAN_ASSERT(instruction);
   3876     ZYAN_ASSERT(index);
   3877 
   3878     if (!instruction->raw.modrm.offset)
   3879     {
   3880         instruction->raw.modrm.offset = instruction->length;
   3881         ZyanU8 modrm_byte;
   3882         ZYAN_CHECK(ZydisInputNext(state, instruction, &modrm_byte));
   3883         ZydisDecodeModRM(instruction, modrm_byte);
   3884     }
   3885     *index = instruction->raw.modrm.reg;
   3886     return ZYAN_STATUS_SUCCESS;
   3887 }
   3888 
   3889 static ZyanStatus ZydisNodeHandlerModrmRm(ZydisDecoderState* state,
   3890     ZydisDecodedInstruction* instruction, ZyanU16* index)
   3891 {
   3892     ZYAN_ASSERT(state);
   3893     ZYAN_ASSERT(instruction);
   3894     ZYAN_ASSERT(index);
   3895 
   3896     if (!instruction->raw.modrm.offset)
   3897     {
   3898         instruction->raw.modrm.offset = instruction->length;
   3899         ZyanU8 modrm_byte;
   3900         ZYAN_CHECK(ZydisInputNext(state, instruction, &modrm_byte));
   3901         ZydisDecodeModRM(instruction, modrm_byte);
   3902     }
   3903     *index = instruction->raw.modrm.rm;
   3904     return ZYAN_STATUS_SUCCESS;
   3905 }
   3906 
   3907 static ZyanStatus ZydisNodeHandlerMandatoryPrefix(const ZydisDecoderState* state,
   3908     ZydisDecodedInstruction* instruction, ZyanU16* index)
   3909 {
   3910     ZYAN_ASSERT(state);
   3911     ZYAN_ASSERT(instruction);
   3912     ZYAN_ASSERT(index);
   3913 
   3914     switch (state->prefixes.mandatory_candidate)
   3915     {
   3916     case 0x66:
   3917         instruction->raw.prefixes[state->prefixes.offset_mandatory].type =
   3918             ZYDIS_PREFIX_TYPE_MANDATORY;
   3919         instruction->attributes &= ~ZYDIS_ATTRIB_HAS_OPERANDSIZE;
   3920         *index = 2;
   3921         break;
   3922     case 0xF3:
   3923         instruction->raw.prefixes[state->prefixes.offset_mandatory].type =
   3924             ZYDIS_PREFIX_TYPE_MANDATORY;
   3925         *index = 3;
   3926         break;
   3927     case 0xF2:
   3928         instruction->raw.prefixes[state->prefixes.offset_mandatory].type =
   3929             ZYDIS_PREFIX_TYPE_MANDATORY;
   3930         *index = 4;
   3931         break;
   3932     default:
   3933         *index = 1;
   3934         break;
   3935     }
   3936     // TODO: Consume prefix and make sure it's available again, if we need to fallback
   3937 
   3938     return ZYAN_STATUS_SUCCESS;
   3939 }
   3940 
   3941 static ZyanStatus ZydisNodeHandlerOperandSize(const ZydisDecoderState* state,
   3942     ZydisDecodedInstruction* instruction, ZyanU16* index)
   3943 {
   3944     ZYAN_ASSERT(state);
   3945     ZYAN_ASSERT(instruction);
   3946     ZYAN_ASSERT(index);
   3947 
   3948     if ((instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) &&
   3949         (state->context->vector_unified.W))
   3950     {
   3951         *index = 2;
   3952     } else
   3953     {
   3954         if (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE)
   3955         {
   3956             instruction->raw.prefixes[state->prefixes.offset_osz_override].type =
   3957                 ZYDIS_PREFIX_TYPE_EFFECTIVE;
   3958         }
   3959         switch (instruction->machine_mode)
   3960         {
   3961         case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
   3962         case ZYDIS_MACHINE_MODE_LEGACY_16:
   3963         case ZYDIS_MACHINE_MODE_REAL_16:
   3964             *index = (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE) ? 1 : 0;
   3965             break;
   3966         case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
   3967         case ZYDIS_MACHINE_MODE_LEGACY_32:
   3968         case ZYDIS_MACHINE_MODE_LONG_64:
   3969             *index = (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE) ? 0 : 1;
   3970             break;
   3971         default:
   3972             ZYAN_UNREACHABLE;
   3973         }
   3974     }
   3975 
   3976     return ZYAN_STATUS_SUCCESS;
   3977 }
   3978 
   3979 static ZyanStatus ZydisNodeHandlerAddressSize(ZydisDecodedInstruction* instruction, ZyanU16* index)
   3980 {
   3981     ZYAN_ASSERT(instruction);
   3982     ZYAN_ASSERT(index);
   3983 
   3984     /*if (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE)
   3985     {
   3986         instruction->raw.prefixes[context->prefixes.offset_asz_override].type =
   3987             ZYDIS_PREFIX_TYPE_EFFECTIVE;
   3988     }*/
   3989     switch (instruction->machine_mode)
   3990     {
   3991     case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
   3992     case ZYDIS_MACHINE_MODE_LEGACY_16:
   3993     case ZYDIS_MACHINE_MODE_REAL_16:
   3994         *index = (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE) ? 1 : 0;
   3995         break;
   3996     case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
   3997     case ZYDIS_MACHINE_MODE_LEGACY_32:
   3998         *index = (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE) ? 0 : 1;
   3999         break;
   4000     case ZYDIS_MACHINE_MODE_LONG_64:
   4001         *index = (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE) ? 1 : 2;
   4002         break;
   4003     default:
   4004         ZYAN_UNREACHABLE;
   4005     }
   4006 
   4007     return ZYAN_STATUS_SUCCESS;
   4008 }
   4009 
   4010 static ZyanStatus ZydisNodeHandlerVectorLength(const ZydisDecoderContext* context,
   4011     const ZydisDecodedInstruction* instruction, ZyanU16* index)
   4012 {
   4013     ZYAN_ASSERT(context);
   4014     ZYAN_ASSERT(instruction);
   4015     ZYAN_ASSERT(index);
   4016 
   4017     switch (instruction->encoding)
   4018     {
   4019     case ZYDIS_INSTRUCTION_ENCODING_XOP:
   4020         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_XOP);
   4021         break;
   4022     case ZYDIS_INSTRUCTION_ENCODING_VEX:
   4023         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX);
   4024         break;
   4025     case ZYDIS_INSTRUCTION_ENCODING_EVEX:
   4026         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX);
   4027         break;
   4028     case ZYDIS_INSTRUCTION_ENCODING_MVEX:
   4029         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX);
   4030         break;
   4031     default:
   4032         ZYAN_UNREACHABLE;
   4033     }
   4034 
   4035     *index = context->vector_unified.LL;
   4036     if (*index == 3)
   4037     {
   4038         return ZYDIS_STATUS_DECODING_ERROR;
   4039     }
   4040     return ZYAN_STATUS_SUCCESS;
   4041 }
   4042 
   4043 static ZyanStatus ZydisNodeHandlerRexW(const ZydisDecoderContext* context,
   4044     const ZydisDecodedInstruction* instruction, ZyanU16* index)
   4045 {
   4046     ZYAN_ASSERT(context);
   4047     ZYAN_ASSERT(instruction);
   4048     ZYAN_ASSERT(index);
   4049 
   4050     switch (instruction->encoding)
   4051     {
   4052     case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
   4053         // nothing to do here
   4054         break;
   4055     case ZYDIS_INSTRUCTION_ENCODING_XOP:
   4056         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_XOP);
   4057         break;
   4058     case ZYDIS_INSTRUCTION_ENCODING_VEX:
   4059         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX);
   4060         break;
   4061     case ZYDIS_INSTRUCTION_ENCODING_EVEX:
   4062         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX);
   4063         break;
   4064     case ZYDIS_INSTRUCTION_ENCODING_MVEX:
   4065         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX);
   4066         break;
   4067     default:
   4068         ZYAN_UNREACHABLE;
   4069     }
   4070     *index = context->vector_unified.W;
   4071     return ZYAN_STATUS_SUCCESS;
   4072 }
   4073 
   4074 static ZyanStatus ZydisNodeHandlerRexB(const ZydisDecoderContext* context,
   4075     const ZydisDecodedInstruction* instruction, ZyanU16* index)
   4076 {
   4077     ZYAN_ASSERT(context);
   4078     ZYAN_ASSERT(instruction);
   4079     ZYAN_ASSERT(index);
   4080 
   4081     switch (instruction->encoding)
   4082     {
   4083     case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
   4084         // nothing to do here
   4085         break;
   4086     case ZYDIS_INSTRUCTION_ENCODING_XOP:
   4087         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_XOP);
   4088         break;
   4089     case ZYDIS_INSTRUCTION_ENCODING_VEX:
   4090         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX);
   4091         break;
   4092     case ZYDIS_INSTRUCTION_ENCODING_EVEX:
   4093         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX);
   4094         break;
   4095     case ZYDIS_INSTRUCTION_ENCODING_MVEX:
   4096         ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX);
   4097         break;
   4098     default:
   4099         ZYAN_UNREACHABLE;
   4100     }
   4101     *index = context->vector_unified.B;
   4102     return ZYAN_STATUS_SUCCESS;
   4103 }
   4104 
   4105 #ifndef ZYDIS_DISABLE_AVX512
   4106 static ZyanStatus ZydisNodeHandlerEvexB(const ZydisDecodedInstruction* instruction, ZyanU16* index)
   4107 {
   4108     ZYAN_ASSERT(instruction);
   4109     ZYAN_ASSERT(index);
   4110 
   4111     ZYAN_ASSERT(instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX);
   4112     ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX);
   4113     *index = instruction->raw.evex.b;
   4114     return ZYAN_STATUS_SUCCESS;
   4115 }
   4116 #endif
   4117 
   4118 #ifndef ZYDIS_DISABLE_KNC
   4119 static ZyanStatus ZydisNodeHandlerMvexE(const ZydisDecodedInstruction* instruction, ZyanU16* index)
   4120 {
   4121     ZYAN_ASSERT(instruction);
   4122     ZYAN_ASSERT(index);
   4123 
   4124     ZYAN_ASSERT(instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX);
   4125     ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX);
   4126     *index = instruction->raw.mvex.E;
   4127     return ZYAN_STATUS_SUCCESS;
   4128 }
   4129 #endif
   4130 
   4131 /* ---------------------------------------------------------------------------------------------- */
   4132 
   4133 /**
   4134  * Populates the internal register id fields for `REG`, `RM`, `NDSNDD`, `BASE` and `INDEX`/`VIDX`
   4135  * encoded operands and performs sanity checks.
   4136  *
   4137  * @param   context     A pointer to the `ZydisDecoderContext` struct.
   4138  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
   4139  * @param   def_reg     The type definition for the `.reg` encoded operand.
   4140  * @param   def_rm      The type definition for the `.rm` encoded operand.
   4141  * @param   def_ndsndd  The type definition for the `.vvvv` encoded operand.
   4142  *
   4143  * @return  A zyan status code.
   4144  *
   4145  * This function sets all unused register ids to `-1`. This rule does currently not apply to
   4146  * `base` and `index`.
   4147  *
   4148  * Definition encoding:
   4149  * - `def_reg`    -> `ZydisRegisterKind`
   4150  * - `def_ndsndd` -> `ZydisRegisterKind`
   4151  * - `def_rm`     -> `ZydisRegisterKind` (`.mod == 3`) or ZydisMemoryOperandType (`.mod != 3`)
   4152  */
   4153 static ZyanStatus ZydisPopulateRegisterIds(ZydisDecoderContext* context,
   4154     const ZydisDecodedInstruction* instruction, ZyanU8 def_reg, ZyanU8 def_rm, ZyanU8 def_ndsndd)
   4155 {
   4156     ZYAN_ASSERT(context);
   4157     ZYAN_ASSERT(instruction);
   4158 
   4159     const ZyanBool is_64_bit = (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64);
   4160     const ZyanBool is_reg    = context->reg_info.is_mod_reg;
   4161     const ZyanBool has_sib   = !is_reg && (instruction->raw.modrm.rm == 4);
   4162     const ZyanBool has_vsib  = has_sib && (def_rm == ZYDIS_MEMOP_TYPE_VSIB);
   4163 
   4164     ZyanU8 id_reg    = instruction->raw.modrm.reg;
   4165     ZyanU8 id_rm     = instruction->raw.modrm.rm;
   4166     ZyanU8 id_ndsndd = is_64_bit ? context->vector_unified.vvvv : context->vector_unified.vvvv & 0x07;
   4167     ZyanU8 id_base   = has_sib ? instruction->raw.sib.base : instruction->raw.modrm.rm;
   4168     ZyanU8 id_index  = instruction->raw.sib.index;
   4169 
   4170     if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
   4171     {
   4172         const ZyanBool is_emvex = (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
   4173                                   (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX);
   4174 
   4175         // The `index` extension by `.v'` is only valid for VSIB operands
   4176         const ZyanU8 vsib_v2 = has_vsib ? context->vector_unified.V2 : 0;
   4177         // The `rm` extension by `.X` is only valid for EVEX/MVEX instructions
   4178         const ZyanU8 evex_x  = is_emvex ? context->vector_unified.X  : 0;
   4179 
   4180         id_reg    |= (context->vector_unified.R2 << 4) | (context->vector_unified.R << 3);
   4181         id_rm     |= (evex_x                     << 4) | (context->vector_unified.B << 3);
   4182         id_ndsndd |= (context->vector_unified.V2 << 4)                                   ;
   4183         id_base   |=                                     (context->vector_unified.B << 3);
   4184         id_index  |= (vsib_v2                    << 4) | (context->vector_unified.X << 3);
   4185 
   4186         // The masking emulates the actual CPU behavior and does not verify if the resulting ids
   4187         // are actually valid for the given register kind.
   4188 
   4189         static const ZyanU8 mask_reg[ZYDIS_REGKIND_MAX_VALUE + 1] =
   4190         {
   4191             /* INVALID */ 0,
   4192             /* GPR     */ (1 << 5) - 1,
   4193             /* X87     */ (1 << 3) - 1, // ignore `.R`, ignore `.R'`
   4194             /* MMX     */ (1 << 3) - 1, // ignore `.R`, ignore `.R'`
   4195             /* VR      */ (1 << 5) - 1,
   4196             /* TMM     */ (1 << 5) - 1,
   4197             /* SEGMENT */ (1 << 3) - 1, // ignore `.R`, ignore `.R'`
   4198             /* TEST    */ (1 << 3) - 1, // ignore `.R`, ignore `.R'`
   4199             /* CONTROL */ (1 << 4) - 1, //              ignore `.R'`
   4200             /* DEBUG   */ (1 << 4) - 1, //              ignore `.R'`
   4201             /* MASK    */ (1 << 5) - 1,
   4202             /* BOUND   */ (1 << 4) - 1  //              ignore `.R'`
   4203         };
   4204         id_reg &= mask_reg[def_reg];
   4205 
   4206         static const ZyanU8 mask_rm[ZYDIS_REGKIND_MAX_VALUE + 1] =
   4207         {
   4208             /* INVALID */ 0,
   4209             /* GPR     */ (1 << 4) - 1, //              ignore `.X`
   4210             /* X87     */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
   4211             /* MMX     */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
   4212             /* VR      */ (1 << 5) - 1,
   4213             /* TMM     */ (1 << 4) - 1, //              ignore `.X`
   4214             /* SEGMENT */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
   4215             /* TEST    */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
   4216             /* CONTROL */ (1 << 4) - 1, //              ignore `.X`
   4217             /* DEBUG   */ (1 << 4) - 1, //              ignore `.X`
   4218             /* MASK    */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
   4219             /* BOUND   */ (1 << 4) - 1  //              ignore `.X`
   4220         };
   4221         id_rm &= (is_reg ? mask_rm[def_rm] : 0xFF);
   4222 
   4223         // Commented out for future reference. Not required at the moment as it's always either
   4224         // a "take all" or "take nothing" situation.
   4225 
   4226         //static const ZyanU8 mask_ndsndd[ZYDIS_REGKIND_MAX_VALUE + 1] =
   4227         //{
   4228         //    /* INVALID */ 0,
   4229         //    /* GPR     */ (1 << 5) - 1,
   4230         //    /* X87     */ 0,            // never encoded in `.vvvv`
   4231         //    /* MMX     */ 0,            // never encoded in `.vvvv`
   4232         //    /* VR      */ (1 << 5) - 1,
   4233         //    /* TMM     */ (1 << 5) - 1,
   4234         //    /* SEGMENT */ 0,            // never encoded in `.vvvv`
   4235         //    /* TEST    */ 0,            // never encoded in `.vvvv`
   4236         //    /* CONTROL */ 0,            // never encoded in `.vvvv`
   4237         //    /* DEBUG   */ 0,            // never encoded in `.vvvv`
   4238         //    /* MASK    */ (1 << 5) - 1,
   4239         //    /* BOUND   */ 0             // never encoded in `.vvvv`
   4240         //};
   4241     }
   4242 
   4243     // Validate
   4244 
   4245     // `.vvvv` is not allowed, if the instruction does not encode a NDS/NDD operand
   4246     if (!def_ndsndd && context->vector_unified.vvvv)
   4247     {
   4248         return ZYDIS_STATUS_BAD_REGISTER;
   4249     }
   4250     // `.v'` is not allowed, if the instruction does not encode a NDS/NDD or VSIB operand
   4251     if (!def_ndsndd && !has_vsib && context->vector_unified.V2)
   4252     {
   4253         return ZYDIS_STATUS_BAD_REGISTER;
   4254     }
   4255 
   4256     static const ZyanU8 available_regs[2][ZYDIS_REGKIND_MAX_VALUE + 1] =
   4257     {
   4258         // 16/32 bit mode
   4259         {
   4260             /* INVALID */ 255,
   4261             /* GPR     */   8,
   4262             /* X87     */   8,
   4263             /* MMX     */   8,
   4264             /* VR      */   8,
   4265             /* TMM     */   8,
   4266             /* SEGMENT */   6,
   4267             /* TEST    */   8,
   4268             /* CONTROL */   8,
   4269             /* DEBUG   */   8,
   4270             /* MASK    */   8,
   4271             /* BOUND   */   4
   4272         },
   4273         // 64 bit mode
   4274         {
   4275             /* INVALID */ 255,
   4276             /* GPR     */  16,
   4277             /* X87     */   8,
   4278             /* MMX     */   8,
   4279             /* VR      */  32,
   4280             /* TMM     */   8,
   4281             /* SEGMENT */   6,
   4282             /* TEST    */   8,
   4283             /* CONTROL */  16,
   4284             // Attempts to reference DR8..DR15 result in undefined opcode (#UD) exceptions. DR4 and
   4285             // DR5 are only valid, if the debug extension (DE) flag in CR4 is set. As we can't
   4286             // check this at runtime we just allow them.
   4287             /* DEBUG   */   8,
   4288             /* MASK    */   8,
   4289             /* BOUND   */   4
   4290         }
   4291     };
   4292 
   4293     if ((id_reg >= available_regs[is_64_bit][def_reg]) ||
   4294         (id_ndsndd >= available_regs[is_64_bit][def_ndsndd]) ||
   4295         (is_reg && (id_rm >= available_regs[is_64_bit][def_rm])))
   4296     {
   4297         return ZYDIS_STATUS_BAD_REGISTER;
   4298     }
   4299 
   4300     ZyanI8 id_cr = -1;
   4301     if (def_reg == ZYDIS_REGKIND_CONTROL)
   4302     {
   4303         id_cr = id_reg;
   4304     }
   4305     if (is_reg && (def_rm == ZYDIS_REGKIND_CONTROL))
   4306     {
   4307         id_cr = id_rm;
   4308     }
   4309     if (id_cr >= 0)
   4310     {
   4311         // Attempts to reference CR1, CR5, CR6, CR7, and CR9..CR15 result in undefined opcode (#UD)
   4312         // exceptions
   4313         static const ZyanU8 lookup[16] =
   4314         {
   4315             1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0
   4316         };
   4317         ZYAN_ASSERT((ZyanUSize)id_cr < ZYAN_ARRAY_LENGTH(lookup));
   4318         if (!lookup[id_cr])
   4319         {
   4320             return ZYDIS_STATUS_BAD_REGISTER;
   4321         }
   4322     }
   4323 
   4324     // Assign to context
   4325 
   4326     context->reg_info.id_reg    = def_reg          ? id_reg    : -1;
   4327     context->reg_info.id_rm     = def_rm && is_reg ? id_rm     : -1;
   4328     context->reg_info.id_ndsndd = def_ndsndd       ? id_ndsndd : -1;
   4329     context->reg_info.id_base   = id_base;  // TODO: Set unused register to -1 as well
   4330     context->reg_info.id_index  = id_index; // TODO: Set unused register to -1 as well
   4331 
   4332     return ZYAN_STATUS_SUCCESS;
   4333 }
   4334 
   4335 /**
   4336  * Checks for certain post-decode error-conditions.
   4337  *
   4338  * @param   state       A pointer to the `ZydisDecoderState` struct.
   4339  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
   4340  * @param   definition  A pointer to the `ZydisInstructionDefinition` struct.
   4341  *
   4342  * @return  A zyan status code.
   4343  *
   4344  * This function is called immediately after a valid instruction-definition was found.
   4345  */
   4346 static ZyanStatus ZydisCheckErrorConditions(ZydisDecoderState* state,
   4347     const ZydisDecodedInstruction* instruction, const ZydisInstructionDefinition* definition)
   4348 {
   4349     ZYAN_ASSERT(state);
   4350     ZYAN_ASSERT(instruction);
   4351     ZYAN_ASSERT(definition);
   4352 
   4353     ZyanU8 def_reg                  = definition->op_reg;
   4354     ZyanU8 def_rm                   = definition->op_rm;
   4355     ZyanU8 def_ndsndd               = ZYDIS_REGKIND_INVALID;
   4356     ZyanBool is_gather              = ZYAN_FALSE;
   4357     ZyanBool no_source_dest_match   = ZYAN_FALSE;
   4358     ZyanBool no_source_source_match = ZYAN_FALSE;
   4359 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
   4360     ZydisMaskPolicy mask_policy     = ZYDIS_MASK_POLICY_INVALID;
   4361 #endif
   4362 
   4363     switch (instruction->encoding)
   4364     {
   4365     case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
   4366     {
   4367         const ZydisInstructionDefinitionLEGACY* def =
   4368             (const ZydisInstructionDefinitionLEGACY*)definition;
   4369 
   4370         if (def->requires_protected_mode &&
   4371             (instruction->machine_mode == ZYDIS_MACHINE_MODE_REAL_16))
   4372         {
   4373             return ZYDIS_STATUS_DECODING_ERROR;
   4374         }
   4375 
   4376         if (def->no_compat_mode &&
   4377             ((instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_COMPAT_16) ||
   4378              (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_COMPAT_32)))
   4379         {
   4380             return ZYDIS_STATUS_DECODING_ERROR;
   4381         }
   4382 
   4383         if (state->prefixes.has_lock && !def->accepts_LOCK)
   4384         {
   4385             return ZYDIS_STATUS_ILLEGAL_LOCK;
   4386         }
   4387         break;
   4388     }
   4389     case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
   4390     {
   4391         break;
   4392     }
   4393     case ZYDIS_INSTRUCTION_ENCODING_XOP:
   4394     {
   4395         const ZydisInstructionDefinitionXOP* def =
   4396             (const ZydisInstructionDefinitionXOP*)definition;
   4397         def_ndsndd = def->op_ndsndd;
   4398         break;
   4399     }
   4400     case ZYDIS_INSTRUCTION_ENCODING_VEX:
   4401     {
   4402         const ZydisInstructionDefinitionVEX* def =
   4403             (const ZydisInstructionDefinitionVEX*)definition;
   4404         def_ndsndd             = def->op_ndsndd;
   4405         is_gather              = def->is_gather;
   4406         no_source_source_match = def->no_source_source_match;
   4407         break;
   4408     }
   4409     case ZYDIS_INSTRUCTION_ENCODING_EVEX:
   4410     {
   4411 #ifndef ZYDIS_DISABLE_AVX512
   4412         const ZydisInstructionDefinitionEVEX* def =
   4413             (const ZydisInstructionDefinitionEVEX*)definition;
   4414         def_ndsndd           = def->op_ndsndd;
   4415         is_gather            = def->is_gather;
   4416         no_source_dest_match = def->no_source_dest_match;
   4417         mask_policy          = def->mask_policy;
   4418 
   4419         // Check for invalid zero-mask
   4420         if ((instruction->raw.evex.z) && (!def->accepts_zero_mask))
   4421         {
   4422             return ZYDIS_STATUS_INVALID_MASK; // TODO: Dedicated status code
   4423         }
   4424 #else
   4425         ZYAN_UNREACHABLE;
   4426 #endif
   4427         break;
   4428     }
   4429     case ZYDIS_INSTRUCTION_ENCODING_MVEX:
   4430     {
   4431 #ifndef ZYDIS_DISABLE_KNC
   4432         const ZydisInstructionDefinitionMVEX* def =
   4433             (const ZydisInstructionDefinitionMVEX*)definition;
   4434         def_ndsndd  = def->op_ndsndd;
   4435         is_gather   = def->is_gather;
   4436         mask_policy = def->mask_policy;
   4437 
   4438         // Check for invalid MVEX.SSS values
   4439         static const ZyanU8 lookup[26][8] =
   4440         {
   4441             // ZYDIS_MVEX_FUNC_IGNORED
   4442             { 1, 1, 1, 1, 1, 1, 1, 1 },
   4443             // ZYDIS_MVEX_FUNC_INVALID
   4444             { 1, 0, 0, 0, 0, 0, 0, 0 },
   4445             // ZYDIS_MVEX_FUNC_RC
   4446             { 1, 1, 1, 1, 1, 1, 1, 1 },
   4447             // ZYDIS_MVEX_FUNC_SAE
   4448             { 1, 1, 1, 1, 1, 1, 1, 1 },
   4449             // ZYDIS_MVEX_FUNC_F_32
   4450             { 1, 0, 0, 0, 0, 0, 0, 0 },
   4451             // ZYDIS_MVEX_FUNC_I_32
   4452             { 1, 0, 0, 0, 0, 0, 0, 0 },
   4453             // ZYDIS_MVEX_FUNC_F_64
   4454             { 1, 0, 0, 0, 0, 0, 0, 0 },
   4455             // ZYDIS_MVEX_FUNC_I_64
   4456             { 1, 0, 0, 0, 0, 0, 0, 0 },
   4457             // ZYDIS_MVEX_FUNC_SWIZZLE_32
   4458             { 1, 1, 1, 1, 1, 1, 1, 1 },
   4459             // ZYDIS_MVEX_FUNC_SWIZZLE_64
   4460             { 1, 1, 1, 1, 1, 1, 1, 1 },
   4461             // ZYDIS_MVEX_FUNC_SF_32
   4462             { 1, 1, 1, 1, 1, 0, 1, 1 },
   4463             // ZYDIS_MVEX_FUNC_SF_32_BCST
   4464             { 1, 1, 1, 0, 0, 0, 0, 0 },
   4465             // ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16
   4466             { 1, 0, 1, 0, 0, 0, 0, 0 },
   4467             // ZYDIS_MVEX_FUNC_SF_64
   4468             { 1, 1, 1, 0, 0, 0, 0, 0 },
   4469             // ZYDIS_MVEX_FUNC_SI_32
   4470             { 1, 1, 1, 0, 1, 1, 1, 1 },
   4471             // ZYDIS_MVEX_FUNC_SI_32_BCST
   4472             { 1, 1, 1, 0, 0, 0, 0, 0 },
   4473             // ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16
   4474             { 1, 0, 1, 0, 0, 0, 0, 0 },
   4475             // ZYDIS_MVEX_FUNC_SI_64
   4476             { 1, 1, 1, 0, 0, 0, 0, 0 },
   4477             // ZYDIS_MVEX_FUNC_UF_32
   4478             { 1, 0, 0, 1, 1, 1, 1, 1 },
   4479             // ZYDIS_MVEX_FUNC_UF_64
   4480             { 1, 0, 0, 0, 0, 0, 0, 0 },
   4481             // ZYDIS_MVEX_FUNC_UI_32
   4482             { 1, 0, 0, 0, 1, 1, 1, 1 },
   4483             // ZYDIS_MVEX_FUNC_UI_64
   4484             { 1, 0, 0, 0, 0, 0, 0, 0 },
   4485             // ZYDIS_MVEX_FUNC_DF_32
   4486             { 1, 0, 0, 1, 1, 1, 1, 1 },
   4487             // ZYDIS_MVEX_FUNC_DF_64
   4488             { 1, 0, 0, 0, 0, 0, 0, 0 },
   4489             // ZYDIS_MVEX_FUNC_DI_32
   4490             { 1, 0, 0, 0, 1, 1, 1, 1 },
   4491             // ZYDIS_MVEX_FUNC_DI_64
   4492             { 1, 0, 0, 0, 0, 0, 0, 0 }
   4493         };
   4494         ZYAN_ASSERT(def->functionality < ZYAN_ARRAY_LENGTH(lookup));
   4495         ZYAN_ASSERT(instruction->raw.mvex.SSS < 8);
   4496         if (!lookup[def->functionality][instruction->raw.mvex.SSS])
   4497         {
   4498             return ZYDIS_STATUS_DECODING_ERROR;
   4499         }
   4500 #else
   4501         ZYAN_UNREACHABLE;
   4502 #endif
   4503         break;
   4504     }
   4505     default:
   4506         ZYAN_UNREACHABLE;
   4507     }
   4508 
   4509     ZydisDecoderContext* context = state->context;
   4510     const ZyanBool is_reg = context->reg_info.is_mod_reg;
   4511 
   4512     ZyanU8 no_rip_rel     = ZYAN_FALSE;
   4513     ZyanU8 is_sr_dest_reg = ZYAN_FALSE;
   4514     ZyanU8 is_sr_dest_rm  = ZYAN_FALSE;
   4515     if (def_reg)
   4516     {
   4517         is_sr_dest_reg = ZYDIS_OPDEF_GET_REG_HIGH_BIT(def_reg);
   4518         def_reg = ZYDIS_OPDEF_GET_REG(def_reg);
   4519     }
   4520     if (def_rm)
   4521     {
   4522         if (is_reg)
   4523         {
   4524             is_sr_dest_rm = ZYDIS_OPDEF_GET_REG_HIGH_BIT(def_rm);
   4525             def_rm = ZYDIS_OPDEF_GET_REG(def_rm);
   4526         }
   4527         else
   4528         {
   4529             no_rip_rel = ZYDIS_OPDEF_GET_MEM_HIGH_BIT(def_rm);
   4530             def_rm = ZYDIS_OPDEF_GET_MEM(def_rm);
   4531         }
   4532     }
   4533 
   4534     // Check RIP-relative memory addressing
   4535     if (no_rip_rel)
   4536     {
   4537         const ZyanBool is_rip_rel =
   4538             (state->decoder->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) &&
   4539             (instruction->raw.modrm.mod == 0) && (instruction->raw.modrm.rm == 5);
   4540         if (is_rip_rel)
   4541         {
   4542             return ZYDIS_STATUS_BAD_REGISTER;
   4543         }
   4544     }
   4545 
   4546     // Populate- and validate register constraints
   4547     ZYAN_CHECK(ZydisPopulateRegisterIds(context, instruction, def_reg, def_rm, def_ndsndd));
   4548 
   4549     // `ZYDIS_REGISTER_CS` is not allowed as `MOV` target
   4550     if (is_sr_dest_reg && (context->reg_info.id_reg == 1))
   4551     {
   4552         return ZYDIS_STATUS_BAD_REGISTER;
   4553     }
   4554     if (is_sr_dest_rm && (context->reg_info.id_rm == 1))
   4555     {
   4556         return ZYDIS_STATUS_BAD_REGISTER;
   4557     }
   4558 
   4559     // Check gather registers
   4560     if (is_gather)
   4561     {
   4562         // ZYAN_ASSERT(has_VSIB);
   4563         ZYAN_ASSERT(instruction->raw.modrm.mod != 3);
   4564         ZYAN_ASSERT(instruction->raw.modrm.rm  == 4);
   4565 
   4566         const ZyanU8 index = context->reg_info.id_index;
   4567         ZyanU8 dest        = context->reg_info.id_reg;
   4568         ZyanU8 mask        = 0xF0;
   4569 
   4570         if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_VEX)
   4571         {
   4572             ZYAN_ASSERT((def_reg    == ZYDIS_REGKIND_VR) &&
   4573                         (def_rm     == ZYDIS_MEMOP_TYPE_VSIB) &&
   4574                         (def_ndsndd == ZYDIS_REGKIND_VR));
   4575             mask = context->reg_info.id_ndsndd;
   4576         }
   4577 
   4578         if ((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
   4579             (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX))
   4580         {
   4581             ZYAN_ASSERT(((def_reg    == ZYDIS_REGKIND_INVALID) ||
   4582                          (def_reg    == ZYDIS_REGKIND_VR)) &&
   4583                          (def_rm     == ZYDIS_MEMOP_TYPE_VSIB) &&
   4584                          (def_ndsndd == ZYDIS_REGKIND_INVALID));
   4585 
   4586             // Some gather instructions (like `VGATHERPF0{D|Q}{PS|PD}`) do not have a destination
   4587             // operand
   4588             if (!def_reg)
   4589             {
   4590                 dest = 0xF1;
   4591             }
   4592         }
   4593 
   4594         // If any pair of the index, mask, or destination registers are the same, the instruction
   4595         // results a UD fault
   4596         if ((dest == index) || (dest == mask) || (index == mask))
   4597         {
   4598             return ZYDIS_STATUS_BAD_REGISTER;
   4599         }
   4600     }
   4601 
   4602     // Check if any source register matches the destination register
   4603     if (no_source_dest_match)
   4604     {
   4605         ZYAN_ASSERT((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
   4606                     (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_VEX));
   4607 
   4608         const ZyanU8 dest    = context->reg_info.id_reg;
   4609         const ZyanU8 source1 = context->reg_info.id_ndsndd;
   4610         const ZyanU8 source2 = context->reg_info.id_rm;
   4611 
   4612         if ((dest == source1) || (is_reg && (dest == source2)))
   4613         {
   4614             return ZYDIS_STATUS_BAD_REGISTER;
   4615         }
   4616     }
   4617 
   4618     // If any pair of the source or destination registers are the same, the instruction results a
   4619     // UD fault
   4620     if (no_source_source_match) // TODO: Find better name
   4621     {
   4622         ZYAN_ASSERT(instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_VEX);
   4623         ZYAN_ASSERT(is_reg);
   4624 
   4625         const ZyanU8 dest    = context->reg_info.id_reg;
   4626         const ZyanU8 source1 = context->reg_info.id_ndsndd;
   4627         const ZyanU8 source2 = context->reg_info.id_rm;
   4628 
   4629         if ((dest == source1) || (dest == source2) || (source1 == source2))
   4630         {
   4631             return ZYDIS_STATUS_BAD_REGISTER;
   4632         }
   4633     }
   4634 
   4635 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
   4636     // Check for invalid MASK registers
   4637     switch (mask_policy)
   4638     {
   4639     case ZYDIS_MASK_POLICY_INVALID:
   4640     case ZYDIS_MASK_POLICY_ALLOWED:
   4641         // Nothing to do here
   4642         break;
   4643     case ZYDIS_MASK_POLICY_REQUIRED:
   4644         if (!context->vector_unified.mask)
   4645         {
   4646             return ZYDIS_STATUS_INVALID_MASK;
   4647         }
   4648         break;
   4649     case ZYDIS_MASK_POLICY_FORBIDDEN:
   4650         if (context->vector_unified.mask)
   4651         {
   4652             return ZYDIS_STATUS_INVALID_MASK;
   4653         }
   4654         break;
   4655     default:
   4656         ZYAN_UNREACHABLE;
   4657     }
   4658 #endif
   4659 
   4660     return ZYAN_STATUS_SUCCESS;
   4661 }
   4662 
   4663 /* ---------------------------------------------------------------------------------------------- */
   4664 
   4665 /**
   4666  * Uses the decoder-tree to decode the current instruction.
   4667  *
   4668  * @param   state       A pointer to the `ZydisDecoderState` struct.
   4669  * @param   instruction A pointer to the `ZydisDecodedInstruction` struct.
   4670  *
   4671  * @return  A zyan status code.
   4672  */
   4673 static ZyanStatus ZydisDecodeInstruction(ZydisDecoderState* state,
   4674     ZydisDecodedInstruction* instruction)
   4675 {
   4676     ZYAN_ASSERT(state);
   4677     ZYAN_ASSERT(instruction);
   4678 
   4679     // Iterate through the decoder tree
   4680     const ZydisDecoderTreeNode* node = ZydisDecoderTreeGetRootNode();
   4681     const ZydisDecoderTreeNode* temp = ZYAN_NULL;
   4682     ZydisDecoderTreeNodeType node_type;
   4683     do
   4684     {
   4685         node_type = node->type;
   4686         ZyanU16 index = 0;
   4687         ZyanStatus status = 0;
   4688         switch (node_type)
   4689         {
   4690         case ZYDIS_NODETYPE_INVALID:
   4691             if (temp)
   4692             {
   4693                 node = temp;
   4694                 temp = ZYAN_NULL;
   4695                 node_type = ZYDIS_NODETYPE_FILTER_MANDATORY_PREFIX;
   4696                 if (state->prefixes.mandatory_candidate != 0x00)
   4697                 {
   4698                     instruction->raw.prefixes[state->prefixes.offset_mandatory].type =
   4699                         ZYDIS_PREFIX_TYPE_IGNORED;
   4700                 }
   4701                 if (state->prefixes.mandatory_candidate == 0x66)
   4702                 {
   4703                     if (state->prefixes.offset_osz_override ==
   4704                         state->prefixes.offset_mandatory)
   4705                     {
   4706                         instruction->raw.prefixes[state->prefixes.offset_mandatory].type =
   4707                             ZYDIS_PREFIX_TYPE_EFFECTIVE;
   4708                     }
   4709                     instruction->attributes |= ZYDIS_ATTRIB_HAS_OPERANDSIZE;
   4710                 }
   4711                 continue;
   4712             }
   4713             return ZYDIS_STATUS_DECODING_ERROR;
   4714         case ZYDIS_NODETYPE_FILTER_XOP:
   4715             status = ZydisNodeHandlerXOP(instruction, &index);
   4716             break;
   4717         case ZYDIS_NODETYPE_FILTER_VEX:
   4718             status = ZydisNodeHandlerVEX(instruction, &index);
   4719             break;
   4720         case ZYDIS_NODETYPE_FILTER_EMVEX:
   4721             status = ZydisNodeHandlerEMVEX(instruction, &index);
   4722             break;
   4723         case ZYDIS_NODETYPE_FILTER_OPCODE:
   4724             status = ZydisNodeHandlerOpcode(state, instruction, &index);
   4725             break;
   4726         case ZYDIS_NODETYPE_FILTER_MODE:
   4727             status = ZydisNodeHandlerMode(instruction, &index);
   4728             break;
   4729         case ZYDIS_NODETYPE_FILTER_MODE_COMPACT:
   4730             status = ZydisNodeHandlerModeCompact(instruction, &index);
   4731             break;
   4732         case ZYDIS_NODETYPE_FILTER_MODRM_MOD:
   4733             status = ZydisNodeHandlerModrmMod(state, instruction, &index);
   4734             break;
   4735         case ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT:
   4736             status = ZydisNodeHandlerModrmModCompact(state, instruction, &index);
   4737             break;
   4738         case ZYDIS_NODETYPE_FILTER_MODRM_REG:
   4739             status = ZydisNodeHandlerModrmReg(state, instruction, &index);
   4740             break;
   4741         case ZYDIS_NODETYPE_FILTER_MODRM_RM:
   4742             status = ZydisNodeHandlerModrmRm(state, instruction, &index);
   4743             break;
   4744         case ZYDIS_NODETYPE_FILTER_PREFIX_GROUP1:
   4745             index = state->prefixes.group1 ? 1 : 0;
   4746             break;
   4747         case ZYDIS_NODETYPE_FILTER_MANDATORY_PREFIX:
   4748             status = ZydisNodeHandlerMandatoryPrefix(state, instruction, &index);
   4749             temp = ZydisDecoderTreeGetChildNode(node, 0);
   4750             // TODO: Return to this point, if index == 0 contains a value and the previous path
   4751             // TODO: was not successful
   4752             // TODO: Restore consumed prefix
   4753             break;
   4754         case ZYDIS_NODETYPE_FILTER_OPERAND_SIZE:
   4755             status = ZydisNodeHandlerOperandSize(state, instruction, &index);
   4756             break;
   4757         case ZYDIS_NODETYPE_FILTER_ADDRESS_SIZE:
   4758             status = ZydisNodeHandlerAddressSize(instruction, &index);
   4759             break;
   4760         case ZYDIS_NODETYPE_FILTER_VECTOR_LENGTH:
   4761             status = ZydisNodeHandlerVectorLength(state->context, instruction, &index);
   4762             break;
   4763         case ZYDIS_NODETYPE_FILTER_REX_W:
   4764             status = ZydisNodeHandlerRexW(state->context, instruction, &index);
   4765             break;
   4766         case ZYDIS_NODETYPE_FILTER_REX_B:
   4767             status = ZydisNodeHandlerRexB(state->context, instruction, &index);
   4768             break;
   4769 #ifndef ZYDIS_DISABLE_AVX512
   4770         case ZYDIS_NODETYPE_FILTER_EVEX_B:
   4771             status = ZydisNodeHandlerEvexB(instruction, &index);
   4772             break;
   4773 #endif
   4774 #ifndef ZYDIS_DISABLE_KNC
   4775         case ZYDIS_NODETYPE_FILTER_MVEX_E:
   4776             status = ZydisNodeHandlerMvexE(instruction, &index);
   4777             break;
   4778 #endif
   4779         case ZYDIS_NODETYPE_FILTER_MODE_AMD:
   4780             index = state->decoder->decoder_mode[ZYDIS_DECODER_MODE_AMD_BRANCHES] ? 1 : 0;
   4781             break;
   4782         case ZYDIS_NODETYPE_FILTER_MODE_KNC:
   4783             index = state->decoder->decoder_mode[ZYDIS_DECODER_MODE_KNC] ? 1 : 0;
   4784             break;
   4785         case ZYDIS_NODETYPE_FILTER_MODE_MPX:
   4786             index = state->decoder->decoder_mode[ZYDIS_DECODER_MODE_MPX] ? 1 : 0;
   4787             break;
   4788         case ZYDIS_NODETYPE_FILTER_MODE_CET:
   4789             index = state->decoder->decoder_mode[ZYDIS_DECODER_MODE_CET] ? 1 : 0;
   4790             break;
   4791         case ZYDIS_NODETYPE_FILTER_MODE_LZCNT:
   4792             index = state->decoder->decoder_mode[ZYDIS_DECODER_MODE_LZCNT] ? 1 : 0;
   4793             break;
   4794         case ZYDIS_NODETYPE_FILTER_MODE_TZCNT:
   4795             index = state->decoder->decoder_mode[ZYDIS_DECODER_MODE_TZCNT] ? 1 : 0;
   4796             break;
   4797         case ZYDIS_NODETYPE_FILTER_MODE_WBNOINVD:
   4798             index = state->decoder->decoder_mode[ZYDIS_DECODER_MODE_WBNOINVD] ? 1 : 0;
   4799             break;
   4800         case ZYDIS_NODETYPE_FILTER_MODE_CLDEMOTE:
   4801             index = state->decoder->decoder_mode[ZYDIS_DECODER_MODE_CLDEMOTE] ? 1 : 0;
   4802             break;
   4803         default:
   4804             if (node_type & ZYDIS_NODETYPE_DEFINITION_MASK)
   4805             {
   4806                 const ZydisInstructionDefinition* definition;
   4807                 ZydisGetInstructionDefinition(instruction->encoding, node->value, &definition);
   4808                 ZydisSetEffectiveOperandWidth(state->context, instruction, definition);
   4809                 ZydisSetEffectiveAddressWidth(state->context, instruction, definition);
   4810 
   4811                 const ZydisInstructionEncodingInfo* info;
   4812                 ZydisGetInstructionEncodingInfo(node, &info);
   4813                 ZYAN_CHECK(ZydisDecodeOptionalInstructionParts(state, instruction, info));
   4814                 ZYAN_CHECK(ZydisCheckErrorConditions(state, instruction, definition));
   4815 
   4816                 if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW)
   4817                 {
   4818                     // Get actual 3DNOW opcode and definition
   4819                     ZYAN_CHECK(ZydisInputNext(state, instruction, &instruction->opcode));
   4820                     node = ZydisDecoderTreeGetRootNode();
   4821                     node = ZydisDecoderTreeGetChildNode(node, 0x0F);
   4822                     node = ZydisDecoderTreeGetChildNode(node, 0x0F);
   4823                     node = ZydisDecoderTreeGetChildNode(node, instruction->opcode);
   4824                     if (node->type == ZYDIS_NODETYPE_INVALID)
   4825                     {
   4826                         return ZYDIS_STATUS_DECODING_ERROR;
   4827                     }
   4828                     ZYAN_ASSERT(node->type == ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT);
   4829                     node = ZydisDecoderTreeGetChildNode(
   4830                         node, (instruction->raw.modrm.mod == 0x3) ? 0 : 1);
   4831                     ZYAN_ASSERT(node->type & ZYDIS_NODETYPE_DEFINITION_MASK);
   4832                     ZydisGetInstructionDefinition(instruction->encoding, node->value, &definition);
   4833                 }
   4834 
   4835                 instruction->mnemonic = definition->mnemonic;
   4836 
   4837 #ifndef ZYDIS_MINIMAL_MODE
   4838 
   4839                 instruction->operand_count = definition->operand_count;
   4840                 instruction->operand_count_visible = definition->operand_count_visible;
   4841                 state->context->definition = definition;
   4842 
   4843                 instruction->meta.category = definition->category;
   4844                 instruction->meta.isa_set = definition->isa_set;
   4845                 instruction->meta.isa_ext = definition->isa_ext;
   4846                 instruction->meta.branch_type = definition->branch_type;
   4847                 ZYAN_ASSERT((instruction->meta.branch_type == ZYDIS_BRANCH_TYPE_NONE) ||
   4848                         ((instruction->meta.category == ZYDIS_CATEGORY_CALL) ||
   4849                          (instruction->meta.category == ZYDIS_CATEGORY_COND_BR) ||
   4850                          (instruction->meta.category == ZYDIS_CATEGORY_UNCOND_BR) ||
   4851                          (instruction->meta.category == ZYDIS_CATEGORY_RET)));
   4852                 instruction->meta.exception_class = definition->exception_class;
   4853 
   4854                 if (!state->decoder->decoder_mode[ZYDIS_DECODER_MODE_MINIMAL])
   4855                 {
   4856                     ZydisSetAttributes(state, instruction, definition);
   4857                     switch (instruction->encoding)
   4858                     {
   4859                     case ZYDIS_INSTRUCTION_ENCODING_XOP:
   4860                     case ZYDIS_INSTRUCTION_ENCODING_VEX:
   4861                     case ZYDIS_INSTRUCTION_ENCODING_EVEX:
   4862                     case ZYDIS_INSTRUCTION_ENCODING_MVEX:
   4863                         ZydisSetAVXInformation(state->context, instruction, definition);
   4864                         break;
   4865                     default:
   4866                         break;
   4867                     }
   4868 
   4869                     const ZydisDefinitionAccessedFlags* flags;
   4870                     if (ZydisGetAccessedFlags(definition, &flags))
   4871                     {
   4872                         instruction->attributes |= ZYDIS_ATTRIB_CPUFLAG_ACCESS;
   4873                     }
   4874                     instruction->cpu_flags = &flags->cpu_flags;
   4875                     instruction->fpu_flags = &flags->fpu_flags;
   4876                 }
   4877 
   4878 #endif
   4879 
   4880                 return ZYAN_STATUS_SUCCESS;
   4881             }
   4882             ZYAN_UNREACHABLE;
   4883         }
   4884         ZYAN_CHECK(status);
   4885         node = ZydisDecoderTreeGetChildNode(node, index);
   4886     } while ((node_type != ZYDIS_NODETYPE_INVALID) && !(node_type & ZYDIS_NODETYPE_DEFINITION_MASK));
   4887     return ZYAN_STATUS_SUCCESS;
   4888 }
   4889 
   4890 /* ---------------------------------------------------------------------------------------------- */
   4891 
   4892 /* ============================================================================================== */
   4893 /* Exported functions                                                                             */
   4894 /* ============================================================================================== */
   4895 
   4896 ZyanStatus ZydisDecoderInit(ZydisDecoder* decoder, ZydisMachineMode machine_mode,
   4897     ZydisStackWidth stack_width)
   4898 {
   4899     static const ZyanBool decoder_modes[ZYDIS_DECODER_MODE_MAX_VALUE + 1] =
   4900     {
   4901 #ifdef ZYDIS_MINIMAL_MODE
   4902         ZYAN_TRUE , // ZYDIS_DECODER_MODE_MINIMAL
   4903 #else
   4904         ZYAN_FALSE, // ZYDIS_DECODER_MODE_MINIMAL
   4905 #endif
   4906         ZYAN_FALSE, // ZYDIS_DECODER_MODE_AMD_BRANCHES
   4907         ZYAN_FALSE, // ZYDIS_DECODER_MODE_KNC
   4908         ZYAN_TRUE , // ZYDIS_DECODER_MODE_MPX
   4909         ZYAN_TRUE , // ZYDIS_DECODER_MODE_CET
   4910         ZYAN_TRUE , // ZYDIS_DECODER_MODE_LZCNT
   4911         ZYAN_TRUE , // ZYDIS_DECODER_MODE_TZCNT
   4912         ZYAN_FALSE, // ZYDIS_DECODER_MODE_WBNOINVD
   4913         ZYAN_TRUE   // ZYDIS_DECODER_MODE_CLDEMOTE
   4914     };
   4915 
   4916     if (!decoder)
   4917     {
   4918         return ZYAN_STATUS_INVALID_ARGUMENT;
   4919     }
   4920     switch (machine_mode)
   4921     {
   4922     case ZYDIS_MACHINE_MODE_LONG_64:
   4923         if (stack_width != ZYDIS_STACK_WIDTH_64)
   4924         {
   4925             return ZYAN_STATUS_INVALID_ARGUMENT;
   4926         }
   4927         break;
   4928     case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
   4929     case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
   4930     case ZYDIS_MACHINE_MODE_LEGACY_32:
   4931     case ZYDIS_MACHINE_MODE_LEGACY_16:
   4932     case ZYDIS_MACHINE_MODE_REAL_16:
   4933         if ((stack_width != ZYDIS_STACK_WIDTH_16) && (stack_width != ZYDIS_STACK_WIDTH_32))
   4934         {
   4935             return ZYAN_STATUS_INVALID_ARGUMENT;
   4936         }
   4937         break;
   4938     default:
   4939         return ZYAN_STATUS_INVALID_ARGUMENT;
   4940     }
   4941 
   4942     decoder->machine_mode = machine_mode;
   4943     decoder->stack_width = stack_width;
   4944     ZYAN_MEMCPY(&decoder->decoder_mode, &decoder_modes, sizeof(decoder_modes));
   4945 
   4946     return ZYAN_STATUS_SUCCESS;
   4947 }
   4948 
   4949 ZyanStatus ZydisDecoderEnableMode(ZydisDecoder* decoder, ZydisDecoderMode mode, ZyanBool enabled)
   4950 {
   4951     if (!decoder || ((ZyanUSize)mode > ZYDIS_DECODER_MODE_MAX_VALUE))
   4952     {
   4953         return ZYAN_STATUS_INVALID_ARGUMENT;
   4954     }
   4955 
   4956 #ifdef ZYDIS_MINIMAL_MODE
   4957     if ((mode == ZYDIS_DECODER_MODE_MINIMAL) && !enabled)
   4958     {
   4959         return ZYAN_STATUS_INVALID_OPERATION;
   4960     }
   4961 #endif
   4962 
   4963     decoder->decoder_mode[mode] = enabled;
   4964 
   4965     return ZYAN_STATUS_SUCCESS;
   4966 }
   4967 
   4968 ZyanStatus ZydisDecoderDecodeFull(const ZydisDecoder* decoder,
   4969     const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction,
   4970     ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT])
   4971 {
   4972     if (!decoder || !instruction || !buffer || !operands)
   4973     {
   4974         return ZYAN_STATUS_INVALID_ARGUMENT;
   4975     }
   4976     if (!length)
   4977     {
   4978         return ZYDIS_STATUS_NO_MORE_DATA;
   4979     }
   4980     if (decoder->decoder_mode[ZYDIS_DECODER_MODE_MINIMAL])
   4981     {
   4982         return ZYAN_STATUS_MISSING_DEPENDENCY; // TODO: Introduce better status code
   4983     }
   4984 
   4985     ZydisDecoderContext context;
   4986     ZYAN_CHECK(ZydisDecoderDecodeInstruction(decoder, &context, buffer, length, instruction));
   4987     ZYAN_CHECK(ZydisDecoderDecodeOperands(decoder, &context, instruction, operands,
   4988         instruction->operand_count));
   4989     ZYAN_MEMSET(&operands[instruction->operand_count], 0,
   4990         (ZYDIS_MAX_OPERAND_COUNT - instruction->operand_count) * sizeof(operands[0]));
   4991 
   4992     return ZYAN_STATUS_SUCCESS;
   4993 }
   4994 
   4995 ZyanStatus ZydisDecoderDecodeInstruction(const ZydisDecoder* decoder, ZydisDecoderContext* context,
   4996     const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction)
   4997 {
   4998     if (!decoder || !instruction || !buffer)
   4999     {
   5000         return ZYAN_STATUS_INVALID_ARGUMENT;
   5001     }
   5002 
   5003     if (!length)
   5004     {
   5005         return ZYDIS_STATUS_NO_MORE_DATA;
   5006     }
   5007 
   5008     ZydisDecoderState state;
   5009     ZYAN_MEMSET(&state, 0, sizeof(state));
   5010     state.decoder = decoder;
   5011     state.buffer = (const ZyanU8*)buffer;
   5012     state.buffer_len = length;
   5013     state.prefixes.offset_notrack = -1;
   5014 
   5015     ZydisDecoderContext default_context;
   5016     if (!context)
   5017     {
   5018         // Use a fallback context if no custom one has been provided
   5019         context = &default_context;
   5020     }
   5021     ZYAN_MEMSET(context, 0, sizeof(*context));
   5022     state.context = context;
   5023 
   5024     ZYAN_MEMSET(instruction, 0, sizeof(*instruction));
   5025     instruction->machine_mode = decoder->machine_mode;
   5026     instruction->stack_width = 16 << decoder->stack_width;
   5027 
   5028     ZYAN_CHECK(ZydisCollectOptionalPrefixes(&state, instruction));
   5029     ZYAN_CHECK(ZydisDecodeInstruction(&state, instruction));
   5030 
   5031     instruction->raw.encoding2 = instruction->encoding;
   5032 
   5033     return ZYAN_STATUS_SUCCESS;
   5034 }
   5035 
   5036 ZyanStatus ZydisDecoderDecodeOperands(const ZydisDecoder* decoder,
   5037     const ZydisDecoderContext* context, const ZydisDecodedInstruction* instruction,
   5038     ZydisDecodedOperand* operands, ZyanU8 operand_count)
   5039 {
   5040 #ifdef ZYDIS_MINIMAL_MODE
   5041 
   5042     ZYAN_UNUSED(decoder);
   5043     ZYAN_UNUSED(context);
   5044     ZYAN_UNUSED(instruction);
   5045     ZYAN_UNUSED(operands);
   5046     ZYAN_UNUSED(operand_count);
   5047 
   5048     return ZYAN_STATUS_MISSING_DEPENDENCY; // TODO: Introduce better status code
   5049 
   5050 #else
   5051 
   5052     if (!decoder || !context || !context->definition || !instruction ||
   5053         (operand_count && !operands) || (operand_count > ZYDIS_MAX_OPERAND_COUNT))
   5054     {
   5055         return ZYAN_STATUS_INVALID_ARGUMENT;
   5056     }
   5057 
   5058     if (decoder->decoder_mode[ZYDIS_DECODER_MODE_MINIMAL])
   5059     {
   5060         return ZYAN_STATUS_MISSING_DEPENDENCY; // TODO: Introduce better status code
   5061     }
   5062 
   5063     operand_count = ZYAN_MIN(operand_count, instruction->operand_count);
   5064     if (!operand_count)
   5065     {
   5066         return ZYAN_STATUS_SUCCESS;
   5067     }
   5068 
   5069     return ZydisDecodeOperands(decoder, context, instruction, operands, operand_count);
   5070 
   5071 #endif
   5072 }
   5073 
   5074 /* ============================================================================================== */