x86: Fix loading of floating point constants
authorAndreas Sandberg <andreas@sandberg.pp.se>
Tue, 18 Jun 2013 14:30:06 +0000 (16:30 +0200)
committerAndreas Sandberg <andreas@sandberg.pp.se>
Tue, 18 Jun 2013 14:30:06 +0000 (16:30 +0200)
This changeset actually fixes two issues:

 * The lfpimm instruction didn't work correctly when applied to a
   floating point constant (it did work for integers containing the
   bit string representation of a constant) since it used
   reinterpret_cast to convert a double to a uint64_t. This caused a
   compilation error, at least, in gcc 4.6.3.

 * The instructions loading floating point constants in the x87
   processor didn't work correctly since they just stored a truncated
   integer instead of a double in the floating point register. This
   changeset fixes the old microcode by using lfpimm instruction
   instead of the limm instructions.

src/arch/x86/isa/includes.isa
src/arch/x86/isa/insts/x87/load_constants/load_0_1_or_pi.py
src/arch/x86/isa/insts/x87/load_constants/load_logarithm.py
src/arch/x86/isa/microops/limmop.isa
src/arch/x86/utility.hh

index eda2ebceb8ae2f8df756360cf8ce704deb19a453..43565fda51671f855f7c07aa8051dd813dc63278 100644 (file)
@@ -64,6 +64,7 @@ output header {{
 #include "arch/x86/isa_traits.hh"
 #include "arch/x86/registers.hh"
 #include "arch/x86/types.hh"
+#include "arch/x86/utility.hh"
 #include "base/misc.hh"
 #include "cpu/static_inst.hh"
 #include "mem/packet.hh"
index cb894731242b7b33d06d0b614729201ee008e186..9f22af89bb7a02305799fc303dcdda90bc746706 100644 (file)
 microcode = '''
 
 def macroop FLDZ {
-    limm ufp1, "double(0)"
+    lfpimm ufp1, 0.0
     movfp st(-1), ufp1, spm=-1
 };
 
 def macroop FLD1 {
-    limm ufp1, "double(1)"
+    lfpimm ufp1, 1.0
     movfp st(-1), ufp1, spm=-1
 };
 
 def macroop FLDPI {
-    limm ufp1, "double(3.14159265359)"
+    lfpimm ufp1, 3.14159265359
     movfp st(-1), ufp1, spm=-1
 };
 
index 7e71c4006c636fc9dacc98ea6adf366e32c781e3..88eb0108655a5c0cffa8a22c36a5670fcae585a8 100644 (file)
 microcode = '''
 
 def macroop FLDL2E {
-    limm ufp1, "double(1.44269504089)"
+    lfpimm ufp1, 1.44269504089
     movfp st(-1), ufp1, spm=-1
 };
 
 def macroop FLDL2T {
-    limm ufp1, "double(3.32192809489)"
+    lfpimm ufp1, 3.32192809489
     movfp st(-1), ufp1, spm=-1
 };
 
 def macroop FLDLG2 {
-    limm ufp1, "double(0.30102999566)"
+    lfpimm ufp1, 0.30102999566
     movfp st(-1), ufp1, spm=-1
 };
 
 def macroop FLDLN2 {
-    limm ufp1, "double(0.69314718056)"
+    lfpimm ufp1, 0.69314718056
     movfp st(-1), ufp1, spm=-1
 };
 
index 9e88e4b94b002a585fe58048c746c72498d2e8a9..2c61aaa45c41819cf7fcf4dda0543a83631f8591 100644 (file)
@@ -140,8 +140,8 @@ let {{
             self.dest = dest
             if isinstance(imm, (int, long)):
                 imm = "ULL(%d)" % imm
-            if isinstance(imm, float):
-                imm = "reinterpret_cast<uint64_t>((double)(%d))"
+            elif isinstance(imm, float):
+                imm = "getDoubleBits(%.16f)" % imm
             self.imm = imm
             self.dataSize = dataSize
 
index 6fc802f2f14baa4c689852dd8ea02b2e2e7e008d..48840ac77f9d221fb2f1190b2632cedef68f0315 100644 (file)
@@ -134,6 +134,13 @@ namespace X86ISA
      * @param val New rflags value to store in TC
      */
     void setRFlags(ThreadContext *tc, uint64_t val);
+
+    /**
+     * Extract the bit string representing a double value.
+     */
+    inline uint64_t getDoubleBits(double val) {
+        return *(uint64_t *)(&val);
+    }
 }
 
 #endif // __ARCH_X86_UTILITY_HH__