vfp.hh revision 7384
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;
1137382Sgblack@eecs.umich.edu    if (fpscr.fz == 1 && (std::fpclassify(op) == FP_SUBNORMAL)) {
1147382Sgblack@eecs.umich.edu        fpscr.idc = 1;
1157382Sgblack@eecs.umich.edu        op = 0;
1167382Sgblack@eecs.umich.edu    }
1177382Sgblack@eecs.umich.edu    _fpscr = fpscr;
1187382Sgblack@eecs.umich.edu}
1197382Sgblack@eecs.umich.edu
1207382Sgblack@eecs.umich.edutemplate <class fpType>
1217382Sgblack@eecs.umich.edustatic inline void
1227382Sgblack@eecs.umich.eduvfpFlushToZero(uint32_t &fpscr, fpType &op1, fpType &op2)
1237382Sgblack@eecs.umich.edu{
1247382Sgblack@eecs.umich.edu    vfpFlushToZero(fpscr, op1);
1257382Sgblack@eecs.umich.edu    vfpFlushToZero(fpscr, op2);
1267382Sgblack@eecs.umich.edu}
1277382Sgblack@eecs.umich.edu
1287384Sgblack@eecs.umich.edustatic inline uint32_t
1297384Sgblack@eecs.umich.edufpToBits(float fp)
1307384Sgblack@eecs.umich.edu{
1317384Sgblack@eecs.umich.edu    union
1327384Sgblack@eecs.umich.edu    {
1337384Sgblack@eecs.umich.edu        float fp;
1347384Sgblack@eecs.umich.edu        uint32_t bits;
1357384Sgblack@eecs.umich.edu    } val;
1367384Sgblack@eecs.umich.edu    val.fp = fp;
1377384Sgblack@eecs.umich.edu    return val.bits;
1387384Sgblack@eecs.umich.edu}
1397384Sgblack@eecs.umich.edu
1407384Sgblack@eecs.umich.edustatic inline uint64_t
1417384Sgblack@eecs.umich.edufpToBits(double fp)
1427384Sgblack@eecs.umich.edu{
1437384Sgblack@eecs.umich.edu    union
1447384Sgblack@eecs.umich.edu    {
1457384Sgblack@eecs.umich.edu        double fp;
1467384Sgblack@eecs.umich.edu        uint64_t bits;
1477384Sgblack@eecs.umich.edu    } val;
1487384Sgblack@eecs.umich.edu    val.fp = fp;
1497384Sgblack@eecs.umich.edu    return val.bits;
1507384Sgblack@eecs.umich.edu}
1517384Sgblack@eecs.umich.edu
1527384Sgblack@eecs.umich.edustatic inline float
1537384Sgblack@eecs.umich.edubitsToFp(uint64_t bits, float junk)
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.bits = bits;
1617384Sgblack@eecs.umich.edu    return val.fp;
1627384Sgblack@eecs.umich.edu}
1637384Sgblack@eecs.umich.edu
1647384Sgblack@eecs.umich.edustatic inline double
1657384Sgblack@eecs.umich.edubitsToFp(uint64_t bits, double junk)
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.bits = bits;
1737384Sgblack@eecs.umich.edu    return val.fp;
1747384Sgblack@eecs.umich.edu}
1757384Sgblack@eecs.umich.edu
1767384Sgblack@eecs.umich.edutemplate <class fpType>
1777384Sgblack@eecs.umich.edustatic inline fpType
1787384Sgblack@eecs.umich.edufixNan(FPSCR fpscr, fpType val, fpType op1, fpType op2)
1797384Sgblack@eecs.umich.edu{
1807384Sgblack@eecs.umich.edu    if (std::isnan(val)) {
1817384Sgblack@eecs.umich.edu        const bool single = (sizeof(val) == sizeof(float));
1827384Sgblack@eecs.umich.edu        const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000);
1837384Sgblack@eecs.umich.edu        const bool nan1 = std::isnan(op1);
1847384Sgblack@eecs.umich.edu        const bool nan2 = std::isnan(op2);
1857384Sgblack@eecs.umich.edu        const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan);
1867384Sgblack@eecs.umich.edu        const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan);
1877384Sgblack@eecs.umich.edu        fpType junk = 0.0;
1887384Sgblack@eecs.umich.edu        if ((!nan1 && !nan2) || (fpscr.dn == 1)) {
1897384Sgblack@eecs.umich.edu            val = bitsToFp(qnan, junk);
1907384Sgblack@eecs.umich.edu        } else if (signal1) {
1917384Sgblack@eecs.umich.edu            val = bitsToFp(fpToBits(op1) | qnan, junk);
1927384Sgblack@eecs.umich.edu        } else if (signal2) {
1937384Sgblack@eecs.umich.edu            val = bitsToFp(fpToBits(op2) | qnan, junk);
1947384Sgblack@eecs.umich.edu        } else if (nan1) {
1957384Sgblack@eecs.umich.edu            val = op1;
1967384Sgblack@eecs.umich.edu        } else if (nan2) {
1977384Sgblack@eecs.umich.edu            val = op2;
1987384Sgblack@eecs.umich.edu        }
1997384Sgblack@eecs.umich.edu    }
2007384Sgblack@eecs.umich.edu    return val;
2017384Sgblack@eecs.umich.edu}
2027384Sgblack@eecs.umich.edu
2037379Sgblack@eecs.umich.edustatic inline uint64_t
2047379Sgblack@eecs.umich.eduvfpFpSToFixed(float val, bool isSigned, bool half, uint8_t imm)
2057379Sgblack@eecs.umich.edu{
2067379Sgblack@eecs.umich.edu    fesetround(FeRoundZero);
2077379Sgblack@eecs.umich.edu    val = val * powf(2.0, imm);
2087379Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (val) : "m" (val));
2097379Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
2107382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (val) : "m" (val));
2117382Sgblack@eecs.umich.edu    float origVal = val;
2127382Sgblack@eecs.umich.edu    val = rintf(val);
2137382Sgblack@eecs.umich.edu    int fpType = std::fpclassify(val);
2147382Sgblack@eecs.umich.edu    if (fpType == FP_SUBNORMAL || fpType == FP_NAN) {
2157382Sgblack@eecs.umich.edu        if (fpType == FP_NAN) {
2167382Sgblack@eecs.umich.edu            feraiseexcept(FeInvalid);
2177382Sgblack@eecs.umich.edu        }
2187382Sgblack@eecs.umich.edu        val = 0.0;
2197382Sgblack@eecs.umich.edu    } else if (origVal != val) {
2207382Sgblack@eecs.umich.edu        feraiseexcept(FeInexact);
2217382Sgblack@eecs.umich.edu    }
2227382Sgblack@eecs.umich.edu
2237379Sgblack@eecs.umich.edu    if (isSigned) {
2247379Sgblack@eecs.umich.edu        if (half) {
2257381Sgblack@eecs.umich.edu            if ((double)val < (int16_t)(1 << 15)) {
2267379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2277382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2287379Sgblack@eecs.umich.edu                return (int16_t)(1 << 15);
2297379Sgblack@eecs.umich.edu            }
2307381Sgblack@eecs.umich.edu            if ((double)val > (int16_t)mask(15)) {
2317379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2327382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2337379Sgblack@eecs.umich.edu                return (int16_t)mask(15);
2347379Sgblack@eecs.umich.edu            }
2357379Sgblack@eecs.umich.edu            return (int16_t)val;
2367379Sgblack@eecs.umich.edu        } else {
2377381Sgblack@eecs.umich.edu            if ((double)val < (int32_t)(1 << 31)) {
2387379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2397382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2407379Sgblack@eecs.umich.edu                return (int32_t)(1 << 31);
2417379Sgblack@eecs.umich.edu            }
2427381Sgblack@eecs.umich.edu            if ((double)val > (int32_t)mask(31)) {
2437379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2447382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2457379Sgblack@eecs.umich.edu                return (int32_t)mask(31);
2467379Sgblack@eecs.umich.edu            }
2477379Sgblack@eecs.umich.edu            return (int32_t)val;
2487379Sgblack@eecs.umich.edu        }
2497379Sgblack@eecs.umich.edu    } else {
2507379Sgblack@eecs.umich.edu        if (half) {
2517381Sgblack@eecs.umich.edu            if ((double)val < 0) {
2527379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2537382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2547379Sgblack@eecs.umich.edu                return 0;
2557379Sgblack@eecs.umich.edu            }
2567381Sgblack@eecs.umich.edu            if ((double)val > (mask(16))) {
2577379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2587382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2597379Sgblack@eecs.umich.edu                return mask(16);
2607379Sgblack@eecs.umich.edu            }
2617379Sgblack@eecs.umich.edu            return (uint16_t)val;
2627379Sgblack@eecs.umich.edu        } else {
2637381Sgblack@eecs.umich.edu            if ((double)val < 0) {
2647379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2657382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2667379Sgblack@eecs.umich.edu                return 0;
2677379Sgblack@eecs.umich.edu            }
2687381Sgblack@eecs.umich.edu            if ((double)val > (mask(32))) {
2697379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2707382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2717379Sgblack@eecs.umich.edu                return mask(32);
2727379Sgblack@eecs.umich.edu            }
2737379Sgblack@eecs.umich.edu            return (uint32_t)val;
2747379Sgblack@eecs.umich.edu        }
2757379Sgblack@eecs.umich.edu    }
2767379Sgblack@eecs.umich.edu}
2777379Sgblack@eecs.umich.edu
2787379Sgblack@eecs.umich.edustatic inline float
2797379Sgblack@eecs.umich.eduvfpUFixedToFpS(uint32_t val, bool half, uint8_t imm)
2807379Sgblack@eecs.umich.edu{
2817379Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
2827379Sgblack@eecs.umich.edu    if (half)
2837379Sgblack@eecs.umich.edu        val = (uint16_t)val;
2847382Sgblack@eecs.umich.edu    float scale = powf(2.0, imm);
2857382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
2867382Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
2877382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
2887382Sgblack@eecs.umich.edu    return val / scale;
2897379Sgblack@eecs.umich.edu}
2907379Sgblack@eecs.umich.edu
2917379Sgblack@eecs.umich.edustatic inline float
2927379Sgblack@eecs.umich.eduvfpSFixedToFpS(int32_t val, bool half, uint8_t imm)
2937379Sgblack@eecs.umich.edu{
2947379Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
2957379Sgblack@eecs.umich.edu    if (half)
2967379Sgblack@eecs.umich.edu        val = sext<16>(val & mask(16));
2977382Sgblack@eecs.umich.edu    float scale = powf(2.0, imm);
2987382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
2997382Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
3007382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
3017382Sgblack@eecs.umich.edu    return val / scale;
3027379Sgblack@eecs.umich.edu}
3037379Sgblack@eecs.umich.edu
3047379Sgblack@eecs.umich.edustatic inline uint64_t
3057379Sgblack@eecs.umich.eduvfpFpDToFixed(double val, bool isSigned, bool half, uint8_t imm)
3067379Sgblack@eecs.umich.edu{
3077382Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
3087379Sgblack@eecs.umich.edu    val = val * pow(2.0, imm);
3097379Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (val) : "m" (val));
3107382Sgblack@eecs.umich.edu    fesetround(FeRoundZero);
3117379Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
3127382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (val) : "m" (val));
3137382Sgblack@eecs.umich.edu    double origVal = val;
3147382Sgblack@eecs.umich.edu    val = rint(val);
3157382Sgblack@eecs.umich.edu    int fpType = std::fpclassify(val);
3167382Sgblack@eecs.umich.edu    if (fpType == FP_SUBNORMAL || fpType == FP_NAN) {
3177382Sgblack@eecs.umich.edu        if (fpType == FP_NAN) {
3187382Sgblack@eecs.umich.edu            feraiseexcept(FeInvalid);
3197382Sgblack@eecs.umich.edu        }
3207382Sgblack@eecs.umich.edu        val = 0.0;
3217382Sgblack@eecs.umich.edu    } else if (origVal != val) {
3227382Sgblack@eecs.umich.edu        feraiseexcept(FeInexact);
3237382Sgblack@eecs.umich.edu    }
3247379Sgblack@eecs.umich.edu    if (isSigned) {
3257379Sgblack@eecs.umich.edu        if (half) {
3267379Sgblack@eecs.umich.edu            if (val < (int16_t)(1 << 15)) {
3277379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3287382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3297379Sgblack@eecs.umich.edu                return (int16_t)(1 << 15);
3307379Sgblack@eecs.umich.edu            }
3317379Sgblack@eecs.umich.edu            if (val > (int16_t)mask(15)) {
3327379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3337382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3347379Sgblack@eecs.umich.edu                return (int16_t)mask(15);
3357379Sgblack@eecs.umich.edu            }
3367379Sgblack@eecs.umich.edu            return (int16_t)val;
3377379Sgblack@eecs.umich.edu        } else {
3387379Sgblack@eecs.umich.edu            if (val < (int32_t)(1 << 31)) {
3397379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3407382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3417379Sgblack@eecs.umich.edu                return (int32_t)(1 << 31);
3427379Sgblack@eecs.umich.edu            }
3437379Sgblack@eecs.umich.edu            if (val > (int32_t)mask(31)) {
3447379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3457382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3467379Sgblack@eecs.umich.edu                return (int32_t)mask(31);
3477379Sgblack@eecs.umich.edu            }
3487379Sgblack@eecs.umich.edu            return (int32_t)val;
3497379Sgblack@eecs.umich.edu        }
3507379Sgblack@eecs.umich.edu    } else {
3517379Sgblack@eecs.umich.edu        if (half) {
3527379Sgblack@eecs.umich.edu            if (val < 0) {
3537379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3547382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3557379Sgblack@eecs.umich.edu                return 0;
3567379Sgblack@eecs.umich.edu            }
3577379Sgblack@eecs.umich.edu            if (val > mask(16)) {
3587379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3597382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3607379Sgblack@eecs.umich.edu                return mask(16);
3617379Sgblack@eecs.umich.edu            }
3627379Sgblack@eecs.umich.edu            return (uint16_t)val;
3637379Sgblack@eecs.umich.edu        } else {
3647379Sgblack@eecs.umich.edu            if (val < 0) {
3657379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3667382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3677379Sgblack@eecs.umich.edu                return 0;
3687379Sgblack@eecs.umich.edu            }
3697379Sgblack@eecs.umich.edu            if (val > mask(32)) {
3707379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3717382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3727379Sgblack@eecs.umich.edu                return mask(32);
3737379Sgblack@eecs.umich.edu            }
3747379Sgblack@eecs.umich.edu            return (uint32_t)val;
3757379Sgblack@eecs.umich.edu        }
3767379Sgblack@eecs.umich.edu    }
3777379Sgblack@eecs.umich.edu}
3787379Sgblack@eecs.umich.edu
3797379Sgblack@eecs.umich.edustatic inline double
3807379Sgblack@eecs.umich.eduvfpUFixedToFpD(uint32_t val, bool half, uint8_t imm)
3817379Sgblack@eecs.umich.edu{
3827379Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
3837379Sgblack@eecs.umich.edu    if (half)
3847379Sgblack@eecs.umich.edu        val = (uint16_t)val;
3857382Sgblack@eecs.umich.edu    double scale = pow(2.0, imm);
3867382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
3877382Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
3887382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
3897382Sgblack@eecs.umich.edu    return val / scale;
3907379Sgblack@eecs.umich.edu}
3917379Sgblack@eecs.umich.edu
3927379Sgblack@eecs.umich.edustatic inline double
3937379Sgblack@eecs.umich.eduvfpSFixedToFpD(int32_t val, bool half, uint8_t imm)
3947379Sgblack@eecs.umich.edu{
3957379Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
3967379Sgblack@eecs.umich.edu    if (half)
3977379Sgblack@eecs.umich.edu        val = sext<16>(val & mask(16));
3987382Sgblack@eecs.umich.edu    double scale = pow(2.0, imm);
3997382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
4007382Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
4017382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
4027382Sgblack@eecs.umich.edu    return val / scale;
4037379Sgblack@eecs.umich.edu}
4047379Sgblack@eecs.umich.edu
4057378Sgblack@eecs.umich.edutypedef int VfpSavedState;
4067378Sgblack@eecs.umich.edu
4077378Sgblack@eecs.umich.edustatic inline VfpSavedState
4087378Sgblack@eecs.umich.eduprepVfpFpscr(FPSCR fpscr)
4097378Sgblack@eecs.umich.edu{
4107378Sgblack@eecs.umich.edu    int roundingMode = fegetround();
4117378Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
4127378Sgblack@eecs.umich.edu    switch (fpscr.rMode) {
4137378Sgblack@eecs.umich.edu      case VfpRoundNearest:
4147378Sgblack@eecs.umich.edu        fesetround(FeRoundNearest);
4157378Sgblack@eecs.umich.edu        break;
4167378Sgblack@eecs.umich.edu      case VfpRoundUpward:
4177378Sgblack@eecs.umich.edu        fesetround(FeRoundUpward);
4187378Sgblack@eecs.umich.edu        break;
4197378Sgblack@eecs.umich.edu      case VfpRoundDown:
4207378Sgblack@eecs.umich.edu        fesetround(FeRoundDown);
4217378Sgblack@eecs.umich.edu        break;
4227378Sgblack@eecs.umich.edu      case VfpRoundZero:
4237378Sgblack@eecs.umich.edu        fesetround(FeRoundZero);
4247378Sgblack@eecs.umich.edu        break;
4257378Sgblack@eecs.umich.edu    }
4267378Sgblack@eecs.umich.edu    return roundingMode;
4277378Sgblack@eecs.umich.edu}
4287378Sgblack@eecs.umich.edu
4297378Sgblack@eecs.umich.edustatic inline FPSCR
4307378Sgblack@eecs.umich.edusetVfpFpscr(FPSCR fpscr, VfpSavedState state)
4317378Sgblack@eecs.umich.edu{
4327378Sgblack@eecs.umich.edu    int exceptions = fetestexcept(FeAllExceptions);
4337378Sgblack@eecs.umich.edu    if (exceptions & FeInvalid) {
4347378Sgblack@eecs.umich.edu        fpscr.ioc = 1;
4357378Sgblack@eecs.umich.edu    }
4367378Sgblack@eecs.umich.edu    if (exceptions & FeDivByZero) {
4377378Sgblack@eecs.umich.edu        fpscr.dzc = 1;
4387378Sgblack@eecs.umich.edu    }
4397378Sgblack@eecs.umich.edu    if (exceptions & FeOverflow) {
4407378Sgblack@eecs.umich.edu        fpscr.ofc = 1;
4417378Sgblack@eecs.umich.edu    }
4427378Sgblack@eecs.umich.edu    if (exceptions & FeUnderflow) {
4437378Sgblack@eecs.umich.edu        fpscr.ufc = 1;
4447378Sgblack@eecs.umich.edu    }
4457378Sgblack@eecs.umich.edu    if (exceptions & FeInexact) {
4467378Sgblack@eecs.umich.edu        fpscr.ixc = 1;
4477378Sgblack@eecs.umich.edu    }
4487378Sgblack@eecs.umich.edu    fesetround(state);
4497378Sgblack@eecs.umich.edu    return fpscr;
4507378Sgblack@eecs.umich.edu}
4517378Sgblack@eecs.umich.edu
4527376Sgblack@eecs.umich.educlass VfpMacroOp : public PredMacroOp
4537376Sgblack@eecs.umich.edu{
4547376Sgblack@eecs.umich.edu  public:
4557376Sgblack@eecs.umich.edu    static bool
4567376Sgblack@eecs.umich.edu    inScalarBank(IntRegIndex idx)
4577376Sgblack@eecs.umich.edu    {
4587376Sgblack@eecs.umich.edu        return (idx % 32) < 8;
4597376Sgblack@eecs.umich.edu    }
4607376Sgblack@eecs.umich.edu
4617376Sgblack@eecs.umich.edu  protected:
4627376Sgblack@eecs.umich.edu    bool wide;
4637376Sgblack@eecs.umich.edu
4647376Sgblack@eecs.umich.edu    VfpMacroOp(const char *mnem, ExtMachInst _machInst,
4657376Sgblack@eecs.umich.edu            OpClass __opClass, bool _wide) :
4667376Sgblack@eecs.umich.edu        PredMacroOp(mnem, _machInst, __opClass), wide(_wide)
4677376Sgblack@eecs.umich.edu    {}
4687376Sgblack@eecs.umich.edu
4697376Sgblack@eecs.umich.edu    IntRegIndex
4707376Sgblack@eecs.umich.edu    addStride(IntRegIndex idx, unsigned stride)
4717376Sgblack@eecs.umich.edu    {
4727376Sgblack@eecs.umich.edu        if (wide) {
4737376Sgblack@eecs.umich.edu            stride *= 2;
4747376Sgblack@eecs.umich.edu        }
4757376Sgblack@eecs.umich.edu        unsigned offset = idx % 8;
4767376Sgblack@eecs.umich.edu        idx = (IntRegIndex)(idx - offset);
4777376Sgblack@eecs.umich.edu        offset += stride;
4787376Sgblack@eecs.umich.edu        idx = (IntRegIndex)(idx + (offset % 8));
4797376Sgblack@eecs.umich.edu        return idx;
4807376Sgblack@eecs.umich.edu    }
4817376Sgblack@eecs.umich.edu
4827376Sgblack@eecs.umich.edu    void
4837376Sgblack@eecs.umich.edu    nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2)
4847376Sgblack@eecs.umich.edu    {
4857376Sgblack@eecs.umich.edu        unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
4867376Sgblack@eecs.umich.edu        assert(!inScalarBank(dest));
4877376Sgblack@eecs.umich.edu        dest = addStride(dest, stride);
4887376Sgblack@eecs.umich.edu        op1 = addStride(op1, stride);
4897376Sgblack@eecs.umich.edu        if (!inScalarBank(op2)) {
4907376Sgblack@eecs.umich.edu            op2 = addStride(op2, stride);
4917376Sgblack@eecs.umich.edu        }
4927376Sgblack@eecs.umich.edu    }
4937376Sgblack@eecs.umich.edu
4947376Sgblack@eecs.umich.edu    void
4957376Sgblack@eecs.umich.edu    nextIdxs(IntRegIndex &dest, IntRegIndex &op1)
4967376Sgblack@eecs.umich.edu    {
4977376Sgblack@eecs.umich.edu        unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
4987376Sgblack@eecs.umich.edu        assert(!inScalarBank(dest));
4997376Sgblack@eecs.umich.edu        dest = addStride(dest, stride);
5007376Sgblack@eecs.umich.edu        if (!inScalarBank(op1)) {
5017376Sgblack@eecs.umich.edu            op1 = addStride(op1, stride);
5027376Sgblack@eecs.umich.edu        }
5037376Sgblack@eecs.umich.edu    }
5047376Sgblack@eecs.umich.edu
5057376Sgblack@eecs.umich.edu    void
5067376Sgblack@eecs.umich.edu    nextIdxs(IntRegIndex &dest)
5077376Sgblack@eecs.umich.edu    {
5087376Sgblack@eecs.umich.edu        unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
5097376Sgblack@eecs.umich.edu        assert(!inScalarBank(dest));
5107376Sgblack@eecs.umich.edu        dest = addStride(dest, stride);
5117376Sgblack@eecs.umich.edu    }
5127376Sgblack@eecs.umich.edu};
5137376Sgblack@eecs.umich.edu
5147375Sgblack@eecs.umich.educlass VfpRegRegOp : public RegRegOp
5157375Sgblack@eecs.umich.edu{
5167375Sgblack@eecs.umich.edu  protected:
5177375Sgblack@eecs.umich.edu    VfpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
5187375Sgblack@eecs.umich.edu                IntRegIndex _dest, IntRegIndex _op1,
5197375Sgblack@eecs.umich.edu                VfpMicroMode mode = VfpNotAMicroop) :
5207375Sgblack@eecs.umich.edu        RegRegOp(mnem, _machInst, __opClass, _dest, _op1)
5217375Sgblack@eecs.umich.edu    {
5227375Sgblack@eecs.umich.edu        setVfpMicroFlags(mode, flags);
5237375Sgblack@eecs.umich.edu    }
5247375Sgblack@eecs.umich.edu};
5257375Sgblack@eecs.umich.edu
5267375Sgblack@eecs.umich.educlass VfpRegImmOp : public RegImmOp
5277375Sgblack@eecs.umich.edu{
5287375Sgblack@eecs.umich.edu  protected:
5297375Sgblack@eecs.umich.edu    VfpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
5307375Sgblack@eecs.umich.edu                IntRegIndex _dest, uint64_t _imm,
5317375Sgblack@eecs.umich.edu                VfpMicroMode mode = VfpNotAMicroop) :
5327375Sgblack@eecs.umich.edu        RegImmOp(mnem, _machInst, __opClass, _dest, _imm)
5337375Sgblack@eecs.umich.edu    {
5347375Sgblack@eecs.umich.edu        setVfpMicroFlags(mode, flags);
5357375Sgblack@eecs.umich.edu    }
5367375Sgblack@eecs.umich.edu};
5377375Sgblack@eecs.umich.edu
5387375Sgblack@eecs.umich.educlass VfpRegRegImmOp : public RegRegImmOp
5397375Sgblack@eecs.umich.edu{
5407375Sgblack@eecs.umich.edu  protected:
5417375Sgblack@eecs.umich.edu    VfpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
5427375Sgblack@eecs.umich.edu                   IntRegIndex _dest, IntRegIndex _op1,
5437375Sgblack@eecs.umich.edu                   uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) :
5447375Sgblack@eecs.umich.edu        RegRegImmOp(mnem, _machInst, __opClass, _dest, _op1, _imm)
5457375Sgblack@eecs.umich.edu    {
5467375Sgblack@eecs.umich.edu        setVfpMicroFlags(mode, flags);
5477375Sgblack@eecs.umich.edu    }
5487375Sgblack@eecs.umich.edu};
5497375Sgblack@eecs.umich.edu
5507375Sgblack@eecs.umich.educlass VfpRegRegRegOp : public RegRegRegOp
5517375Sgblack@eecs.umich.edu{
5527375Sgblack@eecs.umich.edu  protected:
5537375Sgblack@eecs.umich.edu    VfpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
5547375Sgblack@eecs.umich.edu                   IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
5557375Sgblack@eecs.umich.edu                   VfpMicroMode mode = VfpNotAMicroop) :
5567375Sgblack@eecs.umich.edu        RegRegRegOp(mnem, _machInst, __opClass, _dest, _op1, _op2)
5577375Sgblack@eecs.umich.edu    {
5587375Sgblack@eecs.umich.edu        setVfpMicroFlags(mode, flags);
5597375Sgblack@eecs.umich.edu    }
5607375Sgblack@eecs.umich.edu};
5617375Sgblack@eecs.umich.edu
5627384Sgblack@eecs.umich.edu}
5637384Sgblack@eecs.umich.edu
5647375Sgblack@eecs.umich.edu#endif //__ARCH_ARM_INSTS_VFP_HH__
565