ia64/xen-unstable

changeset 17175:a2359114b6cb

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@gmail.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Mar 03 13:13:55 2008 +0000 (2008-03-03)
parents c89f6ed56351
children 38bbaa69c065
files xen/arch/x86/x86_emulate.c
line diff
     1.1 --- a/xen/arch/x86/x86_emulate.c	Mon Mar 03 11:47:40 2008 +0000
     1.2 +++ b/xen/arch/x86/x86_emulate.c	Mon Mar 03 13:13:55 2008 +0000
     1.3 @@ -127,7 +127,7 @@ static uint8_t opcode_table[256] = {
     1.4      ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     1.5      ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     1.6      /* 0x98 - 0x9F */
     1.7 -    ImplicitOps, ImplicitOps, ImplicitOps, 0,
     1.8 +    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     1.9      ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
    1.10      /* 0xA0 - 0xA7 */
    1.11      ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
    1.12 @@ -160,7 +160,8 @@ static uint8_t opcode_table[256] = {
    1.13      ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 
    1.14      ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
    1.15      /* 0xD8 - 0xDF */
    1.16 -    0, ImplicitOps|ModRM, 0, ImplicitOps|ModRM, 0, ImplicitOps|ModRM, 0, 0,
    1.17 +    0, ImplicitOps|ModRM|Mov, 0, ImplicitOps|ModRM|Mov,
    1.18 +    0, ImplicitOps|ModRM|Mov, ImplicitOps|ModRM|Mov, ImplicitOps|ModRM|Mov,
    1.19      /* 0xE0 - 0xE7 */
    1.20      ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
    1.21      ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
    1.22 @@ -309,6 +310,7 @@ struct operand {
    1.23  #define EXC_SS 12
    1.24  #define EXC_GP 13
    1.25  #define EXC_PF 14
    1.26 +#define EXC_MF 16
    1.27  
    1.28  /*
    1.29   * Instruction emulation:
    1.30 @@ -476,6 +478,31 @@ do{ asm volatile (                      
    1.31  #define __emulate_1op_8byte(_op, _dst, _eflags)
    1.32  #endif /* __i386__ */
    1.33  
    1.34 +#ifdef __XEN__
    1.35 +#define __emulate_fpu_insn(_op)                 \
    1.36 +do{ int _exn;                                   \
    1.37 +    asm volatile (                              \
    1.38 +        "1: " _op "\n"                          \
    1.39 +        "2: \n"                                 \
    1.40 +        ".section .fixup,\"ax\"\n"              \
    1.41 +        "3: mov $1,%0\n"                        \
    1.42 +        "   jmp 2b\n"                           \
    1.43 +        ".previous\n"                           \
    1.44 +        ".section __ex_table,\"a\"\n"           \
    1.45 +        "   "__FIXUP_ALIGN"\n"                  \
    1.46 +        "   "__FIXUP_WORD" 1b,3b\n"             \
    1.47 +        ".previous"                             \
    1.48 +        : "=r" (_exn) : "0" (0) );              \
    1.49 +    generate_exception_if(_exn, EXC_MF, -1);    \
    1.50 +} while (0)
    1.51 +#else
    1.52 +#define __emulate_fpu_insn(_op)                 \
    1.53 +do{ rc = X86EMUL_UNHANDLEABLE;                  \
    1.54 +    goto done;                                  \
    1.55 +} while (0)
    1.56 +#endif
    1.57 +
    1.58 +
    1.59  /* Fetch next part of the instruction being emulated. */
    1.60  #define insn_fetch_bytes(_size)                                         \
    1.61  ({ unsigned long _x, _eip = _regs.eip;                                  \
    1.62 @@ -2355,6 +2382,10 @@ x86_emulate(
    1.63          break;
    1.64      }
    1.65  
    1.66 +    case 0x9b:  /* wait/fwait */
    1.67 +        __emulate_fpu_insn("fwait");
    1.68 +        break;
    1.69 +
    1.70      case 0x9c: /* pushf */
    1.71          src.val = _regs.eflags;
    1.72          goto push;
    1.73 @@ -2670,12 +2701,27 @@ x86_emulate(
    1.74      case 0xd9: /* FPU 0xd9 */
    1.75          fail_if(ops->load_fpu_ctxt == NULL);
    1.76          ops->load_fpu_ctxt(ctxt);
    1.77 -        fail_if((modrm_reg & 7) != 7);
    1.78 -        fail_if(modrm >= 0xc0);
    1.79 -        /* fnstcw m2byte */
    1.80 -        ea.bytes = 2;
    1.81 -        dst = ea;
    1.82 -        asm volatile ( "fnstcw %0" : "=m" (dst.val) );
    1.83 +        switch ( modrm )
    1.84 +        {
    1.85 +        case 0xc0: __emulate_fpu_insn("fld %%st(0)"); break;
    1.86 +        case 0xc1: __emulate_fpu_insn("fld %%st(1)"); break;
    1.87 +        case 0xc2: __emulate_fpu_insn("fld %%st(2)"); break;
    1.88 +        case 0xc3: __emulate_fpu_insn("fld %%st(3)"); break;
    1.89 +        case 0xc4: __emulate_fpu_insn("fld %%st(4)"); break;
    1.90 +        case 0xc5: __emulate_fpu_insn("fld %%st(5)"); break;
    1.91 +        case 0xc6: __emulate_fpu_insn("fld %%st(6)"); break;
    1.92 +        case 0xc7: __emulate_fpu_insn("fld %%st(7)"); break;
    1.93 +        case 0xe0: __emulate_fpu_insn("fchs"); break;
    1.94 +        case 0xe8: __emulate_fpu_insn("fld1"); break;
    1.95 +        case 0xee: __emulate_fpu_insn("fldz"); break;
    1.96 +        default:
    1.97 +            fail_if((modrm_reg & 7) != 7);
    1.98 +            fail_if(modrm >= 0xc0);
    1.99 +            /* fnstcw m2byte */
   1.100 +            ea.bytes = 2;
   1.101 +            dst = ea;
   1.102 +            asm volatile ( "fnstcw %0" : "=m" (dst.val) );
   1.103 +        }
   1.104          break;
   1.105  
   1.106      case 0xdb: /* FPU 0xdb */
   1.107 @@ -2697,6 +2743,35 @@ x86_emulate(
   1.108          asm volatile ( "fnstsw %0" : "=m" (dst.val) );
   1.109          break;
   1.110  
   1.111 +    case 0xde: /* FPU 0xde */
   1.112 +        fail_if(ops->load_fpu_ctxt == NULL);
   1.113 +        ops->load_fpu_ctxt(ctxt);
   1.114 +        switch ( modrm )
   1.115 +        {
   1.116 +        case 0xd9: __emulate_fpu_insn("fcompp"); break;
   1.117 +        case 0xf8: __emulate_fpu_insn("fdivp %%st(0),%%st(0)"); break;
   1.118 +        case 0xf9: __emulate_fpu_insn("fdivp %%st(1),%%st(0)"); break;
   1.119 +        case 0xfa: __emulate_fpu_insn("fdivp %%st(2),%%st(0)"); break;
   1.120 +        case 0xfb: __emulate_fpu_insn("fdivp %%st(3),%%st(0)"); break;
   1.121 +        case 0xfc: __emulate_fpu_insn("fdivp %%st(4),%%st(0)"); break;
   1.122 +        case 0xfd: __emulate_fpu_insn("fdivp %%st(5),%%st(0)"); break;
   1.123 +        case 0xfe: __emulate_fpu_insn("fdivp %%st(6),%%st(0)"); break;
   1.124 +        case 0xff: __emulate_fpu_insn("fdivp %%st(7),%%st(0)"); break;
   1.125 +        default: goto cannot_emulate;
   1.126 +        }
   1.127 +        break;
   1.128 +
   1.129 +    case 0xdf: /* FPU 0xdf */
   1.130 +        fail_if(ops->load_fpu_ctxt == NULL);
   1.131 +        ops->load_fpu_ctxt(ctxt);
   1.132 +        fail_if(modrm != 0xe0);
   1.133 +        /* fnstsw %ax */
   1.134 +        dst.bytes = 2;
   1.135 +        dst.type = OP_REG;
   1.136 +        dst.reg = (unsigned long *)&_regs.eax;
   1.137 +        asm volatile ( "fnstsw %0" : "=m" (dst.val) );
   1.138 +        break;
   1.139 +
   1.140      case 0xe0 ... 0xe2: /* loop{,z,nz} */ {
   1.141          int rel = insn_fetch_type(int8_t);
   1.142          int do_jmp = !(_regs.eflags & EFLG_ZF); /* loopnz */