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