Gabe Black has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/56497 )

Change subject: arch-x86: Use iterators to avoid copying around operand types.
......................................................................

arch-x86: Use iterators to avoid copying around operand types.

Also fix some style problems.

Change-Id: Idfc8542bdbce00ece16f82d26d239283a4ffda08
---
M src/arch/x86/isa/formats/cond.isa
M src/arch/x86/isa/formats/multi.isa
M src/arch/x86/isa/formats/string.isa
M src/arch/x86/isa/specialize.isa
4 files changed, 164 insertions(+), 161 deletions(-)



diff --git a/src/arch/x86/isa/formats/cond.isa b/src/arch/x86/isa/formats/cond.isa
index 158dff3..1212fd3 100644
--- a/src/arch/x86/isa/formats/cond.isa
+++ b/src/arch/x86/isa/formats/cond.isa
@@ -37,9 +37,9 @@
 def format CondInst(cond, *opTypeSet) {{
     blocks = OutputBlocks()

-    if_blocks = specializeInst(Name, list(opTypeSet), EmulEnv())
+    if_blocks = specializeInst(Name, iter(opTypeSet), EmulEnv())
     blocks.append(if_blocks)
-    else_blocks = specializeInst('UD2', [], EmulEnv())
+    else_blocks = specializeInst('UD2', iter([]), EmulEnv())
     blocks.append(else_blocks)

     (header_output, decoder_output,
@@ -51,9 +51,9 @@
 def format Cpl0CondInst(cond, *opTypeSet) {{
     blocks = OutputBlocks()

-    if_blocks = specializeInst(Name, list(opTypeSet), EmulEnv())
+    if_blocks = specializeInst(Name, iter(opTypeSet), EmulEnv())
     blocks.append(if_blocks)
-    else_blocks = specializeInst('UD2', [], EmulEnv())
+    else_blocks = specializeInst('UD2', iter([]), EmulEnv())
     blocks.append(else_blocks)

     (header_output, decoder_output,
diff --git a/src/arch/x86/isa/formats/multi.isa b/src/arch/x86/isa/formats/multi.isa
index 0d4e920..7742321 100644
--- a/src/arch/x86/isa/formats/multi.isa
+++ b/src/arch/x86/isa/formats/multi.isa
@@ -42,13 +42,13 @@
 //////////////////////////////////////////////////////////////////////////

 def format Inst(*opTypeSet) {{
-    blocks = specializeInst(Name, list(opTypeSet), EmulEnv())
+    blocks = specializeInst(Name, iter(opTypeSet), EmulEnv())
     (header_output, decoder_output,
      decode_block, exec_output) = blocks.makeList()
 }};

 def format Cpl0Inst(*opTypeSet) {{
-    blocks = specializeInst(Name, list(opTypeSet), EmulEnv())
+    blocks = specializeInst(Name, iter(opTypeSet), EmulEnv())
     (header_output, decoder_output,
      decode_block, exec_output) = blocks.makeList()
     decode_block = '''
@@ -63,8 +63,8 @@

 def format MultiInst(switchVal, *opTypeSets) {{
     switcher = {}
-    for (count, opTypeSet) in zip(range(len(opTypeSets)), opTypeSets):
-        switcher[count] = (specializeInst, Name, opTypeSet, EmulEnv())
+    for count, opTypeSet in enumerate(opTypeSets):
+        switcher[count] = specializeInst(Name, iter(opTypeSet), EmulEnv())
     blocks = doSplitDecode(switchVal, switcher)
     (header_output, decoder_output,
      decode_block, exec_output) = blocks.makeList()
diff --git a/src/arch/x86/isa/formats/string.isa b/src/arch/x86/isa/formats/string.isa
index c75a01b..6943060 100644
--- a/src/arch/x86/isa/formats/string.isa
+++ b/src/arch/x86/isa/formats/string.isa
@@ -44,9 +44,9 @@
 def format StringTestInst(*opTypeSet) {{
     allBlocks = OutputBlocks()

-    regBlocks = specializeInst(Name, list(opTypeSet), EmulEnv())
-    eBlocks = specializeInst(Name + "_E", list(opTypeSet), EmulEnv())
-    nBlocks = specializeInst(Name + "_N", list(opTypeSet), EmulEnv())
+    regBlocks = specializeInst(Name, iter(opTypeSet), EmulEnv())
+    eBlocks = specializeInst(Name + "_E", iter(opTypeSet), EmulEnv())
+    nBlocks = specializeInst(Name + "_N", iter(opTypeSet), EmulEnv())

     for blocks in (regBlocks, eBlocks, nBlocks):
         allBlocks.header_output += blocks.header_output
@@ -70,8 +70,8 @@
 def format StringInst(*opTypeSet) {{
     allBlocks = OutputBlocks()

-    regBlocks = specializeInst(Name, list(opTypeSet), EmulEnv())
-    eBlocks = specializeInst(Name + "_E", list(opTypeSet), EmulEnv())
+    regBlocks = specializeInst(Name, iter(opTypeSet), EmulEnv())
+    eBlocks = specializeInst(Name + "_E", iter(opTypeSet), EmulEnv())

     for blocks in (regBlocks, eBlocks):
         allBlocks.header_output += blocks.header_output
diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa
index f90aa48..554b141 100644
--- a/src/arch/x86/isa/specialize.isa
+++ b/src/arch/x86/isa/specialize.isa
@@ -46,233 +46,225 @@
# vals is a dict which matches case values with what should be decoded to.
     # Each element of the dict is a list containing a function and then the
     # arguments to pass to it.
-    def doSplitDecode(switchVal, vals, default = None):
+    def doSplitDecode(switchVal, vals, default=None):
         blocks = OutputBlocks()
         blocks.decode_block = 'switch(%s) {\n' % switchVal
-        for (val, todo) in vals.items():
-            new_blocks = todo[0](*todo[1:])
-            new_blocks.decode_block = \
-                '\tcase %s: %s\n' % (val, new_blocks.decode_block)
-            blocks.append(new_blocks)
+        for val, ret in vals.items():
+            ret = copy.copy(ret)
+            ret.decode_block = '\tcase %s: %s\n' % (val, ret.decode_block)
+            blocks.append(ret)
         if default:
-            new_blocks = default[0](*default[1:])
-            new_blocks.decode_block = \
-                '\tdefault: %s\n' % new_blocks.decode_block
-            blocks.append(new_blocks)
+            default = copy.copy(default)
+            default.decode_block = '\tdefault: %s\n' % default.decode_block
+            blocks.append(default)
         blocks.decode_block += '}\n'
         return blocks
 }};

 let {{
-    def doRipRelativeDecode(Name, opTypes, env):
-        # print "RIPing %s with opTypes %s" % (Name, opTypes)
+    import itertools
+
+    def doRipRelativeDecode(Name, op_type_iter, env):
         env.memoryInst = True
-        normEnv = copy.copy(env)
-        normEnv.addToDisassembly(
+        norm_iter, rip_iter = itertools.tee(op_type_iter)
+        norm_env = copy.copy(env)
+        norm_env.addToDisassembly(
                 '''printMem(out, env.seg, env.scale, env.index, env.base,
                     machInst.displacement, env.addressSize, false);''')
- normBlocks = specializeInst(Name + "_M", copy.copy(opTypes), normEnv)
-        ripEnv = copy.copy(env)
-        ripEnv.addToDisassembly(
+        norm_blocks = specializeInst(Name + "_M", norm_iter, norm_env)
+        rip_env = copy.copy(env)
+        rip_env.addToDisassembly(
                 '''printMem(out, env.seg, 1, 0, 0,
                     machInst.displacement, env.addressSize, true);''')
-        ripBlocks = specializeInst(Name + "_P", copy.copy(opTypes), ripEnv)
+        rip_blocks = specializeInst(Name + "_P", rip_iter, rip_env)

         blocks = OutputBlocks()
-        blocks.append(normBlocks)
-        blocks.append(ripBlocks)
+        blocks.append(norm_blocks)
+        blocks.append(rip_blocks)

         blocks.decode_block = '''
-        if(machInst.modRM.mod == 0 &&
-          machInst.modRM.rm == 5 &&
-          machInst.mode.submode == SixtyFourBitMode)
-        { %s }
-        else
-        { %s }''' % \
-         (ripBlocks.decode_block, normBlocks.decode_block)
+        if (machInst.modRM.mod == 0 && machInst.modRM.rm == 5 &&
+                machInst.mode.submode == SixtyFourBitMode) {
+            %(rip)s
+        } else {
+            %(norm)s
+        }''' % {'rip': rip_blocks.decode_block,
+                'norm': norm_blocks.decode_block}
         return blocks
-}};

-let {{
     def doBadInstDecode():
         blocks = OutputBlocks()
-        blocks.decode_block = '''
-        return new Unknown(machInst);
-        '''
+        blocks.decode_Block = 'return new Unknown(machInst);'
         return blocks
-}};

-let {{
     class OpType(object):
-        parser = re.compile(r"(?P<tag>[A-Z]+)(?P<size>[a-z]*)|"
-                             "(r(?P<reg>[A-Z0-9]+)(?P<rsize>[a-z]*))|"
-                             "(s(?P<seg>[A-Z0-9]+)(?P<ssize>[a-z]*))")
+        parser = re.compile(r'(?P<tag>[A-Z]+)(?P<size>[a-z]*)|'
+                             '(r(?P<reg>[A-Z0-9]+)(?P<rsize>[a-z]*))|'
+                             '(s(?P<seg>[A-Z0-9]+)(?P<ssize>[a-z]*))')
         def __init__(self, opTypeString):
             match = OpType.parser.search(opTypeString)
             if match == None:
-                raise Exception("Problem parsing operand type {}".format(
+                raise Exception('Problem parsing operand type {}'.format(
                     opTypeString))
-            self.reg = match.group("reg")
-            self.seg = match.group("seg")
-            self.tag = match.group("tag")
-            self.size = match.group("size")
+            self.reg = match.group('reg')
+            self.seg = match.group('seg')
+            self.tag = match.group('tag')
+            self.size = match.group('size')
             if not self.size:
-                self.size = match.group("rsize")
+                self.size = match.group('rsize')
             if not self.size:
-                self.size = match.group("ssize")
+                self.size = match.group('ssize')

-    ModRMRegIndex = "(MODRM_REG | (REX_R << 3))"
-    ModRMRMIndex = "(MODRM_RM | (REX_B << 3))"
-    InstRegIndex = "(OPCODE_OP_BOTTOM3 | (REX_B << 3))"
+    ModRMRegIndex = '(MODRM_REG | (REX_R << 3))'
+    ModRMRMIndex = '(MODRM_RM | (REX_B << 3))'
+    InstRegIndex = '(OPCODE_OP_BOTTOM3 | (REX_B << 3))'

     # This function specializes the given piece of code to use a particular
-    # set of argument types described by "opTypes".
-    def specializeInst(Name, opTypes, env):
-        # print "Specializing %s with opTypes %s" % (Name, opTypes)
-        while len(opTypes):
+    # set of argument types described by "op_types".
+    def specializeInst(Name, op_type_iter, env):
+        for op_type_str in op_type_iter:
             # Parse the operand type string we're working with
-            opType = OpType(opTypes[0])
-            opTypes.pop(0)
+            op_type = OpType(op_type_str)

- if opType.tag not in ("I", "J", "P", "PR", "Q", "V", "VR", "W"):
-                if opType.size:
-                    env.setSize(opType.size)
+ if op_type.tag not in ('I', 'J', 'P', 'PR', 'Q', 'V', 'VR', 'W'):
+                if op_type.size:
+                    env.setSize(op_type.size)

-            if opType.reg:
-                #Figure out what to do with fixed register operands
- #This is the index to use, so we should stick it some place.
-                if opType.reg in ("A", "B", "C", "D"):
-                    regString = "INTREG_R%sX" % opType.reg
+            if op_type.reg:
+                # Figure out what to do with fixed register operands
+ # This is the index to use, so we should stick it some place.
+                if op_type.reg in ('A', 'B', 'C', 'D'):
+                    reg_string = 'INTREG_R%sX' % op_type.reg
                 else:
-                    regString = "INTREG_R%s" % opType.reg
-                env.addReg(regString)
+                    reg_string = 'INTREG_R%s' % op_type.reg
+                env.addReg(reg_string)
                 if env.regmUsed:
-                    regString = "env.regm"
+                    reg_string = 'env.regm'
                 else:
-                    regString = "env.reg"
+                    reg_string = 'env.reg'
                 env.addToDisassembly(
-                    "printReg(out, RegId(IntRegClass, %s), regSize);\n" %
-                    regString)
+                    'printReg(out, RegId(IntRegClass, %s), regSize);\n' %
+                    reg_string)

-                Name += "_R"
+                Name += '_R'

-            elif opType.seg:
-                env.addReg("SEGMENT_REG_%sS" % opType.seg)
+            elif op_type.seg:
+                env.addReg('SEGMENT_REG_%sS' % op_type.seg)
                 if env.regmUsed:
-                    regString = "env.regm"
+                    reg_string = 'env.regm'
                 else:
-                    regString = "env.reg"
- env.addToDisassembly("printSegment(out, %s);\n" % regString)
+                    reg_string = 'env.reg'
+ env.addToDisassembly('printSegment(out, %s);\n' % reg_string)

-                Name += "_S"
+                Name += '_S'

-            elif opType.tag == "B":
+            elif op_type.tag == 'B':
# This refers to registers whose index is encoded as part of
                 # the opcode.
                 env.addToDisassembly(
- "printReg(out, RegId(IntRegClass, %s), regSize);\n" % + 'printReg(out, RegId(IntRegClass, %s), regSize);\n' %
                         InstRegIndex)

-                Name += "_R"
+                Name += '_R'

                 env.addReg(InstRegIndex)
-            elif opType.tag == "M":
+            elif op_type.tag == 'M':
# This refers to memory. The macroop constructor sets up modrm # addressing. Non memory modrm settings should cause an error.
                 env.doModRM = True
-                return doSplitDecode("MODRM_MOD",
-                        {"3" : (doBadInstDecode,) },
-                        (doRipRelativeDecode, Name, opTypes, env))
-            elif opType.tag == None or opType.size == None:
-                raise Exception("Problem parsing operand tag: {}".format(
-                    opType.tag))
-            elif opType.tag == "C":
-                # A control register indexed by the "reg" field
+                return doSplitDecode('MODRM_MOD',
+                        {'3' : doBadInstDecode()},
+                        doRipRelativeDecode(Name, op_type_iter, env))
+            elif op_type.tag == None or op_type.size == None:
+                raise Exception('Problem parsing operand tag: {}'.format(
+                    op_type.tag))
+            elif op_type.tag == 'C':
+                # A control register indexed by the 'reg' field
                 env.addReg(ModRMRegIndex)
                 env.addToDisassembly(
-                        "ccprintf(out, \"CR%%d\", %s);\n" % ModRMRegIndex)
+                        'ccprintf(out, "CR%%d", %s);\n' % ModRMRegIndex)
                 Name += "_C"
-            elif opType.tag == "D":
-                # A debug register indexed by the "reg" field
+            elif op_type.tag == 'D':
+                # A debug register indexed by the 'reg' field
                 env.addReg(ModRMRegIndex)
                 env.addToDisassembly(
-                        "ccprintf(out, \"DR%%d\", %s);\n" % ModRMRegIndex)
-                Name += "_D"
-            elif opType.tag == "S":
-                # A segment selector register indexed by the "reg" field
+                        'ccprintf(out, "DR%%d", %s);\n' % ModRMRegIndex)
+                Name += '_D'
+            elif op_type.tag == 'S':
+                # A segment selector register indexed by the 'reg' field
                 env.addReg(ModRMRegIndex)
                 env.addToDisassembly(
-                        "printSegment(out, %s);\n" % ModRMRegIndex)
-                Name += "_S"
-            elif opType.tag in ("G", "P", "T", "V"):
- # Use the "reg" field of the ModRM byte to select the register
+                        'printSegment(out, %s);\n' % ModRMRegIndex)
+                Name += '_S'
+            elif op_type.tag in ('G', 'P', 'T', 'V'):
+ # Use the 'reg' field of the ModRM byte to select the register
                 env.addReg(ModRMRegIndex)

-                if opType.tag == "P":
-                    regFormat = 'ccprintf(out, "MMX%%d", %s);\n'
-                    Name += "_MMX"
-                elif opType.tag == "V":
-                    regFormat = 'ccprintf(out, "XMM%%d", %s);\n'
-                    Name += "_XMM"
+                if op_type.tag == 'P':
+                    reg_format = 'ccprintf(out, "MMX%%d", %s);\n'
+                    Name += '_MMX'
+                elif op_type.tag == 'V':
+                    reg_format = 'ccprintf(out, "XMM%%d", %s);\n'
+                    Name += '_XMM'
                 else:
-                    regFormat = \
-                        "printReg(out, RegId(IntRegClass, %s), regSize);\n"
-                    Name += "_R"
-                env.addToDisassembly(regFormat % ModRMRegIndex)
-            elif opType.tag in ("E", "Q", "W"):
+                    reg_format = \
+                        'printReg(out, RegId(IntRegClass, %s), regSize);\n'
+                    Name += '_R'
+                env.addToDisassembly(reg_format % ModRMRegIndex)
+            elif op_type.tag in ('E', 'Q', 'W'):
                 # This might refer to memory or to a register. We need to
                 # divide it up farther.
-                regEnv = copy.copy(env)
-                regEnv.addReg(ModRMRMIndex)
+                reg_env = copy.copy(env)
+                reg_env.addReg(ModRMRMIndex)

# This refers to memory. The macroop constructor should set up

                 # modrm addressing.
-                memEnv = copy.copy(env)
-                memEnv.doModRM = True
-                if opType.tag == "Q":
-                    regFormat = 'ccprintf(out, "MMX%%d", %s);\n'
-                    regSuffix = "_MMX"
-                elif opType.tag == "W":
-                    regFormat = 'ccprintf(out, "XMM%%d", %s);\n'
-                    regSuffix = "_XMM"
+                mem_env = copy.copy(env)
+                mem_env.doModRM = True
+                if op_type.tag == 'Q':
+                    reg_format = 'ccprintf(out, "MMX%%d", %s);\n'
+                    reg_suffix = '_MMX'
+                elif op_type.tag == 'W':
+                    reg_format = 'ccprintf(out, "XMM%%d", %s);\n'
+                    reg_suffix = '_XMM'
                 else:
-                    regFormat = \
-                        "printReg(out, RegId(IntRegClass, %s), regSize);\n"
-                    regSuffix = "_R"
-                env.addToDisassembly(regFormat % ModRMRegIndex)
-                return doSplitDecode("MODRM_MOD",
-                    {"3" : (specializeInst, Name + regSuffix,
-                            copy.copy(opTypes), regEnv)},
-                           (doRipRelativeDecode, Name,
-                            copy.copy(opTypes), memEnv))
-            elif opType.tag in ("I", "J"):
+                    reg_format = \
+                        'printReg(out, RegId(IntRegClass, %s), regSize);\n'
+                    reg_suffix = '_R'
+                env.addToDisassembly(reg_format % ModRMRegIndex)
+                reg_iter, mem_iter = itertools.tee(op_type_iter)
+                return doSplitDecode('MODRM_MOD',
+                    {'3' : specializeInst(
+                            Name + reg_suffix, reg_iter, reg_env)},
+                    doRipRelativeDecode(Name, mem_iter, mem_env))
+            elif op_type.tag in ('I', 'J'):
                 # Immediates
                 env.addToDisassembly(
-                        "ccprintf(out, \"%#x\", machInst.immediate);\n")
-                Name += "_I"
-            elif opType.tag == "O":
+                        'ccprintf(out, "%#x", machInst.immediate);\n')
+                Name += '_I'
+            elif op_type.tag == 'O':
                 # Immediate containing a memory offset
-                Name += "_MI"
-            elif opType.tag in ("PR", "R", "VR"):
+                Name += '_MI'
+            elif op_type.tag in ('PR', 'R', 'VR'):
                 # Non register modrm settings should cause an error
                 env.addReg(ModRMRMIndex)

-                if opType.tag == "PR":
-                    regFormat = 'ccprintf(out, "MMX%%d", %s);\n'
-                    Name += "_MMX"
-                elif opType.tag == "VR":
-                    regFormat = 'ccprintf(out, "XMM%%d", %s);\n'
-                    Name += "_XMM"
+                if op_type.tag == 'PR':
+                    reg_format = 'ccprintf(out, "MMX%%d", %s);\n'
+                    Name += '_MMX'
+                elif op_type.tag == 'VR':
+                    reg_format = 'ccprintf(out, "XMM%%d", %s);\n'
+                    Name += '_XMM'
                 else:
-                    regFormat = \
-                        "printReg(out, RegId(IntRegClass, %s), regSize);\n"
-                    Name += "_R"
-                env.addToDisassembly(regFormat % ModRMRegIndex)
-            elif opType.tag in ("X", "Y"):
+                    reg_format = \
+                        'printReg(out, RegId(IntRegClass, %s), regSize);\n'
+                    Name += '_R'
+                env.addToDisassembly(reg_format % ModRMRegIndex)
+            elif op_type.tag in ('X', 'Y'):
# This type of memory addressing is for string instructions.
                 # They'll use the right index and segment internally.
-                if opType.tag == "X":
+                if op_type.tag == 'X':
                     env.addToDisassembly(
                             '''printMem(out, env.seg,
1, X86ISA::NUM_INTREGS, X86ISA::INTREG_RSI, 0,
@@ -282,11 +274,11 @@
                             '''printMem(out, SEGMENT_REG_ES,
1, X86ISA::NUM_INTREGS, X86ISA::INTREG_RDI, 0,
                                 env.addressSize, false);''')
-                Name += "_M"
+                Name += '_M'
             else:
-                raise Exception("Unrecognized tag {}.".format(opType.tag))
+                raise Exception('Unrecognized tag {}.'.format(op_type.tag))

         # Generate code to return a macroop of the given name which will
-        # operate in the "emulation environment" env
+        # operate in the 'emulation environment' env
         return genMacroop(Name, env)
 }};

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/56497
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Idfc8542bdbce00ece16f82d26d239283a4ffda08
Gerrit-Change-Number: 56497
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <gabe.bl...@gmail.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to