Merge zizzer.eecs.umich.edu:/bk/newmem
into ahchoo.blinky.homelinux.org:/home/gblack/m5/newmem-x86 --HG-- extra : convert_revision : c5275ef3e53393496a2ebe05b2f516884bb392f9
This commit is contained in:
@@ -65,12 +65,32 @@ namespace X86ISA
|
||||
{
|
||||
class X86Fault : public FaultBase
|
||||
{
|
||||
protected:
|
||||
const char * name()
|
||||
{
|
||||
return "generic_x86_fault";
|
||||
}
|
||||
|
||||
void invoke(ThreadContext * tc)
|
||||
{
|
||||
panic("X86 faults are not implemented!");
|
||||
}
|
||||
};
|
||||
|
||||
class UnimpInstFault : public FaultBase
|
||||
{
|
||||
public:
|
||||
const char * name()
|
||||
{
|
||||
return "unimplemented_micro";
|
||||
}
|
||||
|
||||
void invoke(ThreadContext * tc)
|
||||
{
|
||||
panic("Unimplemented instruction!");
|
||||
}
|
||||
};
|
||||
|
||||
static inline Fault genPageTableFault(Addr va)
|
||||
{
|
||||
panic("Page table fault not implemented in x86!\n");
|
||||
|
||||
@@ -58,6 +58,38 @@
|
||||
// Base class for sparc instructions, and some support functions
|
||||
//
|
||||
|
||||
let {{
|
||||
# This class will help make dealing with output a little less verbose
|
||||
class OutputBlocks(object):
|
||||
def __init__(self, header_output="",
|
||||
decoder_output="",
|
||||
decode_block="",
|
||||
exec_output=""):
|
||||
self.header_output = header_output
|
||||
self.decoder_output = decoder_output
|
||||
self.decode_block = decode_block
|
||||
self.exec_output = exec_output
|
||||
|
||||
def append(self, blocks):
|
||||
if isinstance(blocks, list) or isinstance(blocks, tuple):
|
||||
assert(len(blocks) == 4)
|
||||
self.header_output += blocks[0]
|
||||
self.decoder_output += blocks[1]
|
||||
self.decode_block += blocks[2]
|
||||
self.exec_output += blocks[3]
|
||||
else:
|
||||
self.header_output += blocks.header_output
|
||||
self.decoder_output += blocks.decoder_output
|
||||
self.decode_block += blocks.decode_block
|
||||
self.exec_output += blocks.exec_output
|
||||
|
||||
def makeList(self):
|
||||
return (self.header_output,
|
||||
self.decoder_output,
|
||||
self.decode_block,
|
||||
self.exec_output)
|
||||
}};
|
||||
|
||||
output header {{
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,11 +61,11 @@
|
||||
0x1: decode OPCODE_OP_TOP5 {
|
||||
format WarnUnimpl {
|
||||
0x00: decode OPCODE_OP_BOTTOM3 {
|
||||
0x4: Inst::add(rAl,Ib);
|
||||
0x5: Inst::add(rAx,Iz);
|
||||
0x4: Inst::ADD(rAl,Ib);
|
||||
0x5: Inst::ADD(rAx,Iz);
|
||||
0x6: push_ES();
|
||||
0x7: pop_ES();
|
||||
default: MultiInst::add(OPCODE_OP_BOTTOM3,
|
||||
default: MultiInst::ADD(OPCODE_OP_BOTTOM3,
|
||||
[Eb,Gb],[Ev,Gv],[Gb,Eb],[Gv,Ev]);
|
||||
}
|
||||
0x01: decode OPCODE_OP_BOTTOM3 {
|
||||
@@ -123,12 +123,12 @@
|
||||
0x7: das();
|
||||
}
|
||||
0x06: decode OPCODE_OP_BOTTOM3 {
|
||||
0x4: Inst::xor(rAl,Ib);
|
||||
0x5: Inst::xor(rAx,Iz);
|
||||
0x4: Inst::XOR(rAl,Ib);
|
||||
0x5: Inst::XOR(rAx,Iz);
|
||||
0x6: M5InternalError::error(
|
||||
{{"Tried to execute the SS segment override prefix!"}});
|
||||
0x7: aaa();
|
||||
default: MultiInst::xor(OPCODE_OP_BOTTOM3,
|
||||
default: MultiInst::XOR(OPCODE_OP_BOTTOM3,
|
||||
[Eb,Gb],[Ev,Gv],[Gb,Eb],[Gv,Ev]);
|
||||
}
|
||||
0x07: decode OPCODE_OP_BOTTOM3 {
|
||||
@@ -237,11 +237,11 @@
|
||||
0x7: xchg_Ev_Gv();
|
||||
}
|
||||
0x11: decode OPCODE_OP_BOTTOM3 {
|
||||
0x0: mov_Eb_Gb();
|
||||
0x1: mov_Ev_Gv();
|
||||
0x2: mov_Gb_Eb();
|
||||
0x3: mov_Gv_Ev();
|
||||
0x4: mov_MwRv_Sw();
|
||||
0x0: Inst::MOV(); //mov_Eb_Gb();
|
||||
0x1: Inst::MOV(); //mov_Ev_Gv();
|
||||
0x2: Inst::MOV(); //mov_Gb_Eb();
|
||||
0x3: Inst::MOV(); //mov_Gv_Ev();
|
||||
0x4: Inst::MOV(); //mov_MwRv_Sw();
|
||||
0x5: lea_Gv_M();
|
||||
0x6: mov_Sw_MwRv();
|
||||
0x7: group10_Ev(); //Make sure this is Ev
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -56,5 +56,8 @@
|
||||
//Common microop stuff
|
||||
##include "base.isa"
|
||||
|
||||
//A microop that generates a specified fault
|
||||
##include "fault.isa"
|
||||
|
||||
//Integer microop definitions
|
||||
##include "int.isa"
|
||||
|
||||
@@ -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
|
||||
}};
|
||||
|
||||
@@ -557,7 +557,7 @@ AtomicSimpleCPU::tick()
|
||||
}
|
||||
|
||||
}
|
||||
if(predecoder.needMoreBytes())
|
||||
if(predecoder.needMoreBytes() || fault != NoFault)
|
||||
advancePC(fault);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user