47 FpCondCompRegOp::generateDisassembly(
104 std::stringstream
ss;
117 std::stringstream
ss;
132 std::stringstream
ss;
147 std::stringstream
ss;
163 std::stringstream
ss;
180 int roundingMode = fegetround();
203 bool underflow =
false;
204 if ((exceptions &
FeInvalid) && mask.ioc) {
218 if ((exceptions &
FeInexact) && !(underflow && flush) && mask.ixc) {
224 template <
class fpType>
230 if (fpClass == FP_NAN) {
231 const bool single = (
sizeof(
val) ==
sizeof(
float));
232 const uint64_t qnan = single ? 0x7fc00000 :
ULL(0x7ff8000000000000);
233 const bool nan = std::isnan(op1);
234 if (!nan || defaultNan) {
239 }
else if (fpClass == FP_SUBNORMAL && flush == 1) {
241 uint64_t bitMask =
ULL(0x1) << (
sizeof(fpType) * 8 - 1);
254 template <
class fpType>
260 if (fpClass == FP_NAN) {
261 const bool single = (
sizeof(
val) ==
sizeof(
float));
262 const uint64_t qnan = single ? 0x7fc00000 :
ULL(0x7ff8000000000000);
263 const bool nan1 = std::isnan(op1);
264 const bool nan2 = std::isnan(op2);
265 const bool signal1 = nan1 && ((
fpToBits(op1) & qnan) != qnan);
266 const bool signal2 = nan2 && ((
fpToBits(op2) & qnan) != qnan);
267 if ((!nan1 && !nan2) || defaultNan) {
269 }
else if (signal1) {
271 }
else if (signal2) {
278 }
else if (fpClass == FP_SUBNORMAL && flush) {
280 uint64_t bitMask =
ULL(0x1) << (
sizeof(fpType) * 8 - 1);
295 template <
class fpType>
299 fpType mid =
fixDest(flush, defaultNan, val, op1, op2);
300 const bool single = (
sizeof(fpType) ==
sizeof(
float));
301 const fpType junk = 0.0;
302 if ((single && (val ==
bitsToFp(0x00800000, junk) ||
303 val ==
bitsToFp(0x80800000, junk))) ||
304 (!single && (val ==
bitsToFp(
ULL(0x0010000000000000), junk) ||
307 __asm__ __volatile__(
"" :
"=m" (op1) :
"m" (op1));
310 __asm__ __volatile__(
"" :
"=m" (temp) :
"m" (temp));
319 __asm__ __volatile__(
"" ::
"m" (temp));
334 const float junk = 0.0;
336 if (std::isnan(val)) {
338 uint32_t op1Bits =
bits(valBits, 50, 29) |
340 (
bits(valBits, 63) << 31);
343 float mid =
fixDest(fpscr.fz, fpscr.dn, (
float)val, op1);
348 if (mid ==
bitsToFp(0x00800000, junk) ||
349 mid ==
bitsToFp(0x80800000, junk)) {
350 __asm__ __volatile__(
"" :
"=m" (val) :
"m" (val));
353 __asm__ __volatile__(
"" :
"=m" (temp) :
"m" (temp));
362 __asm__ __volatile__(
"" ::
"m" (temp));
370 const double junk = 0.0;
372 if (std::isnan(val)) {
374 uint64_t op1Bits = ((uint64_t)
bits(valBits, 21, 0) << 29) |
376 ((uint64_t)
bits(valBits, 31) << 63);
379 double mid =
fixDest(fpscr.fz, fpscr.dn, (
double)val, op1);
380 if (mid ==
bitsToFp(
ULL(0x0010000000000000), junk) ||
382 __asm__ __volatile__(
"" :
"=m" (val) :
"m" (val));
385 __asm__ __volatile__(
"" :
"=m" (temp) :
"m" (temp));
394 __asm__ __volatile__(
"" ::
"m" (temp));
399 static inline uint16_t
401 uint32_t
rMode,
bool ahp, uint64_t opBits,
bool isDouble)
415 sBitPos = eWidth + mWidth;
416 eHalfRange = (1 << (eWidth-1)) - 1;
419 bool neg =
bits(opBits, sBitPos);
420 uint32_t exponent =
bits(opBits, sBitPos-1, mWidth);
421 uint64_t oldMantissa =
bits(opBits, mWidth-1, 0);
422 uint32_t mantissa = oldMantissa >> (mWidth - 10);
424 uint64_t extra = oldMantissa &
mask(mWidth - 10);
425 if (exponent ==
mask(eWidth)) {
426 if (oldMantissa != 0) {
428 if (
bits(mantissa, 9) == 0) {
436 }
else if (defaultNan) {
442 mantissa |= (1 << 9);
454 }
else if (exponent == 0 && oldMantissa == 0) {
459 bool inexact = (extra != 0);
467 if (inexact || fpscr.ufe)
476 (extra == (1 << 9) &&
bits(mantissa, 0))))) {
481 if (mantissa == (1 << 10)) {
490 bool topOne =
bits(extra, mWidth - 10 - 1);
491 bool restZeros =
bits(extra, mWidth - 10 - 2, 0) == 0;
493 if (exponent <= (eHalfRange - 15)) {
495 mantissa |= (1 << 10);
496 while (mantissa && exponent <= (eHalfRange - 15)) {
497 restZeros = restZeros && !topOne;
498 topOne =
bits(mantissa, 0);
499 mantissa = mantissa >> 1;
502 if (topOne || !restZeros)
507 exponent -= (eHalfRange - 15);
510 if (exponent == 0 && (inexact || fpscr.ufe)) {
517 bool nonZero = topOne || !restZeros;
521 (!restZeros ||
bits(mantissa, 0)))) {
526 if (mantissa == (1 << 10)) {
533 if (exponent >= 0x20) {
541 if (exponent >= 0x1f) {
564 uint32_t result =
bits(mantissa, 9, 0);
576 return vcvtFpFpH(fpscr, flush, defaultNan, rMode, ahp, opBits,
false);
584 return vcvtFpFpH(fpscr, flush, defaultNan, rMode, ahp, opBits,
true);
587 static inline uint64_t
602 sBitPos = eWidth + mWidth;
603 eHalfRange = (1 << (eWidth-1)) - 1;
607 uint32_t exponent =
bits(op, 14, 10);
608 uint64_t mantissa =
bits(op, 9, 0);
613 exponent = exponent + (eHalfRange - 15) + 1;
614 while (mantissa < (1 << 10)) {
615 mantissa = mantissa << 1;
619 mantissa = mantissa << (mWidth - 10);
620 }
else if (exponent == 0x1f && !ahp) {
622 exponent =
mask(eWidth);
625 mantissa = mantissa << (mWidth - 10);
626 if (
bits(mantissa, mWidth-1) == 0) {
629 mantissa |= (((uint64_t) 1) << (mWidth-1));
632 mantissa &= ~
mask(mWidth-1);
637 exponent = exponent + (eHalfRange - 15);
638 mantissa = mantissa << (mWidth - 10);
641 uint64_t result =
bits(mantissa, mWidth-1, 0);
644 result |= (((uint64_t) 1) << sBitPos);
655 result =
vcvtFpHFp(fpscr, defaultNan, ahp, op,
true);
665 result =
vcvtFpHFp(fpscr, defaultNan, ahp, op,
false);
671 uint64_t val, uint8_t
width, uint8_t
imm)
676 else if (width == 32)
678 else if (width != 64)
679 panic(
"Unsupported width %d", width);
680 float scale = powf(2.0, imm);
681 __asm__ __volatile__(
"" :
"=m" (scale) :
"m" (scale));
683 __asm__ __volatile__(
"" :
"=m" (scale) :
"m" (scale));
684 return fixDivDest(flush, defaultNan, val / scale, (
float)val, scale);
689 int64_t val, uint8_t
width, uint8_t
imm)
693 val = sext<16>(val &
mask(16));
694 else if (width == 32)
695 val = sext<32>(val &
mask(32));
696 else if (width != 64)
697 panic(
"Unsupported width %d", width);
699 float scale = powf(2.0, imm);
700 __asm__ __volatile__(
"" :
"=m" (scale) :
"m" (scale));
702 __asm__ __volatile__(
"" :
"=m" (scale) :
"m" (scale));
703 return fixDivDest(flush, defaultNan, val / scale, (
float)val, scale);
709 uint64_t val, uint8_t
width, uint8_t
imm)
714 else if (width == 32)
716 else if (width != 64)
717 panic(
"Unsupported width %d", width);
719 double scale = pow(2.0, imm);
720 __asm__ __volatile__(
"" :
"=m" (scale) :
"m" (scale));
722 __asm__ __volatile__(
"" :
"=m" (scale) :
"m" (scale));
723 return fixDivDest(flush, defaultNan, val / scale, (
double)val, scale);
728 int64_t val, uint8_t
width, uint8_t
imm)
732 val = sext<16>(val &
mask(16));
733 else if (width == 32)
734 val = sext<32>(val &
mask(32));
735 else if (width != 64)
736 panic(
"Unsupported width %d", width);
738 double scale = pow(2.0, imm);
739 __asm__ __volatile__(
"" :
"=m" (scale) :
"m" (scale));
741 __asm__ __volatile__(
"" :
"=m" (scale) :
"m" (scale));
742 return fixDivDest(flush, defaultNan, val / scale, (
double)val, scale);
753 q0 = (int64_t)(a * 512.0);
754 r = 1.0 / sqrt(((
double)q0 + 0.5) / 512.0);
756 q1 = (int64_t)(a * 256.0);
757 r = 1.0 / sqrt(((
double)q1 + 0.5) / 256.0);
759 s = (int64_t)(256.0 * r + 0.5);
760 return (
double)s / 256.0;
768 const uint32_t qnan = 0x7fc00000;
771 if (fpClass == FP_NAN) {
775 }
else if (fpClass == FP_ZERO) {
779 (0xFF << 23) | (0 << 0), junk);
784 }
else if (fpClass == FP_INFINITE) {
789 if (
bits(opBits, 23)) {
790 scaled =
bitsToFp((0 << 0) | (
bits(opBits, 22, 0) << 29) |
791 (
ULL(0x3fd) << 52) | (
bits(opBits, 31) << 63),
794 scaled =
bitsToFp((0 << 0) | (
bits(opBits, 22, 0) << 29) |
795 (
ULL(0x3fe) << 52) | (
bits(opBits, 31) << 63),
798 uint64_t resultExp = (380 -
bits(opBits, 30, 23)) / 2;
803 (
bits(resultExp, 7, 0) << 23) |
804 (
bits(estimate, 51, 29) << 0), junk);
811 if (
bits(op, 31, 30) == 0) {
818 (
bits((uint64_t)op, 30, 0) << 21) |
819 (0 << 0), (
double)0.0);
823 (
bits((uint64_t)op, 29, 0) << 22) |
824 (0 << 0), (
double)0.0);
827 return (1 << 31) |
bits(estimate, 51, 21);
839 q = (int64_t)(a * 512.0);
840 r = 1.0 / (((double)q + 0.5) / 512.0);
841 s = (int64_t)(256.0 * r + 0.5);
842 return (
double)s / 256.0;
850 const uint32_t qnan = 0x7fc00000;
853 if (fpClass == FP_NAN) {
857 }
else if (fpClass == FP_INFINITE) {
859 }
else if (fpClass == FP_ZERO) {
863 (0xFF << 23) | (0 << 0), junk);
864 }
else if (fabs(op) >= pow(2.0, 126)) {
870 scaled =
bitsToFp((0 << 0) | (
bits(opBits, 22, 0) << 29) |
871 (
ULL(0x3fe) << 52) | (
ULL(0) << 63),
873 uint64_t resultExp = 253 -
bits(opBits, 30, 23);
878 (
bits(resultExp, 7, 0) << 23) |
879 (
bits(estimate, 51, 29) << 0), junk);
886 if (
bits(op, 31) == 0) {
892 (
bits((uint64_t)op, 30, 0) << 21) |
893 (0 << 0), (
double)0.0);
895 return (1 << 31) |
bits(estimate, 51, 21);
903 new_fpscr.ahp = fpscr.ahp;
906 new_fpscr.fz16 = fpscr.fz16;
910 template <
class fpType>
913 fpType op1, fpType
op2)
const 918 const bool single = (
sizeof(fpType) ==
sizeof(
float));
919 const uint64_t qnan =
920 single ? 0x7fc00000 :
ULL(0x7ff8000000000000);
921 const bool nan1 = std::isnan(op1);
922 const bool nan2 = std::isnan(op2);
923 const bool signal1 = nan1 && ((
fpToBits(op1) & qnan) != qnan);
924 const bool signal2 = nan2 && ((
fpToBits(op2) & qnan) != qnan);
928 }
else if (signal1) {
930 }
else if (signal2) {
937 if (signal1 || signal2) {
948 float op1,
float op2)
const;
951 double op1,
double op2)
const;
954 template <
class fpType>
957 fpType (*func)(fpType, fpType, fpType),
958 bool flush,
bool defaultNan, uint32_t
rMode)
const 960 const bool single = (
sizeof(fpType) ==
sizeof(
float));
966 __asm__ __volatile__ (
"" :
"=m" (op1),
"=m" (op2),
"=m" (op3),
"=m" (state)
967 :
"m" (op1),
"m" (op2),
"m" (op3),
"m" (state));
968 fpType dest = func(op1, op2, op3);
969 __asm__ __volatile__ (
"" :
"=m" (dest) :
"m" (dest));
973 if (fpClass == FP_NAN) {
974 const uint64_t qnan =
975 single ? 0x7fc00000 :
ULL(0x7ff8000000000000);
976 const bool nan1 = std::isnan(op1);
977 const bool nan2 = std::isnan(op2);
978 const bool nan3 = std::isnan(op3);
979 const bool signal1 = nan1 && ((
fpToBits(op1) & qnan) != qnan);
980 const bool signal2 = nan2 && ((
fpToBits(op2) & qnan) != qnan);
981 const bool signal3 = nan3 && ((
fpToBits(op3) & qnan) != qnan);
982 if ((!nan1 && !nan2 && !nan3) || (defaultNan == 1)) {
984 }
else if (signal1) {
986 }
else if (signal2) {
988 }
else if (signal3) {
1000 (single && (dest ==
bitsToFp(0x00800000, junk) ||
1001 dest ==
bitsToFp(0x80800000, junk))) ||
1003 (dest ==
bitsToFp(
ULL(0x0010000000000000), junk) ||
1011 __asm__ __volatile__ (
"" :
"=m" (op1),
"=m" (op2),
"=m" (op3)
1012 :
"m" (op1),
"m" (op2),
"m" (op3));
1013 fpType temp = func(op1, op2, op2);
1014 __asm__ __volatile__ (
"" :
"=m" (temp) :
"m" (temp));
1025 float (*func)(
float,
float,
float),
1026 bool flush,
bool defaultNan, uint32_t
rMode)
const;
1028 double FpOp::ternaryOp(FPSCR &fpscr,
double op1,
double op2,
double op3,
1029 double (*func)(
double,
double,
double),
1030 bool flush,
bool defaultNan, uint32_t rMode)
const;
1032 template <
class fpType>
1035 fpType (*func)(fpType, fpType),
1036 bool flush,
bool defaultNan, uint32_t rMode)
const 1038 const bool single = (
sizeof(fpType) ==
sizeof(
float));
1044 __asm__ __volatile__ (
"" :
"=m" (op1),
"=m" (op2),
"=m" (state)
1045 :
"m" (op1),
"m" (op2),
"m" (state));
1046 fpType dest = func(op1, op2);
1047 __asm__ __volatile__ (
"" :
"=m" (dest) :
"m" (dest));
1050 if (std::isnan(dest)) {
1051 const uint64_t qnan =
1052 single ? 0x7fc00000 :
ULL(0x7ff8000000000000);
1053 const bool nan1 = std::isnan(op1);
1054 const bool nan2 = std::isnan(op2);
1055 const bool signal1 = nan1 && ((
fpToBits(op1) & qnan) != qnan);
1056 const bool signal2 = nan2 && ((
fpToBits(op2) & qnan) != qnan);
1057 if ((!nan1 && !nan2) || (defaultNan == 1)) {
1059 }
else if (signal1) {
1061 }
else if (signal2) {
1071 (single && (dest ==
bitsToFp(0x00800000, junk) ||
1072 dest ==
bitsToFp(0x80800000, junk))) ||
1074 (dest ==
bitsToFp(
ULL(0x0010000000000000), junk) ||
1082 __asm__ __volatile__ (
"" :
"=m" (op1),
"=m" (op2)
1083 :
"m" (op1),
"m" (op2));
1084 fpType temp = func(op1, op2);
1085 __asm__ __volatile__ (
"" :
"=m" (temp) :
"m" (temp));
1096 float (*func)(
float,
float),
1097 bool flush,
bool defaultNan, uint32_t rMode)
const;
1100 double (*func)(
double,
double),
1101 bool flush,
bool defaultNan, uint32_t rMode)
const;
1103 template <
class fpType>
1106 bool flush, uint32_t rMode)
const 1108 const bool single = (
sizeof(fpType) ==
sizeof(
float));
1114 __asm__ __volatile__ (
"" :
"=m" (op1),
"=m" (state)
1115 :
"m" (op1),
"m" (state));
1116 fpType dest = func(op1);
1117 __asm__ __volatile__ (
"" :
"=m" (dest) :
"m" (dest));
1120 if (std::isnan(dest)) {
1121 const uint64_t qnan =
1122 single ? 0x7fc00000 :
ULL(0x7ff8000000000000);
1123 const bool nan = std::isnan(op1);
1124 if (!nan || fpscr.dn == 1) {
1132 (single && (dest ==
bitsToFp(0x00800000, junk) ||
1133 dest ==
bitsToFp(0x80800000, junk))) ||
1135 (dest ==
bitsToFp(
ULL(0x0010000000000000), junk) ||
1143 __asm__ __volatile__ (
"" :
"=m" (op1) :
"m" (op1));
1144 fpType temp = func(op1);
1145 __asm__ __volatile__ (
"" :
"=m" (temp) :
"m" (temp));
1155 float FpOp::unaryOp(FPSCR &fpscr,
float op1,
float (*func)(
float),
1156 bool flush, uint32_t rMode)
const;
1158 double FpOp::unaryOp(FPSCR &fpscr,
double op1,
double (*func)(
double),
1159 bool flush, uint32_t rMode)
const;
1167 unsigned offset = idx % 8;
1178 assert(!inScalarBank(dest));
1179 dest = addStride(dest, stride);
1180 op1 = addStride(op1, stride);
1181 if (!inScalarBank(op2)) {
1182 op2 = addStride(op2, stride);
1190 assert(!inScalarBank(dest));
1191 dest = addStride(dest, stride);
1192 if (!inScalarBank(op1)) {
1193 op1 = addStride(op1, stride);
1201 assert(!inScalarBank(dest));
1202 dest = addStride(dest, stride);
#define panic(...)
This implements a cprintf based panic() function.
void ccprintf(cp::Print &print)
template double fixDest< double >(bool flush, bool defaultNan, double val, double op1)
void printMnemonic(std::ostream &os, const std::string &suffix="", bool withPred=true, bool withCond64=false, ConditionCode cond64=COND_UC) const
double fixFpSFpDDest(FPSCR fpscr, float val)
static float bitsToFp(uint64_t, float)
fpType fixDivDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2)
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
uint32_t unsignedRecipEstimate(uint32_t op)
Bitfield< 21, 20 > stride
float fixFpDFpSDest(FPSCR fpscr, double val)
bool fpclassify(T src0, uint32_t src1)
template float fixDivDest< float >(bool flush, bool defaultNan, float val, float op1, float op2)
static double recipSqrtEstimate(double a)
template double fixDivDest< double >(bool flush, bool defaultNan, double val, double op1, double op2)
uint16_t vcvtFpDFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, double op)
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
double vcvtFpHFpD(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
uint16_t vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, float op)
FPSCR fpStandardFPSCRValue(const FPSCR &fpscr)
void neg(sc_fxval &c, const sc_fxnum &a)
uint32_t unsignedRSqrtEstimate(uint32_t op)
float fprSqrtEstimate(FPSCR &fpscr, float op)
const ExtMachInst machInst
The binary machine instruction.
static double recipEstimate(double a)
static uint32_t fpToBits(float)
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.
static uint16_t vcvtFpFpH(FPSCR &fpscr, bool flush, bool defaultNan, uint32_t rMode, bool ahp, uint64_t opBits, bool isDouble)
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
void finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush, FPSCR mask)
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.
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 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.
fpType binaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType(*func)(fpType, fpType), bool flush, bool defaultNan, uint32_t rMode) const
double vfpUFixedToFpD(bool flush, bool defaultNan, uint64_t val, uint8_t width, uint8_t imm)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
#define ULL(N)
uint64_t constant
fpType unaryOp(FPSCR &fpscr, fpType op1, fpType(*func)(fpType), bool flush, uint32_t rMode) const
double vfpSFixedToFpD(bool flush, bool defaultNan, int64_t val, uint8_t width, uint8_t imm)
void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2)
fpType fixDest(bool flush, bool defaultNan, fpType val, fpType op1)
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
int signbit(uint64_t src, int sz)
fpType ternaryOp(FPSCR &fpscr, fpType op1, fpType op2, fpType op3, fpType(*func)(fpType, fpType, fpType), bool flush, bool defaultNan, uint32_t rMode) const
float fpRecipEstimate(FPSCR &fpscr, float op)
VfpSavedState prepFpState(uint32_t rMode)
float vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
void printFloatReg(std::ostream &os, RegIndex reg_idx) const
template float fixDest< float >(bool flush, bool defaultNan, float val, float op1)
float vfpUFixedToFpS(bool flush, bool defaultNan, uint64_t val, uint8_t width, uint8_t imm)
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
static uint64_t vcvtFpHFp(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op, bool isDouble)
std::string generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
float vfpSFixedToFpS(bool flush, bool defaultNan, int64_t val, uint8_t width, uint8_t imm)
IntRegIndex addStride(IntRegIndex idx, unsigned stride)