| 1 | /* |
| 2 | * Copyright (C) 2016 Veertu Inc, |
| 3 | * |
| 4 | * This program is free software; you can redistribute it and/or |
| 5 | * modify it under the terms of the GNU Lesser General Public |
| 6 | * License as published by the Free Software Foundation; either |
| 7 | * version 2.1 of the License, or (at your option) any later version. |
| 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 |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 | * Lesser General Public License for more details. |
| 13 | * |
| 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/>. |
| 16 | */ |
| 17 | |
| 18 | #ifndef X86_EMU_DECODE_H |
| 19 | #define X86_EMU_DECODE_H |
| 20 | |
| 21 | #include "cpu.h" |
| 22 | #include "x86.h" |
| 23 | |
| 24 | typedef enum x86_prefix { |
| 25 | /* group 1 */ |
| 26 | PREFIX_LOCK = 0xf0, |
| 27 | PREFIX_REPN = 0xf2, |
| 28 | PREFIX_REP = 0xf3, |
| 29 | /* group 2 */ |
| 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, |
| 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; |
| 267 | target_ulong val; |
| 268 | |
| 269 | union { |
| 270 | target_ulong addr; |
| 271 | void *regptr; |
| 272 | }; |
| 273 | } x86_decode_op; |
| 274 | |
| 275 | typedef struct x86_insn_stream { |
| 276 | const uint8_t *bytes; |
| 277 | size_t len; |
| 278 | } x86_insn_stream; |
| 279 | |
| 280 | typedef struct x86_decode { |
| 281 | int len; |
| 282 | uint8_t opcode[4]; |
| 283 | uint8_t opcode_len; |
| 284 | enum x86_decode_cmd cmd; |
| 285 | int addressing_size; |
| 286 | int operand_size; |
| 287 | int lock; |
| 288 | int rep; |
| 289 | int op_size_override; |
| 290 | int addr_size_override; |
| 291 | int segment_override; |
| 292 | int control_change_inst; |
| 293 | bool fwait; |
| 294 | bool fpop_stack; |
| 295 | bool frev; |
| 296 | |
| 297 | uint32_t displacement; |
| 298 | uint8_t displacement_size; |
| 299 | struct x86_rex rex; |
| 300 | bool is_modrm; |
| 301 | bool sib_present; |
| 302 | struct x86_sib sib; |
| 303 | struct x86_modrm modrm; |
| 304 | struct x86_decode_op op[4]; |
| 305 | bool is_fpu; |
| 306 | |
| 307 | x86_insn_stream *stream; |
| 308 | } x86_decode; |
| 309 | |
| 310 | uint64_t sign(uint64_t val, int size); |
| 311 | |
| 312 | uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode); |
| 313 | uint32_t decode_instruction_stream(CPUX86State *env, struct x86_decode *decode, |
| 314 | struct x86_insn_stream *stream); |
| 315 | |
| 316 | void *get_reg_ref(CPUX86State *env, int reg, int rex_present, |
| 317 | int is_extended, int size); |
| 318 | target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present, |
| 319 | int is_extended, int size); |
| 320 | void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode, |
| 321 | struct x86_decode_op *op); |
| 322 | target_ulong decode_linear_addr(CPUX86State *env, struct x86_decode *decode, |
| 323 | target_ulong addr, enum X86Seg seg); |
| 324 | |
| 325 | void init_decoder(void); |
| 326 | void calc_modrm_operand16(CPUX86State *env, struct x86_decode *decode, |
| 327 | struct x86_decode_op *op); |
| 328 | void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode, |
| 329 | struct x86_decode_op *op); |
| 330 | void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode, |
| 331 | struct x86_decode_op *op); |
| 332 | void set_addressing_size(CPUX86State *env, struct x86_decode *decode); |
| 333 | void set_operand_size(CPUX86State *env, struct x86_decode *decode); |
| 334 | |
| 335 | #endif |