]>
Commit | Line | Data |
---|---|---|
c97d6d2c SAGDR |
1 | /* |
2 | * Copyright (C) 2016 Veertu Inc, | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or | |
996feed4 SAGDR |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either | |
8af82b8e | 7 | * version 2.1 of the License, or (at your option) any later version. |
c97d6d2c SAGDR |
8 | * |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
996feed4 SAGDR |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. | |
c97d6d2c | 13 | * |
996feed4 SAGDR |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this program; if not, see <http://www.gnu.org/licenses/>. | |
c97d6d2c SAGDR |
16 | */ |
17 | ||
f9fea777 | 18 | #ifndef HVF_X86_DECODE_H |
177d9e0d | 19 | #define HVF_X86_DECODE_H |
c97d6d2c | 20 | |
c97d6d2c | 21 | #include "cpu.h" |
f9fea777 | 22 | #include "x86.h" |
c97d6d2c SAGDR |
23 | |
24 | typedef enum x86_prefix { | |
25 | /* group 1 */ | |
26 | PREFIX_LOCK = 0xf0, | |
27 | PREFIX_REPN = 0xf2, | |
28 | PREFIX_REP = 0xf3, | |
29 | /* group 2 */ | |
8c3b0e9e CE |
30 | PREFIX_CS_SEG_OVERRIDE = 0x2e, |
31 | PREFIX_SS_SEG_OVERRIDE = 0x36, | |
32 | PREFIX_DS_SEG_OVERRIDE = 0x3e, | |
33 | PREFIX_ES_SEG_OVERRIDE = 0x26, | |
34 | PREFIX_FS_SEG_OVERRIDE = 0x64, | |
35 | PREFIX_GS_SEG_OVERRIDE = 0x65, | |
c97d6d2c SAGDR |
36 | /* group 3 */ |
37 | PREFIX_OP_SIZE_OVERRIDE = 0x66, | |
38 | /* group 4 */ | |
39 | PREFIX_ADDR_SIZE_OVERRIDE = 0x67, | |
40 | ||
41 | PREFIX_REX = 0x40, | |
42 | } x86_prefix; | |
43 | ||
44 | enum x86_decode_cmd { | |
45 | X86_DECODE_CMD_INVL = 0, | |
46 | ||
47 | X86_DECODE_CMD_PUSH, | |
48 | X86_DECODE_CMD_PUSH_SEG, | |
49 | X86_DECODE_CMD_POP, | |
50 | X86_DECODE_CMD_POP_SEG, | |
51 | X86_DECODE_CMD_MOV, | |
52 | X86_DECODE_CMD_MOVSX, | |
53 | X86_DECODE_CMD_MOVZX, | |
54 | X86_DECODE_CMD_CALL_NEAR, | |
55 | X86_DECODE_CMD_CALL_NEAR_ABS_INDIRECT, | |
56 | X86_DECODE_CMD_CALL_FAR_ABS_INDIRECT, | |
57 | X86_DECODE_CMD_CALL_FAR, | |
58 | X86_DECODE_RET_NEAR, | |
59 | X86_DECODE_RET_FAR, | |
60 | X86_DECODE_CMD_ADD, | |
61 | X86_DECODE_CMD_OR, | |
62 | X86_DECODE_CMD_ADC, | |
63 | X86_DECODE_CMD_SBB, | |
64 | X86_DECODE_CMD_AND, | |
65 | X86_DECODE_CMD_SUB, | |
66 | X86_DECODE_CMD_XOR, | |
67 | X86_DECODE_CMD_CMP, | |
68 | X86_DECODE_CMD_INC, | |
69 | X86_DECODE_CMD_DEC, | |
70 | X86_DECODE_CMD_TST, | |
71 | X86_DECODE_CMD_NOT, | |
72 | X86_DECODE_CMD_NEG, | |
73 | X86_DECODE_CMD_JMP_NEAR, | |
74 | X86_DECODE_CMD_JMP_NEAR_ABS_INDIRECT, | |
75 | X86_DECODE_CMD_JMP_FAR, | |
76 | X86_DECODE_CMD_JMP_FAR_ABS_INDIRECT, | |
77 | X86_DECODE_CMD_LEA, | |
78 | X86_DECODE_CMD_JXX, | |
79 | X86_DECODE_CMD_JCXZ, | |
80 | X86_DECODE_CMD_SETXX, | |
81 | X86_DECODE_CMD_MOV_TO_SEG, | |
82 | X86_DECODE_CMD_MOV_FROM_SEG, | |
83 | X86_DECODE_CMD_CLI, | |
84 | X86_DECODE_CMD_STI, | |
85 | X86_DECODE_CMD_CLD, | |
86 | X86_DECODE_CMD_STD, | |
87 | X86_DECODE_CMD_STC, | |
88 | X86_DECODE_CMD_CLC, | |
89 | X86_DECODE_CMD_OUT, | |
90 | X86_DECODE_CMD_IN, | |
91 | X86_DECODE_CMD_INS, | |
92 | X86_DECODE_CMD_OUTS, | |
93 | X86_DECODE_CMD_LIDT, | |
94 | X86_DECODE_CMD_SIDT, | |
95 | X86_DECODE_CMD_LGDT, | |
96 | X86_DECODE_CMD_SGDT, | |
97 | X86_DECODE_CMD_SMSW, | |
98 | X86_DECODE_CMD_LMSW, | |
99 | X86_DECODE_CMD_RDTSCP, | |
100 | X86_DECODE_CMD_INVLPG, | |
101 | X86_DECODE_CMD_MOV_TO_CR, | |
102 | X86_DECODE_CMD_MOV_FROM_CR, | |
103 | X86_DECODE_CMD_MOV_TO_DR, | |
104 | X86_DECODE_CMD_MOV_FROM_DR, | |
105 | X86_DECODE_CMD_PUSHF, | |
106 | X86_DECODE_CMD_POPF, | |
107 | X86_DECODE_CMD_CPUID, | |
108 | X86_DECODE_CMD_ROL, | |
109 | X86_DECODE_CMD_ROR, | |
110 | X86_DECODE_CMD_RCL, | |
111 | X86_DECODE_CMD_RCR, | |
112 | X86_DECODE_CMD_SHL, | |
113 | X86_DECODE_CMD_SAL, | |
114 | X86_DECODE_CMD_SHR, | |
115 | X86_DECODE_CMD_SHRD, | |
116 | X86_DECODE_CMD_SHLD, | |
117 | X86_DECODE_CMD_SAR, | |
118 | X86_DECODE_CMD_DIV, | |
119 | X86_DECODE_CMD_IDIV, | |
120 | X86_DECODE_CMD_MUL, | |
121 | X86_DECODE_CMD_IMUL_3, | |
122 | X86_DECODE_CMD_IMUL_2, | |
123 | X86_DECODE_CMD_IMUL_1, | |
124 | X86_DECODE_CMD_MOVS, | |
125 | X86_DECODE_CMD_CMPS, | |
126 | X86_DECODE_CMD_SCAS, | |
127 | X86_DECODE_CMD_LODS, | |
128 | X86_DECODE_CMD_STOS, | |
129 | X86_DECODE_CMD_BSWAP, | |
130 | X86_DECODE_CMD_XCHG, | |
131 | X86_DECODE_CMD_RDTSC, | |
132 | X86_DECODE_CMD_RDMSR, | |
133 | X86_DECODE_CMD_WRMSR, | |
134 | X86_DECODE_CMD_ENTER, | |
135 | X86_DECODE_CMD_LEAVE, | |
136 | X86_DECODE_CMD_BT, | |
137 | X86_DECODE_CMD_BTS, | |
138 | X86_DECODE_CMD_BTC, | |
139 | X86_DECODE_CMD_BTR, | |
140 | X86_DECODE_CMD_BSF, | |
141 | X86_DECODE_CMD_BSR, | |
142 | X86_DECODE_CMD_IRET, | |
143 | X86_DECODE_CMD_INT, | |
144 | X86_DECODE_CMD_POPA, | |
145 | X86_DECODE_CMD_PUSHA, | |
146 | X86_DECODE_CMD_CWD, | |
147 | X86_DECODE_CMD_CBW, | |
148 | X86_DECODE_CMD_DAS, | |
149 | X86_DECODE_CMD_AAD, | |
150 | X86_DECODE_CMD_AAM, | |
151 | X86_DECODE_CMD_AAS, | |
152 | X86_DECODE_CMD_LOOP, | |
153 | X86_DECODE_CMD_SLDT, | |
154 | X86_DECODE_CMD_STR, | |
155 | X86_DECODE_CMD_LLDT, | |
156 | X86_DECODE_CMD_LTR, | |
157 | X86_DECODE_CMD_VERR, | |
158 | X86_DECODE_CMD_VERW, | |
159 | X86_DECODE_CMD_SAHF, | |
160 | X86_DECODE_CMD_LAHF, | |
161 | X86_DECODE_CMD_WBINVD, | |
162 | X86_DECODE_CMD_LDS, | |
163 | X86_DECODE_CMD_LSS, | |
164 | X86_DECODE_CMD_LES, | |
165 | X86_DECODE_XMD_LGS, | |
166 | X86_DECODE_CMD_LFS, | |
167 | X86_DECODE_CMD_CMC, | |
168 | X86_DECODE_CMD_XLAT, | |
169 | X86_DECODE_CMD_NOP, | |
170 | X86_DECODE_CMD_CMOV, | |
171 | X86_DECODE_CMD_CLTS, | |
172 | X86_DECODE_CMD_XADD, | |
173 | X86_DECODE_CMD_HLT, | |
174 | X86_DECODE_CMD_CMPXCHG8B, | |
175 | X86_DECODE_CMD_CMPXCHG, | |
176 | X86_DECODE_CMD_POPCNT, | |
177 | ||
178 | X86_DECODE_CMD_FNINIT, | |
179 | X86_DECODE_CMD_FLD, | |
180 | X86_DECODE_CMD_FLDxx, | |
181 | X86_DECODE_CMD_FNSTCW, | |
182 | X86_DECODE_CMD_FNSTSW, | |
183 | X86_DECODE_CMD_FNSETPM, | |
184 | X86_DECODE_CMD_FSAVE, | |
185 | X86_DECODE_CMD_FRSTOR, | |
186 | X86_DECODE_CMD_FXSAVE, | |
187 | X86_DECODE_CMD_FXRSTOR, | |
188 | X86_DECODE_CMD_FDIV, | |
189 | X86_DECODE_CMD_FMUL, | |
190 | X86_DECODE_CMD_FSUB, | |
191 | X86_DECODE_CMD_FADD, | |
192 | X86_DECODE_CMD_EMMS, | |
193 | X86_DECODE_CMD_MFENCE, | |
194 | X86_DECODE_CMD_SFENCE, | |
195 | X86_DECODE_CMD_LFENCE, | |
196 | X86_DECODE_CMD_PREFETCH, | |
197 | X86_DECODE_CMD_CLFLUSH, | |
198 | X86_DECODE_CMD_FST, | |
199 | X86_DECODE_CMD_FABS, | |
200 | X86_DECODE_CMD_FUCOM, | |
201 | X86_DECODE_CMD_FUCOMI, | |
202 | X86_DECODE_CMD_FLDCW, | |
203 | X86_DECODE_CMD_FXCH, | |
204 | X86_DECODE_CMD_FCHS, | |
205 | X86_DECODE_CMD_FCMOV, | |
206 | X86_DECODE_CMD_FRNDINT, | |
207 | X86_DECODE_CMD_FXAM, | |
208 | ||
209 | X86_DECODE_CMD_LAST, | |
210 | }; | |
211 | ||
212 | const char *decode_cmd_to_string(enum x86_decode_cmd cmd); | |
213 | ||
214 | typedef struct x86_modrm { | |
215 | union { | |
216 | uint8_t modrm; | |
217 | struct { | |
218 | uint8_t rm:3; | |
219 | uint8_t reg:3; | |
220 | uint8_t mod:2; | |
221 | }; | |
222 | }; | |
223 | } __attribute__ ((__packed__)) x86_modrm; | |
224 | ||
225 | typedef struct x86_sib { | |
226 | union { | |
227 | uint8_t sib; | |
228 | struct { | |
229 | uint8_t base:3; | |
230 | uint8_t index:3; | |
231 | uint8_t scale:2; | |
232 | }; | |
233 | }; | |
234 | } __attribute__ ((__packed__)) x86_sib; | |
235 | ||
236 | typedef struct x86_rex { | |
237 | union { | |
238 | uint8_t rex; | |
239 | struct { | |
240 | uint8_t b:1; | |
241 | uint8_t x:1; | |
242 | uint8_t r:1; | |
243 | uint8_t w:1; | |
244 | uint8_t unused:4; | |
245 | }; | |
246 | }; | |
247 | } __attribute__ ((__packed__)) x86_rex; | |
248 | ||
249 | typedef enum x86_var_type { | |
250 | X86_VAR_IMMEDIATE, | |
251 | X86_VAR_OFFSET, | |
252 | X86_VAR_REG, | |
253 | X86_VAR_RM, | |
254 | ||
255 | /* for floating point computations */ | |
256 | X87_VAR_REG, | |
257 | X87_VAR_FLOATP, | |
258 | X87_VAR_INTP, | |
259 | X87_VAR_BYTEP, | |
260 | } x86_var_type; | |
261 | ||
262 | typedef struct x86_decode_op { | |
263 | enum x86_var_type type; | |
264 | int size; | |
265 | ||
266 | int reg; | |
ff2de166 | 267 | target_ulong val; |
c97d6d2c | 268 | |
ff2de166 | 269 | target_ulong ptr; |
c97d6d2c SAGDR |
270 | } x86_decode_op; |
271 | ||
272 | typedef struct x86_decode { | |
273 | int len; | |
274 | uint8_t opcode[4]; | |
275 | uint8_t opcode_len; | |
276 | enum x86_decode_cmd cmd; | |
277 | int addressing_size; | |
278 | int operand_size; | |
279 | int lock; | |
280 | int rep; | |
281 | int op_size_override; | |
282 | int addr_size_override; | |
283 | int segment_override; | |
284 | int control_change_inst; | |
285 | bool fwait; | |
286 | bool fpop_stack; | |
287 | bool frev; | |
288 | ||
289 | uint32_t displacement; | |
290 | uint8_t displacement_size; | |
291 | struct x86_rex rex; | |
292 | bool is_modrm; | |
293 | bool sib_present; | |
294 | struct x86_sib sib; | |
295 | struct x86_modrm modrm; | |
296 | struct x86_decode_op op[4]; | |
297 | bool is_fpu; | |
ff2de166 | 298 | uint32_t flags_mask; |
c97d6d2c SAGDR |
299 | |
300 | } x86_decode; | |
301 | ||
302 | uint64_t sign(uint64_t val, int size); | |
303 | ||
304 | uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode); | |
305 | ||
8c3b0e9e CE |
306 | target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present, |
307 | int is_extended, int size); | |
308 | target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present, | |
309 | int is_extended, int size); | |
c97d6d2c SAGDR |
310 | void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode, |
311 | struct x86_decode_op *op); | |
ff2de166 PB |
312 | target_ulong decode_linear_addr(CPUX86State *env, struct x86_decode *decode, |
313 | target_ulong addr, enum X86Seg seg); | |
c97d6d2c SAGDR |
314 | |
315 | void init_decoder(void); | |
316 | void calc_modrm_operand16(CPUX86State *env, struct x86_decode *decode, | |
317 | struct x86_decode_op *op); | |
318 | void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode, | |
319 | struct x86_decode_op *op); | |
320 | void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode, | |
321 | struct x86_decode_op *op); | |
322 | void set_addressing_size(CPUX86State *env, struct x86_decode *decode); | |
323 | void set_operand_size(CPUX86State *env, struct x86_decode *decode); | |
f9fea777 PB |
324 | |
325 | #endif |