[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86_emulate: Emulate certain FPU instructions by building the opcode
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1208360567 -3600 # Node ID a38a41de0800cefca755ffb600d6d5e96f084697 # Parent defbab4dba1a40ce08ed5b9331cfaf7a4422853e x86_emulate: Emulate certain FPU instructions by building the opcode on the stack. This allows us to add emulation for a number of extra FPU opcodes without inflating the executable code size. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/arch/x86/x86_emulate/x86_emulate.c | 89 ++++++++++++++++++++++----------- 1 files changed, 60 insertions(+), 29 deletions(-) diff -r defbab4dba1a -r a38a41de0800 xen/arch/x86/x86_emulate/x86_emulate.c --- a/xen/arch/x86/x86_emulate/x86_emulate.c Wed Apr 16 16:10:41 2008 +0100 +++ b/xen/arch/x86/x86_emulate/x86_emulate.c Wed Apr 16 16:42:47 2008 +0100 @@ -558,7 +558,7 @@ static void fpu_handle_exception(void *_ regs->eip += fic->insn_bytes; } -#define __emulate_fpu_insn(_op) \ +#define emulate_fpu_insn(_op) \ do{ struct fpu_insn_ctxt fic = { 0 }; \ fail_if(ops->get_fpu == NULL); \ ops->get_fpu(fpu_handle_exception, &fic, ctxt); \ @@ -571,7 +571,7 @@ do{ struct fpu_insn_ctxt fic = { 0 }; generate_exception_if(fic.exn_raised, EXC_MF, -1); \ } while (0) -#define __emulate_fpu_insn_memdst(_op, _arg) \ +#define emulate_fpu_insn_memdst(_op, _arg) \ do{ struct fpu_insn_ctxt fic = { 0 }; \ fail_if(ops->get_fpu == NULL); \ ops->get_fpu(fpu_handle_exception, &fic, ctxt); \ @@ -583,6 +583,16 @@ do{ struct fpu_insn_ctxt fic = { 0 }; : : "memory" ); \ ops->put_fpu(ctxt); \ generate_exception_if(fic.exn_raised, EXC_MF, -1); \ +} while (0) + +#define emulate_fpu_insn_stub(_bytes...) \ +do{ uint8_t stub[] = { _bytes, 0xc3 }; \ + struct fpu_insn_ctxt fic = { .insn_bytes = sizeof(stub)-1 }; \ + fail_if(ops->get_fpu == NULL); \ + ops->get_fpu(fpu_handle_exception, &fic, ctxt); \ + (*(void(*)(void))stub)(); \ + ops->put_fpu(ctxt); \ + generate_exception_if(fic.exn_raised, EXC_MF, -1); \ } while (0) static unsigned long __get_rep_prefix( @@ -2438,7 +2448,7 @@ x86_emulate( } case 0x9b: /* wait/fwait */ - __emulate_fpu_insn("fwait"); + emulate_fpu_insn("fwait"); break; case 0x9c: /* pushf */ @@ -2760,32 +2770,52 @@ x86_emulate( case 0xd9: /* FPU 0xd9 */ switch ( modrm ) { - case 0xc0: __emulate_fpu_insn(".byte 0xd9,0xc0"); break; /* fld %st0 */ - case 0xc1: __emulate_fpu_insn(".byte 0xd9,0xc1"); break; /* fld %st1 */ - case 0xc2: __emulate_fpu_insn(".byte 0xd9,0xc2"); break; /* fld %st2 */ - case 0xc3: __emulate_fpu_insn(".byte 0xd9,0xc3"); break; /* fld %st3 */ - case 0xc4: __emulate_fpu_insn(".byte 0xd9,0xc4"); break; /* fld %st4 */ - case 0xc5: __emulate_fpu_insn(".byte 0xd9,0xc5"); break; /* fld %st5 */ - case 0xc6: __emulate_fpu_insn(".byte 0xd9,0xc6"); break; /* fld %st6 */ - case 0xc7: __emulate_fpu_insn(".byte 0xd9,0xc7"); break; /* fld %st7 */ - case 0xe0: __emulate_fpu_insn(".byte 0xd9,0xe0"); break; /* fchs */ - case 0xe1: __emulate_fpu_insn(".byte 0xd9,0xe1"); break; /* fabs */ - case 0xe8: __emulate_fpu_insn(".byte 0xd9,0xe8"); break; /* fld1 */ - case 0xee: __emulate_fpu_insn(".byte 0xd9,0xee"); break; /* fldz */ + case 0xc0 ... 0xc7: /* fld %stN */ + case 0xc8 ... 0xcf: /* fxch %stN */ + case 0xd0: /* fnop */ + case 0xe0: /* fchs */ + case 0xe1: /* fabs */ + case 0xe4: /* ftst */ + case 0xe5: /* fxam */ + case 0xe8: /* fld1 */ + case 0xe9: /* fldl2t */ + case 0xea: /* fldl2e */ + case 0xeb: /* fldpi */ + case 0xec: /* fldlg2 */ + case 0xed: /* fldln2 */ + case 0xee: /* fldz */ + case 0xf0: /* f2xm1 */ + case 0xf1: /* fyl2x */ + case 0xf2: /* fptan */ + case 0xf3: /* fpatan */ + case 0xf4: /* fxtract */ + case 0xf5: /* fprem1 */ + case 0xf6: /* fdecstp */ + case 0xf7: /* fincstp */ + case 0xf8: /* fprem */ + case 0xf9: /* fyl2xp1 */ + case 0xfa: /* fsqrt */ + case 0xfb: /* fsincos */ + case 0xfc: /* frndint */ + case 0xfd: /* fscale */ + case 0xfe: /* fsin */ + case 0xff: /* fcos */ + emulate_fpu_insn_stub(0xd9, modrm); + break; default: fail_if((modrm_reg & 7) != 7); fail_if(modrm >= 0xc0); /* fnstcw m2byte */ ea.bytes = 2; dst = ea; - __emulate_fpu_insn_memdst("fnstcw", dst.val); + emulate_fpu_insn_memdst("fnstcw", dst.val); } break; case 0xdb: /* FPU 0xdb */ fail_if(modrm != 0xe3); /* fninit */ - __emulate_fpu_insn("fninit"); + emulate_fpu_insn("fninit"); break; case 0xdd: /* FPU 0xdd */ @@ -2794,22 +2824,23 @@ x86_emulate( /* fnstsw m2byte */ ea.bytes = 2; dst = ea; - __emulate_fpu_insn_memdst("fnstsw", dst.val); + emulate_fpu_insn_memdst("fnstsw", dst.val); break; case 0xde: /* FPU 0xde */ switch ( modrm ) { - case 0xd9: __emulate_fpu_insn(".byte 0xde,0xd9"); break; - case 0xf8: __emulate_fpu_insn(".byte 0xde,0xf8"); break; - case 0xf9: __emulate_fpu_insn(".byte 0xde,0xf9"); break; - case 0xfa: __emulate_fpu_insn(".byte 0xde,0xfa"); break; - case 0xfb: __emulate_fpu_insn(".byte 0xde,0xfb"); break; - case 0xfc: __emulate_fpu_insn(".byte 0xde,0xfc"); break; - case 0xfd: __emulate_fpu_insn(".byte 0xde,0xfd"); break; - case 0xfe: __emulate_fpu_insn(".byte 0xde,0xfe"); break; - case 0xff: __emulate_fpu_insn(".byte 0xde,0xff"); break; - default: goto cannot_emulate; + case 0xc0 ... 0xc7: /* faddp %stN */ + case 0xc8 ... 0xcf: /* fmulp %stN */ + case 0xd9: /* fcompp */ + case 0xe0 ... 0xe7: /* fsubrp %stN */ + case 0xe8 ... 0xef: /* fsubp %stN */ + case 0xf0 ... 0xf7: /* fdivrp %stN */ + case 0xf8 ... 0xff: /* fdivp %stN */ + emulate_fpu_insn_stub(0xde, modrm); + break; + default: + goto cannot_emulate; } break; @@ -2819,7 +2850,7 @@ x86_emulate( dst.bytes = 2; dst.type = OP_REG; dst.reg = (unsigned long *)&_regs.eax; - __emulate_fpu_insn_memdst("fnstsw", dst.val); + emulate_fpu_insn_memdst("fnstsw", dst.val); break; case 0xe0 ... 0xe2: /* loop{,z,nz} */ { _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |