vfp.hh revision 7396
17375Sgblack@eecs.umich.edu/*
27375Sgblack@eecs.umich.edu * Copyright (c) 2010 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
437375Sgblack@eecs.umich.edu#include "arch/arm/insts/misc.hh"
447378Sgblack@eecs.umich.edu#include "arch/arm/miscregs.hh"
457378Sgblack@eecs.umich.edu#include <fenv.h>
467382Sgblack@eecs.umich.edu#include <cmath>
477375Sgblack@eecs.umich.edu
487384Sgblack@eecs.umich.edunamespace ArmISA
497384Sgblack@eecs.umich.edu{
507384Sgblack@eecs.umich.edu
517375Sgblack@eecs.umich.eduenum VfpMicroMode {
527375Sgblack@eecs.umich.edu    VfpNotAMicroop,
537375Sgblack@eecs.umich.edu    VfpMicroop,
547375Sgblack@eecs.umich.edu    VfpFirstMicroop,
557375Sgblack@eecs.umich.edu    VfpLastMicroop
567375Sgblack@eecs.umich.edu};
577375Sgblack@eecs.umich.edu
587375Sgblack@eecs.umich.edutemplate<class T>
597375Sgblack@eecs.umich.edustatic inline void
607375Sgblack@eecs.umich.edusetVfpMicroFlags(VfpMicroMode mode, T &flags)
617375Sgblack@eecs.umich.edu{
627375Sgblack@eecs.umich.edu    switch (mode) {
637375Sgblack@eecs.umich.edu      case VfpMicroop:
647375Sgblack@eecs.umich.edu        flags[StaticInst::IsMicroop] = true;
657375Sgblack@eecs.umich.edu        break;
667375Sgblack@eecs.umich.edu      case VfpFirstMicroop:
677375Sgblack@eecs.umich.edu        flags[StaticInst::IsMicroop] =
687375Sgblack@eecs.umich.edu            flags[StaticInst::IsFirstMicroop] = true;
697375Sgblack@eecs.umich.edu        break;
707375Sgblack@eecs.umich.edu      case VfpLastMicroop:
717375Sgblack@eecs.umich.edu        flags[StaticInst::IsMicroop] =
727375Sgblack@eecs.umich.edu            flags[StaticInst::IsLastMicroop] = true;
737375Sgblack@eecs.umich.edu        break;
747375Sgblack@eecs.umich.edu      case VfpNotAMicroop:
757375Sgblack@eecs.umich.edu        break;
767375Sgblack@eecs.umich.edu    }
777376Sgblack@eecs.umich.edu    if (mode == VfpMicroop || mode == VfpFirstMicroop) {
787376Sgblack@eecs.umich.edu        flags[StaticInst::IsDelayedCommit] = true;
797376Sgblack@eecs.umich.edu    }
807375Sgblack@eecs.umich.edu}
817375Sgblack@eecs.umich.edu
827378Sgblack@eecs.umich.eduenum FeExceptionBit
837378Sgblack@eecs.umich.edu{
847378Sgblack@eecs.umich.edu    FeDivByZero = FE_DIVBYZERO,
857378Sgblack@eecs.umich.edu    FeInexact = FE_INEXACT,
867378Sgblack@eecs.umich.edu    FeInvalid = FE_INVALID,
877378Sgblack@eecs.umich.edu    FeOverflow = FE_OVERFLOW,
887378Sgblack@eecs.umich.edu    FeUnderflow = FE_UNDERFLOW,
897378Sgblack@eecs.umich.edu    FeAllExceptions = FE_ALL_EXCEPT
907378Sgblack@eecs.umich.edu};
917378Sgblack@eecs.umich.edu
927378Sgblack@eecs.umich.eduenum FeRoundingMode
937378Sgblack@eecs.umich.edu{
947378Sgblack@eecs.umich.edu    FeRoundDown = FE_DOWNWARD,
957378Sgblack@eecs.umich.edu    FeRoundNearest = FE_TONEAREST,
967378Sgblack@eecs.umich.edu    FeRoundZero = FE_TOWARDZERO,
977378Sgblack@eecs.umich.edu    FeRoundUpward = FE_UPWARD
987378Sgblack@eecs.umich.edu};
997378Sgblack@eecs.umich.edu
1007378Sgblack@eecs.umich.eduenum VfpRoundingMode
1017378Sgblack@eecs.umich.edu{
1027378Sgblack@eecs.umich.edu    VfpRoundNearest = 0,
1037378Sgblack@eecs.umich.edu    VfpRoundUpward = 1,
1047378Sgblack@eecs.umich.edu    VfpRoundDown = 2,
1057378Sgblack@eecs.umich.edu    VfpRoundZero = 3
1067378Sgblack@eecs.umich.edu};
1077378Sgblack@eecs.umich.edu
1087382Sgblack@eecs.umich.edutemplate <class fpType>
1097382Sgblack@eecs.umich.edustatic inline void
1107382Sgblack@eecs.umich.eduvfpFlushToZero(uint32_t &_fpscr, fpType &op)
1117382Sgblack@eecs.umich.edu{
1127382Sgblack@eecs.umich.edu    FPSCR fpscr = _fpscr;
1137396Sgblack@eecs.umich.edu    fpType junk = 0.0;
1147382Sgblack@eecs.umich.edu    if (fpscr.fz == 1 && (std::fpclassify(op) == FP_SUBNORMAL)) {
1157382Sgblack@eecs.umich.edu        fpscr.idc = 1;
1167396Sgblack@eecs.umich.edu        uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
1177396Sgblack@eecs.umich.edu        op = bitsToFp(fpToBits(op) & bitMask, junk);
1187382Sgblack@eecs.umich.edu    }
1197382Sgblack@eecs.umich.edu    _fpscr = fpscr;
1207382Sgblack@eecs.umich.edu}
1217382Sgblack@eecs.umich.edu
1227382Sgblack@eecs.umich.edutemplate <class fpType>
1237382Sgblack@eecs.umich.edustatic inline void
1247382Sgblack@eecs.umich.eduvfpFlushToZero(uint32_t &fpscr, fpType &op1, fpType &op2)
1257382Sgblack@eecs.umich.edu{
1267382Sgblack@eecs.umich.edu    vfpFlushToZero(fpscr, op1);
1277382Sgblack@eecs.umich.edu    vfpFlushToZero(fpscr, op2);
1287382Sgblack@eecs.umich.edu}
1297382Sgblack@eecs.umich.edu
1307396Sgblack@eecs.umich.edutemplate <class fpType>
1317396Sgblack@eecs.umich.edustatic inline bool
1327396Sgblack@eecs.umich.eduflushToZero(fpType &op)
1337396Sgblack@eecs.umich.edu{
1347396Sgblack@eecs.umich.edu    fpType junk = 0.0;
1357396Sgblack@eecs.umich.edu    if (std::fpclassify(op) == FP_SUBNORMAL) {
1367396Sgblack@eecs.umich.edu        uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
1377396Sgblack@eecs.umich.edu        op = bitsToFp(fpToBits(op) & bitMask, junk);
1387396Sgblack@eecs.umich.edu        return true;
1397396Sgblack@eecs.umich.edu    }
1407396Sgblack@eecs.umich.edu    return false;
1417396Sgblack@eecs.umich.edu}
1427396Sgblack@eecs.umich.edu
1437396Sgblack@eecs.umich.edutemplate <class fpType>
1447396Sgblack@eecs.umich.edustatic inline bool
1457396Sgblack@eecs.umich.eduflushToZero(fpType &op1, fpType &op2)
1467396Sgblack@eecs.umich.edu{
1477396Sgblack@eecs.umich.edu    bool flush1 = flushToZero(op1);
1487396Sgblack@eecs.umich.edu    bool flush2 = flushToZero(op2);
1497396Sgblack@eecs.umich.edu    return flush1 || flush2;
1507396Sgblack@eecs.umich.edu}
1517396Sgblack@eecs.umich.edu
1527384Sgblack@eecs.umich.edustatic inline uint32_t
1537384Sgblack@eecs.umich.edufpToBits(float fp)
1547384Sgblack@eecs.umich.edu{
1557384Sgblack@eecs.umich.edu    union
1567384Sgblack@eecs.umich.edu    {
1577384Sgblack@eecs.umich.edu        float fp;
1587384Sgblack@eecs.umich.edu        uint32_t bits;
1597384Sgblack@eecs.umich.edu    } val;
1607384Sgblack@eecs.umich.edu    val.fp = fp;
1617384Sgblack@eecs.umich.edu    return val.bits;
1627384Sgblack@eecs.umich.edu}
1637384Sgblack@eecs.umich.edu
1647384Sgblack@eecs.umich.edustatic inline uint64_t
1657384Sgblack@eecs.umich.edufpToBits(double fp)
1667384Sgblack@eecs.umich.edu{
1677384Sgblack@eecs.umich.edu    union
1687384Sgblack@eecs.umich.edu    {
1697384Sgblack@eecs.umich.edu        double fp;
1707384Sgblack@eecs.umich.edu        uint64_t bits;
1717384Sgblack@eecs.umich.edu    } val;
1727384Sgblack@eecs.umich.edu    val.fp = fp;
1737384Sgblack@eecs.umich.edu    return val.bits;
1747384Sgblack@eecs.umich.edu}
1757384Sgblack@eecs.umich.edu
1767384Sgblack@eecs.umich.edustatic inline float
1777384Sgblack@eecs.umich.edubitsToFp(uint64_t bits, float junk)
1787384Sgblack@eecs.umich.edu{
1797384Sgblack@eecs.umich.edu    union
1807384Sgblack@eecs.umich.edu    {
1817384Sgblack@eecs.umich.edu        float fp;
1827384Sgblack@eecs.umich.edu        uint32_t bits;
1837384Sgblack@eecs.umich.edu    } val;
1847384Sgblack@eecs.umich.edu    val.bits = bits;
1857384Sgblack@eecs.umich.edu    return val.fp;
1867384Sgblack@eecs.umich.edu}
1877384Sgblack@eecs.umich.edu
1887384Sgblack@eecs.umich.edustatic inline double
1897384Sgblack@eecs.umich.edubitsToFp(uint64_t bits, double junk)
1907384Sgblack@eecs.umich.edu{
1917384Sgblack@eecs.umich.edu    union
1927384Sgblack@eecs.umich.edu    {
1937384Sgblack@eecs.umich.edu        double fp;
1947384Sgblack@eecs.umich.edu        uint64_t bits;
1957384Sgblack@eecs.umich.edu    } val;
1967384Sgblack@eecs.umich.edu    val.bits = bits;
1977384Sgblack@eecs.umich.edu    return val.fp;
1987384Sgblack@eecs.umich.edu}
1997384Sgblack@eecs.umich.edu
2007396Sgblack@eecs.umich.edutypedef int VfpSavedState;
2017396Sgblack@eecs.umich.edu
2027396Sgblack@eecs.umich.edustatic inline VfpSavedState
2037396Sgblack@eecs.umich.eduprepVfpFpscr(FPSCR fpscr)
2047396Sgblack@eecs.umich.edu{
2057396Sgblack@eecs.umich.edu    int roundingMode = fegetround();
2067396Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
2077396Sgblack@eecs.umich.edu    switch (fpscr.rMode) {
2087396Sgblack@eecs.umich.edu      case VfpRoundNearest:
2097396Sgblack@eecs.umich.edu        fesetround(FeRoundNearest);
2107396Sgblack@eecs.umich.edu        break;
2117396Sgblack@eecs.umich.edu      case VfpRoundUpward:
2127396Sgblack@eecs.umich.edu        fesetround(FeRoundUpward);
2137396Sgblack@eecs.umich.edu        break;
2147396Sgblack@eecs.umich.edu      case VfpRoundDown:
2157396Sgblack@eecs.umich.edu        fesetround(FeRoundDown);
2167396Sgblack@eecs.umich.edu        break;
2177396Sgblack@eecs.umich.edu      case VfpRoundZero:
2187396Sgblack@eecs.umich.edu        fesetround(FeRoundZero);
2197396Sgblack@eecs.umich.edu        break;
2207396Sgblack@eecs.umich.edu    }
2217396Sgblack@eecs.umich.edu    return roundingMode;
2227396Sgblack@eecs.umich.edu}
2237396Sgblack@eecs.umich.edu
2247396Sgblack@eecs.umich.edustatic inline VfpSavedState
2257396Sgblack@eecs.umich.eduprepFpState(uint32_t rMode)
2267396Sgblack@eecs.umich.edu{
2277396Sgblack@eecs.umich.edu    int roundingMode = fegetround();
2287396Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
2297396Sgblack@eecs.umich.edu    switch (rMode) {
2307396Sgblack@eecs.umich.edu      case VfpRoundNearest:
2317396Sgblack@eecs.umich.edu        fesetround(FeRoundNearest);
2327396Sgblack@eecs.umich.edu        break;
2337396Sgblack@eecs.umich.edu      case VfpRoundUpward:
2347396Sgblack@eecs.umich.edu        fesetround(FeRoundUpward);
2357396Sgblack@eecs.umich.edu        break;
2367396Sgblack@eecs.umich.edu      case VfpRoundDown:
2377396Sgblack@eecs.umich.edu        fesetround(FeRoundDown);
2387396Sgblack@eecs.umich.edu        break;
2397396Sgblack@eecs.umich.edu      case VfpRoundZero:
2407396Sgblack@eecs.umich.edu        fesetround(FeRoundZero);
2417396Sgblack@eecs.umich.edu        break;
2427396Sgblack@eecs.umich.edu    }
2437396Sgblack@eecs.umich.edu    return roundingMode;
2447396Sgblack@eecs.umich.edu}
2457396Sgblack@eecs.umich.edu
2467396Sgblack@eecs.umich.edustatic inline FPSCR
2477396Sgblack@eecs.umich.edusetVfpFpscr(FPSCR fpscr, VfpSavedState state)
2487396Sgblack@eecs.umich.edu{
2497396Sgblack@eecs.umich.edu    int exceptions = fetestexcept(FeAllExceptions);
2507396Sgblack@eecs.umich.edu    if (exceptions & FeInvalid) {
2517396Sgblack@eecs.umich.edu        fpscr.ioc = 1;
2527396Sgblack@eecs.umich.edu    }
2537396Sgblack@eecs.umich.edu    if (exceptions & FeDivByZero) {
2547396Sgblack@eecs.umich.edu        fpscr.dzc = 1;
2557396Sgblack@eecs.umich.edu    }
2567396Sgblack@eecs.umich.edu    if (exceptions & FeOverflow) {
2577396Sgblack@eecs.umich.edu        fpscr.ofc = 1;
2587396Sgblack@eecs.umich.edu    }
2597396Sgblack@eecs.umich.edu    if (exceptions & FeUnderflow) {
2607396Sgblack@eecs.umich.edu        fpscr.ufc = 1;
2617396Sgblack@eecs.umich.edu    }
2627396Sgblack@eecs.umich.edu    if (exceptions & FeInexact) {
2637396Sgblack@eecs.umich.edu        fpscr.ixc = 1;
2647396Sgblack@eecs.umich.edu    }
2657396Sgblack@eecs.umich.edu    fesetround(state);
2667396Sgblack@eecs.umich.edu    return fpscr;
2677396Sgblack@eecs.umich.edu}
2687396Sgblack@eecs.umich.edu
2697396Sgblack@eecs.umich.edustatic inline void
2707396Sgblack@eecs.umich.edufinishVfp(FPSCR &fpscr, VfpSavedState state)
2717396Sgblack@eecs.umich.edu{
2727396Sgblack@eecs.umich.edu    int exceptions = fetestexcept(FeAllExceptions);
2737396Sgblack@eecs.umich.edu    bool underflow = false;
2747396Sgblack@eecs.umich.edu    if (exceptions & FeInvalid) {
2757396Sgblack@eecs.umich.edu        fpscr.ioc = 1;
2767396Sgblack@eecs.umich.edu    }
2777396Sgblack@eecs.umich.edu    if (exceptions & FeDivByZero) {
2787396Sgblack@eecs.umich.edu        fpscr.dzc = 1;
2797396Sgblack@eecs.umich.edu    }
2807396Sgblack@eecs.umich.edu    if (exceptions & FeOverflow) {
2817396Sgblack@eecs.umich.edu        fpscr.ofc = 1;
2827396Sgblack@eecs.umich.edu    }
2837396Sgblack@eecs.umich.edu    if (exceptions & FeUnderflow) {
2847396Sgblack@eecs.umich.edu        underflow = true;
2857396Sgblack@eecs.umich.edu        fpscr.ufc = 1;
2867396Sgblack@eecs.umich.edu    }
2877396Sgblack@eecs.umich.edu    if ((exceptions & FeInexact) && !(underflow && fpscr.fz)) {
2887396Sgblack@eecs.umich.edu        fpscr.ixc = 1;
2897396Sgblack@eecs.umich.edu    }
2907396Sgblack@eecs.umich.edu    fesetround(state);
2917396Sgblack@eecs.umich.edu}
2927396Sgblack@eecs.umich.edu
2937384Sgblack@eecs.umich.edutemplate <class fpType>
2947384Sgblack@eecs.umich.edustatic inline fpType
2957386Sgblack@eecs.umich.edufixDest(FPSCR fpscr, fpType val, fpType op1)
2967386Sgblack@eecs.umich.edu{
2977386Sgblack@eecs.umich.edu    int fpClass = std::fpclassify(val);
2987386Sgblack@eecs.umich.edu    fpType junk = 0.0;
2997386Sgblack@eecs.umich.edu    if (fpClass == FP_NAN) {
3007386Sgblack@eecs.umich.edu        const bool single = (sizeof(val) == sizeof(float));
3017386Sgblack@eecs.umich.edu        const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000);
3027386Sgblack@eecs.umich.edu        const bool nan = std::isnan(op1);
3037386Sgblack@eecs.umich.edu        if (!nan || (fpscr.dn == 1)) {
3047386Sgblack@eecs.umich.edu            val = bitsToFp(qnan, junk);
3057386Sgblack@eecs.umich.edu        } else if (nan) {
3067386Sgblack@eecs.umich.edu            val = bitsToFp(fpToBits(op1) | qnan, junk);
3077386Sgblack@eecs.umich.edu        }
3087386Sgblack@eecs.umich.edu    } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) {
3097386Sgblack@eecs.umich.edu        // Turn val into a zero with the correct sign;
3107386Sgblack@eecs.umich.edu        uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
3117386Sgblack@eecs.umich.edu        val = bitsToFp(fpToBits(val) & bitMask, junk);
3127396Sgblack@eecs.umich.edu        feclearexcept(FeInexact);
3137386Sgblack@eecs.umich.edu        feraiseexcept(FeUnderflow);
3147386Sgblack@eecs.umich.edu    }
3157386Sgblack@eecs.umich.edu    return val;
3167386Sgblack@eecs.umich.edu}
3177386Sgblack@eecs.umich.edu
3187386Sgblack@eecs.umich.edutemplate <class fpType>
3197386Sgblack@eecs.umich.edustatic inline fpType
3207385Sgblack@eecs.umich.edufixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2)
3217384Sgblack@eecs.umich.edu{
3227385Sgblack@eecs.umich.edu    int fpClass = std::fpclassify(val);
3237385Sgblack@eecs.umich.edu    fpType junk = 0.0;
3247385Sgblack@eecs.umich.edu    if (fpClass == FP_NAN) {
3257384Sgblack@eecs.umich.edu        const bool single = (sizeof(val) == sizeof(float));
3267384Sgblack@eecs.umich.edu        const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000);
3277384Sgblack@eecs.umich.edu        const bool nan1 = std::isnan(op1);
3287384Sgblack@eecs.umich.edu        const bool nan2 = std::isnan(op2);
3297384Sgblack@eecs.umich.edu        const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan);
3307384Sgblack@eecs.umich.edu        const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan);
3317384Sgblack@eecs.umich.edu        if ((!nan1 && !nan2) || (fpscr.dn == 1)) {
3327384Sgblack@eecs.umich.edu            val = bitsToFp(qnan, junk);
3337384Sgblack@eecs.umich.edu        } else if (signal1) {
3347384Sgblack@eecs.umich.edu            val = bitsToFp(fpToBits(op1) | qnan, junk);
3357384Sgblack@eecs.umich.edu        } else if (signal2) {
3367384Sgblack@eecs.umich.edu            val = bitsToFp(fpToBits(op2) | qnan, junk);
3377384Sgblack@eecs.umich.edu        } else if (nan1) {
3387384Sgblack@eecs.umich.edu            val = op1;
3397384Sgblack@eecs.umich.edu        } else if (nan2) {
3407384Sgblack@eecs.umich.edu            val = op2;
3417384Sgblack@eecs.umich.edu        }
3427385Sgblack@eecs.umich.edu    } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) {
3437385Sgblack@eecs.umich.edu        // Turn val into a zero with the correct sign;
3447385Sgblack@eecs.umich.edu        uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
3457385Sgblack@eecs.umich.edu        val = bitsToFp(fpToBits(val) & bitMask, junk);
3467396Sgblack@eecs.umich.edu        feclearexcept(FeInexact);
3477385Sgblack@eecs.umich.edu        feraiseexcept(FeUnderflow);
3487384Sgblack@eecs.umich.edu    }
3497384Sgblack@eecs.umich.edu    return val;
3507384Sgblack@eecs.umich.edu}
3517384Sgblack@eecs.umich.edu
3527386Sgblack@eecs.umich.edutemplate <class fpType>
3537386Sgblack@eecs.umich.edustatic inline fpType
3547386Sgblack@eecs.umich.edufixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2)
3557386Sgblack@eecs.umich.edu{
3567386Sgblack@eecs.umich.edu    fpType mid = fixDest(fpscr, val, op1, op2);
3577386Sgblack@eecs.umich.edu    const bool single = (sizeof(fpType) == sizeof(float));
3587386Sgblack@eecs.umich.edu    const fpType junk = 0.0;
3597386Sgblack@eecs.umich.edu    if ((single && (val == bitsToFp(0x00800000, junk) ||
3607386Sgblack@eecs.umich.edu                    val == bitsToFp(0x80800000, junk))) ||
3617386Sgblack@eecs.umich.edu        (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) ||
3627386Sgblack@eecs.umich.edu                     val == bitsToFp(ULL(0x8010000000000000), junk)))
3637386Sgblack@eecs.umich.edu        ) {
3647386Sgblack@eecs.umich.edu        __asm__ __volatile__("" : "=m" (op1) : "m" (op1));
3657386Sgblack@eecs.umich.edu        fesetround(FeRoundZero);
3667386Sgblack@eecs.umich.edu        fpType temp = 0.0;
3677386Sgblack@eecs.umich.edu        __asm__ __volatile__("" : "=m" (temp) : "m" (temp));
3687386Sgblack@eecs.umich.edu        temp = op1 / op2;
3697396Sgblack@eecs.umich.edu        if (flushToZero(temp)) {
3707386Sgblack@eecs.umich.edu            feraiseexcept(FeUnderflow);
3717396Sgblack@eecs.umich.edu            if (fpscr.fz) {
3727396Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3737396Sgblack@eecs.umich.edu                mid = temp;
3747396Sgblack@eecs.umich.edu            }
3757386Sgblack@eecs.umich.edu        }
3767386Sgblack@eecs.umich.edu        __asm__ __volatile__("" :: "m" (temp));
3777386Sgblack@eecs.umich.edu    }
3787386Sgblack@eecs.umich.edu    return mid;
3797386Sgblack@eecs.umich.edu}
3807386Sgblack@eecs.umich.edu
3817386Sgblack@eecs.umich.edustatic inline float
3827386Sgblack@eecs.umich.edufixFpDFpSDest(FPSCR fpscr, double val)
3837386Sgblack@eecs.umich.edu{
3847386Sgblack@eecs.umich.edu    const float junk = 0.0;
3857386Sgblack@eecs.umich.edu    float op1 = 0.0;
3867386Sgblack@eecs.umich.edu    if (std::isnan(val)) {
3877386Sgblack@eecs.umich.edu        uint64_t valBits = fpToBits(val);
3887386Sgblack@eecs.umich.edu        uint32_t op1Bits = bits(valBits, 50, 29) |
3897386Sgblack@eecs.umich.edu                           (mask(9) << 22) |
3907386Sgblack@eecs.umich.edu                           (bits(valBits, 63) << 31);
3917386Sgblack@eecs.umich.edu        op1 = bitsToFp(op1Bits, junk);
3927386Sgblack@eecs.umich.edu    }
3937386Sgblack@eecs.umich.edu    float mid = fixDest(fpscr, (float)val, op1);
3947396Sgblack@eecs.umich.edu    if (fpscr.fz && fetestexcept(FeUnderflow | FeInexact) ==
3957396Sgblack@eecs.umich.edu                    (FeUnderflow | FeInexact)) {
3967396Sgblack@eecs.umich.edu        feclearexcept(FeInexact);
3977396Sgblack@eecs.umich.edu    }
3987386Sgblack@eecs.umich.edu    if (mid == bitsToFp(0x00800000, junk) ||
3997386Sgblack@eecs.umich.edu        mid == bitsToFp(0x80800000, junk)) {
4007386Sgblack@eecs.umich.edu        __asm__ __volatile__("" : "=m" (val) : "m" (val));
4017386Sgblack@eecs.umich.edu        fesetround(FeRoundZero);
4027386Sgblack@eecs.umich.edu        float temp = 0.0;
4037386Sgblack@eecs.umich.edu        __asm__ __volatile__("" : "=m" (temp) : "m" (temp));
4047386Sgblack@eecs.umich.edu        temp = val;
4057396Sgblack@eecs.umich.edu        if (flushToZero(temp)) {
4067386Sgblack@eecs.umich.edu            feraiseexcept(FeUnderflow);
4077396Sgblack@eecs.umich.edu            if (fpscr.fz) {
4087396Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
4097396Sgblack@eecs.umich.edu                mid = temp;
4107396Sgblack@eecs.umich.edu            }
4117386Sgblack@eecs.umich.edu        }
4127386Sgblack@eecs.umich.edu        __asm__ __volatile__("" :: "m" (temp));
4137386Sgblack@eecs.umich.edu    }
4147386Sgblack@eecs.umich.edu    return mid;
4157386Sgblack@eecs.umich.edu}
4167386Sgblack@eecs.umich.edu
4177396Sgblack@eecs.umich.edustatic inline double
4187396Sgblack@eecs.umich.edufixFpSFpDDest(FPSCR fpscr, float val)
4197396Sgblack@eecs.umich.edu{
4207396Sgblack@eecs.umich.edu    const double junk = 0.0;
4217396Sgblack@eecs.umich.edu    double op1 = 0.0;
4227396Sgblack@eecs.umich.edu    if (std::isnan(val)) {
4237396Sgblack@eecs.umich.edu        uint32_t valBits = fpToBits(val);
4247396Sgblack@eecs.umich.edu        uint64_t op1Bits = ((uint64_t)bits(valBits, 21, 0) << 29) |
4257396Sgblack@eecs.umich.edu                           (mask(12) << 51) |
4267396Sgblack@eecs.umich.edu                           ((uint64_t)bits(valBits, 31) << 63);
4277396Sgblack@eecs.umich.edu        op1 = bitsToFp(op1Bits, junk);
4287396Sgblack@eecs.umich.edu    }
4297396Sgblack@eecs.umich.edu    double mid = fixDest(fpscr, (double)val, op1);
4307396Sgblack@eecs.umich.edu    if (mid == bitsToFp(ULL(0x0010000000000000), junk) ||
4317396Sgblack@eecs.umich.edu        mid == bitsToFp(ULL(0x8010000000000000), junk)) {
4327396Sgblack@eecs.umich.edu        __asm__ __volatile__("" : "=m" (val) : "m" (val));
4337396Sgblack@eecs.umich.edu        fesetround(FeRoundZero);
4347396Sgblack@eecs.umich.edu        double temp = 0.0;
4357396Sgblack@eecs.umich.edu        __asm__ __volatile__("" : "=m" (temp) : "m" (temp));
4367396Sgblack@eecs.umich.edu        temp = val;
4377396Sgblack@eecs.umich.edu        if (flushToZero(temp)) {
4387396Sgblack@eecs.umich.edu            feraiseexcept(FeUnderflow);
4397396Sgblack@eecs.umich.edu            if (fpscr.fz) {
4407396Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
4417396Sgblack@eecs.umich.edu                mid = temp;
4427396Sgblack@eecs.umich.edu            }
4437396Sgblack@eecs.umich.edu        }
4447396Sgblack@eecs.umich.edu        __asm__ __volatile__("" :: "m" (temp));
4457396Sgblack@eecs.umich.edu    }
4467396Sgblack@eecs.umich.edu    return mid;
4477396Sgblack@eecs.umich.edu}
4487396Sgblack@eecs.umich.edu
4497396Sgblack@eecs.umich.edustatic inline double
4507396Sgblack@eecs.umich.edumakeDouble(uint32_t low, uint32_t high)
4517396Sgblack@eecs.umich.edu{
4527396Sgblack@eecs.umich.edu    double junk = 0.0;
4537396Sgblack@eecs.umich.edu    return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
4547396Sgblack@eecs.umich.edu}
4557396Sgblack@eecs.umich.edu
4567396Sgblack@eecs.umich.edustatic inline uint32_t
4577396Sgblack@eecs.umich.edulowFromDouble(double val)
4587396Sgblack@eecs.umich.edu{
4597396Sgblack@eecs.umich.edu    return fpToBits(val);
4607396Sgblack@eecs.umich.edu}
4617396Sgblack@eecs.umich.edu
4627396Sgblack@eecs.umich.edustatic inline uint32_t
4637396Sgblack@eecs.umich.eduhighFromDouble(double val)
4647396Sgblack@eecs.umich.edu{
4657396Sgblack@eecs.umich.edu    return fpToBits(val) >> 32;
4667396Sgblack@eecs.umich.edu}
4677396Sgblack@eecs.umich.edu
4687379Sgblack@eecs.umich.edustatic inline uint64_t
4697388Sgblack@eecs.umich.eduvfpFpSToFixed(float val, bool isSigned, bool half,
4707388Sgblack@eecs.umich.edu              uint8_t imm, bool rzero = true)
4717379Sgblack@eecs.umich.edu{
4727396Sgblack@eecs.umich.edu    int rmode = rzero ? FeRoundZero : fegetround();
4737396Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (rmode) : "m" (rmode));
4747388Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
4757379Sgblack@eecs.umich.edu    val = val * powf(2.0, imm);
4767379Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (val) : "m" (val));
4777396Sgblack@eecs.umich.edu    fesetround(rmode);
4787379Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
4797382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (val) : "m" (val));
4807382Sgblack@eecs.umich.edu    float origVal = val;
4817382Sgblack@eecs.umich.edu    val = rintf(val);
4827382Sgblack@eecs.umich.edu    int fpType = std::fpclassify(val);
4837382Sgblack@eecs.umich.edu    if (fpType == FP_SUBNORMAL || fpType == FP_NAN) {
4847382Sgblack@eecs.umich.edu        if (fpType == FP_NAN) {
4857382Sgblack@eecs.umich.edu            feraiseexcept(FeInvalid);
4867382Sgblack@eecs.umich.edu        }
4877382Sgblack@eecs.umich.edu        val = 0.0;
4887382Sgblack@eecs.umich.edu    } else if (origVal != val) {
4897396Sgblack@eecs.umich.edu        switch (rmode) {
4907396Sgblack@eecs.umich.edu          case FeRoundNearest:
4917396Sgblack@eecs.umich.edu            if (origVal - val > 0.5)
4927396Sgblack@eecs.umich.edu                val += 1.0;
4937396Sgblack@eecs.umich.edu            else if (val - origVal > 0.5)
4947396Sgblack@eecs.umich.edu                val -= 1.0;
4957396Sgblack@eecs.umich.edu            break;
4967396Sgblack@eecs.umich.edu          case FeRoundDown:
4977396Sgblack@eecs.umich.edu            if (origVal < val)
4987396Sgblack@eecs.umich.edu                val -= 1.0;
4997396Sgblack@eecs.umich.edu            break;
5007396Sgblack@eecs.umich.edu          case FeRoundUpward:
5017396Sgblack@eecs.umich.edu            if (origVal > val)
5027396Sgblack@eecs.umich.edu                val += 1.0;
5037396Sgblack@eecs.umich.edu            break;
5047396Sgblack@eecs.umich.edu        }
5057382Sgblack@eecs.umich.edu        feraiseexcept(FeInexact);
5067382Sgblack@eecs.umich.edu    }
5077382Sgblack@eecs.umich.edu
5087379Sgblack@eecs.umich.edu    if (isSigned) {
5097379Sgblack@eecs.umich.edu        if (half) {
5107381Sgblack@eecs.umich.edu            if ((double)val < (int16_t)(1 << 15)) {
5117379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
5127382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
5137379Sgblack@eecs.umich.edu                return (int16_t)(1 << 15);
5147379Sgblack@eecs.umich.edu            }
5157381Sgblack@eecs.umich.edu            if ((double)val > (int16_t)mask(15)) {
5167379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
5177382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
5187379Sgblack@eecs.umich.edu                return (int16_t)mask(15);
5197379Sgblack@eecs.umich.edu            }
5207379Sgblack@eecs.umich.edu            return (int16_t)val;
5217379Sgblack@eecs.umich.edu        } else {
5227381Sgblack@eecs.umich.edu            if ((double)val < (int32_t)(1 << 31)) {
5237379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
5247382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
5257379Sgblack@eecs.umich.edu                return (int32_t)(1 << 31);
5267379Sgblack@eecs.umich.edu            }
5277381Sgblack@eecs.umich.edu            if ((double)val > (int32_t)mask(31)) {
5287379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
5297382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
5307379Sgblack@eecs.umich.edu                return (int32_t)mask(31);
5317379Sgblack@eecs.umich.edu            }
5327379Sgblack@eecs.umich.edu            return (int32_t)val;
5337379Sgblack@eecs.umich.edu        }
5347379Sgblack@eecs.umich.edu    } else {
5357379Sgblack@eecs.umich.edu        if (half) {
5367381Sgblack@eecs.umich.edu            if ((double)val < 0) {
5377379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
5387382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
5397379Sgblack@eecs.umich.edu                return 0;
5407379Sgblack@eecs.umich.edu            }
5417381Sgblack@eecs.umich.edu            if ((double)val > (mask(16))) {
5427379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
5437382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
5447379Sgblack@eecs.umich.edu                return mask(16);
5457379Sgblack@eecs.umich.edu            }
5467379Sgblack@eecs.umich.edu            return (uint16_t)val;
5477379Sgblack@eecs.umich.edu        } else {
5487381Sgblack@eecs.umich.edu            if ((double)val < 0) {
5497379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
5507382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
5517379Sgblack@eecs.umich.edu                return 0;
5527379Sgblack@eecs.umich.edu            }
5537381Sgblack@eecs.umich.edu            if ((double)val > (mask(32))) {
5547379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
5557382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
5567379Sgblack@eecs.umich.edu                return mask(32);
5577379Sgblack@eecs.umich.edu            }
5587379Sgblack@eecs.umich.edu            return (uint32_t)val;
5597379Sgblack@eecs.umich.edu        }
5607379Sgblack@eecs.umich.edu    }
5617379Sgblack@eecs.umich.edu}
5627379Sgblack@eecs.umich.edu
5637379Sgblack@eecs.umich.edustatic inline float
5647386Sgblack@eecs.umich.eduvfpUFixedToFpS(FPSCR fpscr, uint32_t val, bool half, uint8_t imm)
5657379Sgblack@eecs.umich.edu{
5667379Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
5677379Sgblack@eecs.umich.edu    if (half)
5687379Sgblack@eecs.umich.edu        val = (uint16_t)val;
5697382Sgblack@eecs.umich.edu    float scale = powf(2.0, imm);
5707382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
5717382Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
5727382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
5737386Sgblack@eecs.umich.edu    return fixDivDest(fpscr, val / scale, (float)val, scale);
5747379Sgblack@eecs.umich.edu}
5757379Sgblack@eecs.umich.edu
5767379Sgblack@eecs.umich.edustatic inline float
5777386Sgblack@eecs.umich.eduvfpSFixedToFpS(FPSCR fpscr, int32_t val, bool half, uint8_t imm)
5787379Sgblack@eecs.umich.edu{
5797379Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
5807379Sgblack@eecs.umich.edu    if (half)
5817379Sgblack@eecs.umich.edu        val = sext<16>(val & mask(16));
5827382Sgblack@eecs.umich.edu    float scale = powf(2.0, imm);
5837382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
5847382Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
5857382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
5867386Sgblack@eecs.umich.edu    return fixDivDest(fpscr, val / scale, (float)val, scale);
5877379Sgblack@eecs.umich.edu}
5887379Sgblack@eecs.umich.edu
5897379Sgblack@eecs.umich.edustatic inline uint64_t
5907388Sgblack@eecs.umich.eduvfpFpDToFixed(double val, bool isSigned, bool half,
5917388Sgblack@eecs.umich.edu              uint8_t imm, bool rzero = true)
5927379Sgblack@eecs.umich.edu{
5937396Sgblack@eecs.umich.edu    int rmode = rzero ? FeRoundZero : fegetround();
5947382Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
5957379Sgblack@eecs.umich.edu    val = val * pow(2.0, imm);
5967379Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (val) : "m" (val));
5977396Sgblack@eecs.umich.edu    fesetround(rmode);
5987379Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
5997382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (val) : "m" (val));
6007382Sgblack@eecs.umich.edu    double origVal = val;
6017382Sgblack@eecs.umich.edu    val = rint(val);
6027382Sgblack@eecs.umich.edu    int fpType = std::fpclassify(val);
6037382Sgblack@eecs.umich.edu    if (fpType == FP_SUBNORMAL || fpType == FP_NAN) {
6047382Sgblack@eecs.umich.edu        if (fpType == FP_NAN) {
6057382Sgblack@eecs.umich.edu            feraiseexcept(FeInvalid);
6067382Sgblack@eecs.umich.edu        }
6077382Sgblack@eecs.umich.edu        val = 0.0;
6087382Sgblack@eecs.umich.edu    } else if (origVal != val) {
6097396Sgblack@eecs.umich.edu        switch (rmode) {
6107396Sgblack@eecs.umich.edu          case FeRoundNearest:
6117396Sgblack@eecs.umich.edu            if (origVal - val > 0.5)
6127396Sgblack@eecs.umich.edu                val += 1.0;
6137396Sgblack@eecs.umich.edu            else if (val - origVal > 0.5)
6147396Sgblack@eecs.umich.edu                val -= 1.0;
6157396Sgblack@eecs.umich.edu            break;
6167396Sgblack@eecs.umich.edu          case FeRoundDown:
6177396Sgblack@eecs.umich.edu            if (origVal < val)
6187396Sgblack@eecs.umich.edu                val -= 1.0;
6197396Sgblack@eecs.umich.edu            break;
6207396Sgblack@eecs.umich.edu          case FeRoundUpward:
6217396Sgblack@eecs.umich.edu            if (origVal > val)
6227396Sgblack@eecs.umich.edu                val += 1.0;
6237396Sgblack@eecs.umich.edu            break;
6247396Sgblack@eecs.umich.edu        }
6257382Sgblack@eecs.umich.edu        feraiseexcept(FeInexact);
6267382Sgblack@eecs.umich.edu    }
6277379Sgblack@eecs.umich.edu    if (isSigned) {
6287379Sgblack@eecs.umich.edu        if (half) {
6297379Sgblack@eecs.umich.edu            if (val < (int16_t)(1 << 15)) {
6307379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
6317382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
6327379Sgblack@eecs.umich.edu                return (int16_t)(1 << 15);
6337379Sgblack@eecs.umich.edu            }
6347379Sgblack@eecs.umich.edu            if (val > (int16_t)mask(15)) {
6357379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
6367382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
6377379Sgblack@eecs.umich.edu                return (int16_t)mask(15);
6387379Sgblack@eecs.umich.edu            }
6397379Sgblack@eecs.umich.edu            return (int16_t)val;
6407379Sgblack@eecs.umich.edu        } else {
6417379Sgblack@eecs.umich.edu            if (val < (int32_t)(1 << 31)) {
6427379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
6437382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
6447379Sgblack@eecs.umich.edu                return (int32_t)(1 << 31);
6457379Sgblack@eecs.umich.edu            }
6467379Sgblack@eecs.umich.edu            if (val > (int32_t)mask(31)) {
6477379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
6487382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
6497379Sgblack@eecs.umich.edu                return (int32_t)mask(31);
6507379Sgblack@eecs.umich.edu            }
6517379Sgblack@eecs.umich.edu            return (int32_t)val;
6527379Sgblack@eecs.umich.edu        }
6537379Sgblack@eecs.umich.edu    } else {
6547379Sgblack@eecs.umich.edu        if (half) {
6557379Sgblack@eecs.umich.edu            if (val < 0) {
6567379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
6577382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
6587379Sgblack@eecs.umich.edu                return 0;
6597379Sgblack@eecs.umich.edu            }
6607379Sgblack@eecs.umich.edu            if (val > mask(16)) {
6617379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
6627382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
6637379Sgblack@eecs.umich.edu                return mask(16);
6647379Sgblack@eecs.umich.edu            }
6657379Sgblack@eecs.umich.edu            return (uint16_t)val;
6667379Sgblack@eecs.umich.edu        } else {
6677379Sgblack@eecs.umich.edu            if (val < 0) {
6687379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
6697382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
6707379Sgblack@eecs.umich.edu                return 0;
6717379Sgblack@eecs.umich.edu            }
6727379Sgblack@eecs.umich.edu            if (val > mask(32)) {
6737379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
6747382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
6757379Sgblack@eecs.umich.edu                return mask(32);
6767379Sgblack@eecs.umich.edu            }
6777379Sgblack@eecs.umich.edu            return (uint32_t)val;
6787379Sgblack@eecs.umich.edu        }
6797379Sgblack@eecs.umich.edu    }
6807379Sgblack@eecs.umich.edu}
6817379Sgblack@eecs.umich.edu
6827379Sgblack@eecs.umich.edustatic inline double
6837386Sgblack@eecs.umich.eduvfpUFixedToFpD(FPSCR fpscr, uint32_t val, bool half, uint8_t imm)
6847379Sgblack@eecs.umich.edu{
6857379Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
6867379Sgblack@eecs.umich.edu    if (half)
6877379Sgblack@eecs.umich.edu        val = (uint16_t)val;
6887382Sgblack@eecs.umich.edu    double scale = pow(2.0, imm);
6897382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
6907382Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
6917382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
6927386Sgblack@eecs.umich.edu    return fixDivDest(fpscr, val / scale, (double)val, scale);
6937379Sgblack@eecs.umich.edu}
6947379Sgblack@eecs.umich.edu
6957379Sgblack@eecs.umich.edustatic inline double
6967386Sgblack@eecs.umich.eduvfpSFixedToFpD(FPSCR fpscr, int32_t val, bool half, uint8_t imm)
6977379Sgblack@eecs.umich.edu{
6987379Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
6997379Sgblack@eecs.umich.edu    if (half)
7007379Sgblack@eecs.umich.edu        val = sext<16>(val & mask(16));
7017382Sgblack@eecs.umich.edu    double scale = pow(2.0, imm);
7027382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
7037382Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
7047382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
7057386Sgblack@eecs.umich.edu    return fixDivDest(fpscr, val / scale, (double)val, scale);
7067379Sgblack@eecs.umich.edu}
7077379Sgblack@eecs.umich.edu
7087376Sgblack@eecs.umich.educlass VfpMacroOp : public PredMacroOp
7097376Sgblack@eecs.umich.edu{
7107376Sgblack@eecs.umich.edu  public:
7117376Sgblack@eecs.umich.edu    static bool
7127376Sgblack@eecs.umich.edu    inScalarBank(IntRegIndex idx)
7137376Sgblack@eecs.umich.edu    {
7147376Sgblack@eecs.umich.edu        return (idx % 32) < 8;
7157376Sgblack@eecs.umich.edu    }
7167376Sgblack@eecs.umich.edu
7177376Sgblack@eecs.umich.edu  protected:
7187376Sgblack@eecs.umich.edu    bool wide;
7197376Sgblack@eecs.umich.edu
7207376Sgblack@eecs.umich.edu    VfpMacroOp(const char *mnem, ExtMachInst _machInst,
7217376Sgblack@eecs.umich.edu            OpClass __opClass, bool _wide) :
7227376Sgblack@eecs.umich.edu        PredMacroOp(mnem, _machInst, __opClass), wide(_wide)
7237376Sgblack@eecs.umich.edu    {}
7247376Sgblack@eecs.umich.edu
7257376Sgblack@eecs.umich.edu    IntRegIndex
7267376Sgblack@eecs.umich.edu    addStride(IntRegIndex idx, unsigned stride)
7277376Sgblack@eecs.umich.edu    {
7287376Sgblack@eecs.umich.edu        if (wide) {
7297376Sgblack@eecs.umich.edu            stride *= 2;
7307376Sgblack@eecs.umich.edu        }
7317376Sgblack@eecs.umich.edu        unsigned offset = idx % 8;
7327376Sgblack@eecs.umich.edu        idx = (IntRegIndex)(idx - offset);
7337376Sgblack@eecs.umich.edu        offset += stride;
7347376Sgblack@eecs.umich.edu        idx = (IntRegIndex)(idx + (offset % 8));
7357376Sgblack@eecs.umich.edu        return idx;
7367376Sgblack@eecs.umich.edu    }
7377376Sgblack@eecs.umich.edu
7387376Sgblack@eecs.umich.edu    void
7397376Sgblack@eecs.umich.edu    nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2)
7407376Sgblack@eecs.umich.edu    {
7417376Sgblack@eecs.umich.edu        unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
7427376Sgblack@eecs.umich.edu        assert(!inScalarBank(dest));
7437376Sgblack@eecs.umich.edu        dest = addStride(dest, stride);
7447376Sgblack@eecs.umich.edu        op1 = addStride(op1, stride);
7457376Sgblack@eecs.umich.edu        if (!inScalarBank(op2)) {
7467376Sgblack@eecs.umich.edu            op2 = addStride(op2, stride);
7477376Sgblack@eecs.umich.edu        }
7487376Sgblack@eecs.umich.edu    }
7497376Sgblack@eecs.umich.edu
7507376Sgblack@eecs.umich.edu    void
7517376Sgblack@eecs.umich.edu    nextIdxs(IntRegIndex &dest, IntRegIndex &op1)
7527376Sgblack@eecs.umich.edu    {
7537376Sgblack@eecs.umich.edu        unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
7547376Sgblack@eecs.umich.edu        assert(!inScalarBank(dest));
7557376Sgblack@eecs.umich.edu        dest = addStride(dest, stride);
7567376Sgblack@eecs.umich.edu        if (!inScalarBank(op1)) {
7577376Sgblack@eecs.umich.edu            op1 = addStride(op1, stride);
7587376Sgblack@eecs.umich.edu        }
7597376Sgblack@eecs.umich.edu    }
7607376Sgblack@eecs.umich.edu
7617376Sgblack@eecs.umich.edu    void
7627376Sgblack@eecs.umich.edu    nextIdxs(IntRegIndex &dest)
7637376Sgblack@eecs.umich.edu    {
7647376Sgblack@eecs.umich.edu        unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
7657376Sgblack@eecs.umich.edu        assert(!inScalarBank(dest));
7667376Sgblack@eecs.umich.edu        dest = addStride(dest, stride);
7677376Sgblack@eecs.umich.edu    }
7687376Sgblack@eecs.umich.edu};
7697376Sgblack@eecs.umich.edu
7707396Sgblack@eecs.umich.edustatic inline float
7717396Sgblack@eecs.umich.edufpAddS(float a, float b)
7727396Sgblack@eecs.umich.edu{
7737396Sgblack@eecs.umich.edu    return a + b;
7747396Sgblack@eecs.umich.edu}
7757396Sgblack@eecs.umich.edu
7767396Sgblack@eecs.umich.edustatic inline double
7777396Sgblack@eecs.umich.edufpAddD(double a, double b)
7787396Sgblack@eecs.umich.edu{
7797396Sgblack@eecs.umich.edu    return a + b;
7807396Sgblack@eecs.umich.edu}
7817396Sgblack@eecs.umich.edu
7827396Sgblack@eecs.umich.edustatic inline float
7837396Sgblack@eecs.umich.edufpSubS(float a, float b)
7847396Sgblack@eecs.umich.edu{
7857396Sgblack@eecs.umich.edu    return a - b;
7867396Sgblack@eecs.umich.edu}
7877396Sgblack@eecs.umich.edu
7887396Sgblack@eecs.umich.edustatic inline double
7897396Sgblack@eecs.umich.edufpSubD(double a, double b)
7907396Sgblack@eecs.umich.edu{
7917396Sgblack@eecs.umich.edu    return a - b;
7927396Sgblack@eecs.umich.edu}
7937396Sgblack@eecs.umich.edu
7947396Sgblack@eecs.umich.edustatic inline float
7957396Sgblack@eecs.umich.edufpDivS(float a, float b)
7967396Sgblack@eecs.umich.edu{
7977396Sgblack@eecs.umich.edu    return a / b;
7987396Sgblack@eecs.umich.edu}
7997396Sgblack@eecs.umich.edu
8007396Sgblack@eecs.umich.edustatic inline double
8017396Sgblack@eecs.umich.edufpDivD(double a, double b)
8027396Sgblack@eecs.umich.edu{
8037396Sgblack@eecs.umich.edu    return a / b;
8047396Sgblack@eecs.umich.edu}
8057396Sgblack@eecs.umich.edu
8067396Sgblack@eecs.umich.edustatic inline float
8077396Sgblack@eecs.umich.edufpMulS(float a, float b)
8087396Sgblack@eecs.umich.edu{
8097396Sgblack@eecs.umich.edu    return a * b;
8107396Sgblack@eecs.umich.edu}
8117396Sgblack@eecs.umich.edu
8127396Sgblack@eecs.umich.edustatic inline double
8137396Sgblack@eecs.umich.edufpMulD(double a, double b)
8147396Sgblack@eecs.umich.edu{
8157396Sgblack@eecs.umich.edu    return a * b;
8167396Sgblack@eecs.umich.edu}
8177396Sgblack@eecs.umich.edu
8187396Sgblack@eecs.umich.educlass FpOp : public PredOp
8197375Sgblack@eecs.umich.edu{
8207375Sgblack@eecs.umich.edu  protected:
8217396Sgblack@eecs.umich.edu    FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
8227396Sgblack@eecs.umich.edu        PredOp(mnem, _machInst, __opClass)
8237396Sgblack@eecs.umich.edu    {}
8247396Sgblack@eecs.umich.edu
8257396Sgblack@eecs.umich.edu    virtual float
8267396Sgblack@eecs.umich.edu    doOp(float op1, float op2) const
8277396Sgblack@eecs.umich.edu    {
8287396Sgblack@eecs.umich.edu        panic("Unimplemented version of doOp called.\n");
8297396Sgblack@eecs.umich.edu    }
8307396Sgblack@eecs.umich.edu
8317396Sgblack@eecs.umich.edu    virtual float
8327396Sgblack@eecs.umich.edu    doOp(float op1) const
8337396Sgblack@eecs.umich.edu    {
8347396Sgblack@eecs.umich.edu        panic("Unimplemented version of doOp called.\n");
8357396Sgblack@eecs.umich.edu    }
8367396Sgblack@eecs.umich.edu
8377396Sgblack@eecs.umich.edu    virtual double
8387396Sgblack@eecs.umich.edu    doOp(double op1, double op2) const
8397396Sgblack@eecs.umich.edu    {
8407396Sgblack@eecs.umich.edu        panic("Unimplemented version of doOp called.\n");
8417396Sgblack@eecs.umich.edu    }
8427396Sgblack@eecs.umich.edu
8437396Sgblack@eecs.umich.edu    virtual double
8447396Sgblack@eecs.umich.edu    doOp(double op1) const
8457396Sgblack@eecs.umich.edu    {
8467396Sgblack@eecs.umich.edu        panic("Unimplemented version of doOp called.\n");
8477396Sgblack@eecs.umich.edu    }
8487396Sgblack@eecs.umich.edu
8497396Sgblack@eecs.umich.edu    double
8507396Sgblack@eecs.umich.edu    dbl(uint32_t low, uint32_t high) const
8517396Sgblack@eecs.umich.edu    {
8527396Sgblack@eecs.umich.edu        double junk = 0.0;
8537396Sgblack@eecs.umich.edu        return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
8547396Sgblack@eecs.umich.edu    }
8557396Sgblack@eecs.umich.edu
8567396Sgblack@eecs.umich.edu    uint32_t
8577396Sgblack@eecs.umich.edu    dblLow(double val) const
8587396Sgblack@eecs.umich.edu    {
8597396Sgblack@eecs.umich.edu        return fpToBits(val);
8607396Sgblack@eecs.umich.edu    }
8617396Sgblack@eecs.umich.edu
8627396Sgblack@eecs.umich.edu    uint32_t
8637396Sgblack@eecs.umich.edu    dblHi(double val) const
8647396Sgblack@eecs.umich.edu    {
8657396Sgblack@eecs.umich.edu        return fpToBits(val) >> 32;
8667396Sgblack@eecs.umich.edu    }
8677396Sgblack@eecs.umich.edu
8687396Sgblack@eecs.umich.edu    template <class fpType>
8697396Sgblack@eecs.umich.edu    fpType
8707396Sgblack@eecs.umich.edu    binaryOp(FPSCR &fpscr, fpType op1, fpType op2,
8717396Sgblack@eecs.umich.edu            fpType (*func)(fpType, fpType),
8727396Sgblack@eecs.umich.edu            bool flush, uint32_t rMode) const
8737396Sgblack@eecs.umich.edu    {
8747396Sgblack@eecs.umich.edu        const bool single = (sizeof(fpType) == sizeof(float));
8757396Sgblack@eecs.umich.edu        fpType junk = 0.0;
8767396Sgblack@eecs.umich.edu
8777396Sgblack@eecs.umich.edu        if (flush && flushToZero(op1, op2))
8787396Sgblack@eecs.umich.edu            fpscr.idc = 1;
8797396Sgblack@eecs.umich.edu        VfpSavedState state = prepFpState(rMode);
8807396Sgblack@eecs.umich.edu        __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2), "=m" (state)
8817396Sgblack@eecs.umich.edu                                 : "m" (op1), "m" (op2), "m" (state));
8827396Sgblack@eecs.umich.edu        fpType dest = func(op1, op2);
8837396Sgblack@eecs.umich.edu        __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest));
8847396Sgblack@eecs.umich.edu
8857396Sgblack@eecs.umich.edu        int fpClass = std::fpclassify(dest);
8867396Sgblack@eecs.umich.edu        // Get NAN behavior right. This varies between x86 and ARM.
8877396Sgblack@eecs.umich.edu        if (fpClass == FP_NAN) {
8887396Sgblack@eecs.umich.edu            const bool single = (sizeof(fpType) == sizeof(float));
8897396Sgblack@eecs.umich.edu            const uint64_t qnan =
8907396Sgblack@eecs.umich.edu                single ? 0x7fc00000 : ULL(0x7ff8000000000000);
8917396Sgblack@eecs.umich.edu            const bool nan1 = std::isnan(op1);
8927396Sgblack@eecs.umich.edu            const bool nan2 = std::isnan(op2);
8937396Sgblack@eecs.umich.edu            const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan);
8947396Sgblack@eecs.umich.edu            const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan);
8957396Sgblack@eecs.umich.edu            if ((!nan1 && !nan2) || (fpscr.dn == 1)) {
8967396Sgblack@eecs.umich.edu                dest = bitsToFp(qnan, junk);
8977396Sgblack@eecs.umich.edu            } else if (signal1) {
8987396Sgblack@eecs.umich.edu                dest = bitsToFp(fpToBits(op1) | qnan, junk);
8997396Sgblack@eecs.umich.edu            } else if (signal2) {
9007396Sgblack@eecs.umich.edu                dest = bitsToFp(fpToBits(op2) | qnan, junk);
9017396Sgblack@eecs.umich.edu            } else if (nan1) {
9027396Sgblack@eecs.umich.edu                dest = op1;
9037396Sgblack@eecs.umich.edu            } else if (nan2) {
9047396Sgblack@eecs.umich.edu                dest = op2;
9057396Sgblack@eecs.umich.edu            }
9067396Sgblack@eecs.umich.edu        } else if (flush && flushToZero(dest)) {
9077396Sgblack@eecs.umich.edu            feraiseexcept(FeUnderflow);
9087396Sgblack@eecs.umich.edu        } else if ((
9097396Sgblack@eecs.umich.edu                    (single && (dest == bitsToFp(0x00800000, junk) ||
9107396Sgblack@eecs.umich.edu                         dest == bitsToFp(0x80800000, junk))) ||
9117396Sgblack@eecs.umich.edu                    (!single &&
9127396Sgblack@eecs.umich.edu                        (dest == bitsToFp(ULL(0x0010000000000000), junk) ||
9137396Sgblack@eecs.umich.edu                         dest == bitsToFp(ULL(0x8010000000000000), junk)))
9147396Sgblack@eecs.umich.edu                   ) && rMode != VfpRoundZero) {
9157396Sgblack@eecs.umich.edu            /*
9167396Sgblack@eecs.umich.edu             * Correct for the fact that underflow is detected -before- rounding
9177396Sgblack@eecs.umich.edu             * in ARM and -after- rounding in x86.
9187396Sgblack@eecs.umich.edu             */
9197396Sgblack@eecs.umich.edu            fesetround(FeRoundZero);
9207396Sgblack@eecs.umich.edu            __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2)
9217396Sgblack@eecs.umich.edu                                     : "m" (op1), "m" (op2));
9227396Sgblack@eecs.umich.edu            fpType temp = func(op1, op2);
9237396Sgblack@eecs.umich.edu            __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp));
9247396Sgblack@eecs.umich.edu            if (flush && flushToZero(temp)) {
9257396Sgblack@eecs.umich.edu                dest = temp;
9267396Sgblack@eecs.umich.edu            }
9277396Sgblack@eecs.umich.edu        }
9287396Sgblack@eecs.umich.edu        finishVfp(fpscr, state);
9297396Sgblack@eecs.umich.edu        return dest;
9307396Sgblack@eecs.umich.edu    }
9317396Sgblack@eecs.umich.edu
9327396Sgblack@eecs.umich.edu    template <class fpType>
9337396Sgblack@eecs.umich.edu    fpType
9347396Sgblack@eecs.umich.edu    unaryOp(FPSCR &fpscr, fpType op1,
9357396Sgblack@eecs.umich.edu            fpType (*func)(fpType),
9367396Sgblack@eecs.umich.edu            bool flush, uint32_t rMode) const
9377396Sgblack@eecs.umich.edu    {
9387396Sgblack@eecs.umich.edu        const bool single = (sizeof(fpType) == sizeof(float));
9397396Sgblack@eecs.umich.edu        fpType junk = 0.0;
9407396Sgblack@eecs.umich.edu
9417396Sgblack@eecs.umich.edu        if (flush && flushToZero(op1))
9427396Sgblack@eecs.umich.edu            fpscr.idc = 1;
9437396Sgblack@eecs.umich.edu        VfpSavedState state = prepFpState(rMode);
9447396Sgblack@eecs.umich.edu        __asm__ __volatile__ ("" : "=m" (op1), "=m" (state)
9457396Sgblack@eecs.umich.edu                                 : "m" (op1), "m" (state));
9467396Sgblack@eecs.umich.edu        fpType dest = func(op1);
9477396Sgblack@eecs.umich.edu        __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest));
9487396Sgblack@eecs.umich.edu
9497396Sgblack@eecs.umich.edu        int fpClass = std::fpclassify(dest);
9507396Sgblack@eecs.umich.edu        // Get NAN behavior right. This varies between x86 and ARM.
9517396Sgblack@eecs.umich.edu        if (fpClass == FP_NAN) {
9527396Sgblack@eecs.umich.edu            const bool single = (sizeof(fpType) == sizeof(float));
9537396Sgblack@eecs.umich.edu            const uint64_t qnan =
9547396Sgblack@eecs.umich.edu                single ? 0x7fc00000 : ULL(0x7ff8000000000000);
9557396Sgblack@eecs.umich.edu            const bool nan = std::isnan(op1);
9567396Sgblack@eecs.umich.edu            if (!nan || fpscr.dn == 1) {
9577396Sgblack@eecs.umich.edu                dest = bitsToFp(qnan, junk);
9587396Sgblack@eecs.umich.edu            } else if (nan) {
9597396Sgblack@eecs.umich.edu                dest = bitsToFp(fpToBits(op1) | qnan, junk);
9607396Sgblack@eecs.umich.edu            }
9617396Sgblack@eecs.umich.edu        } else if (flush && flushToZero(dest)) {
9627396Sgblack@eecs.umich.edu            feraiseexcept(FeUnderflow);
9637396Sgblack@eecs.umich.edu        } else if ((
9647396Sgblack@eecs.umich.edu                    (single && (dest == bitsToFp(0x00800000, junk) ||
9657396Sgblack@eecs.umich.edu                         dest == bitsToFp(0x80800000, junk))) ||
9667396Sgblack@eecs.umich.edu                    (!single &&
9677396Sgblack@eecs.umich.edu                        (dest == bitsToFp(ULL(0x0010000000000000), junk) ||
9687396Sgblack@eecs.umich.edu                         dest == bitsToFp(ULL(0x8010000000000000), junk)))
9697396Sgblack@eecs.umich.edu                   ) && rMode != VfpRoundZero) {
9707396Sgblack@eecs.umich.edu            /*
9717396Sgblack@eecs.umich.edu             * Correct for the fact that underflow is detected -before- rounding
9727396Sgblack@eecs.umich.edu             * in ARM and -after- rounding in x86.
9737396Sgblack@eecs.umich.edu             */
9747396Sgblack@eecs.umich.edu            fesetround(FeRoundZero);
9757396Sgblack@eecs.umich.edu            __asm__ __volatile__ ("" : "=m" (op1) : "m" (op1));
9767396Sgblack@eecs.umich.edu            fpType temp = func(op1);
9777396Sgblack@eecs.umich.edu            __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp));
9787396Sgblack@eecs.umich.edu            if (flush && flushToZero(temp)) {
9797396Sgblack@eecs.umich.edu                dest = temp;
9807396Sgblack@eecs.umich.edu            }
9817396Sgblack@eecs.umich.edu        }
9827396Sgblack@eecs.umich.edu        finishVfp(fpscr, state);
9837396Sgblack@eecs.umich.edu        return dest;
9847396Sgblack@eecs.umich.edu    }
9857396Sgblack@eecs.umich.edu};
9867396Sgblack@eecs.umich.edu
9877396Sgblack@eecs.umich.educlass FpRegRegOp : public FpOp
9887396Sgblack@eecs.umich.edu{
9897396Sgblack@eecs.umich.edu  protected:
9907396Sgblack@eecs.umich.edu    IntRegIndex dest;
9917396Sgblack@eecs.umich.edu    IntRegIndex op1;
9927396Sgblack@eecs.umich.edu
9937396Sgblack@eecs.umich.edu    FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
9947396Sgblack@eecs.umich.edu               IntRegIndex _dest, IntRegIndex _op1,
9957396Sgblack@eecs.umich.edu               VfpMicroMode mode = VfpNotAMicroop) :
9967396Sgblack@eecs.umich.edu        FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1)
9977375Sgblack@eecs.umich.edu    {
9987375Sgblack@eecs.umich.edu        setVfpMicroFlags(mode, flags);
9997375Sgblack@eecs.umich.edu    }
10007396Sgblack@eecs.umich.edu
10017396Sgblack@eecs.umich.edu    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
10027375Sgblack@eecs.umich.edu};
10037375Sgblack@eecs.umich.edu
10047396Sgblack@eecs.umich.educlass FpRegImmOp : public FpOp
10057375Sgblack@eecs.umich.edu{
10067375Sgblack@eecs.umich.edu  protected:
10077396Sgblack@eecs.umich.edu    IntRegIndex dest;
10087396Sgblack@eecs.umich.edu    uint64_t imm;
10097396Sgblack@eecs.umich.edu
10107396Sgblack@eecs.umich.edu    FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
10117396Sgblack@eecs.umich.edu               IntRegIndex _dest, uint64_t _imm,
10127396Sgblack@eecs.umich.edu               VfpMicroMode mode = VfpNotAMicroop) :
10137396Sgblack@eecs.umich.edu        FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm)
10147375Sgblack@eecs.umich.edu    {
10157375Sgblack@eecs.umich.edu        setVfpMicroFlags(mode, flags);
10167375Sgblack@eecs.umich.edu    }
10177396Sgblack@eecs.umich.edu
10187396Sgblack@eecs.umich.edu    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
10197375Sgblack@eecs.umich.edu};
10207375Sgblack@eecs.umich.edu
10217396Sgblack@eecs.umich.educlass FpRegRegImmOp : public FpOp
10227375Sgblack@eecs.umich.edu{
10237375Sgblack@eecs.umich.edu  protected:
10247396Sgblack@eecs.umich.edu    IntRegIndex dest;
10257396Sgblack@eecs.umich.edu    IntRegIndex op1;
10267396Sgblack@eecs.umich.edu    uint64_t imm;
10277396Sgblack@eecs.umich.edu
10287396Sgblack@eecs.umich.edu    FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
10297396Sgblack@eecs.umich.edu                  IntRegIndex _dest, IntRegIndex _op1,
10307396Sgblack@eecs.umich.edu                  uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) :
10317396Sgblack@eecs.umich.edu        FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm)
10327375Sgblack@eecs.umich.edu    {
10337375Sgblack@eecs.umich.edu        setVfpMicroFlags(mode, flags);
10347375Sgblack@eecs.umich.edu    }
10357396Sgblack@eecs.umich.edu
10367396Sgblack@eecs.umich.edu    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
10377375Sgblack@eecs.umich.edu};
10387375Sgblack@eecs.umich.edu
10397396Sgblack@eecs.umich.educlass FpRegRegRegOp : public FpOp
10407375Sgblack@eecs.umich.edu{
10417375Sgblack@eecs.umich.edu  protected:
10427396Sgblack@eecs.umich.edu    IntRegIndex dest;
10437396Sgblack@eecs.umich.edu    IntRegIndex op1;
10447396Sgblack@eecs.umich.edu    IntRegIndex op2;
10457396Sgblack@eecs.umich.edu
10467396Sgblack@eecs.umich.edu    FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
10477396Sgblack@eecs.umich.edu                  IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
10487396Sgblack@eecs.umich.edu                  VfpMicroMode mode = VfpNotAMicroop) :
10497396Sgblack@eecs.umich.edu        FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2)
10507375Sgblack@eecs.umich.edu    {
10517375Sgblack@eecs.umich.edu        setVfpMicroFlags(mode, flags);
10527375Sgblack@eecs.umich.edu    }
10537396Sgblack@eecs.umich.edu
10547396Sgblack@eecs.umich.edu    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
10557375Sgblack@eecs.umich.edu};
10567375Sgblack@eecs.umich.edu
10577384Sgblack@eecs.umich.edu}
10587384Sgblack@eecs.umich.edu
10597375Sgblack@eecs.umich.edu#endif //__ARCH_ARM_INSTS_VFP_HH__
1060