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