gem5  v22.1.0.0
vfp.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2013, 2019 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 
38 #ifndef __ARCH_ARM_INSTS_VFP_HH__
39 #define __ARCH_ARM_INSTS_VFP_HH__
40 
41 #include <fenv.h>
42 
43 #include <cmath>
44 
45 #include "arch/arm/insts/misc.hh"
46 #include "arch/arm/pcstate.hh"
47 #include "arch/arm/regs/misc.hh"
48 #include "cpu/thread_context.hh"
49 
50 namespace gem5
51 {
52 
53 namespace ArmISA
54 {
55 
57 {
62 };
63 
64 template<class T>
65 static inline void
67 {
68  switch (mode) {
69  case VfpMicroop:
70  flags[StaticInst::IsMicroop] = true;
71  break;
72  case VfpFirstMicroop:
73  flags[StaticInst::IsMicroop] =
74  flags[StaticInst::IsFirstMicroop] = true;
75  break;
76  case VfpLastMicroop:
77  flags[StaticInst::IsMicroop] =
78  flags[StaticInst::IsLastMicroop] = true;
79  break;
80  case VfpNotAMicroop:
81  break;
82  }
83  if (mode == VfpMicroop || mode == VfpFirstMicroop) {
84  flags[StaticInst::IsDelayedCommit] = true;
85  }
86 }
87 
89 {
90  FeDivByZero = FE_DIVBYZERO,
91  FeInexact = FE_INEXACT,
92  FeInvalid = FE_INVALID,
93  FeOverflow = FE_OVERFLOW,
94  FeUnderflow = FE_UNDERFLOW,
95  FeAllExceptions = FE_ALL_EXCEPT
96 };
97 
99 {
100  FeRoundDown = FE_DOWNWARD,
101  FeRoundNearest = FE_TONEAREST,
102  FeRoundZero = FE_TOWARDZERO,
103  FeRoundUpward = FE_UPWARD
104 };
105 
107 {
112  VfpRoundAway = 4
113 };
114 
115 static inline float bitsToFp(uint64_t, float);
116 static inline double bitsToFp(uint64_t, double);
117 static inline uint32_t fpToBits(float);
118 static inline uint64_t fpToBits(double);
119 
120 template <class fpType>
121 static inline bool
122 flushToZero(fpType &op)
123 {
124  fpType junk = 0.0;
125  if (std::fpclassify(op) == FP_SUBNORMAL) {
126  uint64_t bitMask = 0x1ULL << (sizeof(fpType) * 8 - 1);
127  op = bitsToFp(fpToBits(op) & bitMask, junk);
128  return true;
129  }
130  return false;
131 }
132 
133 template <class fpType>
134 static inline bool
135 flushToZero(fpType &op1, fpType &op2)
136 {
137  bool flush1 = flushToZero(op1);
138  bool flush2 = flushToZero(op2);
139  return flush1 || flush2;
140 }
141 
142 template <class fpType>
143 static inline void
144 vfpFlushToZero(FPSCR &fpscr, fpType &op)
145 {
146  if (fpscr.fz == 1 && flushToZero(op)) {
147  fpscr.idc = 1;
148  }
149 }
150 
151 template <class fpType>
152 static inline void
153 vfpFlushToZero(FPSCR &fpscr, fpType &op1, fpType &op2)
154 {
155  vfpFlushToZero(fpscr, op1);
156  vfpFlushToZero(fpscr, op2);
157 }
158 
159 static inline uint32_t
160 fpToBits(float fp)
161 {
162  union
163  {
164  float fp;
165  uint32_t bits;
166  } val;
167  val.fp = fp;
168  return val.bits;
169 }
170 
171 static inline uint64_t
172 fpToBits(double fp)
173 {
174  union
175  {
176  double fp;
177  uint64_t bits;
178  } val;
179  val.fp = fp;
180  return val.bits;
181 }
182 
183 static inline float
184 bitsToFp(uint64_t bits, float junk)
185 {
186  union
187  {
188  float fp;
189  uint32_t bits;
190  } val;
191  val.bits = bits;
192  return val.fp;
193 }
194 
195 static inline double
196 bitsToFp(uint64_t bits, double junk)
197 {
198  union
199  {
200  double fp;
201  uint64_t bits;
202  } val;
203  val.bits = bits;
204  return val.fp;
205 }
206 
207 template <class fpType>
208 static inline bool
209 isSnan(fpType val)
210 {
211  const bool single = (sizeof(fpType) == sizeof(float));
212  const uint64_t qnan =
213  single ? 0x7fc00000 : 0x7ff8000000000000ULL;
214  return std::isnan(val) && ((fpToBits(val) & qnan) != qnan);
215 }
216 
217 typedef int VfpSavedState;
218 
220 void finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush, FPSCR mask = FpscrExcMask);
221 
222 template <class fpType>
223 fpType fixDest(FPSCR fpscr, fpType val, fpType op1);
224 
225 template <class fpType>
226 fpType fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2);
227 
228 template <class fpType>
229 fpType fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2);
230 
231 float fixFpDFpSDest(FPSCR fpscr, double val);
232 double fixFpSFpDDest(FPSCR fpscr, float val);
233 
234 uint16_t vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan,
235  uint32_t rMode, bool ahp, float op);
236 uint16_t vcvtFpDFpH(FPSCR &fpscr, bool flush, bool defaultNan,
237  uint32_t rMode, bool ahp, double op);
238 
239 float vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op);
240 double vcvtFpHFpD(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op);
241 
242 static inline double
243 makeDouble(uint32_t low, uint32_t high)
244 {
245  double junk = 0.0;
246  return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
247 }
248 
249 static inline uint32_t
251 {
252  return fpToBits(val);
253 }
254 
255 static inline uint32_t
257 {
258  return fpToBits(val) >> 32;
259 }
260 
261 static inline void
262 setFPExceptions(int exceptions) {
263  feclearexcept(FeAllExceptions);
264  feraiseexcept(exceptions);
265 }
266 
267 template <typename T>
268 uint64_t
269 vfpFpToFixed(T val, bool isSigned, uint8_t width, uint8_t imm, bool
270  useRmode = true, VfpRoundingMode roundMode = VfpRoundZero,
271  bool aarch64 = false)
272 {
273  int rmode;
274  bool roundAwayFix = false;
275 
276  if (!useRmode) {
277  rmode = fegetround();
278  } else {
279  switch (roundMode)
280  {
281  case VfpRoundNearest:
282  rmode = FeRoundNearest;
283  break;
284  case VfpRoundUpward:
285  rmode = FeRoundUpward;
286  break;
287  case VfpRoundDown:
288  rmode = FeRoundDown;
289  break;
290  case VfpRoundZero:
291  rmode = FeRoundZero;
292  break;
293  case VfpRoundAway:
294  // There is no equivalent rounding mode, use round down and we'll
295  // fix it later
296  rmode = FeRoundDown;
297  roundAwayFix = true;
298  break;
299  default:
300  panic("Unsupported roundMode %d\n", roundMode);
301  }
302  }
303  __asm__ __volatile__("" : "=m" (rmode) : "m" (rmode));
304  fesetround(FeRoundNearest);
305  val = val * pow(2.0, imm);
306  __asm__ __volatile__("" : "=m" (val) : "m" (val));
307  fesetround(rmode);
308  feclearexcept(FeAllExceptions);
309  __asm__ __volatile__("" : "=m" (val) : "m" (val));
310  T origVal = val;
311  val = rint(val);
312  __asm__ __volatile__("" : "=m" (val) : "m" (val));
313 
314  int exceptions = fetestexcept(FeAllExceptions);
315 
316  int fpType = std::fpclassify(val);
317  if (fpType == FP_SUBNORMAL || fpType == FP_NAN) {
318  if (fpType == FP_NAN) {
319  exceptions |= FeInvalid;
320  }
321  val = 0.0;
322  } else if (origVal != val) {
323  switch (rmode) {
324  case FeRoundNearest:
325  if (origVal - val > 0.5)
326  val += 1.0;
327  else if (val - origVal > 0.5)
328  val -= 1.0;
329  break;
330  case FeRoundDown:
331  if (roundAwayFix) {
332  // The ordering on the subtraction looks a bit odd in that we
333  // don't do the obvious origVal - val, instead we do
334  // -(val - origVal). This is required to get the corruct bit
335  // exact behaviour when very close to the 0.5 threshold.
336  volatile T error = val;
337  error -= origVal;
338  error = -error;
339  if ( (error > 0.5) ||
340  ((error == 0.5) && (val >= 0)) )
341  val += 1.0;
342  } else {
343  if (origVal < val)
344  val -= 1.0;
345  }
346  break;
347  case FeRoundUpward:
348  if (origVal > val)
349  val += 1.0;
350  break;
351  }
352  exceptions |= FeInexact;
353  }
354 
355  __asm__ __volatile__("" : "=m" (val) : "m" (val));
356 
357  if (isSigned) {
358  bool outOfRange = false;
359  int64_t result = (int64_t) val;
360  uint64_t finalVal;
361 
362  if (!aarch64) {
363  if (width == 16) {
364  finalVal = (int16_t)val;
365  } else if (width == 32) {
366  finalVal =(int32_t)val;
367  } else if (width == 64) {
368  finalVal = result;
369  } else {
370  panic("Unsupported width %d\n", width);
371  }
372 
373  // check if value is in range
374  int64_t minVal = ~mask(width-1);
375  if ((double)val < minVal) {
376  outOfRange = true;
377  finalVal = minVal;
378  }
379  int64_t maxVal = mask(width-1);
380  if ((double)val > maxVal) {
381  outOfRange = true;
382  finalVal = maxVal;
383  }
384  } else {
385  bool isNeg = val < 0;
386  finalVal = result & mask(width);
387  // If the result is supposed to be less than 64 bits check that the
388  // upper bits that got thrown away are just sign extension bits
389  if (width != 64) {
390  outOfRange = ((uint64_t) result >> (width - 1)) !=
391  (isNeg ? mask(64-width+1) : 0);
392  }
393  // Check if the original floating point value doesn't matches the
394  // integer version we are also out of range. So create a saturated
395  // result.
396  if (isNeg) {
397  outOfRange |= val < result;
398  if (outOfRange) {
399  finalVal = 1LL << (width-1);
400  }
401  } else {
402  outOfRange |= val > result;
403  if (outOfRange) {
404  finalVal = mask(width-1);
405  }
406  }
407  }
408 
409  // Raise an exception if the value was out of range
410  if (outOfRange) {
411  exceptions |= FeInvalid;
412  exceptions &= ~FeInexact;
413  }
414  setFPExceptions(exceptions);
415  return finalVal;
416  } else {
417  if ((double)val < 0) {
418  exceptions |= FeInvalid;
419  exceptions &= ~FeInexact;
420  setFPExceptions(exceptions);
421  return 0;
422  }
423 
424  uint64_t result = ((uint64_t) val) & mask(width);
425  if (val > result) {
426  exceptions |= FeInvalid;
427  exceptions &= ~FeInexact;
428  setFPExceptions(exceptions);
429  return mask(width);
430  }
431 
432  setFPExceptions(exceptions);
433  return result;
434  }
435 };
436 
437 
438 float vfpUFixedToFpS(bool flush, bool defaultNan,
439  uint64_t val, uint8_t width, uint8_t imm);
440 float vfpSFixedToFpS(bool flush, bool defaultNan,
441  int64_t val, uint8_t width, uint8_t imm);
442 
443 double vfpUFixedToFpD(bool flush, bool defaultNan,
444  uint64_t val, uint8_t width, uint8_t imm);
445 double vfpSFixedToFpD(bool flush, bool defaultNan,
446  int64_t val, uint8_t width, uint8_t imm);
447 
448 float fprSqrtEstimate(FPSCR &fpscr, float op);
449 uint32_t unsignedRSqrtEstimate(uint32_t op);
450 
451 float fpRecipEstimate(FPSCR &fpscr, float op);
452 uint32_t unsignedRecipEstimate(uint32_t op);
453 
454 FPSCR
455 fpStandardFPSCRValue(const FPSCR &fpscr);
456 
457 class VfpMacroOp : public PredMacroOp
458 {
459  public:
460  static bool
462  {
463  return (idx % 32) < 8;
464  }
465 
466  protected:
467  bool wide;
468 
469  VfpMacroOp(const char *mnem, ExtMachInst _machInst,
470  OpClass __opClass, bool _wide) :
471  PredMacroOp(mnem, _machInst, __opClass), wide(_wide)
472  {}
473 
474  RegIndex addStride(RegIndex idx, unsigned stride);
475  void nextIdxs(RegIndex &dest, RegIndex &op1, RegIndex &op2);
476  void nextIdxs(RegIndex &dest, RegIndex &op1);
477  void nextIdxs(RegIndex &dest);
478 };
479 
480 template <typename T>
481 static inline T
482 fpAdd(T a, T b)
483 {
484  return a + b;
485 };
486 
487 template <typename T>
488 static inline T
489 fpSub(T a, T b)
490 {
491  return a - b;
492 };
493 
494 static inline float
495 fpAddS(float a, float b)
496 {
497  return a + b;
498 }
499 
500 static inline double
501 fpAddD(double a, double b)
502 {
503  return a + b;
504 }
505 
506 static inline float
507 fpSubS(float a, float b)
508 {
509  return a - b;
510 }
511 
512 static inline double
513 fpSubD(double a, double b)
514 {
515  return a - b;
516 }
517 
518 static inline float
519 fpDivS(float a, float b)
520 {
521  return a / b;
522 }
523 
524 static inline double
525 fpDivD(double a, double b)
526 {
527  return a / b;
528 }
529 
530 template <typename T>
531 static inline T
532 fpDiv(T a, T b)
533 {
534  return a / b;
535 };
536 
537 template <typename T>
538 static inline T
539 fpMulX(T a, T b)
540 {
541  uint64_t opData;
542  uint32_t sign1;
543  uint32_t sign2;
544  const bool single = (sizeof(T) == sizeof(float));
545  if (single) {
546  opData = (fpToBits(a));
547  sign1 = opData>>31;
548  opData = (fpToBits(b));
549  sign2 = opData>>31;
550  } else {
551  opData = (fpToBits(a));
552  sign1 = opData>>63;
553  opData = (fpToBits(b));
554  sign2 = opData>>63;
555  }
556  bool inf1 = (std::fpclassify(a) == FP_INFINITE);
557  bool inf2 = (std::fpclassify(b) == FP_INFINITE);
558  bool zero1 = (std::fpclassify(a) == FP_ZERO);
559  bool zero2 = (std::fpclassify(b) == FP_ZERO);
560  if ((inf1 && zero2) || (zero1 && inf2)) {
561  if (sign1 ^ sign2)
562  return (T)(-2.0);
563  else
564  return (T)(2.0);
565  } else {
566  return (a * b);
567  }
568 };
569 
570 
571 template <typename T>
572 static inline T
573 fpMul(T a, T b)
574 {
575  return a * b;
576 };
577 
578 static inline float
579 fpMulS(float a, float b)
580 {
581  return a * b;
582 }
583 
584 static inline double
585 fpMulD(double a, double b)
586 {
587  return a * b;
588 }
589 
590 template <typename T>
591 static inline T
592 // @todo remove this when all calls to it have been replaced with the new fplib implementation
593 fpMulAdd(T op1, T op2, T addend)
594 {
595  T result;
596 
597  if (sizeof(T) == sizeof(float))
598  result = fmaf(op1, op2, addend);
599  else
600  result = fma(op1, op2, addend);
601 
602  // ARM doesn't generate signed nan's from this opperation, so fix up the result
603  if (std::isnan(result) && !std::isnan(op1) &&
604  !std::isnan(op2) && !std::isnan(addend))
605  {
606  uint64_t bitMask = 0x1ULL << ((sizeof(T) * 8) - 1);
607  result = bitsToFp(fpToBits(result) & ~bitMask, op1);
608  }
609  return result;
610 }
611 
612 template <typename T>
613 static inline T
614 fpRIntX(T a, FPSCR &fpscr)
615 {
616  T rVal;
617 
618  rVal = rint(a);
619  if (rVal != a && !std::isnan(a))
620  fpscr.ixc = 1;
621  return (rVal);
622 };
623 
624 template <typename T>
625 static inline T
626 fpMaxNum(T a, T b)
627 {
628  const bool single = (sizeof(T) == sizeof(float));
629  const uint64_t qnan = single ? 0x7fc00000 : 0x7ff8000000000000ULL;
630 
631  if (std::isnan(a))
632  return ((fpToBits(a) & qnan) == qnan) ? b : a;
633  if (std::isnan(b))
634  return ((fpToBits(b) & qnan) == qnan) ? a : b;
635  // Handle comparisons of +0 and -0.
636  if (!std::signbit(a) && std::signbit(b))
637  return a;
638  return fmax(a, b);
639 };
640 
641 template <typename T>
642 static inline T
643 fpMax(T a, T b)
644 {
645  if (std::isnan(a))
646  return a;
647  if (std::isnan(b))
648  return b;
649  return fpMaxNum<T>(a, b);
650 };
651 
652 template <typename T>
653 static inline T
654 fpMinNum(T a, T b)
655 {
656  const bool single = (sizeof(T) == sizeof(float));
657  const uint64_t qnan = single ? 0x7fc00000 : 0x7ff8000000000000ULL;
658 
659  if (std::isnan(a))
660  return ((fpToBits(a) & qnan) == qnan) ? b : a;
661  if (std::isnan(b))
662  return ((fpToBits(b) & qnan) == qnan) ? a : b;
663  // Handle comparisons of +0 and -0.
664  if (std::signbit(a) && !std::signbit(b))
665  return a;
666  return fmin(a, b);
667 };
668 
669 template <typename T>
670 static inline T
671 fpMin(T a, T b)
672 {
673  if (std::isnan(a))
674  return a;
675  if (std::isnan(b))
676  return b;
677  return fpMinNum<T>(a, b);
678 };
679 
680 template <typename T>
681 static inline T
682 fpRSqrts(T a, T b)
683 {
684  int fpClassA = std::fpclassify(a);
685  int fpClassB = std::fpclassify(b);
686  T aXb;
687  int fpClassAxB;
688 
689  if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
690  (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
691  return 1.5;
692  }
693  aXb = a*b;
694  fpClassAxB = std::fpclassify(aXb);
695  if (fpClassAxB == FP_SUBNORMAL) {
696  feraiseexcept(FeUnderflow);
697  return 1.5;
698  }
699  return (3.0 - (a * b)) / 2.0;
700 };
701 
702 template <typename T>
703 static inline T
704 fpRecps(T a, T b)
705 {
706  int fpClassA = std::fpclassify(a);
707  int fpClassB = std::fpclassify(b);
708  T aXb;
709  int fpClassAxB;
710 
711  if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
712  (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
713  return 2.0;
714  }
715  aXb = a*b;
716  fpClassAxB = std::fpclassify(aXb);
717  if (fpClassAxB == FP_SUBNORMAL) {
718  feraiseexcept(FeUnderflow);
719  return 2.0;
720  }
721  return 2.0 - (a * b);
722 };
723 
724 
725 static inline float
726 fpRSqrtsS(float a, float b)
727 {
728  int fpClassA = std::fpclassify(a);
729  int fpClassB = std::fpclassify(b);
730  float aXb;
731  int fpClassAxB;
732 
733  if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
734  (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
735  return 1.5;
736  }
737  aXb = a*b;
738  fpClassAxB = std::fpclassify(aXb);
739  if (fpClassAxB == FP_SUBNORMAL) {
740  feraiseexcept(FeUnderflow);
741  return 1.5;
742  }
743  return (3.0 - (a * b)) / 2.0;
744 }
745 
746 static inline float
747 fpRecpsS(float a, float b)
748 {
749  int fpClassA = std::fpclassify(a);
750  int fpClassB = std::fpclassify(b);
751  float aXb;
752  int fpClassAxB;
753 
754  if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
755  (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
756  return 2.0;
757  }
758  aXb = a*b;
759  fpClassAxB = std::fpclassify(aXb);
760  if (fpClassAxB == FP_SUBNORMAL) {
761  feraiseexcept(FeUnderflow);
762  return 2.0;
763  }
764  return 2.0 - (a * b);
765 }
766 
767 template <typename T>
768 static inline T
770  T val;
771 
772  val = round(a);
773  if (a - val == 0.5) {
774  if ( (((int) a) & 1) == 0 ) val += 1.0;
775  }
776  else if (a - val == -0.5) {
777  if ( (((int) a) & 1) == 0 ) val -= 1.0;
778  }
779  return val;
780 }
781 
782 
783 
784 class FpOp : public PredOp
785 {
786  protected:
787  FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
788  PredOp(mnem, _machInst, __opClass)
789  {}
790 
791  virtual float
792  doOp(float op1, float op2) const
793  {
794  panic("Unimplemented version of doOp called.\n");
795  }
796 
797  virtual float
798  doOp(float op1) const
799  {
800  panic("Unimplemented version of doOp called.\n");
801  }
802 
803  virtual double
804  doOp(double op1, double op2) const
805  {
806  panic("Unimplemented version of doOp called.\n");
807  }
808 
809  virtual double
810  doOp(double op1) const
811  {
812  panic("Unimplemented version of doOp called.\n");
813  }
814 
815  double
816  dbl(uint32_t low, uint32_t high) const
817  {
818  double junk = 0.0;
819  return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
820  }
821 
822  uint32_t
823  dblLow(double val) const
824  {
825  return fpToBits(val);
826  }
827 
828  uint32_t
829  dblHi(double val) const
830  {
831  return fpToBits(val) >> 32;
832  }
833 
834  template <class fpType>
835  fpType
836  processNans(FPSCR &fpscr, bool &done, bool defaultNan,
837  fpType op1, fpType op2) const;
838 
839  template <class fpType>
840  fpType
841  ternaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType op3,
842  fpType (*func)(fpType, fpType, fpType),
843  bool flush, bool defaultNan, uint32_t rMode) const;
844 
845  template <class fpType>
846  fpType
847  binaryOp(FPSCR &fpscr, fpType op1, fpType op2,
848  fpType (*func)(fpType, fpType),
849  bool flush, bool defaultNan, uint32_t rMode) const;
850 
851  template <class fpType>
852  fpType
853  unaryOp(FPSCR &fpscr, fpType op1,
854  fpType (*func)(fpType),
855  bool flush, uint32_t rMode) const;
856 
857  void
858  advancePC(PCStateBase &pcState) const override
859  {
860  auto &apc = pcState.as<PCState>();
861  if (flags[IsLastMicroop]) {
862  apc.uEnd();
863  } else if (flags[IsMicroop]) {
864  apc.uAdvance();
865  } else {
866  apc.advance();
867  }
868  }
869 
870  void
871  advancePC(ThreadContext *tc) const override
872  {
873  PCState pc = tc->pcState().as<PCState>();
874  if (flags[IsLastMicroop]) {
875  pc.uEnd();
876  } else if (flags[IsMicroop]) {
877  pc.uAdvance();
878  } else {
879  pc.advance();
880  }
881  tc->pcState(pc);
882  }
883 
884  float
885  fpSqrt (FPSCR fpscr,float x) const
886  {
887 
888  return unaryOp(fpscr,x,sqrtf,fpscr.fz,fpscr.rMode);
889 
890  }
891 
892  double
893  fpSqrt (FPSCR fpscr,double x) const
894  {
895 
896  return unaryOp(fpscr,x,sqrt,fpscr.fz,fpscr.rMode);
897 
898  }
899 };
900 
901 class FpCondCompRegOp : public FpOp
902 {
903  protected:
906  uint8_t defCc;
907 
908  FpCondCompRegOp(const char *mnem, ExtMachInst _machInst,
909  OpClass __opClass, RegIndex _op1, RegIndex _op2,
910  ConditionCode _condCode, uint8_t _defCc) :
911  FpOp(mnem, _machInst, __opClass),
912  op1(_op1), op2(_op2), condCode(_condCode), defCc(_defCc)
913  {}
914 
915  std::string generateDisassembly(
916  Addr pc, const loader::SymbolTable *symtab) const override;
917 };
918 
919 class FpCondSelOp : public FpOp
920 {
921  protected:
924 
925  FpCondSelOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
926  RegIndex _dest, RegIndex _op1, RegIndex _op2,
927  ConditionCode _condCode) :
928  FpOp(mnem, _machInst, __opClass),
929  dest(_dest), op1(_op1), op2(_op2), condCode(_condCode)
930  {}
931 
932  std::string generateDisassembly(
933  Addr pc, const loader::SymbolTable *symtab) const override;
934 };
935 
936 class FpRegRegOp : public FpOp
937 {
938  protected:
941 
942  FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
943  RegIndex _dest, RegIndex _op1,
945  FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1)
946  {
948  }
949 
950  std::string generateDisassembly(
951  Addr pc, const loader::SymbolTable *symtab) const override;
952 };
953 
954 class FpRegImmOp : public FpOp
955 {
956  protected:
958  uint64_t imm;
959 
960  FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
961  RegIndex _dest, uint64_t _imm,
963  FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm)
964  {
966  }
967 
968  std::string generateDisassembly(
969  Addr pc, const loader::SymbolTable *symtab) const override;
970 };
971 
972 class FpRegRegImmOp : public FpOp
973 {
974  protected:
977  uint64_t imm;
978 
979  FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
980  RegIndex _dest, RegIndex _op1,
981  uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) :
982  FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm)
983  {
985  }
986 
987  std::string generateDisassembly(
988  Addr pc, const loader::SymbolTable *symtab) const override;
989 };
990 
991 class FpRegRegRegOp : public FpOp
992 {
993  protected:
997 
998  FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
999  RegIndex _dest, RegIndex _op1, RegIndex _op2,
1001  FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2)
1002  {
1004  }
1005 
1006  std::string generateDisassembly(
1007  Addr pc, const loader::SymbolTable *symtab) const override;
1008 };
1009 
1010 class FpRegRegRegCondOp : public FpOp
1011 {
1012  protected:
1017 
1018  FpRegRegRegCondOp(const char *mnem, ExtMachInst _machInst,
1019  OpClass __opClass, RegIndex _dest, RegIndex _op1,
1020  RegIndex _op2, ConditionCode _cond,
1022  FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2),
1023  cond(_cond)
1024  {
1026  }
1027 
1028  std::string generateDisassembly(
1029  Addr pc, const loader::SymbolTable *symtab) const override;
1030 };
1031 
1032 class FpRegRegRegRegOp : public FpOp
1033 {
1034  protected:
1039 
1040  FpRegRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
1041  RegIndex _dest, RegIndex _op1, RegIndex _op2,
1043  FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2),
1044  op3(_op3)
1045  {
1047  }
1048 
1049  std::string generateDisassembly(
1050  Addr pc, const loader::SymbolTable *symtab) const override;
1051 };
1052 
1053 class FpRegRegRegImmOp : public FpOp
1054 {
1055  protected:
1059  uint64_t imm;
1060 
1061  FpRegRegRegImmOp(const char *mnem, ExtMachInst _machInst,
1062  OpClass __opClass, RegIndex _dest,
1063  RegIndex _op1, RegIndex _op2,
1064  uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) :
1065  FpOp(mnem, _machInst, __opClass),
1066  dest(_dest), op1(_op1), op2(_op2), imm(_imm)
1067  {
1069  }
1070 
1071  std::string generateDisassembly(
1072  Addr pc, const loader::SymbolTable *symtab) const override;
1073 };
1074 
1075 } // namespace ArmISA
1076 } // namespace gem5
1077 
1078 #endif //__ARCH_ARM_INSTS_VFP_HH__
std::string error
Definition: remote_gdb.cc:212
ConditionCode condCode
Definition: vfp.hh:905
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:52
FpCondCompRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _op1, RegIndex _op2, ConditionCode _condCode, uint8_t _defCc)
Definition: vfp.hh:908
FpCondSelOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, RegIndex _op1, RegIndex _op2, ConditionCode _condCode)
Definition: vfp.hh:925
ConditionCode condCode
Definition: vfp.hh:923
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:67
void advancePC(ThreadContext *tc) const override
Definition: vfp.hh:871
void advancePC(PCStateBase &pcState) const override
Definition: vfp.hh:858
float fpSqrt(FPSCR fpscr, float x) const
Definition: vfp.hh:885
uint32_t dblLow(double val) const
Definition: vfp.hh:823
fpType unaryOp(FPSCR &fpscr, fpType op1, fpType(*func)(fpType), bool flush, uint32_t rMode) const
Definition: vfp.cc:1110
fpType processNans(FPSCR &fpscr, bool &done, bool defaultNan, fpType op1, fpType op2) const
Definition: vfp.cc:917
uint32_t dblHi(double val) const
Definition: vfp.hh:829
virtual double doOp(double op1) const
Definition: vfp.hh:810
fpType ternaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType op3, fpType(*func)(fpType, fpType, fpType), bool flush, bool defaultNan, uint32_t rMode) const
Definition: vfp.cc:961
virtual float doOp(float op1) const
Definition: vfp.hh:798
fpType binaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType(*func)(fpType, fpType), bool flush, bool defaultNan, uint32_t rMode) const
Definition: vfp.cc:1039
virtual double doOp(double op1, double op2) const
Definition: vfp.hh:804
double fpSqrt(FPSCR fpscr, double x) const
Definition: vfp.hh:893
FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
Definition: vfp.hh:787
virtual float doOp(float op1, float op2) const
Definition: vfp.hh:792
double dbl(uint32_t low, uint32_t high) const
Definition: vfp.hh:816
FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, uint64_t _imm, VfpMicroMode mode=VfpNotAMicroop)
Definition: vfp.hh:960
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:95
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:106
FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, RegIndex _op1, uint64_t _imm, VfpMicroMode mode=VfpNotAMicroop)
Definition: vfp.hh:979
FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, RegIndex _op1, VfpMicroMode mode=VfpNotAMicroop)
Definition: vfp.hh:942
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:83
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:133
FpRegRegRegCondOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, RegIndex _op1, RegIndex _op2, ConditionCode _cond, VfpMicroMode mode=VfpNotAMicroop)
Definition: vfp.hh:1018
FpRegRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, RegIndex _op1, RegIndex _op2, uint64_t _imm, VfpMicroMode mode=VfpNotAMicroop)
Definition: vfp.hh:1061
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:165
FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, RegIndex _op1, RegIndex _op2, VfpMicroMode mode=VfpNotAMicroop)
Definition: vfp.hh:998
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:119
FpRegRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RegIndex _dest, RegIndex _op1, RegIndex _op2, RegIndex _op3, VfpMicroMode mode=VfpNotAMicroop)
Definition: vfp.hh:1040
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:149
Base class for predicated macro-operations.
Definition: pred_inst.hh:343
Base class for predicated integer operations.
Definition: pred_inst.hh:217
static bool inScalarBank(RegIndex idx)
Definition: vfp.hh:461
void nextIdxs(RegIndex &dest, RegIndex &op1, RegIndex &op2)
Definition: vfp.cc:1180
RegIndex addStride(RegIndex idx, unsigned stride)
Definition: vfp.cc:1167
VfpMacroOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, bool _wide)
Definition: vfp.hh:469
Target & as()
Definition: pcstate.hh:72
std::bitset< Num_Flags > flags
Flag values for this instruction.
Definition: static_inst.hh:103
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual const PCStateBase & pcState() const =0
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:76
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
atomic_var_t state
Definition: helpers.cc:188
uint8_t flags
Definition: helpers.cc:66
uint32_t unsignedRecipEstimate(uint32_t op)
Definition: vfp.cc:889
FeRoundingMode
Definition: vfp.hh:99
@ FeRoundZero
Definition: vfp.hh:102
@ FeRoundNearest
Definition: vfp.hh:101
@ FeRoundUpward
Definition: vfp.hh:103
@ FeRoundDown
Definition: vfp.hh:100
static uint32_t fpToBits(float)
Definition: vfp.hh:160
fpType fixDivDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2)
Definition: vfp.cc:302
static uint32_t highFromDouble(double val)
Definition: vfp.hh:256
static double fpMulD(double a, double b)
Definition: vfp.hh:585
static T fpMin(T a, T b)
Definition: vfp.hh:671
Bitfield< 3, 0 > mask
Definition: pcstate.hh:63
static T fpMax(T a, T b)
Definition: vfp.hh:643
double vfpSFixedToFpD(bool flush, bool defaultNan, int64_t val, uint8_t width, uint8_t imm)
Definition: vfp.cc:732
Bitfield< 4, 0 > mode
Definition: misc_types.hh:74
Bitfield< 4 > width
Definition: misc_types.hh:72
static T fpRIntX(T a, FPSCR &fpscr)
Definition: vfp.hh:614
static T fpSub(T a, T b)
Definition: vfp.hh:489
Bitfield< 7, 0 > imm
Definition: types.hh:132
Bitfield< 7 > b
Definition: misc_types.hh:388
static const uint32_t FpscrExcMask
Definition: misc.hh:2755
static float fpRSqrtsS(float a, float b)
Definition: vfp.hh:726
static float fpDivS(float a, float b)
Definition: vfp.hh:519
double vcvtFpHFpD(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
Definition: vfp.cc:655
static T fpMulX(T a, T b)
Definition: vfp.hh:539
static float fpRecpsS(float a, float b)
Definition: vfp.hh:747
float vfpUFixedToFpS(bool flush, bool defaultNan, uint64_t val, uint8_t width, uint8_t imm)
Definition: vfp.cc:675
Bitfield< 23, 22 > rMode
Definition: misc_types.hh:454
uint32_t unsignedRSqrtEstimate(uint32_t op)
Definition: vfp.cc:814
VfpSavedState prepFpState(uint32_t rMode)
Definition: vfp.cc:183
float fixFpDFpSDest(FPSCR fpscr, double val)
Definition: vfp.cc:337
int VfpSavedState
Definition: vfp.hh:217
static T fpMul(T a, T b)
Definition: vfp.hh:573
static float fpMulS(float a, float b)
Definition: vfp.hh:579
static T fpDiv(T a, T b)
Definition: vfp.hh:532
void finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush, FPSCR mask)
Definition: vfp.cc:205
double fixFpSFpDDest(FPSCR fpscr, float val)
Definition: vfp.cc:373
FeExceptionBit
Definition: vfp.hh:89
@ FeUnderflow
Definition: vfp.hh:94
@ FeDivByZero
Definition: vfp.hh:90
@ FeInvalid
Definition: vfp.hh:92
@ FeOverflow
Definition: vfp.hh:93
@ FeAllExceptions
Definition: vfp.hh:95
@ FeInexact
Definition: vfp.hh:91
Bitfield< 26 > ahp
Definition: misc_types.hh:457
float vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
Definition: vfp.cc:665
static T roundNEven(T a)
Definition: vfp.hh:769
VfpMicroMode
Definition: vfp.hh:57
@ VfpNotAMicroop
Definition: vfp.hh:58
@ VfpMicroop
Definition: vfp.hh:59
@ VfpFirstMicroop
Definition: vfp.hh:60
@ VfpLastMicroop
Definition: vfp.hh:61
static T fpMinNum(T a, T b)
Definition: vfp.hh:654
ConditionCode
Definition: cc.hh:92
float vfpSFixedToFpS(bool flush, bool defaultNan, int64_t val, uint8_t width, uint8_t imm)
Definition: vfp.cc:693
static uint32_t lowFromDouble(double val)
Definition: vfp.hh:250
fpType fixDest(bool flush, bool defaultNan, fpType val, fpType op1)
Definition: vfp.cc:231
Bitfield< 8 > a
Definition: misc_types.hh:66
double vfpUFixedToFpD(bool flush, bool defaultNan, uint64_t val, uint8_t width, uint8_t imm)
Definition: vfp.cc:713
Bitfield< 21, 20 > stride
Definition: misc_types.hh:453
static float bitsToFp(uint64_t, float)
Definition: vfp.hh:184
static T fpMulAdd(T op1, T op2, T addend)
Definition: vfp.hh:593
static double fpAddD(double a, double b)
Definition: vfp.hh:501
static float fpSubS(float a, float b)
Definition: vfp.hh:507
uint16_t vcvtFpDFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, double op)
Definition: vfp.cc:585
static double fpSubD(double a, double b)
Definition: vfp.hh:513
FPSCR fpStandardFPSCRValue(const FPSCR &fpscr)
Definition: vfp.cc:905
static T fpRSqrts(T a, T b)
Definition: vfp.hh:682
static bool isSnan(fpType val)
Definition: vfp.hh:209
uint16_t vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, float op)
Definition: vfp.cc:577
static void setFPExceptions(int exceptions)
Definition: vfp.hh:262
static T fpAdd(T a, T b)
Definition: vfp.hh:482
static float fpAddS(float a, float b)
Definition: vfp.hh:495
static double makeDouble(uint32_t low, uint32_t high)
Definition: vfp.hh:243
static void vfpFlushToZero(FPSCR &fpscr, fpType &op)
Definition: vfp.hh:144
Bitfield< 34 > aarch64
Definition: types.hh:81
static double fpDivD(double a, double b)
Definition: vfp.hh:525
uint64_t vfpFpToFixed(T val, bool isSigned, uint8_t width, uint8_t imm, bool useRmode=true, VfpRoundingMode roundMode=VfpRoundZero, bool aarch64=false)
Definition: vfp.hh:269
static void setVfpMicroFlags(VfpMicroMode mode, T &flags)
Definition: vfp.hh:66
Bitfield< 19, 16 > fp
Definition: misc_types.hh:177
static T fpRecps(T a, T b)
Definition: vfp.hh:704
float fprSqrtEstimate(FPSCR &fpscr, float op)
Definition: vfp.cc:771
float fpRecipEstimate(FPSCR &fpscr, float op)
Definition: vfp.cc:853
VfpRoundingMode
Definition: vfp.hh:107
@ VfpRoundNearest
Definition: vfp.hh:108
@ VfpRoundZero
Definition: vfp.hh:111
@ VfpRoundAway
Definition: vfp.hh:112
@ VfpRoundUpward
Definition: vfp.hh:109
@ VfpRoundDown
Definition: vfp.hh:110
static T fpMaxNum(T a, T b)
Definition: vfp.hh:626
Bitfield< 4 > pc
Bitfield< 4 > x
Definition: pagetable.hh:61
Bitfield< 4 > op
Definition: types.hh:83
Bitfield< 63 > val
Definition: misc.hh:776
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
uint16_t RegIndex
Definition: types.hh:176
high
Definition: intmath.hh:176
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147

Generated on Wed Dec 21 2022 10:22:26 for gem5 by doxygen 1.9.1