From 371e3fe5ef4017bececabe56e4958eb22ac0f08f Mon Sep 17 00:00:00 2001 From: Chih-Min Chao Date: Thu, 6 Jun 2019 01:57:32 -0700 Subject: 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 --- riscv/arith.h | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++ riscv/insn_template.h | 2 +- riscv/mulhi.h | 43 ------------------- 3 files changed, 112 insertions(+), 44 deletions(-) create mode 100644 riscv/arith.h delete mode 100644 riscv/mulhi.h 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 +#include + +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 +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 +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 +T sat_addu(T x, T y, bool &sat) +{ + T res = x + y; + sat = false; + + sat = res < x; + res |= -(res < x); + + return res; +} + +template +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 - -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 -- cgit v1.1