2 * Copyright (c) 2010 ARM Limited
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.
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.
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.
40 #ifndef __ARCH_ARM_INSTS_VFP_HH__
41 #define __ARCH_ARM_INSTS_VFP_HH__
47 #include "arch/arm/insts/misc.hh"
48 #include "arch/arm/miscregs.hh"
62 setVfpMicroFlags(VfpMicroMode mode, T &flags)
66 flags[StaticInst::IsMicroop] = true;
69 flags[StaticInst::IsMicroop] =
70 flags[StaticInst::IsFirstMicroop] = true;
73 flags[StaticInst::IsMicroop] =
74 flags[StaticInst::IsLastMicroop] = true;
79 if (mode == VfpMicroop || mode == VfpFirstMicroop) {
80 flags[StaticInst::IsDelayedCommit] = true;
86 FeDivByZero = FE_DIVBYZERO,
87 FeInexact = FE_INEXACT,
88 FeInvalid = FE_INVALID,
89 FeOverflow = FE_OVERFLOW,
90 FeUnderflow = FE_UNDERFLOW,
91 FeAllExceptions = FE_ALL_EXCEPT
96 FeRoundDown = FE_DOWNWARD,
97 FeRoundNearest = FE_TONEAREST,
98 FeRoundZero = FE_TOWARDZERO,
99 FeRoundUpward = FE_UPWARD
110 static inline float bitsToFp(uint64_t, float);
111 static inline double bitsToFp(uint64_t, double);
112 static inline uint32_t fpToBits(float);
113 static inline uint64_t fpToBits(double);
115 template <class fpType>
117 flushToZero(fpType &op)
120 if (std::fpclassify(op) == FP_SUBNORMAL) {
121 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
122 op = bitsToFp(fpToBits(op) & bitMask, junk);
128 template <class fpType>
130 flushToZero(fpType &op1, fpType &op2)
132 bool flush1 = flushToZero(op1);
133 bool flush2 = flushToZero(op2);
134 return flush1 || flush2;
137 template <class fpType>
139 vfpFlushToZero(FPSCR &fpscr, fpType &op)
141 if (fpscr.fz == 1 && flushToZero(op)) {
146 template <class fpType>
148 vfpFlushToZero(FPSCR &fpscr, fpType &op1, fpType &op2)
150 vfpFlushToZero(fpscr, op1);
151 vfpFlushToZero(fpscr, op2);
154 static inline uint32_t
166 static inline uint64_t
179 bitsToFp(uint64_t bits, float junk)
191 bitsToFp(uint64_t bits, double junk)
202 template <class fpType>
206 const bool single = (sizeof(fpType) == sizeof(float));
207 const uint64_t qnan =
208 single ? 0x7fc00000 : ULL(0x7ff8000000000000);
209 return std::isnan(val) && ((fpToBits(val) & qnan) != qnan);
212 typedef int VfpSavedState;
214 VfpSavedState prepFpState(uint32_t rMode);
215 void finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush);
217 template <class fpType>
218 fpType fixDest(FPSCR fpscr, fpType val, fpType op1);
220 template <class fpType>
221 fpType fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2);
223 template <class fpType>
224 fpType fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2);
226 float fixFpDFpSDest(FPSCR fpscr, double val);
227 double fixFpSFpDDest(FPSCR fpscr, float val);
229 uint16_t vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan,
230 uint32_t rMode, bool ahp, float op);
231 float vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op);
234 makeDouble(uint32_t low, uint32_t high)
237 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
240 static inline uint32_t
241 lowFromDouble(double val)
243 return fpToBits(val);
246 static inline uint32_t
247 highFromDouble(double val)
249 return fpToBits(val) >> 32;
252 uint64_t vfpFpSToFixed(float val, bool isSigned, bool half,
253 uint8_t imm, bool rzero = true);
254 float vfpUFixedToFpS(bool flush, bool defaultNan,
255 uint32_t val, bool half, uint8_t imm);
256 float vfpSFixedToFpS(bool flush, bool defaultNan,
257 int32_t val, bool half, uint8_t imm);
259 uint64_t vfpFpDToFixed(double val, bool isSigned, bool half,
260 uint8_t imm, bool rzero = true);
261 double vfpUFixedToFpD(bool flush, bool defaultNan,
262 uint32_t val, bool half, uint8_t imm);
263 double vfpSFixedToFpD(bool flush, bool defaultNan,
264 int32_t val, bool half, uint8_t imm);
266 float fprSqrtEstimate(FPSCR &fpscr, float op);
267 uint32_t unsignedRSqrtEstimate(uint32_t op);
269 float fpRecipEstimate(FPSCR &fpscr, float op);
270 uint32_t unsignedRecipEstimate(uint32_t op);
272 class VfpMacroOp : public PredMacroOp
276 inScalarBank(IntRegIndex idx)
278 return (idx % 32) < 8;
284 VfpMacroOp(const char *mnem, ExtMachInst _machInst,
285 OpClass __opClass, bool _wide) :
286 PredMacroOp(mnem, _machInst, __opClass), wide(_wide)
289 IntRegIndex addStride(IntRegIndex idx, unsigned stride);
290 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2);
291 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1);
292 void nextIdxs(IntRegIndex &dest);
296 fpAddS(float a, float b)
302 fpAddD(double a, double b)
308 fpSubS(float a, float b)
314 fpSubD(double a, double b)
320 fpDivS(float a, float b)
326 fpDivD(double a, double b)
332 fpMulS(float a, float b)
338 fpMulD(double a, double b)
344 fpMaxS(float a, float b)
346 // Handle comparisons of +0 and -0.
347 if (!std::signbit(a) && std::signbit(b))
353 fpMinS(float a, float b)
355 // Handle comparisons of +0 and -0.
356 if (std::signbit(a) && !std::signbit(b))
362 fpRSqrtsS(float a, float b)
364 int fpClassA = std::fpclassify(a);
365 int fpClassB = std::fpclassify(b);
369 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
370 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
374 fpClassAxB = std::fpclassify(aXb);
375 if(fpClassAxB == FP_SUBNORMAL) {
376 feraiseexcept(FeUnderflow);
379 return (3.0 - (a * b)) / 2.0;
383 fpRecpsS(float a, float b)
385 int fpClassA = std::fpclassify(a);
386 int fpClassB = std::fpclassify(b);
390 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
391 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
395 fpClassAxB = std::fpclassify(aXb);
396 if(fpClassAxB == FP_SUBNORMAL) {
397 feraiseexcept(FeUnderflow);
400 return 2.0 - (a * b);
403 class FpOp : public PredOp
406 FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
407 PredOp(mnem, _machInst, __opClass)
411 doOp(float op1, float op2) const
413 panic("Unimplemented version of doOp called.\n");
417 doOp(float op1) const
419 panic("Unimplemented version of doOp called.\n");
423 doOp(double op1, double op2) const
425 panic("Unimplemented version of doOp called.\n");
429 doOp(double op1) const
431 panic("Unimplemented version of doOp called.\n");
435 dbl(uint32_t low, uint32_t high) const
438 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
442 dblLow(double val) const
444 return fpToBits(val);
448 dblHi(double val) const
450 return fpToBits(val) >> 32;
453 template <class fpType>
455 processNans(FPSCR &fpscr, bool &done, bool defaultNan,
456 fpType op1, fpType op2) const;
458 template <class fpType>
460 binaryOp(FPSCR &fpscr, fpType op1, fpType op2,
461 fpType (*func)(fpType, fpType),
462 bool flush, bool defaultNan, uint32_t rMode) const;
464 template <class fpType>
466 unaryOp(FPSCR &fpscr, fpType op1,
467 fpType (*func)(fpType),
468 bool flush, uint32_t rMode) const;
471 advancePC(PCState &pcState) const
473 if (flags[IsLastMicroop]) {
475 } else if (flags[IsMicroop]) {
483 class FpRegRegOp : public FpOp
489 FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
490 IntRegIndex _dest, IntRegIndex _op1,
491 VfpMicroMode mode = VfpNotAMicroop) :
492 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1)
494 setVfpMicroFlags(mode, flags);
497 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
500 class FpRegImmOp : public FpOp
506 FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
507 IntRegIndex _dest, uint64_t _imm,
508 VfpMicroMode mode = VfpNotAMicroop) :
509 FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm)
511 setVfpMicroFlags(mode, flags);
514 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
517 class FpRegRegImmOp : public FpOp
524 FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
525 IntRegIndex _dest, IntRegIndex _op1,
526 uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) :
527 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm)
529 setVfpMicroFlags(mode, flags);
532 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
535 class FpRegRegRegOp : public FpOp
542 FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
543 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
544 VfpMicroMode mode = VfpNotAMicroop) :
545 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2)
547 setVfpMicroFlags(mode, flags);
550 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
553 class FpRegRegRegImmOp : public FpOp
561 FpRegRegRegImmOp(const char *mnem, ExtMachInst _machInst,
562 OpClass __opClass, IntRegIndex _dest,
563 IntRegIndex _op1, IntRegIndex _op2,
564 uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) :
565 FpOp(mnem, _machInst, __opClass),
566 dest(_dest), op1(_op1), op2(_op2), imm(_imm)
568 setVfpMicroFlags(mode, flags);
571 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
576 #endif //__ARCH_ARM_INSTS_VFP_HH__