Go to the documentation of this file.
106 std::stringstream
ss;
119 std::stringstream
ss;
134 std::stringstream
ss;
149 std::stringstream
ss;
165 std::stringstream
ss;
182 int roundingMode = fegetround();
205 bool underflow =
false;
220 if ((exceptions &
FeInexact) && !(underflow && flush) &&
mask.ixc) {
226 template <
class fpType>
230 int fpClass = std::fpclassify(
val);
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) {
241 }
else if (fpClass == FP_SUBNORMAL && flush == 1) {
243 uint64_t bitMask =
ULL(0x1) << (
sizeof(fpType) * 8 - 1);
256 template <
class fpType>
258 fixDest(
bool flush,
bool defaultNan, fpType
val, fpType op1, fpType op2)
260 int fpClass = std::fpclassify(
val);
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) {
271 }
else if (signal1) {
273 }
else if (signal2) {
280 }
else if (fpClass == FP_SUBNORMAL && flush) {
282 uint64_t bitMask =
ULL(0x1) << (
sizeof(fpType) * 8 - 1);
292 float val,
float op1,
float op2);
295 double val,
double op1,
double op2);
297 template <
class fpType>
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) ||
309 __asm__ __volatile__(
"" :
"=m" (op1) :
"m" (op1));
312 __asm__ __volatile__(
"" :
"=m" (temp) :
"m" (temp));
321 __asm__ __volatile__(
"" ::
"m" (temp));
328 float val,
float op1,
float op2);
331 double val,
double op1,
double op2);
336 const float junk = 0.0;
338 if (std::isnan(
val)) {
340 uint32_t op1Bits =
bits(valBits, 50, 29) |
342 (
bits(valBits, 63) << 31);
345 float mid =
fixDest(fpscr.fz, fpscr.dn, (
float)
val, op1);
350 if (mid ==
bitsToFp(0x00800000, junk) ||
351 mid ==
bitsToFp(0x80800000, junk)) {
352 __asm__ __volatile__(
"" :
"=m" (
val) :
"m" (
val));
355 __asm__ __volatile__(
"" :
"=m" (temp) :
"m" (temp));
364 __asm__ __volatile__(
"" ::
"m" (temp));
372 const double junk = 0.0;
374 if (std::isnan(
val)) {
376 uint64_t op1Bits = ((uint64_t)
bits(valBits, 21, 0) << 29) |
378 ((uint64_t)
bits(valBits, 31) << 63);
381 double mid =
fixDest(fpscr.fz, fpscr.dn, (
double)
val, op1);
382 if (mid ==
bitsToFp(
ULL(0x0010000000000000), junk) ||
384 __asm__ __volatile__(
"" :
"=m" (
val) :
"m" (
val));
387 __asm__ __volatile__(
"" :
"=m" (temp) :
"m" (temp));
396 __asm__ __volatile__(
"" ::
"m" (temp));
401 static inline uint16_t
403 uint32_t
rMode,
bool ahp, uint64_t opBits,
bool isDouble)
417 sBitPos = eWidth + mWidth;
418 eHalfRange = (1 << (eWidth-1)) - 1;
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);
426 uint64_t extra = oldMantissa &
mask(mWidth - 10);
427 if (exponent ==
mask(eWidth)) {
428 if (oldMantissa != 0) {
430 if (
bits(mantissa, 9) == 0) {
438 }
else if (defaultNan) {
444 mantissa |= (1 << 9);
456 }
else if (exponent == 0 && oldMantissa == 0) {
461 bool inexact = (extra != 0);
469 if (inexact || fpscr.ufe)
478 (extra == (1 << 9) &&
bits(mantissa, 0))))) {
483 if (mantissa == (1 << 10)) {
492 bool topOne =
bits(extra, mWidth - 10 - 1);
493 bool restZeros =
bits(extra, mWidth - 10 - 2, 0) == 0;
495 if (exponent <= (eHalfRange - 15)) {
497 mantissa |= (1 << 10);
498 while (mantissa && exponent <= (eHalfRange - 15)) {
499 restZeros = restZeros && !topOne;
500 topOne =
bits(mantissa, 0);
501 mantissa = mantissa >> 1;
504 if (topOne || !restZeros)
509 exponent -= (eHalfRange - 15);
512 if (exponent == 0 && (inexact || fpscr.ufe)) {
519 bool nonZero = topOne || !restZeros;
523 (!restZeros ||
bits(mantissa, 0)))) {
528 if (mantissa == (1 << 10)) {
535 if (exponent >= 0x20) {
543 if (exponent >= 0x1f) {
566 uint32_t result =
bits(mantissa, 9, 0);
589 static inline uint64_t
604 sBitPos = eWidth + mWidth;
605 eHalfRange = (1 << (eWidth-1)) - 1;
609 uint32_t exponent =
bits(
op, 14, 10);
610 uint64_t mantissa =
bits(
op, 9, 0);
615 exponent = exponent + (eHalfRange - 15) + 1;
616 while (mantissa < (1 << 10)) {
617 mantissa = mantissa << 1;
621 mantissa = mantissa << (mWidth - 10);
622 }
else if (exponent == 0x1f && !
ahp) {
624 exponent =
mask(eWidth);
627 mantissa = mantissa << (mWidth - 10);
628 if (
bits(mantissa, mWidth-1) == 0) {
631 mantissa |= (((uint64_t) 1) << (mWidth-1));
634 mantissa &= ~
mask(mWidth-1);
639 exponent = exponent + (eHalfRange - 15);
640 mantissa = mantissa << (mWidth - 10);
643 uint64_t result =
bits(mantissa, mWidth-1, 0);
646 result |= (((uint64_t) 1) << sBitPos);
678 else if (
width == 32)
680 else if (
width != 64)
683 __asm__ __volatile__(
"" :
"=m" (
scale) :
"m" (
scale));
685 __asm__ __volatile__(
"" :
"=m" (
scale) :
"m" (
scale));
696 else if (
width == 32)
698 else if (
width != 64)
702 __asm__ __volatile__(
"" :
"=m" (
scale) :
"m" (
scale));
704 __asm__ __volatile__(
"" :
"=m" (
scale) :
"m" (
scale));
716 else if (
width == 32)
718 else if (
width != 64)
722 __asm__ __volatile__(
"" :
"=m" (
scale) :
"m" (
scale));
724 __asm__ __volatile__(
"" :
"=m" (
scale) :
"m" (
scale));
735 else if (
width == 32)
737 else if (
width != 64)
741 __asm__ __volatile__(
"" :
"=m" (
scale) :
"m" (
scale));
743 __asm__ __volatile__(
"" :
"=m" (
scale) :
"m" (
scale));
755 q0 = (int64_t)(
a * 512.0);
756 r = 1.0 / sqrt(((
double)q0 + 0.5) / 512.0);
758 q1 = (int64_t)(
a * 256.0);
759 r = 1.0 / sqrt(((
double)q1 + 0.5) / 256.0);
761 s = (int64_t)(256.0 *
r + 0.5);
762 return (
double)
s / 256.0;
770 const uint32_t qnan = 0x7fc00000;
772 int fpClass = std::fpclassify(
op);
773 if (fpClass == FP_NAN) {
777 }
else if (fpClass == FP_ZERO) {
781 (0xFF << 23) | (0 << 0), junk);
782 }
else if (std::signbit(
op)) {
786 }
else if (fpClass == FP_INFINITE) {
791 if (
bits(opBits, 23)) {
792 scaled =
bitsToFp((0 << 0) | (
bits(opBits, 22, 0) << 29) |
793 (
ULL(0x3fd) << 52) | (
bits(opBits, 31) << 63),
796 scaled =
bitsToFp((0 << 0) | (
bits(opBits, 22, 0) << 29) |
797 (
ULL(0x3fe) << 52) | (
bits(opBits, 31) << 63),
800 uint64_t resultExp = (380 -
bits(opBits, 30, 23)) / 2;
805 (
bits(resultExp, 7, 0) << 23) |
806 (
bits(estimate, 51, 29) << 0), junk);
813 if (
bits(
op, 31, 30) == 0) {
820 (
bits((uint64_t)
op, 30, 0) << 21) |
821 (0 << 0), (
double)0.0);
825 (
bits((uint64_t)
op, 29, 0) << 22) |
826 (0 << 0), (
double)0.0);
829 return (1 << 31) |
bits(estimate, 51, 21);
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;
852 const uint32_t qnan = 0x7fc00000;
854 int fpClass = std::fpclassify(
op);
855 if (fpClass == FP_NAN) {
859 }
else if (fpClass == FP_INFINITE) {
860 return bitsToFp(std::signbit(
op) << 31, junk);
861 }
else if (fpClass == FP_ZERO) {
865 (0xFF << 23) | (0 << 0), junk);
866 }
else if (fabs(
op) >= pow(2.0, 126)) {
868 return bitsToFp(std::signbit(
op) << 31, junk);
872 scaled =
bitsToFp((0 << 0) | (
bits(opBits, 22, 0) << 29) |
873 (
ULL(0x3fe) << 52) | (
ULL(0) << 63),
875 uint64_t resultExp = 253 -
bits(opBits, 30, 23);
880 (
bits(resultExp, 7, 0) << 23) |
881 (
bits(estimate, 51, 29) << 0), junk);
894 (
bits((uint64_t)
op, 30, 0) << 21) |
895 (0 << 0), (
double)0.0);
897 return (1 << 31) |
bits(estimate, 51, 21);
905 new_fpscr.ahp = fpscr.ahp;
908 new_fpscr.fz16 = fpscr.fz16;
912 template <
class fpType>
915 fpType op1, fpType op2)
const
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);
930 }
else if (signal1) {
932 }
else if (signal2) {
939 if (signal1 || signal2) {
950 float op1,
float op2)
const;
953 double op1,
double op2)
const;
956 template <
class fpType>
959 fpType (*func)(fpType, fpType, fpType),
960 bool flush,
bool defaultNan, uint32_t
rMode)
const
962 const bool single = (
sizeof(fpType) ==
sizeof(
float));
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));
973 int fpClass = std::fpclassify(dest);
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)) {
986 }
else if (signal1) {
988 }
else if (signal2) {
990 }
else if (signal3) {
1002 (single && (dest ==
bitsToFp(0x00800000, junk) ||
1003 dest ==
bitsToFp(0x80800000, junk))) ||
1005 (dest ==
bitsToFp(
ULL(0x0010000000000000), junk) ||
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));
1027 float (*func)(
float,
float,
float),
1028 bool flush,
bool defaultNan, uint32_t
rMode)
const;
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;
1034 template <
class fpType>
1037 fpType (*func)(fpType, fpType),
1038 bool flush,
bool defaultNan, uint32_t
rMode)
const
1040 const bool single = (
sizeof(fpType) ==
sizeof(
float));
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));
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)) {
1061 }
else if (signal1) {
1063 }
else if (signal2) {
1073 (single && (dest ==
bitsToFp(0x00800000, junk) ||
1074 dest ==
bitsToFp(0x80800000, junk))) ||
1076 (dest ==
bitsToFp(
ULL(0x0010000000000000), junk) ||
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));
1098 float (*func)(
float,
float),
1099 bool flush,
bool defaultNan, uint32_t
rMode)
const;
1102 double (*func)(
double,
double),
1103 bool flush,
bool defaultNan, uint32_t
rMode)
const;
1105 template <
class fpType>
1108 bool flush, uint32_t
rMode)
const
1110 const bool single = (
sizeof(fpType) ==
sizeof(
float));
1116 __asm__ __volatile__ (
"" :
"=m" (op1),
"=m" (state)
1117 :
"m" (op1),
"m" (state));
1118 fpType dest = func(op1);
1119 __asm__ __volatile__ (
"" :
"=m" (dest) :
"m" (dest));
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) {
1134 (single && (dest ==
bitsToFp(0x00800000, junk) ||
1135 dest ==
bitsToFp(0x80800000, junk))) ||
1137 (dest ==
bitsToFp(
ULL(0x0010000000000000), junk) ||
1145 __asm__ __volatile__ (
"" :
"=m" (op1) :
"m" (op1));
1146 fpType temp = func(op1);
1147 __asm__ __volatile__ (
"" :
"=m" (temp) :
"m" (temp));
1157 float FpOp::unaryOp(FPSCR &fpscr,
float op1,
float (*func)(
float),
1158 bool flush, uint32_t
rMode)
const;
1160 double FpOp::unaryOp(FPSCR &fpscr,
double op1,
double (*func)(
double),
1161 bool flush, uint32_t
rMode)
const;
1169 unsigned offset = idx % 8;
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
uint16_t vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, float op)
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.
fpType ternaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType op3, fpType(*func)(fpType, fpType, fpType), bool flush, bool defaultNan, uint32_t rMode) const
float vfpSFixedToFpS(bool flush, bool defaultNan, int64_t val, uint8_t width, uint8_t imm)
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
template double fixDivDest< double >(bool flush, bool defaultNan, double val, double op1, double op2)
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).
fpType unaryOp(FPSCR &fpscr, fpType op1, fpType(*func)(fpType), bool flush, uint32_t rMode) const
static float bitsToFp(uint64_t, float)
fpType processNans(FPSCR &fpscr, bool &done, bool defaultNan, fpType op1, fpType op2) const
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
uint32_t unsignedRSqrtEstimate(uint32_t op)
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
static uint32_t fpToBits(float)
double fixFpSFpDDest(FPSCR fpscr, float val)
float fixFpDFpSDest(FPSCR fpscr, double val)
float fpRecipEstimate(FPSCR &fpscr, float op)
FPSCR fpStandardFPSCRValue(const FPSCR &fpscr)
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
void neg(sc_fxval &c, const sc_fxnum &a)
float vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
static uint16_t vcvtFpFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, uint64_t opBits, bool isDouble)
template float fixDest< float >(bool flush, bool defaultNan, float val, float op1)
uint16_t vcvtFpDFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, double op)
static double recipEstimate(double a)
double vcvtFpHFpD(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
static bool inScalarBank(IntRegIndex idx)
double vfpSFixedToFpD(bool flush, bool defaultNan, int64_t val, uint8_t width, uint8_t imm)
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
void printCondition(std::ostream &os, unsigned code, bool noImplicit=false) const
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
template double fixDest< double >(bool flush, bool defaultNan, double val, double op1)
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
void printFloatReg(std::ostream &os, RegIndex reg_idx) const
IntRegIndex addStride(IntRegIndex idx, unsigned stride)
float fprSqrtEstimate(FPSCR &fpscr, float op)
const ExtMachInst machInst
The binary machine instruction.
float vfpUFixedToFpS(bool flush, bool defaultNan, uint64_t val, uint8_t width, uint8_t imm)
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
void printMnemonic(std::ostream &os, const std::string &suffix="", bool withPred=true, bool withCond64=false, ConditionCode cond64=COND_UC) const
fpType fixDivDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2)
void ccprintf(cp::Print &print)
double vfpUFixedToFpD(bool flush, bool defaultNan, uint64_t val, uint8_t width, uint8_t imm)
Bitfield< 21, 20 > stride
VfpSavedState prepFpState(uint32_t rMode)
void finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush, FPSCR mask)
uint32_t unsignedRecipEstimate(uint32_t op)
template float fixDivDest< float >(bool flush, bool defaultNan, float val, float op1, float op2)
static uint64_t vcvtFpHFp(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op, bool isDouble)
fpType binaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType(*func)(fpType, fpType), bool flush, bool defaultNan, uint32_t rMode) const
void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2)
fpType fixDest(bool flush, bool defaultNan, fpType val, fpType op1)
#define ULL(N)
uint64_t constant
#define panic(...)
This implements a cprintf based panic() function.
static double recipSqrtEstimate(double a)
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Generated on Wed Sep 30 2020 14:02:00 for gem5 by doxygen 1.8.17