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