Encoder.c (158075B)
1 /*************************************************************************************************** 2 3 Zyan Disassembler Library (Zydis) 4 5 Original Author : Mappa 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 CppClangTidyClangDiagnosticSwitchEnum 28 // ReSharper disable CppClangTidyClangDiagnosticCoveredSwitchDefault 29 // ReSharper disable CppClangTidyClangDiagnosticImplicitFallthrough 30 31 #include "zydis/Zycore/LibC.h" 32 #include "zydis/Zydis/Encoder.h" 33 #include "zydis/Zydis/Utils.h" 34 #include "zydis/Zydis/Internal/EncoderData.h" 35 #include "zydis/Zydis/Internal/SharedData.h" 36 37 /* ============================================================================================== */ 38 /* Macros */ 39 /* ============================================================================================== */ 40 41 /* ---------------------------------------------------------------------------------------------- */ 42 /* Constants */ 43 /* ---------------------------------------------------------------------------------------------- */ 44 45 #define ZYDIS_OPSIZE_MAP_BYTEOP 1 46 #define ZYDIS_OPSIZE_MAP_DEFAULT64 4 47 #define ZYDIS_OPSIZE_MAP_FORCE64 5 48 #define ZYDIS_ADSIZE_MAP_IGNORED 1 49 #define ZYDIS_LEGACY_SEGMENTS (ZYDIS_ATTRIB_HAS_SEGMENT_CS | \ 50 ZYDIS_ATTRIB_HAS_SEGMENT_SS | \ 51 ZYDIS_ATTRIB_HAS_SEGMENT_DS | \ 52 ZYDIS_ATTRIB_HAS_SEGMENT_ES) 53 #define ZYDIS_ENCODABLE_PREFIXES_NO_SEGMENTS (ZYDIS_ENCODABLE_PREFIXES ^ \ 54 ZYDIS_ATTRIB_HAS_SEGMENT) 55 56 /* ---------------------------------------------------------------------------------------------- */ 57 58 /* ============================================================================================== */ 59 /* Internal enums and types */ 60 /* ============================================================================================== */ 61 62 /** 63 * Usage of `REX.W` prefix makes it impossible to use some byte-sized registers. Values of this 64 * enum are used to track and facilitate enforcement of these restrictions. 65 */ 66 typedef enum ZydisEncoderRexType_ 67 { 68 ZYDIS_REX_TYPE_UNKNOWN, 69 ZYDIS_REX_TYPE_REQUIRED, 70 ZYDIS_REX_TYPE_FORBIDDEN, 71 72 /** 73 * Maximum value of this enum. 74 */ 75 ZYDIS_REX_TYPE_MAX_VALUE = ZYDIS_REX_TYPE_FORBIDDEN, 76 /** 77 * The minimum number of bits required to represent all values of this enum. 78 */ 79 ZYDIS_REX_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REX_TYPE_MAX_VALUE) 80 } ZydisEncoderRexType; 81 82 /** 83 * Primary structure used during instruction matching phase. Once filled it contains information 84 * about matched instruction definition and some values deduced from encoder request. It gets 85 * converted to `ZydisEncoderInstruction` during instruction building phase. 86 */ 87 typedef struct ZydisEncoderInstructionMatch_ 88 { 89 /** 90 * A pointer to the `ZydisEncoderRequest` instance. 91 */ 92 const ZydisEncoderRequest *request; 93 /** 94 * A pointer to the `ZydisEncodableInstruction` instance. 95 */ 96 const ZydisEncodableInstruction *definition; 97 /** 98 * A pointer to the `ZydisInstructionDefinition` instance. 99 */ 100 const ZydisInstructionDefinition *base_definition; 101 /** 102 * A pointer to the `ZydisOperandDefinition` array. 103 */ 104 const ZydisOperandDefinition *operands; 105 /** 106 * Encodable attributes for this instruction. 107 */ 108 ZydisInstructionAttributes attributes; 109 /** 110 * Effective operand size attribute. 111 */ 112 ZyanU8 eosz; 113 /** 114 * Effective address size attribute. 115 */ 116 ZyanU8 easz; 117 /** 118 * Effective displacement size. 119 */ 120 ZyanU8 disp_size; 121 /** 122 * Effective immediate size. 123 */ 124 ZyanU8 imm_size; 125 /** 126 * Exponent of compressed displacement scale factor (2^cd8_scale) 127 */ 128 ZyanU8 cd8_scale; 129 /** 130 * `REX` prefix constraints. 131 */ 132 ZydisEncoderRexType rex_type; 133 /** 134 * True for special cases where operand size attribute must be lower than 64 bits. 135 */ 136 ZyanBool eosz64_forbidden; 137 /** 138 * True when instruction definition has relative operand (used for branching instructions). 139 */ 140 ZyanBool has_rel_operand; 141 } ZydisEncoderInstructionMatch; 142 143 /** 144 * Encapsulates information about writable buffer. 145 */ 146 typedef struct ZydisEncoderBuffer_ 147 { 148 /** 149 * A pointer to actual data buffer. 150 */ 151 ZyanU8 *buffer; 152 /** 153 * Size of this buffer. 154 */ 155 ZyanUSize size; 156 /** 157 * Current write offset. 158 */ 159 ZyanUSize offset; 160 } ZydisEncoderBuffer; 161 162 /** 163 * Low-level instruction representation. Once filled this structure contains all information 164 * required for final instruction emission phase. 165 */ 166 typedef struct ZydisEncoderInstruction_ 167 { 168 /** 169 * Encodable attributes for this instruction. 170 */ 171 ZydisInstructionAttributes attributes; 172 /** 173 * The instruction encoding. 174 */ 175 ZydisInstructionEncoding encoding; 176 /** 177 * The opcode map. 178 */ 179 ZydisOpcodeMap opcode_map; 180 /** 181 * The opcode. 182 */ 183 ZyanU8 opcode; 184 /** 185 * The `vvvv` field (`VEX`, `EVEX`, `MVEX`, `XOP`). 186 */ 187 ZyanU8 vvvv; 188 /** 189 * The `sss` field (`MVEX`). 190 */ 191 ZyanU8 sss; 192 /** 193 * The mask register ID. 194 */ 195 ZyanU8 mask; 196 /** 197 * The vector length. 198 */ 199 ZyanU8 vector_length; 200 /** 201 * The `mod` component of Mod/RM byte. 202 */ 203 ZyanU8 mod; 204 /** 205 * The `reg` component of Mod/RM byte. 206 */ 207 ZyanU8 reg; 208 /** 209 * The `rm` component of Mod/RM byte. 210 */ 211 ZyanU8 rm; 212 /** 213 * The scale component of SIB byte. 214 */ 215 ZyanU8 scale; 216 /** 217 * The index component of SIB byte. 218 */ 219 ZyanU8 index; 220 /** 221 * The base component of SIB byte. 222 */ 223 ZyanU8 base; 224 /** 225 * The `REX.W` bit. 226 */ 227 ZyanBool rex_w; 228 /** 229 * True if using zeroing mask (`EVEX`). 230 */ 231 ZyanBool zeroing; 232 /** 233 * True if using eviction hint (`MVEX`). 234 */ 235 ZyanBool eviction_hint; 236 /** 237 * Size of displacement value. 238 */ 239 ZyanU8 disp_size; 240 /** 241 * Size of immediate value. 242 */ 243 ZyanU8 imm_size; 244 /** 245 * The displacement value. 246 */ 247 ZyanU64 disp; 248 /** 249 * The immediate value. 250 */ 251 ZyanU64 imm; 252 } ZydisEncoderInstruction; 253 254 /* ============================================================================================== */ 255 /* Internal functions */ 256 /* ============================================================================================== */ 257 258 /** 259 * Converts `ZydisInstructionEncoding` to `ZydisEncodableEncoding`. 260 * 261 * @param encoding `ZydisInstructionEncoding` value to convert. 262 * 263 * @return Equivalent `ZydisEncodableEncoding` value. 264 */ 265 static ZydisEncodableEncoding ZydisGetEncodableEncoding(ZydisInstructionEncoding encoding) 266 { 267 static const ZydisEncodableEncoding encoding_lookup[6] = 268 { 269 ZYDIS_ENCODABLE_ENCODING_LEGACY, 270 ZYDIS_ENCODABLE_ENCODING_3DNOW, 271 ZYDIS_ENCODABLE_ENCODING_XOP, 272 ZYDIS_ENCODABLE_ENCODING_VEX, 273 ZYDIS_ENCODABLE_ENCODING_EVEX, 274 ZYDIS_ENCODABLE_ENCODING_MVEX, 275 }; 276 ZYAN_ASSERT((ZyanUSize)encoding <= ZYDIS_INSTRUCTION_ENCODING_MAX_VALUE); 277 return encoding_lookup[encoding]; 278 } 279 280 /** 281 * Converts `ZydisMachineMode` to default stack width value expressed in bits. 282 * 283 * @param machine_mode `ZydisMachineMode` value to convert. 284 * 285 * @return Stack width for requested machine mode. 286 */ 287 static ZyanU8 ZydisGetMachineModeWidth(ZydisMachineMode machine_mode) 288 { 289 ZYAN_ASSERT((ZyanUSize)machine_mode <= ZYDIS_MACHINE_MODE_MAX_VALUE); 290 static const ZyanU8 lookup[6] = 291 { 292 /* ZYDIS_MACHINE_MODE_LONG_64 */ 64, 293 /* ZYDIS_MACHINE_MODE_LONG_COMPAT_32 */ 32, 294 /* ZYDIS_MACHINE_MODE_LONG_COMPAT_16 */ 16, 295 /* ZYDIS_MACHINE_MODE_LEGACY_32 */ 32, 296 /* ZYDIS_MACHINE_MODE_LEGACY_16 */ 16, 297 /* ZYDIS_MACHINE_MODE_REAL_16 */ 16, 298 }; 299 return lookup[machine_mode]; 300 } 301 302 /** 303 * Converts `ZydisAddressSizeHint` to address size expressed in bits. 304 * 305 * @param hint Address size hint. 306 * 307 * @return Address size in bits. 308 */ 309 static ZyanU8 ZydisGetAszFromHint(ZydisAddressSizeHint hint) 310 { 311 ZYAN_ASSERT((ZyanUSize)hint <= ZYDIS_ADDRESS_SIZE_HINT_MAX_VALUE); 312 static const ZyanU8 lookup[ZYDIS_ADDRESS_SIZE_HINT_MAX_VALUE + 1] = { 0, 16, 32, 64 }; 313 return lookup[hint]; 314 } 315 316 /** 317 * Converts `ZydisOperandSizeHint` to operand size expressed in bits. 318 * 319 * @param hint Operand size hint. 320 * 321 * @return Operand size in bits. 322 */ 323 static ZyanU8 ZydisGetOszFromHint(ZydisOperandSizeHint hint) 324 { 325 ZYAN_ASSERT((ZyanUSize)hint <= ZYDIS_OPERAND_SIZE_HINT_MAX_VALUE); 326 static const ZyanU8 lookup[ZYDIS_OPERAND_SIZE_HINT_MAX_VALUE + 1] = { 0, 8, 16, 32, 64 }; 327 return lookup[hint]; 328 } 329 330 /** 331 * Calculates maximum size of absolute address value based on address size hint. 332 * 333 * @param request A pointer to `ZydisEncoderRequest` struct. 334 * 335 * @return Maximum address size in bits. 336 */ 337 static ZyanU8 ZydisGetMaxAddressSize(const ZydisEncoderRequest *request) 338 { 339 ZyanU8 addr_size = ZydisGetAszFromHint(request->address_size_hint); 340 if (addr_size == 0) 341 { 342 addr_size = ZydisGetMachineModeWidth(request->machine_mode); 343 } 344 return addr_size; 345 } 346 347 /** 348 * Calculates effective operand size. 349 * 350 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 351 * @param size_table Array of possible size values for different operand sizes. 352 * @param desired_size Operand size requested by caller. 353 * @param exact_match_mode True if desired_size must be matched exactly, false when 354 * "not lower than" matching is desired. 355 * 356 * @return Effective operand size in bits. 357 */ 358 static ZyanU8 ZydisGetOperandSizeFromElementSize(ZydisEncoderInstructionMatch *match, 359 const ZyanU16 *size_table, ZyanU16 desired_size, ZyanBool exact_match_mode) 360 { 361 if ((match->base_definition->operand_size_map == ZYDIS_OPSIZE_MAP_DEFAULT64) && 362 (match->request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)) 363 { 364 if ((exact_match_mode && (size_table[2] == desired_size)) || 365 (!exact_match_mode && (size_table[2] >= desired_size))) 366 { 367 return 64; 368 } 369 else if (size_table[0] == desired_size) 370 { 371 return 16; 372 } 373 } 374 else if ((match->base_definition->operand_size_map == ZYDIS_OPSIZE_MAP_FORCE64) && 375 (match->request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)) 376 { 377 if (size_table[2] == desired_size) 378 { 379 return 64; 380 } 381 } 382 else 383 { 384 static const ZyanI8 eosz_priority_lookup[4][3] = 385 { 386 { 0, 1, -1 }, 387 { 1, 0, -1 }, 388 { 1, 2, 0 }, 389 }; 390 const ZyanU8 eosz_index = ZydisGetMachineModeWidth(match->request->machine_mode) >> 5; 391 for (int i = 0; i < 3; ++i) 392 { 393 const ZyanI8 eosz_candidate = eosz_priority_lookup[eosz_index][i]; 394 if ((eosz_candidate == -1) || 395 !(match->definition->operand_sizes & (1 << eosz_candidate))) 396 { 397 continue; 398 } 399 if ((exact_match_mode && (size_table[eosz_candidate] == desired_size)) || 400 (!exact_match_mode && (size_table[eosz_candidate] >= desired_size))) 401 { 402 return 16 << eosz_candidate; 403 } 404 } 405 } 406 407 return 0; 408 } 409 410 /** 411 * Calculates effective immediate size. 412 * 413 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 414 * @param size_table Array of possible size values for different operand sizes. 415 * @param min_imm_size Minimum immediate size. 416 * 417 * @return Effective operand size in bits. 418 */ 419 static ZyanU8 ZydisGetScaledImmSize(ZydisEncoderInstructionMatch *match, const ZyanU16 *size_table, 420 ZyanU8 min_imm_size) 421 { 422 if (match->eosz == 0) 423 { 424 match->eosz = ZydisGetOperandSizeFromElementSize(match, size_table, min_imm_size, 425 ZYAN_FALSE); 426 return match->eosz != 0 ? (ZyanU8)size_table[match->eosz >> 5] : 0; 427 } 428 429 const ZyanU8 index = match->eosz >> 5; 430 return size_table[index] >= min_imm_size ? (ZyanU8)size_table[index] : 0; 431 } 432 433 /** 434 * Calculates size of smallest integral type able to represent provided signed value. 435 * 436 * @param imm Immediate to be represented. 437 * 438 * @return Size of smallest integral type able to represent provided signed value. 439 */ 440 static ZyanU8 ZydisGetSignedImmSize(ZyanI64 imm) 441 { 442 if (imm >= ZYAN_INT8_MIN && imm <= ZYAN_INT8_MAX) 443 { 444 return 8; 445 } 446 if (imm >= ZYAN_INT16_MIN && imm <= ZYAN_INT16_MAX) 447 { 448 return 16; 449 } 450 if (imm >= ZYAN_INT32_MIN && imm <= ZYAN_INT32_MAX) 451 { 452 return 32; 453 } 454 455 return 64; 456 } 457 458 /** 459 * Calculates size of smallest integral type able to represent provided unsigned value. 460 * 461 * @param imm Immediate to be represented. 462 * 463 * @return Size of smallest integral type able to represent provided unsigned value. 464 */ 465 static ZyanU8 ZydisGetUnsignedImmSize(ZyanU64 imm) 466 { 467 if (imm <= ZYAN_UINT8_MAX) 468 { 469 return 8; 470 } 471 if (imm <= ZYAN_UINT16_MAX) 472 { 473 return 16; 474 } 475 if (imm <= ZYAN_UINT32_MAX) 476 { 477 return 32; 478 } 479 480 return 64; 481 } 482 483 /** 484 * Checks if operand encoding encodes a signed immediate value. 485 * 486 * @param encoding Operand encoding for immediate value. 487 * 488 * @return True for encodings that represent signed values, false otherwise. 489 */ 490 static ZyanBool ZydisIsImmSigned(ZydisOperandEncoding encoding) 491 { 492 switch (encoding) 493 { 494 case ZYDIS_OPERAND_ENCODING_SIMM8: 495 case ZYDIS_OPERAND_ENCODING_SIMM16: 496 case ZYDIS_OPERAND_ENCODING_SIMM32: 497 case ZYDIS_OPERAND_ENCODING_SIMM64: 498 case ZYDIS_OPERAND_ENCODING_SIMM16_32_64: 499 case ZYDIS_OPERAND_ENCODING_SIMM32_32_64: 500 case ZYDIS_OPERAND_ENCODING_SIMM16_32_32: 501 case ZYDIS_OPERAND_ENCODING_JIMM8: 502 case ZYDIS_OPERAND_ENCODING_JIMM16: 503 case ZYDIS_OPERAND_ENCODING_JIMM32: 504 case ZYDIS_OPERAND_ENCODING_JIMM64: 505 case ZYDIS_OPERAND_ENCODING_JIMM16_32_64: 506 case ZYDIS_OPERAND_ENCODING_JIMM32_32_64: 507 case ZYDIS_OPERAND_ENCODING_JIMM16_32_32: 508 case ZYDIS_OPERAND_ENCODING_DISP8: 509 case ZYDIS_OPERAND_ENCODING_DISP16: 510 case ZYDIS_OPERAND_ENCODING_DISP32: 511 case ZYDIS_OPERAND_ENCODING_DISP64: 512 case ZYDIS_OPERAND_ENCODING_DISP16_32_64: 513 case ZYDIS_OPERAND_ENCODING_DISP32_32_64: 514 case ZYDIS_OPERAND_ENCODING_DISP16_32_32: 515 return ZYAN_TRUE; 516 case ZYDIS_OPERAND_ENCODING_UIMM8: 517 case ZYDIS_OPERAND_ENCODING_UIMM16: 518 case ZYDIS_OPERAND_ENCODING_UIMM32: 519 case ZYDIS_OPERAND_ENCODING_UIMM64: 520 case ZYDIS_OPERAND_ENCODING_UIMM16_32_64: 521 case ZYDIS_OPERAND_ENCODING_UIMM32_32_64: 522 case ZYDIS_OPERAND_ENCODING_UIMM16_32_32: 523 case ZYDIS_OPERAND_ENCODING_IS4: 524 return ZYAN_FALSE; 525 default: 526 ZYAN_UNREACHABLE; 527 } 528 } 529 530 /** 531 * Calculates effective immediate size. 532 * 533 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 534 * @param imm Immediate value to encode. 535 * @param def_op Operand definition for immediate operand. 536 * 537 * @return Effective operand size in bits (0 if function failed). 538 */ 539 static ZyanU8 ZydisGetEffectiveImmSize(ZydisEncoderInstructionMatch *match, ZyanI64 imm, 540 const ZydisOperandDefinition *def_op) 541 { 542 ZyanU8 eisz = 0; 543 ZyanU8 min_size = ZydisIsImmSigned((ZydisOperandEncoding)def_op->op.encoding) 544 ? ZydisGetSignedImmSize(imm) 545 : ZydisGetUnsignedImmSize((ZyanU64)imm); 546 547 switch (def_op->op.encoding) 548 { 549 case ZYDIS_OPERAND_ENCODING_UIMM8: 550 case ZYDIS_OPERAND_ENCODING_SIMM8: 551 eisz = 8; 552 break; 553 case ZYDIS_OPERAND_ENCODING_IS4: 554 ZYAN_ASSERT(def_op->element_type == ZYDIS_IELEMENT_TYPE_UINT8); 555 eisz = ((ZyanU64)imm <= 15) ? 8 : 0; 556 break; 557 case ZYDIS_OPERAND_ENCODING_UIMM16: 558 case ZYDIS_OPERAND_ENCODING_SIMM16: 559 eisz = 16; 560 break; 561 case ZYDIS_OPERAND_ENCODING_UIMM32: 562 case ZYDIS_OPERAND_ENCODING_SIMM32: 563 eisz = 32; 564 break; 565 case ZYDIS_OPERAND_ENCODING_UIMM64: 566 case ZYDIS_OPERAND_ENCODING_SIMM64: 567 eisz = 64; 568 break; 569 case ZYDIS_OPERAND_ENCODING_UIMM16_32_64: 570 case ZYDIS_OPERAND_ENCODING_SIMM16_32_64: 571 { 572 static const ZyanU16 simm16_32_64_sizes[3] = { 16, 32, 64 }; 573 return ZydisGetScaledImmSize(match, simm16_32_64_sizes, min_size); 574 } 575 case ZYDIS_OPERAND_ENCODING_UIMM32_32_64: 576 case ZYDIS_OPERAND_ENCODING_SIMM32_32_64: 577 { 578 static const ZyanU16 simm32_32_64_sizes[3] = { 32, 32, 64 }; 579 return ZydisGetScaledImmSize(match, simm32_32_64_sizes, min_size); 580 } 581 case ZYDIS_OPERAND_ENCODING_UIMM16_32_32: 582 case ZYDIS_OPERAND_ENCODING_SIMM16_32_32: 583 { 584 static const ZyanU16 simm16_32_32_sizes[3] = { 16, 32, 32 }; 585 return ZydisGetScaledImmSize(match, simm16_32_32_sizes, min_size); 586 } 587 case ZYDIS_OPERAND_ENCODING_DISP16_32_64: 588 { 589 ZYAN_ASSERT(match->easz == 0); 590 const ZyanU8 addr_size = ZydisGetMaxAddressSize(match->request); 591 const ZyanU64 uimm = imm & (~(0xFFFFFFFFFFFFFFFFULL << (addr_size - 1) << 1)); 592 if (min_size < addr_size && ZydisGetUnsignedImmSize(uimm) > min_size) 593 { 594 min_size = addr_size; 595 } 596 if (match->request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) 597 { 598 if (min_size < 32) 599 { 600 min_size = 32; 601 } 602 match->easz = eisz = min_size; 603 } 604 else 605 { 606 if (min_size < 16) 607 { 608 min_size = 16; 609 } 610 if (min_size == 16 || min_size == 32) 611 { 612 match->easz = eisz = min_size; 613 } 614 } 615 break; 616 } 617 case ZYDIS_OPERAND_ENCODING_JIMM8: 618 case ZYDIS_OPERAND_ENCODING_JIMM16: 619 case ZYDIS_OPERAND_ENCODING_JIMM32: 620 case ZYDIS_OPERAND_ENCODING_JIMM64: 621 { 622 ZyanU8 jimm_index = def_op->op.encoding - ZYDIS_OPERAND_ENCODING_JIMM8; 623 if ((match->request->branch_width != ZYDIS_BRANCH_WIDTH_NONE) && 624 (match->request->branch_width != (ZydisBranchWidth)(ZYDIS_BRANCH_WIDTH_8 + jimm_index))) 625 { 626 return 0; 627 } 628 eisz = 8 << jimm_index; 629 break; 630 } 631 case ZYDIS_OPERAND_ENCODING_JIMM16_32_32: 632 switch (match->request->branch_width) 633 { 634 case ZYDIS_BRANCH_WIDTH_NONE: 635 { 636 static const ZyanU16 jimm16_32_32_sizes[3] = { 16, 32, 32 }; 637 return ZydisGetScaledImmSize(match, jimm16_32_32_sizes, min_size); 638 } 639 case ZYDIS_BRANCH_WIDTH_16: 640 eisz = 16; 641 break; 642 case ZYDIS_BRANCH_WIDTH_32: 643 eisz = 32; 644 break; 645 case ZYDIS_BRANCH_WIDTH_8: 646 case ZYDIS_BRANCH_WIDTH_64: 647 return 0; 648 default: 649 ZYAN_UNREACHABLE; 650 } 651 break; 652 default: 653 ZYAN_UNREACHABLE; 654 } 655 656 return eisz >= min_size ? eisz : 0; 657 } 658 659 /** 660 * Checks if register width is compatible with effective operand size. 661 * 662 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 663 * @param reg_width Register width in bits. 664 * 665 * @return True if width is compatible, false otherwise. 666 */ 667 static ZyanBool ZydisCheckOsz(ZydisEncoderInstructionMatch *match, ZydisRegisterWidth reg_width) 668 { 669 ZYAN_ASSERT(reg_width <= ZYAN_UINT8_MAX); 670 if (match->eosz == 0) 671 { 672 if (reg_width == 8) 673 { 674 return ZYAN_FALSE; 675 } 676 match->eosz = (ZyanU8)reg_width; 677 return ZYAN_TRUE; 678 } 679 680 return match->eosz == (ZyanU8)reg_width ? ZYAN_TRUE : ZYAN_FALSE; 681 } 682 683 /** 684 * Checks if register width is compatible with effective address size. 685 * 686 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 687 * @param reg_width Register width in bits. 688 * 689 * @return True if width is compatible, false otherwise. 690 */ 691 static ZyanBool ZydisCheckAsz(ZydisEncoderInstructionMatch *match, ZydisRegisterWidth reg_width) 692 { 693 ZYAN_ASSERT(reg_width <= ZYAN_UINT8_MAX); 694 if (match->easz == 0) 695 { 696 if ((match->request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) && 697 (reg_width == 16)) 698 { 699 return ZYAN_FALSE; 700 } 701 match->easz = (ZyanU8)reg_width; 702 return ZYAN_TRUE; 703 } 704 705 return match->easz == (ZyanU8)reg_width ? ZYAN_TRUE : ZYAN_FALSE; 706 } 707 708 /** 709 * Checks if specified register is valid for provided register class, encoding and machine mode. 710 * 711 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 712 * @param reg `ZydisRegister` value. 713 * @param reg_class Register class. 714 * 715 * @return True if register value is allowed, false otherwise. 716 */ 717 static ZyanBool ZydisIsRegisterAllowed(ZydisEncoderInstructionMatch *match, ZydisRegister reg, 718 ZydisRegisterClass reg_class) 719 { 720 const ZyanI8 reg_id = ZydisRegisterGetId(reg); 721 ZYAN_ASSERT(reg_id >= 0 && reg_id <= 31); 722 if (match->request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) 723 { 724 if ((match->definition->encoding != ZYDIS_INSTRUCTION_ENCODING_EVEX) && 725 (match->definition->encoding != ZYDIS_INSTRUCTION_ENCODING_MVEX) && 726 (reg_class != ZYDIS_REGCLASS_GPR8) && 727 (reg_id >= 16)) 728 { 729 return ZYAN_FALSE; 730 } 731 } 732 else 733 { 734 if (reg_class == ZYDIS_REGCLASS_GPR64) 735 { 736 return ZYAN_FALSE; 737 } 738 if (reg_id >= 8) 739 { 740 return ZYAN_FALSE; 741 } 742 } 743 744 return ZYAN_TRUE; 745 } 746 747 /** 748 * Checks if specified scale value is valid for use with SIB addressing. 749 * 750 * @param scale Scale value. 751 * 752 * @return True if value is valid, false otherwise. 753 */ 754 static ZyanBool ZydisIsScaleValid(ZyanU8 scale) 755 { 756 switch (scale) 757 { 758 case 0: 759 case 1: 760 case 2: 761 case 4: 762 case 8: 763 return ZYAN_TRUE; 764 default: 765 return ZYAN_FALSE; 766 } 767 } 768 769 /** 770 * Enforces register usage constraints associated with usage of `REX` prefix. 771 * 772 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 773 * @param reg `ZydisRegister` value. 774 * @param addressing_mode True if checked address is used for address calculations. This 775 * implies more permissive checks. 776 * 777 * @return True if register usage is allowed, false otherwise. 778 */ 779 static ZyanBool ZydisValidateRexType(ZydisEncoderInstructionMatch *match, ZydisRegister reg, 780 ZyanBool addressing_mode) 781 { 782 switch (reg) 783 { 784 case ZYDIS_REGISTER_AL: 785 case ZYDIS_REGISTER_CL: 786 case ZYDIS_REGISTER_DL: 787 case ZYDIS_REGISTER_BL: 788 return ZYAN_TRUE; 789 case ZYDIS_REGISTER_AH: 790 case ZYDIS_REGISTER_CH: 791 case ZYDIS_REGISTER_DH: 792 case ZYDIS_REGISTER_BH: 793 if (match->rex_type == ZYDIS_REX_TYPE_UNKNOWN) 794 { 795 match->rex_type = ZYDIS_REX_TYPE_FORBIDDEN; 796 } 797 else if (match->rex_type == ZYDIS_REX_TYPE_REQUIRED) 798 { 799 return ZYAN_FALSE; 800 } 801 break; 802 case ZYDIS_REGISTER_SPL: 803 case ZYDIS_REGISTER_BPL: 804 case ZYDIS_REGISTER_SIL: 805 case ZYDIS_REGISTER_DIL: 806 case ZYDIS_REGISTER_R8B: 807 case ZYDIS_REGISTER_R9B: 808 case ZYDIS_REGISTER_R10B: 809 case ZYDIS_REGISTER_R11B: 810 case ZYDIS_REGISTER_R12B: 811 case ZYDIS_REGISTER_R13B: 812 case ZYDIS_REGISTER_R14B: 813 case ZYDIS_REGISTER_R15B: 814 if (match->rex_type == ZYDIS_REX_TYPE_UNKNOWN) 815 { 816 match->rex_type = ZYDIS_REX_TYPE_REQUIRED; 817 } 818 else if (match->rex_type == ZYDIS_REX_TYPE_FORBIDDEN) 819 { 820 return ZYAN_FALSE; 821 } 822 break; 823 default: 824 if ((ZydisRegisterGetId(reg) > 7) || 825 (!addressing_mode && (ZydisRegisterGetClass(reg) == ZYDIS_REGCLASS_GPR64))) 826 { 827 if (match->rex_type == ZYDIS_REX_TYPE_UNKNOWN) 828 { 829 match->rex_type = ZYDIS_REX_TYPE_REQUIRED; 830 } 831 else if (match->rex_type == ZYDIS_REX_TYPE_FORBIDDEN) 832 { 833 return ZYAN_FALSE; 834 } 835 } 836 break; 837 } 838 839 return ZYAN_TRUE; 840 } 841 842 /** 843 * Checks if specified register is valid for use with SIB addressing. 844 * 845 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 846 * @param reg_class Register class. 847 * @param reg `ZydisRegister` value. 848 * 849 * @return True if register value is allowed, false otherwise. 850 */ 851 static ZyanBool ZydisIsValidAddressingClass(ZydisEncoderInstructionMatch *match, 852 ZydisRegisterClass reg_class, ZydisRegister reg) 853 { 854 ZyanBool result; 855 const ZyanBool is_64 = (match->request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64); 856 switch (reg_class) 857 { 858 case ZYDIS_REGCLASS_INVALID: 859 return ZYAN_TRUE; 860 case ZYDIS_REGCLASS_GPR16: 861 result = !is_64; 862 break; 863 case ZYDIS_REGCLASS_GPR32: 864 result = is_64 || ZydisRegisterGetId(reg) < 8; 865 break; 866 case ZYDIS_REGCLASS_GPR64: 867 result = is_64; 868 break; 869 default: 870 return ZYAN_FALSE; 871 } 872 873 return result && ZydisValidateRexType(match, reg, ZYAN_TRUE); 874 } 875 876 /** 877 * Helper function that determines correct `ModR/M.RM` value for 16-bit addressing mode. 878 * 879 * @param base `ZydisRegister` used as `SIB.base`. 880 * @param index `ZydisRegister` used as `SIB.index`. 881 * 882 * @return `ModR/M.RM` value (-1 if function failed). 883 */ 884 static ZyanI8 ZydisGetRm16(ZydisRegister base, ZydisRegister index) 885 { 886 static const ZydisRegister modrm16_lookup[8][2] = 887 { 888 { ZYDIS_REGISTER_BX, ZYDIS_REGISTER_SI }, 889 { ZYDIS_REGISTER_BX, ZYDIS_REGISTER_DI }, 890 { ZYDIS_REGISTER_BP, ZYDIS_REGISTER_SI }, 891 { ZYDIS_REGISTER_BP, ZYDIS_REGISTER_DI }, 892 { ZYDIS_REGISTER_SI, ZYDIS_REGISTER_NONE }, 893 { ZYDIS_REGISTER_DI, ZYDIS_REGISTER_NONE }, 894 { ZYDIS_REGISTER_BP, ZYDIS_REGISTER_NONE }, 895 { ZYDIS_REGISTER_BX, ZYDIS_REGISTER_NONE }, 896 }; 897 for (ZyanI8 i = 0; i < (ZyanI8)ZYAN_ARRAY_LENGTH(modrm16_lookup); ++i) 898 { 899 if ((modrm16_lookup[i][0] == base) && 900 (modrm16_lookup[i][1] == index)) 901 { 902 return i; 903 } 904 } 905 906 return -1; 907 } 908 909 /** 910 * Encodes `MVEX.sss` field for specified broadcast mode. 911 * 912 * @param broadcast Broadcast mode. 913 * 914 * @return Corresponding `MVEX.sss` value. 915 */ 916 static ZyanU8 ZydisEncodeMvexBroadcastMode(ZydisBroadcastMode broadcast) 917 { 918 switch (broadcast) 919 { 920 case ZYDIS_BROADCAST_MODE_INVALID: 921 return 0; 922 case ZYDIS_BROADCAST_MODE_1_TO_16: 923 case ZYDIS_BROADCAST_MODE_1_TO_8: 924 return 1; 925 case ZYDIS_BROADCAST_MODE_4_TO_16: 926 case ZYDIS_BROADCAST_MODE_4_TO_8: 927 return 2; 928 default: 929 ZYAN_UNREACHABLE; 930 } 931 } 932 933 /** 934 * Encodes `MVEX.sss` field for specified conversion mode. 935 * 936 * @param conversion Conversion mode. 937 * 938 * @return Corresponding `MVEX.sss` value. 939 */ 940 static ZyanU8 ZydisEncodeMvexConversionMode(ZydisConversionMode conversion) 941 { 942 switch (conversion) 943 { 944 case ZYDIS_CONVERSION_MODE_INVALID: 945 return 0; 946 case ZYDIS_CONVERSION_MODE_FLOAT16: 947 return 3; 948 case ZYDIS_CONVERSION_MODE_UINT8: 949 return 4; 950 case ZYDIS_CONVERSION_MODE_SINT8: 951 return 5; 952 case ZYDIS_CONVERSION_MODE_UINT16: 953 return 6; 954 case ZYDIS_CONVERSION_MODE_SINT16: 955 return 7; 956 default: 957 ZYAN_UNREACHABLE; 958 } 959 } 960 961 /** 962 * Determines scale factor for compressed 8-bit displacement (`EVEX` instructions only). 963 * 964 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 965 * 966 * @return log2(scale factor) 967 */ 968 static ZyanU8 ZydisGetCompDispScaleEvex(const ZydisEncoderInstructionMatch *match) 969 { 970 const ZydisInstructionDefinitionEVEX *evex_def = 971 (const ZydisInstructionDefinitionEVEX *)match->base_definition; 972 973 ZYAN_ASSERT(match->definition->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX); 974 ZYAN_ASSERT(evex_def->tuple_type); 975 ZYAN_ASSERT(evex_def->element_size); 976 const ZyanU8 vector_length = match->definition->vector_length - ZYDIS_VECTOR_LENGTH_128; 977 static const ZyanU8 size_indexes[ZYDIS_IELEMENT_SIZE_MAX_VALUE + 1] = 978 { 979 0, 0, 0, 1, 2, 4 980 }; 981 ZYAN_ASSERT(evex_def->element_size < ZYAN_ARRAY_LENGTH(size_indexes)); 982 const ZyanU8 size_index = size_indexes[evex_def->element_size]; 983 switch (evex_def->tuple_type) 984 { 985 case ZYDIS_TUPLETYPE_FV: 986 { 987 static const ZyanU8 scales[2][3][3] = 988 { 989 /*B0*/ { /*16*/ { 4, 5, 6 }, /*32*/ { 4, 5, 6 }, /*64*/ { 4, 5, 6 } }, 990 /*B1*/ { /*16*/ { 1, 1, 1 }, /*32*/ { 2, 2, 2 }, /*64*/ { 3, 3, 3 } } 991 }; 992 const ZyanU8 broadcast = match->request->evex.broadcast ? 1 : 0; 993 ZYAN_ASSERT(size_index < 3); 994 return scales[broadcast][size_index][vector_length]; 995 } 996 case ZYDIS_TUPLETYPE_HV: 997 { 998 static const ZyanU8 scales[2][2][3] = 999 { 1000 /*B0*/ { /*16*/ { 3, 4, 5 }, /*32*/ { 3, 4, 5 } }, 1001 /*B1*/ { /*16*/ { 1, 1, 1 }, /*32*/ { 2, 2, 2 } } 1002 }; 1003 const ZyanU8 broadcast = match->request->evex.broadcast ? 1 : 0; 1004 ZYAN_ASSERT(size_index < 3); 1005 return scales[broadcast][size_index][vector_length]; 1006 } 1007 case ZYDIS_TUPLETYPE_FVM: 1008 { 1009 static const ZyanU8 scales[3] = 1010 { 1011 4, 5, 6 1012 }; 1013 return scales[vector_length]; 1014 } 1015 case ZYDIS_TUPLETYPE_GSCAT: 1016 case ZYDIS_TUPLETYPE_T1S: 1017 { 1018 static const ZyanU8 scales[6] = 1019 { 1020 /* */ 0, 1021 /* 8*/ 0, 1022 /* 16*/ 1, 1023 /* 32*/ 2, 1024 /* 64*/ 3, 1025 /*128*/ 4 1026 }; 1027 ZYAN_ASSERT(evex_def->element_size < ZYAN_ARRAY_LENGTH(scales)); 1028 return scales[evex_def->element_size]; 1029 } 1030 case ZYDIS_TUPLETYPE_T1F: 1031 { 1032 static const ZyanU8 scales[3] = 1033 { 1034 /* 16*/ 1, 1035 /* 32*/ 2, 1036 /* 64*/ 3 1037 }; 1038 ZYAN_ASSERT(size_index < 3); 1039 return scales[size_index]; 1040 } 1041 case ZYDIS_TUPLETYPE_T1_4X: 1042 return 4; 1043 case ZYDIS_TUPLETYPE_T2: 1044 return match->definition->rex_w ? 4 : 3; 1045 case ZYDIS_TUPLETYPE_T4: 1046 return match->definition->rex_w ? 5 : 4; 1047 case ZYDIS_TUPLETYPE_T8: 1048 return 5; 1049 case ZYDIS_TUPLETYPE_HVM: 1050 { 1051 static const ZyanU8 scales[3] = 1052 { 1053 3, 4, 5 1054 }; 1055 return scales[vector_length]; 1056 } 1057 case ZYDIS_TUPLETYPE_QVM: 1058 { 1059 static const ZyanU8 scales[3] = 1060 { 1061 2, 3, 4 1062 }; 1063 return scales[vector_length]; 1064 } 1065 case ZYDIS_TUPLETYPE_OVM: 1066 { 1067 static const ZyanU8 scales[3] = 1068 { 1069 1, 2, 3 1070 }; 1071 return scales[vector_length]; 1072 } 1073 case ZYDIS_TUPLETYPE_M128: 1074 return 4; 1075 case ZYDIS_TUPLETYPE_DUP: 1076 { 1077 static const ZyanU8 scales[3] = 1078 { 1079 3, 5, 6 1080 }; 1081 return scales[vector_length]; 1082 } 1083 case ZYDIS_TUPLETYPE_QUARTER: 1084 { 1085 static const ZyanU8 scales[2][3] = 1086 { 1087 /*B0*/ { 2, 3, 4 }, 1088 /*B1*/ { 1, 1, 1 } 1089 }; 1090 const ZyanU8 broadcast = match->request->evex.broadcast ? 1 : 0; 1091 return scales[broadcast][vector_length]; 1092 } 1093 default: 1094 ZYAN_UNREACHABLE; 1095 } 1096 } 1097 1098 /** 1099 * Determines scale factor for compressed 8-bit displacement (`MVEX` instructions only). 1100 * 1101 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 1102 * 1103 * @return log2(scale factor) 1104 */ 1105 static ZyanU8 ZydisGetCompDispScaleMvex(const ZydisEncoderInstructionMatch *match) 1106 { 1107 const ZydisInstructionDefinitionMVEX *mvex_def = 1108 (const ZydisInstructionDefinitionMVEX *)match->base_definition; 1109 1110 ZyanU8 index = mvex_def->has_element_granularity; 1111 ZYAN_ASSERT(!index || !mvex_def->broadcast); 1112 if (!index && mvex_def->broadcast) 1113 { 1114 switch (mvex_def->broadcast) 1115 { 1116 case ZYDIS_MVEX_STATIC_BROADCAST_1_TO_8: 1117 case ZYDIS_MVEX_STATIC_BROADCAST_1_TO_16: 1118 index = 1; 1119 break; 1120 case ZYDIS_MVEX_STATIC_BROADCAST_4_TO_8: 1121 case ZYDIS_MVEX_STATIC_BROADCAST_4_TO_16: 1122 index = 2; 1123 break; 1124 default: 1125 ZYAN_UNREACHABLE; 1126 } 1127 } 1128 1129 const ZyanU8 sss = ZydisEncodeMvexBroadcastMode(match->request->mvex.broadcast) | 1130 ZydisEncodeMvexConversionMode(match->request->mvex.conversion); 1131 switch (mvex_def->functionality) 1132 { 1133 case ZYDIS_MVEX_FUNC_IGNORED: 1134 case ZYDIS_MVEX_FUNC_INVALID: 1135 case ZYDIS_MVEX_FUNC_RC: 1136 case ZYDIS_MVEX_FUNC_SAE: 1137 case ZYDIS_MVEX_FUNC_SWIZZLE_32: 1138 case ZYDIS_MVEX_FUNC_SWIZZLE_64: 1139 return 0; 1140 case ZYDIS_MVEX_FUNC_F_32: 1141 case ZYDIS_MVEX_FUNC_I_32: 1142 case ZYDIS_MVEX_FUNC_F_64: 1143 case ZYDIS_MVEX_FUNC_I_64: 1144 return 6; 1145 case ZYDIS_MVEX_FUNC_SF_32: 1146 case ZYDIS_MVEX_FUNC_SF_32_BCST: 1147 case ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16: 1148 case ZYDIS_MVEX_FUNC_UF_32: 1149 { 1150 static const ZyanU8 lookup[3][8] = 1151 { 1152 { 6, 2, 4, 5, 4, 4, 5, 5 }, 1153 { 2, 0, 0, 1, 0, 0, 1, 1 }, 1154 { 4, 0, 0, 3, 2, 2, 3, 3 } 1155 }; 1156 ZYAN_ASSERT(sss < ZYAN_ARRAY_LENGTH(lookup[index])); 1157 return lookup[index][sss]; 1158 } 1159 case ZYDIS_MVEX_FUNC_SI_32: 1160 case ZYDIS_MVEX_FUNC_UI_32: 1161 case ZYDIS_MVEX_FUNC_SI_32_BCST: 1162 case ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16: 1163 { 1164 static const ZyanU8 lookup[3][8] = 1165 { 1166 { 6, 2, 4, 0, 4, 4, 5, 5 }, 1167 { 2, 0, 0, 0, 0, 0, 1, 1 }, 1168 { 4, 0, 0, 0, 2, 2, 3, 3 } 1169 }; 1170 ZYAN_ASSERT(sss < ZYAN_ARRAY_LENGTH(lookup[index])); 1171 return lookup[index][sss]; 1172 } 1173 case ZYDIS_MVEX_FUNC_SF_64: 1174 case ZYDIS_MVEX_FUNC_UF_64: 1175 case ZYDIS_MVEX_FUNC_SI_64: 1176 case ZYDIS_MVEX_FUNC_UI_64: 1177 { 1178 static const ZyanU8 lookup[3][3] = 1179 { 1180 { 6, 3, 5 }, 1181 { 3, 0, 0 }, 1182 { 5, 0, 0 } 1183 }; 1184 ZYAN_ASSERT(sss < ZYAN_ARRAY_LENGTH(lookup[index])); 1185 return lookup[index][sss]; 1186 } 1187 case ZYDIS_MVEX_FUNC_DF_32: 1188 case ZYDIS_MVEX_FUNC_DI_32: 1189 { 1190 static const ZyanU8 lookup[2][8] = 1191 { 1192 { 6, 0, 0, 5, 4, 4, 5, 5 }, 1193 { 2, 0, 0, 1, 0, 0, 1, 1 } 1194 }; 1195 ZYAN_ASSERT(index < 2); 1196 ZYAN_ASSERT(sss < ZYAN_ARRAY_LENGTH(lookup[index])); 1197 return lookup[index][sss]; 1198 } 1199 case ZYDIS_MVEX_FUNC_DF_64: 1200 case ZYDIS_MVEX_FUNC_DI_64: 1201 ZYAN_ASSERT(index < 2); 1202 return index == 0 ? 6 : 3; 1203 default: 1204 ZYAN_UNREACHABLE; 1205 } 1206 } 1207 1208 /** 1209 * Determines scale factor for compressed 8-bit displacement. 1210 * 1211 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 1212 * 1213 * @return log2(scale factor) 1214 */ 1215 static ZyanU8 ZydisGetCompDispScale(const ZydisEncoderInstructionMatch *match) 1216 { 1217 switch (match->definition->encoding) 1218 { 1219 case ZYDIS_INSTRUCTION_ENCODING_LEGACY: 1220 case ZYDIS_INSTRUCTION_ENCODING_3DNOW: 1221 case ZYDIS_INSTRUCTION_ENCODING_XOP: 1222 case ZYDIS_INSTRUCTION_ENCODING_VEX: 1223 return 0; 1224 case ZYDIS_INSTRUCTION_ENCODING_EVEX: 1225 return ZydisGetCompDispScaleEvex(match); 1226 case ZYDIS_INSTRUCTION_ENCODING_MVEX: 1227 return ZydisGetCompDispScaleMvex(match); 1228 default: 1229 ZYAN_UNREACHABLE; 1230 } 1231 } 1232 1233 /** 1234 * Checks if requested operand matches register operand from instruction definition. 1235 * 1236 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 1237 * @param user_op Operand definition from `ZydisEncoderRequest` structure. 1238 * @param def_op Decoder's operand definition from current instruction definition. 1239 * 1240 * @return True if operands match, false otherwise. 1241 */ 1242 static ZyanBool ZydisIsRegisterOperandCompatible(ZydisEncoderInstructionMatch *match, 1243 const ZydisEncoderOperand *user_op, const ZydisOperandDefinition *def_op) 1244 { 1245 const ZydisRegisterClass reg_class = ZydisRegisterGetClass(user_op->reg.value); 1246 const ZydisRegisterWidth reg_width = ZydisRegisterClassGetWidth(match->request->machine_mode, 1247 reg_class); 1248 if (reg_width == 0) 1249 { 1250 return ZYAN_FALSE; 1251 } 1252 1253 ZyanBool is4_expected_value = ZYAN_FALSE; 1254 switch (def_op->type) 1255 { 1256 case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG: 1257 switch (def_op->op.reg.type) 1258 { 1259 case ZYDIS_IMPLREG_TYPE_STATIC: 1260 if (def_op->op.reg.reg.reg != user_op->reg.value) 1261 { 1262 return ZYAN_FALSE; 1263 } 1264 break; 1265 case ZYDIS_IMPLREG_TYPE_GPR_OSZ: 1266 if ((reg_class != ZYDIS_REGCLASS_GPR8) && 1267 (reg_class != ZYDIS_REGCLASS_GPR16) && 1268 (reg_class != ZYDIS_REGCLASS_GPR32) && 1269 (reg_class != ZYDIS_REGCLASS_GPR64)) 1270 { 1271 return ZYAN_FALSE; 1272 } 1273 if (def_op->op.reg.reg.id != ZydisRegisterGetId(user_op->reg.value)) 1274 { 1275 return ZYAN_FALSE; 1276 } 1277 if (!ZydisCheckOsz(match, reg_width)) 1278 { 1279 return ZYAN_FALSE; 1280 } 1281 break; 1282 case ZYDIS_IMPLREG_TYPE_GPR_ASZ: 1283 if ((reg_class != ZYDIS_REGCLASS_GPR8) && 1284 (reg_class != ZYDIS_REGCLASS_GPR16) && 1285 (reg_class != ZYDIS_REGCLASS_GPR32) && 1286 (reg_class != ZYDIS_REGCLASS_GPR64)) 1287 { 1288 return ZYAN_FALSE; 1289 } 1290 if (def_op->op.reg.reg.id != ZydisRegisterGetId(user_op->reg.value)) 1291 { 1292 return ZYAN_FALSE; 1293 } 1294 if (!ZydisCheckAsz(match, reg_width)) 1295 { 1296 return ZYAN_FALSE; 1297 } 1298 break; 1299 default: 1300 ZYAN_UNREACHABLE; 1301 } 1302 break; 1303 case ZYDIS_SEMANTIC_OPTYPE_GPR8: 1304 if (reg_class != ZYDIS_REGCLASS_GPR8) 1305 { 1306 return ZYAN_FALSE; 1307 } 1308 if (!ZydisIsRegisterAllowed(match, user_op->reg.value, reg_class)) 1309 { 1310 return ZYAN_FALSE; 1311 } 1312 if (!ZydisValidateRexType(match, user_op->reg.value, ZYAN_FALSE)) 1313 { 1314 return ZYAN_FALSE; 1315 } 1316 break; 1317 case ZYDIS_SEMANTIC_OPTYPE_GPR16: 1318 if (reg_class != ZYDIS_REGCLASS_GPR16) 1319 { 1320 return ZYAN_FALSE; 1321 } 1322 if (!ZydisIsRegisterAllowed(match, user_op->reg.value, reg_class)) 1323 { 1324 return ZYAN_FALSE; 1325 } 1326 break; 1327 case ZYDIS_SEMANTIC_OPTYPE_GPR32: 1328 if (reg_class != ZYDIS_REGCLASS_GPR32) 1329 { 1330 return ZYAN_FALSE; 1331 } 1332 if (!ZydisIsRegisterAllowed(match, user_op->reg.value, reg_class)) 1333 { 1334 return ZYAN_FALSE; 1335 } 1336 break; 1337 case ZYDIS_SEMANTIC_OPTYPE_GPR64: 1338 if (reg_class != ZYDIS_REGCLASS_GPR64) 1339 { 1340 return ZYAN_FALSE; 1341 } 1342 break; 1343 case ZYDIS_SEMANTIC_OPTYPE_GPR16_32_64: 1344 if ((reg_class != ZYDIS_REGCLASS_GPR16) && 1345 (reg_class != ZYDIS_REGCLASS_GPR32) && 1346 (reg_class != ZYDIS_REGCLASS_GPR64)) 1347 { 1348 return ZYAN_FALSE; 1349 } 1350 if (!ZydisCheckOsz(match, reg_width)) 1351 { 1352 return ZYAN_FALSE; 1353 } 1354 if (!ZydisIsRegisterAllowed(match, user_op->reg.value, reg_class)) 1355 { 1356 return ZYAN_FALSE; 1357 } 1358 if (!ZydisValidateRexType(match, user_op->reg.value, ZYAN_FALSE)) 1359 { 1360 return ZYAN_FALSE; 1361 } 1362 break; 1363 case ZYDIS_SEMANTIC_OPTYPE_GPR32_32_64: 1364 if ((reg_class != ZYDIS_REGCLASS_GPR32) && 1365 (reg_class != ZYDIS_REGCLASS_GPR64)) 1366 { 1367 return ZYAN_FALSE; 1368 } 1369 if (match->eosz == 0) 1370 { 1371 if (reg_class == ZYDIS_REGCLASS_GPR64) 1372 { 1373 match->eosz = 64; 1374 } 1375 else 1376 { 1377 match->eosz64_forbidden = ZYAN_TRUE; 1378 } 1379 } 1380 else if (match->eosz != (ZyanU8)reg_width) 1381 { 1382 return ZYAN_FALSE; 1383 } 1384 if (!ZydisIsRegisterAllowed(match, user_op->reg.value, reg_class)) 1385 { 1386 return ZYAN_FALSE; 1387 } 1388 if (!ZydisValidateRexType(match, user_op->reg.value, ZYAN_FALSE)) 1389 { 1390 return ZYAN_FALSE; 1391 } 1392 break; 1393 case ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32: 1394 if ((reg_class != ZYDIS_REGCLASS_GPR16) && 1395 (reg_class != ZYDIS_REGCLASS_GPR32)) 1396 { 1397 return ZYAN_FALSE; 1398 } 1399 if (!ZydisCheckOsz(match, reg_width)) 1400 { 1401 if (match->eosz != 64 || reg_class != ZYDIS_REGCLASS_GPR32) 1402 { 1403 return ZYAN_FALSE; 1404 } 1405 } 1406 if (!ZydisIsRegisterAllowed(match, user_op->reg.value, reg_class)) 1407 { 1408 return ZYAN_FALSE; 1409 } 1410 break; 1411 case ZYDIS_SEMANTIC_OPTYPE_GPR_ASZ: 1412 if ((reg_class != ZYDIS_REGCLASS_GPR16) && 1413 (reg_class != ZYDIS_REGCLASS_GPR32) && 1414 (reg_class != ZYDIS_REGCLASS_GPR64)) 1415 { 1416 return ZYAN_FALSE; 1417 } 1418 if (!ZydisCheckAsz(match, reg_width)) 1419 { 1420 return ZYAN_FALSE; 1421 } 1422 if (!ZydisIsRegisterAllowed(match, user_op->reg.value, reg_class)) 1423 { 1424 return ZYAN_FALSE; 1425 } 1426 break; 1427 case ZYDIS_SEMANTIC_OPTYPE_FPR: 1428 if (reg_class != ZYDIS_REGCLASS_X87) 1429 { 1430 return ZYAN_FALSE; 1431 } 1432 break; 1433 case ZYDIS_SEMANTIC_OPTYPE_MMX: 1434 if (reg_class != ZYDIS_REGCLASS_MMX) 1435 { 1436 return ZYAN_FALSE; 1437 } 1438 break; 1439 case ZYDIS_SEMANTIC_OPTYPE_XMM: 1440 if (reg_class != ZYDIS_REGCLASS_XMM) 1441 { 1442 return ZYAN_FALSE; 1443 } 1444 if (!ZydisIsRegisterAllowed(match, user_op->reg.value, reg_class)) 1445 { 1446 return ZYAN_FALSE; 1447 } 1448 is4_expected_value = def_op->op.encoding == ZYDIS_OPERAND_ENCODING_IS4; 1449 break; 1450 case ZYDIS_SEMANTIC_OPTYPE_YMM: 1451 if (reg_class != ZYDIS_REGCLASS_YMM) 1452 { 1453 return ZYAN_FALSE; 1454 } 1455 if (!ZydisIsRegisterAllowed(match, user_op->reg.value, reg_class)) 1456 { 1457 return ZYAN_FALSE; 1458 } 1459 is4_expected_value = def_op->op.encoding == ZYDIS_OPERAND_ENCODING_IS4; 1460 break; 1461 case ZYDIS_SEMANTIC_OPTYPE_ZMM: 1462 if (reg_class != ZYDIS_REGCLASS_ZMM) 1463 { 1464 return ZYAN_FALSE; 1465 } 1466 if (!ZydisIsRegisterAllowed(match, user_op->reg.value, reg_class)) 1467 { 1468 return ZYAN_FALSE; 1469 } 1470 break; 1471 case ZYDIS_SEMANTIC_OPTYPE_TMM: 1472 if (reg_class != ZYDIS_REGCLASS_TMM) 1473 { 1474 return ZYAN_FALSE; 1475 } 1476 break; 1477 case ZYDIS_SEMANTIC_OPTYPE_BND: 1478 if (reg_class != ZYDIS_REGCLASS_BOUND) 1479 { 1480 return ZYAN_FALSE; 1481 } 1482 break; 1483 case ZYDIS_SEMANTIC_OPTYPE_SREG: 1484 if (reg_class != ZYDIS_REGCLASS_SEGMENT) 1485 { 1486 return ZYAN_FALSE; 1487 } 1488 if ((def_op->actions & ZYDIS_OPERAND_ACTION_MASK_WRITE) && 1489 (user_op->reg.value == ZYDIS_REGISTER_CS)) 1490 { 1491 return ZYAN_FALSE; 1492 } 1493 break; 1494 case ZYDIS_SEMANTIC_OPTYPE_CR: 1495 { 1496 if (reg_class != ZYDIS_REGCLASS_CONTROL) 1497 { 1498 return ZYAN_FALSE; 1499 } 1500 static const ZyanU8 cr_lookup[16] = 1501 { 1502 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 1503 }; 1504 const ZyanI8 reg_id = ZydisRegisterGetId(user_op->reg.value); 1505 if ((match->request->machine_mode != ZYDIS_MACHINE_MODE_LONG_64) && 1506 (reg_id == 8)) 1507 { 1508 return ZYAN_FALSE; 1509 } 1510 if (!cr_lookup[reg_id]) 1511 { 1512 return ZYAN_FALSE; 1513 } 1514 break; 1515 } 1516 case ZYDIS_SEMANTIC_OPTYPE_DR: 1517 if (reg_class != ZYDIS_REGCLASS_DEBUG) 1518 { 1519 return ZYAN_FALSE; 1520 } 1521 if (user_op->reg.value >= ZYDIS_REGISTER_DR8) 1522 { 1523 return ZYAN_FALSE; 1524 } 1525 break; 1526 case ZYDIS_SEMANTIC_OPTYPE_MASK: 1527 if (reg_class != ZYDIS_REGCLASS_MASK) 1528 { 1529 return ZYAN_FALSE; 1530 } 1531 1532 // MVEX does not require similar policy check 1533 if ((match->definition->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) && 1534 (def_op->op.encoding == ZYDIS_OPERAND_ENCODING_MASK)) 1535 { 1536 const ZydisInstructionDefinitionEVEX *evex_def = 1537 (const ZydisInstructionDefinitionEVEX *)match->base_definition; 1538 ZYAN_ASSERT((evex_def->mask_policy != ZYDIS_MASK_POLICY_INVALID) && 1539 (evex_def->mask_policy != ZYDIS_MASK_POLICY_FORBIDDEN)); 1540 if ((evex_def->mask_policy == ZYDIS_MASK_POLICY_REQUIRED) && 1541 (user_op->reg.value == ZYDIS_REGISTER_K0)) 1542 { 1543 return ZYAN_FALSE; 1544 } 1545 if ((evex_def->mask_policy == ZYDIS_MASK_POLICY_ALLOWED) && 1546 (match->request->evex.zeroing_mask) && 1547 (user_op->reg.value == ZYDIS_REGISTER_K0)) 1548 { 1549 return ZYAN_FALSE; 1550 } 1551 } 1552 break; 1553 default: 1554 ZYAN_UNREACHABLE; 1555 } 1556 1557 if (user_op->reg.is4 != is4_expected_value) 1558 { 1559 return ZYAN_FALSE; 1560 } 1561 1562 return ZYAN_TRUE; 1563 } 1564 1565 /** 1566 * Checks if requested operand matches memory operand from instruction definition. 1567 * 1568 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 1569 * @param user_op Operand definition from `ZydisEncoderRequest` structure. 1570 * @param def_op Decoder's operand definition from current instruction definition. 1571 * 1572 * @return True if operands match, false otherwise. 1573 */ 1574 static ZyanBool ZydisIsMemoryOperandCompatible(ZydisEncoderInstructionMatch *match, 1575 const ZydisEncoderOperand *user_op, const ZydisOperandDefinition *def_op) 1576 { 1577 switch (def_op->type) 1578 { 1579 case ZYDIS_SEMANTIC_OPTYPE_MEM: 1580 case ZYDIS_SEMANTIC_OPTYPE_AGEN: 1581 case ZYDIS_SEMANTIC_OPTYPE_MIB: 1582 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBX: 1583 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBY: 1584 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBZ: 1585 { 1586 if ((def_op->type == ZYDIS_SEMANTIC_OPTYPE_MIB) && 1587 (user_op->mem.scale != 0)) 1588 { 1589 return ZYAN_FALSE; 1590 } 1591 const ZyanI64 displacement = user_op->mem.displacement; 1592 ZyanU8 disp_size = 0; 1593 if (displacement) 1594 { 1595 disp_size = ZydisGetSignedImmSize(displacement); 1596 if (disp_size > 32) 1597 { 1598 return ZYAN_FALSE; 1599 } 1600 1601 match->cd8_scale = ZydisGetCompDispScale(match); 1602 if (match->cd8_scale) 1603 { 1604 const ZyanI64 mask = (1 << match->cd8_scale) - 1; 1605 if (!(displacement & mask)) 1606 { 1607 if (ZydisGetSignedImmSize(displacement >> match->cd8_scale) == 8) 1608 { 1609 disp_size = 8; 1610 } 1611 } 1612 else if (disp_size == 8) 1613 { 1614 disp_size = 16; 1615 } 1616 } 1617 } 1618 1619 if (def_op->type != ZYDIS_SEMANTIC_OPTYPE_AGEN) 1620 { 1621 if (match->eosz != 0) 1622 { 1623 const ZyanU8 eosz_index = match->eosz >> 5; 1624 if (def_op->size[eosz_index] != user_op->mem.size) 1625 { 1626 return ZYAN_FALSE; 1627 } 1628 } 1629 else if ((match->definition->vector_length != ZYDIS_VECTOR_LENGTH_INVALID) || 1630 (match->definition->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)) 1631 { 1632 ZyanU8 eosz_index = ZydisGetMachineModeWidth(match->request->machine_mode) >> 5; 1633 if (match->eosz64_forbidden && (eosz_index == 2)) 1634 { 1635 eosz_index = 1; 1636 } 1637 ZyanU16 allowed_mem_size = def_op->size[eosz_index]; 1638 if ((!allowed_mem_size) && 1639 (match->definition->encoding != ZYDIS_INSTRUCTION_ENCODING_VEX)) 1640 { 1641 ZYAN_ASSERT((match->definition->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) || 1642 (match->definition->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)); 1643 switch (match->definition->vector_length) 1644 { 1645 case ZYDIS_VECTOR_LENGTH_128: 1646 allowed_mem_size = 16; 1647 break; 1648 case ZYDIS_VECTOR_LENGTH_256: 1649 allowed_mem_size = 32; 1650 break; 1651 case ZYDIS_VECTOR_LENGTH_INVALID: 1652 ZYAN_ASSERT(match->definition->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX); 1653 ZYAN_FALLTHROUGH; 1654 case ZYDIS_VECTOR_LENGTH_512: 1655 allowed_mem_size = 64; 1656 break; 1657 default: 1658 ZYAN_UNREACHABLE; 1659 } 1660 if (match->definition->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) 1661 { 1662 const ZydisInstructionDefinitionEVEX *evex_def = 1663 (const ZydisInstructionDefinitionEVEX *)match->base_definition; 1664 static const ZyanU8 element_sizes[ZYDIS_IELEMENT_SIZE_MAX_VALUE + 1] = 1665 { 1666 0, 1, 2, 4, 8, 16 1667 }; 1668 ZYAN_ASSERT(evex_def->element_size < ZYAN_ARRAY_LENGTH(element_sizes)); 1669 const ZyanU8 element_size = element_sizes[evex_def->element_size]; 1670 if (match->request->evex.broadcast || evex_def->broadcast) 1671 { 1672 allowed_mem_size = element_size; 1673 } 1674 else 1675 { 1676 switch (evex_def->tuple_type) 1677 { 1678 case ZYDIS_TUPLETYPE_FV: 1679 break; 1680 case ZYDIS_TUPLETYPE_HV: 1681 allowed_mem_size /= 2; 1682 break; 1683 case ZYDIS_TUPLETYPE_QUARTER: 1684 allowed_mem_size /= 4; 1685 break; 1686 default: 1687 ZYAN_UNREACHABLE; 1688 } 1689 } 1690 } 1691 else 1692 { 1693 const ZydisInstructionDefinitionMVEX *mvex_def = 1694 (const ZydisInstructionDefinitionMVEX *)match->base_definition; 1695 ZyanU16 element_size; 1696 switch (match->request->mvex.conversion) 1697 { 1698 case ZYDIS_CONVERSION_MODE_INVALID: 1699 1700 switch (mvex_def->functionality) 1701 { 1702 case ZYDIS_MVEX_FUNC_SF_32: 1703 case ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16: 1704 case ZYDIS_MVEX_FUNC_UF_32: 1705 case ZYDIS_MVEX_FUNC_DF_32: 1706 case ZYDIS_MVEX_FUNC_SI_32: 1707 case ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16: 1708 case ZYDIS_MVEX_FUNC_UI_32: 1709 case ZYDIS_MVEX_FUNC_DI_32: 1710 allowed_mem_size = 64; 1711 element_size = 4; 1712 break; 1713 case ZYDIS_MVEX_FUNC_SF_64: 1714 case ZYDIS_MVEX_FUNC_UF_64: 1715 case ZYDIS_MVEX_FUNC_DF_64: 1716 case ZYDIS_MVEX_FUNC_SI_64: 1717 case ZYDIS_MVEX_FUNC_UI_64: 1718 case ZYDIS_MVEX_FUNC_DI_64: 1719 allowed_mem_size = 64; 1720 element_size = 8; 1721 break; 1722 case ZYDIS_MVEX_FUNC_SF_32_BCST: 1723 case ZYDIS_MVEX_FUNC_SI_32_BCST: 1724 allowed_mem_size = 32; 1725 element_size = 4; 1726 break; 1727 default: 1728 ZYAN_UNREACHABLE; 1729 } 1730 break; 1731 case ZYDIS_CONVERSION_MODE_FLOAT16: 1732 case ZYDIS_CONVERSION_MODE_SINT16: 1733 case ZYDIS_CONVERSION_MODE_UINT16: 1734 allowed_mem_size = 32; 1735 element_size = 2; 1736 break; 1737 case ZYDIS_CONVERSION_MODE_SINT8: 1738 case ZYDIS_CONVERSION_MODE_UINT8: 1739 allowed_mem_size = 16; 1740 element_size = 1; 1741 break; 1742 default: 1743 ZYAN_UNREACHABLE; 1744 } 1745 ZYAN_ASSERT(!mvex_def->broadcast || !match->request->mvex.broadcast); 1746 switch (mvex_def->broadcast) 1747 { 1748 case ZYDIS_MVEX_STATIC_BROADCAST_NONE: 1749 break; 1750 case ZYDIS_MVEX_STATIC_BROADCAST_1_TO_8: 1751 case ZYDIS_MVEX_STATIC_BROADCAST_1_TO_16: 1752 allowed_mem_size = element_size; 1753 break; 1754 case ZYDIS_MVEX_STATIC_BROADCAST_4_TO_8: 1755 case ZYDIS_MVEX_STATIC_BROADCAST_4_TO_16: 1756 allowed_mem_size = element_size * 4; 1757 break; 1758 default: 1759 ZYAN_UNREACHABLE; 1760 } 1761 switch (match->request->mvex.broadcast) 1762 { 1763 case ZYDIS_BROADCAST_MODE_INVALID: 1764 break; 1765 case ZYDIS_BROADCAST_MODE_1_TO_8: 1766 case ZYDIS_BROADCAST_MODE_1_TO_16: 1767 allowed_mem_size = element_size; 1768 break; 1769 case ZYDIS_BROADCAST_MODE_4_TO_8: 1770 case ZYDIS_BROADCAST_MODE_4_TO_16: 1771 allowed_mem_size = element_size * 4; 1772 break; 1773 default: 1774 ZYAN_UNREACHABLE; 1775 } 1776 } 1777 } 1778 if (user_op->mem.size != allowed_mem_size) 1779 { 1780 return ZYAN_FALSE; 1781 } 1782 } 1783 else if (match->definition->rex_w) 1784 { 1785 match->eosz = 64; 1786 } 1787 else if (match->definition->vector_length == ZYDIS_VECTOR_LENGTH_INVALID) 1788 { 1789 match->eosz = ZydisGetOperandSizeFromElementSize(match, def_op->size, 1790 user_op->mem.size, ZYAN_TRUE); 1791 if (match->eosz == 0) 1792 { 1793 return ZYAN_FALSE; 1794 } 1795 } 1796 else 1797 { 1798 ZYAN_UNREACHABLE; 1799 } 1800 } 1801 else 1802 { 1803 if (match->easz != 0) 1804 { 1805 if (match->easz != user_op->mem.size) 1806 { 1807 return ZYAN_FALSE; 1808 } 1809 } 1810 else 1811 { 1812 switch (user_op->mem.size) 1813 { 1814 case 2: 1815 case 4: 1816 case 8: 1817 match->easz = (ZyanU8)user_op->mem.size << 3; 1818 break; 1819 default: 1820 return ZYAN_FALSE; 1821 } 1822 } 1823 } 1824 1825 ZydisRegisterClass vsib_index_class = ZYDIS_REGCLASS_INVALID; 1826 ZyanBool is_vsib = ZYAN_TRUE; 1827 switch (def_op->type) 1828 { 1829 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBX: 1830 vsib_index_class = ZYDIS_REGCLASS_XMM; 1831 break; 1832 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBY: 1833 vsib_index_class = ZYDIS_REGCLASS_YMM; 1834 break; 1835 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBZ: 1836 vsib_index_class = ZYDIS_REGCLASS_ZMM; 1837 break; 1838 default: 1839 is_vsib = ZYAN_FALSE; 1840 break; 1841 } 1842 const ZyanBool is_rip_relative = (user_op->mem.base == ZYDIS_REGISTER_RIP) || 1843 (user_op->mem.base == ZYDIS_REGISTER_EIP); 1844 if (is_rip_relative) 1845 { 1846 const ZyanBool no_rip_rel = ZYDIS_OPDEF_GET_MEM_HIGH_BIT(match->base_definition->op_rm); 1847 if (no_rip_rel || ((match->definition->modrm & 7) == 4)) 1848 { 1849 return ZYAN_FALSE; 1850 } 1851 } 1852 const ZydisRegisterClass reg_base_class = ZydisRegisterGetClass(user_op->mem.base); 1853 if ((reg_base_class == ZYDIS_REGCLASS_INVALID) && 1854 (user_op->mem.base != ZYDIS_REGISTER_NONE)) 1855 { 1856 return ZYAN_FALSE; 1857 } 1858 const ZydisRegisterClass reg_index_class = ZydisRegisterGetClass(user_op->mem.index); 1859 if ((reg_index_class == ZYDIS_REGCLASS_INVALID) && 1860 (user_op->mem.index != ZYDIS_REGISTER_NONE)) 1861 { 1862 return ZYAN_FALSE; 1863 } 1864 if (is_vsib) 1865 { 1866 const ZyanU8 mode_width = ZydisGetMachineModeWidth(match->request->machine_mode); 1867 const ZyanI8 reg_index_id = ZydisRegisterGetId(user_op->mem.index); 1868 if (((match->request->machine_mode != ZYDIS_MACHINE_MODE_LONG_64) || 1869 (reg_base_class != ZYDIS_REGCLASS_GPR64)) && 1870 (reg_base_class != ZYDIS_REGCLASS_GPR32) && 1871 (reg_base_class != ZYDIS_REGCLASS_INVALID)) 1872 { 1873 return ZYAN_FALSE; 1874 } 1875 if ((reg_base_class == ZYDIS_REGCLASS_GPR32) && 1876 (mode_width != 64) && 1877 (ZydisRegisterGetId(user_op->mem.base) > 7)) 1878 { 1879 return ZYAN_FALSE; 1880 } 1881 ZyanU8 max_reg_id = 7; 1882 if (mode_width == 64) 1883 { 1884 max_reg_id = match->definition->encoding != ZYDIS_INSTRUCTION_ENCODING_VEX ? 1885 31 : 15; 1886 } 1887 if ((reg_index_class != vsib_index_class) || 1888 (reg_index_id > max_reg_id)) 1889 { 1890 return ZYAN_FALSE; 1891 } 1892 } 1893 else 1894 { 1895 if (!ZydisIsValidAddressingClass(match, reg_base_class, user_op->mem.base)) 1896 { 1897 if (!is_rip_relative || match->request->machine_mode != ZYDIS_MACHINE_MODE_LONG_64) 1898 { 1899 return ZYAN_FALSE; 1900 } 1901 } 1902 if (!ZydisIsValidAddressingClass(match, reg_index_class, user_op->mem.index)) 1903 { 1904 return ZYAN_FALSE; 1905 } 1906 if (reg_base_class != ZYDIS_REGCLASS_INVALID && 1907 reg_index_class != ZYDIS_REGCLASS_INVALID && 1908 reg_base_class != reg_index_class) 1909 { 1910 return ZYAN_FALSE; 1911 } 1912 if (user_op->mem.index == ZYDIS_REGISTER_ESP || 1913 user_op->mem.index == ZYDIS_REGISTER_RSP) 1914 { 1915 return ZYAN_FALSE; 1916 } 1917 } 1918 if (reg_index_class != ZYDIS_REGCLASS_INVALID && 1919 user_op->mem.scale == 0 && 1920 def_op->type != ZYDIS_SEMANTIC_OPTYPE_MIB) 1921 { 1922 return ZYAN_FALSE; 1923 } 1924 if (reg_index_class == ZYDIS_REGCLASS_INVALID && 1925 user_op->mem.scale != 0) 1926 { 1927 return ZYAN_FALSE; 1928 } 1929 ZyanU8 candidate_easz = 0; 1930 ZyanBool disp_only = ZYAN_FALSE; 1931 if (reg_base_class != ZYDIS_REGCLASS_INVALID) 1932 { 1933 if (is_rip_relative) 1934 { 1935 candidate_easz = user_op->mem.base == ZYDIS_REGISTER_RIP ? 64 : 32; 1936 } 1937 else 1938 { 1939 candidate_easz = (ZyanU8)ZydisRegisterClassGetWidth(match->request->machine_mode, 1940 reg_base_class); 1941 } 1942 } 1943 else if (reg_index_class != ZYDIS_REGCLASS_INVALID) 1944 { 1945 if (is_vsib) 1946 { 1947 candidate_easz = ZydisGetMachineModeWidth(match->request->machine_mode); 1948 } 1949 else 1950 { 1951 candidate_easz = (ZyanU8)ZydisRegisterClassGetWidth(match->request->machine_mode, 1952 reg_index_class); 1953 } 1954 } 1955 else if (disp_size != 8 || !match->cd8_scale) 1956 { 1957 const ZyanU8 addr_size = ZydisGetMaxAddressSize(match->request); 1958 if (disp_size > addr_size) 1959 { 1960 return ZYAN_FALSE; 1961 } 1962 ZyanU8 min_disp_size = match->easz ? match->easz : 16; 1963 if (((min_disp_size == 16) && !(match->definition->address_sizes & ZYDIS_WIDTH_16)) || 1964 (min_disp_size == 64) || 1965 (match->request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)) 1966 { 1967 min_disp_size = 32; 1968 } 1969 if (disp_size < min_disp_size) 1970 { 1971 disp_size = min_disp_size; 1972 } 1973 const ZyanI64 disp = user_op->mem.displacement; 1974 if (match->request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) 1975 { 1976 candidate_easz = addr_size; 1977 if (addr_size == 32 && disp >= 0 && match->easz != 32) 1978 { 1979 candidate_easz = 64; 1980 } 1981 } 1982 else 1983 { 1984 const ZyanU64 uimm = disp & (~(0xFFFFFFFFFFFFFFFFULL << (addr_size - 1) << 1)); 1985 if (disp_size < addr_size && ZydisGetUnsignedImmSize(uimm) > disp_size) 1986 { 1987 disp_size = addr_size; 1988 } 1989 candidate_easz = disp_size; 1990 } 1991 disp_only = ZYAN_TRUE; 1992 } 1993 if (match->request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) 1994 { 1995 if (is_rip_relative && reg_index_class != ZYDIS_REGCLASS_INVALID) 1996 { 1997 return ZYAN_FALSE; 1998 } 1999 } 2000 else 2001 { 2002 if (candidate_easz == 16 && !disp_only) 2003 { 2004 if (disp_size > 16) 2005 { 2006 return ZYAN_FALSE; 2007 } 2008 const ZyanI8 rm16 = ZydisGetRm16(user_op->mem.base, user_op->mem.index); 2009 if (rm16 == -1) 2010 { 2011 return ZYAN_FALSE; 2012 } 2013 const ZyanU8 allowed_scale = rm16 < 4 ? 1 : 0; 2014 if (user_op->mem.scale != allowed_scale) 2015 { 2016 return ZYAN_FALSE; 2017 } 2018 } 2019 } 2020 if (match->easz != 0) 2021 { 2022 if (match->easz != candidate_easz) 2023 { 2024 return ZYAN_FALSE; 2025 } 2026 } 2027 else 2028 { 2029 match->easz = candidate_easz; 2030 } 2031 if ((match->base_definition->address_size_map == ZYDIS_ADSIZE_MAP_IGNORED) && 2032 (match->easz != ZydisGetMachineModeWidth(match->request->machine_mode))) 2033 { 2034 return ZYAN_FALSE; 2035 } 2036 match->disp_size = disp_size; 2037 break; 2038 } 2039 case ZYDIS_SEMANTIC_OPTYPE_MOFFS: 2040 { 2041 if (user_op->mem.base != ZYDIS_REGISTER_NONE || 2042 user_op->mem.index != ZYDIS_REGISTER_NONE || 2043 user_op->mem.scale != 0) 2044 { 2045 return ZYAN_FALSE; 2046 } 2047 const ZyanU8 min_disp_size = ZydisGetSignedImmSize(user_op->mem.displacement); 2048 if (min_disp_size > ZydisGetMaxAddressSize(match->request)) 2049 { 2050 return ZYAN_FALSE; 2051 } 2052 if (match->eosz != 0) 2053 { 2054 const ZyanU8 eosz_index = match->eosz >> 5; 2055 if (def_op->size[eosz_index] != user_op->mem.size) 2056 { 2057 return ZYAN_FALSE; 2058 } 2059 } 2060 else 2061 { 2062 match->eosz = ZydisGetOperandSizeFromElementSize(match, def_op->size, 2063 user_op->mem.size, ZYAN_TRUE); 2064 if (match->eosz == 0) 2065 { 2066 return ZYAN_FALSE; 2067 } 2068 } 2069 match->disp_size = ZydisGetEffectiveImmSize(match, user_op->mem.displacement, def_op); 2070 if (match->disp_size == 0) 2071 { 2072 return ZYAN_FALSE; 2073 } 2074 // This is not a standard rejection. It's a special case for `mov` instructions (`moffs` 2075 // variants only). In 64-bit mode it's possible to get a shorter encoding for addresses 2076 // that can fit into 32-bit displacements. 2077 if (match->disp_size == 64 && min_disp_size < match->disp_size) 2078 { 2079 return ZYAN_FALSE; 2080 } 2081 break; 2082 } 2083 default: 2084 ZYAN_UNREACHABLE; 2085 } 2086 2087 return ZYAN_TRUE; 2088 } 2089 2090 /** 2091 * Checks if requested operand matches pointer operand from instruction definition. 2092 * 2093 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 2094 * @param user_op Operand definition from `ZydisEncoderRequest` structure. 2095 * 2096 * @return True if operands match, false otherwise. 2097 */ 2098 static ZyanBool ZydisIsPointerOperandCompatible(ZydisEncoderInstructionMatch *match, 2099 const ZydisEncoderOperand *user_op) 2100 { 2101 ZYAN_ASSERT(match->eosz == 0); 2102 ZYAN_ASSERT(match->request->machine_mode != ZYDIS_MACHINE_MODE_LONG_64); 2103 ZYAN_ASSERT((match->request->branch_type == ZYDIS_BRANCH_TYPE_NONE) || 2104 (match->request->branch_type == ZYDIS_BRANCH_TYPE_FAR)); 2105 const ZyanU8 min_disp_size = ZydisGetUnsignedImmSize(user_op->ptr.offset); 2106 const ZyanU8 desired_disp_size = (match->request->branch_width == ZYDIS_BRANCH_WIDTH_NONE) 2107 ? ZydisGetMachineModeWidth(match->request->machine_mode) 2108 : (4 << match->request->branch_width); 2109 if (min_disp_size > desired_disp_size) 2110 { 2111 return ZYAN_FALSE; 2112 } 2113 match->eosz = match->disp_size = desired_disp_size; 2114 match->imm_size = 16; 2115 return ZYAN_TRUE; 2116 } 2117 2118 /** 2119 * Checks if requested operand matches immediate operand from instruction definition. 2120 * 2121 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 2122 * @param user_op Operand definition from `ZydisEncoderRequest` structure. 2123 * @param def_op Decoder's operand definition from current instruction definition. 2124 * 2125 * @return True if operands match, false otherwise. 2126 */ 2127 static ZyanBool ZydisIsImmediateOperandCompabile(ZydisEncoderInstructionMatch *match, 2128 const ZydisEncoderOperand *user_op, const ZydisOperandDefinition *def_op) 2129 { 2130 switch (def_op->type) 2131 { 2132 case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1: 2133 if (user_op->imm.u != 1) 2134 { 2135 return ZYAN_FALSE; 2136 } 2137 break; 2138 case ZYDIS_SEMANTIC_OPTYPE_IMM: 2139 case ZYDIS_SEMANTIC_OPTYPE_REL: 2140 { 2141 const ZyanU8 imm_size = ZydisGetEffectiveImmSize(match, user_op->imm.s, def_op); 2142 if (def_op->op.encoding != ZYDIS_OPERAND_ENCODING_IS4) 2143 { 2144 if (imm_size == 0) 2145 { 2146 return ZYAN_FALSE; 2147 } 2148 if (match->imm_size) 2149 { 2150 ZYAN_ASSERT(match->disp_size == 0); 2151 match->disp_size = match->imm_size; 2152 } 2153 } 2154 else 2155 { 2156 ZYAN_ASSERT(match->imm_size == 0); 2157 if (imm_size != 8) 2158 { 2159 return ZYAN_FALSE; 2160 } 2161 } 2162 match->imm_size = imm_size; 2163 match->has_rel_operand = (def_op->type == ZYDIS_SEMANTIC_OPTYPE_REL); 2164 break; 2165 } 2166 default: 2167 ZYAN_UNREACHABLE; 2168 } 2169 2170 return ZYAN_TRUE; 2171 } 2172 2173 /** 2174 * Checks if requested boardcast mode is compatible with instruction definition. 2175 * 2176 * @param evex_def Definition for `EVEX`-encoded instruction. 2177 * @param vector_length Vector length. 2178 * @param broadcast Requested broadcast mode. 2179 * 2180 * @return True if broadcast mode is compatible, false otherwise. 2181 */ 2182 static ZyanBool ZydisIsBroadcastModeCompatible(const ZydisInstructionDefinitionEVEX *evex_def, 2183 ZydisVectorLength vector_length, ZydisBroadcastMode broadcast) 2184 { 2185 if (broadcast == ZYDIS_BROADCAST_MODE_INVALID) 2186 { 2187 return ZYAN_TRUE; 2188 } 2189 2190 ZyanU8 vector_size = 0; 2191 ZYAN_ASSERT(vector_length != ZYDIS_VECTOR_LENGTH_INVALID); 2192 switch (vector_length) 2193 { 2194 case ZYDIS_VECTOR_LENGTH_128: 2195 vector_size = 16; 2196 break; 2197 case ZYDIS_VECTOR_LENGTH_256: 2198 vector_size = 32; 2199 break; 2200 case ZYDIS_VECTOR_LENGTH_512: 2201 vector_size = 64; 2202 break; 2203 default: 2204 ZYAN_UNREACHABLE; 2205 } 2206 switch (evex_def->tuple_type) 2207 { 2208 case ZYDIS_TUPLETYPE_FV: 2209 break; 2210 case ZYDIS_TUPLETYPE_HV: 2211 vector_size /= 2; 2212 break; 2213 case ZYDIS_TUPLETYPE_QUARTER: 2214 vector_size /= 4; 2215 break; 2216 default: 2217 ZYAN_UNREACHABLE; 2218 } 2219 2220 ZyanU8 element_size; 2221 switch (evex_def->element_size) 2222 { 2223 case ZYDIS_IELEMENT_SIZE_16: 2224 element_size = 2; 2225 break; 2226 case ZYDIS_IELEMENT_SIZE_32: 2227 element_size = 4; 2228 break; 2229 case ZYDIS_IELEMENT_SIZE_64: 2230 element_size = 8; 2231 break; 2232 default: 2233 ZYAN_UNREACHABLE; 2234 } 2235 2236 ZydisBroadcastMode allowed_mode; 2237 const ZyanU8 element_count = vector_size / element_size; 2238 switch (element_count) 2239 { 2240 case 2: 2241 allowed_mode = ZYDIS_BROADCAST_MODE_1_TO_2; 2242 break; 2243 case 4: 2244 allowed_mode = ZYDIS_BROADCAST_MODE_1_TO_4; 2245 break; 2246 case 8: 2247 allowed_mode = ZYDIS_BROADCAST_MODE_1_TO_8; 2248 break; 2249 case 16: 2250 allowed_mode = ZYDIS_BROADCAST_MODE_1_TO_16; 2251 break; 2252 case 32: 2253 allowed_mode = ZYDIS_BROADCAST_MODE_1_TO_32; 2254 break; 2255 default: 2256 ZYAN_UNREACHABLE; 2257 } 2258 2259 if (broadcast != allowed_mode) 2260 { 2261 return ZYAN_FALSE; 2262 } 2263 2264 return ZYAN_TRUE; 2265 } 2266 2267 /** 2268 * Checks if requested `EVEX`-specific features are compatible with instruction definition. 2269 * 2270 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 2271 * @param request A pointer to `ZydisEncoderRequest` struct. 2272 * 2273 * @return True if features are compatible, false otherwise. 2274 */ 2275 static ZyanBool ZydisAreEvexFeaturesCompatible(const ZydisEncoderInstructionMatch *match, 2276 const ZydisEncoderRequest *request) 2277 { 2278 if (match->definition->encoding != ZYDIS_INSTRUCTION_ENCODING_EVEX) 2279 { 2280 return ZYAN_TRUE; 2281 } 2282 2283 const ZydisInstructionDefinitionEVEX *evex_def = 2284 (const ZydisInstructionDefinitionEVEX *)match->base_definition; 2285 if ((!evex_def->accepts_zero_mask) && 2286 (evex_def->mask_override != ZYDIS_MASK_OVERRIDE_ZEROING) && 2287 (request->evex.zeroing_mask)) 2288 { 2289 return ZYAN_FALSE; 2290 } 2291 2292 switch (evex_def->functionality) 2293 { 2294 case ZYDIS_EVEX_FUNC_INVALID: 2295 if ((request->evex.sae) || 2296 (request->evex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) || 2297 (request->evex.rounding != ZYDIS_ROUNDING_MODE_INVALID)) 2298 { 2299 return ZYAN_FALSE; 2300 } 2301 break; 2302 case ZYDIS_EVEX_FUNC_BC: 2303 if ((request->evex.sae) || 2304 (request->evex.rounding != ZYDIS_ROUNDING_MODE_INVALID)) 2305 { 2306 return ZYAN_FALSE; 2307 } 2308 if (!ZydisIsBroadcastModeCompatible(evex_def, match->definition->vector_length, 2309 request->evex.broadcast)) 2310 { 2311 return ZYAN_FALSE; 2312 } 2313 break; 2314 case ZYDIS_EVEX_FUNC_RC: 2315 if (request->evex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) 2316 { 2317 return ZYAN_FALSE; 2318 } 2319 if (request->evex.rounding == ZYDIS_ROUNDING_MODE_INVALID) 2320 { 2321 if (request->evex.sae) 2322 { 2323 return ZYAN_FALSE; 2324 } 2325 } 2326 else 2327 { 2328 if (!request->evex.sae) 2329 { 2330 return ZYAN_FALSE; 2331 } 2332 } 2333 break; 2334 case ZYDIS_EVEX_FUNC_SAE: 2335 if ((request->evex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) || 2336 (request->evex.rounding != ZYDIS_ROUNDING_MODE_INVALID)) 2337 { 2338 return ZYAN_FALSE; 2339 } 2340 break; 2341 default: 2342 ZYAN_UNREACHABLE; 2343 } 2344 2345 return ZYAN_TRUE; 2346 } 2347 2348 /** 2349 * Checks if requested `MVEX`-specific features are compatible with instruction definition. 2350 * 2351 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 2352 * @param request A pointer to `ZydisEncoderRequest` struct. 2353 * 2354 * @return True if features are compatible, false otherwise. 2355 */ 2356 static ZyanBool ZydisAreMvexFeaturesCompatible(const ZydisEncoderInstructionMatch *match, 2357 const ZydisEncoderRequest *request) 2358 { 2359 if (match->definition->encoding != ZYDIS_INSTRUCTION_ENCODING_MVEX) 2360 { 2361 return ZYAN_TRUE; 2362 } 2363 if (((match->definition->modrm >> 6) == 3) && 2364 (request->mvex.eviction_hint)) 2365 { 2366 return ZYAN_FALSE; 2367 } 2368 2369 const ZydisInstructionDefinitionMVEX *mvex_def = 2370 (const ZydisInstructionDefinitionMVEX *)match->base_definition; 2371 switch (mvex_def->functionality) 2372 { 2373 case ZYDIS_MVEX_FUNC_IGNORED: 2374 case ZYDIS_MVEX_FUNC_INVALID: 2375 case ZYDIS_MVEX_FUNC_F_32: 2376 case ZYDIS_MVEX_FUNC_I_32: 2377 case ZYDIS_MVEX_FUNC_F_64: 2378 case ZYDIS_MVEX_FUNC_I_64: 2379 case ZYDIS_MVEX_FUNC_UF_64: 2380 case ZYDIS_MVEX_FUNC_UI_64: 2381 case ZYDIS_MVEX_FUNC_DF_64: 2382 case ZYDIS_MVEX_FUNC_DI_64: 2383 if ((request->mvex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) || 2384 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_INVALID) || 2385 (request->mvex.rounding != ZYDIS_ROUNDING_MODE_INVALID) || 2386 (request->mvex.swizzle != ZYDIS_SWIZZLE_MODE_INVALID) || 2387 (request->mvex.sae)) 2388 { 2389 return ZYAN_FALSE; 2390 } 2391 break; 2392 case ZYDIS_MVEX_FUNC_RC: 2393 if ((request->mvex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) || 2394 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_INVALID) || 2395 (request->mvex.swizzle != ZYDIS_SWIZZLE_MODE_INVALID) || 2396 (request->mvex.eviction_hint)) 2397 { 2398 return ZYAN_FALSE; 2399 } 2400 break; 2401 case ZYDIS_MVEX_FUNC_SAE: 2402 if ((request->mvex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) || 2403 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_INVALID) || 2404 (request->mvex.rounding != ZYDIS_ROUNDING_MODE_INVALID) || 2405 (request->mvex.swizzle != ZYDIS_SWIZZLE_MODE_INVALID) || 2406 (request->mvex.eviction_hint)) 2407 { 2408 return ZYAN_FALSE; 2409 } 2410 break; 2411 case ZYDIS_MVEX_FUNC_SWIZZLE_32: 2412 case ZYDIS_MVEX_FUNC_SWIZZLE_64: 2413 if ((request->mvex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) || 2414 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_INVALID) || 2415 (request->mvex.rounding != ZYDIS_ROUNDING_MODE_INVALID) || 2416 (request->mvex.sae)) 2417 { 2418 return ZYAN_FALSE; 2419 } 2420 break; 2421 case ZYDIS_MVEX_FUNC_SF_32: 2422 if ((request->mvex.rounding != ZYDIS_ROUNDING_MODE_INVALID) || 2423 (request->mvex.swizzle != ZYDIS_SWIZZLE_MODE_INVALID) || 2424 (request->mvex.sae)) 2425 { 2426 return ZYAN_FALSE; 2427 } 2428 if ((request->mvex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) && 2429 (request->mvex.broadcast != ZYDIS_BROADCAST_MODE_1_TO_16) && 2430 (request->mvex.broadcast != ZYDIS_BROADCAST_MODE_4_TO_16)) 2431 { 2432 return ZYAN_FALSE; 2433 } 2434 if ((request->mvex.conversion != ZYDIS_CONVERSION_MODE_INVALID) && 2435 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_FLOAT16) && 2436 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_UINT8) && 2437 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_UINT16) && 2438 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_SINT16)) 2439 { 2440 return ZYAN_FALSE; 2441 } 2442 if ((request->mvex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) && 2443 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_INVALID)) 2444 { 2445 return ZYAN_FALSE; 2446 } 2447 break; 2448 case ZYDIS_MVEX_FUNC_SI_32: 2449 if ((request->mvex.rounding != ZYDIS_ROUNDING_MODE_INVALID) || 2450 (request->mvex.swizzle != ZYDIS_SWIZZLE_MODE_INVALID) || 2451 (request->mvex.sae)) 2452 { 2453 return ZYAN_FALSE; 2454 } 2455 if ((request->mvex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) && 2456 (request->mvex.broadcast != ZYDIS_BROADCAST_MODE_1_TO_16) && 2457 (request->mvex.broadcast != ZYDIS_BROADCAST_MODE_4_TO_16)) 2458 { 2459 return ZYAN_FALSE; 2460 } 2461 if ((request->mvex.conversion != ZYDIS_CONVERSION_MODE_INVALID) && 2462 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_UINT8) && 2463 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_SINT8) && 2464 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_UINT16) && 2465 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_SINT16)) 2466 { 2467 return ZYAN_FALSE; 2468 } 2469 if ((request->mvex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) && 2470 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_INVALID)) 2471 { 2472 return ZYAN_FALSE; 2473 } 2474 break; 2475 case ZYDIS_MVEX_FUNC_SF_32_BCST: 2476 case ZYDIS_MVEX_FUNC_SI_32_BCST: 2477 if ((request->mvex.conversion != ZYDIS_CONVERSION_MODE_INVALID) || 2478 (request->mvex.rounding != ZYDIS_ROUNDING_MODE_INVALID) || 2479 (request->mvex.swizzle != ZYDIS_SWIZZLE_MODE_INVALID) || 2480 (request->mvex.sae)) 2481 { 2482 return ZYAN_FALSE; 2483 } 2484 if ((request->mvex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) && 2485 (request->mvex.broadcast != ZYDIS_BROADCAST_MODE_1_TO_16) && 2486 (request->mvex.broadcast != ZYDIS_BROADCAST_MODE_4_TO_16)) 2487 { 2488 return ZYAN_FALSE; 2489 } 2490 break; 2491 case ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16: 2492 case ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16: 2493 if ((request->mvex.conversion != ZYDIS_CONVERSION_MODE_INVALID) || 2494 (request->mvex.rounding != ZYDIS_ROUNDING_MODE_INVALID) || 2495 (request->mvex.swizzle != ZYDIS_SWIZZLE_MODE_INVALID) || 2496 (request->mvex.sae)) 2497 { 2498 return ZYAN_FALSE; 2499 } 2500 if ((request->mvex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) && 2501 (request->mvex.broadcast != ZYDIS_BROADCAST_MODE_4_TO_16)) 2502 { 2503 return ZYAN_FALSE; 2504 } 2505 break; 2506 case ZYDIS_MVEX_FUNC_SF_64: 2507 case ZYDIS_MVEX_FUNC_SI_64: 2508 if ((request->mvex.conversion != ZYDIS_CONVERSION_MODE_INVALID) || 2509 (request->mvex.rounding != ZYDIS_ROUNDING_MODE_INVALID) || 2510 (request->mvex.swizzle != ZYDIS_SWIZZLE_MODE_INVALID) || 2511 (request->mvex.sae)) 2512 { 2513 return ZYAN_FALSE; 2514 } 2515 if ((request->mvex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) && 2516 (request->mvex.broadcast != ZYDIS_BROADCAST_MODE_1_TO_8) && 2517 (request->mvex.broadcast != ZYDIS_BROADCAST_MODE_4_TO_8)) 2518 { 2519 return ZYAN_FALSE; 2520 } 2521 break; 2522 case ZYDIS_MVEX_FUNC_UF_32: 2523 case ZYDIS_MVEX_FUNC_DF_32: 2524 if ((request->mvex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) || 2525 (request->mvex.rounding != ZYDIS_ROUNDING_MODE_INVALID) || 2526 (request->mvex.swizzle != ZYDIS_SWIZZLE_MODE_INVALID) || 2527 (request->mvex.sae)) 2528 { 2529 return ZYAN_FALSE; 2530 } 2531 break; 2532 case ZYDIS_MVEX_FUNC_UI_32: 2533 case ZYDIS_MVEX_FUNC_DI_32: 2534 if ((request->mvex.broadcast != ZYDIS_BROADCAST_MODE_INVALID) || 2535 (request->mvex.rounding != ZYDIS_ROUNDING_MODE_INVALID) || 2536 (request->mvex.swizzle != ZYDIS_SWIZZLE_MODE_INVALID) || 2537 (request->mvex.sae)) 2538 { 2539 return ZYAN_FALSE; 2540 } 2541 if ((request->mvex.conversion != ZYDIS_CONVERSION_MODE_INVALID) && 2542 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_UINT8) && 2543 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_SINT8) && 2544 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_UINT16) && 2545 (request->mvex.conversion != ZYDIS_CONVERSION_MODE_SINT16)) 2546 { 2547 return ZYAN_FALSE; 2548 } 2549 break; 2550 default: 2551 ZYAN_UNREACHABLE; 2552 } 2553 2554 return ZYAN_TRUE; 2555 } 2556 2557 /** 2558 * Checks if operands specified in encoder request satisfy additional constraints mandated by 2559 * matched instruction definition. 2560 * 2561 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 2562 * 2563 * @return True if operands passed the checks, false otherwise. 2564 */ 2565 static ZyanBool ZydisCheckConstraints(const ZydisEncoderInstructionMatch *match) 2566 { 2567 const ZydisEncoderOperand *operands = match->request->operands; 2568 ZyanBool is_gather = ZYAN_FALSE; 2569 switch (match->definition->encoding) 2570 { 2571 case ZYDIS_INSTRUCTION_ENCODING_VEX: 2572 { 2573 const ZydisInstructionDefinitionVEX *vex_def = 2574 (const ZydisInstructionDefinitionVEX *)match->base_definition; 2575 if (vex_def->is_gather) 2576 { 2577 ZYAN_ASSERT(match->request->operand_count == 3); 2578 ZYAN_ASSERT(operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER); 2579 ZYAN_ASSERT(operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY); 2580 ZYAN_ASSERT(operands[2].type == ZYDIS_OPERAND_TYPE_REGISTER); 2581 const ZyanI8 dest = ZydisRegisterGetId(operands[0].reg.value); 2582 const ZyanI8 index = ZydisRegisterGetId(operands[1].mem.index); 2583 const ZyanI8 mask = ZydisRegisterGetId(operands[2].reg.value); 2584 // If any pair of the index, mask, or destination registers are the same, the 2585 // instruction results a UD fault. 2586 if ((dest == index) || (dest == mask) || (index == mask)) 2587 { 2588 return ZYAN_FALSE; 2589 } 2590 } 2591 2592 if (vex_def->no_source_source_match) 2593 { 2594 ZYAN_ASSERT(match->request->operand_count == 3); 2595 ZYAN_ASSERT(operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER); 2596 ZYAN_ASSERT(operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER); 2597 ZYAN_ASSERT(operands[2].type == ZYDIS_OPERAND_TYPE_REGISTER); 2598 const ZydisRegister dest = operands[0].reg.value; 2599 const ZydisRegister source1 = operands[1].reg.value; 2600 const ZydisRegister source2 = operands[2].reg.value; 2601 // AMX-E4: #UD if srcdest == src1 OR src1 == src2 OR srcdest == src2. 2602 if ((dest == source1) || (source1 == source2) || (dest == source2)) 2603 { 2604 return ZYAN_FALSE; 2605 } 2606 } 2607 2608 return ZYAN_TRUE; 2609 } 2610 case ZYDIS_INSTRUCTION_ENCODING_EVEX: 2611 { 2612 const ZydisInstructionDefinitionEVEX *evex_def = 2613 (const ZydisInstructionDefinitionEVEX *)match->base_definition; 2614 is_gather = evex_def->is_gather; 2615 if (evex_def->no_source_dest_match) 2616 { 2617 ZYAN_ASSERT(operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER); 2618 ZYAN_ASSERT(operands[2].type == ZYDIS_OPERAND_TYPE_REGISTER); 2619 ZYAN_ASSERT((operands[3].type == ZYDIS_OPERAND_TYPE_REGISTER) || 2620 (operands[3].type == ZYDIS_OPERAND_TYPE_MEMORY)); 2621 const ZydisRegister dest = operands[0].reg.value; 2622 const ZydisRegister source1 = operands[2].reg.value; 2623 const ZydisRegister source2 = (operands[3].type == ZYDIS_OPERAND_TYPE_REGISTER) 2624 ? operands[3].reg.value 2625 : ZYDIS_REGISTER_NONE; 2626 2627 if ((dest == source1) || (dest == source2)) 2628 { 2629 return ZYAN_FALSE; 2630 } 2631 } 2632 break; 2633 } 2634 case ZYDIS_INSTRUCTION_ENCODING_MVEX: 2635 { 2636 const ZydisInstructionDefinitionMVEX *mvex_def = 2637 (const ZydisInstructionDefinitionMVEX *)match->base_definition; 2638 is_gather = mvex_def->is_gather; 2639 break; 2640 } 2641 default: 2642 return ZYAN_TRUE; 2643 } 2644 2645 if ((is_gather) && (operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER)) 2646 { 2647 ZYAN_ASSERT(match->request->operand_count == 3); 2648 ZYAN_ASSERT(operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER); 2649 ZYAN_ASSERT(operands[2].type == ZYDIS_OPERAND_TYPE_MEMORY); 2650 const ZyanI8 dest = ZydisRegisterGetId(operands[0].reg.value); 2651 const ZyanI8 index = ZydisRegisterGetId(operands[2].mem.index); 2652 // EVEX: The instruction will #UD fault if the destination vector zmm1 is the same as 2653 // index vector VINDEX. 2654 // MVEX: The KNC GATHER instructions forbid using the same vector register for destination 2655 // and for the index. (https://github.com/intelxed/xed/issues/281#issuecomment-970074554) 2656 if (dest == index) 2657 { 2658 return ZYAN_FALSE; 2659 } 2660 } 2661 2662 return ZYAN_TRUE; 2663 } 2664 2665 /** 2666 * Checks if operands and encoding-specific features from `ZydisEncoderRequest` match 2667 * encoder's instruction definition. 2668 * 2669 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 2670 * @param request A pointer to `ZydisEncoderRequest` struct. 2671 * 2672 * @return True if definition is compatible, false otherwise. 2673 */ 2674 static ZyanBool ZydisIsDefinitionCompatible(ZydisEncoderInstructionMatch *match, 2675 const ZydisEncoderRequest *request) 2676 { 2677 ZYAN_ASSERT(request->operand_count == match->base_definition->operand_count_visible); 2678 match->operands = ZydisGetOperandDefinitions(match->base_definition); 2679 2680 if (!ZydisAreEvexFeaturesCompatible(match, request)) 2681 { 2682 return ZYAN_FALSE; 2683 } 2684 if (!ZydisAreMvexFeaturesCompatible(match, request)) 2685 { 2686 return ZYAN_FALSE; 2687 } 2688 2689 for (ZyanU8 i = 0; i < request->operand_count; ++i) 2690 { 2691 const ZydisEncoderOperand *user_op = &request->operands[i]; 2692 const ZydisOperandDefinition *def_op = &match->operands[i]; 2693 ZYAN_ASSERT(def_op->visibility != ZYDIS_OPERAND_VISIBILITY_HIDDEN); 2694 ZyanBool is_compatible = ZYAN_FALSE; 2695 switch (user_op->type) 2696 { 2697 case ZYDIS_OPERAND_TYPE_REGISTER: 2698 is_compatible = ZydisIsRegisterOperandCompatible(match, user_op, def_op); 2699 break; 2700 case ZYDIS_OPERAND_TYPE_MEMORY: 2701 is_compatible = ZydisIsMemoryOperandCompatible(match, user_op, def_op); 2702 break; 2703 case ZYDIS_OPERAND_TYPE_POINTER: 2704 is_compatible = ZydisIsPointerOperandCompatible(match, user_op); 2705 break; 2706 case ZYDIS_OPERAND_TYPE_IMMEDIATE: 2707 is_compatible = ZydisIsImmediateOperandCompabile(match, user_op, def_op); 2708 break; 2709 default: 2710 ZYAN_UNREACHABLE; 2711 } 2712 2713 if (!is_compatible) 2714 { 2715 return ZYAN_FALSE; 2716 } 2717 } 2718 2719 ZyanU8 eosz = 0; 2720 if (match->base_definition->branch_type != ZYDIS_BRANCH_TYPE_NONE) 2721 { 2722 switch (request->branch_width) 2723 { 2724 case ZYDIS_BRANCH_WIDTH_NONE: 2725 break; 2726 case ZYDIS_BRANCH_WIDTH_8: 2727 if ((!match->has_rel_operand) || 2728 (match->base_definition->branch_type != ZYDIS_BRANCH_TYPE_SHORT)) 2729 { 2730 return ZYAN_FALSE; 2731 } 2732 break; 2733 case ZYDIS_BRANCH_WIDTH_16: 2734 eosz = 16; 2735 break; 2736 case ZYDIS_BRANCH_WIDTH_32: 2737 eosz = ((match->has_rel_operand) && 2738 (match->request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) && 2739 (match->base_definition->operand_size_map == ZYDIS_OPSIZE_MAP_FORCE64)) 2740 ? 64 2741 : 32; 2742 break; 2743 case ZYDIS_BRANCH_WIDTH_64: 2744 if (match->has_rel_operand) 2745 { 2746 return ZYAN_FALSE; 2747 } 2748 eosz = 64; 2749 break; 2750 default: 2751 ZYAN_UNREACHABLE; 2752 } 2753 } 2754 if (eosz) 2755 { 2756 if (match->eosz != 0) 2757 { 2758 if (match->eosz != eosz) 2759 { 2760 return ZYAN_FALSE; 2761 } 2762 } 2763 else 2764 { 2765 match->eosz = eosz; 2766 } 2767 } 2768 2769 if (!ZydisCheckConstraints(match)) 2770 { 2771 return ZYAN_FALSE; 2772 } 2773 2774 return ZYAN_TRUE; 2775 } 2776 2777 /** 2778 * Checks if requested set of prefixes is compatible with instruction definition. 2779 * 2780 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 2781 * 2782 * @return A zyan status code. 2783 */ 2784 static ZyanBool ZydisArePrefixesCompatible(const ZydisEncoderInstructionMatch *match) 2785 { 2786 // Early-exit optimization for when no prefixes are requested at all. 2787 if (!(match->attributes & ZYDIS_ENCODABLE_PREFIXES)) 2788 { 2789 return ZYAN_TRUE; 2790 } 2791 2792 if ((!match->base_definition->accepts_segment) && 2793 (match->attributes & ZYDIS_ATTRIB_HAS_SEGMENT)) 2794 { 2795 return ZYAN_FALSE; 2796 } 2797 if (match->definition->encoding != ZYDIS_INSTRUCTION_ENCODING_LEGACY) 2798 { 2799 return !(match->attributes & ZYDIS_ENCODABLE_PREFIXES_NO_SEGMENTS); 2800 } 2801 2802 const ZydisInstructionDefinitionLEGACY *legacy_def = 2803 (const ZydisInstructionDefinitionLEGACY *)match->base_definition; 2804 if ((!legacy_def->accepts_LOCK) && 2805 (match->attributes & ZYDIS_ATTRIB_HAS_LOCK)) 2806 { 2807 return ZYAN_FALSE; 2808 } 2809 if ((!legacy_def->accepts_REP) && 2810 (match->attributes & ZYDIS_ATTRIB_HAS_REP)) 2811 { 2812 return ZYAN_FALSE; 2813 } 2814 if ((!legacy_def->accepts_REPEREPZ) && 2815 (match->attributes & ZYDIS_ATTRIB_HAS_REPE)) 2816 { 2817 return ZYAN_FALSE; 2818 } 2819 if ((!legacy_def->accepts_REPNEREPNZ) && 2820 (match->attributes & ZYDIS_ATTRIB_HAS_REPNE)) 2821 { 2822 return ZYAN_FALSE; 2823 } 2824 if ((!legacy_def->accepts_BOUND) && 2825 (match->attributes & ZYDIS_ATTRIB_HAS_BND)) 2826 { 2827 return ZYAN_FALSE; 2828 } 2829 if ((!legacy_def->accepts_XACQUIRE) && 2830 (match->attributes & ZYDIS_ATTRIB_HAS_XACQUIRE)) 2831 { 2832 return ZYAN_FALSE; 2833 } 2834 if ((!legacy_def->accepts_XRELEASE) && 2835 (match->attributes & ZYDIS_ATTRIB_HAS_XRELEASE)) 2836 { 2837 return ZYAN_FALSE; 2838 } 2839 if ((!legacy_def->accepts_branch_hints) && 2840 (match->attributes & (ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN | 2841 ZYDIS_ATTRIB_HAS_BRANCH_TAKEN))) 2842 { 2843 return ZYAN_FALSE; 2844 } 2845 if ((!legacy_def->accepts_NOTRACK) && 2846 (match->attributes & ZYDIS_ATTRIB_HAS_NOTRACK)) 2847 { 2848 return ZYAN_FALSE; 2849 } 2850 if ((!legacy_def->accepts_hle_without_lock) && 2851 (match->attributes & (ZYDIS_ATTRIB_HAS_XACQUIRE | 2852 ZYDIS_ATTRIB_HAS_XRELEASE)) && 2853 !(match->attributes & ZYDIS_ATTRIB_HAS_LOCK)) 2854 { 2855 return ZYAN_FALSE; 2856 } 2857 2858 return ZYAN_TRUE; 2859 } 2860 2861 /** 2862 * Returns operand mask containing information about operand count and types in a compressed form. 2863 * 2864 * @param request A pointer to `ZydisEncoderRequest` struct. 2865 * 2866 * @return Operand mask. 2867 */ 2868 static ZyanU16 ZydisGetOperandMask(const ZydisEncoderRequest *request) 2869 { 2870 ZyanU16 operand_mask = request->operand_count; 2871 ZyanU8 bit_offset = ZYAN_BITS_TO_REPRESENT(ZYDIS_ENCODER_MAX_OPERANDS); 2872 for (ZyanU8 i = 0; i < request->operand_count; ++i) 2873 { 2874 operand_mask |= (request->operands[i].type - ZYDIS_OPERAND_TYPE_REGISTER) << bit_offset; 2875 bit_offset += ZYAN_BITS_TO_REPRESENT( 2876 ZYDIS_OPERAND_TYPE_MAX_VALUE - ZYDIS_OPERAND_TYPE_REGISTER); 2877 } 2878 2879 return operand_mask; 2880 } 2881 2882 /** 2883 * Handles optimization opportunities indicated by `swappable` field in instruction definition 2884 * structure. See `ZydisEncodableInstruction` for more information. 2885 * 2886 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 2887 * 2888 * @return True if definition has been swapped, false otherwise. 2889 */ 2890 static ZyanBool ZydisHandleSwappableDefinition(ZydisEncoderInstructionMatch *match) 2891 { 2892 if (!match->definition->swappable) 2893 { 2894 return ZYAN_FALSE; 2895 } 2896 2897 // Special case for ISA-wide unique conflict between two `mov` variants 2898 // mov gpr16_32_64(encoding=opcode), imm(encoding=simm16_32_64,scale_factor=osz) 2899 // mov gpr16_32_64(encoding=modrm_rm), imm(encoding=simm16_32_32,scale_factor=osz) 2900 if (match->request->mnemonic == ZYDIS_MNEMONIC_MOV) 2901 { 2902 const ZyanU8 imm_size = ZydisGetSignedImmSize(match->request->operands[1].imm.s); 2903 if ((match->request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) && 2904 (match->eosz == 64) && 2905 (imm_size < 64)) 2906 { 2907 return ZYAN_TRUE; 2908 } 2909 } 2910 2911 ZYAN_ASSERT((match->request->operand_count == 2) || (match->request->operand_count == 3)); 2912 const ZyanU8 src_index = (match->request->operand_count == 3) ? 2 : 1; 2913 const ZyanI8 dest_id = ZydisRegisterGetId(match->request->operands[0].reg.value); 2914 const ZyanI8 src_id = ZydisRegisterGetId(match->request->operands[src_index].reg.value); 2915 if ((dest_id <= 7) && (src_id > 7)) 2916 { 2917 ++match->definition; 2918 ZydisGetInstructionDefinition(match->definition->encoding, 2919 match->definition->instruction_reference, &match->base_definition); 2920 match->operands = ZydisGetOperandDefinitions(match->base_definition); 2921 return ZYAN_TRUE; 2922 } 2923 2924 return ZYAN_FALSE; 2925 } 2926 2927 /** 2928 * This function attempts to find a matching instruction definition for provided encoder request. 2929 * 2930 * @param request A pointer to `ZydisEncoderRequest` struct. 2931 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 2932 * 2933 * @return A zyan status code. 2934 */ 2935 static ZyanStatus ZydisFindMatchingDefinition(const ZydisEncoderRequest *request, 2936 ZydisEncoderInstructionMatch *match) 2937 { 2938 ZYAN_MEMSET(match, 0, sizeof(ZydisEncoderInstructionMatch)); 2939 match->request = request; 2940 match->attributes = request->prefixes; 2941 2942 const ZydisEncodableInstruction *definition = ZYAN_NULL; 2943 const ZyanU8 definition_count = ZydisGetEncodableInstructions(request->mnemonic, &definition); 2944 ZYAN_ASSERT(definition && definition_count); 2945 const ZydisWidthFlag mode_width = ZydisGetMachineModeWidth(request->machine_mode) >> 4; 2946 const ZyanBool is_compat = 2947 (request->machine_mode == ZYDIS_MACHINE_MODE_LONG_COMPAT_16) || 2948 (request->machine_mode == ZYDIS_MACHINE_MODE_LONG_COMPAT_32); 2949 const ZyanU8 default_asz = ZydisGetAszFromHint(request->address_size_hint); 2950 const ZyanU8 default_osz = ZydisGetOszFromHint(request->operand_size_hint); 2951 const ZyanU16 operand_mask = ZydisGetOperandMask(request); 2952 2953 for (ZyanU8 i = 0; i < definition_count; ++i, ++definition) 2954 { 2955 if (definition->operand_mask != operand_mask) 2956 { 2957 continue; 2958 } 2959 const ZydisInstructionDefinition *base_definition = ZYAN_NULL; 2960 ZydisGetInstructionDefinition(definition->encoding, definition->instruction_reference, 2961 &base_definition); 2962 if (!(definition->modes & mode_width)) 2963 { 2964 continue; 2965 } 2966 if ((request->allowed_encodings != ZYDIS_ENCODABLE_ENCODING_DEFAULT) && 2967 !(ZydisGetEncodableEncoding(definition->encoding) & request->allowed_encodings)) 2968 { 2969 continue; 2970 } 2971 if (request->machine_mode == ZYDIS_MACHINE_MODE_REAL_16) 2972 { 2973 if (base_definition->requires_protected_mode) 2974 { 2975 continue; 2976 } 2977 switch (definition->encoding) 2978 { 2979 case ZYDIS_INSTRUCTION_ENCODING_XOP: 2980 case ZYDIS_INSTRUCTION_ENCODING_VEX: 2981 case ZYDIS_INSTRUCTION_ENCODING_EVEX: 2982 case ZYDIS_INSTRUCTION_ENCODING_MVEX: 2983 continue; 2984 default: 2985 break; 2986 } 2987 } 2988 else if ((request->machine_mode != ZYDIS_MACHINE_MODE_LONG_64) && 2989 (definition->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)) 2990 { 2991 continue; 2992 } 2993 if (is_compat && base_definition->no_compat_mode) 2994 { 2995 continue; 2996 } 2997 if ((request->branch_type != ZYDIS_BRANCH_TYPE_NONE) && 2998 (request->branch_type != base_definition->branch_type)) 2999 { 3000 continue; 3001 } 3002 if ((base_definition->branch_type == ZYDIS_BRANCH_TYPE_NONE) && 3003 (request->branch_width != ZYDIS_BRANCH_WIDTH_NONE)) 3004 { 3005 continue; 3006 } 3007 3008 match->definition = definition; 3009 match->base_definition = base_definition; 3010 match->operands = ZYAN_NULL; 3011 match->easz = definition->accepts_hint == ZYDIS_SIZE_HINT_ASZ ? default_asz : 0; 3012 match->eosz = definition->accepts_hint == ZYDIS_SIZE_HINT_OSZ ? default_osz : 0; 3013 match->disp_size = match->imm_size = match->cd8_scale = 0; 3014 match->rex_type = ZYDIS_REX_TYPE_UNKNOWN; 3015 match->eosz64_forbidden = ZYAN_FALSE; 3016 match->has_rel_operand = ZYAN_FALSE; 3017 if ((base_definition->operand_size_map != ZYDIS_OPSIZE_MAP_BYTEOP) && 3018 (match->eosz == 8)) 3019 { 3020 continue; 3021 } 3022 if (!ZydisArePrefixesCompatible(match)) 3023 { 3024 continue; 3025 } 3026 if (!ZydisIsDefinitionCompatible(match, request)) 3027 { 3028 continue; 3029 } 3030 if (ZydisHandleSwappableDefinition(match)) 3031 { 3032 if (definition == match->definition) 3033 { 3034 continue; 3035 } 3036 ++i; 3037 definition = match->definition; 3038 base_definition = match->base_definition; 3039 } 3040 3041 if (match->easz == 0) 3042 { 3043 if (definition->address_sizes & mode_width) 3044 { 3045 match->easz = (ZyanU8)(mode_width << 4); 3046 } 3047 else if (mode_width == ZYDIS_WIDTH_16) 3048 { 3049 match->easz = 32; 3050 } 3051 else if (mode_width == ZYDIS_WIDTH_32) 3052 { 3053 match->easz = 16; 3054 } 3055 else 3056 { 3057 match->easz = 32; 3058 } 3059 ZYAN_ASSERT(definition->address_sizes & (match->easz >> 4)); 3060 } 3061 else if (!(definition->address_sizes & (match->easz >> 4))) 3062 { 3063 continue; 3064 } 3065 3066 if (mode_width == ZYDIS_WIDTH_64) 3067 { 3068 if (base_definition->operand_size_map == ZYDIS_OPSIZE_MAP_DEFAULT64) 3069 { 3070 if (match->eosz == 0) 3071 { 3072 ZYAN_ASSERT(definition->operand_sizes & (ZYDIS_WIDTH_16 | ZYDIS_WIDTH_64)); 3073 if (definition->operand_sizes & ZYDIS_WIDTH_64) 3074 { 3075 match->eosz = 64; 3076 } 3077 else 3078 { 3079 match->eosz = 16; 3080 } 3081 } 3082 else if (match->eosz == 32) 3083 { 3084 continue; 3085 } 3086 } 3087 else if (base_definition->operand_size_map == ZYDIS_OPSIZE_MAP_FORCE64) 3088 { 3089 if (match->eosz == 0) 3090 { 3091 match->eosz = 64; 3092 } 3093 else if (match->eosz != 64) 3094 { 3095 continue; 3096 } 3097 } 3098 } 3099 if (match->eosz == 0) 3100 { 3101 const ZydisWidthFlag default_width = (mode_width == ZYDIS_WIDTH_64) 3102 ? ZYDIS_WIDTH_32 3103 : mode_width; 3104 if (definition->operand_sizes & default_width) 3105 { 3106 match->eosz = (ZyanU8)(default_width << 4); 3107 } 3108 else if (definition->operand_sizes & ZYDIS_WIDTH_16) 3109 { 3110 match->eosz = 16; 3111 } 3112 else if (definition->operand_sizes & ZYDIS_WIDTH_32) 3113 { 3114 match->eosz = 32; 3115 } 3116 else 3117 { 3118 match->eosz = 64; 3119 } 3120 } 3121 else if (match->eosz64_forbidden && match->eosz == 64) 3122 { 3123 continue; 3124 } 3125 else if (!(definition->operand_sizes & (match->eosz >> 4))) 3126 { 3127 continue; 3128 } 3129 3130 return ZYAN_STATUS_SUCCESS; 3131 } 3132 3133 return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; 3134 } 3135 3136 /** 3137 * Emits unsigned integer value. 3138 * 3139 * @param data Value to emit. 3140 * @param size Value size in bytes. 3141 * @param buffer A pointer to `ZydisEncoderBuffer` struct. 3142 * 3143 * @return A zyan status code. 3144 */ 3145 static ZyanStatus ZydisEmitUInt(ZyanU64 data, ZyanU8 size, ZydisEncoderBuffer *buffer) 3146 { 3147 ZYAN_ASSERT(size == 1 || size == 2 || size == 4 || size == 8); 3148 3149 const ZyanUSize new_offset = buffer->offset + size; 3150 if (new_offset > buffer->size) 3151 { 3152 return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; 3153 } 3154 3155 // TODO: fix for big-endian systems 3156 // The size variable is not passed on purpose to allow the compiler 3157 // to generate better code with a known size at compile time. 3158 if (size == 1) 3159 { 3160 ZYAN_MEMCPY(buffer->buffer + buffer->offset, &data, 1); 3161 } 3162 else if (size == 2) 3163 { 3164 ZYAN_MEMCPY(buffer->buffer + buffer->offset, &data, 2); 3165 } 3166 else if (size == 4) 3167 { 3168 ZYAN_MEMCPY(buffer->buffer + buffer->offset, &data, 4); 3169 } 3170 else if (size == 8) 3171 { 3172 ZYAN_MEMCPY(buffer->buffer + buffer->offset, &data, 8); 3173 } 3174 else 3175 { 3176 ZYAN_UNREACHABLE; 3177 } 3178 3179 buffer->offset = new_offset; 3180 return ZYAN_STATUS_SUCCESS; 3181 } 3182 3183 /** 3184 * Emits a single byte. 3185 * 3186 * @param byte Value to emit. 3187 * @param buffer A pointer to `ZydisEncoderBuffer` struct. 3188 * 3189 * @return A zyan status code. 3190 */ 3191 static ZyanStatus ZydisEmitByte(ZyanU8 byte, ZydisEncoderBuffer *buffer) 3192 { 3193 return ZydisEmitUInt(byte, 1, buffer); 3194 } 3195 3196 /** 3197 * Emits legact prefixes. 3198 * 3199 * @param instruction A pointer to `ZydisEncoderInstruction` struct. 3200 * @param buffer A pointer to `ZydisEncoderBuffer` struct. 3201 * 3202 * @return A zyan status code. 3203 */ 3204 static ZyanStatus ZydisEmitLegacyPrefixes(const ZydisEncoderInstruction *instruction, 3205 ZydisEncoderBuffer *buffer) 3206 { 3207 ZyanBool compressed_prefixes = ZYAN_FALSE; 3208 switch (instruction->encoding) 3209 { 3210 case ZYDIS_INSTRUCTION_ENCODING_XOP: 3211 case ZYDIS_INSTRUCTION_ENCODING_VEX: 3212 case ZYDIS_INSTRUCTION_ENCODING_EVEX: 3213 case ZYDIS_INSTRUCTION_ENCODING_MVEX: 3214 compressed_prefixes = ZYAN_TRUE; 3215 break; 3216 default: 3217 break; 3218 } 3219 3220 // Group 1 3221 if (instruction->attributes & ZYDIS_ATTRIB_HAS_LOCK) 3222 { 3223 ZYAN_CHECK(ZydisEmitByte(0xF0, buffer)); 3224 } 3225 if (!compressed_prefixes) 3226 { 3227 if (instruction->attributes & (ZYDIS_ATTRIB_HAS_REPNE | 3228 ZYDIS_ATTRIB_HAS_BND | 3229 ZYDIS_ATTRIB_HAS_XACQUIRE)) 3230 { 3231 ZYAN_CHECK(ZydisEmitByte(0xF2, buffer)); 3232 } 3233 if (instruction->attributes & (ZYDIS_ATTRIB_HAS_REP | 3234 ZYDIS_ATTRIB_HAS_REPE | 3235 ZYDIS_ATTRIB_HAS_XRELEASE)) 3236 { 3237 ZYAN_CHECK(ZydisEmitByte(0xF3, buffer)); 3238 } 3239 } 3240 3241 // Group 2 3242 if (instruction->attributes & (ZYDIS_ATTRIB_HAS_SEGMENT_CS | 3243 ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN)) 3244 { 3245 ZYAN_CHECK(ZydisEmitByte(0x2E, buffer)); 3246 } 3247 if (instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_SS) 3248 { 3249 ZYAN_CHECK(ZydisEmitByte(0x36, buffer)); 3250 } 3251 if (instruction->attributes & (ZYDIS_ATTRIB_HAS_SEGMENT_DS | 3252 ZYDIS_ATTRIB_HAS_BRANCH_TAKEN)) 3253 { 3254 ZYAN_CHECK(ZydisEmitByte(0x3E, buffer)); 3255 } 3256 if (instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_ES) 3257 { 3258 ZYAN_CHECK(ZydisEmitByte(0x26, buffer)); 3259 } 3260 if (instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_FS) 3261 { 3262 ZYAN_CHECK(ZydisEmitByte(0x64, buffer)); 3263 } 3264 if (instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_GS) 3265 { 3266 ZYAN_CHECK(ZydisEmitByte(0x65, buffer)); 3267 } 3268 if (instruction->attributes & ZYDIS_ATTRIB_HAS_NOTRACK) 3269 { 3270 ZYAN_CHECK(ZydisEmitByte(0x3E, buffer)); 3271 } 3272 3273 // Group 3 3274 if (!compressed_prefixes) 3275 { 3276 if (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE) 3277 { 3278 ZYAN_CHECK(ZydisEmitByte(0x66, buffer)); 3279 } 3280 } 3281 3282 // Group 4 3283 if (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE) 3284 { 3285 ZYAN_CHECK(ZydisEmitByte(0x67, buffer)); 3286 } 3287 3288 return ZYAN_STATUS_SUCCESS; 3289 } 3290 3291 /** 3292 * Encodes low nibble of `REX` prefix. 3293 * 3294 * @param instruction A pointer to `ZydisEncoderInstruction` struct. 3295 * @param high_r A pointer to `ZyanBool` variable that will be set to true when the 3296 * highest `ModR/M.reg` bit cannot be encoded using `REX` prefix. 3297 * 3298 * @return A zyan status code. 3299 */ 3300 static ZyanU8 ZydisEncodeRexLowNibble(const ZydisEncoderInstruction *instruction, ZyanBool *high_r) 3301 { 3302 if (high_r) 3303 { 3304 *high_r = ZYAN_FALSE; 3305 } 3306 3307 ZyanU8 rex = 0; 3308 if ((instruction->attributes & ZYDIS_ATTRIB_HAS_MODRM) && 3309 (instruction->attributes & ZYDIS_ATTRIB_HAS_SIB)) 3310 { 3311 if (instruction->base & 0x08) 3312 { 3313 rex |= 1; 3314 } 3315 if (instruction->index & 0x08) 3316 { 3317 rex |= 2; 3318 } 3319 if (instruction->reg & 0x08) 3320 { 3321 rex |= 4; 3322 } 3323 if (high_r && (instruction->reg & 0x10)) 3324 { 3325 *high_r = ZYAN_TRUE; 3326 } 3327 } 3328 else if (instruction->attributes & ZYDIS_ATTRIB_HAS_MODRM) 3329 { 3330 if (instruction->rm & 0x08) 3331 { 3332 rex |= 1; 3333 } 3334 if (instruction->rm & 0x10) 3335 { 3336 rex |= 2; 3337 } 3338 if (instruction->reg & 0x08) 3339 { 3340 rex |= 4; 3341 } 3342 if (high_r && (instruction->reg & 0x10)) 3343 { 3344 *high_r = ZYAN_TRUE; 3345 } 3346 } 3347 else 3348 { 3349 if (instruction->rm & 0x08) 3350 { 3351 rex |= 1; 3352 } 3353 } 3354 3355 if (instruction->rex_w) 3356 { 3357 rex |= 8; 3358 } 3359 3360 return rex; 3361 } 3362 3363 /** 3364 * Emits `REX` prefix. 3365 * 3366 * @param instruction A pointer to `ZydisEncoderInstruction` struct. 3367 * @param buffer A pointer to `ZydisEncoderBuffer` struct. 3368 * 3369 * @return A zyan status code. 3370 */ 3371 static ZyanStatus ZydisEmitRex(const ZydisEncoderInstruction *instruction, 3372 ZydisEncoderBuffer *buffer) 3373 { 3374 const ZyanU8 rex = ZydisEncodeRexLowNibble(instruction, ZYAN_NULL); 3375 if (rex || (instruction->attributes & ZYDIS_ATTRIB_HAS_REX)) 3376 { 3377 ZYAN_CHECK(ZydisEmitByte(0x40 | rex, buffer)); 3378 } 3379 3380 return ZYAN_STATUS_SUCCESS; 3381 } 3382 3383 /** 3384 * Encodes common parts of `VEX` prefix. 3385 * 3386 * @param instruction A pointer to `ZydisEncoderInstruction` struct. 3387 * @param mmmmm A pointer to `ZyanU8` variable that will receive `VEX.mmmmm` 3388 * @param pp A pointer to `ZyanU8` variable that will receive `VEX.pp` 3389 * @param vvvv A pointer to `ZyanU8` variable that will receive `VEX.vvvv` 3390 * @param rex A pointer to `ZyanU8` variable that will receive 'REX` 3391 * @param high_r A pointer to `ZyanBool` variable that will be set to true when the 3392 * highest `ModR/M.reg` bit cannot be encoded using `REX` prefix. 3393 */ 3394 static void ZydisEncodeVexCommons(ZydisEncoderInstruction *instruction, ZyanU8 *mmmmm, ZyanU8 *pp, 3395 ZyanU8 *vvvv, ZyanU8 *rex, ZyanBool *high_r) 3396 { 3397 switch (instruction->opcode_map) 3398 { 3399 case ZYDIS_OPCODE_MAP_DEFAULT: 3400 case ZYDIS_OPCODE_MAP_0F: 3401 case ZYDIS_OPCODE_MAP_0F38: 3402 case ZYDIS_OPCODE_MAP_0F3A: 3403 case ZYDIS_OPCODE_MAP_MAP5: 3404 case ZYDIS_OPCODE_MAP_MAP6: 3405 *mmmmm = (ZyanU8)instruction->opcode_map; 3406 break; 3407 case ZYDIS_OPCODE_MAP_XOP8: 3408 case ZYDIS_OPCODE_MAP_XOP9: 3409 case ZYDIS_OPCODE_MAP_XOPA: 3410 *mmmmm = 8 + ((ZyanU8)instruction->opcode_map - ZYDIS_OPCODE_MAP_XOP8); 3411 break; 3412 default: 3413 ZYAN_UNREACHABLE; 3414 } 3415 instruction->opcode_map = ZYDIS_OPCODE_MAP_DEFAULT; 3416 3417 *pp = 0; 3418 if (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE) 3419 { 3420 *pp = 1; 3421 } 3422 else if (instruction->attributes & ZYDIS_ATTRIB_HAS_REP) 3423 { 3424 *pp = 2; 3425 } 3426 else if (instruction->attributes & ZYDIS_ATTRIB_HAS_REPNE) 3427 { 3428 *pp = 3; 3429 } 3430 3431 *vvvv = ~instruction->vvvv; 3432 *rex = ZydisEncodeRexLowNibble(instruction, high_r); 3433 } 3434 3435 /** 3436 * Emits `XOP` prefix. 3437 * 3438 * @param instruction A pointer to `ZydisEncoderInstruction` struct. 3439 * @param buffer A pointer to `ZydisEncoderBuffer` struct. 3440 * 3441 * @return A zyan status code. 3442 */ 3443 static ZyanStatus ZydisEmitXop(ZydisEncoderInstruction *instruction, ZydisEncoderBuffer *buffer) 3444 { 3445 ZyanU8 mmmmm, pp, vvvv, rex; 3446 ZydisEncodeVexCommons(instruction, &mmmmm, &pp, &vvvv, &rex, ZYAN_NULL); 3447 ZYAN_ASSERT(instruction->vector_length <= 1); 3448 const ZyanU8 b1 = (((~rex) & 0x07) << 5) | mmmmm; 3449 const ZyanU8 b2 = ((rex & 0x08) << 4) | ((vvvv & 0xF) << 3) | (instruction->vector_length << 2) | pp; 3450 ZYAN_CHECK(ZydisEmitByte(0x8F, buffer)); 3451 ZYAN_CHECK(ZydisEmitByte(b1, buffer)); 3452 ZYAN_CHECK(ZydisEmitByte(b2, buffer)); 3453 return ZYAN_STATUS_SUCCESS; 3454 } 3455 3456 /** 3457 * Emits `VEX` prefix. 3458 * 3459 * @param instruction A pointer to `ZydisEncoderInstruction` struct. 3460 * @param buffer A pointer to `ZydisEncoderBuffer` struct. 3461 * 3462 * @return A zyan status code. 3463 */ 3464 static ZyanStatus ZydisEmitVex(ZydisEncoderInstruction *instruction, ZydisEncoderBuffer *buffer) 3465 { 3466 ZyanU8 mmmmm, pp, vvvv, rex; 3467 ZydisEncodeVexCommons(instruction, &mmmmm, &pp, &vvvv, &rex, ZYAN_NULL); 3468 ZYAN_ASSERT(instruction->vector_length <= 1); 3469 if (mmmmm != 1 || (rex & 0x0B)) 3470 { 3471 const ZyanU8 b1 = (((~rex) & 0x07) << 5) | mmmmm; 3472 const ZyanU8 b2 = ((rex & 0x08) << 4) | 3473 ((vvvv & 0xF) << 3) | 3474 (instruction->vector_length << 2) | 3475 pp; 3476 ZYAN_CHECK(ZydisEmitByte(0xC4, buffer)); 3477 ZYAN_CHECK(ZydisEmitByte(b1, buffer)); 3478 ZYAN_CHECK(ZydisEmitByte(b2, buffer)); 3479 } 3480 else 3481 { 3482 const ZyanU8 b1 = (((~rex) & 0x04) << 5) | 3483 ((vvvv & 0xF) << 3) | 3484 (instruction->vector_length << 2) | 3485 pp; 3486 ZYAN_CHECK(ZydisEmitByte(0xC5, buffer)); 3487 ZYAN_CHECK(ZydisEmitByte(b1, buffer)); 3488 } 3489 3490 return ZYAN_STATUS_SUCCESS; 3491 } 3492 3493 /** 3494 * Encodes common parts of `EVEX` prefix. 3495 * 3496 * @param instruction A pointer to `ZydisEncoderInstruction` struct. 3497 * @param p0 A pointer to `ZyanU8` variable that will receive 2nd byte of `EVEX` prefix. 3498 * @param p1 A pointer to `ZyanU8` variable that will receive 3rd byte of `EVEX` prefix. 3499 * @param vvvvv A pointer to `ZyanU8` variable that will receive `EVEX.vvvvv`. 3500 */ 3501 static void ZydisEncodeEvexCommons(ZydisEncoderInstruction *instruction, ZyanU8 *p0, ZyanU8 *p1, 3502 ZyanU8 *vvvvv) 3503 { 3504 ZyanBool high_r; 3505 ZyanU8 mmmmm, pp, rex; 3506 ZydisEncodeVexCommons(instruction, &mmmmm, &pp, vvvvv, &rex, &high_r); 3507 *p0 = (((~rex) & 0x07) << 5) | mmmmm; 3508 if (!high_r) 3509 { 3510 *p0 |= 0x10; 3511 } 3512 *p1 = ((rex & 0x08) << 4) | ((*vvvvv & 0x0F) << 3) | 0x04 | pp; 3513 } 3514 3515 /** 3516 * Emits `EVEX` prefix. 3517 * 3518 * @param instruction A pointer to `ZydisEncoderInstruction` struct. 3519 * @param buffer A pointer to `ZydisEncoderBuffer` struct. 3520 * 3521 * @return A zyan status code. 3522 */ 3523 static ZyanStatus ZydisEmitEvex(ZydisEncoderInstruction *instruction, ZydisEncoderBuffer *buffer) 3524 { 3525 ZyanU8 p0, p1, vvvvv; 3526 ZydisEncodeEvexCommons(instruction, &p0, &p1, &vvvvv); 3527 ZyanU8 p2 = (instruction->vector_length << 5) | ((vvvvv & 0x10) >> 1) | instruction->mask; 3528 if (instruction->zeroing) 3529 { 3530 p2 |= 0x80; 3531 } 3532 if (instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX_B) 3533 { 3534 p2 |= 0x10; 3535 } 3536 if (instruction->index & 0x10) 3537 { 3538 p2 &= 0xF7; 3539 } 3540 3541 ZYAN_CHECK(ZydisEmitByte(0x62, buffer)); 3542 ZYAN_CHECK(ZydisEmitByte(p0, buffer)); 3543 ZYAN_CHECK(ZydisEmitByte(p1, buffer)); 3544 ZYAN_CHECK(ZydisEmitByte(p2, buffer)); 3545 return ZYAN_STATUS_SUCCESS; 3546 } 3547 3548 /** 3549 * Emits `MVEX` prefix. 3550 * 3551 * @param instruction A pointer to `ZydisEncoderInstruction` struct. 3552 * @param buffer A pointer to `ZydisEncoderBuffer` struct. 3553 * 3554 * @return A zyan status code. 3555 */ 3556 static ZyanStatus ZydisEmitMvex(ZydisEncoderInstruction *instruction, ZydisEncoderBuffer *buffer) 3557 { 3558 ZyanU8 p0, p1, vvvvv; 3559 ZydisEncodeEvexCommons(instruction, &p0, &p1, &vvvvv); 3560 ZyanU8 p2 = (instruction->sss << 4) | ((vvvvv & 0x10) >> 1) | instruction->mask; 3561 if (instruction->eviction_hint) 3562 { 3563 p2 |= 0x80; 3564 } 3565 if (instruction->index & 0x10) 3566 { 3567 p2 &= 0xF7; 3568 } 3569 3570 ZYAN_CHECK(ZydisEmitByte(0x62, buffer)); 3571 ZYAN_CHECK(ZydisEmitByte(p0, buffer)); 3572 ZYAN_CHECK(ZydisEmitByte(p1 & 0xFB, buffer)); 3573 ZYAN_CHECK(ZydisEmitByte(p2, buffer)); 3574 return ZYAN_STATUS_SUCCESS; 3575 } 3576 3577 /** 3578 * Emits instruction as stream of bytes. 3579 * 3580 * @param instruction A pointer to `ZydisEncoderInstruction` struct. 3581 * @param buffer A pointer to `ZydisEncoderBuffer` struct. 3582 * 3583 * @return A zyan status code. 3584 */ 3585 static ZyanStatus ZydisEmitInstruction(ZydisEncoderInstruction *instruction, 3586 ZydisEncoderBuffer *buffer) 3587 { 3588 ZYAN_CHECK(ZydisEmitLegacyPrefixes(instruction, buffer)); 3589 3590 switch (instruction->encoding) 3591 { 3592 case ZYDIS_INSTRUCTION_ENCODING_LEGACY: 3593 case ZYDIS_INSTRUCTION_ENCODING_3DNOW: 3594 ZYAN_CHECK(ZydisEmitRex(instruction, buffer)); 3595 break; 3596 case ZYDIS_INSTRUCTION_ENCODING_XOP: 3597 ZYAN_CHECK(ZydisEmitXop(instruction, buffer)); 3598 break; 3599 case ZYDIS_INSTRUCTION_ENCODING_VEX: 3600 ZYAN_CHECK(ZydisEmitVex(instruction, buffer)); 3601 break; 3602 case ZYDIS_INSTRUCTION_ENCODING_EVEX: 3603 ZYAN_CHECK(ZydisEmitEvex(instruction, buffer)); 3604 break; 3605 case ZYDIS_INSTRUCTION_ENCODING_MVEX: 3606 ZYAN_CHECK(ZydisEmitMvex(instruction, buffer)); 3607 break; 3608 default: 3609 ZYAN_UNREACHABLE; 3610 } 3611 3612 switch (instruction->opcode_map) 3613 { 3614 case ZYDIS_OPCODE_MAP_DEFAULT: 3615 break; 3616 case ZYDIS_OPCODE_MAP_0F: 3617 ZYAN_CHECK(ZydisEmitByte(0x0F, buffer)); 3618 break; 3619 case ZYDIS_OPCODE_MAP_0F38: 3620 ZYAN_CHECK(ZydisEmitByte(0x0F, buffer)); 3621 ZYAN_CHECK(ZydisEmitByte(0x38, buffer)); 3622 break; 3623 case ZYDIS_OPCODE_MAP_0F3A: 3624 ZYAN_CHECK(ZydisEmitByte(0x0F, buffer)); 3625 ZYAN_CHECK(ZydisEmitByte(0x3A, buffer)); 3626 break; 3627 case ZYDIS_OPCODE_MAP_0F0F: 3628 ZYAN_CHECK(ZydisEmitByte(0x0F, buffer)); 3629 ZYAN_CHECK(ZydisEmitByte(0x0F, buffer)); 3630 break; 3631 default: 3632 ZYAN_UNREACHABLE; 3633 } 3634 if (instruction->encoding != ZYDIS_INSTRUCTION_ENCODING_3DNOW) 3635 { 3636 ZYAN_CHECK(ZydisEmitByte(instruction->opcode, buffer)); 3637 } 3638 3639 if (instruction->attributes & ZYDIS_ATTRIB_HAS_MODRM) 3640 { 3641 const ZyanU8 modrm = (instruction->mod << 6) | 3642 ((instruction->reg & 7) << 3) | 3643 (instruction->rm & 7); 3644 ZYAN_CHECK(ZydisEmitByte(modrm, buffer)); 3645 } 3646 if (instruction->attributes & ZYDIS_ATTRIB_HAS_SIB) 3647 { 3648 const ZyanU8 sib = (instruction->scale << 6) | 3649 ((instruction->index & 7) << 3) | 3650 (instruction->base & 7); 3651 ZYAN_CHECK(ZydisEmitByte(sib, buffer)); 3652 } 3653 if (instruction->disp_size) 3654 { 3655 ZYAN_CHECK(ZydisEmitUInt(instruction->disp, instruction->disp_size / 8, buffer)); 3656 } 3657 if (instruction->imm_size) 3658 { 3659 ZYAN_CHECK(ZydisEmitUInt(instruction->imm, instruction->imm_size / 8, buffer)); 3660 } 3661 if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW) 3662 { 3663 ZYAN_CHECK(ZydisEmitByte(instruction->opcode, buffer)); 3664 } 3665 3666 return ZYAN_STATUS_SUCCESS; 3667 } 3668 3669 /** 3670 * Encodes register operand as fields inside `ZydisEncoderInstruction` structure. 3671 * 3672 * @param user_op Validated operand definition from `ZydisEncoderRequest` structure. 3673 * @param def_op Decoder's operand definition from instruction definition. 3674 * @param instruction A pointer to `ZydisEncoderInstruction` struct. 3675 */ 3676 static void ZydisBuildRegisterOperand(const ZydisEncoderOperand *user_op, 3677 const ZydisOperandDefinition *def_op, ZydisEncoderInstruction *instruction) 3678 { 3679 if (def_op->type == ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG) 3680 { 3681 return; 3682 } 3683 3684 ZyanU8 reg_id = 0; 3685 if (ZydisRegisterGetClass(user_op->reg.value) != ZYDIS_REGCLASS_GPR8) 3686 { 3687 reg_id = (ZyanU8)ZydisRegisterGetId(user_op->reg.value); 3688 } 3689 else 3690 { 3691 static const ZyanU8 reg8_lookup[] = { 3692 0, 1, 2, 3, // AL, CL, DL, BL 3693 4, 5, 6, 7, // AH, CH, DH, BH 3694 4, 5, 6, 7, // SPL, BPL, SIL, DIL 3695 8, 9, 10, 11, 12, 13, 14, 15, // R8B-R15B 3696 }; 3697 ZYAN_ASSERT( 3698 ((ZyanUSize)user_op->reg.value - ZYDIS_REGISTER_AL) < ZYAN_ARRAY_LENGTH(reg8_lookup)); 3699 reg_id = reg8_lookup[user_op->reg.value - ZYDIS_REGISTER_AL]; 3700 if (user_op->reg.value >= ZYDIS_REGISTER_SPL && user_op->reg.value <= ZYDIS_REGISTER_DIL) 3701 { 3702 instruction->attributes |= ZYDIS_ATTRIB_HAS_REX; 3703 } 3704 } 3705 3706 switch (def_op->op.encoding) 3707 { 3708 case ZYDIS_OPERAND_ENCODING_MODRM_REG: 3709 instruction->attributes |= ZYDIS_ATTRIB_HAS_MODRM; 3710 instruction->reg = reg_id; 3711 break; 3712 case ZYDIS_OPERAND_ENCODING_MODRM_RM: 3713 instruction->attributes |= ZYDIS_ATTRIB_HAS_MODRM; 3714 instruction->rm = reg_id; 3715 break; 3716 case ZYDIS_OPERAND_ENCODING_OPCODE: 3717 instruction->opcode += reg_id & 7; 3718 instruction->rm = reg_id; 3719 break; 3720 case ZYDIS_OPERAND_ENCODING_NDSNDD: 3721 instruction->vvvv = reg_id; 3722 break; 3723 case ZYDIS_OPERAND_ENCODING_IS4: 3724 instruction->imm_size = 8; 3725 instruction->imm = reg_id << 4; 3726 break; 3727 case ZYDIS_OPERAND_ENCODING_MASK: 3728 instruction->mask = reg_id; 3729 break; 3730 default: 3731 ZYAN_UNREACHABLE; 3732 } 3733 } 3734 3735 /** 3736 * Encodes memory operand as fields inside `ZydisEncoderInstruction` structure. 3737 * 3738 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 3739 * @param user_op Decoder's operand definition from instruction definition. 3740 * @param instruction A pointer to `ZydisEncoderInstruction` struct. 3741 */ 3742 static void ZydisBuildMemoryOperand(ZydisEncoderInstructionMatch *match, 3743 const ZydisEncoderOperand *user_op, ZydisEncoderInstruction *instruction) 3744 { 3745 instruction->attributes |= ZYDIS_ATTRIB_HAS_MODRM; 3746 instruction->disp = (ZyanU64)user_op->mem.displacement; 3747 if (match->easz == 16) 3748 { 3749 const ZyanI8 rm = ZydisGetRm16(user_op->mem.base, user_op->mem.index); 3750 if (rm != -1) 3751 { 3752 instruction->rm = (ZyanU8)rm; 3753 instruction->disp_size = match->disp_size; 3754 switch (instruction->disp_size) 3755 { 3756 case 0: 3757 if (rm == 6) 3758 { 3759 instruction->disp_size = 8; 3760 instruction->mod = 1; 3761 } 3762 break; 3763 case 8: 3764 instruction->mod = 1; 3765 break; 3766 case 16: 3767 instruction->mod = 2; 3768 break; 3769 default: 3770 ZYAN_UNREACHABLE; 3771 } 3772 } 3773 else 3774 { 3775 instruction->rm = 6; 3776 instruction->disp_size = 16; 3777 } 3778 return; 3779 } 3780 3781 if (user_op->mem.index == ZYDIS_REGISTER_NONE) 3782 { 3783 if (user_op->mem.base == ZYDIS_REGISTER_NONE) 3784 { 3785 if (match->request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) 3786 { 3787 instruction->rm = 4; 3788 instruction->attributes |= ZYDIS_ATTRIB_HAS_SIB; 3789 instruction->base = 5; 3790 instruction->index = 4; 3791 } 3792 else 3793 { 3794 instruction->rm = 5; 3795 } 3796 instruction->disp_size = 32; 3797 return; 3798 } 3799 else if ((user_op->mem.base == ZYDIS_REGISTER_RIP) || 3800 (user_op->mem.base == ZYDIS_REGISTER_EIP)) 3801 { 3802 instruction->rm = 5; 3803 instruction->disp_size = 32; 3804 return; 3805 } 3806 } 3807 3808 const ZyanU8 reg_base_id = (ZyanU8)ZydisRegisterGetId(user_op->mem.base); 3809 const ZyanU8 reg_index_id = (ZyanU8)ZydisRegisterGetId(user_op->mem.index); 3810 instruction->disp_size = match->disp_size; 3811 switch (instruction->disp_size) 3812 { 3813 case 0: 3814 if (reg_base_id == 5 || reg_base_id == 13) 3815 { 3816 instruction->disp_size = 8; 3817 instruction->disp = 0; 3818 instruction->mod = 1; 3819 } 3820 break; 3821 case 8: 3822 instruction->mod = 1; 3823 break; 3824 case 16: 3825 instruction->disp_size = 32; 3826 ZYAN_FALLTHROUGH; 3827 case 32: 3828 instruction->mod = 2; 3829 break; 3830 default: 3831 ZYAN_UNREACHABLE; 3832 } 3833 if ((user_op->mem.index == ZYDIS_REGISTER_NONE) && 3834 (reg_base_id != 4) && 3835 (reg_base_id != 12) && 3836 ((match->definition->modrm & 7) != 4)) 3837 { 3838 instruction->rm = reg_base_id; 3839 return; 3840 } 3841 instruction->rm = 4; 3842 instruction->attributes |= ZYDIS_ATTRIB_HAS_SIB; 3843 if (reg_base_id != 0xFF) 3844 { 3845 instruction->base = reg_base_id; 3846 } 3847 else 3848 { 3849 instruction->base = 5; 3850 instruction->mod = 0; 3851 instruction->disp_size = 32; 3852 } 3853 if (reg_index_id != 0xFF) 3854 { 3855 instruction->index = reg_index_id; 3856 } 3857 else 3858 { 3859 instruction->index = 4; 3860 } 3861 switch (user_op->mem.scale) 3862 { 3863 case 0: 3864 case 1: 3865 break; 3866 case 2: 3867 instruction->scale = 1; 3868 break; 3869 case 4: 3870 instruction->scale = 2; 3871 break; 3872 case 8: 3873 instruction->scale = 3; 3874 break; 3875 default: 3876 ZYAN_UNREACHABLE; 3877 } 3878 } 3879 3880 /** 3881 * Encodes instruction as emittable `ZydisEncoderInstruction` struct. 3882 * 3883 * @param match A pointer to `ZydisEncoderInstructionMatch` struct. 3884 * @param instruction A pointer to `ZydisEncoderInstruction` struct. 3885 * 3886 * @return A zyan status code. 3887 */ 3888 static ZyanStatus ZydisBuildInstruction(ZydisEncoderInstructionMatch *match, 3889 ZydisEncoderInstruction *instruction) 3890 { 3891 ZYAN_MEMSET(instruction, 0, sizeof(ZydisEncoderInstruction)); 3892 instruction->attributes = match->attributes; 3893 instruction->encoding = match->definition->encoding; 3894 instruction->opcode_map = match->definition->opcode_map; 3895 instruction->opcode = match->definition->opcode; 3896 instruction->rex_w = match->definition->rex_w; 3897 instruction->mod = (match->definition->modrm >> 6) & 3; 3898 instruction->reg = (match->definition->modrm >> 3) & 7; 3899 instruction->rm = match->definition->modrm & 7; 3900 if (match->definition->modrm) 3901 { 3902 instruction->attributes |= ZYDIS_ATTRIB_HAS_MODRM; 3903 } 3904 3905 switch (match->definition->vector_length) 3906 { 3907 case ZYDIS_VECTOR_LENGTH_INVALID: 3908 case ZYDIS_VECTOR_LENGTH_128: 3909 instruction->vector_length = 0; 3910 break; 3911 case ZYDIS_VECTOR_LENGTH_256: 3912 instruction->vector_length = 1; 3913 break; 3914 case ZYDIS_VECTOR_LENGTH_512: 3915 instruction->vector_length = 2; 3916 break; 3917 default: 3918 ZYAN_UNREACHABLE; 3919 } 3920 3921 if (match->definition->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) 3922 { 3923 const ZydisInstructionDefinitionEVEX *evex_def = 3924 (const ZydisInstructionDefinitionEVEX *)match->base_definition; 3925 if (evex_def->mask_override != ZYDIS_MASK_OVERRIDE_ZEROING) 3926 { 3927 instruction->zeroing = match->request->evex.zeroing_mask; 3928 } 3929 if ((match->request->evex.sae) || 3930 (match->request->evex.broadcast != ZYDIS_BROADCAST_MODE_INVALID)) 3931 { 3932 instruction->attributes |= ZYDIS_ATTRIB_HAS_EVEX_B; 3933 } 3934 if (match->request->evex.rounding != ZYDIS_ROUNDING_MODE_INVALID) 3935 { 3936 instruction->attributes |= ZYDIS_ATTRIB_HAS_EVEX_B; 3937 switch (match->request->evex.rounding) 3938 { 3939 case ZYDIS_ROUNDING_MODE_RN: 3940 instruction->vector_length = 0; 3941 break; 3942 case ZYDIS_ROUNDING_MODE_RD: 3943 instruction->vector_length = 1; 3944 break; 3945 case ZYDIS_ROUNDING_MODE_RU: 3946 instruction->vector_length = 2; 3947 break; 3948 case ZYDIS_ROUNDING_MODE_RZ: 3949 instruction->vector_length = 3; 3950 break; 3951 default: 3952 ZYAN_UNREACHABLE; 3953 } 3954 } 3955 } 3956 else if (match->definition->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX) 3957 { 3958 instruction->sss |= ZydisEncodeMvexBroadcastMode(match->request->mvex.broadcast); 3959 instruction->sss |= ZydisEncodeMvexConversionMode(match->request->mvex.conversion); 3960 3961 switch (match->request->mvex.rounding) 3962 { 3963 case ZYDIS_ROUNDING_MODE_INVALID: 3964 break; 3965 case ZYDIS_ROUNDING_MODE_RN: 3966 case ZYDIS_ROUNDING_MODE_RD: 3967 case ZYDIS_ROUNDING_MODE_RU: 3968 case ZYDIS_ROUNDING_MODE_RZ: 3969 instruction->sss |= match->request->mvex.rounding - ZYDIS_ROUNDING_MODE_RN; 3970 break; 3971 default: 3972 ZYAN_UNREACHABLE; 3973 } 3974 3975 switch (match->request->mvex.swizzle) 3976 { 3977 case ZYDIS_SWIZZLE_MODE_INVALID: 3978 break; 3979 case ZYDIS_SWIZZLE_MODE_DCBA: 3980 case ZYDIS_SWIZZLE_MODE_CDAB: 3981 case ZYDIS_SWIZZLE_MODE_BADC: 3982 case ZYDIS_SWIZZLE_MODE_DACB: 3983 case ZYDIS_SWIZZLE_MODE_AAAA: 3984 case ZYDIS_SWIZZLE_MODE_BBBB: 3985 case ZYDIS_SWIZZLE_MODE_CCCC: 3986 case ZYDIS_SWIZZLE_MODE_DDDD: 3987 instruction->sss |= match->request->mvex.swizzle - ZYDIS_SWIZZLE_MODE_DCBA; 3988 break; 3989 default: 3990 ZYAN_UNREACHABLE; 3991 } 3992 3993 if ((match->request->mvex.sae) || 3994 (match->request->mvex.eviction_hint) || 3995 (match->request->mvex.rounding != ZYDIS_ROUNDING_MODE_INVALID)) 3996 { 3997 instruction->eviction_hint = ZYAN_TRUE; 3998 } 3999 if (match->request->mvex.sae) 4000 { 4001 instruction->sss |= 4; 4002 } 4003 4004 // Following instructions violate general `MVEX.EH` handling rules. In all other cases this 4005 // bit is used either as eviction hint (memory operands present) or to encode MVEX-specific 4006 // functionality (register forms). Instructions listed below use `MVEX.EH` to identify 4007 // different instructions with memory operands and don't treat it as eviction hint. 4008 switch (match->request->mnemonic) 4009 { 4010 case ZYDIS_MNEMONIC_VMOVNRAPD: 4011 case ZYDIS_MNEMONIC_VMOVNRAPS: 4012 instruction->eviction_hint = ZYAN_FALSE; 4013 break; 4014 case ZYDIS_MNEMONIC_VMOVNRNGOAPD: 4015 case ZYDIS_MNEMONIC_VMOVNRNGOAPS: 4016 instruction->eviction_hint = ZYAN_TRUE; 4017 break; 4018 default: 4019 break; 4020 } 4021 } 4022 4023 switch (match->definition->mandatory_prefix) 4024 { 4025 case ZYDIS_MANDATORY_PREFIX_NONE: 4026 break; 4027 case ZYDIS_MANDATORY_PREFIX_66: 4028 instruction->attributes |= ZYDIS_ATTRIB_HAS_OPERANDSIZE; 4029 break; 4030 case ZYDIS_MANDATORY_PREFIX_F2: 4031 instruction->attributes |= ZYDIS_ATTRIB_HAS_REPNE; 4032 break; 4033 case ZYDIS_MANDATORY_PREFIX_F3: 4034 instruction->attributes |= ZYDIS_ATTRIB_HAS_REP; 4035 break; 4036 default: 4037 ZYAN_UNREACHABLE; 4038 } 4039 4040 const ZyanU8 mode_width = ZydisGetMachineModeWidth(match->request->machine_mode); 4041 if (match->easz != mode_width) 4042 { 4043 instruction->attributes |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE; 4044 } 4045 if ((match->request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) && 4046 (match->base_definition->operand_size_map != ZYDIS_OPSIZE_MAP_FORCE64)) 4047 { 4048 switch (match->eosz) 4049 { 4050 case 16: 4051 instruction->attributes |= ZYDIS_ATTRIB_HAS_OPERANDSIZE; 4052 break; 4053 case 32: 4054 break; 4055 case 64: 4056 instruction->rex_w = 4057 match->base_definition->operand_size_map != ZYDIS_OPSIZE_MAP_DEFAULT64; 4058 break; 4059 default: 4060 ZYAN_UNREACHABLE; 4061 } 4062 } 4063 else 4064 { 4065 if (match->eosz != mode_width) 4066 { 4067 instruction->attributes |= ZYDIS_ATTRIB_HAS_OPERANDSIZE; 4068 } 4069 } 4070 4071 for (ZyanU8 i = 0; i < match->request->operand_count; ++i) 4072 { 4073 const ZydisEncoderOperand *user_op = &match->request->operands[i]; 4074 const ZydisOperandDefinition *def_op = &match->operands[i]; 4075 switch (user_op->type) 4076 { 4077 case ZYDIS_OPERAND_TYPE_REGISTER: 4078 ZydisBuildRegisterOperand(user_op, def_op, instruction); 4079 break; 4080 case ZYDIS_OPERAND_TYPE_MEMORY: 4081 if (def_op->type != ZYDIS_SEMANTIC_OPTYPE_MOFFS) 4082 { 4083 ZydisBuildMemoryOperand(match, user_op, instruction); 4084 if ((match->cd8_scale) && 4085 (instruction->disp_size == 8)) 4086 { 4087 instruction->disp >>= match->cd8_scale; 4088 } 4089 } 4090 else 4091 { 4092 instruction->disp_size = match->disp_size; 4093 instruction->disp = (ZyanU64)user_op->mem.displacement; 4094 } 4095 break; 4096 case ZYDIS_OPERAND_TYPE_POINTER: 4097 instruction->disp_size = match->disp_size; 4098 instruction->disp = user_op->ptr.offset; 4099 instruction->imm_size = match->imm_size; 4100 instruction->imm = user_op->ptr.segment; 4101 break; 4102 case ZYDIS_OPERAND_TYPE_IMMEDIATE: 4103 if (def_op->type == ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1) 4104 { 4105 break; 4106 } 4107 if (def_op->op.encoding != ZYDIS_OPERAND_ENCODING_IS4) 4108 { 4109 if (instruction->imm_size) 4110 { 4111 ZYAN_ASSERT(instruction->disp_size == 0); 4112 instruction->disp_size = match->disp_size; 4113 instruction->disp = instruction->imm; 4114 } 4115 instruction->imm_size = match->imm_size; 4116 instruction->imm = user_op->imm.u; 4117 } 4118 else 4119 { 4120 ZYAN_ASSERT(instruction->imm_size == 8); 4121 instruction->imm |= user_op->imm.u; 4122 } 4123 break; 4124 default: 4125 ZYAN_UNREACHABLE; 4126 } 4127 } 4128 4129 return ZYAN_STATUS_SUCCESS; 4130 } 4131 4132 /** 4133 * Performs a set of sanity checks that must be satisfied for every valid encoder request. 4134 * 4135 * @param request A pointer to `ZydisEncoderRequest` struct. 4136 * 4137 * @return A zyan status code. 4138 */ 4139 static ZyanStatus ZydisEncoderCheckRequestSanity(const ZydisEncoderRequest *request) 4140 { 4141 if (((ZyanUSize)request->machine_mode > ZYDIS_MACHINE_MODE_MAX_VALUE) || 4142 ((ZyanUSize)request->allowed_encodings > ZYDIS_ENCODABLE_ENCODING_MAX_VALUE) || 4143 ((ZyanUSize)request->mnemonic > ZYDIS_MNEMONIC_MAX_VALUE) || 4144 ((ZyanUSize)request->branch_type > ZYDIS_BRANCH_TYPE_MAX_VALUE) || 4145 ((ZyanUSize)request->branch_width > ZYDIS_BRANCH_WIDTH_MAX_VALUE) || 4146 ((ZyanUSize)request->address_size_hint > ZYDIS_ADDRESS_SIZE_HINT_MAX_VALUE) || 4147 ((ZyanUSize)request->operand_size_hint > ZYDIS_OPERAND_SIZE_HINT_MAX_VALUE) || 4148 ((ZyanUSize)request->evex.broadcast > ZYDIS_BROADCAST_MODE_MAX_VALUE) || 4149 ((ZyanUSize)request->evex.rounding > ZYDIS_ROUNDING_MODE_MAX_VALUE) || 4150 ((ZyanUSize)request->mvex.broadcast > ZYDIS_BROADCAST_MODE_MAX_VALUE) || 4151 ((ZyanUSize)request->mvex.conversion > ZYDIS_CONVERSION_MODE_MAX_VALUE) || 4152 ((ZyanUSize)request->mvex.rounding > ZYDIS_ROUNDING_MODE_MAX_VALUE) || 4153 ((ZyanUSize)request->mvex.swizzle > ZYDIS_SWIZZLE_MODE_MAX_VALUE) || 4154 (request->operand_count > ZYDIS_ENCODER_MAX_OPERANDS) || 4155 (request->mnemonic == ZYDIS_MNEMONIC_INVALID) || 4156 (request->prefixes & ~ZYDIS_ENCODABLE_PREFIXES)) 4157 { 4158 return ZYAN_STATUS_INVALID_ARGUMENT; 4159 } 4160 4161 if (request->prefixes & ZYDIS_ATTRIB_HAS_SEGMENT) 4162 { 4163 if ((request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) && 4164 (request->prefixes & ZYDIS_LEGACY_SEGMENTS)) 4165 { 4166 return ZYAN_STATUS_INVALID_ARGUMENT; 4167 } 4168 4169 ZyanU8 seg_override_count = 0; 4170 if (request->prefixes & ZYDIS_ATTRIB_HAS_SEGMENT_CS) 4171 { 4172 ++seg_override_count; 4173 } 4174 if (request->prefixes & ZYDIS_ATTRIB_HAS_SEGMENT_SS) 4175 { 4176 ++seg_override_count; 4177 } 4178 if (request->prefixes & ZYDIS_ATTRIB_HAS_SEGMENT_DS) 4179 { 4180 ++seg_override_count; 4181 } 4182 if (request->prefixes & ZYDIS_ATTRIB_HAS_SEGMENT_ES) 4183 { 4184 ++seg_override_count; 4185 } 4186 if (request->prefixes & ZYDIS_ATTRIB_HAS_SEGMENT_FS) 4187 { 4188 ++seg_override_count; 4189 } 4190 if (request->prefixes & ZYDIS_ATTRIB_HAS_SEGMENT_GS) 4191 { 4192 ++seg_override_count; 4193 } 4194 if (seg_override_count != 1) 4195 { 4196 return ZYAN_STATUS_INVALID_ARGUMENT; 4197 } 4198 } 4199 ZyanU8 rep_family_count = 0; 4200 if (request->prefixes & ZYDIS_ATTRIB_HAS_REP) 4201 { 4202 ++rep_family_count; 4203 } 4204 if (request->prefixes & ZYDIS_ATTRIB_HAS_REPE) 4205 { 4206 ++rep_family_count; 4207 } 4208 if (request->prefixes & ZYDIS_ATTRIB_HAS_REPNE) 4209 { 4210 ++rep_family_count; 4211 } 4212 if (rep_family_count > 1) 4213 { 4214 return ZYAN_STATUS_INVALID_ARGUMENT; 4215 } 4216 if ((request->prefixes & ZYDIS_ATTRIB_HAS_XACQUIRE) && 4217 (request->prefixes & ZYDIS_ATTRIB_HAS_XRELEASE)) 4218 { 4219 return ZYAN_STATUS_INVALID_ARGUMENT; 4220 } 4221 if ((request->prefixes & ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN) && 4222 (request->prefixes & ZYDIS_ATTRIB_HAS_BRANCH_TAKEN)) 4223 { 4224 return ZYAN_STATUS_INVALID_ARGUMENT; 4225 } 4226 if ((request->prefixes & ZYDIS_ATTRIB_HAS_NOTRACK) && 4227 (request->prefixes & ZYDIS_ATTRIB_HAS_SEGMENT)) 4228 { 4229 return ZYAN_STATUS_INVALID_ARGUMENT; 4230 } 4231 4232 static const ZyanBool branch_lookup 4233 [ZYDIS_BRANCH_WIDTH_MAX_VALUE + 1][ZYDIS_BRANCH_TYPE_MAX_VALUE + 1] = 4234 { 4235 /* NONE */ { ZYAN_TRUE, ZYAN_TRUE, ZYAN_TRUE, ZYAN_TRUE }, 4236 /* 8 */ { ZYAN_TRUE, ZYAN_TRUE, ZYAN_FALSE, ZYAN_FALSE }, 4237 /* 16 */ { ZYAN_TRUE, ZYAN_FALSE, ZYAN_TRUE, ZYAN_TRUE }, 4238 /* 32 */ { ZYAN_TRUE, ZYAN_FALSE, ZYAN_TRUE, ZYAN_TRUE }, 4239 /* 64 */ { ZYAN_TRUE, ZYAN_FALSE, ZYAN_TRUE, ZYAN_TRUE }, 4240 }; 4241 if (!branch_lookup[request->branch_width][request->branch_type]) 4242 { 4243 return ZYAN_STATUS_INVALID_ARGUMENT; 4244 } 4245 4246 if (request->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) 4247 { 4248 if (request->address_size_hint == ZYDIS_ADDRESS_SIZE_HINT_16) 4249 { 4250 return ZYAN_STATUS_INVALID_ARGUMENT; 4251 } 4252 } 4253 else 4254 { 4255 if ((request->branch_width == ZYDIS_BRANCH_WIDTH_64) || 4256 (request->address_size_hint == ZYDIS_ADDRESS_SIZE_HINT_64) || 4257 (request->operand_size_hint == ZYDIS_OPERAND_SIZE_HINT_64)) 4258 { 4259 return ZYAN_STATUS_INVALID_ARGUMENT; 4260 } 4261 } 4262 4263 for (ZyanU8 i = 0; i < request->operand_count; ++i) 4264 { 4265 const ZydisEncoderOperand *op = &request->operands[i]; 4266 if ((op->type == ZYDIS_OPERAND_TYPE_UNUSED) || 4267 ((ZyanUSize)op->type > ZYDIS_OPERAND_TYPE_MAX_VALUE)) 4268 { 4269 return ZYAN_STATUS_INVALID_ARGUMENT; 4270 } 4271 4272 switch (op->type) 4273 { 4274 case ZYDIS_OPERAND_TYPE_REGISTER: 4275 if (op->reg.value > ZYDIS_REGISTER_MAX_VALUE) 4276 { 4277 return ZYAN_STATUS_INVALID_ARGUMENT; 4278 } 4279 break; 4280 case ZYDIS_OPERAND_TYPE_MEMORY: 4281 if (((ZyanUSize)op->mem.base > ZYDIS_REGISTER_MAX_VALUE) || 4282 ((ZyanUSize)op->mem.index > ZYDIS_REGISTER_MAX_VALUE) || 4283 !ZydisIsScaleValid(op->mem.scale)) 4284 { 4285 return ZYAN_STATUS_INVALID_ARGUMENT; 4286 } 4287 break; 4288 case ZYDIS_OPERAND_TYPE_POINTER: 4289 case ZYDIS_OPERAND_TYPE_IMMEDIATE: 4290 break; 4291 default: 4292 return ZYAN_STATUS_INVALID_ARGUMENT; 4293 } 4294 } 4295 4296 return ZYAN_STATUS_SUCCESS; 4297 } 4298 4299 /** 4300 * Encodes instruction with semantics specified in encoder request structure. 4301 * 4302 * @param request A pointer to the `ZydisEncoderRequest` struct. Must be validated before 4303 * calling this function. 4304 * @param buffer A pointer to the output buffer receiving encoded instruction. 4305 * @param length A pointer to the variable containing length of the output buffer. Upon 4306 * successful return this variable receives length of the encoded instruction. 4307 * @param instruction Internal state of the encoder. 4308 * 4309 * @return A zyan status code. 4310 */ 4311 static ZyanStatus ZydisEncoderEncodeInstructionInternal(const ZydisEncoderRequest *request, 4312 void *buffer, ZyanUSize *length, ZydisEncoderInstruction *instruction) 4313 { 4314 ZydisEncoderInstructionMatch match; 4315 ZYAN_CHECK(ZydisFindMatchingDefinition(request, &match)); 4316 ZydisEncoderBuffer output; 4317 output.buffer = (ZyanU8 *)buffer; 4318 output.size = *length; 4319 output.offset = 0; 4320 ZYAN_CHECK(ZydisBuildInstruction(&match, instruction)); 4321 ZYAN_CHECK(ZydisEmitInstruction(instruction, &output)); 4322 *length = output.offset; 4323 return ZYAN_STATUS_SUCCESS; 4324 } 4325 4326 /* ============================================================================================== */ 4327 /* Exported functions */ 4328 /* ============================================================================================== */ 4329 4330 ZYDIS_EXPORT ZyanStatus ZydisEncoderEncodeInstruction(const ZydisEncoderRequest *request, 4331 void *buffer, ZyanUSize *length) 4332 { 4333 if (!request || !buffer || !length) 4334 { 4335 return ZYAN_STATUS_INVALID_ARGUMENT; 4336 } 4337 ZYAN_CHECK(ZydisEncoderCheckRequestSanity(request)); 4338 4339 ZydisEncoderInstruction instruction; 4340 return ZydisEncoderEncodeInstructionInternal(request, buffer, length, &instruction); 4341 } 4342 4343 ZYDIS_EXPORT ZyanStatus ZydisEncoderEncodeInstructionAbsolute(ZydisEncoderRequest *request, 4344 void *buffer, ZyanUSize *length, ZyanU64 runtime_address) 4345 { 4346 if (!request || !buffer || !length) 4347 { 4348 return ZYAN_STATUS_INVALID_ARGUMENT; 4349 } 4350 ZYAN_CHECK(ZydisEncoderCheckRequestSanity(request)); 4351 4352 const ZydisEncoderRelInfo *rel_info = ZydisGetRelInfo(request->mnemonic); 4353 ZydisEncoderOperand *op_rip_rel = ZYAN_NULL; 4354 ZyanBool adjusted_rel = ZYAN_FALSE; 4355 ZyanU64 absolute_address = 0; 4356 ZyanU8 mode_index = ZydisGetMachineModeWidth(request->machine_mode) >> 5; 4357 for (ZyanU8 i = 0; i < request->operand_count; ++i) 4358 { 4359 ZydisEncoderOperand *op = &request->operands[i]; 4360 if ((op->type == ZYDIS_OPERAND_TYPE_IMMEDIATE) && rel_info) 4361 { 4362 if (adjusted_rel) 4363 { 4364 return ZYAN_STATUS_INVALID_ARGUMENT; 4365 } 4366 4367 switch (rel_info->accepts_scaling_hints) 4368 { 4369 case ZYDIS_SIZE_HINT_NONE: 4370 case ZYDIS_SIZE_HINT_OSZ: 4371 { 4372 static const ZyanI8 asz_priority[3][3] = 4373 { 4374 { 0, 1, 2 }, 4375 { 0, 2, 1 }, 4376 { 0, 2, -1 }, 4377 }; 4378 static const ZyanI8 osz_priority[3][3] = 4379 { 4380 { 0, 1, 2 }, 4381 { 0, 2, 1 }, 4382 { 0, 2, 1 }, 4383 }; 4384 ZyanI8 forced_priority_row[3] = { -1, -1, -1 }; 4385 ZyanI8 *priority_row = ZYAN_NULL; 4386 ZyanU8 extra_length = 0; 4387 ZyanU8 start_offset = 0; 4388 if (rel_info->accepts_scaling_hints == ZYDIS_SIZE_HINT_NONE) 4389 { 4390 if ((request->branch_type == ZYDIS_BRANCH_TYPE_FAR) || 4391 (request->branch_width == ZYDIS_BRANCH_WIDTH_64)) 4392 { 4393 return ZYAN_STATUS_INVALID_ARGUMENT; 4394 } 4395 if ((rel_info->accepts_branch_hints) && 4396 (request->prefixes & (ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN | 4397 ZYDIS_ATTRIB_HAS_BRANCH_TAKEN))) 4398 { 4399 extra_length += 1; 4400 } 4401 if ((rel_info->accepts_bound) && (request->prefixes & ZYDIS_ATTRIB_HAS_BND)) 4402 { 4403 extra_length += 1; 4404 // `BND` prefix is not accepted for short `JMP` (Intel SDM Vol. 1) 4405 if ((request->mnemonic == ZYDIS_MNEMONIC_JMP) && 4406 (request->branch_type == ZYDIS_BRANCH_TYPE_NONE) && 4407 (request->branch_width == ZYDIS_BRANCH_WIDTH_NONE)) 4408 { 4409 start_offset = 1; 4410 } 4411 } 4412 if (request->branch_width == ZYDIS_BRANCH_WIDTH_NONE) 4413 { 4414 if (request->branch_type == ZYDIS_BRANCH_TYPE_NEAR) 4415 { 4416 start_offset = 1; 4417 } 4418 priority_row = (ZyanI8 *)&asz_priority[mode_index]; 4419 } 4420 else 4421 { 4422 forced_priority_row[0] = (ZyanI8)(request->branch_width - 1); 4423 priority_row = (ZyanI8 *)&forced_priority_row; 4424 } 4425 } 4426 else 4427 { 4428 if (request->operand_size_hint == ZYDIS_OPERAND_SIZE_HINT_NONE) 4429 { 4430 priority_row = (ZyanI8 *)&osz_priority[mode_index]; 4431 } 4432 else 4433 { 4434 if (request->operand_size_hint == ZYDIS_OPERAND_SIZE_HINT_64) 4435 { 4436 extra_length = 1; 4437 forced_priority_row[0] = 2; 4438 } 4439 else 4440 { 4441 forced_priority_row[0] = (ZyanI8)(request->operand_size_hint - 1); 4442 } 4443 priority_row = (ZyanI8 *)&forced_priority_row; 4444 } 4445 } 4446 ZYAN_ASSERT(ZYAN_ARRAY_LENGTH(asz_priority[0]) == 4447 ZYAN_ARRAY_LENGTH(osz_priority[0])); 4448 for (ZyanU8 j = start_offset; j < ZYAN_ARRAY_LENGTH(asz_priority[0]); ++j) 4449 { 4450 ZyanI8 size_index = priority_row[j]; 4451 if (size_index < 0) 4452 { 4453 break; 4454 } 4455 ZyanU8 base_size = rel_info->size[mode_index][size_index]; 4456 if (base_size == 0) 4457 { 4458 continue; 4459 } 4460 ZyanU8 predicted_size = base_size + extra_length; 4461 if (runtime_address > ZYAN_UINT64_MAX - predicted_size + 1) 4462 { 4463 continue; 4464 } 4465 ZyanI64 rel = (ZyanI64)(op->imm.u - (runtime_address + predicted_size)); 4466 ZyanU8 rel_size = ZydisGetSignedImmSize(rel); 4467 if (rel_size > (8 << size_index)) 4468 { 4469 continue; 4470 } 4471 op->imm.s = rel; 4472 adjusted_rel = ZYAN_TRUE; 4473 if (rel_info->accepts_scaling_hints == ZYDIS_SIZE_HINT_NONE) 4474 { 4475 if (request->branch_width == ZYDIS_BRANCH_WIDTH_NONE) 4476 { 4477 request->branch_width = 4478 (ZydisBranchWidth)(ZYDIS_BRANCH_WIDTH_8 + size_index); 4479 } 4480 } 4481 else 4482 { 4483 if (request->operand_size_hint == ZYDIS_OPERAND_SIZE_HINT_NONE) 4484 { 4485 request->operand_size_hint = 4486 (ZydisOperandSizeHint)(ZYDIS_OPERAND_SIZE_HINT_8 + size_index); 4487 } 4488 } 4489 break; 4490 } 4491 break; 4492 } 4493 case ZYDIS_SIZE_HINT_ASZ: 4494 { 4495 static const ZyanI8 asz_prefix_lookup[3][ZYDIS_ADDRESS_SIZE_HINT_MAX_VALUE + 1] = 4496 { 4497 { 0, 0, 1, -1 }, 4498 { 0, 1, 0, -1 }, 4499 { 0, -1, 1, 0 }, 4500 }; 4501 ZyanI8 extra_length = asz_prefix_lookup[mode_index][request->address_size_hint]; 4502 if (extra_length < 0) 4503 { 4504 return ZYAN_STATUS_INVALID_ARGUMENT; 4505 } 4506 ZyanU8 asz_index = (request->address_size_hint == ZYDIS_ADDRESS_SIZE_HINT_NONE) 4507 ? mode_index 4508 : ZydisGetAszFromHint(request->address_size_hint) >> 5; 4509 ZYAN_ASSERT((rel_info->size[asz_index][0] != 0) && 4510 (rel_info->size[asz_index][1] == 0) && 4511 (rel_info->size[asz_index][2] == 0) && 4512 !rel_info->accepts_branch_hints); 4513 ZyanU8 predicted_size = rel_info->size[asz_index][0] + extra_length; 4514 if (runtime_address > ZYAN_UINT64_MAX - predicted_size + 1) 4515 { 4516 return ZYAN_STATUS_INVALID_ARGUMENT; 4517 } 4518 ZyanI64 rel = (ZyanI64)(op->imm.u - (runtime_address + predicted_size)); 4519 ZyanU8 rel_size = ZydisGetSignedImmSize(rel); 4520 if (rel_size > 8) 4521 { 4522 return ZYAN_STATUS_INVALID_ARGUMENT; 4523 } 4524 op->imm.s = rel; 4525 adjusted_rel = ZYAN_TRUE; 4526 break; 4527 } 4528 default: 4529 ZYAN_UNREACHABLE; 4530 } 4531 if (!adjusted_rel) 4532 { 4533 return ZYAN_STATUS_INVALID_ARGUMENT; 4534 } 4535 } 4536 else if ((op->type == ZYDIS_OPERAND_TYPE_MEMORY) && 4537 ((op->mem.base == ZYDIS_REGISTER_EIP) || 4538 (op->mem.base == ZYDIS_REGISTER_RIP))) 4539 { 4540 if (op_rip_rel) 4541 { 4542 return ZYAN_STATUS_INVALID_ARGUMENT; 4543 } 4544 4545 absolute_address = op->mem.displacement; 4546 op->mem.displacement = 0; 4547 op_rip_rel = op; 4548 } 4549 } 4550 4551 ZydisEncoderInstruction instruction; 4552 ZYAN_CHECK(ZydisEncoderEncodeInstructionInternal(request, buffer, length, &instruction)); 4553 if (op_rip_rel) 4554 { 4555 ZyanUSize instruction_size = *length; 4556 if (runtime_address > ZYAN_UINT64_MAX - instruction_size + 1) 4557 { 4558 return ZYAN_STATUS_INVALID_ARGUMENT; 4559 } 4560 ZyanI64 rip_rel = (ZyanI64)(absolute_address - (runtime_address + instruction_size)); 4561 if (ZydisGetSignedImmSize(rip_rel) > 32) 4562 { 4563 return ZYAN_STATUS_INVALID_ARGUMENT; 4564 } 4565 ZYAN_ASSERT(instruction.disp_size != 0); 4566 ZyanU8 disp_offset = (instruction.disp_size >> 3) + (instruction.imm_size >> 3); 4567 if (instruction.encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW) 4568 { 4569 disp_offset += 1; 4570 } 4571 ZYAN_ASSERT(instruction_size > disp_offset); 4572 ZYAN_MEMCPY((ZyanU8 *)buffer + instruction_size - disp_offset, &rip_rel, sizeof(ZyanI32)); 4573 op_rip_rel->mem.displacement = rip_rel; 4574 } 4575 4576 return ZYAN_STATUS_SUCCESS; 4577 } 4578 4579 ZYDIS_EXPORT ZyanStatus ZydisEncoderDecodedInstructionToEncoderRequest( 4580 const ZydisDecodedInstruction *instruction, const ZydisDecodedOperand* operands, 4581 ZyanU8 operand_count, ZydisEncoderRequest *request) 4582 { 4583 if (!instruction || !request || (operand_count && !operands)) 4584 { 4585 return ZYAN_STATUS_INVALID_ARGUMENT; 4586 } 4587 4588 ZYAN_MEMSET(request, 0, sizeof(ZydisEncoderRequest)); 4589 request->machine_mode = instruction->machine_mode; 4590 request->mnemonic = instruction->mnemonic; 4591 request->prefixes = instruction->attributes & ZYDIS_ENCODABLE_PREFIXES; 4592 request->branch_type = instruction->meta.branch_type; 4593 if (!(instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_SEGMENT)) 4594 { 4595 request->prefixes &= ~ZYDIS_ATTRIB_HAS_SEGMENT; 4596 } 4597 4598 switch (instruction->address_width) 4599 { 4600 case 16: 4601 request->address_size_hint = ZYDIS_ADDRESS_SIZE_HINT_16; 4602 break; 4603 case 32: 4604 request->address_size_hint = ZYDIS_ADDRESS_SIZE_HINT_32; 4605 break; 4606 case 64: 4607 request->address_size_hint = ZYDIS_ADDRESS_SIZE_HINT_64; 4608 break; 4609 default: 4610 return ZYAN_STATUS_INVALID_ARGUMENT; 4611 } 4612 4613 switch (instruction->operand_width) 4614 { 4615 case 8: 4616 request->operand_size_hint = ZYDIS_OPERAND_SIZE_HINT_8; 4617 break; 4618 case 16: 4619 request->operand_size_hint = ZYDIS_OPERAND_SIZE_HINT_16; 4620 break; 4621 case 32: 4622 request->operand_size_hint = ZYDIS_OPERAND_SIZE_HINT_32; 4623 break; 4624 case 64: 4625 request->operand_size_hint = ZYDIS_OPERAND_SIZE_HINT_64; 4626 break; 4627 default: 4628 return ZYAN_STATUS_INVALID_ARGUMENT; 4629 } 4630 4631 switch (request->branch_type) 4632 { 4633 case ZYDIS_BRANCH_TYPE_NONE: 4634 request->branch_width = ZYDIS_BRANCH_WIDTH_NONE; 4635 break; 4636 case ZYDIS_BRANCH_TYPE_SHORT: 4637 request->branch_width = ZYDIS_BRANCH_WIDTH_8; 4638 break; 4639 case ZYDIS_BRANCH_TYPE_NEAR: 4640 case ZYDIS_BRANCH_TYPE_FAR: 4641 switch (instruction->operand_width) 4642 { 4643 case 16: 4644 request->branch_width = ZYDIS_BRANCH_WIDTH_16; 4645 break; 4646 case 32: 4647 request->branch_width = ZYDIS_BRANCH_WIDTH_32; 4648 break; 4649 case 64: 4650 request->branch_width = ZYDIS_BRANCH_WIDTH_64; 4651 break; 4652 default: 4653 ZYAN_UNREACHABLE; 4654 } 4655 break; 4656 default: 4657 return ZYAN_STATUS_INVALID_ARGUMENT; 4658 } 4659 4660 switch (instruction->encoding) 4661 { 4662 case ZYDIS_INSTRUCTION_ENCODING_LEGACY: 4663 case ZYDIS_INSTRUCTION_ENCODING_3DNOW: 4664 case ZYDIS_INSTRUCTION_ENCODING_XOP: 4665 case ZYDIS_INSTRUCTION_ENCODING_VEX: 4666 break; 4667 case ZYDIS_INSTRUCTION_ENCODING_EVEX: 4668 request->evex.broadcast = !instruction->avx.broadcast.is_static ? 4669 instruction->avx.broadcast.mode : ZYDIS_BROADCAST_MODE_INVALID; 4670 request->evex.rounding = instruction->avx.rounding.mode; 4671 request->evex.sae = instruction->avx.has_sae; 4672 request->evex.zeroing_mask = (instruction->avx.mask.mode == ZYDIS_MASK_MODE_ZEROING || 4673 instruction->avx.mask.mode == ZYDIS_MASK_MODE_CONTROL_ZEROING) && 4674 (instruction->raw.evex.z) ? ZYAN_TRUE : ZYAN_FALSE; 4675 break; 4676 case ZYDIS_INSTRUCTION_ENCODING_MVEX: 4677 request->mvex.broadcast = !instruction->avx.broadcast.is_static ? 4678 instruction->avx.broadcast.mode : ZYDIS_BROADCAST_MODE_INVALID; 4679 request->mvex.conversion = instruction->avx.conversion.mode; 4680 request->mvex.rounding = instruction->avx.rounding.mode; 4681 request->mvex.swizzle = instruction->avx.swizzle.mode; 4682 request->mvex.sae = instruction->avx.has_sae; 4683 request->mvex.eviction_hint = instruction->avx.has_eviction_hint; 4684 break; 4685 default: 4686 return ZYAN_STATUS_INVALID_ARGUMENT; 4687 } 4688 request->allowed_encodings = 1 << instruction->encoding; 4689 4690 if ((operand_count > ZYDIS_ENCODER_MAX_OPERANDS) || 4691 (operand_count > instruction->operand_count_visible)) 4692 { 4693 return ZYAN_STATUS_INVALID_ARGUMENT; 4694 } 4695 request->operand_count = operand_count; 4696 for (ZyanU8 i = 0; i < operand_count; ++i) 4697 { 4698 const ZydisDecodedOperand *dec_op = &operands[i]; 4699 ZydisEncoderOperand *enc_op = &request->operands[i]; 4700 4701 enc_op->type = dec_op->type; 4702 switch (dec_op->type) 4703 { 4704 case ZYDIS_OPERAND_TYPE_REGISTER: 4705 enc_op->reg.value = dec_op->reg.value; 4706 enc_op->reg.is4 = dec_op->encoding == ZYDIS_OPERAND_ENCODING_IS4; 4707 break; 4708 case ZYDIS_OPERAND_TYPE_MEMORY: 4709 enc_op->mem.base = dec_op->mem.base; 4710 enc_op->mem.index = dec_op->mem.index; 4711 enc_op->mem.scale = dec_op->mem.type != ZYDIS_MEMOP_TYPE_MIB ? dec_op->mem.scale : 0; 4712 if (dec_op->mem.disp.has_displacement) 4713 { 4714 enc_op->mem.displacement = dec_op->mem.disp.value; 4715 } 4716 enc_op->mem.size = dec_op->size / 8; 4717 break; 4718 case ZYDIS_OPERAND_TYPE_POINTER: 4719 enc_op->ptr.segment = dec_op->ptr.segment; 4720 enc_op->ptr.offset = dec_op->ptr.offset; 4721 break; 4722 case ZYDIS_OPERAND_TYPE_IMMEDIATE: 4723 enc_op->imm.u = dec_op->imm.value.u; 4724 // `XBEGIN` is an ISA-wide unique instruction because it's not a branching instruction 4725 // but it has a relative operand which behaves differently from all other relatives 4726 // (no truncating behavior in 16-bit mode). Encoder treats it as non-branching 4727 // instruction that scales with hidden operand size. 4728 if ((dec_op->imm.is_relative) && 4729 (instruction->mnemonic != ZYDIS_MNEMONIC_XBEGIN)) 4730 { 4731 switch (instruction->raw.imm->size) 4732 { 4733 case 8: 4734 request->branch_width = ZYDIS_BRANCH_WIDTH_8; 4735 break; 4736 case 16: 4737 request->branch_width = ZYDIS_BRANCH_WIDTH_16; 4738 break; 4739 case 32: 4740 request->branch_width = ZYDIS_BRANCH_WIDTH_32; 4741 break; 4742 default: 4743 return ZYAN_STATUS_INVALID_ARGUMENT; 4744 } 4745 } 4746 break; 4747 default: 4748 return ZYAN_STATUS_INVALID_ARGUMENT; 4749 } 4750 } 4751 4752 return ZYAN_STATUS_SUCCESS; 4753 } 4754 4755 ZYDIS_EXPORT ZyanStatus ZydisEncoderNopFill(void *buffer, ZyanUSize length) 4756 { 4757 if (!buffer) 4758 { 4759 return ZYAN_STATUS_INVALID_ARGUMENT; 4760 } 4761 4762 // Intel SDM Vol. 2B "Recommended Multi-Byte Sequence of NOP Instruction" 4763 static const ZyanU8 nops[9][9] = 4764 { 4765 { 0x90 }, 4766 { 0x66, 0x90 }, 4767 { 0x0F, 0x1F, 0x00 }, 4768 { 0x0F, 0x1F, 0x40, 0x00 }, 4769 { 0x0F, 0x1F, 0x44, 0x00, 0x00 }, 4770 { 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00 }, 4771 { 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00 }, 4772 { 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }, 4773 { 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }, 4774 }; 4775 4776 ZyanU8 *output = (ZyanU8 *)buffer; 4777 while (length) 4778 { 4779 ZyanUSize nop_size = (length > 9) ? 9 : length; 4780 ZYAN_MEMCPY(output, nops[nop_size - 1], nop_size); 4781 output += nop_size; 4782 length -= nop_size; 4783 } 4784 4785 return ZYAN_STATUS_SUCCESS; 4786 } 4787 4788 /* ============================================================================================== */