summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-04-10 17:27:33 +0000
committerGabe Black <gblack@eecs.umich.edu>2007-04-10 17:27:33 +0000
commitfcc35a67e0cfa2e627ebba3fca0252bfb18f03c6 (patch)
treecd7bb69a26beca9bae831112a79b56cc3d4bbbfa
parentf71a6c8fed86c62d309908f37311456e8ec7a588 (diff)
parent74122c04cf8105d507f390c456c6e3c113b5a56e (diff)
downloadgem5-fcc35a67e0cfa2e627ebba3fca0252bfb18f03c6.tar.xz
Merge zizzer.eecs.umich.edu:/bk/newmem
into ahchoo.blinky.homelinux.org:/home/gblack/m5/newmem-x86 --HG-- extra : convert_revision : c5275ef3e53393496a2ebe05b2f516884bb392f9
-rw-r--r--src/arch/x86/faults.hh20
-rw-r--r--src/arch/x86/isa/base.isa32
-rw-r--r--src/arch/x86/isa/decoder/one_byte_opcodes.isa22
-rw-r--r--src/arch/x86/isa/formats/multi.isa4
-rw-r--r--src/arch/x86/isa/macroop.isa51
-rw-r--r--src/arch/x86/isa/microasm.isa21
-rw-r--r--src/arch/x86/isa/microops/base.isa49
-rw-r--r--src/arch/x86/isa/microops/microops.isa3
-rw-r--r--src/arch/x86/isa/specialize.isa38
-rw-r--r--src/cpu/simple/atomic.cc2
10 files changed, 169 insertions, 73 deletions
diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh
index 6d89c273a..8c9afcdb5 100644
--- a/src/arch/x86/faults.hh
+++ b/src/arch/x86/faults.hh
@@ -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");
diff --git a/src/arch/x86/isa/base.isa b/src/arch/x86/isa/base.isa
index cd166b306..eba24f709 100644
--- a/src/arch/x86/isa/base.isa
+++ b/src/arch/x86/isa/base.isa
@@ -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 {{
/**
diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
index fed6dda28..4e044363b 100644
--- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa
+++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
@@ -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
diff --git a/src/arch/x86/isa/formats/multi.isa b/src/arch/x86/isa/formats/multi.isa
index 7ad5ecd48..8f91c249c 100644
--- a/src/arch/x86/isa/formats/multi.isa
+++ b/src/arch/x86/isa/formats/multi.isa
@@ -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()
}};
diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa
index 7d41a2dea..663ec7aee 100644
--- a/src/arch/x86/isa/macroop.isa
+++ b/src/arch/x86/isa/macroop.isa
@@ -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 = ''
diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa
index 23567aae9..9d21b6bcc 100644
--- a/src/arch/x86/isa/microasm.isa
+++ b/src/arch/x86/isa/microasm.isa
@@ -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
diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa
index 4254994f3..f0aab7872 100644
--- a/src/arch/x86/isa/microops/base.isa
+++ b/src/arch/x86/isa/microops/base.isa
@@ -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();
diff --git a/src/arch/x86/isa/microops/microops.isa b/src/arch/x86/isa/microops/microops.isa
index bb136fc81..d877152eb 100644
--- a/src/arch/x86/isa/microops/microops.isa
+++ b/src/arch/x86/isa/microops/microops.isa
@@ -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"
diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa
index 9cac09770..ff92c3551 100644
--- a/src/arch/x86/isa/specialize.isa
+++ b/src/arch/x86/isa/specialize.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
}};
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index 6f69b5ac4..b0a01c3a3 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -557,7 +557,7 @@ AtomicSimpleCPU::tick()
}
}
- if(predecoder.needMoreBytes())
+ if(predecoder.needMoreBytes() || fault != NoFault)
advancePC(fault);
}