duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

Register.c (8411B)


      1 /***************************************************************************************************
      2 
      3   Zyan Disassembler Library (Zydis)
      4 
      5   Original Author : Florian Bernd
      6 
      7  * Permission is hereby granted, free of charge, to any person obtaining a copy
      8  * of this software and associated documentation files (the "Software"), to deal
      9  * in the Software without restriction, including without limitation the rights
     10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11  * copies of the Software, and to permit persons to whom the Software is
     12  * furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included in all
     15  * copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24 
     25 ***************************************************************************************************/
     26 
     27 #include <Zydis/Register.h>
     28 
     29 /* ============================================================================================== */
     30 /* Register strings                                                                               */
     31 /* ============================================================================================== */
     32 
     33 #include <Generated/EnumRegister.inc>
     34 
     35 /* ============================================================================================== */
     36 /* Register-class mapping                                                                         */
     37 /* ============================================================================================== */
     38 
     39 /**
     40  * Defines the `ZydisRegisterMapItem` struct.
     41  */
     42 typedef struct ZydisRegisterLookupItem
     43 {
     44     /**
     45      * The register class.
     46      */
     47     ZydisRegisterClass class;
     48     /**
     49      * The register id.
     50      */
     51     ZyanI8 id;
     52     /**
     53      * The width of register 16- and 32-bit mode.
     54      */
     55     ZydisRegisterWidth width;
     56     /**
     57      * The width of register in 64-bit mode.
     58      */
     59     ZydisRegisterWidth width64;
     60 } ZydisRegisterLookupItem;
     61 
     62 #include <Generated/RegisterLookup.inc>
     63 
     64 /**
     65  * Defines the `ZydisRegisterClassLookupItem` struct.
     66  */
     67 typedef struct ZydisRegisterClassLookupItem_
     68 {
     69     /**
     70      * The lowest register of the current class.
     71      */
     72     ZydisRegister lo;
     73     /**
     74      * The highest register of the current class.
     75      */
     76     ZydisRegister hi;
     77     /**
     78      * The width of registers of the current class in 16- and 32-bit mode.
     79      */
     80     ZydisRegisterWidth width;
     81     /**
     82      * The width of registers of the current class in 64-bit mode.
     83      */
     84     ZydisRegisterWidth width64;
     85 } ZydisRegisterClassLookupItem;
     86 
     87 #include <Generated/RegisterClassLookup.inc>
     88 
     89 /* ============================================================================================== */
     90 /* Exported functions                                                                             */
     91 /* ============================================================================================== */
     92 
     93 /* ---------------------------------------------------------------------------------------------- */
     94 /* Register                                                                                       */
     95 /* ---------------------------------------------------------------------------------------------- */
     96 
     97 ZydisRegister ZydisRegisterEncode(ZydisRegisterClass register_class, ZyanU8 id)
     98 {
     99     if ((register_class == ZYDIS_REGCLASS_INVALID) ||
    100         (register_class == ZYDIS_REGCLASS_FLAGS) ||
    101         (register_class == ZYDIS_REGCLASS_IP))
    102     {
    103         return ZYDIS_REGISTER_NONE;
    104     }
    105 
    106     if ((ZyanUSize)register_class >= ZYAN_ARRAY_LENGTH(REG_CLASS_LOOKUP))
    107     {
    108         return ZYDIS_REGISTER_NONE;
    109     }
    110 
    111     const ZydisRegisterClassLookupItem* item = &REG_CLASS_LOOKUP[register_class];
    112     if (id <= (item->hi - item->lo))
    113     {
    114         return item->lo + id;
    115     }
    116 
    117     return ZYDIS_REGISTER_NONE;
    118 }
    119 
    120 ZyanI8 ZydisRegisterGetId(ZydisRegister reg)
    121 {
    122     if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))
    123     {
    124         return -1;
    125     }
    126 
    127     return REG_LOOKUP[reg].id;
    128 }
    129 
    130 ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg)
    131 {
    132     if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))
    133     {
    134         return ZYDIS_REGCLASS_INVALID;
    135     }
    136 
    137     return REG_LOOKUP[reg].class;
    138 }
    139 
    140 ZydisRegisterWidth ZydisRegisterGetWidth(ZydisMachineMode mode, ZydisRegister reg)
    141 {
    142     if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))
    143     {
    144         return 0;
    145     }
    146 
    147     return (mode == ZYDIS_MACHINE_MODE_LONG_64)
    148         ? REG_LOOKUP[reg].width64
    149         : REG_LOOKUP[reg].width;
    150 }
    151 
    152 ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode, ZydisRegister reg)
    153 {
    154     if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))
    155     {
    156         return ZYDIS_REGISTER_NONE;
    157     }
    158 
    159     static const ZyanU8 GPR8_MAPPING[20] =
    160     {
    161         /* AL   */  0,
    162         /* CL   */  1,
    163         /* DL   */  2,
    164         /* BL   */  3,
    165         /* AH   */  0,
    166         /* CH   */  1,
    167         /* DH   */  2,
    168         /* BH   */  3,
    169         /* SPL  */  4,
    170         /* BPL  */  5,
    171         /* SIL  */  6,
    172         /* DIL  */  7,
    173         /* R8B  */  8,
    174         /* R9B  */  9,
    175         /* R10B */ 10,
    176         /* R11B */ 11,
    177         /* R12B */ 12,
    178         /* R13B */ 13,
    179         /* R14B */ 14,
    180         /* R15B */ 15,
    181     };
    182 
    183     const ZydisRegisterClass reg_class = REG_LOOKUP[reg].class;
    184     if ((reg_class == ZYDIS_REGCLASS_INVALID) ||
    185         ((reg_class == ZYDIS_REGCLASS_GPR64) && (mode != ZYDIS_MACHINE_MODE_LONG_64)))
    186     {
    187         return ZYDIS_REGISTER_NONE;
    188     }
    189 
    190     ZyanU8 reg_id = REG_LOOKUP[reg].id;
    191     switch (reg_class)
    192     {
    193     case ZYDIS_REGCLASS_GPR8:
    194         reg_id = GPR8_MAPPING[reg_id];
    195         ZYAN_FALLTHROUGH;
    196     case ZYDIS_REGCLASS_GPR16:
    197     case ZYDIS_REGCLASS_GPR32:
    198     case ZYDIS_REGCLASS_GPR64:
    199         switch (mode)
    200         {
    201         case ZYDIS_MACHINE_MODE_LONG_64:
    202             return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR64].lo + reg_id;
    203         case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
    204         case ZYDIS_MACHINE_MODE_LEGACY_32:
    205             return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR32].lo + reg_id;
    206         case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
    207         case ZYDIS_MACHINE_MODE_LEGACY_16:
    208         case ZYDIS_MACHINE_MODE_REAL_16:
    209             return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR16].lo + reg_id;
    210         default:
    211             return ZYDIS_REGISTER_NONE;
    212         }
    213     case ZYDIS_REGCLASS_XMM:
    214     case ZYDIS_REGCLASS_YMM:
    215     case ZYDIS_REGCLASS_ZMM:
    216 #if defined(ZYDIS_DISABLE_AVX512) && defined(ZYDIS_DISABLE_KNC)
    217         return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_YMM].lo + reg_id;
    218 #else
    219         return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_ZMM].lo + reg_id;
    220 #endif
    221     default:
    222         return ZYDIS_REGISTER_NONE;
    223     }
    224 }
    225 
    226 const char* ZydisRegisterGetString(ZydisRegister reg)
    227 {
    228     if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(STR_REGISTERS))
    229     {
    230         return ZYAN_NULL;
    231     }
    232 
    233     return STR_REGISTERS[reg].data;
    234 }
    235 
    236 const ZydisShortString* ZydisRegisterGetStringWrapped(ZydisRegister reg)
    237 {
    238     if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(STR_REGISTERS))
    239     {
    240         return ZYAN_NULL;
    241     }
    242 
    243     return &STR_REGISTERS[reg];
    244 }
    245 
    246 /* ---------------------------------------------------------------------------------------------- */
    247 /* Register class                                                                                 */
    248 /* ---------------------------------------------------------------------------------------------- */
    249 
    250 ZydisRegisterWidth ZydisRegisterClassGetWidth(ZydisMachineMode mode,
    251     ZydisRegisterClass register_class)
    252 {
    253     if ((ZyanUSize)register_class >= ZYAN_ARRAY_LENGTH(REG_CLASS_LOOKUP))
    254     {
    255         return 0;
    256     }
    257 
    258     return (mode == ZYDIS_MACHINE_MODE_LONG_64)
    259         ? REG_CLASS_LOOKUP[register_class].width64
    260         : REG_CLASS_LOOKUP[register_class].width;
    261 }
    262 
    263 /* ---------------------------------------------------------------------------------------------- */
    264 
    265 /* ============================================================================================== */