aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChih-Min Chao <chihmin.chao@sifive.com>2019-06-06 01:57:32 -0700
committerChih-Min Chao <chihmin.chao@sifive.com>2019-06-18 08:54:10 -0700
commit371e3fe5ef4017bececabe56e4958eb22ac0f08f (patch)
tree3bc810f8ff317662b332613543a495257ce8441f
parentb96463c921671e528c002a1a350c7766f481e2f2 (diff)
downloadriscv-isa-sim-371e3fe5ef4017bececabe56e4958eb22ac0f08f.zip
riscv-isa-sim-371e3fe5ef4017bececabe56e4958eb22ac0f08f.tar.gz
riscv-isa-sim-371e3fe5ef4017bececabe56e4958eb22ac0f08f.tar.bz2
rvv: add saturation helper function
1. add integer signed add/subu and unsigend add/sub saturation function 2. merge these with mulhi helper Signed-off-by: Chih-Min Chao <chihmin.chao@sifive.com>
-rw-r--r--riscv/arith.h111
-rw-r--r--riscv/insn_template.h2
-rw-r--r--riscv/mulhi.h43
3 files changed, 112 insertions, 44 deletions
diff --git a/riscv/arith.h b/riscv/arith.h
new file mode 100644
index 0000000..b4370cb
--- /dev/null
+++ b/riscv/arith.h
@@ -0,0 +1,111 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_ARITH_H
+#define _RISCV_ARITH_H
+
+#include <cstdint>
+#include <climits>
+
+inline uint64_t mulhu(uint64_t a, uint64_t b)
+{
+ uint64_t t;
+ uint32_t y1, y2, y3;
+ uint64_t a0 = (uint32_t)a, a1 = a >> 32;
+ uint64_t b0 = (uint32_t)b, b1 = b >> 32;
+
+ t = a1*b0 + ((a0*b0) >> 32);
+ y1 = t;
+ y2 = t >> 32;
+
+ t = a0*b1 + y1;
+ y1 = t;
+
+ t = a1*b1 + y2 + (t >> 32);
+ y2 = t;
+ y3 = t >> 32;
+
+ return ((uint64_t)y3 << 32) | y2;
+}
+
+inline int64_t mulh(int64_t a, int64_t b)
+{
+ int negate = (a < 0) != (b < 0);
+ uint64_t res = mulhu(a < 0 ? -a : a, b < 0 ? -b : b);
+ return negate ? ~res + (a * b == 0) : res;
+}
+
+inline int64_t mulhsu(int64_t a, uint64_t b)
+{
+ int negate = a < 0;
+ uint64_t res = mulhu(a < 0 ? -a : a, b);
+ return negate ? ~res + (a * b == 0) : res;
+}
+
+//ref: https://locklessinc.com/articles/sat_arithmetic/
+template<typename T, typename UT>
+static inline T sat_add(T x, T y, bool &sat)
+{
+ UT ux = x;
+ UT uy = y;
+ UT res = ux + uy;
+ sat = false;
+ int sh = sizeof(T) * 8 - 1;
+
+ /* Calculate overflowed result. (Don't change the sign bit of ux) */
+ ux = (ux >> sh) + (((UT)0x1 << sh) - 1);
+
+ /* Force compiler to use cmovns instruction */
+ if ((T) ((ux ^ uy) | ~(uy ^ res)) >= 0) {
+ res = ux;
+ sat = true;
+ }
+
+ return res;
+}
+
+template<typename T, typename UT>
+static inline T sat_sub(T x, T y, bool &sat)
+{
+ UT ux = x;
+ UT uy = y;
+ UT res = ux - uy;
+ sat = false;
+ int sh = sizeof(T) * 8 - 1;
+
+ /* Calculate overflowed result. (Don't change the sign bit of ux) */
+ ux = (ux >> sh) + (((UT)0x1 << sh) - 1);
+
+ /* Force compiler to use cmovns instruction */
+ if ((T) ((ux ^ uy) & (ux ^ res)) < 0) {
+ res = ux;
+ sat = true;
+ }
+
+ return res;
+}
+
+template<typename T>
+T sat_addu(T x, T y, bool &sat)
+{
+ T res = x + y;
+ sat = false;
+
+ sat = res < x;
+ res |= -(res < x);
+
+ return res;
+}
+
+template<typename T>
+T sat_subu(T x, T y, bool &sat)
+{
+ T res = x - y;
+ sat = false;
+
+ sat = !(res <= x);
+ res &= -(res <= x);
+
+ return res;
+}
+
+#endif
diff --git a/riscv/insn_template.h b/riscv/insn_template.h
index 07aa16b..3c36d10 100644
--- a/riscv/insn_template.h
+++ b/riscv/insn_template.h
@@ -1,7 +1,7 @@
// See LICENSE for license details.
+#include "arith.h"
#include "mmu.h"
-#include "mulhi.h"
#include "softfloat.h"
#include "internals.h"
#include "specialize.h"
diff --git a/riscv/mulhi.h b/riscv/mulhi.h
deleted file mode 100644
index bb4a484..0000000
--- a/riscv/mulhi.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// See LICENSE for license details.
-
-#ifndef _RISCV_MULHI_H
-#define _RISCV_MULHI_H
-
-#include <cstdint>
-
-inline uint64_t mulhu(uint64_t a, uint64_t b)
-{
- uint64_t t;
- uint32_t y1, y2, y3;
- uint64_t a0 = (uint32_t)a, a1 = a >> 32;
- uint64_t b0 = (uint32_t)b, b1 = b >> 32;
-
- t = a1*b0 + ((a0*b0) >> 32);
- y1 = t;
- y2 = t >> 32;
-
- t = a0*b1 + y1;
- y1 = t;
-
- t = a1*b1 + y2 + (t >> 32);
- y2 = t;
- y3 = t >> 32;
-
- return ((uint64_t)y3 << 32) | y2;
-}
-
-inline int64_t mulh(int64_t a, int64_t b)
-{
- int negate = (a < 0) != (b < 0);
- uint64_t res = mulhu(a < 0 ? -a : a, b < 0 ? -b : b);
- return negate ? ~res + (a * b == 0) : res;
-}
-
-inline int64_t mulhsu(int64_t a, uint64_t b)
-{
- int negate = a < 0;
- uint64_t res = mulhu(a < 0 ? -a : a, b);
- return negate ? ~res + (a * b == 0) : res;
-}
-
-#endif