summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Reinhardt <stever@eecs.umich.edu>2006-02-12 00:31:19 -0500
committerSteve Reinhardt <stever@eecs.umich.edu>2006-02-12 00:31:19 -0500
commit79613686f0f6a8725e88e935a7c9ff4ede4cfc2b (patch)
treebaa659b44e5f561a1686b887b4f3825ef8e1d326
parent8f2e096275386cbd6744c4bd65190dba1c5b89b4 (diff)
downloadgem5-79613686f0f6a8725e88e935a7c9ff4ede4cfc2b.tar.xz
Polishing of isa_parser.py internal operand handling, resulting in
minor change to syntax of 'def operands' in ISA descriptions. arch/alpha/isa/main.isa: arch/mips/isa/operands.isa: arch/sparc/isa/operands.isa: Change 'def operands' statement to work with new isa_parser changes. arch/isa_parser.py: Merge OperandTraits and OperandDescriptor objects into a unified hierarchy of Operand objects. Required a change in the syntax of the 'def operands' statement in the ISA description. --HG-- extra : convert_revision : cb43f1607311497ead88ba13953d410ab5bc6a37
-rw-r--r--arch/alpha/isa/main.isa25
-rwxr-xr-xarch/isa_parser.py413
-rw-r--r--arch/mips/isa/operands.isa29
-rw-r--r--arch/sparc/isa/operands.isa25
4 files changed, 243 insertions, 249 deletions
diff --git a/arch/alpha/isa/main.isa b/arch/alpha/isa/main.isa
index fa2f71a29..c082df8c8 100644
--- a/arch/alpha/isa/main.isa
+++ b/arch/alpha/isa/main.isa
@@ -148,20 +148,19 @@ def operands {{
# Int regs default to unsigned, but code should not count on this.
# For clarity, descriptions that depend on unsigned behavior should
# explicitly specify '.uq'.
- 'Ra': IntRegOperandTraits('uq', 'RA', 'IsInteger', 1),
- 'Rb': IntRegOperandTraits('uq', 'RB', 'IsInteger', 2),
- 'Rc': IntRegOperandTraits('uq', 'RC', 'IsInteger', 3),
- 'Fa': FloatRegOperandTraits('df', 'FA', 'IsFloating', 1),
- 'Fb': FloatRegOperandTraits('df', 'FB', 'IsFloating', 2),
- 'Fc': FloatRegOperandTraits('df', 'FC', 'IsFloating', 3),
- 'Mem': MemOperandTraits('uq', None,
- ('IsMemRef', 'IsLoad', 'IsStore'), 4),
- 'NPC': NPCOperandTraits('uq', None, ( None, None, 'IsControl' ), 4),
- 'Runiq': ControlRegOperandTraits('uq', 'Uniq', None, 1),
- 'FPCR': ControlRegOperandTraits('uq', 'Fpcr', None, 1),
+ 'Ra': ('IntReg', 'uq', 'RA', 'IsInteger', 1),
+ 'Rb': ('IntReg', 'uq', 'RB', 'IsInteger', 2),
+ 'Rc': ('IntReg', 'uq', 'RC', 'IsInteger', 3),
+ 'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1),
+ 'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),
+ 'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
+ 'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
+ 'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
+ 'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1),
+ 'FPCR': (' ControlReg', 'uq', 'Fpcr', None, 1),
# The next two are hacks for non-full-system call-pal emulation
- 'R0': IntRegOperandTraits('uq', '0', None, 1),
- 'R16': IntRegOperandTraits('uq', '16', None, 1)
+ 'R0': ('IntReg', 'uq', '0', None, 1),
+ 'R16': ('IntReg', 'uq', '16', None, 1)
}};
////////////////////////////////////////////////////////////////////
diff --git a/arch/isa_parser.py b/arch/isa_parser.py
index 0e33b4ff7..030bb5a7c 100755
--- a/arch/isa_parser.py
+++ b/arch/isa_parser.py
@@ -320,29 +320,27 @@ def p_global_let(t):
# widths (stored in operandTypeMap).
def p_def_operand_types(t):
'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
- s = 'global operandTypeMap; operandTypeMap = {' + t[3] + '}'
try:
- exec s
+ userDict = eval('{' + t[3] + '}')
except Exception, exc:
error(t.lineno(1),
'error: %s in def operand_types block "%s".' % (exc, t[3]))
- buildOperandSizeMap()
+ buildOperandTypeMap(userDict, t.lineno(1))
t[0] = GenCode() # contributes nothing to the output C++ file
# Define the mapping from operand names to operand classes and other
-# traits. Stored in operandTraitsMap.
+# traits. Stored in operandNameMap.
def p_def_operands(t):
'def_operands : DEF OPERANDS CODELIT SEMI'
- if not globals().has_key('operandSizeMap'):
+ if not globals().has_key('operandTypeMap'):
error(t.lineno(1),
'error: operand types must be defined before operands')
- s = 'global operandTraitsMap; operandTraitsMap = {' + t[3] + '}'
try:
- exec s
+ userDict = eval('{' + t[3] + '}')
except Exception, exc:
error(t.lineno(1),
'error: %s in def operands block "%s".' % (exc, t[3]))
- defineDerivedOperandVars()
+ buildOperandNameMap(userDict, t.lineno(1))
t[0] = GenCode() # contributes nothing to the output C++ file
# A bitfield definition looks like:
@@ -847,6 +845,19 @@ class GenCode:
# a defineInst() method that generates the code for an instruction
# definition.
+exportContextSymbols = ('InstObjParams', 'CodeBlock',
+ 'makeList', 're', 'string')
+
+exportContext = {}
+
+def updateExportContext():
+ exportContext.update(exportDict(*exportContextSymbols))
+ exportContext.update(templateMap)
+
+def exportDict(*symNames):
+ return dict([(s, eval(s)) for s in symNames])
+
+
class Format:
def __init__(self, id, params, code):
# constructor: just save away arguments
@@ -1077,13 +1088,12 @@ def makeList(arg):
else:
return [ arg ]
-# generate operandSizeMap based on provided operandTypeMap:
-# basically generate equiv. C++ type and make is_signed flag
-def buildOperandSizeMap():
- global operandSizeMap
- operandSizeMap = {}
- for ext in operandTypeMap.keys():
- (desc, size) = operandTypeMap[ext]
+# Generate operandTypeMap from the user's 'def operand_types'
+# statement.
+def buildOperandTypeMap(userDict, lineno):
+ global operandTypeMap
+ operandTypeMap = {}
+ for (ext, (desc, size)) in userDict.iteritems():
if desc == 'signed int':
ctype = 'int%d_t' % size
is_signed = 1
@@ -1097,41 +1107,56 @@ def buildOperandSizeMap():
elif size == 64:
ctype = 'double'
if ctype == '':
- error(0, 'Unrecognized type description "%s" in operandTypeMap')
- operandSizeMap[ext] = (size, ctype, is_signed)
+ error(0, 'Unrecognized type description "%s" in userDict')
+ operandTypeMap[ext] = (size, ctype, is_signed)
#
-# Base class for operand traits. An instance of this class (or actually
-# a class derived from this one) encapsulates the traits of a particular
-# operand type (e.g., "32-bit integer register").
#
-class OperandTraits:
- def __init__(self, dflt_ext, reg_spec, flags, sort_pri):
- self.dflt_ext = dflt_ext
- (self.dflt_size, self.dflt_type, self.dflt_is_signed) = \
- operandSizeMap[dflt_ext]
- self.reg_spec = reg_spec
- # Canonical flag structure is a triple of lists, where each list
- # indicates the set of flags implied by this operand always, when
- # used as a source, and when used as a dest, respectively.
- # For simplicity this can be initialized using a variety of fairly
- # obvious shortcuts; we convert these to canonical form here.
- if not flags:
- # no flags specified (e.g., 'None')
- self.flags = ( [], [], [] )
- elif isinstance(flags, str):
- # a single flag: assumed to be unconditional
- self.flags = ( [ flags ], [], [] )
- elif isinstance(flags, list):
- # a list of flags: also assumed to be unconditional
- self.flags = ( flags, [], [] )
- elif isinstance(flags, tuple):
- # it's a tuple: it should be a triple,
- # but each item could be a single string or a list
- (uncond_flags, src_flags, dest_flags) = flags
- self.flags = (makeList(uncond_flags),
- makeList(src_flags), makeList(dest_flags))
- self.sort_pri = sort_pri
+#
+# Base class for operand descriptors. An instance of this class (or
+# actually a class derived from this one) represents a specific
+# operand for a code block (e.g, "Rc.sq" as a dest). Intermediate
+# derived classes encapsulates the traits of a particular operand type
+# (e.g., "32-bit integer register").
+#
+class Operand(object):
+ def __init__(self, full_name, ext, is_src, is_dest):
+ self.full_name = full_name
+ self.ext = ext
+ self.is_src = is_src
+ self.is_dest = is_dest
+ # The 'effective extension' (eff_ext) is either the actual
+ # extension, if one was explicitly provided, or the default.
+ if ext:
+ self.eff_ext = ext
+ else:
+ self.eff_ext = self.dflt_ext
+
+ (self.size, self.ctype, self.is_signed) = operandTypeMap[self.eff_ext]
+
+ # note that mem_acc_size is undefined for non-mem operands...
+ # template must be careful not to use it if it doesn't apply.
+ if self.isMem():
+ self.mem_acc_size = self.makeAccSize()
+
+ # Finalize additional fields (primarily code fields). This step
+ # is done separately since some of these fields may depend on the
+ # register index enumeration that hasn't been performed yet at the
+ # time of __init__().
+ def finalize(self):
+ self.flags = self.getFlags()
+ self.constructor = self.makeConstructor()
+ self.op_decl = self.makeDecl()
+
+ if self.is_src:
+ self.op_rd = self.makeRead()
+ else:
+ self.op_rd = ''
+
+ if self.is_dest:
+ self.op_wb = self.makeWrite()
+ else:
+ self.op_wb = ''
def isMem(self):
return 0
@@ -1148,223 +1173,239 @@ class OperandTraits:
def isControlReg(self):
return 0
- def getFlags(self, op_desc):
+ def getFlags(self):
# note the empty slice '[:]' gives us a copy of self.flags[0]
# instead of a reference to it
my_flags = self.flags[0][:]
- if op_desc.is_src:
+ if self.is_src:
my_flags += self.flags[1]
- if op_desc.is_dest:
+ if self.is_dest:
my_flags += self.flags[2]
return my_flags
- def makeDecl(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
+ def makeDecl(self):
# Note that initializations in the declarations are solely
# to avoid 'uninitialized variable' errors from the compiler.
- return type + ' ' + op_desc.base_name + ' = 0;\n';
+ return self.ctype + ' ' + self.base_name + ' = 0;\n';
-class IntRegOperandTraits(OperandTraits):
+class IntRegOperand(Operand):
def isReg(self):
return 1
def isIntReg(self):
return 1
- def makeConstructor(self, op_desc):
+ def makeConstructor(self):
c = ''
- if op_desc.is_src:
+ if self.is_src:
c += '\n\t_srcRegIdx[%d] = %s;' % \
- (op_desc.src_reg_idx, self.reg_spec)
- if op_desc.is_dest:
+ (self.src_reg_idx, self.reg_spec)
+ if self.is_dest:
c += '\n\t_destRegIdx[%d] = %s;' % \
- (op_desc.dest_reg_idx, self.reg_spec)
+ (self.dest_reg_idx, self.reg_spec)
return c
- def makeRead(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
- if (type == 'float' or type == 'double'):
+ def makeRead(self):
+ if (self.ctype == 'float' or self.ctype == 'double'):
error(0, 'Attempt to read integer register as FP')
- if (size == self.dflt_size):
+ if (self.size == self.dflt_size):
return '%s = xc->readIntReg(this, %d);\n' % \
- (op_desc.base_name, op_desc.src_reg_idx)
+ (self.base_name, self.src_reg_idx)
else:
return '%s = bits(xc->readIntReg(this, %d), %d, 0);\n' % \
- (op_desc.base_name, op_desc.src_reg_idx, size-1)
+ (self.base_name, self.src_reg_idx, self.size-1)
- def makeWrite(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
- if (type == 'float' or type == 'double'):
+ def makeWrite(self):
+ if (self.ctype == 'float' or self.ctype == 'double'):
error(0, 'Attempt to write integer register as FP')
- if (size != self.dflt_size and is_signed):
- final_val = 'sext<%d>(%s)' % (size, op_desc.base_name)
+ if (self.size != self.dflt_size and self.is_signed):
+ final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
else:
- final_val = op_desc.base_name
+ final_val = self.base_name
wb = '''
{
%s final_val = %s;
xc->setIntReg(this, %d, final_val);\n
if (traceData) { traceData->setData(final_val); }
- }''' % (self.dflt_type, final_val, op_desc.dest_reg_idx)
+ }''' % (self.dflt_ctype, final_val, self.dest_reg_idx)
return wb
-class FloatRegOperandTraits(OperandTraits):
+class FloatRegOperand(Operand):
def isReg(self):
return 1
def isFloatReg(self):
return 1
- def makeConstructor(self, op_desc):
+ def makeConstructor(self):
c = ''
- if op_desc.is_src:
+ if self.is_src:
c += '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
- (op_desc.src_reg_idx, self.reg_spec)
- if op_desc.is_dest:
+ (self.src_reg_idx, self.reg_spec)
+ if self.is_dest:
c += '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
- (op_desc.dest_reg_idx, self.reg_spec)
+ (self.dest_reg_idx, self.reg_spec)
return c
- def makeRead(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
+ def makeRead(self):
bit_select = 0
- if (type == 'float'):
+ if (self.ctype == 'float'):
func = 'readFloatRegSingle'
- elif (type == 'double'):
+ elif (self.ctype == 'double'):
func = 'readFloatRegDouble'
else:
func = 'readFloatRegInt'
- if (size != self.dflt_size):
+ if (self.size != self.dflt_size):
bit_select = 1
base = 'xc->%s(this, %d)' % \
- (func, op_desc.src_reg_idx)
+ (func, self.src_reg_idx)
if bit_select:
return '%s = bits(%s, %d, 0);\n' % \
- (op_desc.base_name, base, size-1)
+ (self.base_name, base, self.size-1)
else:
- return '%s = %s;\n' % (op_desc.base_name, base)
+ return '%s = %s;\n' % (self.base_name, base)
- def makeWrite(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
- final_val = op_desc.base_name
- if (type == 'float'):
+ def makeWrite(self):
+ final_val = self.base_name
+ final_ctype = self.ctype
+ if (self.ctype == 'float'):
func = 'setFloatRegSingle'
- elif (type == 'double'):
+ elif (self.ctype == 'double'):
func = 'setFloatRegDouble'
else:
func = 'setFloatRegInt'
- type = 'uint%d_t' % self.dflt_size
- if (size != self.dflt_size and is_signed):
- final_val = 'sext<%d>(%s)' % (size, op_desc.base_name)
+ final_ctype = 'uint%d_t' % self.dflt_size
+ if (self.size != self.dflt_size and self.is_signed):
+ final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
wb = '''
{
%s final_val = %s;
xc->%s(this, %d, final_val);\n
if (traceData) { traceData->setData(final_val); }
- }''' % (type, final_val, func, op_desc.dest_reg_idx)
+ }''' % (final_ctype, final_val, func, self.dest_reg_idx)
return wb
-class ControlRegOperandTraits(OperandTraits):
+class ControlRegOperand(Operand):
def isReg(self):
return 1
def isControlReg(self):
return 1
- def makeConstructor(self, op_desc):
+ def makeConstructor(self):
c = ''
- if op_desc.is_src:
+ if self.is_src:
c += '\n\t_srcRegIdx[%d] = %s_DepTag;' % \
- (op_desc.src_reg_idx, self.reg_spec)
- if op_desc.is_dest:
+ (self.src_reg_idx, self.reg_spec)
+ if self.is_dest:
c += '\n\t_destRegIdx[%d] = %s_DepTag;' % \
- (op_desc.dest_reg_idx, self.reg_spec)
+ (self.dest_reg_idx, self.reg_spec)
return c
- def makeRead(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
+ def makeRead(self):
bit_select = 0
- if (type == 'float' or type == 'double'):
+ if (self.ctype == 'float' or self.ctype == 'double'):
error(0, 'Attempt to read control register as FP')
base = 'xc->read%s()' % self.reg_spec
- if size == self.dflt_size:
- return '%s = %s;\n' % (op_desc.base_name, base)
+ if self.size == self.dflt_size:
+ return '%s = %s;\n' % (self.base_name, base)
else:
return '%s = bits(%s, %d, 0);\n' % \
- (op_desc.base_name, base, size-1)
+ (self.base_name, base, self.size-1)
- def makeWrite(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
- if (type == 'float' or type == 'double'):
+ def makeWrite(self):
+ if (self.ctype == 'float' or self.ctype == 'double'):
error(0, 'Attempt to write control register as FP')
- wb = 'xc->set%s(%s);\n' % (self.reg_spec, op_desc.base_name)
+ wb = 'xc->set%s(%s);\n' % (self.reg_spec, self.base_name)
wb += 'if (traceData) { traceData->setData(%s); }' % \
- op_desc.base_name
+ self.base_name
return wb
-class MemOperandTraits(OperandTraits):
+class MemOperand(Operand):
def isMem(self):
return 1
- def makeConstructor(self, op_desc):
+ def makeConstructor(self):
return ''
- def makeDecl(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
+ def makeDecl(self):
# Note that initializations in the declarations are solely
# to avoid 'uninitialized variable' errors from the compiler.
# Declare memory data variable.
- c = '%s %s = 0;\n' % (type, op_desc.base_name)
+ c = '%s %s = 0;\n' % (self.ctype, self.base_name)
return c
- def makeRead(self, op_desc):
+ def makeRead(self):
return ''
- def makeWrite(self, op_desc):
+ def makeWrite(self):
return ''
# Return the memory access size *in bits*, suitable for
# forming a type via "uint%d_t". Divide by 8 if you want bytes.
- def makeAccSize(self, op_desc):
- (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
- return size
+ def makeAccSize(self):
+ return self.size
-class NPCOperandTraits(OperandTraits):
- def makeConstructor(self, op_desc):
+class NPCOperand(Operand):
+ def makeConstructor(self):
return ''
- def makeRead(self, op_desc):
- return '%s = xc->readPC() + 4;\n' % op_desc.base_name
-
- def makeWrite(self, op_desc):
- return 'xc->setNextPC(%s);\n' % op_desc.base_name
-
-
-exportContextSymbols = ('IntRegOperandTraits', 'FloatRegOperandTraits',
- 'ControlRegOperandTraits', 'MemOperandTraits',
- 'NPCOperandTraits', 'InstObjParams', 'CodeBlock',
- 'makeList', 're', 'string')
-
-exportContext = {}
-
-def updateExportContext():
- exportContext.update(exportDict(*exportContextSymbols))
- exportContext.update(templateMap)
-
+ def makeRead(self):
+ return '%s = xc->readPC() + 4;\n' % self.base_name
-def exportDict(*symNames):
- return dict([(s, eval(s)) for s in symNames])
+ def makeWrite(self):
+ return 'xc->setNextPC(%s);\n' % self.base_name
-#
-# Define operand variables that get derived from the basic declaration
-# of ISA-specific operands in operandTraitsMap. This function must be
-# called by the ISA description file explicitly after defining
-# operandTraitsMap (in a 'let' block).
-#
-def defineDerivedOperandVars():
- global operands
- operands = operandTraitsMap.keys()
+def buildOperandNameMap(userDict, lineno):
+ global operandNameMap
+ operandNameMap = {}
+ for (op_name, val) in userDict.iteritems():
+ (base_cls_name, dflt_ext, reg_spec, flags, sort_pri) = val
+ (dflt_size, dflt_ctype, dflt_is_signed) = operandTypeMap[dflt_ext]
+ # Canonical flag structure is a triple of lists, where each list
+ # indicates the set of flags implied by this operand always, when
+ # used as a source, and when used as a dest, respectively.
+ # For simplicity this can be initialized using a variety of fairly
+ # obvious shortcuts; we convert these to canonical form here.
+ if not flags:
+ # no flags specified (e.g., 'None')
+ flags = ( [], [], [] )
+ elif isinstance(flags, str):
+ # a single flag: assumed to be unconditional
+ flags = ( [ flags ], [], [] )
+ elif isinstance(flags, list):
+ # a list of flags: also assumed to be unconditional
+ flags = ( flags, [], [] )
+ elif isinstance(flags, tuple):
+ # it's a tuple: it should be a triple,
+ # but each item could be a single string or a list
+ (uncond_flags, src_flags, dest_flags) = flags
+ flags = (makeList(uncond_flags),
+ makeList(src_flags), makeList(dest_flags))
+ # Accumulate attributes of new operand class in tmp_dict
+ tmp_dict = {}
+ for attr in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri',
+ 'dflt_size', 'dflt_ctype', 'dflt_is_signed'):
+ tmp_dict[attr] = eval(attr)
+ tmp_dict['base_name'] = op_name
+ # New class name will be e.g. "IntReg_Ra"
+ cls_name = base_cls_name + '_' + op_name
+ # Evaluate string arg to get class object. Note that the
+ # actual base class for "IntReg" is "IntRegOperand", i.e. we
+ # have to append "Operand".
+ try:
+ base_cls = eval(base_cls_name + 'Operand')
+ except NameError:
+ error(lineno,
+ 'error: unknown operand base class "%s"' % base_cls_name)
+ # The following statement creates a new class called
+ # <cls_name> as a subclass of <base_cls> with the attributes
+ # in tmp_dict, just as if we evaluated a class declaration.
+ operandNameMap[op_name] = type(cls_name, (base_cls,), tmp_dict)
+
+ # Define operand variables.
+ operands = userDict.keys()
operandsREString = (r'''
(?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
@@ -1386,54 +1427,10 @@ def defineDerivedOperandVars():
operandsWithExtRE = re.compile(operandsWithExtREString, re.MULTILINE)
-#
-# Operand descriptor class. An instance of this class represents
-# a specific operand for a code block.
-#
-class OperandDescriptor:
- def __init__(self, full_name, base_name, ext, is_src, is_dest):
- self.full_name = full_name
- self.base_name = base_name
- self.ext = ext
- self.is_src = is_src
- self.is_dest = is_dest
- self.traits = operandTraitsMap[base_name]
- # The 'effective extension' (eff_ext) is either the actual
- # extension, if one was explicitly provided, or the default.
- if ext:
- self.eff_ext = ext
- else:
- self.eff_ext = self.traits.dflt_ext
-
- # note that mem_acc_size is undefined for non-mem operands...
- # template must be careful not to use it if it doesn't apply.
- if self.traits.isMem():
- self.mem_acc_size = self.traits.makeAccSize(self)
-
- # Finalize additional fields (primarily code fields). This step
- # is done separately since some of these fields may depend on the
- # register index enumeration that hasn't been performed yet at the
- # time of __init__().
- def finalize(self):
- self.flags = self.traits.getFlags(self)
- self.constructor = self.traits.makeConstructor(self)
- self.op_decl = self.traits.makeDecl(self)
-
- if self.is_src:
- self.op_rd = self.traits.makeRead(self)
- else:
- self.op_rd = ''
-
- if self.is_dest:
- self.op_wb = self.traits.makeWrite(self)
- else:
- self.op_wb = ''
-
-
-class OperandDescriptorList:
+class OperandList:
# Find all the operands in the given code block. Returns an operand
- # descriptor list (instance of class OperandDescriptorList).
+ # descriptor list (instance of class OperandList).
def __init__(self, code):
self.items = []
self.bases = {}
@@ -1463,8 +1460,8 @@ class OperandDescriptorList:
op_desc.is_dest = op_desc.is_dest or is_dest
else:
# new operand: create new descriptor
- op_desc = OperandDescriptor(op_full, op_base, op_ext,
- is_src, is_dest)
+ op_desc = operandNameMap[op_base](op_full, op_ext,
+ is_src, is_dest)
self.append(op_desc)
# start next search after end of current match
next_pos = match.end()
@@ -1477,18 +1474,18 @@ class OperandDescriptorList:
self.numIntDestRegs = 0
self.memOperand = None
for op_desc in self.items:
- if op_desc.traits.isReg():
+ if op_desc.isReg():
if op_desc.is_src:
op_desc.src_reg_idx = self.numSrcRegs
self.numSrcRegs += 1
if op_desc.is_dest:
op_desc.dest_reg_idx = self.numDestRegs
self.numDestRegs += 1
- if op_desc.traits.isFloatReg():
+ if op_desc.isFloatReg():
self.numFPDestRegs += 1
- elif op_desc.traits.isIntReg():
+ elif op_desc.isIntReg():
self.numIntDestRegs += 1
- elif op_desc.traits.isMem():
+ elif op_desc.isMem():
if self.memOperand:
error(0, "Code block has more than one memory operand.")
self.memOperand = op_desc
@@ -1540,7 +1537,7 @@ class OperandDescriptorList:
return self.__internalConcatAttrs(attr_name, filter, [])
def sort(self):
- self.items.sort(lambda a, b: a.traits.sort_pri - b.traits.sort_pri)
+ self.items.sort(lambda a, b: a.sort_pri - b.sort_pri)
# Regular expression object to match C++ comments
# (used in findOperands())
@@ -1552,7 +1549,7 @@ assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
# Munge operand names in code string to make legal C++ variable names.
# This means getting rid of the type extension if any.
-# (Will match base_name attribute of OperandDescriptor object.)
+# (Will match base_name attribute of Operand object.)
def substMungedOpNames(code):
return operandsWithExtRE.sub(r'\1', code)
@@ -1578,7 +1575,7 @@ def makeFlagConstructor(flag_list):
class CodeBlock:
def __init__(self, code):
self.orig_code = code
- self.operands = OperandDescriptorList(code)
+ self.operands = OperandList(code)
self.code = substMungedOpNames(substBitOps(code))
self.constructor = self.operands.concatAttrStrings('constructor')
self.constructor += \
diff --git a/arch/mips/isa/operands.isa b/arch/mips/isa/operands.isa
index 58fa2d3cf..c8e08a436 100644
--- a/arch/mips/isa/operands.isa
+++ b/arch/mips/isa/operands.isa
@@ -13,24 +13,23 @@ def operand_types {{
}};
def operands {{
- 'Rd': IntRegOperandTraits('uw', 'RD', 'IsInteger', 1),
- 'Rs': IntRegOperandTraits('uw', 'RS', 'IsInteger', 2),
- 'Rt': IntRegOperandTraits('uw', 'RT', 'IsInteger', 3),
+ 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 1),
+ 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2),
+ 'Rt': ('IntReg', 'uw', 'RT', 'IsInteger', 3),
- 'IntImm': IntRegOperandTraits('uw', 'INTIMM', 'IsInteger', 3),
- 'Sa': IntRegOperandTraits('uw', 'SA', 'IsInteger', 4),
+ 'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3),
+ 'Sa': ('IntReg', 'uw', 'SA', 'IsInteger', 4),
- 'Fd': FloatRegOperandTraits('sf', 'FD', 'IsFloating', 1),
- 'Fs': FloatRegOperandTraits('sf', 'FS', 'IsFloating', 2),
- 'Ft': FloatRegOperandTraits('sf', 'FT', 'IsFloating', 3),
+ 'Fd': ('FloatReg', 'sf', 'FD', 'IsFloating', 1),
+ 'Fs': ('FloatReg', 'sf', 'FS', 'IsFloating', 2),
+ 'Ft': ('FloatReg', 'sf', 'FT', 'IsFloating', 3),
- 'Mem': MemOperandTraits('udw', None,
- ('IsMemRef', 'IsLoad', 'IsStore'), 4)
+ 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4)
- #'NPC': NPCOperandTraits('uq', None, ( None, None, 'IsControl' ), 4),
- #'Runiq': ControlRegOperandTraits('uq', 'Uniq', None, 1),
- #'FPCR': ControlRegOperandTraits('uq', 'Fpcr', None, 1),
+ #'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
+ #'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1),
+ #'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1),
# The next two are hacks for non-full-system call-pal emulation
- #'R0': IntRegOperandTraits('uq', '0', None, 1),
- #'R16': IntRegOperandTraits('uq', '16', None, 1)
+ #'R0': ('IntReg', 'uq', '0', None, 1),
+ #'R16': ('IntReg', 'uq', '16', None, 1)
}};
diff --git a/arch/sparc/isa/operands.isa b/arch/sparc/isa/operands.isa
index 77de6c9c4..c5ba263d6 100644
--- a/arch/sparc/isa/operands.isa
+++ b/arch/sparc/isa/operands.isa
@@ -16,18 +16,17 @@ def operands {{
# Int regs default to unsigned, but code should not count on this.
# For clarity, descriptions that depend on unsigned behavior should
# explicitly specify '.uq'.
- 'Rd': IntRegOperandTraits('udw', 'RD', 'IsInteger', 1),
- 'Rs1': IntRegOperandTraits('udw', 'RS1', 'IsInteger', 2),
- 'Rs2': IntRegOperandTraits('udw', 'RS2', 'IsInteger', 3),
- #'Fa': FloatRegOperandTraits('df', 'FA', 'IsFloating', 1),
- #'Fb': FloatRegOperandTraits('df', 'FB', 'IsFloating', 2),
- #'Fc': FloatRegOperandTraits('df', 'FC', 'IsFloating', 3),
- 'Mem': MemOperandTraits('udw', None,
- ('IsMemRef', 'IsLoad', 'IsStore'), 4)
- #'NPC': NPCOperandTraits('uq', None, ( None, None, 'IsControl' ), 4),
- #'Runiq': ControlRegOperandTraits('uq', 'Uniq', None, 1),
- #'FPCR': ControlRegOperandTraits('uq', 'Fpcr', None, 1),
+ 'Rd': ('IntReg', 'udw', 'RD', 'IsInteger', 1),
+ 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 2),
+ 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 3),
+ #'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1),
+ #'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),
+ #'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
+ 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4)
+ #'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
+ #'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1),
+ #'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1),
# The next two are hacks for non-full-system call-pal emulation
- #'R0': IntRegOperandTraits('uq', '0', None, 1),
- #'R16': IntRegOperandTraits('uq', '16', None, 1)
+ #'R0': ('IntReg', 'uq', '0', None, 1),
+ #'R16': ('IntReg', 'uq', '16', None, 1)
}};