Register.c (9403B)
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/Zydis/Register.h" 28 29 /* ============================================================================================== */ 30 /* Register strings */ 31 /* ============================================================================================== */ 32 33 #include "zydis/Zydis/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 "zydis/Zydis/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 "zydis/Zydis/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 = ®_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 if (mode > ZYDIS_MACHINE_MODE_MAX_VALUE) 160 { 161 return ZYDIS_REGISTER_NONE; 162 } 163 164 const ZydisRegisterClass reg_class = REG_LOOKUP[reg].class; 165 166 if ((reg_class == ZYDIS_REGCLASS_INVALID) || 167 ((reg_class == ZYDIS_REGCLASS_GPR64) && (mode != ZYDIS_MACHINE_MODE_LONG_64))) 168 { 169 return ZYDIS_REGISTER_NONE; 170 } 171 172 static const ZydisRegister STATIC_MAPPING[ZYDIS_REGCLASS_MAX_VALUE + 1][3] = 173 { 174 /* 16 */ /* 32 */ /* 64 */ 175 [ZYDIS_REGCLASS_FLAGS] = { ZYDIS_REGISTER_FLAGS, ZYDIS_REGISTER_EFLAGS, ZYDIS_REGISTER_RFLAGS }, 176 [ZYDIS_REGCLASS_IP ] = { ZYDIS_REGISTER_IP , ZYDIS_REGISTER_EIP , ZYDIS_REGISTER_RIP }, 177 }; 178 ZYAN_ASSERT(reg_class < ZYAN_ARRAY_LENGTH(STATIC_MAPPING)); 179 180 ZyanU8 mode_bits; 181 switch (mode) 182 { 183 case ZYDIS_MACHINE_MODE_LONG_64: 184 mode_bits = 2; 185 break; 186 case ZYDIS_MACHINE_MODE_LONG_COMPAT_32: 187 case ZYDIS_MACHINE_MODE_LEGACY_32: 188 mode_bits = 1; 189 break; 190 case ZYDIS_MACHINE_MODE_LONG_COMPAT_16: 191 case ZYDIS_MACHINE_MODE_LEGACY_16: 192 case ZYDIS_MACHINE_MODE_REAL_16: 193 mode_bits = 0; 194 break; 195 default: 196 ZYAN_UNREACHABLE; 197 } 198 199 const ZydisRegister static_reg = STATIC_MAPPING[reg_class][mode_bits]; 200 if (static_reg != ZYDIS_REGISTER_NONE) 201 { 202 return static_reg; 203 } 204 205 static const ZyanU8 GPR8_MAPPING[20] = 206 { 207 /* AL */ 0, 208 /* CL */ 1, 209 /* DL */ 2, 210 /* BL */ 3, 211 /* AH */ 0, 212 /* CH */ 1, 213 /* DH */ 2, 214 /* BH */ 3, 215 /* SPL */ 4, 216 /* BPL */ 5, 217 /* SIL */ 6, 218 /* DIL */ 7, 219 /* R8B */ 8, 220 /* R9B */ 9, 221 /* R10B */ 10, 222 /* R11B */ 11, 223 /* R12B */ 12, 224 /* R13B */ 13, 225 /* R14B */ 14, 226 /* R15B */ 15 227 }; 228 229 ZyanU8 reg_id = REG_LOOKUP[reg].id; 230 switch (reg_class) 231 { 232 case ZYDIS_REGCLASS_GPR8: 233 reg_id = GPR8_MAPPING[reg_id]; 234 ZYAN_FALLTHROUGH; 235 case ZYDIS_REGCLASS_GPR16: 236 case ZYDIS_REGCLASS_GPR32: 237 case ZYDIS_REGCLASS_GPR64: 238 switch (mode_bits) 239 { 240 case 2: 241 return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR64].lo + reg_id; 242 case 1: 243 return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR32].lo + reg_id; 244 case 0: 245 return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR16].lo + reg_id; 246 default: 247 ZYAN_UNREACHABLE; 248 } 249 case ZYDIS_REGCLASS_XMM: 250 case ZYDIS_REGCLASS_YMM: 251 case ZYDIS_REGCLASS_ZMM: 252 #if defined(ZYDIS_DISABLE_AVX512) && defined(ZYDIS_DISABLE_KNC) 253 return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_YMM].lo + reg_id; 254 #else 255 return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_ZMM].lo + reg_id; 256 #endif 257 default: 258 return ZYDIS_REGISTER_NONE; 259 } 260 } 261 262 const char* ZydisRegisterGetString(ZydisRegister reg) 263 { 264 if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(STR_REGISTERS)) 265 { 266 return ZYAN_NULL; 267 } 268 269 return STR_REGISTERS[reg].data; 270 } 271 272 const ZydisShortString* ZydisRegisterGetStringWrapped(ZydisRegister reg) 273 { 274 if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(STR_REGISTERS)) 275 { 276 return ZYAN_NULL; 277 } 278 279 return &STR_REGISTERS[reg]; 280 } 281 282 /* ---------------------------------------------------------------------------------------------- */ 283 /* Register class */ 284 /* ---------------------------------------------------------------------------------------------- */ 285 286 ZydisRegisterWidth ZydisRegisterClassGetWidth(ZydisMachineMode mode, 287 ZydisRegisterClass register_class) 288 { 289 if ((ZyanUSize)register_class >= ZYAN_ARRAY_LENGTH(REG_CLASS_LOOKUP)) 290 { 291 return 0; 292 } 293 294 return (mode == ZYDIS_MACHINE_MODE_LONG_64) 295 ? REG_CLASS_LOOKUP[register_class].width64 296 : REG_CLASS_LOOKUP[register_class].width; 297 } 298 299 /* ---------------------------------------------------------------------------------------------- */ 300 301 /* ============================================================================================== */