X86: Use IsSquashAfter if an instruction could affect fetch translation.
authorGabe Black <gblack@eecs.umich.edu>
Sun, 14 Aug 2011 06:03:11 +0000 (23:03 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Sun, 14 Aug 2011 06:03:11 +0000 (23:03 -0700)
Control register operands are set up so that writing to them is serialize
after, serialize before, and non-speculative. These are probably overboard,
but they should usually be safe. Unfortunately there are times when even these
aren't enough. If an instruction modifies state that affects fetch, later
serialized instructions which come after it might have already gone through
fetch and decode by the time it commits. These instructions may have been
translated incorrectly or interpretted incorrectly and need to be destroyed.
This change modifies instructions which will or may have this behavior so that
they use the IsSquashAfter flag when necessary.

src/arch/x86/isa/operands.isa

index aedfedc0c9f4b7162985a6e6a2bfa374b0e1757b..e0ace11d042ef357f4b506ac49a79278d47669d7 100644 (file)
@@ -67,6 +67,19 @@ let {{
                               'IsSerializing',
                               'IsNonSpeculative']),
                 id)
+    def squashCheckReg(idx, id, check, ctype = 'uqw'):
+        return ('ControlReg', ctype, idx,
+                (None, None, ['((%s) ? ' % check+ \
+                                'IsSquashAfter : IsSerializeAfter)',
+                              'IsSerializing',
+                              'IsNonSpeculative']),
+                id)
+    def squashCReg(idx, id, ctype = 'uqw'):
+        return squashCheckReg(idx, id, 'true', ctype)
+    def squashCSReg(idx, id, ctype = 'uqw'):
+        return squashCheckReg(idx, id, 'dest == SEGMENT_REG_CS', ctype)
+    def squashCR0Reg(idx, id, ctype = 'uqw'):
+        return squashCheckReg(idx, id, 'dest == 0', ctype)
 }};
 
 def operands {{
@@ -115,21 +128,21 @@ def operands {{
 
         # Operands to get and set registers indexed by the operands of the
         # original instruction.
-        'ControlDest':   controlReg('MISCREG_CR(dest)', 100),
+        'ControlDest':   squashCR0Reg('MISCREG_CR(dest)', 100),
         'ControlSrc1':   controlReg('MISCREG_CR(src1)', 101),
         'DebugDest':     controlReg('MISCREG_DR(dest)', 102),
         'DebugSrc1':     controlReg('MISCREG_DR(src1)', 103),
-        'SegBaseDest':   controlReg('MISCREG_SEG_BASE(dest)', 104),
+        'SegBaseDest':   squashCSReg('MISCREG_SEG_BASE(dest)', 104),
         'SegBaseSrc1':   controlReg('MISCREG_SEG_BASE(src1)', 105),
-        'SegLimitDest':  controlReg('MISCREG_SEG_LIMIT(dest)', 106),
+        'SegLimitDest':  squashCSReg('MISCREG_SEG_LIMIT(dest)', 106),
         'SegLimitSrc1':  controlReg('MISCREG_SEG_LIMIT(src1)', 107),
         'SegSelDest':    controlReg('MISCREG_SEG_SEL(dest)', 108),
         'SegSelSrc1':    controlReg('MISCREG_SEG_SEL(src1)', 109),
-        'SegAttrDest':   controlReg('MISCREG_SEG_ATTR(dest)', 110),
+        'SegAttrDest':   squashCSReg('MISCREG_SEG_ATTR(dest)', 110),
         'SegAttrSrc1':   controlReg('MISCREG_SEG_ATTR(src1)', 111),
 
         # Operands to access specific control registers directly.
-        'EferOp':        controlReg('MISCREG_EFER', 200),
+        'EferOp':        squashCReg('MISCREG_EFER', 200),
         'CR4Op':         controlReg('MISCREG_CR4', 201),
         'DR7Op':         controlReg('MISCREG_DR7', 202),
         'LDTRBase':      controlReg('MISCREG_TSL_BASE', 203),
@@ -137,12 +150,12 @@ def operands {{
         'LDTRSel':       controlReg('MISCREG_TSL', 205),
         'GDTRBase':      controlReg('MISCREG_TSG_BASE', 206),
         'GDTRLimit':     controlReg('MISCREG_TSG_LIMIT', 207),
-        'CSBase':        controlReg('MISCREG_CS_EFF_BASE', 208),
-        'CSAttr':        controlReg('MISCREG_CS_ATTR', 209),
+        'CSBase':        squashCReg('MISCREG_CS_EFF_BASE', 208),
+        'CSAttr':        squashCReg('MISCREG_CS_ATTR', 209),
         'MiscRegDest':   controlReg('dest', 210),
         'MiscRegSrc1':   controlReg('src1', 211),
         'TscOp':         controlReg('MISCREG_TSC', 212),
-        'M5Reg':         controlReg('MISCREG_M5_REG', 213),
+        'M5Reg':         squashCReg('MISCREG_M5_REG', 213),
         'Mem':           ('Mem', 'uqw', None, \
                           ('IsMemRef', 'IsLoad', 'IsStore'), 300)
 }};