From 9da070ce8a9cf40452b44621808586a5d2c2a189 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 31 Aug 2007 22:28:07 -0700 Subject: [PATCH] X86: Major rework of how regop microops are generated. 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 | 3 +- src/arch/x86/isa/microops/base.isa | 4 +- src/arch/x86/isa/microops/regop.isa | 593 +++++++++++++--------------- 3 files changed, 283 insertions(+), 317 deletions(-) diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa index fdfea6136..3f33c8cfe 100644 --- a/src/arch/x86/isa/macroop.isa +++ b/src/arch/x86/isa/macroop.isa @@ -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): diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa index 71fc3b3a5..9722f182e 100644 --- a/src/arch/x86/isa/microops/base.isa +++ b/src/arch/x86/isa/microops/base.isa @@ -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)) }}; ////////////////////////////////////////////////////////////////////////// diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index eca640d35..a0477dab7 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -228,313 +228,235 @@ def template MicroRegOpImmConstructor {{ }}; let {{ - class X86MicroMeta(type): - def __new__(mcls, name, bases, dict): - abstract = False - if "abstract" in dict: - abstract = dict['abstract'] - del dict['abstract'] - - cls = type.__new__(mcls, name, bases, dict) - if not abstract: - allClasses[name] = cls - return cls - - class XXX86Microop(object): - __metaclass__ = X86MicroMeta - abstract = True - - class RegOp(X86Microop): - abstract = True - def __init__(self, dest, src1, src2, flags, dataSize): - self.dest = dest - self.src1 = src1 - self.src2 = src2 - 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" - - def getAllocator(self, *microFlags): - allocator = '''new %(class_name)s(machInst, mnemonic - %(flags)s, %(src1)s, %(src2)s, %(dest)s, - %(dataSize)s, %(ext)s)''' % { - "class_name" : self.className, - "flags" : self.microFlagsText(microFlags), - "src1" : self.src1, "src2" : self.src2, - "dest" : self.dest, - "dataSize" : self.dataSize, - "ext" : self.ext} - return allocator - - class RegOpImm(X86Microop): - 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" - - 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 -}}; - -let {{ - # Make these empty strings so that concatenating onto # them will always work. header_output = "" decoder_output = "" exec_output = "" - # 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 + immTemplates = ( + MicroRegOpImmDeclare, + MicroRegOpImmConstructor, + MicroRegOpImmExecute) - 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) + 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\\.\\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+)?") + if matcher.search(allCode): + microopClasses[name + 'i'] = cls + return cls - # 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() + class RegOp(X86Microop): + __metaclass__ = RegOpMeta + # This class itself doesn't act as a microop + abstract = True - # 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\\.\\w+)?") - regCode = regPick + matcher.sub("psrc2", code) - immCode = immPick + matcher.sub("imm8", code) + # Default template parameter values + flag_code = "" + cond_check = "true" + else_code = ";" - if not cc: - condCode = "true" - else: - flagCode = "" - condCode = checkCCFlagBits + def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"): + self.dest = dest + self.src1 = src1 + self.op2 = op2 + 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" - regFlagCode = matcher.sub("psrc2", flagCode) - immFlagCode = matcher.sub("imm8", flagCode) + 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, %(op2)s, %(dest)s, + %(dataSize)s, %(ext)s)''' % { + "class_name" : className, + "flags" : self.microFlagsText(microFlags), + "src1" : self.src1, "op2" : self.op2, + "dest" : self.dest, + "dataSize" : self.dataSize, + "ext" : self.ext} + return allocator - 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) + class LogicRegOp(RegOp): + abstract = True + 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); + ''' - microopClasses[name] = RegOpChild + class FlagRegOp(RegOp): + abstract = True + flag_code = \ + "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);" - setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode); - setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp", - regCode, flagCode=regFlagCode, - condCheck=condCode, elseCode=elseCode); + class SubRegOp(RegOp): + abstract = True + flag_code = \ + "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);" - 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) + class CondRegOp(RegOp): + abstract = True + cond_check = "checkCondition(ccFlagBits)" - microopClasses[name + 'i'] = RegOpChildImm + class Add(FlagRegOp): + code = 'DestReg = merge(DestReg, psrc1 + op2, dataSize);' - 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); + class Or(LogicRegOp): + code = 'DestReg = merge(DestReg, psrc1 | op2, dataSize);' - # 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\\.\\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) + class Divq(FlagRegOp): + code = 'DestReg = merge(DestReg, psrc1 / op2, dataSize);' - defineMicroRegOp('Movfp', - 'FpDestReg = FpSrcReg2 + psrc1 * 0 + psrc2 * 0', - elseCode='FpDestReg=FpDestReg;', cc=True, doImm=False) + 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); - ''') + ''' + def __init__(self, dest, imm, flags=None, \ + dataSize="env.dataSize"): + super(Ruflag, self).__init__(dest, \ + "NUM_INTREGS", imm, flags, dataSize) - defineMicroRegOpImm('Sext', ''' + 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);' }};