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