x86: Fix the CPUID Long Mode Address Size function.
[gem5.git] / src / arch / x86 / isa.cc
index d19a2a6cc98ad00dcb5740e566198c21b1e8d659..f65bc2392c5a261ce9331abc1050372fbf4f85c7 100644 (file)
  * Authors: Gabe Black
  */
 
-#include "arch/x86/floatregs.hh"
+#include "arch/x86/decoder.hh"
 #include "arch/x86/isa.hh"
 #include "arch/x86/tlb.hh"
 #include "cpu/base.hh"
 #include "cpu/thread_context.hh"
+#include "params/X86ISA.hh"
 #include "sim/serialize.hh"
 
 namespace X86ISA
@@ -40,9 +41,10 @@ namespace X86ISA
 
 void
 ISA::updateHandyM5Reg(Efer efer, CR0 cr0,
-                      SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags)
+                      SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags,
+                      ThreadContext *tc)
 {
-    HandyM5Reg m5reg;
+    HandyM5Reg m5reg = 0;
     if (efer.lma) {
         m5reg.mode = LongMode;
         if (csAttr.longMode)
@@ -95,6 +97,8 @@ ISA::updateHandyM5Reg(Efer efer, CR0 cr0,
     }
 
     regVal[MISCREG_M5_REG] = m5reg;
+    if (tc)
+        tc->getDecoderPtr()->setM5Reg(m5reg);
 }
 
 void
@@ -107,6 +111,18 @@ ISA::clear()
     regVal[MISCREG_DR7] = 1 << 10;
 }
 
+ISA::ISA(Params *p)
+    : SimObject(p)
+{
+    clear();
+}
+
+const X86ISAParams *
+ISA::params() const
+{
+    return dynamic_cast<const Params *>(_params);
+}
+
 MiscReg
 ISA::readMiscRegNoEffect(int miscReg)
 {
@@ -128,6 +144,13 @@ ISA::readMiscReg(int miscReg, ThreadContext * tc)
     if (miscReg == MISCREG_TSC) {
         return regVal[MISCREG_TSC] + tc->getCpuPtr()->curCycle();
     }
+
+    if (miscReg == MISCREG_FSW) {
+        MiscReg fsw = regVal[MISCREG_FSW];
+        MiscReg top = regVal[MISCREG_X87_TOP];
+        return (fsw & (~(7ULL << 11))) + (top << 11);
+    }
+
     return readMiscRegNoEffect(miscReg);
 }
 
@@ -168,8 +191,8 @@ ISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc)
                 }
             }
             if (toggled.pg) {
-                tc->getITBPtr()->invalidateAll();
-                tc->getDTBPtr()->invalidateAll();
+                tc->getITBPtr()->flushAll();
+                tc->getDTBPtr()->flushAll();
             }
             //This must always be 1.
             newCR0.et = 1;
@@ -178,21 +201,22 @@ ISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc)
                              newCR0,
                              regVal[MISCREG_CS_ATTR],
                              regVal[MISCREG_SS_ATTR],
-                             regVal[MISCREG_RFLAGS]);
+                             regVal[MISCREG_RFLAGS],
+                             tc);
         }
         break;
       case MISCREG_CR2:
         break;
       case MISCREG_CR3:
-        tc->getITBPtr()->invalidateNonGlobal();
-        tc->getDTBPtr()->invalidateNonGlobal();
+        tc->getITBPtr()->flushNonGlobal();
+        tc->getDTBPtr()->flushNonGlobal();
         break;
       case MISCREG_CR4:
         {
             CR4 toggled = regVal[miscReg] ^ val;
             if (toggled.pae || toggled.pse || toggled.pge) {
-                tc->getITBPtr()->invalidateAll();
-                tc->getDTBPtr()->invalidateAll();
+                tc->getITBPtr()->flushAll();
+                tc->getDTBPtr()->flushAll();
             }
         }
         break;
@@ -219,7 +243,8 @@ ISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc)
                              regVal[MISCREG_CR0],
                              newCSAttr,
                              regVal[MISCREG_SS_ATTR],
-                             regVal[MISCREG_RFLAGS]);
+                             regVal[MISCREG_RFLAGS],
+                             tc);
         }
         break;
       case MISCREG_SS_ATTR:
@@ -227,7 +252,8 @@ ISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc)
                          regVal[MISCREG_CR0],
                          regVal[MISCREG_CS_ATTR],
                          val,
-                         regVal[MISCREG_RFLAGS]);
+                         regVal[MISCREG_RFLAGS],
+                         tc);
         break;
       // These segments always actually use their bases, or in other words
       // their effective bases must stay equal to their actual bases.
@@ -334,7 +360,8 @@ ISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc)
                          regVal[MISCREG_CR0],
                          regVal[MISCREG_CS_ATTR],
                          regVal[MISCREG_SS_ATTR],
-                         regVal[MISCREG_RFLAGS]);
+                         regVal[MISCREG_RFLAGS],
+                         tc);
         return;
       default:
         break;
@@ -343,37 +370,33 @@ ISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc)
 }
 
 void
-ISA::serialize(EventManager *em, std::ostream & os)
+ISA::serialize(std::ostream & os)
 {
     SERIALIZE_ARRAY(regVal, NumMiscRegs);
 }
 
 void
-ISA::unserialize(EventManager *em, Checkpoint * cp,
-                 const std::string & section)
+ISA::unserialize(Checkpoint * cp, const std::string & section)
 {
     UNSERIALIZE_ARRAY(regVal, NumMiscRegs);
+    updateHandyM5Reg(regVal[MISCREG_EFER],
+                     regVal[MISCREG_CR0],
+                     regVal[MISCREG_CS_ATTR],
+                     regVal[MISCREG_SS_ATTR],
+                     regVal[MISCREG_RFLAGS],
+                     NULL);
 }
 
-int
-ISA::flattenIntIndex(int reg)
+void
+ISA::startup(ThreadContext *tc)
 {
-    //If we need to fold over the index to match byte semantics, do that.
-    //Otherwise, just strip off any extra bits and pass it through.
-    if (reg & (1 << 6))
-        return (reg & (~(1 << 6) - 0x4));
-    else
-        return (reg & ~(1 << 6));
+    tc->getDecoderPtr()->setM5Reg(regVal[MISCREG_M5_REG]);
 }
 
-int
-ISA::flattenFloatIndex(int reg)
-{
-    if (reg >= NUM_FLOATREGS) {
-        int top = readMiscRegNoEffect(MISCREG_X87_TOP);
-        reg = FLOATREG_STACK(reg - NUM_FLOATREGS, top);
-    }
-    return reg;
 }
 
+X86ISA::ISA *
+X86ISAParams::create()
+{
+    return new X86ISA::ISA(this);
 }