Browse Source

rvp: fix and simplify behavior

Signed-off-by: Chih-Min Chao <chihmin.chao@sifive.com>
pull/2310/head
Chih-Min Chao 3 months ago
parent
commit
6e0889925b
  1. 6
      riscv/insns/pm2wsub_hx.h
  2. 6
      riscv/insns/pm2wsuba_hx.h
  3. 59
      riscv/insns/pssha_dhs.h
  4. 57
      riscv/insns/pssha_dws.h
  5. 81
      riscv/insns/psshar_dhs.h
  6. 81
      riscv/insns/psshar_dws.h

6
riscv/insns/pm2wsub_hx.h

@ -1,7 +1,7 @@
require_rv32; require_rv32;
P_WIDEN_REDUCTION_CROSS_LOOP(32, 16, false, false, { P_WIDEN_REDUCTION_CROSS_LOOP(32, 16, false, false, {
if (j & 1) if (j & 1)
p_res += p_rs1 * p_rs2; p_res -= (int64_t)p_rs1 * p_rs2;
else else
p_res -= p_rs1 * p_rs2; p_res += (int64_t)p_rs1 * p_rs2;
}) })

6
riscv/insns/pm2wsuba_hx.h

@ -1,7 +1,7 @@
require_rv32; require_rv32;
P_WIDEN_REDUCTION_CROSS_LOOP(32, 16, true, false, { P_WIDEN_REDUCTION_CROSS_LOOP(32, 16, true, false, {
if (j & 1) if (j & 1)
p_res += p_rs1 * p_rs2;
else
p_res -= p_rs1 * p_rs2; p_res -= p_rs1 * p_rs2;
}) else
p_res += p_rs1 * p_rs2;
})

59
riscv/insns/pssha_dhs.h

@ -1,45 +1,26 @@
require_rv32; require_rv32;
P_RD_RS1_DW_LOOP(16, 16, { 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; bool ov = false;
int8_t m = P_FIELD(RS2, 0, 8); int8_t sshamt = P_FIELD(RS2, 0, 8);
int8_t rev = static_cast<int8_t>(m); int32_t val = p_rs1;
rev = (m < 0) ? static_cast<uint8_t>(~m + 1u) : m; if (sshamt < 0) {
uint64_t mask = ((uint64_t{1} << 16) - 1); val = (int16_t)(val >> std::min(-sshamt, 16));
p_rs1 &= mask; } else if (sshamt >= 16 && val != 0){
if(m < 0){ val = val > 0 ? INT16_MAX : INT16_MIN;
unsigned sh = ((unsigned)(uint8_t)rev > 255u) ? 255u : (unsigned)(uint8_t)rev; ov = true;
uint64_t sign = (p_rs1 >> (16 - 1)) & 1u; } else if (val != 0) {
int32_t tmp = (int32_t)val << sshamt;
if(sh >= 16) p_rd = (uint16_t)(sign ? mask : 0u); if (tmp > INT16_MAX) {
else{ val = INT16_MAX;
uint64_t shifted = (p_rs1 >> sh); ov = true;
uint64_t fill = (~uint64_t{0}) << (16 - sh); } else if (tmp < INT16_MIN) {
shifted |= fill; val = INT16_MIN;
p_rd = (uint16_t)(shifted & mask); ov = true;
} } else {
} val = tmp;
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);
} }
} }
p_rd = val;
if (ov) P.set_vxsat(); if (ov) P.set_vxsat();
}) })

57
riscv/insns/pssha_dws.h

@ -1,45 +1,26 @@
require_rv32; require_rv32;
P_RD_RS1_DW_LOOP(32, 32, { 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; bool ov = false;
int8_t m = P_FIELD(RS2, 0, 8); int8_t sshamt = P_FIELD(RS2, 0, 8);
int8_t rev = static_cast<int8_t>(m); int64_t val = p_rs1;
rev = (m < 0) ? static_cast<uint8_t>(~m + 1u) : m; if (sshamt < 0) {
uint64_t mask = ((uint64_t{1} << 32) - 1); val = (int32_t)(val >> std::min(-sshamt, 32));
p_rs1 &= mask; } else if (sshamt >= 32 && val != 0){
if(m < 0){ val = val > 0 ? INT32_MAX : INT32_MIN;
unsigned sh = ((unsigned)(uint8_t)rev > 255u) ? 255u : (unsigned)(uint8_t)rev; ov = true;
uint64_t sign = (p_rs1 >> (32 - 1)) & 1u; } else if (val != 0) {
int64_t tmp = (int64_t)val << sshamt;
if(sh >= 32) p_rd = (uint32_t)(sign ? mask : 0u); if (tmp > INT32_MAX) {
else{ val = INT32_MAX;
uint64_t shifted = (p_rs1 >> sh); ov = true;
uint64_t fill = (~uint64_t{0}) << (32 - sh); } else if (tmp < INT32_MIN) {
shifted |= fill; val = INT32_MIN;
p_rd = (uint32_t)(shifted & mask); ov = true;
} } else {
} val = tmp;
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);
} }
} }
p_rd = val;
if (ov) P.set_vxsat(); if (ov) P.set_vxsat();
}) })

81
riscv/insns/psshar_dhs.h

@ -1,64 +1,27 @@
require_rv32; require_rv32;
P_RD_RS1_DW_LOOP(16, 16, { P_RD_RS1_DW_LOOP(16, 16, {
uint64_t bits_SMIN = (uint64_t{1} << (16 - 1)); bool ov = false;
uint64_t bits_SMAX = ((uint64_t{1} << (16 - 1)) - 1); int8_t sshamt = P_FIELD(RS2, 0, 8);
bool ov = false; int32_t val = p_rs1;
int8_t m = P_FIELD(RS2, 0, 8); if (sshamt < 0) {
int8_t rev = static_cast<int8_t>(m); val = (val << 1) >> std::min(-sshamt, 16);
rev = (m < 0) ? static_cast<uint8_t>(~m + 1u) : m; val = (int16_t)((val + 1) >> 1);
uint64_t mask = ((uint64_t{1} << 16) - 1); } else if (sshamt >= 16 && val != 0){
p_rs1 &= mask; val = val > 0 ? INT16_MAX : INT16_MIN;
if(m < 0){ ov = true;
if ((rev & 0xFFu) == 0u) } else if (val != 0) {
p_rd = (uint16_t)p_rs1; int32_t tmp = (int32_t)val << sshamt;
else{ if (tmp > INT16_MAX) {
int128_t v_sext; val = INT16_MAX;
bool neg = ((p_rs1 >> (16 - 1)) & 1u); ov = true;
if(!neg) v_sext = static_cast<int128_t>(p_rs1); } else if (tmp < INT16_MIN) {
else v_sext = static_cast<int128_t>((~static_cast<uint128_t>(0) << 16) | static_cast<uint128_t>(p_rs1)); val = INT16_MIN;
int128_t v_cat0 = v_sext << 1; ov = true;
} else {
unsigned sh = ((unsigned)(uint8_t)rev > 255u) ? 255u : (unsigned)(uint8_t)rev; val = tmp;
int128_t sra_val;
if(sh == 0)
sra_val = v_cat0;
else if(sh >=127)
sra_val = (v_cat0 < 0) ? static_cast<int128_t>(-1) : static_cast<int128_t>(0);
else{
int128_t ux = static_cast<uint128_t>(v_cat0);
int128_t shifted = ux >> sh;
if(v_cat0 < 0)
shifted |= (~static_cast<uint128_t>(0)) << (128 - sh);
sra_val = static_cast<int128_t>(shifted);
}
int128_t plus1 = sra_val + static_cast<int128_t>(1);
uint128_t ures = static_cast<uint128_t>(plus1);
p_rd = (uint16_t)(static_cast<uint64_t>((ures >> 1) & static_cast<uint128_t>(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);
}
} }
}
p_rd = val;
if (ov) P.set_vxsat(); if (ov) P.set_vxsat();
}) })

81
riscv/insns/psshar_dws.h

@ -1,64 +1,27 @@
require_rv32; require_rv32;
P_RD_RS1_DW_LOOP(32, 32, { P_RD_RS1_DW_LOOP(32, 32, {
uint64_t bits_SMIN = (uint64_t{1} << (32 - 1)); bool ov = false;
uint64_t bits_SMAX = ((uint64_t{1} << (32 - 1)) - 1); int8_t sshamt = P_FIELD(RS2, 0, 8);
bool ov = false; int64_t val = p_rs1;
int8_t m = P_FIELD(RS2, 0, 8); if (sshamt < 0) {
int8_t rev = static_cast<int8_t>(m); val = (val << 1) >> std::min(-sshamt, 32);
rev = (m < 0) ? static_cast<uint8_t>(~m + 1u) : m; val = (int32_t)((val + 1) >> 1);
uint64_t mask = ((uint64_t{1} << 32) - 1); } else if (sshamt >= 32 && val != 0){
p_rs1 &= mask; val = val > 0 ? INT32_MAX : INT32_MIN;
if(m < 0){ ov = true;
if ((rev & 0xFFu) == 0u) } else if (val != 0) {
p_rd = (uint32_t)p_rs1; int64_t tmp = (int64_t)val << sshamt;
else{ if (tmp > INT32_MAX) {
int128_t v_sext; val = INT32_MAX;
bool neg = ((p_rs1 >> (32 - 1)) & 1u); ov = true;
if(!neg) v_sext = static_cast<int128_t>(p_rs1); } else if (tmp < INT32_MIN) {
else v_sext = static_cast<int128_t>((~static_cast<uint128_t>(0) << 32) | static_cast<uint128_t>(p_rs1)); val = INT32_MIN;
int128_t v_cat0 = v_sext << 1; ov = true;
} else {
unsigned sh = ((unsigned)(uint8_t)rev > 255u) ? 255u : (unsigned)(uint8_t)rev; val = tmp;
int128_t sra_val;
if(sh == 0)
sra_val = v_cat0;
else if(sh >=127)
sra_val = (v_cat0 < 0) ? static_cast<int128_t>(-1) : static_cast<int128_t>(0);
else{
int128_t ux = static_cast<uint128_t>(v_cat0);
int128_t shifted = ux >> sh;
if(v_cat0 < 0)
shifted |= (~static_cast<uint128_t>(0)) << (128 - sh);
sra_val = static_cast<int128_t>(shifted);
}
int128_t plus1 = sra_val + static_cast<int128_t>(1);
uint128_t ures = static_cast<uint128_t>(plus1);
p_rd = (uint32_t)(static_cast<uint64_t>((ures >> 1) & static_cast<uint128_t>(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);
}
} }
}
p_rd = val;
if (ov) P.set_vxsat(); if (ov) P.set_vxsat();
}) })

Loading…
Cancel
Save