ia64/xen-unstable

changeset 8955:5abf652c4c52

Fix SVM instruction decode, fixing problem with gfxboot package.

Signed-off-by: Tom Woller <thomas.woller@amd.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Feb 21 19:36:00 2006 +0100 (2006-02-21)
parents e9d5563c08be
children 03bc4062fe5f
files xen/arch/x86/hvm/svm/instrlen.c
line diff
     1.1 --- a/xen/arch/x86/hvm/svm/instrlen.c	Tue Feb 21 19:35:34 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/svm/instrlen.c	Tue Feb 21 19:36:00 2006 +0100
     1.3 @@ -2,17 +2,19 @@
     1.4   * instrlen.c - calculates the instruction length for all operating modes
     1.5   * 
     1.6   * Travis Betak, travis.betak@amd.com
     1.7 - * Copyright (c) 2005 AMD
     1.8 + * Copyright (c) 2005,2006 AMD
     1.9 + * Copyright (c) 2005 Keir Fraser
    1.10   *
    1.11 - * Essentially a very, very stripped version of Keir Fraser's work in 
    1.12 - * x86_emulate.c.  Used primarily for MMIO.
    1.13 + * Essentially a very, very stripped version of Keir Fraser's work in
    1.14 + * x86_emulate.c.  Used for MMIO.
    1.15   */
    1.16  
    1.17  /*
    1.18 - * TODO: the way in which we use svm_instrlen is very inefficient as is now 
    1.19 - * stands.  it will be worth while to return the actual instruction buffer
    1.20 - * along with the instruction length since we are getting the instruction length
    1.21 - * so we know how much of the buffer we need to fetch.
    1.22 + * TODO: the way in which we use svm_instrlen is very inefficient as is now
    1.23 + * stands.  It will be worth while to return the actual instruction buffer
    1.24 + * along with the instruction length since one of the reasons we are getting
    1.25 + * the instruction length is to know how many instruction bytes we need to
    1.26 + * fetch.
    1.27   */
    1.28  
    1.29  #include <xen/config.h>
    1.30 @@ -23,6 +25,11 @@
    1.31  #define DPRINTF DPRINTK
    1.32  #include <asm-x86/x86_emulate.h>
    1.33  
    1.34 +/* read from guest memory */
    1.35 +extern int inst_copy_from_guest(unsigned char *buf, unsigned long eip,
    1.36 +        int length);
    1.37 +extern void svm_dump_inst(unsigned long eip);
    1.38 +
    1.39  /*
    1.40   * Opcode effective-address decode tables.
    1.41   * Note that we only emulate instructions that have at least one memory
    1.42 @@ -33,98 +40,101 @@
    1.43   */
    1.44  
    1.45  /* Operand sizes: 8-bit operands or specified/overridden size. */
    1.46 -#define BYTE_OP      (1<<0)  /* 8-bit operands. */
    1.47 +#define ByteOp      (1<<0) /* 8-bit operands. */
    1.48  /* Destination operand type. */
    1.49 -#define IMPLICIT_OPS (1<<1)  /* Implicit in opcode. No generic decode. */
    1.50 -#define DST_REG      (2<<1)  /* Register operand. */
    1.51 -#define DST_MEM      (3<<1)  /* Memory operand. */
    1.52 -#define DST_MASK     (3<<1)
    1.53 +#define ImplicitOps (1<<1) /* Implicit in opcode. No generic decode. */
    1.54 +#define DstReg      (2<<1) /* Register operand. */
    1.55 +#define DstMem      (3<<1) /* Memory operand. */
    1.56 +#define DstMask     (3<<1)
    1.57  /* Source operand type. */
    1.58 -#define SRC_NONE     (0<<3)  /* No source operand. */
    1.59 -#define SRC_IMPLICIT (0<<3)  /* Source operand is implicit in the opcode. */
    1.60 -#define SRC_REG      (1<<3)  /* Register operand. */
    1.61 -#define SRC_MEM      (2<<3)  /* Memory operand. */
    1.62 -#define SRC_IMM      (3<<3)  /* Immediate operand. */
    1.63 -#define SRC_IMMBYTE  (4<<3)  /* 8-bit sign-extended immediate operand. */
    1.64 -#define SRC_MASK     (7<<3)
    1.65 -/* Generic MODRM decode. */
    1.66 -#define MODRM       (1<<6)
    1.67 +#define SrcNone     (0<<3) /* No source operand. */
    1.68 +#define SrcImplicit (0<<3) /* Source operand is implicit in the opcode. */
    1.69 +#define SrcReg      (1<<3) /* Register operand. */
    1.70 +#define SrcMem      (2<<3) /* Memory operand. */
    1.71 +#define SrcMem16    (3<<3) /* Memory operand (16-bit). */
    1.72 +#define SrcMem32    (4<<3) /* Memory operand (32-bit). */
    1.73 +#define SrcImm      (5<<3) /* Immediate operand. */
    1.74 +#define SrcImmByte  (6<<3) /* 8-bit sign-extended immediate operand. */
    1.75 +#define SrcMask     (7<<3)
    1.76 +/* Generic ModRM decode. */
    1.77 +#define ModRM       (1<<6)
    1.78  /* Destination is only written; never read. */
    1.79  #define Mov         (1<<7)
    1.80  
    1.81 -static u8 opcode_table[256] = {
    1.82 +static uint8_t opcode_table[256] = {
    1.83      /* 0x00 - 0x07 */
    1.84 -    BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
    1.85 -    BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
    1.86 +    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
    1.87 +    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
    1.88      0, 0, 0, 0,
    1.89      /* 0x08 - 0x0F */
    1.90 -    BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
    1.91 -    BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
    1.92 +    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
    1.93 +    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
    1.94      0, 0, 0, 0,
    1.95      /* 0x10 - 0x17 */
    1.96 -    BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
    1.97 -    BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
    1.98 +    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
    1.99 +    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
   1.100      0, 0, 0, 0,
   1.101      /* 0x18 - 0x1F */
   1.102 -    BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
   1.103 -    BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
   1.104 +    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
   1.105 +    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
   1.106      0, 0, 0, 0,
   1.107      /* 0x20 - 0x27 */
   1.108 -    BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
   1.109 -    BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
   1.110 +    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
   1.111 +    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
   1.112      0, 0, 0, 0,
   1.113      /* 0x28 - 0x2F */
   1.114 -    BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
   1.115 -    BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
   1.116 +    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
   1.117 +    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
   1.118      0, 0, 0, 0,
   1.119      /* 0x30 - 0x37 */
   1.120 -    BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
   1.121 -    BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
   1.122 +    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
   1.123 +    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
   1.124      0, 0, 0, 0,
   1.125      /* 0x38 - 0x3F */
   1.126 -    BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
   1.127 -    BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
   1.128 +    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
   1.129 +    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
   1.130      0, 0, 0, 0,
   1.131      /* 0x40 - 0x4F */
   1.132      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1.133      /* 0x50 - 0x5F */
   1.134      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1.135      /* 0x60 - 0x6F */
   1.136 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1.137 +    0, 0, 0, DstReg|SrcMem32|ModRM|Mov /* movsxd (x86/64) */,
   1.138 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1.139      /* 0x70 - 0x7F */
   1.140      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1.141      /* 0x80 - 0x87 */
   1.142 -    BYTE_OP | DST_MEM | SRC_IMM | MODRM, DST_MEM | SRC_IMM | MODRM,
   1.143 -    BYTE_OP | DST_MEM | SRC_IMM | MODRM, DST_MEM | SRC_IMMBYTE | MODRM,
   1.144 -    BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
   1.145 -    BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
   1.146 +    ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImm|ModRM,
   1.147 +    ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM,
   1.148 +    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
   1.149 +    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
   1.150      /* 0x88 - 0x8F */
   1.151 -    BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
   1.152 -    BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
   1.153 -    0, 0, 0, DST_MEM | SRC_NONE | MODRM | Mov,
   1.154 +    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
   1.155 +    ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
   1.156 +    0, 0, 0, DstMem|SrcNone|ModRM|Mov,
   1.157      /* 0x90 - 0x9F */
   1.158      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1.159      /* 0xA0 - 0xA7 */
   1.160 -    BYTE_OP | DST_REG | SRC_MEM | Mov, DST_REG | SRC_MEM | Mov,
   1.161 -    BYTE_OP | DST_MEM | SRC_REG | Mov, DST_MEM | SRC_REG | Mov,
   1.162 -    BYTE_OP | IMPLICIT_OPS | Mov, IMPLICIT_OPS | Mov,
   1.163 -    BYTE_OP | IMPLICIT_OPS, IMPLICIT_OPS,
   1.164 +    ByteOp|DstReg|SrcMem|Mov, DstReg|SrcMem|Mov,
   1.165 +    ByteOp|DstMem|SrcReg|Mov, DstMem|SrcReg|Mov,
   1.166 +    ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
   1.167 +    ByteOp|ImplicitOps, ImplicitOps,
   1.168      /* 0xA8 - 0xAF */
   1.169 -    0, 0, BYTE_OP | IMPLICIT_OPS | Mov, IMPLICIT_OPS | Mov,
   1.170 -    BYTE_OP | IMPLICIT_OPS | Mov, IMPLICIT_OPS | Mov,
   1.171 -    BYTE_OP | IMPLICIT_OPS, IMPLICIT_OPS,
   1.172 +    0, 0, ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
   1.173 +    ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
   1.174 +    ByteOp|ImplicitOps, ImplicitOps,
   1.175      /* 0xB0 - 0xBF */
   1.176 -    SRC_IMMBYTE, SRC_IMMBYTE, SRC_IMMBYTE, SRC_IMMBYTE, 
   1.177 -    SRC_IMMBYTE, SRC_IMMBYTE, SRC_IMMBYTE, SRC_IMMBYTE,
   1.178 +    SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte, 
   1.179 +    SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte, 
   1.180      0, 0, 0, 0, 0, 0, 0, 0,
   1.181      /* 0xC0 - 0xC7 */
   1.182 -    BYTE_OP | DST_MEM | SRC_IMM | MODRM, DST_MEM | SRC_IMMBYTE | MODRM, 0, 0,
   1.183 -    0, 0, BYTE_OP | DST_MEM | SRC_IMM | MODRM, DST_MEM | SRC_IMM | MODRM,
   1.184 +    ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM, 0, 0,
   1.185 +    0, 0, ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImm|ModRM,
   1.186      /* 0xC8 - 0xCF */
   1.187      0, 0, 0, 0, 0, 0, 0, 0,
   1.188      /* 0xD0 - 0xD7 */
   1.189 -    BYTE_OP | DST_MEM | SRC_IMPLICIT | MODRM, DST_MEM | SRC_IMPLICIT | MODRM,
   1.190 -    BYTE_OP | DST_MEM | SRC_IMPLICIT | MODRM, DST_MEM | SRC_IMPLICIT | MODRM,
   1.191 +    ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 
   1.192 +    ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 
   1.193      0, 0, 0, 0,
   1.194      /* 0xD8 - 0xDF */
   1.195      0, 0, 0, 0, 0, 0, 0, 0,
   1.196 @@ -132,31 +142,31 @@ static u8 opcode_table[256] = {
   1.197      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1.198      /* 0xF0 - 0xF7 */
   1.199      0, 0, 0, 0,
   1.200 -    0, 0, BYTE_OP | DST_MEM | SRC_NONE | MODRM, DST_MEM | SRC_NONE | MODRM,
   1.201 +    0, 0, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM,
   1.202      /* 0xF8 - 0xFF */
   1.203      0, 0, 0, 0,
   1.204 -    0, 0, BYTE_OP | DST_MEM | SRC_NONE | MODRM, DST_MEM | SRC_NONE | MODRM
   1.205 +    0, 0, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM
   1.206  };
   1.207  
   1.208 -static u8 twobyte_table[256] = {
   1.209 +static uint8_t twobyte_table[256] = {
   1.210      /* 0x00 - 0x0F */
   1.211 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, IMPLICIT_OPS | MODRM, 0, 0,
   1.212 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0,
   1.213      /* 0x10 - 0x1F */
   1.214 -    0, 0, 0, 0, 0, 0, 0, 0, IMPLICIT_OPS | MODRM, 0, 0, 0, 0, 0, 0, 0,
   1.215 +    0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0,
   1.216      /* 0x20 - 0x2F */
   1.217      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1.218      /* 0x30 - 0x3F */
   1.219      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1.220      /* 0x40 - 0x47 */
   1.221 -    DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
   1.222 -    DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
   1.223 -    DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
   1.224 -    DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
   1.225 +    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   1.226 +    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   1.227 +    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   1.228 +    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   1.229      /* 0x48 - 0x4F */
   1.230 -    DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
   1.231 -    DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
   1.232 -    DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
   1.233 -    DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
   1.234 +    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   1.235 +    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   1.236 +    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   1.237 +    DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov,
   1.238      /* 0x50 - 0x5F */
   1.239      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1.240      /* 0x60 - 0x6F */
   1.241 @@ -168,20 +178,17 @@ static u8 twobyte_table[256] = {
   1.242      /* 0x90 - 0x9F */
   1.243      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1.244      /* 0xA0 - 0xA7 */
   1.245 -    0, 0, 0, DST_MEM | SRC_REG | MODRM, 0, 0, 0, 0,
   1.246 +    0, 0, 0, DstMem|SrcReg|ModRM, 0, 0, 0, 0, 
   1.247      /* 0xA8 - 0xAF */
   1.248 -    0, 0, 0, DST_MEM | SRC_REG | MODRM, 0, 0, 0, 0,
   1.249 +    0, 0, 0, DstMem|SrcReg|ModRM, 0, 0, 0, 0,
   1.250      /* 0xB0 - 0xB7 */
   1.251 -    BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM, 0,
   1.252 -    DST_MEM | SRC_REG | MODRM,
   1.253 -    0, 0,
   1.254 -    DST_REG | SRC_MEM | MODRM,
   1.255 -    DST_REG | SRC_REG | MODRM,
   1.256 -
   1.257 +    ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, 0, DstMem|SrcReg|ModRM,
   1.258 +    0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov,
   1.259      /* 0xB8 - 0xBF */
   1.260 -    0, 0, DST_MEM | SRC_IMMBYTE | MODRM, DST_MEM | SRC_REG | MODRM, 0, 0, 0, 0,
   1.261 +    0, 0, DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM,
   1.262 +    0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov,
   1.263      /* 0xC0 - 0xCF */
   1.264 -    0, 0, 0, 0, 0, 0, 0, IMPLICIT_OPS | MODRM, 0, 0, 0, 0, 0, 0, 0, 0,
   1.265 +    0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0, 0,
   1.266      /* 0xD0 - 0xDF */
   1.267      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   1.268      /* 0xE0 - 0xEF */
   1.269 @@ -190,11 +197,6 @@ static u8 twobyte_table[256] = {
   1.270      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
   1.271  };
   1.272  
   1.273 -/* read from guest memory */
   1.274 -extern int inst_copy_from_guest(unsigned char *buf, unsigned long eip,
   1.275 -        int length);
   1.276 -extern void svm_dump_inst(unsigned long eip);
   1.277 -
   1.278  /* 
   1.279   * insn_fetch - fetch the next 1 to 4 bytes from instruction stream 
   1.280   * 
   1.281 @@ -219,206 +221,250 @@ extern void svm_dump_inst(unsigned long 
   1.282      (_type)_x; \
   1.283  })
   1.284  
   1.285 +
   1.286  /**
   1.287 - * get_instruction_length - returns the current instructions length
   1.288 + * svn_instrlen - returns the current instructions length
   1.289   *
   1.290   * @regs: guest register state
   1.291 - * @cr2:  target address
   1.292 - * @ops:  guest memory operations
   1.293   * @mode: guest operating mode
   1.294   *
   1.295   * EXTERNAL this routine calculates the length of the current instruction
   1.296   * pointed to by eip.  The guest state is _not_ changed by this routine.
   1.297   */
   1.298 -unsigned long svm_instrlen(struct cpu_user_regs *regs, int mode)
   1.299 +int svm_instrlen(struct cpu_user_regs *regs, int mode)
   1.300  {
   1.301 -    u8 b, d, twobyte = 0;
   1.302 -    u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
   1.303 -    unsigned int op_bytes = (mode == 8) ? 4 : mode, ad_bytes = mode;
   1.304 -    unsigned int i;
   1.305 +    uint8_t b, d, twobyte = 0, rex_prefix = 0;
   1.306 +    uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
   1.307 +    unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i;
   1.308      int rc = 0;
   1.309 -    u32 length = 0;
   1.310 -    u8 tmp;
   1.311 +    int length = 0;
   1.312 +    unsigned int tmp;
   1.313  
   1.314 -    /* Copy the registers so we don't alter the guest's present state */
   1.315 -    volatile struct cpu_user_regs _regs = *regs;
   1.316 +    /* Shadow copy of register state. Committed on successful emulation. */
   1.317 +    struct cpu_user_regs _regs = *regs;
   1.318  
   1.319 -        /* Check for Real Mode */
   1.320 -    if (mode == 2)
   1.321 -        _regs.eip += (_regs.cs << 4); 
   1.322 +    /* include CS for 16-bit modes */
   1.323 +    if (mode == X86EMUL_MODE_REAL || mode == X86EMUL_MODE_PROT16)
   1.324 +        _regs.eip += (_regs.cs << 4);
   1.325  
   1.326 -    /* Legacy prefix check */
   1.327 -    for (i = 0; i < 8; i++) {
   1.328 -        switch (b = insn_fetch(u8, 1, _regs.eip, length)) {
   1.329 -        case 0x66:  /* operand-size override */
   1.330 -            op_bytes ^= 6;  /* switch between 2/4 bytes */
   1.331 -            break;
   1.332 -        case 0x67:  /* address-size override */
   1.333 -            ad_bytes ^= (mode == 8) ? 12 : 6; /* 2/4/8 bytes */
   1.334 +    switch ( mode )
   1.335 +    {
   1.336 +    case X86EMUL_MODE_REAL:
   1.337 +    case X86EMUL_MODE_PROT16:
   1.338 +        op_bytes = ad_bytes = 2;
   1.339 +        break;
   1.340 +    case X86EMUL_MODE_PROT32:
   1.341 +        op_bytes = ad_bytes = 4;
   1.342 +        break;
   1.343 +#ifdef __x86_64__
   1.344 +    case X86EMUL_MODE_PROT64:
   1.345 +        op_bytes = 4;
   1.346 +        ad_bytes = 8;
   1.347 +        break;
   1.348 +#endif
   1.349 +    default:
   1.350 +        return -1;
   1.351 +    }
   1.352 +
   1.353 +    /* Legacy prefixes. */
   1.354 +    for ( i = 0; i < 8; i++ )
   1.355 +    {
   1.356 +        switch ( b = insn_fetch(uint8_t, 1, _regs.eip, length) )
   1.357 +        {
   1.358 +        case 0x66: /* operand-size override */
   1.359 +            op_bytes ^= 6;      /* switch between 2/4 bytes */
   1.360              break;
   1.361 -        case 0x2e:  /* CS override */
   1.362 -        case 0x3e:  /* DS override */
   1.363 -        case 0x26:  /* ES override */
   1.364 -        case 0x64:  /* FS override */
   1.365 -        case 0x65:  /* GS override */
   1.366 -        case 0x36:  /* SS override */
   1.367 -        case 0xf0:  /* LOCK */
   1.368 -        case 0xf3:  /* REP/REPE/REPZ */
   1.369 -        case 0xf2:  /* REPNE/REPNZ */
   1.370 +        case 0x67: /* address-size override */
   1.371 +            if ( mode == X86EMUL_MODE_PROT64 )
   1.372 +                ad_bytes ^= 12; /* switch between 4/8 bytes */
   1.373 +            else
   1.374 +                ad_bytes ^= 6;  /* switch between 2/4 bytes */
   1.375 +            break;
   1.376 +        case 0x2e: /* CS override */
   1.377 +        case 0x3e: /* DS override */
   1.378 +        case 0x26: /* ES override */
   1.379 +        case 0x64: /* FS override */
   1.380 +        case 0x65: /* GS override */
   1.381 +        case 0x36: /* SS override */
   1.382 +            break;
   1.383 +        case 0xf0: /* LOCK */
   1.384 +            lock_prefix = 1;
   1.385 +            break;
   1.386 +        case 0xf3: /* REP/REPE/REPZ */
   1.387 +            rep_prefix = 1;
   1.388 +            break;
   1.389 +        case 0xf2: /* REPNE/REPNZ */
   1.390              break;
   1.391          default:
   1.392              goto done_prefixes;
   1.393          }
   1.394      }
   1.395 -
   1.396  done_prefixes:
   1.397  
   1.398 -    /* REX prefix check */
   1.399 -    if ((mode == 8) && ((b & 0xf0) == 0x40))
   1.400 +    /* Note quite the same as 80386 real mode, but hopefully good enough. */
   1.401 +    if ( (mode == X86EMUL_MODE_REAL) && (ad_bytes != 2) ) {
   1.402 +        printf("sonofabitch!! we don't support 32-bit addresses in realmode\n");
   1.403 +        goto cannot_emulate;
   1.404 +    }
   1.405 +
   1.406 +    /* REX prefix. */
   1.407 +    if ( (mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40) )
   1.408      {
   1.409 -        if (b & 8)
   1.410 -            op_bytes = 8;   /* REX.W */
   1.411 -        modrm_reg = (b & 4) << 1;   /* REX.R */
   1.412 +        rex_prefix = b;
   1.413 +        if ( b & 8 )
   1.414 +            op_bytes = 8;          /* REX.W */
   1.415 +        modrm_reg = (b & 4) << 1;  /* REX.R */
   1.416          /* REX.B and REX.X do not need to be decoded. */
   1.417 -        b = insn_fetch(u8, 1, _regs.eip, length);
   1.418 +        b = insn_fetch(uint8_t, 1, _regs.eip, length);
   1.419      }
   1.420  
   1.421      /* Opcode byte(s). */
   1.422      d = opcode_table[b];
   1.423 -    if (d == 0) 
   1.424 +    if ( d == 0 )
   1.425      {
   1.426          /* Two-byte opcode? */
   1.427 -        if (b == 0x0f) {
   1.428 +        if ( b == 0x0f )
   1.429 +        {
   1.430              twobyte = 1;
   1.431 -            b = insn_fetch(u8, 1, _regs.eip, length);
   1.432 +            b = insn_fetch(uint8_t, 1, _regs.eip, length);
   1.433              d = twobyte_table[b];
   1.434          }
   1.435  
   1.436          /* Unrecognised? */
   1.437 -        if (d == 0)
   1.438 +        if ( d == 0 )
   1.439              goto cannot_emulate;
   1.440      }
   1.441  
   1.442 -    /* MODRM and SIB bytes. */
   1.443 -    if (d & MODRM) 
   1.444 +    /* ModRM and SIB bytes. */
   1.445 +    if ( d & ModRM )
   1.446      {
   1.447 -        modrm = insn_fetch(u8, 1, _regs.eip, length);
   1.448 +        modrm = insn_fetch(uint8_t, 1, _regs.eip, length);
   1.449          modrm_mod |= (modrm & 0xc0) >> 6;
   1.450          modrm_reg |= (modrm & 0x38) >> 3;
   1.451 -        modrm_rm |= (modrm & 0x07);
   1.452 -        switch (modrm_mod) 
   1.453 +        modrm_rm  |= (modrm & 0x07);
   1.454 +
   1.455 +        if ( modrm_mod == 3 )
   1.456 +        {
   1.457 +            DPRINTF("Cannot parse ModRM.mod == 3.\n");
   1.458 +            goto cannot_emulate;
   1.459 +        }
   1.460 +
   1.461 +        if ( ad_bytes == 2 )
   1.462          {
   1.463 -        case 0:
   1.464 -            if ((modrm_rm == 4) &&
   1.465 -                (((insn_fetch(u8, 1, _regs.eip,
   1.466 -                      length)) & 7) == 5)) 
   1.467 +            /* 16-bit ModR/M decode. */
   1.468 +            switch ( modrm_mod )
   1.469 +            {
   1.470 +            case 0:
   1.471 +                if ( modrm_rm == 6 ) 
   1.472 +                {
   1.473 +                    length += 2;
   1.474 +                    _regs.eip += 2; /* skip disp16 */
   1.475 +                }
   1.476 +                break;
   1.477 +            case 1:
   1.478 +                length += 1;
   1.479 +                _regs.eip += 1; /* skip disp8 */
   1.480 +                break;
   1.481 +            case 2:
   1.482 +                length += 2;
   1.483 +                _regs.eip += 2; /* skip disp16 */
   1.484 +                break;
   1.485 +            }
   1.486 +        }
   1.487 +        else
   1.488 +        {
   1.489 +            /* 32/64-bit ModR/M decode. */
   1.490 +            switch ( modrm_mod )
   1.491              {
   1.492 -                length += 4;
   1.493 -                _regs.eip += 4; /* skip SIB.base disp32 */
   1.494 -            } 
   1.495 -            else if (modrm_rm == 5) 
   1.496 -            {
   1.497 +            case 0:
   1.498 +                if ( (modrm_rm == 4) && 
   1.499 +                     (((insn_fetch(uint8_t, 1, _regs.eip, length)) & 7) 
   1.500 +                        == 5) )
   1.501 +                {
   1.502 +                    length += 4;
   1.503 +                    _regs.eip += 4; /* skip disp32 specified by SIB.base */
   1.504 +                }
   1.505 +                else if ( modrm_rm == 5 )
   1.506 +                {
   1.507 +                    length += 4;
   1.508 +                    _regs.eip += 4; /* skip disp32 */
   1.509 +                }
   1.510 +                break;
   1.511 +            case 1:
   1.512 +                if ( modrm_rm == 4 )
   1.513 +                {
   1.514 +                    insn_fetch(uint8_t, 1, _regs.eip, length);
   1.515 +                }
   1.516 +                length += 1;
   1.517 +                _regs.eip += 1; /* skip disp8 */
   1.518 +                break;
   1.519 +            case 2:
   1.520 +                if ( modrm_rm == 4 )
   1.521 +                {
   1.522 +                    insn_fetch(uint8_t, 1, _regs.eip, length);
   1.523 +                }
   1.524                  length += 4;
   1.525                  _regs.eip += 4; /* skip disp32 */
   1.526 -            }
   1.527 -            break;
   1.528 -        case 1:
   1.529 -            if (modrm_rm == 4) 
   1.530 -            {
   1.531 -                insn_fetch(u8, 1, _regs.eip, length);
   1.532 +                break;
   1.533              }
   1.534 -            length += 1;
   1.535 -            _regs.eip += 1; /* skip disp8 */
   1.536 -            break;
   1.537 -        case 2:
   1.538 -            if (modrm_rm == 4)
   1.539 -            {
   1.540 -                insn_fetch(u8, 1, _regs.eip, length);
   1.541 -            }
   1.542 -            length += 4;
   1.543 -            _regs.eip += 4; /* skip disp32 */
   1.544 -            break;
   1.545 -        case 3:
   1.546 -            DPRINTF("Cannot parse ModRM.mod == 3.\n");
   1.547 -            goto cannot_emulate;
   1.548          }
   1.549      }
   1.550  
   1.551      /* Decode and fetch the destination operand: register or memory. */
   1.552 -    switch (d & DST_MASK) 
   1.553 +    switch ( d & DstMask )
   1.554      {
   1.555 -    case IMPLICIT_OPS:
   1.556 +    case ImplicitOps:
   1.557          /* Special instructions do their own operand decoding. */
   1.558          goto done;
   1.559      }
   1.560  
   1.561 -    /* Decode and fetch the source operand: register, memory or immediate */
   1.562 -    switch (d & SRC_MASK) 
   1.563 +    /* Decode and fetch the source operand: register, memory or immediate. */
   1.564 +    switch ( d & SrcMask )
   1.565      {
   1.566 -    case SRC_IMM:
   1.567 -        tmp = (d & BYTE_OP) ? 1 : op_bytes;
   1.568 -        if (tmp == 8)
   1.569 -            tmp = 4;
   1.570 +    case SrcImm:
   1.571 +        tmp = (d & ByteOp) ? 1 : op_bytes;
   1.572 +        if ( tmp == 8 ) tmp = 4;
   1.573          /* NB. Immediates are sign-extended as necessary. */
   1.574 -        switch (tmp) {
   1.575 -        case 1:
   1.576 -            insn_fetch(s8, 1, _regs.eip, length);
   1.577 -            break;
   1.578 -        case 2:
   1.579 -            insn_fetch(s16, 2, _regs.eip, length);
   1.580 -            break;
   1.581 -        case 4:
   1.582 -            insn_fetch(s32, 4, _regs.eip, length);
   1.583 -            break;
   1.584 +        switch ( tmp )
   1.585 +        {
   1.586 +        case 1: insn_fetch(int8_t,  1, _regs.eip, length); break;
   1.587 +        case 2: insn_fetch(int16_t, 2, _regs.eip, length); break;
   1.588 +        case 4: insn_fetch(int32_t, 4, _regs.eip, length); break;
   1.589          }
   1.590          break;
   1.591 -    case SRC_IMMBYTE:
   1.592 -        insn_fetch(s8, 1, _regs.eip, length);
   1.593 +    case SrcImmByte:
   1.594 +        insn_fetch(int8_t,  1, _regs.eip, length);
   1.595          break;
   1.596      }
   1.597  
   1.598 -    if (twobyte)
   1.599 +    if ( twobyte )
   1.600          goto done;
   1.601  
   1.602 -    switch (b) 
   1.603 +    switch ( b )
   1.604      {
   1.605 -    case 0xa0:
   1.606 -    case 0xa1:      /* mov */
   1.607 +    case 0xa0 ... 0xa1: /* mov */
   1.608          length += ad_bytes;
   1.609 -        _regs.eip += ad_bytes;  /* skip src displacement */
   1.610 +        _regs.eip += ad_bytes; /* skip src displacement */
   1.611          break;
   1.612 -    case 0xa2:
   1.613 -    case 0xa3:      /* mov */
   1.614 +    case 0xa2 ... 0xa3: /* mov */
   1.615          length += ad_bytes;
   1.616 -        _regs.eip += ad_bytes;  /* skip dst displacement */
   1.617 +        _regs.eip += ad_bytes; /* skip dst displacement */
   1.618          break;
   1.619 -    case 0xf6:
   1.620 -    case 0xf7:      /* Grp3 */
   1.621 -        switch (modrm_reg) 
   1.622 +    case 0xf6 ... 0xf7: /* Grp3 */
   1.623 +        switch ( modrm_reg )
   1.624          {
   1.625 -        case 0:
   1.626 -        case 1: /* test */
   1.627 -            /* 
   1.628 -             * Special case in Grp3: test has an 
   1.629 -             * immediate source operand. 
   1.630 -             */
   1.631 -            tmp = (d & BYTE_OP) ? 1 : op_bytes;
   1.632 -            if (tmp == 8)
   1.633 -                tmp = 4;
   1.634 -            switch (tmp) 
   1.635 +        case 0 ... 1: /* test */
   1.636 +            /* Special case in Grp3: test has an immediate source operand. */
   1.637 +            tmp = (d & ByteOp) ? 1 : op_bytes;
   1.638 +            if ( tmp == 8 ) tmp = 4;
   1.639 +            switch ( tmp )
   1.640              {
   1.641 -            case 1:
   1.642 -                insn_fetch(s8, 1, _regs.eip, length);
   1.643 -                break;
   1.644 -            case 2:
   1.645 -                insn_fetch(s16, 2, _regs.eip, length);
   1.646 -                break;
   1.647 -            case 4:
   1.648 -                insn_fetch(s32, 4, _regs.eip, length);
   1.649 -                break;
   1.650 +            case 1: insn_fetch(int8_t,  1, _regs.eip, length); break;
   1.651 +            case 2: insn_fetch(int16_t, 2, _regs.eip, length); break;
   1.652 +            case 4: insn_fetch(int32_t, 4, _regs.eip, length); break;
   1.653              }
   1.654              goto done;
   1.655 -        }
   1.656 +	}
   1.657          break;
   1.658      }
   1.659  
   1.660 @@ -429,5 +475,5 @@ cannot_emulate:
   1.661      DPRINTF("Cannot emulate %02x at address %lx (eip %lx, mode %d)\n",
   1.662              b, (unsigned long)_regs.eip, (unsigned long)regs->eip, mode);
   1.663      svm_dump_inst(_regs.eip);
   1.664 -    return (unsigned long)-1;
   1.665 +    return -1;
   1.666  }