vfp.hh revision 7398
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> 1097396Sgblack@eecs.umich.edustatic inline bool 1107396Sgblack@eecs.umich.eduflushToZero(fpType &op) 1117396Sgblack@eecs.umich.edu{ 1127396Sgblack@eecs.umich.edu fpType junk = 0.0; 1137396Sgblack@eecs.umich.edu if (std::fpclassify(op) == FP_SUBNORMAL) { 1147396Sgblack@eecs.umich.edu uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 1157396Sgblack@eecs.umich.edu op = bitsToFp(fpToBits(op) & bitMask, junk); 1167396Sgblack@eecs.umich.edu return true; 1177396Sgblack@eecs.umich.edu } 1187396Sgblack@eecs.umich.edu return false; 1197396Sgblack@eecs.umich.edu} 1207396Sgblack@eecs.umich.edu 1217396Sgblack@eecs.umich.edutemplate <class fpType> 1227396Sgblack@eecs.umich.edustatic inline bool 1237396Sgblack@eecs.umich.eduflushToZero(fpType &op1, fpType &op2) 1247396Sgblack@eecs.umich.edu{ 1257396Sgblack@eecs.umich.edu bool flush1 = flushToZero(op1); 1267396Sgblack@eecs.umich.edu bool flush2 = flushToZero(op2); 1277396Sgblack@eecs.umich.edu return flush1 || flush2; 1287396Sgblack@eecs.umich.edu} 1297396Sgblack@eecs.umich.edu 1307397Sgblack@eecs.umich.edutemplate <class fpType> 1317397Sgblack@eecs.umich.edustatic inline void 1327397Sgblack@eecs.umich.eduvfpFlushToZero(FPSCR &fpscr, fpType &op) 1337397Sgblack@eecs.umich.edu{ 1347397Sgblack@eecs.umich.edu if (fpscr.fz == 1 && flushToZero(op)) { 1357397Sgblack@eecs.umich.edu fpscr.idc = 1; 1367397Sgblack@eecs.umich.edu } 1377397Sgblack@eecs.umich.edu} 1387397Sgblack@eecs.umich.edu 1397397Sgblack@eecs.umich.edutemplate <class fpType> 1407397Sgblack@eecs.umich.edustatic inline void 1417397Sgblack@eecs.umich.eduvfpFlushToZero(FPSCR &fpscr, fpType &op1, fpType &op2) 1427397Sgblack@eecs.umich.edu{ 1437397Sgblack@eecs.umich.edu vfpFlushToZero(fpscr, op1); 1447397Sgblack@eecs.umich.edu vfpFlushToZero(fpscr, op2); 1457397Sgblack@eecs.umich.edu} 1467397Sgblack@eecs.umich.edu 1477384Sgblack@eecs.umich.edustatic inline uint32_t 1487384Sgblack@eecs.umich.edufpToBits(float fp) 1497384Sgblack@eecs.umich.edu{ 1507384Sgblack@eecs.umich.edu union 1517384Sgblack@eecs.umich.edu { 1527384Sgblack@eecs.umich.edu float fp; 1537384Sgblack@eecs.umich.edu uint32_t bits; 1547384Sgblack@eecs.umich.edu } val; 1557384Sgblack@eecs.umich.edu val.fp = fp; 1567384Sgblack@eecs.umich.edu return val.bits; 1577384Sgblack@eecs.umich.edu} 1587384Sgblack@eecs.umich.edu 1597384Sgblack@eecs.umich.edustatic inline uint64_t 1607384Sgblack@eecs.umich.edufpToBits(double fp) 1617384Sgblack@eecs.umich.edu{ 1627384Sgblack@eecs.umich.edu union 1637384Sgblack@eecs.umich.edu { 1647384Sgblack@eecs.umich.edu double fp; 1657384Sgblack@eecs.umich.edu uint64_t bits; 1667384Sgblack@eecs.umich.edu } val; 1677384Sgblack@eecs.umich.edu val.fp = fp; 1687384Sgblack@eecs.umich.edu return val.bits; 1697384Sgblack@eecs.umich.edu} 1707384Sgblack@eecs.umich.edu 1717384Sgblack@eecs.umich.edustatic inline float 1727384Sgblack@eecs.umich.edubitsToFp(uint64_t bits, float junk) 1737384Sgblack@eecs.umich.edu{ 1747384Sgblack@eecs.umich.edu union 1757384Sgblack@eecs.umich.edu { 1767384Sgblack@eecs.umich.edu float fp; 1777384Sgblack@eecs.umich.edu uint32_t bits; 1787384Sgblack@eecs.umich.edu } val; 1797384Sgblack@eecs.umich.edu val.bits = bits; 1807384Sgblack@eecs.umich.edu return val.fp; 1817384Sgblack@eecs.umich.edu} 1827384Sgblack@eecs.umich.edu 1837384Sgblack@eecs.umich.edustatic inline double 1847384Sgblack@eecs.umich.edubitsToFp(uint64_t bits, double junk) 1857384Sgblack@eecs.umich.edu{ 1867384Sgblack@eecs.umich.edu union 1877384Sgblack@eecs.umich.edu { 1887384Sgblack@eecs.umich.edu double fp; 1897384Sgblack@eecs.umich.edu uint64_t bits; 1907384Sgblack@eecs.umich.edu } val; 1917384Sgblack@eecs.umich.edu val.bits = bits; 1927384Sgblack@eecs.umich.edu return val.fp; 1937384Sgblack@eecs.umich.edu} 1947384Sgblack@eecs.umich.edu 1957396Sgblack@eecs.umich.edutypedef int VfpSavedState; 1967396Sgblack@eecs.umich.edu 1977396Sgblack@eecs.umich.edustatic inline VfpSavedState 1987396Sgblack@eecs.umich.eduprepFpState(uint32_t rMode) 1997396Sgblack@eecs.umich.edu{ 2007396Sgblack@eecs.umich.edu int roundingMode = fegetround(); 2017396Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 2027396Sgblack@eecs.umich.edu switch (rMode) { 2037396Sgblack@eecs.umich.edu case VfpRoundNearest: 2047396Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 2057396Sgblack@eecs.umich.edu break; 2067396Sgblack@eecs.umich.edu case VfpRoundUpward: 2077396Sgblack@eecs.umich.edu fesetround(FeRoundUpward); 2087396Sgblack@eecs.umich.edu break; 2097396Sgblack@eecs.umich.edu case VfpRoundDown: 2107396Sgblack@eecs.umich.edu fesetround(FeRoundDown); 2117396Sgblack@eecs.umich.edu break; 2127396Sgblack@eecs.umich.edu case VfpRoundZero: 2137396Sgblack@eecs.umich.edu fesetround(FeRoundZero); 2147396Sgblack@eecs.umich.edu break; 2157396Sgblack@eecs.umich.edu } 2167396Sgblack@eecs.umich.edu return roundingMode; 2177396Sgblack@eecs.umich.edu} 2187396Sgblack@eecs.umich.edu 2197396Sgblack@eecs.umich.edustatic inline void 2207396Sgblack@eecs.umich.edufinishVfp(FPSCR &fpscr, VfpSavedState state) 2217396Sgblack@eecs.umich.edu{ 2227396Sgblack@eecs.umich.edu int exceptions = fetestexcept(FeAllExceptions); 2237396Sgblack@eecs.umich.edu bool underflow = false; 2247396Sgblack@eecs.umich.edu if (exceptions & FeInvalid) { 2257396Sgblack@eecs.umich.edu fpscr.ioc = 1; 2267396Sgblack@eecs.umich.edu } 2277396Sgblack@eecs.umich.edu if (exceptions & FeDivByZero) { 2287396Sgblack@eecs.umich.edu fpscr.dzc = 1; 2297396Sgblack@eecs.umich.edu } 2307396Sgblack@eecs.umich.edu if (exceptions & FeOverflow) { 2317396Sgblack@eecs.umich.edu fpscr.ofc = 1; 2327396Sgblack@eecs.umich.edu } 2337396Sgblack@eecs.umich.edu if (exceptions & FeUnderflow) { 2347396Sgblack@eecs.umich.edu underflow = true; 2357396Sgblack@eecs.umich.edu fpscr.ufc = 1; 2367396Sgblack@eecs.umich.edu } 2377396Sgblack@eecs.umich.edu if ((exceptions & FeInexact) && !(underflow && fpscr.fz)) { 2387396Sgblack@eecs.umich.edu fpscr.ixc = 1; 2397396Sgblack@eecs.umich.edu } 2407396Sgblack@eecs.umich.edu fesetround(state); 2417396Sgblack@eecs.umich.edu} 2427396Sgblack@eecs.umich.edu 2437384Sgblack@eecs.umich.edutemplate <class fpType> 2447384Sgblack@eecs.umich.edustatic inline fpType 2457386Sgblack@eecs.umich.edufixDest(FPSCR fpscr, fpType val, fpType op1) 2467386Sgblack@eecs.umich.edu{ 2477386Sgblack@eecs.umich.edu int fpClass = std::fpclassify(val); 2487386Sgblack@eecs.umich.edu fpType junk = 0.0; 2497386Sgblack@eecs.umich.edu if (fpClass == FP_NAN) { 2507386Sgblack@eecs.umich.edu const bool single = (sizeof(val) == sizeof(float)); 2517386Sgblack@eecs.umich.edu const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 2527386Sgblack@eecs.umich.edu const bool nan = std::isnan(op1); 2537386Sgblack@eecs.umich.edu if (!nan || (fpscr.dn == 1)) { 2547386Sgblack@eecs.umich.edu val = bitsToFp(qnan, junk); 2557386Sgblack@eecs.umich.edu } else if (nan) { 2567386Sgblack@eecs.umich.edu val = bitsToFp(fpToBits(op1) | qnan, junk); 2577386Sgblack@eecs.umich.edu } 2587386Sgblack@eecs.umich.edu } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) { 2597386Sgblack@eecs.umich.edu // Turn val into a zero with the correct sign; 2607386Sgblack@eecs.umich.edu uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 2617386Sgblack@eecs.umich.edu val = bitsToFp(fpToBits(val) & bitMask, junk); 2627396Sgblack@eecs.umich.edu feclearexcept(FeInexact); 2637386Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 2647386Sgblack@eecs.umich.edu } 2657386Sgblack@eecs.umich.edu return val; 2667386Sgblack@eecs.umich.edu} 2677386Sgblack@eecs.umich.edu 2687386Sgblack@eecs.umich.edutemplate <class fpType> 2697386Sgblack@eecs.umich.edustatic inline fpType 2707385Sgblack@eecs.umich.edufixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2) 2717384Sgblack@eecs.umich.edu{ 2727385Sgblack@eecs.umich.edu int fpClass = std::fpclassify(val); 2737385Sgblack@eecs.umich.edu fpType junk = 0.0; 2747385Sgblack@eecs.umich.edu if (fpClass == FP_NAN) { 2757384Sgblack@eecs.umich.edu const bool single = (sizeof(val) == sizeof(float)); 2767384Sgblack@eecs.umich.edu const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 2777384Sgblack@eecs.umich.edu const bool nan1 = std::isnan(op1); 2787384Sgblack@eecs.umich.edu const bool nan2 = std::isnan(op2); 2797384Sgblack@eecs.umich.edu const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 2807384Sgblack@eecs.umich.edu const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); 2817384Sgblack@eecs.umich.edu if ((!nan1 && !nan2) || (fpscr.dn == 1)) { 2827384Sgblack@eecs.umich.edu val = bitsToFp(qnan, junk); 2837384Sgblack@eecs.umich.edu } else if (signal1) { 2847384Sgblack@eecs.umich.edu val = bitsToFp(fpToBits(op1) | qnan, junk); 2857384Sgblack@eecs.umich.edu } else if (signal2) { 2867384Sgblack@eecs.umich.edu val = bitsToFp(fpToBits(op2) | qnan, junk); 2877384Sgblack@eecs.umich.edu } else if (nan1) { 2887384Sgblack@eecs.umich.edu val = op1; 2897384Sgblack@eecs.umich.edu } else if (nan2) { 2907384Sgblack@eecs.umich.edu val = op2; 2917384Sgblack@eecs.umich.edu } 2927385Sgblack@eecs.umich.edu } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) { 2937385Sgblack@eecs.umich.edu // Turn val into a zero with the correct sign; 2947385Sgblack@eecs.umich.edu uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 2957385Sgblack@eecs.umich.edu val = bitsToFp(fpToBits(val) & bitMask, junk); 2967396Sgblack@eecs.umich.edu feclearexcept(FeInexact); 2977385Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 2987384Sgblack@eecs.umich.edu } 2997384Sgblack@eecs.umich.edu return val; 3007384Sgblack@eecs.umich.edu} 3017384Sgblack@eecs.umich.edu 3027386Sgblack@eecs.umich.edutemplate <class fpType> 3037386Sgblack@eecs.umich.edustatic inline fpType 3047386Sgblack@eecs.umich.edufixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2) 3057386Sgblack@eecs.umich.edu{ 3067386Sgblack@eecs.umich.edu fpType mid = fixDest(fpscr, val, op1, op2); 3077386Sgblack@eecs.umich.edu const bool single = (sizeof(fpType) == sizeof(float)); 3087386Sgblack@eecs.umich.edu const fpType junk = 0.0; 3097386Sgblack@eecs.umich.edu if ((single && (val == bitsToFp(0x00800000, junk) || 3107386Sgblack@eecs.umich.edu val == bitsToFp(0x80800000, junk))) || 3117386Sgblack@eecs.umich.edu (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) || 3127386Sgblack@eecs.umich.edu val == bitsToFp(ULL(0x8010000000000000), junk))) 3137386Sgblack@eecs.umich.edu ) { 3147386Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (op1) : "m" (op1)); 3157386Sgblack@eecs.umich.edu fesetround(FeRoundZero); 3167386Sgblack@eecs.umich.edu fpType temp = 0.0; 3177386Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 3187386Sgblack@eecs.umich.edu temp = op1 / op2; 3197396Sgblack@eecs.umich.edu if (flushToZero(temp)) { 3207386Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 3217396Sgblack@eecs.umich.edu if (fpscr.fz) { 3227396Sgblack@eecs.umich.edu feclearexcept(FeInexact); 3237396Sgblack@eecs.umich.edu mid = temp; 3247396Sgblack@eecs.umich.edu } 3257386Sgblack@eecs.umich.edu } 3267386Sgblack@eecs.umich.edu __asm__ __volatile__("" :: "m" (temp)); 3277386Sgblack@eecs.umich.edu } 3287386Sgblack@eecs.umich.edu return mid; 3297386Sgblack@eecs.umich.edu} 3307386Sgblack@eecs.umich.edu 3317386Sgblack@eecs.umich.edustatic inline float 3327386Sgblack@eecs.umich.edufixFpDFpSDest(FPSCR fpscr, double val) 3337386Sgblack@eecs.umich.edu{ 3347386Sgblack@eecs.umich.edu const float junk = 0.0; 3357386Sgblack@eecs.umich.edu float op1 = 0.0; 3367386Sgblack@eecs.umich.edu if (std::isnan(val)) { 3377386Sgblack@eecs.umich.edu uint64_t valBits = fpToBits(val); 3387386Sgblack@eecs.umich.edu uint32_t op1Bits = bits(valBits, 50, 29) | 3397386Sgblack@eecs.umich.edu (mask(9) << 22) | 3407386Sgblack@eecs.umich.edu (bits(valBits, 63) << 31); 3417386Sgblack@eecs.umich.edu op1 = bitsToFp(op1Bits, junk); 3427386Sgblack@eecs.umich.edu } 3437386Sgblack@eecs.umich.edu float mid = fixDest(fpscr, (float)val, op1); 3447396Sgblack@eecs.umich.edu if (fpscr.fz && fetestexcept(FeUnderflow | FeInexact) == 3457396Sgblack@eecs.umich.edu (FeUnderflow | FeInexact)) { 3467396Sgblack@eecs.umich.edu feclearexcept(FeInexact); 3477396Sgblack@eecs.umich.edu } 3487386Sgblack@eecs.umich.edu if (mid == bitsToFp(0x00800000, junk) || 3497386Sgblack@eecs.umich.edu mid == bitsToFp(0x80800000, junk)) { 3507386Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 3517386Sgblack@eecs.umich.edu fesetround(FeRoundZero); 3527386Sgblack@eecs.umich.edu float temp = 0.0; 3537386Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 3547386Sgblack@eecs.umich.edu temp = val; 3557396Sgblack@eecs.umich.edu if (flushToZero(temp)) { 3567386Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 3577396Sgblack@eecs.umich.edu if (fpscr.fz) { 3587396Sgblack@eecs.umich.edu feclearexcept(FeInexact); 3597396Sgblack@eecs.umich.edu mid = temp; 3607396Sgblack@eecs.umich.edu } 3617386Sgblack@eecs.umich.edu } 3627386Sgblack@eecs.umich.edu __asm__ __volatile__("" :: "m" (temp)); 3637386Sgblack@eecs.umich.edu } 3647386Sgblack@eecs.umich.edu return mid; 3657386Sgblack@eecs.umich.edu} 3667386Sgblack@eecs.umich.edu 3677396Sgblack@eecs.umich.edustatic inline double 3687396Sgblack@eecs.umich.edufixFpSFpDDest(FPSCR fpscr, float val) 3697396Sgblack@eecs.umich.edu{ 3707396Sgblack@eecs.umich.edu const double junk = 0.0; 3717396Sgblack@eecs.umich.edu double op1 = 0.0; 3727396Sgblack@eecs.umich.edu if (std::isnan(val)) { 3737396Sgblack@eecs.umich.edu uint32_t valBits = fpToBits(val); 3747396Sgblack@eecs.umich.edu uint64_t op1Bits = ((uint64_t)bits(valBits, 21, 0) << 29) | 3757396Sgblack@eecs.umich.edu (mask(12) << 51) | 3767396Sgblack@eecs.umich.edu ((uint64_t)bits(valBits, 31) << 63); 3777396Sgblack@eecs.umich.edu op1 = bitsToFp(op1Bits, junk); 3787396Sgblack@eecs.umich.edu } 3797396Sgblack@eecs.umich.edu double mid = fixDest(fpscr, (double)val, op1); 3807396Sgblack@eecs.umich.edu if (mid == bitsToFp(ULL(0x0010000000000000), junk) || 3817396Sgblack@eecs.umich.edu mid == bitsToFp(ULL(0x8010000000000000), junk)) { 3827396Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 3837396Sgblack@eecs.umich.edu fesetround(FeRoundZero); 3847396Sgblack@eecs.umich.edu double temp = 0.0; 3857396Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 3867396Sgblack@eecs.umich.edu temp = val; 3877396Sgblack@eecs.umich.edu if (flushToZero(temp)) { 3887396Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 3897396Sgblack@eecs.umich.edu if (fpscr.fz) { 3907396Sgblack@eecs.umich.edu feclearexcept(FeInexact); 3917396Sgblack@eecs.umich.edu mid = temp; 3927396Sgblack@eecs.umich.edu } 3937396Sgblack@eecs.umich.edu } 3947396Sgblack@eecs.umich.edu __asm__ __volatile__("" :: "m" (temp)); 3957396Sgblack@eecs.umich.edu } 3967396Sgblack@eecs.umich.edu return mid; 3977396Sgblack@eecs.umich.edu} 3987396Sgblack@eecs.umich.edu 3997398Sgblack@eecs.umich.edustatic inline float 4007398Sgblack@eecs.umich.eduvcvtFpSFpH(FPSCR &fpscr, float op, float dest, bool top) 4017398Sgblack@eecs.umich.edu{ 4027398Sgblack@eecs.umich.edu float junk = 0.0; 4037398Sgblack@eecs.umich.edu uint32_t destBits = fpToBits(dest); 4047398Sgblack@eecs.umich.edu uint32_t opBits = fpToBits(op); 4057398Sgblack@eecs.umich.edu // Extract the operand. 4067398Sgblack@eecs.umich.edu bool neg = bits(opBits, 31); 4077398Sgblack@eecs.umich.edu uint32_t exponent = bits(opBits, 30, 23); 4087398Sgblack@eecs.umich.edu uint32_t oldMantissa = bits(opBits, 22, 0); 4097398Sgblack@eecs.umich.edu uint32_t mantissa = oldMantissa >> (23 - 10); 4107398Sgblack@eecs.umich.edu // Do the conversion. 4117398Sgblack@eecs.umich.edu uint32_t extra = oldMantissa & mask(23 - 10); 4127398Sgblack@eecs.umich.edu if (exponent == 0xff) { 4137398Sgblack@eecs.umich.edu if (oldMantissa != 0) { 4147398Sgblack@eecs.umich.edu // Nans. 4157398Sgblack@eecs.umich.edu if (bits(mantissa, 9) == 0) { 4167398Sgblack@eecs.umich.edu // Signalling nan. 4177398Sgblack@eecs.umich.edu fpscr.ioc = 1; 4187398Sgblack@eecs.umich.edu } 4197398Sgblack@eecs.umich.edu if (fpscr.ahp) { 4207398Sgblack@eecs.umich.edu mantissa = 0; 4217398Sgblack@eecs.umich.edu exponent = 0; 4227398Sgblack@eecs.umich.edu fpscr.ioc = 1; 4237398Sgblack@eecs.umich.edu } else if (fpscr.dn) { 4247398Sgblack@eecs.umich.edu mantissa = (1 << 9); 4257398Sgblack@eecs.umich.edu exponent = 0x1f; 4267398Sgblack@eecs.umich.edu neg = false; 4277398Sgblack@eecs.umich.edu } else { 4287398Sgblack@eecs.umich.edu exponent = 0x1f; 4297398Sgblack@eecs.umich.edu mantissa |= (1 << 9); 4307398Sgblack@eecs.umich.edu } 4317398Sgblack@eecs.umich.edu } else { 4327398Sgblack@eecs.umich.edu // Infinities. 4337398Sgblack@eecs.umich.edu exponent = 0x1F; 4347398Sgblack@eecs.umich.edu if (fpscr.ahp) { 4357398Sgblack@eecs.umich.edu fpscr.ioc = 1; 4367398Sgblack@eecs.umich.edu mantissa = 0x3ff; 4377398Sgblack@eecs.umich.edu } else { 4387398Sgblack@eecs.umich.edu mantissa = 0; 4397398Sgblack@eecs.umich.edu } 4407398Sgblack@eecs.umich.edu } 4417398Sgblack@eecs.umich.edu } else if (exponent == 0 && oldMantissa == 0) { 4427398Sgblack@eecs.umich.edu // Zero, don't need to do anything. 4437398Sgblack@eecs.umich.edu } else { 4447398Sgblack@eecs.umich.edu // Normalized or denormalized numbers. 4457398Sgblack@eecs.umich.edu 4467398Sgblack@eecs.umich.edu bool inexact = (extra != 0); 4477398Sgblack@eecs.umich.edu 4487398Sgblack@eecs.umich.edu if (exponent == 0) { 4497398Sgblack@eecs.umich.edu // Denormalized. 4507398Sgblack@eecs.umich.edu 4517398Sgblack@eecs.umich.edu // If flush to zero is on, this shouldn't happen. 4527398Sgblack@eecs.umich.edu assert(fpscr.fz == 0); 4537398Sgblack@eecs.umich.edu 4547398Sgblack@eecs.umich.edu // Check for underflow 4557398Sgblack@eecs.umich.edu if (inexact || fpscr.ufe) 4567398Sgblack@eecs.umich.edu fpscr.ufc = 1; 4577398Sgblack@eecs.umich.edu 4587398Sgblack@eecs.umich.edu // Handle rounding. 4597398Sgblack@eecs.umich.edu unsigned mode = fpscr.rMode; 4607398Sgblack@eecs.umich.edu if ((mode == VfpRoundUpward && !neg && extra) || 4617398Sgblack@eecs.umich.edu (mode == VfpRoundDown && neg && extra) || 4627398Sgblack@eecs.umich.edu (mode == VfpRoundNearest && 4637398Sgblack@eecs.umich.edu (extra > (1 << 9) || 4647398Sgblack@eecs.umich.edu (extra == (1 << 9) && bits(mantissa, 0))))) { 4657398Sgblack@eecs.umich.edu mantissa++; 4667398Sgblack@eecs.umich.edu } 4677398Sgblack@eecs.umich.edu 4687398Sgblack@eecs.umich.edu // See if the number became normalized after rounding. 4697398Sgblack@eecs.umich.edu if (mantissa == (1 << 10)) { 4707398Sgblack@eecs.umich.edu mantissa = 0; 4717398Sgblack@eecs.umich.edu exponent = 1; 4727398Sgblack@eecs.umich.edu } 4737398Sgblack@eecs.umich.edu } else { 4747398Sgblack@eecs.umich.edu // Normalized. 4757398Sgblack@eecs.umich.edu 4767398Sgblack@eecs.umich.edu // We need to track the dropped bits differently since 4777398Sgblack@eecs.umich.edu // more can be dropped by denormalizing. 4787398Sgblack@eecs.umich.edu bool topOne = bits(extra, 12); 4797398Sgblack@eecs.umich.edu bool restZeros = bits(extra, 11, 0) == 0; 4807398Sgblack@eecs.umich.edu 4817398Sgblack@eecs.umich.edu if (exponent <= (127 - 15)) { 4827398Sgblack@eecs.umich.edu // The result is too small. Denormalize. 4837398Sgblack@eecs.umich.edu mantissa |= (1 << 10); 4847398Sgblack@eecs.umich.edu while (mantissa && exponent <= (127 - 15)) { 4857398Sgblack@eecs.umich.edu restZeros = restZeros && !topOne; 4867398Sgblack@eecs.umich.edu topOne = bits(mantissa, 0); 4877398Sgblack@eecs.umich.edu mantissa = mantissa >> 1; 4887398Sgblack@eecs.umich.edu exponent++; 4897398Sgblack@eecs.umich.edu } 4907398Sgblack@eecs.umich.edu if (topOne || !restZeros) 4917398Sgblack@eecs.umich.edu inexact = true; 4927398Sgblack@eecs.umich.edu exponent = 0; 4937398Sgblack@eecs.umich.edu } else { 4947398Sgblack@eecs.umich.edu // Change bias. 4957398Sgblack@eecs.umich.edu exponent -= (127 - 15); 4967398Sgblack@eecs.umich.edu } 4977398Sgblack@eecs.umich.edu 4987398Sgblack@eecs.umich.edu if (exponent == 0 && (inexact || fpscr.ufe)) { 4997398Sgblack@eecs.umich.edu // Underflow 5007398Sgblack@eecs.umich.edu fpscr.ufc = 1; 5017398Sgblack@eecs.umich.edu } 5027398Sgblack@eecs.umich.edu 5037398Sgblack@eecs.umich.edu // Handle rounding. 5047398Sgblack@eecs.umich.edu unsigned mode = fpscr.rMode; 5057398Sgblack@eecs.umich.edu bool nonZero = topOne || !restZeros; 5067398Sgblack@eecs.umich.edu if ((mode == VfpRoundUpward && !neg && nonZero) || 5077398Sgblack@eecs.umich.edu (mode == VfpRoundDown && neg && nonZero) || 5087398Sgblack@eecs.umich.edu (mode == VfpRoundNearest && topOne && 5097398Sgblack@eecs.umich.edu (!restZeros || bits(mantissa, 0)))) { 5107398Sgblack@eecs.umich.edu mantissa++; 5117398Sgblack@eecs.umich.edu } 5127398Sgblack@eecs.umich.edu 5137398Sgblack@eecs.umich.edu // See if we rounded up and need to bump the exponent. 5147398Sgblack@eecs.umich.edu if (mantissa == (1 << 10)) { 5157398Sgblack@eecs.umich.edu mantissa = 0; 5167398Sgblack@eecs.umich.edu exponent++; 5177398Sgblack@eecs.umich.edu } 5187398Sgblack@eecs.umich.edu 5197398Sgblack@eecs.umich.edu // Deal with overflow 5207398Sgblack@eecs.umich.edu if (fpscr.ahp) { 5217398Sgblack@eecs.umich.edu if (exponent >= 0x20) { 5227398Sgblack@eecs.umich.edu exponent = 0x1f; 5237398Sgblack@eecs.umich.edu mantissa = 0x3ff; 5247398Sgblack@eecs.umich.edu fpscr.ioc = 1; 5257398Sgblack@eecs.umich.edu // Supress inexact exception. 5267398Sgblack@eecs.umich.edu inexact = false; 5277398Sgblack@eecs.umich.edu } 5287398Sgblack@eecs.umich.edu } else { 5297398Sgblack@eecs.umich.edu if (exponent >= 0x1f) { 5307398Sgblack@eecs.umich.edu if ((mode == VfpRoundNearest) || 5317398Sgblack@eecs.umich.edu (mode == VfpRoundUpward && !neg) || 5327398Sgblack@eecs.umich.edu (mode == VfpRoundDown && neg)) { 5337398Sgblack@eecs.umich.edu // Overflow to infinity. 5347398Sgblack@eecs.umich.edu exponent = 0x1f; 5357398Sgblack@eecs.umich.edu mantissa = 0; 5367398Sgblack@eecs.umich.edu } else { 5377398Sgblack@eecs.umich.edu // Overflow to max normal. 5387398Sgblack@eecs.umich.edu exponent = 0x1e; 5397398Sgblack@eecs.umich.edu mantissa = 0x3ff; 5407398Sgblack@eecs.umich.edu } 5417398Sgblack@eecs.umich.edu fpscr.ofc = 1; 5427398Sgblack@eecs.umich.edu inexact = true; 5437398Sgblack@eecs.umich.edu } 5447398Sgblack@eecs.umich.edu } 5457398Sgblack@eecs.umich.edu } 5467398Sgblack@eecs.umich.edu 5477398Sgblack@eecs.umich.edu if (inexact) { 5487398Sgblack@eecs.umich.edu fpscr.ixc = 1; 5497398Sgblack@eecs.umich.edu } 5507398Sgblack@eecs.umich.edu } 5517398Sgblack@eecs.umich.edu // Reassemble and install the result. 5527398Sgblack@eecs.umich.edu uint32_t result = bits(mantissa, 9, 0); 5537398Sgblack@eecs.umich.edu replaceBits(result, 14, 10, exponent); 5547398Sgblack@eecs.umich.edu if (neg) 5557398Sgblack@eecs.umich.edu result |= (1 << 15); 5567398Sgblack@eecs.umich.edu if (top) 5577398Sgblack@eecs.umich.edu replaceBits(destBits, 31, 16, result); 5587398Sgblack@eecs.umich.edu else 5597398Sgblack@eecs.umich.edu replaceBits(destBits, 15, 0, result); 5607398Sgblack@eecs.umich.edu return bitsToFp(destBits, junk); 5617398Sgblack@eecs.umich.edu} 5627398Sgblack@eecs.umich.edu 5637398Sgblack@eecs.umich.edustatic inline float 5647398Sgblack@eecs.umich.eduvcvtFpHFpS(FPSCR &fpscr, float op, bool top) 5657398Sgblack@eecs.umich.edu{ 5667398Sgblack@eecs.umich.edu float junk = 0.0; 5677398Sgblack@eecs.umich.edu uint32_t opBits = fpToBits(op); 5687398Sgblack@eecs.umich.edu // Extract the operand. 5697398Sgblack@eecs.umich.edu if (top) 5707398Sgblack@eecs.umich.edu opBits = bits(opBits, 31, 16); 5717398Sgblack@eecs.umich.edu else 5727398Sgblack@eecs.umich.edu opBits = bits(opBits, 15, 0); 5737398Sgblack@eecs.umich.edu // Extract the bitfields. 5747398Sgblack@eecs.umich.edu bool neg = bits(opBits, 15); 5757398Sgblack@eecs.umich.edu uint32_t exponent = bits(opBits, 14, 10); 5767398Sgblack@eecs.umich.edu uint32_t mantissa = bits(opBits, 9, 0); 5777398Sgblack@eecs.umich.edu // Do the conversion. 5787398Sgblack@eecs.umich.edu if (exponent == 0) { 5797398Sgblack@eecs.umich.edu if (mantissa != 0) { 5807398Sgblack@eecs.umich.edu // Normalize the value. 5817398Sgblack@eecs.umich.edu exponent = exponent + (127 - 15) + 1; 5827398Sgblack@eecs.umich.edu while (mantissa < (1 << 10)) { 5837398Sgblack@eecs.umich.edu mantissa = mantissa << 1; 5847398Sgblack@eecs.umich.edu exponent--; 5857398Sgblack@eecs.umich.edu } 5867398Sgblack@eecs.umich.edu } 5877398Sgblack@eecs.umich.edu mantissa = mantissa << (23 - 10); 5887398Sgblack@eecs.umich.edu } else if (exponent == 0x1f && !fpscr.ahp) { 5897398Sgblack@eecs.umich.edu // Infinities and nans. 5907398Sgblack@eecs.umich.edu exponent = 0xff; 5917398Sgblack@eecs.umich.edu if (mantissa != 0) { 5927398Sgblack@eecs.umich.edu // Nans. 5937398Sgblack@eecs.umich.edu mantissa = mantissa << (23 - 10); 5947398Sgblack@eecs.umich.edu if (bits(mantissa, 22) == 0) { 5957398Sgblack@eecs.umich.edu // Signalling nan. 5967398Sgblack@eecs.umich.edu fpscr.ioc = 1; 5977398Sgblack@eecs.umich.edu mantissa |= (1 << 22); 5987398Sgblack@eecs.umich.edu } 5997398Sgblack@eecs.umich.edu if (fpscr.dn) { 6007398Sgblack@eecs.umich.edu mantissa &= ~mask(22); 6017398Sgblack@eecs.umich.edu neg = false; 6027398Sgblack@eecs.umich.edu } 6037398Sgblack@eecs.umich.edu } 6047398Sgblack@eecs.umich.edu } else { 6057398Sgblack@eecs.umich.edu exponent = exponent + (127 - 15); 6067398Sgblack@eecs.umich.edu mantissa = mantissa << (23 - 10); 6077398Sgblack@eecs.umich.edu } 6087398Sgblack@eecs.umich.edu // Reassemble the result. 6097398Sgblack@eecs.umich.edu uint32_t result = bits(mantissa, 22, 0); 6107398Sgblack@eecs.umich.edu replaceBits(result, 30, 23, exponent); 6117398Sgblack@eecs.umich.edu if (neg) 6127398Sgblack@eecs.umich.edu result |= (1 << 31); 6137398Sgblack@eecs.umich.edu return bitsToFp(result, junk); 6147398Sgblack@eecs.umich.edu} 6157398Sgblack@eecs.umich.edu 6167396Sgblack@eecs.umich.edustatic inline double 6177396Sgblack@eecs.umich.edumakeDouble(uint32_t low, uint32_t high) 6187396Sgblack@eecs.umich.edu{ 6197396Sgblack@eecs.umich.edu double junk = 0.0; 6207396Sgblack@eecs.umich.edu return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 6217396Sgblack@eecs.umich.edu} 6227396Sgblack@eecs.umich.edu 6237396Sgblack@eecs.umich.edustatic inline uint32_t 6247396Sgblack@eecs.umich.edulowFromDouble(double val) 6257396Sgblack@eecs.umich.edu{ 6267396Sgblack@eecs.umich.edu return fpToBits(val); 6277396Sgblack@eecs.umich.edu} 6287396Sgblack@eecs.umich.edu 6297396Sgblack@eecs.umich.edustatic inline uint32_t 6307396Sgblack@eecs.umich.eduhighFromDouble(double val) 6317396Sgblack@eecs.umich.edu{ 6327396Sgblack@eecs.umich.edu return fpToBits(val) >> 32; 6337396Sgblack@eecs.umich.edu} 6347396Sgblack@eecs.umich.edu 6357379Sgblack@eecs.umich.edustatic inline uint64_t 6367388Sgblack@eecs.umich.eduvfpFpSToFixed(float val, bool isSigned, bool half, 6377388Sgblack@eecs.umich.edu uint8_t imm, bool rzero = true) 6387379Sgblack@eecs.umich.edu{ 6397396Sgblack@eecs.umich.edu int rmode = rzero ? FeRoundZero : fegetround(); 6407396Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (rmode) : "m" (rmode)); 6417388Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 6427379Sgblack@eecs.umich.edu val = val * powf(2.0, imm); 6437379Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 6447396Sgblack@eecs.umich.edu fesetround(rmode); 6457379Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 6467382Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 6477382Sgblack@eecs.umich.edu float origVal = val; 6487382Sgblack@eecs.umich.edu val = rintf(val); 6497382Sgblack@eecs.umich.edu int fpType = std::fpclassify(val); 6507382Sgblack@eecs.umich.edu if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { 6517382Sgblack@eecs.umich.edu if (fpType == FP_NAN) { 6527382Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 6537382Sgblack@eecs.umich.edu } 6547382Sgblack@eecs.umich.edu val = 0.0; 6557382Sgblack@eecs.umich.edu } else if (origVal != val) { 6567396Sgblack@eecs.umich.edu switch (rmode) { 6577396Sgblack@eecs.umich.edu case FeRoundNearest: 6587396Sgblack@eecs.umich.edu if (origVal - val > 0.5) 6597396Sgblack@eecs.umich.edu val += 1.0; 6607396Sgblack@eecs.umich.edu else if (val - origVal > 0.5) 6617396Sgblack@eecs.umich.edu val -= 1.0; 6627396Sgblack@eecs.umich.edu break; 6637396Sgblack@eecs.umich.edu case FeRoundDown: 6647396Sgblack@eecs.umich.edu if (origVal < val) 6657396Sgblack@eecs.umich.edu val -= 1.0; 6667396Sgblack@eecs.umich.edu break; 6677396Sgblack@eecs.umich.edu case FeRoundUpward: 6687396Sgblack@eecs.umich.edu if (origVal > val) 6697396Sgblack@eecs.umich.edu val += 1.0; 6707396Sgblack@eecs.umich.edu break; 6717396Sgblack@eecs.umich.edu } 6727382Sgblack@eecs.umich.edu feraiseexcept(FeInexact); 6737382Sgblack@eecs.umich.edu } 6747382Sgblack@eecs.umich.edu 6757379Sgblack@eecs.umich.edu if (isSigned) { 6767379Sgblack@eecs.umich.edu if (half) { 6777381Sgblack@eecs.umich.edu if ((double)val < (int16_t)(1 << 15)) { 6787379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 6797382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 6807379Sgblack@eecs.umich.edu return (int16_t)(1 << 15); 6817379Sgblack@eecs.umich.edu } 6827381Sgblack@eecs.umich.edu if ((double)val > (int16_t)mask(15)) { 6837379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 6847382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 6857379Sgblack@eecs.umich.edu return (int16_t)mask(15); 6867379Sgblack@eecs.umich.edu } 6877379Sgblack@eecs.umich.edu return (int16_t)val; 6887379Sgblack@eecs.umich.edu } else { 6897381Sgblack@eecs.umich.edu if ((double)val < (int32_t)(1 << 31)) { 6907379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 6917382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 6927379Sgblack@eecs.umich.edu return (int32_t)(1 << 31); 6937379Sgblack@eecs.umich.edu } 6947381Sgblack@eecs.umich.edu if ((double)val > (int32_t)mask(31)) { 6957379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 6967382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 6977379Sgblack@eecs.umich.edu return (int32_t)mask(31); 6987379Sgblack@eecs.umich.edu } 6997379Sgblack@eecs.umich.edu return (int32_t)val; 7007379Sgblack@eecs.umich.edu } 7017379Sgblack@eecs.umich.edu } else { 7027379Sgblack@eecs.umich.edu if (half) { 7037381Sgblack@eecs.umich.edu if ((double)val < 0) { 7047379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 7057382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 7067379Sgblack@eecs.umich.edu return 0; 7077379Sgblack@eecs.umich.edu } 7087381Sgblack@eecs.umich.edu if ((double)val > (mask(16))) { 7097379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 7107382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 7117379Sgblack@eecs.umich.edu return mask(16); 7127379Sgblack@eecs.umich.edu } 7137379Sgblack@eecs.umich.edu return (uint16_t)val; 7147379Sgblack@eecs.umich.edu } else { 7157381Sgblack@eecs.umich.edu if ((double)val < 0) { 7167379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 7177382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 7187379Sgblack@eecs.umich.edu return 0; 7197379Sgblack@eecs.umich.edu } 7207381Sgblack@eecs.umich.edu if ((double)val > (mask(32))) { 7217379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 7227382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 7237379Sgblack@eecs.umich.edu return mask(32); 7247379Sgblack@eecs.umich.edu } 7257379Sgblack@eecs.umich.edu return (uint32_t)val; 7267379Sgblack@eecs.umich.edu } 7277379Sgblack@eecs.umich.edu } 7287379Sgblack@eecs.umich.edu} 7297379Sgblack@eecs.umich.edu 7307379Sgblack@eecs.umich.edustatic inline float 7317386Sgblack@eecs.umich.eduvfpUFixedToFpS(FPSCR fpscr, uint32_t val, bool half, uint8_t imm) 7327379Sgblack@eecs.umich.edu{ 7337379Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 7347379Sgblack@eecs.umich.edu if (half) 7357379Sgblack@eecs.umich.edu val = (uint16_t)val; 7367382Sgblack@eecs.umich.edu float scale = powf(2.0, imm); 7377382Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 7387382Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 7397382Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 7407386Sgblack@eecs.umich.edu return fixDivDest(fpscr, val / scale, (float)val, scale); 7417379Sgblack@eecs.umich.edu} 7427379Sgblack@eecs.umich.edu 7437379Sgblack@eecs.umich.edustatic inline float 7447386Sgblack@eecs.umich.eduvfpSFixedToFpS(FPSCR fpscr, int32_t val, bool half, uint8_t imm) 7457379Sgblack@eecs.umich.edu{ 7467379Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 7477379Sgblack@eecs.umich.edu if (half) 7487379Sgblack@eecs.umich.edu val = sext<16>(val & mask(16)); 7497382Sgblack@eecs.umich.edu float scale = powf(2.0, imm); 7507382Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 7517382Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 7527382Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 7537386Sgblack@eecs.umich.edu return fixDivDest(fpscr, val / scale, (float)val, scale); 7547379Sgblack@eecs.umich.edu} 7557379Sgblack@eecs.umich.edu 7567379Sgblack@eecs.umich.edustatic inline uint64_t 7577388Sgblack@eecs.umich.eduvfpFpDToFixed(double val, bool isSigned, bool half, 7587388Sgblack@eecs.umich.edu uint8_t imm, bool rzero = true) 7597379Sgblack@eecs.umich.edu{ 7607396Sgblack@eecs.umich.edu int rmode = rzero ? FeRoundZero : fegetround(); 7617382Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 7627379Sgblack@eecs.umich.edu val = val * pow(2.0, imm); 7637379Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 7647396Sgblack@eecs.umich.edu fesetround(rmode); 7657379Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 7667382Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 7677382Sgblack@eecs.umich.edu double origVal = val; 7687382Sgblack@eecs.umich.edu val = rint(val); 7697382Sgblack@eecs.umich.edu int fpType = std::fpclassify(val); 7707382Sgblack@eecs.umich.edu if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { 7717382Sgblack@eecs.umich.edu if (fpType == FP_NAN) { 7727382Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 7737382Sgblack@eecs.umich.edu } 7747382Sgblack@eecs.umich.edu val = 0.0; 7757382Sgblack@eecs.umich.edu } else if (origVal != val) { 7767396Sgblack@eecs.umich.edu switch (rmode) { 7777396Sgblack@eecs.umich.edu case FeRoundNearest: 7787396Sgblack@eecs.umich.edu if (origVal - val > 0.5) 7797396Sgblack@eecs.umich.edu val += 1.0; 7807396Sgblack@eecs.umich.edu else if (val - origVal > 0.5) 7817396Sgblack@eecs.umich.edu val -= 1.0; 7827396Sgblack@eecs.umich.edu break; 7837396Sgblack@eecs.umich.edu case FeRoundDown: 7847396Sgblack@eecs.umich.edu if (origVal < val) 7857396Sgblack@eecs.umich.edu val -= 1.0; 7867396Sgblack@eecs.umich.edu break; 7877396Sgblack@eecs.umich.edu case FeRoundUpward: 7887396Sgblack@eecs.umich.edu if (origVal > val) 7897396Sgblack@eecs.umich.edu val += 1.0; 7907396Sgblack@eecs.umich.edu break; 7917396Sgblack@eecs.umich.edu } 7927382Sgblack@eecs.umich.edu feraiseexcept(FeInexact); 7937382Sgblack@eecs.umich.edu } 7947379Sgblack@eecs.umich.edu if (isSigned) { 7957379Sgblack@eecs.umich.edu if (half) { 7967379Sgblack@eecs.umich.edu if (val < (int16_t)(1 << 15)) { 7977379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 7987382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 7997379Sgblack@eecs.umich.edu return (int16_t)(1 << 15); 8007379Sgblack@eecs.umich.edu } 8017379Sgblack@eecs.umich.edu if (val > (int16_t)mask(15)) { 8027379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 8037382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 8047379Sgblack@eecs.umich.edu return (int16_t)mask(15); 8057379Sgblack@eecs.umich.edu } 8067379Sgblack@eecs.umich.edu return (int16_t)val; 8077379Sgblack@eecs.umich.edu } else { 8087379Sgblack@eecs.umich.edu if (val < (int32_t)(1 << 31)) { 8097379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 8107382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 8117379Sgblack@eecs.umich.edu return (int32_t)(1 << 31); 8127379Sgblack@eecs.umich.edu } 8137379Sgblack@eecs.umich.edu if (val > (int32_t)mask(31)) { 8147379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 8157382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 8167379Sgblack@eecs.umich.edu return (int32_t)mask(31); 8177379Sgblack@eecs.umich.edu } 8187379Sgblack@eecs.umich.edu return (int32_t)val; 8197379Sgblack@eecs.umich.edu } 8207379Sgblack@eecs.umich.edu } else { 8217379Sgblack@eecs.umich.edu if (half) { 8227379Sgblack@eecs.umich.edu if (val < 0) { 8237379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 8247382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 8257379Sgblack@eecs.umich.edu return 0; 8267379Sgblack@eecs.umich.edu } 8277379Sgblack@eecs.umich.edu if (val > mask(16)) { 8287379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 8297382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 8307379Sgblack@eecs.umich.edu return mask(16); 8317379Sgblack@eecs.umich.edu } 8327379Sgblack@eecs.umich.edu return (uint16_t)val; 8337379Sgblack@eecs.umich.edu } else { 8347379Sgblack@eecs.umich.edu if (val < 0) { 8357379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 8367382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 8377379Sgblack@eecs.umich.edu return 0; 8387379Sgblack@eecs.umich.edu } 8397379Sgblack@eecs.umich.edu if (val > mask(32)) { 8407379Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 8417382Sgblack@eecs.umich.edu feclearexcept(FeInexact); 8427379Sgblack@eecs.umich.edu return mask(32); 8437379Sgblack@eecs.umich.edu } 8447379Sgblack@eecs.umich.edu return (uint32_t)val; 8457379Sgblack@eecs.umich.edu } 8467379Sgblack@eecs.umich.edu } 8477379Sgblack@eecs.umich.edu} 8487379Sgblack@eecs.umich.edu 8497379Sgblack@eecs.umich.edustatic inline double 8507386Sgblack@eecs.umich.eduvfpUFixedToFpD(FPSCR fpscr, uint32_t val, bool half, uint8_t imm) 8517379Sgblack@eecs.umich.edu{ 8527379Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 8537379Sgblack@eecs.umich.edu if (half) 8547379Sgblack@eecs.umich.edu val = (uint16_t)val; 8557382Sgblack@eecs.umich.edu double scale = pow(2.0, imm); 8567382Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 8577382Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 8587382Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 8597386Sgblack@eecs.umich.edu return fixDivDest(fpscr, val / scale, (double)val, scale); 8607379Sgblack@eecs.umich.edu} 8617379Sgblack@eecs.umich.edu 8627379Sgblack@eecs.umich.edustatic inline double 8637386Sgblack@eecs.umich.eduvfpSFixedToFpD(FPSCR fpscr, int32_t val, bool half, uint8_t imm) 8647379Sgblack@eecs.umich.edu{ 8657379Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 8667379Sgblack@eecs.umich.edu if (half) 8677379Sgblack@eecs.umich.edu val = sext<16>(val & mask(16)); 8687382Sgblack@eecs.umich.edu double scale = pow(2.0, imm); 8697382Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 8707382Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 8717382Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 8727386Sgblack@eecs.umich.edu return fixDivDest(fpscr, val / scale, (double)val, scale); 8737379Sgblack@eecs.umich.edu} 8747379Sgblack@eecs.umich.edu 8757376Sgblack@eecs.umich.educlass VfpMacroOp : public PredMacroOp 8767376Sgblack@eecs.umich.edu{ 8777376Sgblack@eecs.umich.edu public: 8787376Sgblack@eecs.umich.edu static bool 8797376Sgblack@eecs.umich.edu inScalarBank(IntRegIndex idx) 8807376Sgblack@eecs.umich.edu { 8817376Sgblack@eecs.umich.edu return (idx % 32) < 8; 8827376Sgblack@eecs.umich.edu } 8837376Sgblack@eecs.umich.edu 8847376Sgblack@eecs.umich.edu protected: 8857376Sgblack@eecs.umich.edu bool wide; 8867376Sgblack@eecs.umich.edu 8877376Sgblack@eecs.umich.edu VfpMacroOp(const char *mnem, ExtMachInst _machInst, 8887376Sgblack@eecs.umich.edu OpClass __opClass, bool _wide) : 8897376Sgblack@eecs.umich.edu PredMacroOp(mnem, _machInst, __opClass), wide(_wide) 8907376Sgblack@eecs.umich.edu {} 8917376Sgblack@eecs.umich.edu 8927376Sgblack@eecs.umich.edu IntRegIndex 8937376Sgblack@eecs.umich.edu addStride(IntRegIndex idx, unsigned stride) 8947376Sgblack@eecs.umich.edu { 8957376Sgblack@eecs.umich.edu if (wide) { 8967376Sgblack@eecs.umich.edu stride *= 2; 8977376Sgblack@eecs.umich.edu } 8987376Sgblack@eecs.umich.edu unsigned offset = idx % 8; 8997376Sgblack@eecs.umich.edu idx = (IntRegIndex)(idx - offset); 9007376Sgblack@eecs.umich.edu offset += stride; 9017376Sgblack@eecs.umich.edu idx = (IntRegIndex)(idx + (offset % 8)); 9027376Sgblack@eecs.umich.edu return idx; 9037376Sgblack@eecs.umich.edu } 9047376Sgblack@eecs.umich.edu 9057376Sgblack@eecs.umich.edu void 9067376Sgblack@eecs.umich.edu nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2) 9077376Sgblack@eecs.umich.edu { 9087376Sgblack@eecs.umich.edu unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 9097376Sgblack@eecs.umich.edu assert(!inScalarBank(dest)); 9107376Sgblack@eecs.umich.edu dest = addStride(dest, stride); 9117376Sgblack@eecs.umich.edu op1 = addStride(op1, stride); 9127376Sgblack@eecs.umich.edu if (!inScalarBank(op2)) { 9137376Sgblack@eecs.umich.edu op2 = addStride(op2, stride); 9147376Sgblack@eecs.umich.edu } 9157376Sgblack@eecs.umich.edu } 9167376Sgblack@eecs.umich.edu 9177376Sgblack@eecs.umich.edu void 9187376Sgblack@eecs.umich.edu nextIdxs(IntRegIndex &dest, IntRegIndex &op1) 9197376Sgblack@eecs.umich.edu { 9207376Sgblack@eecs.umich.edu unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 9217376Sgblack@eecs.umich.edu assert(!inScalarBank(dest)); 9227376Sgblack@eecs.umich.edu dest = addStride(dest, stride); 9237376Sgblack@eecs.umich.edu if (!inScalarBank(op1)) { 9247376Sgblack@eecs.umich.edu op1 = addStride(op1, stride); 9257376Sgblack@eecs.umich.edu } 9267376Sgblack@eecs.umich.edu } 9277376Sgblack@eecs.umich.edu 9287376Sgblack@eecs.umich.edu void 9297376Sgblack@eecs.umich.edu nextIdxs(IntRegIndex &dest) 9307376Sgblack@eecs.umich.edu { 9317376Sgblack@eecs.umich.edu unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 9327376Sgblack@eecs.umich.edu assert(!inScalarBank(dest)); 9337376Sgblack@eecs.umich.edu dest = addStride(dest, stride); 9347376Sgblack@eecs.umich.edu } 9357376Sgblack@eecs.umich.edu}; 9367376Sgblack@eecs.umich.edu 9377396Sgblack@eecs.umich.edustatic inline float 9387396Sgblack@eecs.umich.edufpAddS(float a, float b) 9397396Sgblack@eecs.umich.edu{ 9407396Sgblack@eecs.umich.edu return a + b; 9417396Sgblack@eecs.umich.edu} 9427396Sgblack@eecs.umich.edu 9437396Sgblack@eecs.umich.edustatic inline double 9447396Sgblack@eecs.umich.edufpAddD(double a, double b) 9457396Sgblack@eecs.umich.edu{ 9467396Sgblack@eecs.umich.edu return a + b; 9477396Sgblack@eecs.umich.edu} 9487396Sgblack@eecs.umich.edu 9497396Sgblack@eecs.umich.edustatic inline float 9507396Sgblack@eecs.umich.edufpSubS(float a, float b) 9517396Sgblack@eecs.umich.edu{ 9527396Sgblack@eecs.umich.edu return a - b; 9537396Sgblack@eecs.umich.edu} 9547396Sgblack@eecs.umich.edu 9557396Sgblack@eecs.umich.edustatic inline double 9567396Sgblack@eecs.umich.edufpSubD(double a, double b) 9577396Sgblack@eecs.umich.edu{ 9587396Sgblack@eecs.umich.edu return a - b; 9597396Sgblack@eecs.umich.edu} 9607396Sgblack@eecs.umich.edu 9617396Sgblack@eecs.umich.edustatic inline float 9627396Sgblack@eecs.umich.edufpDivS(float a, float b) 9637396Sgblack@eecs.umich.edu{ 9647396Sgblack@eecs.umich.edu return a / b; 9657396Sgblack@eecs.umich.edu} 9667396Sgblack@eecs.umich.edu 9677396Sgblack@eecs.umich.edustatic inline double 9687396Sgblack@eecs.umich.edufpDivD(double a, double b) 9697396Sgblack@eecs.umich.edu{ 9707396Sgblack@eecs.umich.edu return a / b; 9717396Sgblack@eecs.umich.edu} 9727396Sgblack@eecs.umich.edu 9737396Sgblack@eecs.umich.edustatic inline float 9747396Sgblack@eecs.umich.edufpMulS(float a, float b) 9757396Sgblack@eecs.umich.edu{ 9767396Sgblack@eecs.umich.edu return a * b; 9777396Sgblack@eecs.umich.edu} 9787396Sgblack@eecs.umich.edu 9797396Sgblack@eecs.umich.edustatic inline double 9807396Sgblack@eecs.umich.edufpMulD(double a, double b) 9817396Sgblack@eecs.umich.edu{ 9827396Sgblack@eecs.umich.edu return a * b; 9837396Sgblack@eecs.umich.edu} 9847396Sgblack@eecs.umich.edu 9857396Sgblack@eecs.umich.educlass FpOp : public PredOp 9867375Sgblack@eecs.umich.edu{ 9877375Sgblack@eecs.umich.edu protected: 9887396Sgblack@eecs.umich.edu FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 9897396Sgblack@eecs.umich.edu PredOp(mnem, _machInst, __opClass) 9907396Sgblack@eecs.umich.edu {} 9917396Sgblack@eecs.umich.edu 9927396Sgblack@eecs.umich.edu virtual float 9937396Sgblack@eecs.umich.edu doOp(float op1, float op2) const 9947396Sgblack@eecs.umich.edu { 9957396Sgblack@eecs.umich.edu panic("Unimplemented version of doOp called.\n"); 9967396Sgblack@eecs.umich.edu } 9977396Sgblack@eecs.umich.edu 9987396Sgblack@eecs.umich.edu virtual float 9997396Sgblack@eecs.umich.edu doOp(float op1) const 10007396Sgblack@eecs.umich.edu { 10017396Sgblack@eecs.umich.edu panic("Unimplemented version of doOp called.\n"); 10027396Sgblack@eecs.umich.edu } 10037396Sgblack@eecs.umich.edu 10047396Sgblack@eecs.umich.edu virtual double 10057396Sgblack@eecs.umich.edu doOp(double op1, double op2) const 10067396Sgblack@eecs.umich.edu { 10077396Sgblack@eecs.umich.edu panic("Unimplemented version of doOp called.\n"); 10087396Sgblack@eecs.umich.edu } 10097396Sgblack@eecs.umich.edu 10107396Sgblack@eecs.umich.edu virtual double 10117396Sgblack@eecs.umich.edu doOp(double op1) const 10127396Sgblack@eecs.umich.edu { 10137396Sgblack@eecs.umich.edu panic("Unimplemented version of doOp called.\n"); 10147396Sgblack@eecs.umich.edu } 10157396Sgblack@eecs.umich.edu 10167396Sgblack@eecs.umich.edu double 10177396Sgblack@eecs.umich.edu dbl(uint32_t low, uint32_t high) const 10187396Sgblack@eecs.umich.edu { 10197396Sgblack@eecs.umich.edu double junk = 0.0; 10207396Sgblack@eecs.umich.edu return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 10217396Sgblack@eecs.umich.edu } 10227396Sgblack@eecs.umich.edu 10237396Sgblack@eecs.umich.edu uint32_t 10247396Sgblack@eecs.umich.edu dblLow(double val) const 10257396Sgblack@eecs.umich.edu { 10267396Sgblack@eecs.umich.edu return fpToBits(val); 10277396Sgblack@eecs.umich.edu } 10287396Sgblack@eecs.umich.edu 10297396Sgblack@eecs.umich.edu uint32_t 10307396Sgblack@eecs.umich.edu dblHi(double val) const 10317396Sgblack@eecs.umich.edu { 10327396Sgblack@eecs.umich.edu return fpToBits(val) >> 32; 10337396Sgblack@eecs.umich.edu } 10347396Sgblack@eecs.umich.edu 10357396Sgblack@eecs.umich.edu template <class fpType> 10367396Sgblack@eecs.umich.edu fpType 10377396Sgblack@eecs.umich.edu binaryOp(FPSCR &fpscr, fpType op1, fpType op2, 10387396Sgblack@eecs.umich.edu fpType (*func)(fpType, fpType), 10397396Sgblack@eecs.umich.edu bool flush, uint32_t rMode) const 10407396Sgblack@eecs.umich.edu { 10417396Sgblack@eecs.umich.edu const bool single = (sizeof(fpType) == sizeof(float)); 10427396Sgblack@eecs.umich.edu fpType junk = 0.0; 10437396Sgblack@eecs.umich.edu 10447396Sgblack@eecs.umich.edu if (flush && flushToZero(op1, op2)) 10457396Sgblack@eecs.umich.edu fpscr.idc = 1; 10467396Sgblack@eecs.umich.edu VfpSavedState state = prepFpState(rMode); 10477396Sgblack@eecs.umich.edu __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2), "=m" (state) 10487396Sgblack@eecs.umich.edu : "m" (op1), "m" (op2), "m" (state)); 10497396Sgblack@eecs.umich.edu fpType dest = func(op1, op2); 10507396Sgblack@eecs.umich.edu __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest)); 10517396Sgblack@eecs.umich.edu 10527396Sgblack@eecs.umich.edu int fpClass = std::fpclassify(dest); 10537396Sgblack@eecs.umich.edu // Get NAN behavior right. This varies between x86 and ARM. 10547396Sgblack@eecs.umich.edu if (fpClass == FP_NAN) { 10557396Sgblack@eecs.umich.edu const bool single = (sizeof(fpType) == sizeof(float)); 10567396Sgblack@eecs.umich.edu const uint64_t qnan = 10577396Sgblack@eecs.umich.edu single ? 0x7fc00000 : ULL(0x7ff8000000000000); 10587396Sgblack@eecs.umich.edu const bool nan1 = std::isnan(op1); 10597396Sgblack@eecs.umich.edu const bool nan2 = std::isnan(op2); 10607396Sgblack@eecs.umich.edu const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 10617396Sgblack@eecs.umich.edu const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); 10627396Sgblack@eecs.umich.edu if ((!nan1 && !nan2) || (fpscr.dn == 1)) { 10637396Sgblack@eecs.umich.edu dest = bitsToFp(qnan, junk); 10647396Sgblack@eecs.umich.edu } else if (signal1) { 10657396Sgblack@eecs.umich.edu dest = bitsToFp(fpToBits(op1) | qnan, junk); 10667396Sgblack@eecs.umich.edu } else if (signal2) { 10677396Sgblack@eecs.umich.edu dest = bitsToFp(fpToBits(op2) | qnan, junk); 10687396Sgblack@eecs.umich.edu } else if (nan1) { 10697396Sgblack@eecs.umich.edu dest = op1; 10707396Sgblack@eecs.umich.edu } else if (nan2) { 10717396Sgblack@eecs.umich.edu dest = op2; 10727396Sgblack@eecs.umich.edu } 10737396Sgblack@eecs.umich.edu } else if (flush && flushToZero(dest)) { 10747396Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 10757396Sgblack@eecs.umich.edu } else if (( 10767396Sgblack@eecs.umich.edu (single && (dest == bitsToFp(0x00800000, junk) || 10777396Sgblack@eecs.umich.edu dest == bitsToFp(0x80800000, junk))) || 10787396Sgblack@eecs.umich.edu (!single && 10797396Sgblack@eecs.umich.edu (dest == bitsToFp(ULL(0x0010000000000000), junk) || 10807396Sgblack@eecs.umich.edu dest == bitsToFp(ULL(0x8010000000000000), junk))) 10817396Sgblack@eecs.umich.edu ) && rMode != VfpRoundZero) { 10827396Sgblack@eecs.umich.edu /* 10837396Sgblack@eecs.umich.edu * Correct for the fact that underflow is detected -before- rounding 10847396Sgblack@eecs.umich.edu * in ARM and -after- rounding in x86. 10857396Sgblack@eecs.umich.edu */ 10867396Sgblack@eecs.umich.edu fesetround(FeRoundZero); 10877396Sgblack@eecs.umich.edu __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2) 10887396Sgblack@eecs.umich.edu : "m" (op1), "m" (op2)); 10897396Sgblack@eecs.umich.edu fpType temp = func(op1, op2); 10907396Sgblack@eecs.umich.edu __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); 10917396Sgblack@eecs.umich.edu if (flush && flushToZero(temp)) { 10927396Sgblack@eecs.umich.edu dest = temp; 10937396Sgblack@eecs.umich.edu } 10947396Sgblack@eecs.umich.edu } 10957396Sgblack@eecs.umich.edu finishVfp(fpscr, state); 10967396Sgblack@eecs.umich.edu return dest; 10977396Sgblack@eecs.umich.edu } 10987396Sgblack@eecs.umich.edu 10997396Sgblack@eecs.umich.edu template <class fpType> 11007396Sgblack@eecs.umich.edu fpType 11017396Sgblack@eecs.umich.edu unaryOp(FPSCR &fpscr, fpType op1, 11027396Sgblack@eecs.umich.edu fpType (*func)(fpType), 11037396Sgblack@eecs.umich.edu bool flush, uint32_t rMode) const 11047396Sgblack@eecs.umich.edu { 11057396Sgblack@eecs.umich.edu const bool single = (sizeof(fpType) == sizeof(float)); 11067396Sgblack@eecs.umich.edu fpType junk = 0.0; 11077396Sgblack@eecs.umich.edu 11087396Sgblack@eecs.umich.edu if (flush && flushToZero(op1)) 11097396Sgblack@eecs.umich.edu fpscr.idc = 1; 11107396Sgblack@eecs.umich.edu VfpSavedState state = prepFpState(rMode); 11117396Sgblack@eecs.umich.edu __asm__ __volatile__ ("" : "=m" (op1), "=m" (state) 11127396Sgblack@eecs.umich.edu : "m" (op1), "m" (state)); 11137396Sgblack@eecs.umich.edu fpType dest = func(op1); 11147396Sgblack@eecs.umich.edu __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest)); 11157396Sgblack@eecs.umich.edu 11167396Sgblack@eecs.umich.edu int fpClass = std::fpclassify(dest); 11177396Sgblack@eecs.umich.edu // Get NAN behavior right. This varies between x86 and ARM. 11187396Sgblack@eecs.umich.edu if (fpClass == FP_NAN) { 11197396Sgblack@eecs.umich.edu const bool single = (sizeof(fpType) == sizeof(float)); 11207396Sgblack@eecs.umich.edu const uint64_t qnan = 11217396Sgblack@eecs.umich.edu single ? 0x7fc00000 : ULL(0x7ff8000000000000); 11227396Sgblack@eecs.umich.edu const bool nan = std::isnan(op1); 11237396Sgblack@eecs.umich.edu if (!nan || fpscr.dn == 1) { 11247396Sgblack@eecs.umich.edu dest = bitsToFp(qnan, junk); 11257396Sgblack@eecs.umich.edu } else if (nan) { 11267396Sgblack@eecs.umich.edu dest = bitsToFp(fpToBits(op1) | qnan, junk); 11277396Sgblack@eecs.umich.edu } 11287396Sgblack@eecs.umich.edu } else if (flush && flushToZero(dest)) { 11297396Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 11307396Sgblack@eecs.umich.edu } else if (( 11317396Sgblack@eecs.umich.edu (single && (dest == bitsToFp(0x00800000, junk) || 11327396Sgblack@eecs.umich.edu dest == bitsToFp(0x80800000, junk))) || 11337396Sgblack@eecs.umich.edu (!single && 11347396Sgblack@eecs.umich.edu (dest == bitsToFp(ULL(0x0010000000000000), junk) || 11357396Sgblack@eecs.umich.edu dest == bitsToFp(ULL(0x8010000000000000), junk))) 11367396Sgblack@eecs.umich.edu ) && rMode != VfpRoundZero) { 11377396Sgblack@eecs.umich.edu /* 11387396Sgblack@eecs.umich.edu * Correct for the fact that underflow is detected -before- rounding 11397396Sgblack@eecs.umich.edu * in ARM and -after- rounding in x86. 11407396Sgblack@eecs.umich.edu */ 11417396Sgblack@eecs.umich.edu fesetround(FeRoundZero); 11427396Sgblack@eecs.umich.edu __asm__ __volatile__ ("" : "=m" (op1) : "m" (op1)); 11437396Sgblack@eecs.umich.edu fpType temp = func(op1); 11447396Sgblack@eecs.umich.edu __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); 11457396Sgblack@eecs.umich.edu if (flush && flushToZero(temp)) { 11467396Sgblack@eecs.umich.edu dest = temp; 11477396Sgblack@eecs.umich.edu } 11487396Sgblack@eecs.umich.edu } 11497396Sgblack@eecs.umich.edu finishVfp(fpscr, state); 11507396Sgblack@eecs.umich.edu return dest; 11517396Sgblack@eecs.umich.edu } 11527396Sgblack@eecs.umich.edu}; 11537396Sgblack@eecs.umich.edu 11547396Sgblack@eecs.umich.educlass FpRegRegOp : public FpOp 11557396Sgblack@eecs.umich.edu{ 11567396Sgblack@eecs.umich.edu protected: 11577396Sgblack@eecs.umich.edu IntRegIndex dest; 11587396Sgblack@eecs.umich.edu IntRegIndex op1; 11597396Sgblack@eecs.umich.edu 11607396Sgblack@eecs.umich.edu FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 11617396Sgblack@eecs.umich.edu IntRegIndex _dest, IntRegIndex _op1, 11627396Sgblack@eecs.umich.edu VfpMicroMode mode = VfpNotAMicroop) : 11637396Sgblack@eecs.umich.edu FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1) 11647375Sgblack@eecs.umich.edu { 11657375Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 11667375Sgblack@eecs.umich.edu } 11677396Sgblack@eecs.umich.edu 11687396Sgblack@eecs.umich.edu std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 11697375Sgblack@eecs.umich.edu}; 11707375Sgblack@eecs.umich.edu 11717396Sgblack@eecs.umich.educlass FpRegImmOp : public FpOp 11727375Sgblack@eecs.umich.edu{ 11737375Sgblack@eecs.umich.edu protected: 11747396Sgblack@eecs.umich.edu IntRegIndex dest; 11757396Sgblack@eecs.umich.edu uint64_t imm; 11767396Sgblack@eecs.umich.edu 11777396Sgblack@eecs.umich.edu FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 11787396Sgblack@eecs.umich.edu IntRegIndex _dest, uint64_t _imm, 11797396Sgblack@eecs.umich.edu VfpMicroMode mode = VfpNotAMicroop) : 11807396Sgblack@eecs.umich.edu FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm) 11817375Sgblack@eecs.umich.edu { 11827375Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 11837375Sgblack@eecs.umich.edu } 11847396Sgblack@eecs.umich.edu 11857396Sgblack@eecs.umich.edu std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 11867375Sgblack@eecs.umich.edu}; 11877375Sgblack@eecs.umich.edu 11887396Sgblack@eecs.umich.educlass FpRegRegImmOp : public FpOp 11897375Sgblack@eecs.umich.edu{ 11907375Sgblack@eecs.umich.edu protected: 11917396Sgblack@eecs.umich.edu IntRegIndex dest; 11927396Sgblack@eecs.umich.edu IntRegIndex op1; 11937396Sgblack@eecs.umich.edu uint64_t imm; 11947396Sgblack@eecs.umich.edu 11957396Sgblack@eecs.umich.edu FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 11967396Sgblack@eecs.umich.edu IntRegIndex _dest, IntRegIndex _op1, 11977396Sgblack@eecs.umich.edu uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : 11987396Sgblack@eecs.umich.edu FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm) 11997375Sgblack@eecs.umich.edu { 12007375Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 12017375Sgblack@eecs.umich.edu } 12027396Sgblack@eecs.umich.edu 12037396Sgblack@eecs.umich.edu std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 12047375Sgblack@eecs.umich.edu}; 12057375Sgblack@eecs.umich.edu 12067396Sgblack@eecs.umich.educlass FpRegRegRegOp : public FpOp 12077375Sgblack@eecs.umich.edu{ 12087375Sgblack@eecs.umich.edu protected: 12097396Sgblack@eecs.umich.edu IntRegIndex dest; 12107396Sgblack@eecs.umich.edu IntRegIndex op1; 12117396Sgblack@eecs.umich.edu IntRegIndex op2; 12127396Sgblack@eecs.umich.edu 12137396Sgblack@eecs.umich.edu FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 12147396Sgblack@eecs.umich.edu IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, 12157396Sgblack@eecs.umich.edu VfpMicroMode mode = VfpNotAMicroop) : 12167396Sgblack@eecs.umich.edu FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2) 12177375Sgblack@eecs.umich.edu { 12187375Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 12197375Sgblack@eecs.umich.edu } 12207396Sgblack@eecs.umich.edu 12217396Sgblack@eecs.umich.edu std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 12227375Sgblack@eecs.umich.edu}; 12237375Sgblack@eecs.umich.edu 12247384Sgblack@eecs.umich.edu} 12257384Sgblack@eecs.umich.edu 12267375Sgblack@eecs.umich.edu#endif //__ARCH_ARM_INSTS_VFP_HH__ 1227