x86: Fix loading of floating point constants

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.
This commit is contained in:
Andreas Sandberg 2013-06-18 16:30:06 +02:00
parent c9c02efb99
commit a8e8c4f433
5 changed files with 17 additions and 9 deletions

View 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"

View file

@ -40,17 +40,17 @@
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
};

View file

@ -40,22 +40,22 @@
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
};

View 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

View 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__