tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Decoder.c (184736B)


      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 "zydis/Zycore/LibC.h"
     35 #include "zydis/Zydis/Decoder.h"
     36 #include "zydis/Zydis/Status.h"
     37 #include "zydis/Zydis/Internal/DecoderData.h"
     38 #include "zydis/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 static 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 & (1 << 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 & (1 << 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 & (1 << ZYDIS_DECODER_MODE_AMD_BRANCHES));
   4781            break;
   4782        case ZYDIS_NODETYPE_FILTER_MODE_KNC:
   4783            index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_KNC));
   4784            break;
   4785        case ZYDIS_NODETYPE_FILTER_MODE_MPX:
   4786            index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_MPX));
   4787            break;
   4788        case ZYDIS_NODETYPE_FILTER_MODE_CET:
   4789            index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_CET));
   4790            break;
   4791        case ZYDIS_NODETYPE_FILTER_MODE_LZCNT:
   4792            index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_LZCNT));
   4793            break;
   4794        case ZYDIS_NODETYPE_FILTER_MODE_TZCNT:
   4795            index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_TZCNT));
   4796            break;
   4797        case ZYDIS_NODETYPE_FILTER_MODE_WBNOINVD:
   4798            index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_WBNOINVD));
   4799            break;
   4800        case ZYDIS_NODETYPE_FILTER_MODE_CLDEMOTE:
   4801            index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_CLDEMOTE));
   4802            break;
   4803        case ZYDIS_NODETYPE_FILTER_MODE_IPREFETCH:
   4804            index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_IPREFETCH));
   4805            break;
   4806        case ZYDIS_NODETYPE_FILTER_MODE_UD0_COMPAT:
   4807            index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_UD0_COMPAT));
   4808            break;
   4809        default:
   4810            if (node_type & ZYDIS_NODETYPE_DEFINITION_MASK)
   4811            {
   4812                const ZydisInstructionDefinition* definition;
   4813                ZydisGetInstructionDefinition(instruction->encoding, node->value, &definition);
   4814                ZydisSetEffectiveOperandWidth(state->context, instruction, definition);
   4815                ZydisSetEffectiveAddressWidth(state->context, instruction, definition);
   4816 
   4817                const ZydisInstructionEncodingInfo* info;
   4818                ZydisGetInstructionEncodingInfo(node, &info);
   4819                ZYAN_CHECK(ZydisDecodeOptionalInstructionParts(state, instruction, info));
   4820                ZYAN_CHECK(ZydisCheckErrorConditions(state, instruction, definition));
   4821 
   4822                if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW)
   4823                {
   4824                    // Get actual 3DNOW opcode and definition
   4825                    ZYAN_CHECK(ZydisInputNext(state, instruction, &instruction->opcode));
   4826                    node = ZydisDecoderTreeGetRootNode();
   4827                    node = ZydisDecoderTreeGetChildNode(node, 0x0F);
   4828                    node = ZydisDecoderTreeGetChildNode(node, 0x0F);
   4829                    node = ZydisDecoderTreeGetChildNode(node, instruction->opcode);
   4830                    if (node->type == ZYDIS_NODETYPE_INVALID)
   4831                    {
   4832                        return ZYDIS_STATUS_DECODING_ERROR;
   4833                    }
   4834                    ZYAN_ASSERT(node->type == ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT);
   4835                    node = ZydisDecoderTreeGetChildNode(
   4836                        node, (instruction->raw.modrm.mod == 0x3) ? 0 : 1);
   4837                    ZYAN_ASSERT(node->type & ZYDIS_NODETYPE_DEFINITION_MASK);
   4838                    ZydisGetInstructionDefinition(instruction->encoding, node->value, &definition);
   4839                }
   4840 
   4841                instruction->mnemonic = definition->mnemonic;
   4842 
   4843 #ifndef ZYDIS_MINIMAL_MODE
   4844 
   4845                instruction->operand_count = definition->operand_count;
   4846                instruction->operand_count_visible = definition->operand_count_visible;
   4847                state->context->definition = definition;
   4848 
   4849                instruction->meta.category = definition->category;
   4850                instruction->meta.isa_set = definition->isa_set;
   4851                instruction->meta.isa_ext = definition->isa_ext;
   4852                instruction->meta.branch_type = definition->branch_type;
   4853                ZYAN_ASSERT((instruction->meta.branch_type == ZYDIS_BRANCH_TYPE_NONE) ||
   4854                        ((instruction->meta.category == ZYDIS_CATEGORY_CALL) ||
   4855                         (instruction->meta.category == ZYDIS_CATEGORY_COND_BR) ||
   4856                         (instruction->meta.category == ZYDIS_CATEGORY_UNCOND_BR) ||
   4857                         (instruction->meta.category == ZYDIS_CATEGORY_RET)));
   4858                instruction->meta.exception_class = definition->exception_class;
   4859 
   4860                if (!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_MINIMAL)))
   4861                {
   4862                    ZydisSetAttributes(state, instruction, definition);
   4863                    switch (instruction->encoding)
   4864                    {
   4865                    case ZYDIS_INSTRUCTION_ENCODING_XOP:
   4866                    case ZYDIS_INSTRUCTION_ENCODING_VEX:
   4867                    case ZYDIS_INSTRUCTION_ENCODING_EVEX:
   4868                    case ZYDIS_INSTRUCTION_ENCODING_MVEX:
   4869                        ZydisSetAVXInformation(state->context, instruction, definition);
   4870                        break;
   4871                    default:
   4872                        break;
   4873                    }
   4874 
   4875                    const ZydisDefinitionAccessedFlags* flags;
   4876                    if (ZydisGetAccessedFlags(definition, &flags))
   4877                    {
   4878                        instruction->attributes |= ZYDIS_ATTRIB_CPUFLAG_ACCESS;
   4879                    }
   4880                    instruction->cpu_flags = &flags->cpu_flags;
   4881                    instruction->fpu_flags = &flags->fpu_flags;
   4882                }
   4883 
   4884 #endif
   4885 
   4886                return ZYAN_STATUS_SUCCESS;
   4887            }
   4888            ZYAN_UNREACHABLE;
   4889        }
   4890        ZYAN_CHECK(status);
   4891        node = ZydisDecoderTreeGetChildNode(node, index);
   4892    } while ((node_type != ZYDIS_NODETYPE_INVALID) && !(node_type & ZYDIS_NODETYPE_DEFINITION_MASK));
   4893    return ZYAN_STATUS_SUCCESS;
   4894 }
   4895 
   4896 /* ---------------------------------------------------------------------------------------------- */
   4897 
   4898 /* ============================================================================================== */
   4899 /* Exported functions                                                                             */
   4900 /* ============================================================================================== */
   4901 
   4902 ZyanStatus ZydisDecoderInit(ZydisDecoder* decoder, ZydisMachineMode machine_mode,
   4903    ZydisStackWidth stack_width)
   4904 {
   4905    ZYAN_STATIC_ASSERT(ZYDIS_DECODER_MODE_MAX_VALUE <= 32);
   4906 
   4907    static const ZyanU32 decoder_modes =
   4908 #ifdef ZYDIS_MINIMAL_MODE
   4909        (1 << ZYDIS_DECODER_MODE_MINIMAL) |
   4910 #endif
   4911        (1 << ZYDIS_DECODER_MODE_MPX) |
   4912        (1 << ZYDIS_DECODER_MODE_CET) |
   4913        (1 << ZYDIS_DECODER_MODE_LZCNT) |
   4914        (1 << ZYDIS_DECODER_MODE_TZCNT) |
   4915        (1 << ZYDIS_DECODER_MODE_CLDEMOTE) |
   4916        (1 << ZYDIS_DECODER_MODE_IPREFETCH);
   4917 
   4918    if (!decoder)
   4919    {
   4920        return ZYAN_STATUS_INVALID_ARGUMENT;
   4921    }
   4922    switch (machine_mode)
   4923    {
   4924    case ZYDIS_MACHINE_MODE_LONG_64:
   4925        if (stack_width != ZYDIS_STACK_WIDTH_64)
   4926        {
   4927            return ZYAN_STATUS_INVALID_ARGUMENT;
   4928        }
   4929        break;
   4930    case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
   4931    case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
   4932    case ZYDIS_MACHINE_MODE_LEGACY_32:
   4933    case ZYDIS_MACHINE_MODE_LEGACY_16:
   4934    case ZYDIS_MACHINE_MODE_REAL_16:
   4935        if ((stack_width != ZYDIS_STACK_WIDTH_16) && (stack_width != ZYDIS_STACK_WIDTH_32))
   4936        {
   4937            return ZYAN_STATUS_INVALID_ARGUMENT;
   4938        }
   4939        break;
   4940    default:
   4941        return ZYAN_STATUS_INVALID_ARGUMENT;
   4942    }
   4943 
   4944    decoder->machine_mode = machine_mode;
   4945    decoder->stack_width = stack_width;
   4946    decoder->decoder_mode = decoder_modes;
   4947 
   4948    return ZYAN_STATUS_SUCCESS;
   4949 }
   4950 
   4951 ZyanStatus ZydisDecoderEnableMode(ZydisDecoder* decoder, ZydisDecoderMode mode, ZyanBool enabled)
   4952 {
   4953    if (!decoder || ((ZyanUSize)mode > ZYDIS_DECODER_MODE_MAX_VALUE))
   4954    {
   4955        return ZYAN_STATUS_INVALID_ARGUMENT;
   4956    }
   4957 
   4958 #ifdef ZYDIS_MINIMAL_MODE
   4959    if ((mode == ZYDIS_DECODER_MODE_MINIMAL) && !enabled)
   4960    {
   4961        return ZYAN_STATUS_INVALID_OPERATION;
   4962    }
   4963 #endif
   4964 
   4965    if (enabled)
   4966    {
   4967        decoder->decoder_mode |= (1 << mode);
   4968    }
   4969    else
   4970    {
   4971        decoder->decoder_mode &= ~(1 << mode);
   4972    }
   4973 
   4974    return ZYAN_STATUS_SUCCESS;
   4975 }
   4976 
   4977 ZyanStatus ZydisDecoderDecodeFull(const ZydisDecoder* decoder,
   4978    const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction,
   4979    ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT])
   4980 {
   4981    if (!decoder || !instruction || !buffer || !operands)
   4982    {
   4983        return ZYAN_STATUS_INVALID_ARGUMENT;
   4984    }
   4985    if (!length)
   4986    {
   4987        return ZYDIS_STATUS_NO_MORE_DATA;
   4988    }
   4989    if (decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_MINIMAL))
   4990    {
   4991        return ZYAN_STATUS_MISSING_DEPENDENCY; // TODO: Introduce better status code
   4992    }
   4993 
   4994    ZydisDecoderContext context;
   4995    ZYAN_CHECK(ZydisDecoderDecodeInstruction(decoder, &context, buffer, length, instruction));
   4996    ZYAN_CHECK(ZydisDecoderDecodeOperands(decoder, &context, instruction, operands,
   4997        instruction->operand_count));
   4998    ZYAN_MEMSET(&operands[instruction->operand_count], 0,
   4999        (ZYDIS_MAX_OPERAND_COUNT - instruction->operand_count) * sizeof(operands[0]));
   5000 
   5001    return ZYAN_STATUS_SUCCESS;
   5002 }
   5003 
   5004 ZyanStatus ZydisDecoderDecodeInstruction(const ZydisDecoder* decoder, ZydisDecoderContext* context,
   5005    const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction)
   5006 {
   5007    if (!decoder || !instruction || !buffer)
   5008    {
   5009        return ZYAN_STATUS_INVALID_ARGUMENT;
   5010    }
   5011 
   5012    if (!length)
   5013    {
   5014        return ZYDIS_STATUS_NO_MORE_DATA;
   5015    }
   5016 
   5017    ZydisDecoderState state;
   5018    ZYAN_MEMSET(&state, 0, sizeof(state));
   5019    state.decoder = decoder;
   5020    state.buffer = (const ZyanU8*)buffer;
   5021    state.buffer_len = length;
   5022    state.prefixes.offset_notrack = -1;
   5023 
   5024    ZydisDecoderContext default_context;
   5025    if (!context)
   5026    {
   5027        // Use a fallback context if no custom one has been provided
   5028        context = &default_context;
   5029    }
   5030    ZYAN_MEMSET(context, 0, sizeof(*context));
   5031    state.context = context;
   5032 
   5033    ZYAN_MEMSET(instruction, 0, sizeof(*instruction));
   5034    instruction->machine_mode = decoder->machine_mode;
   5035    instruction->stack_width = 16 << decoder->stack_width;
   5036 
   5037    ZYAN_CHECK(ZydisCollectOptionalPrefixes(&state, instruction));
   5038    ZYAN_CHECK(ZydisDecodeInstruction(&state, instruction));
   5039 
   5040    instruction->raw.encoding2 = instruction->encoding;
   5041 
   5042    return ZYAN_STATUS_SUCCESS;
   5043 }
   5044 
   5045 ZyanStatus ZydisDecoderDecodeOperands(const ZydisDecoder* decoder,
   5046    const ZydisDecoderContext* context, const ZydisDecodedInstruction* instruction,
   5047    ZydisDecodedOperand* operands, ZyanU8 operand_count)
   5048 {
   5049 #ifdef ZYDIS_MINIMAL_MODE
   5050 
   5051    ZYAN_UNUSED(decoder);
   5052    ZYAN_UNUSED(context);
   5053    ZYAN_UNUSED(instruction);
   5054    ZYAN_UNUSED(operands);
   5055    ZYAN_UNUSED(operand_count);
   5056 
   5057    return ZYAN_STATUS_MISSING_DEPENDENCY; // TODO: Introduce better status code
   5058 
   5059 #else
   5060 
   5061    if (!decoder || !context || !context->definition || !instruction ||
   5062        (operand_count && !operands) || (operand_count > ZYDIS_MAX_OPERAND_COUNT))
   5063    {
   5064        return ZYAN_STATUS_INVALID_ARGUMENT;
   5065    }
   5066 
   5067    if (decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_MINIMAL))
   5068    {
   5069        return ZYAN_STATUS_MISSING_DEPENDENCY; // TODO: Introduce better status code
   5070    }
   5071 
   5072    operand_count = ZYAN_MIN(operand_count, instruction->operand_count);
   5073    if (!operand_count)
   5074    {
   5075        return ZYAN_STATUS_SUCCESS;
   5076    }
   5077 
   5078    return ZydisDecodeOperands(decoder, context, instruction, operands, operand_count);
   5079 
   5080 #endif
   5081 }
   5082 
   5083 /* ============================================================================================== */