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:
parent
9277545ba6
commit
9da070ce8a
3 changed files with 283 additions and 317 deletions
|
@ -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):
|
||||
|
|
|
@ -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))
|
||||
}};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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);'
|
||||
}};
|
||||
|
|
Loading…
Reference in a new issue