include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / libs / zydis / src / Register.c
blob66ef035e4741ced411a76998a3856855c8262798
1 /***************************************************************************************************
3 Zyan Disassembler Library (Zydis)
5 Original Author : Florian Bernd
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:
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
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.
25 ***************************************************************************************************/
27 #include <Zydis/Register.h>
29 /* ============================================================================================== */
30 /* Register strings */
31 /* ============================================================================================== */
33 #include <Generated/EnumRegister.inc>
35 /* ============================================================================================== */
36 /* Register-class mapping */
37 /* ============================================================================================== */
39 /**
40 * Defines the `ZydisRegisterMapItem` struct.
42 typedef struct ZydisRegisterLookupItem
44 /**
45 * The register class.
47 ZydisRegisterClass class;
48 /**
49 * The register id.
51 ZyanI8 id;
52 /**
53 * The width of register 16- and 32-bit mode.
55 ZydisRegisterWidth width;
56 /**
57 * The width of register in 64-bit mode.
59 ZydisRegisterWidth width64;
60 } ZydisRegisterLookupItem;
62 #include <Generated/RegisterLookup.inc>
64 /**
65 * Defines the `ZydisRegisterClassLookupItem` struct.
67 typedef struct ZydisRegisterClassLookupItem_
69 /**
70 * The lowest register of the current class.
72 ZydisRegister lo;
73 /**
74 * The highest register of the current class.
76 ZydisRegister hi;
77 /**
78 * The width of registers of the current class in 16- and 32-bit mode.
80 ZydisRegisterWidth width;
81 /**
82 * The width of registers of the current class in 64-bit mode.
84 ZydisRegisterWidth width64;
85 } ZydisRegisterClassLookupItem;
87 #include <Generated/RegisterClassLookup.inc>
89 /* ============================================================================================== */
90 /* Exported functions */
91 /* ============================================================================================== */
93 /* ---------------------------------------------------------------------------------------------- */
94 /* Register */
95 /* ---------------------------------------------------------------------------------------------- */
97 ZydisRegister ZydisRegisterEncode(ZydisRegisterClass register_class, ZyanU8 id)
99 if ((register_class == ZYDIS_REGCLASS_INVALID) ||
100 (register_class == ZYDIS_REGCLASS_FLAGS) ||
101 (register_class == ZYDIS_REGCLASS_IP))
103 return ZYDIS_REGISTER_NONE;
106 if ((ZyanUSize)register_class >= ZYAN_ARRAY_LENGTH(REG_CLASS_LOOKUP))
108 return ZYDIS_REGISTER_NONE;
111 const ZydisRegisterClassLookupItem* item = &REG_CLASS_LOOKUP[register_class];
112 if (id <= (item->hi - item->lo))
114 return item->lo + id;
117 return ZYDIS_REGISTER_NONE;
120 ZyanI8 ZydisRegisterGetId(ZydisRegister reg)
122 if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))
124 return -1;
127 return REG_LOOKUP[reg].id;
130 ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg)
132 if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))
134 return ZYDIS_REGCLASS_INVALID;
137 return REG_LOOKUP[reg].class;
140 ZydisRegisterWidth ZydisRegisterGetWidth(ZydisMachineMode mode, ZydisRegister reg)
142 if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))
144 return 0;
147 return (mode == ZYDIS_MACHINE_MODE_LONG_64)
148 ? REG_LOOKUP[reg].width64
149 : REG_LOOKUP[reg].width;
152 ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode, ZydisRegister reg)
154 if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))
156 return ZYDIS_REGISTER_NONE;
159 if (mode > ZYDIS_MACHINE_MODE_MAX_VALUE)
161 return ZYDIS_REGISTER_NONE;
164 const ZydisRegisterClass reg_class = REG_LOOKUP[reg].class;
166 if ((reg_class == ZYDIS_REGCLASS_INVALID) ||
167 ((reg_class == ZYDIS_REGCLASS_GPR64) && (mode != ZYDIS_MACHINE_MODE_LONG_64)))
169 return ZYDIS_REGISTER_NONE;
172 static const ZydisRegister STATIC_MAPPING[ZYDIS_REGCLASS_MAX_VALUE + 1][3] =
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 },
178 ZYAN_ASSERT(reg_class < ZYAN_ARRAY_LENGTH(STATIC_MAPPING));
180 ZyanU8 mode_bits;
181 switch (mode)
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;
199 const ZydisRegister static_reg = STATIC_MAPPING[reg_class][mode_bits];
200 if (static_reg != ZYDIS_REGISTER_NONE)
202 return static_reg;
205 static const ZyanU8 GPR8_MAPPING[20] =
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
229 ZyanU8 reg_id = REG_LOOKUP[reg].id;
230 switch (reg_class)
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)
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;
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;
262 const char* ZydisRegisterGetString(ZydisRegister reg)
264 if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(STR_REGISTERS))
266 return ZYAN_NULL;
269 return STR_REGISTERS[reg].data;
272 const ZydisShortString* ZydisRegisterGetStringWrapped(ZydisRegister reg)
274 if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(STR_REGISTERS))
276 return ZYAN_NULL;
279 return &STR_REGISTERS[reg];
282 /* ---------------------------------------------------------------------------------------------- */
283 /* Register class */
284 /* ---------------------------------------------------------------------------------------------- */
286 ZydisRegisterWidth ZydisRegisterClassGetWidth(ZydisMachineMode mode,
287 ZydisRegisterClass register_class)
289 if ((ZyanUSize)register_class >= ZYAN_ARRAY_LENGTH(REG_CLASS_LOOKUP))
291 return 0;
294 return (mode == ZYDIS_MACHINE_MODE_LONG_64)
295 ? REG_CLASS_LOOKUP[register_class].width64
296 : REG_CLASS_LOOKUP[register_class].width;
299 /* ---------------------------------------------------------------------------------------------- */
301 /* ============================================================================================== */