diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc index 3df948986..7f5ae980a 100644 --- a/src/arch/x86/utility.cc +++ b/src/arch/x86/utility.cc @@ -268,6 +268,52 @@ setRFlags(ThreadContext *tc, uint64_t val) tc->setMiscReg(MISCREG_RFLAGS, val & ~(ccFlagMask | cfofMask | DFBit)); } +uint8_t +convX87TagsToXTags(uint16_t ftw) +{ + uint8_t ftwx(0); + for (int i = 0; i < 8; ++i) { + // Extract the tag for the current element on the FP stack + const unsigned tag((ftw >> (2 * i)) & 0x3); + + /* + * Check the type of the current FP element. Valid values are: + * 0 == Valid + * 1 == Zero + * 2 == Special (Nan, unsupported, infinity, denormal) + * 3 == Empty + */ + // The xsave version of the tag word only keeps track of + // whether the element is empty or not. Set the corresponding + // bit in the ftwx if it's not empty, + if (tag != 0x3) + ftwx |= 1 << i; + } + + return ftwx; +} + +uint16_t +convX87XTagsToTags(uint8_t ftwx) +{ + uint16_t ftw(0); + for (int i = 0; i < 8; ++i) { + const unsigned xtag(((ftwx >> i) & 0x1)); + + // The xtag for an x87 stack position is 0 for empty stack positions. + if (!xtag) { + // Set the tag word to 3 (empty) for the current element. + 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; +} + uint16_t genX87Tags(uint16_t ftw, uint8_t top, int8_t spm) { diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh index 24aca3e0a..dcf61bddb 100644 --- a/src/arch/x86/utility.hh +++ b/src/arch/x86/utility.hh @@ -142,6 +142,37 @@ namespace X86ISA return *(uint64_t *)(&val); } + /** + * Convert an x87 tag word to abridged tag format. + * + * Convert from the x87 tag representation to the tag abridged + * representation used in the FXSAVE area. The classic format uses + * 2 bits per stack position to indicate if a position is valid, + * zero, special, or empty. The abridged format only stores + * whether a position is empty or not. + * + * @param ftw Tag word in classic x87 format. + * @return Tag word in the abridged format. + */ + uint8_t convX87TagsToXTags(uint16_t ftw); + + /** + * Convert an x87 xtag word to normal tags format. + * + * Convert from the abridged x87 tag representation used in the + * FXSAVE area to a full x87 tag. The classic format uses 2 bits + * per stack position to indicate if a position is valid, zero, + * special, or empty. The abridged format only stores whether a + * position is empty or not. + * + * @todo Reconstruct the correct state of stack positions instead + * of just valid/invalid. + * + * @param ftwx Tag word in the abridged format. + * @return Tag word in classic x87 format. + */ + uint16_t convX87XTagsToTags(uint8_t ftwx); + /** * Generate and updated x87 tag register after a push/pop * operation.