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