diff -r d71efc6629d5 -r 168de5ae3706 src/arch/arm/isa/insts/misc.isa --- a/src/arch/arm/isa/insts/misc.isa Fri Aug 13 12:03:20 2010 -0500 +++ b/src/arch/arm/isa/insts/misc.isa Fri Aug 13 12:04:24 2010 -0500 @@ -462,7 +462,7 @@ decoder_output += RegRegRegRegOpConstructor.subst(usada8Iop) exec_output += PredOpExecute.subst(usada8Iop) - bkptIop = InstObjParams("bkpt", "BkptInst", "ArmStaticInst", + bkptIop = InstObjParams("bkpt", "BkptInst", "PredOp", "return new PrefetchAbort(PC, ArmFault::DebugEvent);") header_output += BasicDeclare.subst(bkptIop) decoder_output += BasicConstructor.subst(bkptIop) diff -r d71efc6629d5 -r 168de5ae3706 src/arch/arm/isa/operands.isa --- a/src/arch/arm/isa/operands.isa Fri Aug 13 12:03:20 2010 -0500 +++ b/src/arch/arm/isa/operands.isa Fri Aug 13 12:04:24 2010 -0500 @@ -81,6 +81,12 @@ } ''' + maybePCReset = ''' + if (%(reg_idx)s != PCReg) { + xc->%(func)s(this, %(op_idx)s, %(final_val)s); + } + ''' + readNPC = 'xc->readNextPC() & ~PcModeMask' writeNPC = 'setNextPC(xc, %(final_val)s)' writeIWNPC = 'setIWNextPC(xc, %(final_val)s)' @@ -90,35 +96,35 @@ def operands {{ #Abstracted integer reg operands 'Dest': ('IntReg', 'uw', 'dest', 'IsInteger', 2, - maybePCRead, maybePCWrite), + maybePCRead, maybePCWrite, maybePCReset), 'FpDest': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 2), 'FpDestP0': ('FloatReg', 'sf', '(dest + 0)', 'IsFloating', 2), 'FpDestP1': ('FloatReg', 'sf', '(dest + 1)', 'IsFloating', 2), 'FpDestP2': ('FloatReg', 'sf', '(dest + 2)', 'IsFloating', 2), 'FpDestP3': ('FloatReg', 'sf', '(dest + 3)', 'IsFloating', 2), 'Result': ('IntReg', 'uw', 'result', 'IsInteger', 2, - maybePCRead, maybePCWrite), + maybePCRead, maybePCWrite, maybePCReset), 'Dest2': ('IntReg', 'uw', 'dest2', 'IsInteger', 2, - maybePCRead, maybePCWrite), + maybePCRead, maybePCWrite, maybePCReset), 'FpDest2': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 2), 'FpDest2P0': ('FloatReg', 'sf', '(dest2 + 0)', 'IsFloating', 2), 'FpDest2P1': ('FloatReg', 'sf', '(dest2 + 1)', 'IsFloating', 2), 'FpDest2P2': ('FloatReg', 'sf', '(dest2 + 2)', 'IsFloating', 2), 'FpDest2P3': ('FloatReg', 'sf', '(dest2 + 3)', 'IsFloating', 2), 'IWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 2, - maybePCRead, maybeIWPCWrite), + maybePCRead, maybeIWPCWrite, maybePCReset), 'AIWDest': ('IntReg', 'uw', 'dest', 'IsInteger', 2, - maybePCRead, maybeAIWPCWrite), + maybePCRead, maybeAIWPCWrite, maybePCReset), 'SpMode': ('IntReg', 'uw', 'intRegInMode((OperatingMode)regMode, INTREG_SP)', 'IsInteger', 2), 'MiscDest': ('ControlReg', 'uw', 'dest', (None, None, 'IsControl'), 2), 'Base': ('IntReg', 'uw', 'base', 'IsInteger', 0, - maybeAlignedPCRead, maybePCWrite), + maybeAlignedPCRead, maybePCWrite, maybePCReset), 'Index': ('IntReg', 'uw', 'index', 'IsInteger', 2, - maybePCRead, maybePCWrite), + maybePCRead, maybePCWrite, maybePCReset), 'Op1': ('IntReg', 'uw', 'op1', 'IsInteger', 2, - maybePCRead, maybePCWrite), + maybePCRead, maybePCWrite, maybePCReset), 'FpOp1': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 2), 'FpOp1P0': ('FloatReg', 'sf', '(op1 + 0)', 'IsFloating', 2), 'FpOp1P1': ('FloatReg', 'sf', '(op1 + 1)', 'IsFloating', 2), @@ -126,29 +132,29 @@ 'FpOp1P3': ('FloatReg', 'sf', '(op1 + 3)', 'IsFloating', 2), 'MiscOp1': ('ControlReg', 'uw', 'op1', (None, None, 'IsControl'), 2), 'Op2': ('IntReg', 'uw', 'op2', 'IsInteger', 2, - maybePCRead, maybePCWrite), + maybePCRead, maybePCWrite, maybePCReset), 'FpOp2': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 2), 'FpOp2P0': ('FloatReg', 'sf', '(op2 + 0)', 'IsFloating', 2), 'FpOp2P1': ('FloatReg', 'sf', '(op2 + 1)', 'IsFloating', 2), 'FpOp2P2': ('FloatReg', 'sf', '(op2 + 2)', 'IsFloating', 2), 'FpOp2P3': ('FloatReg', 'sf', '(op2 + 3)', 'IsFloating', 2), 'Op3': ('IntReg', 'uw', 'op3', 'IsInteger', 2, - maybePCRead, maybePCWrite), + maybePCRead, maybePCWrite, maybePCReset), 'Shift': ('IntReg', 'uw', 'shift', 'IsInteger', 2, - maybePCRead, maybePCWrite), + maybePCRead, maybePCWrite, maybePCReset), 'Reg0': ('IntReg', 'uw', 'reg0', 'IsInteger', 2, - maybePCRead, maybePCWrite), + maybePCRead, maybePCWrite, maybePCReset), 'Reg1': ('IntReg', 'uw', 'reg1', 'IsInteger', 2, - maybePCRead, maybePCWrite), + maybePCRead, maybePCWrite, maybePCReset), 'Reg2': ('IntReg', 'uw', 'reg2', 'IsInteger', 2, - maybePCRead, maybePCWrite), + maybePCRead, maybePCWrite, maybePCReset), 'Reg3': ('IntReg', 'uw', 'reg3', 'IsInteger', 2, - maybePCRead, maybePCWrite), + maybePCRead, maybePCWrite, maybePCReset), #General Purpose Integer Reg Operands - 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2, maybePCRead, maybePCWrite), - 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 2, maybePCRead, maybePCWrite), + 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 2, maybePCRead, maybePCWrite, maybePCReset), + 'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 2, maybePCRead, maybePCWrite, maybePCReset), + 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2, maybePCRead, maybePCWrite, maybePCReset), + 'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 2, maybePCRead, maybePCWrite, maybePCReset), 'R7': ('IntReg', 'uw', '7', 'IsInteger', 2), 'R0': ('IntReg', 'uw', '0', 'IsInteger', 2), @@ -159,11 +165,11 @@ INTREG_ZERO : INTREG_CONDCODES''', None, 2), #Register fields for microops - 'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 2, maybePCRead, maybePCWrite), + 'Ra' : ('IntReg', 'uw', 'ura', 'IsInteger', 2, maybePCRead, maybePCWrite, maybePCReset), 'IWRa' : ('IntReg', 'uw', 'ura', 'IsInteger', 2, - maybePCRead, maybeIWPCWrite), + maybePCRead, maybeIWPCWrite, maybePCReset), 'Fa' : ('FloatReg', 'sf', 'ura', 'IsFloating', 2), - 'Rb' : ('IntReg', 'uw', 'urb', 'IsInteger', 2, maybePCRead, maybePCWrite), + 'Rb' : ('IntReg', 'uw', 'urb', 'IsInteger', 2, maybePCRead, maybePCWrite, maybePCReset), #General Purpose Floating Point Reg Operands 'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 2), diff -r d71efc6629d5 -r 168de5ae3706 src/arch/arm/isa/templates/mem.isa --- a/src/arch/arm/isa/templates/mem.isa Fri Aug 13 12:03:20 2010 -0500 +++ b/src/arch/arm/isa/templates/mem.isa Fri Aug 13 12:04:24 2010 -0500 @@ -71,6 +71,7 @@ } } else { xc->setPredicatedFalse(true); + %(resetcode)s; } if (fault == NoFault && machInst.itstateMask != 0) { @@ -107,6 +108,7 @@ } } else { xc->setPredicatedFalse(true); + %(resetcode)s; } if (fault == NoFault && machInst.itstateMask != 0) { @@ -170,6 +172,7 @@ } } else { xc->setPredicatedFalse(true); + %(resetcode)s; } if (fault == NoFault && machInst.itstateMask != 0) { @@ -207,6 +210,7 @@ } } else { xc->setPredicatedFalse(true); + %(resetcode)s; } if (fault == NoFault && machInst.itstateMask != 0) { @@ -250,6 +254,7 @@ } } else { xc->setPredicatedFalse(true); + %(resetcode)s; } if (fault == NoFault && machInst.itstateMask != 0) { @@ -288,6 +293,7 @@ } } else { xc->setPredicatedFalse(true); + %(resetcode)s; } if (fault == NoFault && machInst.itstateMask != 0) { @@ -326,6 +332,7 @@ } } else { xc->setPredicatedFalse(true); + %(resetcode)s; } if (fault == NoFault && machInst.itstateMask != 0) { @@ -354,6 +361,7 @@ } } else { xc->setPredicatedFalse(true); + %(resetcode)s if (fault == NoFault && machInst.itstateMask != 0) { xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); } diff -r d71efc6629d5 -r 168de5ae3706 src/arch/arm/isa/templates/pred.isa --- a/src/arch/arm/isa/templates/pred.isa Fri Aug 13 12:03:20 2010 -0500 +++ b/src/arch/arm/isa/templates/pred.isa Fri Aug 13 12:04:24 2010 -0500 @@ -144,6 +144,7 @@ } } else { xc->setPredicatedFalse(true); + %(resetcode)s; } if (fault == NoFault && machInst.itstateMask != 0) { diff -r d71efc6629d5 -r 168de5ae3706 src/arch/isa_parser.py --- a/src/arch/isa_parser.py Fri Aug 13 12:03:20 2010 -0500 +++ b/src/arch/isa_parser.py Fri Aug 13 12:04:24 2010 -0500 @@ -1,3 +1,15 @@ +# Copyright (c) 2010 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# # Copyright (c) 2003-2005 The Regents of The University of Michigan # All rights reserved. # @@ -168,6 +180,11 @@ # operands explicitly (like Mem) compositeCode += ' ' + template + # operands of resetcode are not in the compositeCode, because + # we do not want make destination registers as source when + # instructions are not predicated (common case) + myDict['resetcode'] = d.operands.concatAttrStrings('resetcode') + operands = SubOperandList(self.parser, compositeCode, d.operands) myDict['op_decl'] = operands.concatAttrStrings('op_decl') @@ -387,16 +404,20 @@ derived classes encapsulates the traits of a particular operand type (e.g., "32-bit integer register").''' - def buildReadCode(self, func = None): + def buildReadCode(self, func = None, rd_reg_idx = None, whole = False): subst_dict = {"name": self.base_name, "func": func, "reg_idx": self.reg_spec, "size": self.size, "ctype": self.ctype} - if hasattr(self, 'src_reg_idx'): - subst_dict['op_idx'] = self.src_reg_idx + if rd_reg_idx is None: + if hasattr(self, 'src_reg_idx'): + subst_dict['op_idx'] = self.src_reg_idx + else: + subst_dict['op_idx'] = rd_reg_idx + code = self.read_code % subst_dict - if self.size != self.dflt_size: + if self.size != self.dflt_size and not whole: return '%s = bits(%s, %d, 0);\n' % \ (self.base_name, code, self.size-1) else: @@ -424,6 +445,27 @@ if (traceData) { traceData->setData(final_val); } }''' % (self.dflt_ctype, final_val, code) + def buildResetCode(self, func = None): + if (self.size != self.dflt_size and self.is_signed): + final_val = 'sext<%d>(%s)' % (self.size, self.base_name) + else: + final_val = self.base_name + subst_dict = {"name": self.base_name, + "func": func, + "reg_idx": self.reg_spec, + "size": self.size, + "ctype": self.ctype, + "final_val": final_val} + if hasattr(self, 'dest_reg_idx'): + subst_dict['op_idx'] = self.dest_reg_idx + code = self.reset_code % subst_dict + return ''' + { + %s final_val = %s; + %s; + if (traceData) { traceData->setData(final_val); } + }''' % (self.dflt_ctype, final_val, code) + def __init__(self, parser, full_name, ext, is_src, is_dest): self.full_name = full_name self.ext = ext @@ -452,7 +494,7 @@ # 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): + def finalize(self, numSrcRegs): self.flags = self.getFlags() self.constructor = self.makeConstructor() self.op_decl = self.makeDecl() @@ -471,6 +513,16 @@ self.op_wb = '' self.op_dest_decl = '' + # Resetcode simply reads from the operand and write the read + # value back to it. It is used when an instruction's destination + # register is renamed, but its execution is predicated false. + # It copies the value from the old physical reg to the newly + # mapped physical register + if self.is_dest and self.isReg(): + self.resetcode = self.makeReset(numSrcRegs) + else: + self.resetcode = '' + def isMem(self): return 0 @@ -501,6 +553,10 @@ # to avoid 'uninitialized variable' errors from the compiler. return self.ctype + ' ' + self.base_name + ' = 0;\n'; + def makeReset(self, numSrcRegs): + reset = '' + return reset + class IntRegOperand(Operand): def isReg(self): return 1 @@ -518,23 +574,28 @@ (self.dest_reg_idx, self.reg_spec) return c - def makeRead(self): + def makeRead(self, rd_reg_idx = None, whole = False): + if rd_reg_idx is None: + rd_reg_idx = self.src_reg_idx if (self.ctype == 'float' or self.ctype == 'double'): error('Attempt to read integer register as FP') if self.read_code != None: - return self.buildReadCode('readIntRegOperand') + return self.buildReadCode('readIntRegOperand', rd_reg_idx, whole) if (self.size == self.dflt_size): return '%s = xc->readIntRegOperand(this, %d);\n' % \ - (self.base_name, self.src_reg_idx) + (self.base_name, rd_reg_idx) elif (self.size > self.dflt_size): int_reg_val = 'xc->readIntRegOperand(this, %d)' % \ - (self.src_reg_idx) + (rd_reg_idx) if (self.is_signed): int_reg_val = 'sext<%d>(%s)' % (self.dflt_size, int_reg_val) return '%s = %s;\n' % (self.base_name, int_reg_val) + elif (whole): + return '%s = xc->readIntRegOperand(this, %d);\n' % \ + (self.base_name, rd_reg_idx) else: return '%s = bits(xc->readIntRegOperand(this, %d), %d, 0);\n' % \ - (self.base_name, self.src_reg_idx, self.size-1) + (self.base_name, rd_reg_idx, self.size-1) def makeWrite(self): if (self.ctype == 'float' or self.ctype == 'double'): @@ -553,6 +614,28 @@ }''' % (self.dflt_ctype, final_val, self.dest_reg_idx) return wb + def makeReset(self, numSrcRegs): + reset = '' + reset += self.dflt_ctype + ' ' + self.base_name + ' = 0;\n'; + reset += self.makeRead(self.dest_reg_idx + numSrcRegs, True) + if (self.ctype == 'float' or self.ctype == 'double'): + error('Attempt to write integer register as FP') + if self.reset_code != None: + reset += self.buildResetCode('setIntRegOperand') + return reset + if (self.size != self.dflt_size and self.is_signed): + final_val = 'sext<%d>(%s)' % (self.size, self.base_name) + else: + final_val = self.base_name + wb = ''' + { + %s final_val = %s; + xc->setIntRegOperand(this, %d, final_val);\n + if (traceData) { traceData->setData(final_val); } + }''' % (self.dflt_ctype, final_val, self.dest_reg_idx) + reset += wb + return reset + class FloatRegOperand(Operand): def isReg(self): return 1 @@ -570,7 +653,9 @@ (self.dest_reg_idx, self.reg_spec) return c - def makeRead(self): + def makeRead(self, rd_reg_idx = None, whole = False): + if rd_reg_idx is None: + rd_reg_idx = self.src_reg_idx bit_select = 0 if (self.ctype == 'float' or self.ctype == 'double'): func = 'readFloatRegOperand' @@ -578,10 +663,10 @@ func = 'readFloatRegOperandBits' if (self.size != self.dflt_size): bit_select = 1 - base = 'xc->%s(this, %d)' % (func, self.src_reg_idx) + base = 'xc->%s(this, %d)' % (func, rd_reg_idx) if self.read_code != None: - return self.buildReadCode(func) - if bit_select: + return self.buildReadCode(func, rd_reg_idx, whole) + if bit_select and not whole: return '%s = bits(%s, %d, 0);\n' % \ (self.base_name, base, self.size-1) else: @@ -609,6 +694,34 @@ }''' % (final_ctype, final_val, func, self.dest_reg_idx) return wb + def makeReset(self, numSrcRegs): + reset = '' + final_val = self.base_name + final_ctype = self.ctype + if (self.ctype == 'float' or self.ctype == 'double'): + func = 'setFloatRegOperand' + elif (self.ctype == 'uint32_t' or self.ctype == 'uint64_t'): + func = 'setFloatRegOperandBits' + else: + func = 'setFloatRegOperandBits' + 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 = '' + if self.reset_code != None: + wb = self.buildResetCode(func) + else: + wb = ''' + { + %s final_val = %s; + xc->%s(this, %d, final_val);\n + if (traceData) { traceData->setData(final_val); } + }''' % (final_ctype, final_val, func, self.dest_reg_idx) + reset += final_ctype + ' ' + self.base_name + ' = 0;\n'; + reset += self.makeRead(self.dest_reg_idx + numSrcRegs, True) + reset += wb + return reset + class ControlRegOperand(Operand): def isReg(self): return 1 @@ -626,14 +739,17 @@ (self.dest_reg_idx, self.reg_spec) return c - def makeRead(self): + def makeRead(self, rd_reg_idx = None, whole = False): + if rd_reg_idx is None: + rd_reg_idx = self.src_reg_idx bit_select = 0 if (self.ctype == 'float' or self.ctype == 'double'): error('Attempt to read control register as FP') if self.read_code != None: - return self.buildReadCode('readMiscRegOperand') - base = 'xc->readMiscRegOperand(this, %s)' % self.src_reg_idx - if self.size == self.dflt_size: + return self.buildReadCode('readMiscRegOperand', rd_reg_idx, + whole) + base = 'xc->readMiscRegOperand(this, %s)' % rd_reg_idx + if self.size == self.dflt_size or whole: return '%s = %s;\n' % (self.base_name, base) else: return '%s = bits(%s, %d, 0);\n' % \ @@ -650,6 +766,22 @@ self.base_name return wb + def makeReset(self, numSrcRegs): + reset = '' + reset = self.ctype + ' ' + self.base_name + ' = 0;\n'; + reset += self.makeRead(self.dest_reg_idx + numSrcRegs, True) + if (self.ctype == 'float' or self.ctype == 'double'): + error('Attempt to write control register as FP') + if self.reset_code != None: + reset += self.buildResetCode('setMiscRegOperand') + return reset + wb = 'xc->setMiscRegOperand(this, %s, %s);\n' % \ + (self.dest_reg_idx, self.base_name) + wb += 'if (traceData) { traceData->setData(%s); }' % \ + self.base_name + reset += wb + return reset + class MemOperand(Operand): def isMem(self): return 1 @@ -676,6 +808,9 @@ return self.buildWriteCode() return '' + def makeReset(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): @@ -691,6 +826,9 @@ def makeWrite(self): return 'xc->setPC(%s);\n' % self.base_name + def makeReset(self): + return '' + class UPCOperand(Operand): def makeConstructor(self): return '' @@ -705,6 +843,9 @@ return self.buildWriteCode('setMicroPC') return 'xc->setMicroPC(%s);\n' % self.base_name + def makeReset(self): + return '' + class NUPCOperand(Operand): def makeConstructor(self): return '' @@ -719,6 +860,9 @@ return self.buildWriteCode('setNextMicroPC') return 'xc->setNextMicroPC(%s);\n' % self.base_name + def makeReset(self): + return '' + class NPCOperand(Operand): def makeConstructor(self): return '' @@ -733,6 +877,9 @@ return self.buildWriteCode('setNextPC') return 'xc->setNextPC(%s);\n' % self.base_name + def makeReset(self): + return '' + class NNPCOperand(Operand): def makeConstructor(self): return '' @@ -747,6 +894,9 @@ return self.buildWriteCode('setNextNPC') return 'xc->setNextNPC(%s);\n' % self.base_name + def makeReset(self): + return '' + class OperandList(object): '''Find all the operands in the given code block. Returns an operand descriptor list (instance of class OperandList).''' @@ -808,14 +958,14 @@ if self.memOperand: error("Code block has more than one memory operand.") self.memOperand = op_desc - if parser.maxInstSrcRegs < self.numSrcRegs: - parser.maxInstSrcRegs = self.numSrcRegs + if parser.maxInstSrcRegs < (self.numSrcRegs + self.numDestRegs): + parser.maxInstSrcRegs = (self.numSrcRegs + self.numDestRegs) if parser.maxInstDestRegs < self.numDestRegs: parser.maxInstDestRegs = self.numDestRegs # now make a final pass to finalize op_desc fields that may depend # on the register enumeration for op_desc in self.items: - op_desc.finalize() + op_desc.finalize(self.numSrcRegs) def __len__(self): return len(self.items) @@ -953,6 +1103,22 @@ '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs self.constructor += \ '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs + + # This part will only work with Arm PredOps + # It is here because the constructor code is not customizable + # This code makes destination registers source registers only if + # the condition code of the StaticInst is not unconditonal or + # always_execute. To support register-renaming with predication. + self.constructor += '\n#ifdef TARGET_ARM\n' + self.constructor += \ + '\n\tif (!(condCode == COND_AL || condCode == COND_UC)) {' + rangelist = range(self.operands.numDestRegs) + for number in rangelist: + self.constructor +=''' + _srcRegIdx[_numSrcRegs++] = _destRegIdx[%d];''' % number + self.constructor += '\n\t}' + self.constructor += '\n#endif // end of TARGET_ARM\n' + self.flags = self.operands.concatAttrLists('flags') # Make a basic guess on the operand class (function unit type). @@ -1871,6 +2037,10 @@ else: write_code = None if len(val) > 7: + reset_code = val[7] + else: + reset_code = None + if len(val) > 8: error(lineno, 'error: too many attributes for operand "%s"' % base_cls_name) @@ -1901,7 +2071,7 @@ tmp_dict = {} for attr in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri', 'dflt_size', 'dflt_ctype', 'dflt_is_signed', - 'read_code', 'write_code'): + 'read_code', 'write_code', 'reset_code'): tmp_dict[attr] = eval(attr) tmp_dict['base_name'] = op_name # New class name will be e.g. "IntReg_Ra"