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
25 ***************************************************************************************************/
27 #include <Zydis/Register.h>
29 /* ============================================================================================== */
30 /* Register strings */
31 /* ============================================================================================== */
33 #include <Generated/EnumRegister.inc>
35 /* ============================================================================================== */
36 /* Register-class mapping */
37 /* ============================================================================================== */
40 * Defines the `ZydisRegisterMapItem` struct.
42 typedef struct ZydisRegisterLookupItem
47 ZydisRegisterClass
class;
53 * The width of register 16- and 32-bit mode.
55 ZydisRegisterWidth width
;
57 * The width of register in 64-bit mode.
59 ZydisRegisterWidth width64
;
60 } ZydisRegisterLookupItem
;
62 #include <Generated/RegisterLookup.inc>
65 * Defines the `ZydisRegisterClassLookupItem` struct.
67 typedef struct ZydisRegisterClassLookupItem_
70 * The lowest register of the current class.
74 * The highest register of the current class.
78 * The width of registers of the current class in 16- and 32-bit mode.
80 ZydisRegisterWidth width
;
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 /* ---------------------------------------------------------------------------------------------- */
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
= ®_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
))
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
))
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
));
183 case ZYDIS_MACHINE_MODE_LONG_64
:
186 case ZYDIS_MACHINE_MODE_LONG_COMPAT_32
:
187 case ZYDIS_MACHINE_MODE_LEGACY_32
:
190 case ZYDIS_MACHINE_MODE_LONG_COMPAT_16
:
191 case ZYDIS_MACHINE_MODE_LEGACY_16
:
192 case ZYDIS_MACHINE_MODE_REAL_16
:
199 const ZydisRegister static_reg
= STATIC_MAPPING
[reg_class
][mode_bits
];
200 if (static_reg
!= ZYDIS_REGISTER_NONE
)
205 static const ZyanU8 GPR8_MAPPING
[20] =
229 ZyanU8 reg_id
= REG_LOOKUP
[reg
].id
;
232 case ZYDIS_REGCLASS_GPR8
:
233 reg_id
= GPR8_MAPPING
[reg_id
];
235 case ZYDIS_REGCLASS_GPR16
:
236 case ZYDIS_REGCLASS_GPR32
:
237 case ZYDIS_REGCLASS_GPR64
:
241 return REG_CLASS_LOOKUP
[ZYDIS_REGCLASS_GPR64
].lo
+ reg_id
;
243 return REG_CLASS_LOOKUP
[ZYDIS_REGCLASS_GPR32
].lo
+ reg_id
;
245 return REG_CLASS_LOOKUP
[ZYDIS_REGCLASS_GPR16
].lo
+ reg_id
;
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
;
255 return REG_CLASS_LOOKUP
[ZYDIS_REGCLASS_ZMM
].lo
+ reg_id
;
258 return ZYDIS_REGISTER_NONE
;
262 const char* ZydisRegisterGetString(ZydisRegister reg
)
264 if ((ZyanUSize
)reg
>= ZYAN_ARRAY_LENGTH(STR_REGISTERS
))
269 return STR_REGISTERS
[reg
].data
;
272 const ZydisShortString
* ZydisRegisterGetStringWrapped(ZydisRegister reg
)
274 if ((ZyanUSize
)reg
>= ZYAN_ARRAY_LENGTH(STR_REGISTERS
))
279 return &STR_REGISTERS
[reg
];
282 /* ---------------------------------------------------------------------------------------------- */
284 /* ---------------------------------------------------------------------------------------------- */
286 ZydisRegisterWidth
ZydisRegisterClassGetWidth(ZydisMachineMode mode
,
287 ZydisRegisterClass register_class
)
289 if ((ZyanUSize
)register_class
>= ZYAN_ARRAY_LENGTH(REG_CLASS_LOOKUP
))
294 return (mode
== ZYDIS_MACHINE_MODE_LONG_64
)
295 ? REG_CLASS_LOOKUP
[register_class
].width64
296 : REG_CLASS_LOOKUP
[register_class
].width
;
299 /* ---------------------------------------------------------------------------------------------- */
301 /* ============================================================================================== */