X86: Keep handy values like the operating mode in one register.
authorGabe Black <gblack@eecs.umich.edu>
Thu, 12 Jun 2008 04:50:25 +0000 (00:50 -0400)
committerGabe Black <gblack@eecs.umich.edu>
Thu, 12 Jun 2008 04:50:25 +0000 (00:50 -0400)
src/arch/x86/isa/microops/regop.isa
src/arch/x86/isa/operands.isa
src/arch/x86/miscregfile.cc
src/arch/x86/miscregs.hh

index 6bd26608e9ba0f751dbb8ef45eeb2c2536d326c1..35f319528ce89d107f88d7e9bc1b128ac2771c44 100644 (file)
@@ -1100,6 +1100,11 @@ let {{
             DestReg = TscOp;
         '''
 
+    class Rdm5reg(RdRegOp):
+        code = '''
+            DestReg = M5Reg;
+        '''
+
     class Wrdl(RegOp):
         code = '''
             SegDescriptor desc = SrcReg1;
index f002b2cea39d8df4e3c4b53b253073c03ebf24b5..446580c1b7417e107ede0cb9bf5052cc03ac8a13 100644 (file)
@@ -151,5 +151,6 @@ def operands {{
         'CSBase':        ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 207),
         'CSAttr':        ('ControlReg', 'udw', 'MISCREG_CS_ATTR', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 208),
         'TscOp':         ('ControlReg', 'udw', 'MISCREG_TSC', (None, None, ['IsSerializeAfter', 'IsSerializing', 'IsNonSpeculative']), 209),
+        'M5Reg':         ('ControlReg', 'udw', 'MISCREG_M5_REG', (None, None, None), 210),
         'Mem':           ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 300)
 }};
index 930bf53c710543883e6aaea5648a859f9f6e2980..6abeb7d34abbf428c8f38bd55a0470cfce8e0bbd 100644 (file)
@@ -300,17 +300,39 @@ void MiscRegFile::setReg(int miscReg,
             CR0 toggled = regVal[miscReg] ^ val;
             CR0 newCR0 = val;
             Efer efer = regVal[MISCREG_EFER];
+            HandyM5Reg m5reg = regVal[MISCREG_M5_REG];
             if (toggled.pg && efer.lme) {
                 if (newCR0.pg) {
                     //Turning on long mode
                     efer.lma = 1;
+                    m5reg.mode = LongMode;
                     regVal[MISCREG_EFER] = efer;
                 } else {
                     //Turning off long mode
                     efer.lma = 0;
+                    m5reg.mode = LegacyMode;
                     regVal[MISCREG_EFER] = efer;
                 }
             }
+            // Figure out what submode we're in.
+            if (m5reg.mode == LongMode) {
+                SegAttr csAttr = regVal[MISCREG_CS_ATTR];
+                if (csAttr.longMode)
+                    m5reg.submode = SixtyFourBitMode;
+                else
+                    m5reg.submode = CompatabilityMode;
+            } else {
+                if (newCR0.pe) {
+                    RFLAGS rflags = regVal[MISCREG_RFLAGS];
+                    if (rflags.vm)
+                        m5reg.submode = Virtual8086Mode;
+                    else
+                        m5reg.submode = ProtectedMode;
+                } else {
+                    m5reg.submode = RealMode;
+                }
+            }
+            regVal[MISCREG_M5_REG] = m5reg;
             if (toggled.pg) {
                 tc->getITBPtr()->invalidateAll();
                 tc->getDTBPtr()->invalidateAll();
@@ -341,20 +363,26 @@ void MiscRegFile::setReg(int miscReg,
         {
             SegAttr toggled = regVal[miscReg] ^ val;
             SegAttr newCSAttr = val;
+            HandyM5Reg m5reg = regVal[MISCREG_M5_REG];
             if (toggled.longMode) {
-                SegAttr newCSAttr = val;
                 if (newCSAttr.longMode) {
+                    if (m5reg.mode == LongMode)
+                        m5reg.submode = SixtyFourBitMode;
                     regVal[MISCREG_ES_EFF_BASE] = 0;
                     regVal[MISCREG_CS_EFF_BASE] = 0;
                     regVal[MISCREG_SS_EFF_BASE] = 0;
                     regVal[MISCREG_DS_EFF_BASE] = 0;
                 } else {
+                    if (m5reg.mode == LongMode)
+                        m5reg.submode = CompatabilityMode;
                     regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE];
                     regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE];
                     regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE];
                     regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE];
                 }
             }
+            m5reg.cpl = newCSAttr.dpl;
+            regVal[MISCREG_M5_REG] = m5reg;
         }
         break;
       // These segments always actually use their bases, or in other words
index 90f1d9fdad81a2600edd2976fcc52cc536eb518e..caa1e817bd64905eaa4e4e4fb1a0d2a6b884cdbe 100644 (file)
@@ -130,6 +130,9 @@ namespace X86ISA
         // Flags register
         MISCREG_RFLAGS = MISCREG_DR_BASE + NumDRegs,
 
+        //Register to keep handy values like the CPU mode in.
+        MISCREG_M5_REG,
+
         /*
          * Model Specific Registers
          */
@@ -563,6 +566,12 @@ namespace X86ISA
         Bitfield<0> cf; // Carry Flag
     EndBitUnion(RFLAGS)
 
+    BitUnion64(HandyM5Reg)
+        Bitfield<0> mode;
+        Bitfield<3, 1> submode;
+        Bitfield<5, 4> cpl;
+    EndBitUnion(HandyM5Reg)
+
     /**
      * Control registers
      */