summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86/faults.cc3
-rw-r--r--src/arch/x86/isa/microops/fpop.isa26
-rw-r--r--src/arch/x86/utility.cc20
-rw-r--r--src/arch/x86/utility.hh15
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__