summaryrefslogtreecommitdiff
path: root/src/arch/arm/insts/vfp.hh
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2010-06-02 12:58:15 -0500
committerGabe Black <gblack@eecs.umich.edu>2010-06-02 12:58:15 -0500
commitfd82a47b964016332611dbe768762377531a3619 (patch)
tree780e5ee395b3bc6df026aea0a9e518e335fca546 /src/arch/arm/insts/vfp.hh
parent186273e5f318786cd4db1b652b9b0332c18ea7bf (diff)
downloadgem5-fd82a47b964016332611dbe768762377531a3619.tar.xz
ARM: Implement flush to zero for destinations as well.
Diffstat (limited to 'src/arch/arm/insts/vfp.hh')
-rw-r--r--src/arch/arm/insts/vfp.hh12
1 files changed, 9 insertions, 3 deletions
diff --git a/src/arch/arm/insts/vfp.hh b/src/arch/arm/insts/vfp.hh
index b69f93598..e32aac721 100644
--- a/src/arch/arm/insts/vfp.hh
+++ b/src/arch/arm/insts/vfp.hh
@@ -175,16 +175,17 @@ bitsToFp(uint64_t bits, double junk)
template <class fpType>
static inline fpType
-fixNan(FPSCR fpscr, fpType val, fpType op1, fpType op2)
+fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2)
{
- if (std::isnan(val)) {
+ int fpClass = std::fpclassify(val);
+ fpType junk = 0.0;
+ if (fpClass == FP_NAN) {
const bool single = (sizeof(val) == 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);
- fpType junk = 0.0;
if ((!nan1 && !nan2) || (fpscr.dn == 1)) {
val = bitsToFp(qnan, junk);
} else if (signal1) {
@@ -196,6 +197,11 @@ fixNan(FPSCR fpscr, fpType val, fpType op1, fpType op2)
} else if (nan2) {
val = op2;
}
+ } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) {
+ // Turn val into a zero with the correct sign;
+ uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
+ val = bitsToFp(fpToBits(val) & bitMask, junk);
+ feraiseexcept(FeUnderflow);
}
return val;
}