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

[Xen-changelog] [xen-unstable] x86_emulate: More FPU instructions.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1204550035 0
# Node ID a2359114b6cb82966fde343f18cfbe1a5b60cc9c
# Parent  c89f6ed5635179695c92810a9c9eec205e5d0d78
x86_emulate: More FPU instructions.

Enables booting OS/2 as a HVM guest on Intel/VT hardware with full
real-mode emulation (no vmxassist).

Signed-off-by: Trolle Selander <trolle.selander@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/x86_emulate.c |   91 +++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 83 insertions(+), 8 deletions(-)

diff -r c89f6ed56351 -r a2359114b6cb xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Mon Mar 03 11:47:40 2008 +0000
+++ b/xen/arch/x86/x86_emulate.c        Mon Mar 03 13:13:55 2008 +0000
@@ -127,7 +127,7 @@ static uint8_t opcode_table[256] = {
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     /* 0x98 - 0x9F */
-    ImplicitOps, ImplicitOps, ImplicitOps, 0,
+    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     /* 0xA0 - 0xA7 */
     ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
@@ -160,7 +160,8 @@ static uint8_t opcode_table[256] = {
     ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     /* 0xD8 - 0xDF */
-    0, ImplicitOps|ModRM, 0, ImplicitOps|ModRM, 0, ImplicitOps|ModRM, 0, 0,
+    0, ImplicitOps|ModRM|Mov, 0, ImplicitOps|ModRM|Mov,
+    0, ImplicitOps|ModRM|Mov, ImplicitOps|ModRM|Mov, ImplicitOps|ModRM|Mov,
     /* 0xE0 - 0xE7 */
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
@@ -309,6 +310,7 @@ struct operand {
 #define EXC_SS 12
 #define EXC_GP 13
 #define EXC_PF 14
+#define EXC_MF 16
 
 /*
  * Instruction emulation:
@@ -475,6 +477,31 @@ do{ asm volatile (                      
 #define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy)
 #define __emulate_1op_8byte(_op, _dst, _eflags)
 #endif /* __i386__ */
+
+#ifdef __XEN__
+#define __emulate_fpu_insn(_op)                 \
+do{ int _exn;                                   \
+    asm volatile (                              \
+        "1: " _op "\n"                          \
+        "2: \n"                                 \
+        ".section .fixup,\"ax\"\n"              \
+        "3: mov $1,%0\n"                        \
+        "   jmp 2b\n"                           \
+        ".previous\n"                           \
+        ".section __ex_table,\"a\"\n"           \
+        "   "__FIXUP_ALIGN"\n"                  \
+        "   "__FIXUP_WORD" 1b,3b\n"             \
+        ".previous"                             \
+        : "=r" (_exn) : "0" (0) );              \
+    generate_exception_if(_exn, EXC_MF, -1);    \
+} while (0)
+#else
+#define __emulate_fpu_insn(_op)                 \
+do{ rc = X86EMUL_UNHANDLEABLE;                  \
+    goto done;                                  \
+} while (0)
+#endif
+
 
 /* Fetch next part of the instruction being emulated. */
 #define insn_fetch_bytes(_size)                                         \
@@ -2355,6 +2382,10 @@ x86_emulate(
         break;
     }
 
+    case 0x9b:  /* wait/fwait */
+        __emulate_fpu_insn("fwait");
+        break;
+
     case 0x9c: /* pushf */
         src.val = _regs.eflags;
         goto push;
@@ -2670,12 +2701,27 @@ x86_emulate(
     case 0xd9: /* FPU 0xd9 */
         fail_if(ops->load_fpu_ctxt == NULL);
         ops->load_fpu_ctxt(ctxt);
-        fail_if((modrm_reg & 7) != 7);
-        fail_if(modrm >= 0xc0);
-        /* fnstcw m2byte */
-        ea.bytes = 2;
-        dst = ea;
-        asm volatile ( "fnstcw %0" : "=m" (dst.val) );
+        switch ( modrm )
+        {
+        case 0xc0: __emulate_fpu_insn("fld %%st(0)"); break;
+        case 0xc1: __emulate_fpu_insn("fld %%st(1)"); break;
+        case 0xc2: __emulate_fpu_insn("fld %%st(2)"); break;
+        case 0xc3: __emulate_fpu_insn("fld %%st(3)"); break;
+        case 0xc4: __emulate_fpu_insn("fld %%st(4)"); break;
+        case 0xc5: __emulate_fpu_insn("fld %%st(5)"); break;
+        case 0xc6: __emulate_fpu_insn("fld %%st(6)"); break;
+        case 0xc7: __emulate_fpu_insn("fld %%st(7)"); break;
+        case 0xe0: __emulate_fpu_insn("fchs"); break;
+        case 0xe8: __emulate_fpu_insn("fld1"); break;
+        case 0xee: __emulate_fpu_insn("fldz"); break;
+        default:
+            fail_if((modrm_reg & 7) != 7);
+            fail_if(modrm >= 0xc0);
+            /* fnstcw m2byte */
+            ea.bytes = 2;
+            dst = ea;
+            asm volatile ( "fnstcw %0" : "=m" (dst.val) );
+        }
         break;
 
     case 0xdb: /* FPU 0xdb */
@@ -2694,6 +2740,35 @@ x86_emulate(
         /* fnstsw m2byte */
         ea.bytes = 2;
         dst = ea;
+        asm volatile ( "fnstsw %0" : "=m" (dst.val) );
+        break;
+
+    case 0xde: /* FPU 0xde */
+        fail_if(ops->load_fpu_ctxt == NULL);
+        ops->load_fpu_ctxt(ctxt);
+        switch ( modrm )
+        {
+        case 0xd9: __emulate_fpu_insn("fcompp"); break;
+        case 0xf8: __emulate_fpu_insn("fdivp %%st(0),%%st(0)"); break;
+        case 0xf9: __emulate_fpu_insn("fdivp %%st(1),%%st(0)"); break;
+        case 0xfa: __emulate_fpu_insn("fdivp %%st(2),%%st(0)"); break;
+        case 0xfb: __emulate_fpu_insn("fdivp %%st(3),%%st(0)"); break;
+        case 0xfc: __emulate_fpu_insn("fdivp %%st(4),%%st(0)"); break;
+        case 0xfd: __emulate_fpu_insn("fdivp %%st(5),%%st(0)"); break;
+        case 0xfe: __emulate_fpu_insn("fdivp %%st(6),%%st(0)"); break;
+        case 0xff: __emulate_fpu_insn("fdivp %%st(7),%%st(0)"); break;
+        default: goto cannot_emulate;
+        }
+        break;
+
+    case 0xdf: /* FPU 0xdf */
+        fail_if(ops->load_fpu_ctxt == NULL);
+        ops->load_fpu_ctxt(ctxt);
+        fail_if(modrm != 0xe0);
+        /* fnstsw %ax */
+        dst.bytes = 2;
+        dst.type = OP_REG;
+        dst.reg = (unsigned long *)&_regs.eax;
         asm volatile ( "fnstsw %0" : "=m" (dst.val) );
         break;
 

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