vfp.hh revision 10037
17375Sgblack@eecs.umich.edu/* 210037SARM gem5 Developers * Copyright (c) 2010-2013 ARM Limited 37375Sgblack@eecs.umich.edu * All rights reserved 47375Sgblack@eecs.umich.edu * 57375Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall 67375Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual 77375Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating 87375Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software 97375Sgblack@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 107375Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 117375Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 127375Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 137375Sgblack@eecs.umich.edu * 147375Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 157375Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 167375Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 177375Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 187375Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 197375Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 207375Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 217375Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 227375Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 237375Sgblack@eecs.umich.edu * this software without specific prior written permission. 247375Sgblack@eecs.umich.edu * 257375Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 267375Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 277375Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 287375Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 297375Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 307375Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 317375Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 327375Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 337375Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 347375Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 357375Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 367375Sgblack@eecs.umich.edu * 377375Sgblack@eecs.umich.edu * Authors: Gabe Black 387375Sgblack@eecs.umich.edu */ 397375Sgblack@eecs.umich.edu 407375Sgblack@eecs.umich.edu#ifndef __ARCH_ARM_INSTS_VFP_HH__ 417375Sgblack@eecs.umich.edu#define __ARCH_ARM_INSTS_VFP_HH__ 427375Sgblack@eecs.umich.edu 438229Snate@binkert.org#include <fenv.h> 448229Snate@binkert.org 458229Snate@binkert.org#include <cmath> 468229Snate@binkert.org 477375Sgblack@eecs.umich.edu#include "arch/arm/insts/misc.hh" 487378Sgblack@eecs.umich.edu#include "arch/arm/miscregs.hh" 497375Sgblack@eecs.umich.edu 507384Sgblack@eecs.umich.edunamespace ArmISA 517384Sgblack@eecs.umich.edu{ 527384Sgblack@eecs.umich.edu 537375Sgblack@eecs.umich.eduenum VfpMicroMode { 547375Sgblack@eecs.umich.edu VfpNotAMicroop, 557375Sgblack@eecs.umich.edu VfpMicroop, 567375Sgblack@eecs.umich.edu VfpFirstMicroop, 577375Sgblack@eecs.umich.edu VfpLastMicroop 587375Sgblack@eecs.umich.edu}; 597375Sgblack@eecs.umich.edu 607375Sgblack@eecs.umich.edutemplate<class T> 617375Sgblack@eecs.umich.edustatic inline void 627375Sgblack@eecs.umich.edusetVfpMicroFlags(VfpMicroMode mode, T &flags) 637375Sgblack@eecs.umich.edu{ 647375Sgblack@eecs.umich.edu switch (mode) { 657375Sgblack@eecs.umich.edu case VfpMicroop: 667375Sgblack@eecs.umich.edu flags[StaticInst::IsMicroop] = true; 677375Sgblack@eecs.umich.edu break; 687375Sgblack@eecs.umich.edu case VfpFirstMicroop: 697375Sgblack@eecs.umich.edu flags[StaticInst::IsMicroop] = 707375Sgblack@eecs.umich.edu flags[StaticInst::IsFirstMicroop] = true; 717375Sgblack@eecs.umich.edu break; 727375Sgblack@eecs.umich.edu case VfpLastMicroop: 737375Sgblack@eecs.umich.edu flags[StaticInst::IsMicroop] = 747375Sgblack@eecs.umich.edu flags[StaticInst::IsLastMicroop] = true; 757375Sgblack@eecs.umich.edu break; 767375Sgblack@eecs.umich.edu case VfpNotAMicroop: 777375Sgblack@eecs.umich.edu break; 787375Sgblack@eecs.umich.edu } 797376Sgblack@eecs.umich.edu if (mode == VfpMicroop || mode == VfpFirstMicroop) { 807376Sgblack@eecs.umich.edu flags[StaticInst::IsDelayedCommit] = true; 817376Sgblack@eecs.umich.edu } 827375Sgblack@eecs.umich.edu} 837375Sgblack@eecs.umich.edu 847378Sgblack@eecs.umich.eduenum FeExceptionBit 857378Sgblack@eecs.umich.edu{ 867378Sgblack@eecs.umich.edu FeDivByZero = FE_DIVBYZERO, 877378Sgblack@eecs.umich.edu FeInexact = FE_INEXACT, 887378Sgblack@eecs.umich.edu FeInvalid = FE_INVALID, 897378Sgblack@eecs.umich.edu FeOverflow = FE_OVERFLOW, 907378Sgblack@eecs.umich.edu FeUnderflow = FE_UNDERFLOW, 917378Sgblack@eecs.umich.edu FeAllExceptions = FE_ALL_EXCEPT 927378Sgblack@eecs.umich.edu}; 937378Sgblack@eecs.umich.edu 947378Sgblack@eecs.umich.eduenum FeRoundingMode 957378Sgblack@eecs.umich.edu{ 967378Sgblack@eecs.umich.edu FeRoundDown = FE_DOWNWARD, 977378Sgblack@eecs.umich.edu FeRoundNearest = FE_TONEAREST, 987378Sgblack@eecs.umich.edu FeRoundZero = FE_TOWARDZERO, 997378Sgblack@eecs.umich.edu FeRoundUpward = FE_UPWARD 1007378Sgblack@eecs.umich.edu}; 1017378Sgblack@eecs.umich.edu 1027378Sgblack@eecs.umich.eduenum VfpRoundingMode 1037378Sgblack@eecs.umich.edu{ 1047378Sgblack@eecs.umich.edu VfpRoundNearest = 0, 1057378Sgblack@eecs.umich.edu VfpRoundUpward = 1, 1067378Sgblack@eecs.umich.edu VfpRoundDown = 2, 10710037SARM gem5 Developers VfpRoundZero = 3, 10810037SARM gem5 Developers VfpRoundAway = 4 1097378Sgblack@eecs.umich.edu}; 1107378Sgblack@eecs.umich.edu 1118737Skoansin.tan@gmail.comstatic inline float bitsToFp(uint64_t, float); 1128865SGiacomo.Gabrielli@arm.comstatic inline double bitsToFp(uint64_t, double); 1138737Skoansin.tan@gmail.comstatic inline uint32_t fpToBits(float); 1148865SGiacomo.Gabrielli@arm.comstatic inline uint64_t fpToBits(double); 1158737Skoansin.tan@gmail.com 1167382Sgblack@eecs.umich.edutemplate <class fpType> 1177396Sgblack@eecs.umich.edustatic inline bool 1187396Sgblack@eecs.umich.eduflushToZero(fpType &op) 1197396Sgblack@eecs.umich.edu{ 1207396Sgblack@eecs.umich.edu fpType junk = 0.0; 1217396Sgblack@eecs.umich.edu if (std::fpclassify(op) == FP_SUBNORMAL) { 1227396Sgblack@eecs.umich.edu uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 1237396Sgblack@eecs.umich.edu op = bitsToFp(fpToBits(op) & bitMask, junk); 1247396Sgblack@eecs.umich.edu return true; 1257396Sgblack@eecs.umich.edu } 1267396Sgblack@eecs.umich.edu return false; 1277396Sgblack@eecs.umich.edu} 1287396Sgblack@eecs.umich.edu 1297396Sgblack@eecs.umich.edutemplate <class fpType> 1307396Sgblack@eecs.umich.edustatic inline bool 1317396Sgblack@eecs.umich.eduflushToZero(fpType &op1, fpType &op2) 1327396Sgblack@eecs.umich.edu{ 1337396Sgblack@eecs.umich.edu bool flush1 = flushToZero(op1); 1347396Sgblack@eecs.umich.edu bool flush2 = flushToZero(op2); 1357396Sgblack@eecs.umich.edu return flush1 || flush2; 1367396Sgblack@eecs.umich.edu} 1377396Sgblack@eecs.umich.edu 1387397Sgblack@eecs.umich.edutemplate <class fpType> 1397397Sgblack@eecs.umich.edustatic inline void 1407397Sgblack@eecs.umich.eduvfpFlushToZero(FPSCR &fpscr, fpType &op) 1417397Sgblack@eecs.umich.edu{ 1427397Sgblack@eecs.umich.edu if (fpscr.fz == 1 && flushToZero(op)) { 1437397Sgblack@eecs.umich.edu fpscr.idc = 1; 1447397Sgblack@eecs.umich.edu } 1457397Sgblack@eecs.umich.edu} 1467397Sgblack@eecs.umich.edu 1477397Sgblack@eecs.umich.edutemplate <class fpType> 1487397Sgblack@eecs.umich.edustatic inline void 1497397Sgblack@eecs.umich.eduvfpFlushToZero(FPSCR &fpscr, fpType &op1, fpType &op2) 1507397Sgblack@eecs.umich.edu{ 1517397Sgblack@eecs.umich.edu vfpFlushToZero(fpscr, op1); 1527397Sgblack@eecs.umich.edu vfpFlushToZero(fpscr, op2); 1537397Sgblack@eecs.umich.edu} 1547397Sgblack@eecs.umich.edu 1557384Sgblack@eecs.umich.edustatic inline uint32_t 1567384Sgblack@eecs.umich.edufpToBits(float fp) 1577384Sgblack@eecs.umich.edu{ 1587384Sgblack@eecs.umich.edu union 1597384Sgblack@eecs.umich.edu { 1607384Sgblack@eecs.umich.edu float fp; 1617384Sgblack@eecs.umich.edu uint32_t bits; 1627384Sgblack@eecs.umich.edu } val; 1637384Sgblack@eecs.umich.edu val.fp = fp; 1647384Sgblack@eecs.umich.edu return val.bits; 1657384Sgblack@eecs.umich.edu} 1667384Sgblack@eecs.umich.edu 1677384Sgblack@eecs.umich.edustatic inline uint64_t 1687384Sgblack@eecs.umich.edufpToBits(double fp) 1697384Sgblack@eecs.umich.edu{ 1707384Sgblack@eecs.umich.edu union 1717384Sgblack@eecs.umich.edu { 1727384Sgblack@eecs.umich.edu double fp; 1737384Sgblack@eecs.umich.edu uint64_t bits; 1747384Sgblack@eecs.umich.edu } val; 1757384Sgblack@eecs.umich.edu val.fp = fp; 1767384Sgblack@eecs.umich.edu return val.bits; 1777384Sgblack@eecs.umich.edu} 1787384Sgblack@eecs.umich.edu 1797384Sgblack@eecs.umich.edustatic inline float 1807384Sgblack@eecs.umich.edubitsToFp(uint64_t bits, float junk) 1817384Sgblack@eecs.umich.edu{ 1827384Sgblack@eecs.umich.edu union 1837384Sgblack@eecs.umich.edu { 1847384Sgblack@eecs.umich.edu float fp; 1857384Sgblack@eecs.umich.edu uint32_t bits; 1867384Sgblack@eecs.umich.edu } val; 1877384Sgblack@eecs.umich.edu val.bits = bits; 1887384Sgblack@eecs.umich.edu return val.fp; 1897384Sgblack@eecs.umich.edu} 1907384Sgblack@eecs.umich.edu 1917384Sgblack@eecs.umich.edustatic inline double 1927384Sgblack@eecs.umich.edubitsToFp(uint64_t bits, double junk) 1937384Sgblack@eecs.umich.edu{ 1947384Sgblack@eecs.umich.edu union 1957384Sgblack@eecs.umich.edu { 1967384Sgblack@eecs.umich.edu double fp; 1977384Sgblack@eecs.umich.edu uint64_t bits; 1987384Sgblack@eecs.umich.edu } val; 1997384Sgblack@eecs.umich.edu val.bits = bits; 2007384Sgblack@eecs.umich.edu return val.fp; 2017384Sgblack@eecs.umich.edu} 2027384Sgblack@eecs.umich.edu 2037639Sgblack@eecs.umich.edutemplate <class fpType> 2047639Sgblack@eecs.umich.edustatic bool 2057639Sgblack@eecs.umich.eduisSnan(fpType val) 2067639Sgblack@eecs.umich.edu{ 2077639Sgblack@eecs.umich.edu const bool single = (sizeof(fpType) == sizeof(float)); 2087639Sgblack@eecs.umich.edu const uint64_t qnan = 2097639Sgblack@eecs.umich.edu single ? 0x7fc00000 : ULL(0x7ff8000000000000); 2107639Sgblack@eecs.umich.edu return std::isnan(val) && ((fpToBits(val) & qnan) != qnan); 2117639Sgblack@eecs.umich.edu} 2127639Sgblack@eecs.umich.edu 2137396Sgblack@eecs.umich.edutypedef int VfpSavedState; 2147396Sgblack@eecs.umich.edu 2157430Sgblack@eecs.umich.eduVfpSavedState prepFpState(uint32_t rMode); 21610037SARM gem5 Developersvoid finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush, FPSCR mask = FpscrExcMask); 2177396Sgblack@eecs.umich.edu 2187384Sgblack@eecs.umich.edutemplate <class fpType> 2197430Sgblack@eecs.umich.edufpType fixDest(FPSCR fpscr, fpType val, fpType op1); 2207386Sgblack@eecs.umich.edu 2217386Sgblack@eecs.umich.edutemplate <class fpType> 2227430Sgblack@eecs.umich.edufpType fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2); 2237384Sgblack@eecs.umich.edu 2247386Sgblack@eecs.umich.edutemplate <class fpType> 2257430Sgblack@eecs.umich.edufpType fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2); 2267386Sgblack@eecs.umich.edu 2277430Sgblack@eecs.umich.edufloat fixFpDFpSDest(FPSCR fpscr, double val); 2287430Sgblack@eecs.umich.edudouble fixFpSFpDDest(FPSCR fpscr, float val); 2297386Sgblack@eecs.umich.edu 2307639Sgblack@eecs.umich.eduuint16_t vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan, 2317639Sgblack@eecs.umich.edu uint32_t rMode, bool ahp, float op); 23210037SARM gem5 Developersuint16_t vcvtFpDFpH(FPSCR &fpscr, bool flush, bool defaultNan, 23310037SARM gem5 Developers uint32_t rMode, bool ahp, double op); 23410037SARM gem5 Developers 23510037SARM gem5 Developersfloat vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op); 23610037SARM gem5 Developersdouble vcvtFpHFpD(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op); 2377398Sgblack@eecs.umich.edu 2387396Sgblack@eecs.umich.edustatic inline double 2397396Sgblack@eecs.umich.edumakeDouble(uint32_t low, uint32_t high) 2407396Sgblack@eecs.umich.edu{ 2417396Sgblack@eecs.umich.edu double junk = 0.0; 2427396Sgblack@eecs.umich.edu return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 2437396Sgblack@eecs.umich.edu} 2447396Sgblack@eecs.umich.edu 2457396Sgblack@eecs.umich.edustatic inline uint32_t 2467396Sgblack@eecs.umich.edulowFromDouble(double val) 2477396Sgblack@eecs.umich.edu{ 2487396Sgblack@eecs.umich.edu return fpToBits(val); 2497396Sgblack@eecs.umich.edu} 2507396Sgblack@eecs.umich.edu 2517396Sgblack@eecs.umich.edustatic inline uint32_t 2527396Sgblack@eecs.umich.eduhighFromDouble(double val) 2537396Sgblack@eecs.umich.edu{ 2547396Sgblack@eecs.umich.edu return fpToBits(val) >> 32; 2557396Sgblack@eecs.umich.edu} 2567396Sgblack@eecs.umich.edu 25710037SARM gem5 Developersstatic inline void 25810037SARM gem5 DeveloperssetFPExceptions(int exceptions) { 25910037SARM gem5 Developers feclearexcept(FeAllExceptions); 26010037SARM gem5 Developers feraiseexcept(exceptions); 26110037SARM gem5 Developers} 26210037SARM gem5 Developers 26310037SARM gem5 Developerstemplate <typename T> 26410037SARM gem5 Developersuint64_t 26510037SARM gem5 DevelopersvfpFpToFixed(T val, bool isSigned, uint8_t width, uint8_t imm, bool 26610037SARM gem5 Developers useRmode = true, VfpRoundingMode roundMode = VfpRoundZero, 26710037SARM gem5 Developers bool aarch64 = false) 26810037SARM gem5 Developers{ 26910037SARM gem5 Developers int rmode; 27010037SARM gem5 Developers bool roundAwayFix = false; 27110037SARM gem5 Developers 27210037SARM gem5 Developers if (!useRmode) { 27310037SARM gem5 Developers rmode = fegetround(); 27410037SARM gem5 Developers } else { 27510037SARM gem5 Developers switch (roundMode) 27610037SARM gem5 Developers { 27710037SARM gem5 Developers case VfpRoundNearest: 27810037SARM gem5 Developers rmode = FeRoundNearest; 27910037SARM gem5 Developers break; 28010037SARM gem5 Developers case VfpRoundUpward: 28110037SARM gem5 Developers rmode = FeRoundUpward; 28210037SARM gem5 Developers break; 28310037SARM gem5 Developers case VfpRoundDown: 28410037SARM gem5 Developers rmode = FeRoundDown; 28510037SARM gem5 Developers break; 28610037SARM gem5 Developers case VfpRoundZero: 28710037SARM gem5 Developers rmode = FeRoundZero; 28810037SARM gem5 Developers break; 28910037SARM gem5 Developers case VfpRoundAway: 29010037SARM gem5 Developers // There is no equivalent rounding mode, use round down and we'll 29110037SARM gem5 Developers // fix it later 29210037SARM gem5 Developers rmode = FeRoundDown; 29310037SARM gem5 Developers roundAwayFix = true; 29410037SARM gem5 Developers break; 29510037SARM gem5 Developers default: 29610037SARM gem5 Developers panic("Unsupported roundMode %d\n", roundMode); 29710037SARM gem5 Developers } 29810037SARM gem5 Developers } 29910037SARM gem5 Developers __asm__ __volatile__("" : "=m" (rmode) : "m" (rmode)); 30010037SARM gem5 Developers fesetround(FeRoundNearest); 30110037SARM gem5 Developers val = val * pow(2.0, imm); 30210037SARM gem5 Developers __asm__ __volatile__("" : "=m" (val) : "m" (val)); 30310037SARM gem5 Developers fesetround(rmode); 30410037SARM gem5 Developers feclearexcept(FeAllExceptions); 30510037SARM gem5 Developers __asm__ __volatile__("" : "=m" (val) : "m" (val)); 30610037SARM gem5 Developers T origVal = val; 30710037SARM gem5 Developers val = rint(val); 30810037SARM gem5 Developers __asm__ __volatile__("" : "=m" (val) : "m" (val)); 30910037SARM gem5 Developers 31010037SARM gem5 Developers int exceptions = fetestexcept(FeAllExceptions); 31110037SARM gem5 Developers 31210037SARM gem5 Developers int fpType = std::fpclassify(val); 31310037SARM gem5 Developers if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { 31410037SARM gem5 Developers if (fpType == FP_NAN) { 31510037SARM gem5 Developers exceptions |= FeInvalid; 31610037SARM gem5 Developers } 31710037SARM gem5 Developers val = 0.0; 31810037SARM gem5 Developers } else if (origVal != val) { 31910037SARM gem5 Developers switch (rmode) { 32010037SARM gem5 Developers case FeRoundNearest: 32110037SARM gem5 Developers if (origVal - val > 0.5) 32210037SARM gem5 Developers val += 1.0; 32310037SARM gem5 Developers else if (val - origVal > 0.5) 32410037SARM gem5 Developers val -= 1.0; 32510037SARM gem5 Developers break; 32610037SARM gem5 Developers case FeRoundDown: 32710037SARM gem5 Developers if (roundAwayFix) { 32810037SARM gem5 Developers // The ordering on the subtraction looks a bit odd in that we 32910037SARM gem5 Developers // don't do the obvious origVal - val, instead we do 33010037SARM gem5 Developers // -(val - origVal). This is required to get the corruct bit 33110037SARM gem5 Developers // exact behaviour when very close to the 0.5 threshold. 33210037SARM gem5 Developers volatile T error = val; 33310037SARM gem5 Developers error -= origVal; 33410037SARM gem5 Developers error = -error; 33510037SARM gem5 Developers if ( (error > 0.5) || 33610037SARM gem5 Developers ((error == 0.5) && (val >= 0)) ) 33710037SARM gem5 Developers val += 1.0; 33810037SARM gem5 Developers } else { 33910037SARM gem5 Developers if (origVal < val) 34010037SARM gem5 Developers val -= 1.0; 34110037SARM gem5 Developers } 34210037SARM gem5 Developers break; 34310037SARM gem5 Developers case FeRoundUpward: 34410037SARM gem5 Developers if (origVal > val) 34510037SARM gem5 Developers val += 1.0; 34610037SARM gem5 Developers break; 34710037SARM gem5 Developers } 34810037SARM gem5 Developers exceptions |= FeInexact; 34910037SARM gem5 Developers } 35010037SARM gem5 Developers 35110037SARM gem5 Developers __asm__ __volatile__("" : "=m" (val) : "m" (val)); 35210037SARM gem5 Developers 35310037SARM gem5 Developers if (isSigned) { 35410037SARM gem5 Developers bool outOfRange = false; 35510037SARM gem5 Developers int64_t result = (int64_t) val; 35610037SARM gem5 Developers uint64_t finalVal; 35710037SARM gem5 Developers 35810037SARM gem5 Developers if (!aarch64) { 35910037SARM gem5 Developers if (width == 16) { 36010037SARM gem5 Developers finalVal = (int16_t)val; 36110037SARM gem5 Developers } else if (width == 32) { 36210037SARM gem5 Developers finalVal =(int32_t)val; 36310037SARM gem5 Developers } else if (width == 64) { 36410037SARM gem5 Developers finalVal = result; 36510037SARM gem5 Developers } else { 36610037SARM gem5 Developers panic("Unsupported width %d\n", width); 36710037SARM gem5 Developers } 36810037SARM gem5 Developers 36910037SARM gem5 Developers // check if value is in range 37010037SARM gem5 Developers int64_t minVal = ~mask(width-1); 37110037SARM gem5 Developers if ((double)val < minVal) { 37210037SARM gem5 Developers outOfRange = true; 37310037SARM gem5 Developers finalVal = minVal; 37410037SARM gem5 Developers } 37510037SARM gem5 Developers int64_t maxVal = mask(width-1); 37610037SARM gem5 Developers if ((double)val > maxVal) { 37710037SARM gem5 Developers outOfRange = true; 37810037SARM gem5 Developers finalVal = maxVal; 37910037SARM gem5 Developers } 38010037SARM gem5 Developers } else { 38110037SARM gem5 Developers bool isNeg = val < 0; 38210037SARM gem5 Developers finalVal = result & mask(width); 38310037SARM gem5 Developers // If the result is supposed to be less than 64 bits check that the 38410037SARM gem5 Developers // upper bits that got thrown away are just sign extension bits 38510037SARM gem5 Developers if (width != 64) { 38610037SARM gem5 Developers outOfRange = ((uint64_t) result >> (width - 1)) != 38710037SARM gem5 Developers (isNeg ? mask(64-width+1) : 0); 38810037SARM gem5 Developers } 38910037SARM gem5 Developers // Check if the original floating point value doesn't matches the 39010037SARM gem5 Developers // integer version we are also out of range. So create a saturated 39110037SARM gem5 Developers // result. 39210037SARM gem5 Developers if (isNeg) { 39310037SARM gem5 Developers outOfRange |= val < result; 39410037SARM gem5 Developers if (outOfRange) { 39510037SARM gem5 Developers finalVal = 1LL << (width-1); 39610037SARM gem5 Developers } 39710037SARM gem5 Developers } else { 39810037SARM gem5 Developers outOfRange |= val > result; 39910037SARM gem5 Developers if (outOfRange) { 40010037SARM gem5 Developers finalVal = mask(width-1); 40110037SARM gem5 Developers } 40210037SARM gem5 Developers } 40310037SARM gem5 Developers } 40410037SARM gem5 Developers 40510037SARM gem5 Developers // Raise an exception if the value was out of range 40610037SARM gem5 Developers if (outOfRange) { 40710037SARM gem5 Developers exceptions |= FeInvalid; 40810037SARM gem5 Developers exceptions &= ~FeInexact; 40910037SARM gem5 Developers } 41010037SARM gem5 Developers setFPExceptions(exceptions); 41110037SARM gem5 Developers return finalVal; 41210037SARM gem5 Developers } else { 41310037SARM gem5 Developers if ((double)val < 0) { 41410037SARM gem5 Developers exceptions |= FeInvalid; 41510037SARM gem5 Developers exceptions &= ~FeInexact; 41610037SARM gem5 Developers setFPExceptions(exceptions); 41710037SARM gem5 Developers return 0; 41810037SARM gem5 Developers } 41910037SARM gem5 Developers 42010037SARM gem5 Developers uint64_t result = ((uint64_t) val) & mask(width); 42110037SARM gem5 Developers if (val > result) { 42210037SARM gem5 Developers exceptions |= FeInvalid; 42310037SARM gem5 Developers exceptions &= ~FeInexact; 42410037SARM gem5 Developers setFPExceptions(exceptions); 42510037SARM gem5 Developers return mask(width); 42610037SARM gem5 Developers } 42710037SARM gem5 Developers 42810037SARM gem5 Developers setFPExceptions(exceptions); 42910037SARM gem5 Developers return result; 43010037SARM gem5 Developers } 43110037SARM gem5 Developers}; 43210037SARM gem5 Developers 43310037SARM gem5 Developers 4347639Sgblack@eecs.umich.edufloat vfpUFixedToFpS(bool flush, bool defaultNan, 43510037SARM gem5 Developers uint64_t val, uint8_t width, uint8_t imm); 4367639Sgblack@eecs.umich.edufloat vfpSFixedToFpS(bool flush, bool defaultNan, 43710037SARM gem5 Developers int64_t val, uint8_t width, uint8_t imm); 4387382Sgblack@eecs.umich.edu 4397639Sgblack@eecs.umich.edudouble vfpUFixedToFpD(bool flush, bool defaultNan, 44010037SARM gem5 Developers uint64_t val, uint8_t width, uint8_t imm); 4417639Sgblack@eecs.umich.edudouble vfpSFixedToFpD(bool flush, bool defaultNan, 44210037SARM gem5 Developers int64_t val, uint8_t width, uint8_t imm); 4437639Sgblack@eecs.umich.edu 4447639Sgblack@eecs.umich.edufloat fprSqrtEstimate(FPSCR &fpscr, float op); 4457639Sgblack@eecs.umich.eduuint32_t unsignedRSqrtEstimate(uint32_t op); 4467639Sgblack@eecs.umich.edu 4477639Sgblack@eecs.umich.edufloat fpRecipEstimate(FPSCR &fpscr, float op); 4487639Sgblack@eecs.umich.eduuint32_t unsignedRecipEstimate(uint32_t op); 4497379Sgblack@eecs.umich.edu 4507376Sgblack@eecs.umich.educlass VfpMacroOp : public PredMacroOp 4517376Sgblack@eecs.umich.edu{ 4527376Sgblack@eecs.umich.edu public: 4537376Sgblack@eecs.umich.edu static bool 4547376Sgblack@eecs.umich.edu inScalarBank(IntRegIndex idx) 4557376Sgblack@eecs.umich.edu { 4567376Sgblack@eecs.umich.edu return (idx % 32) < 8; 4577376Sgblack@eecs.umich.edu } 4587376Sgblack@eecs.umich.edu 4597376Sgblack@eecs.umich.edu protected: 4607376Sgblack@eecs.umich.edu bool wide; 4617376Sgblack@eecs.umich.edu 4627376Sgblack@eecs.umich.edu VfpMacroOp(const char *mnem, ExtMachInst _machInst, 4637376Sgblack@eecs.umich.edu OpClass __opClass, bool _wide) : 4647376Sgblack@eecs.umich.edu PredMacroOp(mnem, _machInst, __opClass), wide(_wide) 4657376Sgblack@eecs.umich.edu {} 4667376Sgblack@eecs.umich.edu 4677430Sgblack@eecs.umich.edu IntRegIndex addStride(IntRegIndex idx, unsigned stride); 4687430Sgblack@eecs.umich.edu void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2); 4697430Sgblack@eecs.umich.edu void nextIdxs(IntRegIndex &dest, IntRegIndex &op1); 4707430Sgblack@eecs.umich.edu void nextIdxs(IntRegIndex &dest); 4717376Sgblack@eecs.umich.edu}; 4727376Sgblack@eecs.umich.edu 47310037SARM gem5 Developerstemplate <typename T> 47410037SARM gem5 Developersstatic inline T 47510037SARM gem5 DevelopersfpAdd(T a, T b) 47610037SARM gem5 Developers{ 47710037SARM gem5 Developers return a + b; 47810037SARM gem5 Developers}; 47910037SARM gem5 Developers 48010037SARM gem5 Developerstemplate <typename T> 48110037SARM gem5 Developersstatic inline T 48210037SARM gem5 DevelopersfpSub(T a, T b) 48310037SARM gem5 Developers{ 48410037SARM gem5 Developers return a - b; 48510037SARM gem5 Developers}; 48610037SARM gem5 Developers 4877396Sgblack@eecs.umich.edustatic inline float 4887396Sgblack@eecs.umich.edufpAddS(float a, float b) 4897396Sgblack@eecs.umich.edu{ 4907396Sgblack@eecs.umich.edu return a + b; 4917396Sgblack@eecs.umich.edu} 4927396Sgblack@eecs.umich.edu 4937396Sgblack@eecs.umich.edustatic inline double 4947396Sgblack@eecs.umich.edufpAddD(double a, double b) 4957396Sgblack@eecs.umich.edu{ 4967396Sgblack@eecs.umich.edu return a + b; 4977396Sgblack@eecs.umich.edu} 4987396Sgblack@eecs.umich.edu 4997396Sgblack@eecs.umich.edustatic inline float 5007396Sgblack@eecs.umich.edufpSubS(float a, float b) 5017396Sgblack@eecs.umich.edu{ 5027396Sgblack@eecs.umich.edu return a - b; 5037396Sgblack@eecs.umich.edu} 5047396Sgblack@eecs.umich.edu 5057396Sgblack@eecs.umich.edustatic inline double 5067396Sgblack@eecs.umich.edufpSubD(double a, double b) 5077396Sgblack@eecs.umich.edu{ 5087396Sgblack@eecs.umich.edu return a - b; 5097396Sgblack@eecs.umich.edu} 5107396Sgblack@eecs.umich.edu 5117396Sgblack@eecs.umich.edustatic inline float 5127396Sgblack@eecs.umich.edufpDivS(float a, float b) 5137396Sgblack@eecs.umich.edu{ 5147396Sgblack@eecs.umich.edu return a / b; 5157396Sgblack@eecs.umich.edu} 5167396Sgblack@eecs.umich.edu 5177396Sgblack@eecs.umich.edustatic inline double 5187396Sgblack@eecs.umich.edufpDivD(double a, double b) 5197396Sgblack@eecs.umich.edu{ 5207396Sgblack@eecs.umich.edu return a / b; 5217396Sgblack@eecs.umich.edu} 5227396Sgblack@eecs.umich.edu 52310037SARM gem5 Developerstemplate <typename T> 52410037SARM gem5 Developersstatic inline T 52510037SARM gem5 DevelopersfpDiv(T a, T b) 52610037SARM gem5 Developers{ 52710037SARM gem5 Developers return a / b; 52810037SARM gem5 Developers}; 52910037SARM gem5 Developers 53010037SARM gem5 Developerstemplate <typename T> 53110037SARM gem5 Developersstatic inline T 53210037SARM gem5 DevelopersfpMulX(T a, T b) 53310037SARM gem5 Developers{ 53410037SARM gem5 Developers uint64_t opData; 53510037SARM gem5 Developers uint32_t sign1; 53610037SARM gem5 Developers uint32_t sign2; 53710037SARM gem5 Developers const bool single = (sizeof(T) == sizeof(float)); 53810037SARM gem5 Developers if (single) { 53910037SARM gem5 Developers opData = (fpToBits(a)); 54010037SARM gem5 Developers sign1 = opData>>31; 54110037SARM gem5 Developers opData = (fpToBits(b)); 54210037SARM gem5 Developers sign2 = opData>>31; 54310037SARM gem5 Developers } else { 54410037SARM gem5 Developers opData = (fpToBits(a)); 54510037SARM gem5 Developers sign1 = opData>>63; 54610037SARM gem5 Developers opData = (fpToBits(b)); 54710037SARM gem5 Developers sign2 = opData>>63; 54810037SARM gem5 Developers } 54910037SARM gem5 Developers bool inf1 = (std::fpclassify(a) == FP_INFINITE); 55010037SARM gem5 Developers bool inf2 = (std::fpclassify(b) == FP_INFINITE); 55110037SARM gem5 Developers bool zero1 = (std::fpclassify(a) == FP_ZERO); 55210037SARM gem5 Developers bool zero2 = (std::fpclassify(b) == FP_ZERO); 55310037SARM gem5 Developers if ((inf1 && zero2) || (zero1 && inf2)) { 55410037SARM gem5 Developers if(sign1 ^ sign2) 55510037SARM gem5 Developers return (T)(-2.0); 55610037SARM gem5 Developers else 55710037SARM gem5 Developers return (T)(2.0); 55810037SARM gem5 Developers } else { 55910037SARM gem5 Developers return (a * b); 56010037SARM gem5 Developers } 56110037SARM gem5 Developers}; 56210037SARM gem5 Developers 56310037SARM gem5 Developers 56410037SARM gem5 Developerstemplate <typename T> 56510037SARM gem5 Developersstatic inline T 56610037SARM gem5 DevelopersfpMul(T a, T b) 56710037SARM gem5 Developers{ 56810037SARM gem5 Developers return a * b; 56910037SARM gem5 Developers}; 57010037SARM gem5 Developers 5717396Sgblack@eecs.umich.edustatic inline float 5727396Sgblack@eecs.umich.edufpMulS(float a, float b) 5737396Sgblack@eecs.umich.edu{ 5747396Sgblack@eecs.umich.edu return a * b; 5757396Sgblack@eecs.umich.edu} 5767396Sgblack@eecs.umich.edu 5777396Sgblack@eecs.umich.edustatic inline double 5787396Sgblack@eecs.umich.edufpMulD(double a, double b) 5797396Sgblack@eecs.umich.edu{ 5807396Sgblack@eecs.umich.edu return a * b; 5817396Sgblack@eecs.umich.edu} 5827396Sgblack@eecs.umich.edu 58310037SARM gem5 Developerstemplate <typename T> 58410037SARM gem5 Developersstatic inline T 58510037SARM gem5 Developers// @todo remove this when all calls to it have been replaced with the new fplib implementation 58610037SARM gem5 DevelopersfpMulAdd(T op1, T op2, T addend) 5877639Sgblack@eecs.umich.edu{ 58810037SARM gem5 Developers T result; 58910037SARM gem5 Developers 59010037SARM gem5 Developers if (sizeof(T) == sizeof(float)) 59110037SARM gem5 Developers result = fmaf(op1, op2, addend); 59210037SARM gem5 Developers else 59310037SARM gem5 Developers result = fma(op1, op2, addend); 59410037SARM gem5 Developers 59510037SARM gem5 Developers // ARM doesn't generate signed nan's from this opperation, so fix up the result 59610037SARM gem5 Developers if (std::isnan(result) && !std::isnan(op1) && 59710037SARM gem5 Developers !std::isnan(op2) && !std::isnan(addend)) 59810037SARM gem5 Developers { 59910037SARM gem5 Developers uint64_t bitMask = ULL(0x1) << ((sizeof(T) * 8) - 1); 60010037SARM gem5 Developers result = bitsToFp(fpToBits(result) & ~bitMask, op1); 60110037SARM gem5 Developers } 60210037SARM gem5 Developers return result; 60310037SARM gem5 Developers} 60410037SARM gem5 Developers 60510037SARM gem5 Developerstemplate <typename T> 60610037SARM gem5 Developersstatic inline T 60710037SARM gem5 DevelopersfpRIntX(T a, FPSCR &fpscr) 60810037SARM gem5 Developers{ 60910037SARM gem5 Developers T rVal; 61010037SARM gem5 Developers 61110037SARM gem5 Developers rVal = rint(a); 61210037SARM gem5 Developers if (rVal != a && !std::isnan(a)) 61310037SARM gem5 Developers fpscr.ixc = 1; 61410037SARM gem5 Developers return (rVal); 61510037SARM gem5 Developers}; 61610037SARM gem5 Developers 61710037SARM gem5 Developerstemplate <typename T> 61810037SARM gem5 Developersstatic inline T 61910037SARM gem5 DevelopersfpMaxNum(T a, T b) 62010037SARM gem5 Developers{ 62110037SARM gem5 Developers const bool single = (sizeof(T) == sizeof(float)); 62210037SARM gem5 Developers const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 62310037SARM gem5 Developers 62410037SARM gem5 Developers if (std::isnan(a)) 62510037SARM gem5 Developers return ((fpToBits(a) & qnan) == qnan) ? b : a; 62610037SARM gem5 Developers if (std::isnan(b)) 62710037SARM gem5 Developers return ((fpToBits(b) & qnan) == qnan) ? a : b; 6287639Sgblack@eecs.umich.edu // Handle comparisons of +0 and -0. 6297639Sgblack@eecs.umich.edu if (!std::signbit(a) && std::signbit(b)) 6307639Sgblack@eecs.umich.edu return a; 63110037SARM gem5 Developers return fmax(a, b); 63210037SARM gem5 Developers}; 6337639Sgblack@eecs.umich.edu 63410037SARM gem5 Developerstemplate <typename T> 63510037SARM gem5 Developersstatic inline T 63610037SARM gem5 DevelopersfpMax(T a, T b) 6377639Sgblack@eecs.umich.edu{ 63810037SARM gem5 Developers if (std::isnan(a)) 63910037SARM gem5 Developers return a; 64010037SARM gem5 Developers if (std::isnan(b)) 64110037SARM gem5 Developers return b; 64210037SARM gem5 Developers return fpMaxNum<T>(a, b); 64310037SARM gem5 Developers}; 64410037SARM gem5 Developers 64510037SARM gem5 Developerstemplate <typename T> 64610037SARM gem5 Developersstatic inline T 64710037SARM gem5 DevelopersfpMinNum(T a, T b) 64810037SARM gem5 Developers{ 64910037SARM gem5 Developers const bool single = (sizeof(T) == sizeof(float)); 65010037SARM gem5 Developers const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 65110037SARM gem5 Developers 65210037SARM gem5 Developers if (std::isnan(a)) 65310037SARM gem5 Developers return ((fpToBits(a) & qnan) == qnan) ? b : a; 65410037SARM gem5 Developers if (std::isnan(b)) 65510037SARM gem5 Developers return ((fpToBits(b) & qnan) == qnan) ? a : b; 6567639Sgblack@eecs.umich.edu // Handle comparisons of +0 and -0. 6577639Sgblack@eecs.umich.edu if (std::signbit(a) && !std::signbit(b)) 6587639Sgblack@eecs.umich.edu return a; 65910037SARM gem5 Developers return fmin(a, b); 66010037SARM gem5 Developers}; 66110037SARM gem5 Developers 66210037SARM gem5 Developerstemplate <typename T> 66310037SARM gem5 Developersstatic inline T 66410037SARM gem5 DevelopersfpMin(T a, T b) 66510037SARM gem5 Developers{ 66610037SARM gem5 Developers if (std::isnan(a)) 66710037SARM gem5 Developers return a; 66810037SARM gem5 Developers if (std::isnan(b)) 66910037SARM gem5 Developers return b; 67010037SARM gem5 Developers return fpMinNum<T>(a, b); 67110037SARM gem5 Developers}; 67210037SARM gem5 Developers 67310037SARM gem5 Developerstemplate <typename T> 67410037SARM gem5 Developersstatic inline T 67510037SARM gem5 DevelopersfpRSqrts(T a, T b) 67610037SARM gem5 Developers{ 67710037SARM gem5 Developers int fpClassA = std::fpclassify(a); 67810037SARM gem5 Developers int fpClassB = std::fpclassify(b); 67910037SARM gem5 Developers T aXb; 68010037SARM gem5 Developers int fpClassAxB; 68110037SARM gem5 Developers 68210037SARM gem5 Developers if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) || 68310037SARM gem5 Developers (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) { 68410037SARM gem5 Developers return 1.5; 68510037SARM gem5 Developers } 68610037SARM gem5 Developers aXb = a*b; 68710037SARM gem5 Developers fpClassAxB = std::fpclassify(aXb); 68810037SARM gem5 Developers if(fpClassAxB == FP_SUBNORMAL) { 68910037SARM gem5 Developers feraiseexcept(FeUnderflow); 69010037SARM gem5 Developers return 1.5; 69110037SARM gem5 Developers } 69210037SARM gem5 Developers return (3.0 - (a * b)) / 2.0; 69310037SARM gem5 Developers}; 69410037SARM gem5 Developers 69510037SARM gem5 Developerstemplate <typename T> 69610037SARM gem5 Developersstatic inline T 69710037SARM gem5 DevelopersfpRecps(T a, T b) 69810037SARM gem5 Developers{ 69910037SARM gem5 Developers int fpClassA = std::fpclassify(a); 70010037SARM gem5 Developers int fpClassB = std::fpclassify(b); 70110037SARM gem5 Developers T aXb; 70210037SARM gem5 Developers int fpClassAxB; 70310037SARM gem5 Developers 70410037SARM gem5 Developers if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) || 70510037SARM gem5 Developers (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) { 70610037SARM gem5 Developers return 2.0; 70710037SARM gem5 Developers } 70810037SARM gem5 Developers aXb = a*b; 70910037SARM gem5 Developers fpClassAxB = std::fpclassify(aXb); 71010037SARM gem5 Developers if(fpClassAxB == FP_SUBNORMAL) { 71110037SARM gem5 Developers feraiseexcept(FeUnderflow); 71210037SARM gem5 Developers return 2.0; 71310037SARM gem5 Developers } 71410037SARM gem5 Developers return 2.0 - (a * b); 71510037SARM gem5 Developers}; 71610037SARM gem5 Developers 7177639Sgblack@eecs.umich.edu 7187639Sgblack@eecs.umich.edustatic inline float 7197639Sgblack@eecs.umich.edufpRSqrtsS(float a, float b) 7207639Sgblack@eecs.umich.edu{ 7217639Sgblack@eecs.umich.edu int fpClassA = std::fpclassify(a); 7227639Sgblack@eecs.umich.edu int fpClassB = std::fpclassify(b); 7237639Sgblack@eecs.umich.edu float aXb; 7247639Sgblack@eecs.umich.edu int fpClassAxB; 7257639Sgblack@eecs.umich.edu 7267639Sgblack@eecs.umich.edu if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) || 7277639Sgblack@eecs.umich.edu (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) { 7287639Sgblack@eecs.umich.edu return 1.5; 7297639Sgblack@eecs.umich.edu } 7307639Sgblack@eecs.umich.edu aXb = a*b; 7317639Sgblack@eecs.umich.edu fpClassAxB = std::fpclassify(aXb); 7327639Sgblack@eecs.umich.edu if(fpClassAxB == FP_SUBNORMAL) { 7337639Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 7347639Sgblack@eecs.umich.edu return 1.5; 7357639Sgblack@eecs.umich.edu } 7367639Sgblack@eecs.umich.edu return (3.0 - (a * b)) / 2.0; 7377639Sgblack@eecs.umich.edu} 7387639Sgblack@eecs.umich.edu 7397639Sgblack@eecs.umich.edustatic inline float 7407639Sgblack@eecs.umich.edufpRecpsS(float a, float b) 7417639Sgblack@eecs.umich.edu{ 7427639Sgblack@eecs.umich.edu int fpClassA = std::fpclassify(a); 7437639Sgblack@eecs.umich.edu int fpClassB = std::fpclassify(b); 7447639Sgblack@eecs.umich.edu float aXb; 7457639Sgblack@eecs.umich.edu int fpClassAxB; 7467639Sgblack@eecs.umich.edu 7477639Sgblack@eecs.umich.edu if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) || 7487639Sgblack@eecs.umich.edu (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) { 7497639Sgblack@eecs.umich.edu return 2.0; 7507639Sgblack@eecs.umich.edu } 7517639Sgblack@eecs.umich.edu aXb = a*b; 7527639Sgblack@eecs.umich.edu fpClassAxB = std::fpclassify(aXb); 7537639Sgblack@eecs.umich.edu if(fpClassAxB == FP_SUBNORMAL) { 7547639Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 7557639Sgblack@eecs.umich.edu return 2.0; 7567639Sgblack@eecs.umich.edu } 7577639Sgblack@eecs.umich.edu return 2.0 - (a * b); 7587639Sgblack@eecs.umich.edu} 7597639Sgblack@eecs.umich.edu 76010037SARM gem5 Developerstemplate <typename T> 76110037SARM gem5 Developersstatic inline T 76210037SARM gem5 DevelopersroundNEven(T a) { 76310037SARM gem5 Developers T val; 76410037SARM gem5 Developers 76510037SARM gem5 Developers val = round(a); 76610037SARM gem5 Developers if (a - val == 0.5) { 76710037SARM gem5 Developers if ( (((int) a) & 1) == 0 ) val += 1.0; 76810037SARM gem5 Developers } 76910037SARM gem5 Developers else if (a - val == -0.5) { 77010037SARM gem5 Developers if ( (((int) a) & 1) == 0 ) val -= 1.0; 77110037SARM gem5 Developers } 77210037SARM gem5 Developers return val; 77310037SARM gem5 Developers} 77410037SARM gem5 Developers 77510037SARM gem5 Developers 77610037SARM gem5 Developers 7777396Sgblack@eecs.umich.educlass FpOp : public PredOp 7787375Sgblack@eecs.umich.edu{ 7797375Sgblack@eecs.umich.edu protected: 7807396Sgblack@eecs.umich.edu FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 7817396Sgblack@eecs.umich.edu PredOp(mnem, _machInst, __opClass) 7827396Sgblack@eecs.umich.edu {} 7837396Sgblack@eecs.umich.edu 7847396Sgblack@eecs.umich.edu virtual float 7857396Sgblack@eecs.umich.edu doOp(float op1, float op2) const 7867396Sgblack@eecs.umich.edu { 7877396Sgblack@eecs.umich.edu panic("Unimplemented version of doOp called.\n"); 7887396Sgblack@eecs.umich.edu } 7897396Sgblack@eecs.umich.edu 7907396Sgblack@eecs.umich.edu virtual float 7917396Sgblack@eecs.umich.edu doOp(float op1) const 7927396Sgblack@eecs.umich.edu { 7937396Sgblack@eecs.umich.edu panic("Unimplemented version of doOp called.\n"); 7947396Sgblack@eecs.umich.edu } 7957396Sgblack@eecs.umich.edu 7967396Sgblack@eecs.umich.edu virtual double 7977396Sgblack@eecs.umich.edu doOp(double op1, double op2) const 7987396Sgblack@eecs.umich.edu { 7997396Sgblack@eecs.umich.edu panic("Unimplemented version of doOp called.\n"); 8007396Sgblack@eecs.umich.edu } 8017396Sgblack@eecs.umich.edu 8027396Sgblack@eecs.umich.edu virtual double 8037396Sgblack@eecs.umich.edu doOp(double op1) const 8047396Sgblack@eecs.umich.edu { 8057396Sgblack@eecs.umich.edu panic("Unimplemented version of doOp called.\n"); 8067396Sgblack@eecs.umich.edu } 8077396Sgblack@eecs.umich.edu 8087396Sgblack@eecs.umich.edu double 8097396Sgblack@eecs.umich.edu dbl(uint32_t low, uint32_t high) const 8107396Sgblack@eecs.umich.edu { 8117396Sgblack@eecs.umich.edu double junk = 0.0; 8127396Sgblack@eecs.umich.edu return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 8137396Sgblack@eecs.umich.edu } 8147396Sgblack@eecs.umich.edu 8157396Sgblack@eecs.umich.edu uint32_t 8167396Sgblack@eecs.umich.edu dblLow(double val) const 8177396Sgblack@eecs.umich.edu { 8187396Sgblack@eecs.umich.edu return fpToBits(val); 8197396Sgblack@eecs.umich.edu } 8207396Sgblack@eecs.umich.edu 8217396Sgblack@eecs.umich.edu uint32_t 8227396Sgblack@eecs.umich.edu dblHi(double val) const 8237396Sgblack@eecs.umich.edu { 8247396Sgblack@eecs.umich.edu return fpToBits(val) >> 32; 8257396Sgblack@eecs.umich.edu } 8267396Sgblack@eecs.umich.edu 8277396Sgblack@eecs.umich.edu template <class fpType> 8287396Sgblack@eecs.umich.edu fpType 8297639Sgblack@eecs.umich.edu processNans(FPSCR &fpscr, bool &done, bool defaultNan, 8307639Sgblack@eecs.umich.edu fpType op1, fpType op2) const; 8317639Sgblack@eecs.umich.edu 8327639Sgblack@eecs.umich.edu template <class fpType> 8337639Sgblack@eecs.umich.edu fpType 83410037SARM gem5 Developers ternaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType op3, 83510037SARM gem5 Developers fpType (*func)(fpType, fpType, fpType), 83610037SARM gem5 Developers bool flush, bool defaultNan, uint32_t rMode) const; 83710037SARM gem5 Developers 83810037SARM gem5 Developers template <class fpType> 83910037SARM gem5 Developers fpType 8407396Sgblack@eecs.umich.edu binaryOp(FPSCR &fpscr, fpType op1, fpType op2, 8417396Sgblack@eecs.umich.edu fpType (*func)(fpType, fpType), 8427639Sgblack@eecs.umich.edu bool flush, bool defaultNan, uint32_t rMode) const; 8437396Sgblack@eecs.umich.edu 8447396Sgblack@eecs.umich.edu template <class fpType> 8457396Sgblack@eecs.umich.edu fpType 8467396Sgblack@eecs.umich.edu unaryOp(FPSCR &fpscr, fpType op1, 8477396Sgblack@eecs.umich.edu fpType (*func)(fpType), 8487430Sgblack@eecs.umich.edu bool flush, uint32_t rMode) const; 8497720Sgblack@eecs.umich.edu 8507720Sgblack@eecs.umich.edu void 8517720Sgblack@eecs.umich.edu advancePC(PCState &pcState) const 8527720Sgblack@eecs.umich.edu { 8537720Sgblack@eecs.umich.edu if (flags[IsLastMicroop]) { 8547720Sgblack@eecs.umich.edu pcState.uEnd(); 8557720Sgblack@eecs.umich.edu } else if (flags[IsMicroop]) { 8567720Sgblack@eecs.umich.edu pcState.uAdvance(); 8577720Sgblack@eecs.umich.edu } else { 8587720Sgblack@eecs.umich.edu pcState.advance(); 8597720Sgblack@eecs.umich.edu } 8607720Sgblack@eecs.umich.edu } 86110037SARM gem5 Developers 86210037SARM gem5 Developers float 86310037SARM gem5 Developers fpSqrt (FPSCR fpscr,float x) const 86410037SARM gem5 Developers { 86510037SARM gem5 Developers 86610037SARM gem5 Developers return unaryOp(fpscr,x,sqrtf,fpscr.fz,fpscr.rMode); 86710037SARM gem5 Developers 86810037SARM gem5 Developers } 86910037SARM gem5 Developers 87010037SARM gem5 Developers double 87110037SARM gem5 Developers fpSqrt (FPSCR fpscr,double x) const 87210037SARM gem5 Developers { 87310037SARM gem5 Developers 87410037SARM gem5 Developers return unaryOp(fpscr,x,sqrt,fpscr.fz,fpscr.rMode); 87510037SARM gem5 Developers 87610037SARM gem5 Developers } 87710037SARM gem5 Developers}; 87810037SARM gem5 Developers 87910037SARM gem5 Developersclass FpCondCompRegOp : public FpOp 88010037SARM gem5 Developers{ 88110037SARM gem5 Developers protected: 88210037SARM gem5 Developers IntRegIndex op1, op2; 88310037SARM gem5 Developers ConditionCode condCode; 88410037SARM gem5 Developers uint8_t defCc; 88510037SARM gem5 Developers 88610037SARM gem5 Developers FpCondCompRegOp(const char *mnem, ExtMachInst _machInst, 88710037SARM gem5 Developers OpClass __opClass, IntRegIndex _op1, IntRegIndex _op2, 88810037SARM gem5 Developers ConditionCode _condCode, uint8_t _defCc) : 88910037SARM gem5 Developers FpOp(mnem, _machInst, __opClass), 89010037SARM gem5 Developers op1(_op1), op2(_op2), condCode(_condCode), defCc(_defCc) 89110037SARM gem5 Developers {} 89210037SARM gem5 Developers 89310037SARM gem5 Developers std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 89410037SARM gem5 Developers}; 89510037SARM gem5 Developers 89610037SARM gem5 Developersclass FpCondSelOp : public FpOp 89710037SARM gem5 Developers{ 89810037SARM gem5 Developers protected: 89910037SARM gem5 Developers IntRegIndex dest, op1, op2; 90010037SARM gem5 Developers ConditionCode condCode; 90110037SARM gem5 Developers 90210037SARM gem5 Developers FpCondSelOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 90310037SARM gem5 Developers IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, 90410037SARM gem5 Developers ConditionCode _condCode) : 90510037SARM gem5 Developers FpOp(mnem, _machInst, __opClass), 90610037SARM gem5 Developers dest(_dest), op1(_op1), op2(_op2), condCode(_condCode) 90710037SARM gem5 Developers {} 90810037SARM gem5 Developers 90910037SARM gem5 Developers std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 9107396Sgblack@eecs.umich.edu}; 9117396Sgblack@eecs.umich.edu 9127396Sgblack@eecs.umich.educlass FpRegRegOp : public FpOp 9137396Sgblack@eecs.umich.edu{ 9147396Sgblack@eecs.umich.edu protected: 9157396Sgblack@eecs.umich.edu IntRegIndex dest; 9167396Sgblack@eecs.umich.edu IntRegIndex op1; 9177396Sgblack@eecs.umich.edu 9187396Sgblack@eecs.umich.edu FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 9197396Sgblack@eecs.umich.edu IntRegIndex _dest, IntRegIndex _op1, 9207396Sgblack@eecs.umich.edu VfpMicroMode mode = VfpNotAMicroop) : 9217396Sgblack@eecs.umich.edu FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1) 9227375Sgblack@eecs.umich.edu { 9237375Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 9247375Sgblack@eecs.umich.edu } 9257396Sgblack@eecs.umich.edu 9267396Sgblack@eecs.umich.edu std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 9277375Sgblack@eecs.umich.edu}; 9287375Sgblack@eecs.umich.edu 9297396Sgblack@eecs.umich.educlass FpRegImmOp : public FpOp 9307375Sgblack@eecs.umich.edu{ 9317375Sgblack@eecs.umich.edu protected: 9327396Sgblack@eecs.umich.edu IntRegIndex dest; 9337396Sgblack@eecs.umich.edu uint64_t imm; 9347396Sgblack@eecs.umich.edu 9357396Sgblack@eecs.umich.edu FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 9367396Sgblack@eecs.umich.edu IntRegIndex _dest, uint64_t _imm, 9377396Sgblack@eecs.umich.edu VfpMicroMode mode = VfpNotAMicroop) : 9387396Sgblack@eecs.umich.edu FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm) 9397375Sgblack@eecs.umich.edu { 9407375Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 9417375Sgblack@eecs.umich.edu } 9427396Sgblack@eecs.umich.edu 9437396Sgblack@eecs.umich.edu std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 9447375Sgblack@eecs.umich.edu}; 9457375Sgblack@eecs.umich.edu 9467396Sgblack@eecs.umich.educlass FpRegRegImmOp : public FpOp 9477375Sgblack@eecs.umich.edu{ 9487375Sgblack@eecs.umich.edu protected: 9497396Sgblack@eecs.umich.edu IntRegIndex dest; 9507396Sgblack@eecs.umich.edu IntRegIndex op1; 9517396Sgblack@eecs.umich.edu uint64_t imm; 9527396Sgblack@eecs.umich.edu 9537396Sgblack@eecs.umich.edu FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 9547396Sgblack@eecs.umich.edu IntRegIndex _dest, IntRegIndex _op1, 9557396Sgblack@eecs.umich.edu uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : 9567396Sgblack@eecs.umich.edu FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm) 9577375Sgblack@eecs.umich.edu { 9587375Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 9597375Sgblack@eecs.umich.edu } 9607396Sgblack@eecs.umich.edu 9617396Sgblack@eecs.umich.edu std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 9627375Sgblack@eecs.umich.edu}; 9637375Sgblack@eecs.umich.edu 9647396Sgblack@eecs.umich.educlass FpRegRegRegOp : public FpOp 9657375Sgblack@eecs.umich.edu{ 9667375Sgblack@eecs.umich.edu protected: 9677396Sgblack@eecs.umich.edu IntRegIndex dest; 9687396Sgblack@eecs.umich.edu IntRegIndex op1; 9697396Sgblack@eecs.umich.edu IntRegIndex op2; 9707396Sgblack@eecs.umich.edu 9717396Sgblack@eecs.umich.edu FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 9727396Sgblack@eecs.umich.edu IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, 9737396Sgblack@eecs.umich.edu VfpMicroMode mode = VfpNotAMicroop) : 9747396Sgblack@eecs.umich.edu FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2) 9757375Sgblack@eecs.umich.edu { 9767375Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 9777375Sgblack@eecs.umich.edu } 9787396Sgblack@eecs.umich.edu 9797396Sgblack@eecs.umich.edu std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 9807375Sgblack@eecs.umich.edu}; 9817375Sgblack@eecs.umich.edu 98210037SARM gem5 Developersclass FpRegRegRegRegOp : public FpOp 98310037SARM gem5 Developers{ 98410037SARM gem5 Developers protected: 98510037SARM gem5 Developers IntRegIndex dest; 98610037SARM gem5 Developers IntRegIndex op1; 98710037SARM gem5 Developers IntRegIndex op2; 98810037SARM gem5 Developers IntRegIndex op3; 98910037SARM gem5 Developers 99010037SARM gem5 Developers FpRegRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 99110037SARM gem5 Developers IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, 99210037SARM gem5 Developers IntRegIndex _op3, VfpMicroMode mode = VfpNotAMicroop) : 99310037SARM gem5 Developers FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2), 99410037SARM gem5 Developers op3(_op3) 99510037SARM gem5 Developers { 99610037SARM gem5 Developers setVfpMicroFlags(mode, flags); 99710037SARM gem5 Developers } 99810037SARM gem5 Developers 99910037SARM gem5 Developers std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 100010037SARM gem5 Developers}; 100110037SARM gem5 Developers 10027639Sgblack@eecs.umich.educlass FpRegRegRegImmOp : public FpOp 10037639Sgblack@eecs.umich.edu{ 10047639Sgblack@eecs.umich.edu protected: 10057639Sgblack@eecs.umich.edu IntRegIndex dest; 10067639Sgblack@eecs.umich.edu IntRegIndex op1; 10077639Sgblack@eecs.umich.edu IntRegIndex op2; 10087639Sgblack@eecs.umich.edu uint64_t imm; 10097639Sgblack@eecs.umich.edu 10107639Sgblack@eecs.umich.edu FpRegRegRegImmOp(const char *mnem, ExtMachInst _machInst, 10117639Sgblack@eecs.umich.edu OpClass __opClass, IntRegIndex _dest, 10127639Sgblack@eecs.umich.edu IntRegIndex _op1, IntRegIndex _op2, 10137639Sgblack@eecs.umich.edu uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : 10147639Sgblack@eecs.umich.edu FpOp(mnem, _machInst, __opClass), 10157639Sgblack@eecs.umich.edu dest(_dest), op1(_op1), op2(_op2), imm(_imm) 10167639Sgblack@eecs.umich.edu { 10177639Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 10187639Sgblack@eecs.umich.edu } 10197639Sgblack@eecs.umich.edu 10207639Sgblack@eecs.umich.edu std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 10217639Sgblack@eecs.umich.edu}; 10227639Sgblack@eecs.umich.edu 10237384Sgblack@eecs.umich.edu} 10247384Sgblack@eecs.umich.edu 10257375Sgblack@eecs.umich.edu#endif //__ARCH_ARM_INSTS_VFP_HH__ 1026