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