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] Add support for MOVSX/MOVSXD/MOVZX (move-with-extend)

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Add support for MOVSX/MOVSXD/MOVZX (move-with-extend)
From: Xen patchbot -unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 21 Dec 2005 14:38:06 +0000
Delivery-date: Wed, 21 Dec 2005 14:41:03 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
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 kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID c259492dfb43d83fdb74bb4f4fd8be6ccfa926ee
# Parent  6e24488a89f7eade3857d1bc11fcc3e24857dc59
Add support for MOVSX/MOVSXD/MOVZX (move-with-extend)
instructions to the generic x86 emulator. Also add
preliminary support for 16-bit addressing: decode the
ModR/M byte properly but still need to access and update
implicit memory operands (esp,esi,edi) with correct width.
Work is also needed to support real-mode addressing.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 6e24488a89f7 -r c259492dfb43 tools/tests/Makefile
--- a/tools/tests/Makefile      Tue Dec 20 17:45:29 2005
+++ b/tools/tests/Makefile      Wed Dec 21 13:29:23 2005
@@ -6,6 +6,8 @@
 
 CC     := gcc
 CFLAGS := -O2 -Wall -Werror -D__TEST_HARNESS__
+
+all: $(TARGET)
 
 $(TARGET): x86_emulate.o test_x86_emulator.o
        $(CC) -o $@ $^
diff -r 6e24488a89f7 -r c259492dfb43 tools/tests/test_x86_emulator.c
--- a/tools/tests/test_x86_emulator.c   Tue Dec 20 17:45:29 2005
+++ b/tools/tests/test_x86_emulator.c   Wed Dec 21 13:29:23 2005
@@ -254,6 +254,36 @@
         goto fail;
     printf("okay\n");
 
+    printf("%-40s", "Testing movsxbd (%%eax),%%ecx...");
+    instr[0] = 0x0f; instr[1] = 0xbe; instr[2] = 0x08;
+    regs.eip    = (unsigned long)&instr[0];
+    regs.ecx    = 0x12345678;
+    cr2         = (unsigned long)&res;
+    res         = 0x82;
+    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);
+    if ( (rc != 0) ||
+         (res != 0x82) ||
+         (regs.ecx != 0xFFFFFF82) ||
+         ((regs.eflags&0x240) != 0x200) ||
+         (regs.eip != (unsigned long)&instr[3]) )
+        goto fail;
+    printf("okay\n");
+
+    printf("%-40s", "Testing movzxwd (%%eax),%%ecx...");
+    instr[0] = 0x0f; instr[1] = 0xb7; instr[2] = 0x08;
+    regs.eip    = (unsigned long)&instr[0];
+    regs.ecx    = 0x12345678;
+    cr2         = (unsigned long)&res;
+    res         = 0x1234aa82;
+    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);
+    if ( (rc != 0) ||
+         (res != 0x1234aa82) ||
+         (regs.ecx != 0xaa82) ||
+         ((regs.eflags&0x240) != 0x200) ||
+         (regs.eip != (unsigned long)&instr[3]) )
+        goto fail;
+    printf("okay\n");
+
     return 0;
 
  fail:
diff -r 6e24488a89f7 -r c259492dfb43 xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Tue Dec 20 17:45:29 2005
+++ b/xen/arch/x86/x86_emulate.c        Wed Dec 21 13:29:23 2005
@@ -9,14 +9,6 @@
 #ifdef __TEST_HARNESS__
 #include <stdio.h>
 #include <stdint.h>
-typedef uint8_t            u8;
-typedef uint16_t           u16;
-typedef uint32_t           u32;
-typedef uint64_t           u64;
-typedef int8_t             s8;
-typedef int16_t            s16;
-typedef int32_t            s32;
-typedef int64_t            s64;
 #include <public/xen.h>
 #define DPRINTF(_f, _a...) printf( _f , ## _a )
 #else
@@ -50,15 +42,17 @@
 #define SrcImplicit (0<<3) /* Source operand is implicit in the opcode. */
 #define SrcReg      (1<<3) /* Register operand. */
 #define SrcMem      (2<<3) /* Memory operand. */
-#define SrcImm      (3<<3) /* Immediate operand. */
-#define SrcImmByte  (4<<3) /* 8-bit sign-extended immediate operand. */
+#define SrcMem16    (3<<3) /* Memory operand (16-bit). */
+#define SrcMem32    (4<<3) /* Memory operand (32-bit). */
+#define SrcImm      (5<<3) /* Immediate operand. */
+#define SrcImmByte  (6<<3) /* 8-bit sign-extended immediate operand. */
 #define SrcMask     (7<<3)
 /* Generic ModRM decode. */
 #define ModRM       (1<<6)
 /* Destination is only written; never read. */
 #define Mov         (1<<7)
 
-static u8 opcode_table[256] = {
+static uint8_t opcode_table[256] = {
     /* 0x00 - 0x07 */
     ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
     ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
@@ -96,7 +90,8 @@
     /* 0x50 - 0x5F */
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     /* 0x60 - 0x6F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, DstReg|SrcMem32|ModRM|Mov /* movsxd (x86/64) */,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     /* 0x70 - 0x7F */
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     /* 0x80 - 0x87 */
@@ -142,7 +137,7 @@
     0, 0, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM
 };
 
-static u8 twobyte_table[256] = {
+static uint8_t twobyte_table[256] = {
     /* 0x00 - 0x0F */
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0,
     /* 0x10 - 0x1F */
@@ -177,9 +172,10 @@
     0, 0, 0, DstMem|SrcReg|ModRM, 0, 0, 0, 0,
     /* 0xB0 - 0xB7 */
     ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, 0, DstMem|SrcReg|ModRM,
-    0, 0, 0, 0,
+    0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov,
     /* 0xB8 - 0xBF */
-    0, 0, DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM, 0, 0, 0, 0,
+    0, 0, DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM,
+    0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov,
     /* 0xC0 - 0xCF */
     0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0, 0,
     /* 0xD0 - 0xDF */
@@ -377,7 +373,7 @@
 
 void *
 decode_register(
-    u8 modrm_reg, struct cpu_user_regs *regs, int highbyte_regs)
+    uint8_t modrm_reg, struct cpu_user_regs *regs, int highbyte_regs)
 {
     void *p;
 
@@ -422,8 +418,8 @@
     struct x86_mem_emulator *ops,
     int mode)
 {
-    u8 b, d, sib, twobyte = 0, rex_prefix = 0;
-    u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
+    uint8_t b, d, sib, twobyte = 0, rex_prefix = 0;
+    uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
     unsigned int op_bytes = (mode == 8) ? 4 : mode, ad_bytes = mode;
     unsigned int lock_prefix = 0, rep_prefix = 0, i;
     int rc = 0;
@@ -435,7 +431,7 @@
     /* Legacy prefixes. */
     for ( i = 0; i < 8; i++ )
     {
-        switch ( b = insn_fetch(u8, 1, _regs.eip) )
+        switch ( b = insn_fetch(uint8_t, 1, _regs.eip) )
         {
         case 0x66: /* operand-size override */
             op_bytes ^= 6;                    /* switch between 2/4 bytes */
@@ -465,12 +461,6 @@
     }
  done_prefixes:
 
-    if ( ad_bytes == 2 )
-    {
-        DPRINTF("Cannot parse 16-bit effective addresses.\n");
-        goto cannot_emulate;
-    }
-
     /* REX prefix. */
     if ( (mode == 8) && ((b & 0xf0) == 0x40) )
     {
@@ -479,7 +469,7 @@
             op_bytes = 8;          /* REX.W */
         modrm_reg = (b & 4) << 1;  /* REX.R */
         /* REX.B and REX.X do not need to be decoded. */
-        b = insn_fetch(u8, 1, _regs.eip);
+        b = insn_fetch(uint8_t, 1, _regs.eip);
     }
 
     /* Opcode byte(s). */
@@ -490,7 +480,7 @@
         if ( b == 0x0f )
         {
             twobyte = 1;
-            b = insn_fetch(u8, 1, _regs.eip);
+            b = insn_fetch(uint8_t, 1, _regs.eip);
             d = twobyte_table[b];
         }
 
@@ -502,32 +492,57 @@
     /* ModRM and SIB bytes. */
     if ( d & ModRM )
     {
-        modrm = insn_fetch(u8, 1, _regs.eip);
+        modrm = insn_fetch(uint8_t, 1, _regs.eip);
         modrm_mod |= (modrm & 0xc0) >> 6;
         modrm_reg |= (modrm & 0x38) >> 3;
         modrm_rm  |= (modrm & 0x07);
-        switch ( modrm_mod )
-        {
-        case 0:
-            if ( (modrm_rm == 4) && 
-                 (((sib = insn_fetch(u8, 1, _regs.eip)) & 7) == 5) )
-                _regs.eip += 4; /* skip disp32 specified by SIB.base */
-            else if ( modrm_rm == 5 )
-                _regs.eip += 4; /* skip disp32 */
-            break;
-        case 1:
-            if ( modrm_rm == 4 )
-                sib = insn_fetch(u8, 1, _regs.eip);
-            _regs.eip += 1; /* skip disp8 */
-            break;
-        case 2:
-            if ( modrm_rm == 4 )
-                sib = insn_fetch(u8, 1, _regs.eip);
-            _regs.eip += 4; /* skip disp32 */
-            break;
-        case 3:
+
+        if ( modrm_mod == 3 )
+        {
             DPRINTF("Cannot parse ModRM.mod == 3.\n");
             goto cannot_emulate;
+        }
+
+        if ( ad_bytes == 2 )
+        {
+            /* 16-bit ModR/M decode. */
+            switch ( modrm_mod )
+            {
+            case 0:
+                if ( modrm_rm == 6 )
+                    _regs.eip += 2; /* skip disp16 */
+                break;
+            case 1:
+                _regs.eip += 1; /* skip disp8 */
+                break;
+            case 2:
+                _regs.eip += 2; /* skip disp16 */
+                break;
+            }
+        }
+        else
+        {
+            /* 32/64-bit ModR/M decode. */
+            switch ( modrm_mod )
+            {
+            case 0:
+                if ( (modrm_rm == 4) && 
+                     (((sib = insn_fetch(uint8_t, 1, _regs.eip)) & 7) == 5) )
+                    _regs.eip += 4; /* skip disp32 specified by SIB.base */
+                else if ( modrm_rm == 5 )
+                    _regs.eip += 4; /* skip disp32 */
+                break;
+            case 1:
+                if ( modrm_rm == 4 )
+                    sib = insn_fetch(uint8_t, 1, _regs.eip);
+                _regs.eip += 1; /* skip disp8 */
+                break;
+            case 2:
+                if ( modrm_rm == 4 )
+                    sib = insn_fetch(uint8_t, 1, _regs.eip);
+                _regs.eip += 4; /* skip disp32 */
+                break;
+            }
         }
     }
 
@@ -542,7 +557,7 @@
         if ( d & ByteOp )
         {
             dst.ptr = decode_register(modrm_reg, &_regs, (rex_prefix == 0));
-            dst.val = *(u8 *)dst.ptr;
+            dst.val = *(uint8_t *)dst.ptr;
             dst.bytes = 1;
         }
         else
@@ -550,9 +565,9 @@
             dst.ptr = decode_register(modrm_reg, &_regs, 0);
             switch ( (dst.bytes = op_bytes) )
             {
-            case 2: dst.val = *(u16 *)dst.ptr; break;
-            case 4: dst.val = *(u32 *)dst.ptr; break;
-            case 8: dst.val = *(u64 *)dst.ptr; break;
+            case 2: dst.val = *(uint16_t *)dst.ptr; break;
+            case 4: dst.val = *(uint32_t *)dst.ptr; break;
+            case 8: dst.val = *(uint64_t *)dst.ptr; break;
             }
         }
         break;
@@ -578,7 +593,7 @@
         if ( d & ByteOp )
         {
             src.ptr = decode_register(modrm_reg, &_regs, (rex_prefix == 0));
-            src.val = src.orig_val = *(u8 *)src.ptr;
+            src.val = src.orig_val = *(uint8_t *)src.ptr;
             src.bytes = 1;
         }
         else
@@ -586,16 +601,23 @@
             src.ptr = decode_register(modrm_reg, &_regs, 0);
             switch ( (src.bytes = op_bytes) )
             {
-            case 2: src.val = src.orig_val = *(u16 *)src.ptr; break;
-            case 4: src.val = src.orig_val = *(u32 *)src.ptr; break;
-            case 8: src.val = src.orig_val = *(u64 *)src.ptr; break;
+            case 2: src.val = src.orig_val = *(uint16_t *)src.ptr; break;
+            case 4: src.val = src.orig_val = *(uint32_t *)src.ptr; break;
+            case 8: src.val = src.orig_val = *(uint64_t *)src.ptr; break;
             }
         }
         break;
+    case SrcMem16:
+        src.bytes = 2;
+        goto srcmem_common;
+    case SrcMem32:
+        src.bytes = 4;
+        goto srcmem_common;
     case SrcMem:
+        src.bytes = (d & ByteOp) ? 1 : op_bytes;
+    srcmem_common:
         src.type  = OP_MEM;
         src.ptr   = (unsigned long *)cr2;
-        src.bytes = (d & ByteOp) ? 1 : op_bytes;
         if ( (rc = ops->read_emulated((unsigned long)src.ptr, 
                                       &src.val, src.bytes)) != 0 )
             goto done;
@@ -609,16 +631,16 @@
         /* NB. Immediates are sign-extended as necessary. */
         switch ( src.bytes )
         {
-        case 1: src.val = insn_fetch(s8,  1, _regs.eip); break;
-        case 2: src.val = insn_fetch(s16, 2, _regs.eip); break;
-        case 4: src.val = insn_fetch(s32, 4, _regs.eip); break;
+        case 1: src.val = insn_fetch(int8_t,  1, _regs.eip); break;
+        case 2: src.val = insn_fetch(int16_t, 2, _regs.eip); break;
+        case 4: src.val = insn_fetch(int32_t, 4, _regs.eip); break;
         }
         break;
     case SrcImmByte:
         src.type  = OP_IMM;
         src.ptr   = (unsigned long *)_regs.eip;
         src.bytes = 1;
-        src.val   = insn_fetch(s8,  1, _regs.eip);
+        src.val   = insn_fetch(int8_t,  1, _regs.eip);
         break;
     }
 
@@ -650,6 +672,11 @@
         break;
     case 0x38 ... 0x3d: cmp: /* cmp */
         emulate_2op_SrcV("cmp", src, dst, _regs.eflags);
+        break;
+    case 0x63: /* movsxd */
+        if ( mode != 8 ) /* x86/64 long mode only */
+            goto cannot_emulate;
+        dst.val = (int32_t)src.val;
         break;
     case 0x80 ... 0x83: /* Grp1 */
         switch ( modrm_reg )
@@ -671,9 +698,9 @@
         /* Write back the register source. */
         switch ( dst.bytes )
         {
-        case 1: *(u8  *)src.ptr = (u8)dst.val; break;
-        case 2: *(u16 *)src.ptr = (u16)dst.val; break;
-        case 4: *src.ptr = (u32)dst.val; break; /* 64b mode: zero-extend */
+        case 1: *(uint8_t  *)src.ptr = (uint8_t)dst.val; break;
+        case 2: *(uint16_t *)src.ptr = (uint16_t)dst.val; break;
+        case 4: *src.ptr = (uint32_t)dst.val; break; /* 64b reg: zero-extend */
         case 8: *src.ptr = dst.val; break;
         }
         /* Write back the memory destination with implicit LOCK prefix. */
@@ -745,9 +772,9 @@
             if ( src.bytes == 8 ) src.bytes = 4;
             switch ( src.bytes )
             {
-            case 1: src.val = insn_fetch(s8,  1, _regs.eip); break;
-            case 2: src.val = insn_fetch(s16, 2, _regs.eip); break;
-            case 4: src.val = insn_fetch(s32, 4, _regs.eip); break;
+            case 1: src.val = insn_fetch(int8_t,  1, _regs.eip); break;
+            case 2: src.val = insn_fetch(int16_t, 2, _regs.eip); break;
+            case 4: src.val = insn_fetch(int32_t, 4, _regs.eip); break;
             }
             goto test;
         case 2: /* not */
@@ -798,9 +825,9 @@
             /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
             switch ( dst.bytes )
             {
-            case 1: *(u8  *)dst.ptr = (u8)dst.val; break;
-            case 2: *(u16 *)dst.ptr = (u16)dst.val; break;
-            case 4: *dst.ptr = (u32)dst.val; break; /* 64b mode: zero-extend */
+            case 1: *(uint8_t  *)dst.ptr = (uint8_t)dst.val; break;
+            case 2: *(uint16_t *)dst.ptr = (uint16_t)dst.val; break;
+            case 4: *dst.ptr = (uint32_t)dst.val; break; /* 64b: zero-ext */
             case 8: *dst.ptr = dst.val; break;
             }
             break;
@@ -953,6 +980,10 @@
         src.val &= (dst.bytes << 3) - 1; /* only subword offset */
         emulate_2op_SrcV_nobyte("bts", src, dst, _regs.eflags);
         break;
+    case 0xb6 ... 0xb7: /* movzx */
+        dst.bytes = op_bytes;
+        dst.val = (d & ByteOp) ? (uint8_t)src.val : (uint16_t)src.val;
+        break;
     case 0xbb: btc: /* btc */
         src.val &= (dst.bytes << 3) - 1; /* only subword offset */
         emulate_2op_SrcV_nobyte("btc", src, dst, _regs.eflags);
@@ -965,6 +996,10 @@
         case 2: goto btr;
         case 3: goto btc;
         }
+        break;
+    case 0xbe ... 0xbf: /* movsx */
+        dst.bytes = op_bytes;
+        dst.val = (d & ByteOp) ? (int8_t)src.val : (int16_t)src.val;
         break;
     }
     goto writeback;
@@ -1009,16 +1044,16 @@
         unsigned long old, new;
         if ( (rc = ops->read_emulated(cr2, &old, 8)) != 0 )
             goto done;
-        if ( ((u32)(old>>0) != (u32)_regs.eax) ||
-             ((u32)(old>>32) != (u32)_regs.edx) )
-        {
-            _regs.eax = (u32)(old>>0);
-            _regs.edx = (u32)(old>>32);
+        if ( ((uint32_t)(old>>0) != (uint32_t)_regs.eax) ||
+             ((uint32_t)(old>>32) != (uint32_t)_regs.edx) )
+        {
+            _regs.eax = (uint32_t)(old>>0);
+            _regs.edx = (uint32_t)(old>>32);
             _regs.eflags &= ~EFLG_ZF;
         }
         else
         {
-            new = (_regs.ecx<<32)|(u32)_regs.ebx;
+            new = (_regs.ecx<<32)|(uint32_t)_regs.ebx;
             if ( (rc = ops->cmpxchg_emulated(cr2, old, new, 8)) != 0 )
                 goto done;
             _regs.eflags |= EFLG_ZF;
diff -r 6e24488a89f7 -r c259492dfb43 xen/include/asm-x86/x86_emulate.h
--- a/xen/include/asm-x86/x86_emulate.h Tue Dec 20 17:45:29 2005
+++ b/xen/include/asm-x86/x86_emulate.h Wed Dec 21 13:29:23 2005
@@ -164,6 +164,6 @@
  */
 extern void *
 decode_register(
-    u8 modrm_reg, struct cpu_user_regs *regs, int highbyte_regs);
+    uint8_t modrm_reg, struct cpu_user_regs *regs, int highbyte_regs);
 
 #endif /* __X86_EMULATE_H__ */

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Add support for MOVSX/MOVSXD/MOVZX (move-with-extend), Xen patchbot -unstable <=