From: Wei Liu Date: Fri, 7 Mar 2025 19:55:24 +0000 (-0800) Subject: target/i386: move x86 instruction emulator out of hvf X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=27458df871097d7fc14b19d9e01c35d29737b9b3;p=people%2Faperard%2Fqemu-dm.git target/i386: move x86 instruction emulator out of hvf Move x86_decode, x86_emu, x86_flags and some headers to the new location. Fix up all the inclusion sites in hvf. Signed-off-by: Wei Liu Link: https://lore.kernel.org/r/1741377325-28175-14-git-send-email-liuwe@linux.microsoft.com Signed-off-by: Paolo Bonzini --- diff --git a/target/i386/emulate/meson.build b/target/i386/emulate/meson.build index e69de29bb2..4edd4f462f 100644 --- a/target/i386/emulate/meson.build +++ b/target/i386/emulate/meson.build @@ -0,0 +1,5 @@ +i386_system_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: files( + 'x86_decode.c', + 'x86_emu.c', + 'x86_flags.c', +)) diff --git a/target/i386/emulate/x86.h b/target/i386/emulate/x86.h new file mode 100644 index 0000000000..73edccfba0 --- /dev/null +++ b/target/i386/emulate/x86.h @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2016 Veertu Inc, + * Copyright (C) 2017 Veertu Inc, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef X86_EMU_DEFS_H +#define X86_EMU_DEFS_H + +typedef struct x86_register { + union { + struct { + uint64_t rrx; /* full 64 bit */ + }; + struct { + uint32_t erx; /* low 32 bit part */ + uint32_t hi32_unused1; + }; + struct { + uint16_t rx; /* low 16 bit part */ + uint16_t hi16_unused1; + uint32_t hi32_unused2; + }; + struct { + uint8_t lx; /* low 8 bit part */ + uint8_t hx; /* high 8 bit */ + uint16_t hi16_unused2; + uint32_t hi32_unused3; + }; + }; +} __attribute__ ((__packed__)) x86_register; + +/* 16 bit Task State Segment */ +typedef struct x86_tss_segment16 { + uint16_t link; + uint16_t sp0; + uint16_t ss0; + uint32_t sp1; + uint16_t ss1; + uint32_t sp2; + uint16_t ss2; + uint16_t ip; + uint16_t flags; + uint16_t ax; + uint16_t cx; + uint16_t dx; + uint16_t bx; + uint16_t sp; + uint16_t bp; + uint16_t si; + uint16_t di; + uint16_t es; + uint16_t cs; + uint16_t ss; + uint16_t ds; + uint16_t ldtr; +} __attribute__((packed)) x86_tss_segment16; + +/* 32 bit Task State Segment */ +typedef struct x86_tss_segment32 { + uint32_t prev_tss; + uint32_t esp0; + uint32_t ss0; + uint32_t esp1; + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldt; + uint16_t trap; + uint16_t iomap_base; +} __attribute__ ((__packed__)) x86_tss_segment32; + +/* 64 bit Task State Segment */ +typedef struct x86_tss_segment64 { + uint32_t unused; + uint64_t rsp0; + uint64_t rsp1; + uint64_t rsp2; + uint64_t unused1; + uint64_t ist1; + uint64_t ist2; + uint64_t ist3; + uint64_t ist4; + uint64_t ist5; + uint64_t ist6; + uint64_t ist7; + uint64_t unused2; + uint16_t unused3; + uint16_t iomap_base; +} __attribute__ ((__packed__)) x86_tss_segment64; + +/* segment descriptors */ +typedef struct x86_segment_descriptor { + uint64_t limit0:16; + uint64_t base0:16; + uint64_t base1:8; + uint64_t type:4; + uint64_t s:1; + uint64_t dpl:2; + uint64_t p:1; + uint64_t limit1:4; + uint64_t avl:1; + uint64_t l:1; + uint64_t db:1; + uint64_t g:1; + uint64_t base2:8; +} __attribute__ ((__packed__)) x86_segment_descriptor; + +static inline uint32_t x86_segment_base(x86_segment_descriptor *desc) +{ + return (uint32_t)((desc->base2 << 24) | (desc->base1 << 16) | desc->base0); +} + +static inline void x86_set_segment_base(x86_segment_descriptor *desc, + uint32_t base) +{ + desc->base2 = base >> 24; + desc->base1 = (base >> 16) & 0xff; + desc->base0 = base & 0xffff; +} + +static inline uint32_t x86_segment_limit(x86_segment_descriptor *desc) +{ + uint32_t limit = (uint32_t)((desc->limit1 << 16) | desc->limit0); + if (desc->g) { + return (limit << 12) | 0xfff; + } + return limit; +} + +static inline void x86_set_segment_limit(x86_segment_descriptor *desc, + uint32_t limit) +{ + desc->limit0 = limit & 0xffff; + desc->limit1 = limit >> 16; +} + +typedef struct x86_call_gate { + uint64_t offset0:16; + uint64_t selector:16; + uint64_t param_count:4; + uint64_t reserved:3; + uint64_t type:4; + uint64_t dpl:1; + uint64_t p:1; + uint64_t offset1:16; +} __attribute__ ((__packed__)) x86_call_gate; + +static inline uint32_t x86_call_gate_offset(x86_call_gate *gate) +{ + return (uint32_t)((gate->offset1 << 16) | gate->offset0); +} + +#define GDT_SEL 0 +#define LDT_SEL 1 + +typedef struct x86_segment_selector { + union { + uint16_t sel; + struct { + uint16_t rpl:2; + uint16_t ti:1; + uint16_t index:13; + }; + }; +} __attribute__ ((__packed__)) x86_segment_selector; + +/* useful register access macros */ +#define x86_reg(cpu, reg) ((x86_register *) &cpu->regs[reg]) + +#define RRX(cpu, reg) (x86_reg(cpu, reg)->rrx) +#define RAX(cpu) RRX(cpu, R_EAX) +#define RCX(cpu) RRX(cpu, R_ECX) +#define RDX(cpu) RRX(cpu, R_EDX) +#define RBX(cpu) RRX(cpu, R_EBX) +#define RSP(cpu) RRX(cpu, R_ESP) +#define RBP(cpu) RRX(cpu, R_EBP) +#define RSI(cpu) RRX(cpu, R_ESI) +#define RDI(cpu) RRX(cpu, R_EDI) +#define R8(cpu) RRX(cpu, R_R8) +#define R9(cpu) RRX(cpu, R_R9) +#define R10(cpu) RRX(cpu, R_R10) +#define R11(cpu) RRX(cpu, R_R11) +#define R12(cpu) RRX(cpu, R_R12) +#define R13(cpu) RRX(cpu, R_R13) +#define R14(cpu) RRX(cpu, R_R14) +#define R15(cpu) RRX(cpu, R_R15) + +#define ERX(cpu, reg) (x86_reg(cpu, reg)->erx) +#define EAX(cpu) ERX(cpu, R_EAX) +#define ECX(cpu) ERX(cpu, R_ECX) +#define EDX(cpu) ERX(cpu, R_EDX) +#define EBX(cpu) ERX(cpu, R_EBX) +#define ESP(cpu) ERX(cpu, R_ESP) +#define EBP(cpu) ERX(cpu, R_EBP) +#define ESI(cpu) ERX(cpu, R_ESI) +#define EDI(cpu) ERX(cpu, R_EDI) + +#define RX(cpu, reg) (x86_reg(cpu, reg)->rx) +#define AX(cpu) RX(cpu, R_EAX) +#define CX(cpu) RX(cpu, R_ECX) +#define DX(cpu) RX(cpu, R_EDX) +#define BP(cpu) RX(cpu, R_EBP) +#define SP(cpu) RX(cpu, R_ESP) +#define BX(cpu) RX(cpu, R_EBX) +#define SI(cpu) RX(cpu, R_ESI) +#define DI(cpu) RX(cpu, R_EDI) + +#define RL(cpu, reg) (x86_reg(cpu, reg)->lx) +#define AL(cpu) RL(cpu, R_EAX) +#define CL(cpu) RL(cpu, R_ECX) +#define DL(cpu) RL(cpu, R_EDX) +#define BL(cpu) RL(cpu, R_EBX) + +#define RH(cpu, reg) (x86_reg(cpu, reg)->hx) +#define AH(cpu) RH(cpu, R_EAX) +#define CH(cpu) RH(cpu, R_ECX) +#define DH(cpu) RH(cpu, R_EDX) +#define BH(cpu) RH(cpu, R_EBX) + +/* deal with GDT/LDT descriptors in memory */ +bool x86_read_segment_descriptor(CPUState *cpu, + struct x86_segment_descriptor *desc, + x86_segment_selector sel); +bool x86_write_segment_descriptor(CPUState *cpu, + struct x86_segment_descriptor *desc, + x86_segment_selector sel); + +bool x86_read_call_gate(CPUState *cpu, struct x86_call_gate *idt_desc, + int gate); + +/* helpers */ +bool x86_is_protected(CPUState *cpu); +bool x86_is_real(CPUState *cpu); +bool x86_is_v8086(CPUState *cpu); +bool x86_is_long_mode(CPUState *cpu); +bool x86_is_long64_mode(CPUState *cpu); +bool x86_is_paging_mode(CPUState *cpu); +bool x86_is_pae_enabled(CPUState *cpu); + +enum X86Seg; +target_ulong linear_addr(CPUState *cpu, target_ulong addr, enum X86Seg seg); +target_ulong linear_addr_size(CPUState *cpu, target_ulong addr, int size, + enum X86Seg seg); +target_ulong linear_rip(CPUState *cpu, target_ulong rip); + +static inline uint64_t rdtscp(void) +{ + uint64_t tsc; + __asm__ __volatile__("rdtscp; " /* serializing read of tsc */ + "shl $32,%%rdx; " /* shift higher 32 bits stored in rdx up */ + "or %%rdx,%%rax" /* and or onto rax */ + : "=a"(tsc) /* output to tsc variable */ + : + : "%rcx", "%rdx"); /* rcx and rdx are clobbered */ + + return tsc; +} + +#endif diff --git a/target/i386/emulate/x86_decode.c b/target/i386/emulate/x86_decode.c new file mode 100644 index 0000000000..ddd7b60bcf --- /dev/null +++ b/target/i386/emulate/x86_decode.c @@ -0,0 +1,2194 @@ +/* + * Copyright (C) 2016 Veertu Inc, + * Copyright (C) 2017 Google Inc, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include "qemu/osdep.h" + +#include "panic.h" +#include "x86_decode.h" +#include "x86_emu.h" + +#define OPCODE_ESCAPE 0xf + +static void decode_invalid(CPUX86State *env, struct x86_decode *decode) +{ + printf("%llx: failed to decode instruction ", env->eip); + for (int i = 0; i < decode->opcode_len; i++) { + printf("%x ", decode->opcode[i]); + } + printf("\n"); + VM_PANIC("decoder failed\n"); +} + +uint64_t sign(uint64_t val, int size) +{ + switch (size) { + case 1: + val = (int8_t)val; + break; + case 2: + val = (int16_t)val; + break; + case 4: + val = (int32_t)val; + break; + case 8: + val = (int64_t)val; + break; + default: + VM_PANIC_EX("%s invalid size %d\n", __func__, size); + break; + } + return val; +} + +static inline uint64_t decode_bytes(CPUX86State *env, struct x86_decode *decode, + int size) +{ + uint64_t val = 0; + + switch (size) { + case 1: + case 2: + case 4: + case 8: + break; + default: + VM_PANIC_EX("%s invalid size %d\n", __func__, size); + break; + } + target_ulong va = linear_rip(env_cpu(env), env->eip) + decode->len; + emul_ops->read_mem(env_cpu(env), &val, va, size); + decode->len += size; + + return val; +} + +static inline uint8_t decode_byte(CPUX86State *env, struct x86_decode *decode) +{ + return (uint8_t)decode_bytes(env, decode, 1); +} + +static inline uint16_t decode_word(CPUX86State *env, struct x86_decode *decode) +{ + return (uint16_t)decode_bytes(env, decode, 2); +} + +static inline uint32_t decode_dword(CPUX86State *env, struct x86_decode *decode) +{ + return (uint32_t)decode_bytes(env, decode, 4); +} + +static inline uint64_t decode_qword(CPUX86State *env, struct x86_decode *decode) +{ + return decode_bytes(env, decode, 8); +} + +static void decode_modrm_rm(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + op->type = X86_VAR_RM; +} + +static void decode_modrm_reg(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + op->type = X86_VAR_REG; + op->reg = decode->modrm.reg; + op->ptr = get_reg_ref(env, op->reg, decode->rex.rex, decode->rex.r, + decode->operand_size); +} + +static void decode_rax(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + op->type = X86_VAR_REG; + op->reg = R_EAX; + /* Since reg is always AX, REX prefix has no impact. */ + op->ptr = get_reg_ref(env, op->reg, false, 0, + decode->operand_size); +} + +static inline void decode_immediate(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *var, int size) +{ + var->type = X86_VAR_IMMEDIATE; + var->size = size; + switch (size) { + case 1: + var->val = decode_byte(env, decode); + break; + case 2: + var->val = decode_word(env, decode); + break; + case 4: + var->val = decode_dword(env, decode); + break; + case 8: + var->val = decode_qword(env, decode); + break; + default: + VM_PANIC_EX("bad size %d\n", size); + } +} + +static void decode_imm8(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + decode_immediate(env, decode, op, 1); + op->type = X86_VAR_IMMEDIATE; +} + +static void decode_imm8_signed(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + decode_immediate(env, decode, op, 1); + op->val = sign(op->val, 1); + op->type = X86_VAR_IMMEDIATE; +} + +static void decode_imm16(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + decode_immediate(env, decode, op, 2); + op->type = X86_VAR_IMMEDIATE; +} + + +static void decode_imm(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + if (8 == decode->operand_size) { + decode_immediate(env, decode, op, 4); + op->val = sign(op->val, decode->operand_size); + } else { + decode_immediate(env, decode, op, decode->operand_size); + } + op->type = X86_VAR_IMMEDIATE; +} + +static void decode_imm_signed(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + decode_immediate(env, decode, op, decode->operand_size); + op->val = sign(op->val, decode->operand_size); + op->type = X86_VAR_IMMEDIATE; +} + +static void decode_imm_1(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + op->type = X86_VAR_IMMEDIATE; + op->val = 1; +} + +static void decode_imm_0(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + op->type = X86_VAR_IMMEDIATE; + op->val = 0; +} + + +static void decode_pushseg(CPUX86State *env, struct x86_decode *decode) +{ + uint8_t op = (decode->opcode_len > 1) ? decode->opcode[1] : decode->opcode[0]; + + decode->op[0].type = X86_VAR_REG; + switch (op) { + case 0xe: + decode->op[0].reg = R_CS; + break; + case 0x16: + decode->op[0].reg = R_SS; + break; + case 0x1e: + decode->op[0].reg = R_DS; + break; + case 0x06: + decode->op[0].reg = R_ES; + break; + case 0xa0: + decode->op[0].reg = R_FS; + break; + case 0xa8: + decode->op[0].reg = R_GS; + break; + } +} + +static void decode_popseg(CPUX86State *env, struct x86_decode *decode) +{ + uint8_t op = (decode->opcode_len > 1) ? decode->opcode[1] : decode->opcode[0]; + + decode->op[0].type = X86_VAR_REG; + switch (op) { + case 0xf: + decode->op[0].reg = R_CS; + break; + case 0x17: + decode->op[0].reg = R_SS; + break; + case 0x1f: + decode->op[0].reg = R_DS; + break; + case 0x07: + decode->op[0].reg = R_ES; + break; + case 0xa1: + decode->op[0].reg = R_FS; + break; + case 0xa9: + decode->op[0].reg = R_GS; + break; + } +} + +static void decode_incgroup(CPUX86State *env, struct x86_decode *decode) +{ + decode->op[0].type = X86_VAR_REG; + decode->op[0].reg = decode->opcode[0] - 0x40; + decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, + decode->rex.b, decode->operand_size); +} + +static void decode_decgroup(CPUX86State *env, struct x86_decode *decode) +{ + decode->op[0].type = X86_VAR_REG; + decode->op[0].reg = decode->opcode[0] - 0x48; + decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, + decode->rex.b, decode->operand_size); +} + +static void decode_incgroup2(CPUX86State *env, struct x86_decode *decode) +{ + if (!decode->modrm.reg) { + decode->cmd = X86_DECODE_CMD_INC; + } else if (1 == decode->modrm.reg) { + decode->cmd = X86_DECODE_CMD_DEC; + } +} + +static void decode_pushgroup(CPUX86State *env, struct x86_decode *decode) +{ + decode->op[0].type = X86_VAR_REG; + decode->op[0].reg = decode->opcode[0] - 0x50; + decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, + decode->rex.b, decode->operand_size); +} + +static void decode_popgroup(CPUX86State *env, struct x86_decode *decode) +{ + decode->op[0].type = X86_VAR_REG; + decode->op[0].reg = decode->opcode[0] - 0x58; + decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, + decode->rex.b, decode->operand_size); +} + +static void decode_jxx(CPUX86State *env, struct x86_decode *decode) +{ + decode->displacement = decode_bytes(env, decode, decode->operand_size); + decode->displacement_size = decode->operand_size; +} + +static void decode_farjmp(CPUX86State *env, struct x86_decode *decode) +{ + decode->op[0].type = X86_VAR_IMMEDIATE; + decode->op[0].val = decode_bytes(env, decode, decode->operand_size); + decode->displacement = decode_word(env, decode); +} + +static void decode_addgroup(CPUX86State *env, struct x86_decode *decode) +{ + enum x86_decode_cmd group[] = { + X86_DECODE_CMD_ADD, + X86_DECODE_CMD_OR, + X86_DECODE_CMD_ADC, + X86_DECODE_CMD_SBB, + X86_DECODE_CMD_AND, + X86_DECODE_CMD_SUB, + X86_DECODE_CMD_XOR, + X86_DECODE_CMD_CMP + }; + decode->cmd = group[decode->modrm.reg]; +} + +static void decode_rotgroup(CPUX86State *env, struct x86_decode *decode) +{ + enum x86_decode_cmd group[] = { + X86_DECODE_CMD_ROL, + X86_DECODE_CMD_ROR, + X86_DECODE_CMD_RCL, + X86_DECODE_CMD_RCR, + X86_DECODE_CMD_SHL, + X86_DECODE_CMD_SHR, + X86_DECODE_CMD_SHL, + X86_DECODE_CMD_SAR + }; + decode->cmd = group[decode->modrm.reg]; +} + +static void decode_f7group(CPUX86State *env, struct x86_decode *decode) +{ + enum x86_decode_cmd group[] = { + X86_DECODE_CMD_TST, + X86_DECODE_CMD_TST, + X86_DECODE_CMD_NOT, + X86_DECODE_CMD_NEG, + X86_DECODE_CMD_MUL, + X86_DECODE_CMD_IMUL_1, + X86_DECODE_CMD_DIV, + X86_DECODE_CMD_IDIV + }; + decode->cmd = group[decode->modrm.reg]; + decode_modrm_rm(env, decode, &decode->op[0]); + + switch (decode->modrm.reg) { + case 0: + case 1: + decode_imm(env, decode, &decode->op[1]); + break; + case 2: + break; + case 3: + decode->op[1].type = X86_VAR_IMMEDIATE; + decode->op[1].val = 0; + break; + default: + break; + } +} + +static void decode_xchgroup(CPUX86State *env, struct x86_decode *decode) +{ + decode->op[0].type = X86_VAR_REG; + decode->op[0].reg = decode->opcode[0] - 0x90; + decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, + decode->rex.b, decode->operand_size); +} + +static void decode_movgroup(CPUX86State *env, struct x86_decode *decode) +{ + decode->op[0].type = X86_VAR_REG; + decode->op[0].reg = decode->opcode[0] - 0xb8; + decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, + decode->rex.b, decode->operand_size); + decode_immediate(env, decode, &decode->op[1], decode->operand_size); +} + +static void fetch_moffs(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + op->type = X86_VAR_OFFSET; + op->ptr = decode_bytes(env, decode, decode->addressing_size); +} + +static void decode_movgroup8(CPUX86State *env, struct x86_decode *decode) +{ + decode->op[0].type = X86_VAR_REG; + decode->op[0].reg = decode->opcode[0] - 0xb0; + decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, + decode->rex.b, decode->operand_size); + decode_immediate(env, decode, &decode->op[1], decode->operand_size); +} + +static void decode_rcx(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + op->type = X86_VAR_REG; + op->reg = R_ECX; + op->ptr = get_reg_ref(env, op->reg, decode->rex.rex, decode->rex.b, + decode->operand_size); +} + +struct decode_tbl { + uint8_t opcode; + enum x86_decode_cmd cmd; + uint8_t operand_size; + bool is_modrm; + void (*decode_op1)(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op1); + void (*decode_op2)(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op2); + void (*decode_op3)(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op3); + void (*decode_op4)(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op4); + void (*decode_postfix)(CPUX86State *env, struct x86_decode *decode); + uint32_t flags_mask; +}; + +struct decode_x87_tbl { + uint8_t opcode; + uint8_t modrm_reg; + uint8_t modrm_mod; + enum x86_decode_cmd cmd; + uint8_t operand_size; + bool rev; + bool pop; + void (*decode_op1)(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op1); + void (*decode_op2)(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op2); + void (*decode_postfix)(CPUX86State *env, struct x86_decode *decode); + uint32_t flags_mask; +}; + +struct decode_tbl invl_inst = {0x0, 0, 0, false, NULL, NULL, NULL, NULL, + decode_invalid}; + +struct decode_tbl _decode_tbl1[256]; +struct decode_tbl _decode_tbl2[256]; +struct decode_x87_tbl _decode_tbl3[256]; + +static void decode_x87_ins(CPUX86State *env, struct x86_decode *decode) +{ + struct decode_x87_tbl *decoder; + + decode->is_fpu = true; + int mode = decode->modrm.mod == 3 ? 1 : 0; + int index = ((decode->opcode[0] & 0xf) << 4) | (mode << 3) | + decode->modrm.reg; + + decoder = &_decode_tbl3[index]; + + decode->cmd = decoder->cmd; + if (decoder->operand_size) { + decode->operand_size = decoder->operand_size; + } + decode->flags_mask = decoder->flags_mask; + decode->fpop_stack = decoder->pop; + decode->frev = decoder->rev; + + if (decoder->decode_op1) { + decoder->decode_op1(env, decode, &decode->op[0]); + } + if (decoder->decode_op2) { + decoder->decode_op2(env, decode, &decode->op[1]); + } + if (decoder->decode_postfix) { + decoder->decode_postfix(env, decode); + } + + VM_PANIC_ON_EX(!decode->cmd, "x87 opcode %x %x (%x %x) not decoded\n", + decode->opcode[0], decode->modrm.modrm, decoder->modrm_reg, + decoder->modrm_mod); +} + +static void decode_ffgroup(CPUX86State *env, struct x86_decode *decode) +{ + enum x86_decode_cmd group[] = { + X86_DECODE_CMD_INC, + X86_DECODE_CMD_DEC, + X86_DECODE_CMD_CALL_NEAR_ABS_INDIRECT, + X86_DECODE_CMD_CALL_FAR_ABS_INDIRECT, + X86_DECODE_CMD_JMP_NEAR_ABS_INDIRECT, + X86_DECODE_CMD_JMP_FAR_ABS_INDIRECT, + X86_DECODE_CMD_PUSH, + X86_DECODE_CMD_INVL, + X86_DECODE_CMD_INVL + }; + decode->cmd = group[decode->modrm.reg]; + if (decode->modrm.reg > 2) { + decode->flags_mask = 0; + } +} + +static void decode_sldtgroup(CPUX86State *env, struct x86_decode *decode) +{ + + enum x86_decode_cmd group[] = { + X86_DECODE_CMD_SLDT, + X86_DECODE_CMD_STR, + X86_DECODE_CMD_LLDT, + X86_DECODE_CMD_LTR, + X86_DECODE_CMD_VERR, + X86_DECODE_CMD_VERW, + X86_DECODE_CMD_INVL, + X86_DECODE_CMD_INVL + }; + decode->cmd = group[decode->modrm.reg]; +} + +static void decode_lidtgroup(CPUX86State *env, struct x86_decode *decode) +{ + enum x86_decode_cmd group[] = { + X86_DECODE_CMD_SGDT, + X86_DECODE_CMD_SIDT, + X86_DECODE_CMD_LGDT, + X86_DECODE_CMD_LIDT, + X86_DECODE_CMD_SMSW, + X86_DECODE_CMD_LMSW, + X86_DECODE_CMD_LMSW, + X86_DECODE_CMD_INVLPG + }; + decode->cmd = group[decode->modrm.reg]; + if (0xf9 == decode->modrm.modrm) { + decode->opcode[decode->len++] = decode->modrm.modrm; + decode->cmd = X86_DECODE_CMD_RDTSCP; + } +} + +static void decode_btgroup(CPUX86State *env, struct x86_decode *decode) +{ + enum x86_decode_cmd group[] = { + X86_DECODE_CMD_INVL, + X86_DECODE_CMD_INVL, + X86_DECODE_CMD_INVL, + X86_DECODE_CMD_INVL, + X86_DECODE_CMD_BT, + X86_DECODE_CMD_BTS, + X86_DECODE_CMD_BTR, + X86_DECODE_CMD_BTC + }; + decode->cmd = group[decode->modrm.reg]; +} + +static void decode_x87_general(CPUX86State *env, struct x86_decode *decode) +{ + decode->is_fpu = true; +} + +static void decode_x87_modrm_floatp(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + op->type = X87_VAR_FLOATP; +} + +static void decode_x87_modrm_intp(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + op->type = X87_VAR_INTP; +} + +static void decode_x87_modrm_bytep(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + op->type = X87_VAR_BYTEP; +} + +static void decode_x87_modrm_st0(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + op->type = X87_VAR_REG; + op->reg = 0; +} + +static void decode_decode_x87_modrm_st0(CPUX86State *env, + struct x86_decode *decode, + struct x86_decode_op *op) +{ + op->type = X87_VAR_REG; + op->reg = decode->modrm.modrm & 7; +} + + +static void decode_aegroup(CPUX86State *env, struct x86_decode *decode) +{ + decode->is_fpu = true; + switch (decode->modrm.reg) { + case 0: + decode->cmd = X86_DECODE_CMD_FXSAVE; + decode_x87_modrm_bytep(env, decode, &decode->op[0]); + break; + case 1: + decode_x87_modrm_bytep(env, decode, &decode->op[0]); + decode->cmd = X86_DECODE_CMD_FXRSTOR; + break; + case 5: + if (decode->modrm.modrm == 0xe8) { + decode->cmd = X86_DECODE_CMD_LFENCE; + } else { + VM_PANIC("xrstor"); + } + break; + case 6: + VM_PANIC_ON(decode->modrm.modrm != 0xf0); + decode->cmd = X86_DECODE_CMD_MFENCE; + break; + case 7: + if (decode->modrm.modrm == 0xf8) { + decode->cmd = X86_DECODE_CMD_SFENCE; + } else { + decode->cmd = X86_DECODE_CMD_CLFLUSH; + } + break; + default: + VM_PANIC_EX("0xae: reg %d\n", decode->modrm.reg); + break; + } +} + +static void decode_bswap(CPUX86State *env, struct x86_decode *decode) +{ + decode->op[0].type = X86_VAR_REG; + decode->op[0].reg = decode->opcode[1] - 0xc8; + decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, + decode->rex.b, decode->operand_size); +} + +static void decode_d9_4(CPUX86State *env, struct x86_decode *decode) +{ + switch (decode->modrm.modrm) { + case 0xe0: + /* FCHS */ + decode->cmd = X86_DECODE_CMD_FCHS; + break; + case 0xe1: + decode->cmd = X86_DECODE_CMD_FABS; + break; + case 0xe4: + VM_PANIC("FTST"); + break; + case 0xe5: + /* FXAM */ + decode->cmd = X86_DECODE_CMD_FXAM; + break; + default: + VM_PANIC("FLDENV"); + break; + } +} + +static void decode_db_4(CPUX86State *env, struct x86_decode *decode) +{ + switch (decode->modrm.modrm) { + case 0xe0: + VM_PANIC_EX("unhandled FNENI: %x %x\n", decode->opcode[0], + decode->modrm.modrm); + break; + case 0xe1: + VM_PANIC_EX("unhandled FNDISI: %x %x\n", decode->opcode[0], + decode->modrm.modrm); + break; + case 0xe2: + VM_PANIC_EX("unhandled FCLEX: %x %x\n", decode->opcode[0], + decode->modrm.modrm); + break; + case 0xe3: + decode->cmd = X86_DECODE_CMD_FNINIT; + break; + case 0xe4: + decode->cmd = X86_DECODE_CMD_FNSETPM; + break; + default: + VM_PANIC_EX("unhandled fpu opcode: %x %x\n", decode->opcode[0], + decode->modrm.modrm); + break; + } +} + + +#define RFLAGS_MASK_NONE 0 +#define RFLAGS_MASK_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C) +#define RFLAGS_MASK_LAHF (CC_S | CC_Z | CC_A | CC_P | CC_C) +#define RFLAGS_MASK_CF (CC_C) +#define RFLAGS_MASK_IF (IF_MASK) +#define RFLAGS_MASK_TF (TF_MASK) +#define RFLAGS_MASK_DF (DF_MASK) +#define RFLAGS_MASK_ZF (CC_Z) + +struct decode_tbl _1op_inst[] = { + {0x0, X86_DECODE_CMD_ADD, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, + NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x1, X86_DECODE_CMD_ADD, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, + NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x2, X86_DECODE_CMD_ADD, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, + NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x3, X86_DECODE_CMD_ADD, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, + NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x4, X86_DECODE_CMD_ADD, 1, false, decode_rax, decode_imm8, NULL, NULL, + NULL, RFLAGS_MASK_OSZAPC}, + {0x5, X86_DECODE_CMD_ADD, 0, false, decode_rax, decode_imm, NULL, NULL, + NULL, RFLAGS_MASK_OSZAPC}, + {0x6, X86_DECODE_CMD_PUSH_SEG, 0, false, false, NULL, NULL, NULL, + decode_pushseg, RFLAGS_MASK_NONE}, + {0x7, X86_DECODE_CMD_POP_SEG, 0, false, false, NULL, NULL, NULL, + decode_popseg, RFLAGS_MASK_NONE}, + {0x8, X86_DECODE_CMD_OR, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, + NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x9, X86_DECODE_CMD_OR, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, + NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xa, X86_DECODE_CMD_OR, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, + NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xb, X86_DECODE_CMD_OR, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xc, X86_DECODE_CMD_OR, 1, false, decode_rax, decode_imm8, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xd, X86_DECODE_CMD_OR, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0xe, X86_DECODE_CMD_PUSH_SEG, 0, false, false, + NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + {0xf, X86_DECODE_CMD_POP_SEG, 0, false, false, + NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + + {0x10, X86_DECODE_CMD_ADC, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x11, X86_DECODE_CMD_ADC, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x12, X86_DECODE_CMD_ADC, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x13, X86_DECODE_CMD_ADC, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x14, X86_DECODE_CMD_ADC, 1, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x15, X86_DECODE_CMD_ADC, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0x16, X86_DECODE_CMD_PUSH_SEG, 0, false, false, + NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + {0x17, X86_DECODE_CMD_POP_SEG, 0, false, false, + NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + + {0x18, X86_DECODE_CMD_SBB, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x19, X86_DECODE_CMD_SBB, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x1a, X86_DECODE_CMD_SBB, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x1b, X86_DECODE_CMD_SBB, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x1c, X86_DECODE_CMD_SBB, 1, false, decode_rax, decode_imm8, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x1d, X86_DECODE_CMD_SBB, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0x1e, X86_DECODE_CMD_PUSH_SEG, 0, false, false, + NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + {0x1f, X86_DECODE_CMD_POP_SEG, 0, false, false, + NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + + {0x20, X86_DECODE_CMD_AND, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x21, X86_DECODE_CMD_AND, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x22, X86_DECODE_CMD_AND, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x23, X86_DECODE_CMD_AND, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x24, X86_DECODE_CMD_AND, 1, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x25, X86_DECODE_CMD_AND, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x28, X86_DECODE_CMD_SUB, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x29, X86_DECODE_CMD_SUB, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x2a, X86_DECODE_CMD_SUB, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x2b, X86_DECODE_CMD_SUB, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x2c, X86_DECODE_CMD_SUB, 1, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x2d, X86_DECODE_CMD_SUB, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x2f, X86_DECODE_CMD_DAS, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x30, X86_DECODE_CMD_XOR, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x31, X86_DECODE_CMD_XOR, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x32, X86_DECODE_CMD_XOR, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x33, X86_DECODE_CMD_XOR, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x34, X86_DECODE_CMD_XOR, 1, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x35, X86_DECODE_CMD_XOR, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0x38, X86_DECODE_CMD_CMP, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x39, X86_DECODE_CMD_CMP, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x3a, X86_DECODE_CMD_CMP, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x3b, X86_DECODE_CMD_CMP, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x3c, X86_DECODE_CMD_CMP, 1, false, decode_rax, decode_imm8, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x3d, X86_DECODE_CMD_CMP, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0x3f, X86_DECODE_CMD_AAS, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0x40, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + {0x41, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + {0x42, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + {0x43, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + {0x44, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + {0x45, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + {0x46, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + {0x47, X86_DECODE_CMD_INC, 0, false, + NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, + + {0x48, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + {0x49, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + {0x4a, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + {0x4b, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + {0x4c, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + {0x4d, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + {0x4e, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + {0x4f, X86_DECODE_CMD_DEC, 0, false, + NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, + + {0x50, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + {0x51, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + {0x52, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + {0x53, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + {0x54, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + {0x55, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + {0x56, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + {0x57, X86_DECODE_CMD_PUSH, 0, false, + NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, + + {0x58, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + {0x59, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + {0x5a, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + {0x5b, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + {0x5c, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + {0x5d, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + {0x5e, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + {0x5f, X86_DECODE_CMD_POP, 0, false, + NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, + + {0x60, X86_DECODE_CMD_PUSHA, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x61, X86_DECODE_CMD_POPA, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0x68, X86_DECODE_CMD_PUSH, 0, false, decode_imm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x6a, X86_DECODE_CMD_PUSH, 0, false, decode_imm8_signed, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x69, X86_DECODE_CMD_IMUL_3, 0, true, decode_modrm_reg, + decode_modrm_rm, decode_imm, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x6b, X86_DECODE_CMD_IMUL_3, 0, true, decode_modrm_reg, decode_modrm_rm, + decode_imm8_signed, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0x6c, X86_DECODE_CMD_INS, 1, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x6d, X86_DECODE_CMD_INS, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x6e, X86_DECODE_CMD_OUTS, 1, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x6f, X86_DECODE_CMD_OUTS, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0x70, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x71, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x72, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x73, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x74, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x75, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x76, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x77, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x78, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x79, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x7a, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x7b, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x7c, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x7d, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x7e, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x7f, X86_DECODE_CMD_JXX, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + + {0x80, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, + NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, + {0x81, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm, + NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, + {0x82, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, + NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, + {0x83, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8_signed, + NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, + {0x84, X86_DECODE_CMD_TST, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x85, X86_DECODE_CMD_TST, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0x86, X86_DECODE_CMD_XCHG, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x87, X86_DECODE_CMD_XCHG, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x88, X86_DECODE_CMD_MOV, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x89, X86_DECODE_CMD_MOV, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x8a, X86_DECODE_CMD_MOV, 1, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x8b, X86_DECODE_CMD_MOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x8c, X86_DECODE_CMD_MOV_FROM_SEG, 0, true, decode_modrm_rm, + decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x8d, X86_DECODE_CMD_LEA, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x8e, X86_DECODE_CMD_MOV_TO_SEG, 0, true, decode_modrm_reg, + decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x8f, X86_DECODE_CMD_POP, 0, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0x90, X86_DECODE_CMD_NOP, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x91, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, + NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + {0x92, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, + NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + {0x93, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, + NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + {0x94, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, + NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + {0x95, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, + NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + {0x96, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, + NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + {0x97, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, + NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, + + {0x98, X86_DECODE_CMD_CBW, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x99, X86_DECODE_CMD_CWD, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0x9a, X86_DECODE_CMD_CALL_FAR, 0, false, NULL, + NULL, NULL, NULL, decode_farjmp, RFLAGS_MASK_NONE}, + + {0x9c, X86_DECODE_CMD_PUSHF, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + /*{0x9d, X86_DECODE_CMD_POPF, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_POPF},*/ + {0x9e, X86_DECODE_CMD_SAHF, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x9f, X86_DECODE_CMD_LAHF, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_LAHF}, + + {0xa0, X86_DECODE_CMD_MOV, 1, false, decode_rax, fetch_moffs, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xa1, X86_DECODE_CMD_MOV, 0, false, decode_rax, fetch_moffs, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xa2, X86_DECODE_CMD_MOV, 1, false, fetch_moffs, decode_rax, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xa3, X86_DECODE_CMD_MOV, 0, false, fetch_moffs, decode_rax, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xa4, X86_DECODE_CMD_MOVS, 1, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xa5, X86_DECODE_CMD_MOVS, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xa6, X86_DECODE_CMD_CMPS, 1, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xa7, X86_DECODE_CMD_CMPS, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xaa, X86_DECODE_CMD_STOS, 1, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xab, X86_DECODE_CMD_STOS, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xac, X86_DECODE_CMD_LODS, 1, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xad, X86_DECODE_CMD_LODS, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xae, X86_DECODE_CMD_SCAS, 1, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xaf, X86_DECODE_CMD_SCAS, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0xa8, X86_DECODE_CMD_TST, 1, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xa9, X86_DECODE_CMD_TST, 0, false, decode_rax, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0xb0, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + {0xb1, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + {0xb2, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + {0xb3, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + {0xb4, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + {0xb5, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + {0xb6, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + {0xb7, X86_DECODE_CMD_MOV, 1, false, NULL, + NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, + + {0xb8, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + {0xb9, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + {0xba, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + {0xbb, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + {0xbc, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + {0xbd, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + {0xbe, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + {0xbf, X86_DECODE_CMD_MOV, 0, false, NULL, + NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, + + {0xc0, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, + NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + {0xc1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8, + NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + + {0xc2, X86_DECODE_RET_NEAR, 0, false, decode_imm16, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xc3, X86_DECODE_RET_NEAR, 0, false, NULL, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xc4, X86_DECODE_CMD_LES, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xc5, X86_DECODE_CMD_LDS, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xc6, X86_DECODE_CMD_MOV, 1, true, decode_modrm_rm, decode_imm8, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xc7, X86_DECODE_CMD_MOV, 0, true, decode_modrm_rm, decode_imm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xc8, X86_DECODE_CMD_ENTER, 0, false, decode_imm16, decode_imm8, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xc9, X86_DECODE_CMD_LEAVE, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xca, X86_DECODE_RET_FAR, 0, false, decode_imm16, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xcb, X86_DECODE_RET_FAR, 0, false, decode_imm_0, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xcd, X86_DECODE_CMD_INT, 0, false, decode_imm8, NULL, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + /*{0xcf, X86_DECODE_CMD_IRET, 0, false, NULL, NULL, + NULL, NULL, NULL, RFLAGS_MASK_IRET},*/ + + {0xd0, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm_1, + NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + {0xd1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm_1, + NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + {0xd2, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_rcx, + NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + {0xd3, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_rcx, + NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, + + {0xd4, X86_DECODE_CMD_AAM, 0, false, decode_imm8, + NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xd5, X86_DECODE_CMD_AAD, 0, false, decode_imm8, + NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0xd7, X86_DECODE_CMD_XLAT, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xd8, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + {0xd9, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + {0xda, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + {0xdb, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + {0xdc, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + {0xdd, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + {0xde, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + {0xdf, X86_DECODE_CMD_INVL, 0, true, NULL, + NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, + + {0xe0, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xe1, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xe2, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xe3, X86_DECODE_CMD_JCXZ, 1, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + + {0xe4, X86_DECODE_CMD_IN, 1, false, decode_imm8, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xe5, X86_DECODE_CMD_IN, 0, false, decode_imm8, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xe6, X86_DECODE_CMD_OUT, 1, false, decode_imm8, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xe7, X86_DECODE_CMD_OUT, 0, false, decode_imm8, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xe8, X86_DECODE_CMD_CALL_NEAR, 0, false, decode_imm_signed, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xe9, X86_DECODE_CMD_JMP_NEAR, 0, false, decode_imm_signed, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xea, X86_DECODE_CMD_JMP_FAR, 0, false, + NULL, NULL, NULL, NULL, decode_farjmp, RFLAGS_MASK_NONE}, + {0xeb, X86_DECODE_CMD_JMP_NEAR, 1, false, decode_imm8_signed, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xec, X86_DECODE_CMD_IN, 1, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xed, X86_DECODE_CMD_IN, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xee, X86_DECODE_CMD_OUT, 1, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xef, X86_DECODE_CMD_OUT, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xf4, X86_DECODE_CMD_HLT, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xf5, X86_DECODE_CMD_CMC, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, + + {0xf6, X86_DECODE_CMD_INVL, 1, true, + NULL, NULL, NULL, NULL, decode_f7group, RFLAGS_MASK_OSZAPC}, + {0xf7, X86_DECODE_CMD_INVL, 0, true, + NULL, NULL, NULL, NULL, decode_f7group, RFLAGS_MASK_OSZAPC}, + + {0xf8, X86_DECODE_CMD_CLC, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, + {0xf9, X86_DECODE_CMD_STC, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, + + {0xfa, X86_DECODE_CMD_CLI, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IF}, + {0xfb, X86_DECODE_CMD_STI, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IF}, + {0xfc, X86_DECODE_CMD_CLD, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_DF}, + {0xfd, X86_DECODE_CMD_STD, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_DF}, + {0xfe, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, + NULL, NULL, NULL, decode_incgroup2, RFLAGS_MASK_OSZAPC}, + {0xff, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, + NULL, NULL, NULL, decode_ffgroup, RFLAGS_MASK_OSZAPC}, +}; + +struct decode_tbl _2op_inst[] = { + {0x0, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, + NULL, NULL, NULL, decode_sldtgroup, RFLAGS_MASK_NONE}, + {0x1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, + NULL, NULL, NULL, decode_lidtgroup, RFLAGS_MASK_NONE}, + {0x6, X86_DECODE_CMD_CLTS, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_TF}, + {0x9, X86_DECODE_CMD_WBINVD, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x18, X86_DECODE_CMD_PREFETCH, 0, true, + NULL, NULL, NULL, NULL, decode_x87_general, RFLAGS_MASK_NONE}, + {0x1f, X86_DECODE_CMD_NOP, 0, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x20, X86_DECODE_CMD_MOV_FROM_CR, 0, true, decode_modrm_rm, + decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x21, X86_DECODE_CMD_MOV_FROM_DR, 0, true, decode_modrm_rm, + decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x22, X86_DECODE_CMD_MOV_TO_CR, 0, true, decode_modrm_reg, + decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x23, X86_DECODE_CMD_MOV_TO_DR, 0, true, decode_modrm_reg, + decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x30, X86_DECODE_CMD_WRMSR, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x31, X86_DECODE_CMD_RDTSC, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x32, X86_DECODE_CMD_RDMSR, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x40, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x41, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x42, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x43, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x44, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x45, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x46, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x47, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x48, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x49, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x4a, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x4b, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x4c, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x4d, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x4e, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x4f, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x77, X86_DECODE_CMD_EMMS, 0, false, + NULL, NULL, NULL, NULL, decode_x87_general, RFLAGS_MASK_NONE}, + {0x82, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x83, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x84, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x85, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x86, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x87, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x88, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x89, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x8a, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x8b, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x8c, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x8d, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x8e, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x8f, X86_DECODE_CMD_JXX, 0, false, + NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, + {0x90, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x91, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x92, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x93, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x94, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x95, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x96, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x97, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x98, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x99, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x9a, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x9b, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x9c, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x9d, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x9e, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0x9f, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xb0, X86_DECODE_CMD_CMPXCHG, 1, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xb1, X86_DECODE_CMD_CMPXCHG, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xb6, X86_DECODE_CMD_MOVZX, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xb7, X86_DECODE_CMD_MOVZX, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xb8, X86_DECODE_CMD_POPCNT, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xbe, X86_DECODE_CMD_MOVSX, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xbf, X86_DECODE_CMD_MOVSX, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xa0, X86_DECODE_CMD_PUSH_SEG, 0, false, false, + NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + {0xa1, X86_DECODE_CMD_POP_SEG, 0, false, false, + NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + {0xa2, X86_DECODE_CMD_CPUID, 0, false, + NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xa3, X86_DECODE_CMD_BT, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_CF}, + {0xa4, X86_DECODE_CMD_SHLD, 0, true, decode_modrm_rm, decode_modrm_reg, + decode_imm8, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xa5, X86_DECODE_CMD_SHLD, 0, true, decode_modrm_rm, decode_modrm_reg, + decode_rcx, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xa8, X86_DECODE_CMD_PUSH_SEG, 0, false, false, + NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, + {0xa9, X86_DECODE_CMD_POP_SEG, 0, false, false, + NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, + {0xab, X86_DECODE_CMD_BTS, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_CF}, + {0xac, X86_DECODE_CMD_SHRD, 0, true, decode_modrm_rm, decode_modrm_reg, + decode_imm8, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xad, X86_DECODE_CMD_SHRD, 0, true, decode_modrm_rm, decode_modrm_reg, + decode_rcx, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0xae, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, + NULL, NULL, NULL, decode_aegroup, RFLAGS_MASK_NONE}, + + {0xaf, X86_DECODE_CMD_IMUL_2, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xb2, X86_DECODE_CMD_LSS, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_NONE}, + {0xb3, X86_DECODE_CMD_BTR, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xba, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8, + NULL, NULL, decode_btgroup, RFLAGS_MASK_OSZAPC}, + {0xbb, X86_DECODE_CMD_BTC, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xbc, X86_DECODE_CMD_BSF, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + {0xbd, X86_DECODE_CMD_BSR, 0, true, decode_modrm_reg, decode_modrm_rm, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0xc1, X86_DECODE_CMD_XADD, 0, true, decode_modrm_rm, decode_modrm_reg, + NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, + + {0xc7, X86_DECODE_CMD_CMPXCHG8B, 0, true, decode_modrm_rm, + NULL, NULL, NULL, NULL, RFLAGS_MASK_ZF}, + + {0xc8, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + {0xc9, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + {0xca, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + {0xcb, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + {0xcc, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + {0xcd, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + {0xce, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, + {0xcf, X86_DECODE_CMD_BSWAP, 0, false, + NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, +}; + +struct decode_x87_tbl invl_inst_x87 = {0x0, 0, 0, 0, 0, false, false, NULL, + NULL, decode_invalid, 0}; + +struct decode_x87_tbl _x87_inst[] = { + {0xd8, 0, 3, X86_DECODE_CMD_FADD, 10, false, false, + decode_x87_modrm_st0, decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xd8, 0, 0, X86_DECODE_CMD_FADD, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xd8, 1, 3, X86_DECODE_CMD_FMUL, 10, false, false, decode_x87_modrm_st0, + decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xd8, 1, 0, X86_DECODE_CMD_FMUL, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xd8, 4, 3, X86_DECODE_CMD_FSUB, 10, false, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xd8, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xd8, 5, 3, X86_DECODE_CMD_FSUB, 10, true, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xd8, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0, + decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xd8, 6, 3, X86_DECODE_CMD_FDIV, 10, false, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xd8, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xd8, 7, 3, X86_DECODE_CMD_FDIV, 10, true, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xd8, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0, + decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + + {0xd9, 0, 3, X86_DECODE_CMD_FLD, 10, false, false, + decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 0, 0, X86_DECODE_CMD_FLD, 4, false, false, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xd9, 1, 0, X86_DECODE_CMD_INVL, 10, false, false, + decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 2, 3, X86_DECODE_CMD_INVL, 10, false, false, + decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 2, 0, X86_DECODE_CMD_FST, 4, false, false, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 3, 3, X86_DECODE_CMD_INVL, 10, false, false, + decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 3, 0, X86_DECODE_CMD_FST, 4, false, true, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, + decode_x87_modrm_st0, NULL, decode_d9_4, RFLAGS_MASK_NONE}, + {0xd9, 4, 0, X86_DECODE_CMD_INVL, 4, false, false, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 5, 3, X86_DECODE_CMD_FLDxx, 10, false, false, NULL, NULL, NULL, + RFLAGS_MASK_NONE}, + {0xd9, 5, 0, X86_DECODE_CMD_FLDCW, 2, false, false, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xd9, 7, 3, X86_DECODE_CMD_FNSTCW, 2, false, false, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + {0xd9, 7, 0, X86_DECODE_CMD_FNSTCW, 2, false, false, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xda, 0, 3, X86_DECODE_CMD_FCMOV, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xda, 0, 0, X86_DECODE_CMD_FADD, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xda, 1, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, + decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xda, 1, 0, X86_DECODE_CMD_FMUL, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xda, 2, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xda, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xda, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, + RFLAGS_MASK_NONE}, + {0xda, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xda, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true, decode_x87_modrm_st0, + decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xda, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0, + decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xda, 6, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, + RFLAGS_MASK_NONE}, + {0xda, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0, + decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xda, 7, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, + RFLAGS_MASK_NONE}, + {0xda, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0, + decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + + {0xdb, 0, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, + decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdb, 0, 0, X86_DECODE_CMD_FLD, 4, false, false, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdb, 1, 3, X86_DECODE_CMD_FCMOV, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdb, 2, 3, X86_DECODE_CMD_FCMOV, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdb, 2, 0, X86_DECODE_CMD_FST, 4, false, false, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdb, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdb, 3, 0, X86_DECODE_CMD_FST, 4, false, true, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdb, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, + decode_db_4, RFLAGS_MASK_NONE}, + {0xdb, 4, 0, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, + RFLAGS_MASK_NONE}, + {0xdb, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdb, 5, 0, X86_DECODE_CMD_FLD, 10, false, false, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdb, 7, 0, X86_DECODE_CMD_FST, 10, false, true, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xdc, 0, 3, X86_DECODE_CMD_FADD, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdc, 0, 0, X86_DECODE_CMD_FADD, 8, false, false, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xdc, 1, 3, X86_DECODE_CMD_FMUL, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdc, 1, 0, X86_DECODE_CMD_FMUL, 8, false, false, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xdc, 4, 3, X86_DECODE_CMD_FSUB, 10, true, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdc, 4, 0, X86_DECODE_CMD_FSUB, 8, false, false, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xdc, 5, 3, X86_DECODE_CMD_FSUB, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdc, 5, 0, X86_DECODE_CMD_FSUB, 8, true, false, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xdc, 6, 3, X86_DECODE_CMD_FDIV, 10, true, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdc, 6, 0, X86_DECODE_CMD_FDIV, 8, false, false, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + {0xdc, 7, 3, X86_DECODE_CMD_FDIV, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdc, 7, 0, X86_DECODE_CMD_FDIV, 8, true, false, + decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, + + {0xdd, 0, 0, X86_DECODE_CMD_FLD, 8, false, false, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdd, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdd, 2, 3, X86_DECODE_CMD_FST, 10, false, false, + decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdd, 2, 0, X86_DECODE_CMD_FST, 8, false, false, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdd, 3, 3, X86_DECODE_CMD_FST, 10, false, true, + decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdd, 3, 0, X86_DECODE_CMD_FST, 8, false, true, + decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdd, 4, 3, X86_DECODE_CMD_FUCOM, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdd, 4, 0, X86_DECODE_CMD_FRSTOR, 8, false, false, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdd, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdd, 7, 0, X86_DECODE_CMD_FNSTSW, 0, false, false, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdd, 7, 3, X86_DECODE_CMD_FNSTSW, 0, false, false, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + + {0xde, 0, 3, X86_DECODE_CMD_FADD, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xde, 0, 0, X86_DECODE_CMD_FADD, 2, false, false, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xde, 1, 3, X86_DECODE_CMD_FMUL, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xde, 1, 0, X86_DECODE_CMD_FMUL, 2, false, false, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xde, 4, 3, X86_DECODE_CMD_FSUB, 10, true, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xde, 4, 0, X86_DECODE_CMD_FSUB, 2, false, false, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xde, 5, 3, X86_DECODE_CMD_FSUB, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xde, 5, 0, X86_DECODE_CMD_FSUB, 2, true, false, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xde, 6, 3, X86_DECODE_CMD_FDIV, 10, true, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xde, 6, 0, X86_DECODE_CMD_FDIV, 2, false, false, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + {0xde, 7, 3, X86_DECODE_CMD_FDIV, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xde, 7, 0, X86_DECODE_CMD_FDIV, 2, true, false, + decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, + + {0xdf, 0, 0, X86_DECODE_CMD_FLD, 2, false, false, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdf, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdf, 2, 3, X86_DECODE_CMD_FST, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdf, 2, 0, X86_DECODE_CMD_FST, 2, false, false, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdf, 3, 3, X86_DECODE_CMD_FST, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdf, 3, 0, X86_DECODE_CMD_FST, 2, false, true, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdf, 4, 3, X86_DECODE_CMD_FNSTSW, 2, false, true, + decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdf, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, true, + decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, + {0xdf, 5, 0, X86_DECODE_CMD_FLD, 8, false, false, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, + {0xdf, 7, 0, X86_DECODE_CMD_FST, 8, false, true, + decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, +}; + +void calc_modrm_operand16(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + target_ulong ptr = 0; + X86Seg seg = R_DS; + + if (!decode->modrm.mod && 6 == decode->modrm.rm) { + ptr = decode->displacement; + goto calc_addr; + } + + if (decode->displacement_size) { + ptr = sign(decode->displacement, decode->displacement_size); + } + + switch (decode->modrm.rm) { + case 0: + ptr += BX(env) + SI(env); + break; + case 1: + ptr += BX(env) + DI(env); + break; + case 2: + ptr += BP(env) + SI(env); + seg = R_SS; + break; + case 3: + ptr += BP(env) + DI(env); + seg = R_SS; + break; + case 4: + ptr += SI(env); + break; + case 5: + ptr += DI(env); + break; + case 6: + ptr += BP(env); + seg = R_SS; + break; + case 7: + ptr += BX(env); + break; + } +calc_addr: + if (X86_DECODE_CMD_LEA == decode->cmd) { + op->ptr = (uint16_t)ptr; + } else { + op->ptr = decode_linear_addr(env, decode, (uint16_t)ptr, seg); + } +} + +target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present, + int is_extended, int size) +{ + target_ulong ptr = 0; + + if (is_extended) { + reg |= R_R8; + } + + switch (size) { + case 1: + if (is_extended || reg < 4 || rex_present) { + ptr = (target_ulong)&RL(env, reg); + } else { + ptr = (target_ulong)&RH(env, reg - 4); + } + break; + default: + ptr = (target_ulong)&RRX(env, reg); + break; + } + return ptr; +} + +target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present, + int is_extended, int size) +{ + target_ulong val = 0; + memcpy(&val, + (void *)get_reg_ref(env, reg, rex_present, is_extended, size), + size); + return val; +} + +static target_ulong get_sib_val(CPUX86State *env, struct x86_decode *decode, + X86Seg *sel) +{ + target_ulong base = 0; + target_ulong scaled_index = 0; + int addr_size = decode->addressing_size; + int base_reg = decode->sib.base; + int index_reg = decode->sib.index; + + *sel = R_DS; + + if (decode->modrm.mod || base_reg != R_EBP) { + if (decode->rex.b) { + base_reg |= R_R8; + } + if (base_reg == R_ESP || base_reg == R_EBP) { + *sel = R_SS; + } + base = get_reg_val(env, decode->sib.base, decode->rex.rex, + decode->rex.b, addr_size); + } + + if (decode->rex.x) { + index_reg |= R_R8; + } + + if (index_reg != R_ESP) { + scaled_index = get_reg_val(env, index_reg, decode->rex.rex, + decode->rex.x, addr_size) << + decode->sib.scale; + } + return base + scaled_index; +} + +void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + X86Seg seg = R_DS; + target_ulong ptr = 0; + int addr_size = decode->addressing_size; + + if (decode->displacement_size) { + ptr = sign(decode->displacement, decode->displacement_size); + } + + if (4 == decode->modrm.rm) { + ptr += get_sib_val(env, decode, &seg); + } else if (!decode->modrm.mod && 5 == decode->modrm.rm) { + if (x86_is_long_mode(env_cpu(env))) { + ptr += env->eip + decode->len; + } else { + ptr = decode->displacement; + } + } else { + if (decode->modrm.rm == R_EBP || decode->modrm.rm == R_ESP) { + seg = R_SS; + } + ptr += get_reg_val(env, decode->modrm.rm, decode->rex.rex, + decode->rex.b, addr_size); + } + + if (X86_DECODE_CMD_LEA == decode->cmd) { + op->ptr = (uint32_t)ptr; + } else { + op->ptr = decode_linear_addr(env, decode, (uint32_t)ptr, seg); + } +} + +void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + X86Seg seg = R_DS; + int32_t offset = 0; + int mod = decode->modrm.mod; + int rm = decode->modrm.rm; + target_ulong ptr; + int src = decode->modrm.rm; + + if (decode->displacement_size) { + offset = sign(decode->displacement, decode->displacement_size); + } + + if (4 == rm) { + ptr = get_sib_val(env, decode, &seg) + offset; + } else if (0 == mod && 5 == rm) { + ptr = env->eip + decode->len + (int32_t) offset; + } else { + ptr = get_reg_val(env, src, decode->rex.rex, decode->rex.b, 8) + + (int64_t) offset; + } + + if (X86_DECODE_CMD_LEA == decode->cmd) { + op->ptr = ptr; + } else { + op->ptr = decode_linear_addr(env, decode, ptr, seg); + } +} + + +void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op) +{ + if (3 == decode->modrm.mod) { + op->reg = decode->modrm.reg; + op->type = X86_VAR_REG; + op->ptr = get_reg_ref(env, decode->modrm.rm, decode->rex.rex, + decode->rex.b, decode->operand_size); + return; + } + + switch (decode->addressing_size) { + case 2: + calc_modrm_operand16(env, decode, op); + break; + case 4: + calc_modrm_operand32(env, decode, op); + break; + case 8: + calc_modrm_operand64(env, decode, op); + break; + default: + VM_PANIC_EX("unsupported address size %d\n", decode->addressing_size); + break; + } +} + +static void decode_prefix(CPUX86State *env, struct x86_decode *decode) +{ + while (1) { + /* + * REX prefix must come after legacy prefixes. + * REX before legacy is ignored. + * Clear rex to simulate this. + */ + uint8_t byte = decode_byte(env, decode); + switch (byte) { + case PREFIX_LOCK: + decode->lock = byte; + decode->rex.rex = 0; + break; + case PREFIX_REPN: + case PREFIX_REP: + decode->rep = byte; + decode->rex.rex = 0; + break; + case PREFIX_CS_SEG_OVERRIDE: + case PREFIX_SS_SEG_OVERRIDE: + case PREFIX_DS_SEG_OVERRIDE: + case PREFIX_ES_SEG_OVERRIDE: + case PREFIX_FS_SEG_OVERRIDE: + case PREFIX_GS_SEG_OVERRIDE: + decode->segment_override = byte; + decode->rex.rex = 0; + break; + case PREFIX_OP_SIZE_OVERRIDE: + decode->op_size_override = byte; + decode->rex.rex = 0; + break; + case PREFIX_ADDR_SIZE_OVERRIDE: + decode->addr_size_override = byte; + decode->rex.rex = 0; + break; + case PREFIX_REX ... (PREFIX_REX + 0xf): + if (x86_is_long_mode(env_cpu(env))) { + decode->rex.rex = byte; + break; + } + /* fall through when not in long mode */ + default: + decode->len--; + return; + } + } +} + +void set_addressing_size(CPUX86State *env, struct x86_decode *decode) +{ + decode->addressing_size = -1; + if (x86_is_real(env_cpu(env)) || x86_is_v8086(env_cpu(env))) { + if (decode->addr_size_override) { + decode->addressing_size = 4; + } else { + decode->addressing_size = 2; + } + } else if (!x86_is_long_mode(env_cpu(env))) { + /* protected */ + x86_segment_descriptor cs; + emul_ops->read_segment_descriptor(env_cpu(env), &cs, R_CS); + /* check db */ + if (cs.db) { + if (decode->addr_size_override) { + decode->addressing_size = 2; + } else { + decode->addressing_size = 4; + } + } else { + if (decode->addr_size_override) { + decode->addressing_size = 4; + } else { + decode->addressing_size = 2; + } + } + } else { + /* long */ + if (decode->addr_size_override) { + decode->addressing_size = 4; + } else { + decode->addressing_size = 8; + } + } +} + +void set_operand_size(CPUX86State *env, struct x86_decode *decode) +{ + decode->operand_size = -1; + if (x86_is_real(env_cpu(env)) || x86_is_v8086(env_cpu(env))) { + if (decode->op_size_override) { + decode->operand_size = 4; + } else { + decode->operand_size = 2; + } + } else if (!x86_is_long_mode(env_cpu(env))) { + /* protected */ + x86_segment_descriptor cs; + emul_ops->read_segment_descriptor(env_cpu(env), &cs, R_CS); + /* check db */ + if (cs.db) { + if (decode->op_size_override) { + decode->operand_size = 2; + } else{ + decode->operand_size = 4; + } + } else { + if (decode->op_size_override) { + decode->operand_size = 4; + } else { + decode->operand_size = 2; + } + } + } else { + /* long */ + if (decode->op_size_override) { + decode->operand_size = 2; + } else { + decode->operand_size = 4; + } + + if (decode->rex.w) { + decode->operand_size = 8; + } + } +} + +static void decode_sib(CPUX86State *env, struct x86_decode *decode) +{ + if ((decode->modrm.mod != 3) && (4 == decode->modrm.rm) && + (decode->addressing_size != 2)) { + decode->sib.sib = decode_byte(env, decode); + decode->sib_present = true; + } +} + +/* 16 bit modrm */ +int disp16_tbl[4][8] = { + {0, 0, 0, 0, 0, 0, 2, 0}, + {1, 1, 1, 1, 1, 1, 1, 1}, + {2, 2, 2, 2, 2, 2, 2, 2}, + {0, 0, 0, 0, 0, 0, 0, 0} +}; + +/* 32/64-bit modrm */ +int disp32_tbl[4][8] = { + {0, 0, 0, 0, -1, 4, 0, 0}, + {1, 1, 1, 1, 1, 1, 1, 1}, + {4, 4, 4, 4, 4, 4, 4, 4}, + {0, 0, 0, 0, 0, 0, 0, 0} +}; + +static inline void decode_displacement(CPUX86State *env, struct x86_decode *decode) +{ + int addressing_size = decode->addressing_size; + int mod = decode->modrm.mod; + int rm = decode->modrm.rm; + + decode->displacement_size = 0; + switch (addressing_size) { + case 2: + decode->displacement_size = disp16_tbl[mod][rm]; + if (decode->displacement_size) { + decode->displacement = (uint16_t)decode_bytes(env, decode, + decode->displacement_size); + } + break; + case 4: + case 8: + if (-1 == disp32_tbl[mod][rm]) { + if (5 == decode->sib.base) { + decode->displacement_size = 4; + } + } else { + decode->displacement_size = disp32_tbl[mod][rm]; + } + + if (decode->displacement_size) { + decode->displacement = (uint32_t)decode_bytes(env, decode, + decode->displacement_size); + } + break; + } +} + +static inline void decode_modrm(CPUX86State *env, struct x86_decode *decode) +{ + decode->modrm.modrm = decode_byte(env, decode); + decode->is_modrm = true; + + decode_sib(env, decode); + decode_displacement(env, decode); +} + +static inline void decode_opcode_general(CPUX86State *env, + struct x86_decode *decode, + uint8_t opcode, + struct decode_tbl *inst_decoder) +{ + decode->cmd = inst_decoder->cmd; + if (inst_decoder->operand_size) { + decode->operand_size = inst_decoder->operand_size; + } + decode->flags_mask = inst_decoder->flags_mask; + + if (inst_decoder->is_modrm) { + decode_modrm(env, decode); + } + if (inst_decoder->decode_op1) { + inst_decoder->decode_op1(env, decode, &decode->op[0]); + } + if (inst_decoder->decode_op2) { + inst_decoder->decode_op2(env, decode, &decode->op[1]); + } + if (inst_decoder->decode_op3) { + inst_decoder->decode_op3(env, decode, &decode->op[2]); + } + if (inst_decoder->decode_op4) { + inst_decoder->decode_op4(env, decode, &decode->op[3]); + } + if (inst_decoder->decode_postfix) { + inst_decoder->decode_postfix(env, decode); + } +} + +static inline void decode_opcode_1(CPUX86State *env, struct x86_decode *decode, + uint8_t opcode) +{ + struct decode_tbl *inst_decoder = &_decode_tbl1[opcode]; + decode_opcode_general(env, decode, opcode, inst_decoder); +} + + +static inline void decode_opcode_2(CPUX86State *env, struct x86_decode *decode, + uint8_t opcode) +{ + struct decode_tbl *inst_decoder = &_decode_tbl2[opcode]; + decode_opcode_general(env, decode, opcode, inst_decoder); +} + +static void decode_opcodes(CPUX86State *env, struct x86_decode *decode) +{ + uint8_t opcode; + + opcode = decode_byte(env, decode); + decode->opcode[decode->opcode_len++] = opcode; + if (opcode != OPCODE_ESCAPE) { + decode_opcode_1(env, decode, opcode); + } else { + opcode = decode_byte(env, decode); + decode->opcode[decode->opcode_len++] = opcode; + decode_opcode_2(env, decode, opcode); + } +} + +uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode) +{ + memset(decode, 0, sizeof(*decode)); + decode_prefix(env, decode); + set_addressing_size(env, decode); + set_operand_size(env, decode); + + decode_opcodes(env, decode); + + return decode->len; +} + +void init_decoder(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(_decode_tbl1); i++) { + memcpy(&_decode_tbl1[i], &invl_inst, sizeof(invl_inst)); + } + for (i = 0; i < ARRAY_SIZE(_decode_tbl2); i++) { + memcpy(&_decode_tbl2[i], &invl_inst, sizeof(invl_inst)); + } + for (i = 0; i < ARRAY_SIZE(_decode_tbl3); i++) { + memcpy(&_decode_tbl3[i], &invl_inst_x87, sizeof(invl_inst_x87)); + + } + for (i = 0; i < ARRAY_SIZE(_1op_inst); i++) { + _decode_tbl1[_1op_inst[i].opcode] = _1op_inst[i]; + } + for (i = 0; i < ARRAY_SIZE(_2op_inst); i++) { + _decode_tbl2[_2op_inst[i].opcode] = _2op_inst[i]; + } + for (i = 0; i < ARRAY_SIZE(_x87_inst); i++) { + int index = ((_x87_inst[i].opcode & 0xf) << 4) | + ((_x87_inst[i].modrm_mod & 1) << 3) | + _x87_inst[i].modrm_reg; + _decode_tbl3[index] = _x87_inst[i]; + } +} + + +const char *decode_cmd_to_string(enum x86_decode_cmd cmd) +{ + static const char *cmds[] = {"INVL", "PUSH", "PUSH_SEG", "POP", "POP_SEG", + "MOV", "MOVSX", "MOVZX", "CALL_NEAR", "CALL_NEAR_ABS_INDIRECT", + "CALL_FAR_ABS_INDIRECT", "CMD_CALL_FAR", "RET_NEAR", "RET_FAR", "ADD", + "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP", "INC", "DEC", "TST", + "NOT", "NEG", "JMP_NEAR", "JMP_NEAR_ABS_INDIRECT", "JMP_FAR", + "JMP_FAR_ABS_INDIRECT", "LEA", "JXX", "JCXZ", "SETXX", "MOV_TO_SEG", + "MOV_FROM_SEG", "CLI", "STI", "CLD", "STD", "STC", "CLC", "OUT", "IN", + "INS", "OUTS", "LIDT", "SIDT", "LGDT", "SGDT", "SMSW", "LMSW", + "RDTSCP", "INVLPG", "MOV_TO_CR", "MOV_FROM_CR", "MOV_TO_DR", + "MOV_FROM_DR", "PUSHF", "POPF", "CPUID", "ROL", "ROR", "RCL", "RCR", + "SHL", "SAL", "SHR", "SHRD", "SHLD", "SAR", "DIV", "IDIV", "MUL", + "IMUL_3", "IMUL_2", "IMUL_1", "MOVS", "CMPS", "SCAS", "LODS", "STOS", + "BSWAP", "XCHG", "RDTSC", "RDMSR", "WRMSR", "ENTER", "LEAVE", "BT", + "BTS", "BTC", "BTR", "BSF", "BSR", "IRET", "INT", "POPA", "PUSHA", + "CWD", "CBW", "DAS", "AAD", "AAM", "AAS", "LOOP", "SLDT", "STR", "LLDT", + "LTR", "VERR", "VERW", "SAHF", "LAHF", "WBINVD", "LDS", "LSS", "LES", + "LGS", "LFS", "CMC", "XLAT", "NOP", "CMOV", "CLTS", "XADD", "HLT", + "CMPXCHG8B", "CMPXCHG", "POPCNT", "FNINIT", "FLD", "FLDxx", "FNSTCW", + "FNSTSW", "FNSETPM", "FSAVE", "FRSTOR", "FXSAVE", "FXRSTOR", "FDIV", + "FMUL", "FSUB", "FADD", "EMMS", "MFENCE", "SFENCE", "LFENCE", + "PREFETCH", "FST", "FABS", "FUCOM", "FUCOMI", "FLDCW", + "FXCH", "FCHS", "FCMOV", "FRNDINT", "FXAM", "LAST"}; + return cmds[cmd]; +} + +target_ulong decode_linear_addr(CPUX86State *env, struct x86_decode *decode, + target_ulong addr, X86Seg seg) +{ + switch (decode->segment_override) { + case PREFIX_CS_SEG_OVERRIDE: + seg = R_CS; + break; + case PREFIX_SS_SEG_OVERRIDE: + seg = R_SS; + break; + case PREFIX_DS_SEG_OVERRIDE: + seg = R_DS; + break; + case PREFIX_ES_SEG_OVERRIDE: + seg = R_ES; + break; + case PREFIX_FS_SEG_OVERRIDE: + seg = R_FS; + break; + case PREFIX_GS_SEG_OVERRIDE: + seg = R_GS; + break; + default: + break; + } + return linear_addr_size(env_cpu(env), addr, decode->addressing_size, seg); +} diff --git a/target/i386/emulate/x86_decode.h b/target/i386/emulate/x86_decode.h new file mode 100644 index 0000000000..930d965164 --- /dev/null +++ b/target/i386/emulate/x86_decode.h @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2016 Veertu Inc, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef X86_EMU_DECODE_H +#define X86_EMU_DECODE_H + +#include "cpu.h" +#include "x86.h" + +typedef enum x86_prefix { + /* group 1 */ + PREFIX_LOCK = 0xf0, + PREFIX_REPN = 0xf2, + PREFIX_REP = 0xf3, + /* group 2 */ + PREFIX_CS_SEG_OVERRIDE = 0x2e, + PREFIX_SS_SEG_OVERRIDE = 0x36, + PREFIX_DS_SEG_OVERRIDE = 0x3e, + PREFIX_ES_SEG_OVERRIDE = 0x26, + PREFIX_FS_SEG_OVERRIDE = 0x64, + PREFIX_GS_SEG_OVERRIDE = 0x65, + /* group 3 */ + PREFIX_OP_SIZE_OVERRIDE = 0x66, + /* group 4 */ + PREFIX_ADDR_SIZE_OVERRIDE = 0x67, + + PREFIX_REX = 0x40, +} x86_prefix; + +enum x86_decode_cmd { + X86_DECODE_CMD_INVL = 0, + + X86_DECODE_CMD_PUSH, + X86_DECODE_CMD_PUSH_SEG, + X86_DECODE_CMD_POP, + X86_DECODE_CMD_POP_SEG, + X86_DECODE_CMD_MOV, + X86_DECODE_CMD_MOVSX, + X86_DECODE_CMD_MOVZX, + X86_DECODE_CMD_CALL_NEAR, + X86_DECODE_CMD_CALL_NEAR_ABS_INDIRECT, + X86_DECODE_CMD_CALL_FAR_ABS_INDIRECT, + X86_DECODE_CMD_CALL_FAR, + X86_DECODE_RET_NEAR, + X86_DECODE_RET_FAR, + X86_DECODE_CMD_ADD, + X86_DECODE_CMD_OR, + X86_DECODE_CMD_ADC, + X86_DECODE_CMD_SBB, + X86_DECODE_CMD_AND, + X86_DECODE_CMD_SUB, + X86_DECODE_CMD_XOR, + X86_DECODE_CMD_CMP, + X86_DECODE_CMD_INC, + X86_DECODE_CMD_DEC, + X86_DECODE_CMD_TST, + X86_DECODE_CMD_NOT, + X86_DECODE_CMD_NEG, + X86_DECODE_CMD_JMP_NEAR, + X86_DECODE_CMD_JMP_NEAR_ABS_INDIRECT, + X86_DECODE_CMD_JMP_FAR, + X86_DECODE_CMD_JMP_FAR_ABS_INDIRECT, + X86_DECODE_CMD_LEA, + X86_DECODE_CMD_JXX, + X86_DECODE_CMD_JCXZ, + X86_DECODE_CMD_SETXX, + X86_DECODE_CMD_MOV_TO_SEG, + X86_DECODE_CMD_MOV_FROM_SEG, + X86_DECODE_CMD_CLI, + X86_DECODE_CMD_STI, + X86_DECODE_CMD_CLD, + X86_DECODE_CMD_STD, + X86_DECODE_CMD_STC, + X86_DECODE_CMD_CLC, + X86_DECODE_CMD_OUT, + X86_DECODE_CMD_IN, + X86_DECODE_CMD_INS, + X86_DECODE_CMD_OUTS, + X86_DECODE_CMD_LIDT, + X86_DECODE_CMD_SIDT, + X86_DECODE_CMD_LGDT, + X86_DECODE_CMD_SGDT, + X86_DECODE_CMD_SMSW, + X86_DECODE_CMD_LMSW, + X86_DECODE_CMD_RDTSCP, + X86_DECODE_CMD_INVLPG, + X86_DECODE_CMD_MOV_TO_CR, + X86_DECODE_CMD_MOV_FROM_CR, + X86_DECODE_CMD_MOV_TO_DR, + X86_DECODE_CMD_MOV_FROM_DR, + X86_DECODE_CMD_PUSHF, + X86_DECODE_CMD_POPF, + X86_DECODE_CMD_CPUID, + X86_DECODE_CMD_ROL, + X86_DECODE_CMD_ROR, + X86_DECODE_CMD_RCL, + X86_DECODE_CMD_RCR, + X86_DECODE_CMD_SHL, + X86_DECODE_CMD_SAL, + X86_DECODE_CMD_SHR, + X86_DECODE_CMD_SHRD, + X86_DECODE_CMD_SHLD, + X86_DECODE_CMD_SAR, + X86_DECODE_CMD_DIV, + X86_DECODE_CMD_IDIV, + X86_DECODE_CMD_MUL, + X86_DECODE_CMD_IMUL_3, + X86_DECODE_CMD_IMUL_2, + X86_DECODE_CMD_IMUL_1, + X86_DECODE_CMD_MOVS, + X86_DECODE_CMD_CMPS, + X86_DECODE_CMD_SCAS, + X86_DECODE_CMD_LODS, + X86_DECODE_CMD_STOS, + X86_DECODE_CMD_BSWAP, + X86_DECODE_CMD_XCHG, + X86_DECODE_CMD_RDTSC, + X86_DECODE_CMD_RDMSR, + X86_DECODE_CMD_WRMSR, + X86_DECODE_CMD_ENTER, + X86_DECODE_CMD_LEAVE, + X86_DECODE_CMD_BT, + X86_DECODE_CMD_BTS, + X86_DECODE_CMD_BTC, + X86_DECODE_CMD_BTR, + X86_DECODE_CMD_BSF, + X86_DECODE_CMD_BSR, + X86_DECODE_CMD_IRET, + X86_DECODE_CMD_INT, + X86_DECODE_CMD_POPA, + X86_DECODE_CMD_PUSHA, + X86_DECODE_CMD_CWD, + X86_DECODE_CMD_CBW, + X86_DECODE_CMD_DAS, + X86_DECODE_CMD_AAD, + X86_DECODE_CMD_AAM, + X86_DECODE_CMD_AAS, + X86_DECODE_CMD_LOOP, + X86_DECODE_CMD_SLDT, + X86_DECODE_CMD_STR, + X86_DECODE_CMD_LLDT, + X86_DECODE_CMD_LTR, + X86_DECODE_CMD_VERR, + X86_DECODE_CMD_VERW, + X86_DECODE_CMD_SAHF, + X86_DECODE_CMD_LAHF, + X86_DECODE_CMD_WBINVD, + X86_DECODE_CMD_LDS, + X86_DECODE_CMD_LSS, + X86_DECODE_CMD_LES, + X86_DECODE_XMD_LGS, + X86_DECODE_CMD_LFS, + X86_DECODE_CMD_CMC, + X86_DECODE_CMD_XLAT, + X86_DECODE_CMD_NOP, + X86_DECODE_CMD_CMOV, + X86_DECODE_CMD_CLTS, + X86_DECODE_CMD_XADD, + X86_DECODE_CMD_HLT, + X86_DECODE_CMD_CMPXCHG8B, + X86_DECODE_CMD_CMPXCHG, + X86_DECODE_CMD_POPCNT, + + X86_DECODE_CMD_FNINIT, + X86_DECODE_CMD_FLD, + X86_DECODE_CMD_FLDxx, + X86_DECODE_CMD_FNSTCW, + X86_DECODE_CMD_FNSTSW, + X86_DECODE_CMD_FNSETPM, + X86_DECODE_CMD_FSAVE, + X86_DECODE_CMD_FRSTOR, + X86_DECODE_CMD_FXSAVE, + X86_DECODE_CMD_FXRSTOR, + X86_DECODE_CMD_FDIV, + X86_DECODE_CMD_FMUL, + X86_DECODE_CMD_FSUB, + X86_DECODE_CMD_FADD, + X86_DECODE_CMD_EMMS, + X86_DECODE_CMD_MFENCE, + X86_DECODE_CMD_SFENCE, + X86_DECODE_CMD_LFENCE, + X86_DECODE_CMD_PREFETCH, + X86_DECODE_CMD_CLFLUSH, + X86_DECODE_CMD_FST, + X86_DECODE_CMD_FABS, + X86_DECODE_CMD_FUCOM, + X86_DECODE_CMD_FUCOMI, + X86_DECODE_CMD_FLDCW, + X86_DECODE_CMD_FXCH, + X86_DECODE_CMD_FCHS, + X86_DECODE_CMD_FCMOV, + X86_DECODE_CMD_FRNDINT, + X86_DECODE_CMD_FXAM, + + X86_DECODE_CMD_LAST, +}; + +const char *decode_cmd_to_string(enum x86_decode_cmd cmd); + +typedef struct x86_modrm { + union { + uint8_t modrm; + struct { + uint8_t rm:3; + uint8_t reg:3; + uint8_t mod:2; + }; + }; +} __attribute__ ((__packed__)) x86_modrm; + +typedef struct x86_sib { + union { + uint8_t sib; + struct { + uint8_t base:3; + uint8_t index:3; + uint8_t scale:2; + }; + }; +} __attribute__ ((__packed__)) x86_sib; + +typedef struct x86_rex { + union { + uint8_t rex; + struct { + uint8_t b:1; + uint8_t x:1; + uint8_t r:1; + uint8_t w:1; + uint8_t unused:4; + }; + }; +} __attribute__ ((__packed__)) x86_rex; + +typedef enum x86_var_type { + X86_VAR_IMMEDIATE, + X86_VAR_OFFSET, + X86_VAR_REG, + X86_VAR_RM, + + /* for floating point computations */ + X87_VAR_REG, + X87_VAR_FLOATP, + X87_VAR_INTP, + X87_VAR_BYTEP, +} x86_var_type; + +typedef struct x86_decode_op { + enum x86_var_type type; + int size; + + int reg; + target_ulong val; + + target_ulong ptr; +} x86_decode_op; + +typedef struct x86_decode { + int len; + uint8_t opcode[4]; + uint8_t opcode_len; + enum x86_decode_cmd cmd; + int addressing_size; + int operand_size; + int lock; + int rep; + int op_size_override; + int addr_size_override; + int segment_override; + int control_change_inst; + bool fwait; + bool fpop_stack; + bool frev; + + uint32_t displacement; + uint8_t displacement_size; + struct x86_rex rex; + bool is_modrm; + bool sib_present; + struct x86_sib sib; + struct x86_modrm modrm; + struct x86_decode_op op[4]; + bool is_fpu; + uint32_t flags_mask; + +} x86_decode; + +uint64_t sign(uint64_t val, int size); + +uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode); + +target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present, + int is_extended, int size); +target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present, + int is_extended, int size); +void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op); +target_ulong decode_linear_addr(CPUX86State *env, struct x86_decode *decode, + target_ulong addr, enum X86Seg seg); + +void init_decoder(void); +void calc_modrm_operand16(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op); +void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op); +void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode, + struct x86_decode_op *op); +void set_addressing_size(CPUX86State *env, struct x86_decode *decode); +void set_operand_size(CPUX86State *env, struct x86_decode *decode); + +#endif diff --git a/target/i386/emulate/x86_emu.c b/target/i386/emulate/x86_emu.c new file mode 100644 index 0000000000..26a4876aac --- /dev/null +++ b/target/i386/emulate/x86_emu.c @@ -0,0 +1,1259 @@ +/* + * Copyright (C) 2016 Veertu Inc, + * Copyright (C) 2017 Google Inc, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001-2012 The Bochs Project +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA +///////////////////////////////////////////////////////////////////////// + +#include "qemu/osdep.h" +#include "panic.h" +#include "x86_decode.h" +#include "x86.h" +#include "x86_emu.h" +#include "x86_flags.h" + +#define EXEC_2OP_FLAGS_CMD(env, decode, cmd, FLAGS_FUNC, save_res) \ +{ \ + fetch_operands(env, decode, 2, true, true, false); \ + switch (decode->operand_size) { \ + case 1: \ + { \ + uint8_t v1 = (uint8_t)decode->op[0].val; \ + uint8_t v2 = (uint8_t)decode->op[1].val; \ + uint8_t diff = v1 cmd v2; \ + if (save_res) { \ + write_val_ext(env, decode->op[0].ptr, diff, 1); \ + } \ + FLAGS_FUNC##8(env, v1, v2, diff); \ + break; \ + } \ + case 2: \ + { \ + uint16_t v1 = (uint16_t)decode->op[0].val; \ + uint16_t v2 = (uint16_t)decode->op[1].val; \ + uint16_t diff = v1 cmd v2; \ + if (save_res) { \ + write_val_ext(env, decode->op[0].ptr, diff, 2); \ + } \ + FLAGS_FUNC##16(env, v1, v2, diff); \ + break; \ + } \ + case 4: \ + { \ + uint32_t v1 = (uint32_t)decode->op[0].val; \ + uint32_t v2 = (uint32_t)decode->op[1].val; \ + uint32_t diff = v1 cmd v2; \ + if (save_res) { \ + write_val_ext(env, decode->op[0].ptr, diff, 4); \ + } \ + FLAGS_FUNC##32(env, v1, v2, diff); \ + break; \ + } \ + default: \ + VM_PANIC("bad size\n"); \ + } \ +} \ + +target_ulong read_reg(CPUX86State *env, int reg, int size) +{ + switch (size) { + case 1: + return x86_reg(env, reg)->lx; + case 2: + return x86_reg(env, reg)->rx; + case 4: + return x86_reg(env, reg)->erx; + case 8: + return x86_reg(env, reg)->rrx; + default: + abort(); + } + return 0; +} + +void write_reg(CPUX86State *env, int reg, target_ulong val, int size) +{ + switch (size) { + case 1: + x86_reg(env, reg)->lx = val; + break; + case 2: + x86_reg(env, reg)->rx = val; + break; + case 4: + x86_reg(env, reg)->rrx = (uint32_t)val; + break; + case 8: + x86_reg(env, reg)->rrx = val; + break; + default: + abort(); + } +} + +target_ulong read_val_from_reg(target_ulong reg_ptr, int size) +{ + target_ulong val; + + switch (size) { + case 1: + val = *(uint8_t *)reg_ptr; + break; + case 2: + val = *(uint16_t *)reg_ptr; + break; + case 4: + val = *(uint32_t *)reg_ptr; + break; + case 8: + val = *(uint64_t *)reg_ptr; + break; + default: + abort(); + } + return val; +} + +void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size) +{ + switch (size) { + case 1: + *(uint8_t *)reg_ptr = val; + break; + case 2: + *(uint16_t *)reg_ptr = val; + break; + case 4: + *(uint64_t *)reg_ptr = (uint32_t)val; + break; + case 8: + *(uint64_t *)reg_ptr = val; + break; + default: + abort(); + } +} + +static bool is_host_reg(CPUX86State *env, target_ulong ptr) +{ + return (ptr - (target_ulong)&env->regs[0]) < sizeof(env->regs); +} + +void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size) +{ + if (is_host_reg(env, ptr)) { + write_val_to_reg(ptr, val, size); + return; + } + emul_ops->write_mem(env_cpu(env), &val, ptr, size); +} + +uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes) +{ + emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes); + return env->emu_mmio_buf; +} + + +target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size) +{ + target_ulong val; + uint8_t *mmio_ptr; + + if (is_host_reg(env, ptr)) { + return read_val_from_reg(ptr, size); + } + + mmio_ptr = read_mmio(env, ptr, size); + switch (size) { + case 1: + val = *(uint8_t *)mmio_ptr; + break; + case 2: + val = *(uint16_t *)mmio_ptr; + break; + case 4: + val = *(uint32_t *)mmio_ptr; + break; + case 8: + val = *(uint64_t *)mmio_ptr; + break; + default: + VM_PANIC("bad size\n"); + break; + } + return val; +} + +static void fetch_operands(CPUX86State *env, struct x86_decode *decode, + int n, bool val_op0, bool val_op1, bool val_op2) +{ + int i; + bool calc_val[3] = {val_op0, val_op1, val_op2}; + + for (i = 0; i < n; i++) { + switch (decode->op[i].type) { + case X86_VAR_IMMEDIATE: + break; + case X86_VAR_REG: + VM_PANIC_ON(!decode->op[i].ptr); + if (calc_val[i]) { + decode->op[i].val = read_val_from_reg(decode->op[i].ptr, + decode->operand_size); + } + break; + case X86_VAR_RM: + calc_modrm_operand(env, decode, &decode->op[i]); + if (calc_val[i]) { + decode->op[i].val = read_val_ext(env, decode->op[i].ptr, + decode->operand_size); + } + break; + case X86_VAR_OFFSET: + decode->op[i].ptr = decode_linear_addr(env, decode, + decode->op[i].ptr, + R_DS); + if (calc_val[i]) { + decode->op[i].val = read_val_ext(env, decode->op[i].ptr, + decode->operand_size); + } + break; + default: + break; + } + } +} + +static void exec_mov(CPUX86State *env, struct x86_decode *decode) +{ + fetch_operands(env, decode, 2, false, true, false); + write_val_ext(env, decode->op[0].ptr, decode->op[1].val, + decode->operand_size); + + env->eip += decode->len; +} + +static void exec_add(CPUX86State *env, struct x86_decode *decode) +{ + EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true); + env->eip += decode->len; +} + +static void exec_or(CPUX86State *env, struct x86_decode *decode) +{ + EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true); + env->eip += decode->len; +} + +static void exec_adc(CPUX86State *env, struct x86_decode *decode) +{ + EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true); + env->eip += decode->len; +} + +static void exec_sbb(CPUX86State *env, struct x86_decode *decode) +{ + EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true); + env->eip += decode->len; +} + +static void exec_and(CPUX86State *env, struct x86_decode *decode) +{ + EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true); + env->eip += decode->len; +} + +static void exec_sub(CPUX86State *env, struct x86_decode *decode) +{ + EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true); + env->eip += decode->len; +} + +static void exec_xor(CPUX86State *env, struct x86_decode *decode) +{ + EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true); + env->eip += decode->len; +} + +static void exec_neg(CPUX86State *env, struct x86_decode *decode) +{ + /*EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);*/ + int32_t val; + fetch_operands(env, decode, 2, true, true, false); + + val = 0 - sign(decode->op[1].val, decode->operand_size); + write_val_ext(env, decode->op[1].ptr, val, decode->operand_size); + + if (4 == decode->operand_size) { + SET_FLAGS_OSZAPC_SUB32(env, 0, 0 - val, val); + } else if (2 == decode->operand_size) { + SET_FLAGS_OSZAPC_SUB16(env, 0, 0 - val, val); + } else if (1 == decode->operand_size) { + SET_FLAGS_OSZAPC_SUB8(env, 0, 0 - val, val); + } else { + VM_PANIC("bad op size\n"); + } + + /*lflags_to_rflags(env);*/ + env->eip += decode->len; +} + +static void exec_cmp(CPUX86State *env, struct x86_decode *decode) +{ + EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); + env->eip += decode->len; +} + +static void exec_inc(CPUX86State *env, struct x86_decode *decode) +{ + decode->op[1].type = X86_VAR_IMMEDIATE; + decode->op[1].val = 0; + + EXEC_2OP_FLAGS_CMD(env, decode, +1+, SET_FLAGS_OSZAP_ADD, true); + + env->eip += decode->len; +} + +static void exec_dec(CPUX86State *env, struct x86_decode *decode) +{ + decode->op[1].type = X86_VAR_IMMEDIATE; + decode->op[1].val = 0; + + EXEC_2OP_FLAGS_CMD(env, decode, -1-, SET_FLAGS_OSZAP_SUB, true); + env->eip += decode->len; +} + +static void exec_tst(CPUX86State *env, struct x86_decode *decode) +{ + EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false); + env->eip += decode->len; +} + +static void exec_not(CPUX86State *env, struct x86_decode *decode) +{ + fetch_operands(env, decode, 1, true, false, false); + + write_val_ext(env, decode->op[0].ptr, ~decode->op[0].val, + decode->operand_size); + env->eip += decode->len; +} + +void exec_movzx(CPUX86State *env, struct x86_decode *decode) +{ + int src_op_size; + int op_size = decode->operand_size; + + fetch_operands(env, decode, 1, false, false, false); + + if (0xb6 == decode->opcode[1]) { + src_op_size = 1; + } else { + src_op_size = 2; + } + decode->operand_size = src_op_size; + calc_modrm_operand(env, decode, &decode->op[1]); + decode->op[1].val = read_val_ext(env, decode->op[1].ptr, src_op_size); + write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size); + + env->eip += decode->len; +} + +static void exec_out(CPUX86State *env, struct x86_decode *decode) +{ + switch (decode->opcode[0]) { + case 0xe6: + emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1); + break; + case 0xe7: + emul_ops->handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1, + decode->operand_size, 1); + break; + case 0xee: + emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1); + break; + case 0xef: + emul_ops->handle_io(env_cpu(env), DX(env), &RAX(env), 1, + decode->operand_size, 1); + break; + default: + VM_PANIC("Bad out opcode\n"); + break; + } + env->eip += decode->len; +} + +static void exec_in(CPUX86State *env, struct x86_decode *decode) +{ + target_ulong val = 0; + switch (decode->opcode[0]) { + case 0xe4: + emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1); + break; + case 0xe5: + emul_ops->handle_io(env_cpu(env), decode->op[0].val, &val, 0, + decode->operand_size, 1); + if (decode->operand_size == 2) { + AX(env) = val; + } else { + RAX(env) = (uint32_t)val; + } + break; + case 0xec: + emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1); + break; + case 0xed: + emul_ops->handle_io(env_cpu(env), DX(env), &val, 0, + decode->operand_size, 1); + if (decode->operand_size == 2) { + AX(env) = val; + } else { + RAX(env) = (uint32_t)val; + } + + break; + default: + VM_PANIC("Bad in opcode\n"); + break; + } + + env->eip += decode->len; +} + +static inline void string_increment_reg(CPUX86State *env, int reg, + struct x86_decode *decode) +{ + target_ulong val = read_reg(env, reg, decode->addressing_size); + if (env->eflags & DF_MASK) { + val -= decode->operand_size; + } else { + val += decode->operand_size; + } + write_reg(env, reg, val, decode->addressing_size); +} + +static inline void string_rep(CPUX86State *env, struct x86_decode *decode, + void (*func)(CPUX86State *env, + struct x86_decode *ins), int rep) +{ + target_ulong rcx = read_reg(env, R_ECX, decode->addressing_size); + while (rcx--) { + func(env, decode); + write_reg(env, R_ECX, rcx, decode->addressing_size); + if ((PREFIX_REP == rep) && !get_ZF(env)) { + break; + } + if ((PREFIX_REPN == rep) && get_ZF(env)) { + break; + } + } +} + +static void exec_ins_single(CPUX86State *env, struct x86_decode *decode) +{ + target_ulong addr = linear_addr_size(env_cpu(env), RDI(env), + decode->addressing_size, R_ES); + + emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0, + decode->operand_size, 1); + emul_ops->write_mem(env_cpu(env), env->emu_mmio_buf, addr, + decode->operand_size); + + string_increment_reg(env, R_EDI, decode); +} + +static void exec_ins(CPUX86State *env, struct x86_decode *decode) +{ + if (decode->rep) { + string_rep(env, decode, exec_ins_single, 0); + } else { + exec_ins_single(env, decode); + } + + env->eip += decode->len; +} + +static void exec_outs_single(CPUX86State *env, struct x86_decode *decode) +{ + target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS); + + emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, addr, + decode->operand_size); + emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1, + decode->operand_size, 1); + + string_increment_reg(env, R_ESI, decode); +} + +static void exec_outs(CPUX86State *env, struct x86_decode *decode) +{ + if (decode->rep) { + string_rep(env, decode, exec_outs_single, 0); + } else { + exec_outs_single(env, decode); + } + + env->eip += decode->len; +} + +static void exec_movs_single(CPUX86State *env, struct x86_decode *decode) +{ + target_ulong src_addr; + target_ulong dst_addr; + target_ulong val; + + src_addr = decode_linear_addr(env, decode, RSI(env), R_DS); + dst_addr = linear_addr_size(env_cpu(env), RDI(env), + decode->addressing_size, R_ES); + + val = read_val_ext(env, src_addr, decode->operand_size); + write_val_ext(env, dst_addr, val, decode->operand_size); + + string_increment_reg(env, R_ESI, decode); + string_increment_reg(env, R_EDI, decode); +} + +static void exec_movs(CPUX86State *env, struct x86_decode *decode) +{ + if (decode->rep) { + string_rep(env, decode, exec_movs_single, 0); + } else { + exec_movs_single(env, decode); + } + + env->eip += decode->len; +} + +static void exec_cmps_single(CPUX86State *env, struct x86_decode *decode) +{ + target_ulong src_addr; + target_ulong dst_addr; + + src_addr = decode_linear_addr(env, decode, RSI(env), R_DS); + dst_addr = linear_addr_size(env_cpu(env), RDI(env), + decode->addressing_size, R_ES); + + decode->op[0].type = X86_VAR_IMMEDIATE; + decode->op[0].val = read_val_ext(env, src_addr, decode->operand_size); + decode->op[1].type = X86_VAR_IMMEDIATE; + decode->op[1].val = read_val_ext(env, dst_addr, decode->operand_size); + + EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); + + string_increment_reg(env, R_ESI, decode); + string_increment_reg(env, R_EDI, decode); +} + +static void exec_cmps(CPUX86State *env, struct x86_decode *decode) +{ + if (decode->rep) { + string_rep(env, decode, exec_cmps_single, decode->rep); + } else { + exec_cmps_single(env, decode); + } + env->eip += decode->len; +} + + +static void exec_stos_single(CPUX86State *env, struct x86_decode *decode) +{ + target_ulong addr; + target_ulong val; + + addr = linear_addr_size(env_cpu(env), RDI(env), + decode->addressing_size, R_ES); + val = read_reg(env, R_EAX, decode->operand_size); + emul_ops->write_mem(env_cpu(env), &val, addr, decode->operand_size); + + string_increment_reg(env, R_EDI, decode); +} + + +static void exec_stos(CPUX86State *env, struct x86_decode *decode) +{ + if (decode->rep) { + string_rep(env, decode, exec_stos_single, 0); + } else { + exec_stos_single(env, decode); + } + + env->eip += decode->len; +} + +static void exec_scas_single(CPUX86State *env, struct x86_decode *decode) +{ + target_ulong addr; + + addr = linear_addr_size(env_cpu(env), RDI(env), + decode->addressing_size, R_ES); + decode->op[1].type = X86_VAR_IMMEDIATE; + emul_ops->read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size); + + EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); + string_increment_reg(env, R_EDI, decode); +} + +static void exec_scas(CPUX86State *env, struct x86_decode *decode) +{ + decode->op[0].type = X86_VAR_REG; + decode->op[0].reg = R_EAX; + if (decode->rep) { + string_rep(env, decode, exec_scas_single, decode->rep); + } else { + exec_scas_single(env, decode); + } + + env->eip += decode->len; +} + +static void exec_lods_single(CPUX86State *env, struct x86_decode *decode) +{ + target_ulong addr; + target_ulong val = 0; + + addr = decode_linear_addr(env, decode, RSI(env), R_DS); + emul_ops->read_mem(env_cpu(env), &val, addr, decode->operand_size); + write_reg(env, R_EAX, val, decode->operand_size); + + string_increment_reg(env, R_ESI, decode); +} + +static void exec_lods(CPUX86State *env, struct x86_decode *decode) +{ + if (decode->rep) { + string_rep(env, decode, exec_lods_single, 0); + } else { + exec_lods_single(env, decode); + } + + env->eip += decode->len; +} + +void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code) +{ + env->exception_nr = exception_index; + env->error_code = error_code; + env->has_error_code = true; + env->exception_injected = 1; +} + +static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode) +{ + emul_ops->simulate_rdmsr(env_cpu(env)); + env->eip += decode->len; +} + +static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode) +{ + emul_ops->simulate_wrmsr(env_cpu(env)); + env->eip += decode->len; +} + +/* + * flag: + * 0 - bt, 1 - btc, 2 - bts, 3 - btr + */ +static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag) +{ + int32_t displacement; + uint8_t index; + bool cf; + int mask = (4 == decode->operand_size) ? 0x1f : 0xf; + + VM_PANIC_ON(decode->rex.rex); + + fetch_operands(env, decode, 2, false, true, false); + index = decode->op[1].val & mask; + + if (decode->op[0].type != X86_VAR_REG) { + if (4 == decode->operand_size) { + displacement = ((int32_t) (decode->op[1].val & 0xffffffe0)) / 32; + decode->op[0].ptr += 4 * displacement; + } else if (2 == decode->operand_size) { + displacement = ((int16_t) (decode->op[1].val & 0xfff0)) / 16; + decode->op[0].ptr += 2 * displacement; + } else { + VM_PANIC("bt 64bit\n"); + } + } + decode->op[0].val = read_val_ext(env, decode->op[0].ptr, + decode->operand_size); + cf = (decode->op[0].val >> index) & 0x01; + + switch (flag) { + case 0: + set_CF(env, cf); + return; + case 1: + decode->op[0].val ^= (1u << index); + break; + case 2: + decode->op[0].val |= (1u << index); + break; + case 3: + decode->op[0].val &= ~(1u << index); + break; + } + write_val_ext(env, decode->op[0].ptr, decode->op[0].val, + decode->operand_size); + set_CF(env, cf); +} + +static void exec_bt(CPUX86State *env, struct x86_decode *decode) +{ + do_bt(env, decode, 0); + env->eip += decode->len; +} + +static void exec_btc(CPUX86State *env, struct x86_decode *decode) +{ + do_bt(env, decode, 1); + env->eip += decode->len; +} + +static void exec_btr(CPUX86State *env, struct x86_decode *decode) +{ + do_bt(env, decode, 3); + env->eip += decode->len; +} + +static void exec_bts(CPUX86State *env, struct x86_decode *decode) +{ + do_bt(env, decode, 2); + env->eip += decode->len; +} + +void exec_shl(CPUX86State *env, struct x86_decode *decode) +{ + uint8_t count; + int of = 0, cf = 0; + + fetch_operands(env, decode, 2, true, true, false); + + count = decode->op[1].val; + count &= 0x1f; /* count is masked to 5 bits*/ + if (!count) { + goto exit; + } + + switch (decode->operand_size) { + case 1: + { + uint8_t res = 0; + if (count <= 8) { + res = (decode->op[0].val << count); + cf = (decode->op[0].val >> (8 - count)) & 0x1; + of = cf ^ (res >> 7); + } + + write_val_ext(env, decode->op[0].ptr, res, 1); + SET_FLAGS_OSZAPC_LOGIC8(env, 0, 0, res); + SET_FLAGS_OxxxxC(env, of, cf); + break; + } + case 2: + { + uint16_t res = 0; + + /* from bochs */ + if (count <= 16) { + res = (decode->op[0].val << count); + cf = (decode->op[0].val >> (16 - count)) & 0x1; + of = cf ^ (res >> 15); /* of = cf ^ result15 */ + } + + write_val_ext(env, decode->op[0].ptr, res, 2); + SET_FLAGS_OSZAPC_LOGIC16(env, 0, 0, res); + SET_FLAGS_OxxxxC(env, of, cf); + break; + } + case 4: + { + uint32_t res = decode->op[0].val << count; + + write_val_ext(env, decode->op[0].ptr, res, 4); + SET_FLAGS_OSZAPC_LOGIC32(env, 0, 0, res); + cf = (decode->op[0].val >> (32 - count)) & 0x1; + of = cf ^ (res >> 31); /* of = cf ^ result31 */ + SET_FLAGS_OxxxxC(env, of, cf); + break; + } + default: + abort(); + } + +exit: + /* lflags_to_rflags(env); */ + env->eip += decode->len; +} + +void exec_movsx(CPUX86State *env, struct x86_decode *decode) +{ + int src_op_size; + int op_size = decode->operand_size; + + fetch_operands(env, decode, 2, false, false, false); + + if (0xbe == decode->opcode[1]) { + src_op_size = 1; + } else { + src_op_size = 2; + } + + decode->operand_size = src_op_size; + calc_modrm_operand(env, decode, &decode->op[1]); + decode->op[1].val = sign(read_val_ext(env, decode->op[1].ptr, src_op_size), + src_op_size); + + write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size); + + env->eip += decode->len; +} + +void exec_ror(CPUX86State *env, struct x86_decode *decode) +{ + uint8_t count; + + fetch_operands(env, decode, 2, true, true, false); + count = decode->op[1].val; + + switch (decode->operand_size) { + case 1: + { + uint32_t bit6, bit7; + uint8_t res; + + if ((count & 0x07) == 0) { + if (count & 0x18) { + bit6 = ((uint8_t)decode->op[0].val >> 6) & 1; + bit7 = ((uint8_t)decode->op[0].val >> 7) & 1; + SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7); + } + } else { + count &= 0x7; /* use only bottom 3 bits */ + res = ((uint8_t)decode->op[0].val >> count) | + ((uint8_t)decode->op[0].val << (8 - count)); + write_val_ext(env, decode->op[0].ptr, res, 1); + bit6 = (res >> 6) & 1; + bit7 = (res >> 7) & 1; + /* set eflags: ROR count affects the following flags: C, O */ + SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7); + } + break; + } + case 2: + { + uint32_t bit14, bit15; + uint16_t res; + + if ((count & 0x0f) == 0) { + if (count & 0x10) { + bit14 = ((uint16_t)decode->op[0].val >> 14) & 1; + bit15 = ((uint16_t)decode->op[0].val >> 15) & 1; + /* of = result14 ^ result15 */ + SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15); + } + } else { + count &= 0x0f; /* use only 4 LSB's */ + res = ((uint16_t)decode->op[0].val >> count) | + ((uint16_t)decode->op[0].val << (16 - count)); + write_val_ext(env, decode->op[0].ptr, res, 2); + + bit14 = (res >> 14) & 1; + bit15 = (res >> 15) & 1; + /* of = result14 ^ result15 */ + SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15); + } + break; + } + case 4: + { + uint32_t bit31, bit30; + uint32_t res; + + count &= 0x1f; + if (count) { + res = ((uint32_t)decode->op[0].val >> count) | + ((uint32_t)decode->op[0].val << (32 - count)); + write_val_ext(env, decode->op[0].ptr, res, 4); + + bit31 = (res >> 31) & 1; + bit30 = (res >> 30) & 1; + /* of = result30 ^ result31 */ + SET_FLAGS_OxxxxC(env, bit30 ^ bit31, bit31); + } + break; + } + } + env->eip += decode->len; +} + +void exec_rol(CPUX86State *env, struct x86_decode *decode) +{ + uint8_t count; + + fetch_operands(env, decode, 2, true, true, false); + count = decode->op[1].val; + + switch (decode->operand_size) { + case 1: + { + uint32_t bit0, bit7; + uint8_t res; + + if ((count & 0x07) == 0) { + if (count & 0x18) { + bit0 = ((uint8_t)decode->op[0].val & 1); + bit7 = ((uint8_t)decode->op[0].val >> 7); + SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0); + } + } else { + count &= 0x7; /* use only lowest 3 bits */ + res = ((uint8_t)decode->op[0].val << count) | + ((uint8_t)decode->op[0].val >> (8 - count)); + + write_val_ext(env, decode->op[0].ptr, res, 1); + /* set eflags: + * ROL count affects the following flags: C, O + */ + bit0 = (res & 1); + bit7 = (res >> 7); + SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0); + } + break; + } + case 2: + { + uint32_t bit0, bit15; + uint16_t res; + + if ((count & 0x0f) == 0) { + if (count & 0x10) { + bit0 = ((uint16_t)decode->op[0].val & 0x1); + bit15 = ((uint16_t)decode->op[0].val >> 15); + /* of = cf ^ result15 */ + SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0); + } + } else { + count &= 0x0f; /* only use bottom 4 bits */ + res = ((uint16_t)decode->op[0].val << count) | + ((uint16_t)decode->op[0].val >> (16 - count)); + + write_val_ext(env, decode->op[0].ptr, res, 2); + bit0 = (res & 0x1); + bit15 = (res >> 15); + /* of = cf ^ result15 */ + SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0); + } + break; + } + case 4: + { + uint32_t bit0, bit31; + uint32_t res; + + count &= 0x1f; + if (count) { + res = ((uint32_t)decode->op[0].val << count) | + ((uint32_t)decode->op[0].val >> (32 - count)); + + write_val_ext(env, decode->op[0].ptr, res, 4); + bit0 = (res & 0x1); + bit31 = (res >> 31); + /* of = cf ^ result31 */ + SET_FLAGS_OxxxxC(env, bit0 ^ bit31, bit0); + } + break; + } + } + env->eip += decode->len; +} + + +void exec_rcl(CPUX86State *env, struct x86_decode *decode) +{ + uint8_t count; + int of = 0, cf = 0; + + fetch_operands(env, decode, 2, true, true, false); + count = decode->op[1].val & 0x1f; + + switch (decode->operand_size) { + case 1: + { + uint8_t op1_8 = decode->op[0].val; + uint8_t res; + count %= 9; + if (!count) { + break; + } + + if (1 == count) { + res = (op1_8 << 1) | get_CF(env); + } else { + res = (op1_8 << count) | (get_CF(env) << (count - 1)) | + (op1_8 >> (9 - count)); + } + + write_val_ext(env, decode->op[0].ptr, res, 1); + + cf = (op1_8 >> (8 - count)) & 0x01; + of = cf ^ (res >> 7); /* of = cf ^ result7 */ + SET_FLAGS_OxxxxC(env, of, cf); + break; + } + case 2: + { + uint16_t res; + uint16_t op1_16 = decode->op[0].val; + + count %= 17; + if (!count) { + break; + } + + if (1 == count) { + res = (op1_16 << 1) | get_CF(env); + } else if (count == 16) { + res = (get_CF(env) << 15) | (op1_16 >> 1); + } else { /* 2..15 */ + res = (op1_16 << count) | (get_CF(env) << (count - 1)) | + (op1_16 >> (17 - count)); + } + + write_val_ext(env, decode->op[0].ptr, res, 2); + + cf = (op1_16 >> (16 - count)) & 0x1; + of = cf ^ (res >> 15); /* of = cf ^ result15 */ + SET_FLAGS_OxxxxC(env, of, cf); + break; + } + case 4: + { + uint32_t res; + uint32_t op1_32 = decode->op[0].val; + + if (!count) { + break; + } + + if (1 == count) { + res = (op1_32 << 1) | get_CF(env); + } else { + res = (op1_32 << count) | (get_CF(env) << (count - 1)) | + (op1_32 >> (33 - count)); + } + + write_val_ext(env, decode->op[0].ptr, res, 4); + + cf = (op1_32 >> (32 - count)) & 0x1; + of = cf ^ (res >> 31); /* of = cf ^ result31 */ + SET_FLAGS_OxxxxC(env, of, cf); + break; + } + } + env->eip += decode->len; +} + +void exec_rcr(CPUX86State *env, struct x86_decode *decode) +{ + uint8_t count; + int of = 0, cf = 0; + + fetch_operands(env, decode, 2, true, true, false); + count = decode->op[1].val & 0x1f; + + switch (decode->operand_size) { + case 1: + { + uint8_t op1_8 = decode->op[0].val; + uint8_t res; + + count %= 9; + if (!count) { + break; + } + res = (op1_8 >> count) | (get_CF(env) << (8 - count)) | + (op1_8 << (9 - count)); + + write_val_ext(env, decode->op[0].ptr, res, 1); + + cf = (op1_8 >> (count - 1)) & 0x1; + of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */ + SET_FLAGS_OxxxxC(env, of, cf); + break; + } + case 2: + { + uint16_t op1_16 = decode->op[0].val; + uint16_t res; + + count %= 17; + if (!count) { + break; + } + res = (op1_16 >> count) | (get_CF(env) << (16 - count)) | + (op1_16 << (17 - count)); + + write_val_ext(env, decode->op[0].ptr, res, 2); + + cf = (op1_16 >> (count - 1)) & 0x1; + of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^ + result14 */ + SET_FLAGS_OxxxxC(env, of, cf); + break; + } + case 4: + { + uint32_t res; + uint32_t op1_32 = decode->op[0].val; + + if (!count) { + break; + } + + if (1 == count) { + res = (op1_32 >> 1) | (get_CF(env) << 31); + } else { + res = (op1_32 >> count) | (get_CF(env) << (32 - count)) | + (op1_32 << (33 - count)); + } + + write_val_ext(env, decode->op[0].ptr, res, 4); + + cf = (op1_32 >> (count - 1)) & 0x1; + of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */ + SET_FLAGS_OxxxxC(env, of, cf); + break; + } + } + env->eip += decode->len; +} + +static void exec_xchg(CPUX86State *env, struct x86_decode *decode) +{ + fetch_operands(env, decode, 2, true, true, false); + + write_val_ext(env, decode->op[0].ptr, decode->op[1].val, + decode->operand_size); + write_val_ext(env, decode->op[1].ptr, decode->op[0].val, + decode->operand_size); + + env->eip += decode->len; +} + +static void exec_xadd(CPUX86State *env, struct x86_decode *decode) +{ + EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true); + write_val_ext(env, decode->op[1].ptr, decode->op[0].val, + decode->operand_size); + + env->eip += decode->len; +} + +static struct cmd_handler { + enum x86_decode_cmd cmd; + void (*handler)(CPUX86State *env, struct x86_decode *ins); +} handlers[] = { + {X86_DECODE_CMD_INVL, NULL,}, + {X86_DECODE_CMD_MOV, exec_mov}, + {X86_DECODE_CMD_ADD, exec_add}, + {X86_DECODE_CMD_OR, exec_or}, + {X86_DECODE_CMD_ADC, exec_adc}, + {X86_DECODE_CMD_SBB, exec_sbb}, + {X86_DECODE_CMD_AND, exec_and}, + {X86_DECODE_CMD_SUB, exec_sub}, + {X86_DECODE_CMD_NEG, exec_neg}, + {X86_DECODE_CMD_XOR, exec_xor}, + {X86_DECODE_CMD_CMP, exec_cmp}, + {X86_DECODE_CMD_INC, exec_inc}, + {X86_DECODE_CMD_DEC, exec_dec}, + {X86_DECODE_CMD_TST, exec_tst}, + {X86_DECODE_CMD_NOT, exec_not}, + {X86_DECODE_CMD_MOVZX, exec_movzx}, + {X86_DECODE_CMD_OUT, exec_out}, + {X86_DECODE_CMD_IN, exec_in}, + {X86_DECODE_CMD_INS, exec_ins}, + {X86_DECODE_CMD_OUTS, exec_outs}, + {X86_DECODE_CMD_RDMSR, exec_rdmsr}, + {X86_DECODE_CMD_WRMSR, exec_wrmsr}, + {X86_DECODE_CMD_BT, exec_bt}, + {X86_DECODE_CMD_BTR, exec_btr}, + {X86_DECODE_CMD_BTC, exec_btc}, + {X86_DECODE_CMD_BTS, exec_bts}, + {X86_DECODE_CMD_SHL, exec_shl}, + {X86_DECODE_CMD_ROL, exec_rol}, + {X86_DECODE_CMD_ROR, exec_ror}, + {X86_DECODE_CMD_RCR, exec_rcr}, + {X86_DECODE_CMD_RCL, exec_rcl}, + /*{X86_DECODE_CMD_CPUID, exec_cpuid},*/ + {X86_DECODE_CMD_MOVS, exec_movs}, + {X86_DECODE_CMD_CMPS, exec_cmps}, + {X86_DECODE_CMD_STOS, exec_stos}, + {X86_DECODE_CMD_SCAS, exec_scas}, + {X86_DECODE_CMD_LODS, exec_lods}, + {X86_DECODE_CMD_MOVSX, exec_movsx}, + {X86_DECODE_CMD_XCHG, exec_xchg}, + {X86_DECODE_CMD_XADD, exec_xadd}, +}; + +static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST]; + +const struct x86_emul_ops *emul_ops; + +static void init_cmd_handler(void) +{ + int i; + for (i = 0; i < ARRAY_SIZE(handlers); i++) { + _cmd_handler[handlers[i].cmd] = handlers[i]; + } +} + +bool exec_instruction(CPUX86State *env, struct x86_decode *ins) +{ + if (!_cmd_handler[ins->cmd].handler) { + printf("Unimplemented handler (%llx) for %d (%x %x) \n", env->eip, + ins->cmd, ins->opcode[0], + ins->opcode_len > 1 ? ins->opcode[1] : 0); + env->eip += ins->len; + return true; + } + + _cmd_handler[ins->cmd].handler(env, ins); + return true; +} + +void init_emu(const struct x86_emul_ops *o) +{ + emul_ops = o; + init_cmd_handler(); +} diff --git a/target/i386/emulate/x86_emu.h b/target/i386/emulate/x86_emu.h new file mode 100644 index 0000000000..555b567e2c --- /dev/null +++ b/target/i386/emulate/x86_emu.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2016 Veertu Inc, + * Copyright (C) 2017 Google Inc, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef X86_EMU_H +#define X86_EMU_H + +#include "x86.h" +#include "x86_decode.h" +#include "cpu.h" + +struct x86_emul_ops { + void (*read_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes); + void (*write_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes); + void (*read_segment_descriptor)(CPUState *cpu, struct x86_segment_descriptor *desc, + enum X86Seg seg); + void (*handle_io)(CPUState *cpu, uint16_t port, void *data, int direction, + int size, int count); + void (*simulate_rdmsr)(CPUState *cs); + void (*simulate_wrmsr)(CPUState *cs); +}; + +extern const struct x86_emul_ops *emul_ops; + +void init_emu(const struct x86_emul_ops *ops); +bool exec_instruction(CPUX86State *env, struct x86_decode *ins); +void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code); + +target_ulong read_reg(CPUX86State *env, int reg, int size); +void write_reg(CPUX86State *env, int reg, target_ulong val, int size); +target_ulong read_val_from_reg(target_ulong reg_ptr, int size); +void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size); +void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size); +uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes); +target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size); + +void exec_movzx(CPUX86State *env, struct x86_decode *decode); +void exec_shl(CPUX86State *env, struct x86_decode *decode); +void exec_movsx(CPUX86State *env, struct x86_decode *decode); +void exec_ror(CPUX86State *env, struct x86_decode *decode); +void exec_rol(CPUX86State *env, struct x86_decode *decode); +void exec_rcl(CPUX86State *env, struct x86_decode *decode); +void exec_rcr(CPUX86State *env, struct x86_decode *decode); +#endif diff --git a/target/i386/emulate/x86_flags.c b/target/i386/emulate/x86_flags.c new file mode 100644 index 0000000000..84e27364a0 --- /dev/null +++ b/target/i386/emulate/x86_flags.c @@ -0,0 +1,305 @@ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001-2012 The Bochs Project +// Copyright (C) 2017 Google Inc. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA +///////////////////////////////////////////////////////////////////////// +/* + * flags functions + */ + +#include "qemu/osdep.h" + +#include "panic.h" +#include "cpu.h" +#include "x86_flags.h" +#include "x86.h" + + +/* this is basically bocsh code */ + +#define LF_SIGN_BIT 31 + +#define LF_BIT_SD (0) /* lazy Sign Flag Delta */ +#define LF_BIT_AF (3) /* lazy Adjust flag */ +#define LF_BIT_PDB (8) /* lazy Parity Delta Byte (8 bits) */ +#define LF_BIT_CF (31) /* lazy Carry Flag */ +#define LF_BIT_PO (30) /* lazy Partial Overflow = CF ^ OF */ + +#define LF_MASK_SD (0x01 << LF_BIT_SD) +#define LF_MASK_AF (0x01 << LF_BIT_AF) +#define LF_MASK_PDB (0xFF << LF_BIT_PDB) +#define LF_MASK_CF (0x01 << LF_BIT_CF) +#define LF_MASK_PO (0x01 << LF_BIT_PO) + +/* ******************* */ +/* OSZAPC */ +/* ******************* */ + +/* size, carries, result */ +#define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \ + target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \ + (((lf_carries) >> (size - 2)) << LF_BIT_PO); \ + env->lflags.result = (target_ulong)(int##size##_t)(lf_result); \ + if ((size) == 32) { \ + temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ + } else if ((size) == 16) { \ + temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \ + } else if ((size) == 8) { \ + temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \ + } else { \ + VM_PANIC("unimplemented"); \ + } \ + env->lflags.auxbits = (target_ulong)(uint32_t)temp; \ +} + +/* carries, result */ +#define SET_FLAGS_OSZAPC_8(carries, result) \ + SET_FLAGS_OSZAPC_SIZE(8, carries, result) +#define SET_FLAGS_OSZAPC_16(carries, result) \ + SET_FLAGS_OSZAPC_SIZE(16, carries, result) +#define SET_FLAGS_OSZAPC_32(carries, result) \ + SET_FLAGS_OSZAPC_SIZE(32, carries, result) + +/* ******************* */ +/* OSZAP */ +/* ******************* */ +/* size, carries, result */ +#define SET_FLAGS_OSZAP_SIZE(size, lf_carries, lf_result) { \ + target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \ + (((lf_carries) >> (size - 2)) << LF_BIT_PO); \ + if ((size) == 32) { \ + temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ + } else if ((size) == 16) { \ + temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \ + } else if ((size) == 8) { \ + temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \ + } else { \ + VM_PANIC("unimplemented"); \ + } \ + env->lflags.result = (target_ulong)(int##size##_t)(lf_result); \ + target_ulong delta_c = (env->lflags.auxbits ^ temp) & LF_MASK_CF; \ + delta_c ^= (delta_c >> 1); \ + env->lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \ +} + +/* carries, result */ +#define SET_FLAGS_OSZAP_8(carries, result) \ + SET_FLAGS_OSZAP_SIZE(8, carries, result) +#define SET_FLAGS_OSZAP_16(carries, result) \ + SET_FLAGS_OSZAP_SIZE(16, carries, result) +#define SET_FLAGS_OSZAP_32(carries, result) \ + SET_FLAGS_OSZAP_SIZE(32, carries, result) + +void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf) +{ + uint32_t temp_po = new_of ^ new_cf; + env->lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF); + env->lflags.auxbits |= (temp_po << LF_BIT_PO) | (new_cf << LF_BIT_CF); +} + +void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2, + uint32_t diff) +{ + SET_FLAGS_OSZAPC_32(SUB_COUT_VEC(v1, v2, diff), diff); +} + +void SET_FLAGS_OSZAPC_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2, + uint16_t diff) +{ + SET_FLAGS_OSZAPC_16(SUB_COUT_VEC(v1, v2, diff), diff); +} + +void SET_FLAGS_OSZAPC_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2, + uint8_t diff) +{ + SET_FLAGS_OSZAPC_8(SUB_COUT_VEC(v1, v2, diff), diff); +} + +void SET_FLAGS_OSZAPC_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2, + uint32_t diff) +{ + SET_FLAGS_OSZAPC_32(ADD_COUT_VEC(v1, v2, diff), diff); +} + +void SET_FLAGS_OSZAPC_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2, + uint16_t diff) +{ + SET_FLAGS_OSZAPC_16(ADD_COUT_VEC(v1, v2, diff), diff); +} + +void SET_FLAGS_OSZAPC_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2, + uint8_t diff) +{ + SET_FLAGS_OSZAPC_8(ADD_COUT_VEC(v1, v2, diff), diff); +} + +void SET_FLAGS_OSZAP_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2, + uint32_t diff) +{ + SET_FLAGS_OSZAP_32(SUB_COUT_VEC(v1, v2, diff), diff); +} + +void SET_FLAGS_OSZAP_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2, + uint16_t diff) +{ + SET_FLAGS_OSZAP_16(SUB_COUT_VEC(v1, v2, diff), diff); +} + +void SET_FLAGS_OSZAP_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2, + uint8_t diff) +{ + SET_FLAGS_OSZAP_8(SUB_COUT_VEC(v1, v2, diff), diff); +} + +void SET_FLAGS_OSZAP_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2, + uint32_t diff) +{ + SET_FLAGS_OSZAP_32(ADD_COUT_VEC(v1, v2, diff), diff); +} + +void SET_FLAGS_OSZAP_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2, + uint16_t diff) +{ + SET_FLAGS_OSZAP_16(ADD_COUT_VEC(v1, v2, diff), diff); +} + +void SET_FLAGS_OSZAP_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2, + uint8_t diff) +{ + SET_FLAGS_OSZAP_8(ADD_COUT_VEC(v1, v2, diff), diff); +} + + +void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State *env, uint32_t v1, uint32_t v2, + uint32_t diff) +{ + SET_FLAGS_OSZAPC_32(0, diff); +} + +void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State *env, uint16_t v1, uint16_t v2, + uint16_t diff) +{ + SET_FLAGS_OSZAPC_16(0, diff); +} + +void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2, + uint8_t diff) +{ + SET_FLAGS_OSZAPC_8(0, diff); +} + +bool get_PF(CPUX86State *env) +{ + uint32_t temp = (255 & env->lflags.result); + temp = temp ^ (255 & (env->lflags.auxbits >> LF_BIT_PDB)); + temp = (temp ^ (temp >> 4)) & 0x0F; + return (0x9669U >> temp) & 1; +} + +void set_PF(CPUX86State *env, bool val) +{ + uint32_t temp = (255 & env->lflags.result) ^ (!val); + env->lflags.auxbits &= ~(LF_MASK_PDB); + env->lflags.auxbits |= (temp << LF_BIT_PDB); +} + +bool get_OF(CPUX86State *env) +{ + return ((env->lflags.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1; +} + +bool get_CF(CPUX86State *env) +{ + return (env->lflags.auxbits >> LF_BIT_CF) & 1; +} + +void set_OF(CPUX86State *env, bool val) +{ + bool old_cf = get_CF(env); + SET_FLAGS_OxxxxC(env, val, old_cf); +} + +void set_CF(CPUX86State *env, bool val) +{ + bool old_of = get_OF(env); + SET_FLAGS_OxxxxC(env, old_of, val); +} + +bool get_AF(CPUX86State *env) +{ + return (env->lflags.auxbits >> LF_BIT_AF) & 1; +} + +void set_AF(CPUX86State *env, bool val) +{ + env->lflags.auxbits &= ~(LF_MASK_AF); + env->lflags.auxbits |= val << LF_BIT_AF; +} + +bool get_ZF(CPUX86State *env) +{ + return !env->lflags.result; +} + +void set_ZF(CPUX86State *env, bool val) +{ + if (val) { + env->lflags.auxbits ^= + (((env->lflags.result >> LF_SIGN_BIT) & 1) << LF_BIT_SD); + /* merge the parity bits into the Parity Delta Byte */ + uint32_t temp_pdb = (255 & env->lflags.result); + env->lflags.auxbits ^= (temp_pdb << LF_BIT_PDB); + /* now zero the .result value */ + env->lflags.result = 0; + } else { + env->lflags.result |= (1 << 8); + } +} + +bool get_SF(CPUX86State *env) +{ + return ((env->lflags.result >> LF_SIGN_BIT) ^ + (env->lflags.auxbits >> LF_BIT_SD)) & 1; +} + +void set_SF(CPUX86State *env, bool val) +{ + bool temp_sf = get_SF(env); + env->lflags.auxbits ^= (temp_sf ^ val) << LF_BIT_SD; +} + +void lflags_to_rflags(CPUX86State *env) +{ + env->eflags &= ~(CC_C|CC_P|CC_A|CC_Z|CC_S|CC_O); + env->eflags |= get_CF(env) ? CC_C : 0; + env->eflags |= get_PF(env) ? CC_P : 0; + env->eflags |= get_AF(env) ? CC_A : 0; + env->eflags |= get_ZF(env) ? CC_Z : 0; + env->eflags |= get_SF(env) ? CC_S : 0; + env->eflags |= get_OF(env) ? CC_O : 0; +} + +void rflags_to_lflags(CPUX86State *env) +{ + env->lflags.auxbits = env->lflags.result = 0; + set_OF(env, env->eflags & CC_O); + set_SF(env, env->eflags & CC_S); + set_ZF(env, env->eflags & CC_Z); + set_AF(env, env->eflags & CC_A); + set_PF(env, env->eflags & CC_P); + set_CF(env, env->eflags & CC_C); +} diff --git a/target/i386/emulate/x86_flags.h b/target/i386/emulate/x86_flags.h new file mode 100644 index 0000000000..6c175007b5 --- /dev/null +++ b/target/i386/emulate/x86_flags.h @@ -0,0 +1,81 @@ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001-2012 The Bochs Project +// Copyright (C) 2017 Google Inc. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA +///////////////////////////////////////////////////////////////////////// +/* + * x86 eflags functions + */ + +#ifndef X86_EMU_FLAGS_H +#define X86_EMU_FLAGS_H + +#include "cpu.h" +void lflags_to_rflags(CPUX86State *env); +void rflags_to_lflags(CPUX86State *env); + +bool get_PF(CPUX86State *env); +void set_PF(CPUX86State *env, bool val); +bool get_CF(CPUX86State *env); +void set_CF(CPUX86State *env, bool val); +bool get_AF(CPUX86State *env); +void set_AF(CPUX86State *env, bool val); +bool get_ZF(CPUX86State *env); +void set_ZF(CPUX86State *env, bool val); +bool get_SF(CPUX86State *env); +void set_SF(CPUX86State *env, bool val); +bool get_OF(CPUX86State *env); +void set_OF(CPUX86State *env, bool val); + +void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf); + +void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2, + uint32_t diff); +void SET_FLAGS_OSZAPC_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2, + uint16_t diff); +void SET_FLAGS_OSZAPC_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2, + uint8_t diff); + +void SET_FLAGS_OSZAPC_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2, + uint32_t diff); +void SET_FLAGS_OSZAPC_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2, + uint16_t diff); +void SET_FLAGS_OSZAPC_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2, + uint8_t diff); + +void SET_FLAGS_OSZAP_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2, + uint32_t diff); +void SET_FLAGS_OSZAP_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2, + uint16_t diff); +void SET_FLAGS_OSZAP_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2, + uint8_t diff); + +void SET_FLAGS_OSZAP_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2, + uint32_t diff); +void SET_FLAGS_OSZAP_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2, + uint16_t diff); +void SET_FLAGS_OSZAP_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2, + uint8_t diff); + +void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State *env, uint32_t v1, uint32_t v2, + uint32_t diff); +void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State *env, uint16_t v1, uint16_t v2, + uint16_t diff); +void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2, + uint8_t diff); + +#endif /* X86_EMU_FLAGS_H */ diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c index 8c31d2e0cf..23ebf2550a 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -59,12 +59,12 @@ #include "hvf-i386.h" #include "vmcs.h" #include "vmx.h" -#include "x86.h" +#include "emulate/x86.h" #include "x86_descr.h" -#include "x86_flags.h" +#include "emulate/x86_flags.h" #include "x86_mmu.h" -#include "x86_decode.h" -#include "x86_emu.h" +#include "emulate/x86_decode.h" +#include "emulate/x86_emu.h" #include "x86_task.h" #include "x86hvf.h" diff --git a/target/i386/hvf/meson.build b/target/i386/hvf/meson.build index 05c3c8cf18..519d190f0e 100644 --- a/target/i386/hvf/meson.build +++ b/target/i386/hvf/meson.build @@ -2,10 +2,7 @@ i386_system_ss.add(when: [hvf, 'CONFIG_HVF'], if_true: files( 'hvf.c', 'x86.c', 'x86_cpuid.c', - 'x86_decode.c', 'x86_descr.c', - 'x86_emu.c', - 'x86_flags.c', 'x86_mmu.c', 'x86_task.c', 'x86hvf.c', diff --git a/target/i386/hvf/vmx.h b/target/i386/hvf/vmx.h index 80ce26279b..3c56afc9d3 100644 --- a/target/i386/hvf/vmx.h +++ b/target/i386/hvf/vmx.h @@ -29,7 +29,7 @@ #include #include "vmcs.h" #include "cpu.h" -#include "x86.h" +#include "emulate/x86.h" #include "system/hvf.h" #include "system/hvf_int.h" diff --git a/target/i386/hvf/x86.c b/target/i386/hvf/x86.c index a0ede13886..5c75ec9a00 100644 --- a/target/i386/hvf/x86.c +++ b/target/i386/hvf/x86.c @@ -19,8 +19,8 @@ #include "qemu/osdep.h" #include "cpu.h" -#include "x86_decode.h" -#include "x86_emu.h" +#include "emulate/x86_decode.h" +#include "emulate/x86_emu.h" #include "vmcs.h" #include "vmx.h" #include "x86_mmu.h" diff --git a/target/i386/hvf/x86.h b/target/i386/hvf/x86.h deleted file mode 100644 index 73edccfba0..0000000000 --- a/target/i386/hvf/x86.h +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (C) 2016 Veertu Inc, - * Copyright (C) 2017 Veertu Inc, - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef X86_EMU_DEFS_H -#define X86_EMU_DEFS_H - -typedef struct x86_register { - union { - struct { - uint64_t rrx; /* full 64 bit */ - }; - struct { - uint32_t erx; /* low 32 bit part */ - uint32_t hi32_unused1; - }; - struct { - uint16_t rx; /* low 16 bit part */ - uint16_t hi16_unused1; - uint32_t hi32_unused2; - }; - struct { - uint8_t lx; /* low 8 bit part */ - uint8_t hx; /* high 8 bit */ - uint16_t hi16_unused2; - uint32_t hi32_unused3; - }; - }; -} __attribute__ ((__packed__)) x86_register; - -/* 16 bit Task State Segment */ -typedef struct x86_tss_segment16 { - uint16_t link; - uint16_t sp0; - uint16_t ss0; - uint32_t sp1; - uint16_t ss1; - uint32_t sp2; - uint16_t ss2; - uint16_t ip; - uint16_t flags; - uint16_t ax; - uint16_t cx; - uint16_t dx; - uint16_t bx; - uint16_t sp; - uint16_t bp; - uint16_t si; - uint16_t di; - uint16_t es; - uint16_t cs; - uint16_t ss; - uint16_t ds; - uint16_t ldtr; -} __attribute__((packed)) x86_tss_segment16; - -/* 32 bit Task State Segment */ -typedef struct x86_tss_segment32 { - uint32_t prev_tss; - uint32_t esp0; - uint32_t ss0; - uint32_t esp1; - uint32_t ss1; - uint32_t esp2; - uint32_t ss2; - uint32_t cr3; - uint32_t eip; - uint32_t eflags; - uint32_t eax; - uint32_t ecx; - uint32_t edx; - uint32_t ebx; - uint32_t esp; - uint32_t ebp; - uint32_t esi; - uint32_t edi; - uint32_t es; - uint32_t cs; - uint32_t ss; - uint32_t ds; - uint32_t fs; - uint32_t gs; - uint32_t ldt; - uint16_t trap; - uint16_t iomap_base; -} __attribute__ ((__packed__)) x86_tss_segment32; - -/* 64 bit Task State Segment */ -typedef struct x86_tss_segment64 { - uint32_t unused; - uint64_t rsp0; - uint64_t rsp1; - uint64_t rsp2; - uint64_t unused1; - uint64_t ist1; - uint64_t ist2; - uint64_t ist3; - uint64_t ist4; - uint64_t ist5; - uint64_t ist6; - uint64_t ist7; - uint64_t unused2; - uint16_t unused3; - uint16_t iomap_base; -} __attribute__ ((__packed__)) x86_tss_segment64; - -/* segment descriptors */ -typedef struct x86_segment_descriptor { - uint64_t limit0:16; - uint64_t base0:16; - uint64_t base1:8; - uint64_t type:4; - uint64_t s:1; - uint64_t dpl:2; - uint64_t p:1; - uint64_t limit1:4; - uint64_t avl:1; - uint64_t l:1; - uint64_t db:1; - uint64_t g:1; - uint64_t base2:8; -} __attribute__ ((__packed__)) x86_segment_descriptor; - -static inline uint32_t x86_segment_base(x86_segment_descriptor *desc) -{ - return (uint32_t)((desc->base2 << 24) | (desc->base1 << 16) | desc->base0); -} - -static inline void x86_set_segment_base(x86_segment_descriptor *desc, - uint32_t base) -{ - desc->base2 = base >> 24; - desc->base1 = (base >> 16) & 0xff; - desc->base0 = base & 0xffff; -} - -static inline uint32_t x86_segment_limit(x86_segment_descriptor *desc) -{ - uint32_t limit = (uint32_t)((desc->limit1 << 16) | desc->limit0); - if (desc->g) { - return (limit << 12) | 0xfff; - } - return limit; -} - -static inline void x86_set_segment_limit(x86_segment_descriptor *desc, - uint32_t limit) -{ - desc->limit0 = limit & 0xffff; - desc->limit1 = limit >> 16; -} - -typedef struct x86_call_gate { - uint64_t offset0:16; - uint64_t selector:16; - uint64_t param_count:4; - uint64_t reserved:3; - uint64_t type:4; - uint64_t dpl:1; - uint64_t p:1; - uint64_t offset1:16; -} __attribute__ ((__packed__)) x86_call_gate; - -static inline uint32_t x86_call_gate_offset(x86_call_gate *gate) -{ - return (uint32_t)((gate->offset1 << 16) | gate->offset0); -} - -#define GDT_SEL 0 -#define LDT_SEL 1 - -typedef struct x86_segment_selector { - union { - uint16_t sel; - struct { - uint16_t rpl:2; - uint16_t ti:1; - uint16_t index:13; - }; - }; -} __attribute__ ((__packed__)) x86_segment_selector; - -/* useful register access macros */ -#define x86_reg(cpu, reg) ((x86_register *) &cpu->regs[reg]) - -#define RRX(cpu, reg) (x86_reg(cpu, reg)->rrx) -#define RAX(cpu) RRX(cpu, R_EAX) -#define RCX(cpu) RRX(cpu, R_ECX) -#define RDX(cpu) RRX(cpu, R_EDX) -#define RBX(cpu) RRX(cpu, R_EBX) -#define RSP(cpu) RRX(cpu, R_ESP) -#define RBP(cpu) RRX(cpu, R_EBP) -#define RSI(cpu) RRX(cpu, R_ESI) -#define RDI(cpu) RRX(cpu, R_EDI) -#define R8(cpu) RRX(cpu, R_R8) -#define R9(cpu) RRX(cpu, R_R9) -#define R10(cpu) RRX(cpu, R_R10) -#define R11(cpu) RRX(cpu, R_R11) -#define R12(cpu) RRX(cpu, R_R12) -#define R13(cpu) RRX(cpu, R_R13) -#define R14(cpu) RRX(cpu, R_R14) -#define R15(cpu) RRX(cpu, R_R15) - -#define ERX(cpu, reg) (x86_reg(cpu, reg)->erx) -#define EAX(cpu) ERX(cpu, R_EAX) -#define ECX(cpu) ERX(cpu, R_ECX) -#define EDX(cpu) ERX(cpu, R_EDX) -#define EBX(cpu) ERX(cpu, R_EBX) -#define ESP(cpu) ERX(cpu, R_ESP) -#define EBP(cpu) ERX(cpu, R_EBP) -#define ESI(cpu) ERX(cpu, R_ESI) -#define EDI(cpu) ERX(cpu, R_EDI) - -#define RX(cpu, reg) (x86_reg(cpu, reg)->rx) -#define AX(cpu) RX(cpu, R_EAX) -#define CX(cpu) RX(cpu, R_ECX) -#define DX(cpu) RX(cpu, R_EDX) -#define BP(cpu) RX(cpu, R_EBP) -#define SP(cpu) RX(cpu, R_ESP) -#define BX(cpu) RX(cpu, R_EBX) -#define SI(cpu) RX(cpu, R_ESI) -#define DI(cpu) RX(cpu, R_EDI) - -#define RL(cpu, reg) (x86_reg(cpu, reg)->lx) -#define AL(cpu) RL(cpu, R_EAX) -#define CL(cpu) RL(cpu, R_ECX) -#define DL(cpu) RL(cpu, R_EDX) -#define BL(cpu) RL(cpu, R_EBX) - -#define RH(cpu, reg) (x86_reg(cpu, reg)->hx) -#define AH(cpu) RH(cpu, R_EAX) -#define CH(cpu) RH(cpu, R_ECX) -#define DH(cpu) RH(cpu, R_EDX) -#define BH(cpu) RH(cpu, R_EBX) - -/* deal with GDT/LDT descriptors in memory */ -bool x86_read_segment_descriptor(CPUState *cpu, - struct x86_segment_descriptor *desc, - x86_segment_selector sel); -bool x86_write_segment_descriptor(CPUState *cpu, - struct x86_segment_descriptor *desc, - x86_segment_selector sel); - -bool x86_read_call_gate(CPUState *cpu, struct x86_call_gate *idt_desc, - int gate); - -/* helpers */ -bool x86_is_protected(CPUState *cpu); -bool x86_is_real(CPUState *cpu); -bool x86_is_v8086(CPUState *cpu); -bool x86_is_long_mode(CPUState *cpu); -bool x86_is_long64_mode(CPUState *cpu); -bool x86_is_paging_mode(CPUState *cpu); -bool x86_is_pae_enabled(CPUState *cpu); - -enum X86Seg; -target_ulong linear_addr(CPUState *cpu, target_ulong addr, enum X86Seg seg); -target_ulong linear_addr_size(CPUState *cpu, target_ulong addr, int size, - enum X86Seg seg); -target_ulong linear_rip(CPUState *cpu, target_ulong rip); - -static inline uint64_t rdtscp(void) -{ - uint64_t tsc; - __asm__ __volatile__("rdtscp; " /* serializing read of tsc */ - "shl $32,%%rdx; " /* shift higher 32 bits stored in rdx up */ - "or %%rdx,%%rax" /* and or onto rax */ - : "=a"(tsc) /* output to tsc variable */ - : - : "%rcx", "%rdx"); /* rcx and rdx are clobbered */ - - return tsc; -} - -#endif diff --git a/target/i386/hvf/x86_cpuid.c b/target/i386/hvf/x86_cpuid.c index ae836f65cc..fa131b18c6 100644 --- a/target/i386/hvf/x86_cpuid.c +++ b/target/i386/hvf/x86_cpuid.c @@ -24,7 +24,7 @@ #include "qemu/cpuid.h" #include "host/cpuinfo.h" #include "cpu.h" -#include "x86.h" +#include "emulate/x86.h" #include "vmx.h" #include "system/hvf.h" #include "hvf-i386.h" diff --git a/target/i386/hvf/x86_decode.c b/target/i386/hvf/x86_decode.c deleted file mode 100644 index ddd7b60bcf..0000000000 --- a/target/i386/hvf/x86_decode.c +++ /dev/null @@ -1,2194 +0,0 @@ -/* - * Copyright (C) 2016 Veertu Inc, - * Copyright (C) 2017 Google Inc, - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#include "qemu/osdep.h" - -#include "panic.h" -#include "x86_decode.h" -#include "x86_emu.h" - -#define OPCODE_ESCAPE 0xf - -static void decode_invalid(CPUX86State *env, struct x86_decode *decode) -{ - printf("%llx: failed to decode instruction ", env->eip); - for (int i = 0; i < decode->opcode_len; i++) { - printf("%x ", decode->opcode[i]); - } - printf("\n"); - VM_PANIC("decoder failed\n"); -} - -uint64_t sign(uint64_t val, int size) -{ - switch (size) { - case 1: - val = (int8_t)val; - break; - case 2: - val = (int16_t)val; - break; - case 4: - val = (int32_t)val; - break; - case 8: - val = (int64_t)val; - break; - default: - VM_PANIC_EX("%s invalid size %d\n", __func__, size); - break; - } - return val; -} - -static inline uint64_t decode_bytes(CPUX86State *env, struct x86_decode *decode, - int size) -{ - uint64_t val = 0; - - switch (size) { - case 1: - case 2: - case 4: - case 8: - break; - default: - VM_PANIC_EX("%s invalid size %d\n", __func__, size); - break; - } - target_ulong va = linear_rip(env_cpu(env), env->eip) + decode->len; - emul_ops->read_mem(env_cpu(env), &val, va, size); - decode->len += size; - - return val; -} - -static inline uint8_t decode_byte(CPUX86State *env, struct x86_decode *decode) -{ - return (uint8_t)decode_bytes(env, decode, 1); -} - -static inline uint16_t decode_word(CPUX86State *env, struct x86_decode *decode) -{ - return (uint16_t)decode_bytes(env, decode, 2); -} - -static inline uint32_t decode_dword(CPUX86State *env, struct x86_decode *decode) -{ - return (uint32_t)decode_bytes(env, decode, 4); -} - -static inline uint64_t decode_qword(CPUX86State *env, struct x86_decode *decode) -{ - return decode_bytes(env, decode, 8); -} - -static void decode_modrm_rm(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - op->type = X86_VAR_RM; -} - -static void decode_modrm_reg(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - op->type = X86_VAR_REG; - op->reg = decode->modrm.reg; - op->ptr = get_reg_ref(env, op->reg, decode->rex.rex, decode->rex.r, - decode->operand_size); -} - -static void decode_rax(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - op->type = X86_VAR_REG; - op->reg = R_EAX; - /* Since reg is always AX, REX prefix has no impact. */ - op->ptr = get_reg_ref(env, op->reg, false, 0, - decode->operand_size); -} - -static inline void decode_immediate(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *var, int size) -{ - var->type = X86_VAR_IMMEDIATE; - var->size = size; - switch (size) { - case 1: - var->val = decode_byte(env, decode); - break; - case 2: - var->val = decode_word(env, decode); - break; - case 4: - var->val = decode_dword(env, decode); - break; - case 8: - var->val = decode_qword(env, decode); - break; - default: - VM_PANIC_EX("bad size %d\n", size); - } -} - -static void decode_imm8(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - decode_immediate(env, decode, op, 1); - op->type = X86_VAR_IMMEDIATE; -} - -static void decode_imm8_signed(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - decode_immediate(env, decode, op, 1); - op->val = sign(op->val, 1); - op->type = X86_VAR_IMMEDIATE; -} - -static void decode_imm16(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - decode_immediate(env, decode, op, 2); - op->type = X86_VAR_IMMEDIATE; -} - - -static void decode_imm(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - if (8 == decode->operand_size) { - decode_immediate(env, decode, op, 4); - op->val = sign(op->val, decode->operand_size); - } else { - decode_immediate(env, decode, op, decode->operand_size); - } - op->type = X86_VAR_IMMEDIATE; -} - -static void decode_imm_signed(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - decode_immediate(env, decode, op, decode->operand_size); - op->val = sign(op->val, decode->operand_size); - op->type = X86_VAR_IMMEDIATE; -} - -static void decode_imm_1(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - op->type = X86_VAR_IMMEDIATE; - op->val = 1; -} - -static void decode_imm_0(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - op->type = X86_VAR_IMMEDIATE; - op->val = 0; -} - - -static void decode_pushseg(CPUX86State *env, struct x86_decode *decode) -{ - uint8_t op = (decode->opcode_len > 1) ? decode->opcode[1] : decode->opcode[0]; - - decode->op[0].type = X86_VAR_REG; - switch (op) { - case 0xe: - decode->op[0].reg = R_CS; - break; - case 0x16: - decode->op[0].reg = R_SS; - break; - case 0x1e: - decode->op[0].reg = R_DS; - break; - case 0x06: - decode->op[0].reg = R_ES; - break; - case 0xa0: - decode->op[0].reg = R_FS; - break; - case 0xa8: - decode->op[0].reg = R_GS; - break; - } -} - -static void decode_popseg(CPUX86State *env, struct x86_decode *decode) -{ - uint8_t op = (decode->opcode_len > 1) ? decode->opcode[1] : decode->opcode[0]; - - decode->op[0].type = X86_VAR_REG; - switch (op) { - case 0xf: - decode->op[0].reg = R_CS; - break; - case 0x17: - decode->op[0].reg = R_SS; - break; - case 0x1f: - decode->op[0].reg = R_DS; - break; - case 0x07: - decode->op[0].reg = R_ES; - break; - case 0xa1: - decode->op[0].reg = R_FS; - break; - case 0xa9: - decode->op[0].reg = R_GS; - break; - } -} - -static void decode_incgroup(CPUX86State *env, struct x86_decode *decode) -{ - decode->op[0].type = X86_VAR_REG; - decode->op[0].reg = decode->opcode[0] - 0x40; - decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, - decode->rex.b, decode->operand_size); -} - -static void decode_decgroup(CPUX86State *env, struct x86_decode *decode) -{ - decode->op[0].type = X86_VAR_REG; - decode->op[0].reg = decode->opcode[0] - 0x48; - decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, - decode->rex.b, decode->operand_size); -} - -static void decode_incgroup2(CPUX86State *env, struct x86_decode *decode) -{ - if (!decode->modrm.reg) { - decode->cmd = X86_DECODE_CMD_INC; - } else if (1 == decode->modrm.reg) { - decode->cmd = X86_DECODE_CMD_DEC; - } -} - -static void decode_pushgroup(CPUX86State *env, struct x86_decode *decode) -{ - decode->op[0].type = X86_VAR_REG; - decode->op[0].reg = decode->opcode[0] - 0x50; - decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, - decode->rex.b, decode->operand_size); -} - -static void decode_popgroup(CPUX86State *env, struct x86_decode *decode) -{ - decode->op[0].type = X86_VAR_REG; - decode->op[0].reg = decode->opcode[0] - 0x58; - decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, - decode->rex.b, decode->operand_size); -} - -static void decode_jxx(CPUX86State *env, struct x86_decode *decode) -{ - decode->displacement = decode_bytes(env, decode, decode->operand_size); - decode->displacement_size = decode->operand_size; -} - -static void decode_farjmp(CPUX86State *env, struct x86_decode *decode) -{ - decode->op[0].type = X86_VAR_IMMEDIATE; - decode->op[0].val = decode_bytes(env, decode, decode->operand_size); - decode->displacement = decode_word(env, decode); -} - -static void decode_addgroup(CPUX86State *env, struct x86_decode *decode) -{ - enum x86_decode_cmd group[] = { - X86_DECODE_CMD_ADD, - X86_DECODE_CMD_OR, - X86_DECODE_CMD_ADC, - X86_DECODE_CMD_SBB, - X86_DECODE_CMD_AND, - X86_DECODE_CMD_SUB, - X86_DECODE_CMD_XOR, - X86_DECODE_CMD_CMP - }; - decode->cmd = group[decode->modrm.reg]; -} - -static void decode_rotgroup(CPUX86State *env, struct x86_decode *decode) -{ - enum x86_decode_cmd group[] = { - X86_DECODE_CMD_ROL, - X86_DECODE_CMD_ROR, - X86_DECODE_CMD_RCL, - X86_DECODE_CMD_RCR, - X86_DECODE_CMD_SHL, - X86_DECODE_CMD_SHR, - X86_DECODE_CMD_SHL, - X86_DECODE_CMD_SAR - }; - decode->cmd = group[decode->modrm.reg]; -} - -static void decode_f7group(CPUX86State *env, struct x86_decode *decode) -{ - enum x86_decode_cmd group[] = { - X86_DECODE_CMD_TST, - X86_DECODE_CMD_TST, - X86_DECODE_CMD_NOT, - X86_DECODE_CMD_NEG, - X86_DECODE_CMD_MUL, - X86_DECODE_CMD_IMUL_1, - X86_DECODE_CMD_DIV, - X86_DECODE_CMD_IDIV - }; - decode->cmd = group[decode->modrm.reg]; - decode_modrm_rm(env, decode, &decode->op[0]); - - switch (decode->modrm.reg) { - case 0: - case 1: - decode_imm(env, decode, &decode->op[1]); - break; - case 2: - break; - case 3: - decode->op[1].type = X86_VAR_IMMEDIATE; - decode->op[1].val = 0; - break; - default: - break; - } -} - -static void decode_xchgroup(CPUX86State *env, struct x86_decode *decode) -{ - decode->op[0].type = X86_VAR_REG; - decode->op[0].reg = decode->opcode[0] - 0x90; - decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, - decode->rex.b, decode->operand_size); -} - -static void decode_movgroup(CPUX86State *env, struct x86_decode *decode) -{ - decode->op[0].type = X86_VAR_REG; - decode->op[0].reg = decode->opcode[0] - 0xb8; - decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, - decode->rex.b, decode->operand_size); - decode_immediate(env, decode, &decode->op[1], decode->operand_size); -} - -static void fetch_moffs(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - op->type = X86_VAR_OFFSET; - op->ptr = decode_bytes(env, decode, decode->addressing_size); -} - -static void decode_movgroup8(CPUX86State *env, struct x86_decode *decode) -{ - decode->op[0].type = X86_VAR_REG; - decode->op[0].reg = decode->opcode[0] - 0xb0; - decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, - decode->rex.b, decode->operand_size); - decode_immediate(env, decode, &decode->op[1], decode->operand_size); -} - -static void decode_rcx(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - op->type = X86_VAR_REG; - op->reg = R_ECX; - op->ptr = get_reg_ref(env, op->reg, decode->rex.rex, decode->rex.b, - decode->operand_size); -} - -struct decode_tbl { - uint8_t opcode; - enum x86_decode_cmd cmd; - uint8_t operand_size; - bool is_modrm; - void (*decode_op1)(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op1); - void (*decode_op2)(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op2); - void (*decode_op3)(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op3); - void (*decode_op4)(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op4); - void (*decode_postfix)(CPUX86State *env, struct x86_decode *decode); - uint32_t flags_mask; -}; - -struct decode_x87_tbl { - uint8_t opcode; - uint8_t modrm_reg; - uint8_t modrm_mod; - enum x86_decode_cmd cmd; - uint8_t operand_size; - bool rev; - bool pop; - void (*decode_op1)(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op1); - void (*decode_op2)(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op2); - void (*decode_postfix)(CPUX86State *env, struct x86_decode *decode); - uint32_t flags_mask; -}; - -struct decode_tbl invl_inst = {0x0, 0, 0, false, NULL, NULL, NULL, NULL, - decode_invalid}; - -struct decode_tbl _decode_tbl1[256]; -struct decode_tbl _decode_tbl2[256]; -struct decode_x87_tbl _decode_tbl3[256]; - -static void decode_x87_ins(CPUX86State *env, struct x86_decode *decode) -{ - struct decode_x87_tbl *decoder; - - decode->is_fpu = true; - int mode = decode->modrm.mod == 3 ? 1 : 0; - int index = ((decode->opcode[0] & 0xf) << 4) | (mode << 3) | - decode->modrm.reg; - - decoder = &_decode_tbl3[index]; - - decode->cmd = decoder->cmd; - if (decoder->operand_size) { - decode->operand_size = decoder->operand_size; - } - decode->flags_mask = decoder->flags_mask; - decode->fpop_stack = decoder->pop; - decode->frev = decoder->rev; - - if (decoder->decode_op1) { - decoder->decode_op1(env, decode, &decode->op[0]); - } - if (decoder->decode_op2) { - decoder->decode_op2(env, decode, &decode->op[1]); - } - if (decoder->decode_postfix) { - decoder->decode_postfix(env, decode); - } - - VM_PANIC_ON_EX(!decode->cmd, "x87 opcode %x %x (%x %x) not decoded\n", - decode->opcode[0], decode->modrm.modrm, decoder->modrm_reg, - decoder->modrm_mod); -} - -static void decode_ffgroup(CPUX86State *env, struct x86_decode *decode) -{ - enum x86_decode_cmd group[] = { - X86_DECODE_CMD_INC, - X86_DECODE_CMD_DEC, - X86_DECODE_CMD_CALL_NEAR_ABS_INDIRECT, - X86_DECODE_CMD_CALL_FAR_ABS_INDIRECT, - X86_DECODE_CMD_JMP_NEAR_ABS_INDIRECT, - X86_DECODE_CMD_JMP_FAR_ABS_INDIRECT, - X86_DECODE_CMD_PUSH, - X86_DECODE_CMD_INVL, - X86_DECODE_CMD_INVL - }; - decode->cmd = group[decode->modrm.reg]; - if (decode->modrm.reg > 2) { - decode->flags_mask = 0; - } -} - -static void decode_sldtgroup(CPUX86State *env, struct x86_decode *decode) -{ - - enum x86_decode_cmd group[] = { - X86_DECODE_CMD_SLDT, - X86_DECODE_CMD_STR, - X86_DECODE_CMD_LLDT, - X86_DECODE_CMD_LTR, - X86_DECODE_CMD_VERR, - X86_DECODE_CMD_VERW, - X86_DECODE_CMD_INVL, - X86_DECODE_CMD_INVL - }; - decode->cmd = group[decode->modrm.reg]; -} - -static void decode_lidtgroup(CPUX86State *env, struct x86_decode *decode) -{ - enum x86_decode_cmd group[] = { - X86_DECODE_CMD_SGDT, - X86_DECODE_CMD_SIDT, - X86_DECODE_CMD_LGDT, - X86_DECODE_CMD_LIDT, - X86_DECODE_CMD_SMSW, - X86_DECODE_CMD_LMSW, - X86_DECODE_CMD_LMSW, - X86_DECODE_CMD_INVLPG - }; - decode->cmd = group[decode->modrm.reg]; - if (0xf9 == decode->modrm.modrm) { - decode->opcode[decode->len++] = decode->modrm.modrm; - decode->cmd = X86_DECODE_CMD_RDTSCP; - } -} - -static void decode_btgroup(CPUX86State *env, struct x86_decode *decode) -{ - enum x86_decode_cmd group[] = { - X86_DECODE_CMD_INVL, - X86_DECODE_CMD_INVL, - X86_DECODE_CMD_INVL, - X86_DECODE_CMD_INVL, - X86_DECODE_CMD_BT, - X86_DECODE_CMD_BTS, - X86_DECODE_CMD_BTR, - X86_DECODE_CMD_BTC - }; - decode->cmd = group[decode->modrm.reg]; -} - -static void decode_x87_general(CPUX86State *env, struct x86_decode *decode) -{ - decode->is_fpu = true; -} - -static void decode_x87_modrm_floatp(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - op->type = X87_VAR_FLOATP; -} - -static void decode_x87_modrm_intp(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - op->type = X87_VAR_INTP; -} - -static void decode_x87_modrm_bytep(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - op->type = X87_VAR_BYTEP; -} - -static void decode_x87_modrm_st0(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - op->type = X87_VAR_REG; - op->reg = 0; -} - -static void decode_decode_x87_modrm_st0(CPUX86State *env, - struct x86_decode *decode, - struct x86_decode_op *op) -{ - op->type = X87_VAR_REG; - op->reg = decode->modrm.modrm & 7; -} - - -static void decode_aegroup(CPUX86State *env, struct x86_decode *decode) -{ - decode->is_fpu = true; - switch (decode->modrm.reg) { - case 0: - decode->cmd = X86_DECODE_CMD_FXSAVE; - decode_x87_modrm_bytep(env, decode, &decode->op[0]); - break; - case 1: - decode_x87_modrm_bytep(env, decode, &decode->op[0]); - decode->cmd = X86_DECODE_CMD_FXRSTOR; - break; - case 5: - if (decode->modrm.modrm == 0xe8) { - decode->cmd = X86_DECODE_CMD_LFENCE; - } else { - VM_PANIC("xrstor"); - } - break; - case 6: - VM_PANIC_ON(decode->modrm.modrm != 0xf0); - decode->cmd = X86_DECODE_CMD_MFENCE; - break; - case 7: - if (decode->modrm.modrm == 0xf8) { - decode->cmd = X86_DECODE_CMD_SFENCE; - } else { - decode->cmd = X86_DECODE_CMD_CLFLUSH; - } - break; - default: - VM_PANIC_EX("0xae: reg %d\n", decode->modrm.reg); - break; - } -} - -static void decode_bswap(CPUX86State *env, struct x86_decode *decode) -{ - decode->op[0].type = X86_VAR_REG; - decode->op[0].reg = decode->opcode[1] - 0xc8; - decode->op[0].ptr = get_reg_ref(env, decode->op[0].reg, decode->rex.rex, - decode->rex.b, decode->operand_size); -} - -static void decode_d9_4(CPUX86State *env, struct x86_decode *decode) -{ - switch (decode->modrm.modrm) { - case 0xe0: - /* FCHS */ - decode->cmd = X86_DECODE_CMD_FCHS; - break; - case 0xe1: - decode->cmd = X86_DECODE_CMD_FABS; - break; - case 0xe4: - VM_PANIC("FTST"); - break; - case 0xe5: - /* FXAM */ - decode->cmd = X86_DECODE_CMD_FXAM; - break; - default: - VM_PANIC("FLDENV"); - break; - } -} - -static void decode_db_4(CPUX86State *env, struct x86_decode *decode) -{ - switch (decode->modrm.modrm) { - case 0xe0: - VM_PANIC_EX("unhandled FNENI: %x %x\n", decode->opcode[0], - decode->modrm.modrm); - break; - case 0xe1: - VM_PANIC_EX("unhandled FNDISI: %x %x\n", decode->opcode[0], - decode->modrm.modrm); - break; - case 0xe2: - VM_PANIC_EX("unhandled FCLEX: %x %x\n", decode->opcode[0], - decode->modrm.modrm); - break; - case 0xe3: - decode->cmd = X86_DECODE_CMD_FNINIT; - break; - case 0xe4: - decode->cmd = X86_DECODE_CMD_FNSETPM; - break; - default: - VM_PANIC_EX("unhandled fpu opcode: %x %x\n", decode->opcode[0], - decode->modrm.modrm); - break; - } -} - - -#define RFLAGS_MASK_NONE 0 -#define RFLAGS_MASK_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C) -#define RFLAGS_MASK_LAHF (CC_S | CC_Z | CC_A | CC_P | CC_C) -#define RFLAGS_MASK_CF (CC_C) -#define RFLAGS_MASK_IF (IF_MASK) -#define RFLAGS_MASK_TF (TF_MASK) -#define RFLAGS_MASK_DF (DF_MASK) -#define RFLAGS_MASK_ZF (CC_Z) - -struct decode_tbl _1op_inst[] = { - {0x0, X86_DECODE_CMD_ADD, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, - NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x1, X86_DECODE_CMD_ADD, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, - NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x2, X86_DECODE_CMD_ADD, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, - NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x3, X86_DECODE_CMD_ADD, 0, true, decode_modrm_reg, decode_modrm_rm, NULL, - NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x4, X86_DECODE_CMD_ADD, 1, false, decode_rax, decode_imm8, NULL, NULL, - NULL, RFLAGS_MASK_OSZAPC}, - {0x5, X86_DECODE_CMD_ADD, 0, false, decode_rax, decode_imm, NULL, NULL, - NULL, RFLAGS_MASK_OSZAPC}, - {0x6, X86_DECODE_CMD_PUSH_SEG, 0, false, false, NULL, NULL, NULL, - decode_pushseg, RFLAGS_MASK_NONE}, - {0x7, X86_DECODE_CMD_POP_SEG, 0, false, false, NULL, NULL, NULL, - decode_popseg, RFLAGS_MASK_NONE}, - {0x8, X86_DECODE_CMD_OR, 1, true, decode_modrm_rm, decode_modrm_reg, NULL, - NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x9, X86_DECODE_CMD_OR, 0, true, decode_modrm_rm, decode_modrm_reg, NULL, - NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xa, X86_DECODE_CMD_OR, 1, true, decode_modrm_reg, decode_modrm_rm, NULL, - NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xb, X86_DECODE_CMD_OR, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xc, X86_DECODE_CMD_OR, 1, false, decode_rax, decode_imm8, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xd, X86_DECODE_CMD_OR, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0xe, X86_DECODE_CMD_PUSH_SEG, 0, false, false, - NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, - {0xf, X86_DECODE_CMD_POP_SEG, 0, false, false, - NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, - - {0x10, X86_DECODE_CMD_ADC, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x11, X86_DECODE_CMD_ADC, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x12, X86_DECODE_CMD_ADC, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x13, X86_DECODE_CMD_ADC, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x14, X86_DECODE_CMD_ADC, 1, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x15, X86_DECODE_CMD_ADC, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0x16, X86_DECODE_CMD_PUSH_SEG, 0, false, false, - NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, - {0x17, X86_DECODE_CMD_POP_SEG, 0, false, false, - NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, - - {0x18, X86_DECODE_CMD_SBB, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x19, X86_DECODE_CMD_SBB, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x1a, X86_DECODE_CMD_SBB, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x1b, X86_DECODE_CMD_SBB, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x1c, X86_DECODE_CMD_SBB, 1, false, decode_rax, decode_imm8, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x1d, X86_DECODE_CMD_SBB, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0x1e, X86_DECODE_CMD_PUSH_SEG, 0, false, false, - NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, - {0x1f, X86_DECODE_CMD_POP_SEG, 0, false, false, - NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, - - {0x20, X86_DECODE_CMD_AND, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x21, X86_DECODE_CMD_AND, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x22, X86_DECODE_CMD_AND, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x23, X86_DECODE_CMD_AND, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x24, X86_DECODE_CMD_AND, 1, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x25, X86_DECODE_CMD_AND, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x28, X86_DECODE_CMD_SUB, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x29, X86_DECODE_CMD_SUB, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x2a, X86_DECODE_CMD_SUB, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x2b, X86_DECODE_CMD_SUB, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x2c, X86_DECODE_CMD_SUB, 1, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x2d, X86_DECODE_CMD_SUB, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x2f, X86_DECODE_CMD_DAS, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x30, X86_DECODE_CMD_XOR, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x31, X86_DECODE_CMD_XOR, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x32, X86_DECODE_CMD_XOR, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x33, X86_DECODE_CMD_XOR, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x34, X86_DECODE_CMD_XOR, 1, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x35, X86_DECODE_CMD_XOR, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0x38, X86_DECODE_CMD_CMP, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x39, X86_DECODE_CMD_CMP, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x3a, X86_DECODE_CMD_CMP, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x3b, X86_DECODE_CMD_CMP, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x3c, X86_DECODE_CMD_CMP, 1, false, decode_rax, decode_imm8, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x3d, X86_DECODE_CMD_CMP, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0x3f, X86_DECODE_CMD_AAS, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0x40, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - {0x41, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - {0x42, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - {0x43, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - {0x44, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - {0x45, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - {0x46, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - {0x47, X86_DECODE_CMD_INC, 0, false, - NULL, NULL, NULL, NULL, decode_incgroup, RFLAGS_MASK_OSZAPC}, - - {0x48, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - {0x49, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - {0x4a, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - {0x4b, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - {0x4c, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - {0x4d, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - {0x4e, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - {0x4f, X86_DECODE_CMD_DEC, 0, false, - NULL, NULL, NULL, NULL, decode_decgroup, RFLAGS_MASK_OSZAPC}, - - {0x50, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - {0x51, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - {0x52, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - {0x53, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - {0x54, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - {0x55, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - {0x56, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - {0x57, X86_DECODE_CMD_PUSH, 0, false, - NULL, NULL, NULL, NULL, decode_pushgroup, RFLAGS_MASK_NONE}, - - {0x58, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - {0x59, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - {0x5a, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - {0x5b, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - {0x5c, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - {0x5d, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - {0x5e, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - {0x5f, X86_DECODE_CMD_POP, 0, false, - NULL, NULL, NULL, NULL, decode_popgroup, RFLAGS_MASK_NONE}, - - {0x60, X86_DECODE_CMD_PUSHA, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x61, X86_DECODE_CMD_POPA, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0x68, X86_DECODE_CMD_PUSH, 0, false, decode_imm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x6a, X86_DECODE_CMD_PUSH, 0, false, decode_imm8_signed, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x69, X86_DECODE_CMD_IMUL_3, 0, true, decode_modrm_reg, - decode_modrm_rm, decode_imm, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x6b, X86_DECODE_CMD_IMUL_3, 0, true, decode_modrm_reg, decode_modrm_rm, - decode_imm8_signed, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0x6c, X86_DECODE_CMD_INS, 1, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x6d, X86_DECODE_CMD_INS, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x6e, X86_DECODE_CMD_OUTS, 1, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x6f, X86_DECODE_CMD_OUTS, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0x70, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x71, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x72, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x73, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x74, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x75, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x76, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x77, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x78, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x79, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x7a, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x7b, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x7c, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x7d, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x7e, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x7f, X86_DECODE_CMD_JXX, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - - {0x80, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, - NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, - {0x81, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm, - NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, - {0x82, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, - NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, - {0x83, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8_signed, - NULL, NULL, decode_addgroup, RFLAGS_MASK_OSZAPC}, - {0x84, X86_DECODE_CMD_TST, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x85, X86_DECODE_CMD_TST, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0x86, X86_DECODE_CMD_XCHG, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x87, X86_DECODE_CMD_XCHG, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x88, X86_DECODE_CMD_MOV, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x89, X86_DECODE_CMD_MOV, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x8a, X86_DECODE_CMD_MOV, 1, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x8b, X86_DECODE_CMD_MOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x8c, X86_DECODE_CMD_MOV_FROM_SEG, 0, true, decode_modrm_rm, - decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x8d, X86_DECODE_CMD_LEA, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x8e, X86_DECODE_CMD_MOV_TO_SEG, 0, true, decode_modrm_reg, - decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x8f, X86_DECODE_CMD_POP, 0, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0x90, X86_DECODE_CMD_NOP, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x91, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, - NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, - {0x92, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, - NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, - {0x93, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, - NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, - {0x94, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, - NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, - {0x95, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, - NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, - {0x96, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, - NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, - {0x97, X86_DECODE_CMD_XCHG, 0, false, NULL, decode_rax, - NULL, NULL, decode_xchgroup, RFLAGS_MASK_NONE}, - - {0x98, X86_DECODE_CMD_CBW, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x99, X86_DECODE_CMD_CWD, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0x9a, X86_DECODE_CMD_CALL_FAR, 0, false, NULL, - NULL, NULL, NULL, decode_farjmp, RFLAGS_MASK_NONE}, - - {0x9c, X86_DECODE_CMD_PUSHF, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - /*{0x9d, X86_DECODE_CMD_POPF, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_POPF},*/ - {0x9e, X86_DECODE_CMD_SAHF, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x9f, X86_DECODE_CMD_LAHF, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_LAHF}, - - {0xa0, X86_DECODE_CMD_MOV, 1, false, decode_rax, fetch_moffs, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xa1, X86_DECODE_CMD_MOV, 0, false, decode_rax, fetch_moffs, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xa2, X86_DECODE_CMD_MOV, 1, false, fetch_moffs, decode_rax, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xa3, X86_DECODE_CMD_MOV, 0, false, fetch_moffs, decode_rax, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xa4, X86_DECODE_CMD_MOVS, 1, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xa5, X86_DECODE_CMD_MOVS, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xa6, X86_DECODE_CMD_CMPS, 1, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xa7, X86_DECODE_CMD_CMPS, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xaa, X86_DECODE_CMD_STOS, 1, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xab, X86_DECODE_CMD_STOS, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xac, X86_DECODE_CMD_LODS, 1, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xad, X86_DECODE_CMD_LODS, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xae, X86_DECODE_CMD_SCAS, 1, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xaf, X86_DECODE_CMD_SCAS, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0xa8, X86_DECODE_CMD_TST, 1, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xa9, X86_DECODE_CMD_TST, 0, false, decode_rax, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0xb0, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - {0xb1, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - {0xb2, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - {0xb3, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - {0xb4, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - {0xb5, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - {0xb6, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - {0xb7, X86_DECODE_CMD_MOV, 1, false, NULL, - NULL, NULL, NULL, decode_movgroup8, RFLAGS_MASK_NONE}, - - {0xb8, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - {0xb9, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - {0xba, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - {0xbb, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - {0xbc, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - {0xbd, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - {0xbe, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - {0xbf, X86_DECODE_CMD_MOV, 0, false, NULL, - NULL, NULL, NULL, decode_movgroup, RFLAGS_MASK_NONE}, - - {0xc0, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm8, - NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, - {0xc1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8, - NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, - - {0xc2, X86_DECODE_RET_NEAR, 0, false, decode_imm16, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xc3, X86_DECODE_RET_NEAR, 0, false, NULL, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xc4, X86_DECODE_CMD_LES, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xc5, X86_DECODE_CMD_LDS, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xc6, X86_DECODE_CMD_MOV, 1, true, decode_modrm_rm, decode_imm8, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xc7, X86_DECODE_CMD_MOV, 0, true, decode_modrm_rm, decode_imm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xc8, X86_DECODE_CMD_ENTER, 0, false, decode_imm16, decode_imm8, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xc9, X86_DECODE_CMD_LEAVE, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xca, X86_DECODE_RET_FAR, 0, false, decode_imm16, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xcb, X86_DECODE_RET_FAR, 0, false, decode_imm_0, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xcd, X86_DECODE_CMD_INT, 0, false, decode_imm8, NULL, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - /*{0xcf, X86_DECODE_CMD_IRET, 0, false, NULL, NULL, - NULL, NULL, NULL, RFLAGS_MASK_IRET},*/ - - {0xd0, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_imm_1, - NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, - {0xd1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm_1, - NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, - {0xd2, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, decode_rcx, - NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, - {0xd3, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_rcx, - NULL, NULL, decode_rotgroup, RFLAGS_MASK_OSZAPC}, - - {0xd4, X86_DECODE_CMD_AAM, 0, false, decode_imm8, - NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xd5, X86_DECODE_CMD_AAD, 0, false, decode_imm8, - NULL, NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0xd7, X86_DECODE_CMD_XLAT, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xd8, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - {0xd9, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - {0xda, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - {0xdb, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - {0xdc, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - {0xdd, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - {0xde, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - {0xdf, X86_DECODE_CMD_INVL, 0, true, NULL, - NULL, NULL, NULL, decode_x87_ins, RFLAGS_MASK_NONE}, - - {0xe0, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xe1, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xe2, X86_DECODE_CMD_LOOP, 0, false, decode_imm8_signed, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xe3, X86_DECODE_CMD_JCXZ, 1, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - - {0xe4, X86_DECODE_CMD_IN, 1, false, decode_imm8, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xe5, X86_DECODE_CMD_IN, 0, false, decode_imm8, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xe6, X86_DECODE_CMD_OUT, 1, false, decode_imm8, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xe7, X86_DECODE_CMD_OUT, 0, false, decode_imm8, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xe8, X86_DECODE_CMD_CALL_NEAR, 0, false, decode_imm_signed, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xe9, X86_DECODE_CMD_JMP_NEAR, 0, false, decode_imm_signed, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xea, X86_DECODE_CMD_JMP_FAR, 0, false, - NULL, NULL, NULL, NULL, decode_farjmp, RFLAGS_MASK_NONE}, - {0xeb, X86_DECODE_CMD_JMP_NEAR, 1, false, decode_imm8_signed, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xec, X86_DECODE_CMD_IN, 1, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xed, X86_DECODE_CMD_IN, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xee, X86_DECODE_CMD_OUT, 1, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xef, X86_DECODE_CMD_OUT, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xf4, X86_DECODE_CMD_HLT, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xf5, X86_DECODE_CMD_CMC, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, - - {0xf6, X86_DECODE_CMD_INVL, 1, true, - NULL, NULL, NULL, NULL, decode_f7group, RFLAGS_MASK_OSZAPC}, - {0xf7, X86_DECODE_CMD_INVL, 0, true, - NULL, NULL, NULL, NULL, decode_f7group, RFLAGS_MASK_OSZAPC}, - - {0xf8, X86_DECODE_CMD_CLC, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, - {0xf9, X86_DECODE_CMD_STC, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_CF}, - - {0xfa, X86_DECODE_CMD_CLI, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IF}, - {0xfb, X86_DECODE_CMD_STI, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_IF}, - {0xfc, X86_DECODE_CMD_CLD, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_DF}, - {0xfd, X86_DECODE_CMD_STD, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_DF}, - {0xfe, X86_DECODE_CMD_INVL, 1, true, decode_modrm_rm, - NULL, NULL, NULL, decode_incgroup2, RFLAGS_MASK_OSZAPC}, - {0xff, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, - NULL, NULL, NULL, decode_ffgroup, RFLAGS_MASK_OSZAPC}, -}; - -struct decode_tbl _2op_inst[] = { - {0x0, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, - NULL, NULL, NULL, decode_sldtgroup, RFLAGS_MASK_NONE}, - {0x1, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, - NULL, NULL, NULL, decode_lidtgroup, RFLAGS_MASK_NONE}, - {0x6, X86_DECODE_CMD_CLTS, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_TF}, - {0x9, X86_DECODE_CMD_WBINVD, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x18, X86_DECODE_CMD_PREFETCH, 0, true, - NULL, NULL, NULL, NULL, decode_x87_general, RFLAGS_MASK_NONE}, - {0x1f, X86_DECODE_CMD_NOP, 0, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x20, X86_DECODE_CMD_MOV_FROM_CR, 0, true, decode_modrm_rm, - decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x21, X86_DECODE_CMD_MOV_FROM_DR, 0, true, decode_modrm_rm, - decode_modrm_reg, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x22, X86_DECODE_CMD_MOV_TO_CR, 0, true, decode_modrm_reg, - decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x23, X86_DECODE_CMD_MOV_TO_DR, 0, true, decode_modrm_reg, - decode_modrm_rm, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x30, X86_DECODE_CMD_WRMSR, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x31, X86_DECODE_CMD_RDTSC, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x32, X86_DECODE_CMD_RDMSR, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x40, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x41, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x42, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x43, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x44, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x45, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x46, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x47, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x48, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x49, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x4a, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x4b, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x4c, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x4d, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x4e, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x4f, X86_DECODE_CMD_CMOV, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x77, X86_DECODE_CMD_EMMS, 0, false, - NULL, NULL, NULL, NULL, decode_x87_general, RFLAGS_MASK_NONE}, - {0x82, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x83, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x84, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x85, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x86, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x87, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x88, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x89, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x8a, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x8b, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x8c, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x8d, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x8e, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x8f, X86_DECODE_CMD_JXX, 0, false, - NULL, NULL, NULL, NULL, decode_jxx, RFLAGS_MASK_NONE}, - {0x90, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x91, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x92, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x93, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x94, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x95, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x96, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x97, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x98, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x99, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x9a, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x9b, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x9c, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x9d, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x9e, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0x9f, X86_DECODE_CMD_SETXX, 1, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xb0, X86_DECODE_CMD_CMPXCHG, 1, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xb1, X86_DECODE_CMD_CMPXCHG, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xb6, X86_DECODE_CMD_MOVZX, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xb7, X86_DECODE_CMD_MOVZX, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xb8, X86_DECODE_CMD_POPCNT, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xbe, X86_DECODE_CMD_MOVSX, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xbf, X86_DECODE_CMD_MOVSX, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xa0, X86_DECODE_CMD_PUSH_SEG, 0, false, false, - NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, - {0xa1, X86_DECODE_CMD_POP_SEG, 0, false, false, - NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, - {0xa2, X86_DECODE_CMD_CPUID, 0, false, - NULL, NULL, NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xa3, X86_DECODE_CMD_BT, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_CF}, - {0xa4, X86_DECODE_CMD_SHLD, 0, true, decode_modrm_rm, decode_modrm_reg, - decode_imm8, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xa5, X86_DECODE_CMD_SHLD, 0, true, decode_modrm_rm, decode_modrm_reg, - decode_rcx, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xa8, X86_DECODE_CMD_PUSH_SEG, 0, false, false, - NULL, NULL, NULL, decode_pushseg, RFLAGS_MASK_NONE}, - {0xa9, X86_DECODE_CMD_POP_SEG, 0, false, false, - NULL, NULL, NULL, decode_popseg, RFLAGS_MASK_NONE}, - {0xab, X86_DECODE_CMD_BTS, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_CF}, - {0xac, X86_DECODE_CMD_SHRD, 0, true, decode_modrm_rm, decode_modrm_reg, - decode_imm8, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xad, X86_DECODE_CMD_SHRD, 0, true, decode_modrm_rm, decode_modrm_reg, - decode_rcx, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0xae, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, - NULL, NULL, NULL, decode_aegroup, RFLAGS_MASK_NONE}, - - {0xaf, X86_DECODE_CMD_IMUL_2, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xb2, X86_DECODE_CMD_LSS, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_NONE}, - {0xb3, X86_DECODE_CMD_BTR, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xba, X86_DECODE_CMD_INVL, 0, true, decode_modrm_rm, decode_imm8, - NULL, NULL, decode_btgroup, RFLAGS_MASK_OSZAPC}, - {0xbb, X86_DECODE_CMD_BTC, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xbc, X86_DECODE_CMD_BSF, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - {0xbd, X86_DECODE_CMD_BSR, 0, true, decode_modrm_reg, decode_modrm_rm, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0xc1, X86_DECODE_CMD_XADD, 0, true, decode_modrm_rm, decode_modrm_reg, - NULL, NULL, NULL, RFLAGS_MASK_OSZAPC}, - - {0xc7, X86_DECODE_CMD_CMPXCHG8B, 0, true, decode_modrm_rm, - NULL, NULL, NULL, NULL, RFLAGS_MASK_ZF}, - - {0xc8, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, - {0xc9, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, - {0xca, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, - {0xcb, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, - {0xcc, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, - {0xcd, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, - {0xce, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, - {0xcf, X86_DECODE_CMD_BSWAP, 0, false, - NULL, NULL, NULL, NULL, decode_bswap, RFLAGS_MASK_NONE}, -}; - -struct decode_x87_tbl invl_inst_x87 = {0x0, 0, 0, 0, 0, false, false, NULL, - NULL, decode_invalid, 0}; - -struct decode_x87_tbl _x87_inst[] = { - {0xd8, 0, 3, X86_DECODE_CMD_FADD, 10, false, false, - decode_x87_modrm_st0, decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xd8, 0, 0, X86_DECODE_CMD_FADD, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xd8, 1, 3, X86_DECODE_CMD_FMUL, 10, false, false, decode_x87_modrm_st0, - decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xd8, 1, 0, X86_DECODE_CMD_FMUL, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xd8, 4, 3, X86_DECODE_CMD_FSUB, 10, false, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xd8, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xd8, 5, 3, X86_DECODE_CMD_FSUB, 10, true, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xd8, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0, - decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xd8, 6, 3, X86_DECODE_CMD_FDIV, 10, false, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xd8, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xd8, 7, 3, X86_DECODE_CMD_FDIV, 10, true, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xd8, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0, - decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - - {0xd9, 0, 3, X86_DECODE_CMD_FLD, 10, false, false, - decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 0, 0, X86_DECODE_CMD_FLD, 4, false, false, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xd9, 1, 0, X86_DECODE_CMD_INVL, 10, false, false, - decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 2, 3, X86_DECODE_CMD_INVL, 10, false, false, - decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 2, 0, X86_DECODE_CMD_FST, 4, false, false, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 3, 3, X86_DECODE_CMD_INVL, 10, false, false, - decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 3, 0, X86_DECODE_CMD_FST, 4, false, true, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, - decode_x87_modrm_st0, NULL, decode_d9_4, RFLAGS_MASK_NONE}, - {0xd9, 4, 0, X86_DECODE_CMD_INVL, 4, false, false, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 5, 3, X86_DECODE_CMD_FLDxx, 10, false, false, NULL, NULL, NULL, - RFLAGS_MASK_NONE}, - {0xd9, 5, 0, X86_DECODE_CMD_FLDCW, 2, false, false, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xd9, 7, 3, X86_DECODE_CMD_FNSTCW, 2, false, false, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - {0xd9, 7, 0, X86_DECODE_CMD_FNSTCW, 2, false, false, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xda, 0, 3, X86_DECODE_CMD_FCMOV, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xda, 0, 0, X86_DECODE_CMD_FADD, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xda, 1, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, - decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xda, 1, 0, X86_DECODE_CMD_FMUL, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xda, 2, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xda, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xda, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, - RFLAGS_MASK_NONE}, - {0xda, 4, 0, X86_DECODE_CMD_FSUB, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xda, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true, decode_x87_modrm_st0, - decode_decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xda, 5, 0, X86_DECODE_CMD_FSUB, 4, true, false, decode_x87_modrm_st0, - decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xda, 6, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, - RFLAGS_MASK_NONE}, - {0xda, 6, 0, X86_DECODE_CMD_FDIV, 4, false, false, decode_x87_modrm_st0, - decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xda, 7, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, - RFLAGS_MASK_NONE}, - {0xda, 7, 0, X86_DECODE_CMD_FDIV, 4, true, false, decode_x87_modrm_st0, - decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - - {0xdb, 0, 3, X86_DECODE_CMD_FCMOV, 10, false, false, decode_x87_modrm_st0, - decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdb, 0, 0, X86_DECODE_CMD_FLD, 4, false, false, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdb, 1, 3, X86_DECODE_CMD_FCMOV, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdb, 2, 3, X86_DECODE_CMD_FCMOV, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdb, 2, 0, X86_DECODE_CMD_FST, 4, false, false, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdb, 3, 3, X86_DECODE_CMD_FCMOV, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdb, 3, 0, X86_DECODE_CMD_FST, 4, false, true, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdb, 4, 3, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, - decode_db_4, RFLAGS_MASK_NONE}, - {0xdb, 4, 0, X86_DECODE_CMD_INVL, 10, false, false, NULL, NULL, NULL, - RFLAGS_MASK_NONE}, - {0xdb, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdb, 5, 0, X86_DECODE_CMD_FLD, 10, false, false, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdb, 7, 0, X86_DECODE_CMD_FST, 10, false, true, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xdc, 0, 3, X86_DECODE_CMD_FADD, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdc, 0, 0, X86_DECODE_CMD_FADD, 8, false, false, - decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xdc, 1, 3, X86_DECODE_CMD_FMUL, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdc, 1, 0, X86_DECODE_CMD_FMUL, 8, false, false, - decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xdc, 4, 3, X86_DECODE_CMD_FSUB, 10, true, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdc, 4, 0, X86_DECODE_CMD_FSUB, 8, false, false, - decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xdc, 5, 3, X86_DECODE_CMD_FSUB, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdc, 5, 0, X86_DECODE_CMD_FSUB, 8, true, false, - decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xdc, 6, 3, X86_DECODE_CMD_FDIV, 10, true, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdc, 6, 0, X86_DECODE_CMD_FDIV, 8, false, false, - decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - {0xdc, 7, 3, X86_DECODE_CMD_FDIV, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdc, 7, 0, X86_DECODE_CMD_FDIV, 8, true, false, - decode_x87_modrm_st0, decode_x87_modrm_floatp, NULL, RFLAGS_MASK_NONE}, - - {0xdd, 0, 0, X86_DECODE_CMD_FLD, 8, false, false, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdd, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdd, 2, 3, X86_DECODE_CMD_FST, 10, false, false, - decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdd, 2, 0, X86_DECODE_CMD_FST, 8, false, false, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdd, 3, 3, X86_DECODE_CMD_FST, 10, false, true, - decode_x87_modrm_st0, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdd, 3, 0, X86_DECODE_CMD_FST, 8, false, true, - decode_x87_modrm_floatp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdd, 4, 3, X86_DECODE_CMD_FUCOM, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdd, 4, 0, X86_DECODE_CMD_FRSTOR, 8, false, false, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdd, 5, 3, X86_DECODE_CMD_FUCOM, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdd, 7, 0, X86_DECODE_CMD_FNSTSW, 0, false, false, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdd, 7, 3, X86_DECODE_CMD_FNSTSW, 0, false, false, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - - {0xde, 0, 3, X86_DECODE_CMD_FADD, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xde, 0, 0, X86_DECODE_CMD_FADD, 2, false, false, - decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xde, 1, 3, X86_DECODE_CMD_FMUL, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xde, 1, 0, X86_DECODE_CMD_FMUL, 2, false, false, - decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xde, 4, 3, X86_DECODE_CMD_FSUB, 10, true, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xde, 4, 0, X86_DECODE_CMD_FSUB, 2, false, false, - decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xde, 5, 3, X86_DECODE_CMD_FSUB, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xde, 5, 0, X86_DECODE_CMD_FSUB, 2, true, false, - decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xde, 6, 3, X86_DECODE_CMD_FDIV, 10, true, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xde, 6, 0, X86_DECODE_CMD_FDIV, 2, false, false, - decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - {0xde, 7, 3, X86_DECODE_CMD_FDIV, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xde, 7, 0, X86_DECODE_CMD_FDIV, 2, true, false, - decode_x87_modrm_st0, decode_x87_modrm_intp, NULL, RFLAGS_MASK_NONE}, - - {0xdf, 0, 0, X86_DECODE_CMD_FLD, 2, false, false, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdf, 1, 3, X86_DECODE_CMD_FXCH, 10, false, false, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdf, 2, 3, X86_DECODE_CMD_FST, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdf, 2, 0, X86_DECODE_CMD_FST, 2, false, false, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdf, 3, 3, X86_DECODE_CMD_FST, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdf, 3, 0, X86_DECODE_CMD_FST, 2, false, true, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdf, 4, 3, X86_DECODE_CMD_FNSTSW, 2, false, true, - decode_x87_modrm_bytep, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdf, 5, 3, X86_DECODE_CMD_FUCOMI, 10, false, true, - decode_x87_modrm_st0, decode_x87_modrm_st0, NULL, RFLAGS_MASK_NONE}, - {0xdf, 5, 0, X86_DECODE_CMD_FLD, 8, false, false, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, - {0xdf, 7, 0, X86_DECODE_CMD_FST, 8, false, true, - decode_x87_modrm_intp, NULL, NULL, RFLAGS_MASK_NONE}, -}; - -void calc_modrm_operand16(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - target_ulong ptr = 0; - X86Seg seg = R_DS; - - if (!decode->modrm.mod && 6 == decode->modrm.rm) { - ptr = decode->displacement; - goto calc_addr; - } - - if (decode->displacement_size) { - ptr = sign(decode->displacement, decode->displacement_size); - } - - switch (decode->modrm.rm) { - case 0: - ptr += BX(env) + SI(env); - break; - case 1: - ptr += BX(env) + DI(env); - break; - case 2: - ptr += BP(env) + SI(env); - seg = R_SS; - break; - case 3: - ptr += BP(env) + DI(env); - seg = R_SS; - break; - case 4: - ptr += SI(env); - break; - case 5: - ptr += DI(env); - break; - case 6: - ptr += BP(env); - seg = R_SS; - break; - case 7: - ptr += BX(env); - break; - } -calc_addr: - if (X86_DECODE_CMD_LEA == decode->cmd) { - op->ptr = (uint16_t)ptr; - } else { - op->ptr = decode_linear_addr(env, decode, (uint16_t)ptr, seg); - } -} - -target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present, - int is_extended, int size) -{ - target_ulong ptr = 0; - - if (is_extended) { - reg |= R_R8; - } - - switch (size) { - case 1: - if (is_extended || reg < 4 || rex_present) { - ptr = (target_ulong)&RL(env, reg); - } else { - ptr = (target_ulong)&RH(env, reg - 4); - } - break; - default: - ptr = (target_ulong)&RRX(env, reg); - break; - } - return ptr; -} - -target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present, - int is_extended, int size) -{ - target_ulong val = 0; - memcpy(&val, - (void *)get_reg_ref(env, reg, rex_present, is_extended, size), - size); - return val; -} - -static target_ulong get_sib_val(CPUX86State *env, struct x86_decode *decode, - X86Seg *sel) -{ - target_ulong base = 0; - target_ulong scaled_index = 0; - int addr_size = decode->addressing_size; - int base_reg = decode->sib.base; - int index_reg = decode->sib.index; - - *sel = R_DS; - - if (decode->modrm.mod || base_reg != R_EBP) { - if (decode->rex.b) { - base_reg |= R_R8; - } - if (base_reg == R_ESP || base_reg == R_EBP) { - *sel = R_SS; - } - base = get_reg_val(env, decode->sib.base, decode->rex.rex, - decode->rex.b, addr_size); - } - - if (decode->rex.x) { - index_reg |= R_R8; - } - - if (index_reg != R_ESP) { - scaled_index = get_reg_val(env, index_reg, decode->rex.rex, - decode->rex.x, addr_size) << - decode->sib.scale; - } - return base + scaled_index; -} - -void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - X86Seg seg = R_DS; - target_ulong ptr = 0; - int addr_size = decode->addressing_size; - - if (decode->displacement_size) { - ptr = sign(decode->displacement, decode->displacement_size); - } - - if (4 == decode->modrm.rm) { - ptr += get_sib_val(env, decode, &seg); - } else if (!decode->modrm.mod && 5 == decode->modrm.rm) { - if (x86_is_long_mode(env_cpu(env))) { - ptr += env->eip + decode->len; - } else { - ptr = decode->displacement; - } - } else { - if (decode->modrm.rm == R_EBP || decode->modrm.rm == R_ESP) { - seg = R_SS; - } - ptr += get_reg_val(env, decode->modrm.rm, decode->rex.rex, - decode->rex.b, addr_size); - } - - if (X86_DECODE_CMD_LEA == decode->cmd) { - op->ptr = (uint32_t)ptr; - } else { - op->ptr = decode_linear_addr(env, decode, (uint32_t)ptr, seg); - } -} - -void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - X86Seg seg = R_DS; - int32_t offset = 0; - int mod = decode->modrm.mod; - int rm = decode->modrm.rm; - target_ulong ptr; - int src = decode->modrm.rm; - - if (decode->displacement_size) { - offset = sign(decode->displacement, decode->displacement_size); - } - - if (4 == rm) { - ptr = get_sib_val(env, decode, &seg) + offset; - } else if (0 == mod && 5 == rm) { - ptr = env->eip + decode->len + (int32_t) offset; - } else { - ptr = get_reg_val(env, src, decode->rex.rex, decode->rex.b, 8) + - (int64_t) offset; - } - - if (X86_DECODE_CMD_LEA == decode->cmd) { - op->ptr = ptr; - } else { - op->ptr = decode_linear_addr(env, decode, ptr, seg); - } -} - - -void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op) -{ - if (3 == decode->modrm.mod) { - op->reg = decode->modrm.reg; - op->type = X86_VAR_REG; - op->ptr = get_reg_ref(env, decode->modrm.rm, decode->rex.rex, - decode->rex.b, decode->operand_size); - return; - } - - switch (decode->addressing_size) { - case 2: - calc_modrm_operand16(env, decode, op); - break; - case 4: - calc_modrm_operand32(env, decode, op); - break; - case 8: - calc_modrm_operand64(env, decode, op); - break; - default: - VM_PANIC_EX("unsupported address size %d\n", decode->addressing_size); - break; - } -} - -static void decode_prefix(CPUX86State *env, struct x86_decode *decode) -{ - while (1) { - /* - * REX prefix must come after legacy prefixes. - * REX before legacy is ignored. - * Clear rex to simulate this. - */ - uint8_t byte = decode_byte(env, decode); - switch (byte) { - case PREFIX_LOCK: - decode->lock = byte; - decode->rex.rex = 0; - break; - case PREFIX_REPN: - case PREFIX_REP: - decode->rep = byte; - decode->rex.rex = 0; - break; - case PREFIX_CS_SEG_OVERRIDE: - case PREFIX_SS_SEG_OVERRIDE: - case PREFIX_DS_SEG_OVERRIDE: - case PREFIX_ES_SEG_OVERRIDE: - case PREFIX_FS_SEG_OVERRIDE: - case PREFIX_GS_SEG_OVERRIDE: - decode->segment_override = byte; - decode->rex.rex = 0; - break; - case PREFIX_OP_SIZE_OVERRIDE: - decode->op_size_override = byte; - decode->rex.rex = 0; - break; - case PREFIX_ADDR_SIZE_OVERRIDE: - decode->addr_size_override = byte; - decode->rex.rex = 0; - break; - case PREFIX_REX ... (PREFIX_REX + 0xf): - if (x86_is_long_mode(env_cpu(env))) { - decode->rex.rex = byte; - break; - } - /* fall through when not in long mode */ - default: - decode->len--; - return; - } - } -} - -void set_addressing_size(CPUX86State *env, struct x86_decode *decode) -{ - decode->addressing_size = -1; - if (x86_is_real(env_cpu(env)) || x86_is_v8086(env_cpu(env))) { - if (decode->addr_size_override) { - decode->addressing_size = 4; - } else { - decode->addressing_size = 2; - } - } else if (!x86_is_long_mode(env_cpu(env))) { - /* protected */ - x86_segment_descriptor cs; - emul_ops->read_segment_descriptor(env_cpu(env), &cs, R_CS); - /* check db */ - if (cs.db) { - if (decode->addr_size_override) { - decode->addressing_size = 2; - } else { - decode->addressing_size = 4; - } - } else { - if (decode->addr_size_override) { - decode->addressing_size = 4; - } else { - decode->addressing_size = 2; - } - } - } else { - /* long */ - if (decode->addr_size_override) { - decode->addressing_size = 4; - } else { - decode->addressing_size = 8; - } - } -} - -void set_operand_size(CPUX86State *env, struct x86_decode *decode) -{ - decode->operand_size = -1; - if (x86_is_real(env_cpu(env)) || x86_is_v8086(env_cpu(env))) { - if (decode->op_size_override) { - decode->operand_size = 4; - } else { - decode->operand_size = 2; - } - } else if (!x86_is_long_mode(env_cpu(env))) { - /* protected */ - x86_segment_descriptor cs; - emul_ops->read_segment_descriptor(env_cpu(env), &cs, R_CS); - /* check db */ - if (cs.db) { - if (decode->op_size_override) { - decode->operand_size = 2; - } else{ - decode->operand_size = 4; - } - } else { - if (decode->op_size_override) { - decode->operand_size = 4; - } else { - decode->operand_size = 2; - } - } - } else { - /* long */ - if (decode->op_size_override) { - decode->operand_size = 2; - } else { - decode->operand_size = 4; - } - - if (decode->rex.w) { - decode->operand_size = 8; - } - } -} - -static void decode_sib(CPUX86State *env, struct x86_decode *decode) -{ - if ((decode->modrm.mod != 3) && (4 == decode->modrm.rm) && - (decode->addressing_size != 2)) { - decode->sib.sib = decode_byte(env, decode); - decode->sib_present = true; - } -} - -/* 16 bit modrm */ -int disp16_tbl[4][8] = { - {0, 0, 0, 0, 0, 0, 2, 0}, - {1, 1, 1, 1, 1, 1, 1, 1}, - {2, 2, 2, 2, 2, 2, 2, 2}, - {0, 0, 0, 0, 0, 0, 0, 0} -}; - -/* 32/64-bit modrm */ -int disp32_tbl[4][8] = { - {0, 0, 0, 0, -1, 4, 0, 0}, - {1, 1, 1, 1, 1, 1, 1, 1}, - {4, 4, 4, 4, 4, 4, 4, 4}, - {0, 0, 0, 0, 0, 0, 0, 0} -}; - -static inline void decode_displacement(CPUX86State *env, struct x86_decode *decode) -{ - int addressing_size = decode->addressing_size; - int mod = decode->modrm.mod; - int rm = decode->modrm.rm; - - decode->displacement_size = 0; - switch (addressing_size) { - case 2: - decode->displacement_size = disp16_tbl[mod][rm]; - if (decode->displacement_size) { - decode->displacement = (uint16_t)decode_bytes(env, decode, - decode->displacement_size); - } - break; - case 4: - case 8: - if (-1 == disp32_tbl[mod][rm]) { - if (5 == decode->sib.base) { - decode->displacement_size = 4; - } - } else { - decode->displacement_size = disp32_tbl[mod][rm]; - } - - if (decode->displacement_size) { - decode->displacement = (uint32_t)decode_bytes(env, decode, - decode->displacement_size); - } - break; - } -} - -static inline void decode_modrm(CPUX86State *env, struct x86_decode *decode) -{ - decode->modrm.modrm = decode_byte(env, decode); - decode->is_modrm = true; - - decode_sib(env, decode); - decode_displacement(env, decode); -} - -static inline void decode_opcode_general(CPUX86State *env, - struct x86_decode *decode, - uint8_t opcode, - struct decode_tbl *inst_decoder) -{ - decode->cmd = inst_decoder->cmd; - if (inst_decoder->operand_size) { - decode->operand_size = inst_decoder->operand_size; - } - decode->flags_mask = inst_decoder->flags_mask; - - if (inst_decoder->is_modrm) { - decode_modrm(env, decode); - } - if (inst_decoder->decode_op1) { - inst_decoder->decode_op1(env, decode, &decode->op[0]); - } - if (inst_decoder->decode_op2) { - inst_decoder->decode_op2(env, decode, &decode->op[1]); - } - if (inst_decoder->decode_op3) { - inst_decoder->decode_op3(env, decode, &decode->op[2]); - } - if (inst_decoder->decode_op4) { - inst_decoder->decode_op4(env, decode, &decode->op[3]); - } - if (inst_decoder->decode_postfix) { - inst_decoder->decode_postfix(env, decode); - } -} - -static inline void decode_opcode_1(CPUX86State *env, struct x86_decode *decode, - uint8_t opcode) -{ - struct decode_tbl *inst_decoder = &_decode_tbl1[opcode]; - decode_opcode_general(env, decode, opcode, inst_decoder); -} - - -static inline void decode_opcode_2(CPUX86State *env, struct x86_decode *decode, - uint8_t opcode) -{ - struct decode_tbl *inst_decoder = &_decode_tbl2[opcode]; - decode_opcode_general(env, decode, opcode, inst_decoder); -} - -static void decode_opcodes(CPUX86State *env, struct x86_decode *decode) -{ - uint8_t opcode; - - opcode = decode_byte(env, decode); - decode->opcode[decode->opcode_len++] = opcode; - if (opcode != OPCODE_ESCAPE) { - decode_opcode_1(env, decode, opcode); - } else { - opcode = decode_byte(env, decode); - decode->opcode[decode->opcode_len++] = opcode; - decode_opcode_2(env, decode, opcode); - } -} - -uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode) -{ - memset(decode, 0, sizeof(*decode)); - decode_prefix(env, decode); - set_addressing_size(env, decode); - set_operand_size(env, decode); - - decode_opcodes(env, decode); - - return decode->len; -} - -void init_decoder(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(_decode_tbl1); i++) { - memcpy(&_decode_tbl1[i], &invl_inst, sizeof(invl_inst)); - } - for (i = 0; i < ARRAY_SIZE(_decode_tbl2); i++) { - memcpy(&_decode_tbl2[i], &invl_inst, sizeof(invl_inst)); - } - for (i = 0; i < ARRAY_SIZE(_decode_tbl3); i++) { - memcpy(&_decode_tbl3[i], &invl_inst_x87, sizeof(invl_inst_x87)); - - } - for (i = 0; i < ARRAY_SIZE(_1op_inst); i++) { - _decode_tbl1[_1op_inst[i].opcode] = _1op_inst[i]; - } - for (i = 0; i < ARRAY_SIZE(_2op_inst); i++) { - _decode_tbl2[_2op_inst[i].opcode] = _2op_inst[i]; - } - for (i = 0; i < ARRAY_SIZE(_x87_inst); i++) { - int index = ((_x87_inst[i].opcode & 0xf) << 4) | - ((_x87_inst[i].modrm_mod & 1) << 3) | - _x87_inst[i].modrm_reg; - _decode_tbl3[index] = _x87_inst[i]; - } -} - - -const char *decode_cmd_to_string(enum x86_decode_cmd cmd) -{ - static const char *cmds[] = {"INVL", "PUSH", "PUSH_SEG", "POP", "POP_SEG", - "MOV", "MOVSX", "MOVZX", "CALL_NEAR", "CALL_NEAR_ABS_INDIRECT", - "CALL_FAR_ABS_INDIRECT", "CMD_CALL_FAR", "RET_NEAR", "RET_FAR", "ADD", - "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP", "INC", "DEC", "TST", - "NOT", "NEG", "JMP_NEAR", "JMP_NEAR_ABS_INDIRECT", "JMP_FAR", - "JMP_FAR_ABS_INDIRECT", "LEA", "JXX", "JCXZ", "SETXX", "MOV_TO_SEG", - "MOV_FROM_SEG", "CLI", "STI", "CLD", "STD", "STC", "CLC", "OUT", "IN", - "INS", "OUTS", "LIDT", "SIDT", "LGDT", "SGDT", "SMSW", "LMSW", - "RDTSCP", "INVLPG", "MOV_TO_CR", "MOV_FROM_CR", "MOV_TO_DR", - "MOV_FROM_DR", "PUSHF", "POPF", "CPUID", "ROL", "ROR", "RCL", "RCR", - "SHL", "SAL", "SHR", "SHRD", "SHLD", "SAR", "DIV", "IDIV", "MUL", - "IMUL_3", "IMUL_2", "IMUL_1", "MOVS", "CMPS", "SCAS", "LODS", "STOS", - "BSWAP", "XCHG", "RDTSC", "RDMSR", "WRMSR", "ENTER", "LEAVE", "BT", - "BTS", "BTC", "BTR", "BSF", "BSR", "IRET", "INT", "POPA", "PUSHA", - "CWD", "CBW", "DAS", "AAD", "AAM", "AAS", "LOOP", "SLDT", "STR", "LLDT", - "LTR", "VERR", "VERW", "SAHF", "LAHF", "WBINVD", "LDS", "LSS", "LES", - "LGS", "LFS", "CMC", "XLAT", "NOP", "CMOV", "CLTS", "XADD", "HLT", - "CMPXCHG8B", "CMPXCHG", "POPCNT", "FNINIT", "FLD", "FLDxx", "FNSTCW", - "FNSTSW", "FNSETPM", "FSAVE", "FRSTOR", "FXSAVE", "FXRSTOR", "FDIV", - "FMUL", "FSUB", "FADD", "EMMS", "MFENCE", "SFENCE", "LFENCE", - "PREFETCH", "FST", "FABS", "FUCOM", "FUCOMI", "FLDCW", - "FXCH", "FCHS", "FCMOV", "FRNDINT", "FXAM", "LAST"}; - return cmds[cmd]; -} - -target_ulong decode_linear_addr(CPUX86State *env, struct x86_decode *decode, - target_ulong addr, X86Seg seg) -{ - switch (decode->segment_override) { - case PREFIX_CS_SEG_OVERRIDE: - seg = R_CS; - break; - case PREFIX_SS_SEG_OVERRIDE: - seg = R_SS; - break; - case PREFIX_DS_SEG_OVERRIDE: - seg = R_DS; - break; - case PREFIX_ES_SEG_OVERRIDE: - seg = R_ES; - break; - case PREFIX_FS_SEG_OVERRIDE: - seg = R_FS; - break; - case PREFIX_GS_SEG_OVERRIDE: - seg = R_GS; - break; - default: - break; - } - return linear_addr_size(env_cpu(env), addr, decode->addressing_size, seg); -} diff --git a/target/i386/hvf/x86_decode.h b/target/i386/hvf/x86_decode.h deleted file mode 100644 index 930d965164..0000000000 --- a/target/i386/hvf/x86_decode.h +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (C) 2016 Veertu Inc, - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef X86_EMU_DECODE_H -#define X86_EMU_DECODE_H - -#include "cpu.h" -#include "x86.h" - -typedef enum x86_prefix { - /* group 1 */ - PREFIX_LOCK = 0xf0, - PREFIX_REPN = 0xf2, - PREFIX_REP = 0xf3, - /* group 2 */ - PREFIX_CS_SEG_OVERRIDE = 0x2e, - PREFIX_SS_SEG_OVERRIDE = 0x36, - PREFIX_DS_SEG_OVERRIDE = 0x3e, - PREFIX_ES_SEG_OVERRIDE = 0x26, - PREFIX_FS_SEG_OVERRIDE = 0x64, - PREFIX_GS_SEG_OVERRIDE = 0x65, - /* group 3 */ - PREFIX_OP_SIZE_OVERRIDE = 0x66, - /* group 4 */ - PREFIX_ADDR_SIZE_OVERRIDE = 0x67, - - PREFIX_REX = 0x40, -} x86_prefix; - -enum x86_decode_cmd { - X86_DECODE_CMD_INVL = 0, - - X86_DECODE_CMD_PUSH, - X86_DECODE_CMD_PUSH_SEG, - X86_DECODE_CMD_POP, - X86_DECODE_CMD_POP_SEG, - X86_DECODE_CMD_MOV, - X86_DECODE_CMD_MOVSX, - X86_DECODE_CMD_MOVZX, - X86_DECODE_CMD_CALL_NEAR, - X86_DECODE_CMD_CALL_NEAR_ABS_INDIRECT, - X86_DECODE_CMD_CALL_FAR_ABS_INDIRECT, - X86_DECODE_CMD_CALL_FAR, - X86_DECODE_RET_NEAR, - X86_DECODE_RET_FAR, - X86_DECODE_CMD_ADD, - X86_DECODE_CMD_OR, - X86_DECODE_CMD_ADC, - X86_DECODE_CMD_SBB, - X86_DECODE_CMD_AND, - X86_DECODE_CMD_SUB, - X86_DECODE_CMD_XOR, - X86_DECODE_CMD_CMP, - X86_DECODE_CMD_INC, - X86_DECODE_CMD_DEC, - X86_DECODE_CMD_TST, - X86_DECODE_CMD_NOT, - X86_DECODE_CMD_NEG, - X86_DECODE_CMD_JMP_NEAR, - X86_DECODE_CMD_JMP_NEAR_ABS_INDIRECT, - X86_DECODE_CMD_JMP_FAR, - X86_DECODE_CMD_JMP_FAR_ABS_INDIRECT, - X86_DECODE_CMD_LEA, - X86_DECODE_CMD_JXX, - X86_DECODE_CMD_JCXZ, - X86_DECODE_CMD_SETXX, - X86_DECODE_CMD_MOV_TO_SEG, - X86_DECODE_CMD_MOV_FROM_SEG, - X86_DECODE_CMD_CLI, - X86_DECODE_CMD_STI, - X86_DECODE_CMD_CLD, - X86_DECODE_CMD_STD, - X86_DECODE_CMD_STC, - X86_DECODE_CMD_CLC, - X86_DECODE_CMD_OUT, - X86_DECODE_CMD_IN, - X86_DECODE_CMD_INS, - X86_DECODE_CMD_OUTS, - X86_DECODE_CMD_LIDT, - X86_DECODE_CMD_SIDT, - X86_DECODE_CMD_LGDT, - X86_DECODE_CMD_SGDT, - X86_DECODE_CMD_SMSW, - X86_DECODE_CMD_LMSW, - X86_DECODE_CMD_RDTSCP, - X86_DECODE_CMD_INVLPG, - X86_DECODE_CMD_MOV_TO_CR, - X86_DECODE_CMD_MOV_FROM_CR, - X86_DECODE_CMD_MOV_TO_DR, - X86_DECODE_CMD_MOV_FROM_DR, - X86_DECODE_CMD_PUSHF, - X86_DECODE_CMD_POPF, - X86_DECODE_CMD_CPUID, - X86_DECODE_CMD_ROL, - X86_DECODE_CMD_ROR, - X86_DECODE_CMD_RCL, - X86_DECODE_CMD_RCR, - X86_DECODE_CMD_SHL, - X86_DECODE_CMD_SAL, - X86_DECODE_CMD_SHR, - X86_DECODE_CMD_SHRD, - X86_DECODE_CMD_SHLD, - X86_DECODE_CMD_SAR, - X86_DECODE_CMD_DIV, - X86_DECODE_CMD_IDIV, - X86_DECODE_CMD_MUL, - X86_DECODE_CMD_IMUL_3, - X86_DECODE_CMD_IMUL_2, - X86_DECODE_CMD_IMUL_1, - X86_DECODE_CMD_MOVS, - X86_DECODE_CMD_CMPS, - X86_DECODE_CMD_SCAS, - X86_DECODE_CMD_LODS, - X86_DECODE_CMD_STOS, - X86_DECODE_CMD_BSWAP, - X86_DECODE_CMD_XCHG, - X86_DECODE_CMD_RDTSC, - X86_DECODE_CMD_RDMSR, - X86_DECODE_CMD_WRMSR, - X86_DECODE_CMD_ENTER, - X86_DECODE_CMD_LEAVE, - X86_DECODE_CMD_BT, - X86_DECODE_CMD_BTS, - X86_DECODE_CMD_BTC, - X86_DECODE_CMD_BTR, - X86_DECODE_CMD_BSF, - X86_DECODE_CMD_BSR, - X86_DECODE_CMD_IRET, - X86_DECODE_CMD_INT, - X86_DECODE_CMD_POPA, - X86_DECODE_CMD_PUSHA, - X86_DECODE_CMD_CWD, - X86_DECODE_CMD_CBW, - X86_DECODE_CMD_DAS, - X86_DECODE_CMD_AAD, - X86_DECODE_CMD_AAM, - X86_DECODE_CMD_AAS, - X86_DECODE_CMD_LOOP, - X86_DECODE_CMD_SLDT, - X86_DECODE_CMD_STR, - X86_DECODE_CMD_LLDT, - X86_DECODE_CMD_LTR, - X86_DECODE_CMD_VERR, - X86_DECODE_CMD_VERW, - X86_DECODE_CMD_SAHF, - X86_DECODE_CMD_LAHF, - X86_DECODE_CMD_WBINVD, - X86_DECODE_CMD_LDS, - X86_DECODE_CMD_LSS, - X86_DECODE_CMD_LES, - X86_DECODE_XMD_LGS, - X86_DECODE_CMD_LFS, - X86_DECODE_CMD_CMC, - X86_DECODE_CMD_XLAT, - X86_DECODE_CMD_NOP, - X86_DECODE_CMD_CMOV, - X86_DECODE_CMD_CLTS, - X86_DECODE_CMD_XADD, - X86_DECODE_CMD_HLT, - X86_DECODE_CMD_CMPXCHG8B, - X86_DECODE_CMD_CMPXCHG, - X86_DECODE_CMD_POPCNT, - - X86_DECODE_CMD_FNINIT, - X86_DECODE_CMD_FLD, - X86_DECODE_CMD_FLDxx, - X86_DECODE_CMD_FNSTCW, - X86_DECODE_CMD_FNSTSW, - X86_DECODE_CMD_FNSETPM, - X86_DECODE_CMD_FSAVE, - X86_DECODE_CMD_FRSTOR, - X86_DECODE_CMD_FXSAVE, - X86_DECODE_CMD_FXRSTOR, - X86_DECODE_CMD_FDIV, - X86_DECODE_CMD_FMUL, - X86_DECODE_CMD_FSUB, - X86_DECODE_CMD_FADD, - X86_DECODE_CMD_EMMS, - X86_DECODE_CMD_MFENCE, - X86_DECODE_CMD_SFENCE, - X86_DECODE_CMD_LFENCE, - X86_DECODE_CMD_PREFETCH, - X86_DECODE_CMD_CLFLUSH, - X86_DECODE_CMD_FST, - X86_DECODE_CMD_FABS, - X86_DECODE_CMD_FUCOM, - X86_DECODE_CMD_FUCOMI, - X86_DECODE_CMD_FLDCW, - X86_DECODE_CMD_FXCH, - X86_DECODE_CMD_FCHS, - X86_DECODE_CMD_FCMOV, - X86_DECODE_CMD_FRNDINT, - X86_DECODE_CMD_FXAM, - - X86_DECODE_CMD_LAST, -}; - -const char *decode_cmd_to_string(enum x86_decode_cmd cmd); - -typedef struct x86_modrm { - union { - uint8_t modrm; - struct { - uint8_t rm:3; - uint8_t reg:3; - uint8_t mod:2; - }; - }; -} __attribute__ ((__packed__)) x86_modrm; - -typedef struct x86_sib { - union { - uint8_t sib; - struct { - uint8_t base:3; - uint8_t index:3; - uint8_t scale:2; - }; - }; -} __attribute__ ((__packed__)) x86_sib; - -typedef struct x86_rex { - union { - uint8_t rex; - struct { - uint8_t b:1; - uint8_t x:1; - uint8_t r:1; - uint8_t w:1; - uint8_t unused:4; - }; - }; -} __attribute__ ((__packed__)) x86_rex; - -typedef enum x86_var_type { - X86_VAR_IMMEDIATE, - X86_VAR_OFFSET, - X86_VAR_REG, - X86_VAR_RM, - - /* for floating point computations */ - X87_VAR_REG, - X87_VAR_FLOATP, - X87_VAR_INTP, - X87_VAR_BYTEP, -} x86_var_type; - -typedef struct x86_decode_op { - enum x86_var_type type; - int size; - - int reg; - target_ulong val; - - target_ulong ptr; -} x86_decode_op; - -typedef struct x86_decode { - int len; - uint8_t opcode[4]; - uint8_t opcode_len; - enum x86_decode_cmd cmd; - int addressing_size; - int operand_size; - int lock; - int rep; - int op_size_override; - int addr_size_override; - int segment_override; - int control_change_inst; - bool fwait; - bool fpop_stack; - bool frev; - - uint32_t displacement; - uint8_t displacement_size; - struct x86_rex rex; - bool is_modrm; - bool sib_present; - struct x86_sib sib; - struct x86_modrm modrm; - struct x86_decode_op op[4]; - bool is_fpu; - uint32_t flags_mask; - -} x86_decode; - -uint64_t sign(uint64_t val, int size); - -uint32_t decode_instruction(CPUX86State *env, struct x86_decode *decode); - -target_ulong get_reg_ref(CPUX86State *env, int reg, int rex_present, - int is_extended, int size); -target_ulong get_reg_val(CPUX86State *env, int reg, int rex_present, - int is_extended, int size); -void calc_modrm_operand(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op); -target_ulong decode_linear_addr(CPUX86State *env, struct x86_decode *decode, - target_ulong addr, enum X86Seg seg); - -void init_decoder(void); -void calc_modrm_operand16(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op); -void calc_modrm_operand32(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op); -void calc_modrm_operand64(CPUX86State *env, struct x86_decode *decode, - struct x86_decode_op *op); -void set_addressing_size(CPUX86State *env, struct x86_decode *decode); -void set_operand_size(CPUX86State *env, struct x86_decode *decode); - -#endif diff --git a/target/i386/hvf/x86_descr.h b/target/i386/hvf/x86_descr.h index ce5de98349..24af4946cd 100644 --- a/target/i386/hvf/x86_descr.h +++ b/target/i386/hvf/x86_descr.h @@ -19,7 +19,7 @@ #ifndef HVF_X86_DESCR_H #define HVF_X86_DESCR_H -#include "x86.h" +#include "emulate/x86.h" typedef struct vmx_segment { uint16_t sel; diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c deleted file mode 100644 index 26a4876aac..0000000000 --- a/target/i386/hvf/x86_emu.c +++ /dev/null @@ -1,1259 +0,0 @@ -/* - * Copyright (C) 2016 Veertu Inc, - * Copyright (C) 2017 Google Inc, - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001-2012 The Bochs Project -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA -///////////////////////////////////////////////////////////////////////// - -#include "qemu/osdep.h" -#include "panic.h" -#include "x86_decode.h" -#include "x86.h" -#include "x86_emu.h" -#include "x86_flags.h" - -#define EXEC_2OP_FLAGS_CMD(env, decode, cmd, FLAGS_FUNC, save_res) \ -{ \ - fetch_operands(env, decode, 2, true, true, false); \ - switch (decode->operand_size) { \ - case 1: \ - { \ - uint8_t v1 = (uint8_t)decode->op[0].val; \ - uint8_t v2 = (uint8_t)decode->op[1].val; \ - uint8_t diff = v1 cmd v2; \ - if (save_res) { \ - write_val_ext(env, decode->op[0].ptr, diff, 1); \ - } \ - FLAGS_FUNC##8(env, v1, v2, diff); \ - break; \ - } \ - case 2: \ - { \ - uint16_t v1 = (uint16_t)decode->op[0].val; \ - uint16_t v2 = (uint16_t)decode->op[1].val; \ - uint16_t diff = v1 cmd v2; \ - if (save_res) { \ - write_val_ext(env, decode->op[0].ptr, diff, 2); \ - } \ - FLAGS_FUNC##16(env, v1, v2, diff); \ - break; \ - } \ - case 4: \ - { \ - uint32_t v1 = (uint32_t)decode->op[0].val; \ - uint32_t v2 = (uint32_t)decode->op[1].val; \ - uint32_t diff = v1 cmd v2; \ - if (save_res) { \ - write_val_ext(env, decode->op[0].ptr, diff, 4); \ - } \ - FLAGS_FUNC##32(env, v1, v2, diff); \ - break; \ - } \ - default: \ - VM_PANIC("bad size\n"); \ - } \ -} \ - -target_ulong read_reg(CPUX86State *env, int reg, int size) -{ - switch (size) { - case 1: - return x86_reg(env, reg)->lx; - case 2: - return x86_reg(env, reg)->rx; - case 4: - return x86_reg(env, reg)->erx; - case 8: - return x86_reg(env, reg)->rrx; - default: - abort(); - } - return 0; -} - -void write_reg(CPUX86State *env, int reg, target_ulong val, int size) -{ - switch (size) { - case 1: - x86_reg(env, reg)->lx = val; - break; - case 2: - x86_reg(env, reg)->rx = val; - break; - case 4: - x86_reg(env, reg)->rrx = (uint32_t)val; - break; - case 8: - x86_reg(env, reg)->rrx = val; - break; - default: - abort(); - } -} - -target_ulong read_val_from_reg(target_ulong reg_ptr, int size) -{ - target_ulong val; - - switch (size) { - case 1: - val = *(uint8_t *)reg_ptr; - break; - case 2: - val = *(uint16_t *)reg_ptr; - break; - case 4: - val = *(uint32_t *)reg_ptr; - break; - case 8: - val = *(uint64_t *)reg_ptr; - break; - default: - abort(); - } - return val; -} - -void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size) -{ - switch (size) { - case 1: - *(uint8_t *)reg_ptr = val; - break; - case 2: - *(uint16_t *)reg_ptr = val; - break; - case 4: - *(uint64_t *)reg_ptr = (uint32_t)val; - break; - case 8: - *(uint64_t *)reg_ptr = val; - break; - default: - abort(); - } -} - -static bool is_host_reg(CPUX86State *env, target_ulong ptr) -{ - return (ptr - (target_ulong)&env->regs[0]) < sizeof(env->regs); -} - -void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size) -{ - if (is_host_reg(env, ptr)) { - write_val_to_reg(ptr, val, size); - return; - } - emul_ops->write_mem(env_cpu(env), &val, ptr, size); -} - -uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes) -{ - emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes); - return env->emu_mmio_buf; -} - - -target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size) -{ - target_ulong val; - uint8_t *mmio_ptr; - - if (is_host_reg(env, ptr)) { - return read_val_from_reg(ptr, size); - } - - mmio_ptr = read_mmio(env, ptr, size); - switch (size) { - case 1: - val = *(uint8_t *)mmio_ptr; - break; - case 2: - val = *(uint16_t *)mmio_ptr; - break; - case 4: - val = *(uint32_t *)mmio_ptr; - break; - case 8: - val = *(uint64_t *)mmio_ptr; - break; - default: - VM_PANIC("bad size\n"); - break; - } - return val; -} - -static void fetch_operands(CPUX86State *env, struct x86_decode *decode, - int n, bool val_op0, bool val_op1, bool val_op2) -{ - int i; - bool calc_val[3] = {val_op0, val_op1, val_op2}; - - for (i = 0; i < n; i++) { - switch (decode->op[i].type) { - case X86_VAR_IMMEDIATE: - break; - case X86_VAR_REG: - VM_PANIC_ON(!decode->op[i].ptr); - if (calc_val[i]) { - decode->op[i].val = read_val_from_reg(decode->op[i].ptr, - decode->operand_size); - } - break; - case X86_VAR_RM: - calc_modrm_operand(env, decode, &decode->op[i]); - if (calc_val[i]) { - decode->op[i].val = read_val_ext(env, decode->op[i].ptr, - decode->operand_size); - } - break; - case X86_VAR_OFFSET: - decode->op[i].ptr = decode_linear_addr(env, decode, - decode->op[i].ptr, - R_DS); - if (calc_val[i]) { - decode->op[i].val = read_val_ext(env, decode->op[i].ptr, - decode->operand_size); - } - break; - default: - break; - } - } -} - -static void exec_mov(CPUX86State *env, struct x86_decode *decode) -{ - fetch_operands(env, decode, 2, false, true, false); - write_val_ext(env, decode->op[0].ptr, decode->op[1].val, - decode->operand_size); - - env->eip += decode->len; -} - -static void exec_add(CPUX86State *env, struct x86_decode *decode) -{ - EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true); - env->eip += decode->len; -} - -static void exec_or(CPUX86State *env, struct x86_decode *decode) -{ - EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true); - env->eip += decode->len; -} - -static void exec_adc(CPUX86State *env, struct x86_decode *decode) -{ - EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true); - env->eip += decode->len; -} - -static void exec_sbb(CPUX86State *env, struct x86_decode *decode) -{ - EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true); - env->eip += decode->len; -} - -static void exec_and(CPUX86State *env, struct x86_decode *decode) -{ - EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true); - env->eip += decode->len; -} - -static void exec_sub(CPUX86State *env, struct x86_decode *decode) -{ - EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true); - env->eip += decode->len; -} - -static void exec_xor(CPUX86State *env, struct x86_decode *decode) -{ - EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true); - env->eip += decode->len; -} - -static void exec_neg(CPUX86State *env, struct x86_decode *decode) -{ - /*EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);*/ - int32_t val; - fetch_operands(env, decode, 2, true, true, false); - - val = 0 - sign(decode->op[1].val, decode->operand_size); - write_val_ext(env, decode->op[1].ptr, val, decode->operand_size); - - if (4 == decode->operand_size) { - SET_FLAGS_OSZAPC_SUB32(env, 0, 0 - val, val); - } else if (2 == decode->operand_size) { - SET_FLAGS_OSZAPC_SUB16(env, 0, 0 - val, val); - } else if (1 == decode->operand_size) { - SET_FLAGS_OSZAPC_SUB8(env, 0, 0 - val, val); - } else { - VM_PANIC("bad op size\n"); - } - - /*lflags_to_rflags(env);*/ - env->eip += decode->len; -} - -static void exec_cmp(CPUX86State *env, struct x86_decode *decode) -{ - EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); - env->eip += decode->len; -} - -static void exec_inc(CPUX86State *env, struct x86_decode *decode) -{ - decode->op[1].type = X86_VAR_IMMEDIATE; - decode->op[1].val = 0; - - EXEC_2OP_FLAGS_CMD(env, decode, +1+, SET_FLAGS_OSZAP_ADD, true); - - env->eip += decode->len; -} - -static void exec_dec(CPUX86State *env, struct x86_decode *decode) -{ - decode->op[1].type = X86_VAR_IMMEDIATE; - decode->op[1].val = 0; - - EXEC_2OP_FLAGS_CMD(env, decode, -1-, SET_FLAGS_OSZAP_SUB, true); - env->eip += decode->len; -} - -static void exec_tst(CPUX86State *env, struct x86_decode *decode) -{ - EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false); - env->eip += decode->len; -} - -static void exec_not(CPUX86State *env, struct x86_decode *decode) -{ - fetch_operands(env, decode, 1, true, false, false); - - write_val_ext(env, decode->op[0].ptr, ~decode->op[0].val, - decode->operand_size); - env->eip += decode->len; -} - -void exec_movzx(CPUX86State *env, struct x86_decode *decode) -{ - int src_op_size; - int op_size = decode->operand_size; - - fetch_operands(env, decode, 1, false, false, false); - - if (0xb6 == decode->opcode[1]) { - src_op_size = 1; - } else { - src_op_size = 2; - } - decode->operand_size = src_op_size; - calc_modrm_operand(env, decode, &decode->op[1]); - decode->op[1].val = read_val_ext(env, decode->op[1].ptr, src_op_size); - write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size); - - env->eip += decode->len; -} - -static void exec_out(CPUX86State *env, struct x86_decode *decode) -{ - switch (decode->opcode[0]) { - case 0xe6: - emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1); - break; - case 0xe7: - emul_ops->handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1, - decode->operand_size, 1); - break; - case 0xee: - emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1); - break; - case 0xef: - emul_ops->handle_io(env_cpu(env), DX(env), &RAX(env), 1, - decode->operand_size, 1); - break; - default: - VM_PANIC("Bad out opcode\n"); - break; - } - env->eip += decode->len; -} - -static void exec_in(CPUX86State *env, struct x86_decode *decode) -{ - target_ulong val = 0; - switch (decode->opcode[0]) { - case 0xe4: - emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1); - break; - case 0xe5: - emul_ops->handle_io(env_cpu(env), decode->op[0].val, &val, 0, - decode->operand_size, 1); - if (decode->operand_size == 2) { - AX(env) = val; - } else { - RAX(env) = (uint32_t)val; - } - break; - case 0xec: - emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1); - break; - case 0xed: - emul_ops->handle_io(env_cpu(env), DX(env), &val, 0, - decode->operand_size, 1); - if (decode->operand_size == 2) { - AX(env) = val; - } else { - RAX(env) = (uint32_t)val; - } - - break; - default: - VM_PANIC("Bad in opcode\n"); - break; - } - - env->eip += decode->len; -} - -static inline void string_increment_reg(CPUX86State *env, int reg, - struct x86_decode *decode) -{ - target_ulong val = read_reg(env, reg, decode->addressing_size); - if (env->eflags & DF_MASK) { - val -= decode->operand_size; - } else { - val += decode->operand_size; - } - write_reg(env, reg, val, decode->addressing_size); -} - -static inline void string_rep(CPUX86State *env, struct x86_decode *decode, - void (*func)(CPUX86State *env, - struct x86_decode *ins), int rep) -{ - target_ulong rcx = read_reg(env, R_ECX, decode->addressing_size); - while (rcx--) { - func(env, decode); - write_reg(env, R_ECX, rcx, decode->addressing_size); - if ((PREFIX_REP == rep) && !get_ZF(env)) { - break; - } - if ((PREFIX_REPN == rep) && get_ZF(env)) { - break; - } - } -} - -static void exec_ins_single(CPUX86State *env, struct x86_decode *decode) -{ - target_ulong addr = linear_addr_size(env_cpu(env), RDI(env), - decode->addressing_size, R_ES); - - emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0, - decode->operand_size, 1); - emul_ops->write_mem(env_cpu(env), env->emu_mmio_buf, addr, - decode->operand_size); - - string_increment_reg(env, R_EDI, decode); -} - -static void exec_ins(CPUX86State *env, struct x86_decode *decode) -{ - if (decode->rep) { - string_rep(env, decode, exec_ins_single, 0); - } else { - exec_ins_single(env, decode); - } - - env->eip += decode->len; -} - -static void exec_outs_single(CPUX86State *env, struct x86_decode *decode) -{ - target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS); - - emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, addr, - decode->operand_size); - emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1, - decode->operand_size, 1); - - string_increment_reg(env, R_ESI, decode); -} - -static void exec_outs(CPUX86State *env, struct x86_decode *decode) -{ - if (decode->rep) { - string_rep(env, decode, exec_outs_single, 0); - } else { - exec_outs_single(env, decode); - } - - env->eip += decode->len; -} - -static void exec_movs_single(CPUX86State *env, struct x86_decode *decode) -{ - target_ulong src_addr; - target_ulong dst_addr; - target_ulong val; - - src_addr = decode_linear_addr(env, decode, RSI(env), R_DS); - dst_addr = linear_addr_size(env_cpu(env), RDI(env), - decode->addressing_size, R_ES); - - val = read_val_ext(env, src_addr, decode->operand_size); - write_val_ext(env, dst_addr, val, decode->operand_size); - - string_increment_reg(env, R_ESI, decode); - string_increment_reg(env, R_EDI, decode); -} - -static void exec_movs(CPUX86State *env, struct x86_decode *decode) -{ - if (decode->rep) { - string_rep(env, decode, exec_movs_single, 0); - } else { - exec_movs_single(env, decode); - } - - env->eip += decode->len; -} - -static void exec_cmps_single(CPUX86State *env, struct x86_decode *decode) -{ - target_ulong src_addr; - target_ulong dst_addr; - - src_addr = decode_linear_addr(env, decode, RSI(env), R_DS); - dst_addr = linear_addr_size(env_cpu(env), RDI(env), - decode->addressing_size, R_ES); - - decode->op[0].type = X86_VAR_IMMEDIATE; - decode->op[0].val = read_val_ext(env, src_addr, decode->operand_size); - decode->op[1].type = X86_VAR_IMMEDIATE; - decode->op[1].val = read_val_ext(env, dst_addr, decode->operand_size); - - EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); - - string_increment_reg(env, R_ESI, decode); - string_increment_reg(env, R_EDI, decode); -} - -static void exec_cmps(CPUX86State *env, struct x86_decode *decode) -{ - if (decode->rep) { - string_rep(env, decode, exec_cmps_single, decode->rep); - } else { - exec_cmps_single(env, decode); - } - env->eip += decode->len; -} - - -static void exec_stos_single(CPUX86State *env, struct x86_decode *decode) -{ - target_ulong addr; - target_ulong val; - - addr = linear_addr_size(env_cpu(env), RDI(env), - decode->addressing_size, R_ES); - val = read_reg(env, R_EAX, decode->operand_size); - emul_ops->write_mem(env_cpu(env), &val, addr, decode->operand_size); - - string_increment_reg(env, R_EDI, decode); -} - - -static void exec_stos(CPUX86State *env, struct x86_decode *decode) -{ - if (decode->rep) { - string_rep(env, decode, exec_stos_single, 0); - } else { - exec_stos_single(env, decode); - } - - env->eip += decode->len; -} - -static void exec_scas_single(CPUX86State *env, struct x86_decode *decode) -{ - target_ulong addr; - - addr = linear_addr_size(env_cpu(env), RDI(env), - decode->addressing_size, R_ES); - decode->op[1].type = X86_VAR_IMMEDIATE; - emul_ops->read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size); - - EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); - string_increment_reg(env, R_EDI, decode); -} - -static void exec_scas(CPUX86State *env, struct x86_decode *decode) -{ - decode->op[0].type = X86_VAR_REG; - decode->op[0].reg = R_EAX; - if (decode->rep) { - string_rep(env, decode, exec_scas_single, decode->rep); - } else { - exec_scas_single(env, decode); - } - - env->eip += decode->len; -} - -static void exec_lods_single(CPUX86State *env, struct x86_decode *decode) -{ - target_ulong addr; - target_ulong val = 0; - - addr = decode_linear_addr(env, decode, RSI(env), R_DS); - emul_ops->read_mem(env_cpu(env), &val, addr, decode->operand_size); - write_reg(env, R_EAX, val, decode->operand_size); - - string_increment_reg(env, R_ESI, decode); -} - -static void exec_lods(CPUX86State *env, struct x86_decode *decode) -{ - if (decode->rep) { - string_rep(env, decode, exec_lods_single, 0); - } else { - exec_lods_single(env, decode); - } - - env->eip += decode->len; -} - -void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code) -{ - env->exception_nr = exception_index; - env->error_code = error_code; - env->has_error_code = true; - env->exception_injected = 1; -} - -static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode) -{ - emul_ops->simulate_rdmsr(env_cpu(env)); - env->eip += decode->len; -} - -static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode) -{ - emul_ops->simulate_wrmsr(env_cpu(env)); - env->eip += decode->len; -} - -/* - * flag: - * 0 - bt, 1 - btc, 2 - bts, 3 - btr - */ -static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag) -{ - int32_t displacement; - uint8_t index; - bool cf; - int mask = (4 == decode->operand_size) ? 0x1f : 0xf; - - VM_PANIC_ON(decode->rex.rex); - - fetch_operands(env, decode, 2, false, true, false); - index = decode->op[1].val & mask; - - if (decode->op[0].type != X86_VAR_REG) { - if (4 == decode->operand_size) { - displacement = ((int32_t) (decode->op[1].val & 0xffffffe0)) / 32; - decode->op[0].ptr += 4 * displacement; - } else if (2 == decode->operand_size) { - displacement = ((int16_t) (decode->op[1].val & 0xfff0)) / 16; - decode->op[0].ptr += 2 * displacement; - } else { - VM_PANIC("bt 64bit\n"); - } - } - decode->op[0].val = read_val_ext(env, decode->op[0].ptr, - decode->operand_size); - cf = (decode->op[0].val >> index) & 0x01; - - switch (flag) { - case 0: - set_CF(env, cf); - return; - case 1: - decode->op[0].val ^= (1u << index); - break; - case 2: - decode->op[0].val |= (1u << index); - break; - case 3: - decode->op[0].val &= ~(1u << index); - break; - } - write_val_ext(env, decode->op[0].ptr, decode->op[0].val, - decode->operand_size); - set_CF(env, cf); -} - -static void exec_bt(CPUX86State *env, struct x86_decode *decode) -{ - do_bt(env, decode, 0); - env->eip += decode->len; -} - -static void exec_btc(CPUX86State *env, struct x86_decode *decode) -{ - do_bt(env, decode, 1); - env->eip += decode->len; -} - -static void exec_btr(CPUX86State *env, struct x86_decode *decode) -{ - do_bt(env, decode, 3); - env->eip += decode->len; -} - -static void exec_bts(CPUX86State *env, struct x86_decode *decode) -{ - do_bt(env, decode, 2); - env->eip += decode->len; -} - -void exec_shl(CPUX86State *env, struct x86_decode *decode) -{ - uint8_t count; - int of = 0, cf = 0; - - fetch_operands(env, decode, 2, true, true, false); - - count = decode->op[1].val; - count &= 0x1f; /* count is masked to 5 bits*/ - if (!count) { - goto exit; - } - - switch (decode->operand_size) { - case 1: - { - uint8_t res = 0; - if (count <= 8) { - res = (decode->op[0].val << count); - cf = (decode->op[0].val >> (8 - count)) & 0x1; - of = cf ^ (res >> 7); - } - - write_val_ext(env, decode->op[0].ptr, res, 1); - SET_FLAGS_OSZAPC_LOGIC8(env, 0, 0, res); - SET_FLAGS_OxxxxC(env, of, cf); - break; - } - case 2: - { - uint16_t res = 0; - - /* from bochs */ - if (count <= 16) { - res = (decode->op[0].val << count); - cf = (decode->op[0].val >> (16 - count)) & 0x1; - of = cf ^ (res >> 15); /* of = cf ^ result15 */ - } - - write_val_ext(env, decode->op[0].ptr, res, 2); - SET_FLAGS_OSZAPC_LOGIC16(env, 0, 0, res); - SET_FLAGS_OxxxxC(env, of, cf); - break; - } - case 4: - { - uint32_t res = decode->op[0].val << count; - - write_val_ext(env, decode->op[0].ptr, res, 4); - SET_FLAGS_OSZAPC_LOGIC32(env, 0, 0, res); - cf = (decode->op[0].val >> (32 - count)) & 0x1; - of = cf ^ (res >> 31); /* of = cf ^ result31 */ - SET_FLAGS_OxxxxC(env, of, cf); - break; - } - default: - abort(); - } - -exit: - /* lflags_to_rflags(env); */ - env->eip += decode->len; -} - -void exec_movsx(CPUX86State *env, struct x86_decode *decode) -{ - int src_op_size; - int op_size = decode->operand_size; - - fetch_operands(env, decode, 2, false, false, false); - - if (0xbe == decode->opcode[1]) { - src_op_size = 1; - } else { - src_op_size = 2; - } - - decode->operand_size = src_op_size; - calc_modrm_operand(env, decode, &decode->op[1]); - decode->op[1].val = sign(read_val_ext(env, decode->op[1].ptr, src_op_size), - src_op_size); - - write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size); - - env->eip += decode->len; -} - -void exec_ror(CPUX86State *env, struct x86_decode *decode) -{ - uint8_t count; - - fetch_operands(env, decode, 2, true, true, false); - count = decode->op[1].val; - - switch (decode->operand_size) { - case 1: - { - uint32_t bit6, bit7; - uint8_t res; - - if ((count & 0x07) == 0) { - if (count & 0x18) { - bit6 = ((uint8_t)decode->op[0].val >> 6) & 1; - bit7 = ((uint8_t)decode->op[0].val >> 7) & 1; - SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7); - } - } else { - count &= 0x7; /* use only bottom 3 bits */ - res = ((uint8_t)decode->op[0].val >> count) | - ((uint8_t)decode->op[0].val << (8 - count)); - write_val_ext(env, decode->op[0].ptr, res, 1); - bit6 = (res >> 6) & 1; - bit7 = (res >> 7) & 1; - /* set eflags: ROR count affects the following flags: C, O */ - SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7); - } - break; - } - case 2: - { - uint32_t bit14, bit15; - uint16_t res; - - if ((count & 0x0f) == 0) { - if (count & 0x10) { - bit14 = ((uint16_t)decode->op[0].val >> 14) & 1; - bit15 = ((uint16_t)decode->op[0].val >> 15) & 1; - /* of = result14 ^ result15 */ - SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15); - } - } else { - count &= 0x0f; /* use only 4 LSB's */ - res = ((uint16_t)decode->op[0].val >> count) | - ((uint16_t)decode->op[0].val << (16 - count)); - write_val_ext(env, decode->op[0].ptr, res, 2); - - bit14 = (res >> 14) & 1; - bit15 = (res >> 15) & 1; - /* of = result14 ^ result15 */ - SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15); - } - break; - } - case 4: - { - uint32_t bit31, bit30; - uint32_t res; - - count &= 0x1f; - if (count) { - res = ((uint32_t)decode->op[0].val >> count) | - ((uint32_t)decode->op[0].val << (32 - count)); - write_val_ext(env, decode->op[0].ptr, res, 4); - - bit31 = (res >> 31) & 1; - bit30 = (res >> 30) & 1; - /* of = result30 ^ result31 */ - SET_FLAGS_OxxxxC(env, bit30 ^ bit31, bit31); - } - break; - } - } - env->eip += decode->len; -} - -void exec_rol(CPUX86State *env, struct x86_decode *decode) -{ - uint8_t count; - - fetch_operands(env, decode, 2, true, true, false); - count = decode->op[1].val; - - switch (decode->operand_size) { - case 1: - { - uint32_t bit0, bit7; - uint8_t res; - - if ((count & 0x07) == 0) { - if (count & 0x18) { - bit0 = ((uint8_t)decode->op[0].val & 1); - bit7 = ((uint8_t)decode->op[0].val >> 7); - SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0); - } - } else { - count &= 0x7; /* use only lowest 3 bits */ - res = ((uint8_t)decode->op[0].val << count) | - ((uint8_t)decode->op[0].val >> (8 - count)); - - write_val_ext(env, decode->op[0].ptr, res, 1); - /* set eflags: - * ROL count affects the following flags: C, O - */ - bit0 = (res & 1); - bit7 = (res >> 7); - SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0); - } - break; - } - case 2: - { - uint32_t bit0, bit15; - uint16_t res; - - if ((count & 0x0f) == 0) { - if (count & 0x10) { - bit0 = ((uint16_t)decode->op[0].val & 0x1); - bit15 = ((uint16_t)decode->op[0].val >> 15); - /* of = cf ^ result15 */ - SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0); - } - } else { - count &= 0x0f; /* only use bottom 4 bits */ - res = ((uint16_t)decode->op[0].val << count) | - ((uint16_t)decode->op[0].val >> (16 - count)); - - write_val_ext(env, decode->op[0].ptr, res, 2); - bit0 = (res & 0x1); - bit15 = (res >> 15); - /* of = cf ^ result15 */ - SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0); - } - break; - } - case 4: - { - uint32_t bit0, bit31; - uint32_t res; - - count &= 0x1f; - if (count) { - res = ((uint32_t)decode->op[0].val << count) | - ((uint32_t)decode->op[0].val >> (32 - count)); - - write_val_ext(env, decode->op[0].ptr, res, 4); - bit0 = (res & 0x1); - bit31 = (res >> 31); - /* of = cf ^ result31 */ - SET_FLAGS_OxxxxC(env, bit0 ^ bit31, bit0); - } - break; - } - } - env->eip += decode->len; -} - - -void exec_rcl(CPUX86State *env, struct x86_decode *decode) -{ - uint8_t count; - int of = 0, cf = 0; - - fetch_operands(env, decode, 2, true, true, false); - count = decode->op[1].val & 0x1f; - - switch (decode->operand_size) { - case 1: - { - uint8_t op1_8 = decode->op[0].val; - uint8_t res; - count %= 9; - if (!count) { - break; - } - - if (1 == count) { - res = (op1_8 << 1) | get_CF(env); - } else { - res = (op1_8 << count) | (get_CF(env) << (count - 1)) | - (op1_8 >> (9 - count)); - } - - write_val_ext(env, decode->op[0].ptr, res, 1); - - cf = (op1_8 >> (8 - count)) & 0x01; - of = cf ^ (res >> 7); /* of = cf ^ result7 */ - SET_FLAGS_OxxxxC(env, of, cf); - break; - } - case 2: - { - uint16_t res; - uint16_t op1_16 = decode->op[0].val; - - count %= 17; - if (!count) { - break; - } - - if (1 == count) { - res = (op1_16 << 1) | get_CF(env); - } else if (count == 16) { - res = (get_CF(env) << 15) | (op1_16 >> 1); - } else { /* 2..15 */ - res = (op1_16 << count) | (get_CF(env) << (count - 1)) | - (op1_16 >> (17 - count)); - } - - write_val_ext(env, decode->op[0].ptr, res, 2); - - cf = (op1_16 >> (16 - count)) & 0x1; - of = cf ^ (res >> 15); /* of = cf ^ result15 */ - SET_FLAGS_OxxxxC(env, of, cf); - break; - } - case 4: - { - uint32_t res; - uint32_t op1_32 = decode->op[0].val; - - if (!count) { - break; - } - - if (1 == count) { - res = (op1_32 << 1) | get_CF(env); - } else { - res = (op1_32 << count) | (get_CF(env) << (count - 1)) | - (op1_32 >> (33 - count)); - } - - write_val_ext(env, decode->op[0].ptr, res, 4); - - cf = (op1_32 >> (32 - count)) & 0x1; - of = cf ^ (res >> 31); /* of = cf ^ result31 */ - SET_FLAGS_OxxxxC(env, of, cf); - break; - } - } - env->eip += decode->len; -} - -void exec_rcr(CPUX86State *env, struct x86_decode *decode) -{ - uint8_t count; - int of = 0, cf = 0; - - fetch_operands(env, decode, 2, true, true, false); - count = decode->op[1].val & 0x1f; - - switch (decode->operand_size) { - case 1: - { - uint8_t op1_8 = decode->op[0].val; - uint8_t res; - - count %= 9; - if (!count) { - break; - } - res = (op1_8 >> count) | (get_CF(env) << (8 - count)) | - (op1_8 << (9 - count)); - - write_val_ext(env, decode->op[0].ptr, res, 1); - - cf = (op1_8 >> (count - 1)) & 0x1; - of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */ - SET_FLAGS_OxxxxC(env, of, cf); - break; - } - case 2: - { - uint16_t op1_16 = decode->op[0].val; - uint16_t res; - - count %= 17; - if (!count) { - break; - } - res = (op1_16 >> count) | (get_CF(env) << (16 - count)) | - (op1_16 << (17 - count)); - - write_val_ext(env, decode->op[0].ptr, res, 2); - - cf = (op1_16 >> (count - 1)) & 0x1; - of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^ - result14 */ - SET_FLAGS_OxxxxC(env, of, cf); - break; - } - case 4: - { - uint32_t res; - uint32_t op1_32 = decode->op[0].val; - - if (!count) { - break; - } - - if (1 == count) { - res = (op1_32 >> 1) | (get_CF(env) << 31); - } else { - res = (op1_32 >> count) | (get_CF(env) << (32 - count)) | - (op1_32 << (33 - count)); - } - - write_val_ext(env, decode->op[0].ptr, res, 4); - - cf = (op1_32 >> (count - 1)) & 0x1; - of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */ - SET_FLAGS_OxxxxC(env, of, cf); - break; - } - } - env->eip += decode->len; -} - -static void exec_xchg(CPUX86State *env, struct x86_decode *decode) -{ - fetch_operands(env, decode, 2, true, true, false); - - write_val_ext(env, decode->op[0].ptr, decode->op[1].val, - decode->operand_size); - write_val_ext(env, decode->op[1].ptr, decode->op[0].val, - decode->operand_size); - - env->eip += decode->len; -} - -static void exec_xadd(CPUX86State *env, struct x86_decode *decode) -{ - EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true); - write_val_ext(env, decode->op[1].ptr, decode->op[0].val, - decode->operand_size); - - env->eip += decode->len; -} - -static struct cmd_handler { - enum x86_decode_cmd cmd; - void (*handler)(CPUX86State *env, struct x86_decode *ins); -} handlers[] = { - {X86_DECODE_CMD_INVL, NULL,}, - {X86_DECODE_CMD_MOV, exec_mov}, - {X86_DECODE_CMD_ADD, exec_add}, - {X86_DECODE_CMD_OR, exec_or}, - {X86_DECODE_CMD_ADC, exec_adc}, - {X86_DECODE_CMD_SBB, exec_sbb}, - {X86_DECODE_CMD_AND, exec_and}, - {X86_DECODE_CMD_SUB, exec_sub}, - {X86_DECODE_CMD_NEG, exec_neg}, - {X86_DECODE_CMD_XOR, exec_xor}, - {X86_DECODE_CMD_CMP, exec_cmp}, - {X86_DECODE_CMD_INC, exec_inc}, - {X86_DECODE_CMD_DEC, exec_dec}, - {X86_DECODE_CMD_TST, exec_tst}, - {X86_DECODE_CMD_NOT, exec_not}, - {X86_DECODE_CMD_MOVZX, exec_movzx}, - {X86_DECODE_CMD_OUT, exec_out}, - {X86_DECODE_CMD_IN, exec_in}, - {X86_DECODE_CMD_INS, exec_ins}, - {X86_DECODE_CMD_OUTS, exec_outs}, - {X86_DECODE_CMD_RDMSR, exec_rdmsr}, - {X86_DECODE_CMD_WRMSR, exec_wrmsr}, - {X86_DECODE_CMD_BT, exec_bt}, - {X86_DECODE_CMD_BTR, exec_btr}, - {X86_DECODE_CMD_BTC, exec_btc}, - {X86_DECODE_CMD_BTS, exec_bts}, - {X86_DECODE_CMD_SHL, exec_shl}, - {X86_DECODE_CMD_ROL, exec_rol}, - {X86_DECODE_CMD_ROR, exec_ror}, - {X86_DECODE_CMD_RCR, exec_rcr}, - {X86_DECODE_CMD_RCL, exec_rcl}, - /*{X86_DECODE_CMD_CPUID, exec_cpuid},*/ - {X86_DECODE_CMD_MOVS, exec_movs}, - {X86_DECODE_CMD_CMPS, exec_cmps}, - {X86_DECODE_CMD_STOS, exec_stos}, - {X86_DECODE_CMD_SCAS, exec_scas}, - {X86_DECODE_CMD_LODS, exec_lods}, - {X86_DECODE_CMD_MOVSX, exec_movsx}, - {X86_DECODE_CMD_XCHG, exec_xchg}, - {X86_DECODE_CMD_XADD, exec_xadd}, -}; - -static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST]; - -const struct x86_emul_ops *emul_ops; - -static void init_cmd_handler(void) -{ - int i; - for (i = 0; i < ARRAY_SIZE(handlers); i++) { - _cmd_handler[handlers[i].cmd] = handlers[i]; - } -} - -bool exec_instruction(CPUX86State *env, struct x86_decode *ins) -{ - if (!_cmd_handler[ins->cmd].handler) { - printf("Unimplemented handler (%llx) for %d (%x %x) \n", env->eip, - ins->cmd, ins->opcode[0], - ins->opcode_len > 1 ? ins->opcode[1] : 0); - env->eip += ins->len; - return true; - } - - _cmd_handler[ins->cmd].handler(env, ins); - return true; -} - -void init_emu(const struct x86_emul_ops *o) -{ - emul_ops = o; - init_cmd_handler(); -} diff --git a/target/i386/hvf/x86_emu.h b/target/i386/hvf/x86_emu.h deleted file mode 100644 index 555b567e2c..0000000000 --- a/target/i386/hvf/x86_emu.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2016 Veertu Inc, - * Copyright (C) 2017 Google Inc, - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, see . - */ - -#ifndef X86_EMU_H -#define X86_EMU_H - -#include "x86.h" -#include "x86_decode.h" -#include "cpu.h" - -struct x86_emul_ops { - void (*read_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes); - void (*write_mem)(CPUState *cpu, void *data, target_ulong addr, int bytes); - void (*read_segment_descriptor)(CPUState *cpu, struct x86_segment_descriptor *desc, - enum X86Seg seg); - void (*handle_io)(CPUState *cpu, uint16_t port, void *data, int direction, - int size, int count); - void (*simulate_rdmsr)(CPUState *cs); - void (*simulate_wrmsr)(CPUState *cs); -}; - -extern const struct x86_emul_ops *emul_ops; - -void init_emu(const struct x86_emul_ops *ops); -bool exec_instruction(CPUX86State *env, struct x86_decode *ins); -void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code); - -target_ulong read_reg(CPUX86State *env, int reg, int size); -void write_reg(CPUX86State *env, int reg, target_ulong val, int size); -target_ulong read_val_from_reg(target_ulong reg_ptr, int size); -void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size); -void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size); -uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes); -target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size); - -void exec_movzx(CPUX86State *env, struct x86_decode *decode); -void exec_shl(CPUX86State *env, struct x86_decode *decode); -void exec_movsx(CPUX86State *env, struct x86_decode *decode); -void exec_ror(CPUX86State *env, struct x86_decode *decode); -void exec_rol(CPUX86State *env, struct x86_decode *decode); -void exec_rcl(CPUX86State *env, struct x86_decode *decode); -void exec_rcr(CPUX86State *env, struct x86_decode *decode); -#endif diff --git a/target/i386/hvf/x86_flags.c b/target/i386/hvf/x86_flags.c deleted file mode 100644 index 84e27364a0..0000000000 --- a/target/i386/hvf/x86_flags.c +++ /dev/null @@ -1,305 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001-2012 The Bochs Project -// Copyright (C) 2017 Google Inc. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA -///////////////////////////////////////////////////////////////////////// -/* - * flags functions - */ - -#include "qemu/osdep.h" - -#include "panic.h" -#include "cpu.h" -#include "x86_flags.h" -#include "x86.h" - - -/* this is basically bocsh code */ - -#define LF_SIGN_BIT 31 - -#define LF_BIT_SD (0) /* lazy Sign Flag Delta */ -#define LF_BIT_AF (3) /* lazy Adjust flag */ -#define LF_BIT_PDB (8) /* lazy Parity Delta Byte (8 bits) */ -#define LF_BIT_CF (31) /* lazy Carry Flag */ -#define LF_BIT_PO (30) /* lazy Partial Overflow = CF ^ OF */ - -#define LF_MASK_SD (0x01 << LF_BIT_SD) -#define LF_MASK_AF (0x01 << LF_BIT_AF) -#define LF_MASK_PDB (0xFF << LF_BIT_PDB) -#define LF_MASK_CF (0x01 << LF_BIT_CF) -#define LF_MASK_PO (0x01 << LF_BIT_PO) - -/* ******************* */ -/* OSZAPC */ -/* ******************* */ - -/* size, carries, result */ -#define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \ - target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \ - (((lf_carries) >> (size - 2)) << LF_BIT_PO); \ - env->lflags.result = (target_ulong)(int##size##_t)(lf_result); \ - if ((size) == 32) { \ - temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ - } else if ((size) == 16) { \ - temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \ - } else if ((size) == 8) { \ - temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \ - } else { \ - VM_PANIC("unimplemented"); \ - } \ - env->lflags.auxbits = (target_ulong)(uint32_t)temp; \ -} - -/* carries, result */ -#define SET_FLAGS_OSZAPC_8(carries, result) \ - SET_FLAGS_OSZAPC_SIZE(8, carries, result) -#define SET_FLAGS_OSZAPC_16(carries, result) \ - SET_FLAGS_OSZAPC_SIZE(16, carries, result) -#define SET_FLAGS_OSZAPC_32(carries, result) \ - SET_FLAGS_OSZAPC_SIZE(32, carries, result) - -/* ******************* */ -/* OSZAP */ -/* ******************* */ -/* size, carries, result */ -#define SET_FLAGS_OSZAP_SIZE(size, lf_carries, lf_result) { \ - target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \ - (((lf_carries) >> (size - 2)) << LF_BIT_PO); \ - if ((size) == 32) { \ - temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ - } else if ((size) == 16) { \ - temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \ - } else if ((size) == 8) { \ - temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \ - } else { \ - VM_PANIC("unimplemented"); \ - } \ - env->lflags.result = (target_ulong)(int##size##_t)(lf_result); \ - target_ulong delta_c = (env->lflags.auxbits ^ temp) & LF_MASK_CF; \ - delta_c ^= (delta_c >> 1); \ - env->lflags.auxbits = (target_ulong)(uint32_t)(temp ^ delta_c); \ -} - -/* carries, result */ -#define SET_FLAGS_OSZAP_8(carries, result) \ - SET_FLAGS_OSZAP_SIZE(8, carries, result) -#define SET_FLAGS_OSZAP_16(carries, result) \ - SET_FLAGS_OSZAP_SIZE(16, carries, result) -#define SET_FLAGS_OSZAP_32(carries, result) \ - SET_FLAGS_OSZAP_SIZE(32, carries, result) - -void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf) -{ - uint32_t temp_po = new_of ^ new_cf; - env->lflags.auxbits &= ~(LF_MASK_PO | LF_MASK_CF); - env->lflags.auxbits |= (temp_po << LF_BIT_PO) | (new_cf << LF_BIT_CF); -} - -void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2, - uint32_t diff) -{ - SET_FLAGS_OSZAPC_32(SUB_COUT_VEC(v1, v2, diff), diff); -} - -void SET_FLAGS_OSZAPC_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2, - uint16_t diff) -{ - SET_FLAGS_OSZAPC_16(SUB_COUT_VEC(v1, v2, diff), diff); -} - -void SET_FLAGS_OSZAPC_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2, - uint8_t diff) -{ - SET_FLAGS_OSZAPC_8(SUB_COUT_VEC(v1, v2, diff), diff); -} - -void SET_FLAGS_OSZAPC_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2, - uint32_t diff) -{ - SET_FLAGS_OSZAPC_32(ADD_COUT_VEC(v1, v2, diff), diff); -} - -void SET_FLAGS_OSZAPC_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2, - uint16_t diff) -{ - SET_FLAGS_OSZAPC_16(ADD_COUT_VEC(v1, v2, diff), diff); -} - -void SET_FLAGS_OSZAPC_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2, - uint8_t diff) -{ - SET_FLAGS_OSZAPC_8(ADD_COUT_VEC(v1, v2, diff), diff); -} - -void SET_FLAGS_OSZAP_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2, - uint32_t diff) -{ - SET_FLAGS_OSZAP_32(SUB_COUT_VEC(v1, v2, diff), diff); -} - -void SET_FLAGS_OSZAP_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2, - uint16_t diff) -{ - SET_FLAGS_OSZAP_16(SUB_COUT_VEC(v1, v2, diff), diff); -} - -void SET_FLAGS_OSZAP_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2, - uint8_t diff) -{ - SET_FLAGS_OSZAP_8(SUB_COUT_VEC(v1, v2, diff), diff); -} - -void SET_FLAGS_OSZAP_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2, - uint32_t diff) -{ - SET_FLAGS_OSZAP_32(ADD_COUT_VEC(v1, v2, diff), diff); -} - -void SET_FLAGS_OSZAP_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2, - uint16_t diff) -{ - SET_FLAGS_OSZAP_16(ADD_COUT_VEC(v1, v2, diff), diff); -} - -void SET_FLAGS_OSZAP_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2, - uint8_t diff) -{ - SET_FLAGS_OSZAP_8(ADD_COUT_VEC(v1, v2, diff), diff); -} - - -void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State *env, uint32_t v1, uint32_t v2, - uint32_t diff) -{ - SET_FLAGS_OSZAPC_32(0, diff); -} - -void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State *env, uint16_t v1, uint16_t v2, - uint16_t diff) -{ - SET_FLAGS_OSZAPC_16(0, diff); -} - -void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2, - uint8_t diff) -{ - SET_FLAGS_OSZAPC_8(0, diff); -} - -bool get_PF(CPUX86State *env) -{ - uint32_t temp = (255 & env->lflags.result); - temp = temp ^ (255 & (env->lflags.auxbits >> LF_BIT_PDB)); - temp = (temp ^ (temp >> 4)) & 0x0F; - return (0x9669U >> temp) & 1; -} - -void set_PF(CPUX86State *env, bool val) -{ - uint32_t temp = (255 & env->lflags.result) ^ (!val); - env->lflags.auxbits &= ~(LF_MASK_PDB); - env->lflags.auxbits |= (temp << LF_BIT_PDB); -} - -bool get_OF(CPUX86State *env) -{ - return ((env->lflags.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1; -} - -bool get_CF(CPUX86State *env) -{ - return (env->lflags.auxbits >> LF_BIT_CF) & 1; -} - -void set_OF(CPUX86State *env, bool val) -{ - bool old_cf = get_CF(env); - SET_FLAGS_OxxxxC(env, val, old_cf); -} - -void set_CF(CPUX86State *env, bool val) -{ - bool old_of = get_OF(env); - SET_FLAGS_OxxxxC(env, old_of, val); -} - -bool get_AF(CPUX86State *env) -{ - return (env->lflags.auxbits >> LF_BIT_AF) & 1; -} - -void set_AF(CPUX86State *env, bool val) -{ - env->lflags.auxbits &= ~(LF_MASK_AF); - env->lflags.auxbits |= val << LF_BIT_AF; -} - -bool get_ZF(CPUX86State *env) -{ - return !env->lflags.result; -} - -void set_ZF(CPUX86State *env, bool val) -{ - if (val) { - env->lflags.auxbits ^= - (((env->lflags.result >> LF_SIGN_BIT) & 1) << LF_BIT_SD); - /* merge the parity bits into the Parity Delta Byte */ - uint32_t temp_pdb = (255 & env->lflags.result); - env->lflags.auxbits ^= (temp_pdb << LF_BIT_PDB); - /* now zero the .result value */ - env->lflags.result = 0; - } else { - env->lflags.result |= (1 << 8); - } -} - -bool get_SF(CPUX86State *env) -{ - return ((env->lflags.result >> LF_SIGN_BIT) ^ - (env->lflags.auxbits >> LF_BIT_SD)) & 1; -} - -void set_SF(CPUX86State *env, bool val) -{ - bool temp_sf = get_SF(env); - env->lflags.auxbits ^= (temp_sf ^ val) << LF_BIT_SD; -} - -void lflags_to_rflags(CPUX86State *env) -{ - env->eflags &= ~(CC_C|CC_P|CC_A|CC_Z|CC_S|CC_O); - env->eflags |= get_CF(env) ? CC_C : 0; - env->eflags |= get_PF(env) ? CC_P : 0; - env->eflags |= get_AF(env) ? CC_A : 0; - env->eflags |= get_ZF(env) ? CC_Z : 0; - env->eflags |= get_SF(env) ? CC_S : 0; - env->eflags |= get_OF(env) ? CC_O : 0; -} - -void rflags_to_lflags(CPUX86State *env) -{ - env->lflags.auxbits = env->lflags.result = 0; - set_OF(env, env->eflags & CC_O); - set_SF(env, env->eflags & CC_S); - set_ZF(env, env->eflags & CC_Z); - set_AF(env, env->eflags & CC_A); - set_PF(env, env->eflags & CC_P); - set_CF(env, env->eflags & CC_C); -} diff --git a/target/i386/hvf/x86_flags.h b/target/i386/hvf/x86_flags.h deleted file mode 100644 index 6c175007b5..0000000000 --- a/target/i386/hvf/x86_flags.h +++ /dev/null @@ -1,81 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001-2012 The Bochs Project -// Copyright (C) 2017 Google Inc. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA -///////////////////////////////////////////////////////////////////////// -/* - * x86 eflags functions - */ - -#ifndef X86_EMU_FLAGS_H -#define X86_EMU_FLAGS_H - -#include "cpu.h" -void lflags_to_rflags(CPUX86State *env); -void rflags_to_lflags(CPUX86State *env); - -bool get_PF(CPUX86State *env); -void set_PF(CPUX86State *env, bool val); -bool get_CF(CPUX86State *env); -void set_CF(CPUX86State *env, bool val); -bool get_AF(CPUX86State *env); -void set_AF(CPUX86State *env, bool val); -bool get_ZF(CPUX86State *env); -void set_ZF(CPUX86State *env, bool val); -bool get_SF(CPUX86State *env); -void set_SF(CPUX86State *env, bool val); -bool get_OF(CPUX86State *env); -void set_OF(CPUX86State *env, bool val); - -void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf); - -void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2, - uint32_t diff); -void SET_FLAGS_OSZAPC_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2, - uint16_t diff); -void SET_FLAGS_OSZAPC_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2, - uint8_t diff); - -void SET_FLAGS_OSZAPC_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2, - uint32_t diff); -void SET_FLAGS_OSZAPC_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2, - uint16_t diff); -void SET_FLAGS_OSZAPC_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2, - uint8_t diff); - -void SET_FLAGS_OSZAP_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2, - uint32_t diff); -void SET_FLAGS_OSZAP_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2, - uint16_t diff); -void SET_FLAGS_OSZAP_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2, - uint8_t diff); - -void SET_FLAGS_OSZAP_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2, - uint32_t diff); -void SET_FLAGS_OSZAP_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2, - uint16_t diff); -void SET_FLAGS_OSZAP_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2, - uint8_t diff); - -void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State *env, uint32_t v1, uint32_t v2, - uint32_t diff); -void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State *env, uint16_t v1, uint16_t v2, - uint16_t diff); -void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2, - uint8_t diff); - -#endif /* X86_EMU_FLAGS_H */ diff --git a/target/i386/hvf/x86_mmu.c b/target/i386/hvf/x86_mmu.c index 579d0c3a4c..afc5c17d5d 100644 --- a/target/i386/hvf/x86_mmu.c +++ b/target/i386/hvf/x86_mmu.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "panic.h" #include "cpu.h" -#include "x86.h" +#include "emulate/x86.h" #include "x86_mmu.h" #include "vmcs.h" #include "vmx.h" diff --git a/target/i386/hvf/x86_task.c b/target/i386/hvf/x86_task.c index 161217991f..bdf8b51ae6 100644 --- a/target/i386/hvf/x86_task.c +++ b/target/i386/hvf/x86_task.c @@ -14,11 +14,11 @@ #include "hvf-i386.h" #include "vmcs.h" #include "vmx.h" -#include "x86.h" +#include "emulate/x86.h" #include "x86_descr.h" #include "x86_mmu.h" -#include "x86_decode.h" -#include "x86_emu.h" +#include "emulate/x86_decode.h" +#include "emulate/x86_emu.h" #include "x86_task.h" #include "x86hvf.h" diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c index 531a340b37..2057314892 100644 --- a/target/i386/hvf/x86hvf.c +++ b/target/i386/hvf/x86hvf.c @@ -24,7 +24,7 @@ #include "vmcs.h" #include "cpu.h" #include "x86_descr.h" -#include "x86_decode.h" +#include "emulate/x86_decode.h" #include "system/hw_accel.h" #include "hw/i386/apic_internal.h"