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:
Gabe Black
2007-04-10 17:27:33 +00:00
10 changed files with 169 additions and 73 deletions

View File

@@ -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");

View File

@@ -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 {{
/**

View File

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

View File

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

View File

@@ -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 = ''

View File

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

View File

@@ -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();

View File

@@ -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"

View File

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

View File

@@ -557,7 +557,7 @@ AtomicSimpleCPU::tick()
}
}
if(predecoder.needMoreBytes())
if(predecoder.needMoreBytes() || fault != NoFault)
advancePC(fault);
}