From b2783252ead3c6e1808a712375648a61a93887ee Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Tue, 13 May 2008 09:28:37 +0000 Subject: [PATCH] Merge r1835 (support fxrstor on x86). Fixes #126389. git-svn-id: svn://svn.valgrind.org/vex/branches/VEX_3_3_BRANCH@1845 --- VEX/priv/guest-x86/gdefs.h | 3 ++ VEX/priv/guest-x86/ghelpers.c | 80 +++++++++++++++++++++++++++++++++++ VEX/priv/guest-x86/toIR.c | 70 ++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+) diff --git a/VEX/priv/guest-x86/gdefs.h b/VEX/priv/guest-x86/gdefs.h index 3ac2ff3732..ea6ac09442 100644 --- a/VEX/priv/guest-x86/gdefs.h +++ b/VEX/priv/guest-x86/gdefs.h @@ -163,6 +163,9 @@ extern UInt x86g_dirtyhelper_IN ( UInt portno, UInt sz/*1,2 or 4*/ ); extern void x86g_dirtyhelper_OUT ( UInt portno, UInt data, UInt sz/*1,2 or 4*/ ); +extern VexEmWarn + x86g_dirtyhelper_FXRSTOR ( VexGuestX86State*, HWord ); + extern VexEmWarn x86g_dirtyhelper_FRSTOR ( VexGuestX86State*, HWord ); diff --git a/VEX/priv/guest-x86/ghelpers.c b/VEX/priv/guest-x86/ghelpers.c index 2c900087ac..949a10e896 100644 --- a/VEX/priv/guest-x86/ghelpers.c +++ b/VEX/priv/guest-x86/ghelpers.c @@ -1726,6 +1726,86 @@ void x86g_dirtyhelper_FXSAVE ( VexGuestX86State* gst, HWord addr ) } +/* CALLED FROM GENERATED CODE */ +/* DIRTY HELPER (writes guest state, reads guest mem) */ +VexEmWarn x86g_dirtyhelper_FXRSTOR ( VexGuestX86State* gst, HWord addr ) +{ + Fpu_State tmp; + VexEmWarn warnX87 = EmWarn_NONE; + VexEmWarn warnXMM = EmWarn_NONE; + UShort* addrS = (UShort*)addr; + UChar* addrC = (UChar*)addr; + U128* xmm = (U128*)(addr + 160); + UShort fp_tags; + Int r, stno, i; + + /* Restore %xmm0 .. %xmm7. If the host is big-endian, these need + to be byte-swapped. */ + vassert(host_is_little_endian()); + +# define COPY_U128(_dst,_src) \ + do { _dst[0] = _src[0]; _dst[1] = _src[1]; \ + _dst[2] = _src[2]; _dst[3] = _src[3]; } \ + while (0) + + COPY_U128( gst->guest_XMM0, xmm[0] ); + COPY_U128( gst->guest_XMM1, xmm[1] ); + COPY_U128( gst->guest_XMM2, xmm[2] ); + COPY_U128( gst->guest_XMM3, xmm[3] ); + COPY_U128( gst->guest_XMM4, xmm[4] ); + COPY_U128( gst->guest_XMM5, xmm[5] ); + COPY_U128( gst->guest_XMM6, xmm[6] ); + COPY_U128( gst->guest_XMM7, xmm[7] ); + +# undef COPY_U128 + + /* Copy the x87 registers out of the image, into a temporary + Fpu_State struct. */ + for (i = 0; i < 14; i++) tmp.env[i] = 0; + for (i = 0; i < 80; i++) tmp.reg[i] = 0; + /* fill in tmp.reg[0..7] */ + for (stno = 0; stno < 8; stno++) { + UShort* dstS = (UShort*)(&tmp.reg[10*stno]); + UShort* srcS = (UShort*)(&addrS[16 + 8*stno]); + dstS[0] = srcS[0]; + dstS[1] = srcS[1]; + dstS[2] = srcS[2]; + dstS[3] = srcS[3]; + dstS[4] = srcS[4]; + } + /* fill in tmp.env[0..13] */ + tmp.env[FP_ENV_CTRL] = addrS[0]; /* FCW: fpu control word */ + tmp.env[FP_ENV_STAT] = addrS[1]; /* FCW: fpu status word */ + + fp_tags = 0; + for (r = 0; r < 8; r++) { + if (addrC[4] & (1<> 32); + + gst->guest_SSEROUND = (UInt)w64; + } + + /* Prefer an X87 emwarn over an XMM one, if both exist. */ + if (warnX87 != EmWarn_NONE) + return warnX87; + else + return warnXMM; +} + + /* CALLED FROM GENERATED CODE */ /* DIRTY HELPER (reads guest state, writes guest mem) */ void x86g_dirtyhelper_FSAVE ( VexGuestX86State* gst, HWord addr ) diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index 041d3247f3..f34a0b9a72 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -7813,6 +7813,76 @@ DisResult disInstr_X86_WRK ( goto decode_success; } + /* 0F AE /1 = FXRSTOR m512 -- read x87 and SSE state from memory */ + if (sz == 4 && insn[0] == 0x0F && insn[1] == 0xAE + && !epartIsReg(insn[2]) && gregOfRM(insn[2]) == 1) { + IRDirty* d; + modrm = getIByte(delta+2); + vassert(sz == 4); + vassert(!epartIsReg(modrm)); + + addr = disAMode ( &alen, sorb, delta+2, dis_buf ); + delta += 2+alen; + + DIP("fxrstor %s\n", dis_buf); + + /* Uses dirty helper: + void x86g_do_FXRSTOR ( VexGuestX86State*, UInt ) */ + d = unsafeIRDirty_0_N ( + 0/*regparms*/, + "x86g_dirtyhelper_FXRSTOR", + &x86g_dirtyhelper_FXRSTOR, + mkIRExprVec_1( mkexpr(addr) ) + ); + d->needsBBP = True; + + /* declare we're reading memory */ + d->mFx = Ifx_Read; + d->mAddr = mkexpr(addr); + d->mSize = 512; + + /* declare we're writing guest state */ + d->nFxState = 7; + + d->fxState[0].fx = Ifx_Write; + d->fxState[0].offset = OFFB_FTOP; + d->fxState[0].size = sizeof(UInt); + + d->fxState[1].fx = Ifx_Write; + d->fxState[1].offset = OFFB_FPREGS; + d->fxState[1].size = 8 * sizeof(ULong); + + d->fxState[2].fx = Ifx_Write; + d->fxState[2].offset = OFFB_FPTAGS; + d->fxState[2].size = 8 * sizeof(UChar); + + d->fxState[3].fx = Ifx_Write; + d->fxState[3].offset = OFFB_FPROUND; + d->fxState[3].size = sizeof(UInt); + + d->fxState[4].fx = Ifx_Write; + d->fxState[4].offset = OFFB_FC3210; + d->fxState[4].size = sizeof(UInt); + + d->fxState[5].fx = Ifx_Write; + d->fxState[5].offset = OFFB_XMM0; + d->fxState[5].size = 8 * sizeof(U128); + + d->fxState[6].fx = Ifx_Write; + d->fxState[6].offset = OFFB_SSEROUND; + d->fxState[6].size = sizeof(UInt); + + /* Be paranoid ... this assertion tries to ensure the 8 %xmm + images are packed back-to-back. If not, the value of + d->fxState[5].size is wrong. */ + vassert(16 == sizeof(U128)); + vassert(OFFB_XMM7 == (OFFB_XMM0 + 7 * 16)); + + stmt( IRStmt_Dirty(d) ); + + goto decode_success; + } + /* ------ SSE decoder main ------ */ /* Skip parts of the decoder which don't apply given the stated -- 2.47.2