Coverage Report

Created: 2025-11-11 06:38

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