diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2010-06-02 12:58:15 -0500 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2010-06-02 12:58:15 -0500 |
commit | aa05e5401c37c7e60f28e13f8e6de5c5f74e904d (patch) | |
tree | 29f57669d184808df45280d9a7928899803a7ca3 /src/arch/arm/insts | |
parent | 86a1093992e686cac81db2555c477e2b4cad0c63 (diff) | |
download | gem5-aa05e5401c37c7e60f28e13f8e6de5c5f74e904d.tar.xz |
ARM: Implement the floating/fixed point VCVT instructions.
Diffstat (limited to 'src/arch/arm/insts')
-rw-r--r-- | src/arch/arm/insts/vfp.hh | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/arch/arm/insts/vfp.hh b/src/arch/arm/insts/vfp.hh index 465384304..ceeaaa3cd 100644 --- a/src/arch/arm/insts/vfp.hh +++ b/src/arch/arm/insts/vfp.hh @@ -101,6 +101,150 @@ enum VfpRoundingMode VfpRoundZero = 3 }; +static inline uint64_t +vfpFpSToFixed(float val, bool isSigned, bool half, uint8_t imm) +{ + fesetround(FeRoundZero); + val = val * powf(2.0, imm); + __asm__ __volatile__("" : "=m" (val) : "m" (val)); + feclearexcept(FeAllExceptions); + if (isSigned) { + if (half) { + if (val < (int16_t)(1 << 15)) { + feraiseexcept(FeInvalid); + return (int16_t)(1 << 15); + } + if (val > (int16_t)mask(15)) { + feraiseexcept(FeInvalid); + return (int16_t)mask(15); + } + return (int16_t)val; + } else { + if (val < (int32_t)(1 << 31)) { + feraiseexcept(FeInvalid); + return (int32_t)(1 << 31); + } + if (val > (int32_t)mask(31)) { + feraiseexcept(FeInvalid); + return (int32_t)mask(31); + } + return (int32_t)val; + } + } else { + if (half) { + if (val < 0) { + feraiseexcept(FeInvalid); + return 0; + } + if (val > (mask(16))) { + feraiseexcept(FeInvalid); + return mask(16); + } + return (uint16_t)val; + } else { + if (val < 0) { + feraiseexcept(FeInvalid); + return 0; + } + if (val > (mask(32))) { + feraiseexcept(FeInvalid); + return mask(32); + } + return (uint32_t)val; + } + } +} + +static inline float +vfpUFixedToFpS(uint32_t val, bool half, uint8_t imm) +{ + fesetround(FeRoundNearest); + if (half) + val = (uint16_t)val; + return val / powf(2.0, imm); +} + +static inline float +vfpSFixedToFpS(int32_t val, bool half, uint8_t imm) +{ + fesetround(FeRoundNearest); + if (half) + val = sext<16>(val & mask(16)); + return val / powf(2.0, imm); +} + +static inline uint64_t +vfpFpDToFixed(double val, bool isSigned, bool half, uint8_t imm) +{ + fesetround(FeRoundZero); + val = val * pow(2.0, imm); + __asm__ __volatile__("" : "=m" (val) : "m" (val)); + feclearexcept(FeAllExceptions); + if (isSigned) { + if (half) { + if (val < (int16_t)(1 << 15)) { + feraiseexcept(FeInvalid); + return (int16_t)(1 << 15); + } + if (val > (int16_t)mask(15)) { + feraiseexcept(FeInvalid); + return (int16_t)mask(15); + } + return (int16_t)val; + } else { + if (val < (int32_t)(1 << 31)) { + feraiseexcept(FeInvalid); + return (int32_t)(1 << 31); + } + if (val > (int32_t)mask(31)) { + feraiseexcept(FeInvalid); + return (int32_t)mask(31); + } + return (int32_t)val; + } + } else { + if (half) { + if (val < 0) { + feraiseexcept(FeInvalid); + return 0; + } + if (val > mask(16)) { + feraiseexcept(FeInvalid); + return mask(16); + } + return (uint16_t)val; + } else { + if (val < 0) { + feraiseexcept(FeInvalid); + return 0; + } + if (val > mask(32)) { + feraiseexcept(FeInvalid); + return mask(32); + } + return (uint32_t)val; + } + } +} + +static inline double +vfpUFixedToFpD(uint32_t val, bool half, uint8_t imm) +{ + fesetround(FeRoundNearest); + if (half) + val = (uint16_t)val; + return val / pow(2.0, imm); +} + +static inline double +vfpSFixedToFpD(int32_t val, bool half, uint8_t imm) +{ + fesetround(FeRoundNearest); + if (half) + val = sext<16>(val & mask(16)); + return val / pow(2.0, imm); +} + typedef int VfpSavedState; static inline VfpSavedState |