X86: Implement the wrcr microop which writes a control register, and some control...
authorGabe Black <gblack@eecs.umich.edu>
Mon, 12 Nov 2007 22:38:59 +0000 (14:38 -0800)
committerGabe Black <gblack@eecs.umich.edu>
Mon, 12 Nov 2007 22:38:59 +0000 (14:38 -0800)
--HG--
extra : convert_revision : 3e9daef9cdd0665c033420e5b4f981649e9908ab

src/arch/x86/isa/decoder/two_byte_opcodes.isa
src/arch/x86/isa/insts/general_purpose/data_transfer/move.py
src/arch/x86/isa/microasm.isa
src/arch/x86/isa/microops/regop.isa
src/arch/x86/isa/operands.isa
src/arch/x86/isa/specialize.isa
src/arch/x86/miscregfile.cc

index 233a5602de62764e173e4d40f4d2f82c6b948ec3..f3485bc4e553e91beacbf6786196cc0e5516ae57 100644 (file)
                 0x0: decode OPCODE_OP_BOTTOM3 {
                     0x0: mov_Rd_Cd();
                     0x1: mov_Rd_Dd();
-                    0x2: mov_Cd_Rd();
+                    0x2: Inst::MOV(Cd,Rd);
                     0x3: mov_Dd_Rd();
                     0x4: mov_Rd_Td();
                     0x6: mov_Td_Rd();
index ada7f28a31bdedfc935cedb9778b784038d102f5..a15fc21ef1537764071d2245c8d6ac5f6665c3fc 100644 (file)
@@ -188,6 +188,10 @@ def macroop MOVZX_W_R_P {
     ld t1, seg, riprel, disp, dataSize=2
     zexti reg, t1, 15
 };
+
+def macroop MOV_C_R {
+    wrcr reg, regm
+};
 '''
 #let {{
 #    class MOVD(Inst):
index e05582e37c696ca0c4c09948c33fe4186507903e..040bb2036a73c1927ad73f6a3beb1236f58b8be4 100644 (file)
@@ -113,6 +113,9 @@ let {{
     for reg in ('ax', 'bx', 'cx', 'dx', 'sp', 'bp', 'si', 'di'):
         assembler.symbols["r%s" % reg] = "INTREG_R%s" % reg.upper()
 
+    for reg in range(15):
+        assembler.symbols["cr%d" % reg] = "MISCREG_CR%d" % reg
+
     for flag in ('CF', 'PF', 'ECF', 'AF', 'EZF', 'ZF', 'SF', 'OF'):
         assembler.symbols[flag] = flag + "Bit"
 
index b5e17d36d9d6064bbe94c46adcdb4db08a93285c..58b267e0d11d91e53404b4af1ea42d361b9011e9 100644 (file)
@@ -884,4 +884,56 @@ let {{
 
     class Zext(RegOp):
         code = 'DestReg = bits(psrc1, op2, 0);'
+
+    class Wrcr(RegOp):
+        def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
+            super(Wrcr, self).__init__(dest, \
+                    src1, "NUM_INTREGS", flags, dataSize)
+        code = '''
+            if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) {
+                fault = new InvalidOpcode();
+            } else {
+                // There are *s in the line below so it doesn't confuse the
+                // parser. They may be unnecessary.
+                //Mis*cReg old*Val = pick(Cont*rolDest, 0, dat*aSize);
+                MiscReg newVal = psrc1;
+
+                // Check for any modifications that would cause a fault.
+                switch(dest) {
+                  case 0:
+                    {
+                        Efer efer = EferOp;
+                        CR0 cr0 = newVal;
+                        CR4 oldCr4 = CR4Op;
+                        if (bits(newVal, 63, 32) ||
+                                (!cr0.pe && cr0.pg) ||
+                                (!cr0.cd && cr0.nw) ||
+                                (cr0.pg && efer.lme && !oldCr4.pae))
+                            fault = new GeneralProtection(0);
+                    }
+                    break;
+                  case 2:
+                    break;
+                  case 3:
+                    break;
+                  case 4:
+                    {
+                        CR4 cr4 = newVal;
+                        // PAE can't be disabled in long mode.
+                        if (bits(newVal, 63, 11) ||
+                                (machInst.mode.mode == LongMode && !cr4.pae))
+                            fault = new GeneralProtection(0);
+                    }
+                    break;
+                  case 8:
+                    {
+                        if (bits(newVal, 63, 4))
+                            fault = new GeneralProtection(0);
+                    }
+                  default:
+                    panic("Unrecognized control register %d.\\n", dest);
+                }
+                ControlDest = newVal;
+            }
+            '''
 }};
index 8c0eacca202c3dde854b77bbedbda9e2bd1a5eac..542638eddf9e6f70a49775eca8999e9c1c3f4811 100644 (file)
@@ -122,5 +122,9 @@ def operands {{
         # instructions don't map their indexes with an old value.
         'TOP':           ('ControlReg', 'ub', 'MISCREG_X87_TOP', None, 61),
         'SegBase':       ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(segment)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 70),
+        'ControlDest':   ('ControlReg', 'uqw', 'MISCREG_CR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 71),
+        'ControlSrc1':   ('ControlReg', 'uqw', 'MISCREG_CR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 72),
+        'EferOp':        ('ControlReg', 'uqw', 'MISCREG_EFER', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 73),
+        'CR4Op':         ('ControlReg', 'uqw', 'MISCREG_CR4', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 74),
         'Mem':           ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100)
 }};
index cf6b6ff868b5e83b73b362fcd039cc9eb07f63e0..3802d89490fc3a796fcb88a230d2be4a64663e03 100644 (file)
@@ -153,7 +153,13 @@ let {{
                 return doRipRelativeDecode(Name, opTypes, env)
             elif opType.tag == None or opType.size == None:
                 raise Exception, "Problem parsing operand tag: %s" % opType.tag
-            elif opType.tag in ("C", "D", "G", "P", "S", "T", "V"):
+            elif opType.tag == "C":
+                env.addReg(ModRMRegIndex)
+                Name += "_C"
+            elif opType.tag == "D":
+                env.addReg(ModRMRegIndex)
+                Name += "_D"
+            elif opType.tag in ("G", "P", "S", "T", "V"):
                 # Use the "reg" field of the ModRM byte to select the register
                 env.addReg(ModRMRegIndex)
                 Name += "_R"
index cd76e96aae8a5f7cbd59de18fb059127acdeb170..a6aed336fb2b70169ed8ff3adbdd13d2201b2d98 100644 (file)
@@ -106,22 +106,15 @@ void MiscRegFile::clear()
 
 MiscReg MiscRegFile::readRegNoEffect(int miscReg)
 {
-    switch(miscReg)
-    {
-      case MISCREG_CR1:
-      case MISCREG_CR5:
-      case MISCREG_CR6:
-      case MISCREG_CR7:
-      case MISCREG_CR9:
-      case MISCREG_CR10:
-      case MISCREG_CR11:
-      case MISCREG_CR12:
-      case MISCREG_CR13:
-      case MISCREG_CR14:
-      case MISCREG_CR15:
-        panic("Tried to read invalid control register %d\n", miscReg);
-        break;
-    }
+    // Make sure we're not dealing with an illegal control register.
+    // Instructions should filter out these indexes, and nothing else should
+    // attempt to read them directly.
+    assert( miscReg != MISCREG_CR1 &&
+            !(miscReg > MISCREG_CR4 &&
+              miscReg < MISCREG_CR8) &&
+            !(miscReg > MISCREG_CR8 &&
+              miscReg <= MISCREG_CR15));
+
     return regVal[miscReg];
 }
 
@@ -132,22 +125,14 @@ MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc)
 
 void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val)
 {
-    switch(miscReg)
-    {
-      case MISCREG_CR1:
-      case MISCREG_CR5:
-      case MISCREG_CR6:
-      case MISCREG_CR7:
-      case MISCREG_CR9:
-      case MISCREG_CR10:
-      case MISCREG_CR11:
-      case MISCREG_CR12:
-      case MISCREG_CR13:
-      case MISCREG_CR14:
-      case MISCREG_CR15:
-        panic("Tried to write invalid control register %d\n", miscReg);
-        break;
-    }
+    // Make sure we're not dealing with an illegal control register.
+    // Instructions should filter out these indexes, and nothing else should
+    // attempt to write to them directly.
+    assert( miscReg != MISCREG_CR1 &&
+            !(miscReg > MISCREG_CR4 &&
+              miscReg < MISCREG_CR8) &&
+            !(miscReg > MISCREG_CR8 &&
+              miscReg <= MISCREG_CR15));
     regVal[miscReg] = val;
 }
 
@@ -158,23 +143,33 @@ void MiscRegFile::setReg(int miscReg,
     switch(miscReg)
     {
       case MISCREG_CR0:
-        CR0 toggled = regVal[miscReg] ^ val;
-        CR0 newCR0 = val;
-        Efer efer = regVal[MISCREG_EFER];
-        if (toggled.pg && efer.lme) {
-            if (newCR0.pg) {
-                //Turning on long mode
-                efer.lma = 1;
-                regVal[MISCREG_EFER] = efer;
-            } else {
-                //Turning off long mode
-                efer.lma = 0;
-                regVal[MISCREG_EFER] = efer;
+        {
+            CR0 toggled = regVal[miscReg] ^ val;
+            CR0 newCR0 = val;
+            Efer efer = regVal[MISCREG_EFER];
+            if (toggled.pg && efer.lme) {
+                if (newCR0.pg) {
+                    //Turning on long mode
+                    efer.lma = 1;
+                    regVal[MISCREG_EFER] = efer;
+                } else {
+                    //Turning off long mode
+                    efer.lma = 0;
+                    regVal[MISCREG_EFER] = efer;
+                }
             }
+            //This must always be 1.
+            newCR0.et = 1;
+            newVal = newCR0;
         }
-        //This must always be 1.
-        newCR0.et = 1;
-        newVal = newCR0;
+        break;
+      case MISCREG_CR2:
+        break;
+      case MISCREG_CR3:
+        break;
+      case MISCREG_CR4:
+        break;
+      case MISCREG_CR8:
         break;
     }
     setRegNoEffect(miscReg, newVal);