x86 fixes
[gem5.git] / src / arch / x86 / isa / microops / regop.isa
index 52c13231cf7ced0820bc1199bab0a1c0e85a8169..f833f89be3a6c0202aa87f1c8df8e9a3f7862533 100644 (file)
@@ -67,7 +67,16 @@ def template MicroRegOpExecute {{
 
             %(op_decl)s;
             %(op_rd)s;
-            %(code)s;
+
+            if(%(cond_check)s)
+            {
+                %(code)s;
+                %(flag_code)s;
+            }
+            else
+            {
+                %(else_code)s;
+            }
 
             //Write the resulting state to the execution context
             if(fault == NoFault)
@@ -86,7 +95,16 @@ def template MicroRegOpImmExecute {{
 
             %(op_decl)s;
             %(op_rd)s;
-            %(code)s;
+
+            if(%(cond_check)s)
+            {
+                %(code)s;
+                %(flag_code)s;
+            }
+            else
+            {
+                %(else_code)s;
+            }
 
             //Write the resulting state to the execution context
             if(fault == NoFault)
@@ -101,12 +119,6 @@ def template MicroRegOpDeclare {{
     class %(class_name)s : public %(base_class)s
     {
       protected:
-        const RegIndex src1;
-        const RegIndex src2;
-        const RegIndex dest;
-        const bool setStatus;
-        const uint8_t dataSize;
-        const uint8_t ext;
         void buildMe();
 
       public:
@@ -114,12 +126,12 @@ def template MicroRegOpDeclare {{
                 const char * instMnem,
                 bool isMicro, bool isDelayed, bool isFirst, bool isLast,
                 RegIndex _src1, RegIndex _src2, RegIndex _dest,
-                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
+                uint8_t _dataSize, uint16_t _ext);
 
         %(class_name)s(ExtMachInst _machInst,
                 const char * instMnem,
                 RegIndex _src1, RegIndex _src2, RegIndex _dest,
-                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
+                uint8_t _dataSize, uint16_t _ext);
 
         %(BasicExecDeclare)s
     };
@@ -130,12 +142,6 @@ def template MicroRegOpImmDeclare {{
     class %(class_name)sImm : public %(base_class)s
     {
       protected:
-        const RegIndex src1;
-        const uint8_t imm8;
-        const RegIndex dest;
-        const bool setStatus;
-        const uint8_t dataSize;
-        const uint8_t ext;
         void buildMe();
 
       public:
@@ -143,12 +149,12 @@ def template MicroRegOpImmDeclare {{
                 const char * instMnem,
                 bool isMicro, bool isDelayed, bool isFirst, bool isLast,
                 RegIndex _src1, uint8_t _imm8, RegIndex _dest,
-                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
+                uint8_t _dataSize, uint16_t _ext);
 
         %(class_name)sImm(ExtMachInst _machInst,
                 const char * instMnem,
                 RegIndex _src1, uint8_t _imm8, RegIndex _dest,
-                bool _setStatus, uint8_t _dataSize, uint8_t _ext);
+                uint8_t _dataSize, uint16_t _ext);
 
         %(BasicExecDeclare)s
     };
@@ -164,11 +170,11 @@ def template MicroRegOpConstructor {{
     inline %(class_name)s::%(class_name)s(
             ExtMachInst machInst, const char * instMnem,
             RegIndex _src1, RegIndex _src2, RegIndex _dest,
-            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
+            uint8_t _dataSize, uint16_t _ext) :
         %(base_class)s(machInst, "%(mnemonic)s", instMnem,
-                false, false, false, false, %(op_class)s),
-                src1(_src1), src2(_src2), dest(_dest),
-                setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
+                false, false, false, false,
+                _src1, _src2, _dest, _dataSize, _ext,
+                %(op_class)s)
     {
         buildMe();
     }
@@ -177,11 +183,11 @@ def template MicroRegOpConstructor {{
             ExtMachInst machInst, const char * instMnem,
             bool isMicro, bool isDelayed, bool isFirst, bool isLast,
             RegIndex _src1, RegIndex _src2, RegIndex _dest,
-            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
+            uint8_t _dataSize, uint16_t _ext) :
         %(base_class)s(machInst, "%(mnemonic)s", instMnem,
-                isMicro, isDelayed, isFirst, isLast, %(op_class)s),
-                src1(_src1), src2(_src2), dest(_dest),
-                setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
+                isMicro, isDelayed, isFirst, isLast,
+                _src1, _src2, _dest, _dataSize, _ext,
+                %(op_class)s)
     {
         buildMe();
     }
@@ -197,11 +203,11 @@ def template MicroRegOpImmConstructor {{
     inline %(class_name)sImm::%(class_name)sImm(
             ExtMachInst machInst, const char * instMnem,
             RegIndex _src1, uint8_t _imm8, RegIndex _dest,
-            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
+            uint8_t _dataSize, uint16_t _ext) :
         %(base_class)s(machInst, "%(mnemonic)s", instMnem,
-                false, false, false, false, %(op_class)s),
-                src1(_src1), imm8(_imm8), dest(_dest),
-                setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
+                false, false, false, false,
+                _src1, _imm8, _dest, _dataSize, _ext,
+                %(op_class)s)
     {
         buildMe();
     }
@@ -210,60 +216,88 @@ def template MicroRegOpImmConstructor {{
             ExtMachInst machInst, const char * instMnem,
             bool isMicro, bool isDelayed, bool isFirst, bool isLast,
             RegIndex _src1, uint8_t _imm8, RegIndex _dest,
-            bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
+            uint8_t _dataSize, uint16_t _ext) :
         %(base_class)s(machInst, "%(mnemonic)s", instMnem,
-                isMicro, isDelayed, isFirst, isLast, %(op_class)s),
-                src1(_src1), imm8(_imm8), dest(_dest),
-                setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
+                isMicro, isDelayed, isFirst, isLast,
+                _src1, _imm8, _dest, _dataSize, _ext,
+                %(op_class)s)
     {
         buildMe();
     }
 }};
 
 let {{
+    class X86MicroMeta(type):
+        def __new__(mcls, name, bases, dict):
+            abstract = False
+            if "abstract" in dict:
+                abstract = dict['abstract']
+                del dict['abstract']
+
+            cls = type.__new__(mcls, name, bases, dict)
+            if not abstract:
+                allClasses[name] = cls
+            return cls
+
+    class XXX86Microop(object):
+        __metaclass__ = X86MicroMeta
+        abstract = True
+
     class RegOp(X86Microop):
-        def __init__(self, dest, src1, src2):
+        abstract = True
+        def __init__(self, dest, src1, src2, flags, dataSize):
             self.dest = dest
             self.src1 = src1
             self.src2 = src2
-            self.setStatus = False
-            self.dataSize = 1
-            self.ext = 0
+            self.flags = flags
+            self.dataSize = dataSize
+            if flags is None:
+                self.ext = 0
+            else:
+                if not isinstance(flags, (list, tuple)):
+                    raise Exception, "flags must be a list or tuple of flags"
+                self.ext = " | ".join(flags)
+                self.className += "Flags"
 
         def getAllocator(self, *microFlags):
-            allocator = '''new %(class_name)s(machInst, %(mnemonic)s,
-                    %(flags)s %(src1)s, %(src2)s, %(dest)s,
-                    %(setStatus)s, %(dataSize)s, %(ext)s)''' % {
+            allocator = '''new %(class_name)s(machInst, mnemonic
+                    %(flags)s, %(src1)s, %(src2)s, %(dest)s,
+                    %(dataSize)s, %(ext)s)''' % {
                 "class_name" : self.className,
-                "mnemonic" : self.mnemonic,
                 "flags" : self.microFlagsText(microFlags),
                 "src1" : self.src1, "src2" : self.src2,
                 "dest" : self.dest,
-                "setStatus" : self.setStatus,
                 "dataSize" : self.dataSize,
                 "ext" : self.ext}
+            return allocator
 
     class RegOpImm(X86Microop):
-        def __init__(self, dest, src1, imm):
+        abstract = True
+        def __init__(self, dest, src1, imm8, flags, dataSize):
             self.dest = dest
             self.src1 = src1
-            self.imm = imm
-            self.setStatus = False
-            self.dataSize = 1
-            self.ext = 0
+            self.imm8 = imm8
+            self.flags = flags
+            self.dataSize = dataSize
+            if flags is None:
+                self.ext = 0
+            else:
+                if not isinstance(flags, (list, tuple)):
+                    raise Exception, "flags must be a list or tuple of flags"
+                self.ext = " | ".join(flags)
+                self.className += "Flags"
 
         def getAllocator(self, *microFlags):
-            allocator = '''new %(class_name)s(machInst, %(mnemonic)s,
-                    %(flags)s %(src1)s, %(imm8)s, %(dest)s,
-                    %(setStatus)s, %(dataSize)s, %(ext)s)''' % {
+            allocator = '''new %(class_name)s(machInst, mnemonic
+                    %(flags)s, %(src1)s, %(imm8)s, %(dest)s,
+                    %(dataSize)s, %(ext)s)''' % {
                 "class_name" : self.className,
-                "mnemonic" : self.mnemonic,
                 "flags" : self.microFlagsText(microFlags),
                 "src1" : self.src1, "imm8" : self.imm8,
                 "dest" : self.dest,
-                "setStatus" : self.setStatus,
                 "dataSize" : self.dataSize,
                 "ext" : self.ext}
+            return allocator
 }};
 
 let {{
@@ -274,11 +308,30 @@ let {{
     decoder_output = ""
     exec_output = ""
 
-    def defineMicroRegOp(mnemonic, code):
+    # A function which builds the C++ classes that implement the microops
+    def setUpMicroRegOp(name, Name, base, code, flagCode, condCheck, elseCode):
         global header_output
         global decoder_output
         global exec_output
         global microopClasses
+
+        iop = InstObjParams(name, Name, base,
+                {"code" : code,
+                 "flag_code" : flagCode,
+                 "cond_check" : condCheck,
+                 "else_code" : elseCode})
+        header_output += MicroRegOpDeclare.subst(iop)
+        decoder_output += MicroRegOpConstructor.subst(iop)
+        exec_output += MicroRegOpExecute.subst(iop)
+
+
+    checkCCFlagBits = "checkCondition(ccFlagBits)"
+    genCCFlagBits = "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, SrcReg1, %s);"
+
+
+    # This creates a python representations of a microop which are a cross
+    # product of reg/immediate and flag/no flag versions.
+    def defineMicroRegOp(mnemonic, code, secondSrc = "op2", cc=False, elseCode=";"):
         Name = mnemonic
         name = mnemonic.lower()
 
@@ -289,43 +342,119 @@ let {{
         regCode = matcher.sub("SrcReg2", code)
         immCode = matcher.sub("imm8", code)
 
-        # Build up the all register version of this micro op
-        iop = InstObjParams(name, Name, 'X86MicroOpBase', {"code" : regCode})
-        header_output += MicroRegOpDeclare.subst(iop)
-        decoder_output += MicroRegOpConstructor.subst(iop)
-        exec_output += MicroRegOpExecute.subst(iop)
+        if not cc:
+            flagCode = genCCFlagBits % secondSrc
+            condCode = "true"
+        else:
+            flagCode = ""
+            condCode = checkCCFlagBits
+
+        regFlagCode = matcher.sub("SrcReg2", flagCode)
+        immFlagCode = matcher.sub("imm8", flagCode)
 
         class RegOpChild(RegOp):
-            def __init__(self, dest, src1, src2):
-                super(RegOpChild, self).__init__(dest, src1, src2)
-                self.className = Name
-                self.mnemonic = name
+            mnemonic = name
+            className = Name
+            def __init__(self, dest, src1, src2, flags=None, dataSize="env.dataSize"):
+                super(RegOpChild, self).__init__(dest, src1, src2, flags, dataSize)
 
         microopClasses[name] = RegOpChild
 
-        # Build up the immediate version of this micro op
-        iop = InstObjParams(name + "i", Name,
-                'X86MicroOpBase', {"code" : immCode})
-        header_output += MicroRegOpImmDeclare.subst(iop)
-        decoder_output += MicroRegOpImmConstructor.subst(iop)
-        exec_output += MicroRegOpImmExecute.subst(iop)
+        setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode, "", "true", elseCode);
+        setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", regCode, regFlagCode, condCode, elseCode);
 
-        class RegOpImmChild(RegOpImm):
-            def __init__(self, dest, src1, imm):
-                super(RegOpImmChild, self).__init__(dest, src1, imm)
-                self.className = Name + "Imm"
-                self.mnemonic = name + "i"
+        class RegOpChildImm(RegOpImm):
+            mnemonic = name + 'i'
+            className = Name + 'Imm'
+            def __init__(self, dest, src1, src2, flags=None, dataSize="env.dataSize"):
+                super(RegOpChildImm, self).__init__(dest, src1, src2, flags, dataSize)
 
-        microopClasses[name + "i"] = RegOpChild
+        microopClasses[name + 'i'] = RegOpChildImm
 
-    defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') #Needs to set OF,CF,SF
+        setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", immCode, "", "true", elseCode);
+        setUpMicroRegOp(name + "i", Name + "ImmFlags", "X86ISA::RegOpImm", immCode, immFlagCode, condCode, elseCode);
+
+    defineMicroRegOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)')
     defineMicroRegOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)')
-    defineMicroRegOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') #Needs to add in CF, set OF,CF,SF
-    defineMicroRegOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)') #Needs to subtract CF, set OF,CF,SF
+    defineMicroRegOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)')
+    defineMicroRegOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', '-op2')
     defineMicroRegOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)')
-    defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)') #Needs to set OF,CF,SF
+    defineMicroRegOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)', '-op2')
     defineMicroRegOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)')
-    defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)') #Needs to set OF,CF,SF and not DestReg
-    defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)')
+    defineMicroRegOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)', '-op2')
+    defineMicroRegOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)',
+            elseCode='DestReg=DestReg;', cc=True)
+
+    # This has it's own function because Wr ops have implicit destinations
+    def defineMicroRegOpWr(mnemonic, code, elseCode=";"):
+        Name = mnemonic
+        name = mnemonic.lower()
+
+        # Find op2 in each of the instruction definitions. Create two versions
+        # of the code, one with an integer operand, and one with an immediate
+        # operand.
+        matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
+        regCode = matcher.sub("SrcReg2", code)
+        immCode = matcher.sub("imm8", code)
+
+        class RegOpChild(RegOp):
+            mnemonic = name
+            className = Name
+            def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"):
+                super(RegOpChild, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize)
+
+        microopClasses[name] = RegOpChild
+
+        setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode, "", "true", elseCode);
+        setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", regCode, "", checkCCFlagBits, elseCode);
+
+        class RegOpChildImm(RegOpImm):
+            mnemonic = name + 'i'
+            className = Name + 'Imm'
+            def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"):
+                super(RegOpChildImm, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize)
+
+        microopClasses[name + 'i'] = RegOpChildImm
+
+        setUpMicroRegOp(name + 'i', Name + "Imm", "X86ISA::RegOpImm", immCode, "", "true", elseCode);
+        setUpMicroRegOp(name + 'i', Name + "ImmFlags", "X86ISA::RegOpImm", immCode, "", checkCCFlagBits, elseCode);
+
+    defineMicroRegOpWr('Wrip', 'RIP = SrcReg1 + op2', elseCode="RIP = RIP;")
+
+    # This has it's own function because Rd ops don't always have two parameters
+    def defineMicroRegOpRd(mnemonic, code):
+        Name = mnemonic
+        name = mnemonic.lower()
+
+        class RegOpChild(RegOp):
+            def __init__(self, dest, src1 = "NUM_INTREGS", dataSize="env.dataSize"):
+                super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize)
+                self.className = Name
+                self.mnemonic = name
+
+        microopClasses[name] = RegOpChild
+
+        setUpMicroRegOp(name, Name, "X86ISA::RegOp", code, "", "true", ";");
+
+    defineMicroRegOpRd('Rdip', 'DestReg = RIP')
+
+    def defineMicroRegOpImm(mnemonic, code):
+        Name = mnemonic
+        name = mnemonic.lower()
+
+        class RegOpChild(RegOpImm):
+            def __init__(self, dest, src1, src2, dataSize="env.dataSize"):
+                super(RegOpChild, self).__init__(dest, src1, src2, None, dataSize)
+                self.className = Name
+                self.mnemonic = name
+
+        microopClasses[name] = RegOpChild
+
+        setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code, "", "true", ";");
 
+    defineMicroRegOpImm('Sext', '''
+            IntReg val = SrcReg1;
+            int sign_bit = bits(val, imm8-1, imm8-1);
+            val = sign_bit ? (val | ~mask(imm8)) : val;
+            DestReg = merge(DestReg, val, dataSize);''')
 }};