vfp.hh revision 7385
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
1787385Sgblack@eecs.umich.edufixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2)
1797384Sgblack@eecs.umich.edu{
1807385Sgblack@eecs.umich.edu    int fpClass = std::fpclassify(val);
1817385Sgblack@eecs.umich.edu    fpType junk = 0.0;
1827385Sgblack@eecs.umich.edu    if (fpClass == FP_NAN) {
1837384Sgblack@eecs.umich.edu        const bool single = (sizeof(val) == sizeof(float));
1847384Sgblack@eecs.umich.edu        const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000);
1857384Sgblack@eecs.umich.edu        const bool nan1 = std::isnan(op1);
1867384Sgblack@eecs.umich.edu        const bool nan2 = std::isnan(op2);
1877384Sgblack@eecs.umich.edu        const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan);
1887384Sgblack@eecs.umich.edu        const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan);
1897384Sgblack@eecs.umich.edu        if ((!nan1 && !nan2) || (fpscr.dn == 1)) {
1907384Sgblack@eecs.umich.edu            val = bitsToFp(qnan, junk);
1917384Sgblack@eecs.umich.edu        } else if (signal1) {
1927384Sgblack@eecs.umich.edu            val = bitsToFp(fpToBits(op1) | qnan, junk);
1937384Sgblack@eecs.umich.edu        } else if (signal2) {
1947384Sgblack@eecs.umich.edu            val = bitsToFp(fpToBits(op2) | qnan, junk);
1957384Sgblack@eecs.umich.edu        } else if (nan1) {
1967384Sgblack@eecs.umich.edu            val = op1;
1977384Sgblack@eecs.umich.edu        } else if (nan2) {
1987384Sgblack@eecs.umich.edu            val = op2;
1997384Sgblack@eecs.umich.edu        }
2007385Sgblack@eecs.umich.edu    } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) {
2017385Sgblack@eecs.umich.edu        // Turn val into a zero with the correct sign;
2027385Sgblack@eecs.umich.edu        uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
2037385Sgblack@eecs.umich.edu        val = bitsToFp(fpToBits(val) & bitMask, junk);
2047385Sgblack@eecs.umich.edu        feraiseexcept(FeUnderflow);
2057384Sgblack@eecs.umich.edu    }
2067384Sgblack@eecs.umich.edu    return val;
2077384Sgblack@eecs.umich.edu}
2087384Sgblack@eecs.umich.edu
2097379Sgblack@eecs.umich.edustatic inline uint64_t
2107379Sgblack@eecs.umich.eduvfpFpSToFixed(float val, bool isSigned, bool half, uint8_t imm)
2117379Sgblack@eecs.umich.edu{
2127379Sgblack@eecs.umich.edu    fesetround(FeRoundZero);
2137379Sgblack@eecs.umich.edu    val = val * powf(2.0, imm);
2147379Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (val) : "m" (val));
2157379Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
2167382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (val) : "m" (val));
2177382Sgblack@eecs.umich.edu    float origVal = val;
2187382Sgblack@eecs.umich.edu    val = rintf(val);
2197382Sgblack@eecs.umich.edu    int fpType = std::fpclassify(val);
2207382Sgblack@eecs.umich.edu    if (fpType == FP_SUBNORMAL || fpType == FP_NAN) {
2217382Sgblack@eecs.umich.edu        if (fpType == FP_NAN) {
2227382Sgblack@eecs.umich.edu            feraiseexcept(FeInvalid);
2237382Sgblack@eecs.umich.edu        }
2247382Sgblack@eecs.umich.edu        val = 0.0;
2257382Sgblack@eecs.umich.edu    } else if (origVal != val) {
2267382Sgblack@eecs.umich.edu        feraiseexcept(FeInexact);
2277382Sgblack@eecs.umich.edu    }
2287382Sgblack@eecs.umich.edu
2297379Sgblack@eecs.umich.edu    if (isSigned) {
2307379Sgblack@eecs.umich.edu        if (half) {
2317381Sgblack@eecs.umich.edu            if ((double)val < (int16_t)(1 << 15)) {
2327379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2337382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2347379Sgblack@eecs.umich.edu                return (int16_t)(1 << 15);
2357379Sgblack@eecs.umich.edu            }
2367381Sgblack@eecs.umich.edu            if ((double)val > (int16_t)mask(15)) {
2377379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2387382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2397379Sgblack@eecs.umich.edu                return (int16_t)mask(15);
2407379Sgblack@eecs.umich.edu            }
2417379Sgblack@eecs.umich.edu            return (int16_t)val;
2427379Sgblack@eecs.umich.edu        } else {
2437381Sgblack@eecs.umich.edu            if ((double)val < (int32_t)(1 << 31)) {
2447379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2457382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2467379Sgblack@eecs.umich.edu                return (int32_t)(1 << 31);
2477379Sgblack@eecs.umich.edu            }
2487381Sgblack@eecs.umich.edu            if ((double)val > (int32_t)mask(31)) {
2497379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2507382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2517379Sgblack@eecs.umich.edu                return (int32_t)mask(31);
2527379Sgblack@eecs.umich.edu            }
2537379Sgblack@eecs.umich.edu            return (int32_t)val;
2547379Sgblack@eecs.umich.edu        }
2557379Sgblack@eecs.umich.edu    } else {
2567379Sgblack@eecs.umich.edu        if (half) {
2577381Sgblack@eecs.umich.edu            if ((double)val < 0) {
2587379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2597382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2607379Sgblack@eecs.umich.edu                return 0;
2617379Sgblack@eecs.umich.edu            }
2627381Sgblack@eecs.umich.edu            if ((double)val > (mask(16))) {
2637379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2647382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2657379Sgblack@eecs.umich.edu                return mask(16);
2667379Sgblack@eecs.umich.edu            }
2677379Sgblack@eecs.umich.edu            return (uint16_t)val;
2687379Sgblack@eecs.umich.edu        } else {
2697381Sgblack@eecs.umich.edu            if ((double)val < 0) {
2707379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2717382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2727379Sgblack@eecs.umich.edu                return 0;
2737379Sgblack@eecs.umich.edu            }
2747381Sgblack@eecs.umich.edu            if ((double)val > (mask(32))) {
2757379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
2767382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
2777379Sgblack@eecs.umich.edu                return mask(32);
2787379Sgblack@eecs.umich.edu            }
2797379Sgblack@eecs.umich.edu            return (uint32_t)val;
2807379Sgblack@eecs.umich.edu        }
2817379Sgblack@eecs.umich.edu    }
2827379Sgblack@eecs.umich.edu}
2837379Sgblack@eecs.umich.edu
2847379Sgblack@eecs.umich.edustatic inline float
2857379Sgblack@eecs.umich.eduvfpUFixedToFpS(uint32_t val, bool half, uint8_t imm)
2867379Sgblack@eecs.umich.edu{
2877379Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
2887379Sgblack@eecs.umich.edu    if (half)
2897379Sgblack@eecs.umich.edu        val = (uint16_t)val;
2907382Sgblack@eecs.umich.edu    float scale = powf(2.0, imm);
2917382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
2927382Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
2937382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
2947382Sgblack@eecs.umich.edu    return val / scale;
2957379Sgblack@eecs.umich.edu}
2967379Sgblack@eecs.umich.edu
2977379Sgblack@eecs.umich.edustatic inline float
2987379Sgblack@eecs.umich.eduvfpSFixedToFpS(int32_t val, bool half, uint8_t imm)
2997379Sgblack@eecs.umich.edu{
3007379Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
3017379Sgblack@eecs.umich.edu    if (half)
3027379Sgblack@eecs.umich.edu        val = sext<16>(val & mask(16));
3037382Sgblack@eecs.umich.edu    float scale = powf(2.0, imm);
3047382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
3057382Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
3067382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
3077382Sgblack@eecs.umich.edu    return val / scale;
3087379Sgblack@eecs.umich.edu}
3097379Sgblack@eecs.umich.edu
3107379Sgblack@eecs.umich.edustatic inline uint64_t
3117379Sgblack@eecs.umich.eduvfpFpDToFixed(double val, bool isSigned, bool half, uint8_t imm)
3127379Sgblack@eecs.umich.edu{
3137382Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
3147379Sgblack@eecs.umich.edu    val = val * pow(2.0, imm);
3157379Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (val) : "m" (val));
3167382Sgblack@eecs.umich.edu    fesetround(FeRoundZero);
3177379Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
3187382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (val) : "m" (val));
3197382Sgblack@eecs.umich.edu    double origVal = val;
3207382Sgblack@eecs.umich.edu    val = rint(val);
3217382Sgblack@eecs.umich.edu    int fpType = std::fpclassify(val);
3227382Sgblack@eecs.umich.edu    if (fpType == FP_SUBNORMAL || fpType == FP_NAN) {
3237382Sgblack@eecs.umich.edu        if (fpType == FP_NAN) {
3247382Sgblack@eecs.umich.edu            feraiseexcept(FeInvalid);
3257382Sgblack@eecs.umich.edu        }
3267382Sgblack@eecs.umich.edu        val = 0.0;
3277382Sgblack@eecs.umich.edu    } else if (origVal != val) {
3287382Sgblack@eecs.umich.edu        feraiseexcept(FeInexact);
3297382Sgblack@eecs.umich.edu    }
3307379Sgblack@eecs.umich.edu    if (isSigned) {
3317379Sgblack@eecs.umich.edu        if (half) {
3327379Sgblack@eecs.umich.edu            if (val < (int16_t)(1 << 15)) {
3337379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3347382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3357379Sgblack@eecs.umich.edu                return (int16_t)(1 << 15);
3367379Sgblack@eecs.umich.edu            }
3377379Sgblack@eecs.umich.edu            if (val > (int16_t)mask(15)) {
3387379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3397382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3407379Sgblack@eecs.umich.edu                return (int16_t)mask(15);
3417379Sgblack@eecs.umich.edu            }
3427379Sgblack@eecs.umich.edu            return (int16_t)val;
3437379Sgblack@eecs.umich.edu        } else {
3447379Sgblack@eecs.umich.edu            if (val < (int32_t)(1 << 31)) {
3457379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3467382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3477379Sgblack@eecs.umich.edu                return (int32_t)(1 << 31);
3487379Sgblack@eecs.umich.edu            }
3497379Sgblack@eecs.umich.edu            if (val > (int32_t)mask(31)) {
3507379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3517382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3527379Sgblack@eecs.umich.edu                return (int32_t)mask(31);
3537379Sgblack@eecs.umich.edu            }
3547379Sgblack@eecs.umich.edu            return (int32_t)val;
3557379Sgblack@eecs.umich.edu        }
3567379Sgblack@eecs.umich.edu    } else {
3577379Sgblack@eecs.umich.edu        if (half) {
3587379Sgblack@eecs.umich.edu            if (val < 0) {
3597379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3607382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3617379Sgblack@eecs.umich.edu                return 0;
3627379Sgblack@eecs.umich.edu            }
3637379Sgblack@eecs.umich.edu            if (val > mask(16)) {
3647379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3657382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3667379Sgblack@eecs.umich.edu                return mask(16);
3677379Sgblack@eecs.umich.edu            }
3687379Sgblack@eecs.umich.edu            return (uint16_t)val;
3697379Sgblack@eecs.umich.edu        } else {
3707379Sgblack@eecs.umich.edu            if (val < 0) {
3717379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3727382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3737379Sgblack@eecs.umich.edu                return 0;
3747379Sgblack@eecs.umich.edu            }
3757379Sgblack@eecs.umich.edu            if (val > mask(32)) {
3767379Sgblack@eecs.umich.edu                feraiseexcept(FeInvalid);
3777382Sgblack@eecs.umich.edu                feclearexcept(FeInexact);
3787379Sgblack@eecs.umich.edu                return mask(32);
3797379Sgblack@eecs.umich.edu            }
3807379Sgblack@eecs.umich.edu            return (uint32_t)val;
3817379Sgblack@eecs.umich.edu        }
3827379Sgblack@eecs.umich.edu    }
3837379Sgblack@eecs.umich.edu}
3847379Sgblack@eecs.umich.edu
3857379Sgblack@eecs.umich.edustatic inline double
3867379Sgblack@eecs.umich.eduvfpUFixedToFpD(uint32_t val, bool half, uint8_t imm)
3877379Sgblack@eecs.umich.edu{
3887379Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
3897379Sgblack@eecs.umich.edu    if (half)
3907379Sgblack@eecs.umich.edu        val = (uint16_t)val;
3917382Sgblack@eecs.umich.edu    double scale = pow(2.0, imm);
3927382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
3937382Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
3947382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
3957382Sgblack@eecs.umich.edu    return val / scale;
3967379Sgblack@eecs.umich.edu}
3977379Sgblack@eecs.umich.edu
3987379Sgblack@eecs.umich.edustatic inline double
3997379Sgblack@eecs.umich.eduvfpSFixedToFpD(int32_t val, bool half, uint8_t imm)
4007379Sgblack@eecs.umich.edu{
4017379Sgblack@eecs.umich.edu    fesetround(FeRoundNearest);
4027379Sgblack@eecs.umich.edu    if (half)
4037379Sgblack@eecs.umich.edu        val = sext<16>(val & mask(16));
4047382Sgblack@eecs.umich.edu    double scale = pow(2.0, imm);
4057382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
4067382Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
4077382Sgblack@eecs.umich.edu    __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
4087382Sgblack@eecs.umich.edu    return val / scale;
4097379Sgblack@eecs.umich.edu}
4107379Sgblack@eecs.umich.edu
4117378Sgblack@eecs.umich.edutypedef int VfpSavedState;
4127378Sgblack@eecs.umich.edu
4137378Sgblack@eecs.umich.edustatic inline VfpSavedState
4147378Sgblack@eecs.umich.eduprepVfpFpscr(FPSCR fpscr)
4157378Sgblack@eecs.umich.edu{
4167378Sgblack@eecs.umich.edu    int roundingMode = fegetround();
4177378Sgblack@eecs.umich.edu    feclearexcept(FeAllExceptions);
4187378Sgblack@eecs.umich.edu    switch (fpscr.rMode) {
4197378Sgblack@eecs.umich.edu      case VfpRoundNearest:
4207378Sgblack@eecs.umich.edu        fesetround(FeRoundNearest);
4217378Sgblack@eecs.umich.edu        break;
4227378Sgblack@eecs.umich.edu      case VfpRoundUpward:
4237378Sgblack@eecs.umich.edu        fesetround(FeRoundUpward);
4247378Sgblack@eecs.umich.edu        break;
4257378Sgblack@eecs.umich.edu      case VfpRoundDown:
4267378Sgblack@eecs.umich.edu        fesetround(FeRoundDown);
4277378Sgblack@eecs.umich.edu        break;
4287378Sgblack@eecs.umich.edu      case VfpRoundZero:
4297378Sgblack@eecs.umich.edu        fesetround(FeRoundZero);
4307378Sgblack@eecs.umich.edu        break;
4317378Sgblack@eecs.umich.edu    }
4327378Sgblack@eecs.umich.edu    return roundingMode;
4337378Sgblack@eecs.umich.edu}
4347378Sgblack@eecs.umich.edu
4357378Sgblack@eecs.umich.edustatic inline FPSCR
4367378Sgblack@eecs.umich.edusetVfpFpscr(FPSCR fpscr, VfpSavedState state)
4377378Sgblack@eecs.umich.edu{
4387378Sgblack@eecs.umich.edu    int exceptions = fetestexcept(FeAllExceptions);
4397378Sgblack@eecs.umich.edu    if (exceptions & FeInvalid) {
4407378Sgblack@eecs.umich.edu        fpscr.ioc = 1;
4417378Sgblack@eecs.umich.edu    }
4427378Sgblack@eecs.umich.edu    if (exceptions & FeDivByZero) {
4437378Sgblack@eecs.umich.edu        fpscr.dzc = 1;
4447378Sgblack@eecs.umich.edu    }
4457378Sgblack@eecs.umich.edu    if (exceptions & FeOverflow) {
4467378Sgblack@eecs.umich.edu        fpscr.ofc = 1;
4477378Sgblack@eecs.umich.edu    }
4487378Sgblack@eecs.umich.edu    if (exceptions & FeUnderflow) {
4497378Sgblack@eecs.umich.edu        fpscr.ufc = 1;
4507378Sgblack@eecs.umich.edu    }
4517378Sgblack@eecs.umich.edu    if (exceptions & FeInexact) {
4527378Sgblack@eecs.umich.edu        fpscr.ixc = 1;
4537378Sgblack@eecs.umich.edu    }
4547378Sgblack@eecs.umich.edu    fesetround(state);
4557378Sgblack@eecs.umich.edu    return fpscr;
4567378Sgblack@eecs.umich.edu}
4577378Sgblack@eecs.umich.edu
4587376Sgblack@eecs.umich.educlass VfpMacroOp : public PredMacroOp
4597376Sgblack@eecs.umich.edu{
4607376Sgblack@eecs.umich.edu  public:
4617376Sgblack@eecs.umich.edu    static bool
4627376Sgblack@eecs.umich.edu    inScalarBank(IntRegIndex idx)
4637376Sgblack@eecs.umich.edu    {
4647376Sgblack@eecs.umich.edu        return (idx % 32) < 8;
4657376Sgblack@eecs.umich.edu    }
4667376Sgblack@eecs.umich.edu
4677376Sgblack@eecs.umich.edu  protected:
4687376Sgblack@eecs.umich.edu    bool wide;
4697376Sgblack@eecs.umich.edu
4707376Sgblack@eecs.umich.edu    VfpMacroOp(const char *mnem, ExtMachInst _machInst,
4717376Sgblack@eecs.umich.edu            OpClass __opClass, bool _wide) :
4727376Sgblack@eecs.umich.edu        PredMacroOp(mnem, _machInst, __opClass), wide(_wide)
4737376Sgblack@eecs.umich.edu    {}
4747376Sgblack@eecs.umich.edu
4757376Sgblack@eecs.umich.edu    IntRegIndex
4767376Sgblack@eecs.umich.edu    addStride(IntRegIndex idx, unsigned stride)
4777376Sgblack@eecs.umich.edu    {
4787376Sgblack@eecs.umich.edu        if (wide) {
4797376Sgblack@eecs.umich.edu            stride *= 2;
4807376Sgblack@eecs.umich.edu        }
4817376Sgblack@eecs.umich.edu        unsigned offset = idx % 8;
4827376Sgblack@eecs.umich.edu        idx = (IntRegIndex)(idx - offset);
4837376Sgblack@eecs.umich.edu        offset += stride;
4847376Sgblack@eecs.umich.edu        idx = (IntRegIndex)(idx + (offset % 8));
4857376Sgblack@eecs.umich.edu        return idx;
4867376Sgblack@eecs.umich.edu    }
4877376Sgblack@eecs.umich.edu
4887376Sgblack@eecs.umich.edu    void
4897376Sgblack@eecs.umich.edu    nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2)
4907376Sgblack@eecs.umich.edu    {
4917376Sgblack@eecs.umich.edu        unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
4927376Sgblack@eecs.umich.edu        assert(!inScalarBank(dest));
4937376Sgblack@eecs.umich.edu        dest = addStride(dest, stride);
4947376Sgblack@eecs.umich.edu        op1 = addStride(op1, stride);
4957376Sgblack@eecs.umich.edu        if (!inScalarBank(op2)) {
4967376Sgblack@eecs.umich.edu            op2 = addStride(op2, stride);
4977376Sgblack@eecs.umich.edu        }
4987376Sgblack@eecs.umich.edu    }
4997376Sgblack@eecs.umich.edu
5007376Sgblack@eecs.umich.edu    void
5017376Sgblack@eecs.umich.edu    nextIdxs(IntRegIndex &dest, IntRegIndex &op1)
5027376Sgblack@eecs.umich.edu    {
5037376Sgblack@eecs.umich.edu        unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
5047376Sgblack@eecs.umich.edu        assert(!inScalarBank(dest));
5057376Sgblack@eecs.umich.edu        dest = addStride(dest, stride);
5067376Sgblack@eecs.umich.edu        if (!inScalarBank(op1)) {
5077376Sgblack@eecs.umich.edu            op1 = addStride(op1, stride);
5087376Sgblack@eecs.umich.edu        }
5097376Sgblack@eecs.umich.edu    }
5107376Sgblack@eecs.umich.edu
5117376Sgblack@eecs.umich.edu    void
5127376Sgblack@eecs.umich.edu    nextIdxs(IntRegIndex &dest)
5137376Sgblack@eecs.umich.edu    {
5147376Sgblack@eecs.umich.edu        unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
5157376Sgblack@eecs.umich.edu        assert(!inScalarBank(dest));
5167376Sgblack@eecs.umich.edu        dest = addStride(dest, stride);
5177376Sgblack@eecs.umich.edu    }
5187376Sgblack@eecs.umich.edu};
5197376Sgblack@eecs.umich.edu
5207375Sgblack@eecs.umich.educlass VfpRegRegOp : public RegRegOp
5217375Sgblack@eecs.umich.edu{
5227375Sgblack@eecs.umich.edu  protected:
5237375Sgblack@eecs.umich.edu    VfpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
5247375Sgblack@eecs.umich.edu                IntRegIndex _dest, IntRegIndex _op1,
5257375Sgblack@eecs.umich.edu                VfpMicroMode mode = VfpNotAMicroop) :
5267375Sgblack@eecs.umich.edu        RegRegOp(mnem, _machInst, __opClass, _dest, _op1)
5277375Sgblack@eecs.umich.edu    {
5287375Sgblack@eecs.umich.edu        setVfpMicroFlags(mode, flags);
5297375Sgblack@eecs.umich.edu    }
5307375Sgblack@eecs.umich.edu};
5317375Sgblack@eecs.umich.edu
5327375Sgblack@eecs.umich.educlass VfpRegImmOp : public RegImmOp
5337375Sgblack@eecs.umich.edu{
5347375Sgblack@eecs.umich.edu  protected:
5357375Sgblack@eecs.umich.edu    VfpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
5367375Sgblack@eecs.umich.edu                IntRegIndex _dest, uint64_t _imm,
5377375Sgblack@eecs.umich.edu                VfpMicroMode mode = VfpNotAMicroop) :
5387375Sgblack@eecs.umich.edu        RegImmOp(mnem, _machInst, __opClass, _dest, _imm)
5397375Sgblack@eecs.umich.edu    {
5407375Sgblack@eecs.umich.edu        setVfpMicroFlags(mode, flags);
5417375Sgblack@eecs.umich.edu    }
5427375Sgblack@eecs.umich.edu};
5437375Sgblack@eecs.umich.edu
5447375Sgblack@eecs.umich.educlass VfpRegRegImmOp : public RegRegImmOp
5457375Sgblack@eecs.umich.edu{
5467375Sgblack@eecs.umich.edu  protected:
5477375Sgblack@eecs.umich.edu    VfpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
5487375Sgblack@eecs.umich.edu                   IntRegIndex _dest, IntRegIndex _op1,
5497375Sgblack@eecs.umich.edu                   uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) :
5507375Sgblack@eecs.umich.edu        RegRegImmOp(mnem, _machInst, __opClass, _dest, _op1, _imm)
5517375Sgblack@eecs.umich.edu    {
5527375Sgblack@eecs.umich.edu        setVfpMicroFlags(mode, flags);
5537375Sgblack@eecs.umich.edu    }
5547375Sgblack@eecs.umich.edu};
5557375Sgblack@eecs.umich.edu
5567375Sgblack@eecs.umich.educlass VfpRegRegRegOp : public RegRegRegOp
5577375Sgblack@eecs.umich.edu{
5587375Sgblack@eecs.umich.edu  protected:
5597375Sgblack@eecs.umich.edu    VfpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
5607375Sgblack@eecs.umich.edu                   IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
5617375Sgblack@eecs.umich.edu                   VfpMicroMode mode = VfpNotAMicroop) :
5627375Sgblack@eecs.umich.edu        RegRegRegOp(mnem, _machInst, __opClass, _dest, _op1, _op2)
5637375Sgblack@eecs.umich.edu    {
5647375Sgblack@eecs.umich.edu        setVfpMicroFlags(mode, flags);
5657375Sgblack@eecs.umich.edu    }
5667375Sgblack@eecs.umich.edu};
5677375Sgblack@eecs.umich.edu
5687384Sgblack@eecs.umich.edu}
5697384Sgblack@eecs.umich.edu
5707375Sgblack@eecs.umich.edu#endif //__ARCH_ARM_INSTS_VFP_HH__
571