From: Julian Seward Date: Sun, 27 Mar 2005 02:22:32 +0000 (+0000) Subject: Implement ldmxcsr/stmxcsr. X-Git-Tag: svn/VALGRIND_3_0_1^2~232 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c2d604fd344093d672b822a231d9bba1cd5cb293;p=thirdparty%2Fvalgrind.git Implement ldmxcsr/stmxcsr. git-svn-id: svn://svn.valgrind.org/vex/trunk@1102 --- diff --git a/VEX/priv/guest-amd64/gdefs.h b/VEX/priv/guest-amd64/gdefs.h index 3e21bc1f8d..8e0006e2a9 100644 --- a/VEX/priv/guest-amd64/gdefs.h +++ b/VEX/priv/guest-amd64/gdefs.h @@ -101,9 +101,9 @@ extern ULong amd64g_calculate_condition ( //extern ULong amd64g_create_fpucw ( ULong fpround ); -//extern ULong amd64g_check_ldmxcsr ( ULong mxcsr ); +extern ULong amd64g_check_ldmxcsr ( ULong mxcsr ); -//extern ULong amd64g_create_mxcsr ( ULong sseround ); +extern ULong amd64g_create_mxcsr ( ULong sseround ); /* Translate a guest virtual_addr into a guest linear address by consulting the supplied LDT/GDT structures. Their representation diff --git a/VEX/priv/guest-amd64/ghelpers.c b/VEX/priv/guest-amd64/ghelpers.c index 3cb23604f0..e306565ca9 100644 --- a/VEX/priv/guest-amd64/ghelpers.c +++ b/VEX/priv/guest-amd64/ghelpers.c @@ -1202,6 +1202,52 @@ void amd64g_storeF80le ( ULong addrU, ULong f64 ) } +/* CALLED FROM GENERATED CODE */ +/* CLEAN HELPER */ +/* mxcsr[15:0] contains a SSE native format MXCSR value. + Extract from it the required SSEROUND value and any resulting + emulation warning, and return (warn << 32) | sseround value. +*/ +ULong amd64g_check_ldmxcsr ( ULong mxcsr ) +{ + /* Decide on a rounding mode. mxcsr[14:13] holds it. */ + /* NOTE, encoded exactly as per enum IRRoundingMode. */ + ULong rmode = (mxcsr >> 13) & 3; + + /* Detect any required emulation warnings. */ + VexEmWarn ew = EmWarn_NONE; + + if ((mxcsr & 0x1F80) != 0x1F80) { + /* unmasked exceptions! */ + ew = EmWarn_X86_sseExns; + } + else + if (mxcsr & (1<<15)) { + /* FZ is set */ + ew = EmWarn_X86_fz; + } + else + if (mxcsr & (1<<6)) { + /* DAZ is set */ + ew = EmWarn_X86_daz; + } + + return (((ULong)ew) << 32) | ((ULong)rmode); +} + + +/* CALLED FROM GENERATED CODE */ +/* CLEAN HELPER */ +/* Given sseround as an IRRoundingMode value, create a suitable SSE + native format MXCSR value. */ +ULong amd64g_create_mxcsr ( ULong sseround ) +{ + sseround &= 3; + return 0x1F80 | (sseround << 13); +} + + + /*---------------------------------------------------------------*/ /*--- Misc integer helpers, including rotates and CPUID. ---*/ /*---------------------------------------------------------------*/ @@ -1417,7 +1463,7 @@ VexGuestLayout /* Describe any sections to be regarded by Memcheck as 'always-defined'. */ - .n_alwaysDefd = 11, + .n_alwaysDefd = 12, /* flags thunk: OP and NDEP are always defd, whereas DEP1 and DEP2 have to be tracked. See detailed comment in @@ -1441,7 +1487,8 @@ VexGuestLayout // /* */ ALWAYSDEFD(guest_SS), // /* */ ALWAYSDEFD(guest_LDT), // /* */ ALWAYSDEFD(guest_GDT), - /* 6 */ ALWAYSDEFD(guest_EMWARN) + /* 10 */ ALWAYSDEFD(guest_EMWARN), + /* 11 */ ALWAYSDEFD(guest_SSEROUND) } }; diff --git a/VEX/priv/guest-amd64/toIR.c b/VEX/priv/guest-amd64/toIR.c index bb0b22f0bf..f325b65a0e 100644 --- a/VEX/priv/guest-amd64/toIR.c +++ b/VEX/priv/guest-amd64/toIR.c @@ -361,7 +361,7 @@ static void unimplemented ( HChar* str ) #define OFFB_XMM14 offsetof(VexGuestAMD64State,guest_XMM14) #define OFFB_XMM15 offsetof(VexGuestAMD64State,guest_XMM15) -//.. #define OFFB_EMWARN offsetof(VexGuestX86State,guest_EMWARN) +#define OFFB_EMWARN offsetof(VexGuestAMD64State,guest_EMWARN) /*------------------------------------------------------------*/ @@ -4088,20 +4088,21 @@ ULong dis_imul_I_E_G ( Prefix pfx, } -//.. /*------------------------------------------------------------*/ -//.. /*--- ---*/ -//.. /*--- x87 FLOATING POINT INSTRUCTIONS ---*/ -//.. /*--- ---*/ -//.. /*------------------------------------------------------------*/ -//.. -//.. /* --- Helper functions for dealing with the register stack. --- */ -//.. -//.. /* --- Set the emulation-warning pseudo-register. --- */ -//.. -//.. static void put_emwarn ( IRExpr* e /* :: Ity_I32 */ ) -//.. { -//.. stmt( IRStmt_Put( OFFB_EMWARN, e ) ); -//.. } +/*------------------------------------------------------------*/ +/*--- ---*/ +/*--- x87 FLOATING POINT INSTRUCTIONS ---*/ +/*--- ---*/ +/*------------------------------------------------------------*/ + +/* --- Helper functions for dealing with the register stack. --- */ + +/* --- Set the emulation-warning pseudo-register. --- */ + +static void put_emwarn ( IRExpr* e /* :: Ity_I32 */ ) +{ + vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I32); + stmt( IRStmt_Put( OFFB_EMWARN, e ) ); +} /* --- Produce an IRExpr* denoting a 64-bit QNaN. --- */ @@ -7710,12 +7711,13 @@ static IRExpr* /* :: Ity_I32 */ get_sse_roundingmode ( void ) mkU64(3) )); } -//.. static void put_sse_roundingmode ( IRExpr* sseround ) -//.. { -//.. vassert(typeOfIRExpr(irbb->tyenv, sseround) == Ity_I32); -//.. stmt( IRStmt_Put( OFFB_SSEROUND, sseround ) ); -//.. } -//.. +static void put_sse_roundingmode ( IRExpr* sseround ) +{ + vassert(typeOfIRExpr(irbb->tyenv, sseround) == Ity_I32); + stmt( IRStmt_Put( OFFB_SSEROUND, + unop(Iop_32Uto64,sseround) ) ); +} + //.. /* Break a 128-bit value up into four 32-bit ints. */ //.. //.. static void breakup128to32s ( IRTemp t128, @@ -8384,53 +8386,55 @@ DisResult disInstr ( /*IN*/ Bool resteerOK, goto decode_success; } -//.. /* 0F AE /2 = LDMXCSR m32 -- load %mxcsr */ -//.. if (insn[0] == 0x0F && insn[1] == 0xAE -//.. && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 2) { -//.. -//.. IRTemp t64 = newTemp(Ity_I64); -//.. IRTemp ew = newTemp(Ity_I32); -//.. -//.. modrm = getUChar(delta+2); -//.. vassert(!epartIsReg(modrm)); -//.. vassert(sz == 4); -//.. -//.. addr = disAMode ( &alen, sorb, delta+2, dis_buf ); -//.. delta += 2+alen; -//.. DIP("ldmxcsr %s\n", dis_buf); -//.. -//.. /* The only thing we observe in %mxcsr is the rounding mode. -//.. Therefore, pass the 32-bit value (SSE native-format control -//.. word) to a clean helper, getting back a 64-bit value, the -//.. lower half of which is the SSEROUND value to store, and the -//.. upper half of which is the emulation-warning token which may -//.. be generated. -//.. */ -//.. /* ULong x86h_check_ldmxcsr ( UInt ); */ -//.. assign( t64, mkIRExprCCall( -//.. Ity_I64, 0/*regparms*/, -//.. "x86g_check_ldmxcsr", -//.. &x86g_check_ldmxcsr, -//.. mkIRExprVec_1( loadLE(Ity_I32, mkexpr(addr)) ) -//.. ) -//.. ); -//.. -//.. put_sse_roundingmode( unop(Iop_64to32, mkexpr(t64)) ); -//.. assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) ); -//.. put_emwarn( mkexpr(ew) ); -//.. /* Finally, if an emulation warning was reported, side-exit to -//.. the next insn, reporting the warning, so that Valgrind's -//.. dispatcher sees the warning. */ -//.. stmt( -//.. IRStmt_Exit( -//.. binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)), -//.. Ijk_EmWarn, -//.. IRConst_U32( ((Addr32)guest_eip_bbstart)+delta) -//.. ) -//.. ); -//.. goto decode_success; -//.. } -//.. + /* 0F AE /2 = LDMXCSR m32 -- load %mxcsr */ + if (insn[0] == 0x0F && insn[1] == 0xAE + && haveNo66noF2noF3(pfx) + && !epartIsReg(insn[2]) && gregLO3ofRM(insn[2]) == 2) { + + IRTemp t64 = newTemp(Ity_I64); + IRTemp ew = newTemp(Ity_I32); + + vassert(sz == 4); + addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 ); + delta += 2+alen; + DIP("ldmxcsr %s\n", dis_buf); + + /* The only thing we observe in %mxcsr is the rounding mode. + Therefore, pass the 32-bit value (SSE native-format control + word) to a clean helper, getting back a 64-bit value, the + lower half of which is the SSEROUND value to store, and the + upper half of which is the emulation-warning token which may + be generated. + */ + /* ULong amd64h_check_ldmxcsr ( ULong ); */ + assign( t64, mkIRExprCCall( + Ity_I64, 0/*regparms*/, + "amd64g_check_ldmxcsr", + &amd64g_check_ldmxcsr, + mkIRExprVec_1( + unop(Iop_32Uto64, + loadLE(Ity_I32, mkexpr(addr)) + ) + ) + ) + ); + + put_sse_roundingmode( unop(Iop_64to32, mkexpr(t64)) ); + assign( ew, unop(Iop_64HIto32, mkexpr(t64) ) ); + put_emwarn( mkexpr(ew) ); + /* Finally, if an emulation warning was reported, side-exit to + the next insn, reporting the warning, so that Valgrind's + dispatcher sees the warning. */ + stmt( + IRStmt_Exit( + binop(Iop_CmpNE64, unop(Iop_32Uto64,mkexpr(ew)), mkU64(0)), + Ijk_EmWarn, + IRConst_U64(guest_rip_bbstart+delta) + ) + ); + goto decode_success; + } + //.. /* 0F 5F = MAXPS -- max 32Fx4 from R/M to R */ //.. if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5F) { //.. delta = dis_SSE_E_to_G_all( sorb, delta+2, "maxps", Iop_Max32Fx4 ); @@ -8862,7 +8866,7 @@ DisResult disInstr ( /*IN*/ Bool resteerOK, /* 0F 18 /2 = PREFETCH1 */ /* 0F 18 /3 = PREFETCH2 */ if (insn[0] == 0x0F && insn[1] == 0x18 - && !haveF2orF3(pfx) + && haveNo66noF2noF3(pfx) && !epartIsReg(insn[2]) && gregLO3ofRM(insn[2]) >= 0 && gregLO3ofRM(insn[2]) <= 3) { HChar* hintstr = "??"; @@ -9040,32 +9044,34 @@ DisResult disInstr ( /*IN*/ Bool resteerOK, //.. "sqrtss", Iop_Sqrt32F0x4 ); //.. goto decode_success; //.. } -//.. -//.. /* 0F AE /3 = STMXCSR m32 -- store %mxcsr */ -//.. if (insn[0] == 0x0F && insn[1] == 0xAE -//.. && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 3) { -//.. modrm = getUChar(delta+2); -//.. vassert(sz == 4); -//.. vassert(!epartIsReg(modrm)); -//.. -//.. addr = disAMode ( &alen, sorb, delta+2, dis_buf ); -//.. delta += 2+alen; -//.. -//.. /* Fake up a native SSE mxcsr word. The only thing it depends -//.. on is SSEROUND[1:0], so call a clean helper to cook it up. -//.. */ -//.. /* UInt x86h_create_mxcsr ( UInt sseround ) */ -//.. DIP("stmxcsr %s\n", dis_buf); -//.. storeLE( mkexpr(addr), -//.. mkIRExprCCall( -//.. Ity_I32, 0/*regp*/, -//.. "x86g_create_mxcsr", &x86g_create_mxcsr, -//.. mkIRExprVec_1( get_sse_roundingmode() ) -//.. ) -//.. ); -//.. goto decode_success; -//.. } -//.. + + /* 0F AE /3 = STMXCSR m32 -- store %mxcsr */ + if (insn[0] == 0x0F && insn[1] == 0xAE + && haveNo66noF2noF3(pfx) + && !epartIsReg(insn[2]) && gregLO3ofRM(insn[2]) == 3) { + + vassert(sz == 4); + addr = disAMode ( &alen, pfx, delta+2, dis_buf, 0 ); + delta += 2+alen; + + /* Fake up a native SSE mxcsr word. The only thing it depends + on is SSEROUND[1:0], so call a clean helper to cook it up. + */ + /* ULong amd64h_create_mxcsr ( ULong sseround ) */ + DIP("stmxcsr %s\n", dis_buf); + storeLE( + mkexpr(addr), + unop(Iop_64to32, + mkIRExprCCall( + Ity_I64, 0/*regp*/, + "amd64g_create_mxcsr", &amd64g_create_mxcsr, + mkIRExprVec_1( unop(Iop_32Uto64,get_sse_roundingmode()) ) + ) + ) + ); + goto decode_success; + } + //.. /* 0F 5C = SUBPS -- sub 32Fx4 from R/M to R */ //.. if (sz == 4 && insn[0] == 0x0F && insn[1] == 0x5C) { //.. delta = dis_SSE_E_to_G_all( sorb, delta+2, "subps", Iop_Sub32Fx4 );