Coverage Report

Created: 2026-01-10 06:09

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