diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2007-09-19 18:27:55 -0700 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2007-09-19 18:27:55 -0700 |
commit | a75b6f51060ceaa52014aa4dd6aadc6ca83365f8 (patch) | |
tree | a8da313b6cf771f07ab0e1b795ea6be3137d4e29 /src/arch/x86/isa/microops | |
parent | f3f3747431e001dc6c80da5b6489516b610c22d6 (diff) | |
download | gem5-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.isa | 8 | ||||
-rw-r--r-- | src/arch/x86/isa/microops/fpop.isa | 341 | ||||
-rw-r--r-- | src/arch/x86/isa/microops/microops.isa | 3 | ||||
-rw-r--r-- | src/arch/x86/isa/microops/regop.isa | 65 |
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;' }}; |