Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/zydis/src/Register.c
6236 views
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
/* ============================================================================================== */
266
267