X86: Major rework of how regop microops are generated.
authorGabe Black <gblack@eecs.umich.edu>
Sat, 1 Sep 2007 05:28:07 +0000 (22:28 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Sat, 1 Sep 2007 05:28:07 +0000 (22:28 -0700)
The new implementation uses metaclass, and gives a lot more precise control
with a lot less verbosity. The flags/no flags reg/imm variants are all handled
by the same python class now which supplies a constructor to the right C++
class based on context.

--HG--
extra : convert_revision : 712e3ec6de7a5a038da083f79635fd7a687d56e5

src/arch/x86/isa/macroop.isa
src/arch/x86/isa/microops/base.isa
src/arch/x86/isa/microops/regop.isa

index fdfea6136470942440d4917e9e49cfd24b75a2a1..3f33c8cfe7e2d4d9fabfef5e1782f39f8dbf37c9 100644 (file)
@@ -153,7 +153,8 @@ def template MacroConstructor {{
 let {{
     from micro_asm import Combinational_Macroop, Rom_Macroop
     class X86Macroop(Combinational_Macroop):
-        def add_microop(self, microop):
+        def add_microop(self, mnemonic, microop):
+            microop.mnemonic = mnemonic
             microop.micropc = len(self.microops)
             self.microops.append(microop)
         def setAdjustEnv(self, val):
index 71fc3b3a55c03dc8dd95fbc005dc2a4c48bb65cf..9722f182e07f3babb9acc4c93204c64310524632 100644 (file)
@@ -69,6 +69,7 @@ let {{
 
 let {{
     class X86Microop(object):
+
         def __init__(self, name):
             self.name = name
 
@@ -88,7 +89,8 @@ let {{
             return text
 
         def getAllocator(self, mnemonic, *microFlags):
-            return 'new %s(machInst, %s)' % (self.className, mnemonic, self.microFlagsText(microFlags))
+            return 'new %s(machInst, %s)' % \
+                (self.className, mnemonic, self.microFlagsText(microFlags))
 }};
 
 //////////////////////////////////////////////////////////////////////////
index eca640d35a33d5385bee66361389f91a0f34fe84..a0477dab772ba5fe56363beb538fe6ae7259abcf 100644 (file)
@@ -228,28 +228,137 @@ def template MicroRegOpImmConstructor {{
 }};
 
 let {{
-    class X86MicroMeta(type):
-        def __new__(mcls, name, bases, dict):
+    # Make these empty strings so that concatenating onto
+    # them will always work.
+    header_output = ""
+    decoder_output = ""
+    exec_output = ""
+
+    immTemplates = (
+            MicroRegOpImmDeclare,
+            MicroRegOpImmConstructor,
+            MicroRegOpImmExecute)
+
+    regTemplates = (
+            MicroRegOpDeclare,
+            MicroRegOpConstructor,
+            MicroRegOpExecute)
+
+    class RegOpMeta(type):
+        def buildCppClasses(self, name, Name, suffix, \
+                code, flag_code, cond_check, else_code):
+
+            # Globals to stick the output in
+            global header_output
+            global decoder_output
+            global exec_output
+
+            # Stick all the code together so it can be searched at once
+            allCode = "|".join((code, flag_code, cond_check, else_code))
+
+            # If op2 is used anywhere, make register and immediate versions
+            # of this code.
+            matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
+            if matcher.search(allCode):
+                self.buildCppClasses(name, Name, suffix,
+                        matcher.sub("psrc2", code),
+                        matcher.sub("psrc2", flag_code),
+                        matcher.sub("psrc2", cond_check),
+                        matcher.sub("psrc2", else_code))
+                self.buildCppClasses(name + "i", Name, suffix + "Imm",
+                        matcher.sub("imm8", code),
+                        matcher.sub("imm8", flag_code),
+                        matcher.sub("imm8", cond_check),
+                        matcher.sub("imm8", else_code))
+                return
+
+            # If there's something optional to do with flags, generate
+            # a version without it and fix up this version to use it.
+            if flag_code is not "" or cond_check is not "true":
+                self.buildCppClasses(name, Name, suffix,
+                        code, "", "true", else_code)
+                suffix = "Flags" + suffix
+
+            # If psrc1 or psrc2 is used, we need to actually insert code to
+            # compute it.
+            matcher = re.compile("(?<!\w)psrc1(?!\w)")
+            if matcher.search(allCode):
+                code = "IntReg psrc1 = pick(SrcReg1, 0, dataSize);" + code
+            matcher = re.compile("(?<!\w)psrc2(?!\w)")
+            if matcher.search(allCode):
+                code = "IntReg psrc2 = pick(SrcReg2, 1, dataSize);" + code
+
+            base = "X86ISA::RegOp"
+
+            # If imm8 shows up in the code, use the immediate templates, if
+            # not, hopefully the register ones will be correct.
+            templates = regTemplates
+            matcher = re.compile("(?<!\w)imm8(?!\w)")
+            if matcher.search(allCode):
+                base += "Imm"
+                templates = immTemplates
+
+            # Get everything ready for the substitution
+            iop = InstObjParams(name, Name + suffix, base,
+                    {"code" : code,
+                     "flag_code" : flag_code,
+                     "cond_check" : cond_check,
+                     "else_code" : else_code})
+
+            # Generate the actual code (finally!)
+            header_output += templates[0].subst(iop)
+            decoder_output += templates[1].subst(iop)
+            exec_output += templates[2].subst(iop)
+
+
+        def __new__(mcls, Name, bases, dict):
             abstract = False
+            name = Name.lower()
             if "abstract" in dict:
                 abstract = dict['abstract']
                 del dict['abstract']
 
-            cls = type.__new__(mcls, name, bases, dict)
+            cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict)
             if not abstract:
-                allClasses[name] = cls
+                cls.className = Name
+                cls.base_mnemonic = name
+                code = cls.code
+                flag_code = cls.flag_code
+                cond_check = cls.cond_check
+                else_code = cls.else_code
+
+                # Set up the C++ classes
+                mcls.buildCppClasses(cls, name, Name, "",
+                        code, flag_code, cond_check, else_code)
+
+                # Hook into the microassembler dict
+                global microopClasses
+                microopClasses[name] = cls
+
+                allCode = "|".join((code, flag_code, cond_check, else_code))
+
+                # If op2 is used anywhere, make register and immediate versions
+                # of this code.
+                matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
+                if matcher.search(allCode):
+                    microopClasses[name + 'i'] = cls
             return cls
 
-    class XXX86Microop(object):
-        __metaclass__ = X86MicroMeta
-        abstract = True
 
     class RegOp(X86Microop):
+        __metaclass__ = RegOpMeta
+        # This class itself doesn't act as a microop
         abstract = True
-        def __init__(self, dest, src1, src2, flags, dataSize):
+
+        # Default template parameter values
+        flag_code = ""
+        cond_check = "true"
+        else_code = ";"
+
+        def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"):
             self.dest = dest
             self.src1 = src1
-            self.src2 = src2
+            self.op2 = op2
             self.flags = flags
             self.dataSize = dataSize
             if flags is None:
@@ -261,280 +370,93 @@ let {{
                 self.className += "Flags"
 
         def getAllocator(self, *microFlags):
+            className = self.className
+            if self.mnemonic == self.base_mnemonic + 'i':
+                className += "Imm"
             allocator = '''new %(class_name)s(machInst, mnemonic
-                    %(flags)s, %(src1)s, %(src2)s, %(dest)s,
+                    %(flags)s, %(src1)s, %(op2)s, %(dest)s,
                     %(dataSize)s, %(ext)s)''' % {
-                "class_name" : self.className,
+                "class_name" : className,
                 "flags" : self.microFlagsText(microFlags),
-                "src1" : self.src1, "src2" : self.src2,
+                "src1" : self.src1, "op2" : self.op2,
                 "dest" : self.dest,
                 "dataSize" : self.dataSize,
                 "ext" : self.ext}
             return allocator
 
-    class RegOpImm(X86Microop):
+    class LogicRegOp(RegOp):
         abstract = True
-        def __init__(self, dest, src1, imm8, flags, dataSize):
-            self.dest = dest
-            self.src1 = src1
-            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"
+        flag_code = '''
+            //Don't have genFlags handle the OF or CF bits
+            uint64_t mask = CFBit | OFBit;
+            ccFlagBits = genFlags(ccFlagBits, ext & ~mask, DestReg, psrc1, op2);
+            //If a logic microop wants to set these, it wants to set them to 0.
+            ccFlagBits &= ~(CFBit & ext);
+            ccFlagBits &= ~(OFBit & ext);
+        '''
+
+    class FlagRegOp(RegOp):
+        abstract = True
+        flag_code = \
+            "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);"
 
-        def getAllocator(self, *microFlags):
-            allocator = '''new %(class_name)s(machInst, mnemonic
-                    %(flags)s, %(src1)s, %(imm8)s, %(dest)s,
-                    %(dataSize)s, %(ext)s)''' % {
-                "class_name" : self.className,
-                "flags" : self.microFlagsText(microFlags),
-                "src1" : self.src1, "imm8" : self.imm8,
-                "dest" : self.dest,
-                "dataSize" : self.dataSize,
-                "ext" : self.ext}
-            return allocator
-}};
+    class SubRegOp(RegOp):
+        abstract = True
+        flag_code = \
+            "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);"
 
-let {{
+    class CondRegOp(RegOp):
+        abstract = True
+        cond_check = "checkCondition(ccFlagBits)"
 
-    # Make these empty strings so that concatenating onto
-    # them will always work.
-    header_output = ""
-    decoder_output = ""
-    exec_output = ""
+    class Add(FlagRegOp):
+        code = 'DestReg = merge(DestReg, psrc1 + op2, dataSize);'
+
+    class Or(LogicRegOp):
+        code = 'DestReg = merge(DestReg, psrc1 | op2, dataSize);'
 
-    # A function which builds the C++ classes that implement the microops
-    def setUpMicroRegOp(name, Name, base, code, flagCode = "", condCheck = "true", elseCode = ";", imm=False):
-        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})
-        if imm:
-            header_output += MicroRegOpImmDeclare.subst(iop)
-            decoder_output += MicroRegOpImmConstructor.subst(iop)
-            exec_output += MicroRegOpImmExecute.subst(iop)
-        else:
-            header_output += MicroRegOpDeclare.subst(iop)
-            decoder_output += MicroRegOpConstructor.subst(iop)
-            exec_output += MicroRegOpExecute.subst(iop)
-
-
-    checkCCFlagBits = "checkCondition(ccFlagBits)"
-    genCCFlagBits = \
-        "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);"
-    genCCFlagBitsSub = \
-        "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);"
-    genCCFlagBitsLogic = '''
-        //Don't have genFlags handle the OF or CF bits
-        uint64_t mask = CFBit | OFBit;
-        ccFlagBits = genFlags(ccFlagBits, ext & ~mask, DestReg, psrc1, op2);
-        //If a logic microop wants to set these, it wants to set them to 0.
-        ccFlagBits &= ~(CFBit & ext);
-        ccFlagBits &= ~(OFBit & ext);
-    '''
-
-    regPick = '''
-        IntReg psrc1 = pick(SrcReg1, 0, dataSize);
-        IntReg psrc2 = pick(SrcReg2, 1, dataSize);
-    '''
-    immPick = '''
-        IntReg psrc1 = pick(SrcReg1, 0, dataSize);
-    '''
-
-
-    # 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, flagCode=genCCFlagBits, \
-            cc=False, doImm=True, 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 = regPick + matcher.sub("psrc2", code)
-        immCode = immPick + matcher.sub("imm8", code)
-
-        if not cc:
-            condCode = "true"
-        else:
-            flagCode = ""
-            condCode = checkCCFlagBits
-
-        regFlagCode = matcher.sub("psrc2", flagCode)
-        immFlagCode = matcher.sub("imm8", flagCode)
-
-        class RegOpChild(RegOp):
-            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
-
-        setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode);
-        setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp",
-                regCode, flagCode=regFlagCode,
-                condCheck=condCode, elseCode=elseCode);
-
-        if doImm:
-            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'] = RegOpChildImm
-
-            setUpMicroRegOp(name + "i", Name + "Imm", "X86ISA::RegOpImm", \
-                    immCode, imm=True);
-            setUpMicroRegOp(name + "i", Name + "ImmFlags", "X86ISA::RegOpImm",
-                    immCode, flagCode=immFlagCode,
-                    condCheck=condCode, elseCode=elseCode, imm=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 = regPick + matcher.sub("psrc2", code)
-        immCode = immPick + 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);
-        setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", regCode,
-                condCheck = checkCCFlagBits, elseCode = 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, imm=True);
-        setUpMicroRegOp(name + 'i', Name + "ImmFlags", "X86ISA::RegOpImm", \
-                immCode, condCheck = checkCCFlagBits, elseCode = elseCode, \
-                imm=True);
-
-    # 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):
-            className = Name
-            mnemonic = name
-            def __init__(self, dest, src1 = "NUM_INTREGS", dataSize="env.dataSize"):
-                super(RegOpChild, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize)
-
-        microopClasses[name] = RegOpChild
-
-        setUpMicroRegOp(name, Name, "X86ISA::RegOp", code);
-
-    def defineMicroRegOpImm(mnemonic, code, flagCode=""):
-        Name = mnemonic
-        name = mnemonic.lower()
-        code = immPick + code
-
-        class RegOpChild(RegOpImm):
-            className = Name
-            mnemonic = name
-            def __init__(self, dest, src1, src2, \
-                    flags=None, dataSize="env.dataSize"):
-                super(RegOpChild, self).__init__(dest, \
-                        src1, src2, flags, dataSize)
-
-        microopClasses[name] = RegOpChild
-
-        setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code, imm=True);
-        setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOpImm", \
-                code, flagCode=flagCode, imm=True);
-
-    def defineMicroRegOpRdImm(mnemonic, code, flagCode=""):
-        Name = mnemonic
-        name = mnemonic.lower()
-        code = immPick + code
-
-        class RegOpChildRdImm(RegOpImm):
-            className = Name
-            mnemonic = name
-            def __init__(self, dest, imm, flags=None, \
-                    dataSize="env.dataSize"):
-                super(RegOpChildRdImm, self).__init__(dest, \
-                        "NUM_INTREGS", imm, flags, dataSize)
-
-        microopClasses[name] = RegOpChildRdImm
-
-        setUpMicroRegOp(name, Name, "X86ISA::RegOpImm", code, imm=True);
-        setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOpImm", \
-                code, flagCode=flagCode, imm=True);
-
-    defineMicroRegOp('Add', 'DestReg = merge(DestReg, psrc1 + op2, dataSize)')
-    defineMicroRegOp('Or', 'DestReg = merge(DestReg, psrc1 | op2, dataSize);',
-            flagCode = genCCFlagBitsLogic)
-    defineMicroRegOp('Adc', '''
+    class Adc(FlagRegOp):
+        code = '''
             CCFlagBits flags = ccFlagBits;
             DestReg = merge(DestReg, psrc1 + op2 + flags.CF, dataSize);
-            ''')
-    defineMicroRegOp('Sbb', '''
+            '''
+
+    class Sbb(SubRegOp):
+        code = '''
             CCFlagBits flags = ccFlagBits;
             DestReg = merge(DestReg, psrc1 - op2 - flags.CF, dataSize);
-            ''', flagCode = genCCFlagBitsSub)
-    defineMicroRegOp('And', \
-            'DestReg = merge(DestReg, psrc1 & op2, dataSize)', \
-            flagCode = genCCFlagBitsLogic)
-    defineMicroRegOp('Sub', \
-            'DestReg = merge(DestReg, psrc1 - op2, dataSize)', \
-            flagCode = genCCFlagBitsSub)
-    defineMicroRegOp('Xor', \
-            'DestReg = merge(DestReg, psrc1 ^ op2, dataSize)', \
-            flagCode = genCCFlagBitsLogic)
-    defineMicroRegOp('Mul1s', '''
+            '''
+
+    class And(LogicRegOp):
+        code = 'DestReg = merge(DestReg, psrc1 & op2, dataSize)'
+
+    class Sub(SubRegOp):
+        code = 'DestReg = merge(DestReg, psrc1 - op2, dataSize)'
+
+    class Xor(LogicRegOp):
+        code = 'DestReg = merge(DestReg, psrc1 ^ op2, dataSize)'
+
+    class Mul1s(FlagRegOp):
+        code = '''
             int signPos = (dataSize * 8) / 2 - 1;
             IntReg srcVal1 = psrc1 | (-bits(psrc1, signPos) << signPos);
             IntReg srcVal2 = op2 | (-bits(psrc1, signPos) << signPos);
             DestReg = merge(DestReg, srcVal1 * srcVal2, dataSize)
-            ''')
-    defineMicroRegOp('Mul1u', '''
+            '''
+
+    class Mul1u(FlagRegOp):
+        code = '''
             int halfSize = (dataSize * 8) / 2;
             IntReg srcVal1 = psrc1 & mask(halfSize);
             IntReg srcVal2 = op2 & mask(halfSize);
             DestReg = merge(DestReg, srcVal1 * srcVal2, dataSize)
-            ''')
-    defineMicroRegOp('Mulel', \
-            'DestReg = merge(DestReg, psrc1 * op2, dataSize)')
-    defineMicroRegOp('Muleh', '''
+            '''
+
+    class Mulel(FlagRegOp):
+        code = 'DestReg = merge(DestReg, psrc1 * op2, dataSize)'
+
+    class Muleh(FlagRegOp):
+        code = '''
             int halfSize = (dataSize * 8) / 2;
             uint64_t psrc1_h = psrc1 >> halfSize;
             uint64_t psrc1_l = psrc1 & mask(halfSize);
@@ -545,46 +467,51 @@ let {{
                 ((psrc1_h * psrc2_l) >> halfSize) +
                 psrc1_h * psrc2_h;
             DestReg = merge(DestReg, result, dataSize);
-            ''')
-    defineMicroRegOp('Div1', '''
+            '''
+
+    class Div1(FlagRegOp):
+        code = '''
             int halfSize = (dataSize * 8) / 2;
             IntReg quotient = (psrc1 / op2) & mask(halfSize);
             IntReg remainder = (psrc1 % op2) & mask(halfSize);
             IntReg result = quotient | (remainder << halfSize);
             DestReg = merge(DestReg, result, dataSize);
-            ''')
-    defineMicroRegOp('Divq', '''
-            DestReg = merge(DestReg, psrc1 / op2, dataSize);
-            ''')
-    defineMicroRegOp('Divr', '''
-            DestReg = merge(DestReg, psrc1 % op2, dataSize);
-            ''')
-
-    #
-    # HACK HACK HACK HACK - Put psrc1 in here but make it inert to shut up gcc.
-    #
-    defineMicroRegOp('Mov',
-            'DestReg = merge(SrcReg1, psrc1 * 0 + op2, dataSize)',
-            elseCode='DestReg=DestReg;', cc=True)
-
-    defineMicroRegOp('Movfp',
-            'FpDestReg = FpSrcReg2 + psrc1 * 0 + psrc2 * 0',
-            elseCode='FpDestReg=FpDestReg;', cc=True, doImm=False)
+            '''
+
+    class Divq(FlagRegOp):
+        code = 'DestReg = merge(DestReg, psrc1 / op2, dataSize);'
+
+    class Divr(FlagRegOp):
+        code = 'DestReg = merge(DestReg, psrc1 % op2, dataSize);'
+
+    class Mov(CondRegOp):
+        code = 'DestReg = merge(SrcReg1, op2, dataSize)'
+        else_code = 'DestReg=DestReg;'
+
+    class Movfp(CondRegOp):
+        code = 'FpDestReg = FpSrcReg2'
+        else_code = 'FpDestReg = FpDestReg;'
 
     # Shift instructions
-    defineMicroRegOp('Sll', '''
+
+    class Sll(FlagRegOp):
+        code = '''
             uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
             DestReg = merge(DestReg, psrc1 << shiftAmt, dataSize);
-            ''')
-    defineMicroRegOp('Srl', '''
+            '''
+
+    class Srl(FlagRegOp):
+        code = '''
             uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
             // Because what happens to the bits shift -in- on a right shift
             // is not defined in the C/C++ standard, we have to mask them out
             // to be sure they're zero.
             uint64_t logicalMask = mask(dataSize * 8 - shiftAmt);
             DestReg = merge(DestReg, (psrc1 >> shiftAmt) & logicalMask, dataSize);
-            ''')
-    defineMicroRegOp('Sra', '''
+            '''
+
+    class Sra(FlagRegOp):
+        code = '''
             uint8_t shiftAmt = (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
             // Because what happens to the bits shift -in- on a right shift
             // is not defined in the C/C++ standard, we have to sign extend
@@ -592,8 +519,10 @@ let {{
             uint64_t arithMask =
                 -bits(psrc1, dataSize * 8 - 1) << (dataSize * 8 - shiftAmt);
             DestReg = merge(DestReg, (psrc1 >> shiftAmt) | arithMask, dataSize);
-            ''')
-    defineMicroRegOp('Ror', '''
+            '''
+
+    class Ror(FlagRegOp):
+        code = '''
             uint8_t shiftAmt =
                 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
             if(shiftAmt)
@@ -604,8 +533,10 @@ let {{
             }
             else
                 DestReg = DestReg;
-            ''')
-    defineMicroRegOp('Rcr', '''
+            '''
+
+    class Rcr(FlagRegOp):
+        code = '''
             uint8_t shiftAmt =
                 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
             if(shiftAmt)
@@ -619,8 +550,10 @@ let {{
             }
             else
                 DestReg = DestReg;
-            ''')
-    defineMicroRegOp('Rol', '''
+            '''
+
+    class Rol(FlagRegOp):
+        code = '''
             uint8_t shiftAmt =
                 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
             if(shiftAmt)
@@ -632,8 +565,10 @@ let {{
             }
             else
                 DestReg = DestReg;
-            ''')
-    defineMicroRegOp('Rcl', '''
+            '''
+
+    class Rcl(FlagRegOp):
+        code = '''
             uint8_t shiftAmt =
                 (op2 & ((dataSize == 8) ? mask(6) : mask(5)));
             if(shiftAmt)
@@ -649,28 +584,56 @@ let {{
             }
             else
                 DestReg = DestReg;
-            ''')
+            '''
 
-    defineMicroRegOpWr('Wrip', 'RIP = psrc1 + op2', elseCode="RIP = RIP;")
-    defineMicroRegOpWr('Br', 'nuIP = psrc1 + op2;', elseCode='nuIP = nuIP;')
-    defineMicroRegOpWr('Wruflags', 'ccFlagBits = psrc1 ^ op2')
+    class WrRegOp(RegOp):
+        abstract = True
+        def __init__(self, src1, src2, flags=None, dataSize="env.dataSize"):
+            super(WrRegOp, self).__init__("NUM_INTREGS", src1, src2, flags, dataSize)
 
-    defineMicroRegOpRd('Rdip', 'DestReg = RIP')
-    defineMicroRegOpRd('Ruflags', 'DestReg = ccFlagBits')
-    defineMicroRegOpRdImm('Ruflag', '''
+    class Wrip(WrRegOp, CondRegOp):
+        code = 'RIP = psrc1 + op2'
+        else_code="RIP = RIP;"
+
+    class Br(WrRegOp, CondRegOp):
+        code = 'nuIP = psrc1 + op2;'
+        else_code='nuIP = nuIP;'
+
+    class Wruflags(WrRegOp):
+        code = 'ccFlagBits = psrc1 ^ op2'
+
+    class RdRegOp(RegOp):
+        abstract = True
+        def __init__(self, dest, src1 = "NUM_INTREGS", dataSize="env.dataSize"):
+            super(RdRegOp, self).__init__(dest, src1, "NUM_INTREGS", None, dataSize)
+
+    class Rdip(RdRegOp):
+        code = 'DestReg = RIP'
+
+    class Ruflags(RdRegOp):
+        code = 'DestReg = ccFlagBits'
+
+    class Ruflag(RegOp):
+        code = '''
             int flag = bits(ccFlagBits, imm8 + 0*psrc1);
             DestReg = merge(DestReg, flag, dataSize);
             ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
                                        (ccFlagBits & ~EZFBit);
-            ''')
-
-    defineMicroRegOpImm('Sext', '''
+            '''
+        def __init__(self, dest, imm, flags=None, \
+                dataSize="env.dataSize"):
+            super(Ruflag, self).__init__(dest, \
+                    "NUM_INTREGS", imm, flags, dataSize)
+
+    class Sext(RegOp):
+        code = '''
             IntReg val = psrc1;
             int sign_bit = bits(val, imm8-1, imm8-1);
             uint64_t maskVal = mask(imm8);
             val = sign_bit ? (val | ~maskVal) : (val & maskVal);
             DestReg = merge(DestReg, val, dataSize);
-            ''')
+            '''
 
-    defineMicroRegOpImm('Zext', 'DestReg = bits(psrc1, imm8-1, 0);')
+    class Zext(RegOp):
+        code = 'DestReg = bits(psrc1, imm8-1, 0);'
 }};