diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/x86/faults.cc | 3 | ||||
-rw-r--r-- | src/arch/x86/isa/microops/fpop.isa | 26 | ||||
-rw-r--r-- | src/arch/x86/utility.cc | 20 | ||||
-rw-r--r-- | src/arch/x86/utility.hh | 15 |
4 files changed, 60 insertions, 4 deletions
diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc index 995326562..aa859052e 100644 --- a/src/arch/x86/faults.cc +++ b/src/arch/x86/faults.cc @@ -270,6 +270,9 @@ namespace X86ISA tc->setMiscReg(MISCREG_MXCSR, 0x1f80); + // 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 --git a/src/arch/x86/isa/microops/fpop.isa b/src/arch/x86/isa/microops/fpop.isa index 22d6fbcda..142138fb2 100644 --- a/src/arch/x86/isa/microops/fpop.isa +++ b/src/arch/x86/isa/microops/fpop.isa @@ -57,6 +57,7 @@ def template MicroFpOpExecute {{ { %(code)s; %(flag_code)s; + %(tag_code)s; %(top_code)s; } else @@ -128,11 +129,20 @@ let {{ 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 @@ let {{ "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 @@ let {{ 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 @@ let {{ 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 @@ let {{ 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 @@ let {{ 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, @@ -359,10 +377,10 @@ let {{ 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 --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc index 2398ca073..3df948986 100644 --- a/src/arch/x86/utility.cc +++ b/src/arch/x86/utility.cc @@ -268,4 +268,24 @@ setRFlags(ThreadContext *tc, uint64_t val) tc->setMiscReg(MISCREG_RFLAGS, val & ~(ccFlagMask | cfofMask | DFBit)); } +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 = new_top; i != top; i = (i + 1 + 8) % 8) + ftw &= ~(0x3 << (2 * i)); + } + + return ftw; +} + } // namespace X86_ISA diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh index 48840ac77..24aca3e0a 100644 --- a/src/arch/x86/utility.hh +++ b/src/arch/x86/utility.hh @@ -141,6 +141,21 @@ namespace X86ISA 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__ |