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

[Xen-changelog] [xen-unstable] [XEN] Fill in some more opcode space in the emulator.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1168344281 0
# Node ID 9518bff7c76229793086a5bff7c9336e3eabb005
# Parent  717f64715f3256b55f8af59c4e178285ae26a0b5
[XEN] Fill in some more opcode space in the emulator.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/x86_emulate.c |  122 ++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 114 insertions(+), 8 deletions(-)

diff -r 717f64715f32 -r 9518bff7c762 xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Tue Jan 09 11:52:15 2007 +0000
+++ b/xen/arch/x86/x86_emulate.c        Tue Jan 09 12:04:41 2007 +0000
@@ -62,19 +62,19 @@ static uint8_t opcode_table[256] = {
     /* 0x20 - 0x27 */
     ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
     ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
-    ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, 0,
+    ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, ImplicitOps,
     /* 0x28 - 0x2F */
     ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
     ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
-    ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, 0,
+    ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, ImplicitOps,
     /* 0x30 - 0x37 */
     ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
     ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
-    ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, 0,
+    ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, ImplicitOps,
     /* 0x38 - 0x3F */
     ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
     ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
-    ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, 0,
+    ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, ImplicitOps,
     /* 0x40 - 0x4F */
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
@@ -113,7 +113,8 @@ static uint8_t opcode_table[256] = {
     ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
     ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, 0, 0,
     /* 0xA8 - 0xAF */
-    0, 0, ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
+    ByteOp|DstReg|SrcImm, DstReg|SrcImm,
+    ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
     ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, 0, 0,
     /* 0xB0 - 0xB7 */
     ByteOp|DstReg|SrcImm|Mov, ByteOp|DstReg|SrcImm|Mov,
@@ -131,7 +132,7 @@ static uint8_t opcode_table[256] = {
     /* 0xD0 - 0xD7 */
     ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 
     ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 
-    0, 0, 0, 0,
+    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     /* 0xD8 - 0xDF */
     0, 0, 0, 0, 0, 0, 0, 0,
     /* 0xE0 - 0xE7 */
@@ -227,6 +228,9 @@ struct operand {
 #define EFLG_AF (1<<4)
 #define EFLG_PF (1<<2)
 #define EFLG_CF (1<<0)
+
+/* Exception definitions. */
+#define EXC_DE 0
 
 /*
  * Instruction emulation:
@@ -408,6 +412,23 @@ do{ __asm__ __volatile__ (              
 
 #define mode_64bit() (def_ad_bytes == 8)
 
+#define fail_if(p)                              \
+do {                                            \
+    rc = (p) ? X86EMUL_UNHANDLEABLE : 0;        \
+    if ( rc ) goto done;                        \
+} while (0)
+
+/* In future we will be able to generate arbitrary exceptions. */
+#define generate_exception_if(p, e) fail_if(p)
+
+/* Given byte has even parity (even number of 1s)? */
+static int even_parity(uint8_t v)
+{
+    __asm__ ( "test %%al,%%al; setp %%al"
+              : "=a" (v) : "0" (v) );
+    return v;
+}
+
 /* Update address held in a register, based on addressing mode. */
 #define _register_address_increment(reg, inc, byte_width)               \
 do {                                                                    \
@@ -942,6 +963,9 @@ x86_emulate(
         }
         break;
 
+    case 0xa8 ... 0xa9: /* test imm,%%eax */
+        dst.reg = (unsigned long *)&_regs.eax;
+        dst.val = dst.orig_val = _regs.eax;
     case 0x84 ... 0x85: test: /* test */
         emulate_2op_SrcV("test", src, dst, _regs.eflags);
         break;
@@ -960,8 +984,9 @@ x86_emulate(
         lock_prefix = 1;
         break;
 
+    case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
+        fail_if((modrm_reg & 7) != 0);
     case 0x88 ... 0x8b: /* mov */
-    case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
         dst.val = src.val;
         break;
 
@@ -970,6 +995,7 @@ x86_emulate(
         break;
 
     case 0x8f: /* pop (sole member of Grp1a) */
+        fail_if((modrm_reg & 7) != 0);
         /* 64-bit mode: POP defaults to a 64-bit operand. */
         if ( mode_64bit() && (dst.bytes == 4) )
             dst.bytes = 8;
@@ -1056,7 +1082,9 @@ x86_emulate(
         }
         break;
 
-    case 0xfe ... 0xff: /* Grp4/Grp5 */
+    case 0xfe: /* Grp4 */
+        fail_if((modrm_reg & 7) >= 2);
+    case 0xff: /* Grp5 */
         switch ( modrm_reg & 7 )
         {
         case 0: /* inc */
@@ -1080,6 +1108,8 @@ x86_emulate(
                 goto done;
             dst.val = dst.orig_val; /* skanky: disable writeback */
             break;
+        case 7:
+            fail_if(1);
         default:
             goto cannot_emulate;
         }
@@ -1142,6 +1172,43 @@ x86_emulate(
 
     switch ( b )
     {
+    case 0x27: /* daa */ {
+        uint8_t al = _regs.eax;
+        unsigned long tmp;
+        fail_if(mode_64bit());
+        __asm__ __volatile__ (
+            _PRE_EFLAGS("0","4","2") "daa; " _POST_EFLAGS("0","4","2")
+            : "=m" (_regs.eflags), "=a" (al), "=&r" (tmp)
+            : "a" (al), "i" (EFLAGS_MASK) );
+        *(uint8_t *)_regs.eax = al;
+        break;
+    }
+
+    case 0x2f: /* das */ {
+        uint8_t al = _regs.eax;
+        unsigned long tmp;
+        fail_if(mode_64bit());
+        __asm__ __volatile__ (
+            _PRE_EFLAGS("0","4","2") "das; " _POST_EFLAGS("0","4","2")
+            : "=m" (_regs.eflags), "=a" (al), "=&r" (tmp)
+            : "a" (al), "i" (EFLAGS_MASK) );
+        *(uint8_t *)_regs.eax = al;
+        break;
+    }
+
+    case 0x37: /* aaa */
+    case 0x3f: /* aas */
+        fail_if(mode_64bit());
+        _regs.eflags &= ~EFLG_CF;
+        if ( ((uint8_t)_regs.eax > 9) || (_regs.eflags & EFLG_AF) )
+        {
+            ((uint8_t *)&_regs.eax)[0] += (b == 0x37) ? 6 : -6;
+            ((uint8_t *)&_regs.eax)[1] += (b == 0x37) ? 1 : -1;
+            _regs.eflags |= EFLG_CF | EFLG_AF;
+        }
+        ((uint8_t *)&_regs.eax)[0] &= 0x0f;
+        break;
+
     case 0x40 ... 0x4f: /* inc/dec reg */
         dst.type  = OP_REG;
         dst.reg   = decode_register(b & 7, &_regs, 0);
@@ -1253,6 +1320,45 @@ x86_emulate(
             _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
         break;
 
+    case 0xd4: /* aam */ {
+        unsigned int base = insn_fetch_type(uint8_t);
+        uint8_t al = _regs.eax;
+        fail_if(mode_64bit());
+        generate_exception_if(base == 0, EXC_DE);
+        *(uint16_t *)&_regs.eax = ((al / base) << 8) | (al % base);
+        _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
+        _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
+        _regs.eflags |= (( int8_t)_regs.eax <  0) ? EFLG_SF : 0;
+        _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0;
+        break;
+    }
+
+    case 0xd5: /* aad */ {
+        unsigned int base = insn_fetch_type(uint8_t);
+        uint16_t ax = _regs.eax;
+        fail_if(mode_64bit());
+        *(uint16_t *)&_regs.eax = (uint8_t)(ax + ((ax >> 8) * base));
+        _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
+        _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
+        _regs.eflags |= (( int8_t)_regs.eax <  0) ? EFLG_SF : 0;
+        _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0;
+        break;
+    }
+
+    case 0xd6: /* salc */
+        fail_if(mode_64bit());
+        *(uint8_t *)&_regs.eax = (_regs.eflags & EFLG_CF) ? 0xff : 0x00;
+        break;
+
+    case 0xd7: /* xlat */ {
+        unsigned long al = (uint8_t)_regs.eax;
+        if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.ebx + al),
+                             &al, 1, ctxt)) != 0 )
+            goto done;
+        *(uint8_t *)&_regs.eax = al;
+        break;
+    }
+
     case 0xe3: /* jcxz/jecxz (short) */ {
         int rel = insn_fetch_type(int8_t);
         if ( (ad_bytes == 2) ? !(uint16_t)_regs.ecx :

_______________________________________________
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®.