x86: Add support routines to convert between x87 tag formats
authorAndreas Sandberg <andreas@sandberg.pp.se>
Thu, 19 Sep 2013 15:30:26 +0000 (17:30 +0200)
committerAndreas Sandberg <andreas@sandberg.pp.se>
Thu, 19 Sep 2013 15:30:26 +0000 (17:30 +0200)
This changeset adds the convX87XTagsToTags() and convX87TagsToXTags()
which convert between the tag formats in the FTW register and the
format used in the xsave area. The conversion from to the x87 FTW
representation is currently loses some information since it does not
reconstruct the valid/zero/special flags which are not included in the
xsave representation.

src/arch/x86/utility.cc
src/arch/x86/utility.hh

index 3df948986d503dbcd1489c2402da57011dad2f48..7f5ae980a2caec28bcc304e39424d052d0eecd77 100644 (file)
@@ -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)
 {
index 24aca3e0ad58f754c4885689d2b601831fc4e2a4..dcf61bddbb83d2c5c190cc747742120ce13a544b 100644 (file)
@@ -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.