summaryrefslogtreecommitdiff
path: root/src/arch/arm/insts
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
commitaa05e5401c37c7e60f28e13f8e6de5c5f74e904d (patch)
tree29f57669d184808df45280d9a7928899803a7ca3 /src/arch/arm/insts
parent86a1093992e686cac81db2555c477e2b4cad0c63 (diff)
downloadgem5-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.hh144
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