xref: /openbmc/qemu/target/i386/emulate/x86_decode.h (revision cacb211471e3a4b4abc517bfb2aef7bde5e71eaa)
127458df8SWei Liu /*
227458df8SWei Liu  * Copyright (C) 2016 Veertu Inc,
327458df8SWei Liu  *
427458df8SWei Liu  * This program is free software; you can redistribute it and/or
527458df8SWei Liu  * modify it under the terms of the GNU Lesser General Public
627458df8SWei Liu  * License as published by the Free Software Foundation; either
727458df8SWei Liu  * version 2.1 of the License, or (at your option) any later version.
827458df8SWei Liu  *
927458df8SWei Liu  * This program is distributed in the hope that it will be useful,
1027458df8SWei Liu  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1127458df8SWei Liu  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1227458df8SWei Liu  * Lesser General Public License for more details.
1327458df8SWei Liu  *
1427458df8SWei Liu  * You should have received a copy of the GNU Lesser General Public
1527458df8SWei Liu  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
1627458df8SWei Liu  */
1727458df8SWei Liu 
1827458df8SWei Liu #ifndef X86_EMU_DECODE_H
1927458df8SWei Liu #define X86_EMU_DECODE_H
2027458df8SWei Liu 
2127458df8SWei Liu #include "cpu.h"
2227458df8SWei Liu #include "x86.h"
2327458df8SWei Liu 
2427458df8SWei Liu typedef enum x86_prefix {
2527458df8SWei Liu     /* group 1 */
2627458df8SWei Liu     PREFIX_LOCK =                  0xf0,
2727458df8SWei Liu     PREFIX_REPN =                  0xf2,
2827458df8SWei Liu     PREFIX_REP =                   0xf3,
2927458df8SWei Liu     /* group 2 */
3027458df8SWei Liu     PREFIX_CS_SEG_OVERRIDE =       0x2e,
3127458df8SWei Liu     PREFIX_SS_SEG_OVERRIDE =       0x36,
3227458df8SWei Liu     PREFIX_DS_SEG_OVERRIDE =       0x3e,
3327458df8SWei Liu     PREFIX_ES_SEG_OVERRIDE =       0x26,
3427458df8SWei Liu     PREFIX_FS_SEG_OVERRIDE =       0x64,
3527458df8SWei Liu     PREFIX_GS_SEG_OVERRIDE =       0x65,
3627458df8SWei Liu     /* group 3 */
3727458df8SWei Liu     PREFIX_OP_SIZE_OVERRIDE =      0x66,
3827458df8SWei Liu     /* group 4 */
3927458df8SWei Liu     PREFIX_ADDR_SIZE_OVERRIDE =    0x67,
4027458df8SWei Liu 
4127458df8SWei Liu     PREFIX_REX                   = 0x40,
4227458df8SWei Liu } x86_prefix;
4327458df8SWei Liu 
4427458df8SWei Liu enum x86_decode_cmd {
4527458df8SWei Liu     X86_DECODE_CMD_INVL = 0,
4627458df8SWei Liu 
4727458df8SWei Liu     X86_DECODE_CMD_PUSH,
4827458df8SWei Liu     X86_DECODE_CMD_PUSH_SEG,
4927458df8SWei Liu     X86_DECODE_CMD_POP,
5027458df8SWei Liu     X86_DECODE_CMD_POP_SEG,
5127458df8SWei Liu     X86_DECODE_CMD_MOV,
5227458df8SWei Liu     X86_DECODE_CMD_MOVSX,
5327458df8SWei Liu     X86_DECODE_CMD_MOVZX,
5427458df8SWei Liu     X86_DECODE_CMD_CALL_NEAR,
5527458df8SWei Liu     X86_DECODE_CMD_CALL_NEAR_ABS_INDIRECT,
5627458df8SWei Liu     X86_DECODE_CMD_CALL_FAR_ABS_INDIRECT,
5727458df8SWei Liu     X86_DECODE_CMD_CALL_FAR,
5827458df8SWei Liu     X86_DECODE_RET_NEAR,
5927458df8SWei Liu     X86_DECODE_RET_FAR,
6027458df8SWei Liu     X86_DECODE_CMD_ADD,
6127458df8SWei Liu     X86_DECODE_CMD_OR,
6227458df8SWei Liu     X86_DECODE_CMD_ADC,
6327458df8SWei Liu     X86_DECODE_CMD_SBB,
6427458df8SWei Liu     X86_DECODE_CMD_AND,
6527458df8SWei Liu     X86_DECODE_CMD_SUB,
6627458df8SWei Liu     X86_DECODE_CMD_XOR,
6727458df8SWei Liu     X86_DECODE_CMD_CMP,
6827458df8SWei Liu     X86_DECODE_CMD_INC,
6927458df8SWei Liu     X86_DECODE_CMD_DEC,
7027458df8SWei Liu     X86_DECODE_CMD_TST,
7127458df8SWei Liu     X86_DECODE_CMD_NOT,
7227458df8SWei Liu     X86_DECODE_CMD_NEG,
7327458df8SWei Liu     X86_DECODE_CMD_JMP_NEAR,
7427458df8SWei Liu     X86_DECODE_CMD_JMP_NEAR_ABS_INDIRECT,
7527458df8SWei Liu     X86_DECODE_CMD_JMP_FAR,
7627458df8SWei Liu     X86_DECODE_CMD_JMP_FAR_ABS_INDIRECT,
7727458df8SWei Liu     X86_DECODE_CMD_LEA,
7827458df8SWei Liu     X86_DECODE_CMD_JXX,
7927458df8SWei Liu     X86_DECODE_CMD_JCXZ,
8027458df8SWei Liu     X86_DECODE_CMD_SETXX,
8127458df8SWei Liu     X86_DECODE_CMD_MOV_TO_SEG,
8227458df8SWei Liu     X86_DECODE_CMD_MOV_FROM_SEG,
8327458df8SWei Liu     X86_DECODE_CMD_CLI,
8427458df8SWei Liu     X86_DECODE_CMD_STI,
8527458df8SWei Liu     X86_DECODE_CMD_CLD,
8627458df8SWei Liu     X86_DECODE_CMD_STD,
8727458df8SWei Liu     X86_DECODE_CMD_STC,
8827458df8SWei Liu     X86_DECODE_CMD_CLC,
8927458df8SWei Liu     X86_DECODE_CMD_OUT,
9027458df8SWei Liu     X86_DECODE_CMD_IN,
9127458df8SWei Liu     X86_DECODE_CMD_INS,
9227458df8SWei Liu     X86_DECODE_CMD_OUTS,
9327458df8SWei Liu     X86_DECODE_CMD_LIDT,
9427458df8SWei Liu     X86_DECODE_CMD_SIDT,
9527458df8SWei Liu     X86_DECODE_CMD_LGDT,
9627458df8SWei Liu     X86_DECODE_CMD_SGDT,
9727458df8SWei Liu     X86_DECODE_CMD_SMSW,
9827458df8SWei Liu     X86_DECODE_CMD_LMSW,
9927458df8SWei Liu     X86_DECODE_CMD_RDTSCP,
10027458df8SWei Liu     X86_DECODE_CMD_INVLPG,
10127458df8SWei Liu     X86_DECODE_CMD_MOV_TO_CR,
10227458df8SWei Liu     X86_DECODE_CMD_MOV_FROM_CR,
10327458df8SWei Liu     X86_DECODE_CMD_MOV_TO_DR,
10427458df8SWei Liu     X86_DECODE_CMD_MOV_FROM_DR,
10527458df8SWei Liu     X86_DECODE_CMD_PUSHF,
10627458df8SWei Liu     X86_DECODE_CMD_POPF,
10727458df8SWei Liu     X86_DECODE_CMD_CPUID,
10827458df8SWei Liu     X86_DECODE_CMD_ROL,
10927458df8SWei Liu     X86_DECODE_CMD_ROR,
11027458df8SWei Liu     X86_DECODE_CMD_RCL,
11127458df8SWei Liu     X86_DECODE_CMD_RCR,
11227458df8SWei Liu     X86_DECODE_CMD_SHL,
11327458df8SWei Liu     X86_DECODE_CMD_SAL,
11427458df8SWei Liu     X86_DECODE_CMD_SHR,
11527458df8SWei Liu     X86_DECODE_CMD_SHRD,
11627458df8SWei Liu     X86_DECODE_CMD_SHLD,
11727458df8SWei Liu     X86_DECODE_CMD_SAR,
11827458df8SWei Liu     X86_DECODE_CMD_DIV,
11927458df8SWei Liu     X86_DECODE_CMD_IDIV,
12027458df8SWei Liu     X86_DECODE_CMD_MUL,
12127458df8SWei Liu     X86_DECODE_CMD_IMUL_3,
12227458df8SWei Liu     X86_DECODE_CMD_IMUL_2,
12327458df8SWei Liu     X86_DECODE_CMD_IMUL_1,
12427458df8SWei Liu     X86_DECODE_CMD_MOVS,
12527458df8SWei Liu     X86_DECODE_CMD_CMPS,
12627458df8SWei Liu     X86_DECODE_CMD_SCAS,
12727458df8SWei Liu     X86_DECODE_CMD_LODS,
12827458df8SWei Liu     X86_DECODE_CMD_STOS,
12927458df8SWei Liu     X86_DECODE_CMD_BSWAP,
13027458df8SWei Liu     X86_DECODE_CMD_XCHG,
13127458df8SWei Liu     X86_DECODE_CMD_RDTSC,
13227458df8SWei Liu     X86_DECODE_CMD_RDMSR,
13327458df8SWei Liu     X86_DECODE_CMD_WRMSR,
13427458df8SWei Liu     X86_DECODE_CMD_ENTER,
13527458df8SWei Liu     X86_DECODE_CMD_LEAVE,
13627458df8SWei Liu     X86_DECODE_CMD_BT,
13727458df8SWei Liu     X86_DECODE_CMD_BTS,
13827458df8SWei Liu     X86_DECODE_CMD_BTC,
13927458df8SWei Liu     X86_DECODE_CMD_BTR,
14027458df8SWei Liu     X86_DECODE_CMD_BSF,
14127458df8SWei Liu     X86_DECODE_CMD_BSR,
14227458df8SWei Liu     X86_DECODE_CMD_IRET,
14327458df8SWei Liu     X86_DECODE_CMD_INT,
14427458df8SWei Liu     X86_DECODE_CMD_POPA,
14527458df8SWei Liu     X86_DECODE_CMD_PUSHA,
14627458df8SWei Liu     X86_DECODE_CMD_CWD,
14727458df8SWei Liu     X86_DECODE_CMD_CBW,
14827458df8SWei Liu     X86_DECODE_CMD_DAS,
14927458df8SWei Liu     X86_DECODE_CMD_AAD,
15027458df8SWei Liu     X86_DECODE_CMD_AAM,
15127458df8SWei Liu     X86_DECODE_CMD_AAS,
15227458df8SWei Liu     X86_DECODE_CMD_LOOP,
15327458df8SWei Liu     X86_DECODE_CMD_SLDT,
15427458df8SWei Liu     X86_DECODE_CMD_STR,
15527458df8SWei Liu     X86_DECODE_CMD_LLDT,
15627458df8SWei Liu     X86_DECODE_CMD_LTR,
15727458df8SWei Liu     X86_DECODE_CMD_VERR,
15827458df8SWei Liu     X86_DECODE_CMD_VERW,
15927458df8SWei Liu     X86_DECODE_CMD_SAHF,
16027458df8SWei Liu     X86_DECODE_CMD_LAHF,
16127458df8SWei Liu     X86_DECODE_CMD_WBINVD,
16227458df8SWei Liu     X86_DECODE_CMD_LDS,
16327458df8SWei Liu     X86_DECODE_CMD_LSS,
16427458df8SWei Liu     X86_DECODE_CMD_LES,
16527458df8SWei Liu     X86_DECODE_XMD_LGS,
16627458df8SWei Liu     X86_DECODE_CMD_LFS,
16727458df8SWei Liu     X86_DECODE_CMD_CMC,
16827458df8SWei Liu     X86_DECODE_CMD_XLAT,
16927458df8SWei Liu     X86_DECODE_CMD_NOP,
17027458df8SWei Liu     X86_DECODE_CMD_CMOV,
17127458df8SWei Liu     X86_DECODE_CMD_CLTS,
17227458df8SWei Liu     X86_DECODE_CMD_XADD,
17327458df8SWei Liu     X86_DECODE_CMD_HLT,
17427458df8SWei Liu     X86_DECODE_CMD_CMPXCHG8B,
17527458df8SWei Liu     X86_DECODE_CMD_CMPXCHG,
17627458df8SWei Liu     X86_DECODE_CMD_POPCNT,
17727458df8SWei Liu 
17827458df8SWei Liu     X86_DECODE_CMD_FNINIT,
17927458df8SWei Liu     X86_DECODE_CMD_FLD,
18027458df8SWei Liu     X86_DECODE_CMD_FLDxx,
18127458df8SWei Liu     X86_DECODE_CMD_FNSTCW,
18227458df8SWei Liu     X86_DECODE_CMD_FNSTSW,
18327458df8SWei Liu     X86_DECODE_CMD_FNSETPM,
18427458df8SWei Liu     X86_DECODE_CMD_FSAVE,
18527458df8SWei Liu     X86_DECODE_CMD_FRSTOR,
18627458df8SWei Liu     X86_DECODE_CMD_FXSAVE,
18727458df8SWei Liu     X86_DECODE_CMD_FXRSTOR,
18827458df8SWei Liu     X86_DECODE_CMD_FDIV,
18927458df8SWei Liu     X86_DECODE_CMD_FMUL,
19027458df8SWei Liu     X86_DECODE_CMD_FSUB,
19127458df8SWei Liu     X86_DECODE_CMD_FADD,
19227458df8SWei Liu     X86_DECODE_CMD_EMMS,
19327458df8SWei Liu     X86_DECODE_CMD_MFENCE,
19427458df8SWei Liu     X86_DECODE_CMD_SFENCE,
19527458df8SWei Liu     X86_DECODE_CMD_LFENCE,
19627458df8SWei Liu     X86_DECODE_CMD_PREFETCH,
19727458df8SWei Liu     X86_DECODE_CMD_CLFLUSH,
19827458df8SWei Liu     X86_DECODE_CMD_FST,
19927458df8SWei Liu     X86_DECODE_CMD_FABS,
20027458df8SWei Liu     X86_DECODE_CMD_FUCOM,
20127458df8SWei Liu     X86_DECODE_CMD_FUCOMI,
20227458df8SWei Liu     X86_DECODE_CMD_FLDCW,
20327458df8SWei Liu     X86_DECODE_CMD_FXCH,
20427458df8SWei Liu     X86_DECODE_CMD_FCHS,
20527458df8SWei Liu     X86_DECODE_CMD_FCMOV,
20627458df8SWei Liu     X86_DECODE_CMD_FRNDINT,
20727458df8SWei Liu     X86_DECODE_CMD_FXAM,
20827458df8SWei Liu 
20927458df8SWei Liu     X86_DECODE_CMD_LAST,
21027458df8SWei Liu };
21127458df8SWei Liu 
21227458df8SWei Liu const char *decode_cmd_to_string(enum x86_decode_cmd cmd);
21327458df8SWei Liu 
21427458df8SWei Liu typedef struct x86_modrm {
21527458df8SWei Liu     union {
21627458df8SWei Liu         uint8_t modrm;
21727458df8SWei Liu         struct {
21827458df8SWei Liu             uint8_t rm:3;
21927458df8SWei Liu             uint8_t reg:3;
22027458df8SWei Liu             uint8_t mod:2;
22127458df8SWei Liu         };
22227458df8SWei Liu     };
22327458df8SWei Liu } __attribute__ ((__packed__)) x86_modrm;
22427458df8SWei Liu 
22527458df8SWei Liu typedef struct x86_sib {
22627458df8SWei Liu     union {
22727458df8SWei Liu         uint8_t sib;
22827458df8SWei Liu         struct {
22927458df8SWei Liu             uint8_t base:3;
23027458df8SWei Liu             uint8_t index:3;
23127458df8SWei Liu             uint8_t scale:2;
23227458df8SWei Liu         };
23327458df8SWei Liu     };
23427458df8SWei Liu } __attribute__ ((__packed__)) x86_sib;
23527458df8SWei Liu 
23627458df8SWei Liu typedef struct x86_rex {
23727458df8SWei Liu     union {
23827458df8SWei Liu         uint8_t rex;
23927458df8SWei Liu         struct {
24027458df8SWei Liu             uint8_t b:1;
24127458df8SWei Liu             uint8_t x:1;
24227458df8SWei Liu             uint8_t r:1;
24327458df8SWei Liu             uint8_t w:1;
24427458df8SWei Liu             uint8_t unused:4;
24527458df8SWei Liu         };
24627458df8SWei Liu     };
24727458df8SWei Liu } __attribute__ ((__packed__)) x86_rex;
24827458df8SWei Liu 
24927458df8SWei Liu typedef enum x86_var_type {
25027458df8SWei Liu     X86_VAR_IMMEDIATE,
25127458df8SWei Liu     X86_VAR_OFFSET,
25227458df8SWei Liu     X86_VAR_REG,
25327458df8SWei Liu     X86_VAR_RM,
25427458df8SWei Liu 
25527458df8SWei Liu     /* for floating point computations */
25627458df8SWei Liu     X87_VAR_REG,
25727458df8SWei Liu     X87_VAR_FLOATP,
25827458df8SWei Liu     X87_VAR_INTP,
25927458df8SWei Liu     X87_VAR_BYTEP,
26027458df8SWei Liu } x86_var_type;
26127458df8SWei Liu 
26227458df8SWei Liu typedef struct x86_decode_op {
26327458df8SWei Liu     enum x86_var_type type;
26427458df8SWei Liu     int size;
26527458df8SWei Liu 
26627458df8SWei Liu     int reg;
26727458df8SWei Liu     target_ulong val;
26827458df8SWei Liu 
269*77a2dba4SPaolo Bonzini     union {
270*77a2dba4SPaolo Bonzini         target_ulong addr;
271*77a2dba4SPaolo Bonzini         void *regptr;
272*77a2dba4SPaolo Bonzini     };
27327458df8SWei Liu } x86_decode_op;
27427458df8SWei Liu 
27527458df8SWei Liu typedef struct x86_decode {
27627458df8SWei Liu     int len;
27727458df8SWei Liu     uint8_t opcode[4];
27827458df8SWei Liu     uint8_t opcode_len;
27927458df8SWei Liu     enum x86_decode_cmd cmd;
28027458df8SWei Liu     int addressing_size;
28127458df8SWei Liu     int operand_size;
28227458df8SWei Liu     int lock;
28327458df8SWei Liu     int rep;
28427458df8SWei Liu     int op_size_override;
28527458df8SWei Liu     int addr_size_override;
28627458df8SWei Liu     int segment_override;
28727458df8SWei Liu     int control_change_inst;
28827458df8SWei Liu     bool fwait;
28927458df8SWei Liu     bool fpop_stack;
29027458df8SWei Liu     bool frev;
29127458df8SWei Liu 
29227458df8SWei Liu     uint32_t displacement;
29327458df8SWei Liu     uint8_t displacement_size;
29427458df8SWei Liu     struct x86_rex rex;
29527458df8SWei Liu     bool is_modrm;
29627458df8SWei Liu     bool sib_present;
29727458df8SWei Liu     struct x86_sib sib;
29827458df8SWei Liu     struct x86_modrm modrm;
29927458df8SWei Liu     struct x86_decode_op op[4];
30027458df8SWei Liu     bool is_fpu;
30127458df8SWei Liu } x86_decode;
30227458df8SWei Liu 
30327458df8SWei Liu uint64_t sign(uint64_t val, int size);
30427458df8SWei Liu 
30527458df8SWei Liu uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode);
30627458df8SWei Liu 
307*77a2dba4SPaolo Bonzini void *get_reg_ref(CPUX86State *env, int reg, int rex_present,
30827458df8SWei Liu                   int is_extended, int size);
30927458df8SWei Liu target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present,
31027458df8SWei Liu                          int is_extended, int size);
31127458df8SWei Liu void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode,
31227458df8SWei Liu                         struct x86_decode_op *op);
31327458df8SWei Liu target_ulong decode_linear_addr(CPUX86State *env, struct x86_decode *decode,
31427458df8SWei Liu                                target_ulong addr, enum X86Seg seg);
31527458df8SWei Liu 
31627458df8SWei Liu void init_decoder(void);
31727458df8SWei Liu void calc_modrm_operand16(CPUX86State *env, struct x86_decode *decode,
31827458df8SWei Liu                           struct x86_decode_op *op);
31927458df8SWei Liu void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode,
32027458df8SWei Liu                           struct x86_decode_op *op);
32127458df8SWei Liu void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode,
32227458df8SWei Liu                           struct x86_decode_op *op);
32327458df8SWei Liu void set_addressing_size(CPUX86State *env, struct x86_decode *decode);
32427458df8SWei Liu void set_operand_size(CPUX86State *env, struct x86_decode *decode);
32527458df8SWei Liu 
32627458df8SWei Liu #endif
327