fpop.isa revision 9582:0632d2d1575c
16657Snate@binkert.org// Copyright (c) 2007 The Hewlett-Packard Development Company 26657Snate@binkert.org// Copyright (c) 2012-2013 Mark D. Hill and David A. Wood 36657Snate@binkert.org// All rights reserved. 46657Snate@binkert.org// 56657Snate@binkert.org// The license below extends only to copyright in the software and shall 66657Snate@binkert.org// not be construed as granting a license to any other intellectual 76657Snate@binkert.org// property including but not limited to intellectual property relating 86657Snate@binkert.org// to a hardware implementation of the functionality of the software 96657Snate@binkert.org// licensed hereunder. You may use the software subject to the license 106657Snate@binkert.org// terms below provided that you ensure that this notice is replicated 116657Snate@binkert.org// unmodified and in its entirety in all distributions of the software, 126657Snate@binkert.org// modified or unmodified, in source code or in binary form. 136657Snate@binkert.org// 146657Snate@binkert.org// Redistribution and use in source and binary forms, with or without 156657Snate@binkert.org// modification, are permitted provided that the following conditions are 166657Snate@binkert.org// met: redistributions of source code must retain the above copyright 176657Snate@binkert.org// notice, this list of conditions and the following disclaimer; 186657Snate@binkert.org// redistributions in binary form must reproduce the above copyright 196657Snate@binkert.org// notice, this list of conditions and the following disclaimer in the 206657Snate@binkert.org// documentation and/or other materials provided with the distribution; 216657Snate@binkert.org// neither the name of the copyright holders nor the names of its 226657Snate@binkert.org// contributors may be used to endorse or promote products derived from 236657Snate@binkert.org// this software without specific prior written permission. 246657Snate@binkert.org// 256657Snate@binkert.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 266657Snate@binkert.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 276657Snate@binkert.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 286999Snate@binkert.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 296657Snate@binkert.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 306657Snate@binkert.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 316657Snate@binkert.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 326657Snate@binkert.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 338189SLisa.Hsu@amd.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 346657Snate@binkert.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 359499Snilay@cs.wisc.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 369499Snilay@cs.wisc.edu// 379364Snilay@cs.wisc.edu// Authors: Gabe Black 387055Snate@binkert.org// Nilay Vaish 396882SBrad.Beckmann@amd.com 406882SBrad.Beckmann@amd.com////////////////////////////////////////////////////////////////////////// 418191SLisa.Hsu@amd.com// 426882SBrad.Beckmann@amd.com// FpOp Microop templates 436882SBrad.Beckmann@amd.com// 449102SNuwan.Jayasena@amd.com////////////////////////////////////////////////////////////////////////// 459366Snilay@cs.wisc.edu 469499Snilay@cs.wisc.edudef template MicroFpOpExecute {{ 479499Snilay@cs.wisc.edu Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, 489499Snilay@cs.wisc.edu Trace::InstRecord *traceData) const 496882SBrad.Beckmann@amd.com { 506657Snate@binkert.org Fault fault = NoFault; 516657Snate@binkert.org 526657Snate@binkert.org DPRINTF(X86, "The data size is %d\n", dataSize); 536657Snate@binkert.org %(op_decl)s; 546657Snate@binkert.org %(op_rd)s; 559366Snilay@cs.wisc.edu 567839Snilay@cs.wisc.edu if(%(cond_check)s) 576657Snate@binkert.org { 586882SBrad.Beckmann@amd.com %(code)s; 596882SBrad.Beckmann@amd.com %(flag_code)s; 606882SBrad.Beckmann@amd.com %(top_code)s; 616882SBrad.Beckmann@amd.com } 626882SBrad.Beckmann@amd.com else 636882SBrad.Beckmann@amd.com { 646657Snate@binkert.org %(else_code)s; 659366Snilay@cs.wisc.edu } 669366Snilay@cs.wisc.edu 676657Snate@binkert.org //Write the resulting state to the execution context 686657Snate@binkert.org if(fault == NoFault) 696657Snate@binkert.org { 706657Snate@binkert.org %(op_wb)s; 719104Shestness@cs.utexas.edu } 726657Snate@binkert.org return fault; 736657Snate@binkert.org } 746657Snate@binkert.org}}; 756657Snate@binkert.org 767839Snilay@cs.wisc.edudef template MicroFpOpDeclare {{ 777839Snilay@cs.wisc.edu class %(class_name)s : public %(base_class)s 786657Snate@binkert.org { 796657Snate@binkert.org public: 806657Snate@binkert.org %(class_name)s(ExtMachInst _machInst, 816657Snate@binkert.org const char * instMnem, uint64_t setFlags, 826657Snate@binkert.org InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest, 836657Snate@binkert.org uint8_t _dataSize, int8_t _spm); 846657Snate@binkert.org 856657Snate@binkert.org %(BasicExecDeclare)s 866657Snate@binkert.org }; 876657Snate@binkert.org}}; 886657Snate@binkert.org 896657Snate@binkert.orgdef template MicroFpOpConstructor {{ 906657Snate@binkert.org inline %(class_name)s::%(class_name)s( 916657Snate@binkert.org ExtMachInst machInst, const char * instMnem, uint64_t setFlags, 926657Snate@binkert.org InstRegIndex _src1, InstRegIndex _src2, InstRegIndex _dest, 936657Snate@binkert.org uint8_t _dataSize, int8_t _spm) : 946657Snate@binkert.org %(base_class)s(machInst, "%(mnemonic)s", instMnem, setFlags, 956657Snate@binkert.org _src1, _src2, _dest, _dataSize, _spm, 966779SBrad.Beckmann@amd.com %(op_class)s) 976657Snate@binkert.org { 986657Snate@binkert.org %(constructor)s; 996657Snate@binkert.org } 1006657Snate@binkert.org}}; 1016657Snate@binkert.org 1026657Snate@binkert.orglet {{ 1036657Snate@binkert.org # Make these empty strings so that concatenating onto 1046657Snate@binkert.org # them will always work. 1056657Snate@binkert.org header_output = "" 1069104Shestness@cs.utexas.edu decoder_output = "" 1079104Shestness@cs.utexas.edu exec_output = "" 1089104Shestness@cs.utexas.edu 1099104Shestness@cs.utexas.edu class FpOpMeta(type): 1106657Snate@binkert.org def buildCppClasses(self, name, Name, suffix, \ 1116657Snate@binkert.org code, flag_code, cond_check, else_code): 1126657Snate@binkert.org 1136657Snate@binkert.org # Globals to stick the output in 1146657Snate@binkert.org global header_output 1156657Snate@binkert.org global decoder_output 1166657Snate@binkert.org global exec_output 1176657Snate@binkert.org 1186657Snate@binkert.org # Stick all the code together so it can be searched at once 1196657Snate@binkert.org allCode = "|".join((code, flag_code, cond_check, else_code)) 1206657Snate@binkert.org 1216657Snate@binkert.org # If there's something optional to do with flags, generate 1226657Snate@binkert.org # a version without it and fix up this version to use it. 1236657Snate@binkert.org if flag_code is not "" or cond_check is not "true": 1246657Snate@binkert.org self.buildCppClasses(name, Name, suffix, 1257839Snilay@cs.wisc.edu code, "", "true", else_code) 1267839Snilay@cs.wisc.edu suffix = "Flags" + suffix 1277839Snilay@cs.wisc.edu 1287839Snilay@cs.wisc.edu base = "X86ISA::FpOp" 1297839Snilay@cs.wisc.edu 1307839Snilay@cs.wisc.edu # Get everything ready for the substitution 1317839Snilay@cs.wisc.edu iop_top = InstObjParams(name, Name + suffix + "Top", base, 1327839Snilay@cs.wisc.edu {"code" : code, 1337839Snilay@cs.wisc.edu "flag_code" : flag_code, 1347839Snilay@cs.wisc.edu "cond_check" : cond_check, 1357839Snilay@cs.wisc.edu "else_code" : else_code, 1367839Snilay@cs.wisc.edu "top_code" : "TOP = (TOP + spm + 8) % 8;"}) 1377839Snilay@cs.wisc.edu iop = InstObjParams(name, Name + suffix, base, 1387839Snilay@cs.wisc.edu {"code" : code, 1397839Snilay@cs.wisc.edu "flag_code" : flag_code, 1406657Snate@binkert.org "cond_check" : cond_check, 1416657Snate@binkert.org "else_code" : else_code, 1426657Snate@binkert.org "top_code" : ";"}) 1436657Snate@binkert.org 1446657Snate@binkert.org # Generate the actual code (finally!) 1456657Snate@binkert.org header_output += MicroFpOpDeclare.subst(iop_top) 1466657Snate@binkert.org decoder_output += MicroFpOpConstructor.subst(iop_top) 1476657Snate@binkert.org exec_output += MicroFpOpExecute.subst(iop_top) 1486657Snate@binkert.org header_output += MicroFpOpDeclare.subst(iop) 1496657Snate@binkert.org decoder_output += MicroFpOpConstructor.subst(iop) 1506657Snate@binkert.org exec_output += MicroFpOpExecute.subst(iop) 1516657Snate@binkert.org 1526657Snate@binkert.org 1536657Snate@binkert.org def __new__(mcls, Name, bases, dict): 1546657Snate@binkert.org abstract = False 1556657Snate@binkert.org name = Name.lower() 1566657Snate@binkert.org if "abstract" in dict: 1576657Snate@binkert.org abstract = dict['abstract'] 1586657Snate@binkert.org del dict['abstract'] 1596657Snate@binkert.org 1606657Snate@binkert.org cls = super(FpOpMeta, mcls).__new__(mcls, Name, bases, dict) 1616657Snate@binkert.org if not abstract: 1626657Snate@binkert.org cls.className = Name 1636657Snate@binkert.org cls.mnemonic = name 1646657Snate@binkert.org code = cls.code 1656657Snate@binkert.org flag_code = cls.flag_code 1666657Snate@binkert.org cond_check = cls.cond_check 1676657Snate@binkert.org else_code = cls.else_code 1686657Snate@binkert.org 1696657Snate@binkert.org # Set up the C++ classes 1709219Spower.jg@gmail.com mcls.buildCppClasses(cls, name, Name, "", 1716877Ssteve.reinhardt@amd.com code, flag_code, cond_check, else_code) 1726657Snate@binkert.org 1739219Spower.jg@gmail.com # Hook into the microassembler dict 1746657Snate@binkert.org global microopClasses 1759219Spower.jg@gmail.com microopClasses[name] = cls 1766657Snate@binkert.org 1776657Snate@binkert.org return cls 1787542SBrad.Beckmann@amd.com 1797542SBrad.Beckmann@amd.com class FpUnaryOp(X86Microop): 1806657Snate@binkert.org __metaclass__ = FpOpMeta 1816877Ssteve.reinhardt@amd.com # This class itself doesn't act as a microop 1826999Snate@binkert.org abstract = True 1836877Ssteve.reinhardt@amd.com 1846877Ssteve.reinhardt@amd.com # Default template parameter values 1856877Ssteve.reinhardt@amd.com flag_code = "" 1866877Ssteve.reinhardt@amd.com cond_check = "true" 1876877Ssteve.reinhardt@amd.com else_code = ";" 1886877Ssteve.reinhardt@amd.com 1896877Ssteve.reinhardt@amd.com def __init__(self, dest, src1, spm=0, \ 1906877Ssteve.reinhardt@amd.com SetStatus=False, dataSize="env.dataSize"): 1916877Ssteve.reinhardt@amd.com self.dest = dest 1926877Ssteve.reinhardt@amd.com self.src1 = src1 1939338SAndreas.Sandberg@arm.com self.src2 = "InstRegIndex(0)" 1946877Ssteve.reinhardt@amd.com self.spm = spm 1956877Ssteve.reinhardt@amd.com self.dataSize = dataSize 1966877Ssteve.reinhardt@amd.com if SetStatus: 1976877Ssteve.reinhardt@amd.com self.className += "Flags" 1986877Ssteve.reinhardt@amd.com if spm: 1996877Ssteve.reinhardt@amd.com self.className += "Top" 2006882SBrad.Beckmann@amd.com 2016882SBrad.Beckmann@amd.com def getAllocator(self, microFlags): 2026882SBrad.Beckmann@amd.com return '''new %(class_name)s(machInst, macrocodeBlock, 2036882SBrad.Beckmann@amd.com %(flags)s, %(src1)s, %(src2)s, %(dest)s, 2046882SBrad.Beckmann@amd.com %(dataSize)s, %(spm)d)''' % { 2056882SBrad.Beckmann@amd.com "class_name" : self.className, 2066882SBrad.Beckmann@amd.com "flags" : self.microFlagsText(microFlags), 2076877Ssteve.reinhardt@amd.com "src1" : self.src1, "src2" : self.src2, 2086877Ssteve.reinhardt@amd.com "dest" : self.dest, 2096877Ssteve.reinhardt@amd.com "dataSize" : self.dataSize, 2106877Ssteve.reinhardt@amd.com "spm" : self.spm} 2116657Snate@binkert.org 2126657Snate@binkert.org class FpBinaryOp(X86Microop): 2136999Snate@binkert.org __metaclass__ = FpOpMeta 2146657Snate@binkert.org # This class itself doesn't act as a microop 2156657Snate@binkert.org abstract = True 2166657Snate@binkert.org 2176657Snate@binkert.org # Default template parameter values 2187007Snate@binkert.org flag_code = "" 2196657Snate@binkert.org cond_check = "true" 2206657Snate@binkert.org else_code = ";" 2216657Snate@binkert.org 2226657Snate@binkert.org def __init__(self, dest, src1, src2, spm=0, \ 2236657Snate@binkert.org SetStatus=False, dataSize="env.dataSize"): 2247007Snate@binkert.org self.dest = dest 2257007Snate@binkert.org self.src1 = src1 2266657Snate@binkert.org self.src2 = src2 2277002Snate@binkert.org self.spm = spm 2287002Snate@binkert.org self.dataSize = dataSize 2297002Snate@binkert.org if SetStatus: 2307002Snate@binkert.org self.className += "Flags" 2318229Snate@binkert.org if spm: 2328229Snate@binkert.org self.className += "Top" 2336657Snate@binkert.org 2346657Snate@binkert.org def getAllocator(self, microFlags): 2358229Snate@binkert.org return '''new %(class_name)s(machInst, macrocodeBlock, 2368229Snate@binkert.org %(flags)s, %(src1)s, %(src2)s, %(dest)s, 2378229Snate@binkert.org %(dataSize)s, %(spm)d)''' % { 2388229Snate@binkert.org "class_name" : self.className, 2396657Snate@binkert.org "flags" : self.microFlagsText(microFlags), 2406657Snate@binkert.org "src1" : self.src1, "src2" : self.src2, 2416657Snate@binkert.org "dest" : self.dest, 2429595Snilay@cs.wisc.edu "dataSize" : self.dataSize, 2436657Snate@binkert.org "spm" : self.spm} 2446793SBrad.Beckmann@amd.com 2456657Snate@binkert.org class Movfp(FpUnaryOp): 2469595Snilay@cs.wisc.edu code = 'FpDestReg_uqw = FpSrcReg1_uqw;' 2479595Snilay@cs.wisc.edu else_code = 'FpDestReg_uqw = FpDestReg_uqw;' 2486657Snate@binkert.org cond_check = "checkCondition(ccFlagBits | cfofBits | dfBit | \ 2496657Snate@binkert.org ecfBit | ezfBit, src2)" 2506657Snate@binkert.org 2516657Snate@binkert.org class Xorfp(FpBinaryOp): 2527002Snate@binkert.org code = 'FpDestReg_uqw = FpSrcReg1_uqw ^ FpSrcReg2_uqw;' 2536657Snate@binkert.org 2547007Snate@binkert.org class Sqrtfp(FpBinaryOp): 2557007Snate@binkert.org code = 'FpDestReg = sqrt(FpSrcReg2);' 2569271Snilay@cs.wisc.edu 2576877Ssteve.reinhardt@amd.com class Cosfp(FpUnaryOp): 2586877Ssteve.reinhardt@amd.com code = 'FpDestReg = cos(FpSrcReg1);' 2596657Snate@binkert.org 2606877Ssteve.reinhardt@amd.com class Sinfp(FpUnaryOp): 2616657Snate@binkert.org code = 'FpDestReg = sin(FpSrcReg1);' 2626657Snate@binkert.org 2637002Snate@binkert.org class Tanfp(FpUnaryOp): 2647002Snate@binkert.org code = 'FpDestReg = tan(FpSrcReg1);' 2656881SBrad.Beckmann@amd.com 2667002Snate@binkert.org 2676657Snate@binkert.org # Conversion microops 2687002Snate@binkert.org class ConvOp(FpBinaryOp): 2696902SBrad.Beckmann@amd.com abstract = True 2706863Sdrh5@cs.wisc.edu def __init__(self, dest, src1): 2716863Sdrh5@cs.wisc.edu super(ConvOp, self).__init__(dest, src1, \ 2728683Snilay@cs.wisc.edu "InstRegIndex(FLOATREG_MICROFP0)") 2738683Snilay@cs.wisc.edu 2747007Snate@binkert.org # These probably shouldn't look at the ExtMachInst directly to figure 2759302Snilay@cs.wisc.edu # out what size to use and should instead delegate that to the macroop's 2769302Snilay@cs.wisc.edu # constructor. That would be more efficient, and it would make the 2779302Snilay@cs.wisc.edu # microops a little more modular. 2786657Snate@binkert.org class cvtf_i2d(ConvOp): 2796657Snate@binkert.org code = ''' 2806657Snate@binkert.org X86IntReg intReg = SSrcReg1; 2816657Snate@binkert.org if (REX_W) 2826657Snate@binkert.org FpDestReg = intReg.SR; 2836657Snate@binkert.org else 2846882SBrad.Beckmann@amd.com FpDestReg = intReg.SE; 2856882SBrad.Beckmann@amd.com ''' 2866882SBrad.Beckmann@amd.com 2876882SBrad.Beckmann@amd.com class cvtf_i2d_hi(ConvOp): 2886657Snate@binkert.org code = 'FpDestReg = bits(SSrcReg1, 63, 32);' 2896657Snate@binkert.org 2907007Snate@binkert.org class cvtf_d2i(ConvOp): 2917839Snilay@cs.wisc.edu code = ''' 2927839Snilay@cs.wisc.edu int64_t intSrcReg1 = static_cast<int64_t>(FpSrcReg1); 2937839Snilay@cs.wisc.edu if (REX_W) 2947839Snilay@cs.wisc.edu SDestReg = intSrcReg1; 2957839Snilay@cs.wisc.edu else 2967839Snilay@cs.wisc.edu SDestReg = merge(SDestReg, intSrcReg1, 4); 2977839Snilay@cs.wisc.edu ''' 2987839Snilay@cs.wisc.edu 2997839Snilay@cs.wisc.edu # These need to consider size at some point. They'll always use doubles 3007839Snilay@cs.wisc.edu # for the moment. 3017839Snilay@cs.wisc.edu class addfp(FpBinaryOp): 3027839Snilay@cs.wisc.edu code = 'FpDestReg = FpSrcReg1 + FpSrcReg2;' 3037007Snate@binkert.org 3047007Snate@binkert.org class mulfp(FpBinaryOp): 3057007Snate@binkert.org code = 'FpDestReg = FpSrcReg1 * FpSrcReg2;' 3067007Snate@binkert.org 3077007Snate@binkert.org class divfp(FpBinaryOp): 3087839Snilay@cs.wisc.edu code = 'FpDestReg = FpSrcReg1 / FpSrcReg2;' 3097839Snilay@cs.wisc.edu 3107839Snilay@cs.wisc.edu class subfp(FpBinaryOp): 3117839Snilay@cs.wisc.edu code = 'FpDestReg = FpSrcReg1 - FpSrcReg2;' 3127839Snilay@cs.wisc.edu 3137839Snilay@cs.wisc.edu class Yl2xFp(FpBinaryOp): 3147839Snilay@cs.wisc.edu code = ''' 3157839Snilay@cs.wisc.edu FpDestReg = FpSrcReg2 * (log(FpSrcReg1) / log(2)); 3167839Snilay@cs.wisc.edu ''' 3177839Snilay@cs.wisc.edu 3187839Snilay@cs.wisc.edu class PremFp(FpBinaryOp): 3197839Snilay@cs.wisc.edu code = ''' 3207007Snate@binkert.org FpDestReg = fmod(FpSrcReg1, FpSrcReg2); 3217007Snate@binkert.org DPRINTF(X86, "src1: %lf, src2: %lf, dest: %lf\\n", FpSrcReg1, FpSrcReg2, FpDestReg); 3227542SBrad.Beckmann@amd.com ''' 3237542SBrad.Beckmann@amd.com 3246657Snate@binkert.org class Compfp(FpBinaryOp): 3257007Snate@binkert.org def __init__(self, src1, src2, spm=0, setStatus=False, \ 3266657Snate@binkert.org dataSize="env.dataSize"): 3276657Snate@binkert.org super(Compfp, self).__init__("InstRegIndex(FLOATREG_MICROFP0)", \ 3286657Snate@binkert.org src1, src2, spm, setStatus, dataSize) 3296657Snate@binkert.org # This class sets the condition codes in rflags according to the 3306657Snate@binkert.org # rules for comparing floating point. 3316657Snate@binkert.org code = ''' 3326657Snate@binkert.org // ZF PF CF 3336657Snate@binkert.org // Unordered 1 1 1 3349595Snilay@cs.wisc.edu // Greater than 0 0 0 3359595Snilay@cs.wisc.edu // Less than 0 0 1 3367839Snilay@cs.wisc.edu // Equal 1 0 0 3377839Snilay@cs.wisc.edu // OF = SF = AF = 0 3387839Snilay@cs.wisc.edu ccFlagBits = ccFlagBits & ~(SFBit | AFBit | ZFBit | PFBit); 3397839Snilay@cs.wisc.edu cfofBits = cfofBits & ~(OFBit | CFBit); 3407839Snilay@cs.wisc.edu 3417839Snilay@cs.wisc.edu if (std::isnan(FpSrcReg1) || std::isnan(FpSrcReg2)) { 3427839Snilay@cs.wisc.edu ccFlagBits = ccFlagBits | (ZFBit | PFBit); 3437839Snilay@cs.wisc.edu cfofBits = cfofBits | CFBit; 3447839Snilay@cs.wisc.edu } 3457839Snilay@cs.wisc.edu else if(FpSrcReg1 < FpSrcReg2) 3467839Snilay@cs.wisc.edu cfofBits = cfofBits | CFBit; 3477839Snilay@cs.wisc.edu else if(FpSrcReg1 == FpSrcReg2) 3487839Snilay@cs.wisc.edu ccFlagBits = ccFlagBits | ZFBit; 3497839Snilay@cs.wisc.edu ''' 3507839Snilay@cs.wisc.edu 3517839Snilay@cs.wisc.edu class absfp(FpUnaryOp): 3526657Snate@binkert.org code = 'FpDestReg = fabs(FpSrcReg1);' 3536657Snate@binkert.org flag_code = 'FSW &= (~CC1Bit);' 3546657Snate@binkert.org 3556657Snate@binkert.org class chsfp(FpUnaryOp): 3567839Snilay@cs.wisc.edu code = 'FpDestReg = (-1) * (FpSrcReg1);' 3577839Snilay@cs.wisc.edu flag_code = 'FSW &= (~CC1Bit);' 3587839Snilay@cs.wisc.edu}}; 3597839Snilay@cs.wisc.edu