diff -r f7df7b862186 -r 81aac6e3008d src/arch/x86/isa/insts/simd128/integer/save_and_restore_state/save_and_restore_state.py --- a/src/arch/x86/isa/insts/simd128/integer/save_and_restore_state/save_and_restore_state.py Thu Jun 13 11:45:18 2013 +0200 +++ b/src/arch/x86/isa/insts/simd128/integer/save_and_restore_state/save_and_restore_state.py Thu Jun 13 13:29:52 2013 +0200 @@ -1,15 +1,6 @@ -# Copyright (c) 2007 The Hewlett-Packard Development Company +# Copyright (c) 2013 Andreas Sandberg # All rights reserved. # -# The license below extends only to copyright in the software and shall -# not be construed as granting a license to any other intellectual -# property including but not limited to intellectual property relating -# to a hardware implementation of the functionality of the software -# licensed hereunder. You may use the software subject to the license -# terms below provided that you ensure that this notice is replicated -# unmodified and in its entirety in all distributions of the software, -# modified or unmodified, in source code or in binary form. -# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: redistributions of source code must retain the above copyright @@ -33,9 +24,189 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -# Authors: Gabe Black +# Authors: Andreas Sandberg + +# Register usage: +# t1, t2 == temporaries +# t7 == base address (RIP or SIB) + + +loadX87RegTemplate = ''' + ld t1, seg, t7rel, "DISPLACEMENT + 32 + 16 * %(idx)i", dataSize=8 + ld t2, seg, t7rel, "DISPLACEMENT + 32 + 16 * %(idx)i + 8", dataSize=2 + cvtint_fp80 st(%(idx)i), t1, t2 +''' + +storeX87RegTemplate = ''' + cvtfp80h_int t1, st(%(idx)i) + cvtfp80l_int t2, st(%(idx)i) + st t1, seg, t7rel, "DISPLACEMENT + 32 + 16 * %(idx)i", dataSize=8 + st t2, seg, t7rel, "DISPLACEMENT + 32 + 16 * %(idx)i + 8", dataSize=2 +''' + +loadXMMRegTemplate = ''' + ldfp "InstRegIndex(FLOATREG_XMM_LOW(%(idx)i))", seg, t7rel, "DISPLACEMENT + 160 + 16 * %(idx)i", dataSize=8 + ldfp "InstRegIndex(FLOATREG_XMM_HIGH(%(idx)i))", seg, t7rel, "DISPLACEMENT + 160 + 16 * %(idx)i + 8", dataSize=8 +''' + +storeXMMRegTemplate = ''' + stfp "InstRegIndex(FLOATREG_XMM_LOW(%(idx)i))", seg, t7rel, "DISPLACEMENT + 160 + 16 * %(idx)i", dataSize=8 + stfp "InstRegIndex(FLOATREG_XMM_HIGH(%(idx)i))", seg, t7rel, "DISPLACEMENT + 160 + 16 * %(idx)i + 8", dataSize=8 +''' + +loadAllDataRegs = \ + "".join([loadX87RegTemplate % { "idx" : i } for i in range(8)]) + \ + "".join([loadXMMRegTemplate % { "idx" : i } for i in range(16)]) + + +storeAllDataRegs = \ + "".join([storeX87RegTemplate % { "idx" : i } for i in range(8)]) + \ + "".join([storeXMMRegTemplate % { "idx" : i } for i in range(16)]) + microcode = ''' -# FXSAVE -# FXRESTORE + +def rom { + +extern fxsave32: + rdval t1, "InstRegIndex(MISCREG_FIOFF)" + st t1, seg, t7rel, "DISPLACEMENT + 8", dataSize=4 + + rdval t1, "InstRegIndex(MISCREG_FISEG)" + st t1, seg, t7rel, "DISPLACEMENT + 12", dataSize=2 + + rdval t1, "InstRegIndex(MISCREG_FOOFF)" + st t1, seg, t7rel, "DISPLACEMENT + 16 + 0", dataSize=4 + + rdval t1, "InstRegIndex(MISCREG_FOSEG)" + st t1, seg, t7rel, "DISPLACEMENT + 16 + 4", dataSize=2 + + br rom_label("fxsaveCommon") + +extern fxsave64: + rdval t1, "InstRegIndex(MISCREG_FIOFF)" + st t1, seg, t7rel, "DISPLACEMENT + 8", dataSize=8 + + rdval t1, "InstRegIndex(MISCREG_FOOFF)" + st t1, seg, t7rel, "DISPLACEMENT + 16 + 0", dataSize=8 + + br rom_label("fxsaveCommon") + +extern fxsaveCommon: + rdval t1, fcw + st t1, seg, t7rel, "DISPLACEMENT + 0", dataSize=2 + + # FSW includes TOP when read + rdval t1, fsw + st t1, seg, t7rel, "DISPLACEMENT + 2", dataSize=2 + + # FTW + rdxftw t1 + st t1, seg, t7rel, "DISPLACEMENT + 4", dataSize=1 + + rdval t1, "InstRegIndex(MISCREG_FOP)" + st t1, seg, t7rel, "DISPLACEMENT + 6", dataSize=2 + + rdval t1, "InstRegIndex(MISCREG_MXCSR)" + st t1, seg, t7rel, "DISPLACEMENT + 16 + 8", dataSize=4 + + # MXCSR_MASK, software assumes the default (0xFFBF) if 0. + limm t1, 0xFFFF + st t1, seg, t7rel, "DISPLACEMENT + 16 + 12", dataSize=4 + +''' + storeAllDataRegs + ''' + eret + +extern fxrstor32: + ld t1, seg, t7rel, "DISPLACEMENT + 8", dataSize=4 + wrval "InstRegIndex(MISCREG_FIOFF)", t1 + + ld t1, seg, t7rel, "DISPLACEMENT + 12", dataSize=2 + wrval "InstRegIndex(MISCREG_FISEG)", t1 + + ld t1, seg, t7rel, "DISPLACEMENT + 16 + 0", dataSize=4 + wrval "InstRegIndex(MISCREG_FOOFF)", t1 + + ld t1, seg, t7rel, "DISPLACEMENT + 16 + 4", dataSize=2 + wrval "InstRegIndex(MISCREG_FOSEG)", t1 + + br rom_label("fxrstorCommon") + +extern fxrstor64: + limm t2, 0, dataSize=8 + + ld t1, seg, t7rel, "DISPLACEMENT + 8", dataSize=8 + wrval "InstRegIndex(MISCREG_FIOFF)", t1 + wrval "InstRegIndex(MISCREG_FISEG)", t2 + + ld t1, seg, t7rel, "DISPLACEMENT + 16 + 0", dataSize=4 + wrval "InstRegIndex(MISCREG_FOOFF)", t1 + wrval "InstRegIndex(MISCREG_FOSEG)", t2 + + br rom_label("fxrstorCommon") + +extern fxrstorCommon: + ld t1, seg, t7rel, "DISPLACEMENT + 0", dataSize=2 + wrval fcw, t1 + + # FSW includes TOP when read + ld t1, seg, t7rel, "DISPLACEMENT + 2", dataSize=2 + wrval fsw, t1 + srli t1, t1, 11, dataSize=2 + andi t1, t1, 0x7, dataSize=2 + wrval "InstRegIndex(MISCREG_X87_TOP)", t1 + + # FTW + ld t1, seg, t7rel, "DISPLACEMENT + 4", dataSize=1 + wrxftw t1 + + ld t1, seg, t7rel, "DISPLACEMENT + 6", dataSize=2 + wrval "InstRegIndex(MISCREG_FOP)", t1 + + ld t1, seg, t7rel, "DISPLACEMENT + 16 + 8", dataSize=4 + wrval "InstRegIndex(MISCREG_MXCSR)", t1 + +''' + loadAllDataRegs + ''' + eret +}; + +def macroop FXSAVE_M { + lea t7, seg, sib, dataSize=asz + br rom_label("fxsave32") +}; + +def macroop FXSAVE_P { + rdip t7 + br rom_label("fxsave32") +}; + +def macroop FXSAVE64_M { + lea t7, seg, sib, dataSize=asz + br rom_label("fxsave64") +}; + +def macroop FXSAVE64_P { + rdip t7 + br rom_label("fxsave64") +}; + +def macroop FXRSTOR_M { + lea t7, seg, sib, dataSize=asz + br rom_label("fxrstor32") +}; + +def macroop FXRSTOR_P { + rdip t7 + br rom_label("fxrstor32") +}; + +def macroop FXRSTOR64_M { + lea t7, seg, sib, dataSize=asz + br rom_label("fxrstor64") +}; + +def macroop FXRSTOR64_P { + rdip t7 + br rom_label("fxrstor64") +}; ''' diff -r f7df7b862186 -r 81aac6e3008d src/arch/x86/isa/decoder/two_byte_opcodes.isa --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa Thu Jun 13 11:45:18 2013 +0200 +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa Thu Jun 13 13:29:52 2013 +0200 @@ -762,8 +762,16 @@ default: Inst::UD2(); } default: decode MODRM_REG { - 0x0: fxsave(); - 0x1: fxrstor(); + 0x0: decode OPSIZE { + 4: Inst::FXSAVE(M); + 8: Inst::FXSAVE64(M); + default: fxsave(); + } + 0x1: decode OPSIZE { + 4: Inst::FXRSTOR(M); + 8: Inst::FXRSTOR64(M); + default: fxrstor(); + } 0x2: Inst::LDMXCSR(Md); 0x3: Inst::STMXCSR(Md); 0x4: xsave(); diff -r f7df7b862186 -r 81aac6e3008d src/arch/x86/isa/microops/regop.isa --- a/src/arch/x86/isa/microops/regop.isa Thu Jun 13 11:45:18 2013 +0200 +++ b/src/arch/x86/isa/microops/regop.isa Thu Jun 13 13:29:52 2013 +0200 @@ -1679,4 +1679,18 @@ break; } ''' + + class Wrxftw(WrRegOp): + def __init__(self, src1, **kwargs): + super(Wrxftw, self).__init__(src1, "InstRegIndex(NUM_INTREGS)", \ + **kwargs) + + code = ''' + FTW = X86ISA::convX87XTagsToTags(SrcReg1); + ''' + + class Rdxftw(RdRegOp): + code = ''' + DestReg = X86ISA::convX87TagsToXTags(FTW); + ''' }}; diff -r f7df7b862186 -r 81aac6e3008d src/arch/x86/utility.hh --- a/src/arch/x86/utility.hh Thu Jun 13 11:45:18 2013 +0200 +++ b/src/arch/x86/utility.hh Thu Jun 13 13:29:52 2013 +0200 @@ -134,6 +134,12 @@ * @param val New rflags value to store in TC */ void setRFlags(ThreadContext *tc, uint64_t val); + + /** Convert an x87 tag word to xtags format. */ + uint8_t convX87TagsToXTags(MiscReg ftw); + + /** Convert an x87 xtag word to normal tags format. */ + uint16_t convX87XTagsToTags(uint8_t ftwx); } #endif // __ARCH_X86_UTILITY_HH__ diff -r f7df7b862186 -r 81aac6e3008d src/arch/x86/utility.cc --- a/src/arch/x86/utility.cc Thu Jun 13 11:45:18 2013 +0200 +++ b/src/arch/x86/utility.cc Thu Jun 13 13:29:52 2013 +0200 @@ -268,4 +268,37 @@ tc->setMiscReg(MISCREG_RFLAGS, val & ~(ccFlagMask | cfofMask | DFBit)); } +uint8_t +convX87TagsToXTags(MiscReg ftw) +{ + uint8_t ftwx(0); + for (int i = 0; i < 8; ++i) { + if (((ftw >> (2 * i)) & 0x3) != 0x3) { + // Element is non-empty. + ftwx |= 1 << i; + } + } + + return ftwx; +} + +uint16_t +convX87XTagsToTags(uint8_t ftwx) +{ + uint16_t ftw(0); + for (int i = 0; i < 8; ++i) { + if (!((ftwx >> i) & 0x1)) { + // Element is empty. + ftw |= 0x3 << (2 * i); + } else { + // TODO: We currently assume that non-empty elements are + // valid (0x0), but we should ideally reconstruct the full + // state (valid/zero/special). + } + } + + return ftw; +} + + } // namespace X86_ISA