summaryrefslogtreecommitdiff
path: root/src/arch/x86/isa/microops
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/isa/microops')
-rw-r--r--src/arch/x86/isa/microops/base.isa31
-rw-r--r--src/arch/x86/isa/microops/debug.isa229
-rw-r--r--src/arch/x86/isa/microops/fpop.isa2
-rw-r--r--src/arch/x86/isa/microops/ldstop.isa145
-rw-r--r--src/arch/x86/isa/microops/limmop.isa2
-rw-r--r--src/arch/x86/isa/microops/microops.isa8
-rw-r--r--src/arch/x86/isa/microops/regop.isa323
-rw-r--r--src/arch/x86/isa/microops/seqop.isa251
-rw-r--r--src/arch/x86/isa/microops/specop.isa19
9 files changed, 891 insertions, 119 deletions
diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa
index 75658a26c..f1007bf71 100644
--- a/src/arch/x86/isa/microops/base.isa
+++ b/src/arch/x86/isa/microops/base.isa
@@ -69,6 +69,29 @@ let {{
let {{
class X86Microop(object):
+
+ generatorNameTemplate = "generate_%s_%d"
+
+ generatorTemplate = '''
+ StaticInstPtr
+ ''' + generatorNameTemplate + '''(StaticInstPtr curMacroop)
+ {
+ static const char *macrocodeBlock = romMnemonic;
+ static const ExtMachInst dummyExtMachInst;
+ static const EmulEnv dummyEmulEnv(0, 0, 1, 1, 1);
+
+ Macroop * macroop = dynamic_cast<Macroop *>(curMacroop.get());
+ const ExtMachInst &machInst =
+ macroop ? macroop->getExtMachInst() : dummyExtMachInst;
+ const EmulEnv &env =
+ macroop ? macroop->getEmulEnv() : dummyEmulEnv;
+ // env may not be used in the microop's constructor.
+ RegIndex reg = env.reg;
+ reg = reg;
+ using namespace RomLabels;
+ return %s;
+ }
+ '''
def __init__(self, name):
self.name = name
@@ -91,4 +114,12 @@ let {{
def getAllocator(self, mnemonic, *microFlags):
return 'new %s(machInst, %s)' % \
(self.className, mnemonic, self.microFlagsText(microFlags))
+
+ def getGeneratorDef(self, micropc):
+ return self.generatorTemplate % \
+ (self.className, micropc, \
+ self.getAllocator(True, True, False, False))
+
+ def getGenerator(self, micropc):
+ return self.generatorNameTemplate % (self.className, micropc)
}};
diff --git a/src/arch/x86/isa/microops/debug.isa b/src/arch/x86/isa/microops/debug.isa
new file mode 100644
index 000000000..38fee59bb
--- /dev/null
+++ b/src/arch/x86/isa/microops/debug.isa
@@ -0,0 +1,229 @@
+// Copyright (c) 2008 The Hewlett-Packard Development Company
+// All rights reserved.
+//
+// Redistribution and use of this software in source and binary forms,
+// with or without modification, are permitted provided that the
+// following conditions are met:
+//
+// The software must be used only for Non-Commercial Use which means any
+// use which is NOT directed to receiving any direct monetary
+// compensation for, or commercial advantage from such use. Illustrative
+// examples of non-commercial use are academic research, personal study,
+// teaching, education and corporate research & development.
+// Illustrative examples of commercial use are distributing products for
+// commercial advantage and providing services using the software for
+// commercial advantage.
+//
+// If you wish to use this software or functionality therein that may be
+// covered by patents for commercial use, please contact:
+// Director of Intellectual Property Licensing
+// Office of Strategy and Technology
+// Hewlett-Packard Company
+// 1501 Page Mill Road
+// Palo Alto, California 94304
+//
+// Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer. Redistributions
+// in binary form must reproduce the above copyright notice, this list of
+// conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution. Neither the name of
+// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission. No right of
+// sublicense is granted herewith. Derivatives of the software and
+// output created using the software may be prepared, but only for
+// Non-Commercial Uses. Derivatives of the software may be shared with
+// others provided: (i) the others agree to abide by the list of
+// conditions herein which includes the Non-Commercial Use restrictions;
+// and (ii) such Derivatives of the software include the above copyright
+// notice to acknowledge the contribution from this software where
+// applicable, this list of conditions and the disclaimer below.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: Gabe Black
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Debug Microops
+//
+//////////////////////////////////////////////////////////////////////////
+
+output header {{
+ class MicroDebugBase : public X86ISA::X86MicroopBase
+ {
+ protected:
+ std::string message;
+ uint8_t cc;
+
+ public:
+ MicroDebugBase(ExtMachInst _machInst, const char * mnem,
+ const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ std::string _message, uint8_t _cc);
+
+ MicroDebugBase(ExtMachInst _machInst, const char * mnem,
+ const char * instMnem, std::string _message, uint8_t _cc);
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+}};
+
+def template MicroDebugDeclare {{
+ class %(class_name)s : public %(base_class)s
+ {
+ private:
+ void buildMe();
+ public:
+ %(class_name)s(ExtMachInst _machInst, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ std::string _message, uint8_t _cc);
+
+ %(class_name)s(ExtMachInst _machInst, const char * instMnem,
+ std::string _message, uint8_t _cc);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+def template MicroDebugExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ %(op_decl)s
+ %(op_rd)s
+ if (%(cond_test)s) {
+ %(func)s("%s\n", message);
+ }
+ return NoFault;
+ }
+}};
+
+output decoder {{
+ inline MicroDebugBase::MicroDebugBase(
+ ExtMachInst machInst, const char * mnem, const char * instMnem,
+ std::string _message, uint8_t _cc) :
+ X86MicroopBase(machInst, mnem, instMnem,
+ false, false, false, false, No_OpClass),
+ message(_message), cc(_cc)
+ {
+ }
+
+ inline MicroDebugBase::MicroDebugBase(
+ ExtMachInst machInst, const char * mnem, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ std::string _message, uint8_t _cc) :
+ X86MicroopBase(machInst, mnem, instMnem,
+ isMicro, isDelayed, isFirst, isLast, No_OpClass),
+ message(_message), cc(_cc)
+ {
+ }
+}};
+
+def template MicroDebugConstructor {{
+
+ inline void %(class_name)s::buildMe()
+ {
+ %(constructor)s;
+ }
+
+ inline %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem,
+ std::string _message, uint8_t _cc) :
+ %(base_class)s(machInst, "%(func)s", instMnem, _message, _cc)
+ {
+ buildMe();
+ }
+
+ inline %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ std::string _message, uint8_t _cc) :
+ %(base_class)s(machInst, "%(func)s", instMnem,
+ isMicro, isDelayed, isFirst, isLast, _message, _cc)
+ {
+ buildMe();
+ }
+}};
+
+output decoder {{
+ std::string MicroDebugBase::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+
+ printMnemonic(response, instMnem, mnemonic);
+ response << "\"" << message << "\"";
+
+ return response.str();
+ }
+}};
+
+let {{
+ class MicroDebug(X86Microop):
+ def __init__(self, message, flags=None):
+ self.message = message
+ if flags:
+ if not isinstance(flags, (list, tuple)):
+ raise Exception, "flags must be a list or tuple of flags"
+ self.cond = " | ".join(flags)
+ self.className += "Flags"
+ else:
+ self.cond = "0"
+
+ def getAllocator(self, *microFlags):
+ allocator = '''new %(class_name)s(machInst, macrocodeBlock
+ %(flags)s, "%(message)s", %(cc)s)''' % {
+ "class_name" : self.className,
+ "flags" : self.microFlagsText(microFlags),
+ "message" : self.message,
+ "cc" : self.cond}
+ return allocator
+
+ exec_output = ""
+ header_output = ""
+ decoder_output = ""
+
+ def buildDebugMicro(func):
+ global exec_output, header_output, decoder_output
+
+ iop = InstObjParams(func, "Micro%sFlags" % func.capitalize(),
+ "MicroDebugBase",
+ {"code": "",
+ "func": func,
+ "cond_test": "checkCondition(ccFlagBits, cc)"})
+ exec_output += MicroDebugExecute.subst(iop)
+ header_output += MicroDebugDeclare.subst(iop)
+ decoder_output += MicroDebugConstructor.subst(iop)
+
+ iop = InstObjParams(func, "Micro%s" % func.capitalize(),
+ "MicroDebugBase",
+ {"code": "",
+ "func": func,
+ "cond_test": "true"})
+ exec_output += MicroDebugExecute.subst(iop)
+ header_output += MicroDebugDeclare.subst(iop)
+ decoder_output += MicroDebugConstructor.subst(iop)
+
+ class MicroDebugChild(MicroDebug):
+ className = "Micro%s" % func.capitalize()
+
+ global microopClasses
+ microopClasses[func] = MicroDebugChild
+
+ buildDebugMicro("panic")
+ buildDebugMicro("fatal")
+ buildDebugMicro("warn")
+ buildDebugMicro("warn_once")
+}};
diff --git a/src/arch/x86/isa/microops/fpop.isa b/src/arch/x86/isa/microops/fpop.isa
index 2919aa277..d4acfdbf4 100644
--- a/src/arch/x86/isa/microops/fpop.isa
+++ b/src/arch/x86/isa/microops/fpop.isa
@@ -245,7 +245,7 @@ let {{
self.className += "Top"
def getAllocator(self, *microFlags):
- return '''new %(class_name)s(machInst, mnemonic
+ return '''new %(class_name)s(machInst, macrocodeBlock
%(flags)s, %(src1)s, %(src2)s, %(dest)s,
%(dataSize)s, %(spm)d)''' % {
"class_name" : self.className,
diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa
index cb63e7cd9..af94cf31e 100644
--- a/src/arch/x86/isa/microops/ldstop.isa
+++ b/src/arch/x86/isa/microops/ldstop.isa
@@ -124,14 +124,16 @@ def template MicroLeaDeclare {{
uint8_t _scale, RegIndex _index, RegIndex _base,
uint64_t _disp, uint8_t _segment,
RegIndex _data,
- uint8_t _dataSize, uint8_t _addressSize);
+ uint8_t _dataSize, uint8_t _addressSize,
+ Request::FlagsType _memFlags);
%(class_name)s(ExtMachInst _machInst,
const char * instMnem,
uint8_t _scale, RegIndex _index, RegIndex _base,
uint64_t _disp, uint8_t _segment,
RegIndex _data,
- uint8_t _dataSize, uint8_t _addressSize);
+ uint8_t _dataSize, uint8_t _addressSize,
+ Request::FlagsType _memFlags);
%(BasicExecDeclare)s
};
@@ -151,11 +153,13 @@ def template MicroLoadExecute {{
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
- fault = read(xc, EA, Mem, (%(mem_flags)s) | segment);
+ fault = read(xc, EA, Mem, memFlags);
- if(fault == NoFault)
- {
+ if (fault == NoFault) {
%(code)s;
+ } else if (memFlags & Request::PF_EXCLUSIVE) {
+ // For prefetches, ignore any faults/exceptions.
+ return NoFault;
}
if(fault == NoFault)
{
@@ -178,7 +182,7 @@ def template MicroLoadInitiateAcc {{
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
- fault = read(xc, EA, Mem, (%(mem_flags)s) | segment);
+ fault = read(xc, EA, Mem, memFlags);
return fault;
}
@@ -194,7 +198,7 @@ def template MicroLoadCompleteAcc {{
%(op_decl)s;
%(op_rd)s;
- Mem = pkt->get<typeof(Mem)>();
+ Mem = get(pkt);
%(code)s;
@@ -225,9 +229,10 @@ def template MicroStoreExecute {{
if(fault == NoFault)
{
- fault = write(xc, Mem, EA, (%(mem_flags)s) | segment);
+ fault = write(xc, Mem, EA, memFlags);
if(fault == NoFault)
{
+ %(post_code)s;
%(op_wb)s;
}
}
@@ -252,20 +257,20 @@ def template MicroStoreInitiateAcc {{
if(fault == NoFault)
{
- fault = write(xc, Mem, EA, (%(mem_flags)s) | segment);
- if(fault == NoFault)
- {
- %(op_wb)s;
- }
+ write(xc, Mem, EA, memFlags);
}
return fault;
}
}};
def template MicroStoreCompleteAcc {{
- Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
- Trace::InstRecord * traceData) const
+ Fault %(class_name)s::completeAcc(PacketPtr pkt,
+ %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const
{
+ %(op_decl)s;
+ %(op_rd)s;
+ %(complete_code)s;
+ %(op_wb)s;
return NoFault;
}
}};
@@ -295,14 +300,16 @@ def template MicroLdStOpDeclare {{
uint8_t _scale, RegIndex _index, RegIndex _base,
uint64_t _disp, uint8_t _segment,
RegIndex _data,
- uint8_t _dataSize, uint8_t _addressSize);
+ uint8_t _dataSize, uint8_t _addressSize,
+ Request::FlagsType _memFlags);
%(class_name)s(ExtMachInst _machInst,
const char * instMnem,
uint8_t _scale, RegIndex _index, RegIndex _base,
uint64_t _disp, uint8_t _segment,
RegIndex _data,
- uint8_t _dataSize, uint8_t _addressSize);
+ uint8_t _dataSize, uint8_t _addressSize,
+ Request::FlagsType _memFlags);
%(BasicExecDeclare)s
@@ -324,12 +331,13 @@ def template MicroLdStOpConstructor {{
uint8_t _scale, RegIndex _index, RegIndex _base,
uint64_t _disp, uint8_t _segment,
RegIndex _data,
- uint8_t _dataSize, uint8_t _addressSize) :
+ uint8_t _dataSize, uint8_t _addressSize,
+ Request::FlagsType _memFlags) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
false, false, false, false,
_scale, _index, _base,
_disp, _segment, _data,
- _dataSize, _addressSize, %(op_class)s)
+ _dataSize, _addressSize, _memFlags, %(op_class)s)
{
buildMe();
}
@@ -340,12 +348,13 @@ def template MicroLdStOpConstructor {{
uint8_t _scale, RegIndex _index, RegIndex _base,
uint64_t _disp, uint8_t _segment,
RegIndex _data,
- uint8_t _dataSize, uint8_t _addressSize) :
+ uint8_t _dataSize, uint8_t _addressSize,
+ Request::FlagsType _memFlags) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
isMicro, isDelayed, isFirst, isLast,
_scale, _index, _base,
_disp, _segment, _data,
- _dataSize, _addressSize, %(op_class)s)
+ _dataSize, _addressSize, _memFlags, %(op_class)s)
{
buildMe();
}
@@ -353,26 +362,35 @@ def template MicroLdStOpConstructor {{
let {{
class LdStOp(X86Microop):
- def __init__(self, data, segment, addr, disp, dataSize, addressSize):
+ def __init__(self, data, segment, addr, disp,
+ dataSize, addressSize, baseFlags, atCPL0, prefetch):
self.data = data
[self.scale, self.index, self.base] = addr
self.disp = disp
self.segment = segment
self.dataSize = dataSize
self.addressSize = addressSize
+ self.memFlags = baseFlags
+ if atCPL0:
+ self.memFlags += " | (CPL0FlagBit << FlagShift)"
+ if prefetch:
+ self.memFlags += " | Request::PF_EXCLUSIVE"
+ self.memFlags += " | (machInst.legacy.addr ? " + \
+ "(AddrSizeFlagBit << FlagShift) : 0)"
def getAllocator(self, *microFlags):
- allocator = '''new %(class_name)s(machInst, mnemonic
+ allocator = '''new %(class_name)s(machInst, macrocodeBlock
%(flags)s, %(scale)s, %(index)s, %(base)s,
%(disp)s, %(segment)s, %(data)s,
- %(dataSize)s, %(addressSize)s)''' % {
+ %(dataSize)s, %(addressSize)s, %(memFlags)s)''' % {
"class_name" : self.className,
"flags" : self.microFlagsText(microFlags),
"scale" : self.scale, "index" : self.index,
"base" : self.base,
"disp" : self.disp,
"segment" : self.segment, "data" : self.data,
- "dataSize" : self.dataSize, "addressSize" : self.addressSize}
+ "dataSize" : self.dataSize, "addressSize" : self.addressSize,
+ "memFlags" : self.memFlags}
return allocator
}};
@@ -384,9 +402,11 @@ let {{
decoder_output = ""
exec_output = ""
- calculateEA = "EA = SegBase + scale * Index + Base + disp;"
+ calculateEA = '''
+ EA = bits(SegBase + scale * Index + Base + disp, addressSize * 8 - 1, 0);
+ '''
- def defineMicroLoadOp(mnemonic, code, mem_flags=0):
+ def defineMicroLoadOp(mnemonic, code, mem_flags="0"):
global header_output
global decoder_output
global exec_output
@@ -397,8 +417,7 @@ let {{
# Build up the all register version of this micro op
iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
{"code": code,
- "ea_code": calculateEA,
- "mem_flags": mem_flags})
+ "ea_code": calculateEA})
header_output += MicroLdStOpDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroLoadExecute.subst(iop)
@@ -407,19 +426,24 @@ let {{
class LoadOp(LdStOp):
def __init__(self, data, segment, addr, disp = 0,
- dataSize="env.dataSize", addressSize="env.addressSize"):
- super(LoadOp, self).__init__(data, segment,
- addr, disp, dataSize, addressSize)
+ dataSize="env.dataSize",
+ addressSize="env.addressSize",
+ atCPL0=False, prefetch=False):
+ super(LoadOp, self).__init__(data, segment, addr,
+ disp, dataSize, addressSize, mem_flags,
+ atCPL0, prefetch)
self.className = Name
self.mnemonic = name
microopClasses[name] = LoadOp
defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);')
- defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);', 'StoreCheck')
+ defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);',
+ 'X86ISA::StoreCheck')
defineMicroLoadOp('Ldfp', 'FpData.uqw = Mem;')
- def defineMicroStoreOp(mnemonic, code, mem_flags=0):
+ def defineMicroStoreOp(mnemonic, code, \
+ postCode="", completeCode="", mem_flags="0"):
global header_output
global decoder_output
global exec_output
@@ -430,8 +454,9 @@ let {{
# Build up the all register version of this micro op
iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
{"code": code,
- "ea_code": calculateEA,
- "mem_flags": mem_flags})
+ "post_code": postCode,
+ "complete_code": completeCode,
+ "ea_code": calculateEA})
header_output += MicroLdStOpDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroStoreExecute.subst(iop)
@@ -440,26 +465,26 @@ let {{
class StoreOp(LdStOp):
def __init__(self, data, segment, addr, disp = 0,
- dataSize="env.dataSize", addressSize="env.addressSize"):
- super(StoreOp, self).__init__(data, segment,
- addr, disp, dataSize, addressSize)
+ dataSize="env.dataSize",
+ addressSize="env.addressSize",
+ atCPL0=False):
+ super(StoreOp, self).__init__(data, segment, addr,
+ disp, dataSize, addressSize, mem_flags, atCPL0, False)
self.className = Name
self.mnemonic = name
microopClasses[name] = StoreOp
- defineMicroStoreOp('St', 'Mem = Data;')
+ defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);')
defineMicroStoreOp('Stfp', 'Mem = FpData.uqw;')
- defineMicroStoreOp('Stupd', '''
- Mem = Data;
- Base = merge(Base, EA - SegBase, addressSize);
- ''');
-
+ defineMicroStoreOp('Stupd', 'Mem = pick(Data, 2, dataSize);',
+ 'Base = merge(Base, EA - SegBase, addressSize);',
+ 'Base = merge(Base, pkt->req->getVaddr() - SegBase, addressSize);');
+ defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS")
iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
{"code": "Data = merge(Data, EA, dataSize);",
- "ea_code": calculateEA,
- "mem_flags": 0})
+ "ea_code": calculateEA})
header_output += MicroLeaDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroLeaExecute.subst(iop)
@@ -468,7 +493,7 @@ let {{
def __init__(self, data, segment, addr, disp = 0,
dataSize="env.dataSize", addressSize="env.addressSize"):
super(LeaOp, self).__init__(data, segment,
- addr, disp, dataSize, addressSize)
+ addr, disp, dataSize, addressSize, "0", False, False)
self.className = "Lea"
self.mnemonic = "lea"
@@ -477,38 +502,28 @@ let {{
iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp',
{"code": "xc->demapPage(EA, 0);",
- "ea_code": calculateEA,
- "mem_flags": 0})
+ "ea_code": calculateEA})
header_output += MicroLeaDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroLeaExecute.subst(iop)
class TiaOp(LdStOp):
def __init__(self, segment, addr, disp = 0,
- dataSize="env.dataSize", addressSize="env.addressSize"):
+ dataSize="env.dataSize",
+ addressSize="env.addressSize"):
super(TiaOp, self).__init__("NUM_INTREGS", segment,
- addr, disp, dataSize, addressSize)
+ addr, disp, dataSize, addressSize, "0", False, False)
self.className = "Tia"
self.mnemonic = "tia"
microopClasses["tia"] = TiaOp
- iop = InstObjParams("cda", "Cda", 'X86ISA::LdStOp',
- {"code": '''
- Addr paddr;
- fault = xc->translateDataWriteAddr(EA, paddr,
- dataSize, (1 << segment));
- ''',
- "ea_code": calculateEA})
- header_output += MicroLeaDeclare.subst(iop)
- decoder_output += MicroLdStOpConstructor.subst(iop)
- exec_output += MicroLeaExecute.subst(iop)
-
class CdaOp(LdStOp):
def __init__(self, segment, addr, disp = 0,
- dataSize="env.dataSize", addressSize="env.addressSize"):
+ dataSize="env.dataSize",
+ addressSize="env.addressSize", atCPL0=False):
super(CdaOp, self).__init__("NUM_INTREGS", segment,
- addr, disp, dataSize, addressSize)
+ addr, disp, dataSize, addressSize, "0", atCPL0, False)
self.className = "Cda"
self.mnemonic = "cda"
diff --git a/src/arch/x86/isa/microops/limmop.isa b/src/arch/x86/isa/microops/limmop.isa
index 6686444fd..4e75ab8b0 100644
--- a/src/arch/x86/isa/microops/limmop.isa
+++ b/src/arch/x86/isa/microops/limmop.isa
@@ -154,7 +154,7 @@ let {{
self.dataSize = dataSize
def getAllocator(self, *microFlags):
- allocator = '''new %(class_name)s(machInst, mnemonic
+ allocator = '''new %(class_name)s(machInst, macrocodeBlock
%(flags)s, %(dest)s, %(imm)s, %(dataSize)s)''' % {
"class_name" : self.className,
"mnemonic" : self.mnemonic,
diff --git a/src/arch/x86/isa/microops/microops.isa b/src/arch/x86/isa/microops/microops.isa
index 53f34d3f2..19266f6d6 100644
--- a/src/arch/x86/isa/microops/microops.isa
+++ b/src/arch/x86/isa/microops/microops.isa
@@ -1,4 +1,4 @@
-// Copyright (c) 2007 The Hewlett-Packard Development Company
+// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
// All rights reserved.
//
// Redistribution and use of this software in source and binary forms,
@@ -68,5 +68,11 @@
//Load/store microop definitions
##include "ldstop.isa"
+//Control flow microop definitions
+##include "seqop.isa"
+
//Miscellaneous microop definitions
##include "specop.isa"
+
+//Microops for printing out debug messages through M5
+##include "debug.isa"
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa
index e761f0034..f9bc82119 100644
--- a/src/arch/x86/isa/microops/regop.isa
+++ b/src/arch/x86/isa/microops/regop.isa
@@ -1,4 +1,4 @@
-// Copyright (c) 2007 The Hewlett-Packard Development Company
+// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
// All rights reserved.
//
// Redistribution and use of this software in source and binary forms,
@@ -231,6 +231,21 @@ output header {{
void
divide(uint64_t dividend, uint64_t divisor,
uint64_t &quotient, uint64_t &remainder);
+
+ enum SegmentSelectorCheck {
+ SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck,
+ SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck,
+ SegTRCheck, SegTSSCheck, SegInGDTCheck, SegLDTCheck
+ };
+
+ enum LongModeDescriptorType {
+ LDT64 = 2,
+ AvailableTSS64 = 9,
+ BusyTSS64 = 0xb,
+ CallGate64 = 0xc,
+ IntGate64 = 0xe,
+ TrapGate64 = 0xf
+ };
}};
output decoder {{
@@ -424,7 +439,7 @@ let {{
className = self.className
if self.mnemonic == self.base_mnemonic + 'i':
className += "Imm"
- allocator = '''new %(class_name)s(machInst, mnemonic
+ allocator = '''new %(class_name)s(machInst, macrocodeBlock
%(flags)s, %(src1)s, %(op2)s, %(dest)s,
%(dataSize)s, %(ext)s)''' % {
"class_name" : className,
@@ -838,19 +853,28 @@ let {{
code = 'RIP = psrc1 + sop2 + CSBase'
else_code="RIP = RIP;"
- class Br(WrRegOp, CondRegOp):
- code = 'nuIP = psrc1 + op2;'
- else_code='nuIP = nuIP;'
-
class Wruflags(WrRegOp):
code = 'ccFlagBits = psrc1 ^ op2'
+ class Wrflags(WrRegOp):
+ code = '''
+ MiscReg newFlags = psrc1 ^ op2;
+ MiscReg userFlagMask = 0xDD5;
+ // Get only the user flags
+ ccFlagBits = newFlags & userFlagMask;
+ // Get everything else
+ nccFlagBits = newFlags & ~userFlagMask;
+ '''
+
class Rdip(RdRegOp):
code = 'DestReg = RIP - CSBase'
class Ruflags(RdRegOp):
code = 'DestReg = ccFlagBits'
+ class Rflags(RdRegOp):
+ code = 'DestReg = ccFlagBits | nccFlagBits'
+
class Ruflag(RegOp):
code = '''
int flag = bits(ccFlagBits, imm8);
@@ -863,6 +887,20 @@ let {{
super(Ruflag, self).__init__(dest, \
"NUM_INTREGS", imm, flags, dataSize)
+ class Rflag(RegOp):
+ code = '''
+ MiscReg flagMask = 0x3F7FDD5;
+ MiscReg flags = (nccFlagBits | ccFlagBits) & flagMask;
+ int flag = bits(flags, imm8);
+ DestReg = merge(DestReg, flag, dataSize);
+ ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
+ (ccFlagBits & ~EZFBit);
+ '''
+ def __init__(self, dest, imm, flags=None, \
+ dataSize="env.dataSize"):
+ super(Rflag, self).__init__(dest, \
+ "NUM_INTREGS", imm, flags, dataSize)
+
class Sext(RegOp):
code = '''
IntReg val = psrc1;
@@ -883,17 +921,53 @@ let {{
'''
class Zext(RegOp):
- code = 'DestReg = bits(psrc1, op2, 0);'
+ code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);'
+
+ class Rddr(RegOp):
+ def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
+ super(Rddr, self).__init__(dest, \
+ src1, "NUM_INTREGS", flags, dataSize)
+ code = '''
+ CR4 cr4 = CR4Op;
+ DR7 dr7 = DR7Op;
+ if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) {
+ fault = new InvalidOpcode();
+ } else if (dr7.gd) {
+ fault = new DebugException();
+ } else {
+ DestReg = merge(DestReg, DebugSrc1, dataSize);
+ }
+ '''
+
+ class Wrdr(RegOp):
+ def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
+ super(Wrdr, self).__init__(dest, \
+ src1, "NUM_INTREGS", flags, dataSize)
+ code = '''
+ CR4 cr4 = CR4Op;
+ DR7 dr7 = DR7Op;
+ if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) {
+ fault = new InvalidOpcode();
+ } else if ((dest == 6 || dest == 7) &&
+ bits(psrc1, 63, 32) &&
+ machInst.mode.mode == LongMode) {
+ fault = new GeneralProtection(0);
+ } else if (dr7.gd) {
+ fault = new DebugException();
+ } else {
+ DebugDest = psrc1;
+ }
+ '''
class Rdcr(RegOp):
def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
super(Rdcr, self).__init__(dest, \
src1, "NUM_INTREGS", flags, dataSize)
code = '''
- if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) {
+ if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) {
fault = new InvalidOpcode();
} else {
- DestReg = ControlSrc1;
+ DestReg = merge(DestReg, ControlSrc1, dataSize);
}
'''
@@ -950,7 +1024,7 @@ let {{
'''
# Microops for manipulating segmentation registers
- class SegOp(RegOp):
+ class SegOp(CondRegOp):
abstract = True
def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
super(SegOp, self).__init__(dest, \
@@ -971,74 +1045,223 @@ let {{
SegSelDest = psrc1;
'''
+ class WrAttr(SegOp):
+ code = '''
+ SegAttrDest = psrc1;
+ '''
+
class Rdbase(SegOp):
code = '''
- DestReg = SegBaseDest;
+ DestReg = merge(DestReg, SegBaseSrc1, dataSize);
'''
class Rdlimit(SegOp):
code = '''
- DestReg = SegLimitSrc1;
+ DestReg = merge(DestReg, SegLimitSrc1, dataSize);
+ '''
+
+ class RdAttr(SegOp):
+ code = '''
+ DestReg = merge(DestReg, SegAttrSrc1, dataSize);
'''
class Rdsel(SegOp):
code = '''
- DestReg = SegSelSrc1;
+ DestReg = merge(DestReg, SegSelSrc1, dataSize);
'''
- class Chks(SegOp):
+ class Rdval(RegOp):
+ def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
+ super(Rdval, self).__init__(dest, \
+ src1, "NUM_INTREGS", flags, dataSize)
code = '''
- // The selector is in source 1.
- SegSelector selector = psrc1;
-
- // Compute the address of the descriptor and set DestReg to it.
- if (selector.ti) {
- // A descriptor in the LDT
- Addr target = (selector.esi << 3) + LDTRBase;
- if (!LDTRSel || (selector.esi << 3) + dataSize > LDTRLimit)
- fault = new GeneralProtection(selector & mask(16));
- DestReg = target;
- } else {
- // A descriptor in the GDT
- Addr target = (selector.esi << 3) + GDTRBase;
- if ((selector.esi << 3) + dataSize > GDTRLimit)
- fault = new GeneralProtection(selector & mask(16));
- DestReg = target;
+ DestReg = MiscRegSrc1;
+ '''
+
+ class Wrval(RegOp):
+ def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
+ super(Wrval, self).__init__(dest, \
+ src1, "NUM_INTREGS", flags, dataSize)
+ code = '''
+ MiscRegDest = SrcReg1;
+ '''
+
+ class Chks(RegOp):
+ def __init__(self, dest, src1, src2=0,
+ flags=None, dataSize="env.dataSize"):
+ super(Chks, self).__init__(dest,
+ src1, src2, flags, dataSize)
+ code = '''
+ // The selector is in source 1 and can be at most 16 bits.
+ SegSelector selector = DestReg;
+ SegDescriptor desc = SrcReg1;
+ HandyM5Reg m5reg = M5Reg;
+
+ switch (imm8)
+ {
+ case SegNoCheck:
+ break;
+ case SegCSCheck:
+ panic("CS checks for far calls/jumps not implemented.\\n");
+ break;
+ case SegCallGateCheck:
+ panic("CS checks for far calls/jumps through call gates"
+ "not implemented.\\n");
+ break;
+ case SegSoftIntGateCheck:
+ // Check permissions.
+ if (desc.dpl < m5reg.cpl) {
+ fault = new GeneralProtection(selector);
+ }
+ // Fall through on purpose
+ case SegIntGateCheck:
+ // Make sure the gate's the right type.
+ if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) ||
+ ((desc.type & 0x6) != 0x6)) {
+ fault = new GeneralProtection(0);
+ }
+ break;
+ case SegSSCheck:
+ if (selector.si || selector.ti) {
+ if (!desc.p) {
+ fault = new StackFault(selector);
+ }
+ } else {
+ if ((m5reg.submode != SixtyFourBitMode ||
+ m5reg.cpl == 3) ||
+ !(desc.s == 1 &&
+ desc.type.codeOrData == 0 && desc.type.w) ||
+ (desc.dpl != m5reg.cpl) ||
+ (selector.rpl != m5reg.cpl)) {
+ fault = new GeneralProtection(selector);
+ }
+ }
+ break;
+ case SegIretCheck:
+ {
+ if ((!selector.si && !selector.ti) ||
+ (selector.rpl < m5reg.cpl) ||
+ !(desc.s == 1 && desc.type.codeOrData == 1) ||
+ (!desc.type.c && desc.dpl != selector.rpl) ||
+ (desc.type.c && desc.dpl > selector.rpl)) {
+ fault = new GeneralProtection(selector);
+ } else if (!desc.p) {
+ fault = new SegmentNotPresent(selector);
+ }
+ break;
+ }
+ case SegIntCSCheck:
+ if (m5reg.mode == LongMode) {
+ if (desc.l != 1 || desc.d != 0) {
+ fault = new GeneralProtection(selector);
+ }
+ } else {
+ panic("Interrupt CS checks not implemented "
+ "in legacy mode.\\n");
+ }
+ break;
+ case SegTRCheck:
+ if (!selector.si || selector.ti) {
+ fault = new GeneralProtection(selector);
+ }
+ break;
+ case SegTSSCheck:
+ if (!desc.p) {
+ fault = new SegmentNotPresent(selector);
+ } else if (!(desc.type == 0x9 ||
+ (desc.type == 1 &&
+ m5reg.mode != LongMode))) {
+ fault = new GeneralProtection(selector);
+ }
+ break;
+ case SegInGDTCheck:
+ if (selector.ti) {
+ fault = new GeneralProtection(selector);
+ }
+ break;
+ case SegLDTCheck:
+ if (!desc.p) {
+ fault = new SegmentNotPresent(selector);
+ } else if (desc.type != 0x2) {
+ fault = new GeneralProtection(selector);
+ }
+ break;
+ default:
+ panic("Undefined segment check type.\\n");
}
'''
flag_code = '''
// Check for a NULL selector and set ZF,EZF appropriately.
ccFlagBits = ccFlagBits & ~(ext & (ZFBit | EZFBit));
- if (!selector.esi && !selector.ti)
+ if (!selector.si && !selector.ti)
ccFlagBits = ccFlagBits | (ext & (ZFBit | EZFBit));
'''
class Wrdh(RegOp):
code = '''
+ SegDescriptor desc = SrcReg1;
+
+ uint64_t target = bits(SrcReg2, 31, 0) << 32;
+ switch(desc.type) {
+ case LDT64:
+ case AvailableTSS64:
+ case BusyTSS64:
+ replaceBits(target, 23, 0, desc.baseLow);
+ replaceBits(target, 31, 24, desc.baseHigh);
+ break;
+ case CallGate64:
+ case IntGate64:
+ case TrapGate64:
+ replaceBits(target, 15, 0, bits(desc, 15, 0));
+ replaceBits(target, 31, 16, bits(desc, 63, 48));
+ break;
+ default:
+ panic("Wrdh used with wrong descriptor type!\\n");
+ }
+ DestReg = target;
+ '''
+
+ class Wrtsc(WrRegOp):
+ code = '''
+ TscOp = psrc1;
+ '''
+
+ class Rdtsc(RdRegOp):
+ code = '''
+ DestReg = TscOp;
+ '''
+ class Rdm5reg(RdRegOp):
+ code = '''
+ DestReg = M5Reg;
'''
class Wrdl(RegOp):
code = '''
SegDescriptor desc = SrcReg1;
- SegAttr attr = 0;
- attr.dpl = desc.dpl;
- attr.defaultSize = desc.d;
- if (!desc.s) {
- SegBaseDest = SegBaseDest;
- SegLimitDest = SegLimitDest;
- SegAttrDest = SegAttrDest;
- panic("System segment encountered.\\n");
- } else {
- if (!desc.p)
- panic("Segment not present.\\n");
- if (desc.type.codeOrData) {
- attr.readable = desc.type.r;
- attr.longMode = desc.l;
- } else {
- attr.expandDown = desc.type.e;
+ SegSelector selector = SrcReg2;
+ if (selector.si || selector.ti) {
+ SegAttr attr = 0;
+ attr.dpl = desc.dpl;
+ attr.defaultSize = desc.d;
+ if (!desc.s) {
+ // The expand down bit happens to be set for gates.
+ if (desc.type.e) {
+ panic("Gate descriptor encountered.\\n");
+ }
attr.readable = 1;
- attr.writable = desc.type.w;
+ attr.writable = 1;
+ } else {
+ if (!desc.p)
+ panic("Segment not present.\\n");
+ if (desc.type.codeOrData) {
+ attr.readable = desc.type.r;
+ attr.longMode = desc.l;
+ } else {
+ attr.expandDown = desc.type.e;
+ attr.readable = 1;
+ attr.writable = desc.type.w;
+ }
}
Addr base = desc.baseLow | (desc.baseHigh << 24);
Addr limit = desc.limitLow | (desc.limitHigh << 16);
@@ -1047,6 +1270,10 @@ let {{
SegBaseDest = base;
SegLimitDest = limit;
SegAttrDest = attr;
+ } else {
+ SegBaseDest = SegBaseDest;
+ SegLimitDest = SegLimitDest;
+ SegAttrDest = SegAttrDest;
}
'''
}};
diff --git a/src/arch/x86/isa/microops/seqop.isa b/src/arch/x86/isa/microops/seqop.isa
new file mode 100644
index 000000000..332519b87
--- /dev/null
+++ b/src/arch/x86/isa/microops/seqop.isa
@@ -0,0 +1,251 @@
+// Copyright (c) 2008 The Hewlett-Packard Development Company
+// All rights reserved.
+//
+// Redistribution and use of this software in source and binary forms,
+// with or without modification, are permitted provided that the
+// following conditions are met:
+//
+// The software must be used only for Non-Commercial Use which means any
+// use which is NOT directed to receiving any direct monetary
+// compensation for, or commercial advantage from such use. Illustrative
+// examples of non-commercial use are academic research, personal study,
+// teaching, education and corporate research & development.
+// Illustrative examples of commercial use are distributing products for
+// commercial advantage and providing services using the software for
+// commercial advantage.
+//
+// If you wish to use this software or functionality therein that may be
+// covered by patents for commercial use, please contact:
+// Director of Intellectual Property Licensing
+// Office of Strategy and Technology
+// Hewlett-Packard Company
+// 1501 Page Mill Road
+// Palo Alto, California 94304
+//
+// Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer. Redistributions
+// in binary form must reproduce the above copyright notice, this list of
+// conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution. Neither the name of
+// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission. No right of
+// sublicense is granted herewith. Derivatives of the software and
+// output created using the software may be prepared, but only for
+// Non-Commercial Uses. Derivatives of the software may be shared with
+// others provided: (i) the others agree to abide by the list of
+// conditions herein which includes the Non-Commercial Use restrictions;
+// and (ii) such Derivatives of the software include the above copyright
+// notice to acknowledge the contribution from this software where
+// applicable, this list of conditions and the disclaimer below.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: Gabe Black
+
+output header {{
+ class SeqOpBase : public X86ISA::X86MicroopBase
+ {
+ protected:
+ uint16_t target;
+ uint8_t cc;
+
+ public:
+ SeqOpBase(ExtMachInst _machInst, const char * instMnem,
+ const char * mnemonic,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ uint16_t _target, uint8_t _cc);
+
+ SeqOpBase(ExtMachInst _machInst, const char * instMnem,
+ const char * mnemonic,
+ uint16_t _target, uint8_t _cc);
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+}};
+
+def template SeqOpDeclare {{
+ class %(class_name)s : public %(base_class)s
+ {
+ private:
+ void buildMe();
+ public:
+ %(class_name)s(ExtMachInst _machInst, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ uint16_t _target, uint8_t _cc);
+
+ %(class_name)s(ExtMachInst _machInst, const char * instMnem,
+ uint16_t _target, uint8_t _cc);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+def template SeqOpExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ %(op_decl)s;
+ %(op_rd)s;
+ if (%(cond_test)s) {
+ %(code)s;
+ } else {
+ %(else_code)s;
+ }
+ %(op_wb)s;
+ return NoFault;
+ }
+}};
+
+output decoder {{
+ inline SeqOpBase::SeqOpBase(
+ ExtMachInst machInst, const char * mnemonic, const char * instMnem,
+ uint16_t _target, uint8_t _cc) :
+ X86MicroopBase(machInst, mnemonic, instMnem,
+ false, false, false, false, No_OpClass),
+ target(_target), cc(_cc)
+ {
+ }
+
+ inline SeqOpBase::SeqOpBase(
+ ExtMachInst machInst, const char * mnemonic, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ uint16_t _target, uint8_t _cc) :
+ X86MicroopBase(machInst, mnemonic, instMnem,
+ isMicro, isDelayed, isFirst, isLast, No_OpClass),
+ target(_target), cc(_cc)
+ {
+ }
+}};
+
+def template SeqOpConstructor {{
+
+ inline void %(class_name)s::buildMe()
+ {
+ %(constructor)s;
+ }
+
+ inline %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem,
+ uint16_t _target, uint8_t _cc) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem, _target, _cc)
+ {
+ buildMe();
+ }
+
+ inline %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ uint16_t _target, uint8_t _cc) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ isMicro, isDelayed, isFirst, isLast, _target, _cc)
+ {
+ buildMe();
+ }
+}};
+
+output decoder {{
+ std::string SeqOpBase::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+
+ printMnemonic(response, instMnem, mnemonic);
+ ccprintf(response, "%#x", target);
+
+ return response.str();
+ }
+}};
+
+let {{
+ class SeqOp(X86Microop):
+ def __init__(self, target, flags=None):
+ self.target = target
+ if flags:
+ if not isinstance(flags, (list, tuple)):
+ raise Exception, "flags must be a list or tuple of flags"
+ self.cond = " | ".join(flags)
+ self.className += "Flags"
+ else:
+ self.cond = "0"
+
+ def getAllocator(self, *microFlags):
+ allocator = '''new %(class_name)s(machInst, macrocodeBlock
+ %(flags)s, %(target)s, %(cc)s)''' % {
+ "class_name" : self.className,
+ "flags" : self.microFlagsText(microFlags),
+ "target" : self.target,
+ "cc" : self.cond}
+ return allocator
+
+ class Br(SeqOp):
+ className = "MicroBranch"
+
+ def getAllocator(self, *microFlags):
+ (is_micro, is_delayed, is_first, is_last) = microFlags
+ is_last = False
+ is_delayed = True
+ microFlags = (is_micro, is_delayed, is_first, is_last)
+ return super(Br, self).getAllocator(*microFlags)
+
+ class Eret(SeqOp):
+ target = "normalMicroPC(0)"
+ className = "Eret"
+
+ def __init__(self, flags=None):
+ if flags:
+ if not isinstance(flags, (list, tuple)):
+ raise Exception, "flags must be a list or tuple of flags"
+ self.cond = " | ".join(flags)
+ self.className += "Flags"
+ else:
+ self.cond = "0"
+
+ def getAllocator(self, *microFlags):
+ (is_micro, is_delayed, is_first, is_last) = microFlags
+ is_last = True
+ is_delayed = False
+ microFlags = (is_micro, is_delayed, is_first, is_last)
+ return super(Eret, self).getAllocator(*microFlags)
+
+ iop = InstObjParams("br", "MicroBranchFlags", "SeqOpBase",
+ {"code": "nuIP = target",
+ "else_code": "nuIP = nuIP",
+ "cond_test": "checkCondition(ccFlagBits, cc)"})
+ exec_output += SeqOpExecute.subst(iop)
+ header_output += SeqOpDeclare.subst(iop)
+ decoder_output += SeqOpConstructor.subst(iop)
+ iop = InstObjParams("br", "MicroBranch", "SeqOpBase",
+ {"code": "nuIP = target",
+ "else_code": "nuIP = nuIP",
+ "cond_test": "true"})
+ exec_output += SeqOpExecute.subst(iop)
+ header_output += SeqOpDeclare.subst(iop)
+ decoder_output += SeqOpConstructor.subst(iop)
+ microopClasses["br"] = Br
+
+ iop = InstObjParams("eret", "EretFlags", "SeqOpBase",
+ {"code": "", "else_code": "",
+ "cond_test": "checkCondition(ccFlagBits, cc)"})
+ exec_output += SeqOpExecute.subst(iop)
+ header_output += SeqOpDeclare.subst(iop)
+ decoder_output += SeqOpConstructor.subst(iop)
+ iop = InstObjParams("eret", "Eret", "SeqOpBase",
+ {"code": "", "else_code": "",
+ "cond_test": "true"})
+ exec_output += SeqOpExecute.subst(iop)
+ header_output += SeqOpDeclare.subst(iop)
+ decoder_output += SeqOpConstructor.subst(iop)
+ microopClasses["eret"] = Eret
+}};
diff --git a/src/arch/x86/isa/microops/specop.isa b/src/arch/x86/isa/microops/specop.isa
index 6bcc7ff91..c6e172ef1 100644
--- a/src/arch/x86/isa/microops/specop.isa
+++ b/src/arch/x86/isa/microops/specop.isa
@@ -1,4 +1,4 @@
-// Copyright (c) 2007 The Hewlett-Packard Development Company
+// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
// All rights reserved.
//
// Redistribution and use of this software in source and binary forms,
@@ -95,6 +95,9 @@ output header {{
}
%(BasicExecDeclare)s
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
};
}};
@@ -201,6 +204,16 @@ output decoder {{
return response.str();
}
+
+ std::string MicroHalt::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+
+ printMnemonic(response, instMnem, mnemonic);
+
+ return response.str();
+ }
}};
let {{
@@ -217,7 +230,7 @@ let {{
self.cond = "0"
def getAllocator(self, *microFlags):
- allocator = '''new %(class_name)s(machInst, mnemonic
+ allocator = '''new %(class_name)s(machInst, macrocodeBlock
%(flags)s, %(fault)s, %(cc)s)''' % {
"class_name" : self.className,
"flags" : self.microFlagsText(microFlags),
@@ -244,7 +257,7 @@ let {{
pass
def getAllocator(self, *microFlags):
- return "new MicroHalt(machInst, mnemonic %s)" % \
+ return "new MicroHalt(machInst, macrocodeBlock %s)" % \
self.microFlagsText(microFlags)
microopClasses["halt"] = Halt