WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [XEN] Emulate relative near/short jumps,

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [XEN] Emulate relative near/short jumps, including Jcc.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 10 Jan 2007 04:00:33 -0800
Delivery-date: Wed, 10 Jan 2007 04:01:56 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1168271573 0
# Node ID f240c09f08d218a253e08f9fbdd97c7c50e8cc35
# Parent  5eeb4bac1b173d972f16f031fc8fa264c186cc5a
[XEN] Emulate relative near/short jumps, including Jcc.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/x86_emulate.c |  221 ++++++++++++++++++++++++++++++++++-----------
 1 files changed, 168 insertions(+), 53 deletions(-)

diff -r 5eeb4bac1b17 -r f240c09f08d2 xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Mon Jan 08 14:26:57 2007 +0000
+++ b/xen/arch/x86/x86_emulate.c        Mon Jan 08 15:52:53 2007 +0000
@@ -88,8 +88,12 @@ static uint8_t opcode_table[256] = {
     /* 0x60 - 0x6F */
     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,
+    /* 0x70 - 0x77 */
+    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+    /* 0x78 - 0x7F */
+    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     /* 0x80 - 0x87 */
     ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImm|ModRM,
     ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM,
@@ -130,8 +134,10 @@ static uint8_t opcode_table[256] = {
     0, 0, 0, 0,
     /* 0xD8 - 0xDF */
     0, 0, 0, 0, 0, 0, 0, 0,
-    /* 0xE0 - 0xEF */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    /* 0xE0 - 0xE7 */
+    0, 0, 0, ImplicitOps, 0, 0, 0, 0,
+    /* 0xE8 - 0xEF */
+    0, ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0,
     /* 0xF0 - 0xF7 */
     0, 0, 0, 0,
     0, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM,
@@ -165,8 +171,12 @@ static uint8_t twobyte_table[256] = {
     0, 0, 0, 0, 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 - 0x8F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    /* 0x80 - 0x87 */
+    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+    /* 0x88 - 0x8F */
+    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     /* 0x90 - 0x9F */
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     /* 0xA0 - 0xA7 */
@@ -380,31 +390,82 @@ do{ __asm__ __volatile__ (              
 
 /* Fetch next part of the instruction being emulated. */
 #define insn_fetch_bytes(_size)                                         \
-({ unsigned long _x;                                                    \
-   rc = ops->insn_fetch(x86_seg_cs, _regs.eip, &_x, (_size), ctxt);     \
+({ unsigned long _x, _eip = _truncate_ea(_regs.eip, def_ad_bytes);      \
+   rc = ops->insn_fetch(x86_seg_cs, _eip, &_x, (_size), ctxt);          \
    if ( rc != 0 )                                                       \
        goto done;                                                       \
-   _regs.eip += (_size);                                                \
+   _register_address_increment(_regs.eip, (_size), def_ad_bytes);       \
    _x;                                                                  \
 })
 #define insn_fetch_type(_type) ((_type)insn_fetch_bytes(sizeof(_type)))
 
-#define truncate_ea(ea)                                 \
+#define _truncate_ea(ea, byte_width)                    \
 ({  unsigned long __ea = (ea);                          \
-    ((ad_bytes == sizeof(unsigned long)) ? __ea :       \
-     (__ea & ((1UL << (ad_bytes << 3)) - 1)));          \
+    (((byte_width) == sizeof(unsigned long)) ? __ea :   \
+     (__ea & ((1UL << ((byte_width) << 3)) - 1)));      \
 })
+#define truncate_ea(ea) _truncate_ea((ea), ad_bytes)
 
 /* Update address held in a register, based on addressing mode. */
-#define register_address_increment(reg, inc)                            \
+#define _register_address_increment(reg, inc, byte_width)               \
 do {                                                                    \
     int _inc = (inc); /* signed type ensures sign extension to long */  \
-    if ( ad_bytes == sizeof(unsigned long) )                            \
+    if ( (byte_width) == sizeof(unsigned long) )                        \
         (reg) += _inc;                                                  \
+    else if ( mode == X86EMUL_MODE_PROT64 )                             \
+        (reg) = ((reg) + _inc) & ((1UL << ((byte_width) << 3)) - 1);    \
     else                                                                \
-        (reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) |             \
-                (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1));      \
+        (reg) = ((reg) & ~((1UL << ((byte_width) << 3)) - 1)) |         \
+                (((reg) + _inc) & ((1UL << ((byte_width) << 3)) - 1));  \
 } while (0)
+#define register_address_increment(reg, inc) \
+    _register_address_increment((reg), (inc), ad_bytes)
+
+#define jmp_rel(rel)                                                    \
+do {                                                                    \
+    _regs.eip += (int)(rel);                                            \
+    if ( mode != X86EMUL_MODE_PROT64 )                                  \
+        _regs.eip = ((op_bytes == 2)                                    \
+                     ? (uint16_t)_regs.eip : (uint32_t)_regs.eip);      \
+} while (0)
+
+static int
+test_cc(
+    unsigned int condition, unsigned int flags)
+{
+    int rc = 0;
+
+    switch ( (condition & 15) >> 1 )
+    {
+    case 0: /* o */
+        rc |= (flags & EFLG_OF);
+        break;
+    case 1: /* b/c/nae */
+        rc |= (flags & EFLG_CF);
+        break;
+    case 2: /* z/e */
+        rc |= (flags & EFLG_ZF);
+        break;
+    case 3: /* be/na */
+        rc |= (flags & (EFLG_CF|EFLG_ZF));
+        break;
+    case 4: /* s */
+        rc |= (flags & EFLG_SF);
+        break;
+    case 5: /* p/pe */
+        rc |= (flags & EFLG_PF);
+        break;
+    case 7: /* le/ng */
+        rc |= (flags & EFLG_ZF);
+        /* fall through */
+    case 6: /* l/nge */
+        rc |= (!(flags & EFLG_SF) != !(flags & EFLG_OF));
+        break;
+    }
+
+    /* Odd condition identifiers (lsb == 1) have inverted sense. */
+    return (!!rc ^ (condition & 1));
+}
 
 void *
 decode_register(
@@ -456,7 +517,8 @@ x86_emulate(
 
     uint8_t b, d, sib, sib_index, sib_base, 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;
+    unsigned int op_bytes, ad_bytes, def_ad_bytes;
+    unsigned int lock_prefix = 0, rep_prefix = 0, i;
     int rc = 0;
     struct operand src, dst;
     int mode = ctxt->mode;
@@ -473,20 +535,22 @@ x86_emulate(
     {
     case X86EMUL_MODE_REAL:
     case X86EMUL_MODE_PROT16:
-        op_bytes = ad_bytes = 2;
+        op_bytes = def_ad_bytes = 2;
         break;
     case X86EMUL_MODE_PROT32:
-        op_bytes = ad_bytes = 4;
+        op_bytes = def_ad_bytes = 4;
         break;
 #ifdef __x86_64__
     case X86EMUL_MODE_PROT64:
         op_bytes = 4;
-        ad_bytes = 8;
+        def_ad_bytes = 8;
         break;
 #endif
     default:
         return -1;
     }
+
+    ad_bytes = def_ad_bytes;
 
     /* Prefix bytes. */
     for ( i = 0; i < 8; i++ )
@@ -820,53 +884,62 @@ x86_emulate(
     case 0x00 ... 0x03: add: /* add */
         emulate_2op_SrcV("add", src, dst, _regs.eflags);
         break;
+
     case 0x0c ... 0x0d: /* or imm,%%eax */
         dst.reg = (unsigned long *)&_regs.eax;
         dst.val = dst.orig_val = _regs.eax;
     case 0x08 ... 0x0b: or:  /* or */
         emulate_2op_SrcV("or", src, dst, _regs.eflags);
         break;
+
     case 0x14 ... 0x15: /* adc imm,%%eax */
         dst.reg = (unsigned long *)&_regs.eax;
         dst.val = dst.orig_val = _regs.eax;
     case 0x10 ... 0x13: adc: /* adc */
         emulate_2op_SrcV("adc", src, dst, _regs.eflags);
         break;
+
     case 0x1c ... 0x1d: /* sbb imm,%%eax */
         dst.reg = (unsigned long *)&_regs.eax;
         dst.val = dst.orig_val = _regs.eax;
     case 0x18 ... 0x1b: sbb: /* sbb */
         emulate_2op_SrcV("sbb", src, dst, _regs.eflags);
         break;
+
     case 0x24 ... 0x25: /* and imm,%%eax */
         dst.reg = (unsigned long *)&_regs.eax;
         dst.val = dst.orig_val = _regs.eax;
     case 0x20 ... 0x23: and: /* and */
         emulate_2op_SrcV("and", src, dst, _regs.eflags);
         break;
+
     case 0x2c ... 0x2d: /* sub imm,%%eax */
         dst.reg = (unsigned long *)&_regs.eax;
         dst.val = dst.orig_val = _regs.eax;
     case 0x28 ... 0x2b: sub: /* sub */
         emulate_2op_SrcV("sub", src, dst, _regs.eflags);
         break;
+
     case 0x34 ... 0x35: /* xor imm,%%eax */
         dst.reg = (unsigned long *)&_regs.eax;
         dst.val = dst.orig_val = _regs.eax;
     case 0x30 ... 0x33: xor: /* xor */
         emulate_2op_SrcV("xor", src, dst, _regs.eflags);
         break;
+
     case 0x3c ... 0x3d: /* cmp imm,%%eax */
         dst.reg = (unsigned long *)&_regs.eax;
         dst.val = dst.orig_val = _regs.eax;
     case 0x38 ... 0x3b: cmp: /* cmp */
         emulate_2op_SrcV("cmp", src, dst, _regs.eflags);
         break;
+
     case 0x63: /* movsxd */
         if ( mode != X86EMUL_MODE_PROT64 )
             goto cannot_emulate;
         dst.val = (int32_t)src.val;
         break;
+
     case 0x80 ... 0x83: /* Grp1 */
         switch ( modrm_reg & 7 )
         {
@@ -880,9 +953,11 @@ x86_emulate(
         case 7: goto cmp;
         }
         break;
+
     case 0x84 ... 0x85: test: /* test */
         emulate_2op_SrcV("test", src, dst, _regs.eflags);
         break;
+
     case 0x86 ... 0x87: xchg: /* xchg */
         /* Write back the register source. */
         switch ( dst.bytes )
@@ -896,13 +971,16 @@ x86_emulate(
         dst.val = src.val;
         lock_prefix = 1;
         break;
+
     case 0x88 ... 0x8b: /* mov */
     case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
         dst.val = src.val;
         break;
+
     case 0x8d: /* lea */
         dst.val = ea.mem.off;
         break;
+
     case 0x8f: /* pop (sole member of Grp1a) */
         /* 64-bit mode: POP defaults to a 64-bit operand. */
         if ( (mode == X86EMUL_MODE_PROT64) && (dst.bytes == 4) )
@@ -912,11 +990,13 @@ x86_emulate(
             goto done;
         register_address_increment(_regs.esp, dst.bytes);
         break;
+
     case 0xb0 ... 0xb7: /* mov imm8,r8 */
         dst.reg = decode_register(
             (b & 7) | ((rex_prefix & 1) << 3), &_regs, (rex_prefix == 0));
         dst.val = src.val;
         break;
+
     case 0xb8 ... 0xbf: /* mov imm{16,32,64},r{16,32,64} */
         if ( dst.bytes == 8 ) /* Fetch more bytes to obtain imm64 */
             src.val = ((uint32_t)src.val |
@@ -925,6 +1005,7 @@ x86_emulate(
             (b & 7) | ((rex_prefix & 1) << 3), &_regs, 0);
         dst.val = src.val;
         break;
+
     case 0xc0 ... 0xc1: grp2: /* Grp2 */
         switch ( modrm_reg & 7 )
         {
@@ -952,12 +1033,15 @@ x86_emulate(
             break;
         }
         break;
+
     case 0xd0 ... 0xd1: /* Grp2 */
         src.val = 1;
         goto grp2;
+
     case 0xd2 ... 0xd3: /* Grp2 */
         src.val = _regs.ecx;
         goto grp2;
+
     case 0xf6 ... 0xf7: /* Grp3 */
         switch ( modrm_reg & 7 )
         {
@@ -983,6 +1067,7 @@ x86_emulate(
             goto cannot_emulate;
         }
         break;
+
     case 0xfe ... 0xff: /* Grp4/Grp5 */
         switch ( modrm_reg & 7 )
         {
@@ -1052,8 +1137,10 @@ x86_emulate(
  special_insn:
     /* Default action: disable writeback. There may be no dest operand. */
     dst.orig_val = dst.val;
+
     if ( twobyte )
         goto twobyte_special_insn;
+
     if ( rep_prefix )
     {
         if ( _regs.ecx == 0 )
@@ -1064,6 +1151,7 @@ x86_emulate(
         _regs.ecx--;
         _regs.eip = ctxt->regs->eip;
     }
+
     switch ( b )
     {
     case 0x40 ... 0x4f: /* inc/dec reg */
@@ -1076,6 +1164,7 @@ x86_emulate(
         else
             emulate_1op("inc", dst, _regs.eflags);
         break;
+
     case 0x50 ... 0x57: /* push reg */
         dst.type  = OP_MEM;
         dst.bytes = op_bytes;
@@ -1087,6 +1176,7 @@ x86_emulate(
         dst.mem.seg = x86_seg_ss;
         dst.mem.off = truncate_ea(_regs.esp);
         break;
+
     case 0x58 ... 0x5f: /* pop reg */
         dst.type  = OP_REG;
         dst.reg   = decode_register(
@@ -1099,9 +1189,18 @@ x86_emulate(
             goto done;
         register_address_increment(_regs.esp, dst.bytes);
         break;
+
+    case 0x70 ... 0x7f: /* jcc (short) */ {
+        int rel = insn_fetch_type(int8_t);
+        if ( test_cc(b, _regs.eflags) )
+            jmp_rel(rel);
+        break;
+    }
+
     case 0x90: /* nop / xchg %%r8,%%rax */
         if ( !(rex_prefix & 1) )
             break; /* nop */
+
     case 0x91 ... 0x97: /* xchg reg,%%rax */
         src.type = dst.type = OP_REG;
         src.bytes = dst.bytes = op_bytes;
@@ -1111,6 +1210,7 @@ x86_emulate(
             (b & 7) | ((rex_prefix & 1) << 3), &_regs, 0);
         dst.val  = dst.orig_val = *dst.reg;
         goto xchg;
+
     case 0xa0 ... 0xa1: /* mov mem.offs,{%al,%ax,%eax,%rax} */
         /* Source EA is not encoded via ModRM. */
         dst.type  = OP_REG;
@@ -1120,6 +1220,7 @@ x86_emulate(
                              &dst.val, dst.bytes, ctxt)) != 0 )
             goto done;
         break;
+
     case 0xa2 ... 0xa3: /* mov {%al,%ax,%eax,%rax},mem.offs */
         /* Destination EA is not encoded via ModRM. */
         dst.type  = OP_MEM;
@@ -1128,6 +1229,7 @@ x86_emulate(
         dst.bytes = (d & ByteOp) ? 1 : op_bytes;
         dst.val   = (unsigned long)_regs.eax;
         break;
+
     case 0xa4 ... 0xa5: /* movs */
         dst.type  = OP_MEM;
         dst.bytes = (d & ByteOp) ? 1 : op_bytes;
@@ -1141,6 +1243,7 @@ x86_emulate(
         register_address_increment(
             _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
         break;
+
     case 0xaa ... 0xab: /* stos */
         dst.type  = OP_MEM;
         dst.bytes = (d & ByteOp) ? 1 : op_bytes;
@@ -1150,6 +1253,7 @@ x86_emulate(
         register_address_increment(
             _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
         break;
+
     case 0xac ... 0xad: /* lods */
         dst.type  = OP_REG;
         dst.bytes = (d & ByteOp) ? 1 : op_bytes;
@@ -1160,18 +1264,40 @@ x86_emulate(
         register_address_increment(
             _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
         break;
+
+    case 0xe3: /* jcxz/jecxz (short) */ {
+        int rel = insn_fetch_type(int8_t);
+        if ( (ad_bytes == 2) ? !(uint16_t)_regs.ecx :
+             (ad_bytes == 4) ? !(uint32_t)_regs.ecx : !_regs.ecx )
+            jmp_rel(rel);
+        break;
+    }
+
+    case 0xe9: /* jmp (short) */
+        jmp_rel(insn_fetch_type(int8_t));
+        break;
+
+    case 0xeb: /* jmp (near) */
+        jmp_rel(insn_fetch_bytes(
+            (mode == X86EMUL_MODE_PROT64) ? 4 : op_bytes));
+        break;
+
     case 0xf5: /* cmc */
         _regs.eflags ^= EFLG_CF;
         break;
+
     case 0xf8: /* clc */
         _regs.eflags &= ~EFLG_CF;
         break;
+
     case 0xf9: /* stc */
         _regs.eflags |= EFLG_CF;
         break;
+
     case 0xfc: /* cld */
         _regs.eflags &= ~EFLG_DF;
         break;
+
     case 0xfd: /* std */
         _regs.eflags |= EFLG_DF;
         break;
@@ -1183,39 +1309,9 @@ x86_emulate(
     {
     case 0x40 ... 0x4f: /* cmov */
         dst.val = dst.orig_val = src.val;
-        d &= ~Mov; /* default to no move */
-        /* First, assume we're decoding an even cmov opcode (lsb == 0). */
-        switch ( (b & 15) >> 1 )
-        {
-        case 0: /* cmovo */
-            d |= (_regs.eflags & EFLG_OF) ? Mov : 0;
-            break;
-        case 1: /* cmovb/cmovc/cmovnae */
-            d |= (_regs.eflags & EFLG_CF) ? Mov : 0;
-            break;
-        case 2: /* cmovz/cmove */
-            d |= (_regs.eflags & EFLG_ZF) ? Mov : 0;
-            break;
-        case 3: /* cmovbe/cmovna */
-            d |= (_regs.eflags & (EFLG_CF|EFLG_ZF)) ? Mov : 0;
-            break;
-        case 4: /* cmovs */
-            d |= (_regs.eflags & EFLG_SF) ? Mov : 0;
-            break;
-        case 5: /* cmovp/cmovpe */
-            d |= (_regs.eflags & EFLG_PF) ? Mov : 0;
-            break;
-        case 7: /* cmovle/cmovng */
-            d |= (_regs.eflags & EFLG_ZF) ? Mov : 0;
-            /* fall through */
-        case 6: /* cmovl/cmovnge */
-            d |= (!(_regs.eflags & EFLG_SF) != !(_regs.eflags & EFLG_OF)) ?
-                Mov : 0;
-            break;
-        }
-        /* Odd cmov opcodes (lsb == 1) have inverted sense. */
-        d ^= (b & 1) ? Mov : 0;
-        break;
+        d = (d & ~Mov) | (test_cc(b, _regs.eflags) ? Mov : 0);
+        break;
+
     case 0xb0 ... 0xb1: /* cmpxchg */
         /* Save real source value, then compare EAX against destination. */
         src.orig_val = src.val;
@@ -1235,27 +1331,34 @@ x86_emulate(
             dst.reg  = (unsigned long *)&_regs.eax;
         }
         break;
+
     case 0xa3: bt: /* bt */
         emulate_2op_SrcV_nobyte("bt", src, dst, _regs.eflags);
         break;
+
     case 0xb3: btr: /* btr */
         emulate_2op_SrcV_nobyte("btr", src, dst, _regs.eflags);
         break;
+
     case 0xab: bts: /* bts */
         emulate_2op_SrcV_nobyte("bts", src, dst, _regs.eflags);
         break;
+
     case 0xb6: /* movzx rm8,r{16,32,64} */
         /* Recompute DstReg as we may have decoded AH/BH/CH/DH. */
         dst.reg   = decode_register(modrm_reg, &_regs, 0);
         dst.bytes = op_bytes;
         dst.val   = (uint8_t)src.val;
         break;
+
     case 0xb7: /* movzx rm16,r{16,32,64} */
         dst.val = (uint16_t)src.val;
         break;
+
     case 0xbb: btc: /* btc */
         emulate_2op_SrcV_nobyte("btc", src, dst, _regs.eflags);
         break;
+
     case 0xba: /* Grp8 */
         switch ( modrm_reg & 3 )
         {
@@ -1265,15 +1368,18 @@ x86_emulate(
         case 3: goto btc;
         }
         break;
+
     case 0xbe: /* movsx rm8,r{16,32,64} */
         /* Recompute DstReg as we may have decoded AH/BH/CH/DH. */
         dst.reg   = decode_register(modrm_reg, &_regs, 0);
         dst.bytes = op_bytes;
         dst.val   = (int8_t)src.val;
         break;
+
     case 0xbf: /* movsx rm16,r{16,32,64} */
         dst.val = (int16_t)src.val;
         break;
+
     case 0xc0 ... 0xc1: /* xadd */
         /* Write back the register source. */
         switch ( dst.bytes )
@@ -1293,6 +1399,15 @@ x86_emulate(
     case 0x0d: /* GrpP (prefetch) */
     case 0x18: /* Grp16 (prefetch/nop) */
         break;
+
+    case 0x80 ... 0x8f: /* jcc (near) */ {
+        int rel = insn_fetch_bytes(
+            (mode == X86EMUL_MODE_PROT64) ? 4 : op_bytes);
+        if ( test_cc(b, _regs.eflags) )
+            jmp_rel(rel);
+        break;
+    }
+
     case 0xc7: /* Grp9 (cmpxchg8b) */
 #if defined(__i386__)
     {

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [XEN] Emulate relative near/short jumps, including Jcc., Xen patchbot-unstable <=