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