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