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
This commit is contained in:
Gabe Black 2007-08-31 22:28:07 -07:00
parent 9277545ba6
commit 9da070ce8a
3 changed files with 283 additions and 317 deletions

View file

@ -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):

View file

@ -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))
}};
//////////////////////////////////////////////////////////////////////////

View file

@ -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<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)
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);
'''
def __new__(mcls, Name, bases, dict):
abstract = False
name = Name.lower()
if "abstract" in dict:
abstract = dict['abstract']
del dict['abstract']
regPick = '''
IntReg psrc1 = pick(SrcReg1, 0, dataSize);
IntReg psrc2 = pick(SrcReg2, 1, dataSize);
'''
immPick = '''
IntReg psrc1 = pick(SrcReg1, 0, dataSize);
'''
cls = super(RegOpMeta, mcls).__new__(mcls, Name, bases, dict)
if not abstract:
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
# 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<typeQual>\\.\\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<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)
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);'
}};