[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [XEN] Emulator extensions to decode ModRM.MOD == 3.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1166627773 0
# Node ID 4fb80f21c77df84f6a6d7f61fdce4c337d538291
# Parent  ed815cbdc90e4991da69ec57a4b9e2793bb43b7b
[XEN] Emulator extensions to decode ModRM.MOD == 3.
This allows emulation of register-only instructions.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 tools/tests/test_x86_emulator.c |   44 +++----
 xen/arch/x86/x86_32/seg_fixup.c |    5 
 xen/arch/x86/x86_emulate.c      |  229 +++++++++++++++++++++++-----------------
 3 files changed, 155 insertions(+), 123 deletions(-)

diff -r ed815cbdc90e -r 4fb80f21c77d tools/tests/test_x86_emulator.c
--- a/tools/tests/test_x86_emulator.c   Wed Dec 20 13:54:04 2006 +0000
+++ b/tools/tests/test_x86_emulator.c   Wed Dec 20 15:16:13 2006 +0000
@@ -15,8 +15,6 @@ typedef int64_t            s64;
 #include <asm-x86/x86_emulate.h>
 #include <sys/mman.h>
 
-#define PFEC_write_access (1U<<1)
-
 static int read(
     unsigned int seg,
     unsigned long offset,
@@ -119,12 +117,26 @@ int main(int argc, char **argv)
     regs.eflags = 0x200;
     regs.eip    = (unsigned long)&instr[0];
     regs.ecx    = 0x12345678;
-    regs.error_code = PFEC_write_access;
     regs.eax    = (unsigned long)res;
     *res        = 0x7FFFFFFF;
     rc = x86_emulate_memop(&ctxt, &emulops);
     if ( (rc != 0) || 
          (*res != 0x92345677) || 
+         (regs.eflags != 0xa94) ||
+         (regs.eip != (unsigned long)&instr[2]) )
+        goto fail;
+    printf("okay\n");
+
+    printf("%-40s", "Testing addl %%ecx,%%eax...");
+    instr[0] = 0x01; instr[1] = 0xc8;
+    regs.eflags = 0x200;
+    regs.eip    = (unsigned long)&instr[0];
+    regs.ecx    = 0x12345678;
+    regs.eax    = 0x7FFFFFFF;
+    rc = x86_emulate_memop(&ctxt, &emulops);
+    if ( (rc != 0) || 
+         (regs.ecx != 0x12345678) ||
+         (regs.eax != 0x92345677) ||
          (regs.eflags != 0xa94) ||
          (regs.eip != (unsigned long)&instr[2]) )
         goto fail;
@@ -140,7 +152,6 @@ int main(int argc, char **argv)
     regs.ecx    = 0x12345678UL;
 #endif
     regs.eax    = (unsigned long)res;
-    regs.error_code = 0;
     rc = x86_emulate_memop(&ctxt, &emulops);
     if ( (rc != 0) || 
          (*res != 0x92345677) || 
@@ -155,7 +166,6 @@ int main(int argc, char **argv)
     regs.eip    = (unsigned long)&instr[0];
     regs.ecx    = ~0UL;
     regs.eax    = (unsigned long)res;
-    regs.error_code = 0;
     rc = x86_emulate_memop(&ctxt, &emulops);
     if ( (rc != 0) || 
          (*res != 0x92345677) || 
@@ -171,7 +181,6 @@ int main(int argc, char **argv)
     regs.eax    = 0x92345677UL;
     regs.ecx    = 0xAA;
     regs.ebx    = (unsigned long)res;
-    regs.error_code = PFEC_write_access;
     rc = x86_emulate_memop(&ctxt, &emulops);
     if ( (rc != 0) || 
          (*res != 0x923456AA) || 
@@ -188,7 +197,6 @@ int main(int argc, char **argv)
     regs.eax    = 0xAABBCC77UL;
     regs.ecx    = 0xFF;
     regs.ebx    = (unsigned long)res;
-    regs.error_code = PFEC_write_access;
     rc = x86_emulate_memop(&ctxt, &emulops);
     if ( (rc != 0) || 
          (*res != 0x923456AA) || 
@@ -205,7 +213,6 @@ int main(int argc, char **argv)
     regs.eip    = (unsigned long)&instr[0];
     regs.ecx    = 0x12345678;
     regs.eax    = (unsigned long)res;
-    regs.error_code = PFEC_write_access;
     rc = x86_emulate_memop(&ctxt, &emulops);
     if ( (rc != 0) || 
          (*res != 0x12345678) || 
@@ -223,7 +230,6 @@ int main(int argc, char **argv)
     regs.eax    = 0x923456AAUL;
     regs.ecx    = 0xDDEEFF00L;
     regs.ebx    = (unsigned long)res;
-    regs.error_code = PFEC_write_access;
     rc = x86_emulate_memop(&ctxt, &emulops);
     if ( (rc != 0) || 
          (*res != 0xDDEEFF00) || 
@@ -241,7 +247,6 @@ int main(int argc, char **argv)
     regs.eip    = (unsigned long)&instr[0];
     regs.esi    = (unsigned long)res + 0;
     regs.edi    = (unsigned long)res + 2;
-    regs.error_code = 0; /* read fault */
     rc = x86_emulate_memop(&ctxt, &emulops);
     if ( (rc != 0) || 
          (*res != 0x44554455) ||
@@ -259,9 +264,8 @@ int main(int argc, char **argv)
     regs.eflags = 0x200;
     regs.eip    = (unsigned long)&instr[0];
     regs.edi    = (unsigned long)res;
-    regs.error_code = PFEC_write_access;
-    rc = x86_emulate_memop(&ctxt, &emulops);
-    if ( (rc != 0) || 
+    rc = x86_emulate_memop(&ctxt, &emulops);
+    if ( (rc != 0) ||
          (*res != 0x2233445D) ||
          ((regs.eflags&0x201) != 0x201) ||
          (regs.eip != (unsigned long)&instr[4]) )
@@ -275,9 +279,8 @@ int main(int argc, char **argv)
     regs.eip    = (unsigned long)&instr[0];
     regs.eax    = -32;
     regs.edi    = (unsigned long)(res+1);
-    regs.error_code = PFEC_write_access;
-    rc = x86_emulate_memop(&ctxt, &emulops);
-    if ( (rc != 0) || 
+    rc = x86_emulate_memop(&ctxt, &emulops);
+    if ( (rc != 0) ||
          (*res != 0x2233445E) ||
          ((regs.eflags&0x201) != 0x201) ||
          (regs.eip != (unsigned long)&instr[3]) )
@@ -296,9 +299,8 @@ int main(int argc, char **argv)
     regs.ecx    = 0xCCCCFFFF;
     regs.eip    = (unsigned long)&instr[0];
     regs.edi    = (unsigned long)res;
-    regs.error_code = PFEC_write_access;
-    rc = x86_emulate_memop(&ctxt, &emulops);
-    if ( (rc != 0) || 
+    rc = x86_emulate_memop(&ctxt, &emulops);
+    if ( (rc != 0) ||
          (res[0] != 0x9999AAAA) ||
          (res[1] != 0xCCCCFFFF) ||
          ((regs.eflags&0x240) != 0x240) ||
@@ -311,7 +313,6 @@ int main(int argc, char **argv)
     regs.eflags = 0x200;
     regs.eip    = (unsigned long)&instr[0];
     regs.edi    = (unsigned long)res;
-    regs.error_code = PFEC_write_access;
     rc = x86_emulate_memop(&ctxt, &emulops);
     if ( (rc != 0) || 
          (res[0] != 0x9999AAAA) ||
@@ -330,7 +331,6 @@ int main(int argc, char **argv)
     regs.ecx    = 0x12345678;
     regs.eax    = (unsigned long)res;
     *res        = 0x82;
-    regs.error_code = 0;
     rc = x86_emulate_memop(&ctxt, &emulops);
     if ( (rc != 0) ||
          (*res != 0x82) ||
@@ -347,7 +347,6 @@ int main(int argc, char **argv)
     regs.ecx    = 0x12345678;
     regs.eax    = (unsigned long)res;
     *res        = 0x1234aa82;
-    regs.error_code = 0;
     rc = x86_emulate_memop(&ctxt, &emulops);
     if ( (rc != 0) ||
          (*res != 0x1234aa82) ||
@@ -364,7 +363,6 @@ int main(int argc, char **argv)
     regs.ecx    = (unsigned long)res;
     regs.eax    = 0x12345678;
     *res        = 0x11111111;
-    regs.error_code = 0;
     rc = x86_emulate_memop(&ctxt, &emulops);
     if ( (rc != 0) ||
          (*res != 0x11116789) ||
diff -r ed815cbdc90e -r 4fb80f21c77d xen/arch/x86/x86_32/seg_fixup.c
--- a/xen/arch/x86/x86_32/seg_fixup.c   Wed Dec 20 13:54:04 2006 +0000
+++ b/xen/arch/x86/x86_32/seg_fixup.c   Wed Dec 20 15:16:13 2006 +0000
@@ -268,7 +268,7 @@ int gpf_emulate_4gb(struct cpu_user_regs
     struct trap_info   *ti;
     struct trap_bounce *tb;
     u8            modrm, mod, reg, rm, decode;
-    void         *memreg, *regreg;
+    void         *memreg;
     unsigned long offset;
     u8            disp8;
     u32           disp32 = 0;
@@ -384,8 +384,7 @@ int gpf_emulate_4gb(struct cpu_user_regs
         goto fixme;
     }
 
-    /* Decode Reg and R/M fields. */
-    regreg = decode_register(reg, regs, 0);
+    /* Decode R/M field. */
     memreg = decode_register(rm,  regs, 0);
 
     /* Decode Mod field. */
diff -r ed815cbdc90e -r 4fb80f21c77d xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Wed Dec 20 13:54:04 2006 +0000
+++ b/xen/arch/x86/x86_emulate.c        Wed Dec 20 15:16:13 2006 +0000
@@ -192,11 +192,15 @@ struct operand {
     enum { OP_REG, OP_MEM, OP_IMM } type;
     unsigned int  bytes;
     unsigned long val, orig_val;
-    /* OP_REG: Pointer to register field. */
-    unsigned long *reg;
-    /* OP_MEM: Segment and offset. */
-    enum x86_segment mem_seg;
-    unsigned long    mem_off;
+    union {
+        /* OP_REG: Pointer to register field. */
+        unsigned long *reg;
+        /* OP_MEM: Segment and offset. */
+        struct {
+            enum x86_segment seg;
+            unsigned long    off;
+        } mem;
+    };
 };
 
 /* EFLAGS bit definitions. */
@@ -451,8 +455,13 @@ x86_emulate_memop(
     struct operand src, dst;
     int mode = ctxt->mode;
 
-    enum x86_segment ea_seg = x86_seg_ds;
-    unsigned long    ea_off = 0;
+    /* Data operand effective address (usually computed from ModRM). */
+    struct operand ea;
+
+    /* Default is a memory operand relative to segment DS. */
+    ea.type    = OP_MEM;
+    ea.mem.seg = x86_seg_ds;
+    ea.mem.off = 0;
 
     switch ( mode )
     {
@@ -488,22 +497,22 @@ x86_emulate_memop(
                 ad_bytes ^= 6;  /* switch between 2/4 bytes */
             break;
         case 0x2e: /* CS override */
-            ea_seg = x86_seg_cs;
+            ea.mem.seg = x86_seg_cs;
             break;
         case 0x3e: /* DS override */
-            ea_seg = x86_seg_ds;
+            ea.mem.seg = x86_seg_ds;
             break;
         case 0x26: /* ES override */
-            ea_seg = x86_seg_es;
+            ea.mem.seg = x86_seg_es;
             break;
         case 0x64: /* FS override */
-            ea_seg = x86_seg_fs;
+            ea.mem.seg = x86_seg_fs;
             break;
         case 0x65: /* GS override */
-            ea_seg = x86_seg_gs;
+            ea.mem.seg = x86_seg_gs;
             break;
         case 0x36: /* SS override */
-            ea_seg = x86_seg_ss;
+            ea.mem.seg = x86_seg_ss;
             break;
         case 0xf0: /* LOCK */
             lock_prefix = 1;
@@ -554,35 +563,39 @@ x86_emulate_memop(
         modrm_rm  = modrm & 0x07;
 
         if ( modrm_mod == 3 )
-            goto cannot_emulate;
-
-        if ( ad_bytes == 2 )
+        {
+            ea.type = OP_REG;
+            ea.reg  = decode_register(
+                modrm_rm, &_regs, (d & ByteOp) && (rex_prefix == 0));
+        }
+        else if ( ad_bytes == 2 )
         {
             /* 16-bit ModR/M decode. */
             switch ( modrm_rm )
             {
-            case 0: ea_off = _regs.ebx + _regs.esi; break;
-            case 1: ea_off = _regs.ebx + _regs.edi; break;
-            case 2: ea_off = _regs.ebp + _regs.esi; break;
-            case 3: ea_off = _regs.ebp + _regs.edi; break;
-            case 4: ea_off = _regs.esi; break;
-            case 5: ea_off = _regs.edi; break;
-            case 6: ea_off = _regs.ebp; break;
-            case 7: ea_off = _regs.ebx; break;
+            case 0: ea.mem.off = _regs.ebx + _regs.esi; break;
+            case 1: ea.mem.off = _regs.ebx + _regs.edi; break;
+            case 2: ea.mem.off = _regs.ebp + _regs.esi; break;
+            case 3: ea.mem.off = _regs.ebp + _regs.edi; break;
+            case 4: ea.mem.off = _regs.esi; break;
+            case 5: ea.mem.off = _regs.edi; break;
+            case 6: ea.mem.off = _regs.ebp; break;
+            case 7: ea.mem.off = _regs.ebx; break;
             }
             switch ( modrm_mod )
             {
             case 0:
                 if ( modrm_rm == 6 )
-                    ea_off = insn_fetch_type(int16_t);
+                    ea.mem.off = insn_fetch_type(int16_t);
                 break;
             case 1:
-                ea_off += insn_fetch_type(int8_t);
+                ea.mem.off += insn_fetch_type(int8_t);
                 break;
             case 2:
-                ea_off += insn_fetch_type(int16_t);
+                ea.mem.off += insn_fetch_type(int16_t);
                 break;
             }
+            ea.mem.off = truncate_ea(ea.mem.off);
         }
         else
         {
@@ -593,49 +606,48 @@ x86_emulate_memop(
                 sib_index = ((sib >> 3) & 7) | ((rex_prefix << 2) & 8);
                 sib_base  = (sib & 7) | ((rex_prefix << 3) & 8);
                 if ( sib_index != 4 )
-                    ea_off = *(long *)decode_register(sib_index, &_regs, 0);
-                ea_off <<= (sib >> 6) & 3;
+                    ea.mem.off = *(long*)decode_register(sib_index, &_regs, 0);
+                ea.mem.off <<= (sib >> 6) & 3;
                 if ( (modrm_mod == 0) && ((sib_base & 7) == 5) )
-                    ea_off += insn_fetch_type(int32_t);
+                    ea.mem.off += insn_fetch_type(int32_t);
                 else
-                    ea_off += *(long *)decode_register(sib_base, &_regs, 0);
+                    ea.mem.off += *(long*)decode_register(sib_base, &_regs, 0);
             }
             else
             {
                 modrm_rm |= (rex_prefix & 1) << 3;
-                ea_off = *(long *)decode_register(modrm_rm, &_regs, 0);
+                ea.mem.off = *(long *)decode_register(modrm_rm, &_regs, 0);
             }
             switch ( modrm_mod )
             {
             case 0:
                 if ( (modrm_rm & 7) != 5 )
                     break;
-                ea_off = insn_fetch_type(int32_t);
+                ea.mem.off = insn_fetch_type(int32_t);
                 if ( mode != X86EMUL_MODE_PROT64 )
                     break;
                 /* Relative to RIP of next instruction. Argh! */
-                ea_off += _regs.eip;
+                ea.mem.off += _regs.eip;
                 if ( (d & SrcMask) == SrcImm )
-                    ea_off += (d & ByteOp) ? 1 :
+                    ea.mem.off += (d & ByteOp) ? 1 :
                         ((op_bytes == 8) ? 4 : op_bytes);
                 else if ( (d & SrcMask) == SrcImmByte )
-                    ea_off += 1;
+                    ea.mem.off += 1;
                 else if ( ((b == 0xf6) || (b == 0xf7)) &&
                           ((modrm_reg & 7) <= 1) )
                     /* Special case in Grp3: test has immediate operand. */
-                    ea_off += (d & ByteOp) ? 1
+                    ea.mem.off += (d & ByteOp) ? 1
                         : ((op_bytes == 8) ? 4 : op_bytes);
                 break;
             case 1:
-                ea_off += insn_fetch_type(int8_t);
+                ea.mem.off += insn_fetch_type(int8_t);
                 break;
             case 2:
-                ea_off += insn_fetch_type(int32_t);
+                ea.mem.off += insn_fetch_type(int32_t);
                 break;
             }
-        }
-
-        ea_off = truncate_ea(ea_off);
+            ea.mem.off = truncate_ea(ea.mem.off);
+        }
     }
 
     /* Special instructions do their own operand decoding. */
@@ -652,7 +664,7 @@ x86_emulate_memop(
         if ( d & ByteOp )
         {
             src.reg = decode_register(modrm_reg, &_regs, (rex_prefix == 0));
-            src.val = src.orig_val = *(uint8_t *)src.reg;
+            src.val = *(uint8_t *)src.reg;
             src.bytes = 1;
         }
         else
@@ -660,28 +672,35 @@ x86_emulate_memop(
             src.reg = decode_register(modrm_reg, &_regs, 0);
             switch ( (src.bytes = op_bytes) )
             {
-            case 2: src.val = src.orig_val = *(uint16_t *)src.reg; break;
-            case 4: src.val = src.orig_val = *(uint32_t *)src.reg; break;
-            case 8: src.val = src.orig_val = *(uint64_t *)src.reg; break;
+            case 2: src.val = *(uint16_t *)src.reg; break;
+            case 4: src.val = *(uint32_t *)src.reg; break;
+            case 8: src.val = *(uint64_t *)src.reg; break;
             }
         }
         break;
     case SrcMem16:
-        src.bytes = 2;
+        ea.bytes = 2;
         goto srcmem_common;
     case SrcMem32:
-        src.bytes = 4;
+        ea.bytes = 4;
         goto srcmem_common;
     case SrcMem:
-        src.bytes = (d & ByteOp) ? 1 : op_bytes;
+        ea.bytes = (d & ByteOp) ? 1 : op_bytes;
     srcmem_common:
-        src.type  = OP_MEM;
-        src.mem_seg = ea_seg;
-        src.mem_off = ea_off;
-        if ( (rc = ops->read(src.mem_seg, src.mem_off,
-                             &src.val, src.bytes, ctxt)) != 0 )
+        src = ea;
+        if ( src.type == OP_REG )
+        {
+            switch ( src.bytes )
+            {
+            case 1: src.val = *(uint8_t  *)src.reg; break;
+            case 2: src.val = *(uint16_t *)src.reg; break;
+            case 4: src.val = *(uint32_t *)src.reg; break;
+            case 8: src.val = *(uint64_t *)src.reg; break;
+            }
+        }
+        else if ( (rc = ops->read(src.mem.seg, src.mem.off,
+                                  &src.val, src.bytes, ctxt)) )
             goto done;
-        src.orig_val = src.val;
         break;
     case SrcImm:
         src.type  = OP_IMM;
@@ -725,8 +744,7 @@ x86_emulate_memop(
         }
         break;
     case DstBitBase:
-        dst.mem_off = ea_off;
-        if ( (d & SrcMask) == SrcImmByte )
+        if ( ((d & SrcMask) == SrcImmByte) || (ea.type == OP_REG) )
         {
             src.val &= (op_bytes << 3) - 1;
         }
@@ -746,28 +764,34 @@ x86_emulate_memop(
             {
                 unsigned long byte_offset;
                 byte_offset = op_bytes + (((-src.val-1) >> 3) & ~(op_bytes-1));
-                dst.mem_off -= byte_offset;
+                ea.mem.off -= byte_offset;
                 src.val = (byte_offset << 3) + src.val;
             }
             else
             {
-                dst.mem_off += (src.val >> 3) & ~(op_bytes - 1);
+                ea.mem.off += (src.val >> 3) & ~(op_bytes - 1);
                 src.val &= (op_bytes << 3) - 1;
             }
         }
         /* Becomes a normal DstMem operation from here on. */
         d = (d & ~DstMask) | DstMem;
-        goto dstmem_common;
     case DstMem:
-        dst.mem_off = ea_off;
-    dstmem_common:
-        dst.mem_seg = ea_seg;
-        dst.type  = OP_MEM;
-        dst.bytes = (d & ByteOp) ? 1 : op_bytes;
-        if ( !(d & Mov) && /* optimisation - avoid slow emulated read */
-             ((rc = ops->read(dst.mem_seg, dst.mem_off,
-                              &dst.val, dst.bytes, ctxt)) != 0) )
-             goto done;
+        ea.bytes = (d & ByteOp) ? 1 : op_bytes;
+        dst = ea;
+        if ( dst.type == OP_REG )
+        {
+            switch ( dst.bytes )
+            {
+            case 1: dst.val = *(uint8_t  *)dst.reg; break;
+            case 2: dst.val = *(uint16_t *)dst.reg; break;
+            case 4: dst.val = *(uint32_t *)dst.reg; break;
+            case 8: dst.val = *(uint64_t *)dst.reg; break;
+            }
+        }
+        else if ( !(d & Mov) && /* optimisation - avoid slow emulated read */
+                  (rc = ops->read(dst.mem.seg, dst.mem.off,
+                                  &dst.val, dst.bytes, ctxt)) )
+            goto done;
         break;
     }
     dst.orig_val = dst.val;
@@ -920,7 +944,7 @@ x86_emulate_memop(
             if ( mode == X86EMUL_MODE_PROT64 )
             {
                 dst.bytes = 8;
-                if ( (rc = ops->read(dst.mem_seg, dst.mem_off,
+                if ( (rc = ops->read(dst.mem.seg, dst.mem.off,
                                      &dst.val, 8, ctxt)) != 0 )
                     goto done;
             }
@@ -954,11 +978,11 @@ x86_emulate_memop(
         case OP_MEM:
             if ( lock_prefix )
                 rc = ops->cmpxchg(
-                    dst.mem_seg, dst.mem_off, dst.orig_val,
+                    dst.mem.seg, dst.mem.off, dst.orig_val,
                     dst.val, dst.bytes, ctxt);
             else
                 rc = ops->write(
-                    dst.mem_seg, dst.mem_off, dst.val, dst.bytes, ctxt);
+                    dst.mem.seg, dst.mem.off, dst.val, dst.bytes, ctxt);
             if ( rc != 0 )
                 goto done;
         default:
@@ -987,29 +1011,29 @@ x86_emulate_memop(
     }
     switch ( b )
     {
-    case 0xa0 ... 0xa1: /* mov moffs,{%al,%ax,%eax,%rax} */
+    case 0xa0 ... 0xa1: /* mov mem.offs,{%al,%ax,%eax,%rax} */
         /* Source EA is not encoded via ModRM. */
         dst.type  = OP_REG;
         dst.reg   = (unsigned long *)&_regs.eax;
         dst.bytes = (d & ByteOp) ? 1 : op_bytes;
-        if ( (rc = ops->read(ea_seg, insn_fetch_bytes(ad_bytes),
+        if ( (rc = ops->read(ea.mem.seg, insn_fetch_bytes(ad_bytes),
                              &dst.val, dst.bytes, ctxt)) != 0 )
             goto done;
         break;
-    case 0xa2 ... 0xa3: /* mov {%al,%ax,%eax,%rax},moffs */
+    case 0xa2 ... 0xa3: /* mov {%al,%ax,%eax,%rax},mem.offs */
         /* Destination EA is not encoded via ModRM. */
-        dst.type    = OP_MEM;
-        dst.mem_seg = ea_seg;
-        dst.mem_off = insn_fetch_bytes(ad_bytes);
-        dst.bytes   = (d & ByteOp) ? 1 : op_bytes;
-        dst.val     = (unsigned long)_regs.eax;
+        dst.type  = OP_MEM;
+        dst.mem.seg = ea.mem.seg;
+        dst.mem.off = insn_fetch_bytes(ad_bytes);
+        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;
-        dst.mem_seg = x86_seg_es;
-        dst.mem_off = truncate_ea(_regs.edi);
-        if ( (rc = ops->read(ea_seg, truncate_ea(_regs.esi),
+        dst.mem.seg = x86_seg_es;
+        dst.mem.off = truncate_ea(_regs.edi);
+        if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
                              &dst.val, dst.bytes, ctxt)) != 0 )
             goto done;
         register_address_increment(
@@ -1020,8 +1044,8 @@ x86_emulate_memop(
     case 0xaa ... 0xab: /* stos */
         dst.type  = OP_MEM;
         dst.bytes = (d & ByteOp) ? 1 : op_bytes;
-        dst.mem_seg = x86_seg_es;
-        dst.mem_off = truncate_ea(_regs.edi);
+        dst.mem.seg = x86_seg_es;
+        dst.mem.off = truncate_ea(_regs.edi);
         dst.val   = _regs.eax;
         register_address_increment(
             _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
@@ -1030,7 +1054,7 @@ x86_emulate_memop(
         dst.type  = OP_REG;
         dst.bytes = (d & ByteOp) ? 1 : op_bytes;
         dst.reg   = (unsigned long *)&_regs.eax;
-        if ( (rc = ops->read(ea_seg, truncate_ea(_regs.esi),
+        if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
                              &dst.val, dst.bytes, ctxt)) != 0 )
             goto done;
         register_address_increment(
@@ -1105,9 +1129,14 @@ x86_emulate_memop(
     case 0xab: bts: /* bts */
         emulate_2op_SrcV_nobyte("bts", src, dst, _regs.eflags);
         break;
-    case 0xb6 ... 0xb7: /* movzx */
+    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 = (d & ByteOp) ? (uint8_t)src.val : (uint16_t)src.val;
+        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);
@@ -1121,9 +1150,14 @@ x86_emulate_memop(
         case 3: goto btc;
         }
         break;
-    case 0xbe ... 0xbf: /* movsx */
+    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 = (d & ByteOp) ? (int8_t)src.val : (int16_t)src.val;
+        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. */
@@ -1150,8 +1184,8 @@ x86_emulate_memop(
 #if defined(__i386__)
     {
         unsigned long old_lo, old_hi;
-        if ( ((rc = ops->read(ea_seg, ea_off+0, &old_lo, 4, ctxt)) != 0) ||
-             ((rc = ops->read(ea_seg, ea_off+4, &old_hi, 4, ctxt)) != 0) )
+        if ( (rc = ops->read(ea.mem.seg, ea.mem.off+0, &old_lo, 4, ctxt)) ||
+             (rc = ops->read(ea.mem.seg, ea.mem.off+4, &old_hi, 4, ctxt)) )
             goto done;
         if ( (old_lo != _regs.eax) || (old_hi != _regs.edx) )
         {
@@ -1166,7 +1200,7 @@ x86_emulate_memop(
         }
         else
         {
-            if ( (rc = ops->cmpxchg8b(ea_seg, ea_off, old_lo, old_hi,
+            if ( (rc = ops->cmpxchg8b(ea.mem.seg, ea.mem.off, old_lo, old_hi,
                                       _regs.ebx, _regs.ecx, ctxt)) != 0 )
                 goto done;
             _regs.eflags |= EFLG_ZF;
@@ -1176,7 +1210,7 @@ x86_emulate_memop(
 #elif defined(__x86_64__)
     {
         unsigned long old, new;
-        if ( (rc = ops->read(ea_seg, ea_off, &old, 8, ctxt)) != 0 )
+        if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &old, 8, ctxt)) != 0 )
             goto done;
         if ( ((uint32_t)(old>>0) != (uint32_t)_regs.eax) ||
              ((uint32_t)(old>>32) != (uint32_t)_regs.edx) )
@@ -1188,7 +1222,8 @@ x86_emulate_memop(
         else
         {
             new = (_regs.ecx<<32)|(uint32_t)_regs.ebx;
-            if ( (rc = ops->cmpxchg(ea_seg, ea_off, old, new, 8, ctxt)) != 0 )
+            if ( (rc = ops->cmpxchg(ea.mem.seg, ea.mem.off, old,
+                                    new, 8, ctxt)) != 0 )
                 goto done;
             _regs.eflags |= EFLG_ZF;
         }
@@ -1201,10 +1236,10 @@ x86_emulate_memop(
  cannot_emulate:
 #ifdef __XEN__
     gdprintk(XENLOG_DEBUG, "Instr:");
-    for ( ea_off = ctxt->regs->eip; ea_off < _regs.eip; ea_off++ )
+    for ( ea.mem.off = ctxt->regs->eip; ea.mem.off < _regs.eip; ea.mem.off++ )
     {
         unsigned long x;
-        ops->insn_fetch(x86_seg_cs, ea_off, &x, 1, ctxt);
+        ops->insn_fetch(x86_seg_cs, ea.mem.off, &x, 1, ctxt);
         printk(" %02x", (uint8_t)x);
     }
     printk("\n");

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.