vfp.hh revision 7397
13096SN/A/* 23096SN/A * Copyright (c) 2010 ARM Limited 33096SN/A * All rights reserved 49988Snilay@cs.wisc.edu * 58835SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall 69988Snilay@cs.wisc.edu * not be construed as granting a license to any other intellectual 77935SN/A * property including but not limited to intellectual property relating 87935SN/A * to a hardware implementation of the functionality of the software 97935SN/A * licensed hereunder. You may use the software subject to the license 103096SN/A * terms below provided that you ensure that this notice is replicated 113096SN/A * unmodified and in its entirety in all distributions of the software, 123096SN/A * modified or unmodified, in source code or in binary form. 1310315Snilay@cs.wisc.edu * 148835SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 159885Sstever@gmail.com * modification, are permitted provided that the following conditions are 169885Sstever@gmail.com * met: redistributions of source code must retain the above copyright 1711570SCurtis.Dunham@arm.com * notice, this list of conditions and the following disclaimer; 189988Snilay@cs.wisc.edu * redistributions in binary form must reproduce the above copyright 1911312Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer in the 208835SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 218835SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 2210315Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from 238835SAli.Saidi@ARM.com * this software without specific prior written permission. 2410242Ssteve.reinhardt@amd.com * 259481Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 269481Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 278464SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2810736Snilay@cs.wisc.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2911219Snilay@cs.wisc.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 308721SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3111570SCurtis.Dunham@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3211570SCurtis.Dunham@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3311570SCurtis.Dunham@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3411570SCurtis.Dunham@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 358835SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 368835SAli.Saidi@ARM.com * 3711440SCurtis.Dunham@arm.com * Authors: Gabe Black 3811440SCurtis.Dunham@arm.com */ 397935SN/A 407935SN/A#ifndef __ARCH_ARM_INSTS_VFP_HH__ 417935SN/A#define __ARCH_ARM_INSTS_VFP_HH__ 427935SN/A 437935SN/A#include "arch/arm/insts/misc.hh" 447935SN/A#include "arch/arm/miscregs.hh" 457935SN/A#include <fenv.h> 468983Snate@binkert.org#include <cmath> 473096SN/A 489885Sstever@gmail.comnamespace ArmISA 499885Sstever@gmail.com{ 509885Sstever@gmail.com 5110315Snilay@cs.wisc.eduenum VfpMicroMode { 529988Snilay@cs.wisc.edu VfpNotAMicroop, 5310315Snilay@cs.wisc.edu VfpMicroop, 549885Sstever@gmail.com VfpFirstMicroop, 559885Sstever@gmail.com VfpLastMicroop 563096SN/A}; 573096SN/A 589481Snilay@cs.wisc.edutemplate<class T> 593096SN/Astatic inline void 603096SN/AsetVfpMicroFlags(VfpMicroMode mode, T &flags) 618241SN/A{ 628241SN/A switch (mode) { 633096SN/A case VfpMicroop: 643096SN/A flags[StaticInst::IsMicroop] = true; 653096SN/A break; 663096SN/A case VfpFirstMicroop: 679481Snilay@cs.wisc.edu flags[StaticInst::IsMicroop] = 684657SN/A flags[StaticInst::IsFirstMicroop] = true; 695876SN/A break; 709885Sstever@gmail.com case VfpLastMicroop: 713096SN/A flags[StaticInst::IsMicroop] = 723096SN/A flags[StaticInst::IsLastMicroop] = true; 733096SN/A break; 743096SN/A case VfpNotAMicroop: 753096SN/A break; 764289SN/A } 773096SN/A if (mode == VfpMicroop || mode == VfpFirstMicroop) { 783096SN/A flags[StaticInst::IsDelayedCommit] = true; 793096SN/A } 8011570SCurtis.Dunham@arm.com} 813096SN/A 825876SN/Aenum FeExceptionBit 838835SAli.Saidi@ARM.com{ 845876SN/A FeDivByZero = FE_DIVBYZERO, 855000SN/A FeInexact = FE_INEXACT, 869988Snilay@cs.wisc.edu FeInvalid = FE_INVALID, 879988Snilay@cs.wisc.edu FeOverflow = FE_OVERFLOW, 8810451Snilay@cs.wisc.edu FeUnderflow = FE_UNDERFLOW, 893096SN/A FeAllExceptions = FE_ALL_EXCEPT 903096SN/A}; 913096SN/A 923096SN/Aenum FeRoundingMode 933096SN/A{ 943096SN/A FeRoundDown = FE_DOWNWARD, 953096SN/A FeRoundNearest = FE_TONEAREST, 963096SN/A FeRoundZero = FE_TOWARDZERO, 973096SN/A FeRoundUpward = FE_UPWARD 983096SN/A}; 993096SN/A 1008835SAli.Saidi@ARM.comenum VfpRoundingMode 1019348SAli.Saidi@ARM.com{ 1023096SN/A VfpRoundNearest = 0, 1033096SN/A VfpRoundUpward = 1, 1045000SN/A VfpRoundDown = 2, 1053096SN/A VfpRoundZero = 3 1063096SN/A}; 1073096SN/A 1083096SN/Atemplate <class fpType> 1098835SAli.Saidi@ARM.comstatic inline bool 1103096SN/AflushToZero(fpType &op) 1119924Ssteve.reinhardt@amd.com{ 1123096SN/A fpType junk = 0.0; 1133096SN/A if (std::fpclassify(op) == FP_SUBNORMAL) { 1143096SN/A uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 1153096SN/A op = bitsToFp(fpToBits(op) & bitMask, junk); 1163096SN/A return true; 11711570SCurtis.Dunham@arm.com } 11811570SCurtis.Dunham@arm.com return false; 11911570SCurtis.Dunham@arm.com} 12011570SCurtis.Dunham@arm.com 1218835SAli.Saidi@ARM.comtemplate <class fpType> 1223147SN/Astatic inline bool 1233096SN/AflushToZero(fpType &op1, fpType &op2) 1243096SN/A{ 1253096SN/A bool flush1 = flushToZero(op1); 1263096SN/A bool flush2 = flushToZero(op2); 1273096SN/A return flush1 || flush2; 1289885Sstever@gmail.com} 1294657SN/A 1304657SN/Atemplate <class fpType> 1314657SN/Astatic inline void 1324657SN/AvfpFlushToZero(FPSCR &fpscr, fpType &op) 1334657SN/A{ 1344657SN/A if (fpscr.fz == 1 && flushToZero(op)) { 1354657SN/A fpscr.idc = 1; 1364657SN/A } 1374657SN/A} 13810242Ssteve.reinhardt@amd.com 1393096SN/Atemplate <class fpType> 1408546SN/Astatic inline void 1419481Snilay@cs.wisc.eduvfpFlushToZero(FPSCR &fpscr, fpType &op1, fpType &op2) 1423096SN/A{ 1434938SN/A vfpFlushToZero(fpscr, op1); 1443096SN/A vfpFlushToZero(fpscr, op2); 1453096SN/A} 1463096SN/A 1473104SN/Astatic inline uint32_t 1483104SN/AfpToBits(float fp) 1493096SN/A{ 1509481Snilay@cs.wisc.edu union 15110798Ssteve.reinhardt@amd.com { 1529481Snilay@cs.wisc.edu float fp; 1539481Snilay@cs.wisc.edu uint32_t bits; 1549481Snilay@cs.wisc.edu } val; 1559481Snilay@cs.wisc.edu val.fp = fp; 1569481Snilay@cs.wisc.edu return val.bits; 1579988Snilay@cs.wisc.edu} 1589481Snilay@cs.wisc.edu 1599481Snilay@cs.wisc.edustatic inline uint64_t 16011440SCurtis.Dunham@arm.comfpToBits(double fp) 16111440SCurtis.Dunham@arm.com{ 16211440SCurtis.Dunham@arm.com union 16311440SCurtis.Dunham@arm.com { 16411440SCurtis.Dunham@arm.com double fp; 16511440SCurtis.Dunham@arm.com uint64_t bits; 1669481Snilay@cs.wisc.edu } val; 1679481Snilay@cs.wisc.edu val.fp = fp; 1689481Snilay@cs.wisc.edu return val.bits; 1699481Snilay@cs.wisc.edu} 1709481Snilay@cs.wisc.edu 17111440SCurtis.Dunham@arm.comstatic inline float 1729481Snilay@cs.wisc.edubitsToFp(uint64_t bits, float junk) 1733096SN/A{ 17411066Snilay@cs.wisc.edu union 1759885Sstever@gmail.com { 17611680SCurtis.Dunham@arm.com float fp; 1773096SN/A uint32_t bits; 1789885Sstever@gmail.com } val; 17911219Snilay@cs.wisc.edu val.bits = bits; 18011731Sjason@lowepower.com return val.fp; 18111570SCurtis.Dunham@arm.com} 18210636Snilay@cs.wisc.edu 1839988Snilay@cs.wisc.edustatic inline double 18411066Snilay@cs.wisc.edubitsToFp(uint64_t bits, double junk) 1853096SN/A{ 1869348SAli.Saidi@ARM.com union 18711570SCurtis.Dunham@arm.com { 18811570SCurtis.Dunham@arm.com double fp; 18911570SCurtis.Dunham@arm.com uint64_t bits; 19011570SCurtis.Dunham@arm.com } val; 1915876SN/A val.bits = bits; 1928835SAli.Saidi@ARM.com return val.fp; 1939348SAli.Saidi@ARM.com} 19410036SAli.Saidi@ARM.com 1953096SN/Atypedef int VfpSavedState; 1968835SAli.Saidi@ARM.com 19711731Sjason@lowepower.comstatic inline VfpSavedState 1989885Sstever@gmail.comprepFpState(uint32_t rMode) 1994316SN/A{ 2003096SN/A int roundingMode = fegetround(); 20111219Snilay@cs.wisc.edu feclearexcept(FeAllExceptions); 2023104SN/A switch (rMode) { 2038983Snate@binkert.org case VfpRoundNearest: 2043096SN/A fesetround(FeRoundNearest); 2059885Sstever@gmail.com break; 2069885Sstever@gmail.com case VfpRoundUpward: 2079885Sstever@gmail.com fesetround(FeRoundUpward); 2089885Sstever@gmail.com break; 2099885Sstever@gmail.com case VfpRoundDown: 21011731Sjason@lowepower.com fesetround(FeRoundDown); 21111570SCurtis.Dunham@arm.com break; 2129988Snilay@cs.wisc.edu case VfpRoundZero: 21311570SCurtis.Dunham@arm.com fesetround(FeRoundZero); 21411570SCurtis.Dunham@arm.com break; 21511570SCurtis.Dunham@arm.com } 21611570SCurtis.Dunham@arm.com return roundingMode; 21710036SAli.Saidi@ARM.com} 2189885Sstever@gmail.com 21911731Sjason@lowepower.comstatic inline void 2209885Sstever@gmail.comfinishVfp(FPSCR &fpscr, VfpSavedState state) 2215000SN/A{ 2226024SN/A int exceptions = fetestexcept(FeAllExceptions); 2239988Snilay@cs.wisc.edu bool underflow = false; 2245000SN/A if (exceptions & FeInvalid) { 2255000SN/A fpscr.ioc = 1; 2263096SN/A } 2273096SN/A if (exceptions & FeDivByZero) { 2287761SN/A fpscr.dzc = 1; 2297761SN/A } 2309988Snilay@cs.wisc.edu if (exceptions & FeOverflow) { 2313096SN/A fpscr.ofc = 1; 2323096SN/A } 2333096SN/A if (exceptions & FeUnderflow) { 2344938SN/A underflow = true; 2353096SN/A fpscr.ufc = 1; 2369988Snilay@cs.wisc.edu } 2374938SN/A if ((exceptions & FeInexact) && !(underflow && fpscr.fz)) { 2383096SN/A fpscr.ixc = 1; 2394938SN/A } 2403096SN/A fesetround(state); 2419988Snilay@cs.wisc.edu} 2423096SN/A 2433096SN/Atemplate <class fpType> 24411066Snilay@cs.wisc.edustatic inline fpType 2453096SN/AfixDest(FPSCR fpscr, fpType val, fpType op1) 2463096SN/A{ 2473096SN/A int fpClass = std::fpclassify(val); 2483096SN/A fpType junk = 0.0; 2493096SN/A if (fpClass == FP_NAN) { 2509988Snilay@cs.wisc.edu const bool single = (sizeof(val) == sizeof(float)); 2513096SN/A const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 2523096SN/A const bool nan = std::isnan(op1); 2533096SN/A if (!nan || (fpscr.dn == 1)) { 2543096SN/A val = bitsToFp(qnan, junk); 2559988Snilay@cs.wisc.edu } else if (nan) { 2563096SN/A val = bitsToFp(fpToBits(op1) | qnan, junk); 2573096SN/A } 25811066Snilay@cs.wisc.edu } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) { 2593096SN/A // Turn val into a zero with the correct sign; 2603096SN/A uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 2613096SN/A val = bitsToFp(fpToBits(val) & bitMask, junk); 2629988Snilay@cs.wisc.edu feclearexcept(FeInexact); 2633096SN/A feraiseexcept(FeUnderflow); 2643096SN/A } 26511066Snilay@cs.wisc.edu return val; 2663096SN/A} 2673096SN/A 2683096SN/Atemplate <class fpType> 2693096SN/Astatic inline fpType 2703096SN/AfixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2) 2719988Snilay@cs.wisc.edu{ 2723096SN/A int fpClass = std::fpclassify(val); 2733096SN/A fpType junk = 0.0; 2743096SN/A if (fpClass == FP_NAN) { 2753096SN/A const bool single = (sizeof(val) == sizeof(float)); 2769988Snilay@cs.wisc.edu const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 2773096SN/A const bool nan1 = std::isnan(op1); 2783096SN/A const bool nan2 = std::isnan(op2); 27911066Snilay@cs.wisc.edu const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 2803096SN/A const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); 2813096SN/A if ((!nan1 && !nan2) || (fpscr.dn == 1)) { 2823096SN/A val = bitsToFp(qnan, junk); 2839988Snilay@cs.wisc.edu } else if (signal1) { 2843096SN/A val = bitsToFp(fpToBits(op1) | qnan, junk); 2853096SN/A } else if (signal2) { 28611066Snilay@cs.wisc.edu val = bitsToFp(fpToBits(op2) | qnan, junk); 2873096SN/A } else if (nan1) { 2883096SN/A val = op1; 2893096SN/A } else if (nan2) { 2909988Snilay@cs.wisc.edu val = op2; 2913096SN/A } 2923096SN/A } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) { 29311066Snilay@cs.wisc.edu // Turn val into a zero with the correct sign; 2943096SN/A uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 2953096SN/A val = bitsToFp(fpToBits(val) & bitMask, junk); 2963096SN/A feclearexcept(FeInexact); 29711731Sjason@lowepower.com feraiseexcept(FeUnderflow); 2983096SN/A } 2999988Snilay@cs.wisc.edu return val; 30011731Sjason@lowepower.com} 3013096SN/A 3023096SN/Atemplate <class fpType> 3033096SN/Astatic inline fpType 3049988Snilay@cs.wisc.edufixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2) 3053096SN/A{ 3063096SN/A fpType mid = fixDest(fpscr, val, op1, op2); 30711066Snilay@cs.wisc.edu const bool single = (sizeof(fpType) == sizeof(float)); 3083096SN/A const fpType junk = 0.0; 3093096SN/A if ((single && (val == bitsToFp(0x00800000, junk) || 3103096SN/A val == bitsToFp(0x80800000, junk))) || 3119988Snilay@cs.wisc.edu (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) || 31211731Sjason@lowepower.com val == bitsToFp(ULL(0x8010000000000000), junk))) 31311731Sjason@lowepower.com ) { 31411731Sjason@lowepower.com __asm__ __volatile__("" : "=m" (op1) : "m" (op1)); 31511731Sjason@lowepower.com fesetround(FeRoundZero); 31611731Sjason@lowepower.com fpType temp = 0.0; 31711731Sjason@lowepower.com __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 31811731Sjason@lowepower.com temp = op1 / op2; 31911731Sjason@lowepower.com if (flushToZero(temp)) { 32011731Sjason@lowepower.com feraiseexcept(FeUnderflow); 32111731Sjason@lowepower.com if (fpscr.fz) { 32211731Sjason@lowepower.com feclearexcept(FeInexact); 32311731Sjason@lowepower.com mid = temp; 32411731Sjason@lowepower.com } 32511731Sjason@lowepower.com } 3263096SN/A __asm__ __volatile__("" :: "m" (temp)); 3273096SN/A } 32811066Snilay@cs.wisc.edu return mid; 3293096SN/A} 33011731Sjason@lowepower.com 3313096SN/Astatic inline float 3329988Snilay@cs.wisc.edufixFpDFpSDest(FPSCR fpscr, double val) 3333096SN/A{ 3343096SN/A const float junk = 0.0; 33511066Snilay@cs.wisc.edu float op1 = 0.0; 3363096SN/A if (std::isnan(val)) { 3373096SN/A uint64_t valBits = fpToBits(val); 3383096SN/A uint32_t op1Bits = bits(valBits, 50, 29) | 33911731Sjason@lowepower.com (mask(9) << 22) | 3403096SN/A (bits(valBits, 63) << 31); 3419988Snilay@cs.wisc.edu op1 = bitsToFp(op1Bits, junk); 34211731Sjason@lowepower.com } 3433096SN/A float mid = fixDest(fpscr, (float)val, op1); 34411731Sjason@lowepower.com if (fpscr.fz && fetestexcept(FeUnderflow | FeInexact) == 3453096SN/A (FeUnderflow | FeInexact)) { 3469988Snilay@cs.wisc.edu feclearexcept(FeInexact); 3473096SN/A } 3483096SN/A if (mid == bitsToFp(0x00800000, junk) || 34911066Snilay@cs.wisc.edu mid == bitsToFp(0x80800000, junk)) { 3503096SN/A __asm__ __volatile__("" : "=m" (val) : "m" (val)); 35111731Sjason@lowepower.com fesetround(FeRoundZero); 35211731Sjason@lowepower.com float temp = 0.0; 35311731Sjason@lowepower.com __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 35411731Sjason@lowepower.com temp = val; 35511731Sjason@lowepower.com if (flushToZero(temp)) { 35611731Sjason@lowepower.com feraiseexcept(FeUnderflow); 35711731Sjason@lowepower.com if (fpscr.fz) { 3583096SN/A feclearexcept(FeInexact); 3593096SN/A mid = temp; 3607761SN/A } 3617761SN/A } 3629988Snilay@cs.wisc.edu __asm__ __volatile__("" :: "m" (temp)); 3637761SN/A } 3643096SN/A return mid; 3657761SN/A} 3663096SN/A 3679988Snilay@cs.wisc.edustatic inline double 3687761SN/AfixFpSFpDDest(FPSCR fpscr, float val) 3697761SN/A{ 37011066Snilay@cs.wisc.edu const double junk = 0.0; 3717761SN/A double op1 = 0.0; 3727761SN/A if (std::isnan(val)) { 3737761SN/A uint32_t valBits = fpToBits(val); 3749988Snilay@cs.wisc.edu uint64_t op1Bits = ((uint64_t)bits(valBits, 21, 0) << 29) | 3757761SN/A (mask(12) << 51) | 3767761SN/A ((uint64_t)bits(valBits, 31) << 63); 37711066Snilay@cs.wisc.edu op1 = bitsToFp(op1Bits, junk); 3787761SN/A } 3797761SN/A double mid = fixDest(fpscr, (double)val, op1); 3807761SN/A if (mid == bitsToFp(ULL(0x0010000000000000), junk) || 3819988Snilay@cs.wisc.edu mid == bitsToFp(ULL(0x8010000000000000), junk)) { 3827761SN/A __asm__ __volatile__("" : "=m" (val) : "m" (val)); 3837761SN/A fesetround(FeRoundZero); 38411066Snilay@cs.wisc.edu double temp = 0.0; 3857761SN/A __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 3867761SN/A temp = val; 3877761SN/A if (flushToZero(temp)) { 3889988Snilay@cs.wisc.edu feraiseexcept(FeUnderflow); 3897761SN/A if (fpscr.fz) { 3907761SN/A feclearexcept(FeInexact); 39111066Snilay@cs.wisc.edu mid = temp; 3927761SN/A } 3937761SN/A } 3947761SN/A __asm__ __volatile__("" :: "m" (temp)); 3959988Snilay@cs.wisc.edu } 3967761SN/A return mid; 3977761SN/A} 39811066Snilay@cs.wisc.edu 3997761SN/Astatic inline double 4007761SN/AmakeDouble(uint32_t low, uint32_t high) 4017761SN/A{ 4029988Snilay@cs.wisc.edu double junk = 0.0; 4037761SN/A return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 4047761SN/A} 40511066Snilay@cs.wisc.edu 4067761SN/Astatic inline uint32_t 4077761SN/AlowFromDouble(double val) 4087761SN/A{ 4099988Snilay@cs.wisc.edu return fpToBits(val); 4107761SN/A} 4117761SN/A 41211066Snilay@cs.wisc.edustatic inline uint32_t 4137761SN/AhighFromDouble(double val) 4147761SN/A{ 4157761SN/A return fpToBits(val) >> 32; 4169988Snilay@cs.wisc.edu} 4177761SN/A 4187761SN/Astatic inline uint64_t 41911066Snilay@cs.wisc.eduvfpFpSToFixed(float val, bool isSigned, bool half, 4207761SN/A uint8_t imm, bool rzero = true) 4217761SN/A{ 4227761SN/A int rmode = rzero ? FeRoundZero : fegetround(); 4239988Snilay@cs.wisc.edu __asm__ __volatile__("" : "=m" (rmode) : "m" (rmode)); 4247761SN/A fesetround(FeRoundNearest); 4257761SN/A val = val * powf(2.0, imm); 42611066Snilay@cs.wisc.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 4277761SN/A fesetround(rmode); 4287761SN/A feclearexcept(FeAllExceptions); 4297761SN/A __asm__ __volatile__("" : "=m" (val) : "m" (val)); 4309988Snilay@cs.wisc.edu float origVal = val; 4317761SN/A val = rintf(val); 4327761SN/A int fpType = std::fpclassify(val); 43311066Snilay@cs.wisc.edu if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { 4347761SN/A if (fpType == FP_NAN) { 4357761SN/A feraiseexcept(FeInvalid); 4367761SN/A } 4379988Snilay@cs.wisc.edu val = 0.0; 4387761SN/A } else if (origVal != val) { 4397761SN/A switch (rmode) { 44011066Snilay@cs.wisc.edu case FeRoundNearest: 4417761SN/A if (origVal - val > 0.5) 4427761SN/A val += 1.0; 4437761SN/A else if (val - origVal > 0.5) 4449988Snilay@cs.wisc.edu val -= 1.0; 4457761SN/A break; 4467761SN/A case FeRoundDown: 44711066Snilay@cs.wisc.edu if (origVal < val) 4487761SN/A val -= 1.0; 4497761SN/A break; 4507761SN/A case FeRoundUpward: 4519988Snilay@cs.wisc.edu if (origVal > val) 4527761SN/A val += 1.0; 4537761SN/A break; 45411066Snilay@cs.wisc.edu } 4557761SN/A feraiseexcept(FeInexact); 4567761SN/A } 4577761SN/A 4589988Snilay@cs.wisc.edu if (isSigned) { 4597761SN/A if (half) { 4607761SN/A if ((double)val < (int16_t)(1 << 15)) { 46111066Snilay@cs.wisc.edu feraiseexcept(FeInvalid); 4627761SN/A feclearexcept(FeInexact); 4637761SN/A return (int16_t)(1 << 15); 4647761SN/A } 4659988Snilay@cs.wisc.edu if ((double)val > (int16_t)mask(15)) { 4667761SN/A feraiseexcept(FeInvalid); 4677761SN/A feclearexcept(FeInexact); 46811066Snilay@cs.wisc.edu return (int16_t)mask(15); 4697761SN/A } 4707761SN/A return (int16_t)val; 4717761SN/A } else { 4729988Snilay@cs.wisc.edu if ((double)val < (int32_t)(1 << 31)) { 4737761SN/A feraiseexcept(FeInvalid); 4747761SN/A feclearexcept(FeInexact); 47511066Snilay@cs.wisc.edu return (int32_t)(1 << 31); 4767761SN/A } 4777761SN/A if ((double)val > (int32_t)mask(31)) { 4787761SN/A feraiseexcept(FeInvalid); 4799988Snilay@cs.wisc.edu feclearexcept(FeInexact); 4807761SN/A return (int32_t)mask(31); 4817761SN/A } 48211066Snilay@cs.wisc.edu return (int32_t)val; 4837761SN/A } 4847761SN/A } else { 4857761SN/A if (half) { 4869988Snilay@cs.wisc.edu if ((double)val < 0) { 4877761SN/A feraiseexcept(FeInvalid); 4887761SN/A feclearexcept(FeInexact); 48911066Snilay@cs.wisc.edu return 0; 4907761SN/A } 4917761SN/A if ((double)val > (mask(16))) { 4927761SN/A feraiseexcept(FeInvalid); 4939988Snilay@cs.wisc.edu feclearexcept(FeInexact); 4947761SN/A return mask(16); 4957761SN/A } 49611066Snilay@cs.wisc.edu return (uint16_t)val; 4977761SN/A } else { 4987761SN/A if ((double)val < 0) { 4997761SN/A feraiseexcept(FeInvalid); 5009988Snilay@cs.wisc.edu feclearexcept(FeInexact); 5017761SN/A return 0; 5023096SN/A } 50311066Snilay@cs.wisc.edu if ((double)val > (mask(32))) { 5043096SN/A feraiseexcept(FeInvalid); 5053096SN/A feclearexcept(FeInexact); 5063096SN/A return mask(32); 50711731Sjason@lowepower.com } 5087761SN/A return (uint32_t)val; 5099988Snilay@cs.wisc.edu } 51011731Sjason@lowepower.com } 5113096SN/A} 51211731Sjason@lowepower.com 5133096SN/Astatic inline float 5149988Snilay@cs.wisc.eduvfpUFixedToFpS(FPSCR fpscr, uint32_t val, bool half, uint8_t imm) 5153096SN/A{ 5163096SN/A fesetround(FeRoundNearest); 51711066Snilay@cs.wisc.edu if (half) 5183096SN/A val = (uint16_t)val; 51911731Sjason@lowepower.com float scale = powf(2.0, imm); 52011731Sjason@lowepower.com __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 52111731Sjason@lowepower.com feclearexcept(FeAllExceptions); 52211731Sjason@lowepower.com __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 52311731Sjason@lowepower.com return fixDivDest(fpscr, val / scale, (float)val, scale); 52411731Sjason@lowepower.com} 52511731Sjason@lowepower.com 5263096SN/Astatic inline float 5273096SN/AvfpSFixedToFpS(FPSCR fpscr, int32_t val, bool half, uint8_t imm) 52811731Sjason@lowepower.com{ 5297761SN/A fesetround(FeRoundNearest); 5309988Snilay@cs.wisc.edu if (half) 53111731Sjason@lowepower.com val = sext<16>(val & mask(16)); 5327761SN/A float scale = powf(2.0, imm); 5337761SN/A __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 5347761SN/A feclearexcept(FeAllExceptions); 5359988Snilay@cs.wisc.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 5367761SN/A return fixDivDest(fpscr, val / scale, (float)val, scale); 5377761SN/A} 53811066Snilay@cs.wisc.edu 5397761SN/Astatic inline uint64_t 5407761SN/AvfpFpDToFixed(double val, bool isSigned, bool half, 5417761SN/A uint8_t imm, bool rzero = true) 5429988Snilay@cs.wisc.edu{ 5437761SN/A int rmode = rzero ? FeRoundZero : fegetround(); 5447761SN/A fesetround(FeRoundNearest); 54511066Snilay@cs.wisc.edu val = val * pow(2.0, imm); 5467761SN/A __asm__ __volatile__("" : "=m" (val) : "m" (val)); 54711731Sjason@lowepower.com fesetround(rmode); 54811731Sjason@lowepower.com feclearexcept(FeAllExceptions); 54911731Sjason@lowepower.com __asm__ __volatile__("" : "=m" (val) : "m" (val)); 55011731Sjason@lowepower.com double origVal = val; 55111731Sjason@lowepower.com val = rint(val); 55211731Sjason@lowepower.com int fpType = std::fpclassify(val); 55311731Sjason@lowepower.com if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { 55411731Sjason@lowepower.com if (fpType == FP_NAN) { 55511731Sjason@lowepower.com feraiseexcept(FeInvalid); 55611731Sjason@lowepower.com } 55711731Sjason@lowepower.com val = 0.0; 55811731Sjason@lowepower.com } else if (origVal != val) { 55911731Sjason@lowepower.com switch (rmode) { 56011731Sjason@lowepower.com case FeRoundNearest: 5617761SN/A if (origVal - val > 0.5) 5627761SN/A val += 1.0; 5634938SN/A else if (val - origVal > 0.5) 5643096SN/A val -= 1.0; 5659988Snilay@cs.wisc.edu break; 5667761SN/A case FeRoundDown: 5673096SN/A if (origVal < val) 5687761SN/A val -= 1.0; 5693096SN/A break; 5709988Snilay@cs.wisc.edu case FeRoundUpward: 5713096SN/A if (origVal > val) 5723096SN/A val += 1.0; 57311066Snilay@cs.wisc.edu break; 5743096SN/A } 5753096SN/A feraiseexcept(FeInexact); 57611066Snilay@cs.wisc.edu } 5779885Sstever@gmail.com if (isSigned) { 57811680SCurtis.Dunham@arm.com if (half) { 5793096SN/A if (val < (int16_t)(1 << 15)) { 5809885Sstever@gmail.com feraiseexcept(FeInvalid); 58111219Snilay@cs.wisc.edu feclearexcept(FeInexact); 58211731Sjason@lowepower.com return (int16_t)(1 << 15); 58311570SCurtis.Dunham@arm.com } 58410636Snilay@cs.wisc.edu if (val > (int16_t)mask(15)) { 5859988Snilay@cs.wisc.edu feraiseexcept(FeInvalid); 58611066Snilay@cs.wisc.edu feclearexcept(FeInexact); 5873096SN/A return (int16_t)mask(15); 5889348SAli.Saidi@ARM.com } 58911570SCurtis.Dunham@arm.com return (int16_t)val; 59011570SCurtis.Dunham@arm.com } else { 59111570SCurtis.Dunham@arm.com if (val < (int32_t)(1 << 31)) { 59211570SCurtis.Dunham@arm.com feraiseexcept(FeInvalid); 5935876SN/A feclearexcept(FeInexact); 5948835SAli.Saidi@ARM.com return (int32_t)(1 << 31); 5959348SAli.Saidi@ARM.com } 59610036SAli.Saidi@ARM.com if (val > (int32_t)mask(31)) { 5973096SN/A feraiseexcept(FeInvalid); 5988835SAli.Saidi@ARM.com feclearexcept(FeInexact); 59911731Sjason@lowepower.com return (int32_t)mask(31); 6009885Sstever@gmail.com } 6014316SN/A return (int32_t)val; 6023096SN/A } 60311219Snilay@cs.wisc.edu } else { 6043104SN/A if (half) { 6058983Snate@binkert.org if (val < 0) { 6063096SN/A feraiseexcept(FeInvalid); 6079885Sstever@gmail.com feclearexcept(FeInexact); 6089885Sstever@gmail.com return 0; 6099885Sstever@gmail.com } 6109885Sstever@gmail.com if (val > mask(16)) { 6119885Sstever@gmail.com feraiseexcept(FeInvalid); 61211731Sjason@lowepower.com feclearexcept(FeInexact); 61311570SCurtis.Dunham@arm.com return mask(16); 6149988Snilay@cs.wisc.edu } 61511570SCurtis.Dunham@arm.com return (uint16_t)val; 61611570SCurtis.Dunham@arm.com } else { 61711570SCurtis.Dunham@arm.com if (val < 0) { 61811570SCurtis.Dunham@arm.com feraiseexcept(FeInvalid); 61910036SAli.Saidi@ARM.com feclearexcept(FeInexact); 6209885Sstever@gmail.com return 0; 62111731Sjason@lowepower.com } 6229885Sstever@gmail.com if (val > mask(32)) { 6238835SAli.Saidi@ARM.com feraiseexcept(FeInvalid); 6248835SAli.Saidi@ARM.com feclearexcept(FeInexact); 6259988Snilay@cs.wisc.edu return mask(32); 6268835SAli.Saidi@ARM.com } 6279348SAli.Saidi@ARM.com return (uint32_t)val; 6289348SAli.Saidi@ARM.com } 6299988Snilay@cs.wisc.edu } 63010036SAli.Saidi@ARM.com} 6319348SAli.Saidi@ARM.com 6325000SN/Astatic inline double 6336024SN/AvfpUFixedToFpD(FPSCR fpscr, uint32_t val, bool half, uint8_t imm) 6349988Snilay@cs.wisc.edu{ 6355000SN/A fesetround(FeRoundNearest); 6365000SN/A if (half) 6373096SN/A val = (uint16_t)val; 63811066Snilay@cs.wisc.edu double scale = pow(2.0, imm); 6399885Sstever@gmail.com __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 64011680SCurtis.Dunham@arm.com feclearexcept(FeAllExceptions); 6419348SAli.Saidi@ARM.com __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 6429885Sstever@gmail.com return fixDivDest(fpscr, val / scale, (double)val, scale); 64311219Snilay@cs.wisc.edu} 64411731Sjason@lowepower.com 64511570SCurtis.Dunham@arm.comstatic inline double 64610636Snilay@cs.wisc.eduvfpSFixedToFpD(FPSCR fpscr, int32_t val, bool half, uint8_t imm) 6479988Snilay@cs.wisc.edu{ 64811066Snilay@cs.wisc.edu fesetround(FeRoundNearest); 6493096SN/A if (half) 6509348SAli.Saidi@ARM.com val = sext<16>(val & mask(16)); 65111570SCurtis.Dunham@arm.com double scale = pow(2.0, imm); 65211570SCurtis.Dunham@arm.com __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 65311570SCurtis.Dunham@arm.com feclearexcept(FeAllExceptions); 65411570SCurtis.Dunham@arm.com __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 6555876SN/A return fixDivDest(fpscr, val / scale, (double)val, scale); 6568835SAli.Saidi@ARM.com} 6579348SAli.Saidi@ARM.com 65810036SAli.Saidi@ARM.comclass VfpMacroOp : public PredMacroOp 6593096SN/A{ 6608835SAli.Saidi@ARM.com public: 66111731Sjason@lowepower.com static bool 6629885Sstever@gmail.com inScalarBank(IntRegIndex idx) 6639348SAli.Saidi@ARM.com { 6643096SN/A return (idx % 32) < 8; 66511219Snilay@cs.wisc.edu } 6668983Snate@binkert.org 6678983Snate@binkert.org protected: 6683096SN/A bool wide; 6699885Sstever@gmail.com 6709885Sstever@gmail.com VfpMacroOp(const char *mnem, ExtMachInst _machInst, 6719885Sstever@gmail.com OpClass __opClass, bool _wide) : 6729885Sstever@gmail.com PredMacroOp(mnem, _machInst, __opClass), wide(_wide) 6739885Sstever@gmail.com {} 67411731Sjason@lowepower.com 67511570SCurtis.Dunham@arm.com IntRegIndex 6769988Snilay@cs.wisc.edu addStride(IntRegIndex idx, unsigned stride) 67711570SCurtis.Dunham@arm.com { 67811570SCurtis.Dunham@arm.com if (wide) { 67911570SCurtis.Dunham@arm.com stride *= 2; 68011570SCurtis.Dunham@arm.com } 68110036SAli.Saidi@ARM.com unsigned offset = idx % 8; 6829885Sstever@gmail.com idx = (IntRegIndex)(idx - offset); 68311731Sjason@lowepower.com offset += stride; 6849885Sstever@gmail.com idx = (IntRegIndex)(idx + (offset % 8)); 6853096SN/A return idx; 68610451Snilay@cs.wisc.edu } 68711219Snilay@cs.wisc.edu 6889885Sstever@gmail.com void 68911570SCurtis.Dunham@arm.com nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2) 6909988Snilay@cs.wisc.edu { 69110736Snilay@cs.wisc.edu unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 69210736Snilay@cs.wisc.edu assert(!inScalarBank(dest)); 69311570SCurtis.Dunham@arm.com dest = addStride(dest, stride); 69411570SCurtis.Dunham@arm.com op1 = addStride(op1, stride); 69511570SCurtis.Dunham@arm.com if (!inScalarBank(op2)) { 69611384Ssteve.reinhardt@amd.com op2 = addStride(op2, stride); 69711570SCurtis.Dunham@arm.com } 69810736Snilay@cs.wisc.edu } 69911219Snilay@cs.wisc.edu 70010736Snilay@cs.wisc.edu void 7019578Snilay@cs.wisc.edu nextIdxs(IntRegIndex &dest, IntRegIndex &op1) 7027524SN/A { 7039348SAli.Saidi@ARM.com unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 7048983Snate@binkert.org assert(!inScalarBank(dest)); 7058983Snate@binkert.org dest = addStride(dest, stride); 7063096SN/A if (!inScalarBank(op1)) { 70711219Snilay@cs.wisc.edu op1 = addStride(op1, stride); 70811219Snilay@cs.wisc.edu } 70911219Snilay@cs.wisc.edu } 71011219Snilay@cs.wisc.edu 71111219Snilay@cs.wisc.edu void 71211219Snilay@cs.wisc.edu nextIdxs(IntRegIndex &dest) 71311219Snilay@cs.wisc.edu { 7144938SN/A unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 7154938SN/A assert(!inScalarBank(dest)); 7169988Snilay@cs.wisc.edu dest = addStride(dest, stride); 7174938SN/A } 7183096SN/A}; 7193096SN/A 7203096SN/Astatic inline float 7213974SN/AfpAddS(float a, float b) 72210636Snilay@cs.wisc.edu{ 7233147SN/A return a + b; 7243096SN/A} 7255516SN/A 7263147SN/Astatic inline double 7279988Snilay@cs.wisc.edufpAddD(double a, double b) 72811731Sjason@lowepower.com{ 7293147SN/A return a + b; 7303096SN/A} 73110636Snilay@cs.wisc.edu 7325328SN/Astatic inline float 7333096SN/AfpSubS(float a, float b) 7343147SN/A{ 7353147SN/A return a - b; 7365509SN/A} 7373096SN/A 7383147SN/Astatic inline double 73910451Snilay@cs.wisc.edufpSubD(double a, double b) 7403096SN/A{ 7419885Sstever@gmail.com return a - b; 7429885Sstever@gmail.com} 7439885Sstever@gmail.com 74410315Snilay@cs.wisc.edustatic inline float 7459988Snilay@cs.wisc.edufpDivS(float a, float b) 74610315Snilay@cs.wisc.edu{ 7479885Sstever@gmail.com return a / b; 7489885Sstever@gmail.com} 74910315Snilay@cs.wisc.edu 75010315Snilay@cs.wisc.edustatic inline double 75110315Snilay@cs.wisc.edufpDivD(double a, double b) 75210315Snilay@cs.wisc.edu{ 75310315Snilay@cs.wisc.edu return a / b; 75410315Snilay@cs.wisc.edu} 75510315Snilay@cs.wisc.edu 75610315Snilay@cs.wisc.edustatic inline float 7573096SN/AfpMulS(float a, float b) 75810451Snilay@cs.wisc.edu{ 75911680SCurtis.Dunham@arm.com return a * b; 7609885Sstever@gmail.com} 76111570SCurtis.Dunham@arm.com 7629988Snilay@cs.wisc.edustatic inline double 76310736Snilay@cs.wisc.edufpMulD(double a, double b) 76410736Snilay@cs.wisc.edu{ 76511570SCurtis.Dunham@arm.com return a * b; 76611570SCurtis.Dunham@arm.com} 76711570SCurtis.Dunham@arm.com 76811384Ssteve.reinhardt@amd.comclass FpOp : public PredOp 76911570SCurtis.Dunham@arm.com{ 77010736Snilay@cs.wisc.edu protected: 77111680SCurtis.Dunham@arm.com FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 77210736Snilay@cs.wisc.edu PredOp(mnem, _machInst, __opClass) 7739578Snilay@cs.wisc.edu {} 7747524SN/A 77510736Snilay@cs.wisc.edu virtual float 7769150SAli.Saidi@ARM.com doOp(float op1, float op2) const 7778983Snate@binkert.org { 7783096SN/A panic("Unimplemented version of doOp called.\n"); 77911680SCurtis.Dunham@arm.com } 78011680SCurtis.Dunham@arm.com 78111680SCurtis.Dunham@arm.com virtual float 78211680SCurtis.Dunham@arm.com doOp(float op1) const 78311680SCurtis.Dunham@arm.com { 78411680SCurtis.Dunham@arm.com panic("Unimplemented version of doOp called.\n"); 78511680SCurtis.Dunham@arm.com } 7863096SN/A 78710242Ssteve.reinhardt@amd.com virtual double 78811680SCurtis.Dunham@arm.com doOp(double op1, double op2) const 78910451Snilay@cs.wisc.edu { 79011680SCurtis.Dunham@arm.com panic("Unimplemented version of doOp called.\n"); 79110451Snilay@cs.wisc.edu } 79210451Snilay@cs.wisc.edu 79310451Snilay@cs.wisc.edu virtual double 79411680SCurtis.Dunham@arm.com doOp(double op1) const 79510451Snilay@cs.wisc.edu { 79611680SCurtis.Dunham@arm.com panic("Unimplemented version of doOp called.\n"); 79710451Snilay@cs.wisc.edu } 79810451Snilay@cs.wisc.edu 79910451Snilay@cs.wisc.edu double 80011680SCurtis.Dunham@arm.com dbl(uint32_t low, uint32_t high) const 80110451Snilay@cs.wisc.edu { 80211680SCurtis.Dunham@arm.com double junk = 0.0; 80310451Snilay@cs.wisc.edu return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 80411680SCurtis.Dunham@arm.com } 80510451Snilay@cs.wisc.edu 80611680SCurtis.Dunham@arm.com uint32_t 80710451Snilay@cs.wisc.edu dblLow(double val) const 80811680SCurtis.Dunham@arm.com { 80910451Snilay@cs.wisc.edu return fpToBits(val); 81010451Snilay@cs.wisc.edu } 81110451Snilay@cs.wisc.edu 8129578Snilay@cs.wisc.edu uint32_t 81310736Snilay@cs.wisc.edu dblHi(double val) const 81410451Snilay@cs.wisc.edu { 8159348SAli.Saidi@ARM.com return fpToBits(val) >> 32; 8169885Sstever@gmail.com } 8179578Snilay@cs.wisc.edu 8189885Sstever@gmail.com template <class fpType> 8199885Sstever@gmail.com fpType 82011570SCurtis.Dunham@arm.com binaryOp(FPSCR &fpscr, fpType op1, fpType op2, 8219885Sstever@gmail.com fpType (*func)(fpType, fpType), 8229885Sstever@gmail.com bool flush, uint32_t rMode) const 82310636Snilay@cs.wisc.edu { 8249885Sstever@gmail.com const bool single = (sizeof(fpType) == sizeof(float)); 82510451Snilay@cs.wisc.edu fpType junk = 0.0; 8269988Snilay@cs.wisc.edu 8278983Snate@binkert.org if (flush && flushToZero(op1, op2)) 82811680SCurtis.Dunham@arm.com fpscr.idc = 1; 82910242Ssteve.reinhardt@amd.com VfpSavedState state = prepFpState(rMode); 8309578Snilay@cs.wisc.edu __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2), "=m" (state) 83110242Ssteve.reinhardt@amd.com : "m" (op1), "m" (op2), "m" (state)); 8325509SN/A fpType dest = func(op1, op2); 83311570SCurtis.Dunham@arm.com __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest)); 83411570SCurtis.Dunham@arm.com 83511570SCurtis.Dunham@arm.com int fpClass = std::fpclassify(dest); 83610242Ssteve.reinhardt@amd.com // Get NAN behavior right. This varies between x86 and ARM. 83711570SCurtis.Dunham@arm.com if (fpClass == FP_NAN) { 83811680SCurtis.Dunham@arm.com const bool single = (sizeof(fpType) == sizeof(float)); 8399348SAli.Saidi@ARM.com const uint64_t qnan = 8409348SAli.Saidi@ARM.com single ? 0x7fc00000 : ULL(0x7ff8000000000000); 8419885Sstever@gmail.com const bool nan1 = std::isnan(op1); 8429885Sstever@gmail.com const bool nan2 = std::isnan(op2); 8439578Snilay@cs.wisc.edu const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 84410451Snilay@cs.wisc.edu const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); 84510242Ssteve.reinhardt@amd.com if ((!nan1 && !nan2) || (fpscr.dn == 1)) { 8469578Snilay@cs.wisc.edu dest = bitsToFp(qnan, junk); 84710451Snilay@cs.wisc.edu } else if (signal1) { 8489988Snilay@cs.wisc.edu dest = bitsToFp(fpToBits(op1) | qnan, junk); 8499578Snilay@cs.wisc.edu } else if (signal2) { 8509348SAli.Saidi@ARM.com dest = bitsToFp(fpToBits(op2) | qnan, junk); 85110242Ssteve.reinhardt@amd.com } else if (nan1) { 8529578Snilay@cs.wisc.edu dest = op1; 85310242Ssteve.reinhardt@amd.com } else if (nan2) { 85410451Snilay@cs.wisc.edu dest = op2; 85510242Ssteve.reinhardt@amd.com } 85610242Ssteve.reinhardt@amd.com } else if (flush && flushToZero(dest)) { 85710242Ssteve.reinhardt@amd.com feraiseexcept(FeUnderflow); 8589578Snilay@cs.wisc.edu } else if (( 85910242Ssteve.reinhardt@amd.com (single && (dest == bitsToFp(0x00800000, junk) || 86011680SCurtis.Dunham@arm.com dest == bitsToFp(0x80800000, junk))) || 86110451Snilay@cs.wisc.edu (!single && 86211680SCurtis.Dunham@arm.com (dest == bitsToFp(ULL(0x0010000000000000), junk) || 86310451Snilay@cs.wisc.edu dest == bitsToFp(ULL(0x8010000000000000), junk))) 86410242Ssteve.reinhardt@amd.com ) && rMode != VfpRoundZero) { 86510242Ssteve.reinhardt@amd.com /* 86610242Ssteve.reinhardt@amd.com * Correct for the fact that underflow is detected -before- rounding 8678983Snate@binkert.org * in ARM and -after- rounding in x86. 8683096SN/A */ 8699885Sstever@gmail.com fesetround(FeRoundZero); 8709885Sstever@gmail.com __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2) 8719988Snilay@cs.wisc.edu : "m" (op1), "m" (op2)); 8729885Sstever@gmail.com fpType temp = func(op1, op2); 8739885Sstever@gmail.com __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); 874 if (flush && flushToZero(temp)) { 875 dest = temp; 876 } 877 } 878 finishVfp(fpscr, state); 879 return dest; 880 } 881 882 template <class fpType> 883 fpType 884 unaryOp(FPSCR &fpscr, fpType op1, 885 fpType (*func)(fpType), 886 bool flush, uint32_t rMode) const 887 { 888 const bool single = (sizeof(fpType) == sizeof(float)); 889 fpType junk = 0.0; 890 891 if (flush && flushToZero(op1)) 892 fpscr.idc = 1; 893 VfpSavedState state = prepFpState(rMode); 894 __asm__ __volatile__ ("" : "=m" (op1), "=m" (state) 895 : "m" (op1), "m" (state)); 896 fpType dest = func(op1); 897 __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest)); 898 899 int fpClass = std::fpclassify(dest); 900 // Get NAN behavior right. This varies between x86 and ARM. 901 if (fpClass == FP_NAN) { 902 const bool single = (sizeof(fpType) == sizeof(float)); 903 const uint64_t qnan = 904 single ? 0x7fc00000 : ULL(0x7ff8000000000000); 905 const bool nan = std::isnan(op1); 906 if (!nan || fpscr.dn == 1) { 907 dest = bitsToFp(qnan, junk); 908 } else if (nan) { 909 dest = bitsToFp(fpToBits(op1) | qnan, junk); 910 } 911 } else if (flush && flushToZero(dest)) { 912 feraiseexcept(FeUnderflow); 913 } else if (( 914 (single && (dest == bitsToFp(0x00800000, junk) || 915 dest == bitsToFp(0x80800000, junk))) || 916 (!single && 917 (dest == bitsToFp(ULL(0x0010000000000000), junk) || 918 dest == bitsToFp(ULL(0x8010000000000000), junk))) 919 ) && rMode != VfpRoundZero) { 920 /* 921 * Correct for the fact that underflow is detected -before- rounding 922 * in ARM and -after- rounding in x86. 923 */ 924 fesetround(FeRoundZero); 925 __asm__ __volatile__ ("" : "=m" (op1) : "m" (op1)); 926 fpType temp = func(op1); 927 __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); 928 if (flush && flushToZero(temp)) { 929 dest = temp; 930 } 931 } 932 finishVfp(fpscr, state); 933 return dest; 934 } 935}; 936 937class FpRegRegOp : public FpOp 938{ 939 protected: 940 IntRegIndex dest; 941 IntRegIndex op1; 942 943 FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 944 IntRegIndex _dest, IntRegIndex _op1, 945 VfpMicroMode mode = VfpNotAMicroop) : 946 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1) 947 { 948 setVfpMicroFlags(mode, flags); 949 } 950 951 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 952}; 953 954class FpRegImmOp : public FpOp 955{ 956 protected: 957 IntRegIndex dest; 958 uint64_t imm; 959 960 FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 961 IntRegIndex _dest, uint64_t _imm, 962 VfpMicroMode mode = VfpNotAMicroop) : 963 FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm) 964 { 965 setVfpMicroFlags(mode, flags); 966 } 967 968 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 969}; 970 971class FpRegRegImmOp : public FpOp 972{ 973 protected: 974 IntRegIndex dest; 975 IntRegIndex op1; 976 uint64_t imm; 977 978 FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 979 IntRegIndex _dest, IntRegIndex _op1, 980 uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : 981 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm) 982 { 983 setVfpMicroFlags(mode, flags); 984 } 985 986 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 987}; 988 989class FpRegRegRegOp : public FpOp 990{ 991 protected: 992 IntRegIndex dest; 993 IntRegIndex op1; 994 IntRegIndex op2; 995 996 FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 997 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, 998 VfpMicroMode mode = VfpNotAMicroop) : 999 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2) 1000 { 1001 setVfpMicroFlags(mode, flags); 1002 } 1003 1004 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 1005}; 1006 1007} 1008 1009#endif //__ARCH_ARM_INSTS_VFP_HH__ 1010