tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

FormatterBase.c (30393B)


      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/Zydis/Internal/FormatterBase.h"
     28 #include "zydis/Zydis/Utils.h"
     29 
     30 /* ============================================================================================== */
     31 /* Constants                                                                                      */
     32 /* ============================================================================================== */
     33 
     34 #include "zydis/Zydis/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 /* ============================================================================================== */