summaryrefslogtreecommitdiff
path: root/src/arch/x86/isa/microops
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-09-19 18:27:55 -0700
committerGabe Black <gblack@eecs.umich.edu>2007-09-19 18:27:55 -0700
commita75b6f51060ceaa52014aa4dd6aadc6ca83365f8 (patch)
treea8da313b6cf771f07ab0e1b795ea6be3137d4e29 /src/arch/x86/isa/microops
parentf3f3747431e001dc6c80da5b6489516b610c22d6 (diff)
downloadgem5-a75b6f51060ceaa52014aa4dd6aadc6ca83365f8.tar.xz
X86: Move the fp microops to their own file with their own base classes in C++ and python.
--HG-- extra : convert_revision : 9cd223f2005adb36fea2bb56fa39793a58ec958c
Diffstat (limited to 'src/arch/x86/isa/microops')
-rw-r--r--src/arch/x86/isa/microops/base.isa8
-rw-r--r--src/arch/x86/isa/microops/fpop.isa341
-rw-r--r--src/arch/x86/isa/microops/microops.isa3
-rw-r--r--src/arch/x86/isa/microops/regop.isa65
4 files changed, 345 insertions, 72 deletions
diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa
index 9722f182e..75658a26c 100644
--- a/src/arch/x86/isa/microops/base.isa
+++ b/src/arch/x86/isa/microops/base.isa
@@ -92,11 +92,3 @@ let {{
return 'new %s(machInst, %s)' % \
(self.className, mnemonic, self.microFlagsText(microFlags))
}};
-
-//////////////////////////////////////////////////////////////////////////
-//
-// FpOp Microop templates
-//
-//////////////////////////////////////////////////////////////////////////
-
-//TODO Actually write an fp microop base class.
diff --git a/src/arch/x86/isa/microops/fpop.isa b/src/arch/x86/isa/microops/fpop.isa
new file mode 100644
index 000000000..e9a7cb84f
--- /dev/null
+++ b/src/arch/x86/isa/microops/fpop.isa
@@ -0,0 +1,341 @@
+// 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
+
+//////////////////////////////////////////////////////////////////////////
+//
+// FpOp Microop templates
+//
+//////////////////////////////////////////////////////////////////////////
+
+def template MicroFpOpExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ DPRINTF(X86, "The data size is %d\n", dataSize);
+ %(op_decl)s;
+ %(op_rd)s;
+
+ if(%(cond_check)s)
+ {
+ %(code)s;
+ %(flag_code)s;
+ %(top_code)s;
+ }
+ else
+ {
+ %(else_code)s;
+ }
+
+ //Write the resulting state to the execution context
+ if(fault == NoFault)
+ {
+ %(op_wb)s;
+ }
+ return fault;
+ }
+}};
+
+def template MicroFpOpDeclare {{
+ class %(class_name)s : public %(base_class)s
+ {
+ protected:
+ 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,
+ uint8_t _dataSize, int8_t _spm);
+
+ %(class_name)s(ExtMachInst _machInst,
+ const char * instMnem,
+ RegIndex _src1, RegIndex _src2, RegIndex _dest,
+ uint8_t _dataSize, int8_t _spm);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+def template MicroFpOpConstructor {{
+
+ 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,
+ uint8_t _dataSize, int8_t _spm) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ false, false, false, false,
+ _src1, _src2, _dest, _dataSize, _spm,
+ %(op_class)s)
+ {
+ 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,
+ uint8_t _dataSize, int8_t _spm) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ isMicro, isDelayed, isFirst, isLast,
+ _src1, _src2, _dest, _dataSize, _spm,
+ %(op_class)s)
+ {
+ buildMe();
+ }
+}};
+
+let {{
+ # Make these empty strings so that concatenating onto
+ # them will always work.
+ header_output = ""
+ decoder_output = ""
+ exec_output = ""
+
+ class FpOpMeta(type):
+ def buildCppClasses(self, name, Name, suffix, \
+ code, flag_code, cond_check, else_code):
+
+ # Globals to stick the output in
+ global header_output
+ global decoder_output
+ global exec_output
+
+ # Stick all the code together so it can be searched at once
+ allCode = "|".join((code, flag_code, cond_check, else_code))
+
+ # If there's something optional to do with flags, generate
+ # a version without it and fix up this version to use it.
+ if flag_code is not "" or cond_check is not "true":
+ self.buildCppClasses(name, Name, suffix,
+ code, "", "true", else_code)
+ suffix = "Flags" + suffix
+
+ base = "X86ISA::FpOp"
+
+ # Get everything ready for the substitution
+ iop_top = InstObjParams(name, Name + suffix + "Top", base,
+ {"code" : code,
+ "flag_code" : flag_code,
+ "cond_check" : cond_check,
+ "else_code" : else_code,
+ "top_code" : "TOP = (TOP + spm + 8) % 8;"})
+ iop = InstObjParams(name, Name + suffix, base,
+ {"code" : code,
+ "flag_code" : flag_code,
+ "cond_check" : cond_check,
+ "else_code" : else_code,
+ "top_code" : ";"})
+
+ # Generate the actual code (finally!)
+ header_output += MicroFpOpDeclare.subst(iop_top)
+ decoder_output += MicroFpOpConstructor.subst(iop_top)
+ exec_output += MicroFpOpExecute.subst(iop_top)
+ header_output += MicroFpOpDeclare.subst(iop)
+ decoder_output += MicroFpOpConstructor.subst(iop)
+ exec_output += MicroFpOpExecute.subst(iop)
+
+
+ def __new__(mcls, Name, bases, dict):
+ abstract = False
+ name = Name.lower()
+ if "abstract" in dict:
+ abstract = dict['abstract']
+ del dict['abstract']
+
+ cls = super(FpOpMeta, mcls).__new__(mcls, Name, bases, dict)
+ if not abstract:
+ cls.className = Name
+ cls.mnemonic = name
+ code = cls.code
+ flag_code = cls.flag_code
+ cond_check = cls.cond_check
+ else_code = cls.else_code
+
+ # Set up the C++ classes
+ mcls.buildCppClasses(cls, name, Name, "",
+ code, flag_code, cond_check, else_code)
+
+ # Hook into the microassembler dict
+ global microopClasses
+ microopClasses[name] = cls
+
+ return cls
+
+
+ class FpOp(X86Microop):
+ __metaclass__ = FpOpMeta
+ # This class itself doesn't act as a microop
+ abstract = True
+
+ # Default template parameter values
+ flag_code = ""
+ cond_check = "true"
+ else_code = ";"
+
+ def __init__(self, dest, src1, src2, spm=0, \
+ SetStatus=False, dataSize="env.dataSize"):
+ self.dest = dest
+ self.src1 = src1
+ self.src2 = src2
+ self.spm = spm
+ self.dataSize = dataSize
+ if SetStatus:
+ self.className += "Flags"
+ if spm:
+ self.className += "Top"
+
+ def getAllocator(self, *microFlags):
+ return '''new %(class_name)s(machInst, mnemonic
+ %(flags)s, %(src1)s, %(src2)s, %(dest)s,
+ %(dataSize)s, %(spm)d)''' % {
+ "class_name" : self.className,
+ "flags" : self.microFlagsText(microFlags),
+ "src1" : self.src1, "src2" : self.src2,
+ "dest" : self.dest,
+ "dataSize" : self.dataSize,
+ "spm" : self.spm}
+
+ class Movfp(FpOp):
+ def __init__(self, dest, src1, flags=0, spm=0, \
+ SetStatus=False, dataSize="env.dataSize"):
+ super(Movfp, self).__init__(dest, src1, flags, \
+ spm, SetStatus, dataSize)
+ code = 'FpDestReg.uqw = FpSrcReg2.uqw;'
+ else_code = 'FpDestReg.uqw = FpDestReg.uqw;'
+ cond_check = "checkCondition(ccFlagBits, src2)"
+
+ class Xorfp(FpOp):
+ code = 'FpDestReg.uqw = FpSrcReg1.uqw ^ FpSrcReg2.uqw;'
+
+ class Sqrtfp(FpOp):
+ code = 'FpDestReg = sqrt(FpSrcReg2);'
+
+ # Conversion microops
+ class ConvOp(FpOp):
+ abstract = True
+ def __init__(self, dest, src1):
+ super(ConvOp, self).__init__(dest, src1, "(int)FLOATREG_MICROFP0")
+
+ # These probably shouldn't look at the ExtMachInst directly to figure
+ # out what size to use and should instead delegate that to the macroop's
+ # constructor. That would be more efficient, and it would make the
+ # microops a little more modular.
+ class cvtf_i2d(ConvOp):
+ code = '''
+ X86IntReg intReg = SSrcReg1;
+ if (REX_W)
+ FpDestReg = intReg.SR;
+ else
+ FpDestReg = intReg.SE;
+ '''
+
+ class cvtf_i2d_hi(ConvOp):
+ code = 'FpDestReg = bits(SSrcReg1, 63, 32);'
+
+ class cvtf_d2i(ConvOp):
+ code = '''
+ int64_t intSrcReg1 = static_cast<int64_t>(FpSrcReg1);
+ if (REX_W)
+ SDestReg = intSrcReg1;
+ else
+ SDestReg = merge(SDestReg, intSrcReg1, 4);
+ '''
+
+ # These need to consider size at some point. They'll always use doubles
+ # for the moment.
+ class addfp(FpOp):
+ code = 'FpDestReg = FpSrcReg1 + FpSrcReg2;'
+
+ class mulfp(FpOp):
+ code = 'FpDestReg = FpSrcReg1 * FpSrcReg2;'
+
+ class divfp(FpOp):
+ code = 'FpDestReg = FpSrcReg1 / FpSrcReg2;'
+
+ class subfp(FpOp):
+ code = 'FpDestReg = FpSrcReg1 - FpSrcReg2;'
+
+ class Compfp(FpOp):
+ def __init__(self, src1, src2, spm=0, setStatus=False, \
+ dataSize="env.dataSize"):
+ super(Compfp, self).__init__("(int)FLOATREG_MICROFP0", \
+ src1, src2, spm, setStatus, dataSize)
+ # This class sets the condition codes in rflags according to the
+ # rules for comparing floating point.
+ code = '''
+ // ZF PF CF
+ // Unordered 1 1 1
+ // Greater than 0 0 0
+ // Less than 0 0 1
+ // Equal 1 0 0
+ // OF = SF = AF = 0
+ ccFlagBits = ccFlagBits & ~(OFBit | SFBit | AFBit |
+ ZFBit | PFBit | CFBit);
+ if (isnan(FpSrcReg1) || isnan(FpSrcReg2))
+ ccFlagBits = ccFlagBits | (ZFBit | PFBit | CFBit);
+ else if(FpSrcReg1 < FpSrcReg2)
+ ccFlagBits = ccFlagBits | CFBit;
+ else if(FpSrcReg1 == FpSrcReg2)
+ ccFlagBits = ccFlagBits | ZFBit;
+ '''
+}};
diff --git a/src/arch/x86/isa/microops/microops.isa b/src/arch/x86/isa/microops/microops.isa
index 50c9ac498..53f34d3f2 100644
--- a/src/arch/x86/isa/microops/microops.isa
+++ b/src/arch/x86/isa/microops/microops.isa
@@ -56,6 +56,9 @@
//Common microop stuff
##include "base.isa"
+//Floating point definitions
+##include "fpop.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
index 98743e603..40a441b1e 100644
--- a/src/arch/x86/isa/microops/regop.isa
+++ b/src/arch/x86/isa/microops/regop.isa
@@ -458,7 +458,7 @@ let {{
class CondRegOp(RegOp):
abstract = True
- cond_check = "checkCondition(ccFlagBits)"
+ cond_check = "checkCondition(ccFlagBits, ext)"
class RdRegOp(RegOp):
abstract = True
@@ -873,67 +873,4 @@ let {{
class Zext(RegOp):
code = 'DestReg = bits(psrc1, imm8-1, 0);'
-
- class Compfp(WrRegOp):
- # This class sets the condition codes in rflags according to the
- # rules for comparing floating point.
- code = '''
- // ZF PF CF
- // Unordered 1 1 1
- // Greater than 0 0 0
- // Less than 0 0 1
- // Equal 1 0 0
- // OF = SF = AF = 0
- ccFlagBits = ccFlagBits & ~(OFBit | SFBit | AFBit |
- ZFBit | PFBit | CFBit);
- if (isnan(FpSrcReg1) || isnan(FpSrcReg2))
- ccFlagBits = ccFlagBits | (ZFBit | PFBit | CFBit);
- else if(FpSrcReg1 < FpSrcReg2)
- ccFlagBits = ccFlagBits | CFBit;
- else if(FpSrcReg1 == FpSrcReg2)
- ccFlagBits = ccFlagBits | ZFBit;
- '''
-
- class Xorfp(RegOp):
- code = 'FpDestReg.uqw = FpSrcReg1.uqw ^ FpSrcReg2.uqw;'
-
- class Sqrtfp(RegOp):
- code = 'FpDestReg = sqrt(FpSrcReg2);'
-
- class Movfp(CondRegOp):
- code = 'FpDestReg.uqw = FpSrcReg2.uqw;'
- else_code = 'FpDestReg.uqw = FpDestReg.uqw;'
-
- # Conversion microops
- class ConvOp(RegOp):
- abstract = True
- def __init__(self, dest, src1):
- super(ConvOp, self).__init__(dest, src1, "NUM_INTREGS")
-
- #FIXME This needs to always use 32 bits unless REX.W is present
- class cvtf_i2d(ConvOp):
- code = 'FpDestReg = spsrc1;'
-
- class cvtf_i2d_hi(ConvOp):
- code = 'FpDestReg = bits(SrcReg1, 63, 32);'
-
- class cvtf_d2i(ConvOp):
- code = '''
- int64_t intSrcReg1 = static_cast<int64_t>(FpSrcReg1);
- DestReg = merge(DestReg, intSrcReg1, dataSize);
- '''
-
- # These need to consider size at some point. They'll always use doubles
- # for the moment.
- class addfp(RegOp):
- code = 'FpDestReg = FpSrcReg1 + FpSrcReg2;'
-
- class mulfp(RegOp):
- code = 'FpDestReg = FpSrcReg1 * FpSrcReg2;'
-
- class divfp(RegOp):
- code = 'FpDestReg = FpSrcReg1 / FpSrcReg2;'
-
- class subfp(RegOp):
- code = 'FpDestReg = FpSrcReg1 - FpSrcReg2;'
}};