1/* 2 * Copyright (c) 2010 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Gabe Black 38 */ 39 40#ifndef __ARCH_ARM_INSTS_VFP_HH__ 41#define __ARCH_ARM_INSTS_VFP_HH__ 42 43#include "arch/arm/insts/misc.hh" 44#include "arch/arm/miscregs.hh" 45#include <fenv.h> 46#include <cmath> 47 48namespace ArmISA 49{ 50 51enum VfpMicroMode { 52 VfpNotAMicroop, 53 VfpMicroop, 54 VfpFirstMicroop, 55 VfpLastMicroop 56}; 57 58template<class T> 59static inline void 60setVfpMicroFlags(VfpMicroMode mode, T &flags) 61{ 62 switch (mode) { 63 case VfpMicroop: 64 flags[StaticInst::IsMicroop] = true; 65 break; 66 case VfpFirstMicroop: 67 flags[StaticInst::IsMicroop] = 68 flags[StaticInst::IsFirstMicroop] = true; 69 break; 70 case VfpLastMicroop: 71 flags[StaticInst::IsMicroop] = 72 flags[StaticInst::IsLastMicroop] = true; 73 break; 74 case VfpNotAMicroop: 75 break; 76 } 77 if (mode == VfpMicroop || mode == VfpFirstMicroop) { 78 flags[StaticInst::IsDelayedCommit] = true; 79 } 80} 81 82enum FeExceptionBit 83{ 84 FeDivByZero = FE_DIVBYZERO, 85 FeInexact = FE_INEXACT, 86 FeInvalid = FE_INVALID, 87 FeOverflow = FE_OVERFLOW, 88 FeUnderflow = FE_UNDERFLOW, 89 FeAllExceptions = FE_ALL_EXCEPT 90}; 91 92enum FeRoundingMode 93{ 94 FeRoundDown = FE_DOWNWARD, 95 FeRoundNearest = FE_TONEAREST, 96 FeRoundZero = FE_TOWARDZERO, 97 FeRoundUpward = FE_UPWARD 98}; 99 100enum VfpRoundingMode 101{ 102 VfpRoundNearest = 0, 103 VfpRoundUpward = 1, 104 VfpRoundDown = 2, 105 VfpRoundZero = 3 106}; 107 108template <class fpType> 109static inline bool 110flushToZero(fpType &op) 111{ 112 fpType junk = 0.0; 113 if (std::fpclassify(op) == FP_SUBNORMAL) { 114 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 115 op = bitsToFp(fpToBits(op) & bitMask, junk); 116 return true; 117 } 118 return false; 119} 120 121template <class fpType> 122static inline bool 123flushToZero(fpType &op1, fpType &op2) 124{ 125 bool flush1 = flushToZero(op1); 126 bool flush2 = flushToZero(op2); 127 return flush1 || flush2; 128} 129 130template <class fpType> 131static inline void 132vfpFlushToZero(FPSCR &fpscr, fpType &op) 133{ 134 if (fpscr.fz == 1 && flushToZero(op)) { 135 fpscr.idc = 1; 136 } 137} 138 139template <class fpType> 140static inline void 141vfpFlushToZero(FPSCR &fpscr, fpType &op1, fpType &op2) 142{ 143 vfpFlushToZero(fpscr, op1); 144 vfpFlushToZero(fpscr, op2); 145} 146 147static inline uint32_t 148fpToBits(float fp) 149{ 150 union 151 { 152 float fp; 153 uint32_t bits; 154 } val; 155 val.fp = fp; 156 return val.bits; 157} 158 159static inline uint64_t 160fpToBits(double fp) 161{ 162 union 163 { 164 double fp; 165 uint64_t bits; 166 } val; 167 val.fp = fp; 168 return val.bits; 169} 170 171static inline float 172bitsToFp(uint64_t bits, float junk) 173{ 174 union 175 { 176 float fp; 177 uint32_t bits; 178 } val; 179 val.bits = bits; 180 return val.fp; 181} 182 183static inline double 184bitsToFp(uint64_t bits, double junk) 185{ 186 union 187 { 188 double fp; 189 uint64_t bits; 190 } val; 191 val.bits = bits; 192 return val.fp; 193} 194 195template <class fpType> 196static bool 197isSnan(fpType val) 198{ 199 const bool single = (sizeof(fpType) == sizeof(float)); 200 const uint64_t qnan = 201 single ? 0x7fc00000 : ULL(0x7ff8000000000000); 202 return std::isnan(val) && ((fpToBits(val) & qnan) != qnan); 203} 204 205typedef int VfpSavedState; 206 207VfpSavedState prepFpState(uint32_t rMode); 208void finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush); 209 210template <class fpType> 211fpType fixDest(FPSCR fpscr, fpType val, fpType op1); 212 213template <class fpType> 214fpType fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2); 215 216template <class fpType> 217fpType fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2); 218 219float fixFpDFpSDest(FPSCR fpscr, double val); 220double fixFpSFpDDest(FPSCR fpscr, float val); 221 222uint16_t vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan, 223 uint32_t rMode, bool ahp, float op); 224float vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op); 225 226static inline double 227makeDouble(uint32_t low, uint32_t high) 228{ 229 double junk = 0.0; 230 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 231} 232 233static inline uint32_t 234lowFromDouble(double val) 235{ 236 return fpToBits(val); 237} 238 239static inline uint32_t 240highFromDouble(double val) 241{ 242 return fpToBits(val) >> 32; 243} 244 245uint64_t vfpFpSToFixed(float val, bool isSigned, bool half, 246 uint8_t imm, bool rzero = true); 247float vfpUFixedToFpS(bool flush, bool defaultNan, 248 uint32_t val, bool half, uint8_t imm); 249float vfpSFixedToFpS(bool flush, bool defaultNan, 250 int32_t val, bool half, uint8_t imm); 251 252uint64_t vfpFpDToFixed(double val, bool isSigned, bool half, 253 uint8_t imm, bool rzero = true); 254double vfpUFixedToFpD(bool flush, bool defaultNan, 255 uint32_t val, bool half, uint8_t imm); 256double vfpSFixedToFpD(bool flush, bool defaultNan, 257 int32_t val, bool half, uint8_t imm); 258 259float fprSqrtEstimate(FPSCR &fpscr, float op); 260uint32_t unsignedRSqrtEstimate(uint32_t op); 261 262float fpRecipEstimate(FPSCR &fpscr, float op); 263uint32_t unsignedRecipEstimate(uint32_t op); 264 265class VfpMacroOp : public PredMacroOp 266{ 267 public: 268 static bool 269 inScalarBank(IntRegIndex idx) 270 { 271 return (idx % 32) < 8; 272 } 273 274 protected: 275 bool wide; 276 277 VfpMacroOp(const char *mnem, ExtMachInst _machInst, 278 OpClass __opClass, bool _wide) : 279 PredMacroOp(mnem, _machInst, __opClass), wide(_wide) 280 {} 281 282 IntRegIndex addStride(IntRegIndex idx, unsigned stride); 283 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2); 284 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1); 285 void nextIdxs(IntRegIndex &dest); 286}; 287 288static inline float 289fpAddS(float a, float b) 290{ 291 return a + b; 292} 293 294static inline double 295fpAddD(double a, double b) 296{ 297 return a + b; 298} 299 300static inline float 301fpSubS(float a, float b) 302{ 303 return a - b; 304} 305 306static inline double 307fpSubD(double a, double b) 308{ 309 return a - b; 310} 311 312static inline float 313fpDivS(float a, float b) 314{ 315 return a / b; 316} 317 318static inline double 319fpDivD(double a, double b) 320{ 321 return a / b; 322} 323 324static inline float 325fpMulS(float a, float b) 326{ 327 return a * b; 328} 329 330static inline double 331fpMulD(double a, double b) 332{ 333 return a * b; 334} 335 336static inline float 337fpMaxS(float a, float b) 338{ 339 // Handle comparisons of +0 and -0. 340 if (!std::signbit(a) && std::signbit(b)) 341 return a; 342 return fmaxf(a, b); 343} 344 345static inline float 346fpMinS(float a, float b) 347{ 348 // Handle comparisons of +0 and -0. 349 if (std::signbit(a) && !std::signbit(b)) 350 return a; 351 return fminf(a, b); 352} 353 354static inline float 355fpRSqrtsS(float a, float b) 356{ 357 int fpClassA = std::fpclassify(a); 358 int fpClassB = std::fpclassify(b); 359 float aXb; 360 int fpClassAxB; 361 362 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) || 363 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) { 364 return 1.5; 365 } 366 aXb = a*b; 367 fpClassAxB = std::fpclassify(aXb); 368 if(fpClassAxB == FP_SUBNORMAL) { 369 feraiseexcept(FeUnderflow); 370 return 1.5; 371 } 372 return (3.0 - (a * b)) / 2.0; 373} 374 375static inline float 376fpRecpsS(float a, float b) 377{ 378 int fpClassA = std::fpclassify(a); 379 int fpClassB = std::fpclassify(b); 380 float aXb; 381 int fpClassAxB; 382 383 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) || 384 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) { 385 return 2.0; 386 } 387 aXb = a*b; 388 fpClassAxB = std::fpclassify(aXb); 389 if(fpClassAxB == FP_SUBNORMAL) { 390 feraiseexcept(FeUnderflow); 391 return 2.0; 392 } 393 return 2.0 - (a * b); 394} 395 396class FpOp : public PredOp 397{ 398 protected: 399 FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 400 PredOp(mnem, _machInst, __opClass) 401 {} 402 403 virtual float 404 doOp(float op1, float op2) const 405 { 406 panic("Unimplemented version of doOp called.\n"); 407 } 408 409 virtual float 410 doOp(float op1) const 411 { 412 panic("Unimplemented version of doOp called.\n"); 413 } 414 415 virtual double 416 doOp(double op1, double op2) const 417 { 418 panic("Unimplemented version of doOp called.\n"); 419 } 420 421 virtual double 422 doOp(double op1) const 423 { 424 panic("Unimplemented version of doOp called.\n"); 425 } 426 427 double 428 dbl(uint32_t low, uint32_t high) const 429 { 430 double junk = 0.0; 431 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 432 } 433 434 uint32_t 435 dblLow(double val) const 436 { 437 return fpToBits(val); 438 } 439 440 uint32_t 441 dblHi(double val) const 442 { 443 return fpToBits(val) >> 32; 444 } 445 446 template <class fpType> 447 fpType 448 processNans(FPSCR &fpscr, bool &done, bool defaultNan, 449 fpType op1, fpType op2) const; 450 451 template <class fpType> 452 fpType 453 binaryOp(FPSCR &fpscr, fpType op1, fpType op2, 454 fpType (*func)(fpType, fpType), 455 bool flush, bool defaultNan, uint32_t rMode) const; 456 457 template <class fpType> 458 fpType 459 unaryOp(FPSCR &fpscr, fpType op1, 460 fpType (*func)(fpType), 461 bool flush, uint32_t rMode) const;
| 1/* 2 * Copyright (c) 2010 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Gabe Black 38 */ 39 40#ifndef __ARCH_ARM_INSTS_VFP_HH__ 41#define __ARCH_ARM_INSTS_VFP_HH__ 42 43#include "arch/arm/insts/misc.hh" 44#include "arch/arm/miscregs.hh" 45#include <fenv.h> 46#include <cmath> 47 48namespace ArmISA 49{ 50 51enum VfpMicroMode { 52 VfpNotAMicroop, 53 VfpMicroop, 54 VfpFirstMicroop, 55 VfpLastMicroop 56}; 57 58template<class T> 59static inline void 60setVfpMicroFlags(VfpMicroMode mode, T &flags) 61{ 62 switch (mode) { 63 case VfpMicroop: 64 flags[StaticInst::IsMicroop] = true; 65 break; 66 case VfpFirstMicroop: 67 flags[StaticInst::IsMicroop] = 68 flags[StaticInst::IsFirstMicroop] = true; 69 break; 70 case VfpLastMicroop: 71 flags[StaticInst::IsMicroop] = 72 flags[StaticInst::IsLastMicroop] = true; 73 break; 74 case VfpNotAMicroop: 75 break; 76 } 77 if (mode == VfpMicroop || mode == VfpFirstMicroop) { 78 flags[StaticInst::IsDelayedCommit] = true; 79 } 80} 81 82enum FeExceptionBit 83{ 84 FeDivByZero = FE_DIVBYZERO, 85 FeInexact = FE_INEXACT, 86 FeInvalid = FE_INVALID, 87 FeOverflow = FE_OVERFLOW, 88 FeUnderflow = FE_UNDERFLOW, 89 FeAllExceptions = FE_ALL_EXCEPT 90}; 91 92enum FeRoundingMode 93{ 94 FeRoundDown = FE_DOWNWARD, 95 FeRoundNearest = FE_TONEAREST, 96 FeRoundZero = FE_TOWARDZERO, 97 FeRoundUpward = FE_UPWARD 98}; 99 100enum VfpRoundingMode 101{ 102 VfpRoundNearest = 0, 103 VfpRoundUpward = 1, 104 VfpRoundDown = 2, 105 VfpRoundZero = 3 106}; 107 108template <class fpType> 109static inline bool 110flushToZero(fpType &op) 111{ 112 fpType junk = 0.0; 113 if (std::fpclassify(op) == FP_SUBNORMAL) { 114 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 115 op = bitsToFp(fpToBits(op) & bitMask, junk); 116 return true; 117 } 118 return false; 119} 120 121template <class fpType> 122static inline bool 123flushToZero(fpType &op1, fpType &op2) 124{ 125 bool flush1 = flushToZero(op1); 126 bool flush2 = flushToZero(op2); 127 return flush1 || flush2; 128} 129 130template <class fpType> 131static inline void 132vfpFlushToZero(FPSCR &fpscr, fpType &op) 133{ 134 if (fpscr.fz == 1 && flushToZero(op)) { 135 fpscr.idc = 1; 136 } 137} 138 139template <class fpType> 140static inline void 141vfpFlushToZero(FPSCR &fpscr, fpType &op1, fpType &op2) 142{ 143 vfpFlushToZero(fpscr, op1); 144 vfpFlushToZero(fpscr, op2); 145} 146 147static inline uint32_t 148fpToBits(float fp) 149{ 150 union 151 { 152 float fp; 153 uint32_t bits; 154 } val; 155 val.fp = fp; 156 return val.bits; 157} 158 159static inline uint64_t 160fpToBits(double fp) 161{ 162 union 163 { 164 double fp; 165 uint64_t bits; 166 } val; 167 val.fp = fp; 168 return val.bits; 169} 170 171static inline float 172bitsToFp(uint64_t bits, float junk) 173{ 174 union 175 { 176 float fp; 177 uint32_t bits; 178 } val; 179 val.bits = bits; 180 return val.fp; 181} 182 183static inline double 184bitsToFp(uint64_t bits, double junk) 185{ 186 union 187 { 188 double fp; 189 uint64_t bits; 190 } val; 191 val.bits = bits; 192 return val.fp; 193} 194 195template <class fpType> 196static bool 197isSnan(fpType val) 198{ 199 const bool single = (sizeof(fpType) == sizeof(float)); 200 const uint64_t qnan = 201 single ? 0x7fc00000 : ULL(0x7ff8000000000000); 202 return std::isnan(val) && ((fpToBits(val) & qnan) != qnan); 203} 204 205typedef int VfpSavedState; 206 207VfpSavedState prepFpState(uint32_t rMode); 208void finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush); 209 210template <class fpType> 211fpType fixDest(FPSCR fpscr, fpType val, fpType op1); 212 213template <class fpType> 214fpType fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2); 215 216template <class fpType> 217fpType fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2); 218 219float fixFpDFpSDest(FPSCR fpscr, double val); 220double fixFpSFpDDest(FPSCR fpscr, float val); 221 222uint16_t vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan, 223 uint32_t rMode, bool ahp, float op); 224float vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op); 225 226static inline double 227makeDouble(uint32_t low, uint32_t high) 228{ 229 double junk = 0.0; 230 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 231} 232 233static inline uint32_t 234lowFromDouble(double val) 235{ 236 return fpToBits(val); 237} 238 239static inline uint32_t 240highFromDouble(double val) 241{ 242 return fpToBits(val) >> 32; 243} 244 245uint64_t vfpFpSToFixed(float val, bool isSigned, bool half, 246 uint8_t imm, bool rzero = true); 247float vfpUFixedToFpS(bool flush, bool defaultNan, 248 uint32_t val, bool half, uint8_t imm); 249float vfpSFixedToFpS(bool flush, bool defaultNan, 250 int32_t val, bool half, uint8_t imm); 251 252uint64_t vfpFpDToFixed(double val, bool isSigned, bool half, 253 uint8_t imm, bool rzero = true); 254double vfpUFixedToFpD(bool flush, bool defaultNan, 255 uint32_t val, bool half, uint8_t imm); 256double vfpSFixedToFpD(bool flush, bool defaultNan, 257 int32_t val, bool half, uint8_t imm); 258 259float fprSqrtEstimate(FPSCR &fpscr, float op); 260uint32_t unsignedRSqrtEstimate(uint32_t op); 261 262float fpRecipEstimate(FPSCR &fpscr, float op); 263uint32_t unsignedRecipEstimate(uint32_t op); 264 265class VfpMacroOp : public PredMacroOp 266{ 267 public: 268 static bool 269 inScalarBank(IntRegIndex idx) 270 { 271 return (idx % 32) < 8; 272 } 273 274 protected: 275 bool wide; 276 277 VfpMacroOp(const char *mnem, ExtMachInst _machInst, 278 OpClass __opClass, bool _wide) : 279 PredMacroOp(mnem, _machInst, __opClass), wide(_wide) 280 {} 281 282 IntRegIndex addStride(IntRegIndex idx, unsigned stride); 283 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2); 284 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1); 285 void nextIdxs(IntRegIndex &dest); 286}; 287 288static inline float 289fpAddS(float a, float b) 290{ 291 return a + b; 292} 293 294static inline double 295fpAddD(double a, double b) 296{ 297 return a + b; 298} 299 300static inline float 301fpSubS(float a, float b) 302{ 303 return a - b; 304} 305 306static inline double 307fpSubD(double a, double b) 308{ 309 return a - b; 310} 311 312static inline float 313fpDivS(float a, float b) 314{ 315 return a / b; 316} 317 318static inline double 319fpDivD(double a, double b) 320{ 321 return a / b; 322} 323 324static inline float 325fpMulS(float a, float b) 326{ 327 return a * b; 328} 329 330static inline double 331fpMulD(double a, double b) 332{ 333 return a * b; 334} 335 336static inline float 337fpMaxS(float a, float b) 338{ 339 // Handle comparisons of +0 and -0. 340 if (!std::signbit(a) && std::signbit(b)) 341 return a; 342 return fmaxf(a, b); 343} 344 345static inline float 346fpMinS(float a, float b) 347{ 348 // Handle comparisons of +0 and -0. 349 if (std::signbit(a) && !std::signbit(b)) 350 return a; 351 return fminf(a, b); 352} 353 354static inline float 355fpRSqrtsS(float a, float b) 356{ 357 int fpClassA = std::fpclassify(a); 358 int fpClassB = std::fpclassify(b); 359 float aXb; 360 int fpClassAxB; 361 362 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) || 363 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) { 364 return 1.5; 365 } 366 aXb = a*b; 367 fpClassAxB = std::fpclassify(aXb); 368 if(fpClassAxB == FP_SUBNORMAL) { 369 feraiseexcept(FeUnderflow); 370 return 1.5; 371 } 372 return (3.0 - (a * b)) / 2.0; 373} 374 375static inline float 376fpRecpsS(float a, float b) 377{ 378 int fpClassA = std::fpclassify(a); 379 int fpClassB = std::fpclassify(b); 380 float aXb; 381 int fpClassAxB; 382 383 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) || 384 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) { 385 return 2.0; 386 } 387 aXb = a*b; 388 fpClassAxB = std::fpclassify(aXb); 389 if(fpClassAxB == FP_SUBNORMAL) { 390 feraiseexcept(FeUnderflow); 391 return 2.0; 392 } 393 return 2.0 - (a * b); 394} 395 396class FpOp : public PredOp 397{ 398 protected: 399 FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 400 PredOp(mnem, _machInst, __opClass) 401 {} 402 403 virtual float 404 doOp(float op1, float op2) const 405 { 406 panic("Unimplemented version of doOp called.\n"); 407 } 408 409 virtual float 410 doOp(float op1) const 411 { 412 panic("Unimplemented version of doOp called.\n"); 413 } 414 415 virtual double 416 doOp(double op1, double op2) const 417 { 418 panic("Unimplemented version of doOp called.\n"); 419 } 420 421 virtual double 422 doOp(double op1) const 423 { 424 panic("Unimplemented version of doOp called.\n"); 425 } 426 427 double 428 dbl(uint32_t low, uint32_t high) const 429 { 430 double junk = 0.0; 431 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 432 } 433 434 uint32_t 435 dblLow(double val) const 436 { 437 return fpToBits(val); 438 } 439 440 uint32_t 441 dblHi(double val) const 442 { 443 return fpToBits(val) >> 32; 444 } 445 446 template <class fpType> 447 fpType 448 processNans(FPSCR &fpscr, bool &done, bool defaultNan, 449 fpType op1, fpType op2) const; 450 451 template <class fpType> 452 fpType 453 binaryOp(FPSCR &fpscr, fpType op1, fpType op2, 454 fpType (*func)(fpType, fpType), 455 bool flush, bool defaultNan, uint32_t rMode) const; 456 457 template <class fpType> 458 fpType 459 unaryOp(FPSCR &fpscr, fpType op1, 460 fpType (*func)(fpType), 461 bool flush, uint32_t rMode) const;
|
462}; 463 464class FpRegRegOp : public FpOp 465{ 466 protected: 467 IntRegIndex dest; 468 IntRegIndex op1; 469 470 FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 471 IntRegIndex _dest, IntRegIndex _op1, 472 VfpMicroMode mode = VfpNotAMicroop) : 473 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1) 474 { 475 setVfpMicroFlags(mode, flags); 476 } 477 478 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 479}; 480 481class FpRegImmOp : public FpOp 482{ 483 protected: 484 IntRegIndex dest; 485 uint64_t imm; 486 487 FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 488 IntRegIndex _dest, uint64_t _imm, 489 VfpMicroMode mode = VfpNotAMicroop) : 490 FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm) 491 { 492 setVfpMicroFlags(mode, flags); 493 } 494 495 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 496}; 497 498class FpRegRegImmOp : public FpOp 499{ 500 protected: 501 IntRegIndex dest; 502 IntRegIndex op1; 503 uint64_t imm; 504 505 FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 506 IntRegIndex _dest, IntRegIndex _op1, 507 uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : 508 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm) 509 { 510 setVfpMicroFlags(mode, flags); 511 } 512 513 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 514}; 515 516class FpRegRegRegOp : public FpOp 517{ 518 protected: 519 IntRegIndex dest; 520 IntRegIndex op1; 521 IntRegIndex op2; 522 523 FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 524 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, 525 VfpMicroMode mode = VfpNotAMicroop) : 526 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2) 527 { 528 setVfpMicroFlags(mode, flags); 529 } 530 531 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 532}; 533 534class FpRegRegRegImmOp : public FpOp 535{ 536 protected: 537 IntRegIndex dest; 538 IntRegIndex op1; 539 IntRegIndex op2; 540 uint64_t imm; 541 542 FpRegRegRegImmOp(const char *mnem, ExtMachInst _machInst, 543 OpClass __opClass, IntRegIndex _dest, 544 IntRegIndex _op1, IntRegIndex _op2, 545 uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : 546 FpOp(mnem, _machInst, __opClass), 547 dest(_dest), op1(_op1), op2(_op2), imm(_imm) 548 { 549 setVfpMicroFlags(mode, flags); 550 } 551 552 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 553}; 554 555} 556 557#endif //__ARCH_ARM_INSTS_VFP_HH__
| 474}; 475 476class FpRegRegOp : public FpOp 477{ 478 protected: 479 IntRegIndex dest; 480 IntRegIndex op1; 481 482 FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 483 IntRegIndex _dest, IntRegIndex _op1, 484 VfpMicroMode mode = VfpNotAMicroop) : 485 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1) 486 { 487 setVfpMicroFlags(mode, flags); 488 } 489 490 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 491}; 492 493class FpRegImmOp : public FpOp 494{ 495 protected: 496 IntRegIndex dest; 497 uint64_t imm; 498 499 FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 500 IntRegIndex _dest, uint64_t _imm, 501 VfpMicroMode mode = VfpNotAMicroop) : 502 FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm) 503 { 504 setVfpMicroFlags(mode, flags); 505 } 506 507 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 508}; 509 510class FpRegRegImmOp : public FpOp 511{ 512 protected: 513 IntRegIndex dest; 514 IntRegIndex op1; 515 uint64_t imm; 516 517 FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 518 IntRegIndex _dest, IntRegIndex _op1, 519 uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : 520 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm) 521 { 522 setVfpMicroFlags(mode, flags); 523 } 524 525 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 526}; 527 528class FpRegRegRegOp : public FpOp 529{ 530 protected: 531 IntRegIndex dest; 532 IntRegIndex op1; 533 IntRegIndex op2; 534 535 FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 536 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, 537 VfpMicroMode mode = VfpNotAMicroop) : 538 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2) 539 { 540 setVfpMicroFlags(mode, flags); 541 } 542 543 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 544}; 545 546class FpRegRegRegImmOp : public FpOp 547{ 548 protected: 549 IntRegIndex dest; 550 IntRegIndex op1; 551 IntRegIndex op2; 552 uint64_t imm; 553 554 FpRegRegRegImmOp(const char *mnem, ExtMachInst _machInst, 555 OpClass __opClass, IntRegIndex _dest, 556 IntRegIndex _op1, IntRegIndex _op2, 557 uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : 558 FpOp(mnem, _machInst, __opClass), 559 dest(_dest), op1(_op1), op2(_op2), imm(_imm) 560 { 561 setVfpMicroFlags(mode, flags); 562 } 563 564 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 565}; 566 567} 568 569#endif //__ARCH_ARM_INSTS_VFP_HH__
|