vfp.hh revision 7430
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 195typedef int VfpSavedState; 196 197VfpSavedState prepFpState(uint32_t rMode); 198void finishVfp(FPSCR &fpscr, VfpSavedState state); 199 200template <class fpType> 201fpType fixDest(FPSCR fpscr, fpType val, fpType op1); 202 203template <class fpType> 204fpType fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2); 205 206template <class fpType> 207fpType fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2); 208 209float fixFpDFpSDest(FPSCR fpscr, double val); 210double fixFpSFpDDest(FPSCR fpscr, float val); 211 212float vcvtFpSFpH(FPSCR &fpscr, float op, float dest, bool top); 213float vcvtFpHFpS(FPSCR &fpscr, float op, bool top); 214 215static inline double 216makeDouble(uint32_t low, uint32_t high) 217{ 218 double junk = 0.0; 219 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 220} 221 222static inline uint32_t 223lowFromDouble(double val) 224{ 225 return fpToBits(val); 226} 227 228static inline uint32_t 229highFromDouble(double val) 230{ 231 return fpToBits(val) >> 32; 232} 233 234uint64_t vfpFpSToFixed(float val, bool isSigned, bool half, 235 uint8_t imm, bool rzero = true); 236float vfpUFixedToFpS(FPSCR fpscr, uint32_t val, bool half, uint8_t imm); 237float vfpSFixedToFpS(FPSCR fpscr, int32_t val, bool half, uint8_t imm); 238 239uint64_t vfpFpDToFixed(double val, bool isSigned, bool half, 240 uint8_t imm, bool rzero = true); 241double vfpUFixedToFpD(FPSCR fpscr, uint32_t val, bool half, uint8_t imm); 242double vfpSFixedToFpD(FPSCR fpscr, int32_t val, bool half, uint8_t imm); 243 244class VfpMacroOp : public PredMacroOp 245{ 246 public: 247 static bool 248 inScalarBank(IntRegIndex idx) 249 { 250 return (idx % 32) < 8; 251 } 252 253 protected: 254 bool wide; 255 256 VfpMacroOp(const char *mnem, ExtMachInst _machInst, 257 OpClass __opClass, bool _wide) : 258 PredMacroOp(mnem, _machInst, __opClass), wide(_wide) 259 {} 260 261 IntRegIndex addStride(IntRegIndex idx, unsigned stride); 262 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2); 263 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1); 264 void nextIdxs(IntRegIndex &dest); 265}; 266 267static inline float 268fpAddS(float a, float b) 269{ 270 return a + b; 271} 272 273static inline double 274fpAddD(double a, double b) 275{ 276 return a + b; 277} 278 279static inline float 280fpSubS(float a, float b) 281{ 282 return a - b; 283} 284 285static inline double 286fpSubD(double a, double b) 287{ 288 return a - b; 289} 290 291static inline float 292fpDivS(float a, float b) 293{ 294 return a / b; 295} 296 297static inline double 298fpDivD(double a, double b) 299{ 300 return a / b; 301} 302 303static inline float 304fpMulS(float a, float b) 305{ 306 return a * b; 307} 308 309static inline double 310fpMulD(double a, double b) 311{ 312 return a * b; 313} 314 315class FpOp : public PredOp 316{ 317 protected: 318 FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : 319 PredOp(mnem, _machInst, __opClass) 320 {} 321 322 virtual float 323 doOp(float op1, float op2) const 324 { 325 panic("Unimplemented version of doOp called.\n"); 326 } 327 328 virtual float 329 doOp(float op1) const 330 { 331 panic("Unimplemented version of doOp called.\n"); 332 } 333 334 virtual double 335 doOp(double op1, double op2) const 336 { 337 panic("Unimplemented version of doOp called.\n"); 338 } 339 340 virtual double 341 doOp(double op1) const 342 { 343 panic("Unimplemented version of doOp called.\n"); 344 } 345 346 double 347 dbl(uint32_t low, uint32_t high) const 348 { 349 double junk = 0.0; 350 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk); 351 } 352 353 uint32_t 354 dblLow(double val) const 355 { 356 return fpToBits(val); 357 } 358 359 uint32_t 360 dblHi(double val) const 361 { 362 return fpToBits(val) >> 32; 363 } 364 365 template <class fpType> 366 fpType 367 binaryOp(FPSCR &fpscr, fpType op1, fpType op2, 368 fpType (*func)(fpType, fpType), 369 bool flush, uint32_t rMode) const; 370 371 template <class fpType> 372 fpType 373 unaryOp(FPSCR &fpscr, fpType op1, 374 fpType (*func)(fpType), 375 bool flush, uint32_t rMode) const; 376}; 377 378class FpRegRegOp : public FpOp 379{ 380 protected: 381 IntRegIndex dest; 382 IntRegIndex op1; 383 384 FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 385 IntRegIndex _dest, IntRegIndex _op1, 386 VfpMicroMode mode = VfpNotAMicroop) : 387 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1) 388 { 389 setVfpMicroFlags(mode, flags); 390 } 391 392 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 393}; 394 395class FpRegImmOp : public FpOp 396{ 397 protected: 398 IntRegIndex dest; 399 uint64_t imm; 400 401 FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 402 IntRegIndex _dest, uint64_t _imm, 403 VfpMicroMode mode = VfpNotAMicroop) : 404 FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm) 405 { 406 setVfpMicroFlags(mode, flags); 407 } 408 409 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 410}; 411 412class FpRegRegImmOp : public FpOp 413{ 414 protected: 415 IntRegIndex dest; 416 IntRegIndex op1; 417 uint64_t imm; 418 419 FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 420 IntRegIndex _dest, IntRegIndex _op1, 421 uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) : 422 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm) 423 { 424 setVfpMicroFlags(mode, flags); 425 } 426 427 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 428}; 429 430class FpRegRegRegOp : public FpOp 431{ 432 protected: 433 IntRegIndex dest; 434 IntRegIndex op1; 435 IntRegIndex op2; 436 437 FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, 438 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2, 439 VfpMicroMode mode = VfpNotAMicroop) : 440 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2) 441 { 442 setVfpMicroFlags(mode, flags); 443 } 444 445 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; 446}; 447 448} 449 450#endif //__ARCH_ARM_INSTS_VFP_HH__ 451