summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-08-31 22:28:07 -0700
committerGabe Black <gblack@eecs.umich.edu>2007-08-31 22:28:07 -0700
commit9da070ce8a9cf40452b44621808586a5d2c2a189 (patch)
tree85d55c9bce21dde66c44f9037c5921edacd958db /src
parent9277545ba6b9a7756c34f90626860e44a833847d (diff)
downloadgem5-9da070ce8a9cf40452b44621808586a5d2c2a189.tar.xz
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
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86/isa/macroop.isa3
-rw-r--r--src/arch/x86/isa/microops/base.isa4
-rw-r--r--src/arch/x86/isa/microops/regop.isa569
3 files changed, 271 insertions, 305 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,28 +228,137 @@ def template MicroRegOpImmConstructor {{
}};
let {{
- class X86MicroMeta(type):
- def __new__(mcls, name, bases, dict):
+ # Make these empty strings so that concatenating onto
+ # them will always work.
+ header_output = ""
+ decoder_output = ""
+ exec_output = ""
+
+ immTemplates = (
+ MicroRegOpImmDeclare,
+ MicroRegOpImmConstructor,
+ MicroRegOpImmExecute)
+
+ 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<typeQual>\\.\\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)psrc1(?!\w)")
+ if matcher.search(allCode):
+ code = "IntReg psrc1 = pick(SrcReg1, 0, dataSize);" + code
+ matcher = re.compile("(?<!\w)psrc2(?!\w)")
+ if matcher.search(allCode):
+ code = "IntReg psrc2 = pick(SrcReg2, 1, dataSize);" + code
+
+ base = "X86ISA::RegOp"
+
+ # If imm8 shows up in the code, use the immediate templates, if
+ # not, hopefully the register ones will be correct.
+ templates = regTemplates
+ matcher = re.compile("(?<!\w)imm8(?!\w)")
+ if matcher.search(allCode):
+ base += "Imm"
+ templates = immTemplates
+
+ # Get everything ready for the substitution
+ iop = InstObjParams(name, Name + suffix, base,
+ {"code" : code,
+ "flag_code" : flag_code,
+ "cond_check" : cond_check,
+ "else_code" : else_code})
+
+ # Generate the actual code (finally!)
+ header_output += templates[0].subst(iop)
+ decoder_output += templates[1].subst(iop)
+ exec_output += templates[2].subst(iop)
+
+
+ def __new__(mcls, Name, bases, dict):
abstract = False
+ name = Name.lower()
if "abstract" in dict:
abstract = dict['abstract']
del dict['abstract']
- cls = type.__new__(mcls, name, bases, dict)
+ cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict)
if not abstract:
- allClasses[name] = cls
+ cls.className = Name
+ cls.base_mnemonic = name
+ code = cls.code
+ flag_code = cls.flag_code
+ cond_check = cls.cond_check
+ else_code = cls.else_code
+
+ # Set up the C++ classes
+ mcls.buildCppClasses(cls, name, Name, "",
+ code, flag_code, cond_check, else_code)
+
+ # Hook into the microassembler dict
+ global microopClasses
+ microopClasses[name] = cls
+
+ 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<typeQual>\\.\\w+)?")
+ if matcher.search(allCode):
+ microopClasses[name + 'i'] = cls
return cls
- class XXX86Microop(object):
- __metaclass__ = X86MicroMeta
- abstract = True
class RegOp(X86Microop):
+ __metaclass__ = RegOpMeta
+ # This class itself doesn't act as a microop
abstract = True
- def __init__(self, dest, src1, src2, flags, dataSize):
+
+ # Default template parameter values
+ flag_code = ""
+ cond_check = "true"
+ else_code = ";"
+
+ def __init__(self, dest, src1, op2, flags = None, dataSize = "env.dataSize"):
self.dest = dest
self.src1 = src1
- self.src2 = src2
+ self.op2 = op2
self.flags = flags
self.dataSize = dataSize
if flags is None:
@@ -261,280 +370,93 @@ let {{
self.className += "Flags"
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, %(src2)s, %(dest)s,
+ %(flags)s, %(src1)s, %(op2)s, %(dest)s,
%(dataSize)s, %(ext)s)''' % {
- "class_name" : self.className,
+ "class_name" : className,
"flags" : self.microFlagsText(microFlags),
- "src1" : self.src1, "src2" : self.src2,
+ "src1" : self.src1, "op2" : self.op2,
"dest" : self.dest,
"dataSize" : self.dataSize,
"ext" : self.ext}
return allocator
- class RegOpImm(X86Microop):
+ class LogicRegOp(RegOp):
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"
+ 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);
+ '''
+
+ class FlagRegOp(RegOp):
+ abstract = True
+ flag_code = \
+ "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);"
- 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
-}};
+ class SubRegOp(RegOp):
+ abstract = True
+ flag_code = \
+ "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);"
-let {{
+ class CondRegOp(RegOp):
+ abstract = True
+ cond_check = "checkCondition(ccFlagBits)"
- # Make these empty strings so that concatenating onto
- # them will always work.
- header_output = ""
- decoder_output = ""
- exec_output = ""
+ class Add(FlagRegOp):
+ code = 'DestReg = merge(DestReg, psrc1 + op2, dataSize);'
+
+ class Or(LogicRegOp):
+ code = 'DestReg = merge(DestReg, psrc1 | op2, dataSize);'
- # 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
-
- 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)
-
-
- checkCCFlagBits = "checkCondition(ccFlagBits)"
- genCCFlagBits = \
- "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, op2);"
- genCCFlagBitsSub = \
- "ccFlagBits = genFlags(ccFlagBits, ext, DestReg, psrc1, ~op2, true);"
- genCCFlagBitsLogic = '''
- //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);
- '''
-
- regPick = '''
- IntReg psrc1 = pick(SrcReg1, 0, dataSize);
- IntReg psrc2 = pick(SrcReg2, 1, dataSize);
- '''
- immPick = '''
- IntReg psrc1 = pick(SrcReg1, 0, dataSize);
- '''
-
-
- # 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()
-
- # 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<typeQual>\\.\\w+)?")
- regCode = regPick + matcher.sub("psrc2", code)
- immCode = immPick + matcher.sub("imm8", code)
-
- if not cc:
- condCode = "true"
- else:
- flagCode = ""
- condCode = checkCCFlagBits
-
- regFlagCode = matcher.sub("psrc2", flagCode)
- immFlagCode = matcher.sub("imm8", flagCode)
-
- 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)
-
- microopClasses[name] = RegOpChild
-
- setUpMicroRegOp(name, Name, "X86ISA::RegOp", regCode);
- setUpMicroRegOp(name, Name + "Flags", "X86ISA::RegOp",
- regCode, flagCode=regFlagCode,
- condCheck=condCode, elseCode=elseCode);
-
- 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)
-
- microopClasses[name + 'i'] = RegOpChildImm
-
- 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);
-
- # 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<typeQual>\\.\\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)
-
- defineMicroRegOp('Movfp',
- 'FpDestReg = FpSrcReg2 + psrc1 * 0 + psrc2 * 0',
- elseCode='FpDestReg=FpDestReg;', cc=True, doImm=False)
+ '''
+
+ class Divq(FlagRegOp):
+ code = 'DestReg = merge(DestReg, psrc1 / op2, dataSize);'
+
+ 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);
- ''')
-
- defineMicroRegOpImm('Sext', '''
+ '''
+ def __init__(self, dest, imm, flags=None, \
+ dataSize="env.dataSize"):
+ super(Ruflag, self).__init__(dest, \
+ "NUM_INTREGS", imm, flags, dataSize)
+
+ 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);'
}};