# 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
|