aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorChih-Min Chao <chihmin.chao@sifive.com>2019-04-03 00:25:35 -0700
committerChih-Min Chao <chihmin.chao@sifive.com>2019-04-03 00:25:35 -0700
commita1133dcf763446fe23e018339504d6cb4eb2eb1d (patch)
treef27ebded2117c692272341bb7b37db48aafbfca1 /riscv
parent5efcf97b0a17375b6c9cf4f817d5682004466312 (diff)
downloadspike-a1133dcf763446fe23e018339504d6cb4eb2eb1d.zip
spike-a1133dcf763446fe23e018339504d6cb4eb2eb1d.tar.gz
spike-a1133dcf763446fe23e018339504d6cb4eb2eb1d.tar.bz2
rvv: add integer saturation helper function
Signed-off-by: Chih-Min Chao <chihmin.chao@sifive.com>
Diffstat (limited to 'riscv')
-rw-r--r--riscv/arith.h44
-rw-r--r--riscv/insn_template.h1
2 files changed, 45 insertions, 0 deletions
diff --git a/riscv/arith.h b/riscv/arith.h
new file mode 100644
index 0000000..ddffbac
--- /dev/null
+++ b/riscv/arith.h
@@ -0,0 +1,44 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_ARITH_H
+#define _RISCV_ARITH_H
+#include <limits.h>
+#include <stdint.h>
+
+//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>
+T sat_addu(T x, T y, bool &sat)
+{
+ T res = x + y;
+ sat = false;
+
+ if (res < x) {
+ res |= -(res < x);
+ sat = true;
+ }
+
+ return res;
+}
+
+#endif
diff --git a/riscv/insn_template.h b/riscv/insn_template.h
index 07aa16b..668966f 100644
--- a/riscv/insn_template.h
+++ b/riscv/insn_template.h
@@ -1,5 +1,6 @@
// See LICENSE for license details.
+#include "arith.h"
#include "mmu.h"
#include "mulhi.h"
#include "softfloat.h"