diff options
Diffstat (limited to 'src/arch/x86/isa/microops/fpop.isa')
-rw-r--r-- | src/arch/x86/isa/microops/fpop.isa | 341 |
1 files changed, 341 insertions, 0 deletions
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; + ''' +}}; |