direct-io.hg

changeset 13292:f240c09f08d2

[XEN] Emulate relative near/short jumps, including Jcc.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Mon Jan 08 15:52:53 2007 +0000 (2007-01-08)
parents 5eeb4bac1b17
children dbb387175f1b
files xen/arch/x86/x86_emulate.c
line diff
     1.1 --- a/xen/arch/x86/x86_emulate.c	Mon Jan 08 14:26:57 2007 +0000
     1.2 +++ b/xen/arch/x86/x86_emulate.c	Mon Jan 08 15:52:53 2007 +0000
     1.3 @@ -88,8 +88,12 @@ static uint8_t opcode_table[256] = {
     1.4      /* 0x60 - 0x6F */
     1.5      0, 0, 0, DstReg|SrcMem32|ModRM|Mov /* movsxd (x86/64) */,
     1.6      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     1.7 -    /* 0x70 - 0x7F */
     1.8 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     1.9 +    /* 0x70 - 0x77 */
    1.10 +    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
    1.11 +    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
    1.12 +    /* 0x78 - 0x7F */
    1.13 +    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
    1.14 +    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
    1.15      /* 0x80 - 0x87 */
    1.16      ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImm|ModRM,
    1.17      ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM,
    1.18 @@ -130,8 +134,10 @@ static uint8_t opcode_table[256] = {
    1.19      0, 0, 0, 0,
    1.20      /* 0xD8 - 0xDF */
    1.21      0, 0, 0, 0, 0, 0, 0, 0,
    1.22 -    /* 0xE0 - 0xEF */
    1.23 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    1.24 +    /* 0xE0 - 0xE7 */
    1.25 +    0, 0, 0, ImplicitOps, 0, 0, 0, 0,
    1.26 +    /* 0xE8 - 0xEF */
    1.27 +    0, ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0,
    1.28      /* 0xF0 - 0xF7 */
    1.29      0, 0, 0, 0,
    1.30      0, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM,
    1.31 @@ -165,8 +171,12 @@ static uint8_t twobyte_table[256] = {
    1.32      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    1.33      /* 0x70 - 0x7F */
    1.34      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    1.35 -    /* 0x80 - 0x8F */
    1.36 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    1.37 +    /* 0x80 - 0x87 */
    1.38 +    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
    1.39 +    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
    1.40 +    /* 0x88 - 0x8F */
    1.41 +    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
    1.42 +    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
    1.43      /* 0x90 - 0x9F */
    1.44      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    1.45      /* 0xA0 - 0xA7 */
    1.46 @@ -380,32 +390,83 @@ do{ __asm__ __volatile__ (              
    1.47  
    1.48  /* Fetch next part of the instruction being emulated. */
    1.49  #define insn_fetch_bytes(_size)                                         \
    1.50 -({ unsigned long _x;                                                    \
    1.51 -   rc = ops->insn_fetch(x86_seg_cs, _regs.eip, &_x, (_size), ctxt);     \
    1.52 +({ unsigned long _x, _eip = _truncate_ea(_regs.eip, def_ad_bytes);      \
    1.53 +   rc = ops->insn_fetch(x86_seg_cs, _eip, &_x, (_size), ctxt);          \
    1.54     if ( rc != 0 )                                                       \
    1.55         goto done;                                                       \
    1.56 -   _regs.eip += (_size);                                                \
    1.57 +   _register_address_increment(_regs.eip, (_size), def_ad_bytes);       \
    1.58     _x;                                                                  \
    1.59  })
    1.60  #define insn_fetch_type(_type) ((_type)insn_fetch_bytes(sizeof(_type)))
    1.61  
    1.62 -#define truncate_ea(ea)                                 \
    1.63 +#define _truncate_ea(ea, byte_width)                    \
    1.64  ({  unsigned long __ea = (ea);                          \
    1.65 -    ((ad_bytes == sizeof(unsigned long)) ? __ea :       \
    1.66 -     (__ea & ((1UL << (ad_bytes << 3)) - 1)));          \
    1.67 +    (((byte_width) == sizeof(unsigned long)) ? __ea :   \
    1.68 +     (__ea & ((1UL << ((byte_width) << 3)) - 1)));      \
    1.69  })
    1.70 +#define truncate_ea(ea) _truncate_ea((ea), ad_bytes)
    1.71  
    1.72  /* Update address held in a register, based on addressing mode. */
    1.73 -#define register_address_increment(reg, inc)                            \
    1.74 +#define _register_address_increment(reg, inc, byte_width)               \
    1.75  do {                                                                    \
    1.76      int _inc = (inc); /* signed type ensures sign extension to long */  \
    1.77 -    if ( ad_bytes == sizeof(unsigned long) )                            \
    1.78 +    if ( (byte_width) == sizeof(unsigned long) )                        \
    1.79          (reg) += _inc;                                                  \
    1.80 +    else if ( mode == X86EMUL_MODE_PROT64 )                             \
    1.81 +        (reg) = ((reg) + _inc) & ((1UL << ((byte_width) << 3)) - 1);    \
    1.82      else                                                                \
    1.83 -        (reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) |             \
    1.84 -                (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1));      \
    1.85 +        (reg) = ((reg) & ~((1UL << ((byte_width) << 3)) - 1)) |         \
    1.86 +                (((reg) + _inc) & ((1UL << ((byte_width) << 3)) - 1));  \
    1.87 +} while (0)
    1.88 +#define register_address_increment(reg, inc) \
    1.89 +    _register_address_increment((reg), (inc), ad_bytes)
    1.90 +
    1.91 +#define jmp_rel(rel)                                                    \
    1.92 +do {                                                                    \
    1.93 +    _regs.eip += (int)(rel);                                            \
    1.94 +    if ( mode != X86EMUL_MODE_PROT64 )                                  \
    1.95 +        _regs.eip = ((op_bytes == 2)                                    \
    1.96 +                     ? (uint16_t)_regs.eip : (uint32_t)_regs.eip);      \
    1.97  } while (0)
    1.98  
    1.99 +static int
   1.100 +test_cc(
   1.101 +    unsigned int condition, unsigned int flags)
   1.102 +{
   1.103 +    int rc = 0;
   1.104 +
   1.105 +    switch ( (condition & 15) >> 1 )
   1.106 +    {
   1.107 +    case 0: /* o */
   1.108 +        rc |= (flags & EFLG_OF);
   1.109 +        break;
   1.110 +    case 1: /* b/c/nae */
   1.111 +        rc |= (flags & EFLG_CF);
   1.112 +        break;
   1.113 +    case 2: /* z/e */
   1.114 +        rc |= (flags & EFLG_ZF);
   1.115 +        break;
   1.116 +    case 3: /* be/na */
   1.117 +        rc |= (flags & (EFLG_CF|EFLG_ZF));
   1.118 +        break;
   1.119 +    case 4: /* s */
   1.120 +        rc |= (flags & EFLG_SF);
   1.121 +        break;
   1.122 +    case 5: /* p/pe */
   1.123 +        rc |= (flags & EFLG_PF);
   1.124 +        break;
   1.125 +    case 7: /* le/ng */
   1.126 +        rc |= (flags & EFLG_ZF);
   1.127 +        /* fall through */
   1.128 +    case 6: /* l/nge */
   1.129 +        rc |= (!(flags & EFLG_SF) != !(flags & EFLG_OF));
   1.130 +        break;
   1.131 +    }
   1.132 +
   1.133 +    /* Odd condition identifiers (lsb == 1) have inverted sense. */
   1.134 +    return (!!rc ^ (condition & 1));
   1.135 +}
   1.136 +
   1.137  void *
   1.138  decode_register(
   1.139      uint8_t modrm_reg, struct cpu_user_regs *regs, int highbyte_regs)
   1.140 @@ -456,7 +517,8 @@ x86_emulate(
   1.141  
   1.142      uint8_t b, d, sib, sib_index, sib_base, twobyte = 0, rex_prefix = 0;
   1.143      uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
   1.144 -    unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i;
   1.145 +    unsigned int op_bytes, ad_bytes, def_ad_bytes;
   1.146 +    unsigned int lock_prefix = 0, rep_prefix = 0, i;
   1.147      int rc = 0;
   1.148      struct operand src, dst;
   1.149      int mode = ctxt->mode;
   1.150 @@ -473,21 +535,23 @@ x86_emulate(
   1.151      {
   1.152      case X86EMUL_MODE_REAL:
   1.153      case X86EMUL_MODE_PROT16:
   1.154 -        op_bytes = ad_bytes = 2;
   1.155 +        op_bytes = def_ad_bytes = 2;
   1.156          break;
   1.157      case X86EMUL_MODE_PROT32:
   1.158 -        op_bytes = ad_bytes = 4;
   1.159 +        op_bytes = def_ad_bytes = 4;
   1.160          break;
   1.161  #ifdef __x86_64__
   1.162      case X86EMUL_MODE_PROT64:
   1.163          op_bytes = 4;
   1.164 -        ad_bytes = 8;
   1.165 +        def_ad_bytes = 8;
   1.166          break;
   1.167  #endif
   1.168      default:
   1.169          return -1;
   1.170      }
   1.171  
   1.172 +    ad_bytes = def_ad_bytes;
   1.173 +
   1.174      /* Prefix bytes. */
   1.175      for ( i = 0; i < 8; i++ )
   1.176      {
   1.177 @@ -820,53 +884,62 @@ x86_emulate(
   1.178      case 0x00 ... 0x03: add: /* add */
   1.179          emulate_2op_SrcV("add", src, dst, _regs.eflags);
   1.180          break;
   1.181 +
   1.182      case 0x0c ... 0x0d: /* or imm,%%eax */
   1.183          dst.reg = (unsigned long *)&_regs.eax;
   1.184          dst.val = dst.orig_val = _regs.eax;
   1.185      case 0x08 ... 0x0b: or:  /* or */
   1.186          emulate_2op_SrcV("or", src, dst, _regs.eflags);
   1.187          break;
   1.188 +
   1.189      case 0x14 ... 0x15: /* adc imm,%%eax */
   1.190          dst.reg = (unsigned long *)&_regs.eax;
   1.191          dst.val = dst.orig_val = _regs.eax;
   1.192      case 0x10 ... 0x13: adc: /* adc */
   1.193          emulate_2op_SrcV("adc", src, dst, _regs.eflags);
   1.194          break;
   1.195 +
   1.196      case 0x1c ... 0x1d: /* sbb imm,%%eax */
   1.197          dst.reg = (unsigned long *)&_regs.eax;
   1.198          dst.val = dst.orig_val = _regs.eax;
   1.199      case 0x18 ... 0x1b: sbb: /* sbb */
   1.200          emulate_2op_SrcV("sbb", src, dst, _regs.eflags);
   1.201          break;
   1.202 +
   1.203      case 0x24 ... 0x25: /* and imm,%%eax */
   1.204          dst.reg = (unsigned long *)&_regs.eax;
   1.205          dst.val = dst.orig_val = _regs.eax;
   1.206      case 0x20 ... 0x23: and: /* and */
   1.207          emulate_2op_SrcV("and", src, dst, _regs.eflags);
   1.208          break;
   1.209 +
   1.210      case 0x2c ... 0x2d: /* sub imm,%%eax */
   1.211          dst.reg = (unsigned long *)&_regs.eax;
   1.212          dst.val = dst.orig_val = _regs.eax;
   1.213      case 0x28 ... 0x2b: sub: /* sub */
   1.214          emulate_2op_SrcV("sub", src, dst, _regs.eflags);
   1.215          break;
   1.216 +
   1.217      case 0x34 ... 0x35: /* xor imm,%%eax */
   1.218          dst.reg = (unsigned long *)&_regs.eax;
   1.219          dst.val = dst.orig_val = _regs.eax;
   1.220      case 0x30 ... 0x33: xor: /* xor */
   1.221          emulate_2op_SrcV("xor", src, dst, _regs.eflags);
   1.222          break;
   1.223 +
   1.224      case 0x3c ... 0x3d: /* cmp imm,%%eax */
   1.225          dst.reg = (unsigned long *)&_regs.eax;
   1.226          dst.val = dst.orig_val = _regs.eax;
   1.227      case 0x38 ... 0x3b: cmp: /* cmp */
   1.228          emulate_2op_SrcV("cmp", src, dst, _regs.eflags);
   1.229          break;
   1.230 +
   1.231      case 0x63: /* movsxd */
   1.232          if ( mode != X86EMUL_MODE_PROT64 )
   1.233              goto cannot_emulate;
   1.234          dst.val = (int32_t)src.val;
   1.235          break;
   1.236 +
   1.237      case 0x80 ... 0x83: /* Grp1 */
   1.238          switch ( modrm_reg & 7 )
   1.239          {
   1.240 @@ -880,9 +953,11 @@ x86_emulate(
   1.241          case 7: goto cmp;
   1.242          }
   1.243          break;
   1.244 +
   1.245      case 0x84 ... 0x85: test: /* test */
   1.246          emulate_2op_SrcV("test", src, dst, _regs.eflags);
   1.247          break;
   1.248 +
   1.249      case 0x86 ... 0x87: xchg: /* xchg */
   1.250          /* Write back the register source. */
   1.251          switch ( dst.bytes )
   1.252 @@ -896,13 +971,16 @@ x86_emulate(
   1.253          dst.val = src.val;
   1.254          lock_prefix = 1;
   1.255          break;
   1.256 +
   1.257      case 0x88 ... 0x8b: /* mov */
   1.258      case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
   1.259          dst.val = src.val;
   1.260          break;
   1.261 +
   1.262      case 0x8d: /* lea */
   1.263          dst.val = ea.mem.off;
   1.264          break;
   1.265 +
   1.266      case 0x8f: /* pop (sole member of Grp1a) */
   1.267          /* 64-bit mode: POP defaults to a 64-bit operand. */
   1.268          if ( (mode == X86EMUL_MODE_PROT64) && (dst.bytes == 4) )
   1.269 @@ -912,11 +990,13 @@ x86_emulate(
   1.270              goto done;
   1.271          register_address_increment(_regs.esp, dst.bytes);
   1.272          break;
   1.273 +
   1.274      case 0xb0 ... 0xb7: /* mov imm8,r8 */
   1.275          dst.reg = decode_register(
   1.276              (b & 7) | ((rex_prefix & 1) << 3), &_regs, (rex_prefix == 0));
   1.277          dst.val = src.val;
   1.278          break;
   1.279 +
   1.280      case 0xb8 ... 0xbf: /* mov imm{16,32,64},r{16,32,64} */
   1.281          if ( dst.bytes == 8 ) /* Fetch more bytes to obtain imm64 */
   1.282              src.val = ((uint32_t)src.val |
   1.283 @@ -925,6 +1005,7 @@ x86_emulate(
   1.284              (b & 7) | ((rex_prefix & 1) << 3), &_regs, 0);
   1.285          dst.val = src.val;
   1.286          break;
   1.287 +
   1.288      case 0xc0 ... 0xc1: grp2: /* Grp2 */
   1.289          switch ( modrm_reg & 7 )
   1.290          {
   1.291 @@ -952,12 +1033,15 @@ x86_emulate(
   1.292              break;
   1.293          }
   1.294          break;
   1.295 +
   1.296      case 0xd0 ... 0xd1: /* Grp2 */
   1.297          src.val = 1;
   1.298          goto grp2;
   1.299 +
   1.300      case 0xd2 ... 0xd3: /* Grp2 */
   1.301          src.val = _regs.ecx;
   1.302          goto grp2;
   1.303 +
   1.304      case 0xf6 ... 0xf7: /* Grp3 */
   1.305          switch ( modrm_reg & 7 )
   1.306          {
   1.307 @@ -983,6 +1067,7 @@ x86_emulate(
   1.308              goto cannot_emulate;
   1.309          }
   1.310          break;
   1.311 +
   1.312      case 0xfe ... 0xff: /* Grp4/Grp5 */
   1.313          switch ( modrm_reg & 7 )
   1.314          {
   1.315 @@ -1052,8 +1137,10 @@ x86_emulate(
   1.316   special_insn:
   1.317      /* Default action: disable writeback. There may be no dest operand. */
   1.318      dst.orig_val = dst.val;
   1.319 +
   1.320      if ( twobyte )
   1.321          goto twobyte_special_insn;
   1.322 +
   1.323      if ( rep_prefix )
   1.324      {
   1.325          if ( _regs.ecx == 0 )
   1.326 @@ -1064,6 +1151,7 @@ x86_emulate(
   1.327          _regs.ecx--;
   1.328          _regs.eip = ctxt->regs->eip;
   1.329      }
   1.330 +
   1.331      switch ( b )
   1.332      {
   1.333      case 0x40 ... 0x4f: /* inc/dec reg */
   1.334 @@ -1076,6 +1164,7 @@ x86_emulate(
   1.335          else
   1.336              emulate_1op("inc", dst, _regs.eflags);
   1.337          break;
   1.338 +
   1.339      case 0x50 ... 0x57: /* push reg */
   1.340          dst.type  = OP_MEM;
   1.341          dst.bytes = op_bytes;
   1.342 @@ -1087,6 +1176,7 @@ x86_emulate(
   1.343          dst.mem.seg = x86_seg_ss;
   1.344          dst.mem.off = truncate_ea(_regs.esp);
   1.345          break;
   1.346 +
   1.347      case 0x58 ... 0x5f: /* pop reg */
   1.348          dst.type  = OP_REG;
   1.349          dst.reg   = decode_register(
   1.350 @@ -1099,9 +1189,18 @@ x86_emulate(
   1.351              goto done;
   1.352          register_address_increment(_regs.esp, dst.bytes);
   1.353          break;
   1.354 +
   1.355 +    case 0x70 ... 0x7f: /* jcc (short) */ {
   1.356 +        int rel = insn_fetch_type(int8_t);
   1.357 +        if ( test_cc(b, _regs.eflags) )
   1.358 +            jmp_rel(rel);
   1.359 +        break;
   1.360 +    }
   1.361 +
   1.362      case 0x90: /* nop / xchg %%r8,%%rax */
   1.363          if ( !(rex_prefix & 1) )
   1.364              break; /* nop */
   1.365 +
   1.366      case 0x91 ... 0x97: /* xchg reg,%%rax */
   1.367          src.type = dst.type = OP_REG;
   1.368          src.bytes = dst.bytes = op_bytes;
   1.369 @@ -1111,6 +1210,7 @@ x86_emulate(
   1.370              (b & 7) | ((rex_prefix & 1) << 3), &_regs, 0);
   1.371          dst.val  = dst.orig_val = *dst.reg;
   1.372          goto xchg;
   1.373 +
   1.374      case 0xa0 ... 0xa1: /* mov mem.offs,{%al,%ax,%eax,%rax} */
   1.375          /* Source EA is not encoded via ModRM. */
   1.376          dst.type  = OP_REG;
   1.377 @@ -1120,6 +1220,7 @@ x86_emulate(
   1.378                               &dst.val, dst.bytes, ctxt)) != 0 )
   1.379              goto done;
   1.380          break;
   1.381 +
   1.382      case 0xa2 ... 0xa3: /* mov {%al,%ax,%eax,%rax},mem.offs */
   1.383          /* Destination EA is not encoded via ModRM. */
   1.384          dst.type  = OP_MEM;
   1.385 @@ -1128,6 +1229,7 @@ x86_emulate(
   1.386          dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   1.387          dst.val   = (unsigned long)_regs.eax;
   1.388          break;
   1.389 +
   1.390      case 0xa4 ... 0xa5: /* movs */
   1.391          dst.type  = OP_MEM;
   1.392          dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   1.393 @@ -1141,6 +1243,7 @@ x86_emulate(
   1.394          register_address_increment(
   1.395              _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
   1.396          break;
   1.397 +
   1.398      case 0xaa ... 0xab: /* stos */
   1.399          dst.type  = OP_MEM;
   1.400          dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   1.401 @@ -1150,6 +1253,7 @@ x86_emulate(
   1.402          register_address_increment(
   1.403              _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
   1.404          break;
   1.405 +
   1.406      case 0xac ... 0xad: /* lods */
   1.407          dst.type  = OP_REG;
   1.408          dst.bytes = (d & ByteOp) ? 1 : op_bytes;
   1.409 @@ -1160,18 +1264,40 @@ x86_emulate(
   1.410          register_address_increment(
   1.411              _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
   1.412          break;
   1.413 +
   1.414 +    case 0xe3: /* jcxz/jecxz (short) */ {
   1.415 +        int rel = insn_fetch_type(int8_t);
   1.416 +        if ( (ad_bytes == 2) ? !(uint16_t)_regs.ecx :
   1.417 +             (ad_bytes == 4) ? !(uint32_t)_regs.ecx : !_regs.ecx )
   1.418 +            jmp_rel(rel);
   1.419 +        break;
   1.420 +    }
   1.421 +
   1.422 +    case 0xe9: /* jmp (short) */
   1.423 +        jmp_rel(insn_fetch_type(int8_t));
   1.424 +        break;
   1.425 +
   1.426 +    case 0xeb: /* jmp (near) */
   1.427 +        jmp_rel(insn_fetch_bytes(
   1.428 +            (mode == X86EMUL_MODE_PROT64) ? 4 : op_bytes));
   1.429 +        break;
   1.430 +
   1.431      case 0xf5: /* cmc */
   1.432          _regs.eflags ^= EFLG_CF;
   1.433          break;
   1.434 +
   1.435      case 0xf8: /* clc */
   1.436          _regs.eflags &= ~EFLG_CF;
   1.437          break;
   1.438 +
   1.439      case 0xf9: /* stc */
   1.440          _regs.eflags |= EFLG_CF;
   1.441          break;
   1.442 +
   1.443      case 0xfc: /* cld */
   1.444          _regs.eflags &= ~EFLG_DF;
   1.445          break;
   1.446 +
   1.447      case 0xfd: /* std */
   1.448          _regs.eflags |= EFLG_DF;
   1.449          break;
   1.450 @@ -1183,39 +1309,9 @@ x86_emulate(
   1.451      {
   1.452      case 0x40 ... 0x4f: /* cmov */
   1.453          dst.val = dst.orig_val = src.val;
   1.454 -        d &= ~Mov; /* default to no move */
   1.455 -        /* First, assume we're decoding an even cmov opcode (lsb == 0). */
   1.456 -        switch ( (b & 15) >> 1 )
   1.457 -        {
   1.458 -        case 0: /* cmovo */
   1.459 -            d |= (_regs.eflags & EFLG_OF) ? Mov : 0;
   1.460 -            break;
   1.461 -        case 1: /* cmovb/cmovc/cmovnae */
   1.462 -            d |= (_regs.eflags & EFLG_CF) ? Mov : 0;
   1.463 -            break;
   1.464 -        case 2: /* cmovz/cmove */
   1.465 -            d |= (_regs.eflags & EFLG_ZF) ? Mov : 0;
   1.466 -            break;
   1.467 -        case 3: /* cmovbe/cmovna */
   1.468 -            d |= (_regs.eflags & (EFLG_CF|EFLG_ZF)) ? Mov : 0;
   1.469 -            break;
   1.470 -        case 4: /* cmovs */
   1.471 -            d |= (_regs.eflags & EFLG_SF) ? Mov : 0;
   1.472 -            break;
   1.473 -        case 5: /* cmovp/cmovpe */
   1.474 -            d |= (_regs.eflags & EFLG_PF) ? Mov : 0;
   1.475 -            break;
   1.476 -        case 7: /* cmovle/cmovng */
   1.477 -            d |= (_regs.eflags & EFLG_ZF) ? Mov : 0;
   1.478 -            /* fall through */
   1.479 -        case 6: /* cmovl/cmovnge */
   1.480 -            d |= (!(_regs.eflags & EFLG_SF) != !(_regs.eflags & EFLG_OF)) ?
   1.481 -                Mov : 0;
   1.482 -            break;
   1.483 -        }
   1.484 -        /* Odd cmov opcodes (lsb == 1) have inverted sense. */
   1.485 -        d ^= (b & 1) ? Mov : 0;
   1.486 +        d = (d & ~Mov) | (test_cc(b, _regs.eflags) ? Mov : 0);
   1.487          break;
   1.488 +
   1.489      case 0xb0 ... 0xb1: /* cmpxchg */
   1.490          /* Save real source value, then compare EAX against destination. */
   1.491          src.orig_val = src.val;
   1.492 @@ -1235,27 +1331,34 @@ x86_emulate(
   1.493              dst.reg  = (unsigned long *)&_regs.eax;
   1.494          }
   1.495          break;
   1.496 +
   1.497      case 0xa3: bt: /* bt */
   1.498          emulate_2op_SrcV_nobyte("bt", src, dst, _regs.eflags);
   1.499          break;
   1.500 +
   1.501      case 0xb3: btr: /* btr */
   1.502          emulate_2op_SrcV_nobyte("btr", src, dst, _regs.eflags);
   1.503          break;
   1.504 +
   1.505      case 0xab: bts: /* bts */
   1.506          emulate_2op_SrcV_nobyte("bts", src, dst, _regs.eflags);
   1.507          break;
   1.508 +
   1.509      case 0xb6: /* movzx rm8,r{16,32,64} */
   1.510          /* Recompute DstReg as we may have decoded AH/BH/CH/DH. */
   1.511          dst.reg   = decode_register(modrm_reg, &_regs, 0);
   1.512          dst.bytes = op_bytes;
   1.513          dst.val   = (uint8_t)src.val;
   1.514          break;
   1.515 +
   1.516      case 0xb7: /* movzx rm16,r{16,32,64} */
   1.517          dst.val = (uint16_t)src.val;
   1.518          break;
   1.519 +
   1.520      case 0xbb: btc: /* btc */
   1.521          emulate_2op_SrcV_nobyte("btc", src, dst, _regs.eflags);
   1.522          break;
   1.523 +
   1.524      case 0xba: /* Grp8 */
   1.525          switch ( modrm_reg & 3 )
   1.526          {
   1.527 @@ -1265,15 +1368,18 @@ x86_emulate(
   1.528          case 3: goto btc;
   1.529          }
   1.530          break;
   1.531 +
   1.532      case 0xbe: /* movsx rm8,r{16,32,64} */
   1.533          /* Recompute DstReg as we may have decoded AH/BH/CH/DH. */
   1.534          dst.reg   = decode_register(modrm_reg, &_regs, 0);
   1.535          dst.bytes = op_bytes;
   1.536          dst.val   = (int8_t)src.val;
   1.537          break;
   1.538 +
   1.539      case 0xbf: /* movsx rm16,r{16,32,64} */
   1.540          dst.val = (int16_t)src.val;
   1.541          break;
   1.542 +
   1.543      case 0xc0 ... 0xc1: /* xadd */
   1.544          /* Write back the register source. */
   1.545          switch ( dst.bytes )
   1.546 @@ -1293,6 +1399,15 @@ x86_emulate(
   1.547      case 0x0d: /* GrpP (prefetch) */
   1.548      case 0x18: /* Grp16 (prefetch/nop) */
   1.549          break;
   1.550 +
   1.551 +    case 0x80 ... 0x8f: /* jcc (near) */ {
   1.552 +        int rel = insn_fetch_bytes(
   1.553 +            (mode == X86EMUL_MODE_PROT64) ? 4 : op_bytes);
   1.554 +        if ( test_cc(b, _regs.eflags) )
   1.555 +            jmp_rel(rel);
   1.556 +        break;
   1.557 +    }
   1.558 +
   1.559      case 0xc7: /* Grp9 (cmpxchg8b) */
   1.560  #if defined(__i386__)
   1.561      {