ntdll: Buffer pagemap reads in fill_working_set_info().
[wine.git] / libs / zydis / src / Decoder.c
blob2d73c554a28ba3db72e7524ace32faa6f54a1b6f
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
23 * SOFTWARE.
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 /* ---------------------------------------------------------------------------------------------- */
45 /* Decoder context */
46 /* ---------------------------------------------------------------------------------------------- */
48 /**
49 * Defines the `ZydisDecoderState` struct.
51 typedef struct ZydisDecoderState_
53 /**
54 * A pointer to the `ZydisDecoder` instance.
56 const ZydisDecoder* decoder;
57 /**
58 * A pointer to the `ZydisDecoderContext` struct.
60 ZydisDecoderContext* context;
61 /**
62 * The input buffer.
64 const ZyanU8* buffer;
65 /**
66 * The input buffer length.
68 ZyanUSize buffer_len;
69 /**
70 * Prefix information.
72 struct
74 /**
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.
80 ZyanBool has_lock;
81 /**
82 * The effective prefix of group 1 (either `F2` or `F3`).
84 ZyanU8 group1;
85 /**
86 * The effective prefix of group 2 (`2E`, `36`, `3E`, `26`, `64` or `65`).
88 ZyanU8 group2;
89 /**
90 * The effective segment prefix.
92 ZyanU8 effective_segment;
93 /**
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.
104 ZyanU8 offset_lock;
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;
137 } prefixes;
138 } ZydisDecoderState;
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:
154 * - `REX.B`
156 ZYDIS_REG_ENCODING_OPCODE,
158 * The register-id is encoded in `modrm.reg`.
160 * Possible extension by:
161 * - `.R`
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:
176 * - `.B`
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:
184 * - `.B`
186 ZYDIS_REG_ENCODING_BASE,
188 * The register-id is encoded in `sib.index`.
190 * Possible extension by:
191 * - `.X`
193 ZYDIS_REG_ENCODING_INDEX,
195 * The register-id is encoded in `sib.index`.
197 * Possible extension by:
198 * - `.X`
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
206 * all other modes.
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
244 * data is available.
246 static ZyanStatus ZydisInputPeek(ZydisDecoderState* state,
247 ZydisDecodedInstruction* instruction, ZyanU8* value)
249 ZYAN_ASSERT(state);
250 ZYAN_ASSERT(instruction);
251 ZYAN_ASSERT(value);
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)
279 ZYAN_ASSERT(state);
280 ZYAN_ASSERT(instruction);
281 ZYAN_ASSERT(instruction->length < ZYDIS_MAX_INSTRUCTION_LENGTH);
283 ++instruction->length;
284 ++state->buffer;
285 --state->buffer_len;
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)
303 ZYAN_ASSERT(state);
304 ZYAN_ASSERT(instruction);
305 ZYAN_ASSERT(value);
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;
316 --state->buffer_len;
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
330 * data-source.
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)
340 ZYAN_ASSERT(state);
341 ZYAN_ASSERT(instruction);
342 ZYAN_ASSERT(value);
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,
375 ZyanU8 data)
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;
467 switch (data[0])
469 case 0xC4:
470 ZYAN_ASSERT(instruction->raw.vex.offset == instruction->length - 3);
471 instruction->raw.vex.size = 3;
472 instruction->raw.vex.R = (data[1] >> 7) & 0x01;
473 instruction->raw.vex.X = (data[1] >> 6) & 0x01;
474 instruction->raw.vex.B = (data[1] >> 5) & 0x01;
475 instruction->raw.vex.m_mmmm = (data[1] >> 0) & 0x1F;
476 instruction->raw.vex.W = (data[2] >> 7) & 0x01;
477 instruction->raw.vex.vvvv = (data[2] >> 3) & 0x0F;
478 instruction->raw.vex.L = (data[2] >> 2) & 0x01;
479 instruction->raw.vex.pp = (data[2] >> 0) & 0x03;
480 break;
481 case 0xC5:
482 ZYAN_ASSERT(instruction->raw.vex.offset == instruction->length - 2);
483 instruction->raw.vex.size = 2;
484 instruction->raw.vex.R = (data[1] >> 7) & 0x01;
485 instruction->raw.vex.X = 1;
486 instruction->raw.vex.B = 1;
487 instruction->raw.vex.m_mmmm = 1;
488 instruction->raw.vex.W = 0;
489 instruction->raw.vex.vvvv = (data[1] >> 3) & 0x0F;
490 instruction->raw.vex.L = (data[1] >> 2) & 0x01;
491 instruction->raw.vex.pp = (data[1] >> 0) & 0x03;
492 break;
493 default:
494 ZYAN_UNREACHABLE;
497 // Map 0 is only valid for some KNC instructions
498 #ifdef ZYDIS_DISABLE_KNC
499 if ((instruction->raw.vex.m_mmmm == 0) || (instruction->raw.vex.m_mmmm > 0x03))
500 #else
501 if (instruction->raw.vex.m_mmmm > 0x03)
502 #endif
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;
549 if (data[1] & 0x08)
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;
613 #endif
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;
675 #endif
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)
729 ZYAN_ASSERT(state);
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;
736 switch (size)
738 case 8:
740 ZyanU8 value;
741 ZYAN_CHECK(ZydisInputNext(state, instruction, &value));
742 instruction->raw.disp.value = *(ZyanI8*)&value;
743 break;
745 case 16:
747 ZyanU16 value;
748 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 2));
749 instruction->raw.disp.value = *(ZyanI16*)&value;
750 break;
752 case 32:
754 ZyanU32 value;
755 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 4));
756 instruction->raw.disp.value = *(ZyanI32*)&value;
757 break;
759 case 64:
761 ZyanU64 value;
762 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 8));
763 instruction->raw.disp.value = *(ZyanI64*)&value;
764 break;
766 default:
767 ZYAN_UNREACHABLE;
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)
791 ZYAN_ASSERT(state);
792 ZYAN_ASSERT(instruction);
793 ZYAN_ASSERT((id == 0) || (id == 1));
794 ZYAN_ASSERT(is_signed || !is_relative);
795 ZYAN_ASSERT(instruction->raw.imm[id].size == 0);
797 instruction->raw.imm[id].size = size;
798 instruction->raw.imm[id].offset = instruction->length;
799 instruction->raw.imm[id].is_signed = is_signed;
800 instruction->raw.imm[id].is_relative = is_relative;
801 switch (size)
803 case 8:
805 ZyanU8 value;
806 ZYAN_CHECK(ZydisInputNext(state, instruction, &value));
807 if (is_signed)
809 instruction->raw.imm[id].value.s = (ZyanI8)value;
810 } else
812 instruction->raw.imm[id].value.u = value;
814 break;
816 case 16:
818 ZyanU16 value;
819 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 2));
820 if (is_signed)
822 instruction->raw.imm[id].value.s = (ZyanI16)value;
823 } else
825 instruction->raw.imm[id].value.u = value;
827 break;
829 case 32:
831 ZyanU32 value;
832 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 4));
833 if (is_signed)
835 instruction->raw.imm[id].value.s = (ZyanI32)value;
836 } else
838 instruction->raw.imm[id].value.u = value;
840 break;
842 case 64:
844 ZyanU64 value;
845 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 8));
846 if (is_signed)
848 instruction->raw.imm[id].value.s = (ZyanI64)value;
849 } else
851 instruction->raw.imm[id].value.u = value;
853 break;
855 default:
856 ZYAN_UNREACHABLE;
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
880 * decoded structs.
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
892 switch (encoding)
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);
912 if (value > 7)
914 value = value - 8;
916 if (instruction->machine_mode != ZYDIS_MACHINE_MODE_LONG_64)
918 return value;
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);
940 default:
941 break;
944 return value;
946 case ZYDIS_REG_ENCODING_MASK:
947 return context->vector_unified.mask;
948 default:
949 ZYAN_UNREACHABLE;
952 #endif
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);
972 // Operand size
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;
980 } else
982 operand->size = ZydisRegisterGetWidth(instruction->machine_mode,
983 operand->reg.value);
985 operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
986 operand->element_size = operand->size;
987 break;
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;
1001 } else
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;
1007 break;
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;
1014 } else
1016 // Operand size depends on the tuple-type, the element-size and the number of
1017 // elements
1018 ZYAN_ASSERT(instruction->avx.vector_length);
1019 ZYAN_ASSERT(context->evex.element_size);
1020 switch (context->evex.tuple_type)
1022 case ZYDIS_TUPLETYPE_FV:
1023 if (instruction->avx.broadcast.mode)
1025 operand->size = context->evex.element_size;
1026 } else
1028 operand->size = instruction->avx.vector_length;
1030 break;
1031 case ZYDIS_TUPLETYPE_HV:
1032 if (instruction->avx.broadcast.mode)
1034 operand->size = context->evex.element_size;
1035 } else
1037 operand->size = (ZyanU16)instruction->avx.vector_length / 2;
1039 break;
1040 case ZYDIS_TUPLETYPE_QUARTER:
1041 if (instruction->avx.broadcast.mode)
1043 operand->size = context->evex.element_size;
1045 else
1047 operand->size = (ZyanU16)instruction->avx.vector_length / 4;
1049 break;
1050 default:
1051 ZYAN_UNREACHABLE;
1054 ZYAN_ASSERT(operand->size);
1055 #else
1056 ZYAN_UNREACHABLE;
1057 #endif
1058 break;
1059 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
1060 #ifndef ZYDIS_DISABLE_KNC
1061 if (definition->size[context->eosz_index])
1063 // Operand size is hardcoded
1064 operand->size = definition->size[context->eosz_index] * 8;
1065 } else
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;
1082 break;
1083 case ZYDIS_MVEX_FUNC_SF_32_BCST:
1084 operand->size = 256;
1085 operand->element_type = ZYDIS_ELEMENT_TYPE_FLOAT32;
1086 operand->element_size = 32;
1087 break;
1088 case ZYDIS_MVEX_FUNC_SI_32:
1089 case ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16:
1090 case ZYDIS_MVEX_FUNC_UI_32:
1091 case ZYDIS_MVEX_FUNC_DI_32:
1092 operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
1093 operand->element_size = 32;
1094 break;
1095 case ZYDIS_MVEX_FUNC_SI_32_BCST:
1096 operand->size = 256;
1097 operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
1098 operand->element_size = 32;
1099 break;
1100 case ZYDIS_MVEX_FUNC_SF_64:
1101 case ZYDIS_MVEX_FUNC_UF_64:
1102 case ZYDIS_MVEX_FUNC_DF_64:
1103 operand->element_type = ZYDIS_ELEMENT_TYPE_FLOAT64;
1104 operand->element_size = 64;
1105 break;
1106 case ZYDIS_MVEX_FUNC_SI_64:
1107 case ZYDIS_MVEX_FUNC_UI_64:
1108 case ZYDIS_MVEX_FUNC_DI_64:
1109 operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
1110 operand->element_size = 64;
1111 break;
1112 default:
1113 ZYAN_UNREACHABLE;
1115 break;
1116 case ZYDIS_CONVERSION_MODE_FLOAT16:
1117 operand->size = 256;
1118 operand->element_type = ZYDIS_ELEMENT_TYPE_FLOAT16;
1119 operand->element_size = 16;
1120 break;
1121 case ZYDIS_CONVERSION_MODE_SINT16:
1122 operand->size = 256;
1123 operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
1124 operand->element_size = 16;
1125 break;
1126 case ZYDIS_CONVERSION_MODE_UINT16:
1127 operand->size = 256;
1128 operand->element_type = ZYDIS_ELEMENT_TYPE_UINT;
1129 operand->element_size = 16;
1130 break;
1131 case ZYDIS_CONVERSION_MODE_SINT8:
1132 operand->size = 128;
1133 operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
1134 operand->element_size = 8;
1135 break;
1136 case ZYDIS_CONVERSION_MODE_UINT8:
1137 operand->size = 128;
1138 operand->element_type = ZYDIS_ELEMENT_TYPE_UINT;
1139 operand->element_size = 8;
1140 break;
1141 default:
1142 ZYAN_UNREACHABLE;
1145 switch (instruction->avx.broadcast.mode)
1147 case ZYDIS_BROADCAST_MODE_INVALID:
1148 // Nothing to do here
1149 break;
1150 case ZYDIS_BROADCAST_MODE_1_TO_8:
1151 case ZYDIS_BROADCAST_MODE_1_TO_16:
1152 operand->size = operand->element_size;
1153 break;
1154 case ZYDIS_BROADCAST_MODE_4_TO_8:
1155 case ZYDIS_BROADCAST_MODE_4_TO_16:
1156 operand->size = operand->element_size * 4;
1157 break;
1158 default:
1159 ZYAN_UNREACHABLE;
1162 #else
1163 ZYAN_UNREACHABLE;
1164 #endif
1165 break;
1166 default:
1167 ZYAN_UNREACHABLE;
1169 break;
1170 case ZYDIS_OPERAND_TYPE_POINTER:
1171 ZYAN_ASSERT((instruction->raw.imm[0].size == 16) ||
1172 (instruction->raw.imm[0].size == 32));
1173 ZYAN_ASSERT( instruction->raw.imm[1].size == 16);
1174 operand->size = instruction->raw.imm[0].size + instruction->raw.imm[1].size;
1175 break;
1176 case ZYDIS_OPERAND_TYPE_IMMEDIATE:
1177 operand->size = definition->size[context->eosz_index] * 8;
1178 break;
1179 default:
1180 ZYAN_UNREACHABLE;
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
1191 // scaling operands
1192 operand->element_size = operand->size;
1196 // Element count
1197 if (operand->element_size && operand->size && (operand->element_type != ZYDIS_ELEMENT_TYPE_CC))
1199 operand->element_count = operand->size / operand->element_size;
1200 } else
1202 operand->element_count = 1;
1205 #endif
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);
1231 } else
1233 operand->reg.value = ZYDIS_REGISTER_AL + register_id;
1235 } else
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;
1247 #endif
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)
1280 case 16:
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)
1297 case 0:
1298 if (modrm_rm == 6)
1300 displacement_size = 16;
1301 operand->mem.base = ZYDIS_REGISTER_NONE;
1303 break;
1304 case 1:
1305 displacement_size = 8;
1306 break;
1307 case 2:
1308 displacement_size = 16;
1309 break;
1310 default:
1311 ZYAN_UNREACHABLE;
1313 break;
1315 case 32:
1317 operand->mem.base = ZYDIS_REGISTER_EAX + ZydisCalcRegisterId(context, instruction,
1318 ZYDIS_REG_ENCODING_BASE, ZYDIS_REGCLASS_GPR32);
1319 switch (instruction->raw.modrm.mod)
1321 case 0:
1322 if (modrm_rm == 5)
1324 if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
1326 operand->mem.base = ZYDIS_REGISTER_EIP;
1327 } else
1329 operand->mem.base = ZYDIS_REGISTER_NONE;
1331 displacement_size = 32;
1333 break;
1334 case 1:
1335 displacement_size = 8;
1336 break;
1337 case 2:
1338 displacement_size = 32;
1339 break;
1340 default:
1341 ZYAN_UNREACHABLE;
1343 if (modrm_rm == 4)
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;
1365 } else
1367 operand->mem.index = ZYDIS_REGISTER_NONE;
1368 operand->mem.scale = 0;
1370 break;
1372 case 64:
1374 operand->mem.base = ZYDIS_REGISTER_RAX + ZydisCalcRegisterId(context, instruction,
1375 ZYDIS_REG_ENCODING_BASE, ZYDIS_REGCLASS_GPR64);
1376 switch (instruction->raw.modrm.mod)
1378 case 0:
1379 if (modrm_rm == 5)
1381 if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
1383 operand->mem.base = ZYDIS_REGISTER_RIP;
1384 } else
1386 operand->mem.base = ZYDIS_REGISTER_NONE;
1388 displacement_size = 32;
1390 break;
1391 case 1:
1392 displacement_size = 8;
1393 break;
1394 case 2:
1395 displacement_size = 32;
1396 break;
1397 default:
1398 ZYAN_UNREACHABLE;
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;
1423 } else
1425 operand->mem.index = ZYDIS_REGISTER_NONE;
1426 operand->mem.scale = 0;
1428 break;
1430 default:
1431 ZYAN_UNREACHABLE;
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;
1441 #endif
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;
1468 break;
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);
1479 break;
1481 case ZYDIS_IMPLREG_TYPE_GPR_ASZ:
1482 operand->reg.value = ZydisRegisterEncode(
1483 (instruction->address_width == 16) ? ZYDIS_REGCLASS_GPR16 :
1484 (instruction->address_width == 32) ? ZYDIS_REGCLASS_GPR32 : ZYDIS_REGCLASS_GPR64,
1485 definition->op.reg.reg.id);
1486 break;
1487 case ZYDIS_IMPLREG_TYPE_IP_ASZ:
1488 operand->reg.value =
1489 (instruction->address_width == 16) ? ZYDIS_REGISTER_IP :
1490 (instruction->address_width == 32) ? ZYDIS_REGISTER_EIP : ZYDIS_REGISTER_RIP;
1491 break;
1492 case ZYDIS_IMPLREG_TYPE_GPR_SSZ:
1493 operand->reg.value = ZydisRegisterEncode(
1494 (decoder->stack_width == ZYDIS_STACK_WIDTH_16) ? ZYDIS_REGCLASS_GPR16 :
1495 (decoder->stack_width == ZYDIS_STACK_WIDTH_32) ? ZYDIS_REGCLASS_GPR32 :
1496 ZYDIS_REGCLASS_GPR64,
1497 definition->op.reg.reg.id);
1498 break;
1499 case ZYDIS_IMPLREG_TYPE_IP_SSZ:
1500 operand->reg.value =
1501 (decoder->stack_width == ZYDIS_STACK_WIDTH_16) ? ZYDIS_REGISTER_EIP :
1502 (decoder->stack_width == ZYDIS_STACK_WIDTH_32) ? ZYDIS_REGISTER_EIP :
1503 ZYDIS_REGISTER_RIP;
1504 break;
1505 case ZYDIS_IMPLREG_TYPE_FLAGS_SSZ:
1506 operand->reg.value =
1507 (decoder->stack_width == ZYDIS_STACK_WIDTH_16) ? ZYDIS_REGISTER_FLAGS :
1508 (decoder->stack_width == ZYDIS_STACK_WIDTH_32) ? ZYDIS_REGISTER_EFLAGS :
1509 ZYDIS_REGISTER_RFLAGS;
1510 break;
1511 default:
1512 ZYAN_UNREACHABLE;
1515 #endif
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]));
1551 break;
1552 case ZYDIS_IMPLMEM_BASE_AGPR_RM:
1553 operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index],
1554 ZydisCalcRegisterId(context, instruction, ZYDIS_REG_ENCODING_RM,
1555 lookup[context->easz_index]));
1556 break;
1557 case ZYDIS_IMPLMEM_BASE_AAX:
1558 operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 0);
1559 break;
1560 case ZYDIS_IMPLMEM_BASE_ADX:
1561 operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 2);
1562 break;
1563 case ZYDIS_IMPLMEM_BASE_ABX:
1564 operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 3);
1565 break;
1566 case ZYDIS_IMPLMEM_BASE_ASI:
1567 operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 6);
1568 break;
1569 case ZYDIS_IMPLMEM_BASE_ADI:
1570 operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 7);
1571 break;
1572 case ZYDIS_IMPLMEM_BASE_SSP:
1573 operand->mem.base = ZydisRegisterEncode(lookup[decoder->stack_width], 4);
1574 break;
1575 case ZYDIS_IMPLMEM_BASE_SBP:
1576 operand->mem.base = ZydisRegisterEncode(lookup[decoder->stack_width], 5);
1577 break;
1578 default:
1579 ZYAN_UNREACHABLE;
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);
1589 #endif
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);
1608 ZyanU8 imm_id = 0;
1609 for (ZyanU8 i = 0; i < operand_count; ++i)
1611 ZydisRegisterClass register_class = ZYDIS_REGCLASS_INVALID;
1613 operands[i].id = i;
1614 operands[i].visibility = operand->visibility;
1615 operands[i].actions = operand->actions;
1616 ZYAN_ASSERT(!(operand->actions &
1617 ZYDIS_OPERAND_ACTION_READ & ZYDIS_OPERAND_ACTION_CONDREAD) ||
1618 (operand->actions & ZYDIS_OPERAND_ACTION_READ) ^
1619 (operand->actions & ZYDIS_OPERAND_ACTION_CONDREAD));
1620 ZYAN_ASSERT(!(operand->actions &
1621 ZYDIS_OPERAND_ACTION_WRITE & ZYDIS_OPERAND_ACTION_CONDWRITE) ||
1622 (operand->actions & ZYDIS_OPERAND_ACTION_WRITE) ^
1623 (operand->actions & ZYDIS_OPERAND_ACTION_CONDWRITE));
1625 // Implicit operands
1626 switch (operand->type)
1628 case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG:
1629 ZydisDecodeOperandImplicitRegister(decoder, context, instruction, &operands[i], operand);
1630 break;
1631 case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM:
1632 ZydisDecodeOperandImplicitMemory(decoder, context, instruction, &operands[i], operand);
1633 break;
1634 case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1:
1635 operands[i].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
1636 operands[i].size = 8;
1637 operands[i].imm.value.u = 1;
1638 operands[i].imm.is_signed = ZYAN_FALSE;
1639 operands[i].imm.is_relative = ZYAN_FALSE;
1640 break;
1641 default:
1642 break;
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;
1656 break;
1657 case ZYDIS_SEMANTIC_OPTYPE_GPR16:
1658 register_class = ZYDIS_REGCLASS_GPR16;
1659 break;
1660 case ZYDIS_SEMANTIC_OPTYPE_GPR32:
1661 register_class = ZYDIS_REGCLASS_GPR32;
1662 break;
1663 case ZYDIS_SEMANTIC_OPTYPE_GPR64:
1664 register_class = ZYDIS_REGCLASS_GPR64;
1665 break;
1666 case ZYDIS_SEMANTIC_OPTYPE_GPR16_32_64:
1667 ZYAN_ASSERT((instruction->operand_width == 16) || (instruction->operand_width == 32) ||
1668 (instruction->operand_width == 64));
1669 register_class =
1670 (instruction->operand_width == 16) ? ZYDIS_REGCLASS_GPR16 : (
1671 (instruction->operand_width == 32) ? ZYDIS_REGCLASS_GPR32 : ZYDIS_REGCLASS_GPR64);
1672 break;
1673 case ZYDIS_SEMANTIC_OPTYPE_GPR32_32_64:
1674 ZYAN_ASSERT((instruction->operand_width == 16) || (instruction->operand_width == 32) ||
1675 (instruction->operand_width == 64));
1676 register_class =
1677 (instruction->operand_width == 16) ? ZYDIS_REGCLASS_GPR32 : (
1678 (instruction->operand_width == 32) ? ZYDIS_REGCLASS_GPR32 : ZYDIS_REGCLASS_GPR64);
1679 break;
1680 case ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32:
1681 ZYAN_ASSERT((instruction->operand_width == 16) || (instruction->operand_width == 32) ||
1682 (instruction->operand_width == 64));
1683 register_class =
1684 (instruction->operand_width == 16) ? ZYDIS_REGCLASS_GPR16 : ZYDIS_REGCLASS_GPR32;
1685 break;
1686 case ZYDIS_SEMANTIC_OPTYPE_GPR_ASZ:
1687 ZYAN_ASSERT((instruction->address_width == 16) || (instruction->address_width == 32) ||
1688 (instruction->address_width == 64));
1689 register_class =
1690 (instruction->address_width == 16) ? ZYDIS_REGCLASS_GPR16 : (
1691 (instruction->address_width == 32) ? ZYDIS_REGCLASS_GPR32 : ZYDIS_REGCLASS_GPR64);
1692 break;
1693 case ZYDIS_SEMANTIC_OPTYPE_FPR:
1694 register_class = ZYDIS_REGCLASS_X87;
1695 break;
1696 case ZYDIS_SEMANTIC_OPTYPE_MMX:
1697 register_class = ZYDIS_REGCLASS_MMX;
1698 break;
1699 case ZYDIS_SEMANTIC_OPTYPE_XMM:
1700 register_class = ZYDIS_REGCLASS_XMM;
1701 break;
1702 case ZYDIS_SEMANTIC_OPTYPE_YMM:
1703 register_class = ZYDIS_REGCLASS_YMM;
1704 break;
1705 case ZYDIS_SEMANTIC_OPTYPE_ZMM:
1706 register_class = ZYDIS_REGCLASS_ZMM;
1707 break;
1708 case ZYDIS_SEMANTIC_OPTYPE_TMM:
1709 register_class = ZYDIS_REGCLASS_TMM;
1710 break;
1711 case ZYDIS_SEMANTIC_OPTYPE_BND:
1712 register_class = ZYDIS_REGCLASS_BOUND;
1713 break;
1714 case ZYDIS_SEMANTIC_OPTYPE_SREG:
1715 register_class = ZYDIS_REGCLASS_SEGMENT;
1716 break;
1717 case ZYDIS_SEMANTIC_OPTYPE_CR:
1718 register_class = ZYDIS_REGCLASS_CONTROL;
1719 break;
1720 case ZYDIS_SEMANTIC_OPTYPE_DR:
1721 register_class = ZYDIS_REGCLASS_DEBUG;
1722 break;
1723 case ZYDIS_SEMANTIC_OPTYPE_MASK:
1724 register_class = ZYDIS_REGCLASS_MASK;
1725 break;
1726 default:
1727 break;
1729 if (register_class)
1731 switch (operand->op.encoding)
1733 case ZYDIS_OPERAND_ENCODING_MODRM_REG:
1734 ZYAN_CHECK(
1735 ZydisDecodeOperandRegister(
1736 instruction, &operands[i], register_class,
1737 ZydisCalcRegisterId(
1738 context, instruction, ZYDIS_REG_ENCODING_REG, register_class)));
1739 break;
1740 case ZYDIS_OPERAND_ENCODING_MODRM_RM:
1741 ZYAN_CHECK(
1742 ZydisDecodeOperandRegister(
1743 instruction, &operands[i], register_class,
1744 ZydisCalcRegisterId(
1745 context, instruction, ZYDIS_REG_ENCODING_RM, register_class)));
1746 break;
1747 case ZYDIS_OPERAND_ENCODING_OPCODE:
1748 ZYAN_CHECK(
1749 ZydisDecodeOperandRegister(
1750 instruction, &operands[i], register_class,
1751 ZydisCalcRegisterId(
1752 context, instruction, ZYDIS_REG_ENCODING_OPCODE, register_class)));
1753 break;
1754 case ZYDIS_OPERAND_ENCODING_NDSNDD:
1755 ZYAN_CHECK(
1756 ZydisDecodeOperandRegister(
1757 instruction, &operands[i], register_class,
1758 ZydisCalcRegisterId(
1759 context, instruction, ZYDIS_REG_ENCODING_NDSNDD, register_class)));
1760 break;
1761 case ZYDIS_OPERAND_ENCODING_MASK:
1762 ZYAN_CHECK(
1763 ZydisDecodeOperandRegister(
1764 instruction, &operands[i], register_class,
1765 ZydisCalcRegisterId(
1766 context, instruction, ZYDIS_REG_ENCODING_MASK, register_class)));
1767 break;
1768 case ZYDIS_OPERAND_ENCODING_IS4:
1769 ZYAN_CHECK(
1770 ZydisDecodeOperandRegister(
1771 instruction, &operands[i], register_class,
1772 ZydisCalcRegisterId(
1773 context, instruction, ZYDIS_REG_ENCODING_IS4, register_class)));
1774 break;
1775 default:
1776 ZYAN_UNREACHABLE;
1779 if (operand->is_multisource4)
1781 operands[i].attributes |= ZYDIS_OATTRIB_IS_MULTISOURCE4;
1784 goto FinalizeOperand;
1787 // Memory operands
1788 switch (operand->type)
1790 case ZYDIS_SEMANTIC_OPTYPE_MEM:
1791 ZYAN_CHECK(
1792 ZydisDecodeOperandMemory(
1793 context, instruction, &operands[i], ZYDIS_REGCLASS_INVALID));
1794 break;
1795 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBX:
1796 ZYAN_CHECK(
1797 ZydisDecodeOperandMemory(
1798 context, instruction, &operands[i], ZYDIS_REGCLASS_XMM));
1799 operands[i].mem.type = ZYDIS_MEMOP_TYPE_VSIB;
1800 break;
1801 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBY:
1802 ZYAN_CHECK(
1803 ZydisDecodeOperandMemory(
1804 context, instruction, &operands[i], ZYDIS_REGCLASS_YMM));
1805 operands[i].mem.type = ZYDIS_MEMOP_TYPE_VSIB;
1806 break;
1807 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBZ:
1808 ZYAN_CHECK(
1809 ZydisDecodeOperandMemory(
1810 context, instruction, &operands[i], ZYDIS_REGCLASS_ZMM));
1811 operands[i].mem.type = ZYDIS_MEMOP_TYPE_VSIB;
1812 break;
1813 case ZYDIS_SEMANTIC_OPTYPE_PTR:
1814 ZYAN_ASSERT((instruction->raw.imm[0].size == 16) ||
1815 (instruction->raw.imm[0].size == 32));
1816 ZYAN_ASSERT(instruction->raw.imm[1].size == 16);
1817 operands[i].type = ZYDIS_OPERAND_TYPE_POINTER;
1818 operands[i].ptr.offset = (ZyanU32)instruction->raw.imm[0].value.u;
1819 operands[i].ptr.segment = (ZyanU16)instruction->raw.imm[1].value.u;
1820 break;
1821 case ZYDIS_SEMANTIC_OPTYPE_AGEN:
1822 operands[i].actions = 0; // TODO: Remove after generator update
1823 ZYAN_CHECK(
1824 ZydisDecodeOperandMemory(
1825 context, instruction, &operands[i], ZYDIS_REGCLASS_INVALID));
1826 operands[i].mem.type = ZYDIS_MEMOP_TYPE_AGEN;
1827 break;
1828 case ZYDIS_SEMANTIC_OPTYPE_MOFFS:
1829 ZYAN_ASSERT(instruction->raw.disp.size);
1830 operands[i].type = ZYDIS_OPERAND_TYPE_MEMORY;
1831 operands[i].mem.type = ZYDIS_MEMOP_TYPE_MEM;
1832 operands[i].mem.disp.has_displacement = ZYAN_TRUE;
1833 operands[i].mem.disp.value = instruction->raw.disp.value;
1834 break;
1835 case ZYDIS_SEMANTIC_OPTYPE_MIB:
1836 operands[i].actions = 0; // TODO: Remove after generator update
1837 ZYAN_CHECK(
1838 ZydisDecodeOperandMemory(
1839 context, instruction, &operands[i], ZYDIS_REGCLASS_INVALID));
1840 operands[i].mem.type = ZYDIS_MEMOP_TYPE_MIB;
1841 break;
1842 default:
1843 break;
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;
1855 #endif
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);
1865 ZYAN_FALLTHROUGH;
1866 case ZYDIS_SEMANTIC_OPTYPE_IMM:
1867 ZYAN_ASSERT((imm_id == 0) || (imm_id == 1));
1868 operands[i].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
1869 operands[i].size = operand->size[context->eosz_index] * 8;
1870 if (operand->op.encoding == ZYDIS_OPERAND_ENCODING_IS4)
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;
1876 else
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;
1882 ++imm_id;
1883 break;
1884 default:
1885 break;
1887 ZYAN_ASSERT(operands[i].type == ZYDIS_OPERAND_TYPE_IMMEDIATE);
1889 FinalizeOperand:
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;
1898 else
1899 if (!operand->ignore_seg_override &&
1900 instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_SS)
1902 operands[i].mem.segment = ZYDIS_REGISTER_SS;
1904 else
1905 if (!operand->ignore_seg_override &&
1906 instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_DS)
1908 operands[i].mem.segment = ZYDIS_REGISTER_DS;
1910 else
1911 if (!operand->ignore_seg_override &&
1912 instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_ES)
1914 operands[i].mem.segment = ZYDIS_REGISTER_ES;
1916 else
1917 if (!operand->ignore_seg_override &&
1918 instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_FS)
1920 operands[i].mem.segment = ZYDIS_REGISTER_FS;
1922 else
1923 if (!operand->ignore_seg_override &&
1924 instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_GS)
1926 operands[i].mem.segment = ZYDIS_REGISTER_GS;
1928 else
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;
1941 else
1943 operands[i].mem.segment = ZYDIS_REGISTER_DS;
1949 ZydisSetOperandSizeAndElementInfo(context, instruction, &operands[i], operand);
1950 ++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;
1965 else
1967 operands[0].actions = ZYDIS_OPERAND_ACTION_READ_CONDWRITE;
1969 break;
1970 case ZYDIS_OPERAND_ACTION_READWRITE:
1971 operands[0].actions = ZYDIS_OPERAND_ACTION_READ_CONDWRITE;
1972 break;
1973 default:
1974 break;
1977 #endif
1979 return ZYAN_STATUS_SUCCESS;
1981 #endif
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)
1996 ZYAN_ASSERT(state);
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] =
2004 /* NONE */ 0,
2005 /* READ */ ZYDIS_ATTRIB_CPU_STATE_CR,
2006 /* WRITE */ ZYDIS_ATTRIB_CPU_STATE_CW,
2007 /* READWRITE */ ZYDIS_ATTRIB_CPU_STATE_CR | ZYDIS_ATTRIB_CPU_STATE_CW
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] =
2017 /* NONE */ 0,
2018 /* READ */ ZYDIS_ATTRIB_FPU_STATE_CR,
2019 /* WRITE */ ZYDIS_ATTRIB_FPU_STATE_CW,
2020 /* READWRITE */ ZYDIS_ATTRIB_FPU_STATE_CR | ZYDIS_ATTRIB_FPU_STATE_CW
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] =
2030 /* NONE */ 0,
2031 /* READ */ ZYDIS_ATTRIB_XMM_STATE_CR,
2032 /* WRITE */ ZYDIS_ATTRIB_XMM_STATE_CW,
2033 /* READWRITE */ ZYDIS_ATTRIB_XMM_STATE_CR | ZYDIS_ATTRIB_XMM_STATE_CW
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)
2091 case 0xF2:
2092 if (instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_REPNE)
2094 instruction->attributes |= ZYDIS_ATTRIB_HAS_REPNE;
2095 break;
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;
2103 break;
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;
2110 break;
2112 break;
2113 case 0xF3:
2114 if (instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_REP)
2116 instruction->attributes |= ZYDIS_ATTRIB_HAS_REP;
2117 break;
2119 if (instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_REPE)
2121 instruction->attributes |= ZYDIS_ATTRIB_HAS_REPE;
2122 break;
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;
2130 break;
2133 break;
2134 default:
2135 break;
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)
2152 case 0x2E:
2153 instruction->attributes |= ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN;
2154 instruction->raw.prefixes[state->prefixes.offset_group2].type =
2155 ZYDIS_PREFIX_TYPE_EFFECTIVE;
2156 break;
2157 case 0x3E:
2158 instruction->attributes |= ZYDIS_ATTRIB_HAS_BRANCH_TAKEN;
2159 instruction->raw.prefixes[state->prefixes.offset_group2].type =
2160 ZYDIS_PREFIX_TYPE_EFFECTIVE;
2161 break;
2162 default:
2163 break;
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)
2187 case 0x2E:
2188 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_CS;
2189 break;
2190 case 0x36:
2191 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
2192 break;
2193 case 0x3E:
2194 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
2195 break;
2196 case 0x26:
2197 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_ES;
2198 break;
2199 case 0x64:
2200 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_FS;
2201 break;
2202 case 0x65:
2203 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_GS;
2204 break;
2205 default:
2206 ZYAN_UNREACHABLE;
2209 if (instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT)
2211 instruction->raw.prefixes[state->prefixes.offset_segment].type =
2212 ZYDIS_PREFIX_TYPE_EFFECTIVE;
2216 break;
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)
2230 case 0x2E:
2231 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_CS;
2232 break;
2233 case 0x36:
2234 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
2235 break;
2236 case 0x3E:
2237 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
2238 break;
2239 case 0x26:
2240 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_ES;
2241 break;
2242 case 0x64:
2243 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_FS;
2244 break;
2245 case 0x65:
2246 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_GS;
2247 break;
2248 default:
2249 ZYAN_UNREACHABLE;
2252 if (instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT)
2254 instruction->raw.prefixes[state->prefixes.offset_segment].type =
2255 ZYDIS_PREFIX_TYPE_EFFECTIVE;
2258 break;
2259 default:
2260 ZYAN_UNREACHABLE;
2263 #endif
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`:
2274 * - Vector Length
2276 * Information set for `VEX`:
2277 * - Vector length
2278 * - Static broadcast-factor
2280 * Information set for `EVEX`:
2281 * - Vector length
2282 * - Broadcast-factor (static and dynamic)
2283 * - Rounding-mode and SAE
2284 * - Mask mode
2285 * - Compressed 8-bit displacement scale-factor
2287 * Information set for `MVEX`:
2288 * - Vector length
2289 * - Broadcast-factor (static and dynamic)
2290 * - Rounding-mode and SAE
2291 * - Swizzle- and conversion-mode
2292 * - Mask mode
2293 * - Eviction hint
2294 * - Compressed 8-bit displacement scale-factor
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:
2307 // Vector length
2308 static const ZyanU16 lookup[2] =
2310 128,
2313 ZYAN_ASSERT(context->vector_unified.LL < ZYAN_ARRAY_LENGTH(lookup));
2314 instruction->avx.vector_length = lookup[context->vector_unified.LL];
2315 break;
2317 case ZYDIS_INSTRUCTION_ENCODING_VEX:
2319 // Vector length
2320 static const ZyanU16 lookup[2] =
2322 128,
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;
2331 if (def->broadcast)
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];
2346 break;
2348 case ZYDIS_INSTRUCTION_ENCODING_EVEX:
2350 #ifndef ZYDIS_DISABLE_AVX512
2351 const ZydisInstructionDefinitionEVEX* def =
2352 (const ZydisInstructionDefinitionEVEX*)definition;
2354 // Vector length
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] =
2362 128,
2363 256,
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);
2375 // 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] =
2402 /*B0*/
2404 /*16*/
2406 ZYDIS_BROADCAST_MODE_INVALID,
2407 ZYDIS_BROADCAST_MODE_INVALID,
2408 ZYDIS_BROADCAST_MODE_INVALID
2410 /*32*/
2412 ZYDIS_BROADCAST_MODE_INVALID,
2413 ZYDIS_BROADCAST_MODE_INVALID,
2414 ZYDIS_BROADCAST_MODE_INVALID
2416 /*64*/
2418 ZYDIS_BROADCAST_MODE_INVALID,
2419 ZYDIS_BROADCAST_MODE_INVALID,
2420 ZYDIS_BROADCAST_MODE_INVALID
2423 /*B1*/
2425 /*16*/
2427 ZYDIS_BROADCAST_MODE_1_TO_8,
2428 ZYDIS_BROADCAST_MODE_1_TO_16,
2429 ZYDIS_BROADCAST_MODE_1_TO_32
2431 /*32*/
2433 ZYDIS_BROADCAST_MODE_1_TO_4,
2434 ZYDIS_BROADCAST_MODE_1_TO_8,
2435 ZYDIS_BROADCAST_MODE_1_TO_16
2437 /*64*/
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];
2451 break;
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] =
2469 /*B0*/
2471 /*16*/
2473 ZYDIS_BROADCAST_MODE_INVALID,
2474 ZYDIS_BROADCAST_MODE_INVALID,
2475 ZYDIS_BROADCAST_MODE_INVALID
2477 /*32*/
2479 ZYDIS_BROADCAST_MODE_INVALID,
2480 ZYDIS_BROADCAST_MODE_INVALID,
2481 ZYDIS_BROADCAST_MODE_INVALID
2484 /*B1*/
2486 /*16*/
2488 ZYDIS_BROADCAST_MODE_1_TO_4,
2489 ZYDIS_BROADCAST_MODE_1_TO_8,
2490 ZYDIS_BROADCAST_MODE_1_TO_16
2492 /*32*/
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];
2506 break;
2508 case ZYDIS_TUPLETYPE_FVM:
2510 static const ZyanU8 scales[3] =
2512 16, 32, 64
2514 context->cd8_scale = scales[vector_length];
2515 break;
2517 case ZYDIS_TUPLETYPE_GSCAT:
2518 switch (context->vector_unified.W)
2520 case 0:
2521 ZYAN_ASSERT(context->evex.element_size == 32);
2522 break;
2523 case 1:
2524 ZYAN_ASSERT(context->evex.element_size == 64);
2525 break;
2526 default:
2527 ZYAN_UNREACHABLE;
2529 ZYAN_FALLTHROUGH;
2530 case ZYDIS_TUPLETYPE_T1S:
2532 static const ZyanU8 scales[6] =
2534 /* */ 0,
2535 /* 8*/ 1,
2536 /* 16*/ 2,
2537 /* 32*/ 4,
2538 /* 64*/ 8,
2539 /*128*/ 16,
2541 ZYAN_ASSERT(def->element_size < ZYAN_ARRAY_LENGTH(scales));
2542 context->cd8_scale = scales[def->element_size];
2543 break;
2545 case ZYDIS_TUPLETYPE_T1F:
2547 static const ZyanU8 scales[3] =
2549 /* 16*/ 2,
2550 /* 32*/ 4,
2551 /* 64*/ 8
2554 const ZyanU8 size_index = context->evex.element_size >> 5;
2555 ZYAN_ASSERT(size_index < 3);
2557 context->cd8_scale = scales[size_index];
2558 break;
2560 case ZYDIS_TUPLETYPE_T1_4X:
2561 ZYAN_ASSERT(context->evex.element_size == 32);
2562 ZYAN_ASSERT(context->vector_unified.W == 0);
2563 context->cd8_scale = 16;
2564 break;
2565 case ZYDIS_TUPLETYPE_T2:
2566 switch (context->vector_unified.W)
2568 case 0:
2569 ZYAN_ASSERT(context->evex.element_size == 32);
2570 context->cd8_scale = 8;
2571 break;
2572 case 1:
2573 ZYAN_ASSERT(context->evex.element_size == 64);
2574 ZYAN_ASSERT((instruction->avx.vector_length == 256) ||
2575 (instruction->avx.vector_length == 512));
2576 context->cd8_scale = 16;
2577 break;
2578 default:
2579 ZYAN_UNREACHABLE;
2581 break;
2582 case ZYDIS_TUPLETYPE_T4:
2583 switch (context->vector_unified.W)
2585 case 0:
2586 ZYAN_ASSERT(context->evex.element_size == 32);
2587 ZYAN_ASSERT((instruction->avx.vector_length == 256) ||
2588 (instruction->avx.vector_length == 512));
2589 context->cd8_scale = 16;
2590 break;
2591 case 1:
2592 ZYAN_ASSERT(context->evex.element_size == 64);
2593 ZYAN_ASSERT(instruction->avx.vector_length == 512);
2594 context->cd8_scale = 32;
2595 break;
2596 default:
2597 ZYAN_UNREACHABLE;
2599 break;
2600 case ZYDIS_TUPLETYPE_T8:
2601 ZYAN_ASSERT(!context->vector_unified.W);
2602 ZYAN_ASSERT(instruction->avx.vector_length == 512);
2603 ZYAN_ASSERT(context->evex.element_size == 32);
2604 context->cd8_scale = 32;
2605 break;
2606 case ZYDIS_TUPLETYPE_HVM:
2608 static const ZyanU8 scales[3] =
2610 8, 16, 32
2612 context->cd8_scale = scales[vector_length];
2613 break;
2615 case ZYDIS_TUPLETYPE_QVM:
2617 static const ZyanU8 scales[3] =
2619 4, 8, 16
2621 context->cd8_scale = scales[vector_length];
2622 break;
2624 case ZYDIS_TUPLETYPE_OVM:
2626 static const ZyanU8 scales[3] =
2628 2, 4, 8
2630 context->cd8_scale = scales[vector_length];
2631 break;
2633 case ZYDIS_TUPLETYPE_M128:
2634 context->cd8_scale = 16;
2635 break;
2636 case ZYDIS_TUPLETYPE_DUP:
2638 static const ZyanU8 scales[3] =
2640 8, 32, 64
2642 context->cd8_scale = scales[vector_length];
2643 break;
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 },
2656 /*B1*/ { 2, 2, 2 }
2658 static const ZydisBroadcastMode broadcasts[2][3] =
2660 /*B0*/
2662 ZYDIS_BROADCAST_MODE_INVALID,
2663 ZYDIS_BROADCAST_MODE_INVALID,
2664 ZYDIS_BROADCAST_MODE_INVALID
2666 /*B1*/
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];
2675 break;
2677 default:
2678 ZYAN_UNREACHABLE;
2680 } else
2682 ZYAN_ASSERT(instruction->raw.modrm.mod == 3);
2685 // Static broadcast-factor
2686 if (def->broadcast)
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
2718 break;
2719 case ZYDIS_EVEX_FUNC_RC:
2720 instruction->avx.rounding.mode = ZYDIS_ROUNDING_MODE_RN + context->vector_unified.LL;
2721 ZYAN_FALLTHROUGH;
2722 case ZYDIS_EVEX_FUNC_SAE:
2723 instruction->avx.has_sae = ZYAN_TRUE;
2724 break;
2725 default:
2726 ZYAN_UNREACHABLE;
2730 // Mask
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;
2736 break;
2737 case ZYDIS_MASK_OVERRIDE_ZEROING:
2738 instruction->avx.mask.mode = ZYDIS_MASK_MODE_ZEROING;
2739 break;
2740 case ZYDIS_MASK_OVERRIDE_CONTROL:
2741 instruction->avx.mask.mode = ZYDIS_MASK_MODE_CONTROL + instruction->raw.evex.z;
2742 break;
2743 default:
2744 ZYAN_UNREACHABLE;
2746 if (!instruction->raw.evex.aaa)
2748 instruction->avx.mask.mode = ZYDIS_MASK_MODE_DISABLED;
2750 #else
2751 ZYAN_UNREACHABLE;
2752 #endif
2753 break;
2755 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
2757 #ifndef ZYDIS_DISABLE_KNC
2758 // Vector length
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;
2774 index = 1;
2775 break;
2776 case ZYDIS_MVEX_STATIC_BROADCAST_1_TO_16:
2777 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_16;
2778 index = 1;
2779 break;
2780 case ZYDIS_MVEX_STATIC_BROADCAST_4_TO_8:
2781 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_8;
2782 index = 2;
2783 break;
2784 case ZYDIS_MVEX_STATIC_BROADCAST_4_TO_16:
2785 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_16;
2786 index = 2;
2787 break;
2788 default:
2789 ZYAN_UNREACHABLE;
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
2803 break;
2804 case ZYDIS_MVEX_FUNC_F_32:
2805 case ZYDIS_MVEX_FUNC_I_32:
2806 case ZYDIS_MVEX_FUNC_F_64:
2807 case ZYDIS_MVEX_FUNC_I_64:
2808 context->cd8_scale = 64;
2809 break;
2810 case ZYDIS_MVEX_FUNC_SF_32:
2811 case ZYDIS_MVEX_FUNC_SF_32_BCST:
2812 case ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16:
2813 case ZYDIS_MVEX_FUNC_UF_32:
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];
2823 break;
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];
2838 break;
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] =
2847 { 64, 8, 32 },
2848 { 8, 0, 0 },
2849 { 32, 0, 0 }
2851 ZYAN_ASSERT(instruction->raw.mvex.SSS < ZYAN_ARRAY_LENGTH(lookup[index]));
2852 context->cd8_scale = lookup[index][instruction->raw.mvex.SSS];
2853 break;
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];
2866 break;
2868 case ZYDIS_MVEX_FUNC_DF_64:
2869 case ZYDIS_MVEX_FUNC_DI_64:
2871 static const ZyanU8 lookup[2][1] =
2873 { 64 },
2874 { 8 }
2876 ZYAN_ASSERT(index < 2);
2877 ZYAN_ASSERT(instruction->raw.mvex.SSS < ZYAN_ARRAY_LENGTH(lookup[index]));
2878 context->cd8_scale = lookup[index][instruction->raw.mvex.SSS];
2879 break;
2881 default:
2882 ZYAN_UNREACHABLE;
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
2896 break;
2897 case ZYDIS_MVEX_FUNC_RC:
2898 instruction->avx.rounding.mode = ZYDIS_ROUNDING_MODE_RN + (instruction->raw.mvex.SSS & 3);
2899 ZYAN_FALLTHROUGH;
2900 case ZYDIS_MVEX_FUNC_SAE:
2901 if (instruction->raw.mvex.SSS >= 4)
2903 instruction->avx.has_sae = ZYAN_TRUE;
2905 break;
2906 case ZYDIS_MVEX_FUNC_SWIZZLE_32:
2907 case ZYDIS_MVEX_FUNC_SWIZZLE_64:
2908 instruction->avx.swizzle.mode = ZYDIS_SWIZZLE_MODE_DCBA + instruction->raw.mvex.SSS;
2909 break;
2910 case ZYDIS_MVEX_FUNC_SF_32:
2911 case ZYDIS_MVEX_FUNC_SF_32_BCST:
2912 case ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16:
2913 switch (instruction->raw.mvex.SSS)
2915 case 0:
2916 break;
2917 case 1:
2918 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_16;
2919 break;
2920 case 2:
2921 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_16;
2922 break;
2923 case 3:
2924 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_FLOAT16;
2925 break;
2926 case 4:
2927 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT8;
2928 break;
2929 case 5:
2930 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT8;
2931 break;
2932 case 6:
2933 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT16;
2934 break;
2935 case 7:
2936 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT16;
2937 break;
2938 default:
2939 ZYAN_UNREACHABLE;
2941 break;
2942 case ZYDIS_MVEX_FUNC_SI_32:
2943 case ZYDIS_MVEX_FUNC_SI_32_BCST:
2944 case ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16:
2945 switch (instruction->raw.mvex.SSS)
2947 case 0:
2948 break;
2949 case 1:
2950 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_16;
2951 break;
2952 case 2:
2953 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_16;
2954 break;
2955 case 4:
2956 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT8;
2957 break;
2958 case 5:
2959 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT8;
2960 break;
2961 case 6:
2962 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT16;
2963 break;
2964 case 7:
2965 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT16;
2966 break;
2967 default:
2968 ZYAN_UNREACHABLE;
2970 break;
2971 case ZYDIS_MVEX_FUNC_SF_64:
2972 case ZYDIS_MVEX_FUNC_SI_64:
2973 switch (instruction->raw.mvex.SSS)
2975 case 0:
2976 break;
2977 case 1:
2978 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_8;
2979 break;
2980 case 2:
2981 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_8;
2982 break;
2983 default:
2984 ZYAN_UNREACHABLE;
2986 break;
2987 case ZYDIS_MVEX_FUNC_UF_32:
2988 case ZYDIS_MVEX_FUNC_DF_32:
2989 switch (instruction->raw.mvex.SSS)
2991 case 0:
2992 break;
2993 case 3:
2994 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_FLOAT16;
2995 break;
2996 case 4:
2997 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT8;
2998 break;
2999 case 5:
3000 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT8;
3001 break;
3002 case 6:
3003 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT16;
3004 break;
3005 case 7:
3006 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT16;
3007 break;
3008 default:
3009 ZYAN_UNREACHABLE;
3011 break;
3012 case ZYDIS_MVEX_FUNC_UF_64:
3013 case ZYDIS_MVEX_FUNC_DF_64:
3014 break;
3015 case ZYDIS_MVEX_FUNC_UI_32:
3016 case ZYDIS_MVEX_FUNC_DI_32:
3017 switch (instruction->raw.mvex.SSS)
3019 case 0:
3020 break;
3021 case 4:
3022 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT8;
3023 break;
3024 case 5:
3025 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT8;
3026 break;
3027 case 6:
3028 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT16;
3029 break;
3030 case 7:
3031 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT16;
3032 break;
3033 default:
3034 ZYAN_UNREACHABLE;
3036 break;
3037 case ZYDIS_MVEX_FUNC_UI_64:
3038 case ZYDIS_MVEX_FUNC_DI_64:
3039 break;
3040 default:
3041 ZYAN_UNREACHABLE;
3044 // Eviction hint
3045 if ((instruction->raw.modrm.mod != 3) && instruction->raw.mvex.E)
3047 instruction->avx.has_eviction_hint = ZYAN_TRUE;
3050 // Mask
3051 instruction->avx.mask.mode = ZYDIS_MASK_MODE_MERGING;
3052 instruction->avx.mask.reg = ZYDIS_REGISTER_K0 + instruction->raw.mvex.kkk;
3053 #else
3054 ZYAN_UNREACHABLE;
3055 #endif
3056 break;
3058 default:
3059 // Nothing to do here
3060 break;
3063 #endif
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)
3083 ZYAN_ASSERT(state);
3084 ZYAN_ASSERT(instruction);
3085 ZYAN_ASSERT(instruction->raw.prefix_count == 0);
3087 ZyanU8 rex = 0x00;
3088 ZyanU8 offset = 0;
3089 ZyanBool done = ZYAN_FALSE;
3092 ZyanU8 prefix_byte;
3093 ZYAN_CHECK(ZydisInputPeek(state, instruction, &prefix_byte));
3094 switch (prefix_byte)
3096 case 0xF0:
3097 state->prefixes.has_lock = ZYAN_TRUE;
3098 state->prefixes.offset_lock = offset;
3099 break;
3100 case 0xF2:
3101 ZYAN_FALLTHROUGH;
3102 case 0xF3:
3103 state->prefixes.group1 = prefix_byte;
3104 state->prefixes.mandatory_candidate = prefix_byte;
3105 state->prefixes.offset_group1 = offset;
3106 state->prefixes.offset_mandatory = offset;
3107 break;
3108 case 0x2E:
3109 ZYAN_FALLTHROUGH;
3110 case 0x36:
3111 ZYAN_FALLTHROUGH;
3112 case 0x3E:
3113 ZYAN_FALLTHROUGH;
3114 case 0x26:
3115 if (state->decoder->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
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;
3125 break;
3127 ZYAN_FALLTHROUGH;
3128 case 0x64:
3129 ZYAN_FALLTHROUGH;
3130 case 0x65:
3131 state->prefixes.group2 = prefix_byte;
3132 state->prefixes.offset_group2 = offset;
3133 state->prefixes.effective_segment = prefix_byte;
3134 state->prefixes.offset_segment = offset;
3135 state->prefixes.offset_notrack = -1;
3136 break;
3137 case 0x66:
3138 // context->prefixes.has_osz_override = ZYAN_TRUE;
3139 state->prefixes.offset_osz_override = offset;
3140 if (!state->prefixes.mandatory_candidate)
3142 state->prefixes.mandatory_candidate = 0x66;
3143 state->prefixes.offset_mandatory = offset;
3145 instruction->attributes |= ZYDIS_ATTRIB_HAS_OPERANDSIZE;
3146 break;
3147 case 0x67:
3148 // context->prefixes.has_asz_override = ZYAN_TRUE;
3149 state->prefixes.offset_asz_override = offset;
3150 instruction->attributes |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
3151 break;
3152 default:
3153 if ((state->decoder->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) &&
3154 (prefix_byte & 0xF0) == 0x40)
3156 rex = prefix_byte;
3157 instruction->raw.rex.offset = offset;
3158 } else
3160 done = ZYAN_TRUE;
3162 break;
3164 if (!done)
3166 // Invalidate `REX`, if it's not the last legacy prefix
3167 if (rex && (rex != prefix_byte))
3169 rex = 0x00;
3170 instruction->raw.rex.offset = 0;
3172 instruction->raw.prefixes[instruction->raw.prefix_count++].value = prefix_byte;
3173 ZydisInputSkip(state, instruction);
3174 ++offset;
3176 } while (!done);
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;
3188 if (rex)
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)
3215 ZYAN_ASSERT(state);
3216 ZYAN_ASSERT(instruction);
3217 ZYAN_ASSERT(info);
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;
3226 ZyanU8 modrm_byte;
3227 ZYAN_CHECK(ZydisInputNext(state, instruction, &modrm_byte));
3228 ZydisDecodeModRM(instruction, modrm_byte);
3231 if (!(info->flags & ZYDIS_INSTR_ENC_FLAG_FORCE_REG_FORM))
3233 ZyanU8 has_sib = 0;
3234 ZyanU8 displacement_size = 0;
3235 switch (instruction->address_width)
3237 case 16:
3238 switch (instruction->raw.modrm.mod)
3240 case 0:
3241 if (instruction->raw.modrm.rm == 6)
3243 displacement_size = 16;
3245 break;
3246 case 1:
3247 displacement_size = 8;
3248 break;
3249 case 2:
3250 displacement_size = 16;
3251 break;
3252 case 3:
3253 break;
3254 default:
3255 ZYAN_UNREACHABLE;
3257 break;
3258 case 32:
3259 case 64:
3260 has_sib =
3261 (instruction->raw.modrm.mod != 3) && (instruction->raw.modrm.rm == 4);
3262 switch (instruction->raw.modrm.mod)
3264 case 0:
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;
3273 break;
3274 case 1:
3275 displacement_size = 8;
3276 break;
3277 case 2:
3278 displacement_size = 32;
3279 break;
3280 case 3:
3281 break;
3282 default:
3283 ZYAN_UNREACHABLE;
3285 break;
3286 default:
3287 ZYAN_UNREACHABLE;
3289 if (has_sib)
3291 instruction->raw.sib.offset = instruction->length;
3292 ZyanU8 sib_byte;
3293 ZYAN_CHECK(ZydisInputNext(state, instruction, &sib_byte));
3294 ZydisDecodeSIB(instruction, sib_byte);
3295 if (instruction->raw.sib.base == 5)
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
3358 16, // 16 __ W0
3359 32, // 16 66 W0
3360 32, // 32 __ W0
3361 16, // 32 66 W0
3362 32, // 64 __ W0
3363 16, // 64 66 W0
3364 64, // 64 __ W1
3365 64 // 64 66 W1
3367 // Operand size is forced to 8-bit (this is done later to preserve the `eosz_index`)
3369 16, // 16 __ W0
3370 32, // 16 66 W0
3371 32, // 32 __ W0
3372 16, // 32 66 W0
3373 32, // 64 __ W0
3374 16, // 64 66 W0
3375 64, // 64 __ W1
3376 64 // 64 66 W1
3378 // Operand size override 0x66 is ignored
3380 16, // 16 __ W0
3381 16, // 16 66 W0
3382 32, // 32 __ W0
3383 32, // 32 66 W0
3384 32, // 64 __ W0
3385 32, // 64 66 W0
3386 64, // 64 __ W1
3387 64 // 64 66 W1
3389 // REX.W promotes to 32-bit instead of 64-bit
3391 16, // 16 __ W0
3392 32, // 16 66 W0
3393 32, // 32 __ W0
3394 16, // 32 66 W0
3395 32, // 64 __ W0
3396 16, // 64 66 W0
3397 32, // 64 __ W1
3398 32 // 64 66 W1
3400 // Operand size defaults to 64-bit in 64-bit mode
3402 16, // 16 __ W0
3403 32, // 16 66 W0
3404 32, // 32 __ W0
3405 16, // 32 66 W0
3406 64, // 64 __ W0
3407 16, // 64 66 W0
3408 64, // 64 __ W1
3409 64 // 64 66 W1
3411 // Operand size is forced to 64-bit in 64-bit mode
3413 16, // 16 __ W0
3414 32, // 16 66 W0
3415 32, // 32 __ W0
3416 16, // 32 66 W0
3417 64, // 64 __ W0
3418 64, // 64 66 W0
3419 64, // 64 __ W1
3420 64 // 64 66 W1
3422 // Operand size is forced to 32-bit, if no REX.W is present.
3424 32, // 16 __ W0
3425 32, // 16 66 W0
3426 32, // 32 __ W0
3427 32, // 32 66 W0
3428 32, // 64 __ W0
3429 32, // 64 66 W0
3430 64, // 64 __ W1
3431 64 // 64 66 W1
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`.
3436 32, // 16 __ W0
3437 32, // 16 66 W0
3438 32, // 32 __ W0
3439 32, // 32 66 W0
3440 64, // 64 __ W0
3441 64, // 64 66 W0
3442 64, // 64 __ W1
3443 64 // 64 66 W1
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))
3451 index += 2;
3453 else if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
3455 index += 4;
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
3489 16, // 16 __
3490 32, // 16 67
3491 32, // 32 __
3492 16, // 32 67
3493 64, // 64 __
3494 32 // 64 67
3496 // The address-size override is ignored
3498 16, // 16 __
3499 16, // 16 67
3500 32, // 32 __
3501 32, // 32 67
3502 64, // 64 __
3503 64 // 64 67
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`.
3508 32, // 16 __
3509 32, // 16 67
3510 32, // 32 __
3511 32, // 32 67
3512 64, // 64 __
3513 64 // 64 67
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))
3521 index += 2;
3523 else if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
3525 index += 4;
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);
3540 ZYAN_ASSERT(index);
3542 switch (instruction->encoding)
3544 case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
3545 *index = 0;
3546 break;
3547 case ZYDIS_INSTRUCTION_ENCODING_XOP:
3548 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_XOP);
3549 *index = (instruction->raw.xop.m_mmmm - 0x08) + (instruction->raw.xop.pp * 3) + 1;
3550 break;
3551 default:
3552 ZYAN_UNREACHABLE;
3554 return ZYAN_STATUS_SUCCESS;
3557 static ZyanStatus ZydisNodeHandlerVEX(const ZydisDecodedInstruction* instruction, ZyanU16* index)
3559 ZYAN_ASSERT(instruction);
3560 ZYAN_ASSERT(index);
3562 switch (instruction->encoding)
3564 case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
3565 *index = 0;
3566 break;
3567 case ZYDIS_INSTRUCTION_ENCODING_VEX:
3568 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX);
3569 *index = instruction->raw.vex.m_mmmm + (instruction->raw.vex.pp << 2) + 1;
3570 break;
3571 default:
3572 ZYAN_UNREACHABLE;
3574 return ZYAN_STATUS_SUCCESS;
3577 static ZyanStatus ZydisNodeHandlerEMVEX(const ZydisDecodedInstruction* instruction, ZyanU16* index)
3579 ZYAN_ASSERT(instruction);
3580 ZYAN_ASSERT(index);
3582 switch (instruction->encoding)
3584 case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
3585 *index = 0;
3586 break;
3587 case ZYDIS_INSTRUCTION_ENCODING_EVEX:
3588 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX);
3589 *index = instruction->raw.evex.mmm + (instruction->raw.evex.pp << 3) + 1;
3590 break;
3591 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
3592 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX);
3593 *index = instruction->raw.mvex.mmmm + (instruction->raw.mvex.pp << 2) + 33;
3594 break;
3595 default:
3596 ZYAN_UNREACHABLE;
3598 return ZYAN_STATUS_SUCCESS;
3601 static ZyanStatus ZydisNodeHandlerOpcode(ZydisDecoderState* state,
3602 ZydisDecodedInstruction* instruction, ZyanU16* index)
3604 ZYAN_ASSERT(state);
3605 ZYAN_ASSERT(instruction);
3606 ZYAN_ASSERT(index);
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)
3618 case 0x0F:
3619 instruction->opcode_map = ZYDIS_OPCODE_MAP_0F;
3620 break;
3621 case 0xC4:
3622 case 0xC5:
3623 case 0x62:
3625 ZyanU8 next_input;
3626 ZYAN_CHECK(ZydisInputPeek(state, instruction, &next_input));
3627 if (((next_input & 0xF0) >= 0xC0) ||
3628 (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64))
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)
3646 case 0xC4:
3647 instruction->raw.vex.offset = instruction->length - 1;
3648 // Read additional 3-byte VEX-prefix data
3649 ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX));
3650 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, &prefix_bytes[1], 2));
3651 break;
3652 case 0xC5:
3653 instruction->raw.vex.offset = instruction->length - 1;
3654 // Read additional 2-byte VEX-prefix data
3655 ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX));
3656 ZYAN_CHECK(ZydisInputNext(state, instruction, &prefix_bytes[1]));
3657 break;
3658 case 0x62:
3659 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
3660 // Read additional EVEX/MVEX-prefix data
3661 ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX));
3662 ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX));
3663 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, &prefix_bytes[1], 3));
3664 break;
3665 #else
3666 return ZYDIS_STATUS_DECODING_ERROR;
3667 #endif
3668 default:
3669 ZYAN_UNREACHABLE;
3671 switch (instruction->opcode)
3673 case 0xC4:
3674 case 0xC5:
3675 // Decode VEX-prefix
3676 instruction->encoding = ZYDIS_INSTRUCTION_ENCODING_VEX;
3677 ZYAN_CHECK(ZydisDecodeVEX(state->context, instruction, prefix_bytes));
3678 instruction->opcode_map =
3679 ZYDIS_OPCODE_MAP_DEFAULT + instruction->raw.vex.m_mmmm;
3680 break;
3681 case 0x62:
3682 #if defined(ZYDIS_DISABLE_AVX512) && defined(ZYDIS_DISABLE_KNC)
3683 return ZYDIS_STATUS_DECODING_ERROR;
3684 #else
3685 switch ((prefix_bytes[2] >> 2) & 0x01)
3687 case 0:
3688 #ifndef ZYDIS_DISABLE_KNC
3689 instruction->raw.mvex.offset = instruction->length - 4;
3690 // `KNC` instructions are only valid in 64-bit mode.
3691 // This condition catches the `MVEX` encoded ones to save a bunch of
3692 // `mode` filters in the data-tables.
3693 // `KNC` instructions with `VEX` encoding still require a `mode` filter.
3694 if (state->decoder->machine_mode != ZYDIS_MACHINE_MODE_LONG_64)
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;
3703 break;
3704 #else
3705 return ZYDIS_STATUS_DECODING_ERROR;
3706 #endif
3707 case 1:
3708 #ifndef ZYDIS_DISABLE_AVX512
3709 instruction->raw.evex.offset = instruction->length - 4;
3710 // Decode EVEX-prefix
3711 instruction->encoding = ZYDIS_INSTRUCTION_ENCODING_EVEX;
3712 ZYAN_CHECK(ZydisDecodeEVEX(state->context, instruction, prefix_bytes));
3713 instruction->opcode_map =
3714 ZYDIS_OPCODE_MAP_DEFAULT + instruction->raw.evex.mmm;
3715 break;
3716 #else
3717 return ZYDIS_STATUS_DECODING_ERROR;
3718 #endif
3719 default:
3720 ZYAN_UNREACHABLE;
3722 break;
3723 #endif
3724 default:
3725 ZYAN_UNREACHABLE;
3728 break;
3730 case 0x8F:
3732 ZyanU8 next_input;
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;
3758 break;
3760 default:
3761 break;
3763 break;
3764 case ZYDIS_OPCODE_MAP_0F:
3765 switch (instruction->opcode)
3767 case 0x0F:
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;
3774 break;
3775 case 0x38:
3776 instruction->opcode_map = ZYDIS_OPCODE_MAP_0F38;
3777 break;
3778 case 0x3A:
3779 instruction->opcode_map = ZYDIS_OPCODE_MAP_0F3A;
3780 break;
3781 default:
3782 break;
3784 break;
3785 case ZYDIS_OPCODE_MAP_0F38:
3786 case ZYDIS_OPCODE_MAP_0F3A:
3787 case ZYDIS_OPCODE_MAP_XOP8:
3788 case ZYDIS_OPCODE_MAP_XOP9:
3789 case ZYDIS_OPCODE_MAP_XOPA:
3790 // Nothing to do here
3791 break;
3792 default:
3793 ZYAN_UNREACHABLE;
3795 break;
3796 case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
3797 // All 3DNOW (0x0F 0x0F) instructions are using the same operand encoding. We just
3798 // decode a random (pi2fw) instruction and extract the actual opcode later.
3799 *index = 0x0C;
3800 return ZYAN_STATUS_SUCCESS;
3801 default:
3802 ZYAN_CHECK(ZydisInputNext(state, instruction, &instruction->opcode));
3803 break;
3806 *index = instruction->opcode;
3807 return ZYAN_STATUS_SUCCESS;
3810 static ZyanStatus ZydisNodeHandlerMode(const ZydisDecodedInstruction* instruction, ZyanU16* index)
3812 ZYAN_ASSERT(instruction);
3813 ZYAN_ASSERT(index);
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:
3820 *index = 0;
3821 break;
3822 case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
3823 case ZYDIS_MACHINE_MODE_LEGACY_32:
3824 *index = 1;
3825 break;
3826 case ZYDIS_MACHINE_MODE_LONG_64:
3827 *index = 2;
3828 break;
3829 default:
3830 ZYAN_UNREACHABLE;
3832 return ZYAN_STATUS_SUCCESS;
3835 static ZyanStatus ZydisNodeHandlerModeCompact(const ZydisDecodedInstruction* instruction,
3836 ZyanU16* index)
3838 ZYAN_ASSERT(instruction);
3839 ZYAN_ASSERT(index);
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)
3848 ZYAN_ASSERT(state);
3849 ZYAN_ASSERT(instruction);
3850 ZYAN_ASSERT(index);
3852 if (!instruction->raw.modrm.offset)
3854 instruction->raw.modrm.offset = instruction->length;
3855 ZyanU8 modrm_byte;
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)
3874 ZYAN_ASSERT(state);
3875 ZYAN_ASSERT(instruction);
3876 ZYAN_ASSERT(index);
3878 if (!instruction->raw.modrm.offset)
3880 instruction->raw.modrm.offset = instruction->length;
3881 ZyanU8 modrm_byte;
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)
3892 ZYAN_ASSERT(state);
3893 ZYAN_ASSERT(instruction);
3894 ZYAN_ASSERT(index);
3896 if (!instruction->raw.modrm.offset)
3898 instruction->raw.modrm.offset = instruction->length;
3899 ZyanU8 modrm_byte;
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)
3910 ZYAN_ASSERT(state);
3911 ZYAN_ASSERT(instruction);
3912 ZYAN_ASSERT(index);
3914 switch (state->prefixes.mandatory_candidate)
3916 case 0x66:
3917 instruction->raw.prefixes[state->prefixes.offset_mandatory].type =
3918 ZYDIS_PREFIX_TYPE_MANDATORY;
3919 instruction->attributes &= ~ZYDIS_ATTRIB_HAS_OPERANDSIZE;
3920 *index = 2;
3921 break;
3922 case 0xF3:
3923 instruction->raw.prefixes[state->prefixes.offset_mandatory].type =
3924 ZYDIS_PREFIX_TYPE_MANDATORY;
3925 *index = 3;
3926 break;
3927 case 0xF2:
3928 instruction->raw.prefixes[state->prefixes.offset_mandatory].type =
3929 ZYDIS_PREFIX_TYPE_MANDATORY;
3930 *index = 4;
3931 break;
3932 default:
3933 *index = 1;
3934 break;
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)
3944 ZYAN_ASSERT(state);
3945 ZYAN_ASSERT(instruction);
3946 ZYAN_ASSERT(index);
3948 if ((instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) &&
3949 (state->context->vector_unified.W))
3951 *index = 2;
3952 } else
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;
3965 break;
3966 case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
3967 case ZYDIS_MACHINE_MODE_LEGACY_32:
3968 case ZYDIS_MACHINE_MODE_LONG_64:
3969 *index = (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE) ? 0 : 1;
3970 break;
3971 default:
3972 ZYAN_UNREACHABLE;
3976 return ZYAN_STATUS_SUCCESS;
3979 static ZyanStatus ZydisNodeHandlerAddressSize(ZydisDecodedInstruction* instruction, ZyanU16* index)
3981 ZYAN_ASSERT(instruction);
3982 ZYAN_ASSERT(index);
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;
3995 break;
3996 case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
3997 case ZYDIS_MACHINE_MODE_LEGACY_32:
3998 *index = (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE) ? 0 : 1;
3999 break;
4000 case ZYDIS_MACHINE_MODE_LONG_64:
4001 *index = (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE) ? 1 : 2;
4002 break;
4003 default:
4004 ZYAN_UNREACHABLE;
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);
4015 ZYAN_ASSERT(index);
4017 switch (instruction->encoding)
4019 case ZYDIS_INSTRUCTION_ENCODING_XOP:
4020 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_XOP);
4021 break;
4022 case ZYDIS_INSTRUCTION_ENCODING_VEX:
4023 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX);
4024 break;
4025 case ZYDIS_INSTRUCTION_ENCODING_EVEX:
4026 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX);
4027 break;
4028 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
4029 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX);
4030 break;
4031 default:
4032 ZYAN_UNREACHABLE;
4035 *index = context->vector_unified.LL;
4036 if (*index == 3)
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);
4048 ZYAN_ASSERT(index);
4050 switch (instruction->encoding)
4052 case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
4053 // nothing to do here
4054 break;
4055 case ZYDIS_INSTRUCTION_ENCODING_XOP:
4056 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_XOP);
4057 break;
4058 case ZYDIS_INSTRUCTION_ENCODING_VEX:
4059 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX);
4060 break;
4061 case ZYDIS_INSTRUCTION_ENCODING_EVEX:
4062 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX);
4063 break;
4064 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
4065 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX);
4066 break;
4067 default:
4068 ZYAN_UNREACHABLE;
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);
4079 ZYAN_ASSERT(index);
4081 switch (instruction->encoding)
4083 case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
4084 // nothing to do here
4085 break;
4086 case ZYDIS_INSTRUCTION_ENCODING_XOP:
4087 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_XOP);
4088 break;
4089 case ZYDIS_INSTRUCTION_ENCODING_VEX:
4090 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX);
4091 break;
4092 case ZYDIS_INSTRUCTION_ENCODING_EVEX:
4093 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX);
4094 break;
4095 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
4096 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX);
4097 break;
4098 default:
4099 ZYAN_UNREACHABLE;
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);
4109 ZYAN_ASSERT(index);
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;
4116 #endif
4118 #ifndef ZYDIS_DISABLE_KNC
4119 static ZyanStatus ZydisNodeHandlerMvexE(const ZydisDecodedInstruction* instruction, ZyanU16* index)
4121 ZYAN_ASSERT(instruction);
4122 ZYAN_ASSERT(index);
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;
4129 #endif
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] =
4191 /* INVALID */ 0,
4192 /* GPR */ (1 << 5) - 1,
4193 /* X87 */ (1 << 3) - 1, // ignore `.R`, ignore `.R'`
4194 /* MMX */ (1 << 3) - 1, // ignore `.R`, ignore `.R'`
4195 /* VR */ (1 << 5) - 1,
4196 /* TMM */ (1 << 5) - 1,
4197 /* SEGMENT */ (1 << 3) - 1, // ignore `.R`, ignore `.R'`
4198 /* TEST */ (1 << 3) - 1, // ignore `.R`, ignore `.R'`
4199 /* CONTROL */ (1 << 4) - 1, // ignore `.R'`
4200 /* DEBUG */ (1 << 4) - 1, // ignore `.R'`
4201 /* MASK */ (1 << 5) - 1,
4202 /* BOUND */ (1 << 4) - 1 // ignore `.R'`
4204 id_reg &= mask_reg[def_reg];
4206 static const ZyanU8 mask_rm[ZYDIS_REGKIND_MAX_VALUE + 1] =
4208 /* INVALID */ 0,
4209 /* GPR */ (1 << 4) - 1, // ignore `.X`
4210 /* X87 */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
4211 /* MMX */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
4212 /* VR */ (1 << 5) - 1,
4213 /* TMM */ (1 << 4) - 1, // ignore `.X`
4214 /* SEGMENT */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
4215 /* TEST */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
4216 /* CONTROL */ (1 << 4) - 1, // ignore `.X`
4217 /* DEBUG */ (1 << 4) - 1, // ignore `.X`
4218 /* MASK */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
4219 /* BOUND */ (1 << 4) - 1 // ignore `.X`
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] =
4228 // /* INVALID */ 0,
4229 // /* GPR */ (1 << 5) - 1,
4230 // /* X87 */ 0, // never encoded in `.vvvv`
4231 // /* MMX */ 0, // never encoded in `.vvvv`
4232 // /* VR */ (1 << 5) - 1,
4233 // /* TMM */ (1 << 5) - 1,
4234 // /* SEGMENT */ 0, // never encoded in `.vvvv`
4235 // /* TEST */ 0, // never encoded in `.vvvv`
4236 // /* CONTROL */ 0, // never encoded in `.vvvv`
4237 // /* DEBUG */ 0, // never encoded in `.vvvv`
4238 // /* MASK */ (1 << 5) - 1,
4239 // /* BOUND */ 0 // never encoded in `.vvvv`
4240 //};
4243 // Validate
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] =
4258 // 16/32 bit mode
4260 /* INVALID */ 255,
4261 /* GPR */ 8,
4262 /* X87 */ 8,
4263 /* MMX */ 8,
4264 /* VR */ 8,
4265 /* TMM */ 8,
4266 /* SEGMENT */ 6,
4267 /* TEST */ 8,
4268 /* CONTROL */ 8,
4269 /* DEBUG */ 8,
4270 /* MASK */ 8,
4271 /* BOUND */ 4
4273 // 64 bit mode
4275 /* INVALID */ 255,
4276 /* GPR */ 16,
4277 /* X87 */ 8,
4278 /* MMX */ 8,
4279 /* VR */ 32,
4280 /* TMM */ 8,
4281 /* SEGMENT */ 6,
4282 /* TEST */ 8,
4283 /* CONTROL */ 16,
4284 // Attempts to reference DR8..DR15 result in undefined opcode (#UD) exceptions. DR4 and
4285 // DR5 are only valid, if the debug extension (DE) flag in CR4 is set. As we can't
4286 // check this at runtime we just allow them.
4287 /* DEBUG */ 8,
4288 /* MASK */ 8,
4289 /* BOUND */ 4
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;
4300 ZyanI8 id_cr = -1;
4301 if (def_reg == ZYDIS_REGKIND_CONTROL)
4303 id_cr = id_reg;
4305 if (is_reg && (def_rm == ZYDIS_REGKIND_CONTROL))
4307 id_cr = id_rm;
4309 if (id_cr >= 0)
4311 // Attempts to reference CR1, CR5, CR6, CR7, and CR9..CR15 result in undefined opcode (#UD)
4312 // exceptions
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));
4318 if (!lookup[id_cr])
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)
4349 ZYAN_ASSERT(state);
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;
4361 #endif
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;
4387 break;
4389 case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
4391 break;
4393 case ZYDIS_INSTRUCTION_ENCODING_XOP:
4395 const ZydisInstructionDefinitionXOP* def =
4396 (const ZydisInstructionDefinitionXOP*)definition;
4397 def_ndsndd = def->op_ndsndd;
4398 break;
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;
4407 break;
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
4424 #else
4425 ZYAN_UNREACHABLE;
4426 #endif
4427 break;
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;
4500 #else
4501 ZYAN_UNREACHABLE;
4502 #endif
4503 break;
4505 default:
4506 ZYAN_UNREACHABLE;
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;
4515 if (def_reg)
4517 is_sr_dest_reg = ZYDIS_OPDEF_GET_REG_HIGH_BIT(def_reg);
4518 def_reg = ZYDIS_OPDEF_GET_REG(def_reg);
4520 if (def_rm)
4522 if (is_reg)
4524 is_sr_dest_rm = ZYDIS_OPDEF_GET_REG_HIGH_BIT(def_rm);
4525 def_rm = ZYDIS_OPDEF_GET_REG(def_rm);
4527 else
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
4535 if (no_rip_rel)
4537 const ZyanBool is_rip_rel =
4538 (state->decoder->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) &&
4539 (instruction->raw.modrm.mod == 0) && (instruction->raw.modrm.rm == 5);
4540 if (is_rip_rel)
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
4560 if (is_gather)
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;
4568 ZyanU8 mask = 0xF0;
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
4587 // operand
4588 if (!def_reg)
4590 dest = 0xF1;
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
4619 // UD fault
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
4642 break;
4643 case ZYDIS_MASK_POLICY_REQUIRED:
4644 if (!context->vector_unified.mask)
4646 return ZYDIS_STATUS_INVALID_MASK;
4648 break;
4649 case ZYDIS_MASK_POLICY_FORBIDDEN:
4650 if (context->vector_unified.mask)
4652 return ZYDIS_STATUS_INVALID_MASK;
4654 break;
4655 default:
4656 ZYAN_UNREACHABLE;
4658 #endif
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)
4676 ZYAN_ASSERT(state);
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;
4686 ZyanU16 index = 0;
4687 ZyanStatus status = 0;
4688 switch (node_type)
4690 case ZYDIS_NODETYPE_INVALID:
4691 if (temp)
4693 node = temp;
4694 temp = ZYAN_NULL;
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;
4711 continue;
4713 return ZYDIS_STATUS_DECODING_ERROR;
4714 case ZYDIS_NODETYPE_FILTER_XOP:
4715 status = ZydisNodeHandlerXOP(instruction, &index);
4716 break;
4717 case ZYDIS_NODETYPE_FILTER_VEX:
4718 status = ZydisNodeHandlerVEX(instruction, &index);
4719 break;
4720 case ZYDIS_NODETYPE_FILTER_EMVEX:
4721 status = ZydisNodeHandlerEMVEX(instruction, &index);
4722 break;
4723 case ZYDIS_NODETYPE_FILTER_OPCODE:
4724 status = ZydisNodeHandlerOpcode(state, instruction, &index);
4725 break;
4726 case ZYDIS_NODETYPE_FILTER_MODE:
4727 status = ZydisNodeHandlerMode(instruction, &index);
4728 break;
4729 case ZYDIS_NODETYPE_FILTER_MODE_COMPACT:
4730 status = ZydisNodeHandlerModeCompact(instruction, &index);
4731 break;
4732 case ZYDIS_NODETYPE_FILTER_MODRM_MOD:
4733 status = ZydisNodeHandlerModrmMod(state, instruction, &index);
4734 break;
4735 case ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT:
4736 status = ZydisNodeHandlerModrmModCompact(state, instruction, &index);
4737 break;
4738 case ZYDIS_NODETYPE_FILTER_MODRM_REG:
4739 status = ZydisNodeHandlerModrmReg(state, instruction, &index);
4740 break;
4741 case ZYDIS_NODETYPE_FILTER_MODRM_RM:
4742 status = ZydisNodeHandlerModrmRm(state, instruction, &index);
4743 break;
4744 case ZYDIS_NODETYPE_FILTER_PREFIX_GROUP1:
4745 index = state->prefixes.group1 ? 1 : 0;
4746 break;
4747 case ZYDIS_NODETYPE_FILTER_MANDATORY_PREFIX:
4748 status = ZydisNodeHandlerMandatoryPrefix(state, instruction, &index);
4749 temp = ZydisDecoderTreeGetChildNode(node, 0);
4750 // TODO: Return to this point, if index == 0 contains a value and the previous path
4751 // TODO: was not successful
4752 // TODO: Restore consumed prefix
4753 break;
4754 case ZYDIS_NODETYPE_FILTER_OPERAND_SIZE:
4755 status = ZydisNodeHandlerOperandSize(state, instruction, &index);
4756 break;
4757 case ZYDIS_NODETYPE_FILTER_ADDRESS_SIZE:
4758 status = ZydisNodeHandlerAddressSize(instruction, &index);
4759 break;
4760 case ZYDIS_NODETYPE_FILTER_VECTOR_LENGTH:
4761 status = ZydisNodeHandlerVectorLength(state->context, instruction, &index);
4762 break;
4763 case ZYDIS_NODETYPE_FILTER_REX_W:
4764 status = ZydisNodeHandlerRexW(state->context, instruction, &index);
4765 break;
4766 case ZYDIS_NODETYPE_FILTER_REX_B:
4767 status = ZydisNodeHandlerRexB(state->context, instruction, &index);
4768 break;
4769 #ifndef ZYDIS_DISABLE_AVX512
4770 case ZYDIS_NODETYPE_FILTER_EVEX_B:
4771 status = ZydisNodeHandlerEvexB(instruction, &index);
4772 break;
4773 #endif
4774 #ifndef ZYDIS_DISABLE_KNC
4775 case ZYDIS_NODETYPE_FILTER_MVEX_E:
4776 status = ZydisNodeHandlerMvexE(instruction, &index);
4777 break;
4778 #endif
4779 case ZYDIS_NODETYPE_FILTER_MODE_AMD:
4780 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_AMD_BRANCHES));
4781 break;
4782 case ZYDIS_NODETYPE_FILTER_MODE_KNC:
4783 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_KNC));
4784 break;
4785 case ZYDIS_NODETYPE_FILTER_MODE_MPX:
4786 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_MPX));
4787 break;
4788 case ZYDIS_NODETYPE_FILTER_MODE_CET:
4789 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_CET));
4790 break;
4791 case ZYDIS_NODETYPE_FILTER_MODE_LZCNT:
4792 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_LZCNT));
4793 break;
4794 case ZYDIS_NODETYPE_FILTER_MODE_TZCNT:
4795 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_TZCNT));
4796 break;
4797 case ZYDIS_NODETYPE_FILTER_MODE_WBNOINVD:
4798 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_WBNOINVD));
4799 break;
4800 case ZYDIS_NODETYPE_FILTER_MODE_CLDEMOTE:
4801 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_CLDEMOTE));
4802 break;
4803 case ZYDIS_NODETYPE_FILTER_MODE_IPREFETCH:
4804 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_IPREFETCH));
4805 break;
4806 case ZYDIS_NODETYPE_FILTER_MODE_UD0_COMPAT:
4807 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_UD0_COMPAT));
4808 break;
4809 default:
4810 if (node_type & ZYDIS_NODETYPE_DEFINITION_MASK)
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);
4870 break;
4871 default:
4872 break;
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;
4884 #endif
4886 return ZYAN_STATUS_SUCCESS;
4888 ZYAN_UNREACHABLE;
4890 ZYAN_CHECK(status);
4891 node = ZydisDecoderTreeGetChildNode(node, index);
4892 } while ((node_type != ZYDIS_NODETYPE_INVALID) && !(node_type & ZYDIS_NODETYPE_DEFINITION_MASK));
4893 return ZYAN_STATUS_SUCCESS;
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) |
4910 #endif
4911 (1 << ZYDIS_DECODER_MODE_MPX) |
4912 (1 << ZYDIS_DECODER_MODE_CET) |
4913 (1 << ZYDIS_DECODER_MODE_LZCNT) |
4914 (1 << ZYDIS_DECODER_MODE_TZCNT) |
4915 (1 << ZYDIS_DECODER_MODE_CLDEMOTE) |
4916 (1 << ZYDIS_DECODER_MODE_IPREFETCH);
4918 if (!decoder)
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;
4929 break;
4930 case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
4931 case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
4932 case ZYDIS_MACHINE_MODE_LEGACY_32:
4933 case ZYDIS_MACHINE_MODE_LEGACY_16:
4934 case ZYDIS_MACHINE_MODE_REAL_16:
4935 if ((stack_width != ZYDIS_STACK_WIDTH_16) && (stack_width != ZYDIS_STACK_WIDTH_32))
4937 return ZYAN_STATUS_INVALID_ARGUMENT;
4939 break;
4940 default:
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;
4963 #endif
4965 if (enabled)
4967 decoder->decoder_mode |= (1 << mode);
4969 else
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;
4985 if (!length)
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;
5012 if (!length)
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;
5025 if (!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
5059 #else
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);
5073 if (!operand_count)
5075 return ZYAN_STATUS_SUCCESS;
5078 return ZydisDecodeOperands(decoder, context, instruction, operands, operand_count);
5080 #endif
5083 /* ============================================================================================== */