1 /***************************************************************************************************
3 Zyan Disassembler Library (Zydis)
5 Original Author : Florian Bernd
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:
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
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
25 ***************************************************************************************************/
27 // ReSharper disable CppClangTidyClangDiagnosticImplicitFallthrough
28 // ReSharper disable CppClangTidyClangDiagnosticSwitchEnum
29 // ReSharper disable CppClangTidyClangDiagnosticCoveredSwitchDefault
31 // Temporarily disabled due to a LLVM issue:
32 // ReSharper disable CppClangTidyBugproneNarrowingConversions
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>
40 /* ============================================================================================== */
41 /* Internal enums and types */
42 /* ============================================================================================== */
44 /* ---------------------------------------------------------------------------------------------- */
46 /* ---------------------------------------------------------------------------------------------- */
49 * Defines the `ZydisDecoderState` struct.
51 typedef struct ZydisDecoderState_
54 * A pointer to the `ZydisDecoder` instance.
56 const ZydisDecoder
* decoder
;
58 * A pointer to the `ZydisDecoderContext` struct.
60 ZydisDecoderContext
* context
;
66 * The input buffer length.
75 * Signals, if the instruction has a `LOCK` prefix (`F0`).
77 * This prefix originally belongs to group 1, but separating it from the other ones makes
78 * parsing easier for us later.
82 * The effective prefix of group 1 (either `F2` or `F3`).
86 * The effective prefix of group 2 (`2E`, `36`, `3E`, `26`, `64` or `65`).
90 * The effective segment prefix.
92 ZyanU8 effective_segment
;
94 * The prefix that should be treated as the mandatory-prefix, if the
95 * current instruction needs one.
97 * The last `F3`/`F2` prefix has precedence over previous ones and
98 * `F3`/`F2` in general have precedence over `66`.
100 ZyanU8 mandatory_candidate
;
102 * The offset of the effective `LOCK` prefix.
106 * The offset of the effective prefix in group 1.
108 ZyanU8 offset_group1
;
110 * The offset of the effective prefix in group 2.
112 ZyanU8 offset_group2
;
114 * The offset of the operand-size override prefix (`66`).
116 * This is the only prefix in group 3.
118 ZyanU8 offset_osz_override
;
120 * The offset of the address-size override prefix (`67`).
122 * This is the only prefix in group 4.
124 ZyanU8 offset_asz_override
;
126 * The offset of the effective segment prefix.
128 ZyanU8 offset_segment
;
130 * The offset of the mandatory-candidate prefix.
132 ZyanU8 offset_mandatory
;
134 * The offset of a possible `CET` `no-lock` prefix.
136 ZyanI8 offset_notrack
;
140 /* ---------------------------------------------------------------------------------------------- */
141 /* Register encoding */
142 /* ---------------------------------------------------------------------------------------------- */
145 * Defines the `ZydisRegisterEncoding` enum.
147 typedef enum ZydisRegisterEncoding_
149 ZYDIS_REG_ENCODING_INVALID
,
151 * The register-id is encoded as part of the opcode (bits [3..0]).
153 * Possible extension by:
156 ZYDIS_REG_ENCODING_OPCODE
,
158 * The register-id is encoded in `modrm.reg`.
160 * Possible extension by:
162 * - `.R'` (vector only, EVEX/MVEX)
164 ZYDIS_REG_ENCODING_REG
,
166 * The register-id is encoded in `.vvvv`.
168 * Possible extension by:
169 * - `.v'` (vector only, EVEX/MVEX).
171 ZYDIS_REG_ENCODING_NDSNDD
,
173 * The register-id is encoded in `modrm.rm`.
175 * Possible extension by:
177 * - `.X` (vector only, EVEX/MVEX)`
179 ZYDIS_REG_ENCODING_RM
,
181 * The register-id is encoded in `modrm.rm` or `sib.base` (if `SIB` is present).
183 * Possible extension by:
186 ZYDIS_REG_ENCODING_BASE
,
188 * The register-id is encoded in `sib.index`.
190 * Possible extension by:
193 ZYDIS_REG_ENCODING_INDEX
,
195 * The register-id is encoded in `sib.index`.
197 * Possible extension by:
199 * - `.V'` (vector only, EVEX/MVEX)
201 ZYDIS_REG_ENCODING_VIDX
,
203 * The register-id is encoded in an additional 8-bit immediate value.
205 * Bits [7:4] in 64-bit mode with possible extension by bit [3] (vector only), bits [7:5] for
208 ZYDIS_REG_ENCODING_IS4
,
210 * The register-id is encoded in `EVEX.aaa/MVEX.kkk`.
212 ZYDIS_REG_ENCODING_MASK
,
215 * Maximum value of this enum.
217 ZYDIS_REG_ENCODING_MAX_VALUE
= ZYDIS_REG_ENCODING_MASK
,
219 * The minimum number of bits required to represent all values of this enum.
221 ZYDIS_REG_ENCODING_REQUIRED_BITS
= ZYAN_BITS_TO_REPRESENT(ZYDIS_REG_ENCODING_MAX_VALUE
)
222 } ZydisRegisterEncoding
;
224 /* ---------------------------------------------------------------------------------------------- */
226 /* ============================================================================================== */
227 /* Internal functions */
228 /* ============================================================================================== */
230 /* ---------------------------------------------------------------------------------------------- */
231 /* Input helper functions */
232 /* ---------------------------------------------------------------------------------------------- */
235 * Reads one byte from the current read-position of the input data-source.
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.
241 * @return A zyan status code.
243 * This function may fail, if the `ZYDIS_MAX_INSTRUCTION_LENGTH` limit got exceeded, or no more
246 static ZyanStatus
ZydisInputPeek(ZydisDecoderState
* state
,
247 ZydisDecodedInstruction
* instruction
, ZyanU8
* value
)
250 ZYAN_ASSERT(instruction
);
253 if (instruction
->length
>= ZYDIS_MAX_INSTRUCTION_LENGTH
)
255 return ZYDIS_STATUS_INSTRUCTION_TOO_LONG
;
258 if (state
->buffer_len
> 0)
260 *value
= state
->buffer
[0];
261 return ZYAN_STATUS_SUCCESS
;
264 return ZYDIS_STATUS_NO_MORE_DATA
;
268 * Increases the read-position of the input data-source by one byte.
270 * @param state A pointer to the `ZydisDecoderState` instance
271 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
273 * This function is supposed to get called ONLY after a successful call of `ZydisInputPeek`.
275 * This function increases the `length` field of the `ZydisDecodedInstruction` struct by one.
277 static void ZydisInputSkip(ZydisDecoderState
* state
, ZydisDecodedInstruction
* instruction
)
280 ZYAN_ASSERT(instruction
);
281 ZYAN_ASSERT(instruction
->length
< ZYDIS_MAX_INSTRUCTION_LENGTH
);
283 ++instruction
->length
;
289 * Reads one byte from the current read-position of the input data-source and increases
290 * the read-position by one byte afterwards.
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.
296 * @return A zyan status code.
298 * This function acts like a subsequent call of `ZydisInputPeek` and `ZydisInputSkip`.
300 static ZyanStatus
ZydisInputNext(ZydisDecoderState
* state
,
301 ZydisDecodedInstruction
* instruction
, ZyanU8
* value
)
304 ZYAN_ASSERT(instruction
);
307 if (instruction
->length
>= ZYDIS_MAX_INSTRUCTION_LENGTH
)
309 return ZYDIS_STATUS_INSTRUCTION_TOO_LONG
;
312 if (state
->buffer_len
> 0)
314 *value
= state
->buffer
++[0];
315 ++instruction
->length
;
317 return ZYAN_STATUS_SUCCESS
;
320 return ZYDIS_STATUS_NO_MORE_DATA
;
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.
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
331 * @param number_of_bytes The number of bytes to read from the input data-source.
333 * @return A zyan status code.
335 * This function acts like a subsequent call of `ZydisInputPeek` and `ZydisInputSkip`.
337 static ZyanStatus
ZydisInputNextBytes(ZydisDecoderState
* state
,
338 ZydisDecodedInstruction
* instruction
, ZyanU8
* value
, ZyanU8 number_of_bytes
)
341 ZYAN_ASSERT(instruction
);
344 if (instruction
->length
+ number_of_bytes
> ZYDIS_MAX_INSTRUCTION_LENGTH
)
346 return ZYDIS_STATUS_INSTRUCTION_TOO_LONG
;
349 if (state
->buffer_len
>= number_of_bytes
)
351 instruction
->length
+= number_of_bytes
;
353 ZYAN_MEMCPY(value
, state
->buffer
, number_of_bytes
);
354 state
->buffer
+= number_of_bytes
;
355 state
->buffer_len
-= number_of_bytes
;
357 return ZYAN_STATUS_SUCCESS
;
360 return ZYDIS_STATUS_NO_MORE_DATA
;
363 /* ---------------------------------------------------------------------------------------------- */
364 /* Decode functions */
365 /* ---------------------------------------------------------------------------------------------- */
368 * Decodes the `REX`-prefix.
370 * @param context A pointer to the `ZydisDecoderContext` struct.
371 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
372 * @param data The `REX` byte.
374 static void ZydisDecodeREX(ZydisDecoderContext
* context
, ZydisDecodedInstruction
* instruction
,
377 ZYAN_ASSERT(instruction
);
378 ZYAN_ASSERT((data
& 0xF0) == 0x40);
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;
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
;
394 * Decodes the `XOP`-prefix.
396 * @param context A pointer to the `ZydisDecoderContext` struct.
397 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
398 * @param data The `XOP` bytes.
400 * @return A zyan status code.
402 static ZyanStatus
ZydisDecodeXOP(ZydisDecoderContext
* context
,
403 ZydisDecodedInstruction
* instruction
, const ZyanU8 data
[3])
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);
410 if (instruction
->machine_mode
== ZYDIS_MACHINE_MODE_REAL_16
)
412 // XOP is invalid in 16-bit real mode
413 return ZYDIS_STATUS_DECODING_ERROR
;
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;
422 if ((instruction
->raw
.xop
.m_mmmm
< 0x08) || (instruction
->raw
.xop
.m_mmmm
> 0x0A))
424 // Invalid according to the AMD documentation
425 return ZYDIS_STATUS_INVALID_MAP
;
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;
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
);
442 return ZYAN_STATUS_SUCCESS
;
446 * Decodes the `VEX`-prefix.
448 * @param context A pointer to the `ZydisDecoderContext` struct.
449 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
450 * @param data The `VEX` bytes.
452 * @return A zyan status code.
454 static ZyanStatus
ZydisDecodeVEX(ZydisDecoderContext
* context
,
455 ZydisDecodedInstruction
* instruction
, const ZyanU8 data
[3])
457 ZYAN_ASSERT(instruction
);
458 ZYAN_ASSERT((data
[0] == 0xC4) || (data
[0] == 0xC5));
460 if (instruction
->machine_mode
== ZYDIS_MACHINE_MODE_REAL_16
)
462 // VEX is invalid in 16-bit real mode
463 return ZYDIS_STATUS_DECODING_ERROR
;
466 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_VEX
;
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;
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;
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))
501 if (instruction
->raw
.vex
.m_mmmm
> 0x03)
504 // Invalid according to the intel documentation
505 return ZYDIS_STATUS_INVALID_MAP
;
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
);
517 return ZYAN_STATUS_SUCCESS
;
520 #ifndef ZYDIS_DISABLE_AVX512
522 * Decodes the `EVEX`-prefix.
524 * @param context A pointer to the `ZydisDecoderContext` struct.
525 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
526 * @param data The `EVEX` bytes.
528 * @return A zyan status code.
530 static ZyanStatus
ZydisDecodeEVEX(ZydisDecoderContext
* context
,
531 ZydisDecodedInstruction
* instruction
, const ZyanU8 data
[4])
533 ZYAN_ASSERT(instruction
);
534 ZYAN_ASSERT(data
[0] == 0x62);
535 ZYAN_ASSERT(instruction
->raw
.evex
.offset
== instruction
->length
- 4);
537 if (instruction
->machine_mode
== ZYDIS_MACHINE_MODE_REAL_16
)
539 // EVEX is invalid in 16-bit real mode
540 return ZYDIS_STATUS_DECODING_ERROR
;
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;
551 // Invalid according to the intel documentation
552 return ZYDIS_STATUS_MALFORMED_EVEX
;
555 instruction
->raw
.evex
.mmm
= (data
[1] >> 0) & 0x07;
557 if ((instruction
->raw
.evex
.mmm
== 0x00) ||
558 (instruction
->raw
.evex
.mmm
== 0x04) ||
559 (instruction
->raw
.evex
.mmm
== 0x07))
561 // Invalid according to the intel documentation
562 return ZYDIS_STATUS_INVALID_MAP
;
565 instruction
->raw
.evex
.W
= (data
[2] >> 7) & 0x01;
566 instruction
->raw
.evex
.vvvv
= (data
[2] >> 3) & 0x0F;
568 ZYAN_ASSERT(((data
[2] >> 2) & 0x01) == 0x01);
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;
577 if (!instruction
->raw
.evex
.V2
&&
578 (instruction
->machine_mode
!= ZYDIS_MACHINE_MODE_LONG_64
))
580 return ZYDIS_STATUS_MALFORMED_EVEX
;
583 instruction
->raw
.evex
.aaa
= (data
[3] >> 0) & 0x07;
585 if (instruction
->raw
.evex
.z
&& !instruction
->raw
.evex
.aaa
)
587 return ZYDIS_STATUS_INVALID_MASK
; // TODO: Dedicated status code
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
;
601 if (!instruction
->raw
.evex
.V2
&& (instruction
->machine_mode
!= ZYDIS_MACHINE_MODE_LONG_64
))
603 return ZYDIS_STATUS_MALFORMED_EVEX
;
605 if (!instruction
->raw
.evex
.b
&& (context
->vector_unified
.LL
== 3))
607 // LL = 3 is only valid for instructions with embedded rounding control
608 return ZYDIS_STATUS_MALFORMED_EVEX
;
611 return ZYAN_STATUS_SUCCESS
;
615 #ifndef ZYDIS_DISABLE_KNC
617 * Decodes the `MVEX`-prefix.
619 * @param context A pointer to the `ZydisDecoderContext` struct.
620 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
621 * @param data The `MVEX` bytes.
623 * @return A zyan status code.
625 static ZyanStatus
ZydisDecodeMVEX(ZydisDecoderContext
* context
,
626 ZydisDecodedInstruction
* instruction
, const ZyanU8 data
[4])
628 ZYAN_ASSERT(instruction
);
629 ZYAN_ASSERT(data
[0] == 0x62);
630 ZYAN_ASSERT(instruction
->raw
.mvex
.offset
== instruction
->length
- 4);
632 if (instruction
->machine_mode
!= ZYDIS_MACHINE_MODE_LONG_64
)
634 // MVEX is only valid in 64-bit mode
635 return ZYDIS_STATUS_DECODING_ERROR
;
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;
645 if (instruction
->raw
.mvex
.mmmm
> 0x03)
647 // Invalid according to the intel documentation
648 return ZYDIS_STATUS_INVALID_MAP
;
651 instruction
->raw
.mvex
.W
= (data
[2] >> 7) & 0x01;
652 instruction
->raw
.mvex
.vvvv
= (data
[2] >> 3) & 0x0F;
654 ZYAN_ASSERT(((data
[2] >> 2) & 0x01) == 0x00);
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;
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
;
673 return ZYAN_STATUS_SUCCESS
;
678 * Decodes the `ModRM`-byte.
680 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
681 * @param data The `ModRM` byte.
683 static void ZydisDecodeModRM(ZydisDecodedInstruction
* instruction
, ZyanU8 data
)
685 ZYAN_ASSERT(instruction
);
686 ZYAN_ASSERT(!(instruction
->attributes
& ZYDIS_ATTRIB_HAS_MODRM
));
687 ZYAN_ASSERT(instruction
->raw
.modrm
.offset
== instruction
->length
- 1);
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;
696 * Decodes the `SIB`-byte.
698 * @param instruction A pointer to the `ZydisDecodedInstruction` struct
699 * @param data The `SIB` byte.
701 static void ZydisDecodeSIB(ZydisDecodedInstruction
* instruction
, ZyanU8 data
)
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);
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;
715 /* ---------------------------------------------------------------------------------------------- */
718 * Reads a displacement value.
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.
724 * @return A zyan status code.
726 static ZyanStatus
ZydisReadDisplacement(ZydisDecoderState
* state
,
727 ZydisDecodedInstruction
* instruction
, ZyanU8 size
)
730 ZYAN_ASSERT(instruction
);
731 ZYAN_ASSERT(instruction
->raw
.disp
.size
== 0);
733 instruction
->raw
.disp
.size
= size
;
734 instruction
->raw
.disp
.offset
= instruction
->length
;
741 ZYAN_CHECK(ZydisInputNext(state
, instruction
, &value
));
742 instruction
->raw
.disp
.value
= *(ZyanI8
*)&value
;
748 ZYAN_CHECK(ZydisInputNextBytes(state
, instruction
, (ZyanU8
*)&value
, 2));
749 instruction
->raw
.disp
.value
= *(ZyanI16
*)&value
;
755 ZYAN_CHECK(ZydisInputNextBytes(state
, instruction
, (ZyanU8
*)&value
, 4));
756 instruction
->raw
.disp
.value
= *(ZyanI32
*)&value
;
762 ZYAN_CHECK(ZydisInputNextBytes(state
, instruction
, (ZyanU8
*)&value
, 8));
763 instruction
->raw
.disp
.value
= *(ZyanI64
*)&value
;
770 // TODO: Fix endianess on big-endian systems
772 return ZYAN_STATUS_SUCCESS
;
776 * Reads an immediate value.
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.
785 * @return A zyan status code.
787 static ZyanStatus
ZydisReadImmediate(ZydisDecoderState
* state
,
788 ZydisDecodedInstruction
* instruction
, ZyanU8 id
, ZyanU8 size
, ZyanBool is_signed
,
789 ZyanBool is_relative
)
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);
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
;
806 ZYAN_CHECK(ZydisInputNext(state
, instruction
, &value
));
809 instruction
->raw
.imm
[id
].value
.s
= (ZyanI8
)value
;
812 instruction
->raw
.imm
[id
].value
.u
= value
;
819 ZYAN_CHECK(ZydisInputNextBytes(state
, instruction
, (ZyanU8
*)&value
, 2));
822 instruction
->raw
.imm
[id
].value
.s
= (ZyanI16
)value
;
825 instruction
->raw
.imm
[id
].value
.u
= value
;
832 ZYAN_CHECK(ZydisInputNextBytes(state
, instruction
, (ZyanU8
*)&value
, 4));
835 instruction
->raw
.imm
[id
].value
.s
= (ZyanI32
)value
;
838 instruction
->raw
.imm
[id
].value
.u
= value
;
845 ZYAN_CHECK(ZydisInputNextBytes(state
, instruction
, (ZyanU8
*)&value
, 8));
848 instruction
->raw
.imm
[id
].value
.s
= (ZyanI64
)value
;
851 instruction
->raw
.imm
[id
].value
.u
= value
;
859 // TODO: Fix endianess on big-endian systems
861 return ZYAN_STATUS_SUCCESS
;
864 /* ---------------------------------------------------------------------------------------------- */
865 /* Semantic instruction decoding */
866 /* ---------------------------------------------------------------------------------------------- */
868 #ifndef ZYDIS_MINIMAL_MODE
870 * Calculates the register-id for a specific register-encoding and register-class.
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.
877 * @return A zyan status code.
879 * This function calculates the register-id by combining different fields and flags of previously
882 static ZyanU8
ZydisCalcRegisterId(const ZydisDecoderContext
* context
,
883 const ZydisDecodedInstruction
* instruction
, ZydisRegisterEncoding encoding
,
884 ZydisRegisterClass register_class
)
886 ZYAN_ASSERT(context
);
887 ZYAN_ASSERT(instruction
);
889 // TODO: Combine OPCODE and IS4 in `ZydisPopulateRegisterIds` and get rid of this
890 // TODO: function entirely
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
:
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);
916 if (instruction
->machine_mode
!= ZYDIS_MACHINE_MODE_LONG_64
)
920 return value
| (context
->vector_unified
.B
<< 3);
922 case ZYDIS_REG_ENCODING_IS4
:
924 if (instruction
->machine_mode
!= ZYDIS_MACHINE_MODE_LONG_64
)
926 return (instruction
->raw
.imm
[0].value
.u
>> 4) & 0x07;
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
))
934 switch (register_class
)
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);
946 case ZYDIS_REG_ENCODING_MASK
:
947 return context
->vector_unified
.mask
;
954 #ifndef ZYDIS_MINIMAL_MODE
956 * Sets the operand-size and element-specific information for the given operand.
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.
963 static void ZydisSetOperandSizeAndElementInfo(const ZydisDecoderContext
* context
,
964 const ZydisDecodedInstruction
* instruction
, ZydisDecodedOperand
* operand
,
965 const ZydisOperandDefinition
* definition
)
967 ZYAN_ASSERT(context
);
968 ZYAN_ASSERT(instruction
);
969 ZYAN_ASSERT(operand
);
970 ZYAN_ASSERT(definition
);
973 switch (operand
->type
)
975 case ZYDIS_OPERAND_TYPE_REGISTER
:
977 if (definition
->size
[context
->eosz_index
])
979 operand
->size
= definition
->size
[context
->eosz_index
] * 8;
982 operand
->size
= ZydisRegisterGetWidth(instruction
->machine_mode
,
985 operand
->element_type
= ZYDIS_ELEMENT_TYPE_INT
;
986 operand
->element_size
= operand
->size
;
989 case ZYDIS_OPERAND_TYPE_MEMORY
:
990 switch (instruction
->encoding
)
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
)
998 ZYAN_ASSERT(definition
->size
[context
->eosz_index
] == 0);
999 operand
->size
= instruction
->address_width
;
1000 operand
->element_type
= ZYDIS_ELEMENT_TYPE_INT
;
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;
1008 case ZYDIS_INSTRUCTION_ENCODING_EVEX
:
1009 #ifndef ZYDIS_DISABLE_AVX512
1010 if (definition
->size
[context
->eosz_index
])
1012 // Operand size is hardcoded
1013 operand
->size
= definition
->size
[context
->eosz_index
] * 8;
1016 // Operand size depends on the tuple-type, the element-size and the number of
1018 ZYAN_ASSERT(instruction
->avx
.vector_length
);
1019 ZYAN_ASSERT(context
->evex
.element_size
);
1020 switch (context
->evex
.tuple_type
)
1022 case ZYDIS_TUPLETYPE_FV
:
1023 if (instruction
->avx
.broadcast
.mode
)
1025 operand
->size
= context
->evex
.element_size
;
1028 operand
->size
= instruction
->avx
.vector_length
;
1031 case ZYDIS_TUPLETYPE_HV
:
1032 if (instruction
->avx
.broadcast
.mode
)
1034 operand
->size
= context
->evex
.element_size
;
1037 operand
->size
= (ZyanU16
)instruction
->avx
.vector_length
/ 2;
1040 case ZYDIS_TUPLETYPE_QUARTER
:
1041 if (instruction
->avx
.broadcast
.mode
)
1043 operand
->size
= context
->evex
.element_size
;
1047 operand
->size
= (ZyanU16
)instruction
->avx
.vector_length
/ 4;
1054 ZYAN_ASSERT(operand
->size
);
1059 case ZYDIS_INSTRUCTION_ENCODING_MVEX
:
1060 #ifndef ZYDIS_DISABLE_KNC
1061 if (definition
->size
[context
->eosz_index
])
1063 // Operand size is hardcoded
1064 operand
->size
= definition
->size
[context
->eosz_index
] * 8;
1067 ZYAN_ASSERT(definition
->element_type
== ZYDIS_IELEMENT_TYPE_VARIABLE
);
1068 ZYAN_ASSERT(instruction
->avx
.vector_length
== 512);
1070 switch (instruction
->avx
.conversion
.mode
)
1072 case ZYDIS_CONVERSION_MODE_INVALID
:
1073 operand
->size
= 512;
1074 switch (context
->mvex
.functionality
)
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;
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;
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;
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;
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;
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;
1116 case ZYDIS_CONVERSION_MODE_FLOAT16
:
1117 operand
->size
= 256;
1118 operand
->element_type
= ZYDIS_ELEMENT_TYPE_FLOAT16
;
1119 operand
->element_size
= 16;
1121 case ZYDIS_CONVERSION_MODE_SINT16
:
1122 operand
->size
= 256;
1123 operand
->element_type
= ZYDIS_ELEMENT_TYPE_INT
;
1124 operand
->element_size
= 16;
1126 case ZYDIS_CONVERSION_MODE_UINT16
:
1127 operand
->size
= 256;
1128 operand
->element_type
= ZYDIS_ELEMENT_TYPE_UINT
;
1129 operand
->element_size
= 16;
1131 case ZYDIS_CONVERSION_MODE_SINT8
:
1132 operand
->size
= 128;
1133 operand
->element_type
= ZYDIS_ELEMENT_TYPE_INT
;
1134 operand
->element_size
= 8;
1136 case ZYDIS_CONVERSION_MODE_UINT8
:
1137 operand
->size
= 128;
1138 operand
->element_type
= ZYDIS_ELEMENT_TYPE_UINT
;
1139 operand
->element_size
= 8;
1145 switch (instruction
->avx
.broadcast
.mode
)
1147 case ZYDIS_BROADCAST_MODE_INVALID
:
1148 // Nothing to do here
1150 case ZYDIS_BROADCAST_MODE_1_TO_8
:
1151 case ZYDIS_BROADCAST_MODE_1_TO_16
:
1152 operand
->size
= operand
->element_size
;
1154 case ZYDIS_BROADCAST_MODE_4_TO_8
:
1155 case ZYDIS_BROADCAST_MODE_4_TO_16
:
1156 operand
->size
= operand
->element_size
* 4;
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
;
1176 case ZYDIS_OPERAND_TYPE_IMMEDIATE
:
1177 operand
->size
= definition
->size
[context
->eosz_index
] * 8;
1183 // Element-type and -size
1184 if (definition
->element_type
&& (definition
->element_type
!= ZYDIS_IELEMENT_TYPE_VARIABLE
))
1186 ZydisGetElementInfo(definition
->element_type
, &operand
->element_type
,
1187 &operand
->element_size
);
1188 if (!operand
->element_size
)
1190 // The element size is the same as the operand size. This is used for single element
1192 operand
->element_size
= operand
->size
;
1197 if (operand
->element_size
&& operand
->size
&& (operand
->element_type
!= ZYDIS_ELEMENT_TYPE_CC
))
1199 operand
->element_count
= operand
->size
/ operand
->element_size
;
1202 operand
->element_count
= 1;
1207 #ifndef ZYDIS_MINIMAL_MODE
1209 * Decodes an register-operand.
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.
1216 * @return A zyan status code.
1218 static ZyanStatus
ZydisDecodeOperandRegister(const ZydisDecodedInstruction
* instruction
,
1219 ZydisDecodedOperand
* operand
, ZydisRegisterClass register_class
, ZyanU8 register_id
)
1221 ZYAN_ASSERT(instruction
);
1222 ZYAN_ASSERT(operand
);
1224 operand
->type
= ZYDIS_OPERAND_TYPE_REGISTER
;
1226 if (register_class
== ZYDIS_REGCLASS_GPR8
)
1228 if ((instruction
->attributes
& ZYDIS_ATTRIB_HAS_REX
) && (register_id
>= 4))
1230 operand
->reg
.value
= ZYDIS_REGISTER_SPL
+ (register_id
- 4);
1233 operand
->reg
.value
= ZYDIS_REGISTER_AL
+ register_id
;
1237 operand
->reg
.value
= ZydisRegisterEncode(register_class
, register_id
);
1238 ZYAN_ASSERT(operand
->reg
.value
);
1239 /*if (!operand->reg.value)
1241 return ZYAN_STATUS_BAD_REGISTER;
1245 return ZYAN_STATUS_SUCCESS
;
1249 #ifndef ZYDIS_MINIMAL_MODE
1251 * Decodes a memory operand.
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.
1259 * @return A zyan status code.
1261 static ZyanStatus
ZydisDecodeOperandMemory(const ZydisDecoderContext
* context
,
1262 const ZydisDecodedInstruction
* instruction
, ZydisDecodedOperand
* operand
,
1263 ZydisRegisterClass vidx_register_class
)
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))));
1273 operand
->type
= ZYDIS_OPERAND_TYPE_MEMORY
;
1274 operand
->mem
.type
= ZYDIS_MEMOP_TYPE_MEM
;
1276 const ZyanU8 modrm_rm
= instruction
->raw
.modrm
.rm
;
1277 ZyanU8 displacement_size
= 0;
1278 switch (instruction
->address_width
)
1282 static const ZydisRegister bases
[] =
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
1287 static const ZydisRegister indices
[] =
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
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
)
1300 displacement_size
= 16;
1301 operand
->mem
.base
= ZYDIS_REGISTER_NONE
;
1305 displacement_size
= 8;
1308 displacement_size
= 16;
1317 operand
->mem
.base
= ZYDIS_REGISTER_EAX
+ ZydisCalcRegisterId(context
, instruction
,
1318 ZYDIS_REG_ENCODING_BASE
, ZYDIS_REGCLASS_GPR32
);
1319 switch (instruction
->raw
.modrm
.mod
)
1324 if (instruction
->machine_mode
== ZYDIS_MACHINE_MODE_LONG_64
)
1326 operand
->mem
.base
= ZYDIS_REGISTER_EIP
;
1329 operand
->mem
.base
= ZYDIS_REGISTER_NONE
;
1331 displacement_size
= 32;
1335 displacement_size
= 8;
1338 displacement_size
= 32;
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
)
1354 operand
->mem
.index
= ZYDIS_REGISTER_NONE
;
1355 operand
->mem
.scale
= 0;
1357 if (operand
->mem
.base
== ZYDIS_REGISTER_EBP
)
1359 if (instruction
->raw
.modrm
.mod
== 0)
1361 operand
->mem
.base
= ZYDIS_REGISTER_NONE
;
1363 displacement_size
= (instruction
->raw
.modrm
.mod
== 1) ? 8 : 32;
1367 operand
->mem
.index
= ZYDIS_REGISTER_NONE
;
1368 operand
->mem
.scale
= 0;
1374 operand
->mem
.base
= ZYDIS_REGISTER_RAX
+ ZydisCalcRegisterId(context
, instruction
,
1375 ZYDIS_REG_ENCODING_BASE
, ZYDIS_REGCLASS_GPR64
);
1376 switch (instruction
->raw
.modrm
.mod
)
1381 if (instruction
->machine_mode
== ZYDIS_MACHINE_MODE_LONG_64
)
1383 operand
->mem
.base
= ZYDIS_REGISTER_RIP
;
1386 operand
->mem
.base
= ZYDIS_REGISTER_NONE
;
1388 displacement_size
= 32;
1392 displacement_size
= 8;
1395 displacement_size
= 32;
1400 if ((modrm_rm
& 0x07) == 4)
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
)
1411 operand
->mem
.index
= ZYDIS_REGISTER_NONE
;
1412 operand
->mem
.scale
= 0;
1414 if ((operand
->mem
.base
== ZYDIS_REGISTER_RBP
) ||
1415 (operand
->mem
.base
== ZYDIS_REGISTER_R13
))
1417 if (instruction
->raw
.modrm
.mod
== 0)
1419 operand
->mem
.base
= ZYDIS_REGISTER_NONE
;
1421 displacement_size
= (instruction
->raw
.modrm
.mod
== 1) ? 8 : 32;
1425 operand
->mem
.index
= ZYDIS_REGISTER_NONE
;
1426 operand
->mem
.scale
= 0;
1433 if (displacement_size
)
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
;
1439 return ZYAN_STATUS_SUCCESS
;
1443 #ifndef ZYDIS_MINIMAL_MODE
1445 * Decodes an implicit register operand.
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.
1453 static void ZydisDecodeOperandImplicitRegister(const ZydisDecoder
* decoder
,
1454 const ZydisDecoderContext
* context
, const ZydisDecodedInstruction
* instruction
,
1455 ZydisDecodedOperand
* operand
, const ZydisOperandDefinition
* definition
)
1457 ZYAN_ASSERT(context
);
1458 ZYAN_ASSERT(instruction
);
1459 ZYAN_ASSERT(operand
);
1460 ZYAN_ASSERT(definition
);
1462 operand
->type
= ZYDIS_OPERAND_TYPE_REGISTER
;
1464 switch (definition
->op
.reg
.type
)
1466 case ZYDIS_IMPLREG_TYPE_STATIC
:
1467 operand
->reg
.value
= definition
->op
.reg
.reg
.reg
;
1469 case ZYDIS_IMPLREG_TYPE_GPR_OSZ
:
1471 static const ZydisRegisterClass lookup
[3] =
1473 ZYDIS_REGCLASS_GPR16
,
1474 ZYDIS_REGCLASS_GPR32
,
1475 ZYDIS_REGCLASS_GPR64
1477 operand
->reg
.value
=
1478 ZydisRegisterEncode(lookup
[context
->eosz_index
], definition
->op
.reg
.reg
.id
);
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
);
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
;
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
);
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
:
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
;
1517 #ifndef ZYDIS_MINIMAL_MODE
1519 * Decodes an implicit memory operand.
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.
1527 static void ZydisDecodeOperandImplicitMemory(const ZydisDecoder
* decoder
,
1528 const ZydisDecoderContext
* context
, const ZydisDecodedInstruction
* instruction
,
1529 ZydisDecodedOperand
* operand
, const ZydisOperandDefinition
* definition
)
1531 ZYAN_ASSERT(context
);
1532 ZYAN_ASSERT(operand
);
1533 ZYAN_ASSERT(definition
);
1535 static const ZydisRegisterClass lookup
[3] =
1537 ZYDIS_REGCLASS_GPR16
,
1538 ZYDIS_REGCLASS_GPR32
,
1539 ZYDIS_REGCLASS_GPR64
1542 operand
->type
= ZYDIS_OPERAND_TYPE_MEMORY
;
1543 operand
->mem
.type
= ZYDIS_MEMOP_TYPE_MEM
;
1545 switch (definition
->op
.mem
.base
)
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
]));
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
]));
1557 case ZYDIS_IMPLMEM_BASE_AAX
:
1558 operand
->mem
.base
= ZydisRegisterEncode(lookup
[context
->easz_index
], 0);
1560 case ZYDIS_IMPLMEM_BASE_ADX
:
1561 operand
->mem
.base
= ZydisRegisterEncode(lookup
[context
->easz_index
], 2);
1563 case ZYDIS_IMPLMEM_BASE_ABX
:
1564 operand
->mem
.base
= ZydisRegisterEncode(lookup
[context
->easz_index
], 3);
1566 case ZYDIS_IMPLMEM_BASE_ASI
:
1567 operand
->mem
.base
= ZydisRegisterEncode(lookup
[context
->easz_index
], 6);
1569 case ZYDIS_IMPLMEM_BASE_ADI
:
1570 operand
->mem
.base
= ZydisRegisterEncode(lookup
[context
->easz_index
], 7);
1572 case ZYDIS_IMPLMEM_BASE_SSP
:
1573 operand
->mem
.base
= ZydisRegisterEncode(lookup
[decoder
->stack_width
], 4);
1575 case ZYDIS_IMPLMEM_BASE_SBP
:
1576 operand
->mem
.base
= ZydisRegisterEncode(lookup
[decoder
->stack_width
], 5);
1582 if (definition
->op
.mem
.seg
)
1584 operand
->mem
.segment
=
1585 ZydisRegisterEncode(ZYDIS_REGCLASS_SEGMENT
, definition
->op
.mem
.seg
- 1);
1586 ZYAN_ASSERT(operand
->mem
.segment
);
1591 #ifndef ZYDIS_MINIMAL_MODE
1592 static ZyanStatus
ZydisDecodeOperands(const ZydisDecoder
* decoder
, const ZydisDecoderContext
* context
,
1593 const ZydisDecodedInstruction
* instruction
, ZydisDecodedOperand
* operands
, ZyanU8 operand_count
)
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
);
1603 const ZydisInstructionDefinition
* definition
= context
->definition
;
1604 const ZydisOperandDefinition
* operand
= ZydisGetOperandDefinitions(definition
);
1606 ZYAN_MEMSET(operands
, 0, sizeof(ZydisDecodedOperand
) * operand_count
);
1609 for (ZyanU8 i
= 0; i
< operand_count
; ++i
)
1611 ZydisRegisterClass register_class
= ZYDIS_REGCLASS_INVALID
;
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
));
1625 // Implicit operands
1626 switch (operand
->type
)
1628 case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG
:
1629 ZydisDecodeOperandImplicitRegister(decoder
, context
, instruction
, &operands
[i
], operand
);
1631 case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM
:
1632 ZydisDecodeOperandImplicitMemory(decoder
, context
, instruction
, &operands
[i
], operand
);
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
;
1644 if (operands
[i
].type
)
1646 goto FinalizeOperand
;
1649 operands
[i
].encoding
= operand
->op
.encoding
;
1651 // Register operands
1652 switch (operand
->type
)
1654 case ZYDIS_SEMANTIC_OPTYPE_GPR8
:
1655 register_class
= ZYDIS_REGCLASS_GPR8
;
1657 case ZYDIS_SEMANTIC_OPTYPE_GPR16
:
1658 register_class
= ZYDIS_REGCLASS_GPR16
;
1660 case ZYDIS_SEMANTIC_OPTYPE_GPR32
:
1661 register_class
= ZYDIS_REGCLASS_GPR32
;
1663 case ZYDIS_SEMANTIC_OPTYPE_GPR64
:
1664 register_class
= ZYDIS_REGCLASS_GPR64
;
1666 case ZYDIS_SEMANTIC_OPTYPE_GPR16_32_64
:
1667 ZYAN_ASSERT((instruction
->operand_width
== 16) || (instruction
->operand_width
== 32) ||
1668 (instruction
->operand_width
== 64));
1670 (instruction
->operand_width
== 16) ? ZYDIS_REGCLASS_GPR16
: (
1671 (instruction
->operand_width
== 32) ? ZYDIS_REGCLASS_GPR32
: ZYDIS_REGCLASS_GPR64
);
1673 case ZYDIS_SEMANTIC_OPTYPE_GPR32_32_64
:
1674 ZYAN_ASSERT((instruction
->operand_width
== 16) || (instruction
->operand_width
== 32) ||
1675 (instruction
->operand_width
== 64));
1677 (instruction
->operand_width
== 16) ? ZYDIS_REGCLASS_GPR32
: (
1678 (instruction
->operand_width
== 32) ? ZYDIS_REGCLASS_GPR32
: ZYDIS_REGCLASS_GPR64
);
1680 case ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32
:
1681 ZYAN_ASSERT((instruction
->operand_width
== 16) || (instruction
->operand_width
== 32) ||
1682 (instruction
->operand_width
== 64));
1684 (instruction
->operand_width
== 16) ? ZYDIS_REGCLASS_GPR16
: ZYDIS_REGCLASS_GPR32
;
1686 case ZYDIS_SEMANTIC_OPTYPE_GPR_ASZ
:
1687 ZYAN_ASSERT((instruction
->address_width
== 16) || (instruction
->address_width
== 32) ||
1688 (instruction
->address_width
== 64));
1690 (instruction
->address_width
== 16) ? ZYDIS_REGCLASS_GPR16
: (
1691 (instruction
->address_width
== 32) ? ZYDIS_REGCLASS_GPR32
: ZYDIS_REGCLASS_GPR64
);
1693 case ZYDIS_SEMANTIC_OPTYPE_FPR
:
1694 register_class
= ZYDIS_REGCLASS_X87
;
1696 case ZYDIS_SEMANTIC_OPTYPE_MMX
:
1697 register_class
= ZYDIS_REGCLASS_MMX
;
1699 case ZYDIS_SEMANTIC_OPTYPE_XMM
:
1700 register_class
= ZYDIS_REGCLASS_XMM
;
1702 case ZYDIS_SEMANTIC_OPTYPE_YMM
:
1703 register_class
= ZYDIS_REGCLASS_YMM
;
1705 case ZYDIS_SEMANTIC_OPTYPE_ZMM
:
1706 register_class
= ZYDIS_REGCLASS_ZMM
;
1708 case ZYDIS_SEMANTIC_OPTYPE_TMM
:
1709 register_class
= ZYDIS_REGCLASS_TMM
;
1711 case ZYDIS_SEMANTIC_OPTYPE_BND
:
1712 register_class
= ZYDIS_REGCLASS_BOUND
;
1714 case ZYDIS_SEMANTIC_OPTYPE_SREG
:
1715 register_class
= ZYDIS_REGCLASS_SEGMENT
;
1717 case ZYDIS_SEMANTIC_OPTYPE_CR
:
1718 register_class
= ZYDIS_REGCLASS_CONTROL
;
1720 case ZYDIS_SEMANTIC_OPTYPE_DR
:
1721 register_class
= ZYDIS_REGCLASS_DEBUG
;
1723 case ZYDIS_SEMANTIC_OPTYPE_MASK
:
1724 register_class
= ZYDIS_REGCLASS_MASK
;
1731 switch (operand
->op
.encoding
)
1733 case ZYDIS_OPERAND_ENCODING_MODRM_REG
:
1735 ZydisDecodeOperandRegister(
1736 instruction
, &operands
[i
], register_class
,
1737 ZydisCalcRegisterId(
1738 context
, instruction
, ZYDIS_REG_ENCODING_REG
, register_class
)));
1740 case ZYDIS_OPERAND_ENCODING_MODRM_RM
:
1742 ZydisDecodeOperandRegister(
1743 instruction
, &operands
[i
], register_class
,
1744 ZydisCalcRegisterId(
1745 context
, instruction
, ZYDIS_REG_ENCODING_RM
, register_class
)));
1747 case ZYDIS_OPERAND_ENCODING_OPCODE
:
1749 ZydisDecodeOperandRegister(
1750 instruction
, &operands
[i
], register_class
,
1751 ZydisCalcRegisterId(
1752 context
, instruction
, ZYDIS_REG_ENCODING_OPCODE
, register_class
)));
1754 case ZYDIS_OPERAND_ENCODING_NDSNDD
:
1756 ZydisDecodeOperandRegister(
1757 instruction
, &operands
[i
], register_class
,
1758 ZydisCalcRegisterId(
1759 context
, instruction
, ZYDIS_REG_ENCODING_NDSNDD
, register_class
)));
1761 case ZYDIS_OPERAND_ENCODING_MASK
:
1763 ZydisDecodeOperandRegister(
1764 instruction
, &operands
[i
], register_class
,
1765 ZydisCalcRegisterId(
1766 context
, instruction
, ZYDIS_REG_ENCODING_MASK
, register_class
)));
1768 case ZYDIS_OPERAND_ENCODING_IS4
:
1770 ZydisDecodeOperandRegister(
1771 instruction
, &operands
[i
], register_class
,
1772 ZydisCalcRegisterId(
1773 context
, instruction
, ZYDIS_REG_ENCODING_IS4
, register_class
)));
1779 if (operand
->is_multisource4
)
1781 operands
[i
].attributes
|= ZYDIS_OATTRIB_IS_MULTISOURCE4
;
1784 goto FinalizeOperand
;
1788 switch (operand
->type
)
1790 case ZYDIS_SEMANTIC_OPTYPE_MEM
:
1792 ZydisDecodeOperandMemory(
1793 context
, instruction
, &operands
[i
], ZYDIS_REGCLASS_INVALID
));
1795 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBX
:
1797 ZydisDecodeOperandMemory(
1798 context
, instruction
, &operands
[i
], ZYDIS_REGCLASS_XMM
));
1799 operands
[i
].mem
.type
= ZYDIS_MEMOP_TYPE_VSIB
;
1801 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBY
:
1803 ZydisDecodeOperandMemory(
1804 context
, instruction
, &operands
[i
], ZYDIS_REGCLASS_YMM
));
1805 operands
[i
].mem
.type
= ZYDIS_MEMOP_TYPE_VSIB
;
1807 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBZ
:
1809 ZydisDecodeOperandMemory(
1810 context
, instruction
, &operands
[i
], ZYDIS_REGCLASS_ZMM
));
1811 operands
[i
].mem
.type
= ZYDIS_MEMOP_TYPE_VSIB
;
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
;
1821 case ZYDIS_SEMANTIC_OPTYPE_AGEN
:
1822 operands
[i
].actions
= 0; // TODO: Remove after generator update
1824 ZydisDecodeOperandMemory(
1825 context
, instruction
, &operands
[i
], ZYDIS_REGCLASS_INVALID
));
1826 operands
[i
].mem
.type
= ZYDIS_MEMOP_TYPE_AGEN
;
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
;
1835 case ZYDIS_SEMANTIC_OPTYPE_MIB
:
1836 operands
[i
].actions
= 0; // TODO: Remove after generator update
1838 ZydisDecodeOperandMemory(
1839 context
, instruction
, &operands
[i
], ZYDIS_REGCLASS_INVALID
));
1840 operands
[i
].mem
.type
= ZYDIS_MEMOP_TYPE_MIB
;
1845 if (operands
[i
].type
)
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))
1853 operands
[i
].mem
.disp
.value
*= context
->cd8_scale
;
1857 goto FinalizeOperand
;
1860 // Immediate operands
1861 switch (operand
->type
)
1863 case ZYDIS_SEMANTIC_OPTYPE_REL
:
1864 ZYAN_ASSERT(instruction
->raw
.imm
[imm_id
].is_relative
);
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
)
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;
1878 operands
[i
].imm
.value
.u
= instruction
->raw
.imm
[imm_id
].value
.u
;
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
;
1887 ZYAN_ASSERT(operands
[i
].type
== ZYDIS_OPERAND_TYPE_IMMEDIATE
);
1890 // Set segment-register for memory operands
1891 if (operands
[i
].type
== ZYDIS_OPERAND_TYPE_MEMORY
)
1893 if (!operand
->ignore_seg_override
&&
1894 instruction
->attributes
& ZYDIS_ATTRIB_HAS_SEGMENT_CS
)
1896 operands
[i
].mem
.segment
= ZYDIS_REGISTER_CS
;
1899 if (!operand
->ignore_seg_override
&&
1900 instruction
->attributes
& ZYDIS_ATTRIB_HAS_SEGMENT_SS
)
1902 operands
[i
].mem
.segment
= ZYDIS_REGISTER_SS
;
1905 if (!operand
->ignore_seg_override
&&
1906 instruction
->attributes
& ZYDIS_ATTRIB_HAS_SEGMENT_DS
)
1908 operands
[i
].mem
.segment
= ZYDIS_REGISTER_DS
;
1911 if (!operand
->ignore_seg_override
&&
1912 instruction
->attributes
& ZYDIS_ATTRIB_HAS_SEGMENT_ES
)
1914 operands
[i
].mem
.segment
= ZYDIS_REGISTER_ES
;
1917 if (!operand
->ignore_seg_override
&&
1918 instruction
->attributes
& ZYDIS_ATTRIB_HAS_SEGMENT_FS
)
1920 operands
[i
].mem
.segment
= ZYDIS_REGISTER_FS
;
1923 if (!operand
->ignore_seg_override
&&
1924 instruction
->attributes
& ZYDIS_ATTRIB_HAS_SEGMENT_GS
)
1926 operands
[i
].mem
.segment
= ZYDIS_REGISTER_GS
;
1930 if (operands
[i
].mem
.segment
== ZYDIS_REGISTER_NONE
)
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
))
1939 operands
[i
].mem
.segment
= ZYDIS_REGISTER_SS
;
1943 operands
[i
].mem
.segment
= ZYDIS_REGISTER_DS
;
1949 ZydisSetOperandSizeAndElementInfo(context
, instruction
, &operands
[i
], operand
);
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
)
1957 ZYAN_ASSERT(operand_count
>= 1);
1958 switch (operands
[0].actions
)
1960 case ZYDIS_OPERAND_ACTION_WRITE
:
1961 if (operands
[0].type
== ZYDIS_OPERAND_TYPE_MEMORY
)
1963 operands
[0].actions
= ZYDIS_OPERAND_ACTION_CONDWRITE
;
1967 operands
[0].actions
= ZYDIS_OPERAND_ACTION_READ_CONDWRITE
;
1970 case ZYDIS_OPERAND_ACTION_READWRITE
:
1971 operands
[0].actions
= ZYDIS_OPERAND_ACTION_READ_CONDWRITE
;
1979 return ZYAN_STATUS_SUCCESS
;
1983 /* ---------------------------------------------------------------------------------------------- */
1985 #ifndef ZYDIS_MINIMAL_MODE
1987 * Sets attributes for the given instruction.
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.
1993 static void ZydisSetAttributes(ZydisDecoderState
* state
, ZydisDecodedInstruction
* instruction
,
1994 const ZydisInstructionDefinition
* definition
)
1997 ZYAN_ASSERT(instruction
);
1998 ZYAN_ASSERT(definition
);
2000 if (definition
->cpu_state
!= ZYDIS_RW_ACTION_NONE
)
2002 static const ZydisInstructionAttributes mapping
[ZYDIS_RW_ACTION_MAX_VALUE
+ 1] =
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
2009 ZYAN_ASSERT(definition
->cpu_state
< ZYAN_ARRAY_LENGTH(mapping
));
2010 instruction
->attributes
|= mapping
[definition
->cpu_state
];
2013 if (definition
->fpu_state
!= ZYDIS_RW_ACTION_NONE
)
2015 static const ZydisInstructionAttributes mapping
[ZYDIS_RW_ACTION_MAX_VALUE
+ 1] =
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
2022 ZYAN_ASSERT(definition
->fpu_state
< ZYAN_ARRAY_LENGTH(mapping
));
2023 instruction
->attributes
|= mapping
[definition
->fpu_state
];
2026 if (definition
->xmm_state
!= ZYDIS_RW_ACTION_NONE
)
2028 static const ZydisInstructionAttributes mapping
[ZYDIS_RW_ACTION_MAX_VALUE
+ 1] =
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
2035 ZYAN_ASSERT(definition
->xmm_state
< ZYAN_ARRAY_LENGTH(mapping
));
2036 instruction
->attributes
|= mapping
[definition
->xmm_state
];
2039 switch (instruction
->encoding
)
2041 case ZYDIS_INSTRUCTION_ENCODING_LEGACY
:
2043 const ZydisInstructionDefinitionLEGACY
* def
=
2044 (const ZydisInstructionDefinitionLEGACY
*)definition
;
2046 if (def
->is_privileged
)
2048 instruction
->attributes
|= ZYDIS_ATTRIB_IS_PRIVILEGED
;
2050 if (def
->accepts_LOCK
)
2052 instruction
->attributes
|= ZYDIS_ATTRIB_ACCEPTS_LOCK
;
2053 if (state
->prefixes
.has_lock
)
2055 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_LOCK
;
2056 instruction
->raw
.prefixes
[state
->prefixes
.offset_lock
].type
=
2057 ZYDIS_PREFIX_TYPE_EFFECTIVE
;
2060 if (def
->accepts_REP
)
2062 instruction
->attributes
|= ZYDIS_ATTRIB_ACCEPTS_REP
;
2064 if (def
->accepts_REPEREPZ
)
2066 instruction
->attributes
|= ZYDIS_ATTRIB_ACCEPTS_REPE
;
2068 if (def
->accepts_REPNEREPNZ
)
2070 instruction
->attributes
|= ZYDIS_ATTRIB_ACCEPTS_REPNE
;
2072 if (def
->accepts_BOUND
)
2074 instruction
->attributes
|= ZYDIS_ATTRIB_ACCEPTS_BND
;
2076 if (def
->accepts_XACQUIRE
)
2078 instruction
->attributes
|= ZYDIS_ATTRIB_ACCEPTS_XACQUIRE
;
2080 if (def
->accepts_XRELEASE
)
2082 instruction
->attributes
|= ZYDIS_ATTRIB_ACCEPTS_XRELEASE
;
2084 if (def
->accepts_hle_without_lock
)
2086 instruction
->attributes
|= ZYDIS_ATTRIB_ACCEPTS_HLE_WITHOUT_LOCK
;
2089 switch (state
->prefixes
.group1
)
2092 if (instruction
->attributes
& ZYDIS_ATTRIB_ACCEPTS_REPNE
)
2094 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_REPNE
;
2097 if (instruction
->attributes
& ZYDIS_ATTRIB_ACCEPTS_XACQUIRE
)
2099 if ((instruction
->attributes
& ZYDIS_ATTRIB_HAS_LOCK
) ||
2100 (def
->accepts_hle_without_lock
))
2102 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_XACQUIRE
;
2106 if ((state
->decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_MPX
)) &&
2107 instruction
->attributes
& ZYDIS_ATTRIB_ACCEPTS_BND
)
2109 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_BND
;
2114 if (instruction
->attributes
& ZYDIS_ATTRIB_ACCEPTS_REP
)
2116 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_REP
;
2119 if (instruction
->attributes
& ZYDIS_ATTRIB_ACCEPTS_REPE
)
2121 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_REPE
;
2124 if (instruction
->attributes
& ZYDIS_ATTRIB_ACCEPTS_XRELEASE
)
2126 if ((instruction
->attributes
& ZYDIS_ATTRIB_HAS_LOCK
) ||
2127 (def
->accepts_hle_without_lock
))
2129 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_XRELEASE
;
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
)))
2143 instruction
->raw
.prefixes
[state
->prefixes
.offset_group1
].type
=
2144 ZYDIS_PREFIX_TYPE_EFFECTIVE
;
2147 if (def
->accepts_branch_hints
)
2149 instruction
->attributes
|= ZYDIS_ATTRIB_ACCEPTS_BRANCH_HINTS
;
2150 switch (state
->prefixes
.group2
)
2153 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN
;
2154 instruction
->raw
.prefixes
[state
->prefixes
.offset_group2
].type
=
2155 ZYDIS_PREFIX_TYPE_EFFECTIVE
;
2158 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_BRANCH_TAKEN
;
2159 instruction
->raw
.prefixes
[state
->prefixes
.offset_group2
].type
=
2160 ZYDIS_PREFIX_TYPE_EFFECTIVE
;
2167 if (def
->accepts_NOTRACK
)
2169 instruction
->attributes
|= ZYDIS_ATTRIB_ACCEPTS_NOTRACK
;
2170 if ((state
->decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_CET
)) &&
2171 (state
->prefixes
.offset_notrack
>= 0))
2173 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_NOTRACK
;
2174 instruction
->raw
.prefixes
[state
->prefixes
.offset_notrack
].type
=
2175 ZYDIS_PREFIX_TYPE_EFFECTIVE
;
2179 if (def
->accepts_segment
&& !def
->accepts_branch_hints
)
2181 instruction
->attributes
|= ZYDIS_ATTRIB_ACCEPTS_SEGMENT
;
2182 if (state
->prefixes
.effective_segment
&&
2183 !(instruction
->attributes
& ZYDIS_ATTRIB_HAS_NOTRACK
))
2185 switch (state
->prefixes
.effective_segment
)
2188 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_SEGMENT_CS
;
2191 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_SEGMENT_SS
;
2194 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_SEGMENT_DS
;
2197 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_SEGMENT_ES
;
2200 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_SEGMENT_FS
;
2203 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_SEGMENT_GS
;
2209 if (instruction
->attributes
& ZYDIS_ATTRIB_HAS_SEGMENT
)
2211 instruction
->raw
.prefixes
[state
->prefixes
.offset_segment
].type
=
2212 ZYDIS_PREFIX_TYPE_EFFECTIVE
;
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
)
2225 instruction
->attributes
|= ZYDIS_ATTRIB_ACCEPTS_SEGMENT
;
2226 if (state
->prefixes
.effective_segment
)
2228 switch (state
->prefixes
.effective_segment
)
2231 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_SEGMENT_CS
;
2234 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_SEGMENT_SS
;
2237 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_SEGMENT_DS
;
2240 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_SEGMENT_ES
;
2243 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_SEGMENT_FS
;
2246 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_SEGMENT_GS
;
2252 if (instruction
->attributes
& ZYDIS_ATTRIB_HAS_SEGMENT
)
2254 instruction
->raw
.prefixes
[state
->prefixes
.offset_segment
].type
=
2255 ZYDIS_PREFIX_TYPE_EFFECTIVE
;
2265 #ifndef ZYDIS_MINIMAL_MODE
2267 * Sets AVX-specific information for the given instruction.
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.
2273 * Information set for `XOP`:
2276 * Information set for `VEX`:
2278 * - Static broadcast-factor
2280 * Information set for `EVEX`:
2282 * - Broadcast-factor (static and dynamic)
2283 * - Rounding-mode and SAE
2285 * - Compressed 8-bit displacement scale-factor
2287 * Information set for `MVEX`:
2289 * - Broadcast-factor (static and dynamic)
2290 * - Rounding-mode and SAE
2291 * - Swizzle- and conversion-mode
2294 * - Compressed 8-bit displacement scale-factor
2296 static void ZydisSetAVXInformation(ZydisDecoderContext
* context
,
2297 ZydisDecodedInstruction
* instruction
, const ZydisInstructionDefinition
* definition
)
2299 ZYAN_ASSERT(context
);
2300 ZYAN_ASSERT(instruction
);
2301 ZYAN_ASSERT(definition
);
2303 switch (instruction
->encoding
)
2305 case ZYDIS_INSTRUCTION_ENCODING_XOP
:
2308 static const ZyanU16 lookup
[2] =
2313 ZYAN_ASSERT(context
->vector_unified
.LL
< ZYAN_ARRAY_LENGTH(lookup
));
2314 instruction
->avx
.vector_length
= lookup
[context
->vector_unified
.LL
];
2317 case ZYDIS_INSTRUCTION_ENCODING_VEX
:
2320 static const ZyanU16 lookup
[2] =
2325 ZYAN_ASSERT(context
->vector_unified
.LL
< ZYAN_ARRAY_LENGTH(lookup
));
2326 instruction
->avx
.vector_length
= lookup
[context
->vector_unified
.LL
];
2328 // Static broadcast-factor
2329 const ZydisInstructionDefinitionVEX
* def
=
2330 (const ZydisInstructionDefinitionVEX
*)definition
;
2333 instruction
->avx
.broadcast
.is_static
= ZYAN_TRUE
;
2334 static ZydisBroadcastMode broadcasts
[ZYDIS_VEX_STATIC_BROADCAST_MAX_VALUE
+ 1] =
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
2344 instruction
->avx
.broadcast
.mode
= broadcasts
[def
->broadcast
];
2348 case ZYDIS_INSTRUCTION_ENCODING_EVEX
:
2350 #ifndef ZYDIS_DISABLE_AVX512
2351 const ZydisInstructionDefinitionEVEX
* def
=
2352 (const ZydisInstructionDefinitionEVEX
*)definition
;
2355 ZyanU8 vector_length
= context
->vector_unified
.LL
;
2356 if (def
->vector_length
)
2358 vector_length
= def
->vector_length
- 1;
2360 static const ZyanU16 lookup
[3] =
2366 ZYAN_ASSERT(vector_length
< ZYAN_ARRAY_LENGTH(lookup
));
2367 instruction
->avx
.vector_length
= lookup
[vector_length
];
2369 context
->evex
.tuple_type
= def
->tuple_type
;
2370 if (def
->tuple_type
)
2372 ZYAN_ASSERT(instruction
->raw
.modrm
.mod
!= 3);
2373 ZYAN_ASSERT(def
->element_size
);
2376 static const ZyanU8 element_sizes
[ZYDIS_IELEMENT_SIZE_MAX_VALUE
+ 1] =
2378 0, 8, 16, 32, 64, 128
2380 ZYAN_ASSERT(def
->element_size
< ZYAN_ARRAY_LENGTH(element_sizes
));
2381 context
->evex
.element_size
= element_sizes
[def
->element_size
];
2383 // Compressed disp8 scale and broadcast-factor
2384 switch (def
->tuple_type
)
2386 case ZYDIS_TUPLETYPE_FV
:
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
);
2395 static const ZyanU8 scales
[2][3][3] =
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 } }
2400 static const ZydisBroadcastMode broadcasts
[2][3][3] =
2406 ZYDIS_BROADCAST_MODE_INVALID
,
2407 ZYDIS_BROADCAST_MODE_INVALID
,
2408 ZYDIS_BROADCAST_MODE_INVALID
2412 ZYDIS_BROADCAST_MODE_INVALID
,
2413 ZYDIS_BROADCAST_MODE_INVALID
,
2414 ZYDIS_BROADCAST_MODE_INVALID
2418 ZYDIS_BROADCAST_MODE_INVALID
,
2419 ZYDIS_BROADCAST_MODE_INVALID
,
2420 ZYDIS_BROADCAST_MODE_INVALID
2427 ZYDIS_BROADCAST_MODE_1_TO_8
,
2428 ZYDIS_BROADCAST_MODE_1_TO_16
,
2429 ZYDIS_BROADCAST_MODE_1_TO_32
2433 ZYDIS_BROADCAST_MODE_1_TO_4
,
2434 ZYDIS_BROADCAST_MODE_1_TO_8
,
2435 ZYDIS_BROADCAST_MODE_1_TO_16
2439 ZYDIS_BROADCAST_MODE_1_TO_2
,
2440 ZYDIS_BROADCAST_MODE_1_TO_4
,
2441 ZYDIS_BROADCAST_MODE_1_TO_8
2446 const ZyanU8 size_index
= context
->evex
.element_size
>> 5;
2447 ZYAN_ASSERT(size_index
< 3);
2449 context
->cd8_scale
= scales
[evex_b
][size_index
][vector_length
];
2450 instruction
->avx
.broadcast
.mode
= broadcasts
[evex_b
][size_index
][vector_length
];
2453 case ZYDIS_TUPLETYPE_HV
:
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
);
2462 static const ZyanU8 scales
[2][2][3] =
2464 /*B0*/ { /*16*/ { 8, 16, 32 }, /*32*/ { 8, 16, 32 } },
2465 /*B1*/ { /*16*/ { 2, 2, 2 }, /*32*/ { 4, 4, 4 } }
2467 static const ZydisBroadcastMode broadcasts
[2][2][3] =
2473 ZYDIS_BROADCAST_MODE_INVALID
,
2474 ZYDIS_BROADCAST_MODE_INVALID
,
2475 ZYDIS_BROADCAST_MODE_INVALID
2479 ZYDIS_BROADCAST_MODE_INVALID
,
2480 ZYDIS_BROADCAST_MODE_INVALID
,
2481 ZYDIS_BROADCAST_MODE_INVALID
2488 ZYDIS_BROADCAST_MODE_1_TO_4
,
2489 ZYDIS_BROADCAST_MODE_1_TO_8
,
2490 ZYDIS_BROADCAST_MODE_1_TO_16
2494 ZYDIS_BROADCAST_MODE_1_TO_2
,
2495 ZYDIS_BROADCAST_MODE_1_TO_4
,
2496 ZYDIS_BROADCAST_MODE_1_TO_8
2501 const ZyanU8 size_index
= context
->evex
.element_size
>> 5;
2502 ZYAN_ASSERT(size_index
< 3);
2504 context
->cd8_scale
= scales
[evex_b
][size_index
][vector_length
];
2505 instruction
->avx
.broadcast
.mode
= broadcasts
[evex_b
][size_index
][vector_length
];
2508 case ZYDIS_TUPLETYPE_FVM
:
2510 static const ZyanU8 scales
[3] =
2514 context
->cd8_scale
= scales
[vector_length
];
2517 case ZYDIS_TUPLETYPE_GSCAT
:
2518 switch (context
->vector_unified
.W
)
2521 ZYAN_ASSERT(context
->evex
.element_size
== 32);
2524 ZYAN_ASSERT(context
->evex
.element_size
== 64);
2530 case ZYDIS_TUPLETYPE_T1S
:
2532 static const ZyanU8 scales
[6] =
2541 ZYAN_ASSERT(def
->element_size
< ZYAN_ARRAY_LENGTH(scales
));
2542 context
->cd8_scale
= scales
[def
->element_size
];
2545 case ZYDIS_TUPLETYPE_T1F
:
2547 static const ZyanU8 scales
[3] =
2554 const ZyanU8 size_index
= context
->evex
.element_size
>> 5;
2555 ZYAN_ASSERT(size_index
< 3);
2557 context
->cd8_scale
= scales
[size_index
];
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;
2565 case ZYDIS_TUPLETYPE_T2
:
2566 switch (context
->vector_unified
.W
)
2569 ZYAN_ASSERT(context
->evex
.element_size
== 32);
2570 context
->cd8_scale
= 8;
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;
2582 case ZYDIS_TUPLETYPE_T4
:
2583 switch (context
->vector_unified
.W
)
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;
2592 ZYAN_ASSERT(context
->evex
.element_size
== 64);
2593 ZYAN_ASSERT(instruction
->avx
.vector_length
== 512);
2594 context
->cd8_scale
= 32;
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;
2606 case ZYDIS_TUPLETYPE_HVM
:
2608 static const ZyanU8 scales
[3] =
2612 context
->cd8_scale
= scales
[vector_length
];
2615 case ZYDIS_TUPLETYPE_QVM
:
2617 static const ZyanU8 scales
[3] =
2621 context
->cd8_scale
= scales
[vector_length
];
2624 case ZYDIS_TUPLETYPE_OVM
:
2626 static const ZyanU8 scales
[3] =
2630 context
->cd8_scale
= scales
[vector_length
];
2633 case ZYDIS_TUPLETYPE_M128
:
2634 context
->cd8_scale
= 16;
2636 case ZYDIS_TUPLETYPE_DUP
:
2638 static const ZyanU8 scales
[3] =
2642 context
->cd8_scale
= scales
[vector_length
];
2645 case ZYDIS_TUPLETYPE_QUARTER
:
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
);
2653 static const ZyanU8 scales
[2][3] =
2655 /*B0*/ { 4, 8, 16 },
2658 static const ZydisBroadcastMode broadcasts
[2][3] =
2662 ZYDIS_BROADCAST_MODE_INVALID
,
2663 ZYDIS_BROADCAST_MODE_INVALID
,
2664 ZYDIS_BROADCAST_MODE_INVALID
2668 ZYDIS_BROADCAST_MODE_1_TO_2
,
2669 ZYDIS_BROADCAST_MODE_1_TO_4
,
2670 ZYDIS_BROADCAST_MODE_1_TO_8
2673 context
->cd8_scale
= scales
[evex_b
][vector_length
];
2674 instruction
->avx
.broadcast
.mode
= broadcasts
[evex_b
][vector_length
];
2682 ZYAN_ASSERT(instruction
->raw
.modrm
.mod
== 3);
2685 // Static broadcast-factor
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] =
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
2706 ZYAN_ASSERT(def
->broadcast
< ZYAN_ARRAY_LENGTH(broadcasts
));
2707 instruction
->avx
.broadcast
.mode
= broadcasts
[def
->broadcast
];
2710 // Rounding mode and SAE
2711 if (instruction
->raw
.evex
.b
)
2713 switch (def
->functionality
)
2715 case ZYDIS_EVEX_FUNC_INVALID
:
2716 case ZYDIS_EVEX_FUNC_BC
:
2717 // Noting to do here
2719 case ZYDIS_EVEX_FUNC_RC
:
2720 instruction
->avx
.rounding
.mode
= ZYDIS_ROUNDING_MODE_RN
+ context
->vector_unified
.LL
;
2722 case ZYDIS_EVEX_FUNC_SAE
:
2723 instruction
->avx
.has_sae
= ZYAN_TRUE
;
2731 instruction
->avx
.mask
.reg
= ZYDIS_REGISTER_K0
+ instruction
->raw
.evex
.aaa
;
2732 switch (def
->mask_override
)
2734 case ZYDIS_MASK_OVERRIDE_DEFAULT
:
2735 instruction
->avx
.mask
.mode
= ZYDIS_MASK_MODE_MERGING
+ instruction
->raw
.evex
.z
;
2737 case ZYDIS_MASK_OVERRIDE_ZEROING
:
2738 instruction
->avx
.mask
.mode
= ZYDIS_MASK_MODE_ZEROING
;
2740 case ZYDIS_MASK_OVERRIDE_CONTROL
:
2741 instruction
->avx
.mask
.mode
= ZYDIS_MASK_MODE_CONTROL
+ instruction
->raw
.evex
.z
;
2746 if (!instruction
->raw
.evex
.aaa
)
2748 instruction
->avx
.mask
.mode
= ZYDIS_MASK_MODE_DISABLED
;
2755 case ZYDIS_INSTRUCTION_ENCODING_MVEX
:
2757 #ifndef ZYDIS_DISABLE_KNC
2759 instruction
->avx
.vector_length
= 512;
2761 const ZydisInstructionDefinitionMVEX
* def
=
2762 (const ZydisInstructionDefinitionMVEX
*)definition
;
2764 // Static broadcast-factor
2765 ZyanU8 index
= def
->has_element_granularity
;
2766 ZYAN_ASSERT(!index
|| !def
->broadcast
);
2767 if (!index
&& def
->broadcast
)
2769 instruction
->avx
.broadcast
.is_static
= ZYAN_TRUE
;
2770 switch (def
->broadcast
)
2772 case ZYDIS_MVEX_STATIC_BROADCAST_1_TO_8
:
2773 instruction
->avx
.broadcast
.mode
= ZYDIS_BROADCAST_MODE_1_TO_8
;
2776 case ZYDIS_MVEX_STATIC_BROADCAST_1_TO_16
:
2777 instruction
->avx
.broadcast
.mode
= ZYDIS_BROADCAST_MODE_1_TO_16
;
2780 case ZYDIS_MVEX_STATIC_BROADCAST_4_TO_8
:
2781 instruction
->avx
.broadcast
.mode
= ZYDIS_BROADCAST_MODE_4_TO_8
;
2784 case ZYDIS_MVEX_STATIC_BROADCAST_4_TO_16
:
2785 instruction
->avx
.broadcast
.mode
= ZYDIS_BROADCAST_MODE_4_TO_16
;
2793 // Compressed disp8 scale and broadcast-factor
2794 switch (def
->functionality
)
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
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;
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
:
2815 static const ZyanU8 lookup
[3][8] =
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 }
2821 ZYAN_ASSERT(instruction
->raw
.mvex
.SSS
< ZYAN_ARRAY_LENGTH(lookup
[index
]));
2822 context
->cd8_scale
= lookup
[index
][instruction
->raw
.mvex
.SSS
];
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
:
2830 static const ZyanU8 lookup
[3][8] =
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 }
2836 ZYAN_ASSERT(instruction
->raw
.mvex
.SSS
< ZYAN_ARRAY_LENGTH(lookup
[index
]));
2837 context
->cd8_scale
= lookup
[index
][instruction
->raw
.mvex
.SSS
];
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
:
2845 static const ZyanU8 lookup
[3][3] =
2851 ZYAN_ASSERT(instruction
->raw
.mvex
.SSS
< ZYAN_ARRAY_LENGTH(lookup
[index
]));
2852 context
->cd8_scale
= lookup
[index
][instruction
->raw
.mvex
.SSS
];
2855 case ZYDIS_MVEX_FUNC_DF_32
:
2856 case ZYDIS_MVEX_FUNC_DI_32
:
2858 static const ZyanU8 lookup
[2][8] =
2860 { 64, 0, 0, 32, 16, 16, 32, 32 },
2861 { 4, 0, 0, 2, 1, 1, 2, 2 }
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
];
2868 case ZYDIS_MVEX_FUNC_DF_64
:
2869 case ZYDIS_MVEX_FUNC_DI_64
:
2871 static const ZyanU8 lookup
[2][1] =
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
];
2885 // Rounding mode, sae, swizzle, convert
2886 context
->mvex
.functionality
= def
->functionality
;
2887 switch (def
->functionality
)
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
2897 case ZYDIS_MVEX_FUNC_RC
:
2898 instruction
->avx
.rounding
.mode
= ZYDIS_ROUNDING_MODE_RN
+ (instruction
->raw
.mvex
.SSS
& 3);
2900 case ZYDIS_MVEX_FUNC_SAE
:
2901 if (instruction
->raw
.mvex
.SSS
>= 4)
2903 instruction
->avx
.has_sae
= ZYAN_TRUE
;
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
;
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
)
2918 instruction
->avx
.broadcast
.mode
= ZYDIS_BROADCAST_MODE_1_TO_16
;
2921 instruction
->avx
.broadcast
.mode
= ZYDIS_BROADCAST_MODE_4_TO_16
;
2924 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_FLOAT16
;
2927 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_UINT8
;
2930 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_SINT8
;
2933 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_UINT16
;
2936 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_SINT16
;
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
)
2950 instruction
->avx
.broadcast
.mode
= ZYDIS_BROADCAST_MODE_1_TO_16
;
2953 instruction
->avx
.broadcast
.mode
= ZYDIS_BROADCAST_MODE_4_TO_16
;
2956 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_UINT8
;
2959 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_SINT8
;
2962 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_UINT16
;
2965 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_SINT16
;
2971 case ZYDIS_MVEX_FUNC_SF_64
:
2972 case ZYDIS_MVEX_FUNC_SI_64
:
2973 switch (instruction
->raw
.mvex
.SSS
)
2978 instruction
->avx
.broadcast
.mode
= ZYDIS_BROADCAST_MODE_1_TO_8
;
2981 instruction
->avx
.broadcast
.mode
= ZYDIS_BROADCAST_MODE_4_TO_8
;
2987 case ZYDIS_MVEX_FUNC_UF_32
:
2988 case ZYDIS_MVEX_FUNC_DF_32
:
2989 switch (instruction
->raw
.mvex
.SSS
)
2994 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_FLOAT16
;
2997 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_UINT8
;
3000 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_SINT8
;
3003 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_UINT16
;
3006 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_SINT16
;
3012 case ZYDIS_MVEX_FUNC_UF_64
:
3013 case ZYDIS_MVEX_FUNC_DF_64
:
3015 case ZYDIS_MVEX_FUNC_UI_32
:
3016 case ZYDIS_MVEX_FUNC_DI_32
:
3017 switch (instruction
->raw
.mvex
.SSS
)
3022 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_UINT8
;
3025 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_SINT8
;
3028 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_UINT16
;
3031 instruction
->avx
.conversion
.mode
= ZYDIS_CONVERSION_MODE_SINT16
;
3037 case ZYDIS_MVEX_FUNC_UI_64
:
3038 case ZYDIS_MVEX_FUNC_DI_64
:
3045 if ((instruction
->raw
.modrm
.mod
!= 3) && instruction
->raw
.mvex
.E
)
3047 instruction
->avx
.has_eviction_hint
= ZYAN_TRUE
;
3051 instruction
->avx
.mask
.mode
= ZYDIS_MASK_MODE_MERGING
;
3052 instruction
->avx
.mask
.reg
= ZYDIS_REGISTER_K0
+ instruction
->raw
.mvex
.kkk
;
3059 // Nothing to do here
3065 /* ---------------------------------------------------------------------------------------------- */
3066 /* Physical instruction decoding */
3067 /* ---------------------------------------------------------------------------------------------- */
3070 * Collects optional instruction prefixes.
3072 * @param state A pointer to the `ZydisDecoderState` struct.
3073 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
3075 * @return A zyan status code.
3077 * This function sets the corresponding flag for each prefix and automatically decodes the last
3078 * `REX`-prefix (if exists).
3080 static ZyanStatus
ZydisCollectOptionalPrefixes(ZydisDecoderState
* state
,
3081 ZydisDecodedInstruction
* instruction
)
3084 ZYAN_ASSERT(instruction
);
3085 ZYAN_ASSERT(instruction
->raw
.prefix_count
== 0);
3089 ZyanBool done
= ZYAN_FALSE
;
3093 ZYAN_CHECK(ZydisInputPeek(state
, instruction
, &prefix_byte
));
3094 switch (prefix_byte
)
3097 state
->prefixes
.has_lock
= ZYAN_TRUE
;
3098 state
->prefixes
.offset_lock
= offset
;
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
;
3115 if (state
->decoder
->machine_mode
== ZYDIS_MACHINE_MODE_LONG_64
)
3117 if ((prefix_byte
== 0x3E) &&
3118 (state
->prefixes
.effective_segment
!= 0x64) &&
3119 (state
->prefixes
.effective_segment
!= 0x65))
3121 state
->prefixes
.offset_notrack
= offset
;
3123 state
->prefixes
.group2
= prefix_byte
;
3124 state
->prefixes
.offset_group2
= offset
;
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;
3138 // context->prefixes.has_osz_override = ZYAN_TRUE;
3139 state
->prefixes
.offset_osz_override
= offset
;
3140 if (!state
->prefixes
.mandatory_candidate
)
3142 state
->prefixes
.mandatory_candidate
= 0x66;
3143 state
->prefixes
.offset_mandatory
= offset
;
3145 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_OPERANDSIZE
;
3148 // context->prefixes.has_asz_override = ZYAN_TRUE;
3149 state
->prefixes
.offset_asz_override
= offset
;
3150 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_ADDRESSSIZE
;
3153 if ((state
->decoder
->machine_mode
== ZYDIS_MACHINE_MODE_LONG_64
) &&
3154 (prefix_byte
& 0xF0) == 0x40)
3157 instruction
->raw
.rex
.offset
= offset
;
3166 // Invalidate `REX`, if it's not the last legacy prefix
3167 if (rex
&& (rex
!= prefix_byte
))
3170 instruction
->raw
.rex
.offset
= 0;
3172 instruction
->raw
.prefixes
[instruction
->raw
.prefix_count
++].value
= prefix_byte
;
3173 ZydisInputSkip(state
, instruction
);
3178 if (instruction
->attributes
& ZYDIS_ATTRIB_HAS_OPERANDSIZE
)
3180 instruction
->raw
.prefixes
[state
->prefixes
.offset_osz_override
].type
=
3181 ZYDIS_PREFIX_TYPE_EFFECTIVE
;
3183 if (instruction
->attributes
& ZYDIS_ATTRIB_HAS_ADDRESSSIZE
)
3185 instruction
->raw
.prefixes
[state
->prefixes
.offset_asz_override
].type
=
3186 ZYDIS_PREFIX_TYPE_EFFECTIVE
;
3190 instruction
->raw
.prefixes
[instruction
->raw
.rex
.offset
].type
= ZYDIS_PREFIX_TYPE_EFFECTIVE
;
3191 ZydisDecodeREX(state
->context
, instruction
, rex
);
3193 if ((state
->decoder
->machine_mode
!= ZYDIS_MACHINE_MODE_LONG_64
) &&
3194 (state
->prefixes
.group2
== 0x3E))
3196 state
->prefixes
.offset_notrack
= state
->prefixes
.offset_group2
;
3199 return ZYAN_STATUS_SUCCESS
;
3203 * Decodes optional instruction parts like the ModRM byte, the SIB byte and
3204 * additional displacements and/or immediate values.
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.
3210 * @return A zyan status code.
3212 static ZyanStatus
ZydisDecodeOptionalInstructionParts(ZydisDecoderState
* state
,
3213 ZydisDecodedInstruction
* instruction
, const ZydisInstructionEncodingInfo
* info
)
3216 ZYAN_ASSERT(instruction
);
3219 ZydisDecoderContext
* context
= state
->context
;
3221 if (info
->flags
& ZYDIS_INSTR_ENC_FLAG_HAS_MODRM
)
3223 if (!instruction
->raw
.modrm
.offset
)
3225 instruction
->raw
.modrm
.offset
= instruction
->length
;
3227 ZYAN_CHECK(ZydisInputNext(state
, instruction
, &modrm_byte
));
3228 ZydisDecodeModRM(instruction
, modrm_byte
);
3231 if (!(info
->flags
& ZYDIS_INSTR_ENC_FLAG_FORCE_REG_FORM
))
3234 ZyanU8 displacement_size
= 0;
3235 switch (instruction
->address_width
)
3238 switch (instruction
->raw
.modrm
.mod
)
3241 if (instruction
->raw
.modrm
.rm
== 6)
3243 displacement_size
= 16;
3247 displacement_size
= 8;
3250 displacement_size
= 16;
3261 (instruction
->raw
.modrm
.mod
!= 3) && (instruction
->raw
.modrm
.rm
== 4);
3262 switch (instruction
->raw
.modrm
.mod
)
3265 if (instruction
->raw
.modrm
.rm
== 5)
3267 if (instruction
->machine_mode
== ZYDIS_MACHINE_MODE_LONG_64
)
3269 instruction
->attributes
|= ZYDIS_ATTRIB_IS_RELATIVE
;
3271 displacement_size
= 32;
3275 displacement_size
= 8;
3278 displacement_size
= 32;
3291 instruction
->raw
.sib
.offset
= instruction
->length
;
3293 ZYAN_CHECK(ZydisInputNext(state
, instruction
, &sib_byte
));
3294 ZydisDecodeSIB(instruction
, sib_byte
);
3295 if (instruction
->raw
.sib
.base
== 5)
3297 displacement_size
= (instruction
->raw
.modrm
.mod
== 1) ? 8 : 32;
3300 if (displacement_size
)
3302 ZYAN_CHECK(ZydisReadDisplacement(state
, instruction
, displacement_size
));
3306 context
->reg_info
.is_mod_reg
= (instruction
->raw
.modrm
.mod
== 3) ||
3307 (info
->flags
& ZYDIS_INSTR_ENC_FLAG_FORCE_REG_FORM
);
3310 if (info
->flags
& ZYDIS_INSTR_ENC_FLAG_HAS_DISP
)
3312 ZYAN_CHECK(ZydisReadDisplacement(
3313 state
, instruction
, info
->disp
.size
[context
->easz_index
]));
3316 if (info
->flags
& ZYDIS_INSTR_ENC_FLAG_HAS_IMM0
)
3318 if (info
->imm
[0].is_relative
)
3320 instruction
->attributes
|= ZYDIS_ATTRIB_IS_RELATIVE
;
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
));
3327 if (info
->flags
& ZYDIS_INSTR_ENC_FLAG_HAS_IMM1
)
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
));
3335 return ZYAN_STATUS_SUCCESS
;
3338 /* ---------------------------------------------------------------------------------------------- */
3341 * Sets the effective operand size for the given instruction.
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.
3347 static void ZydisSetEffectiveOperandWidth(ZydisDecoderContext
* context
,
3348 ZydisDecodedInstruction
* instruction
, const ZydisInstructionDefinition
* definition
)
3350 ZYAN_ASSERT(context
);
3351 ZYAN_ASSERT(instruction
);
3352 ZYAN_ASSERT(definition
);
3354 static const ZyanU8 operand_size_map
[8][8] =
3356 // Default for most instructions
3367 // Operand size is forced to 8-bit (this is done later to preserve the `eosz_index`)
3378 // Operand size override 0x66 is ignored
3389 // REX.W promotes to 32-bit instead of 64-bit
3400 // Operand size defaults to 64-bit in 64-bit mode
3411 // Operand size is forced to 64-bit in 64-bit mode
3422 // Operand size is forced to 32-bit, if no REX.W is present.
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`.
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
))
3453 else if (instruction
->machine_mode
== ZYDIS_MACHINE_MODE_LONG_64
)
3456 index
+= (context
->vector_unified
.W
& 0x01) << 1;
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
]));
3462 instruction
->operand_width
= operand_size_map
[definition
->operand_size_map
][index
];
3463 context
->eosz_index
= instruction
->operand_width
>> 5;
3465 // TODO: Cleanup code and remove hardcoded condition
3466 if (definition
->operand_size_map
== 1)
3468 instruction
->operand_width
= 8;
3473 * Sets the effective address width for the given instruction.
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.
3479 static void ZydisSetEffectiveAddressWidth(ZydisDecoderContext
* context
,
3480 ZydisDecodedInstruction
* instruction
, const ZydisInstructionDefinition
* definition
)
3482 ZYAN_ASSERT(context
);
3483 ZYAN_ASSERT(instruction
);
3485 static const ZyanU8 address_size_map
[3][8] =
3487 // Default for most instructions
3496 // The address-size override is ignored
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`.
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
))
3523 else if (instruction
->machine_mode
== ZYDIS_MACHINE_MODE_LONG_64
)
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
]));
3531 instruction
->address_width
= address_size_map
[definition
->address_size_map
][index
];
3532 context
->easz_index
= instruction
->address_width
>> 5;
3535 /* ---------------------------------------------------------------------------------------------- */
3537 static ZyanStatus
ZydisNodeHandlerXOP(const ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
3539 ZYAN_ASSERT(instruction
);
3542 switch (instruction
->encoding
)
3544 case ZYDIS_INSTRUCTION_ENCODING_LEGACY
:
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;
3554 return ZYAN_STATUS_SUCCESS
;
3557 static ZyanStatus
ZydisNodeHandlerVEX(const ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
3559 ZYAN_ASSERT(instruction
);
3562 switch (instruction
->encoding
)
3564 case ZYDIS_INSTRUCTION_ENCODING_LEGACY
:
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;
3574 return ZYAN_STATUS_SUCCESS
;
3577 static ZyanStatus
ZydisNodeHandlerEMVEX(const ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
3579 ZYAN_ASSERT(instruction
);
3582 switch (instruction
->encoding
)
3584 case ZYDIS_INSTRUCTION_ENCODING_LEGACY
:
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;
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;
3598 return ZYAN_STATUS_SUCCESS
;
3601 static ZyanStatus
ZydisNodeHandlerOpcode(ZydisDecoderState
* state
,
3602 ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
3605 ZYAN_ASSERT(instruction
);
3608 // Handle possible encoding-prefix and opcode-map changes
3609 switch (instruction
->encoding
)
3611 case ZYDIS_INSTRUCTION_ENCODING_LEGACY
:
3612 ZYAN_CHECK(ZydisInputNext(state
, instruction
, &instruction
->opcode
));
3613 switch (instruction
->opcode_map
)
3615 case ZYDIS_OPCODE_MAP_DEFAULT
:
3616 switch (instruction
->opcode
)
3619 instruction
->opcode_map
= ZYDIS_OPCODE_MAP_0F
;
3626 ZYAN_CHECK(ZydisInputPeek(state
, instruction
, &next_input
));
3627 if (((next_input
& 0xF0) >= 0xC0) ||
3628 (instruction
->machine_mode
== ZYDIS_MACHINE_MODE_LONG_64
))
3630 if (instruction
->attributes
& ZYDIS_ATTRIB_HAS_REX
)
3632 return ZYDIS_STATUS_ILLEGAL_REX
;
3634 if (state
->prefixes
.has_lock
)
3636 return ZYDIS_STATUS_ILLEGAL_LOCK
;
3638 if (state
->prefixes
.mandatory_candidate
)
3640 return ZYDIS_STATUS_ILLEGAL_LEGACY_PFX
;
3642 ZyanU8 prefix_bytes
[4] = { 0, 0, 0, 0 };
3643 prefix_bytes
[0] = instruction
->opcode
;
3644 switch (instruction
->opcode
)
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));
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]));
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));
3666 return ZYDIS_STATUS_DECODING_ERROR
;
3671 switch (instruction
->opcode
)
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
;
3682 #if defined(ZYDIS_DISABLE_AVX512) && defined(ZYDIS_DISABLE_KNC)
3683 return ZYDIS_STATUS_DECODING_ERROR
;
3685 switch ((prefix_bytes
[2] >> 2) & 0x01)
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
)
3696 return ZYDIS_STATUS_DECODING_ERROR
;
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
;
3705 return ZYDIS_STATUS_DECODING_ERROR
;
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
;
3717 return ZYDIS_STATUS_DECODING_ERROR
;
3733 ZYAN_CHECK(ZydisInputPeek(state
, instruction
, &next_input
));
3734 if ((next_input
& 0x1F) >= 8)
3736 if (instruction
->attributes
& ZYDIS_ATTRIB_HAS_REX
)
3738 return ZYDIS_STATUS_ILLEGAL_REX
;
3740 if (state
->prefixes
.has_lock
)
3742 return ZYDIS_STATUS_ILLEGAL_LOCK
;
3744 if (state
->prefixes
.mandatory_candidate
)
3746 return ZYDIS_STATUS_ILLEGAL_LEGACY_PFX
;
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;
3764 case ZYDIS_OPCODE_MAP_0F
:
3765 switch (instruction
->opcode
)
3768 if (state
->prefixes
.has_lock
)
3770 return ZYDIS_STATUS_ILLEGAL_LOCK
;
3772 instruction
->encoding
= ZYDIS_INSTRUCTION_ENCODING_3DNOW
;
3773 instruction
->opcode_map
= ZYDIS_OPCODE_MAP_0F0F
;
3776 instruction
->opcode_map
= ZYDIS_OPCODE_MAP_0F38
;
3779 instruction
->opcode_map
= ZYDIS_OPCODE_MAP_0F3A
;
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
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.
3800 return ZYAN_STATUS_SUCCESS
;
3802 ZYAN_CHECK(ZydisInputNext(state
, instruction
, &instruction
->opcode
));
3806 *index
= instruction
->opcode
;
3807 return ZYAN_STATUS_SUCCESS
;
3810 static ZyanStatus
ZydisNodeHandlerMode(const ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
3812 ZYAN_ASSERT(instruction
);
3815 switch (instruction
->machine_mode
)
3817 case ZYDIS_MACHINE_MODE_LONG_COMPAT_16
:
3818 case ZYDIS_MACHINE_MODE_LEGACY_16
:
3819 case ZYDIS_MACHINE_MODE_REAL_16
:
3822 case ZYDIS_MACHINE_MODE_LONG_COMPAT_32
:
3823 case ZYDIS_MACHINE_MODE_LEGACY_32
:
3826 case ZYDIS_MACHINE_MODE_LONG_64
:
3832 return ZYAN_STATUS_SUCCESS
;
3835 static ZyanStatus
ZydisNodeHandlerModeCompact(const ZydisDecodedInstruction
* instruction
,
3838 ZYAN_ASSERT(instruction
);
3841 *index
= (instruction
->machine_mode
== ZYDIS_MACHINE_MODE_LONG_64
) ? 0 : 1;
3842 return ZYAN_STATUS_SUCCESS
;
3845 static ZyanStatus
ZydisNodeHandlerModrmMod(ZydisDecoderState
* state
,
3846 ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
3849 ZYAN_ASSERT(instruction
);
3852 if (!instruction
->raw
.modrm
.offset
)
3854 instruction
->raw
.modrm
.offset
= instruction
->length
;
3856 ZYAN_CHECK(ZydisInputNext(state
, instruction
, &modrm_byte
));
3857 ZydisDecodeModRM(instruction
, modrm_byte
);
3859 *index
= instruction
->raw
.modrm
.mod
;
3860 return ZYAN_STATUS_SUCCESS
;
3863 static ZyanStatus
ZydisNodeHandlerModrmModCompact(ZydisDecoderState
* state
,
3864 ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
3866 ZYAN_CHECK(ZydisNodeHandlerModrmMod(state
, instruction
, index
));
3867 *index
= (*index
== 0x3) ? 0 : 1;
3868 return ZYAN_STATUS_SUCCESS
;
3871 static ZyanStatus
ZydisNodeHandlerModrmReg(ZydisDecoderState
* state
,
3872 ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
3875 ZYAN_ASSERT(instruction
);
3878 if (!instruction
->raw
.modrm
.offset
)
3880 instruction
->raw
.modrm
.offset
= instruction
->length
;
3882 ZYAN_CHECK(ZydisInputNext(state
, instruction
, &modrm_byte
));
3883 ZydisDecodeModRM(instruction
, modrm_byte
);
3885 *index
= instruction
->raw
.modrm
.reg
;
3886 return ZYAN_STATUS_SUCCESS
;
3889 static ZyanStatus
ZydisNodeHandlerModrmRm(ZydisDecoderState
* state
,
3890 ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
3893 ZYAN_ASSERT(instruction
);
3896 if (!instruction
->raw
.modrm
.offset
)
3898 instruction
->raw
.modrm
.offset
= instruction
->length
;
3900 ZYAN_CHECK(ZydisInputNext(state
, instruction
, &modrm_byte
));
3901 ZydisDecodeModRM(instruction
, modrm_byte
);
3903 *index
= instruction
->raw
.modrm
.rm
;
3904 return ZYAN_STATUS_SUCCESS
;
3907 static ZyanStatus
ZydisNodeHandlerMandatoryPrefix(const ZydisDecoderState
* state
,
3908 ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
3911 ZYAN_ASSERT(instruction
);
3914 switch (state
->prefixes
.mandatory_candidate
)
3917 instruction
->raw
.prefixes
[state
->prefixes
.offset_mandatory
].type
=
3918 ZYDIS_PREFIX_TYPE_MANDATORY
;
3919 instruction
->attributes
&= ~ZYDIS_ATTRIB_HAS_OPERANDSIZE
;
3923 instruction
->raw
.prefixes
[state
->prefixes
.offset_mandatory
].type
=
3924 ZYDIS_PREFIX_TYPE_MANDATORY
;
3928 instruction
->raw
.prefixes
[state
->prefixes
.offset_mandatory
].type
=
3929 ZYDIS_PREFIX_TYPE_MANDATORY
;
3936 // TODO: Consume prefix and make sure it's available again, if we need to fallback
3938 return ZYAN_STATUS_SUCCESS
;
3941 static ZyanStatus
ZydisNodeHandlerOperandSize(const ZydisDecoderState
* state
,
3942 ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
3945 ZYAN_ASSERT(instruction
);
3948 if ((instruction
->machine_mode
== ZYDIS_MACHINE_MODE_LONG_64
) &&
3949 (state
->context
->vector_unified
.W
))
3954 if (instruction
->attributes
& ZYDIS_ATTRIB_HAS_OPERANDSIZE
)
3956 instruction
->raw
.prefixes
[state
->prefixes
.offset_osz_override
].type
=
3957 ZYDIS_PREFIX_TYPE_EFFECTIVE
;
3959 switch (instruction
->machine_mode
)
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;
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;
3976 return ZYAN_STATUS_SUCCESS
;
3979 static ZyanStatus
ZydisNodeHandlerAddressSize(ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
3981 ZYAN_ASSERT(instruction
);
3984 /*if (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE)
3986 instruction->raw.prefixes[context->prefixes.offset_asz_override].type =
3987 ZYDIS_PREFIX_TYPE_EFFECTIVE;
3989 switch (instruction
->machine_mode
)
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;
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;
4000 case ZYDIS_MACHINE_MODE_LONG_64
:
4001 *index
= (instruction
->attributes
& ZYDIS_ATTRIB_HAS_ADDRESSSIZE
) ? 1 : 2;
4007 return ZYAN_STATUS_SUCCESS
;
4010 static ZyanStatus
ZydisNodeHandlerVectorLength(const ZydisDecoderContext
* context
,
4011 const ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
4013 ZYAN_ASSERT(context
);
4014 ZYAN_ASSERT(instruction
);
4017 switch (instruction
->encoding
)
4019 case ZYDIS_INSTRUCTION_ENCODING_XOP
:
4020 ZYAN_ASSERT(instruction
->attributes
& ZYDIS_ATTRIB_HAS_XOP
);
4022 case ZYDIS_INSTRUCTION_ENCODING_VEX
:
4023 ZYAN_ASSERT(instruction
->attributes
& ZYDIS_ATTRIB_HAS_VEX
);
4025 case ZYDIS_INSTRUCTION_ENCODING_EVEX
:
4026 ZYAN_ASSERT(instruction
->attributes
& ZYDIS_ATTRIB_HAS_EVEX
);
4028 case ZYDIS_INSTRUCTION_ENCODING_MVEX
:
4029 ZYAN_ASSERT(instruction
->attributes
& ZYDIS_ATTRIB_HAS_MVEX
);
4035 *index
= context
->vector_unified
.LL
;
4038 return ZYDIS_STATUS_DECODING_ERROR
;
4040 return ZYAN_STATUS_SUCCESS
;
4043 static ZyanStatus
ZydisNodeHandlerRexW(const ZydisDecoderContext
* context
,
4044 const ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
4046 ZYAN_ASSERT(context
);
4047 ZYAN_ASSERT(instruction
);
4050 switch (instruction
->encoding
)
4052 case ZYDIS_INSTRUCTION_ENCODING_LEGACY
:
4053 // nothing to do here
4055 case ZYDIS_INSTRUCTION_ENCODING_XOP
:
4056 ZYAN_ASSERT(instruction
->attributes
& ZYDIS_ATTRIB_HAS_XOP
);
4058 case ZYDIS_INSTRUCTION_ENCODING_VEX
:
4059 ZYAN_ASSERT(instruction
->attributes
& ZYDIS_ATTRIB_HAS_VEX
);
4061 case ZYDIS_INSTRUCTION_ENCODING_EVEX
:
4062 ZYAN_ASSERT(instruction
->attributes
& ZYDIS_ATTRIB_HAS_EVEX
);
4064 case ZYDIS_INSTRUCTION_ENCODING_MVEX
:
4065 ZYAN_ASSERT(instruction
->attributes
& ZYDIS_ATTRIB_HAS_MVEX
);
4070 *index
= context
->vector_unified
.W
;
4071 return ZYAN_STATUS_SUCCESS
;
4074 static ZyanStatus
ZydisNodeHandlerRexB(const ZydisDecoderContext
* context
,
4075 const ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
4077 ZYAN_ASSERT(context
);
4078 ZYAN_ASSERT(instruction
);
4081 switch (instruction
->encoding
)
4083 case ZYDIS_INSTRUCTION_ENCODING_LEGACY
:
4084 // nothing to do here
4086 case ZYDIS_INSTRUCTION_ENCODING_XOP
:
4087 ZYAN_ASSERT(instruction
->attributes
& ZYDIS_ATTRIB_HAS_XOP
);
4089 case ZYDIS_INSTRUCTION_ENCODING_VEX
:
4090 ZYAN_ASSERT(instruction
->attributes
& ZYDIS_ATTRIB_HAS_VEX
);
4092 case ZYDIS_INSTRUCTION_ENCODING_EVEX
:
4093 ZYAN_ASSERT(instruction
->attributes
& ZYDIS_ATTRIB_HAS_EVEX
);
4095 case ZYDIS_INSTRUCTION_ENCODING_MVEX
:
4096 ZYAN_ASSERT(instruction
->attributes
& ZYDIS_ATTRIB_HAS_MVEX
);
4101 *index
= context
->vector_unified
.B
;
4102 return ZYAN_STATUS_SUCCESS
;
4105 #ifndef ZYDIS_DISABLE_AVX512
4106 static ZyanStatus
ZydisNodeHandlerEvexB(const ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
4108 ZYAN_ASSERT(instruction
);
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
;
4118 #ifndef ZYDIS_DISABLE_KNC
4119 static ZyanStatus
ZydisNodeHandlerMvexE(const ZydisDecodedInstruction
* instruction
, ZyanU16
* index
)
4121 ZYAN_ASSERT(instruction
);
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
;
4131 /* ---------------------------------------------------------------------------------------------- */
4134 * Populates the internal register id fields for `REG`, `RM`, `NDSNDD`, `BASE` and `INDEX`/`VIDX`
4135 * encoded operands and performs sanity checks.
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.
4143 * @return A zyan status code.
4145 * This function sets all unused register ids to `-1`. This rule does currently not apply to
4146 * `base` and `index`.
4148 * Definition encoding:
4149 * - `def_reg` -> `ZydisRegisterKind`
4150 * - `def_ndsndd` -> `ZydisRegisterKind`
4151 * - `def_rm` -> `ZydisRegisterKind` (`.mod == 3`) or ZydisMemoryOperandType (`.mod != 3`)
4153 static ZyanStatus
ZydisPopulateRegisterIds(ZydisDecoderContext
* context
,
4154 const ZydisDecodedInstruction
* instruction
, ZyanU8 def_reg
, ZyanU8 def_rm
, ZyanU8 def_ndsndd
)
4156 ZYAN_ASSERT(context
);
4157 ZYAN_ASSERT(instruction
);
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
);
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
;
4170 if (instruction
->machine_mode
== ZYDIS_MACHINE_MODE_LONG_64
)
4172 const ZyanBool is_emvex
= (instruction
->encoding
== ZYDIS_INSTRUCTION_ENCODING_EVEX
) ||
4173 (instruction
->encoding
== ZYDIS_INSTRUCTION_ENCODING_MVEX
);
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;
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);
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.
4189 static const ZyanU8 mask_reg
[ZYDIS_REGKIND_MAX_VALUE
+ 1] =
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'`
4204 id_reg
&= mask_reg
[def_reg
];
4206 static const ZyanU8 mask_rm
[ZYDIS_REGKIND_MAX_VALUE
+ 1] =
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`
4221 id_rm
&= (is_reg
? mask_rm
[def_rm
] : 0xFF);
4223 // Commented out for future reference. Not required at the moment as it's always either
4224 // a "take all" or "take nothing" situation.
4226 //static const ZyanU8 mask_ndsndd[ZYDIS_REGKIND_MAX_VALUE + 1] =
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`
4245 // `.vvvv` is not allowed, if the instruction does not encode a NDS/NDD operand
4246 if (!def_ndsndd
&& context
->vector_unified
.vvvv
)
4248 return ZYDIS_STATUS_BAD_REGISTER
;
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
)
4253 return ZYDIS_STATUS_BAD_REGISTER
;
4256 static const ZyanU8 available_regs
[2][ZYDIS_REGKIND_MAX_VALUE
+ 1] =
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.
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
])))
4297 return ZYDIS_STATUS_BAD_REGISTER
;
4301 if (def_reg
== ZYDIS_REGKIND_CONTROL
)
4305 if (is_reg
&& (def_rm
== ZYDIS_REGKIND_CONTROL
))
4311 // Attempts to reference CR1, CR5, CR6, CR7, and CR9..CR15 result in undefined opcode (#UD)
4313 static const ZyanU8 lookup
[16] =
4315 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0
4317 ZYAN_ASSERT((ZyanUSize
)id_cr
< ZYAN_ARRAY_LENGTH(lookup
));
4320 return ZYDIS_STATUS_BAD_REGISTER
;
4324 // Assign to context
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
4332 return ZYAN_STATUS_SUCCESS
;
4336 * Checks for certain post-decode error-conditions.
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.
4342 * @return A zyan status code.
4344 * This function is called immediately after a valid instruction-definition was found.
4346 static ZyanStatus
ZydisCheckErrorConditions(ZydisDecoderState
* state
,
4347 const ZydisDecodedInstruction
* instruction
, const ZydisInstructionDefinition
* definition
)
4350 ZYAN_ASSERT(instruction
);
4351 ZYAN_ASSERT(definition
);
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
;
4363 switch (instruction
->encoding
)
4365 case ZYDIS_INSTRUCTION_ENCODING_LEGACY
:
4367 const ZydisInstructionDefinitionLEGACY
* def
=
4368 (const ZydisInstructionDefinitionLEGACY
*)definition
;
4370 if (def
->requires_protected_mode
&&
4371 (instruction
->machine_mode
== ZYDIS_MACHINE_MODE_REAL_16
))
4373 return ZYDIS_STATUS_DECODING_ERROR
;
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
)))
4380 return ZYDIS_STATUS_DECODING_ERROR
;
4383 if (state
->prefixes
.has_lock
&& !def
->accepts_LOCK
)
4385 return ZYDIS_STATUS_ILLEGAL_LOCK
;
4389 case ZYDIS_INSTRUCTION_ENCODING_3DNOW
:
4393 case ZYDIS_INSTRUCTION_ENCODING_XOP
:
4395 const ZydisInstructionDefinitionXOP
* def
=
4396 (const ZydisInstructionDefinitionXOP
*)definition
;
4397 def_ndsndd
= def
->op_ndsndd
;
4400 case ZYDIS_INSTRUCTION_ENCODING_VEX
:
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
;
4409 case ZYDIS_INSTRUCTION_ENCODING_EVEX
:
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
;
4419 // Check for invalid zero-mask
4420 if ((instruction
->raw
.evex
.z
) && (!def
->accepts_zero_mask
))
4422 return ZYDIS_STATUS_INVALID_MASK
; // TODO: Dedicated status code
4429 case ZYDIS_INSTRUCTION_ENCODING_MVEX
:
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
;
4438 // Check for invalid MVEX.SSS values
4439 static const ZyanU8 lookup
[26][8] =
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 }
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
])
4498 return ZYDIS_STATUS_DECODING_ERROR
;
4509 ZydisDecoderContext
* context
= state
->context
;
4510 const ZyanBool is_reg
= context
->reg_info
.is_mod_reg
;
4512 ZyanU8 no_rip_rel
= ZYAN_FALSE
;
4513 ZyanU8 is_sr_dest_reg
= ZYAN_FALSE
;
4514 ZyanU8 is_sr_dest_rm
= ZYAN_FALSE
;
4517 is_sr_dest_reg
= ZYDIS_OPDEF_GET_REG_HIGH_BIT(def_reg
);
4518 def_reg
= ZYDIS_OPDEF_GET_REG(def_reg
);
4524 is_sr_dest_rm
= ZYDIS_OPDEF_GET_REG_HIGH_BIT(def_rm
);
4525 def_rm
= ZYDIS_OPDEF_GET_REG(def_rm
);
4529 no_rip_rel
= ZYDIS_OPDEF_GET_MEM_HIGH_BIT(def_rm
);
4530 def_rm
= ZYDIS_OPDEF_GET_MEM(def_rm
);
4534 // Check RIP-relative memory addressing
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);
4542 return ZYDIS_STATUS_BAD_REGISTER
;
4546 // Populate- and validate register constraints
4547 ZYAN_CHECK(ZydisPopulateRegisterIds(context
, instruction
, def_reg
, def_rm
, def_ndsndd
));
4549 // `ZYDIS_REGISTER_CS` is not allowed as `MOV` target
4550 if (is_sr_dest_reg
&& (context
->reg_info
.id_reg
== 1))
4552 return ZYDIS_STATUS_BAD_REGISTER
;
4554 if (is_sr_dest_rm
&& (context
->reg_info
.id_rm
== 1))
4556 return ZYDIS_STATUS_BAD_REGISTER
;
4559 // Check gather registers
4562 // ZYAN_ASSERT(has_VSIB);
4563 ZYAN_ASSERT(instruction
->raw
.modrm
.mod
!= 3);
4564 ZYAN_ASSERT(instruction
->raw
.modrm
.rm
== 4);
4566 const ZyanU8 index
= context
->reg_info
.id_index
;
4567 ZyanU8 dest
= context
->reg_info
.id_reg
;
4570 if (instruction
->encoding
== ZYDIS_INSTRUCTION_ENCODING_VEX
)
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
;
4578 if ((instruction
->encoding
== ZYDIS_INSTRUCTION_ENCODING_EVEX
) ||
4579 (instruction
->encoding
== ZYDIS_INSTRUCTION_ENCODING_MVEX
))
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
));
4586 // Some gather instructions (like `VGATHERPF0{D|Q}{PS|PD}`) do not have a destination
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
))
4598 return ZYDIS_STATUS_BAD_REGISTER
;
4602 // Check if any source register matches the destination register
4603 if (no_source_dest_match
)
4605 ZYAN_ASSERT((instruction
->encoding
== ZYDIS_INSTRUCTION_ENCODING_EVEX
) ||
4606 (instruction
->encoding
== ZYDIS_INSTRUCTION_ENCODING_VEX
));
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
;
4612 if ((dest
== source1
) || (is_reg
&& (dest
== source2
)))
4614 return ZYDIS_STATUS_BAD_REGISTER
;
4618 // If any pair of the source or destination registers are the same, the instruction results a
4620 if (no_source_source_match
) // TODO: Find better name
4622 ZYAN_ASSERT(instruction
->encoding
== ZYDIS_INSTRUCTION_ENCODING_VEX
);
4623 ZYAN_ASSERT(is_reg
);
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
;
4629 if ((dest
== source1
) || (dest
== source2
) || (source1
== source2
))
4631 return ZYDIS_STATUS_BAD_REGISTER
;
4635 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
4636 // Check for invalid MASK registers
4637 switch (mask_policy
)
4639 case ZYDIS_MASK_POLICY_INVALID
:
4640 case ZYDIS_MASK_POLICY_ALLOWED
:
4641 // Nothing to do here
4643 case ZYDIS_MASK_POLICY_REQUIRED
:
4644 if (!context
->vector_unified
.mask
)
4646 return ZYDIS_STATUS_INVALID_MASK
;
4649 case ZYDIS_MASK_POLICY_FORBIDDEN
:
4650 if (context
->vector_unified
.mask
)
4652 return ZYDIS_STATUS_INVALID_MASK
;
4660 return ZYAN_STATUS_SUCCESS
;
4663 /* ---------------------------------------------------------------------------------------------- */
4666 * Uses the decoder-tree to decode the current instruction.
4668 * @param state A pointer to the `ZydisDecoderState` struct.
4669 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
4671 * @return A zyan status code.
4673 static ZyanStatus
ZydisDecodeInstruction(ZydisDecoderState
* state
,
4674 ZydisDecodedInstruction
* instruction
)
4677 ZYAN_ASSERT(instruction
);
4679 // Iterate through the decoder tree
4680 const ZydisDecoderTreeNode
* node
= ZydisDecoderTreeGetRootNode();
4681 const ZydisDecoderTreeNode
* temp
= ZYAN_NULL
;
4682 ZydisDecoderTreeNodeType node_type
;
4685 node_type
= node
->type
;
4687 ZyanStatus status
= 0;
4690 case ZYDIS_NODETYPE_INVALID
:
4695 node_type
= ZYDIS_NODETYPE_FILTER_MANDATORY_PREFIX
;
4696 if (state
->prefixes
.mandatory_candidate
!= 0x00)
4698 instruction
->raw
.prefixes
[state
->prefixes
.offset_mandatory
].type
=
4699 ZYDIS_PREFIX_TYPE_IGNORED
;
4701 if (state
->prefixes
.mandatory_candidate
== 0x66)
4703 if (state
->prefixes
.offset_osz_override
==
4704 state
->prefixes
.offset_mandatory
)
4706 instruction
->raw
.prefixes
[state
->prefixes
.offset_mandatory
].type
=
4707 ZYDIS_PREFIX_TYPE_EFFECTIVE
;
4709 instruction
->attributes
|= ZYDIS_ATTRIB_HAS_OPERANDSIZE
;
4713 return ZYDIS_STATUS_DECODING_ERROR
;
4714 case ZYDIS_NODETYPE_FILTER_XOP
:
4715 status
= ZydisNodeHandlerXOP(instruction
, &index
);
4717 case ZYDIS_NODETYPE_FILTER_VEX
:
4718 status
= ZydisNodeHandlerVEX(instruction
, &index
);
4720 case ZYDIS_NODETYPE_FILTER_EMVEX
:
4721 status
= ZydisNodeHandlerEMVEX(instruction
, &index
);
4723 case ZYDIS_NODETYPE_FILTER_OPCODE
:
4724 status
= ZydisNodeHandlerOpcode(state
, instruction
, &index
);
4726 case ZYDIS_NODETYPE_FILTER_MODE
:
4727 status
= ZydisNodeHandlerMode(instruction
, &index
);
4729 case ZYDIS_NODETYPE_FILTER_MODE_COMPACT
:
4730 status
= ZydisNodeHandlerModeCompact(instruction
, &index
);
4732 case ZYDIS_NODETYPE_FILTER_MODRM_MOD
:
4733 status
= ZydisNodeHandlerModrmMod(state
, instruction
, &index
);
4735 case ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT
:
4736 status
= ZydisNodeHandlerModrmModCompact(state
, instruction
, &index
);
4738 case ZYDIS_NODETYPE_FILTER_MODRM_REG
:
4739 status
= ZydisNodeHandlerModrmReg(state
, instruction
, &index
);
4741 case ZYDIS_NODETYPE_FILTER_MODRM_RM
:
4742 status
= ZydisNodeHandlerModrmRm(state
, instruction
, &index
);
4744 case ZYDIS_NODETYPE_FILTER_PREFIX_GROUP1
:
4745 index
= state
->prefixes
.group1
? 1 : 0;
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
4754 case ZYDIS_NODETYPE_FILTER_OPERAND_SIZE
:
4755 status
= ZydisNodeHandlerOperandSize(state
, instruction
, &index
);
4757 case ZYDIS_NODETYPE_FILTER_ADDRESS_SIZE
:
4758 status
= ZydisNodeHandlerAddressSize(instruction
, &index
);
4760 case ZYDIS_NODETYPE_FILTER_VECTOR_LENGTH
:
4761 status
= ZydisNodeHandlerVectorLength(state
->context
, instruction
, &index
);
4763 case ZYDIS_NODETYPE_FILTER_REX_W
:
4764 status
= ZydisNodeHandlerRexW(state
->context
, instruction
, &index
);
4766 case ZYDIS_NODETYPE_FILTER_REX_B
:
4767 status
= ZydisNodeHandlerRexB(state
->context
, instruction
, &index
);
4769 #ifndef ZYDIS_DISABLE_AVX512
4770 case ZYDIS_NODETYPE_FILTER_EVEX_B
:
4771 status
= ZydisNodeHandlerEvexB(instruction
, &index
);
4774 #ifndef ZYDIS_DISABLE_KNC
4775 case ZYDIS_NODETYPE_FILTER_MVEX_E
:
4776 status
= ZydisNodeHandlerMvexE(instruction
, &index
);
4779 case ZYDIS_NODETYPE_FILTER_MODE_AMD
:
4780 index
= !!(state
->decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_AMD_BRANCHES
));
4782 case ZYDIS_NODETYPE_FILTER_MODE_KNC
:
4783 index
= !!(state
->decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_KNC
));
4785 case ZYDIS_NODETYPE_FILTER_MODE_MPX
:
4786 index
= !!(state
->decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_MPX
));
4788 case ZYDIS_NODETYPE_FILTER_MODE_CET
:
4789 index
= !!(state
->decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_CET
));
4791 case ZYDIS_NODETYPE_FILTER_MODE_LZCNT
:
4792 index
= !!(state
->decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_LZCNT
));
4794 case ZYDIS_NODETYPE_FILTER_MODE_TZCNT
:
4795 index
= !!(state
->decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_TZCNT
));
4797 case ZYDIS_NODETYPE_FILTER_MODE_WBNOINVD
:
4798 index
= !!(state
->decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_WBNOINVD
));
4800 case ZYDIS_NODETYPE_FILTER_MODE_CLDEMOTE
:
4801 index
= !!(state
->decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_CLDEMOTE
));
4803 case ZYDIS_NODETYPE_FILTER_MODE_IPREFETCH
:
4804 index
= !!(state
->decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_IPREFETCH
));
4806 case ZYDIS_NODETYPE_FILTER_MODE_UD0_COMPAT
:
4807 index
= !!(state
->decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_UD0_COMPAT
));
4810 if (node_type
& ZYDIS_NODETYPE_DEFINITION_MASK
)
4812 const ZydisInstructionDefinition
* definition
;
4813 ZydisGetInstructionDefinition(instruction
->encoding
, node
->value
, &definition
);
4814 ZydisSetEffectiveOperandWidth(state
->context
, instruction
, definition
);
4815 ZydisSetEffectiveAddressWidth(state
->context
, instruction
, definition
);
4817 const ZydisInstructionEncodingInfo
* info
;
4818 ZydisGetInstructionEncodingInfo(node
, &info
);
4819 ZYAN_CHECK(ZydisDecodeOptionalInstructionParts(state
, instruction
, info
));
4820 ZYAN_CHECK(ZydisCheckErrorConditions(state
, instruction
, definition
));
4822 if (instruction
->encoding
== ZYDIS_INSTRUCTION_ENCODING_3DNOW
)
4824 // Get actual 3DNOW opcode and definition
4825 ZYAN_CHECK(ZydisInputNext(state
, instruction
, &instruction
->opcode
));
4826 node
= ZydisDecoderTreeGetRootNode();
4827 node
= ZydisDecoderTreeGetChildNode(node
, 0x0F);
4828 node
= ZydisDecoderTreeGetChildNode(node
, 0x0F);
4829 node
= ZydisDecoderTreeGetChildNode(node
, instruction
->opcode
);
4830 if (node
->type
== ZYDIS_NODETYPE_INVALID
)
4832 return ZYDIS_STATUS_DECODING_ERROR
;
4834 ZYAN_ASSERT(node
->type
== ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT
);
4835 node
= ZydisDecoderTreeGetChildNode(
4836 node
, (instruction
->raw
.modrm
.mod
== 0x3) ? 0 : 1);
4837 ZYAN_ASSERT(node
->type
& ZYDIS_NODETYPE_DEFINITION_MASK
);
4838 ZydisGetInstructionDefinition(instruction
->encoding
, node
->value
, &definition
);
4841 instruction
->mnemonic
= definition
->mnemonic
;
4843 #ifndef ZYDIS_MINIMAL_MODE
4845 instruction
->operand_count
= definition
->operand_count
;
4846 instruction
->operand_count_visible
= definition
->operand_count_visible
;
4847 state
->context
->definition
= definition
;
4849 instruction
->meta
.category
= definition
->category
;
4850 instruction
->meta
.isa_set
= definition
->isa_set
;
4851 instruction
->meta
.isa_ext
= definition
->isa_ext
;
4852 instruction
->meta
.branch_type
= definition
->branch_type
;
4853 ZYAN_ASSERT((instruction
->meta
.branch_type
== ZYDIS_BRANCH_TYPE_NONE
) ||
4854 ((instruction
->meta
.category
== ZYDIS_CATEGORY_CALL
) ||
4855 (instruction
->meta
.category
== ZYDIS_CATEGORY_COND_BR
) ||
4856 (instruction
->meta
.category
== ZYDIS_CATEGORY_UNCOND_BR
) ||
4857 (instruction
->meta
.category
== ZYDIS_CATEGORY_RET
)));
4858 instruction
->meta
.exception_class
= definition
->exception_class
;
4860 if (!(state
->decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_MINIMAL
)))
4862 ZydisSetAttributes(state
, instruction
, definition
);
4863 switch (instruction
->encoding
)
4865 case ZYDIS_INSTRUCTION_ENCODING_XOP
:
4866 case ZYDIS_INSTRUCTION_ENCODING_VEX
:
4867 case ZYDIS_INSTRUCTION_ENCODING_EVEX
:
4868 case ZYDIS_INSTRUCTION_ENCODING_MVEX
:
4869 ZydisSetAVXInformation(state
->context
, instruction
, definition
);
4875 const ZydisDefinitionAccessedFlags
* flags
;
4876 if (ZydisGetAccessedFlags(definition
, &flags
))
4878 instruction
->attributes
|= ZYDIS_ATTRIB_CPUFLAG_ACCESS
;
4880 instruction
->cpu_flags
= &flags
->cpu_flags
;
4881 instruction
->fpu_flags
= &flags
->fpu_flags
;
4886 return ZYAN_STATUS_SUCCESS
;
4891 node
= ZydisDecoderTreeGetChildNode(node
, index
);
4892 } while ((node_type
!= ZYDIS_NODETYPE_INVALID
) && !(node_type
& ZYDIS_NODETYPE_DEFINITION_MASK
));
4893 return ZYAN_STATUS_SUCCESS
;
4896 /* ---------------------------------------------------------------------------------------------- */
4898 /* ============================================================================================== */
4899 /* Exported functions */
4900 /* ============================================================================================== */
4902 ZyanStatus
ZydisDecoderInit(ZydisDecoder
* decoder
, ZydisMachineMode machine_mode
,
4903 ZydisStackWidth stack_width
)
4905 ZYAN_STATIC_ASSERT(ZYDIS_DECODER_MODE_MAX_VALUE
<= 32);
4907 static const ZyanU32 decoder_modes
=
4908 #ifdef ZYDIS_MINIMAL_MODE
4909 (1 << ZYDIS_DECODER_MODE_MINIMAL
) |
4911 (1 << ZYDIS_DECODER_MODE_MPX
) |
4912 (1 << ZYDIS_DECODER_MODE_CET
) |
4913 (1 << ZYDIS_DECODER_MODE_LZCNT
) |
4914 (1 << ZYDIS_DECODER_MODE_TZCNT
) |
4915 (1 << ZYDIS_DECODER_MODE_CLDEMOTE
) |
4916 (1 << ZYDIS_DECODER_MODE_IPREFETCH
);
4920 return ZYAN_STATUS_INVALID_ARGUMENT
;
4922 switch (machine_mode
)
4924 case ZYDIS_MACHINE_MODE_LONG_64
:
4925 if (stack_width
!= ZYDIS_STACK_WIDTH_64
)
4927 return ZYAN_STATUS_INVALID_ARGUMENT
;
4930 case ZYDIS_MACHINE_MODE_LONG_COMPAT_32
:
4931 case ZYDIS_MACHINE_MODE_LONG_COMPAT_16
:
4932 case ZYDIS_MACHINE_MODE_LEGACY_32
:
4933 case ZYDIS_MACHINE_MODE_LEGACY_16
:
4934 case ZYDIS_MACHINE_MODE_REAL_16
:
4935 if ((stack_width
!= ZYDIS_STACK_WIDTH_16
) && (stack_width
!= ZYDIS_STACK_WIDTH_32
))
4937 return ZYAN_STATUS_INVALID_ARGUMENT
;
4941 return ZYAN_STATUS_INVALID_ARGUMENT
;
4944 decoder
->machine_mode
= machine_mode
;
4945 decoder
->stack_width
= stack_width
;
4946 decoder
->decoder_mode
= decoder_modes
;
4948 return ZYAN_STATUS_SUCCESS
;
4951 ZyanStatus
ZydisDecoderEnableMode(ZydisDecoder
* decoder
, ZydisDecoderMode mode
, ZyanBool enabled
)
4953 if (!decoder
|| ((ZyanUSize
)mode
> ZYDIS_DECODER_MODE_MAX_VALUE
))
4955 return ZYAN_STATUS_INVALID_ARGUMENT
;
4958 #ifdef ZYDIS_MINIMAL_MODE
4959 if ((mode
== ZYDIS_DECODER_MODE_MINIMAL
) && !enabled
)
4961 return ZYAN_STATUS_INVALID_OPERATION
;
4967 decoder
->decoder_mode
|= (1 << mode
);
4971 decoder
->decoder_mode
&= ~(1 << mode
);
4974 return ZYAN_STATUS_SUCCESS
;
4977 ZyanStatus
ZydisDecoderDecodeFull(const ZydisDecoder
* decoder
,
4978 const void* buffer
, ZyanUSize length
, ZydisDecodedInstruction
* instruction
,
4979 ZydisDecodedOperand operands
[ZYDIS_MAX_OPERAND_COUNT
])
4981 if (!decoder
|| !instruction
|| !buffer
|| !operands
)
4983 return ZYAN_STATUS_INVALID_ARGUMENT
;
4987 return ZYDIS_STATUS_NO_MORE_DATA
;
4989 if (decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_MINIMAL
))
4991 return ZYAN_STATUS_MISSING_DEPENDENCY
; // TODO: Introduce better status code
4994 ZydisDecoderContext context
;
4995 ZYAN_CHECK(ZydisDecoderDecodeInstruction(decoder
, &context
, buffer
, length
, instruction
));
4996 ZYAN_CHECK(ZydisDecoderDecodeOperands(decoder
, &context
, instruction
, operands
,
4997 instruction
->operand_count
));
4998 ZYAN_MEMSET(&operands
[instruction
->operand_count
], 0,
4999 (ZYDIS_MAX_OPERAND_COUNT
- instruction
->operand_count
) * sizeof(operands
[0]));
5001 return ZYAN_STATUS_SUCCESS
;
5004 ZyanStatus
ZydisDecoderDecodeInstruction(const ZydisDecoder
* decoder
, ZydisDecoderContext
* context
,
5005 const void* buffer
, ZyanUSize length
, ZydisDecodedInstruction
* instruction
)
5007 if (!decoder
|| !instruction
|| !buffer
)
5009 return ZYAN_STATUS_INVALID_ARGUMENT
;
5014 return ZYDIS_STATUS_NO_MORE_DATA
;
5017 ZydisDecoderState state
;
5018 ZYAN_MEMSET(&state
, 0, sizeof(state
));
5019 state
.decoder
= decoder
;
5020 state
.buffer
= (const ZyanU8
*)buffer
;
5021 state
.buffer_len
= length
;
5022 state
.prefixes
.offset_notrack
= -1;
5024 ZydisDecoderContext default_context
;
5027 // Use a fallback context if no custom one has been provided
5028 context
= &default_context
;
5030 ZYAN_MEMSET(context
, 0, sizeof(*context
));
5031 state
.context
= context
;
5033 ZYAN_MEMSET(instruction
, 0, sizeof(*instruction
));
5034 instruction
->machine_mode
= decoder
->machine_mode
;
5035 instruction
->stack_width
= 16 << decoder
->stack_width
;
5037 ZYAN_CHECK(ZydisCollectOptionalPrefixes(&state
, instruction
));
5038 ZYAN_CHECK(ZydisDecodeInstruction(&state
, instruction
));
5040 instruction
->raw
.encoding2
= instruction
->encoding
;
5042 return ZYAN_STATUS_SUCCESS
;
5045 ZyanStatus
ZydisDecoderDecodeOperands(const ZydisDecoder
* decoder
,
5046 const ZydisDecoderContext
* context
, const ZydisDecodedInstruction
* instruction
,
5047 ZydisDecodedOperand
* operands
, ZyanU8 operand_count
)
5049 #ifdef ZYDIS_MINIMAL_MODE
5051 ZYAN_UNUSED(decoder
);
5052 ZYAN_UNUSED(context
);
5053 ZYAN_UNUSED(instruction
);
5054 ZYAN_UNUSED(operands
);
5055 ZYAN_UNUSED(operand_count
);
5057 return ZYAN_STATUS_MISSING_DEPENDENCY
; // TODO: Introduce better status code
5061 if (!decoder
|| !context
|| !context
->definition
|| !instruction
||
5062 (operand_count
&& !operands
) || (operand_count
> ZYDIS_MAX_OPERAND_COUNT
))
5064 return ZYAN_STATUS_INVALID_ARGUMENT
;
5067 if (decoder
->decoder_mode
& (1 << ZYDIS_DECODER_MODE_MINIMAL
))
5069 return ZYAN_STATUS_MISSING_DEPENDENCY
; // TODO: Introduce better status code
5072 operand_count
= ZYAN_MIN(operand_count
, instruction
->operand_count
);
5075 return ZYAN_STATUS_SUCCESS
;
5078 return ZydisDecodeOperands(decoder
, context
, instruction
, operands
, operand_count
);
5083 /* ============================================================================================== */