17375Sgblack@eecs.umich.edu/* 213978Sciro.santilli@arm.com * Copyright (c) 2010-2013, 2019 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> 20412032Sandreas.sandberg@arm.comstatic inline 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 45013978Sciro.santilli@arm.comFPSCR 45113978Sciro.santilli@arm.comfpStandardFPSCRValue(const FPSCR &fpscr); 45213978Sciro.santilli@arm.com 4537376Sgblack@eecs.umich.educlass VfpMacroOp : public PredMacroOp 4547376Sgblack@eecs.umich.edu{ 4557376Sgblack@eecs.umich.edu public: 4567376Sgblack@eecs.umich.edu static bool 4577376Sgblack@eecs.umich.edu inScalarBank(IntRegIndex idx) 4587376Sgblack@eecs.umich.edu { 4597376Sgblack@eecs.umich.edu return (idx % 32) < 8; 4607376Sgblack@eecs.umich.edu } 4617376Sgblack@eecs.umich.edu 4627376Sgblack@eecs.umich.edu protected: 4637376Sgblack@eecs.umich.edu bool wide; 4647376Sgblack@eecs.umich.edu 4657376Sgblack@eecs.umich.edu VfpMacroOp(const char *mnem, ExtMachInst _machInst, 4667376Sgblack@eecs.umich.edu OpClass __opClass, bool _wide) : 4677376Sgblack@eecs.umich.edu PredMacroOp(mnem, _machInst, __opClass), wide(_wide) 4687376Sgblack@eecs.umich.edu {} 4697376Sgblack@eecs.umich.edu 4707430Sgblack@eecs.umich.edu IntRegIndex addStride(IntRegIndex idx, unsigned stride); 4717430Sgblack@eecs.umich.edu void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2); 4727430Sgblack@eecs.umich.edu void nextIdxs(IntRegIndex &dest, IntRegIndex &op1); 4737430Sgblack@eecs.umich.edu void nextIdxs(IntRegIndex &dest); 4747376Sgblack@eecs.umich.edu}; 4757376Sgblack@eecs.umich.edu 47610037SARM gem5 Developerstemplate <typename T> 47710037SARM gem5 Developersstatic inline T 47810037SARM gem5 DevelopersfpAdd(T a, T b) 47910037SARM gem5 Developers{ 48010037SARM gem5 Developers return a + b; 48110037SARM gem5 Developers}; 48210037SARM gem5 Developers 48310037SARM gem5 Developerstemplate <typename T> 48410037SARM gem5 Developersstatic inline T 48510037SARM gem5 DevelopersfpSub(T a, T b) 48610037SARM gem5 Developers{ 48710037SARM gem5 Developers return a - b; 48810037SARM gem5 Developers}; 48910037SARM gem5 Developers 4907396Sgblack@eecs.umich.edustatic inline float 4917396Sgblack@eecs.umich.edufpAddS(float a, float b) 4927396Sgblack@eecs.umich.edu{ 4937396Sgblack@eecs.umich.edu return a + b; 4947396Sgblack@eecs.umich.edu} 4957396Sgblack@eecs.umich.edu 4967396Sgblack@eecs.umich.edustatic inline double 4977396Sgblack@eecs.umich.edufpAddD(double a, double b) 4987396Sgblack@eecs.umich.edu{ 4997396Sgblack@eecs.umich.edu return a + b; 5007396Sgblack@eecs.umich.edu} 5017396Sgblack@eecs.umich.edu 5027396Sgblack@eecs.umich.edustatic inline float 5037396Sgblack@eecs.umich.edufpSubS(float a, float b) 5047396Sgblack@eecs.umich.edu{ 5057396Sgblack@eecs.umich.edu return a - b; 5067396Sgblack@eecs.umich.edu} 5077396Sgblack@eecs.umich.edu 5087396Sgblack@eecs.umich.edustatic inline double 5097396Sgblack@eecs.umich.edufpSubD(double a, double b) 5107396Sgblack@eecs.umich.edu{ 5117396Sgblack@eecs.umich.edu return a - b; 5127396Sgblack@eecs.umich.edu} 5137396Sgblack@eecs.umich.edu 5147396Sgblack@eecs.umich.edustatic inline float 5157396Sgblack@eecs.umich.edufpDivS(float a, float b) 5167396Sgblack@eecs.umich.edu{ 5177396Sgblack@eecs.umich.edu return a / b; 5187396Sgblack@eecs.umich.edu} 5197396Sgblack@eecs.umich.edu 5207396Sgblack@eecs.umich.edustatic inline double 5217396Sgblack@eecs.umich.edufpDivD(double a, double b) 5227396Sgblack@eecs.umich.edu{ 5237396Sgblack@eecs.umich.edu return a / b; 5247396Sgblack@eecs.umich.edu} 5257396Sgblack@eecs.umich.edu 52610037SARM gem5 Developerstemplate <typename T> 52710037SARM gem5 Developersstatic inline T 52810037SARM gem5 DevelopersfpDiv(T a, T b) 52910037SARM gem5 Developers{ 53010037SARM gem5 Developers return a / b; 53110037SARM gem5 Developers}; 53210037SARM gem5 Developers 53310037SARM gem5 Developerstemplate <typename T> 53410037SARM gem5 Developersstatic inline T 53510037SARM gem5 DevelopersfpMulX(T a, T b) 53610037SARM gem5 Developers{ 53710037SARM gem5 Developers uint64_t opData; 53810037SARM gem5 Developers uint32_t sign1; 53910037SARM gem5 Developers uint32_t sign2; 54010037SARM gem5 Developers const bool single = (sizeof(T) == sizeof(float)); 54110037SARM gem5 Developers if (single) { 54210037SARM gem5 Developers opData = (fpToBits(a)); 54310037SARM gem5 Developers sign1 = opData>>31; 54410037SARM gem5 Developers opData = (fpToBits(b)); 54510037SARM gem5 Developers sign2 = opData>>31; 54610037SARM gem5 Developers } else { 54710037SARM gem5 Developers opData = (fpToBits(a)); 54810037SARM gem5 Developers sign1 = opData>>63; 54910037SARM gem5 Developers opData = (fpToBits(b)); 55010037SARM gem5 Developers sign2 = opData>>63; 55110037SARM gem5 Developers } 55210037SARM gem5 Developers bool inf1 = (std::fpclassify(a) == FP_INFINITE); 55310037SARM gem5 Developers bool inf2 = (std::fpclassify(b) == FP_INFINITE); 55410037SARM gem5 Developers bool zero1 = (std::fpclassify(a) == FP_ZERO); 55510037SARM gem5 Developers bool zero2 = (std::fpclassify(b) == FP_ZERO); 55610037SARM gem5 Developers if ((inf1 && zero2) || (zero1 && inf2)) { 55711321Ssteve.reinhardt@amd.com if (sign1 ^ sign2) 55810037SARM gem5 Developers return (T)(-2.0); 55910037SARM gem5 Developers else 56010037SARM gem5 Developers return (T)(2.0); 56110037SARM gem5 Developers } else { 56210037SARM gem5 Developers return (a * b); 56310037SARM gem5 Developers } 56410037SARM gem5 Developers}; 56510037SARM gem5 Developers 56610037SARM gem5 Developers 56710037SARM gem5 Developerstemplate <typename T> 56810037SARM gem5 Developersstatic inline T 56910037SARM gem5 DevelopersfpMul(T a, T b) 57010037SARM gem5 Developers{ 57110037SARM gem5 Developers return a * b; 57210037SARM gem5 Developers}; 57310037SARM gem5 Developers 5747396Sgblack@eecs.umich.edustatic inline float 5757396Sgblack@eecs.umich.edufpMulS(float a, float b) 5767396Sgblack@eecs.umich.edu{ 5777396Sgblack@eecs.umich.edu return a * b; 5787396Sgblack@eecs.umich.edu} 5797396Sgblack@eecs.umich.edu 5807396Sgblack@eecs.umich.edustatic inline double 5817396Sgblack@eecs.umich.edufpMulD(double a, double b) 5827396Sgblack@eecs.umich.edu{ 5837396Sgblack@eecs.umich.edu return a * b; 5847396Sgblack@eecs.umich.edu} 5857396Sgblack@eecs.umich.edu 58610037SARM gem5 Developerstemplate <typename T> 58710037SARM gem5 Developersstatic inline T 58810037SARM gem5 Developers// @todo remove this when all calls to it have been replaced with the new fplib implementation 58910037SARM gem5 DevelopersfpMulAdd(T op1, T op2, T addend) 5907639Sgblack@eecs.umich.edu{ 59110037SARM gem5 Developers T result; 59210037SARM gem5 Developers 59310037SARM gem5 Developers if (sizeof(T) == sizeof(float)) 59410037SARM gem5 Developers result = fmaf(op1, op2, addend); 59510037SARM gem5 Developers else 59610037SARM gem5 Developers result = fma(op1, op2, addend); 59710037SARM gem5 Developers 59810037SARM gem5 Developers // ARM doesn't generate signed nan's from this opperation, so fix up the result 59910037SARM gem5 Developers if (std::isnan(result) && !std::isnan(op1) && 60010037SARM gem5 Developers !std::isnan(op2) && !std::isnan(addend)) 60110037SARM gem5 Developers { 60210037SARM gem5 Developers uint64_t bitMask = ULL(0x1) << ((sizeof(T) * 8) - 1); 60310037SARM gem5 Developers result = bitsToFp(fpToBits(result) & ~bitMask, op1); 60410037SARM gem5 Developers } 60510037SARM gem5 Developers return result; 60610037SARM gem5 Developers} 60710037SARM gem5 Developers 60810037SARM gem5 Developerstemplate <typename T> 60910037SARM gem5 Developersstatic inline T 61010037SARM gem5 DevelopersfpRIntX(T a, FPSCR &fpscr) 61110037SARM gem5 Developers{ 61210037SARM gem5 Developers T rVal; 61310037SARM gem5 Developers 61410037SARM gem5 Developers rVal = rint(a); 61510037SARM gem5 Developers if (rVal != a && !std::isnan(a)) 61610037SARM gem5 Developers fpscr.ixc = 1; 61710037SARM gem5 Developers return (rVal); 61810037SARM gem5 Developers}; 61910037SARM gem5 Developers 62010037SARM gem5 Developerstemplate <typename T> 62110037SARM gem5 Developersstatic inline T 62210037SARM gem5 DevelopersfpMaxNum(T a, T b) 62310037SARM gem5 Developers{ 62410037SARM gem5 Developers const bool single = (sizeof(T) == sizeof(float)); 62510037SARM gem5 Developers const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 62610037SARM gem5 Developers 62710037SARM gem5 Developers if (std::isnan(a)) 62810037SARM gem5 Developers return ((fpToBits(a) & qnan) == qnan) ? b : a; 62910037SARM gem5 Developers if (std::isnan(b)) 63010037SARM gem5 Developers return ((fpToBits(b) & qnan) == qnan) ? a : b; 6317639Sgblack@eecs.umich.edu // Handle comparisons of +0 and -0. 6327639Sgblack@eecs.umich.edu if (!std::signbit(a) && std::signbit(b)) 6337639Sgblack@eecs.umich.edu return a; 63410037SARM gem5 Developers return fmax(a, b); 63510037SARM gem5 Developers}; 6367639Sgblack@eecs.umich.edu 63710037SARM gem5 Developerstemplate <typename T> 63810037SARM gem5 Developersstatic inline T 63910037SARM gem5 DevelopersfpMax(T a, T b) 6407639Sgblack@eecs.umich.edu{ 64110037SARM gem5 Developers if (std::isnan(a)) 64210037SARM gem5 Developers return a; 64310037SARM gem5 Developers if (std::isnan(b)) 64410037SARM gem5 Developers return b; 64510037SARM gem5 Developers return fpMaxNum<T>(a, b); 64610037SARM gem5 Developers}; 64710037SARM gem5 Developers 64810037SARM gem5 Developerstemplate <typename T> 64910037SARM gem5 Developersstatic inline T 65010037SARM gem5 DevelopersfpMinNum(T a, T b) 65110037SARM gem5 Developers{ 65210037SARM gem5 Developers const bool single = (sizeof(T) == sizeof(float)); 65310037SARM gem5 Developers const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 65410037SARM gem5 Developers 65510037SARM gem5 Developers if (std::isnan(a)) 65610037SARM gem5 Developers return ((fpToBits(a) & qnan) == qnan) ? b : a; 65710037SARM gem5 Developers if (std::isnan(b)) 65810037SARM gem5 Developers return ((fpToBits(b) & qnan) == qnan) ? a : b; 6597639Sgblack@eecs.umich.edu // Handle comparisons of +0 and -0. 6607639Sgblack@eecs.umich.edu if (std::signbit(a) && !std::signbit(b)) 6617639Sgblack@eecs.umich.edu return a; 66210037SARM gem5 Developers return fmin(a, b); 66310037SARM gem5 Developers}; 66410037SARM gem5 Developers 66510037SARM gem5 Developerstemplate <typename T> 66610037SARM gem5 Developersstatic inline T 66710037SARM gem5 DevelopersfpMin(T a, T b) 66810037SARM gem5 Developers{ 66910037SARM gem5 Developers if (std::isnan(a)) 67010037SARM gem5 Developers return a; 67110037SARM gem5 Developers if (std::isnan(b)) 67210037SARM gem5 Developers return b; 67310037SARM gem5 Developers return fpMinNum<T>(a, b); 67410037SARM gem5 Developers}; 67510037SARM gem5 Developers 67610037SARM gem5 Developerstemplate <typename T> 67710037SARM gem5 Developersstatic inline T 67810037SARM gem5 DevelopersfpRSqrts(T a, T b) 67910037SARM gem5 Developers{ 68010037SARM gem5 Developers int fpClassA = std::fpclassify(a); 68110037SARM gem5 Developers int fpClassB = std::fpclassify(b); 68210037SARM gem5 Developers T aXb; 68310037SARM gem5 Developers int fpClassAxB; 68410037SARM gem5 Developers 68510037SARM gem5 Developers if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) || 68610037SARM gem5 Developers (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) { 68710037SARM gem5 Developers return 1.5; 68810037SARM gem5 Developers } 68910037SARM gem5 Developers aXb = a*b; 69010037SARM gem5 Developers fpClassAxB = std::fpclassify(aXb); 69111321Ssteve.reinhardt@amd.com if (fpClassAxB == FP_SUBNORMAL) { 69210037SARM gem5 Developers feraiseexcept(FeUnderflow); 69310037SARM gem5 Developers return 1.5; 69410037SARM gem5 Developers } 69510037SARM gem5 Developers return (3.0 - (a * b)) / 2.0; 69610037SARM gem5 Developers}; 69710037SARM gem5 Developers 69810037SARM gem5 Developerstemplate <typename T> 69910037SARM gem5 Developersstatic inline T 70010037SARM gem5 DevelopersfpRecps(T a, T b) 70110037SARM gem5 Developers{ 70210037SARM gem5 Developers int fpClassA = std::fpclassify(a); 70310037SARM gem5 Developers int fpClassB = std::fpclassify(b); 70410037SARM gem5 Developers T aXb; 70510037SARM gem5 Developers int fpClassAxB; 70610037SARM gem5 Developers 70710037SARM gem5 Developers if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) || 70810037SARM gem5 Developers (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) { 70910037SARM gem5 Developers return 2.0; 71010037SARM gem5 Developers } 71110037SARM gem5 Developers aXb = a*b; 71210037SARM gem5 Developers fpClassAxB = std::fpclassify(aXb); 71311321Ssteve.reinhardt@amd.com if (fpClassAxB == FP_SUBNORMAL) { 71410037SARM gem5 Developers feraiseexcept(FeUnderflow); 71510037SARM gem5 Developers return 2.0; 71610037SARM gem5 Developers } 71710037SARM gem5 Developers return 2.0 - (a * b); 71810037SARM gem5 Developers}; 71910037SARM gem5 Developers 7207639Sgblack@eecs.umich.edu 7217639Sgblack@eecs.umich.edustatic inline float 7227639Sgblack@eecs.umich.edufpRSqrtsS(float a, float b) 7237639Sgblack@eecs.umich.edu{ 7247639Sgblack@eecs.umich.edu int fpClassA = std::fpclassify(a); 7257639Sgblack@eecs.umich.edu int fpClassB = std::fpclassify(b); 7267639Sgblack@eecs.umich.edu float aXb; 7277639Sgblack@eecs.umich.edu int fpClassAxB; 7287639Sgblack@eecs.umich.edu 7297639Sgblack@eecs.umich.edu if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) || 7307639Sgblack@eecs.umich.edu (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) { 7317639Sgblack@eecs.umich.edu return 1.5; 7327639Sgblack@eecs.umich.edu } 7337639Sgblack@eecs.umich.edu aXb = a*b; 7347639Sgblack@eecs.umich.edu fpClassAxB = std::fpclassify(aXb); 73511321Ssteve.reinhardt@amd.com if (fpClassAxB == FP_SUBNORMAL) { 7367639Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 7377639Sgblack@eecs.umich.edu return 1.5; 7387639Sgblack@eecs.umich.edu } 7397639Sgblack@eecs.umich.edu return (3.0 - (a * b)) / 2.0; 7407639Sgblack@eecs.umich.edu} 7417639Sgblack@eecs.umich.edu 7427639Sgblack@eecs.umich.edustatic inline float 7437639Sgblack@eecs.umich.edufpRecpsS(float a, float b) 7447639Sgblack@eecs.umich.edu{ 7457639Sgblack@eecs.umich.edu int fpClassA = std::fpclassify(a); 7467639Sgblack@eecs.umich.edu int fpClassB = std::fpclassify(b); 7477639Sgblack@eecs.umich.edu float aXb; 7487639Sgblack@eecs.umich.edu int fpClassAxB; 7497639Sgblack@eecs.umich.edu 7507639Sgblack@eecs.umich.edu if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) || 7517639Sgblack@eecs.umich.edu (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) { 7527639Sgblack@eecs.umich.edu return 2.0; 7537639Sgblack@eecs.umich.edu } 7547639Sgblack@eecs.umich.edu aXb = a*b; 7557639Sgblack@eecs.umich.edu fpClassAxB = std::fpclassify(aXb); 75611321Ssteve.reinhardt@amd.com if (fpClassAxB == FP_SUBNORMAL) { 7577639Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 7587639Sgblack@eecs.umich.edu return 2.0; 7597639Sgblack@eecs.umich.edu } 7607639Sgblack@eecs.umich.edu return 2.0 - (a * b); 7617639Sgblack@eecs.umich.edu} 7627639Sgblack@eecs.umich.edu 76310037SARM gem5 Developerstemplate <typename T> 76410037SARM gem5 Developersstatic inline T 76510037SARM gem5 DevelopersroundNEven(T a) { 76610037SARM gem5 Developers T val; 76710037SARM gem5 Developers 76810037SARM gem5 Developers val = round(a); 76910037SARM gem5 Developers if (a - val == 0.5) { 77010037SARM gem5 Developers if ( (((int) a) & 1) == 0 ) val += 1.0; 77110037SARM gem5 Developers } 77210037SARM gem5 Developers else if (a - val == -0.5) { 77310037SARM gem5 Developers if ( (((int) a) & 1) == 0 ) val -= 1.0; 77410037SARM gem5 Developers } 77510037SARM gem5 Developers return val; 77610037SARM gem5 Developers} 77710037SARM gem5 Developers 77810037SARM gem5 Developers 77910037SARM gem5 Developers 7807396Sgblack@eecs.umich.educlass FpOp : public PredOp 7817375Sgblack@eecs.umich.edu{ 7827375Sgblack@eecs.umich.edu protected: 7837396Sgblack@eecs.umich.edu FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 7847396Sgblack@eecs.umich.edu PredOp(mnem, _machInst, __opClass) 7857396Sgblack@eecs.umich.edu {} 7867396Sgblack@eecs.umich.edu 7877396Sgblack@eecs.umich.edu virtual float 7887396Sgblack@eecs.umich.edu doOp(float op1, float op2) const 7897396Sgblack@eecs.umich.edu { 7907396Sgblack@eecs.umich.edu panic("Unimplemented version of doOp called.\n"); 7917396Sgblack@eecs.umich.edu } 7927396Sgblack@eecs.umich.edu 7937396Sgblack@eecs.umich.edu virtual float 7947396Sgblack@eecs.umich.edu doOp(float op1) const 7957396Sgblack@eecs.umich.edu { 7967396Sgblack@eecs.umich.edu panic("Unimplemented version of doOp called.\n"); 7977396Sgblack@eecs.umich.edu } 7987396Sgblack@eecs.umich.edu 7997396Sgblack@eecs.umich.edu virtual double 8007396Sgblack@eecs.umich.edu doOp(double op1, double op2) const 8017396Sgblack@eecs.umich.edu { 8027396Sgblack@eecs.umich.edu panic("Unimplemented version of doOp called.\n"); 8037396Sgblack@eecs.umich.edu } 8047396Sgblack@eecs.umich.edu 8057396Sgblack@eecs.umich.edu virtual double 8067396Sgblack@eecs.umich.edu doOp(double op1) const 8077396Sgblack@eecs.umich.edu { 8087396Sgblack@eecs.umich.edu panic("Unimplemented version of doOp called.\n"); 8097396Sgblack@eecs.umich.edu } 8107396Sgblack@eecs.umich.edu 8117396Sgblack@eecs.umich.edu double 8127396Sgblack@eecs.umich.edu dbl(uint32_t low, uint32_t high) const 8137396Sgblack@eecs.umich.edu { 8147396Sgblack@eecs.umich.edu double junk = 0.0; 8157396Sgblack@eecs.umich.edu return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 8167396Sgblack@eecs.umich.edu } 8177396Sgblack@eecs.umich.edu 8187396Sgblack@eecs.umich.edu uint32_t 8197396Sgblack@eecs.umich.edu dblLow(double val) const 8207396Sgblack@eecs.umich.edu { 8217396Sgblack@eecs.umich.edu return fpToBits(val); 8227396Sgblack@eecs.umich.edu } 8237396Sgblack@eecs.umich.edu 8247396Sgblack@eecs.umich.edu uint32_t 8257396Sgblack@eecs.umich.edu dblHi(double val) const 8267396Sgblack@eecs.umich.edu { 8277396Sgblack@eecs.umich.edu return fpToBits(val) >> 32; 8287396Sgblack@eecs.umich.edu } 8297396Sgblack@eecs.umich.edu 8307396Sgblack@eecs.umich.edu template <class fpType> 8317396Sgblack@eecs.umich.edu fpType 8327639Sgblack@eecs.umich.edu processNans(FPSCR &fpscr, bool &done, bool defaultNan, 8337639Sgblack@eecs.umich.edu fpType op1, fpType op2) const; 8347639Sgblack@eecs.umich.edu 8357639Sgblack@eecs.umich.edu template <class fpType> 8367639Sgblack@eecs.umich.edu fpType 83710037SARM gem5 Developers ternaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType op3, 83810037SARM gem5 Developers fpType (*func)(fpType, fpType, fpType), 83910037SARM gem5 Developers bool flush, bool defaultNan, uint32_t rMode) const; 84010037SARM gem5 Developers 84110037SARM gem5 Developers template <class fpType> 84210037SARM gem5 Developers fpType 8437396Sgblack@eecs.umich.edu binaryOp(FPSCR &fpscr, fpType op1, fpType op2, 8447396Sgblack@eecs.umich.edu fpType (*func)(fpType, fpType), 8457639Sgblack@eecs.umich.edu bool flush, bool defaultNan, uint32_t rMode) const; 8467396Sgblack@eecs.umich.edu 8477396Sgblack@eecs.umich.edu template <class fpType> 8487396Sgblack@eecs.umich.edu fpType 8497396Sgblack@eecs.umich.edu unaryOp(FPSCR &fpscr, fpType op1, 8507396Sgblack@eecs.umich.edu fpType (*func)(fpType), 8517430Sgblack@eecs.umich.edu bool flush, uint32_t rMode) const; 8527720Sgblack@eecs.umich.edu 8537720Sgblack@eecs.umich.edu void 8547720Sgblack@eecs.umich.edu advancePC(PCState &pcState) const 8557720Sgblack@eecs.umich.edu { 8567720Sgblack@eecs.umich.edu if (flags[IsLastMicroop]) { 8577720Sgblack@eecs.umich.edu pcState.uEnd(); 8587720Sgblack@eecs.umich.edu } else if (flags[IsMicroop]) { 8597720Sgblack@eecs.umich.edu pcState.uAdvance(); 8607720Sgblack@eecs.umich.edu } else { 8617720Sgblack@eecs.umich.edu pcState.advance(); 8627720Sgblack@eecs.umich.edu } 8637720Sgblack@eecs.umich.edu } 86410037SARM gem5 Developers 86510037SARM gem5 Developers float 86610037SARM gem5 Developers fpSqrt (FPSCR fpscr,float x) const 86710037SARM gem5 Developers { 86810037SARM gem5 Developers 86910037SARM gem5 Developers return unaryOp(fpscr,x,sqrtf,fpscr.fz,fpscr.rMode); 87010037SARM gem5 Developers 87110037SARM gem5 Developers } 87210037SARM gem5 Developers 87310037SARM gem5 Developers double 87410037SARM gem5 Developers fpSqrt (FPSCR fpscr,double x) const 87510037SARM gem5 Developers { 87610037SARM gem5 Developers 87710037SARM gem5 Developers return unaryOp(fpscr,x,sqrt,fpscr.fz,fpscr.rMode); 87810037SARM gem5 Developers 87910037SARM gem5 Developers } 88010037SARM gem5 Developers}; 88110037SARM gem5 Developers 88210037SARM gem5 Developersclass FpCondCompRegOp : public FpOp 88310037SARM gem5 Developers{ 88410037SARM gem5 Developers protected: 88510037SARM gem5 Developers IntRegIndex op1, op2; 88610037SARM gem5 Developers ConditionCode condCode; 88710037SARM gem5 Developers uint8_t defCc; 88810037SARM gem5 Developers 88910037SARM gem5 Developers FpCondCompRegOp(const char *mnem, ExtMachInst _machInst, 89010037SARM gem5 Developers OpClass __opClass, IntRegIndex _op1, IntRegIndex _op2, 89110037SARM gem5 Developers ConditionCode _condCode, uint8_t _defCc) : 89210037SARM gem5 Developers FpOp(mnem, _machInst, __opClass), 89310037SARM gem5 Developers op1(_op1), op2(_op2), condCode(_condCode), defCc(_defCc) 89410037SARM gem5 Developers {} 89510037SARM gem5 Developers 89612616Sgabeblack@google.com std::string generateDisassembly( 89712616Sgabeblack@google.com Addr pc, const SymbolTable *symtab) const override; 89810037SARM gem5 Developers}; 89910037SARM gem5 Developers 90010037SARM gem5 Developersclass FpCondSelOp : public FpOp 90110037SARM gem5 Developers{ 90210037SARM gem5 Developers protected: 90310037SARM gem5 Developers IntRegIndex dest, op1, op2; 90410037SARM gem5 Developers ConditionCode condCode; 90510037SARM gem5 Developers 90610037SARM gem5 Developers FpCondSelOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 90710037SARM gem5 Developers IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, 90810037SARM gem5 Developers ConditionCode _condCode) : 90910037SARM gem5 Developers FpOp(mnem, _machInst, __opClass), 91010037SARM gem5 Developers dest(_dest), op1(_op1), op2(_op2), condCode(_condCode) 91110037SARM gem5 Developers {} 91210037SARM gem5 Developers 91312616Sgabeblack@google.com std::string generateDisassembly( 91412616Sgabeblack@google.com Addr pc, const SymbolTable *symtab) const override; 9157396Sgblack@eecs.umich.edu}; 9167396Sgblack@eecs.umich.edu 9177396Sgblack@eecs.umich.educlass FpRegRegOp : public FpOp 9187396Sgblack@eecs.umich.edu{ 9197396Sgblack@eecs.umich.edu protected: 9207396Sgblack@eecs.umich.edu IntRegIndex dest; 9217396Sgblack@eecs.umich.edu IntRegIndex op1; 9227396Sgblack@eecs.umich.edu 9237396Sgblack@eecs.umich.edu FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 9247396Sgblack@eecs.umich.edu IntRegIndex _dest, IntRegIndex _op1, 9257396Sgblack@eecs.umich.edu VfpMicroMode mode = VfpNotAMicroop) : 9267396Sgblack@eecs.umich.edu FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1) 9277375Sgblack@eecs.umich.edu { 9287375Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 9297375Sgblack@eecs.umich.edu } 9307396Sgblack@eecs.umich.edu 93112616Sgabeblack@google.com std::string generateDisassembly( 93212616Sgabeblack@google.com Addr pc, const SymbolTable *symtab) const override; 9337375Sgblack@eecs.umich.edu}; 9347375Sgblack@eecs.umich.edu 9357396Sgblack@eecs.umich.educlass FpRegImmOp : public FpOp 9367375Sgblack@eecs.umich.edu{ 9377375Sgblack@eecs.umich.edu protected: 9387396Sgblack@eecs.umich.edu IntRegIndex dest; 9397396Sgblack@eecs.umich.edu uint64_t imm; 9407396Sgblack@eecs.umich.edu 9417396Sgblack@eecs.umich.edu FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 9427396Sgblack@eecs.umich.edu IntRegIndex _dest, uint64_t _imm, 9437396Sgblack@eecs.umich.edu VfpMicroMode mode = VfpNotAMicroop) : 9447396Sgblack@eecs.umich.edu FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm) 9457375Sgblack@eecs.umich.edu { 9467375Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 9477375Sgblack@eecs.umich.edu } 9487396Sgblack@eecs.umich.edu 94912616Sgabeblack@google.com std::string generateDisassembly( 95012616Sgabeblack@google.com Addr pc, const SymbolTable *symtab) const override; 9517375Sgblack@eecs.umich.edu}; 9527375Sgblack@eecs.umich.edu 9537396Sgblack@eecs.umich.educlass FpRegRegImmOp : public FpOp 9547375Sgblack@eecs.umich.edu{ 9557375Sgblack@eecs.umich.edu protected: 9567396Sgblack@eecs.umich.edu IntRegIndex dest; 9577396Sgblack@eecs.umich.edu IntRegIndex op1; 9587396Sgblack@eecs.umich.edu uint64_t imm; 9597396Sgblack@eecs.umich.edu 9607396Sgblack@eecs.umich.edu FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 9617396Sgblack@eecs.umich.edu IntRegIndex _dest, IntRegIndex _op1, 9627396Sgblack@eecs.umich.edu uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : 9637396Sgblack@eecs.umich.edu FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm) 9647375Sgblack@eecs.umich.edu { 9657375Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 9667375Sgblack@eecs.umich.edu } 9677396Sgblack@eecs.umich.edu 96812616Sgabeblack@google.com std::string generateDisassembly( 96912616Sgabeblack@google.com Addr pc, const SymbolTable *symtab) const override; 9707375Sgblack@eecs.umich.edu}; 9717375Sgblack@eecs.umich.edu 9727396Sgblack@eecs.umich.educlass FpRegRegRegOp : public FpOp 9737375Sgblack@eecs.umich.edu{ 9747375Sgblack@eecs.umich.edu protected: 9757396Sgblack@eecs.umich.edu IntRegIndex dest; 9767396Sgblack@eecs.umich.edu IntRegIndex op1; 9777396Sgblack@eecs.umich.edu IntRegIndex op2; 9787396Sgblack@eecs.umich.edu 9797396Sgblack@eecs.umich.edu FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 9807396Sgblack@eecs.umich.edu IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, 9817396Sgblack@eecs.umich.edu VfpMicroMode mode = VfpNotAMicroop) : 9827396Sgblack@eecs.umich.edu FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2) 9837375Sgblack@eecs.umich.edu { 9847375Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 9857375Sgblack@eecs.umich.edu } 9867396Sgblack@eecs.umich.edu 98712616Sgabeblack@google.com std::string generateDisassembly( 98812616Sgabeblack@google.com Addr pc, const SymbolTable *symtab) const override; 9897375Sgblack@eecs.umich.edu}; 9907375Sgblack@eecs.umich.edu 99111671Smitch.hayenga@arm.comclass FpRegRegRegCondOp : public FpOp 99211671Smitch.hayenga@arm.com{ 99311671Smitch.hayenga@arm.com protected: 99411671Smitch.hayenga@arm.com IntRegIndex dest; 99511671Smitch.hayenga@arm.com IntRegIndex op1; 99611671Smitch.hayenga@arm.com IntRegIndex op2; 99711671Smitch.hayenga@arm.com ConditionCode cond; 99811671Smitch.hayenga@arm.com 99911671Smitch.hayenga@arm.com FpRegRegRegCondOp(const char *mnem, ExtMachInst _machInst, 100011671Smitch.hayenga@arm.com OpClass __opClass, IntRegIndex _dest, IntRegIndex _op1, 100111671Smitch.hayenga@arm.com IntRegIndex _op2, ConditionCode _cond, 100211671Smitch.hayenga@arm.com VfpMicroMode mode = VfpNotAMicroop) : 100311671Smitch.hayenga@arm.com FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2), 100411671Smitch.hayenga@arm.com cond(_cond) 100511671Smitch.hayenga@arm.com { 100611671Smitch.hayenga@arm.com setVfpMicroFlags(mode, flags); 100711671Smitch.hayenga@arm.com } 100811671Smitch.hayenga@arm.com 100912616Sgabeblack@google.com std::string generateDisassembly( 101012616Sgabeblack@google.com Addr pc, const SymbolTable *symtab) const override; 101111671Smitch.hayenga@arm.com}; 101211671Smitch.hayenga@arm.com 101310037SARM gem5 Developersclass FpRegRegRegRegOp : public FpOp 101410037SARM gem5 Developers{ 101510037SARM gem5 Developers protected: 101610037SARM gem5 Developers IntRegIndex dest; 101710037SARM gem5 Developers IntRegIndex op1; 101810037SARM gem5 Developers IntRegIndex op2; 101910037SARM gem5 Developers IntRegIndex op3; 102010037SARM gem5 Developers 102110037SARM gem5 Developers FpRegRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 102210037SARM gem5 Developers IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, 102310037SARM gem5 Developers IntRegIndex _op3, VfpMicroMode mode = VfpNotAMicroop) : 102410037SARM gem5 Developers FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2), 102510037SARM gem5 Developers op3(_op3) 102610037SARM gem5 Developers { 102710037SARM gem5 Developers setVfpMicroFlags(mode, flags); 102810037SARM gem5 Developers } 102910037SARM gem5 Developers 103012616Sgabeblack@google.com std::string generateDisassembly( 103112616Sgabeblack@google.com Addr pc, const SymbolTable *symtab) const override; 103210037SARM gem5 Developers}; 103310037SARM gem5 Developers 10347639Sgblack@eecs.umich.educlass FpRegRegRegImmOp : public FpOp 10357639Sgblack@eecs.umich.edu{ 10367639Sgblack@eecs.umich.edu protected: 10377639Sgblack@eecs.umich.edu IntRegIndex dest; 10387639Sgblack@eecs.umich.edu IntRegIndex op1; 10397639Sgblack@eecs.umich.edu IntRegIndex op2; 10407639Sgblack@eecs.umich.edu uint64_t imm; 10417639Sgblack@eecs.umich.edu 10427639Sgblack@eecs.umich.edu FpRegRegRegImmOp(const char *mnem, ExtMachInst _machInst, 10437639Sgblack@eecs.umich.edu OpClass __opClass, IntRegIndex _dest, 10447639Sgblack@eecs.umich.edu IntRegIndex _op1, IntRegIndex _op2, 10457639Sgblack@eecs.umich.edu uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : 10467639Sgblack@eecs.umich.edu FpOp(mnem, _machInst, __opClass), 10477639Sgblack@eecs.umich.edu dest(_dest), op1(_op1), op2(_op2), imm(_imm) 10487639Sgblack@eecs.umich.edu { 10497639Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 10507639Sgblack@eecs.umich.edu } 10517639Sgblack@eecs.umich.edu 105212616Sgabeblack@google.com std::string generateDisassembly( 105312616Sgabeblack@google.com Addr pc, const SymbolTable *symtab) const override; 10547639Sgblack@eecs.umich.edu}; 10557639Sgblack@eecs.umich.edu 10567384Sgblack@eecs.umich.edu} 10577384Sgblack@eecs.umich.edu 10587375Sgblack@eecs.umich.edu#endif //__ARCH_ARM_INSTS_VFP_HH__ 1059