93a94,107
> std::string
> FpRegRegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
> {
> std::stringstream ss;
> printMnemonic(ss);
> printReg(ss, dest + FP_Base_DepTag);
> ss << ", ";
> printReg(ss, op1 + FP_Base_DepTag);
> ss << ", ";
> printReg(ss, op2 + FP_Base_DepTag);
> ccprintf(ss, ", #%d", imm);
> return ss.str();
> }
>
120c134
< finishVfp(FPSCR &fpscr, VfpSavedState state)
---
> finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush)
137c151
< if ((exceptions & FeInexact) && !(underflow && fpscr.fz)) {
---
> if ((exceptions & FeInexact) && !(underflow && flush)) {
145c159
< fixDest(FPSCR fpscr, fpType val, fpType op1)
---
> fixDest(bool flush, bool defaultNan, fpType val, fpType op1)
153c167
< if (!nan || (fpscr.dn == 1)) {
---
> if (!nan || defaultNan) {
158c172
< } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) {
---
> } else if (fpClass == FP_SUBNORMAL && flush == 1) {
169c183
< float fixDest<float>(FPSCR fpscr, float val, float op1);
---
> float fixDest<float>(bool flush, bool defaultNan, float val, float op1);
171c185
< double fixDest<double>(FPSCR fpscr, double val, double op1);
---
> double fixDest<double>(bool flush, bool defaultNan, double val, double op1);
175c189
< fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2)
---
> fixDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2)
186c200
< if ((!nan1 && !nan2) || (fpscr.dn == 1)) {
---
> if ((!nan1 && !nan2) || defaultNan) {
197c211
< } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) {
---
> } else if (fpClass == FP_SUBNORMAL && flush) {
208c222,223
< float fixDest<float>(FPSCR fpscr, float val, float op1, float op2);
---
> float fixDest<float>(bool flush, bool defaultNan,
> float val, float op1, float op2);
210c225,226
< double fixDest<double>(FPSCR fpscr, double val, double op1, double op2);
---
> double fixDest<double>(bool flush, bool defaultNan,
> double val, double op1, double op2);
214c230
< fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2)
---
> fixDivDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2)
216c232
< fpType mid = fixDest(fpscr, val, op1, op2);
---
> fpType mid = fixDest(flush, defaultNan, val, op1, op2);
231c247
< if (fpscr.fz) {
---
> if (flush) {
242c258,259
< float fixDivDest<float>(FPSCR fpscr, float val, float op1, float op2);
---
> float fixDivDest<float>(bool flush, bool defaultNan,
> float val, float op1, float op2);
244c261,262
< double fixDivDest<double>(FPSCR fpscr, double val, double op1, double op2);
---
> double fixDivDest<double>(bool flush, bool defaultNan,
> double val, double op1, double op2);
258c276
< float mid = fixDest(fpscr, (float)val, op1);
---
> float mid = fixDest(fpscr.fz, fpscr.dn, (float)val, op1);
294c312
< double mid = fixDest(fpscr, (double)val, op1);
---
> double mid = fixDest(fpscr.fz, fpscr.dn, (double)val, op1);
314,315c332,334
< float
< vcvtFpSFpH(FPSCR &fpscr, float op, float dest, bool top)
---
> uint16_t
> vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan,
> uint32_t rMode, bool ahp, float op)
317,318d335
< float junk = 0.0;
< uint32_t destBits = fpToBits(dest);
334c351
< if (fpscr.ahp) {
---
> if (ahp) {
338c355
< } else if (fpscr.dn) {
---
> } else if (defaultNan) {
349c366
< if (fpscr.ahp) {
---
> if (ahp) {
367c384
< assert(fpscr.fz == 0);
---
> assert(!flush);
374c391
< unsigned mode = fpscr.rMode;
---
> unsigned mode = rMode;
419c436
< unsigned mode = fpscr.rMode;
---
> unsigned mode = rMode;
435c452
< if (fpscr.ahp) {
---
> if (ahp) {
471,475c488
< if (top)
< replaceBits(destBits, 31, 16, result);
< else
< replaceBits(destBits, 15, 0, result);
< return bitsToFp(destBits, junk);
---
> return result;
479c492
< vcvtFpHFpS(FPSCR &fpscr, float op, bool top)
---
> vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
482,487d494
< uint32_t opBits = fpToBits(op);
< // Extract the operand.
< if (top)
< opBits = bits(opBits, 31, 16);
< else
< opBits = bits(opBits, 15, 0);
489,491c496,498
< bool neg = bits(opBits, 15);
< uint32_t exponent = bits(opBits, 14, 10);
< uint32_t mantissa = bits(opBits, 9, 0);
---
> bool neg = bits(op, 15);
> uint32_t exponent = bits(op, 14, 10);
> uint32_t mantissa = bits(op, 9, 0);
503c510
< } else if (exponent == 0x1f && !fpscr.ahp) {
---
> } else if (exponent == 0x1f && !ahp) {
514c521
< if (fpscr.dn) {
---
> if (defaultNan) {
627c634,635
< vfpUFixedToFpS(FPSCR fpscr, uint32_t val, bool half, uint8_t imm)
---
> vfpUFixedToFpS(bool flush, bool defaultNan,
> uint32_t val, bool half, uint8_t imm)
636c644
< return fixDivDest(fpscr, val / scale, (float)val, scale);
---
> return fixDivDest(flush, defaultNan, val / scale, (float)val, scale);
640c648,649
< vfpSFixedToFpS(FPSCR fpscr, int32_t val, bool half, uint8_t imm)
---
> vfpSFixedToFpS(bool flush, bool defaultNan,
> int32_t val, bool half, uint8_t imm)
649c658
< return fixDivDest(fpscr, val / scale, (float)val, scale);
---
> return fixDivDest(flush, defaultNan, val / scale, (float)val, scale);
746c755,756
< vfpUFixedToFpD(FPSCR fpscr, uint32_t val, bool half, uint8_t imm)
---
> vfpUFixedToFpD(bool flush, bool defaultNan,
> uint32_t val, bool half, uint8_t imm)
755c765
< return fixDivDest(fpscr, val / scale, (double)val, scale);
---
> return fixDivDest(flush, defaultNan, val / scale, (double)val, scale);
759c769,770
< vfpSFixedToFpD(FPSCR fpscr, int32_t val, bool half, uint8_t imm)
---
> vfpSFixedToFpD(bool flush, bool defaultNan,
> int32_t val, bool half, uint8_t imm)
768c779
< return fixDivDest(fpscr, val / scale, (double)val, scale);
---
> return fixDivDest(flush, defaultNan, val / scale, (double)val, scale);
770a782,935
> // This function implements a magic formula taken from the architecture
> // reference manual. It was originally called recip_sqrt_estimate.
> static double
> recipSqrtEstimate(double a)
> {
> int64_t q0, q1, s;
> double r;
> if (a < 0.5) {
> q0 = (int64_t)(a * 512.0);
> r = 1.0 / sqrt(((double)q0 + 0.5) / 512.0);
> } else {
> q1 = (int64_t)(a * 256.0);
> r = 1.0 / sqrt(((double)q1 + 0.5) / 256.0);
> }
> s = (int64_t)(256.0 * r + 0.5);
> return (double)s / 256.0;
> }
>
> // This function is only intended for use in Neon instructions because
> // it ignores certain bits in the FPSCR.
> float
> fprSqrtEstimate(FPSCR &fpscr, float op)
> {
> const uint32_t qnan = 0x7fc00000;
> float junk = 0.0;
> int fpClass = std::fpclassify(op);
> if (fpClass == FP_NAN) {
> if ((fpToBits(op) & qnan) != qnan)
> fpscr.ioc = 1;
> return bitsToFp(qnan, junk);
> } else if (fpClass == FP_ZERO) {
> fpscr.dzc = 1;
> // Return infinity with the same sign as the operand.
> return bitsToFp((std::signbit(op) << 31) |
> (0xFF << 23) | (0 << 0), junk);
> } else if (std::signbit(op)) {
> // Set invalid op bit.
> fpscr.ioc = 1;
> return bitsToFp(qnan, junk);
> } else if (fpClass == FP_INFINITE) {
> return 0.0;
> } else {
> uint64_t opBits = fpToBits(op);
> double scaled;
> if (bits(opBits, 23)) {
> scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) |
> (ULL(0x3fd) << 52) | (bits(opBits, 31) << 63),
> (double)0.0);
> } else {
> scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) |
> (ULL(0x3fe) << 52) | (bits(opBits, 31) << 63),
> (double)0.0);
> }
> uint64_t resultExp = (380 - bits(opBits, 30, 23)) / 2;
>
> uint64_t estimate = fpToBits(recipSqrtEstimate(scaled));
>
> return bitsToFp((bits(estimate, 63) << 31) |
> (bits(resultExp, 7, 0) << 23) |
> (bits(estimate, 51, 29) << 0), junk);
> }
> }
>
> uint32_t
> unsignedRSqrtEstimate(uint32_t op)
> {
> if (bits(op, 31, 30) == 0) {
> return -1;
> } else {
> double dpOp;
> if (bits(op, 31)) {
> dpOp = bitsToFp((ULL(0) << 63) |
> (ULL(0x3fe) << 52) |
> (bits((uint64_t)op, 30, 0) << 21) |
> (0 << 0), (double)0.0);
> } else {
> dpOp = bitsToFp((ULL(0) << 63) |
> (ULL(0x3fd) << 52) |
> (bits((uint64_t)op, 29, 0) << 22) |
> (0 << 0), (double)0.0);
> }
> uint64_t estimate = fpToBits(recipSqrtEstimate(dpOp));
> return (1 << 31) | bits(estimate, 51, 21);
> }
> }
>
> // This function implements a magic formula taken from the architecture
> // reference manual. It was originally called recip_estimate.
>
> static double
> recipEstimate(double a)
> {
> int64_t q, s;
> double r;
> q = (int64_t)(a * 512.0);
> r = 1.0 / (((double)q + 0.5) / 512.0);
> s = (int64_t)(256.0 * r + 0.5);
> return (double)s / 256.0;
> }
>
> // This function is only intended for use in Neon instructions because
> // it ignores certain bits in the FPSCR.
> float
> fpRecipEstimate(FPSCR &fpscr, float op)
> {
> const uint32_t qnan = 0x7fc00000;
> float junk = 0.0;
> int fpClass = std::fpclassify(op);
> if (fpClass == FP_NAN) {
> if ((fpToBits(op) & qnan) != qnan)
> fpscr.ioc = 1;
> return bitsToFp(qnan, junk);
> } else if (fpClass == FP_INFINITE) {
> return bitsToFp(std::signbit(op) << 31, junk);
> } else if (fpClass == FP_ZERO) {
> fpscr.dzc = 1;
> // Return infinity with the same sign as the operand.
> return bitsToFp((std::signbit(op) << 31) |
> (0xFF << 23) | (0 << 0), junk);
> } else if (fabs(op) >= pow(2.0, 126)) {
> fpscr.ufc = 1;
> return bitsToFp(std::signbit(op) << 31, junk);
> } else {
> uint64_t opBits = fpToBits(op);
> double scaled;
> scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) |
> (ULL(0x3fe) << 52) | (ULL(0) << 63),
> (double)0.0);
> uint64_t resultExp = 253 - bits(opBits, 30, 23);
>
> uint64_t estimate = fpToBits(recipEstimate(scaled));
>
> return bitsToFp((bits(opBits, 31) << 31) |
> (bits(resultExp, 7, 0) << 23) |
> (bits(estimate, 51, 29) << 0), junk);
> }
> }
>
> uint32_t
> unsignedRecipEstimate(uint32_t op)
> {
> if (bits(op, 31) == 0) {
> return -1;
> } else {
> double dpOp;
> dpOp = bitsToFp((ULL(0) << 63) |
> (ULL(0x3fe) << 52) |
> (bits((uint64_t)op, 30, 0) << 21) |
> (0 << 0), (double)0.0);
> uint64_t estimate = fpToBits(recipEstimate(dpOp));
> return (1 << 31) | bits(estimate, 51, 21);
> }
> }
>
772a938,980
> FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan,
> fpType op1, fpType op2) const
> {
> done = true;
> fpType junk = 0.0;
> fpType dest = 0.0;
> const bool single = (sizeof(fpType) == sizeof(float));
> const uint64_t qnan =
> single ? 0x7fc00000 : ULL(0x7ff8000000000000);
> const bool nan1 = std::isnan(op1);
> const bool nan2 = std::isnan(op2);
> const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan);
> const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan);
> if (nan1 || nan2) {
> if (defaultNan) {
> dest = bitsToFp(qnan, junk);
> } else if (signal1) {
> dest = bitsToFp(fpToBits(op1) | qnan, junk);
> } else if (signal2) {
> dest = bitsToFp(fpToBits(op2) | qnan, junk);
> } else if (nan1) {
> dest = op1;
> } else if (nan2) {
> dest = op2;
> }
> if (signal1 || signal2) {
> fpscr.ioc = 1;
> }
> } else {
> done = false;
> }
> return dest;
> }
>
> template
> float FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan,
> float op1, float op2) const;
> template
> double FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan,
> double op1, double op2) const;
>
> template <class fpType>
> fpType
775c983
< bool flush, uint32_t rMode) const
---
> bool flush, bool defaultNan, uint32_t rMode) const
798c1006
< if ((!nan1 && !nan2) || (fpscr.dn == 1)) {
---
> if ((!nan1 && !nan2) || (defaultNan == 1)) {
831c1039
< finishVfp(fpscr, state);
---
> finishVfp(fpscr, state, flush);
838c1046
< bool flush, uint32_t rMode) const;
---
> bool flush, bool defaultNan, uint32_t rMode) const;
842c1050
< bool flush, uint32_t rMode) const;
---
> bool flush, bool defaultNan, uint32_t rMode) const;
893c1101
< finishVfp(fpscr, state);
---
> finishVfp(fpscr, state, flush);