diff --git a/riscv/insns/pm2wsub_hx.h b/riscv/insns/pm2wsub_hx.h index 81da3652..df35dc04 100644 --- a/riscv/insns/pm2wsub_hx.h +++ b/riscv/insns/pm2wsub_hx.h @@ -1,7 +1,7 @@ require_rv32; P_WIDEN_REDUCTION_CROSS_LOOP(32, 16, false, false, { if (j & 1) - p_res += p_rs1 * p_rs2; + p_res -= (int64_t)p_rs1 * p_rs2; else - p_res -= p_rs1 * p_rs2; -}) \ No newline at end of file + p_res += (int64_t)p_rs1 * p_rs2; +}) diff --git a/riscv/insns/pm2wsuba_hx.h b/riscv/insns/pm2wsuba_hx.h index 58a99d03..353a078d 100644 --- a/riscv/insns/pm2wsuba_hx.h +++ b/riscv/insns/pm2wsuba_hx.h @@ -1,7 +1,7 @@ require_rv32; P_WIDEN_REDUCTION_CROSS_LOOP(32, 16, true, false, { if (j & 1) - p_res += p_rs1 * p_rs2; - else p_res -= p_rs1 * p_rs2; -}) \ No newline at end of file + else + p_res += p_rs1 * p_rs2; +}) diff --git a/riscv/insns/pssha_dhs.h b/riscv/insns/pssha_dhs.h index e72b4cf9..c3266108 100644 --- a/riscv/insns/pssha_dhs.h +++ b/riscv/insns/pssha_dhs.h @@ -1,45 +1,26 @@ require_rv32; P_RD_RS1_DW_LOOP(16, 16, { - uint64_t bits_SMIN = (uint64_t{1} << (16 - 1)); - uint64_t bits_SMAX = ((uint64_t{1} << (16 - 1)) - 1); bool ov = false; - int8_t m = P_FIELD(RS2, 0, 8); - int8_t rev = static_cast(m); - rev = (m < 0) ? static_cast(~m + 1u) : m; - uint64_t mask = ((uint64_t{1} << 16) - 1); - p_rs1 &= mask; - if(m < 0){ - unsigned sh = ((unsigned)(uint8_t)rev > 255u) ? 255u : (unsigned)(uint8_t)rev; - uint64_t sign = (p_rs1 >> (16 - 1)) & 1u; - - if(sh >= 16) p_rd = (uint16_t)(sign ? mask : 0u); - else{ - uint64_t shifted = (p_rs1 >> sh); - uint64_t fill = (~uint64_t{0}) << (16 - sh); - shifted |= fill; - p_rd = (uint16_t)(shifted & mask); - } - } - else{ - if(rev==0) p_rd = (uint16_t)p_rs1; - else if(rev >= 16){ - if(p_rs1==0) p_rd = 0; - else{ - ov = true; - uint64_t sign = (p_rs1 >> (16 - 1)) & 1u; - p_rd = (uint16_t)(sign ? bits_SMIN : bits_SMAX); - } - } - else{ - uint64_t sign = (p_rs1 >> (16 - 1)) & 1u; - uint64_t top = (p_rs1 >> (16 - rev)); - uint64_t need = sign ? ((uint64_t{1} << rev) - 1) : 0u; - ov = (top != need); - if(ov) - p_rd = (uint16_t)(sign ? bits_SMIN : bits_SMAX); - else - p_rd = (uint16_t)((p_rs1 << rev) & mask); + int8_t sshamt = P_FIELD(RS2, 0, 8); + int32_t val = p_rs1; + if (sshamt < 0) { + val = (int16_t)(val >> std::min(-sshamt, 16)); + } else if (sshamt >= 16 && val != 0){ + val = val > 0 ? INT16_MAX : INT16_MIN; + ov = true; + } else if (val != 0) { + int32_t tmp = (int32_t)val << sshamt; + if (tmp > INT16_MAX) { + val = INT16_MAX; + ov = true; + } else if (tmp < INT16_MIN) { + val = INT16_MIN; + ov = true; + } else { + val = tmp; } } + p_rd = val; + if (ov) P.set_vxsat(); -}) \ No newline at end of file +}) diff --git a/riscv/insns/pssha_dws.h b/riscv/insns/pssha_dws.h index 8048daff..98bb4e89 100644 --- a/riscv/insns/pssha_dws.h +++ b/riscv/insns/pssha_dws.h @@ -1,45 +1,26 @@ require_rv32; P_RD_RS1_DW_LOOP(32, 32, { - uint64_t bits_SMIN = (uint64_t{1} << (32 - 1)); - uint64_t bits_SMAX = ((uint64_t{1} << (32 - 1)) - 1); bool ov = false; - int8_t m = P_FIELD(RS2, 0, 8); - int8_t rev = static_cast(m); - rev = (m < 0) ? static_cast(~m + 1u) : m; - uint64_t mask = ((uint64_t{1} << 32) - 1); - p_rs1 &= mask; - if(m < 0){ - unsigned sh = ((unsigned)(uint8_t)rev > 255u) ? 255u : (unsigned)(uint8_t)rev; - uint64_t sign = (p_rs1 >> (32 - 1)) & 1u; - - if(sh >= 32) p_rd = (uint32_t)(sign ? mask : 0u); - else{ - uint64_t shifted = (p_rs1 >> sh); - uint64_t fill = (~uint64_t{0}) << (32 - sh); - shifted |= fill; - p_rd = (uint32_t)(shifted & mask); - } - } - else{ - if(rev==0) p_rd = (uint32_t)p_rs1; - else if(rev >= 32){ - if(p_rs1==0) p_rd = 0; - else{ - ov = true; - uint64_t sign = (p_rs1 >> (32 - 1)) & 1u; - p_rd = (uint32_t)(sign ? bits_SMIN : bits_SMAX); - } - } - else{ - uint64_t sign = (p_rs1 >> (32 - 1)) & 1u; - uint64_t top = (p_rs1 >> (32 - rev)); - uint64_t need = sign ? ((uint64_t{1} << rev) - 1) : 0u; - ov = (top != need); - if(ov) - p_rd = (uint32_t)(sign ? bits_SMIN : bits_SMAX); - else - p_rd = (uint32_t)((p_rs1 << rev) & mask); + int8_t sshamt = P_FIELD(RS2, 0, 8); + int64_t val = p_rs1; + if (sshamt < 0) { + val = (int32_t)(val >> std::min(-sshamt, 32)); + } else if (sshamt >= 32 && val != 0){ + val = val > 0 ? INT32_MAX : INT32_MIN; + ov = true; + } else if (val != 0) { + int64_t tmp = (int64_t)val << sshamt; + if (tmp > INT32_MAX) { + val = INT32_MAX; + ov = true; + } else if (tmp < INT32_MIN) { + val = INT32_MIN; + ov = true; + } else { + val = tmp; } } + p_rd = val; + if (ov) P.set_vxsat(); }) diff --git a/riscv/insns/psshar_dhs.h b/riscv/insns/psshar_dhs.h index e1ccc6b9..ed5a0fb1 100644 --- a/riscv/insns/psshar_dhs.h +++ b/riscv/insns/psshar_dhs.h @@ -1,64 +1,27 @@ require_rv32; P_RD_RS1_DW_LOOP(16, 16, { - uint64_t bits_SMIN = (uint64_t{1} << (16 - 1)); - uint64_t bits_SMAX = ((uint64_t{1} << (16 - 1)) - 1); - bool ov = false; - int8_t m = P_FIELD(RS2, 0, 8); - int8_t rev = static_cast(m); - rev = (m < 0) ? static_cast(~m + 1u) : m; - uint64_t mask = ((uint64_t{1} << 16) - 1); - p_rs1 &= mask; - if(m < 0){ - if ((rev & 0xFFu) == 0u) - p_rd = (uint16_t)p_rs1; - else{ - int128_t v_sext; - bool neg = ((p_rs1 >> (16 - 1)) & 1u); - if(!neg) v_sext = static_cast(p_rs1); - else v_sext = static_cast((~static_cast(0) << 16) | static_cast(p_rs1)); - int128_t v_cat0 = v_sext << 1; - - unsigned sh = ((unsigned)(uint8_t)rev > 255u) ? 255u : (unsigned)(uint8_t)rev; - - int128_t sra_val; - if(sh == 0) - sra_val = v_cat0; - else if(sh >=127) - sra_val = (v_cat0 < 0) ? static_cast(-1) : static_cast(0); - else{ - int128_t ux = static_cast(v_cat0); - int128_t shifted = ux >> sh; - if(v_cat0 < 0) - shifted |= (~static_cast(0)) << (128 - sh); - sra_val = static_cast(shifted); - } - - int128_t plus1 = sra_val + static_cast(1); - uint128_t ures = static_cast(plus1); - p_rd = (uint16_t)(static_cast((ures >> 1) & static_cast(mask))); - } - } - else{ - if(rev==0) p_rd = (uint16_t)p_rs1; - else if(rev >= 16){ - if(p_rs1==0) - p_rd = 0; - else{ - ov = true; - uint64_t sign = (p_rs1 >> (16 - 1)) & 1u; - p_rd = (uint16_t)(sign ? bits_SMIN : bits_SMAX); - } - } - else{ - uint64_t sign = (p_rs1 >> (16 - 1)) & 1u; - uint64_t top = (p_rs1 >> (16 - rev)); - uint64_t need = sign ? ((uint64_t{1} << rev) - 1) : 0u; - ov = (top != need); - if(ov) - p_rd = (uint16_t)(sign ? bits_SMIN : bits_SMAX); - else - p_rd = (uint16_t)((p_rs1 << rev) & mask); - } + bool ov = false; + int8_t sshamt = P_FIELD(RS2, 0, 8); + int32_t val = p_rs1; + if (sshamt < 0) { + val = (val << 1) >> std::min(-sshamt, 16); + val = (int16_t)((val + 1) >> 1); + } else if (sshamt >= 16 && val != 0){ + val = val > 0 ? INT16_MAX : INT16_MIN; + ov = true; + } else if (val != 0) { + int32_t tmp = (int32_t)val << sshamt; + if (tmp > INT16_MAX) { + val = INT16_MAX; + ov = true; + } else if (tmp < INT16_MIN) { + val = INT16_MIN; + ov = true; + } else { + val = tmp; } + } + p_rd = val; + if (ov) P.set_vxsat(); }) diff --git a/riscv/insns/psshar_dws.h b/riscv/insns/psshar_dws.h index 95718649..b73f0cf9 100644 --- a/riscv/insns/psshar_dws.h +++ b/riscv/insns/psshar_dws.h @@ -1,64 +1,27 @@ require_rv32; P_RD_RS1_DW_LOOP(32, 32, { - uint64_t bits_SMIN = (uint64_t{1} << (32 - 1)); - uint64_t bits_SMAX = ((uint64_t{1} << (32 - 1)) - 1); - bool ov = false; - int8_t m = P_FIELD(RS2, 0, 8); - int8_t rev = static_cast(m); - rev = (m < 0) ? static_cast(~m + 1u) : m; - uint64_t mask = ((uint64_t{1} << 32) - 1); - p_rs1 &= mask; - if(m < 0){ - if ((rev & 0xFFu) == 0u) - p_rd = (uint32_t)p_rs1; - else{ - int128_t v_sext; - bool neg = ((p_rs1 >> (32 - 1)) & 1u); - if(!neg) v_sext = static_cast(p_rs1); - else v_sext = static_cast((~static_cast(0) << 32) | static_cast(p_rs1)); - int128_t v_cat0 = v_sext << 1; - - unsigned sh = ((unsigned)(uint8_t)rev > 255u) ? 255u : (unsigned)(uint8_t)rev; - - int128_t sra_val; - if(sh == 0) - sra_val = v_cat0; - else if(sh >=127) - sra_val = (v_cat0 < 0) ? static_cast(-1) : static_cast(0); - else{ - int128_t ux = static_cast(v_cat0); - int128_t shifted = ux >> sh; - if(v_cat0 < 0) - shifted |= (~static_cast(0)) << (128 - sh); - sra_val = static_cast(shifted); - } - - int128_t plus1 = sra_val + static_cast(1); - uint128_t ures = static_cast(plus1); - p_rd = (uint32_t)(static_cast((ures >> 1) & static_cast(mask))); - } - } - else{ - if(rev==0) p_rd = (uint32_t)p_rs1; - else if(rev >= 32){ - if(p_rs1==0) - p_rd = 0; - else{ - ov = true; - uint64_t sign = (p_rs1 >> (32 - 1)) & 1u; - p_rd = (uint32_t)(sign ? bits_SMIN : bits_SMAX); - } - } - else{ - uint64_t sign = (p_rs1 >> (32 - 1)) & 1u; - uint64_t top = (p_rs1 >> (32 - rev)); - uint64_t need = sign ? ((uint64_t{1} << rev) - 1) : 0u; - ov = (top != need); - if(ov) - p_rd = (uint32_t)(sign ? bits_SMIN : bits_SMAX); - else - p_rd = (uint32_t)((p_rs1 << rev) & mask); - } + bool ov = false; + int8_t sshamt = P_FIELD(RS2, 0, 8); + int64_t val = p_rs1; + if (sshamt < 0) { + val = (val << 1) >> std::min(-sshamt, 32); + val = (int32_t)((val + 1) >> 1); + } else if (sshamt >= 32 && val != 0){ + val = val > 0 ? INT32_MAX : INT32_MIN; + ov = true; + } else if (val != 0) { + int64_t tmp = (int64_t)val << sshamt; + if (tmp > INT32_MAX) { + val = INT32_MAX; + ov = true; + } else if (tmp < INT32_MIN) { + val = INT32_MIN; + ov = true; + } else { + val = tmp; } + } + p_rd = val; + if (ov) P.set_vxsat(); })