vfp.hh revision 7397
12623SN/A/* 22623SN/A * Copyright (c) 2010 ARM Limited 32623SN/A * All rights reserved 42623SN/A * 52623SN/A * The license below extends only to copyright in the software and shall 62623SN/A * not be construed as granting a license to any other intellectual 72623SN/A * property including but not limited to intellectual property relating 82623SN/A * to a hardware implementation of the functionality of the software 92623SN/A * licensed hereunder. You may use the software subject to the license 102623SN/A * terms below provided that you ensure that this notice is replicated 112623SN/A * unmodified and in its entirety in all distributions of the software, 122623SN/A * modified or unmodified, in source code or in binary form. 132623SN/A * 142623SN/A * Redistribution and use in source and binary forms, with or without 152623SN/A * modification, are permitted provided that the following conditions are 162623SN/A * met: redistributions of source code must retain the above copyright 172623SN/A * notice, this list of conditions and the following disclaimer; 182623SN/A * redistributions in binary form must reproduce the above copyright 192623SN/A * notice, this list of conditions and the following disclaimer in the 202623SN/A * documentation and/or other materials provided with the distribution; 212623SN/A * neither the name of the copyright holders nor the names of its 222623SN/A * contributors may be used to endorse or promote products derived from 232623SN/A * this software without specific prior written permission. 242623SN/A * 252623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 262623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 272665Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 282665Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 292623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 302623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 313170Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 323806Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 332623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 344040Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 352623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 362623SN/A * 373348Sbinkertn@umich.edu * Authors: Gabe Black 383348Sbinkertn@umich.edu */ 394762Snate@binkert.org 402901Ssaidi@eecs.umich.edu#ifndef __ARCH_ARM_INSTS_VFP_HH__ 412623SN/A#define __ARCH_ARM_INSTS_VFP_HH__ 422623SN/A 432623SN/A#include "arch/arm/insts/misc.hh" 442623SN/A#include "arch/arm/miscregs.hh" 452623SN/A#include <fenv.h> 465606Snate@binkert.org#include <cmath> 472623SN/A 482623SN/Anamespace ArmISA 492623SN/A{ 502623SN/A 512623SN/Aenum VfpMicroMode { 522623SN/A VfpNotAMicroop, 532623SN/A VfpMicroop, 542623SN/A VfpFirstMicroop, 552623SN/A VfpLastMicroop 562623SN/A}; 572623SN/A 585336Shines@cs.fsu.edutemplate<class T> 592623SN/Astatic inline void 604873Sstever@eecs.umich.edusetVfpMicroFlags(VfpMicroMode mode, T &flags) 612623SN/A{ 622623SN/A switch (mode) { 632856Srdreslin@umich.edu case VfpMicroop: 642856Srdreslin@umich.edu flags[StaticInst::IsMicroop] = true; 652856Srdreslin@umich.edu break; 662856Srdreslin@umich.edu case VfpFirstMicroop: 672856Srdreslin@umich.edu flags[StaticInst::IsMicroop] = 682856Srdreslin@umich.edu flags[StaticInst::IsFirstMicroop] = true; 692856Srdreslin@umich.edu break; 704968Sacolyte@umich.edu case VfpLastMicroop: 714968Sacolyte@umich.edu flags[StaticInst::IsMicroop] = 724968Sacolyte@umich.edu flags[StaticInst::IsLastMicroop] = true; 734968Sacolyte@umich.edu break; 742856Srdreslin@umich.edu case VfpNotAMicroop: 752856Srdreslin@umich.edu break; 762856Srdreslin@umich.edu } 772623SN/A if (mode == VfpMicroop || mode == VfpFirstMicroop) { 782623SN/A flags[StaticInst::IsDelayedCommit] = true; 792623SN/A } 802623SN/A} 812623SN/A 822623SN/Aenum FeExceptionBit 832680Sktlim@umich.edu{ 842680Sktlim@umich.edu FeDivByZero = FE_DIVBYZERO, 852623SN/A FeInexact = FE_INEXACT, 862623SN/A FeInvalid = FE_INVALID, 875714Shsul@eecs.umich.edu FeOverflow = FE_OVERFLOW, 882623SN/A FeUnderflow = FE_UNDERFLOW, 892623SN/A FeAllExceptions = FE_ALL_EXCEPT 904968Sacolyte@umich.edu}; 914968Sacolyte@umich.edu 924968Sacolyte@umich.eduenum FeRoundingMode 934968Sacolyte@umich.edu{ 944968Sacolyte@umich.edu FeRoundDown = FE_DOWNWARD, 954968Sacolyte@umich.edu FeRoundNearest = FE_TONEAREST, 965714Shsul@eecs.umich.edu FeRoundZero = FE_TOWARDZERO, 975712Shsul@eecs.umich.edu FeRoundUpward = FE_UPWARD 985712Shsul@eecs.umich.edu}; 995712Shsul@eecs.umich.edu 1002623SN/Aenum VfpRoundingMode 1012623SN/A{ 1022623SN/A VfpRoundNearest = 0, 1033349Sbinkertn@umich.edu VfpRoundUpward = 1, 1042623SN/A VfpRoundDown = 2, 1053184Srdreslin@umich.edu VfpRoundZero = 3 1062623SN/A}; 1072623SN/A 1082623SN/Atemplate <class fpType> 1092623SN/Astatic inline bool 1103349Sbinkertn@umich.eduflushToZero(fpType &op) 1112623SN/A{ 1123310Srdreslin@umich.edu fpType junk = 0.0; 1133649Srdreslin@umich.edu if (std::fpclassify(op) == FP_SUBNORMAL) { 1142623SN/A uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 1152623SN/A op = bitsToFp(fpToBits(op) & bitMask, junk); 1162623SN/A return true; 1173349Sbinkertn@umich.edu } 1182623SN/A return false; 1193184Srdreslin@umich.edu} 1203184Srdreslin@umich.edu 1212623SN/Atemplate <class fpType> 1222623SN/Astatic inline bool 1232623SN/AflushToZero(fpType &op1, fpType &op2) 1242623SN/A{ 1252623SN/A bool flush1 = flushToZero(op1); 1263647Srdreslin@umich.edu bool flush2 = flushToZero(op2); 1273647Srdreslin@umich.edu return flush1 || flush2; 1283647Srdreslin@umich.edu} 1293647Srdreslin@umich.edu 1303647Srdreslin@umich.edutemplate <class fpType> 1312626SN/Astatic inline void 1323647Srdreslin@umich.eduvfpFlushToZero(FPSCR &fpscr, fpType &op) 1332626SN/A{ 1342623SN/A if (fpscr.fz == 1 && flushToZero(op)) { 1352623SN/A fpscr.idc = 1; 1362623SN/A } 1372657Ssaidi@eecs.umich.edu} 1382623SN/A 1392623SN/Atemplate <class fpType> 1402623SN/Astatic inline void 1412623SN/AvfpFlushToZero(FPSCR &fpscr, fpType &op1, fpType &op2) 1422623SN/A{ 1434192Sktlim@umich.edu vfpFlushToZero(fpscr, op1); 1444192Sktlim@umich.edu vfpFlushToZero(fpscr, op2); 1454192Sktlim@umich.edu} 1464192Sktlim@umich.edu 1474192Sktlim@umich.edustatic inline uint32_t 1484192Sktlim@umich.edufpToBits(float fp) 1494192Sktlim@umich.edu{ 1504192Sktlim@umich.edu union 1515497Ssaidi@eecs.umich.edu { 1524192Sktlim@umich.edu float fp; 1534192Sktlim@umich.edu uint32_t bits; 1542623SN/A } val; 1555529Snate@binkert.org val.fp = fp; 1565487Snate@binkert.org return val.bits; 1575487Snate@binkert.org} 1585487Snate@binkert.org 1594968Sacolyte@umich.edustatic inline uint64_t 1604968Sacolyte@umich.edufpToBits(double fp) 1612623SN/A{ 1622623SN/A union 1632623SN/A { 1643647Srdreslin@umich.edu double fp; 1653647Srdreslin@umich.edu uint64_t bits; 1663647Srdreslin@umich.edu } val; 1672623SN/A val.fp = fp; 1682623SN/A return val.bits; 1692623SN/A} 1702623SN/A 1712623SN/Astatic inline float 1722623SN/AbitsToFp(uint64_t bits, float junk) 1732623SN/A{ 1742623SN/A union 1752623SN/A { 1762623SN/A float fp; 1772915Sktlim@umich.edu uint32_t bits; 1782915Sktlim@umich.edu } val; 1793145Shsul@eecs.umich.edu val.bits = bits; 1802623SN/A return val.fp; 1812623SN/A} 1822623SN/A 1832623SN/Astatic inline double 1842623SN/AbitsToFp(uint64_t bits, double junk) 1852623SN/A{ 1862623SN/A union 1872915Sktlim@umich.edu { 1882915Sktlim@umich.edu double fp; 1893145Shsul@eecs.umich.edu uint64_t bits; 1902915Sktlim@umich.edu } val; 1912915Sktlim@umich.edu val.bits = bits; 1922915Sktlim@umich.edu return val.fp; 1932915Sktlim@umich.edu} 1942915Sktlim@umich.edu 1952915Sktlim@umich.edutypedef int VfpSavedState; 1965220Ssaidi@eecs.umich.edu 1975220Ssaidi@eecs.umich.edustatic inline VfpSavedState 1985220Ssaidi@eecs.umich.eduprepFpState(uint32_t rMode) 1994940Snate@binkert.org{ 2005220Ssaidi@eecs.umich.edu int roundingMode = fegetround(); 2013324Shsul@eecs.umich.edu feclearexcept(FeAllExceptions); 2025220Ssaidi@eecs.umich.edu switch (rMode) { 2035220Ssaidi@eecs.umich.edu case VfpRoundNearest: 2045606Snate@binkert.org fesetround(FeRoundNearest); 2055606Snate@binkert.org break; 2062915Sktlim@umich.edu case VfpRoundUpward: 2072623SN/A fesetround(FeRoundUpward); 2082623SN/A break; 2092623SN/A case VfpRoundDown: 2102798Sktlim@umich.edu fesetround(FeRoundDown); 2112623SN/A break; 2125496Ssaidi@eecs.umich.edu case VfpRoundZero: 2132798Sktlim@umich.edu fesetround(FeRoundZero); 2142623SN/A break; 2152798Sktlim@umich.edu } 2162623SN/A return roundingMode; 2172623SN/A} 2182623SN/A 2192623SN/Astatic inline void 2202623SN/AfinishVfp(FPSCR &fpscr, VfpSavedState state) 2212623SN/A{ 2224192Sktlim@umich.edu int exceptions = fetestexcept(FeAllExceptions); 2232623SN/A bool underflow = false; 2242623SN/A if (exceptions & FeInvalid) { 2252623SN/A fpscr.ioc = 1; 2262680Sktlim@umich.edu } 2272623SN/A if (exceptions & FeDivByZero) { 2282680Sktlim@umich.edu fpscr.dzc = 1; 2292680Sktlim@umich.edu } 2302680Sktlim@umich.edu if (exceptions & FeOverflow) { 2312623SN/A fpscr.ofc = 1; 2325606Snate@binkert.org } 2332623SN/A if (exceptions & FeUnderflow) { 2342623SN/A underflow = true; 2352623SN/A fpscr.ufc = 1; 2363512Sktlim@umich.edu } 2373512Sktlim@umich.edu if ((exceptions & FeInexact) && !(underflow && fpscr.fz)) { 2383512Sktlim@umich.edu fpscr.ixc = 1; 2395169Ssaidi@eecs.umich.edu } 2405712Shsul@eecs.umich.edu fesetround(state); 2415712Shsul@eecs.umich.edu} 2425712Shsul@eecs.umich.edu 2432623SN/Atemplate <class fpType> 2442623SN/Astatic inline fpType 2452623SN/AfixDest(FPSCR fpscr, fpType val, fpType op1) 2462623SN/A{ 2472623SN/A int fpClass = std::fpclassify(val); 2482623SN/A fpType junk = 0.0; 2494940Snate@binkert.org if (fpClass == FP_NAN) { 2504940Snate@binkert.org const bool single = (sizeof(val) == sizeof(float)); 2512623SN/A const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 2522683Sktlim@umich.edu const bool nan = std::isnan(op1); 2532623SN/A if (!nan || (fpscr.dn == 1)) { 2542623SN/A val = bitsToFp(qnan, junk); 2552623SN/A } else if (nan) { 2562623SN/A val = bitsToFp(fpToBits(op1) | qnan, junk); 2572623SN/A } 2585101Ssaidi@eecs.umich.edu } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) { 2593686Sktlim@umich.edu // Turn val into a zero with the correct sign; 2603430Sgblack@eecs.umich.edu uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 2615606Snate@binkert.org val = bitsToFp(fpToBits(val) & bitMask, junk); 2622623SN/A feclearexcept(FeInexact); 2632623SN/A feraiseexcept(FeUnderflow); 2642623SN/A } 2652623SN/A return val; 2662623SN/A} 2672623SN/A 2682623SN/Atemplate <class fpType> 2694940Snate@binkert.orgstatic inline fpType 2704940Snate@binkert.orgfixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2) 2712623SN/A{ 2722683Sktlim@umich.edu int fpClass = std::fpclassify(val); 2732623SN/A fpType junk = 0.0; 2742623SN/A if (fpClass == FP_NAN) { 2752626SN/A const bool single = (sizeof(val) == sizeof(float)); 2762626SN/A const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 2772626SN/A const bool nan1 = std::isnan(op1); 2782626SN/A const bool nan2 = std::isnan(op2); 2795606Snate@binkert.org const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 2802623SN/A const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); 2812623SN/A if ((!nan1 && !nan2) || (fpscr.dn == 1)) { 2822623SN/A val = bitsToFp(qnan, junk); 2832623SN/A } else if (signal1) { 2842623SN/A val = bitsToFp(fpToBits(op1) | qnan, junk); 2852623SN/A } else if (signal2) { 2862623SN/A val = bitsToFp(fpToBits(op2) | qnan, junk); 2872623SN/A } else if (nan1) { 2882623SN/A val = op1; 2892623SN/A } else if (nan2) { 2903169Sstever@eecs.umich.edu val = op2; 2914870Sstever@eecs.umich.edu } 2922623SN/A } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) { 2932623SN/A // Turn val into a zero with the correct sign; 2942623SN/A uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 2952623SN/A val = bitsToFp(fpToBits(val) & bitMask, junk); 2962623SN/A feclearexcept(FeInexact); 2974999Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 2984999Sgblack@eecs.umich.edu } 2994999Sgblack@eecs.umich.edu return val; 3004999Sgblack@eecs.umich.edu} 3012623SN/A 3024999Sgblack@eecs.umich.edutemplate <class fpType> 3032623SN/Astatic inline fpType 3044999Sgblack@eecs.umich.edufixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2) 3054999Sgblack@eecs.umich.edu{ 3064999Sgblack@eecs.umich.edu fpType mid = fixDest(fpscr, val, op1, op2); 3074999Sgblack@eecs.umich.edu const bool single = (sizeof(fpType) == sizeof(float)); 3084999Sgblack@eecs.umich.edu const fpType junk = 0.0; 3094999Sgblack@eecs.umich.edu if ((single && (val == bitsToFp(0x00800000, junk) || 3104999Sgblack@eecs.umich.edu val == bitsToFp(0x80800000, junk))) || 3114999Sgblack@eecs.umich.edu (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) || 3124999Sgblack@eecs.umich.edu val == bitsToFp(ULL(0x8010000000000000), junk))) 3134999Sgblack@eecs.umich.edu ) { 3144999Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (op1) : "m" (op1)); 3154999Sgblack@eecs.umich.edu fesetround(FeRoundZero); 3164999Sgblack@eecs.umich.edu fpType temp = 0.0; 3175891Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 3184999Sgblack@eecs.umich.edu temp = op1 / op2; 3194999Sgblack@eecs.umich.edu if (flushToZero(temp)) { 3204999Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 3214999Sgblack@eecs.umich.edu if (fpscr.fz) { 3224999Sgblack@eecs.umich.edu feclearexcept(FeInexact); 3234999Sgblack@eecs.umich.edu mid = temp; 3244999Sgblack@eecs.umich.edu } 3254999Sgblack@eecs.umich.edu } 3264999Sgblack@eecs.umich.edu __asm__ __volatile__("" :: "m" (temp)); 3274999Sgblack@eecs.umich.edu } 3284999Sgblack@eecs.umich.edu return mid; 3294999Sgblack@eecs.umich.edu} 3304999Sgblack@eecs.umich.edu 3314999Sgblack@eecs.umich.edustatic inline float 3324999Sgblack@eecs.umich.edufixFpDFpSDest(FPSCR fpscr, double val) 3334999Sgblack@eecs.umich.edu{ 3344999Sgblack@eecs.umich.edu const float junk = 0.0; 3355012Sgblack@eecs.umich.edu float op1 = 0.0; 3364999Sgblack@eecs.umich.edu if (std::isnan(val)) { 3374999Sgblack@eecs.umich.edu uint64_t valBits = fpToBits(val); 3384999Sgblack@eecs.umich.edu uint32_t op1Bits = bits(valBits, 50, 29) | 3394999Sgblack@eecs.umich.edu (mask(9) << 22) | 3404999Sgblack@eecs.umich.edu (bits(valBits, 63) << 31); 3414968Sacolyte@umich.edu op1 = bitsToFp(op1Bits, junk); 3424986Ssaidi@eecs.umich.edu } 3434999Sgblack@eecs.umich.edu float mid = fixDest(fpscr, (float)val, op1); 3444999Sgblack@eecs.umich.edu if (fpscr.fz && fetestexcept(FeUnderflow | FeInexact) == 3454999Sgblack@eecs.umich.edu (FeUnderflow | FeInexact)) { 3464762Snate@binkert.org feclearexcept(FeInexact); 3474999Sgblack@eecs.umich.edu } 3484999Sgblack@eecs.umich.edu if (mid == bitsToFp(0x00800000, junk) || 3494999Sgblack@eecs.umich.edu mid == bitsToFp(0x80800000, junk)) { 3504999Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 3514999Sgblack@eecs.umich.edu fesetround(FeRoundZero); 3524999Sgblack@eecs.umich.edu float temp = 0.0; 3534999Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 3545408Sgblack@eecs.umich.edu temp = val; 3555408Sgblack@eecs.umich.edu if (flushToZero(temp)) { 3565408Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 3574999Sgblack@eecs.umich.edu if (fpscr.fz) { 3584968Sacolyte@umich.edu feclearexcept(FeInexact); 3593170Sstever@eecs.umich.edu mid = temp; 3604999Sgblack@eecs.umich.edu } 3614999Sgblack@eecs.umich.edu } 3624999Sgblack@eecs.umich.edu __asm__ __volatile__("" :: "m" (temp)); 3634999Sgblack@eecs.umich.edu } 3644999Sgblack@eecs.umich.edu return mid; 3654999Sgblack@eecs.umich.edu} 3664999Sgblack@eecs.umich.edu 3674999Sgblack@eecs.umich.edustatic inline double 3684999Sgblack@eecs.umich.edufixFpSFpDDest(FPSCR fpscr, float val) 3694999Sgblack@eecs.umich.edu{ 3702623SN/A const double junk = 0.0; 3712623SN/A double op1 = 0.0; 3722623SN/A if (std::isnan(val)) { 3732623SN/A uint32_t valBits = fpToBits(val); 3742623SN/A uint64_t op1Bits = ((uint64_t)bits(valBits, 21, 0) << 29) | 3752623SN/A (mask(12) << 51) | 3762623SN/A ((uint64_t)bits(valBits, 31) << 63); 3774115Ssaidi@eecs.umich.edu op1 = bitsToFp(op1Bits, junk); 3784115Ssaidi@eecs.umich.edu } 3794115Ssaidi@eecs.umich.edu double mid = fixDest(fpscr, (double)val, op1); 3804115Ssaidi@eecs.umich.edu if (mid == bitsToFp(ULL(0x0010000000000000), junk) || 3814040Ssaidi@eecs.umich.edu mid == bitsToFp(ULL(0x8010000000000000), junk)) { 3824040Ssaidi@eecs.umich.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 3834040Ssaidi@eecs.umich.edu fesetround(FeRoundZero); 3844040Ssaidi@eecs.umich.edu double temp = 0.0; 3852623SN/A __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 3862623SN/A temp = val; 3872623SN/A if (flushToZero(temp)) { 3882623SN/A feraiseexcept(FeUnderflow); 3892623SN/A if (fpscr.fz) { 3902623SN/A feclearexcept(FeInexact); 3912623SN/A mid = temp; 3922623SN/A } 3932623SN/A } 3942623SN/A __asm__ __volatile__("" :: "m" (temp)); 3952623SN/A } 3962623SN/A return mid; 3972623SN/A} 3982623SN/A 3992623SN/Astatic inline double 4002623SN/AmakeDouble(uint32_t low, uint32_t high) 4012623SN/A{ 4022623SN/A double junk = 0.0; 4032623SN/A return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 4042623SN/A} 4052623SN/A 4062623SN/Astatic inline uint32_t 4072623SN/AlowFromDouble(double val) 4082623SN/A{ 4092623SN/A return fpToBits(val); 4102623SN/A} 4112623SN/A 4122623SN/Astatic inline uint32_t 4132623SN/AhighFromDouble(double val) 4142623SN/A{ 4152623SN/A return fpToBits(val) >> 32; 4162623SN/A} 4172623SN/A 4182623SN/Astatic inline uint64_t 4192623SN/AvfpFpSToFixed(float val, bool isSigned, bool half, 4202623SN/A uint8_t imm, bool rzero = true) 4212623SN/A{ 4222623SN/A int rmode = rzero ? FeRoundZero : fegetround(); 4232623SN/A __asm__ __volatile__("" : "=m" (rmode) : "m" (rmode)); 4242623SN/A fesetround(FeRoundNearest); 4252623SN/A val = val * powf(2.0, imm); 4262623SN/A __asm__ __volatile__("" : "=m" (val) : "m" (val)); 4272623SN/A fesetround(rmode); 4283169Sstever@eecs.umich.edu feclearexcept(FeAllExceptions); 4294870Sstever@eecs.umich.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 4302623SN/A float origVal = val; 4312623SN/A val = rintf(val); 4322623SN/A int fpType = std::fpclassify(val); 4332623SN/A if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { 4342623SN/A if (fpType == FP_NAN) { 4354999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 4364999Sgblack@eecs.umich.edu } 4374999Sgblack@eecs.umich.edu val = 0.0; 4384999Sgblack@eecs.umich.edu } else if (origVal != val) { 4392623SN/A switch (rmode) { 4404999Sgblack@eecs.umich.edu case FeRoundNearest: 4412623SN/A if (origVal - val > 0.5) 4424999Sgblack@eecs.umich.edu val += 1.0; 4434999Sgblack@eecs.umich.edu else if (val - origVal > 0.5) 4444999Sgblack@eecs.umich.edu val -= 1.0; 4454999Sgblack@eecs.umich.edu break; 4464999Sgblack@eecs.umich.edu case FeRoundDown: 4474999Sgblack@eecs.umich.edu if (origVal < val) 4484999Sgblack@eecs.umich.edu val -= 1.0; 4494999Sgblack@eecs.umich.edu break; 4504999Sgblack@eecs.umich.edu case FeRoundUpward: 4514999Sgblack@eecs.umich.edu if (origVal > val) 4524999Sgblack@eecs.umich.edu val += 1.0; 4534999Sgblack@eecs.umich.edu break; 4544999Sgblack@eecs.umich.edu } 4555891Sgblack@eecs.umich.edu feraiseexcept(FeInexact); 4564999Sgblack@eecs.umich.edu } 4574999Sgblack@eecs.umich.edu 4584999Sgblack@eecs.umich.edu if (isSigned) { 4594999Sgblack@eecs.umich.edu if (half) { 4604999Sgblack@eecs.umich.edu if ((double)val < (int16_t)(1 << 15)) { 4614999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 4624999Sgblack@eecs.umich.edu feclearexcept(FeInexact); 4634999Sgblack@eecs.umich.edu return (int16_t)(1 << 15); 4644999Sgblack@eecs.umich.edu } 4654999Sgblack@eecs.umich.edu if ((double)val > (int16_t)mask(15)) { 4664999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 4674999Sgblack@eecs.umich.edu feclearexcept(FeInexact); 4684999Sgblack@eecs.umich.edu return (int16_t)mask(15); 4694999Sgblack@eecs.umich.edu } 4704999Sgblack@eecs.umich.edu return (int16_t)val; 4714999Sgblack@eecs.umich.edu } else { 4724999Sgblack@eecs.umich.edu if ((double)val < (int32_t)(1 << 31)) { 4734999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 4744999Sgblack@eecs.umich.edu feclearexcept(FeInexact); 4754999Sgblack@eecs.umich.edu return (int32_t)(1 << 31); 4764999Sgblack@eecs.umich.edu } 4774999Sgblack@eecs.umich.edu if ((double)val > (int32_t)mask(31)) { 4784999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 4794999Sgblack@eecs.umich.edu feclearexcept(FeInexact); 4804999Sgblack@eecs.umich.edu return (int32_t)mask(31); 4814999Sgblack@eecs.umich.edu } 4824999Sgblack@eecs.umich.edu return (int32_t)val; 4834999Sgblack@eecs.umich.edu } 4844999Sgblack@eecs.umich.edu } else { 4854999Sgblack@eecs.umich.edu if (half) { 4864999Sgblack@eecs.umich.edu if ((double)val < 0) { 4874999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 4884999Sgblack@eecs.umich.edu feclearexcept(FeInexact); 4894999Sgblack@eecs.umich.edu return 0; 4904999Sgblack@eecs.umich.edu } 4914999Sgblack@eecs.umich.edu if ((double)val > (mask(16))) { 4924999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 4934999Sgblack@eecs.umich.edu feclearexcept(FeInexact); 4944999Sgblack@eecs.umich.edu return mask(16); 4954999Sgblack@eecs.umich.edu } 4964999Sgblack@eecs.umich.edu return (uint16_t)val; 4974999Sgblack@eecs.umich.edu } else { 4984999Sgblack@eecs.umich.edu if ((double)val < 0) { 4994999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 5004999Sgblack@eecs.umich.edu feclearexcept(FeInexact); 5014878Sstever@eecs.umich.edu return 0; 5024040Ssaidi@eecs.umich.edu } 5034040Ssaidi@eecs.umich.edu if ((double)val > (mask(32))) { 5044999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 5054999Sgblack@eecs.umich.edu feclearexcept(FeInexact); 5064999Sgblack@eecs.umich.edu return mask(32); 5072631SN/A } 5084999Sgblack@eecs.umich.edu return (uint32_t)val; 5094999Sgblack@eecs.umich.edu } 5104999Sgblack@eecs.umich.edu } 5114999Sgblack@eecs.umich.edu} 5124999Sgblack@eecs.umich.edu 5134999Sgblack@eecs.umich.edustatic inline float 5144999Sgblack@eecs.umich.eduvfpUFixedToFpS(FPSCR fpscr, uint32_t val, bool half, uint8_t imm) 5155408Sgblack@eecs.umich.edu{ 5165408Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 5175408Sgblack@eecs.umich.edu if (half) 5184999Sgblack@eecs.umich.edu val = (uint16_t)val; 5193170Sstever@eecs.umich.edu float scale = powf(2.0, imm); 5203170Sstever@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 5214999Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 5224999Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 5234999Sgblack@eecs.umich.edu return fixDivDest(fpscr, val / scale, (float)val, scale); 5244999Sgblack@eecs.umich.edu} 5254999Sgblack@eecs.umich.edu 5264999Sgblack@eecs.umich.edustatic inline float 5274999Sgblack@eecs.umich.eduvfpSFixedToFpS(FPSCR fpscr, int32_t val, bool half, uint8_t imm) 5284999Sgblack@eecs.umich.edu{ 5294999Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 5304999Sgblack@eecs.umich.edu if (half) 5312623SN/A val = sext<16>(val & mask(16)); 5322623SN/A float scale = powf(2.0, imm); 5332623SN/A __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 5342623SN/A feclearexcept(FeAllExceptions); 5352623SN/A __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 5364224Sgblack@eecs.umich.edu return fixDivDest(fpscr, val / scale, (float)val, scale); 5374224Sgblack@eecs.umich.edu} 5384224Sgblack@eecs.umich.edu 5394224Sgblack@eecs.umich.edustatic inline uint64_t 5404224Sgblack@eecs.umich.eduvfpFpDToFixed(double val, bool isSigned, bool half, 5414224Sgblack@eecs.umich.edu uint8_t imm, bool rzero = true) 5424224Sgblack@eecs.umich.edu{ 5434224Sgblack@eecs.umich.edu int rmode = rzero ? FeRoundZero : fegetround(); 5444224Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 5454224Sgblack@eecs.umich.edu val = val * pow(2.0, imm); 5464224Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 5472623SN/A fesetround(rmode); 5482623SN/A feclearexcept(FeAllExceptions); 5492623SN/A __asm__ __volatile__("" : "=m" (val) : "m" (val)); 5502623SN/A double origVal = val; 5512623SN/A val = rint(val); 5522623SN/A int fpType = std::fpclassify(val); 5532623SN/A if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { 5542623SN/A if (fpType == FP_NAN) { 5552623SN/A feraiseexcept(FeInvalid); 5562623SN/A } 5572623SN/A val = 0.0; 5582623SN/A } else if (origVal != val) { 5592623SN/A switch (rmode) { 5602623SN/A case FeRoundNearest: 5612623SN/A if (origVal - val > 0.5) 5622623SN/A val += 1.0; 5632623SN/A else if (val - origVal > 0.5) 5642623SN/A val -= 1.0; 5652623SN/A break; 5662623SN/A case FeRoundDown: 5672623SN/A if (origVal < val) 5682623SN/A val -= 1.0; 5692623SN/A break; 5702623SN/A case FeRoundUpward: 5712623SN/A if (origVal > val) 5722623SN/A val += 1.0; 5732623SN/A break; 5742623SN/A } 5752623SN/A feraiseexcept(FeInexact); 5762623SN/A } 5772623SN/A if (isSigned) { 5782623SN/A if (half) { 5792623SN/A if (val < (int16_t)(1 << 15)) { 5802623SN/A feraiseexcept(FeInvalid); 5812623SN/A feclearexcept(FeInexact); 5822623SN/A return (int16_t)(1 << 15); 5832623SN/A } 5842623SN/A if (val > (int16_t)mask(15)) { 5852623SN/A feraiseexcept(FeInvalid); 5862623SN/A feclearexcept(FeInexact); 5872623SN/A return (int16_t)mask(15); 5882623SN/A } 5892623SN/A return (int16_t)val; 5902623SN/A } else { 5912623SN/A if (val < (int32_t)(1 << 31)) { 5922623SN/A feraiseexcept(FeInvalid); 5932623SN/A feclearexcept(FeInexact); 5942623SN/A return (int32_t)(1 << 31); 5954940Snate@binkert.org } 5964940Snate@binkert.org if (val > (int32_t)mask(31)) { 5975487Snate@binkert.org feraiseexcept(FeInvalid); 5982623SN/A feclearexcept(FeInexact); 5992623SN/A return (int32_t)mask(31); 6002623SN/A } 6012623SN/A return (int32_t)val; 6023387Sgblack@eecs.umich.edu } 6033387Sgblack@eecs.umich.edu } else { 6042626SN/A if (half) { 6055348Ssaidi@eecs.umich.edu if (val < 0) { 6065348Ssaidi@eecs.umich.edu feraiseexcept(FeInvalid); 6075669Sgblack@eecs.umich.edu feclearexcept(FeInexact); 6085669Sgblack@eecs.umich.edu return 0; 6095669Sgblack@eecs.umich.edu } 6105914Sgblack@eecs.umich.edu if (val > mask(16)) { 6115894Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 6125894Sgblack@eecs.umich.edu feclearexcept(FeInexact); 6135894Sgblack@eecs.umich.edu return mask(16); 6142623SN/A } 6152623SN/A return (uint16_t)val; 6164182Sgblack@eecs.umich.edu } else { 6174182Sgblack@eecs.umich.edu if (val < 0) { 6184182Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 6192662Sstever@eecs.umich.edu feclearexcept(FeInexact); 6205914Sgblack@eecs.umich.edu return 0; 6215694Sgblack@eecs.umich.edu } 6225694Sgblack@eecs.umich.edu if (val > mask(32)) { 6235694Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 6245694Sgblack@eecs.umich.edu feclearexcept(FeInexact); 6255669Sgblack@eecs.umich.edu return mask(32); 6265669Sgblack@eecs.umich.edu } 6275669Sgblack@eecs.umich.edu return (uint32_t)val; 6285669Sgblack@eecs.umich.edu } 6295669Sgblack@eecs.umich.edu } 6305669Sgblack@eecs.umich.edu} 6315669Sgblack@eecs.umich.edu 6322623SN/Astatic inline double 6335669Sgblack@eecs.umich.eduvfpUFixedToFpD(FPSCR fpscr, uint32_t val, bool half, uint8_t imm) 6345669Sgblack@eecs.umich.edu{ 6355669Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 6365669Sgblack@eecs.umich.edu if (half) 6374968Sacolyte@umich.edu val = (uint16_t)val; 6385669Sgblack@eecs.umich.edu double scale = pow(2.0, imm); 6394968Sacolyte@umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 6405669Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 6415669Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 6425669Sgblack@eecs.umich.edu return fixDivDest(fpscr, val / scale, (double)val, scale); 6435669Sgblack@eecs.umich.edu} 6444182Sgblack@eecs.umich.edu 6452623SN/Astatic inline double 6463814Ssaidi@eecs.umich.eduvfpSFixedToFpD(FPSCR fpscr, int32_t val, bool half, uint8_t imm) 6475001Sgblack@eecs.umich.edu{ 6484182Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 6494998Sgblack@eecs.umich.edu if (half) 6504998Sgblack@eecs.umich.edu val = sext<16>(val & mask(16)); 6514998Sgblack@eecs.umich.edu double scale = pow(2.0, imm); 6524998Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 6535001Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 6545001Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 6555001Sgblack@eecs.umich.edu return fixDivDest(fpscr, val / scale, (double)val, scale); 6565001Sgblack@eecs.umich.edu} 6575001Sgblack@eecs.umich.edu 6584998Sgblack@eecs.umich.educlass VfpMacroOp : public PredMacroOp 6594182Sgblack@eecs.umich.edu{ 6604182Sgblack@eecs.umich.edu public: 6612623SN/A static bool 6623814Ssaidi@eecs.umich.edu inScalarBank(IntRegIndex idx) 6634539Sgblack@eecs.umich.edu { 6644539Sgblack@eecs.umich.edu return (idx % 32) < 8; 6653814Ssaidi@eecs.umich.edu } 6663814Ssaidi@eecs.umich.edu 6675487Snate@binkert.org protected: 6685487Snate@binkert.org bool wide; 6695487Snate@binkert.org 6705487Snate@binkert.org VfpMacroOp(const char *mnem, ExtMachInst _machInst, 6715487Snate@binkert.org OpClass __opClass, bool _wide) : 6725487Snate@binkert.org PredMacroOp(mnem, _machInst, __opClass), wide(_wide) 6735487Snate@binkert.org {} 6745487Snate@binkert.org 6755487Snate@binkert.org IntRegIndex 6765487Snate@binkert.org addStride(IntRegIndex idx, unsigned stride) 6775487Snate@binkert.org { 6785487Snate@binkert.org if (wide) { 6795487Snate@binkert.org stride *= 2; 6805487Snate@binkert.org } 6815487Snate@binkert.org unsigned offset = idx % 8; 6822623SN/A idx = (IntRegIndex)(idx - offset); 6832623SN/A offset += stride; 6842623SN/A idx = (IntRegIndex)(idx + (offset % 8)); 6854377Sgblack@eecs.umich.edu return idx; 6864182Sgblack@eecs.umich.edu } 6872623SN/A 6882623SN/A void 6895487Snate@binkert.org nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2) 6905487Snate@binkert.org { 6915487Snate@binkert.org unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 6925487Snate@binkert.org assert(!inScalarBank(dest)); 6932626SN/A dest = addStride(dest, stride); 6945606Snate@binkert.org op1 = addStride(op1, stride); 6952623SN/A if (!inScalarBank(op2)) { 6962623SN/A op2 = addStride(op2, stride); 6972623SN/A } 6985315Sstever@gmail.com } 6995315Sstever@gmail.com 7005315Sstever@gmail.com void 7015315Sstever@gmail.com nextIdxs(IntRegIndex &dest, IntRegIndex &op1) 7025315Sstever@gmail.com { 7035315Sstever@gmail.com unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 7045315Sstever@gmail.com assert(!inScalarBank(dest)); 7052623SN/A dest = addStride(dest, stride); 7062623SN/A if (!inScalarBank(op1)) { 7072623SN/A op1 = addStride(op1, stride); 7082623SN/A } 7094762Snate@binkert.org } 7104762Snate@binkert.org 7112623SN/A void 7125529Snate@binkert.org nextIdxs(IntRegIndex &dest) 7135529Snate@binkert.org { 7144762Snate@binkert.org unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 7154762Snate@binkert.org assert(!inScalarBank(dest)); 7162623SN/A dest = addStride(dest, stride); 7175529Snate@binkert.org } 7182623SN/A}; 719 720static inline float 721fpAddS(float a, float b) 722{ 723 return a + b; 724} 725 726static inline double 727fpAddD(double a, double b) 728{ 729 return a + b; 730} 731 732static inline float 733fpSubS(float a, float b) 734{ 735 return a - b; 736} 737 738static inline double 739fpSubD(double a, double b) 740{ 741 return a - b; 742} 743 744static inline float 745fpDivS(float a, float b) 746{ 747 return a / b; 748} 749 750static inline double 751fpDivD(double a, double b) 752{ 753 return a / b; 754} 755 756static inline float 757fpMulS(float a, float b) 758{ 759 return a * b; 760} 761 762static inline double 763fpMulD(double a, double b) 764{ 765 return a * b; 766} 767 768class FpOp : public PredOp 769{ 770 protected: 771 FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 772 PredOp(mnem, _machInst, __opClass) 773 {} 774 775 virtual float 776 doOp(float op1, float op2) const 777 { 778 panic("Unimplemented version of doOp called.\n"); 779 } 780 781 virtual float 782 doOp(float op1) const 783 { 784 panic("Unimplemented version of doOp called.\n"); 785 } 786 787 virtual double 788 doOp(double op1, double op2) const 789 { 790 panic("Unimplemented version of doOp called.\n"); 791 } 792 793 virtual double 794 doOp(double op1) const 795 { 796 panic("Unimplemented version of doOp called.\n"); 797 } 798 799 double 800 dbl(uint32_t low, uint32_t high) const 801 { 802 double junk = 0.0; 803 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 804 } 805 806 uint32_t 807 dblLow(double val) const 808 { 809 return fpToBits(val); 810 } 811 812 uint32_t 813 dblHi(double val) const 814 { 815 return fpToBits(val) >> 32; 816 } 817 818 template <class fpType> 819 fpType 820 binaryOp(FPSCR &fpscr, fpType op1, fpType op2, 821 fpType (*func)(fpType, fpType), 822 bool flush, uint32_t rMode) const 823 { 824 const bool single = (sizeof(fpType) == sizeof(float)); 825 fpType junk = 0.0; 826 827 if (flush && flushToZero(op1, op2)) 828 fpscr.idc = 1; 829 VfpSavedState state = prepFpState(rMode); 830 __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2), "=m" (state) 831 : "m" (op1), "m" (op2), "m" (state)); 832 fpType dest = func(op1, op2); 833 __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest)); 834 835 int fpClass = std::fpclassify(dest); 836 // Get NAN behavior right. This varies between x86 and ARM. 837 if (fpClass == FP_NAN) { 838 const bool single = (sizeof(fpType) == sizeof(float)); 839 const uint64_t qnan = 840 single ? 0x7fc00000 : ULL(0x7ff8000000000000); 841 const bool nan1 = std::isnan(op1); 842 const bool nan2 = std::isnan(op2); 843 const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 844 const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); 845 if ((!nan1 && !nan2) || (fpscr.dn == 1)) { 846 dest = bitsToFp(qnan, junk); 847 } else if (signal1) { 848 dest = bitsToFp(fpToBits(op1) | qnan, junk); 849 } else if (signal2) { 850 dest = bitsToFp(fpToBits(op2) | qnan, junk); 851 } else if (nan1) { 852 dest = op1; 853 } else if (nan2) { 854 dest = op2; 855 } 856 } else if (flush && flushToZero(dest)) { 857 feraiseexcept(FeUnderflow); 858 } else if (( 859 (single && (dest == bitsToFp(0x00800000, junk) || 860 dest == bitsToFp(0x80800000, junk))) || 861 (!single && 862 (dest == bitsToFp(ULL(0x0010000000000000), junk) || 863 dest == bitsToFp(ULL(0x8010000000000000), junk))) 864 ) && rMode != VfpRoundZero) { 865 /* 866 * Correct for the fact that underflow is detected -before- rounding 867 * in ARM and -after- rounding in x86. 868 */ 869 fesetround(FeRoundZero); 870 __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2) 871 : "m" (op1), "m" (op2)); 872 fpType temp = func(op1, op2); 873 __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