[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Fix SVM instruction decode, fixing problem with gfxboot package.
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID 5abf652c4c52ae39c232bde1c298949210b36dfb # Parent e9d5563c08beee69a3228b0410edc64fe8723b8a Fix SVM instruction decode, fixing problem with gfxboot package. Signed-off-by: Tom Woller <thomas.woller@xxxxxxx> diff -r e9d5563c08be -r 5abf652c4c52 xen/arch/x86/hvm/svm/instrlen.c --- a/xen/arch/x86/hvm/svm/instrlen.c Tue Feb 21 18:35:34 2006 +++ b/xen/arch/x86/hvm/svm/instrlen.c Tue Feb 21 18:36:00 2006 @@ -2,17 +2,19 @@ * instrlen.c - calculates the instruction length for all operating modes * * Travis Betak, travis.betak@xxxxxxx - * Copyright (c) 2005 AMD + * Copyright (c) 2005,2006 AMD + * Copyright (c) 2005 Keir Fraser * - * Essentially a very, very stripped version of Keir Fraser's work in - * x86_emulate.c. Used primarily for MMIO. + * Essentially a very, very stripped version of Keir Fraser's work in + * x86_emulate.c. Used for MMIO. */ /* - * TODO: the way in which we use svm_instrlen is very inefficient as is now - * stands. it will be worth while to return the actual instruction buffer - * along with the instruction length since we are getting the instruction length - * so we know how much of the buffer we need to fetch. + * TODO: the way in which we use svm_instrlen is very inefficient as is now + * stands. It will be worth while to return the actual instruction buffer + * along with the instruction length since one of the reasons we are getting + * the instruction length is to know how many instruction bytes we need to + * fetch. */ #include <xen/config.h> @@ -22,6 +24,11 @@ #include <asm/regs.h> #define DPRINTF DPRINTK #include <asm-x86/x86_emulate.h> + +/* read from guest memory */ +extern int inst_copy_from_guest(unsigned char *buf, unsigned long eip, + int length); +extern void svm_dump_inst(unsigned long eip); /* * Opcode effective-address decode tables. @@ -33,98 +40,101 @@ */ /* Operand sizes: 8-bit operands or specified/overridden size. */ -#define BYTE_OP (1<<0) /* 8-bit operands. */ +#define ByteOp (1<<0) /* 8-bit operands. */ /* Destination operand type. */ -#define IMPLICIT_OPS (1<<1) /* Implicit in opcode. No generic decode. */ -#define DST_REG (2<<1) /* Register operand. */ -#define DST_MEM (3<<1) /* Memory operand. */ -#define DST_MASK (3<<1) +#define ImplicitOps (1<<1) /* Implicit in opcode. No generic decode. */ +#define DstReg (2<<1) /* Register operand. */ +#define DstMem (3<<1) /* Memory operand. */ +#define DstMask (3<<1) /* Source operand type. */ -#define SRC_NONE (0<<3) /* No source operand. */ -#define SRC_IMPLICIT (0<<3) /* Source operand is implicit in the opcode. */ -#define SRC_REG (1<<3) /* Register operand. */ -#define SRC_MEM (2<<3) /* Memory operand. */ -#define SRC_IMM (3<<3) /* Immediate operand. */ -#define SRC_IMMBYTE (4<<3) /* 8-bit sign-extended immediate operand. */ -#define SRC_MASK (7<<3) -/* Generic MODRM decode. */ -#define MODRM (1<<6) +#define SrcNone (0<<3) /* No source operand. */ +#define SrcImplicit (0<<3) /* Source operand is implicit in the opcode. */ +#define SrcReg (1<<3) /* Register operand. */ +#define SrcMem (2<<3) /* Memory operand. */ +#define SrcMem16 (3<<3) /* Memory operand (16-bit). */ +#define SrcMem32 (4<<3) /* Memory operand (32-bit). */ +#define SrcImm (5<<3) /* Immediate operand. */ +#define SrcImmByte (6<<3) /* 8-bit sign-extended immediate operand. */ +#define SrcMask (7<<3) +/* Generic ModRM decode. */ +#define ModRM (1<<6) /* Destination is only written; never read. */ #define Mov (1<<7) -static u8 opcode_table[256] = { +static uint8_t opcode_table[256] = { /* 0x00 - 0x07 */ - BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM, - BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM, + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, + ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM, 0, 0, 0, 0, /* 0x08 - 0x0F */ - BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM, - BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM, + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, + ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM, 0, 0, 0, 0, /* 0x10 - 0x17 */ - BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM, - BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM, + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, + ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM, 0, 0, 0, 0, /* 0x18 - 0x1F */ - BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM, - BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM, + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, + ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM, 0, 0, 0, 0, /* 0x20 - 0x27 */ - BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM, - BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM, + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, + ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM, 0, 0, 0, 0, /* 0x28 - 0x2F */ - BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM, - BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM, + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, + ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM, 0, 0, 0, 0, /* 0x30 - 0x37 */ - BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM, - BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM, + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, + ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM, 0, 0, 0, 0, /* 0x38 - 0x3F */ - BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM, - BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM, + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, + ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM, 0, 0, 0, 0, /* 0x40 - 0x4F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, DstReg|SrcMem32|ModRM|Mov /* movsxd (x86/64) */, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x87 */ - BYTE_OP | DST_MEM | SRC_IMM | MODRM, DST_MEM | SRC_IMM | MODRM, - BYTE_OP | DST_MEM | SRC_IMM | MODRM, DST_MEM | SRC_IMMBYTE | MODRM, - BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM, - BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM, + ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImm|ModRM, + ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM, + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, /* 0x88 - 0x8F */ - BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM, - BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM, - 0, 0, 0, DST_MEM | SRC_NONE | MODRM | Mov, + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, + ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM, + 0, 0, 0, DstMem|SrcNone|ModRM|Mov, /* 0x90 - 0x9F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xA7 */ - BYTE_OP | DST_REG | SRC_MEM | Mov, DST_REG | SRC_MEM | Mov, - BYTE_OP | DST_MEM | SRC_REG | Mov, DST_MEM | SRC_REG | Mov, - BYTE_OP | IMPLICIT_OPS | Mov, IMPLICIT_OPS | Mov, - BYTE_OP | IMPLICIT_OPS, IMPLICIT_OPS, + ByteOp|DstReg|SrcMem|Mov, DstReg|SrcMem|Mov, + ByteOp|DstMem|SrcReg|Mov, DstMem|SrcReg|Mov, + ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, + ByteOp|ImplicitOps, ImplicitOps, /* 0xA8 - 0xAF */ - 0, 0, BYTE_OP | IMPLICIT_OPS | Mov, IMPLICIT_OPS | Mov, - BYTE_OP | IMPLICIT_OPS | Mov, IMPLICIT_OPS | Mov, - BYTE_OP | IMPLICIT_OPS, IMPLICIT_OPS, + 0, 0, ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, + ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, + ByteOp|ImplicitOps, ImplicitOps, /* 0xB0 - 0xBF */ - SRC_IMMBYTE, SRC_IMMBYTE, SRC_IMMBYTE, SRC_IMMBYTE, - SRC_IMMBYTE, SRC_IMMBYTE, SRC_IMMBYTE, SRC_IMMBYTE, + SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte, + SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xC7 */ - BYTE_OP | DST_MEM | SRC_IMM | MODRM, DST_MEM | SRC_IMMBYTE | MODRM, 0, 0, - 0, 0, BYTE_OP | DST_MEM | SRC_IMM | MODRM, DST_MEM | SRC_IMM | MODRM, + ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM, 0, 0, + 0, 0, ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImm|ModRM, /* 0xC8 - 0xCF */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xD7 */ - BYTE_OP | DST_MEM | SRC_IMPLICIT | MODRM, DST_MEM | SRC_IMPLICIT | MODRM, - BYTE_OP | DST_MEM | SRC_IMPLICIT | MODRM, DST_MEM | SRC_IMPLICIT | MODRM, + ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, + ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 0, 0, 0, 0, /* 0xD8 - 0xDF */ 0, 0, 0, 0, 0, 0, 0, 0, @@ -132,31 +142,31 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0 - 0xF7 */ 0, 0, 0, 0, - 0, 0, BYTE_OP | DST_MEM | SRC_NONE | MODRM, DST_MEM | SRC_NONE | MODRM, + 0, 0, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM, /* 0xF8 - 0xFF */ 0, 0, 0, 0, - 0, 0, BYTE_OP | DST_MEM | SRC_NONE | MODRM, DST_MEM | SRC_NONE | MODRM + 0, 0, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM }; -static u8 twobyte_table[256] = { +static uint8_t twobyte_table[256] = { /* 0x00 - 0x0F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, IMPLICIT_OPS | MODRM, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, /* 0x10 - 0x1F */ - 0, 0, 0, 0, 0, 0, 0, 0, IMPLICIT_OPS | MODRM, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x47 */ - DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov, - DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov, - DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov, - DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov, + DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, + DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, + DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, + DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, /* 0x48 - 0x4F */ - DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov, - DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov, - DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov, - DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov, + DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, + DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, + DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, + DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, /* 0x50 - 0x5F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ @@ -168,20 +178,17 @@ /* 0x90 - 0x9F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xA7 */ - 0, 0, 0, DST_MEM | SRC_REG | MODRM, 0, 0, 0, 0, + 0, 0, 0, DstMem|SrcReg|ModRM, 0, 0, 0, 0, /* 0xA8 - 0xAF */ - 0, 0, 0, DST_MEM | SRC_REG | MODRM, 0, 0, 0, 0, + 0, 0, 0, DstMem|SrcReg|ModRM, 0, 0, 0, 0, /* 0xB0 - 0xB7 */ - BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM, 0, - DST_MEM | SRC_REG | MODRM, - 0, 0, - DST_REG | SRC_MEM | MODRM, - DST_REG | SRC_REG | MODRM, - + ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, 0, DstMem|SrcReg|ModRM, + 0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov, /* 0xB8 - 0xBF */ - 0, 0, DST_MEM | SRC_IMMBYTE | MODRM, DST_MEM | SRC_REG | MODRM, 0, 0, 0, 0, + 0, 0, DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM, + 0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov, /* 0xC0 - 0xCF */ - 0, 0, 0, 0, 0, 0, 0, IMPLICIT_OPS | MODRM, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0 - 0xEF */ @@ -189,11 +196,6 @@ /* 0xF0 - 0xFF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -/* read from guest memory */ -extern int inst_copy_from_guest(unsigned char *buf, unsigned long eip, - int length); -extern void svm_dump_inst(unsigned long eip); /* * insn_fetch - fetch the next 1 to 4 bytes from instruction stream @@ -219,206 +221,250 @@ (_type)_x; \ }) + /** - * get_instruction_length - returns the current instructions length + * svn_instrlen - returns the current instructions length * * @regs: guest register state - * @cr2: target address - * @ops: guest memory operations * @mode: guest operating mode * * EXTERNAL this routine calculates the length of the current instruction * pointed to by eip. The guest state is _not_ changed by this routine. */ -unsigned long svm_instrlen(struct cpu_user_regs *regs, int mode) +int svm_instrlen(struct cpu_user_regs *regs, int mode) { - u8 b, d, twobyte = 0; - u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; - unsigned int op_bytes = (mode == 8) ? 4 : mode, ad_bytes = mode; - unsigned int i; + uint8_t b, d, twobyte = 0, rex_prefix = 0; + uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; + unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i; int rc = 0; - u32 length = 0; - u8 tmp; - - /* Copy the registers so we don't alter the guest's present state */ - volatile struct cpu_user_regs _regs = *regs; - - /* Check for Real Mode */ - if (mode == 2) - _regs.eip += (_regs.cs << 4); - - /* Legacy prefix check */ - for (i = 0; i < 8; i++) { - switch (b = insn_fetch(u8, 1, _regs.eip, length)) { - case 0x66: /* operand-size override */ - op_bytes ^= 6; /* switch between 2/4 bytes */ - break; - case 0x67: /* address-size override */ - ad_bytes ^= (mode == 8) ? 12 : 6; /* 2/4/8 bytes */ - break; - case 0x2e: /* CS override */ - case 0x3e: /* DS override */ - case 0x26: /* ES override */ - case 0x64: /* FS override */ - case 0x65: /* GS override */ - case 0x36: /* SS override */ - case 0xf0: /* LOCK */ - case 0xf3: /* REP/REPE/REPZ */ - case 0xf2: /* REPNE/REPNZ */ + int length = 0; + unsigned int tmp; + + /* Shadow copy of register state. Committed on successful emulation. */ + struct cpu_user_regs _regs = *regs; + + /* include CS for 16-bit modes */ + if (mode == X86EMUL_MODE_REAL || mode == X86EMUL_MODE_PROT16) + _regs.eip += (_regs.cs << 4); + + switch ( mode ) + { + case X86EMUL_MODE_REAL: + case X86EMUL_MODE_PROT16: + op_bytes = ad_bytes = 2; + break; + case X86EMUL_MODE_PROT32: + op_bytes = ad_bytes = 4; + break; +#ifdef __x86_64__ + case X86EMUL_MODE_PROT64: + op_bytes = 4; + ad_bytes = 8; + break; +#endif + default: + return -1; + } + + /* Legacy prefixes. */ + for ( i = 0; i < 8; i++ ) + { + switch ( b = insn_fetch(uint8_t, 1, _regs.eip, length) ) + { + case 0x66: /* operand-size override */ + op_bytes ^= 6; /* switch between 2/4 bytes */ + break; + case 0x67: /* address-size override */ + if ( mode == X86EMUL_MODE_PROT64 ) + ad_bytes ^= 12; /* switch between 4/8 bytes */ + else + ad_bytes ^= 6; /* switch between 2/4 bytes */ + break; + case 0x2e: /* CS override */ + case 0x3e: /* DS override */ + case 0x26: /* ES override */ + case 0x64: /* FS override */ + case 0x65: /* GS override */ + case 0x36: /* SS override */ + break; + case 0xf0: /* LOCK */ + lock_prefix = 1; + break; + case 0xf3: /* REP/REPE/REPZ */ + rep_prefix = 1; + break; + case 0xf2: /* REPNE/REPNZ */ break; default: goto done_prefixes; } } - done_prefixes: - /* REX prefix check */ - if ((mode == 8) && ((b & 0xf0) == 0x40)) - { - if (b & 8) - op_bytes = 8; /* REX.W */ - modrm_reg = (b & 4) << 1; /* REX.R */ + /* Note quite the same as 80386 real mode, but hopefully good enough. */ + if ( (mode == X86EMUL_MODE_REAL) && (ad_bytes != 2) ) { + printf("sonofabitch!! we don't support 32-bit addresses in realmode\n"); + goto cannot_emulate; + } + + /* REX prefix. */ + if ( (mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40) ) + { + rex_prefix = b; + if ( b & 8 ) + op_bytes = 8; /* REX.W */ + modrm_reg = (b & 4) << 1; /* REX.R */ /* REX.B and REX.X do not need to be decoded. */ - b = insn_fetch(u8, 1, _regs.eip, length); + b = insn_fetch(uint8_t, 1, _regs.eip, length); } /* Opcode byte(s). */ d = opcode_table[b]; - if (d == 0) + if ( d == 0 ) { /* Two-byte opcode? */ - if (b == 0x0f) { + if ( b == 0x0f ) + { twobyte = 1; - b = insn_fetch(u8, 1, _regs.eip, length); + b = insn_fetch(uint8_t, 1, _regs.eip, length); d = twobyte_table[b]; } /* Unrecognised? */ - if (d == 0) + if ( d == 0 ) goto cannot_emulate; } - /* MODRM and SIB bytes. */ - if (d & MODRM) - { - modrm = insn_fetch(u8, 1, _regs.eip, length); + /* ModRM and SIB bytes. */ + if ( d & ModRM ) + { + modrm = insn_fetch(uint8_t, 1, _regs.eip, length); modrm_mod |= (modrm & 0xc0) >> 6; modrm_reg |= (modrm & 0x38) >> 3; - modrm_rm |= (modrm & 0x07); - switch (modrm_mod) - { - case 0: - if ((modrm_rm == 4) && - (((insn_fetch(u8, 1, _regs.eip, - length)) & 7) == 5)) + modrm_rm |= (modrm & 0x07); + + if ( modrm_mod == 3 ) + { + DPRINTF("Cannot parse ModRM.mod == 3.\n"); + goto cannot_emulate; + } + + if ( ad_bytes == 2 ) + { + /* 16-bit ModR/M decode. */ + switch ( modrm_mod ) { - length += 4; - _regs.eip += 4; /* skip SIB.base disp32 */ - } - else if (modrm_rm == 5) + case 0: + if ( modrm_rm == 6 ) + { + length += 2; + _regs.eip += 2; /* skip disp16 */ + } + break; + case 1: + length += 1; + _regs.eip += 1; /* skip disp8 */ + break; + case 2: + length += 2; + _regs.eip += 2; /* skip disp16 */ + break; + } + } + else + { + /* 32/64-bit ModR/M decode. */ + switch ( modrm_mod ) { + case 0: + if ( (modrm_rm == 4) && + (((insn_fetch(uint8_t, 1, _regs.eip, length)) & 7) + == 5) ) + { + length += 4; + _regs.eip += 4; /* skip disp32 specified by SIB.base */ + } + else if ( modrm_rm == 5 ) + { + length += 4; + _regs.eip += 4; /* skip disp32 */ + } + break; + case 1: + if ( modrm_rm == 4 ) + { + insn_fetch(uint8_t, 1, _regs.eip, length); + } + length += 1; + _regs.eip += 1; /* skip disp8 */ + break; + case 2: + if ( modrm_rm == 4 ) + { + insn_fetch(uint8_t, 1, _regs.eip, length); + } length += 4; _regs.eip += 4; /* skip disp32 */ + break; } - break; - case 1: - if (modrm_rm == 4) - { - insn_fetch(u8, 1, _regs.eip, length); - } - length += 1; - _regs.eip += 1; /* skip disp8 */ - break; - case 2: - if (modrm_rm == 4) - { - insn_fetch(u8, 1, _regs.eip, length); - } - length += 4; - _regs.eip += 4; /* skip disp32 */ - break; - case 3: - DPRINTF("Cannot parse ModRM.mod == 3.\n"); - goto cannot_emulate; } } /* Decode and fetch the destination operand: register or memory. */ - switch (d & DST_MASK) - { - case IMPLICIT_OPS: + switch ( d & DstMask ) + { + case ImplicitOps: /* Special instructions do their own operand decoding. */ goto done; } - /* Decode and fetch the source operand: register, memory or immediate */ - switch (d & SRC_MASK) - { - case SRC_IMM: - tmp = (d & BYTE_OP) ? 1 : op_bytes; - if (tmp == 8) - tmp = 4; + /* Decode and fetch the source operand: register, memory or immediate. */ + switch ( d & SrcMask ) + { + case SrcImm: + tmp = (d & ByteOp) ? 1 : op_bytes; + if ( tmp == 8 ) tmp = 4; /* NB. Immediates are sign-extended as necessary. */ - switch (tmp) { - case 1: - insn_fetch(s8, 1, _regs.eip, length); - break; - case 2: - insn_fetch(s16, 2, _regs.eip, length); - break; - case 4: - insn_fetch(s32, 4, _regs.eip, length); - break; - } - break; - case SRC_IMMBYTE: - insn_fetch(s8, 1, _regs.eip, length); - break; - } - - if (twobyte) + switch ( tmp ) + { + case 1: insn_fetch(int8_t, 1, _regs.eip, length); break; + case 2: insn_fetch(int16_t, 2, _regs.eip, length); break; + case 4: insn_fetch(int32_t, 4, _regs.eip, length); break; + } + break; + case SrcImmByte: + insn_fetch(int8_t, 1, _regs.eip, length); + break; + } + + if ( twobyte ) goto done; - switch (b) - { - case 0xa0: - case 0xa1: /* mov */ + switch ( b ) + { + case 0xa0 ... 0xa1: /* mov */ length += ad_bytes; - _regs.eip += ad_bytes; /* skip src displacement */ - break; - case 0xa2: - case 0xa3: /* mov */ + _regs.eip += ad_bytes; /* skip src displacement */ + break; + case 0xa2 ... 0xa3: /* mov */ length += ad_bytes; - _regs.eip += ad_bytes; /* skip dst displacement */ - break; - case 0xf6: - case 0xf7: /* Grp3 */ - switch (modrm_reg) - { - case 0: - case 1: /* test */ - /* - * Special case in Grp3: test has an - * immediate source operand. - */ - tmp = (d & BYTE_OP) ? 1 : op_bytes; - if (tmp == 8) - tmp = 4; - switch (tmp) + _regs.eip += ad_bytes; /* skip dst displacement */ + break; + case 0xf6 ... 0xf7: /* Grp3 */ + switch ( modrm_reg ) + { + case 0 ... 1: /* test */ + /* Special case in Grp3: test has an immediate source operand. */ + tmp = (d & ByteOp) ? 1 : op_bytes; + if ( tmp == 8 ) tmp = 4; + switch ( tmp ) { - case 1: - insn_fetch(s8, 1, _regs.eip, length); - break; - case 2: - insn_fetch(s16, 2, _regs.eip, length); - break; - case 4: - insn_fetch(s32, 4, _regs.eip, length); - break; + case 1: insn_fetch(int8_t, 1, _regs.eip, length); break; + case 2: insn_fetch(int16_t, 2, _regs.eip, length); break; + case 4: insn_fetch(int32_t, 4, _regs.eip, length); break; } goto done; - } + } break; } @@ -429,5 +475,5 @@ DPRINTF("Cannot emulate %02x at address %lx (eip %lx, mode %d)\n", b, (unsigned long)_regs.eip, (unsigned long)regs->eip, mode); svm_dump_inst(_regs.eip); - return (unsigned long)-1; + return -1; } _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |