1 /*************************************************************************************************** 2 3 Zyan Disassembler Library (Zydis) 4 5 Original Author : Florian Bernd, Joel Hoener 6 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in all 15 * copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 25 ***************************************************************************************************/ 26 27 #include <Zydis/Internal/FormatterBase.h> 28 #include <Zydis/Utils.h> 29 30 /* ============================================================================================== */ 31 /* Constants */ 32 /* ============================================================================================== */ 33 34 #include <Generated/FormatterStrings.inc> 35 36 static const ZydisShortString* const STR_PREF_REX[16] = 37 { 38 &STR_PREF_REX_40, 39 &STR_PREF_REX_41, 40 &STR_PREF_REX_42, 41 &STR_PREF_REX_43, 42 &STR_PREF_REX_44, 43 &STR_PREF_REX_45, 44 &STR_PREF_REX_46, 45 &STR_PREF_REX_47, 46 &STR_PREF_REX_48, 47 &STR_PREF_REX_49, 48 &STR_PREF_REX_4A, 49 &STR_PREF_REX_4B, 50 &STR_PREF_REX_4C, 51 &STR_PREF_REX_4D, 52 &STR_PREF_REX_4E, 53 &STR_PREF_REX_4F 54 }; 55 56 static const ZydisPredefinedToken* const TOK_PREF_REX[16] = 57 { 58 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_40, 59 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_41, 60 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_42, 61 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_43, 62 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_44, 63 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_45, 64 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_46, 65 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_47, 66 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_48, 67 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_49, 68 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_4A, 69 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_4B, 70 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_4C, 71 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_4D, 72 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_4E, 73 (const ZydisPredefinedToken* const)&TOK_DATA_PREF_REX_4F 74 }; 75 76 /* ============================================================================================== */ 77 /* Helper functions */ 78 /* ============================================================================================== */ 79 80 ZyanU32 ZydisFormatterHelperGetExplicitSize(const ZydisFormatter* formatter, 81 ZydisFormatterContext* context, const ZydisDecodedOperand* operand) 82 { 83 ZYAN_ASSERT(formatter); 84 ZYAN_ASSERT(context); 85 ZYAN_ASSERT(operand); 86 87 ZYAN_ASSERT(operand->type == ZYDIS_OPERAND_TYPE_MEMORY); 88 ZYAN_ASSERT((operand->mem.type == ZYDIS_MEMOP_TYPE_MEM) || 89 (operand->mem.type == ZYDIS_MEMOP_TYPE_AGEN) || 90 (operand->mem.type == ZYDIS_MEMOP_TYPE_VSIB)); 91 92 if (formatter->force_memory_size) 93 { 94 return operand->size; 95 } 96 else if (operand->mem.type == ZYDIS_MEMOP_TYPE_AGEN) 97 { 98 return 0; 99 } 100 101 if (!context->operands) 102 { 103 // Single operand formatting. We can not derive the explicit size by using the other 104 // operands. 105 return 0; 106 } 107 108 switch (operand->id) 109 { 110 case 0: 111 if (context->instruction->operand_count_visible < 2) 112 { 113 return 0; 114 } 115 if ((context->operands[1].type == ZYDIS_OPERAND_TYPE_UNUSED) || 116 (context->operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE)) 117 { 118 return context->operands[0].size; 119 } 120 if (context->operands[0].size != context->operands[1].size) 121 { 122 return context->operands[0].size; 123 } 124 if ((context->operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER) && 125 (context->operands[1].visibility == ZYDIS_OPERAND_VISIBILITY_IMPLICIT) && 126 (context->operands[1].reg.value == ZYDIS_REGISTER_CL)) 127 { 128 return context->operands[0].size; 129 } 130 break; 131 case 1: 132 case 2: 133 if (context->operands[operand->id - 1].size != 134 context->operands[operand->id].size) 135 { 136 return context->operands[operand->id].size; 137 } 138 break; 139 default: 140 break; 141 } 142 143 return 0; 144 } 145 146 /* ============================================================================================== */ 147 /* Formatter functions */ 148 /* ============================================================================================== */ 149 150 /* ---------------------------------------------------------------------------------------------- */ 151 /* Operands */ 152 /* ---------------------------------------------------------------------------------------------- */ 153 154 ZyanStatus ZydisFormatterBaseFormatOperandREG(const ZydisFormatter* formatter, 155 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 156 { 157 ZYAN_ASSERT(formatter); 158 ZYAN_ASSERT(buffer); 159 ZYAN_ASSERT(context); 160 161 return formatter->func_print_register(formatter, buffer, context, context->operand->reg.value); 162 } 163 164 ZyanStatus ZydisFormatterBaseFormatOperandPTR(const ZydisFormatter* formatter, 165 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 166 { 167 ZYAN_ASSERT(formatter); 168 ZYAN_ASSERT(buffer); 169 ZYAN_ASSERT(context); 170 171 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE); 172 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string, 173 context->operand->ptr.segment, 4, formatter->hex_force_leading_number); 174 ZYDIS_BUFFER_APPEND(buffer, DELIM_SEGMENT); 175 176 ZyanU8 padding; 177 switch (context->instruction->operand_width) 178 { 179 case 16: 180 padding = 4; 181 break; 182 case 32: 183 padding = 8; 184 break; 185 default: 186 return ZYAN_STATUS_INVALID_ARGUMENT; 187 } 188 189 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE); 190 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string, 191 context->operand->ptr.offset , padding, formatter->hex_force_leading_number); 192 193 return ZYAN_STATUS_SUCCESS; 194 } 195 196 ZyanStatus ZydisFormatterBaseFormatOperandIMM(const ZydisFormatter* formatter, 197 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 198 { 199 ZYAN_ASSERT(formatter); 200 ZYAN_ASSERT(buffer); 201 ZYAN_ASSERT(context); 202 203 // The immediate operand contains an address 204 if (context->operand->imm.is_relative) 205 { 206 const ZyanBool absolute = !formatter->force_relative_branches && 207 (context->runtime_address != ZYDIS_RUNTIME_ADDRESS_NONE); 208 if (absolute) 209 { 210 return formatter->func_print_address_abs(formatter, buffer, context); 211 } 212 return formatter->func_print_address_rel(formatter, buffer, context); 213 } 214 215 // The immediate operand contains an actual ordinal value 216 return formatter->func_print_imm(formatter, buffer, context); 217 } 218 219 /* ---------------------------------------------------------------------------------------------- */ 220 /* Elemental tokens */ 221 /* ---------------------------------------------------------------------------------------------- */ 222 223 ZyanStatus ZydisFormatterBasePrintAddressABS(const ZydisFormatter* formatter, 224 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 225 { 226 ZYAN_ASSERT(formatter); 227 ZYAN_ASSERT(buffer); 228 ZYAN_ASSERT(context); 229 230 ZyanU64 address; 231 ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand, 232 context->runtime_address, &address)); 233 ZyanU8 padding = (formatter->addr_padding_absolute == 234 ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_absolute; 235 if ((formatter->addr_padding_absolute == ZYDIS_PADDING_AUTO) && 236 (formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX)) 237 { 238 switch (context->instruction->address_width) 239 { 240 case 16: 241 padding = 4; 242 address = (ZyanU16)address; 243 break; 244 case 32: 245 padding = 8; 246 address = (ZyanU32)address; 247 break; 248 case 64: 249 padding = 16; 250 break; 251 default: 252 return ZYAN_STATUS_INVALID_ARGUMENT; 253 } 254 } 255 256 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_ADDRESS_ABS); 257 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string, address, padding, 258 formatter->hex_force_leading_number); 259 260 return ZYAN_STATUS_SUCCESS; 261 } 262 263 ZyanStatus ZydisFormatterBasePrintAddressREL(const ZydisFormatter* formatter, 264 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 265 { 266 ZYAN_ASSERT(formatter); 267 ZYAN_ASSERT(buffer); 268 ZYAN_ASSERT(context); 269 270 ZyanU64 address; 271 ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand, 0, &address)); 272 273 ZyanU8 padding = (formatter->addr_padding_relative == 274 ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_relative; 275 if ((formatter->addr_padding_relative == ZYDIS_PADDING_AUTO) && 276 (formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX)) 277 { 278 switch (context->instruction->address_width) 279 { 280 case 16: 281 padding = 4; 282 address = (ZyanU16)address; 283 break; 284 case 32: 285 padding = 8; 286 address = (ZyanU32)address; 287 break; 288 case 64: 289 padding = 16; 290 break; 291 default: 292 return ZYAN_STATUS_INVALID_ARGUMENT; 293 } 294 } 295 296 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_ADDRESS_REL); 297 switch (formatter->addr_signedness) 298 { 299 case ZYDIS_SIGNEDNESS_AUTO: 300 case ZYDIS_SIGNEDNESS_SIGNED: 301 ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->addr_base, &buffer->string, address, 302 padding, formatter->hex_force_leading_number, ZYAN_TRUE); 303 break; 304 case ZYDIS_SIGNEDNESS_UNSIGNED: 305 ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_ADD)); 306 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string, address, 307 padding, formatter->hex_force_leading_number); 308 break; 309 default: 310 return ZYAN_STATUS_INVALID_ARGUMENT; 311 } 312 313 return ZYAN_STATUS_SUCCESS; 314 } 315 316 ZyanStatus ZydisFormatterBasePrintIMM(const ZydisFormatter* formatter, 317 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 318 { 319 ZYAN_ASSERT(formatter); 320 ZYAN_ASSERT(buffer); 321 ZYAN_ASSERT(context); 322 323 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE); 324 325 const ZyanBool is_signed = 326 (formatter->imm_signedness == ZYDIS_SIGNEDNESS_SIGNED) || 327 (formatter->imm_signedness == ZYDIS_SIGNEDNESS_AUTO && (context->operand->imm.is_signed)); 328 if (is_signed && (context->operand->imm.value.s < 0)) 329 { 330 ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->imm_base, &buffer->string, 331 context->operand->imm.value.s, formatter->imm_padding, 332 formatter->hex_force_leading_number, ZYAN_FALSE); 333 return ZYAN_STATUS_SUCCESS; 334 } 335 ZyanU64 value; 336 ZyanU8 padding = (formatter->imm_padding == 337 ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->imm_padding; 338 switch (context->instruction->operand_width) 339 { 340 case 8: 341 if (formatter->imm_padding == ZYDIS_PADDING_AUTO) 342 { 343 padding = 2; 344 } 345 value = (ZyanU8 )context->operand->imm.value.u; 346 break; 347 case 16: 348 if (formatter->imm_padding == ZYDIS_PADDING_AUTO) 349 { 350 padding = 4; 351 } 352 value = (ZyanU16)context->operand->imm.value.u; 353 break; 354 case 32: 355 if (formatter->imm_padding == ZYDIS_PADDING_AUTO) 356 { 357 padding = 8; 358 } 359 value = (ZyanU32)context->operand->imm.value.u; 360 break; 361 case 64: 362 if (formatter->imm_padding == ZYDIS_PADDING_AUTO) 363 { 364 padding = 16; 365 } 366 value = (ZyanU64)context->operand->imm.value.u; 367 break; 368 default: 369 return ZYAN_STATUS_INVALID_ARGUMENT; 370 } 371 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->imm_base, &buffer->string, value, padding, 372 formatter->hex_force_leading_number); 373 374 return ZYAN_STATUS_SUCCESS; 375 } 376 377 /* ---------------------------------------------------------------------------------------------- */ 378 /* Optional tokens */ 379 /* ---------------------------------------------------------------------------------------------- */ 380 381 ZyanStatus ZydisFormatterBasePrintSegment(const ZydisFormatter* formatter, 382 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 383 { 384 ZYAN_ASSERT(formatter); 385 ZYAN_ASSERT(buffer); 386 ZYAN_ASSERT(context); 387 388 ZyanBool printed_segment = ZYAN_FALSE; 389 switch (context->operand->mem.segment) 390 { 391 case ZYDIS_REGISTER_ES: 392 case ZYDIS_REGISTER_CS: 393 case ZYDIS_REGISTER_FS: 394 case ZYDIS_REGISTER_GS: 395 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 396 context->operand->mem.segment)); 397 printed_segment = ZYAN_TRUE; 398 break; 399 case ZYDIS_REGISTER_SS: 400 if ((formatter->force_memory_segment) || 401 (context->instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_SS)) 402 { 403 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 404 context->operand->mem.segment)); 405 printed_segment = ZYAN_TRUE; 406 } 407 break; 408 case ZYDIS_REGISTER_DS: 409 if ((formatter->force_memory_segment) || 410 (context->instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_DS)) 411 { 412 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 413 context->operand->mem.segment)); 414 printed_segment = ZYAN_TRUE; 415 } 416 break; 417 default: 418 break; 419 } 420 if (printed_segment) 421 { 422 ZYDIS_BUFFER_APPEND(buffer, DELIM_SEGMENT); 423 } 424 425 return ZYAN_STATUS_SUCCESS; 426 } 427 428 ZyanStatus ZydisFormatterBasePrintPrefixes(const ZydisFormatter* formatter, 429 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 430 { 431 ZYAN_ASSERT(formatter); 432 ZYAN_ASSERT(buffer); 433 ZYAN_ASSERT(context); 434 435 if (formatter->detailed_prefixes) 436 { 437 for (ZyanU8 i = 0; i < context->instruction->raw.prefix_count; ++i) 438 { 439 const ZyanU8 value = context->instruction->raw.prefixes[i].value; 440 switch (context->instruction->raw.prefixes[i].type) 441 { 442 case ZYDIS_PREFIX_TYPE_IGNORED: 443 case ZYDIS_PREFIX_TYPE_MANDATORY: 444 { 445 if ((value & 0xF0) == 0x40) 446 { 447 if (buffer->is_token_list) 448 { 449 // TODO: Case 450 ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer, 451 TOK_PREF_REX[value & 0x0F])); 452 } else 453 { 454 ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, 455 STR_PREF_REX[value & 0x0F], formatter->case_prefixes)); 456 } 457 } else 458 { 459 switch (value) 460 { 461 case 0xF0: 462 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_LOCK, formatter->case_prefixes); 463 break; 464 case 0x2E: 465 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_CS, formatter->case_prefixes); 466 break; 467 case 0x36: 468 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_SS, formatter->case_prefixes); 469 break; 470 case 0x3E: 471 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_DS, formatter->case_prefixes); 472 break; 473 case 0x26: 474 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_ES, formatter->case_prefixes); 475 break; 476 case 0x64: 477 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_FS, formatter->case_prefixes); 478 break; 479 case 0x65: 480 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_GS, formatter->case_prefixes); 481 break; 482 default: 483 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_PREFIX); 484 ZYAN_CHECK(ZydisStringAppendHexU(&buffer->string, value, 0, 485 formatter->hex_force_leading_number, formatter->hex_uppercase, 486 ZYAN_NULL, ZYAN_NULL)); 487 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_WHITESPACE); 488 ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_WHITESPACE)); 489 break; 490 } 491 } 492 break; 493 } 494 case ZYDIS_PREFIX_TYPE_EFFECTIVE: 495 switch (value) 496 { 497 case 0xF0: 498 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_LOCK, formatter->case_prefixes); 499 break; 500 case 0xF2: 501 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XACQUIRE) 502 { 503 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XACQUIRE, formatter->case_prefixes); 504 } 505 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPNE) 506 { 507 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPNE, formatter->case_prefixes); 508 } 509 510 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_BND) 511 { 512 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_BND, formatter->case_prefixes); 513 } 514 break; 515 case 0xF3: 516 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XRELEASE) 517 { 518 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XRELEASE, formatter->case_prefixes); 519 } 520 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REP) 521 { 522 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REP, formatter->case_prefixes); 523 } 524 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPE) 525 { 526 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPE, formatter->case_prefixes); 527 } 528 break; 529 default: 530 break; 531 } 532 break; 533 default: 534 return ZYAN_STATUS_INVALID_ARGUMENT; 535 } 536 } 537 return ZYAN_STATUS_SUCCESS; 538 } 539 540 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XACQUIRE) 541 { 542 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XACQUIRE, formatter->case_prefixes); 543 } 544 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XRELEASE) 545 { 546 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XRELEASE, formatter->case_prefixes); 547 } 548 549 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_LOCK) 550 { 551 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_LOCK, formatter->case_prefixes); 552 } 553 554 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_BND) 555 { 556 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_BND, formatter->case_prefixes); 557 } 558 559 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_NOTRACK) 560 { 561 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_NOTRACK, formatter->case_prefixes); 562 } 563 564 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REP) 565 { 566 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REP, formatter->case_prefixes); 567 return ZYAN_STATUS_SUCCESS; 568 } 569 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPE) 570 { 571 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPE, formatter->case_prefixes); 572 return ZYAN_STATUS_SUCCESS; 573 } 574 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPNE) 575 { 576 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPNE, formatter->case_prefixes); 577 return ZYAN_STATUS_SUCCESS; 578 } 579 580 return ZYAN_STATUS_SUCCESS; 581 } 582 583 ZyanStatus ZydisFormatterBasePrintDecorator(const ZydisFormatter* formatter, 584 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisDecorator decorator) 585 { 586 ZYAN_ASSERT(formatter); 587 ZYAN_ASSERT(buffer); 588 ZYAN_ASSERT(context); 589 590 #if defined(ZYDIS_DISABLE_AVX512) && defined(ZYDIS_DISABLE_KNC) 591 ZYAN_UNUSED(formatter); 592 ZYAN_UNUSED(buffer); 593 ZYAN_UNUSED(context); 594 #endif 595 596 switch (decorator) 597 { 598 case ZYDIS_DECORATOR_MASK: 599 { 600 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC) 601 if (context->instruction->avx.mask.reg != ZYDIS_REGISTER_K0) 602 { 603 if (buffer->is_token_list) 604 { 605 ZYDIS_BUFFER_APPEND(buffer, DECO_BEGIN); 606 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 607 context->instruction->avx.mask.reg)); 608 ZYDIS_BUFFER_APPEND(buffer, DECO_END); 609 } else 610 { 611 ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_DECO_BEGIN)); 612 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 613 context->instruction->avx.mask.reg)); 614 ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_DECO_END)); 615 } 616 617 // Only print the zeroing decorator, if the instruction is not a "zeroing masking only" 618 // instruction (e.g. `vcmpsd`) 619 if ((context->instruction->avx.mask.mode == ZYDIS_MASK_MODE_ZEROING || 620 context->instruction->avx.mask.mode == ZYDIS_MASK_MODE_CONTROL_ZEROING) && 621 (context->instruction->raw.evex.z)) 622 { 623 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_ZERO, formatter->case_decorators); 624 } 625 } 626 #endif 627 break; 628 } 629 case ZYDIS_DECORATOR_BC: 630 #if !defined(ZYDIS_DISABLE_AVX512) 631 if (!context->instruction->avx.broadcast.is_static) 632 { 633 switch (context->instruction->avx.broadcast.mode) 634 { 635 case ZYDIS_BROADCAST_MODE_INVALID: 636 break; 637 case ZYDIS_BROADCAST_MODE_1_TO_2: 638 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO2, formatter->case_decorators); 639 break; 640 case ZYDIS_BROADCAST_MODE_1_TO_4: 641 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO4, formatter->case_decorators); 642 break; 643 case ZYDIS_BROADCAST_MODE_1_TO_8: 644 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO8, formatter->case_decorators); 645 break; 646 case ZYDIS_BROADCAST_MODE_1_TO_16: 647 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO16, formatter->case_decorators); 648 break; 649 case ZYDIS_BROADCAST_MODE_1_TO_32: 650 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO32, formatter->case_decorators); 651 break; 652 case ZYDIS_BROADCAST_MODE_1_TO_64: 653 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO64, formatter->case_decorators); 654 break; 655 case ZYDIS_BROADCAST_MODE_4_TO_8: 656 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_4TO8, formatter->case_decorators); 657 break; 658 case ZYDIS_BROADCAST_MODE_4_TO_16: 659 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_4TO16, formatter->case_decorators); 660 break; 661 case ZYDIS_BROADCAST_MODE_8_TO_16: 662 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_8TO16, formatter->case_decorators); 663 break; 664 default: 665 return ZYAN_STATUS_INVALID_ARGUMENT; 666 } 667 } 668 #endif 669 break; 670 case ZYDIS_DECORATOR_RC: 671 #if !defined(ZYDIS_DISABLE_AVX512) 672 if (context->instruction->avx.has_sae) 673 { 674 switch (context->instruction->avx.rounding.mode) 675 { 676 case ZYDIS_ROUNDING_MODE_INVALID: 677 break; 678 case ZYDIS_ROUNDING_MODE_RN: 679 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RN_SAE, formatter->case_decorators); 680 break; 681 case ZYDIS_ROUNDING_MODE_RD: 682 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RD_SAE, formatter->case_decorators); 683 break; 684 case ZYDIS_ROUNDING_MODE_RU: 685 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RU_SAE, formatter->case_decorators); 686 break; 687 case ZYDIS_ROUNDING_MODE_RZ: 688 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RZ_SAE, formatter->case_decorators); 689 break; 690 default: 691 return ZYAN_STATUS_INVALID_ARGUMENT; 692 } 693 } else 694 { 695 switch (context->instruction->avx.rounding.mode) 696 { 697 case ZYDIS_ROUNDING_MODE_INVALID: 698 break; 699 case ZYDIS_ROUNDING_MODE_RN: 700 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RN, formatter->case_decorators); 701 break; 702 case ZYDIS_ROUNDING_MODE_RD: 703 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RD, formatter->case_decorators); 704 break; 705 case ZYDIS_ROUNDING_MODE_RU: 706 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RU, formatter->case_decorators); 707 break; 708 case ZYDIS_ROUNDING_MODE_RZ: 709 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RZ, formatter->case_decorators); 710 break; 711 default: 712 return ZYAN_STATUS_INVALID_ARGUMENT; 713 } 714 } 715 #endif 716 break; 717 case ZYDIS_DECORATOR_SAE: 718 #if !defined(ZYDIS_DISABLE_AVX512) 719 if (context->instruction->avx.has_sae && !context->instruction->avx.rounding.mode) 720 { 721 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_SAE, formatter->case_decorators); 722 } 723 #endif 724 break; 725 case ZYDIS_DECORATOR_SWIZZLE: 726 #if !defined(ZYDIS_DISABLE_KNC) 727 switch (context->instruction->avx.swizzle.mode) 728 { 729 case ZYDIS_SWIZZLE_MODE_INVALID: 730 case ZYDIS_SWIZZLE_MODE_DCBA: 731 // Nothing to do here 732 break; 733 case ZYDIS_SWIZZLE_MODE_CDAB: 734 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_CDAB, formatter->case_decorators); 735 break; 736 case ZYDIS_SWIZZLE_MODE_BADC: 737 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_BADC, formatter->case_decorators); 738 break; 739 case ZYDIS_SWIZZLE_MODE_DACB: 740 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_DACB, formatter->case_decorators); 741 break; 742 case ZYDIS_SWIZZLE_MODE_AAAA: 743 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_AAAA, formatter->case_decorators); 744 break; 745 case ZYDIS_SWIZZLE_MODE_BBBB: 746 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_BBBB, formatter->case_decorators); 747 break; 748 case ZYDIS_SWIZZLE_MODE_CCCC: 749 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_CCCC, formatter->case_decorators); 750 break; 751 case ZYDIS_SWIZZLE_MODE_DDDD: 752 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_DDDD, formatter->case_decorators); 753 break; 754 default: 755 return ZYAN_STATUS_INVALID_ARGUMENT; 756 } 757 #endif 758 break; 759 case ZYDIS_DECORATOR_CONVERSION: 760 #if !defined(ZYDIS_DISABLE_KNC) 761 switch (context->instruction->avx.conversion.mode) 762 { 763 case ZYDIS_CONVERSION_MODE_INVALID: 764 break; 765 case ZYDIS_CONVERSION_MODE_FLOAT16: 766 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_FLOAT16, formatter->case_decorators); 767 break; 768 case ZYDIS_CONVERSION_MODE_SINT8: 769 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_SINT8, formatter->case_decorators); 770 break; 771 case ZYDIS_CONVERSION_MODE_UINT8: 772 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_UINT8, formatter->case_decorators); 773 break; 774 case ZYDIS_CONVERSION_MODE_SINT16: 775 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_SINT16, formatter->case_decorators); 776 break; 777 case ZYDIS_CONVERSION_MODE_UINT16: 778 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_UINT16, formatter->case_decorators); 779 break; 780 default: 781 return ZYAN_STATUS_INVALID_ARGUMENT; 782 } 783 #endif 784 break; 785 case ZYDIS_DECORATOR_EH: 786 #if !defined(ZYDIS_DISABLE_KNC) 787 if (context->instruction->avx.has_eviction_hint) 788 { 789 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_EH, formatter->case_decorators); 790 } 791 #endif 792 break; 793 default: 794 return ZYAN_STATUS_INVALID_ARGUMENT; 795 } 796 797 return ZYAN_STATUS_SUCCESS; 798 } 799 800 /* ---------------------------------------------------------------------------------------------- */ 801 802 /* ============================================================================================== */ 803