FormatterBase.c (30214B)
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_VSIB)); 90 91 if (formatter->force_memory_size) 92 { 93 return operand->size; 94 } 95 96 if (!context->operands) 97 { 98 // Single operand formatting. We can not derive the explicit size by using the other 99 // operands. 100 return 0; 101 } 102 103 switch (operand->id) 104 { 105 case 0: 106 if (context->instruction->operand_count_visible < 2) 107 { 108 return 0; 109 } 110 if ((context->operands[1].type == ZYDIS_OPERAND_TYPE_UNUSED) || 111 (context->operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE)) 112 { 113 return context->operands[0].size; 114 } 115 if (context->operands[0].size != context->operands[1].size) 116 { 117 return context->operands[0].size; 118 } 119 if ((context->operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER) && 120 (context->operands[1].visibility == ZYDIS_OPERAND_VISIBILITY_IMPLICIT) && 121 (context->operands[1].reg.value == ZYDIS_REGISTER_CL)) 122 { 123 return context->operands[0].size; 124 } 125 break; 126 case 1: 127 case 2: 128 if (context->operands[operand->id - 1].size != 129 context->operands[operand->id].size) 130 { 131 return context->operands[operand->id].size; 132 } 133 break; 134 default: 135 break; 136 } 137 138 return 0; 139 } 140 141 /* ============================================================================================== */ 142 /* Formatter functions */ 143 /* ============================================================================================== */ 144 145 /* ---------------------------------------------------------------------------------------------- */ 146 /* Operands */ 147 /* ---------------------------------------------------------------------------------------------- */ 148 149 ZyanStatus ZydisFormatterBaseFormatOperandREG(const ZydisFormatter* formatter, 150 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 151 { 152 ZYAN_ASSERT(formatter); 153 ZYAN_ASSERT(buffer); 154 ZYAN_ASSERT(context); 155 156 return formatter->func_print_register(formatter, buffer, context, context->operand->reg.value); 157 } 158 159 ZyanStatus ZydisFormatterBaseFormatOperandPTR(const ZydisFormatter* formatter, 160 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 161 { 162 ZYAN_ASSERT(formatter); 163 ZYAN_ASSERT(buffer); 164 ZYAN_ASSERT(context); 165 166 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE); 167 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string, 168 context->operand->ptr.segment, 4, formatter->hex_force_leading_number); 169 ZYDIS_BUFFER_APPEND(buffer, DELIM_SEGMENT); 170 171 ZyanU8 padding; 172 switch (context->instruction->operand_width) 173 { 174 case 16: 175 padding = 4; 176 break; 177 case 32: 178 padding = 8; 179 break; 180 default: 181 return ZYAN_STATUS_INVALID_ARGUMENT; 182 } 183 184 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE); 185 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string, 186 context->operand->ptr.offset , padding, formatter->hex_force_leading_number); 187 188 return ZYAN_STATUS_SUCCESS; 189 } 190 191 ZyanStatus ZydisFormatterBaseFormatOperandIMM(const ZydisFormatter* formatter, 192 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 193 { 194 ZYAN_ASSERT(formatter); 195 ZYAN_ASSERT(buffer); 196 ZYAN_ASSERT(context); 197 198 // The immediate operand contains an address 199 if (context->operand->imm.is_relative) 200 { 201 const ZyanBool absolute = !formatter->force_relative_branches && 202 (context->runtime_address != ZYDIS_RUNTIME_ADDRESS_NONE); 203 if (absolute) 204 { 205 return formatter->func_print_address_abs(formatter, buffer, context); 206 } 207 return formatter->func_print_address_rel(formatter, buffer, context); 208 } 209 210 // The immediate operand contains an actual ordinal value 211 return formatter->func_print_imm(formatter, buffer, context); 212 } 213 214 /* ---------------------------------------------------------------------------------------------- */ 215 /* Elemental tokens */ 216 /* ---------------------------------------------------------------------------------------------- */ 217 218 ZyanStatus ZydisFormatterBasePrintAddressABS(const ZydisFormatter* formatter, 219 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 220 { 221 ZYAN_ASSERT(formatter); 222 ZYAN_ASSERT(buffer); 223 ZYAN_ASSERT(context); 224 225 ZyanU64 address; 226 ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand, 227 context->runtime_address, &address)); 228 ZyanU8 padding = (formatter->addr_padding_absolute == 229 ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_absolute; 230 if ((formatter->addr_padding_absolute == ZYDIS_PADDING_AUTO) && 231 (formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX)) 232 { 233 switch (context->instruction->stack_width) 234 { 235 case 16: 236 padding = 4; 237 address = (ZyanU16)address; 238 break; 239 case 32: 240 padding = 8; 241 address = (ZyanU32)address; 242 break; 243 case 64: 244 padding = 16; 245 break; 246 default: 247 return ZYAN_STATUS_INVALID_ARGUMENT; 248 } 249 } 250 251 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_ADDRESS_ABS); 252 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string, address, padding, 253 formatter->hex_force_leading_number); 254 255 return ZYAN_STATUS_SUCCESS; 256 } 257 258 ZyanStatus ZydisFormatterBasePrintAddressREL(const ZydisFormatter* formatter, 259 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 260 { 261 ZYAN_ASSERT(formatter); 262 ZYAN_ASSERT(buffer); 263 ZYAN_ASSERT(context); 264 265 ZyanU64 address; 266 ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand, 0, &address)); 267 268 ZyanU8 padding = (formatter->addr_padding_relative == 269 ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_relative; 270 if ((formatter->addr_padding_relative == ZYDIS_PADDING_AUTO) && 271 (formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX)) 272 { 273 switch (context->instruction->stack_width) 274 { 275 case 16: 276 padding = 4; 277 address = (ZyanU16)address; 278 break; 279 case 32: 280 padding = 8; 281 address = (ZyanU32)address; 282 break; 283 case 64: 284 padding = 16; 285 break; 286 default: 287 return ZYAN_STATUS_INVALID_ARGUMENT; 288 } 289 } 290 291 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_ADDRESS_REL); 292 switch (formatter->addr_signedness) 293 { 294 case ZYDIS_SIGNEDNESS_AUTO: 295 case ZYDIS_SIGNEDNESS_SIGNED: 296 ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->addr_base, &buffer->string, address, 297 padding, formatter->hex_force_leading_number, ZYAN_TRUE); 298 break; 299 case ZYDIS_SIGNEDNESS_UNSIGNED: 300 ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_ADD)); 301 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->addr_base, &buffer->string, address, 302 padding, formatter->hex_force_leading_number); 303 break; 304 default: 305 return ZYAN_STATUS_INVALID_ARGUMENT; 306 } 307 308 return ZYAN_STATUS_SUCCESS; 309 } 310 311 ZyanStatus ZydisFormatterBasePrintIMM(const ZydisFormatter* formatter, 312 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 313 { 314 ZYAN_ASSERT(formatter); 315 ZYAN_ASSERT(buffer); 316 ZYAN_ASSERT(context); 317 318 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE); 319 320 const ZyanBool is_signed = 321 (formatter->imm_signedness == ZYDIS_SIGNEDNESS_SIGNED) || 322 (formatter->imm_signedness == ZYDIS_SIGNEDNESS_AUTO && (context->operand->imm.is_signed)); 323 if (is_signed && (context->operand->imm.value.s < 0)) 324 { 325 ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->imm_base, &buffer->string, 326 context->operand->imm.value.s, formatter->imm_padding, 327 formatter->hex_force_leading_number, ZYAN_FALSE); 328 return ZYAN_STATUS_SUCCESS; 329 } 330 ZyanU64 value; 331 ZyanU8 padding = (formatter->imm_padding == 332 ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->imm_padding; 333 switch (context->instruction->operand_width) 334 { 335 case 8: 336 if (formatter->imm_padding == ZYDIS_PADDING_AUTO) 337 { 338 padding = 2; 339 } 340 value = (ZyanU8 )context->operand->imm.value.u; 341 break; 342 case 16: 343 if (formatter->imm_padding == ZYDIS_PADDING_AUTO) 344 { 345 padding = 4; 346 } 347 value = (ZyanU16)context->operand->imm.value.u; 348 break; 349 case 32: 350 if (formatter->imm_padding == ZYDIS_PADDING_AUTO) 351 { 352 padding = 8; 353 } 354 value = (ZyanU32)context->operand->imm.value.u; 355 break; 356 case 64: 357 if (formatter->imm_padding == ZYDIS_PADDING_AUTO) 358 { 359 padding = 16; 360 } 361 value = (ZyanU64)context->operand->imm.value.u; 362 break; 363 default: 364 return ZYAN_STATUS_INVALID_ARGUMENT; 365 } 366 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->imm_base, &buffer->string, value, padding, 367 formatter->hex_force_leading_number); 368 369 return ZYAN_STATUS_SUCCESS; 370 } 371 372 /* ---------------------------------------------------------------------------------------------- */ 373 /* Optional tokens */ 374 /* ---------------------------------------------------------------------------------------------- */ 375 376 ZyanStatus ZydisFormatterBasePrintSegment(const ZydisFormatter* formatter, 377 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 378 { 379 ZYAN_ASSERT(formatter); 380 ZYAN_ASSERT(buffer); 381 ZYAN_ASSERT(context); 382 383 ZyanBool printed_segment = ZYAN_FALSE; 384 switch (context->operand->mem.segment) 385 { 386 case ZYDIS_REGISTER_ES: 387 case ZYDIS_REGISTER_CS: 388 case ZYDIS_REGISTER_FS: 389 case ZYDIS_REGISTER_GS: 390 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 391 context->operand->mem.segment)); 392 printed_segment = ZYAN_TRUE; 393 break; 394 case ZYDIS_REGISTER_SS: 395 if ((formatter->force_memory_segment) || 396 (context->instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_SS)) 397 { 398 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 399 context->operand->mem.segment)); 400 printed_segment = ZYAN_TRUE; 401 } 402 break; 403 case ZYDIS_REGISTER_DS: 404 if ((formatter->force_memory_segment) || 405 (context->instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_DS)) 406 { 407 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 408 context->operand->mem.segment)); 409 printed_segment = ZYAN_TRUE; 410 } 411 break; 412 default: 413 break; 414 } 415 if (printed_segment) 416 { 417 ZYDIS_BUFFER_APPEND(buffer, DELIM_SEGMENT); 418 } 419 420 return ZYAN_STATUS_SUCCESS; 421 } 422 423 ZyanStatus ZydisFormatterBasePrintPrefixes(const ZydisFormatter* formatter, 424 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 425 { 426 ZYAN_ASSERT(formatter); 427 ZYAN_ASSERT(buffer); 428 ZYAN_ASSERT(context); 429 430 if (formatter->detailed_prefixes) 431 { 432 for (ZyanU8 i = 0; i < context->instruction->raw.prefix_count; ++i) 433 { 434 const ZyanU8 value = context->instruction->raw.prefixes[i].value; 435 switch (context->instruction->raw.prefixes[i].type) 436 { 437 case ZYDIS_PREFIX_TYPE_IGNORED: 438 case ZYDIS_PREFIX_TYPE_MANDATORY: 439 { 440 if ((value & 0xF0) == 0x40) 441 { 442 if (buffer->is_token_list) 443 { 444 // TODO: Case 445 ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer, 446 TOK_PREF_REX[value & 0x0F])); 447 } else 448 { 449 ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, 450 STR_PREF_REX[value & 0x0F], formatter->case_prefixes)); 451 } 452 } else 453 { 454 switch (value) 455 { 456 case 0xF0: 457 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_LOCK, formatter->case_prefixes); 458 break; 459 case 0x2E: 460 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_CS, formatter->case_prefixes); 461 break; 462 case 0x36: 463 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_SS, formatter->case_prefixes); 464 break; 465 case 0x3E: 466 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_DS, formatter->case_prefixes); 467 break; 468 case 0x26: 469 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_ES, formatter->case_prefixes); 470 break; 471 case 0x64: 472 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_FS, formatter->case_prefixes); 473 break; 474 case 0x65: 475 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_SEG_GS, formatter->case_prefixes); 476 break; 477 default: 478 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_PREFIX); 479 ZYAN_CHECK(ZydisStringAppendHexU(&buffer->string, value, 0, 480 formatter->hex_force_leading_number, formatter->hex_uppercase, 481 ZYAN_NULL, ZYAN_NULL)); 482 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_WHITESPACE); 483 ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_WHITESPACE)); 484 break; 485 } 486 } 487 break; 488 } 489 case ZYDIS_PREFIX_TYPE_EFFECTIVE: 490 switch (value) 491 { 492 case 0xF0: 493 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_LOCK, formatter->case_prefixes); 494 break; 495 case 0xF2: 496 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XACQUIRE) 497 { 498 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XACQUIRE, formatter->case_prefixes); 499 } 500 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPNE) 501 { 502 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPNE, formatter->case_prefixes); 503 } 504 505 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_BND) 506 { 507 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_BND, formatter->case_prefixes); 508 } 509 break; 510 case 0xF3: 511 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XRELEASE) 512 { 513 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XRELEASE, formatter->case_prefixes); 514 } 515 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REP) 516 { 517 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REP, formatter->case_prefixes); 518 } 519 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPE) 520 { 521 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPE, formatter->case_prefixes); 522 } 523 break; 524 default: 525 break; 526 } 527 break; 528 default: 529 return ZYAN_STATUS_INVALID_ARGUMENT; 530 } 531 } 532 return ZYAN_STATUS_SUCCESS; 533 } 534 535 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XACQUIRE) 536 { 537 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XACQUIRE, formatter->case_prefixes); 538 } 539 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_XRELEASE) 540 { 541 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_XRELEASE, formatter->case_prefixes); 542 } 543 544 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_LOCK) 545 { 546 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_LOCK, formatter->case_prefixes); 547 } 548 549 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_BND) 550 { 551 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_BND, formatter->case_prefixes); 552 } 553 554 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_NOTRACK) 555 { 556 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_NOTRACK, formatter->case_prefixes); 557 } 558 559 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REP) 560 { 561 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REP, formatter->case_prefixes); 562 return ZYAN_STATUS_SUCCESS; 563 } 564 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPE) 565 { 566 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPE, formatter->case_prefixes); 567 return ZYAN_STATUS_SUCCESS; 568 } 569 if (context->instruction->attributes & ZYDIS_ATTRIB_HAS_REPNE) 570 { 571 ZYDIS_BUFFER_APPEND_CASE(buffer, PREF_REPNE, formatter->case_prefixes); 572 return ZYAN_STATUS_SUCCESS; 573 } 574 575 return ZYAN_STATUS_SUCCESS; 576 } 577 578 ZyanStatus ZydisFormatterBasePrintDecorator(const ZydisFormatter* formatter, 579 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisDecorator decorator) 580 { 581 ZYAN_ASSERT(formatter); 582 ZYAN_ASSERT(buffer); 583 ZYAN_ASSERT(context); 584 585 #if defined(ZYDIS_DISABLE_AVX512) && defined(ZYDIS_DISABLE_KNC) 586 ZYAN_UNUSED(formatter); 587 ZYAN_UNUSED(buffer); 588 ZYAN_UNUSED(context); 589 #endif 590 591 switch (decorator) 592 { 593 case ZYDIS_DECORATOR_MASK: 594 { 595 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC) 596 if (context->instruction->avx.mask.reg != ZYDIS_REGISTER_K0) 597 { 598 if (buffer->is_token_list) 599 { 600 ZYDIS_BUFFER_APPEND(buffer, DECO_BEGIN); 601 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 602 context->instruction->avx.mask.reg)); 603 ZYDIS_BUFFER_APPEND(buffer, DECO_END); 604 } else 605 { 606 ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_DECO_BEGIN)); 607 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 608 context->instruction->avx.mask.reg)); 609 ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_DECO_END)); 610 } 611 612 // Only print the zeroing decorator, if the instruction is not a "zeroing masking only" 613 // instruction (e.g. `vcmpsd`) 614 if ((context->instruction->avx.mask.mode == ZYDIS_MASK_MODE_ZEROING || 615 context->instruction->avx.mask.mode == ZYDIS_MASK_MODE_CONTROL_ZEROING) && 616 (context->instruction->raw.evex.z)) 617 { 618 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_ZERO, formatter->case_decorators); 619 } 620 } 621 #endif 622 break; 623 } 624 case ZYDIS_DECORATOR_BC: 625 #if !defined(ZYDIS_DISABLE_AVX512) 626 if (!context->instruction->avx.broadcast.is_static) 627 { 628 switch (context->instruction->avx.broadcast.mode) 629 { 630 case ZYDIS_BROADCAST_MODE_INVALID: 631 break; 632 case ZYDIS_BROADCAST_MODE_1_TO_2: 633 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO2, formatter->case_decorators); 634 break; 635 case ZYDIS_BROADCAST_MODE_1_TO_4: 636 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO4, formatter->case_decorators); 637 break; 638 case ZYDIS_BROADCAST_MODE_1_TO_8: 639 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO8, formatter->case_decorators); 640 break; 641 case ZYDIS_BROADCAST_MODE_1_TO_16: 642 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO16, formatter->case_decorators); 643 break; 644 case ZYDIS_BROADCAST_MODE_1_TO_32: 645 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO32, formatter->case_decorators); 646 break; 647 case ZYDIS_BROADCAST_MODE_1_TO_64: 648 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_1TO64, formatter->case_decorators); 649 break; 650 case ZYDIS_BROADCAST_MODE_4_TO_8: 651 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_4TO8, formatter->case_decorators); 652 break; 653 case ZYDIS_BROADCAST_MODE_4_TO_16: 654 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_4TO16, formatter->case_decorators); 655 break; 656 case ZYDIS_BROADCAST_MODE_8_TO_16: 657 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_8TO16, formatter->case_decorators); 658 break; 659 default: 660 return ZYAN_STATUS_INVALID_ARGUMENT; 661 } 662 } 663 #endif 664 break; 665 case ZYDIS_DECORATOR_RC: 666 #if !defined(ZYDIS_DISABLE_AVX512) 667 if (context->instruction->avx.has_sae) 668 { 669 switch (context->instruction->avx.rounding.mode) 670 { 671 case ZYDIS_ROUNDING_MODE_INVALID: 672 break; 673 case ZYDIS_ROUNDING_MODE_RN: 674 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RN_SAE, formatter->case_decorators); 675 break; 676 case ZYDIS_ROUNDING_MODE_RD: 677 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RD_SAE, formatter->case_decorators); 678 break; 679 case ZYDIS_ROUNDING_MODE_RU: 680 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RU_SAE, formatter->case_decorators); 681 break; 682 case ZYDIS_ROUNDING_MODE_RZ: 683 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RZ_SAE, formatter->case_decorators); 684 break; 685 default: 686 return ZYAN_STATUS_INVALID_ARGUMENT; 687 } 688 } else 689 { 690 switch (context->instruction->avx.rounding.mode) 691 { 692 case ZYDIS_ROUNDING_MODE_INVALID: 693 break; 694 case ZYDIS_ROUNDING_MODE_RN: 695 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RN, formatter->case_decorators); 696 break; 697 case ZYDIS_ROUNDING_MODE_RD: 698 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RD, formatter->case_decorators); 699 break; 700 case ZYDIS_ROUNDING_MODE_RU: 701 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RU, formatter->case_decorators); 702 break; 703 case ZYDIS_ROUNDING_MODE_RZ: 704 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_RZ, formatter->case_decorators); 705 break; 706 default: 707 return ZYAN_STATUS_INVALID_ARGUMENT; 708 } 709 } 710 #endif 711 break; 712 case ZYDIS_DECORATOR_SAE: 713 #if !defined(ZYDIS_DISABLE_AVX512) 714 if (context->instruction->avx.has_sae && !context->instruction->avx.rounding.mode) 715 { 716 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_SAE, formatter->case_decorators); 717 } 718 #endif 719 break; 720 case ZYDIS_DECORATOR_SWIZZLE: 721 #if !defined(ZYDIS_DISABLE_KNC) 722 switch (context->instruction->avx.swizzle.mode) 723 { 724 case ZYDIS_SWIZZLE_MODE_INVALID: 725 case ZYDIS_SWIZZLE_MODE_DCBA: 726 // Nothing to do here 727 break; 728 case ZYDIS_SWIZZLE_MODE_CDAB: 729 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_CDAB, formatter->case_decorators); 730 break; 731 case ZYDIS_SWIZZLE_MODE_BADC: 732 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_BADC, formatter->case_decorators); 733 break; 734 case ZYDIS_SWIZZLE_MODE_DACB: 735 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_DACB, formatter->case_decorators); 736 break; 737 case ZYDIS_SWIZZLE_MODE_AAAA: 738 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_AAAA, formatter->case_decorators); 739 break; 740 case ZYDIS_SWIZZLE_MODE_BBBB: 741 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_BBBB, formatter->case_decorators); 742 break; 743 case ZYDIS_SWIZZLE_MODE_CCCC: 744 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_CCCC, formatter->case_decorators); 745 break; 746 case ZYDIS_SWIZZLE_MODE_DDDD: 747 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_DDDD, formatter->case_decorators); 748 break; 749 default: 750 return ZYAN_STATUS_INVALID_ARGUMENT; 751 } 752 #endif 753 break; 754 case ZYDIS_DECORATOR_CONVERSION: 755 #if !defined(ZYDIS_DISABLE_KNC) 756 switch (context->instruction->avx.conversion.mode) 757 { 758 case ZYDIS_CONVERSION_MODE_INVALID: 759 break; 760 case ZYDIS_CONVERSION_MODE_FLOAT16: 761 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_FLOAT16, formatter->case_decorators); 762 break; 763 case ZYDIS_CONVERSION_MODE_SINT8: 764 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_SINT8, formatter->case_decorators); 765 break; 766 case ZYDIS_CONVERSION_MODE_UINT8: 767 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_UINT8, formatter->case_decorators); 768 break; 769 case ZYDIS_CONVERSION_MODE_SINT16: 770 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_SINT16, formatter->case_decorators); 771 break; 772 case ZYDIS_CONVERSION_MODE_UINT16: 773 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_UINT16, formatter->case_decorators); 774 break; 775 default: 776 return ZYAN_STATUS_INVALID_ARGUMENT; 777 } 778 #endif 779 break; 780 case ZYDIS_DECORATOR_EH: 781 #if !defined(ZYDIS_DISABLE_KNC) 782 if (context->instruction->avx.has_eviction_hint) 783 { 784 ZYDIS_BUFFER_APPEND_CASE(buffer, DECO_EH, formatter->case_decorators); 785 } 786 #endif 787 break; 788 default: 789 return ZYAN_STATUS_INVALID_ARGUMENT; 790 } 791 792 return ZYAN_STATUS_SUCCESS; 793 } 794 795 /* ---------------------------------------------------------------------------------------------- */ 796 797 /* ============================================================================================== */