Reworked x86 a bit
--HG-- extra : convert_revision : def1a30e54b59c718c451a631a1be6f8e787e843
This commit is contained in:
@@ -72,7 +72,7 @@ def format Inst(*opTypeSet) {{
|
||||
(header_output,
|
||||
decoder_output,
|
||||
decode_block,
|
||||
exec_output) = doInst(name, Name, list(opTypeSet))
|
||||
exce_output) = doInst(name, Name, list(opTypeSet)).makeList()
|
||||
}};
|
||||
|
||||
def format MultiInst(switchVal, *opTypeSets) {{
|
||||
@@ -82,5 +82,5 @@ def format MultiInst(switchVal, *opTypeSets) {{
|
||||
(header_output,
|
||||
decoder_output,
|
||||
decode_block,
|
||||
exec_output) = doSplitDecode(name, Name, doInst, switchVal, switcher)
|
||||
exec_output) = doSplitDecode(name, Name, doInst, switchVal, switcher).makeList()
|
||||
}};
|
||||
|
||||
@@ -55,26 +55,30 @@
|
||||
//
|
||||
// Authors: Gabe Black
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Architecture independent
|
||||
//
|
||||
|
||||
// Execute method for macroops.
|
||||
def template MacroExecPanic {{
|
||||
Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
|
||||
{
|
||||
panic("Tried to execute macroop directly!");
|
||||
M5_DUMMY_RETURN
|
||||
return NoFault;
|
||||
}
|
||||
}};
|
||||
|
||||
output header {{
|
||||
|
||||
// Base class for most macroops, except ones that need to commit as
|
||||
// they go.
|
||||
class X86MacroInst : public StaticInst
|
||||
// Base class for macroops
|
||||
class MacroOp : public StaticInst
|
||||
{
|
||||
protected:
|
||||
const uint32_t numMicroOps;
|
||||
|
||||
//Constructor.
|
||||
X86MacroInst(const char *mnem, ExtMachInst _machInst,
|
||||
MacroOp(const char *mnem, ExtMachInst _machInst,
|
||||
uint32_t _numMicroOps)
|
||||
: StaticInst(mnem, _machInst, No_OpClass),
|
||||
numMicroOps(_numMicroOps)
|
||||
@@ -84,7 +88,7 @@ output header {{
|
||||
flags[IsMacroOp] = true;
|
||||
}
|
||||
|
||||
~X86MacroInst()
|
||||
~MacroOp()
|
||||
{
|
||||
delete [] microOps;
|
||||
}
|
||||
@@ -97,10 +101,29 @@ output header {{
|
||||
return microOps[microPC];
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
return mnemonic;
|
||||
}
|
||||
|
||||
%(MacroExecPanic)s
|
||||
};
|
||||
}};
|
||||
|
||||
// Basic instruction class declaration template.
|
||||
def template MacroDeclare {{
|
||||
/**
|
||||
* Static instruction class for "%(mnemonic)s".
|
||||
*/
|
||||
class %(class_name)s : public %(base_class)s
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
%(class_name)s(ExtMachInst machInst);
|
||||
};
|
||||
}};
|
||||
|
||||
// Basic instruction class constructor template.
|
||||
def template MacroConstructor {{
|
||||
inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
|
||||
@@ -113,23 +136,27 @@ def template MacroConstructor {{
|
||||
}
|
||||
}};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// X86 specific
|
||||
//
|
||||
|
||||
let {{
|
||||
def genMacroOp(name, Name, opSeq):
|
||||
baseClass = 'X86MacroInst'
|
||||
numMicroOps = len(opSeq.ops)
|
||||
numMicroOps = len(opSeq)
|
||||
allocMicroOps = ''
|
||||
micropc = 0
|
||||
for op in opSeq.ops:
|
||||
for op in opSeq:
|
||||
allocMicroOps += \
|
||||
"microOps[%d] = %s;\n" % \
|
||||
(micropc, op.getAllocator(True, op.delayed,
|
||||
(micropc, op.getAllocator('"' + name + '"', True, False, #op.delayed,
|
||||
micropc == 0,
|
||||
micropc == numMicroOps - 1))
|
||||
micropc += 1
|
||||
iop = InstObjParams(name, Name, baseClass,
|
||||
iop = InstObjParams(name, Name, 'MacroOp',
|
||||
{'code' : '', 'num_micro_ops' : numMicroOps,
|
||||
'alloc_micro_ops' : allocMicroOps})
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
header_output = MacroDeclare.subst(iop)
|
||||
decoder_output = MacroConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = ''
|
||||
|
||||
@@ -85,7 +85,7 @@ let {{
|
||||
text += ", false"
|
||||
return text
|
||||
|
||||
def getAllocator(self, *microFlags):
|
||||
def getAllocator(self, mnemonic, *microFlags):
|
||||
args = ''
|
||||
signature = "<"
|
||||
emptySig = True
|
||||
@@ -104,7 +104,7 @@ let {{
|
||||
else:
|
||||
raise Exception, "Unrecognized operand type."
|
||||
signature += ">"
|
||||
return 'new %s%s(machInst%s%s)' % (self.className, signature, self.microFlagsText(microFlags), args)
|
||||
return 'new %s%s(machInst, %s%s%s)' % (self.className, signature, mnemonic, self.microFlagsText(microFlags), args)
|
||||
}};
|
||||
|
||||
let{{
|
||||
@@ -123,7 +123,7 @@ let{{
|
||||
# the beginning of the line, so the previous component is stripped
|
||||
# before continuing.
|
||||
labelRe = re.compile(r'^[ \t]*(?P<label>\w\w*)[ \t]:')
|
||||
lineRe = re.compile(r'^(?P<line>[^\n][^\n]*)$')
|
||||
lineRe = re.compile(r'^(?P<line>..*)(\n|$)')
|
||||
classRe = re.compile(r'^[ \t]*(?P<className>[a-zA-Z_]\w*)')
|
||||
# This recognizes three different flavors of operands:
|
||||
# 1. Raw decimal numbers composed of digits between 0 and 9
|
||||
@@ -145,14 +145,14 @@ let{{
|
||||
# Get a line and seperate it from the rest of the code
|
||||
line = lineMatch.group("line")
|
||||
orig_line = line
|
||||
# print "Parsing line %s" % line
|
||||
#print "Parsing line %s" % line
|
||||
code = lineRe.sub('', code, 1)
|
||||
|
||||
# Find the label, if any
|
||||
labelMatch = labelRe.search(line)
|
||||
if labelMatch != None:
|
||||
statement.label = labelMatch.group("label")
|
||||
# print "Found label %s." % statement.label
|
||||
#print "Found label %s." % statement.label
|
||||
# Clear the label from the statement
|
||||
line = labelRe.sub('', line, 1)
|
||||
|
||||
@@ -163,7 +163,7 @@ let{{
|
||||
% orig_line
|
||||
else:
|
||||
statement.className = classMatch.group("className")
|
||||
# print "Found class name %s." % statement.className
|
||||
#print "Found class name %s." % statement.className
|
||||
|
||||
# Clear the class name from the statement
|
||||
line = classRe.sub('', line, 1)
|
||||
@@ -185,9 +185,9 @@ let{{
|
||||
print "Problem parsing operand in statement: %s" \
|
||||
% orig_line
|
||||
line = opRe.sub('', line, 1)
|
||||
# print "Found operand %s." % statement.args[-1]
|
||||
#print "Found operand %s." % statement.args[-1]
|
||||
opMatch = opRe.search(line)
|
||||
# print "Found operands", statement.args
|
||||
#print "Found operands", statement.args
|
||||
|
||||
# Add this statement to our collection
|
||||
statements.append(statement)
|
||||
@@ -215,11 +215,14 @@ let{{
|
||||
arg["operandImm"] = labels[arg["operandLabel"]] - micropc - 1
|
||||
micropc += 1
|
||||
|
||||
if len(statements) == 0:
|
||||
raise Exception, "Didn't find any microops in microcode: \n%s" % orig_code
|
||||
|
||||
# If we can implement this instruction with exactly one microop, just
|
||||
# use that directly.
|
||||
if len(statements) == 1:
|
||||
decode_block = "return %s;" % \
|
||||
statements[0].getAllocator()
|
||||
statements[0].getAllocator('"' + name + '"')
|
||||
return ('', '', decode_block, '')
|
||||
else:
|
||||
# Build a macroop to contain the sequence of microops we've
|
||||
|
||||
@@ -69,20 +69,33 @@ output header {{
|
||||
class X86MicroOpBase : public X86StaticInst
|
||||
{
|
||||
protected:
|
||||
const char * instMnem;
|
||||
uint8_t opSize;
|
||||
uint8_t addrSize;
|
||||
|
||||
X86MicroOpBase(bool isMicro, bool isDelayed,
|
||||
X86MicroOpBase(ExtMachInst _machInst,
|
||||
const char *mnem, const char *_instMnem,
|
||||
bool isMicro, bool isDelayed,
|
||||
bool isFirst, bool isLast,
|
||||
const char *mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass) :
|
||||
X86StaticInst(mnem, _machInst, __opClass)
|
||||
X86StaticInst(mnem, _machInst, __opClass),
|
||||
instMnem(_instMnem)
|
||||
{
|
||||
flags[IsMicroOp] = isMicro;
|
||||
flags[IsDelayedCommit] = isDelayed;
|
||||
flags[IsFirstMicroOp] = isFirst;
|
||||
flags[IsLastMicroOp] = isLast;
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ccprintf(ss, "\t%s.%s", instMnem, mnemonic);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
}};
|
||||
|
||||
@@ -127,7 +140,7 @@ let {{
|
||||
}};
|
||||
|
||||
// A tmeplate for building a specialized version of the microcode
|
||||
// instruction which knows specifies which arguments it wants
|
||||
// instruction which specifies which arguments it wants
|
||||
def template MicroOpDeclare {{
|
||||
template<>
|
||||
class %(class_name)s%(signature)s : public X86MicroOpBase
|
||||
@@ -137,11 +150,15 @@ def template MicroOpDeclare {{
|
||||
void buildMe();
|
||||
|
||||
public:
|
||||
%(class_name)s(bool isMicro, bool isDelayed,
|
||||
bool isFirst, bool isLast,
|
||||
ExtMachInst _machInst %(param_arg_dec)s);
|
||||
%(class_name)s(ExtMachInst _machInst,
|
||||
const char * instMnem,
|
||||
bool isMicro, bool isDelayed,
|
||||
bool isFirst, bool isLast
|
||||
%(param_arg_dec)s);
|
||||
|
||||
%(class_name)s(ExtMachInst _machInst %(param_arg_dec)s);
|
||||
%(class_name)s(ExtMachInst _machInst,
|
||||
const char * instMnem
|
||||
%(param_arg_dec)s);
|
||||
|
||||
%(BasicExecDeclare)s
|
||||
};
|
||||
@@ -155,19 +172,21 @@ def template MicroOpConstructor {{
|
||||
}
|
||||
|
||||
inline %(class_name)s%(signature)s::%(class_name)s(
|
||||
ExtMachInst machInst %(param_arg_dec)s) :
|
||||
%(base_class)s(false, false, false, false,
|
||||
"%(mnemonic)s", machInst, %(op_class)s)
|
||||
ExtMachInst machInst, const char * instMnem
|
||||
%(param_arg_dec)s) :
|
||||
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||
false, false, false, false, %(op_class)s)
|
||||
%(param_init)s
|
||||
{
|
||||
buildMe();
|
||||
}
|
||||
|
||||
inline %(class_name)s%(signature)s::%(class_name)s(
|
||||
bool isMicro, bool isDelayed, bool isFirst, bool isLast,
|
||||
ExtMachInst machInst %(param_arg_dec)s)
|
||||
: %(base_class)s(isMicro, isDelayed, isFirst, isLast,
|
||||
"%(mnemonic)s", machInst, %(op_class)s)
|
||||
ExtMachInst machInst, const char * instMnem,
|
||||
bool isMicro, bool isDelayed, bool isFirst, bool isLast
|
||||
%(param_arg_dec)s)
|
||||
: %(base_class)s(machInst, "%(mnemonic)s", instMnem,
|
||||
isMicro, isDelayed, isFirst, isLast, %(op_class)s)
|
||||
%(param_init)s
|
||||
{
|
||||
buildMe();
|
||||
|
||||
@@ -67,30 +67,18 @@ let {{
|
||||
# builder is called on the exploded contents of "vals" values to generate
|
||||
# whatever code should be used.
|
||||
def doSplitDecode(name, Name, builder, switchVal, vals, default = None):
|
||||
header_output = ''
|
||||
decoder_output = ''
|
||||
decode_block = 'switch(%s) {\n' % switchVal
|
||||
exec_output = ''
|
||||
blocks = OutputBlocks()
|
||||
blocks.decode_block += 'switch(%s) {\n' % switchVal
|
||||
for (val, todo) in vals.items():
|
||||
(new_header_output,
|
||||
new_decoder_output,
|
||||
new_decode_block,
|
||||
new_exec_output) = builder(name, Name, *todo)
|
||||
header_output += new_header_output
|
||||
decoder_output += new_decoder_output
|
||||
decode_block += '\tcase %s: %s\n' % (val, new_decode_block)
|
||||
exec_output += new_exec_output
|
||||
built = builder(name, Name, *todo)
|
||||
built.decode_block = '\tcase %s: %s\n' % (val, built.decode_block)
|
||||
blocks.append(built)
|
||||
if default:
|
||||
(new_header_output,
|
||||
new_decoder_output,
|
||||
new_decode_block,
|
||||
new_exec_output) = builder(name, Name, *default)
|
||||
header_output += new_header_output
|
||||
decoder_output += new_decoder_output
|
||||
decode_block += '\tdefault: %s\n' % new_decode_block
|
||||
exec_output += new_exec_output
|
||||
decode_block += '}\n'
|
||||
return (header_output, decoder_output, decode_block, exec_output)
|
||||
built = builder(name, Name, *default)
|
||||
built.decode_block = '\tdefault: %s\n' % built.decode_block
|
||||
blocks.append(built)
|
||||
blocks.decode_block += '}\n'
|
||||
return blocks
|
||||
}};
|
||||
|
||||
let {{
|
||||
@@ -143,6 +131,7 @@ let {{
|
||||
# This needs to refer to memory, but we'll fill in the details
|
||||
# later. It needs to take into account unaligned memory
|
||||
# addresses.
|
||||
code = "GenFault ${new UnimpInstFault}\n" + code
|
||||
memCode = opRe.sub("%0", code)
|
||||
memTypes = copy.copy(opTypes)
|
||||
memTypes.pop(-1)
|
||||
@@ -156,6 +145,7 @@ let {{
|
||||
# This needs to refer to memory, but we'll fill in the details
|
||||
# later. It needs to take into account unaligned memory
|
||||
# addresses.
|
||||
code = "GenFault ${new UnimpInstFault}\n" + code
|
||||
code = opRe.sub("%0", code)
|
||||
elif opType.tag in ("PR", "R", "VR"):
|
||||
# There should probably be a check here to verify that mod
|
||||
@@ -168,5 +158,7 @@ let {{
|
||||
# At this point, we've built up "code" to have all the necessary extra
|
||||
# instructions needed to implement whatever types of operands were
|
||||
# specified. Now we'll assemble it it into a StaticInst.
|
||||
return assembleMicro(name, Name, code)
|
||||
blocks = OutputBlocks()
|
||||
blocks.append(assembleMicro(name, Name, code))
|
||||
return blocks
|
||||
}};
|
||||
|
||||
Reference in New Issue
Block a user