diff -r f3e7cefe878d -r cfc4fa8529b3 src/arch/x86/faults.cc --- a/src/arch/x86/faults.cc Tue Jun 11 10:50:30 2013 +0200 +++ b/src/arch/x86/faults.cc Tue Jun 11 10:54:09 2013 +0200 @@ -268,6 +268,9 @@ tc->setMiscReg(MISCREG_DR6, 0x00000000ffff0ff0ULL); tc->setMiscReg(MISCREG_DR7, 0x0000000000000400ULL); + // Flag all elements on the x87 stack as empty. + tc->setMiscReg(MISCREG_FTW, 0xFFFF); + // Update the handy M5 Reg. tc->setMiscReg(MISCREG_M5_REG, 0); MicroPC entry = X86ISAInst::RomLabels::extern_label_initIntHalt; diff -r f3e7cefe878d -r cfc4fa8529b3 src/arch/x86/isa/microops/fpop.isa --- a/src/arch/x86/isa/microops/fpop.isa Tue Jun 11 10:50:30 2013 +0200 +++ b/src/arch/x86/isa/microops/fpop.isa Tue Jun 11 10:54:09 2013 +0200 @@ -57,6 +57,7 @@ { %(code)s; %(flag_code)s; + %(tag_code)s; %(top_code)s; } else @@ -128,11 +129,20 @@ base = "X86ISA::FpOp" # Get everything ready for the substitution + iop_tag = InstObjParams(name, Name + suffix + "TopTag", base, + {"code" : code, + "flag_code" : flag_code, + "cond_check" : cond_check, + "else_code" : else_code, + "tag_code" : "FTW = genX87Tags(FTW, TOP, spm);", + "top_code" : "TOP = (TOP + spm + 8) % 8;", + "op_class" : op_class}) iop_top = InstObjParams(name, Name + suffix + "Top", base, {"code" : code, "flag_code" : flag_code, "cond_check" : cond_check, "else_code" : else_code, + "tag_code" : ";", "top_code" : "TOP = (TOP + spm + 8) % 8;", "op_class" : op_class}) iop = InstObjParams(name, Name + suffix, base, @@ -140,10 +150,14 @@ "flag_code" : flag_code, "cond_check" : cond_check, "else_code" : else_code, + "tag_code" : ";", "top_code" : ";", "op_class" : op_class}) # Generate the actual code (finally!) + header_output += MicroFpOpDeclare.subst(iop_tag) + decoder_output += MicroFpOpConstructor.subst(iop_tag) + exec_output += MicroFpOpExecute.subst(iop_tag) header_output += MicroFpOpDeclare.subst(iop_top) decoder_output += MicroFpOpConstructor.subst(iop_top) exec_output += MicroFpOpExecute.subst(iop_top) @@ -191,7 +205,7 @@ op_class = "FloatAddOp" def __init__(self, dest, src1, spm=0, \ - SetStatus=False, dataSize="env.dataSize"): + SetStatus=False, UpdateFTW=True, dataSize="env.dataSize"): self.dest = dest self.src1 = src1 self.src2 = "InstRegIndex(0)" @@ -201,6 +215,8 @@ self.className += "Flags" if spm: self.className += "Top" + if spm and UpdateFTW: + self.className += "Tag" def getAllocator(self, microFlags): return '''new %(class_name)s(machInst, macrocodeBlock, @@ -225,7 +241,7 @@ op_class = "FloatAddOp" def __init__(self, dest, src1, src2, spm=0, \ - SetStatus=False, dataSize="env.dataSize"): + SetStatus=False, UpdateFTW=True, dataSize="env.dataSize"): self.dest = dest self.src1 = src1 self.src2 = src2 @@ -235,6 +251,8 @@ self.className += "Flags" if spm: self.className += "Top" + if spm and UpdateFTW: + self.className += "Tag" def getAllocator(self, microFlags): return '''new %(class_name)s(machInst, macrocodeBlock, @@ -386,10 +404,10 @@ flag_code = 'FSW = new_fsw;' class Compfp(FpBinaryOp): - def __init__(self, src1, src2, spm=0, setStatus=False, \ + def __init__(self, src1, src2, spm=0, setStatus=False, updateFTW=True, \ dataSize="env.dataSize"): super(Compfp, self).__init__("InstRegIndex(FLOATREG_MICROFP0)", \ - src1, src2, spm, setStatus, dataSize) + src1, src2, spm, setStatus, updateFTW, dataSize) # This class sets the condition codes in rflags according to the # rules for comparing floating point. code = ''' diff -r f3e7cefe878d -r cfc4fa8529b3 src/arch/x86/utility.hh --- a/src/arch/x86/utility.hh Tue Jun 11 10:50:30 2013 +0200 +++ b/src/arch/x86/utility.hh Tue Jun 11 10:54:09 2013 +0200 @@ -147,6 +147,21 @@ inline uint64_t getDoubleBits(double val) { return *(uint64_t *)(&val); } + + /** + * Generate and updated x87 tag register after a push/pop + * operation. + * + * @note There is currently no support for setting other tags than + * valid and invalid. A real x87 will set the tag value to zero or + * special for some special floating point values. + * + * @param ftw Current value of the FTW register. + * @param top Current x87 TOP value. + * @param spm Stack displacement. + * @return New value of the FTW register. + */ + uint16_t genX87Tags(uint16_t ftw, uint8_t top, int8_t spm); } #endif // __ARCH_X86_UTILITY_HH__ diff -r f3e7cefe878d -r cfc4fa8529b3 src/arch/x86/utility.cc --- a/src/arch/x86/utility.cc Tue Jun 11 10:50:30 2013 +0200 +++ b/src/arch/x86/utility.cc Tue Jun 11 10:54:09 2013 +0200 @@ -301,4 +301,24 @@ } +uint16_t +genX87Tags(uint16_t ftw, uint8_t top, int8_t spm) +{ + const uint8_t new_top((top + spm + 8) % 8); + + if (spm > 0) { + // Removing elements from the stack. Flag the elements as empty. + for (int i = top; i != new_top; i = (i + 1 + 8) % 8) + ftw |= 0x3 << (2 * i); + } else if (spm < 0) { + // Adding elements to the stack. Flag the new elements as + // valid. We should ideally decode them and "do the right + // thing". + for (int i = top; i != new_top; i = (i - 1 + 8) % 8) + ftw &= ~(0x3 << (2 * i)); + } + + return ftw; +} + } // namespace X86_ISA