/***************************************************************************************************12Zyan Disassembler Library (Zydis)34Original Author : Florian Bernd56* Permission is hereby granted, free of charge, to any person obtaining a copy7* of this software and associated documentation files (the "Software"), to deal8* in the Software without restriction, including without limitation the rights9* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell10* copies of the Software, and to permit persons to whom the Software is11* furnished to do so, subject to the following conditions:12*13* The above copyright notice and this permission notice shall be included in all14* copies or substantial portions of the Software.15*16* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR17* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,18* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE19* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER20* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,21* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE22* SOFTWARE.2324***************************************************************************************************/2526#include <Zydis/Register.h>2728/* ============================================================================================== */29/* Register strings */30/* ============================================================================================== */3132#include <Generated/EnumRegister.inc>3334/* ============================================================================================== */35/* Register-class mapping */36/* ============================================================================================== */3738/**39* Defines the `ZydisRegisterMapItem` struct.40*/41typedef struct ZydisRegisterLookupItem42{43/**44* The register class.45*/46ZydisRegisterClass class;47/**48* The register id.49*/50ZyanI8 id;51/**52* The width of register 16- and 32-bit mode.53*/54ZydisRegisterWidth width;55/**56* The width of register in 64-bit mode.57*/58ZydisRegisterWidth width64;59} ZydisRegisterLookupItem;6061#include <Generated/RegisterLookup.inc>6263/**64* Defines the `ZydisRegisterClassLookupItem` struct.65*/66typedef struct ZydisRegisterClassLookupItem_67{68/**69* The lowest register of the current class.70*/71ZydisRegister lo;72/**73* The highest register of the current class.74*/75ZydisRegister hi;76/**77* The width of registers of the current class in 16- and 32-bit mode.78*/79ZydisRegisterWidth width;80/**81* The width of registers of the current class in 64-bit mode.82*/83ZydisRegisterWidth width64;84} ZydisRegisterClassLookupItem;8586#include <Generated/RegisterClassLookup.inc>8788/* ============================================================================================== */89/* Exported functions */90/* ============================================================================================== */9192/* ---------------------------------------------------------------------------------------------- */93/* Register */94/* ---------------------------------------------------------------------------------------------- */9596ZydisRegister ZydisRegisterEncode(ZydisRegisterClass register_class, ZyanU8 id)97{98if ((register_class == ZYDIS_REGCLASS_INVALID) ||99(register_class == ZYDIS_REGCLASS_FLAGS) ||100(register_class == ZYDIS_REGCLASS_IP))101{102return ZYDIS_REGISTER_NONE;103}104105if ((ZyanUSize)register_class >= ZYAN_ARRAY_LENGTH(REG_CLASS_LOOKUP))106{107return ZYDIS_REGISTER_NONE;108}109110const ZydisRegisterClassLookupItem* item = ®_CLASS_LOOKUP[register_class];111if (id <= (item->hi - item->lo))112{113return item->lo + id;114}115116return ZYDIS_REGISTER_NONE;117}118119ZyanI8 ZydisRegisterGetId(ZydisRegister reg)120{121if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))122{123return -1;124}125126return REG_LOOKUP[reg].id;127}128129ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg)130{131if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))132{133return ZYDIS_REGCLASS_INVALID;134}135136return REG_LOOKUP[reg].class;137}138139ZydisRegisterWidth ZydisRegisterGetWidth(ZydisMachineMode mode, ZydisRegister reg)140{141if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))142{143return 0;144}145146return (mode == ZYDIS_MACHINE_MODE_LONG_64)147? REG_LOOKUP[reg].width64148: REG_LOOKUP[reg].width;149}150151ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode, ZydisRegister reg)152{153if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))154{155return ZYDIS_REGISTER_NONE;156}157158static const ZyanU8 GPR8_MAPPING[20] =159{160/* AL */ 0,161/* CL */ 1,162/* DL */ 2,163/* BL */ 3,164/* AH */ 0,165/* CH */ 1,166/* DH */ 2,167/* BH */ 3,168/* SPL */ 4,169/* BPL */ 5,170/* SIL */ 6,171/* DIL */ 7,172/* R8B */ 8,173/* R9B */ 9,174/* R10B */ 10,175/* R11B */ 11,176/* R12B */ 12,177/* R13B */ 13,178/* R14B */ 14,179/* R15B */ 15,180};181182const ZydisRegisterClass reg_class = REG_LOOKUP[reg].class;183if ((reg_class == ZYDIS_REGCLASS_INVALID) ||184((reg_class == ZYDIS_REGCLASS_GPR64) && (mode != ZYDIS_MACHINE_MODE_LONG_64)))185{186return ZYDIS_REGISTER_NONE;187}188189ZyanU8 reg_id = REG_LOOKUP[reg].id;190switch (reg_class)191{192case ZYDIS_REGCLASS_GPR8:193reg_id = GPR8_MAPPING[reg_id];194ZYAN_FALLTHROUGH;195case ZYDIS_REGCLASS_GPR16:196case ZYDIS_REGCLASS_GPR32:197case ZYDIS_REGCLASS_GPR64:198switch (mode)199{200case ZYDIS_MACHINE_MODE_LONG_64:201return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR64].lo + reg_id;202case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:203case ZYDIS_MACHINE_MODE_LEGACY_32:204return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR32].lo + reg_id;205case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:206case ZYDIS_MACHINE_MODE_LEGACY_16:207case ZYDIS_MACHINE_MODE_REAL_16:208return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR16].lo + reg_id;209default:210return ZYDIS_REGISTER_NONE;211}212case ZYDIS_REGCLASS_XMM:213case ZYDIS_REGCLASS_YMM:214case ZYDIS_REGCLASS_ZMM:215#if defined(ZYDIS_DISABLE_AVX512) && defined(ZYDIS_DISABLE_KNC)216return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_YMM].lo + reg_id;217#else218return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_ZMM].lo + reg_id;219#endif220default:221return ZYDIS_REGISTER_NONE;222}223}224225const char* ZydisRegisterGetString(ZydisRegister reg)226{227if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(STR_REGISTERS))228{229return ZYAN_NULL;230}231232return STR_REGISTERS[reg].data;233}234235const ZydisShortString* ZydisRegisterGetStringWrapped(ZydisRegister reg)236{237if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(STR_REGISTERS))238{239return ZYAN_NULL;240}241242return &STR_REGISTERS[reg];243}244245/* ---------------------------------------------------------------------------------------------- */246/* Register class */247/* ---------------------------------------------------------------------------------------------- */248249ZydisRegisterWidth ZydisRegisterClassGetWidth(ZydisMachineMode mode,250ZydisRegisterClass register_class)251{252if ((ZyanUSize)register_class >= ZYAN_ARRAY_LENGTH(REG_CLASS_LOOKUP))253{254return 0;255}256257return (mode == ZYDIS_MACHINE_MODE_LONG_64)258? REG_CLASS_LOOKUP[register_class].width64259: REG_CLASS_LOOKUP[register_class].width;260}261262/* ---------------------------------------------------------------------------------------------- */263264/* ============================================================================================== */265266267