gem5  v20.1.0.0
vfp.cc
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 #include "arch/arm/insts/vfp.hh"
39 
40 using namespace ArmISA;
41 
42 /*
43  * The asm statements below are to keep gcc from reordering code. Otherwise
44  * the rounding mode might be set after the operation it was intended for, the
45  * exception bits read before it, etc.
46  */
47 
48 std::string
50  Addr pc, const Loader::SymbolTable *symtab) const
51 {
52  std::stringstream ss;
53  printMnemonic(ss, "", false);
54  printIntReg(ss, op1);
55  ccprintf(ss, ", ");
56  printIntReg(ss, op2);
57  ccprintf(ss, ", #%d", defCc);
58  ccprintf(ss, ", ");
59  printCondition(ss, condCode, true);
60  return ss.str();
61 }
62 
63 std::string
65  Addr pc, const Loader::SymbolTable *symtab) const
66 {
67  std::stringstream ss;
68  printMnemonic(ss, "", false);
70  ccprintf(ss, ", ");
71  printIntReg(ss, op1);
72  ccprintf(ss, ", ");
73  printIntReg(ss, op2);
74  ccprintf(ss, ", ");
75  printCondition(ss, condCode, true);
76  return ss.str();
77 }
78 
79 std::string
81  Addr pc, const Loader::SymbolTable *symtab) const
82 {
83  std::stringstream ss;
86  ss << ", ";
88  return ss.str();
89 }
90 
91 std::string
93  Addr pc, const Loader::SymbolTable *symtab) const
94 {
95  std::stringstream ss;
98  ccprintf(ss, ", #%d", imm);
99  return ss.str();
100 }
101 
102 std::string
104  Addr pc, const Loader::SymbolTable *symtab) const
105 {
106  std::stringstream ss;
107  printMnemonic(ss);
109  ss << ", ";
110  printFloatReg(ss, op1);
111  ccprintf(ss, ", #%d", imm);
112  return ss.str();
113 }
114 
115 std::string
117  Addr pc, const Loader::SymbolTable *symtab) const
118 {
119  std::stringstream ss;
120  printMnemonic(ss);
122  ss << ", ";
123  printFloatReg(ss, op1);
124  ss << ", ";
125  printFloatReg(ss, op2);
126  return ss.str();
127 }
128 
129 std::string
131  Addr pc, const Loader::SymbolTable *symtab)
132  const
133 {
134  std::stringstream ss;
135  printMnemonic(ss);
138  ss << ", ";
139  printFloatReg(ss, op1);
140  ss << ", ";
141  printFloatReg(ss, op2);
142  return ss.str();
143 }
144 
145 std::string
147  Addr pc, const Loader::SymbolTable *symtab) const
148 {
149  std::stringstream ss;
150  printMnemonic(ss);
152  ss << ", ";
153  printFloatReg(ss, op1);
154  ss << ", ";
155  printFloatReg(ss, op2);
156  ss << ", ";
157  printFloatReg(ss, op3);
158  return ss.str();
159 }
160 
161 std::string
163  Addr pc, const Loader::SymbolTable *symtab) const
164 {
165  std::stringstream ss;
166  printMnemonic(ss);
168  ss << ", ";
169  printFloatReg(ss, op1);
170  ss << ", ";
171  printFloatReg(ss, op2);
172  ccprintf(ss, ", #%d", imm);
173  return ss.str();
174 }
175 
176 namespace ArmISA
177 {
178 
181 {
182  int roundingMode = fegetround();
183  feclearexcept(FeAllExceptions);
184  switch (rMode) {
185  case VfpRoundNearest:
186  fesetround(FeRoundNearest);
187  break;
188  case VfpRoundUpward:
189  fesetround(FeRoundUpward);
190  break;
191  case VfpRoundDown:
192  fesetround(FeRoundDown);
193  break;
194  case VfpRoundZero:
195  fesetround(FeRoundZero);
196  break;
197  }
198  return roundingMode;
199 }
200 
201 void
202 finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush, FPSCR mask)
203 {
204  int exceptions = fetestexcept(FeAllExceptions);
205  bool underflow = false;
206  if ((exceptions & FeInvalid) && mask.ioc) {
207  fpscr.ioc = 1;
208  }
209  if ((exceptions & FeDivByZero) && mask.dzc) {
210  fpscr.dzc = 1;
211  }
212  if ((exceptions & FeOverflow) && mask.ofc) {
213  fpscr.ofc = 1;
214  }
215  if (exceptions & FeUnderflow) {
216  underflow = true;
217  if (mask.ufc)
218  fpscr.ufc = 1;
219  }
220  if ((exceptions & FeInexact) && !(underflow && flush) && mask.ixc) {
221  fpscr.ixc = 1;
222  }
223  fesetround(state);
224 }
225 
226 template <class fpType>
227 fpType
228 fixDest(bool flush, bool defaultNan, fpType val, fpType op1)
229 {
230  int fpClass = std::fpclassify(val);
231  fpType junk = 0.0;
232  if (fpClass == FP_NAN) {
233  const bool single = (sizeof(val) == sizeof(float));
234  const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000);
235  const bool nan = std::isnan(op1);
236  if (!nan || defaultNan) {
237  val = bitsToFp(qnan, junk);
238  } else if (nan) {
239  val = bitsToFp(fpToBits(op1) | qnan, junk);
240  }
241  } else if (fpClass == FP_SUBNORMAL && flush == 1) {
242  // Turn val into a zero with the correct sign;
243  uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
244  val = bitsToFp(fpToBits(val) & bitMask, junk);
245  feclearexcept(FeInexact);
246  feraiseexcept(FeUnderflow);
247  }
248  return val;
249 }
250 
251 template
252 float fixDest<float>(bool flush, bool defaultNan, float val, float op1);
253 template
254 double fixDest<double>(bool flush, bool defaultNan, double val, double op1);
255 
256 template <class fpType>
257 fpType
258 fixDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2)
259 {
260  int fpClass = std::fpclassify(val);
261  fpType junk = 0.0;
262  if (fpClass == FP_NAN) {
263  const bool single = (sizeof(val) == sizeof(float));
264  const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000);
265  const bool nan1 = std::isnan(op1);
266  const bool nan2 = std::isnan(op2);
267  const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan);
268  const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan);
269  if ((!nan1 && !nan2) || defaultNan) {
270  val = bitsToFp(qnan, junk);
271  } else if (signal1) {
272  val = bitsToFp(fpToBits(op1) | qnan, junk);
273  } else if (signal2) {
274  val = bitsToFp(fpToBits(op2) | qnan, junk);
275  } else if (nan1) {
276  val = op1;
277  } else if (nan2) {
278  val = op2;
279  }
280  } else if (fpClass == FP_SUBNORMAL && flush) {
281  // Turn val into a zero with the correct sign;
282  uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
283  val = bitsToFp(fpToBits(val) & bitMask, junk);
284  feclearexcept(FeInexact);
285  feraiseexcept(FeUnderflow);
286  }
287  return val;
288 }
289 
290 template
291 float fixDest<float>(bool flush, bool defaultNan,
292  float val, float op1, float op2);
293 template
294 double fixDest<double>(bool flush, bool defaultNan,
295  double val, double op1, double op2);
296 
297 template <class fpType>
298 fpType
299 fixDivDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2)
300 {
301  fpType mid = fixDest(flush, defaultNan, val, op1, op2);
302  const bool single = (sizeof(fpType) == sizeof(float));
303  const fpType junk = 0.0;
304  if ((single && (val == bitsToFp(0x00800000, junk) ||
305  val == bitsToFp(0x80800000, junk))) ||
306  (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) ||
307  val == bitsToFp(ULL(0x8010000000000000), junk)))
308  ) {
309  __asm__ __volatile__("" : "=m" (op1) : "m" (op1));
310  fesetround(FeRoundZero);
311  fpType temp = 0.0;
312  __asm__ __volatile__("" : "=m" (temp) : "m" (temp));
313  temp = op1 / op2;
314  if (flushToZero(temp)) {
315  feraiseexcept(FeUnderflow);
316  if (flush) {
317  feclearexcept(FeInexact);
318  mid = temp;
319  }
320  }
321  __asm__ __volatile__("" :: "m" (temp));
322  }
323  return mid;
324 }
325 
326 template
327 float fixDivDest<float>(bool flush, bool defaultNan,
328  float val, float op1, float op2);
329 template
330 double fixDivDest<double>(bool flush, bool defaultNan,
331  double val, double op1, double op2);
332 
333 float
334 fixFpDFpSDest(FPSCR fpscr, double val)
335 {
336  const float junk = 0.0;
337  float op1 = 0.0;
338  if (std::isnan(val)) {
339  uint64_t valBits = fpToBits(val);
340  uint32_t op1Bits = bits(valBits, 50, 29) |
341  (mask(9) << 22) |
342  (bits(valBits, 63) << 31);
343  op1 = bitsToFp(op1Bits, junk);
344  }
345  float mid = fixDest(fpscr.fz, fpscr.dn, (float)val, op1);
346  if (fpscr.fz && fetestexcept(FeUnderflow | FeInexact) ==
347  (FeUnderflow | FeInexact)) {
348  feclearexcept(FeInexact);
349  }
350  if (mid == bitsToFp(0x00800000, junk) ||
351  mid == bitsToFp(0x80800000, junk)) {
352  __asm__ __volatile__("" : "=m" (val) : "m" (val));
353  fesetround(FeRoundZero);
354  float temp = 0.0;
355  __asm__ __volatile__("" : "=m" (temp) : "m" (temp));
356  temp = val;
357  if (flushToZero(temp)) {
358  feraiseexcept(FeUnderflow);
359  if (fpscr.fz) {
360  feclearexcept(FeInexact);
361  mid = temp;
362  }
363  }
364  __asm__ __volatile__("" :: "m" (temp));
365  }
366  return mid;
367 }
368 
369 double
370 fixFpSFpDDest(FPSCR fpscr, float val)
371 {
372  const double junk = 0.0;
373  double op1 = 0.0;
374  if (std::isnan(val)) {
375  uint32_t valBits = fpToBits(val);
376  uint64_t op1Bits = ((uint64_t)bits(valBits, 21, 0) << 29) |
377  (mask(12) << 51) |
378  ((uint64_t)bits(valBits, 31) << 63);
379  op1 = bitsToFp(op1Bits, junk);
380  }
381  double mid = fixDest(fpscr.fz, fpscr.dn, (double)val, op1);
382  if (mid == bitsToFp(ULL(0x0010000000000000), junk) ||
383  mid == bitsToFp(ULL(0x8010000000000000), junk)) {
384  __asm__ __volatile__("" : "=m" (val) : "m" (val));
385  fesetround(FeRoundZero);
386  double temp = 0.0;
387  __asm__ __volatile__("" : "=m" (temp) : "m" (temp));
388  temp = val;
389  if (flushToZero(temp)) {
390  feraiseexcept(FeUnderflow);
391  if (fpscr.fz) {
392  feclearexcept(FeInexact);
393  mid = temp;
394  }
395  }
396  __asm__ __volatile__("" :: "m" (temp));
397  }
398  return mid;
399 }
400 
401 static inline uint16_t
402 vcvtFpFpH(FPSCR &fpscr, bool flush, bool defaultNan,
403  uint32_t rMode, bool ahp, uint64_t opBits, bool isDouble)
404 {
405  uint32_t mWidth;
406  uint32_t eWidth;
407  uint32_t eHalfRange;
408  uint32_t sBitPos;
409 
410  if (isDouble) {
411  mWidth = 52;
412  eWidth = 11;
413  } else {
414  mWidth = 23;
415  eWidth = 8;
416  }
417  sBitPos = eWidth + mWidth;
418  eHalfRange = (1 << (eWidth-1)) - 1;
419 
420  // Extract the operand.
421  bool neg = bits(opBits, sBitPos);
422  uint32_t exponent = bits(opBits, sBitPos-1, mWidth);
423  uint64_t oldMantissa = bits(opBits, mWidth-1, 0);
424  uint32_t mantissa = oldMantissa >> (mWidth - 10);
425  // Do the conversion.
426  uint64_t extra = oldMantissa & mask(mWidth - 10);
427  if (exponent == mask(eWidth)) {
428  if (oldMantissa != 0) {
429  // Nans.
430  if (bits(mantissa, 9) == 0) {
431  // Signalling nan.
432  fpscr.ioc = 1;
433  }
434  if (ahp) {
435  mantissa = 0;
436  exponent = 0;
437  fpscr.ioc = 1;
438  } else if (defaultNan) {
439  mantissa = (1 << 9);
440  exponent = 0x1f;
441  neg = false;
442  } else {
443  exponent = 0x1f;
444  mantissa |= (1 << 9);
445  }
446  } else {
447  // Infinities.
448  exponent = 0x1F;
449  if (ahp) {
450  fpscr.ioc = 1;
451  mantissa = 0x3ff;
452  } else {
453  mantissa = 0;
454  }
455  }
456  } else if (exponent == 0 && oldMantissa == 0) {
457  // Zero, don't need to do anything.
458  } else {
459  // Normalized or denormalized numbers.
460 
461  bool inexact = (extra != 0);
462 
463  if (exponent == 0) {
464  // Denormalized.
465  // If flush to zero is on, this shouldn't happen.
466  assert(!flush);
467 
468  // Check for underflow
469  if (inexact || fpscr.ufe)
470  fpscr.ufc = 1;
471 
472  // Handle rounding.
473  unsigned mode = rMode;
474  if ((mode == VfpRoundUpward && !neg && extra) ||
475  (mode == VfpRoundDown && neg && extra) ||
476  (mode == VfpRoundNearest &&
477  (extra > (1 << 9) ||
478  (extra == (1 << 9) && bits(mantissa, 0))))) {
479  mantissa++;
480  }
481 
482  // See if the number became normalized after rounding.
483  if (mantissa == (1 << 10)) {
484  mantissa = 0;
485  exponent = 1;
486  }
487  } else {
488  // Normalized.
489 
490  // We need to track the dropped bits differently since
491  // more can be dropped by denormalizing.
492  bool topOne = bits(extra, mWidth - 10 - 1);
493  bool restZeros = bits(extra, mWidth - 10 - 2, 0) == 0;
494 
495  if (exponent <= (eHalfRange - 15)) {
496  // The result is too small. Denormalize.
497  mantissa |= (1 << 10);
498  while (mantissa && exponent <= (eHalfRange - 15)) {
499  restZeros = restZeros && !topOne;
500  topOne = bits(mantissa, 0);
501  mantissa = mantissa >> 1;
502  exponent++;
503  }
504  if (topOne || !restZeros)
505  inexact = true;
506  exponent = 0;
507  } else {
508  // Change bias.
509  exponent -= (eHalfRange - 15);
510  }
511 
512  if (exponent == 0 && (inexact || fpscr.ufe)) {
513  // Underflow
514  fpscr.ufc = 1;
515  }
516 
517  // Handle rounding.
518  unsigned mode = rMode;
519  bool nonZero = topOne || !restZeros;
520  if ((mode == VfpRoundUpward && !neg && nonZero) ||
521  (mode == VfpRoundDown && neg && nonZero) ||
522  (mode == VfpRoundNearest && topOne &&
523  (!restZeros || bits(mantissa, 0)))) {
524  mantissa++;
525  }
526 
527  // See if we rounded up and need to bump the exponent.
528  if (mantissa == (1 << 10)) {
529  mantissa = 0;
530  exponent++;
531  }
532 
533  // Deal with overflow
534  if (ahp) {
535  if (exponent >= 0x20) {
536  exponent = 0x1f;
537  mantissa = 0x3ff;
538  fpscr.ioc = 1;
539  // Supress inexact exception.
540  inexact = false;
541  }
542  } else {
543  if (exponent >= 0x1f) {
544  if ((mode == VfpRoundNearest) ||
545  (mode == VfpRoundUpward && !neg) ||
546  (mode == VfpRoundDown && neg)) {
547  // Overflow to infinity.
548  exponent = 0x1f;
549  mantissa = 0;
550  } else {
551  // Overflow to max normal.
552  exponent = 0x1e;
553  mantissa = 0x3ff;
554  }
555  fpscr.ofc = 1;
556  inexact = true;
557  }
558  }
559  }
560 
561  if (inexact) {
562  fpscr.ixc = 1;
563  }
564  }
565  // Reassemble and install the result.
566  uint32_t result = bits(mantissa, 9, 0);
567  replaceBits(result, 14, 10, exponent);
568  if (neg)
569  result |= (1 << 15);
570  return result;
571 }
572 
573 uint16_t
574 vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan,
575  uint32_t rMode, bool ahp, float op)
576 {
577  uint64_t opBits = fpToBits(op);
578  return vcvtFpFpH(fpscr, flush, defaultNan, rMode, ahp, opBits, false);
579 }
580 
581 uint16_t
582 vcvtFpDFpH(FPSCR &fpscr, bool flush, bool defaultNan,
583  uint32_t rMode, bool ahp, double op)
584 {
585  uint64_t opBits = fpToBits(op);
586  return vcvtFpFpH(fpscr, flush, defaultNan, rMode, ahp, opBits, true);
587 }
588 
589 static inline uint64_t
590 vcvtFpHFp(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op, bool isDouble)
591 {
592  uint32_t mWidth;
593  uint32_t eWidth;
594  uint32_t eHalfRange;
595  uint32_t sBitPos;
596 
597  if (isDouble) {
598  mWidth = 52;
599  eWidth = 11;
600  } else {
601  mWidth = 23;
602  eWidth = 8;
603  }
604  sBitPos = eWidth + mWidth;
605  eHalfRange = (1 << (eWidth-1)) - 1;
606 
607  // Extract the bitfields.
608  bool neg = bits(op, 15);
609  uint32_t exponent = bits(op, 14, 10);
610  uint64_t mantissa = bits(op, 9, 0);
611  // Do the conversion.
612  if (exponent == 0) {
613  if (mantissa != 0) {
614  // Normalize the value.
615  exponent = exponent + (eHalfRange - 15) + 1;
616  while (mantissa < (1 << 10)) {
617  mantissa = mantissa << 1;
618  exponent--;
619  }
620  }
621  mantissa = mantissa << (mWidth - 10);
622  } else if (exponent == 0x1f && !ahp) {
623  // Infinities and nans.
624  exponent = mask(eWidth);
625  if (mantissa != 0) {
626  // Nans.
627  mantissa = mantissa << (mWidth - 10);
628  if (bits(mantissa, mWidth-1) == 0) {
629  // Signalling nan.
630  fpscr.ioc = 1;
631  mantissa |= (((uint64_t) 1) << (mWidth-1));
632  }
633  if (defaultNan) {
634  mantissa &= ~mask(mWidth-1);
635  neg = false;
636  }
637  }
638  } else {
639  exponent = exponent + (eHalfRange - 15);
640  mantissa = mantissa << (mWidth - 10);
641  }
642  // Reassemble the result.
643  uint64_t result = bits(mantissa, mWidth-1, 0);
644  replaceBits(result, sBitPos-1, mWidth, exponent);
645  if (neg) {
646  result |= (((uint64_t) 1) << sBitPos);
647  }
648  return result;
649 }
650 
651 double
652 vcvtFpHFpD(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
653 {
654  double junk = 0.0;
655  uint64_t result;
656 
657  result = vcvtFpHFp(fpscr, defaultNan, ahp, op, true);
658  return bitsToFp(result, junk);
659 }
660 
661 float
662 vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
663 {
664  float junk = 0.0;
665  uint64_t result;
666 
667  result = vcvtFpHFp(fpscr, defaultNan, ahp, op, false);
668  return bitsToFp(result, junk);
669 }
670 
671 float
672 vfpUFixedToFpS(bool flush, bool defaultNan,
673  uint64_t val, uint8_t width, uint8_t imm)
674 {
675  fesetround(FeRoundNearest);
676  if (width == 16)
677  val = (uint16_t)val;
678  else if (width == 32)
679  val = (uint32_t)val;
680  else if (width != 64)
681  panic("Unsupported width %d", width);
682  float scale = powf(2.0, imm);
683  __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
684  feclearexcept(FeAllExceptions);
685  __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
686  return fixDivDest(flush, defaultNan, val / scale, (float)val, scale);
687 }
688 
689 float
690 vfpSFixedToFpS(bool flush, bool defaultNan,
691  int64_t val, uint8_t width, uint8_t imm)
692 {
693  fesetround(FeRoundNearest);
694  if (width == 16)
695  val = sext<16>(val & mask(16));
696  else if (width == 32)
697  val = sext<32>(val & mask(32));
698  else if (width != 64)
699  panic("Unsupported width %d", width);
700 
701  float scale = powf(2.0, imm);
702  __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
703  feclearexcept(FeAllExceptions);
704  __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
705  return fixDivDest(flush, defaultNan, val / scale, (float)val, scale);
706 }
707 
708 
709 double
710 vfpUFixedToFpD(bool flush, bool defaultNan,
711  uint64_t val, uint8_t width, uint8_t imm)
712 {
713  fesetround(FeRoundNearest);
714  if (width == 16)
715  val = (uint16_t)val;
716  else if (width == 32)
717  val = (uint32_t)val;
718  else if (width != 64)
719  panic("Unsupported width %d", width);
720 
721  double scale = pow(2.0, imm);
722  __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
723  feclearexcept(FeAllExceptions);
724  __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
725  return fixDivDest(flush, defaultNan, val / scale, (double)val, scale);
726 }
727 
728 double
729 vfpSFixedToFpD(bool flush, bool defaultNan,
730  int64_t val, uint8_t width, uint8_t imm)
731 {
732  fesetround(FeRoundNearest);
733  if (width == 16)
734  val = sext<16>(val & mask(16));
735  else if (width == 32)
736  val = sext<32>(val & mask(32));
737  else if (width != 64)
738  panic("Unsupported width %d", width);
739 
740  double scale = pow(2.0, imm);
741  __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
742  feclearexcept(FeAllExceptions);
743  __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
744  return fixDivDest(flush, defaultNan, val / scale, (double)val, scale);
745 }
746 
747 // This function implements a magic formula taken from the architecture
748 // reference manual. It was originally called recip_sqrt_estimate.
749 static double
751 {
752  int64_t q0, q1, s;
753  double r;
754  if (a < 0.5) {
755  q0 = (int64_t)(a * 512.0);
756  r = 1.0 / sqrt(((double)q0 + 0.5) / 512.0);
757  } else {
758  q1 = (int64_t)(a * 256.0);
759  r = 1.0 / sqrt(((double)q1 + 0.5) / 256.0);
760  }
761  s = (int64_t)(256.0 * r + 0.5);
762  return (double)s / 256.0;
763 }
764 
765 // This function is only intended for use in Neon instructions because
766 // it ignores certain bits in the FPSCR.
767 float
768 fprSqrtEstimate(FPSCR &fpscr, float op)
769 {
770  const uint32_t qnan = 0x7fc00000;
771  float junk = 0.0;
772  int fpClass = std::fpclassify(op);
773  if (fpClass == FP_NAN) {
774  if ((fpToBits(op) & qnan) != qnan)
775  fpscr.ioc = 1;
776  return bitsToFp(qnan, junk);
777  } else if (fpClass == FP_ZERO) {
778  fpscr.dzc = 1;
779  // Return infinity with the same sign as the operand.
780  return bitsToFp((std::signbit(op) << 31) |
781  (0xFF << 23) | (0 << 0), junk);
782  } else if (std::signbit(op)) {
783  // Set invalid op bit.
784  fpscr.ioc = 1;
785  return bitsToFp(qnan, junk);
786  } else if (fpClass == FP_INFINITE) {
787  return 0.0;
788  } else {
789  uint64_t opBits = fpToBits(op);
790  double scaled;
791  if (bits(opBits, 23)) {
792  scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) |
793  (ULL(0x3fd) << 52) | (bits(opBits, 31) << 63),
794  (double)0.0);
795  } else {
796  scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) |
797  (ULL(0x3fe) << 52) | (bits(opBits, 31) << 63),
798  (double)0.0);
799  }
800  uint64_t resultExp = (380 - bits(opBits, 30, 23)) / 2;
801 
802  uint64_t estimate = fpToBits(recipSqrtEstimate(scaled));
803 
804  return bitsToFp((bits(estimate, 63) << 31) |
805  (bits(resultExp, 7, 0) << 23) |
806  (bits(estimate, 51, 29) << 0), junk);
807  }
808 }
809 
810 uint32_t
812 {
813  if (bits(op, 31, 30) == 0) {
814  return -1;
815  } else {
816  double dpOp;
817  if (bits(op, 31)) {
818  dpOp = bitsToFp((ULL(0) << 63) |
819  (ULL(0x3fe) << 52) |
820  (bits((uint64_t)op, 30, 0) << 21) |
821  (0 << 0), (double)0.0);
822  } else {
823  dpOp = bitsToFp((ULL(0) << 63) |
824  (ULL(0x3fd) << 52) |
825  (bits((uint64_t)op, 29, 0) << 22) |
826  (0 << 0), (double)0.0);
827  }
828  uint64_t estimate = fpToBits(recipSqrtEstimate(dpOp));
829  return (1 << 31) | bits(estimate, 51, 21);
830  }
831 }
832 
833 // This function implements a magic formula taken from the architecture
834 // reference manual. It was originally called recip_estimate.
835 
836 static double
838 {
839  int64_t q, s;
840  double r;
841  q = (int64_t)(a * 512.0);
842  r = 1.0 / (((double)q + 0.5) / 512.0);
843  s = (int64_t)(256.0 * r + 0.5);
844  return (double)s / 256.0;
845 }
846 
847 // This function is only intended for use in Neon instructions because
848 // it ignores certain bits in the FPSCR.
849 float
850 fpRecipEstimate(FPSCR &fpscr, float op)
851 {
852  const uint32_t qnan = 0x7fc00000;
853  float junk = 0.0;
854  int fpClass = std::fpclassify(op);
855  if (fpClass == FP_NAN) {
856  if ((fpToBits(op) & qnan) != qnan)
857  fpscr.ioc = 1;
858  return bitsToFp(qnan, junk);
859  } else if (fpClass == FP_INFINITE) {
860  return bitsToFp(std::signbit(op) << 31, junk);
861  } else if (fpClass == FP_ZERO) {
862  fpscr.dzc = 1;
863  // Return infinity with the same sign as the operand.
864  return bitsToFp((std::signbit(op) << 31) |
865  (0xFF << 23) | (0 << 0), junk);
866  } else if (fabs(op) >= pow(2.0, 126)) {
867  fpscr.ufc = 1;
868  return bitsToFp(std::signbit(op) << 31, junk);
869  } else {
870  uint64_t opBits = fpToBits(op);
871  double scaled;
872  scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) |
873  (ULL(0x3fe) << 52) | (ULL(0) << 63),
874  (double)0.0);
875  uint64_t resultExp = 253 - bits(opBits, 30, 23);
876 
877  uint64_t estimate = fpToBits(recipEstimate(scaled));
878 
879  return bitsToFp((bits(opBits, 31) << 31) |
880  (bits(resultExp, 7, 0) << 23) |
881  (bits(estimate, 51, 29) << 0), junk);
882  }
883 }
884 
885 uint32_t
887 {
888  if (bits(op, 31) == 0) {
889  return -1;
890  } else {
891  double dpOp;
892  dpOp = bitsToFp((ULL(0) << 63) |
893  (ULL(0x3fe) << 52) |
894  (bits((uint64_t)op, 30, 0) << 21) |
895  (0 << 0), (double)0.0);
896  uint64_t estimate = fpToBits(recipEstimate(dpOp));
897  return (1 << 31) | bits(estimate, 51, 21);
898  }
899 }
900 
901 FPSCR
902 fpStandardFPSCRValue(const FPSCR &fpscr)
903 {
904  FPSCR new_fpscr(0);
905  new_fpscr.ahp = fpscr.ahp;
906  new_fpscr.dn = 1;
907  new_fpscr.fz = 1;
908  new_fpscr.fz16 = fpscr.fz16;
909  return new_fpscr;
910 };
911 
912 template <class fpType>
913 fpType
914 FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan,
915  fpType op1, fpType op2) const
916 {
917  done = true;
918  fpType junk = 0.0;
919  fpType dest = 0.0;
920  const bool single = (sizeof(fpType) == sizeof(float));
921  const uint64_t qnan =
922  single ? 0x7fc00000 : ULL(0x7ff8000000000000);
923  const bool nan1 = std::isnan(op1);
924  const bool nan2 = std::isnan(op2);
925  const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan);
926  const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan);
927  if (nan1 || nan2) {
928  if (defaultNan) {
929  dest = bitsToFp(qnan, junk);
930  } else if (signal1) {
931  dest = bitsToFp(fpToBits(op1) | qnan, junk);
932  } else if (signal2) {
933  dest = bitsToFp(fpToBits(op2) | qnan, junk);
934  } else if (nan1) {
935  dest = op1;
936  } else if (nan2) {
937  dest = op2;
938  }
939  if (signal1 || signal2) {
940  fpscr.ioc = 1;
941  }
942  } else {
943  done = false;
944  }
945  return dest;
946 }
947 
948 template
949 float FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan,
950  float op1, float op2) const;
951 template
952 double FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan,
953  double op1, double op2) const;
954 
955 // @TODO remove this function when we've finished switching all FMA code to use the new FPLIB
956 template <class fpType>
957 fpType
958 FpOp::ternaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType op3,
959  fpType (*func)(fpType, fpType, fpType),
960  bool flush, bool defaultNan, uint32_t rMode) const
961 {
962  const bool single = (sizeof(fpType) == sizeof(float));
963  fpType junk = 0.0;
964 
965  if (flush && (flushToZero(op1, op2) || flushToZero(op3)))
966  fpscr.idc = 1;
968  __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2), "=m" (op3), "=m" (state)
969  : "m" (op1), "m" (op2), "m" (op3), "m" (state));
970  fpType dest = func(op1, op2, op3);
971  __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest));
972 
973  int fpClass = std::fpclassify(dest);
974  // Get NAN behavior right. This varies between x86 and ARM.
975  if (fpClass == FP_NAN) {
976  const uint64_t qnan =
977  single ? 0x7fc00000 : ULL(0x7ff8000000000000);
978  const bool nan1 = std::isnan(op1);
979  const bool nan2 = std::isnan(op2);
980  const bool nan3 = std::isnan(op3);
981  const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan);
982  const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan);
983  const bool signal3 = nan3 && ((fpToBits(op3) & qnan) != qnan);
984  if ((!nan1 && !nan2 && !nan3) || (defaultNan == 1)) {
985  dest = bitsToFp(qnan, junk);
986  } else if (signal1) {
987  dest = bitsToFp(fpToBits(op1) | qnan, junk);
988  } else if (signal2) {
989  dest = bitsToFp(fpToBits(op2) | qnan, junk);
990  } else if (signal3) {
991  dest = bitsToFp(fpToBits(op3) | qnan, junk);
992  } else if (nan1) {
993  dest = op1;
994  } else if (nan2) {
995  dest = op2;
996  } else if (nan3) {
997  dest = op3;
998  }
999  } else if (flush && flushToZero(dest)) {
1000  feraiseexcept(FeUnderflow);
1001  } else if ((
1002  (single && (dest == bitsToFp(0x00800000, junk) ||
1003  dest == bitsToFp(0x80800000, junk))) ||
1004  (!single &&
1005  (dest == bitsToFp(ULL(0x0010000000000000), junk) ||
1006  dest == bitsToFp(ULL(0x8010000000000000), junk)))
1007  ) && rMode != VfpRoundZero) {
1008  /*
1009  * Correct for the fact that underflow is detected -before- rounding
1010  * in ARM and -after- rounding in x86.
1011  */
1012  fesetround(FeRoundZero);
1013  __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2), "=m" (op3)
1014  : "m" (op1), "m" (op2), "m" (op3));
1015  fpType temp = func(op1, op2, op2);
1016  __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp));
1017  if (flush && flushToZero(temp)) {
1018  dest = temp;
1019  }
1020  }
1021  finishVfp(fpscr, state, flush);
1022  return dest;
1023 }
1024 
1025 template
1026 float FpOp::ternaryOp(FPSCR &fpscr, float op1, float op2, float op3,
1027  float (*func)(float, float, float),
1028  bool flush, bool defaultNan, uint32_t rMode) const;
1029 template
1030 double FpOp::ternaryOp(FPSCR &fpscr, double op1, double op2, double op3,
1031  double (*func)(double, double, double),
1032  bool flush, bool defaultNan, uint32_t rMode) const;
1033 
1034 template <class fpType>
1035 fpType
1036 FpOp::binaryOp(FPSCR &fpscr, fpType op1, fpType op2,
1037  fpType (*func)(fpType, fpType),
1038  bool flush, bool defaultNan, uint32_t rMode) const
1039 {
1040  const bool single = (sizeof(fpType) == sizeof(float));
1041  fpType junk = 0.0;
1042 
1043  if (flush && flushToZero(op1, op2))
1044  fpscr.idc = 1;
1045  VfpSavedState state = prepFpState(rMode);
1046  __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2), "=m" (state)
1047  : "m" (op1), "m" (op2), "m" (state));
1048  fpType dest = func(op1, op2);
1049  __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest));
1050 
1051  // Get NAN behavior right. This varies between x86 and ARM.
1052  if (std::isnan(dest)) {
1053  const uint64_t qnan =
1054  single ? 0x7fc00000 : ULL(0x7ff8000000000000);
1055  const bool nan1 = std::isnan(op1);
1056  const bool nan2 = std::isnan(op2);
1057  const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan);
1058  const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan);
1059  if ((!nan1 && !nan2) || (defaultNan == 1)) {
1060  dest = bitsToFp(qnan, junk);
1061  } else if (signal1) {
1062  dest = bitsToFp(fpToBits(op1) | qnan, junk);
1063  } else if (signal2) {
1064  dest = bitsToFp(fpToBits(op2) | qnan, junk);
1065  } else if (nan1) {
1066  dest = op1;
1067  } else if (nan2) {
1068  dest = op2;
1069  }
1070  } else if (flush && flushToZero(dest)) {
1071  feraiseexcept(FeUnderflow);
1072  } else if ((
1073  (single && (dest == bitsToFp(0x00800000, junk) ||
1074  dest == bitsToFp(0x80800000, junk))) ||
1075  (!single &&
1076  (dest == bitsToFp(ULL(0x0010000000000000), junk) ||
1077  dest == bitsToFp(ULL(0x8010000000000000), junk)))
1078  ) && rMode != VfpRoundZero) {
1079  /*
1080  * Correct for the fact that underflow is detected -before- rounding
1081  * in ARM and -after- rounding in x86.
1082  */
1083  fesetround(FeRoundZero);
1084  __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2)
1085  : "m" (op1), "m" (op2));
1086  fpType temp = func(op1, op2);
1087  __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp));
1088  if (flush && flushToZero(temp)) {
1089  dest = temp;
1090  }
1091  }
1092  finishVfp(fpscr, state, flush);
1093  return dest;
1094 }
1095 
1096 template
1097 float FpOp::binaryOp(FPSCR &fpscr, float op1, float op2,
1098  float (*func)(float, float),
1099  bool flush, bool defaultNan, uint32_t rMode) const;
1100 template
1101 double FpOp::binaryOp(FPSCR &fpscr, double op1, double op2,
1102  double (*func)(double, double),
1103  bool flush, bool defaultNan, uint32_t rMode) const;
1104 
1105 template <class fpType>
1106 fpType
1107 FpOp::unaryOp(FPSCR &fpscr, fpType op1, fpType (*func)(fpType),
1108  bool flush, uint32_t rMode) const
1109 {
1110  const bool single = (sizeof(fpType) == sizeof(float));
1111  fpType junk = 0.0;
1112 
1113  if (flush && flushToZero(op1))
1114  fpscr.idc = 1;
1115  VfpSavedState state = prepFpState(rMode);
1116  __asm__ __volatile__ ("" : "=m" (op1), "=m" (state)
1117  : "m" (op1), "m" (state));
1118  fpType dest = func(op1);
1119  __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest));
1120 
1121  // Get NAN behavior right. This varies between x86 and ARM.
1122  if (std::isnan(dest)) {
1123  const uint64_t qnan =
1124  single ? 0x7fc00000 : ULL(0x7ff8000000000000);
1125  const bool nan = std::isnan(op1);
1126  if (!nan || fpscr.dn == 1) {
1127  dest = bitsToFp(qnan, junk);
1128  } else if (nan) {
1129  dest = bitsToFp(fpToBits(op1) | qnan, junk);
1130  }
1131  } else if (flush && flushToZero(dest)) {
1132  feraiseexcept(FeUnderflow);
1133  } else if ((
1134  (single && (dest == bitsToFp(0x00800000, junk) ||
1135  dest == bitsToFp(0x80800000, junk))) ||
1136  (!single &&
1137  (dest == bitsToFp(ULL(0x0010000000000000), junk) ||
1138  dest == bitsToFp(ULL(0x8010000000000000), junk)))
1139  ) && rMode != VfpRoundZero) {
1140  /*
1141  * Correct for the fact that underflow is detected -before- rounding
1142  * in ARM and -after- rounding in x86.
1143  */
1144  fesetround(FeRoundZero);
1145  __asm__ __volatile__ ("" : "=m" (op1) : "m" (op1));
1146  fpType temp = func(op1);
1147  __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp));
1148  if (flush && flushToZero(temp)) {
1149  dest = temp;
1150  }
1151  }
1152  finishVfp(fpscr, state, flush);
1153  return dest;
1154 }
1155 
1156 template
1157 float FpOp::unaryOp(FPSCR &fpscr, float op1, float (*func)(float),
1158  bool flush, uint32_t rMode) const;
1159 template
1160 double FpOp::unaryOp(FPSCR &fpscr, double op1, double (*func)(double),
1161  bool flush, uint32_t rMode) const;
1162 
1165 {
1166  if (wide) {
1167  stride *= 2;
1168  }
1169  unsigned offset = idx % 8;
1170  idx = (IntRegIndex)(idx - offset);
1171  offset += stride;
1172  idx = (IntRegIndex)(idx + (offset % 8));
1173  return idx;
1174 }
1175 
1176 void
1178 {
1179  unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
1180  assert(!inScalarBank(dest));
1181  dest = addStride(dest, stride);
1182  op1 = addStride(op1, stride);
1183  if (!inScalarBank(op2)) {
1184  op2 = addStride(op2, stride);
1185  }
1186 }
1187 
1188 void
1190 {
1191  unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
1192  assert(!inScalarBank(dest));
1193  dest = addStride(dest, stride);
1194  if (!inScalarBank(op1)) {
1195  op1 = addStride(op1, stride);
1196  }
1197 }
1198 
1199 void
1201 {
1202  unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
1203  assert(!inScalarBank(dest));
1204  dest = addStride(dest, stride);
1205 }
1206 
1207 }
ArmISA::FpRegRegRegCondOp::generateDisassembly
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:130
ArmISA::FpCondCompRegOp::defCc
uint8_t defCc
Definition: vfp.hh:885
ArmISA::vcvtFpSFpH
uint16_t vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, float op)
Definition: vfp.cc:574
replaceBits
void replaceBits(T &val, int first, int last, B bit_val)
A convenience function to replace bits first to last of val with bit_val in place.
Definition: bitfield.hh:179
ArmISA::FpOp::ternaryOp
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:958
ArmISA::FpCondCompRegOp::op1
IntRegIndex op1
Definition: vfp.hh:883
ArmISA::FpCondCompRegOp::condCode
ConditionCode condCode
Definition: vfp.hh:884
ArmISA::vfpSFixedToFpS
float vfpSFixedToFpS(bool flush, bool defaultNan, int64_t val, uint8_t width, uint8_t imm)
Definition: vfp.cc:690
ArmISA::FpCondSelOp::condCode
ConditionCode condCode
Definition: vfp.hh:902
ArmISA::FpRegRegRegCondOp::dest
IntRegIndex dest
Definition: vfp.hh:992
ArmISA::FeInvalid
@ FeInvalid
Definition: vfp.hh:86
ArmISA::FeUnderflow
@ FeUnderflow
Definition: vfp.hh:88
ArmISA::FeInexact
@ FeInexact
Definition: vfp.hh:85
ArmISA::width
Bitfield< 4 > width
Definition: miscregs_types.hh:68
ArmISA::FpRegRegOp::generateDisassembly
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:80
vfp.hh
ArmISA::VfpRoundDown
@ VfpRoundDown
Definition: vfp.hh:104
ArmISA::FpCondSelOp::generateDisassembly
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:64
Loader::SymbolTable
Definition: symtab.hh:59
ArmISA::IntRegIndex
IntRegIndex
Definition: intregs.hh:51
ArmISA::FeDivByZero
@ FeDivByZero
Definition: vfp.hh:84
ArmISA::q
Bitfield< 27 > q
Definition: miscregs_types.hh:52
ArmISA::fixDivDest< double >
template double fixDivDest< double >(bool flush, bool defaultNan, double val, double op1, double op2)
X86ISA::op
Bitfield< 4 > op
Definition: types.hh:78
ArmISA::ArmStaticInst::printIntReg
void printIntReg(std::ostream &os, RegIndex reg_idx, uint8_t opWidth=0) const
Print a register name for disassembly given the unique dependence tag number (FP or int).
Definition: static_inst.cc:296
ArmISA::FpOp::unaryOp
fpType unaryOp(FPSCR &fpscr, fpType op1, fpType(*func)(fpType), bool flush, uint32_t rMode) const
Definition: vfp.cc:1107
ArmISA::ahp
Bitfield< 26 > ahp
Definition: miscregs_types.hh:445
ArmISA::FpCondSelOp::dest
IntRegIndex dest
Definition: vfp.hh:901
ArmISA::FeOverflow
@ FeOverflow
Definition: vfp.hh:87
ArmISA::bitsToFp
static float bitsToFp(uint64_t, float)
Definition: vfp.hh:178
ArmISA
Definition: ccregs.hh:41
X86ISA::scale
scale
Definition: types.hh:92
ArmISA::FeRoundNearest
@ FeRoundNearest
Definition: vfp.hh:95
ArmISA::FpCondSelOp::op1
IntRegIndex op1
Definition: vfp.hh:901
ArmISA::VfpSavedState
int VfpSavedState
Definition: vfp.hh:211
ArmISA::FpRegRegRegImmOp::op2
IntRegIndex op2
Definition: vfp.hh:1037
ArmISA::FpOp::processNans
fpType processNans(FPSCR &fpscr, bool &done, bool defaultNan, fpType op1, fpType op2) const
Definition: vfp.cc:914
ArmISA::FpRegImmOp::generateDisassembly
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:92
ArmISA::FpRegRegRegImmOp::dest
IntRegIndex dest
Definition: vfp.hh:1035
ArmISA::VfpMacroOp::wide
bool wide
Definition: vfp.hh:461
ArmISA::unsignedRSqrtEstimate
uint32_t unsignedRSqrtEstimate(uint32_t op)
Definition: vfp.cc:811
ArmISA::FpRegRegRegRegOp::generateDisassembly
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:146
ArmISA::fpToBits
static uint32_t fpToBits(float)
Definition: vfp.hh:154
ArmISA::fixFpSFpDDest
double fixFpSFpDDest(FPSCR fpscr, float val)
Definition: vfp.cc:370
ArmISA::fixFpDFpSDest
float fixFpDFpSDest(FPSCR fpscr, double val)
Definition: vfp.cc:334
ArmISA::ss
Bitfield< 21 > ss
Definition: miscregs_types.hh:56
ArmISA::a
Bitfield< 8 > a
Definition: miscregs_types.hh:62
ArmISA::fpRecipEstimate
float fpRecipEstimate(FPSCR &fpscr, float op)
Definition: vfp.cc:850
ArmISA::FeAllExceptions
@ FeAllExceptions
Definition: vfp.hh:89
ArmISA::fpStandardFPSCRValue
FPSCR fpStandardFPSCRValue(const FPSCR &fpscr)
Definition: vfp.cc:902
ArmISA::FeRoundUpward
@ FeRoundUpward
Definition: vfp.hh:97
ArmISA::FpRegRegRegImmOp::generateDisassembly
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:162
sc_dt::neg
void neg(sc_fxval &c, const sc_fxnum &a)
Definition: sc_fxnum.hh:2270
ArmISA::vcvtFpHFpS
float vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
Definition: vfp.cc:662
ArmISA::FpRegRegRegCondOp::op2
IntRegIndex op2
Definition: vfp.hh:994
ArmISA::imm
Bitfield< 7, 0 > imm
Definition: types.hh:141
ArmISA::FpRegRegRegImmOp::op1
IntRegIndex op1
Definition: vfp.hh:1036
MipsISA::pc
Bitfield< 4 > pc
Definition: pra_constants.hh:240
ArmISA::vcvtFpFpH
static uint16_t vcvtFpFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, uint64_t opBits, bool isDouble)
Definition: vfp.cc:402
ArmISA::FpRegRegRegRegOp::dest
IntRegIndex dest
Definition: vfp.hh:1014
MipsISA::r
r
Definition: pra_constants.hh:95
ArmISA::fixDest< float >
template float fixDest< float >(bool flush, bool defaultNan, float val, float op1)
ArmISA::FpRegRegImmOp::op1
IntRegIndex op1
Definition: vfp.hh:955
ArmISA::mode
Bitfield< 4, 0 > mode
Definition: miscregs_types.hh:70
ArmISA::vcvtFpDFpH
uint16_t vcvtFpDFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, double op)
Definition: vfp.cc:582
ArmISA::FpRegRegOp::dest
IntRegIndex dest
Definition: vfp.hh:918
ArmISA::recipEstimate
static double recipEstimate(double a)
Definition: vfp.cc:837
ArmISA::FpRegRegImmOp::imm
uint64_t imm
Definition: vfp.hh:956
ArmISA::FpRegImmOp::dest
IntRegIndex dest
Definition: vfp.hh:936
ArmISA::vcvtFpHFpD
double vcvtFpHFpD(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
Definition: vfp.cc:652
ArmISA::FpRegRegRegCondOp::op1
IntRegIndex op1
Definition: vfp.hh:993
ArmISA::FpRegRegRegRegOp::op3
IntRegIndex op3
Definition: vfp.hh:1017
ArmISA::VfpMacroOp::inScalarBank
static bool inScalarBank(IntRegIndex idx)
Definition: vfp.hh:455
ArmISA::FpRegRegOp::op1
IntRegIndex op1
Definition: vfp.hh:919
ArmISA::FpRegRegRegRegOp::op2
IntRegIndex op2
Definition: vfp.hh:1016
ArmISA::vfpSFixedToFpD
double vfpSFixedToFpD(bool flush, bool defaultNan, int64_t val, uint8_t width, uint8_t imm)
Definition: vfp.cc:729
ArmISA::FpRegRegRegOp::op2
IntRegIndex op2
Definition: vfp.hh:975
ArmISA::FpRegRegImmOp::generateDisassembly
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:103
X86ISA::val
Bitfield< 63 > val
Definition: misc.hh:769
ArmISA::FpCondCompRegOp::op2
IntRegIndex op2
Definition: vfp.hh:883
ArmISA::ArmStaticInst::printCondition
void printCondition(std::ostream &os, unsigned code, bool noImplicit=false) const
Definition: static_inst.cc:414
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
ArmISA::FpRegRegRegOp::dest
IntRegIndex dest
Definition: vfp.hh:973
ArmISA::FpRegRegImmOp::dest
IntRegIndex dest
Definition: vfp.hh:954
ArmISA::fixDest< double >
template double fixDest< double >(bool flush, bool defaultNan, double val, double op1)
ArmISA::FpRegRegRegOp::generateDisassembly
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:116
ArmISA::rMode
Bitfield< 23, 22 > rMode
Definition: miscregs_types.hh:442
ArmISA::VfpRoundUpward
@ VfpRoundUpward
Definition: vfp.hh:103
ArmISA::ArmStaticInst::printFloatReg
void printFloatReg(std::ostream &os, RegIndex reg_idx) const
Definition: static_inst.cc:342
ArmISA::VfpMacroOp::addStride
IntRegIndex addStride(IntRegIndex idx, unsigned stride)
Definition: vfp.cc:1164
ArmISA::FpRegRegRegRegOp::op1
IntRegIndex op1
Definition: vfp.hh:1015
ArmISA::FpRegImmOp::imm
uint64_t imm
Definition: vfp.hh:937
ArmISA::fprSqrtEstimate
float fprSqrtEstimate(FPSCR &fpscr, float op)
Definition: vfp.cc:768
ArmISA::FeRoundDown
@ FeRoundDown
Definition: vfp.hh:94
ArmISA::VfpRoundNearest
@ VfpRoundNearest
Definition: vfp.hh:102
StaticInst::machInst
const ExtMachInst machInst
The binary machine instruction.
Definition: static_inst.hh:243
ArmISA::vfpUFixedToFpS
float vfpUFixedToFpS(bool flush, bool defaultNan, uint64_t val, uint8_t width, uint8_t imm)
Definition: vfp.cc:672
ArmISA::FpCondSelOp::op2
IntRegIndex op2
Definition: vfp.hh:901
ArmISA::FpCondCompRegOp::generateDisassembly
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Definition: vfp.cc:49
ArmISA::ArmStaticInst::printMnemonic
void printMnemonic(std::ostream &os, const std::string &suffix="", bool withPred=true, bool withCond64=false, ConditionCode cond64=COND_UC) const
Definition: static_inst.cc:374
ArmISA::fixDivDest
fpType fixDivDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2)
Definition: vfp.cc:299
ccprintf
void ccprintf(cp::Print &print)
Definition: cprintf.hh:127
ArmISA::vfpUFixedToFpD
double vfpUFixedToFpD(bool flush, bool defaultNan, uint64_t val, uint8_t width, uint8_t imm)
Definition: vfp.cc:710
ArmISA::stride
Bitfield< 21, 20 > stride
Definition: miscregs_types.hh:441
ArmISA::prepFpState
VfpSavedState prepFpState(uint32_t rMode)
Definition: vfp.cc:180
ArmISA::finishVfp
void finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush, FPSCR mask)
Definition: vfp.cc:202
ArmISA::unsignedRecipEstimate
uint32_t unsignedRecipEstimate(uint32_t op)
Definition: vfp.cc:886
ArmISA::VfpRoundZero
@ VfpRoundZero
Definition: vfp.hh:105
ArmISA::flushToZero
flushToZero
Definition: miscregs_types.hh:471
ArmISA::FpRegRegRegOp::op1
IntRegIndex op1
Definition: vfp.hh:974
ArmISA::fixDivDest< float >
template float fixDivDest< float >(bool flush, bool defaultNan, float val, float op1, float op2)
ArmISA::s
Bitfield< 4 > s
Definition: miscregs_types.hh:556
ArmISA::vcvtFpHFp
static uint64_t vcvtFpHFp(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op, bool isDouble)
Definition: vfp.cc:590
ArmISA::FpOp::binaryOp
fpType binaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType(*func)(fpType, fpType), bool flush, bool defaultNan, uint32_t rMode) const
Definition: vfp.cc:1036
ArmISA::VfpMacroOp::nextIdxs
void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2)
Definition: vfp.cc:1177
ArmISA::FpRegRegRegImmOp::imm
uint64_t imm
Definition: vfp.hh:1038
ArmISA::FpRegRegRegCondOp::cond
ConditionCode cond
Definition: vfp.hh:995
ArmISA::fixDest
fpType fixDest(bool flush, bool defaultNan, fpType val, fpType op1)
Definition: vfp.cc:228
ULL
#define ULL(N)
uint64_t constant
Definition: types.hh:50
ArmISA::mask
Bitfield< 28, 24 > mask
Definition: miscregs_types.hh:711
ArmISA::FeRoundZero
@ FeRoundZero
Definition: vfp.hh:96
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
ArmISA::recipSqrtEstimate
static double recipSqrtEstimate(double a)
Definition: vfp.cc:750
ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:153
bits
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:75

Generated on Wed Sep 30 2020 14:02:00 for gem5 by doxygen 1.8.17