summaryrefslogtreecommitdiff
path: root/src/arch/x86
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-06-04 15:59:20 +0000
committerGabe Black <gblack@eecs.umich.edu>2007-06-04 15:59:20 +0000
commit41bc0fc5b27b97f6235e5cd3fe089ff43b588bef (patch)
tree7c29765ea484fd0fde4a6d82b0f03aba3203c856 /src/arch/x86
parente47f1667b6f5f3b329c171a10d571696bd24b045 (diff)
downloadgem5-41bc0fc5b27b97f6235e5cd3fe089ff43b588bef.tar.xz
Reworking x86's microcode system. This is a work in progress, and X86 doesn't compile.
src/arch/x86/isa/decoder/one_byte_opcodes.isa: src/arch/x86/isa/macroop.isa: src/arch/x86/isa/main.isa: src/arch/x86/isa/microasm.isa: src/arch/x86/isa/microops/base.isa: src/arch/x86/isa/microops/microops.isa: src/arch/x86/isa/operands.isa: src/arch/x86/isa/microops/regop.isa: src/arch/x86/isa/microops/specop.isa: Reworking x86's microcode system --HG-- extra : convert_revision : cab66be59ed758b192226af17eddd5a86aa190f3
Diffstat (limited to 'src/arch/x86')
-rw-r--r--src/arch/x86/isa/decoder/one_byte_opcodes.isa22
-rw-r--r--src/arch/x86/isa/macroop.isa3
-rw-r--r--src/arch/x86/isa/main.isa4
-rw-r--r--src/arch/x86/isa/microasm.isa164
-rw-r--r--src/arch/x86/isa/microops/base.isa202
-rw-r--r--src/arch/x86/isa/microops/microops.isa8
-rw-r--r--src/arch/x86/isa/microops/regop.isa328
-rw-r--r--src/arch/x86/isa/microops/specop.isa125
-rw-r--r--src/arch/x86/isa/operands.isa3
9 files changed, 623 insertions, 236 deletions
diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
index 12f3c5f96..0ee9c53c6 100644
--- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa
+++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
@@ -61,12 +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: ADD();
+ 0x5: ADD();
0x6: push_ES();
0x7: pop_ES();
- default: MultiInst::ADD(OPCODE_OP_BOTTOM3,
- [Eb,Gb],[Ev,Gv],[Gb,Eb],[Gv,Ev]);
+ default: ADD();
}
0x01: decode OPCODE_OP_BOTTOM3 {
0x0: or_Eb_Gb();
@@ -123,13 +122,12 @@
0x7: das();
}
0x06: decode OPCODE_OP_BOTTOM3 {
- 0x4: Inst::XOR(rAl,Ib);
- 0x5: Inst::XOR(rAx,Iz);
+ 0x4: Inst::XOR(ALIb);
+ 0x5: Inst::XOR(rAX,Iz);
0x6: M5InternalError::error(
{{"Tried to execute the SS segment override prefix!"}});
0x7: aaa();
- default: MultiInst::XOR(OPCODE_OP_BOTTOM3,
- [Eb,Gb],[Ev,Gv],[Gb,Eb],[Gv,Ev]);
+ default: MultiInst::XOR(EbGb, EvGv, GbEb, GvEv);
}
0x07: decode OPCODE_OP_BOTTOM3 {
0x0: cmp_Eb_Gb();
@@ -237,10 +235,10 @@
0x7: xchg_Ev_Gv();
}
0x11: decode OPCODE_OP_BOTTOM3 {
- 0x0: Inst::MOV(Eb, Gb);
- 0x1: Inst::MOV(Ev, Gv);
- 0x2: Inst::MOV(Gb, Eb);
- 0x3: Inst::MOV(Gv, Ev);
+ 0x0: MOV();
+ 0x1: MOV();
+ 0x2: MOV();
+ 0x3: MOV();
0x4: mov_MwRv_Sw(); //What to do with this one?
0x5: lea_Gv_M();
0x6: mov_Sw_MwRv();
diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa
index 663ec7aee..ba21c41a7 100644
--- a/src/arch/x86/isa/macroop.isa
+++ b/src/arch/x86/isa/macroop.isa
@@ -149,7 +149,8 @@ let {{
for op in opSeq:
allocMicroOps += \
"microOps[%d] = %s;\n" % \
- (micropc, op.getAllocator('"' + name + '"', True, False, #op.delayed,
+ (micropc, op.getAllocator('"' + name + '"', True, False,
+ #op.delayed,
micropc == 0,
micropc == numMicroOps - 1))
micropc += 1
diff --git a/src/arch/x86/isa/main.isa b/src/arch/x86/isa/main.isa
index 063d7125d..a9f01d3e0 100644
--- a/src/arch/x86/isa/main.isa
+++ b/src/arch/x86/isa/main.isa
@@ -81,10 +81,6 @@ namespace X86ISA;
//Include code to build macroops.
##include "macroop.isa"
-//Include the simple microcode assembler. This will hopefully stay
-//unspecialized for x86 and can later be made available to other ISAs.
-##include "microasm.isa"
-
////////////////////////////////////////////////////////////////////
//
// X86 only infrastructure code.
diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa
index 9d21b6bcc..50a0b10e7 100644
--- a/src/arch/x86/isa/microasm.isa
+++ b/src/arch/x86/isa/microasm.isa
@@ -57,22 +57,24 @@
////////////////////////////////////////////////////////////////////
//
-// The microcode assembler
+// Microcode assembler specialization for x86
//
let {{
- # These are used when setting up microops so that they can specialize their
- # base class template properly.
- RegOpType = "RegisterOperand"
- ImmOpType = "ImmediateOperand"
+ from micro_asm import MicroAssembler, Combinational_Macroop, Rom_Macroop, Rom
+ class X86Macroop(Combinational_Macroop):
+ def __init__(self, name):
+ super(X86Macroop, self).__init__(name)
+ self.directives = {
+ }
+
+ mainRom = Rom('main ROM')
}};
let {{
- class MicroOpStatement(object):
- def __init__(self):
- self.className = ''
- self.label = ''
- self.args = []
+ class X86Microop(object):
+ def __init__(self, name):
+ self.name = name
# This converts a list of python bools into
# a comma seperated list of C++ bools.
@@ -87,145 +89,5 @@ let {{
def getAllocator(self, mnemonic, *microFlags):
args = ''
- signature = "<"
- emptySig = True
- for arg in self.args:
- if not emptySig:
- signature += ", "
- emptySig = False
- if arg.has_key("operandImm"):
- args += ", %s" % arg["operandImm"]
- signature += ImmOpType
- elif arg.has_key("operandReg"):
- args += ", %s" % arg["operandReg"]
- signature += RegOpType
- elif arg.has_key("operandLabel"):
- raise Exception, "Found a label while creating allocator string."
- else:
- raise Exception, "Unrecognized operand type."
- signature += ">"
- return 'new %s%s(machInst, %s%s%s)' % (self.className, signature, mnemonic, self.microFlagsText(microFlags), args)
-}};
-
-let{{
- def assembleMicro(name, Name, code):
-
- # This function takes in a block of microcode assembly and returns
- # a python list of objects which describe it.
-
- # Keep this around in case we need it later
- orig_code = code
- # A list of the statements we've found thus far
- statements = []
-
- # Regular expressions to pull each piece of the statement out at a
- # time. Each expression expects the thing it's looking for to be at
- # 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|$)')
- 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
- # 2. Code beginning with "{" and continuing until the first "}"
- # ^ This one might need revising
- # 3. A label, which starts with a capital or small letter, or
- # underscore, which is optionally followed by a sequence of
- # capital or small letters, underscores, or digts between 0 and 9
- opRe = re.compile( \
- r'^[ \t]*((\@(?P<operandLabel0>\w\w*))|' +
- r'(\@\{(?P<operandLabel1>[^}]*)\})|' +
- r'(\%(?P<operandReg0>\w\w*))|' +
- r'(\%\{(?P<operandReg1>[^}]*)\})|' +
- r'(\$(?P<operandImm0>\w\w*))|' +
- r'(\$\{(?P<operandImm1>[^}]*)\}))')
- lineMatch = lineRe.search(code)
- while lineMatch != None:
- statement = MicroOpStatement()
- # Get a line and seperate it from the rest of the code
- line = lineMatch.group("line")
- orig_line = 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
- # Clear the label from the statement
- line = labelRe.sub('', line, 1)
-
- # Find the class name which is roughly equivalent to the op name
- classMatch = classRe.search(line)
- if classMatch == None:
- raise Exception, "Couldn't find class name in statement: %s" \
- % orig_line
- else:
- statement.className = classMatch.group("className")
- #print "Found class name %s." % statement.className
-
- # Clear the class name from the statement
- line = classRe.sub('', line, 1)
-
- #Find as many arguments as you can
- statement.args = []
- opMatch = opRe.search(line)
- while opMatch is not None:
- statement.args.append({})
- # args is a list of dicts which collect different
- # representations of operand values. Different forms might be
- # needed in different places, for instance to replace a label
- # with an offset.
- for opType in ("operandLabel0", "operandReg0", "operandImm0",
- "operandLabel1", "operandReg1", "operandImm1"):
- if opMatch.group(opType):
- statement.args[-1][opType[:-1]] = opMatch.group(opType)
- if len(statement.args[-1]) == 0:
- print "Problem parsing operand in statement: %s" \
- % orig_line
- line = opRe.sub('', line, 1)
- #print "Found operand %s." % statement.args[-1]
- opMatch = opRe.search(line)
- #print "Found operands", statement.args
-
- # Add this statement to our collection
- statements.append(statement)
-
- # Get the next line
- lineMatch = lineRe.search(code)
-
- # Decode the labels into displacements
-
- labels = {}
- micropc = 0
- for statement in statements:
- if statement.label:
- labels[statement.label] = count
- micropc += 1
- micropc = 0
- for statement in statements:
- for arg in statement.args:
- if arg.has_key("operandLabel"):
- if not labels.has_key(arg["operandLabel"]):
- raise Exception, "Unrecognized label: %s." % arg["operandLabel"]
- # This is assuming that intra microcode branches go to
- # the next micropc + displacement, or
- # micropc + 1 + displacement.
- 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('"' + name + '"')
- return ('', '', decode_block, '')
- else:
- # Build a macroop to contain the sequence of microops we've
- # been given.
- return genMacroOp(name, Name, statements)
+ return 'new %s(machInst, %s%s%s)' % (self.className, mnemonic, self.microFlagsText(microFlags), args)
}};
diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa
index f0aab7872..04cfa6e57 100644
--- a/src/arch/x86/isa/microops/base.isa
+++ b/src/arch/x86/isa/microops/base.isa
@@ -55,12 +55,10 @@
//
// Authors: Gabe Black
-//The operand types a microop template can be specialized with
-output header {{
- enum OperandType {
- RegisterOperand,
- ImmediateOperand
- };
+let {{
+ # This will be populated with mappings between microop mnemonics and
+ # the classes that represent them.
+ microopClasses = {}
}};
//A class which is the base of all x86 micro ops. It provides a function to
@@ -99,96 +97,172 @@ output header {{
};
}};
-// This sets up a class which is templated on the type of
-// arguments a particular flavor of a microcode instruction
-// can accept. It's parameters are specialized to create polymorphic
-// behavior in microops.
-def template BaseMicroOpTemplateDeclare {{
- template%(signature)s
- class %(class_name)s;
-}};
+//////////////////////////////////////////////////////////////////////////
+//
+// Base class for the python representation of x86 microops
let {{
- def buildBaseMicroOpTemplate(Name, numParams):
- assert(numParams > 0)
- signature = "<"
- signature += "int SignatureOperandTypeSpecifier0"
- for count in xrange(1,numParams):
- signature += \
- ", int SingatureOperandTypeSpecifier%d" % count
- signature += ">"
- subs = {"signature" : signature, "class_name" : Name}
- return BaseMicroOpTemplateDeclare.subst(subs)
+ class X86Microop(object):
+ def __init__(self, name):
+ self.name = name
+
+ # This converts a list of python bools into
+ # a comma seperated list of C++ bools.
+ def microFlagsText(self, vals):
+ text = ""
+ for val in vals:
+ if val:
+ text += ", true"
+ else:
+ text += ", false"
+ return text
+
+ def getAllocator(self, mnemonic, *microFlags):
+ return 'new %s(machInst, %s)' % (self.className, mnemonic, self.microFlagsText(microFlags))
}};
-let {{
- def buildMicroOpTemplateDict(*params):
- signature = "<"
- if len(params):
- signature += params[0]
- if len(params) > 1:
- for param in params[1:]:
- signature += ", %s" % param
- signature += ">"
- subs = {"param_dec" : "", "param_arg_dec" : "",
- "param_init" : "", "signature" : signature}
- for count in xrange(len(params)):
- subs["param_dec"] += "uint64_t param%d;\n" % count
- subs["param_arg_dec"] += ", uint64_t _param%d" % count
- subs["param_init"] += ", param%d(_param%d)" % (count, count)
- return subs
+//////////////////////////////////////////////////////////////////////////
+//
+// LdStOp Microop templates
+//
+//////////////////////////////////////////////////////////////////////////
+
+def template MicroLdStOpDeclare {{
+ class %(class_name)s : public X86MicroOpBase
+ {
+ protected:
+ const uint8_t scale;
+ const RegIndex index;
+ const RegIndex base;
+ const uint64_t disp;
+ const uint8_t segment;
+ const RegIndex data;
+ const uint8_t dataSize;
+ const uint8_t addressSize;
+ void buildMe();
+
+ public:
+ %(class_name)s(ExtMachInst _machInst,
+ const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ uint8_t _scale, RegIndex _index, RegIndex _base,
+ uint64_t _disp, uint8_t _segment,
+ RegIndex _data,
+ uint8_t _dataSize, uint8_t _addressSize);
+
+ %(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);
+
+ %(BasicExecDeclare)s
+ };
}};
-// A tmeplate for building a specialized version of the microcode
-// instruction which specifies which arguments it wants
-def template MicroOpDeclare {{
- template<>
- class %(class_name)s%(signature)s : public X86MicroOpBase
+def template MicroLdStOpConstructor {{
+
+ inline void %(class_name)s::buildMe()
+ {
+ %(constructor)s;
+ }
+
+ inline %(class_name)s::%(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) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ false, false, false, false, %(op_class)s),
+ scale(_scale), index(_index), base(_base),
+ disp(_disp), segment(_segment),
+ data(_data),
+ dataSize(_dataSize), addressSize(_addressSize)
+ {
+ buildMe();
+ }
+
+ inline %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ uint8_t _scale, RegIndex _index, RegIndex _base,
+ uint64_t _disp, uint8_t segment,
+ RegIndex data,
+ uint8_t dataSize, uint8_t addressSize) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ isMicro, isDelayed, isFirst, isLast, %(op_class)s),
+ scale(_scale), index(_index), base(_base),
+ disp(_disp), segment(_segment),
+ data(_data),
+ dataSize(_dataSize), addressSize(_addressSize)
+ {
+ buildMe();
+ }
+}};
+
+//////////////////////////////////////////////////////////////////////////
+//
+// LIMMOp Microop templates
+//
+//////////////////////////////////////////////////////////////////////////
+
+def template MicroLIMMOpDeclare {{
+ class %(class_name)s : public X86MicroOpBase
{
protected:
- %(param_dec)s
+ const RegIndex dest;
+ const uint64_t imm;
void buildMe();
public:
%(class_name)s(ExtMachInst _machInst,
const char * instMnem,
- bool isMicro, bool isDelayed,
- bool isFirst, bool isLast
- %(param_arg_dec)s);
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ RegIndex _dest, uint64_t _imm);
%(class_name)s(ExtMachInst _machInst,
- const char * instMnem
- %(param_arg_dec)s);
+ const char * instMnem,
+ RegIndex _dest, uint64_t _imm);
%(BasicExecDeclare)s
};
}};
-def template MicroOpConstructor {{
+def template MicroLIMMOpConstructor {{
- inline void %(class_name)s%(signature)s::buildMe()
+ inline void %(class_name)s::buildMe()
{
%(constructor)s;
}
- inline %(class_name)s%(signature)s::%(class_name)s(
- ExtMachInst machInst, const char * instMnem
- %(param_arg_dec)s) :
+ inline %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem,
+ RegIndex _dest, uint64_t _imm) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
- false, false, false, false, %(op_class)s)
- %(param_init)s
+ false, false, false, false, %(op_class)s),
+ dest(_dest), imm(_imm)
{
buildMe();
}
- inline %(class_name)s%(signature)s::%(class_name)s(
+ inline %(class_name)s::%(class_name)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
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ RegIndex _dest, uint64_t _imm) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ isMicro, isDelayed, isFirst, isLast, %(op_class)s),
+ dest(_dest), imm(_imm)
{
buildMe();
}
}};
+
+//////////////////////////////////////////////////////////////////////////
+//
+// FpOp Microop templates
+//
+//////////////////////////////////////////////////////////////////////////
+
+//TODO Actually write an fp microop base class.
diff --git a/src/arch/x86/isa/microops/microops.isa b/src/arch/x86/isa/microops/microops.isa
index d877152eb..0262cde02 100644
--- a/src/arch/x86/isa/microops/microops.isa
+++ b/src/arch/x86/isa/microops/microops.isa
@@ -56,8 +56,8 @@
//Common microop stuff
##include "base.isa"
-//A microop that generates a specified fault
-##include "fault.isa"
+//Miscellaneous microop definitions
+##include "specop.isa"
-//Integer microop definitions
-##include "int.isa"
+//Register microop definitions
+##include "regop.isa"
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa
new file mode 100644
index 000000000..7411f6a14
--- /dev/null
+++ b/src/arch/x86/isa/microops/regop.isa
@@ -0,0 +1,328 @@
+// Copyright (c) 2007 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
+
+//////////////////////////////////////////////////////////////////////////
+//
+// RegOp Microop templates
+//
+//////////////////////////////////////////////////////////////////////////
+
+def template MicroRegOpExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ //Write the resulting state to the execution context
+ if(fault == NoFault)
+ {
+ %(op_wb)s;
+ }
+ return fault;
+ }
+}};
+
+def template MicroRegOpImmExecute {{
+ Fault %(class_name)sImm::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ //Write the resulting state to the execution context
+ if(fault == NoFault)
+ {
+ %(op_wb)s;
+ }
+ return fault;
+ }
+}};
+
+def template MicroRegOpDeclare {{
+ class %(class_name)s : public %(base_class)s
+ {
+ protected:
+ const RegIndex src1;
+ const RegIndex src2;
+ const RegIndex dest;
+ const bool setStatus;
+ const uint8_t dataSize;
+ const uint8_t ext;
+ void buildMe();
+
+ public:
+ %(class_name)s(ExtMachInst _machInst,
+ const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ RegIndex _src1, RegIndex _src2, RegIndex _dest,
+ bool _setStatus, uint8_t _dataSize, uint8_t _ext);
+
+ %(class_name)s(ExtMachInst _machInst,
+ const char * instMnem,
+ RegIndex _src1, RegIndex _src2, RegIndex _dest,
+ bool _setStatus, uint8_t _dataSize, uint8_t _ext);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+def template MicroRegOpImmDeclare {{
+
+ class %(class_name)sImm : public %(base_class)s
+ {
+ protected:
+ const RegIndex src1;
+ const uint8_t imm8;
+ const RegIndex dest;
+ const bool setStatus;
+ const uint8_t dataSize;
+ const uint8_t ext;
+ void buildMe();
+
+ public:
+ %(class_name)sImm(ExtMachInst _machInst,
+ const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ RegIndex _src1, uint8_t _imm8, RegIndex _dest,
+ bool _setStatus, uint8_t _dataSize, uint8_t _ext);
+
+ %(class_name)sImm(ExtMachInst _machInst,
+ const char * instMnem,
+ RegIndex _src1, uint8_t _imm8, RegIndex _dest,
+ bool _setStatus, uint8_t _dataSize, uint8_t _ext);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+def template MicroRegOpConstructor {{
+
+ inline void %(class_name)s::buildMe()
+ {
+ %(constructor)s;
+ }
+
+ inline %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem,
+ RegIndex _src1, RegIndex _src2, RegIndex _dest,
+ bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ false, false, false, false, %(op_class)s),
+ src1(_src1), src2(_src2), dest(_dest),
+ setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
+ {
+ buildMe();
+ }
+
+ inline %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ RegIndex _src1, RegIndex _src2, RegIndex _dest,
+ bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ isMicro, isDelayed, isFirst, isLast, %(op_class)s),
+ src1(_src1), src2(_src2), dest(_dest),
+ setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
+ {
+ buildMe();
+ }
+}};
+
+def template MicroRegOpImmConstructor {{
+
+ inline void %(class_name)sImm::buildMe()
+ {
+ %(constructor)s;
+ }
+
+ inline %(class_name)sImm::%(class_name)sImm(
+ ExtMachInst machInst, const char * instMnem,
+ RegIndex _src1, uint8_t _imm8, RegIndex _dest,
+ bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ false, false, false, false, %(op_class)s),
+ src1(_src1), imm8(_imm8), dest(_dest),
+ setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
+ {
+ buildMe();
+ }
+
+ inline %(class_name)sImm::%(class_name)sImm(
+ ExtMachInst machInst, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ RegIndex _src1, uint8_t _imm8, RegIndex _dest,
+ bool _setStatus, uint8_t _dataSize, uint8_t _ext) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ isMicro, isDelayed, isFirst, isLast, %(op_class)s),
+ src1(_src1), imm8(_imm8), dest(_dest),
+ setStatus(_setStatus), dataSize(_dataSize), ext(_ext)
+ {
+ buildMe();
+ }
+}};
+
+let {{
+ class RegOp(object):
+ def __init__(self, dest, src1, src2):
+ self.dest = dest
+ self.src1 = src1
+ self.src2 = src2
+ self.setStatus = False
+ self.dataSize = 1
+ self.ext = 0
+
+ def getAllocator(self, *microFlags):
+ allocator = '''new %(class_name)s(machInst, %(mnemonic)s,
+ %(flags)s %(src1)s, %(src2)s, %(dest)s,
+ %(setStatus)s, %(dataSize)s, %(ext)s)''' % {
+ "class_name" : self.className,
+ "mnemonic" : self.mnemonic,
+ "flags" : self.microFlagsText(microFlags),
+ "src1" : self.src1, "src2" : self.src2,
+ "dest" : self.dest,
+ "setStatus" : self.setStatus,
+ "dataSize" : self.dataSize,
+ "ext" : self.ext}
+
+ class RegOpImm(object):
+ def __init__(self, dest, src1, imm):
+ self.dest = dest
+ self.src1 = src1
+ self.imm = imm
+ self.setStatus = False
+ self.dataSize = 1
+ self.ext = 0
+
+ def getAllocator(self, *microFlags):
+ allocator = '''new %(class_name)s(machInst, %(mnemonic)s,
+ %(flags)s %(src1)s, %(imm8)s, %(dest)s,
+ %(setStatus)s, %(dataSize)s, %(ext)s)''' % {
+ "class_name" : self.className,
+ "mnemonic" : self.mnemonic,
+ "flags" : self.microFlagsText(microFlags),
+ "src1" : self.src1, "imm8" : self.imm8,
+ "dest" : self.dest,
+ "setStatus" : self.setStatus,
+ "dataSize" : self.dataSize,
+ "ext" : self.ext}
+}};
+
+let {{
+
+ # Make these empty strings so that concatenating onto
+ # them will always work.
+ header_output = ""
+ decoder_output = ""
+ exec_output = ""
+
+ def defineMicroIntOp(mnemonic, code):
+ global header_output
+ global decoder_output
+ global exec_output
+ Name = mnemonic
+ name = mnemonic.lower()
+
+ # Find op2 in each of the instruction definitions. Create two versions
+ # of the code, one with an integer operand, and one with an immediate
+ # operand.
+ matcher = re.compile("op2(?P<typeQual>\\.\\w+)?")
+ regCode = matcher.sub("SrcReg2", code)
+ immCode = matcher.sub("imm8", code)
+
+ # Build up the all register version of this micro op
+ iop = InstObjParams(name, Name, 'X86MicroOpBase', {"code" : regCode})
+ header_output += MicroRegOpDeclare.subst(iop)
+ decoder_output += MicroRegOpConstructor.subst(iop)
+ exec_output += MicroRegOpExecute.subst(iop)
+
+ class RegOpChild(RegOp):
+ def __init__(self, dest, src1, src2):
+ super(RegOpChild, self).__init__(self, dest, src1, src2)
+ self.mnemonic = name
+
+ microopClasses[name] = RegOpChild
+
+ # Build up the immediate version of this micro op
+ iop = InstObjParams(name + "i", Name,
+ 'X86MicroOpBase', {"code" : immCode})
+ header_output += MicroRegOpImmDeclare.subst(iop)
+ decoder_output += MicroRegOpImmConstructor.subst(iop)
+ exec_output += MicroRegOpImmExecute.subst(iop)
+
+ class RegOpImmChild(RegOpImm):
+ def __init__(self, dest, src1, imm):
+ super(RegOpImmChild, self).__init__(self, dest, src1, imm)
+ self.mnemonic = name + "i"
+
+ microopClasses[name + "i"] = RegOpChild
+
+ defineMicroIntOp('Add', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') #Needs to set OF,CF,SF
+ defineMicroIntOp('Or', 'DestReg = merge(DestReg, SrcReg1 | op2, dataSize)')
+ defineMicroIntOp('Adc', 'DestReg = merge(DestReg, SrcReg1 + op2, dataSize)') #Needs to add in CF, set OF,CF,SF
+ defineMicroIntOp('Sbb', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)') #Needs to subtract CF, set OF,CF,SF
+ defineMicroIntOp('And', 'DestReg = merge(DestReg, SrcReg1 & op2, dataSize)')
+ defineMicroIntOp('Sub', 'DestReg = merge(DestReg, SrcReg1 - op2, dataSize)') #Needs to set OF,CF,SF
+ defineMicroIntOp('Xor', 'DestReg = merge(DestReg, SrcReg1 ^ op2, dataSize)')
+ defineMicroIntOp('Cmp', 'DestReg = merge(DestReg, DestReg - op2, dataSize)') #Needs to set OF,CF,SF and not DestReg
+ defineMicroIntOp('Mov', 'DestReg = merge(SrcReg1, op2, dataSize)')
+
+}};
diff --git a/src/arch/x86/isa/microops/specop.isa b/src/arch/x86/isa/microops/specop.isa
new file mode 100644
index 000000000..a3ca7d91c
--- /dev/null
+++ b/src/arch/x86/isa/microops/specop.isa
@@ -0,0 +1,125 @@
+// Copyright (c) 2007 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
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Fault Microop
+//
+//////////////////////////////////////////////////////////////////////////
+
+def template MicroFaultExecute {{
+ Fault %(class_name)s ::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ //Return the fault we were constructed with
+ return fault;
+ }
+}};
+
+def template MicroFaultDeclare {{
+ class %(class_name)s : public X86MicroOpBase
+ {
+ protected:
+ Fault fault;
+ void buildMe();
+
+ public:
+ %(class_name)s(ExtMachInst _machInst,
+ const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ Fault _fault);
+
+ %(class_name)s(ExtMachInst _machInst,
+ const char * instMnem,
+ Fault _fault);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+def template MicroFaultConstructor {{
+
+ inline void %(class_name)s::buildMe()
+ {
+ %(constructor)s;
+ }
+
+ inline %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem, Fault _fault) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ false, false, false, false, %(op_class)s), fault(_fault)
+ {
+ buildMe();
+ }
+
+ inline %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ Fault _fault) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ isMicro, isDelayed, isFirst, isLast, %(op_class)s),
+ fault(_fault)
+ {
+ buildMe();
+ }
+}};
+
+let {{
+ # This microop takes in a single parameter, a fault to return.
+ iop = InstObjParams("fault", "GenFault", 'X86MicroOpBase', {"code" : ""})
+ header_output += MicroFaultDeclare.subst(iop)
+ decoder_output += MicroFaultConstructor.subst(iop)
+ exec_output += MicroFaultExecute.subst(iop)
+}};
diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa
index af469ab3d..1564c23e9 100644
--- a/src/arch/x86/isa/operands.isa
+++ b/src/arch/x86/isa/operands.isa
@@ -96,6 +96,9 @@ def operand_types {{
}};
def operands {{
+ 'DestReg': ('IntReg', 'uqw', 'dest', 'IsInteger', 1),
+ 'SrcReg1': ('IntReg', 'uqw', 'src1', 'IsInteger', 2),
+ 'SrcReg2': ('IntReg', 'uqw', 'src2', 'IsInteger', 3),
'IntRegOp0': ('IntReg', 'udw', 'param0', 'IsInteger', 1),
'IntRegOp1': ('IntReg', 'udw', 'param1', 'IsInteger', 2),
'IntRegOp2': ('IntReg', 'udw', 'param2', 'IsInteger', 2),