vfp.hh revision 7388
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 void 1103349Sbinkertn@umich.eduvfpFlushToZero(uint32_t &_fpscr, fpType &op) 1112623SN/A{ 1123310Srdreslin@umich.edu FPSCR fpscr = _fpscr; 1133649Srdreslin@umich.edu if (fpscr.fz == 1 && (std::fpclassify(op) == FP_SUBNORMAL)) { 1142623SN/A fpscr.idc = 1; 1152623SN/A op = 0; 1162623SN/A } 1173349Sbinkertn@umich.edu _fpscr = fpscr; 1182623SN/A} 1193184Srdreslin@umich.edu 1203184Srdreslin@umich.edutemplate <class fpType> 1212623SN/Astatic inline void 1222623SN/AvfpFlushToZero(uint32_t &fpscr, fpType &op1, fpType &op2) 1232623SN/A{ 1242623SN/A vfpFlushToZero(fpscr, op1); 1252623SN/A vfpFlushToZero(fpscr, op2); 1263647Srdreslin@umich.edu} 1273647Srdreslin@umich.edu 1283647Srdreslin@umich.edustatic inline uint32_t 1293647Srdreslin@umich.edufpToBits(float fp) 1303647Srdreslin@umich.edu{ 1312626SN/A union 1323647Srdreslin@umich.edu { 1332626SN/A float fp; 1342623SN/A uint32_t bits; 1352623SN/A } val; 1362623SN/A val.fp = fp; 1372657Ssaidi@eecs.umich.edu return val.bits; 1382623SN/A} 1392623SN/A 1402623SN/Astatic inline uint64_t 1412623SN/AfpToBits(double fp) 1422623SN/A{ 1434192Sktlim@umich.edu union 1444192Sktlim@umich.edu { 1454192Sktlim@umich.edu double fp; 1464192Sktlim@umich.edu uint64_t bits; 1474192Sktlim@umich.edu } val; 1484192Sktlim@umich.edu val.fp = fp; 1494192Sktlim@umich.edu return val.bits; 1504192Sktlim@umich.edu} 1515497Ssaidi@eecs.umich.edu 1524192Sktlim@umich.edustatic inline float 1534192Sktlim@umich.edubitsToFp(uint64_t bits, float junk) 1542623SN/A{ 1555529Snate@binkert.org union 1565487Snate@binkert.org { 1575487Snate@binkert.org float fp; 1585487Snate@binkert.org uint32_t bits; 1594968Sacolyte@umich.edu } val; 1604968Sacolyte@umich.edu val.bits = bits; 1612623SN/A return val.fp; 1622623SN/A} 1632623SN/A 1643647Srdreslin@umich.edustatic inline double 1653647Srdreslin@umich.edubitsToFp(uint64_t bits, double junk) 1663647Srdreslin@umich.edu{ 1672623SN/A union 1682623SN/A { 1692623SN/A double fp; 1702623SN/A uint64_t bits; 1712623SN/A } val; 1722623SN/A val.bits = bits; 1732623SN/A return val.fp; 1742623SN/A} 1752623SN/A 1762623SN/Atemplate <class fpType> 1772915Sktlim@umich.edustatic inline fpType 1782915Sktlim@umich.edufixDest(FPSCR fpscr, fpType val, fpType op1) 1793145Shsul@eecs.umich.edu{ 1802623SN/A int fpClass = std::fpclassify(val); 1812623SN/A fpType junk = 0.0; 1822623SN/A if (fpClass == FP_NAN) { 1832623SN/A const bool single = (sizeof(val) == sizeof(float)); 1842623SN/A const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 1852623SN/A const bool nan = std::isnan(op1); 1862623SN/A if (!nan || (fpscr.dn == 1)) { 1872915Sktlim@umich.edu val = bitsToFp(qnan, junk); 1882915Sktlim@umich.edu } else if (nan) { 1893145Shsul@eecs.umich.edu val = bitsToFp(fpToBits(op1) | qnan, junk); 1902915Sktlim@umich.edu } 1912915Sktlim@umich.edu } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) { 1922915Sktlim@umich.edu // Turn val into a zero with the correct sign; 1932915Sktlim@umich.edu uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 1942915Sktlim@umich.edu val = bitsToFp(fpToBits(val) & bitMask, junk); 1952915Sktlim@umich.edu feraiseexcept(FeUnderflow); 1965220Ssaidi@eecs.umich.edu } 1975220Ssaidi@eecs.umich.edu return val; 1985220Ssaidi@eecs.umich.edu} 1994940Snate@binkert.org 2005220Ssaidi@eecs.umich.edutemplate <class fpType> 2013324Shsul@eecs.umich.edustatic inline fpType 2025220Ssaidi@eecs.umich.edufixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2) 2035220Ssaidi@eecs.umich.edu{ 2045606Snate@binkert.org int fpClass = std::fpclassify(val); 2055606Snate@binkert.org fpType junk = 0.0; 2062915Sktlim@umich.edu if (fpClass == FP_NAN) { 2072623SN/A const bool single = (sizeof(val) == sizeof(float)); 2082623SN/A const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 2092623SN/A const bool nan1 = std::isnan(op1); 2102798Sktlim@umich.edu const bool nan2 = std::isnan(op2); 2112623SN/A const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 2125496Ssaidi@eecs.umich.edu const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); 2132798Sktlim@umich.edu if ((!nan1 && !nan2) || (fpscr.dn == 1)) { 2142623SN/A val = bitsToFp(qnan, junk); 2152798Sktlim@umich.edu } else if (signal1) { 2162623SN/A val = bitsToFp(fpToBits(op1) | qnan, junk); 2172623SN/A } else if (signal2) { 2182623SN/A val = bitsToFp(fpToBits(op2) | qnan, junk); 2192623SN/A } else if (nan1) { 2202623SN/A val = op1; 2212623SN/A } else if (nan2) { 2224192Sktlim@umich.edu val = op2; 2232623SN/A } 2242623SN/A } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) { 2252623SN/A // Turn val into a zero with the correct sign; 2262680Sktlim@umich.edu uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 2272623SN/A val = bitsToFp(fpToBits(val) & bitMask, junk); 2282680Sktlim@umich.edu feraiseexcept(FeUnderflow); 2292680Sktlim@umich.edu } 2302680Sktlim@umich.edu return val; 2312623SN/A} 2325606Snate@binkert.org 2332623SN/Atemplate <class fpType> 2342623SN/Astatic inline fpType 2352623SN/AfixMultDest(FPSCR fpscr, fpType val, fpType op1, fpType op2) 2363512Sktlim@umich.edu{ 2373512Sktlim@umich.edu fpType mid = fixDest(fpscr, val, op1, op2); 2383512Sktlim@umich.edu const bool single = (sizeof(fpType) == sizeof(float)); 2395169Ssaidi@eecs.umich.edu const fpType junk = 0.0; 2405712Shsul@eecs.umich.edu if ((single && (val == bitsToFp(0x00800000, junk) || 2415712Shsul@eecs.umich.edu val == bitsToFp(0x80800000, junk))) || 2425712Shsul@eecs.umich.edu (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) || 2432623SN/A val == bitsToFp(ULL(0x8010000000000000), junk))) 2442623SN/A ) { 2452623SN/A __asm__ __volatile__("" : "=m" (op1) : "m" (op1)); 2462623SN/A fesetround(FeRoundZero); 2472623SN/A fpType temp = 0.0; 2482623SN/A __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 2494940Snate@binkert.org temp = op1 * op2; 2504940Snate@binkert.org if (!std::isnormal(temp)) { 2512623SN/A feraiseexcept(FeUnderflow); 2522683Sktlim@umich.edu } 2532623SN/A __asm__ __volatile__("" :: "m" (temp)); 2542623SN/A } 2552623SN/A return mid; 2562623SN/A} 2572623SN/A 2585101Ssaidi@eecs.umich.edutemplate <class fpType> 2593686Sktlim@umich.edustatic inline fpType 2603430Sgblack@eecs.umich.edufixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2) 2615606Snate@binkert.org{ 2622623SN/A fpType mid = fixDest(fpscr, val, op1, op2); 2632623SN/A const bool single = (sizeof(fpType) == sizeof(float)); 2642623SN/A const fpType junk = 0.0; 2652623SN/A if ((single && (val == bitsToFp(0x00800000, junk) || 2662623SN/A val == bitsToFp(0x80800000, junk))) || 2672623SN/A (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) || 2682623SN/A val == bitsToFp(ULL(0x8010000000000000), junk))) 2694940Snate@binkert.org ) { 2704940Snate@binkert.org __asm__ __volatile__("" : "=m" (op1) : "m" (op1)); 2712623SN/A fesetround(FeRoundZero); 2722683Sktlim@umich.edu fpType temp = 0.0; 2732623SN/A __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 2742623SN/A temp = op1 / op2; 2752626SN/A if (!std::isnormal(temp)) { 2762626SN/A feraiseexcept(FeUnderflow); 2772626SN/A } 2782626SN/A __asm__ __volatile__("" :: "m" (temp)); 2795606Snate@binkert.org } 2802623SN/A return mid; 2812623SN/A} 2822623SN/A 2832623SN/Astatic inline float 2842623SN/AfixFpDFpSDest(FPSCR fpscr, double val) 2852623SN/A{ 2862623SN/A const float junk = 0.0; 2872623SN/A float op1 = 0.0; 2882623SN/A if (std::isnan(val)) { 2892623SN/A uint64_t valBits = fpToBits(val); 2903169Sstever@eecs.umich.edu uint32_t op1Bits = bits(valBits, 50, 29) | 2914870Sstever@eecs.umich.edu (mask(9) << 22) | 2922623SN/A (bits(valBits, 63) << 31); 2932623SN/A op1 = bitsToFp(op1Bits, junk); 2942623SN/A } 2952623SN/A float mid = fixDest(fpscr, (float)val, op1); 2962623SN/A if (mid == bitsToFp(0x00800000, junk) || 2974999Sgblack@eecs.umich.edu mid == bitsToFp(0x80800000, junk)) { 2984999Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 2994999Sgblack@eecs.umich.edu fesetround(FeRoundZero); 3004999Sgblack@eecs.umich.edu float temp = 0.0; 3012623SN/A __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 3024999Sgblack@eecs.umich.edu temp = val; 3032623SN/A if (!std::isnormal(temp)) { 3044999Sgblack@eecs.umich.edu feraiseexcept(FeUnderflow); 3054999Sgblack@eecs.umich.edu } 3064999Sgblack@eecs.umich.edu __asm__ __volatile__("" :: "m" (temp)); 3074999Sgblack@eecs.umich.edu } 3084999Sgblack@eecs.umich.edu return mid; 3094999Sgblack@eecs.umich.edu} 3104999Sgblack@eecs.umich.edu 3114999Sgblack@eecs.umich.edustatic inline uint64_t 3124999Sgblack@eecs.umich.eduvfpFpSToFixed(float val, bool isSigned, bool half, 3134999Sgblack@eecs.umich.edu uint8_t imm, bool rzero = true) 3144999Sgblack@eecs.umich.edu{ 3154999Sgblack@eecs.umich.edu int rmode = fegetround(); 3164999Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 3174999Sgblack@eecs.umich.edu val = val * powf(2.0, imm); 3184999Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 3194999Sgblack@eecs.umich.edu if (rzero) 3204999Sgblack@eecs.umich.edu fesetround(FeRoundZero); 3214999Sgblack@eecs.umich.edu else 3224999Sgblack@eecs.umich.edu fesetround(rmode); 3234999Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 3244999Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 3254999Sgblack@eecs.umich.edu float origVal = val; 3264999Sgblack@eecs.umich.edu val = rintf(val); 3274999Sgblack@eecs.umich.edu int fpType = std::fpclassify(val); 3284999Sgblack@eecs.umich.edu if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { 3294999Sgblack@eecs.umich.edu if (fpType == FP_NAN) { 3304999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 3314999Sgblack@eecs.umich.edu } 3324999Sgblack@eecs.umich.edu val = 0.0; 3334999Sgblack@eecs.umich.edu } else if (origVal != val) { 3344999Sgblack@eecs.umich.edu feraiseexcept(FeInexact); 3355012Sgblack@eecs.umich.edu } 3364999Sgblack@eecs.umich.edu 3374999Sgblack@eecs.umich.edu if (isSigned) { 3384999Sgblack@eecs.umich.edu if (half) { 3394999Sgblack@eecs.umich.edu if ((double)val < (int16_t)(1 << 15)) { 3404999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 3414968Sacolyte@umich.edu feclearexcept(FeInexact); 3424986Ssaidi@eecs.umich.edu return (int16_t)(1 << 15); 3434999Sgblack@eecs.umich.edu } 3444999Sgblack@eecs.umich.edu if ((double)val > (int16_t)mask(15)) { 3454999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 3464762Snate@binkert.org feclearexcept(FeInexact); 3474999Sgblack@eecs.umich.edu return (int16_t)mask(15); 3484999Sgblack@eecs.umich.edu } 3494999Sgblack@eecs.umich.edu return (int16_t)val; 3504999Sgblack@eecs.umich.edu } else { 3514999Sgblack@eecs.umich.edu if ((double)val < (int32_t)(1 << 31)) { 3524999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 3534999Sgblack@eecs.umich.edu feclearexcept(FeInexact); 3545408Sgblack@eecs.umich.edu return (int32_t)(1 << 31); 3555408Sgblack@eecs.umich.edu } 3565408Sgblack@eecs.umich.edu if ((double)val > (int32_t)mask(31)) { 3574999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 3584968Sacolyte@umich.edu feclearexcept(FeInexact); 3593170Sstever@eecs.umich.edu return (int32_t)mask(31); 3604999Sgblack@eecs.umich.edu } 3614999Sgblack@eecs.umich.edu return (int32_t)val; 3624999Sgblack@eecs.umich.edu } 3634999Sgblack@eecs.umich.edu } else { 3644999Sgblack@eecs.umich.edu if (half) { 3654999Sgblack@eecs.umich.edu if ((double)val < 0) { 3664999Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 3674999Sgblack@eecs.umich.edu feclearexcept(FeInexact); 3684999Sgblack@eecs.umich.edu return 0; 3694999Sgblack@eecs.umich.edu } 3702623SN/A if ((double)val > (mask(16))) { 3712623SN/A feraiseexcept(FeInvalid); 3722623SN/A feclearexcept(FeInexact); 3735177Sgblack@eecs.umich.edu return mask(16); 3745177Sgblack@eecs.umich.edu } 3755177Sgblack@eecs.umich.edu return (uint16_t)val; 3765177Sgblack@eecs.umich.edu } else { 3775177Sgblack@eecs.umich.edu if ((double)val < 0) { 3785177Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 3795177Sgblack@eecs.umich.edu feclearexcept(FeInexact); 3805177Sgblack@eecs.umich.edu return 0; 3815177Sgblack@eecs.umich.edu } 3825177Sgblack@eecs.umich.edu if ((double)val > (mask(32))) { 3835177Sgblack@eecs.umich.edu feraiseexcept(FeInvalid); 3845177Sgblack@eecs.umich.edu feclearexcept(FeInexact); 3855177Sgblack@eecs.umich.edu return mask(32); 3865177Sgblack@eecs.umich.edu } 3875177Sgblack@eecs.umich.edu return (uint32_t)val; 3885177Sgblack@eecs.umich.edu } 3895177Sgblack@eecs.umich.edu } 3905177Sgblack@eecs.umich.edu} 3915177Sgblack@eecs.umich.edu 3925177Sgblack@eecs.umich.edustatic inline float 3935177Sgblack@eecs.umich.eduvfpUFixedToFpS(FPSCR fpscr, uint32_t val, bool half, uint8_t imm) 3945177Sgblack@eecs.umich.edu{ 3955177Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 3965177Sgblack@eecs.umich.edu if (half) 3975177Sgblack@eecs.umich.edu val = (uint16_t)val; 3985177Sgblack@eecs.umich.edu float scale = powf(2.0, imm); 3995177Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 4005177Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 4015177Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 4025177Sgblack@eecs.umich.edu return fixDivDest(fpscr, val / scale, (float)val, scale); 4035177Sgblack@eecs.umich.edu} 4045177Sgblack@eecs.umich.edu 4055177Sgblack@eecs.umich.edustatic inline float 4065177Sgblack@eecs.umich.eduvfpSFixedToFpS(FPSCR fpscr, int32_t val, bool half, uint8_t imm) 4075177Sgblack@eecs.umich.edu{ 4085177Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 4095177Sgblack@eecs.umich.edu if (half) 4105177Sgblack@eecs.umich.edu val = sext<16>(val & mask(16)); 4115177Sgblack@eecs.umich.edu float scale = powf(2.0, imm); 4125177Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 4135177Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 4145177Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 4155177Sgblack@eecs.umich.edu return fixDivDest(fpscr, val / scale, (float)val, scale); 4165177Sgblack@eecs.umich.edu} 4175177Sgblack@eecs.umich.edu 4185177Sgblack@eecs.umich.edustatic inline uint64_t 4195177Sgblack@eecs.umich.eduvfpFpDToFixed(double val, bool isSigned, bool half, 4205177Sgblack@eecs.umich.edu uint8_t imm, bool rzero = true) 4215177Sgblack@eecs.umich.edu{ 4225177Sgblack@eecs.umich.edu int rmode = fegetround(); 4235177Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 4245177Sgblack@eecs.umich.edu val = val * pow(2.0, imm); 4255177Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (val) : "m" (val)); 4265177Sgblack@eecs.umich.edu if (rzero) 4275177Sgblack@eecs.umich.edu fesetround(FeRoundZero); 4282623SN/A else 4292623SN/A fesetround(rmode); 4302623SN/A feclearexcept(FeAllExceptions); 4312623SN/A __asm__ __volatile__("" : "=m" (val) : "m" (val)); 4324115Ssaidi@eecs.umich.edu double origVal = val; 4334115Ssaidi@eecs.umich.edu val = rint(val); 4344115Ssaidi@eecs.umich.edu int fpType = std::fpclassify(val); 4354115Ssaidi@eecs.umich.edu if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { 4364040Ssaidi@eecs.umich.edu if (fpType == FP_NAN) { 4374040Ssaidi@eecs.umich.edu feraiseexcept(FeInvalid); 4384040Ssaidi@eecs.umich.edu } 4394040Ssaidi@eecs.umich.edu val = 0.0; 4402623SN/A } else if (origVal != val) { 4412623SN/A feraiseexcept(FeInexact); 4422623SN/A } 4432623SN/A if (isSigned) { 4442623SN/A if (half) { 4452623SN/A if (val < (int16_t)(1 << 15)) { 4462623SN/A feraiseexcept(FeInvalid); 4472623SN/A feclearexcept(FeInexact); 4482623SN/A return (int16_t)(1 << 15); 4492623SN/A } 4502623SN/A if (val > (int16_t)mask(15)) { 4512623SN/A feraiseexcept(FeInvalid); 4522623SN/A feclearexcept(FeInexact); 4532623SN/A return (int16_t)mask(15); 4542623SN/A } 4552623SN/A return (int16_t)val; 4562623SN/A } else { 4572623SN/A if (val < (int32_t)(1 << 31)) { 4582623SN/A feraiseexcept(FeInvalid); 4592623SN/A feclearexcept(FeInexact); 4602623SN/A return (int32_t)(1 << 31); 4612623SN/A } 4622623SN/A if (val > (int32_t)mask(31)) { 4632623SN/A feraiseexcept(FeInvalid); 4642623SN/A feclearexcept(FeInexact); 4652623SN/A return (int32_t)mask(31); 4662623SN/A } 4672623SN/A return (int32_t)val; 4682623SN/A } 4692623SN/A } else { 4702623SN/A if (half) { 4712623SN/A if (val < 0) { 4722623SN/A feraiseexcept(FeInvalid); 4732623SN/A feclearexcept(FeInexact); 4742623SN/A return 0; 4752623SN/A } 4762623SN/A if (val > mask(16)) { 4772623SN/A feraiseexcept(FeInvalid); 4782623SN/A feclearexcept(FeInexact); 4792623SN/A return mask(16); 4802623SN/A } 4812623SN/A return (uint16_t)val; 4822623SN/A } else { 4833169Sstever@eecs.umich.edu if (val < 0) { 4844870Sstever@eecs.umich.edu feraiseexcept(FeInvalid); 4852623SN/A feclearexcept(FeInexact); 4862623SN/A return 0; 4872623SN/A } 4882623SN/A if (val > mask(32)) { 4892623SN/A feraiseexcept(FeInvalid); 4904999Sgblack@eecs.umich.edu feclearexcept(FeInexact); 4914999Sgblack@eecs.umich.edu return mask(32); 4924999Sgblack@eecs.umich.edu } 4934999Sgblack@eecs.umich.edu return (uint32_t)val; 4942623SN/A } 4954999Sgblack@eecs.umich.edu } 4962623SN/A} 4974999Sgblack@eecs.umich.edu 4984999Sgblack@eecs.umich.edustatic inline double 4994999Sgblack@eecs.umich.eduvfpUFixedToFpD(FPSCR fpscr, uint32_t val, bool half, uint8_t imm) 5004999Sgblack@eecs.umich.edu{ 5014999Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 5024999Sgblack@eecs.umich.edu if (half) 5034999Sgblack@eecs.umich.edu val = (uint16_t)val; 5044999Sgblack@eecs.umich.edu double scale = pow(2.0, imm); 5054999Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 5064999Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 5074999Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 5084999Sgblack@eecs.umich.edu return fixDivDest(fpscr, val / scale, (double)val, scale); 5094999Sgblack@eecs.umich.edu} 5104999Sgblack@eecs.umich.edu 5114999Sgblack@eecs.umich.edustatic inline double 5124999Sgblack@eecs.umich.eduvfpSFixedToFpD(FPSCR fpscr, int32_t val, bool half, uint8_t imm) 5134999Sgblack@eecs.umich.edu{ 5144999Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 5154999Sgblack@eecs.umich.edu if (half) 5164999Sgblack@eecs.umich.edu val = sext<16>(val & mask(16)); 5174999Sgblack@eecs.umich.edu double scale = pow(2.0, imm); 5184999Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 5194999Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 5204999Sgblack@eecs.umich.edu __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 5214999Sgblack@eecs.umich.edu return fixDivDest(fpscr, val / scale, (double)val, scale); 5224999Sgblack@eecs.umich.edu} 5234999Sgblack@eecs.umich.edu 5244999Sgblack@eecs.umich.edutypedef int VfpSavedState; 5254999Sgblack@eecs.umich.edu 5264999Sgblack@eecs.umich.edustatic inline VfpSavedState 5274999Sgblack@eecs.umich.eduprepVfpFpscr(FPSCR fpscr) 5284999Sgblack@eecs.umich.edu{ 5294999Sgblack@eecs.umich.edu int roundingMode = fegetround(); 5304999Sgblack@eecs.umich.edu feclearexcept(FeAllExceptions); 5314999Sgblack@eecs.umich.edu switch (fpscr.rMode) { 5324999Sgblack@eecs.umich.edu case VfpRoundNearest: 5334999Sgblack@eecs.umich.edu fesetround(FeRoundNearest); 5344999Sgblack@eecs.umich.edu break; 5354999Sgblack@eecs.umich.edu case VfpRoundUpward: 5364999Sgblack@eecs.umich.edu fesetround(FeRoundUpward); 5374999Sgblack@eecs.umich.edu break; 5384999Sgblack@eecs.umich.edu case VfpRoundDown: 5394999Sgblack@eecs.umich.edu fesetround(FeRoundDown); 5404999Sgblack@eecs.umich.edu break; 5414999Sgblack@eecs.umich.edu case VfpRoundZero: 5424999Sgblack@eecs.umich.edu fesetround(FeRoundZero); 5434999Sgblack@eecs.umich.edu break; 5444999Sgblack@eecs.umich.edu } 5454999Sgblack@eecs.umich.edu return roundingMode; 5464999Sgblack@eecs.umich.edu} 5474999Sgblack@eecs.umich.edu 5484999Sgblack@eecs.umich.edustatic inline FPSCR 5494999Sgblack@eecs.umich.edusetVfpFpscr(FPSCR fpscr, VfpSavedState state) 5504999Sgblack@eecs.umich.edu{ 5514999Sgblack@eecs.umich.edu int exceptions = fetestexcept(FeAllExceptions); 5524999Sgblack@eecs.umich.edu if (exceptions & FeInvalid) { 5534999Sgblack@eecs.umich.edu fpscr.ioc = 1; 5544999Sgblack@eecs.umich.edu } 5554999Sgblack@eecs.umich.edu if (exceptions & FeDivByZero) { 5564878Sstever@eecs.umich.edu fpscr.dzc = 1; 5574040Ssaidi@eecs.umich.edu } 5584040Ssaidi@eecs.umich.edu if (exceptions & FeOverflow) { 5594999Sgblack@eecs.umich.edu fpscr.ofc = 1; 5604999Sgblack@eecs.umich.edu } 5614999Sgblack@eecs.umich.edu if (exceptions & FeUnderflow) { 5622631SN/A fpscr.ufc = 1; 5634999Sgblack@eecs.umich.edu } 5644999Sgblack@eecs.umich.edu if (exceptions & FeInexact) { 5654999Sgblack@eecs.umich.edu fpscr.ixc = 1; 5664999Sgblack@eecs.umich.edu } 5674999Sgblack@eecs.umich.edu fesetround(state); 5684999Sgblack@eecs.umich.edu return fpscr; 5694999Sgblack@eecs.umich.edu} 5705408Sgblack@eecs.umich.edu 5715408Sgblack@eecs.umich.educlass VfpMacroOp : public PredMacroOp 5725408Sgblack@eecs.umich.edu{ 5734999Sgblack@eecs.umich.edu public: 5743170Sstever@eecs.umich.edu static bool 5753170Sstever@eecs.umich.edu inScalarBank(IntRegIndex idx) 5764999Sgblack@eecs.umich.edu { 5774999Sgblack@eecs.umich.edu return (idx % 32) < 8; 5784999Sgblack@eecs.umich.edu } 5794999Sgblack@eecs.umich.edu 5804999Sgblack@eecs.umich.edu protected: 5814999Sgblack@eecs.umich.edu bool wide; 5824999Sgblack@eecs.umich.edu 5834999Sgblack@eecs.umich.edu VfpMacroOp(const char *mnem, ExtMachInst _machInst, 5844999Sgblack@eecs.umich.edu OpClass __opClass, bool _wide) : 5854999Sgblack@eecs.umich.edu PredMacroOp(mnem, _machInst, __opClass), wide(_wide) 5862623SN/A {} 5872623SN/A 5882623SN/A IntRegIndex 5895177Sgblack@eecs.umich.edu addStride(IntRegIndex idx, unsigned stride) 5905177Sgblack@eecs.umich.edu { 5915177Sgblack@eecs.umich.edu if (wide) { 5925177Sgblack@eecs.umich.edu stride *= 2; 5935177Sgblack@eecs.umich.edu } 5945177Sgblack@eecs.umich.edu unsigned offset = idx % 8; 5955177Sgblack@eecs.umich.edu idx = (IntRegIndex)(idx - offset); 5965177Sgblack@eecs.umich.edu offset += stride; 5975177Sgblack@eecs.umich.edu idx = (IntRegIndex)(idx + (offset % 8)); 5985177Sgblack@eecs.umich.edu return idx; 5995177Sgblack@eecs.umich.edu } 6005177Sgblack@eecs.umich.edu 6015177Sgblack@eecs.umich.edu void 6025177Sgblack@eecs.umich.edu nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2) 6035177Sgblack@eecs.umich.edu { 6045177Sgblack@eecs.umich.edu unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 6055177Sgblack@eecs.umich.edu assert(!inScalarBank(dest)); 6065177Sgblack@eecs.umich.edu dest = addStride(dest, stride); 6075177Sgblack@eecs.umich.edu op1 = addStride(op1, stride); 6085177Sgblack@eecs.umich.edu if (!inScalarBank(op2)) { 6095177Sgblack@eecs.umich.edu op2 = addStride(op2, stride); 6105177Sgblack@eecs.umich.edu } 6115177Sgblack@eecs.umich.edu } 6125177Sgblack@eecs.umich.edu 6135177Sgblack@eecs.umich.edu void 6145177Sgblack@eecs.umich.edu nextIdxs(IntRegIndex &dest, IntRegIndex &op1) 6155177Sgblack@eecs.umich.edu { 6165177Sgblack@eecs.umich.edu unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 6175177Sgblack@eecs.umich.edu assert(!inScalarBank(dest)); 6185278Sgblack@eecs.umich.edu dest = addStride(dest, stride); 6195177Sgblack@eecs.umich.edu if (!inScalarBank(op1)) { 6205177Sgblack@eecs.umich.edu op1 = addStride(op1, stride); 6215177Sgblack@eecs.umich.edu } 6225177Sgblack@eecs.umich.edu } 6235177Sgblack@eecs.umich.edu 6245177Sgblack@eecs.umich.edu void 6255177Sgblack@eecs.umich.edu nextIdxs(IntRegIndex &dest) 6265177Sgblack@eecs.umich.edu { 6275177Sgblack@eecs.umich.edu unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 6285177Sgblack@eecs.umich.edu assert(!inScalarBank(dest)); 6295177Sgblack@eecs.umich.edu dest = addStride(dest, stride); 6305177Sgblack@eecs.umich.edu } 6315177Sgblack@eecs.umich.edu}; 6325177Sgblack@eecs.umich.edu 6335177Sgblack@eecs.umich.educlass VfpRegRegOp : public RegRegOp 6345177Sgblack@eecs.umich.edu{ 6355177Sgblack@eecs.umich.edu protected: 6365177Sgblack@eecs.umich.edu VfpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 6375177Sgblack@eecs.umich.edu IntRegIndex _dest, IntRegIndex _op1, 6385177Sgblack@eecs.umich.edu VfpMicroMode mode = VfpNotAMicroop) : 6395177Sgblack@eecs.umich.edu RegRegOp(mnem, _machInst, __opClass, _dest, _op1) 6405177Sgblack@eecs.umich.edu { 6415177Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 6425177Sgblack@eecs.umich.edu } 6435177Sgblack@eecs.umich.edu}; 6445177Sgblack@eecs.umich.edu 6455177Sgblack@eecs.umich.educlass VfpRegImmOp : public RegImmOp 6465177Sgblack@eecs.umich.edu{ 6472623SN/A protected: 6482623SN/A VfpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 6494224Sgblack@eecs.umich.edu IntRegIndex _dest, uint64_t _imm, 6504224Sgblack@eecs.umich.edu VfpMicroMode mode = VfpNotAMicroop) : 6514224Sgblack@eecs.umich.edu RegImmOp(mnem, _machInst, __opClass, _dest, _imm) 6524224Sgblack@eecs.umich.edu { 6534224Sgblack@eecs.umich.edu setVfpMicroFlags(mode, flags); 6544224Sgblack@eecs.umich.edu } 6554224Sgblack@eecs.umich.edu}; 6564224Sgblack@eecs.umich.edu 6574224Sgblack@eecs.umich.educlass VfpRegRegImmOp : public RegRegImmOp 6584224Sgblack@eecs.umich.edu{ 6594224Sgblack@eecs.umich.edu protected: 6602623SN/A VfpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 6612623SN/A IntRegIndex _dest, IntRegIndex _op1, 6622623SN/A uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : 6632623SN/A RegRegImmOp(mnem, _machInst, __opClass, _dest, _op1, _imm) 6642623SN/A { 6652623SN/A setVfpMicroFlags(mode, flags); 6662623SN/A } 6672623SN/A}; 6682623SN/A 6692623SN/Aclass VfpRegRegRegOp : public RegRegRegOp 6702623SN/A{ 6712623SN/A protected: 6722623SN/A VfpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 6732623SN/A IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, 6742623SN/A VfpMicroMode mode = VfpNotAMicroop) : 6752623SN/A RegRegRegOp(mnem, _machInst, __opClass, _dest, _op1, _op2) 6762623SN/A { 6772623SN/A setVfpMicroFlags(mode, flags); 6782623SN/A } 6792623SN/A}; 6802623SN/A 6812623SN/A} 6822623SN/A 6832623SN/A#endif //__ARCH_ARM_INSTS_VFP_HH__ 6842623SN/A