From: Julian Seward Date: Fri, 26 Nov 2004 17:57:40 +0000 (+0000) Subject: x86 guest: implement fsave/frstor instructions X-Git-Tag: svn/VALGRIND_3_0_1^2~743 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bf229ea06747523099c0aaa9bf6702193b9a8c92;p=thirdparty%2Fvalgrind.git x86 guest: implement fsave/frstor instructions git-svn-id: svn://svn.valgrind.org/vex/trunk@591 --- diff --git a/VEX/priv/guest-x86/gdefs.h b/VEX/priv/guest-x86/gdefs.h index 77099c1cf8..2cca5032a2 100644 --- a/VEX/priv/guest-x86/gdefs.h +++ b/VEX/priv/guest-x86/gdefs.h @@ -160,6 +160,10 @@ extern void x86g_storeF80le ( UInt, ULong ); extern void x86g_dirtyhelper_CPUID ( VexGuestX86State* ); +extern void x86g_dirtyhelper_FSAVE ( VexGuestX86State*, HWord ); + +extern void x86g_dirtyhelper_FRSTOR ( VexGuestX86State*, HWord ); + /*---------------------------------------------------------*/ /*--- Condition code stuff ---*/ diff --git a/VEX/priv/guest-x86/ghelpers.c b/VEX/priv/guest-x86/ghelpers.c index af352b75aa..54a4259581 100644 --- a/VEX/priv/guest-x86/ghelpers.c +++ b/VEX/priv/guest-x86/ghelpers.c @@ -1543,7 +1543,7 @@ void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state ) /*----------------------------------------------*/ -/*--- Misc integer helpers ---*/ +/*--- Misc integer/fp helpers ---*/ /*----------------------------------------------*/ /* CALLED FROM GENERATED CODE: CLEAN HELPER */ @@ -1620,6 +1620,20 @@ void x86g_dirtyhelper_CPUID ( VexGuestX86State* st ) } +/* CALLED FROM GENERATED CODE */ +/* DIRTY HELPER (reads guest state, writes guest mem) */ +void x86g_dirtyhelper_FSAVE ( VexGuestX86State* gst, HWord addr ) +{ + LibVEX_GuestX86_get_x87( gst, (UChar*)addr ); +} + +/* CALLED FROM GENERATED CODE */ +/* DIRTY HELPER (writes guest state, reads guest mem) */ +void x86g_dirtyhelper_FRSTOR ( VexGuestX86State* gst, HWord addr ) +{ + LibVEX_GuestX86_put_x87( (UChar*)addr, gst ); +} + /*----------------------------------------------*/ /*--- Helpers for MMX ---*/ diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index ff33371692..66646dd713 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -4171,7 +4171,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) } case 7: { /* FSTP extended-real */ - /* Uses dirty helper: void storeF80le ( UInt, ULong ) */ + /* Uses dirty helper: void x86g_storeF80le ( UInt, ULong ) */ IRExpr** args = mkIRExprVec_2( mkexpr(addr), unop(Iop_ReinterpF64asI64, get_ST(0)) ); @@ -4366,6 +4366,92 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta ) fp_pop(); break; + case 4: { /* FRSTOR m108 */ + /* Uses dirty helper: x86g_do_FRSTOR ( VexGuestX86State*, UInt ) */ + IRDirty* d = unsafeIRDirty_0_N ( + 0/*regparms*/, + "x86g_dirtyhelper_FRSTOR", + &x86g_dirtyhelper_FRSTOR, + mkIRExprVec_1( mkexpr(addr) ) + ); + d->needsBBP = True; + /* declare we're reading memory */ + d->mFx = Ifx_Read; + d->mAddr = mkexpr(addr); + d->mSize = 108; + + /* declare we're writing guest state */ + d->nFxState = 5; + + d->fxState[0].fx = Ifx_Write; + d->fxState[0].offset = offsetof(VexGuestX86State,guest_FTOP); + d->fxState[0].size = sizeof(UInt); + + d->fxState[1].fx = Ifx_Write; + d->fxState[1].offset = offsetof(VexGuestX86State,guest_FPREG); + d->fxState[1].size = 8 * sizeof(ULong); + + d->fxState[2].fx = Ifx_Write; + d->fxState[2].offset = offsetof(VexGuestX86State,guest_FPTAG); + d->fxState[2].size = 8 * sizeof(UChar); + + d->fxState[3].fx = Ifx_Write; + d->fxState[3].offset = offsetof(VexGuestX86State,guest_FPUCW); + d->fxState[3].size = sizeof(UInt); + + d->fxState[4].fx = Ifx_Write; + d->fxState[4].offset = offsetof(VexGuestX86State,guest_FC3210); + d->fxState[4].size = sizeof(UInt); + + stmt( IRStmt_Dirty(d) ); + + DIP("frstor %s", dis_buf); + break; + } + + case 6: { /* FNSAVE m108 */ + /* Uses dirty helper: x86g_do_FSAVE ( VexGuestX86State*, UInt ) */ + IRDirty* d = unsafeIRDirty_0_N ( + 0/*regparms*/, + "x86g_dirtyhelper_FSAVE", + &x86g_dirtyhelper_FSAVE, + mkIRExprVec_1( mkexpr(addr) ) + ); + d->needsBBP = True; + /* declare we're writing memory */ + d->mFx = Ifx_Write; + d->mAddr = mkexpr(addr); + d->mSize = 108; + + /* declare we're reading guest state */ + d->nFxState = 5; + + d->fxState[0].fx = Ifx_Read; + d->fxState[0].offset = offsetof(VexGuestX86State,guest_FTOP); + d->fxState[0].size = sizeof(UInt); + + d->fxState[1].fx = Ifx_Read; + d->fxState[1].offset = offsetof(VexGuestX86State,guest_FPREG); + d->fxState[1].size = 8 * sizeof(ULong); + + d->fxState[2].fx = Ifx_Read; + d->fxState[2].offset = offsetof(VexGuestX86State,guest_FPTAG); + d->fxState[2].size = 8 * sizeof(UChar); + + d->fxState[3].fx = Ifx_Read; + d->fxState[3].offset = offsetof(VexGuestX86State,guest_FPUCW); + d->fxState[3].size = sizeof(UInt); + + d->fxState[4].fx = Ifx_Read; + d->fxState[4].offset = offsetof(VexGuestX86State,guest_FC3210); + d->fxState[4].size = sizeof(UInt); + + stmt( IRStmt_Dirty(d) ); + + DIP("fnsave %s", dis_buf); + break; + } + default: vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm)); vex_printf("first_opcode == 0xDD\n"); diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 9feb773584..aa847a3f00 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -537,7 +537,7 @@ inline static Bool isAtom ( IRExpr* e ) { evaluation. */ -#define VEX_N_FXSTATE 4 /* enough for CPUID on x86 */ +#define VEX_N_FXSTATE 5 /* enough for FSAVE/FRSTOR on x86 */ typedef enum { diff --git a/VEX/test/frstor.c b/VEX/test/frstor.c new file mode 100644 index 0000000000..437f094d02 --- /dev/null +++ b/VEX/test/frstor.c @@ -0,0 +1,35 @@ + +#include +#include + +void do_fsave ( void* p ) +{ + asm("movl 8(%esp), %eax ; fsave (%eax)"); +} + +void do_frstor ( void* p ) +{ + asm("movl 8(%esp), %eax ; frstor (%eax)"); +} + +int main ( void ) +{ + int i; + unsigned short* buf = malloc(54*sizeof(int)); + for (i = 0; i < 54; i++) + buf[i] = i; + buf[0] = 0x037f; + + for (i = 0; i < 8; i++) + *(long double *)(&buf[14+5 *i]) = 0.1234 * i; + + do_frstor(buf); + do_fsave(buf); + for (i = 0; i < 54; i++) { + printf("%04x ", buf[i]); + if (i > 0 && ((i % 12) == 11)) + printf("\n"); + } + printf("\n"); + return 0; +} diff --git a/VEX/test/fsave.c b/VEX/test/fsave.c new file mode 100644 index 0000000000..2e0ba1512e --- /dev/null +++ b/VEX/test/fsave.c @@ -0,0 +1,22 @@ + +#include +#include + +void do_fsave ( void* p ) +{ + asm("fldpi ; fld1; fldln2 ; movl 8(%esp), %eax ; fsave (%eax)"); +} + +int main ( void ) +{ + int i; + unsigned int* buf = malloc(27*sizeof(int)); + do_fsave(buf); + for (i = 0; i < 27; i++) { + printf("%08x ", buf[i]); + if (i > 0 && ((i % 6) == 5)) + printf("\n"); + } + printf("\n"); + return 0; +}