diff options
author | Chih-Min Chao <chihmin.chao@sifive.com> | 2019-04-03 00:25:35 -0700 |
---|---|---|
committer | Chih-Min Chao <chihmin.chao@sifive.com> | 2019-04-03 00:25:35 -0700 |
commit | a1133dcf763446fe23e018339504d6cb4eb2eb1d (patch) | |
tree | f27ebded2117c692272341bb7b37db48aafbfca1 /riscv | |
parent | 5efcf97b0a17375b6c9cf4f817d5682004466312 (diff) | |
download | spike-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.h | 44 | ||||
-rw-r--r-- | riscv/insn_template.h | 1 |
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" |